From 25f4cb0be14e14f0850aeca0b704bac94ca0e2ae Mon Sep 17 00:00:00 2001 From: Abhishek Malik Date: Fri, 9 Sep 2016 19:12:25 -0700 Subject: [PATCH] MPR121: Added C Source Signed-off-by: Abhishek Malik --- src/mpr121/CMakeLists.txt | 14 ++- src/mpr121/mpr121.c | 205 ++++++++++++++++++++++++++++++++++++++ src/mpr121/mpr121.h | 111 +++++++++++++++++++++ src/mpr121/mpr121_fti.c | 75 ++++++++++++++ 4 files changed, 400 insertions(+), 5 deletions(-) create mode 100644 src/mpr121/mpr121.c create mode 100644 src/mpr121/mpr121.h create mode 100644 src/mpr121/mpr121_fti.c diff --git a/src/mpr121/CMakeLists.txt b/src/mpr121/CMakeLists.txt index 669a59e5..c8d2b3d1 100644 --- a/src/mpr121/CMakeLists.txt +++ b/src/mpr121/CMakeLists.txt @@ -1,5 +1,9 @@ -set (libname "mpr121") -set (libdescription "upm mpr121 I2C Touch module") -set (module_src ${libname}.cxx) -set (module_hpp ${libname}.hpp) -upm_module_init() +upm_mixed_module_init (NAME mpr121 + DESCRIPTION "upm mpr121sensor module" + C_HDR mpr121.h + C_SRC mpr121.c + CPP_HDR mpr121.hpp + CPP_SRC mpr121.cxx + FTI_SRC mpr121_fti.c + CPP_WRAPS_C + REQUIRES mraa) \ No newline at end of file diff --git a/src/mpr121/mpr121.c b/src/mpr121/mpr121.c new file mode 100644 index 00000000..c63fb8df --- /dev/null +++ b/src/mpr121/mpr121.c @@ -0,0 +1,205 @@ +/* + * Author: Jon Trulson + * Abhishek Malik + * Copyright (c) 2014 Intel Corporation. + * + * 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. + */ + +#include "mpr121.h" + +mpr121_context mpr121_init(int bus, uint8_t address){ + mpr121_context dev = (mpr121_context)malloc(sizeof(struct _mpr121_context)); + + if (!dev) + return NULL; + + dev->bus = bus; + dev->address = address; + dev->i2c = mraa_i2c_init(dev->bus); + + if(dev->i2c == NULL){ + free(dev); + return NULL; + } + + if (mraa_i2c_address(dev->i2c, dev->address) != MRAA_SUCCESS){ + free(dev); + printf("error using i2c address: %x\n", dev->address); + return NULL; + } + + dev->over_current_fault = false; + return dev; +} + +void mpr121_close(mpr121_context dev){ + mraa_i2c_stop(dev->i2c); + free(dev); +} + +upm_result_t mpr121_write_bytes(mpr121_context dev, uint8_t reg, + uint8_t *buffer, int len){ + if(!len || !buffer) + return UPM_ERROR_INVALID_SIZE; + + // create a buffer 1 byte larger than the supplied buffer, + // store the register in the first byte + uint8_t buf2[len + 1]; + buf2[0] = reg; + + // copy in the buffer after the reg byte + + int i; + for(i=1; i<(len + 1); i++) + buf2[i] = buffer[i-1]; + + if(mraa_i2c_address(dev->i2c, dev->address) != MRAA_SUCCESS){ + printf("write byte error address\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + if(mraa_i2c_write(dev->i2c, buf2, len+1) != MRAA_SUCCESS){ + printf("write byte error while writing\n"); + return UPM_ERROR_OPERATION_FAILED; + } + return UPM_SUCCESS; +} + +upm_result_t mpr121_read_bytes(mpr121_context dev, uint8_t reg, + uint8_t *buffer, int len){ + if(!len || !buffer) + return UPM_ERROR_INVALID_SIZE; + + // The usual m_i2c.read() does not work here, so we need to + // read each byte individually. + int i; + for (i=0; ii2c, reg+i); + + return UPM_SUCCESS; +} + +upm_result_t mpr121_read_buttons(mpr121_context dev, uint32_t* states, + int num){ + int len = 2; + uint8_t buffer[2]; + + // read in the 2 bytes at register 0x00-0x01, and setup the member + // variables accordingly. + mpr121_read_bytes(dev, 0x00, buffer, len); + + *states = (buffer[0] | ((buffer[1] & 0x1f) << 8)); + if (buffer[1] & 0x80) + dev->over_current_fault = true; + else + dev->over_current_fault = false; + + return UPM_SUCCESS; +} + +upm_result_t mpr121_config_an3944(mpr121_context dev){ + // Configure the mpr121 chip as recommended in the AN3944 MPR121 + // Quick Start Guide + // First, turn off all electrodes by zeroing out the Electrode Configuration + // register. + // If this one fails, it's unlikely any of the others will succeed. + uint8_t eleConf = 0x00; + if (mpr121_write_bytes(dev, 0x5e, &eleConf, 1) != UPM_SUCCESS){ + printf("write to electrode configuration register failed\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + // Section A + // Filtering when data is greater than baseline + // regs 0x2b-0x2e + + uint8_t sectA[] = {0x01, 0x01, 0x00, 0x00}; + if (mpr121_write_bytes(dev, 0x2b, sectA, 4) != UPM_SUCCESS){ + printf("write to section a failed\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + // Section B + // Filtering when data is less than baseline + // regs 0x2f-0x32 + + uint8_t sectB[] = {0x01, 0x01, 0xff, 0x02}; + if (mpr121_write_bytes(dev, 0x2f, sectB, 4) != UPM_SUCCESS){ + printf("write to section b failed\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + // Section C + // Touch Threshold/Release registers, ELE0-ELE11 + // regs 0x41-0x58 + // __T_ __R_ + uint8_t sectC[] = {0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a, + 0x0f, 0x0a}; + + if (mpr121_write_bytes(dev, 0x41, sectC, 24) != UPM_SUCCESS){ + printf("failed to configure touch threshold/release regs\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + // Section D + // Filter configuration + // reg 0x5d + uint8_t filterConf = 0x04; + if (mpr121_write_bytes(dev, 0x5d, &filterConf, 1) != UPM_SUCCESS){ + printf("unable to configure filters\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + // Section F + // Autoconfiguration registers + // regs 0x7b-0x7f + uint8_t sectF0 = 0x0b; + if (mpr121_write_bytes(dev, 0x7b, §F0, 1) != UPM_SUCCESS){ + printf("unable to configure auto config regs\n"); + return UPM_ERROR_OPERATION_FAILED; + } + + uint8_t sectF1[] = {0x9c, 0x65, 0x8c}; + if (mpr121_write_bytes(dev, 0x7d, sectF1, 3) != UPM_SUCCESS){ + return UPM_ERROR_OPERATION_FAILED; + } + + // Section E - this one must be set last, and switches to run mode + // Enable all 12 electrodes, and set a pre-calibration to avoid + // excessive calibration delay on startup. + // reg 0x5e + eleConf = 0x8c; + if (mpr121_write_bytes(dev, 0x5e, &eleConf, 3) != UPM_SUCCESS){ + return UPM_ERROR_OPERATION_FAILED; + } + + return UPM_SUCCESS; +} diff --git a/src/mpr121/mpr121.h b/src/mpr121/mpr121.h new file mode 100644 index 00000000..69b815ab --- /dev/null +++ b/src/mpr121/mpr121.h @@ -0,0 +1,111 @@ +/* + * Author: Jon Trulson + * Abhishek Malik + * Copyright (c) 2014 Intel Corporation. + * + * 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 +#include "upm.h" +#include "mraa/i2c.h" + +#define MPR121_I2C_BUS 0 +#define MPR121_DEFAULT_I2C_ADDR 0x5a + +/** + * device context + */ +typedef struct _mpr121_context { + mraa_i2c_context i2c; + int bus; + uint8_t address; + uint8_t over_current_fault; +} *mpr121_context; + +/** + * MPR121 Init function + * + * @param bus i2c bus + * @param address i2c address of the sensor + * @return void* pointer to the sensor struct + */ +mpr121_context mpr121_init(int bus, uint8_t address); + +/** + * MPR121 Close function + * + * @param dev pointer to sensor struct + */ +void mpr121_close(mpr121_context dev); + +/** + * Sets up a default configuration, based on Application Note 3944 + * (AN3944): + * http://cache.freescale.com/files/sensors/doc/app_note/AN3944.pdf + * + * After configuration, the sensor is left in the run state. + * + * @param dev pointer to the sensor struct + * @return upm_result_t UPM success/error code + */ +upm_result_t mpr121_config_an3944(mpr121_context dev); + +/** + * Function to read the individual button values + * + * @param dev pointer to the sensor struct + * @param states Pointer to store the states of the individual buttons + * @param num used to retrieve the state of a particular button + * @return upm_result_t UPM success/error code + */ +upm_result_t mpr121_read_buttons(mpr121_context dev, uint32_t* states, int num); + +/** + * Function used to write multiple bytes to the i2c bus + * + * @param dev sensor struct + * @param reg i2c register to read from + * @param *buffer pointer that contains the values that have to be + * written to the registers + * @param len length of the values that have to be written to the regs + * @return upm_result_t UPM success/error code + */ +upm_result_t mpr121_write_bytes(mpr121_context dev, uint8_t reg, + uint8_t *buffer, int len); + +/** + * Function used to read multiple bytes from the i2c bus + * + * @param dev sensor struct + * @param reg i2c register to read from + * @param *buffer pointer that contains the values that have been + * read from the registers + * @param len length of the values that have to be read + * @return upm_result_t UPM success/error code + */ + +upm_result_t mpr121_read_bytes(mpr121_context dev, uint8_t reg, + uint8_t *buffer, int len); + +#endif /* MPR121_H_ */ diff --git a/src/mpr121/mpr121_fti.c b/src/mpr121/mpr121_fti.c new file mode 100644 index 00000000..d6fc7b45 --- /dev/null +++ b/src/mpr121/mpr121_fti.c @@ -0,0 +1,75 @@ +/* + * Author: Jon Trulson + * Abhishek Malik + * Copyright (c) 2014 Intel Corporation. + * + * 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. + */ + +#include "mpr121.h" +#include "upm_fti.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_mpr121_name[] = "MPR121"; +const char upm_mpr121_description[] = "MPR121 Touch Sensor"; +const upm_protocol_t upm_mpr121_protocol[] = {UPM_I2C}; +const upm_sensor_t upm_mpr121_category[] = {UPM_SWITCH}; + +// forward declarationss +const upm_sensor_descriptor_t upm_mpr121_get_descriptor (); +const void* upm_mpr121_get_ft(upm_sensor_t sensor_type); +void* upm_mpr121_init_name(); +void upm_mpr121_close(void* dev); + +const upm_sensor_descriptor_t upm_mpr121_get_descriptor (){ + upm_sensor_descriptor_t usd; + usd.name = upm_mpr121_name; + usd.description = upm_mpr121_description; + usd.protocol_size = 1; + usd.protocol = upm_mpr121_protocol; + usd.category_size = 1; + usd.category = upm_mpr121_category; + return usd; +} + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = &upm_mpr121_init_name, + .upm_sensor_close = &upm_mpr121_close, + .upm_sensor_get_descriptor = &upm_mpr121_get_descriptor +}; + +const void* upm_mpr121_get_ft(upm_sensor_t sensor_type){ + if(sensor_type == UPM_SENSOR){ + return &ft; + } + return NULL; +} + +void* upm_mpr121_init_name(){ + return NULL; +} + +void upm_mpr121_close(void* dev){ + mpr121_close((mpr121_context)dev); +}