ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
44
45#include <stddef.h>
46#include <stdint.h>
47
48#include "jof.h"
49#include "longstrip.h"
50#include "ra8_board_ek_ra8d2.h"
52#include "ra8_boot_entry.h"
53#include "ra8_cgc.h"
54#include "ra8_check.h"
55#include "ra8_display_pal.h"
56#include "ra8_display_pal_lcd.h"
57#include "ra8_err.h"
58#include "ra8_gfx.h"
59#include "ra8_gfx_font.h"
60#include "ra8_io_i2c_bus.h"
61#include "ra8_isr.h"
62#include "ra8_mstp.h"
63#include "ra8_panel.h"
64#include "ra8_panel_timing.h"
65#include "ra8_sdramc.h"
66#include "ra8_tile_cache.h"
67#include "ra8_time.h"
68#include "ra8_touch.h"
69
70/* ===========================================================================
71 * Geometry (no magic numbers)
72 * ===========================================================================
73 */
74
98
104typedef enum : uint32_t {
106 k_ls_canvas_h = (uint32_t)k_ls_bands * (uint32_t)k_ls_band_h,
107 k_ls_bpp = 3U,
109 k_ls_band_bytes = (uint32_t)k_panel_width_px * (uint32_t)k_ls_band_h * 3U,
114 ((uint32_t)k_panel_height_px * 9U) / 10U,
115} ls_size_t;
116
128typedef enum : uint32_t {
133 k_ls_atlas_total = (uint32_t)k_ls_hdr_bytes + ((uint32_t)k_ls_bands * 8U) +
134 (uint32_t)k_ls_ftr_bytes,
139} ls_atlas_t;
140
146typedef enum : uint32_t {
153} ls_paint_t;
154
160typedef enum : uint16_t {
161 k_ls_zone_top = (uint16_t)(k_panel_height_px / 3U),
162 k_ls_zone_mid = (uint16_t)((k_panel_height_px * 2U) / 3U),
163} ls_zone_t;
164
170typedef enum : uint32_t {
171 k_ls_col_bg = 0x0A0A12U,
172 k_ls_col_status_bg = 0x101826U,
173 k_ls_col_text = 0xF0F4FFU,
174 k_ls_col_text_dim = 0x8FA0C0U,
175 k_ls_col_rail_bg = 0x263042U,
177} ls_color_t;
178
184typedef enum : int32_t {
186} ls_rail_t;
187
193typedef enum : uint32_t {
194 k_ls_uart_baud = 115200U,
195 k_ls_fnv_offset = 2166136261U,
196 k_ls_fnv_prime = 16777619U,
203
212typedef enum : uint8_t {
215
216/* ===========================================================================
217 * Static storage
218 * ===========================================================================
219 */
220
222static const char* const s_tag = "ereader_longstrip";
223
229static const uint32_t k_ls_palette[k_ls_palette_size] = {
230 0xE6194BU,
231 0xF58231U,
232 0xFFE119U,
233 0xBFEF45U,
234 0x3CB44BU,
235 0x42D4F4U,
236 0x4363D8U,
237 0x911EB4U,
238 0xF032E6U,
239 0xFABEBEU,
240 0x469990U,
241 0x9A6324U,
242 0x800000U,
243 0x808000U,
244 0x000075U,
245 0xA9A9A9U,
246};
247
254[[gnu::section(".sdram_data"), gnu::aligned(k_ra8_board_fb_align_bytes)]] static uint16_t
256
258[[gnu::section(
259 ".sdram_data")]] static uint8_t s_cells[(size_t)k_ls_cells * (size_t)k_ls_band_bytes];
260
262static uint8_t s_atlas[k_ls_atlas_total];
263
267static int32_t s_buckets[(size_t)k_ls_buckets];
268
272
278typedef struct {
279 uint32_t width;
280 uint32_t canvas_h;
281 uint16_t band_h;
282 uint8_t bpp;
284
287
291 .framebuffer = s_framebuffer,
292 .framebuffer_bytes = sizeof(s_framebuffer),
293 .width_px = (uint16_t)k_ls_view_w,
294 .height_px = (uint16_t)k_ls_view_h,
295 .pixfmt = k_display_pixfmt_rgb565,
296 .panel_timing = &s_ra8_panel_ek_ra8d2_timing,
297};
298
300static display_handle_t* s_display = nullptr;
304static bool s_chrome = true;
306static uint16_t s_last_skipped = 0U;
308static bool s_was_sw1 = false;
310static bool s_was_sw2 = false;
311
313volatile uint32_t g_ls_loop_ticks = 0U;
315volatile uint32_t g_ls_scroll_y = 0U;
317volatile uint32_t g_ls_redraws = 0U;
319volatile uint32_t g_ls_frame_crc = 0U;
320
322static const uint8_t k_msg_boot[] = "ereader-longstrip: boot\r\n";
323static const uint8_t k_msg_pre[] = "ereader-longstrip: bands=";
324static const uint8_t k_msg_view[] = " view=";
325static const uint8_t k_msg_x[] = "x";
326static const uint8_t k_msg_scroll[] = " scroll=";
327static const uint8_t k_msg_crc[] = " crc=";
328static const uint8_t k_msg_eol[] = "\r\n";
329
330/* ===========================================================================
331 * Console helpers
332 * ===========================================================================
333 */
334
336static void ls_print(const uint8_t* msg, uint32_t len)
337{
338 (void)ra8_board_uart_console_write(msg, (size_t)len);
339}
340
342static void ls_print_hex(uint32_t value)
343{
344 uint8_t buf[k_ls_hex_nibbles];
345 for (uint32_t i = 0U; i < (uint32_t)k_ls_hex_nibbles; i++) {
346 const uint32_t shift = ((uint32_t)k_ls_hex_nibbles - 1U - i) * (uint32_t)k_ls_nibble_bits;
347 const uint32_t nib = (value >> shift) & (uint32_t)k_ls_nibble_mask;
348 buf[i] = (uint8_t)((nib < (uint32_t)k_ls_dec_ten) ? ('0' + nib) : ('A' + (nib - k_ls_dec_ten)));
349 }
350 ls_print(buf, (uint32_t)k_ls_hex_nibbles);
351}
352
354static void ls_print_uint(uint32_t value)
355{
356 uint8_t buf[k_ls_dec_digits];
357 uint32_t n = 0U;
358 if (value == 0U) {
359 buf[n] = '0';
360 n++;
361 }
362 while ((value > 0U) && (n < (uint32_t)k_ls_dec_digits)) {
363 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_ls_dec_ten));
364 n++;
365 value /= (uint32_t)k_ls_dec_ten;
366 }
367 for (uint32_t i = 0U; i < n; i++) {
368 ls_print(&buf[n - 1U - i], 1U);
369 }
370}
371
379static const char* ls_utoa(char* buf, uint32_t value)
380{
381 char tmp[k_ls_dec_digits];
382 uint32_t n = 0U;
383 if (value == 0U) {
384 tmp[n] = '0';
385 n++;
386 }
387 while ((value > 0U) && (n < (uint32_t)k_ls_dec_digits)) {
388 tmp[n] = (char)('0' + (value % (uint32_t)k_ls_dec_ten));
389 n++;
390 value /= (uint32_t)k_ls_dec_ten;
391 }
392 for (uint32_t i = 0U; i < n; i++) {
393 buf[i] = tmp[n - 1U - i];
394 }
395 buf[n] = '\0';
396 return buf;
397}
398
399/* ===========================================================================
400 * Boot helpers
401 * ===========================================================================
402 */
403
405static void app_panic_halt(void)
406{
408 while (1) {
409 __asm__ volatile("wfi");
410 }
411}
412
414static void app_bringup_clocks(void)
415{
416 uint32_t cpuclk0_hz = 0U;
417 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
419 }
422 }
423 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
425 }
428 }
432 }
434}
435
437static void app_bringup_panel(void)
438{
439 ra8_delay_ms((uint32_t)k_ls_settle_ms);
440 if (ra8_sdramc_init() != k_ra8_ok) {
442 }
445 }
448 }
449}
450
452static void app_bringup_gfx(void)
453{
454 if (ra8_gfx_init(s_fb.pixels, s_fb.width_px, s_fb.height_px, k_ra8_gfx_format_rgb565) !=
455 k_ra8_ok) {
457 }
458}
459
461static void app_bringup_touch(void)
462{
463 const ra8_board_touch_cfg_t cfg = {
464 .max_points = (uint8_t)k_ls_touch_max_points,
465 .irq_pin = (uint8_t)k_ra8_touch_irq_pin_unset,
466 };
467 (void)ra8_board_touch_open(&cfg);
468}
469
470/* ===========================================================================
471 * Metadata-only JOF atlas builder
472 * ===========================================================================
473 */
474
476static void ls_put_u16(uint8_t* p, uint16_t v)
477{
478 p[0] = (uint8_t)(v & (uint16_t)k_ls_byte_mask);
479 p[1] = (uint8_t)((v >> (uint16_t)k_ls_shift_8) & (uint16_t)k_ls_byte_mask);
480}
481
483static void ls_put_u32(uint8_t* p, uint32_t v)
484{
485 p[0] = (uint8_t)(v & (uint32_t)k_ls_byte_mask);
486 p[1] = (uint8_t)((v >> (uint32_t)k_ls_shift_8) & (uint32_t)k_ls_byte_mask);
487 p[2] = (uint8_t)((v >> (uint32_t)k_ls_shift_16) & (uint32_t)k_ls_byte_mask);
488 p[3] = (uint8_t)((v >> (uint32_t)k_ls_shift_24) & (uint32_t)k_ls_byte_mask);
489}
490
503static uint32_t ls_build_atlas(void)
504{
505 const uint32_t width = (uint32_t)k_ls_canvas_w;
506 const uint32_t height = (uint32_t)k_ls_canvas_h;
507 const uint32_t band_h = (uint32_t)k_ls_band_h;
508 const uint32_t bands = (uint32_t)k_ls_bands;
509 for (uint32_t i = 0U; i < (uint32_t)k_ls_hdr_bytes; i++) {
510 s_atlas[i] = 0U;
511 }
512 s_atlas[0] = 'J';
513 s_atlas[1] = 'O';
514 s_atlas[2] = 'F';
515 s_atlas[3] = '1';
516 ls_put_u16(&s_atlas[4], (uint16_t)width);
517 ls_put_u16(&s_atlas[6], (uint16_t)height);
518 ls_put_u16(&s_atlas[8], (uint16_t)width); /* tile_w == width (band column) */
519 ls_put_u16(&s_atlas[10], (uint16_t)band_h);
520 s_atlas[12] = (uint8_t)k_ls_bpp;
521 s_atlas[13] = (uint8_t)k_jof_codec_raw;
522 ls_put_u32(&s_atlas[16], bands);
523
524 const uint32_t index_off = (uint32_t)k_ls_hdr_bytes; /* no pixel region */
525 for (uint32_t n = 0U; n < bands; n++) {
526 const uint32_t y0 = n * band_h;
527 const uint32_t th = ((height - y0) < band_h) ? (height - y0) : band_h;
528 ls_put_u32(&s_atlas[index_off + (n * (uint32_t)k_ls_idx_entry)], index_off);
529 ls_put_u32(&s_atlas[index_off + (n * (uint32_t)k_ls_idx_entry) + 4U],
530 width * th * (uint32_t)k_ls_bpp);
531 }
532 const uint32_t ftr = index_off + (bands * (uint32_t)k_ls_idx_entry);
533 ls_put_u32(&s_atlas[ftr], index_off);
534 ls_put_u32(&s_atlas[ftr + 4U], bands);
535 ls_put_u32(&s_atlas[ftr + 8U], (uint32_t)k_ls_atlas_total);
536 const uint32_t mag = ftr + (uint32_t)k_ls_ftr_magic_off;
537 s_atlas[mag + 0U] = 'J';
538 s_atlas[mag + 1U] = 'O';
539 s_atlas[mag + 2U] = 'F';
540 s_atlas[mag + 3U] = 'E';
541 return (uint32_t)k_ls_atlas_total;
542}
543
544/* ===========================================================================
545 * Procedural band painter (tile-cache decode-on-miss seam)
546 * ===========================================================================
547 */
548
550static uint8_t ls_scale_u8(uint8_t v, uint32_t pct)
551{
552 return (uint8_t)(((uint32_t)v * pct) / (uint32_t)k_ls_pct_full);
553}
554
569static void ls_row_color(uint32_t base, uint32_t r, uint32_t th, uint8_t* rgb)
570{
571 if (r < (uint32_t)k_ls_seam_h) {
572 rgb[0] = (uint8_t)k_ls_seam_level;
573 rgb[1] = (uint8_t)k_ls_seam_level;
574 rgb[2] = (uint8_t)k_ls_seam_level;
575 return;
576 }
577 const uint32_t span = (th > 1U) ? (th - 1U) : 1U;
578 const uint32_t pct = (uint32_t)k_ls_grad_lo + (((uint32_t)k_ls_grad_span * r) / span);
579 rgb[0] =
580 ls_scale_u8((uint8_t)((base >> (uint32_t)k_ls_shift_16) & (uint32_t)k_ls_byte_mask), pct);
581 rgb[1] = ls_scale_u8((uint8_t)((base >> (uint32_t)k_ls_shift_8) & (uint32_t)k_ls_byte_mask), pct);
582 rgb[2] = ls_scale_u8((uint8_t)(base & (uint32_t)k_ls_byte_mask), pct);
583}
584
601/* cppcheck-suppress constParameterCallback -- bound to ra8_tile_source_t::decode; constifying ctx would break the binding. */
602static ra8_err_t ls_band_decode(void* ctx,
603 const ra8_tile_key_t* key,
604 uint8_t* cell,
605 uint32_t cell_bytes,
606 uint16_t* out_w,
607 uint16_t* out_h)
608{
609 RA8_CHECK_NULL_PTR(ctx, s_tag, "decode ctx must not be nullptr");
610 RA8_CHECK_NULL_PTR(key, s_tag, "key must not be nullptr");
611 RA8_CHECK_NULL_PTR(cell, s_tag, "cell must not be nullptr");
612 RA8_CHECK_NULL_PTR(out_w, s_tag, "out_w must not be nullptr");
613 RA8_CHECK_NULL_PTR(out_h, s_tag, "out_h must not be nullptr");
614 const ls_paint_ctx_t* pc = (const ls_paint_ctx_t*)ctx;
615 const uint32_t y0 = (uint32_t)key->tile_y * (uint32_t)pc->band_h;
616 uint32_t th = (uint32_t)pc->band_h;
617 if ((y0 + th) > pc->canvas_h) {
618 th = pc->canvas_h - y0;
619 }
620 if ((pc->width * th * (uint32_t)pc->bpp) > cell_bytes) {
622 }
623 const uint32_t base = k_ls_palette[(uint32_t)key->tile_y % (uint32_t)k_ls_palette_size];
624 uint32_t off = 0U;
625 for (uint32_t r = 0U; r < th; r++) { /* bounded by band_h */
626 uint8_t rgb[k_ls_bpp];
627 ls_row_color(base, r, th, rgb);
628 for (uint32_t x = 0U; x < pc->width; x++) { /* bounded by canvas width */
629 cell[off] = rgb[0];
630 cell[off + 1U] = rgb[1];
631 cell[off + 2U] = rgb[2];
632 off += (uint32_t)pc->bpp;
633 }
634 }
635 *out_w = (uint16_t)pc->width;
636 *out_h = (uint16_t)th;
637 return k_ra8_ok;
638}
639
640/* ===========================================================================
641 * Strip open + render
642 * ===========================================================================
643 */
644
645static ra8_err_t ls_blit(void* ctx,
646 const uint8_t* pixels,
647 uint16_t src_w,
648 uint16_t src_h,
649 uint8_t bpp,
650 int32_t dst_x,
651 int32_t dst_y);
652
654static void ls_open_strip(uint32_t total)
655{
656 s_store = (jof_memstore_t){.buf = s_atlas, .cap = (size_t)k_ls_atlas_total, .len = total};
657 s_paint = (ls_paint_ctx_t){.width = (uint32_t)k_ls_canvas_w,
658 .canvas_h = (uint32_t)k_ls_canvas_h,
659 .band_h = (uint16_t)k_ls_band_h,
660 .bpp = (uint8_t)k_ls_bpp};
661 const ra8_tile_cache_cfg_t ccfg = {.cell_mem = s_cells,
662 .cell_bytes = (uint32_t)k_ls_band_bytes,
663 .cell_count = (uint32_t)k_ls_cells,
664 .meta = s_meta,
665 .keys = s_keys,
666 .dims = s_dims,
667 .buckets = s_buckets,
668 .bucket_count = (uint32_t)k_ls_buckets,
669 .decode = ls_band_decode,
670 .decode_ctx = &s_paint};
671 if (ra8_tile_cache_init(&s_cache, &ccfg) != k_ra8_ok) {
673 }
674 const longstrip_cfg_t lcfg = {.pread = jof_memstore_pread,
675 .pread_ctx = &s_store,
676 .atlas_size = total,
677 .cache = &s_cache,
678 .image_id = (uint32_t)k_ls_image_id,
679 .viewport_w = (uint16_t)k_ls_view_w,
680 .viewport_h = (uint16_t)k_ls_view_h,
681 .blit = ls_blit,
682 .blit_ctx = nullptr};
683 if (longstrip_open(&s_strip, &lcfg) != k_ra8_ok) {
685 }
686}
687
701static ra8_err_t ls_blit(void* ctx,
702 const uint8_t* pixels,
703 uint16_t src_w,
704 uint16_t src_h,
705 uint8_t bpp,
706 int32_t dst_x,
707 int32_t dst_y)
708{
709 (void)ctx;
710 (void)bpp; /* strip is RGB888 by construction */
711 RA8_CHECK_NULL_PTR(pixels, s_tag, "blit pixels must not be nullptr");
712 return ra8_gfx_blit(pixels, src_w, src_h, k_ra8_gfx_format_rgb888, dst_x, dst_y);
713}
714
716static int32_t ls_text(int32_t x, int32_t y, const char* str, uint32_t color)
717{
718 (void)ra8_gfx_text_out(x, y, str, &ra8_gfx_font_8x16, color, (uint32_t)k_ls_col_status_bg);
719 uint32_t w = 0U;
720 uint32_t h = 0U;
721 if (ra8_gfx_text_size(str, &ra8_gfx_font_8x16, &w, &h) != k_ra8_ok) {
722 return x;
723 }
724 return x + (int32_t)w;
725}
726
728static void ls_draw_status(void)
729{
730 (void)ra8_gfx_rect(0,
731 0,
732 (int32_t)k_ls_view_w,
733 (int32_t)k_ls_status_h,
734 (uint32_t)k_ls_col_status_bg,
735 true);
736 const int32_t y = (int32_t)((k_ls_status_h - k_ls_glyph_h) / 2U);
737 const uint32_t band =
738 (s_strip.band_h > 0U) ? ((uint32_t)s_strip.scroll_y / (uint32_t)s_strip.band_h) + 1U : 1U;
739 const uint32_t pct =
740 (s_strip.max_scroll > 0)
741 ? ((uint32_t)s_strip.scroll_y * (uint32_t)k_ls_pct_full) / (uint32_t)s_strip.max_scroll
742 : 0U;
743 char num[k_ls_dec_digits + 1U];
744 int32_t x = (int32_t)k_ls_text_pad;
745 x = ls_text(x, y, "LONGSTRIP", (uint32_t)k_ls_col_text);
746 x = ls_text(x, y, " band ", (uint32_t)k_ls_col_text_dim);
747 x = ls_text(x, y, ls_utoa(num, band), (uint32_t)k_ls_col_text);
748 x = ls_text(x, y, "/", (uint32_t)k_ls_col_text_dim);
749 x = ls_text(x, y, ls_utoa(num, (uint32_t)k_ls_bands), (uint32_t)k_ls_col_text);
750 x = ls_text(x, y, " pos ", (uint32_t)k_ls_col_text_dim);
751 x = ls_text(x, y, ls_utoa(num, pct), (uint32_t)k_ls_col_text);
752 x = ls_text(x, y, "% skip ", (uint32_t)k_ls_col_text_dim);
753 (void)ls_text(x, y, ls_utoa(num, (uint32_t)s_last_skipped), (uint32_t)k_ls_col_text);
754}
755
757static void ls_draw_rail(void)
758{
759 const int32_t rx = (int32_t)k_ls_view_w - (int32_t)k_ls_rail_w;
760 (void)ra8_gfx_rect(rx,
761 0,
762 (int32_t)k_ls_rail_w,
763 (int32_t)k_ls_view_h,
764 (uint32_t)k_ls_col_rail_bg,
765 true);
766 int32_t th = (int32_t)(((uint32_t)k_ls_view_h * (uint32_t)k_ls_view_h) / (uint32_t)k_ls_canvas_h);
767 if (th < (int32_t)k_ls_rail_min_thumb) {
768 th = (int32_t)k_ls_rail_min_thumb;
769 }
770 const int32_t range = (int32_t)k_ls_view_h - th;
771 int32_t ty = 0;
772 if ((s_strip.max_scroll > 0) && (range > 0)) {
773 ty = (int32_t)(((uint32_t)s_strip.scroll_y * (uint32_t)range) / (uint32_t)s_strip.max_scroll);
774 }
775 (void)ra8_gfx_rect(rx, ty, (int32_t)k_ls_rail_w, th, (uint32_t)k_ls_col_rail_thumb, true);
776}
777
779static void ls_redraw(void)
780{
781 (void)ra8_gfx_reset_clip();
782 (void)ra8_gfx_clear((uint32_t)k_ls_col_bg);
784 (void)longstrip_render(&s_strip, &st);
786 if (s_chrome) {
787 ls_draw_rail();
789 }
790 g_ls_scroll_y = (uint32_t)s_strip.scroll_y;
791 g_ls_redraws++;
792}
793
799
801static uint32_t ls_hash_fb(void)
802{
803 const uint8_t* p = (const uint8_t*)s_framebuffer;
804 const size_t n = sizeof(s_framebuffer);
805 uint32_t hsh = (uint32_t)k_ls_fnv_offset;
806 for (size_t i = 0U; i < n; i++) {
807 hsh = (hsh ^ (uint32_t)p[i]) * (uint32_t)k_ls_fnv_prime;
808 }
809 return hsh;
810}
811
813static void ls_emit_banner(void)
814{
816 ls_print(k_msg_pre, (uint32_t)sizeof(k_msg_pre) - 1U);
817 ls_print_uint((uint32_t)k_ls_bands);
818 ls_print(k_msg_view, (uint32_t)sizeof(k_msg_view) - 1U);
819 ls_print_uint((uint32_t)k_ls_view_w);
820 ls_print(k_msg_x, (uint32_t)sizeof(k_msg_x) - 1U);
821 ls_print_uint((uint32_t)k_ls_view_h);
822 ls_print(k_msg_scroll, (uint32_t)sizeof(k_msg_scroll) - 1U);
823 ls_print_uint((uint32_t)s_strip.scroll_y);
824 ls_print(k_msg_crc, (uint32_t)sizeof(k_msg_crc) - 1U);
826 ls_print(k_msg_eol, (uint32_t)sizeof(k_msg_eol) - 1U);
827}
828
829/* ===========================================================================
830 * Input handling (tap zones + buttons)
831 * ===========================================================================
832 */
833
841static void ls_apply_nav(int32_t delta, bool toggle)
842{
843 if (toggle) {
845 } else {
846 const int32_t before = s_strip.scroll_y;
847 (void)longstrip_scroll_by(&s_strip, delta);
848 if ((s_strip.scroll_y == before) && (delta != 0)) {
849 return; /* already pinned at an end -- nothing to repaint */
850 }
851 }
852 ls_redraw();
853 ls_present();
854}
855
862static void ls_handle_tap(int32_t y)
863{
864 if (y < (int32_t)k_ls_zone_top) {
865 ls_apply_nav(-(int32_t)k_ls_scroll_page, false);
866 } else if (y < (int32_t)k_ls_zone_mid) {
867 ls_apply_nav(0, true);
868 } else {
869 ls_apply_nav((int32_t)k_ls_scroll_page, false);
870 }
871}
872
886static void ls_poll_touch(void)
887{
888 ra8_touch_point_t pt = {};
889 uint8_t got = 0U;
890 if (ra8_touch_read(&pt, (uint8_t)k_ls_touch_max_points, &got) != k_ra8_ok) {
891 return;
892 }
893 if (got > 0U) {
894 ls_handle_tap((int32_t)pt.y);
895 }
896}
897
899static void ls_poll_buttons(void)
900{
901 ra8_board_sw_state_t s1 = {};
902 ra8_board_sw_state_t s2 = {};
903 const bool d1 =
905 const bool d2 =
907 if (d1 && !s_was_sw1) {
908 ls_apply_nav((int32_t)k_ls_scroll_page, false);
909 }
910 if (d2 && !s_was_sw2) {
911 ls_apply_nav(-(int32_t)k_ls_scroll_page, false);
912 }
913 s_was_sw1 = d1;
914 s_was_sw2 = d2;
915}
916
917/* ===========================================================================
918 * Boot + main
919 * ===========================================================================
920 */
921
930void main(void)
931{
933 ls_print(k_msg_boot, (uint32_t)sizeof(k_msg_boot) - 1U);
939
940 const uint32_t total = ls_build_atlas();
941 ls_open_strip(total);
942
943 ls_redraw();
944 ls_present();
946
947 while (1) {
950 if ((g_ls_loop_ticks % (uint32_t)k_ls_led_every) == 0U) {
952 }
954 ra8_delay_ms((uint32_t)k_ls_frame_ms);
955 }
956}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static const uint8_t k_msg_pre[]
Definition main.c:151
static const uint8_t k_msg_crc[]
Definition main.c:152
static const uint8_t k_msg_boot[]
Definition main.c:140
static display_handle_t * s_display
Definition main.c:78
static uint16_t s_framebuffer[(size_t) k_panel_height_px *(size_t) k_panel_width_px]
1024x600 RGB565 framebuffer in external SDRAM (GLCDC scans this).
Definition main.c:67
static display_fb_t s_fb
Definition main.c:203
static const uint8_t k_msg_x[]
Definition main.c:85
static void ls_poll_buttons(void)
Poll SW1/SW2 and page up/down on a fresh press (button fallback).
Definition main.c:899
static void app_bringup_touch(void)
Open the GT911 touch controller (best-effort, polled; non-fatal).
Definition main.c:461
volatile uint32_t g_ls_scroll_y
Current scroll position (px) mirrored for --dump-sym telemetry.
Definition main.c:315
static const uint8_t k_msg_scroll[]
Definition main.c:326
static int32_t ls_text(int32_t x, int32_t y, const char *str, uint32_t color)
Draw a text run in the bundled font; return the next x column.
Definition main.c:716
static uint8_t s_cells[(size_t) k_ls_cells *(size_t) k_ls_band_bytes]
Tile-cache cell storage in SDRAM (one decoded band per cell).
Definition main.c:259
static void app_bringup_clocks(void)
Bring up clocks, MSTP, SysTick, the SCI8 console and both LEDs.
Definition main.c:414
static ls_paint_ctx_t s_paint
Painter context bound as the tile cache's decode ctx.
Definition main.c:286
static ra8_err_t ls_blit(void *ctx, const uint8_t *pixels, uint16_t src_w, uint16_t src_h, uint8_t bpp, int32_t dst_x, int32_t dst_y)
Longstrip blit sink -> ra8_gfx software blit (RGB888 -> RGB565).
Definition main.c:701
static void app_bringup_panel(void)
Bring up external SDRAM + the GLCDC panel, then cache the FB.
Definition main.c:437
static void ls_draw_status(void)
Draw the status bar overlay: wordmark + band + scroll-position text.
Definition main.c:728
static void app_panic_halt(void)
Halt forever with the red board LED on (visual sign of fatal init).
Definition main.c:405
static void ls_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:336
static const uint8_t k_msg_eol[]
Definition main.c:328
static uint32_t ls_hash_fb(void)
Fold an FNV-1a-32 over the whole panel framebuffer.
Definition main.c:801
ls_rail_t
Scroll-rail thumb geometry, pixels.
Definition main.c:184
@ k_ls_rail_min_thumb
Minimum thumb height so it stays grabbable.
Definition main.c:185
static void ls_apply_nav(int32_t delta, bool toggle)
Apply one navigation action, redrawing + presenting if state changed.
Definition main.c:841
ls_touch_cfg_t
GT911 touch-controller wiring (IIC_B channel 0, polled).
Definition main.c:212
@ k_ls_touch_max_points
One contact = one tap.
Definition main.c:213
static bool s_chrome
True while the status bar + scroll rail chrome is shown.
Definition main.c:304
ls_zone_t
Vertical tap-zone thresholds (thirds of the panel), pixels.
Definition main.c:160
@ k_ls_zone_top
y < this: up.
Definition main.c:161
@ k_ls_zone_mid
< this: chrome.
Definition main.c:162
static const char * ls_utoa(char *buf, uint32_t value)
Format an unsigned integer as a NUL-terminated ASCII decimal string.
Definition main.c:379
ls_color_t
Chrome palette, 0x00RRGGBB.
Definition main.c:170
@ k_ls_col_status_bg
Status-bar fill.
Definition main.c:172
@ k_ls_col_text
Status-bar primary text.
Definition main.c:173
@ k_ls_col_rail_thumb
Scroll-rail thumb (amber).
Definition main.c:176
@ k_ls_col_rail_bg
Scroll-rail track.
Definition main.c:175
@ k_ls_col_bg
Content backdrop (behind bands).
Definition main.c:171
@ k_ls_col_text_dim
Status-bar secondary text.
Definition main.c:174
static void ls_print_hex(uint32_t value)
Print a 32-bit value as 8 upper-case hex digits.
Definition main.c:342
static const uint8_t k_msg_view[]
Definition main.c:324
ls_paint_t
Procedural band-painter constants.
Definition main.c:146
@ k_ls_seam_level
Seam-stripe grey level (near white).
Definition main.c:151
@ k_ls_grad_span
Top->bottom brightness gain (percent).
Definition main.c:148
@ k_ls_seam_h
White seam-stripe rows at each band top.
Definition main.c:150
@ k_ls_grad_lo
Band-top brightness (percent of the hue).
Definition main.c:147
@ k_ls_pct_full
Percentage denominator.
Definition main.c:149
@ k_ls_palette_size
Entries in the vivid band palette.
Definition main.c:152
static void ls_print_uint(uint32_t value)
Print a small unsigned integer in decimal on the console.
Definition main.c:354
static void ls_put_u16(uint8_t *p, uint16_t v)
Write a little-endian u16 at p.
Definition main.c:476
static void ls_redraw(void)
Repaint the whole panel: strip bands, then the chrome overlays.
Definition main.c:779
static bool s_was_sw1
Edge-detect: was SW1 held on the previous button poll.
Definition main.c:308
static const uint32_t k_ls_palette[k_ls_palette_size]
Vivid 16-hue band palette (0x00RRGGBB) – distinct so scroll is obvious.
Definition main.c:229
static uint16_t s_last_skipped
Skipped-band count from the last render (must stay 0: #289 contract).
Definition main.c:306
volatile uint32_t g_ls_frame_crc
FNV-1a-32 over the panel FB at the boot banner (render fingerprint).
Definition main.c:319
static ra8_tile_key_t s_keys[(size_t) k_ls_cells]
Cache key storage.
Definition main.c:264
static longstrip_t s_strip
Opened longstrip scroll state.
Definition main.c:271
static uint8_t ls_scale_u8(uint8_t v, uint32_t pct)
Scale an 8-bit channel by a 0..100 percentage (saturating at 255).
Definition main.c:550
static const display_cfg_t k_ls_display_cfg
Display-PAL config: LCD/GLCDC backend over the SDRAM framebuffer.
Definition main.c:289
static void ls_draw_rail(void)
Draw the right-edge scroll rail overlay (track + proportional thumb).
Definition main.c:757
static bool s_was_sw2
Edge-detect: was SW2 held on the previous button poll.
Definition main.c:310
volatile uint32_t g_ls_loop_ticks
Free-running main-loop counter – HIL/liveness probe symbol.
Definition main.c:313
static ra8_err_t ls_band_decode(void *ctx, const ra8_tile_key_t *key, uint8_t *cell, uint32_t cell_bytes, uint16_t *out_w, uint16_t *out_h)
Tile-cache decode-on-miss: paint band key->tile_y procedurally.
Definition main.c:602
static void ls_row_color(uint32_t base, uint32_t r, uint32_t th, uint8_t *rgb)
Compute the RGB888 colour of one strip row inside a band.
Definition main.c:569
static uint8_t s_atlas[k_ls_atlas_total]
Metadata-only JOF atlas backing (header + index + footer).
Definition main.c:262
static void app_bringup_gfx(void)
Bind ra8_gfx to the panel framebuffer.
Definition main.c:452
static void ls_present(void)
Present the framebuffer to the panel (clean full refresh).
Definition main.c:795
static void ls_put_u32(uint8_t *p, uint32_t v)
Write a little-endian u32 at p.
Definition main.c:483
static uint32_t ls_build_atlas(void)
Build the metadata-only JOF band-tile atlas; return its byte length.
Definition main.c:503
static void ls_poll_touch(void)
Poll the touch controller; dispatch one tap per delivered GT911 frame.
Definition main.c:886
static int32_t s_buckets[(size_t) k_ls_buckets]
Cache hash buckets.
Definition main.c:267
ls_size_t
32-bit strip + cache + scroll magnitudes.
Definition main.c:104
@ k_ls_canvas_h
4480 px.
Definition main.c:106
@ k_ls_buckets
Tile-cache hash buckets.
Definition main.c:111
@ k_ls_band_bytes
One band payload, bytes.
Definition main.c:109
@ k_ls_bpp
RGB888 strip pixels.
Definition main.c:107
@ k_ls_scroll_page
Page-scroll step (~90% of a viewport), pixels.
Definition main.c:113
@ k_ls_cells
Tile-cache cells (< 16 bands -> LRU eviction).
Definition main.c:110
@ k_ls_canvas_w
Strip width, pixels.
Definition main.c:105
@ k_ls_image_id
Tile-cache key namespace for this strip.
Definition main.c:112
static jof_memstore_t s_store
Atlas backing-read seam.
Definition main.c:269
static ra8_tile_cache_t s_cache
Band cache (procedural decode).
Definition main.c:270
ls_atlas_t
JOF metadata-only atlas layout (procedural bands -> no pixel region).
Definition main.c:128
@ k_ls_shift_24
Three-byte shift.
Definition main.c:138
@ k_ls_ftr_magic_off
Footer "JOFE" magic offset.
Definition main.c:132
@ k_ls_hdr_bytes
JOF header length.
Definition main.c:129
@ k_ls_shift_16
Two-byte shift.
Definition main.c:137
@ k_ls_idx_entry
Index-entry length (offset + len).
Definition main.c:131
@ k_ls_shift_8
One-byte shift.
Definition main.c:136
@ k_ls_ftr_bytes
JOF footer length.
Definition main.c:130
@ k_ls_atlas_total
176-byte atlas length.
Definition main.c:133
@ k_ls_byte_mask
Low-byte mask.
Definition main.c:135
static ra8_keycache_cell_t s_meta[(size_t) k_ls_cells]
Cache link metadata.
Definition main.c:266
volatile uint32_t g_ls_redraws
Count of full redraws since boot – render-progress telemetry.
Definition main.c:317
static void ls_open_strip(uint32_t total)
Wire the memstore/painter/cache and open the strip; halt on failure.
Definition main.c:654
static void ls_emit_banner(void)
Emit the deterministic boot banner (bands, viewport, scroll, FB CRC).
Definition main.c:813
static ra8_tile_dims_t s_dims[(size_t) k_ls_cells]
Cache dim storage.
Definition main.c:265
ls_geom_t
Panel, chrome and strip geometry in pixels.
Definition main.c:84
@ k_ls_glyph_h
Bundled font cell height.
Definition main.c:93
@ k_ls_status_h
Status-bar overlay band height.
Definition main.c:89
@ k_ls_settle_ms
PLL / SDRAM / panel-POR settle.
Definition main.c:94
@ k_ls_view_w
Viewport / strip width (== panel).
Definition main.c:85
@ k_ls_view_h
Viewport / strip-window height.
Definition main.c:86
@ k_ls_led_every
Toggle heartbeat LED every Nth frame.
Definition main.c:96
@ k_ls_bands
Bands in the strip (16 palette hues).
Definition main.c:88
@ k_ls_band_h
One band (JOF tile) height, pixels.
Definition main.c:87
@ k_ls_text_pad
Status-bar left text inset.
Definition main.c:91
@ k_ls_glyph_w
Bundled font cell width.
Definition main.c:92
@ k_ls_rail_w
Scroll-rail overlay width, pixels.
Definition main.c:90
@ k_ls_frame_ms
Input-poll period (ms).
Definition main.c:95
static void ls_handle_tap(int32_t y)
Map a tap Y coordinate to a navigation action (tap-zone hit-test).
Definition main.c:862
ls_console_t
Console baud + FNV-1a-32 + decimal/hex print knobs.
Definition main.c:193
@ k_ls_nibble_mask
Low-nibble mask.
Definition main.c:199
@ k_ls_dec_digits
Max decimal digits (u32).
Definition main.c:201
@ k_ls_hex_nibbles
Hex digits in a 32-bit value.
Definition main.c:197
@ k_ls_nibble_bits
Bits per hex nibble.
Definition main.c:198
@ k_ls_fnv_prime
FNV-1a-32 prime.
Definition main.c:196
@ k_ls_fnv_offset
FNV-1a-32 offset basis.
Definition main.c:195
@ k_ls_uart_baud
SCI8 console baud.
Definition main.c:194
@ k_ls_dec_ten
Decimal base / hex split.
Definition main.c:200
JOF band-tile atlas: the display-native normalized image format (#231, shared with the longstrip scro...
ra8_err_t jof_memstore_pread(void *ctx, uint64_t offset, uint8_t *buf, size_t len, size_t *got)
Positioned read from a jof_memstore_t (reader seam).
Definition jof.c:177
@ k_jof_codec_raw
Tile stream is the packed pixels.
Definition jof.h:191
Continuous vertical-scroll (longstrip / manhwa) reading mode over an JOF band-tile atlas (#289).
ra8_err_t longstrip_scroll_by(longstrip_t *wt, int32_t delta)
Scroll by a signed pixel delta (a finger drag), clamping at the ends.
Definition longstrip.c:273
ra8_err_t longstrip_render(longstrip_t *wt, longstrip_render_stats_t *stats)
Composite every visible band at the current scroll position.
Definition longstrip.c:550
ra8_err_t longstrip_open(longstrip_t *wt, const longstrip_cfg_t *cfg)
Open a longstrip strip over a parsed + validated JOF atlas.
Definition longstrip.c:154
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_led_toggle(ra8_board_led_id_t led)
Toggle led's output state.
ra8_err_t ra8_board_sw_read(ra8_board_sw_id_t sw, ra8_board_sw_state_t *out_pressed)
Sample the current state of sw.
ra8_err_t ra8_board_sw_init(ra8_board_sw_id_t sw)
Configure a switch pin as an input with internal pull-up.
@ k_ra8_board_sw1
SW1, P009, IRQ13-DS (jumper E31).
@ k_ra8_board_sw2
SW2, P008, IRQ12-DS (jumper E32).
ra8_err_t ra8_board_led_init(ra8_board_led_id_t led)
Configure led as a digital output, initial level low (off).
ra8_err_t ra8_board_led_on(ra8_board_led_id_t led)
Drive led HIGH (light it).
ra8_board_sw_state_t
Logical "pressed" / "released" state.
@ k_ra8_board_sw_pressed
RA8 board sw pressed.
@ k_ra8_board_led_blue
Convenience aliases by colour.
@ k_ra8_board_led_red
RA8 board led red.
ra8_err_t ra8_board_uart_console_write(const uint8_t *data, size_t len)
Polled blocking write to the J-Link OB VCOM console.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
One-call bring-up of the EK-RA8D2 panel's GoodIX GT911 touch controller.
ra8_err_t ra8_board_touch_open(const ra8_board_touch_cfg_t *cfg)
Bring the on-board GT911 up and open the touch driver against it.
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_get_clock_hz(ra8_clock_id_t id, uint32_t *out_hz)
Query the current frequency of a clock-tree domain.
Definition ra8_cgc.c:132
@ k_ra8_clock_id_cpuclk0
Cortex-M85 CPUCLK0.
Definition ra8_cgc.h:70
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Display Platform Abstraction Layer for the RA8D2.
@ k_display_pixfmt_rgb565
16 bpp, 5/6/5 packed.
display_rect_t display_full_rect(const display_handle_t *d)
Convenience helper returning the rect covering the whole framebuffer.
ra8_err_t display_get_framebuffer(const display_handle_t *d, display_fb_t *out)
Return the framebuffer descriptor the backend is targeting.
ra8_err_t display_flush(const display_handle_t *d, display_rect_t rect, display_refresh_hint_t hint)
Commit pending framebuffer changes to the panel.
struct display_handle display_handle_t
ra8_err_t display_init(const display_cfg_t *cfg, display_handle_t **out_handle)
Initialise the display PAL and bring the selected backend up to a state where display_flush succeeds.
@ k_display_refresh_quality
Prioritise final quality.
LCD backend (ra8_glcdc) for the display PAL.
const display_backend_iface_t k_display_backend_lcd_ra8_glcdc
LCD backend vtable – pass its address through display_cfg_t.iface to drive the EK-RA8D2 panel.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Software 2D graphics primitives layered on top of a caller-ownedframebuffer (DRW / D/AVE 2D / GLCDC r...
@ k_ra8_gfx_format_rgb565
16-bit RGB565, little-endian in memory.
Definition ra8_gfx.h:40
@ k_ra8_gfx_format_rgb888
24-bit packed R,G,B bytes.
Definition ra8_gfx.h:41
ra8_err_t ra8_gfx_reset_clip(void)
Reset the clip rectangle to the whole framebuffer.
ra8_err_t ra8_gfx_blit(const void *src_buf, uint16_t src_w, uint16_t src_h, ra8_gfx_format_t src_format, int32_t dst_x, int32_t dst_y)
Copy a sub-image from src_buf into the framebuffer at (dst_x,dst_y).
ra8_err_t ra8_gfx_clear(uint32_t color)
Fill the bound framebuffer's clip region with a single colour.
ra8_err_t ra8_gfx_text_size(const char *str, const ra8_gfx_font_t *font, uint32_t *out_w, uint32_t *out_h)
Compute rendered pixel dimensions of a string.
ra8_err_t ra8_gfx_text_out(int32_t x, int32_t y, const char *str, const ra8_gfx_font_t *font, uint32_t fg_color, uint32_t bg_color)
Render a NUL-terminated ASCII string.
ra8_err_t ra8_gfx_init(void *fb, uint16_t width, uint16_t height, ra8_gfx_format_t format)
Bind ra8_gfx to a caller-owned framebuffer.
ra8_err_t ra8_gfx_rect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color, bool filled)
Draw an axis-aligned rectangle.
Bitmap font descriptor + bundled font handles for ra8_gfx.
const ra8_gfx_font_t ra8_gfx_font_8x16
Bundled 8x16 IBM PC VGA bitmap font, ASCII 0x20..0x7E.
ra8_io I2C-bus facade – one controller-transfer vtable over thechip's two I2C implementations.
NVIC + ICU IELSR allocator.
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_init(void)
Re-establish the ra8_mstp ref-count table from current hardware state.
Definition ra8_mstp.c:291
Active display-panel descriptor for the EK-RA8D2 (ER-TFT070-6).
@ k_ra8_board_fb_align_bytes
GLCDC AXI burst alignment, in bytes.
Definition ra8_panel.h:108
@ k_panel_height_px
Native height (pixels).
Definition ra8_panel.h:52
@ k_panel_width_px
Native width (pixels).
Definition ra8_panel.h:51
EK-RA8D2 panel timing as the HAL's ra8_glcdc_timing_t (ER-TFT070-6).
static const ra8_glcdc_timing_t s_ra8_panel_ek_ra8d2_timing
EK-RA8D2 ER-TFT070-6 RGB timing for ra8_glcdc_init / the LCD backend.
External SDRAM controller driver (framework).
ra8_err_t ra8_sdramc_init(void)
Initialise the external SDRAM at k_ra8_sdram_base_addr.
Definition ra8_sdramc.c:257
Fixed-RAM-budget image-tile cache with LRU eviction (Layer 3b, #147).
ra8_err_t ra8_tile_cache_init(ra8_tile_cache_t *tc, const ra8_tile_cache_cfg_t *cfg)
Initialise a tile cache over caller-supplied storage.
SysTick-based tick counter, delay and timestamp helpers.
ra8_err_t ra8_time_init(uint32_t cpu_hz)
Initialise SysTick for a 1 kHz tick interrupt.
Definition ra8_time.c:59
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
Multi-touch input driver – GoodIX GT911 backend.
ra8_err_t ra8_touch_read(ra8_touch_point_t *out_points, uint8_t max_count, uint8_t *got_count)
Drain the current touch frame.
Definition ra8_touch.c:551
@ k_ra8_touch_irq_pin_unset
Sentinel for "no IRQ pin attached".
Definition ra8_touch.h:72
Configuration descriptor passed into display_init.
Framebuffer descriptor returned by display_get_framebuffer.
Append-only memory store: the simplest atlas backing (RAM/SDRAM).
Definition jof.h:256
One-shot configuration handed to longstrip_open.
Definition longstrip.h:160
Per-frame render accounting returned by longstrip_render.
Definition longstrip.h:215
uint16_t skipped
Visible bands that failed to composite.
Definition longstrip.h:217
Opened longstrip-strip scroll state (caller-owned; treat as private).
Definition longstrip.h:185
Geometry the procedural band painter needs (tile-cache decode ctx).
Definition main.c:278
uint8_t bpp
Bytes per pixel (3 = RGB888).
Definition main.c:282
uint32_t canvas_h
Total strip height, pixels.
Definition main.c:280
uint32_t width
Strip / band width, pixels.
Definition main.c:279
uint16_t band_h
Nominal band height, pixels.
Definition main.c:281
The two touch settings that are an APPLICATION choice, not a board fact.
Per-cell link metadata (one caller-owned array entry per cell).
Caller-supplied storage + decoder for ra8_tile_cache_init.
Tile-cache state (caller-owned; treat as private).
Per-cell user descriptor: the decoded tile dimensions.
Identifies one decoded image tile.
uint16_t tile_y
Tile row index (in tile units).
One decoded touch contact.
Definition ra8_touch.h:93
uint16_t y
Panel Y coordinate.
Definition ra8_touch.h:95