Fast AnalogIn module which asks for a single non blocking reading and causes and interrupt when done.
NbAnalogIn.cpp@2:336af413f75c, 2017-04-03 (annotated)
- Committer:
- dontknowhow
- Date:
- Mon Apr 03 10:59:17 2017 +0000
- Revision:
- 2:336af413f75c
- Parent:
- 1:2666729acca1
- Child:
- 3:d4f99bc10643
Multiple channels, custom interrupt;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dontknowhow | 0:058d32b78e5d | 1 | #include "NbAnalogIn.h" |
dontknowhow | 0:058d32b78e5d | 2 | |
dontknowhow | 1:2666729acca1 | 3 | static inline int pos_inc(int i) { |
dontknowhow | 1:2666729acca1 | 4 | |
dontknowhow | 1:2666729acca1 | 5 | if (i < ADC_BUF_SIZE - 1) { |
dontknowhow | 1:2666729acca1 | 6 | i++; |
dontknowhow | 1:2666729acca1 | 7 | } else { |
dontknowhow | 1:2666729acca1 | 8 | i = 0; |
dontknowhow | 1:2666729acca1 | 9 | } |
dontknowhow | 1:2666729acca1 | 10 | return i; |
dontknowhow | 1:2666729acca1 | 11 | } |
dontknowhow | 1:2666729acca1 | 12 | |
dontknowhow | 2:336af413f75c | 13 | static const PinMap PinMap_ADC[] = { |
dontknowhow | 2:336af413f75c | 14 | P0_23, ADC0_0, 1, |
dontknowhow | 2:336af413f75c | 15 | P0_24, ADC0_1, 1, |
dontknowhow | 2:336af413f75c | 16 | P0_25, ADC0_2, 1, |
dontknowhow | 2:336af413f75c | 17 | P0_26, ADC0_3, 1, |
dontknowhow | 2:336af413f75c | 18 | P1_30, ADC0_4, 3, |
dontknowhow | 2:336af413f75c | 19 | P1_31, ADC0_5, 3, |
dontknowhow | 2:336af413f75c | 20 | P0_2, ADC0_7, 2, |
dontknowhow | 2:336af413f75c | 21 | P0_3, ADC0_6, 2, |
dontknowhow | 2:336af413f75c | 22 | NC, NC, 0 |
dontknowhow | 2:336af413f75c | 23 | }; |
dontknowhow | 1:2666729acca1 | 24 | |
dontknowhow | 2:336af413f75c | 25 | //set the static handlers array to 0 |
dontknowhow | 2:336af413f75c | 26 | NbAnalogIn* NbAnalogIn::handlers[ADC_CHANNELS] = {0}; |
dontknowhow | 2:336af413f75c | 27 | volatile bool NbAnalogIn::converting = false; |
dontknowhow | 2:336af413f75c | 28 | |
dontknowhow | 2:336af413f75c | 29 | NbAnalogIn::NbAnalogIn( PinName pin, void (*irqfunc)() ) { |
dontknowhow | 0:058d32b78e5d | 30 | |
dontknowhow | 0:058d32b78e5d | 31 | NVIC_EnableIRQ(ADC_IRQn); |
dontknowhow | 1:2666729acca1 | 32 | NVIC_SetVector(ADC_IRQn, (uint32_t)irq); |
dontknowhow | 1:2666729acca1 | 33 | |
dontknowhow | 2:336af413f75c | 34 | cirq = irqfunc; |
dontknowhow | 2:336af413f75c | 35 | |
dontknowhow | 2:336af413f75c | 36 | channel = (ADCName)pinmap_peripheral(pin, PinMap_ADC); |
dontknowhow | 2:336af413f75c | 37 | if (channel == (uint32_t)NC) |
dontknowhow | 2:336af413f75c | 38 | error("ADC pin mapping failed"); |
dontknowhow | 2:336af413f75c | 39 | |
dontknowhow | 2:336af413f75c | 40 | |
dontknowhow | 1:2666729acca1 | 41 | write_pos = 0; // next position to be written to |
dontknowhow | 1:2666729acca1 | 42 | read_pos = 0; // next position to be read from |
dontknowhow | 1:2666729acca1 | 43 | |
dontknowhow | 2:336af413f75c | 44 | handlers[channel] = this; // put a pointer to this object into the handlers array |
dontknowhow | 0:058d32b78e5d | 45 | |
dontknowhow | 0:058d32b78e5d | 46 | LPC_SC->PCONP |= (1 << 12); // turn power for ADC on |
dontknowhow | 0:058d32b78e5d | 47 | |
dontknowhow | 2:336af413f75c | 48 | |
dontknowhow | 0:058d32b78e5d | 49 | // set peripheral clock registers to provide clock for ADC (bits 24 & 25) |
dontknowhow | 0:058d32b78e5d | 50 | // set to 00 for PCLK = CCLK |
dontknowhow | 0:058d32b78e5d | 51 | LPC_SC->PCLKSEL0 &= ~(0x3 << 24); // clear bits |
dontknowhow | 0:058d32b78e5d | 52 | LPC_SC->PCLKSEL0 |= (0x1 << 24); // set bits |
dontknowhow | 2:336af413f75c | 53 | |
dontknowhow | 0:058d32b78e5d | 54 | |
dontknowhow | 2:336af413f75c | 55 | //Map pins |
dontknowhow | 2:336af413f75c | 56 | pinmap_pinout(pin, PinMap_ADC); |
dontknowhow | 0:058d32b78e5d | 57 | |
dontknowhow | 0:058d32b78e5d | 58 | /* set the A/D control register */ |
dontknowhow | 0:058d32b78e5d | 59 | |
dontknowhow | 2:336af413f75c | 60 | // select clkdiv = 7, enable, don't start yet |
dontknowhow | 2:336af413f75c | 61 | LPC_ADC->ADCR |= (7 << 8) // set CLKDIV=7 (the fastest) |
dontknowhow | 2:336af413f75c | 62 | | (1 << 21) // Power On |
dontknowhow | 2:336af413f75c | 63 | | (0 << 24) ; // Don't Start yet |
dontknowhow | 2:336af413f75c | 64 | |
dontknowhow | 2:336af413f75c | 65 | LPC_ADC->ADINTEN |= (1 << 8); |
dontknowhow | 0:058d32b78e5d | 66 | } |
dontknowhow | 0:058d32b78e5d | 67 | |
dontknowhow | 0:058d32b78e5d | 68 | |
dontknowhow | 2:336af413f75c | 69 | int NbAnalogIn::readBl() { |
dontknowhow | 0:058d32b78e5d | 70 | |
dontknowhow | 2:336af413f75c | 71 | /* disable interrupt */ |
dontknowhow | 2:336af413f75c | 72 | NVIC_EnableIRQ(ADC_IRQn); |
dontknowhow | 0:058d32b78e5d | 73 | |
dontknowhow | 2:336af413f75c | 74 | LPC_ADC->ADCR &= ~( 0xff ); // disable all other channels |
dontknowhow | 2:336af413f75c | 75 | LPC_ADC->ADCR |= (1 << channel) |
dontknowhow | 2:336af413f75c | 76 | | (1 << 24) ; // start conversion |
dontknowhow | 2:336af413f75c | 77 | |
dontknowhow | 0:058d32b78e5d | 78 | |
dontknowhow | 2:336af413f75c | 79 | while((LPC_ADC->ADSTAT & (1 << channel)) == 0); |
dontknowhow | 0:058d32b78e5d | 80 | |
dontknowhow | 2:336af413f75c | 81 | int adc_result = (int)( (LPC_ADC->ADGDR >> 4) & 0xFFF ); |
dontknowhow | 2:336af413f75c | 82 | |
dontknowhow | 2:336af413f75c | 83 | NVIC_EnableIRQ(ADC_IRQn); |
dontknowhow | 2:336af413f75c | 84 | return adc_result; |
dontknowhow | 0:058d32b78e5d | 85 | } |
dontknowhow | 0:058d32b78e5d | 86 | |
dontknowhow | 2:336af413f75c | 87 | void NbAnalogIn::triggerConv( bool wait) { |
dontknowhow | 2:336af413f75c | 88 | |
dontknowhow | 2:336af413f75c | 89 | if(wait) { |
dontknowhow | 2:336af413f75c | 90 | while(converting); |
dontknowhow | 2:336af413f75c | 91 | } |
dontknowhow | 0:058d32b78e5d | 92 | |
dontknowhow | 2:336af413f75c | 93 | converting = true; |
dontknowhow | 2:336af413f75c | 94 | LPC_ADC->ADCR &= ~( 0xff ); // disable all other channels |
dontknowhow | 2:336af413f75c | 95 | LPC_ADC->ADCR |= (1 << channel) |
dontknowhow | 2:336af413f75c | 96 | | (1 << 24) ; // start conversion |
dontknowhow | 2:336af413f75c | 97 | |
dontknowhow | 2:336af413f75c | 98 | |
dontknowhow | 1:2666729acca1 | 99 | } |
dontknowhow | 1:2666729acca1 | 100 | |
dontknowhow | 1:2666729acca1 | 101 | // static interrupt handler |
dontknowhow | 1:2666729acca1 | 102 | void NbAnalogIn::irq() { |
dontknowhow | 1:2666729acca1 | 103 | |
dontknowhow | 2:336af413f75c | 104 | |
dontknowhow | 1:2666729acca1 | 105 | int adc_result = (int)((LPC_ADC->ADGDR >> 4) & 0xFFF); |
dontknowhow | 2:336af413f75c | 106 | uint8_t adc_channel = (uint8_t)((LPC_ADC->ADGDR >> 24) & 0x7); |
dontknowhow | 1:2666729acca1 | 107 | |
dontknowhow | 2:336af413f75c | 108 | converting = false; |
dontknowhow | 2:336af413f75c | 109 | |
dontknowhow | 2:336af413f75c | 110 | /** for debug |
dontknowhow | 1:2666729acca1 | 111 | static int count = 0; |
dontknowhow | 1:2666729acca1 | 112 | adc_result = count++; |
dontknowhow | 2:336af413f75c | 113 | printf("NbAnalogIn::irq(): channel %d, result %d \n",adc_channel, adc_result); |
dontknowhow | 2:336af413f75c | 114 | */ |
dontknowhow | 1:2666729acca1 | 115 | |
dontknowhow | 1:2666729acca1 | 116 | // call the right channel's handler |
dontknowhow | 2:336af413f75c | 117 | handlers[adc_channel]->handler(adc_result); |
dontknowhow | 1:2666729acca1 | 118 | |
dontknowhow | 1:2666729acca1 | 119 | } |
dontknowhow | 1:2666729acca1 | 120 | |
dontknowhow | 1:2666729acca1 | 121 | void NbAnalogIn::handler( int adc_result ) { |
dontknowhow | 1:2666729acca1 | 122 | |
dontknowhow | 1:2666729acca1 | 123 | |
dontknowhow | 1:2666729acca1 | 124 | buffer[write_pos] = adc_result; |
dontknowhow | 1:2666729acca1 | 125 | |
dontknowhow | 2:336af413f75c | 126 | //printf("NbAnalogIn::handler(c%d): %d written into pos %d \n", channel,adc_result, write_pos); |
dontknowhow | 1:2666729acca1 | 127 | write_pos = pos_inc( write_pos ); |
dontknowhow | 1:2666729acca1 | 128 | |
dontknowhow | 1:2666729acca1 | 129 | // loop around |
dontknowhow | 1:2666729acca1 | 130 | if( write_pos == read_pos ) { |
dontknowhow | 1:2666729acca1 | 131 | read_pos = pos_inc( read_pos ); // keep read position ahead of write position |
dontknowhow | 2:336af413f75c | 132 | //printf("NbAnalogIn::handler(c%d): LOOP AROUND!!! incremented r \n", channel); |
dontknowhow | 1:2666729acca1 | 133 | } |
dontknowhow | 2:336af413f75c | 134 | //printf("NbAnalogIn::handler(c%d): w=%d, r=%d \n", channel, write_pos, read_pos); |
dontknowhow | 1:2666729acca1 | 135 | |
dontknowhow | 2:336af413f75c | 136 | // call custom irq handler if set |
dontknowhow | 2:336af413f75c | 137 | if (cirq) |
dontknowhow | 2:336af413f75c | 138 | cirq(); |
dontknowhow | 1:2666729acca1 | 139 | } |
dontknowhow | 1:2666729acca1 | 140 | |
dontknowhow | 1:2666729acca1 | 141 | bool NbAnalogIn::readable() { |
dontknowhow | 1:2666729acca1 | 142 | return write_pos != read_pos; |
dontknowhow | 1:2666729acca1 | 143 | } |
dontknowhow | 1:2666729acca1 | 144 | |
dontknowhow | 2:336af413f75c | 145 | int NbAnalogIn::read() { |
dontknowhow | 1:2666729acca1 | 146 | |
dontknowhow | 1:2666729acca1 | 147 | while(write_pos == read_pos); |
dontknowhow | 1:2666729acca1 | 148 | |
dontknowhow | 1:2666729acca1 | 149 | int result = buffer[read_pos]; |
dontknowhow | 1:2666729acca1 | 150 | |
dontknowhow | 2:336af413f75c | 151 | //printf("NbAnalogIn::readNb(c%d): read %d from pos %d\n", channel, buffer[read_pos], read_pos ); |
dontknowhow | 1:2666729acca1 | 152 | |
dontknowhow | 1:2666729acca1 | 153 | read_pos = pos_inc( read_pos ); // increment reading position |
dontknowhow | 1:2666729acca1 | 154 | |
dontknowhow | 1:2666729acca1 | 155 | return result; |
dontknowhow | 0:058d32b78e5d | 156 | } |