|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Implementation of the touch-screen calibration utility. More...
#include "ra8_touch_cal.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "ra8_attributes.h"#include "ra8_err.h"Go to the source code of this file.
Data Structures | |
| struct | internal_lsq_sums_t |
| Accumulated least-squares sums driving the calibration solve. More... | |
Enumerations | |
| enum | mat3_idx_t : uint8_t { k_m3_00 = 0U , k_m3_01 = 1U , k_m3_02 = 2U , k_m3_10 = 3U , k_m3_11 = 4U , k_m3_12 = 5U , k_m3_20 = 6U , k_m3_21 = 7U , k_m3_22 = 8U , k_m3_len = 9U } |
| Row-major flat indices of a 3x3 matrix (a[r*3+c]). More... | |
| enum | affine_coeff_idx_t : uint8_t { k_coeff_a = 0U , k_coeff_b = 1U , k_coeff_c = 2U , k_coeff_d = 3U , k_coeff_e = 4U , k_coeff_f = 5U } |
| Affine calibration coefficient indices (a..f). More... | |
| enum | internal_const_t : uint32_t { k_internal_centre_div = 2U , k_internal_byte_mask = 0xFFU , k_internal_byte_shift_8 = 8U , k_internal_byte_shift_16 = 16U , k_internal_byte_shift_24 = 24U , k_internal_crc32_init = 0xFFFFFFFFU , k_internal_crc32_poly = 0xEDB88320U , k_internal_bits_per_byte = 8U } |
| Module-private numeric constants (no magic numbers). More... | |
Functions | |
| static void | internal_pack_le32 (uint8_t *dst, uint32_t word) |
| Pack a 32-bit little-endian word into a byte buffer. | |
| static uint32_t | internal_unpack_le32 (const uint8_t *src) |
| Unpack a 32-bit little-endian word from a byte buffer. | |
| static uint32_t | internal_float_to_u32 (float f) |
| Bitwise reinterpret a float as a uint32_t. | |
| static float | internal_u32_to_float (uint32_t w) |
| Bitwise reinterpret a uint32_t as a float. | |
| static uint32_t | internal_crc32 (const uint8_t *data, size_t len) |
| Compute the IEEE 802.3 CRC32 of a byte range. | |
| static void | internal_solve3 (const float a[k_m3_len], const float b[3], float x[3], bool *ok) |
| Solve a 3x3 system A * x = b via Cramer's rule. | |
| static int32_t | internal_clip32 (int32_t v, int32_t lo, int32_t hi) |
| Clip a value to [lo, hi]. | |
| static void | internal_accumulate_sums (const ra8_touch_cal_point_t *raw, const ra8_touch_cal_point_t *screen, uint8_t n, internal_lsq_sums_t *s) |
| Accumulate the 11 least-squares sums over n sample pairs. | |
| ra8_err_t | ra8_touch_cal_compute (const ra8_touch_cal_point_t *raw, const ra8_touch_cal_point_t *screen, uint8_t n, ra8_touch_cal_matrix_t *out_mtx) |
| Compute an affine transform from N target/sample pairs. | |
| ra8_err_t | ra8_touch_cal_run (const ra8_touch_cal_run_cfg_t *cfg, ra8_touch_cal_matrix_t *out_matrix) |
| Drive the on-screen calibration sequence and produce a matrix. | |
| ra8_err_t | ra8_touch_cal_apply (ra8_touch_cal_point_t raw, const ra8_touch_cal_matrix_t *matrix, uint16_t screen_width, uint16_t screen_height, ra8_touch_cal_point_t *out_screen) |
| Apply a calibration matrix to a single raw touch sample. | |
| ra8_err_t | ra8_touch_cal_save (const ra8_touch_cal_matrix_t *matrix, uint8_t *dst, size_t dst_size) |
| Serialise a calibration matrix to a fixed-size byte blob. | |
| ra8_err_t | ra8_touch_cal_load (const uint8_t *src, size_t src_size, ra8_touch_cal_matrix_t *out_matrix) |
| Deserialise a calibration matrix from a byte blob. | |
Variables | |
| static const float | s_min_det = 1.0e-3F |
| Floor for |det| below which the normal equations are treated as singular. | |
| static const float | s_round_bias = 0.5F |
| Round-to-nearest bias for float->int conversion. | |
Implementation of the touch-screen calibration utility.
The math here implements the weighted least-squares affine fit from Fang & Chang, "Calibration of Touch Screens for Use with Embedded Systems" (Analog Dialogue 41-08, 2007). For N raw/screen sample pairs the screen-X coefficients (a, b, c) satisfy
[ Sxx Sxy Sx ] [ a ] [ Sxu ] [ Sxy Syy Sy ] [ b ] = [ Syu ] [ Sx Sy N ] [ c ] [ Su ]
where the sums run over the N samples. The same 3x3 system with the right-hand side replaced by (Sxv, Syv, Sv) solves for the screen-Y coefficients (d, e, f). The solver is Cramer's rule on the shared coefficient matrix, which keeps the implementation branch-light and avoids dynamic allocation.
Definition in file ra8_touch_cal.c.
| enum affine_coeff_idx_t : uint8_t |
Affine calibration coefficient indices (a..f).
| Enumerator | |
|---|---|
| k_coeff_a | Coeff a. |
| k_coeff_b | Coeff b. |
| k_coeff_c | Coeff c. |
| k_coeff_d | Coeff d. |
| k_coeff_e | Coeff e. |
| k_coeff_f | Coeff f. |
Definition at line 57 of file ra8_touch_cal.c.
| enum internal_const_t : uint32_t |
Module-private numeric constants (no magic numbers).
Definition at line 70 of file ra8_touch_cal.c.
| enum mat3_idx_t : uint8_t |
Row-major flat indices of a 3x3 matrix (a[r*3+c]).
| Enumerator | |
|---|---|
| k_m3_00 | M3 00. |
| k_m3_01 | M3 01. |
| k_m3_02 | M3 02. |
| k_m3_10 | M3 10. |
| k_m3_11 | M3 11. |
| k_m3_12 | M3 12. |
| k_m3_20 | M3 20. |
| k_m3_21 | M3 21. |
| k_m3_22 | M3 22. |
| k_m3_len | M3 length. |
Definition at line 43 of file ra8_touch_cal.c.
|
static |
Accumulate the 11 least-squares sums over n sample pairs.
Pure-data helper extracted from ra8_touch_cal_compute to keep the top-level function within the NASA P10 Rule 4 cap. The arithmetic is bit-identical to the inlined original.
| [in] | raw | Raw touch samples (length n). |
| [in] | screen | Screen targets (length n). |
| [in] | n | Sample count. |
| [out] | s | Accumulated sums (zero-initialized by the helper). |
Definition at line 360 of file ra8_touch_cal.c.
References internal_lsq_sums_t::Su, internal_lsq_sums_t::Sv, internal_lsq_sums_t::Sx, internal_lsq_sums_t::Sxu, internal_lsq_sums_t::Sxv, internal_lsq_sums_t::Sxx, internal_lsq_sums_t::Sxy, internal_lsq_sums_t::Sy, internal_lsq_sums_t::Syu, internal_lsq_sums_t::Syv, and internal_lsq_sums_t::Syy.
Referenced by ra8_touch_cal_compute().
|
static |
Clip a value to [lo, hi].
See implementation.
| [in] | v | See implementation. |
| [in] | lo | See implementation. |
| [in] | hi | See implementation. |
| k_ra8_ok | Operation succeeded. |
Definition at line 298 of file ra8_touch_cal.c.
Referenced by ra8_touch_cal_apply().
|
static |
Compute the IEEE 802.3 CRC32 of a byte range.
Bit-banged so the function works without depending on ra8_crc.
| [in] | data | Input bytes. |
| [in] | len | Number of bytes. |
| k_ra8_ok | Operation succeeded. |
Definition at line 217 of file ra8_touch_cal.c.
References k_internal_bits_per_byte, k_internal_crc32_init, and k_internal_crc32_poly.
Referenced by ra8_touch_cal_load(), and ra8_touch_cal_save().
|
static |
Bitwise reinterpret a float as a uint32_t.
Implemented via memcpy to avoid strict-aliasing UB.
| [in] | f | Source float. |
| k_ra8_ok | Operation succeeded. |
Definition at line 168 of file ra8_touch_cal.c.
References memcpy().
Referenced by ra8_touch_cal_save().
|
static |
Pack a 32-bit little-endian word into a byte buffer.
| [out] | dst | Destination (4 bytes available). |
| [in] | word | Value to write. |
See implementation.
Definition at line 118 of file ra8_touch_cal.c.
References k_internal_byte_mask, k_internal_byte_shift_16, k_internal_byte_shift_24, and k_internal_byte_shift_8.
Referenced by ra8_touch_cal_save().
|
static |
Solve a 3x3 system A * x = b via Cramer's rule.
Pure float math. Degenerate (collinear) systems are flagged via the ok out-parameter rather than an error code so the call sites can fold the check into their existing return path.
| [in] | a | Row-major coefficient matrix (length 9). |
| [in] | b | Right-hand side (length 3). |
| [out] | x | Solution vector (length 3). |
| [out] | ok | Set to true on success, false if |det| < s_min_det. |
Definition at line 251 of file ra8_touch_cal.c.
References k_m3_00, k_m3_01, k_m3_02, k_m3_10, k_m3_11, k_m3_12, k_m3_20, k_m3_21, k_m3_22, k_m3_len, and s_min_det.
Referenced by ra8_touch_cal_compute().
|
static |
Bitwise reinterpret a uint32_t as a float.
| [in] | w | Source bit pattern. |
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 191 of file ra8_touch_cal.c.
References memcpy().
Referenced by ra8_touch_cal_load().
|
static |
Unpack a 32-bit little-endian word from a byte buffer.
| [in] | src | Source (4 bytes available). |
See implementation.
| k_ra8_ok | Operation succeeded. |
Definition at line 142 of file ra8_touch_cal.c.
References k_internal_byte_shift_16, k_internal_byte_shift_24, and k_internal_byte_shift_8.
Referenced by ra8_touch_cal_load().
|
nodiscard |
Apply a calibration matrix to a single raw touch sample.
Computes (u, v) = M * (x, y) + t and clips to [0, screen_width-1] x [0, screen_height-1]. The clip is necessary because least-squares fits can map slightly off-panel raw samples to negative or beyond-panel pixel coordinates.
| [in] | raw | Raw controller sample. |
| [in] | matrix | Pre-computed affine transform. |
| [in] | screen_width | Panel width in pixels (>0). |
| [in] | screen_height | Panel height in pixels (>0). |
| [out] | out_screen | Destination screen pixel. |
| k_ra8_ok | Sample mapped. |
| k_ra8_err_null_ptr | matrix or out_screen NULL. |
| k_ra8_err_invalid_arg | Panel size is zero. |
Definition at line 506 of file ra8_touch_cal.c.
References ra8_touch_cal_matrix_t::a, ra8_touch_cal_matrix_t::b, ra8_touch_cal_matrix_t::c, ra8_touch_cal_matrix_t::d, ra8_touch_cal_matrix_t::e, ra8_touch_cal_matrix_t::f, internal_clip32(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, s_round_bias, ra8_touch_cal_point_t::x, and ra8_touch_cal_point_t::y.
Referenced by internal_tc_apply_and_measure().
|
nodiscard |
Compute an affine transform from N target/sample pairs.
Pure-math entry point. Solves the 3x3 normal-equation system per axis using Cramer's rule. The function does not touch any hardware and is the workhorse exercised by the unit tests.
Algorithm (Fang & Chang, eqn. 4–7):
| [in] | raw | Array of n raw controller samples. |
| [in] | screen | Array of n corresponding screen targets. |
| [in] | n | Number of pairs (3..5). |
| [out] | out_mtx | Destination matrix. |
| k_ra8_ok | Matrix populated. |
| k_ra8_err_null_ptr | Any pointer NULL. |
| k_ra8_err_invalid_arg | n out of range or system is singular. |
Definition at line 395 of file ra8_touch_cal.c.
References ra8_touch_cal_matrix_t::a, ra8_touch_cal_matrix_t::b, ra8_touch_cal_matrix_t::c, ra8_touch_cal_matrix_t::d, ra8_touch_cal_matrix_t::e, ra8_touch_cal_matrix_t::f, internal_accumulate_sums(), internal_solve3(), k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_touch_cal_max_targets, k_ra8_touch_cal_min_targets, internal_lsq_sums_t::Su, internal_lsq_sums_t::Sv, internal_lsq_sums_t::Sx, internal_lsq_sums_t::Sxu, internal_lsq_sums_t::Sxv, internal_lsq_sums_t::Sxx, internal_lsq_sums_t::Sxy, internal_lsq_sums_t::Sy, internal_lsq_sums_t::Syu, internal_lsq_sums_t::Syv, and internal_lsq_sums_t::Syy.
Referenced by ra8_touch_cal_run().
|
nodiscard |
Deserialise a calibration matrix from a byte blob.
| [in] | src | Source buffer (non-NULL, >= blob size). |
| [in] | src_size | Bytes available in src. |
| [out] | out_matrix | Destination matrix. |
| k_ra8_ok | Blob accepted, matrix populated. |
| k_ra8_err_null_ptr | Any pointer NULL. |
| k_ra8_err_invalid_size | src_size is too small. |
| k_ra8_err_invalid_arg | Magic, version, or reserved bytes wrong. |
| k_ra8_err_crc_mismatch | CRC trailer does not match payload. |
Definition at line 576 of file ra8_touch_cal.c.
References ra8_touch_cal_matrix_t::a, ra8_touch_cal_matrix_t::b, ra8_touch_cal_matrix_t::c, ra8_touch_cal_matrix_t::d, ra8_touch_cal_matrix_t::e, ra8_touch_cal_matrix_t::f, internal_crc32(), internal_u32_to_float(), internal_unpack_le32(), k_coeff_a, k_coeff_b, k_coeff_c, k_coeff_d, k_coeff_e, k_coeff_f, k_ra8_err_crc_mismatch, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_touch_cal_blob_size, k_ra8_touch_cal_magic_b0, k_ra8_touch_cal_magic_b1, k_ra8_touch_cal_magic_b2, k_ra8_touch_cal_magic_b3, k_ra8_touch_cal_off_coeffs, k_ra8_touch_cal_off_crc32, k_ra8_touch_cal_off_magic, k_ra8_touch_cal_off_reserved, k_ra8_touch_cal_off_version, and k_ra8_touch_cal_storage_version.
Referenced by internal_tc_blob_roundtrip().
|
nodiscard |
Drive the on-screen calibration sequence and produce a matrix.
For each of the five built-in targets (4 corners inset by cfg->inset_px plus the panel centre), this function:
Once all five samples are captured, it invokes ra8_touch_cal_compute and copies the result into out_matrix.
| [in] | cfg | Configuration (non-NULL). |
| [out] | out_matrix | Destination matrix (non-NULL). |
| k_ra8_ok | Calibration matrix produced. |
| k_ra8_err_null_ptr | Any pointer or shim NULL. |
| k_ra8_err_invalid_arg | Panel size or inset implausible, or solve failed. |
| k_ra8_err_hw_error | A draw or read shim returned non-OK. |
Definition at line 450 of file ra8_touch_cal.c.
References ra8_touch_cal_run_cfg_t::draw_ctx, ra8_touch_cal_run_cfg_t::draw_target, ra8_touch_cal_run_cfg_t::inset_px, k_internal_centre_div, k_ra8_err_hw_error, k_ra8_err_invalid_arg, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_touch_cal_n_targets, ra8_touch_cal_compute(), ra8_touch_cal_run_cfg_t::read_ctx, ra8_touch_cal_run_cfg_t::read_raw, ra8_touch_cal_run_cfg_t::screen_height, and ra8_touch_cal_run_cfg_t::screen_width.
Referenced by internal_tc_run_calibration().
|
nodiscard |
Serialise a calibration matrix to a fixed-size byte blob.
Writes k_ra8_touch_cal_blob_size bytes laid out as documented in the file header. The byte order of the IEEE-754 float words is little-endian to match the Cortex-M85 native order. The blob is intended for ra8_flash page storage but the function does not touch flash itself – the caller is responsible for the actual write.
| [in] | matrix | Matrix to serialise (non-NULL). |
| [out] | dst | Destination buffer (non-NULL). |
| [in] | dst_size | Capacity of dst in bytes. |
| k_ra8_ok | Blob written. |
| k_ra8_err_null_ptr | Any pointer NULL. |
| k_ra8_err_invalid_size | dst_size < k_ra8_touch_cal_blob_size. |
Definition at line 538 of file ra8_touch_cal.c.
References ra8_touch_cal_matrix_t::a, ra8_touch_cal_matrix_t::b, ra8_touch_cal_matrix_t::c, ra8_touch_cal_matrix_t::d, ra8_touch_cal_matrix_t::e, ra8_touch_cal_matrix_t::f, internal_crc32(), internal_float_to_u32(), internal_pack_le32(), k_ra8_err_invalid_size, k_ra8_err_null_ptr, k_ra8_ok, k_ra8_touch_cal_blob_size, k_ra8_touch_cal_magic_b0, k_ra8_touch_cal_magic_b1, k_ra8_touch_cal_magic_b2, k_ra8_touch_cal_magic_b3, k_ra8_touch_cal_off_coeffs, k_ra8_touch_cal_off_crc32, k_ra8_touch_cal_off_magic, k_ra8_touch_cal_off_reserved, k_ra8_touch_cal_off_version, and k_ra8_touch_cal_storage_version.
Referenced by internal_tc_blob_roundtrip().
|
static |
Floor for |det| below which the normal equations are treated as singular.
1e-3 is chosen empirically for a 1024x600 panel: real-world raw-sample spreads produce |det| in the 1e8 .. 1e10 range, so 1e-3 only trips on truly collinear inputs.
Definition at line 93 of file ra8_touch_cal.c.
Referenced by internal_solve3().
|
static |
Round-to-nearest bias for float->int conversion.
Definition at line 96 of file ra8_touch_cal.c.
Referenced by ra8_touch_cal_apply().