From 1920e90dcdbebc1e2f86001f1491a9f28eb0f0f3 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Sat, 5 Nov 2022 00:15:43 +0100 Subject: embassy-nrf: Add SPIS module --- examples/nrf/src/bin/spis.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 examples/nrf/src/bin/spis.rs (limited to 'examples') diff --git a/examples/nrf/src/bin/spis.rs b/examples/nrf/src/bin/spis.rs new file mode 100644 index 000000000..181e08404 --- /dev/null +++ b/examples/nrf/src/bin/spis.rs @@ -0,0 +1,25 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::interrupt; +use embassy_nrf::spis::{self, Config}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + info!("Running!"); + + let irq = interrupt::take!(SPIM2_SPIS2_SPI2); + let mut spis = spis::Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default()); + + loop { + let mut buf = [0_u8; 64]; + if let Ok(n) = spis.read(&mut buf).await { + info!("RX: {:?}", buf[..n]); + } + } +} -- cgit From 7da18e194a8a9fef207803b96b16e7b7bc787ca7 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Sat, 5 Nov 2022 01:12:25 +0100 Subject: Add status checks --- examples/nrf/src/bin/spis.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/spis.rs b/examples/nrf/src/bin/spis.rs index 181e08404..0fce23d31 100644 --- a/examples/nrf/src/bin/spis.rs +++ b/examples/nrf/src/bin/spis.rs @@ -5,7 +5,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_nrf::interrupt; -use embassy_nrf::spis::{self, Config}; +use embassy_nrf::spis::{Spis, Config}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) { info!("Running!"); let irq = interrupt::take!(SPIM2_SPIS2_SPI2); - let mut spis = spis::Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default()); + let mut spis = Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default()); loop { let mut buf = [0_u8; 64]; -- cgit From af34fc4ccc110bf37165f2b9655585ba3a33889a Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Sat, 5 Nov 2022 01:40:20 +0100 Subject: rustfmt --- examples/nrf/src/bin/spis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/spis.rs b/examples/nrf/src/bin/spis.rs index 0fce23d31..dade5fcbd 100644 --- a/examples/nrf/src/bin/spis.rs +++ b/examples/nrf/src/bin/spis.rs @@ -5,7 +5,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_nrf::interrupt; -use embassy_nrf::spis::{Spis, Config}; +use embassy_nrf::spis::{Config, Spis}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] -- cgit From cecd77938c694ff2bad2a259ff64f2f468dcb04a Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Wed, 9 Nov 2022 19:14:43 +0100 Subject: Draft: Initial support for I2S with a working example. Co-authored-by: @brainstorm --- examples/nrf/Cargo.toml | 2 +- examples/nrf/src/bin/i2s.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 examples/nrf/src/bin/i2s.rs (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index c633f82f5..a79044e8e 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -14,7 +14,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } +embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "i2s", "unstable-pac"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } embedded-io = "0.3.1" diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs new file mode 100644 index 000000000..556f6b2e2 --- /dev/null +++ b/examples/nrf/src/bin/i2s.rs @@ -0,0 +1,48 @@ +// Example inspired by RTIC's I2S demo: https://github.com/nrf-rs/nrf-hal/blob/master/examples/i2s-controller-demo/src/main.rs + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::{i2s}; +use {defmt_rtt as _, panic_probe as _}; + +#[repr(align(4))] +pub struct Aligned(T); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + let config = i2s::Config::default(); + + let mut i2s = i2s::I2s::new(p.I2S, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config); + + let mut signal_buf: Aligned<[i16; 32]> = Aligned([0i16; 32]); + let len = signal_buf.0.len() / 2; + for x in 0..len { + signal_buf.0[2 * x] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; + signal_buf.0[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; + } + + let ptr = &signal_buf.0 as *const i16 as *const u8; + let len = signal_buf.0.len() * core::mem::size_of::(); + + i2s.start(); + i2s.set_tx_enabled(true); + + loop { + i2s.tx(ptr, len).await; + } +} + +fn triangle_wave(x: i32, length: usize, amplitude: i32, phase: i32, periods: i32) -> i32 { + let length = length as i32; + amplitude + - ((2 * periods * (x + phase + length / (4 * periods)) * amplitude / length) + % (2 * amplitude) + - amplitude) + .abs() + - amplitude / 2 +} -- cgit From 3760b60db382c8c4f8d7067a8d472affa6db928b Mon Sep 17 00:00:00 2001 From: Roman Valls Guimera Date: Wed, 9 Nov 2022 21:58:56 +0100 Subject: Make bors grin ;) --- examples/nrf/src/bin/i2s.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 556f6b2e2..60cde3b65 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -4,9 +4,9 @@ #![no_main] #![feature(type_alias_impl_trait)] -use defmt::*; +//use defmt::*; use embassy_executor::Spawner; -use embassy_nrf::{i2s}; +use embassy_nrf::i2s; use {defmt_rtt as _, panic_probe as _}; #[repr(align(4))] @@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) { let config = i2s::Config::default(); let mut i2s = i2s::I2s::new(p.I2S, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config); - + let mut signal_buf: Aligned<[i16; 32]> = Aligned([0i16; 32]); let len = signal_buf.0.len() / 2; for x in 0..len { @@ -31,18 +31,19 @@ async fn main(_spawner: Spawner) { i2s.start(); i2s.set_tx_enabled(true); - + loop { - i2s.tx(ptr, len).await; + match i2s.tx(ptr, len).await { + Ok(_) => todo!(), + Err(_) => todo!(), + }; } } fn triangle_wave(x: i32, length: usize, amplitude: i32, phase: i32, periods: i32) -> i32 { let length = length as i32; amplitude - - ((2 * periods * (x + phase + length / (4 * periods)) * amplitude / length) - % (2 * amplitude) - - amplitude) + - ((2 * periods * (x + phase + length / (4 * periods)) * amplitude / length) % (2 * amplitude) - amplitude) .abs() - amplitude / 2 } -- cgit From 356beabc3b11d78612c6958d1cfe542209e43558 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Wed, 9 Nov 2022 22:47:55 +0100 Subject: Apply config --- examples/nrf/src/bin/i2s.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 60cde3b65..a395c7141 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); let config = i2s::Config::default(); - let mut i2s = i2s::I2s::new(p.I2S, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config); + let mut i2s = i2s::I2S::new(p.I2S, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config); let mut signal_buf: Aligned<[i16; 32]> = Aligned([0i16; 32]); let len = signal_buf.0.len() / 2; -- cgit From 5a64bf651c66f2da16cd3ae20ed9ba2489f40d7a Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Thu, 10 Nov 2022 00:10:42 +0100 Subject: Buffer trait. Simpler config. --- examples/nrf/src/bin/i2s.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index a395c7141..e8ddb4a40 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -26,14 +26,11 @@ async fn main(_spawner: Spawner) { signal_buf.0[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; } - let ptr = &signal_buf.0 as *const i16 as *const u8; - let len = signal_buf.0.len() * core::mem::size_of::(); - - i2s.start(); i2s.set_tx_enabled(true); + i2s.start(); loop { - match i2s.tx(ptr, len).await { + match i2s.tx(signal_buf.0.as_slice()).await { Ok(_) => todo!(), Err(_) => todo!(), }; -- cgit From cbc97758e391d981d497bf37fe63b5a35913c115 Mon Sep 17 00:00:00 2001 From: Matous Hybl Date: Wed, 9 Nov 2022 14:10:46 +0100 Subject: stm32: Fix watchdog division by zero for 256 prescaler, add watchdog example for H7 --- examples/stm32h7/src/bin/wdg.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 examples/stm32h7/src/bin/wdg.rs (limited to 'examples') diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs new file mode 100644 index 000000000..2b0301aad --- /dev/null +++ b/examples/stm32h7/src/bin/wdg.rs @@ -0,0 +1,24 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); + + unsafe { wdg.unleash() }; + + loop { + Timer::after(Duration::from_secs(1)).await; + unsafe { wdg.pet() }; + } +} -- cgit From 4a2e810485a996014999ad630a604c3fe4fc81a4 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Thu, 10 Nov 2022 23:13:01 +0100 Subject: Restrict to pacs supporting i2s --- examples/nrf/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index a79044e8e..c633f82f5 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -14,7 +14,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "i2s", "unstable-pac"] } +embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } embedded-io = "0.3.1" -- cgit From 122a31d20877005c7201d4e7c98da5544666dd1d Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sat, 12 Nov 2022 18:48:57 +0100 Subject: Interrupts, async, sine oscillator --- examples/nrf/src/bin/i2s.rs | 132 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 21 deletions(-) (limited to 'examples') 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 @@ #![no_main] #![feature(type_alias_impl_trait)] -//use defmt::*; +use core::f32::consts::PI; + +use defmt::{error, info}; use embassy_executor::Spawner; -use embassy_nrf::i2s; +use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000}; +use embassy_nrf::{i2s, interrupt}; use {defmt_rtt as _, panic_probe as _}; #[repr(align(4))] -pub struct Aligned(T); +pub struct AlignedBuffer(T); + +impl AsRef for AlignedBuffer { + fn as_ref(&self) -> &T { + &self.0 + } +} + +impl AsMut for AlignedBuffer { + fn as_mut(&mut self) -> &mut T { + &mut self.0 + } +} #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); - let config = i2s::Config::default(); + let mut config = i2s::Config::default(); + // config.mode = MODE_MASTER_16000; + config.mode = Mode::Master { + freq: MckFreq::_32MDiv10, + ratio: Ratio::_256x, + }; // 12500 Hz + let sample_rate = config.mode.sample_rate().expect("I2S Master"); + let inv_sample_rate = 1.0 / sample_rate as f32; - let mut i2s = i2s::I2S::new(p.I2S, p.P0_28, p.P0_29, p.P0_31, p.P0_11, p.P0_30, config); + info!("Sample rate: {}", sample_rate); - let mut signal_buf: Aligned<[i16; 32]> = Aligned([0i16; 32]); - let len = signal_buf.0.len() / 2; - for x in 0..len { - signal_buf.0[2 * x] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; - signal_buf.0[2 * x + 1] = triangle_wave(x as i32, len, 2048, 0, 1) as i16; - } + let irq = interrupt::take!(I2S); + 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); + + const BUF_SAMPLES: usize = 250; + const BUF_SIZE: usize = BUF_SAMPLES * 2; + let mut buf = AlignedBuffer([0i16; BUF_SIZE]); + + let mut carrier = SineOsc::new(); + carrier.set_frequency(300.0, inv_sample_rate); + + let mut modulator = SineOsc::new(); + modulator.set_frequency(0.01, inv_sample_rate); + modulator.set_amplitude(0.2); i2s.set_tx_enabled(true); i2s.start(); loop { - match i2s.tx(signal_buf.0.as_slice()).await { - Ok(_) => todo!(), - Err(_) => todo!(), - }; + for sample in buf.as_mut().chunks_mut(2) { + let signal = carrier.generate(); + // let modulation = bipolar_to_unipolar(modulator.generate()); + // carrier.set_frequency(200.0 + 100.0 * modulation, inv_sample_rate); + // carrier.set_amplitude((modulation); + let value = (i16::MAX as f32 * signal) as i16; + sample[0] = value; + sample[1] = value; + // info!("{}", signal); + } + + if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { + error!("{}", err); + } + } +} + +struct SineOsc { + amplitude: f32, + modulo: f32, + phase_inc: f32, +} + +impl SineOsc { + const B: f32 = 4.0 / PI; + const C: f32 = -4.0 / (PI * PI); + const P: f32 = 0.225; + + pub fn new() -> Self { + Self { + amplitude: 1.0, + modulo: 0.0, + phase_inc: 0.0, + } + } + + pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) { + self.phase_inc = freq * inv_sample_rate; + } + + pub fn set_amplitude(&mut self, amplitude: f32) { + self.amplitude = amplitude; + } + + pub fn generate(&mut self) -> f32 { + let signal = self.parabolic_sin(self.modulo); + self.modulo += self.phase_inc; + if self.modulo < 0.0 { + self.modulo += 1.0; + } else if self.modulo > 1.0 { + self.modulo -= 1.0; + } + signal * self.amplitude + } + + fn parabolic_sin(&mut self, modulo: f32) -> f32 { + let angle = PI - modulo * 2.0 * PI; + let y = Self::B * angle + Self::C * angle * abs(angle); + Self::P * (y * abs(y) - y) + y + } +} + +#[inline] +fn abs(value: f32) -> f32 { + if value < 0.0 { + -value + } else { + value } } -fn triangle_wave(x: i32, length: usize, amplitude: i32, phase: i32, periods: i32) -> i32 { - let length = length as i32; - amplitude - - ((2 * periods * (x + phase + length / (4 * periods)) * amplitude / length) % (2 * amplitude) - amplitude) - .abs() - - amplitude / 2 +#[inline] +fn bipolar_to_unipolar(value: f32) -> f32 { + (value + 1.0) / 2.0 } -- cgit From d2e8794f29d3d0afef7a6bc610b2ee4a4d680643 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sun, 13 Nov 2022 01:41:32 +0100 Subject: Investigating discontinuities in the signal --- examples/nrf/src/bin/i2s.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 53ccb3b85..7fb1ecb84 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -9,6 +9,7 @@ use core::f32::consts::PI; use defmt::{error, info}; use embassy_executor::Spawner; use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000}; +use embassy_nrf::pac::ficr::info; use embassy_nrf::{i2s, interrupt}; use {defmt_rtt as _, panic_probe as _}; @@ -49,16 +50,14 @@ async fn main(_spawner: Spawner) { let mut buf = AlignedBuffer([0i16; BUF_SIZE]); let mut carrier = SineOsc::new(); - carrier.set_frequency(300.0, inv_sample_rate); + carrier.set_frequency(240.0, inv_sample_rate); - let mut modulator = SineOsc::new(); - modulator.set_frequency(0.01, inv_sample_rate); - modulator.set_amplitude(0.2); + // let mut modulator = SineOsc::new(); + // modulator.set_frequency(0.01, inv_sample_rate); + // modulator.set_amplitude(0.2); - i2s.set_tx_enabled(true); - i2s.start(); - - loop { + let mut lastf = 0.0; + let mut generate = |buf: &mut [i16]| { for sample in buf.as_mut().chunks_mut(2) { let signal = carrier.generate(); // let modulation = bipolar_to_unipolar(modulator.generate()); @@ -67,8 +66,18 @@ async fn main(_spawner: Spawner) { let value = (i16::MAX as f32 * signal) as i16; sample[0] = value; sample[1] = value; - // info!("{}", signal); } + }; + + generate(buf.as_mut().as_mut_slice()); + + i2s.set_tx_enabled(true); + i2s.start(); + + loop { + // info!("--"); + + generate(buf.as_mut().as_mut_slice()); if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { error!("{}", err); -- cgit From dca11095e2f41d50dbc96d48474a64d9198728c4 Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Sun, 13 Nov 2022 01:49:55 +0100 Subject: Disable UARTE in embassy-nrf::init --- examples/nrf/src/bin/spis.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/spis.rs b/examples/nrf/src/bin/spis.rs index dade5fcbd..fe3b0c53d 100644 --- a/examples/nrf/src/bin/spis.rs +++ b/examples/nrf/src/bin/spis.rs @@ -17,9 +17,11 @@ async fn main(_spawner: Spawner) { let mut spis = Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default()); loop { - let mut buf = [0_u8; 64]; - if let Ok(n) = spis.read(&mut buf).await { - info!("RX: {:?}", buf[..n]); + let mut rx_buf = [0_u8; 64]; + let tx_buf = [1_u8, 2, 3, 4, 5, 6, 7, 8]; + if let Ok((n_rx, n_tx)) = spis.transfer(&mut rx_buf, &tx_buf).await { + info!("RX: {:?}", rx_buf[..n_rx]); + info!("TX: {:?}", tx_buf[..n_tx]); } } } -- cgit From 17857bc18fee95be07ee0c51687d2eb109e5aea6 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sun, 13 Nov 2022 02:12:58 +0100 Subject: Minor changes --- examples/nrf/src/bin/i2s.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 7fb1ecb84..33b5398d9 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) { let irq = interrupt::take!(I2S); 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); - const BUF_SAMPLES: usize = 250; + const BUF_SAMPLES: usize = 500; const BUF_SIZE: usize = BUF_SAMPLES * 2; let mut buf = AlignedBuffer([0i16; BUF_SIZE]); @@ -56,7 +56,6 @@ async fn main(_spawner: Spawner) { // modulator.set_frequency(0.01, inv_sample_rate); // modulator.set_amplitude(0.2); - let mut lastf = 0.0; let mut generate = |buf: &mut [i16]| { for sample in buf.as_mut().chunks_mut(2) { let signal = carrier.generate(); @@ -71,12 +70,14 @@ async fn main(_spawner: Spawner) { generate(buf.as_mut().as_mut_slice()); + if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { + error!("{}", err); + } + i2s.set_tx_enabled(true); i2s.start(); loop { - // info!("--"); - generate(buf.as_mut().as_mut_slice()); if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { -- cgit From 4fe834db2f491179edf28105faf79d6fc89785c6 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sun, 13 Nov 2022 02:48:07 +0100 Subject: Mono channels --- examples/nrf/src/bin/i2s.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 33b5398d9..4b6f8ab2d 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -8,7 +8,7 @@ use core::f32::consts::PI; use defmt::{error, info}; use embassy_executor::Spawner; -use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000}; +use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000, Channels}; use embassy_nrf::pac::ficr::info; use embassy_nrf::{i2s, interrupt}; use {defmt_rtt as _, panic_probe as _}; @@ -37,6 +37,7 @@ async fn main(_spawner: Spawner) { freq: MckFreq::_32MDiv10, ratio: Ratio::_256x, }; // 12500 Hz + config.channels = Channels::Left; let sample_rate = config.mode.sample_rate().expect("I2S Master"); let inv_sample_rate = 1.0 / sample_rate as f32; @@ -46,25 +47,24 @@ async fn main(_spawner: Spawner) { 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); const BUF_SAMPLES: usize = 500; - const BUF_SIZE: usize = BUF_SAMPLES * 2; + const BUF_SIZE: usize = BUF_SAMPLES; let mut buf = AlignedBuffer([0i16; BUF_SIZE]); let mut carrier = SineOsc::new(); - carrier.set_frequency(240.0, inv_sample_rate); + carrier.set_frequency(16.0, inv_sample_rate); // let mut modulator = SineOsc::new(); // modulator.set_frequency(0.01, inv_sample_rate); // modulator.set_amplitude(0.2); let mut generate = |buf: &mut [i16]| { - for sample in buf.as_mut().chunks_mut(2) { + for sample in buf.as_mut() { let signal = carrier.generate(); // let modulation = bipolar_to_unipolar(modulator.generate()); // carrier.set_frequency(200.0 + 100.0 * modulation, inv_sample_rate); // carrier.set_amplitude((modulation); let value = (i16::MAX as f32 * signal) as i16; - sample[0] = value; - sample[1] = value; + *sample = value; } }; -- cgit From eba42cb5f4c4dc1be54c27729325e982d85fc8b0 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Sun, 13 Nov 2022 22:15:19 +0100 Subject: embassy-nrf: Add TWIS module --- examples/nrf/src/bin/twis.rs | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 examples/nrf/src/bin/twis.rs (limited to 'examples') diff --git a/examples/nrf/src/bin/twis.rs b/examples/nrf/src/bin/twis.rs new file mode 100644 index 000000000..f85173c08 --- /dev/null +++ b/examples/nrf/src/bin/twis.rs @@ -0,0 +1,45 @@ +//! TWIS example + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_nrf::interrupt; +use embassy_nrf::twis::{self, Command, Twis}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + + let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); + let mut config = twis::Config::default(); + // Set i2c address + config.addr0 = 0x55; + let mut i2c = Twis::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); + + info!("Listening..."); + loop { + let mut buf = [0u8; 16]; + let tx_buf = [1, 2, 3, 4, 5, 6, 7, 8]; + match i2c.listen(&mut buf).await { + Ok(Command::Read) => { + info!("Got READ command. Writing back data:\n{:?}\n", tx_buf); + if let Err(e) = i2c.write(&tx_buf).await { + error!("{:?}", e); + } + } + Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]), + Ok(Command::WriteRead(n)) => { + info!("Got WRITE/READ command with data:\n{:?}", buf[..n]); + info!("Writing back data:\n{:?}\n", tx_buf); + if let Err(e) = i2c.write(&tx_buf).await { + error!("{:?}", e); + } + } + Err(e) => error!("{:?}", e), + } + } +} -- cgit From 43c1afb6a6b31a60f43b2faf8ca93bf5129e4d68 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Mon, 14 Nov 2022 11:22:14 +0100 Subject: Return number of bytes written, add address match getter --- examples/nrf/src/bin/twis.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/twis.rs b/examples/nrf/src/bin/twis.rs index f85173c08..a34bb2711 100644 --- a/examples/nrf/src/bin/twis.rs +++ b/examples/nrf/src/bin/twis.rs @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); let mut config = twis::Config::default(); // Set i2c address - config.addr0 = 0x55; + config.address0 = 0x55; let mut i2c = Twis::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); info!("Listening..."); -- cgit From eb149a0bd42d7690e78e5f2b37579c1f68be613b Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 15 Nov 2022 16:12:07 +0100 Subject: embassy-rp: Add basic ADC module --- examples/rp/src/bin/adc.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 examples/rp/src/bin/adc.rs (limited to 'examples') diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs new file mode 100644 index 000000000..2a9e93732 --- /dev/null +++ b/examples/rp/src/bin/adc.rs @@ -0,0 +1,33 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_rp::adc::{Adc, Config}; +use embassy_rp::interrupt; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let irq = interrupt::take!(ADC_IRQ_FIFO); + let mut adc = Adc::new(p.ADC, irq, Config::default()); + + let mut p26 = p.PIN_26; + let mut p27 = p.PIN_27; + let mut p28 = p.PIN_28; + + loop { + let level = adc.read(&mut p26).await; + info!("Pin 26 ADC: {}", level); + let level = adc.read(&mut p27).await; + info!("Pin 27 ADC: {}", level); + let level = adc.read(&mut p28).await; + info!("Pin 28 ADC: {}", level); + let temp = adc.read_temperature().await; + info!("Temp: {}", temp); + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From 1ed260b1055fad6ddd89053ae3e1997ec34c6332 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Thu, 17 Nov 2022 00:19:22 +0100 Subject: Fix buffer overruns --- examples/nrf/src/bin/i2s.rs | 86 +++++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 34 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs index 4b6f8ab2d..9b3144f24 100644 --- a/examples/nrf/src/bin/i2s.rs +++ b/examples/nrf/src/bin/i2s.rs @@ -1,14 +1,13 @@ -// Example inspired by RTIC's I2S demo: https://github.com/nrf-rs/nrf-hal/blob/master/examples/i2s-controller-demo/src/main.rs - #![no_std] #![no_main] #![feature(type_alias_impl_trait)] use core::f32::consts::PI; -use defmt::{error, info}; +use defmt::{error, info, trace}; use embassy_executor::Spawner; -use embassy_nrf::i2s::{MckFreq, Mode, Ratio, MODE_MASTER_16000, MODE_MASTER_8000, Channels}; +use embassy_nrf::gpio::{Input, Pin, Pull}; +use embassy_nrf::i2s::{Channels, MckFreq, Mode, Ratio, SampleWidth, MODE_MASTER_32000}; use embassy_nrf::pac::ficr::info; use embassy_nrf::{i2s, interrupt}; use {defmt_rtt as _, panic_probe as _}; @@ -32,60 +31,79 @@ impl AsMut for AlignedBuffer { async fn main(_spawner: Spawner) { let p = embassy_nrf::init(Default::default()); let mut config = i2s::Config::default(); - // config.mode = MODE_MASTER_16000; - config.mode = Mode::Master { - freq: MckFreq::_32MDiv10, - ratio: Ratio::_256x, - }; // 12500 Hz + config.mode = MODE_MASTER_32000; + // config.mode = Mode::Master { + // freq: MckFreq::_32MDiv10, + // ratio: Ratio::_256x, + // }; // 12500 Hz config.channels = Channels::Left; + config.swidth = SampleWidth::_16bit; let sample_rate = config.mode.sample_rate().expect("I2S Master"); let inv_sample_rate = 1.0 / sample_rate as f32; info!("Sample rate: {}", sample_rate); + // Wait for a button press + // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up); + // btn1.wait_for_low().await; + let irq = interrupt::take!(I2S); - 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); + 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).output(); - const BUF_SAMPLES: usize = 500; - const BUF_SIZE: usize = BUF_SAMPLES; - let mut buf = AlignedBuffer([0i16; BUF_SIZE]); + type Sample = i16; + const MAX_UNIPOLAR_VALUE: Sample = (1 << 15) as Sample; + const NUM_SAMPLES: usize = 2000; + let mut buffers: [AlignedBuffer<[Sample; NUM_SAMPLES]>; 3] = [ + AlignedBuffer([0; NUM_SAMPLES]), + AlignedBuffer([0; NUM_SAMPLES]), + AlignedBuffer([0; NUM_SAMPLES]), + ]; let mut carrier = SineOsc::new(); - carrier.set_frequency(16.0, inv_sample_rate); - // let mut modulator = SineOsc::new(); - // modulator.set_frequency(0.01, inv_sample_rate); - // modulator.set_amplitude(0.2); + let mut freq_mod = SineOsc::new(); + freq_mod.set_frequency(8.0, inv_sample_rate); + freq_mod.set_amplitude(1.0); + + let mut amp_mod = SineOsc::new(); + amp_mod.set_frequency(4.0, inv_sample_rate); + amp_mod.set_amplitude(0.5); - let mut generate = |buf: &mut [i16]| { - for sample in buf.as_mut() { + let mut generate = |buf: &mut [Sample]| { + let ptr = buf as *const [Sample] as *const Sample as u32; + trace!("GEN: {}", ptr); + + for sample in &mut buf.as_mut().chunks_mut(1) { let signal = carrier.generate(); - // let modulation = bipolar_to_unipolar(modulator.generate()); - // carrier.set_frequency(200.0 + 100.0 * modulation, inv_sample_rate); - // carrier.set_amplitude((modulation); - let value = (i16::MAX as f32 * signal) as i16; - *sample = value; + let freq_modulation = bipolar_to_unipolar(freq_mod.generate()); + carrier.set_frequency(220.0 + 220.0 * freq_modulation, inv_sample_rate); + let amp_modulation = bipolar_to_unipolar(amp_mod.generate()); + carrier.set_amplitude(amp_modulation); + let value = (MAX_UNIPOLAR_VALUE as f32 * signal) as Sample; + sample[0] = value; } }; - generate(buf.as_mut().as_mut_slice()); + generate(buffers[0].as_mut().as_mut_slice()); + generate(buffers[1].as_mut().as_mut_slice()); - if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { - error!("{}", err); - } - - i2s.set_tx_enabled(true); - i2s.start(); + i2s.start(buffers[0].as_ref().as_slice()).expect("I2S Start"); + let mut index = 1; loop { - generate(buf.as_mut().as_mut_slice()); - - if let Err(err) = i2s.tx(buf.as_ref().as_slice()).await { + if let Err(err) = i2s.send(buffers[index].as_ref().as_slice()).await { error!("{}", err); } + + index += 1; + if index >= 3 { + index = 0; + } + generate(buffers[index].as_mut().as_mut_slice()); } } +#[derive(Clone)] struct SineOsc { amplitude: f32, modulo: f32, -- cgit From a444a65ebfcea674e74dcedc7f26a7aa37f59c69 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 17 Nov 2022 09:26:15 +0100 Subject: feat: embassy-usb-logger and example for rpi pico * Add embassy-usb-logger which allows logging over USB for any device implementing embassy-usb * Add example using logger for rpi pico. --- examples/rp/Cargo.toml | 2 ++ examples/rp/src/bin/usb_logger.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 examples/rp/src/bin/usb_logger.rs (limited to 'examples') diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 31f688305..250228862 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -13,6 +13,7 @@ embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt" embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } +embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } defmt = "0.3" defmt-rtt = "0.3" @@ -32,6 +33,7 @@ embedded-hal-async = { version = "0.1.0-alpha.3" } embedded-io = { version = "0.3.1", features = ["async", "defmt"] } embedded-storage = { version = "0.3" } static_cell = "1.0.0" +log = "0.4" [profile.release] debug = true diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs new file mode 100644 index 000000000..52417a02e --- /dev/null +++ b/examples/rp/src/bin/usb_logger.rs @@ -0,0 +1,30 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Spawner; +use embassy_rp::interrupt; +use embassy_rp::peripherals::USB; +use embassy_rp::usb::Driver; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::task] +async fn logger_task(driver: Driver<'static, USB>) { + embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let irq = interrupt::take!(USBCTRL_IRQ); + let driver = Driver::new(p.USB, irq); + spawner.spawn(logger_task(driver)).unwrap(); + + let mut counter = 0; + loop { + counter += 1; + log::info!("Tick {}", counter); + Timer::after(Duration::from_secs(1)).await; + } +} -- cgit From 6b88057aef79e32a66c9c99cf048f905d10c2d3a Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sat, 19 Nov 2022 00:29:05 +0100 Subject: Add missing parts and Cleanup --- examples/nrf/src/bin/i2s-generate.rs | 143 ++++++++++++++++++++++++++++++ examples/nrf/src/bin/i2s.rs | 164 ----------------------------------- 2 files changed, 143 insertions(+), 164 deletions(-) create mode 100644 examples/nrf/src/bin/i2s-generate.rs delete mode 100644 examples/nrf/src/bin/i2s.rs (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s-generate.rs b/examples/nrf/src/bin/i2s-generate.rs new file mode 100644 index 000000000..f59b63ce6 --- /dev/null +++ b/examples/nrf/src/bin/i2s-generate.rs @@ -0,0 +1,143 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::f32::consts::PI; + +use defmt::{error, info}; +use embassy_executor::Spawner; +use embassy_nrf::i2s::{self, Sample as _}; +use embassy_nrf::interrupt; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + + let mut config = i2s::Config::default(); + config.mode = i2s::ExactSampleRate::_50000.into(); + config.channels = i2s::Channels::Left; + config.swidth = i2s::SampleWidth::_16bit; + let sample_rate = config.mode.sample_rate().expect("I2S Master"); + let inv_sample_rate = 1.0 / sample_rate as f32; + + info!("Sample rate: {}", sample_rate); + + // Wait for a button press + // use embassy_nrf::gpio::{Input, Pin, Pull}; + // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up); + // btn1.wait_for_low().await; + + let irq = interrupt::take!(I2S); + 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(); + + type Sample = i16; + const NUM_SAMPLES: usize = 6000; + + let mut buffers: [i2s::AlignedBuffer; 3] = [ + i2s::AlignedBuffer::default(), + i2s::AlignedBuffer::default(), + i2s::AlignedBuffer::default(), + ]; + + let mut carrier = SineOsc::new(); + + let mut freq_mod = SineOsc::new(); + freq_mod.set_frequency(8.0, inv_sample_rate); + freq_mod.set_amplitude(1.0); + + let mut amp_mod = SineOsc::new(); + amp_mod.set_frequency(16.0, inv_sample_rate); + amp_mod.set_amplitude(0.5); + + let mut generate = |buf: &mut [Sample]| { + for sample in &mut buf.chunks_mut(1) { + let freq_modulation = bipolar_to_unipolar(freq_mod.generate()); + carrier.set_frequency(220.0 + 440.0 * freq_modulation, inv_sample_rate); + let amp_modulation = bipolar_to_unipolar(amp_mod.generate()); + carrier.set_amplitude(amp_modulation); + let signal = carrier.generate(); + let value = (Sample::SCALE as f32 * signal) as Sample; + sample[0] = value; + } + }; + + generate(buffers[0].as_mut()); + generate(buffers[1].as_mut()); + + i2s.start(buffers[0].as_ref()).await.expect("I2S Start"); + + let mut index = 1; + loop { + if let Err(err) = i2s.send(buffers[index].as_ref()).await { + error!("{}", err); + } + + index += 1; + if index >= 3 { + index = 0; + } + generate(buffers[index].as_mut()); + } +} + +#[derive(Clone)] +struct SineOsc { + amplitude: f32, + modulo: f32, + phase_inc: f32, +} + +impl SineOsc { + const B: f32 = 4.0 / PI; + const C: f32 = -4.0 / (PI * PI); + const P: f32 = 0.225; + + pub fn new() -> Self { + Self { + amplitude: 1.0, + modulo: 0.0, + phase_inc: 0.0, + } + } + + pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) { + self.phase_inc = freq * inv_sample_rate; + } + + pub fn set_amplitude(&mut self, amplitude: f32) { + self.amplitude = amplitude; + } + + pub fn generate(&mut self) -> f32 { + let signal = self.parabolic_sin(self.modulo); + self.modulo += self.phase_inc; + if self.modulo < 0.0 { + self.modulo += 1.0; + } else if self.modulo > 1.0 { + self.modulo -= 1.0; + } + signal * self.amplitude + } + + fn parabolic_sin(&mut self, modulo: f32) -> f32 { + let angle = PI - modulo * 2.0 * PI; + let y = Self::B * angle + Self::C * angle * abs(angle); + Self::P * (y * abs(y) - y) + y + } +} + +#[inline] +fn abs(value: f32) -> f32 { + if value < 0.0 { + -value + } else { + value + } +} + +#[inline] +fn bipolar_to_unipolar(value: f32) -> f32 { + (value + 1.0) / 2.0 +} diff --git a/examples/nrf/src/bin/i2s.rs b/examples/nrf/src/bin/i2s.rs deleted file mode 100644 index 9b3144f24..000000000 --- a/examples/nrf/src/bin/i2s.rs +++ /dev/null @@ -1,164 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use core::f32::consts::PI; - -use defmt::{error, info, trace}; -use embassy_executor::Spawner; -use embassy_nrf::gpio::{Input, Pin, Pull}; -use embassy_nrf::i2s::{Channels, MckFreq, Mode, Ratio, SampleWidth, MODE_MASTER_32000}; -use embassy_nrf::pac::ficr::info; -use embassy_nrf::{i2s, interrupt}; -use {defmt_rtt as _, panic_probe as _}; - -#[repr(align(4))] -pub struct AlignedBuffer(T); - -impl AsRef for AlignedBuffer { - fn as_ref(&self) -> &T { - &self.0 - } -} - -impl AsMut for AlignedBuffer { - fn as_mut(&mut self) -> &mut T { - &mut self.0 - } -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = embassy_nrf::init(Default::default()); - let mut config = i2s::Config::default(); - config.mode = MODE_MASTER_32000; - // config.mode = Mode::Master { - // freq: MckFreq::_32MDiv10, - // ratio: Ratio::_256x, - // }; // 12500 Hz - config.channels = Channels::Left; - config.swidth = SampleWidth::_16bit; - let sample_rate = config.mode.sample_rate().expect("I2S Master"); - let inv_sample_rate = 1.0 / sample_rate as f32; - - info!("Sample rate: {}", sample_rate); - - // Wait for a button press - // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up); - // btn1.wait_for_low().await; - - let irq = interrupt::take!(I2S); - 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).output(); - - type Sample = i16; - const MAX_UNIPOLAR_VALUE: Sample = (1 << 15) as Sample; - const NUM_SAMPLES: usize = 2000; - let mut buffers: [AlignedBuffer<[Sample; NUM_SAMPLES]>; 3] = [ - AlignedBuffer([0; NUM_SAMPLES]), - AlignedBuffer([0; NUM_SAMPLES]), - AlignedBuffer([0; NUM_SAMPLES]), - ]; - - let mut carrier = SineOsc::new(); - - let mut freq_mod = SineOsc::new(); - freq_mod.set_frequency(8.0, inv_sample_rate); - freq_mod.set_amplitude(1.0); - - let mut amp_mod = SineOsc::new(); - amp_mod.set_frequency(4.0, inv_sample_rate); - amp_mod.set_amplitude(0.5); - - let mut generate = |buf: &mut [Sample]| { - let ptr = buf as *const [Sample] as *const Sample as u32; - trace!("GEN: {}", ptr); - - for sample in &mut buf.as_mut().chunks_mut(1) { - let signal = carrier.generate(); - let freq_modulation = bipolar_to_unipolar(freq_mod.generate()); - carrier.set_frequency(220.0 + 220.0 * freq_modulation, inv_sample_rate); - let amp_modulation = bipolar_to_unipolar(amp_mod.generate()); - carrier.set_amplitude(amp_modulation); - let value = (MAX_UNIPOLAR_VALUE as f32 * signal) as Sample; - sample[0] = value; - } - }; - - generate(buffers[0].as_mut().as_mut_slice()); - generate(buffers[1].as_mut().as_mut_slice()); - - i2s.start(buffers[0].as_ref().as_slice()).expect("I2S Start"); - - let mut index = 1; - loop { - if let Err(err) = i2s.send(buffers[index].as_ref().as_slice()).await { - error!("{}", err); - } - - index += 1; - if index >= 3 { - index = 0; - } - generate(buffers[index].as_mut().as_mut_slice()); - } -} - -#[derive(Clone)] -struct SineOsc { - amplitude: f32, - modulo: f32, - phase_inc: f32, -} - -impl SineOsc { - const B: f32 = 4.0 / PI; - const C: f32 = -4.0 / (PI * PI); - const P: f32 = 0.225; - - pub fn new() -> Self { - Self { - amplitude: 1.0, - modulo: 0.0, - phase_inc: 0.0, - } - } - - pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) { - self.phase_inc = freq * inv_sample_rate; - } - - pub fn set_amplitude(&mut self, amplitude: f32) { - self.amplitude = amplitude; - } - - pub fn generate(&mut self) -> f32 { - let signal = self.parabolic_sin(self.modulo); - self.modulo += self.phase_inc; - if self.modulo < 0.0 { - self.modulo += 1.0; - } else if self.modulo > 1.0 { - self.modulo -= 1.0; - } - signal * self.amplitude - } - - fn parabolic_sin(&mut self, modulo: f32) -> f32 { - let angle = PI - modulo * 2.0 * PI; - let y = Self::B * angle + Self::C * angle * abs(angle); - Self::P * (y * abs(y) - y) + y - } -} - -#[inline] -fn abs(value: f32) -> f32 { - if value < 0.0 { - -value - } else { - value - } -} - -#[inline] -fn bipolar_to_unipolar(value: f32) -> f32 { - (value + 1.0) / 2.0 -} -- cgit From 16838f8a66d8a3b74f0fe1ab9124532226e7166a Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sat, 19 Nov 2022 00:32:09 +0100 Subject: Fix format --- examples/nrf/src/bin/i2s-generate.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s-generate.rs b/examples/nrf/src/bin/i2s-generate.rs index f59b63ce6..c2b5578f3 100644 --- a/examples/nrf/src/bin/i2s-generate.rs +++ b/examples/nrf/src/bin/i2s-generate.rs @@ -29,8 +29,7 @@ async fn main(_spawner: Spawner) { // btn1.wait_for_low().await; let irq = interrupt::take!(I2S); - 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(); + 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(); type Sample = i16; const NUM_SAMPLES: usize = 6000; -- cgit From 15a93246d6bb3e0bea268ff919bca073a9890247 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Sat, 19 Nov 2022 19:18:20 +0100 Subject: Buffer management in line with other peripherals. Constructor and config redesign --- examples/nrf/src/bin/i2s-generate.rs | 142 ------------------------------ examples/nrf/src/bin/i2s_waveform.rs | 161 +++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 142 deletions(-) delete mode 100644 examples/nrf/src/bin/i2s-generate.rs create mode 100644 examples/nrf/src/bin/i2s_waveform.rs (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s-generate.rs b/examples/nrf/src/bin/i2s-generate.rs deleted file mode 100644 index c2b5578f3..000000000 --- a/examples/nrf/src/bin/i2s-generate.rs +++ /dev/null @@ -1,142 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use core::f32::consts::PI; - -use defmt::{error, info}; -use embassy_executor::Spawner; -use embassy_nrf::i2s::{self, Sample as _}; -use embassy_nrf::interrupt; -use {defmt_rtt as _, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = embassy_nrf::init(Default::default()); - - let mut config = i2s::Config::default(); - config.mode = i2s::ExactSampleRate::_50000.into(); - config.channels = i2s::Channels::Left; - config.swidth = i2s::SampleWidth::_16bit; - let sample_rate = config.mode.sample_rate().expect("I2S Master"); - let inv_sample_rate = 1.0 / sample_rate as f32; - - info!("Sample rate: {}", sample_rate); - - // Wait for a button press - // use embassy_nrf::gpio::{Input, Pin, Pull}; - // let mut btn1 = Input::new(p.P1_00.degrade(), Pull::Up); - // btn1.wait_for_low().await; - - let irq = interrupt::take!(I2S); - 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(); - - type Sample = i16; - const NUM_SAMPLES: usize = 6000; - - let mut buffers: [i2s::AlignedBuffer; 3] = [ - i2s::AlignedBuffer::default(), - i2s::AlignedBuffer::default(), - i2s::AlignedBuffer::default(), - ]; - - let mut carrier = SineOsc::new(); - - let mut freq_mod = SineOsc::new(); - freq_mod.set_frequency(8.0, inv_sample_rate); - freq_mod.set_amplitude(1.0); - - let mut amp_mod = SineOsc::new(); - amp_mod.set_frequency(16.0, inv_sample_rate); - amp_mod.set_amplitude(0.5); - - let mut generate = |buf: &mut [Sample]| { - for sample in &mut buf.chunks_mut(1) { - let freq_modulation = bipolar_to_unipolar(freq_mod.generate()); - carrier.set_frequency(220.0 + 440.0 * freq_modulation, inv_sample_rate); - let amp_modulation = bipolar_to_unipolar(amp_mod.generate()); - carrier.set_amplitude(amp_modulation); - let signal = carrier.generate(); - let value = (Sample::SCALE as f32 * signal) as Sample; - sample[0] = value; - } - }; - - generate(buffers[0].as_mut()); - generate(buffers[1].as_mut()); - - i2s.start(buffers[0].as_ref()).await.expect("I2S Start"); - - let mut index = 1; - loop { - if let Err(err) = i2s.send(buffers[index].as_ref()).await { - error!("{}", err); - } - - index += 1; - if index >= 3 { - index = 0; - } - generate(buffers[index].as_mut()); - } -} - -#[derive(Clone)] -struct SineOsc { - amplitude: f32, - modulo: f32, - phase_inc: f32, -} - -impl SineOsc { - const B: f32 = 4.0 / PI; - const C: f32 = -4.0 / (PI * PI); - const P: f32 = 0.225; - - pub fn new() -> Self { - Self { - amplitude: 1.0, - modulo: 0.0, - phase_inc: 0.0, - } - } - - pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) { - self.phase_inc = freq * inv_sample_rate; - } - - pub fn set_amplitude(&mut self, amplitude: f32) { - self.amplitude = amplitude; - } - - pub fn generate(&mut self) -> f32 { - let signal = self.parabolic_sin(self.modulo); - self.modulo += self.phase_inc; - if self.modulo < 0.0 { - self.modulo += 1.0; - } else if self.modulo > 1.0 { - self.modulo -= 1.0; - } - signal * self.amplitude - } - - fn parabolic_sin(&mut self, modulo: f32) -> f32 { - let angle = PI - modulo * 2.0 * PI; - let y = Self::B * angle + Self::C * angle * abs(angle); - Self::P * (y * abs(y) - y) + y - } -} - -#[inline] -fn abs(value: f32) -> f32 { - if value < 0.0 { - -value - } else { - value - } -} - -#[inline] -fn bipolar_to_unipolar(value: f32) -> f32 { - (value + 1.0) / 2.0 -} diff --git a/examples/nrf/src/bin/i2s_waveform.rs b/examples/nrf/src/bin/i2s_waveform.rs new file mode 100644 index 000000000..81858ff59 --- /dev/null +++ b/examples/nrf/src/bin/i2s_waveform.rs @@ -0,0 +1,161 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::f32::consts::PI; + +use defmt::{error, info}; +use embassy_executor::Spawner; +use embassy_nrf::i2s::{self, Channels, Config, MasterClock, Sample as _, SampleWidth, I2S}; +use embassy_nrf::interrupt; +use {defmt_rtt as _, panic_probe as _}; + +type Sample = i16; + +const NUM_SAMPLES: usize = 6000; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + + let master_clock: MasterClock = i2s::ExactSampleRate::_50000.into(); + + let sample_rate = master_clock.sample_rate(); + info!("Sample rate: {}", sample_rate); + + let config = Config::default() + .sample_width(SampleWidth::_16bit) + .channels(Channels::MonoLeft); + + let irq = interrupt::take!(I2S); + 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); + + let mut buffers: [i2s::AlignedBuffer; 3] = [ + i2s::AlignedBuffer::default(), + i2s::AlignedBuffer::default(), + i2s::AlignedBuffer::default(), + ]; + + let mut waveform = Waveform::new(1.0 / sample_rate as f32); + + waveform.process(&mut buffers[0]); + waveform.process(&mut buffers[1]); + + output_stream.start(&buffers[0]).await.expect("I2S Start"); + + let mut index = 1; + loop { + if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { + error!("{}", err); + } + + index += 1; + if index >= 3 { + index = 0; + } + + waveform.process(&mut buffers[index]); + } +} + +struct Waveform { + inv_sample_rate: f32, + carrier: SineOsc, + freq_mod: SineOsc, + amp_mod: SineOsc, +} + +impl Waveform { + fn new(inv_sample_rate: f32) -> Self { + let carrier = SineOsc::new(); + + let mut freq_mod = SineOsc::new(); + freq_mod.set_frequency(8.0, inv_sample_rate); + freq_mod.set_amplitude(1.0); + + let mut amp_mod = SineOsc::new(); + amp_mod.set_frequency(16.0, inv_sample_rate); + amp_mod.set_amplitude(0.5); + + Self { + inv_sample_rate, + carrier, + freq_mod, + amp_mod, + } + } + + fn process(&mut self, buf: &mut [Sample]) { + for sample in buf.chunks_mut(1) { + let freq_modulation = bipolar_to_unipolar(self.freq_mod.generate()); + self.carrier + .set_frequency(110.0 + 440.0 * freq_modulation, self.inv_sample_rate); + + let amp_modulation = bipolar_to_unipolar(self.amp_mod.generate()); + self.carrier.set_amplitude(amp_modulation); + + let signal = self.carrier.generate(); + + sample[0] = (Sample::SCALE as f32 * signal) as Sample; + } + } +} + +struct SineOsc { + amplitude: f32, + modulo: f32, + phase_inc: f32, +} + +impl SineOsc { + const B: f32 = 4.0 / PI; + const C: f32 = -4.0 / (PI * PI); + const P: f32 = 0.225; + + pub fn new() -> Self { + Self { + amplitude: 1.0, + modulo: 0.0, + phase_inc: 0.0, + } + } + + pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) { + self.phase_inc = freq * inv_sample_rate; + } + + pub fn set_amplitude(&mut self, amplitude: f32) { + self.amplitude = amplitude; + } + + pub fn generate(&mut self) -> f32 { + let signal = self.parabolic_sin(self.modulo); + self.modulo += self.phase_inc; + if self.modulo < 0.0 { + self.modulo += 1.0; + } else if self.modulo > 1.0 { + self.modulo -= 1.0; + } + signal * self.amplitude + } + + fn parabolic_sin(&mut self, modulo: f32) -> f32 { + let angle = PI - modulo * 2.0 * PI; + let y = Self::B * angle + Self::C * angle * abs(angle); + Self::P * (y * abs(y) - y) + y + } +} + +#[inline] +fn abs(value: f32) -> f32 { + if value < 0.0 { + -value + } else { + value + } +} + +#[inline] +fn bipolar_to_unipolar(value: f32) -> f32 { + (value + 1.0) / 2.0 +} -- cgit From cf900a8a3f048428cc1209763f4188366818ab8a Mon Sep 17 00:00:00 2001 From: Henrik Alsér Date: Tue, 22 Nov 2022 22:10:04 +0100 Subject: Rename write to respond_to_read --- examples/nrf/src/bin/twis.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/twis.rs b/examples/nrf/src/bin/twis.rs index a34bb2711..54cba9494 100644 --- a/examples/nrf/src/bin/twis.rs +++ b/examples/nrf/src/bin/twis.rs @@ -22,20 +22,21 @@ async fn main(_spawner: Spawner) { info!("Listening..."); loop { + let response = [1, 2, 3, 4, 5, 6, 7, 8]; + // This buffer is used if the i2c master performs a Write or WriteRead let mut buf = [0u8; 16]; - let tx_buf = [1, 2, 3, 4, 5, 6, 7, 8]; match i2c.listen(&mut buf).await { Ok(Command::Read) => { - info!("Got READ command. Writing back data:\n{:?}\n", tx_buf); - if let Err(e) = i2c.write(&tx_buf).await { + info!("Got READ command. Respond with data:\n{:?}\n", response); + if let Err(e) = i2c.respond_to_read(&response).await { error!("{:?}", e); } } Ok(Command::Write(n)) => info!("Got WRITE command with data:\n{:?}\n", buf[..n]), Ok(Command::WriteRead(n)) => { info!("Got WRITE/READ command with data:\n{:?}", buf[..n]); - info!("Writing back data:\n{:?}\n", tx_buf); - if let Err(e) = i2c.write(&tx_buf).await { + info!("Respond with data:\n{:?}\n", response); + if let Err(e) = i2c.respond_to_read(&response).await { error!("{:?}", e); } } -- cgit From 28991d77941da2d77fcb242e025af06ceb936460 Mon Sep 17 00:00:00 2001 From: "@imrank03" Date: Wed, 23 Nov 2022 17:30:58 +0530 Subject: added blinky example for stm32f0 --- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f0/src/bin/blinky.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 examples/stm32f0/src/bin/blinky.rs (limited to 'examples') diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index a56c546ee..d4dc81cb5 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -15,5 +15,5 @@ panic-probe = "0.3" embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f030f4", "time-driver-any"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any"] } diff --git a/examples/stm32f0/src/bin/blinky.rs b/examples/stm32f0/src/bin/blinky.rs new file mode 100644 index 000000000..9f923399c --- /dev/null +++ b/examples/stm32f0/src/bin/blinky.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +// main is itself an async function. +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + //PA5 is the onboard LED on the Nucleo F091RC + let mut led = Output::new(p.PA5, Level::High, Speed::Low); + + loop { + info!("high"); + led.set_high(); + Timer::after(Duration::from_millis(300)).await; + + info!("low"); + led.set_low(); + Timer::after(Duration::from_millis(300)).await; + } +} -- cgit From 5aad2129ef2eefd6ea2f2bda05f6c0e6172ba1c8 Mon Sep 17 00:00:00 2001 From: "@imrank03" Date: Wed, 23 Nov 2022 17:51:43 +0530 Subject: added the runner for stm32f091rc --- examples/stm32f0/.cargo/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/stm32f0/.cargo/config.toml b/examples/stm32f0/.cargo/config.toml index d1b1cd0bf..16abc29bc 100644 --- a/examples/stm32f0/.cargo/config.toml +++ b/examples/stm32f0/.cargo/config.toml @@ -1,5 +1,5 @@ [target.thumbv6m-none-eabi] -runner = 'probe-run --chip STM32F030F4Px' +runner = 'probe-run --chip STM32F091RCTX' [build] target = "thumbv6m-none-eabi" -- cgit From 1e2fb0459d8546ba658bb9fe150be5f1f537b48e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 21 Nov 2022 23:31:31 +0100 Subject: Switch to async-fn-in-trait --- examples/nrf/Cargo.toml | 4 ++-- examples/rp/Cargo.toml | 4 ++-- examples/std/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 6 +++--- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 5 ----- 10 files changed, 13 insertions(+), 18 deletions(-) (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index c633f82f5..64dbc663e 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -17,7 +17,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } -embedded-io = "0.3.1" +embedded-io = "0.4.0" embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } @@ -34,4 +34,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa rand = { version = "0.8.4", default-features = false } embedded-storage = "0.3.0" usbd-hid = "0.6.0" -serde = { version = "1.0.136", default-features = false } +serde = { version = "1.0.136", default-features = false } \ No newline at end of file diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 250228862..364f738dd 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -29,8 +29,8 @@ display-interface = "0.4.1" byte-slice-cast = { version = "1.2.0", default-features = false } embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } -embedded-hal-async = { version = "0.1.0-alpha.3" } -embedded-io = { version = "0.3.1", features = ["async", "defmt"] } +embedded-hal-async = "0.2.0-alpha.0" +embedded-io = { version = "0.4.0", features = ["async", "defmt"] } embedded-storage = { version = "0.3" } static_cell = "1.0.0" log = "0.4" diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 790258382..41680f8f4 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -9,7 +9,7 @@ embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["lo embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] } embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dhcpv4", "pool-16"] } -embedded-io = { version = "0.3.1", features = ["async", "std", "futures"] } +embedded-io = { version = "0.4.0", features = ["async", "std", "futures"] } critical-section = { version = "1.1", features = ["std"] } async-io = "1.6.0" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index b05457eaa..594b61612 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -17,7 +17,7 @@ defmt-rtt = "0.3" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" -embedded-io = "0.3.1" +embedded-io = "0.4.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index b14afd2fe..caabe068e 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } -embedded-io = { version = "0.3.1", features = ["async"] } +embedded-io = { version = "0.4.0", features = ["async"] } defmt = "0.3" defmt-rtt = "0.3" diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 0dccff6e8..de9459998 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -10,7 +10,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16", "unstable-traits"] } -embedded-io = { version = "0.3.1", features = ["async"] } +embedded-io = { version = "0.4.0", features = ["async"] } defmt = "0.3" defmt-rtt = "0.3" @@ -19,8 +19,8 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } -embedded-hal-async = { version = "=0.1.0-alpha.3" } -embedded-nal-async = "0.2.0" +embedded-hal-async = { version = "=0.2.0-alpha.0" } +embedded-nal-async = { git = "https://github.com/embassy-rs/embedded-nal.git", rev = "691601e550449a53ab3a7c5eaa0411aee0a64ed0" } panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 8b00773be..f5fd18f11 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -22,7 +22,7 @@ defmt = "0.3" defmt-rtt = "0.3" embedded-storage = "0.3.0" -embedded-io = "0.3.1" +embedded-io = "0.4.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 83d456b26..9092d85c7 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -20,7 +20,7 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } -embedded-hal-async = { version = "=0.1.0-alpha.3" } +embedded-hal-async = { version = "=0.2.0-alpha.0" } panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 848723f8b..376e9e519 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -26,5 +26,5 @@ embedded-hal = "0.2.6" futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } rand_core = { version = "0.6.3", default-features = false } -embedded-io = { version = "0.3.1", features = ["async"] } +embedded-io = { version = "0.4.0", features = ["async"] } static_cell = "1.0" diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 3d704011b..1cf1078dc 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -21,8 +21,3 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } micromath = "2.0.0" - -#[patch.crates-io] -#defmt = { git="https://github.com/knurling-rs/defmt.git" } -#defmt-rtt = { git="https://github.com/knurling-rs/defmt.git" } - -- cgit From 199504be564b231154e07c58bcc52b11afdc9fe7 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Tue, 29 Nov 2022 01:09:47 +0100 Subject: Optimization to be able to work with only 2 buffers --- examples/nrf/src/bin/i2s_waveform.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s_waveform.rs b/examples/nrf/src/bin/i2s_waveform.rs index 81858ff59..13b1300ea 100644 --- a/examples/nrf/src/bin/i2s_waveform.rs +++ b/examples/nrf/src/bin/i2s_waveform.rs @@ -12,7 +12,8 @@ use {defmt_rtt as _, panic_probe as _}; type Sample = i16; -const NUM_SAMPLES: usize = 6000; +const NUM_BUFFERS: usize = 2; +const NUM_SAMPLES: usize = 50; #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -30,31 +31,27 @@ async fn main(_spawner: Spawner) { let irq = interrupt::take!(I2S); 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); - let mut buffers: [i2s::AlignedBuffer; 3] = [ - i2s::AlignedBuffer::default(), - i2s::AlignedBuffer::default(), - i2s::AlignedBuffer::default(), - ]; + let mut buffers: [i2s::AlignedBuffer; NUM_BUFFERS] = + [i2s::AlignedBuffer::default(); NUM_BUFFERS]; let mut waveform = Waveform::new(1.0 / sample_rate as f32); waveform.process(&mut buffers[0]); - waveform.process(&mut buffers[1]); output_stream.start(&buffers[0]).await.expect("I2S Start"); let mut index = 1; loop { + waveform.process(&mut buffers[index]); + if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { error!("{}", err); } index += 1; - if index >= 3 { + if index >= NUM_BUFFERS { index = 0; } - - waveform.process(&mut buffers[index]); } } @@ -67,7 +64,8 @@ struct Waveform { impl Waveform { fn new(inv_sample_rate: f32) -> Self { - let carrier = SineOsc::new(); + let mut carrier = SineOsc::new(); + carrier.set_frequency(110.0, inv_sample_rate); let mut freq_mod = SineOsc::new(); freq_mod.set_frequency(8.0, inv_sample_rate); -- cgit From 3135ad016d580a2a5912c4ade8a1f61c1d0375d7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 29 Nov 2022 12:05:46 +0100 Subject: Bump embedded-nal-async to 0.3.0 --- examples/stm32h7/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index de9459998..f665f7c14 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -20,7 +20,7 @@ cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } embedded-hal-async = { version = "=0.2.0-alpha.0" } -embedded-nal-async = { git = "https://github.com/embassy-rs/embedded-nal.git", rev = "691601e550449a53ab3a7c5eaa0411aee0a64ed0" } +embedded-nal-async = "0.3.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } -- cgit From 1dcb0ea1f5dbd9357c7c05627f06abbcaaedd134 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 29 Nov 2022 21:15:24 +0100 Subject: Bump defmt-rtt to 0.4 --- examples/boot/application/nrf/Cargo.toml | 2 +- examples/boot/application/stm32f3/Cargo.toml | 2 +- examples/boot/application/stm32f7/Cargo.toml | 2 +- examples/boot/application/stm32h7/Cargo.toml | 2 +- examples/boot/application/stm32l0/Cargo.toml | 2 +- examples/boot/application/stm32l1/Cargo.toml | 2 +- examples/boot/application/stm32l4/Cargo.toml | 2 +- examples/boot/application/stm32wl/Cargo.toml | 2 +- examples/boot/bootloader/nrf/Cargo.toml | 2 +- examples/boot/bootloader/stm32/Cargo.toml | 2 +- examples/nrf/Cargo.toml | 2 +- examples/rp/Cargo.toml | 2 +- examples/stm32f0/Cargo.toml | 2 +- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f2/Cargo.toml | 2 +- examples/stm32f3/Cargo.toml | 2 +- examples/stm32f4/Cargo.toml | 2 +- examples/stm32f7/Cargo.toml | 2 +- examples/stm32g0/Cargo.toml | 2 +- examples/stm32g4/Cargo.toml | 2 +- examples/stm32h7/Cargo.toml | 2 +- examples/stm32l0/Cargo.toml | 2 +- examples/stm32l1/Cargo.toml | 2 +- examples/stm32l4/Cargo.toml | 2 +- examples/stm32l5/Cargo.toml | 2 +- examples/stm32u5/Cargo.toml | 2 +- examples/stm32wb/Cargo.toml | 2 +- examples/stm32wl/Cargo.toml | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) (limited to 'examples') diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml index a5d82b601..1e7a5a84b 100644 --- a/examples/boot/application/nrf/Cargo.toml +++ b/examples/boot/application/nrf/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-nrf = { version = "0.1.0", path = "../../../../embassy-boot/nrf" } embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml index 3a1843562..aa279fb76 100644 --- a/examples/boot/application/stm32f3/Cargo.toml +++ b/examples/boot/application/stm32f3/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml index 8d9c4490e..1ec0643a6 100644 --- a/examples/boot/application/stm32f7/Cargo.toml +++ b/examples/boot/application/stm32f7/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml index b4314aa72..a4eefe2a5 100644 --- a/examples/boot/application/stm32h7/Cargo.toml +++ b/examples/boot/application/stm32h7/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml index a17d336a6..36eada29b 100644 --- a/examples/boot/application/stm32l0/Cargo.toml +++ b/examples/boot/application/stm32l0/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml index 683f2c860..67efda748 100644 --- a/examples/boot/application/stm32l1/Cargo.toml +++ b/examples/boot/application/stm32l1/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml index b879c0d76..4b2e02dd2 100644 --- a/examples/boot/application/stm32l4/Cargo.toml +++ b/examples/boot/application/stm32l4/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml index e3bc0e49c..fecbfc51d 100644 --- a/examples/boot/application/stm32wl/Cargo.toml +++ b/examples/boot/application/stm32wl/Cargo.toml @@ -13,7 +13,7 @@ embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32 embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } panic-reset = { version = "0.1.1" } embedded-hal = { version = "0.2.6" } diff --git a/examples/boot/bootloader/nrf/Cargo.toml b/examples/boot/bootloader/nrf/Cargo.toml index b417a40d1..8a6f53643 100644 --- a/examples/boot/bootloader/nrf/Cargo.toml +++ b/examples/boot/bootloader/nrf/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } embassy-nrf = { path = "../../../../embassy-nrf", default-features = false, features = ["nightly"] } embassy-boot-nrf = { path = "../../../../embassy-boot/nrf", default-features = false } diff --git a/examples/boot/bootloader/stm32/Cargo.toml b/examples/boot/bootloader/stm32/Cargo.toml index 4ddd1c99c..be659e02a 100644 --- a/examples/boot/bootloader/stm32/Cargo.toml +++ b/examples/boot/bootloader/stm32/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" [dependencies] defmt = { version = "0.3", optional = true } -defmt-rtt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } embassy-stm32 = { path = "../../../../embassy-stm32", default-features = false, features = ["nightly"] } embassy-boot-stm32 = { path = "../../../../embassy-boot/stm32", default-features = false } diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 64dbc663e..8b95ac3a6 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -24,7 +24,7 @@ lorawan-device = { version = "0.8.0", default-features = false, features = ["asy lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" static_cell = "1.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 364f738dd..60a8ba94d 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -16,7 +16,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index a56c546ee..8f4100488 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -10,7 +10,7 @@ license = "MIT OR Apache-2.0" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" panic-probe = "0.3" embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 6be131f30..53f369b3a 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -13,7 +13,7 @@ embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defm embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index f6adda2a3..afaf9a0c9 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 27188dd19..69ebef786 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -13,7 +13,7 @@ embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defm embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 594b61612..62d3f08df 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -12,7 +12,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index caabe068e..f4d674cdc 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -13,7 +13,7 @@ embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp embedded-io = { version = "0.4.0", features = ["async"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index f5673718d..e7273c9fc 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index ecda28805..8a57a8ef0 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -12,7 +12,7 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [" embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index f665f7c14..11ce35053 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -13,7 +13,7 @@ embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp embedded-io = { version = "0.4.0", features = ["async"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index f5fd18f11..86933a629 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -19,7 +19,7 @@ lorawan-device = { version = "0.8.0", default-features = false, features = ["asy lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" embedded-storage = "0.3.0" embedded-io = "0.4.0" diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index 9460febf5..6e3b2103c 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 9092d85c7..45d3dd366 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -14,7 +14,7 @@ embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 376e9e519..73ad50787 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -17,7 +17,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } usbd-hid = "0.6.0" defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" panic-probe = { version = "0.3", features = ["print-defmt"] } cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index 1cf1078dc..d88fdda50 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 5b96fa191..e27b4527c 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -11,7 +11,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55cc", "time-driver-any", "exti"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index c827d2b71..690481bbf 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -15,7 +15,7 @@ lorawan-device = { version = "0.8.0", default-features = false, features = ["asy lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"] } defmt = "0.3" -defmt-rtt = "0.3" +defmt-rtt = "0.4" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.0" -- cgit From bb89a2341cca1aad79bc6d5f3532008541c9e428 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Thu, 1 Dec 2022 18:26:22 +0100 Subject: feat: embassy-boot for rp2040 Add embassy-boot support for RP2040, with examples for the Raspberry Pi Pico. Co-authored-by: Mathias Koch --- examples/boot/application/rp/.cargo/config.toml | 12 ++++++ examples/boot/application/rp/Cargo.toml | 33 ++++++++++++++++ examples/boot/application/rp/README.md | 28 +++++++++++++ examples/boot/application/rp/build.rs | 35 +++++++++++++++++ examples/boot/application/rp/memory.x | 15 +++++++ examples/boot/application/rp/src/bin/a.rs | 52 +++++++++++++++++++++++++ examples/boot/application/rp/src/bin/b.rs | 23 +++++++++++ examples/boot/bootloader/rp/.cargo/config.toml | 8 ++++ examples/boot/bootloader/rp/Cargo.toml | 29 ++++++++++++++ examples/boot/bootloader/rp/README.md | 17 ++++++++ examples/boot/bootloader/rp/build.rs | 28 +++++++++++++ examples/boot/bootloader/rp/memory.x | 19 +++++++++ examples/boot/bootloader/rp/src/main.rs | 51 ++++++++++++++++++++++++ 13 files changed, 350 insertions(+) create mode 100644 examples/boot/application/rp/.cargo/config.toml create mode 100644 examples/boot/application/rp/Cargo.toml create mode 100644 examples/boot/application/rp/README.md create mode 100644 examples/boot/application/rp/build.rs create mode 100644 examples/boot/application/rp/memory.x create mode 100644 examples/boot/application/rp/src/bin/a.rs create mode 100644 examples/boot/application/rp/src/bin/b.rs create mode 100644 examples/boot/bootloader/rp/.cargo/config.toml create mode 100644 examples/boot/bootloader/rp/Cargo.toml create mode 100644 examples/boot/bootloader/rp/README.md create mode 100644 examples/boot/bootloader/rp/build.rs create mode 100644 examples/boot/bootloader/rp/memory.x create mode 100644 examples/boot/bootloader/rp/src/main.rs (limited to 'examples') diff --git a/examples/boot/application/rp/.cargo/config.toml b/examples/boot/application/rp/.cargo/config.toml new file mode 100644 index 000000000..edbd0a867 --- /dev/null +++ b/examples/boot/application/rp/.cargo/config.toml @@ -0,0 +1,12 @@ +[unstable] +build-std = ["core"] +build-std-features = ["panic_immediate_abort"] + +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-run --chip RP2040" + +[build] +target = "thumbv6m-none-eabi" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/boot/application/rp/Cargo.toml b/examples/boot/application/rp/Cargo.toml new file mode 100644 index 000000000..8d826790b --- /dev/null +++ b/examples/boot/application/rp/Cargo.toml @@ -0,0 +1,33 @@ +[package] +edition = "2021" +name = "embassy-boot-rp-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" } +embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } +embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } +embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] } +embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp" } +embassy-embedded-hal = { version = "0.1.0", path = "../../../../embassy-embedded-hal" } + +defmt = "0.3" +defmt-rtt = "0.4" +panic-probe = { version = "0.3", features = ["print-defmt"], optional = true } +panic-reset = { version = "0.1.1", optional = true } +embedded-hal = { version = "0.2.6" } + +cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } +cortex-m-rt = "0.7.0" + +[features] +default = ["panic-reset"] +debug = [ + "embassy-rp/defmt", + "embassy-boot-rp/defmt", + "panic-probe" +] + +[profile.release] +debug = true diff --git a/examples/boot/application/rp/README.md b/examples/boot/application/rp/README.md new file mode 100644 index 000000000..41304c526 --- /dev/null +++ b/examples/boot/application/rp/README.md @@ -0,0 +1,28 @@ +# Examples using bootloader + +Example for Raspberry Pi Pico demonstrating the bootloader. The example consists of application binaries, 'a' +which waits for 5 seconds before flashing the 'b' binary, which blinks the LED. + +NOTE: The 'b' binary does not mark the new binary as active, so if you reset the device, it will roll back to the 'a' binary before automatically updating it again. + +## Prerequisites + +* `cargo-binutils` +* `cargo-flash` +* `embassy-boot-rp` + +## Usage + +``` +# Flash bootloader +cargo flash --manifest-path ../../bootloader/rp/Cargo.toml --release --chip RP2040 + +# Build 'b' +cargo build --release --bin b + +# Generate binary for 'b' +cargo objcopy --release --bin b -- -O binary b.bin + +# Flash `a` (which includes b.bin) +cargo flash --release --bin a --chip RP2040 +``` diff --git a/examples/boot/application/rp/build.rs b/examples/boot/application/rp/build.rs new file mode 100644 index 000000000..30691aa97 --- /dev/null +++ b/examples/boot/application/rp/build.rs @@ -0,0 +1,35 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/boot/application/rp/memory.x b/examples/boot/application/rp/memory.x new file mode 100644 index 000000000..c19473114 --- /dev/null +++ b/examples/boot/application/rp/memory.x @@ -0,0 +1,15 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 + BOOTLOADER_STATE : ORIGIN = 0x10006000, LENGTH = 4K + FLASH : ORIGIN = 0x10007000, LENGTH = 512K + DFU : ORIGIN = 0x10087000, LENGTH = 516K + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOT2); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOT2); + +__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOT2); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOT2); diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs new file mode 100644 index 000000000..3736c9141 --- /dev/null +++ b/examples/boot/application/rp/src/bin/a.rs @@ -0,0 +1,52 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt_rtt as _; +use embassy_boot_rp::*; +use embassy_executor::Spawner; +use embassy_rp::flash::Flash; +use embassy_rp::gpio::{Level, Output}; +use embassy_time::{Duration, Timer}; +#[cfg(feature = "panic-probe")] +use panic_probe as _; +#[cfg(feature = "panic-reset")] +use panic_reset as _; + +static APP_B: &[u8] = include_bytes!("../../b.bin"); +const FLASH_SIZE: usize = 2 * 1024 * 1024; + +#[embassy_executor::main] +async fn main(_s: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut flash: Flash<_, FLASH_SIZE> = Flash::new(p.FLASH); + + let mut updater = FirmwareUpdater::default(); + + Timer::after(Duration::from_secs(5)).await; + led.set_high(); + let mut offset = 0; + let mut buf: AlignedBuffer<4096> = AlignedBuffer([0; 4096]); + defmt::info!("preparing update"); + let mut writer = updater + .prepare_update_blocking(&mut flash) + .map_err(|e| defmt::warn!("E: {:?}", defmt::Debug2Format(&e))) + .unwrap(); + defmt::info!("writer created, starting write"); + for chunk in APP_B.chunks(4096) { + buf.0[..chunk.len()].copy_from_slice(chunk); + defmt::info!("writing block at offset {}", offset); + writer + .write_block_blocking(offset, &buf.0[..], &mut flash, 256) + .unwrap(); + offset += chunk.len(); + } + defmt::info!("firmware written, marking update"); + updater.mark_updated_blocking(&mut flash, &mut buf.0[..1]).unwrap(); + Timer::after(Duration::from_secs(2)).await; + led.set_low(); + defmt::info!("update marked, resetting"); + cortex_m::peripheral::SCB::sys_reset(); +} diff --git a/examples/boot/application/rp/src/bin/b.rs b/examples/boot/application/rp/src/bin/b.rs new file mode 100644 index 000000000..47dec329c --- /dev/null +++ b/examples/boot/application/rp/src/bin/b.rs @@ -0,0 +1,23 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Spawner; +use embassy_rp::gpio; +use embassy_time::{Duration, Timer}; +use gpio::{Level, Output}; +use {defmt_rtt as _, panic_reset as _}; + +#[embassy_executor::main] +async fn main(_s: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut led = Output::new(p.PIN_25, Level::Low); + + loop { + led.set_high(); + Timer::after(Duration::from_millis(100)).await; + + led.set_low(); + Timer::after(Duration::from_millis(100)).await; + } +} diff --git a/examples/boot/bootloader/rp/.cargo/config.toml b/examples/boot/bootloader/rp/.cargo/config.toml new file mode 100644 index 000000000..18bd4dfe8 --- /dev/null +++ b/examples/boot/bootloader/rp/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-run --chip RP2040" + +[build] +target = "thumbv6m-none-eabi" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/boot/bootloader/rp/Cargo.toml b/examples/boot/bootloader/rp/Cargo.toml new file mode 100644 index 000000000..580ced22e --- /dev/null +++ b/examples/boot/bootloader/rp/Cargo.toml @@ -0,0 +1,29 @@ +[package] +edition = "2021" +name = "rp-bootloader-example" +version = "0.1.0" +description = "Example bootloader for RP2040 chips" +license = "MIT OR Apache-2.0" + +[dependencies] +defmt = { version = "0.3", optional = true } +defmt-rtt = { version = "0.4", optional = true } + +embassy-rp = { path = "../../../../embassy-rp", default-features = false, features = ["nightly"] } +embassy-boot-rp = { path = "../../../../embassy-boot/rp", default-features = false } +cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } +cortex-m-rt = { version = "0.7" } +embedded-storage = "0.3.0" +embedded-storage-async = "0.3.0" +cfg-if = "1.0.0" + +[features] +defmt = [ + "dep:defmt", + "embassy-boot-rp/defmt", + "embassy-rp/defmt", +] +debug = ["defmt-rtt", "defmt"] + +[profile.release] +debug = true diff --git a/examples/boot/bootloader/rp/README.md b/examples/boot/bootloader/rp/README.md new file mode 100644 index 000000000..064e87273 --- /dev/null +++ b/examples/boot/bootloader/rp/README.md @@ -0,0 +1,17 @@ +# Bootloader for RP2040 + +The bootloader uses `embassy-boot` to interact with the flash. + +# Usage + +Flashing the bootloader + +``` +cargo flash --release --chip RP2040 +``` + +To debug, use `cargo run` and enable the debug feature flag + +``` rust +cargo run --release --features debug +``` diff --git a/examples/boot/bootloader/rp/build.rs b/examples/boot/bootloader/rp/build.rs new file mode 100644 index 000000000..c201704ad --- /dev/null +++ b/examples/boot/bootloader/rp/build.rs @@ -0,0 +1,28 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tlink-rp.x"); + if env::var("CARGO_FEATURE_DEFMT").is_ok() { + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); + } +} diff --git a/examples/boot/bootloader/rp/memory.x b/examples/boot/bootloader/rp/memory.x new file mode 100644 index 000000000..d6ef38469 --- /dev/null +++ b/examples/boot/bootloader/rp/memory.x @@ -0,0 +1,19 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 + FLASH : ORIGIN = 0x10000100, LENGTH = 24K + BOOTLOADER_STATE : ORIGIN = 0x10006000, LENGTH = 4K + ACTIVE : ORIGIN = 0x10007000, LENGTH = 512K + DFU : ORIGIN = 0x10087000, LENGTH = 516K + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} + +__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOT2); +__bootloader_state_end = ORIGIN(BOOTLOADER_STATE) + LENGTH(BOOTLOADER_STATE) - ORIGIN(BOOT2); + +__bootloader_active_start = ORIGIN(ACTIVE) - ORIGIN(BOOT2); +__bootloader_active_end = ORIGIN(ACTIVE) + LENGTH(ACTIVE) - ORIGIN(BOOT2); + +__bootloader_dfu_start = ORIGIN(DFU) - ORIGIN(BOOT2); +__bootloader_dfu_end = ORIGIN(DFU) + LENGTH(DFU) - ORIGIN(BOOT2); diff --git a/examples/boot/bootloader/rp/src/main.rs b/examples/boot/bootloader/rp/src/main.rs new file mode 100644 index 000000000..5028ec688 --- /dev/null +++ b/examples/boot/bootloader/rp/src/main.rs @@ -0,0 +1,51 @@ +#![no_std] +#![no_main] + +use cortex_m_rt::{entry, exception}; +#[cfg(feature = "defmt")] +use defmt_rtt as _; +use embassy_boot_rp::*; +use embassy_rp::flash::{Flash, ERASE_SIZE}; +use embassy_rp::peripherals::FLASH; + +const FLASH_SIZE: usize = 2 * 1024 * 1024; + +#[entry] +fn main() -> ! { + let p = embassy_rp::init(Default::default()); + + // Uncomment this if you are debugging the bootloader with debugger/RTT attached, + // as it prevents a hard fault when accessing flash 'too early' after boot. + /* + for i in 0..10000000 { + cortex_m::asm::nop(); + } + */ + + let mut bl: BootLoader = BootLoader::default(); + let flash: Flash<'_, FLASH, FLASH_SIZE> = Flash::new(p.FLASH); + let mut flash = BootFlash::<_, ERASE_SIZE>::new(flash); + let start = bl.prepare(&mut SingleFlashConfig::new(&mut flash)); + core::mem::drop(flash); + + unsafe { bl.load(start) } +} + +#[no_mangle] +#[cfg_attr(target_os = "none", link_section = ".HardFault.user")] +unsafe extern "C" fn HardFault() { + cortex_m::peripheral::SCB::sys_reset(); +} + +#[exception] +unsafe fn DefaultHandler(_: i16) -> ! { + const SCB_ICSR: *const u32 = 0xE000_ED04 as *const u32; + let irqn = core::ptr::read_volatile(SCB_ICSR) as u8 as i16 - 16; + + panic!("DefaultHandler #{:?}", irqn); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + cortex_m::asm::udf(); +} -- cgit From 5fdd521a767fd8825a2d55d6b833fd99627353d7 Mon Sep 17 00:00:00 2001 From: Christian Perez Llamas <932644+chris-zen@users.noreply.github.com> Date: Thu, 8 Dec 2022 20:22:50 +0100 Subject: Move the responsibility to manage buffers to the I2S stream --- examples/nrf/src/bin/i2s_effect.rs | 117 +++++++++++++++++++++++++++++++++++ examples/nrf/src/bin/i2s_monitor.rs | 115 ++++++++++++++++++++++++++++++++++ examples/nrf/src/bin/i2s_waveform.rs | 26 +++----- 3 files changed, 241 insertions(+), 17 deletions(-) create mode 100644 examples/nrf/src/bin/i2s_effect.rs create mode 100644 examples/nrf/src/bin/i2s_monitor.rs (limited to 'examples') diff --git a/examples/nrf/src/bin/i2s_effect.rs b/examples/nrf/src/bin/i2s_effect.rs new file mode 100644 index 000000000..3cca005b1 --- /dev/null +++ b/examples/nrf/src/bin/i2s_effect.rs @@ -0,0 +1,117 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::f32::consts::PI; + +use defmt::{error, info}; +use embassy_executor::Spawner; +use embassy_nrf::i2s::{self, Channels, Config, MasterClock, MultiBuffering, Sample as _, SampleWidth, I2S}; +use embassy_nrf::interrupt; +use {defmt_rtt as _, panic_probe as _}; + +type Sample = i16; + +const NUM_BUFFERS: usize = 2; +const NUM_SAMPLES: usize = 4; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + + let master_clock: MasterClock = i2s::ExactSampleRate::_50000.into(); + + let sample_rate = master_clock.sample_rate(); + info!("Sample rate: {}", sample_rate); + + let config = Config::default() + .sample_width(SampleWidth::_16bit) + .channels(Channels::MonoLeft); + + let irq = interrupt::take!(I2S); + let buffers_out = MultiBuffering::::new(); + let buffers_in = MultiBuffering::::new(); + let mut full_duplex_stream = I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).full_duplex( + p.P0_29, + p.P0_28, + buffers_out, + buffers_in, + ); + + let mut modulator = SineOsc::new(); + modulator.set_frequency(8.0, 1.0 / sample_rate as f32); + modulator.set_amplitude(1.0); + + full_duplex_stream.start().await.expect("I2S Start"); + + loop { + let (buff_out, buff_in) = full_duplex_stream.buffers(); + for i in 0..NUM_SAMPLES { + let modulation = (Sample::SCALE as f32 * bipolar_to_unipolar(modulator.generate())) as Sample; + buff_out[i] = buff_in[i] * modulation; + } + + if let Err(err) = full_duplex_stream.send_and_receive().await { + error!("{}", err); + } + } +} + +struct SineOsc { + amplitude: f32, + modulo: f32, + phase_inc: f32, +} + +impl SineOsc { + const B: f32 = 4.0 / PI; + const C: f32 = -4.0 / (PI * PI); + const P: f32 = 0.225; + + pub fn new() -> Self { + Self { + amplitude: 1.0, + modulo: 0.0, + phase_inc: 0.0, + } + } + + pub fn set_frequency(&mut self, freq: f32, inv_sample_rate: f32) { + self.phase_inc = freq * inv_sample_rate; + } + + pub fn set_amplitude(&mut self, amplitude: f32) { + self.amplitude = amplitude; + } + + pub fn generate(&mut self) -> f32 { + let signal = self.parabolic_sin(self.modulo); + self.modulo += self.phase_inc; + if self.modulo < 0.0 { + self.modulo += 1.0; + } else if self.modulo > 1.0 { + self.modulo -= 1.0; + } + signal * self.amplitude + } + + fn parabolic_sin(&mut self, modulo: f32) -> f32 { + let angle = PI - modulo * 2.0 * PI; + let y = Self::B * angle + Self::C * angle * abs(angle); + Self::P * (y * abs(y) - y) + y + } +} + +#[inline] +fn abs(value: f32) -> f32 { + if value < 0.0 { + -value + } else { + value + } +} + +#[inline] +fn bipolar_to_unipolar(value: f32) -> f32 { + (value + 1.0) / 2.0 +} diff --git a/examples/nrf/src/bin/i2s_monitor.rs b/examples/nrf/src/bin/i2s_monitor.rs new file mode 100644 index 000000000..48eb7d581 --- /dev/null +++ b/examples/nrf/src/bin/i2s_monitor.rs @@ -0,0 +1,115 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{debug, error, info}; +use embassy_executor::Spawner; +use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; +use embassy_nrf::interrupt; +use embassy_nrf::pwm::{Prescaler, SimplePwm}; +use {defmt_rtt as _, panic_probe as _}; + +type Sample = i16; + +const NUM_SAMPLES: usize = 500; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_nrf::init(Default::default()); + + let master_clock: MasterClock = i2s::ExactSampleRate::_50000.into(); + + let sample_rate = master_clock.sample_rate(); + info!("Sample rate: {}", sample_rate); + + let config = Config::default() + .sample_width(SampleWidth::_16bit) + .channels(Channels::MonoLeft); + + let irq = interrupt::take!(I2S); + let buffers = DoubleBuffering::::new(); + let mut input_stream = + I2S::master(p.I2S, irq, p.P0_25, p.P0_26, p.P0_27, master_clock, config).input(p.P0_29, buffers); + + // Configure the PWM to use the pins corresponding to the RGB leds + let mut pwm = SimplePwm::new_3ch(p.PWM0, p.P0_23, p.P0_22, p.P0_24); + pwm.set_prescaler(Prescaler::Div1); + pwm.set_max_duty(255); + + let mut rms_online = RmsOnline::::default(); + + input_stream.start().await.expect("I2S Start"); + + loop { + let rms = rms_online.process(input_stream.buffer()); + let rgb = rgb_from_rms(rms); + + debug!("RMS: {}, RGB: {:?}", rms, rgb); + for i in 0..3 { + pwm.set_duty(i, rgb[i].into()); + } + + if let Err(err) = input_stream.receive().await { + error!("{}", err); + } + } +} + +/// RMS from 0.0 until 0.75 will give green with a proportional intensity +/// RMS from 0.75 until 0.9 will give a blend between orange and red proportionally to the intensity +/// RMS above 0.9 will give a red with a proportional intensity +fn rgb_from_rms(rms: f32) -> [u8; 3] { + if rms < 0.75 { + let intensity = rms / 0.75; + [0, (intensity * 165.0) as u8, 0] + } else if rms < 0.9 { + let intensity = (rms - 0.75) / 0.15; + [200, 165 - (165.0 * intensity) as u8, 0] + } else { + let intensity = (rms - 0.9) / 0.1; + [200 + (55.0 * intensity) as u8, 0, 0] + } +} + +pub struct RmsOnline { + pub squares: [f32; N], + pub head: usize, +} + +impl Default for RmsOnline { + fn default() -> Self { + RmsOnline { + squares: [0.0; N], + head: 0, + } + } +} + +impl RmsOnline { + pub fn reset(&mut self) { + self.squares = [0.0; N]; + self.head = 0; + } + + pub fn process(&mut self, buf: &[Sample]) -> f32 { + buf.iter() + .for_each(|sample| self.push(*sample as f32 / Sample::SCALE as f32)); + + let sum_of_squares = self.squares.iter().fold(0.0, |acc, v| acc + *v); + Self::approx_sqrt(sum_of_squares / N as f32) + } + + pub fn push(&mut self, signal: f32) { + let square = signal * signal; + self.squares[self.head] = square; + self.head = (self.head + 1) % N; + } + + /// Approximated sqrt taken from [micromath] + /// + /// [micromath]: https://docs.rs/micromath/latest/src/micromath/float/sqrt.rs.html#11-17 + /// + fn approx_sqrt(value: f32) -> f32 { + f32::from_bits((value.to_bits() + 0x3f80_0000) >> 1) + } +} diff --git a/examples/nrf/src/bin/i2s_waveform.rs b/examples/nrf/src/bin/i2s_waveform.rs index 13b1300ea..1b0e8ebc8 100644 --- a/examples/nrf/src/bin/i2s_waveform.rs +++ b/examples/nrf/src/bin/i2s_waveform.rs @@ -6,13 +6,12 @@ use core::f32::consts::PI; use defmt::{error, info}; use embassy_executor::Spawner; -use embassy_nrf::i2s::{self, Channels, Config, MasterClock, Sample as _, SampleWidth, I2S}; +use embassy_nrf::i2s::{self, Channels, Config, DoubleBuffering, MasterClock, Sample as _, SampleWidth, I2S}; use embassy_nrf::interrupt; use {defmt_rtt as _, panic_probe as _}; type Sample = i16; -const NUM_BUFFERS: usize = 2; const NUM_SAMPLES: usize = 50; #[embassy_executor::main] @@ -29,29 +28,22 @@ async fn main(_spawner: Spawner) { .channels(Channels::MonoLeft); let irq = interrupt::take!(I2S); - 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); - - let mut buffers: [i2s::AlignedBuffer; NUM_BUFFERS] = - [i2s::AlignedBuffer::default(); NUM_BUFFERS]; + let buffers = DoubleBuffering::::new(); + 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, buffers); let mut waveform = Waveform::new(1.0 / sample_rate as f32); - waveform.process(&mut buffers[0]); + waveform.process(output_stream.buffer()); - output_stream.start(&buffers[0]).await.expect("I2S Start"); + output_stream.start().await.expect("I2S Start"); - let mut index = 1; loop { - waveform.process(&mut buffers[index]); + waveform.process(output_stream.buffer()); - if let Err(err) = output_stream.send_from_ram(&buffers[index]).await { + if let Err(err) = output_stream.send().await { error!("{}", err); } - - index += 1; - if index >= NUM_BUFFERS { - index = 0; - } } } @@ -68,7 +60,7 @@ impl Waveform { carrier.set_frequency(110.0, inv_sample_rate); let mut freq_mod = SineOsc::new(); - freq_mod.set_frequency(8.0, inv_sample_rate); + freq_mod.set_frequency(1.0, inv_sample_rate); freq_mod.set_amplitude(1.0); let mut amp_mod = SineOsc::new(); -- cgit