An I/O controller for virtual pinball machines: accelerometer nudge sensing, analog plunger input, button input encoding, LedWiz compatible output controls, and more.

Dependencies:   mbed FastIO FastPWM USBDevice

Fork of Pinscape_Controller by Mike R

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AltAnalogIn_KL25Z.cpp Source File

AltAnalogIn_KL25Z.cpp

00001 #if defined(TARGET_KLXX) || defined(TARGET_K20D50M)
00002 
00003 #include "AltAnalogIn.h"
00004 #include "clk_freqs.h"
00005 
00006 #ifdef TARGET_K20D50M
00007 static const PinMap PinMap_ADC[] = {
00008     {PTC2, ADC0_SE4b, 0},
00009     {PTD1, ADC0_SE5b, 0},
00010     {PTD5, ADC0_SE6b, 0},
00011     {PTD6, ADC0_SE7b, 0},
00012     {PTB0, ADC0_SE8,  0},
00013     {PTB1, ADC0_SE9,  0},
00014     {PTB2, ADC0_SE12, 0},
00015     {PTB3, ADC0_SE13, 0},
00016     {PTC0, ADC0_SE14, 0},
00017     {PTC1, ADC0_SE15, 0},
00018     {NC,   NC,        0}
00019 };
00020 #endif
00021 
00022 // statics
00023 int AltAnalogIn::lastMux = -1;
00024 uint32_t AltAnalogIn::lastId = 0;
00025 
00026 AltAnalogIn::AltAnalogIn(PinName pin, bool continuous, int long_sample_clocks, int averaging, int sample_bits)
00027 {
00028     // set our unique ID
00029     static uint32_t nextID = 1;
00030     id = nextID++;
00031     
00032     // presume no DMA or interrupts
00033     dma = 0;
00034     sc1_aien = 0;
00035     
00036     // do nothing if explicitly not connected
00037     if (pin == NC)
00038         return;
00039             
00040     // validate the sample bit size, and figure the ADC_xxBIT code for it
00041     uint32_t adc_xxbit = ADC_8BIT;
00042     switch (sample_bits)
00043     {
00044     case 8:
00045         adc_xxbit = ADC_8BIT;
00046         break;
00047         
00048     case 10:
00049         adc_xxbit = ADC_10BIT;
00050         break;
00051         
00052     case 12:
00053         adc_xxbit = ADC_12BIT;
00054         break;
00055         
00056     case 16:
00057         adc_xxbit = ADC_16BIT;
00058         break;
00059         
00060     default:
00061         error("invalid sample size for AltAnalogIn - must be 8, 10, 12, or 16 bits");
00062     }
00063     
00064     // validate the long sample mode
00065     uint32_t cfg1_adlsmp = ADC_CFG1_ADLSMP;
00066     uint32_t cfg2_adlsts = ADC_CFG2_ADLSTS(3);
00067     switch (long_sample_clocks)
00068     {
00069     case 0:
00070         // disable long sample mode
00071         cfg1_adlsmp = 0;
00072         cfg2_adlsts = ADC_CFG2_ADLSTS(3);
00073         break;
00074         
00075     case 6:
00076         cfg1_adlsmp = ADC_CFG1_ADLSMP;  // enable long sample mode
00077         cfg2_adlsts = ADC_CFG2_ADLSTS(3);  // Long sample time mode 3 -> 6 ADCK cycles total
00078         break;
00079         
00080     case 10:
00081         cfg1_adlsmp = ADC_CFG1_ADLSMP;  // enable long sample mode
00082         cfg2_adlsts = ADC_CFG2_ADLSTS(2); // Long sample time mode 2 -> 10 ADCK cycles total
00083         break;
00084         
00085     case 16:
00086         cfg1_adlsmp = ADC_CFG1_ADLSMP;  // enable long sample mode
00087         cfg2_adlsts = ADC_CFG2_ADLSTS(1); // Long sample time mode 1 -> 16 ADCK cycles total
00088         break;
00089         
00090     case 24:
00091         cfg1_adlsmp = ADC_CFG1_ADLSMP;  // enable long sample mode
00092         cfg2_adlsts = ADC_CFG2_ADLSTS(0); // Long sample time mode 0 -> 24 ADCK cycles total
00093         break;
00094         
00095     default:
00096         error("invalid long sample mode clock count - must be 0 (disabled), 6, 10, 16, or 24");
00097     }
00098     
00099     // figure the averaging bits
00100     uint32_t sc3_avg = 0;
00101     switch (averaging)
00102     {
00103     case 0:
00104     case 1:
00105         // 0/1 = no averaging
00106         sc3_avg = 0;
00107         break;
00108         
00109     case 4:
00110         sc3_avg = ADC_SC3_AVGE | ADC_SC3_AVGS_4;
00111         break;
00112         
00113     case 8:
00114         sc3_avg = ADC_SC3_AVGE | ADC_SC3_AVGS_8;
00115         break;
00116         
00117     case 16:
00118         sc3_avg = ADC_SC3_AVGE | ADC_SC3_AVGS_16;
00119         break;
00120         
00121     case 32:
00122         sc3_avg = ADC_SC3_AVGE | ADC_SC3_AVGS_32;
00123         break;
00124         
00125     default:
00126         error("invalid ADC averaging count: must be 1, 4, 8, 16, or 32");
00127     }
00128     
00129     // figure our ADC number
00130     ADCnumber = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
00131     if (ADCnumber == (ADCName)NC) {
00132         error("ADC pin mapping failed");
00133     }
00134     
00135     // figure our multiplexer channel (A or B)
00136     ADCmux = (ADCnumber >> CHANNELS_A_SHIFT) ^ 1;
00137 
00138     // enable the ADC0 clock in the system control module
00139     SIM->SCGC6 |= SIM_SCGC6_ADC0_MASK;
00140 
00141     // enable the port clock gate for the port containing our GPIO pin
00142     uint32_t port = (uint32_t)pin >> PORT_SHIFT;
00143     SIM->SCGC5 |= 1 << (SIM_SCGC5_PORTA_SHIFT + port);
00144         
00145     // Figure the maximum clock frequency.  In 12-bit mode or less, we can 
00146     // run the ADC at up to 18 MHz per the KL25Z data sheet.  (16-bit mode
00147     // is limited to 12 MHz.)
00148     int clkdiv = 0;
00149     uint32_t adcfreq = bus_frequency();
00150     uint32_t maxfreq = sample_bits <= 12 ? MAX_FADC_12BIT : MAX_FADC_16BIT;
00151     for ( ; adcfreq > maxfreq ; adcfreq /= 2, clkdiv += 1) ;
00152     
00153     // The "high speed configuration" bit is required if the ADC clock 
00154     // frequency is above a certain threshold.  The actual threshold is 
00155     // poorly documented: the reference manual only says that it's required
00156     // when running the ADC at "high speed" but doesn't define how high
00157     // "high" is.  The only numerical figure I can find is in the Freescale
00158     // ADC sample time calculator tool (a Windows program downloadable from
00159     // the Freescale site), which has a little notation on the checkbox for
00160     // the ADHSC bit that says to use it when the ADC clock is 8 MHz or
00161     // higher.
00162     //
00163     // Note that this bit is somewhat confusingly named.  It doesn't mean
00164     // "make the ADC go faster".  It actually means just the opposite.
00165     // What it really means is that the external clock is running so fast 
00166     // that the ADC has to pad out its sample time slightly to compensate,
00167     // by adding a couple of extra clock cycles to each sampling interval.
00168     const uint32_t ADHSC_SPEED_LIMIT = 8000000;
00169     uint32_t adhsc_bit = (adcfreq >= ADHSC_SPEED_LIMIT ? ADC_CFG2_ADHSC_MASK : 0);
00170     
00171     // map the GPIO pin in the system multiplexer to the ADC
00172     pinmap_pinout(pin, PinMap_ADC);
00173     
00174     // set up the ADC control registers - these are common to all users of this class
00175     
00176     ADC0->CFG1 = ADC_CFG1_ADIV(clkdiv)    // Clock Divide Select (as calculated above)
00177                | cfg1_adlsmp              // Long sample time
00178                | ADC_CFG1_MODE(adc_xxbit) // Sample precision
00179                | ADC_CFG1_ADICLK(0);      // Input Clock = bus clock
00180 
00181     ADC0->CFG2 = adhsc_bit                // High-Speed Configuration, if needed
00182                | cfg2_adlsts;             // long sample time mode
00183                
00184     // Figure our SC1 register bits
00185     sc1 = ADC_SC1_ADCH(ADCnumber & ~(1 << CHANNELS_A_SHIFT))
00186         | sc1_aien;
00187 
00188     // figure our SC2 register bits
00189     sc2 = ADC_SC2_REFSEL(0);              // Default Voltage Reference
00190 
00191     // Set our SC3 bits.  The defaults (0 bits) are calibration mode off,
00192     // single sample, averaging disabled.
00193     sc3 = (continuous ? ADC_SC3_CONTINUOUS : 0) // enable continuous mode if desired
00194         | sc3_avg;                        // sample averaging mode bits
00195 }
00196 
00197 void AltAnalogIn::calibrate()
00198 {
00199     // Select our channel to set up the MUX and SC2/SC3 registers.  This
00200     // will set up the clock source and sample time we'll use to take
00201     // actual samples.
00202     selectChannel();
00203     
00204     // Make sure DMA is disabled on the channel, so that we can see COCO.
00205     // Also make sure that software triggering is in effect.
00206     ADC0->SC2 &= ~(ADC_SC2_DMAEN | ADC_SC2_ADTRG);
00207     
00208     // clear any past calibration results
00209     ADC0->SC3 |= ADC_SC3_CALF;
00210     
00211     // select 32X averaging mode for highest accuracy, and begin calibration
00212     ADC0->SC3 = (sc3 & ~ADC_SC3_AVGS_MASK) | ADC_SC3_AVGS_32 | ADC_SC3_CAL;
00213     
00214     // Wait for calibration to finish, but not more than 10ms, just in 
00215     // case something goes wrong in the setup.
00216     Timer t;
00217     t.start();
00218     uint32_t t0 = t.read_us();
00219     while ((ADC0->SC1[0] & ADC_SC1_COCO_MASK) == 0 && static_cast<uint32_t>(t.read_us() - t0) < 10000) ;
00220     
00221     // debugging
00222     // printf("ADC calibration %s, run time %u us\r\n", 
00223     //     (ADC0->SC3 & ADC_SC3_CALF) != 0 ? "error" : "ok",
00224     //     static_cast<uint32_t>(t.read_us() - t0));
00225     
00226     // Check results
00227     if ((ADC0->SC3 & ADC_SC3_CALF) == 0)
00228     {
00229         // Success - calculate the plus-side calibration results and store
00230         // in the PG register.  (This procedure is from reference manual.)
00231         uint16_t sum = 0;
00232         sum += ADC0->CLP0;
00233         sum += ADC0->CLP1;
00234         sum += ADC0->CLP2;
00235         sum += ADC0->CLP3;
00236         sum += ADC0->CLP4;
00237         sum += ADC0->CLPS;
00238         sum /= 2;
00239         sum |= 0x8000;
00240         ADC0->PG = sum;
00241         
00242         // do the same for the minus-side results
00243         sum = 0;
00244         sum += ADC0->CLM0;
00245         sum += ADC0->CLM1;
00246         sum += ADC0->CLM2;
00247         sum += ADC0->CLM3;
00248         sum += ADC0->CLM4;
00249         sum += ADC0->CLMS;
00250         sum /= 2;
00251         sum |= 0x8000;
00252         ADC0->MG = sum;
00253     }
00254     
00255     // Clear any error (this is one of those perverse cases where we clear
00256     // a bit in a peripheral by writing 1 to the bit)
00257     ADC0->SC3 |= ADC_SC3_CALF;
00258     
00259     // restore our normal SC2 and SC3 settings
00260     ADC0->SC2 = sc2;
00261     ADC0->SC3 = sc3;
00262     
00263     // un-select the channel so that we reset all registers next time
00264     unselectChannel();
00265 }
00266 
00267 void AltAnalogIn::enableInterrupts()
00268 {
00269     sc1_aien = ADC_SC1_AIEN;
00270     sc1 |= ADC_SC1_AIEN;
00271 }
00272 
00273 void AltAnalogIn::initDMA(SimpleDMA *dma)
00274 {
00275     // remember the DMA interface object
00276     this->dma = dma;
00277     
00278     // set to read from the ADC result register
00279     dma->source(&ADC0->R[0], false, 8);
00280     
00281     // set to trigger on the ADC
00282     dma->trigger(Trigger_ADC0);
00283 
00284     // enable DMA in our SC2 bits
00285     sc2 |= ADC_SC2_DMAEN;
00286 }
00287 
00288 void AltAnalogIn::setTriggerTPM(int tpmUnitNumber)
00289 {
00290     // select my channel
00291     selectChannel();
00292 
00293     // set the hardware trigger for the ADC to the specified TPM unit
00294     SIM->SOPT7 = ADC0ALTTRGEN | ADC0TRGSEL_TPM(tpmUnitNumber);
00295     
00296     // set the ADC to hardware trigger mode
00297     ADC0->SC2 = sc2 | ADC_SC2_ADTRG;
00298 
00299     // set SC1a and SC1b
00300     ADC0->SC1[0] = sc1;
00301     ADC0->SC1[1] = sc1;
00302 }
00303 
00304 #endif //defined TARGET_KLXX