adc.c

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  *  \file   adc.c
00003  *
00004  *  \brief  This file provides all the functionality provided by ADC driver  
00005  *          module of Freescale MPC563 power-pc MCU
00006  *
00007  *  \version    1.0A - Initial Draft
00008  *  \date       25 June 2010
00009  *
00010  *  \version    1.1A - Design changed to support run-time CCW addition and 
00011  *                      configuration
00012  *  \date       16 July 2010
00013  ******************************************************************************/
00014 
00015 /******************************************************************************
00016                                 Include Files
00017 ******************************************************************************/
00018 #include "mpc563.h"
00019 #include "m_common.h"
00020 #include "m_qadc64.h"
00021 #include "hal_types.h"
00022 #include "adc_Cfg.h"
00023 #include "adc.h"
00024 
00025 
00026 /******************************************************************************
00027                                 Type defines
00028 ******************************************************************************/
00029 /** \brief  This structure defines the data for each CCW and the 
00030             Application call-back function for that conversion */
00031 typedef struct
00032 {
00033     /** Call-back function to be called after this CCW conversion 
00034         is complete */
00035     ConvComplCB ApplCB;
00036     /** Upper two bits will be used for mask configuration and lower 
00037         10 bits for CCW Info */
00038     U16 u16CCW_Data;
00039 }QADC_CCW_Data;
00040 
00041 /** \brief  This structure holds all global data of teh ADC module */
00042  typedef struct
00043  {
00044     /** Provides ADC converter active status */
00045     QADC_Drv_Status DrvStatus;
00046     /** Application call-back function to be called after conversion 
00047         complete. Assign 'NULL', if no call-back needed */
00048     ConvComplCB fptrCB;
00049     /** Provides ccurrent mode of operation for ADC converter module */
00050     QADC_OpMode ConvModOpMode;
00051     QADC_CCW_Data CCW_Data[ADC_MOD_CCW_TOT];
00052     /** Provides the Queue-2 CCW begin position in the Queue */
00053     U8 u8Q2BeginPos;
00054  }QADC_Drv;
00055 
00056 /******************************************************************************
00057                             Global Variables
00058 ******************************************************************************/
00059 /** \var    self
00060  *  \brief  This global static variable holds ADC driver related data for each
00061             ADC converter module */
00062 static QADC_Drv self[ADC_TOT_MOD];
00063 
00064 /** \brief  This variable holds the address for register array of all the 
00065             ADC converters */
00066 struct QADC64_tag* const ModRegAddr[ADC_TOT_MOD] = 
00067                                     {QADC_MOD_A, QADC_MOD_B};
00068 /******************************************************************************
00069                             Function Prototypes
00070 ******************************************************************************/
00071  INTERRUPT void ADC_MOD_A_Q1_CI_ISR (void);
00072  INTERRUPT void ADC_MOD_A_Q2_CI_ISR (void);
00073  INTERRUPT void ADC_MOD_A_Q1_PI_ISR (void);
00074  INTERRUPT void ADC_MOD_A_Q2_PI_ISR (void);
00075  INTERRUPT void ADC_MOD_B_Q1_CI_ISR (void);
00076  INTERRUPT void ADC_MOD_B_Q2_CI_ISR (void);
00077  INTERRUPT void ADC_MOD_B_Q1_PI_ISR (void);
00078  INTERRUPT void ADC_MOD_B_Q2_PI_ISR (void);
00079 void QADC_CompletionIntCB(QADC_Module_ID ModID);
00080 void QADC_PauseIntCB(QADC_Module_ID ModID);
00081 /******************************************************************************
00082                             Function Definitions
00083 ******************************************************************************/
00084 
00085 /**************************************************************************//**
00086  *  \fn     QADC_DrvOpStatus ADC_Init(QADC_ConvModConf* ModConf)
00087  *
00088  *  \brief  This API will initialize a ADC converter module and start its
00089  *          operation
00090  *
00091  *  \param  ModConf - QADC converter module configuration data
00092  *  \return Driver operation status
00093  *          - ADC_OP_FAIL           - Module Initialization failed
00094  *          - ADC_OP_INVALID_MOD_ID - Invalid Module ID
00095  *          - ADC_OP_SUCCESS        - Module Initialized successfully
00096  *
00097  *  - The followwing actions will be taken on each ADC converetr module
00098  *  - If the Module ID is valid,
00099  *      - It resets the ADC converter module status to uninitialized mode
00100  *      - Get the register array address for the ADC converter module
00101  *      - Update the Operation mode, Register access level from application
00102  *      - Update Queue-1 and Queue-2 interrupt priority
00103  *      - Update external MUX selection, presclar clock high and low time,
00104  *        and External Triggering types for Queue-1 and Queue-2
00105  *      - Update Queue-1 operational mode and single scan option
00106  *      - Update Queue-2 operational mode, single scan option, operation
00107  *        resume type and Queue-2 begin location in the queue
00108  *      - Configure the ADC converter module to Initialized mode
00109  *****************************************************************************/
00110  QADC_DrvOpStatus ADC_Init(QADC_ConvModConf* ModConf)
00111  {
00112     QADC_DrvOpStatus RetVal = ADC_OP_FAIL;
00113     struct QADC64_tag* QADC_Reg;
00114     if(ModConf->ModID < ADC_TOT_MOD)
00115     {
00116         /* Set the default status of the driver */
00117         self[ModConf->ModID].DrvStatus = ADC_DRV_UNINIT;
00118         QADC_Reg = ModRegAddr[ModConf->ModID];
00119         /* If QADCMCR.STOP is set to enable stop mode/ low power mode,
00120             - The DDRQA, PORTQA/PORTQB, QACR0 are not reset and are read-only accessible
00121             - QACR1, QACR2, QASR0 and QASR1 are reset and are read-only accessible
00122             - QADCMCR and QADCINT are fully accessible and are not reset
00123             So before configuring the operation modes, the converter
00124             needs to be active
00125         */
00126         /* QADCMCR - Module Configuration Register settings */
00127         QADC_Reg->QADC64MCR.B.FRZ   = ADC_ENABLE_FREEZE;
00128         QADC_Reg->QADC64MCR.B.STOP  = ADC_DISABLE_STOP_MODE;
00129         QADC_Reg->QADC64MCR.B.SUPV  = ModConf->RegAcc;
00130         QADC_Reg->QADC64MCR.B.LOCK  = ADC_MODE_LOCK_DISABLE;
00131         QADC_Reg->QADC64MCR.B.FLIP  = ModConf->OpMode;
00132         self[ModConf->ModID].ConvModOpMode = ModConf->OpMode;
00133         QADC_Reg->QADC64MCR.B.LOCK  = ADC_MODE_LOCK_ENABLE;
00134 
00135         /* Configure ADC interrupts */
00136         QADC_Reg->QADC64INT.B.IRL1  = ModConf->u8Q1IntPrio;
00137         QADC_Reg->QADC64INT.B.IRL2  = ModConf->u8Q2IntPrio;
00138 
00139         /* Control register-0 settings */
00140         QADC_Reg->QACR0.B.EMUX = ModConf->ExtMux;
00141         QADC_Reg->QACR0.B.TRG = ModConf->ExtTrigType;
00142         QADC_Reg->QACR0.B.PSH = ModConf->u8PresclClkHighTime;
00143         QADC_Reg->QACR0.B.PSA = 0;
00144         QADC_Reg->QACR0.B.PSL = ModConf->u8PresclClkLowTime;
00145 
00146         /* Control register-1 settings */
00147         QADC_Reg->QACR1.B.CIE1  = ADC_Q1_COMP_INT_ENABLE;
00148         QADC_Reg->QACR1.B.PIE1  = ADC_Q1_PAUSE_INT_ENABLE;
00149         QADC_Reg->QACR1.B.MQ1   = ModConf->Q1_OpMode;
00150 
00151         /* Control register-2 settings */
00152         QADC_Reg->QACR2.B.CIE2  = ADC_Q2_COMP_INT_ENABLE;
00153         QADC_Reg->QACR2.B.PIE2  = ADC_Q2_PAUSE_INT_ENABLE;
00154         QADC_Reg->QACR2.B.MQ2   = ModConf->Q2_OpMode;
00155         QADC_Reg->QACR2.B.RESUME    = ModConf->Q2_ResumeType;
00156         QADC_Reg->QACR2.B.BQ2   = ModConf->u8Q2Begin;
00157         /* Keep the Queue-2 begin position for record */
00158         self[ModConf->ModID].u8Q2BeginPos = ModConf->u8Q2Begin;
00159 
00160         /* Update ADc converter module status */
00161         self[ModConf->ModID].DrvStatus  = ADC_DRV_INIT;
00162 
00163         RetVal = ADC_OP_SUCCESS;
00164     }/* if(ModID < ADC_TOT_MOD) */
00165     else
00166     {
00167         return ADC_OP_INVALID_MOD_ID;
00168     }
00169     return RetVal;
00170  }
00171 
00172 
00173 /**************************************************************************//**
00174  *  \fn     QADC_DrvOpStatus ADC_Read (QADC_CCW_ApplResultData* ResultData)
00175  *
00176  *  \brief  This API will read ADC conversion result value for the request
00177  *          client ID/ (CCW) as per the described result format
00178  *
00179  *  \param  ResultData - Structure to hold user request data to
00180  *                          read the ADC conversion result
00181  *
00182  *  \return Operation status
00183  *          - ADC_OP_FAIL           - Operation failed due to unknown reason
00184  *          - ADC_OP_SUCCESS        - Operation success
00185  *          - ADC_OP_UNSUPP_RD_FMT  - Unsupported result read format
00186  *          - ADC_OP_UNSUPP_STATE   - Current state of driver does not
00187  *                                      allow this action. The analog
00188  *                                      conversion for the drive should
00189  *                                      be active before calling this API
00190  *          - ADC_OP_INVALID_CCW_ID - Invalid CCW ID provided by the user
00191  *          - ADC_OP_INVALID_MOD_ID - Invalid ADC converter module ID
00192  *                                      provided by the user
00193  *          - ADC_OP_INVALID_DATA   - Invalid user Data
00194  *  \note   This API will only process the request, if the ADC
00195  *          conversion is started
00196  *****************************************************************************/
00197  QADC_DrvOpStatus ADC_Read (QADC_CCW_ApplResultData* ResultData)
00198  {
00199     QADC_DrvOpStatus RetVal = ADC_OP_FAIL;
00200 
00201     if(ResultData != NULL)
00202     {
00203         /* Check if the user provided ADC converter module ID is correct */
00204         if(ResultData->ModID < ADC_TOT_MOD)
00205         {
00206             if(ResultData->QueueID < ADC_MOD_CCW_TOT)
00207             {
00208                 struct QADC64_tag* QADC_Reg = ModRegAddr[ResultData->ModID];
00209                 /* If QADCMCR.STOP is set to Enable stop mode/ driver is in not active,
00210                     - The CCW and result is not reset and is not accessible */
00211                 if(ADC_DRV_INIT == self[ResultData->ModID].DrvStatus)
00212                 {
00213                     RetVal = ADC_OP_SUCCESS;
00214                     /* Get the conversion result */
00215                     switch(ResultData->ReadFormat)
00216                     {
00217                         case ADC_RIGHT_JUST_UNSIGN:
00218                             ResultData->u16Data = QADC_Reg->RJURR[ResultData->QueueID].R;
00219                             break;
00220                         case ADC_LEFT_JUST_SIGN:
00221                             ResultData->u16Data = QADC_Reg->LJSRR[ResultData->QueueID].R;
00222                             break;
00223                         case ADC_LEFT_JUST_UNSIGN:
00224                             ResultData->u16Data = QADC_Reg->LJURR[ResultData->QueueID].R;
00225                             break;
00226                         default:
00227                             ResultData->u16Data = 0;
00228                             RetVal = ADC_OP_UNSUPP_RD_FMT;
00229                             break;
00230                     }
00231                 }
00232                 else
00233                 {
00234                     RetVal = ADC_OP_UNSUPP_STATE;
00235                 }
00236             }
00237             else
00238             {
00239                 RetVal = ADC_OP_INVALID_CCW_ID;
00240             }
00241         }
00242         else
00243         {
00244             RetVal = ADC_OP_INVALID_MOD_ID;
00245         }
00246     }
00247     else
00248     {
00249         RetVal = ADC_OP_INVALID_DATA;
00250     }
00251     return RetVal;
00252  }
00253 
00254  /**************************************************************************//**
00255  *  \fn     QADC_IO_OpStatus QADC_PortConfig(QADC_Module_ID ModID, QADC_Ports PortID, QADC_PortConfigType Type)
00256  *
00257  *  \brief  This API will help in configuraing any port A pins of
00258  *          any ADC converetr module in Input/ Output mode. Port B
00259  *          is always configured in input mode
00260  *
00261  *  \param  ModID   - ADC converter module ID
00262  *  \param  PortID  - Port ID to be configured
00263  *  \param  Type    - Configuration type (Output/Input mode)
00264  *
00265  *  \return Operation status
00266  *          - QADC_IO_INVALID_CFG_TYPE  - Invalid configuration type selected
00267  *          - QADC_IO_INVALID_PORT_ID   - Invalid port ID selected
00268  *          - QADC_IO_INVALID_MOD_ID    - Invalid Module ID selected
00269  *****************************************************************************/
00270  QADC_IO_OpStatus QADC_PortConfig(QADC_Module_ID ModID, QADC_Ports PortID, QADC_PortConfigType Type)
00271  {
00272      if((QADC_CONFIG_OUT == Type) || (QADC_CONFIG_IN == Type))
00273      {
00274         /* Check if the user provided ADC converter module ID is correct */
00275         if(ModID < ADC_TOT_MOD)
00276         {
00277             switch(PortID)
00278             {
00279                 case QADC_PORT_A0:
00280                     ModRegAddr[ModID]->DDRQA.B.DDQA0 = Type;
00281                     break;
00282                 case QADC_PORT_A1:
00283                     ModRegAddr[ModID]->DDRQA.B.DDQA1 = Type;
00284                     break;
00285                 case QADC_PORT_A2:
00286                     ModRegAddr[ModID]->DDRQA.B.DDQA2 = Type;
00287                     break;
00288                 case QADC_PORT_A3:
00289                     ModRegAddr[ModID]->DDRQA.B.DDQA3 = Type;
00290                     break;
00291                 case QADC_PORT_A4:
00292                     ModRegAddr[ModID]->DDRQA.B.DDQA4 = Type;
00293                     break;
00294                 case QADC_PORT_A5:
00295                     ModRegAddr[ModID]->DDRQA.B.DDQA5 = Type;
00296                     break;
00297                 case QADC_PORT_A6:
00298                     ModRegAddr[ModID]->DDRQA.B.DDQA6 = Type;
00299                     break;
00300                 case QADC_PORT_A7:
00301                     ModRegAddr[ModID]->DDRQA.B.DDQA7 = Type;
00302                     break;
00303                 default:
00304                     return QADC_IO_INVALID_PORT_ID;
00305                     break;
00306             }
00307             return QADC_IO_SUCCESS;
00308         }
00309         else
00310         {
00311             return QADC_IO_INVALID_MOD_ID;
00312         }
00313      }
00314      else
00315      {
00316          return QADC_IO_INVALID_CFG_TYPE;
00317      }
00318  }
00319  /**************************************************************************//**
00320  *  \fn     QADC_IO_OpStatus QADC_PortSet(QADC_Module_ID ModID, QADC_Ports PortID, QADC_PortVal Value)
00321  *
00322  *  \brief  This API will help to set the value of any pin of port
00323  *          A to the defined value
00324  *
00325  *  \param  ModID   - ADC converter module ID
00326  *  \param  PortID  - Port ID to be configured
00327  *  \param  Value   - Value of the port to be set
00328  *
00329  *  \return Operation status
00330  *          - QADC_IO_INVALID_CFG_TYPE  - Invalid configuration type selected
00331  *          - QADC_IO_INVALID_PORT_ID   - Invalid port ID selected
00332  *          - QADC_IO_INVALID_MOD_ID    - Invalid Module ID selected
00333  *****************************************************************************/
00334  QADC_IO_OpStatus QADC_PortSet(QADC_Module_ID ModID, QADC_Ports PortID, QADC_PortVal Value)
00335  {
00336     /* Check if the user provided ADC converter module ID is correct */
00337     if(ModID < ADC_TOT_MOD)
00338     {
00339         switch(PortID)
00340         {
00341             case QADC_PORT_A0:
00342                 ModRegAddr[ModID]->PORTQA.B.PQA0 = Value;
00343                 break;
00344             case QADC_PORT_A1:
00345                 ModRegAddr[ModID]->PORTQA.B.PQA1 = Value;
00346                 break;
00347             case QADC_PORT_A2:
00348                 ModRegAddr[ModID]->PORTQA.B.PQA2 = Value;
00349                 break;
00350             case QADC_PORT_A3:
00351                 ModRegAddr[ModID]->PORTQA.B.PQA3 = Value;
00352                 break;
00353             case QADC_PORT_A4:
00354                 ModRegAddr[ModID]->PORTQA.B.PQA4 = Value;
00355                 break;
00356             case QADC_PORT_A5:
00357                 ModRegAddr[ModID]->PORTQA.B.PQA5 = Value;
00358                 break;
00359             case QADC_PORT_A6:
00360                 ModRegAddr[ModID]->PORTQA.B.PQA6 = Value;
00361                 break;
00362             case QADC_PORT_A7:
00363                 ModRegAddr[ModID]->PORTQA.B.PQA7 = Value;
00364                 break;
00365             default:
00366                 return QADC_IO_INVALID_PORT_ID;
00367                 break;
00368         }
00369         return QADC_IO_SUCCESS;
00370     }
00371     else
00372     {
00373         return QADC_IO_INVALID_MOD_ID;
00374     }
00375  }
00376 
00377 /**************************************************************************//**
00378  *  \fn     QADC_IO_OpStatus QADC_PortGet(QADC_Module_ID ModID, QADC_Ports PortID, QADC_PortVal* Value)
00379  *
00380  *  \brief  This API will help to get the value of any pin of port
00381  *          A and B
00382  *
00383  *  \param  ModID   - ADC converter module ID
00384  *  \param  PortID  - Port ID to be configured
00385  *  \param  Value   - Value of the port to be set
00386  *
00387  *  \return Operation status
00388  *          - QADC_IO_INVALID_CFG_TYPE  - Invalid configuration type selected
00389  *          - QADC_IO_INVALID_PORT_ID   - Invalid port ID selected
00390  *          - QADC_IO_INVALID_MOD_ID    - Invalid Module ID selected
00391  *****************************************************************************/
00392  QADC_IO_OpStatus QADC_PortGet(QADC_Module_ID ModID, QADC_Ports PortID, QADC_PortVal* Value)
00393  {
00394     /* Check if the user provided ADC converter module ID is correct */
00395     if(ModID < ADC_TOT_MOD)
00396     {
00397         switch(PortID)
00398         {
00399             case QADC_PORT_A0:
00400                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA0;
00401                 break;
00402             case QADC_PORT_A1:
00403                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA1;
00404                 break;
00405             case QADC_PORT_A2:
00406                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA2;
00407                 break;
00408             case QADC_PORT_A3:
00409                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA3;
00410                 break;
00411             case QADC_PORT_A4:
00412                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA4;
00413                 break;
00414             case QADC_PORT_A5:
00415                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA5;
00416                 break;
00417             case QADC_PORT_A6:
00418                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA6;
00419                 break;
00420             case QADC_PORT_A7:
00421                 *Value = ModRegAddr[ModID]->PORTQA.B.PQA7;
00422                 break;
00423             case QADC_PORT_B0:
00424                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB0;
00425                 break;
00426             case QADC_PORT_B1:
00427                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB1;
00428                 break;
00429             case QADC_PORT_B2:
00430                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB2;
00431                 break;
00432             case QADC_PORT_B3:
00433                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB3;
00434                 break;
00435             case QADC_PORT_B4:
00436                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB4;
00437                 break;
00438             case QADC_PORT_B5:
00439                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB5;
00440                 break;
00441             case QADC_PORT_B6:
00442                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB6;
00443                 break;
00444             case QADC_PORT_B7:
00445                 *Value = ModRegAddr[ModID]->PORTQB.B.PQB7;
00446                 break;
00447             default:
00448                 return QADC_IO_INVALID_PORT_ID;
00449                 break;
00450         }
00451         return QADC_IO_SUCCESS;
00452     }
00453     else
00454     {
00455         return QADC_IO_INVALID_MOD_ID;
00456     }
00457  }
00458