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

Multi-touch input driver – GoodIX GT911 backend (implementation). More...

#include "ra8_touch.h"
#include <stddef.h>
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_i2c_bus_ops.h"
#include "ra8_icu.h"
#include "ra8_log.h"
#include "ra8_touch_gt911_regs.h"
Include dependency graph for ra8_touch.c:

Go to the source code of this file.

Data Structures

struct  ra8_touch_state_t
 Driver-private state slot. More...

Enumerations

enum  ra8_touch_internal_t : uint32_t {
  k_ra8_touch_product_id_byte0 = (uint32_t)'9' ,
  k_ra8_touch_irq_pin_count = 32U ,
  k_ra8_touch_byte_mask = 0xFFU ,
  k_ra8_touch_byte_shift = 8U
}
 Implementation-only constants (no magic numbers). More...

Functions

static void internal_pack_reg (uint16_t reg, uint8_t *out_buf)
 Pack a 16-bit GT911 register pointer into MSB-first wire order.
static ra8_err_t internal_gt911_read (uint16_t reg, uint8_t *buf, uint32_t len)
 Read len bytes from the GT911 starting at reg.
static ra8_err_t internal_gt911_write_byte (uint16_t reg, uint8_t value)
 Write a single byte value into 16-bit register reg.
static void internal_decode_one (const uint8_t *raw, ra8_touch_point_t *out)
 Decode one 8-byte GT911 point record.
static void internal_decode_block (const uint8_t *raw, uint8_t n_points, ra8_touch_point_t *out, uint8_t max_count, uint8_t *got_count)
 Decode n GT911 point records from a flat raw buffer.
static ra8_err_t internal_validate_cfg (const ra8_touch_cfg_t *cfg)
 Validate a config descriptor.
static ra8_err_t internal_attach_irq_pin (uint8_t irq_pin)
 Optional ICU IRQ-pin programming for the GT911 INT line.
static void internal_stash_state (const ra8_touch_cfg_t *cfg)
 Stash the validated config into the state slot.
static ra8_err_t internal_check_product_id (void)
 Read the GT911 product id and verify the first byte is '9'.
static ra8_err_t internal_open_finalise (const ra8_touch_cfg_t *cfg)
 Post-validate bring-up: product-id check, status ack, IRQ pin.
ra8_err_t ra8_touch_open (const ra8_touch_cfg_t *cfg)
 Bring up the touch IC over the injected I2C bus seam.
ra8_err_t ra8_touch_close (void)
 Tear the driver down and detach any registered handler.
ra8_err_t ra8_touch_attach_handler (ra8_touch_event_fn_t fn, void *ctx)
 Register a touch event callback.
void ra8_touch_dispatch_irq (void)
 Test-callable IRQ dispatch shim.
static uint8_t internal_clamp_emit (uint8_t status_byte, uint8_t max_count)
 Compute the actual number of touch records to drain.
static void internal_ack_frame (void)
 Acknowledge the current frame; ignore I2C errors.
static ra8_err_t internal_read_inner (ra8_touch_point_t *out_points, uint8_t max_count, uint8_t *got_count)
 Inner read: assumes args validated and driver opened.
ra8_err_t ra8_touch_read (ra8_touch_point_t *out_points, uint8_t max_count, uint8_t *got_count)
 Drain the current touch frame.
ra8_err_t ra8_touch_calibrate (void)
 Run any backend-specific calibration routine.

Variables

static const char * s_tag = "TOUCH"
 Log tag.
static ra8_touch_state_t s_state
 Single driver-private state slot.

Detailed Description

Multi-touch input driver – GoodIX GT911 backend (implementation).

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

GT911-specific implementation of ra8_touch.h. Speaks to the IC through the injected I2C bus seam (ra8_i2c_bus_ops_t, bound by the app – IIC_B in I2C-compat mode today, RIIC on a future board revision) using the standard "write 16-bit register pointer, RESTART, read N bytes" pattern. The driver carries no per-frame state – all touch decoding happens against caller-provided buffers.

