2018-11-14 07:43:50 +00:00
|
|
|
#include <Arduino.h>
|
|
|
|
#include <U8g2lib.h>
|
|
|
|
#include <Wire.h>
|
|
|
|
|
|
|
|
#include "display.h"
|
|
|
|
|
|
|
|
// display
|
2018-11-14 20:34:51 +00:00
|
|
|
//U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ 16, /* clock=*/ 5, /* data=*/ 4);
|
|
|
|
U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=16*/ -1, /* clock=*/ 5, /* data=*/ 4);
|
|
|
|
//U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0);
|
|
|
|
//U8X8_SH1106_128X64_NONAME_4W_HW_SPI u8g2(/* cs=*/ 10, /* dc=*/ 9, /* reset=*/ 8);
|
2018-11-14 07:43:50 +00:00
|
|
|
|
|
|
|
#define LOGO16_GLCD_HEIGHT 16
|
|
|
|
#define LOGO16_GLCD_WIDTH 16
|
|
|
|
static const unsigned char PROGMEM logo16_glcd_bmp[] =
|
|
|
|
{ 0x00, 0xc0, // B00000000, B11000000,
|
|
|
|
0x01, 0xc0, // B00000001, B11000000,
|
|
|
|
0x01, 0xc0, // B00000001, B11000000,
|
|
|
|
0x03, 0xe0, // B00000011, B11100000,
|
|
|
|
0xf3, 0xe0, // B11110011, B11100000,
|
|
|
|
0xfe, 0xf8, // B11111110, B11111000,
|
|
|
|
0x7e, 0xff, // B01111110, B11111111,
|
|
|
|
0x33, 0x9f, // B00110011, B10011111,
|
|
|
|
0x1f, 0xfc, // B00011111, B11111100,
|
|
|
|
0x0d, 0x70, // B00001101, B01110000,
|
|
|
|
0x1b, 0xa0, // B00011011, B10100000,
|
|
|
|
0x3f, 0xe0, // B00111111, B11100000,
|
|
|
|
0x3f, 0xf0, // B00111111, B11110000,
|
|
|
|
0x7c, 0xf0, // B01111100, B11110000,
|
|
|
|
0x70, 0x70, // B01110000, B01110000,
|
|
|
|
0x00, 0x30 // B00000000, B00110000
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void Display::setSmallTextSize(void) { u8g2.setFont(/*u8g2_font_profont10_tf*/ u8g2_font_4x6_tf ); }
|
|
|
|
int Display::getTextHeight(void) { return u8g2.getMaxCharHeight(); }
|
|
|
|
int Display::getTextCharsPerLine(void) { return u8g2.getDisplayWidth() / u8g2.getMaxCharWidth(); }
|
|
|
|
|
|
|
|
void Display::setNormalTextSize(void) { u8g2.setFont(/*u8g2_font_t0_11_tf*/ u8g2_font_mozart_nbp_tf); }
|
|
|
|
//static uint8_t getNormalTextHeight() { return Org_01.yAdvance; }
|
|
|
|
//static uint8_t getNormalTextCharsPerLine() { return 24; }
|
|
|
|
|
|
|
|
void Display::setLargeTextSize(void) { u8g2.setFont(u8g2_font_9x15B_tf); }
|
|
|
|
//static uint8_t getLargeTextHeight() { return FreeMonoBold9pt7b.yAdvance; }
|
|
|
|
//static uint8_t getLargeTextCharsPerLine() { return 12; }
|
|
|
|
|
|
|
|
Display::Display() {
|
|
|
|
currentScreen = NoScreen;
|
|
|
|
numberLogLines = 0;
|
|
|
|
setClockName("noname");
|
|
|
|
setClockSpeed("---");
|
|
|
|
setTime(5, 0);
|
|
|
|
setClockWeekday("Mon");
|
|
|
|
setClockHalted(true);
|
|
|
|
setNumberKnownClients(0);
|
2018-11-14 10:27:06 +00:00
|
|
|
for (int i=0; i<MAX_NUMBER_CLIENTS_DISPLAYED; ++i) setClientName(i, "");
|
2018-11-14 07:43:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Display::begin(void) {
|
|
|
|
u8g2.begin();
|
|
|
|
u8g2.setPowerSave(0);
|
|
|
|
setLargeTextSize();
|
|
|
|
u8g2.drawStr(0,16,"Booting FastClock");
|
|
|
|
u8g2.sendBuffer();
|
2018-12-01 12:12:33 +00:00
|
|
|
delay(400);
|
2018-11-14 07:43:50 +00:00
|
|
|
//addLogMessage("Display initialized");
|
|
|
|
}
|
|
|
|
|
2018-12-01 12:59:16 +00:00
|
|
|
#define BOOT_CLOCK_WIDTH 16
|
|
|
|
#define BOOT_CLOCK_PIXEL_WIDTH 2
|
|
|
|
#define BOOT_CLOCK_PIXELS_PER_SIDE (BOOT_CLOCK_WIDTH / BOOT_CLOCK_PIXEL_WIDTH - 1)
|
|
|
|
#define BOOT_CLOCK_PIXELS (BOOT_CLOCK_PIXELS_PER_SIDE * 4)
|
|
|
|
#define BOOT_CLOCK_FORWARD_AFTER_ms 200
|
|
|
|
// Example: WIDTH=16, PIXEL_WIDTH = 4 --> 3 pixels per side (4 seen, but one would be counted double)
|
|
|
|
// Result: Pixels a / b / c / d
|
|
|
|
// a1 a2 a3 b1
|
|
|
|
// d3 b2
|
|
|
|
// d2 b3
|
|
|
|
// d1 c3 c2 c1
|
|
|
|
//
|
|
|
|
void Display::showBootClock(void) {
|
|
|
|
static unsigned long lastClockUpdate_ts = 0;
|
|
|
|
static int tick = 0;
|
|
|
|
|
|
|
|
if (millis() - lastClockUpdate_ts >= BOOT_CLOCK_FORWARD_AFTER_ms) {
|
|
|
|
++tick;
|
|
|
|
if (tick >= BOOT_CLOCK_PIXELS) {
|
|
|
|
tick = 0;
|
|
|
|
/*
|
|
|
|
u8g2.setDrawColor(0);
|
|
|
|
u8g2.drawBox(u8g2.getDisplayWidth()-BOOT_CLOCK_WIDTH, 0, BOOT_CLOCK_WIDTH, BOOT_CLOCK_WIDTH);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
u8g2.setDrawColor(2); // XOR
|
|
|
|
// draw appropriate pixels
|
|
|
|
int x=0, y=0, side, pixelOnSide; // side = 0, 1, 2, 3 for a, b, c, d
|
|
|
|
|
|
|
|
side = tick / BOOT_CLOCK_PIXELS_PER_SIDE;
|
|
|
|
pixelOnSide = tick % BOOT_CLOCK_PIXELS_PER_SIDE;
|
|
|
|
switch (side) {
|
|
|
|
case 0: // top
|
|
|
|
x = u8g2.getDisplayWidth() - BOOT_CLOCK_WIDTH + pixelOnSide * BOOT_CLOCK_PIXEL_WIDTH;
|
|
|
|
y = 0;
|
|
|
|
break;
|
|
|
|
case 1: // right
|
|
|
|
x = u8g2.getDisplayWidth() - BOOT_CLOCK_PIXEL_WIDTH;
|
|
|
|
y = pixelOnSide * BOOT_CLOCK_PIXEL_WIDTH;
|
|
|
|
break;
|
|
|
|
case 2: // bottom
|
|
|
|
x = u8g2.getDisplayWidth() - (1 + pixelOnSide) * BOOT_CLOCK_PIXEL_WIDTH;
|
|
|
|
y = BOOT_CLOCK_WIDTH - BOOT_CLOCK_PIXEL_WIDTH;
|
|
|
|
break;
|
|
|
|
case 3: // left
|
|
|
|
x = u8g2.getDisplayWidth() - BOOT_CLOCK_WIDTH;
|
|
|
|
y = BOOT_CLOCK_WIDTH - (1 + pixelOnSide) * BOOT_CLOCK_PIXEL_WIDTH;
|
|
|
|
}
|
|
|
|
u8g2.drawBox(x, y, BOOT_CLOCK_PIXEL_WIDTH, BOOT_CLOCK_PIXEL_WIDTH);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
u8g2.drawCircle(u8g2.getDisplayWidth()-BOOT_CLOCK_WIDTH/2, BOOT_CLOCK_WIDTH/2, BOOT_CLOCK_PIXEL_WIDTH, U8G2_DRAW_ALL);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
u8g2.sendBuffer();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-11-14 07:43:50 +00:00
|
|
|
bool Display::showBootSequenceFinished(unsigned int ms_per_step) {
|
|
|
|
static int step = 0;
|
|
|
|
static unsigned long lastStep_ms = 0;
|
|
|
|
|
|
|
|
if (step > 4) return true; // all is done; the value "4" corresponds to the number of steps in following case statement!
|
2018-12-01 12:59:16 +00:00
|
|
|
showBootClock();
|
2018-11-14 07:43:50 +00:00
|
|
|
if (ms_per_step > millis() - lastStep_ms) return false; // do nothing, if last step execution is not long enough ago
|
|
|
|
Serial.print("showBootSequence: step="); Serial.println(step);
|
|
|
|
lastStep_ms = millis();
|
|
|
|
|
|
|
|
switch (step) {
|
|
|
|
case 0:
|
|
|
|
currentScreen = BootSequenceScreen;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
break;
|
|
|
|
case 3:
|
2018-12-01 12:59:16 +00:00
|
|
|
//u8g2.drawXBMP(60, 0, 16, 16, logo16_glcd_bmp);
|
|
|
|
//u8g2.sendBuffer();
|
2018-11-14 07:43:50 +00:00
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
break; // empty step to be sure, that last step is displayed long enough
|
|
|
|
// if you add a step, then you need to change the condition at the beginning of this method as well (if (step > ...)
|
|
|
|
default: // do nothing
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++step;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Display::showLog(void) {
|
|
|
|
currentScreen = LogScreen;
|
|
|
|
u8g2.clearBuffer();
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
setSmallTextSize();
|
|
|
|
for (int i=0; i<MAX_NUMBER_LOG_LINES; ++i) {
|
|
|
|
u8g2.setCursor(0, i * getTextHeight());
|
|
|
|
u8g2.print(logLine[i]);
|
|
|
|
}
|
|
|
|
u8g2.sendBuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Display::addLogMessage(const char *message) {
|
|
|
|
if (numberLogLines >= MAX_NUMBER_LOG_LINES) {
|
|
|
|
for (int i=0; i<MAX_NUMBER_LOG_LINES-1; ++i) memcpy(logLine[i], logLine[i+1], MAX_LOG_MESSAGE_LEN);
|
|
|
|
--numberLogLines;
|
|
|
|
}
|
|
|
|
strncpy(logLine[numberLogLines++], message, MAX_LOG_MESSAGE_LEN);
|
|
|
|
if (currentScreen == LogScreen) showLog();
|
|
|
|
Serial.println(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Display::showDashboard(void) {
|
|
|
|
static unsigned long lastDisplayUpdate_ms = 0;
|
2018-11-14 10:12:36 +00:00
|
|
|
static unsigned long lastBlinkChange_ms = 0;
|
|
|
|
static bool blinkOnCycle = false; // toggles the on/off blinking phase
|
2018-11-14 07:43:50 +00:00
|
|
|
|
|
|
|
currentScreen = DashboardScreen;
|
|
|
|
// avoid flickering of the display:
|
|
|
|
if (millis() - lastDisplayUpdate_ms < TIME_BETWEEN_DISPLAY_UPDATES_ms) return;
|
|
|
|
lastDisplayUpdate_ms = millis();
|
2018-11-14 10:12:36 +00:00
|
|
|
if (lastDisplayUpdate_ms - lastBlinkChange_ms > BLINK_ON_OFF_TIME_ms) {
|
|
|
|
lastBlinkChange_ms = lastDisplayUpdate_ms;
|
|
|
|
blinkOnCycle = !blinkOnCycle;
|
|
|
|
}
|
2018-11-14 07:43:50 +00:00
|
|
|
u8g2.clearBuffer();
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
|
|
|
|
// ***** clock name *****
|
|
|
|
setNormalTextSize();
|
|
|
|
u8g2.setCursor(0, getTextHeight()-1);
|
|
|
|
u8g2.print(clockName);
|
|
|
|
|
|
|
|
// ****** speed *****
|
2018-11-14 10:12:36 +00:00
|
|
|
setSmallTextSize();
|
|
|
|
u8g2.setCursor(55, 2*getTextHeight());
|
2018-11-14 07:43:50 +00:00
|
|
|
u8g2.print(clockSpeed);
|
|
|
|
|
|
|
|
// ***** time *****
|
2018-11-14 10:12:36 +00:00
|
|
|
if (!clockHalted || blinkOnCycle) {
|
|
|
|
setLargeTextSize();
|
|
|
|
u8g2.setCursor(0, u8g2.getDisplayHeight()-1);
|
|
|
|
if (clockHour < 10) u8g2.print("0");
|
|
|
|
u8g2.print(clockHour);
|
|
|
|
u8g2.print(":");
|
|
|
|
if (clockMinute < 10) u8g2.print("0");
|
|
|
|
u8g2.print(clockMinute);
|
|
|
|
}
|
2018-11-14 07:43:50 +00:00
|
|
|
|
|
|
|
// ***** halt/go *****
|
|
|
|
if (clockHalted) {
|
|
|
|
setSmallTextSize();
|
2018-11-14 10:12:36 +00:00
|
|
|
u8g2.setDrawColor(blinkOnCycle ? 1 : 0);
|
|
|
|
u8g2.drawBox(55, u8g2.getDisplayHeight() - 2*getTextHeight()-4, 4*u8g2.getMaxCharWidth()+3, getTextHeight()+1);
|
|
|
|
u8g2.setDrawColor(blinkOnCycle ? 0 : 1);
|
|
|
|
u8g2.setCursor(57, u8g2.getDisplayHeight() - getTextHeight()-4);
|
2018-11-14 07:43:50 +00:00
|
|
|
u8g2.print("HALT");
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// **** weekday *****
|
|
|
|
setSmallTextSize();
|
|
|
|
u8g2.setCursor(60, u8g2.getDisplayHeight());
|
|
|
|
u8g2.print(clockWeekday);
|
|
|
|
|
|
|
|
// ***** # of clients *****
|
|
|
|
setSmallTextSize();
|
|
|
|
u8g2.setCursor(55, getTextHeight());
|
2018-11-14 10:27:06 +00:00
|
|
|
u8g2.print(numberKnownClients); u8g2.print(" Clks");
|
2018-11-14 07:43:50 +00:00
|
|
|
|
|
|
|
// ***** client list *****
|
|
|
|
u8g2.drawVLine(79, 0, u8g2.getDisplayHeight());
|
|
|
|
for (int i=0; i<5; ++i) {
|
2018-11-14 10:27:06 +00:00
|
|
|
if (clientName[i][0] != 0) {
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
u8g2.drawBox(81, i * getTextHeight(), 3*3+1, getTextHeight());
|
|
|
|
u8g2.setCursor(82, (i+1) * getTextHeight());
|
|
|
|
u8g2.setDrawColor(0);
|
|
|
|
if (i < 10) u8g2.print(0);
|
|
|
|
u8g2.print(i);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
u8g2.setCursor(82+3*3+1+1, (i+1) * getTextHeight());
|
|
|
|
u8g2.print(clientName[i]);
|
|
|
|
}
|
2018-11-14 07:43:50 +00:00
|
|
|
}
|
|
|
|
u8g2.sendBuffer();
|
|
|
|
}
|