Implement mpr121 touch sensor capability to GPIO Expanders (#192)

Co-authored-by: Andy Boff <gitdev@plek.me.uk>
This commit is contained in:
Andy Boff
2022-10-22 05:55:04 +01:00
committed by GitHub
parent e34cec1ad1
commit 6c524cd094

View File

@@ -60,6 +60,10 @@ static const char TAG[] = "gpio expander";
static void IRAM_ATTR intr_isr_handler(void* arg);
static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio);
static esp_err_t mpr121_init(gpio_exp_t* self);
static uint32_t mpr121_read(gpio_exp_t* self);
static void mpr121_write(gpio_exp_t* self);
static void pca9535_set_direction(gpio_exp_t* self);
static uint32_t pca9535_read(gpio_exp_t* self);
static void pca9535_write(gpio_exp_t* self);
@@ -98,6 +102,11 @@ static const struct gpio_exp_model_s {
void (*set_direction)(gpio_exp_t* self);
void (*set_pull_mode)(gpio_exp_t* self);
} registered[] = {
{ .model = "mpr121",
.trigger = GPIO_INTR_LOW_LEVEL,
.init = mpr121_init,
.read = mpr121_read,
.write = mpr121_write, },
{ .model = "pca9535",
.trigger = GPIO_INTR_LOW_LEVEL,
.set_direction = pca9535_set_direction,
@@ -498,6 +507,111 @@ static gpio_exp_t* find_expander(gpio_exp_t *expander, int *gpio) {
DRIVERS
****************************************************************************************/
/****************************************************************************************
* MPR121 family : init, direction, read and write
*/
static esp_err_t mpr121_init(gpio_exp_t* self) {
// soft reset the MPR121
esp_err_t err = i2c_write(self->phy.port, self->phy.addr, 0x80, 0x63, 1);
/*
There is variance of default values between libraries:
Reg AN3944 Adafruit_MPR121 BareConductive/MPR121
MHDR 0x2b 0x01 0x01 0x01
NHDR 0x2c 0x01 0x01 0x01
NCLR 0x2d 0x00 0x0e 0x10
FDLR 0x2e 0x00 0x00 0x20
MHDF 0x2f 0x01 0x01 0x01
NHDF 0x30 0x01 0x05 0x01
NCLF 0x31 0xff 0x01 0x10
FDLF 0x32 0x20 0x00 0x20
NHDT 0x33 ---- 0x00 0x01
NCLT 0x34 ---- 0x00 0x10
FDLT 0x35 ---- 0x00 0xff
DTR 0x5b ---- 0x00 0x11
AFE1 0x5c ---- 0x10 0xff
AFE2 0x5d 0x04 0x20 0x30
ECR 0x5e 0x0c ---- 0xcc
ACCR0 0x7b 0x0b 0x0b 0x00
ACCR1 0x7c ---- ---- 0x00
USL 0x7d 0x9c 0xc8 0x00
LSL 0x7e 0x65 0xb4 0x00
TL 0x7f 0x8c 0x82 0x00
BareConductive MPR121 values used below.
*/
err |= i2c_write(self->phy.port, self->phy.addr, 0x2b, 0x01, 1); // MHDR
err |= i2c_write(self->phy.port, self->phy.addr, 0x2c, 0x01, 1); // NHDR
err |= i2c_write(self->phy.port, self->phy.addr, 0x2d, 0x10, 1); // NCLR
err |= i2c_write(self->phy.port, self->phy.addr, 0x2e, 0x20, 1); // FDLR
err |= i2c_write(self->phy.port, self->phy.addr, 0x2f, 0x01, 1); // MHDF
err |= i2c_write(self->phy.port, self->phy.addr, 0x30, 0x01, 1); // NHDF
err |= i2c_write(self->phy.port, self->phy.addr, 0x31, 0x10, 1); // NCLF
err |= i2c_write(self->phy.port, self->phy.addr, 0x32, 0x20, 1); // FDLF
err |= i2c_write(self->phy.port, self->phy.addr, 0x33, 0x01, 1); // NHDT
err |= i2c_write(self->phy.port, self->phy.addr, 0x34, 0x10, 1); // NCLT
err |= i2c_write(self->phy.port, self->phy.addr, 0x35, 0xff, 1); // FDLT
err |= i2c_write(self->phy.port, self->phy.addr, 0x5b, 0x11, 1); // DTR
err |= i2c_write(self->phy.port, self->phy.addr, 0x5c, 0xff, 1); // AFE1
err |= i2c_write(self->phy.port, self->phy.addr, 0x5d, 0x30, 1); // AFE2
// ECR set last
err |= i2c_write(self->phy.port, self->phy.addr, 0x7b, 0x00, 1); // ACCR0
err |= i2c_write(self->phy.port, self->phy.addr, 0x7c, 0x00, 1); // ACCR1
err |= i2c_write(self->phy.port, self->phy.addr, 0x7d, 0x00, 1); // USL
err |= i2c_write(self->phy.port, self->phy.addr, 0x7e, 0x00, 1); // LSL
err |= i2c_write(self->phy.port, self->phy.addr, 0x7f, 0x00, 1); // TL
// Touch & Release thresholds
err |= i2c_write(self->phy.port, self->phy.addr, 0x41, 0x28, 1); // ELE0 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x42, 0x14, 1); // ELE0 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x43, 0x28, 1); // ELE1 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x44, 0x14, 1); // ELE1 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x45, 0x28, 1); // ELE2 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x46, 0x14, 1); // ELE2 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x47, 0x28, 1); // ELE3 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x48, 0x14, 1); // ELE3 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x49, 0x28, 1); // ELE4 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x4a, 0x14, 1); // ELE4 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x4b, 0x28, 1); // ELE5 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x4c, 0x14, 1); // ELE5 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x4d, 0x28, 1); // ELE6 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x4e, 0x14, 1); // ELE6 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x4f, 0x28, 1); // ELE7 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x50, 0x14, 1); // ELE7 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x51, 0x28, 1); // ELE8 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x52, 0x14, 1); // ELE8 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x53, 0x28, 1); // ELE9 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x54, 0x14, 1); // ELE9 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x55, 0x28, 1); // ELE10 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x56, 0x14, 1); // ELE10 Release Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x57, 0x28, 1); // ELE11 Touch Threshold
err |= i2c_write(self->phy.port, self->phy.addr, 0x58, 0x14, 1); // ELE11 Release Threshold
// finally set to run mode with 12 electrodes enabled
err |= i2c_write(self->phy.port, self->phy.addr, 0x5e, 0xcc, 1); // ECR
return err;
}
static uint32_t mpr121_read(gpio_exp_t* self) {
// only return the lower 12 bits of the pin status registers
return i2c_read(self->phy.port, self->phy.addr, 0x00, 2) & 0x0fff;
}
static void mpr121_write(gpio_exp_t* self) {
ESP_LOGE(TAG, "MPR121 GPIO write not implemented");
}
/****************************************************************************************
* PCA9535 family : direction, read and write
*/