New terminal outputs using serial: morse and spkmodem.
This commit is contained in:
parent
34f71cb866
commit
b78d6c32e3
10 changed files with 512 additions and 132 deletions
|
@ -778,6 +778,18 @@ module = {
|
|||
enable = x86;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = spkmodem;
|
||||
x86 = term/spkmodem.c;
|
||||
enable = x86;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = morse;
|
||||
x86 = term/morse.c;
|
||||
enable = x86;
|
||||
};
|
||||
|
||||
module = {
|
||||
name = probe;
|
||||
common = commands/probe.c;
|
||||
|
|
|
@ -28,80 +28,12 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/speaker.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define BASE_TEMPO (60 * 1000)
|
||||
|
||||
/* The speaker port. */
|
||||
#define SPEAKER 0x61
|
||||
|
||||
/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output
|
||||
from timer 2. */
|
||||
#define SPEAKER_TMR2 0x01
|
||||
|
||||
/* If SPEAKER_TMR2 is not set, this provides direct input into the
|
||||
speaker. Otherwise, this enables or disables the output from the
|
||||
timer. */
|
||||
#define SPEAKER_DATA 0x02
|
||||
|
||||
/* The PIT channel value ports. You can write to and read from them.
|
||||
Do not mess with timer 0 or 1. */
|
||||
#define PIT_COUNTER_0 0x40
|
||||
#define PIT_COUNTER_1 0x41
|
||||
#define PIT_COUNTER_2 0x42
|
||||
|
||||
/* The frequency of the PIT clock. */
|
||||
#define PIT_FREQUENCY 0x1234dd
|
||||
|
||||
/* The PIT control port. You can only write to it. Do not mess with
|
||||
timer 0 or 1. */
|
||||
#define PIT_CTRL 0x43
|
||||
#define PIT_CTRL_SELECT_MASK 0xc0
|
||||
#define PIT_CTRL_SELECT_0 0x00
|
||||
#define PIT_CTRL_SELECT_1 0x40
|
||||
#define PIT_CTRL_SELECT_2 0x80
|
||||
|
||||
/* Read and load control. */
|
||||
#define PIT_CTRL_READLOAD_MASK 0x30
|
||||
#define PIT_CTRL_COUNTER_LATCH 0x00 /* Hold timer value until read. */
|
||||
#define PIT_CTRL_READLOAD_LSB 0x10 /* Read/load the LSB. */
|
||||
#define PIT_CTRL_READLOAD_MSB 0x20 /* Read/load the MSB. */
|
||||
#define PIT_CTRL_READLOAD_WORD 0x30 /* Read/load the LSB then the MSB. */
|
||||
|
||||
/* Mode control. */
|
||||
#define PIT_CTRL_MODE_MASK 0x0e
|
||||
|
||||
/* Interrupt on terminal count. Setting the mode sets output to low.
|
||||
When counter is set and terminated, output is set to high. */
|
||||
#define PIT_CTRL_INTR_ON_TERM 0x00
|
||||
|
||||
/* Programmable one-shot. When loading counter, output is set to
|
||||
high. When counter terminated, output is set to low. Can be
|
||||
triggered again from that point on by setting the gate pin to
|
||||
high. */
|
||||
#define PIT_CTRL_PROGR_ONE_SHOT 0x02
|
||||
|
||||
/* Rate generator. Output is low for one period of the counter, and
|
||||
high for the other. */
|
||||
#define PIT_CTRL_RATE_GEN 0x04
|
||||
|
||||
/* Square wave generator. Output is low for one half of the period,
|
||||
and high for the other half. */
|
||||
#define PIT_CTRL_SQUAREWAVE_GEN 0x06
|
||||
|
||||
/* Software triggered strobe. Setting the mode sets output to high.
|
||||
When counter is set and terminated, output is set to low. */
|
||||
#define PIT_CTRL_SOFTSTROBE 0x08
|
||||
|
||||
/* Hardware triggered strobe. Like software triggered strobe, but
|
||||
only starts the counter when the gate pin is set to high. */
|
||||
#define PIT_CTRL_HARDSTROBE 0x0a
|
||||
|
||||
/* Count mode. */
|
||||
#define PIT_CTRL_COUNT_MASK 0x01
|
||||
#define PIT_CTRL_COUNT_BINARY 0x00 /* 16-bit binary counter. */
|
||||
#define PIT_CTRL_COUNT_BCD 0x01 /* 4-decade BCD counter. */
|
||||
|
||||
#define T_REST ((grub_uint16_t) 0)
|
||||
#define T_FINE ((grub_uint16_t) -1)
|
||||
|
@ -112,39 +44,6 @@ struct note
|
|||
grub_uint16_t duration;
|
||||
};
|
||||
|
||||
static void
|
||||
beep_off (void)
|
||||
{
|
||||
unsigned char status;
|
||||
|
||||
status = grub_inb (SPEAKER);
|
||||
grub_outb (status & ~(SPEAKER_TMR2 | SPEAKER_DATA), SPEAKER);
|
||||
}
|
||||
|
||||
static void
|
||||
beep_on (grub_uint16_t pitch)
|
||||
{
|
||||
unsigned char status;
|
||||
unsigned int counter;
|
||||
|
||||
if (pitch < 20)
|
||||
pitch = 20;
|
||||
else if (pitch > 20000)
|
||||
pitch = 20000;
|
||||
|
||||
counter = PIT_FREQUENCY / pitch;
|
||||
|
||||
/* Program timer 2. */
|
||||
grub_outb (PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD
|
||||
| PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY, PIT_CTRL);
|
||||
grub_outb (counter & 0xff, PIT_COUNTER_2); /* LSB */
|
||||
grub_outb ((counter >> 8) & 0xff, PIT_COUNTER_2); /* MSB */
|
||||
|
||||
/* Start speaker. */
|
||||
status = grub_inb (SPEAKER);
|
||||
grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER);
|
||||
}
|
||||
|
||||
/* Returns whether playing should continue. */
|
||||
static int
|
||||
play (unsigned tempo, struct note *note)
|
||||
|
@ -160,11 +59,11 @@ play (unsigned tempo, struct note *note)
|
|||
switch (note->pitch)
|
||||
{
|
||||
case T_REST:
|
||||
beep_off ();
|
||||
grub_speaker_beep_off ();
|
||||
break;
|
||||
|
||||
default:
|
||||
beep_on (note->pitch);
|
||||
grub_speaker_beep_on (note->pitch);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -263,7 +162,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
|
|||
}
|
||||
}
|
||||
|
||||
beep_off ();
|
||||
grub_speaker_beep_off ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,37 +20,30 @@
|
|||
#include <grub/i386/io.h>
|
||||
#include <grub/i386/pit.h>
|
||||
|
||||
#define TIMER2_REG_CONTROL 0x42
|
||||
#define TIMER_REG_COMMAND 0x43
|
||||
#define TIMER2_REG_LATCH 0x61
|
||||
|
||||
#define TIMER2_SELECT 0x80
|
||||
#define TIMER_ENABLE_LSB 0x20
|
||||
#define TIMER_ENABLE_MSB 0x10
|
||||
#define TIMER2_LATCH 0x20
|
||||
#define TIMER2_SPEAKER 0x02
|
||||
#define TIMER2_GATE 0x01
|
||||
|
||||
void
|
||||
grub_pit_wait (grub_uint16_t tics)
|
||||
{
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
|
||||
TIMER2_REG_LATCH);
|
||||
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
||||
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
/* Set tics. */
|
||||
grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND);
|
||||
grub_outb (tics & 0xff, TIMER2_REG_CONTROL);
|
||||
grub_outb (tics >> 8, TIMER2_REG_CONTROL);
|
||||
grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD,
|
||||
GRUB_PIT_CTRL);
|
||||
grub_outb (tics & 0xff, GRUB_PIT_COUNTER_2);
|
||||
grub_outb (tics >> 8, GRUB_PIT_COUNTER_2);
|
||||
|
||||
/* Enable timer2 gate, keep speaker disabled. */
|
||||
grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE,
|
||||
TIMER2_REG_LATCH);
|
||||
grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA)
|
||||
| GRUB_PIT_SPK_TMR2,
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
|
||||
/* Wait. */
|
||||
while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00);
|
||||
while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00);
|
||||
|
||||
/* Disable timer2 gate and speaker. */
|
||||
grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE),
|
||||
TIMER2_REG_LATCH);
|
||||
grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT)
|
||||
& ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2),
|
||||
GRUB_PIT_SPEAKER_PORT);
|
||||
}
|
||||
|
|
131
grub-core/term/morse.c
Normal file
131
grub-core/term/morse.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2011,2012,2013 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/err.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/speaker.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
#define BASE_TIME 250
|
||||
|
||||
static const char codes[0x80][6] =
|
||||
{
|
||||
['0'] = { 3, 3, 3, 3, 3, 0 },
|
||||
['1'] = { 1, 3, 3, 3, 3, 0 },
|
||||
['2'] = { 1, 1, 3, 3, 3, 0 },
|
||||
['3'] = { 1, 1, 1, 3, 3, 0 },
|
||||
['4'] = { 1, 1, 1, 1, 3, 0 },
|
||||
['5'] = { 1, 1, 1, 1, 1, 0 },
|
||||
['6'] = { 3, 1, 1, 1, 1, 0 },
|
||||
['7'] = { 3, 3, 1, 1, 1, 0 },
|
||||
['8'] = { 3, 3, 3, 1, 1, 0 },
|
||||
['9'] = { 3, 3, 3, 3, 1, 0 },
|
||||
['a'] = { 1, 3, 0 },
|
||||
['b'] = { 3, 1, 1, 1, 0 },
|
||||
['c'] = { 3, 1, 3, 1, 0 },
|
||||
['d'] = { 3, 1, 1, 0 },
|
||||
['e'] = { 1, 0 },
|
||||
['f'] = { 1, 1, 3, 1, 0 },
|
||||
['g'] = { 3, 3, 1, 0 },
|
||||
['h'] = { 1, 1, 1, 1, 0 },
|
||||
['i'] = { 1, 1, 0 },
|
||||
['j'] = { 1, 3, 3, 3, 0 },
|
||||
['k'] = { 3, 1, 3, 0 },
|
||||
['l'] = { 1, 3, 1, 1, 0 },
|
||||
['m'] = { 3, 3, 0 },
|
||||
['n'] = { 3, 1, 0 },
|
||||
['o'] = { 3, 3, 3, 0 },
|
||||
['p'] = { 1, 3, 3, 1, 0 },
|
||||
['q'] = { 3, 3, 1, 3, 0 },
|
||||
['r'] = { 1, 3, 1, 0 },
|
||||
['s'] = { 1, 1, 1, 0 },
|
||||
['t'] = { 3, 0 },
|
||||
['u'] = { 1, 1, 3, 0 },
|
||||
['v'] = { 1, 1, 1, 3, 0 },
|
||||
['w'] = { 1, 3, 3, 0 },
|
||||
['x'] = { 3, 1, 1, 3, 0 },
|
||||
['y'] = { 3, 1, 3, 3, 0 },
|
||||
['z'] = { 3, 3, 1, 1, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
grub_audio_tone (int length)
|
||||
{
|
||||
grub_speaker_beep_on (1000);
|
||||
grub_millisleep (length);
|
||||
grub_speaker_beep_off ();
|
||||
}
|
||||
|
||||
static void
|
||||
grub_audio_putchar (struct grub_term_output *term __attribute__ ((unused)),
|
||||
const struct grub_unicode_glyph *c_in)
|
||||
{
|
||||
grub_uint8_t c;
|
||||
int i;
|
||||
|
||||
/* For now, do not try to use a surrogate pair. */
|
||||
if (c_in->base > 0x7f)
|
||||
c = '?';
|
||||
else
|
||||
c = grub_tolower (c_in->base);
|
||||
for (i = 0; codes[c][i]; i++)
|
||||
{
|
||||
grub_audio_tone (codes[c][i] * BASE_TIME);
|
||||
grub_millisleep (BASE_TIME);
|
||||
}
|
||||
grub_millisleep (2 * BASE_TIME);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
dummy (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct grub_term_output grub_audio_term_output =
|
||||
{
|
||||
.name = "morse",
|
||||
.init = (void *) dummy,
|
||||
.fini = (void *) dummy,
|
||||
.putchar = grub_audio_putchar,
|
||||
.getwh = (void *) dummy,
|
||||
.getxy = (void *) dummy,
|
||||
.gotoxy = (void *) dummy,
|
||||
.cls = (void *) dummy,
|
||||
.setcolorstate = (void *) dummy,
|
||||
.setcursor = (void *) dummy,
|
||||
.normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
||||
.highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
||||
.flags = GRUB_TERM_CODE_TYPE_ASCII | GRUB_TERM_DUMB
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT (morse)
|
||||
{
|
||||
grub_term_register_output ("audio", &grub_audio_term_output);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI (morse)
|
||||
{
|
||||
grub_term_unregister_output (&grub_audio_term_output);
|
||||
}
|
106
grub-core/term/spkmodem.c
Normal file
106
grub-core/term/spkmodem.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/* console.c -- Open Firmware console for GRUB. */
|
||||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/term.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/time.h>
|
||||
#include <grub/terminfo.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/speaker.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
extern struct grub_terminfo_output_state grub_spkmodem_terminfo_output;
|
||||
|
||||
static void
|
||||
put (struct grub_term_output *term __attribute__ ((unused)), const int c)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 7; i >= 0; i--)
|
||||
{
|
||||
if ((c >> i) & 1)
|
||||
grub_speaker_beep_on (2000);
|
||||
else
|
||||
grub_speaker_beep_on (4000);
|
||||
grub_millisleep (10);
|
||||
grub_speaker_beep_on (1000);
|
||||
grub_millisleep (10);
|
||||
}
|
||||
grub_speaker_beep_on (50);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_spkmodem_init_output (struct grub_term_output *term)
|
||||
{
|
||||
grub_speaker_beep_on (50);
|
||||
grub_millisleep (50);
|
||||
|
||||
grub_terminfo_output_init (term);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_spkmodem_fini_output (struct grub_term_output *term __attribute__ ((unused)))
|
||||
{
|
||||
grub_speaker_beep_off ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
struct grub_terminfo_output_state grub_spkmodem_terminfo_output =
|
||||
{
|
||||
.put = put,
|
||||
.width = 80,
|
||||
.height = 24
|
||||
};
|
||||
|
||||
static struct grub_term_output grub_spkmodem_term_output =
|
||||
{
|
||||
.name = "spkmodem",
|
||||
.init = grub_spkmodem_init_output,
|
||||
.fini = grub_spkmodem_fini_output,
|
||||
.putchar = grub_terminfo_putchar,
|
||||
.getxy = grub_terminfo_getxy,
|
||||
.getwh = grub_terminfo_getwh,
|
||||
.gotoxy = grub_terminfo_gotoxy,
|
||||
.cls = grub_terminfo_cls,
|
||||
.setcolorstate = grub_terminfo_setcolorstate,
|
||||
.setcursor = grub_terminfo_setcursor,
|
||||
.flags = GRUB_TERM_CODE_TYPE_ASCII,
|
||||
.data = &grub_spkmodem_terminfo_output,
|
||||
.normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR,
|
||||
.highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR,
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT (spkmodem)
|
||||
{
|
||||
grub_term_register_output ("spkmodem", &grub_spkmodem_term_output);
|
||||
}
|
||||
|
||||
|
||||
GRUB_MOD_FINI (spkmodem)
|
||||
{
|
||||
grub_term_unregister_output (&grub_spkmodem_term_output);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue