diff options
| author | Your Name <you@example.com> | 2026-05-18 19:13:23 +0530 |
|---|---|---|
| committer | Your Name <you@example.com> | 2026-05-18 19:13:23 +0530 |
| commit | f0f8cca10196b265c3b453f71322239d2ecaf4ae (patch) | |
| tree | 654131659e02068a10eb2f58f7b99d0f06c298ea | |
| parent | a02a0dbbf4e945ad00433e3fc9fd2b40550d3e82 (diff) | |
Fix display: add RAMWR before pixel data, correct colors, smaller text
Root cause: missing RAMWR (0x2C) command before pixel data transfer.
Without RAMWR, the display didn't know to write data into the RAM window
set by CASET/RASET, causing wrapping and double-vision artifacts.
- Add qspi_write_command(RAMWR) before pixel data in flush()
- Use internal DMA byte-swap buffer (MALLOC_CAP_DMA) for correct colors
- Reduce font scale: TollGate scale 2, starting... scale 1
- Centered text positions for 320x480 portrait
Display now shows: blue TollGate + yellow starting... on black
| -rw-r--r-- | components/axs15231b/axs15231b.c | 1 | ||||
| -rw-r--r-- | main/display.c | 55 |
2 files changed, 23 insertions, 33 deletions
diff --git a/components/axs15231b/axs15231b.c b/components/axs15231b/axs15231b.c index 49122a1..7424a20 100644 --- a/components/axs15231b/axs15231b.c +++ b/components/axs15231b/axs15231b.c | |||
| @@ -316,6 +316,7 @@ void axs15231b_flush(void) { | |||
| 316 | 316 | ||
| 317 | qspi_write_cmd_d16d16(CASET, 0, s_width - 1); | 317 | qspi_write_cmd_d16d16(CASET, 0, s_width - 1); |
| 318 | qspi_write_cmd_d16d16(RASET, 0, s_height - 1); | 318 | qspi_write_cmd_d16d16(RASET, 0, s_height - 1); |
| 319 | qspi_write_command(RAMWR); | ||
| 319 | 320 | ||
| 320 | int total_pixels = s_width * s_height; | 321 | int total_pixels = s_width * s_height; |
| 321 | int pixel_offset = 0; | 322 | int pixel_offset = 0; |
diff --git a/main/display.c b/main/display.c index 26d0c5f..0b641ea 100644 --- a/main/display.c +++ b/main/display.c | |||
| @@ -148,8 +148,8 @@ void display_render_qr(const char *text) { | |||
| 148 | 148 | ||
| 149 | static void render_boot_screen(void) { | 149 | static void render_boot_screen(void) { |
| 150 | axs15231b_fill_screen(0x0000); | 150 | axs15231b_fill_screen(0x0000); |
| 151 | display_render_text(64, 210, "TollGate", 0x07FF, 0x0000, 3); | 151 | display_render_text(96, 220, "TollGate", 0x07FF, 0x0000, 2); |
| 152 | display_render_text(72, 250, "starting...", 0xFFE0, 0x0000, 2); | 152 | display_render_text(116, 245, "starting...", 0xFFE0, 0x0000, 1); |
| 153 | axs15231b_flush(); | 153 | axs15231b_flush(); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| @@ -185,15 +185,15 @@ static void render_ready_screen(void) { | |||
| 185 | 185 | ||
| 186 | static void render_payment_screen(void) { | 186 | static void render_payment_screen(void) { |
| 187 | axs15231b_fill_screen(0x07E0); | 187 | axs15231b_fill_screen(0x07E0); |
| 188 | display_render_text(100, 220, "Paid!", 0x0000, 0x07E0, 3); | 188 | display_render_text(128, 225, "Paid!", 0x0000, 0x07E0, 2); |
| 189 | display_render_text(48, 260, "Access granted", 0x0000, 0x07E0, 2); | 189 | display_render_text(104, 245, "Access granted", 0x0000, 0x07E0, 1); |
| 190 | axs15231b_flush(); | 190 | axs15231b_flush(); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static void render_error_screen(void) { | 193 | static void render_error_screen(void) { |
| 194 | axs15231b_fill_screen(0xF800); | 194 | axs15231b_fill_screen(0xF800); |
| 195 | display_render_text(28, 220, "No upstream", 0xFFFF, 0xF800, 3); | 195 | display_render_text(104, 225, "No upstream", 0xFFFF, 0xF800, 2); |
| 196 | display_render_text(64, 260, "Check config", 0xFFFF, 0xF800, 2); | 196 | display_render_text(120, 245, "Check config", 0xFFFF, 0xF800, 1); |
| 197 | axs15231b_flush(); | 197 | axs15231b_flush(); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| @@ -203,43 +203,32 @@ static void display_task(void *pvParameters) { | |||
| 203 | while (1) { | 203 | while (1) { |
| 204 | display_state_t state = s_state; | 204 | display_state_t state = s_state; |
| 205 | 205 | ||
| 206 | bool qr_changed = false; | ||
| 207 | if (state == DISPLAY_READY) { | 206 | if (state == DISPLAY_READY) { |
| 208 | int64_t now = (int64_t)xTaskGetTickCount() * portTICK_PERIOD_MS; | 207 | int64_t now = (int64_t)xTaskGetTickCount() * portTICK_PERIOD_MS; |
| 209 | if ((now - s_last_qr_switch) >= QR_CYCLE_MS) { | 208 | 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; | 209 | s_qr_mode = (s_qr_mode == DISPLAY_QR_WIFI) ? DISPLAY_QR_PORTAL : DISPLAY_QR_WIFI; |
| 211 | s_last_qr_switch = now; | 210 | s_last_qr_switch = now; |
| 212 | qr_changed = true; | ||
| 213 | } | 211 | } |
| 214 | } | 212 | } |
| 215 | 213 | ||
| 216 | if (s_force_render || state != s_rendered_state || | 214 | switch (state) { |
| 217 | (state == DISPLAY_READY && qr_changed)) { | 215 | case DISPLAY_BOOT: |
| 218 | s_force_render = false; | 216 | render_boot_screen(); |
| 219 | 217 | break; | |
| 220 | switch (state) { | 218 | case DISPLAY_READY: |
| 221 | case DISPLAY_BOOT: | 219 | render_ready_screen(); |
| 222 | render_boot_screen(); | 220 | break; |
| 223 | break; | 221 | case DISPLAY_PAYMENT_RECEIVED: |
| 224 | case DISPLAY_READY: | 222 | render_payment_screen(); |
| 225 | render_ready_screen(); | 223 | vTaskDelay(pdMS_TO_TICKS(2000)); |
| 226 | break; | 224 | s_state = DISPLAY_READY; |
| 227 | case DISPLAY_PAYMENT_RECEIVED: | 225 | break; |
| 228 | render_payment_screen(); | 226 | case DISPLAY_ERROR: |
| 229 | vTaskDelay(pdMS_TO_TICKS(2000)); | 227 | render_error_screen(); |
| 230 | s_state = DISPLAY_READY; | 228 | break; |
| 231 | s_force_render = true; | ||
| 232 | break; | ||
| 233 | case DISPLAY_ERROR: | ||
| 234 | render_error_screen(); | ||
| 235 | break; | ||
| 236 | } | ||
| 237 | |||
| 238 | s_rendered_state = state; | ||
| 239 | s_rendered_qr_mode = s_qr_mode; | ||
| 240 | } | 229 | } |
| 241 | 230 | ||
| 242 | vTaskDelay(pdMS_TO_TICKS(500)); | 231 | vTaskDelay(pdMS_TO_TICKS(1000)); |
| 243 | } | 232 | } |
| 244 | } | 233 | } |
| 245 | 234 | ||