Definition in file ra8_touch.c.

Enumeration Type Documentation

◆ ra8_touch_internal_t

enum ra8_touch_internal_t : uint32_t

Implementation-only constants (no magic numbers).

Enumerator
k_ra8_touch_product_id_byte0 

First char of "911".

k_ra8_touch_irq_pin_count 

Total ICU IRQ channels.

k_ra8_touch_byte_mask 

8-bit byte mask.

k_ra8_touch_byte_shift 

Bits per byte.

Definition at line 40 of file ra8_touch.c.

Function Documentation

◆ internal_ack_frame()

void internal_ack_frame ( void )
static

Acknowledge the current frame; ignore I2C errors.

See implementation.

Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 488 of file ra8_touch.c.

References internal_gt911_write_byte(), k_ra8_touch_gt911_cmd_clear_status, k_ra8_touch_gt911_reg_status, and RA8_INTERNAL.

Referenced by internal_read_inner().

◆ internal_attach_irq_pin()

ra8_err_t internal_attach_irq_pin ( uint8_t irq_pin)
static

Optional ICU IRQ-pin programming for the GT911 INT line.

Parameters
[in]irq_pinIRQ pin index, or k_ra8_touch_irq_pin_unset.
Returns
k_ra8_ok if the pin was either out of range (skipped) or programmed for falling-edge detection.

See implementation.

Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 282 of file ra8_touch.c.

References k_ra8_icu_fclksel_pclkb, k_ra8_icu_irqmd_falling, k_ra8_ok, k_ra8_touch_irq_pin_count, ra8_icu_configure_irq_pin(), and RA8_INTERNAL.

Referenced by internal_open_finalise().

◆ internal_check_product_id()

ra8_err_t internal_check_product_id ( void )
static

Read the GT911 product id and verify the first byte is '9'.

Issues the 4-byte PRODUCT_ID read and rejects both a failed transfer and a first byte other than ASCII '9' ("911" is the id string): either means the bus is broken or the device behind the configured address is not a GT911, so bring-up must not proceed. Both rejection legs compile on every build; the host tests drive them through a scripted-RX trampoline filled into the ra8_i2c_bus_ops_t seam.

Returns
Result code.
Return values
k_ra8_okProduct id read back and byte 0 matched.
k_ra8_err_hw_init_failedThe read transfer failed, or the product-id byte did not match.
Precondition
Module state is consistent.
The injected I2C bus seam is bound.
Postcondition
Caller-visible state matches the documented contract.
No hardware state is mutated.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 343 of file ra8_touch.c.

References internal_gt911_read(), k_ra8_err_hw_init_failed, k_ra8_ok, k_ra8_touch_gt911_id_bytes, k_ra8_touch_gt911_reg_product, k_ra8_touch_product_id_byte0, and RA8_INTERNAL.

Referenced by internal_open_finalise().

◆ internal_clamp_emit()

uint8_t internal_clamp_emit ( uint8_t status_byte,
uint8_t max_count )
static

Compute the actual number of touch records to drain.

See implementation.

Parameters
[in]status_byteSee implementation.
[in]max_countSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 464 of file ra8_touch.c.

References k_ra8_touch_gt911_status_count_mask, RA8_INTERNAL, and s_state.

Referenced by internal_read_inner().

◆ internal_decode_block()

void internal_decode_block ( const uint8_t * raw,
uint8_t n_points,
ra8_touch_point_t * out,
uint8_t max_count,
uint8_t * got_count )
static

Decode n GT911 point records from a flat raw buffer.

Parameters
[in]rawSource buffer holding n * 8 bytes.
[in]n_pointsNumber of point records present in raw.
[out]outDestination buffer.
[in]max_countCapacity of out.
[out]got_countEntries actually written.

See implementation.

Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 212 of file ra8_touch.c.

References internal_decode_one(), k_ra8_touch_gt911_max_points, k_ra8_touch_gt911_point_bytes, and RA8_INTERNAL.

