Fast AnalogIn module which asks for a single non blocking reading and causes and interrupt when done.
NbAnalogIn.cpp
- Committer:
- dontknowhow
- Date:
- 2017-04-04
- Revision:
- 3:d4f99bc10643
- Parent:
- 2:336af413f75c
File content as of revision 3:d4f99bc10643:
#include "NbAnalogIn.h" static inline int pos_inc(int i) { if (i < ADC_BUF_SIZE - 1) { i++; } else { i = 0; } return i; } static const PinMap PinMap_ADC[] = { P0_23, ADC0_0, 1, P0_24, ADC0_1, 1, P0_25, ADC0_2, 1, P0_26, ADC0_3, 1, P1_30, ADC0_4, 3, P1_31, ADC0_5, 3, P0_2, ADC0_7, 2, P0_3, ADC0_6, 2, NC, NC, 0 }; //set the static handlers array to 0 NbAnalogIn* NbAnalogIn::handlers[ADC_CHANNELS] = {0}; volatile bool NbAnalogIn::converting = false; NbAnalogIn::NbAnalogIn( PinName pin) { NVIC_EnableIRQ(ADC_IRQn); NVIC_SetVector(ADC_IRQn, (uint32_t)irq); channel = (ADCName)pinmap_peripheral(pin, PinMap_ADC); if (channel == (uint32_t)NC) error("ADC pin mapping failed"); write_pos = 0; // next position to be written to read_pos = 0; // next position to be read from handlers[channel] = this; // put a pointer to this object into the handlers array LPC_SC->PCONP |= (1 << 12); // turn power for ADC on // set peripheral clock registers to provide clock for ADC (bits 24 & 25) // set to 00 for PCLK = CCLK LPC_SC->PCLKSEL0 &= ~(0x3 << 24); // clear bits LPC_SC->PCLKSEL0 |= (0x1 << 24); // set bits //Map pins pinmap_pinout(pin, PinMap_ADC); /* set the A/D control register */ // select clkdiv = 7, enable, don't start yet LPC_ADC->ADCR |= (7 << 8) // set CLKDIV=7 (the fastest) | (1 << 21) // Power On | (0 << 24) ; // Don't Start yet LPC_ADC->ADINTEN |= (1 << 8); } void NbAnalogIn::setInterrupt(void (*irqfunc)() , int prio) { cirq = irqfunc; if( prio >=0 && prio <=32 ) { NVIC_SetPriority(ADC_IRQn, prio); //set priority of these interrupts } } int NbAnalogIn::readBl() { /* disable interrupt */ NVIC_EnableIRQ(ADC_IRQn); LPC_ADC->ADCR &= ~( 0xff ); // disable all other channels LPC_ADC->ADCR |= (1 << channel) | (1 << 24) ; // start conversion while((LPC_ADC->ADSTAT & (1 << channel)) == 0); int adc_result = (int)( (LPC_ADC->ADGDR >> 4) & 0xFFF ); NVIC_EnableIRQ(ADC_IRQn); return adc_result; } void NbAnalogIn::triggerConv( bool wait) { if(wait) { while(converting); } converting = true; LPC_ADC->ADCR &= ~( 0xff ); // disable all other channels LPC_ADC->ADCR |= (1 << channel) | (1 << 24) ; // start conversion } // static interrupt handler void NbAnalogIn::irq() { int adc_result = (int)((LPC_ADC->ADGDR >> 4) & 0xFFF); uint8_t adc_channel = (uint8_t)((LPC_ADC->ADGDR >> 24) & 0x7); converting = false; /** for debug static int count = 0; adc_result = count++; printf("NbAnalogIn::irq(): channel %d, result %d \n",adc_channel, adc_result); */ // call the right channel's handler handlers[adc_channel]->handler(adc_result); } void NbAnalogIn::handler( int adc_result ) { buffer[write_pos] = adc_result; //printf("NbAnalogIn::handler(c%d): %d written into pos %d \n", channel,adc_result, write_pos); write_pos = pos_inc( write_pos ); // loop around if( write_pos == read_pos ) { read_pos = pos_inc( read_pos ); // keep read position ahead of write position //printf("NbAnalogIn::handler(c%d): LOOP AROUND!!! incremented r \n", channel); } //printf("NbAnalogIn::handler(c%d): w=%d, r=%d \n", channel, write_pos, read_pos); // call custom irq handler if set if (cirq) cirq(); } bool NbAnalogIn::readable() { return write_pos != read_pos; } int NbAnalogIn::read() { while(write_pos == read_pos); int result = buffer[read_pos]; //printf("NbAnalogIn::readNb(c%d): read %d from pos %d\n", channel, buffer[read_pos], read_pos ); read_pos = pos_inc( read_pos ); // increment reading position return result; }