Krolyxon
Commit fa8c856

Branches

Tags

Refs →

orion-rfsrcdriversdisplay.rs

94 lines · 3.2 KB · Rust

1//! SSD1306 128x64 OLED over the shared I2C0 bus.
2//!
3//! Parity reference: `src-arduino/ui/display.cpp` (u8g2 `..._F_HW_I2C`, font
4//! `u8g2_font_6x12_tr`). We approximate u8g2 with `embedded-graphics`
5//! `MonoTextStyle` + `FONT_6X10`, keeping the Arduino draw coordinates so menu
6//! layout matches 1:1. Drawing uses u8g2-style baseline coordinates
7//! (`Baseline::Alphabetic`): the given `y` is the text baseline, as in
8//! `u8g2.drawStr(x, y, ...)`.
9
10use embedded_graphics::{
11 mono_font::{
12 ascii::{FONT_6X10, FONT_9X18_BOLD},
13 MonoFont, MonoTextStyle,
14 },
15 pixelcolor::BinaryColor,
16 prelude::*,
17 primitives::{PrimitiveStyle, Rectangle},
18 text::{Baseline, Text},
19};
20use embedded_hal_bus::i2c::RefCellDevice;
21use esp_idf_hal::i2c::I2cDriver;
22use ssd1306::{
23 mode::{BufferedGraphicsMode, DisplayConfig},
24 prelude::*,
25 I2CDisplayInterface, Ssd1306,
26};
27
28use crate::board::board::SharedI2c;
29
30/// The I2C device the OLED talks over: a `RefCellDevice` sharing the `'static`
31/// bus so PN532 can later take a second device on the same `RefCell`.
32type OledI2c = RefCellDevice<'static, I2cDriver<'static>>;
33
34type Oled =
35 Ssd1306<I2CInterface<OledI2c>, DisplaySize128x64, BufferedGraphicsMode<DisplaySize128x64>>;
36
37pub struct Display {
38 raw: Oled,
39}
40
41impl Display {
42 /// Build + initialise the SSD1306 over the shared bus and clear the screen.
43 pub fn new(bus: SharedI2c) -> Self {
44 let dev = RefCellDevice::new(bus);
45 let iface = I2CDisplayInterface::new(dev);
46 let mut raw = Ssd1306::new(iface, DisplaySize128x64, DisplayRotation::Rotate0)
47 .into_buffered_graphics_mode();
48 raw.init().expect("ssd1306 init");
49
50 let mut display = Self { raw };
51 display.clear();
52 display.flush();
53 display
54 }
55
56 /// Clear the off-screen buffer (does not touch the panel until `flush`).
57 pub fn clear(&mut self) {
58 self.raw.clear_buffer();
59 }
60
61 /// Push the off-screen buffer to the panel (u8g2 `sendBuffer`).
62 pub fn flush(&mut self) {
63 let _ = self.raw.flush();
64 }
65
66 /// Normal text: foreground pixels on, baseline at `y`.
67 pub fn text(&mut self, x: i32, y: i32, s: &str) {
68 self.draw_text(x, y, s, &FONT_6X10, BinaryColor::On);
69 }
70
71 /// Reversed text (off pixels) for drawing over a filled box
72 /// (u8g2 `setDrawColor(0)`).
73 pub fn text_rev(&mut self, x: i32, y: i32, s: &str) {
74 self.draw_text(x, y, s, &FONT_6X10, BinaryColor::Off);
75 }
76
77 /// Large title text (approximates u8g2 `logisoso20`) for the splash screen.
78 pub fn title(&mut self, x: i32, y: i32, s: &str) {
79 self.draw_text(x, y, s, &FONT_9X18_BOLD, BinaryColor::On);
80 }
81
82 /// Filled rectangle (u8g2 `drawBox`).
83 pub fn fill_rect(&mut self, x: i32, y: i32, w: u32, h: u32) {
84 let _ = Rectangle::new(Point::new(x, y), Size::new(w, h))
85 .into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
86 .draw(&mut self.raw);
87 }
88
89 fn draw_text(&mut self, x: i32, y: i32, s: &str, font: &MonoFont<'static>, color: BinaryColor) {
90 let style = MonoTextStyle::new(font, color);
91 let _ = Text::with_baseline(s, Point::new(x, y), style, Baseline::Alphabetic)
92 .draw(&mut self.raw);
93 }
94}