ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_touch_cal.h File Reference

Resistive/capacitive touch-screen calibration utility. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_err.h"
Include dependency graph for ra8_touch_cal.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_touch_cal_point_t
 One (x, y) integer coordinate pair. More...
struct  ra8_touch_cal_matrix_t
 2-D affine transform screen = [a b; d e] * raw + [c; f]. More...
struct  ra8_touch_cal_run_cfg_t
 Configuration for ra8_touch_cal_run. More...

Typedefs

typedef ra8_err_t(* ra8_touch_cal_draw_target_fn_t) (void *ctx, ra8_touch_cal_point_t target)
 LCD shim: paint a cross-hair at the given pixel.
typedef ra8_err_t(* ra8_touch_cal_read_raw_fn_t) (void *ctx, ra8_touch_cal_point_t *out_raw)
 Touch shim: block until one raw touch sample is captured.

Enumerations

enum  ra8_touch_cal_limits_t : uint8_t {
  k_ra8_touch_cal_n_targets = 5U ,
  k_ra8_touch_cal_min_targets = 3U ,
  k_ra8_touch_cal_max_targets = 5U ,
  k_ra8_touch_cal_blob_size = 36U ,
  k_ra8_touch_cal_storage_version = 1U
}
 Static-allocation caps and protocol constants. More...
enum  ra8_touch_cal_layout_t : uint8_t {
  k_ra8_touch_cal_off_magic = 0U ,
  k_ra8_touch_cal_off_version = 4U ,
  k_ra8_touch_cal_off_reserved = 5U ,
  k_ra8_touch_cal_off_coeffs = 8U ,
  k_ra8_touch_cal_off_crc32 = 32U
}
 Byte-offsets inside the serialised storage blob. More...
enum  ra8_touch_cal_magic_t : uint8_t {
  k_ra8_touch_cal_magic_b0 = 0x54U ,
  k_ra8_touch_cal_magic_b1 = 0x43U ,
  k_ra8_touch_cal_magic_b2 = 0x41U ,
  k_ra8_touch_cal_magic_b3 = 0x4CU
}
 Bytes of the storage magic 'TCAL'. More...

Functions

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.

Detailed Description

Resistive/capacitive touch-screen calibration utility.

Tag
[Ring 3 / HAL] {World: NS}

ra8_touch_cal computes and applies the 2-D affine transform that maps raw touch-controller coordinates (the values reported by ra8_touch_read straight from the GT911 / FT5x06 / Atmel maXTouch silicon) onto on-screen pixel coordinates of the panel attached to ra8_lcd.

