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
42#include "book.h"
43#include "font_fixture.h"
44#include "ra8_board_ek_ra8d2.h"
45#include "ra8_boot_entry.h"
46#include "ra8_cgc.h"
47#include "ra8_err.h"
48#include "ra8_gfx.h"
49#include "ra8_isr.h"
50#include "ra8_mstp.h"
51#include "ra8_time.h"
52#include "rabook_fixture.h"
54#include "reflow.h"
55
57typedef enum : uint32_t {
58 k_erb_fb_w = 128U,
59 k_erb_fb_h = 160U,
61 k_erb_ink = 0xFF101010U,
62 k_erb_link_col = 0xFF2A52BEU,
63 k_erb_bg = 0xF4F0E8U,
65 k_erb_uart_baud = 115200U,
66 k_erb_fnv_offset = 2166136261U,
67 k_erb_fnv_prime = 16777619U,
73
75static uint16_t s_framebuffer[(size_t)k_erb_fb_h * (size_t)k_erb_fb_w];
76
79
82
83static const uint8_t k_msg_boot[] = "ereader-rabook-hil: boot\r\n";
84static const uint8_t k_msg_fail[] = "ereader-rabook-hil: FAIL init\r\n";
85static const uint8_t k_msg_berr[] = "ereader-rabook-hil: FAIL book\r\n";
86static const uint8_t k_msg_lerr[] = "ereader-rabook-hil: FAIL layout\r\n";
87static const uint8_t k_msg_pre[] = "ereader-rabook-hil: chapters=";
88static const uint8_t k_msg_ch[] = " ch";
89static const uint8_t k_msg_p[] = " p=";
90static const uint8_t k_msg_crc[] = " crc=";
91static const uint8_t k_msg_img[] = " img ";
92static const uint8_t k_msg_x[] = "x";
93static const uint8_t k_msg_g8[] = " gray8";
94static const uint8_t k_msg_ok[] = " ok\r\n";
95
97typedef enum : uint32_t {
100 k_erb_img_max_px = 96U * 48U,
102
104static void erb_print(const uint8_t* msg, uint32_t len)
105{
106 (void)ra8_board_uart_console_write(msg, (size_t)len);
107}
108
110static void erb_panic_halt(const uint8_t* msg, uint32_t len)
111{
112 erb_print(msg, len);
113 __asm__ volatile("bkpt #0");
114 while (1) {
115 __asm__ volatile("wfi");
116 }
117}
118
120static void erb_print_hex(uint32_t value)
121{
122 uint8_t buf[k_erb_hex_nibbles];
123 for (uint32_t i = 0U; i < (uint32_t)k_erb_hex_nibbles; i++) {
124 const uint32_t shift = ((uint32_t)k_erb_hex_nibbles - 1U - i) * (uint32_t)k_erb_nibble_bits;
125 const uint32_t nib = (value >> shift) & (uint32_t)k_erb_nibble_mask;
126 buf[i] =
127 (uint8_t)((nib < (uint32_t)k_erb_dec_ten) ? ('0' + nib) : ('A' + (nib - k_erb_dec_ten)));
128 }
129 erb_print(buf, (uint32_t)k_erb_hex_nibbles);
130}
131
133static void erb_print_uint(uint32_t value)
134{
135 uint8_t buf[k_erb_dec_ten];
136 uint32_t n = 0U;
137 if (value == 0U) {
138 buf[n] = '0';
139 n++;
140 }
141 while ((value > 0U) && (n < (uint32_t)k_erb_dec_ten)) {
142 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_erb_dec_ten));
143 n++;
144 value /= (uint32_t)k_erb_dec_ten;
145 }
146 for (uint32_t i = 0U; i < n; i++) {
147 erb_print(&buf[n - 1U - i], 1U);
148 }
149}
150
156static uint32_t erb_hash_fb(uint32_t seed)
157{
158 const size_t nbytes = (size_t)k_erb_fb_w * (size_t)k_erb_fb_h * sizeof(uint16_t);
159 const uint8_t* fb = (const uint8_t*)s_framebuffer;
160 uint32_t hsh = seed;
161 for (size_t i = 0U; i < nbytes; i++) {
162 hsh = (hsh ^ (uint32_t)fb[i]) * (uint32_t)k_erb_fnv_prime;
163 }
164 return hsh;
165}
166
172static uint32_t erb_render_all(uint32_t* out_hash)
173{
174 uint32_t pages = 0U;
175 (void)reflow_get_page_count(&s_engine, &pages);
176 uint32_t hsh = (uint32_t)k_erb_fnv_offset;
177 for (uint32_t p = 0U; p < pages; p++) {
178 (void)ra8_gfx_clear((uint32_t)k_erb_bg);
180 hsh = erb_hash_fb(hsh);
181 }
182 *out_hash = hsh;
183 return pages;
184}
185
187static void erb_setup_or_halt(void)
188{
189 uint32_t cpuclk0_hz = 0U;
190 if ((ra8_cgc_init() != k_ra8_ok) || (ra8_mstp_init() != k_ra8_ok)) {
191 erb_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
192 }
194 erb_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
195 }
196 if (ra8_time_init(cpuclk0_hz) != k_ra8_ok) {
197 erb_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
198 }
200 erb_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
201 }
202}
203
205static void erb_render_chapter(const void* book, uint32_t chapter_idx)
206{
207 size_t xlen = 0U;
208 if (book_chapter_to_xhtml(book, chapter_idx, s_xhtml, (size_t)k_erb_xhtml_cap, &xlen) !=
209 k_ra8_ok) {
210 erb_panic_halt(k_msg_berr, (uint32_t)sizeof(k_msg_berr) - 1U);
211 }
212 uint32_t pages = 0U;
213 if (reflow_layout_chapter(&s_engine, (const uint8_t*)s_xhtml, (uint32_t)xlen, &pages) !=
214 k_ra8_ok) {
215 erb_panic_halt(k_msg_lerr, (uint32_t)sizeof(k_msg_lerr) - 1U);
216 }
217 uint32_t hash = 0U;
218 const uint32_t rendered = erb_render_all(&hash);
219
220 erb_print(k_msg_ch, (uint32_t)sizeof(k_msg_ch) - 1U);
221 erb_print_uint(chapter_idx);
222 erb_print(k_msg_p, (uint32_t)sizeof(k_msg_p) - 1U);
223 erb_print_uint(rendered);
224 erb_print(k_msg_crc, (uint32_t)sizeof(k_msg_crc) - 1U);
225 erb_print_hex(hash);
226}
227
234static uint32_t erb_distinct_levels(const uint8_t* px, uint32_t n)
235{
236 bool seen[k_erb_level_count] = {};
237 uint32_t distinct = 0U;
238 const uint32_t lim = (n < (uint32_t)k_erb_img_max_px) ? n : (uint32_t)k_erb_img_max_px;
239 for (uint32_t i = 0U; i < lim; i++) {
240 if (!seen[px[i]]) {
241 seen[px[i]] = true;
242 distinct++;
243 }
244 }
245 return distinct;
246}
247
264static void erb_render_image(void)
265{
266 const void* img_book = (const void*)k_rabook_gray8_fixture;
267 if (book_validate(img_book, (size_t)k_rabook_gray8_fixture_len) != k_ra8_ok) {
268 erb_panic_halt(k_msg_berr, (uint32_t)sizeof(k_msg_berr) - 1U);
269 }
270 const book_header_t* hdr = book_header(img_book);
271 if (hdr->image_count == 0U) {
272 erb_panic_halt(k_msg_berr, (uint32_t)sizeof(k_msg_berr) - 1U);
273 }
274 const book_image_t* im = &book_images(img_book)[0];
275 const uint32_t npx = (uint32_t)im->width * (uint32_t)im->height;
276 /* Must be a gray8 raster (8bpp: one byte per pixel), within the scan bound. */
277 if ((im->format != (uint8_t)k_book_image_gray4) ||
278 (book_image_pixfmt(im) != k_book_pixfmt_gray8) || (im->raw_size != npx) || (npx == 0U) ||
279 (npx > (uint32_t)k_erb_img_max_px)) {
280 erb_panic_halt(k_msg_berr, (uint32_t)sizeof(k_msg_berr) - 1U);
281 }
282 /* Continuous tone survived: more than 16 distinct levels is impossible for a
283 * 4bpp store, so this proves the source was kept at full depth, not quantised. */
284 const uint8_t* px = book_image_data(img_book, im);
285 if (erb_distinct_levels(px, npx) <= (uint32_t)k_erb_gray4_levels) {
286 erb_panic_halt(k_msg_berr, (uint32_t)sizeof(k_msg_berr) - 1U);
287 }
288
289 /* Render the retained pixels straight (1 byte/pixel, no unpack) at full res. */
290 (void)ra8_gfx_clear((uint32_t)k_erb_bg);
291 (void)ra8_gfx_blit_gray8(px, (int32_t)im->width, (int32_t)im->height, 0, 0);
292
293 erb_print(k_msg_img, (uint32_t)sizeof(k_msg_img) - 1U);
294 erb_print_uint((uint32_t)im->width);
295 erb_print(k_msg_x, (uint32_t)sizeof(k_msg_x) - 1U);
296 erb_print_uint((uint32_t)im->height);
297 erb_print(k_msg_g8, (uint32_t)sizeof(k_msg_g8) - 1U);
298}
299
308void main(void)
309{
312 erb_print(k_msg_boot, (uint32_t)sizeof(k_msg_boot) - 1U);
313
314 const void* book = (const void*)k_rabook_fixture;
315 if (book_validate(book, (size_t)k_rabook_fixture_len) != k_ra8_ok) {
316 erb_panic_halt(k_msg_berr, (uint32_t)sizeof(k_msg_berr) - 1U);
317 }
318 const uint32_t chapters = book_header(book)->chapter_count;
319
321 (uint16_t)k_erb_fb_w,
322 (uint16_t)k_erb_fb_h,
324 erb_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
325 }
326 if (reflow_init((uint16_t)k_erb_fb_w,
327 (uint16_t)k_erb_fb_h,
329 (size_t)k_ahem_ttf_len,
330 (uint16_t)k_erb_font_px,
331 (uint32_t)k_erb_ink,
332 (uint32_t)k_erb_link_col,
333 &s_engine) != k_ra8_ok) {
334 erb_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
335 }
336
337 erb_print(k_msg_pre, (uint32_t)sizeof(k_msg_pre) - 1U);
338 erb_print_uint(chapters);
339 for (uint32_t ci = 0U; ci < chapters; ci++) {
340 erb_render_chapter(book, ci);
341 }
342 erb_render_image(); /* #476: render the retained full-resolution gray8 figure */
343 erb_print(k_msg_ok, (uint32_t)sizeof(k_msg_ok) - 1U);
344
345 while (1) {
346 __asm__ volatile("wfi");
347 }
348}
void main(void)
Secure fallback main entry point.
Definition main.c:37
Flat, execute-in-place container for a build-time "compiled" e-book.
static const book_image_t * book_images(const void *base)
Base of the image table.
Definition book.h:518
ra8_err_t book_chapter_to_xhtml(const void *base, uint32_t chapter_idx, char *out, size_t cap, size_t *out_len)
Serialize one chapter's DOM subtree back to XHTML for the renderer.
Definition book_xhtml.c:702
static const book_header_t * book_header(const void *base)
View the blob base as its header.
Definition book.h:382
@ k_book_image_gray4
4bpp gray, 2px/byte; pixel (x,y) is at flat index y*width + x.
Definition book.h:175
static book_image_pixfmt_t book_image_pixfmt(const book_image_t *img)
Declared pixel depth of one image descriptor.
Definition book.h:599
@ k_book_pixfmt_gray8
8bpp grayscale, 1px/byte (lossless against any grey panel).
Definition book.h:215
static const uint8_t * book_image_data(const void *base, const book_image_t *img)
Image-pool pointer to one image's compressed pixel data.
Definition book.h:566
ra8_err_t book_validate(const void *base, size_t size)
Validate that a byte buffer is a well-formed, intact .rabook blob.
Definition book.c:231
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_crc[]
Definition main.c:152
static const uint8_t k_msg_boot[]
Definition main.c:140
static const uint8_t k_msg_fail[]
Definition main.c:63
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 reflow_t s_engine
Reflow engine (glyph / page / token / text pools live inside).
Definition main.c:199
static const uint8_t k_msg_x[]
Definition main.c:85
static const uint8_t k_msg_ch[]
Definition main.c:197
static const uint8_t k_msg_lerr[]
Definition main.c:71
static const uint8_t k_msg_g8[]
Definition main.c:93
static void erb_render_chapter(const void *book, uint32_t chapter_idx)
Lay out + render one chapter; emit chN p=<pages> crc=<hash>.
Definition main.c:205
static const uint8_t k_msg_berr[]
Definition main.c:85
static uint32_t erb_distinct_levels(const uint8_t *px, uint32_t n)
Count the distinct gray8 tone levels in px[0..n) (bounded scan).
Definition main.c:234
static void erb_panic_halt(const uint8_t *msg, uint32_t len)
Print the fail banner and trap (ra8_emulator halts on the BKPT).
Definition main.c:110
static void erb_print_hex(uint32_t value)
Print a 32-bit value as 8 upper-case hex digits.
Definition main.c:120
static uint32_t erb_hash_fb(uint32_t seed)
Fold the whole RGB565 framebuffer into a running FNV-1a-32.
Definition main.c:156
static void erb_setup_or_halt(void)
Bring up clocks/MSTP/time + the SCI8 console; halt on failure.
Definition main.c:187
static void erb_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:104
erb_img_const_t
Full-resolution gray8 figure check bounds (#476).
Definition main.c:97
@ k_erb_img_max_px
Fixture image pixel cap (bounds the scan).
Definition main.c:100
@ k_erb_gray4_levels
Distinct tones a 4bpp store can ever show.
Definition main.c:98
@ k_erb_level_count
gray8 value space (presence bitmap size).
Definition main.c:99
static void erb_render_image(void)
Render the retained full-resolution gray8 figure and check it (#476).
Definition main.c:264
static const uint8_t k_msg_img[]
Definition main.c:91
static const uint8_t k_msg_p[]
Definition main.c:89
static uint32_t erb_render_all(uint32_t *out_hash)
Render every laid-out page of the current chapter; fold an FNV over it.
Definition main.c:172
erb_consts_t
Framebuffer / console / hash / buffer knobs.
Definition main.c:57
@ k_erb_bg
Page background (0x00RRGGBB).
Definition main.c:63
@ k_erb_fnv_prime
FNV-1a-32 prime.
Definition main.c:67
@ k_erb_xhtml_cap
Per-chapter serialized XHTML cap.
Definition main.c:64
@ k_erb_fb_h
Framebuffer height, pixels.
Definition main.c:59
@ k_erb_fb_w
Framebuffer width, pixels.
Definition main.c:58
@ k_erb_ink
Body ink colour (ARGB).
Definition main.c:61
@ k_erb_hex_nibbles
Hex digits in a 32-bit value.
Definition main.c:68
@ k_erb_link_col
Anchor colour (ARGB).
Definition main.c:62
@ k_erb_nibble_bits
Bits per hex nibble.
Definition main.c:69
@ k_erb_fnv_offset
FNV-1a-32 offset basis.
Definition main.c:66
@ k_erb_dec_ten
Hex digit / decimal split.
Definition main.c:71
@ k_erb_uart_baud
Console baud.
Definition main.c:65
@ k_erb_nibble_mask
Low-nibble mask.
Definition main.c:70
@ k_erb_font_px
Body font size, pixels.
Definition main.c:60
static void erb_print_uint(uint32_t value)
Print a small unsigned integer in decimal.
Definition main.c:133
static const uint8_t k_rabook_fixture[k_rabook_fixture_len]
The baked, inflated .rabook flat blob (validate + walk directly).
@ k_rabook_fixture_len
Inflated flat-blob length.
static const uint8_t k_ahem_ttf[]
Ahem TTF bytes.
static const uint32_t k_ahem_ttf_len
Length of k_ahem_ttf in bytes.
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
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.
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
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
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_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_blit_gray8(const uint8_t *src, int32_t w, int32_t h, int32_t dst_x, int32_t dst_y)
Blit an 8-bit grayscale image to a framebuffer rectangle.
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
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
@ k_rabook_gray8_fixture_len
Inflated flat-blob length.
static const uint8_t k_rabook_gray8_fixture[4785U]
Baked, inflated gray8-image .rabook blob (validate + walk).
HTML / CSS reflow + paginate engine for the ra8d2 ereader.
ra8_err_t reflow_render_page(const reflow_t *engine, uint32_t page_idx, void *framebuffer)
Render one page into the active ra8_gfx framebuffer.
ra8_err_t reflow_layout_chapter(reflow_t *engine, const uint8_t *xhtml_buf, size_t xhtml_len, uint32_t *out_total_pages)
Parse + lay out one chapter of XHTML.
ra8_err_t reflow_init(uint16_t viewport_w, uint16_t viewport_h, const uint8_t *font_data, size_t font_len, uint16_t font_px, uint32_t body_color, uint32_t link_color, reflow_t *out_engine)
Initialise a reflow engine for a given viewport / font.
ra8_err_t reflow_get_page_count(const reflow_t *engine, uint32_t *out_count)
Report the laid-out page count.
static uint8_t s_xhtml[k_sh_xhtml_cap]
Definition sh_book.c:55
Fixed 100-byte prologue describing every table and pool in the blob.
Definition book.h:246
uint32_t chapter_count
Number of spine chapters.
Definition book.h:256
uint32_t image_count
Number of image descriptors.
Definition book.h:264
Descriptor for one transcoded image in the image pool.
Definition book.h:354
uint16_t height
Pixel height.
Definition book.h:357
uint32_t raw_size
Inflated length in bytes.
Definition book.h:363
uint8_t format
book_image_format_t.
Definition book.h:358
uint16_t width
Pixel width.
Definition book.h:356
Reflow / pagination engine state.