~sircmpwn/public-inbox

com32/modules: introduce play module v1 PROPOSED

Drew DeVault: 1
 com32/modules: introduce play module

 2 files changed, 96 insertions(+), 1 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~sircmpwn/public-inbox/patches/9585/mbox | git am -3
Learn more about email & git

[PATCH] com32/modules: introduce play module Export this patch

This plays a tune through the PC speaker and is compatible with the
GRUB2 command of the same name.

Signed-off-by: Drew DeVault <sir@cmpwn.com>
---
 com32/modules/Makefile |  2 +-
 com32/modules/play.c   | 95 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 com32/modules/play.c

diff --git a/com32/modules/Makefile b/com32/modules/Makefile
index c01d6338..5e69a0d7 100644
--- a/com32/modules/Makefile
+++ b/com32/modules/Makefile
@@ -20,7 +20,7 @@ include $(MAKEDIR)/elf.mk

# BIOS-specific modules
MOD_BIOS = disk.c32 elf.c32 ethersel.c32 gpxecmd.c32 ifmemdsk.c32 ifplop.c32 \
	   kbdmap.c32 kontron_wdt.c32 pcitest.c32 pmload.c32 poweroff.c32 \
	   kbdmap.c32 kontron_wdt.c32 pcitest.c32 play.c32 pmload.c32 poweroff.c32 \
	   prdhcp.c32 pxechn.c32 sanboot.c32 sdi.c32 vesainfo.c32

# All-architecture modules
diff --git a/com32/modules/play.c b/com32/modules/play.c
new file mode 100644
index 00000000..68741bf5
--- /dev/null
+++ b/com32/modules/play.c
@@ -0,0 +1,95 @@
/*
 * Plays a tune through the PC speaker.
 *
 * This file is based loosely on similar GRUB2 code.
 */
#include <stdlib.h>
#include <stdio.h>
#include <sys/io.h>
#include <unistd.h>

#define SPEAKER_PIT_FREQUENCY 0x1234dd
#define BASE_TEMPO (60 * 1000)
#define T_REST 0

#define PIT_COUNTER_2 0x42
#define PIT_CTRL 0x43
#define PIT_SPEAKER_PORT 0x61

#define PIT_SPK_TMR2 0x01
#define PIT_SPK_DATA 0x02
#define PIT_SPK_TMR2_LATCH 0x20
#define PIT_CTRL_SELECT_2 0x80
#define PIT_CTRL_READLOAD_WORD 0x30
#define PIT_CTRL_SQUAREWAVE_GEN 0x06
#define PIT_CTRL_COUNT_BINARY 0x00

static void beep_off(void)
{
	unsigned char status;

	status = inb(PIT_SPEAKER_PORT);
	outb(status & ~(PIT_SPK_TMR2 | PIT_SPK_DATA), PIT_SPEAKER_PORT);
}

static void beep_on(uint16_t pitch)
{
	unsigned char status;
	unsigned int counter;

	if (pitch < 20)
		pitch = 20;
	else if (pitch > 20000)
		pitch = 20000;

	counter = SPEAKER_PIT_FREQUENCY / pitch;
	outb(PIT_CTRL_SELECT_2
			| PIT_CTRL_READLOAD_WORD
			| PIT_CTRL_SQUAREWAVE_GEN
			| PIT_CTRL_COUNT_BINARY, PIT_CTRL);
	outb(counter & 0xff, PIT_COUNTER_2);
	outb((counter >> 8) & 0xff, PIT_COUNTER_2);

	status = inb(PIT_SPEAKER_PORT);
	outb(status | PIT_SPK_TMR2 | PIT_SPK_DATA, PIT_SPEAKER_PORT);
}

static void play(unsigned int tempo, uint16_t pitch, uint16_t duration)
{
	unsigned int ms = BASE_TEMPO * duration / tempo;

	switch (pitch) {
	case T_REST:
		beep_off();
		break;
	default:
		beep_on(pitch);
		break;
	}

	msleep(ms);
}

int main(int argc, char *argv[])
{
	int i;
	unsigned int tempo = 0;

	tempo = strtol(argv[1], NULL, 10);
	if (!tempo) {
		printf("usage: play [<tempo>] [<pitch> <duration>...]\n");
		return 1;
	}

	for (i = 2; i + 1 < argc; i += 2) {
		uint16_t pitch;
		uint16_t duration;

		pitch = strtol(argv[i], NULL, 10);
		duration = strtol(argv[i + 1], NULL, 10);
		play(tempo, pitch, duration);
	}

	beep_off();
	return 0;
}
-- 
2.25.0
View this thread in the archives