The library is hardware-agnostic: it does not include any LCD or touch-driver header. Instead, the caller supplies two function-pointer shims (Dependency Inversion, NASA Power-of-10 deviation #9 documented in CLAUDE.md):

  • draw_target_fn – paint a cross-hair at a screen coordinate.
  • read_raw_fn – block until one stable raw touch sample is captured, returning the controller-space (x, y) pair.

Algorithm:

The implementation follows the weighted-least-squares affine fit from Fang & Chang, "Calibration of Touch Screens for Use with Embedded Systems", which is itself a 2-D restatement of the Press / Teukolsky least-squares normal equations. Five target points (the four panel corners inset by an enum-defined margin plus the panel centre) are sufficient to produce a 3x3 normal- equation system that is solved per axis via Cramer's rule:

[ Sxx Sxy Sx ] [ a ]   [ Sxu ]
[ Sxy Syy Sy ] [ b ] = [ Syu ]
[ Sx  Sy  N  ] [ c ]   [ Su  ]

where (x, y) are raw touch samples, u is the screen X coordinate of the corresponding target, and N is the number of target points (here k_ra8_touch_cal_n_targets == 5). The same 3x3 system with v substituted for u solves the second row of the matrix.

Three points (k_ra8_touch_cal_n_targets reduced) would also work via a direct 3x3 inversion (Fang & Chang section 2), but the weighted 5-point fit averages out controller jitter and is the default. Three-point fitting can be exercised by passing exactly three sample pairs to ra8_touch_cal_compute().

NASA Power-of-10 deviation
The matrix coefficients are stored as IEEE-754 float and the normal-equation solve runs in float. The Cortex-M85 has a hardware FPU; using fixed-point Q15.16 here would eat two extra multiplications per pixel mapping for a worse numerical conditioning on the normal equations. The deviation is local to this module: the public ra8_touch_cal_apply API still accepts and returns integer pixel coordinates.

Storage layout for ra8_touch_cal_save / ra8_touch_cal_load:

*   offset  size  field
*   ------  ----  ------------------------------------------------
*   0       4     magic   = 'T','C','A','L' (ASCII)
*   4       1     version = ::k_ra8_touch_cal_storage_version
*   5       3     reserved (zeroed)
*   8       24    coeffs  = a..f, six little-endian IEEE-754 floats
*   32      4     crc32   = IEEE 802.3 polynomial over bytes 0..31
*   ------  ----  ------------------------------------------------
*   36 total bytes (::k_ra8_touch_cal_blob_size)
* 

Definition in file ra8_touch_cal.h.

Typedef Documentation

◆ ra8_touch_cal_draw_target_fn_t

typedef ra8_err_t(* ra8_touch_cal_draw_target_fn_t) (void *ctx, ra8_touch_cal_point_t target)

LCD shim: paint a cross-hair at the given pixel.

Parameters
[in]ctxCaller-supplied context (forwarded verbatim).
[in]targetCentre of the cross-hair, in screen pixels.
Returns
ra8_err_t – shim implementation defined; k_ra8_ok on success.

Definition at line 194 of file ra8_touch_cal.h.

◆ ra8_touch_cal_read_raw_fn_t

typedef ra8_err_t(* ra8_touch_cal_read_raw_fn_t) (void *ctx, ra8_touch_cal_point_t *out_raw)

Touch shim: block until one raw touch sample is captured.

Parameters
[in]ctxCaller-supplied context.
[out]out_rawDestination for the raw controller coordinates.
Returns
ra8_err_t – shim implementation defined; k_ra8_ok on success.

Definition at line 206 of file ra8_touch_cal.h.

Enumeration Type Documentation

◆ ra8_touch_cal_layout_t

enum ra8_touch_cal_layout_t : uint8_t

Byte-offsets inside the serialised storage blob.

Enumerator
k_ra8_touch_cal_off_magic 

Offset of 'TCAL' magic.

k_ra8_touch_cal_off_version 

Offset of version byte.

k_ra8_touch_cal_off_reserved 

Offset of 3 reserved zero bytes.

k_ra8_touch_cal_off_coeffs 

Offset of the 6-float coeff array.

k_ra8_touch_cal_off_crc32 

Offset of the CRC32 trailer.

Definition at line 111 of file ra8_touch_cal.h.

◆ ra8_touch_cal_limits_t

enum ra8_touch_cal_limits_t : uint8_t

Static-allocation caps and protocol constants.

Enumerator
k_ra8_touch_cal_n_targets 

4 corners + centre.

k_ra8_touch_cal_min_targets 

Floor for a unique solve.

k_ra8_touch_cal_max_targets 

Ceiling for the fit.

k_ra8_touch_cal_blob_size 

Bytes in ra8_touch_cal_save.

k_ra8_touch_cal_storage_version 

On-disk format version.

Definition at line 99 of file ra8_touch_cal.h.

◆ ra8_touch_cal_magic_t

enum ra8_touch_cal_magic_t : uint8_t

Bytes of the storage magic 'TCAL'.

Enumerator
k_ra8_touch_cal_magic_b0 

'T'

k_ra8_touch_cal_magic_b1 

'C'

k_ra8_touch_cal_magic_b2 

'A'

k_ra8_touch_cal_magic_b3 

'L'

Definition at line 123 of file ra8_touch_cal.h.

Function Documentation

◆ ra8_touch_cal_apply()

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 )
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.

Parameters
[in]rawRaw controller sample.
[in]matrixPre-computed affine transform.
[in]screen_widthPanel width in pixels (>0).
[in]screen_heightPanel height in pixels (>0).
[out]out_screenDestination screen pixel.
Returns
ra8_err_t error code.
Return values
k_ra8_okSample mapped.
k_ra8_err_null_ptrmatrix or out_screen NULL.
k_ra8_err_invalid_argPanel size is zero.
Precondition
matrix, out_screen non-NULL.
Postcondition
out_screen->x in [0, screen_width-1].
out_screen->y in [0, screen_height-1].
Note
Pure function. Constant-time, branch-free except for the clip.
Since
0.1.0

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().

◆ ra8_touch_cal_compute()

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 )
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):

  1. Accumulate sums Sx, Sy, Sxx, Syy, Sxy, Sxu, Syu, Su, Sxv, Syv, Sv.
  2. Compute det of the 3x3 system. Reject as k_ra8_err_invalid_arg if |det| is below ::k_ra8_touch_cal_min_det (panel-collinear targets).
  3. Solve for (a, b, c) and (d, e, f) via Cramer's rule.
