make SequenceConfig struct is consistent with other Config structs, that are always non_exhaustive and have a Default
This commit is contained in:
parent
d961fd1015
commit
b726ef1886
@ -12,43 +12,6 @@ use crate::interrupt::Interrupt;
|
||||
use crate::pac;
|
||||
use crate::util::slice_in_ram_or;
|
||||
|
||||
/// PWM Base clock is system clock (16MHz) divided by prescaler
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum Prescaler {
|
||||
Div1,
|
||||
Div2,
|
||||
Div4,
|
||||
Div8,
|
||||
Div16,
|
||||
Div32,
|
||||
Div64,
|
||||
Div128,
|
||||
}
|
||||
|
||||
/// How the sequence values are distributed across the channels
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum SequenceLoad {
|
||||
/// Provided sequence will be used across all channels
|
||||
Common,
|
||||
/// Provided sequence contains grouped values for each channel ex:
|
||||
/// [ch0_0_and_ch1_0, ch2_0_and_ch3_0, ... ch0_n_and_ch1_n, ch2_n_and_ch3_n]
|
||||
Grouped,
|
||||
/// Provided sequence contains individual values for each channel ex:
|
||||
/// [ch0_0, ch1_0, ch2_0, ch3_0... ch0_n, ch1_n, ch2_n, ch3_n]
|
||||
Individual,
|
||||
/// Similar to Individual mode, but only three channels are used. The fourth
|
||||
/// value is loaded into the pulse generator counter as its top value.
|
||||
Waveform,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum CounterMode {
|
||||
/// Up counter (edge-aligned PWM duty cycle)
|
||||
Up,
|
||||
/// Up and down counter (center-aligned PWM duty cycle)
|
||||
UpAndDown,
|
||||
}
|
||||
|
||||
/// Interface to the PWM peripheral
|
||||
pub struct SimplePwm<'d, T: Instance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
@ -58,6 +21,18 @@ pub struct SequencePwm<'d, T: Instance> {
|
||||
phantom: PhantomData<&'d mut T>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// Max Sequence size is 32767
|
||||
SequenceTooLong,
|
||||
/// Min Sequence count is 1
|
||||
SequenceTimesAtLeastOne,
|
||||
/// EasyDMA can only read from data memory, read only buffers in flash will fail.
|
||||
DMABufferNotInDataMemory,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> SequencePwm<'d, T> {
|
||||
/// Creates the interface to a PWM Sequence interface.
|
||||
///
|
||||
@ -69,17 +44,18 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
||||
/// mechanisms) on stack allocated buffers which which have been passed to
|
||||
/// [`new()`](SequencePwm::new).
|
||||
#[allow(unused_unsafe)]
|
||||
pub fn new(
|
||||
pub fn new<'a>(
|
||||
_pwm: impl Unborrow<Target = T> + 'd,
|
||||
ch0: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||
ch1: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||
ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||
ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
|
||||
config: SequenceConfig,
|
||||
sequence: &'a [u16],
|
||||
) -> Result<Self, Error> {
|
||||
slice_in_ram_or(config.sequence, Error::DMABufferNotInDataMemory)?;
|
||||
slice_in_ram_or(sequence, Error::DMABufferNotInDataMemory)?;
|
||||
|
||||
if config.sequence.len() > 32767 {
|
||||
if sequence.len() > 32767 {
|
||||
return Err(Error::SequenceTooLong);
|
||||
}
|
||||
|
||||
@ -120,10 +96,10 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
||||
|
||||
r.seq0
|
||||
.ptr
|
||||
.write(|w| unsafe { w.bits(config.sequence.as_ptr() as u32) });
|
||||
.write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
|
||||
r.seq0
|
||||
.cnt
|
||||
.write(|w| unsafe { w.bits(config.sequence.len() as u32) });
|
||||
.write(|w| unsafe { w.bits(sequence.len() as u32) });
|
||||
r.seq0.refresh.write(|w| unsafe { w.bits(config.refresh) });
|
||||
r.seq0
|
||||
.enddelay
|
||||
@ -131,10 +107,10 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
|
||||
|
||||
r.seq1
|
||||
.ptr
|
||||
.write(|w| unsafe { w.bits(config.sequence.as_ptr() as u32) });
|
||||
.write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
|
||||
r.seq1
|
||||
.cnt
|
||||
.write(|w| unsafe { w.bits(config.sequence.len() as u32) });
|
||||
.write(|w| unsafe { w.bits(sequence.len() as u32) });
|
||||
r.seq1.refresh.write(|w| unsafe { w.bits(config.refresh) });
|
||||
r.seq1
|
||||
.enddelay
|
||||
@ -237,24 +213,15 @@ impl<'a, T: Instance> Drop for SequencePwm<'a, T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum SequenceMode {
|
||||
/// Run sequence n Times total
|
||||
Times(u16),
|
||||
/// Repeat until `stop` is called.
|
||||
Infinite,
|
||||
}
|
||||
|
||||
/// Configure an infinite looping sequence for `simple_playback`
|
||||
pub struct SequenceConfig<'a> {
|
||||
#[non_exhaustive]
|
||||
pub struct SequenceConfig {
|
||||
/// Selects up mode or up-and-down mode for the counter
|
||||
pub counter_mode: CounterMode,
|
||||
/// Top value to be compared against buffer values
|
||||
pub top: u16,
|
||||
/// Configuration for PWM_CLK
|
||||
pub prescaler: Prescaler,
|
||||
/// In ram buffer to be played back
|
||||
pub sequence: &'a [u16],
|
||||
/// How a sequence is read from RAM and is spread to the compare register
|
||||
pub sequence_load: SequenceLoad,
|
||||
/// Number of Times PWM periods to delay between each sequence sample
|
||||
@ -263,16 +230,62 @@ pub struct SequenceConfig<'a> {
|
||||
pub end_delay: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// Max Sequence size is 32767
|
||||
SequenceTooLong,
|
||||
/// Min Sequence size is 1
|
||||
SequenceTimesAtLeastOne,
|
||||
/// EasyDMA can only read from data memory, read only buffers in flash will fail.
|
||||
DMABufferNotInDataMemory,
|
||||
impl Default for SequenceConfig {
|
||||
fn default() -> SequenceConfig {
|
||||
SequenceConfig {
|
||||
counter_mode: CounterMode::Up,
|
||||
top: 1000,
|
||||
prescaler: Prescaler::Div16,
|
||||
sequence_load: SequenceLoad::Common,
|
||||
refresh: 0,
|
||||
end_delay: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum SequenceMode {
|
||||
/// Run sequence n Times total
|
||||
Times(u16),
|
||||
/// Repeat until `stop` is called.
|
||||
Infinite,
|
||||
}
|
||||
|
||||
/// PWM Base clock is system clock (16MHz) divided by prescaler
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum Prescaler {
|
||||
Div1,
|
||||
Div2,
|
||||
Div4,
|
||||
Div8,
|
||||
Div16,
|
||||
Div32,
|
||||
Div64,
|
||||
Div128,
|
||||
}
|
||||
|
||||
/// How the sequence values are distributed across the channels
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum SequenceLoad {
|
||||
/// Provided sequence will be used across all channels
|
||||
Common,
|
||||
/// Provided sequence contains grouped values for each channel ex:
|
||||
/// [ch0_0_and_ch1_0, ch2_0_and_ch3_0, ... ch0_n_and_ch1_n, ch2_n_and_ch3_n]
|
||||
Grouped,
|
||||
/// Provided sequence contains individual values for each channel ex:
|
||||
/// [ch0_0, ch1_0, ch2_0, ch3_0... ch0_n, ch1_n, ch2_n, ch3_n]
|
||||
Individual,
|
||||
/// Similar to Individual mode, but only three channels are used. The fourth
|
||||
/// value is loaded into the pulse generator counter as its top value.
|
||||
Waveform,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum CounterMode {
|
||||
/// Up counter (edge-aligned PWM duty cycle)
|
||||
Up,
|
||||
/// Up and down counter (center-aligned PWM duty cycle)
|
||||
UpAndDown,
|
||||
}
|
||||
|
||||
impl<'d, T: Instance> SimplePwm<'d, T> {
|
||||
|
@ -7,9 +7,7 @@ mod example_common;
|
||||
use defmt::*;
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy_nrf::pwm::{
|
||||
CounterMode, Prescaler, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm,
|
||||
};
|
||||
use embassy_nrf::pwm::{Prescaler, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm};
|
||||
use embassy_nrf::Peripherals;
|
||||
|
||||
#[embassy::main]
|
||||
@ -18,18 +16,19 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
0x8000, 0, 0, 0, 0, 0x8000, 0, 0, 0, 0, 0x8000, 0, 0, 0, 0, 0x8000,
|
||||
];
|
||||
|
||||
let config = SequenceConfig {
|
||||
counter_mode: CounterMode::Up,
|
||||
top: 15625,
|
||||
prescaler: Prescaler::Div128,
|
||||
sequence: &seq_values,
|
||||
sequence_load: SequenceLoad::Individual,
|
||||
refresh: 0,
|
||||
end_delay: 0,
|
||||
};
|
||||
let mut config = SequenceConfig::default();
|
||||
config.top = 15625;
|
||||
config.prescaler = Prescaler::Div128;
|
||||
config.sequence_load = SequenceLoad::Individual;
|
||||
|
||||
let pwm = unwrap!(SequencePwm::new(
|
||||
p.PWM0, p.P0_13, p.P0_15, p.P0_16, p.P0_14, config
|
||||
p.PWM0,
|
||||
p.P0_13,
|
||||
p.P0_15,
|
||||
p.P0_16,
|
||||
p.P0_14,
|
||||
config,
|
||||
&seq_values,
|
||||
));
|
||||
let _ = pwm.start(SequenceMode::Times(5));
|
||||
info!("pwm started!");
|
||||
|
@ -9,9 +9,7 @@ use defmt::*;
|
||||
use embassy::executor::Spawner;
|
||||
use embassy::time::{Duration, Timer};
|
||||
use embassy_nrf::gpio::NoPin;
|
||||
use embassy_nrf::pwm::{
|
||||
CounterMode, Prescaler, SequenceConfig, SequenceLoad, SequenceMode, SequencePwm,
|
||||
};
|
||||
use embassy_nrf::pwm::{CounterMode, SequenceConfig, SequenceMode, SequencePwm};
|
||||
use embassy_nrf::Peripherals;
|
||||
use micromath::F32Ext;
|
||||
|
||||
@ -22,18 +20,18 @@ async fn main(_spawner: Spawner, p: Peripherals) {
|
||||
// probably not best use of resources to create the table at runtime, but makes testing fast
|
||||
let seq_values: [u16; 220] = core::array::from_fn(|n| ((W1 * n as f32).sin() * 10000.0) as u16);
|
||||
|
||||
let config = SequenceConfig {
|
||||
counter_mode: CounterMode::UpAndDown,
|
||||
top: 12000,
|
||||
prescaler: Prescaler::Div16,
|
||||
sequence: &seq_values,
|
||||
sequence_load: SequenceLoad::Common,
|
||||
refresh: 0,
|
||||
end_delay: 0,
|
||||
};
|
||||
let mut config = SequenceConfig::default();
|
||||
config.counter_mode = CounterMode::UpAndDown;
|
||||
config.top = 12000;
|
||||
|
||||
let pwm = unwrap!(SequencePwm::new(
|
||||
p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config
|
||||
p.PWM0,
|
||||
p.P0_13,
|
||||
NoPin,
|
||||
NoPin,
|
||||
NoPin,
|
||||
config,
|
||||
&seq_values
|
||||
));
|
||||
let _ = pwm.start(SequenceMode::Infinite);
|
||||
info!("pwm started!");
|
||||
|
Loading…
Reference in New Issue
Block a user