It is a library for controlling Wallbot
Embed:
(wiki syntax)
Show/hide line numbers
HighSpeedAnalogIn.cpp
00001 00002 #include "HighSpeedAnalogIn.h" 00003 00004 HighSpeedAnalogIn *HighSpeedAnalogIn::instance; 00005 int HighSpeedAnalogIn::refcnt = 0; 00006 00007 HighSpeedAnalogIn::HighSpeedAnalogIn(PinName pin0, PinName pin1, PinName pin2, PinName pin3, PinName pin4, PinName pin5) { 00008 00009 refcnt++; 00010 if (refcnt > 1) { 00011 error("Please do not use over an object."); 00012 } 00013 00014 static const int sample_rate = 200000; 00015 static const int cclk_div = 1; 00016 00017 int adc_clk_freq = CLKS_PER_SAMPLE * sample_rate; 00018 int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1; 00019 int n = (LPC_SC->PLL0CFG >> 16) + 1; 00020 int cclkdiv = LPC_SC->CCLKCFG + 1; 00021 int Fcco = (2 * m * XTAL_FREQ) / n; 00022 int cclk = Fcco / cclkdiv; 00023 00024 LPC_SC->PCONP |= (1 << 12); 00025 LPC_SC->PCLKSEL0 &= ~(0x3 << 24); 00026 switch (cclk_div) { 00027 case 1: 00028 LPC_SC->PCLKSEL0 |= 0x1 << 24; 00029 break; 00030 case 2: 00031 LPC_SC->PCLKSEL0 |= 0x2 << 24; 00032 break; 00033 case 4: 00034 LPC_SC->PCLKSEL0 |= 0x0 << 24; 00035 break; 00036 case 8: 00037 LPC_SC->PCLKSEL0 |= 0x3 << 24; 00038 break; 00039 default: 00040 fprintf(stderr, "Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n", cclk_div); 00041 fprintf(stderr, "Defaulting to 1.\n"); 00042 LPC_SC->PCLKSEL0 |= 0x1 << 24; 00043 break; 00044 } 00045 int pclk = cclk / cclk_div; 00046 int clock_div = pclk / adc_clk_freq; 00047 00048 if (clock_div > 0xFF) { 00049 fprintf(stderr, "Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n", clock_div); 00050 clock_div = 0xFF; 00051 } 00052 if (clock_div == 0) { 00053 fprintf(stderr, "Warning: Clock division is 0. Re-Setting to 1.\n"); 00054 clock_div = 1; 00055 } 00056 00057 int _adc_clk_freq = pclk / clock_div; 00058 if (_adc_clk_freq > MAX_ADC_CLOCK) { 00059 fprintf(stderr, "Warning: Actual ADC sample rate of %u which is above %u limit\n", _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE); 00060 int max_div = 1; 00061 while ((pclk / max_div) > MAX_ADC_CLOCK) { 00062 max_div++; 00063 } 00064 fprintf(stderr, "Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE); 00065 } 00066 00067 LPC_ADC->ADCR = ((clock_div - 1) << 8) | (1 << 21); 00068 LPC_ADC->ADCR &= ~0xFF; 00069 00070 for (int i = 0; i < 8; i++) { 00071 _adc_data[i] = 0; 00072 } 00073 00074 // Attach IRQ 00075 instance = this; 00076 NVIC_SetVector(ADC_IRQn, (uint32_t)&static_adcisr); 00077 00078 // Disable global interrupt 00079 LPC_ADC->ADINTEN &= ~0x100; 00080 00081 // Clock frequency. 00082 printf("Clock frequency:%d\n", _adc_clk_freq); 00083 00084 // Actual sampling rate. 00085 printf("Actual sampling rate:%d\n", _adc_clk_freq / CLKS_PER_SAMPLE); 00086 00087 int tmp = LPC_ADC->ADCR & ~(0x0F << 24); 00088 tmp |= ((0x0 & 7) << 24) | ((0x0 & 1) << 27); 00089 LPC_ADC->ADCR = tmp; 00090 LPC_ADC->ADCR |= (1 << 16); 00091 00092 if (pin0 != NC) setup(pin0, 1); 00093 if (pin1 != NC) setup(pin1, 1); 00094 if (pin2 != NC) setup(pin2, 1); 00095 if (pin3 != NC) setup(pin3, 1); 00096 if (pin4 != NC) setup(pin4, 1); 00097 if (pin5 != NC) setup(pin5, 1); 00098 00099 interrupt_state(pin0, 1); 00100 } 00101 00102 HighSpeedAnalogIn::~HighSpeedAnalogIn() { 00103 } 00104 00105 void HighSpeedAnalogIn::static_adcisr(void) { 00106 instance->adcisr(); 00107 } 00108 00109 void HighSpeedAnalogIn::adcisr(void) { 00110 uint32_t stat = LPC_ADC->ADSTAT; 00111 // Scan channels for over-run or done and update array 00112 if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0; 00113 if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1; 00114 if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2; 00115 if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3; 00116 if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4; 00117 if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5; 00118 if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6; 00119 if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7; 00120 } 00121 00122 int HighSpeedAnalogIn::get_channel(PinName pin) { 00123 int ch; 00124 switch (pin) { 00125 case p15:// =p0.23 of LPC1768 00126 ch = 0; 00127 break; 00128 case p16:// =p0.24 of LPC1768 00129 ch = 1; 00130 break; 00131 case p17:// =p0.25 of LPC1768 00132 ch = 2; 00133 break; 00134 case p18:// =p0.26 of LPC1768 00135 ch = 3; 00136 break; 00137 case p19:// =p1.30 of LPC1768 00138 ch = 4; 00139 break; 00140 case p20:// =p1.31 of LPC1768 00141 ch = 5; 00142 break; 00143 default: 00144 ch = 0; 00145 break; 00146 } 00147 return ch; 00148 } 00149 00150 uint32_t HighSpeedAnalogIn::get_data(PinName pin) { 00151 // If in burst mode and at least one interrupt enabled then 00152 // take all values from _adc_data 00153 if (LPC_ADC->ADINTEN & 0x3F) { 00154 return (_adc_data[get_channel(pin)]); 00155 } else { 00156 // Return current register value or last value from interrupt 00157 switch (pin) { 00158 case p15:// =p0.23 of LPC1768 00159 return ((LPC_ADC->ADINTEN & 0x01) ? _adc_data[0] : LPC_ADC->ADDR0); 00160 case p16:// =p0.24 of LPC1768 00161 return ((LPC_ADC->ADINTEN & 0x02) ? _adc_data[1] : LPC_ADC->ADDR1); 00162 case p17:// =p0.25 of LPC1768 00163 return ((LPC_ADC->ADINTEN & 0x04) ? _adc_data[2] : LPC_ADC->ADDR2); 00164 case p18:// =p0.26 of LPC1768: 00165 return ((LPC_ADC->ADINTEN & 0x08) ? _adc_data[3] : LPC_ADC->ADDR3); 00166 case p19:// =p1.30 of LPC1768 00167 return ((LPC_ADC->ADINTEN & 0x10) ? _adc_data[4] : LPC_ADC->ADDR4); 00168 case p20:// =p1.31 of LPC1768 00169 return ((LPC_ADC->ADINTEN & 0x20) ? _adc_data[5] : LPC_ADC->ADDR5); 00170 default: 00171 return 0; 00172 } 00173 } 00174 } 00175 00176 // Enable or disable an HighSpeedAnalogIn pin 00177 void HighSpeedAnalogIn::setup(PinName pin, int state) { 00178 int ch = get_channel(pin); 00179 if ((state & 1) == 1) { 00180 switch (pin) { 00181 case p15:// =p0.23 of LPC1768 00182 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); 00183 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14; 00184 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); 00185 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14; 00186 break; 00187 case p16:// =p0.24 of LPC1768 00188 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); 00189 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16; 00190 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); 00191 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16; 00192 break; 00193 case p17:// =p0.25 of LPC1768 00194 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); 00195 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18; 00196 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); 00197 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18; 00198 break; 00199 case p18:// =p0.26 of LPC1768: 00200 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); 00201 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20; 00202 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); 00203 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20; 00204 break; 00205 case p19:// =p1.30 of LPC1768 00206 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); 00207 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28; 00208 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); 00209 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28; 00210 break; 00211 case p20:// =p1.31 of LPC1768 00212 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); 00213 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30; 00214 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); 00215 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30; 00216 break; 00217 default: 00218 error("Invalid pin."); 00219 break; 00220 } 00221 // Select channel 00222 LPC_ADC->ADCR |= (1 << ch); 00223 } else { 00224 switch (pin) { 00225 case p15://=p0.23 of LPC1768 00226 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14); 00227 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14); 00228 break; 00229 case p16://=p0.24 of LPC1768 00230 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16); 00231 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16); 00232 break; 00233 case p17://=p0.25 of LPC1768 00234 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18); 00235 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18); 00236 break; 00237 case p18://=p0.26 of LPC1768: 00238 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20); 00239 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20); 00240 break; 00241 case p19://=p1.30 of LPC1768 00242 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28); 00243 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28); 00244 break; 00245 case p20://=p1.31 of LPC1768 00246 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30); 00247 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30); 00248 break; 00249 default: 00250 error("Invalid pin."); 00251 break; 00252 } 00253 LPC_ADC->ADCR &= ~(1 << ch); 00254 } 00255 } 00256 00257 void HighSpeedAnalogIn::interrupt_state(PinName pin, int state) { 00258 int ch = get_channel(pin); 00259 if (state == 1) { 00260 LPC_ADC->ADINTEN &= ~0x100; 00261 LPC_ADC->ADINTEN |= 1 << ch; 00262 /* Enable the HighSpeedAnalogIn Interrupt */ 00263 NVIC_EnableIRQ(ADC_IRQn); 00264 } else { 00265 LPC_ADC->ADINTEN &= ~(1 << ch); 00266 //Disable interrrupt if no active pins left 00267 if ((LPC_ADC->ADINTEN & 0xFF) == 0) 00268 NVIC_DisableIRQ(ADC_IRQn); 00269 } 00270 } 00271 00272 float HighSpeedAnalogIn::read(PinName pin) { 00273 /* 00274 * Reset DONE and OVERRUN. 00275 * 00276 * bit 31 : DONE 00277 * bit 30 : OVERRUN 00278 */ 00279 _adc_data[get_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30)); 00280 return (float)((get_data(pin) >> 4) & 0xFFF) / (float)0xFFF; 00281 } 00282 00283 unsigned short HighSpeedAnalogIn::read_u16(PinName pin) { 00284 /* 00285 * Reset DONE and OVERRUN. 00286 * 00287 * bit 31 : DONE 00288 * bit 30 : OVERRUN 00289 */ 00290 _adc_data[get_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30)); 00291 return ((get_data(pin) >> 4) & 0xFFF); 00292 }
Generated on Sun Jul 17 2022 09:53:56 by 1.7.2