diff options
Diffstat (limited to 'examples/stm32h5/src')
| -rw-r--r-- | examples/stm32h5/src/bin/cordic.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/examples/stm32h5/src/bin/cordic.rs b/examples/stm32h5/src/bin/cordic.rs new file mode 100644 index 000000000..73e873574 --- /dev/null +++ b/examples/stm32h5/src/bin/cordic.rs | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::cordic::{self, utils}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let mut dp = embassy_stm32::init(Default::default()); | ||
| 12 | |||
| 13 | let mut cordic = cordic::Cordic::new( | ||
| 14 | &mut dp.CORDIC, | ||
| 15 | unwrap!(cordic::Config::new( | ||
| 16 | cordic::Function::Sin, | ||
| 17 | Default::default(), | ||
| 18 | Default::default(), | ||
| 19 | )), | ||
| 20 | ); | ||
| 21 | |||
| 22 | // for output buf, the length is not that strict, larger than minimal required is ok. | ||
| 23 | let mut output_f64 = [0f64; 19]; | ||
| 24 | let mut output_u32 = [0u32; 21]; | ||
| 25 | |||
| 26 | // tips: | ||
| 27 | // CORDIC peripheral has some strict on input value, you can also use ".check_argX_fXX()" methods | ||
| 28 | // to make sure your input values are compatible with current CORDIC setup. | ||
| 29 | 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] | ||
| 30 | let arg2 = [0.5]; // and for Sin function, ARG2 should be in [0, 1] | ||
| 31 | |||
| 32 | let mut input_buf = [0u32; 9]; | ||
| 33 | |||
| 34 | // convert input from floating point to fixed point | ||
| 35 | input_buf[0] = unwrap!(utils::f64_to_q1_31(arg1[0])); | ||
| 36 | input_buf[1] = unwrap!(utils::f64_to_q1_31(arg2[0])); | ||
| 37 | |||
| 38 | // If input length is small, blocking mode can be used to minimize overhead. | ||
| 39 | let cnt0 = unwrap!(cordic.blocking_calc_32bit( | ||
| 40 | &input_buf[..2], // input length is strict, since driver use its length to detect calculation count | ||
| 41 | &mut output_u32, | ||
| 42 | false, | ||
| 43 | false | ||
| 44 | )); | ||
| 45 | |||
| 46 | // convert result from fixed point into floating point | ||
| 47 | for (&u32_val, f64_val) in output_u32[..cnt0].iter().zip(output_f64.iter_mut()) { | ||
| 48 | *f64_val = utils::q1_31_to_f64(u32_val); | ||
| 49 | } | ||
| 50 | |||
| 51 | // convert input from floating point to fixed point | ||
| 52 | // | ||
| 53 | // first value from arg1 is used, so truncate to arg1[1..] | ||
| 54 | for (&f64_val, u32_val) in arg1[1..].iter().zip(input_buf.iter_mut()) { | ||
| 55 | *u32_val = unwrap!(utils::f64_to_q1_31(f64_val)); | ||
| 56 | } | ||
| 57 | |||
| 58 | // If calculation is a little longer, async mode can make use of DMA, and let core do some other stuff. | ||
| 59 | let cnt1 = unwrap!( | ||
| 60 | cordic | ||
| 61 | .async_calc_32bit( | ||
| 62 | &mut dp.GPDMA1_CH0, | ||
| 63 | &mut dp.GPDMA1_CH1, | ||
| 64 | &input_buf[..arg1.len() - 1], // limit input buf to its actual length | ||
| 65 | &mut output_u32, | ||
| 66 | true, | ||
| 67 | false | ||
| 68 | ) | ||
| 69 | .await | ||
| 70 | ); | ||
| 71 | |||
| 72 | // convert result from fixed point into floating point | ||
| 73 | for (&u32_val, f64_val) in output_u32[..cnt1].iter().zip(output_f64[cnt0..cnt0 + cnt1].iter_mut()) { | ||
| 74 | *f64_val = utils::q1_31_to_f64(u32_val); | ||
| 75 | } | ||
| 76 | |||
| 77 | println!("result: {}", output_f64[..cnt0 + cnt1]); | ||
| 78 | } | ||
