aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/pio_programs/clock_divider.rs25
-rw-r--r--embassy-rp/src/pio_programs/hd44780.rs14
-rw-r--r--embassy-rp/src/pio_programs/mod.rs1
-rw-r--r--embassy-rp/src/pio_programs/rotary_encoder.rs10
-rw-r--r--embassy-rp/src/pio_programs/stepper.rs18
5 files changed, 43 insertions, 25 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 3aa54495f..546c85a89 100644
--- a/embassy-rp/src/pio_programs/hd44780.rs
+++ b/embassy-rp/src/pio_programs/hd44780.rs
@@ -1,11 +1,11 @@
1//! [HD44780 display driver](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) 1//! [HD44780 display driver](https://www.sparkfun.com/datasheets/LCD/HD44780.pdf)
2 2
3use crate::clocks::clk_sys_freq;
4use crate::dma::{AnyChannel, Channel}; 3use crate::dma::{AnyChannel, Channel};
5use crate::pio::{ 4use crate::pio::{
6 Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, 5 Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection,
7 StateMachine, 6 StateMachine,
8}; 7};
8use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
9use crate::Peri; 9use crate::Peri;
10 10
11/// 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>)
@@ -136,10 +136,8 @@ impl<'l, P: Instance, const S: usize> PioHD44780<'l, P, S> {
136 let mut cfg = Config::default(); 136 let mut cfg = Config::default();
137 cfg.use_program(&word_prg.prg, &[&e]); 137 cfg.use_program(&word_prg.prg, &[&e]);
138 138
139 // Scale the divider based on system clock frequency 139 // Target 1 MHz PIO clock (each cycle is 1µs)
140 // Original: 125 at 125 MHz (1 MHz PIO clock) 140 cfg.clock_divider = calculate_pio_clock_divider(1_000_000);
141 let word_divider = (clk_sys_freq() / 1_000_000) as u8; // Target 1 MHz PIO clock
142 cfg.clock_divider = word_divider.into();
143 141
144 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); 142 cfg.set_out_pins(&[&db4, &db5, &db6, &db7]);
145 cfg.shift_out = ShiftConfig { 143 cfg.shift_out = ShiftConfig {
@@ -167,10 +165,8 @@ impl<'l, P: Instance, const S: usize> PioHD44780<'l, P, S> {
167 let mut cfg = Config::default(); 165 let mut cfg = Config::default();
168 cfg.use_program(&seq_prg.prg, &[&e]); 166 cfg.use_program(&seq_prg.prg, &[&e]);
169 167
170 // Original: 8 at 125 MHz (~15.6 MHz PIO clock) 168 // Target ~15.6 MHz PIO clock (~64ns/insn)
171 // Comment says ~64ns/insn which is 1/(15.6 MHz) = ~64ns 169 cfg.clock_divider = calculate_pio_clock_divider(15_600_000);
172 let seq_divider = (clk_sys_freq() / 15_600_000) as u8; // Target ~15.6 MHz PIO clock (~64ns/insn)
173 cfg.clock_divider = seq_divider.into();
174 170
175 cfg.set_jmp_pin(&db7); 171 cfg.set_jmp_pin(&db7);
176 cfg.set_set_pins(&[&rs, &rw]); 172 cfg.set_set_pins(&[&rs, &rw]);
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 71567a602..70b3795e9 100644
--- a/embassy-rp/src/pio_programs/rotary_encoder.rs
+++ b/embassy-rp/src/pio_programs/rotary_encoder.rs
@@ -1,12 +1,10 @@
1//! PIO backed quadrature encoder 1//! PIO backed quadrature encoder
2 2
3use fixed::traits::ToFixed;
4
5use crate::clocks::clk_sys_freq;
6use crate::gpio::Pull; 3use crate::gpio::Pull;
7use crate::pio::{ 4use crate::pio::{
8 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine, 5 Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine,
9}; 6};
7use crate::pio_programs::clock_divider::calculate_pio_clock_divider;
10use crate::Peri; 8use crate::Peri;
11 9
12/// This struct represents an Encoder program loaded into pio instruction memory. 10/// This struct represents an Encoder program loaded into pio instruction memory.
@@ -50,10 +48,8 @@ impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> {
50 cfg.fifo_join = FifoJoin::RxOnly; 48 cfg.fifo_join = FifoJoin::RxOnly;
51 cfg.shift_in.direction = ShiftDirection::Left; 49 cfg.shift_in.direction = ShiftDirection::Left;
52 50
53 // Original: 10_000 at 125 MHz (12.5 KHz PIO clock) 51 // Target 12.5 KHz PIO clock
54 // Scale divider to maintain same PIO clock frequency at different system clocks 52 cfg.clock_divider = calculate_pio_clock_divider(12_500);
55 let divider = (clk_sys_freq() as f32 / 12_500.0).to_fixed();
56 cfg.clock_divider = divider;
57 53
58 cfg.use_program(&program.prg, &[]); 54 cfg.use_program(&program.prg, &[]);
59 sm.set_config(&cfg); 55 sm.set_config(&cfg);
diff --git a/embassy-rp/src/pio_programs/stepper.rs b/embassy-rp/src/pio_programs/stepper.rs
index 6878c32f5..0e9a8daf9 100644
--- a/embassy-rp/src/pio_programs/stepper.rs
+++ b/embassy-rp/src/pio_programs/stepper.rs
@@ -2,12 +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::clocks::clk_sys_freq;
10use 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;
11use crate::Peri; 7use crate::Peri;
12 8
13/// 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.
@@ -65,7 +61,9 @@ impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> {
65 sm.set_pin_dirs(Direction::Out, &[&pin0, &pin1, &pin2, &pin3]); 61 sm.set_pin_dirs(Direction::Out, &[&pin0, &pin1, &pin2, &pin3]);
66 let mut cfg = Config::default(); 62 let mut cfg = Config::default();
67 cfg.set_out_pins(&[&pin0, &pin1, &pin2, &pin3]); 63 cfg.set_out_pins(&[&pin0, &pin1, &pin2, &pin3]);
68 cfg.clock_divider = (clk_sys_freq() / (100 * 136)).to_fixed(); 64
65 cfg.clock_divider = calculate_pio_clock_divider(100 * 136);
66
69 cfg.use_program(&program.prg, &[]); 67 cfg.use_program(&program.prg, &[]);
70 sm.set_config(&cfg); 68 sm.set_config(&cfg);
71 sm.set_enable(true); 69 sm.set_enable(true);
@@ -74,9 +72,11 @@ impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> {
74 72
75 /// Set pulse frequency 73 /// Set pulse frequency
76 pub fn set_frequency(&mut self, freq: u32) { 74 pub fn set_frequency(&mut self, freq: u32) {
77 let clock_divider: FixedU32<U8> = (clk_sys_freq() / (freq * 136)).to_fixed(); 75 let clock_divider = calculate_pio_clock_divider(freq * 136);
78 assert!(clock_divider <= 65536, "clkdiv must be <= 65536"); 76 let divider_f32 = clock_divider.to_num::<f32>();
79 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
80 self.sm.set_clock_divider(clock_divider); 80 self.sm.set_clock_divider(clock_divider);
81 self.sm.clkdiv_restart(); 81 self.sm.clkdiv_restart();
82 } 82 }