1#![allow(dead_code)]
3
4extern crate alloc;
5use crate::kernel::audio_stream_fmt::{pwm_range, PcmQueue, PWM_STREAM_CLOCK_HZ};
6use crate::os_lib::mml::Note;
7use alloc::vec::Vec;
8use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
9use spin::Mutex;
10
11const GPIO_BASE: usize = 0x3F20_0000;
12const GPFSEL4: *mut u32 = (GPIO_BASE + 0x10) as *mut u32;
13
14const CM_BASE: usize = 0x3F10_1000;
15const CM_PWMCTL: *mut u32 = (CM_BASE + 0x10A0) as *mut u32;
16const CM_PWMDIV: *mut u32 = (CM_BASE + 0x10A4) as *mut u32;
17
18const PWM_BASE: usize = 0x3F20_C000;
19const PWM_CTL: *mut u32 = PWM_BASE as *mut u32;
20const PWM_STA: *mut u32 = (PWM_BASE + 0x04) as *mut u32;
21const PWM_DMAC: *mut u32 = (PWM_BASE + 0x08) as *mut u32;
22const PWM_RNG1: *mut u32 = (PWM_BASE + 0x10) as *mut u32;
23const PWM_DAT1: *mut u32 = (PWM_BASE + 0x14) as *mut u32;
24const PWM_FIF1: *mut u32 = (PWM_BASE + 0x18) as *mut u32;
25const PWM_RNG2: *mut u32 = (PWM_BASE + 0x20) as *mut u32;
26const PWM_DAT2: *mut u32 = (PWM_BASE + 0x24) as *mut u32;
27
28const I2S_BASE: usize = 0x3F20_3000;
30const I2S_CS: *mut u32 = I2S_BASE as *mut u32;
31const I2S_FIFO: *mut u32 = (I2S_BASE + 0x04) as *mut u32;
32const I2S_MODE: *mut u32 = (I2S_BASE + 0x08) as *mut u32;
33const I2S_RXC: *mut u32 = (I2S_BASE + 0x0C) as *mut u32;
34const I2S_TXC: *mut u32 = (I2S_BASE + 0x10) as *mut u32;
35const I2S_DREQ: *mut u32 = (I2S_BASE + 0x14) as *mut u32;
36
37const DMA3_BASE: usize = 0x3F00_7300;
39const DMA3_CS: *mut u32 = DMA3_BASE as *mut u32;
40const DMA3_CONBLK_AD: *mut u32 = (DMA3_BASE + 0x04) as *mut u32;
41
42const DMA4_BASE: usize = 0x3F00_7400;
43const DMA4_CS: *mut u32 = DMA4_BASE as *mut u32;
44const DMA4_CONBLK_AD: *mut u32 = (DMA4_BASE + 0x04) as *mut u32;
45
46const PWM_CLOCK_FREQ: u32 = 1_200_000;
48
49static PLAY_QUEUE: Mutex<Vec<Note>> = Mutex::new(Vec::new());
51static PLAY_INDEX: Mutex<usize> = Mutex::new(0);
52static IS_PLAYING: Mutex<bool> = Mutex::new(false);
53static THREAD_STARTED: Mutex<bool> = Mutex::new(false);
54
55static mut PCM_BUFFER_PWM: [u8; 65536] = [0; 65536];
57static mut PCM_BUFFER_I2S: [i16; 65536] = [0; 65536];
58static mut DMA_CB_PWM: crate::kernel::dma::DmaControlBlock = crate::kernel::dma::DmaControlBlock {
59 ti: 0,
60 source_ad: 0,
61 dest_ad: 0,
62 txfr_len: 0,
63 stride: 0,
64 nextconbk: 0,
65 _reserved: [0; 2],
66};
67static mut DMA_CB_I2S: crate::kernel::dma::DmaControlBlock = crate::kernel::dma::DmaControlBlock {
68 ti: 0,
69 source_ad: 0,
70 dest_ad: 0,
71 txfr_len: 0,
72 stride: 0,
73 nextconbk: 0,
74 _reserved: [0; 2],
75};
76
77pub struct Audio;
78
79impl Audio {
80 pub fn init() {
82 unsafe {
83 let mut val = core::ptr::read_volatile(GPFSEL4);
85 val &= !0b111; val |= 0b100; val &= !(0b111 << 15); val |= 0b100 << 15; core::ptr::write_volatile(GPFSEL4, val);
90
91 core::ptr::write_volatile(CM_PWMCTL, 0x5A00_0000);
94 for _ in 0..1000 {
95 core::arch::asm!("nop");
96 }
97
98 core::ptr::write_volatile(CM_PWMDIV, 0x5A00_0000 | (16 << 12));
100 for _ in 0..1000 {
101 core::arch::asm!("nop");
102 }
103
104 core::ptr::write_volatile(CM_PWMCTL, 0x5A00_0010 | 0x01);
106 for _ in 0..1000 {
107 core::arch::asm!("nop");
108 }
109
110 core::ptr::write_volatile(PWM_CTL, 0);
113 for _ in 0..1000 {
114 core::arch::asm!("nop");
115 }
116
117 core::ptr::write_volatile(PWM_RNG1, 1024);
119 core::ptr::write_volatile(PWM_RNG2, 1024);
120
121 core::ptr::write_volatile(PWM_DAT1, 0);
123 core::ptr::write_volatile(PWM_DAT2, 0);
124
125 core::ptr::write_volatile(PWM_CTL, (1 << 0) | (1 << 1) | (1 << 8) | (1 << 9));
127
128 core::ptr::write_volatile(I2S_CS, 0); core::ptr::write_volatile(I2S_MODE, 0);
132 core::ptr::write_volatile(I2S_TXC, (1 << 30) | (1 << 29) | (8 << 16) | (1 << 15)); core::ptr::write_volatile(I2S_DREQ, (8 << 24) | (8 << 8)); core::ptr::write_volatile(I2S_CS, 1 << 2); let dma_en_ptr = 0x3F007FF0 as *mut u32;
140 let current_en = core::ptr::read_volatile(dma_en_ptr);
141 core::ptr::write_volatile(dma_en_ptr, current_en | (1 << 3) | (1 << 4));
142 }
144
145 crate::info!(
146 "[AUD] Hardware PWM (Analog) and I2S (HDMI) audio engines initialized successfully."
147 );
148 }
149
150 fn ensure_playback_thread() {
155 let mut started = THREAD_STARTED.lock();
156 if !*started {
157 *started = true;
158 let pid = crate::kernel::scheduler::spawn(
163 Self::playback_thread_entry,
164 crate::kernel::scheduler::Priority::High,
165 "mml_player",
166 );
167 if pid == 0 {
168 crate::warn!("[AUDIO] 再生スレッドを起動できません(ヒープ不足)");
169 *started = false;
170 }
171 }
172 }
173
174 pub fn set_tone(freq: u32) {
176 if STREAM_ACTIVE.load(Ordering::Acquire) {
178 return;
179 }
180 if freq == 0 {
181 Self::mute();
182 return;
183 }
184
185 let rng = PWM_CLOCK_FREQ / freq;
186 let dat = rng / 2; unsafe {
189 core::ptr::write_volatile(PWM_RNG1, rng);
190 core::ptr::write_volatile(PWM_RNG2, rng);
191 core::ptr::write_volatile(PWM_DAT1, dat);
192 core::ptr::write_volatile(PWM_DAT2, dat);
193 }
194 }
195
196 pub fn mute() {
198 if STREAM_ACTIVE.load(Ordering::Acquire) {
199 return;
200 }
201 unsafe {
202 core::ptr::write_volatile(PWM_DAT1, 0);
203 core::ptr::write_volatile(PWM_DAT2, 0);
204 }
205 }
206
207 pub fn play_mml(mml_str: &str) {
209 let notes = crate::os_lib::mml::parse_mml(mml_str);
210 if notes.is_empty() {
211 return;
212 }
213
214 Self::ensure_playback_thread();
215 {
216 let mut queue = PLAY_QUEUE.lock();
217 let mut idx = PLAY_INDEX.lock();
218 let mut playing = IS_PLAYING.lock();
219
220 *queue = notes;
222 *idx = 0;
223 *playing = true;
224 }
225 }
226
227 pub fn is_playing() -> bool {
229 *IS_PLAYING.lock()
230 }
231
232 pub fn stop_mml() {
234 let mut queue = PLAY_QUEUE.lock();
235 let mut idx = PLAY_INDEX.lock();
236 queue.clear();
237 *idx = 0;
238 Self::mute();
239 }
240
241 pub fn play_tone_async(freq: u32, duration_ms: u32) {
243 let notes = alloc::vec![Note { freq, duration_ms }];
244
245 Self::ensure_playback_thread();
246 {
247 let mut queue = PLAY_QUEUE.lock();
248 let mut idx = PLAY_INDEX.lock();
249 let mut playing = IS_PLAYING.lock();
250
251 *queue = notes;
253 *idx = 0;
254 *playing = true;
255 }
256 }
257
258 fn playback_thread_entry() {
260 loop {
261 let note_opt = {
262 let mut queue = PLAY_QUEUE.lock();
263 let mut idx = PLAY_INDEX.lock();
264 if *idx < queue.len() {
265 let note = queue[*idx];
266 *idx += 1;
267 Some(note)
268 } else {
269 queue.clear();
271 *idx = 0;
272 let mut playing = IS_PLAYING.lock();
273 *playing = false;
274 None
275 }
276 };
277
278 if let Some(note) = note_opt {
279 if note.freq == 0 {
280 Self::mute();
281 } else {
282 Self::set_tone(note.freq);
283 }
284
285 let ticks = (note.duration_ms / 10) as usize;
287 if ticks > 0 {
288 crate::kernel::scheduler::sleep(ticks);
289 } else {
290 crate::kernel::scheduler::sleep(1);
291 }
292
293 Self::mute();
295 crate::kernel::scheduler::sleep(1);
296 } else {
297 crate::kernel::scheduler::sleep(2);
299 }
300 }
301 }
302
303 pub fn play_pcm_stream(pcm_data: &[i16]) {
305 if pcm_data.is_empty() {
306 return;
307 }
308
309 unsafe {
310 let len = pcm_data.len().min(65536);
312
313 core::ptr::copy_nonoverlapping(pcm_data.as_ptr(), PCM_BUFFER_I2S.as_mut_ptr(), len);
315
316 for i in 0..len {
318 let sample_8 = (((pcm_data[i] as i32 + 32768) >> 8) & 0xFF) as u8;
320 PCM_BUFFER_PWM[i] = ((sample_8 as u32 * 4).min(1023)) as u8;
322 }
323
324 let pwm_buf_ptr = PCM_BUFFER_PWM.as_ptr() as usize;
326 let i2s_buf_ptr = PCM_BUFFER_I2S.as_ptr() as usize;
327
328 crate::kernel::mmu::clean_dcache_range(pwm_buf_ptr, len);
329 crate::kernel::mmu::clean_dcache_range(i2s_buf_ptr, len * 2);
330
331 DMA_CB_PWM = crate::kernel::dma::DmaControlBlock {
333 ti: (5 << 16) | (1 << 8) | (1 << 4) | (1 << 3), source_ad: crate::kernel::dma::to_bus_address(pwm_buf_ptr as u32),
335 dest_ad: crate::kernel::dma::to_bus_address(PWM_FIF1 as u32),
336 txfr_len: len as u32,
337 stride: 0,
338 nextconbk: 0,
339 _reserved: [0; 2],
340 };
341 crate::kernel::mmu::clean_dcache_range(
342 &DMA_CB_PWM as *const _ as usize,
343 core::mem::size_of::<crate::kernel::dma::DmaControlBlock>(),
344 );
345
346 DMA_CB_I2S = crate::kernel::dma::DmaControlBlock {
348 ti: (6 << 16) | (1 << 8) | (1 << 4) | (1 << 3), source_ad: crate::kernel::dma::to_bus_address(i2s_buf_ptr as u32),
350 dest_ad: crate::kernel::dma::to_bus_address(I2S_FIFO as u32),
351 txfr_len: (len * 2) as u32,
352 stride: 0,
353 nextconbk: 0,
354 _reserved: [0; 2],
355 };
356 crate::kernel::mmu::clean_dcache_range(
357 &DMA_CB_I2S as *const _ as usize,
358 core::mem::size_of::<crate::kernel::dma::DmaControlBlock>(),
359 );
360
361 if !crate::kernel::dma::is_qemu_env() {
362 core::ptr::write_volatile(
365 DMA3_CONBLK_AD,
366 crate::kernel::dma::to_bus_address(&DMA_CB_PWM as *const _ as *const _ as u32),
367 );
368 core::ptr::write_volatile(DMA3_CS, (1 << 0) | (8 << 16)); core::ptr::write_volatile(
372 DMA4_CONBLK_AD,
373 crate::kernel::dma::to_bus_address(&DMA_CB_I2S as *const _ as *const _ as u32),
374 );
375 core::ptr::write_volatile(DMA4_CS, (1 << 0) | (8 << 16)); }
377 }
378 }
379}
380
381#[derive(Clone, Copy, Debug)]
382pub enum SeType {
383 Apply, Save, Delete, Close, }
388
389pub fn play_system_se(se: SeType) {
391 if !crate::kernel::config::get_config().enable_sound {
393 return;
394 }
395
396 let mml = match se {
397 SeType::Apply => "T180 L16 O5 C E G",
398 SeType::Save => "T240 L16 O5 G O6 C",
399 SeType::Delete => "T150 L12 O4 C O3 G",
400 SeType::Close => "T240 L16 O5 F D",
401 };
402
403 Audio::play_mml(mml);
404}
405
406const STREAM_DMA_CH: usize = 5;
428const STREAM_DMA_BASE: usize = 0x3F00_7000 + STREAM_DMA_CH * 0x100;
429const STREAM_DMA_CS: *mut u32 = STREAM_DMA_BASE as *mut u32;
430const STREAM_DMA_CONBLK_AD: *mut u32 = (STREAM_DMA_BASE + 0x04) as *mut u32;
431const DMA_ENABLE_REG: *mut u32 = 0x3F00_7FF0 as *mut u32;
432const PWM_FIF1_BUS: u32 = 0x7E20_C018;
434const CM_MAGIC: u32 = 0x5A00_0000;
436const STREAM_HALF_FRAMES: usize = 2048;
438const STREAM_HALF_WORDS: usize = STREAM_HALF_FRAMES * 2;
439
440#[repr(C, align(32))]
441struct StreamBuf([u32; STREAM_HALF_WORDS * 2]);
442static mut STREAM_BUF: StreamBuf = StreamBuf([0; STREAM_HALF_WORDS * 2]);
443static mut STREAM_CBS: [crate::kernel::dma::DmaControlBlock; 2] = [crate::kernel::dma::DmaControlBlock {
444 ti: 0,
445 source_ad: 0,
446 dest_ad: 0,
447 txfr_len: 0,
448 stride: 0,
449 nextconbk: 0,
450 _reserved: [0; 2],
451}; 2];
452
453static STREAM_QUEUE: Mutex<Option<PcmQueue>> = Mutex::new(None);
454static STREAM_ACTIVE: AtomicBool = AtomicBool::new(false);
455static STREAM_PAUSED: AtomicBool = AtomicBool::new(false);
456static STREAM_RANGE: AtomicU32 = AtomicU32::new(0);
457static FEEDER_RUNNING: AtomicBool = AtomicBool::new(false);
458
459fn ram_bus(addr: usize) -> u32 {
461 (addr as u32) | 0xC000_0000
462}
463
464pub struct AudioStream;
465
466impl AudioStream {
467 pub fn start(sample_rate: u32, channels: u32) {
469 if sample_rate == 0 {
470 return;
471 }
472 {
473 let mut q = STREAM_QUEUE.lock();
474 if let Some(cur) = q.as_ref() {
475 if STREAM_ACTIVE.load(Ordering::Acquire) && cur.sample_rate == sample_rate && cur.channels == channels.clamp(1, 2) {
476 return;
477 }
478 }
479 *q = Some(PcmQueue::new(sample_rate, channels));
480 }
481 let range = pwm_range(PWM_STREAM_CLOCK_HZ, sample_rate);
482 STREAM_RANGE.store(range, Ordering::Release);
483 STREAM_PAUSED.store(false, Ordering::Release);
484 Audio::stop_mml();
486 STREAM_ACTIVE.store(true, Ordering::Release);
487 if !crate::kernel::dma::is_qemu_env() {
488 unsafe { Self::hw_start(range) };
489 }
490 if !FEEDER_RUNNING.swap(true, Ordering::AcqRel) {
491 let pid = crate::kernel::scheduler::spawn(
492 Self::feeder_thread,
493 crate::kernel::scheduler::Priority::High,
494 "audio_feeder",
495 );
496 if pid == 0 {
497 crate::warn!("[AUDIO] 補給スレッドを起動できません(ヒープ不足)。連続再生を止めます");
498 FEEDER_RUNNING.store(false, Ordering::Release);
499 Self::stop();
500 return;
501 }
502 }
503 crate::warn!("[AUDIO] 連続再生開始 {}Hz {}ch range={}", sample_rate, channels, range);
504 }
505
506 pub fn push(pcm: &[i16]) {
508 if let Some(q) = STREAM_QUEUE.lock().as_mut() {
509 q.push(pcm);
510 }
511 }
512
513 pub fn buffered_ms() -> u64 {
515 STREAM_QUEUE.lock().as_ref().map(|q| q.buffered_ms()).unwrap_or(0)
516 }
517
518 pub fn set_paused(paused: bool) {
520 STREAM_PAUSED.store(paused, Ordering::Release);
521 }
522
523 pub fn flush() {
525 if let Some(q) = STREAM_QUEUE.lock().as_mut() {
526 q.clear();
527 }
528 }
529
530 pub fn is_active() -> bool {
531 STREAM_ACTIVE.load(Ordering::Acquire)
532 }
533
534 pub fn stop() {
536 if !STREAM_ACTIVE.swap(false, Ordering::AcqRel) {
537 return;
538 }
539 if !crate::kernel::dma::is_qemu_env() {
540 unsafe {
541 core::ptr::write_volatile(STREAM_DMA_CS, 1 << 31); core::ptr::write_volatile(PWM_DMAC, 0);
543 core::ptr::write_volatile(PWM_CTL, 0);
544 Self::delay();
545 Self::restore_tone_mode();
546 }
547 }
548 *STREAM_QUEUE.lock() = None;
549 crate::warn!("[AUDIO] 連続再生停止");
550 }
551
552 fn delay() {
553 for _ in 0..2000 {
554 core::hint::spin_loop();
555 }
556 }
557
558 unsafe fn hw_start(range: u32) {
560 unsafe {
561 core::ptr::write_volatile(STREAM_DMA_CS, 1 << 31);
563 core::ptr::write_volatile(PWM_DMAC, 0);
564 core::ptr::write_volatile(PWM_CTL, 0);
565 Self::delay();
566
567 let ctl = core::ptr::read_volatile(CM_PWMCTL);
569 core::ptr::write_volatile(CM_PWMCTL, CM_MAGIC | (ctl & !0x10));
570 let mut guard = 0;
571 while core::ptr::read_volatile(CM_PWMCTL) & 0x80 != 0 && guard < 100_000 {
572 guard += 1;
573 core::hint::spin_loop();
574 }
575 core::ptr::write_volatile(CM_PWMDIV, CM_MAGIC | (2 << 12));
576 core::ptr::write_volatile(CM_PWMCTL, CM_MAGIC | 6);
577 core::ptr::write_volatile(CM_PWMCTL, CM_MAGIC | 6 | 0x10);
578 Self::delay();
579
580 core::ptr::write_volatile(PWM_RNG1, range);
581 core::ptr::write_volatile(PWM_RNG2, range);
582 core::ptr::write_volatile(PWM_CTL, 1 << 6); Self::delay();
584 core::ptr::write_volatile(PWM_STA, 0x1FC); core::ptr::write_volatile(PWM_DMAC, (1 << 31) | (7 << 8) | 7);
587 core::ptr::write_volatile(PWM_CTL, (1 << 0) | (1 << 5) | (1 << 8) | (1 << 13));
589
590 Self::fill_half(0);
592 Self::fill_half(1);
593
594 let cbs = core::ptr::addr_of_mut!(STREAM_CBS) as *mut crate::kernel::dma::DmaControlBlock;
596 let buf = core::ptr::addr_of_mut!(STREAM_BUF.0) as *mut u32;
597 for i in 0..2usize {
598 let next = cbs.add(1 - i) as usize;
599 *cbs.add(i) = crate::kernel::dma::DmaControlBlock {
600 ti: (5 << 16) | (1 << 8) | (1 << 6) | (1 << 3),
602 source_ad: ram_bus(buf.add(i * STREAM_HALF_WORDS) as usize),
603 dest_ad: PWM_FIF1_BUS,
604 txfr_len: (STREAM_HALF_WORDS * 4) as u32,
605 stride: 0,
606 nextconbk: ram_bus(next),
607 _reserved: [0; 2],
608 };
609 }
610 crate::kernel::mmu::clean_dcache_range(
611 cbs as usize,
612 2 * core::mem::size_of::<crate::kernel::dma::DmaControlBlock>(),
613 );
614
615 let en = core::ptr::read_volatile(DMA_ENABLE_REG);
616 core::ptr::write_volatile(DMA_ENABLE_REG, en | (1 << STREAM_DMA_CH));
617 core::ptr::write_volatile(STREAM_DMA_CONBLK_AD, ram_bus(cbs as usize));
618 core::ptr::write_volatile(STREAM_DMA_CS, (1 << 0) | (8 << 16) | (8 << 20));
620 }
621 }
622
623 unsafe fn fill_half(half: usize) {
625 let range = STREAM_RANGE.load(Ordering::Acquire);
626 let buf = unsafe { core::ptr::addr_of_mut!(STREAM_BUF.0) as *mut u32 };
627 let words = unsafe { core::slice::from_raw_parts_mut(buf.add(half * STREAM_HALF_WORDS), STREAM_HALF_WORDS) };
628 if STREAM_PAUSED.load(Ordering::Acquire) {
629 words.fill(range / 2);
630 } else {
631 match STREAM_QUEUE.lock().as_mut() {
632 Some(q) => {
633 q.fill_words(words, range);
634 }
635 None => words.fill(range / 2),
636 }
637 }
638 crate::kernel::mmu::clean_dcache_range(words.as_ptr() as usize, STREAM_HALF_WORDS * 4);
639 }
640
641 fn feeder_thread() {
643 let qemu = crate::kernel::dma::is_qemu_env();
644 let cb1_bus = unsafe { ram_bus((core::ptr::addr_of!(STREAM_CBS) as *const crate::kernel::dma::DmaControlBlock).add(1) as usize) };
645 let mut last_half = 0usize;
646 let mut last_ms = crate::kernel::timer::get_system_time_ms();
647 while STREAM_ACTIVE.load(Ordering::Acquire) {
648 if qemu {
649 let now = crate::kernel::timer::get_system_time_ms();
650 let dt = now.wrapping_sub(last_ms);
651 last_ms = now;
652 if !STREAM_PAUSED.load(Ordering::Acquire) {
653 if let Some(q) = STREAM_QUEUE.lock().as_mut() {
654 let frames = (q.sample_rate as u64 * dt / 1000) as usize;
655 q.drain_frames(frames);
656 }
657 }
658 } else {
659 let cur = unsafe { core::ptr::read_volatile(STREAM_DMA_CONBLK_AD) };
660 let half = if cur == cb1_bus { 1 } else { 0 };
661 if half != last_half {
662 unsafe { Self::fill_half(last_half) };
664 last_half = half;
665 }
666 }
667 crate::kernel::scheduler::sleep(1);
668 }
669 FEEDER_RUNNING.store(false, Ordering::Release);
670 crate::kernel::scheduler::exit();
671 }
672
673 unsafe fn restore_tone_mode() {
675 unsafe {
676 core::ptr::write_volatile(CM_PWMCTL, CM_MAGIC);
677 Self::delay();
678 core::ptr::write_volatile(CM_PWMDIV, CM_MAGIC | (16 << 12));
679 Self::delay();
680 core::ptr::write_volatile(CM_PWMCTL, CM_MAGIC | 0x10 | 0x01);
681 Self::delay();
682 core::ptr::write_volatile(PWM_RNG1, 1024);
683 core::ptr::write_volatile(PWM_RNG2, 1024);
684 core::ptr::write_volatile(PWM_DAT1, 0);
685 core::ptr::write_volatile(PWM_DAT2, 0);
686 core::ptr::write_volatile(PWM_CTL, (1 << 0) | (1 << 1) | (1 << 8) | (1 << 9));
687 }
688 }
689}