adv_shift_registers/
lib.rs1#![no_std]
2
3use core::ops::Range;
4use embedded_hal::digital::{OutputPin, PinState};
5use wrappers::{ShifterPin, ShifterValue, ShifterValueRange};
6
7pub mod wrappers;
8
9pub struct AdvancedShiftRegister<const N: usize, OP: OutputPin> {
10 pub shifters: [u8; N],
12
13 data_pin: OP,
15
16 clk_pin: OP,
18
19 latch_pin: OP,
21}
22
23impl<const N: usize, OP: OutputPin> AdvancedShiftRegister<N, OP> {
24 pub fn new(data_pin: OP, clk_pin: OP, latch_pin: OP, default_val: u8) -> Self {
25 Self {
26 shifters: [default_val; N],
27 data_pin,
28 clk_pin,
29 latch_pin,
30 }
31 }
32
33 pub fn get_shifter_mut(&mut self, i: usize) -> ShifterValue {
35 ShifterValue {
36 inner: core::ptr::addr_of_mut!(self.shifters[i]),
37 update_shifters_ptr: MutFuncPtr::new(self, Self::update_shifters_trampoline),
38 }
39 }
40
41 pub fn get_pin_mut(&mut self, i: usize, bit: u8, auto_shift: bool) -> ShifterPin {
43 ShifterPin {
44 bit,
45 auto_update: auto_shift,
46 inner: core::ptr::addr_of_mut!(self.shifters[i]),
47 update_shifters_ptr: MutFuncPtr::new(self, Self::update_shifters_trampoline),
48 }
49 }
50
51 pub fn get_shifter_range_mut(&mut self, range: Range<usize>) -> ShifterValueRange {
54 ShifterValueRange {
55 inner: core::ptr::addr_of_mut!(self.shifters[range]),
57 update_shifters_ptr: MutFuncPtr::new(self, Self::update_shifters_trampoline),
58 }
59 }
60
61 pub fn update_shifters(&mut self) {
63 for i in (0..N).rev() {
64 let mut val = self.shifters[i];
65
66 for _ in 0..8 {
67 let state = PinState::from(val & 1 > 0);
68 _ = self.data_pin.set_state(state);
69 val >>= 1;
70
71 _ = self.clk_pin.set_high();
72 _ = self.clk_pin.set_low();
73 }
74 }
75
76 _ = self.latch_pin.set_high();
77 _ = self.latch_pin.set_low();
78 }
79
80 unsafe extern "C" fn update_shifters_trampoline(this: *mut Self) {
83 (&mut *this).update_shifters();
84 }
85}
86
87#[derive(Clone)]
88struct MutFuncPtr {
89 parent: *mut (),
90 call_ptr: unsafe extern "C" fn(*mut ()),
91}
92
93impl MutFuncPtr {
94 pub fn new<N>(parent: &mut N, function: unsafe extern "C" fn(*mut N)) -> Self {
95 unsafe {
96 Self {
97 parent: parent as *mut _ as *mut (),
98 call_ptr: core::mem::transmute(function),
99 }
100 }
101 }
102
103 pub unsafe fn call(&self) {
104 (self.call_ptr)(self.parent);
105 }
106}