SAMV71 Xplained Ultra Software Package 1.5

afec.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /** \addtogroup AFEC_module Working with AFE
00031  * \ingroup peripherals_module
00032  * The AFE driver provides the interface to configure and use the AFE peripheral.
00033  * \n
00034  *
00035  * It converts the analog input to digital format. The converted result could be
00036  * 12bit or 10bit. The AFE supports up to 16 analog lines.
00037  *
00038  * To Enable a AFE conversion,the user has to follow these few steps:
00039  * <ul>
00040  * <li> Select an appropriate reference voltage on ADVREF   </li>
00041  * <li> Configure the AFE according to its requirements and special needs,which
00042  * could be  broken down into several parts:
00043  * -#   Select the resolution by setting or clearing AFEC_MR_LOWRES bit in
00044  *      AFEC_MR (Mode Register)
00045  * -#   Set AFE clock by setting AFEC_MR_PRESCAL bits in AFEC_MR, the clock is
00046  *      calculated with AFEClock = MCK / ((PRESCAL+1) * 2)
00047  * -#   Set Startup Time,Tracking Clock cycles and Transfer Clock respectively
00048  *      in AFEC_MR.
00049  </li>
00050  * <li> Start conversion by setting AFEC_CR_START in AFEC_CR. </li>
00051  * </ul>
00052  *
00053  * For more accurate information, please look at the AFE section of the
00054  * Datasheet.
00055  *
00056  * Related files :\n
00057  * \ref afec.c\n
00058  * \ref afec.h\n
00059  * \ref afe_dma.c\n
00060  * \ref afe_dma.h\n
00061  */
00062 /*@{*/
00063 /*@}*/
00064 /**
00065  * \file
00066  *
00067  * Implementation of Analog-to-Digital Converter (AFE).
00068  *
00069  */
00070 /*----------------------------------------------------------------------------
00071  *        Headers
00072  *----------------------------------------------------------------------------*/
00073 
00074 #include "chip.h"
00075 
00076 
00077 /*----------------------------------------------------------------------------
00078  *        Local variables
00079  *----------------------------------------------------------------------------*/
00080 
00081 /** Current working clock */
00082 static uint32_t dwAFEClock = 0;
00083 
00084 /*----------------------------------------------------------------------------
00085  *        Exported functions
00086  *----------------------------------------------------------------------------*/
00087 
00088 /**
00089  * \brief Initialize the AFE controller
00090  *
00091  * \param pAFE Pointer to an AFE instance.
00092  * \param dwID AFE Index
00093  */
00094 extern void AFEC_Initialize(Afec *pAFE, uint32_t dwID)
00095 {
00096     /* Enable peripheral clock*/
00097     PMC_EnablePeripheral(dwID);
00098 
00099     /*  Reset the controller */
00100     pAFE->AFEC_CR = AFEC_CR_SWRST;
00101 
00102     /* Reset Mode Register */
00103     pAFE->AFEC_MR = 0;
00104 }
00105 
00106 /**
00107  * \brief Set AFE clock.
00108  *
00109  * \param pAFE Pointer to an AFE instance.
00110  * \param dwPres prescale value
00111  * \param dwMck Board MCK (Hz)
00112  *
00113  * \return AFE clock
00114  */
00115 
00116 extern uint32_t AFEC_SetClock(Afec *pAFE, uint32_t dwClk, uint32_t dwMck)
00117 {
00118     uint32_t dwPres, dwMr;
00119     /* Formula for PRESCAL is:
00120        PRESCAL = peripheral clock/ fAFE Clock - 1 */
00121 
00122     dwPres = (dwMck) / (dwClk) - 1;
00123     dwMr = AFEC_MR_PRESCAL(dwPres);
00124 
00125     if (dwMr == 0) return 0;
00126 
00127     dwMr |= (pAFE->AFEC_MR & ~AFEC_MR_PRESCAL_Msk);
00128     pAFE->AFEC_MR = dwMr;
00129     dwAFEClock = dwMck / (dwPres + 1);
00130     return dwAFEClock;
00131 }
00132 
00133 /**
00134  * \brief Set AFE timing.
00135  *
00136  * \param pAFE Pointer to an AFE instance.
00137  * \param dwStartup startup value
00138  * \param dwTracking tracking value
00139  * \param dwSettling settling value
00140  */
00141 extern void AFEC_SetTiming(Afec *pAFE, uint32_t dwStartup, uint32_t dwTracking,
00142                             uint32_t dwSettling)
00143 {
00144     uint32_t dwMr;
00145 
00146     dwMr = pAFE->AFEC_MR;
00147     dwMr &= (~AFEC_MR_STARTUP_Msk) & (~AFEC_MR_TRACKTIM_Msk) &
00148             (~AFEC_MR_SETTLING_Msk);
00149 
00150     /* Formula:
00151      *     Startup  Time = startup value / AFEClock
00152      *     Transfer Time = (TRANSFER * 2 + 3) / AFEClock
00153      *     Tracking Time = (TRACKTIM + 1) / AFEClock
00154      *     Settling Time = settling value / AFEClock
00155      */
00156     dwMr |= dwStartup | dwTracking | dwSettling;
00157     pAFE->AFEC_MR |= dwMr;
00158 }
00159 
00160 /**
00161  * \brief Set AFE trigger.
00162  *
00163  * \param pAFE Pointer to an AFE instance.
00164  * \param dwTrgSel Trigger selection
00165  */
00166 extern void AFEC_SetTrigger(Afec *pAFE, uint32_t dwTrgSel)
00167 {
00168     uint32_t dwMr;
00169 
00170     dwMr = pAFE->AFEC_MR;
00171     dwMr &= ~AFEC_MR_TRGSEL_Msk;
00172     dwMr |= dwTrgSel;
00173     pAFE->AFEC_MR |= dwMr;
00174 }
00175 
00176 
00177 /**
00178  * \brief Enable/Disable sleep mode.
00179  *
00180  * \param pAFE Pointer to an AFE instance.
00181  * \param bEnDis Enable/Disable sleep mode.
00182  */
00183 extern void AFEC_SetSleepMode(Afec *pAFE, uint8_t bEnDis)
00184 {
00185     if (bEnDis)
00186         pAFE->AFEC_MR |=  AFEC_MR_SLEEP;
00187     else
00188         pAFE->AFEC_MR &= ~AFEC_MR_SLEEP;
00189 }
00190 
00191 /**
00192  * \brief Enable/Disable fast wake up.
00193  *
00194  * \param pAFE Pointer to an AFE instance.
00195  * \param bEnDis Enable/Disable fast wake up in sleep mode.
00196  */
00197 extern void AFEC_SetFastWakeup(Afec *pAFE, uint8_t bEnDis)
00198 {
00199     if (bEnDis)
00200         pAFE->AFEC_MR |=  AFEC_MR_FWUP;
00201     else
00202         pAFE->AFEC_MR &= ~AFEC_MR_FWUP;
00203 }
00204 
00205 /**
00206  * \brief Enable/Disable sequence mode.
00207  *
00208  * \param pAFE  Pointer to an AFE instance.
00209  * \param bEnDis Enable/Disable sequence mode.
00210  */
00211 extern void AFEC_SetSequenceMode(Afec *pAFE, uint8_t bEnDis)
00212 {
00213     if (bEnDis) {
00214         /* User Sequence Mode: The sequence respects what is defined in
00215            AFEC_SEQR1 and AFEC_SEQR2 */
00216         pAFE->AFEC_MR |=  AFEC_MR_USEQ;
00217     } else {
00218         /* Normal Mode: The controller converts channels in a simple
00219         numeric order. */
00220         pAFE->AFEC_MR &= ~AFEC_MR_USEQ;
00221     }
00222 }
00223 
00224 /**
00225  * \brief Set channel sequence.
00226  *
00227  * \param pAFE   Pointer to an AFE instance.
00228  * \param dwSEQ1 Sequence 1 ~ 8  channel number.
00229  * \param dwSEQ2 Sequence 9 ~ 16 channel number.
00230  */
00231 extern void AFEC_SetSequence(Afec *pAFE, uint32_t dwSEQ1, uint32_t dwSEQ2)
00232 {
00233     pAFE->AFEC_SEQ1R = dwSEQ1;
00234     pAFE->AFEC_SEQ2R = dwSEQ2;
00235 }
00236 
00237 /**
00238  * \brief Set channel sequence by given channel list.
00239  *
00240  * \param pAFE    Pointer to an AFE instance.
00241  * \param ucChList Channel list.
00242  * \param ucNumCh  Number of channels in list.
00243  */
00244 extern void AFEC_SetSequenceByList(Afec *pAFE, uint8_t ucChList[],
00245                                     uint8_t ucNumCh)
00246 {
00247     uint8_t i;
00248     uint8_t ucShift;
00249 
00250     pAFE->AFEC_SEQ1R = 0;
00251 
00252     for (i = 0, ucShift = 0; i < 8; i ++, ucShift += 4) {
00253         if (i >= ucNumCh) return;
00254 
00255         pAFE->AFEC_SEQ1R |= ucChList[i] << ucShift;
00256 
00257     }
00258 
00259     pAFE->AFEC_SEQ2R = 0;
00260 
00261     for (ucShift = 0; i < 16; i ++, ucShift += 4) {
00262         if (i >= ucNumCh) return;
00263 
00264         pAFE->AFEC_SEQ2R |= ucChList[i] << ucShift;
00265     }
00266 }
00267 
00268 /**
00269  * \brief Set analog change.
00270  * IF enabled, it allows different analog settings for each channel,
00271  * otherwise, DIFF0, GAIN0 and OFF0 are used for all channels.
00272  *
00273  * \param pAFE   Pointer to an AFE instance.
00274  * \param bEnDis Enable/Disable.
00275  */
00276 extern void AFEC_SetAnalogChange(Afec *pAFE, uint8_t bEnDis)
00277 {
00278     if (bEnDis)
00279         pAFE->AFEC_MR |=  AFEC_MR_ONE;
00280     else
00281         pAFE->AFEC_MR &= ~AFEC_MR_ONE;
00282 }
00283 
00284 /**
00285  * \brief Set "TAG" mode, show channel number in last data or not.
00286  *
00287  * \param pAFE   Pointer to an AFE instance.
00288  * \param bEnDis Enable/Disable TAG value.
00289  */
00290 extern void AFEC_SetTagEnable(Afec *pAFE, uint8_t bEnDis)
00291 {
00292     if (bEnDis)
00293         pAFE->AFEC_EMR |=  AFEC_EMR_TAG;
00294     else
00295         pAFE->AFEC_EMR &= ~AFEC_EMR_TAG;
00296 }
00297 
00298 /**
00299  * \brief Set compare channel.
00300  *
00301  * \param pAFE Pointer to an AFE instance.
00302  * \param dwChannel channel number to be set,16 for all channels
00303  */
00304 extern void AFEC_SetCompareChannel(Afec *pAFE, uint32_t dwChannel)
00305 {
00306     assert(dwChannel <= 16);
00307 
00308     if (dwChannel < 16) {
00309         pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPALL);
00310         pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPSEL_Msk);
00311         pAFE->AFEC_EMR |= (dwChannel << AFEC_EMR_CMPSEL_Pos);
00312     } else
00313         pAFE->AFEC_EMR |= AFEC_EMR_CMPALL;
00314 }
00315 
00316 /**
00317  * \brief Set compare mode.
00318  *
00319  * \param pAFE Pointer to an AFE instance.
00320  * \param dwMode compare mode
00321  */
00322 extern void AFEC_SetCompareMode(Afec *pAFE, uint32_t dwMode)
00323 {
00324     pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPMODE_Msk);
00325     pAFE->AFEC_EMR |= (dwMode & AFEC_EMR_CMPMODE_Msk);
00326 }
00327 
00328 /**
00329  * \brief Set comparison window.
00330  *
00331  * \param pAFE Pointer to an AFE instance.
00332  * \param dwHi_Lo Comparison Window
00333  */
00334 extern void AFEC_SetComparisonWindow(Afec *pAFE, uint32_t dwHi_Lo)
00335 {
00336     pAFE->AFEC_CWR = dwHi_Lo;
00337 }
00338 
00339 /**
00340  * \brief Return the Channel Converted Data
00341  *
00342  * \param pAFE Pointer to an AFE instance.
00343  * \param dwChannel channel to get converted value
00344  */
00345 extern uint32_t AFEC_GetConvertedData(Afec *pAFE, uint32_t dwChannel)
00346 {
00347     uint32_t dwData = 0;
00348     assert(dwChannel < 12);
00349     pAFE->AFEC_CSELR = dwChannel;
00350     dwData = pAFE->AFEC_CDR;
00351 
00352     return dwData;
00353 }
00354 
00355 
00356 /**
00357  * Sets the AFE startup time.
00358  * \param pAFE  Pointer to an AFE instance.
00359  * \param dwUs  Startup time in uS.
00360  */
00361 void AFEC_SetStartupTime(Afec *pAFE, uint32_t dwUs)
00362 {
00363     uint32_t dwStart;
00364     uint32_t dwMr;
00365 
00366     if (dwAFEClock == 0) return;
00367 
00368     /* Formula for STARTUP is:
00369        STARTUP = (time x AFECLK) / (1000000) - 1
00370        Division multiplied by 10 for higher precision */
00371 
00372     dwStart = (dwUs * dwAFEClock) / (100000);
00373 
00374     if (dwStart % 10) dwStart /= 10;
00375     else {
00376         dwStart /= 10;
00377 
00378         if (dwStart) dwStart --;
00379     }
00380 
00381     if      (dwStart >  896) dwMr = AFEC_MR_STARTUP_SUT960;
00382     else if (dwStart >  832) dwMr = AFEC_MR_STARTUP_SUT896;
00383     else if (dwStart >  768) dwMr = AFEC_MR_STARTUP_SUT832;
00384     else if (dwStart >  704) dwMr = AFEC_MR_STARTUP_SUT768;
00385     else if (dwStart >  640) dwMr = AFEC_MR_STARTUP_SUT704;
00386     else if (dwStart >  576) dwMr = AFEC_MR_STARTUP_SUT640;
00387     else if (dwStart >  512) dwMr = AFEC_MR_STARTUP_SUT576;
00388     else if (dwStart >  112) dwMr = AFEC_MR_STARTUP_SUT512;
00389     else if (dwStart >   96) dwMr = AFEC_MR_STARTUP_SUT112;
00390     else if (dwStart >   80) dwMr = AFEC_MR_STARTUP_SUT96;
00391     else if (dwStart >   64) dwMr = AFEC_MR_STARTUP_SUT80;
00392     else if (dwStart >   24) dwMr = AFEC_MR_STARTUP_SUT64;
00393     else if (dwStart >   16) dwMr = AFEC_MR_STARTUP_SUT24;
00394     else if (dwStart >    8) dwMr = AFEC_MR_STARTUP_SUT16;
00395     else if (dwStart >    0) dwMr = AFEC_MR_STARTUP_SUT8;
00396     else                     dwMr = AFEC_MR_STARTUP_SUT0;
00397 
00398     dwMr |= pAFE->AFEC_MR & ~AFEC_MR_STARTUP_Msk;
00399     pAFE->AFEC_MR = dwMr;
00400 }
00401 
00402 
00403 /**
00404  * Set AFE tracking time
00405  * \param pAFE  Pointer to an AFE instance.
00406  * \param dwNs  Tracking time in nS.
00407  */
00408 void AFEC_SetTrackingTime(Afec *pAFE, uint32_t dwNs)
00409 {
00410     uint32_t dwShtim;
00411     uint32_t dwMr;
00412 
00413     if (dwAFEClock == 0) return;
00414 
00415     /* Formula for SHTIM is:
00416        SHTIM = (time x AFECLK) / (1000000000) - 1
00417        Since 1 billion is close to the maximum value for an integer, we first
00418        divide AFECLK by 1000 to avoid an overflow */
00419     dwShtim = (dwNs * (dwAFEClock / 1000)) / 100000;
00420 
00421     if (dwShtim % 10) dwShtim /= 10;
00422     else {
00423         dwShtim /= 10;
00424 
00425         if (dwShtim) dwShtim --;
00426     }
00427 
00428     dwMr  = AFEC_MR_TRACKTIM(dwShtim);
00429     dwMr |= pAFE->AFEC_MR & ~AFEC_MR_TRACKTIM_Msk;
00430     pAFE->AFEC_MR = dwMr;
00431 }
00432 
00433 /**
00434  * \brief Set analog offset to be used for channel CSEL.
00435  *
00436  * \param afec  Base address of the AFEC.
00437  * \param dwChannel AFEC channel number.
00438  * \param aoffset  Analog offset value.
00439  */
00440 void AFEC_SetAnalogOffset(Afec *pAFE, uint32_t dwChannel, uint32_t aoffset)
00441 {
00442     assert(dwChannel < 12);
00443     pAFE->AFEC_CSELR = dwChannel;
00444     pAFE->AFEC_COCR = (aoffset & AFEC_COCR_AOFF_Msk);;
00445 }
00446 
00447 /**
00448  * \brief Set analog offset to be used for channel CSEL.
00449  *
00450  * \param afec  Base address of the AFEC.
00451  * \param control  Analog control value.
00452  */
00453 void AFEC_SetAnalogControl(Afec *pAFE, uint32_t control)
00454 {
00455     pAFE->AFEC_ACR = control;
00456 }
00457 
00458 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines