mirror of
https://github.com/nopnop2002/esp-idf-mpr121.git
synced 2025-12-16 17:34:31 +03:00
434 lines
15 KiB
C
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
|
|
|