mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
Add a method to allow setting the PIO's clock divisor without floats (#440)
* pio: Changes `PIOBuilder::clock_divisor` from f32 to fixed point) * pio: mark clock_divisor as deprecated
This commit is contained in:
parent
6d75cd8291
commit
0e2b4cf7be
|
@ -61,10 +61,10 @@ fn main() -> ! {
|
||||||
// Initialize and start PIO
|
// Initialize and start PIO
|
||||||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
let installed = pio.install(&program).unwrap();
|
let installed = pio.install(&program).unwrap();
|
||||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
let (int, frac) = (0, 0); // as slow as possible (0 is interpreted as 65536)
|
||||||
let (sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
let (sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||||
.set_pins(led_pin_id, 1)
|
.set_pins(led_pin_id, 1)
|
||||||
.clock_divisor(div)
|
.clock_divisor_fixed_point(int, frac)
|
||||||
.build(sm0);
|
.build(sm0);
|
||||||
sm.start();
|
sm.start();
|
||||||
|
|
||||||
|
|
|
@ -47,10 +47,10 @@ fn main() -> ! {
|
||||||
// Initialize and start PIO
|
// Initialize and start PIO
|
||||||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
let installed = pio.install(&program.program).unwrap();
|
let installed = pio.install(&program.program).unwrap();
|
||||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
let (int, frac) = (0, 0); // as slow as possible (0 is interpreted as 65536)
|
||||||
let (mut sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
let (mut sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||||
.set_pins(led_pin_id, 1)
|
.set_pins(led_pin_id, 1)
|
||||||
.clock_divisor(div)
|
.clock_divisor_fixed_point(int, frac)
|
||||||
.build(sm0);
|
.build(sm0);
|
||||||
// The GPIO pin needs to be configured as an output.
|
// The GPIO pin needs to be configured as an output.
|
||||||
sm.set_pindirs([(led_pin_id, hal::pio::PinDir::Output)]);
|
sm.set_pindirs([(led_pin_id, hal::pio::PinDir::Output)]);
|
||||||
|
|
|
@ -50,10 +50,10 @@ fn main() -> ! {
|
||||||
// Initialize and start PIO
|
// Initialize and start PIO
|
||||||
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
|
||||||
let installed = pio.install(&program.program).unwrap();
|
let installed = pio.install(&program.program).unwrap();
|
||||||
let div = 0f32; // as slow as possible (0 is interpreted as 65536)
|
let (int, frac) = (0, 0); // as slow as possible (0 is interpreted as 65536)
|
||||||
let (mut sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
let (mut sm, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||||
.side_set_pin_base(led_pin_id)
|
.side_set_pin_base(led_pin_id)
|
||||||
.clock_divisor(div)
|
.clock_divisor_fixed_point(int, frac)
|
||||||
.build(sm0);
|
.build(sm0);
|
||||||
// The GPIO pin needs to be configured as an output.
|
// The GPIO pin needs to be configured as an output.
|
||||||
sm.set_pindirs([(led_pin_id, hal::pio::PinDir::Output)]);
|
sm.set_pindirs([(led_pin_id, hal::pio::PinDir::Output)]);
|
||||||
|
|
|
@ -57,12 +57,12 @@ fn main() -> ! {
|
||||||
// then through a LED. If there is a clock offset, there will be a
|
// then through a LED. If there is a clock offset, there will be a
|
||||||
// short time with a voltage between the pins, so the LED will flash up.
|
// short time with a voltage between the pins, so the LED will flash up.
|
||||||
// With a slow clock this is not visible, so use a reasonably fast clock.
|
// With a slow clock this is not visible, so use a reasonably fast clock.
|
||||||
let div = 256f32;
|
let (int, frac) = (256, 0);
|
||||||
|
|
||||||
let installed = pio.install(&program.program).unwrap();
|
let installed = pio.install(&program.program).unwrap();
|
||||||
let (mut sm0, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
let (mut sm0, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||||
.set_pins(pin0, 1)
|
.set_pins(pin0, 1)
|
||||||
.clock_divisor(div)
|
.clock_divisor_fixed_point(int, frac)
|
||||||
.build(sm0);
|
.build(sm0);
|
||||||
// The GPIO pin needs to be configured as an output.
|
// The GPIO pin needs to be configured as an output.
|
||||||
sm0.set_pindirs([(pin0, hal::pio::PinDir::Output)]);
|
sm0.set_pindirs([(pin0, hal::pio::PinDir::Output)]);
|
||||||
|
@ -72,7 +72,7 @@ fn main() -> ! {
|
||||||
let installed = pio.install(&program.program).unwrap();
|
let installed = pio.install(&program.program).unwrap();
|
||||||
let (mut sm1, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
let (mut sm1, _, _) = rp2040_hal::pio::PIOBuilder::from_program(installed)
|
||||||
.set_pins(pin1, 1)
|
.set_pins(pin1, 1)
|
||||||
.clock_divisor(div)
|
.clock_divisor_fixed_point(int, frac)
|
||||||
.build(sm1);
|
.build(sm1);
|
||||||
// The GPIO pin needs to be configured as an output.
|
// The GPIO pin needs to be configured as an output.
|
||||||
sm1.set_pindirs([(pin1, hal::pio::PinDir::Output)]);
|
sm1.set_pindirs([(pin1, hal::pio::PinDir::Output)]);
|
||||||
|
|
|
@ -471,11 +471,7 @@ impl<SM: ValidStateMachine> UninitStateMachine<SM> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safety: The Send trait assumes this is the only write to sm_clkdiv
|
// Safety: The Send trait assumes this is the only write to sm_clkdiv
|
||||||
fn set_clock_divisor(&self, divisor: f32) {
|
fn set_clock_divisor(&self, int: u16, frac: u8) {
|
||||||
// sm frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256)
|
|
||||||
let int = divisor as u16;
|
|
||||||
let frac = ((divisor - int as f32) * 256.0) as u8;
|
|
||||||
|
|
||||||
self.sm().sm_clkdiv.write(|w| {
|
self.sm().sm_clkdiv.write(|w| {
|
||||||
unsafe {
|
unsafe {
|
||||||
w.int().bits(int);
|
w.int().bits(int);
|
||||||
|
@ -1619,7 +1615,7 @@ impl ShiftDirection {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PIOBuilder<P> {
|
pub struct PIOBuilder<P> {
|
||||||
/// Clock divisor.
|
/// Clock divisor.
|
||||||
clock_divisor: f32,
|
clock_divisor: (u16, u8),
|
||||||
|
|
||||||
/// Program location and configuration.
|
/// Program location and configuration.
|
||||||
program: InstalledProgram<P>,
|
program: InstalledProgram<P>,
|
||||||
|
@ -1688,7 +1684,7 @@ impl<P: PIOExt> PIOBuilder<P> {
|
||||||
/// Additional configuration may be needed in addition to this.
|
/// Additional configuration may be needed in addition to this.
|
||||||
pub fn from_program(p: InstalledProgram<P>) -> Self {
|
pub fn from_program(p: InstalledProgram<P>) -> Self {
|
||||||
PIOBuilder {
|
PIOBuilder {
|
||||||
clock_divisor: 1.0,
|
clock_divisor: (1, 0),
|
||||||
program: p,
|
program: p,
|
||||||
jmp_pin: 0,
|
jmp_pin: 0,
|
||||||
out_sticky: false,
|
out_sticky: false,
|
||||||
|
@ -1771,8 +1767,24 @@ impl<P: PIOExt> PIOBuilder<P> {
|
||||||
///
|
///
|
||||||
/// The is based on the sys_clk. Set 1 for full speed. A clock divisor of `n` will cause the state machine to run 1
|
/// The is based on the sys_clk. Set 1 for full speed. A clock divisor of `n` will cause the state machine to run 1
|
||||||
/// cycle every `n` clock cycles. For small values of `n`, a fractional divisor may introduce unacceptable jitter.
|
/// cycle every `n` clock cycles. For small values of `n`, a fractional divisor may introduce unacceptable jitter.
|
||||||
|
#[deprecated(
|
||||||
|
since = "0.7.0",
|
||||||
|
note = "Pulls in floating points. Use the fixed point alternative: clock_divisor_fixed_point"
|
||||||
|
)]
|
||||||
pub fn clock_divisor(mut self, divisor: f32) -> Self {
|
pub fn clock_divisor(mut self, divisor: f32) -> Self {
|
||||||
self.clock_divisor = divisor;
|
self.clock_divisor = (divisor as u16, (divisor * 256.0) as u8);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The clock is based on the `sys_clk` and will execute an intruction every `int + (frac/256)` ticks.
|
||||||
|
///
|
||||||
|
/// A clock divisor of `n` will cause the state machine to run 1 cycle every `n` clock cycles. If the integer part
|
||||||
|
/// is 0 then the fractional part must be 0. This is interpreted by the device as the integer 65536.
|
||||||
|
///
|
||||||
|
/// For small values of `int`, a fractional divisor may introduce unacceptable jitter.
|
||||||
|
pub fn clock_divisor_fixed_point(mut self, int: u16, frac: u8) -> Self {
|
||||||
|
assert!(int != 0 || frac == 0);
|
||||||
|
self.clock_divisor = (int, frac);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1852,7 +1864,7 @@ impl<P: PIOExt> PIOBuilder<P> {
|
||||||
sm.set_enabled(false);
|
sm.set_enabled(false);
|
||||||
|
|
||||||
// Write all configuration bits
|
// Write all configuration bits
|
||||||
sm.set_clock_divisor(self.clock_divisor);
|
sm.set_clock_divisor(self.clock_divisor.0, self.clock_divisor.1);
|
||||||
|
|
||||||
sm.sm().sm_execctrl.write(|w| {
|
sm.sm().sm_execctrl.write(|w| {
|
||||||
w.side_en().bit(self.program.side_set.optional());
|
w.side_en().bit(self.program.side_set.optional());
|
||||||
|
|
Loading…
Reference in a new issue