ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_epaper.c
Go to the documentation of this file.
1
29
30#include "ra8_epaper.h"
31
32#include <stddef.h>
33#include <stdint.h>
34
35#include "ra8_attributes.h"
36#include "ra8_check.h"
37#include "ra8_err.h"
38#include "ra8_hw_err.h"
39#include "ra8_log.h"
40#include "ra8_port_regs.h"
41#include "ra8_port_utils.h"
42#include "ra8_spi_bus_ops.h"
43#include "ra8_time.h"
44
49static const char* s_tag = "EPAPER";
50
51/* =============================================================================
52 * Constants -- typed enums per the no-magic-number rule.
53 * =============================================================================
54 */
55
65
84
95typedef enum : uint16_t {
99
109
126
153
162
189
195
196/* =============================================================================
197 * Low-level SPI helpers
198 * =============================================================================
199 */
200
212[[nodiscard]] static ra8_err_t internal_ra8_epaper_send16(uint16_t word)
213{
214 const ra8_spi_bus_ops_t* bus = &s_panel.cfg.bus;
215 uint8_t hi =
216 (uint8_t)((word >> (uint16_t)k_ra8_epaper_byte_shift) & (uint16_t)k_ra8_epaper_byte_mask);
217 uint8_t lo = (uint8_t)(word & (uint16_t)k_ra8_epaper_byte_mask);
218 uint8_t rx = 0U;
219 ra8_err_t err = bus->xfer8(bus->ctx, hi, &rx);
220 if (err != k_ra8_ok) {
221 return err;
222 }
223 return bus->xfer8(bus->ctx, lo, &rx);
224}
225
237[[nodiscard]] static ra8_err_t internal_ra8_epaper_recv16(uint16_t* out_word)
238{
239 const ra8_spi_bus_ops_t* bus = &s_panel.cfg.bus;
240 uint8_t hi = 0U;
241 uint8_t lo = 0U;
242 ra8_err_t err = bus->xfer8(bus->ctx, (uint8_t)k_ra8_epaper_dummy_tx, &hi);
243 if (err != k_ra8_ok) {
244 return err;
245 }
246 err = bus->xfer8(bus->ctx, (uint8_t)k_ra8_epaper_dummy_tx, &lo);
247 if (err != k_ra8_ok) {
248 return err;
249 }
250 *out_word = (uint16_t)(((uint16_t)hi << (uint16_t)k_ra8_epaper_byte_shift) | (uint16_t)lo);
251 return k_ra8_ok;
252}
253
270{
271 const ra8_port_pin_t pin = (ra8_port_pin_t)s_panel.cfg.busy_pin;
272#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
273 volatile const void* hrdy_key = (volatile const void*)&ra8_port(RA8_PIN_PORT(pin))->PCNTR2;
274#endif
275 for (uint32_t i = 0U; i < (uint32_t)k_ra8_epaper_busy_poll_max; i++) {
277 bool ready = false;
278 if (ra8_gpio_read(pin, &level) == k_ra8_ok) {
279 ready = (level == k_ra8_level_high);
280 }
281#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
282 if (ra8_fake_mmio_wait_eval(hrdy_key, i, ready)) {
283 return k_ra8_ok;
284 }
285#else
286 if (ready) {
287 return k_ra8_ok;
288 }
289#endif
290 }
291 ra8_log_error(s_tag, "HRDY poll timeout");
293}
294
303[[nodiscard]] static ra8_err_t internal_ra8_epaper_write_cmd(uint16_t cmd)
304{
306 if (err != k_ra8_ok) {
307 return err;
308 }
310 if (err != k_ra8_ok) {
311 return err;
312 }
314 if (err != k_ra8_ok) {
315 return err;
316 }
317 return internal_ra8_epaper_send16(cmd);
318}
319
327[[nodiscard]] static ra8_err_t internal_ra8_epaper_write_data16(uint16_t word)
328{
330 if (err != k_ra8_ok) {
331 return err;
332 }
334 if (err != k_ra8_ok) {
335 return err;
336 }
338 if (err != k_ra8_ok) {
339 return err;
340 }
341 return internal_ra8_epaper_send16(word);
342}
343
351[[nodiscard]] static ra8_err_t internal_ra8_epaper_read_data16(uint16_t* out_word)
352{
354 if (err != k_ra8_ok) {
355 return err;
356 }
358 if (err != k_ra8_ok) {
359 return err;
360 }
362 if (err != k_ra8_ok) {
363 return err;
364 }
365 /* IT8951 inserts one dummy word after the read preamble (DS 3.4). */
366 uint16_t dummy = 0U;
367 err = internal_ra8_epaper_recv16(&dummy);
368 if (err != k_ra8_ok) {
369 return err;
370 }
371 return internal_ra8_epaper_recv16(out_word);
372}
373
386[[nodiscard]] static ra8_err_t internal_ra8_epaper_reg_write(uint16_t reg, uint16_t value)
387{
389 if (err != k_ra8_ok) {
390 return err;
391 }
393 if (err != k_ra8_ok) {
394 return err;
395 }
397}
398
407[[nodiscard]] static ra8_err_t internal_ra8_epaper_reg_read(uint16_t reg, uint16_t* value)
408{
410 if (err != k_ra8_ok) {
411 return err;
412 }
414 if (err != k_ra8_ok) {
415 return err;
416 }
418}
419
452
467{
468 uint16_t words[k_ra8_epaper_dev_info_words] = {};
470 if (err != k_ra8_ok) {
471 return err;
472 }
473 for (uint32_t i = 0U; i < (uint32_t)k_ra8_epaper_dev_info_words; i++) {
474 err = internal_ra8_epaper_read_data16(&words[i]);
475 if (err != k_ra8_ok) {
476 return err;
477 }
478 }
479 /* Buffer the whole block, then decode it in one pure pass -- the decode
480 * lives in ra8_epaper_devinfo.c so it is testable without a bus. */
482}
483
498{
499 switch (pf) {
501 return (uint16_t)k_ra8_epaper_wire_pf_2bpp;
503 return (uint16_t)k_ra8_epaper_wire_pf_4bpp;
506 default:
507 return (uint16_t)k_ra8_epaper_wire_pf_8bpp;
508 }
509}
510
522 ra8_epaper_endian_t endian)
523{
524 /* DS 4.2.7 LD_IMG_AREA argument layout:
525 * arg0 = (endian << 8) | (pf << 4) | rotate
526 * arg1..arg4 = x, y, width, height
527 */
528 const uint16_t arg0 =
529 (uint16_t)(((uint16_t)endian << (uint16_t)k_ra8_epaper_byte_shift) |
532 if (err != k_ra8_ok) {
533 return err;
534 }
536 if (err != k_ra8_ok) {
537 return err;
538 }
540 if (err != k_ra8_ok) {
541 return err;
542 }
544 if (err != k_ra8_ok) {
545 return err;
546 }
548}
549
564[[nodiscard]] static ra8_err_t internal_ra8_epaper_stream_pixels(const uint8_t* buf, size_t buf_len)
565{
566 for (size_t i = 0U; (i + 1U) < buf_len; i += 2U) {
567 const uint16_t word =
568 (uint16_t)(((uint16_t)buf[i] << (uint16_t)k_ra8_epaper_byte_shift) | (uint16_t)buf[i + 1U]);
570 if (err != k_ra8_ok) {
571 return err;
572 }
573 }
574 if ((buf_len & 1U) != 0U) {
575 const uint16_t word =
576 (uint16_t)(((uint16_t)buf[buf_len - 1U] << (uint16_t)k_ra8_epaper_byte_shift) |
577 (uint16_t)k_ra8_epaper_white_pad);
579 }
580 return k_ra8_ok;
581}
582
598 uint16_t* out_mode)
599{
600 const ra8_epaper_waveform_cfg_t* wf = &s_panel.cfg.waveform;
601 switch (waveform) {
603 *out_mode = (uint16_t)wf->init;
604 return k_ra8_ok;
606 *out_mode = (uint16_t)wf->du;
607 return k_ra8_ok;
609 *out_mode = (uint16_t)wf->gc16;
610 return k_ra8_ok;
612 *out_mode = (uint16_t)wf->a2;
613 return k_ra8_ok;
614 default:
616 }
617}
618
628 uint16_t wf_mode)
629{
631 if (err != k_ra8_ok) {
632 return err;
633 }
635 if (err != k_ra8_ok) {
636 return err;
637 }
639 if (err != k_ra8_ok) {
640 return err;
641 }
643 if (err != k_ra8_ok) {
644 return err;
645 }
646 return internal_ra8_epaper_write_data16(wf_mode);
647}
648
649/* =============================================================================
650 * Public API
651 * =============================================================================
652 */
653
655{
656 RA8_CHECK_NULL_PTR(cfg, s_tag, "epaper_init: cfg null");
657
658 if (s_panel.state != k_ra8_epaper_state_uninit) {
659 ra8_log_error(s_tag, "epaper_init: already initialized");
661 }
663 if (err != k_ra8_ok) {
664 ra8_log_error(s_tag, "epaper_init: cfg field out of range");
665 return err;
666 }
667
668 s_panel.cfg = *cfg;
669 /* A fresh controller has been given no VCOM by us, so the INV-VCOM-1
670 * permit starts revoked. Only a verified ``ra8_epaper_set_vcom`` grants
671 * it, and until then every display command is refused. */
672 s_panel.vcom_verified = false;
673 s_panel.vcom_mv = 0U;
674
677 if (err != k_ra8_ok) {
678 return err;
679 }
681 if (err != k_ra8_ok) {
682 return err;
683 }
685 if (err != k_ra8_ok) {
686 return err;
687 }
688 if (!ra8_epaper_geometry_agrees(&s_panel.info, cfg)) {
689 /* Reported geometry disagrees with the descriptor. Logged, not fatal:
690 * a controller that has not finished loading its waveform answers the
691 * first GET_DEV_INFO with zeroes, and the app may legitimately drive a
692 * sub-window of a larger panel. */
693 ra8_log_warn(s_tag, "epaper_init: GET_DEV_INFO geometry differs from cfg");
694 }
695
697 ra8_log_info(s_tag, "epaper_init ok");
698 return k_ra8_ok;
699}
700
702{
703 RA8_CHECK_NULL_PTR(out_info, s_tag, "dev_info: out null");
704 if (s_panel.state != k_ra8_epaper_state_ready) {
706 }
707 *out_info = s_panel.info;
708 return k_ra8_ok;
709}
710
711[[nodiscard]] ra8_err_t ra8_epaper_get_vcom(uint16_t* out_mv)
712{
713 RA8_CHECK_NULL_PTR(out_mv, s_tag, "get_vcom: out null");
714 if (s_panel.state != k_ra8_epaper_state_ready) {
716 }
718 if (err != k_ra8_ok) {
719 return err;
720 }
722 if (err != k_ra8_ok) {
723 return err;
724 }
725 return internal_ra8_epaper_read_data16(out_mv);
726}
727
730[[nodiscard]] ra8_err_t ra8_epaper_set_vcom(uint16_t mv)
731{
732 if (s_panel.state != k_ra8_epaper_state_ready) {
734 }
735 if (mv == 0U) {
736 ra8_log_error(s_tag, "set_vcom: refusing a zero VCOM");
738 }
739
740 /* Revoke first. Every early return below then leaves the panel
741 * un-drivable rather than trusting a half-completed write, and a second
742 * set_vcom that fails cannot leave the previous call's permit standing. */
743 s_panel.vcom_verified = false;
744 s_panel.vcom_mv = 0U;
745
747 if (err != k_ra8_ok) {
748 return err;
749 }
751 if (err != k_ra8_ok) {
752 return err;
753 }
755 if (err != k_ra8_ok) {
756 return err;
757 }
758
759 /* Read it straight back. A silently dead COPI line, a controller that
760 * NAKs the command, or a bus stuck returning zeroes all accept the write
761 * and change nothing -- a failure mode indistinguishable from success
762 * without this compare, and one that would leave the film biased at the
763 * controller's own unknown value. */
764 uint16_t readback = 0U;
765 err = ra8_epaper_get_vcom(&readback);
766 if (err != k_ra8_ok) {
767 return err;
768 }
769 if (readback != mv) {
770 ra8_log_error(s_tag, "set_vcom: readback mismatch -- panel stays dark");
772 }
773
774 s_panel.vcom_mv = mv;
775 s_panel.vcom_verified = true;
776 return k_ra8_ok;
777}
778
781[[nodiscard]] bool ra8_epaper_vcom_verified(void)
782{
783 /* Deliberately not `(state == ready) && vcom_verified`. The latch is set
784 * only by a set_vcom that ran in the ready state and is cleared by both
785 * init and sleep, so `vcom_verified` implies `state == ready` -- see the
786 * ra8_epaper_panel_t invariant. Testing the state as well would add a
787 * condition no test could ever vary independently, which is an
788 * untestable branch rather than defence in depth. */
789 return s_panel.vcom_verified;
790}
791
819 size_t buf_len,
821{
822 if (s_panel.state != k_ra8_epaper_state_ready) {
824 }
825 size_t expect = 0U;
826 const ra8_err_t serr = ra8_epaper_image_bytes(area, pf, &expect);
827 if ((serr != k_ra8_ok) || (buf_len != expect)) {
829 }
830 if (!ra8_epaper_area_is_aligned(area, pf)) {
831 ra8_log_error(s_tag, "load_image: 1bpp area violates 32px X/width alignment");
833 }
834 return k_ra8_ok;
835}
836
838 const uint8_t* buf,
839 size_t buf_len,
841 ra8_epaper_endian_t endian)
842{
843 RA8_CHECK_NULL_PTR(area, s_tag, "load_image: area null");
844 RA8_CHECK_NULL_PTR(buf, s_tag, "load_image: buf null");
845
846 const ra8_err_t verr = internal_ra8_epaper_validate_load(area, buf_len, pf);
847 if (verr != k_ra8_ok) {
848 return verr;
849 }
850
851 /* DS 4.4 -- LISAR holds the 32-bit target frame address; on a
852 * single-image driver we keep image base at 0 (the controller's
853 * default frame buffer after SYS_RUN). */
855 if (err != k_ra8_ok) {
856 return err;
857 }
859 if (err != k_ra8_ok) {
860 return err;
861 }
862
864 if (err != k_ra8_ok) {
865 return err;
866 }
867 err = internal_ra8_epaper_send_load_args(area, pf, endian);
868 if (err != k_ra8_ok) {
869 return err;
870 }
871 err = internal_ra8_epaper_stream_pixels(buf, buf_len);
872 if (err != k_ra8_ok) {
873 return err;
874 }
876}
877
903{
904#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
905 /* Not a register access: the address is only used as a fault-table key. */
906 volatile const void* lut_probe = (volatile const void*)s_panel.cfg.bus.ctx;
907#endif
908 for (uint32_t i = 0U; i < (uint32_t)k_ra8_epaper_lut_poll_max; i++) {
909 uint16_t status = (uint16_t)k_ra8_epaper_status_unset;
911 if (err != k_ra8_ok) {
912 return err;
913 }
914#if defined(RA8_OFF_TARGET) && defined(UNIT_TEST)
915 if (ra8_fake_mmio_wait_eval(lut_probe, i, (status == 0U))) {
916 return k_ra8_ok;
917 }
918#else
919 if (status == 0U) {
920 return k_ra8_ok;
921 }
922#endif
923 }
925}
926
928 ra8_epaper_waveform_t waveform)
929{
930 RA8_CHECK_NULL_PTR(area, s_tag, "display_area: area null");
931
932 if (s_panel.state != k_ra8_epaper_state_ready) {
934 }
935 /* INV-VCOM-1. DPY_AREA is the command that actually biases the film, so
936 * this is the one place the invariant has to hold. Loading pixels into
937 * frame RAM applies no bias and is deliberately left ungated -- an app
938 * may stage a full frame before calibration completes. */
939 if (!s_panel.vcom_verified) {
940 ra8_log_error(s_tag, "display_area: no verified VCOM -- refusing (INV-VCOM-1)");
942 }
943 uint16_t wf_mode = 0U;
944 ra8_err_t err = internal_ra8_epaper_resolve_waveform(waveform, &wf_mode);
945 if (err != k_ra8_ok) {
946 ra8_log_error(s_tag, "display_area: unknown waveform selector");
947 return err;
948 }
949
951 if (err != k_ra8_ok) {
952 return err;
953 }
954 err = internal_ra8_epaper_send_display_args(area, wf_mode);
955 if (err != k_ra8_ok) {
956 return err;
957 }
959}
960
961[[nodiscard]] ra8_err_t ra8_epaper_sleep(void)
962{
963 if (s_panel.state != k_ra8_epaper_state_ready) {
965 }
967 /* Whether the SLEEP command made it out or not, the controller is
968 * no longer in a defined state from the driver's perspective -- and a
969 * controller that may have dropped its VCOM must not inherit the permit
970 * across the next init. */
972 s_panel.vcom_verified = false;
973 s_panel.vcom_mv = 0U;
974 return err;
975}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
ra8_board_eth_pin_t pin
Pin.
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
static ra8_epaper_panel_t s_panel
Single-instance panel context.
Definition ra8_epaper.c:194
ra8_epaper_cmd_t
Subset of IT8951 user commands used by this driver.
Definition ra8_epaper.c:73
@ k_ra8_epaper_cmd_sys_run
Wake from standby.
Definition ra8_epaper.c:74
@ k_ra8_epaper_cmd_reg_rd
Register read.
Definition ra8_epaper.c:76
@ k_ra8_epaper_cmd_ld_img_end
End load.
Definition ra8_epaper.c:79
@ k_ra8_epaper_cmd_sleep
Enter deep-sleep.
Definition ra8_epaper.c:75
@ k_ra8_epaper_cmd_reg_wr
Register write.
Definition ra8_epaper.c:77
@ k_ra8_epaper_cmd_dpy_area
Refresh rectangle.
Definition ra8_epaper.c:80
@ k_ra8_epaper_cmd_get_dev_info
40-byte info block.
Definition ra8_epaper.c:82
@ k_ra8_epaper_cmd_ld_img_area
Begin load (rectangle).
Definition ra8_epaper.c:78
@ k_ra8_epaper_cmd_vcom
Get / set VCOM bias.
Definition ra8_epaper.c:81
ra8_err_t ra8_epaper_display_area(const ra8_epaper_area_t *area, ra8_epaper_waveform_t waveform)
Refresh the indicated rectangle on the physical panel.
Definition ra8_epaper.c:927
ra8_err_t ra8_epaper_dev_info(ra8_epaper_dev_info_t *out_info)
Hand back the GET_DEV_INFO block captured during init.
Definition ra8_epaper.c:701
ra8_epaper_wire_pf_t
LD_IMG_AREA arg0 pixel-format codes (IT8951 programming guide).
Definition ra8_epaper.c:147
@ k_ra8_epaper_wire_pf_2bpp
2 bits per pixel.
Definition ra8_epaper.c:148
@ k_ra8_epaper_wire_pf_8bpp
8 bits per pixel.
Definition ra8_epaper.c:151
@ k_ra8_epaper_wire_pf_3bpp
3 bits per pixel.
Definition ra8_epaper.c:149
@ k_ra8_epaper_wire_pf_4bpp
4 bits per pixel.
Definition ra8_epaper.c:150
ra8_epaper_preamble_t
SPI preamble words (DS chapter 3.4 table 3-3).
Definition ra8_epaper.c:60
@ k_ra8_epaper_preamble_cmd
Host -> command write.
Definition ra8_epaper.c:61
@ k_ra8_epaper_preamble_rd
Host <- data read.
Definition ra8_epaper.c:63
@ k_ra8_epaper_preamble_wr
Host -> data write.
Definition ra8_epaper.c:62
static ra8_err_t internal_ra8_epaper_send16(uint16_t word)
Send a 16-bit word MSB-first over the injected SPI bus seam.
Definition ra8_epaper.c:212
static ra8_err_t internal_ra8_epaper_read_data16(uint16_t *out_word)
Read a 16-bit data word (DS chapter 3.4).
Definition ra8_epaper.c:351
static uint16_t internal_ra8_epaper_wire_pf(ra8_epaper_pixel_format_t pf)
Map a driver pixel-format selector onto the LD_IMG_AREA wire code.
Definition ra8_epaper.c:497
static ra8_err_t internal_ra8_epaper_stream_pixels(const uint8_t *buf, size_t buf_len)
Stream a packed pixel buffer into the controller as 16-bit words.
Definition ra8_epaper.c:564
static ra8_err_t internal_ra8_epaper_write_data16(uint16_t word)
Send a 16-bit data word (DS chapter 3.4).
Definition ra8_epaper.c:327
ra8_epaper_state_t
Driver lifecycle state.
Definition ra8_epaper.c:158
@ k_ra8_epaper_state_ready
Initialized and idle.
Definition ra8_epaper.c:160
@ k_ra8_epaper_state_uninit
Not initialized yet.
Definition ra8_epaper.c:159
static ra8_err_t internal_ra8_epaper_reg_read(uint16_t reg, uint16_t *value)
Read from an IT8951 internal register.
Definition ra8_epaper.c:407
static ra8_err_t internal_ra8_epaper_write_cmd(uint16_t cmd)
Send a command code (DS chapter 3.4).
Definition ra8_epaper.c:303
ra8_err_t ra8_epaper_set_vcom(uint16_t mv)
Implementation of ra8_epaper_set_vcom() – write, then read back and compare before granting the INV-V...
Definition ra8_epaper.c:730
static ra8_err_t internal_ra8_epaper_send_load_args(const ra8_epaper_area_t *area, ra8_epaper_pixel_format_t pf, ra8_epaper_endian_t endian)
Send the LD_IMG_AREA argument block (5 words: arg0..arg4).
Definition ra8_epaper.c:520
ra8_err_t ra8_epaper_init(const ra8_epaper_cfg_t *cfg)
Bring up the IT8951 panel against the injected SPI bus seam.
Definition ra8_epaper.c:654
static ra8_err_t internal_ra8_epaper_wait_ready(void)
Block until the panel asserts HRDY.
Definition ra8_epaper.c:269
ra8_epaper_reg_t
Memory-mapped controller registers we touch.
Definition ra8_epaper.c:104
@ k_ra8_epaper_reg_lisar_hi
LISAR high half.
Definition ra8_epaper.c:106
@ k_ra8_epaper_reg_lisar_lo
LISAR low half (DS 4.4).
Definition ra8_epaper.c:105
@ k_ra8_epaper_reg_lutafsr
LUT busy status.
Definition ra8_epaper.c:107
ra8_err_t ra8_epaper_sleep(void)
Drop the panel into deep-sleep (~15 uA per Waveshare AN).
Definition ra8_epaper.c:961
static ra8_err_t internal_ra8_epaper_resolve_waveform(ra8_epaper_waveform_t waveform, uint16_t *out_mode)
Resolve a symbolic waveform selector into this panel's LUT mode.
Definition ra8_epaper.c:597
ra8_err_t ra8_epaper_get_vcom(uint16_t *out_mv)
Read the controller's current VCOM setting, in millivolts.
Definition ra8_epaper.c:711
ra8_err_t ra8_epaper_load_image(const ra8_epaper_area_t *area, const uint8_t *buf, size_t buf_len, ra8_epaper_pixel_format_t pf, ra8_epaper_endian_t endian)
Push a packed greyscale buffer into the controller's frame RAM.
Definition ra8_epaper.c:837
static ra8_err_t internal_ra8_epaper_reg_write(uint16_t reg, uint16_t value)
Write to an IT8951 internal register.
Definition ra8_epaper.c:386
static ra8_err_t internal_ra8_epaper_recv16(uint16_t *out_word)
Receive one 16-bit word MSB-first.
Definition ra8_epaper.c:237
static ra8_err_t internal_ra8_epaper_send_display_args(const ra8_epaper_area_t *area, uint16_t wf_mode)
Send the DPY_AREA argument block (5 words: x,y,w,h,wf).
Definition ra8_epaper.c:627
ra8_epaper_limits_t
Bounded retry / sizing limits.
Definition ra8_epaper.c:114
@ k_ra8_epaper_white_pad
0xFF pad for odd tail.
Definition ra8_epaper.c:122
@ k_ra8_epaper_byte_mask
Low-byte extraction mask.
Definition ra8_epaper.c:120
@ k_ra8_epaper_lut_poll_max
LUT-busy poll budget.
Definition ra8_epaper.c:116
@ k_ra8_epaper_dummy_tx
Dummy byte for SPI reads.
Definition ra8_epaper.c:121
@ k_ra8_epaper_pf_shift
LD_IMG_AREA arg0 PF shift.
Definition ra8_epaper.c:124
@ k_ra8_epaper_byte_shift
Bits per byte.
Definition ra8_epaper.c:123
@ k_ra8_epaper_dev_info_words
40-byte block / 2.
Definition ra8_epaper.c:117
@ k_ra8_epaper_status_unset
Pre-read sentinel value.
Definition ra8_epaper.c:119
@ k_ra8_epaper_reset_pulse_ms
Reset assert dwell.
Definition ra8_epaper.c:118
@ k_ra8_epaper_busy_poll_max
Outer HRDY poll budget.
Definition ra8_epaper.c:115
static ra8_err_t internal_ra8_epaper_wait_lut_idle(void)
Poll REG_LUTAFSR until the controller reports every LUT idle.
Definition ra8_epaper.c:902
static ra8_err_t internal_ra8_epaper_validate_load(const ra8_epaper_area_t *area, size_t buf_len, ra8_epaper_pixel_format_t pf)
Validate a load request's lifecycle, buffer size and geometry.
Definition ra8_epaper.c:818
static ra8_err_t internal_ra8_epaper_read_dev_info(ra8_epaper_dev_info_t *out)
Read and decode the 40-byte GET_DEV_INFO response.
Definition ra8_epaper.c:466
ra8_epaper_vcom_arg_t
Argument word selecting the direction of the VCOM command.
Definition ra8_epaper.c:95
@ k_ra8_epaper_vcom_get
Read VCOM; one word follows back.
Definition ra8_epaper.c:96
@ k_ra8_epaper_vcom_set
Write VCOM; one word follows out.
Definition ra8_epaper.c:97
bool ra8_epaper_vcom_verified(void)
Implementation of ra8_epaper_vcom_verified() – the latch alone already implies the lifecycle state.
Definition ra8_epaper.c:781
static void internal_ra8_epaper_pulse_reset(void)
Pulse the panel /RESET line low for 10 ms then back high.
Definition ra8_epaper.c:442
IT8951 e-paper controller SPI driver – public API.
ra8_epaper_pixel_format_t
Source pixel depth for a ra8_epaper_load_image transfer.
Definition ra8_epaper.h:180
@ k_ra8_epaper_pf_1bpp
1 bpp bi-level, 8 px per byte (A2).
Definition ra8_epaper.h:181
@ k_ra8_epaper_pf_4bpp
4 bpp, 2 px per byte – preferred.
Definition ra8_epaper.h:183
@ k_ra8_epaper_pf_2bpp
2 bpp, 4 px per byte.
Definition ra8_epaper.h:182
@ k_ra8_epaper_pf_8bpp
8 bpp, one byte per pixel.
Definition ra8_epaper.h:184
ra8_err_t ra8_epaper_validate_cfg(const ra8_epaper_cfg_t *cfg)
Validate a panel descriptor without touching any hardware.
ra8_epaper_waveform_t
Symbolic IT8951 panel-refresh waveform selectors.
Definition ra8_epaper.h:106
@ k_ra8_epaper_wf_init
INIT - flush to white, slowest.
Definition ra8_epaper.h:107
@ k_ra8_epaper_wf_a2
A2 - black/white only, fastest.
Definition ra8_epaper.h:110
@ k_ra8_epaper_wf_gc16
GC16 - 16-grey full quality.
Definition ra8_epaper.h:109
@ k_ra8_epaper_wf_du
DU - direct update, 1 bpp, fast.
Definition ra8_epaper.h:108
ra8_epaper_endian_t
Source-buffer endianness flag for the LD_IMG_AREA transfer.
Definition ra8_epaper.h:263
bool ra8_epaper_area_is_aligned(const ra8_epaper_area_t *area, ra8_epaper_pixel_format_t pf)
Report whether area satisfies the depth's X/width alignment.
ra8_err_t ra8_epaper_decode_dev_info(const uint16_t *words, size_t count, ra8_epaper_dev_info_t *out_info)
Decode a raw GET_DEV_INFO word block into a device-info struct.
bool ra8_epaper_geometry_agrees(const ra8_epaper_dev_info_t *info, const ra8_epaper_cfg_t *cfg)
Report whether reported panel geometry matches the descriptor.
ra8_err_t ra8_epaper_image_bytes(const ra8_epaper_area_t *area, ra8_epaper_pixel_format_t pf, size_t *out_bytes)
Bytes a packed source buffer needs for area at depth pf.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ 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
Bounded wait-flag primitives for RA8D2 HAL drivers.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_warn(tag, message)
RA8 log warn.
Definition ra8_log.h:347
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
#define ra8_log_error(tag, message)
RA8 log error.
Definition ra8_log.h:335
ra8_port_pin_t
Packed (port << 8) | pin pin identifier.
ra8_level_t
Digital output / input level.
@ k_ra8_level_high
Drive or read 1.
@ k_ra8_level_low
Drive or read 0.
#define RA8_PIN_PORT(p)
Extract the port index from a packed ra8_port_pin_t.
IOPORT (GPIO) register layout for the Renesas RA8D2.
static volatile r_port_regs_t * ra8_port(ra8_port_t port)
Get the PORT register window for a given port index.
High-level GPIO helpers on top of the PORT + PFS register layer.
ra8_err_t ra8_gpio_read(ra8_port_pin_t pin, ra8_level_t *out_level)
Read a previously-configured input.
Definition gpio.c:210
ra8_err_t ra8_gpio_write(ra8_port_pin_t pin, ra8_level_t level)
Drive a previously-configured output to the given level.
Definition gpio.c:154
Injected SPI-bus seam consumed by Ring-3 SPI device drivers.
SysTick-based tick counter, delay and timestamp helpers.
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129
volatile uint32_t PCNTR2
PCNTR2 – { EIDR[31:16], PIDR[15:0] } (read-only).
Rectangle descriptor (top-left + size) used by load + display.
Definition ra8_epaper.h:317
uint16_t x
Top-left X in panel coords (0 = left).
Definition ra8_epaper.h:318
uint16_t y
Top-left Y in panel coords (0 = top).
Definition ra8_epaper.h:319
uint16_t height
Height in pixels.
Definition ra8_epaper.h:321
uint16_t width
Width in pixels.
Definition ra8_epaper.h:320
Configuration descriptor for ra8_epaper_init.
Definition ra8_epaper.h:304
Decoded GET_DEV_INFO (0x0302) response.
Definition ra8_epaper.h:247
File-scope panel context.
Definition ra8_epaper.c:182
ra8_epaper_cfg_t cfg
Copy of init cfg.
Definition ra8_epaper.c:183
ra8_epaper_state_t state
Current lifecycle state.
Definition ra8_epaper.c:185
ra8_epaper_dev_info_t info
Decoded GET_DEV_INFO from init.
Definition ra8_epaper.c:184
uint16_t vcom_mv
Last verified VCOM magnitude, mV.
Definition ra8_epaper.c:186
bool vcom_verified
INV-VCOM-1 permit; see.
Definition ra8_epaper.c:187
Per-panel map from ra8_epaper_waveform_t onto LUT mode numbers.
Definition ra8_epaper.h:148
uint8_t init
LUT mode number for INIT (flush to white).
Definition ra8_epaper.h:149
uint8_t du
LUT mode number for DU (direct update).
Definition ra8_epaper.h:150
uint8_t a2
LUT mode number for A2 (bi-level, fastest).
Definition ra8_epaper.h:152
uint8_t gc16
LUT mode number for GC16 (16-grey quality).
Definition ra8_epaper.h:151
Caller-filled SPI transfer seam: one full-duplex byte exchange.
void * ctx
Opaque cookie handed to xfer8 (binder-owned).
ra8_err_t(* xfer8)(void *ctx, uint8_t tx, uint8_t *rx)
Full-duplex single-byte exchange on the bound bus.