DMA for pwm works
This commit is contained in:
parent
60da60250e
commit
54c7ef4b33
114
src/main.rs
114
src/main.rs
|
@ -21,6 +21,8 @@ mod si5153;
|
|||
#[app(device = stm32f4xx_hal::pac, peripherals = true, dispatchers = [SPI3])]
|
||||
mod app {
|
||||
|
||||
use core::mem;
|
||||
|
||||
use embedded_hal::blocking::spi::transfer;
|
||||
use num::Complex;
|
||||
use stm32f4xx_hal::{
|
||||
|
@ -32,13 +34,17 @@ mod app {
|
|||
},
|
||||
Adc,
|
||||
},
|
||||
dma::{self, config::DmaConfig, PeripheralToMemory, Stream0, StreamsTuple, Transfer},
|
||||
dma::{
|
||||
self, config::DmaConfig, PeripheralToMemory, Stream0, Stream7, StreamsTuple, Transfer,
|
||||
},
|
||||
gpio::{self, gpioa, gpioc, Analog, Output, PushPull},
|
||||
i2c::{self, I2c},
|
||||
pac::{ADC1, DMA2, I2C1, SPI1, TIM2, TIM4},
|
||||
pac::{ADC1, DMA1, DMA2, I2C1, SPI1, TIM2, TIM4},
|
||||
prelude::*,
|
||||
spi::{self, Spi},
|
||||
timer::{self, Channel, Channel1, Channel3, ChannelBuilder, CounterHz, Event, PwmHz},
|
||||
timer::{
|
||||
self, Channel, Channel1, Channel3, ChannelBuilder, CounterHz, Event, PwmHz, CCR, CCR3,
|
||||
},
|
||||
};
|
||||
|
||||
use cortex_m::{asm, singleton};
|
||||
|
@ -67,15 +73,25 @@ mod app {
|
|||
//mic_in: gpio::Pin<'A', 4, Analog>,
|
||||
i_in: gpio::Pin<'A', 1, Analog>,
|
||||
q_in: gpio::Pin<'A', 0, Analog>,
|
||||
phase: f32,
|
||||
i_offset: f32,
|
||||
q_offset: f32,
|
||||
audio_pwm: AudioPwm,
|
||||
usb_filter: filters::FirFilter<63>,
|
||||
transfer:
|
||||
adc_transfer:
|
||||
Transfer<Stream0<DMA2>, 0, Adc<ADC1>, PeripheralToMemory, &'static mut [u16; 256]>,
|
||||
iq_buffer: Option<&'static mut [u16; 256]>,
|
||||
|
||||
pwm_transfer: Transfer<
|
||||
Stream7<DMA1>,
|
||||
2,
|
||||
CCR<stm32f4xx_hal::pac::TIM4, 2>,
|
||||
stm32f4xx_hal::dma::MemoryToPeripheral,
|
||||
&'static mut [u16; 256],
|
||||
>,
|
||||
audio_buffer: Option<&'static mut [u16; 256]>,
|
||||
phase: f32,
|
||||
audio_max_duty: u16,
|
||||
|
||||
disp_led: gpioa::PA10<Output<PushPull>>,
|
||||
disp_cs: gpioa::PA15<Output<PushPull>>,
|
||||
disp: ST7735<Spi<SPI1>, gpio::Pin<'A', 12, Output>, gpio::Pin<'A', 11, Output>>,
|
||||
|
@ -198,17 +214,47 @@ mod app {
|
|||
.memory_increment(true)
|
||||
.double_buffer(false);
|
||||
|
||||
let mut transfer =
|
||||
let mut adc_transfer =
|
||||
Transfer::init_peripheral_to_memory(dma2.0, adc1, iq_buff1, None, config);
|
||||
|
||||
transfer.start(|_| {});
|
||||
adc_transfer.start(|_| {});
|
||||
|
||||
defmt::info!("DMA Setup done");
|
||||
defmt::info!("ADC DMA Setup done");
|
||||
|
||||
let ccr3_tim4: CCR3<TIM4> = unsafe { mem::transmute_copy(&cx.device.TIM4) };
|
||||
|
||||
let audio_out = Channel3::new(gpiob.pb8);
|
||||
let mut audio_pwm = cx.device.TIM4.pwm_hz(audio_out, 192.kHz(), &clocks);
|
||||
let mut audio_pwm = cx.device.TIM4.pwm_hz(audio_out, 8.kHz(), &clocks);
|
||||
audio_pwm.enable(Channel::C3);
|
||||
audio_pwm.set_duty(Channel::C3, 0u16);
|
||||
audio_pwm.set_duty(Channel::C3, audio_pwm.get_max_duty() / 2);
|
||||
let audio_max_duty = audio_pwm.get_max_duty();
|
||||
|
||||
defmt::info!("Max duty: {}", audio_pwm.get_max_duty());
|
||||
|
||||
unsafe {
|
||||
(*TIM4::ptr()).dier.modify(|_, w| {
|
||||
w.tde().set_bit(); // enable DMA trigger
|
||||
w.cc3de().set_bit(); // dma on Update
|
||||
w
|
||||
});
|
||||
};
|
||||
|
||||
let audio_buff1 = singleton!(: [u16; 256] = [100; 256]).unwrap();
|
||||
let audio_buff2 = singleton!(: [u16; 256] = [100; 256]).unwrap();
|
||||
|
||||
let dma1 = StreamsTuple::new(cx.device.DMA1);
|
||||
|
||||
let config = DmaConfig::default()
|
||||
.transfer_complete_interrupt(true)
|
||||
.memory_increment(true)
|
||||
.double_buffer(false);
|
||||
|
||||
let mut pwm_transfer =
|
||||
Transfer::init_memory_to_peripheral(dma1.7, ccr3_tim4, audio_buff1, None, config);
|
||||
|
||||
pwm_transfer.start(|_| {});
|
||||
|
||||
defmt::info!("PWM DMA Setup done");
|
||||
|
||||
let mut rx_en = gpioa.pa7.into_push_pull_output();
|
||||
rx_en.set_high();
|
||||
|
@ -226,14 +272,18 @@ mod app {
|
|||
//mic_in,
|
||||
i_in,
|
||||
q_in,
|
||||
phase: 0.0,
|
||||
i_offset: 2048.0,
|
||||
q_offset: 2048.0,
|
||||
audio_pwm,
|
||||
usb_filter: filters::usb_firfilter(),
|
||||
transfer,
|
||||
adc_transfer,
|
||||
iq_buffer: Some(iq_buff2),
|
||||
|
||||
pwm_transfer,
|
||||
audio_buffer: Some(audio_buff2),
|
||||
phase: 0.0,
|
||||
audio_max_duty,
|
||||
|
||||
disp_led,
|
||||
disp_cs,
|
||||
disp,
|
||||
|
@ -246,7 +296,7 @@ mod app {
|
|||
#[task(priority = 0, local = [disp, col_pos, max_mag])]
|
||||
async fn update_display(cx: update_display::Context, col: [Complex<f32>; 128]) {
|
||||
for samp in col {
|
||||
let mag = (samp.re.pow(2) + samp.im.pow(2)) as f32;
|
||||
let mag = (samp.re.pow(2) + samp.im.pow(2)) / 5.0 as f32;
|
||||
*cx.local.max_mag = if mag > *cx.local.max_mag {
|
||||
mag
|
||||
} else {
|
||||
|
@ -274,15 +324,15 @@ mod app {
|
|||
defmt::info!("Position is {}", cx.local.col_pos);
|
||||
}
|
||||
|
||||
#[task(binds = DMA2_STREAM0, local = [transfer, iq_buffer, board_led, i_offset, q_offset, usb_filter])]
|
||||
#[task(binds = DMA2_STREAM0, local = [adc_transfer, iq_buffer, board_led, i_offset, q_offset, usb_filter])]
|
||||
fn dma2_stream0(cx: dma2_stream0::Context) {
|
||||
let (buffer, _) = cx
|
||||
.local
|
||||
.transfer
|
||||
.adc_transfer
|
||||
.next_transfer(cx.local.iq_buffer.take().unwrap())
|
||||
.unwrap();
|
||||
|
||||
defmt::info!("Transfer complete");
|
||||
defmt::info!("ADC transfer complete");
|
||||
cx.local.board_led.toggle();
|
||||
|
||||
let mut samples = [Complex::<f32>::default(); 128];
|
||||
|
@ -296,13 +346,14 @@ mod app {
|
|||
let i_sample = (i_raw as f32) - *cx.local.i_offset;
|
||||
let q_sample = (q_raw as f32) - *cx.local.q_offset;
|
||||
|
||||
samples[idx] = Complex::new(i_sample as f32 / 4096.0, q_sample as f32 / 4096.0);
|
||||
samples[idx] = Complex::new(q_sample as f32 / 4096.0, i_sample as f32 / 4096.0);
|
||||
}
|
||||
|
||||
let mut fft_input = [Complex::<f32>::default(); 128];
|
||||
|
||||
for idx in 0..samples.len() / 2 {
|
||||
let _filtered = cx.local.usb_filter.compute(samples[idx]);
|
||||
fft_input[idx] = samples[idx];
|
||||
let filtered = cx.local.usb_filter.compute(samples[idx]);
|
||||
fft_input[idx] = filtered;
|
||||
}
|
||||
|
||||
let spectrum = cfft_128(&mut fft_input);
|
||||
|
@ -311,4 +362,29 @@ mod app {
|
|||
|
||||
*cx.local.iq_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
#[task(binds = DMA1_STREAM7, local = [pwm_transfer, audio_buffer, phase, audio_max_duty])]
|
||||
fn dma1_stream7(cx: dma1_stream7::Context) {
|
||||
let (mut buffer, _) = cx
|
||||
.local
|
||||
.pwm_transfer
|
||||
.next_transfer(cx.local.audio_buffer.take().unwrap())
|
||||
.unwrap();
|
||||
|
||||
defmt::info!("PWM transfer complete");
|
||||
|
||||
let phase_inc = core::f32::consts::PI * 2.0 / 8000.0 * 440.0;
|
||||
|
||||
for i in 0..buffer.len() {
|
||||
*cx.local.phase += phase_inc;
|
||||
if *cx.local.phase > 2.0 * core::f32::consts::PI {
|
||||
*cx.local.phase -= 2.0 * core::f32::consts::PI;
|
||||
}
|
||||
|
||||
buffer[i] =
|
||||
((cx.local.phase.sin() + 1.0) * (*cx.local.audio_max_duty as f32) / 4.0) as u16;
|
||||
}
|
||||
|
||||
*cx.local.audio_buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue