From 0abcccee966af0b12e62fc7fae8499fa03194823 Mon Sep 17 00:00:00 2001 From: eZio Pan Date: Fri, 22 Mar 2024 17:29:10 +0800 Subject: stm32 CORDIC: re-design API --- examples/stm32h5/src/bin/cordic.rs | 59 ++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 8 deletions(-) (limited to 'examples') diff --git a/examples/stm32h5/src/bin/cordic.rs b/examples/stm32h5/src/bin/cordic.rs index d49f75b8f..73e873574 100644 --- a/examples/stm32h5/src/bin/cordic.rs +++ b/examples/stm32h5/src/bin/cordic.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::cordic; +use embassy_stm32::cordic::{self, utils}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -16,20 +16,63 @@ async fn main(_spawner: Spawner) { cordic::Function::Sin, Default::default(), Default::default(), - false, )), ); - let mut output = [0f64; 16]; + // for output buf, the length is not that strict, larger than minimal required is ok. + let mut output_f64 = [0f64; 19]; + let mut output_u32 = [0u32; 21]; - let arg1 = [1.0, 0.0, -1.0]; // for trigonometric function, the ARG1 value [-pi, pi] should be map to [-1, 1] - let arg2 = [0.5, 1.0]; + // tips: + // CORDIC peripheral has some strict on input value, you can also use ".check_argX_fXX()" methods + // to make sure your input values are compatible with current CORDIC setup. + let arg1 = [-1.0, -0.5, 0.0, 0.5, 1.0]; // for trigonometric function, the ARG1 value [-pi, pi] should be map to [-1, 1] + let arg2 = [0.5]; // and for Sin function, ARG2 should be in [0, 1] - let cnt = unwrap!( + let mut input_buf = [0u32; 9]; + + // convert input from floating point to fixed point + input_buf[0] = unwrap!(utils::f64_to_q1_31(arg1[0])); + input_buf[1] = unwrap!(utils::f64_to_q1_31(arg2[0])); + + // If input length is small, blocking mode can be used to minimize overhead. + let cnt0 = unwrap!(cordic.blocking_calc_32bit( + &input_buf[..2], // input length is strict, since driver use its length to detect calculation count + &mut output_u32, + false, + false + )); + + // convert result from fixed point into floating point + for (&u32_val, f64_val) in output_u32[..cnt0].iter().zip(output_f64.iter_mut()) { + *f64_val = utils::q1_31_to_f64(u32_val); + } + + // convert input from floating point to fixed point + // + // first value from arg1 is used, so truncate to arg1[1..] + for (&f64_val, u32_val) in arg1[1..].iter().zip(input_buf.iter_mut()) { + *u32_val = unwrap!(utils::f64_to_q1_31(f64_val)); + } + + // If calculation is a little longer, async mode can make use of DMA, and let core do some other stuff. + let cnt1 = unwrap!( cordic - .async_calc_32bit(&mut dp.GPDMA1_CH0, &mut dp.GPDMA1_CH1, &arg1, Some(&arg2), &mut output,) + .async_calc_32bit( + &mut dp.GPDMA1_CH0, + &mut dp.GPDMA1_CH1, + &input_buf[..arg1.len() - 1], // limit input buf to its actual length + &mut output_u32, + true, + false + ) .await ); - println!("async calc 32bit: {}", output[..cnt]); + // convert result from fixed point into floating point + for (&u32_val, f64_val) in output_u32[..cnt1].iter().zip(output_f64[cnt0..cnt0 + cnt1].iter_mut()) { + *f64_val = utils::q1_31_to_f64(u32_val); + } + + println!("result: {}", output_f64[..cnt0 + cnt1]); } -- cgit