|
|
f96e0b |
From ded439de5b72d33474f96fbc08b9687a76c938ac Mon Sep 17 00:00:00 2001
|
|
|
f96e0b |
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
|
|
|
f96e0b |
Date: Wed, 16 Jan 2013 20:39:54 +0100
|
|
|
f96e0b |
Subject: [PATCH 111/482] New terminal outputs using serial: morse and
|
|
|
f96e0b |
spkmodem.
|
|
|
f96e0b |
|
|
|
f96e0b |
---
|
|
|
f96e0b |
ChangeLog | 4 ++
|
|
|
f96e0b |
docs/grub.texi | 24 +++++--
|
|
|
f96e0b |
grub-core/Makefile.core.def | 12 ++++
|
|
|
f96e0b |
grub-core/commands/i386/pc/play.c | 109 ++-----------------------------
|
|
|
f96e0b |
grub-core/kern/i386/pit.c | 35 ++++------
|
|
|
f96e0b |
grub-core/term/morse.c | 131 ++++++++++++++++++++++++++++++++++++++
|
|
|
f96e0b |
grub-core/term/spkmodem.c | 106 ++++++++++++++++++++++++++++++
|
|
|
f96e0b |
include/grub/i386/pit.h | 78 +++++++++++++++++++++++
|
|
|
f96e0b |
include/grub/speaker.h | 47 ++++++++++++++
|
|
|
f96e0b |
util/spkmodem-recv.c | 98 ++++++++++++++++++++++++++++
|
|
|
f96e0b |
10 files changed, 512 insertions(+), 132 deletions(-)
|
|
|
f96e0b |
create mode 100644 grub-core/term/morse.c
|
|
|
f96e0b |
create mode 100644 grub-core/term/spkmodem.c
|
|
|
f96e0b |
create mode 100644 include/grub/speaker.h
|
|
|
f96e0b |
create mode 100644 util/spkmodem-recv.c
|
|
|
f96e0b |
|
|
|
f96e0b |
diff --git a/ChangeLog b/ChangeLog
|
|
|
f96e0b |
index 96aca66..f1c53e3 100644
|
|
|
f96e0b |
--- a/ChangeLog
|
|
|
f96e0b |
+++ b/ChangeLog
|
|
|
f96e0b |
@@ -1,5 +1,9 @@
|
|
|
f96e0b |
2013-01-16 Vladimir Serbinenko <phcoder@gmail.com>
|
|
|
f96e0b |
|
|
|
f96e0b |
+ New terminal outputs using serial: morse and spkmodem.
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+2013-01-16 Vladimir Serbinenko <phcoder@gmail.com>
|
|
|
f96e0b |
+
|
|
|
f96e0b |
Improve bidi handling in entry editor.
|
|
|
f96e0b |
|
|
|
f96e0b |
2013-01-16 Vladimir Serbinenko <phcoder@gmail.com>
|
|
|
f96e0b |
diff --git a/docs/grub.texi b/docs/grub.texi
|
|
|
f96e0b |
index e75bae9..efedd27 100644
|
|
|
f96e0b |
--- a/docs/grub.texi
|
|
|
f96e0b |
+++ b/docs/grub.texi
|
|
|
f96e0b |
@@ -1229,9 +1229,9 @@ Select the terminal input device. You may select multiple devices here,
|
|
|
f96e0b |
separated by spaces.
|
|
|
f96e0b |
|
|
|
f96e0b |
Valid terminal input names depend on the platform, but may include
|
|
|
f96e0b |
-@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal),
|
|
|
f96e0b |
-@samp{ofconsole} (Open Firmware console), @samp{at_keyboard} (PC AT
|
|
|
f96e0b |
-keyboard, mainly useful with Coreboot), or @samp{usb_keyboard} (USB keyboard
|
|
|
f96e0b |
+@samp{console} (native platform console), @samp{serial} (serial terminal),
|
|
|
f96e0b |
+@samp{serial_<port>} (serial terminal with explicit port selection),
|
|
|
f96e0b |
+@samp{at_keyboard} (PC AT keyboard), or @samp{usb_keyboard} (USB keyboard
|
|
|
f96e0b |
using the HID Boot Protocol, for cases where the firmware does not handle
|
|
|
f96e0b |
this).
|
|
|
f96e0b |
|
|
|
f96e0b |
@@ -1242,9 +1242,21 @@ Select the terminal output device. You may select multiple devices here,
|
|
|
f96e0b |
separated by spaces.
|
|
|
f96e0b |
|
|
|
f96e0b |
Valid terminal output names depend on the platform, but may include
|
|
|
f96e0b |
-@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal),
|
|
|
f96e0b |
-@samp{gfxterm} (graphics-mode output), @samp{ofconsole} (Open Firmware
|
|
|
f96e0b |
-console), or @samp{vga_text} (VGA text output, mainly useful with Coreboot).
|
|
|
f96e0b |
+@samp{console} (native platform console), @samp{serial} (serial terminal),
|
|
|
f96e0b |
+@samp{serial_<port>} (serial terminal with explicit port selection),
|
|
|
f96e0b |
+@samp{gfxterm} (graphics-mode output), @samp{vga_text} (VGA text output),
|
|
|
f96e0b |
+@samp{mda_text} (MDA text output), @samp{morse} (Morse-coding using system
|
|
|
f96e0b |
+beeper) or @samp{spkmodem} (simple data protocol using system speaker).
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+@samp{spkmodem} is useful when no serial port is available. Connect the output
|
|
|
f96e0b |
+of sending system (where GRUB is running) to line-in of receiving system
|
|
|
f96e0b |
+(usually developper machine).
|
|
|
f96e0b |
+On receiving system compile @samp{spkmodem-recv} from
|
|
|
f96e0b |
+@samp{util/spkmodem-recv.c} and run:
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+@example
|
|
|
f96e0b |
+parecord --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv
|
|
|
f96e0b |
+@end example
|
|
|
f96e0b |
|
|
|
f96e0b |
The default is to use the platform's native terminal output.
|
|
|
f96e0b |
|
|
|
f96e0b |
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
|
|
f96e0b |
index f4dd645..baf80b8 100644
|
|
|
f96e0b |
--- a/grub-core/Makefile.core.def
|
|
|
f96e0b |
+++ b/grub-core/Makefile.core.def
|
|
|
f96e0b |
@@ -779,6 +779,18 @@ module = {
|
|
|
f96e0b |
};
|
|
|
f96e0b |
|
|
|
f96e0b |
module = {
|
|
|
f96e0b |
+ name = spkmodem;
|
|
|
f96e0b |
+ x86 = term/spkmodem.c;
|
|
|
f96e0b |
+ enable = x86;
|
|
|
f96e0b |
+};
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+module = {
|
|
|
f96e0b |
+ name = morse;
|
|
|
f96e0b |
+ x86 = term/morse.c;
|
|
|
f96e0b |
+ enable = x86;
|
|
|
f96e0b |
+};
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+module = {
|
|
|
f96e0b |
name = probe;
|
|
|
f96e0b |
common = commands/probe.c;
|
|
|
f96e0b |
};
|
|
|
f96e0b |
diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c
|
|
|
f96e0b |
index 10a0181..40798c9 100644
|
|
|
f96e0b |
--- a/grub-core/commands/i386/pc/play.c
|
|
|
f96e0b |
+++ b/grub-core/commands/i386/pc/play.c
|
|
|
f96e0b |
@@ -28,80 +28,12 @@
|
|
|
f96e0b |
#include <grub/command.h>
|
|
|
f96e0b |
#include <grub/i18n.h>
|
|
|
f96e0b |
#include <grub/time.h>
|
|
|
f96e0b |
+#include <grub/speaker.h>
|
|
|
f96e0b |
|
|
|
f96e0b |
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
f96e0b |
|
|
|
f96e0b |
#define BASE_TEMPO (60 * 1000)
|
|
|
f96e0b |
|
|
|
f96e0b |
-/* The speaker port. */
|
|
|
f96e0b |
-#define SPEAKER 0x61
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output
|
|
|
f96e0b |
- from timer 2. */
|
|
|
f96e0b |
-#define SPEAKER_TMR2 0x01
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* If SPEAKER_TMR2 is not set, this provides direct input into the
|
|
|
f96e0b |
- speaker. Otherwise, this enables or disables the output from the
|
|
|
f96e0b |
- timer. */
|
|
|
f96e0b |
-#define SPEAKER_DATA 0x02
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* The PIT channel value ports. You can write to and read from them.
|
|
|
f96e0b |
- Do not mess with timer 0 or 1. */
|
|
|
f96e0b |
-#define PIT_COUNTER_0 0x40
|
|
|
f96e0b |
-#define PIT_COUNTER_1 0x41
|
|
|
f96e0b |
-#define PIT_COUNTER_2 0x42
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* The frequency of the PIT clock. */
|
|
|
f96e0b |
-#define PIT_FREQUENCY 0x1234dd
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* The PIT control port. You can only write to it. Do not mess with
|
|
|
f96e0b |
- timer 0 or 1. */
|
|
|
f96e0b |
-#define PIT_CTRL 0x43
|
|
|
f96e0b |
-#define PIT_CTRL_SELECT_MASK 0xc0
|
|
|
f96e0b |
-#define PIT_CTRL_SELECT_0 0x00
|
|
|
f96e0b |
-#define PIT_CTRL_SELECT_1 0x40
|
|
|
f96e0b |
-#define PIT_CTRL_SELECT_2 0x80
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Read and load control. */
|
|
|
f96e0b |
-#define PIT_CTRL_READLOAD_MASK 0x30
|
|
|
f96e0b |
-#define PIT_CTRL_COUNTER_LATCH 0x00 /* Hold timer value until read. */
|
|
|
f96e0b |
-#define PIT_CTRL_READLOAD_LSB 0x10 /* Read/load the LSB. */
|
|
|
f96e0b |
-#define PIT_CTRL_READLOAD_MSB 0x20 /* Read/load the MSB. */
|
|
|
f96e0b |
-#define PIT_CTRL_READLOAD_WORD 0x30 /* Read/load the LSB then the MSB. */
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Mode control. */
|
|
|
f96e0b |
-#define PIT_CTRL_MODE_MASK 0x0e
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Interrupt on terminal count. Setting the mode sets output to low.
|
|
|
f96e0b |
- When counter is set and terminated, output is set to high. */
|
|
|
f96e0b |
-#define PIT_CTRL_INTR_ON_TERM 0x00
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Programmable one-shot. When loading counter, output is set to
|
|
|
f96e0b |
- high. When counter terminated, output is set to low. Can be
|
|
|
f96e0b |
- triggered again from that point on by setting the gate pin to
|
|
|
f96e0b |
- high. */
|
|
|
f96e0b |
-#define PIT_CTRL_PROGR_ONE_SHOT 0x02
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Rate generator. Output is low for one period of the counter, and
|
|
|
f96e0b |
- high for the other. */
|
|
|
f96e0b |
-#define PIT_CTRL_RATE_GEN 0x04
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Square wave generator. Output is low for one half of the period,
|
|
|
f96e0b |
- and high for the other half. */
|
|
|
f96e0b |
-#define PIT_CTRL_SQUAREWAVE_GEN 0x06
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Software triggered strobe. Setting the mode sets output to high.
|
|
|
f96e0b |
- When counter is set and terminated, output is set to low. */
|
|
|
f96e0b |
-#define PIT_CTRL_SOFTSTROBE 0x08
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Hardware triggered strobe. Like software triggered strobe, but
|
|
|
f96e0b |
- only starts the counter when the gate pin is set to high. */
|
|
|
f96e0b |
-#define PIT_CTRL_HARDSTROBE 0x0a
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-/* Count mode. */
|
|
|
f96e0b |
-#define PIT_CTRL_COUNT_MASK 0x01
|
|
|
f96e0b |
-#define PIT_CTRL_COUNT_BINARY 0x00 /* 16-bit binary counter. */
|
|
|
f96e0b |
-#define PIT_CTRL_COUNT_BCD 0x01 /* 4-decade BCD counter. */
|
|
|
f96e0b |
|
|
|
f96e0b |
#define T_REST ((grub_uint16_t) 0)
|
|
|
f96e0b |
#define T_FINE ((grub_uint16_t) -1)
|
|
|
f96e0b |
@@ -112,39 +44,6 @@ struct note
|
|
|
f96e0b |
grub_uint16_t duration;
|
|
|
f96e0b |
};
|
|
|
f96e0b |
|
|
|
f96e0b |
-static void
|
|
|
f96e0b |
-beep_off (void)
|
|
|
f96e0b |
-{
|
|
|
f96e0b |
- unsigned char status;
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- status = grub_inb (SPEAKER);
|
|
|
f96e0b |
- grub_outb (status & ~(SPEAKER_TMR2 | SPEAKER_DATA), SPEAKER);
|
|
|
f96e0b |
-}
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-static void
|
|
|
f96e0b |
-beep_on (grub_uint16_t pitch)
|
|
|
f96e0b |
-{
|
|
|
f96e0b |
- unsigned char status;
|
|
|
f96e0b |
- unsigned int counter;
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- if (pitch < 20)
|
|
|
f96e0b |
- pitch = 20;
|
|
|
f96e0b |
- else if (pitch > 20000)
|
|
|
f96e0b |
- pitch = 20000;
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- counter = PIT_FREQUENCY / pitch;
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- /* Program timer 2. */
|
|
|
f96e0b |
- grub_outb (PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD
|
|
|
f96e0b |
- | PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY, PIT_CTRL);
|
|
|
f96e0b |
- grub_outb (counter & 0xff, PIT_COUNTER_2); /* LSB */
|
|
|
f96e0b |
- grub_outb ((counter >> 8) & 0xff, PIT_COUNTER_2); /* MSB */
|
|
|
f96e0b |
-
|
|
|
f96e0b |
- /* Start speaker. */
|
|
|
f96e0b |
- status = grub_inb (SPEAKER);
|
|
|
f96e0b |
- grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER);
|
|
|
f96e0b |
-}
|
|
|
f96e0b |
-
|
|
|
f96e0b |
/* Returns whether playing should continue. */
|
|
|
f96e0b |
static int
|
|
|
f96e0b |
play (unsigned tempo, struct note *note)
|
|
|
f96e0b |
@@ -160,11 +59,11 @@ play (unsigned tempo, struct note *note)
|
|
|
f96e0b |
switch (note->pitch)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
case T_REST:
|
|
|
f96e0b |
- beep_off ();
|
|
|
f96e0b |
+ grub_speaker_beep_off ();
|
|
|
f96e0b |
break;
|
|
|
f96e0b |
|
|
|
f96e0b |
default:
|
|
|
f96e0b |
- beep_on (note->pitch);
|
|
|
f96e0b |
+ grub_speaker_beep_on (note->pitch);
|
|
|
f96e0b |
break;
|
|
|
f96e0b |
}
|
|
|
f96e0b |
|
|
|
f96e0b |
@@ -263,7 +162,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|
|
f96e0b |
}
|
|
|
f96e0b |
}
|
|
|
f96e0b |
|
|
|
f96e0b |
- beep_off ();
|
|
|
f96e0b |
+ grub_speaker_beep_off ();
|
|
|
f96e0b |
|
|
|
f96e0b |
return 0;
|
|
|
f96e0b |
}
|
|
|
f96e0b |
diff --git a/grub-core/kern/i386/pit.c b/grub-core/kern/i386/pit.c
|
|
|
f96e0b |
index 82a17d3..092481a 100644
|
|
|
f96e0b |
--- a/grub-core/kern/i386/pit.c
|
|
|
f96e0b |
+++ b/grub-core/kern/i386/pit.c
|
|
|
f96e0b |
@@ -20,37 +20,30 @@
|
|
|
f96e0b |
#include <grub/i386/io.h>
|
|
|
f96e0b |
#include <grub/i386/pit.h>
|
|
|
f96e0b |
|
|
|
f96e0b |
-#define TIMER2_REG_CONTROL 0x42
|
|
|
f96e0b |
-#define TIMER_REG_COMMAND 0x43
|
|
|
f96e0b |
-#define TIMER2_REG_LATCH 0x61
|
|
|
f96e0b |
-
|
|
|
f96e0b |
-#define TIMER2_SELECT 0x80
|
|
|
f96e0b |
-#define TIMER_ENABLE_LSB 0x20
|
|
|
f96e0b |
-#define TIMER_ENABLE_MSB 0x10
|
|
|
f96e0b |
-#define TIMER2_LATCH 0x20
|
|
|
f96e0b |
-#define TIMER2_SPEAKER 0x02
|
|
|
f96e0b |
-#define TIMER2_GATE 0x01
|
|
|
f96e0b |
-
|
|
|
f96e0b |
void
|
|
|
f96e0b |
grub_pit_wait (grub_uint16_t tics)
|
|
|
f96e0b |
{
|
|
|
f96e0b |
/* Disable timer2 gate and speaker. */
|
|
|
f96e0b |
- grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
|
|
|
f96e0b |
- TIMER2_REG_LATCH);
|
|
|
f96e0b |
+ grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
|
|
f96e0b |
+ & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
|
|
f96e0b |
+ GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
|
|
|
f96e0b |
/* Set tics. */
|
|
|
f96e0b |
- grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND);
|
|
|
f96e0b |
- grub_outb (tics & 0xff, TIMER2_REG_CONTROL);
|
|
|
f96e0b |
- grub_outb (tics >> 8, TIMER2_REG_CONTROL);
|
|
|
f96e0b |
+ grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD,
|
|
|
f96e0b |
+ GRUB_PIT_CTRL);
|
|
|
f96e0b |
+ grub_outb (tics & 0xff, GRUB_PIT_COUNTER_2);
|
|
|
f96e0b |
+ grub_outb (tics >> 8, GRUB_PIT_COUNTER_2);
|
|
|
f96e0b |
|
|
|
f96e0b |
/* Enable timer2 gate, keep speaker disabled. */
|
|
|
f96e0b |
- grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE,
|
|
|
f96e0b |
- TIMER2_REG_LATCH);
|
|
|
f96e0b |
+ grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA)
|
|
|
f96e0b |
+ | GRUB_PIT_SPK_TMR2,
|
|
|
f96e0b |
+ GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
|
|
|
f96e0b |
/* Wait. */
|
|
|
f96e0b |
- while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00);
|
|
|
f96e0b |
+ while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00);
|
|
|
f96e0b |
|
|
|
f96e0b |
/* Disable timer2 gate and speaker. */
|
|
|
f96e0b |
- grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
|
|
|
f96e0b |
- TIMER2_REG_LATCH);
|
|
|
f96e0b |
+ grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
|
|
f96e0b |
+ & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
|
|
f96e0b |
+ GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
}
|
|
|
f96e0b |
diff --git a/grub-core/term/morse.c b/grub-core/term/morse.c
|
|
|
f96e0b |
new file mode 100644
|
|
|
f96e0b |
index 0000000..3d6c650
|
|
|
f96e0b |
--- /dev/null
|
|
|
f96e0b |
+++ b/grub-core/term/morse.c
|
|
|
f96e0b |
@@ -0,0 +1,131 @@
|
|
|
f96e0b |
+/*
|
|
|
f96e0b |
+ * GRUB -- GRand Unified Bootloader
|
|
|
f96e0b |
+ * Copyright (C) 2011,2012,2013 Free Software Foundation, Inc.
|
|
|
f96e0b |
+ *
|
|
|
f96e0b |
+ * GRUB is free software: you can redistribute it and/or modify
|
|
|
f96e0b |
+ * it under the terms of the GNU General Public License as published by
|
|
|
f96e0b |
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
f96e0b |
+ * (at your option) any later version.
|
|
|
f96e0b |
+ *
|
|
|
f96e0b |
+ * GRUB is distributed in the hope that it will be useful,
|
|
|
f96e0b |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
f96e0b |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
f96e0b |
+ * GNU General Public License for more details.
|
|
|
f96e0b |
+ *
|
|
|
f96e0b |
+ * You should have received a copy of the GNU General Public License
|
|
|
f96e0b |
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
|
f96e0b |
+ */
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#include <grub/term.h>
|
|
|
f96e0b |
+#include <grub/misc.h>
|
|
|
f96e0b |
+#include <grub/types.h>
|
|
|
f96e0b |
+#include <grub/err.h>
|
|
|
f96e0b |
+#include <grub/dl.h>
|
|
|
f96e0b |
+#include <grub/time.h>
|
|
|
f96e0b |
+#include <grub/speaker.h>
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#define BASE_TIME 250
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static const char codes[0x80][6] =
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ ['0'] = { 3, 3, 3, 3, 3, 0 },
|
|
|
f96e0b |
+ ['1'] = { 1, 3, 3, 3, 3, 0 },
|
|
|
f96e0b |
+ ['2'] = { 1, 1, 3, 3, 3, 0 },
|
|
|
f96e0b |
+ ['3'] = { 1, 1, 1, 3, 3, 0 },
|
|
|
f96e0b |
+ ['4'] = { 1, 1, 1, 1, 3, 0 },
|
|
|
f96e0b |
+ ['5'] = { 1, 1, 1, 1, 1, 0 },
|
|
|
f96e0b |
+ ['6'] = { 3, 1, 1, 1, 1, 0 },
|
|
|
f96e0b |
+ ['7'] = { 3, 3, 1, 1, 1, 0 },
|
|
|
f96e0b |
+ ['8'] = { 3, 3, 3, 1, 1, 0 },
|
|
|
f96e0b |
+ ['9'] = { 3, 3, 3, 3, 1, 0 },
|
|
|
f96e0b |
+ ['a'] = { 1, 3, 0 },
|
|
|
f96e0b |
+ ['b'] = { 3, 1, 1, 1, 0 },
|
|
|
f96e0b |
+ ['c'] = { 3, 1, 3, 1, 0 },
|
|
|
f96e0b |
+ ['d'] = { 3, 1, 1, 0 },
|
|
|
f96e0b |
+ ['e'] = { 1, 0 },
|
|
|
f96e0b |
+ ['f'] = { 1, 1, 3, 1, 0 },
|
|
|
f96e0b |
+ ['g'] = { 3, 3, 1, 0 },
|
|
|
f96e0b |
+ ['h'] = { 1, 1, 1, 1, 0 },
|
|
|
f96e0b |
+ ['i'] = { 1, 1, 0 },
|
|
|
f96e0b |
+ ['j'] = { 1, 3, 3, 3, 0 },
|
|
|
f96e0b |
+ ['k'] = { 3, 1, 3, 0 },
|
|
|
f96e0b |
+ ['l'] = { 1, 3, 1, 1, 0 },
|
|
|
f96e0b |
+ ['m'] = { 3, 3, 0 },
|
|
|
f96e0b |
+ ['n'] = { 3, 1, 0 },
|
|
|
f96e0b |
+ ['o'] = { 3, 3, 3, 0 },
|
|
|
f96e0b |
+ ['p'] = { 1, 3, 3, 1, 0 },
|
|
|
f96e0b |
+ ['q'] = { 3, 3, 1, 3, 0 },
|
|
|
f96e0b |
+ ['r'] = { 1, 3, 1, 0 },
|
|
|
f96e0b |
+ ['s'] = { 1, 1, 1, 0 },
|
|
|
f96e0b |
+ ['t'] = { 3, 0 },
|
|
|
f96e0b |
+ ['u'] = { 1, 1, 3, 0 },
|
|
|
f96e0b |
+ ['v'] = { 1, 1, 1, 3, 0 },
|
|
|
f96e0b |
+ ['w'] = { 1, 3, 3, 0 },
|
|
|
f96e0b |
+ ['x'] = { 3, 1, 1, 3, 0 },
|
|
|
f96e0b |
+ ['y'] = { 3, 1, 3, 3, 0 },
|
|
|
f96e0b |
+ ['z'] = { 3, 3, 1, 1, 0 }
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static void
|
|
|
f96e0b |
+grub_audio_tone (int length)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_speaker_beep_on (1000);
|
|
|
f96e0b |
+ grub_millisleep (length);
|
|
|
f96e0b |
+ grub_speaker_beep_off ();
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static void
|
|
|
f96e0b |
+grub_audio_putchar (struct grub_term_output *term __attribute__ ((unused)),
|
|
|
f96e0b |
+ const struct grub_unicode_glyph *c_in)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_uint8_t c;
|
|
|
f96e0b |
+ int i;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* For now, do not try to use a surrogate pair. */
|
|
|
f96e0b |
+ if (c_in->base > 0x7f)
|
|
|
f96e0b |
+ c = '?';
|
|
|
f96e0b |
+ else
|
|
|
f96e0b |
+ c = grub_tolower (c_in->base);
|
|
|
f96e0b |
+ for (i = 0; codes[c][i]; i++)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ grub_audio_tone (codes[c][i] * BASE_TIME);
|
|
|
f96e0b |
+ grub_millisleep (BASE_TIME);
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ grub_millisleep (2 * BASE_TIME);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static int
|
|
|
f96e0b |
+dummy (void)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ return 0;
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static struct grub_term_output grub_audio_term_output =
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ .name = "morse",
|
|
|
f96e0b |
+ .init = (void *) dummy,
|
|
|
f96e0b |
+ .fini = (void *) dummy,
|
|
|
f96e0b |
+ .putchar = grub_audio_putchar,
|
|
|
f96e0b |
+ .getwh = (void *) dummy,
|
|
|
f96e0b |
+ .getxy = (void *) dummy,
|
|
|
f96e0b |
+ .gotoxy = (void *) dummy,
|
|
|
f96e0b |
+ .cls = (void *) dummy,
|
|
|
f96e0b |
+ .setcolorstate = (void *) dummy,
|
|
|
f96e0b |
+ .setcursor = (void *) dummy,
|
|
|
f96e0b |
+ .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
|
|
f96e0b |
+ .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
|
|
f96e0b |
+ .flags = GRUB_TERM_CODE_TYPE_ASCII | GRUB_TERM_DUMB
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+GRUB_MOD_INIT (morse)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_term_register_output ("audio", &grub_audio_term_output);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+GRUB_MOD_FINI (morse)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_term_unregister_output (&grub_audio_term_output);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
diff --git a/grub-core/term/spkmodem.c b/grub-core/term/spkmodem.c
|
|
|
f96e0b |
new file mode 100644
|
|
|
f96e0b |
index 0000000..31dab65
|
|
|
f96e0b |
--- /dev/null
|
|
|
f96e0b |
+++ b/grub-core/term/spkmodem.c
|
|
|
f96e0b |
@@ -0,0 +1,106 @@
|
|
|
f96e0b |
+/* console.c -- Open Firmware console for GRUB. */
|
|
|
f96e0b |
+/*
|
|
|
f96e0b |
+ * GRUB -- GRand Unified Bootloader
|
|
|
f96e0b |
+ * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
|
|
f96e0b |
+ *
|
|
|
f96e0b |
+ * GRUB is free software: you can redistribute it and/or modify
|
|
|
f96e0b |
+ * it under the terms of the GNU General Public License as published by
|
|
|
f96e0b |
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
f96e0b |
+ * (at your option) any later version.
|
|
|
f96e0b |
+ *
|
|
|
f96e0b |
+ * GRUB is distributed in the hope that it will be useful,
|
|
|
f96e0b |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
f96e0b |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
f96e0b |
+ * GNU General Public License for more details.
|
|
|
f96e0b |
+ *
|
|
|
f96e0b |
+ * You should have received a copy of the GNU General Public License
|
|
|
f96e0b |
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
|
f96e0b |
+ */
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#include <grub/term.h>
|
|
|
f96e0b |
+#include <grub/types.h>
|
|
|
f96e0b |
+#include <grub/misc.h>
|
|
|
f96e0b |
+#include <grub/mm.h>
|
|
|
f96e0b |
+#include <grub/time.h>
|
|
|
f96e0b |
+#include <grub/terminfo.h>
|
|
|
f96e0b |
+#include <grub/dl.h>
|
|
|
f96e0b |
+#include <grub/speaker.h>
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+extern struct grub_terminfo_output_state grub_spkmodem_terminfo_output;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static void
|
|
|
f96e0b |
+put (struct grub_term_output *term __attribute__ ((unused)), const int c)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ int i;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ for (i = 7; i >= 0; i--)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ if ((c >> i) & 1)
|
|
|
f96e0b |
+ grub_speaker_beep_on (2000);
|
|
|
f96e0b |
+ else
|
|
|
f96e0b |
+ grub_speaker_beep_on (4000);
|
|
|
f96e0b |
+ grub_millisleep (10);
|
|
|
f96e0b |
+ grub_speaker_beep_on (1000);
|
|
|
f96e0b |
+ grub_millisleep (10);
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ grub_speaker_beep_on (50);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static grub_err_t
|
|
|
f96e0b |
+grub_spkmodem_init_output (struct grub_term_output *term)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_speaker_beep_on (50);
|
|
|
f96e0b |
+ grub_millisleep (50);
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ grub_terminfo_output_init (term);
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ return 0;
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static grub_err_t
|
|
|
f96e0b |
+grub_spkmodem_fini_output (struct grub_term_output *term __attribute__ ((unused)))
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_speaker_beep_off ();
|
|
|
f96e0b |
+ return 0;
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+struct grub_terminfo_output_state grub_spkmodem_terminfo_output =
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ .put = put,
|
|
|
f96e0b |
+ .width = 80,
|
|
|
f96e0b |
+ .height = 24
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static struct grub_term_output grub_spkmodem_term_output =
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ .name = "spkmodem",
|
|
|
f96e0b |
+ .init = grub_spkmodem_init_output,
|
|
|
f96e0b |
+ .fini = grub_spkmodem_fini_output,
|
|
|
f96e0b |
+ .putchar = grub_terminfo_putchar,
|
|
|
f96e0b |
+ .getxy = grub_terminfo_getxy,
|
|
|
f96e0b |
+ .getwh = grub_terminfo_getwh,
|
|
|
f96e0b |
+ .gotoxy = grub_terminfo_gotoxy,
|
|
|
f96e0b |
+ .cls = grub_terminfo_cls,
|
|
|
f96e0b |
+ .setcolorstate = grub_terminfo_setcolorstate,
|
|
|
f96e0b |
+ .setcursor = grub_terminfo_setcursor,
|
|
|
f96e0b |
+ .flags = GRUB_TERM_CODE_TYPE_ASCII,
|
|
|
f96e0b |
+ .data = &grub_spkmodem_terminfo_output,
|
|
|
f96e0b |
+ .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
|
|
f96e0b |
+ .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+GRUB_MOD_INIT (spkmodem)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_term_register_output ("spkmodem", &grub_spkmodem_term_output);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+GRUB_MOD_FINI (spkmodem)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ grub_term_unregister_output (&grub_spkmodem_term_output);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
diff --git a/include/grub/i386/pit.h b/include/grub/i386/pit.h
|
|
|
f96e0b |
index ff9b9a6..e1c92cd 100644
|
|
|
f96e0b |
--- a/include/grub/i386/pit.h
|
|
|
f96e0b |
+++ b/include/grub/i386/pit.h
|
|
|
f96e0b |
@@ -22,6 +22,84 @@
|
|
|
f96e0b |
#include <grub/types.h>
|
|
|
f96e0b |
#include <grub/err.h>
|
|
|
f96e0b |
|
|
|
f96e0b |
+enum
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ /* The PIT channel value ports. You can write to and read from them.
|
|
|
f96e0b |
+ Do not mess with timer 0 or 1. */
|
|
|
f96e0b |
+ GRUB_PIT_COUNTER_0 = 0x40,
|
|
|
f96e0b |
+ GRUB_PIT_COUNTER_1 = 0x41,
|
|
|
f96e0b |
+ GRUB_PIT_COUNTER_2 = 0x42,
|
|
|
f96e0b |
+ /* The PIT control port. You can only write to it. Do not mess with
|
|
|
f96e0b |
+ timer 0 or 1. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL = 0x43,
|
|
|
f96e0b |
+ /* The speaker port. */
|
|
|
f96e0b |
+ GRUB_PIT_SPEAKER_PORT = 0x61,
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+/* The speaker port. */
|
|
|
f96e0b |
+enum
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ /* If 0, follow state of SPEAKER_DATA bit, otherwise enable output
|
|
|
f96e0b |
+ from timer 2. */
|
|
|
f96e0b |
+ GRUB_PIT_SPK_TMR2 = 0x01,
|
|
|
f96e0b |
+ /* If SPEAKER_TMR2 is not set, this provides direct input into the
|
|
|
f96e0b |
+ speaker. Otherwise, this enables or disables the output from the
|
|
|
f96e0b |
+ timer. */
|
|
|
f96e0b |
+ GRUB_PIT_SPK_DATA = 0x02,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ GRUB_PIT_SPK_TMR2_LATCH = 0x20
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+/* The PIT control port. You can only write to it. Do not mess with
|
|
|
f96e0b |
+ timer 0 or 1. */
|
|
|
f96e0b |
+enum
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_SELECT_MASK = 0xc0,
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_SELECT_0 = 0x00,
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_SELECT_1 = 0x40,
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_SELECT_2 = 0x80,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Read and load control. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_READLOAD_MASK= 0x30,
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_COUNTER_LATCH = 0x00, /* Hold timer value until read. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_READLOAD_LSB = 0x10, /* Read/load the LSB. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_READLOAD_MSB = 0x20, /* Read/load the MSB. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_READLOAD_WORD = 0x30, /* Read/load the LSB then the MSB. */
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Mode control. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_MODE_MASK = 0x0e,
|
|
|
f96e0b |
+ /* Interrupt on terminal count. Setting the mode sets output to low.
|
|
|
f96e0b |
+ When counter is set and terminated, output is set to high. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_INTR_ON_TERM = 0x00,
|
|
|
f96e0b |
+ /* Programmable one-shot. When loading counter, output is set to
|
|
|
f96e0b |
+ high. When counter terminated, output is set to low. Can be
|
|
|
f96e0b |
+ triggered again from that point on by setting the gate pin to
|
|
|
f96e0b |
+ high. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_PROGR_ONE_SHOT = 0x02,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Rate generator. Output is low for one period of the counter, and
|
|
|
f96e0b |
+ high for the other. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_RATE_GEN = 0x04,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Square wave generator. Output is low for one half of the period,
|
|
|
f96e0b |
+ and high for the other half. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_SQUAREWAVE_GEN = 0x06,
|
|
|
f96e0b |
+ /* Software triggered strobe. Setting the mode sets output to high.
|
|
|
f96e0b |
+ When counter is set and terminated, output is set to low. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_SOFTSTROBE = 0x08,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Hardware triggered strobe. Like software triggered strobe, but
|
|
|
f96e0b |
+ only starts the counter when the gate pin is set to high. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_HARDSTROBE = 0x0a,
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Count mode. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_COUNT_MASK = 0x01,
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_COUNT_BINARY = 0x00, /* 16-bit binary counter. */
|
|
|
f96e0b |
+ GRUB_PIT_CTRL_COUNT_BCD = 0x01 /* 4-decade BCD counter. */
|
|
|
f96e0b |
+ };
|
|
|
f96e0b |
+
|
|
|
f96e0b |
void EXPORT_FUNC(grub_pit_wait) (grub_uint16_t tics);
|
|
|
f96e0b |
|
|
|
f96e0b |
#endif /* ! KERNEL_CPU_PIT_HEADER */
|
|
|
f96e0b |
diff --git a/include/grub/speaker.h b/include/grub/speaker.h
|
|
|
f96e0b |
new file mode 100644
|
|
|
f96e0b |
index 0000000..a076fcf
|
|
|
f96e0b |
--- /dev/null
|
|
|
f96e0b |
+++ b/include/grub/speaker.h
|
|
|
f96e0b |
@@ -0,0 +1,47 @@
|
|
|
f96e0b |
+#ifndef GRUB_SPEAKER_HEADER
|
|
|
f96e0b |
+#define GRUB_SPEAKER_HEADER 1
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#include <grub/cpu/io.h>
|
|
|
f96e0b |
+#include <grub/i386/pit.h>
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+/* The frequency of the PIT clock. */
|
|
|
f96e0b |
+#define GRUB_SPEAKER_PIT_FREQUENCY 0x1234dd
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static inline void
|
|
|
f96e0b |
+grub_speaker_beep_off (void)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ unsigned char status;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ status = grub_inb (GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
+ grub_outb (status & ~(GRUB_PIT_SPK_TMR2 | GRUB_PIT_SPK_DATA),
|
|
|
f96e0b |
+ GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static inline void
|
|
|
f96e0b |
+grub_speaker_beep_on (grub_uint16_t pitch)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ unsigned char status;
|
|
|
f96e0b |
+ unsigned int counter;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ if (pitch < 20)
|
|
|
f96e0b |
+ pitch = 20;
|
|
|
f96e0b |
+ else if (pitch > 20000)
|
|
|
f96e0b |
+ pitch = 20000;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ counter = GRUB_SPEAKER_PIT_FREQUENCY / pitch;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Program timer 2. */
|
|
|
f96e0b |
+ grub_outb (GRUB_PIT_CTRL_SELECT_2
|
|
|
f96e0b |
+ | GRUB_PIT_CTRL_READLOAD_WORD
|
|
|
f96e0b |
+ | GRUB_PIT_CTRL_SQUAREWAVE_GEN
|
|
|
f96e0b |
+ | GRUB_PIT_CTRL_COUNT_BINARY, GRUB_PIT_CTRL);
|
|
|
f96e0b |
+ grub_outb (counter & 0xff, GRUB_PIT_COUNTER_2); /* LSB */
|
|
|
f96e0b |
+ grub_outb ((counter >> 8) & 0xff, GRUB_PIT_COUNTER_2); /* MSB */
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ /* Start speaker. */
|
|
|
f96e0b |
+ status = grub_inb (GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
+ grub_outb (status | GRUB_PIT_SPK_TMR2 | GRUB_PIT_SPK_DATA,
|
|
|
f96e0b |
+ GRUB_PIT_SPEAKER_PORT);
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#endif
|
|
|
f96e0b |
diff --git a/util/spkmodem-recv.c b/util/spkmodem-recv.c
|
|
|
f96e0b |
new file mode 100644
|
|
|
f96e0b |
index 0000000..cbec3af
|
|
|
f96e0b |
--- /dev/null
|
|
|
f96e0b |
+++ b/util/spkmodem-recv.c
|
|
|
f96e0b |
@@ -0,0 +1,98 @@
|
|
|
f96e0b |
+#include <stdio.h>
|
|
|
f96e0b |
+#include <stdlib.h>
|
|
|
f96e0b |
+#include <string.h>
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+/* Compilation: gcc -o spkmodem-recv spkmodem-recv */
|
|
|
f96e0b |
+/* Usage: parecord --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv */
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#define RATE 48000
|
|
|
f96e0b |
+#define SAMPLES_PER_TRAME 480
|
|
|
f96e0b |
+#define AMPLITUDE_THRESHOLD 100000
|
|
|
f96e0b |
+#define FREQ_SEP_MIN 15
|
|
|
f96e0b |
+#define FREQ_SEP_NOM 20
|
|
|
f96e0b |
+#define FREQ_SEP_MAX 25
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#define FREQ_DATA_MIN 10
|
|
|
f96e0b |
+#define FREQ_DATA_THRESHOLD 60
|
|
|
f96e0b |
+#define FREQ_DATA_MAX 120
|
|
|
f96e0b |
+#define AMPLITUDE_SAMPLES 2 * SAMPLES_PER_TRAME
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#define THRESHOLD 1000
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+#define DEBUG 0
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static signed short trame[2 * SAMPLES_PER_TRAME];
|
|
|
f96e0b |
+static signed short pulse[2 * SAMPLES_PER_TRAME];
|
|
|
f96e0b |
+static int ringpos = 0;
|
|
|
f96e0b |
+static int pos, f1, f2;
|
|
|
f96e0b |
+static int amplitude = 0;
|
|
|
f96e0b |
+static int lp = 0;
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+static void
|
|
|
f96e0b |
+read_sample (void)
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ amplitude -= abs (trame[ringpos]);
|
|
|
f96e0b |
+ f1 -= pulse[ringpos];
|
|
|
f96e0b |
+ f1 += pulse[(ringpos + SAMPLES_PER_TRAME) % (2 * SAMPLES_PER_TRAME)];
|
|
|
f96e0b |
+ f2 -= pulse[(ringpos + SAMPLES_PER_TRAME) % (2 * SAMPLES_PER_TRAME)];
|
|
|
f96e0b |
+ fread (trame + ringpos, 1, sizeof (trame[0]), stdin);
|
|
|
f96e0b |
+ amplitude += abs (trame[ringpos]);
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+ if (pos ? (trame[ringpos] < -THRESHOLD)
|
|
|
f96e0b |
+ : (trame[ringpos] > +THRESHOLD))
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ pulse[ringpos] = 1;
|
|
|
f96e0b |
+ pos = !pos;
|
|
|
f96e0b |
+ f2++;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ else
|
|
|
f96e0b |
+ pulse[ringpos] = 0;
|
|
|
f96e0b |
+ ringpos++;
|
|
|
f96e0b |
+ ringpos %= 2 * SAMPLES_PER_TRAME;
|
|
|
f96e0b |
+ lp++;
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
+
|
|
|
f96e0b |
+int
|
|
|
f96e0b |
+main ()
|
|
|
f96e0b |
+{
|
|
|
f96e0b |
+ int bitn = 7;
|
|
|
f96e0b |
+ char c = 0;
|
|
|
f96e0b |
+ int i;
|
|
|
f96e0b |
+ while (!feof (stdin))
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ if (lp > 20000)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+ fflush (stdout);
|
|
|
f96e0b |
+ bitn = 7;
|
|
|
f96e0b |
+ c = 0;
|
|
|
f96e0b |
+ lp = 0;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ if (f2 > 12 && f2 < 25
|
|
|
f96e0b |
+ && f1 > 5 && f1 < 120)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+#if DEBUG
|
|
|
f96e0b |
+ printf ("%d %d %d @%d\n", f1, f2, FREQ_DATA_THRESHOLD,
|
|
|
f96e0b |
+ ftell (stdin) - sizeof (trame));
|
|
|
f96e0b |
+#endif
|
|
|
f96e0b |
+ if (f1 < 60)
|
|
|
f96e0b |
+ c |= (1 << bitn);
|
|
|
f96e0b |
+ bitn--;
|
|
|
f96e0b |
+ if (bitn < 0)
|
|
|
f96e0b |
+ {
|
|
|
f96e0b |
+#if DEBUG
|
|
|
f96e0b |
+ printf ("<%c, %x>", c, c);
|
|
|
f96e0b |
+#else
|
|
|
f96e0b |
+ printf ("%c", c);
|
|
|
f96e0b |
+#endif
|
|
|
f96e0b |
+ bitn = 7;
|
|
|
f96e0b |
+ c = 0;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ lp = 0;
|
|
|
f96e0b |
+ for (i = 0; i < SAMPLES_PER_TRAME; i++)
|
|
|
f96e0b |
+ read_sample ();
|
|
|
f96e0b |
+ continue;
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ read_sample ();
|
|
|
f96e0b |
+ }
|
|
|
f96e0b |
+ return 0;
|
|
|
f96e0b |
+}
|
|
|
f96e0b |
--
|
|
|
f96e0b |
1.8.2.1
|
|
|
f96e0b |
|