Something went wrong. Try again.
Firmware for a USB screen displaying system stats
Something went wrong. Try again.
6.0 kB · 174 lines
Rust
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175use embedded_graphics::Drawable;use embedded_graphics::framebuffer::{Framebuffer, buffer_size};use embedded_graphics::geometry::Point;use embedded_graphics::image::ImageDrawable;use embedded_graphics::mono_font::MonoTextStyle;use embedded_graphics::mono_font::ascii::FONT_10X20;use embedded_graphics::pixelcolor::Rgb565;use embedded_graphics::pixelcolor::raw::LittleEndian;use embedded_graphics::text::{Alignment, Text};use embedded_hal_bus::spi::ExclusiveDevice;use embedded_iconoir::prelude::IconoirNewIcon;use embedded_iconoir::size24px::development::ElectronicsChip;use embedded_iconoir::size24px::devices::SaveFloppyDisk;use embedded_iconoir::size24px::other::Clock;use embedded_iconoir::size24px::system::Cpu;use embedded_iconoir::size24px::weather::TemperatureLow;use embedded_iconoir::{Icon, icons};use esp_hal::mcpwm::operator::PwmPin;use esp_hal::peripherals::MCPWM0;use esp_hal::spi::master::Spi;
use mipidsi::interface::SpiInterface;use mipidsi::models::ST7735s;
use embedded_graphics::draw_target::DrawTarget;use embedded_graphics::prelude::RgbColor;
use core::fmt::Debug;
use crate::Data;use crate::graph::Graph;use crate::label::Label;
pub struct DisplayController { display: Display, backlight: Backlight,
cpu_graph: Graph<60, 5, ICON_SIZE>, memory_graph: Graph<60, 5, ICON_SIZE>,
cpu_label: Label<Icon<Rgb565, Cpu>>, memory_label: Label<Icon<Rgb565, ElectronicsChip>>, disk_label: Label<Icon<Rgb565, SaveFloppyDisk>>, temp_label: Label<Icon<Rgb565, TemperatureLow>>, uptime_label: Label<Icon<Rgb565, Clock>>,}
type Display = mipidsi::Display< SpiInterface< 'static, ExclusiveDevice< Spi<'static, esp_hal::Blocking>, esp_hal::gpio::Output<'static>, esp_hal::delay::Delay, >, esp_hal::gpio::Output<'static>, >, ST7735s, esp_hal::gpio::Output<'static>,>;
type Backlight = PwmPin<'static, MCPWM0<'static>, 0, true>;
pub const PADDING: i32 = 5;pub const ICON_SIZE: i32 = 24;
impl DisplayController { const CPU_ICON: Point = Point::new(PADDING, PADDING); const MEMORY_ICON: Point = Point::new(PADDING, Self::CPU_ICON.y + ICON_SIZE + PADDING); const TEMP_ICON: Point = Point::new(PADDING * 3 + 80, Self::MEMORY_ICON.y + ICON_SIZE + PADDING); const DISK_ICON: Point = Point::new(PADDING, Self::MEMORY_ICON.y + ICON_SIZE + PADDING); const UPTIME_ICON: Point = Point::new(PADDING, Self::DISK_ICON.y + ICON_SIZE + PADDING);
const CPU_GRAPH: Point = Point::new(PADDING * 3 + 80, Self::CPU_ICON.y + ICON_SIZE); const MEMORY_GRAPH: Point = Point::new(PADDING * 3 + 80, Self::MEMORY_ICON.y + ICON_SIZE);
pub fn new(display: Display, backlight: Backlight) -> Self { let cpu_icon = icons::size24px::system::Cpu::new(Rgb565::WHITE); let memory_icon = icons::size24px::development::ElectronicsChip::new(Rgb565::WHITE); let disk_icon = icons::size24px::devices::SaveFloppyDisk::new(Rgb565::WHITE); let temp_icon = icons::size24px::weather::TemperatureLow::new(Rgb565::WHITE); let uptime_icon = icons::size24px::other::Clock::new(Rgb565::WHITE);
Self { display, backlight, cpu_label: Label::new(cpu_icon, Self::CPU_ICON), memory_label: Label::new(memory_icon, Self::MEMORY_ICON), disk_label: Label::new(disk_icon, Self::DISK_ICON), temp_label: Label::new(temp_icon, Self::TEMP_ICON), uptime_label: Label::new(uptime_icon, Self::UPTIME_ICON), cpu_graph: Graph::new(Self::CPU_GRAPH), memory_graph: Graph::new(Self::MEMORY_GRAPH), } }
pub fn set_backlight(&mut self, brightness: u16) { self.backlight.set_timestamp(brightness); }
pub fn clear(&mut self) { self.display.clear(Rgb565::BLACK).unwrap(); }
pub fn draw_no_connection(&mut self) { self.clear();
static CHARACTER_STYLE: MonoTextStyle<'static, Rgb565> = MonoTextStyle::new(&FONT_10X20, Rgb565::WHITE);
let text = Text::with_alignment( "No Data", Point::new(PADDING, PADDING + 11), CHARACTER_STYLE, Alignment::Left, );
text.draw(&mut self.display).unwrap(); }
pub fn draw_data(&mut self, data: &Data) { let mut fb = Framebuffer::< Rgb565, _, LittleEndian, 320, 240, { buffer_size::<Rgb565>(320, 240) }, >::new();
self.cpu_label .draw(&mut fb, format_args!("{:0.1}%", data.cpu_usage * 100.0)); self.memory_label .draw(&mut fb, format_args!("{:0.1}%", data.memory_usage * 100.0)); self.temp_label .draw(&mut fb, format_args!("{:0.0}C", data.max_temp)); self.disk_label .draw(&mut fb, format_args!("{:0.1}%", data.disk_usage * 100.0));
self.draw_uptime(&mut fb, data);
self.cpu_graph.add_value(data.cpu_usage); self.memory_graph.add_value(data.memory_usage);
self.cpu_graph.draw(&mut fb); self.memory_graph.draw(&mut fb);
fb.as_image().draw(&mut self.display).unwrap(); }
fn draw_uptime<T>(&self, draw_target: &mut T, data: &Data) where T: DrawTarget<Color = Rgb565>, <T as DrawTarget>::Error: Debug, { let days = data.uptime / 86_400; let hours = (data.uptime % 86_400) / 3_600; let minutes = (data.uptime % 3_600) / 60; let seconds = data.uptime % 60;
let args = if days > 0 { format_args!("{}d {}h", days, hours) } else if hours > 0 { format_args!("{}h {}m", hours, minutes) } else if minutes > 0 { format_args!("{}m {}s", minutes, seconds) } else { format_args!("{}s", seconds) };
self.uptime_label.draw(draw_target, args); }}