diff options
| author | Christian Perez Llamas <[email protected]> | 2022-11-19 19:18:20 +0100 |
|---|---|---|
| committer | Christian Perez Llamas <[email protected]> | 2022-11-19 19:18:20 +0100 |
| commit | 15a93246d6bb3e0bea268ff919bca073a9890247 (patch) | |
| tree | b7ac9969e2ec491cf1d200ba9f2239ecedd6f2f5 /examples | |
| parent | f5391efe22374e0c55005f20c6a644bda3acd50c (diff) | |
Buffer management in line with other peripherals. Constructor and config redesign
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/nrf/src/bin/i2s_waveform.rs (renamed from examples/nrf/src/bin/i2s-generate.rs) | 103 |
1 files changed, 61 insertions, 42 deletions
diff --git a/examples/nrf/src/bin/i2s-generate.rs b/examples/nrf/src/bin/i2s_waveform.rs index c2b5578f3..81858ff59 100644 --- a/examples/nrf/src/bin/i2s-generate.rs +++ b/examples/nrf/src/bin/i2s_waveform.rs | |||
| @@ -6,33 +6,29 @@ use core::f32::consts::PI; | |||
| 6 | 6 | ||
| 7 | use defmt::{error, info}; | 7 | use defmt::{error, info}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_nrf::i2s::{self, Sample as _}; | 9 | use embassy_nrf::i2s::{self, Channels, Config, MasterClock, Sample as _, SampleWidth, I2S}; |
| 10 | use embassy_nrf::interrupt; | 10 | use embassy_nrf::interrupt; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 12 | ||
| 13 | type Sample = i16; | ||
| 14 | |||
| 15 | const NUM_SAMPLES: usize = 6000; | ||
| 16 | |||
| 13 | #[embassy_executor::main] | 17 | #[embassy_executor::main] |
| 14 | async fn main(_spawner: Spawner) { | 18 | async fn main(_spawner: Spawner) { |
| 15 | let p = embassy_nrf::init(Default::default()); | 19 | let p = embassy_nrf::init(Default::default()); |
| 16 | 20 | ||
| 17 | let mut config = i2s::Config::default(); | 21 | let master_clock: MasterClock = i2s::ExactSampleRate::_50000.into(); |
| 18 | config.mode = i2s::ExactSampleRate::_50000.into(); | ||
| 19 | config.channels = i2s::Channels::Left; | ||
| 20 | config.swidth = i2s::SampleWidth::_16bit; | ||
| 21 | let sample_rate = config.mode.sample_rate().expect("I2S Master"); | ||
| 22 | let inv_sample_rate = 1.0 / sample_rate as f32; | ||
| 23 | 22 | ||
| 23 | let sample_rate = master_clock.sample_rate(); | ||
| 24 | info!("Sample rate: {}", sample_rate); | 24 | info!("Sample rate: {}", sample_rate); |
| 25 | 25 | ||
| 26 | // Wait for a button press | 26 | let config = Config::default() |
| 27 | // use embassy_nrf::gpio::{Input, Pin, Pull}; | 27 | .sample_width(SampleWidth::_16bit) |
| 28 | // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up); | 28 | .channels(Channels::MonoLeft); |
| 29 | // btn1.wait_for_low().await; | ||
| 30 | 29 | ||
| 31 | let irq = interrupt::take!(I2S); | 30 | let irq = interrupt::take!(I2S); |
| 32 | let mut i2s = i2s::I2S::new(p.I2S, irq, p.P0_28, p.P0_29, p.P0_31, p.P0_27, p.P0_30, config).output(); | 31 | let mut output_stream = I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).output(p.P0_28); |
| 33 | |||
| 34 | type Sample = i16; | ||
| 35 | const NUM_SAMPLES: usize = 6000; | ||
| 36 | 32 | ||
| 37 | let mut buffers: [i2s::AlignedBuffer<Sample, NUM_SAMPLES>; 3] = [ | 33 | let mut buffers: [i2s::AlignedBuffer<Sample, NUM_SAMPLES>; 3] = [ |
| 38 | i2s::AlignedBuffer::default(), | 34 | i2s::AlignedBuffer::default(), |
| @@ -40,36 +36,16 @@ async fn main(_spawner: Spawner) { | |||
| 40 | i2s::AlignedBuffer::default(), | 36 | i2s::AlignedBuffer::default(), |
| 41 | ]; | 37 | ]; |
| 42 | 38 | ||
| 43 | let mut carrier = SineOsc::new(); | 39 | let mut waveform = Waveform::new(1.0 / sample_rate as f32); |
| 44 | |||
| 45 | let mut freq_mod = SineOsc::new(); | ||
| 46 | freq_mod.set_frequency(8.0, inv_sample_rate); | ||
| 47 | freq_mod.set_amplitude(1.0); | ||
| 48 | |||
| 49 | let mut amp_mod = SineOsc::new(); | ||
| 50 | amp_mod.set_frequency(16.0, inv_sample_rate); | ||
| 51 | amp_mod.set_amplitude(0.5); | ||
| 52 | |||
| 53 | let mut generate = |buf: &mut [Sample]| { | ||
| 54 | for sample in &mut buf.chunks_mut(1) { | ||
| 55 | let freq_modulation = bipolar_to_unipolar(freq_mod.generate()); | ||
| 56 | carrier.set_frequency(220.0 + 440.0 * freq_modulation, inv_sample_rate); | ||
| 57 | let amp_modulation = bipolar_to_unipolar(amp_mod.generate()); | ||
| 58 | carrier.set_amplitude(amp_modulation); | ||
| 59 | let signal = carrier.generate(); | ||
| 60 | let value = (Sample::SCALE as f32 * signal) as Sample; | ||
| 61 | sample[0] = value; | ||
| 62 | } | ||
| 63 | }; | ||
| 64 | 40 | ||
| 65 | generate(buffers[0].as_mut()); | 41 | waveform.process(&mut buffers[0]); |
| 66 | generate(buffers[1].as_mut()); | 42 | waveform.process(&mut buffers[1]); |
| 67 | 43 | ||
| 68 | i2s.start(buffers[0].as_ref()).await.expect("I2S Start"); | 44 | output_stream.start(&buffers[0]).await.expect("I2S Start"); |
| 69 | 45 | ||
| 70 | let mut index = 1; | 46 | let mut index = 1; |
| 71 | loop { | 47 | loop { |
| 72 | if let Err(err) = i2s.send(buffers[index].as_ref()).await { | 48 | if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { |
| 73 | error!("{}", err); | 49 | error!("{}", err); |
| 74 | } | 50 | } |
| 75 | 51 | ||
| @@ -77,11 +53,54 @@ async fn main(_spawner: Spawner) { | |||
| 77 | if index >= 3 { | 53 | if index >= 3 { |
| 78 | index = 0; | 54 | index = 0; |
| 79 | } | 55 | } |
| 80 | generate(buffers[index].as_mut()); | 56 | |
| 57 | waveform.process(&mut buffers[index]); | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | struct Waveform { | ||
| 62 | inv_sample_rate: f32, | ||
| 63 | carrier: SineOsc, | ||
| 64 | freq_mod: SineOsc, | ||
| 65 | amp_mod: SineOsc, | ||
| 66 | } | ||
| 67 | |||
| 68 | impl Waveform { | ||
| 69 | fn new(inv_sample_rate: f32) -> Self { | ||
| 70 | let carrier = SineOsc::new(); | ||
| 71 | |||
| 72 | let mut freq_mod = SineOsc::new(); | ||
| 73 | freq_mod.set_frequency(8.0, inv_sample_rate); | ||
| 74 | freq_mod.set_amplitude(1.0); | ||
| 75 | |||
| 76 | let mut amp_mod = SineOsc::new(); | ||
| 77 | amp_mod.set_frequency(16.0, inv_sample_rate); | ||
| 78 | amp_mod.set_amplitude(0.5); | ||
| 79 | |||
| 80 | Self { | ||
| 81 | inv_sample_rate, | ||
| 82 | carrier, | ||
| 83 | freq_mod, | ||
| 84 | amp_mod, | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | fn process(&mut self, buf: &mut [Sample]) { | ||
| 89 | for sample in buf.chunks_mut(1) { | ||
| 90 | let freq_modulation = bipolar_to_unipolar(self.freq_mod.generate()); | ||
| 91 | self.carrier | ||
| 92 | .set_frequency(110.0 + 440.0 * freq_modulation, self.inv_sample_rate); | ||
| 93 | |||
| 94 | let amp_modulation = bipolar_to_unipolar(self.amp_mod.generate()); | ||
| 95 | self.carrier.set_amplitude(amp_modulation); | ||
| 96 | |||
| 97 | let signal = self.carrier.generate(); | ||
| 98 | |||
| 99 | sample[0] = (Sample::SCALE as f32 * signal) as Sample; | ||
| 100 | } | ||
| 81 | } | 101 | } |
| 82 | } | 102 | } |
| 83 | 103 | ||
| 84 | #[derive(Clone)] | ||
| 85 | struct SineOsc { | 104 | struct SineOsc { |
| 86 | amplitude: f32, | 105 | amplitude: f32, |
| 87 | modulo: f32, | 106 | modulo: f32, |
