|
From: | Vincent Pelletier |
Subject: | play.c |
Date: | Sat, 05 Nov 2005 15:17:36 +0100 |
User-agent: | Debian Thunderbird 1.0.7 (X11/20051017) |
Hi. Here is the play command, along with some songs. 2005-11-05 Vincent Pelletier <address@hidden> * commands/i386/pc/play.c: New file. * conf/i386-pc.rmk (pkgdata_MODULES): Added play.mod. (play_mod_SOURCES, play_mod_CFLAGS, play_mod_LDFLAGS): New macros. Vincent Pelletier
Index: commands/i386/pc/play.c =================================================================== RCS file: commands/i386/pc/play.c diff -N commands/i386/pc/play.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ commands/i386/pc/play.c 5 Nov 2005 14:06:00 -0000 @@ -0,0 +1,248 @@ +/* play.c - command to play a tune */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003 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 2 of the License, or + * (at your option) any later version. + * + * This program 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Lots of this file is borowed from GNU/Hurd generic-speaker driver */ + +#include <grub/normal.h> +#include <grub/dl.h> +#include <grub/arg.h> +#include <grub/file.h> +#include <grub/disk.h> +#include <grub/term.h> +#include <grub/misc.h> + +/* Read a byte from a port. */ +static inline unsigned char +inb (unsigned short port) +{ + unsigned char value; + + asm volatile ("inb %w1, %0" : "=a" (value) : "Nd" (port)); + asm volatile ("outb %%al, $0x80" : : ); + + return value; +} + +/* Write a byte to a port. */ +static inline void +outb (unsigned short port, unsigned char value) +{ + asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); + asm volatile ("outb %%al, $0x80" : : ); +} + +/* 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 ((short) 0) +#define T_FINE ((short) -1) + +struct note { + short pitch; + short duration; +}; + +static void +beep_off (void) +{ + unsigned char status; + + status = inb (SPEAKER) & ~(SPEAKER_TMR2 | SPEAKER_DATA); + outb (SPEAKER, status); +} + +static void +beep_on (short 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. */ + outb (PIT_CTRL, PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD + | PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY); + outb (PIT_COUNTER_2, counter & 0xff); /* LSB */ + outb (PIT_COUNTER_2, (counter >> 8) & 0xff); /* MSB */ + + /* Start speaker. */ + status = inb (SPEAKER) | SPEAKER_TMR2 | SPEAKER_DATA; + outb (SPEAKER, status); + +} + +static grub_err_t +grub_cmd_play (struct grub_arg_list *state __attribute__ ((unused)), + int argc, char **args) +{ + grub_file_t file; + struct note buf; + int tempo; + unsigned int to; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + file = grub_file_open (args[0]); + if (! file) + return 0; + + if (grub_file_read (file, (void *) &tempo, sizeof(tempo)) != sizeof(tempo)) + return 0; + + grub_printf ("Now playing %s...\n", args[0]); + + grub_dprintf ("play","tempo = %d\n", tempo); + + while (grub_file_read (file, (void *) &buf, sizeof(struct note)) == sizeof(struct note) && + buf.pitch != T_FINE && + grub_checkkey () == -1) + { + + grub_dprintf ("play","pitch = %d, duration = %d\n", buf.pitch, buf.duration); + + switch (buf.pitch) + { + case T_REST: + beep_off (); + break; + + default: + beep_on (buf.pitch); + break; + } + + to = grub_get_rtc () + 120*buf.duration/tempo; + while ((unsigned int) grub_get_rtc () <= to && grub_checkkey () == -1) + ; + + } + + beep_off (); + + grub_printf ("Done\n"); + + grub_file_close (file); + + while (grub_checkkey () != -1) + grub_getkey (); + + return 0; +} + + +#ifdef GRUB_UTIL +void +grub_play_init (void) +{ + grub_register_command ("play", grub_cmd_play, GRUB_COMMAND_FLAG_BOTH, + "play FILE", "Play a tune", 0); +} + +void +grub_play_fini (void) +{ + grub_unregister_command ("play"); +} +#else /* ! GRUB_UTIL */ +GRUB_MOD_INIT +{ + (void)mod; /* To stop warning. */ + grub_register_command ("play", grub_cmd_play, GRUB_COMMAND_FLAG_BOTH, + "play FILE", "Play a tune", 0); +} + +GRUB_MOD_FINI +{ + grub_unregister_command ("play"); +} +#endif /* ! GRUB_UTIL */ Index: conf/i386-pc.rmk =================================================================== RCS file: /cvsroot/grub/grub2/conf/i386-pc.rmk,v retrieving revision 1.50 diff -u -p -r1.50 i386-pc.rmk --- conf/i386-pc.rmk 24 Oct 2005 10:23:46 -0000 1.50 +++ conf/i386-pc.rmk 5 Nov 2005 14:06:02 -0000 @@ -117,7 +117,7 @@ pkgdata_MODULES = _chain.mod _linux.mod apple.mod pc.mod sun.mod loopback.mod reboot.mod halt.mod \ help.mod default.mod timeout.mod configfile.mod vbe.mod \ vesafb.mod vbetest.mod vbeinfo.mod search.mod gzio.mod \ - terminfo.mod serial.mod xfs.mod affs.mod sfs.mod + terminfo.mod serial.mod xfs.mod affs.mod sfs.mod play.mod # For _chain.mod. _chain_mod_SOURCES = loader/i386/pc/chainloader.c @@ -347,3 +347,8 @@ search_mod_LDFLAGS = $(COMMON_LDFLAGS) gzio_mod_SOURCES = io/gzio.c gzio_mod_CFLAGS = $(COMMON_CFLAGS) gzio_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For play.mod. +play_mod_SOURCES = commands/i386/pc/play.c +play_mod_CFLAGS = $(COMMON_CFLAGS) +play_mod_LDFLAGS = $(COMMON_LDFLAGS)
Beverly Hills Cop.
Description: Binary data
Enclosure
Description: Binary data
FSF_Song
Description: Binary data
I_Feel_Pretty
Description: Binary data
Indiana_Jones_Theme
Description: Binary data
Star Trek: The Next Generation
Description: Binary data
Summertime
Description: Binary data
Tetris_Theme
Description: Binary data
signature.asc
Description: OpenPGP digital signature
[Prev in Thread] | Current Thread | [Next in Thread] |