28 return (uint16_t)(((uint16_t)status_lo | ((uint16_t)status_hi << 8)) & 0x0FFF);
38 return (status_hi & 0x10) != 0;
43 return (status_hi & 0x80) != 0;
48 return (uint16_t)(((uint16_t)lsb | ((uint16_t)msb << 8)) & 0x03FF);
51size_t pc_mpr121_build_init(uint8_t *buf,
size_t cap, uint8_t n, uint8_t touch_thr, uint8_t release_thr)
58 static const uint8_t fixed[] = {
61 0x2B, 0x01, 0x2C, 0x01,
62 0x2D, 0x0E, 0x2E, 0x00,
63 0x2F, 0x01, 0x30, 0x05,
64 0x31, 0x01, 0x32, 0x00,
65 0x33, 0x00, 0x34, 0x00,
68 size_t need =
sizeof(fixed) + (
size_t)n * 4 + 8;
73 size_t i =
sizeof(fixed);
74 memcpy(buf, fixed,
sizeof(fixed));
75 for (uint8_t e = 0; e < n; e++)
77 buf[i++] = (uint8_t)(0x41 + 2 * e);
79 buf[i++] = (uint8_t)(0x42 + 2 * e);
80 buf[i++] = release_thr;
89 buf[i++] = (uint8_t)(0x80 | n);
109bool wr(uint8_t reg, uint8_t val)
111 Wire.beginTransmission(s_mpr.addr);
114 return Wire.endTransmission() == 0;
117bool rd(uint8_t reg, uint8_t *out, uint8_t n)
119 Wire.beginTransmission(s_mpr.addr);
121 if (Wire.endTransmission(
false) != 0)
125 if (Wire.requestFrom((
int)s_mpr.addr, (
int)n) != (
int)n)
129 for (uint8_t i = 0; i < n; i++)
131 out[i] = (uint8_t)Wire.read();
148 if (!wr(seq[0], seq[1]))
153 for (
size_t i = 2; i + 1 < n; i += 2)
155 if (!wr(seq[i], seq[i + 1]))
165 uint8_t s[2] = {0, 0};
179 uint8_t d[2] = {0, 0};
180 if (!rd((uint8_t)(0x04 + 2 * e), d, 2))
Pluggable monotonic clock for all library timing.
void pcdelay(uint32_t ms)
Block for at least ms milliseconds - the library's single delay primitive.
The one owner of the shared I2C bus bring-up for the peripheral drivers.
void pc_i2c_begin()
Bring up the shared I2C bus on PC_I2C_SDA_PIN / PC_I2C_SCL_PIN (-1 = default).
NXP MPR121 12-channel capacitive-touch controller codec (PC_ENABLE_MPR121).
bool pc_mpr121_proximity(uint8_t status_hi)
True if the proximity electrode (status bit 12) is active.
#define MPR121_INIT_MAX
Largest init sequence in bytes: (17 fixed + 2*12 threshold) pairs * 2 bytes.
size_t pc_mpr121_build_init(uint8_t *buf, size_t cap, uint8_t n_electrodes, uint8_t touch_thr, uint8_t release_thr)
Build the MPR121 bring-up sequence as consecutive (register, value) byte pairs.
bool pc_mpr121_is_touched(uint16_t mask, uint8_t e)
True if electrode e (0..11) is touched in a mask from pc_mpr121_touched.
uint16_t pc_mpr121_read_filtered(uint8_t e)
Read electrode e's 10-bit filtered capacitance value.
bool pc_mpr121_overcurrent(uint8_t status_hi)
True if the over-current flag (status bit 15) is set (wiring fault / short).
uint16_t pc_mpr121_word10(uint8_t lsb, uint8_t msb)
Combine a little-endian LSB/MSB register pair into a 10-bit value (filtered/baseline).
uint16_t pc_mpr121_read_touched()
Read the current 12-electrode touch bitmask (0 if the device is absent).
uint16_t pc_mpr121_touched(uint8_t status_lo, uint8_t status_hi)
Decode the 12-electrode touch bitmask from the two status registers (0x00 low, 0x01 high)....
bool pc_mpr121_begin(uint8_t addr)
Reset + configure the MPR121 at addr over I2C.
#define MPR121_ELECTRODES
Sense electrodes on the MPR121 (ELE0..ELE11).
uint32_t mask(uint8_t width)
Mask of width low bits (width 32 handled without a 32-bit shift, which is UB).
User-facing configuration for ProtoCore.
#define PC_MPR121_TOUCH_THRESHOLD
MPR121 per-electrode touch threshold (delta counts from baseline; NXP AN3944 suggests ~4....
#define PC_MPR121_I2C_ADDR
I2C address of the MPR121 (0x5A default; 0x5B/0x5C/0x5D via the ADDR pin).
#define PC_MPR121_RELEASE_THRESHOLD
MPR121 per-electrode release threshold (delta counts; should be below the touch threshold).