#![allow(dead_code, unused_variables)]
extern crate rppal;
use std::cell::RefCell;
use rppal::gpio::{Gpio, OutputPin};
struct ShiftRegister {
data: usize, pins: u8, }
impl std::fmt::Display for ShiftRegister {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let string = format!("{:b}", self.data);
let pad = (self.pins as usize) - string.len();
let _ = f.write_str("0b");
for _ in 0..pad { let _ = f.write_str("0").unwrap(); }
f.pad_integral(true, "", &string)
}
}
impl ShiftRegister {
fn set(&mut self, data: usize) {
self.data = data;
}
fn get_ref(self) -> RefCell<ShiftRegister> {
RefCell::new(self)
}
}
pub struct Shifter {
pub data: OutputPin,
pub latch: OutputPin,
pub clock: OutputPin,
shift_registers: Vec<ShiftRegister>,
invert: bool,
}
impl Shifter {
pub fn new(data_pin: u8, latch_pin: u8, clock_pin: u8, num_shift_registers: u8) -> Shifter {
let gpio = Gpio::new().unwrap();
let shift_registers: Vec<ShiftRegister> = Vec::with_capacity(num_shift_registers as usize);
Shifter {
data: gpio.get(data_pin).unwrap().into_output_low(),
latch: gpio.get(latch_pin).unwrap().into_output_low(),
clock: gpio.get(clock_pin).unwrap().into_output_low(),
shift_registers: shift_registers,
invert: false,
}
}
pub fn add(&mut self, pins: u8) -> usize {
let sr = ShiftRegister { data: 0, pins: pins };
self.shift_registers.push(sr);
self.shift_registers.len() - 1
}
pub fn set(&mut self, sr_index: usize, data: usize, apply: bool) {
for (i, sr) in self.shift_registers.iter_mut().enumerate() {
if i == sr_index {
sr.set(data);
break;
}
}
if apply { self.apply(); }
}
pub fn set_pin_high(&mut self, sr_index: usize, pin: u8, apply: bool) {
for (i, sr) in self.shift_registers.iter_mut().enumerate() {
if i == sr_index {
let new_state = sr.data | 1 << pin;
sr.set(new_state);
break;
}
}
if apply { self.apply(); }
}
pub fn set_pin_low(&mut self, sr_index: usize, pin: u8, apply: bool) {
for (i, sr) in self.shift_registers.iter_mut().enumerate() {
if i == sr_index {
let new_state = sr.data & !(1 << pin);
sr.set(new_state);
break;
}
}
if apply { self.apply(); }
}
pub fn invert(&mut self) {
match self.invert {
true => self.invert = false,
false => self.invert = true,
}
}
pub fn apply(&mut self) {
self.latch.set_low();
self.clock.set_low();
std::thread::sleep(std::time::Duration::from_millis(1));
for sr in self.shift_registers.iter() {
for n in 0..sr.pins {
if self.invert {
match sr.data >> n & 1 {
1 => self.data.set_low(),
0 => self.data.set_high(),
_ => unreachable!(),
}
} else {
match sr.data >> n & 1 {
0 => self.data.set_low(),
1 => self.data.set_high(),
_ => unreachable!(),
}
}
self.clock.set_high();
std::thread::sleep(std::time::Duration::from_micros(100));
self.clock.set_low();
std::thread::sleep(std::time::Duration::from_micros(100));
if self.invert{self.data.set_low(); } else {self.data.set_high();} }
}
self.latch.set_high();
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
}
}