134 lines
5.3 KiB
C++
134 lines
5.3 KiB
C++
#include "GxEPDDisplay.h"
|
|
|
|
using panel::Call;
|
|
|
|
static void paint(GxEPDDisplay& display, const char* text) {
|
|
display.setTextSize(1);
|
|
display.setCursor(2, 20);
|
|
display.print(text);
|
|
}
|
|
|
|
static void frame(GxEPDDisplay& display, const char* text) {
|
|
display.startFrame();
|
|
paint(display, text);
|
|
display.endFrame();
|
|
}
|
|
|
|
static void cleanBaseline(GxEPDDisplay& display, int interval = 2) {
|
|
assert(display.begin());
|
|
assert(display.width() == 250 && display.height() == 122);
|
|
display.setMaxPartialRefresh(interval);
|
|
display.forceFullRefresh();
|
|
frame(display, "Network");
|
|
assert(panel::updates(Call::Full) == 1 && panel::updates(Call::Partial) == 0);
|
|
assert(panel::images.back() == "Network");
|
|
assert(panel::updates(Call::PrepareFull) == 1 && panel::updates(Call::Finish) == 1);
|
|
assert(panel::updates(Call::PowerOff) == 0);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
assert(argc == 2);
|
|
const std::string scenario = argv[1];
|
|
GxEPDDisplay display;
|
|
if (scenario == "boot") {
|
|
display.turnOff();
|
|
assert(panel::calls.empty() && "an uninitialized display must not access hardware");
|
|
assert(display.begin());
|
|
display.startFrame();
|
|
display.setMaxPartialRefresh(30);
|
|
paint(display, "First image");
|
|
display.endFrame();
|
|
assert(panel::updates(Call::Full) == 1 && panel::updates(Call::Partial) == 0);
|
|
frame(display, "Clock 13:44");
|
|
assert(panel::updates(Call::Partial) == 1);
|
|
return 0;
|
|
}
|
|
cleanBaseline(display);
|
|
|
|
if (scenario == "manual") {
|
|
// Requesting a clean once rendering has started must clean this frame,
|
|
// including when it has exactly the same drawing commands as before.
|
|
display.startFrame();
|
|
paint(display, "Network");
|
|
display.forceFullRefresh();
|
|
display.endFrame();
|
|
assert(panel::updates(Call::Full) == 2 && panel::updates(Call::Partial) == 0);
|
|
const auto calls = panel::calls.size();
|
|
frame(display, "Network");
|
|
assert(panel::calls.size() == calls && "identical clean image needs no repeat SPI update");
|
|
display.forceFullRefresh();
|
|
frame(display, "Network");
|
|
assert(panel::updates(Call::Full) == 3);
|
|
} else if (scenario == "periodic") {
|
|
const auto calls = panel::calls.size();
|
|
frame(display, "Network");
|
|
assert(panel::calls.size() == calls);
|
|
frame(display, "Clock 13:44");
|
|
assert(panel::updates(Call::Partial) == 1 && panel::updates(Call::Full) == 1);
|
|
const auto after_first = panel::calls.size();
|
|
for (unsigned i = 0; i < 8; ++i) frame(display, "Clock 13:44");
|
|
assert(panel::calls.size() == after_first && "unchanged frames must not exhaust the clean interval");
|
|
frame(display, "Clock 13:45");
|
|
assert(panel::updates(Call::Partial) == 2 && panel::updates(Call::Full) == 1);
|
|
frame(display, "Clock 13:46");
|
|
assert(panel::updates(Call::Full) == 2 && panel::updates(Call::Partial) == 2);
|
|
frame(display, "Clock 13:47");
|
|
assert(panel::updates(Call::Partial) == 3 && "a clean resets the partial-update allowance");
|
|
assert(panel::images.back() == "Clock 13:47");
|
|
} else if (scenario == "interval") {
|
|
// A settings change must preserve a clean requested before drawing starts.
|
|
display.forceFullRefresh();
|
|
display.setMaxPartialRefresh(60);
|
|
frame(display, "Network");
|
|
assert(panel::updates(Call::Full) == 2 && panel::updates(Call::Partial) == 0);
|
|
// Settings may also be applied by the GUI after startFrame(). Neither
|
|
// increasing the allowance nor manual cleanup may cancel a requested clean.
|
|
for (int interval : {30, -1, 1}) {
|
|
const auto full = panel::updates(Call::Full);
|
|
display.forceFullRefresh();
|
|
display.startFrame();
|
|
display.setMaxPartialRefresh(interval);
|
|
paint(display, "Network");
|
|
display.endFrame();
|
|
assert(panel::updates(Call::Full) == full + 1);
|
|
}
|
|
display.setMaxPartialRefresh(-1);
|
|
const auto full = panel::updates(Call::Full);
|
|
for (unsigned i = 0; i < 70; ++i) {
|
|
const std::string value = "tick " + std::to_string(i);
|
|
frame(display, value.c_str());
|
|
}
|
|
assert(panel::updates(Call::Full) == full + 6 && "manual mode must also honor the ten-partial hardware limit");
|
|
assert(panel::updates(Call::Partial) == 64);
|
|
} else if (scenario == "wake") {
|
|
display.turnOff();
|
|
assert(!display.isOn() && panel::updates(Call::Finish) == 2);
|
|
const auto full = panel::updates(Call::Full);
|
|
const auto partial = panel::updates(Call::Partial);
|
|
display.turnOn();
|
|
assert(display.isOn());
|
|
frame(display, "Network");
|
|
assert(panel::updates(Call::Full) == full + 1);
|
|
assert(panel::updates(Call::Partial) == partial);
|
|
// An already-awake turnOn() should not force a clean or discard history.
|
|
display.turnOn();
|
|
frame(display, "Clock 13:45");
|
|
assert(panel::updates(Call::Full) == full + 1);
|
|
assert(panel::updates(Call::Partial) == partial + 1);
|
|
} else if (scenario == "rotation") {
|
|
display.startFrame();
|
|
display.setNativeRotation(1);
|
|
paint(display, "Flipped");
|
|
display.endFrame();
|
|
assert(display.width() == 250 && display.height() == 122);
|
|
assert(panel::updates(Call::Full) == 2 && panel::updates(Call::Partial) == 0);
|
|
display.setNativeRotation(1);
|
|
frame(display, "Flipped");
|
|
assert(panel::updates(Call::Full) == 2 && panel::updates(Call::Partial) == 0);
|
|
frame(display, "Flipped clock");
|
|
assert(panel::updates(Call::Partial) == 1);
|
|
} else {
|
|
assert(false && "unknown scenario");
|
|
}
|
|
}
|