|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
E-ink (IT8951) backend for the display PAL, wired to ra8_epaper. More...
#include "ra8_display_pal_eink.h"#include <stddef.h>#include <stdint.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_display_pal.h"#include "ra8_display_pal_internal.h"#include "ra8_epaper.h"#include "ra8_err.h"#include "ra8_log.h"Go to the source code of this file.
Data Structures | |
| struct | eink_ctx_t |
| E-ink backend context attached to the PAL handle. More... | |
Enumerations | |
| enum | ra8_display_pal_eink_const_t : uint32_t { k_eink_rgb565_bpp = 2U , k_eink_refresh_quality_us = 450000U , k_eink_line_max_px = 4096U , k_eink_luma_r = 77U , k_eink_luma_g = 150U , k_eink_luma_b = 29U , k_eink_luma_shift = 8U , k_eink_nibble_shift = 4U , k_eink_px_per_byte_4bpp = 2U , k_eink_nibble_mask = 0x0FU , k_eink_white_nibble = 0x0FU } |
| Internal numeric constants (no magic numbers). More... | |
| enum | ra8_display_pal_eink_rgb_t : uint16_t { k_eink_r5_shift = 11U , k_eink_g6_shift = 5U , k_eink_r5_mask = 0x1FU , k_eink_g6_mask = 0x3FU , k_eink_b5_mask = 0x1FU } |
| RGB565 field shifts / masks for luma extraction. More... | |
Functions | |
| uint8_t | ra8_display_pal_eink_luma_from_rgb565 (uint16_t px) |
| Convert one RGB565 pixel to an 8 bpp greyscale (Rec.601 luma). | |
| static ra8_epaper_waveform_t | internal_eink_waveform (display_refresh_hint_t hint) |
| Map a PAL refresh hint onto an IT8951 waveform mode. | |
| static ra8_err_t | internal_eink_validate_cfg (const display_cfg_t *cfg) |
| Validate the caller cfg against the e-ink backend's rules. | |
| static void | internal_eink_snapshot (const display_cfg_t *cfg) |
| Snapshot the validated cfg into s_eink_ctx. | |
| static ra8_err_t | internal_eink_check_rect (const display_caps_t *caps, display_rect_t r) |
| Confirm a rectangle stays inside the active framebuffer. | |
| static void | internal_eink_pack_row_4bpp (const uint16_t *src, uint16_t width) |
| Pack one RGB565 span into s_eink_line as 4 bpp greyscale. | |
| static ra8_err_t | internal_eink_load_rect (const eink_ctx_t *c, display_rect_t rect) |
| Convert + stream each row of rect into the IT8951 frame RAM. | |
| static ra8_err_t | internal_eink_init (const display_cfg_t *cfg, void **out_ctx) |
| E-ink backend init – validate, bring up the IT8951, snapshot. | |
| static ra8_err_t | internal_eink_get_caps (const void *ctx, display_caps_t *out) |
| Vtable get_caps – O(1) copy from s_eink_ctx.caps. | |
| static ra8_err_t | internal_eink_get_framebuffer (void *ctx, display_fb_t *out) |
| Vtable get_framebuffer – hand back the RGB565 FB descriptor. | |
| static ra8_err_t | internal_eink_flush (void *ctx, display_rect_t rect, display_refresh_hint_t hint) |
| Vtable flush – convert rect to 8bpp and refresh the panel. | |
| static ra8_err_t | internal_eink_clear (void *ctx, uint32_t color) |
| Vtable clear – fill the RGB565 framebuffer with color. | |
| static ra8_err_t | internal_eink_deinit (void *ctx) |
| Vtable deinit – sleep the panel and drop state. | |
Variables | |
| static const char *const | s_tag = "ra8_display_pal_eink" |
| Module log tag. | |
| static eink_ctx_t | s_eink_ctx |
| Single e-ink backend context. | |
| static uint8_t | s_eink_line [k_eink_line_max_px] |
| Bounded RGB565 -> 4 bpp conversion scratch (one panel row). | |
| const display_backend_iface_t | k_display_backend_eink_it8951 |
| E-ink (IT8951) backend vtable. | |
E-ink (IT8951) backend for the display PAL, wired to ra8_epaper.
Drives an IT8951-compatible e-paper panel through the HAL driver libs/ra8_hal/src/ra8_epaper.c. The app keeps painting the same canonical RGB565 framebuffer it uses on the LCD backend; this backend converts each flushed rectangle to the IT8951's native 8 bpp greyscale (Rec.601 luma) on the way to the controller, then triggers a panel update with the waveform mapped from the caller's display_refresh_hint_t.
The IT8951 hardware descriptor (injected SPI bus seam, reset+busy GPIO, native panel size) is not hard-coded here – it is supplied by the board BSP through display_cfg_t.panel_timing as a const ra8_epaper_cfg_t* (the same opaque-config seam the GLCDC backend uses for its ra8_glcdc_timing_t). This keeps the PAL accessory-agnostic: the BSP owns the SPI peripheral and binds the seam (typically via ra8_io_spi_bus_as_ops()).
Conversion is streamed one framebuffer row at a time through a bounded static line buffer (s_eink_line), so no full-panel 8 bpp shadow buffer is needed regardless of panel size (NASA P10 Rule 3: no unbounded allocation). On-panel HIL validation needs an IT8951 panel on the bench; the vtable + conversion are host-verified against the fake-backed ra8_epaper (see tests/graphics/src/test_ra8_display_pal.c).
Definition in file ra8_display_pal_eink.c.
| enum ra8_display_pal_eink_const_t : uint32_t |
Internal numeric constants (no magic numbers).
Definition at line 73 of file ra8_display_pal_eink.c.
| enum ra8_display_pal_eink_rgb_t : uint16_t |
RGB565 field shifts / masks for luma extraction.
| Enumerator | |
|---|---|
| k_eink_r5_shift | Red field shift in RGB565. |
| k_eink_g6_shift | Green field shift in RGB565. |
| k_eink_r5_mask | 5-bit red mask. |
| k_eink_g6_mask | 6-bit green mask. |
| k_eink_b5_mask | 5-bit blue mask. |
Definition at line 93 of file ra8_display_pal_eink.c.
|
static |
Confirm a rectangle stays inside the active framebuffer.
Split into four simple decisions so MC/DC stays trivial.
| [in] | caps | Backend capabilities. |
| [in] | r | Candidate rectangle. |
| k_ra8_ok | Rectangle fits. |
| k_ra8_err_invalid_arg | Rectangle steps out of bounds. |
Definition at line 280 of file ra8_display_pal_eink.c.
References display_rect_t::h, display_caps_t::height_px, k_ra8_err_invalid_arg, k_ra8_ok, display_rect_t::w, display_caps_t::width_px, display_rect_t::x, and display_rect_t::y.
Referenced by internal_eink_flush().
|
static |
Vtable clear – fill the RGB565 framebuffer with color.
Per the PAL contract display_clear only writes the framebuffer; it does not push to the panel (the caller follows with display_flush). So this mirrors the LCD backend: a tight RGB565 fill loop.
| [in] | ctx | Backend context. |
| [in] | color | Pixel value (low 16 bits used as RGB565). |
| k_ra8_ok | Buffer cleared. |
| k_ra8_err_null_ptr | ctx was NULL. |
Definition at line 592 of file ra8_display_pal_eink.c.
References eink_ctx_t::fb, display_fb_t::height_px, k_ra8_ok, display_fb_t::pixels, RA8_CHECK_NULL_PTR, s_tag, and display_fb_t::width_px.
|
static |
Vtable deinit – sleep the panel and drop state.
Issues ra8_epaper_sleep (which returns the driver to its uninitialised state so a fresh internal_eink_init works), then clears the context.
| [in] | ctx | Backend context. |
| k_ra8_ok | Panel asleep; state dropped. |
| k_ra8_err_null_ptr | ctx was NULL. |
| (from | ra8_epaper) Forwarded sleep failure. |
Definition at line 630 of file ra8_display_pal_eink.c.
References eink_ctx_t::fb, eink_ctx_t::initialised, display_fb_t::pixels, RA8_CHECK_NULL_PTR, ra8_epaper_sleep(), and s_tag.
|
static |
Vtable flush – convert rect to 8bpp and refresh the panel.
Bounds-checks rect, streams the converted rows into the IT8951 frame RAM (internal_eink_load_rect), then issues one ra8_epaper_display_area with the waveform mapped from hint.
| [in] | ctx | Backend context. |
| [in] | rect | Region of the framebuffer to push. |
| [in] | hint | Refresh-mode intent (selects the waveform). |
| k_ra8_ok | Region pushed and refreshed. |
| k_ra8_err_null_ptr | ctx was NULL. |
| k_ra8_err_invalid_arg | rect leaves the framebuffer. |
| (from | ra8_epaper) Forwarded load / display failure. |
Definition at line 551 of file ra8_display_pal_eink.c.
References eink_ctx_t::caps, display_rect_t::h, internal_eink_check_rect(), internal_eink_load_rect(), internal_eink_waveform(), k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_epaper_display_area(), s_tag, display_rect_t::w, display_rect_t::x, and display_rect_t::y.
|
static |
Vtable get_caps – O(1) copy from s_eink_ctx.caps.
Caps were snapshotted from cfg at init time.
| [in] | ctx | Backend context. |
| [out] | out | Capabilities snapshot. |
| k_ra8_ok | Caps written. |
| k_ra8_err_null_ptr | Either argument was NULL. |
Definition at line 482 of file ra8_display_pal_eink.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
|
static |
Vtable get_framebuffer – hand back the RGB565 FB descriptor.
The app paints this canonical RGB565 buffer; flush converts it to the panel's native depth. Same pointer the caller passed via cfg.
| [in] | ctx | Backend context. |
| [out] | out | Framebuffer descriptor. |
| k_ra8_ok | Descriptor written. |
| k_ra8_err_null_ptr | Either argument was NULL. |
Definition at line 515 of file ra8_display_pal_eink.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
|
static |
E-ink backend init – validate, bring up the IT8951, snapshot.
Vtable entry for k_display_backend_eink_it8951. Validates the cfg, then brings up the panel via ra8_epaper_init using the BSP-supplied ra8_epaper_cfg_t carried in cfg->panel_timing, and snapshots geometry for the O(1) accessors.
| [in] | cfg | Caller configuration. |
| [out] | out_ctx | Filled with the backend context pointer. |
| k_ra8_ok | Backend ready. |
| k_ra8_err_null_ptr | cfg / out_ctx / framebuffer NULL. |
| k_ra8_err_invalid_arg | Dimensions / descriptor invalid. |
| k_ra8_err_not_supported | Pixel format not RGB565. |
| k_ra8_err_busy | Backend already initialised. |
| (from | ra8_epaper_init) Panel bring-up failure. |
Definition at line 437 of file ra8_display_pal_eink.c.
References internal_eink_snapshot(), internal_eink_validate_cfg(), k_ra8_err_busy, k_ra8_ok, display_cfg_t::panel_timing, RA8_CHECK_NULL_PTR, ra8_epaper_init(), ra8_log_error, ra8_log_info, s_eink_ctx, and s_tag.
|
static |
Convert + stream each row of rect into the IT8951 frame RAM.
For every framebuffer row in rect: pack the RGB565 span to 4 bpp greyscale in the bounded s_eink_line buffer, then ra8_epaper_load_image that 1-row sub-area (the controller places it via the area's x/y). The byte count comes from ra8_epaper_image_bytes rather than being recomputed here, so the PAL's packing and the driver's expectation cannot drift apart. The panel is refreshed once by the caller after all rows are loaded.
| [in] | c | Backend context (validated). |
| [in] | rect | Region to push (already bounds-checked). |
| k_ra8_ok | All rows loaded into frame RAM. |
| (from | ra8_epaper) Forwarded from ra8_epaper_image_bytes or ra8_epaper_load_image. |
Definition at line 373 of file ra8_display_pal_eink.c.
References eink_ctx_t::fb, display_rect_t::h, internal_eink_pack_row_4bpp(), k_ra8_epaper_endian_little, k_ra8_epaper_pf_4bpp, k_ra8_ok, display_fb_t::pixels, ra8_epaper_image_bytes(), ra8_epaper_load_image(), s_eink_line, display_rect_t::w, display_fb_t::width_px, display_rect_t::x, and display_rect_t::y.
Referenced by internal_eink_flush().
|
static |
Pack one RGB565 span into s_eink_line as 4 bpp greyscale.
Converts each pixel to 8 bpp Rec.601 luma, keeps its high nibble, and packs two pixels per byte – first pixel in the high nibble. An odd trailing pixel is paired with white so the row still ends on a byte boundary, which is what the controller's row stride assumes.
4 bpp is the panel's real depth: it renders 16 grey levels and the IT8951 discards the low nibble of 8 bpp data anyway, so this halves the bytes on the wire at no optical cost.
| [in] | src | First RGB565 pixel of the row; non-NULL, width long. |
| [in] | width | Pixels to convert; 1 .. k_eink_line_max_px. |
Definition at line 325 of file ra8_display_pal_eink.c.
References k_eink_nibble_mask, k_eink_nibble_shift, k_eink_px_per_byte_4bpp, k_eink_white_nibble, ra8_display_pal_eink_luma_from_rgb565(), and s_eink_line.
Referenced by internal_eink_load_rect().
|
static |
Snapshot the validated cfg into s_eink_ctx.
Records geometry, the RGB565 framebuffer pointer, and the known GC16 latency so get_caps / get_framebuffer are O(1) reads.
| [in] | cfg | Validated caller configuration. |
Definition at line 239 of file ra8_display_pal_eink.c.
References display_cfg_t::framebuffer, display_cfg_t::height_px, k_display_pixfmt_rgb565, k_eink_refresh_quality_us, k_eink_rgb565_bpp, s_eink_ctx, and display_cfg_t::width_px.
Referenced by internal_eink_init().
|
static |
Validate the caller cfg against the e-ink backend's rules.
Same canonical-format rules as the LCD backend, plus: the BSP must supply the IT8951 descriptor through panel_timing, and the framebuffer width must fit the bounded conversion line buffer.
| [in] | cfg | Caller configuration (non-NULL; checked by caller). |
| k_ra8_ok | Cfg accepted. |
| k_ra8_err_null_ptr | framebuffer was NULL. |
| k_ra8_err_invalid_arg | Dimensions / buffer / descriptor invalid. |
| k_ra8_err_not_supported | Pixel format not RGB565. |
Definition at line 196 of file ra8_display_pal_eink.c.
References display_cfg_t::framebuffer, display_cfg_t::framebuffer_bytes, display_cfg_t::height_px, k_display_pixfmt_rgb565, k_eink_line_max_px, k_eink_rgb565_bpp, k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_ok, display_cfg_t::panel_timing, display_cfg_t::pixfmt, RA8_CHECK_NULL_PTR, s_tag, and display_cfg_t::width_px.
Referenced by internal_eink_init().
|
static |
Map a PAL refresh hint onto an IT8951 waveform mode.
fast -> A2 (1bpp, fastest), quality -> GC16 (16-grey, cleanest), init -> the full INIT flush-to-white.
| [in] | hint | Caller refresh intent. |
| k_ra8_epaper_wf_a2 | For k_display_refresh_fast. |
| k_ra8_epaper_wf_gc16 | For k_display_refresh_quality / default. |
Definition at line 159 of file ra8_display_pal_eink.c.
References k_display_refresh_fast, k_display_refresh_init, k_ra8_epaper_wf_a2, k_ra8_epaper_wf_gc16, and k_ra8_epaper_wf_init.
Referenced by internal_eink_flush().
| uint8_t ra8_display_pal_eink_luma_from_rgb565 | ( | uint16_t | px | ) |
Convert one RGB565 pixel to an 8 bpp greyscale (Rec.601 luma).
Internal-but-exposed so host unit tests can pin the conversion the e-ink flush path relies on. Expands the 5/6/5 channels to 8 bits by bit-replication, then applies the integer Rec.601 weights (77/150/29, /256). Pure white maps to 255 and pure black to 0.
| [in] | px | Source pixel in RGB565 (little-endian field layout). |
| 0 | For px == 0x0000 (black). |
| 255 | For px == 0xFFFF (white). |
Definition at line 122 of file ra8_display_pal_eink.c.
References k_eink_b5_mask, k_eink_g6_mask, k_eink_g6_shift, k_eink_luma_b, k_eink_luma_g, k_eink_luma_r, k_eink_luma_shift, k_eink_r5_mask, and k_eink_r5_shift.
Referenced by internal_eink_pack_row_4bpp().
| const display_backend_iface_t k_display_backend_eink_it8951 |
E-ink (IT8951) backend vtable.
init brings up the IT8951 over SPI via ra8_epaper_init (using the ra8_epaper_cfg_t supplied in display_cfg_t.panel_timing); get_framebuffer hands back the app's RGB565 buffer; flush converts the dirty rectangle to 8 bpp luma and refreshes the panel; clear fills the framebuffer; deinit sleeps the panel.
Definition at line 645 of file ra8_display_pal_eink.c.
Referenced by main().
|
static |
Single e-ink backend context.
Definition at line 65 of file ra8_display_pal_eink.c.
Referenced by internal_eink_init(), and internal_eink_snapshot().
|
static |
Bounded RGB565 -> 4 bpp conversion scratch (one panel row).
Sized for a full-width row at 8 bpp even though the flush path packs at 4 bpp, so the buffer stays correct if a future caller needs the wider depth. At 4 bpp only the first ceil(width / 2) bytes are used.
Definition at line 115 of file ra8_display_pal_eink.c.
Referenced by internal_eink_load_rect(), and internal_eink_pack_row_4bpp().
|
static |
Module log tag.
Definition at line 50 of file ra8_display_pal_eink.c.