Jared Baxter
/
Impedance_Fast_Circuitry
Fork of DSP_200kHz by
Diff: Sample/adc.cpp
- Revision:
- 52:5a40cc58c4c2
- Parent:
- 51:43143a3fc2d7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sample/adc.cpp Sat Jan 31 20:56:04 2015 +0000 @@ -0,0 +1,221 @@ +#include "adc.h" + +/* +TODO: remove interrupt handlers + finish calibration + change clock speed +*/ +DigitalOut toggle1(PTA0); +DigitalOut green(LED_GREEN); +DigitalOut red(LED_RED); +//Serial debug(USBTX,USBRX); + + + +/* The ADCs are setup so that ADC0 and ADC1 are triggered by the PDB. + * When the conversions are complete, ADC0 and ADC1 then trigger DMA0 + * and DMA1, respectively. ADC0 is using channel B and ADC1 is uing + * channel A. If they are on the same channel, then weird things + * happen. I think they interfere with each other so they have to be + * on separate channels if they're going to be triggered at the same + * time by the PDB. */ +void adc_init() +{ + // red, indicating now ready + red = 0; + green = 1; + + // Turn on the ADC0 and ADC1 clocks + SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK; + SIM_SCGC3 |= SIM_SCGC3_ADC1_MASK; + + // Set ADC hardware trigger to PDB0 + SIM_SOPT7 = SIM_SOPT7_ADC0TRGSEL(0); // Select triggering by PDB and select pre-trigger A + SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0); // Select triggering by PDB and select pre-trigger A + + // Setup Configuration Register 1 + ADC0_CFG1 = 0; // clear register + ADC0_CFG1 |= ADC_CFG1_ADICLK(0); // select bus clock + ADC0_CFG1 |= ADC_CFG1_MODE(3); // select 16-bit 2's complement output + ADC0_CFG1 |= ADC_CFG1_ADIV(0); // select short sample time + ADC0_CFG1 &= ~ADC_CFG1_ADLSMP_MASK; // select short sample time + ADC0_CFG1 &= ~ADC_CFG1_ADLPC_MASK; // select normal power configuration + ADC1_CFG1 = 0; // clear register + ADC1_CFG1 |= ADC_CFG1_ADICLK(0); // select bus clock + ADC1_CFG1 |= ADC_CFG1_MODE(3); // select 16-bit 2's complement output + ADC1_CFG1 |= ADC_CFG1_ADIV(0); // select short sample time + ADC1_CFG1 &= ~ADC_CFG1_ADLSMP_MASK; // select short sample time + ADC1_CFG1 &= ~ADC_CFG1_ADLPC_MASK; // select normal power configuration + + // Setup Configuration Register 2 + ADC0_CFG2 = 0; // clear register + ADC0_CFG2 |= ADC_CFG2_ADHSC_MASK ; // select high-speed conversion + ADC0_CFG2 &= ~ADC_CFG2_MUXSEL_MASK; // select a channels + ADC1_CFG2 = 0; // clear register + ADC1_CFG2 |= ADC_CFG2_ADHSC_MASK ; // select high-speed conversion + ADC1_CFG2 &= ~ADC_CFG2_MUXSEL_MASK; // select a channels + + + // Setup Status and Control Register 2 + ADC0_SC2 = 0; // clear register + ADC0_SC2 |= ADC_SC2_REFSEL(0); // select external voltage reference + ADC0_SC2 |= ADC_SC2_DMAEN_MASK; // enable DMA + ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // select software trigger until calibration is complete + ADC1_SC2 = 0; // clear register + ADC1_SC2 |= ADC_SC2_REFSEL(0); // select external voltage reference + ADC1_SC2 |= ADC_SC2_DMAEN_MASK; // enable DMA + ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // select software trigger until calibration is complete + + // Setup Status and Control Register 3 + ADC0_SC3 = 0; // Hardware Average set to 4 samples averaged + // Hardware Average Disabled + // select single conversion mode + ADC1_SC3 = 0; // Hardware Average set to 4 samples averaged + // Hardware Average Disabled + // select single conversion mode + + // calibrate the ADC + ADC0_SC3 |= ADC_SC3_CAL_MASK; // start calibration + while(ADC0_SC3&ADC_SC3_CALF_MASK) {} // wait for calibration to complete + ADC1_SC3 |= ADC_SC3_CAL_MASK; // start calibration + while(ADC1_SC3&ADC_SC3_CALF_MASK) {} // wait for calibration to complete + + + // calculate the gains (see user manual page 864) + int16_t gain = (ADC0_CLP0+ADC0_CLP1+ADC0_CLP2+ADC0_CLP3+ADC0_CLP4+ADC0_CLPS); + gain = (gain>>1); // divide by 2 + gain |= 0x8000; // set the MSB + ADC0_PG = gain; + + gain = (ADC1_CLP0+ADC1_CLP1+ADC1_CLP2+ADC1_CLP3+ADC1_CLP4+ADC1_CLPS); + gain = (gain>>1); // divide by 2 + gain |= 0x8000; // set the MSB + ADC1_PG = gain; + + gain = (ADC0_CLM0+ADC0_CLM1+ADC0_CLM2+ADC0_CLM3+ADC0_CLM4+ADC0_CLMS); + gain = (gain>>1); // divide by 2 + gain |= 0x8000; // set the MSB + ADC0_MG = gain; + + gain = (ADC1_CLM0+ADC1_CLM1+ADC1_CLM2+ADC1_CLM3+ADC1_CLM4+ADC1_CLMS); + gain = (gain>>1); // divide by 2 + gain |= 0x8000; // set the MSB + ADC1_MG = gain; + + ADC0_SC3 &= ~ADC_SC3_CAL_MASK; // stop calibration + ADC1_SC3 &= ~ADC_SC3_CAL_MASK; // stop calibration + + + + // yellow indicating calibration complete + red = 0; + green = 0; + + ADC0_SC2 |= ADC_SC2_ADTRG_MASK; // select hardware trigger now that calibration is complete + ADC1_SC2 |= ADC_SC2_ADTRG_MASK; // select hardware trigger now that calibration is complete + + // Setup Status and Control Register 1A + ADC0_SC1B = 0; // clear register + ADC0_SC1B &= ~ADC_SC1_DIFF_MASK; // select single-ended mode + ADC0_SC1B |= ADC_SC1_AIEN_MASK; // enable interrupt (for debugging) + ADC0_SC1B |= ADC_SC1_ADCH(13); // select channel 13 + ADC1_SC1A = 0; // clear register + ADC1_SC1A &= ~ADC_SC1_DIFF_MASK; // select single-ended mode + ADC1_SC1A |= ADC_SC1_AIEN_MASK; // enable interrupt (for debugging) + ADC1_SC1A |= ADC_SC1_ADCH(14); // select channel 14 + + + // Check if ADC is finished initializing TODO: This part doesn't seem right, but I did it according to 871 + while( (ADC0_SC1B&ADC_SC1_COCO_MASK)) {} + gain = ADC0_RA; // read the register to clear SC1A[COCO] + while( (ADC1_SC1A&ADC_SC1_COCO_MASK)) {} + gain = ADC1_RA; // read the register to clear SC1A[COCO] + + + // green indicating calibration and initialization complete + red = 1; + green = 0; + + // Enable the ISR vector + //NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler); + //NVIC_EnableIRQ(ADC0_IRQn); +} + + +void ADC0_IRQHandler() { + + toggle1 = !toggle1; +} + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DEBUG: This is supposed to put the ADC in continuous * + * mode so it samples without the PCB. But for * + * some reason it isn't working. I haven't deleted * + * it just in case it is needed for debug purposes * + * in the future. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +void adc_start() { + // reset DMA + dma_reset(); + + // set ADC to continuous mode + ADC0_SC3 |= ADC_SC3_ADCO_MASK; + ADC1_SC3 |= ADC_SC3_ADCO_MASK; + + // set ADC to software trigger + ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; + ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; + + // start ADC conversion (SW trigger) + ADC0_SC1B |= ADC_SC1_ADCH(13); // write to SC1A causing a trigger + ADC1_SC1A |= ADC_SC1_ADCH(14); // write to SC1A causing a trigger +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DEBUG: This is supposed to revert back from adc_start() * + * but because adc_start() isn't working, this * + * function is good for nothing. I held on to * + * it just in case it is needed for debug purposes * + * in the future. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +void adc_stop() { + // set ADC to hardware trigger + ADC0_SC2 |= ADC_SC2_ADTRG_MASK; + ADC1_SC2 |= ADC_SC2_ADTRG_MASK; + + // set to single conversion mode effectively stopping the ADC unless a timer triggers the ADC + ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; + ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * DEBUG: This is supposed to trigger a software conversion * + * and take a single sample. However, it only * + * worked for ADC1 for some reason. It is here for * + * possible debug purposes in the future. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +void adc_single_sample() { + ADC0_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode + ADC1_SC3 &= ~ADC_SC3_ADCO_MASK; // single conversion mode + ADC0_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger + ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK; // set ADC to software trigger + ADC0_SC1B |= ADC_SC1_ADCH(13); // write to SC1B causing a trigger + ADC1_SC1A |= ADC_SC1_ADCH(14); // write to SC1A causing a trigger + + // Set back to hardware trigger + ADC0_SC2 |= ADC_SC2_ADTRG_MASK; // set ADC to software trigger + ADC1_SC2 |= ADC_SC2_ADTRG_MASK; // set ADC to software trigger +} + + +/* + debug.printf("ADC0_SC1a: %08x\r\n",ADC0_SC1A); //(0x0000004d) + debug.printf("ADC0_SC1b: %08x\r\n",ADC0_SC1B); //(0x0000001f) + debug.printf("ADC0_CFG1: %08x\r\n",ADC0_CFG1); //(0x0000000c) + debug.printf("ADC0_CFG2: %08x\r\n",ADC0_CFG2); //(0x00000004) + debug.printf("ADC0_RA: %08x\r\n",ADC0_RA); //(0x00000000) + debug.printf("ADC0_RB: %08x\r\n",ADC0_RB); //(0x00000000) + debug.printf("ADC0_SC2: %08x\r\n",ADC0_SC2); //(0x00000044) + debug.printf("ADC0_SC3: %08x\r\n\n",ADC0_SC3); //(0x00000000) + */ \ No newline at end of file