Referenced by internal_read_inner().

◆ internal_decode_one()

void internal_decode_one ( const uint8_t * raw,
ra8_touch_point_t * out )
static

Decode one 8-byte GT911 point record.

Parameters
[in]rawSource buffer (8 bytes, GT911 wire format).
[out]outDecoded point.

See implementation.

Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 181 of file ra8_touch.c.

References k_ra8_touch_byte_shift, k_ra8_touch_gt911_point_off_size_lsb, k_ra8_touch_gt911_point_off_track, k_ra8_touch_gt911_point_off_x_lsb, k_ra8_touch_gt911_point_off_x_msb, k_ra8_touch_gt911_point_off_y_lsb, k_ra8_touch_gt911_point_off_y_msb, ra8_touch_point_t::pressure, RA8_INTERNAL, ra8_touch_point_t::track_id, ra8_touch_point_t::x, and ra8_touch_point_t::y.

Referenced by internal_decode_block().

◆ internal_gt911_read()

ra8_err_t internal_gt911_read ( uint16_t reg,
uint8_t * buf,
uint32_t len )
static

Read len bytes from the GT911 starting at reg.

Issues a write-then-RESTART-then-read transfer:

  • write 2 bytes (the 16-bit register pointer, MSB first),
  • read len bytes back into buf.
Parameters
[in]regStarting register address.
[out]bufDestination buffer.
[in]lenByte count.
Returns
bus.transfer return code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 121 of file ra8_touch.c.

References internal_pack_reg(), k_ra8_touch_gt911_reg_ptr_bytes, RA8_INTERNAL, and s_state.

Referenced by internal_check_product_id(), internal_i3c_reset(), and internal_read_inner().

◆ internal_gt911_write_byte()

ra8_err_t internal_gt911_write_byte ( uint16_t reg,
uint8_t value )
static

Write a single byte value into 16-bit register reg.

Parameters
[in]regRegister address.
[in]valueByte to write.
Returns
bus.write return code.

See implementation.

Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

< Payload length.

Definition at line 151 of file ra8_touch.c.

References internal_pack_reg(), k_ra8_touch_gt911_reg_ptr_bytes, RA8_INTERNAL, and s_state.

Referenced by internal_ack_frame(), and internal_open_finalise().

◆ internal_open_finalise()

ra8_err_t internal_open_finalise ( const ra8_touch_cfg_t * cfg)
static

Post-validate bring-up: product-id check, status ack, IRQ pin.

Runs against the injected bus seam already stashed in s_state. There is nothing to roll back on failure – the bus peripheral is app-owned, so the driver simply reports the error and leaves the slot unopened.

Parameters
[in]cfgSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 377 of file ra8_touch.c.

References internal_attach_irq_pin(), internal_check_product_id(), internal_gt911_write_byte(), ra8_touch_cfg_t::irq_pin, k_ra8_ok, k_ra8_touch_gt911_cmd_clear_status, k_ra8_touch_gt911_reg_status, and RA8_INTERNAL.

Referenced by ra8_touch_open().

◆ internal_pack_reg()

void internal_pack_reg ( uint16_t reg,
uint8_t * out_buf )
inlinestatic

Pack a 16-bit GT911 register pointer into MSB-first wire order.

Parameters
[in]regRegister pointer.
[out]out_bufTwo-byte destination buffer.
Precondition
out_buf is non-NULL and has at least 2 bytes of room.
Postcondition
out_buf[0] holds the high byte, out_buf[1] the low byte.

See implementation.

Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 92 of file ra8_touch.c.

References k_ra8_touch_byte_mask, k_ra8_touch_byte_shift, and RA8_INTERNAL.

Referenced by internal_gt911_read(), and internal_gt911_write_byte().

◆ internal_read_inner()

ra8_err_t internal_read_inner ( ra8_touch_point_t * out_points,
uint8_t max_count,
uint8_t * got_count )
static

Inner read: assumes args validated and driver opened.

