Merge branch 'embassy-rs:master' into master
This commit is contained in:
@ -4,15 +4,13 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::gpio::{AnyPin, Pin};
|
||||
use embassy_rp::pio::{
|
||||
Pio0, PioCommon, PioCommonInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance, ShiftDirection, Sm0,
|
||||
Sm1, Sm2,
|
||||
};
|
||||
use embassy_rp::peripherals::PIO0;
|
||||
use embassy_rp::pio::{Pio, PioCommon, PioStateMachine, PioStateMachineInstance, ShiftDirection};
|
||||
use embassy_rp::pio_instr_util;
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm0>, pin: AnyPin) {
|
||||
fn setup_pio_task_sm0(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 0>, pin: AnyPin) {
|
||||
// Setup sm0
|
||||
|
||||
// Send data serially to pin
|
||||
@ -40,7 +38,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
|
||||
async fn pio_task_sm0(mut sm: PioStateMachineInstance<'static, PIO0, 0>) {
|
||||
sm.set_enable(true);
|
||||
|
||||
let mut v = 0x0f0caffa;
|
||||
@ -51,7 +49,7 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) {
|
||||
fn setup_pio_task_sm1(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 1>) {
|
||||
// Setupm sm1
|
||||
|
||||
// Read 0b10101 repeatedly until ISR is full
|
||||
@ -70,7 +68,7 @@ fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
|
||||
async fn pio_task_sm1(mut sm: PioStateMachineInstance<'static, PIO0, 1>) {
|
||||
sm.set_enable(true);
|
||||
loop {
|
||||
let rx = sm.wait_pull().await;
|
||||
@ -78,7 +76,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) {
|
||||
fn setup_pio_task_sm2(pio: &mut PioCommon<PIO0>, sm: &mut PioStateMachineInstance<PIO0, 2>) {
|
||||
// Setup sm2
|
||||
|
||||
// Repeatedly trigger IRQ 3
|
||||
@ -102,7 +100,7 @@ fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) {
|
||||
async fn pio_task_sm2(mut sm: PioStateMachineInstance<'static, PIO0, 2>) {
|
||||
sm.set_enable(true);
|
||||
loop {
|
||||
sm.wait_irq(3).await;
|
||||
@ -115,11 +113,17 @@ async fn main(spawner: Spawner) {
|
||||
let p = embassy_rp::init(Default::default());
|
||||
let pio = p.PIO0;
|
||||
|
||||
let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split();
|
||||
let Pio {
|
||||
mut common,
|
||||
mut sm0,
|
||||
mut sm1,
|
||||
mut sm2,
|
||||
..
|
||||
} = Pio::new(pio);
|
||||
|
||||
setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade());
|
||||
setup_pio_task_sm1(&mut pio0, &mut sm1);
|
||||
setup_pio_task_sm2(&mut pio0, &mut sm2);
|
||||
setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0.degrade());
|
||||
setup_pio_task_sm1(&mut common, &mut sm1);
|
||||
setup_pio_task_sm2(&mut common, &mut sm2);
|
||||
spawner.spawn(pio_task_sm0(sm0)).unwrap();
|
||||
spawner.spawn(pio_task_sm1(sm1)).unwrap();
|
||||
spawner.spawn(pio_task_sm2(sm2)).unwrap();
|
||||
|
@ -4,7 +4,7 @@
|
||||
use defmt::info;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_futures::join::join;
|
||||
use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection};
|
||||
use embassy_rp::pio::{Pio, PioStateMachine, ShiftDirection};
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use embassy_rp::{pio_instr_util, Peripheral};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
@ -19,7 +19,11 @@ fn swap_nibbles(v: u32) -> u32 {
|
||||
async fn main(_spawner: Spawner) {
|
||||
let p = embassy_rp::init(Default::default());
|
||||
let pio = p.PIO0;
|
||||
let (mut pio0, mut sm, ..) = pio.split();
|
||||
let Pio {
|
||||
mut common,
|
||||
sm0: mut sm,
|
||||
..
|
||||
} = Pio::new(pio);
|
||||
|
||||
let prg = pio_proc::pio_asm!(
|
||||
".origin 0",
|
||||
@ -34,7 +38,7 @@ async fn main(_spawner: Spawner) {
|
||||
);
|
||||
|
||||
let relocated = RelocatedProgram::new(&prg.program);
|
||||
pio0.write_instr(relocated.origin() as usize, relocated.code());
|
||||
common.write_instr(relocated.origin() as usize, relocated.code());
|
||||
pio_instr_util::exec_jmp(&mut sm, relocated.origin());
|
||||
sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32);
|
||||
let pio::Wrap { source, target } = relocated.wrap();
|
||||
|
243
examples/rp/src/bin/pio_hd44780.rs
Normal file
243
examples/rp/src/bin/pio_hd44780.rs
Normal file
@ -0,0 +1,243 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::dma::{AnyChannel, Channel};
|
||||
use embassy_rp::gpio::Pin;
|
||||
use embassy_rp::peripherals::PIO0;
|
||||
use embassy_rp::pio::{FifoJoin, Pio, PioStateMachine, PioStateMachineInstance, ShiftDirection};
|
||||
use embassy_rp::pwm::{Config, Pwm};
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use embassy_rp::{into_ref, Peripheral, PeripheralRef};
|
||||
use embassy_time::{Duration, Instant, Timer};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
// this test assumes a 2x16 HD44780 display attached as follow:
|
||||
// rs = PIN0
|
||||
// rw = PIN1
|
||||
// e = PIN2
|
||||
// db4 = PIN3
|
||||
// db5 = PIN4
|
||||
// db6 = PIN5
|
||||
// db7 = PIN6
|
||||
// additionally a pwm signal for a bias voltage charge pump is provided on pin 15,
|
||||
// allowing direct connection of the display to the RP2040 without level shifters.
|
||||
let p = embassy_rp::init(Default::default());
|
||||
|
||||
let _pwm = Pwm::new_output_b(p.PWM_CH7, p.PIN_15, {
|
||||
let mut c = Config::default();
|
||||
c.divider = 125.into();
|
||||
c.top = 100;
|
||||
c.compare_b = 50;
|
||||
c
|
||||
});
|
||||
|
||||
let mut hd = HD44780::new(
|
||||
p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6,
|
||||
)
|
||||
.await;
|
||||
|
||||
loop {
|
||||
struct Buf<const N: usize>([u8; N], usize);
|
||||
impl<const N: usize> Write for Buf<N> {
|
||||
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
|
||||
for b in s.as_bytes() {
|
||||
if self.1 >= N {
|
||||
return Err(core::fmt::Error);
|
||||
}
|
||||
self.0[self.1] = *b;
|
||||
self.1 += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
let mut buf = Buf([0; 16], 0);
|
||||
write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap();
|
||||
hd.add_line(&buf.0[0..buf.1]).await;
|
||||
Timer::after(Duration::from_secs(1)).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HD44780<'l> {
|
||||
dma: PeripheralRef<'l, AnyChannel>,
|
||||
sm: PioStateMachineInstance<'l, PIO0, 0>,
|
||||
|
||||
buf: [u8; 40],
|
||||
}
|
||||
|
||||
impl<'l> HD44780<'l> {
|
||||
pub async fn new(
|
||||
pio: impl Peripheral<P = PIO0> + 'l,
|
||||
dma: impl Peripheral<P = impl Channel> + 'l,
|
||||
rs: impl Pin,
|
||||
rw: impl Pin,
|
||||
e: impl Pin,
|
||||
db4: impl Pin,
|
||||
db5: impl Pin,
|
||||
db6: impl Pin,
|
||||
db7: impl Pin,
|
||||
) -> HD44780<'l> {
|
||||
into_ref!(dma);
|
||||
|
||||
let db7pin = db7.pin();
|
||||
let Pio {
|
||||
mut common, mut sm0, ..
|
||||
} = Pio::new(pio);
|
||||
|
||||
// takes command words (<wait:24> <command:4> <0:4>)
|
||||
let prg = pio_proc::pio_asm!(
|
||||
r#"
|
||||
.side_set 1 opt
|
||||
|
||||
loop:
|
||||
out x, 24
|
||||
delay:
|
||||
jmp x--, delay
|
||||
out pins, 4 side 1
|
||||
out null, 4 side 0
|
||||
jmp !osre, loop
|
||||
irq 0
|
||||
"#,
|
||||
);
|
||||
|
||||
let rs = common.make_pio_pin(rs);
|
||||
let rw = common.make_pio_pin(rw);
|
||||
let e = common.make_pio_pin(e);
|
||||
let db4 = common.make_pio_pin(db4);
|
||||
let db5 = common.make_pio_pin(db5);
|
||||
let db6 = common.make_pio_pin(db6);
|
||||
let db7 = common.make_pio_pin(db7);
|
||||
|
||||
sm0.set_set_pins(&[&rs, &rw]);
|
||||
embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11);
|
||||
sm0.set_set_pins(&[&e]);
|
||||
embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b1);
|
||||
sm0.set_set_pins(&[&db4, &db5, &db6, &db7]);
|
||||
embassy_rp::pio_instr_util::set_pindir(&mut sm0, 0b11111);
|
||||
|
||||
let relocated = RelocatedProgram::new(&prg.program);
|
||||
common.write_instr(relocated.origin() as usize, relocated.code());
|
||||
embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
|
||||
sm0.set_clkdiv(125 * 256);
|
||||
let pio::Wrap { source, target } = relocated.wrap();
|
||||
sm0.set_wrap(source, target);
|
||||
sm0.set_side_enable(true);
|
||||
sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
|
||||
sm0.set_sideset_base_pin(&e);
|
||||
sm0.set_sideset_count(2);
|
||||
sm0.set_out_shift_dir(ShiftDirection::Left);
|
||||
sm0.set_fifo_join(FifoJoin::TxOnly);
|
||||
sm0.set_autopull(true);
|
||||
sm0.set_pull_threshold(32);
|
||||
|
||||
sm0.set_enable(true);
|
||||
// init to 8 bit thrice
|
||||
sm0.push_tx((50000 << 8) | 0x30);
|
||||
sm0.push_tx((5000 << 8) | 0x30);
|
||||
sm0.push_tx((200 << 8) | 0x30);
|
||||
// init 4 bit
|
||||
sm0.push_tx((200 << 8) | 0x20);
|
||||
// set font and lines
|
||||
sm0.push_tx((50 << 8) | 0x20);
|
||||
sm0.push_tx(0b1100_0000);
|
||||
|
||||
sm0.wait_irq(0).await;
|
||||
sm0.set_enable(false);
|
||||
|
||||
// takes command sequences (<rs:1> <count:7>, data...)
|
||||
// many side sets are only there to free up a delay bit!
|
||||
let prg = pio_proc::pio_asm!(
|
||||
r#"
|
||||
.origin 7
|
||||
.side_set 1
|
||||
|
||||
.wrap_target
|
||||
pull side 0
|
||||
out x 1 side 0 ; !rs
|
||||
out y 7 side 0 ; #data - 1
|
||||
|
||||
; rs/rw to e: >= 60ns
|
||||
; e high time: >= 500ns
|
||||
; e low time: >= 500ns
|
||||
; read data valid after e falling: ~5ns
|
||||
; write data hold after e falling: ~10ns
|
||||
|
||||
loop:
|
||||
pull side 0
|
||||
jmp !x data side 0
|
||||
command:
|
||||
set pins 0b00 side 0
|
||||
jmp shift side 0
|
||||
data:
|
||||
set pins 0b01 side 0
|
||||
shift:
|
||||
out pins 4 side 1 [9]
|
||||
nop side 0 [9]
|
||||
out pins 4 side 1 [9]
|
||||
mov osr null side 0 [7]
|
||||
out pindirs 4 side 0
|
||||
set pins 0b10 side 0
|
||||
busy:
|
||||
nop side 1 [9]
|
||||
jmp pin more side 0 [9]
|
||||
mov osr ~osr side 1 [9]
|
||||
nop side 0 [4]
|
||||
out pindirs 4 side 0
|
||||
jmp y-- loop side 0
|
||||
.wrap
|
||||
more:
|
||||
nop side 1 [9]
|
||||
jmp busy side 0 [9]
|
||||
"#
|
||||
);
|
||||
|
||||
let relocated = RelocatedProgram::new(&prg.program);
|
||||
common.write_instr(relocated.origin() as usize, relocated.code());
|
||||
embassy_rp::pio_instr_util::exec_jmp(&mut sm0, relocated.origin());
|
||||
let pio::Wrap { source, target } = relocated.wrap();
|
||||
sm0.set_clkdiv(8 * 256); // ~64ns/insn
|
||||
sm0.set_side_enable(false);
|
||||
sm0.set_jmp_pin(db7pin);
|
||||
sm0.set_wrap(source, target);
|
||||
sm0.set_set_pins(&[&rs, &rw]);
|
||||
sm0.set_out_pins(&[&db4, &db5, &db6, &db7]);
|
||||
sm0.set_sideset_base_pin(&e);
|
||||
sm0.set_sideset_count(1);
|
||||
sm0.set_out_shift_dir(ShiftDirection::Left);
|
||||
sm0.set_fifo_join(FifoJoin::TxOnly);
|
||||
|
||||
sm0.set_enable(true);
|
||||
|
||||
// display on and cursor on and blinking, reset display
|
||||
sm0.dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1]).await;
|
||||
|
||||
Self {
|
||||
dma: dma.map_into(),
|
||||
sm: sm0,
|
||||
buf: [0x20; 40],
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn add_line(&mut self, s: &[u8]) {
|
||||
// move cursor to 0:0, prepare 16 characters
|
||||
self.buf[..3].copy_from_slice(&[0x80, 0x80, 15]);
|
||||
// move line 2 up
|
||||
self.buf.copy_within(22..38, 3);
|
||||
// move cursor to 1:0, prepare 16 characters
|
||||
self.buf[19..22].copy_from_slice(&[0x80, 0xc0, 15]);
|
||||
// file line 2 with spaces
|
||||
self.buf[22..38].fill(0x20);
|
||||
// copy input line
|
||||
let len = s.len().min(16);
|
||||
self.buf[22..22 + len].copy_from_slice(&s[0..len]);
|
||||
// set cursor to 1:15
|
||||
self.buf[38..].copy_from_slice(&[0x80, 0xcf]);
|
||||
|
||||
self.sm.dma_push(self.dma.reborrow(), &self.buf).await;
|
||||
}
|
||||
}
|
@ -6,20 +6,19 @@ use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_rp::gpio::{self, Pin};
|
||||
use embassy_rp::pio::{
|
||||
FifoJoin, PioCommon, PioCommonInstance, PioInstance, PioPeripheral, PioStateMachine, PioStateMachineInstance,
|
||||
ShiftDirection, SmInstance,
|
||||
FifoJoin, Pio, PioCommon, PioInstance, PioStateMachine, PioStateMachineInstance, ShiftDirection,
|
||||
};
|
||||
use embassy_rp::pio_instr_util;
|
||||
use embassy_rp::relocate::RelocatedProgram;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use smart_leds::RGB8;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
pub struct Ws2812<P: PioInstance, S: SmInstance> {
|
||||
sm: PioStateMachineInstance<P, S>,
|
||||
pub struct Ws2812<'d, P: PioInstance, const S: usize> {
|
||||
sm: PioStateMachineInstance<'d, P, S>,
|
||||
}
|
||||
|
||||
impl<P: PioInstance, S: SmInstance> Ws2812<P, S> {
|
||||
pub fn new(mut pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self {
|
||||
impl<'d, P: PioInstance, const S: usize> Ws2812<'d, P, S> {
|
||||
pub fn new(mut pio: PioCommon<'d, P>, mut sm: PioStateMachineInstance<'d, P, S>, pin: gpio::AnyPin) -> Self {
|
||||
// Setup sm0
|
||||
|
||||
// prepare the PIO program
|
||||
@ -116,7 +115,7 @@ async fn main(_spawner: Spawner) {
|
||||
info!("Start");
|
||||
let p = embassy_rp::init(Default::default());
|
||||
|
||||
let (pio0, sm0, _sm1, _sm2, _sm3) = p.PIO0.split();
|
||||
let Pio { common, sm0, .. } = Pio::new(p.PIO0);
|
||||
|
||||
// This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit
|
||||
// feather boards for the 2040 both have one built in.
|
||||
@ -125,7 +124,7 @@ async fn main(_spawner: Spawner) {
|
||||
|
||||
// For the thing plus, use pin 8
|
||||
// For the feather, use pin 16
|
||||
let mut ws2812 = Ws2812::new(pio0, sm0, p.PIN_8.degrade());
|
||||
let mut ws2812 = Ws2812::new(common, sm0, p.PIN_8.degrade());
|
||||
|
||||
// Loop forever making RGB values and pushing them out to the WS2812.
|
||||
loop {
|
||||
|
Reference in New Issue
Block a user