110 lines
3.7 KiB
Rust
110 lines
3.7 KiB
Rust
//! 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;
|
|
}
|
|
}
|
|
}
|