separate display to its own file
This commit is contained in:
86
display.cpp
Normal file
86
display.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include <ctype.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "hardware/i2c.h"
|
||||
#include "pico-ssd1306/ssd1306.h"
|
||||
#include "pico-ssd1306/textRenderer/TextRenderer.h"
|
||||
#include "hardware/gpio.h"
|
||||
|
||||
#include "display.h"
|
||||
#include <new>
|
||||
|
||||
|
||||
using namespace pico_ssd1306;
|
||||
|
||||
// Implement the methods declared in `display.h`.
|
||||
|
||||
// Use in-place storage for the SSD1306 object to avoid heap allocation on
|
||||
// constrained embedded systems. The storage is sized using the complete
|
||||
// `SSD1306` type (this file includes the concrete header), and the object
|
||||
// is constructed with placement-new during `init()` and explicitly destroyed
|
||||
// in the destructor.
|
||||
namespace {
|
||||
alignas(SSD1306) unsigned char display_storage[sizeof(SSD1306)];
|
||||
bool display_constructed = false;
|
||||
}
|
||||
DisplayManager::DisplayManager()
|
||||
: display_(nullptr)
|
||||
{
|
||||
last_echo_[0] = '\0';
|
||||
}
|
||||
|
||||
DisplayManager::~DisplayManager() {
|
||||
if (display_constructed && display_) {
|
||||
// Call destructor explicitly since we used placement-new.
|
||||
display_->~SSD1306();
|
||||
display_constructed = false;
|
||||
}
|
||||
display_ = nullptr;
|
||||
}
|
||||
|
||||
// (No singleton accessor — the DisplayManager is constructed explicitly by callers.)
|
||||
|
||||
void DisplayManager::init(uint8_t i2c_addr) {
|
||||
if (display_) return; // already initialized
|
||||
|
||||
// Initialize I2C for the SSD1306 display (common pins: SDA=GPIO4, SCL=GPIO5)
|
||||
i2c_init(i2c0, 400 * 1000);
|
||||
gpio_set_function(4, GPIO_FUNC_I2C);
|
||||
gpio_set_function(5, GPIO_FUNC_I2C);
|
||||
gpio_pull_up(4);
|
||||
gpio_pull_up(5);
|
||||
|
||||
// Construct the display object in pre-allocated storage to avoid heap use.
|
||||
display_ = reinterpret_cast<SSD1306 *>(display_storage);
|
||||
new (display_) SSD1306(i2c0, i2c_addr, Size::W128xH64);
|
||||
display_constructed = true;
|
||||
display_->setOrientation(false);
|
||||
display_->clear();
|
||||
display_->sendBuffer();
|
||||
|
||||
last_echo_[0] = '\0';
|
||||
refresh("> ", nullptr);
|
||||
}
|
||||
|
||||
void DisplayManager::refresh(const char *current_input, const char *last_echo) {
|
||||
if (!display_) return;
|
||||
display_->clear();
|
||||
|
||||
size_t input_len = current_input ? strlen(current_input) : 0;
|
||||
const unsigned char *input_font = (input_len > LAST_ECHO_VISIBLE_CHARS) ? font_5x8 : font_12x16;
|
||||
|
||||
pico_ssd1306::drawText(display_, input_font, current_input ? current_input : "", 0, 0);
|
||||
|
||||
const char *echo_to_draw = last_echo ? last_echo : (last_echo_[0] ? last_echo_ : "");
|
||||
pico_ssd1306::drawText(display_, font_12x16, echo_to_draw, 0, 20);
|
||||
|
||||
display_->sendBuffer();
|
||||
}
|
||||
|
||||
void DisplayManager::set_last_echo(const char *text) {
|
||||
if (!text) return;
|
||||
strncpy(last_echo_, text, sizeof(last_echo_) - 1);
|
||||
last_echo_[sizeof(last_echo_) - 1] = '\0';
|
||||
}
|
||||
|
||||
// No C-compatible wrappers: prefer `DisplayManager::instance()` API directly.
|
||||
Reference in New Issue
Block a user