00001 /****************************************************************************** 00002 ** Copyright (C) 2007 Pablo Garcia 00003 ** 00004 ** This library is free software; you can redistribute it and/or 00005 ** modify it under the terms of the GNU Lesser General Public 00006 ** License as published by the Free Software Foundation; either 00007 ** version 2.1 of the License, or (at your option) any later version. 00008 00009 ** This library is distributed in the hope that it will be useful, 00010 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 ** Lesser General Public License for more details. 00013 00014 ** You should have received a copy of the GNU Lesser General Public 00015 ** License along with this library; if not, write to the Free Software 00016 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00017 **********************************************************************1********/ 00018 00019 // ---------------------------------------------------------------------------- 00020 // Includes 00021 // ---------------------------------------------------------------------------- 00022 #include "adc.h" 00023 #include "cpu.h" 00024 00025 //----------------------------------------------------------------------------- 00026 // Define 00027 //----------------------------------------------------------------------------- 00028 #define ADC_usDELAY 5000L 00029 00030 struct ADConfiguration adConfiguration; 00031 00034 static inline void CalculateADClocks(_iq fAD, Uint16 tSH, volatile Uint16* adcCLKPS, 00035 volatile Uint16* cps, volatile Uint16* acq_ps) 00036 { 00037 _iq hspCLKinMhz = HspCLKInMhz(); 00038 _iq adcCLK; 00039 *cps = 0; 00040 *adcCLKPS = hspCLKinMhz/fAD >> 1; 00041 if ((*adcCLKPS) > 15){ 00042 *cps = 1; 00043 *adcCLKPS = (*adcCLKPS) >> 1; 00044 } 00045 if((*adcCLKPS) > 0) 00046 adcCLK = hspCLKinMhz/((*adcCLKPS)*(*cps + 1)<<1); 00047 else 00048 adcCLK = hspCLKinMhz/(*cps + 1); 00049 //adcCLK = *adcCLKPS > 0 ? hspCLKinMhz/((*adcCLKPS)*(*cps + 1)<<1) : hspCLKinMhz/(*cps + 1); 00050 *acq_ps = (Uint16)(_IQtoF(_IQmpy(_IQ(tSH)/1000,adcCLK))); 00051 } 00052 00053 //----------------------------------------------------------------------------- 00054 00055 void ConfigureAD(void(*interruptFCN)(void), _iq fAD, Uint16 tSH, 00056 SEQ_MODE seqMode, SAMPLING_MODE samplingMode, SOC_MODE socMode, 00057 Uint16 offtrim) 00058 { 00059 int chCnt; 00060 volatile Uint16 adcCLKPS, cps, acq_ps; 00061 InitAD(); 00062 // configure AD clocking 00063 // @DOC SPRU716B, pp 28, 34, 38 00064 // AD prescaler 00065 // 0 ADCLK = HSPCLK/(CPS + 1) 00066 // ADCCLKPS(!=0) ADCLK = HSPCLK/[2*ADCCLKPS*(CPS + 1)] 00067 CalculateADClocks(fAD, tSH, &adcCLKPS, &cps, &acq_ps); 00068 00069 AdcRegs.ADCTRL3.bit.ADCCLKPS=adcCLKPS;//2; // (4 Juama) // (0 - 0xF) 00070 AdcRegs.ADCTRL1.bit.CPS=cps;//1; 00071 // Acquisition window size ((ACQ_PS+1)*ADCLKK --AD clock) 00072 AdcRegs.ADCTRL1.bit.ACQ_PS=acq_ps;//0x7; //(0xF Juamma); 00073 // channel list initialization and clear 00074 AdcRegs.ADCCHSELSEQ1.all = 0; 00075 AdcRegs.ADCCHSELSEQ2.all = 0; 00076 AdcRegs.ADCCHSELSEQ3.all = 0; 00077 AdcRegs.ADCCHSELSEQ4.all = 0; 00078 AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 0; 00079 AdcRegs.ADCMAXCONV.bit.MAX_CONV2 = 0; 00080 // cascade/dual sequence 00081 AdcRegs.ADCTRL1.bit.SEQ_CASC = seqMode; 00082 // simultaneous/sequential 00083 AdcRegs.ADCTRL3.bit.SMODE_SEL = samplingMode; 00084 // configure EOC interrupts 00085 // enable interrupt if ISR is specified 00086 if(interruptFCN != 0){ 00087 EALLOW; 00088 PieVectTable.ADCINT = interruptFCN; 00089 EDIS; 00090 PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // Enable ADCINT in PIE 00091 IER |= M_INT1; // Enable CPU Interrupt 1 00092 } 00093 // configure SOC event 00094 AdcRegs.ADCTRL2.all |= socMode; 00095 //AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; 00096 //AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; 00097 // Enable SEQ1 interrupt (every EOS) 00098 // AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // (not needed) 00099 // Adquisition hardware registers 00100 AdcRegs.ADCREFSEL.bit.REF_SEL=0; // Internal reference selected 00101 AdcRegs.ADCOFFTRIM.bit.OFFSET_TRIM = offtrim; 00102 00103 // initialize AD conf structure 00104 adConfiguration.fAD = fAD; 00105 adConfiguration.tSH = tSH; 00106 adConfiguration.selSeqPtr = &AdcRegs.ADCCHSELSEQ1.all; 00107 *(adConfiguration.selSeqPtr) = 0; 00108 adConfiguration.max_ch = 0; 00109 adConfiguration.trigger=0; 00110 for (chCnt=0; chCnt < MAX_CH; chCnt++) 00111 adConfiguration.convChannel[chCnt] = 0; 00112 00113 } 00114 00115 // ---------------------------------------------------------------------------- 00116 00117 /*----------------------------------------------------------------------------- 00118 Add a channel to the channel list. 00119 00120 Parameters: 00121 - input: ADCINPUT that is sampled 00122 - channel: channel select in the converter list 00123 - offset: allows to specify an offset between the bits value and the units 00124 - gain: gain between the bits value and the units one 00125 val = gain*bits+offset 00126 ------------------------------------------------------------------------------*/ 00127 void AddChannel(Uint16 input, Uint16 canal, _iq offset, _iq gain) 00128 { 00129 if(adConfiguration.max_ch == MAX_CH-1) 00130 return; 00131 // add channel to channel list 00132 adConfiguration.chlChannels[input] = canal*(SIMULTANEOUS_MODE+1) + 00133 adConfiguration.convChannel[canal]++; 00134 // configure channel offset and gain 00135 adConfiguration.chlGains[input] = gain; 00136 adConfiguration.chlOffsets[input] = offset; 00137 // set default polarity (bipolar --> 2048) 00138 adConfiguration.chlPolarity[input] = AD_ORIGIN; 00139 // get the appropiate sequence number 00140 if( (AdcRegs.ADCTRL3.bit.SMODE_SEL == SIMULTANEOUS_MODE) && input >=ADCINB0 ) 00141 input = input%ADCINB0; 00142 // add input to ADCCHSELSEQX 00143 // @DOC SPRU716B --> pag. 21 00144 (*(adConfiguration.selSeqPtr+canal/4)) |= ( (input & 0x000F) << (canal*4)%16 ); 00145 // specify max number of conversions. It depends on sequence configuration 00146 if(adConfiguration.max_ch < canal){ 00147 adConfiguration.max_ch = canal; 00148 AdcRegs.ADCMAXCONV.all = adConfiguration.max_ch;// | (adConfiguration.max_ch << 4); 00149 } 00150 } 00151 00152 // ---------------------------------------------------------------------------- 00153 00154 void AddUnipolarChannel(Uint16 input, Uint16 channel, _iq offset, _iq gain) 00155 { 00156 AddChannel(input, channel, offset, gain); 00157 adConfiguration.chlPolarity[input] = 0; 00158 00159 } 00160 00161 // ---------------------------------------------------------------------------- 00162 00163 void InitAD(void) 00164 { 00165 InitADPeripheralClocks(); 00166 // To powerup the ADC the ADCENCLK bit should be set first to enable 00167 // clocks, followed by powering up the bandgap, reference circuitry, and ADC core. 00168 // Before the first conversion is performed a 5ms delay must be observed 00169 // after power up to give all analog circuits time to power up and settle 00170 AdcRegs.ADCTRL3.all = 0x00E0; // Power up bandgap/reference/ADC circuits 00171 DELAY_US(ADC_usDELAY); // Delay before converting ADC channels 00172 } 00173 00174 // ---------------------------------------------------------------------------- 00175 00176 void InitADPeripheralClocks(void) 00177 { 00178 EALLOW; 00179 SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1; // ADC 00180 EDIS; 00181 } 00182 00183 // ---------------------------------------------------------------------------- 00184 00185 00186 //----------------------------------------------------------------------------- 00187 // End Of File 00188 //-----------------------------------------------------------------------------