MULTIPLE: 3 изменения (реализован спикер, таймер больше не срет в логи, в ядре крутая бутанимация со спикером)
SPEAKER: реализован TIMER: не срет в логи больше KERNEL: крутая бутанимация со спикером
This commit is contained in:
parent
bcbb8f8303
commit
fe18dc2f99
7 changed files with 95 additions and 10 deletions
3
Makefile
3
Makefile
|
|
@ -23,6 +23,7 @@ OBJ = boot/boot.o \
|
|||
kernel/string.o \
|
||||
drivers/serial.o \
|
||||
drivers/vga.o \
|
||||
drivers/speaker.o \
|
||||
drivers/timer.o \
|
||||
drivers/keyboard.o
|
||||
|
||||
|
|
@ -67,7 +68,7 @@ iso: $(TARGET)
|
|||
# Честный запуск через ISO в QEMU
|
||||
run: iso
|
||||
@echo "[+] Запускаем peredOS в QEMU через CD-ROM..."
|
||||
qemu-system-i386 -cdrom $(ISO_IMAGE) -serial stdio
|
||||
qemu-system-i386 -cdrom $(ISO_IMAGE) -serial stdio -audiodev sdl,id=snd0 -machine pcspk-audiodev=snd0
|
||||
|
||||
# Очистка мусора
|
||||
clean:
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
- [x] Драйвер клавиатуры
|
||||
- [x] Нормальный драйвер VGA (скролл итд)
|
||||
- [x] Нормальный драйвер клавиатуры (Caps Lock, Shift, Numpad итд)
|
||||
- [ ] Драйвер PC Speaker
|
||||
- [x] Драйвер PC Speaker
|
||||
- [ ] Screen buffers (как tty в Linux)
|
||||
- [ ] ANSI Escape в screen buffers
|
||||
- [ ] Драйвер мыши
|
||||
|
|
|
|||
48
drivers/speaker.c
Normal file
48
drivers/speaker.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include "speaker.h"
|
||||
#include "timer.h" // Теперь здесь виден extern uint32_t system_ticks
|
||||
#include "../kernel/io.h"
|
||||
|
||||
void sleep_ms(uint32_t ms) {
|
||||
// 1 тик = 10 мс на частоте 100 Гц
|
||||
uint32_t ticks_to_wait = ms / 10;
|
||||
if (ticks_to_wait == 0) ticks_to_wait = 1; // Защита от слишком маленького интервала
|
||||
|
||||
uint32_t start_ticks = system_ticks;
|
||||
|
||||
// Ждем, пока разница тиков не достигнет нужного значения
|
||||
while ((system_ticks - start_ticks) < ticks_to_wait) {
|
||||
// Аппаратно засыпаем до следующего прерывания PIT
|
||||
__asm__ __volatile__("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void speaker_play(uint32_t frequency) {
|
||||
if (frequency == 0) return;
|
||||
|
||||
uint32_t divisor = 1193182 / frequency;
|
||||
|
||||
// Настраиваем Канал 2 PIT (порт 0x43, режим 0xB6)
|
||||
outb(0x43, 0xB6);
|
||||
|
||||
// Передаем делитель в порт данных Канала 2 (0x42)
|
||||
outb(0x42, (uint8_t)(divisor & 0xFF));
|
||||
outb(0x42, (uint8_t)((divisor >> 8) & 0xFF));
|
||||
|
||||
// Подключаем PIT к динамику через порт управления системными функциями
|
||||
uint8_t speaker_state = inb(0x61);
|
||||
if ((speaker_state & 3) != 3) {
|
||||
outb(0x61, speaker_state | 3);
|
||||
}
|
||||
}
|
||||
|
||||
void speaker_stop(void) {
|
||||
// Отключаем динамик, сбрасывая 0 и 1 биты
|
||||
uint8_t speaker_state = inb(0x61) & 0xFC;
|
||||
outb(0x61, speaker_state);
|
||||
}
|
||||
|
||||
void speaker_beep(uint32_t frequency, uint32_t duration_ms) {
|
||||
speaker_play(frequency);
|
||||
sleep_ms(duration_ms); // Наш халяльный sleep по прерываниям
|
||||
speaker_stop();
|
||||
}
|
||||
15
drivers/speaker.h
Normal file
15
drivers/speaker.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef SPEAKER_H
|
||||
#define SPEAKER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Включить звук заданной частоты (в Герцах)
|
||||
void speaker_play(uint32_t frequency);
|
||||
|
||||
// Выключить звук
|
||||
void speaker_stop(void);
|
||||
|
||||
// Издать короткий писк (бип) заданной частоты и длительности
|
||||
void speaker_beep(uint32_t frequency, uint32_t duration);
|
||||
|
||||
#endif
|
||||
|
|
@ -23,9 +23,4 @@ void timer_init(uint32_t frequency) {
|
|||
|
||||
void timer_handler(void) {
|
||||
system_ticks++;
|
||||
log_info(LOG_DETAIL, "Timer: tick!");
|
||||
// Каждые 100 тиков (1 раз в секунду) шлем инфу в логгер
|
||||
if (system_ticks % 100 == 0) {
|
||||
log_info(LOG_DETAIL, "Timer: one second passed");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
// Инициализация таймера нужной частотой (например, 100 Гц)
|
||||
void timer_init(uint32_t frequency);
|
||||
// Делаем счетчик видимым для всего ядра
|
||||
extern uint32_t system_ticks;
|
||||
|
||||
// Эта функция будет вызываться из нашего ассемблерного обработчика irq0
|
||||
void timer_init(uint32_t frequency);
|
||||
void timer_handler(void);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "../drivers/vga.h"
|
||||
#include "../drivers/serial.h"
|
||||
#include "../drivers/timer.h"
|
||||
#include "../drivers/speaker.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "pic.h"
|
||||
|
|
@ -27,5 +28,30 @@ void kernel_main(void) {
|
|||
timer_init(100);
|
||||
log_info(LOG_NORMAL, "Enabling IRQ...");
|
||||
__asm__ __volatile__("sti");
|
||||
vga_set_color(VGA_COLOR_LIGHT_GREEN, VGA_COLOR_BLACK);
|
||||
vga_print("h");
|
||||
speaker_beep(100, 10);
|
||||
vga_print("a");
|
||||
speaker_beep(125, 10);
|
||||
vga_print("i");
|
||||
speaker_beep(150, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(175, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(200, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(225, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(250, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(275, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(300, 10);
|
||||
vga_print("!");
|
||||
speaker_beep(325, 10);
|
||||
vga_print("\n # ### #### \n #### ### # ## ### #### # # # \n # # ##### ## ##### # # # # ### \n # # # # # # # # # # \n #### ### # ### #### ### #### \n # \n");
|
||||
speaker_beep(350, 400);
|
||||
vga_init();
|
||||
vga_set_color(VGA_COLOR_LIGHT_GRAY, VGA_COLOR_BLACK);
|
||||
while (1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue