Fiona Lin / Mbed OS cap_sense
Revision:
2:d9745be6c253
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_MPR121.cpp	Thu Aug 04 15:14:29 2022 -0400
@@ -0,0 +1,261 @@
+/*!
+ * @file Adafruit_MPR121.cpp
+ *
+ *  @mainpage Adafruit MPR121 arduino driver
+ *
+ *  @section intro_sec Introduction
+ *
+ *  This is a library for the MPR121 I2C 12-chan Capacitive Sensor
+ *
+ *  Designed specifically to work with the MPR121 sensor from Adafruit
+ *  ----> https://www.adafruit.com/products/1982
+ *
+ *  These sensors use I2C to communicate, 2+ pins are required to
+ *  interface
+ *
+ *  Adafruit invests time and resources providing this open source code,
+ *  please support Adafruit and open-source hardware by purchasing
+ *  products from Adafruit!
+ *
+ *  @section author Author
+ *
+ *  Written by Limor Fried/Ladyada for Adafruit Industries.
+ *
+ *  @section license License
+ *
+ *  BSD license, all text here must be included in any redistribution.
+ */
+
+#include "Adafruit_MPR121.h"
+
+// uncomment to use autoconfig !
+//#define AUTOCONFIG // use autoconfig (Yes it works pretty well!)
+
+/*!
+ *  @brief      Default constructor
+ */
+Adafruit_MPR121::Adafruit_MPR121() {}
+
+/*!
+ *  @brief    Begin an MPR121 object on a given I2C bus. This function resets
+ *            the device and writes the default settings.
+ *  @param    i2c_addr
+ *            the i2c address the device can be found on. Defaults to 0x5A.
+ *  @param    i2c_sda
+ *            SDA pin for I2C
+ *  @param    i2c_scl
+ *            SCL pin for I2C
+ *  @param    touchThreshold
+ *            touch detection threshold value
+ *  @param    releaseThreshold
+ *            release detection threshold value
+ *  @returns  true on success, false otherwise
+ */
+bool Adafruit_MPR121::begin(uint8_t i2c_addr, PinName i2c_sda, PinName i2c_scl,
+                            uint8_t touchThreshold, uint8_t releaseThreshold) {
+  this->i2c_addr = i2c_addr;
+
+  if (i2c_dev) {
+    delete i2c_dev;
+  }
+  i2c_dev = new I2C(i2c_sda, i2c_scl);
+
+  // soft reset
+  writeRegister(MPR121_SOFTRESET, 0x63);
+  wait_us(1000);
+  for (uint8_t i = 0; i < 0x7F; i++) {
+    //  Serial.print("$"); Serial.print(i, HEX);
+    //  Serial.print(": 0x"); Serial.println(readRegister8(i));
+  }
+
+  writeRegister(MPR121_ECR, 0x0);
+
+  uint8_t c = readRegister8(MPR121_CONFIG2);
+
+  if (c != 0x24)
+    return false;
+
+  setThresholds(touchThreshold, releaseThreshold);
+  writeRegister(MPR121_MHDR, 0x01);
+  writeRegister(MPR121_NHDR, 0x01);
+  writeRegister(MPR121_NCLR, 0x0E);
+  writeRegister(MPR121_FDLR, 0x00);
+
+  writeRegister(MPR121_MHDF, 0x01);
+  writeRegister(MPR121_NHDF, 0x05);
+  writeRegister(MPR121_NCLF, 0x01);
+  writeRegister(MPR121_FDLF, 0x00);
+
+  writeRegister(MPR121_NHDT, 0x00);
+  writeRegister(MPR121_NCLT, 0x00);
+  writeRegister(MPR121_FDLT, 0x00);
+
+  writeRegister(MPR121_DEBOUNCE, 0);
+  writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
+  writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
+
+#ifdef AUTOCONFIG
+  writeRegister(MPR121_AUTOCONFIG0, 0x0B);
+
+  // correct values for Vdd = 3.3V
+  writeRegister(MPR121_UPLIMIT, 200);     // ((Vdd - 0.7)/Vdd) * 256
+  writeRegister(MPR121_TARGETLIMIT, 180); // UPLIMIT * 0.9
+  writeRegister(MPR121_LOWLIMIT, 130);    // UPLIMIT * 0.65
+#endif
+
+  // enable X electrodes and start MPR121
+  uint8_t ECR_SETTING =
+        0x80 + 12; // 5 bits for baseline tracking & proximity disabled + X
+                   // amount of electrodes running (12)
+  writeRegister(MPR121_ECR, ECR_SETTING); // start with above ECR setting
+
+  return true;
+}
+
+/*!
+ *  @brief      DEPRECATED. Use Adafruit_MPR121::setThresholds(uint8_t touch,
+ *              uint8_t release) instead.
+ *  @param      touch
+ *              see Adafruit_MPR121::setThresholds(uint8_t touch, uint8_t
+ * *release)
+ *  @param      release
+ *              see Adafruit_MPR121::setThresholds(uint8_t touch, *uint8_t
+ * release)
+ */
+void Adafruit_MPR121::setThreshholds(uint8_t touch, uint8_t release) {
+  setThresholds(touch, release);
+}
+
+/*!
+ *  @brief      Set the touch and release thresholds for all 13 channels on the
+ *              device to the passed values. The threshold is defined as a
+ *              deviation value from the baseline value, so it remains constant
+ * even baseline value changes. Typically the touch threshold is a little bigger
+ * than the release threshold to touch debounce and hysteresis. For typical
+ * touch application, the value can be in range 0x05~0x30 for example. The
+ * setting of the threshold is depended on the actual application. For the
+ * operation details and how to set the threshold refer to application note
+ * AN3892 and MPR121 design guidelines.
+ *  @param      touch
+ *              the touch threshold value from 0 to 255.
+ *  @param      release
+ *              the release threshold from 0 to 255.
+ */
+void Adafruit_MPR121::setThresholds(uint8_t touch, uint8_t release) {
+  // set all thresholds (the same)
+  for (uint8_t i = 0; i < 12; i++) {
+    writeRegister(MPR121_TOUCHTH_0 + 2 * i, touch);
+    writeRegister(MPR121_RELEASETH_0 + 2 * i, release);
+  }
+}
+
+/*!
+ *  @brief      Read the filtered data from channel t. The ADC raw data outputs
+ *              run through 3 levels of digital filtering to filter out the high
+ * frequency and low frequency noise encountered. For detailed information on
+ * this filtering see page 6 of the device datasheet.
+ *  @param      t
+ *              the channel to read
+ *  @returns    the filtered reading as a 10 bit unsigned value
+ */
+uint16_t Adafruit_MPR121::filteredData(uint8_t t) {
+  if (t > 12)
+    return 0;
+  return readRegister16(MPR121_FILTDATA_0L + t * 2);
+}
+
+/*!
+ *  @brief      Read the baseline value for the channel. The 3rd level filtered
+ *              result is internally 10bit but only high 8 bits are readable
+ * from registers 0x1E~0x2A as the baseline value output for each channel.
+ *  @param      t
+ *              the channel to read.
+ *  @returns    the baseline data that was read
+ */
+uint16_t Adafruit_MPR121::baselineData(uint8_t t) {
+  if (t > 12)
+    return 0;
+  uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
+  return (bl << 2);
+}
+
+/**
+ *  @brief      Read the touch status of all 13 channels as bit values in a 12
+ * bit integer.
+ *  @returns    a 12 bit integer with each bit corresponding to the touch status
+ *              of a sensor. For example, if bit 0 is set then channel 0 of the
+ * device is currently deemed to be touched.
+ */
+uint16_t Adafruit_MPR121::touched(void) {
+  uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
+  return t & 0x0FFF;
+}
+
+/*!
+ *  @brief      Read the contents of an 8 bit device register.
+ *  @param      reg the register address to read from
+ *  @returns    the 8 bit value that was read.
+ */
+uint8_t Adafruit_MPR121::readRegister8(uint8_t reg) {
+  // Adafruit's library sends TWO bytes address. If you have
+  // only one byte, send it as the first byte and zero the
+  // second byte.
+  char reg_addr[2] = {reg, 0x00};
+  char value;
+  i2c_dev->write(i2c_addr, reg_addr, 2);
+  i2c_dev->read(i2c_addr, &value, 1);
+
+  return value;
+}
+
+/*!
+ *  @brief      Read the contents of a 16 bit device register.
+ *  @param      reg the register address to read from
+ *  @returns    the 16 bit value that was read.
+ */
+uint16_t Adafruit_MPR121::readRegister16(uint8_t reg) {
+  // Adafruit's library sends TWO bytes address. If you have
+  // only one byte, send it as the first byte and zero the
+  // second byte.
+  char reg_addr[2] = {reg, 0x00};
+  char value[2];
+  i2c_dev->write(i2c_addr, reg_addr, 2);
+  i2c_dev->read(i2c_addr, value, 2);
+
+  // Combine the two bytes into a single value of 16 bits.
+  return ((uint16_t)value[1] << 8) + (uint16_t)value[0];
+}
+
+/*!
+    @brief  Writes 8-bits to the specified destination register
+    @param  reg the register address to write to
+    @param  value the value to write
+*/
+void Adafruit_MPR121::writeRegister(uint8_t reg, uint8_t value) {
+  // MPR121 must be put in Stop Mode to write to most registers
+  bool stop_required = true;
+
+  // first get the current set value of the MPR121_ECR register
+  uint8_t ecr_backup = readRegister8(MPR121_ECR);
+  if ((reg == MPR121_ECR) || ((0x73 <= reg) && (reg <= 0x7A))) {
+    stop_required = false;
+  }
+
+  if (stop_required) {
+    // clear this register to set stop mode
+    writeRegister(MPR121_ECR, 0x00);
+  }
+
+  // Write to the register by writing the address first then writing
+  // the intended value for the register
+  char reg_addr[2] = {reg, 0x00};  // Adafruit's library uses TWO bytes addr (see readRegister8)
+  i2c_dev->write(i2c_addr, reg_addr, 2);
+  i2c_dev->write(i2c_addr, (char*)&value, 1);
+
+  if (stop_required) {
+    // write back the previous set ECR settings
+    char ecr_addr[2] = {MPR121_ECR, 0x00};
+    i2c_dev->write(i2c_addr, ecr_addr, 2);
+    i2c_dev->write(i2c_addr, (char*)&ecr_backup, 1);
+  }
+}
\ No newline at end of file