Files
OptoTest/OpticalChannelTester/Display.cpp
Razvalyaev 4b88ac6a42 Merge remote-tracking branch 'OptoTest/master'
# Conflicts:
#	OpticalChannelTester/App.cpp
2026-08-07 09:59:53 +03:00

65 lines
2.3 KiB
C++

#include "Display.h"
#include "Config.h"
#include "Log.h"
#include <Wire.h>
#include <esp_log.h>
#include <string.h>
Display::Display() : oled_(128, 32, &Wire, -1) {}
bool Display::begin() {
Wire.begin(GPIO_SDA, GPIO_SCL);
// An absent optional OLED produces a large burst of ESP-IDF NACK messages.
// Probe it once and keep the I2C driver quiet when no display is connected.
esp_log_level_set("i2c.master", ESP_LOG_NONE);
Wire.beginTransmission(OLED_ADDRESS);
if (Wire.endTransmission() != 0) {
ok_ = false;
Log::printf("OLED", "not detected at I2C address=0x%02X", OLED_ADDRESS);
return false;
}
ok_ = oled_.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS);
if (ok_) {
oled_.setRotation(OLED_ROTATION);
oled_.setTextColor(SSD1306_WHITE);
oled_.setTextSize(1);
}
Log::printf("OLED", "initialization %s, I2C address=0x%02X", ok_ ? "OK" : "FAILED", OLED_ADDRESS);
return ok_;
}
void Display::fit(char *s) {
int16_t x, y; uint16_t w, h;
while (*s) {
oled_.getTextBounds(s, 0, 0, &x, &y, &w, &h);
if (w <= 128) break;
s[strlen(s) - 1] = '\0';
}
}
void Display::show(const char *a, const char *b) {
char one[32], two[32];
snprintf(one, sizeof(one), "%s", a ? a : ""); snprintf(two, sizeof(two), "%s", b ? b : "");
// Serial is the primary UI mirror and remains available when OLED is absent.
Log::printf("UI", "%s | %s", one, two);
if (!ok_) return;
fit(one); fit(two);
oled_.clearDisplay(); oled_.setCursor(0, 3); oled_.print(one);
oled_.setCursor(0, 19); oled_.print(two); oled_.display();
}
void Display::formatFrequency(float hz, char *out, size_t n) {
float value = hz; const char *suffix = "Hz";
if (hz >= 1000000.0f) { value = hz / 1000000.0f; suffix = "M"; }
else if (hz >= 1000.0f) { value = hz / 1000.0f; suffix = "k"; }
if (fabsf(value - roundf(value)) < 0.005f) snprintf(out, n, "%.0f%s", value, suffix);
else if (fabsf(value * 10.0f - roundf(value * 10.0f)) < 0.005f) snprintf(out, n, "%.1f%s", value, suffix);
else snprintf(out, n, "%.2f%s", value, suffix);
}
void Display::formatDuration(uint64_t us, char *out, size_t n) {
const uint64_t minutes = us / 60000000ULL;
if (minutes < 60) snprintf(out, n, "%02llu:%02llu", minutes, (us / 1000000ULL) % 60ULL);
else snprintf(out, n, "%llu:%02llu", minutes / 60ULL, minutes % 60ULL);
}