SPEAKER: реализован TIMER: не срет в логи больше KERNEL: крутая бутанимация со спикером
48 lines
1.7 KiB
C
48 lines
1.7 KiB
C
#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();
|
|
}
|