ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
fdc2214.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file fdc2214.h
6 * @brief TI FDC2114/2214 capacitance-to-digital field-sensing codec (PROTOCORE_ENABLE_FDC2214).
7 *
8 * The FDC2x14 measures the resonant frequency of an external LC tank; a capacitance shift (a finger
9 * near the electrode, a liquid rising past it, a material change) moves that frequency, so watching the
10 * 28-bit conversion result gives proximity / level / material sensing without contact. Each channel's
11 * result is two 16-bit registers - a DATA MSB register whose top 4 bits are error flags and low 12 bits
12 * are the data MSB, and a DATA LSB register - which combine into the 28-bit reading. `f_sensor =
13 * data / 2^28 * f_ref`.
14 *
15 * This codec is pure and host-tested: ::protocore_fdc2214_data combines the register pair, ::protocore_fdc2214_error
16 * pulls the flags, ::protocore_fdc2214_sensor_freq_hz scales to frequency, and ::protocore_fdc2214_build_config emits a
17 * single-channel continuous-conversion bring-up as `(reg, msb, lsb)` triples. On an ESP32 the binding
18 * replays that config and reads the channel over I2C (Wire); only that touches hardware. Bridge the
19 * readings northbound like any sensor.
20 */
21
22#ifndef PROTOCORE_FDC2214_H
23#define PROTOCORE_FDC2214_H
24
25#include "protocore_config.h" // the entry point: protocore_types.h for the widths
26
27#if PROTOCORE_ENABLE_FDC2214
28
30
31// PROTOCORE_I2C_DEVICE_BORROW - the bytes this module runs out of - is stated in protocore_config.h, which sums
32// it into its arena. A caller takes them once and passes the pointer to every call. How they
33// are carved is this module's and is never named here.
34
35#define FDC2214_REG_DATA_CH0_MSB 0x00
36
37#define FDC2214_REG_DATA_CH0_LSB 0x01
38
39#define FDC2214_REG_RCOUNT_CH0 0x08
40
41#define FDC2214_REG_SETTLECOUNT_CH0 0x10
42
43#define FDC2214_REG_CLOCK_DIVIDERS_CH0 0x14
44
45#define FDC2214_REG_STATUS 0x18
46
47#define FDC2214_REG_ERROR_CONFIG 0x19
48
49#define FDC2214_REG_CONFIG 0x1A
50
51#define FDC2214_REG_MUX_CONFIG 0x1B
52
53#define FDC2214_REG_DRIVE_CURRENT_CH0 0x1E
54
55#define FDC2214_REG_MANUFACTURER_ID 0x7E
56
57#define FDC2214_REG_DEVICE_ID 0x7F
58
59#define FDC2214_MANUFACTURER_ID 0x5449 ///< "TI".
60
61#define FDC2214_DEVICE_ID 0x3055 ///< FDC2214 (the 12-bit FDC2114 reads 0x3054).
62
63#define FDC2214_CONFIG_MAX 21
64
65/** @brief What data takes: msb_reg, lsb_reg. */
66typedef struct
67{
68 uint16_t msb_reg;
69 uint16_t lsb_reg;
70} Fdc2214DataArgs;
71
72/** @brief What error takes: msb_reg. */
73typedef struct
74{
75 uint16_t msb_reg;
76} Fdc2214ErrorArgs;
77
78/** @brief What sensor_freq_hz takes: data28, fref_hz. */
79typedef struct
80{
81 uint32_t data28;
82 uint32_t fref_hz;
83} Fdc2214SensorFreqHzArgs;
84
85/** @brief What build_config takes: buf, cap, rcount, settlecount. */
86typedef struct
87{
88 uint8_t *buf;
89 size_t cap;
90 uint16_t rcount;
91 uint16_t settlecount;
92} Fdc2214BuildConfigArgs;
93
94/** @brief What begin takes: addr, rcount, settlecount. */
95typedef struct
96{
97 uint8_t addr;
98 uint16_t rcount;
99 uint16_t settlecount;
100} Fdc2214BeginArgs;
101
102/** @brief What read_ch0 takes: out. */
103typedef struct
104{
105 uint32_t *out;
106} Fdc2214ReadCh0Args;
107
108/**
109 * @brief TI FDC2114/2214 capacitance-to-digital field-sensing codec (PROTOCORE_ENABLE_FDC2214).
110 *
111 * A caller sets the members a call takes, invokes it through ::Fdc2214 with the bytes it runs
112 * out of, and reads the outcome off the same handle.
113 *
114 * Fdc2214.data_args.msb_reg = ...;
115 * Fdc2214.data_args.lsb_reg = ...;
116 * Fdc2214.data(work);
117 * // Fdc2214.value is what the call reports
118 *
119 * @var Fdc2214Ns::data_args what data takes: msb_reg, lsb_reg
120 * @var Fdc2214Ns::error_args what error takes: msb_reg
121 * @var Fdc2214Ns::sensor_freq_hz_args what sensor_freq_hz takes: data28, fref_hz
122 * @var Fdc2214Ns::build_config_args what build_config takes: buf, cap, rcount, settlecount
123 * @var Fdc2214Ns::begin_args what begin takes: addr, rcount, settlecount
124 * @var Fdc2214Ns::read_ch0_args what read_ch0 takes: out
125 * @var Fdc2214Ns::ok a call's true/false outcome
126 * @var Fdc2214Ns::value the value a call reports
127 * @var Fdc2214Ns::flags what a call reports
128 * @var Fdc2214Ns::hz what a call reports
129 * @var Fdc2214Ns::n bytes written (7 * 3 = 21), or 0 if cap < FDC2214_CONFIG_MAX
130 * @var Fdc2214Ns::data combine a DATA MSB register (low 12 bits) and DATA LSB register ...
131 * @var Fdc2214Ns::error the 4 error flags from the top of a DATA MSB register (bits 15:12)
132 * @var Fdc2214Ns::sensor_freq_hz sensor frequency in Hz for a 28-bit result against a reference ...
133 * @var Fdc2214Ns::build_config emit a single-channel (CH0) continuous-conversion bring-up as ...
134 * @var Fdc2214Ns::begin verify the device id and apply the CH0 config at addr. true if ...
135 * @var Fdc2214Ns::read_ch0 read channel 0's 28-bit conversion result into out. false on I2C ...
136 *
137 * @c work is PROTOCORE_I2C_DEVICE_BORROW bytes the CALLER took, at an address it knows. It is not held past the call,
138 * so nothing here aliases it. How those bytes are carved is this module's and is never named here.
139 */
140typedef struct
141{
142 Fdc2214DataArgs data_args;
143 Fdc2214ErrorArgs error_args;
144 Fdc2214SensorFreqHzArgs sensor_freq_hz_args;
145 Fdc2214BuildConfigArgs build_config_args;
146 Fdc2214BeginArgs begin_args;
147 Fdc2214ReadCh0Args read_ch0_args;
148 proto_bool ok;
149 uint32_t value;
150 uint8_t flags;
151 uint64_t hz;
152 size_t n;
153} Fdc2214Vars;
154
155/** @brief The operands and the outcome. */
156extern Fdc2214Vars Fdc2214V;
157
158/** @brief The entries. */
159typedef struct
160{
161 void (*const data)(uint8_t *work);
162 void (*const error)(uint8_t *work);
163 void (*const sensor_freq_hz)(uint8_t *work);
164 void (*const build_config)(uint8_t *work);
165 void (*const begin)(uint8_t *work);
166 void (*const read_ch0)(uint8_t *work);
167} Fdc2214Ns;
168
169// What the table binds, defined once in the .c and taking one parameter each: everything
170// else an entry needs is an operand in Fdc2214V or a region of the borrow at a fixed offset.
171void protocore_fdc2214_data(uint8_t *work);
172void protocore_fdc2214_error(uint8_t *work);
173void protocore_fdc2214_sensor_freq_hz(uint8_t *work);
174void protocore_fdc2214_build_config(uint8_t *work);
175void protocore_fdc2214_begin(uint8_t *work);
176void protocore_fdc2214_read_ch0(uint8_t *work);
177
178// `static const`, initialised HERE rather than `extern` against a definition in the .c: a
179// const object whose initializer every translation unit can see is a COMPILE-TIME FACT, so
180// `Fdc2214.data(work)` resolves to a named function and becomes a DIRECT call. An extern table
181// leaves the call indirect and the symbol live at every level, -O2 -flto included.
182static const Fdc2214Ns Fdc2214 __attribute__((unused)) = {
183 .data = protocore_fdc2214_data,
184 .error = protocore_fdc2214_error,
185 .sensor_freq_hz = protocore_fdc2214_sensor_freq_hz,
186 .build_config = protocore_fdc2214_build_config,
187 .begin = protocore_fdc2214_begin,
188 .read_ch0 = protocore_fdc2214_read_ch0,
189};
190
191/**
192 * @brief The PROTOCORE_I2C_DEVICE_BORROW bytes this module's state lives in.
193 *
194 * Stated beside the namespace rather than on it: an entry takes a borrow, and this is where
195 * that borrow comes from. Taken once from the end of the pool, which no mark and no release
196 * walks, so the state lasts the life of the program.
197 *
198 * @return the span.
199 */
200uint8_t *protocore_fdc2214_span(void);
201
203
204#endif // PROTOCORE_ENABLE_FDC2214
205
206#endif // PROTOCORE_FDC2214_H
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97