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