mirror of
https://github.com/grillbaer/esp32-geiger-counter.git
synced 2025-12-21 13:23:15 +01:00
101 lines
2.8 KiB
C++
101 lines
2.8 KiB
C++
#include "U8g2lib.h"
|
|
|
|
#include "display.h"
|
|
|
|
// OLED display 128x64 with SH1106 controller
|
|
// on I2C GPIOs SCL 22 and SDA 21
|
|
U8G2_SH1106_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, 22, 21);
|
|
|
|
void initDisplay() {
|
|
// high I2c clock still results in about 100ms buffer transmission to OLED:
|
|
u8g2.setBusClock(1000000);
|
|
u8g2.begin();
|
|
}
|
|
|
|
void renderDigits(char uSphStr[16], char cpmStr[16]) {
|
|
uint16_t y = 14;
|
|
uint16_t xCpm = 56;
|
|
uint16_t xUSph = 127;
|
|
|
|
u8g2.setFont(u8g2_font_crox4hb_tr);
|
|
u8g2_uint_t w = u8g2.getStrWidth(uSphStr);
|
|
u8g2.setCursor(xUSph - w, y);
|
|
u8g2.print(uSphStr);
|
|
|
|
w = u8g2.getStrWidth(cpmStr);
|
|
u8g2.setCursor(xCpm - w, y);
|
|
u8g2.print(cpmStr);
|
|
|
|
y = 21;
|
|
u8g2.setFont(u8g2_font_4x6_tf);
|
|
w = u8g2.getStrWidth("µS/h");
|
|
u8g2.setCursor(xUSph - w, y);
|
|
u8g2.print("µS/h");
|
|
|
|
w = u8g2.getStrWidth("cnt/min");
|
|
u8g2.setCursor(xCpm - w, y);
|
|
u8g2.print("cnt/min");
|
|
}
|
|
|
|
void renderHistoryBarGraph(GeigerData &geigerData) {
|
|
const uint16_t bars = 120;
|
|
const uint16_t maxBarHeight = 40;
|
|
const uint16_t samplesPerBar = geigerData.sampleCount / bars;
|
|
const uint16_t barsPerMinute = 60
|
|
/ (samplesPerBar * geigerData.sampleSeconds);
|
|
|
|
// determine max value for y scale:
|
|
uint16_t offset = geigerData.getCurrentSample() % samplesPerBar + 1;
|
|
uint32_t maxPulses = 0;
|
|
for (int16_t i = 0; i < bars - 1; i++) {
|
|
const uint32_t prevPulses = geigerData.getPreviousPulses(offset,
|
|
samplesPerBar);
|
|
if (prevPulses > maxPulses)
|
|
maxPulses = prevPulses;
|
|
|
|
offset += samplesPerBar;
|
|
}
|
|
|
|
const float maxUSph = geigerData.toMicroSievertPerHour(maxPulses,
|
|
samplesPerBar);
|
|
const float uSphPerPixel = maxUSph > 40. ? 10. : maxUSph > 4. ? 1. :
|
|
maxUSph > 0.4 ? 0.1 : 0.01;
|
|
// labels and grid
|
|
u8g2.setFont(u8g2_font_4x6_tn);
|
|
char s[10];
|
|
for (uint16_t i = 10; i <= maxBarHeight; i += 10) {
|
|
u8g2.setCursor(0, 63 - i + 3);
|
|
if (uSphPerPixel >= 0.1)
|
|
sprintf(s, "%.0f", i * uSphPerPixel);
|
|
else
|
|
sprintf(s, ".%.0f", i * uSphPerPixel * 10);
|
|
|
|
u8g2.print(s);
|
|
for (int16_t x = 127 - barsPerMinute; x >= 8; x -= barsPerMinute) {
|
|
u8g2.drawPixel(x, 63 - i);
|
|
}
|
|
}
|
|
|
|
// bars
|
|
offset = geigerData.getCurrentSample() % samplesPerBar + 1;
|
|
for (int16_t i = 0; i < bars - 1; i++) {
|
|
const uint32_t prevPulses = geigerData.getPreviousPulses(offset,
|
|
samplesPerBar);
|
|
const float uSph = geigerData.toMicroSievertPerHour(prevPulses,
|
|
samplesPerBar);
|
|
offset += samplesPerBar;
|
|
uint16_t barHeight = 1 + (int) ((uSph / uSphPerPixel));
|
|
if (barHeight > 40)
|
|
barHeight = 40;
|
|
|
|
u8g2.drawVLine(127 - i, 63 - barHeight, barHeight);
|
|
}
|
|
}
|
|
|
|
void updateDisplay(GeigerData &geigerData, char uSphStr[16], char cpmStr[16]) {
|
|
u8g2.clearBuffer();
|
|
renderDigits(uSphStr, cpmStr);
|
|
renderHistoryBarGraph(geigerData);
|
|
u8g2.sendBuffer();
|
|
}
|