//! OneWire pio driver use crate::pio::{self, Common, Config, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine}; /// This struct represents an onewire driver program pub struct PioOneWireProgram<'a, PIO: Instance> { prg: LoadedProgram<'a, PIO>, } impl<'a, PIO: Instance> PioOneWireProgram<'a, PIO> { /// Load the program into the given pio pub fn new(common: &mut Common<'a, PIO>) -> Self { let prg = pio_proc::pio_asm!( r#" .wrap_target again: pull block mov x, osr jmp !x, read write: set pindirs, 1 set pins, 0 loop1: jmp x--,loop1 set pindirs, 0 [31] wait 1 pin 0 [31] pull block mov x, osr bytes1: pull block set y, 7 set pindirs, 1 bit1: set pins, 0 [1] out pins,1 [31] set pins, 1 [20] jmp y--,bit1 jmp x--,bytes1 set pindirs, 0 [31] jmp again read: pull block mov x, osr bytes2: set y, 7 bit2: set pindirs, 1 set pins, 0 [1] set pindirs, 0 [5] in pins,1 [10] jmp y--,bit2 jmp x--,bytes2 .wrap "#, ); let prg = common.load_program(&prg.program); Self { prg } } } /// Pio backed OneWire driver pub struct PioOneWire<'d, PIO: pio::Instance, const SM: usize> { sm: StateMachine<'d, PIO, SM>, } impl<'d, PIO: pio::Instance, const SM: usize> PioOneWire<'d, PIO, SM> { /// Create a new instance the driver pub fn new( common: &mut Common<'d, PIO>, mut sm: StateMachine<'d, PIO, SM>, pin: impl PioPin, program: &PioOneWireProgram<'d, PIO>, ) -> Self { let pin = common.make_pio_pin(pin); let mut cfg = Config::default(); cfg.use_program(&program.prg, &[]); cfg.set_out_pins(&[&pin]); cfg.set_in_pins(&[&pin]); cfg.set_set_pins(&[&pin]); cfg.shift_in = ShiftConfig { auto_fill: true, direction: ShiftDirection::Right, threshold: 8, }; cfg.clock_divider = 255_u8.into(); sm.set_config(&cfg); sm.set_enable(true); Self { sm } } /// Write bytes over the wire pub async fn write_bytes(&mut self, bytes: &[u8]) { self.sm.tx().wait_push(250).await; self.sm.tx().wait_push(bytes.len() as u32 - 1).await; for b in bytes { self.sm.tx().wait_push(*b as u32).await; } } /// Read bytes from the wire pub async fn read_bytes(&mut self, bytes: &mut [u8]) { self.sm.tx().wait_push(0).await; self.sm.tx().wait_push(bytes.len() as u32 - 1).await; for b in bytes.iter_mut() { *b = (self.sm.rx().wait_pull().await >> 24) as u8; } } }