summaryrefslogtreecommitdiff
path: root/firmware/drivers/mpr121.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/mpr121.c')
-rw-r--r--firmware/drivers/mpr121.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/firmware/drivers/mpr121.c b/firmware/drivers/mpr121.c
new file mode 100644
index 0000000000..7b41208a3a
--- /dev/null
+++ b/firmware/drivers/mpr121.c
@@ -0,0 +1,350 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2012 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/** Driver for the Freescale MPR121 Capacitive Proximity Sensor */
23#include "system.h"
24#include "mpr121.h"
25#include "i2c.h"
26
27/* Touch status: EL{0,7} */
28#define REG_TOUCH_STATUS 0x00
29#define REG_TOUCH_STATUS__ELE(x) (1 << (x))
30/* Touch status: EL{8-11,prox}, overcurrent */
31#define REG_TOUCH_STATUS2 0x01
32#define REG_TOUCH_STATUS2__ELE(x) (1 << ((x) - 8))
33#define REG_TOUCH_STATUS2__ELEPROX (1 << 4)
34#define REG_TOUCH_STATUS2__OVCF (1 << 7)
35/* Out of range: EL{0,7} */
36#define REG_OOR_STATUS 0x02
37#define REG_OOR_STATUS__ELE(x) (1 << (x))
38/* Out of range: EL{8-11,prox}, autoconf err */
39#define REG_OOR_STATUS2 0x03
40#define REG_OOR_STATUS2__ELE(x) (1 << (x))
41#define REG_OOR_STATUS2__ELEPROX (1 << 4)
42#define REG_OOR_STATUS2__ACFF (1 << 6)
43#define REG_OOR_STATUS2__ARFF (1 << 7)
44/* Electrode X filtered data LSB */
45#define REG_EFDxLB(x) (0x04 + 0x02 * (x))
46/* Electrode X filtered data MSB */
47#define REG_EFDxHB(x) (0x05 + 0x02 * (x))
48/* Proximity electrode X filtered data LSB */
49#define REG_EFDPROXLB 0x1c
50/* Proximity electrode X filtered data MSB */
51#define REG_EFDPROXHB 0x1d
52/* Electrode baseline value */
53#define REG_ExBV(x) (0x1e + (x))
54/* Proximity electrode baseline value */
55#define REG_EPROXBV 0x2a
56/* Max Half Delta Rising */
57#define REG_MHDR 0x2b
58/* Noise Half Delta Rising */
59#define REG_NHDR 0x2c
60/* Noise Count Limit Rising */
61#define REG_NCLR 0x2d
62/* Filter Delay Limit Rising */
63#define REG_FDLR 0x2e
64/* Max Half Delta Falling */
65#define REG_MHDF 0x2f
66/* Noise Half Delta Falling */
67#define REG_NHDF 0x30
68/* Noise Count Limit Falling */
69#define REG_NCLF 0x31
70/* Filter Delay Limit Falling */
71#define REG_FDLF 0x32
72/* Noise Half Delta Touched */
73#define REG_NHDT 0x33
74/* Noise Count Limit Touched */
75#define REG_NCLT 0x34
76/* Filter Delay Limit Touched */
77#define REG_FDLT 0x35
78/* Proximity Max Half Delta Rising */
79#define REG_MHDPROXR 0x36
80/* Proximity Noise Half Delta Rising */
81#define REG_NHDPROXR 0x37
82/* Proximity Noise Count Limit Rising */
83#define REG_NCLPROXR 0x38
84/* Proximity Filter Delay Limit Rising */
85#define REG_FDLPROXR 0x39
86/* Proximity Max Half Delta Falling */
87#define REG_MHDPROXF 0x3a
88/* Proximity Noise Half Delta Falling */
89#define REG_NHDPROXF 0x3b
90/* Proximity Noise Count Limit Falling */
91#define REG_NCLPROXF 0x3c
92/* Proximity Filter Delay Limit Falling */
93#define REG_FDLPROXF 0x3d
94/* Proximity Noise Half Delta Touched */
95#define REG_NHDPROXT 0x3e
96/* Proximity Noise Count Limit Touched */
97#define REG_NCLPROXT 0x3f
98/* Proximity Filter Delay Limit Touched */
99#define REG_FDLPROXT 0x40
100/* Eletrode Touch Threshold */
101#define REG_ExTTH(x) (0x41 + 2 * (x))
102/* Eletrode Release Threshold */
103#define REG_ExRTH(x) (0x42 + 2 * (x))
104/* Proximity Eletrode Touch Threshold */
105#define REG_EPROXTTH 0x59
106/* Proximity Eletrode Release Threshold */
107#define REG_EPROXRTH 0x5a
108/* Debounce Control */
109#define REG_DEBOUNCE 0x5b
110#define REG_DEBOUNCE__DR(dr) ((dr) << 4)
111#define REG_DEBOUNCE__DT(dt) (dt)
112/* Analog Front End Configuration */
113#define REG_AFE 0x5c
114#define REG_AFE__CDC(cdc) (cdc)
115#define REG_AFE__FFI(ffi) ((ffi) << 6)
116/* Filter Configuration */
117#define REG_FILTER 0x5d
118#define REG_FILTER__ESI(esi) (esi)
119#define REG_FILTER__SFI(sfi) ((sfi) << 3)
120#define REG_FILTER__CDT(cdt) ((cdt) << 5)
121/* Electrode Configuration */
122#define REG_ELECTRODE 0x5e
123#define REG_ELECTRODE__ELE_EN(en) (en)
124#define REG_ELECTRODE__ELEPROX_EN(en) ((en) << 4)
125#define REG_ELECTRODE__CL(cl) ((cl) << 6)
126/* Electrode X Current */
127#define REG_CDCx(x) (0x5f + (x))
128/* Proximity Eletrode X Current */
129#define REG_CDCPROX 0x6b
130/* Electrode X Charge Time */
131#define REG_CDTx(x) (0x6c + (x) / 2)
132#define REG_CDTx__CDT0(x) (x)
133#define REG_CDTx__CDT1(x) ((x) << 4)
134/* Proximity Eletrode X Charge Time */
135#define REG_CDTPROX 0x72
136/* GPIO Control Register: CTL0{4-11} */
137#define REG_GPIO_CTL0 0x73
138#define REG_GPIO_CTL0__CTL0x(x) (1 << ((x) - 4))
139/* GPIO Control Register: CTL1{4-11} */
140#define REG_GPIO_CTL1 0x74
141#define REG_GPIO_CTL1__CTL1x(x) (1 << ((x) - 4))
142/* GPIO Data Register */
143#define REG_GPIO_DATA 0x75
144#define REG_GPIO_DATA__DATx(x) (1 << ((x) - 4))
145/* GPIO Direction Register */
146#define REG_GPIO_DIR 0x76
147#define REG_GPIO_DIR__DIRx(x) (1 << ((x) - 4))
148/* GPIO Enable Register */
149#define REG_GPIO_EN 0x77
150#define REG_GPIO_EN__ENx(x) (1 << ((x) - 4))
151/* GPIO Data Set Register */
152#define REG_GPIO_SET 0x78
153#define REG_GPIO_SET__SETx(x) (1 << ((x) - 4))
154/* GPIO Data Clear Register */
155#define REG_GPIO_CLR 0x79
156#define REG_GPIO_CLR__CLRx(x) (1 << ((x) - 4))
157/* GPIO Data Toggle Register */
158#define REG_GPIO_TOG 0x7a
159#define REG_GPIO_TOG__TOGx(x) (1 << ((x) - 4))
160/* Auto-Configuration Control 0 */
161#define REG_AUTO_CONF 0x7b
162#define REG_AUTO_CONF__ACE(ace) (ace)
163#define REG_AUTO_CONF__ARE(are) ((are) << 1)
164#define REG_AUTO_CONF__BVA(bva) ((bva) << 2)
165#define REG_AUTO_CONF__RETRY(retry) ((retry) << 4)
166#define REG_AUTO_CONF__FFI(ffi) ((ffi) << 6)
167/* Auto-Configuration Control 1 */
168#define REG_AUTO_CONF2 0x7c
169#define REG_AUTO_CONF2__ACFIE(acfie) (acfie)
170#define REG_AUTO_CONF2__ARFIE(arfie) ((arfie) << 1)
171#define REG_AUTO_CONF2__OORIE(oorie) ((oorie) << 2)
172#define REG_AUTO_CONF2__SCTS(scts) ((scts) << 7)
173/* Auto-Configuration Upper-Limit */
174#define REG_USL 0x7d
175/* Auto-Configuration Lower-Limit */
176#define REG_LSL 0x7e
177/* Auto-Configuration Target Level */
178#define REG_TL 0x7f
179/* Soft-Reset */
180#define REG_SOFTRESET 0x80
181#define REG_SOFTRESET__MAGIC 0x63
182/* PWM Control */
183#define REG_PWMx(x) (0x81 + ((x) - 4) / 2)
184#define REG_PWMx_IS_PWM0(x) (((x) % 2) == 0)
185#define REG_PWMx__PWM0(x) (x)
186#define REG_PWMx__PWM0_BM 0xf
187#define REG_PWMx__PWM1(x) ((x) << 4)
188#define REG_PWMx__PWM1_BM 0xf0
189
190static int i2c_addr;
191
192static inline int mpr121_write_reg(uint8_t reg, uint8_t data)
193{
194 return i2c_writemem(i2c_addr, reg, &data, 1);
195}
196
197static inline int mpr121_read_reg(uint8_t reg, uint8_t *data)
198{
199 return i2c_readmem(i2c_addr, reg, data, 1);
200}
201
202int mpr121_init(int dev_i2c_addr)
203{
204 i2c_addr = dev_i2c_addr;
205 return 0;
206}
207
208int mpr121_soft_reset(void)
209{
210 return mpr121_write_reg(REG_SOFTRESET, REG_SOFTRESET__MAGIC);
211}
212int mpr121_set_config(struct mpr121_config_t *conf)
213{
214 int ret;
215#define safe_write(reg, val) \
216 do { ret = mpr121_write_reg(reg, val); \
217 if(ret) return ret; } while(0)
218 /* stop mode */
219 safe_write(REG_ELECTRODE, 0);
220 /* write baseline values */
221 for(int i = 0; i < ELECTRODE_COUNT; i++)
222 safe_write(REG_ExBV(i), conf->ele[i].bv);
223 /* write eleprox bv */
224 safe_write(REG_EPROXBV, conf->eleprox.bv);
225 /* write global fields */
226 safe_write(REG_MHDR, conf->filters.ele.rising.mhd);
227 safe_write(REG_NHDR, conf->filters.ele.rising.nhd);
228 safe_write(REG_NCLR, conf->filters.ele.rising.ncl);
229 safe_write(REG_FDLR, conf->filters.ele.rising.fdl);
230 safe_write(REG_MHDF, conf->filters.ele.falling.mhd);
231 safe_write(REG_NHDF, conf->filters.ele.falling.nhd);
232 safe_write(REG_NCLF, conf->filters.ele.falling.ncl);
233 safe_write(REG_FDLF, conf->filters.ele.falling.fdl);
234 safe_write(REG_NHDT, conf->filters.ele.touched.nhd);
235 safe_write(REG_NCLT, conf->filters.ele.touched.ncl);
236 safe_write(REG_FDLT, conf->filters.ele.touched.fdl);
237 safe_write(REG_MHDPROXR, conf->filters.eleprox.rising.mhd);
238 safe_write(REG_NHDPROXR, conf->filters.eleprox.rising.nhd);
239 safe_write(REG_NCLPROXR, conf->filters.eleprox.rising.ncl);
240 safe_write(REG_FDLPROXR, conf->filters.eleprox.rising.fdl);
241 safe_write(REG_MHDPROXF, conf->filters.eleprox.falling.mhd);
242 safe_write(REG_NHDPROXF, conf->filters.eleprox.falling.nhd);
243 safe_write(REG_NCLPROXF, conf->filters.eleprox.falling.ncl);
244 safe_write(REG_FDLPROXF, conf->filters.eleprox.falling.fdl);
245 safe_write(REG_NHDPROXT, conf->filters.eleprox.touched.nhd);
246 safe_write(REG_NCLPROXT, conf->filters.eleprox.touched.ncl);
247 safe_write(REG_FDLPROXT, conf->filters.eleprox.touched.fdl);
248 /* touch & release thresholds */
249 for(int i = 0; i < ELECTRODE_COUNT; i++)
250 {
251 safe_write(REG_ExTTH(i), conf->ele[i].tth);
252 safe_write(REG_ExRTH(i), conf->ele[i].rth);
253 }
254 safe_write(REG_EPROXTTH, conf->eleprox.tth);
255 safe_write(REG_EPROXRTH, conf->eleprox.rth);
256 /* debounce */
257 safe_write(REG_DEBOUNCE, REG_DEBOUNCE__DR(conf->debounce.dr) |
258 REG_DEBOUNCE__DT(conf->debounce.dt));
259 /* analog-front end and filters */
260 safe_write(REG_AFE, REG_AFE__CDC(conf->global.cdc) |
261 REG_AFE__FFI(conf->global.ffi));
262 safe_write(REG_FILTER, REG_FILTER__CDT(conf->global.cdt) |
263 REG_FILTER__ESI(conf->global.esi) | REG_FILTER__SFI(conf->global.sfi));
264 /* electrode charge */
265 for(int i = 0; i < ELECTRODE_COUNT; i++)
266 safe_write(REG_CDCx(i), conf->ele[i].cdc);
267 safe_write(REG_CDCPROX, conf->eleprox.cdc);
268 for(int i = 0; i < ELECTRODE_COUNT; i += 2)
269 {
270 safe_write(REG_CDTx(i), REG_CDTx__CDT0(conf->ele[i].cdt) |
271 REG_CDTx__CDT1(conf->ele[i+1].cdt));
272 }
273 safe_write(REG_CDTPROX, conf->eleprox.cdt);
274 /* Auto-Configuration */
275 safe_write(REG_AUTO_CONF, REG_AUTO_CONF__ACE(conf->autoconf.en) |
276 REG_AUTO_CONF__ARE(conf->autoconf.ren) |
277 REG_AUTO_CONF__BVA(conf->cal_lock) |
278 REG_AUTO_CONF__RETRY(conf->autoconf.retry) |
279 REG_AUTO_CONF__FFI(conf->global.ffi));
280 safe_write(REG_AUTO_CONF2, REG_AUTO_CONF2__ACFIE(conf->autoconf.acfie) |
281 REG_AUTO_CONF2__ARFIE(conf->autoconf.arfie) |
282 REG_AUTO_CONF2__OORIE(conf->autoconf.oorie) |
283 REG_AUTO_CONF2__SCTS(conf->autoconf.scts));
284 safe_write(REG_USL, conf->autoconf.usl);
285 safe_write(REG_LSL, conf->autoconf.lsl);
286 safe_write(REG_TL, conf->autoconf.tl);
287 /* electrode configuration */
288 safe_write(REG_ELECTRODE, REG_ELECTRODE__ELE_EN(conf->ele_en) |
289 REG_ELECTRODE__ELEPROX_EN(conf->eleprox_en) |
290 REG_ELECTRODE__CL(conf->cal_lock));
291 /* gpio config */
292 uint8_t ctl = 0;
293 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
294 if(ELE_GPIO_CTL0(conf->ele[i].gpio))
295 ctl |= REG_GPIO_CTL0__CTL0x(i);
296 safe_write(REG_GPIO_CTL0, ctl);
297 ctl = 0;
298 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
299 if(ELE_GPIO_CTL1(conf->ele[i].gpio))
300 ctl |= REG_GPIO_CTL1__CTL1x(i);
301 safe_write(REG_GPIO_CTL1, ctl);
302 ctl = 0;
303 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
304 if(ELE_GPIO_DIR(conf->ele[i].gpio))
305 ctl |= REG_GPIO_DIR__DIRx(i);
306 safe_write(REG_GPIO_DIR, ctl);
307 ctl = 0;
308 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
309 if(ELE_GPIO_EN(conf->ele[i].gpio))
310 ctl |= REG_GPIO_EN__ENx(i);
311 safe_write(REG_GPIO_EN, ctl);
312
313 return 0;
314}
315
316int mpr121_set_gpio_output(int ele, int gpio_val)
317{
318 switch(gpio_val)
319 {
320 case ELE_GPIO_SET:
321 return mpr121_write_reg(REG_GPIO_SET, REG_GPIO_SET__SETx(ele));
322 case ELE_GPIO_CLR:
323 return mpr121_write_reg(REG_GPIO_CLR, REG_GPIO_CLR__CLRx(ele));
324 case ELE_GPIO_TOG:
325 return mpr121_write_reg(REG_GPIO_TOG, REG_GPIO_TOG__TOGx(ele));
326 default:
327 return -1;
328 }
329}
330
331int mpr121_set_gpio_pwm(int ele, int pwm)
332{
333 uint8_t reg_val;
334 int ret = mpr121_read_reg(REG_PWMx(ele), &reg_val);
335 if(ret) return ret;
336 if(REG_PWMx_IS_PWM0(ele))
337 reg_val = (reg_val & ~REG_PWMx__PWM0_BM) | REG_PWMx__PWM0(pwm);
338 else
339 reg_val = (reg_val & ~REG_PWMx__PWM1_BM) | REG_PWMx__PWM1(pwm);
340 return mpr121_write_reg(REG_PWMx(ele), reg_val);
341}
342
343int mpr121_get_touch_status(unsigned *status)
344{
345 uint8_t buf[2];
346 int ret = i2c_readmem(i2c_addr, REG_TOUCH_STATUS, buf, 2);
347 if(!ret && status)
348 *status = buf[0] | buf[1];
349 return ret;
350}