#![no_std]
#![no_main]
// ---------------------------------------------
use core::fmt::Write;
use esp_backtrace as _;
use esp_hal::{
clock::CpuClock,
delay::{self, Delay},
gpio::{Input, Level, Output, Pull},
i2c::master::{Config as I2cConfig, I2c},
main,
};
use ssd1306::{mode::BufferedGraphicsMode, prelude::*, I2CDisplayInterface, Ssd1306};
use embedded_graphics::{
mono_font::{ascii::FONT_6X10, MonoTextStyle, MonoTextStyleBuilder},
pixelcolor::BinaryColor,
prelude::*,
text::{Baseline, Text},
};
use heapless::String;
use esp_println::logger;
use log::info;
// ------------------------------------------
/*
* Hardware{
* green_led : GPIO17
* red_led: GPIO18
* blue_button: GPIO19
* led : {sda:GPIO12, scl:GPIO14}
* }
*/
// ------------------------------------------
#[derive(PartialEq, Eq)]
enum State {
Hold,
OnPress,
Overload,
}
// ------------------------------------------
#[main]
fn process() -> ! {
esp_println::logger::init_logger_from_env();
let delay = Delay::new();
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
let mut green_led = Output::new(peripherals.GPIO17, Level::Low);
let mut red_led = Output::new(peripherals.GPIO18, Level::Low);
let mut blue_button = Input::new(peripherals.GPIO19, Pull::Up);
let i2c = I2c::new(peripherals.I2C0, I2cConfig::default())
.unwrap()
.with_scl(peripherals.GPIO14)
.with_sda(peripherals.GPIO12);
let mut display = Ssd1306::new(
I2CDisplayInterface::new(i2c),
DisplaySize128x64,
DisplayRotation::Rotate0,
)
.into_buffered_graphics_mode();
let text_style = MonoTextStyleBuilder::new()
.font(&FONT_6X10)
.text_color(BinaryColor::On)
.build();
display.init().unwrap();
// --------------------------------------
const GREEN_LED_PERIOD: u32 = 600;
const RED_LED_PERIOD: u32 = 300;
const ONPRESS_RED_LED_PERIOD: u32 = 100;
const OVERLOAD_LED_PERIOD: u32 = 400;
const OVERLOAD_PRESS_COUNT: u32 = 4;
const OVERLOAD_PRESS_DELAY: u32 = 5000;
const STABILIZE_TIME: u32 = 400;
const REPORT_DELAY: u32 = 10000;
const TICKRATE: u32 = 10;
let mut timetick: u32 = 0;
let mut press_inbound_timer: u32 = 0;
let mut press_count: u32 = 0;
let mut last_press_time: u32 = 0;
let mut overload_start_time: u32 = 0;
let mut state = State::Hold;
// --------------------------------------
loop {
let button_pressed = blue_button.is_low();
match state {
State::Hold => {
if timetick % GREEN_LED_PERIOD == 0 {
green_led.toggle();
}
if timetick % RED_LED_PERIOD == 0 {
red_led.toggle();
}
if button_pressed {
press_inbound_timer = timetick;
state = State::OnPress;
let overload_tick = timetick - last_press_time;
if overload_tick > OVERLOAD_PRESS_DELAY {
press_count = 0;
}
press_count += 1;
last_press_time = timetick;
// ----------------
display.clear(BinaryColor::Off).unwrap();
let mut overload_cap: String<32> = String::new();
write!(
&mut overload_cap,
"Overload\n[{}/{}] last: [{}ms]",
press_count, OVERLOAD_PRESS_COUNT, overload_tick
)
.unwrap();
Text::with_baseline(
&overload_cap,
Point::new(0, 10),
text_style,
Baseline::Top,
)
.draw(&mut display)
.unwrap();
display.flush().unwrap();
// ----------------
if press_count >= OVERLOAD_PRESS_COUNT {
state = State::Overload;
overload_start_time = timetick;
press_count = 0;
}
}
}
State::OnPress => {
green_led.set_low();
if timetick % ONPRESS_RED_LED_PERIOD == 0 {
red_led.toggle();
}
if timetick - press_inbound_timer >= STABILIZE_TIME {
state = State::Hold;
}
}
State::Overload => {
if timetick % OVERLOAD_LED_PERIOD == 0 {
green_led.toggle();
red_led.toggle();
}
if timetick - overload_start_time >= OVERLOAD_PRESS_DELAY {
state = State::Hold;
green_led.set_low();
red_led.set_low();
}
}
}
delay.delay_millis(TICKRATE);
timetick += TICKRATE;
}
}