1 /*
2 * Author: Jon Trulson <jtrulson@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
MPR121(int bus,uint8_t address)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
writeBytes(uint8_t reg,uint8_t * buffer,int len)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
readBytes(uint8_t reg,uint8_t * buffer,int len)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
configAN3944()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
readButtons()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