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
|
||||
reference de plage de valeurs attendues : `Vin` ~400V, `Iin` ~1.2A,
|
||||
`V1`/`Vout` ~200V, `I1`/`I2` ~2.5A, `T1`/`T2` ~40°C).
|
||||
- `include/config.h` : `TMS_DUMMY_MODE` (actuellement `true`) fait
|
||||
tourner l'ESP32 sur la simulation interne au lieu de lire l'UART reel.
|
||||
**A passer a `false` une fois le firmware TMS320 pret et teste**, pour
|
||||
activer la reception reelle des trames `$T,...*XX`.
|
||||
- `include/config.h` : `TMS_DUMMY_MODE` (actuellement `false`, liaison
|
||||
reelle active) fait tourner l'ESP32 sur la simulation interne au lieu
|
||||
de lire l'UART reel quand mis a `true` (utile pour developper l'IHM
|
||||
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
|
||||
|
||||
@ -149,7 +161,7 @@ trame si ca ne correspond pas (trame corrompue).
|
||||
pas d'erreur visible — la telemetrie n'avancera simplement pas).
|
||||
- Terminer chaque trame par `\n` uniquement (le `\r` est tolere/ignore
|
||||
cote ESP32 mais pas necessaire).
|
||||
- Ne pas depasser une longueur de ligne de 160 caracteres (buffer fixe
|
||||
cote ESP32, `g_lineBuf[160]` dans `tms_link.cpp`).
|
||||
- Ne pas depasser une longueur de ligne de 200 caracteres (buffer fixe
|
||||
cote ESP32, `g_lineBuf[200]` dans `tms_link.cpp`).
|
||||
- Verifier au multimetre/oscilloscope le niveau logique du TMS320 avant
|
||||
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_DC 1
|
||||
|
||||
// Le firmware TMS320 n'est pas encore programme : on simule la telemetrie
|
||||
// en local le temps que le hardware TMS320 tourne. Passer a false quand le
|
||||
// TMS320 emet reellement des trames $T,...*XX sur l'UART.
|
||||
#define TMS_DUMMY_MODE true
|
||||
// Le firmware TMS320 emet reellement des trames $T,...*XX sur l'UART :
|
||||
// on lit/ecrit le vrai Serial1 au lieu de simuler la telemetrie en local.
|
||||
// Repasser a true pour developper l'IHM sans hardware TMS320 branche.
|
||||
#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
|
||||
// (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"
|
||||
|
||||
@ -13,3 +13,12 @@ platform = espressif32
|
||||
board = esp32-c3-devkitm-1
|
||||
framework = arduino
|
||||
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 <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 "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 {
|
||||
|
||||
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;
|
||||
|
||||
void drawLine(uint8_t y, const char *text) {
|
||||
char padded[33];
|
||||
snprintf(padded, sizeof(padded), "%-32s", text);
|
||||
er_oled_string(0, y, padded, 0);
|
||||
// Port du serveur web de l'IHM -- doit rester synchronise avec
|
||||
// `WebServer server(80)` dans web_ui.cpp (pas d'accesseur dedie pour
|
||||
// l'instant, les deux sont a changer ensemble si le port change).
|
||||
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) {
|
||||
char l0[33], l1[33], l2[33], l3[33];
|
||||
const CommandState &cmd = TmsLink::command();
|
||||
snprintf(l0, sizeof(l0), "TMS:%s HT:%s P1:%s P2:%s", linkOk ? "OK" : "KO",
|
||||
cmd.ht ? "ON" : "OFF", cmd.pwm1 ? "ON" : "OFF", cmd.pwm2 ? "ON" : "OFF");
|
||||
snprintf(l1, sizeof(l1), "Vin=%.0fV Iin=%.2fA Iout=%.2fA", t.vin, t.iin, t.iout);
|
||||
snprintf(l2, sizeof(l2), "E1 F%.0fk D%.0f%% V%.0fV I%.2fA T%.0fC", t.freq1 / 1000.0f,
|
||||
t.duty1, t.v1, t.i1, t.t1);
|
||||
snprintf(l3, sizeof(l3), "E2 F%.0fk D%.0f%% V%.0fV I%.2fA T%.0fC", t.freq2 / 1000.0f,
|
||||
t.duty2, t.vout, t.i2, t.t2);
|
||||
drawLine(0, l0);
|
||||
drawLine(16, l1);
|
||||
drawLine(32, l2);
|
||||
drawLine(48, l3);
|
||||
u8g2.clearBuffer();
|
||||
// setDrawColor(1) explicite : l'economiseur d'ecran laisse le contexte
|
||||
// u8g2 sur un niveau de gris partiel (degrade de la trainee) apres son
|
||||
// dernier appel -- sans ca, le dashboard heriterait de ce niveau au
|
||||
// lieu du blanc plein apres une sortie de veille.
|
||||
u8g2.setDrawColor(1);
|
||||
char buf[40];
|
||||
|
||||
// --- bandeau haut : HIVY (gauche) / SYS:OK (centre) / WIFI:... (droite) ---
|
||||
// SSID dynamique (config.h, maintenant "HIVY") + IP reelle (WiFi.softAPIP(),
|
||||
// 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
|
||||
|
||||
void begin() {
|
||||
er_oled_begin();
|
||||
er_oled_clear();
|
||||
// Broches SPI personnalisees (comme l'ancien driver er_oled.cpp) :
|
||||
// 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) {
|
||||
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();
|
||||
if (now - g_lastRefreshMs < REFRESH_PERIOD_MS) return;
|
||||
g_lastRefreshMs = now;
|
||||
|
||||
drawDashboard(t, linkOk);
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "protocol.h"
|
||||
|
||||
namespace OledUi {
|
||||
|
||||
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);
|
||||
|
||||
} // namespace OledUi
|
||||
|
||||
@ -14,7 +14,7 @@ CommandState g_command;
|
||||
uint32_t g_lastValidFrameMs = 0;
|
||||
uint32_t g_lastCommandSentMs = 0;
|
||||
|
||||
char g_lineBuf[160];
|
||||
char g_lineBuf[200];
|
||||
uint8_t g_lineLen = 0;
|
||||
|
||||
const uint32_t COMMAND_SEND_PERIOD_MS = 500;
|
||||
@ -75,12 +75,25 @@ bool parseTelemetryLine(char *line) {
|
||||
void pollUart() {
|
||||
while (Serial1.available()) {
|
||||
char c = (char)Serial1.read();
|
||||
|
||||
if (c == '\n') {
|
||||
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_lastValidFrameMs = g_telemetry.lastUpdateMs;
|
||||
}
|
||||
if (TMS_DEBUG_ECHO) {
|
||||
Serial.print(ok ? "TMS<< " : "TMS<< [rejete] ");
|
||||
Serial.println(display);
|
||||
}
|
||||
g_lineLen = 0;
|
||||
} else if (c != '\r') {
|
||||
if (g_lineLen < sizeof(g_lineBuf) - 1) {
|
||||
@ -136,6 +149,7 @@ void sendCommandFrame() {
|
||||
char frame[64];
|
||||
snprintf(frame, sizeof(frame), "$%s*%02X\n", body, cs);
|
||||
Serial1.print(frame);
|
||||
if (TMS_DEBUG_ECHO) Serial.printf("TMS>> %s", frame);
|
||||
}
|
||||
|
||||
} // 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);
|
||||
|
||||
uint32_t g_lastActivityMs = 0;
|
||||
void markActivity() { g_lastActivityMs = millis(); }
|
||||
|
||||
const char INDEX_HTML[] PROGMEM = R"html(<!DOCTYPE html>
|
||||
<html><head><meta charset="utf-8"><title>AlimHT</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
@ -121,9 +124,13 @@ refresh();
|
||||
</body></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() {
|
||||
markActivity();
|
||||
const Telemetry &t = TmsLink::telemetry();
|
||||
const CommandState &cmd = TmsLink::command();
|
||||
char buf[400];
|
||||
@ -139,6 +146,7 @@ void handleState() {
|
||||
}
|
||||
|
||||
void handleCommand() {
|
||||
markActivity();
|
||||
CommandState cmd;
|
||||
cmd.ht = server.arg("ht") == "1";
|
||||
cmd.pwm1 = server.arg("pwm1") == "1";
|
||||
@ -164,4 +172,6 @@ void begin() {
|
||||
|
||||
void poll() { server.handleClient(); }
|
||||
|
||||
uint32_t lastActivityMs() { return g_lastActivityMs; }
|
||||
|
||||
} // namespace WebUi
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// 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.
|
||||
|
||||
@ -8,4 +10,10 @@ namespace WebUi {
|
||||
void begin();
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user