Mark Uckermann / NbAnalogIn
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NbAnalogIn.cpp Source File

NbAnalogIn.cpp

00001 #include "NbAnalogIn.h"
00002 
00003 static inline int pos_inc(int i) {
00004     
00005     if (i < ADC_BUF_SIZE - 1) {
00006         i++;
00007     } else {
00008         i = 0;
00009     }    
00010     return i;  
00011 }
00012 
00013 static const PinMap PinMap_ADC[] = {
00014     P0_23, ADC0_0, 1,
00015     P0_24, ADC0_1, 1,
00016     P0_25, ADC0_2, 1,
00017     P0_26, ADC0_3, 1,
00018     P1_30, ADC0_4, 3,
00019     P1_31, ADC0_5, 3,
00020     P0_2,  ADC0_7, 2,
00021     P0_3,  ADC0_6, 2,
00022     NC,    NC,     0
00023 };
00024 
00025 //set the static handlers array to 0
00026 NbAnalogIn* NbAnalogIn::handlers[ADC_CHANNELS] = {0}; 
00027 volatile bool NbAnalogIn::converting = false; 
00028 
00029 NbAnalogIn::NbAnalogIn( PinName pin) {
00030     
00031     NVIC_EnableIRQ(ADC_IRQn);
00032     NVIC_SetVector(ADC_IRQn, (uint32_t)irq);
00033     
00034  
00035     
00036     channel = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
00037     if (channel == (uint32_t)NC)
00038         error("ADC pin mapping failed");
00039     
00040     
00041     write_pos = 0;      // next position to be written to
00042     read_pos = 0;       // next position to be read from
00043     
00044     handlers[channel] = this;    // put a pointer to this object into the handlers array
00045     
00046     LPC_SC->PCONP |= (1 << 12); // turn power for ADC on
00047     
00048     
00049     // set peripheral clock registers to provide clock for ADC (bits 24 & 25)
00050     // set to 00 for PCLK = CCLK
00051     LPC_SC->PCLKSEL0 &= ~(0x3 << 24); // clear bits
00052     LPC_SC->PCLKSEL0 |= (0x1 << 24);  // set bits
00053         
00054     
00055     //Map pins
00056     pinmap_pinout(pin, PinMap_ADC);
00057     
00058     /* set the A/D control register */
00059     
00060     // select clkdiv = 7, enable, don't start yet
00061     LPC_ADC->ADCR  |= (7 << 8)          // set CLKDIV=7 (the fastest)
00062                     | (1 << 21)         // Power On
00063                     | (0 << 24) ;       // Don't Start yet
00064                     
00065     LPC_ADC->ADINTEN |= (1 << 8);
00066 }
00067 
00068 void NbAnalogIn::setInterrupt(void (*irqfunc)() , int prio) {
00069     cirq = irqfunc;
00070     
00071     if( prio >=0 && prio <=32 ) {
00072         NVIC_SetPriority(ADC_IRQn, prio);  //set priority of these interrupts
00073     }
00074 }
00075 
00076 int NbAnalogIn::readBl() {
00077     
00078     /* disable interrupt */
00079     NVIC_EnableIRQ(ADC_IRQn);
00080     
00081     LPC_ADC->ADCR   &= ~( 0xff );  // disable all other channels
00082     LPC_ADC->ADCR   |= (1 << channel)
00083                     |  (1 << 24) ; // start conversion
00084                     
00085     
00086     while((LPC_ADC->ADSTAT & (1 << channel)) == 0);
00087     
00088     int adc_result = (int)( (LPC_ADC->ADGDR >> 4) & 0xFFF );
00089     
00090     NVIC_EnableIRQ(ADC_IRQn);
00091     return adc_result;
00092 }
00093 
00094 void NbAnalogIn::triggerConv( bool wait) {
00095     
00096     if(wait) {
00097         while(converting);
00098     }
00099     
00100     converting = true;
00101     LPC_ADC->ADCR   &= ~( 0xff );  // disable all other channels
00102     LPC_ADC->ADCR   |= (1 << channel)
00103                     |  (1 << 24) ; // start conversion
00104                     
00105  
00106 }
00107 
00108 // static interrupt handler
00109 void NbAnalogIn::irq() {
00110     
00111     
00112     int adc_result = (int)((LPC_ADC->ADGDR >> 4) & 0xFFF);
00113     uint8_t adc_channel = (uint8_t)((LPC_ADC->ADGDR >> 24) & 0x7);
00114     
00115     converting = false;
00116     
00117     /** for debug 
00118     static int count = 0;    
00119     adc_result = count++;    
00120     printf("NbAnalogIn::irq(): channel %d, result %d \n",adc_channel, adc_result);
00121     */
00122     
00123     // call the right channel's handler
00124     handlers[adc_channel]->handler(adc_result);
00125     
00126 }
00127 
00128 void NbAnalogIn::handler( int adc_result ) {
00129     
00130     
00131     buffer[write_pos] = adc_result;
00132     
00133     //printf("NbAnalogIn::handler(c%d): %d written into pos %d \n", channel,adc_result, write_pos);
00134     write_pos = pos_inc( write_pos );
00135     
00136     // loop around
00137     if( write_pos == read_pos ) {
00138         read_pos = pos_inc( read_pos ); // keep read position ahead of write position
00139         //printf("NbAnalogIn::handler(c%d): LOOP AROUND!!! incremented r \n", channel);
00140     }
00141     //printf("NbAnalogIn::handler(c%d): w=%d, r=%d \n", channel, write_pos, read_pos);
00142 
00143         // call custom irq handler if set
00144     if (cirq)
00145         cirq();    
00146 }
00147 
00148 bool NbAnalogIn::readable() {
00149     return  write_pos != read_pos;
00150 }
00151 
00152 int NbAnalogIn::read() {
00153     
00154     while(write_pos == read_pos);
00155     
00156     int result = buffer[read_pos];
00157     
00158     //printf("NbAnalogIn::readNb(c%d): read %d from pos %d\n", channel, buffer[read_pos], read_pos );
00159     
00160     read_pos = pos_inc( read_pos ); // increment reading position
00161     
00162     return result;
00163 }