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
38
39#include <stddef.h>
40#include <stdint.h>
41#include <string.h>
42
43#include "jof.h"
44#include "jof_produce.h"
45#include "mg_page_fixture.h"
46#include "mg_reader.h"
47#include "ra8_board_ek_ra8d2.h"
49#include "ra8_boot_entry.h"
50#include "ra8_cgc.h"
51#include "ra8_display_pal.h"
52#include "ra8_display_pal_lcd.h"
53#include "ra8_err.h"
54#include "ra8_gfx.h"
55#include "ra8_isr.h"
56#include "ra8_mstp.h"
57#include "ra8_panel.h"
58#include "ra8_panel_timing.h"
59#include "ra8_sdramc.h"
60#include "ra8_tile_cache.h"
61#include "ra8_time.h"
62#include "ra8_touch.h"
63
69typedef enum : uint32_t {
70 k_mg_uart_baud = 115200U,
75} mg_boot_t;
76
82typedef enum : uint32_t {
84 k_mg_cap_edge = 2048U,
85 k_mg_cell_bytes = 256U * 256U,
86 /* ::k_mg_view_cols / ::k_mg_view_rows are the tile columns/rows one 1:1
87 * viewport frame can straddle: ceil(extent / tile) tiles, plus one for the
88 * viewport not being tile-aligned. The content area is the panel minus the
89 * status bar (the render clips there). See the derivation note below. */
91 (((uint32_t)k_panel_width_px + k_mg_tile_edge - 1U) / k_mg_tile_edge) + 1U,
93 ((((uint32_t)k_panel_height_px - (uint32_t)k_mg_statusbar_h) + k_mg_tile_edge - 1U) /
95 1U,
98 k_mg_cell_budget_bytes = 4U * 1024U * 1024U,
99 k_mg_scratch = 96U * 1024U,
100 k_mg_work_bytes = 3203832U,
101 k_mg_store_bytes = 4U * 1024U * 1024U,
107} mg_atlas_t;
108
109/*
110 * ::k_mg_cells is DERIVED from the panel + tile geometry, never hand-picked
111 * (#338). The reader pages the atlas one tile at a time (get / blit / put), so
112 * the cache does not need every on-screen tile pinned at once -- but it must
113 * still be able to *hold* the tiles a frame touches, or a one-tile pan evicts
114 * tiles that are still on screen and re-inflates them next frame. That is the
115 * thrash: with a sub-frame budget every pan re-decodes ~a full screen of
116 * 64 KiB DEFLATE tiles.
117 *
118 * At 1:1 a 1024x600 panel with a 48 px status bar shows a 1024x552 content
119 * window over 256x256 tiles, straddling at most ::k_mg_view_cols x
120 * ::k_mg_view_rows = 5 x 4 = 20 tiles. Sizing the cache to that frame plus one
121 * tile of margin on each axis (::k_mg_cells = 6 x 5 = 30, ~1.9 MiB of the
122 * 64 MB SDRAM) means the union of any single-step pan's before/after frames
123 * stays resident, so a pan re-decodes only the newly exposed row/column, never
124 * a tile still on screen. `apps/board/stand_alone/ereader/tests/src/test_app_ereader_manga.c`
125 * (test_manga_pan_no_thrash) measures the eviction/decode count for a
126 * representative pan against the old 4-cell budget and asserts it collapses.
127 *
128 * Two compile-time tripwires keep the budget honest:
129 * - the first static_assert fails the build if ::k_mg_cells is ever set below
130 * the frame demand (a manual override, or a geometry change that outgrows
131 * it), the condition that reintroduces the thrash;
132 * - the second bounds the resident-tile arena by ::k_mg_cell_budget_bytes so
133 * the derivation cannot silently balloon the SDRAM working set.
134 * The 4-cell budget lives on only as the explicit eviction-stress case in the
135 * host test, which is what it was always right for.
136 */
137static_assert((uint64_t)k_mg_cells >= (uint64_t)k_mg_view_cols * (uint64_t)k_mg_view_rows,
138 "tile cache is smaller than the 1:1 viewport tile demand: re-derive k_mg_cells from "
139 "the panel + tile geometry so a single-step pan cannot thrash (#338)");
140static_assert((uint64_t)k_mg_cells * (uint64_t)k_mg_cell_bytes <= (uint64_t)k_mg_cell_budget_bytes,
141 "resident tile arena exceeds its SDRAM budget: the tile-cache derivation grew past "
142 "k_mg_cell_budget_bytes");
143
144/*
145 * ::k_mg_work_bytes is DERIVED, never hand-picked: it is exactly
146 * `jof_work_bytes(k_mg_cap_edge, k_mg_cap_edge, k_mg_tile_edge,
147 * k_mg_tile_edge)` -- the producer's own worst-case arena requirement for the
148 * cap this app advertises, taken at the format's maximum 4 bpp. A round number
149 * here is how the advertised cap and the real capability drift apart: a 2 MiB
150 * arena backs a cap of only 1016 px, so the app used to advertise 2048 and
151 * fail-closed (`k_ra8_err_invalid_size`) on any in-budget source wider than
152 * that. Three layers keep the two in agreement:
153 * - the static_assert below is a compile-time tripwire on the band term
154 * (`cap * tile_h * bpp_max`), a strict lower bound on the full
155 * requirement, so raising ::k_mg_cap_edge without re-deriving the arena
156 * fails the build;
157 * - `apps/board/stand_alone/ereader/tests/src/test_app_ereader_manga.c` asserts the arena
158 * against the real
159 * `jof_work_bytes()` return, which is the exact and
160 * authoritative check, and runs in CI;
161 * - `mg_build_atlas()` re-checks the same call at boot, so a mismatch that
162 * somehow reaches silicon reports `FAIL atlas` instead of silently
163 * under-delivering the advertised cap.
164 * The band term alone is a lower bound, not the whole requirement, so the
165 * static_assert can only catch an under-sized arena, never certify a
166 * sufficient one -- that is the test's and the boot check's job.
167 */
168static_assert((uint64_t)k_mg_work_bytes >=
169 ((uint64_t)k_mg_cap_edge * (uint64_t)k_mg_tile_edge * (uint64_t)k_jof_bpp_max),
170 "work arena is below the producer band term for the advertised cap: re-derive "
171 "k_mg_work_bytes from jof_work_bytes() for k_mg_cap_edge");
172
182
191
193[[gnu::section(".sdram_data")]] static uint8_t s_work[k_mg_work_bytes];
195[[gnu::section(".sdram_data")]] static uint8_t s_store_buf[k_mg_store_bytes];
197[[gnu::section(
198 ".sdram_data")]] static uint8_t s_cell_mem[(size_t)k_mg_cells * (size_t)k_mg_cell_bytes];
200[[gnu::section(".sdram_data")]] static uint8_t s_scratch[k_mg_scratch];
201
205 .framebuffer = s_framebuffer,
206 .framebuffer_bytes = sizeof(s_framebuffer),
207 .width_px = (uint16_t)k_mg_fb_w,
208 .height_px = (uint16_t)k_mg_fb_h,
209 .pixfmt = k_display_pixfmt_rgb565,
210 .panel_timing = &s_ra8_panel_ek_ra8d2_timing,
211};
212
214static display_handle_t* s_display = nullptr;
217
228
236static int32_t s_buckets[k_mg_buckets];
237
243typedef struct {
244 const uint8_t* data;
245 uint32_t len;
246 uint32_t pos;
248
251
253/* Console banner fragments. */
254static const uint8_t k_msg_boot[] = "ereader-manga: boot\r\n";
255static const uint8_t k_msg_fail[] = "ereader-manga: FAIL init\r\n";
256static const uint8_t k_msg_atl[] = "ereader-manga: FAIL atlas\r\n";
257static const uint8_t k_msg_rend[] = "ereader-manga: FAIL render\r\n";
258static const uint8_t k_msg_pre[] = "ereader-manga: page ";
259static const uint8_t k_msg_x[] = "x";
260static const uint8_t k_msg_tiles[] = " tiles=";
261static const uint8_t k_msg_atlas[] = " atlas=";
262static const uint8_t k_msg_view[] = " view=0,0 zoom=1:1 crc=";
263static const uint8_t k_msg_ok[] = " ok\r\n";
264
266static void mg_print(const uint8_t* msg, uint32_t len)
267{
268 (void)ra8_board_uart_console_write(msg, (size_t)len);
269}
270
272static void mg_panic_halt(const uint8_t* msg, uint32_t len)
273{
274 mg_print(msg, len);
276 __asm__ volatile("bkpt #0");
277 while (1) {
278 __asm__ volatile("wfi");
279 }
280}
281
283static void mg_print_hex(uint32_t value)
284{
285 uint8_t buf[k_mg_hex_nibbles];
286 for (uint32_t i = 0U; i < (uint32_t)k_mg_hex_nibbles; ++i) {
287 const uint32_t shift = ((uint32_t)k_mg_hex_nibbles - 1U - i) * (uint32_t)k_mg_nibble_bits;
288 const uint32_t nib = (value >> shift) & (uint32_t)k_mg_nibble_mask;
289 buf[i] = (uint8_t)((nib < (uint32_t)k_mg_dec_ten) ? ('0' + nib) : ('A' + (nib - k_mg_dec_ten)));
290 }
291 mg_print(buf, (uint32_t)k_mg_hex_nibbles);
292}
293
295static void mg_print_uint(uint32_t value)
296{
297 uint8_t buf[k_mg_dec_ten];
298 uint32_t n = 0U;
299 if (value == 0U) {
300 buf[n] = '0';
301 n++;
302 }
303 while ((value > 0U) && (n < (uint32_t)k_mg_dec_ten)) {
304 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_mg_dec_ten));
305 n++;
306 value /= (uint32_t)k_mg_dec_ten;
307 }
308 for (uint32_t i = 0U; i < n; ++i) {
309 mg_print(&buf[n - 1U - i], 1U);
310 }
311}
312
313/* ===========================================================================
314 * Boot helpers
315 * =========================================================================== */
316
318static void mg_bringup_clocks(void)
319{
320 uint32_t cpuclk0_hz = 0U;
321 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
322 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
323 }
325 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
326 }
327 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
328 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
329 }
332 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
333 }
335 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
336 }
338}
339
341static void mg_bringup_panel(void)
342{
343 ra8_delay_ms((uint32_t)k_mg_settle_ms);
344 if (ra8_sdramc_init() != k_ra8_ok) {
345 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
346 }
348 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
349 }
351 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
352 }
353 if (ra8_gfx_init(s_fb.pixels, s_fb.width_px, s_fb.height_px, k_ra8_gfx_format_rgb565) !=
354 k_ra8_ok) {
355 mg_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
356 }
357}
358
360static void mg_bringup_touch(void)
361{
362 const ra8_board_touch_cfg_t cfg = {.max_points = (uint8_t)k_mg_touch_max_points,
363 .irq_pin = (uint8_t)k_ra8_touch_irq_pin_unset};
364 (void)ra8_board_touch_open(&cfg);
365}
366
367/* ===========================================================================
368 * Atlas produce + cache + reader setup
369 * =========================================================================== */
370
372static ra8_err_t mg_png_pull(void* ctx, uint8_t* buf, size_t cap, size_t* got)
373{
375 const uint32_t avail = c->len - c->pos;
376 size_t take = ((uint32_t)cap < avail) ? cap : (size_t)avail;
377 (void)memcpy(buf, &c->data[c->pos], take);
378 c->pos += (uint32_t)take;
379 *got = take;
380 return k_ra8_ok;
381}
382
384static bool mg_build_atlas(void)
385{
386 /* The advertised cap must be one this arena can actually serve. The producer
387 * carves from the *decoded* geometry, so an under-sized arena would not show
388 * up until some in-budget source happened to be wide enough or deep enough in
389 * bpp to exhaust it; asking the producer for its own requirement up front
390 * turns that latent capability lie into a deterministic boot failure. */
391 const uint32_t need = jof_work_bytes((uint16_t)k_mg_cap_edge,
392 (uint16_t)k_mg_cap_edge,
393 (uint16_t)k_mg_tile_edge,
394 (uint16_t)k_mg_tile_edge);
395 if ((need == 0U) || (need > (uint32_t)sizeof(s_work))) {
396 return false;
397 }
398 s_png_cursor = (mg_png_cursor_t){.data = k_mg_png, .len = k_mg_png_len, .pos = 0U};
399 s_store = (jof_memstore_t){.buf = s_store_buf, .cap = sizeof(s_store_buf), .len = 0U};
400 const jof_produce_cfg_t cfg = {
401 .pull = mg_png_pull,
402 .pull_ctx = &s_png_cursor,
403 .sink = jof_memstore_sink,
404 .sink_ctx = &s_store,
405 .tile_w = (uint16_t)k_mg_tile_edge,
406 .tile_h = (uint16_t)k_mg_tile_edge,
407 /* Deflate tiles (codec 1): each tile is an intra-coded raw-DEFLATE stream,
408 * so the 3 MiB page normalizes to a ~20 KiB atlas and every cache miss does
409 * real decode-on-demand work (one bounded inflate into the pinned cell) --
410 * the streaming-larger-than-RAM property the tile cache exists for. On the
411 * 1 GHz M85 a 64 KiB-tile inflate is microseconds; the cost only shows under
412 * the ra8_emulator CPU emulator, where boot still completes well inside budget. */
413 .codec = (uint8_t)k_jof_codec_deflate,
414 .max_width = (uint16_t)k_mg_cap_edge,
415 .max_height = (uint16_t)k_mg_cap_edge,
416 .work = s_work,
417 .work_cap = sizeof(s_work),
418 .webp_work = nullptr,
419 };
420 if (jof_produce(&cfg, &s_info) != k_ra8_ok) {
421 return false;
422 }
424}
425
427static bool mg_setup_cache(void)
428{
429 s_tile_src = (mg_tile_src_t){.info = &s_info,
430 .pread = jof_memstore_pread,
431 .pread_ctx = &s_store,
432 .scratch = s_scratch,
433 .scratch_cap = (uint32_t)sizeof(s_scratch)};
434 const ra8_tile_cache_cfg_t cache_cfg = {.cell_mem = s_cell_mem,
435 .cell_bytes = (uint32_t)k_mg_cell_bytes,
436 .cell_count = (uint32_t)k_mg_cells,
437 .meta = s_meta,
438 .keys = s_keys,
439 .dims = s_dims,
440 .buckets = s_buckets,
441 .bucket_count = (uint32_t)k_mg_buckets,
442 .decode = mg_tile_decode,
443 .decode_ctx = &s_tile_src};
444 return ra8_tile_cache_init(&s_cache, &cache_cfg) == k_ra8_ok;
445}
446
452
454static void mg_print_banner(void)
455{
456 mg_print(k_msg_pre, (uint32_t)sizeof(k_msg_pre) - 1U);
457 mg_print_uint((uint32_t)s_info.width);
458 mg_print(k_msg_x, (uint32_t)sizeof(k_msg_x) - 1U);
459 mg_print_uint((uint32_t)s_info.height);
460 mg_print(k_msg_tiles, (uint32_t)sizeof(k_msg_tiles) - 1U);
461 mg_print_uint(s_info.tile_count);
462 mg_print(k_msg_atlas, (uint32_t)sizeof(k_msg_atlas) - 1U);
463 mg_print_uint(s_info.total_size);
464 mg_print(k_msg_view, (uint32_t)sizeof(k_msg_view) - 1U);
466 mg_print(k_msg_ok, (uint32_t)sizeof(k_msg_ok) - 1U);
467}
468
470static void mg_poll_touch(bool* was_touching)
471{
472 ra8_touch_point_t pt = {};
473 uint8_t got = 0U;
474 if (ra8_touch_read(&pt, 1U, &got) != k_ra8_ok) {
475 return;
476 }
477 const bool touching = (got > 0U);
478 if (touching && !(*was_touching)) {
479 if (mg_reader_tap(&s_reader, (int32_t)pt.x, (int32_t)pt.y)) {
481 mg_present();
482 /* Idle-window read-ahead: warm the next pan step's tiles so a follow-on
483 * pan finds them resident instead of stalling on a cold decode (#341). */
485 }
486 }
487 }
488 *was_touching = touching;
489}
490
498void main(void)
499{
501 mg_print(k_msg_boot, (uint32_t)sizeof(k_msg_boot) - 1U);
504
505 if (!mg_build_atlas()) {
506 mg_panic_halt(k_msg_atl, (uint32_t)sizeof(k_msg_atl) - 1U);
507 }
508 if (!mg_setup_cache()) {
509 mg_panic_halt(k_msg_atl, (uint32_t)sizeof(k_msg_atl) - 1U);
510 }
511 const mg_reader_cfg_t rcfg = {.fb = s_framebuffer,
512 .fb_w = (int32_t)k_mg_fb_w,
513 .fb_h = (int32_t)k_mg_fb_h,
514 .cache = &s_cache,
515 .info = &s_info,
516 .image_id = (uint32_t)k_mg_image_id};
517 if (mg_reader_init(&s_reader, &rcfg) != k_ra8_ok) {
518 mg_panic_halt(k_msg_atl, (uint32_t)sizeof(k_msg_atl) - 1U);
519 }
521 mg_panic_halt(k_msg_rend, (uint32_t)sizeof(k_msg_rend) - 1U);
522 }
523 mg_present();
525
526 bool was_touching = false;
527 uint32_t ticks = 0U;
528 while (1) {
529 mg_poll_touch(&was_touching);
530 if ((ticks % (uint32_t)k_mg_led_every) == 0U) {
532 }
533 ticks++;
534 ra8_delay_ms((uint32_t)k_mg_frame_ms);
535 }
536}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static uint8_t s_scratch[(size_t) k_ra8_compress_scratch_bytes]
Compressor scratch (one miniz tdefl_compressor) in SRAM.
Definition main.c:96
static const uint8_t k_msg_pre[]
Definition main.c:151
static const uint8_t k_msg_ok[]
Definition main.c:153
static const uint8_t k_msg_boot[]
Definition main.c:140
static const uint8_t k_msg_fail[]
Definition main.c:63
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 const uint8_t k_msg_view[]
Definition main.c:324
static ra8_tile_key_t s_keys[(size_t) k_ls_cells]
Cache key storage.
Definition main.c:264
static int32_t s_buckets[(size_t) k_ls_buckets]
Cache hash buckets.
Definition main.c:267
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
static ra8_keycache_cell_t s_meta[(size_t) k_ls_cells]
Cache link metadata.
Definition main.c:266
static ra8_tile_dims_t s_dims[(size_t) k_ls_cells]
Cache dim storage.
Definition main.c:265
static const uint8_t k_msg_tiles[]
Definition main.c:260
static const display_cfg_t k_mg_display_cfg
Display PAL config – LCD/GLCDC backend over the SDRAM framebuffer.
Definition main.c:203
static mg_reader_t s_reader
The pan/zoom viewer over the tiled page.
Definition main.c:227
static ra8_err_t mg_png_pull(void *ctx, uint8_t *buf, size_t cap, size_t *got)
produce pull seam: stream the baked PNG bytes to the transcoder.
Definition main.c:372
static uint8_t s_work[k_mg_work_bytes]
Producer work arena (SDRAM: the transcode working set).
Definition main.c:193
static const uint8_t k_msg_atl[]
Definition main.c:256
static void mg_bringup_panel(void)
Bring up SDRAM + the GLCDC panel, then bind ra8_gfx to the FB.
Definition main.c:341
static mg_png_cursor_t s_png_cursor
PNG pull cursor for the produce source.
Definition main.c:250
static const uint8_t k_msg_atlas[]
Definition main.c:261
static jof_info_t s_info
Parsed atlas geometry after produce.
Definition main.c:221
static void mg_print_uint(uint32_t value)
Print a small unsigned integer in decimal.
Definition main.c:295
static const uint8_t k_msg_rend[]
Definition main.c:257
static bool mg_setup_cache(void)
Wire the tile cache (decode-on-miss = read_tile) over the atlas.
Definition main.c:427
static void mg_print_hex(uint32_t value)
Print a 32-bit value as 8 upper-case hex digits.
Definition main.c:283
mg_boot_t
Boot / console / touch knobs.
Definition main.c:69
@ k_mg_led_every
Heartbeat LED toggle sub-cadence.
Definition main.c:73
@ k_mg_settle_ms
PLL / SDRAM / panel-POR settle.
Definition main.c:71
@ k_mg_uart_baud
Console baud.
Definition main.c:70
@ k_mg_touch_max_points
One contact = one tap.
Definition main.c:74
@ k_mg_frame_ms
Input poll period, ms.
Definition main.c:72
static void mg_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the console.
Definition main.c:266
static void mg_print_banner(void)
Print the deterministic boot banner (geometry + render hash).
Definition main.c:454
mg_fb_t
Framebuffer geometry (mirrors the EK-RA8D2 panel).
Definition main.c:178
@ k_mg_fb_w
Framebuffer width, pixels.
Definition main.c:179
@ k_mg_fb_h
Framebuffer height, pixels.
Definition main.c:180
static void mg_present(void)
Present the framebuffer (clean full update).
Definition main.c:448
static mg_tile_src_t s_tile_src
Decode-on-miss context bound into the cache.
Definition main.c:225
static bool mg_build_atlas(void)
Transcode the baked page into a JOF atlas + parse its geometry.
Definition main.c:384
static uint8_t s_store_buf[k_mg_store_bytes]
Atlas memstore backing (SDRAM: the produced JOF atlas).
Definition main.c:195
static void mg_bringup_touch(void)
Open the GT911 touch controller (best-effort, polled).
Definition main.c:360
static uint8_t s_cell_mem[(size_t) k_mg_cells *(size_t) k_mg_cell_bytes]
Tile-cache cell storage (k_mg_cells gray8 256x256 tiles, SDRAM).
Definition main.c:198
mg_atlas_t
JOF produce + cache budget (page geometry rides in the fixture).
Definition main.c:82
@ k_mg_store_bytes
SDRAM atlas memstore.
Definition main.c:101
@ k_mg_view_cols
1:1 cols.
Definition main.c:90
@ k_mg_cells
Frame + 1-tile pan margin.
Definition main.c:96
@ k_mg_image_id
Tile-cache key image id.
Definition main.c:102
@ k_mg_cell_bytes
One gray8 256x256 tile.
Definition main.c:85
@ k_mg_tile_edge
Import + cache tile edge, pixels.
Definition main.c:83
@ k_mg_cell_budget_bytes
SDRAM tile cache may claim.
Definition main.c:98
@ k_mg_nibble_mask
Low-nibble mask.
Definition main.c:105
@ k_mg_scratch
read_tile deflate staging.
Definition main.c:99
@ k_mg_hex_nibbles
Hex digits per 32-bit value.
Definition main.c:103
@ k_mg_buckets
Hash buckets (>= cells).
Definition main.c:97
@ k_mg_nibble_bits
Bits per hex nibble.
Definition main.c:104
@ k_mg_dec_ten
Decimal radix / hex split.
Definition main.c:106
@ k_mg_work_bytes
SDRAM producer work arena.
Definition main.c:100
@ k_mg_cap_edge
Produce budget cap, pixels.
Definition main.c:84
@ k_mg_view_rows
1:1 content rows.
Definition main.c:92
static void mg_panic_halt(const uint8_t *msg, uint32_t len)
Print a fail banner, then trap (ra8_emulator halts on the BKPT).
Definition main.c:272
static void mg_poll_touch(bool *was_touching)
Poll the GT911 once; on a fresh tap, mutate + redraw the viewport.
Definition main.c:470
static void mg_bringup_clocks(void)
Bring up clocks, MSTP, system tick, LEDs and the SCI console.
Definition main.c:318
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_bpp_max
Max bytes per pixel.
Definition jof.h:178
ra8_err_t jof_parse(jof_pread_fn pread, void *pread_ctx, uint64_t total_size, jof_info_t *out_info)
Parse + validate a JOF atlas's header, footer and index bounds.
Definition jof.c:379
@ k_jof_codec_deflate
Tile stream is one raw-DEFLATE run.
Definition jof.h:192
ra8_err_t jof_memstore_sink(void *ctx, const uint8_t *buf, size_t len)
Append len bytes to a jof_memstore_t (producer sink).
Definition jof.c:163
Import-time transcode producer: JPEG/PNG/WebP -> JOF band-tile atlas in bounded RAM (#231,...
uint32_t jof_work_bytes(uint16_t max_width, uint16_t max_height, uint16_t tile_w, uint16_t tile_h)
Compute the work-arena size the producer needs for given caps.
ra8_err_t jof_produce(const jof_produce_cfg_t *cfg, jof_info_t *out_info)
Transcode one encoded JPEG/PNG/WebP source into a JOF atlas (#231, #290).
Baked demo manga page for the ereader_manga viewer.
static const uint32_t k_mg_png_len
Length of k_mg_png in bytes.
static const uint8_t k_mg_png[]
Baked 19680-byte 1536x2048 grayscale PNG page.
Tap-driven pan/zoom viewer over a tiled manga page (ereader_manga).
bool mg_reader_tap(mg_reader_t *r, int32_t x, int32_t y)
Apply a tap: pan or toggle zoom, and report whether state changed.
Definition mg_reader.c:461
ra8_err_t mg_tile_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 callback: page one atlas tile into a cell.
Definition mg_reader.c:633
uint32_t mg_fnv1a(const void *buf, uint32_t len)
FNV-1a-32 over a byte buffer (framebuffer render hash for the banner).
Definition mg_reader.c:540
ra8_err_t mg_reader_prefetch(mg_reader_t *r)
Warm the tiles one step ahead of the last pan (predictive prefetch).
Definition mg_reader.c:349
ra8_err_t mg_reader_render(mg_reader_t *r)
Render the current viewport + chrome into the framebuffer.
Definition mg_reader.c:332
@ k_mg_statusbar_h
Top status-bar band height, panel px.
Definition mg_reader.h:55
ra8_err_t mg_reader_init(mg_reader_t *r, const mg_reader_cfg_t *cfg)
Bind a viewer to a produced atlas and reset it to 1:1 top-left.
Definition mg_reader.c:619
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_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).
@ 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
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_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
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
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_init(void *fb, uint16_t width, uint16_t height, ra8_gfx_format_t format)
Bind ra8_gfx to a caller-owned framebuffer.
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_panel_height_px
Native height (pixels).
Definition ra8_panel.h:52
@ k_panel_width_px
Native width (pixels).
Definition ra8_panel.h:51
#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
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.
Parsed + validated geometry of one JOF atlas.
Definition jof.h:208
Append-only memory store: the simplest atlas backing (RAM/SDRAM).
Definition jof.h:256
Producer configuration: source, sink, tile geometry and work arena.
Forward cursor over the baked PNG for the produce pull seam.
Definition main.c:243
const uint8_t * data
Baked PNG bytes.
Definition main.c:244
uint32_t len
Total length.
Definition main.c:245
uint32_t pos
Bytes delivered so far.
Definition main.c:246
Everything mg_reader_init needs to bind a viewer to a page.
Definition mg_reader.h:115
Viewer state: the page geometry plus the current viewport + zoom.
Definition mg_reader.h:133
Decode-on-miss context bound into the tile cache (DIP seam).
Definition mg_reader.h:101
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.
One decoded touch contact.
Definition ra8_touch.h:93
uint16_t x
Panel X coordinate.
Definition ra8_touch.h:94
uint16_t y
Panel Y coordinate.
Definition ra8_touch.h:95