]> rtime.felk.cvut.cz Git - sysless.git/blob - board/arm/lpceurobot/libs/eb_ebb/adc_filtr.c
h8eurobot: Enable PXMC
[sysless.git] / board / arm / lpceurobot / libs / eb_ebb / adc_filtr.c
1 #include <lpc21xx.h>                          // LPC21XX Peripheral Registers
2 #include <types.h> 
3 #include "adc_filtr.h"
4 #include <stdlib.h>
5 #include <string.h>
6 #include <deb_led.h>
7
8
9
10 #define ADCCH0 22       ///< ADC0 value for PINSEL
11 #define ADCCH1 24       ///< ADC1 value for PINSEL
12 #define ADCCH2 26       ///< ADC2 value for PINSEL
13 #define ADCCH3 28       ///< ADC3 value for PINSEL
14
15
16 /**
17  *  Comparsion function  for quicksort
18  *
19  * @param *a    first number for comparion
20  * @param *b    second number for comparion
21  *
22  * @return      1 if b is higher than a
23  */ 
24 int compare( const void *a, const void *b)
25 {
26         return (*((unsigned int*)a) < *(((unsigned int*)b)));
27 }
28
29
30 /**
31  *  Median filter for ADC. If new data is available the median is recalculated. 
32  *  This function may be called from main function, it should take long time
33  *  to calculate the median for all ADC value.
34  * 
35  * @param chan  bit oriented (0~3) value, defines which ADC channels have new data
36  */ 
37 void adc_filter(unsigned char chan)
38 {
39         if(adc_update_adc & 1) 
40         {
41                 memcpy(&adc_filtr_0_m, adc_filtr_0, sizeof(uint16_t) * ADC_FILTR_SIZE );
42                 qsort(adc_filtr_0_m , ADC_FILTR_SIZE , sizeof(uint16_t), compare);
43                 adc_val[0] = adc_filtr_0_m[(ADC_FILTR_SIZE/2 + 1)];
44                 adc_update_adc &= ~ 1;
45
46         }
47         if(adc_update_adc & 2) 
48         {
49                 memcpy(&adc_filtr_1_m, adc_filtr_1, sizeof(uint16_t) * ADC_FILTR_SIZE );
50                 qsort(adc_filtr_1_m , ADC_FILTR_SIZE , sizeof(uint16_t), compare);
51                 adc_val[1] = adc_filtr_1_m[(ADC_FILTR_SIZE/2 + 1)];
52                 adc_update_adc &= ~ 2;
53         }
54         if(adc_update_adc & 4) 
55         {       
56                 memcpy(&adc_filtr_2_m, adc_filtr_2, sizeof(uint16_t) * ADC_FILTR_SIZE );
57                 qsort(adc_filtr_2_m , ADC_FILTR_SIZE , sizeof(uint16_t), compare);
58                 adc_val[2] = adc_filtr_2_m[(ADC_FILTR_SIZE/2 + 1)];
59                 adc_update_adc &= ~ 4;
60         }
61         if(adc_update_adc & 8) 
62         {
63                 memcpy(&adc_filtr_3_m, adc_filtr_3, sizeof(uint16_t) * ADC_FILTR_SIZE );
64                 qsort(adc_filtr_3_m , ADC_FILTR_SIZE , sizeof(uint16_t), compare);
65                 adc_val[3] = adc_filtr_3_m[(ADC_FILTR_SIZE/2 + 1)];
66                 adc_update_adc &= ~ 8;
67         }
68 }
69
70
71
72
73 /**
74  *  ADC ISR routine. This routine reads selected ADC value and
75  *  multiplies it by #ADC_MUL and adds #ADC_OFFSET to calculate the
76  *  volage (3.25mV/div).  After this reading the next ADC channel is
77  *  set up for measuring.
78  */ 
79 void adc_isr_filtr(void) __attribute__ ((interrupt));
80 void adc_isr_filtr(void) 
81 {
82         unsigned char chan =0;
83         unsigned int val =0;
84
85
86         chan = (char) ((ADDR>>24) & 0x07);
87         val = (((((ADDR >> 6) & 0x3FF) * ADC_MUL + ADC_OFFSET) + adc_val[chan]) >> 1) ;
88
89
90         if(chan == 0) 
91         {
92                 adc_filtr_0[adc_filtr_p] =  val;
93                 adc_update_adc |= 1;
94         }
95         else if(chan == 1) 
96         {
97                 adc_filtr_1[adc_filtr_p] =  val;
98                 adc_update_adc |= 2;
99         }
100         else if(chan == 2) 
101         {       
102                 adc_filtr_2[adc_filtr_p] =  val;
103                 adc_update_adc |= 4;
104         }
105         else if(chan == 3) 
106         {
107                 adc_filtr_3[adc_filtr_p] =  val;
108                 adc_update_adc |= 8;
109                 
110                 if(adc_filtr_p == (ADC_FILTR_SIZE -1 )) adc_filtr_p = 0;
111                 else ++adc_filtr_p;
112         }
113
114
115         ADCR &= ~(ADC_CR_START_OFF_m);
116
117
118         switch(chan)
119         {
120                 case 0:
121                         ADCR = ((ADC_CR_ADC1_m) | (ADC_CR_CLKS_11_m) | (ADC_CR_PDN_ON_m) | (ADC_CR_START_NOW_m) | (ADC_VPB_DIV*ADC_CR_CLK_DIV_1_m));
122                         break;
123
124                 case 1:
125                         ADCR = ((ADC_CR_ADC2_m) | (ADC_CR_CLKS_11_m) | (ADC_CR_PDN_ON_m) | (ADC_CR_START_NOW_m) | (ADC_VPB_DIV*ADC_CR_CLK_DIV_1_m));
126                         break;
127                         
128                 case 2:
129                         ADCR = ((ADC_CR_ADC3_m) | (ADC_CR_CLKS_11_m) | (ADC_CR_PDN_ON_m) | (ADC_CR_START_NOW_m) | (ADC_VPB_DIV*ADC_CR_CLK_DIV_1_m));
130                         break;
131                         
132                 case 3:
133                         ADCR = ((ADC_CR_ADC0_m) | (ADC_CR_CLKS_11_m) | (ADC_CR_PDN_ON_m) | (ADC_CR_START_NOW_m) | (ADC_VPB_DIV*ADC_CR_CLK_DIV_1_m));
134                         break;                                                                                                                   
135         }
136         
137          VICVectAddr = 0;
138
139 }
140
141 /**
142  *  Inicializes ADC service for all ADC (4) channels and installs ISR routine to VIC.
143  *   Automaticly starts the conversion of first channel on given conversion frequency.
144  */ 
145 void init_adc_filter(unsigned rx_isr_vect)
146 {
147         
148         PINSEL1 |= ((PINSEL_1 << ADCCH0) | (PINSEL_1 << ADCCH1) | (PINSEL_1 << ADCCH2) | (PINSEL_1 << ADCCH3));         
149
150         int x;
151
152         for (x = 0; x < 21; ++x)
153         {
154                 adc_filtr_0[x] = 0;
155                 adc_filtr_1[x] = 0;
156                 adc_filtr_2[x] = 0;
157                 adc_filtr_3[x] = 0;
158         }
159
160         adc_filtr_p = 0;
161         adc_update_adc = 0;
162
163         ((uint32_t*)&VICVectCntl0)[rx_isr_vect] = 0x32;
164         ((uint32_t*)&VICVectAddr0)[rx_isr_vect] = (unsigned) adc_isr_filtr;
165         VICIntEnable = 0x40000;
166
167         ADCR = ((ADC_CR_ADC0_m) | (ADC_CR_CLKS_11_m) | (ADC_CR_PDN_ON_m) | (ADC_CR_START_NOW_m) | (ADC_VPB_DIV*ADC_CR_CLK_DIV_1_m));
168 }