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