SAMV71 Xplained Ultra Software Package 1.3

afec.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2014, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
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     if (dwMr == 0) return 0;
00125 
00126     dwMr |= (pAFE->AFEC_MR & ~AFEC_MR_PRESCAL_Msk);
00127     pAFE->AFEC_MR = dwMr;
00128     dwAFEClock = dwMck / (dwPres + 1);
00129     return dwAFEClock;
00130 }
00131 
00132 /**
00133  * \brief Set AFE timing.
00134  *
00135  * \param pAFE Pointer to an AFE instance.
00136  * \param dwStartup startup value
00137  * \param dwTracking tracking value
00138  * \param dwSettling settling value
00139  */
00140 extern void AFEC_SetTiming( Afec* pAFE, uint32_t dwStartup, uint32_t dwTracking, 
00141                         uint32_t dwSettling )
00142 {
00143     uint32_t dwMr;
00144 
00145     dwMr = pAFE->AFEC_MR;
00146     dwMr &= (~AFEC_MR_STARTUP_Msk) & (~AFEC_MR_TRACKTIM_Msk) & (~AFEC_MR_SETTLING_Msk);
00147 
00148     /* Formula:
00149      *     Startup  Time = startup value / AFEClock
00150      *     Transfer Time = (TRANSFER * 2 + 3) / AFEClock
00151      *     Tracking Time = (TRACKTIM + 1) / AFEClock
00152      *     Settling Time = settling value / AFEClock
00153      */
00154     dwMr |= dwStartup | dwTracking | dwSettling;
00155     pAFE->AFEC_MR |= dwMr;
00156 }
00157 
00158 /**
00159  * \brief Set AFE trigger.
00160  *
00161  * \param pAFE Pointer to an AFE instance.
00162  * \param dwTrgSel Trigger selection
00163  */
00164 extern void AFEC_SetTrigger( Afec* pAFE, uint32_t dwTrgSel )
00165 {
00166     uint32_t dwMr;
00167 
00168     dwMr = pAFE->AFEC_MR;
00169     dwMr &= ~AFEC_MR_TRGSEL_Msk;
00170     dwMr |= dwTrgSel;
00171     pAFE->AFEC_MR |= dwMr;
00172 }
00173 
00174 
00175 /**
00176  * \brief Enable/Disable sleep mode.
00177  *
00178  * \param pAFE Pointer to an AFE instance.
00179  * \param bEnDis Enable/Disable sleep mode.
00180  */
00181 extern void AFEC_SetSleepMode( Afec *pAFE, uint8_t bEnDis )
00182 {
00183     if ( bEnDis ) {
00184         pAFE->AFEC_MR |=  AFEC_MR_SLEEP;
00185     } else {
00186         pAFE->AFEC_MR &= ~AFEC_MR_SLEEP;
00187     }
00188 }
00189 
00190 /**
00191  * \brief Enable/Disable fast wake up.
00192  *
00193  * \param pAFE Pointer to an AFE instance.
00194  * \param bEnDis Enable/Disable fast wake up in sleep mode.
00195  */
00196 extern void AFEC_SetFastWakeup( Afec *pAFE, uint8_t bEnDis )
00197 {
00198     if ( bEnDis ) {
00199         pAFE->AFEC_MR |=  AFEC_MR_FWUP;
00200     } else {
00201         pAFE->AFEC_MR &= ~AFEC_MR_FWUP;
00202     }
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[], uint8_t ucNumCh )
00245 {
00246     uint8_t i;
00247     uint8_t ucShift;
00248 
00249     pAFE->AFEC_SEQ1R = 0;
00250     for (i = 0, ucShift = 0; i < 8; i ++, ucShift += 4) {
00251         if (i >= ucNumCh) return;
00252         pAFE->AFEC_SEQ1R |= ucChList[i] << ucShift;
00253 
00254     }
00255     pAFE->AFEC_SEQ2R = 0;
00256     for (ucShift = 0; i < 16; i ++, ucShift += 4)   {
00257         if (i >= ucNumCh) return;
00258         pAFE->AFEC_SEQ2R |= ucChList[i] << ucShift;
00259     }
00260 }
00261 
00262 /**
00263  * \brief Set analog change.
00264  * IF enabled, it allows different analog settings for each channel,
00265  * otherwise, DIFF0, GAIN0 and OFF0 are used for all channels.
00266  *
00267  * \param pAFE   Pointer to an AFE instance.
00268  * \param bEnDis Enable/Disable.
00269  */
00270 extern void AFEC_SetAnalogChange( Afec* pAFE, uint8_t bEnDis )
00271 {
00272     if ( bEnDis ) {
00273         pAFE->AFEC_MR |=  AFEC_MR_ONE;
00274     } else {
00275         pAFE->AFEC_MR &= ~AFEC_MR_ONE;
00276     }
00277 }
00278 
00279 /**
00280  * \brief Set "TAG" mode, show channel number in last data or not.
00281  *
00282  * \param pAFE   Pointer to an AFE instance.
00283  * \param bEnDis Enable/Disable TAG value.
00284  */
00285 extern void AFEC_SetTagEnable( Afec *pAFE, uint8_t bEnDis )
00286 {
00287     if ( bEnDis ) {
00288         pAFE->AFEC_EMR |=  AFEC_EMR_TAG;
00289     } else {
00290         pAFE->AFEC_EMR &= ~AFEC_EMR_TAG;
00291     }
00292 }
00293 
00294 /**
00295  * \brief Set compare channel.
00296  *
00297  * \param pAFE Pointer to an AFE instance.
00298  * \param dwChannel channel number to be set,16 for all channels
00299  */
00300 extern void AFEC_SetCompareChannel( Afec* pAFE, uint32_t dwChannel )
00301 {
00302     assert( dwChannel <= 16 ) ;
00303 
00304     if ( dwChannel < 16 ) {
00305         pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPALL);
00306         pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPSEL_Msk);
00307         pAFE->AFEC_EMR |= (dwChannel << AFEC_EMR_CMPSEL_Pos);
00308     } else {
00309         pAFE->AFEC_EMR |= AFEC_EMR_CMPALL;
00310     }
00311 }
00312 
00313 /**
00314  * \brief Set compare mode.
00315  *
00316  * \param pAFE Pointer to an AFE instance.
00317  * \param dwMode compare mode
00318  */
00319 extern void AFEC_SetCompareMode( Afec* pAFE, uint32_t dwMode )
00320 {
00321     pAFE->AFEC_EMR &= ~(AFEC_EMR_CMPMODE_Msk);
00322     pAFE->AFEC_EMR |= (dwMode & AFEC_EMR_CMPMODE_Msk);
00323 }
00324 
00325 /**
00326  * \brief Set comparison window.
00327  *
00328  * \param pAFE Pointer to an AFE instance.
00329  * \param dwHi_Lo Comparison Window
00330  */
00331 extern void AFEC_SetComparisonWindow( Afec* pAFE, uint32_t dwHi_Lo )
00332 {
00333     pAFE->AFEC_CWR = dwHi_Lo ;
00334 }
00335 
00336 /**
00337  * \brief Return the Channel Converted Data
00338  *
00339  * \param pAFE Pointer to an AFE instance.
00340  * \param dwChannel channel to get converted value
00341  */
00342 extern uint32_t AFEC_GetConvertedData( Afec* pAFE, uint32_t dwChannel )
00343 {
00344     uint32_t dwData = 0;
00345     assert( dwChannel < 12 ) ;
00346     pAFE->AFEC_CSELR = dwChannel;
00347     dwData = pAFE->AFEC_CDR;
00348 
00349     return dwData ;
00350 }
00351 
00352 
00353 /**
00354  * Sets the AFE startup time.
00355  * \param pAFE  Pointer to an AFE instance.
00356  * \param dwUs  Startup time in uS.
00357  */
00358 void AFEC_SetStartupTime( Afec *pAFE, uint32_t dwUs )
00359 {
00360     uint32_t dwStart;
00361     uint32_t dwMr;
00362 
00363     if (dwAFEClock == 0) return;
00364     /* Formula for STARTUP is:
00365        STARTUP = (time x AFECLK) / (1000000) - 1
00366        Division multiplied by 10 for higher precision */
00367 
00368     dwStart = (dwUs * dwAFEClock) / (100000);
00369     if (dwStart % 10) dwStart /= 10;
00370     else
00371     {
00372         dwStart /= 10;
00373         if (dwStart) dwStart --;
00374     }
00375     if      (dwStart >  896) dwMr = AFEC_MR_STARTUP_SUT960;
00376     else if (dwStart >  832) dwMr = AFEC_MR_STARTUP_SUT896;
00377     else if (dwStart >  768) dwMr = AFEC_MR_STARTUP_SUT832;
00378     else if (dwStart >  704) dwMr = AFEC_MR_STARTUP_SUT768;
00379     else if (dwStart >  640) dwMr = AFEC_MR_STARTUP_SUT704;
00380     else if (dwStart >  576) dwMr = AFEC_MR_STARTUP_SUT640;
00381     else if (dwStart >  512) dwMr = AFEC_MR_STARTUP_SUT576;
00382     else if (dwStart >  112) dwMr = AFEC_MR_STARTUP_SUT512;
00383     else if (dwStart >   96) dwMr = AFEC_MR_STARTUP_SUT112;
00384     else if (dwStart >   80) dwMr = AFEC_MR_STARTUP_SUT96;
00385     else if (dwStart >   64) dwMr = AFEC_MR_STARTUP_SUT80;
00386     else if (dwStart >   24) dwMr = AFEC_MR_STARTUP_SUT64;
00387     else if (dwStart >   16) dwMr = AFEC_MR_STARTUP_SUT24;
00388     else if (dwStart >    8) dwMr = AFEC_MR_STARTUP_SUT16;
00389     else if (dwStart >    0) dwMr = AFEC_MR_STARTUP_SUT8;
00390     else                     dwMr = AFEC_MR_STARTUP_SUT0;
00391 
00392     dwMr |= pAFE->AFEC_MR & ~AFEC_MR_STARTUP_Msk;
00393     pAFE->AFEC_MR = dwMr;
00394 }
00395 
00396 
00397 /**
00398  * Set AFE tracking time
00399  * \param pAFE  Pointer to an AFE instance.
00400  * \param dwNs  Tracking time in nS.
00401  */
00402 void AFEC_SetTrackingTime( Afec *pAFE, uint32_t dwNs )
00403 {
00404     uint32_t dwShtim;
00405     uint32_t dwMr;
00406 
00407     if (dwAFEClock == 0) return;
00408     /* Formula for SHTIM is:
00409        SHTIM = (time x AFECLK) / (1000000000) - 1
00410        Since 1 billion is close to the maximum value for an integer, we first
00411        divide AFECLK by 1000 to avoid an overflow */
00412     dwShtim = (dwNs * (dwAFEClock / 1000)) / 100000;
00413     if (dwShtim % 10) dwShtim /= 10;
00414     else
00415     {
00416         dwShtim /= 10;
00417         if (dwShtim) dwShtim --;
00418     }
00419     dwMr  = AFEC_MR_TRACKTIM(dwShtim);
00420     dwMr |= pAFE->AFEC_MR & ~AFEC_MR_TRACKTIM_Msk;
00421     pAFE->AFEC_MR = dwMr;
00422 }
00423 
00424 /**
00425  * \brief Set analog offset to be used for channel CSEL.
00426  *
00427  * \param afec  Base address of the AFEC.
00428  * \param dwChannel AFEC channel number.
00429  * \param aoffset  Analog offset value.
00430  */
00431 void AFEC_SetAnalogOffset( Afec *pAFE, uint32_t dwChannel,uint32_t aoffset )
00432 {
00433     assert( dwChannel < 12 ) ;
00434     pAFE->AFEC_CSELR = dwChannel;
00435     pAFE->AFEC_COCR = (aoffset & AFEC_COCR_AOFF_Msk);;
00436 }
00437 
00438 /**
00439  * \brief Set analog offset to be used for channel CSEL.
00440  *
00441  * \param afec  Base address of the AFEC.
00442  * \param control  Analog control value.
00443  */
00444 void AFEC_SetAnalogControl( Afec *pAFE, uint32_t control)
00445 {
00446     pAFE->AFEC_ACR = control;
00447 }
00448 
00449 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines