|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Continuous vertical-scroll (longstrip / manhwa) reading mode over an JOF band-tile atlas (#289). More...
Go to the source code of this file.
Data Structures | |
| struct | longstrip_decode_ctx_t |
| Context binding a JOF atlas to a ::ra8_tile_cache decode-on-miss. More... | |
| struct | longstrip_cfg_t |
| One-shot configuration handed to longstrip_open. More... | |
| struct | longstrip_t |
| Opened longstrip-strip scroll state (caller-owned; treat as private). More... | |
| struct | longstrip_render_stats_t |
| Per-frame render accounting returned by longstrip_render. More... | |
Typedefs | |
| typedef ra8_err_t(* | longstrip_blit_fn) (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) |
| Composite one decoded band sub-window onto the display (DIP seam). | |
Enumerations | |
| enum | longstrip_limits_t : uint16_t { k_longstrip_max_visible_bands = 4096U , k_longstrip_max_prefetch = 8U } |
| Fixed engine bounds (NASA P10 Rule 2: every loop provably bounded). More... | |
Functions | |
| ra8_err_t | longstrip_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) |
| JOF-backed ra8_tile_decode_fn: page one band in on a cache miss. | |
| ra8_err_t | longstrip_open (longstrip_t *wt, const longstrip_cfg_t *cfg) |
| Open a longstrip strip over a parsed + validated JOF atlas. | |
| ra8_err_t | longstrip_set_viewport (longstrip_t *wt, uint16_t viewport_w, uint16_t viewport_h) |
| Resize the viewport of an open strip and re-derive the scroll clamp. | |
| int32_t | longstrip_clamp_scroll (const longstrip_t *wt, int32_t y) |
| Clamp a candidate scroll position to the strip's legal range. | |
| ra8_err_t | longstrip_band_at_y (const longstrip_t *wt, uint32_t y, uint16_t *out_band) |
Report the band index containing canvas row y. | |
| ra8_err_t | longstrip_visible_bands (const longstrip_t *wt, int32_t scroll_y, uint16_t *out_first, uint16_t *out_last) |
| Compute the inclusive visible band range for a scroll position. | |
| 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. | |
| ra8_err_t | longstrip_fling (longstrip_t *wt, int32_t v0) |
Start a momentum fling with initial velocity v0. | |
| bool | longstrip_tick (longstrip_t *wt) |
| Advance the fling one physics step (integer velocity + friction). | |
| ra8_err_t | longstrip_prefetch (longstrip_t *wt, uint16_t depth) |
| Warm the cache with bands just beyond the viewport, in scroll order. | |
| ra8_err_t | longstrip_render (longstrip_t *wt, longstrip_render_stats_t *stats) |
| Composite every visible band at the current scroll position. | |
Continuous vertical-scroll (longstrip / manhwa) reading mode over an JOF band-tile atlas (#289).
The third e-reader reading mode, beside reflowable EPUB text (reflow) and paged CBZ/manga (comic): a chapter is one continuous vertical strip – a sequence of tall image slices stacked seamlessly and read by scrolling, with no page boundaries. On RA8D2/RA8P1 there is no hardware JPEG decoder and a single slice can decode to tens of megabytes, so the strip is normalised at import into the shared JOF band-tile atlas (jof.h): a longstrip band is simply a JOF tile the full image width (tile_w == width, one tile column), so the JOF tile index is the band index – byte offset + exact height per band – giving O(1) random access to any scroll position with a single bounded read + decode. No parallel format is invented; this module is a thin scroll/geometry engine over JOF, paged through ra8_tile_cache.
The engine allocates nothing. Band pixels live in the caller's tile-cache cells (SDRAM); the atlas bytes live behind the caller's pread seam; the engine state is one caller-owned longstrip_t. The tile cache bounds the resident decoded-pixel set.
The atlas arrives from untrusted EPUB/CBZ content. longstrip_open() validates the geometry through jof_parse() and additionally rejects any atlas that is not a single full-width band column, so the O(1) band math can never index outside the grid.
Definition in file longstrip.h.
| typedef ra8_err_t(* longstrip_blit_fn) (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) |
Composite one decoded band sub-window onto the display (DIP seam).
The engine computes each visible band's destination top-left (dst_y may be negative when the band is partly scrolled off the top) and hands the caller the whole decoded band; the sink clips to the framebuffer. Production binds ra8_gfx_blit (software) or ra8_drw_blit_textured_rect (DRW-accelerated, zero-copy from SDRAM); tests bind a recording sink to prove coverage.
| [in] | ctx | Sink context (blit_ctx from the config). |
| [in] | pixels | Decoded band pixels, tightly packed row-major. |
| [in] | src_w | Band width, pixels (== canvas width). |
| [in] | src_h | Band height, pixels (clamped for the last band). |
| [in] | bpp | Bytes per pixel (1 gray8 / 3 RGB888 / 4 RGBA8888). |
| [in] | dst_x | Destination left in the framebuffer (may be negative). |
| [in] | dst_y | Destination top in the framebuffer (may be negative). |
Definition at line 114 of file longstrip.h.
| enum longstrip_limits_t : uint16_t |
Fixed engine bounds (NASA P10 Rule 2: every loop provably bounded).
k_longstrip_max_visible_bands caps the visible-band loop: a viewport can straddle at most ceil(viewport_h / 1) + 1 bands in the degenerate band_h == 1 case, but a longstrip band is hundreds of pixels tall, so this is a comfortable ceiling that also bounds the render loop independent of the untrusted band height. k_longstrip_max_prefetch caps the prefetch depth per call.
| Enumerator | |
|---|---|
| k_longstrip_max_visible_bands | Visible + render loop bound. |
| k_longstrip_max_prefetch | Max prefetch depth per call. |
Definition at line 88 of file longstrip.h.
|
nodiscard |
Report the band index containing canvas row y.
| [in] | wt | Opened strip. |
| [in] | y | Canvas row, pixels. |
| [out] | out_band | Receives the band index in [0, band_count). |
| k_ra8_ok | Band reported. |
| k_ra8_err_null_ptr | wt or out_band is NULL. |
| k_ra8_err_out_of_range | y is at/beyond canvas_h. |
wt was opened by longstrip_open. out_band is writable. Definition at line 209 of file longstrip.c.
References longstrip_t::band_h, longstrip_t::canvas_h, k_ra8_err_out_of_range, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
|
nodiscard |
Clamp a candidate scroll position to the strip's legal range.
| [in] | wt | Opened strip. |
| [in] | y | Candidate viewport-top position, pixels (may be out of range). |
| 0 | y was at/below the top, or the strip fits fully. |
| wt->max_scroll | y was at/beyond the bottom. |
wt was opened by longstrip_open. wt. Definition at line 195 of file longstrip.c.
References longstrip_t::max_scroll.
Referenced by longstrip_render(), longstrip_scroll_by(), longstrip_set_viewport(), longstrip_tick(), and longstrip_visible_bands().
|
nodiscard |
Start a momentum fling with initial velocity v0.
| [in,out] | wt | Opened strip. |
| [in] | v0 | Initial velocity, px/tick (down positive, up negative). |
| k_ra8_ok | Fling armed. |
| k_ra8_err_null_ptr | wt is NULL. |
wt was opened by longstrip_open. Definition at line 284 of file longstrip.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and longstrip_t::velocity.
|
nodiscard |
Open a longstrip strip over a parsed + validated JOF atlas.
Parses the atlas through jof_parse() and then fail-closed rejects anything that is not a single full-width band column (tile_w == width and tile_cols == 1), because the O(1) y -> band math relies on one band per row. On success the virtual-canvas geometry is cached and scroll_y/velocity are zeroed (top of strip, at rest).
| [out] | wt | Engine state to populate (need not be pre-zeroed). |
| [in] | cfg | Configuration (see the struct contract). |
| k_ra8_ok | Strip opened; positioned at the top. |
| k_ra8_err_null_ptr | wt, cfg, or a required cfg seam (pread, cache, blit) is NULL. |
| k_ra8_err_invalid_arg | viewport_w or viewport_h is zero. |
| k_ra8_err_not_supported | Atlas is not a full-width band column. |
| other | Propagated from jof_parse(). |
cfg->cache was initialised with longstrip_tile_decode over the SAME atlas cfg->pread serves. cfg->pread serves [0, cfg->atlas_size) of the atlas. Definition at line 154 of file longstrip.c.
References longstrip_cfg_t::atlas_size, internal_bind(), internal_check_ptrs(), jof_parse(), k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_ok, longstrip_cfg_t::pread, longstrip_cfg_t::pread_ctx, jof_info_t::tile_w, longstrip_cfg_t::viewport_h, longstrip_cfg_t::viewport_w, and jof_info_t::width.
Referenced by internal_wire(), and ls_open_strip().
|
nodiscard |
Warm the cache with bands just beyond the viewport, in scroll order.
Directional decode-ahead: with a non-negative velocity (or at rest) it warms up to depth bands below the visible range; with a negative velocity it warms above it. Each band is fetched and immediately released, so it becomes resident + MRU without holding a pin – the tile cache's LRU then bounds residency and reclaims stale prefetches. A reversal simply prefetches the other side on the next call, so stale-direction bands age out naturally.
| [in,out] | wt | Opened strip. |
| [in] | depth | Bands to warm ahead (clamped to k_longstrip_max_prefetch). |
| k_ra8_ok | Prefetch attempted (misses that fail to decode are skipped, not fatal – the visible render still decodes on demand). |
| k_ra8_err_null_ptr | wt is NULL. |
wt was opened by longstrip_open. wt->cache has at least one unpinned cell to spare. Definition at line 430 of file longstrip.c.
References longstrip_t::band_count, internal_warm_band(), k_longstrip_max_prefetch, k_ra8_ok, longstrip_visible_bands(), RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, and longstrip_t::velocity.
|
nodiscard |
Composite every visible band at the current scroll position.
For each band in the visible range, fetches it from the cache (decode-on-miss reads the JOF tile), computes its destination (dst_x, dst_y) – dst_x centres the column in the viewport, dst_y = band_top - scroll_y (negative for the partly-scrolled top band) – blits it through the sink, then releases the pin. Because bands are contiguous and the whole visible range is drawn, the result is seamless with no gap; stats->skipped counts any band that failed to composite and must be zero for a clean frame.
| [in,out] | wt | Opened strip. |
| [out] | stats | Receives per-frame accounting (may be NULL to ignore). |
| k_ra8_ok | Frame attempted; stats->skipped == 0 means every visible band composited (a clean, seamless frame), > 0 means a band failed to page in. |
| k_ra8_err_null_ptr | wt is NULL. |
| other | Propagated from the blit sink or the cache release (a genuine I/O failure aborts the frame). |
wt was opened by longstrip_open. Definition at line 550 of file longstrip.c.
References longstrip_t::canvas_w, internal_draw_band(), k_ra8_ok, longstrip_clamp_scroll(), longstrip_visible_bands(), RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, and longstrip_t::viewport_w.
Referenced by ls_redraw(), priv_viewer_render_jof(), and priv_viewer_tile_jof().
|
nodiscard |
Scroll by a signed pixel delta (a finger drag), clamping at the ends.
Adds delta to scroll_y and clamps. When the clamp pins the position at an end, velocity is zeroed so a fling that ran into the boundary comes to rest instead of pushing further.
| [in,out] | wt | Opened strip. |
| [in] | delta | Signed pixel delta (down positive, up negative). |
| k_ra8_ok | Position updated. |
| k_ra8_err_null_ptr | wt is NULL. |
wt was opened by longstrip_open. Definition at line 273 of file longstrip.c.
References internal_sat_add(), k_ra8_ok, longstrip_clamp_scroll(), longstrip_t::max_scroll, RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, and longstrip_t::velocity.
Referenced by internal_seek(), and ls_apply_nav().
|
nodiscard |
Resize the viewport of an open strip and re-derive the scroll clamp.
max_scroll is a function of the viewport height (canvas_h - viewport_h), so a viewport that changes after open – a resized window, or a paginated caller rendering a short final page – leaves the clamp stale. A stale clamp is not a cosmetic problem: it silently pins scroll_y short of the position the caller asked for, and the strip then composites a window it has already shown. This entry point recomputes the clamp and re-applies it to the current scroll_y so the invariant 0 <= scroll_y <= max_scroll still holds.
A paginated caller must set the viewport to the height of the page it is about to draw. For the final page of a strip whose height is not a whole multiple of the page height, that content height is exactly canvas_h - page_index * page_height, which makes the requested scroll position land exactly on the recomputed max_scroll instead of being clamped backwards into the previous page.
| [in,out] | wt | Opened strip to resize (non-NULL). |
| [in] | viewport_w | New viewport width, pixels (non-zero). |
| [in] | viewport_h | New viewport height, pixels (non-zero). |
| k_ra8_ok | Viewport applied; max_scroll re-derived. |
| k_ra8_err_null_ptr | wt is NULL. |
| k_ra8_err_invalid_arg | viewport_w or viewport_h is zero. |
wt was opened by longstrip_open. wt). Definition at line 180 of file longstrip.c.
References longstrip_t::canvas_h, k_ra8_err_invalid_arg, k_ra8_ok, longstrip_clamp_scroll(), longstrip_t::max_scroll, RA8_CHECK_NULL_PTR, s_tag, longstrip_t::scroll_y, longstrip_t::viewport_h, and longstrip_t::viewport_w.
Referenced by internal_seek().
| bool longstrip_tick | ( | longstrip_t * | wt | ) |
Advance the fling one physics step (integer velocity + friction).
Applies the current velocity to scroll_y (clamped), then decays |velocity| by one friction step toward zero. Motion stops when the velocity reaches zero OR the position pins against the end it is travelling toward. Call once per display tick until it returns false.
| [in,out] | wt | Opened strip. |
wt). | true | The fling advanced and still has velocity to run. |
| false | The fling came to rest this tick, or wt is NULL. |
wt was opened by longstrip_open. Definition at line 383 of file longstrip.c.
References internal_apply_friction(), internal_fling_should_stop(), internal_sat_add(), longstrip_clamp_scroll(), longstrip_t::scroll_y, and longstrip_t::velocity.
|
nodiscard |
JOF-backed ra8_tile_decode_fn: page one band in on a cache miss.
Adapts ::ra8_tile_cache's decode-on-miss to jof_read_tile: the tile key's (tile_x, tile_y) select the band (tile_x is always 0 for a longstrip column), and the tile is read + decoded into the cache cell in bounded RAM. Bind this as the cache's decode with a longstrip_decode_ctx_t as decode_ctx.
| [in] | ctx | A longstrip_decode_ctx_t*. |
| [in] | key | Band to decode (tile_y = band index). |
| [out] | cell | Destination cell pixels. |
| [in] | cell_bytes | Cell capacity in bytes. |
| [out] | out_w | Decoded band width, pixels. |
| [out] | out_h | Decoded band height, pixels (clamped for last band). |
| k_ra8_ok | Band decoded into cell. |
| k_ra8_err_null_ptr | ctx, key, cell, out_w or out_h is NULL. |
| other | Propagated from jof_read_tile(). |
ctx->info was parsed over ctx->pread's atlas. cell holds cell_bytes writable bytes. Definition at line 53 of file longstrip.c.
References longstrip_decode_ctx_t::info, jof_read_tile(), longstrip_decode_ctx_t::pread, longstrip_decode_ctx_t::pread_ctx, RA8_CHECK_NULL_PTR, s_tag, longstrip_decode_ctx_t::scratch, longstrip_decode_ctx_t::scratch_cap, ra8_tile_key_t::tile_x, and ra8_tile_key_t::tile_y.
Referenced by internal_wire().
|
nodiscard |
Compute the inclusive visible band range for a scroll position.
The viewport [scroll_y, scroll_y + viewport_h) intersects bands first = scroll_y / band_h through last = (bottom - 1) / band_h, with last clamped to the final band. scroll_y is clamped internally, so an out-of-range value yields the nearest legal range.
| [in] | wt | Opened strip. |
| [in] | scroll_y | Viewport-top position, pixels. |
| [out] | out_first | Receives the first visible band index. |
| [out] | out_last | Receives the last visible band index (>= first). |
| k_ra8_ok | Range reported. |
| k_ra8_err_null_ptr | wt, out_first or out_last is NULL. |
wt was opened by longstrip_open. out_first and out_last are writable. Definition at line 220 of file longstrip.c.
References longstrip_t::band_count, longstrip_t::band_h, longstrip_t::canvas_h, k_ra8_ok, longstrip_clamp_scroll(), RA8_CHECK_NULL_PTR, s_tag, and longstrip_t::viewport_h.
Referenced by longstrip_prefetch(), and longstrip_render().