Chatgpt wrote a crappy beeper
This commit is contained in:
parent
4a446c2d51
commit
554f16cc7d
6
Makefile
6
Makefile
@ -44,7 +44,9 @@ OBJECTS = ./kernel/kstart.o ./kernel.o ./console.o ./drivers/vga.o ./drivers/uar
|
||||
./fs/fs.o ./drivers/ata.o ./lib/string.o ./proc.o ./drivers/pit.o ./kernel/vm.o
|
||||
|
||||
run: image.bin
|
||||
qemu-system-i386 -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait
|
||||
qemu-system-i386 -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait \
|
||||
-audiodev pa,id=SAUND \
|
||||
-machine pcspk-audiodev=SAUND
|
||||
|
||||
run-nox: image.bin
|
||||
qemu-system-i386 -nographic -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait
|
||||
@ -106,7 +108,7 @@ debug-nox: image.bin
|
||||
-ex "break _start" \
|
||||
-ex "continue"
|
||||
|
||||
USERPROGS=./user/false ./user/greet ./user/div0 ./user/shout ./user/badputs ./user/bss ./user/snake
|
||||
USERPROGS=./user/false ./user/greet ./user/div0 ./user/shout ./user/badputs ./user/bss ./user/snake ./user/player
|
||||
|
||||
fs.img: ./kernel.bin ./tools/mkfs $(USERPROGS)
|
||||
./tools/mkfs $@ $< $(USERPROGS)
|
||||
|
||||
@ -299,6 +299,13 @@ static void handle_syscall(registers_t* r) {
|
||||
case SYS_getc:
|
||||
r->eax = handle_getc();
|
||||
break;
|
||||
case SYS_set_beep:
|
||||
if (r->ebx > MAX_BEEP_FREQUENCY_HZ) {
|
||||
userspace_panic("Userspace panic: beep frequency out of range\n");
|
||||
}
|
||||
set_beep_frequency_hz(r->ebx);
|
||||
r->eax = 0;
|
||||
break;
|
||||
default:
|
||||
userspace_panic("Userspace panic: Unknown syscall\n");
|
||||
}
|
||||
|
||||
@ -23,6 +23,11 @@ enum {
|
||||
PIT_MODES_SQUARE_WAVE_GENERATOR = 0x3,
|
||||
PIT_MODES_SW_TRIGGERRED_STROBE = 0x4,
|
||||
PIT_MODES_HW_TRIGGERRED_STROBE = 0x5,
|
||||
|
||||
PIT_COMMAND_PORT = 0x43,
|
||||
PIT_CHANNEL0_DATA_PORT = 0x40,
|
||||
PIT_CHANNEL2_DATA_PORT = 0x42,
|
||||
PC_SPEAKER_PORT = 0x61,
|
||||
};
|
||||
|
||||
|
||||
@ -30,6 +35,7 @@ enum {
|
||||
static timer_callback callbacks[100];
|
||||
static int registered_callbacks = 0;
|
||||
static volatile uint32_t uptime_ms = 0;
|
||||
static volatile uint32_t speaker_frequency_hz = 0;
|
||||
|
||||
void add_timer_callback(timer_callback tc) {
|
||||
callbacks[registered_callbacks++] = tc;
|
||||
@ -57,9 +63,9 @@ void init_pit() {
|
||||
.operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR,
|
||||
.bcd = 0,
|
||||
};
|
||||
port_byte_out(0x43, *(unsigned char *)(&cmd));
|
||||
port_byte_out(0x40, PIT_PROGRAM_REG & 0xff);
|
||||
port_byte_out(0x40, (PIT_PROGRAM_REG & 0xff00) >> 8);
|
||||
port_byte_out(PIT_COMMAND_PORT, *(unsigned char *)(&cmd));
|
||||
port_byte_out(PIT_CHANNEL0_DATA_PORT, PIT_PROGRAM_REG & 0xff);
|
||||
port_byte_out(PIT_CHANNEL0_DATA_PORT, (PIT_PROGRAM_REG & 0xff00) >> 8);
|
||||
|
||||
register_interrupt_handler(IRQ0, timer_interrupt_handler);
|
||||
add_timer_callback(timer_int_callback);
|
||||
@ -76,6 +82,45 @@ uint32_t get_uptime_ms(void) {
|
||||
return uptime_ms;
|
||||
}
|
||||
|
||||
void set_beep_frequency_hz(uint32_t frequency_hz) {
|
||||
if (frequency_hz == 0) {
|
||||
disable_beep();
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t divisor = PIT_CRYSTAL_HZ / frequency_hz;
|
||||
if (divisor == 0) {
|
||||
divisor = 1;
|
||||
}
|
||||
if (divisor > 0xffff) {
|
||||
divisor = 0xffff;
|
||||
}
|
||||
|
||||
struct pit_command_t cmd = {
|
||||
.select_channel = PIT_SELECT_CHANNEL2,
|
||||
.access_mode = PIT_ACCESS_MODE_LOHIBYTE,
|
||||
.operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR,
|
||||
.bcd = 0,
|
||||
};
|
||||
port_byte_out(PIT_COMMAND_PORT, *(unsigned char *)(&cmd));
|
||||
port_byte_out(PIT_CHANNEL2_DATA_PORT, divisor & 0xff);
|
||||
port_byte_out(PIT_CHANNEL2_DATA_PORT, (divisor & 0xff00) >> 8);
|
||||
|
||||
uint8_t speaker = port_byte_in(PC_SPEAKER_PORT);
|
||||
port_byte_out(PC_SPEAKER_PORT, speaker | 0x03);
|
||||
speaker_frequency_hz = frequency_hz;
|
||||
}
|
||||
|
||||
void disable_beep(void) {
|
||||
uint8_t speaker = port_byte_in(PC_SPEAKER_PORT);
|
||||
port_byte_out(PC_SPEAKER_PORT, speaker & 0xfc);
|
||||
speaker_frequency_hz = 0;
|
||||
}
|
||||
|
||||
uint32_t get_beep_frequency_hz(void) {
|
||||
return speaker_frequency_hz;
|
||||
}
|
||||
|
||||
void msleep(int ms) {
|
||||
sleep_counter = ms / 10;
|
||||
while (sleep_counter > 0) {
|
||||
|
||||
@ -2,10 +2,15 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAX_BEEP_FREQUENCY_HZ 44100u
|
||||
|
||||
typedef void (*timer_callback)(void);
|
||||
|
||||
void init_pit(void);
|
||||
void add_timer_callback(timer_callback tc);
|
||||
|
||||
uint32_t get_uptime_ms(void);
|
||||
void set_beep_frequency_hz(uint32_t frequency_hz);
|
||||
void disable_beep(void);
|
||||
uint32_t get_beep_frequency_hz(void);
|
||||
void msleep(int ms);
|
||||
|
||||
2
proc.c
2
proc.c
@ -1,4 +1,5 @@
|
||||
#include "proc.h"
|
||||
#include "drivers/pit.h"
|
||||
#include "drivers/vga.h"
|
||||
|
||||
struct context {
|
||||
@ -88,6 +89,7 @@ void run_elf(const char* name) {
|
||||
|
||||
_Noreturn void killproc() {
|
||||
void* task_stack;
|
||||
disable_beep();
|
||||
if (!vga_is_text_mode()) {
|
||||
switch_to_text_mode();
|
||||
vga_clear_screen();
|
||||
|
||||
@ -14,6 +14,7 @@ enum {
|
||||
SYS_time_ms = 7,
|
||||
SYS_halt = 8,
|
||||
SYS_getc = 9,
|
||||
SYS_set_beep = 10,
|
||||
};
|
||||
|
||||
int syscall(int call, uintptr_t arg);
|
||||
|
||||
24
user/player.c
Normal file
24
user/player.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "../syscall.h"
|
||||
#include <stdint.h>
|
||||
|
||||
static uint32_t time_ms(void) {
|
||||
return (uint32_t)syscall(SYS_time_ms, 0);
|
||||
}
|
||||
|
||||
static void wait_ms(uint32_t duration_ms) {
|
||||
uint32_t start = time_ms();
|
||||
while ((uint32_t)(time_ms() - start) < duration_ms) {
|
||||
syscall(SYS_halt, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
syscall(SYS_set_beep, 10000);
|
||||
wait_ms(1000);
|
||||
|
||||
syscall(SYS_set_beep, 15000);
|
||||
wait_ms(1000);
|
||||
|
||||
// syscall(SYS_set_beep, 0);
|
||||
return 0;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user