Home | History | Annotate | Download | only in mpr121
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2014 Intel Corporation.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be
     14  * included in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 #include <iostream>
     26 #include <string>
     27 #include <stdexcept>
     28 
     29 #include "mpr121.h"
     30 
     31 using namespace upm;
     32 using namespace std;
     33 
     34 
     35 MPR121::MPR121(int bus, uint8_t address) : m_i2c(bus)
     36 {
     37   m_addr = address;
     38   mraa::Result ret = m_i2c.address(m_addr);
     39 
     40   if (ret != mraa::SUCCESS)
     41     {
     42       throw std::invalid_argument(std::string(__FUNCTION__) +
     43                                   ": mraa_i2c_address() failed");
     44       return;
     45     }
     46 
     47   m_buttonStates = 0;
     48   m_overCurrentFault = false;
     49 }
     50 
     51 mraa::Result MPR121::writeBytes(uint8_t reg, uint8_t *buffer, int len)
     52 {
     53   if (!len || !buffer)
     54     return mraa::SUCCESS;
     55 
     56   // create a buffer 1 byte larger than the supplied buffer,
     57   // store the register in the first byte
     58   uint8_t buf2[len + 1];
     59 
     60   buf2[0] = reg;
     61 
     62   // copy in the buffer after the reg byte
     63   for (int i=1; i<(len + 1); i++)
     64     buf2[i] = buffer[i-1];
     65 
     66   m_i2c.address(m_addr);
     67 
     68   return m_i2c.write(buf2, len + 1);
     69 }
     70 
     71 int MPR121::readBytes(uint8_t reg, uint8_t *buffer, int len)
     72 {
     73   if (!len || !buffer)
     74     return 0;
     75 
     76   // The usual m_i2c.read() does not work here, so we need to
     77   // read each byte individually.
     78   for (int i=0; i<len; i++)
     79     buffer[i] = m_i2c.readReg(reg + i);
     80 
     81   return len;
     82 }
     83 
     84 bool MPR121::configAN3944()
     85 {
     86   // Configure the mpr121 chip as recommended in the AN3944 MPR121
     87   // Quick Start Guide
     88 
     89   mraa::Result rv;
     90 
     91   // First, turn off all electrodes by zeroing out the Electrode Configuration
     92   // register.
     93   // If this one fails, it's unlikely any of the others will succeed.
     94   uint8_t eleConf = 0x00;
     95   if ((rv = writeBytes(0x5e, &eleConf, 1)) != mraa::SUCCESS)
     96     {
     97       throw std::runtime_error(std::string(__FUNCTION__) +
     98                                ": writeBytes(0x5e) failed");
     99       return false;
    100     }
    101 
    102   // Section A
    103   // Filtering when data is greater than baseline
    104   // regs 0x2b-0x2e
    105   uint8_t sectA[] = { 0x01, 0x01, 0x00, 0x00 };
    106   if ((rv = writeBytes(0x2b, sectA, 4)) != mraa::SUCCESS)
    107     {
    108       throw std::runtime_error(std::string(__FUNCTION__) +
    109                                ": writeBytes(0x2b) failed");
    110       return false;
    111     }
    112 
    113   // Section B
    114   // Filtering when data is less than baseline
    115   // regs 0x2f-0x32
    116   uint8_t sectB[] = { 0x01, 0x01, 0xff, 0x02 };
    117   if ((rv = writeBytes(0x2f, sectB, 4)) != mraa::SUCCESS)
    118     {
    119       throw std::runtime_error(std::string(__FUNCTION__) +
    120                                ": writeBytes(0x2f) failed");
    121       return false;
    122     }
    123 
    124   // Section C
    125   // Touch Threshold/Release registers, ELE0-ELE11
    126   // regs 0x41-0x58
    127   //                __T_  __R_
    128   uint8_t sectC[] = { 0x0f, 0x0a,
    129                       0x0f, 0x0a,
    130                       0x0f, 0x0a,
    131                       0x0f, 0x0a,
    132                       0x0f, 0x0a,
    133                       0x0f, 0x0a,
    134                       0x0f, 0x0a,
    135                       0x0f, 0x0a,
    136                       0x0f, 0x0a,
    137                       0x0f, 0x0a,
    138                       0x0f, 0x0a,
    139                       0x0f, 0x0a };
    140   if ((rv = writeBytes(0x41, sectC, 24)) != mraa::SUCCESS)
    141     {
    142       throw std::runtime_error(std::string(__FUNCTION__) +
    143                                ": writeBytes(0x41) failed");
    144       return false;
    145     }
    146 
    147   // Section D
    148   // Filter configuration
    149   // reg 0x5d
    150   uint8_t filterConf = 0x04;
    151   if ((rv = writeBytes(0x5d, &filterConf, 1)) != mraa::SUCCESS)
    152     {
    153       throw std::runtime_error(std::string(__FUNCTION__) +
    154                                ": writeBytes(0x5d) failed");
    155       return false;
    156     }
    157 
    158   // Section F
    159   // Autoconfiguration registers
    160   // regs 0x7b-0x7f
    161   uint8_t sectF0 = 0x0b;
    162   if ((rv = writeBytes(0x7b, &sectF0, 1)) != mraa::SUCCESS)
    163     {
    164       throw std::runtime_error(std::string(__FUNCTION__) +
    165                                ": writeBytes(0x7b) failed");
    166       return false;
    167     }
    168   uint8_t sectF1[] = { 0x9c, 0x65, 0x8c };
    169   if ((rv = writeBytes(0x7d, sectF1, 3)) != mraa::SUCCESS)
    170     {
    171       throw std::runtime_error(std::string(__FUNCTION__) +
    172                                ": writeBytes(0x7d) failed");
    173       return false;
    174     }
    175 
    176   // Section E - this one must be set last, and switches to run mode
    177   // Enable all 12 electrodes, and set a pre-calibration to avoid
    178   // excessive calibration delay on startup.
    179   // reg 0x5e
    180   eleConf = 0x8c;
    181   if ((rv = writeBytes(0x5e, &eleConf, 1)) != mraa::SUCCESS)
    182     {
    183       throw std::runtime_error(std::string(__FUNCTION__) +
    184                                ": writeBytes(0x5e) failed");
    185       return false;
    186     }
    187 
    188   return true;
    189 }
    190 
    191 void MPR121::readButtons()
    192 {
    193   uint8_t rv;
    194   uint8_t buffer[2];
    195 
    196   // read in the 2 bytes at register 0x00-0x01, and setup the member
    197   // variables accordingly.
    198 
    199   readBytes(0x00, buffer, 2);
    200 
    201   m_buttonStates = (buffer[0] | ((buffer[1] & 0x1f) << 8));
    202   if (buffer[1] & 0x80)
    203     m_overCurrentFault = true;
    204   else
    205     m_overCurrentFault = false;
    206 
    207   return;
    208 }
    209