diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2023-05-08 09:17:51 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-08 09:17:51 +0000 |
| commit | 79c60f4a7d17613269f795df867c3c83ca90cbcc (patch) | |
| tree | 34d841fd742d6b3e7fa4919a9bd60f5bc67e0afb /examples | |
| parent | a9c7263ba02181fc4d54975a63d8a1e92426dff3 (diff) | |
| parent | db9b8eb88f095687ed624171cf79fbacf06c199a (diff) | |
Merge #1434
1434: rp pio IV (the voyage home) r=Dirbaio a=pennae
this should hopefully be the last entry in this series. after this we'll have a reasonably safe interface to pio, both for configuration and at runtime. pio now looks very much like the other peripherals (though not exactly, seeing how state machines can't be constructed from a config but only have it applied to them later). the generated code for `StateMachine::set_config` is still larger than we'd like (almost 300 bytes at Oz), but it's a great step up in safety from the previous interface at approximately the same code space cost.
Co-authored-by: pennae <[email protected]>
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/rp/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_async.rs | 62 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_dma.rs | 32 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_hd44780.rs | 66 | ||||
| -rw-r--r-- | examples/rp/src/bin/ws2812-pio.rs | 58 |
5 files changed, 100 insertions, 120 deletions
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index 57f6f5c67..d2829df99 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml | |||
| @@ -22,6 +22,8 @@ lorawan = { version = "0.7.3", default-features = false, features = ["default-cr | |||
| 22 | 22 | ||
| 23 | defmt = "0.3" | 23 | defmt = "0.3" |
| 24 | defmt-rtt = "0.4" | 24 | defmt-rtt = "0.4" |
| 25 | fixed = "1.23.1" | ||
| 26 | fixed-macro = "1.2" | ||
| 25 | 27 | ||
| 26 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } | 28 | #cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } |
| 27 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } | 29 | cortex-m = { version = "0.7.6", features = ["inline-asm"] } |
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 4e0ab5e3c..12484e882 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -2,14 +2,16 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_embedded_hal::SetConfig; | ||
| 5 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 6 | use embassy_rp::peripherals::PIO0; | 7 | use embassy_rp::peripherals::PIO0; |
| 7 | use embassy_rp::pio::{Pio, PioCommon, PioIrq, PioPin, PioStateMachine, ShiftDirection}; | 8 | use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; |
| 8 | use embassy_rp::pio_instr_util; | ||
| 9 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 10 | use fixed::traits::ToFixed; | ||
| 11 | use fixed_macro::types::U56F8; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 13 | ||
| 12 | fn setup_pio_task_sm0(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachine<PIO0, 0>, pin: impl PioPin) { | 14 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { |
| 13 | // Setup sm0 | 15 | // Setup sm0 |
| 14 | 16 | ||
| 15 | // Send data serially to pin | 17 | // Send data serially to pin |
| @@ -22,22 +24,18 @@ fn setup_pio_task_sm0(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachine<PIO0, | |||
| 22 | ); | 24 | ); |
| 23 | 25 | ||
| 24 | let relocated = RelocatedProgram::new(&prg.program); | 26 | let relocated = RelocatedProgram::new(&prg.program); |
| 27 | let mut cfg = Config::default(); | ||
| 28 | cfg.use_program(&pio.load_program(&relocated), &[]); | ||
| 25 | let out_pin = pio.make_pio_pin(pin); | 29 | let out_pin = pio.make_pio_pin(pin); |
| 26 | let pio_pins = [&out_pin]; | 30 | cfg.set_out_pins(&[&out_pin]); |
| 27 | sm.set_out_pins(&pio_pins); | 31 | cfg.set_set_pins(&[&out_pin]); |
| 28 | pio.write_instr(relocated.origin() as usize, relocated.code()); | 32 | cfg.clock_divider = (U56F8!(125_000_000) / 20 / 200).to_fixed(); |
| 29 | pio_instr_util::exec_jmp(sm, relocated.origin()); | 33 | cfg.shift_out.auto_fill = true; |
| 30 | sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); | 34 | sm.set_config(&cfg); |
| 31 | sm.set_set_range(0, 1); | ||
| 32 | let pio::Wrap { source, target } = relocated.wrap(); | ||
| 33 | sm.set_wrap(source, target); | ||
| 34 | |||
| 35 | sm.set_autopull(true); | ||
| 36 | sm.set_out_shift_dir(ShiftDirection::Left); | ||
| 37 | } | 35 | } |
| 38 | 36 | ||
| 39 | #[embassy_executor::task] | 37 | #[embassy_executor::task] |
| 40 | async fn pio_task_sm0(mut sm: PioStateMachine<'static, PIO0, 0>) { | 38 | async fn pio_task_sm0(mut sm: StateMachine<'static, PIO0, 0>) { |
| 41 | sm.set_enable(true); | 39 | sm.set_enable(true); |
| 42 | 40 | ||
| 43 | let mut v = 0x0f0caffa; | 41 | let mut v = 0x0f0caffa; |
| @@ -48,26 +46,23 @@ async fn pio_task_sm0(mut sm: PioStateMachine<'static, PIO0, 0>) { | |||
| 48 | } | 46 | } |
| 49 | } | 47 | } |
| 50 | 48 | ||
| 51 | fn setup_pio_task_sm1(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachine<PIO0, 1>) { | 49 | fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 1>) { |
| 52 | // Setupm sm1 | 50 | // Setupm sm1 |
| 53 | 51 | ||
| 54 | // Read 0b10101 repeatedly until ISR is full | 52 | // Read 0b10101 repeatedly until ISR is full |
| 55 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); | 53 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); |
| 56 | 54 | ||
| 57 | let relocated = RelocatedProgram::new(&prg.program); | 55 | let relocated = RelocatedProgram::new(&prg.program); |
| 58 | pio.write_instr(relocated.origin() as usize, relocated.code()); | 56 | let mut cfg = Config::default(); |
| 59 | pio_instr_util::exec_jmp(sm, relocated.origin()); | 57 | cfg.use_program(&pio.load_program(&relocated), &[]); |
| 60 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | 58 | cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); |
| 61 | sm.set_set_range(0, 0); | 59 | cfg.shift_in.auto_fill = true; |
| 62 | let pio::Wrap { source, target } = relocated.wrap(); | 60 | cfg.shift_in.direction = ShiftDirection::Right; |
| 63 | sm.set_wrap(source, target); | 61 | sm.set_config(&cfg); |
| 64 | |||
| 65 | sm.set_autopush(true); | ||
| 66 | sm.set_in_shift_dir(ShiftDirection::Right); | ||
| 67 | } | 62 | } |
| 68 | 63 | ||
| 69 | #[embassy_executor::task] | 64 | #[embassy_executor::task] |
| 70 | async fn pio_task_sm1(mut sm: PioStateMachine<'static, PIO0, 1>) { | 65 | async fn pio_task_sm1(mut sm: StateMachine<'static, PIO0, 1>) { |
| 71 | sm.set_enable(true); | 66 | sm.set_enable(true); |
| 72 | loop { | 67 | loop { |
| 73 | let rx = sm.rx().wait_pull().await; | 68 | let rx = sm.rx().wait_pull().await; |
| @@ -75,7 +70,7 @@ async fn pio_task_sm1(mut sm: PioStateMachine<'static, PIO0, 1>) { | |||
| 75 | } | 70 | } |
| 76 | } | 71 | } |
| 77 | 72 | ||
| 78 | fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachine<PIO0, 2>) { | 73 | fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 2>) { |
| 79 | // Setup sm2 | 74 | // Setup sm2 |
| 80 | 75 | ||
| 81 | // Repeatedly trigger IRQ 3 | 76 | // Repeatedly trigger IRQ 3 |
| @@ -89,17 +84,14 @@ fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachine<PIO0, | |||
| 89 | ".wrap", | 84 | ".wrap", |
| 90 | ); | 85 | ); |
| 91 | let relocated = RelocatedProgram::new(&prg.program); | 86 | let relocated = RelocatedProgram::new(&prg.program); |
| 92 | pio.write_instr(relocated.origin() as usize, relocated.code()); | 87 | let mut cfg = Config::default(); |
| 93 | 88 | cfg.use_program(&pio.load_program(&relocated), &[]); | |
| 94 | let pio::Wrap { source, target } = relocated.wrap(); | 89 | cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); |
| 95 | sm.set_wrap(source, target); | 90 | sm.set_config(&cfg); |
| 96 | |||
| 97 | pio_instr_util::exec_jmp(sm, relocated.origin()); | ||
| 98 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | ||
| 99 | } | 91 | } |
| 100 | 92 | ||
| 101 | #[embassy_executor::task] | 93 | #[embassy_executor::task] |
| 102 | async fn pio_task_sm2(mut irq: PioIrq<'static, PIO0, 3>, mut sm: PioStateMachine<'static, PIO0, 2>) { | 94 | async fn pio_task_sm2(mut irq: Irq<'static, PIO0, 3>, mut sm: StateMachine<'static, PIO0, 2>) { |
| 103 | sm.set_enable(true); | 95 | sm.set_enable(true); |
| 104 | loop { | 96 | loop { |
| 105 | irq.wait().await; | 97 | irq.wait().await; |
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index c664482e5..7f85288bf 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs | |||
| @@ -2,11 +2,14 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_embedded_hal::SetConfig; | ||
| 5 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 7 | use embassy_futures::join::join; |
| 7 | use embassy_rp::pio::{Pio, ShiftDirection}; | 8 | use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use embassy_rp::{pio_instr_util, Peripheral}; | 10 | use embassy_rp::Peripheral; |
| 11 | use fixed::traits::ToFixed; | ||
| 12 | use fixed_macro::types::U56F8; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 11 | 14 | ||
| 12 | fn swap_nibbles(v: u32) -> u32 { | 15 | fn swap_nibbles(v: u32) -> u32 { |
| @@ -38,18 +41,21 @@ async fn main(_spawner: Spawner) { | |||
| 38 | ); | 41 | ); |
| 39 | 42 | ||
| 40 | let relocated = RelocatedProgram::new(&prg.program); | 43 | let relocated = RelocatedProgram::new(&prg.program); |
| 41 | common.write_instr(relocated.origin() as usize, relocated.code()); | 44 | let mut cfg = Config::default(); |
| 42 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); | 45 | cfg.use_program(&common.load_program(&relocated), &[]); |
| 43 | sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); | 46 | cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); |
| 44 | let pio::Wrap { source, target } = relocated.wrap(); | 47 | cfg.shift_in = ShiftConfig { |
| 45 | sm.set_wrap(source, target); | 48 | auto_fill: true, |
| 46 | sm.set_autopull(true); | 49 | threshold: 32, |
| 47 | sm.set_autopush(true); | 50 | direction: ShiftDirection::Left, |
| 48 | sm.set_pull_threshold(32); | 51 | }; |
| 49 | sm.set_push_threshold(32); | 52 | cfg.shift_out = ShiftConfig { |
| 50 | sm.set_out_shift_dir(ShiftDirection::Right); | 53 | auto_fill: true, |
| 51 | sm.set_in_shift_dir(ShiftDirection::Left); | 54 | threshold: 32, |
| 55 | direction: ShiftDirection::Right, | ||
| 56 | }; | ||
| 52 | 57 | ||
| 58 | sm.set_config(&cfg); | ||
| 53 | sm.set_enable(true); | 59 | sm.set_enable(true); |
| 54 | 60 | ||
| 55 | let mut dma_out_ref = p.DMA_CH0.into_ref(); | 61 | let mut dma_out_ref = p.DMA_CH0.into_ref(); |
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index f76d334e7..088fd5649 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | use core::fmt::Write; | 5 | use core::fmt::Write; |
| 6 | 6 | ||
| 7 | use embassy_embedded_hal::SetConfig; | ||
| 7 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::dma::{AnyChannel, Channel}; | 9 | use embassy_rp::dma::{AnyChannel, Channel}; |
| 9 | use embassy_rp::peripherals::PIO0; | 10 | use embassy_rp::peripherals::PIO0; |
| 10 | use embassy_rp::pio::{FifoJoin, Pio, PioPin, PioStateMachine, ShiftDirection}; | 11 | use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; |
| 11 | use embassy_rp::pwm::{Config, Pwm}; | 12 | use embassy_rp::pwm::{self, Pwm}; |
| 12 | use embassy_rp::relocate::RelocatedProgram; | 13 | use embassy_rp::relocate::RelocatedProgram; |
| 13 | use embassy_rp::{into_ref, Peripheral, PeripheralRef}; | 14 | use embassy_rp::{into_ref, Peripheral, PeripheralRef}; |
| 14 | use embassy_time::{Duration, Instant, Timer}; | 15 | use embassy_time::{Duration, Instant, Timer}; |
| @@ -29,7 +30,7 @@ async fn main(_spawner: Spawner) { | |||
| 29 | let p = embassy_rp::init(Default::default()); | 30 | let p = embassy_rp::init(Default::default()); |
| 30 | 31 | ||
| 31 | let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, { | 32 | let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, { |
| 32 | let mut c = Config::default(); | 33 | let mut c = pwm::Config::default(); |
| 33 | c.divider = 125.into(); | 34 | c.divider = 125.into(); |
| 34 | c.top = 100; | 35 | c.top = 100; |
| 35 | c.compare_b = 50; | 36 | c.compare_b = 50; |
| @@ -64,7 +65,7 @@ async fn main(_spawner: Spawner) { | |||
| 64 | 65 | ||
| 65 | pub struct HD44780<'l> { | 66 | pub struct HD44780<'l> { |
| 66 | dma: PeripheralRef<'l, AnyChannel>, | 67 | dma: PeripheralRef<'l, AnyChannel>, |
| 67 | sm: PioStateMachine<'l, PIO0, 0>, | 68 | sm: StateMachine<'l, PIO0, 0>, |
| 68 | 69 | ||
| 69 | buf: [u8; 40], | 70 | buf: [u8; 40], |
| 70 | } | 71 | } |
| @@ -83,7 +84,6 @@ impl<'l> HD44780<'l> { | |||
| 83 | ) -> HD44780<'l> { | 84 | ) -> HD44780<'l> { |
| 84 | into_ref!(dma); | 85 | into_ref!(dma); |
| 85 | 86 | ||
| 86 | let db7pin = db7.pin(); | ||
| 87 | let Pio { | 87 | let Pio { |
| 88 | mut common, | 88 | mut common, |
| 89 | mut irq0, | 89 | mut irq0, |
| @@ -95,6 +95,7 @@ impl<'l> HD44780<'l> { | |||
| 95 | let prg = pio_proc::pio_asm!( | 95 | let prg = pio_proc::pio_asm!( |
| 96 | r#" | 96 | r#" |
| 97 | .side_set 1 opt | 97 | .side_set 1 opt |
| 98 | .origin 20 | ||
| 98 | 99 | ||
| 99 | loop: | 100 | loop: |
| 100 | out x, 24 | 101 | out x, 24 |
| @@ -115,27 +116,20 @@ impl<'l> HD44780<'l> { | |||
| 115 | let db6 = common.make_pio_pin(db6); | 116 | let db6 = common.make_pio_pin(db6); |
| 116 | let db7 = common.make_pio_pin(db7); | 117 | let db7 = common.make_pio_pin(db7); |
| 117 | 118 | ||
| 118 | sm0.set_set_pins(&[&rs, &rw]); | 119 | sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); |
| 119 | embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11); | ||
| 120 | sm0.set_set_pins(&[&e]); | ||
| 121 | embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1); | ||
| 122 | sm0.set_set_pins(&[&db4, &db5, &db6, &db7]); | ||
| 123 | embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111); | ||
| 124 | 120 | ||
| 125 | let relocated = RelocatedProgram::new(&prg.program); | 121 | let relocated = RelocatedProgram::new(&prg.program); |
| 126 | common.write_instr(relocated.origin() as usize, relocated.code()); | 122 | let mut cfg = Config::default(); |
| 127 | embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin()); | 123 | cfg.use_program(&common.load_program(&relocated), &[&e]); |
| 128 | sm0.set_clkdiv(125 * 256); | 124 | cfg.clock_divider = 125u8.into(); |
| 129 | let pio::Wrap { source, target } = relocated.wrap(); | 125 | cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); |
| 130 | sm0.set_wrap(source, target); | 126 | cfg.shift_out = ShiftConfig { |
| 131 | sm0.set_side_enable(true); | 127 | auto_fill: true, |
| 132 | sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); | 128 | direction: ShiftDirection::Left, |
| 133 | sm0.set_sideset_base_pin(&e); | 129 | threshold: 32, |
| 134 | sm0.set_sideset_count(2); | 130 | }; |
| 135 | sm0.set_out_shift_dir(ShiftDirection::Left); | 131 | cfg.fifo_join = FifoJoin::TxOnly; |
| 136 | sm0.set_fifo_join(FifoJoin::TxOnly); | 132 | sm0.set_config(&cfg); |
| 137 | sm0.set_autopull(true); | ||
| 138 | sm0.set_pull_threshold(32); | ||
| 139 | 133 | ||
| 140 | sm0.set_enable(true); | 134 | sm0.set_enable(true); |
| 141 | // init to 8 bit thrice | 135 | // init to 8 bit thrice |
| @@ -155,7 +149,7 @@ impl<'l> HD44780<'l> { | |||
| 155 | // many side sets are only there to free up a delay bit! | 149 | // many side sets are only there to free up a delay bit! |
| 156 | let prg = pio_proc::pio_asm!( | 150 | let prg = pio_proc::pio_asm!( |
| 157 | r#" | 151 | r#" |
| 158 | .origin 7 | 152 | .origin 27 |
| 159 | .side_set 1 | 153 | .side_set 1 |
| 160 | 154 | ||
| 161 | .wrap_target | 155 | .wrap_target |
| @@ -199,19 +193,15 @@ impl<'l> HD44780<'l> { | |||
| 199 | ); | 193 | ); |
| 200 | 194 | ||
| 201 | let relocated = RelocatedProgram::new(&prg.program); | 195 | let relocated = RelocatedProgram::new(&prg.program); |
| 202 | common.write_instr(relocated.origin() as usize, relocated.code()); | 196 | let mut cfg = Config::default(); |
| 203 | embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin()); | 197 | cfg.use_program(&common.load_program(&relocated), &[&e]); |
| 204 | let pio::Wrap { source, target } = relocated.wrap(); | 198 | cfg.clock_divider = 8u8.into(); // ~64ns/insn |
| 205 | sm0.set_clkdiv(8 * 256); // ~64ns/insn | 199 | cfg.set_jmp_pin(&db7); |
| 206 | sm0.set_side_enable(false); | 200 | cfg.set_set_pins(&[&rs, &rw]); |
| 207 | sm0.set_jmp_pin(db7pin); | 201 | cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); |
| 208 | sm0.set_wrap(source, target); | 202 | cfg.shift_out.direction = ShiftDirection::Left; |
| 209 | sm0.set_set_pins(&[&rs, &rw]); | 203 | cfg.fifo_join = FifoJoin::TxOnly; |
| 210 | sm0.set_out_pins(&[&db4, &db5, &db6, &db7]); | 204 | sm0.set_config(&cfg); |
| 211 | sm0.set_sideset_base_pin(&e); | ||
| 212 | sm0.set_sideset_count(1); | ||
| 213 | sm0.set_out_shift_dir(ShiftDirection::Left); | ||
| 214 | sm0.set_fifo_join(FifoJoin::TxOnly); | ||
| 215 | 205 | ||
| 216 | sm0.set_enable(true); | 206 | sm0.set_enable(true); |
| 217 | 207 | ||
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index c9c701a70..d7c4742d8 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs | |||
| @@ -3,19 +3,20 @@ | |||
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_embedded_hal::SetConfig; | ||
| 6 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::pio::{FifoJoin, Pio, PioCommon, PioInstance, PioPin, PioStateMachine, ShiftDirection}; | 8 | use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; |
| 8 | use embassy_rp::pio_instr_util; | ||
| 9 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 10 | use embassy_time::{Duration, Timer}; | 10 | use embassy_time::{Duration, Timer}; |
| 11 | use fixed_macro::fixed; | ||
| 11 | use smart_leds::RGB8; | 12 | use smart_leds::RGB8; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | pub struct Ws2812<'d, P: PioInstance, const S: usize> { | 14 | pub struct Ws2812<'d, P: Instance, const S: usize> { |
| 14 | sm: PioStateMachine<'d, P, S>, | 15 | sm: StateMachine<'d, P, S>, |
| 15 | } | 16 | } |
| 16 | 17 | ||
| 17 | impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { | 18 | impl<'d, P: Instance, const S: usize> Ws2812<'d, P, S> { |
| 18 | pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachine<'d, P, S>, pin: impl PioPin) -> Self { | 19 | pub fn new(mut pio: Common<'d, P>, mut sm: StateMachine<'d, P, S>, pin: impl PioPin) -> Self { |
| 19 | // Setup sm0 | 20 | // Setup sm0 |
| 20 | 21 | ||
| 21 | // prepare the PIO program | 22 | // prepare the PIO program |
| @@ -44,41 +45,30 @@ impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> { | |||
| 44 | a.bind(&mut wrap_source); | 45 | a.bind(&mut wrap_source); |
| 45 | 46 | ||
| 46 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); | 47 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); |
| 47 | 48 | let mut cfg = Config::default(); | |
| 48 | let relocated = RelocatedProgram::new(&prg); | ||
| 49 | pio.write_instr(relocated.origin() as usize, relocated.code()); | ||
| 50 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); | ||
| 51 | 49 | ||
| 52 | // Pin config | 50 | // Pin config |
| 53 | let out_pin = pio.make_pio_pin(pin); | 51 | let out_pin = pio.make_pio_pin(pin); |
| 54 | sm.set_set_pins(&[&out_pin]); | ||
| 55 | sm.set_sideset_base_pin(&out_pin); | ||
| 56 | sm.set_sideset_count(1); | ||
| 57 | 52 | ||
| 58 | // Clock config | 53 | let relocated = RelocatedProgram::new(&prg); |
| 59 | // TODO CLOCK_FREQ should come from embassy_rp | 54 | cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); |
| 60 | const CLOCK_FREQ: u32 = 125_000_000; | ||
| 61 | const WS2812_FREQ: u32 = 800_000; | ||
| 62 | |||
| 63 | let bit_freq = WS2812_FREQ * CYCLES_PER_BIT; | ||
| 64 | let mut int = CLOCK_FREQ / bit_freq; | ||
| 65 | let rem = CLOCK_FREQ - (int * bit_freq); | ||
| 66 | let frac = (rem * 256) / bit_freq; | ||
| 67 | // 65536.0 is represented as 0 in the pio's clock divider | ||
| 68 | if int == 65536 { | ||
| 69 | int = 0; | ||
| 70 | } | ||
| 71 | 55 | ||
| 72 | sm.set_clkdiv((int << 8) | frac); | 56 | // Clock config, measured in kHz to avoid overflows |
| 73 | let pio::Wrap { source, target } = relocated.wrap(); | 57 | // TODO CLOCK_FREQ should come from embassy_rp |
| 74 | sm.set_wrap(source, target); | 58 | let clock_freq = fixed!(125_000: U24F8); |
| 59 | let ws2812_freq = fixed!(800: U24F8); | ||
| 60 | let bit_freq = ws2812_freq * CYCLES_PER_BIT; | ||
| 61 | cfg.clock_divider = clock_freq / bit_freq; | ||
| 75 | 62 | ||
| 76 | // FIFO config | 63 | // FIFO config |
| 77 | sm.set_autopull(true); | 64 | cfg.fifo_join = FifoJoin::TxOnly; |
| 78 | sm.set_fifo_join(FifoJoin::TxOnly); | 65 | cfg.shift_out = ShiftConfig { |
| 79 | sm.set_pull_threshold(24); | 66 | auto_fill: true, |
| 80 | sm.set_out_shift_dir(ShiftDirection::Left); | 67 | threshold: 24, |
| 81 | 68 | direction: ShiftDirection::Left, | |
| 69 | }; | ||
| 70 | |||
| 71 | sm.set_config(&cfg); | ||
| 82 | sm.set_enable(true); | 72 | sm.set_enable(true); |
| 83 | 73 | ||
| 84 | Self { sm } | 74 | Self { sm } |
