Skip to content

Commit c3d01a2

Browse files
Merge pull request #209 from kalkyl/i2s-dma
Use DMA Transfer API in I2S module
2 parents 78add9d + 3b4cc4b commit c3d01a2

File tree

5 files changed

+192
-123
lines changed

5 files changed

+192
-123
lines changed

examples/i2s-controller-demo/src/main.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,8 @@ use {
3232
#[rtic::app(device = crate::hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)]
3333
const APP: () = {
3434
struct Resources {
35-
i2s: hal::i2s::I2S,
36-
#[init([0; 32])]
37-
signal_buf: [i16; 32],
38-
#[init([0; 32])]
39-
mute_buf: [i16; 32],
35+
signal_buf: &'static [i16],
36+
mute_buf: &'static [i16],
4037
#[init(None)]
4138
queue: Option<Queue<State, U256>>,
4239
producer: Producer<'static, State, U256>,
@@ -49,10 +46,21 @@ const APP: () = {
4946
btn1: Pin<Input<PullUp>>,
5047
btn2: Pin<Input<PullUp>>,
5148
led: Pin<Output<PushPull>>,
49+
transfer: Option<Transfer<&'static [i16]>>,
5250
}
5351

54-
#[init(resources = [queue, signal_buf, mute_buf], spawn = [tick])]
52+
#[init(resources = [queue], spawn = [tick])]
5553
fn init(mut ctx: init::Context) -> init::LateResources {
54+
static mut MUTE_BUF: [i16; 32] = [0i16; 32];
55+
static mut SIGNAL_BUF: [i16; 32] = [0i16; 32];
56+
57+
// Fill signal buffer with triangle waveform, 2 channels interleaved
58+
let len = SIGNAL_BUF.len() / 2;
59+
for x in 0..len {
60+
SIGNAL_BUF[2 * x] = triangle_wave(x as i32, len, 2048, 0, 1) as i16;
61+
SIGNAL_BUF[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16;
62+
}
63+
5664
let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc();
5765
// Enable the monotonic timer (CYCCNT)
5866
ctx.core.DCB.enable_trace();
@@ -75,16 +83,7 @@ const APP: () = {
7583
None,
7684
Some(&sdout_pin),
7785
);
78-
i2s.tx_buffer(&ctx.resources.mute_buf[..]).ok();
79-
i2s.enable().start();
80-
81-
// Fill signal buffer with triangle waveform, 2 channels interleaved
82-
let signal_buf = ctx.resources.signal_buf;
83-
let len = signal_buf.len() / 2;
84-
for x in 0..len {
85-
signal_buf[2 * x] = triangle_wave(x as i32, len, 2048, 0, 1) as i16;
86-
signal_buf[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16;
87-
}
86+
i2s.start();
8887

8988
// Configure buttons
9089
let btn1 = p0.p0_11.into_pullup_input().degrade();
@@ -117,7 +116,6 @@ const APP: () = {
117116
ctx.spawn.tick().ok();
118117

119118
init::LateResources {
120-
i2s,
121119
producer,
122120
consumer,
123121
gpiote,
@@ -126,6 +124,9 @@ const APP: () = {
126124
led: p0.p0_13.into_push_pull_output(Level::High).degrade(),
127125
uarte,
128126
uarte_timer: Timer::new(ctx.device.TIMER0),
127+
transfer: i2s.tx(&MUTE_BUF[..]).ok(),
128+
signal_buf: &SIGNAL_BUF[..],
129+
mute_buf: &MUTE_BUF[..],
129130
}
130131
}
131132

@@ -150,7 +151,7 @@ const APP: () = {
150151
}
151152
}
152153
Err(hal::uarte::Error::Timeout(n)) if n > 0 => {
153-
if let Ok(msg) = core::str::from_utf8(&uarte_rx_buf[0..n]) {
154+
if let Ok(msg) = core::str::from_utf8(&uarte_rx_buf[..n]) {
154155
rprintln!("{}", msg);
155156
for action in encode(msg) {
156157
for _ in 0..action.duration {
@@ -164,18 +165,18 @@ const APP: () = {
164165
}
165166
}
166167

167-
#[task(resources = [consumer, i2s, signal_buf, mute_buf, led, speed], schedule = [tick])]
168+
#[task(resources = [consumer, transfer, signal_buf, mute_buf, led, speed], schedule = [tick])]
168169
fn tick(ctx: tick::Context) {
169-
let i2s = ctx.resources.i2s;
170+
let (_buf, i2s) = ctx.resources.transfer.take().unwrap().wait();
170171
match ctx.resources.consumer.dequeue() {
171172
Some(State::On) => {
172173
// Move TX pointer to signal buffer (sound ON)
173-
i2s.tx_buffer(&ctx.resources.signal_buf[..]).ok();
174+
*ctx.resources.transfer = i2s.tx(*ctx.resources.signal_buf).ok();
174175
ctx.resources.led.set_low().ok();
175176
}
176177
_ => {
177178
// Move TX pointer to silent buffer (sound OFF)
178-
i2s.tx_buffer(&ctx.resources.mute_buf[..]).ok();
179+
*ctx.resources.transfer = i2s.tx(*ctx.resources.mute_buf).ok();
179180
ctx.resources.led.set_high().ok();
180181
}
181182
}
@@ -190,7 +191,7 @@ const APP: () = {
190191
ctx.schedule.debounce(ctx.start + 3_000_000.cycles()).ok();
191192
}
192193

193-
#[task(resources = [btn1, btn2, i2s, speed])]
194+
#[task(resources = [btn1, btn2, speed])]
194195
fn debounce(ctx: debounce::Context) {
195196
if ctx.resources.btn1.is_low().unwrap() {
196197
rprintln!("Go slower");

examples/i2s-peripheral-demo/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ cortex-m = "0.6.2"
1212
cortex-m-rtic = "0.5.3"
1313
rtt-target = {version = "0.2.0", features = ["cortex-m"] }
1414
nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" }
15-
small_morse = "0.1.0"
16-
m = "0.1.1"
1715

1816
[dependencies.embedded-hal]
1917
version = "0.2.3"

examples/i2s-peripheral-demo/src/main.rs

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
#![no_main]
33

44
// I2S `peripheral mode` demo
5-
// RMS level indicator using an RGB LED (APA102 on ItsyBitsy nRF52840)
5+
// Signal average level indicator using an RGB LED (APA102 on ItsyBitsy nRF52840)
66

77
use embedded_hal::blocking::spi::Write;
8-
use m::Float;
98
use {
109
core::{
1110
panic::PanicInfo,
@@ -29,14 +28,14 @@ const RED: [u8; 9] = [0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x10, 0xFF];
2928
#[rtic::app(device = crate::hal::pac, peripherals = true)]
3029
const APP: () = {
3130
struct Resources {
32-
i2s: I2S,
33-
#[init([0; 128])]
34-
rx_buf: [i16; 128],
3531
rgb: Spim<SPIM0>,
32+
transfer: Option<Transfer<&'static mut [i16; 128]>>,
3633
}
3734

38-
#[init(resources = [rx_buf])]
35+
#[init]
3936
fn init(ctx: init::Context) -> init::LateResources {
37+
static mut RX_BUF: [i16; 128] = [0; 128];
38+
4039
let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc();
4140
rtt_init_print!();
4241
rprintln!("Play me some audio...");
@@ -56,10 +55,7 @@ const APP: () = {
5655
Some(&sdin_pin),
5756
None,
5857
);
59-
i2s.enable_interrupt(I2SEvent::RxPtrUpdated)
60-
.rx_buffer(&mut ctx.resources.rx_buf[..])
61-
.ok();
62-
i2s.enable().start();
58+
i2s.enable_interrupt(I2SEvent::RxPtrUpdated).start();
6359

6460
// Configure APA102 RGB LED control
6561
let p1 = hal::gpio::p1::Parts::new(ctx.device.P1);
@@ -80,28 +76,29 @@ const APP: () = {
8076
},
8177
0,
8278
);
83-
84-
init::LateResources { i2s, rgb }
79+
init::LateResources {
80+
rgb,
81+
transfer: i2s.rx(RX_BUF).ok(),
82+
}
8583
}
8684

87-
#[task(binds = I2S, resources = [i2s, rx_buf, rgb])]
85+
#[task(binds = I2S, resources = [rgb, transfer])]
8886
fn on_i2s(ctx: on_i2s::Context) {
89-
let on_i2s::Resources { i2s, rx_buf, rgb } = ctx.resources;
87+
let (rx_buf, i2s) = ctx.resources.transfer.take().unwrap().wait();
9088
if i2s.is_event_triggered(I2SEvent::RxPtrUpdated) {
9189
i2s.reset_event(I2SEvent::RxPtrUpdated);
92-
// Calculate mono summed RMS of received buffer
93-
let rms = Float::sqrt(
94-
(rx_buf.iter().map(|x| *x as i32).map(|x| x * x).sum::<i32>() / rx_buf.len() as i32)
95-
as f32,
96-
) as u16;
97-
let color = match rms {
90+
//Calculate mono summed average of received buffer
91+
let avg = (rx_buf.iter().map(|x| (*x).abs() as u32).sum::<u32>() / rx_buf.len() as u32)
92+
as u16;
93+
let color = match avg {
9894
0..=4 => &OFF,
9995
5..=10_337 => &GREEN,
10096
10_338..=16_383 => &ORANGE,
10197
_ => &RED,
10298
};
103-
<Spim<SPIM0> as Write<u8>>::write(rgb, color).ok();
99+
<Spim<SPIM0> as Write<u8>>::write(ctx.resources.rgb, color).ok();
104100
}
101+
*ctx.resources.transfer = i2s.rx(rx_buf).ok();
105102
}
106103
};
107104

nrf-hal-common/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ nb = "1.0.0"
2424
fixed = "1.0.0"
2525
rand_core = "0.5.1"
2626
cfg-if = "0.1.10"
27+
embedded-dma = "0.1.1"
2728

2829
[dependencies.void]
2930
default-features = false

0 commit comments

Comments
 (0)