diff options
Diffstat (limited to 'firmware/target/arm/imx233')
4 files changed, 433 insertions, 76 deletions
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 | ||
30 | void backlight_hw_brightness(int brightness) | 30 | void 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 | ||
45 | static struct mpr121_config_t config = | 39 | /* MPR121 configuration, mostly extracted from OF */ |
40 | static 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 | |||
78 | static int touchpad_btns = 0; | ||
79 | static long mpr121_stack[DEFAULT_STACK_SIZE/sizeof(long)]; | ||
80 | static const char mpr121_thread_name[] = "mpr121"; | ||
81 | static struct event_queue mpr121_queue; | ||
82 | |||
83 | static 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 | |||
93 | static 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 */ |
130 | void button_init_device(void) | 72 | void 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 | |||
42 | static unsigned touch_status = 0; /* touch bitmask as reported by mpr121 */ | ||
43 | static struct imx233_i2c_xfer_t read_status_xfer; /* async transfer to read touch status */ | ||
44 | static uint8_t read_status_sel_reg; /* buffer for async transfer operation */ | ||
45 | static uint8_t read_status_buf[2]; /* buffer for async transfer operation */ | ||
46 | |||
47 | static void mpr121_irq_cb(int bank, int pin, intptr_t user); | ||
48 | |||
49 | static 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 | |||
59 | void 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 | |||
85 | static inline int mpr121_write_reg(uint8_t reg, uint8_t data) | ||
86 | { | ||
87 | return i2c_writemem(MPR121_I2C_ADDR, reg, &data, 1); | ||
88 | } | ||
89 | |||
90 | static inline int mpr121_read_reg(uint8_t reg, uint8_t *data) | ||
91 | { | ||
92 | return i2c_readmem(MPR121_I2C_ADDR, reg, data, 1); | ||
93 | } | ||
94 | |||
95 | void 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 | |||
106 | void 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 | |||
204 | void 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 | |||
222 | void mpr121_set_gpio_pwm(int ele, int pwm) | ||
223 | { | ||
224 | uint8_t reg_val; | ||
225 | mpr121_read_reg(REG_PWMx(ele), ®_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 | |||
233 | unsigned 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 | |||
46 | struct 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 | |||
56 | struct 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 | |||
64 | struct 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 | |||
71 | struct 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 | |||
96 | struct 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 | |||
110 | struct 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 | |||
138 | struct 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 | |||
165 | void mpr121_init(void); | ||
166 | void mpr121_set_config(struct mpr121_config_t *conf); | ||
167 | /* gpios are only implemented for electrode>=4, use ELE_GPIO_* for value */ | ||
168 | void 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 */ | ||
170 | void 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. */ | ||
174 | unsigned mpr121_get_touch_status(void); | ||
175 | |||
176 | #endif /* __MPR121_ZENXFI3_H__ */ | ||