summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2016-05-30 16:24:38 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2016-06-01 23:09:27 +0200
commitd42a4a4eb4bc20fda41543b8b831c1970723346f (patch)
treef6ba16e95c61e441c1f110131b17a710c785285c
parentb2afd931e2d83ce346811a68a34ee56c48be6d35 (diff)
downloadrockbox-d42a4a4eb4bc20fda41543b8b831c1970723346f.tar.gz
rockbox-d42a4a4eb4bc20fda41543b8b831c1970723346f.zip
zenxfi3: rewrite mpr121 driver
The new driver uses an asynchronous architecture for touch status reading. Change-Id: Ic75a8b91bc47ee16c3af873afde178cd70186376
-rw-r--r--firmware/SOURCES2
-rw-r--r--firmware/drivers/mpr121.c350
-rw-r--r--firmware/export/mpr121.h314
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c2
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/button-zenxfi3.c95
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.c236
-rw-r--r--firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.h176
7 files changed, 601 insertions, 574 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 34d2db39b2..db3f09ea8e 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1231,10 +1231,10 @@ target/arm/imx233/creative-zenxfi2/powermgmt-zenxfi2.c
1231#endif 1231#endif
1232 1232
1233#ifdef CREATIVE_ZENXFI3 1233#ifdef CREATIVE_ZENXFI3
1234drivers/mpr121.c
1235#ifndef BOOTLOADER 1234#ifndef BOOTLOADER
1236target/arm/imx233/fmradio-imx233.c 1235target/arm/imx233/fmradio-imx233.c
1237#endif 1236#endif
1237target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.c
1238target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c 1238target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c
1239target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c 1239target/arm/imx233/creative-zenxfi3/lcd-zenxfi3.c
1240target/arm/imx233/creative-zenxfi3/button-zenxfi3.c 1240target/arm/imx233/creative-zenxfi3/button-zenxfi3.c
diff --git a/firmware/drivers/mpr121.c b/firmware/drivers/mpr121.c
deleted file mode 100644
index 7b41208a3a..0000000000
--- a/firmware/drivers/mpr121.c
+++ /dev/null
@@ -1,350 +0,0 @@
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}
diff --git a/firmware/export/mpr121.h b/firmware/export/mpr121.h
index 96b83ecc90..50c13a1c7b 100644
--- a/firmware/export/mpr121.h
+++ b/firmware/export/mpr121.h
@@ -18,153 +18,173 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef __MPR121_H__
22#define __MPR121_H__
21 23
22/** Driver for the Freescale MPR121 Capacitive Proximity Sensor */ 24/** Registers for the Freescale MPR121 Capacitive Proximity Sensor */
23#include "system.h" 25#include "system.h"
24 26
25#define ELECTRODE_COUNT 12 27/* Touch status: EL{0,7} */
26#define ELE_GPIO_FIRST 4 28#define REG_TOUCH_STATUS 0x00
27#define ELE_GPIO_LAST 11 29#define REG_TOUCH_STATUS__ELE(x) (1 << (x))
28 30/* Touch status: EL{8-11,prox}, overcurrent */
29/* gpio config (encoding: [0]=en,[1]=dir,[2]=ctl[1],[3]=ctl[0]) */ 31#define REG_TOUCH_STATUS2 0x01
30#define ELE_GPIO_DISABLE 0 32#define REG_TOUCH_STATUS2__ELE(x) (1 << ((x) - 8))
31#define ELE_GPIO_INPUT 1 33#define REG_TOUCH_STATUS2__ELEPROX (1 << 4)
32#define ELE_GPIO_INPUT_PULLDOWN 9 /* input with pull-down */ 34#define REG_TOUCH_STATUS2__OVCF (1 << 7)
33#define ELE_GPIO_INPUT_PULLUP 13 /* input with pull-up */ 35/* Out of range: EL{0,7} */
34#define ELE_GPIO_OUTPUT 3 36#define REG_OOR_STATUS 0x02
35#define ELE_GPIO_OUTPUT_OPEN 11 /* open drain low-side */ 37#define REG_OOR_STATUS__ELE(x) (1 << (x))
36#define ELE_GPIO_OUTPUT_OPEN_LED 15 /* open drain high-side (led driver) */ 38/* Out of range: EL{8-11,prox}, autoconf err */
37 39#define REG_OOR_STATUS2 0x03
38/* internal use */ 40#define REG_OOR_STATUS2__ELE(x) (1 << (x))
39#define ELE_GPIO_EN(val) ((val) & 1) 41#define REG_OOR_STATUS2__ELEPROX (1 << 4)
40#define ELE_GPIO_DIR(val) (((val) >> 1) & 1) 42#define REG_OOR_STATUS2__ACFF (1 << 6)
41#define ELE_GPIO_CTL0(val) (((val) >> 3) & 1) 43#define REG_OOR_STATUS2__ARFF (1 << 7)
42#define ELE_GPIO_CTL1(val) (((val) >> 1) & 1) 44/* Electrode X filtered data LSB */
43 45#define REG_EFDxLB(x) (0x04 + 0x02 * (x))
44struct mpr121_electrode_config_t 46/* Electrode X filtered data MSB */
45{ 47#define REG_EFDxHB(x) (0x05 + 0x02 * (x))
46 uint8_t bv; /* baseline value */ 48/* Proximity electrode X filtered data LSB */
47 uint8_t tth; /* touch threshold */ 49#define REG_EFDPROXLB 0x1c
48 uint8_t rth; /* release threshold */ 50/* Proximity electrode X filtered data MSB */
49 uint8_t cdc; /* charge current (optional if auto-conf) */ 51#define REG_EFDPROXHB 0x1d
50 uint8_t cdt; /* charge time (optional if auto-conf) */ 52/* Electrode baseline value */
51 int gpio; /* gpio config */ 53#define REG_ExBV(x) (0x1e + (x))
52}; 54/* Proximity electrode baseline value */
53 55#define REG_EPROXBV 0x2a
54struct mpr121_baseline_filter_config_t 56/* Max Half Delta Rising */
55{ 57#define REG_MHDR 0x2b
56 uint8_t mhd; /* max half delta (except for touched) */ 58/* Noise Half Delta Rising */
57 uint8_t nhd; /* noise half delta */ 59#define REG_NHDR 0x2c
58 uint8_t ncl; /* noise count limit */ 60/* Noise Count Limit Rising */
59 uint8_t fdl; /* filter delay count limit */ 61#define REG_NCLR 0x2d
60}; 62/* Filter Delay Limit Rising */
61 63#define REG_FDLR 0x2e
62struct mpr121_baseline_filters_config_t 64/* Max Half Delta Falling */
63{ 65#define REG_MHDF 0x2f
64 struct mpr121_baseline_filter_config_t rising; 66/* Noise Half Delta Falling */
65 struct mpr121_baseline_filter_config_t falling; 67#define REG_NHDF 0x30
66 struct mpr121_baseline_filter_config_t touched; 68/* Noise Count Limit Falling */
67}; 69#define REG_NCLF 0x31
68 70/* Filter Delay Limit Falling */
69struct mpr121_debounce_config_t 71#define REG_FDLF 0x32
70{ 72/* Noise Half Delta Touched */
71 uint8_t dt; /* debounce count for touch */ 73#define REG_NHDT 0x33
72 uint8_t dr; /* debounce count for release */ 74/* Noise Count Limit Touched */
73}; 75#define REG_NCLT 0x34
74 76/* Filter Delay Limit Touched */
75/* first filter iterations */ 77#define REG_FDLT 0x35
76#define FFI_6_SAMPLES 0 78/* Proximity Max Half Delta Rising */
77#define FFI_10_SAMPLES 1 79#define REG_MHDPROXR 0x36
78#define FFI_18_SAMPLES 2 80/* Proximity Noise Half Delta Rising */
79#define FFI_34_SAMPLES 3 81#define REG_NHDPROXR 0x37
80/* charge discharge current */ 82/* Proximity Noise Count Limit Rising */
81#define CDC_DISABLE 0 83#define REG_NCLPROXR 0x38
82#define CDC_uA(ua) (ua) 84/* Proximity Filter Delay Limit Rising */
83/* charge discharge time */ 85#define REG_FDLPROXR 0x39
84#define CDT_DISABLE 0 86/* Proximity Max Half Delta Falling */
85#define CDT_log_us(lus) (lus) /* actual value = 2^{us-2} µs */ 87#define REG_MHDPROXF 0x3a
86/* second filter iterations */ 88/* Proximity Noise Half Delta Falling */
87#define SFI_4_SAMPLES 0 89#define REG_NHDPROXF 0x3b
88#define SFI_6_SAMPLES 1 90/* Proximity Noise Count Limit Falling */
89#define SFI_10_SAMPLES 2 91#define REG_NCLPROXF 0x3c
90#define SFI_18_SAMPLES 3 92/* Proximity Filter Delay Limit Falling */
91/* Eletrode sample interval */ 93#define REG_FDLPROXF 0x3d
92#define ESI_log_ms(lms) (lms) /* actual value = 2^{lms} ms */ 94/* Proximity Noise Half Delta Touched */
93 95#define REG_NHDPROXT 0x3e
94struct mpr121_global_config_t 96/* Proximity Noise Count Limit Touched */
95{ 97#define REG_NCLPROXT 0x3f
96 uint8_t ffi; /* first filter iterations */ 98/* Proximity Filter Delay Limit Touched */
97 uint8_t cdc; /* global charge discharge current */ 99#define REG_FDLPROXT 0x40
98 uint8_t cdt; /* global charge discharge time */ 100/* Eletrode Touch Threshold */
99 uint8_t sfi; /* second first iterations */ 101#define REG_ExTTH(x) (0x41 + 2 * (x))
100 uint8_t esi; /* electrode sample interval */ 102/* Eletrode Release Threshold */
101}; 103#define REG_ExRTH(x) (0x42 + 2 * (x))
102 104/* Proximity Eletrode Touch Threshold */
103#define RETRY_NEVER 0 105#define REG_EPROXTTH 0x59
104#define RETRY_2_TIMES 1 106/* Proximity Eletrode Release Threshold */
105#define RETRY_4_TIMES 2 107#define REG_EPROXRTH 0x5a
106#define RETRY_8_TIMES 3 108/* Debounce Control */
107 109#define REG_DEBOUNCE 0x5b
108struct mpr121_auto_config_t 110#define REG_DEBOUNCE__DR(dr) ((dr) << 4)
109{ 111#define REG_DEBOUNCE__DT(dt) (dt)
110 bool en; /* auto-conf enable */ 112/* Analog Front End Configuration */
111 bool ren; /* auto-reconf enable */ 113#define REG_AFE 0x5c
112 uint8_t retry; /* retry count */ 114#define REG_AFE__CDC(cdc) (cdc)
113 bool scts; /* skip charge time search */ 115#define REG_AFE__FFI(ffi) ((ffi) << 6)
114 uint8_t usl; /* upper-side limit */ 116/* Filter Configuration */
115 uint8_t lsl; /* lower-side limit */ 117#define REG_FILTER 0x5d
116 uint8_t tl; /* target level */ 118#define REG_FILTER__ESI(esi) (esi)
117 bool acfie; /* auto-conf fail interrupt en */ 119#define REG_FILTER__SFI(sfi) ((sfi) << 3)
118 bool arfie; /* auto-reconf fail interrupt en */ 120#define REG_FILTER__CDT(cdt) ((cdt) << 5)
119 bool oorie; /* out of range interrupt en */ 121/* Electrode Configuration */
120}; 122#define REG_ELECTRODE 0x5e
121 123#define REG_ELECTRODE__ELE_EN(en) (en)
122/* electrode mode */ 124#define REG_ELECTRODE__ELEPROX_EN(en) ((en) << 4)
123#define ELE_DISABLE 0 125#define REG_ELECTRODE__CL(cl) ((cl) << 6)
124#define ELE_EN0_x(x) ((x) + 1) 126/* Electrode X Current */
125/* eleprox mode */ 127#define REG_CDCx(x) (0x5f + (x))
126#define ELEPROX_DISABLE 0 128/* Proximity Eletrode X Current */
127#define ELEPROX_EN0_1 1 129#define REG_CDCPROX 0x6b
128#define ELEPROX_EN0_3 2 130/* Electrode X Charge Time */
129#define ELEPROX_EN0_11 3 131#define REG_CDTx(x) (0x6c + (x) / 2)
130/* calibration lock */ 132#define REG_CDTx__CDT0(x) (x)
131#define CL_SLOW_TRACK 0 133#define REG_CDTx__CDT1(x) ((x) << 4)
132#define CL_DISABLE 1 134/* Proximity Eletrode X Charge Time */
133#define CL_TRACK 2 135#define REG_CDTPROX 0x72
134#define CL_FAST_TRACK 3 136/* GPIO Control Register: CTL0{4-11} */
135 137#define REG_GPIO_CTL0 0x73
136struct mpr121_config_t 138#define REG_GPIO_CTL0__CTL0x(x) (1 << ((x) - 4))
137{ 139/* GPIO Control Register: CTL1{4-11} */
138 struct mpr121_electrode_config_t ele[ELECTRODE_COUNT]; 140#define REG_GPIO_CTL1 0x74
139 struct mpr121_electrode_config_t eleprox; 141#define REG_GPIO_CTL1__CTL1x(x) (1 << ((x) - 4))
140 struct 142/* GPIO Data Register */
141 { 143#define REG_GPIO_DATA 0x75
142 struct mpr121_baseline_filters_config_t ele; 144#define REG_GPIO_DATA__DATx(x) (1 << ((x) - 4))
143 struct mpr121_baseline_filters_config_t eleprox; 145/* GPIO Direction Register */
144 }filters; 146#define REG_GPIO_DIR 0x76
145 struct mpr121_debounce_config_t debounce; 147#define REG_GPIO_DIR__DIRx(x) (1 << ((x) - 4))
146 struct mpr121_global_config_t global; 148/* GPIO Enable Register */
147 struct mpr121_auto_config_t autoconf; 149#define REG_GPIO_EN 0x77
148 uint8_t ele_en; /* eletroce mode */ 150#define REG_GPIO_EN__ENx(x) (1 << ((x) - 4))
149 uint8_t eleprox_en; /* proximity mode */ 151/* GPIO Data Set Register */
150 uint8_t cal_lock; /* calibration lock */ 152#define REG_GPIO_SET 0x78
151}; 153#define REG_GPIO_SET__SETx(x) (1 << ((x) - 4))
152 154/* GPIO Data Clear Register */
153/* gpio value */ 155#define REG_GPIO_CLR 0x79
154#define ELE_GPIO_CLR 0 156#define REG_GPIO_CLR__CLRx(x) (1 << ((x) - 4))
155#define ELE_GPIO_SET 1 157/* GPIO Data Toggle Register */
156#define ELE_GPIO_TOG 2 158#define REG_GPIO_TOG 0x7a
157/* pwm value */ 159#define REG_GPIO_TOG__TOGx(x) (1 << ((x) - 4))
158#define ELE_PWM_DISABLE 0 160/* Auto-Configuration Control 0 */
159#define ELE_PWM_DUTY(x) (x) 161#define REG_AUTO_CONF 0x7b
160#define ELE_PWM_MIN_DUTY 1 162#define REG_AUTO_CONF__ACE(ace) (ace)
161#define ELE_PWM_MAX_DUTY 15 163#define REG_AUTO_CONF__ARE(are) ((are) << 1)
162 164#define REG_AUTO_CONF__BVA(bva) ((bva) << 2)
163int mpr121_init(int dev_i2c_addr); 165#define REG_AUTO_CONF__RETRY(retry) ((retry) << 4)
164int mpr121_soft_reset(void); 166#define REG_AUTO_CONF__FFI(ffi) ((ffi) << 6)
165int mpr121_set_config(struct mpr121_config_t *conf); 167/* Auto-Configuration Control 1 */
166/* gpios are only implemented for electrode>=4 */ 168#define REG_AUTO_CONF2 0x7c
167int mpr121_set_gpio_output(int ele, int gpio_val); 169#define REG_AUTO_CONF2__ACFIE(acfie) (acfie)
168int mpr121_set_gpio_pwm(int ele, int pwm); 170#define REG_AUTO_CONF2__ARFIE(arfie) ((arfie) << 1)
169/* get electrode status (bitmap) */ 171#define REG_AUTO_CONF2__OORIE(oorie) ((oorie) << 2)
170int mpr121_get_touch_status(unsigned *status); 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
190#endif /* __MPR121_H__ */
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c b/firmware/target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c
index 2b77a4d7ac..e3baddea1e 100644
--- a/firmware/target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c
+++ b/firmware/target/arm/imx233/creative-zenxfi3/backlight-zenxfi3.c
@@ -25,7 +25,7 @@
25#include "backlight.h" 25#include "backlight.h"
26#include "backlight-target.h" 26#include "backlight-target.h"
27#include "pwm-imx233.h" 27#include "pwm-imx233.h"
28#include "mpr121.h" 28#include "mpr121-zenxfi3.h"
29 29
30void backlight_hw_brightness(int brightness) 30void backlight_hw_brightness(int brightness)
31{ 31{
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/button-zenxfi3.c b/firmware/target/arm/imx233/creative-zenxfi3/button-zenxfi3.c
index 756231a042..ed8e769e2d 100644
--- a/firmware/target/arm/imx233/creative-zenxfi3/button-zenxfi3.c
+++ b/firmware/target/arm/imx233/creative-zenxfi3/button-zenxfi3.c
@@ -18,16 +18,10 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#include "button-target.h"
22#include "system.h" 21#include "system.h"
23#include "system-target.h" 22#include "tick.h"
24#include "pinctrl-imx233.h"
25#include "power-imx233.h"
26#include "button-imx233.h" 23#include "button-imx233.h"
27#include "string.h" 24#include "mpr121-zenxfi3.h"
28#include "usb.h"
29#include "backlight.h"
30#include "mpr121.h"
31 25
32#define I_VDDIO 0 /* index in the table */ 26#define I_VDDIO 0 /* index in the table */
33 27
@@ -42,7 +36,8 @@ struct imx233_button_map_t imx233_button_map[] =
42 IMX233_BUTTON_(END, END(), "") 36 IMX233_BUTTON_(END, END(), "")
43}; 37};
44 38
45static struct mpr121_config_t config = 39/* MPR121 configuration, mostly extracted from OF */
40static struct mpr121_config_t mpr121_config =
46{ 41{
47 .ele = 42 .ele =
48 { 43 {
@@ -73,74 +68,11 @@ static struct mpr121_config_t config =
73 .cal_lock = CL_TRACK 68 .cal_lock = CL_TRACK
74}; 69};
75 70
76#define MPR121_INTERRUPT 1
77
78static int touchpad_btns = 0;
79static long mpr121_stack[DEFAULT_STACK_SIZE/sizeof(long)];
80static const char mpr121_thread_name[] = "mpr121";
81static struct event_queue mpr121_queue;
82
83static void mpr121_irq_cb(int bank, int pin, intptr_t user)
84{
85 (void) bank;
86 (void) pin;
87 (void) user;
88 /* the callback will not be fired until interrupt is enabled back so
89 * the queue will not overflow or contain multiple MPR121_INTERRUPT events */
90 queue_post(&mpr121_queue, MPR121_INTERRUPT, 0);
91}
92
93static void mpr121_thread(void)
94{
95 struct queue_event ev;
96
97 while(1)
98 {
99 queue_wait(&mpr121_queue, &ev);
100 /* handle usb connect and ignore all messages except rmi interrupts */
101 if(ev.id == SYS_USB_CONNECTED)
102 {
103 usb_acknowledge(SYS_USB_CONNECTED_ACK);
104 continue;
105 }
106 else if(ev.id != MPR121_INTERRUPT)
107 continue;
108 /* clear interrupt and get status */
109 unsigned status;
110 touchpad_btns = 0;
111 if(!mpr121_get_touch_status(&status))
112 {
113 /* ELE3: up
114 * ELE4: back
115 * ELE5: menu
116 * ELE6: down
117 * ELE7: play */
118 if(status & 0x8) touchpad_btns |= BUTTON_UP;
119 if(status & 0x10) touchpad_btns |= BUTTON_BACK;
120 if(status & 0x20) touchpad_btns |= BUTTON_MENU;
121 if(status & 0x40) touchpad_btns |= BUTTON_DOWN;
122 if(status & 0x80) touchpad_btns |= BUTTON_PLAY;
123 }
124 /* enable interrupt */
125 imx233_pinctrl_setup_irq(0, 18, true, true, false, &mpr121_irq_cb, 0);
126 }
127}
128
129/* B0P18 is #IRQ line of the touchpad */ 71/* B0P18 is #IRQ line of the touchpad */
130void button_init_device(void) 72void button_init_device(void)
131{ 73{
132 mpr121_init(0xb4); 74 mpr121_init();
133 mpr121_soft_reset(); 75 mpr121_set_config(&mpr121_config);
134 mpr121_set_config(&config);
135
136 queue_init(&mpr121_queue, true);
137 create_thread(mpr121_thread, mpr121_stack, sizeof(mpr121_stack), 0,
138 mpr121_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
139 /* enable interrupt */
140 imx233_pinctrl_acquire(0, 18, "mpr121_int");
141 imx233_pinctrl_set_function(0, 18, PINCTRL_FUNCTION_GPIO);
142 imx233_pinctrl_enable_gpio(0, 18, false);
143 imx233_pinctrl_setup_irq(0, 18, true, true, false, &mpr121_irq_cb, 0);
144 /* generic part */ 76 /* generic part */
145 imx233_button_init(); 77 imx233_button_init();
146} 78}
@@ -151,7 +83,6 @@ int button_read_device(void)
151 * for one second after hold is released */ 83 * for one second after hold is released */
152 static int power_ignore_counter = 0; 84 static int power_ignore_counter = 0;
153 static bool old_hold; 85 static bool old_hold;
154 /* light handling */
155 bool hold = button_hold(); 86 bool hold = button_hold();
156 if(hold != old_hold) 87 if(hold != old_hold)
157 { 88 {
@@ -159,6 +90,20 @@ int button_read_device(void)
159 if(!hold) 90 if(!hold)
160 power_ignore_counter = HZ; 91 power_ignore_counter = HZ;
161 } 92 }
93 /* interpret touchpad status */
94 unsigned status = mpr121_get_touch_status();
95 unsigned touchpad_btns = 0;
96 /* ELE3: up
97 * ELE4: back
98 * ELE5: menu
99 * ELE6: down
100 * ELE7: play */
101 if(status & 0x8) touchpad_btns |= BUTTON_UP;
102 if(status & 0x10) touchpad_btns |= BUTTON_BACK;
103 if(status & 0x20) touchpad_btns |= BUTTON_MENU;
104 if(status & 0x40) touchpad_btns |= BUTTON_DOWN;
105 if(status & 0x80) touchpad_btns |= BUTTON_PLAY;
106 /* feed it to generic code */
162 int res = imx233_button_read(touchpad_btns); 107 int res = imx233_button_read(touchpad_btns);
163 if(power_ignore_counter > 0) 108 if(power_ignore_counter > 0)
164 { 109 {
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.c b/firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.c
new file mode 100644
index 0000000000..23fcc7f0e4
--- /dev/null
+++ b/firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.c
@@ -0,0 +1,236 @@
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 "kernel.h"
25#include "usb.h"
26#include "mpr121.h"
27#include "mpr121-zenxfi3.h"
28#include "i2c-imx233.h"
29#include "pinctrl-imx233.h"
30
31#define MPR121_I2C_ADDR 0xb4
32
33/* NOTE on the architecture of the driver
34 *
35 * All non-time-critical operations (setup, gpio/pwm changes) are done with
36 * blocking i2c transfers to make the code simpler. Since reading the touch
37 * status is time critical, it is done asynchronously: when the IRQ pin is
38 * asserted, it will disable IRQ pin sensing and trigger an asynchronous i2c
39 * transfer to read touch status. When the transfer finishes, the driver will
40 * renable IRQ pin sensing. */
41
42static unsigned touch_status = 0; /* touch bitmask as reported by mpr121 */
43static struct imx233_i2c_xfer_t read_status_xfer; /* async transfer to read touch status */
44static uint8_t read_status_sel_reg; /* buffer for async transfer operation */
45static uint8_t read_status_buf[2]; /* buffer for async transfer operation */
46
47static void mpr121_irq_cb(int bank, int pin, intptr_t user);
48
49static void touch_status_i2c_cb(struct imx233_i2c_xfer_t *xfer, enum imx233_i2c_error_t status)
50{
51 (void) xfer;
52 (void) status;
53 /* put status in the global variable */
54 touch_status = read_status_buf[0] | read_status_buf[1] << 8;
55 /* start sensing IRQ pin again */
56 imx233_pinctrl_setup_irq(0, 18, true, true, false, &mpr121_irq_cb, 0);
57}
58
59void mpr121_irq_cb(int bank, int pin, intptr_t user)
60{
61 (void) bank;
62 (void) pin;
63 (void) user;
64 /* NOTE the callback will not be fired until interrupt is enabled back.
65 *
66 * now setup an asynchronous i2c transfer to read touch status register,
67 * this is a readmem operation with a first stage to select register
68 * and a second stage to read status (2 bytes) */
69 read_status_sel_reg = REG_TOUCH_STATUS;
70
71 read_status_xfer.next = NULL;
72 read_status_xfer.fast_mode = true;
73 read_status_xfer.dev_addr = MPR121_I2C_ADDR;
74 read_status_xfer.mode = I2C_READ;
75 read_status_xfer.count[0] = 1; /* set touch status register address */
76 read_status_xfer.data[0] = &read_status_sel_reg;
77 read_status_xfer.count[1] = 2;
78 read_status_xfer.data[1] = &read_status_buf;
79 read_status_xfer.tmo_ms = 1000;
80 read_status_xfer.callback = &touch_status_i2c_cb;
81
82 imx233_i2c_transfer(&read_status_xfer);
83}
84
85static inline int mpr121_write_reg(uint8_t reg, uint8_t data)
86{
87 return i2c_writemem(MPR121_I2C_ADDR, reg, &data, 1);
88}
89
90static inline int mpr121_read_reg(uint8_t reg, uint8_t *data)
91{
92 return i2c_readmem(MPR121_I2C_ADDR, reg, data, 1);
93}
94
95void mpr121_init(void)
96{
97 /* soft reset */
98 mpr121_write_reg(REG_SOFTRESET, REG_SOFTRESET__MAGIC);
99 /* enable interrupt */
100 imx233_pinctrl_acquire(0, 18, "mpr121_int");
101 imx233_pinctrl_set_function(0, 18, PINCTRL_FUNCTION_GPIO);
102 imx233_pinctrl_enable_gpio(0, 18, false);
103 imx233_pinctrl_setup_irq(0, 18, true, true, false, &mpr121_irq_cb, 0);
104}
105
106void mpr121_set_config(struct mpr121_config_t *conf)
107{
108 /* stop mode */
109 mpr121_write_reg(REG_ELECTRODE, 0);
110 /* write baseline values */
111 for(int i = 0; i < ELECTRODE_COUNT; i++)
112 mpr121_write_reg(REG_ExBV(i), conf->ele[i].bv);
113 /* write eleprox bv */
114 mpr121_write_reg(REG_EPROXBV, conf->eleprox.bv);
115 /* write global fields */
116 mpr121_write_reg(REG_MHDR, conf->filters.ele.rising.mhd);
117 mpr121_write_reg(REG_NHDR, conf->filters.ele.rising.nhd);
118 mpr121_write_reg(REG_NCLR, conf->filters.ele.rising.ncl);
119 mpr121_write_reg(REG_FDLR, conf->filters.ele.rising.fdl);
120 mpr121_write_reg(REG_MHDF, conf->filters.ele.falling.mhd);
121 mpr121_write_reg(REG_NHDF, conf->filters.ele.falling.nhd);
122 mpr121_write_reg(REG_NCLF, conf->filters.ele.falling.ncl);
123 mpr121_write_reg(REG_FDLF, conf->filters.ele.falling.fdl);
124 mpr121_write_reg(REG_NHDT, conf->filters.ele.touched.nhd);
125 mpr121_write_reg(REG_NCLT, conf->filters.ele.touched.ncl);
126 mpr121_write_reg(REG_FDLT, conf->filters.ele.touched.fdl);
127 mpr121_write_reg(REG_MHDPROXR, conf->filters.eleprox.rising.mhd);
128 mpr121_write_reg(REG_NHDPROXR, conf->filters.eleprox.rising.nhd);
129 mpr121_write_reg(REG_NCLPROXR, conf->filters.eleprox.rising.ncl);
130 mpr121_write_reg(REG_FDLPROXR, conf->filters.eleprox.rising.fdl);
131 mpr121_write_reg(REG_MHDPROXF, conf->filters.eleprox.falling.mhd);
132 mpr121_write_reg(REG_NHDPROXF, conf->filters.eleprox.falling.nhd);
133 mpr121_write_reg(REG_NCLPROXF, conf->filters.eleprox.falling.ncl);
134 mpr121_write_reg(REG_FDLPROXF, conf->filters.eleprox.falling.fdl);
135 mpr121_write_reg(REG_NHDPROXT, conf->filters.eleprox.touched.nhd);
136 mpr121_write_reg(REG_NCLPROXT, conf->filters.eleprox.touched.ncl);
137 mpr121_write_reg(REG_FDLPROXT, conf->filters.eleprox.touched.fdl);
138 /* touch & release thresholds */
139 for(int i = 0; i < ELECTRODE_COUNT; i++)
140 {
141 mpr121_write_reg(REG_ExTTH(i), conf->ele[i].tth);
142 mpr121_write_reg(REG_ExRTH(i), conf->ele[i].rth);
143 }
144 mpr121_write_reg(REG_EPROXTTH, conf->eleprox.tth);
145 mpr121_write_reg(REG_EPROXRTH, conf->eleprox.rth);
146 /* debounce */
147 mpr121_write_reg(REG_DEBOUNCE, REG_DEBOUNCE__DR(conf->debounce.dr) |
148 REG_DEBOUNCE__DT(conf->debounce.dt));
149 /* analog-front end and filters */
150 mpr121_write_reg(REG_AFE, REG_AFE__CDC(conf->global.cdc) |
151 REG_AFE__FFI(conf->global.ffi));
152 mpr121_write_reg(REG_FILTER, REG_FILTER__CDT(conf->global.cdt) |
153 REG_FILTER__ESI(conf->global.esi) | REG_FILTER__SFI(conf->global.sfi));
154 /* electrode charge */
155 for(int i = 0; i < ELECTRODE_COUNT; i++)
156 mpr121_write_reg(REG_CDCx(i), conf->ele[i].cdc);
157 mpr121_write_reg(REG_CDCPROX, conf->eleprox.cdc);
158 for(int i = 0; i < ELECTRODE_COUNT; i += 2)
159 {
160 mpr121_write_reg(REG_CDTx(i), REG_CDTx__CDT0(conf->ele[i].cdt) |
161 REG_CDTx__CDT1(conf->ele[i+1].cdt));
162 }
163 mpr121_write_reg(REG_CDTPROX, conf->eleprox.cdt);
164 /* Auto-Configuration */
165 mpr121_write_reg(REG_AUTO_CONF, REG_AUTO_CONF__ACE(conf->autoconf.en) |
166 REG_AUTO_CONF__ARE(conf->autoconf.ren) |
167 REG_AUTO_CONF__BVA(conf->cal_lock) |
168 REG_AUTO_CONF__RETRY(conf->autoconf.retry) |
169 REG_AUTO_CONF__FFI(conf->global.ffi));
170 mpr121_write_reg(REG_AUTO_CONF2, REG_AUTO_CONF2__ACFIE(conf->autoconf.acfie) |
171 REG_AUTO_CONF2__ARFIE(conf->autoconf.arfie) |
172 REG_AUTO_CONF2__OORIE(conf->autoconf.oorie) |
173 REG_AUTO_CONF2__SCTS(conf->autoconf.scts));
174 mpr121_write_reg(REG_USL, conf->autoconf.usl);
175 mpr121_write_reg(REG_LSL, conf->autoconf.lsl);
176 mpr121_write_reg(REG_TL, conf->autoconf.tl);
177 /* electrode configuration */
178 mpr121_write_reg(REG_ELECTRODE, REG_ELECTRODE__ELE_EN(conf->ele_en) |
179 REG_ELECTRODE__ELEPROX_EN(conf->eleprox_en) |
180 REG_ELECTRODE__CL(conf->cal_lock));
181 /* gpio config */
182 uint8_t ctl = 0;
183 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
184 if(ELE_GPIO_CTL0(conf->ele[i].gpio))
185 ctl |= REG_GPIO_CTL0__CTL0x(i);
186 mpr121_write_reg(REG_GPIO_CTL0, ctl);
187 ctl = 0;
188 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
189 if(ELE_GPIO_CTL1(conf->ele[i].gpio))
190 ctl |= REG_GPIO_CTL1__CTL1x(i);
191 mpr121_write_reg(REG_GPIO_CTL1, ctl);
192 ctl = 0;
193 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
194 if(ELE_GPIO_DIR(conf->ele[i].gpio))
195 ctl |= REG_GPIO_DIR__DIRx(i);
196 mpr121_write_reg(REG_GPIO_DIR, ctl);
197 ctl = 0;
198 for(int i = ELE_GPIO_FIRST; i <= ELE_GPIO_LAST; i++)
199 if(ELE_GPIO_EN(conf->ele[i].gpio))
200 ctl |= REG_GPIO_EN__ENx(i);
201 mpr121_write_reg(REG_GPIO_EN, ctl);
202}
203
204void mpr121_set_gpio_output(int ele, int gpio_val)
205{
206 switch(gpio_val)
207 {
208 case ELE_GPIO_SET:
209 mpr121_write_reg(REG_GPIO_SET, REG_GPIO_SET__SETx(ele));
210 break;
211 case ELE_GPIO_CLR:
212 mpr121_write_reg(REG_GPIO_CLR, REG_GPIO_CLR__CLRx(ele));
213 break;
214 case ELE_GPIO_TOG:
215 mpr121_write_reg(REG_GPIO_TOG, REG_GPIO_TOG__TOGx(ele));
216 break;
217 default:
218 break;
219 }
220}
221
222void mpr121_set_gpio_pwm(int ele, int pwm)
223{
224 uint8_t reg_val;
225 mpr121_read_reg(REG_PWMx(ele), &reg_val);
226 if(REG_PWMx_IS_PWM0(ele))
227 reg_val = (reg_val & ~REG_PWMx__PWM0_BM) | REG_PWMx__PWM0(pwm);
228 else
229 reg_val = (reg_val & ~REG_PWMx__PWM1_BM) | REG_PWMx__PWM1(pwm);
230 mpr121_write_reg(REG_PWMx(ele), reg_val);
231}
232
233unsigned mpr121_get_touch_status(void)
234{
235 return touch_status;
236}
diff --git a/firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.h b/firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.h
new file mode 100644
index 0000000000..eb8b00eeee
--- /dev/null
+++ b/firmware/target/arm/imx233/creative-zenxfi3/mpr121-zenxfi3.h
@@ -0,0 +1,176 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2016 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#ifndef __MPR121_ZENXFI3_H__
22#define __MPR121_ZENXFI3_H__
23
24/** Driver for the Freescale MPR121 Capacitive Proximity Sensor */
25#include "system.h"
26
27#define ELECTRODE_COUNT 12
28#define ELE_GPIO_FIRST 4
29#define ELE_GPIO_LAST 11
30
31/* gpio config (encoding: [0]=en,[1]=dir,[2]=ctl[1],[3]=ctl[0]) */
32#define ELE_GPIO_DISABLE 0
33#define ELE_GPIO_INPUT 1
34#define ELE_GPIO_INPUT_PULLDOWN 9 /* input with pull-down */
35#define ELE_GPIO_INPUT_PULLUP 13 /* input with pull-up */
36#define ELE_GPIO_OUTPUT 3
37#define ELE_GPIO_OUTPUT_OPEN 11 /* open drain low-side */
38#define ELE_GPIO_OUTPUT_OPEN_LED 15 /* open drain high-side (led driver) */
39
40/* internal use */
41#define ELE_GPIO_EN(val) ((val) & 1)
42#define ELE_GPIO_DIR(val) (((val) >> 1) & 1)
43#define ELE_GPIO_CTL0(val) (((val) >> 3) & 1)
44#define ELE_GPIO_CTL1(val) (((val) >> 1) & 1)
45
46struct mpr121_electrode_config_t
47{
48 uint8_t bv; /* baseline value */
49 uint8_t tth; /* touch threshold */
50 uint8_t rth; /* release threshold */
51 uint8_t cdc; /* charge current (optional if auto-conf) */
52 uint8_t cdt; /* charge time (optional if auto-conf) */
53 int gpio; /* gpio config */
54};
55
56struct mpr121_baseline_filter_config_t
57{
58 uint8_t mhd; /* max half delta (except for touched) */
59 uint8_t nhd; /* noise half delta */
60 uint8_t ncl; /* noise count limit */
61 uint8_t fdl; /* filter delay count limit */
62};
63
64struct mpr121_baseline_filters_config_t
65{
66 struct mpr121_baseline_filter_config_t rising;
67 struct mpr121_baseline_filter_config_t falling;
68 struct mpr121_baseline_filter_config_t touched;
69};
70
71struct mpr121_debounce_config_t
72{
73 uint8_t dt; /* debounce count for touch */
74 uint8_t dr; /* debounce count for release */
75};
76
77/* first filter iterations */
78#define FFI_6_SAMPLES 0
79#define FFI_10_SAMPLES 1
80#define FFI_18_SAMPLES 2
81#define FFI_34_SAMPLES 3
82/* charge discharge current */
83#define CDC_DISABLE 0
84#define CDC_uA(ua) (ua)
85/* charge discharge time */
86#define CDT_DISABLE 0
87#define CDT_log_us(lus) (lus) /* actual value = 2^{us-2} µs */
88/* second filter iterations */
89#define SFI_4_SAMPLES 0
90#define SFI_6_SAMPLES 1
91#define SFI_10_SAMPLES 2
92#define SFI_18_SAMPLES 3
93/* Eletrode sample interval */
94#define ESI_log_ms(lms) (lms) /* actual value = 2^{lms} ms */
95
96struct mpr121_global_config_t
97{
98 uint8_t ffi; /* first filter iterations */
99 uint8_t cdc; /* global charge discharge current */
100 uint8_t cdt; /* global charge discharge time */
101 uint8_t sfi; /* second first iterations */
102 uint8_t esi; /* electrode sample interval */
103};
104
105#define RETRY_NEVER 0
106#define RETRY_2_TIMES 1
107#define RETRY_4_TIMES 2
108#define RETRY_8_TIMES 3
109
110struct mpr121_auto_config_t
111{
112 bool en; /* auto-conf enable */
113 bool ren; /* auto-reconf enable */
114 uint8_t retry; /* retry count */
115 bool scts; /* skip charge time search */
116 uint8_t usl; /* upper-side limit */
117 uint8_t lsl; /* lower-side limit */
118 uint8_t tl; /* target level */
119 bool acfie; /* auto-conf fail interrupt en */
120 bool arfie; /* auto-reconf fail interrupt en */
121 bool oorie; /* out of range interrupt en */
122};
123
124/* electrode mode */
125#define ELE_DISABLE 0
126#define ELE_EN0_x(x) ((x) + 1)
127/* eleprox mode */
128#define ELEPROX_DISABLE 0
129#define ELEPROX_EN0_1 1
130#define ELEPROX_EN0_3 2
131#define ELEPROX_EN0_11 3
132/* calibration lock */
133#define CL_SLOW_TRACK 0
134#define CL_DISABLE 1
135#define CL_TRACK 2
136#define CL_FAST_TRACK 3
137
138struct mpr121_config_t
139{
140 struct mpr121_electrode_config_t ele[ELECTRODE_COUNT];
141 struct mpr121_electrode_config_t eleprox;
142 struct
143 {
144 struct mpr121_baseline_filters_config_t ele;
145 struct mpr121_baseline_filters_config_t eleprox;
146 }filters;
147 struct mpr121_debounce_config_t debounce;
148 struct mpr121_global_config_t global;
149 struct mpr121_auto_config_t autoconf;
150 uint8_t ele_en; /* eletroce mode */
151 uint8_t eleprox_en; /* proximity mode */
152 uint8_t cal_lock; /* calibration lock */
153};
154
155/* gpio value */
156#define ELE_GPIO_CLR 0
157#define ELE_GPIO_SET 1
158#define ELE_GPIO_TOG 2
159/* pwm value */
160#define ELE_PWM_DISABLE 0
161#define ELE_PWM_DUTY(x) (x)
162#define ELE_PWM_MIN_DUTY 1
163#define ELE_PWM_MAX_DUTY 15
164
165void mpr121_init(void);
166void mpr121_set_config(struct mpr121_config_t *conf);
167/* gpios are only implemented for electrode>=4, use ELE_GPIO_* for value */
168void mpr121_set_gpio_output(int ele, int gpio_val);
169/* pwm value is between 0 and 15, use ELE_PWM_DISABLE or ELE_PWM_DUTY */
170void mpr121_set_gpio_pwm(int ele, int pwm);
171/* get electrode status (bitmap)
172 * NOTE this function merely returns the last electrode status read from the
173 * device and does not actively ask the device for touch status. */
174unsigned mpr121_get_touch_status(void);
175
176#endif /* __MPR121_ZENXFI3_H__ */