#![no_std]
#![no_main]
use esp_hal::main;
use esp_hal::time::Duration;
use esp_hal::{clock::CpuClock, delay::Delay};
use embedded_graphics::{
mono_font::{MonoTextStyle, ascii::FONT_10X20 as THE_FONT},
pixelcolor::Rgb565,
prelude::*,
text::Text,
};
use rotary_encoder_hal::Direction;
use heapless::String;
use core::fmt::Write;
use defmt::{Debug2Format, debug, error, info};
use {defmt_rtt as _, esp_backtrace as _};
use esp_hal::gpio::{Event, Input, Io, Level, Output};
use esp_hal::{handler, ram};
use m5dial_bsp::{backlight, bsp::*};
extern crate alloc;
use core::cell::RefCell;
use critical_section::Mutex;
use rotary_encoder_hal::{DefaultPhase, Rotary};
esp_bootloader_esp_idf::esp_app_desc!();
static ENCODER: Mutex<RefCell<Option<Rotary<Input<'static>, Input<'static>, DefaultPhase>>>> =
Mutex::new(RefCell::new(None));
static POSITION: Mutex<RefCell<i32>> = Mutex::new(RefCell::new(0));
#[handler]
#[ram]
fn encoder_irq() {
debug!("In IRQ");
critical_section::with(|cs| {
let rot = ENCODER
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.update()
.unwrap();
match rot {
Direction::Clockwise => *POSITION.borrow_ref_mut(cs) += 1,
Direction::CounterClockwise => {
*POSITION.borrow_ref_mut(cs) -= 1;
}
Direction::None => {}
}
ENCODER
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.pin_a()
.clear_interrupt();
ENCODER
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.pin_b()
.clear_interrupt();
});
}
fn get_encoder_position() -> i32 {
critical_section::with(|cs| *POSITION.borrow_ref_mut(cs))
}
#[main]
fn main() -> ! {
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
let mut buzzer = m5dial_bsp::get_buzzer!(peripherals);
let mut display = m5dial_bsp::get_screen!(peripherals);
let mut encoder = m5dial_bsp::get_encoder!(peripherals);
let mut board = m5dial_bsp::board_init!(peripherals);
m5dial_bsp::make_display_backlight!(bl, peripherals);
bl.set_backlight(80);
const STYLE_LIST: [MonoTextStyle<Rgb565>; 7] = [
MonoTextStyle::new(&THE_FONT, RgbColor::BLUE),
MonoTextStyle::new(&THE_FONT, RgbColor::RED),
MonoTextStyle::new(&THE_FONT, RgbColor::GREEN),
MonoTextStyle::new(&THE_FONT, RgbColor::CYAN),
MonoTextStyle::new(&THE_FONT, RgbColor::YELLOW),
MonoTextStyle::new(&THE_FONT, RgbColor::MAGENTA),
MonoTextStyle::new(&THE_FONT, RgbColor::WHITE),
];
let mut style_index: usize = 0;
let mut buffer: String<64> = String::new();
esp_alloc::heap_allocator!(size: 72 * 1024);
let mut io = Io::new(peripherals.IO_MUX);
io.set_interrupt_handler(encoder_irq);
info!("On screen counter demo running!");
let tone_freq: u32 = 261;
buzzer
.tone(Rate::from_hz(tone_freq), Duration::from_millis(100))
.expect("start tone failed");
critical_section::with(|cs| {
encoder.pin_a().listen(Event::AnyEdge);
encoder.pin_b().listen(Event::AnyEdge);
ENCODER.borrow_ref_mut(cs).replace(encoder)
});
let mut old_pos: i32 = 0;
let mut need_redraw = true;
let mut backlight_intensity = 80;
loop {
if let Some(state) = board.has_button_changed() {
if state == false {
style_index = (style_index + 1) % STYLE_LIST.len();
need_redraw = true;
}
}
let current_pos = get_encoder_position();
if current_pos != old_pos {
debug!("Encoder at new position {} ({})", current_pos, old_pos);
need_redraw = true;
let increment = current_pos - old_pos;
backlight_intensity += increment;
if backlight_intensity > 100 {
backlight_intensity = 100;
}
if backlight_intensity <= 0 {
backlight_intensity = 0;
}
old_pos = current_pos;
}
if need_redraw {
bl.set_backlight(backlight_intensity as u8);
buffer.clear();
if write!(&mut buffer, "Backlight {}", backlight_intensity).is_ok() {
display.clear();
Text::with_alignment(
&buffer,
display.bounding_box().center(),
STYLE_LIST[style_index],
embedded_graphics::text::Alignment::Center,
)
.draw(&mut display)
.unwrap();
if display.flush().is_err() {
error!("Display flush error");
}
} else {
error!("Buffer overflow");
}
need_redraw = false;
}
}
}