Skip to main content

adv_shift_registers/
lib.rs

1#![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    /// Shifter data (currently set bits)
11    pub shifters: [u8; N],
12
13    /// Data pin
14    data_pin: OP,
15
16    /// Clock pin
17    clk_pin: OP,
18
19    /// Latch pin
20    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    /// Get wrapper for value of one shifter register (for easy modyfing)
34    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    /// Get wrapper for one bit of specifed shifter register (with embedded_hal digitalpin trait)
42    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    /// Get wrapper for range of shifter registers
52    /// (for easy modyfing of multiple registers at the same time)
53    pub fn get_shifter_range_mut(&mut self, range: Range<usize>) -> ShifterValueRange {
54        ShifterValueRange {
55            //len: range.len(),
56            inner: core::ptr::addr_of_mut!(self.shifters[range]),
57            update_shifters_ptr: MutFuncPtr::new(self, Self::update_shifters_trampoline),
58        }
59    }
60
61    /// Push stored shifters data onto shifter registers
62    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    /// Trampoline function to execute `.update_shifters()` function outside this struct
81    /// without using any generics
82    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}