6
Copyright (C) 2006 Marc Singer
8
This program is free software; you can redistribute it and/or
9
modify it under the terms of the GNU General Public License
10
version 2 as published by the Free Software Foundation.
11
Please refer to the file debian/copyright for further details.
18
Initialize the adc to its default state.
19
Map all touchscreen pins to ADC input
20
Set up the idle step to prevent false pen auto-triggering.
21
Flush the result FIFO.
22
Clear the pen and end of sequence interrupts.
23
Set up the sequence as follows:
24
0. Strong pullup on X+ pin, other pins float.
25
Measure on pin x+. This measurement will be discarded.
26
This step de-glitches any partial triggers.
27
1. Weak pullup on X+ pin, X- floats, Y- to Ground and neg
28
ref, Y+ floats (ratiometric).
29
Measure on X+ pin. This measurement is used to verify
30
the pen was down at the beginning of the coordinate
32
2. X+ and X- float, Y- to Ground and neg
33
ref, Y+ to VDDA_ADC and positive reference (ratiometric).
34
Measure on pin x+. This is the X measurement.
35
3. Repeat the X measurement 3 more times (we will average
36
4 measurements to improve signal-to-noise.
37
4. Y+ and Y- float, X- to Ground and neg
38
ref, X+ to VDDA_ADC and positive reference (ratiometric).
39
Measure on pin Y+. This is the Y measurement.
40
5. Repeat the Y measurement 3 more times (we will average
41
4 measurements to improve signal-to-noise.
42
6. Strong pullup on X+ pin, other pins float.
43
Measure on pin x+. This measurement will be discarded.
44
This step de-glitches any partial triggers.
45
7. Weak pullup on X+ pin, X- floats, Y- to Ground and neg
46
ref, Y+ floats (ratiometric).
47
Measure on X+ pin. This measurement is used to verify
48
the pen was down at the end of the coordinate
57
#include <linux/string.h>
60
#include <mach/hardware.h>
67
#define PRINTF(f...) printf (f)
68
#define ENTRY(l) printf ("%s\n", __FUNCTION__)
69
#define DBG(l,f...) do { if (TALK >= l) printf (f); } while (0)
71
#define PRINTF(f...) do {} while (0)
72
#define ENTRY(l) do {} while (0)
73
#define DBG(l,f...) do {} while (0)
76
#define ADC_FS_FFF (1<<3)
77
#define ADC_FS_FEMPTY (1<<2)
79
#define ADC_IC_BOI (1<<2)
80
#define ADC_IC_PEN (1<<1)
81
#define ADC_IC_EOS (1<<0)
83
#define ADC_IS_BROWNOUT (1<<4)
84
#define ADC_IS_PEN (1<<3)
85
#define ADC_IS_EOS (1<<2)
87
#define ADC_PC_CLKSEL_SHIFT (8)
88
#define ADC_PC_CLKSEL_MASK (7<<ADC_PC_CLKSEL_SHIFT)
89
#define ADC_PC_REFEN (1<<5)
90
#define ADC_PC_BATEN (1<<4)
91
#define ADC_PC_NOC_SHIFT (0)
92
#define ADC_PC_NOC_MASK (0xf)
93
#define ADC_PC_PWM_MASK (3<<6)
94
#define ADC_PC_PWM_OFF (0<<6)
95
#define ADC_PC_PWM_STANDBY (1<<6)
96
#define ADC_PC_PWM_RUN (2<<6)
98
#define ADC_HW_SETTIME_SHIFT (7)
99
#define ADC_HW_SETTIME_MASK (0x1ff<<ADC_HW_SETTIME_SHIFT)
100
#define ADC_HW_INP_SHIFT (3)
101
#define ADC_HW_INP_MASK (0xf<<ADC_HW_INP_SHIFT)
102
#define ADC_HW_INP_AN0 (0<<3) /* UL/X+ */
103
#define ADC_HW_INP_AN1 (1<<3) /* UR/X- */
104
#define ADC_HW_INP_AN2 (2<<3) /* LL/Y+ */
105
#define ADC_HW_INP_AN3 (3<<3) /* LR/Y- */
106
#define ADC_HW_INP_AN4 (4<<3) /* Wiper */
107
#define ADC_HW_INP_AN5 (5<<3)
108
#define ADC_HW_INP_AN6 (6<<3)
109
#define ADC_HW_INP_AN7 (7<<3)
110
#define ADC_HW_INP_AN8 (8<<3)
111
#define ADC_HW_INP_AN9 (9<<3)
112
#define ADC_HW_INP_VREFN (10<<3) /* VREF- */
113
#define ADC_HW_INN_GND (1<<2)
114
#define ADC_HW_INN_REFN (0<<2) /* VREF- */
115
#define ADC_HW_REFP_MASK (3<<0)
116
#define ADC_HW_REFP_VREFP (0<<0) /* VREF+ */
117
#define ADC_HW_REFP_AN0 (1<<0) /* UL/X+ */
118
#define ADC_HW_REFP_AN2 (2<<0) /* LL/Y+ */
119
#define ADC_HW_REFP_AN8 (3<<0)
120
#define ADC_LW_REFN_VREFN (0<<0)
121
#define ADC_LW_REFN_AN1 (1<<0)
122
#define ADC_LW_REFN_AN3 (2<<0)
123
#define ADC_LW_REFN_AN9 (3<<0)
124
#define ADC_LW_BIASCON_SHIFT (2)
125
#define ADC_LW_BIASCON_MASK (0xfff<<2)
127
#define ADC_LW_FET_AN0_VDD (1<<2)
128
#define ADC_LW_FET_AN0_VDD100K (1<<12)
129
#define ADC_LW_FET_AN1_VDD (1<<3)
130
#define ADC_LW_FET_AN1_GND (1<<4)
131
#define ADC_LW_FET_AN2_VDD (1<<5)
132
#define ADC_LW_FET_AN2_GND (1<<6)
133
#define ADC_LW_FET_AN3_GND (1<<7)
134
#define ADC_LW_FET_AN4_VDD100K (1<<13)
135
#define ADC_LW_FET_AN4_GND (1<<8)
137
#define ADC_GC_SSM_MASK (3<<0)
138
#define ADC_GC_SSM_SSB_PEN (0<<0)
139
#define ADC_GC_SSM_PEN (1<<0)
140
#define ADC_GC_SSM_SSB (2<<0)
141
#define ADC_GC_SSM_CONT (3<<0)
142
#define ADC_GC_SSB (1<<2)
143
#define ADC_GC_FIFOWMK_SHIFT (3)
144
#define ADC_GC_FIFOWMK_MASK (0xf<<ADC_GC_FIFOWMK_SHIFT)
146
# define US_SETTLING (20) /* Signal stablization */
148
/* We're aiming for sampling at about 400KHz */
150
#if defined (CONFIG_ARCH_LH79524) || defined (CONFIG_ARCH_LH79525)
151
# define ADC_CLKSEL (0x7)
152
# define CLKSEL (1<<ADC_CLKSEL)
153
# define RCPC_ADCPRE_V (1)
154
# define A2DCLK (50803200/RCPC_ADCPRE_V/CLKSEL)
157
#if defined (CONFIG_ARCH_LH7A404)
158
# define ADC_CLKSEL (0x2)
159
# define CLKSEL (1<<ADC_CLKSEL)
160
# define A2DCLK (1843200/CLKSEL)
163
#define ADC_PC_CLKSEL_V (ADC_CLKSEL<<ADC_PC_CLKSEL_SHIFT)
165
#define SETTIME(us) (((A2DCLK*(us) + 1000000/2)/1000000)\
166
<<ADC_HW_SETTIME_SHIFT)
170
static void accel_setup (void)
176
PRINTF ("adc: A2DCLK %d SETTIME(US) %0xx\n", A2DCLK, SETTIME(US_SETTLING));
178
ADC_IC = ADC_IC_BOI | ADC_IC_PEN | ADC_IC_EOS;
180
/* Flush the results FIFO */
181
while ((ADC_FS & ADC_FS_FEMPTY) == 0)
184
MASK_AND_SET (ADC_PC,
185
ADC_PC_NOC_MASK | ADC_PC_PWM_MASK,
186
((SAMPLES - 1)<<ADC_PC_NOC_SHIFT)|(ADC_PC_PWM_OFF)
190
MASK_AND_SET (ADC_GC,
191
ADC_GC_SSM_MASK | ADC_GC_FIFOWMK_MASK,
194
// | (12<<ADC_GC_FIFOWMK_SHIFT)
197
// ADC_PC |= ADC_PC_REFEN;
199
#define _HI(p) (SETTIME (US_SETTLING) | (p) | ADC_HW_INN_REFN)
203
ADC_IHWCTRL = _HI (ADC_HW_INP_AN9);
204
ADC_ILWCTRL = _LO (ADC_LW_REFN_AN9); /* No bias control necessary */
207
for (i = 0; i < 16; ++i) {
217
__REG(ADC_HWC_BASE_PHYS + i*4) = _HI (ADC_HW_INP_AN0 | ADC_HW_REFP_AN8);
218
__REG(ADC_LWC_BASE_PHYS + i*4) = _LO (ADC_LW_REFN_AN9);
228
__REG(ADC_HWC_BASE_PHYS + i*4) = _HI (ADC_HW_INP_AN1 | ADC_HW_REFP_AN8);
229
__REG(ADC_LWC_BASE_PHYS + i*4) = _LO (ADC_LW_REFN_AN9);
232
__REG(ADC_HWC_BASE_PHYS + i*4) = 0;
233
__REG(ADC_LWC_BASE_PHYS + i*4) = 0;
238
MASK_AND_SET (ADC_PC, ADC_PC_PWM_MASK, ADC_PC_PWM_STANDBY);
241
static void accel_init (void)
247
ADC_IM = 0; /* Disable all interrupts */
249
ADC_PC = ADC_PC_CLKSEL_V | ADC_PC_PWM_OFF | (1<<ADC_PC_NOC_SHIFT);
252
| (0xf<<ADC_GC_FIFOWMK_SHIFT);
255
for (i = 0; i < SAMPLES; ++i) {
256
__REG(ADC_HWC_BASE_PHYS + i*4) = (0x1ff << ADC_HW_SETTIME_SHIFT)
257
| (i << ADC_HW_INP_SHIFT) | ADC_HW_INN_GND | ADC_HW_REFP_VREFP;
258
__REG(ADC_LWC_BASE_PHYS + i*4) = ADC_LW_REFN_VREFN;
261
ADC_IHWCTRL = (0x1ff << ADC_HW_SETTIME_SHIFT)
262
| ADC_HW_INP_AN0 | ADC_HW_INN_GND | ADC_HW_REFP_VREFP;
263
ADC_ILWCTRL = ADC_LW_REFN_VREFN;
265
/* Flush the results FIFO */
266
while ((ADC_FS & ADC_FS_FEMPTY) == 0)
269
ADC_IC = ADC_IC_BOI | ADC_IC_PEN | ADC_IC_EOS;
274
#define MS_TIMEOUT 2*1000
275
#define MS_ADC_DELAY 600
277
#define REF ((1023*33)/10)
279
static int cmd_accel (int argc, const char** argv)
281
unsigned long status;
283
unsigned long timeStart;
288
// printf ("\n\n\n\n\n");
291
/* Flush the results FIFO */
292
while ((ADC_FS & ADC_FS_FEMPTY) == 0)
295
PRINTF ("[%4lx %4lx] ", ADC_FS, status);
296
// printf ("start %lx\n", status);
298
ADC_IC |= ADC_IC_EOS | ADC_IC_PEN;
299
ADC_GC |= (1<<2); /* Start sampling */
301
timeStart = timer_read ();
304
if (ADC_IS & ADC_IS_EOS)
307
unsigned long l = ADC_GS;
308
if ((l & (0xf<<4)) != (status & (0xf<<4)))
309
printf ("state %lx\n", (l >> 4) & 0xf);
311
if (((status >> 4) & 0xf) == 0x4) /* End of sequence */
313
if (((status >> 4) & 0xf) == 0x1) /* Idle, which is really an error */
316
} while (timer_delta (timeStart, timer_read ()) < MS_TIMEOUT);
318
PRINTF ("-> [gs %lx %lx]\n", ADC_GS, ADC_FS);
319
// printf ("fifo %lx\n", ADC_FS);
321
for (i = 0; i < SAMPLES; ++i) {
322
unsigned long v = ADC_RR;
327
// printf ("%2d rr %5ld (%lx) - (%lx)\n", i, (v >> 6), (v & 0xf), ADC_FS);
328
PRINTF (" %4ld", (v >> 6));
333
printf ("x %d.%d (%d) y %d.%d (%d)\n",
342
PRINTF ("fifo %4lx ", ADC_FS);
343
PRINTF ("hw 0x%4lx lw 0x%4lx\n", ADC_HW, ADC_LW);
345
timeStart = timer_read ();
346
while (timer_delta (timeStart, timer_read ()) < MS_ADC_DELAY)
347
if (console->poll (0, 0))
349
// printf ("\n\n\n\n\n");
358
static __command struct command_d c_accel = {
360
.description = "test accelerometer",
364
static __service_7 struct service_d karma_accel_service = {