robert@501
|
1 /*
|
robert@501
|
2 * I2C_MPR121.cpp
|
robert@501
|
3 *
|
robert@501
|
4 * Created on: Oct 14, 2013
|
robert@501
|
5 * Author: Victor Zappi
|
robert@501
|
6 */
|
robert@501
|
7
|
robert@501
|
8
|
robert@501
|
9 #include "I2C_MPR121.h"
|
robert@501
|
10
|
robert@501
|
11 I2C_MPR121::I2C_MPR121() {
|
robert@501
|
12
|
robert@501
|
13 }
|
robert@501
|
14
|
robert@501
|
15 boolean I2C_MPR121::begin(uint8_t bus, uint8_t i2caddr) {
|
robert@501
|
16 _i2c_address = i2caddr;
|
robert@501
|
17
|
robert@501
|
18 if(initI2C_RW(bus, i2caddr, 0) > 0)
|
robert@501
|
19 return false;
|
robert@501
|
20
|
robert@501
|
21 // soft reset
|
robert@501
|
22 writeRegister(MPR121_SOFTRESET, 0x63);
|
robert@501
|
23 usleep(1000);
|
robert@501
|
24 //delay(1);
|
robert@501
|
25 for (uint8_t i=0; i<0x7F; i++) {
|
robert@501
|
26 // Serial.print("$"); Serial.print(i, HEX);
|
robert@501
|
27 // Serial.print(": 0x"); Serial.println(readRegister8(i));
|
robert@501
|
28 }
|
robert@501
|
29
|
robert@501
|
30
|
robert@501
|
31 writeRegister(MPR121_ECR, 0x0);
|
robert@501
|
32
|
robert@501
|
33 uint8_t c = readRegister8(MPR121_CONFIG2);
|
robert@501
|
34
|
robert@501
|
35 if (c != 0x24) {
|
robert@501
|
36 rt_printf("MPR121 read 0x%x instead of 0x24\n", c);
|
robert@501
|
37 return false;
|
robert@501
|
38 }
|
robert@501
|
39
|
robert@501
|
40 setThresholds(12, 6);
|
robert@501
|
41 writeRegister(MPR121_MHDR, 0x01);
|
robert@501
|
42 writeRegister(MPR121_NHDR, 0x01);
|
robert@501
|
43 writeRegister(MPR121_NCLR, 0x0E);
|
robert@501
|
44 writeRegister(MPR121_FDLR, 0x00);
|
robert@501
|
45
|
robert@501
|
46 writeRegister(MPR121_MHDF, 0x01);
|
robert@501
|
47 writeRegister(MPR121_NHDF, 0x05);
|
robert@501
|
48 writeRegister(MPR121_NCLF, 0x01);
|
robert@501
|
49 writeRegister(MPR121_FDLF, 0x00);
|
robert@501
|
50
|
robert@501
|
51 writeRegister(MPR121_NHDT, 0x00);
|
robert@501
|
52 writeRegister(MPR121_NCLT, 0x00);
|
robert@501
|
53 writeRegister(MPR121_FDLT, 0x00);
|
robert@501
|
54
|
robert@501
|
55 writeRegister(MPR121_DEBOUNCE, 0);
|
robert@501
|
56 writeRegister(MPR121_CONFIG1, 0x10); // default, 16uA charge current
|
robert@501
|
57 writeRegister(MPR121_CONFIG2, 0x20); // 0.5uS encoding, 1ms period
|
robert@501
|
58
|
robert@501
|
59 // writeRegister(MPR121_AUTOCONFIG0, 0x8F);
|
robert@501
|
60
|
robert@501
|
61 // writeRegister(MPR121_UPLIMIT, 150);
|
robert@501
|
62 // writeRegister(MPR121_TARGETLIMIT, 100); // should be ~400 (100 shifted)
|
robert@501
|
63 // writeRegister(MPR121_LOWLIMIT, 50);
|
robert@501
|
64 // enable all electrodes
|
robert@501
|
65 writeRegister(MPR121_ECR, 0x8F); // start with first 5 bits of baseline tracking
|
robert@501
|
66
|
robert@501
|
67 return true;
|
robert@501
|
68 }
|
robert@501
|
69
|
robert@501
|
70 void I2C_MPR121::setThresholds(uint8_t touch, uint8_t release) {
|
robert@501
|
71 for (uint8_t i=0; i<12; i++) {
|
robert@501
|
72 writeRegister(MPR121_TOUCHTH_0 + 2*i, touch);
|
robert@501
|
73 writeRegister(MPR121_RELEASETH_0 + 2*i, release);
|
robert@501
|
74 }
|
robert@501
|
75 }
|
robert@501
|
76
|
robert@501
|
77 uint16_t I2C_MPR121::filteredData(uint8_t t) {
|
robert@501
|
78 if (t > 12) return 0;
|
robert@501
|
79 return readRegister16(MPR121_FILTDATA_0L + t*2);
|
robert@501
|
80 }
|
robert@501
|
81
|
robert@501
|
82 uint16_t I2C_MPR121::baselineData(uint8_t t) {
|
robert@501
|
83 if (t > 12) return 0;
|
robert@501
|
84 uint16_t bl = readRegister8(MPR121_BASELINE_0 + t);
|
robert@501
|
85 return (bl << 2);
|
robert@501
|
86 }
|
robert@501
|
87
|
robert@501
|
88 uint16_t I2C_MPR121::touched(void) {
|
robert@501
|
89 uint16_t t = readRegister16(MPR121_TOUCHSTATUS_L);
|
robert@501
|
90 return t & 0x0FFF;
|
robert@501
|
91 }
|
robert@501
|
92
|
robert@501
|
93 /*********************************************************************/
|
robert@501
|
94
|
robert@501
|
95
|
robert@501
|
96 uint8_t I2C_MPR121::readRegister8(uint8_t reg) {
|
robert@501
|
97 unsigned char inbuf, outbuf;
|
robert@501
|
98 struct i2c_rdwr_ioctl_data packets;
|
robert@501
|
99 struct i2c_msg messages[2];
|
robert@501
|
100
|
robert@501
|
101 /*
|
robert@501
|
102 * In order to read a register, we first do a "dummy write" by writing
|
robert@501
|
103 * 0 bytes to the register we want to read from. This is similar to
|
robert@501
|
104 * the packet in set_i2c_register, except it's 1 byte rather than 2.
|
robert@501
|
105 */
|
robert@501
|
106 outbuf = reg;
|
robert@501
|
107 messages[0].addr = 0x5A;
|
robert@501
|
108 messages[0].flags = 0;
|
robert@501
|
109 messages[0].len = sizeof(outbuf);
|
robert@501
|
110 messages[0].buf = &outbuf;
|
robert@501
|
111
|
robert@501
|
112 /* The data will get returned in this structure */
|
robert@501
|
113 messages[1].addr = 0x5A;
|
robert@501
|
114 messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
|
robert@501
|
115 messages[1].len = sizeof(inbuf);
|
robert@501
|
116 messages[1].buf = &inbuf;
|
robert@501
|
117
|
robert@501
|
118 /* Send the request to the kernel and get the result back */
|
robert@501
|
119 packets.msgs = messages;
|
robert@501
|
120 packets.nmsgs = 2;
|
robert@501
|
121 if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
|
robert@501
|
122 rt_printf("Unable to send data");
|
robert@501
|
123 return 0;
|
robert@501
|
124 }
|
robert@501
|
125
|
robert@501
|
126 return inbuf;
|
robert@501
|
127 }
|
robert@501
|
128
|
robert@501
|
129 uint16_t I2C_MPR121::readRegister16(uint8_t reg) {
|
robert@501
|
130 unsigned char inbuf[2], outbuf;
|
robert@501
|
131 struct i2c_rdwr_ioctl_data packets;
|
robert@501
|
132 struct i2c_msg messages[2];
|
robert@501
|
133
|
robert@501
|
134 /*
|
robert@501
|
135 * In order to read a register, we first do a "dummy write" by writing
|
robert@501
|
136 * 0 bytes to the register we want to read from. This is similar to
|
robert@501
|
137 * the packet in set_i2c_register, except it's 1 byte rather than 2.
|
robert@501
|
138 */
|
robert@501
|
139 outbuf = reg;
|
robert@501
|
140 messages[0].addr = _i2c_address;
|
robert@501
|
141 messages[0].flags = 0;
|
robert@501
|
142 messages[0].len = sizeof(outbuf);
|
robert@501
|
143 messages[0].buf = &outbuf;
|
robert@501
|
144
|
robert@501
|
145 /* The data will get returned in this structure */
|
robert@501
|
146 messages[1].addr = _i2c_address;
|
robert@501
|
147 messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
|
robert@501
|
148 messages[1].len = sizeof(inbuf);
|
robert@501
|
149 messages[1].buf = inbuf;
|
robert@501
|
150
|
robert@501
|
151 /* Send the request to the kernel and get the result back */
|
robert@501
|
152 packets.msgs = messages;
|
robert@501
|
153 packets.nmsgs = 2;
|
robert@501
|
154 if(ioctl(i2C_file, I2C_RDWR, &packets) < 0) {
|
robert@501
|
155 rt_printf("Unable to send data");
|
robert@501
|
156 return 0;
|
robert@501
|
157 }
|
robert@501
|
158
|
robert@501
|
159 return (uint16_t)inbuf[0] | (((uint16_t)inbuf[1]) << 8);
|
robert@501
|
160 }
|
robert@501
|
161
|
robert@501
|
162 /**************************************************************************/
|
robert@501
|
163 /*!
|
robert@501
|
164 @brief Writes 8-bits to the specified destination register
|
robert@501
|
165 */
|
robert@501
|
166 /**************************************************************************/
|
robert@501
|
167 void I2C_MPR121::writeRegister(uint8_t reg, uint8_t value) {
|
robert@501
|
168 uint8_t buf[2] = { reg, value };
|
robert@501
|
169
|
robert@501
|
170 if(write(i2C_file, buf, 2) != 2)
|
robert@501
|
171 {
|
robert@501
|
172 cout << "Failed to write register " << (int)reg << " on MPR121\n";
|
robert@501
|
173 return;
|
robert@501
|
174 }
|
robert@501
|
175 }
|
robert@501
|
176
|