aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorChristian Perez Llamas <[email protected]>2022-11-12 18:48:57 +0100
committerChristian Perez Llamas <[email protected]>2022-11-12 18:48:57 +0100
commit122a31d20877005c7201d4e7c98da5544666dd1d (patch)
treec97037ba880f63a4e03e642c6630efb1042a3cde /examples
parent10e3c3f2ec358da6d81f2bb9c05936c2ab6da567 (diff)
Interrupts, async, sine oscillator
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf/src/bin/i2s.rs132
1 files changed, 111 insertions, 21 deletions
diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs
index e8ddb4a40..53ccb3b85 100644
--- a/examples/nrf/src/bin/i2s.rs
+++ b/examples/nrf/src/bin/i2s.rs
@@ -4,43 +4,133 @@
4#![no_main] 4#![no_main]
5#![feature(type_alias_impl_trait)] 5#![feature(type_alias_impl_trait)]
6 6
7//use defmt::*; 7use core::f32::consts::PI;
8
9use defmt::{error, info};
8use embassy_executor::Spawner; 10use embassy_executor::Spawner;
9use embassy_nrf::i2s; 11use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000};
12use embassy_nrf::{i2s, interrupt};
10use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
11 14
12#[repr(align(4))] 15#[repr(align(4))]
13pub struct Aligned<T: ?Sized>(T); 16pub struct AlignedBuffer<T: ?Sized>(T);
17
18impl<T> AsRef<T> for AlignedBuffer<T> {
19 fn as_ref(&self) -> &T {
20 &self.0
21 }
22}
23
24impl<T> AsMut<T> for AlignedBuffer<T> {
25 fn as_mut(&mut self) -> &mut T {
26 &mut self.0
27 }
28}
14 29
15#[embassy_executor::main] 30#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 31async fn main(_spawner: Spawner) {
17 let p = embassy_nrf::init(Default::default()); 32 let p = embassy_nrf::init(Default::default());
18 let config = i2s::Config::default(); 33 let mut config = i2s::Config::default();
34 // config.mode = MODE_MASTER_16000;
35 config.mode = Mode::Master {
36 freq: MckFreq::_32MDiv10,
37 ratio: Ratio::_256x,
38 }; // 12500 Hz
39 let sample_rate = config.mode.sample_rate().expect("I2S Master");
40 let inv_sample_rate = 1.0 / sample_rate as f32;
19 41
20 let mut i2s = i2s::I2S::new(p.I2S, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config); 42 info!("Sample rate: {}", sample_rate);
21 43
22 let mut signal_buf: Aligned<[i16; 32]> = Aligned([0i16; 32]); 44 let irq = interrupt::take!(I2S);
23 let len = signal_buf.0.len() / 2; 45 let mut i2s = i2s::I2S::new(p.I2S, irq, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config);
24 for x in 0..len { 46
25 signal_buf.0[2 * x] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; 47 const BUF_SAMPLES: usize = 250;
26 signal_buf.0[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; 48 const BUF_SIZE: usize = BUF_SAMPLES * 2;
27 } 49 let mut buf = AlignedBuffer([0i16; BUF_SIZE]);
50
51 let mut carrier = SineOsc::new();
52 carrier.set_frequency(300.0, inv_sample_rate);
53
54 let mut modulator = SineOsc::new();
55 modulator.set_frequency(0.01, inv_sample_rate);
56 modulator.set_amplitude(0.2);
28 57
29 i2s.set_tx_enabled(true); 58 i2s.set_tx_enabled(true);
30 i2s.start(); 59 i2s.start();
31 60
32 loop { 61 loop {
33 match i2s.tx(signal_buf.0.as_slice()).await { 62 for sample in buf.as_mut().chunks_mut(2) {
34 Ok(_) => todo!(), 63 let signal = carrier.generate();
35 Err(_) => todo!(), 64 // let modulation = bipolar_to_unipolar(modulator.generate());
36 }; 65 // carrier.set_frequency(200.0 + 100.0 * modulation, inv_sample_rate);
66 // carrier.set_amplitude((modulation);
67 let value = (i16::MAX as f32 * signal) as i16;
68 sample[0] = value;
69 sample[1] = value;
70 // info!("{}", signal);
71 }
72
73 if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await {
74 error!("{}", err);
75 }
76 }
77}
78
79struct SineOsc {
80 amplitude: f32,
81 modulo: f32,
82 phase_inc: f32,
83}
84
85impl SineOsc {
86 const B: f32 = 4.0 / PI;
87 const C: f32 = -4.0 / (PI * PI);
88 const P: f32 = 0.225;
89
90 pub fn new() -> Self {
91 Self {
92 amplitude: 1.0,
93 modulo: 0.0,
94 phase_inc: 0.0,
95 }
96 }
97
98 pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) {
99 self.phase_inc = freq * inv_sample_rate;
100 }
101
102 pub fn set_amplitude(&mut self, amplitude: f32) {
103 self.amplitude = amplitude;
104 }
105
106 pub fn generate(&mut self) -> f32 {
107 let signal = self.parabolic_sin(self.modulo);
108 self.modulo += self.phase_inc;
109 if self.modulo < 0.0 {
110 self.modulo += 1.0;
111 } else if self.modulo > 1.0 {
112 self.modulo -= 1.0;
113 }
114 signal * self.amplitude
115 }
116
117 fn parabolic_sin(&mut self, modulo: f32) -> f32 {
118 let angle = PI - modulo * 2.0 * PI;
119 let y = Self::B * angle + Self::C * angle * abs(angle);
120 Self::P * (y * abs(y) - y) + y
121 }
122}
123
124#[inline]
125fn abs(value: f32) -> f32 {
126 if value < 0.0 {
127 -value
128 } else {
129 value
37 } 130 }
38} 131}
39 132
40fn triangle_wave(x: i32, length: usize, amplitude: i32, phase: i32, periods: i32) -> i32 { 133#[inline]
41 let length = length as i32; 134fn bipolar_to_unipolar(value: f32) -> f32 {
42 amplitude 135 (value + 1.0) / 2.0
43 - ((2 * periods * (x + phase + length / (4 * periods)) * amplitude / length) % (2 * amplitude) - amplitude)
44 .abs()
45 - amplitude / 2
46} 136}