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
30#include <string.h>
31
32#include "miniz.h"
33#include "ra8_board_ek_ra8d2.h"
35#include "ra8_boot_entry.h"
36#include "ra8_cgc.h"
37#include "ra8_display_pal.h"
38#include "ra8_display_pal_lcd.h"
39#include "ra8_gfx.h"
40#include "ra8_gfx_font.h"
41#include "ra8_isr.h"
42#include "ra8_mstp.h"
43#include "ra8_panel_timing.h"
44#include "ra8_sdramc.h"
45#include "ra8_time.h"
46#include "ra8_touch.h"
47#include "ra8_wdt.h"
48#include "sh_app.h"
49
51typedef enum : uint32_t {
56 k_sh_fnv_offset = 2166136261U,
57 k_sh_fnv_prime = 16777619U,
62
65
68
71 .framebuffer = s_framebuffer,
72 .framebuffer_bytes = sizeof(s_framebuffer),
73 .width_px = (uint16_t)k_sh_fb_w,
74 .height_px = (uint16_t)k_sh_fb_h,
76 .panel_timing = &s_ra8_panel_ek_ra8d2_timing,
77};
79
80static const uint8_t k_msg_fail[] = "ereader-shelf: FAIL init\r\n";
81
83static void sh_print(const uint8_t* msg, uint32_t len)
84{
85 (void)ra8_board_uart_console_write(msg, (size_t)len);
86}
87
89static uint32_t sh_fb_hash(void)
90{
91 uint32_t h = (uint32_t)k_sh_fnv_offset;
92 const uint8_t* p = (const uint8_t*)s_framebuffer;
93 const size_t bytes = sizeof s_framebuffer;
94 for (size_t i = 0U; i < bytes; ++i) {
95 h = (h ^ p[i]) * (uint32_t)k_sh_fnv_prime;
96 }
97 return h;
98}
99
112static void sh_print_banner(const sh_comic_probe_t* cbz, const sh_comic_probe_t* cbr, bool rtl_ok)
113{
114 char b[k_sh_linebuf];
115 size_t p = 0U;
116 const char* pre = "ereader-shelf: books=";
117 for (const char* s = pre; *s != '\0'; ++s) {
118 b[p++] = *s;
119 }
120 p = sh_fmt_uint(b, p, g_sh.book_count);
121 const char* mid = " sd=";
122 for (const char* s = mid; *s != '\0'; ++s) {
123 b[p++] = *s;
124 }
125 p = sh_fmt_uint(b, p, g_sh.sd_ready ? 1U : 0U);
126 const char* fbp = " fb=";
127 for (const char* s = fbp; *s != '\0'; ++s) {
128 b[p++] = *s;
129 }
130 const uint32_t h = sh_fb_hash();
131 for (uint32_t d = 0U; d < (uint32_t)k_sh_hex_digits; ++d) {
132 const uint32_t nib =
133 (h >> (((uint32_t)k_sh_hex_digits - 1U - d) * (uint32_t)k_sh_nib_bits)) & k_sh_nib_mask;
134 b[p++] = (char)((nib < k_sh_dec_base) ? ('0' + nib) : ('A' + (nib - (uint32_t)k_sh_dec_base)));
135 }
136 sh_comic_append_banner(b, &p, cbz, cbr, rtl_ok);
137 const char* end = " ok\r\n";
138 for (const char* s = end; *s != '\0'; ++s) {
139 b[p++] = *s;
140 }
141 sh_print((const uint8_t*)b, (uint32_t)p);
142}
143
145static void sh_panic_halt(void)
146{
147 sh_print(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
148 __asm__ volatile("bkpt #0");
149 while (1) {
150 __asm__ volatile("wfi");
151 }
152}
153
158static tinfl_decompressor s_tinfl;
159
160ra8_err_t sh_inflate(const void* src, size_t src_len, void* dst, size_t dst_cap, size_t* out_len)
161{
162 tinfl_init(&s_tinfl);
163 size_t in_n = src_len;
164 size_t out_n = dst_cap;
165 const tinfl_status st = tinfl_decompress(
166 &s_tinfl,
167 (const mz_uint8*)src,
168 &in_n,
169 (mz_uint8*)dst,
170 (mz_uint8*)dst,
171 &out_n,
172 (mz_uint32)(TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF));
173 if (st != TINFL_STATUS_DONE) {
175 }
176 *out_len = out_n;
177 return k_ra8_ok;
178}
179
180uint16_t* sh_fb_pixels(void)
181{
182 return s_framebuffer;
183}
184
186static void sh_seed_baked(void)
187{
188 g_sh.book_count = 0U;
189 for (uint16_t i = 0U;
190 (i < (uint16_t)k_library_count) && (g_sh.book_count < (uint16_t)k_sh_max_books);
191 ++i) {
192 sh_entry_t* e = &g_sh.entry[g_sh.book_count];
193 e->from_sd = false;
194 e->blob = k_library[i].blob;
195 e->blob_len = k_library[i].len;
196 e->thumb = k_library[i].thumb;
197 e->thumb_w = k_library[i].thumb_w;
198 e->thumb_h = k_library[i].thumb_h;
199 (void)strncpy(e->title, k_library[i].title, sizeof e->title - 1U);
200 e->title[sizeof e->title - 1U] = '\0';
201 (void)strncpy(e->author, k_library[i].author, sizeof e->author - 1U);
202 e->author[sizeof e->author - 1U] = '\0';
203 g_sh.book_count++;
204 }
205}
206
208static int32_t sh_center_x(const char* s)
209{
210 return ((int32_t)k_sh_fb_w - ((int32_t)strlen(s) * (int32_t)k_sh_glyph_w)) / 2;
211}
212
221static void sh_loading_overlay(const char* name)
222{
223 (void)ra8_gfx_clear((uint32_t)k_sh_col_bg);
224 const int32_t my = ((int32_t)k_sh_fb_h / 2) - (int32_t)k_sh_glyph_h;
225 (void)ra8_gfx_text_out(sh_center_x("Loading from SD card..."),
226 my,
227 "Loading from SD card...",
229 (uint32_t)k_sh_col_card,
230 (uint32_t)k_sh_col_bg);
231 (void)ra8_gfx_text_out(sh_center_x(name),
232 my + (int32_t)k_sh_line_h,
233 name,
235 (uint32_t)k_sh_col_sub,
236 (uint32_t)k_sh_col_bg);
237 const display_rect_t full = {.x = 0U,
238 .y = 0U,
239 .w = (uint16_t)k_sh_fb_w,
240 .h = (uint16_t)k_sh_fb_h};
242}
243
245static bool sh_select_book(uint16_t idx)
246{
247 if (g_sh.entry[idx].from_sd) {
248 sh_loading_overlay(g_sh.entry[idx].title);
249 }
250 if (!sh_book_open(idx)) {
251 return false;
252 }
253 g_sh.selected = idx;
254 g_sh.toc_scroll = 0;
255 /* Comics open straight into the full-page image reader; text books land on
256 * the cover / title page as before. */
258 return true;
259}
260
262static int32_t sh_edge_dir(int32_t x)
263{
264 const int32_t third = (int32_t)k_sh_fb_w / (int32_t)k_sh_thirds;
265 if (x < third) {
266 return -1;
267 }
268 if (x >= ((int32_t)k_sh_fb_w - third)) {
269 return 1;
270 }
271 return 0;
272}
273
280
282static bool sh_tap_cover(int32_t x, int32_t y, bool header)
283{
284 if (header) {
285 g_sh.screen = k_sh_screen_shelf;
286 return true;
287 }
288 const sh_cover_act_t act = sh_cover_action(x, y);
289 if (act == k_sh_cover_read) {
291 return true;
292 }
293 if (act == k_sh_cover_toc) {
294 g_sh.screen = k_sh_screen_toc;
295 return true;
296 }
297 return false;
298}
299
301static bool sh_tap_toc(int32_t x, int32_t y, bool header)
302{
303 if (header) {
304 g_sh.screen = k_sh_screen_cover;
305 return true;
306 }
307 const int32_t ci = sh_toc_hit(x, y);
308 if (ci < 0) {
309 return false;
310 }
311 sh_reader_load_chapter((uint32_t)ci);
312 g_sh.screen = k_sh_screen_reader;
313 return true;
314}
315
317static bool sh_tap_reader(int32_t x, int32_t y, bool header)
318{
319 (void)y;
320 if (header) {
321 g_sh.screen = k_sh_screen_toc;
322 return true;
323 }
324 const int32_t dir = sh_edge_dir(x);
325 return (dir != 0) && sh_reader_turn(dir);
326}
327
329static bool sh_handle_tap(int32_t x, int32_t y)
330{
331 const bool header = (y < (int32_t)k_sh_bar_h);
332 switch (g_sh.screen) {
334 return sh_tap_cover(x, y, header);
335 case k_sh_screen_toc:
336 return sh_tap_toc(x, y, header);
338 return sh_tap_reader(x, y, header);
340 return sh_comic_tap(x, header);
342 default: {
343 const int32_t card = sh_shelf_hit(x, y);
344 return (card >= 0) && sh_select_book((uint16_t)card);
345 }
346 }
347}
348
357static bool sh_loupe_held(int32_t x, int32_t y, bool* out_lens_only)
358{
359 if (g_sh.loupe_active) {
360 int32_t cx = g_sh.loupe_cx;
361 int32_t cy = g_sh.loupe_cy;
362 if (sh_cover_loupe_map(x, y, &cx, &cy)) {
363 g_sh.loupe_cx = cx;
364 g_sh.loupe_cy = cy;
365 }
366 *out_lens_only = true; /* lens is a fixed window; only its contents pan */
367 return true;
368 }
369 if ((ra8_time_ms() - g_sh.touch_down_ms) < (uint32_t)k_sh_loupe_hold_ms) {
370 return false; /* not held long enough yet */
371 }
372 int32_t cx = 0;
373 int32_t cy = 0;
374 if (!sh_cover_loupe_map(g_sh.touch_down_x, g_sh.touch_down_y, &cx, &cy)) {
375 return false; /* press did not start over a magnifiable cover image */
376 }
377 g_sh.loupe_active = true;
378 g_sh.loupe_cx = cx;
379 g_sh.loupe_cy = cy;
380 return true;
381}
382
396static bool sh_cover_gesture(bool down, int32_t x, int32_t y, bool was_down, bool* out_lens_only)
397{
398 *out_lens_only = false;
399 if (down && !was_down) {
400 g_sh.touch_down_ms = ra8_time_ms();
401 g_sh.touch_down_x = x;
402 g_sh.touch_down_y = y;
403 return false; /* defer: could still become a tap or a hold */
404 }
405 if (down) {
406 return sh_loupe_held(x, y, out_lens_only);
407 }
408 if (was_down && g_sh.loupe_active) {
409 g_sh.loupe_active = false;
410 return true; /* release closes the lens */
411 }
412 if (was_down) {
413 return sh_tap_cover(g_sh.touch_down_x,
414 g_sh.touch_down_y,
415 g_sh.touch_down_y < (int32_t)k_sh_bar_h);
416 }
417 return false; /* idle: no finger down this poll or last */
418}
419
421static bool sh_handle_button(bool is_sw2)
422{
423 switch (g_sh.screen) {
425 if (g_sh.book_count == 0U) {
426 return false;
427 }
428 if (is_sw2) {
429 return sh_select_book(g_sh.selected);
430 }
431 g_sh.selected = (uint16_t)((g_sh.selected + g_sh.book_count - 1U) % g_sh.book_count);
432 return true;
434 if (is_sw2) {
436 return true;
437 }
438 g_sh.screen = k_sh_screen_shelf;
439 return true;
440 case k_sh_screen_toc:
441 sh_toc_scroll(is_sw2 ? 1 : -1);
442 return true;
444 /* SW2 = next page, SW1 = previous page (in the active reading order). */
445 return sh_comic_turn(is_sw2 ? 1 : -1);
447 default:
448 return sh_reader_turn(is_sw2 ? 1 : -1);
449 }
450}
451
453static void sh_present(void)
454{
455 switch (g_sh.screen) {
458 if (g_sh.loupe_active) {
460 }
461 break;
462 case k_sh_screen_toc:
464 break;
467 break;
470 break;
472 default:
474 break;
475 }
476 const display_rect_t full = {.x = 0U,
477 .y = 0U,
478 .w = (uint16_t)k_sh_fb_w,
479 .h = (uint16_t)k_sh_fb_h};
481 /* Flush issued: spend the panel-refresh idle window (before the next input
482 * poll) warming the adjacent chapters' first content frames so a
483 * chapter-crossing page turn finds them resident (#207). Reader screen only,
484 * so it never runs before the boot banner; best-effort and output-transparent. */
485 if (g_sh.screen == k_sh_screen_reader) {
487 }
488}
489
496static void sh_present_loupe(void)
497{
499 const display_rect_t lens = {.x = (uint16_t)(((int32_t)k_sh_fb_w - (int32_t)k_sh_loupe_w) / 2),
500 .y = (uint16_t)(((int32_t)k_sh_fb_h - (int32_t)k_sh_loupe_h) / 2),
501 .w = (uint16_t)k_sh_loupe_w,
502 .h = (uint16_t)k_sh_loupe_h};
504}
505
507static void sh_setup_or_halt(void)
508{
509 uint32_t cpuclk0_hz = 0U;
510 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
512 }
515 }
516 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
518 }
521 }
522}
523
525static void sh_panel_or_halt(void)
526{
527 display_fb_t fb = {};
528 if ((ra8_sdramc_init() != k_ra8_ok) ||
532 }
533 if (ra8_gfx_init(fb.pixels, (uint16_t)k_sh_fb_w, (uint16_t)k_sh_fb_h, k_ra8_gfx_format_rgb565) !=
534 k_ra8_ok) {
536 }
537}
538
561static void sh_wdt_arm_or_halt(void)
562{
563 const ra8_wdt_cfg_t cfg = {
564 .timeout = k_ra8_wdt_timeout_16384, /* longest count ... */
565 .clock_div = k_ra8_wdt_clkdiv_8192, /* ... x longest divisor. */
566 .window_start = k_ra8_wdt_window_start_100, /* no upper bound. */
567 .window_end = k_ra8_wdt_window_end_0, /* no lower bound. */
568 .on_expiry = k_ra8_wdt_on_expiry_reset, /* reboot a hung reader. */
569 .stop_in_sleep = k_ra8_wdt_sleep_keep_count, /* count through WFI naps. */
570 };
571 if (ra8_wdt_init(&cfg) != k_ra8_ok) {
573 }
574}
575
577static void sh_input_init(void)
578{
579 const ra8_board_touch_cfg_t cfg = {.max_points = (uint8_t)k_sh_poll_pts,
580 .irq_pin = (uint8_t)k_ra8_touch_irq_pin_unset};
581 (void)ra8_board_touch_open(&cfg);
584}
585
587static bool
588sh_pump_input(uint8_t* prev_touch, ra8_board_sw_state_t* prev1, ra8_board_sw_state_t* prev2)
589{
590 bool changed = false;
591 bool acted = false;
592 bool lens_only = false;
593
595 uint8_t got = 0U;
596 if (ra8_touch_read(pts, (uint8_t)k_sh_poll_pts, &got) == k_ra8_ok) {
597 const bool down = (got > 0U);
598 const bool was_down = (*prev_touch > 0U);
599 /* The cover screen defers its tap so a press-hold can open the loupe; every
600 * other screen keeps the unchanged tap-on-press path (page-turn thirds). */
601 if (g_sh.screen == k_sh_screen_cover) {
602 const int32_t x = down ? (int32_t)pts[0].x : g_sh.touch_down_x;
603 const int32_t y = down ? (int32_t)pts[0].y : g_sh.touch_down_y;
604 changed = sh_cover_gesture(down, x, y, was_down, &lens_only);
605 acted = down || was_down;
606 } else if (down && !was_down) {
607 acted = true;
608 changed = sh_handle_tap((int32_t)pts[0].x, (int32_t)pts[0].y);
609 }
610 *prev_touch = got;
611 }
612
616 (*prev1 == k_ra8_board_sw_released)) {
617 acted = true;
618 changed = sh_handle_button(false) || changed;
619 }
621 (*prev2 == k_ra8_board_sw_released)) {
622 acted = true;
623 changed = sh_handle_button(true) || changed;
624 }
625 *prev1 = s1;
626 *prev2 = s2;
627
628 if (changed) {
629 if (lens_only) {
631 } else {
632 sh_present();
633 }
634 }
635 return acted;
636}
637
649
656static void sh_demo_step(uint32_t step)
657{
658 if (g_sh.book_count == 0U) {
659 return; /* nothing to demo; also guards the % book_count below */
660 }
661 switch ((sh_demo_t)(step % k_sh_demo_steps)) {
662 case k_sh_demo_cover0:
663 (void)sh_select_book(0U);
664 break;
665 case k_sh_demo_toc0:
666 g_sh.screen = k_sh_screen_toc;
667 break;
668 case k_sh_demo_read0:
670 break;
671 case k_sh_demo_turn:
672 (void)sh_reader_turn(1);
673 break;
674 case k_sh_demo_cover1:
675 (void)sh_select_book((uint16_t)(1U % g_sh.book_count));
676 break;
677 case k_sh_demo_toc1:
678 g_sh.screen = k_sh_screen_toc;
679 break;
680 case k_sh_demo_cover2:
681 (void)sh_select_book((uint16_t)(2U % g_sh.book_count));
682 break;
683 case k_sh_demo_read2:
684 default:
686 break;
687 }
688}
689
707static void sh_run(void)
708{
710 (void)ra8_board_sw_read(k_ra8_board_sw1, &sw1_boot);
711 uint8_t prev_touch = 0U;
712 ra8_board_sw_state_t prev1 = sw1_boot;
714 bool demo = (sw1_boot == k_ra8_board_sw_pressed);
715 uint32_t demo_ticks = 0U;
716 uint32_t demo_step = 0U;
717 uint32_t idle_ref_ms = ra8_time_ms(); /* timestamp of last activity. */
718 bool backlit = true; /* backlight currently lit. */
720 while (1) {
721 (void)ra8_wdt_refresh_for(k_ra8_wdt0); /* heartbeat: loop is alive. */
722 const bool acted = sh_pump_input(&prev_touch, &prev1, &prev2);
723 if (acted) {
724 demo = false; /* a real touch / button takes over */
725 } else if (demo && (++demo_ticks >= (uint32_t)k_sh_demo_period)) {
726 demo_ticks = 0U;
727 sh_demo_step(demo_step++);
728 sh_present();
729 }
730 if (acted || demo) {
731 idle_ref_ms = ra8_time_ms();
732 if (!backlit) {
733 (void)ra8_board_backlight_set(true);
734 backlit = true;
735 }
736 } else if (backlit && ((ra8_time_ms() - idle_ref_ms) >= (uint32_t)k_sh_idle_dim_ms)) {
737 (void)ra8_board_backlight_set(false);
738 backlit = false;
739 }
740 (void)ra8_delay_ms((uint32_t)k_sh_poll_ms);
741 }
742}
743
750void main(void)
751{
756
757 g_sh.screen = k_sh_screen_shelf;
758 g_sh.selected = 0U;
760 g_sh.sd_ready = sh_sd_mount();
761 if (g_sh.sd_ready) {
762 sh_sd_scan();
763 }
765
766 sh_present();
767
768 /* Prove the integrated comic path (#236) headlessly: decode page 0 of the
769 * baked CBZ + CBR fixtures into an off-screen scratch (rebinding ra8_gfx to it
770 * and back), so the shelf render that `sh_present` just left in the live
771 * framebuffer -- and its pinned `fb=` hash -- is untouched. */
772 sh_comic_probe_t cbz = {};
773 sh_comic_probe_t cbr = {};
774 bool rtl_ok = false;
775 sh_comic_selfcheck(&cbz, &cbr, &rtl_ok);
776 sh_print_banner(&cbz, &cbr, rtl_ok);
777
778 sh_run(); /* never returns */
779}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static const uint8_t k_msg_fail[]
Definition main.c:63
static int32_t sh_center_x(const char *s)
Centre a string horizontally for the bitmap font.
Definition main.c:208
static bool sh_handle_tap(int32_t x, int32_t y)
Route a touch tap to the active screen; returns whether to repaint.
Definition main.c:329
static void sh_demo_step(uint32_t step)
Advance the idle self-demo one step (shelf -> cover -> TOC -> read ...).
Definition main.c:656
static void sh_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:83
static display_handle_t * s_display
Definition main.c:78
static void sh_run(void)
Run the reader superloop – input pump, opt-in self-demo, watchdog, backlight idle-dim.
Definition main.c:707
static void sh_start_reading(void)
Start the reader at the book's first prose chapter (past front matter).
Definition main.c:275
sh_demo_t
Idle-demo step indices (one screen transition each).
Definition main.c:639
@ k_sh_demo_cover0
Open book 0 on its cover.
Definition main.c:640
@ k_sh_demo_read2
Read book 2.
Definition main.c:647
@ k_sh_demo_cover1
Open book 1 cover.
Definition main.c:644
@ k_sh_demo_cover2
Open book 2 cover.
Definition main.c:646
@ k_sh_demo_turn
Turn one page.
Definition main.c:643
@ k_sh_demo_toc0
Book 0 table of contents.
Definition main.c:641
@ k_sh_demo_read0
Read book 0.
Definition main.c:642
@ k_sh_demo_toc1
Book 1 table of contents.
Definition main.c:645
static bool sh_handle_button(bool is_sw2)
Route an SW1/SW2 edge to the active screen; returns whether to repaint.
Definition main.c:421
static void sh_seed_baked(void)
Seed the shelf with the MRAM-baked library books.
Definition main.c:186
static void sh_present(void)
Re-render the active screen and push it to the panel.
Definition main.c:453
static bool sh_pump_input(uint8_t *prev_touch, ra8_board_sw_state_t *prev1, ra8_board_sw_state_t *prev2)
Poll touch + buttons once; re-present on any change.
Definition main.c:588
static bool sh_tap_toc(int32_t x, int32_t y, bool header)
Handle a TOC-screen tap; returns whether to repaint.
Definition main.c:301
static bool sh_select_book(uint16_t idx)
Open the selected book and move to the cover screen; ignore on failure.
Definition main.c:245
static bool sh_tap_reader(int32_t x, int32_t y, bool header)
Handle a reader-screen tap (header back / edge page turn).
Definition main.c:317
ra8_err_t sh_inflate(const void *src, size_t src_len, void *dst, size_t dst_cap, size_t *out_len)
Heap-free zlib inflater matching book_inflate_fn (miniz; main.c).
Definition main.c:160
static void sh_wdt_arm_or_halt(void)
Arm WDT0 to reset a wedged reader loop; fatal on failure.
Definition main.c:561
static void sh_panic_halt(void)
Print the fail banner and trap (ra8_emulator halts on the BKPT).
Definition main.c:145
static bool sh_loupe_held(int32_t x, int32_t y, bool *out_lens_only)
Held-finger step of the cover loupe gesture: pan an open lens, or open one once the press has been he...
Definition main.c:357
sh_main_const_t
Boot + banner formatting constants.
Definition main.c:51
@ k_sh_fnv_prime
FNV-1a 32-bit prime.
Definition main.c:57
@ k_sh_thirds
Reader edge-tap split.
Definition main.c:52
@ k_sh_fnv_offset
FNV-1a 32-bit offset basis.
Definition main.c:56
@ k_sh_hex_digits
Hex digits in the framebuffer hash.
Definition main.c:58
@ k_sh_nib_bits
Bits per hex digit.
Definition main.c:59
@ k_sh_nib_mask
Low-nibble mask.
Definition main.c:60
@ k_sh_demo_period
Input polls between demo steps.
Definition main.c:54
@ k_sh_demo_steps
Idle-demo sequence length.
Definition main.c:53
@ k_sh_idle_dim_ms
No-input time before backlight off.
Definition main.c:55
static int32_t sh_edge_dir(int32_t x)
Reader edge-tap to direction: -1 left third, +1 right third, else 0.
Definition main.c:262
static void sh_input_init(void)
Open touch + the two user buttons (best-effort; input is optional).
Definition main.c:577
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 void sh_loading_overlay(const char *name)
Paint a "Loading from SD card..." panel before a (blocking) SD open.
Definition main.c:221
static void sh_print_banner(const sh_comic_probe_t *cbz, const sh_comic_probe_t *cbr, bool rtl_ok)
Emit the gate banner: book count, SD flag, framebuffer hash, comic digests.
Definition main.c:112
static void sh_setup_or_halt(void)
Bring up clocks/MSTP/time + the SCI8 console; halt on failure.
Definition main.c:507
static const display_cfg_t k_sh_display_cfg
Definition main.c:69
static void sh_panel_or_halt(void)
SDRAM + GLCDC panel bring-up; bind ra8_gfx to the live framebuffer.
Definition main.c:525
uint16_t * sh_fb_pixels(void)
The live RGB565 framebuffer ra8_gfx scans (defined in main.c).
Definition main.c:180
static bool sh_tap_cover(int32_t x, int32_t y, bool header)
Handle a cover-screen tap; returns whether to repaint.
Definition main.c:282
static uint32_t sh_fb_hash(void)
FNV-1a hash of the whole framebuffer (deterministic render digest).
Definition main.c:89
static tinfl_decompressor s_tinfl
Static DEFLATE decompressor state (~11 KiB) kept off the small stack.
Definition main.c:158
static void sh_present_loupe(void)
Repaint only the fixed lens window during a loupe pan and flush just it.
Definition main.c:496
static bool sh_cover_gesture(bool down, int32_t x, int32_t y, bool was_down, bool *out_lens_only)
Cover-screen press-hold loupe gesture: a hold opens the magnifier, drag pans it, release exits; a sho...
Definition main.c:396
@ k_library_count
Number of entries in k_library.
Definition library.h:54714
static const library_book_t k_library[k_library_count]
Definition library.h:54717
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_backlight_set(bool on)
Turn the J1 panel backlight (BLEN, P514) on or off.
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_board_sw_state_t
Logical "pressed" / "released" state.
@ k_ra8_board_sw_released
RA8 board sw released.
@ k_ra8_board_sw_pressed
RA8 board sw pressed.
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
Display Platform Abstraction Layer for the RA8D2.
@ k_display_pixfmt_rgb565
16 bpp, 5/6/5 packed.
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.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
char * strncpy(char *dst, const char *src, size_t n)
Copy bounded string to destination buffer.
size_t strlen(const char *s)
Calculate string length.
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
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_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.
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.
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
#define RA8_BOARD_PANEL_FRAMEBUFFER(name)
Declare a correctly aligned, sized and placed RGB565 framebuffer for the on-board panel.
Definition ra8_panel.h:165
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
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
uint32_t ra8_time_ms(void)
Get the current 1 kHz tick count.
Definition ra8_time.c:108
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
Software Watchdog Timer (WDT) driver header.
@ k_ra8_wdt_timeout_16384
16384 cycles.
Definition ra8_wdt.h:150
@ k_ra8_wdt_clkdiv_8192
PCLKB / 8192.
Definition ra8_wdt.h:131
ra8_err_t ra8_wdt_refresh_for(ra8_wdt_instance_t which)
Refresh a specific WDT instance.
Definition ra8_wdt.c:356
ra8_err_t ra8_wdt_init(const ra8_wdt_cfg_t *cfg)
Initialise the WDT in register-start mode.
Definition ra8_wdt.c:296
@ k_ra8_wdt_window_start_100
100 % (no upper bound).
Definition ra8_wdt.h:166
@ k_ra8_wdt_on_expiry_reset
RSTIRQS=1 – internal reset.
Definition ra8_wdt.h:202
@ k_ra8_wdt_sleep_keep_count
SLCSTP=0 – counter runs in Sleep.
Definition ra8_wdt.h:218
@ k_ra8_wdt_window_end_0
0 % (no lower bound).
Definition ra8_wdt.h:185
@ k_ra8_wdt0
WDT0 – Cortex-M85 side.
Shared contract for the ereader_shelf multi-screen e-reader.
bool sh_reader_turn(int32_t dir)
Turn the reader page by dir (-1/+1) across chapters; returns changed.
Definition sh_reader.c:254
bool sh_comic_tap(int32_t x, bool header)
Handle a comic-screen tap: header returns to the shelf, else page-turn.
Definition sh_comic.c:285
void sh_comic_render(void)
Render the current comic page full-screen (title bar + fitted image).
Definition sh_comic.c:222
uint32_t sh_reader_first_content(void)
First chapter with substantial prose (skips title/imprint front matter).
Definition sh_reader.c:198
void sh_reader_load_chapter(uint32_t chapter)
Load + wrap a chapter into the reader working set.
Definition sh_reader.c:177
void sh_shelf_build_thumbs(void)
Copy the baked books' pre-decoded covers into sh_state_t::thumb at boot.
Definition sh_shelf.c:62
void sh_toc_scroll(int32_t dir)
Scroll the TOC list by dir pages (-1 up / +1 down), clamped.
Definition sh_toc.c:90
bool sh_book_open(uint16_t idx)
Open shelf entry idx by its format; sets g_sh.open_fmt + chapter count, and (for SD books on first op...
Definition sh_book.c:431
int32_t sh_shelf_hit(int32_t x, int32_t y)
Hit-test a shelf tap; returns the book index or -1.
Definition sh_shelf.c:170
void sh_comic_selfcheck(sh_comic_probe_t *cbz, sh_comic_probe_t *cbr, bool *rtl_ok)
Headless boot self-check: decode the baked CBZ + CBR page 0, verify RTL.
Definition sh_comic.c:335
bool sh_comic_turn(int32_t dir)
Turn the comic page by dir in reading order, clamped to the ends.
Definition sh_comic.c:268
@ k_sh_screen_shelf
Book grid with cover thumbnails.
Definition sh_app.h:116
@ k_sh_screen_comic
Full-page image reader (CBZ / CBR).
Definition sh_app.h:120
@ k_sh_screen_reader
Reading a book.
Definition sh_app.h:119
@ k_sh_screen_cover
One book's cover / title page.
Definition sh_app.h:117
@ k_sh_screen_toc
Chapter list.
Definition sh_app.h:118
void sh_sd_scan(void)
Append every root *.RBK file on the card as an SD shelf entry.
Definition sh_sd.c:143
@ k_sh_loupe_w
Lens window width in framebuffer pixels.
Definition sh_app.h:85
@ k_sh_loupe_h
Lens window height in framebuffer pixels.
Definition sh_app.h:86
@ k_sh_loupe_hold_ms
Press-hold duration that opens the lens (ms).
Definition sh_app.h:89
@ k_sh_uart_baud
Console baud.
Definition sh_app.h:68
@ k_sh_line_h
Reader text line height.
Definition sh_app.h:50
@ k_sh_glyph_h
Bitmap font cell height.
Definition sh_app.h:49
@ k_sh_fb_h
Panel height in pixels.
Definition sh_app.h:47
@ k_sh_poll_ms
Input poll period in ms.
Definition sh_app.h:70
@ k_sh_glyph_w
Bitmap font cell width.
Definition sh_app.h:48
@ k_sh_bar_h
Header / title-bar height.
Definition sh_app.h:51
@ k_sh_linebuf
Per-line draw buffer bytes.
Definition sh_app.h:59
@ k_sh_poll_pts
Touch points polled per read.
Definition sh_app.h:69
@ k_sh_fb_w
Panel width in pixels.
Definition sh_app.h:46
@ k_sh_dec_base
Decimal formatting base.
Definition sh_app.h:71
@ k_sh_max_books
Shelf / thumbnail-cache capacity.
Definition sh_app.h:62
void sh_cover_loupe_render(void)
Draw the magnifier loupe over the cover at the current pan centre.
Definition sh_cover.c:124
sh_cover_act_t
Result of a tap on the cover screen.
Definition sh_app.h:446
@ k_sh_cover_read
Open the reader at chapter 0.
Definition sh_app.h:448
@ k_sh_cover_toc
Open the table of contents.
Definition sh_app.h:449
void sh_toc_render(void)
Render the open book's chapter list (TOC).
Definition sh_toc.c:42
bool sh_cover_loupe_map(int32_t px, int32_t py, int32_t *out_cx, int32_t *out_cy)
Map a cover-screen touch to full-res source coordinates for the loupe.
Definition sh_cover.c:103
void sh_reader_render(void)
Render the current reader page.
Definition sh_reader.c:210
void sh_comic_append_banner(char *b, size_t *pos, const sh_comic_probe_t *cbz, const sh_comic_probe_t *cbr, bool rtl_ok)
Append " cbz=P:WxH:CRC cbr=P:WxH:CRC rtl=OK" to the boot banner buffer.
Definition sh_comic.c:359
void sh_reader_prefetch_adjacent(void)
Read-ahead warm the adjacent chapters into the page cache (#207).
Definition sh_reader.c:282
size_t sh_fmt_uint(char *dst, size_t pos, uint32_t v)
Append unsigned v as decimal into dst at pos; returns new pos.
Definition sh_util.c:52
bool sh_sd_mount(void)
Bring up the Pmod2 microSD over ra8_sdmmc_spi and mount its FAT volume.
Definition sh_sd.c:97
void sh_shelf_render(void)
Render the shelf grid (cover cards) into the framebuffer.
Definition sh_shelf.c:160
sh_state_t g_sh
The single whole-app state instance (defined in main.c).
Definition main.c:64
sh_cover_act_t sh_cover_action(int32_t x, int32_t y)
Classify a cover-screen tap into a sh_cover_act_t.
Definition sh_cover.c:91
int32_t sh_toc_hit(int32_t x, int32_t y)
Hit-test a TOC tap; returns the chapter index or -1.
Definition sh_toc.c:79
@ k_sh_col_bg
App background (dark wood).
Definition sh_app.h:98
@ k_sh_col_card
Card / page fill (paper).
Definition sh_app.h:100
@ k_sh_col_sub
Secondary ink (author / hints).
Definition sh_app.h:103
void sh_cover_render(void)
Render the selected book's cover / title page.
Definition sh_cover.c:51
static bool sh_fmt_is_comic(sh_book_fmt_t fmt)
True if fmt is a comic-archive container (CBZ, CBR, or CBT).
Definition sh_classify.h:59
Configuration descriptor passed into display_init.
Framebuffer descriptor returned by display_get_framebuffer.
void * pixels
Base of pixel data (RGB565 unless noted).
Rectangle in framebuffer coordinates passed into display_flush.
The two touch settings that are an APPLICATION choice, not a board fact.
One decoded touch contact.
Definition ra8_touch.h:93
Register-start-mode configuration block.
Definition ra8_wdt.h:305
One container's headless self-check result (page 0 decode digest).
Definition sh_app.h:686
One shelf book, sourced from MRAM (baked) or the SD card, in either the .rabook or ....
Definition sh_app.h:141
bool from_sd
true: read sd_name from SD; false: use blob.
Definition sh_app.h:142
const uint8_t * blob
Baked RBKC bytes (MRAM), or NULL when SD.
Definition sh_app.h:144
uint16_t thumb_w
Pre-baked thumbnail width.
Definition sh_app.h:147
uint16_t thumb_h
Pre-baked thumbnail height.
Definition sh_app.h:148
const uint8_t * thumb
Pre-baked gray8 cover thumbnail, or NULL.
Definition sh_app.h:146
uint32_t blob_len
Baked length, or SD file size in bytes.
Definition sh_app.h:145
char title[k_sh_title_cap]
Display title.
Definition sh_app.h:150
char author[k_sh_author_cap]
Display author.
Definition sh_app.h:151
Whole-app UI + reader state (single instance g_sh).
Definition sh_app.h:165