upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorYour Name <you@example.com>2026-05-19 02:00:31 +0530
committerYour Name <you@example.com>2026-05-19 02:00:31 +0530
commit9f7dd94029c8dc12117494548f5f32221a729307 (patch)
tree0db4cf1f0e2cb5ad64cf9c7eb93085598a4722a2 /components
parent58a0b5fd115d9687a1292e5e82e6b9fa8454b930 (diff)
Fix display rotation: use stride=480 for correct framebuffer addressing
The framebuffer was using s_width as row stride, but s_width changes after rotation (320→480). This caused buffer overflows and black screen in landscape mode. Now uses fixed stride=480 with 480*480*2 allocation.
Diffstat (limited to 'components')
-rw-r--r--components/axs15231b/axs15231b.c66
1 files changed, 35 insertions, 31 deletions
diff --git a/components/axs15231b/axs15231b.c b/components/axs15231b/axs15231b.c
index 77708dd..ac05ba7 100644
--- a/components/axs15231b/axs15231b.c
+++ b/components/axs15231b/axs15231b.c
@@ -38,6 +38,7 @@ static uint16_t *s_fb = NULL;
38static int s_width = AXS15231B_WIDTH; 38static int s_width = AXS15231B_WIDTH;
39static int s_height = AXS15231B_HEIGHT; 39static int s_height = AXS15231B_HEIGHT;
40static int s_rotation = 0; 40static int s_rotation = 0;
41static int s_stride = 480;
41static uint8_t *s_swap_buf = NULL; 42static uint8_t *s_swap_buf = NULL;
42#define SWAP_BUF_PIXELS 2048 43#define SWAP_BUF_PIXELS 2048
43 44
@@ -242,7 +243,7 @@ esp_err_t axs15231b_init(void) {
242 243
243 cs_init(); 244 cs_init();
244 245
245 size_t fb_size = (size_t)s_width * s_height * 2; 246 size_t fb_size = (size_t)480 * 480 * 2;
246 s_fb = heap_caps_malloc(fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); 247 s_fb = heap_caps_malloc(fb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
247 if (!s_fb) { 248 if (!s_fb) {
248 ESP_LOGE(TAG, "Failed to allocate framebuffer (%zu bytes)", fb_size); 249 ESP_LOGE(TAG, "Failed to allocate framebuffer (%zu bytes)", fb_size);
@@ -297,9 +298,10 @@ void axs15231b_set_backlight(bool on) {
297} 298}
298 299
299void axs15231b_fill_screen(uint16_t color) { 300void axs15231b_fill_screen(uint16_t color) {
300 uint32_t pixels = (uint32_t)s_width * s_height; 301 for (int row = 0; row < s_height; row++) {
301 for (uint32_t i = 0; i < pixels; i++) { 302 for (int col = 0; col < s_width; col++) {
302 s_fb[i] = color; 303 s_fb[row * s_stride + col] = color;
304 }
303 } 305 }
304} 306}
305 307
@@ -307,7 +309,7 @@ void axs15231b_fill_rect(int x, int y, int w, int h, uint16_t color) {
307 if (x < 0 || y < 0 || x + w > s_width || y + h > s_height) return; 309 if (x < 0 || y < 0 || x + w > s_width || y + h > s_height) return;
308 for (int row = y; row < y + h; row++) { 310 for (int row = y; row < y + h; row++) {
309 for (int col = x; col < x + w; col++) { 311 for (int col = x; col < x + w; col++) {
310 s_fb[row * s_width + col] = color; 312 s_fb[row * s_stride + col] = color;
311 } 313 }
312 } 314 }
313} 315}
@@ -319,36 +321,38 @@ void axs15231b_flush(void) {
319 qspi_write_cmd_d16d16(RASET, 0, s_height - 1); 321 qspi_write_cmd_d16d16(RASET, 0, s_height - 1);
320 qspi_write_command(RAMWR); 322 qspi_write_command(RAMWR);
321 323
322 int total_pixels = s_width * s_height;
323 int pixel_offset = 0;
324 bool first = true; 324 bool first = true;
325 325
326 cs_low(); 326 cs_low();
327 while (pixel_offset < total_pixels) { 327 for (int row = 0; row < s_height; row++) {
328 int remaining = total_pixels - pixel_offset; 328 int chunk_remaining = s_width;
329 int chunk_pixels = remaining < SWAP_BUF_PIXELS ? remaining : SWAP_BUF_PIXELS; 329 int col_offset = 0;
330 int chunk_bytes = chunk_pixels * 2; 330 while (chunk_remaining > 0) {
331 331 int chunk_pixels = chunk_remaining < SWAP_BUF_PIXELS ? chunk_remaining : SWAP_BUF_PIXELS;
332 uint8_t *src = (uint8_t *)(s_fb + pixel_offset); 332 int chunk_bytes = chunk_pixels * 2;
333 for (int i = 0; i < chunk_bytes; i += 2) { 333
334 s_swap_buf[i] = src[i + 1]; 334 uint8_t *src = (uint8_t *)(s_fb + row * s_stride + col_offset);
335 s_swap_buf[i + 1] = src[i]; 335 for (int i = 0; i < chunk_bytes; i += 2) {
336 } 336 s_swap_buf[i] = src[i + 1];
337 337 s_swap_buf[i + 1] = src[i];
338 spi_transaction_ext_t t = {0}; 338 }
339 if (first) { 339
340 t.base.flags = SPI_TRANS_MODE_QIO; 340 spi_transaction_ext_t t = {0};
341 t.base.cmd = QSPI_CMD_DATA_WRITE; 341 if (first) {
342 t.base.addr = QSPI_DATA_ADDR; 342 t.base.flags = SPI_TRANS_MODE_QIO;
343 first = false; 343 t.base.cmd = QSPI_CMD_DATA_WRITE;
344 } else { 344 t.base.addr = QSPI_DATA_ADDR;
345 t.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD | 345 first = false;
346 SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY; 346 } else {
347 t.base.flags = SPI_TRANS_MODE_QIO | SPI_TRANS_VARIABLE_CMD |
348 SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_DUMMY;
349 }
350 t.base.tx_buffer = s_swap_buf;
351 t.base.length = chunk_pixels * 16;
352 spi_device_polling_transmit(s_spi, (spi_transaction_t *)&t);
353 col_offset += chunk_pixels;
354 chunk_remaining -= chunk_pixels;
347 } 355 }
348 t.base.tx_buffer = s_swap_buf;
349 t.base.length = chunk_pixels * 16;
350 spi_device_polling_transmit(s_spi, (spi_transaction_t *)&t);
351 pixel_offset += chunk_pixels;
352 } 356 }
353 cs_high(); 357 cs_high();
354} 358}