Class similar to AnalogIn that uses burst mode to run continious background conversions so when the input is read, the last value can immediatly be returned. This slightly modified version allows NC pins.

Dependents:   Pinscape_Controller

Fork of FastAnalogIn by Erik -

Committer:
frankvnk
Date:
Sat Mar 08 15:44:57 2014 +0000
Revision:
2:9b61d0792927
Parent:
FastAnalogIn.cpp@1:575f4d2d6e9c
Child:
4:cd84739f7640
Added KLxx support

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 2:9b61d0792927 1 #ifdef TARGET_LPC1768
frankvnk 2:9b61d0792927 2
Sissors 0:c2a7b899e6c7 3 #include "FastAnalogIn.h"
Sissors 0:c2a7b899e6c7 4 static inline int div_round_up(int x, int y)
Sissors 0:c2a7b899e6c7 5 {
Sissors 0:c2a7b899e6c7 6 return (x + (y - 1)) / y;
Sissors 0:c2a7b899e6c7 7 }
Sissors 0:c2a7b899e6c7 8
frankvnk 2:9b61d0792927 9 static const PinMap PinMap_ADC[] = {
frankvnk 2:9b61d0792927 10 P0_23, ADC0_0, 1,
frankvnk 2:9b61d0792927 11 P0_24, ADC0_1, 1,
frankvnk 2:9b61d0792927 12 P0_25, ADC0_2, 1,
frankvnk 2:9b61d0792927 13 P0_26, ADC0_3, 1,
frankvnk 2:9b61d0792927 14 P1_30, ADC0_4, 3,
frankvnk 2:9b61d0792927 15 P1_31, ADC0_5, 3,
frankvnk 2:9b61d0792927 16 P0_2, ADC0_7, 2,
frankvnk 2:9b61d0792927 17 P0_3, ADC0_6, 2,
frankvnk 2:9b61d0792927 18 NC, NC, 0
Sissors 0:c2a7b899e6c7 19 };
Sissors 0:c2a7b899e6c7 20
Sissors 0:c2a7b899e6c7 21 FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
Sissors 0:c2a7b899e6c7 22 {
Sissors 0:c2a7b899e6c7 23 ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
Sissors 0:c2a7b899e6c7 24 if (ADCnumber == (uint32_t)NC)
Sissors 0:c2a7b899e6c7 25 error("ADC pin mapping failed");
Sissors 0:c2a7b899e6c7 26 datareg = (uint32_t*) (&LPC_ADC->ADDR0 + ADCnumber);
Sissors 0:c2a7b899e6c7 27
Sissors 0:c2a7b899e6c7 28 // ensure power is turned on
Sissors 0:c2a7b899e6c7 29 LPC_SC->PCONP |= (1 << 12);
Sissors 0:c2a7b899e6c7 30 // set PCLK of ADC to /1
Sissors 0:c2a7b899e6c7 31 LPC_SC->PCLKSEL0 &= ~(0x3 << 24);
Sissors 0:c2a7b899e6c7 32 LPC_SC->PCLKSEL0 |= (0x1 << 24);
Sissors 0:c2a7b899e6c7 33 uint32_t PCLK = SystemCoreClock;
Sissors 0:c2a7b899e6c7 34
Sissors 0:c2a7b899e6c7 35 // calculate minimum clock divider
Sissors 0:c2a7b899e6c7 36 // clkdiv = divider - 1
Sissors 0:c2a7b899e6c7 37 uint32_t MAX_ADC_CLK = 13000000;
Sissors 0:c2a7b899e6c7 38 uint32_t clkdiv = div_round_up(PCLK, MAX_ADC_CLK) - 1;
Sissors 0:c2a7b899e6c7 39 // Set the clkdiv
Sissors 0:c2a7b899e6c7 40 LPC_ADC->ADCR &= ~(255<<8);
Sissors 0:c2a7b899e6c7 41 LPC_ADC->ADCR |= clkdiv<<8;
Sissors 0:c2a7b899e6c7 42
Sissors 0:c2a7b899e6c7 43 //Enable ADC:
Sissors 0:c2a7b899e6c7 44 LPC_ADC->ADCR |= 1<<21;
Sissors 0:c2a7b899e6c7 45
Sissors 0:c2a7b899e6c7 46 //Enable burstmode, set start as zero
Sissors 0:c2a7b899e6c7 47 LPC_ADC->ADCR |= 1<<16;
Sissors 0:c2a7b899e6c7 48 LPC_ADC->ADCR &= ~(7<<24);
Sissors 0:c2a7b899e6c7 49
Sissors 0:c2a7b899e6c7 50 //Map pins
Sissors 0:c2a7b899e6c7 51 pinmap_pinout(pin, PinMap_ADC);
Sissors 0:c2a7b899e6c7 52
Sissors 0:c2a7b899e6c7 53 //Enable channel
Sissors 0:c2a7b899e6c7 54 running = false;
Sissors 0:c2a7b899e6c7 55 enable(enabled);
Sissors 0:c2a7b899e6c7 56
Sissors 0:c2a7b899e6c7 57 }
Sissors 0:c2a7b899e6c7 58
Sissors 0:c2a7b899e6c7 59 void FastAnalogIn::enable(bool enabled)
Sissors 0:c2a7b899e6c7 60 {
Sissors 0:c2a7b899e6c7 61 //If currently not running
Sissors 0:c2a7b899e6c7 62 if (!running) {
Sissors 0:c2a7b899e6c7 63 if (enabled) {
Sissors 0:c2a7b899e6c7 64 //Enable the ADC channel
Sissors 0:c2a7b899e6c7 65 channel_usage[ADCnumber]++;
Sissors 0:c2a7b899e6c7 66 LPC_ADC->ADCR |= (1<<ADCnumber);
Sissors 0:c2a7b899e6c7 67 running = true;
Sissors 0:c2a7b899e6c7 68 } else
Sissors 0:c2a7b899e6c7 69 disable();
Sissors 0:c2a7b899e6c7 70 }
frankvnk 2:9b61d0792927 71 }
Sissors 0:c2a7b899e6c7 72
Sissors 0:c2a7b899e6c7 73 void FastAnalogIn::disable( void )
Sissors 0:c2a7b899e6c7 74 {
Sissors 0:c2a7b899e6c7 75 //If currently running
Sissors 0:c2a7b899e6c7 76 if (running) {
Sissors 0:c2a7b899e6c7 77 channel_usage[ADCnumber]--;
Sissors 0:c2a7b899e6c7 78
Sissors 0:c2a7b899e6c7 79 if (channel_usage[ADCnumber]==0)
Sissors 0:c2a7b899e6c7 80 LPC_ADC->ADCR &= ~(1<<ADCnumber);
Sissors 0:c2a7b899e6c7 81 }
Sissors 0:c2a7b899e6c7 82 running = false;
frankvnk 2:9b61d0792927 83 }
Sissors 0:c2a7b899e6c7 84
Sissors 0:c2a7b899e6c7 85 unsigned short FastAnalogIn::read_u16( void )
Sissors 0:c2a7b899e6c7 86 {
Sissors 1:575f4d2d6e9c 87 volatile unsigned int retval;
Sissors 0:c2a7b899e6c7 88 //If object is enabled return current value of datareg
Sissors 1:575f4d2d6e9c 89 if (running )
Sissors 1:575f4d2d6e9c 90 retval = *datareg;
Sissors 1:575f4d2d6e9c 91
Sissors 0:c2a7b899e6c7 92 //If it isn't running, enable it and wait until new value is written to datareg
Sissors 0:c2a7b899e6c7 93 else {
Sissors 0:c2a7b899e6c7 94 //Force a read to clear done bit, enable the ADC channel
Sissors 1:575f4d2d6e9c 95 retval = *datareg;
Sissors 0:c2a7b899e6c7 96 enable();
Sissors 0:c2a7b899e6c7 97 //Wait until it is converted
Sissors 0:c2a7b899e6c7 98 while(1) {
Sissors 0:c2a7b899e6c7 99 wait_us(1);
Sissors 0:c2a7b899e6c7 100 retval = *datareg;
Sissors 0:c2a7b899e6c7 101 if ((retval>>31) == 1)
Sissors 0:c2a7b899e6c7 102 break;
Sissors 0:c2a7b899e6c7 103 }
Sissors 0:c2a7b899e6c7 104
Sissors 0:c2a7b899e6c7 105 //Do a second conversion since first one always fails for some reason
Sissors 0:c2a7b899e6c7 106 while(1) {
Sissors 0:c2a7b899e6c7 107 wait_us(1);
Sissors 0:c2a7b899e6c7 108 retval = *datareg;
Sissors 0:c2a7b899e6c7 109 if ((retval>>31) == 1)
Sissors 0:c2a7b899e6c7 110 break;
Sissors 0:c2a7b899e6c7 111 }
Sissors 0:c2a7b899e6c7 112
Sissors 0:c2a7b899e6c7 113 //Disable again
Sissors 0:c2a7b899e6c7 114 disable();
Sissors 0:c2a7b899e6c7 115 }
Sissors 1:575f4d2d6e9c 116
Sissors 1:575f4d2d6e9c 117 //Do same thing as standard mbed lib, unused bit 0-3, replicate 4-7 in it
Sissors 1:575f4d2d6e9c 118 retval &= ~0xFFFF000F;
Sissors 1:575f4d2d6e9c 119 retval |= (retval >> 8) & 0x000F;
Sissors 1:575f4d2d6e9c 120 return retval;
Sissors 0:c2a7b899e6c7 121
Sissors 0:c2a7b899e6c7 122 }
frankvnk 2:9b61d0792927 123 #endif //defined TARGET_LPC1768