Dependencies:   mbed-dsp mbed

Fork of DSP_200kHz by Mazzeo Research Group

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