Chatgpt wrote a crappy beeper

This commit is contained in:
Андреев Григорий 2026-04-06 16:40:50 +03:00
parent 4a446c2d51
commit 554f16cc7d
7 changed files with 91 additions and 5 deletions

View File

@ -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 ./fs/fs.o ./drivers/ata.o ./lib/string.o ./proc.o ./drivers/pit.o ./kernel/vm.o
run: image.bin 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 run-nox: image.bin
qemu-system-i386 -nographic -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait 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 "break _start" \
-ex "continue" -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) fs.img: ./kernel.bin ./tools/mkfs $(USERPROGS)
./tools/mkfs $@ $< $(USERPROGS) ./tools/mkfs $@ $< $(USERPROGS)

View File

@ -299,6 +299,13 @@ static void handle_syscall(registers_t* r) {
case SYS_getc: case SYS_getc:
r->eax = handle_getc(); r->eax = handle_getc();
break; 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: default:
userspace_panic("Userspace panic: Unknown syscall\n"); userspace_panic("Userspace panic: Unknown syscall\n");
} }

View File

@ -23,6 +23,11 @@ enum {
PIT_MODES_SQUARE_WAVE_GENERATOR = 0x3, PIT_MODES_SQUARE_WAVE_GENERATOR = 0x3,
PIT_MODES_SW_TRIGGERRED_STROBE = 0x4, PIT_MODES_SW_TRIGGERRED_STROBE = 0x4,
PIT_MODES_HW_TRIGGERRED_STROBE = 0x5, 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 timer_callback callbacks[100];
static int registered_callbacks = 0; static int registered_callbacks = 0;
static volatile uint32_t uptime_ms = 0; static volatile uint32_t uptime_ms = 0;
static volatile uint32_t speaker_frequency_hz = 0;
void add_timer_callback(timer_callback tc) { void add_timer_callback(timer_callback tc) {
callbacks[registered_callbacks++] = tc; callbacks[registered_callbacks++] = tc;
@ -57,9 +63,9 @@ void init_pit() {
.operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR, .operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR,
.bcd = 0, .bcd = 0,
}; };
port_byte_out(0x43, *(unsigned char *)(&cmd)); port_byte_out(PIT_COMMAND_PORT, *(unsigned char *)(&cmd));
port_byte_out(0x40, PIT_PROGRAM_REG & 0xff); port_byte_out(PIT_CHANNEL0_DATA_PORT, PIT_PROGRAM_REG & 0xff);
port_byte_out(0x40, (PIT_PROGRAM_REG & 0xff00) >> 8); port_byte_out(PIT_CHANNEL0_DATA_PORT, (PIT_PROGRAM_REG & 0xff00) >> 8);
register_interrupt_handler(IRQ0, timer_interrupt_handler); register_interrupt_handler(IRQ0, timer_interrupt_handler);
add_timer_callback(timer_int_callback); add_timer_callback(timer_int_callback);
@ -76,6 +82,45 @@ uint32_t get_uptime_ms(void) {
return uptime_ms; 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) { void msleep(int ms) {
sleep_counter = ms / 10; sleep_counter = ms / 10;
while (sleep_counter > 0) { while (sleep_counter > 0) {

View File

@ -2,10 +2,15 @@
#include <stdint.h> #include <stdint.h>
#define MAX_BEEP_FREQUENCY_HZ 44100u
typedef void (*timer_callback)(void); typedef void (*timer_callback)(void);
void init_pit(void); void init_pit(void);
void add_timer_callback(timer_callback tc); void add_timer_callback(timer_callback tc);
uint32_t get_uptime_ms(void); 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); void msleep(int ms);

2
proc.c
View File

@ -1,4 +1,5 @@
#include "proc.h" #include "proc.h"
#include "drivers/pit.h"
#include "drivers/vga.h" #include "drivers/vga.h"
struct context { struct context {
@ -88,6 +89,7 @@ void run_elf(const char* name) {
_Noreturn void killproc() { _Noreturn void killproc() {
void* task_stack; void* task_stack;
disable_beep();
if (!vga_is_text_mode()) { if (!vga_is_text_mode()) {
switch_to_text_mode(); switch_to_text_mode();
vga_clear_screen(); vga_clear_screen();

View File

@ -14,6 +14,7 @@ enum {
SYS_time_ms = 7, SYS_time_ms = 7,
SYS_halt = 8, SYS_halt = 8,
SYS_getc = 9, SYS_getc = 9,
SYS_set_beep = 10,
}; };
int syscall(int call, uintptr_t arg); int syscall(int call, uintptr_t arg);

24
user/player.c Normal file
View 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;
}