diff options
| author | Your Name <you@example.com> | 2026-05-18 18:34:33 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-18 18:34:33 +0530 |
| commit | 067a5700e26518d9a3f8bd92966c8957d17f0817 (patch) | |
| tree | 1379c544731f0edd9c52016c117221085713887d /main | |
| parent | 8f00db9d57e9e06df7fbf3e7285ae9256d21d716 (diff) | |
Document QSPI protocol findings and display fix plan
- DISPLAY_FIX_PLAN.md: root cause analysis, byte-order mismatch,
PSRAM cache coherency issue, reference implementations studied
- axs15231b.c: QSPI protocol rewrite with correct ArduinoGFX framing
(cmd=0x02 for regs, cmd=0x32/addr=0x003C00 for pixels)
- display.c: portrait centering for 320x480, render-on-change logic
- Makefile: Board C support (flash-c, lock-c)
- axs15231b.h: QSPI command/address constants
Display shows recognizable text, colors wrong due to byte-swap
Diffstat (limited to 'main')
| -rw-r--r-- | main/display.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/main/display.c b/main/display.c index 2b6cc88..1085d4a 100644 --- a/main/display.c +++ b/main/display.c | |||
| @@ -21,6 +21,9 @@ static uint64_t s_wallet_balance = 0; | |||
| 21 | static bool s_initialized = false; | 21 | static bool s_initialized = false; |
| 22 | static int64_t s_last_qr_switch = 0; | 22 | static int64_t s_last_qr_switch = 0; |
| 23 | static display_qr_mode_t s_qr_mode = DISPLAY_QR_WIFI; | 23 | static display_qr_mode_t s_qr_mode = DISPLAY_QR_WIFI; |
| 24 | static display_state_t s_rendered_state = DISPLAY_BOOT; | ||
| 25 | static display_qr_mode_t s_rendered_qr_mode = DISPLAY_QR_WIFI; | ||
| 26 | static bool s_force_render = true; | ||
| 24 | 27 | ||
| 25 | static int qr_version_from_strlen(int len) { | 28 | static int qr_version_from_strlen(int len) { |
| 26 | if (len <= 17) return 1; | 29 | if (len <= 17) return 1; |
| @@ -145,8 +148,8 @@ void display_render_qr(const char *text) { | |||
| 145 | 148 | ||
| 146 | static void render_boot_screen(void) { | 149 | static void render_boot_screen(void) { |
| 147 | axs15231b_fill_screen(0x0000); | 150 | axs15231b_fill_screen(0x0000); |
| 148 | display_render_text(140, 100, "TollGate", 0xF79F, 0x0000, 3); | 151 | display_render_text(64, 210, "TollGate", 0xF79F, 0x0000, 3); |
| 149 | display_render_text(140, 140, "starting...", 0xB5B6, 0x0000, 2); | 152 | display_render_text(72, 250, "starting...", 0xB5B6, 0x0000, 2); |
| 150 | axs15231b_flush(); | 153 | axs15231b_flush(); |
| 151 | } | 154 | } |
| 152 | 155 | ||
| @@ -182,24 +185,33 @@ static void render_ready_screen(void) { | |||
| 182 | 185 | ||
| 183 | static void render_payment_screen(void) { | 186 | static void render_payment_screen(void) { |
| 184 | axs15231b_fill_screen(0x07E0); | 187 | axs15231b_fill_screen(0x07E0); |
| 185 | display_render_text(140, 100, "Paid!", 0x0000, 0x07E0, 3); | 188 | display_render_text(100, 220, "Paid!", 0x0000, 0x07E0, 3); |
| 186 | display_render_text(130, 140, "Access granted", 0x0000, 0x07E0, 2); | 189 | display_render_text(48, 260, "Access granted", 0x0000, 0x07E0, 2); |
| 187 | axs15231b_flush(); | 190 | axs15231b_flush(); |
| 188 | } | 191 | } |
| 189 | 192 | ||
| 190 | static void render_error_screen(void) { | 193 | static void render_error_screen(void) { |
| 191 | axs15231b_fill_screen(0xF800); | 194 | axs15231b_fill_screen(0xF800); |
| 192 | display_render_text(120, 100, "No upstream", 0xFFFF, 0xF800, 3); | 195 | display_render_text(28, 220, "No upstream", 0xFFFF, 0xF800, 3); |
| 193 | display_render_text(130, 140, "Check config", 0xFFFF, 0xF800, 2); | 196 | display_render_text(64, 260, "Check config", 0xFFFF, 0xF800, 2); |
| 194 | axs15231b_flush(); | 197 | axs15231b_flush(); |
| 195 | } | 198 | } |
| 196 | 199 | ||
| 197 | static void display_task(void *pvParameters) { | 200 | static void display_task(void *pvParameters) { |
| 198 | ESP_LOGI(TAG, "Display task started"); | 201 | ESP_LOGI(TAG, "Display task started"); |
| 202 | vTaskDelay(pdMS_TO_TICKS(500)); | ||
| 199 | 203 | ||
| 200 | while (1) { | 204 | while (1) { |
| 201 | display_state_t state = s_state; | 205 | display_state_t state = s_state; |
| 202 | 206 | ||
| 207 | if (state == DISPLAY_READY) { | ||
| 208 | int64_t now = (int64_t)xTaskGetTickCount() * portTICK_PERIOD_MS; | ||
| 209 | if ((now - s_last_qr_switch) >= QR_CYCLE_MS) { | ||
| 210 | s_qr_mode = (s_qr_mode == DISPLAY_QR_WIFI) ? DISPLAY_QR_PORTAL : DISPLAY_QR_WIFI; | ||
| 211 | s_last_qr_switch = now; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 203 | switch (state) { | 215 | switch (state) { |
| 204 | case DISPLAY_BOOT: | 216 | case DISPLAY_BOOT: |
| 205 | render_boot_screen(); | 217 | render_boot_screen(); |
| @@ -217,12 +229,6 @@ static void display_task(void *pvParameters) { | |||
| 217 | break; | 229 | break; |
| 218 | } | 230 | } |
| 219 | 231 | ||
| 220 | int64_t now = (int64_t)xTaskGetTickCount() * portTICK_PERIOD_MS; | ||
| 221 | if (state == DISPLAY_READY && (now - s_last_qr_switch) >= QR_CYCLE_MS) { | ||
| 222 | s_qr_mode = (s_qr_mode == DISPLAY_QR_WIFI) ? DISPLAY_QR_PORTAL : DISPLAY_QR_WIFI; | ||
| 223 | s_last_qr_switch = now; | ||
| 224 | } | ||
| 225 | |||
| 226 | vTaskDelay(pdMS_TO_TICKS(1000)); | 232 | vTaskDelay(pdMS_TO_TICKS(1000)); |
| 227 | } | 233 | } |
| 228 | } | 234 | } |
| @@ -247,6 +253,7 @@ esp_err_t display_init(void) { | |||
| 247 | 253 | ||
| 248 | void display_set_state(display_state_t state) { | 254 | void display_set_state(display_state_t state) { |
| 249 | s_state = state; | 255 | s_state = state; |
| 256 | s_force_render = true; | ||
| 250 | } | 257 | } |
| 251 | 258 | ||
| 252 | void display_update(const char *ap_ssid, int active_clients, | 259 | void display_update(const char *ap_ssid, int active_clients, |