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, §F0, 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