Parameters
[in]rawArray of n raw controller samples.
[in]screenArray of n corresponding screen targets.
[in]nNumber of pairs (3..5).
[out]out_mtxDestination matrix.
Returns
ra8_err_t error code.
Return values
k_ra8_okMatrix populated.
k_ra8_err_null_ptrAny pointer NULL.
k_ra8_err_invalid_argn out of range or system is singular.
Precondition
raw, screen, out_mtx non-NULL.
n in [k_ra8_touch_cal_min_targets, k_ra8_touch_cal_max_targets].
Postcondition
On success out_mtx holds the affine transform.
On error out_mtx is unmodified.
Note
Pure function – no hardware access, safe from any context.
Example:
ra8_touch_cal_point_t raw[5] = { ... };
ra8_touch_cal_point_t scr[5] = { ... };
if (ra8_touch_cal_compute(raw, scr, 5, &m) == k_ra8_ok) { ... }
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
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.
2-D affine transform screen = [a b; d e] * raw + [c; f].
One (x, y) integer coordinate pair.
See also
ra8_touch_cal_run
ra8_touch_cal_apply
Since
0.1.0

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().

◆ ra8_touch_cal_load()

ra8_err_t ra8_touch_cal_load ( const uint8_t * src,
size_t src_size,
ra8_touch_cal_matrix_t * out_matrix )
nodiscard

Deserialise a calibration matrix from a byte blob.

Parameters
[in]srcSource buffer (non-NULL, >= blob size).
[in]src_sizeBytes available in src.
[out]out_matrixDestination matrix.
Returns
ra8_err_t error code.
Return values
k_ra8_okBlob accepted, matrix populated.
k_ra8_err_null_ptrAny pointer NULL.
k_ra8_err_invalid_sizesrc_size is too small.
k_ra8_err_invalid_argMagic, version, or reserved bytes wrong.
k_ra8_err_crc_mismatchCRC trailer does not match payload.
Precondition
src, out_matrix non-NULL.
src_size >= k_ra8_touch_cal_blob_size.
Postcondition
On error out_matrix is unmodified.
Since
0.1.0

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().

◆ ra8_touch_cal_run()

ra8_err_t ra8_touch_cal_run ( const ra8_touch_cal_run_cfg_t * cfg,
ra8_touch_cal_matrix_t * out_matrix )
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:

  1. Calls cfg->draw_target to paint the cross-hair.
  2. Calls cfg->read_raw to capture the user's touch.
  3. Stores the sample.

Once all five samples are captured, it invokes ra8_touch_cal_compute and copies the result into out_matrix.

Parameters
[in]cfgConfiguration (non-NULL).
[out]out_matrixDestination matrix (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okCalibration matrix produced.
k_ra8_err_null_ptrAny pointer or shim NULL.
k_ra8_err_invalid_argPanel size or inset implausible, or solve failed.
k_ra8_err_hw_errorA draw or read shim returned non-OK.
Precondition
cfg->draw_target, cfg->read_raw non-NULL.
cfg->inset_px * 2 < min(width, height).
Postcondition
On success *out_matrix is fully written.
Note
Blocks for the duration of all five touches. Caller must ensure any concurrent UI is paused.
See also
ra8_touch_cal_compute
Since
0.1.0

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().

◆ ra8_touch_cal_save()

ra8_err_t ra8_touch_cal_save ( const ra8_touch_cal_matrix_t * matrix,
uint8_t * dst,
size_t dst_size )
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.

Parameters
[in]matrixMatrix to serialise (non-NULL).
[out]dstDestination buffer (non-NULL).
[in]dst_sizeCapacity of dst in bytes.
Returns
ra8_err_t error code.
Return values
k_ra8_okBlob written.
k_ra8_err_null_ptrAny pointer NULL.
k_ra8_err_invalid_sizedst_size < k_ra8_touch_cal_blob_size.
Precondition
dst_size >= k_ra8_touch_cal_blob_size.
Postcondition
On success the first k_ra8_touch_cal_blob_size bytes of dst form a valid blob.
Note
Round-trip stable with ra8_touch_cal_load on any platform that uses IEEE-754 binary32 floats (i.e. all Cortex-M85 builds and all glibc / musl hosts).
Since
0.1.0

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().