See implementation.

Parameters
[in]out_pointsSee implementation.
[in]max_countSee implementation.
[in]got_countSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 511 of file ra8_touch.c.

References internal_ack_frame(), internal_clamp_emit(), internal_decode_block(), internal_gt911_read(), k_ra8_err_hw_error, k_ra8_ok, k_ra8_touch_gt911_max_points, k_ra8_touch_gt911_point_bytes, k_ra8_touch_gt911_reg_point0, k_ra8_touch_gt911_reg_status, and k_ra8_touch_gt911_status_ready_mask.

Referenced by ra8_touch_read().

◆ internal_stash_state()

void internal_stash_state ( const ra8_touch_cfg_t * cfg)
static

Stash the validated config into the state slot.

See implementation.

Parameters
[in]cfgSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 309 of file ra8_touch.c.

References ra8_touch_cfg_t::bus, ra8_touch_cfg_t::irq_pin, k_ra8_touch_max_points, ra8_touch_cfg_t::max_points, RA8_INTERNAL, s_state, and ra8_touch_cfg_t::target_7b.

Referenced by ra8_touch_open().

◆ internal_validate_cfg()

ra8_err_t internal_validate_cfg ( const ra8_touch_cfg_t * cfg)
static

Validate a config descriptor.

Parameters
[in]cfgNon-NULL configuration descriptor.
Returns
k_ra8_ok if valid, otherwise k_ra8_err_invalid_arg.

See implementation.

Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 253 of file ra8_touch.c.

References ra8_touch_cfg_t::bus, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_touch_gt911_addr_high, k_ra8_touch_gt911_addr_low, RA8_INTERNAL, ra8_touch_cfg_t::target_7b, ra8_i2c_bus_ops_t::transfer, and ra8_i2c_bus_ops_t::write.

Referenced by ra8_touch_open().

◆ ra8_touch_attach_handler()

ra8_err_t ra8_touch_attach_handler ( ra8_touch_event_fn_t fn,
void * ctx )
nodiscard

Register a touch event callback.

Parameters
[in]fnCallback fired on GT911 INT assertion. NULL detaches.
[in]ctxForwarded to the callback as its only argument.
Returns
ra8_err_t error code.
Return values
k_ra8_okHandler stored.
k_ra8_err_not_initializedDriver is not open.
Precondition
Driver is open.
Since
0.1.0

Definition at line 424 of file ra8_touch.c.

References k_ra8_err_not_initialized, k_ra8_ok, and s_state.

◆ ra8_touch_calibrate()

ra8_err_t ra8_touch_calibrate ( void )
nodiscard

Run any backend-specific calibration routine.

No-op for GT911 (factory-calibrated). Returns k_ra8_ok so callers can wire it unconditionally; resistive backends added later will actually drive the calibration sequence here.

Returns
k_ra8_ok unconditionally for the GT911 backend.
Since
0.1.0

Definition at line 566 of file ra8_touch.c.

References k_ra8_ok.

◆ ra8_touch_close()

ra8_err_t ra8_touch_close ( void )
nodiscard

Tear the driver down and detach any registered handler.

Returns
ra8_err_t error code.
Return values
k_ra8_okDriver closed.
k_ra8_err_not_initializedra8_touch_open was not called.
Precondition
Driver is currently open.
Postcondition
No handler is registered and the driver slot is free; the app keeps owning the bus peripheral behind the injected seam.
Since
0.1.0

Definition at line 408 of file ra8_touch.c.

References k_ra8_err_not_initialized, k_ra8_ok, and s_state.

◆ ra8_touch_dispatch_irq()

void ra8_touch_dispatch_irq ( void )

Test-callable IRQ dispatch shim.

Mirrors the ERI dispatch helper from ra8_i3c_i2c: this is the function the application's IRQ vector should call when the GT911 INT pin fires. The shim simply forwards to the registered handler.

Since
0.1.0
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.

Definition at line 434 of file ra8_touch.c.

