use anyhow::{anyhow, Result, Ok}; use embedded_graphics::{ mono_font::{ascii::FONT_10X20, iso_8859_10::FONT_6X10, MonoTextStyle}, pixelcolor::Rgb565, prelude::{Dimensions, Drawable, Point, Primitive, RgbColor}, primitives::{PrimitiveStyleBuilder, Rectangle}, text::Text, }; use embedded_hal::{delay::blocking::DelayUs, i2c::blocking::{I2c, Operation}}; use esp_idf_hal::{ delay, gpio::{self}, i2c::{self, Master, I2C0}, prelude::*, }; use log::warn; use ssd1306::{ mode::{BufferedGraphicsMode, DisplayConfig}, prelude::I2CInterface, size::DisplaySize128x64, Ssd1306, }; type Display = Ssd1306< I2CInterface, gpio::Gpio10>>, DisplaySize128x64, BufferedGraphicsMode, >; pub struct Screen { pub display: Option, } impl Screen { pub fn new( i2c: i2c::I2C0, sda: gpio::Gpio4, scl: gpio::Gpio10, ) -> Result { let config = ::default().baudrate(400.kHz().into()); let mut i2c = i2c::Master::::new(i2c, i2c::MasterPins { sda, scl }, config)?; let mut buff = [0u8; 10]; if let Err(err) = i2c.transaction(0x3C, &mut [Operation::Read(&mut buff)]) { warn!("Failed to initialize display: {}", err); warn!("Failed to initialize display: {}", err); warn!("Failed to initialize display: {}", err); warn!("Failed to initialize display: {}", err); warn!("Failed to initialize display: {}", err); return Ok(Self { display: None }); } let di = ssd1306::I2CDisplayInterface::new(i2c); let mut delay = delay::Ets; delay.delay_ms(10_u32)?; let mut display = ssd1306::Ssd1306::new( di, ssd1306::size::DisplaySize128x64, ssd1306::rotation::DisplayRotation::Rotate0, ) .into_buffered_graphics_mode(); display .init() .map_err(|err| anyhow!("Can not init display: {:?}", err))?; let mut instance = Screen { display: Some(display) }; instance.draw_boot()?; Ok(instance) } pub fn draw_boot(&mut self) -> Result<()> { if self.display.is_none() { return Ok(()); } let display = self.display.as_mut().unwrap(); display.clear(); Rectangle::new( display.bounding_box().top_left, display.bounding_box().size, ) .into_styled( PrimitiveStyleBuilder::new() .fill_color(Rgb565::BLUE.into()) .stroke_color(Rgb565::YELLOW.into()) .stroke_width(1) .build(), ) .draw(display) .expect("Failed to draw rectangle"); Text::new( "Ivan's UPS", Point::new( 12, (display.bounding_box().size.height - 10) as i32 / 2 + 1, ), MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE.into()), ) .draw(display) .expect("Failed to draw text"); display .flush() .map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?; Ok(()) } pub fn draw_voltage(&mut self, adapter: f32, battery: f32) -> Result<()> { if let Some(display) = self.display.as_mut() { display.clear(); Text::new( format!("Adp. {:.2} mV", adapter).as_str(), Point::new(12, 24), MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE.into()), ) .draw(display) .expect("Failed to draw text"); Text::new( format!("Bat. {:.2} mV", battery).as_str(), Point::new(12, 36), MonoTextStyle::new(&FONT_6X10, Rgb565::WHITE.into()), ) .draw(display) .expect("Failed to draw text"); display .flush() .map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?; } Ok(()) } }