Files
esp-idf-mpr121/components/mpr121/mpr121.h
2025-06-14 13:19:06 +09:00

434 lines
15 KiB
C

/*******************************************************************************
Bare Conductive MPR121 library
------------------------------
MPR121.h - MPR121 class header file
Based on code by Jim Lindblom and plenty of inspiration from the Freescale
Semiconductor datasheets and application notes.
Bare Conductive code written by Stefan Dzisiewski-Smith, Peter Krige
and Szymon Kaliski.
This work is licensed under a MIT license https://opensource.org/licenses/MIT
Copyright (c) 2016, Bare Conductive
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*******************************************************************************/
#ifndef MPR121_H
#define MPR121_H
#include "mpr121_defs.h"
// idea behind this is to create a settings structure that we can use to store
// all the setup variables for a particular setup - comes pre-instantiated with
// defaults and can be easily tweaked - we pass by reference (as a pointer) to
// save RAM
typedef struct
{
// touch and release thresholds
uint8_t _TTHRESH;
uint8_t _RTHRESH;
uint8_t _INTERRUPT;
// general electrode touch sense baseline filters
// rising filter
uint8_t _MHDR;
uint8_t _NHDR;
uint8_t _NCLR;
uint8_t _FDLR;
// falling filter
uint8_t _MHDF;
uint8_t _NHDF;
uint8_t _NCLF;
uint8_t _FDLF;
// touched filter
uint8_t _NHDT;
uint8_t _NCLT;
uint8_t _FDLT;
// proximity electrode touch sense baseline filters
// rising filter
uint8_t _MHDPROXR;
uint8_t _NHDPROXR;
uint8_t _NCLPROXR;
uint8_t _FDLPROXR;
// falling filter
uint8_t _MHDPROXF;
uint8_t _NHDPROXF;
uint8_t _NCLPROXF;
uint8_t _FDLPROXF;
// touched filter
uint8_t _NHDPROXT;
uint8_t _NCLPROXT;
uint8_t _FDLPROXT;
// debounce settings
uint8_t _DTR;
// configuration registers
uint8_t _AFE1;
uint8_t _AFE2;
uint8_t _ECR;
// auto-configuration registers
uint8_t _ACCR0;
uint8_t _ACCR1;
uint8_t _USL;
uint8_t _LSL;
uint8_t _TL;
} MPR121_settings_type;
typedef struct {
uint8_t address;
MPR121_settings_type defaultSettings;
uint8_t ECR_backup; // so we can re-enable the correct number of electrodes
// when recovering from stop mode
uint8_t error;
bool running;
uint8_t interruptPin;
int16_t filteredData[13];
int16_t baselineData[13];
uint16_t touchData;
uint16_t lastTouchData;
bool autoTouchStatusFlag; // we use this to catch touch / release events that happen
// during other update calls
} MPR121_t;
// GPIO pin function constants
enum mpr121_pinf_type
{
// INPUT and OUTPUT (and others) are already defined by Arduino, use its definitions if they exist
#ifndef INPUT
INPUT, // digital input
#endif
#ifndef INPUT_PULLUP
INPUT_PULLUP, // digital input with pullup
#endif
#ifndef INPUT_PULLDOWN
INPUT_PULLDOWN, // digital input with pulldown
#endif
#ifndef OUTPUT
OUTPUT, // digital output (push-pull)
#endif
#ifndef OUTPUT_HIGHSIDE
OUTPUT_HIGHSIDE, // digital output, open collector (high side)
#endif
#ifndef OUTPUT_LOWSIDE
OUTPUT_LOWSIDE // digital output, open collector (low side)
#endif
};
// "13th electrode" proximity modes
// N.B. this does not relate to normal proximity detection
// see http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf
enum mpr121_proxmode_type
{
PROX_DISABLED, // proximity mode disabled
PROX_0_1, // proximity mode for ELE0..ELE1
PROX_0_3, // proximity mode for ELE0..ELE3
PROX_0_11 // proximity mode for ELE0..ELE11
};
// baseline calibration lock modes
enum mpr121_cal_lock_type
{
CAL_LOCK_ENABLED, // baseline tracking enabled, no value change on run
CAL_LOCK_DISABLED, // baseline tracking disabled
CAL_LOCK_ENABLED_5_BIT_COPY, // baseline tracking enabled, load 5 MSB of filtered data on entering run mode
CAL_LOCK_ENABLED_10_BIT_COPY // baseline tracking enabled, load 10 MSB of filtered data on entering run mode
};
// error codes
enum mpr121_error_type
{
NO_ERROR, // no error
RETURN_TO_SENDER, // not implemented
ADDRESS_UNKNOWN, // no MPR121 found at specified I2C address
READBACK_FAIL, // readback from MPR121 was not as expected
OVERCURRENT_FLAG, // overcurrent on REXT pin
OUT_OF_RANGE, // autoconfiguration fail, often a result of shorted pins
NOT_INITED // device has not been initialised
};
// sample intervals
enum mpr121_sample_interval_type
{
SAMPLE_INTERVAL_1MS = 0x00,
SAMPLE_INTERVAL_2MS = 0x01,
SAMPLE_INTERVAL_4MS = 0x02,
SAMPLE_INTERVAL_8MS = 0x03,
SAMPLE_INTERVAL_16MS = 0x04,
SAMPLE_INTERVAL_32MS = 0x05,
SAMPLE_INTERVAL_64MS = 0x06,
SAMPLE_INTERVAL_128MS = 0x07
};
// charge / discharge times (CDT)
enum mpr121_CDT_type
{
CDT_500NS = 0x01,
CDT_1US = 0x02,
CDT_2US = 0x03,
CDT_4US = 0x04,
CDT_8US = 0x05,
CDT_16US = 0x06,
CDT_32US = 0x07
};
// first filter iterations (FFI)
enum mpr121_FFI_type
{
FFI_6 = 0x00,
FFI_10 = 0x01,
FFI_18 = 0x02,
FFI_34 = 0x03
};
// second filter iterations (SFI)
enum mpr121_SFI_type
{
SFI_4 = 0x00,
SFI_6 = 0x01,
SFI_10 = 0x02,
SFI_18 = 0x03
};
// -------------------- BASIC FUNCTIONS --------------------
void MPR121_type(MPR121_t * dev);
// begin() must be called before using any other function
// address is optional, default is 0x5C
bool MPR121_begin(MPR121_t * dev, int16_t address, int16_t touchThreshold, int16_t releaseThreshold, int16_t interruptPin, int16_t sda, int16_t scl);
// read touch and release threshold saved to EEPROM using
// saveTouchThreshold and releaseTouchThreshold
void MPR121_restoreSavedThresholds(MPR121_t * dev);
// reset saved thresholds to 255, which will force the MPR121
// to load default thresholds
void MPR121_clearSavedThresholds(MPR121_t * dev);
// I2C speed control functions - goFast() sets the SCL clock
// to 400kHz - goSlow() sets the SCL clock to 100kHz. Defaults
// to 100kHz and affects all devices on the I2C bus. Included
// for speed freaks only.
void MPR121_goSlow(MPR121_t * dev);
void MPR121_goFast(MPR121_t * dev);
// getError() returns an mpr121_error_type indicating the current
// error on the MPR121 - clearError() clears this
uint8_t MPR121_getError(MPR121_t * dev);
void MPR121_clearError(MPR121_t * dev);
// returns status of the MPR121 INT pin as read via digitalRead() on the
// Arduino board - this tells us if there has been a change in touch status
// on any active electrode since we last read any data
bool MPR121_touchStatusChanged(MPR121_t * dev);
// updates the data from the MPR121 into our internal buffer
// updateTouchData() does this only for touch on / off status
// updateBaseLineData() does this for background baseline
// updateFilteredData() does this for continuous proximity data
// updateAll() does all three
// the appropriate function from these must be called before data
// from getTouchData(), getFilteredData() etc. can be considered
// valid
void MPR121_updateTouchData(MPR121_t * dev);
bool MPR121_updateBaselineData(MPR121_t * dev);
bool MPR121_updateFilteredData(MPR121_t * dev);
void MPR121_updateAll(MPR121_t * dev);
// returns a boolean indicating the touch status of a given electrode
bool MPR121_getTouchData(MPR121_t * dev, uint8_t electrode);
// returns the number of touches currently detected
uint8_t MPR121_getNumTouches(MPR121_t * dev);
bool MPR121_getLastTouchData(MPR121_t * dev, uint8_t electrode);
// returns continous proximity or baseline data for a given electrode
int MPR121_getFilteredData(MPR121_t * dev, uint8_t electrode);
int MPR121_getBaselineData(MPR121_t * dev, uint8_t electrode);
// returns boolean indicating whether a new touch or release has been
// detected since the last time updateTouchData() was called
bool MPR121_isNewTouch(MPR121_t * dev, uint8_t electrode);
bool MPR121_isNewRelease(MPR121_t * dev, uint8_t electrode);
// sets touch and release thresholds either for all electrodes, or
// for a specfic electrode - higher values = less sensitive and
// release threshold must ALWAYS be lower than touch threshold
void MPR121_setTouchThresholdAll(MPR121_t * dev, uint8_t val);
void MPR121_setTouchThreshold(MPR121_t * dev, uint8_t electrode, uint8_t val);
void MPR121_saveTouchThreshold(MPR121_t * dev, uint8_t electrode, uint8_t val);
void MPR121_setReleaseThresholdAll(MPR121_t * dev, uint8_t val);
void MPR121_setReleaseThreshold(MPR121_t * dev, uint8_t electrode, uint8_t val);
void MPR121_saveReleaseThreshold(MPR121_t * dev, uint8_t electrode, uint8_t val);
// returns the current touch or release threshold for a specified electrode
uint8_t MPR121_getTouchThreshold(MPR121_t * dev, uint8_t electrode);
uint8_t MPR121_getReleaseThreshold(MPR121_t * dev, uint8_t electrode);
// ------------------ ADVANCED FUNCTIONS ------------------
void MPR121_settingsType(MPR121_settings_type *defaultSettings);
// applies a complete array of settings from an
// MPR121_settings_type variable passed as a pointer
// useful if you want to do a bulk setup of the device
//void MPR121_applySettings(MPR121_t * dev, MPR121_settings_type *settings);
void MPR121_applySettings(MPR121_t * dev);
// setRegister() and getRegister() manipulate registers on
// the MPR121 directly, whilst correctly stopping and
// restarting the MPR121 if necessary
void MPR121_setRegister(MPR121_t * dev, uint8_t reg, uint8_t value);
uint8_t MPR121_getRegister(MPR121_t * dev, uint8_t reg);
// stop() and run() take the MPR121 in and out of stop mode
// which reduces current consumption to 3uA
void MPR121_run(MPR121_t * dev);
void MPR121_stop(MPR121_t * dev);
// resets the MPR121
bool MPR121_reset(MPR121_t * dev);
// tells us if we are in run mode, and if we have inited the
// MPR121
bool MPR121_isRunning(MPR121_t * dev);
bool MPR121_isInited(MPR121_t * dev);
// sets the pin that the MPR121 INT output is connected to on the
// Arduino board - does not have to be a hardware interrupt pin
// if it is, however, an interrupt service routine will automatically
// set an internal flag when a touch event occurs - thus minimising
// lost events if you are also reading other data types (filtered data,
// baseline data)
void MPR121_setInterruptPin(MPR121_t * dev, uint8_t pin);
// set number of electrodes to use to generate virtual "13th"
// proximity electrode
// see http://cache.freescale.com/files/sensors/doc/app_note/AN3893.pdf
//
// N.B. - this is not related to general proximity detection or
// reading back continuous proximity data
void MPR121_setProxMode(MPR121_t * dev, uint8_t mode);
// set calibration lock mode for baseline tracking
// this can be useful to disable baseline tracking, set it to
// current values (with 5 or 10 most significant bits copied across from
// current filtered values to baseline the next time run mode is entered)
// or leave it enabled with its current values in place (and no copy-across
// when run mode is re-entered)
void MPR121_setCalibrationLock(MPR121_t * dev, uint8_t lock);
// set global or per-electrode charge / discharge current in microamps
// current_uA is valid 0..63 (for global value, 0 means use electrode-specific setting)
// electrode is valid 0..12 (includes virtual proximity electrode)
void MPR121_setGlobalCDC(MPR121_t * dev, uint8_t CDC);
void MPR121_setElectrodeCDC(MPR121_t * dev, uint8_t electrode, uint8_t CDC);
// runs hardware routine for automatic electrode calibration for all electrodes
// this is implemented in the MPR121 hardware itself
// fixedChargeTime flag keeps CDT constant (useful for carbon-based inks with high lead-in resistance)
bool MPR121_autoSetElectrodes(MPR121_t * dev, uint16_t VCC_mV, bool fixedChargeTime);
bool MPR121_autoSetElectrodesDefault(MPR121_t * dev, bool fixedChargeTime);
// software routine to keep CDT constant and adjust CDC to fit
bool MPR121_autoSetElectrodeCDC(MPR121_t * dev, uint8_t electrode, uint16_t VCC_mV);
bool MPR121_autoSetElectrodeCDCDefault(MPR121_t * dev, uint8_t electrode);
bool MPR121_autoSetElectrodeCDCAll(MPR121_t * dev); // runs autocal for all electrodes
// set global or per-electrode charge / discharge time
// CDT follows a 0.5(2^(n-1))uS rule, so an enum type is provided for clarity
void MPR121_setGlobalCDT(MPR121_t * dev, uint8_t CDT);
void MPR121_setElectrodeCDT(MPR121_t * dev, uint8_t electrode, uint8_t CDT);
// Set / get the number of enabled electrodes, from 0 (which implicitly enters
// stop mode) up to 12. This allows for a reduction in power consumption
// when using fewer electrodes and faster update rates. Implementation is
// similar to setNumDigPins below, butwith a different intent.
void MPR121_setNumEnabledElectrodes(MPR121_t * dev, uint8_t numElectrodes);
uint8_t MPR121_getNumEnabledElectrodes(MPR121_t * dev);
// Enables GPIO mode for up to 8 of the MPR121 electrodes
// starts with electrode 11 - i.e. setNumDigPins(1) sets just
// electrode 11 as GPIO, setNumDigPins(2) sets electrodes 11
// & 10 as GPIO, and so on. Electrodes 0 to 3 cannot be used
// as GPIO
//
// N.B. electrodes are 3.3V and WILL be damaged if driven by
// a greater voltage
void MPR121_setNumDigPins(MPR121_t * dev, uint8_t numPins);
// Sets pin mode for an electrode already set as GPIO by
// setNumDigPins() - see section "GPIO pin function constants"
// for details
#if 0
void MPR121_pinMode(MPR121_t * dev, uint8_t electrode, mpr121_pinf_type mode);
#endif
void MPR121_pinMode(MPR121_t * dev, uint8_t electrode, int mode);
// Similar to digitalWrite in Arduino for GPIO electrode
void MPR121_digitalWrite(MPR121_t * dev, uint8_t electrode, uint8_t val);
// Toggles electrode set as GPIO output
void MPR121_digitalToggle(MPR121_t * dev, uint8_t electrode);
// Reads electrode set as GPIO input
bool MPR121_digitalRead(MPR121_t * dev, uint8_t electrode);
// Writes PWM value to electrode set as GPIO output - very limited
// (4 bit, although input to function is 0..255 to match Arduino,
// internally reduced to 4 bit) and broken on ELE9 and ELE10
// see https://community.freescale.com/thread/305474
void MPR121_analogWrite(MPR121_t * dev, uint8_t electrode, uint8_t val);
// Sets the sample period of the MPR121 - the time between capacitive
// readings. Higher values consume less power, but are less responsive.
void MPR121_setSamplePeriod(MPR121_t * dev, uint8_t period);
void MPR121_setFFI(MPR121_t * dev, uint8_t FFI);
void MPR121_setSFI(MPR121_t * dev, uint8_t SFI);
//extern MPR121_type MPR121;
#endif // MPR121_H