DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
ldc1614.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file ldc1614.cpp
6 * @brief LDC1614 inductance-to-digital codec + ESP32 binding (see ldc1614.h).
7 */
8
10#include "ServerConfig.h"
11
12#if DETWS_ENABLE_LDC1614
13
14uint32_t ldc1614_data(uint16_t msb_reg, uint16_t lsb_reg)
15{
16 return ((uint32_t)(msb_reg & 0x0FFF) << 16) | lsb_reg;
17}
18
19uint8_t ldc1614_error(uint16_t msb_reg)
20{
21 return (uint8_t)((msb_reg >> 12) & 0x0F);
22}
23
24uint64_t ldc1614_sensor_freq_hz(uint32_t data28, uint32_t fref_hz)
25{
26 return ((uint64_t)data28 * fref_hz) >> 28;
27}
28
29size_t ldc1614_build_config(uint8_t *buf, size_t cap, uint16_t rcount, uint16_t settlecount)
30{
31 if (!buf || cap < LDC1614_CONFIG_MAX)
32 return 0;
33 const uint16_t seq[][2] = {
34 {LDC1614_REG_RCOUNT_CH0, rcount},
35 {LDC1614_REG_SETTLECOUNT_CH0, settlecount},
36 {LDC1614_REG_CLOCK_DIVIDERS_CH0, 0x1001}, // FIN_SEL=1, FREF_DIVIDER=1
37 {LDC1614_REG_DRIVE_CURRENT_CH0, 0x9000}, // sensor drive current
38 {LDC1614_REG_ERROR_CONFIG, 0x0000}, // no error reporting on INTB
39 {LDC1614_REG_MUX_CONFIG, 0x020D}, // single channel CH0, 10 MHz deglitch
40 {LDC1614_REG_CONFIG, 0x1601}, // active CH0, internal ref, full current, start
41 };
42 size_t o = 0;
43 for (size_t i = 0; i < sizeof(seq) / sizeof(seq[0]); i++)
44 {
45 buf[o++] = (uint8_t)seq[i][0];
46 buf[o++] = (uint8_t)(seq[i][1] >> 8);
47 buf[o++] = (uint8_t)seq[i][1];
48 }
49 return o;
50}
51
52#if defined(ARDUINO)
53
54#include "services/i2c.h"
55#include <Arduino.h>
56#include <Wire.h>
57
58namespace
59{
60// All LDC1614 I2C-binding state, owned by one instance (internal linkage): the device address,
61// so it is one named owner, unreachable from any other translation unit.
62struct Ldc1614Ctx
63{
64 uint8_t addr = 0x2A;
65};
66Ldc1614Ctx s_ldc;
67
68bool read16(uint8_t reg, uint16_t *out)
69{
70 Wire.beginTransmission(s_ldc.addr);
71 Wire.write(reg);
72 if (Wire.endTransmission(false) != 0)
73 return false;
74 if (Wire.requestFrom((int)s_ldc.addr, 2) != 2)
75 return false;
76 uint16_t hi = Wire.read();
77 uint16_t lo = Wire.read();
78 *out = (uint16_t)((hi << 8) | lo);
79 return true;
80}
81
82bool write16(uint8_t reg, uint16_t val)
83{
84 Wire.beginTransmission(s_ldc.addr);
85 Wire.write(reg);
86 Wire.write((uint8_t)(val >> 8));
87 Wire.write((uint8_t)val);
88 return Wire.endTransmission() == 0;
89}
90} // namespace
91
92bool ldc1614_begin(uint8_t addr, uint16_t rcount, uint16_t settlecount)
93{
95 s_ldc.addr = addr;
96 uint16_t id = 0;
97 if (!read16(LDC1614_REG_DEVICE_ID, &id))
98 return false;
99 if (id != LDC1614_DEVICE_ID)
100 return false;
101 uint8_t seq[LDC1614_CONFIG_MAX];
102 size_t n = ldc1614_build_config(seq, sizeof(seq), rcount, settlecount);
103 for (size_t i = 0; i + 3 <= n; i += 3)
104 if (!write16(seq[i], (uint16_t)((seq[i + 1] << 8) | seq[i + 2])))
105 return false;
106 return true;
107}
108
109bool ldc1614_read_ch0(uint32_t *out)
110{
111 if (!out)
112 return false;
113 uint16_t msb = 0;
114 uint16_t lsb = 0;
115 if (!read16(LDC1614_REG_DATA_CH0_MSB, &msb) || !read16(LDC1614_REG_DATA_CH0_LSB, &lsb))
116 return false;
117 *out = ldc1614_data(msb, lsb);
118 return true;
119}
120
121#endif // ARDUINO
122
123#endif // DETWS_ENABLE_LDC1614
User-facing configuration for DeterministicESPAsyncWebServer.
The one owner of the shared I2C bus bring-up for the peripheral drivers.
void detws_i2c_begin()
Bring up the shared I2C bus on DETWS_I2C_SDA_PIN / DETWS_I2C_SCL_PIN (-1 = default).
Definition i2c.h:33
TI LDC1614 inductance-to-digital field-sensing codec (DETWS_ENABLE_LDC1614).
size_t ldc1614_build_config(uint8_t *buf, size_t cap, uint16_t rcount, uint16_t settlecount)
Emit a single-channel (CH0) continuous-conversion bring-up as (reg, val_msb, val_lsb) triples.
#define LDC1614_REG_CONFIG
Definition ldc1614.h:35
#define LDC1614_REG_ERROR_CONFIG
Definition ldc1614.h:34
#define LDC1614_DEVICE_ID
LDC1614 / LDC1612.
Definition ldc1614.h:42
#define LDC1614_REG_DRIVE_CURRENT_CH0
Definition ldc1614.h:37
uint64_t ldc1614_sensor_freq_hz(uint32_t data28, uint32_t fref_hz)
Sensor frequency in Hz for a 28-bit result against a reference clock: data / 2^28 * fref.
#define LDC1614_REG_DATA_CH0_MSB
Definition ldc1614.h:28
bool ldc1614_begin(uint8_t addr, uint16_t rcount, uint16_t settlecount)
Verify the device id and apply the CH0 config at addr.
#define LDC1614_REG_CLOCK_DIVIDERS_CH0
Definition ldc1614.h:32
bool ldc1614_read_ch0(uint32_t *out)
Read channel 0's 28-bit conversion result into out.
#define LDC1614_REG_DEVICE_ID
Definition ldc1614.h:39
uint8_t ldc1614_error(uint16_t msb_reg)
The 4 error flags from the top of a DATA MSB register (bits 15:12).
#define LDC1614_REG_DATA_CH0_LSB
Definition ldc1614.h:29
uint32_t ldc1614_data(uint16_t msb_reg, uint16_t lsb_reg)
Combine a DATA MSB register (low 12 bits) and DATA LSB register into the 28-bit result.
#define LDC1614_REG_MUX_CONFIG
Definition ldc1614.h:36
#define LDC1614_REG_SETTLECOUNT_CH0
Definition ldc1614.h:31
#define LDC1614_CONFIG_MAX
Largest config sequence in bytes: 7 register writes * 3 bytes (reg, msb, lsb).
Definition ldc1614.h:45
#define LDC1614_REG_RCOUNT_CH0
Definition ldc1614.h:30