Jared Baxter / Mbed 2 deprecated Impedance_Fast_Circuitry_print_V_I

Dependencies:   mbed-dsp mbed

Fork of Impedance_Fast_Circuitry by Jared Baxter

adc.cpp

Committer:
timmey9
Date:
2015-01-31
Revision:
46:a015ebf4663b
Parent:
45:d591d138cdeb
Child:
47:54fafe151669

File content as of revision 46:a015ebf4663b:

#include "adc.h"

/*
TODO:   remove interrupt handlers
        add calibration
        change clock speed
        
Possible causes of the triggering problem:
        more multiplexing somehow?
        does the ADC interrupt need to be enabled?
        clock speed?
        hardware/software trigger
        channel A or B?
        single vs continuous mode
        does asynchronous clock have to do with this?
*/
DigitalOut toggle1(PTC16);
DigitalOut green(LED_GREEN);
DigitalOut red(LED_RED);
Serial debug(USBTX,USBRX);

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);
    SIM_SOPT7 = SIM_SOPT7_ADC1TRGSEL(0);
    
    // 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    
    
    // 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_SC1A = 0; // clear register
    ADC0_SC1A &= ~ADC_SC1_DIFF_MASK; // select single-ended mode
    ADC0_SC1A |= ADC_SC1_AIEN_MASK;  // enable interrupt (for debugging)
    ADC0_SC1A |= 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(13);   // select channel 13
    
    // Check if ADC is finished initializing  TODO:  This part doesn't seem right, but I did it according to 871
    while( (ADC0_SC1A&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;
    
    
    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)
    
    // Enable the ISR vector
    NVIC_SetVector(ADC0_IRQn, (uint32_t)&ADC0_IRQHandler);
    NVIC_EnableIRQ(ADC0_IRQn);
}

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
    ADC1_SC2 &= ~ADC_SC2_ADTRG_MASK;
    
    // start ADC conversion (SW trigger)
    ADC0_SC1A |= ADC_SC1_ADCH(13);   // write to SC1A causing a trigger
    ADC1_SC1A |= ADC_SC1_ADCH(14);   // write to SC1A causing a trigger
    //BW_ADC_SC1n_ADCH(0, 0, kAdcChannel13); // trigger the ADC
}

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; 
}

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_SC1A |= ADC_SC1_ADCH(13);   // write to SC1A causing a trigger
    ADC1_SC1A |= ADC_SC1_ADCH(14);   // write to SC1A causing a trigger
}

void ADC0_IRQHandler() {
    toggle1 = !toggle1;
}