Jim Patterson / Mbed 2 deprecated MultiSensor_00

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers daq.cpp Source File

daq.cpp

00001 #include "mbed.h"
00002 #include "daq.h"
00003 
00004 /**
00005  *  A class to implement BURST mode sampling of multiple ADCs
00006  */
00007 
00008 ADC_BURST *ADC_BURST::instance;
00009 
00010 /**
00011  * Constructor for BURST mode.
00012  * ADCs in use are on mbed pins 15-17 and 19
00013  * These equate to ADCs
00014  */
00015 
00016 ADC_BURST::ADC_BURST () {
00017     // Make this instance available for pointing to privately
00018     instance = this;
00019     // Power up the ADC
00020     LPC_SC->PCONP |= (1 << 12);
00021     // Set up the pins
00022     //  DIP15:17 = ADC0:2
00023     LPC_PINCON->PINSEL1 &=     ~((uint32_t)0x3F << 14);
00024     LPC_PINCON->PINSEL1 |=      ((uint32_t)0x15 << 14);
00025     //  DIP19 = ADC4
00026     LPC_PINCON->PINSEL3 |=      ((uint32_t)0x3 << 28);
00027     //  Tri-state, no-pull
00028     LPC_PINCON->PINMODE1 &=    ~((uint32_t)0x3F << 14);
00029     LPC_PINCON->PINMODE1 |=     ((uint32_t)0x2A << 14);
00030     LPC_PINCON->PINMODE3 &=    ~((uint32_t)0x3 << 28);
00031     LPC_PINCON->PINMODE3 |=     ((uint32_t)0x2 << 28);
00032     // Set the clock divider to 256 (96e6/4/24 = 1e6) [LPC_SC->PCLKSEL0:PCLK_ADC = x20 by default]
00033     LPC_ADC->ADCR = (255 << 8);
00034     // Select the ADC channel
00035     LPC_ADC->ADCR &= ~0xFF;
00036     LPC_ADC->ADCR |= 0x17;      // ADC0:2,4 - DIP15:17,19
00037     // Attach a function to the interrupt vector table
00038     NVIC_SetVector(ADC_IRQn, (uint32_t)&_burst_isr);
00039     NVIC_EnableIRQ(ADC_IRQn);
00040     // Enable interrupts
00041     LPC_ADC->ADINTEN = 0x17;    // Interrupt on channels 0:2,4
00042     attached_ = false;
00043 }
00044 
00045 /**
00046  * Attach a function to the interrupt service routine
00047  *
00048  * @param inptr Function pointer passed from main code.
00049  */
00050 
00051 void ADC_BURST::attach (FuncPtr inptr) {
00052     isr_pointer_ = inptr;
00053     // Power up the ADC circuitry
00054     LPC_ADC->ADCR |= (1 << 21);
00055     // Enable BURST mode to start continuous conversions
00056     LPC_ADC->ADCR |= (1 << 16);
00057     attached_ = true;
00058 }
00059 
00060 void ADC_BURST::burst_isr () {
00061     // CanNOT read from global ADC interrupt register - otherwise interrupt is NOT CLEARED
00062     if ((LPC_ADC->ADSTAT & 0xFF00) != 0)
00063         // Overflow!
00064         error("ADSTAT: %x\n", LPC_ADC->ADSTAT);
00065 
00066     uint32_t chan = (LPC_ADC->ADGDR >> 24) & 0xF;
00067     switch (chan) {
00068         case 0:
00069             data[0] = (LPC_ADC->ADDR0 & 0x0000FFF0);
00070             break;
00071         case 1:
00072             data[1] = (LPC_ADC->ADDR1 & 0x0000FFF0);
00073             break;
00074         case 2:
00075             data[2] = (LPC_ADC->ADDR2 & 0x0000FFF0);
00076             break;
00077         case 4:
00078             data[3] = (LPC_ADC->ADDR4 & 0x0000FFF0);
00079             if (attached_) (*isr_pointer_)();
00080             break;
00081         default:
00082             error("Random channel interrupt: %d!\n",chan);
00083     }
00084 }
00085 
00086 void ADC_BURST::_burst_isr() {
00087     instance->burst_isr();
00088 }
00089 
00090 ADC_BURST::~ADC_BURST () {
00091     // Kill ADC
00092     LPC_ADC->ADINTEN = 0;
00093     LPC_SC->PCONP &= ~(1 << 12);
00094 }
00095 
00096 /**
00097  *  Decimator class to implement simple low-pass filtering on uC
00098  */
00099 
00100 /**
00101  * Decimator constructor.
00102  * Constructor to zero circular decimation buffer and pointers.
00103  * As init state is zero accumulator is safe from underflow on subtraction.
00104  */
00105 Decimator::Decimator (uint8_t order) {
00106     decimation_pointer_ = 0;                       // Initialise the buffer pointer
00107     decimation_order_ = (order > 5) ? 5: order;    // Limit the order to 5
00108     decimation_length_ = 1 << decimation_order_;
00109     // Clear the buffer
00110     for (uint8_t i=0; i<decimation_length_; i++) {
00111         decimation_buffer_[i] = 0;
00112     }
00113     accumulator_ = 0;
00114 }
00115 
00116 /**
00117  *  Data input function
00118  *  Write a new value into the decimator.
00119  *  Input is unsigned 16bits, max decimation length is 32 (5bits)
00120  *  so 32 bit accumulator is safe from overflow
00121  */
00122 void Decimator::write (uint16_t in_sample) {
00123     // Remove oldest sample from accumulator
00124     accumulator_ -= decimation_buffer_[decimation_pointer_];
00125     // Write in the newest sample
00126     decimation_buffer_[decimation_pointer_] = in_sample;
00127     accumulator_ += in_sample;
00128     // Increment the pointer
00129     decimation_pointer_++;
00130     if (decimation_pointer_ >= decimation_length_)
00131         decimation_pointer_ = 0;
00132 }
00133 
00134 /**
00135  * Data output function
00136  * Read the decimated signal
00137  */
00138 uint16_t Decimator::read() {
00139     // Just return the accumulator. Don't bother with any down scaling
00140     uint32_t output = accumulator_ >> decimation_order_;
00141     if ((accumulator_ & (decimation_length_>>1)) != 0)
00142         output++;
00143     return (uint16_t)output;
00144 }