#![no_std]
#![no_main]
use core::mem::MaybeUninit;
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::rng::Rng;
use esp_hal::{
rtc_cntl::{sleep, Rtc, sleep::Ext0WakeupSource, sleep::WakeupLevel},
clock::CpuClock,
delay::Delay,
gpio::{Input, Level, Output, Pull, RtcPin},
main, Config,
peripheral::Peripheral,
};
use embedded_hal::digital::{InputPin, ErrorType, Error, ErrorKind};
use rotary_encoder_embedded::{RotaryEncoder, Direction};
use log::{ info};
mod tft;
mod neopixel;
mod main_model;
mod planter_model;
mod shift_register;
use tft::TftDisplay;
use main_model::{MainModel, PLANTER_COUNT};
use planter_model::WateringLevel;
use neopixel::Neopixel;
use shift_register::PumpControl;
pub struct EncoderPin {
pin: Input<'static>
}
impl EncoderPin {
pub fn new(pin: Input<'static>) -> Self {
Self {pin}
}
}
impl InputPin for EncoderPin {
fn is_high(&mut self) -> Result<bool, Self::Error> {
Ok(self.pin.is_high())
}
fn is_low(&mut self) -> Result<bool, Self::Error> {
Ok(self.pin.is_low())
}
}
impl ErrorType for EncoderPin {
type Error = E;
}
#[derive(Debug)]
pub struct E;
impl Error for E {
fn kind(&self) -> ErrorKind {
ErrorKind::Other
}
}
fn init_heap() {
const HEAP_SIZE: usize = 32 * 1024;
static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit();
unsafe {
esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
HEAP.as_mut_ptr() as *mut u8,
HEAP_SIZE,
esp_alloc::MemoryCapability::Internal.into(),
));
}
}
#[main]
fn main() -> ! {
init_heap();
esp_println::logger::init_logger_from_env();
let config = Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
let mut display = TftDisplay::new(
Output::new(peripherals.GPIO25, Level::Low),
Output::new(peripherals.GPIO13, Level::Low),
Input::new(peripherals.GPIO12, Pull::Up),
Output::new(peripherals.GPIO2, Level::Low),
Output::new(peripherals.GPIO22, Level::Low),
Output::new(peripherals.GPIO21, Level::Low),
Output::new(peripherals.GPIO32, Level::Low),
peripherals.SPI2,
);
let mut rtc = Rtc::new(peripherals.LPWR);
let wake_pin = Input::new(peripherals.GPIO16, Pull::None);
// let mut wake_pins: [&mut dyn RtcPin; 1] = [&mut *wake_pin.into_ref()];
let ext0 = Ext0WakeupSource::new(wake_pin, WakeupLevel::Low);
let dt_pin = EncoderPin::new(Input::new(peripherals.GPIO4, Pull::Up));
let clk_pin = EncoderPin::new(Input::new(peripherals.GPIO0, Pull::Up));
let mut encoder = RotaryEncoder::new(dt_pin, clk_pin).into_standard_mode();
let mut model = MainModel::new(&mut Rng::new(peripherals.RNG));
// TEST:
for i in 0..PLANTER_COUNT {
model.set_planter_active(i, i % 2 == 0);
model.planter_models[i].watering_amount = WateringLevel::Level2;
info!("level: {}", model.planter(i).watering_amount as u8);
}
let mut neopixel = Neopixel::new(peripherals.RMT, peripherals.GPIO17);
let delay = Delay::new();
let mut i: usize = 0;
let mut i_sleep = 0;
// sck_pin rck_pin, ser_pin
let mut pump_control = PumpControl::new(
Output::new(peripherals.GPIO14, Level::Low),
Output::new(peripherals.GPIO27, Level::Low),
Output::new(peripherals.GPIO26, Level::Low)
);
pump_control.set_output(7, true, false);
// TEST:
loop {
delay.delay_millis(1);
match encoder.update() {
Direction::Clockwise => info!("CW"),
Direction::Anticlockwise => info!("anti"),
Direction::None => ()
};
/*delay.delay_millis(1000);
i_sleep += 1;
if i < 8 {
display.render_page(model.planter(i));
info!(
"planter[{}] level: {}",
model.planter(i).id,
model.planter(i).watering_amount as u8,
);
neopixel.set_color(model.planter(i).color_as_rgb8(), Some(i), true);
i += 1;
} else {
neopixel.turn_off(None);
display.render_dashboard(model, 255);
for pl in model.planter_models {
neopixel.set_color(pl.color_as_rgb8(), Some(pl.id), false);
delay.delay_millis(10);
}
i = 0;
}*/
/*
if i_sleep == 5 {
rtc.sleep_deep(&[&ext0]);
}
*/
}
//
// // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/v0.23.1/examples/src/bin
}