Migre l'IHM OLED vers u8g2 (dashboard graphique, splash anime, economiseur d'ecran) et active la liaison TMS320 reelle
- TMS_DUMMY_MODE=false : reception/emission UART reelle avec le TMS320 (au lieu de la simulation), echo debug optionnel sur Serial. - Remplace le driver OLED maison (legacy/er_oled.*) par u8g2 : dashboard graphique avec bargraphs, icones d'alerte/danger, splash logo anime, economiseur d'ecran (balle rebondissante) qui se reactive sur activite HT ou consultation du dashboard web. - Renomme le SSID WiFi en "HIVY", documente le protocole UART et les problemes d'affichage SSD1322/u8g2 rencontres (doc/OLED-u8g2.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@ -137,10 +137,22 @@ trame si ca ne correspond pas (trame corrompue).
|
|||||||
`updateSimulation()`, qui simule des valeurs realistes (utile comme
|
`updateSimulation()`, qui simule des valeurs realistes (utile comme
|
||||||
reference de plage de valeurs attendues : `Vin` ~400V, `Iin` ~1.2A,
|
reference de plage de valeurs attendues : `Vin` ~400V, `Iin` ~1.2A,
|
||||||
`V1`/`Vout` ~200V, `I1`/`I2` ~2.5A, `T1`/`T2` ~40°C).
|
`V1`/`Vout` ~200V, `I1`/`I2` ~2.5A, `T1`/`T2` ~40°C).
|
||||||
- `include/config.h` : `TMS_DUMMY_MODE` (actuellement `true`) fait
|
- `include/config.h` : `TMS_DUMMY_MODE` (actuellement `false`, liaison
|
||||||
tourner l'ESP32 sur la simulation interne au lieu de lire l'UART reel.
|
reelle active) fait tourner l'ESP32 sur la simulation interne au lieu
|
||||||
**A passer a `false` une fois le firmware TMS320 pret et teste**, pour
|
de lire l'UART reel quand mis a `true` (utile pour developper l'IHM
|
||||||
activer la reception reelle des trames `$T,...*XX`.
|
sans hardware TMS320 branche).
|
||||||
|
|
||||||
|
## A faire cote protocole (pas encore implemente)
|
||||||
|
|
||||||
|
- **Trame de defaut** : le TMS doit signaler lui-meme une coupure de
|
||||||
|
securite des sorties PWM (court-circuit, surintensite I1/I2,
|
||||||
|
temperature critique >80°C) — pas de champ dedie actuellement, la
|
||||||
|
telemetrie ne donne que les mesures brutes. Cote ESP32,
|
||||||
|
`OledUi::drawDashboard()` (`src/oled_ui.cpp`) affiche pour l'instant
|
||||||
|
DEFAUT simplement quand HT n'est pas commande (`!cmd.ht`), en attendant
|
||||||
|
cette trame. Quand elle existera, ajouter le champ correspondant dans
|
||||||
|
`Telemetry` (`include/protocol.h`) et brancher la vraie condition dans
|
||||||
|
`drawDashboard()`.
|
||||||
|
|
||||||
## Points de vigilance
|
## Points de vigilance
|
||||||
|
|
||||||
@ -149,7 +161,7 @@ trame si ca ne correspond pas (trame corrompue).
|
|||||||
pas d'erreur visible — la telemetrie n'avancera simplement pas).
|
pas d'erreur visible — la telemetrie n'avancera simplement pas).
|
||||||
- Terminer chaque trame par `\n` uniquement (le `\r` est tolere/ignore
|
- Terminer chaque trame par `\n` uniquement (le `\r` est tolere/ignore
|
||||||
cote ESP32 mais pas necessaire).
|
cote ESP32 mais pas necessaire).
|
||||||
- Ne pas depasser une longueur de ligne de 160 caracteres (buffer fixe
|
- Ne pas depasser une longueur de ligne de 200 caracteres (buffer fixe
|
||||||
cote ESP32, `g_lineBuf[160]` dans `tms_link.cpp`).
|
cote ESP32, `g_lineBuf[200]` dans `tms_link.cpp`).
|
||||||
- Verifier au multimetre/oscilloscope le niveau logique du TMS320 avant
|
- Verifier au multimetre/oscilloscope le niveau logique du TMS320 avant
|
||||||
de le relier a l'ESP32-C3 (3,3V attendu).
|
de le relier a l'ESP32-C3 (3,3V attendu).
|
||||||
|
|||||||
66
doc/OLED-u8g2.md
Normal file
66
doc/OLED-u8g2.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Ecran OLED : migration vers u8g2
|
||||||
|
|
||||||
|
L'IHM OLED (`src/oled_ui.cpp`) utilise la librairie u8g2
|
||||||
|
(`U8G2_SSD1322_NHD_256X64_F_4W_HW_SPI`) depuis la migration du driver
|
||||||
|
maison (conserve dans `legacy/er_oled.cpp` / `legacy/er_oled.h` pour
|
||||||
|
reference, non compile).
|
||||||
|
|
||||||
|
## SPI matériel sur broches personnalisees
|
||||||
|
|
||||||
|
Le SSD1322 est cable sur des broches qui ne sont pas les broches SPI
|
||||||
|
par defaut de l'ESP32-C3. `SPI.begin(PIN_OLED_CLK, -1, PIN_OLED_MOSI,
|
||||||
|
PIN_OLED_CS)` doit etre appele **avant** `u8g2.begin()` pour que le bus
|
||||||
|
HW SPI d'u8g2 utilise ces broches (voir `OledUi::begin()`).
|
||||||
|
|
||||||
|
## Registre remap (0xA0)
|
||||||
|
|
||||||
|
Le remap par defaut d'u8g2 pour ce controleur (`0x06` dans
|
||||||
|
`u8x8_d_ssd1322.c`) ne correspond pas au cablage de notre panneau
|
||||||
|
(image en miroir horizontal). On reapplique apres `u8g2.begin()` la
|
||||||
|
valeur validee sur l'ancien driver maison : `u8g2.sendF("caa", 0xA0,
|
||||||
|
0x14, 0x11)` (COM remap + nibble remap actifs, column remap desactive).
|
||||||
|
|
||||||
|
**Ne pas desactiver le nibble remap** (`0x10` au lieu de `0x14`) : deja
|
||||||
|
teste, ca fait reapparaitre un miroir vertical et rend l'affichage
|
||||||
|
illisible. u8g2 lui-meme active ce bit dans son propre remap par
|
||||||
|
defaut (`0x06`), donc il est necessaire quelle que soit la config.
|
||||||
|
|
||||||
|
## Logo splash coupe en deux moities (128px)
|
||||||
|
|
||||||
|
Le logo de demarrage (256x64, dessine en un seul `drawXBMP`) s'affichait
|
||||||
|
coupe en deux moities de 128px inversees, alors que le texte du
|
||||||
|
dashboard (courtes sequences, meme chemin de dessin u8g2 sous-jacent)
|
||||||
|
s'affichait correctement. Plusieurs hypotheses testees sur le hardware,
|
||||||
|
**aucune n'a resolu le probleme individuellement** :
|
||||||
|
|
||||||
|
1. Bit "nibble remap" du registre 0xA0 -- écarté (voir ci-dessus, a
|
||||||
|
empire le probleme).
|
||||||
|
2. Optimisation RLE de `u8g2_DrawXBMP` (regroupe les runs de pixels en
|
||||||
|
longs segments qui traversent la frontiere interne a 128px du
|
||||||
|
SSD1322, puce a double controleur de colonnes) -- dessin pixel par
|
||||||
|
pixel teste, n'a pas resolu le probleme non plus.
|
||||||
|
3. `u8g2_uint_t` tronque a 8 bits sur les largeurs >= 256 si
|
||||||
|
`U8G2_16BIT` n'est pas actif -- **verifie non applicable** : dans
|
||||||
|
u8g2 >= 2.36 (celle utilisee ici, voir `platformio.ini`),
|
||||||
|
`U8G2_16BIT` est defini inconditionnellement (fix upstream de
|
||||||
|
l'issue olikraus/u8g2#1222), confirme par un `static_assert(sizeof(
|
||||||
|
u8g2_uint_t) == 2)` qui compile sans erreur. Le flag `-D U8G2_16BIT`
|
||||||
|
est neanmoins ajoute en dur dans `platformio.ini` par precaution,
|
||||||
|
au cas ou une future version de la lib restreindrait a nouveau la
|
||||||
|
detection auto par architecture (ESP32-C3 = RISC-V, absent de la
|
||||||
|
liste `__arm__`/`__xtensa__`/... citee par cette issue).
|
||||||
|
|
||||||
|
**Cause racine non identifiee formellement.** Contournement retenu :
|
||||||
|
dessiner le logo en deux moities de 128px (`lebel_logo_left` /
|
||||||
|
`lebel_logo_right` dans `src/lebel_logo_xbm.h`) via deux `drawXBMP`
|
||||||
|
successifs (`OledUi::showSplash()`), aucun appel ne depassant alors la
|
||||||
|
frontiere des 128px quelle que soit sa cause exacte. Le tableau
|
||||||
|
`lebel_logo_bits` (image complete 256x64) reste dans le fichier a
|
||||||
|
titre de reference mais n'est plus utilise et n'est pas garanti complet
|
||||||
|
(voir taille reelle du tableau si besoin de le reactiver un jour).
|
||||||
|
|
||||||
|
**A confirmer sur le hardware** : si le contournement en deux moities
|
||||||
|
fonctionne, tant mieux. Si le probleme persiste malgre tout, la cause
|
||||||
|
est ailleurs (registre remap plus subtil, alimentation, cablage) et il
|
||||||
|
faudra reprendre l'investigation cote registre SSD1322 avec plus de
|
||||||
|
prudence (deja regresse une fois en touchant ce registre a l'aveugle).
|
||||||
@ -15,12 +15,16 @@
|
|||||||
#define PIN_OLED_RST 3
|
#define PIN_OLED_RST 3
|
||||||
#define PIN_OLED_DC 1
|
#define PIN_OLED_DC 1
|
||||||
|
|
||||||
// Le firmware TMS320 n'est pas encore programme : on simule la telemetrie
|
// Le firmware TMS320 emet reellement des trames $T,...*XX sur l'UART :
|
||||||
// en local le temps que le hardware TMS320 tourne. Passer a false quand le
|
// on lit/ecrit le vrai Serial1 au lieu de simuler la telemetrie en local.
|
||||||
// TMS320 emet reellement des trames $T,...*XX sur l'UART.
|
// Repasser a true pour developper l'IHM sans hardware TMS320 branche.
|
||||||
#define TMS_DUMMY_MODE true
|
#define TMS_DUMMY_MODE false
|
||||||
|
|
||||||
|
// Recopie sur Serial (USB, moniteur PlatformIO) de chaque trame TMS320
|
||||||
|
// recue/envoyee sur Serial1, pour debug sans adaptateur UART externe.
|
||||||
|
#define TMS_DEBUG_ECHO true
|
||||||
|
|
||||||
// WiFi/serveur web de l'IHM : l'ESP32 cree son propre point d'acces
|
// WiFi/serveur web de l'IHM : l'ESP32 cree son propre point d'acces
|
||||||
// (mode AP), pas de dependance a un reseau local existant.
|
// (mode AP), pas de dependance a un reseau local existant.
|
||||||
#define WIFI_AP_SSID "AlimHT"
|
#define WIFI_AP_SSID "HIVY"
|
||||||
#define WIFI_AP_PASSWORD "Milou1234"
|
#define WIFI_AP_PASSWORD "Milou1234"
|
||||||
|
|||||||
@ -13,3 +13,12 @@ platform = espressif32
|
|||||||
board = esp32-c3-devkitm-1
|
board = esp32-c3-devkitm-1
|
||||||
framework = arduino
|
framework = arduino
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
lib_deps =
|
||||||
|
olikraus/U8g2@^2.35.19
|
||||||
|
; Deja actif inconditionnellement dans u8g2 >= 2.36 (fix upstream de
|
||||||
|
; l'issue #1222), mais force explicitement au cas ou une future version
|
||||||
|
; de la lib restreindrait a nouveau la detection auto par architecture
|
||||||
|
; (ESP32-C3 = RISC-V, absent de la liste __arm__/__xtensa__/... citee
|
||||||
|
; par cette issue).
|
||||||
|
build_flags =
|
||||||
|
-D U8G2_16BIT
|
||||||
|
|||||||
269
src/lebel_logo_xbm.h
Normal file
269
src/lebel_logo_xbm.h
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
// Logo LEBEL 256x64, format XBM pour u8g2 (drawXBMP).
|
||||||
|
// LSB = pixel le plus a gauche.
|
||||||
|
//
|
||||||
|
// Deux variantes fournies :
|
||||||
|
// - lebel_logo_bits : image complete 256x64 (necessite U8G2_16BIT)
|
||||||
|
// - lebel_logo_left/right : deux moities 128x64, sures meme en 8 bits
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define LEBEL_LOGO_WIDTH 256
|
||||||
|
#define LEBEL_LOGO_HEIGHT 64
|
||||||
|
#define LEBEL_LOGO_HALF_W 128
|
||||||
|
|
||||||
|
static const unsigned char lebel_logo_bits[] PROGMEM = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
|
||||||
|
0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
|
||||||
|
0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00,
|
||||||
|
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00,
|
||||||
|
0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x01, 0xC0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0x0F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFC, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x07, 0xE0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFC, 0x1F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x0F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xF8, 0x3F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xF0, 0x7F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xE0, 0xFF, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xC0, 0xFF, 0x01, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x80, 0xFF, 0x03, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xFF, 0x07, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xFE, 0x0F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xFC, 0x1F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xF8, 0x3F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xF0, 0x7F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xE0, 0xFF, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0xC0, 0xFF, 0xF9, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0x80, 0xFF, 0xF9, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0xFF, 0xF9, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x0F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFC, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x07, 0xE0, 0xE7, 0xFF, 0xFF, 0x7F, 0xE0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xF8, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x01, 0xC0, 0xE7, 0xFF, 0xFF, 0x7F, 0xC0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
||||||
|
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00,
|
||||||
|
0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00,
|
||||||
|
0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char lebel_logo_left[] PROGMEM = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0x0F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFC, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFC, 0x1F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xF8, 0x3F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xF0, 0x7F, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xE0, 0xFF, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xC0, 0xFF, 0x01, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x80, 0xFF, 0x03, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xFF, 0x07, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xFE, 0x0F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xFC, 0x1F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xF8, 0x3F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xF0, 0x7F, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xE0, 0xFF, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0xC0, 0xFF, 0xF9, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0x80, 0xFF, 0xF9, 0x07, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0xFF, 0xF9, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x0C, 0x00, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFE, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xFC, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x0C, 0xFE, 0xFF, 0xFF, 0xF9, 0xE7, 0xFF, 0xFF, 0x3F, 0xF8, 0xF8, 0xFF, 0xFF, 0x0F, 0xFE,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xE0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char lebel_logo_right[] PROGMEM = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x01, 0xC0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x07, 0xE0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x0F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0x01, 0x00, 0xC0, 0x1F, 0xF0, 0x07, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x1F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x0F, 0xF0, 0xE7, 0xFF, 0xFF, 0x7F, 0xF0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x07, 0xE0, 0xE7, 0xFF, 0xFF, 0x7F, 0xE0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0xF9, 0xFF, 0xFF, 0x01, 0xC0, 0xE7, 0xFF, 0xFF, 0x7F, 0xC0, 0xC7, 0xFF, 0xFF, 0x7F, 0x30, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
503
src/oled_ui.cpp
503
src/oled_ui.cpp
@ -1,54 +1,509 @@
|
|||||||
#include "oled_ui.h"
|
#include "oled_ui.h"
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <U8g2lib.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
|
||||||
#include "er_oled.h"
|
#include "config.h" // PIN_OLED_MOSI / CLK / CS / DC / RST, WIFI_AP_SSID
|
||||||
#include "tms_link.h"
|
#include "tms_link.h"
|
||||||
|
#include "web_ui.h" // WebUi::lastActivityMs(), reveil ecran si dashboard web consulte
|
||||||
|
#include "lebel_logo_xbm.h" // logo splash 256x64 (deux moities 128px)
|
||||||
|
#include "warning_icon_xbm.h" // icone danger principale 40x40
|
||||||
|
|
||||||
namespace OledUi {
|
namespace OledUi {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const uint32_t REFRESH_PERIOD_MS = 500;
|
// Memes broches que dans l'ancien er_oled_begin() : SPI matériel avec
|
||||||
|
// broches personnalisees (SCK/MOSI ne sont pas les pins HW SPI par
|
||||||
|
// defaut de l'ESP32-C3, d'ou l'appel explicite a SPI.begin() dans begin()
|
||||||
|
// ci-dessous, avant u8g2.begin()).
|
||||||
|
//
|
||||||
|
// NB : "_1_"/"_2_"/"_F_" dans le nom du constructeur u8g2 designent le
|
||||||
|
// mode de buffer (taille memoire), pas une variante de cablage du
|
||||||
|
// panneau -- il n'y a donc qu'un seul constructeur "full buffer" HW SPI
|
||||||
|
// pour ce controleur. Le remap segment/COM par defaut d'u8g2 ne
|
||||||
|
// correspondait pas au cablage de notre panneau (image coupee en deux
|
||||||
|
// moities gauche/droite inversees + miroir horizontal) ; corrige dans
|
||||||
|
// begin() en reappliquant le registre remap connu-fonctionnel de
|
||||||
|
// l'ancien driver maison (voir legacy/er_oled.cpp).
|
||||||
|
U8G2_SSD1322_NHD_256X64_F_4W_HW_SPI u8g2(
|
||||||
|
U8G2_R0,
|
||||||
|
/* cs=*/ PIN_OLED_CS,
|
||||||
|
/* dc=*/ PIN_OLED_DC,
|
||||||
|
/* reset=*/ PIN_OLED_RST);
|
||||||
|
|
||||||
|
const uint32_t REFRESH_PERIOD_MS = 300;
|
||||||
uint32_t g_lastRefreshMs = 0;
|
uint32_t g_lastRefreshMs = 0;
|
||||||
|
|
||||||
void drawLine(uint8_t y, const char *text) {
|
// Port du serveur web de l'IHM -- doit rester synchronise avec
|
||||||
char padded[33];
|
// `WebServer server(80)` dans web_ui.cpp (pas d'accesseur dedie pour
|
||||||
snprintf(padded, sizeof(padded), "%-32s", text);
|
// l'instant, les deux sont a changer ensemble si le port change).
|
||||||
er_oled_string(0, y, padded, 0);
|
const uint16_t WEB_UI_PORT = 80;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Splash logo (voir doc/OLED-u8g2.md pour l'historique des problemes
|
||||||
|
// d'affichage rencontres et resolus sur ce panneau).
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Logo remonte de 4px : drawXBMP ne prend pas de y negatif (u8g2_uint_t
|
||||||
|
// est non signe), donc on saute les 4 premieres lignes de la source
|
||||||
|
// (deja du blanc) et on reduit la hauteur d'autant.
|
||||||
|
const uint8_t LOGO_Y_SHIFT = 4;
|
||||||
|
const uint8_t LOGO_HALF_STRIDE = LEBEL_LOGO_HALF_W / 8;
|
||||||
|
const uint8_t LOGO_DRAW_H = LEBEL_LOGO_HEIGHT - LOGO_Y_SHIFT;
|
||||||
|
|
||||||
|
const uint32_t SPLASH_ANIM_MS = 500;
|
||||||
|
const uint8_t SPLASH_ANIM_FRAMES = 20;
|
||||||
|
const uint32_t SPLASH_HOLD_MS = 4000;
|
||||||
|
|
||||||
|
void drawLogo(uint16_t x) {
|
||||||
|
const uint8_t *leftBits = lebel_logo_left + LOGO_Y_SHIFT * LOGO_HALF_STRIDE;
|
||||||
|
const uint8_t *rightBits = lebel_logo_right + LOGO_Y_SHIFT * LOGO_HALF_STRIDE;
|
||||||
|
u8g2.drawXBMP(x, 0, LEBEL_LOGO_HALF_W, LOGO_DRAW_H, leftBits);
|
||||||
|
u8g2.drawXBMP(x + LEBEL_LOGO_HALF_W, 0, LEBEL_LOGO_HALF_W, LOGO_DRAW_H, rightBits);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dessine "s" caractere par caractere a partir d'un x signe : les
|
||||||
|
// caracteres dont la position tombe encore hors ecran (x < 0) ne sont
|
||||||
|
// pas dessines. u8g2.drawStr() n'accepte pas de x negatif
|
||||||
|
// (u8g2_uint_t est non signe) -- c'est le seul moyen de faire "entrer"
|
||||||
|
// du texte depuis en dehors de l'ecran.
|
||||||
|
void drawStrFromOffscreen(int16_t x, uint8_t y, const char *s) {
|
||||||
|
u8g2_t *raw = u8g2.getU8g2();
|
||||||
|
int16_t cx = x;
|
||||||
|
for (const char *p = s; *p; p++) {
|
||||||
|
uint8_t w = (uint8_t)u8g2_GetGlyphWidth(raw, (uint8_t)*p);
|
||||||
|
if (cx >= 0) u8g2.drawGlyph((uint16_t)cx, y, (uint8_t)*p);
|
||||||
|
cx += w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showSplash() {
|
||||||
|
u8g2.setFont(u8g2_font_6x10_tr);
|
||||||
|
u8g2.setFontPosTop();
|
||||||
|
const char *title = "HIVY - Alimentation Haute Tension 2026";
|
||||||
|
int16_t titleW = u8g2.getStrWidth(title);
|
||||||
|
int16_t titleFinalX = (LEBEL_LOGO_WIDTH - titleW) / 2;
|
||||||
|
if (titleFinalX < 0) titleFinalX = 0;
|
||||||
|
|
||||||
|
// Phase 1 (~500ms) : le logo arrive de la droite (x: 256 -> 0).
|
||||||
|
for (uint8_t frame = 0; frame <= SPLASH_ANIM_FRAMES; frame++) {
|
||||||
|
float t = (float)frame / SPLASH_ANIM_FRAMES;
|
||||||
|
uint16_t logoX = (uint16_t)(LEBEL_LOGO_WIDTH * (1.0f - t));
|
||||||
|
u8g2.clearBuffer();
|
||||||
|
drawLogo(logoX);
|
||||||
|
u8g2.sendBuffer();
|
||||||
|
delay(SPLASH_ANIM_MS / SPLASH_ANIM_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 2 (~500ms) : le logo est arrive, la phrase arrive ensuite de
|
||||||
|
// la gauche, depuis entierement hors ecran (x: -titleW -> centree).
|
||||||
|
for (uint8_t frame = 0; frame <= SPLASH_ANIM_FRAMES; frame++) {
|
||||||
|
float t = (float)frame / SPLASH_ANIM_FRAMES;
|
||||||
|
int16_t textX = (int16_t)(-titleW + (titleW + titleFinalX) * t);
|
||||||
|
u8g2.clearBuffer();
|
||||||
|
drawLogo(0);
|
||||||
|
drawStrFromOffscreen(textX, 51, title);
|
||||||
|
u8g2.sendBuffer();
|
||||||
|
delay(SPLASH_ANIM_MS / SPLASH_ANIM_FRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
delay(SPLASH_HOLD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Dashboard -- echelles d'affichage (VALEURS PROVISOIRES a corriger
|
||||||
|
// avec les vraies specs de l'alim, cf. doc/parametre-liaisonUART-TMS320-ESP32.txt
|
||||||
|
// et la calibration ADC dans doc/ESP32-UART.md pour les ordres de grandeur
|
||||||
|
// deja connus : VIN 30V max, IIN 3A max, VOUT 450V max, IOUT 50mA max).
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
const float VIN_MIN = 0.0f, VIN_MAX = 25.0f;
|
||||||
|
const float IIN_MIN = 0.0f, IIN_MAX = 3.0f;
|
||||||
|
const float VOUT_MIN = 200.0f, VOUT_MAX = 500.0f;
|
||||||
|
const float IOUT_MIN = 0.0f, IOUT_MAX = 0.050f; // 50 mA
|
||||||
|
const float PWR_MIN = 0.0f, PWR_MAX = 30.0f; // W, PIN/POUT
|
||||||
|
const float RDT_MIN = 50.0f, RDT_MAX = 100.0f; // %, rendement
|
||||||
|
|
||||||
|
const float ALERT_THRESHOLD = 0.90f; // 90% de l'echelle -> icone attention
|
||||||
|
|
||||||
|
// DEBUG PROVISOIRE : force l'affichage de toutes les icones (alerte +
|
||||||
|
// danger principale) pour verifier leur positionnement, independamment
|
||||||
|
// des seuils/etat reels. Positions validees -> desactive.
|
||||||
|
const bool DEBUG_FORCE_ALL_ICONS = false;
|
||||||
|
|
||||||
|
// Seuils temperature -- PROVISOIRES, a corriger avec les vraies specs.
|
||||||
|
const float T1_ALERT_C = 70.0f;
|
||||||
|
const float T2_ALERT_C = 70.0f;
|
||||||
|
|
||||||
|
// Icone danger principale : affichee seulement si HT actif ET Vout > 50V
|
||||||
|
// (jamais avec DEFAUT, meme si Vout resterait > 50V par inertie).
|
||||||
|
const float VOUT_DANGER_THRESHOLD = 50.0f;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Layout colonnes (256x64 reel)
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
const int SCREEN_W = 256;
|
||||||
|
const int COL1_X = 0;
|
||||||
|
const int COL2_X = 110;
|
||||||
|
const int COL3_X = 205;
|
||||||
|
|
||||||
|
// Bargraphs + valeurs min/max + mesures descendus de 2px (BAR_Y 16->18).
|
||||||
|
const int BAR_Y = 18;
|
||||||
|
const int BAR_H = 32;
|
||||||
|
const int BAR_W = 8;
|
||||||
|
|
||||||
|
// Ligne verticale entre colonne 1 et 2, decalee de 2px vers la gauche
|
||||||
|
// par rapport a COL2_X (qui reste la reference des elements colonne 2).
|
||||||
|
const int COL1_COL2_DIVIDER_X = COL2_X - 2;
|
||||||
|
|
||||||
|
// Clignotement 1s ON / 1s OFF, partage par toutes les icones d'alerte
|
||||||
|
// et les mots d'etat de defaut (DEFAUT, SYS:KO).
|
||||||
|
bool Blink1Hz() { return (millis() / 1000) % 2 == 0; }
|
||||||
|
|
||||||
|
// Mini icone triangle + "!" (dessin vectoriel, trop petit pour un bitmap net)
|
||||||
|
void drawAlertIcon(int x, int y) {
|
||||||
|
u8g2.drawTriangle(x + 5, y, x, y + 9, x + 10, y + 9);
|
||||||
|
u8g2.drawVLine(x + 4, y + 3, 3);
|
||||||
|
u8g2.drawPixel(x + 4, y + 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Icone danger principale a moitie taille (20x20) : drawXBMP ne
|
||||||
|
// redimensionne pas, donc on ne prend qu'un pixel source sur deux
|
||||||
|
// (nearest-neighbor) sur le bitmap 40x40 existant plutot que de
|
||||||
|
// fabriquer un second asset.
|
||||||
|
void drawWarningIconHalf(int x, int y) {
|
||||||
|
const uint8_t stride = WARNING_ICON_WIDTH / 8;
|
||||||
|
for (int dy = 0; dy < WARNING_ICON_HEIGHT / 2; dy++) {
|
||||||
|
for (int dx = 0; dx < WARNING_ICON_WIDTH / 2; dx++) {
|
||||||
|
uint8_t b = pgm_read_byte(&warning_icon_bits[dy * 2 * stride + (dx * 2) / 8]);
|
||||||
|
if (b & (1 << ((dx * 2) % 8))) u8g2.drawPixel(x + dx, y + dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bargraph vertical avec limites affichees a droite et icone d'alerte
|
||||||
|
// optionnelle si valeur >= ALERT_THRESHOLD de l'echelle.
|
||||||
|
// Valeurs min/max remontees de 4px par rapport au haut de la barre
|
||||||
|
// (LABEL_Y_SHIFT) pour ne plus mordre sur le cadre du bargraph -- ce
|
||||||
|
// shift suit BAR_Y (descend avec le bargraph). Le TITRE (nom de la
|
||||||
|
// grandeur, ex. "VIN") ne doit lui pas bouger quand BAR_Y descend, donc
|
||||||
|
// TITLE_Y_SHIFT = LABEL_Y_SHIFT + (delta BAR_Y) pour compenser.
|
||||||
|
const int LABEL_Y_SHIFT = 4;
|
||||||
|
const int TITLE_Y_SHIFT = 6;
|
||||||
|
|
||||||
|
// labelScale : facteur applique uniquement a l'affichage des bornes
|
||||||
|
// min/max (ex. IOUT_MAX=0.050 A -> affiche "50" avec labelScale=1000,
|
||||||
|
// pour matcher l'unite mA affichee ailleurs). Le remplissage de la
|
||||||
|
// barre reste calcule sur value/vmin/vmax tels quels (unite d'origine).
|
||||||
|
// labelXOffset : decalage horizontal du seul texte du label (le nom de
|
||||||
|
// la grandeur, ex. "RENDEMENT"), independant du bar/valeurs.
|
||||||
|
void drawVBar(int x, const char *label, float value, float vmin, float vmax,
|
||||||
|
bool showAlert, int alertXOffset = 0, float labelScale = 1.0f,
|
||||||
|
int labelXOffset = 0) {
|
||||||
|
u8g2.setFont(u8g2_font_4x6_tr);
|
||||||
|
u8g2.drawStr(x + labelXOffset, BAR_Y - 3 - TITLE_Y_SHIFT, label);
|
||||||
|
|
||||||
|
u8g2.drawFrame(x, BAR_Y, BAR_W, BAR_H);
|
||||||
|
float pct = (value - vmin) / (vmax - vmin);
|
||||||
|
if (pct < 0) pct = 0;
|
||||||
|
if (pct > 1) pct = 1;
|
||||||
|
int fillH = (int)(pct * (BAR_H - 2));
|
||||||
|
if (fillH > 0) {
|
||||||
|
u8g2.drawBox(x + 1, BAR_Y + (BAR_H - 1 - fillH), BAR_W - 2, fillH);
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[8];
|
||||||
|
u8g2.setFont(u8g2_font_4x6_tr);
|
||||||
|
snprintf(buf, sizeof(buf), "%.0f", vmax * labelScale);
|
||||||
|
u8g2.drawStr(x + BAR_W + 3, BAR_Y + 5 - LABEL_Y_SHIFT, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%.0f", vmin * labelScale);
|
||||||
|
u8g2.drawStr(x + BAR_W + 3, BAR_Y + BAR_H - LABEL_Y_SHIFT, buf);
|
||||||
|
|
||||||
|
if (showAlert && (DEBUG_FORCE_ALL_ICONS || pct >= ALERT_THRESHOLD) && Blink1Hz()) {
|
||||||
|
drawAlertIcon(x + BAR_W + 16 + alertXOffset, BAR_Y + BAR_H / 2 - 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Economiseur d'ecran : balle rebondissante avec trainee de 20px qui
|
||||||
|
// s'estompe progressivement (utilise les 16 niveaux de gris du SSD1322).
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
const uint32_t IDLE_TIMEOUT_MS = 5UL * 60UL * 1000UL; // 5 min sans activite
|
||||||
|
const uint32_t BALL_STEP_MS = 40; // ~25 fps
|
||||||
|
const int BALL_SIZE = 3; // balle 3x3 px
|
||||||
|
const int TRAIL_LEN = 40; // longueur de la trainee (~40px)
|
||||||
|
|
||||||
|
float g_ballX = 40, g_ballY = 20;
|
||||||
|
float g_ballVX = 1.3f, g_ballVY = 0.9f;
|
||||||
|
|
||||||
|
// buffer circulaire des dernieres positions (centre de la balle)
|
||||||
|
int g_trailX[TRAIL_LEN];
|
||||||
|
int g_trailY[TRAIL_LEN];
|
||||||
|
int g_trailCount = 0; // nb de positions valides (monte jusqu'a TRAIL_LEN)
|
||||||
|
int g_trailHead = 0; // index de la position la plus recente
|
||||||
|
|
||||||
|
uint32_t g_lastActivityMs = 0;
|
||||||
|
uint32_t g_lastBallStepMs = 0;
|
||||||
|
bool g_screensaverActive = false;
|
||||||
|
|
||||||
|
bool g_lastHtState = false;
|
||||||
|
bool g_htStateInit = false;
|
||||||
|
|
||||||
|
void resetActivityTimer() {
|
||||||
|
g_lastActivityMs = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkActivity(const Telemetry & /*t*/, bool /*linkOk*/, bool htOn) {
|
||||||
|
if (!g_htStateInit) {
|
||||||
|
g_lastHtState = htOn;
|
||||||
|
g_htStateInit = true;
|
||||||
|
resetActivityTimer();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (htOn != g_lastHtState) {
|
||||||
|
g_lastHtState = htOn;
|
||||||
|
resetActivityTimer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pushTrailPoint(int x, int y) {
|
||||||
|
g_trailHead = (g_trailHead + 1) % TRAIL_LEN;
|
||||||
|
g_trailX[g_trailHead] = x;
|
||||||
|
g_trailY[g_trailHead] = y;
|
||||||
|
if (g_trailCount < TRAIL_LEN) g_trailCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stepBall() {
|
||||||
|
pushTrailPoint((int)g_ballX + BALL_SIZE / 2, (int)g_ballY + BALL_SIZE / 2);
|
||||||
|
|
||||||
|
g_ballX += g_ballVX;
|
||||||
|
g_ballY += g_ballVY;
|
||||||
|
|
||||||
|
if (g_ballX <= 0 || g_ballX >= SCREEN_W - BALL_SIZE) g_ballVX = -g_ballVX;
|
||||||
|
if (g_ballY <= 0 || g_ballY >= 64 - BALL_SIZE) g_ballVY = -g_ballVY;
|
||||||
|
|
||||||
|
if (g_ballX < 0) g_ballX = 0;
|
||||||
|
if (g_ballY < 0) g_ballY = 0;
|
||||||
|
if (g_ballX > SCREEN_W - BALL_SIZE) g_ballX = SCREEN_W - BALL_SIZE;
|
||||||
|
if (g_ballY > 64 - BALL_SIZE) g_ballY = 64 - BALL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawScreensaver() {
|
||||||
|
uint32_t now = millis();
|
||||||
|
if (now - g_lastBallStepMs >= BALL_STEP_MS) {
|
||||||
|
g_lastBallStepMs = now;
|
||||||
|
stepBall();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8g2.clearBuffer();
|
||||||
|
|
||||||
|
// trainee : fade par densite, pas par niveau de gris. Le buffer u8g2
|
||||||
|
// pour ce driver (u8g2_ll_hvline_vertical_top_lsb, u8g2_ll_hvline.c)
|
||||||
|
// est 1 bit/pixel -- setDrawColor(2..15) y fait un XOR/toggle, pas un
|
||||||
|
// niveau de gris intermediaire (seuls 0/1 sont on/off reels). Les 16
|
||||||
|
// niveaux de gris du SSD1322 sont une capacite materielle (contraste),
|
||||||
|
// pas exposee en 4bpp par pixel par cette configuration u8g2. On
|
||||||
|
// simule donc le fade en n'affichant qu'un point sur deux dans la
|
||||||
|
// moitie la plus ancienne de la trainee (dense pres de la balle,
|
||||||
|
// clairsemee derriere).
|
||||||
|
u8g2.setDrawColor(1);
|
||||||
|
for (int i = 0; i < g_trailCount; i++) {
|
||||||
|
int idx = (g_trailHead - g_trailCount + 1 + i + TRAIL_LEN) % TRAIL_LEN;
|
||||||
|
if (i < TRAIL_LEN / 2 && (i % 2) != 0) continue;
|
||||||
|
u8g2.drawPixel(g_trailX[idx], g_trailY[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8g2.setDrawColor(1); // pas 15 : cf. remarque ci-dessus, XOR/toggle sinon
|
||||||
|
u8g2.drawBox((int)g_ballX, (int)g_ballY, BALL_SIZE, BALL_SIZE);
|
||||||
|
|
||||||
|
u8g2.sendBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tout sur un seul ecran (4 lignes de 32 caracteres) : statut liaison et
|
|
||||||
// commandes, electrique d'entree, puis un resume par etage.
|
|
||||||
void drawDashboard(const Telemetry &t, bool linkOk) {
|
void drawDashboard(const Telemetry &t, bool linkOk) {
|
||||||
char l0[33], l1[33], l2[33], l3[33];
|
|
||||||
const CommandState &cmd = TmsLink::command();
|
const CommandState &cmd = TmsLink::command();
|
||||||
snprintf(l0, sizeof(l0), "TMS:%s HT:%s P1:%s P2:%s", linkOk ? "OK" : "KO",
|
u8g2.clearBuffer();
|
||||||
cmd.ht ? "ON" : "OFF", cmd.pwm1 ? "ON" : "OFF", cmd.pwm2 ? "ON" : "OFF");
|
// setDrawColor(1) explicite : l'economiseur d'ecran laisse le contexte
|
||||||
snprintf(l1, sizeof(l1), "Vin=%.0fV Iin=%.2fA Iout=%.2fA", t.vin, t.iin, t.iout);
|
// u8g2 sur un niveau de gris partiel (degrade de la trainee) apres son
|
||||||
snprintf(l2, sizeof(l2), "E1 F%.0fk D%.0f%% V%.0fV I%.2fA T%.0fC", t.freq1 / 1000.0f,
|
// dernier appel -- sans ca, le dashboard heriterait de ce niveau au
|
||||||
t.duty1, t.v1, t.i1, t.t1);
|
// lieu du blanc plein apres une sortie de veille.
|
||||||
snprintf(l3, sizeof(l3), "E2 F%.0fk D%.0f%% V%.0fV I%.2fA T%.0fC", t.freq2 / 1000.0f,
|
u8g2.setDrawColor(1);
|
||||||
t.duty2, t.vout, t.i2, t.t2);
|
char buf[40];
|
||||||
drawLine(0, l0);
|
|
||||||
drawLine(16, l1);
|
// --- bandeau haut : HIVY (gauche) / SYS:OK (centre) / WIFI:... (droite) ---
|
||||||
drawLine(32, l2);
|
// SSID dynamique (config.h, maintenant "HIVY") + IP reelle (WiFi.softAPIP(),
|
||||||
drawLine(48, l3);
|
// attribuee par WiFi.softAP() dans web_ui.cpp) + port (WEB_UI_PORT ci-dessus).
|
||||||
|
u8g2.setFont(u8g2_font_5x8_tr);
|
||||||
|
u8g2.setFontPosTop();
|
||||||
|
u8g2.drawStr(0, 0, "HIVY");
|
||||||
|
|
||||||
|
// SYS:KO clignote (Blink1Hz) pour attirer l'attention ; SYS:OK reste fixe.
|
||||||
|
if (linkOk || Blink1Hz()) {
|
||||||
|
snprintf(buf, sizeof(buf), "SYS:%s", linkOk ? "OK" : "KO");
|
||||||
|
int wSys = u8g2.getStrWidth(buf);
|
||||||
|
u8g2.drawStr((SCREEN_W - wSys) / 2 - 40, 0, buf); // historique : +20, -40, -20 = -40
|
||||||
|
}
|
||||||
|
|
||||||
|
IPAddress ip = WiFi.softAPIP();
|
||||||
|
snprintf(buf, sizeof(buf), "WIFI:%s %d.%d.%d.%d:%u", WIFI_AP_SSID, ip[0], ip[1],
|
||||||
|
ip[2], ip[3], WEB_UI_PORT);
|
||||||
|
int wWifi = u8g2.getStrWidth(buf);
|
||||||
|
u8g2.drawStr(SCREEN_W - wWifi, 0, buf);
|
||||||
|
|
||||||
|
// --- colonne 1 : VIN / IIN / VOUT / IOUT ---
|
||||||
|
// Logo 4 (IOUT) : -10 encore -3px = -13.
|
||||||
|
drawVBar(COL1_X + 2, "VIN", t.vin, VIN_MIN, VIN_MAX, true, -14);
|
||||||
|
drawVBar(COL1_X + 29, "IIN", t.iin, IIN_MIN, IIN_MAX, true, -14);
|
||||||
|
drawVBar(COL1_X + 56, "VOUT", t.vout, VOUT_MIN, VOUT_MAX, true, -14);
|
||||||
|
// labelScale=1000 : bornes affichees en mA (0/50) au lieu de A (0/0.05).
|
||||||
|
drawVBar(COL1_X + 83, "IOUT", t.iout, IOUT_MIN, IOUT_MAX, true, -13, 1000.0f);
|
||||||
|
|
||||||
|
u8g2.setFont(u8g2_font_6x12_tr);
|
||||||
|
snprintf(buf, sizeof(buf), "%.1fV", t.vin);
|
||||||
|
u8g2.drawStr(COL1_X, BAR_Y + BAR_H + 4, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%.1fA", t.iin); // 2 digits (X.Y)
|
||||||
|
u8g2.drawStr(COL1_X + 27, BAR_Y + BAR_H + 4, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%.0fV", t.vout);
|
||||||
|
u8g2.drawStr(COL1_X + 54, BAR_Y + BAR_H + 4, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%.0fmA", t.iout * 1000.0f);
|
||||||
|
u8g2.drawStr(COL1_X + 81, BAR_Y + BAR_H + 4, buf);
|
||||||
|
|
||||||
|
u8g2.drawVLine(COL1_COL2_DIVIDER_X, BAR_Y - 6, BAR_H + 20);
|
||||||
|
|
||||||
|
// --- colonne 2 : RENDEMENT (50-100%, pas d'alerte) / PIN / POUT ---
|
||||||
|
float pin = t.vin * t.iin;
|
||||||
|
float pout = t.vout * t.iout;
|
||||||
|
float eff = (pin > 0.01f) ? (pout / pin * 100.0f) : 0.0f;
|
||||||
|
if (eff > 100.0f) eff = 100.0f;
|
||||||
|
if (eff < 0.0f) eff = 0.0f;
|
||||||
|
|
||||||
|
// RENDEMENT (bar+valeur) decale de 6px a droite ; PIN/POUT (bar+valeur)
|
||||||
|
// decales de 4px a droite. Logos 5 et 6 (PIN/POUT) suivent
|
||||||
|
// automatiquement puisque l'offset icone est relatif au x du bar.
|
||||||
|
// Seul le mot "RENDEMENT" est ensuite recentre 6px vers la gauche
|
||||||
|
// (labelXOffset), independamment du bar/valeur qui restent en place.
|
||||||
|
drawVBar(COL2_X + 9, "RENDEMENT", eff, RDT_MIN, RDT_MAX, false, 0, 1.0f, -6); // pas d'icone (showAlert=false)
|
||||||
|
drawVBar(COL2_X + 43, "PIN", pin, PWR_MIN, PWR_MAX, true, -14);
|
||||||
|
drawVBar(COL2_X + 70, "POUT", pout, PWR_MIN, PWR_MAX, true, -14);
|
||||||
|
|
||||||
|
u8g2.setFont(u8g2_font_6x12_tr);
|
||||||
|
snprintf(buf, sizeof(buf), "%.0f%%", eff);
|
||||||
|
u8g2.drawStr(COL2_X + 7, BAR_Y + BAR_H + 4, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%.1fW", pin);
|
||||||
|
u8g2.drawStr(COL2_X + 41, BAR_Y + BAR_H + 4, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "%.1fW", pout);
|
||||||
|
u8g2.drawStr(COL2_X + 68, BAR_Y + BAR_H + 4, buf);
|
||||||
|
|
||||||
|
u8g2.drawVLine(COL3_X, BAR_Y - 6, BAR_H + 20);
|
||||||
|
|
||||||
|
// --- colonne 3 : I1/T1, I2/T2, HT/OFF/DEFAUT, icone danger ---
|
||||||
|
// Tout le contenu de la colonne remonte de 5px.
|
||||||
|
u8g2.setFont(u8g2_font_5x8_tr);
|
||||||
|
snprintf(buf, sizeof(buf), "I1 %.1fA", t.i1); // 2 digits (X.Y)
|
||||||
|
u8g2.drawStr(COL3_X + 4, 11, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "T1 %.0fC", t.t1);
|
||||||
|
u8g2.drawStr(COL3_X + 4, 21, buf);
|
||||||
|
// Icone T1 completement a droite (flush ecran) ; le haut du triangle
|
||||||
|
// (apex, "y" dans drawAlertIcon) aligne sur le haut de la ligne I1 (y=11).
|
||||||
|
if ((DEBUG_FORCE_ALL_ICONS || t.t1 >= T1_ALERT_C) && Blink1Hz()) drawAlertIcon(SCREEN_W - 10, 11);
|
||||||
|
|
||||||
|
// I2/T2 remontes de 2px supplementaires (35->33, 45->43).
|
||||||
|
snprintf(buf, sizeof(buf), "I2 %.1fA", t.i2); // 2 digits (X.Y)
|
||||||
|
u8g2.drawStr(COL3_X + 4, 33, buf);
|
||||||
|
snprintf(buf, sizeof(buf), "T2 %.0fC", t.t2);
|
||||||
|
u8g2.drawStr(COL3_X + 4, 43, buf);
|
||||||
|
// Icone T2 completement a droite (flush ecran) ; la base du triangle
|
||||||
|
// (y+9 dans drawAlertIcon) aligne sur la base de la ligne I2 (33+8=41,
|
||||||
|
// donc y=41-9=32).
|
||||||
|
if ((DEBUG_FORCE_ALL_ICONS || t.t2 >= T2_ALERT_C) && Blink1Hz()) drawAlertIcon(SCREEN_W - 10, 32);
|
||||||
|
|
||||||
|
u8g2.setFont(u8g2_font_7x13B_tr);
|
||||||
|
// HT/OFF/DEFAUT (coherent avec le libelle du bouton "HT" de la page
|
||||||
|
// web, plutot que "RUN") : HT si HT_EN actif, OFF si inactif, DEFAUT
|
||||||
|
// (clignotant) si un probleme est detecte. HT/OFF restent fixes,
|
||||||
|
// seul DEFAUT clignote (Blink1Hz).
|
||||||
|
//
|
||||||
|
// TODO(protocole) : la detection de probleme n'existe pas encore --
|
||||||
|
// problemDetected reste a false pour l'instant. Le TMS doit signaler
|
||||||
|
// lui-meme le defaut (court-circuit, surintensite I1/I2, temperature
|
||||||
|
// critique >80C) via une trame dediee, pas encore implementee cote TMS
|
||||||
|
// (cf. discussion). Quand cette trame existera (ajouter un champ
|
||||||
|
// correspondant dans Telemetry/protocol.h), c'est ici qu'il faudra
|
||||||
|
// brancher la vraie condition, plutot que de deviner des seuils cote
|
||||||
|
// ESP32 sans donnee du TMS pour les confirmer.
|
||||||
|
bool problemDetected = false;
|
||||||
|
if (problemDetected) {
|
||||||
|
if (Blink1Hz()) u8g2.drawStr(COL3_X + 2, 53, "DEFAUT");
|
||||||
|
} else {
|
||||||
|
u8g2.drawStr(COL3_X + 2, 53, cmd.ht ? "HT" : "OFF");
|
||||||
|
}
|
||||||
|
|
||||||
|
// icone danger principale (20x20), clignotante (Blink1Hz, 1s ON/1s OFF).
|
||||||
|
// Regle reelle : HT actif (cmd.ht) ET Vout > 50V -- jamais avec DEFAUT,
|
||||||
|
// meme si Vout mesure encore > 50V par inertie a ce moment-la.
|
||||||
|
// Calee tout en bas a droite de la colonne 3 (= bord ecran).
|
||||||
|
bool dangerActive = cmd.ht && t.vout > VOUT_DANGER_THRESHOLD;
|
||||||
|
if ((DEBUG_FORCE_ALL_ICONS || dangerActive) && Blink1Hz()) {
|
||||||
|
drawWarningIconHalf(SCREEN_W - WARNING_ICON_WIDTH / 2, 64 - WARNING_ICON_HEIGHT / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
u8g2.sendBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void begin() {
|
void begin() {
|
||||||
er_oled_begin();
|
// Broches SPI personnalisees (comme l'ancien driver er_oled.cpp) :
|
||||||
er_oled_clear();
|
// sck, miso (non cable), mosi, ss. A faire avant u8g2.begin() pour
|
||||||
|
// que le bus HW SPI d'u8g2 utilise ces pins plutot que les pins par
|
||||||
|
// defaut de l'ESP32-C3.
|
||||||
|
SPI.begin(PIN_OLED_CLK, -1, PIN_OLED_MOSI, PIN_OLED_CS);
|
||||||
|
|
||||||
|
u8g2.begin();
|
||||||
|
|
||||||
|
// Re-applique le registre "Set Re-map / Dual COM Line Mode" (0xA0) tel
|
||||||
|
// que valide sur l'ancien driver maison (legacy/er_oled.cpp) : COM
|
||||||
|
// remap + nibble remap actives, column remap desactive. Le remap par
|
||||||
|
// defaut d'u8g2 pour ce controleur ne correspond pas au cablage de ce
|
||||||
|
// panneau (image en miroir horizontal sinon).
|
||||||
|
//
|
||||||
|
// NB : desactiver le nibble remap (0x10 au lieu de 0x14) a ete essaye
|
||||||
|
// pour tenter de corriger le logo coupe en deux, mais a fait
|
||||||
|
// reapparaitre le miroir vertical et rendu l'affichage illisible --
|
||||||
|
// donc le nibble remap doit rester actif ici, contrairement a
|
||||||
|
// l'hypothese initiale.
|
||||||
|
u8g2.sendF("caa", 0xA0, 0x14, 0x11);
|
||||||
|
|
||||||
|
showSplash();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const Telemetry &t, bool linkOk) {
|
void update(const Telemetry &t, bool linkOk) {
|
||||||
|
const CommandState &cmd = TmsLink::command();
|
||||||
|
checkActivity(t, linkOk, cmd.ht);
|
||||||
|
|
||||||
|
// Page web consultee recemment (chargement de page ou poll /api/state,
|
||||||
|
// qui revient toutes les 1s tant que la page reste ouverte dans un
|
||||||
|
// navigateur) -> compte comme de l'activite, reactive/maintient le
|
||||||
|
// dashboard OLED.
|
||||||
|
if (millis() - WebUi::lastActivityMs() < IDLE_TIMEOUT_MS) {
|
||||||
|
resetActivityTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool idle = (millis() - g_lastActivityMs) >= IDLE_TIMEOUT_MS;
|
||||||
|
if (idle) {
|
||||||
|
g_screensaverActive = true;
|
||||||
|
drawScreensaver();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (g_screensaverActive) {
|
||||||
|
g_screensaverActive = false;
|
||||||
|
g_lastRefreshMs = 0; // force un redraw complet du dashboard au reveil
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t now = millis();
|
uint32_t now = millis();
|
||||||
if (now - g_lastRefreshMs < REFRESH_PERIOD_MS) return;
|
if (now - g_lastRefreshMs < REFRESH_PERIOD_MS) return;
|
||||||
g_lastRefreshMs = now;
|
g_lastRefreshMs = now;
|
||||||
|
|
||||||
drawDashboard(t, linkOk);
|
drawDashboard(t, linkOk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
|
||||||
namespace OledUi {
|
namespace OledUi {
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
|
|
||||||
// A appeler en boucle. Redessine l'ecran periodiquement et fait tourner
|
|
||||||
// les pages (entree/commandes, etage 1, etage 2).
|
|
||||||
void update(const Telemetry &t, bool linkOk);
|
void update(const Telemetry &t, bool linkOk);
|
||||||
|
|
||||||
} // namespace OledUi
|
} // namespace OledUi
|
||||||
|
|||||||
@ -14,7 +14,7 @@ CommandState g_command;
|
|||||||
uint32_t g_lastValidFrameMs = 0;
|
uint32_t g_lastValidFrameMs = 0;
|
||||||
uint32_t g_lastCommandSentMs = 0;
|
uint32_t g_lastCommandSentMs = 0;
|
||||||
|
|
||||||
char g_lineBuf[160];
|
char g_lineBuf[200];
|
||||||
uint8_t g_lineLen = 0;
|
uint8_t g_lineLen = 0;
|
||||||
|
|
||||||
const uint32_t COMMAND_SEND_PERIOD_MS = 500;
|
const uint32_t COMMAND_SEND_PERIOD_MS = 500;
|
||||||
@ -75,12 +75,25 @@ bool parseTelemetryLine(char *line) {
|
|||||||
void pollUart() {
|
void pollUart() {
|
||||||
while (Serial1.available()) {
|
while (Serial1.available()) {
|
||||||
char c = (char)Serial1.read();
|
char c = (char)Serial1.read();
|
||||||
|
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
g_lineBuf[g_lineLen] = '\0';
|
g_lineBuf[g_lineLen] = '\0';
|
||||||
if (parseTelemetryLine(g_lineBuf)) {
|
|
||||||
|
// Copie avant parsing : parseTelemetryLine() decoupe g_lineBuf en
|
||||||
|
// place (strtok_r, '=' -> '\0'), donc l'afficher apres coup ne
|
||||||
|
// montrerait que le premier fragment tronque.
|
||||||
|
char display[sizeof(g_lineBuf)];
|
||||||
|
if (TMS_DEBUG_ECHO) memcpy(display, g_lineBuf, g_lineLen + 1);
|
||||||
|
|
||||||
|
bool ok = parseTelemetryLine(g_lineBuf);
|
||||||
|
if (ok) {
|
||||||
g_telemetry.lastUpdateMs = millis();
|
g_telemetry.lastUpdateMs = millis();
|
||||||
g_lastValidFrameMs = g_telemetry.lastUpdateMs;
|
g_lastValidFrameMs = g_telemetry.lastUpdateMs;
|
||||||
}
|
}
|
||||||
|
if (TMS_DEBUG_ECHO) {
|
||||||
|
Serial.print(ok ? "TMS<< " : "TMS<< [rejete] ");
|
||||||
|
Serial.println(display);
|
||||||
|
}
|
||||||
g_lineLen = 0;
|
g_lineLen = 0;
|
||||||
} else if (c != '\r') {
|
} else if (c != '\r') {
|
||||||
if (g_lineLen < sizeof(g_lineBuf) - 1) {
|
if (g_lineLen < sizeof(g_lineBuf) - 1) {
|
||||||
@ -136,6 +149,7 @@ void sendCommandFrame() {
|
|||||||
char frame[64];
|
char frame[64];
|
||||||
snprintf(frame, sizeof(frame), "$%s*%02X\n", body, cs);
|
snprintf(frame, sizeof(frame), "$%s*%02X\n", body, cs);
|
||||||
Serial1.print(frame);
|
Serial1.print(frame);
|
||||||
|
if (TMS_DEBUG_ECHO) Serial.printf("TMS>> %s", frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
24
src/warning_icon_xbm.h
Normal file
24
src/warning_icon_xbm.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Icone danger haute tension (triangle + eclair), 40x40, format XBM pour u8g2.drawXBMP
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define WARNING_ICON_WIDTH 40
|
||||||
|
#define WARNING_ICON_HEIGHT 40
|
||||||
|
|
||||||
|
static const unsigned char warning_icon_bits[] PROGMEM = {
|
||||||
|
// 1er octet corrige (etait 0x01) : un pixel isole allumait le coin
|
||||||
|
// superieur gauche du bitmap, sans aucun pixel voisin -- defaut de la
|
||||||
|
// donnee source, sans rapport avec le code de dessin.
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x08, 0x00, 0x80, 0x00, 0x00, 0x18, 0x00, 0x80, 0x00,
|
||||||
|
0x00, 0x1C, 0x00, 0x80, 0x00, 0x00, 0x34, 0x00, 0x80, 0x00, 0x00, 0x36, 0x00, 0x80, 0x00, 0x00,
|
||||||
|
0x62, 0x00, 0x80, 0x00, 0x00, 0x63, 0x00, 0x80, 0x00, 0x00, 0xC1, 0x00, 0x80, 0x00, 0x80, 0xC1,
|
||||||
|
0x00, 0x80, 0x00, 0x80, 0x80, 0x01, 0x80, 0x00, 0xC0, 0x80, 0x01, 0x80, 0x00, 0x40, 0x1C, 0x03,
|
||||||
|
0x80, 0x00, 0x60, 0x1C, 0x03, 0x80, 0x00, 0x20, 0x1C, 0x06, 0x80, 0x00, 0x30, 0x1C, 0x06, 0x80,
|
||||||
|
0x00, 0x10, 0x1C, 0x0C, 0x80, 0x00, 0x18, 0x0C, 0x0C, 0x80, 0x00, 0x08, 0x0E, 0x18, 0x80, 0x00,
|
||||||
|
0x0C, 0x0E, 0x18, 0x80, 0x00, 0x04, 0x0E, 0x30, 0x80, 0x00, 0x06, 0x8E, 0x30, 0x80, 0x00, 0x02,
|
||||||
|
0xFE, 0x60, 0x80, 0x00, 0x03, 0x7E, 0x60, 0x80, 0x00, 0x01, 0x7E, 0xC0, 0x80, 0x80, 0x01, 0x62,
|
||||||
|
0xC0, 0x80, 0x80, 0x01, 0x60, 0x80, 0x81, 0xC0, 0x00, 0x30, 0x80, 0x81, 0xC0, 0x00, 0x30, 0x00,
|
||||||
|
0x83, 0x60, 0x00, 0x30, 0x00, 0x83, 0x60, 0x00, 0x30, 0x00, 0x86, 0x30, 0x00, 0x38, 0x00, 0x86,
|
||||||
|
0x30, 0x00, 0x3C, 0x00, 0x8C, 0x18, 0x00, 0x38, 0x00, 0x8C, 0x18, 0x00, 0x18, 0x00, 0x98, 0x0C,
|
||||||
|
0x00, 0x08, 0x00, 0x98, 0x04, 0x00, 0x00, 0x00, 0xB0, 0xFE, 0xFF, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xBF, 0xFD, 0xFF, 0xFF, 0xFF, 0xBF,
|
||||||
|
};
|
||||||
@ -13,6 +13,9 @@ namespace {
|
|||||||
|
|
||||||
WebServer server(80);
|
WebServer server(80);
|
||||||
|
|
||||||
|
uint32_t g_lastActivityMs = 0;
|
||||||
|
void markActivity() { g_lastActivityMs = millis(); }
|
||||||
|
|
||||||
const char INDEX_HTML[] PROGMEM = R"html(<!DOCTYPE html>
|
const char INDEX_HTML[] PROGMEM = R"html(<!DOCTYPE html>
|
||||||
<html><head><meta charset="utf-8"><title>AlimHT</title>
|
<html><head><meta charset="utf-8"><title>AlimHT</title>
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
@ -121,9 +124,13 @@ refresh();
|
|||||||
</body></html>
|
</body></html>
|
||||||
)html";
|
)html";
|
||||||
|
|
||||||
void handleRoot() { server.send_P(200, "text/html", INDEX_HTML); }
|
void handleRoot() {
|
||||||
|
markActivity();
|
||||||
|
server.send_P(200, "text/html", INDEX_HTML);
|
||||||
|
}
|
||||||
|
|
||||||
void handleState() {
|
void handleState() {
|
||||||
|
markActivity();
|
||||||
const Telemetry &t = TmsLink::telemetry();
|
const Telemetry &t = TmsLink::telemetry();
|
||||||
const CommandState &cmd = TmsLink::command();
|
const CommandState &cmd = TmsLink::command();
|
||||||
char buf[400];
|
char buf[400];
|
||||||
@ -139,6 +146,7 @@ void handleState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleCommand() {
|
void handleCommand() {
|
||||||
|
markActivity();
|
||||||
CommandState cmd;
|
CommandState cmd;
|
||||||
cmd.ht = server.arg("ht") == "1";
|
cmd.ht = server.arg("ht") == "1";
|
||||||
cmd.pwm1 = server.arg("pwm1") == "1";
|
cmd.pwm1 = server.arg("pwm1") == "1";
|
||||||
@ -164,4 +172,6 @@ void begin() {
|
|||||||
|
|
||||||
void poll() { server.handleClient(); }
|
void poll() { server.handleClient(); }
|
||||||
|
|
||||||
|
uint32_t lastActivityMs() { return g_lastActivityMs; }
|
||||||
|
|
||||||
} // namespace WebUi
|
} // namespace WebUi
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
// Serveur web de l'IHM : l'ESP32 cree son propre point d'acces WiFi
|
// Serveur web de l'IHM : l'ESP32 cree son propre point d'acces WiFi
|
||||||
// (voir config.h) et sert un dashboard + controles HT/PWM1/PWM2.
|
// (voir config.h) et sert un dashboard + controles HT/PWM1/PWM2.
|
||||||
|
|
||||||
@ -8,4 +10,10 @@ namespace WebUi {
|
|||||||
void begin();
|
void begin();
|
||||||
void poll();
|
void poll();
|
||||||
|
|
||||||
|
// millis() de la derniere requete HTTP servie (page, /api/state ou
|
||||||
|
// /api/command) -- permet a l'IHM OLED de savoir si le dashboard web
|
||||||
|
// est actuellement consulte (ex. pour reactiver l'ecran OLED depuis
|
||||||
|
// l'economiseur).
|
||||||
|
uint32_t lastActivityMs();
|
||||||
|
|
||||||
} // namespace WebUi
|
} // namespace WebUi
|
||||||
|
|||||||
Reference in New Issue
Block a user