425: Implements continuous sampling for the nRF SAADC r=huntc a=huntc
Implements continuous sampling for the nRF SAADC and also renames `OneShot` to `Saadc`. The one-shot behaviour is retained with the `sample` method and a new `run_sampler` method is provided for efficiently (i.e. zero copying) sampler processing. A double buffer is used for continuously sampling, which is swapped appropriately.
A sample frequency is provided and will set the internal timer of the SAADC when there is just one channel being sampled. Otherwise, PPI will be used to hook up the TIMER peripheral to drive the sampling task. Two methods are provided for this: `run_task_sampler` and `run_task_sampler` with the latter available where the compiler sees that just one channel is configured. Note that we set up the PPI and timer behaviour outside of the `Saadc` for maximum flexibility.
A callback is provided to the `run_sampler` method. This is a synchronous callback that should return in a reasonably short space of time. The SAADC could stall if it does not. A reasonable practice is to perform a small amount of processing within the callback to yield a signal, perhaps via `mpsc`. In the case of `mpsc`, the `try_send` method becomes useful.
A new example has been provided to illustrate continuous sampling, along with multiple channels and external timing:
```rust
#[embassy::main]
async fn main(_spawner: Spawner, mut p: Peripherals) {
let config = Config::default();
let channel_1_config = ChannelConfig::single_ended(&mut p.P0_02);
let channel_2_config = ChannelConfig::single_ended(&mut p.P0_03);
let channel_3_config = ChannelConfig::single_ended(&mut p.P0_04);
let mut saadc = Saadc::new(
p.SAADC,
interrupt::take!(SAADC),
config,
[channel_1_config, channel_2_config, channel_3_config],
);
let mut timer = Timer::new(p.TIMER0);
timer.set_frequency(Frequency::F1MHz);
timer.cc(0).write(100); // We want to sample at 10KHz
timer.cc(0).short_compare_clear();
let mut ppi = Ppi::new(p.PPI_CH0);
ppi.set_event(timer.cc(0).event_compare());
ppi.set_task(saadc.task_sample());
ppi.enable();
timer.start();
let mut bufs = [[[0; 3]; 50]; 2];
let mut c = 0;
let mut a: i32 = 0;
saadc
.run_task_sampler(&mut bufs, move |buf| {
for b in buf {
a += b[0] as i32;
}
c += buf.len();
if c > 10000 {
a = a / c as i32;
info!("channel 1: {=i32}", a);
c = 0;
a = 0;
}
SamplerState::Sampled
})
.await;
}
```
Co-authored-by: huntc <huntchr@gmail.com>
Implements continuous sampling for the nRF SAADC and also renames `OneShot` to `Saadc`. The one-shot behaviour is retained with the `sample` method and a new `run_sampler` method is provided for efficiently (i.e. zero copying) sampler processing. A double buffer is used for continuously sampling, which wlll be swapped once sampling has taken place.
A sample frequency is provided and will set the internal timer of the SAADC when there is just the one channel being sampled. Otherwise, PPI will be used to hook up the TIMER peripheral to drive the sampling task.
One-shot mode now permits the sampling of differential pins, and the sampling of multiple pins simultaneously.
A new ChannelConfig structure has been introduced so that multiple channels can be configured individually. Further, the `sample` method now accepts a buffer into which samples are written.
Along the way, I've reset some default configuration to align with Nordic's settings in their nrfx saadc driver. Specifically, the channel gain defaults to 6 (from 4) and the time defaults to 10us (from 20us).
This crate contains async radio drivers for various lora drivers that
work with embassy timers. The code is imported from Drogue Device (
https://github.com/drogue-iot/drogue-device)
The radio drivers integrate with the async LoRaWAN MAC layer in the
lorawan-device crate.
Also added is an example for the STM32WL55 and for STM32L0 (requires
the LoRa Discovery board) for LoRaWAN. Future work is to make the
underlying radio drivers using fully async SPI when communicating
with the peripheral.
* Adds an executor for WASM runtimes based on wasm_bindgen.
* Add time driver based on JS time handling.
* Add example that can run in browser locally.
* Update to critical-section version that supports 'std' flag
Based on the HAL from stm32wl, the peripheral driver has been
modified to fit into embassy, using the embassy APIs, providing
operation of the radio peripheral.
The initial version does not offer any async APIs, but the example
shows how the radio IRQ can be used to perform async TX of the radio.