aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/pio_programs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-rp/src/pio_programs')
-rw-r--r--embassy-rp/src/pio_programs/clock_divider.rs25
-rw-r--r--embassy-rp/src/pio_programs/hd44780.rs11
-rw-r--r--embassy-rp/src/pio_programs/mod.rs1
-rw-r--r--embassy-rp/src/pio_programs/rotary_encoder.rs8
-rw-r--r--embassy-rp/src/pio_programs/stepper.rs17
5 files changed, 49 insertions, 13 deletions
diff --git a/embassy-rp/src/pio_programs/clock_divider.rs b/embassy-rp/src/pio_programs/clock_divider.rs
new file mode 100644
index 000000000..02e353f53
--- /dev/null
+++ b/embassy-rp/src/pio_programs/clock_divider.rs
@@ -0,0 +1,25 @@
1//! Helper functions for calculating PIO clock dividers
2
3use fixed::traits::ToFixed;
4use fixed::types::extra::U8;
5
6use crate::clocks::clk_sys_freq;
7
8/// Calculate a PIO clock divider value based on the desired target frequency.
9///
10/// # Arguments
11///
12/// * `target_hz` - The desired PIO clock frequency in Hz
13///
14/// # Returns
15///
16/// A fixed-point divider value suitable for use in a PIO state machine configuration
17#[inline]
18pub fn calculate_pio_clock_divider(target_hz: u32) -> fixed::FixedU32<U8> {
19 // Requires a non-zero frequency
20 assert!(target_hz > 0, "PIO clock frequency cannot be zero");
21
22 // Calculate the divider
23 let divider = (clk_sys_freq() + target_hz / 2) / target_hz;
24 divider.to_fixed()
25}
diff --git a/embassy-rp/src/pio_programs/hd44780.rs b/embassy-rp/src/pio_programs/hd44780.rs
index 5846a8027..546c85a89 100644
--- a/embassy-rp/src/pio_programs/hd44780.rs
+++ b/embassy-rp/src/pio_programs/hd44780.rs
@@ -5,6 +5,7 @@ use crate::pio::{
5 Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, 5 Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection,
6 StateMachine, 6 StateMachine,
7}; 7};
8use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
8use crate::Peri; 9use crate::Peri;
9 10
10/// This struct represents a HD44780 program that takes command words (<wait:24> <command:4> <0:4>) 11/// This struct represents a HD44780 program that takes command words (<wait:24> <command:4> <0:4>)
@@ -134,7 +135,10 @@ impl<'l, P: Instance, const S: usize> PioHD44780<'l, P, S> {
134 135
135 let mut cfg = Config::default(); 136 let mut cfg = Config::default();
136 cfg.use_program(&word_prg.prg, &[&e]); 137 cfg.use_program(&word_prg.prg, &[&e]);
137 cfg.clock_divider = 125u8.into(); 138
139 // Target 1 MHz PIO clock (each cycle is 1µs)
140 cfg.clock_divider = calculate_pio_clock_divider(1_000_000);
141
138 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); 142 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]);
139 cfg.shift_out = ShiftConfig { 143 cfg.shift_out = ShiftConfig {
140 auto_fill: true, 144 auto_fill: true,
@@ -160,7 +164,10 @@ impl<'l, P: Instance, const S: usize> PioHD44780<'l, P, S> {
160 164
161 let mut cfg = Config::default(); 165 let mut cfg = Config::default();
162 cfg.use_program(&seq_prg.prg, &[&e]); 166 cfg.use_program(&seq_prg.prg, &[&e]);
163 cfg.clock_divider = 8u8.into(); // ~64ns/insn 167
168 // Target ~15.6 MHz PIO clock (~64ns/insn)
169 cfg.clock_divider = calculate_pio_clock_divider(15_600_000);
170
164 cfg.set_jmp_pin(&db7); 171 cfg.set_jmp_pin(&db7);
165 cfg.set_set_pins(&[&rs, &rw]); 172 cfg.set_set_pins(&[&rs, &rw]);
166 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); 173 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]);
diff --git a/embassy-rp/src/pio_programs/mod.rs b/embassy-rp/src/pio_programs/mod.rs
index 74537825b..8eac328b3 100644
--- a/embassy-rp/src/pio_programs/mod.rs
+++ b/embassy-rp/src/pio_programs/mod.rs
@@ -1,5 +1,6 @@
1//! Pre-built pio programs for common interfaces 1//! Pre-built pio programs for common interfaces
2 2
3pub mod clock_divider;
3pub mod hd44780; 4pub mod hd44780;
4pub mod i2s; 5pub mod i2s;
5pub mod onewire; 6pub mod onewire;
diff --git a/embassy-rp/src/pio_programs/rotary_encoder.rs b/embassy-rp/src/pio_programs/rotary_encoder.rs
index e520da8a3..70b3795e9 100644
--- a/embassy-rp/src/pio_programs/rotary_encoder.rs
+++ b/embassy-rp/src/pio_programs/rotary_encoder.rs
@@ -1,11 +1,10 @@
1//! PIO backed quadrature encoder 1//! PIO backed quadrature encoder
2 2
3use fixed::traits::ToFixed;
4
5use crate::gpio::Pull; 3use crate::gpio::Pull;
6use crate::pio::{ 4use crate::pio::{
7 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine, 5 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine,
8}; 6};
7use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
9use crate::Peri; 8use crate::Peri;
10 9
11/// This struct represents an Encoder program loaded into pio instruction memory. 10/// This struct represents an Encoder program loaded into pio instruction memory.
@@ -48,7 +47,10 @@ impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> {
48 cfg.set_in_pins(&[&pin_a, &pin_b]); 47 cfg.set_in_pins(&[&pin_a, &pin_b]);
49 cfg.fifo_join = FifoJoin::RxOnly; 48 cfg.fifo_join = FifoJoin::RxOnly;
50 cfg.shift_in.direction = ShiftDirection::Left; 49 cfg.shift_in.direction = ShiftDirection::Left;
51 cfg.clock_divider = 10_000.to_fixed(); 50
51 // Target 12.5 KHz PIO clock
52 cfg.clock_divider = calculate_pio_clock_divider(12_500);
53
52 cfg.use_program(&program.prg, &[]); 54 cfg.use_program(&program.prg, &[]);
53 sm.set_config(&cfg); 55 sm.set_config(&cfg);
54 sm.set_enable(true); 56 sm.set_enable(true);
diff --git a/embassy-rp/src/pio_programs/stepper.rs b/embassy-rp/src/pio_programs/stepper.rs
index 495191659..0e9a8daf9 100644
--- a/embassy-rp/src/pio_programs/stepper.rs
+++ b/embassy-rp/src/pio_programs/stepper.rs
@@ -2,11 +2,8 @@
2 2
3use core::mem::{self, MaybeUninit}; 3use core::mem::{self, MaybeUninit};
4 4
5use fixed::traits::ToFixed;
6use fixed::types::extra::U8;
7use fixed::FixedU32;
8
9use crate::pio::{Common, Config, Direction, Instance, Irq, LoadedProgram, PioPin, StateMachine}; 5use crate::pio::{Common, Config, Direction, Instance, Irq, LoadedProgram, PioPin, StateMachine};
6use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
10use crate::Peri; 7use crate::Peri;
11 8
12/// This struct represents a Stepper driver program loaded into pio instruction memory. 9/// This struct represents a Stepper driver program loaded into pio instruction memory.
@@ -64,7 +61,9 @@ impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> {
64 sm.set_pin_dirs(Direction::Out, &[&pin0, &pin1, &pin2, &pin3]); 61 sm.set_pin_dirs(Direction::Out, &[&pin0, &pin1, &pin2, &pin3]);
65 let mut cfg = Config::default(); 62 let mut cfg = Config::default();
66 cfg.set_out_pins(&[&pin0, &pin1, &pin2, &pin3]); 63 cfg.set_out_pins(&[&pin0, &pin1, &pin2, &pin3]);
67 cfg.clock_divider = (125_000_000 / (100 * 136)).to_fixed(); 64
65 cfg.clock_divider = calculate_pio_clock_divider(100 * 136);
66
68 cfg.use_program(&program.prg, &[]); 67 cfg.use_program(&program.prg, &[]);
69 sm.set_config(&cfg); 68 sm.set_config(&cfg);
70 sm.set_enable(true); 69 sm.set_enable(true);
@@ -73,9 +72,11 @@ impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> {
73 72
74 /// Set pulse frequency 73 /// Set pulse frequency
75 pub fn set_frequency(&mut self, freq: u32) { 74 pub fn set_frequency(&mut self, freq: u32) {
76 let clock_divider: FixedU32<U8> = (125_000_000 / (freq * 136)).to_fixed(); 75 let clock_divider = calculate_pio_clock_divider(freq * 136);
77 assert!(clock_divider <= 65536, "clkdiv must be <= 65536"); 76 let divider_f32 = clock_divider.to_num::<f32>();
78 assert!(clock_divider >= 1, "clkdiv must be >= 1"); 77 assert!(divider_f32 <= 65536.0, "clkdiv must be <= 65536");
78 assert!(divider_f32 >= 1.0, "clkdiv must be >= 1");
79
79 self.sm.set_clock_divider(clock_divider); 80 self.sm.set_clock_divider(clock_divider);
80 self.sm.clkdiv_restart(); 81 self.sm.clkdiv_restart();
81 } 82 }