aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32h5/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-04 21:32:27 +0000
committerGitHub <[email protected]>2024-04-04 21:32:27 +0000
commit6c35a1769d9bce27805ed6dcbb09d1306be6e452 (patch)
tree3fba5b2ae92677744f7da246ecd4bd96fa2d48f7 /examples/stm32h5/src
parent067e422863674762c0ee20178f3671ce16a5986c (diff)
parent6b2e15e318c05a66f17575cde4987353a52108a4 (diff)
Merge pull request #2697 from eZioPan/stm32-cordic
stm32 CORDIC driver
Diffstat (limited to 'examples/stm32h5/src')
-rw-r--r--examples/stm32h5/src/bin/cordic.rs78
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
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::cordic::{self, utils};
7use {defmt_rtt as _, panic_probe as _};
8
9#[embassy_executor::main]
10async 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}