use esp_hal::Blocking;
use gc9a01::{mode::BufferedGraphics, prelude::*, Gc9a01, SPIDisplayInterface};
use esp_hal::delay::Delay;
use esp_hal::gpio::{Input, Level, Output, Pull};
use esp_hal::spi::{
master::{Config as SpiConfig, Spi},
Mode,
};
use esp_hal::time::RateExtU32;
use esp_hal::i2c::master::{Config as I2cConfig, I2c as EspI2C};
use embedded_hal_bus::spi::{ExclusiveDevice, NoDelay};
use rotary_encoder_hal::{DefaultPhase, Rotary};
use defmt::error;
use crate::ft3267::{Ft3267, TouchPoint};
pub type M5DialDisplay = Gc9a01<
SPIInterface<
ExclusiveDevice<Spi<'static, Blocking>, Output<'static>, NoDelay>,
Output<'static>,
>,
DisplayResolution240x240,
BufferedGraphics<DisplayResolution240x240>,
>;
pub struct M5DialBsp {
pub display: M5DialDisplay,
touch: Ft3267,
display_bl: Output<'static>,
pub encoder: Rotary<Input<'static>, Input<'static>, DefaultPhase>,
hold: Output<'static>,
wake: Input<'static>,
last_wake_state: bool,
tp_i2c: EspI2C<'static, Blocking>,
}
pub fn init(peripherals: esp_hal::peripherals::Peripherals) -> M5DialBsp {
let mut delay = Delay::new();
let spi = Spi::new(
peripherals.SPI2,
SpiConfig::default()
.with_frequency(50.MHz())
.with_mode(Mode::_0),
)
.unwrap()
.with_sck(peripherals.GPIO6)
.with_mosi(peripherals.GPIO5);
let cs = Output::new(peripherals.GPIO7, Level::High);
let rs = Output::new(peripherals.GPIO4, Level::High);
let display_dev = ExclusiveDevice::new_no_delay(spi, cs).unwrap();
let display_iface = SPIDisplayInterface::new(display_dev, rs);
let mut display = Gc9a01::new(
display_iface,
DisplayResolution240x240,
DisplayRotation::Rotate180,
)
.into_buffered_graphics();
let mut display_reset = Output::new(peripherals.GPIO8, Level::High);
if display.reset(&mut display_reset, &mut delay).is_err() {
error!("Display reset error");
loop {}
}
if display.init(&mut delay).is_err() {
error!("Display Init error");
loop {}
}
display.clear();
display.fill(0x0);
if display.flush().is_err() {
error!("Display flush error");
}
let pin_a = Input::new(peripherals.GPIO41, Pull::None);
let pin_b = Input::new(peripherals.GPIO40, Pull::None);
let encoder = Rotary::new(pin_a, pin_b);
let bl = Output::new(peripherals.GPIO9, Level::Low);
let hold = Output::new(peripherals.GPIO46, Level::High);
let wake = Input::new(peripherals.GPIO42, Pull::None);
let wake_state = wake.is_low();
let mut tp_i2c = EspI2C::new(peripherals.I2C0, I2cConfig::default())
.unwrap()
.with_sda(peripherals.GPIO11)
.with_scl(peripherals.GPIO12);
let touch = Ft3267::new(0);
touch.init(&mut tp_i2c);
M5DialBsp {
display,
touch,
display_bl: bl,
encoder,
hold,
wake,
last_wake_state: wake_state,
tp_i2c,
}
}
impl M5DialBsp {
pub fn set_backlight(&mut self, state: bool) {
if state {
self.display_bl.set_high();
} else {
self.display_bl.set_low();
}
}
pub fn shutdown(&mut self) {
self.hold.set_low();
}
pub fn is_button_pushed(&mut self) -> bool {
self.last_wake_state = self.wake.is_low();
self.last_wake_state
}
pub fn has_button_changed(&mut self) -> Option<bool> {
let current_state = self.wake.is_low();
if current_state != self.last_wake_state {
self.last_wake_state = current_state;
Some(current_state)
} else {
None
}
}
pub fn touch_count(&mut self) -> Option<u8> {
let touch_count = self.touch.pool(&mut self.tp_i2c);
if touch_count > 0 {
Some(touch_count)
} else {
None
}
}
pub fn touch_position(&mut self, n: u8) -> TouchPoint {
self.touch.get_point(&mut self.tp_i2c, n)
}
}