//! Using shift register 74hc595 and multiplexer cd4051b with ESP32
//!
#![no_std]
#![no_main]
use core::result::Result;
use hal::{
clock::ClockControl, gpio::IO, peripherals::Peripherals, prelude::*, timer::TimerGroup, Delay,
Rtc,
};
use esp_backtrace as _;
use esp_println::println;
use drive_74hc595::ShiftRegister;
use hal::ehal::digital::v2::OutputPin;
//
// Refer https://wokwi.com/projects/343522915673702994
// for cd4051b.chip.c and cd4051b.chip.json
//
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let mut system = peripherals.DPORT.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
// Disable the RTC and TIMG watchdog timers
let mut rtc = Rtc::new(peripherals.RTC_CNTL);
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let mut wdt0 = timer_group0.wdt;
let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks);
let mut wdt1 = timer_group1.wdt;
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();
println!("Hello world!");
// Setup the GPIOs.
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let mut clock_pin = io.pins.gpio4.into_push_pull_output();
let mut latch_pin = io.pins.gpio2.into_push_pull_output();
let mut data_pin = io.pins.gpio15.into_push_pull_output();
let mut relay_control = EightBitRelayControl::new(data_pin, clock_pin, latch_pin);
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);
relay_control.begin();
loop {
for pin in 0..=7 {
relay_control.set_high(pin);
delay.delay_ms(50u32);
}
for pin in 0..=7 {
relay_control.set_low(pin);
delay.delay_ms(50u32);
}
}
}
struct EightBitRelayControl<DP, CP, LP>
where
DP: OutputPin,
CP: OutputPin,
LP: OutputPin
{
drive: ShiftRegister<DummyPin, DP, DummyPin, CP, LP>,
curr_val: u8,
}
impl<DP, CP, LP> EightBitRelayControl<DP, CP, LP>
where
DP: OutputPin,
CP: OutputPin,
LP: OutputPin
{
pub fn new(data_pin: DP, clock_pin: CP, latch_pin: LP) -> Self {
let drive = ShiftRegister::new(DummyPin, data_pin, DummyPin, clock_pin, latch_pin);
Self {
drive,
curr_val: 0,
}
}
pub fn begin(&mut self) {
self.drive.begin();
self.drive.output_clear();
}
pub fn all_high(&mut self) {
self.drive.disable_output();
self.drive.load(255);
self.curr_val = 255;
self.drive.enable_output();
}
pub fn all_low(&mut self) {
self.drive.disable_output();
self.drive.load(0);
self.curr_val = 0;
self.drive.enable_output();
}
pub fn set_high(&mut self, addr: u8) {
assert!(addr < 8);
let addr = u8::pow(2, addr as u32);
self.drive.disable_output();
self.curr_val |= addr;
self.drive.load(self.curr_val);
self.drive.enable_output();
}
pub fn set_low(&mut self, addr: u8) {
assert!(addr < 8);
let addr = u8::pow(2, addr as u32);
self.drive.disable_output();
self.curr_val -= self.curr_val & addr;
self.drive.load(self.curr_val);
self.drive.enable_output();
}
}
struct DummyPin;
impl OutputPin for DummyPin {
type Error = ();
fn set_low(&mut self) -> Result<(), Self::Error> {
Ok(())
}
fn set_high(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}