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
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
Generated on Wed Jul 13 2022 03:30:10 by 1.7.2