Fiona Lin / Mbed OS cap_sense
Committer:
fionalin
Date:
Thu Aug 04 15:14:29 2022 -0400
Revision:
2:d9745be6c253
hehe forgot to commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fionalin 2:d9745be6c253 1 /*!
fionalin 2:d9745be6c253 2 * @file Adafruit_MPR121.cpp
fionalin 2:d9745be6c253 3 *
fionalin 2:d9745be6c253 4 * @mainpage Adafruit MPR121 arduino driver
fionalin 2:d9745be6c253 5 *
fionalin 2:d9745be6c253 6 * @section intro_sec Introduction
fionalin 2:d9745be6c253 7 *
fionalin 2:d9745be6c253 8 * This is a library for the MPR121 I2C 12-chan Capacitive Sensor
fionalin 2:d9745be6c253 9 *
fionalin 2:d9745be6c253 10 * Designed specifically to work with the MPR121 sensor from Adafruit
fionalin 2:d9745be6c253 11 * ----> https://www.adafruit.com/products/1982
fionalin 2:d9745be6c253 12 *
fionalin 2:d9745be6c253 13 * These sensors use I2C to communicate, 2+ pins are required to
fionalin 2:d9745be6c253 14 * interface
fionalin 2:d9745be6c253 15 *
fionalin 2:d9745be6c253 16 * Adafruit invests time and resources providing this open source code,
fionalin 2:d9745be6c253 17 * please support Adafruit and open-source hardware by purchasing
fionalin 2:d9745be6c253 18 * products from Adafruit!
fionalin 2:d9745be6c253 19 *
fionalin 2:d9745be6c253 20 * @section author Author
fionalin 2:d9745be6c253 21 *
fionalin 2:d9745be6c253 22 * Written by Limor Fried/Ladyada for Adafruit Industries.
fionalin 2:d9745be6c253 23 *
fionalin 2:d9745be6c253 24 * @section license License
fionalin 2:d9745be6c253 25 *
fionalin 2:d9745be6c253 26 * BSD license, all text here must be included in any redistribution.
fionalin 2:d9745be6c253 27 */
fionalin 2:d9745be6c253 28
fionalin 2:d9745be6c253 29 #include "Adafruit_MPR121.h"
fionalin 2:d9745be6c253 30
fionalin 2:d9745be6c253 31 // uncomment to use autoconfig !
fionalin 2:d9745be6c253 32 //#define AUTOCONFIG // use autoconfig (Yes it works pretty well!)
fionalin 2:d9745be6c253 33
fionalin 2:d9745be6c253 34 /*!
fionalin 2:d9745be6c253 35 * @brief Default constructor
fionalin 2:d9745be6c253 36 */
fionalin 2:d9745be6c253 37 Adafruit_MPR121::Adafruit_MPR121() {}
fionalin 2:d9745be6c253 38
fionalin 2:d9745be6c253 39 /*!
fionalin 2:d9745be6c253 40 * @brief Begin an MPR121 object on a given I2C bus. This function resets
fionalin 2:d9745be6c253 41 * the device and writes the default settings.
fionalin 2:d9745be6c253 42 * @param i2c_addr
fionalin 2:d9745be6c253 43 * the i2c address the device can be found on. Defaults to 0x5A.
fionalin 2:d9745be6c253 44 * @param i2c_sda
fionalin 2:d9745be6c253 45 * SDA pin for I2C
fionalin 2:d9745be6c253 46 * @param i2c_scl
fionalin 2:d9745be6c253 47 * SCL pin for I2C
fionalin 2:d9745be6c253 48 * @param touchThreshold
fionalin 2:d9745be6c253 49 * touch detection threshold value
fionalin 2:d9745be6c253 50 * @param releaseThreshold
fionalin 2:d9745be6c253 51 * release detection threshold value
fionalin 2:d9745be6c253 52 * @returns true on success, false otherwise
fionalin 2:d9745be6c253 53 */
fionalin 2:d9745be6c253 54 bool Adafruit_MPR121::begin(uint8_t i2c_addr, PinName i2c_sda, PinName i2c_scl,
fionalin 2:d9745be6c253 55 uint8_t touchThreshold, uint8_t releaseThreshold) {
fionalin 2:d9745be6c253 56 this->i2c_addr = i2c_addr;
fionalin 2:d9745be6c253 57
fionalin 2:d9745be6c253 58 if (i2c_dev) {
fionalin 2:d9745be6c253 59 delete i2c_dev;
fionalin 2:d9745be6c253 60 }
fionalin 2:d9745be6c253 61 i2c_dev = new I2C(i2c_sda, i2c_scl);
fionalin 2:d9745be6c253 62
fionalin 2:d9745be6c253 63 // soft reset
fionalin 2:d9745be6c253 64 writeRegister(MPR121_SOFTRESET, 0x63);
fionalin 2:d9745be6c253 65 wait_us(1000);
fionalin 2:d9745be6c253 66 for (uint8_t i = 0; i < 0x7F; i++) {
fionalin 2:d9745be6c253 67 // Serial.print("$"); Serial.print(i, HEX);
fionalin 2:d9745be6c253 68 // Serial.print(": 0x"); Serial.println(readRegister8(i));
fionalin 2:d9745be6c253 69 }
fionalin 2:d9745be6c253 70
fionalin 2:d9745be6c253 71 writeRegister(MPR121_ECR, 0x0);
fionalin 2:d9745be6c253 72
fionalin 2:d9745be6c253 73 uint8_t c = readRegister8(MPR121_CONFIG2);
fionalin 2:d9745be6c253 74
fionalin 2:d9745be6c253 75 if (c != 0x24)
fionalin 2:d9745be6c253 76 return false;
fionalin 2:d9745be6c253 77
fionalin 2:d9745be6c253 78 setThresholds(touchThreshold, releaseThreshold);
fionalin 2:d9745be6c253 79 writeRegister(MPR121_MHDR, 0x01);
fionalin 2:d9745be6c253 80 writeRegister(MPR121_NHDR, 0x01);
fionalin 2:d9745be6c253 81 writeRegister(MPR121_NCLR, 0x0E);
fionalin 2:d9745be6c253 82 writeRegister(MPR121_FDLR, 0x00);
fionalin 2:d9745be6c253 83
fionalin 2:d9745be6c253 84 writeRegister(MPR121_MHDF, 0x01);
fionalin 2:d9745be6c253 85 writeRegister(MPR121_NHDF, 0x05);
fionalin 2:d9745be6c253 86 writeRegister(MPR121_NCLF, 0x01);
fionalin 2:d9745be6c253 87 writeRegister(MPR121_FDLF, 0x00);
fionalin 2:d9745be6c253 88
fionalin 2:d9745be6c253 89 writeRegister(MPR121_NHDT, 0x00);
fionalin 2:d9745be6c253 90 writeRegister(MPR121_NCLT, 0x00);
fionalin 2:d9745be6c253 91 writeRegister(MPR121_FDLT, 0x00);
fionalin 2:d9745be6c253 92
fionalin 2:d9745be6c253 93 writeRegister(MPR121_DEBOUNCE, 0);
fionalin 2:d9745be6c253 94 writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
fionalin 2:d9745be6c253 95 writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
fionalin 2:d9745be6c253 96
fionalin 2:d9745be6c253 97 #ifdef AUTOCONFIG
fionalin 2:d9745be6c253 98 writeRegister(MPR121_AUTOCONFIG0, 0x0B);
fionalin 2:d9745be6c253 99
fionalin 2:d9745be6c253 100 // correct values for Vdd = 3.3V
fionalin 2:d9745be6c253 101 writeRegister(MPR121_UPLIMIT, 200); // ((Vdd - 0.7)/Vdd) * 256
fionalin 2:d9745be6c253 102 writeRegister(MPR121_TARGETLIMIT, 180); // UPLIMIT * 0.9
fionalin 2:d9745be6c253 103 writeRegister(MPR121_LOWLIMIT, 130); // UPLIMIT * 0.65
fionalin 2:d9745be6c253 104 #endif
fionalin 2:d9745be6c253 105
fionalin 2:d9745be6c253 106 // enable X electrodes and start MPR121
fionalin 2:d9745be6c253 107 uint8_t ECR_SETTING =
fionalin 2:d9745be6c253 108 0x80 + 12; // 5 bits for baseline tracking & proximity disabled + X
fionalin 2:d9745be6c253 109 // amount of electrodes running (12)
fionalin 2:d9745be6c253 110 writeRegister(MPR121_ECR, ECR_SETTING); // start with above ECR setting
fionalin 2:d9745be6c253 111
fionalin 2:d9745be6c253 112 return true;
fionalin 2:d9745be6c253 113 }
fionalin 2:d9745be6c253 114
fionalin 2:d9745be6c253 115 /*!
fionalin 2:d9745be6c253 116 * @brief DEPRECATED. Use Adafruit_MPR121::setThresholds(uint8_t touch,
fionalin 2:d9745be6c253 117 * uint8_t release) instead.
fionalin 2:d9745be6c253 118 * @param touch
fionalin 2:d9745be6c253 119 * see Adafruit_MPR121::setThresholds(uint8_t touch, uint8_t
fionalin 2:d9745be6c253 120 * *release)
fionalin 2:d9745be6c253 121 * @param release
fionalin 2:d9745be6c253 122 * see Adafruit_MPR121::setThresholds(uint8_t touch, *uint8_t
fionalin 2:d9745be6c253 123 * release)
fionalin 2:d9745be6c253 124 */
fionalin 2:d9745be6c253 125 void Adafruit_MPR121::setThreshholds(uint8_t touch, uint8_t release) {
fionalin 2:d9745be6c253 126 setThresholds(touch, release);
fionalin 2:d9745be6c253 127 }
fionalin 2:d9745be6c253 128
fionalin 2:d9745be6c253 129 /*!
fionalin 2:d9745be6c253 130 * @brief Set the touch and release thresholds for all 13 channels on the
fionalin 2:d9745be6c253 131 * device to the passed values. The threshold is defined as a
fionalin 2:d9745be6c253 132 * deviation value from the baseline value, so it remains constant
fionalin 2:d9745be6c253 133 * even baseline value changes. Typically the touch threshold is a little bigger
fionalin 2:d9745be6c253 134 * than the release threshold to touch debounce and hysteresis. For typical
fionalin 2:d9745be6c253 135 * touch application, the value can be in range 0x05~0x30 for example. The
fionalin 2:d9745be6c253 136 * setting of the threshold is depended on the actual application. For the
fionalin 2:d9745be6c253 137 * operation details and how to set the threshold refer to application note
fionalin 2:d9745be6c253 138 * AN3892 and MPR121 design guidelines.
fionalin 2:d9745be6c253 139 * @param touch
fionalin 2:d9745be6c253 140 * the touch threshold value from 0 to 255.
fionalin 2:d9745be6c253 141 * @param release
fionalin 2:d9745be6c253 142 * the release threshold from 0 to 255.
fionalin 2:d9745be6c253 143 */
fionalin 2:d9745be6c253 144 void Adafruit_MPR121::setThresholds(uint8_t touch, uint8_t release) {
fionalin 2:d9745be6c253 145 // set all thresholds (the same)
fionalin 2:d9745be6c253 146 for (uint8_t i = 0; i < 12; i++) {
fionalin 2:d9745be6c253 147 writeRegister(MPR121_TOUCHTH_0 + 2 * i, touch);
fionalin 2:d9745be6c253 148 writeRegister(MPR121_RELEASETH_0 + 2 * i, release);
fionalin 2:d9745be6c253 149 }
fionalin 2:d9745be6c253 150 }
fionalin 2:d9745be6c253 151
fionalin 2:d9745be6c253 152 /*!
fionalin 2:d9745be6c253 153 * @brief Read the filtered data from channel t. The ADC raw data outputs
fionalin 2:d9745be6c253 154 * run through 3 levels of digital filtering to filter out the high
fionalin 2:d9745be6c253 155 * frequency and low frequency noise encountered. For detailed information on
fionalin 2:d9745be6c253 156 * this filtering see page 6 of the device datasheet.
fionalin 2:d9745be6c253 157 * @param t
fionalin 2:d9745be6c253 158 * the channel to read
fionalin 2:d9745be6c253 159 * @returns the filtered reading as a 10 bit unsigned value
fionalin 2:d9745be6c253 160 */
fionalin 2:d9745be6c253 161 uint16_t Adafruit_MPR121::filteredData(uint8_t t) {
fionalin 2:d9745be6c253 162 if (t > 12)
fionalin 2:d9745be6c253 163 return 0;
fionalin 2:d9745be6c253 164 return readRegister16(MPR121_FILTDATA_0L + t * 2);
fionalin 2:d9745be6c253 165 }
fionalin 2:d9745be6c253 166
fionalin 2:d9745be6c253 167 /*!
fionalin 2:d9745be6c253 168 * @brief Read the baseline value for the channel. The 3rd level filtered
fionalin 2:d9745be6c253 169 * result is internally 10bit but only high 8 bits are readable
fionalin 2:d9745be6c253 170 * from registers 0x1E~0x2A as the baseline value output for each channel.
fionalin 2:d9745be6c253 171 * @param t
fionalin 2:d9745be6c253 172 * the channel to read.
fionalin 2:d9745be6c253 173 * @returns the baseline data that was read
fionalin 2:d9745be6c253 174 */
fionalin 2:d9745be6c253 175 uint16_t Adafruit_MPR121::baselineData(uint8_t t) {
fionalin 2:d9745be6c253 176 if (t > 12)
fionalin 2:d9745be6c253 177 return 0;
fionalin 2:d9745be6c253 178 uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
fionalin 2:d9745be6c253 179 return (bl << 2);
fionalin 2:d9745be6c253 180 }
fionalin 2:d9745be6c253 181
fionalin 2:d9745be6c253 182 /**
fionalin 2:d9745be6c253 183 * @brief Read the touch status of all 13 channels as bit values in a 12
fionalin 2:d9745be6c253 184 * bit integer.
fionalin 2:d9745be6c253 185 * @returns a 12 bit integer with each bit corresponding to the touch status
fionalin 2:d9745be6c253 186 * of a sensor. For example, if bit 0 is set then channel 0 of the
fionalin 2:d9745be6c253 187 * device is currently deemed to be touched.
fionalin 2:d9745be6c253 188 */
fionalin 2:d9745be6c253 189 uint16_t Adafruit_MPR121::touched(void) {
fionalin 2:d9745be6c253 190 uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
fionalin 2:d9745be6c253 191 return t & 0x0FFF;
fionalin 2:d9745be6c253 192 }
fionalin 2:d9745be6c253 193
fionalin 2:d9745be6c253 194 /*!
fionalin 2:d9745be6c253 195 * @brief Read the contents of an 8 bit device register.
fionalin 2:d9745be6c253 196 * @param reg the register address to read from
fionalin 2:d9745be6c253 197 * @returns the 8 bit value that was read.
fionalin 2:d9745be6c253 198 */
fionalin 2:d9745be6c253 199 uint8_t Adafruit_MPR121::readRegister8(uint8_t reg) {
fionalin 2:d9745be6c253 200 // Adafruit's library sends TWO bytes address. If you have
fionalin 2:d9745be6c253 201 // only one byte, send it as the first byte and zero the
fionalin 2:d9745be6c253 202 // second byte.
fionalin 2:d9745be6c253 203 char reg_addr[2] = {reg, 0x00};
fionalin 2:d9745be6c253 204 char value;
fionalin 2:d9745be6c253 205 i2c_dev->write(i2c_addr, reg_addr, 2);
fionalin 2:d9745be6c253 206 i2c_dev->read(i2c_addr, &value, 1);
fionalin 2:d9745be6c253 207
fionalin 2:d9745be6c253 208 return value;
fionalin 2:d9745be6c253 209 }
fionalin 2:d9745be6c253 210
fionalin 2:d9745be6c253 211 /*!
fionalin 2:d9745be6c253 212 * @brief Read the contents of a 16 bit device register.
fionalin 2:d9745be6c253 213 * @param reg the register address to read from
fionalin 2:d9745be6c253 214 * @returns the 16 bit value that was read.
fionalin 2:d9745be6c253 215 */
fionalin 2:d9745be6c253 216 uint16_t Adafruit_MPR121::readRegister16(uint8_t reg) {
fionalin 2:d9745be6c253 217 // Adafruit's library sends TWO bytes address. If you have
fionalin 2:d9745be6c253 218 // only one byte, send it as the first byte and zero the
fionalin 2:d9745be6c253 219 // second byte.
fionalin 2:d9745be6c253 220 char reg_addr[2] = {reg, 0x00};
fionalin 2:d9745be6c253 221 char value[2];
fionalin 2:d9745be6c253 222 i2c_dev->write(i2c_addr, reg_addr, 2);
fionalin 2:d9745be6c253 223 i2c_dev->read(i2c_addr, value, 2);
fionalin 2:d9745be6c253 224
fionalin 2:d9745be6c253 225 // Combine the two bytes into a single value of 16 bits.
fionalin 2:d9745be6c253 226 return ((uint16_t)value[1] << 8) + (uint16_t)value[0];
fionalin 2:d9745be6c253 227 }
fionalin 2:d9745be6c253 228
fionalin 2:d9745be6c253 229 /*!
fionalin 2:d9745be6c253 230 @brief Writes 8-bits to the specified destination register
fionalin 2:d9745be6c253 231 @param reg the register address to write to
fionalin 2:d9745be6c253 232 @param value the value to write
fionalin 2:d9745be6c253 233 */
fionalin 2:d9745be6c253 234 void Adafruit_MPR121::writeRegister(uint8_t reg, uint8_t value) {
fionalin 2:d9745be6c253 235 // MPR121 must be put in Stop Mode to write to most registers
fionalin 2:d9745be6c253 236 bool stop_required = true;
fionalin 2:d9745be6c253 237
fionalin 2:d9745be6c253 238 // first get the current set value of the MPR121_ECR register
fionalin 2:d9745be6c253 239 uint8_t ecr_backup = readRegister8(MPR121_ECR);
fionalin 2:d9745be6c253 240 if ((reg == MPR121_ECR) || ((0x73 <= reg) && (reg <= 0x7A))) {
fionalin 2:d9745be6c253 241 stop_required = false;
fionalin 2:d9745be6c253 242 }
fionalin 2:d9745be6c253 243
fionalin 2:d9745be6c253 244 if (stop_required) {
fionalin 2:d9745be6c253 245 // clear this register to set stop mode
fionalin 2:d9745be6c253 246 writeRegister(MPR121_ECR, 0x00);
fionalin 2:d9745be6c253 247 }
fionalin 2:d9745be6c253 248
fionalin 2:d9745be6c253 249 // Write to the register by writing the address first then writing
fionalin 2:d9745be6c253 250 // the intended value for the register
fionalin 2:d9745be6c253 251 char reg_addr[2] = {reg, 0x00}; // Adafruit's library uses TWO bytes addr (see readRegister8)
fionalin 2:d9745be6c253 252 i2c_dev->write(i2c_addr, reg_addr, 2);
fionalin 2:d9745be6c253 253 i2c_dev->write(i2c_addr, (char*)&value, 1);
fionalin 2:d9745be6c253 254
fionalin 2:d9745be6c253 255 if (stop_required) {
fionalin 2:d9745be6c253 256 // write back the previous set ECR settings
fionalin 2:d9745be6c253 257 char ecr_addr[2] = {MPR121_ECR, 0x00};
fionalin 2:d9745be6c253 258 i2c_dev->write(i2c_addr, ecr_addr, 2);
fionalin 2:d9745be6c253 259 i2c_dev->write(i2c_addr, (char*)&ecr_backup, 1);
fionalin 2:d9745be6c253 260 }
fionalin 2:d9745be6c253 261 }