Programming of the DDS-60 (AD9851) frequency synthesizer from AmQRP http://midnightdesignsolutions.com/dds60/index.html I had to use long, floating math in order to get accurate frequency output.

Dependencies:   TextLCD mbed ChaNFS

Committer:
loopsva
Date:
Wed Apr 04 18:14:54 2012 +0000
Revision:
0:1ed24aaf786d
050511

Who changed what in which revision?

UserRevisionLine numberNew contents of line
loopsva 0:1ed24aaf786d 1 /* mbed Library - ADC
loopsva 0:1ed24aaf786d 2 * Copyright (c) 2010, sblandford
loopsva 0:1ed24aaf786d 3 * released under MIT license http://mbed.org/licence/mit
loopsva 0:1ed24aaf786d 4 */
loopsva 0:1ed24aaf786d 5 #include "mbed.h"
loopsva 0:1ed24aaf786d 6 #include "adc.h"
loopsva 0:1ed24aaf786d 7
loopsva 0:1ed24aaf786d 8
loopsva 0:1ed24aaf786d 9 ADC *ADC::instance;
loopsva 0:1ed24aaf786d 10
loopsva 0:1ed24aaf786d 11 ADC::ADC(int sample_rate, int cclk_div)
loopsva 0:1ed24aaf786d 12 {
loopsva 0:1ed24aaf786d 13
loopsva 0:1ed24aaf786d 14 int i, adc_clk_freq, pclk, clock_div, max_div=1;
loopsva 0:1ed24aaf786d 15
loopsva 0:1ed24aaf786d 16 //Work out CCLK
loopsva 0:1ed24aaf786d 17 adc_clk_freq=CLKS_PER_SAMPLE*sample_rate;
loopsva 0:1ed24aaf786d 18 int m = (LPC_SC->PLL0CFG & 0xFFFF) + 1;
loopsva 0:1ed24aaf786d 19 int n = (LPC_SC->PLL0CFG >> 16) + 1;
loopsva 0:1ed24aaf786d 20 int cclkdiv = LPC_SC->CCLKCFG + 1;
loopsva 0:1ed24aaf786d 21 int Fcco = (2 * m * XTAL_FREQ) / n;
loopsva 0:1ed24aaf786d 22 int cclk = Fcco / cclkdiv;
loopsva 0:1ed24aaf786d 23
loopsva 0:1ed24aaf786d 24 //Power up the ADC
loopsva 0:1ed24aaf786d 25 LPC_SC->PCONP |= (1 << 12);
loopsva 0:1ed24aaf786d 26 //Set clock at cclk / 1.
loopsva 0:1ed24aaf786d 27 LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
loopsva 0:1ed24aaf786d 28 switch (cclk_div) {
loopsva 0:1ed24aaf786d 29 case 1:
loopsva 0:1ed24aaf786d 30 LPC_SC->PCLKSEL0 |= 0x1 << 24;
loopsva 0:1ed24aaf786d 31 break;
loopsva 0:1ed24aaf786d 32 case 2:
loopsva 0:1ed24aaf786d 33 LPC_SC->PCLKSEL0 |= 0x2 << 24;
loopsva 0:1ed24aaf786d 34 break;
loopsva 0:1ed24aaf786d 35 case 4:
loopsva 0:1ed24aaf786d 36 LPC_SC->PCLKSEL0 |= 0x0 << 24;
loopsva 0:1ed24aaf786d 37 break;
loopsva 0:1ed24aaf786d 38 case 8:
loopsva 0:1ed24aaf786d 39 LPC_SC->PCLKSEL0 |= 0x3 << 24;
loopsva 0:1ed24aaf786d 40 break;
loopsva 0:1ed24aaf786d 41 default:
loopsva 0:1ed24aaf786d 42 fprintf(stderr, "Warning: ADC CCLK clock divider must be 1, 2, 4 or 8. %u supplied.\n",
loopsva 0:1ed24aaf786d 43 cclk_div);
loopsva 0:1ed24aaf786d 44 fprintf(stderr, "Defaulting to 1.\n");
loopsva 0:1ed24aaf786d 45 LPC_SC->PCLKSEL0 |= 0x1 << 24;
loopsva 0:1ed24aaf786d 46 break;
loopsva 0:1ed24aaf786d 47 }
loopsva 0:1ed24aaf786d 48 pclk = cclk / cclk_div;
loopsva 0:1ed24aaf786d 49 clock_div=pclk / adc_clk_freq;
loopsva 0:1ed24aaf786d 50
loopsva 0:1ed24aaf786d 51 if (clock_div > 0xFF) {
loopsva 0:1ed24aaf786d 52 fprintf(stderr, "Warning: Clock division is %u which is above 255 limit. Re-Setting at limit.\n",
loopsva 0:1ed24aaf786d 53 clock_div);
loopsva 0:1ed24aaf786d 54 clock_div=0xFF;
loopsva 0:1ed24aaf786d 55 }
loopsva 0:1ed24aaf786d 56 if (clock_div == 0) {
loopsva 0:1ed24aaf786d 57 fprintf(stderr, "Warning: Clock division is 0. Re-Setting to 1.\n");
loopsva 0:1ed24aaf786d 58 clock_div=1;
loopsva 0:1ed24aaf786d 59 }
loopsva 0:1ed24aaf786d 60
loopsva 0:1ed24aaf786d 61 _adc_clk_freq=pclk / clock_div;
loopsva 0:1ed24aaf786d 62 if (_adc_clk_freq > MAX_ADC_CLOCK) {
loopsva 0:1ed24aaf786d 63 fprintf(stderr, "Warning: Actual ADC sample rate of %u which is above %u limit\n",
loopsva 0:1ed24aaf786d 64 _adc_clk_freq / CLKS_PER_SAMPLE, MAX_ADC_CLOCK / CLKS_PER_SAMPLE);
loopsva 0:1ed24aaf786d 65 while ((pclk / max_div) > MAX_ADC_CLOCK) max_div++;
loopsva 0:1ed24aaf786d 66 fprintf(stderr, "Maximum recommended sample rate is %u\n", (pclk / max_div) / CLKS_PER_SAMPLE);
loopsva 0:1ed24aaf786d 67 }
loopsva 0:1ed24aaf786d 68
loopsva 0:1ed24aaf786d 69 LPC_ADC->ADCR =
loopsva 0:1ed24aaf786d 70 ((clock_div - 1 ) << 8 ) | //Clkdiv
loopsva 0:1ed24aaf786d 71 ( 1 << 21 ); //A/D operational
loopsva 0:1ed24aaf786d 72
loopsva 0:1ed24aaf786d 73 //Default no channels enabled
loopsva 0:1ed24aaf786d 74 LPC_ADC->ADCR &= ~0xFF;
loopsva 0:1ed24aaf786d 75 //Default NULL global custom isr
loopsva 0:1ed24aaf786d 76 _adc_g_isr = NULL;
loopsva 0:1ed24aaf786d 77 //Initialize arrays
loopsva 0:1ed24aaf786d 78 for (i=7; i>=0; i--) {
loopsva 0:1ed24aaf786d 79 _adc_data[i] = 0;
loopsva 0:1ed24aaf786d 80 _adc_isr[i] = NULL;
loopsva 0:1ed24aaf786d 81 }
loopsva 0:1ed24aaf786d 82
loopsva 0:1ed24aaf786d 83
loopsva 0:1ed24aaf786d 84 //* Attach IRQ
loopsva 0:1ed24aaf786d 85 instance = this;
loopsva 0:1ed24aaf786d 86 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
loopsva 0:1ed24aaf786d 87
loopsva 0:1ed24aaf786d 88 //Disable global interrupt
loopsva 0:1ed24aaf786d 89 LPC_ADC->ADINTEN &= ~0x100;
loopsva 0:1ed24aaf786d 90
loopsva 0:1ed24aaf786d 91 };
loopsva 0:1ed24aaf786d 92
loopsva 0:1ed24aaf786d 93 void ADC::_adcisr(void)
loopsva 0:1ed24aaf786d 94 {
loopsva 0:1ed24aaf786d 95 instance->adcisr();
loopsva 0:1ed24aaf786d 96 }
loopsva 0:1ed24aaf786d 97
loopsva 0:1ed24aaf786d 98
loopsva 0:1ed24aaf786d 99 void ADC::adcisr(void)
loopsva 0:1ed24aaf786d 100 {
loopsva 0:1ed24aaf786d 101 uint32_t stat;
loopsva 0:1ed24aaf786d 102 int chan;
loopsva 0:1ed24aaf786d 103
loopsva 0:1ed24aaf786d 104 // Read status
loopsva 0:1ed24aaf786d 105 stat = LPC_ADC->ADSTAT;
loopsva 0:1ed24aaf786d 106 //Scan channels for over-run or done and update array
loopsva 0:1ed24aaf786d 107 if (stat & 0x0101) _adc_data[0] = LPC_ADC->ADDR0;
loopsva 0:1ed24aaf786d 108 if (stat & 0x0202) _adc_data[1] = LPC_ADC->ADDR1;
loopsva 0:1ed24aaf786d 109 if (stat & 0x0404) _adc_data[2] = LPC_ADC->ADDR2;
loopsva 0:1ed24aaf786d 110 if (stat & 0x0808) _adc_data[3] = LPC_ADC->ADDR3;
loopsva 0:1ed24aaf786d 111 if (stat & 0x1010) _adc_data[4] = LPC_ADC->ADDR4;
loopsva 0:1ed24aaf786d 112 if (stat & 0x2020) _adc_data[5] = LPC_ADC->ADDR5;
loopsva 0:1ed24aaf786d 113 if (stat & 0x4040) _adc_data[6] = LPC_ADC->ADDR6;
loopsva 0:1ed24aaf786d 114 if (stat & 0x8080) _adc_data[7] = LPC_ADC->ADDR7;
loopsva 0:1ed24aaf786d 115
loopsva 0:1ed24aaf786d 116 // Channel that triggered interrupt
loopsva 0:1ed24aaf786d 117 chan = (LPC_ADC->ADGDR >> 24) & 0x07;
loopsva 0:1ed24aaf786d 118 //User defined interrupt handlers
loopsva 0:1ed24aaf786d 119 if (_adc_isr[chan] != NULL)
loopsva 0:1ed24aaf786d 120 _adc_isr[chan](_adc_data[chan]);
loopsva 0:1ed24aaf786d 121 if (_adc_g_isr != NULL)
loopsva 0:1ed24aaf786d 122 _adc_g_isr(chan, _adc_data[chan]);
loopsva 0:1ed24aaf786d 123 return;
loopsva 0:1ed24aaf786d 124 }
loopsva 0:1ed24aaf786d 125
loopsva 0:1ed24aaf786d 126 int ADC::_pin_to_channel(PinName pin) {
loopsva 0:1ed24aaf786d 127 int chan;
loopsva 0:1ed24aaf786d 128 switch (pin) {
loopsva 0:1ed24aaf786d 129 case p15://=p0.23 of LPC1768
loopsva 0:1ed24aaf786d 130 default:
loopsva 0:1ed24aaf786d 131 chan=0;
loopsva 0:1ed24aaf786d 132 break;
loopsva 0:1ed24aaf786d 133 case p16://=p0.24 of LPC1768
loopsva 0:1ed24aaf786d 134 chan=1;
loopsva 0:1ed24aaf786d 135 break;
loopsva 0:1ed24aaf786d 136 case p17://=p0.25 of LPC1768
loopsva 0:1ed24aaf786d 137 chan=2;
loopsva 0:1ed24aaf786d 138 break;
loopsva 0:1ed24aaf786d 139 case p18://=p0.26 of LPC1768
loopsva 0:1ed24aaf786d 140 chan=3;
loopsva 0:1ed24aaf786d 141 break;
loopsva 0:1ed24aaf786d 142 case p19://=p1.30 of LPC1768
loopsva 0:1ed24aaf786d 143 chan=4;
loopsva 0:1ed24aaf786d 144 break;
loopsva 0:1ed24aaf786d 145 case p20://=p1.31 of LPC1768
loopsva 0:1ed24aaf786d 146 chan=5;
loopsva 0:1ed24aaf786d 147 break;
loopsva 0:1ed24aaf786d 148 }
loopsva 0:1ed24aaf786d 149 return(chan);
loopsva 0:1ed24aaf786d 150 }
loopsva 0:1ed24aaf786d 151
loopsva 0:1ed24aaf786d 152 PinName ADC::channel_to_pin(int chan) {
loopsva 0:1ed24aaf786d 153 const PinName pin[8]={p15, p16, p17, p18, p19, p20, p15, p15};
loopsva 0:1ed24aaf786d 154
loopsva 0:1ed24aaf786d 155 if ((chan < 0) || (chan > 5))
loopsva 0:1ed24aaf786d 156 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
loopsva 0:1ed24aaf786d 157 return(pin[chan & 0x07]);
loopsva 0:1ed24aaf786d 158 }
loopsva 0:1ed24aaf786d 159
loopsva 0:1ed24aaf786d 160
loopsva 0:1ed24aaf786d 161 int ADC::channel_to_pin_number(int chan) {
loopsva 0:1ed24aaf786d 162 const int pin[8]={15, 16, 17, 18, 19, 20, 0, 0};
loopsva 0:1ed24aaf786d 163
loopsva 0:1ed24aaf786d 164 if ((chan < 0) || (chan > 5))
loopsva 0:1ed24aaf786d 165 fprintf(stderr, "ADC channel %u is outside range available to MBED pins.\n", chan);
loopsva 0:1ed24aaf786d 166 return(pin[chan & 0x07]);
loopsva 0:1ed24aaf786d 167 }
loopsva 0:1ed24aaf786d 168
loopsva 0:1ed24aaf786d 169
loopsva 0:1ed24aaf786d 170 uint32_t ADC::_data_of_pin(PinName pin) {
loopsva 0:1ed24aaf786d 171 //If in burst mode and at least one interrupt enabled then
loopsva 0:1ed24aaf786d 172 //take all values from _adc_data
loopsva 0:1ed24aaf786d 173 if (burst() && (LPC_ADC->ADINTEN & 0x3F)) {
loopsva 0:1ed24aaf786d 174 return(_adc_data[_pin_to_channel(pin)]);
loopsva 0:1ed24aaf786d 175 } else {
loopsva 0:1ed24aaf786d 176 //Return current register value or last value from interrupt
loopsva 0:1ed24aaf786d 177 switch (pin) {
loopsva 0:1ed24aaf786d 178 case p15://=p0.23 of LPC1768
loopsva 0:1ed24aaf786d 179 default:
loopsva 0:1ed24aaf786d 180 return(LPC_ADC->ADINTEN & 0x01?_adc_data[0]:LPC_ADC->ADDR0);
loopsva 0:1ed24aaf786d 181 case p16://=p0.24 of LPC1768
loopsva 0:1ed24aaf786d 182 return(LPC_ADC->ADINTEN & 0x02?_adc_data[1]:LPC_ADC->ADDR1);
loopsva 0:1ed24aaf786d 183 case p17://=p0.25 of LPC1768
loopsva 0:1ed24aaf786d 184 return(LPC_ADC->ADINTEN & 0x04?_adc_data[2]:LPC_ADC->ADDR2);
loopsva 0:1ed24aaf786d 185 case p18://=p0.26 of LPC1768:
loopsva 0:1ed24aaf786d 186 return(LPC_ADC->ADINTEN & 0x08?_adc_data[3]:LPC_ADC->ADDR3);
loopsva 0:1ed24aaf786d 187 case p19://=p1.30 of LPC1768
loopsva 0:1ed24aaf786d 188 return(LPC_ADC->ADINTEN & 0x10?_adc_data[4]:LPC_ADC->ADDR4);
loopsva 0:1ed24aaf786d 189 case p20://=p1.31 of LPC1768
loopsva 0:1ed24aaf786d 190 return(LPC_ADC->ADINTEN & 0x20?_adc_data[5]:LPC_ADC->ADDR5);
loopsva 0:1ed24aaf786d 191 }
loopsva 0:1ed24aaf786d 192 }
loopsva 0:1ed24aaf786d 193 }
loopsva 0:1ed24aaf786d 194
loopsva 0:1ed24aaf786d 195 //Enable or disable an ADC pin
loopsva 0:1ed24aaf786d 196 void ADC::setup(PinName pin, int state) {
loopsva 0:1ed24aaf786d 197 int chan;
loopsva 0:1ed24aaf786d 198 chan=_pin_to_channel(pin);
loopsva 0:1ed24aaf786d 199 if ((state & 1) == 1) {
loopsva 0:1ed24aaf786d 200 switch(pin) {
loopsva 0:1ed24aaf786d 201 case p15://=p0.23 of LPC1768
loopsva 0:1ed24aaf786d 202 default:
loopsva 0:1ed24aaf786d 203 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
loopsva 0:1ed24aaf786d 204 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 14;
loopsva 0:1ed24aaf786d 205 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
loopsva 0:1ed24aaf786d 206 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 14;
loopsva 0:1ed24aaf786d 207 break;
loopsva 0:1ed24aaf786d 208 case p16://=p0.24 of LPC1768
loopsva 0:1ed24aaf786d 209 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
loopsva 0:1ed24aaf786d 210 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 16;
loopsva 0:1ed24aaf786d 211 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
loopsva 0:1ed24aaf786d 212 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 16;
loopsva 0:1ed24aaf786d 213 break;
loopsva 0:1ed24aaf786d 214 case p17://=p0.25 of LPC1768
loopsva 0:1ed24aaf786d 215 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
loopsva 0:1ed24aaf786d 216 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 18;
loopsva 0:1ed24aaf786d 217 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
loopsva 0:1ed24aaf786d 218 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 18;
loopsva 0:1ed24aaf786d 219 break;
loopsva 0:1ed24aaf786d 220 case p18://=p0.26 of LPC1768:
loopsva 0:1ed24aaf786d 221 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
loopsva 0:1ed24aaf786d 222 LPC_PINCON->PINSEL1 |= (unsigned int)0x1 << 20;
loopsva 0:1ed24aaf786d 223 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
loopsva 0:1ed24aaf786d 224 LPC_PINCON->PINMODE1 |= (unsigned int)0x2 << 20;
loopsva 0:1ed24aaf786d 225 break;
loopsva 0:1ed24aaf786d 226 case p19://=p1.30 of LPC1768
loopsva 0:1ed24aaf786d 227 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
loopsva 0:1ed24aaf786d 228 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 28;
loopsva 0:1ed24aaf786d 229 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
loopsva 0:1ed24aaf786d 230 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 28;
loopsva 0:1ed24aaf786d 231 break;
loopsva 0:1ed24aaf786d 232 case p20://=p1.31 of LPC1768
loopsva 0:1ed24aaf786d 233 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
loopsva 0:1ed24aaf786d 234 LPC_PINCON->PINSEL3 |= (unsigned int)0x3 << 30;
loopsva 0:1ed24aaf786d 235 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
loopsva 0:1ed24aaf786d 236 LPC_PINCON->PINMODE3 |= (unsigned int)0x2 << 30;
loopsva 0:1ed24aaf786d 237 break;
loopsva 0:1ed24aaf786d 238 }
loopsva 0:1ed24aaf786d 239 //Only one channel can be selected at a time if not in burst mode
loopsva 0:1ed24aaf786d 240 if (!burst()) LPC_ADC->ADCR &= ~0xFF;
loopsva 0:1ed24aaf786d 241 //Select channel
loopsva 0:1ed24aaf786d 242 LPC_ADC->ADCR |= (1 << chan);
loopsva 0:1ed24aaf786d 243 }
loopsva 0:1ed24aaf786d 244 else {
loopsva 0:1ed24aaf786d 245 switch(pin) {
loopsva 0:1ed24aaf786d 246 case p15://=p0.23 of LPC1768
loopsva 0:1ed24aaf786d 247 default:
loopsva 0:1ed24aaf786d 248 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 14);
loopsva 0:1ed24aaf786d 249 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 14);
loopsva 0:1ed24aaf786d 250 break;
loopsva 0:1ed24aaf786d 251 case p16://=p0.24 of LPC1768
loopsva 0:1ed24aaf786d 252 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 16);
loopsva 0:1ed24aaf786d 253 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 16);
loopsva 0:1ed24aaf786d 254 break;
loopsva 0:1ed24aaf786d 255 case p17://=p0.25 of LPC1768
loopsva 0:1ed24aaf786d 256 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 18);
loopsva 0:1ed24aaf786d 257 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 18);
loopsva 0:1ed24aaf786d 258 break;
loopsva 0:1ed24aaf786d 259 case p18://=p0.26 of LPC1768:
loopsva 0:1ed24aaf786d 260 LPC_PINCON->PINSEL1 &= ~((unsigned int)0x3 << 20);
loopsva 0:1ed24aaf786d 261 LPC_PINCON->PINMODE1 &= ~((unsigned int)0x3 << 20);
loopsva 0:1ed24aaf786d 262 break;
loopsva 0:1ed24aaf786d 263 case p19://=p1.30 of LPC1768
loopsva 0:1ed24aaf786d 264 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 28);
loopsva 0:1ed24aaf786d 265 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 28);
loopsva 0:1ed24aaf786d 266 break;
loopsva 0:1ed24aaf786d 267 case p20://=p1.31 of LPC1768
loopsva 0:1ed24aaf786d 268 LPC_PINCON->PINSEL3 &= ~((unsigned int)0x3 << 30);
loopsva 0:1ed24aaf786d 269 LPC_PINCON->PINMODE3 &= ~((unsigned int)0x3 << 30);
loopsva 0:1ed24aaf786d 270 break;
loopsva 0:1ed24aaf786d 271 }
loopsva 0:1ed24aaf786d 272 LPC_ADC->ADCR &= ~(1 << chan);
loopsva 0:1ed24aaf786d 273 }
loopsva 0:1ed24aaf786d 274 }
loopsva 0:1ed24aaf786d 275 //Return channel enabled/disabled state
loopsva 0:1ed24aaf786d 276 int ADC::setup(PinName pin) {
loopsva 0:1ed24aaf786d 277 int chan;
loopsva 0:1ed24aaf786d 278
loopsva 0:1ed24aaf786d 279 chan = _pin_to_channel(pin);
loopsva 0:1ed24aaf786d 280 return((LPC_ADC->ADCR & (1 << chan)) >> chan);
loopsva 0:1ed24aaf786d 281 }
loopsva 0:1ed24aaf786d 282
loopsva 0:1ed24aaf786d 283 //Select channel already setup
loopsva 0:1ed24aaf786d 284 void ADC::select(PinName pin) {
loopsva 0:1ed24aaf786d 285 int chan;
loopsva 0:1ed24aaf786d 286
loopsva 0:1ed24aaf786d 287 //Only one channel can be selected at a time if not in burst mode
loopsva 0:1ed24aaf786d 288 if (!burst()) LPC_ADC->ADCR &= ~0xFF;
loopsva 0:1ed24aaf786d 289 //Select channel
loopsva 0:1ed24aaf786d 290 chan = _pin_to_channel(pin);
loopsva 0:1ed24aaf786d 291 LPC_ADC->ADCR |= (1 << chan);
loopsva 0:1ed24aaf786d 292 }
loopsva 0:1ed24aaf786d 293
loopsva 0:1ed24aaf786d 294 //Enable or disable burst mode
loopsva 0:1ed24aaf786d 295 void ADC::burst(int state) {
loopsva 0:1ed24aaf786d 296 if ((state & 1) == 1) {
loopsva 0:1ed24aaf786d 297 if (startmode(0) != 0)
loopsva 0:1ed24aaf786d 298 fprintf(stderr, "Warning. startmode is %u. Must be 0 for burst mode.\n", startmode(0));
loopsva 0:1ed24aaf786d 299 LPC_ADC->ADCR |= (1 << 16);
loopsva 0:1ed24aaf786d 300 }
loopsva 0:1ed24aaf786d 301 else
loopsva 0:1ed24aaf786d 302 LPC_ADC->ADCR &= ~(1 << 16);
loopsva 0:1ed24aaf786d 303 }
loopsva 0:1ed24aaf786d 304 //Return burst mode state
loopsva 0:1ed24aaf786d 305 int ADC::burst(void) {
loopsva 0:1ed24aaf786d 306 return((LPC_ADC->ADCR & (1 << 16)) >> 16);
loopsva 0:1ed24aaf786d 307 }
loopsva 0:1ed24aaf786d 308
loopsva 0:1ed24aaf786d 309 //Set startmode and edge
loopsva 0:1ed24aaf786d 310 void ADC::startmode(int mode, int edge) {
loopsva 0:1ed24aaf786d 311 int lpc_adc_temp;
loopsva 0:1ed24aaf786d 312
loopsva 0:1ed24aaf786d 313 //Reset start mode and edge bit,
loopsva 0:1ed24aaf786d 314 lpc_adc_temp = LPC_ADC->ADCR & ~(0x0F << 24);
loopsva 0:1ed24aaf786d 315 //Write with new values
loopsva 0:1ed24aaf786d 316 lpc_adc_temp |= ((mode & 7) << 24) | ((edge & 1) << 27);
loopsva 0:1ed24aaf786d 317 LPC_ADC->ADCR = lpc_adc_temp;
loopsva 0:1ed24aaf786d 318 }
loopsva 0:1ed24aaf786d 319
loopsva 0:1ed24aaf786d 320 //Return startmode state according to mode_edge=0: mode and mode_edge=1: edge
loopsva 0:1ed24aaf786d 321 int ADC::startmode(int mode_edge){
loopsva 0:1ed24aaf786d 322 switch (mode_edge) {
loopsva 0:1ed24aaf786d 323 case 0:
loopsva 0:1ed24aaf786d 324 default:
loopsva 0:1ed24aaf786d 325 return((LPC_ADC->ADCR >> 24) & 0x07);
loopsva 0:1ed24aaf786d 326 case 1:
loopsva 0:1ed24aaf786d 327 return((LPC_ADC->ADCR >> 27) & 0x01);
loopsva 0:1ed24aaf786d 328 }
loopsva 0:1ed24aaf786d 329 }
loopsva 0:1ed24aaf786d 330
loopsva 0:1ed24aaf786d 331 //Start ADC conversion
loopsva 0:1ed24aaf786d 332 void ADC::start(void) {
loopsva 0:1ed24aaf786d 333 startmode(1,0);
loopsva 0:1ed24aaf786d 334 }
loopsva 0:1ed24aaf786d 335
loopsva 0:1ed24aaf786d 336
loopsva 0:1ed24aaf786d 337 //Set interrupt enable/disable for pin to state
loopsva 0:1ed24aaf786d 338 void ADC::interrupt_state(PinName pin, int state) {
loopsva 0:1ed24aaf786d 339 int chan;
loopsva 0:1ed24aaf786d 340
loopsva 0:1ed24aaf786d 341 chan = _pin_to_channel(pin);
loopsva 0:1ed24aaf786d 342 if (state == 1) {
loopsva 0:1ed24aaf786d 343 LPC_ADC->ADINTEN &= ~0x100;
loopsva 0:1ed24aaf786d 344 LPC_ADC->ADINTEN |= 1 << chan;
loopsva 0:1ed24aaf786d 345 /* Enable the ADC Interrupt */
loopsva 0:1ed24aaf786d 346 NVIC_EnableIRQ(ADC_IRQn);
loopsva 0:1ed24aaf786d 347 } else {
loopsva 0:1ed24aaf786d 348 LPC_ADC->ADINTEN &= ~( 1 << chan );
loopsva 0:1ed24aaf786d 349 //Disable interrrupt if no active pins left
loopsva 0:1ed24aaf786d 350 if ((LPC_ADC->ADINTEN & 0xFF) == 0)
loopsva 0:1ed24aaf786d 351 NVIC_DisableIRQ(ADC_IRQn);
loopsva 0:1ed24aaf786d 352 }
loopsva 0:1ed24aaf786d 353 }
loopsva 0:1ed24aaf786d 354
loopsva 0:1ed24aaf786d 355 //Return enable/disable state of interrupt for pin
loopsva 0:1ed24aaf786d 356 int ADC::interrupt_state(PinName pin) {
loopsva 0:1ed24aaf786d 357 int chan;
loopsva 0:1ed24aaf786d 358
loopsva 0:1ed24aaf786d 359 chan = _pin_to_channel(pin);
loopsva 0:1ed24aaf786d 360 return((LPC_ADC->ADINTEN >> chan) & 0x01);
loopsva 0:1ed24aaf786d 361 }
loopsva 0:1ed24aaf786d 362
loopsva 0:1ed24aaf786d 363
loopsva 0:1ed24aaf786d 364 //Attach custom interrupt handler replacing default
loopsva 0:1ed24aaf786d 365 void ADC::attach(void(*fptr)(void)) {
loopsva 0:1ed24aaf786d 366 //* Attach IRQ
loopsva 0:1ed24aaf786d 367 NVIC_SetVector(ADC_IRQn, (uint32_t)fptr);
loopsva 0:1ed24aaf786d 368 }
loopsva 0:1ed24aaf786d 369
loopsva 0:1ed24aaf786d 370 //Restore default interrupt handler
loopsva 0:1ed24aaf786d 371 void ADC::detach(void) {
loopsva 0:1ed24aaf786d 372 //* Attach IRQ
loopsva 0:1ed24aaf786d 373 instance = this;
loopsva 0:1ed24aaf786d 374 NVIC_SetVector(ADC_IRQn, (uint32_t)&_adcisr);
loopsva 0:1ed24aaf786d 375 }
loopsva 0:1ed24aaf786d 376
loopsva 0:1ed24aaf786d 377
loopsva 0:1ed24aaf786d 378 //Append interrupt handler for pin to function isr
loopsva 0:1ed24aaf786d 379 void ADC::append(PinName pin, void(*fptr)(uint32_t value)) {
loopsva 0:1ed24aaf786d 380 int chan;
loopsva 0:1ed24aaf786d 381
loopsva 0:1ed24aaf786d 382 chan = _pin_to_channel(pin);
loopsva 0:1ed24aaf786d 383 _adc_isr[chan] = fptr;
loopsva 0:1ed24aaf786d 384 }
loopsva 0:1ed24aaf786d 385
loopsva 0:1ed24aaf786d 386 //Append interrupt handler for pin to function isr
loopsva 0:1ed24aaf786d 387 void ADC::unappend(PinName pin) {
loopsva 0:1ed24aaf786d 388 int chan;
loopsva 0:1ed24aaf786d 389
loopsva 0:1ed24aaf786d 390 chan = _pin_to_channel(pin);
loopsva 0:1ed24aaf786d 391 _adc_isr[chan] = NULL;
loopsva 0:1ed24aaf786d 392 }
loopsva 0:1ed24aaf786d 393
loopsva 0:1ed24aaf786d 394 //Unappend global interrupt handler to function isr
loopsva 0:1ed24aaf786d 395 void ADC::append(void(*fptr)(int chan, uint32_t value)) {
loopsva 0:1ed24aaf786d 396 _adc_g_isr = fptr;
loopsva 0:1ed24aaf786d 397 }
loopsva 0:1ed24aaf786d 398
loopsva 0:1ed24aaf786d 399 //Detach global interrupt handler to function isr
loopsva 0:1ed24aaf786d 400 void ADC::unappend() {
loopsva 0:1ed24aaf786d 401 _adc_g_isr = NULL;
loopsva 0:1ed24aaf786d 402 }
loopsva 0:1ed24aaf786d 403
loopsva 0:1ed24aaf786d 404 //Set ADC offset
loopsva 0:1ed24aaf786d 405 void offset(int offset) {
loopsva 0:1ed24aaf786d 406 LPC_ADC->ADTRM &= ~(0x07 << 4);
loopsva 0:1ed24aaf786d 407 LPC_ADC->ADTRM |= (offset & 0x07) << 4;
loopsva 0:1ed24aaf786d 408 }
loopsva 0:1ed24aaf786d 409
loopsva 0:1ed24aaf786d 410 //Return current ADC offset
loopsva 0:1ed24aaf786d 411 int offset(void) {
loopsva 0:1ed24aaf786d 412 return((LPC_ADC->ADTRM >> 4) & 0x07);
loopsva 0:1ed24aaf786d 413 }
loopsva 0:1ed24aaf786d 414
loopsva 0:1ed24aaf786d 415 //Return value of ADC on pin
loopsva 0:1ed24aaf786d 416 int ADC::read(PinName pin) {
loopsva 0:1ed24aaf786d 417 //Reset DONE and OVERRUN flags of interrupt handled ADC data
loopsva 0:1ed24aaf786d 418 _adc_data[_pin_to_channel(pin)] &= ~(((uint32_t)0x01 << 31) | ((uint32_t)0x01 << 30));
loopsva 0:1ed24aaf786d 419 //Return value
loopsva 0:1ed24aaf786d 420 return((_data_of_pin(pin) >> 4) & 0xFFF);
loopsva 0:1ed24aaf786d 421 }
loopsva 0:1ed24aaf786d 422
loopsva 0:1ed24aaf786d 423 //Return DONE flag of ADC on pin
loopsva 0:1ed24aaf786d 424 int ADC::done(PinName pin) {
loopsva 0:1ed24aaf786d 425 return((_data_of_pin(pin) >> 31) & 0x01);
loopsva 0:1ed24aaf786d 426 }
loopsva 0:1ed24aaf786d 427
loopsva 0:1ed24aaf786d 428 //Return OVERRUN flag of ADC on pin
loopsva 0:1ed24aaf786d 429 int ADC::overrun(PinName pin) {
loopsva 0:1ed24aaf786d 430 return((_data_of_pin(pin) >> 30) & 0x01);
loopsva 0:1ed24aaf786d 431 }
loopsva 0:1ed24aaf786d 432
loopsva 0:1ed24aaf786d 433 int ADC::actual_adc_clock(void) {
loopsva 0:1ed24aaf786d 434 return(_adc_clk_freq);
loopsva 0:1ed24aaf786d 435 }
loopsva 0:1ed24aaf786d 436
loopsva 0:1ed24aaf786d 437 int ADC::actual_sample_rate(void) {
loopsva 0:1ed24aaf786d 438 return(_adc_clk_freq / CLKS_PER_SAMPLE);
loopsva 0:1ed24aaf786d 439 }