References s_state.

◆ ra8_touch_open()

ra8_err_t ra8_touch_open ( const ra8_touch_cfg_t * cfg)
nodiscard

Bring up the touch IC over the injected I2C bus seam.

Steps:

  1. Validate cfg (non-NULL bus.write / bus.transfer, known GT911 address) and clamp max_points to k_ra8_touch_max_points.
  2. Read the GT911 PRODUCT_ID register (4 ASCII bytes) to confirm the IC is alive. If the read fails or the id does not start with '9', return k_ra8_err_hw_init_failed.
  3. Clear the GT911 status byte so the next interrupt corresponds to a fresh frame.
  4. If cfg->irq_pin is in range, configure that ICU IRQ pin for falling-edge detection.

The bus peripheral behind cfg->bus (IIC_B in I2C-compat mode at fast-mode speed today) is initialised by the app before this call, typically bound through ra8_io_i2c_bus_as_ops().

Parameters
[in]cfgConfiguration descriptor (non-NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okIC alive, driver ready.
k_ra8_err_null_ptrcfg is NULL.
k_ra8_err_invalid_argcfg->bus seam incomplete or cfg->target_7b not 0x5D/0x14.
k_ra8_err_invalid_statera8_touch_open was already called.
k_ra8_err_hw_init_failedProduct-id check failed.
Precondition
IRQs masked or single-threaded init context.
The bus peripheral behind cfg->bus is initialised.
Postcondition
On success the driver is in the open state.
Note
Not thread-safe.
Since
0.1.0

Definition at line 387 of file ra8_touch.c.

References internal_open_finalise(), internal_stash_state(), internal_validate_cfg(), k_ra8_err_invalid_state, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_info, RA8_RETURN_ON_ERROR, s_state, and s_tag.

Referenced by ra8_board_touch_open().

◆ ra8_touch_read()

ra8_err_t ra8_touch_read ( ra8_touch_point_t * out_points,
uint8_t max_count,
uint8_t * got_count )
nodiscard

Drain the current touch frame.

Sequence:

  1. bus.transfer with the 16-bit register pointer to k_ra8_touch_gt911_reg_status, reads 1 status byte.
  2. If bit7 is clear (no frame ready), set *got_count = 0 and return k_ra8_ok.
  3. Otherwise read up to min(status & 0x0F, max_count) 8-byte point records starting at k_ra8_touch_gt911_reg_point0 and decode them into out_points.
  4. Write k_ra8_touch_gt911_cmd_clear_status (0x00) into the status register so the IC can latch the next frame.
Parameters
[out]out_pointsDestination buffer (non-NULL, must hold max_count entries).
[in]max_countCapacity of out_points, in entries.
[out]got_countNumber of valid entries written.
Returns
ra8_err_t error code.
Return values
k_ra8_okFrame drained (possibly empty).
k_ra8_err_null_ptrAny pointer NULL.
k_ra8_err_invalid_argmax_count == 0.
k_ra8_err_not_initializedDriver is not open.
k_ra8_err_hw_errorI2C transport failed.
Precondition
Driver is open.
Postcondition
On success *got_count <= max_count.
Since
0.1.0

Definition at line 551 of file ra8_touch.c.

References internal_read_inner(), k_ra8_err_invalid_arg, k_ra8_err_not_initialized, RA8_CHECK_NULL_PTR, s_state, and s_tag.

Referenced by cm_poll_touch(), er_poll_touch(), ez_poll_touch(), internal_tc_read_raw(), internal_td_poll_points(), ls_poll_touch(), mg_poll_touch(), and sh_pump_input().

Variable Documentation

◆ s_state

ra8_touch_state_t s_state
static

Single driver-private state slot.

One touch IC is supported at a time. Holding state in file scope avoids handing the caller a large opaque struct.

Definition at line 69 of file ra8_touch.c.

◆ s_tag

const char* s_tag = "TOUCH"
static

Log tag.

Definition at line 34 of file ra8_touch.c.