Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Sat Jul 16 2022 02:18:32 by
1.7.2