Class similar to AnalogIn that uses burst mode to run continious background conversions so when the input is read, the last value can immediatly be returned. This slightly modified version allows NC pins.

Dependents:   Pinscape_Controller

Fork of FastAnalogIn by Erik Olieman

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FastAnalogIn_KLXX_K20D50M.cpp Source File

FastAnalogIn_KLXX_K20D50M.cpp

00001 #if defined(TARGET_KLXX) || defined(TARGET_K20D50M)
00002 
00003 #include "FastAnalogIn.h"
00004 #include "clk_freqs.h"
00005 
00006 #define MAX_FADC            6000000
00007 #define CHANNELS_A_SHIFT    5
00008 
00009 #ifdef TARGET_K20D50M
00010 static const PinMap PinMap_ADC[] = {
00011     {PTC2, ADC0_SE4b, 0},
00012     {PTD1, ADC0_SE5b, 0},
00013     {PTD5, ADC0_SE6b, 0},
00014     {PTD6, ADC0_SE7b, 0},
00015     {PTB0, ADC0_SE8,  0},
00016     {PTB1, ADC0_SE9,  0},
00017     {PTB2, ADC0_SE12, 0},
00018     {PTB3, ADC0_SE13, 0},
00019     {PTC0, ADC0_SE14, 0},
00020     {PTC1, ADC0_SE15, 0},
00021     {NC,   NC,        0}
00022 };
00023 #endif
00024 
00025 FastAnalogIn::FastAnalogIn(PinName pin, bool enabled)
00026 {
00027     if (pin == NC)
00028         return;
00029     
00030     ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
00031     if (ADCnumber == (ADCName)NC) {
00032         error("ADC pin mapping failed");
00033     }
00034 
00035     SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
00036 
00037     uint32_t port = (uint32_t)pin >> PORT_SHIFT;
00038     SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
00039 
00040     uint32_t cfg2_muxsel = ADC_CFG2_MUXSEL_MASK;
00041     if (ADCnumber & (1 << CHANNELS_A_SHIFT)) {
00042         cfg2_muxsel = 0;
00043     }
00044     
00045     // bus clk
00046     uint32_t PCLK = bus_frequency();
00047     uint32_t clkdiv;
00048     for (clkdiv = 0; clkdiv < 4; clkdiv++) {
00049         if ((PCLK >> clkdiv) <= MAX_FADC)
00050             break;
00051     }
00052     if (clkdiv == 4)                    //Set max div
00053         clkdiv = 0x7;
00054 
00055     ADC0->SC1[1] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));
00056 
00057     ADC0->CFG1 = ADC_CFG1_ADIV(clkdiv & 0x3)    // Clock Divide Select: (Input Clock)/8
00058                | ADC_CFG1_MODE(3)               // (16)bits Resolution
00059                | ADC_CFG1_ADICLK(clkdiv >> 2);  // Input Clock: (Bus Clock)/2
00060 
00061     ADC0->CFG2 = cfg2_muxsel            // ADxxb or ADxxa channels
00062                | ADC_CFG2_ADACKEN_MASK  // Asynchronous Clock Output Enable
00063                | ADC_CFG2_ADHSC_MASK;   // High-Speed Configuration
00064 
00065     ADC0->SC2 = ADC_SC2_REFSEL(0);      // Default Voltage Reference
00066 
00067     pinmap_pinout(pin, PinMap_ADC);
00068 
00069     //Enable channel
00070     running = false;
00071     enable(enabled);
00072 }
00073 
00074 void FastAnalogIn::enable(bool enabled)
00075 {
00076     //If currently not running
00077     if (!running) {
00078         if (enabled) {
00079             //Enable the ADC channel
00080             ADC0->SC3 |= ADC_SC3_ADCO_MASK;       // Enable continuous conversion
00081             ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));  //Start conversion
00082             running = true;
00083         } else
00084             disable();
00085     }
00086 }
00087  
00088 void FastAnalogIn::disable( void )
00089 {
00090     //If currently running
00091     if (running) {
00092         ADC0->SC3 &= ~ADC_SC3_ADCO_MASK;      // Disable continuous conversion
00093     }
00094     running = false;
00095 }
00096 
00097 uint16_t FastAnalogIn::read_u16()
00098 {
00099     if (!running)
00100     {
00101         // start conversion
00102         ADC0->SC1[0] = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT));
00103         // Wait Conversion Complete
00104         while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
00105     }
00106     if(running && ((ADC0->SC1[0]&ADC_SC1_ADCH_MASK) != (ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT)))))
00107     {
00108         running = false;
00109         enable();
00110         while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) != ADC_SC1_COCO_MASK);
00111     }
00112     // Return value
00113     return (uint16_t)ADC0->R[0];
00114 }
00115 
00116 #endif //defined TARGET_KLXX
00117