diff --git a/examples/audio_testsignal.rs b/examples/audio_testsignal.rs index 64f47d9..4195993 100644 --- a/examples/audio_testsignal.rs +++ b/examples/audio_testsignal.rs @@ -81,7 +81,7 @@ fn main() -> ! { } if counter % 5 == 0 { - println!("counter: {}", counter); + //println!("counter: {}", counter); } counter += 1; @@ -110,21 +110,39 @@ extern "C" fn MachineExternal() { pac::Interrupt::DMAC_NS => { let dmac = unsafe { &*pac::DMAC::PTR }; - // clear pending interrupts - dmac.dmac_irq_pend_reg0.write(|w| w.dma2_hlaf_irq_pend().set_bit()); - while dmac.dmac_irq_pend_reg0.read().dma2_hlaf_irq_pend().bit_is_set() {} - dmac.dmac_irq_pend_reg0.write(|w| w.dma2_pkg_irq_pend().set_bit()); - while dmac.dmac_irq_pend_reg0.read().dma2_pkg_irq_pend().bit_is_set() {} - //dmac.dmac_irq_pend_reg0.write(|w| w.dma2_queue_irq_pend().set_bit()); - //while dmac.dmac_irq_pend_reg0.read().dma2_queue_irq_pend().bit_is_set() {} - + // get some stats let packages = dmac.dmac_pkg_num_reg2.read().bits(); - println!("DMAC_NS {}", packages); + let left = dmac.dmac_bcnt_left_reg2.read().bits(); + //let bits = dmac.dmac_sta_reg.read().bits(); + //let mbus = twiddle::bit(bits, 31); + //let chans = twiddle::range(bits, 0..15); + + // get pending bits + let bits = dmac.dmac_irq_pend_reg0.read().bits(); + let pending = twiddle::range(bits, 8..10); + + // clear pending interrupts + if twiddle::bit(pending, 0) { // half package + dmac.dmac_irq_pend_reg0.write(|w| w.dma2_hlaf_irq_pend().set_bit()); + while dmac.dmac_irq_pend_reg0.read().dma2_hlaf_irq_pend().bit_is_set() {} + } + if twiddle::bit(pending, 1) { // end of package + dmac.dmac_irq_pend_reg0.write(|w| w.dma2_pkg_irq_pend().set_bit()); + while dmac.dmac_irq_pend_reg0.read().dma2_pkg_irq_pend().bit_is_set() {} + } + if twiddle::bit(pending, 2) { // end of queue + dmac.dmac_irq_pend_reg0.write(|w| w.dma2_queue_irq_pend().set_bit()); + while dmac.dmac_irq_pend_reg0.read().dma2_queue_irq_pend().bit_is_set() {} + } - let bits = dmac.dmac_sta_reg.read().bits(); - let mbus = twiddle::bit(bits, 31); - let chans = twiddle::range(bits, 0..15); - println!("DMAC_NS mbus:{} chans:{:#018b}", mbus, chans); // 0: idle, 1: busy + // dump some debug info + let counter = unsafe { COUNTER }; + if counter % 1000 == 0 { + println!("DMAC_NS pend:{:#05b}", pending); // 0: idle, 1: busy + println!("DMAC_NS pkg:{}", packages); + println!("DMAC_NS left:{}\n", left); + //println!("DMAC_NS mbus:{} chans:{:#018b}", mbus, chans); // 0: idle, 1: busy + } } pac::Interrupt::AUDIO_CODEC => { let audio_codec = unsafe { &*pac::AUDIOCODEC::PTR }; @@ -140,7 +158,6 @@ extern "C" fn MachineExternal() { //let mut ac_dac_txdata = unsafe { &*AUDIOCODEC::PTR }.ac_dac_txdata; const AC_DAC_TXDATA: *mut u32 = (audio_codec::SUNXI_AUDIO_CODEC + 0x0020) as *mut u32; let sample = audio_codec::TX_BUFFER[COUNTER]; - COUNTER += 1; if COUNTER == audio_codec::TX_BUFFER.len() { COUNTER = 0; } @@ -191,6 +208,8 @@ extern "C" fn MachineExternal() { } } + unsafe { COUNTER += 1 }; + // Release claim plic.complete(claim); } diff --git a/src/audio_codec.rs b/src/audio_codec.rs index f4686b9..1356946 100644 --- a/src/audio_codec.rs +++ b/src/audio_codec.rs @@ -68,6 +68,7 @@ use core::ptr::NonNull; use d1_pac as pac; use pac::{AUDIOCODEC, CCU}; +use crate::dmac::descriptor::Descriptor; use crate::dmac::{self, descriptor, descriptor::DescriptorConfig, Dmac}; use twiddle; use crate::println; @@ -439,10 +440,11 @@ fn configure_dac(codec: &AUDIOCODEC) { // .modify(|r, w| unsafe { w.bits(r.bits() | (0 << PB12)) }); } -pub const BLOCK_LENGTH: usize = 128; +pub const BLOCK_LENGTH: usize = 64; pub const STEREO_BLOCK_LENGTH: usize = BLOCK_LENGTH * 2; // 2 channels pub const TX_BUFFER_LENGTH:usize = STEREO_BLOCK_LENGTH * 2; // 2 half-blocks -pub static mut TX_BUFFER: [u32; TX_BUFFER_LENGTH] = [0; TX_BUFFER_LENGTH]; +pub static mut TX_BUFFER_1: [u32; TX_BUFFER_LENGTH] = [0; TX_BUFFER_LENGTH]; +pub static mut TX_BUFFER_2: [u32; TX_BUFFER_LENGTH] = [0; TX_BUFFER_LENGTH]; /// 8.4.4.2 Playback Process, page 769-770 /// @@ -461,8 +463,15 @@ fn enable_dac_drq_dma(codec: &AUDIOCODEC, dmac: &mut Dmac) { // generate some test noise unsafe { let mut counter = 0; - for byte in &mut TX_BUFFER { - *byte = ((u32::MAX / TX_BUFFER.len() as u32) * counter) as u32; + for byte in &mut TX_BUFFER_1 { + *byte = ((u32::MAX / TX_BUFFER_1.len() as u32) * counter) as u32; + counter += 1; + } + } + unsafe { + let mut counter = 0; + for byte in &mut TX_BUFFER_2 { + *byte = ((u32::MAX / TX_BUFFER_2.len() as u32) * counter) as u32; counter += 1; } } @@ -473,29 +482,52 @@ fn enable_dac_drq_dma(codec: &AUDIOCODEC, dmac: &mut Dmac) { let bits = twiddle::set(bits, 3, true); // DAC_IRQ_EN codec.ac_dac_fifoc.write(|w| unsafe { w.bits(bits) }); + // TODO pg. 225 make sure that TX_BUFFER_1 is word-aligned + // enable dma let ac_dac_txdata = &unsafe { &*AUDIOCODEC::PTR }.ac_dac_txdata as *const _ as *mut (); let descriptor_config = descriptor::DescriptorConfig { - source: unsafe { TX_BUFFER.as_ptr().cast() }, + // memory + source: unsafe { TX_BUFFER_1.as_ptr().cast() }, destination: ac_dac_txdata, - byte_counter: unsafe { TX_BUFFER.len() }, + byte_counter: unsafe { TX_BUFFER_1.len() }, // ??? + // byte_counter: unsafe { TX_BUFFER_LENGTH * 4 }, // ??? + // config link: None, wait_clock_cycles: 0, bmode: descriptor::BModeSel::Normal, + // destination dest_width: descriptor::DataWidth::Bit32, dest_addr_mode: descriptor::AddressMode::IoMode, dest_block_size: descriptor::BlockSize::Byte4, dest_drq_type: descriptor::DestDrqType::AudioCodec, + // source src_data_width: descriptor::DataWidth::Bit32, src_addr_mode: descriptor::AddressMode::LinearMode, - src_block_size: descriptor::BlockSize::Byte1, + src_block_size: descriptor::BlockSize::Byte4, src_drq_type: descriptor::SrcDrqType::Dram, }; - let descriptor = descriptor_config.try_into().unwrap(); + let mut descriptor_config_2 = descriptor_config.clone();; + + let mut descriptor_1: Descriptor = descriptor_config.try_into().unwrap(); + + // link descriptor_1 to descriptor_2 + let descriptor_1_ptr = &descriptor_1 as* const Descriptor as *const (); + descriptor_config_2.source = unsafe { TX_BUFFER_2.as_ptr().cast() }; + descriptor_config_2.link = Some(descriptor_1_ptr); + let descriptor_2: Descriptor = descriptor_config_2.try_into().unwrap(); + + // link descriptor_2 to descriptor_1 + let descriptor_2_ptr = &descriptor_2 as* const Descriptor as *const (); + descriptor_1.link = descriptor_2_ptr as u32; + descriptor_1.link |= ((descriptor_2_ptr as usize >> 32) as u32) & 0b11; unsafe { dmac.channels[2].set_channel_modes(dmac::ChannelMode::Wait, dmac::ChannelMode::Handshake); - dmac.channels[2].start_descriptor(NonNull::from(&descriptor)); + //dmac.channels[2].set_channel_modes(dmac::ChannelMode::Handshake, dmac::ChannelMode::Handshake); + //dmac.channels[2].set_channel_modes(dmac::ChannelMode::Wait, dmac::ChannelMode::Wait); + //dmac.channels[2].set_channel_modes(dmac::ChannelMode::Handshake, dmac::ChannelMode::Wait); + dmac.channels[2].start_descriptor(NonNull::from(&descriptor_1)); } } diff --git a/src/dmac.rs b/src/dmac.rs index 20fd680..1798635 100644 --- a/src/dmac.rs +++ b/src/dmac.rs @@ -28,6 +28,12 @@ pub struct Dmac { impl Dmac { pub fn new(dmac: DMAC, ccu: &mut CCU) -> Self { ccu.dma_bgr.write(|w| w.gating().pass().rst().deassert()); + // disable auto-gating, probably not needed? + dmac.dmac_auto_gate_reg.write( + |w| w.dma_chan_circuit().set_bit() + .dma_common_circuit().set_bit() + .dma_mclk_circuit().set_bit() + ); Self { dmac, channels: [ @@ -179,9 +185,9 @@ impl Channel { // TODO only handles channel 0 self.irq_en_reg0().write( - |w| w.dma2_hlaf_irq_en().set_bit() + |w| w//.dma2_hlaf_irq_en().set_bit() .dma2_pkg_irq_en().set_bit() - //.dma2_queue_irq_en().set_bit() + .dma2_queue_irq_en().set_bit() ); let desc_addr = desc.as_ptr() as usize; diff --git a/src/dmac/descriptor.rs b/src/dmac/descriptor.rs index 21e7d85..f4ecd8c 100644 --- a/src/dmac/descriptor.rs +++ b/src/dmac/descriptor.rs @@ -6,10 +6,11 @@ pub struct Descriptor { destination_address: u32, byte_counter: u32, parameter: u32, - link: u32, + pub link: u32, } // TODO: THIS COULD PROBABLY BE A BITFIELD LIBRARY +#[derive(Clone)] pub struct DescriptorConfig { pub source: *const (), pub destination: *mut (),