splittet Display into combinable parts
This commit is contained in:
parent
3fad49cfb4
commit
85e635169d
29
data/http/index.css
Normal file
29
data/http/index.css
Normal file
@ -0,0 +1,29 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 8vw;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 33vmin;
|
||||
font-size: 9vw;
|
||||
}
|
||||
|
||||
button.cancel {
|
||||
width: 15vmin;
|
||||
height: 15vmin;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
svg {
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
height: calc(11 / 27 * 100%);
|
||||
}
|
||||
@ -5,41 +5,11 @@
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<title>Sporttafel</title>
|
||||
<link rel="icon" href="icon.svg">
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 8vw;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 33vmin;
|
||||
font-size: 9vw;
|
||||
}
|
||||
|
||||
button.cancel {
|
||||
width: 15vmin;
|
||||
height: 15vmin;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
svg {
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
height: calc(11 / 27 * 100%);
|
||||
}
|
||||
</style>
|
||||
<script src="index.js"></script>
|
||||
<link rel="stylesheet" href="index.css">
|
||||
</head>
|
||||
<body>
|
||||
<svg width="800" height="325" id="display" style="background-color: black">
|
||||
</svg>
|
||||
<svg width="800" height="325" id="display" style="background-color: black"></svg>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
@ -68,130 +38,24 @@
|
||||
</td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
|
||||
<script>
|
||||
|
||||
const DEV_HOST = "10.0.0.119";
|
||||
|
||||
const S = 100 / 27;
|
||||
|
||||
const display = document.getElementById("display");
|
||||
|
||||
const segments = [];
|
||||
|
||||
function url(protocol, path) {
|
||||
const hostPart = location.host.substring(0, location.host.indexOf(":"))
|
||||
const isLocal = hostPart === "" || hostPart === "localhost" || hostPart === "0";
|
||||
const host = isLocal ? DEV_HOST : hostPart;
|
||||
const port = isLocal ? "80" : location.port;
|
||||
return `${protocol}://${host}:${port}${path}`;
|
||||
}
|
||||
|
||||
function get(path) {
|
||||
const request = new XMLHttpRequest();
|
||||
request.open("GET", url("http", path), true);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function drawDigit(x, y) {
|
||||
drawPixel(x, y, 0, 3);
|
||||
drawPixel(x, y, 0, 2);
|
||||
drawPixel(x, y, 0, 1);
|
||||
|
||||
drawPixel(x, y, 1, 0);
|
||||
drawPixel(x, y, 2, 0);
|
||||
drawPixel(x, y, 3, 0);
|
||||
|
||||
drawPixel(x, y, 4, 1);
|
||||
drawPixel(x, y, 4, 2);
|
||||
drawPixel(x, y, 4, 3);
|
||||
|
||||
drawPixel(x, y, 4, 5);
|
||||
drawPixel(x, y, 4, 6);
|
||||
drawPixel(x, y, 4, 7);
|
||||
|
||||
drawPixel(x, y, 3, 8);
|
||||
drawPixel(x, y, 2, 8);
|
||||
drawPixel(x, y, 1, 8);
|
||||
|
||||
drawPixel(x, y, 0, 7);
|
||||
drawPixel(x, y, 0, 6);
|
||||
drawPixel(x, y, 0, 5);
|
||||
|
||||
drawPixel(x, y, 1, 4);
|
||||
drawPixel(x, y, 2, 4);
|
||||
drawPixel(x, y, 3, 4);
|
||||
}
|
||||
|
||||
function drawPixel(offsetRasterX, offsetRasterY, innerRasterX, innerRasterY) {
|
||||
const segment = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
const x = (offsetRasterX + innerRasterX) * S;
|
||||
const y = (offsetRasterY + innerRasterY) * S;
|
||||
segment.setAttribute("x", x + "vw");
|
||||
segment.setAttribute("y", y + "vw");
|
||||
segment.setAttribute("width", S + "vw");
|
||||
segment.setAttribute("height", S + "vw");
|
||||
segment.setAttribute("stroke", "white");
|
||||
segment.setAttribute("fill", "none");
|
||||
segment.setAttribute("id", "segment" + segments.length);
|
||||
display.appendChild(segment);
|
||||
segments.push(segment);
|
||||
}
|
||||
|
||||
function drawDisplay(rasterX, rasterY) {
|
||||
drawDigit(rasterX, rasterY);
|
||||
rasterX += 6;
|
||||
drawDigit(rasterX, rasterY);
|
||||
rasterX += 6;
|
||||
drawPixel(rasterX, rasterY, 0, 0);
|
||||
drawPixel(rasterX, rasterY + 2, 0, 0);
|
||||
drawPixel(rasterX, rasterY + 6, 0, 0);
|
||||
drawPixel(rasterX, rasterY + 8, 0, 0);
|
||||
rasterX += 2;
|
||||
drawDigit(rasterX, rasterY);
|
||||
rasterX += 6;
|
||||
drawDigit(rasterX, rasterY);
|
||||
}
|
||||
|
||||
function connect() {
|
||||
console.log("connecting websocket...");
|
||||
const socket = new WebSocket(url("ws", "/ws"));
|
||||
socket.timeout = 1;
|
||||
socket.addEventListener('open', _ => {
|
||||
console.log('websocket connected');
|
||||
segments.forEach(segment => {
|
||||
segment.setAttribute("fill", "none");
|
||||
segment.setAttribute("stroke", "none");
|
||||
});
|
||||
});
|
||||
socket.addEventListener('message', event => {
|
||||
const len = event.data.length;
|
||||
let index = 0;
|
||||
let start = 0;
|
||||
while (start < len) {
|
||||
const end = start + 3;
|
||||
const color = event.data.substring(start, end);
|
||||
const segment = segments[index];
|
||||
segment.setAttribute("fill", "#" + color)
|
||||
index++;
|
||||
start = end;
|
||||
}
|
||||
});
|
||||
socket.addEventListener('close', _ => {
|
||||
console.log('websocket disconnected');
|
||||
segments.forEach(segment => {
|
||||
segment.setAttribute("fill", "none");
|
||||
segment.setAttribute("stroke", "white");
|
||||
});
|
||||
setTimeout(connect, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
drawDisplay(1, 1);
|
||||
setTimeout(connect, 1000);
|
||||
|
||||
</script>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<button onclick="get('/action/left/up')">↑</button>
|
||||
</td>
|
||||
<td> </td>
|
||||
<td>
|
||||
<button onclick="get('/action/right/up')">↑</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<button onclick="get('/action/left/down')">↓</button>
|
||||
</td>
|
||||
<td> </td>
|
||||
<td>
|
||||
<button onclick="get('/action/right/down')">↓</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
118
data/http/index.js
Normal file
118
data/http/index.js
Normal file
@ -0,0 +1,118 @@
|
||||
const DEV_HOST = "10.0.0.119";
|
||||
|
||||
const S = 100 / 27;
|
||||
|
||||
const display = document.getElementById("display");
|
||||
|
||||
const segments = [];
|
||||
|
||||
function url(protocol, path) {
|
||||
const hostPart = location.host.substring(0, location.host.indexOf(":"))
|
||||
const isLocal = hostPart === "" || hostPart === "localhost" || hostPart === "0";
|
||||
const host = isLocal ? DEV_HOST : hostPart;
|
||||
const port = isLocal ? "80" : location.port;
|
||||
return `${protocol}://${host}:${port}${path}`;
|
||||
}
|
||||
|
||||
function get(path) {
|
||||
const request = new XMLHttpRequest();
|
||||
request.open("GET", url("http", path), true);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function drawDigit(x, y) {
|
||||
drawPixel(x, y, 0, 3);
|
||||
drawPixel(x, y, 0, 2);
|
||||
drawPixel(x, y, 0, 1);
|
||||
|
||||
drawPixel(x, y, 1, 0);
|
||||
drawPixel(x, y, 2, 0);
|
||||
drawPixel(x, y, 3, 0);
|
||||
|
||||
drawPixel(x, y, 4, 1);
|
||||
drawPixel(x, y, 4, 2);
|
||||
drawPixel(x, y, 4, 3);
|
||||
|
||||
drawPixel(x, y, 4, 5);
|
||||
drawPixel(x, y, 4, 6);
|
||||
drawPixel(x, y, 4, 7);
|
||||
|
||||
drawPixel(x, y, 3, 8);
|
||||
drawPixel(x, y, 2, 8);
|
||||
drawPixel(x, y, 1, 8);
|
||||
|
||||
drawPixel(x, y, 0, 7);
|
||||
drawPixel(x, y, 0, 6);
|
||||
drawPixel(x, y, 0, 5);
|
||||
|
||||
drawPixel(x, y, 1, 4);
|
||||
drawPixel(x, y, 2, 4);
|
||||
drawPixel(x, y, 3, 4);
|
||||
}
|
||||
|
||||
function drawPixel(offsetRasterX, offsetRasterY, innerRasterX, innerRasterY) {
|
||||
const segment = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
const x = (offsetRasterX + innerRasterX) * S;
|
||||
const y = (offsetRasterY + innerRasterY) * S;
|
||||
segment.setAttribute("x", x + "vw");
|
||||
segment.setAttribute("y", y + "vw");
|
||||
segment.setAttribute("width", S + "vw");
|
||||
segment.setAttribute("height", S + "vw");
|
||||
segment.setAttribute("stroke", "white");
|
||||
segment.setAttribute("fill", "none");
|
||||
segment.setAttribute("id", "segment" + segments.length);
|
||||
display.appendChild(segment);
|
||||
segments.push(segment);
|
||||
}
|
||||
|
||||
function drawDisplay(rasterX, rasterY) {
|
||||
drawDigit(rasterX, rasterY);
|
||||
rasterX += 6;
|
||||
drawDigit(rasterX, rasterY);
|
||||
rasterX += 6;
|
||||
drawPixel(rasterX, rasterY, 0, 0);
|
||||
drawPixel(rasterX, rasterY + 2, 0, 0);
|
||||
drawPixel(rasterX, rasterY + 6, 0, 0);
|
||||
drawPixel(rasterX, rasterY + 8, 0, 0);
|
||||
rasterX += 2;
|
||||
drawDigit(rasterX, rasterY);
|
||||
rasterX += 6;
|
||||
drawDigit(rasterX, rasterY);
|
||||
}
|
||||
|
||||
function connect() {
|
||||
console.log("connecting websocket...");
|
||||
const socket = new WebSocket(url("ws", "/ws"));
|
||||
socket.timeout = 1;
|
||||
socket.addEventListener('open', _ => {
|
||||
console.log('websocket connected');
|
||||
segments.forEach(segment => {
|
||||
segment.setAttribute("fill", "none");
|
||||
segment.setAttribute("stroke", "none");
|
||||
});
|
||||
});
|
||||
socket.addEventListener('message', event => {
|
||||
const len = event.data.length;
|
||||
let index = 0;
|
||||
let start = 0;
|
||||
while (start < len) {
|
||||
const end = start + 3;
|
||||
const color = event.data.substring(start, end);
|
||||
const segment = segments[index];
|
||||
segment.setAttribute("fill", "#" + color)
|
||||
index++;
|
||||
start = end;
|
||||
}
|
||||
});
|
||||
socket.addEventListener('close', _ => {
|
||||
console.log('websocket disconnected');
|
||||
segments.forEach(segment => {
|
||||
segment.setAttribute("fill", "none");
|
||||
segment.setAttribute("stroke", "white");
|
||||
});
|
||||
setTimeout(connect, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
drawDisplay(1, 1);
|
||||
setTimeout(connect, 1000);
|
||||
@ -4,7 +4,7 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <LittleFS.h>
|
||||
#include <core/log.h>
|
||||
#include <display/Display.h>
|
||||
#include <display/MyDisplay.h>
|
||||
|
||||
#define CONFIG_WRITE_DELAY_MILLIS (30 * 1000)
|
||||
|
||||
@ -87,6 +87,22 @@ public:
|
||||
//
|
||||
}
|
||||
|
||||
virtual void leftUp() {
|
||||
//
|
||||
}
|
||||
|
||||
virtual void leftDown() {
|
||||
//
|
||||
}
|
||||
|
||||
virtual void rightUp() {
|
||||
//
|
||||
}
|
||||
|
||||
virtual void rightDown() {
|
||||
//
|
||||
}
|
||||
|
||||
virtual bool setConfig(const String& key, const String& valueStr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ protected:
|
||||
|
||||
void draw() override {
|
||||
display.clear();
|
||||
display.strokeRect(step, step, DISPLAY_VIRTUAL_WIDTH - 1 - 2 * step, DISPLAY_VIRTUAL_HEIGHT - 1 - 2 * step);
|
||||
display.main.strokeRect(step, step, DISPLAY_VIRTUAL_WIDTH - 1 - 2 * step, DISPLAY_VIRTUAL_HEIGHT - 1 - 2 * step);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@ -52,10 +52,14 @@ class AppMatch final : public App {
|
||||
|
||||
State state = INITIAL;
|
||||
|
||||
int pointsLeft = 0;
|
||||
|
||||
int pointsRight = 0;
|
||||
|
||||
public:
|
||||
|
||||
explicit AppMatch()
|
||||
: App(APP_MATCH_NAME) {
|
||||
: App(APP_MATCH_NAME) {
|
||||
//
|
||||
}
|
||||
|
||||
@ -118,12 +122,35 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void leftUp() override {
|
||||
pointsLeft++;
|
||||
markDirty(true);
|
||||
}
|
||||
|
||||
void leftDown() override {
|
||||
pointsLeft = max(0, pointsLeft - 1);
|
||||
markDirty(true);
|
||||
}
|
||||
|
||||
void rightUp() override {
|
||||
pointsRight++;
|
||||
markDirty(true);
|
||||
}
|
||||
|
||||
void rightDown() override {
|
||||
pointsRight = max(0, pointsRight - 1);
|
||||
markDirty(true);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void _start() override {
|
||||
configMillis = configGet<unsigned long>(CONFIG_SECONDS_KEY, CONFIG_SECONDS_DEFAULT) * MS_PER_SEC;
|
||||
configCentis = configGet<bool>(CONFIG_CENTIS_KEY, CONFIG_CENTIS_DEFAULT);
|
||||
|
||||
pointsLeft = 0;
|
||||
pointsRight = 0;
|
||||
|
||||
info("config:");
|
||||
info(" seconds = %ld", configMillis / MS_PER_SEC);
|
||||
info(" centis = %s", configCentis ? "true" : "false");
|
||||
@ -177,17 +204,21 @@ protected:
|
||||
}
|
||||
if (blinkIntervalMillis == 0 || blinkState) {
|
||||
if (totalMinutes > 0) {
|
||||
display.printf("%2d:%02d", totalMinutes, partSeconds);
|
||||
display.main.printf("%2d:%02d", totalMinutes, partSeconds);
|
||||
} else if (totalMillis > 0) {
|
||||
if (configCentis) {
|
||||
display.printf("%2d.%02d", partSeconds, partCentis);
|
||||
display.main.printf("%2d.%02d", partSeconds, partCentis);
|
||||
} else {
|
||||
display.printf(" %2d", partSeconds);
|
||||
display.main.printf(" %2d", partSeconds);
|
||||
}
|
||||
} else {
|
||||
display.printf("00:00");
|
||||
display.main.printf("00:00");
|
||||
}
|
||||
}
|
||||
// ReSharper disable once CppExpressionWithoutSideEffects
|
||||
display.left.printf("%2d", pointsLeft);
|
||||
// ReSharper disable once CppExpressionWithoutSideEffects
|
||||
display.right.printf("%2d", pointsRight);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
12
src/core/BASICS.h
Normal file
12
src/core/BASICS.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef BASICS_H
|
||||
#define BASICS_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "log.h"
|
||||
|
||||
#define X true
|
||||
#define _ false
|
||||
|
||||
#define countof(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
#endif
|
||||
@ -53,6 +53,34 @@ void httpActionConfirm(AsyncWebServerRequest *request) {
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
void httpActionLeftUp(AsyncWebServerRequest *request) {
|
||||
if (app != nullptr) {
|
||||
app->leftUp();
|
||||
}
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
void httpActionLeftDown(AsyncWebServerRequest *request) {
|
||||
if (app != nullptr) {
|
||||
app->leftDown();
|
||||
}
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
void httpActionRightUp(AsyncWebServerRequest *request) {
|
||||
if (app != nullptr) {
|
||||
app->rightUp();
|
||||
}
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
void httpActionRightDown(AsyncWebServerRequest *request) {
|
||||
if (app != nullptr) {
|
||||
app->rightDown();
|
||||
}
|
||||
request->send(200);
|
||||
}
|
||||
|
||||
void httpAppConfig(AsyncWebServerRequest *request) {
|
||||
if (!request->hasArg("key")) {
|
||||
error("missing parameter 'key'");
|
||||
@ -97,6 +125,10 @@ void httpSetup() {
|
||||
server.on("/action/right", HTTP_GET, httpActionRight);
|
||||
server.on("/action/cancel", HTTP_GET, httpActionCancel);
|
||||
server.on("/action/confirm", HTTP_GET, httpActionConfirm);
|
||||
server.on("/action/left/up", HTTP_GET, httpActionLeftUp);
|
||||
server.on("/action/left/down", HTTP_GET, httpActionLeftDown);
|
||||
server.on("/action/right/up", HTTP_GET, httpActionRightUp);
|
||||
server.on("/action/right/down", HTTP_GET, httpActionRightDown);
|
||||
server.on("/app/config", HTTP_GET, httpAppConfig);
|
||||
server.serveStatic("/", LittleFS, "/http/", "max-age=86400").setDefaultFile("index.html");
|
||||
server.onNotFound(httpNotFound);
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#include "Display.h"
|
||||
|
||||
Display display;
|
||||
@ -5,53 +5,69 @@
|
||||
|
||||
#include <AsyncWebSocket.h>
|
||||
#include <cstdint>
|
||||
#include <core/log.h>
|
||||
|
||||
#include "Color.h"
|
||||
#include "font.h"
|
||||
#include "core/http.h"
|
||||
|
||||
#define PIXELS_PER_SEGMENT 3
|
||||
#define SEGMENTS_PER_DIGIT 7
|
||||
#define PIXELS_PER_DOT 1
|
||||
#define DOT_COUNT 4
|
||||
#define DIGIT_COUNT 4
|
||||
|
||||
#define PIXELS_PER_DIGIT (PIXELS_PER_SEGMENT * SEGMENTS_PER_DIGIT)
|
||||
#define TOTAL_DOT_PIXEL_COUNT (PIXELS_PER_DOT * DOT_COUNT)
|
||||
#define TOTAL_SEGMENT_PIXEL_COUNT (DIGIT_COUNT * PIXELS_PER_DIGIT)
|
||||
#define TOTAL_PIXEL_COUNT (TOTAL_SEGMENT_PIXEL_COUNT + TOTAL_DOT_PIXEL_COUNT)
|
||||
#define TOTAL_PIXEL_BYTE_COUNT (TOTAL_PIXEL_COUNT * sizeof(Color))
|
||||
#define HEX_BUFFER_SIZE (TOTAL_PIXEL_BYTE_COUNT + 1)
|
||||
|
||||
#define DISPLAY_VIRTUAL_WIDTH 25
|
||||
#define DISPLAY_VIRTUAL_HEIGHT 9
|
||||
|
||||
#define HEX_BUFFER_MIN_WAIT_MS 500
|
||||
|
||||
class Display {
|
||||
|
||||
// Adafruit_NeoPixel leds;
|
||||
|
||||
Color pixels[TOTAL_PIXEL_COUNT] = {};
|
||||
size_t totalPixelCount;
|
||||
|
||||
size_t pixelByteCount;
|
||||
|
||||
Color *pixels;
|
||||
|
||||
char *hexBuffer;
|
||||
|
||||
Color color = WHITE;
|
||||
|
||||
char hexBuffer[HEX_BUFFER_SIZE] = "";
|
||||
protected:
|
||||
|
||||
struct Mapping {
|
||||
uint8_t x;
|
||||
uint8_t y;
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Display() /* : leds(PIXEL_COUNT, GPIO_NUM_13) */ {
|
||||
explicit Display(const int totalPixelCount) :/* leds(totalPixelCount, GPIO_NUM_13) ,*/ totalPixelCount(totalPixelCount), pixelByteCount(totalPixelCount * sizeof(Color)) {
|
||||
// leds.begin();
|
||||
|
||||
pixels = static_cast<Color *>(malloc(pixelByteCount));
|
||||
if (pixels == nullptr) {
|
||||
error("Failed to allocate memory for Display.pixels");
|
||||
}
|
||||
|
||||
hexBuffer = static_cast<char *>(malloc(pixelByteCount + 1));
|
||||
if (hexBuffer == nullptr) {
|
||||
error("Failed to allocate memory for Display.hexBuffer");
|
||||
} else {
|
||||
*hexBuffer = 0;
|
||||
}
|
||||
|
||||
setBrightness(6);
|
||||
clear();
|
||||
flush();
|
||||
}
|
||||
|
||||
~Display() {
|
||||
if (pixels != nullptr) {
|
||||
free(pixels);
|
||||
pixels = nullptr;
|
||||
}
|
||||
if (hexBuffer != nullptr) {
|
||||
free(hexBuffer);
|
||||
hexBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void setPixel(const int index) const {
|
||||
if (pixels == nullptr) {
|
||||
return;
|
||||
}
|
||||
pixels[index] = color;
|
||||
}
|
||||
|
||||
void setColor(const Color newColor) {
|
||||
this->color = newColor;
|
||||
}
|
||||
@ -60,12 +76,15 @@ public:
|
||||
// leds.setBrightness(brightness);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
memset(pixels, 0, TOTAL_PIXEL_BYTE_COUNT);
|
||||
void clear() const {
|
||||
if (pixels == nullptr) {
|
||||
return;
|
||||
}
|
||||
memset(pixels, 0, pixelByteCount);
|
||||
}
|
||||
|
||||
void flush(const bool forceNextHexBuffer = false) {
|
||||
// memcpy(leds.getPixels(), buffer, PIXEL_BYTE_COUNT);
|
||||
void flush(const bool forceNextHexBuffer = false) const {
|
||||
// memcpy(leds.getPixels(), buffer, pixelByteCount);
|
||||
// leds.show();
|
||||
|
||||
const auto now = millis() - HEX_BUFFER_MIN_WAIT_MS;
|
||||
@ -73,178 +92,43 @@ public:
|
||||
if (now - last >= HEX_BUFFER_MIN_WAIT_MS || forceNextHexBuffer) {
|
||||
last = now;
|
||||
fillHexBuffer();
|
||||
websocketSendAll(hexBuffer);
|
||||
sendHexBufferAll();
|
||||
}
|
||||
}
|
||||
|
||||
void printf(const char *format, ...) {
|
||||
char buffer[64];
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer, sizeof buffer, format, args);
|
||||
va_end(args);
|
||||
|
||||
print(buffer);
|
||||
void sendHexBufferAll() const {
|
||||
if (hexBuffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (*hexBuffer == 0) {
|
||||
return;
|
||||
}
|
||||
websocketSendAll(hexBuffer);
|
||||
}
|
||||
|
||||
void print(const char *str) {
|
||||
auto digit = 0;
|
||||
for (auto c = str; *c != 0 && digit < 4; c++) {
|
||||
switch (*c) {
|
||||
case '\'':
|
||||
case '"':
|
||||
case '`':
|
||||
case '.':
|
||||
printDots(false, false, false, true);
|
||||
digit = 2;
|
||||
break;
|
||||
case ',':
|
||||
printDots(false, false, true, true);
|
||||
digit = 2;
|
||||
break;
|
||||
case ':':
|
||||
printDots(false, true, true, false);
|
||||
digit = 2;
|
||||
break;
|
||||
case ';':
|
||||
printDots(false, true, true, true);
|
||||
digit = 2;
|
||||
break;
|
||||
case '|':
|
||||
printDots(true, true, true, true);
|
||||
digit = 2;
|
||||
break;
|
||||
default:
|
||||
printCharacter(digit++, *c);
|
||||
break;
|
||||
}
|
||||
void sendHexBuffer(AsyncWebSocketClient *client) const {
|
||||
if (hexBuffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void printDots(const bool dot0, const bool dot1, const bool dot2, const bool dot3) {
|
||||
auto pixel = PIXELS_PER_DIGIT * 2;
|
||||
if (dot0) {
|
||||
pixels[pixel] = color;
|
||||
if (*hexBuffer == 0) {
|
||||
return;
|
||||
}
|
||||
pixel++;
|
||||
if (dot1) {
|
||||
pixels[pixel] = color;
|
||||
}
|
||||
pixel++;
|
||||
if (dot2) {
|
||||
pixels[pixel] = color;
|
||||
}
|
||||
pixel++;
|
||||
if (dot3) {
|
||||
pixels[pixel] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void printCharacter(int digit, const char character) {
|
||||
auto pixel = digit * PIXELS_PER_DIGIT + (digit >= 2 ? TOTAL_DOT_PIXEL_COUNT : 0);
|
||||
const auto symbol = getSymbol(character);
|
||||
for (auto s = *symbol; s < *symbol + SYMBOL_SIZE; s++) {
|
||||
if (*s) {
|
||||
pixels[pixel++] = color;
|
||||
pixels[pixel++] = color;
|
||||
pixels[pixel++] = color;
|
||||
} else {
|
||||
pixel += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendHexBuffer(AsyncWebSocketClient *client) {
|
||||
client->text(hexBuffer);
|
||||
}
|
||||
|
||||
void fillRect(const uint8_t x, uint8_t y, uint8_t w, uint8_t h) {
|
||||
for (int dx = 0; dx < w; ++dx) {
|
||||
for (int dy = 0; dy < h; ++dy) {
|
||||
drawVirtualPixel(x + dx, y + dy);
|
||||
}
|
||||
private
|
||||
:
|
||||
|
||||
void fillHexBuffer() const {
|
||||
if (pixels == nullptr || hexBuffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void strokeRect(const uint8_t x, uint8_t y, uint8_t w, uint8_t h) {
|
||||
for (int dx = 0; dx < w; ++dx) {
|
||||
drawVirtualPixel(x + dx, y);
|
||||
drawVirtualPixel(x + dx, y + h);
|
||||
}
|
||||
for (int dy = 0; dy < h; ++dy) {
|
||||
drawVirtualPixel(x, y + dy);
|
||||
drawVirtualPixel(x + w, y + dy);
|
||||
}
|
||||
}
|
||||
|
||||
void drawVirtualPixel(const uint8_t x, const uint8_t y) {
|
||||
const auto index = findIndexForVirtualCoordinates(x, y);
|
||||
if (index >= 0) {
|
||||
pixels[index] = color;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Mapping digitMapping[32] = {
|
||||
// @formatter:off
|
||||
{0, 3}, {0, 2}, {0, 1}, // top left
|
||||
{1, 0}, {2, 0}, {3, 0}, // top
|
||||
{4, 1}, {4, 2}, {4, 3}, // top right
|
||||
{4, 5}, {4, 6}, {4, 7}, // bottom right
|
||||
{3, 8}, {2, 8}, {1, 8}, // bottom
|
||||
{0, 7}, {0, 6}, {0, 5}, // bottom left
|
||||
{1, 4}, {2, 4}, {3, 4}, // middle
|
||||
// @formatter:on
|
||||
};
|
||||
|
||||
uint8_t dotMapping[4] = {0, 2, 6, 8};
|
||||
|
||||
uint8_t findIndexForVirtualCoordinates(const uint8_t x, const uint8_t y) {
|
||||
if (x < 0 || x > 24 || y < 0 || y > 8) {
|
||||
return -1;
|
||||
} else if (x >= 20) {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x - 20, y) + 3 * PIXELS_PER_DIGIT + TOTAL_DOT_PIXEL_COUNT;
|
||||
} else if (x >= 14) {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x - 14, y) + 2 * PIXELS_PER_DIGIT + TOTAL_DOT_PIXEL_COUNT;
|
||||
} else if (x == 12) {
|
||||
return _findIndexForVirtualCoordinates_dotRelative(y) + 2 * PIXELS_PER_DIGIT;
|
||||
} else if (x >= 6) {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x - 6, y) + 1 * PIXELS_PER_DIGIT;
|
||||
} else {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x, y) + 0 * PIXELS_PER_DIGIT;;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t _findIndexForVirtualCoordinates_digitRelative(const uint8_t x, const uint8_t y) {
|
||||
for (auto index = 0; index < PIXELS_PER_DIGIT; index++) {
|
||||
auto item = digitMapping[index];
|
||||
if (item.x == x && item.y == y) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t _findIndexForVirtualCoordinates_dotRelative(const uint8_t y) {
|
||||
for (auto index = 0; index < DOT_COUNT; index++) {
|
||||
auto dotY = dotMapping[index];
|
||||
if (dotY == y) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void fillHexBuffer() {
|
||||
auto b = hexBuffer;
|
||||
for (const auto& pixel: pixels) {
|
||||
b += snprintf(b, sizeof hexBuffer - (b - hexBuffer), "%X%X%X", pixel.r / 16, pixel.g / 16, pixel.b / 16);
|
||||
for (auto pixel = pixels; pixel < pixels + totalPixelCount; ++pixel) {
|
||||
b += snprintf(b, sizeof hexBuffer - (b - hexBuffer), "%X%X%X", pixel->r / 16, pixel->g / 16, pixel->b / 16);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern Display display;
|
||||
|
||||
#endif
|
||||
|
||||
200
src/display/DisplayDigits4.h
Normal file
200
src/display/DisplayDigits4.h
Normal file
@ -0,0 +1,200 @@
|
||||
#ifndef DISPLAY_DIGITS4_H
|
||||
#define DISPLAY_DIGITS4_H
|
||||
|
||||
#include "DisplayPart.h"
|
||||
#include "font.h"
|
||||
|
||||
#define PIXELS_PER_SEGMENT 3
|
||||
#define SEGMENTS_PER_DIGIT 7
|
||||
#define PIXELS_PER_DOT 1
|
||||
#define DOT_COUNT 4
|
||||
#define DIGIT_COUNT 4
|
||||
|
||||
#define PIXELS_PER_DIGIT (PIXELS_PER_SEGMENT * SEGMENTS_PER_DIGIT)
|
||||
#define TOTAL_DOT_PIXEL_COUNT (PIXELS_PER_DOT * DOT_COUNT)
|
||||
#define TOTAL_SEGMENT_PIXEL_COUNT (DIGIT_COUNT * PIXELS_PER_DIGIT)
|
||||
#define TOTAL_POINTS_PIXEL_COUNT (4 * 3 * 5)
|
||||
#define TOTAL_PIXEL_COUNT (TOTAL_SEGMENT_PIXEL_COUNT + TOTAL_DOT_PIXEL_COUNT + TOTAL_POINTS_PIXEL_COUNT)
|
||||
|
||||
#define DISPLAY_VIRTUAL_WIDTH 25
|
||||
#define DISPLAY_VIRTUAL_HEIGHT 9
|
||||
|
||||
class DisplayDigits4 final : public DisplayPart {
|
||||
|
||||
struct Mapping {
|
||||
|
||||
uint8_t x;
|
||||
|
||||
uint8_t y;
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
explicit DisplayDigits4(Display *display, const int indexOffset)
|
||||
: DisplayPart(display, indexOffset,TOTAL_PIXEL_COUNT) {
|
||||
//
|
||||
}
|
||||
|
||||
void printf(const char *format, ...) const {
|
||||
char buffer[64];
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(buffer, sizeof buffer, format, args);
|
||||
va_end(args);
|
||||
|
||||
print(buffer);
|
||||
}
|
||||
|
||||
void print(const char *str) const {
|
||||
auto digit = 0;
|
||||
for (auto c = str; *c != 0 && digit < 4; c++) {
|
||||
switch (*c) {
|
||||
case '\'':
|
||||
case '"':
|
||||
case '`':
|
||||
case '.':
|
||||
printDots(false, false, false, true);
|
||||
digit = 2;
|
||||
break;
|
||||
case ',':
|
||||
printDots(false, false, true, true);
|
||||
digit = 2;
|
||||
break;
|
||||
case ':':
|
||||
printDots(false, true, true, false);
|
||||
digit = 2;
|
||||
break;
|
||||
case ';':
|
||||
printDots(false, true, true, true);
|
||||
digit = 2;
|
||||
break;
|
||||
case '|':
|
||||
printDots(true, true, true, true);
|
||||
digit = 2;
|
||||
break;
|
||||
default:
|
||||
printCharacter(digit++, *c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printDots(const bool dot0, const bool dot1, const bool dot2, const bool dot3) const {
|
||||
auto pixel = PIXELS_PER_DIGIT * 2;
|
||||
if (dot0) {
|
||||
setIndexPixel(pixel);
|
||||
}
|
||||
pixel++;
|
||||
if (dot1) {
|
||||
setIndexPixel(pixel);
|
||||
}
|
||||
pixel++;
|
||||
if (dot2) {
|
||||
setIndexPixel(pixel);
|
||||
}
|
||||
pixel++;
|
||||
if (dot3) {
|
||||
setIndexPixel(pixel);
|
||||
}
|
||||
}
|
||||
|
||||
void printCharacter(const int digit, const char character) const {
|
||||
auto pixel = digit * PIXELS_PER_DIGIT + (digit >= 2 ? TOTAL_DOT_PIXEL_COUNT : 0);
|
||||
const auto symbol = getSegment7Character(character);
|
||||
for (auto s = *symbol; s < *symbol + sizeof(Segment7Character); s++) {
|
||||
if (*s) {
|
||||
setIndexPixel(pixel++);
|
||||
setIndexPixel(pixel++);
|
||||
setIndexPixel(pixel++);
|
||||
} else {
|
||||
pixel += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fillRect(const uint8_t x, const uint8_t y, const uint8_t w, const uint8_t h) const {
|
||||
for (auto dx = 0; dx < w; ++dx) {
|
||||
for (auto dy = 0; dy < h; ++dy) {
|
||||
setRasterPixel(x + dx, y + dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void strokeRect(const uint8_t x, const uint8_t y, const uint8_t w, const uint8_t h) const {
|
||||
for (auto dx = 0; dx < w; ++dx) {
|
||||
setRasterPixel(x + dx, y);
|
||||
setRasterPixel(x + dx, y + h);
|
||||
}
|
||||
for (auto dy = 0; dy < h; ++dy) {
|
||||
setRasterPixel(x, y + dy);
|
||||
setRasterPixel(x + w, y + dy);
|
||||
}
|
||||
}
|
||||
|
||||
void setRasterPixel(const uint8_t x, const uint8_t y) const override {
|
||||
const auto index = findIndexForVirtualCoordinates(x, y);
|
||||
if (index >= 0) {
|
||||
setIndexPixel(index);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Mapping digitMapping[32] = {
|
||||
// @formatter:off
|
||||
{0, 3}, {0, 2}, {0, 1}, // top left
|
||||
{1, 0}, {2, 0}, {3, 0}, // top
|
||||
{4, 1}, {4, 2}, {4, 3}, // top right
|
||||
{4, 5}, {4, 6}, {4, 7}, // bottom right
|
||||
{3, 8}, {2, 8}, {1, 8}, // bottom
|
||||
{0, 7}, {0, 6}, {0, 5}, // bottom left
|
||||
{1, 4}, {2, 4}, {3, 4}, // middle
|
||||
// @formatter:on
|
||||
};
|
||||
|
||||
uint8_t dotMapping[4] = {0, 2, 6, 8};
|
||||
|
||||
int findIndexForVirtualCoordinates(const uint8_t x, const uint8_t y) const {
|
||||
if (x < 0 || x > 24 || y < 0 || y > 8) {
|
||||
return -1;
|
||||
}
|
||||
if (x >= 20) {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x - 20, y) + 3 * PIXELS_PER_DIGIT + TOTAL_DOT_PIXEL_COUNT;
|
||||
}
|
||||
if (x >= 14) {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x - 14, y) + 2 * PIXELS_PER_DIGIT + TOTAL_DOT_PIXEL_COUNT;
|
||||
}
|
||||
if (x == 12) {
|
||||
return _findIndexForVirtualCoordinates_dotRelative(y) + 2 * PIXELS_PER_DIGIT;
|
||||
}
|
||||
if (x >= 6) {
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x - 6, y) + 1 * PIXELS_PER_DIGIT;
|
||||
}
|
||||
return _findIndexForVirtualCoordinates_digitRelative(x, y) + 0 * PIXELS_PER_DIGIT;
|
||||
}
|
||||
|
||||
int _findIndexForVirtualCoordinates_digitRelative(const uint8_t x, const uint8_t y) const {
|
||||
for (auto index = 0; index < PIXELS_PER_DIGIT; index++) {
|
||||
const auto item = digitMapping[index];
|
||||
if (item.x == x && item.y == y) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _findIndexForVirtualCoordinates_dotRelative(const uint8_t y) const {
|
||||
for (auto index = 0; index < DOT_COUNT; index++) {
|
||||
const auto dotY = dotMapping[index];
|
||||
if (dotY == y) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
66
src/display/DisplayMatrix.h
Normal file
66
src/display/DisplayMatrix.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef DISPLAY_MATRIX_H
|
||||
#define DISPLAY_MATRIX_H
|
||||
|
||||
#include "DisplayPart.h"
|
||||
#include "DisplayRasterFont.h"
|
||||
|
||||
class DisplayMatrix final : public DisplayPart {
|
||||
|
||||
public:
|
||||
|
||||
const int rows;
|
||||
|
||||
DisplayMatrix(Display *display, const int indexOffset, const int cols, const int rows) : DisplayPart(display, indexOffset, cols * rows), rows(rows) {
|
||||
//
|
||||
}
|
||||
|
||||
int printf(const char *format, ...) const {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
const auto x = printf(0, 0, format, args);
|
||||
va_end(args);
|
||||
return x;
|
||||
}
|
||||
|
||||
int printf(int x, const int y, const char *format, ...) const {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
x = printf(x, y, format, args);
|
||||
va_end(args);
|
||||
return x;
|
||||
}
|
||||
|
||||
int printf(const int x, const int y, const char *format, const va_list args) const {
|
||||
char buffer[128];
|
||||
vsnprintf(buffer, sizeof buffer, format, args);
|
||||
return print(x, y, buffer);
|
||||
}
|
||||
|
||||
int print(int x, const int y, const char *text) const {
|
||||
for (auto c = text; *c != '\0'; ++c) {
|
||||
x = print(x, y, *c) + 1;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
int print(const int x, const int y, const char c) const {
|
||||
auto maxWidth = 0;
|
||||
const auto character = getRasterCharacter(c);
|
||||
for (auto cy = 0; cy < sizeof(RasterCharacter); cy++) {
|
||||
for (auto cx = 0; cx < sizeof(RasterCharacter[0]); cx++) {
|
||||
if (character[y][x]) {
|
||||
setRasterPixel(x + cx, y + cy);
|
||||
maxWidth = max(maxWidth, x + cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
return x + maxWidth;
|
||||
}
|
||||
|
||||
void setRasterPixel(const uint8_t x, const uint8_t y) const override {
|
||||
setIndexPixel(x * rows + y);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
37
src/display/DisplayPart.h
Normal file
37
src/display/DisplayPart.h
Normal file
@ -0,0 +1,37 @@
|
||||
#ifndef DISPLAYPART_H
|
||||
#define DISPLAYPART_H
|
||||
|
||||
#include "Display.h"
|
||||
|
||||
|
||||
class DisplayPart {
|
||||
|
||||
Display *display;
|
||||
|
||||
public:
|
||||
|
||||
const int indexOffset;
|
||||
|
||||
const int totalPixelCount;
|
||||
|
||||
const int nextPixelIndex;
|
||||
|
||||
protected:
|
||||
|
||||
DisplayPart(Display *display, const int indexOffset, const int totalPixelCount) : display(display), indexOffset(indexOffset), totalPixelCount(totalPixelCount), nextPixelIndex(indexOffset + totalPixelCount) {
|
||||
//
|
||||
}
|
||||
|
||||
virtual ~DisplayPart() = default;
|
||||
|
||||
public:
|
||||
|
||||
virtual void setRasterPixel(uint8_t x, uint8_t y) const = 0;
|
||||
|
||||
void setIndexPixel(const int index) const {
|
||||
display->setPixel(indexOffset + index);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
325
src/display/DisplayRasterFont.cpp
Normal file
325
src/display/DisplayRasterFont.cpp
Normal file
@ -0,0 +1,325 @@
|
||||
#include "DisplayRasterFont.h"
|
||||
|
||||
#include "../core/BASICS.h"
|
||||
|
||||
#define RASTER_FONT_NUMBER 0
|
||||
#define RASTER_FONT_ALPHA (RASTER_FONT_NUMBER + 10)
|
||||
#define RASTER_FONT_SPECIAL (RASTER_FONT_ALPHA + 26)
|
||||
|
||||
#define RASTER_FONT_COLON (RASTER_FONT_SPECIAL + 1)
|
||||
#define RASTER_FONT_DASH (RASTER_FONT_COLON + 1)
|
||||
#define RASTER_FONT_PERCENT (RASTER_FONT_DASH + 1)
|
||||
#define RASTER_FONT_DEGREE (RASTER_FONT_PERCENT + 1)
|
||||
#define RASTER_FONT_FALLBACK (RASTER_FONT_DEGREE + 1)
|
||||
|
||||
RasterCharacter *getRasterCharacter(const char character) {
|
||||
if (character >= '0' && character <= '9') {
|
||||
return &RASTER_FONT[character - '0' + RASTER_FONT_NUMBER];
|
||||
}
|
||||
if (character >= 'a' && character <= 'z') {
|
||||
return &RASTER_FONT[character - 'a' + RASTER_FONT_ALPHA];
|
||||
}
|
||||
if (character >= 'A' && character <= 'Z') {
|
||||
return &RASTER_FONT[character - 'A' + RASTER_FONT_ALPHA];
|
||||
}
|
||||
switch (character) {
|
||||
case ':': return &RASTER_FONT[RASTER_FONT_COLON];
|
||||
case '-': return &RASTER_FONT[RASTER_FONT_DASH];
|
||||
case '%': return &RASTER_FONT[RASTER_FONT_PERCENT];
|
||||
case '^': return &RASTER_FONT[RASTER_FONT_DEGREE];
|
||||
default: {
|
||||
error("[ERROR] NO RASTER MAPPING FOR CHARACTER \"%c\" = #%d\n", character, character);
|
||||
return &RASTER_FONT[RASTER_FONT_FALLBACK];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RasterCharacter RASTER_FONT[] = {
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
}, // 0
|
||||
{
|
||||
{_, _, X},
|
||||
{_, X, X},
|
||||
{X, _, X},
|
||||
{_, _, X},
|
||||
{_, _, X},
|
||||
}, // 1
|
||||
{
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{X, X, X},
|
||||
{X, _, _},
|
||||
{X, X, X},
|
||||
}, // 2
|
||||
{
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{_, X, X},
|
||||
{_, _, X},
|
||||
{X, X, X},
|
||||
}, // 3
|
||||
{
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{_, _, X},
|
||||
}, // 4
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, _},
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{X, X, X},
|
||||
}, // 5
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, _},
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
}, // 6
|
||||
{
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{_, X, _},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
}, // 7
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
}, // 8
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{X, X, X},
|
||||
}, // 9
|
||||
{
|
||||
{_, X, _},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
}, // A
|
||||
{
|
||||
{X, X, _},
|
||||
{X, _, X},
|
||||
{X, X, _},
|
||||
{X, _, X},
|
||||
{X, X, _},
|
||||
}, //
|
||||
{
|
||||
{_, X, X},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
{_, X, X},
|
||||
}, //
|
||||
{
|
||||
{X, X, _},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, _},
|
||||
{X, X, _},
|
||||
{X, _, _},
|
||||
{X, X, X},
|
||||
}, //
|
||||
{
|
||||
{X, X, X},
|
||||
{X, _, _},
|
||||
{X, X, _},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
}, //
|
||||
{
|
||||
{_, X, X},
|
||||
{X, _, _},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
}, //
|
||||
{
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, X, X},
|
||||
{_, _, X},
|
||||
{_, _, X},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, _, X},
|
||||
{X, X, _},
|
||||
{X, X, _},
|
||||
{X, _, _},
|
||||
{X, _, X},
|
||||
}, //
|
||||
{
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
{X, X, X},
|
||||
}, //
|
||||
{
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
}, //
|
||||
{
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
{_, X, _},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
}, //
|
||||
{
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
{_, X, _},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, X, _},
|
||||
{X, _, X},
|
||||
{X, X, _},
|
||||
{X, _, _},
|
||||
{X, _, _},
|
||||
}, //
|
||||
{
|
||||
{_, _, _},
|
||||
{_, X, X},
|
||||
{X, _, X},
|
||||
{_, X, X},
|
||||
{_, _, X},
|
||||
}, //
|
||||
{
|
||||
{X, X, _},
|
||||
{X, _, X},
|
||||
{X, X, _},
|
||||
{X, X, _},
|
||||
{X, _, X},
|
||||
}, //
|
||||
{
|
||||
{_, X, X},
|
||||
{X, _, _},
|
||||
{_, X, _},
|
||||
{_, _, X},
|
||||
{X, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, X, X},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
}, //
|
||||
{
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
}, // :
|
||||
{
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
}, // :
|
||||
{
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{X, X, X},
|
||||
{X, _, X},
|
||||
}, // :
|
||||
{
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
{X, _, X},
|
||||
}, // :
|
||||
{
|
||||
{X, _, X},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
{_, X, _},
|
||||
{X, _, _},
|
||||
}, // :
|
||||
{
|
||||
{X, X, X},
|
||||
{_, X, X},
|
||||
{_, X, _},
|
||||
{X, _, _},
|
||||
{X, X, X},
|
||||
}, // :
|
||||
{
|
||||
{_, _, _},
|
||||
{_, X, _},
|
||||
{_, _, _},
|
||||
{_, X, _},
|
||||
{_, _, _},
|
||||
}, // :
|
||||
{
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
{X, X, X},
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
}, // -
|
||||
{
|
||||
{X, _, _},
|
||||
{_, _, X},
|
||||
{_, X, _},
|
||||
{X, _, _},
|
||||
{_, _, X},
|
||||
}, // %
|
||||
{
|
||||
{_, X, _},
|
||||
{X, _, X},
|
||||
{_, X, _},
|
||||
{_, _, _},
|
||||
{_, _, _},
|
||||
}, // %
|
||||
{
|
||||
{X, X, X},
|
||||
{X, X, X},
|
||||
{X, X, X},
|
||||
{X, X, X},
|
||||
{X, X, X},
|
||||
}, // FALLBACK
|
||||
};
|
||||
10
src/display/DisplayRasterFont.h
Normal file
10
src/display/DisplayRasterFont.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef RASTER_FONT_H
|
||||
#define RASTER_FONT_H
|
||||
|
||||
typedef bool RasterCharacter[5][4];
|
||||
|
||||
extern RasterCharacter RASTER_FONT[];
|
||||
|
||||
RasterCharacter *getRasterCharacter(char character);
|
||||
|
||||
#endif
|
||||
3
src/display/MyDisplay.cpp
Normal file
3
src/display/MyDisplay.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
#include "MyDisplay.h"
|
||||
|
||||
MyDisplay display;
|
||||
32
src/display/MyDisplay.h
Normal file
32
src/display/MyDisplay.h
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef MY_DISPLAY_H
|
||||
#define MY_DISPLAY_H
|
||||
|
||||
#include "DisplayDigits4.h"
|
||||
|
||||
#include "DisplayMatrix.h"
|
||||
|
||||
class MyDisplay : public Display {
|
||||
|
||||
public:
|
||||
|
||||
DisplayDigits4 main;
|
||||
|
||||
DisplayMatrix left;
|
||||
|
||||
DisplayMatrix right;
|
||||
|
||||
explicit MyDisplay()
|
||||
: Display(TOTAL_PIXEL_COUNT + 2 * 3 * 5),
|
||||
main(this, 0),
|
||||
left(this, main.nextPixelIndex, 3, 5),
|
||||
right(this, left.nextPixelIndex, 3, 5) {
|
||||
//
|
||||
}
|
||||
|
||||
~MyDisplay() = default;
|
||||
|
||||
};
|
||||
|
||||
extern MyDisplay display;
|
||||
|
||||
#endif
|
||||
@ -1,9 +1,30 @@
|
||||
#include "font.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "../core/log.h"
|
||||
#include "../core/BASICS.h"
|
||||
|
||||
SYMBOL SYMBOLS[][SYMBOL_SIZE] = {
|
||||
Segment7Character *getSegment7Character(const char character) {
|
||||
if (character >= '0' && character <= '9') {
|
||||
return &SEGMENT7_FONT[character - '0'];
|
||||
}
|
||||
if (character >= 'a' && character <= 'z') {
|
||||
return &SEGMENT7_FONT[character - 'a' + 10];
|
||||
}
|
||||
if (character >= 'A' && character <= 'Z') {
|
||||
return &SEGMENT7_FONT[character - 'A' + 10];
|
||||
}
|
||||
switch (character) {
|
||||
case '-': return &SEGMENT7_FONT[36];
|
||||
case '_': return &SEGMENT7_FONT[37];
|
||||
case '^': return &SEGMENT7_FONT[38];
|
||||
case ' ': return &SEGMENT7_FONT[39];
|
||||
default: {
|
||||
error("[ERROR] NO SEGMENT7 MAPPING FOR CHARACTER \"%c\" = #%d\n", character, character);
|
||||
return &SEGMENT7_FONT[countof(SEGMENT7_FONT) - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Segment7Character SEGMENT7_FONT[] = {
|
||||
{X,X,X,X,X,X,_}, // 0
|
||||
{_,_,X,X,_,_,_}, // 1
|
||||
{_,X,X,_,X,X,X}, // 2
|
||||
@ -45,25 +66,3 @@ SYMBOL SYMBOLS[][SYMBOL_SIZE] = {
|
||||
{X,X,X,_,_,_,X}, // °
|
||||
{_,_,_,_,_,_,_}, //
|
||||
};
|
||||
|
||||
SYMBOL *getSymbol(const char character) {
|
||||
if (character >= '0' && character <= '9') {
|
||||
return SYMBOLS[character - '0'];
|
||||
}
|
||||
if (character >= 'a' && character <= 'z') {
|
||||
return SYMBOLS[character - 'a' + 10];
|
||||
}
|
||||
if (character >= 'A' && character <= 'Z') {
|
||||
return SYMBOLS[character - 'A' + 10];
|
||||
}
|
||||
switch (character) {
|
||||
case '-': return SYMBOLS[36];
|
||||
case '_': return SYMBOLS[37];
|
||||
case '^': return SYMBOLS[38];
|
||||
case ' ': return SYMBOLS[39];
|
||||
default: {
|
||||
error("[ERROR] NO SYMBOL MAPPING FOR CHARACTER \"%c\" = #%d\n", character, character);
|
||||
return SYMBOLS[SYMBOL_SIZE - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,10 @@
|
||||
#ifndef FONT_H
|
||||
#define FONT_H
|
||||
|
||||
#define X true
|
||||
#define _ false
|
||||
typedef const bool Segment7Character[7];
|
||||
|
||||
constexpr auto SYMBOL_COUNT = 39;
|
||||
extern Segment7Character SEGMENT7_FONT[40];
|
||||
|
||||
constexpr auto SYMBOL_SIZE = 7;
|
||||
|
||||
typedef const bool SYMBOL[SYMBOL_SIZE];
|
||||
|
||||
extern SYMBOL SYMBOLS[][SYMBOL_SIZE];
|
||||
|
||||
SYMBOL *getSymbol(char character);
|
||||
Segment7Character *getSegment7Character(char character);
|
||||
|
||||
#endif
|
||||
|
||||
@ -12,7 +12,7 @@ void setup() {
|
||||
bootDelay();
|
||||
fsMount();
|
||||
httpSetup();
|
||||
appStart(APP_DEMO_NAME);
|
||||
appStart(APP_MATCH_NAME);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user