adbe1a5aaf15195882a7c38911599ee4902b1601
[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.1 / adc / 0004-tscadc-Add-general-purpose-mode-untested-with-touchs.patch
1 From 2b44ca7878e41f25b91486ebcb8db2c3be1f61eb Mon Sep 17 00:00:00 2001
2 From: Joel A Fernandes <joelagnel@ti.com>
3 Date: Sat, 29 Oct 2011 01:17:43 -0500
4 Subject: [PATCH 4/9] tscadc: Add general purpose mode, untested with touchscreen functionality
6 Signed-off-by: Joel A Fernandes <joelagnel@ti.com>
7 ---
8 adc-notes.txt | 33 +++++
9 arch/arm/mach-omap2/board-am335xevm.c | 6 +
10 arch/arm/mach-omap2/mux33xx.c | 12 ++
11 arch/arm/mach-omap2/mux33xx.h | 4 +
12 drivers/input/touchscreen/ti_tscadc.c | 209 +++++++++++++++++++++++++--------
13 include/linux/input/ti_tscadc.h | 4 +
14 6 files changed, 216 insertions(+), 52 deletions(-)
15 create mode 100755 adc-notes.txt
17 diff --git a/adc-notes.txt b/adc-notes.txt
18 new file mode 100755
19 index 0000000..178e262
20 --- /dev/null
21 +++ b/adc-notes.txt
22 @@ -0,0 +1,33 @@
23 +Features
24 + - software register bit for SOC (Start of conversion) and EOC
25 + - single conversion (one-shot) - software enabled
26 + - Data stored in either of 2 fifo groups- can be read through dma or cpu
27 +
28 +
29 +Events
30 + - Status bit to indicate if ADC is busy converting (can use polling to check if conversion is finished)
31 + - Interrupts on FIFO threhold levels reached
32 + - In on one-shot mode, Step-enable bit is turned off automatically after conversion - can be used to check if conversion is finished.
33 + - END_OF_SEQUENCE interrupt can be configured when the FSM is done with the last enabled step (but should not be used to check if data is in the FIFO)
34 + - For availability of data, the FIFO interrupts and word count reg should be used.
35 +
36 +Clocks-
37 + - ADC uses adc_clk
38 + - Sequencers, FIFO etc use ocp_clk
39 +
40 +One shot mode
41 + - Step-enable bit is turned off automatically after conversion - can be used to check if conversion is finished.
42 +
43 +ADC Controller
44 +==============
45 +*** config steps
46 +1. configure a STEPCONFIG register
47 + For ADC we would like to configure the steps as general-purpose (non-touch screen)
48 +2. Enable TSC_ADC_SS
49 +3. Set STEPENABLE bit of any step for the sequencer to go to that step, perform conversion and store the data in FIFO
50 +
51 +*** reading data:
52 +1. Check word count reg in FIFO register
53 +2. If non 0, read word
54 +3. Step enable bit can be polled to check if conversion is over or not.
55 +
56 diff --git a/arch/arm/mach-omap2/board-am335xevm.c b/arch/arm/mach-omap2/board-am335xevm.c
57 index 46fce3e..c8da580 100644
58 --- a/arch/arm/mach-omap2/board-am335xevm.c
59 +++ b/arch/arm/mach-omap2/board-am335xevm.c
60 @@ -456,6 +456,10 @@ static struct pinmux_config tsc_pin_mux[] = {
61 {"ain1.ain1", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
62 {"ain2.ain2", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
63 {"ain3.ain3", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
64 + {"ain4.ain4", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
65 + {"ain5.ain5", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
66 + {"ain6.ain6", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
67 + {"ain7.ain7", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
68 {"vrefp.vrefp", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
69 {"vrefn.vrefn", OMAP_MUX_MODE0 | AM33XX_INPUT_EN},
70 {NULL, 0},
71 @@ -1513,6 +1517,7 @@ static struct evm_dev_cfg beaglebone_old_dev_cfg[] = {
72 {usb1_init, DEV_ON_BASEBOARD, PROFILE_NONE},
73 {mmc0_init, DEV_ON_BASEBOARD, PROFILE_NONE},
74 {boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
75 + {tsc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
76 {NULL, 0, 0},
77 };
79 @@ -1524,6 +1529,7 @@ static struct evm_dev_cfg beaglebone_dev_cfg[] = {
80 {usb1_init, DEV_ON_BASEBOARD, PROFILE_NONE},
81 {mmc0_init, DEV_ON_BASEBOARD, PROFILE_NONE},
82 {boneleds_init, DEV_ON_BASEBOARD, PROFILE_ALL},
83 + {tsc_init, DEV_ON_BASEBOARD, PROFILE_ALL},
84 {NULL, 0, 0},
85 };
87 diff --git a/arch/arm/mach-omap2/mux33xx.c b/arch/arm/mach-omap2/mux33xx.c
88 index 4399003..832a50b 100644
89 --- a/arch/arm/mach-omap2/mux33xx.c
90 +++ b/arch/arm/mach-omap2/mux33xx.c
91 @@ -587,6 +587,18 @@ static struct omap_mux __initdata am33xx_muxmodes[] = {
92 _AM33XX_MUXENTRY(AIN3, 0,
93 "ain3", NULL, NULL, NULL,
94 NULL, NULL, NULL, NULL),
95 + _AM33XX_MUXENTRY(AIN4, 0,
96 + "ain4", NULL, NULL, NULL,
97 + NULL, NULL, NULL, NULL),
98 + _AM33XX_MUXENTRY(AIN5, 0,
99 + "ain5", NULL, NULL, NULL,
100 + NULL, NULL, NULL, NULL),
101 + _AM33XX_MUXENTRY(AIN6, 0,
102 + "ain6", NULL, NULL, NULL,
103 + NULL, NULL, NULL, NULL),
104 + _AM33XX_MUXENTRY(AIN7, 0,
105 + "ain7", NULL, NULL, NULL,
106 + NULL, NULL, NULL, NULL),
107 _AM33XX_MUXENTRY(VREFP, 0,
108 "vrefp", NULL, NULL, NULL,
109 NULL, NULL, NULL, NULL),
110 diff --git a/arch/arm/mach-omap2/mux33xx.h b/arch/arm/mach-omap2/mux33xx.h
111 index 70a3012..348c8e5 100644
112 --- a/arch/arm/mach-omap2/mux33xx.h
113 +++ b/arch/arm/mach-omap2/mux33xx.h
114 @@ -228,6 +228,10 @@
115 #define AM33XX_CONTROL_PADCONF_DDR_DQSN1_OFFSET 0x0AFC
116 #define AM33XX_CONTROL_PADCONF_DDR_VREF_OFFSET 0x0B00
117 #define AM33XX_CONTROL_PADCONF_DDR_VTP_OFFSET 0x0B04
118 +#define AM33XX_CONTROL_PADCONF_AIN7_OFFSET 0x0B10
119 +#define AM33XX_CONTROL_PADCONF_AIN6_OFFSET 0x0B14
120 +#define AM33XX_CONTROL_PADCONF_AIN5_OFFSET 0x0B18
121 +#define AM33XX_CONTROL_PADCONF_AIN4_OFFSET 0x0B1C
122 #define AM33XX_CONTROL_PADCONF_AIN3_OFFSET 0x0B20
123 #define AM33XX_CONTROL_PADCONF_AIN2_OFFSET 0x0B24
124 #define AM33XX_CONTROL_PADCONF_AIN1_OFFSET 0x0B28
125 diff --git a/drivers/input/touchscreen/ti_tscadc.c b/drivers/input/touchscreen/ti_tscadc.c
126 index 9783435..76fc7b6 100644
127 --- a/drivers/input/touchscreen/ti_tscadc.c
128 +++ b/drivers/input/touchscreen/ti_tscadc.c
129 @@ -27,6 +27,8 @@
130 #include <linux/input/ti_tscadc.h>
131 #include <linux/delay.h>
133 +/* Memory mapped registers here have incorrect offsets!
134 + * Correct after referring TRM */
135 #define TSCADC_REG_IRQEOI 0x020
136 #define TSCADC_REG_RAWIRQSTATUS 0x024
137 #define TSCADC_REG_IRQSTATUS 0x028
138 @@ -54,12 +56,18 @@
140 /* Register Bitfields */
141 #define TSCADC_IRQWKUP_ENB BIT(0)
142 -#define TSCADC_STPENB_STEPENB 0x7FFF
143 +#define TSCADC_STPENB_STEPENB_TOUCHSCREEN 0x7FFF
144 +#define TSCADC_STPENB_STEPENB_GENERAL 0x0400
145 #define TSCADC_IRQENB_FIFO0THRES BIT(2)
146 +#define TSCADC_IRQENB_FIFO0OVERRUN BIT(3)
147 #define TSCADC_IRQENB_FIFO1THRES BIT(5)
148 +#define TSCADC_IRQENB_EOS BIT(1)
149 #define TSCADC_IRQENB_PENUP BIT(9)
150 -#define TSCADC_STEPCONFIG_MODE_HWSYNC 0x2
151 +#define TSCADC_STEPCONFIG_MODE_HWSYNC 0x2
152 +#define TSCADC_STEPCONFIG_MODE_SWCONT 0x1
153 +#define TSCADC_STEPCONFIG_MODE_SWONESHOT 0x0
154 #define TSCADC_STEPCONFIG_2SAMPLES_AVG (1 << 4)
155 +#define TSCADC_STEPCONFIG_NO_AVG 0
156 #define TSCADC_STEPCONFIG_XPP BIT(5)
157 #define TSCADC_STEPCONFIG_XNN BIT(6)
158 #define TSCADC_STEPCONFIG_YPP BIT(7)
159 @@ -72,7 +80,7 @@
160 #define TSCADC_STEPCONFIG_INP (1 << 20)
161 #define TSCADC_STEPCONFIG_INP_5 (1 << 21)
162 #define TSCADC_STEPCONFIG_FIFO1 (1 << 26)
163 -#define TSCADC_STEPCONFIG_IDLE_INP (1 << 22)
164 +#define TSCADC_STEPCONFIG_IDLE_INP 0x0000
165 #define TSCADC_STEPCONFIG_OPENDLY 0x018
166 #define TSCADC_STEPCONFIG_SAMPLEDLY 0x88
167 #define TSCADC_STEPCONFIG_Z1 (3 << 19)
168 @@ -104,6 +112,7 @@ struct tscadc {
169 int wires;
170 int analog_input;
171 int x_plate_resistance;
172 + int mode;
173 struct clk *clk;
174 int irq;
175 void __iomem *tsc_base;
176 @@ -120,6 +129,86 @@ static void tscadc_writel(struct tscadc *tsc, unsigned int reg,
177 writel(val, tsc->tsc_base + reg);
178 }
180 +static void tsc_adc_step_config(struct tscadc *ts_dev)
181 +{
182 + unsigned int stepconfig = 0, delay = 0, chargeconfig = 0;
183 +
184 + /*
185 + * Step Configuration
186 + * software-enabled continous mode
187 + * 2 sample averaging
188 + * sample channel 1 (SEL_INP mux bits = 0)
189 + */
190 + stepconfig = TSCADC_STEPCONFIG_MODE_SWONESHOT |
191 + TSCADC_STEPCONFIG_2SAMPLES_AVG |
192 + (0x7 << 19);
193 +
194 + delay = TSCADC_STEPCONFIG_SAMPLEDLY | TSCADC_STEPCONFIG_OPENDLY;
195 +
196 + tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG(10), stepconfig);
197 + tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY(10), delay);
198 +
199 + /* Get the ball rolling, this will trigger the FSM to step through
200 + * as soon as TSC_ADC_SS is turned on */
201 + tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_GENERAL);
202 +}
203 +
204 +static irqreturn_t tsc_adc_interrupt(int irq, void *dev)
205 +{
206 + struct tscadc *ts_dev = (struct tscadc *)dev;
207 + struct input_dev *input_dev = ts_dev->input;
208 + unsigned int status, irqclr = 0;
209 + int i;
210 + int fsm = 0, fifo0count = 0, fifo1count = 0;
211 + unsigned int read_sample = 0, ready1 = 0;
212 + unsigned int prev_val_x = ~0, prev_val_y = ~0;
213 + unsigned int prev_diff_x = ~0, prev_diff_y = ~0;
214 + unsigned int cur_diff_x = 0, cur_diff_y = 0;
215 + unsigned int val_x = 0, val_y = 0, diffx = 0, diffy = 0;
216 +
217 + status = tscadc_readl(ts_dev, TSCADC_REG_IRQSTATUS);
218 +
219 + printk("interrupt! status=%x\n", status);
220 + // if (status & TSCADC_IRQENB_EOS) {
221 + // irqclr |= TSCADC_IRQENB_EOS;
222 + // }
223 +
224 + if (status & TSCADC_IRQENB_FIFO0THRES) {
225 + fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO0CNT);
226 + printk("fifo 0 count = %d\n", fifo1count);
227 +
228 + for (i = 0; i < fifo1count; i++) {
229 + read_sample = tscadc_readl(ts_dev, TSCADC_REG_FIFO0);
230 + printk("sample: %d: %x\n", i, read_sample);
231 + }
232 + irqclr |= TSCADC_IRQENB_FIFO0THRES;
233 + }
234 +
235 +
236 + if (status & TSCADC_IRQENB_FIFO1THRES) {
237 + fifo1count = tscadc_readl(ts_dev, TSCADC_REG_FIFO1CNT);
238 +
239 + for (i = 0; i < fifo1count; i++) {
240 + read_sample = tscadc_readl(ts_dev, TSCADC_REG_FIFO1);
241 + // read_sample = read_sample & 0xfff;
242 + printk("sample: %d: %d\n", i, read_sample);
243 + panic("sample read from fifo1!");
244 + }
245 + irqclr |= TSCADC_IRQENB_FIFO1THRES;
246 + }
247 +
248 + mdelay(500);
249 +
250 + tscadc_writel(ts_dev, TSCADC_REG_IRQSTATUS, irqclr);
251 +
252 + /* check pending interrupts */
253 + tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
254 +
255 + /* Turn on Step 1 again */
256 + tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_GENERAL);
257 + return IRQ_HANDLED;
258 +}
259 +
260 static void tsc_step_config(struct tscadc *ts_dev)
261 {
262 unsigned int stepconfigx = 0, stepconfigy = 0;
263 @@ -224,7 +313,7 @@ static void tsc_step_config(struct tscadc *ts_dev)
264 tscadc_writel(ts_dev, TSCADC_REG_STEPCONFIG14, stepconfigz2);
265 tscadc_writel(ts_dev, TSCADC_REG_STEPDELAY14, delay);
267 - tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
268 + tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_TOUCHSCREEN);
269 }
271 static void tsc_idle_config(struct tscadc *ts_config)
272 @@ -242,7 +331,7 @@ static void tsc_idle_config(struct tscadc *ts_config)
273 tscadc_writel(ts_config, TSCADC_REG_IDLECONFIG, idleconfig);
274 }
276 -static irqreturn_t tscadc_interrupt(int irq, void *dev)
277 +static irqreturn_t tsc_interrupt(int irq, void *dev)
278 {
279 struct tscadc *ts_dev = (struct tscadc *)dev;
280 struct input_dev *input_dev = ts_dev->input;
281 @@ -362,7 +451,7 @@ static irqreturn_t tscadc_interrupt(int irq, void *dev)
282 /* check pending interrupts */
283 tscadc_writel(ts_dev, TSCADC_REG_IRQEOI, 0x0);
285 - tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB);
286 + tscadc_writel(ts_dev, TSCADC_REG_SE, TSCADC_STPENB_STEPENB_TOUCHSCREEN);
287 return IRQ_HANDLED;
288 }
290 @@ -400,13 +489,15 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
291 return -ENODEV;
292 }
294 - input_dev = input_allocate_device();
295 - if (!input_dev) {
296 - dev_err(&pdev->dev, "failed to allocate input device.\n");
297 - err = -ENOMEM;
298 - goto err_free_mem;
299 + if(pdata->mode == TI_TSCADC_TSCMODE) {
300 + input_dev = input_allocate_device();
301 + if (!input_dev) {
302 + dev_err(&pdev->dev, "failed to allocate input device.\n");
303 + err = -ENOMEM;
304 + goto err_free_mem;
305 + }
306 + ts_dev->input = input_dev;
307 }
308 - ts_dev->input = input_dev;
310 ts_dev->tsc_base = ioremap(res->start, resource_size(res));
311 if (!ts_dev->tsc_base) {
312 @@ -415,8 +506,15 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
313 goto err_release_mem;
314 }
316 - err = request_irq(ts_dev->irq, tscadc_interrupt, IRQF_DISABLED,
317 - pdev->dev.driver->name, ts_dev);
318 + if(pdata->mode == TI_TSCADC_TSCMODE) {
319 + err = request_irq(ts_dev->irq, tsc_interrupt, IRQF_DISABLED,
320 + pdev->dev.driver->name, ts_dev);
321 + }
322 + else {
323 + err = request_irq(ts_dev->irq, tsc_adc_interrupt, IRQF_DISABLED,
324 + pdev->dev.driver->name, ts_dev);
325 + }
326 +
327 if (err) {
328 dev_err(&pdev->dev, "failed to allocate irq.\n");
329 goto err_unmap_regs;
330 @@ -436,11 +534,15 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
331 goto err_free_irq;
332 }
333 clock_rate = clk_get_rate(ts_dev->clk);
334 +
335 + /* clk_value of atleast 21MHz required
336 + * Clock verified on BeagleBone to be 24MHz */
337 clk_value = clock_rate / ADC_CLK;
338 if (clk_value < 7) {
339 dev_err(&pdev->dev, "clock input less than min clock requirement\n");
340 goto err_fail;
341 }
342 +
343 /* TSCADC_CLKDIV needs to be configured to the value minus 1 */
344 clk_value = clk_value - 1;
345 tscadc_writel(ts_dev, TSCADC_REG_CLKDIV, clk_value);
346 @@ -451,56 +553,59 @@ static int __devinit tscadc_probe(struct platform_device *pdev)
347 ts_dev->wires = pdata->wires;
348 ts_dev->analog_input = pdata->analog_input;
349 ts_dev->x_plate_resistance = pdata->x_plate_resistance;
350 + ts_dev->mode = pdata->mode;
352 - /* Set the control register bits */
353 + /* Set the control register bits - 12.5.44 TRM */
354 ctrl = TSCADC_CNTRLREG_STEPCONFIGWRT |
355 - TSCADC_CNTRLREG_TSCENB |
356 - TSCADC_CNTRLREG_STEPID;
357 - switch (ts_dev->wires) {
358 - case 4:
359 - ctrl |= TSCADC_CNTRLREG_4WIRE;
360 - break;
361 - case 5:
362 - ctrl |= TSCADC_CNTRLREG_5WIRE;
363 - break;
364 - case 8:
365 - ctrl |= TSCADC_CNTRLREG_8WIRE;
366 - break;
367 + TSCADC_CNTRLREG_STEPID;
368 + if(pdata->mode == TI_TSCADC_TSCMODE) {
369 + ctrl |= TSCADC_CNTRLREG_TSCENB;
370 + switch (ts_dev->wires) {
371 + case 4:
372 + ctrl |= TSCADC_CNTRLREG_4WIRE;
373 + break;
374 + case 5:
375 + ctrl |= TSCADC_CNTRLREG_5WIRE;
376 + break;
377 + case 8:
378 + ctrl |= TSCADC_CNTRLREG_8WIRE;
379 + break;
380 + }
381 }
382 tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
384 - /* Set register bits for Idel Config Mode */
385 - tsc_idle_config(ts_dev);
386 -
387 - /* IRQ Enable */
388 - irqenable = TSCADC_IRQENB_FIFO1THRES;
389 + /* Touch screen / ADC configuration */
390 + if(pdata->mode == TI_TSCADC_TSCMODE) {
391 + tsc_idle_config(ts_dev);
392 + tsc_step_config(ts_dev);
393 + tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
394 + irqenable = TSCADC_IRQENB_FIFO1THRES;
395 + /* Touch screen also needs an input_dev */
396 + input_dev->name = "ti-tsc-adcc";
397 + input_dev->dev.parent = &pdev->dev;
398 + input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
399 + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
400 + input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
401 + input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
402 + /* register to the input system */
403 + err = input_register_device(input_dev);
404 + if (err)
405 + goto err_fail;
406 + }
407 + else {
408 + tsc_adc_step_config(ts_dev);
409 + tscadc_writel(ts_dev, TSCADC_REG_FIFO0THR, 0);
410 + irqenable = TSCADC_IRQENB_FIFO0THRES;
411 + }
412 tscadc_writel(ts_dev, TSCADC_REG_IRQENABLE, irqenable);
414 - tsc_step_config(ts_dev);
415 -
416 - tscadc_writel(ts_dev, TSCADC_REG_FIFO1THR, 6);
417 -
418 ctrl |= TSCADC_CNTRLREG_TSCSSENB;
419 - tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl);
420 -
421 - input_dev->name = "ti-tsc-adcc";
422 - input_dev->dev.parent = &pdev->dev;
423 -
424 - input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
425 - input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
426 -
427 - input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
428 - input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
429 - input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
430 -
431 - /* register to the input system */
432 - err = input_register_device(input_dev);
433 - if (err)
434 - goto err_fail;
435 + tscadc_writel(ts_dev, TSCADC_REG_CTRL, ctrl); /* Turn on TSC_ADC */
437 return 0;
439 err_fail:
440 + printk(KERN_ERR "Fatal error, shutting down TSC_ADC\n");
441 clk_disable(ts_dev->clk);
442 clk_put(ts_dev->clk);
443 err_free_irq:
444 diff --git a/include/linux/input/ti_tscadc.h b/include/linux/input/ti_tscadc.h
445 index 2c547bb..850cd4b 100644
446 --- a/include/linux/input/ti_tscadc.h
447 +++ b/include/linux/input/ti_tscadc.h
448 @@ -14,8 +14,12 @@
449 * @x_plate_resistance: X plate resistance.
450 */
452 +#define TI_TSCADC_TSCMODE 0
453 +#define TI_TSCADC_GENMODE 1
454 +
455 struct tsc_data {
456 int wires;
457 int analog_input;
458 int x_plate_resistance;
459 + int mode;
460 };
461 --
462 1.7.4.1