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:
Sissors
Date:
Thu May 09 17:46:32 2013 +0000
Revision:
0:c2a7b899e6c7
Child:
1:575f4d2d6e9c
v0.1
;

Who changed what in which revision?

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