aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/i2s.rs715
-rw-r--r--examples/nrf/src/bin/i2s_waveform.rs (renamed from examples/nrf/src/bin/i2s-generate.rs)103
2 files changed, 392 insertions, 426 deletions
diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs
index 11c09a229..d5815160a 100644
--- a/embassy-nrf/src/i2s.rs
+++ b/embassy-nrf/src/i2s.rs
@@ -4,6 +4,8 @@
4 4
5use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData; 6use core::marker::PhantomData;
7use core::mem::size_of;
8use core::ops::{Deref, DerefMut};
7use core::sync::atomic::{compiler_fence, Ordering}; 9use core::sync::atomic::{compiler_fence, Ordering};
8use core::task::Poll; 10use core::task::Poll;
9 11
@@ -14,14 +16,9 @@ use embassy_hal_common::{into_ref, PeripheralRef};
14use crate::gpio::{AnyPin, Pin as GpioPin}; 16use crate::gpio::{AnyPin, Pin as GpioPin};
15use crate::interrupt::Interrupt; 17use crate::interrupt::Interrupt;
16use crate::pac::i2s::RegisterBlock; 18use crate::pac::i2s::RegisterBlock;
19use crate::util::{slice_in_ram_or, slice_ptr_parts};
17use crate::{Peripheral, EASY_DMA_SIZE}; 20use crate::{Peripheral, EASY_DMA_SIZE};
18 21
19// TODO: Define those in lib.rs somewhere else
20
21/// Limits for Easy DMA - it can only read from data ram
22pub const SRAM_LOWER: usize = 0x2000_0000;
23pub const SRAM_UPPER: usize = 0x3000_0000;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)] 22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))] 23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27#[non_exhaustive] 24#[non_exhaustive]
@@ -33,159 +30,42 @@ pub enum Error {
33 BufferLengthMisaligned, 30 BufferLengthMisaligned,
34} 31}
35 32
36/// Approximate sample rates. 33/// I2S configuration.
37/// 34#[derive(Clone)]
38/// Those are common sample rates that can not be configured without an small error. 35#[non_exhaustive]
39/// 36pub struct Config {
40/// For custom master clock configuration, please refer to [Mode]. 37 pub sample_width: SampleWidth,
41#[derive(Clone, Copy)] 38 pub align: Align,
42pub enum ApproxSampleRate { 39 pub format: Format,
43 _11025, 40 pub channels: Channels,
44 _16000,
45 _22050,
46 _32000,
47 _44100,
48 _48000,
49} 41}
50 42
51impl From<ApproxSampleRate> for Mode { 43impl Config {
52 fn from(value: ApproxSampleRate) -> Self { 44 pub fn sample_width(mut self, sample_width: SampleWidth) -> Self {
53 match value { 45 self.sample_width = sample_width;
54 // error = 86 46 self
55 ApproxSampleRate::_11025 => Mode::Master {
56 freq: MckFreq::_32MDiv15,
57 ratio: Ratio::_192x,
58 },
59 // error = 127
60 ApproxSampleRate::_16000 => Mode::Master {
61 freq: MckFreq::_32MDiv21,
62 ratio: Ratio::_96x,
63 },
64 // error = 172
65 ApproxSampleRate::_22050 => Mode::Master {
66 freq: MckFreq::_32MDiv15,
67 ratio: Ratio::_96x,
68 },
69 // error = 254
70 ApproxSampleRate::_32000 => Mode::Master {
71 freq: MckFreq::_32MDiv21,
72 ratio: Ratio::_48x,
73 },
74 // error = 344
75 ApproxSampleRate::_44100 => Mode::Master {
76 freq: MckFreq::_32MDiv15,
77 ratio: Ratio::_48x,
78 },
79 // error = 381
80 ApproxSampleRate::_48000 => Mode::Master {
81 freq: MckFreq::_32MDiv21,
82 ratio: Ratio::_32x,
83 },
84 }
85 } 47 }
86}
87 48
88impl ApproxSampleRate { 49 pub fn align(mut self, align: Align) -> Self {
89 pub fn sample_rate(&self) -> u32 { 50 self.align = align;
90 // This will always provide a Master mode, so it is safe to unwrap. 51 self
91 Mode::from(*self).sample_rate().unwrap()
92 } 52 }
93}
94 53
95/// Exact sample rates. 54 pub fn format(mut self, format: Format) -> Self {
96/// 55 self.format = format;
97/// Those are non standard sample rates that can be configured without error. 56 self
98///
99/// For custom master clock configuration, please refer to [Mode].
100#[derive(Clone, Copy)]
101pub enum ExactSampleRate {
102 _8000,
103 _10582,
104 _12500,
105 _15625,
106 _15873,
107 _25000,
108 _31250,
109 _50000,
110 _62500,
111 _100000,
112 _125000,
113}
114
115impl ExactSampleRate {
116 pub fn sample_rate(&self) -> u32 {
117 // This will always provide a Master mode, so it is safe to unwrap.
118 Mode::from(*self).sample_rate().unwrap()
119 } 57 }
120}
121 58
122impl From<ExactSampleRate> for Mode { 59 pub fn channels(mut self, channels: Channels) -> Self {
123 fn from(value: ExactSampleRate) -> Self { 60 self.channels = channels;
124 match value { 61 self
125 ExactSampleRate::_8000 => Mode::Master {
126 freq: MckFreq::_32MDiv125,
127 ratio: Ratio::_32x,
128 },
129 ExactSampleRate::_10582 => Mode::Master {
130 freq: MckFreq::_32MDiv63,
131 ratio: Ratio::_48x,
132 },
133 ExactSampleRate::_12500 => Mode::Master {
134 freq: MckFreq::_32MDiv10,
135 ratio: Ratio::_256x,
136 },
137 ExactSampleRate::_15625 => Mode::Master {
138 freq: MckFreq::_32MDiv32,
139 ratio: Ratio::_64x,
140 },
141 ExactSampleRate::_15873 => Mode::Master {
142 freq: MckFreq::_32MDiv63,
143 ratio: Ratio::_32x,
144 },
145 ExactSampleRate::_25000 => Mode::Master {
146 freq: MckFreq::_32MDiv10,
147 ratio: Ratio::_128x,
148 },
149 ExactSampleRate::_31250 => Mode::Master {
150 freq: MckFreq::_32MDiv32,
151 ratio: Ratio::_32x,
152 },
153 ExactSampleRate::_50000 => Mode::Master {
154 freq: MckFreq::_32MDiv10,
155 ratio: Ratio::_64x,
156 },
157 ExactSampleRate::_62500 => Mode::Master {
158 freq: MckFreq::_32MDiv16,
159 ratio: Ratio::_32x,
160 },
161 ExactSampleRate::_100000 => Mode::Master {
162 freq: MckFreq::_32MDiv10,
163 ratio: Ratio::_32x,
164 },
165 ExactSampleRate::_125000 => Mode::Master {
166 freq: MckFreq::_32MDiv8,
167 ratio: Ratio::_32x,
168 },
169 }
170 } 62 }
171} 63}
172 64
173/// I2S configuration.
174#[derive(Clone)]
175#[non_exhaustive]
176pub struct Config {
177 pub mode: Mode,
178 pub swidth: SampleWidth,
179 pub align: Align,
180 pub format: Format,
181 pub channels: Channels,
182}
183
184impl Default for Config { 65impl Default for Config {
185 fn default() -> Self { 66 fn default() -> Self {
186 Self { 67 Self {
187 mode: ExactSampleRate::_31250.into(), 68 sample_width: SampleWidth::_16bit,
188 swidth: SampleWidth::_16bit,
189 align: Align::Left, 69 align: Align::Left,
190 format: Format::I2S, 70 format: Format::I2S,
191 channels: Channels::Stereo, 71 channels: Channels::Stereo,
@@ -195,17 +75,20 @@ impl Default for Config {
195 75
196/// I2S Mode 76/// I2S Mode
197#[derive(Debug, Eq, PartialEq, Clone, Copy)] 77#[derive(Debug, Eq, PartialEq, Clone, Copy)]
198pub enum Mode { 78pub struct MasterClock {
199 Master { freq: MckFreq, ratio: Ratio }, 79 freq: MckFreq,
200 Slave, 80 ratio: Ratio,
201} 81}
202 82
203impl Mode { 83impl MasterClock {
204 pub fn sample_rate(&self) -> Option<u32> { 84 pub fn new(freq: MckFreq, ratio: Ratio) -> Self {
205 match self { 85 Self { freq, ratio }
206 Mode::Master { freq, ratio } => Some(freq.to_frequency() / ratio.to_divisor()), 86 }
207 Mode::Slave => None, 87}
208 } 88
89impl MasterClock {
90 pub fn sample_rate(&self) -> u32 {
91 self.freq.to_frequency() / self.ratio.to_divisor()
209 } 92 }
210} 93}
211 94
@@ -275,17 +158,106 @@ pub enum Ratio {
275impl Ratio { 158impl Ratio {
276 const RATIOS: &'static [u32] = &[32, 48, 64, 96, 128, 192, 256, 384, 512]; 159 const RATIOS: &'static [u32] = &[32, 48, 64, 96, 128, 192, 256, 384, 512];
277 160
161 /// Return the value that needs to be written to the register.
162 pub fn to_register_value(&self) -> u8 {
163 usize::from(*self) as u8
164 }
165
278 pub fn to_divisor(&self) -> u32 { 166 pub fn to_divisor(&self) -> u32 {
279 Self::RATIOS[u8::from(*self) as usize] 167 Self::RATIOS[usize::from(*self)]
280 } 168 }
281} 169}
282 170
283impl From<Ratio> for u8 { 171impl From<Ratio> for usize {
284 fn from(variant: Ratio) -> Self { 172 fn from(variant: Ratio) -> Self {
285 variant as _ 173 variant as _
286 } 174 }
287} 175}
288 176
177/// Approximate sample rates.
178///
179/// Those are common sample rates that can not be configured without an small error.
180///
181/// For custom master clock configuration, please refer to [MasterClock].
182#[derive(Clone, Copy)]
183pub enum ApproxSampleRate {
184 _11025,
185 _16000,
186 _22050,
187 _32000,
188 _44100,
189 _48000,
190}
191
192impl From<ApproxSampleRate> for MasterClock {
193 fn from(value: ApproxSampleRate) -> Self {
194 match value {
195 // error = 86
196 ApproxSampleRate::_11025 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_192x),
197 // error = 127
198 ApproxSampleRate::_16000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_96x),
199 // error = 172
200 ApproxSampleRate::_22050 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_96x),
201 // error = 254
202 ApproxSampleRate::_32000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_48x),
203 // error = 344
204 ApproxSampleRate::_44100 => MasterClock::new(MckFreq::_32MDiv15, Ratio::_48x),
205 // error = 381
206 ApproxSampleRate::_48000 => MasterClock::new(MckFreq::_32MDiv21, Ratio::_32x),
207 }
208 }
209}
210
211impl ApproxSampleRate {
212 pub fn sample_rate(&self) -> u32 {
213 MasterClock::from(*self).sample_rate()
214 }
215}
216
217/// Exact sample rates.
218///
219/// Those are non standard sample rates that can be configured without error.
220///
221/// For custom master clock configuration, please refer to [Mode].
222#[derive(Clone, Copy)]
223pub enum ExactSampleRate {
224 _8000,
225 _10582,
226 _12500,
227 _15625,
228 _15873,
229 _25000,
230 _31250,
231 _50000,
232 _62500,
233 _100000,
234 _125000,
235}
236
237impl ExactSampleRate {
238 pub fn sample_rate(&self) -> u32 {
239 MasterClock::from(*self).sample_rate()
240 }
241}
242
243impl From<ExactSampleRate> for MasterClock {
244 fn from(value: ExactSampleRate) -> Self {
245 match value {
246 ExactSampleRate::_8000 => MasterClock::new(MckFreq::_32MDiv125, Ratio::_32x),
247 ExactSampleRate::_10582 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_48x),
248 ExactSampleRate::_12500 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_256x),
249 ExactSampleRate::_15625 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_64x),
250 ExactSampleRate::_15873 => MasterClock::new(MckFreq::_32MDiv63, Ratio::_32x),
251 ExactSampleRate::_25000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_128x),
252 ExactSampleRate::_31250 => MasterClock::new(MckFreq::_32MDiv32, Ratio::_32x),
253 ExactSampleRate::_50000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_64x),
254 ExactSampleRate::_62500 => MasterClock::new(MckFreq::_32MDiv16, Ratio::_32x),
255 ExactSampleRate::_100000 => MasterClock::new(MckFreq::_32MDiv10, Ratio::_32x),
256 ExactSampleRate::_125000 => MasterClock::new(MckFreq::_32MDiv8, Ratio::_32x),
257 }
258 }
259}
260
289/// Sample width. 261/// Sample width.
290#[derive(Debug, Eq, PartialEq, Clone, Copy)] 262#[derive(Debug, Eq, PartialEq, Clone, Copy)]
291pub enum SampleWidth { 263pub enum SampleWidth {
@@ -336,10 +308,8 @@ impl From<Format> for bool {
336#[derive(Debug, Eq, PartialEq, Clone, Copy)] 308#[derive(Debug, Eq, PartialEq, Clone, Copy)]
337pub enum Channels { 309pub enum Channels {
338 Stereo, 310 Stereo,
339 /// Mono left 311 MonoLeft,
340 Left, 312 MonoRight,
341 /// Mono right
342 Right,
343} 313}
344 314
345impl From<Channels> for u8 { 315impl From<Channels> for u8 {
@@ -350,131 +320,160 @@ impl From<Channels> for u8 {
350 320
351/// Interface to the I2S peripheral using EasyDMA to offload the transmission and reception workload. 321/// Interface to the I2S peripheral using EasyDMA to offload the transmission and reception workload.
352pub struct I2S<'d, T: Instance> { 322pub struct I2S<'d, T: Instance> {
353 _p: PeripheralRef<'d, T>, 323 i2s: PeripheralRef<'d, T>,
324 irq: PeripheralRef<'d, T::Interrupt>,
325 mck: Option<PeripheralRef<'d, AnyPin>>,
326 sck: PeripheralRef<'d, AnyPin>,
327 lrck: PeripheralRef<'d, AnyPin>,
328 sdin: Option<PeripheralRef<'d, AnyPin>>,
329 sdout: Option<PeripheralRef<'d, AnyPin>>,
330 master_clock: Option<MasterClock>,
331 config: Config,
354} 332}
355 333
356impl<'d, T: Instance> I2S<'d, T> { 334impl<'d, T: Instance> I2S<'d, T> {
357 /// Create a new I2S 335 /// Create a new I2S in master mode
358 pub fn new( 336 pub fn master(
359 i2s: impl Peripheral<P = T> + 'd, 337 i2s: impl Peripheral<P = T> + 'd,
360 irq: impl Peripheral<P = T::Interrupt> + 'd, 338 irq: impl Peripheral<P = T::Interrupt> + 'd,
361 mck: impl Peripheral<P = impl GpioPin> + 'd, 339 mck: impl Peripheral<P = impl GpioPin> + 'd,
362 sck: impl Peripheral<P = impl GpioPin> + 'd, 340 sck: impl Peripheral<P = impl GpioPin> + 'd,
363 lrck: impl Peripheral<P = impl GpioPin> + 'd, 341 lrck: impl Peripheral<P = impl GpioPin> + 'd,
364 sdin: impl Peripheral<P = impl GpioPin> + 'd, 342 master_clock: MasterClock,
365 sdout: impl Peripheral<P = impl GpioPin> + 'd,
366 config: Config, 343 config: Config,
367 ) -> Self { 344 ) -> Self {
368 into_ref!(mck, sck, lrck, sdin, sdout); 345 into_ref!(i2s, irq, mck, sck, lrck);
369 Self::new_inner( 346 Self {
370 i2s, 347 i2s,
371 irq, 348 irq,
372 mck.map_into(), 349 mck: Some(mck.map_into()),
373 sck.map_into(), 350 sck: sck.map_into(),
374 lrck.map_into(), 351 lrck: lrck.map_into(),
375 sdin.map_into(), 352 sdin: None,
376 sdout.map_into(), 353 sdout: None,
354 master_clock: Some(master_clock),
377 config, 355 config,
378 ) 356 }
379 } 357 }
380 358
381 fn new_inner( 359 /// Create a new I2S in slave mode
360 pub fn slave(
382 i2s: impl Peripheral<P = T> + 'd, 361 i2s: impl Peripheral<P = T> + 'd,
383 irq: impl Peripheral<P = T::Interrupt> + 'd, 362 irq: impl Peripheral<P = T::Interrupt> + 'd,
384 mck: PeripheralRef<'d, AnyPin>, 363 sck: impl Peripheral<P = impl GpioPin> + 'd,
385 sck: PeripheralRef<'d, AnyPin>, 364 lrck: impl Peripheral<P = impl GpioPin> + 'd,
386 lrck: PeripheralRef<'d, AnyPin>,
387 sdin: PeripheralRef<'d, AnyPin>,
388 sdout: PeripheralRef<'d, AnyPin>,
389 config: Config, 365 config: Config,
390 ) -> Self { 366 ) -> Self {
391 into_ref!(i2s, irq, mck, sck, lrck, sdin, sdout); 367 into_ref!(i2s, irq, sck, lrck);
392 368 Self {
393 Self::apply_config(&config); 369 i2s,
394 Self::select_pins(mck, sck, lrck, sdin, sdout); 370 irq,
395 Self::setup_interrupt(irq); 371 mck: None,
396 372 sck: sck.map_into(),
397 T::regs().enable.write(|w| w.enable().enabled()); 373 lrck: lrck.map_into(),
398 374 sdin: None,
399 Self { _p: i2s } 375 sdout: None,
376 master_clock: None,
377 config,
378 }
400 } 379 }
401 380
402 /// I2S output only 381 /// I2S output only
403 pub fn output(self) -> Output<'d, T> { 382 pub fn output(mut self, sdout: impl Peripheral<P = impl GpioPin> + 'd) -> OutputStream<'d, T> {
404 Output { _p: self._p } 383 self.sdout = Some(sdout.into_ref().map_into());
384 OutputStream { _p: self.build() }
405 } 385 }
406 386
407 /// I2S input only 387 /// I2S input only
408 pub fn input(self) -> Input<'d, T> { 388 pub fn input(mut self, sdin: impl Peripheral<P = impl GpioPin> + 'd) -> InputStream<'d, T> {
409 Input { _p: self._p } 389 self.sdin = Some(sdin.into_ref().map_into());
390 InputStream { _p: self.build() }
410 } 391 }
411 392
412 /// I2S full duplex (input and output) 393 /// I2S full duplex (input and output)
413 pub fn full_duplex(self) -> FullDuplex<'d, T> { 394 pub fn full_duplex(
414 FullDuplex { _p: self._p } 395 mut self,
396 sdin: impl Peripheral<P = impl GpioPin> + 'd,
397 sdout: impl Peripheral<P = impl GpioPin> + 'd,
398 ) -> FullDuplexStream<'d, T> {
399 self.sdout = Some(sdout.into_ref().map_into());
400 self.sdin = Some(sdin.into_ref().map_into());
401 FullDuplexStream { _p: self.build() }
415 } 402 }
416 403
417 fn apply_config(config: &Config) { 404 fn build(self) -> PeripheralRef<'d, T> {
405 self.apply_config();
406 self.select_pins();
407 self.setup_interrupt();
408
409 let device = Device::<T>::new();
410 device.enable();
411
412 self.i2s
413 }
414
415 fn apply_config(&self) {
418 let c = &T::regs().config; 416 let c = &T::regs().config;
419 match config.mode { 417 match &self.master_clock {
420 Mode::Master { freq, ratio } => { 418 Some(MasterClock { freq, ratio }) => {
421 c.mode.write(|w| w.mode().master()); 419 c.mode.write(|w| w.mode().master());
422 c.mcken.write(|w| w.mcken().enabled()); 420 c.mcken.write(|w| w.mcken().enabled());
423 c.mckfreq 421 c.mckfreq
424 .write(|w| unsafe { w.mckfreq().bits(freq.to_register_value()) }); 422 .write(|w| unsafe { w.mckfreq().bits(freq.to_register_value()) });
425 c.ratio.write(|w| unsafe { w.ratio().bits(ratio.into()) }); 423 c.ratio.write(|w| unsafe { w.ratio().bits(ratio.to_register_value()) });
426 } 424 }
427 Mode::Slave => { 425 None => {
428 c.mode.write(|w| w.mode().slave()); 426 c.mode.write(|w| w.mode().slave());
429 } 427 }
430 }; 428 };
431 429
432 c.swidth.write(|w| unsafe { w.swidth().bits(config.swidth.into()) }); 430 c.swidth
433 c.align.write(|w| w.align().bit(config.align.into())); 431 .write(|w| unsafe { w.swidth().bits(self.config.sample_width.into()) });
434 c.format.write(|w| w.format().bit(config.format.into())); 432 c.align.write(|w| w.align().bit(self.config.align.into()));
433 c.format.write(|w| w.format().bit(self.config.format.into()));
435 c.channels 434 c.channels
436 .write(|w| unsafe { w.channels().bits(config.channels.into()) }); 435 .write(|w| unsafe { w.channels().bits(self.config.channels.into()) });
437 } 436 }
438 437
439 fn select_pins( 438 fn select_pins(&self) {
440 mck: PeripheralRef<'d, AnyPin>,
441 sck: PeripheralRef<'d, AnyPin>,
442 lrck: PeripheralRef<'d, AnyPin>,
443 sdin: PeripheralRef<'d, AnyPin>,
444 sdout: PeripheralRef<'d, AnyPin>,
445 ) {
446 let psel = &T::regs().psel; 439 let psel = &T::regs().psel;
447 440
448 psel.mck.write(|w| { 441 if let Some(mck) = &self.mck {
449 unsafe { w.bits(mck.psel_bits()) }; 442 psel.mck.write(|w| {
450 w.connect().connected() 443 unsafe { w.bits(mck.psel_bits()) };
451 }); 444 w.connect().connected()
445 });
446 }
452 447
453 psel.sck.write(|w| { 448 psel.sck.write(|w| {
454 unsafe { w.bits(sck.psel_bits()) }; 449 unsafe { w.bits(self.sck.psel_bits()) };
455 w.connect().connected() 450 w.connect().connected()
456 }); 451 });
457 452
458 psel.lrck.write(|w| { 453 psel.lrck.write(|w| {
459 unsafe { w.bits(lrck.psel_bits()) }; 454 unsafe { w.bits(self.lrck.psel_bits()) };
460 w.connect().connected() 455 w.connect().connected()
461 }); 456 });
462 457
463 psel.sdin.write(|w| { 458 if let Some(sdin) = &self.sdin {
464 unsafe { w.bits(sdin.psel_bits()) }; 459 psel.sdin.write(|w| {
465 w.connect().connected() 460 unsafe { w.bits(sdin.psel_bits()) };
466 }); 461 w.connect().connected()
462 });
463 }
467 464
468 psel.sdout.write(|w| { 465 if let Some(sdout) = &self.sdout {
469 unsafe { w.bits(sdout.psel_bits()) }; 466 psel.sdout.write(|w| {
470 w.connect().connected() 467 unsafe { w.bits(sdout.psel_bits()) };
471 }); 468 w.connect().connected()
469 });
470 }
472 } 471 }
473 472
474 fn setup_interrupt(irq: PeripheralRef<'d, T::Interrupt>) { 473 fn setup_interrupt(&self) {
475 irq.set_handler(Self::on_interrupt); 474 self.irq.set_handler(Self::on_interrupt);
476 irq.unpend(); 475 self.irq.unpend();
477 irq.enable(); 476 self.irq.enable();
478 477
479 let device = Device::<T>::new(); 478 let device = Device::<T>::new();
480 device.disable_tx_ptr_interrupt(); 479 device.disable_tx_ptr_interrupt();
@@ -538,17 +537,32 @@ impl<'d, T: Instance> I2S<'d, T> {
538 device.disable(); 537 device.disable();
539 } 538 }
540 539
541 async fn send<B>(buffer: B) -> Result<(), Error> 540 async fn send_from_ram<S>(buffer_ptr: *const [S]) -> Result<(), Error>
542 where 541 where
543 B: Buffer, 542 S: Sample,
544 { 543 {
545 trace!("SEND: {}", buffer.bytes_ptr() as u32); 544 trace!("SEND: {}", buffer_ptr as *const S as u32);
546 545
547 let device = Device::<T>::new(); 546 slice_in_ram_or(buffer_ptr, Error::BufferNotInDataMemory)?;
548 let drop = device.on_tx_drop();
549 547
550 compiler_fence(Ordering::SeqCst); 548 compiler_fence(Ordering::SeqCst);
551 549
550 let device = Device::<T>::new();
551
552 let drop = OnDrop::new(move || {
553 trace!("TX DROP: Stopping");
554
555 let device = Device::<T>::new();
556 device.disable_tx_ptr_interrupt();
557 device.reset_tx_ptr_event();
558 device.disable_tx();
559
560 // TX is stopped almost instantly, spinning is fine.
561 while !device.is_tx_ptr_updated() {}
562
563 trace!("TX DROP: Stopped");
564 });
565
552 poll_fn(|cx| { 566 poll_fn(|cx| {
553 T::state().tx_waker.register(cx.waker()); 567 T::state().tx_waker.register(cx.waker());
554 568
@@ -564,7 +578,7 @@ impl<'d, T: Instance> I2S<'d, T> {
564 }) 578 })
565 .await; 579 .await;
566 580
567 device.set_tx_buffer(buffer)?; 581 device.update_tx(buffer_ptr)?;
568 582
569 compiler_fence(Ordering::SeqCst); 583 compiler_fence(Ordering::SeqCst);
570 drop.defuse(); 584 drop.defuse();
@@ -572,17 +586,33 @@ impl<'d, T: Instance> I2S<'d, T> {
572 Ok(()) 586 Ok(())
573 } 587 }
574 588
575 async fn receive<B>(buffer: B) -> Result<(), Error> 589 async fn receive_from_ram<S>(buffer_ptr: *mut [S]) -> Result<(), Error>
576 where 590 where
577 B: Buffer, 591 S: Sample,
578 { 592 {
579 trace!("RECEIVE: {}", buffer.bytes_ptr() as u32); 593 trace!("RECEIVE: {}", buffer_ptr as *const S as u32);
580 594
581 let device = Device::<T>::new(); 595 // NOTE: RAM slice check for rx is not necessary, as a mutable
582 let drop = device.on_rx_drop(); 596 // slice can only be built from data located in RAM.
583 597
584 compiler_fence(Ordering::SeqCst); 598 compiler_fence(Ordering::SeqCst);
585 599
600 let device = Device::<T>::new();
601
602 let drop = OnDrop::new(move || {
603 trace!("RX DROP: Stopping");
604
605 let device = Device::<T>::new();
606 device.disable_rx_ptr_interrupt();
607 device.reset_rx_ptr_event();
608 device.disable_rx();
609
610 // TX is stopped almost instantly, spinning is fine.
611 while !device.is_rx_ptr_updated() {}
612
613 trace!("RX DROP: Stopped");
614 });
615
586 poll_fn(|cx| { 616 poll_fn(|cx| {
587 T::state().rx_waker.register(cx.waker()); 617 T::state().rx_waker.register(cx.waker());
588 618
@@ -598,9 +628,10 @@ impl<'d, T: Instance> I2S<'d, T> {
598 }) 628 })
599 .await; 629 .await;
600 630
601 device.set_rx_buffer(buffer)?; 631 device.update_rx(buffer_ptr)?;
602 632
603 compiler_fence(Ordering::SeqCst); 633 compiler_fence(Ordering::SeqCst);
634
604 drop.defuse(); 635 drop.defuse();
605 636
606 Ok(()) 637 Ok(())
@@ -608,15 +639,15 @@ impl<'d, T: Instance> I2S<'d, T> {
608} 639}
609 640
610/// I2S output 641/// I2S output
611pub struct Output<'d, T: Instance> { 642pub struct OutputStream<'d, T: Instance> {
612 _p: PeripheralRef<'d, T>, 643 _p: PeripheralRef<'d, T>,
613} 644}
614 645
615impl<'d, T: Instance> Output<'d, T> { 646impl<'d, T: Instance> OutputStream<'d, T> {
616 /// Prepare the initial buffer and start the I2S transfer. 647 /// Prepare the initial buffer and start the I2S transfer.
617 pub async fn start<B>(&self, buffer: B) -> Result<(), Error> 648 pub async fn start<S>(&self, buffer: &[S]) -> Result<(), Error>
618 where 649 where
619 B: Buffer, 650 S: Sample,
620 { 651 {
621 let device = Device::<T>::new(); 652 let device = Device::<T>::new();
622 653
@@ -627,7 +658,8 @@ impl<'d, T: Instance> Output<'d, T> {
627 658
628 device.enable(); 659 device.enable();
629 device.enable_tx(); 660 device.enable_tx();
630 device.set_tx_buffer(buffer)?; 661
662 device.update_tx(buffer as *const [S])?;
631 663
632 s.started.store(true, Ordering::Relaxed); 664 s.started.store(true, Ordering::Relaxed);
633 665
@@ -647,24 +679,24 @@ impl<'d, T: Instance> Output<'d, T> {
647 /// The buffer must not be written while being used by the DMA, 679 /// The buffer must not be written while being used by the DMA,
648 /// which takes two other `send`s being awaited. 680 /// which takes two other `send`s being awaited.
649 #[allow(unused_mut)] 681 #[allow(unused_mut)]
650 pub async fn send<B>(&mut self, buffer: B) -> Result<(), Error> 682 pub async fn send_from_ram<S>(&mut self, buffer: &[S]) -> Result<(), Error>
651 where 683 where
652 B: Buffer, 684 S: Sample,
653 { 685 {
654 I2S::<T>::send(buffer).await 686 I2S::<T>::send_from_ram(buffer as *const [S]).await
655 } 687 }
656} 688}
657 689
658/// I2S input 690/// I2S input
659pub struct Input<'d, T: Instance> { 691pub struct InputStream<'d, T: Instance> {
660 _p: PeripheralRef<'d, T>, 692 _p: PeripheralRef<'d, T>,
661} 693}
662 694
663impl<'d, T: Instance> Input<'d, T> { 695impl<'d, T: Instance> InputStream<'d, T> {
664 /// Prepare the initial buffer and start the I2S transfer. 696 /// Prepare the initial buffer and start the I2S transfer.
665 pub async fn start<B>(&self, buffer: B) -> Result<(), Error> 697 pub async fn start<S>(&self, buffer: &mut [S]) -> Result<(), Error>
666 where 698 where
667 B: Buffer, 699 S: Sample,
668 { 700 {
669 let device = Device::<T>::new(); 701 let device = Device::<T>::new();
670 702
@@ -675,7 +707,8 @@ impl<'d, T: Instance> Input<'d, T> {
675 707
676 device.enable(); 708 device.enable();
677 device.enable_rx(); 709 device.enable_rx();
678 device.set_rx_buffer(buffer)?; 710
711 device.update_rx(buffer as *mut [S])?;
679 712
680 s.started.store(true, Ordering::Relaxed); 713 s.started.store(true, Ordering::Relaxed);
681 714
@@ -695,24 +728,24 @@ impl<'d, T: Instance> Input<'d, T> {
695 /// The buffer must not be read while being used by the DMA, 728 /// The buffer must not be read while being used by the DMA,
696 /// which takes two other `receive`s being awaited. 729 /// which takes two other `receive`s being awaited.
697 #[allow(unused_mut)] 730 #[allow(unused_mut)]
698 pub async fn receive<B>(&mut self, buffer: B) -> Result<(), Error> 731 pub async fn receive_from_ram<S>(&mut self, buffer: &mut [S]) -> Result<(), Error>
699 where 732 where
700 B: Buffer, 733 S: Sample,
701 { 734 {
702 I2S::<T>::receive(buffer).await 735 I2S::<T>::receive_from_ram(buffer as *mut [S]).await
703 } 736 }
704} 737}
705 738
706/// I2S ful duplex (input & output) 739/// I2S full duplex stream (input & output)
707pub struct FullDuplex<'d, T: Instance> { 740pub struct FullDuplexStream<'d, T: Instance> {
708 _p: PeripheralRef<'d, T>, 741 _p: PeripheralRef<'d, T>,
709} 742}
710 743
711impl<'d, T: Instance> FullDuplex<'d, T> { 744impl<'d, T: Instance> FullDuplexStream<'d, T> {
712 /// Prepare the initial buffers and start the I2S transfer. 745 /// Prepare the initial buffers and start the I2S transfer.
713 pub async fn start<B>(&self, buffer_out: B, buffer_in: B) -> Result<(), Error> 746 pub async fn start<S>(&self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error>
714 where 747 where
715 B: Buffer, 748 S: Sample,
716 { 749 {
717 let device = Device::<T>::new(); 750 let device = Device::<T>::new();
718 751
@@ -724,8 +757,9 @@ impl<'d, T: Instance> FullDuplex<'d, T> {
724 device.enable(); 757 device.enable();
725 device.enable_tx(); 758 device.enable_tx();
726 device.enable_rx(); 759 device.enable_rx();
727 device.set_tx_buffer(buffer_out)?; 760
728 device.set_rx_buffer(buffer_in)?; 761 device.update_tx(buffer_out as *const [S])?;
762 device.update_rx(buffer_in as *mut [S])?;
729 763
730 s.started.store(true, Ordering::Relaxed); 764 s.started.store(true, Ordering::Relaxed);
731 765
@@ -745,12 +779,12 @@ impl<'d, T: Instance> FullDuplex<'d, T> {
745 /// The buffers must not be written/read while being used by the DMA, 779 /// The buffers must not be written/read while being used by the DMA,
746 /// which takes two other `send_and_receive` operations being awaited. 780 /// which takes two other `send_and_receive` operations being awaited.
747 #[allow(unused_mut)] 781 #[allow(unused_mut)]
748 pub async fn send_and_receive<B>(&mut self, buffer_out: B, buffer_in: B) -> Result<(), Error> 782 pub async fn send_and_receive_from_ram<S>(&mut self, buffer_out: &[S], buffer_in: &mut [S]) -> Result<(), Error>
749 where 783 where
750 B: Buffer, 784 S: Sample,
751 { 785 {
752 I2S::<T>::send(buffer_out).await?; 786 I2S::<T>::send_from_ram(buffer_out as *const [S]).await?;
753 I2S::<T>::receive(buffer_in).await?; 787 I2S::<T>::receive_from_ram(buffer_in as *mut [S]).await?;
754 Ok(()) 788 Ok(())
755 } 789 }
756} 790}
@@ -833,38 +867,6 @@ impl<T: Instance> Device<T> {
833 self.0.intenset.write(|w| w.stopped().set()); 867 self.0.intenset.write(|w| w.stopped().set());
834 } 868 }
835 869
836 #[inline]
837 fn set_tx_buffer<B>(&self, buffer: B) -> Result<(), Error>
838 where
839 B: Buffer,
840 {
841 let (ptr, maxcnt) = Self::validate_buffer(buffer)?;
842 self.0.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
843 self.0.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr) });
844 Ok(())
845 }
846
847 #[inline]
848 fn set_rx_buffer<B>(&self, buffer: B) -> Result<(), Error>
849 where
850 B: Buffer,
851 {
852 let (ptr, maxcnt) = Self::validate_buffer(buffer)?;
853 self.0.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
854 self.0.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr) });
855 Ok(())
856 }
857
858 #[inline(always)]
859 fn is_tx_ptr_updated(&self) -> bool {
860 self.0.events_txptrupd.read().bits() != 0
861 }
862
863 #[inline(always)]
864 fn is_rx_ptr_updated(&self) -> bool {
865 self.0.events_rxptrupd.read().bits() != 0
866 }
867
868 #[inline(always)] 870 #[inline(always)]
869 fn reset_tx_ptr_event(&self) { 871 fn reset_tx_ptr_event(&self) {
870 trace!("TX PTR EVENT: Reset"); 872 trace!("TX PTR EVENT: Reset");
@@ -901,58 +903,44 @@ impl<T: Instance> Device<T> {
901 self.0.intenclr.write(|w| w.rxptrupd().clear()); 903 self.0.intenclr.write(|w| w.rxptrupd().clear());
902 } 904 }
903 905
904 #[inline] 906 #[inline(always)]
905 fn on_tx_drop(&self) -> OnDrop<fn()> { 907 fn is_tx_ptr_updated(&self) -> bool {
906 OnDrop::new(move || { 908 self.0.events_txptrupd.read().bits() != 0
907 trace!("TX DROP: Stopping"); 909 }
908
909 let device = Device::<T>::new();
910 device.disable_tx_ptr_interrupt();
911 device.reset_tx_ptr_event();
912 device.disable_tx();
913
914 // TX is stopped almost instantly, spinning is fine.
915 while !device.is_tx_ptr_updated() {}
916 910
917 trace!("TX DROP: Stopped"); 911 #[inline(always)]
918 }) 912 fn is_rx_ptr_updated(&self) -> bool {
913 self.0.events_rxptrupd.read().bits() != 0
919 } 914 }
920 915
921 #[inline] 916 #[inline]
922 fn on_rx_drop(&self) -> OnDrop<fn()> { 917 fn update_tx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
923 OnDrop::new(move || { 918 let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
924 trace!("RX DROP: Stopping"); 919 self.0.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
925 920 self.0.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr) });
926 let device = Device::<T>::new(); 921 Ok(())
927 device.disable_rx_ptr_interrupt(); 922 }
928 device.reset_rx_ptr_event();
929 device.disable_rx();
930
931 // TX is stopped almost instantly, spinning is fine.
932 while !device.is_rx_ptr_updated() {}
933 923
934 trace!("RX DROP: Stopped"); 924 #[inline]
935 }) 925 fn update_rx<S>(&self, buffer_ptr: *const [S]) -> Result<(), Error> {
926 let (ptr, maxcnt) = Self::validated_dma_parts(buffer_ptr)?;
927 self.0.rxtxd.maxcnt.write(|w| unsafe { w.bits(maxcnt) });
928 self.0.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr) });
929 Ok(())
936 } 930 }
937 931
938 fn validate_buffer<B>(buffer: B) -> Result<(u32, u32), Error> 932 fn validated_dma_parts<S>(buffer_ptr: *const [S]) -> Result<(u32, u32), Error> {
939 where 933 let (ptr, len) = slice_ptr_parts(buffer_ptr);
940 B: Buffer, 934 let ptr = ptr as u32;
941 { 935 let bytes_len = len * size_of::<S>();
942 let ptr = buffer.bytes_ptr() as u32; 936 let maxcnt = (bytes_len / size_of::<u32>()) as u32;
943 let len = buffer.bytes_len();
944 let maxcnt = ((len + core::mem::size_of::<u32>() - 1) / core::mem::size_of::<u32>()) as u32;
945 937
946 trace!("PTR={}, MAXCNT={}", ptr, maxcnt); 938 trace!("PTR={}, MAXCNT={}", ptr, maxcnt);
947 939
948 // TODO can we avoid repeating all those runtime checks for the same buffer again and again?
949
950 if ptr % 4 != 0 { 940 if ptr % 4 != 0 {
951 Err(Error::BufferMisaligned) 941 Err(Error::BufferMisaligned)
952 } else if len % 4 != 0 { 942 } else if bytes_len % 4 != 0 {
953 Err(Error::BufferLengthMisaligned) 943 Err(Error::BufferLengthMisaligned)
954 } else if (ptr as usize) < SRAM_LOWER || (ptr as usize) > SRAM_UPPER {
955 Err(Error::BufferNotInDataMemory)
956 } else if maxcnt as usize > EASY_DMA_SIZE { 944 } else if maxcnt as usize > EASY_DMA_SIZE {
957 Err(Error::BufferTooLong) 945 Err(Error::BufferTooLong)
958 } else { 946 } else {
@@ -998,60 +986,19 @@ impl<T: Sample, const N: usize> Default for AlignedBuffer<T, N> {
998 } 986 }
999} 987}
1000 988
1001impl<T: Sample, const N: usize> AsRef<[T]> for AlignedBuffer<T, N> { 989impl<T: Sample, const N: usize> Deref for AlignedBuffer<T, N> {
1002 fn as_ref(&self) -> &[T] { 990 type Target = [T];
991 fn deref(&self) -> &Self::Target {
1003 self.0.as_slice() 992 self.0.as_slice()
1004 } 993 }
1005} 994}
1006 995
1007impl<T: Sample, const N: usize> AsMut<[T]> for AlignedBuffer<T, N> { 996impl<T: Sample, const N: usize> DerefMut for AlignedBuffer<T, N> {
1008 fn as_mut(&mut self) -> &mut [T] { 997 fn deref_mut(&mut self) -> &mut Self::Target {
1009 self.0.as_mut_slice() 998 self.0.as_mut_slice()
1010 } 999 }
1011} 1000}
1012 1001
1013/// Common operations required for a buffer to be used by the DMA
1014pub trait Buffer: Sized {
1015 fn bytes_ptr(&self) -> *const u8;
1016 fn bytes_len(&self) -> usize;
1017}
1018
1019impl Buffer for &[i8] {
1020 #[inline]
1021 fn bytes_ptr(&self) -> *const u8 {
1022 self.as_ptr() as *const u8
1023 }
1024
1025 #[inline]
1026 fn bytes_len(&self) -> usize {
1027 self.len()
1028 }
1029}
1030
1031impl Buffer for &[i16] {
1032 #[inline]
1033 fn bytes_ptr(&self) -> *const u8 {
1034 self.as_ptr() as *const u8
1035 }
1036
1037 #[inline]
1038 fn bytes_len(&self) -> usize {
1039 self.len() * core::mem::size_of::<i16>()
1040 }
1041}
1042
1043impl Buffer for &[i32] {
1044 #[inline]
1045 fn bytes_ptr(&self) -> *const u8 {
1046 self.as_ptr() as *const u8
1047 }
1048
1049 #[inline]
1050 fn bytes_len(&self) -> usize {
1051 self.len() * core::mem::size_of::<i32>()
1052 }
1053}
1054
1055pub(crate) mod sealed { 1002pub(crate) mod sealed {
1056 use core::sync::atomic::AtomicBool; 1003 use core::sync::atomic::AtomicBool;
1057 1004
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
7use defmt::{error, info}; 7use defmt::{error, info};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_nrf::i2s::{self, Sample as _}; 9use embassy_nrf::i2s::{self, Channels, Config, MasterClock, Sample as _, SampleWidth, I2S};
10use embassy_nrf::interrupt; 10use embassy_nrf::interrupt;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13type Sample = i16;
14
15const NUM_SAMPLES: usize = 6000;
16
13#[embassy_executor::main] 17#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 18async 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
61struct Waveform {
62 inv_sample_rate: f32,
63 carrier: SineOsc,
64 freq_mod: SineOsc,
65 amp_mod: SineOsc,
66}
67
68impl 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)]
85struct SineOsc { 104struct SineOsc {
86 amplitude: f32, 105 amplitude: f32,
87 modulo: f32, 106 modulo: f32,