#pragma once #include "DisplayDriver.h" #include #include #ifndef DISPLAY_ADDRESS #define DISPLAY_ADDRESS 0x3C #endif #ifndef OLED_WIDTH #define OLED_WIDTH 72 #endif #ifndef OLED_HEIGHT #define OLED_HEIGHT 40 #endif class U8g2Display : public DisplayDriver { // U8g2 constructor for SSD1306/SSD1315 72×40 panel — handles all // GDDRAM column/page offsets, SETMULTIPLEX, SETDISPLAYOFFSET internally U8G2_SSD1306_72X40_ER_F_HW_I2C _u8g2; bool _isOn; uint8_t _drawColor; // Font metrics for current font (cached on setTextSize) uint8_t _fontAscent; uint8_t _fontHeight; void applyFont(int sz) { if (sz >= 2) { _u8g2.setFont(u8g2_font_6x10_mr); // slightly larger font for better readability. TODO: more font sizes? } else { _u8g2.setFont(u8g2_font_5x7_mr); } _fontAscent = _u8g2.getAscent(); _fontHeight = _u8g2.getAscent() - _u8g2.getDescent(); } public: U8g2Display() : DisplayDriver(OLED_WIDTH, OLED_HEIGHT), _u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE), _isOn(false), _drawColor(1), _fontAscent(5), _fontHeight(6) {} bool begin() { // Wire must already be initialised by board.begin() before this is called bool ok = _u8g2.begin(); if (ok) { _u8g2.setI2CAddress(DISPLAY_ADDRESS * 2); // U8g2 uses 8-bit address _u8g2.setFontPosTop(); // y coordinate = top of text, not baseline _u8g2.setFontMode(1); // transparent background applyFont(1); // default to compact font _isOn = true; } return ok; } bool isOn() override { return _isOn; } void turnOn() override { _u8g2.setPowerSave(0); _isOn = true; } void turnOff() override { _u8g2.setPowerSave(1); _isOn = false; } void clear() override { _u8g2.clearBuffer(); _u8g2.sendBuffer(); } void startFrame(Color bkg = DARK) override { _u8g2.clearBuffer(); _drawColor = 1; _u8g2.setDrawColor(1); applyFont(1); } void setTextSize(int sz) override { applyFont(sz); } void setColor(Color c) override { _drawColor = (c != DARK) ? 1 : 0; _u8g2.setDrawColor(_drawColor); } void setCursor(int x, int y) override { _cursorX = x; _cursorY = y; } void print(const char* str) override { _u8g2.setDrawColor(_drawColor); _u8g2.drawStr(_cursorX, _cursorY, str); } void fillRect(int x, int y, int w, int h) override { _u8g2.setDrawColor(_drawColor); _u8g2.drawBox(x, y, w, h); } void drawRect(int x, int y, int w, int h) override { _u8g2.setDrawColor(_drawColor); _u8g2.drawFrame(x, y, w, h); } void drawXbm(int x, int y, const uint8_t* bits, int w, int h) override { _u8g2.setDrawColor(1); _u8g2.drawXBM(x, y, w, h, bits); } uint16_t getTextWidth(const char* str) override { return _u8g2.getStrWidth(str); } void endFrame() override { _u8g2.sendBuffer(); } private: int _cursorX = 0; int _cursorY = 0; };