1
2 #include <unistd.h>
3 #include <sys/types.h>
4 #include <sys/mman.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <fcntl.h>
8 #include <assert.h>
9
10 #include "peekpoke.h"
11 #include "ep93xx_adc.h"
12
13 #define DATA_PAGE 0x12C00000
14 #define CALIB_LOC 2027 //location of calibration values
15 #define NUM_SAMPLES 5
16 #define NUM_CHANNELS 4
17
18 /* globals */
19 static unsigned long adc_page, syscon_page;
20 char *dr_page;
21 double el, az;
22
23 /*Calculate the adc value corresponding to 0V*/
24 //val1 is the ADC val corresponding to 0.833V
25 //val2 is the ADC val corresponding to 2.5V
calcZeroVal(int val1,int val2)26 int calcZeroVal(int val1, int val2)
27 {
28 val2 += 0x10000;
29 return (int)(val1 - (((val2 - val1) / (2.5 - 0.833)) * 0.833));
30 }
31
32
33 //return value of 1 indicates the board has no calibration values
34 //return value of 0 indicates the board has calibration values
read_calibration(int buf[NUM_CHANNELS][2])35 int read_calibration(int buf[NUM_CHANNELS][2])
36 {
37 int i, j, k = 0;
38 unsigned short cal[NUM_CHANNELS * 2];
39 // read 16 calibration bytes into buffer
40 FILE *f = fopen("/etc/ADC-calibration.dat", "r");
41
42 if (!f) { goto empty_calibration; }
43
44 printf("Non-virgin board detected, evaluating stored "
45 "calibration values\n");
46 printf("Stored Calibration values [");
47
48 if (fread(cal, NUM_CHANNELS * 4, 1, f) == 1)
49 {
50 fclose(f);
51
52 for (j = 0; j < 2; j++)
53 for (i = 0; i < NUM_CHANNELS; i++)
54 {
55 printf("0x%x", cal[k]);
56 buf[i][j] = cal[k];
57 k++;
58
59 if (k < NUM_CHANNELS * 2)
60 {
61 printf(", ");
62 }
63
64 }
65
66 printf("]\n");
67 return 1;
68 }
69
70 empty_calibration:
71
72 fclose(f);
73
74 printf("/etc/ADC-calibration.dat not found or it's not readable\n");
75
76 return 0;
77 }
78
write_calibration(int cal[NUM_CHANNELS][2])79 void write_calibration(int cal[NUM_CHANNELS][2])
80 {
81 unsigned short buf[16];
82 int i, j, k = 0;
83 FILE *f = fopen("/etc/ADC-calibration.dat", "w");
84
85 //Convert 32 bit vals to 16 bit vals
86 for (j = 0; j < 2; j++)
87 for (i = 0; i < NUM_CHANNELS; i++)
88 {
89 buf[k] = (unsigned short)cal[i][j];
90 k++;
91
92 }
93
94 if (!f) { goto unwrite_calibration; }
95
96 if (fwrite(buf, NUM_CHANNELS * 4, 1, f) == 1) { return; }
97
98 unwrite_calibration:
99
100 printf("Problem writing /etc/ADC-calibration.dat: %m\n");
101 }
102
erase_calibration()103 static void erase_calibration()
104 {
105 printf("Erasing calibration values...\n");
106 unlink("/etc/ADC-calibration.dat");
107 }
108
check_calibration(int cal[NUM_CHANNELS][2],int stored_cal[NUM_CHANNELS][2],int state)109 int check_calibration(int cal[NUM_CHANNELS][2],
110 int stored_cal[NUM_CHANNELS][2], int state)
111 {
112 double pcnt_diff;
113 int i, j, erase_cal = 0;
114 int failure = 0;
115
116 if (state == 0) //no calibration values
117 {
118 printf("Virgin board detected...\n");
119
120 for (j = 0; j < 2; j++)
121 {
122
123 for (i = 0; i < NUM_CHANNELS; i++)
124 {
125
126 if (j == 0)
127 pcnt_diff = (((double)abs(0xa000 -
128 cal[i][j])) / 0xa000) * 100;
129 else
130 pcnt_diff = (((double)abs(0x3300 -
131 cal[i][j])) / 0x3300) * 100;
132
133 if (pcnt_diff > 10)
134 {
135 printf("Calculated calibration "
136 "values out of range...\n");
137
138 exit(-1);
139 }
140
141 }
142 }
143
144 write_calibration(cal);
145
146 }
147 else //calibration values read
148 {
149
150 for (j = 0; j < 2; j++)
151 {
152 for (i = 0; i < NUM_CHANNELS; i++)
153 {
154
155 pcnt_diff = (((double)abs(stored_cal[i][j] -
156 cal[i][j])) / stored_cal[i][j])
157 * 100;
158
159 if (pcnt_diff > 0.25)
160 {
161 if (!failure)
162 {
163 printf("Calibration values out"
164 "of range\n");
165 failure = 1;
166 erase_cal = 1;
167 }
168
169 printf("\tChannel %d: %3.3f%%\n", i
170 , pcnt_diff);
171 }
172 }
173 }
174 }
175
176 if (erase_cal) { erase_calibration(); }
177
178 if (failure) { return 0; }
179
180 return 1;
181 }
182
setDR(char * x,int n,int val)183 void setDR(char *x, int n, int val)
184 {
185 if (n < 0 || n > 8)
186 {
187 return;
188 }
189
190 x[0] = (x[0] & ~(1 << n)) | (val ? (1 << n) : 0);
191 }
192
setD(char * x,int n,int val)193 void setD(char *x, int n, int val)
194 {
195 if (n < 0 || n > 8)
196 {
197 return;
198 }
199
200 x[2] = (x[2] & ~(1 << n)) | (val ? (1 << n) : 0);
201 }
202
get_volts(int val,int zero,int range)203 double get_volts(int val, int zero, int range)
204 {
205 if (val <= 0x7000)
206 {
207 val = val + 0x10000;
208 }
209
210 val = val - zero;
211
212 return ((double)val * 3.3) / range;
213 }
214
calc_calibration(int calibration[NUM_CHANNELS][2],int adc_result_1[NUM_CHANNELS][NUM_SAMPLES],int adc_result_2[NUM_CHANNELS][NUM_SAMPLES])215 void calc_calibration(int calibration[NUM_CHANNELS][2],
216 int adc_result_1[NUM_CHANNELS][NUM_SAMPLES],
217 int adc_result_2[NUM_CHANNELS][NUM_SAMPLES])
218 {
219 int i, j;
220
221 /* zero out our calibration values */
222 for (i = 0; i < NUM_CHANNELS; i++)
223 for (j = 0; j < 2; j++)
224 {
225 calibration[i][j] = 0;
226 }
227
228 //convert 0.833V vals to 0V vals
229 for (i = 0; i < NUM_CHANNELS; i++)
230 {
231 for (j = 0; j < NUM_SAMPLES; j++)
232 {
233 if (i % 2) //odd channels
234 adc_result_1[i][j] =
235 calcZeroVal(adc_result_1[i][j],
236 adc_result_1[0][j]);
237 else
238 adc_result_2[i][j] =
239 calcZeroVal(adc_result_2[i][j],
240 adc_result_2[1][j]);
241 }
242 }
243
244 //sum the readings
245 for (i = 0; i < NUM_CHANNELS; i++)
246 {
247 for (j = 0; j < NUM_SAMPLES; j++)
248 {
249 if (i % 2 == 0)
250 {
251 //0.833 volt values
252 calibration[i][0] = adc_result_2[i][j]
253 + calibration[i][0];
254 //2.5 volt values
255 calibration[i][1] = adc_result_1[i][j]
256 + calibration[i][1];
257 }
258 else
259 {
260 //0.833 volt values
261 calibration[i][0] = adc_result_1[i][j]
262 + calibration[i][0];
263 //2.5 volt values
264 calibration[i][1] = adc_result_2[i][j]
265 + calibration[i][1];
266 }
267 }
268 }
269
270 //printf("Calculated Calibration values [");
271 for (j = 0; j < 2; j++)
272 {
273 for (i = 0; i < NUM_CHANNELS; i++)
274 {
275 calibration[i][j] = (calibration[i][j] / NUM_SAMPLES);
276
277 //printf("0x%x", calibration[i][j]);
278
279 //if((i == NUM_CHANNELS-1) && (j == 1))
280 //printf("]\n");
281 //else
282 //printf(", ");
283 }
284 }
285 }
286
287 /************************************************************************
288 *DESCRIPTION: Read the EP93xx onboard ADC. Discard the first
289 *two samples then save the next NUM_SAMPLES.
290 ***********************************************************************/
read_7xxx_adc(int adc_result[NUM_CHANNELS][NUM_SAMPLES])291 static void read_7xxx_adc(int adc_result[NUM_CHANNELS][NUM_SAMPLES])
292 {
293 int i, j, cur_ch;
294
295 for (i = 0; i < NUM_CHANNELS; i++)
296 {
297 switch (i)
298 {
299 case 0:
300 cur_ch = ADC_CH0;
301 break;
302
303 case 1:
304 cur_ch = ADC_CH1;
305 break;
306
307 case 2:
308 cur_ch = ADC_CH2;
309 break;
310
311 case 3:
312 cur_ch = ADC_CH3;
313 break;
314
315 case 4:
316 cur_ch = ADC_CH4;
317 break;
318
319 }
320
321 //discard first two samples
322 read_channel(adc_page, cur_ch);
323 read_channel(adc_page, cur_ch);
324
325 //read more samples
326 for (j = 0; j < NUM_SAMPLES; j++)
327 {
328 hl_usleep(10000);
329 adc_result[i][j] = read_channel(adc_page, cur_ch);
330 }
331 }
332 }
333
test_ADC(int calibration[NUM_CHANNELS][2])334 int test_ADC(int calibration[NUM_CHANNELS][2])
335 {
336 int adc_result_1[NUM_CHANNELS][NUM_SAMPLES];
337 int adc_result_2[NUM_CHANNELS][NUM_SAMPLES];
338 int i, j, return_val;
339 int failure = 0;
340 //double voltage,el,az;
341 double voltage;
342
343 setD(dr_page, 0, 1); //ADC1 = ADC3 = 0.833V
344 setD(dr_page, 2, 1); //ADC0 = ADC2 = 2.5V
345 read_7xxx_adc(adc_result_1);
346
347 setD(dr_page, 0, 0); //ADC1 = ADC3 = 2.5V
348 setD(dr_page, 2, 1); //ADC0 = ADC2 = 0.833V
349 read_7xxx_adc(adc_result_2);
350
351
352 el = get_volts(adc_result_1[0][0], 0x9E58, 0xC350);
353 az = get_volts(adc_result_1[1][0], 0x9E58, 0xC350);
354
355 el = (el / 3.3) * 180;
356 az = (az / 3.3) * 360;
357 //printf("\t El.: %3.1f Az.: %3.1f \n", el, az);
358
359 //verify results are within range
360 for (i = 0; i < NUM_CHANNELS; i++)
361 {
362 for (j = 0; j < NUM_SAMPLES; j++)
363 {
364 //use the datasheet values
365 voltage = get_volts(adc_result_1[i][j], 0x9E58, 0xC350);
366
367 //printf("\tChannel %d: %3.1f \n", i, voltage);
368 //even channels 2.5V(+-150mV)
369 if (i % 2 == 0 &&
370 (voltage < 2.35 || voltage > 2.65))
371 {
372 if (!failure)
373 {
374 failure = 1;
375 //printf("EP93XX ADC out of range\n");
376 }
377
378 //printf("\tChannel %d: %3.3fV"
379 //"(expected 2.5V +- 150mV)\n", i, voltage);
380 //odd channels 0.833(+-50mV)
381 }
382 else if (i % 2 == 1 &&
383 (voltage < 0.333 || voltage > 1.333))
384 {
385 if (!failure)
386 {
387 failure = 1;
388 //printf( "EP93xx ADC out of range\n");
389 }
390
391 //printf("\tChannel %d: %3.3fV"
392 // "(expected 0.833V +- 50mV)\n", i, voltage);
393 }
394
395
396 //use the datasheet values
397 voltage = get_volts(adc_result_2[i][j], 0x9E58, 0xC350);
398
399 //odd channels 2.5V(+-150mV)
400 if (i % 2 == 1 &&
401 (voltage < 2.35 || voltage > 2.65))
402 {
403 if (!failure)
404 {
405 failure = 1;
406 //printf("EP93XX ADC out of range\n");
407 }
408
409 //printf("\tChannel %d: %3.3fV"
410 //"(expected 2.5V +- 150mV)\n", i, voltage);
411 //even channels 0.833(+-50mV)
412 }
413 else if (i % 2 == 0 &&
414 (voltage < 0.333 || voltage > 1.333))
415 {
416 if (!failure)
417 {
418 failure = 1;
419 //printf( "EP93xx ADC out of range\n");
420 }
421
422 ///printf("\tChannel %d: %3.3fV" "(expected 0.833V +- 50mV)\n", i, voltage);
423 }
424 }
425 }
426
427
428 calc_calibration(calibration, adc_result_1, adc_result_2);
429
430 if (failure)
431 {
432 return_val = 0;
433 }
434 else { return_val = 1; }
435
436 return return_val;
437 }
438
439
440
441
main(void)442 int main(void)
443 {
444 int calibration[NUM_CHANNELS][2];
445 int ret_val;
446 int devmem = open("/dev/mem", O_RDWR | O_SYNC);
447 assert(devmem != -1);
448
449 dr_page = mmap(0, getpagesize(), PROT_READ | PROT_WRITE,
450 MAP_SHARED, devmem, DATA_PAGE);
451 assert(&dr_page != MAP_FAILED);
452 adc_page = (unsigned long)mmap(0, getpagesize(), PROT_READ | PROT_WRITE,
453 MAP_SHARED, devmem, ADC_PAGE);
454 assert(&adc_page != MAP_FAILED);
455 syscon_page = (unsigned long)mmap(0, getpagesize(), PROT_READ | PROT_WRITE
456 , MAP_SHARED, devmem, SYSCON_PAGE);
457 assert(&syscon_page != MAP_FAILED);
458
459 init_ADC(adc_page, syscon_page);
460 setDR(dr_page, 0, 1);
461 setDR(dr_page, 1, 0);
462 setDR(dr_page, 2, 1);
463 setDR(dr_page, 3, 0);
464
465
466 if (test_ADC(calibration))
467 {
468 int state;
469 int stored_calibration[NUM_CHANNELS][2];
470 printf("ADC tested ok(data sheet values)\n");
471 state = read_calibration(stored_calibration);
472
473 if (check_calibration(calibration, stored_calibration, state))
474 {
475 ret_val = 0;
476 }
477 else
478 {
479 ret_val = 1;
480 }
481
482 }
483 else
484 {
485 ret_val = 1;
486 }
487
488 printf("\t El.: %3.1f Az.: %3.1f \n", el, az);
489 close(devmem);
490 return ret_val;
491 }
492