/************************************************************************** * * Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file InternalADC.c * * @author (last) Sean * @date (last) 07-Aug-2024 * * @author (original) Sean * @date (original) 07-Aug-2024 * ***************************************************************************/ #include "adc.h" #include "InternalADC.h" /** * @addtogroup InternalADC * @{ */ // ********** private definitions ********** #define MAX_ADC_CHANNELS 24 ///< ADC supports up to 24 channels. #define SIZE_OF_ROLLING_AVG 8 ///< Samples in rolling average calculations. #define ROLLING_AVG_SHIFT_DIVIDER 3 ///< Rolling average shift divider. /// Mapping from enumerated used ADC channel to processor channel ID. const INT_ADC_CHANNEL_T ADC_CHANNEL_NUM_TO_CHANNEL_ID[ MAX_ADC_CHANNELS ] = { INT_ADC_NOT_USED, // 0 INT_ADC_PS_THERMISTOR, // 1 INT_ADC_PBA_ADC_REF, // 2 INT_ADC_24V_ACTUATORS_REG, // 3 INT_ADC_1_2V_PROCESSOR, // 4 INT_ADC_5V_SENSORS, // 5 INT_ADC_NOT_USED, // 6 INT_ADC_NOT_USED, // 7 INT_ADC_PRIMARY_ALARM_CURRENT_HG, // 8 INT_ADC_NOT_USED, // 9 INT_ADC_BOARD_THERMISTOR, // 10 INT_ADC_1_25_FPGA_ADC_REF, // 11 INT_ADC_3_3V, // 12 INT_ADC_5V_LOGIC, // 13 INT_ADC_PRIMARY_ALARM_CURRENT_LG, // 14 INT_ADC_NOT_USED, // 15 INT_ADC_BLOOD_PUMP_SPEED, // 16 INT_ADC_BLOOD_PUMP_MOTOR_CURRENT, // 17 INT_ADC_BACKUP_V, // 18 INT_ADC_NOT_USED, // 19 INT_ADC_NOT_USED, // 20 INT_ADC_NOT_USED, // 21 INT_ADC_24V_ACTUATORS, // 22 INT_ADC_NOT_USED // 23 }; const F32 ADC_CHANNEL_READ_TO_UNITS[ NUM_OF_INT_ADC_CHANNELS ] = { 0.0, // - INT_ADC_NOT_USED 1.601601, // RPM - INT_ADC_BLOOD_PUMP_SPEED 0.003002, // A - INT_ADC_BLOOD_PUMP_MOTOR_CURRENT 0.001221, // V - INT_ADC_PS_THERMISTOR 0.001465, // V - INT_ADC_REFIN_1 0.009420, // V - INT_ADC_24V_ACTUATORS_REG 0.000733, // V - INT_ADC_1_2V_PROCESSOR 0.001465, // V - INT_ADC_5V_SENSORS 0.014650, // mA - INT_ADC_PRIMARY_ALARM_CURRENT_HG 0.001221, // V - INT_ADC_BOARD_THERMISTOR 0.000733, // V - INT_ADC_1_25_FPGA_ADC_REF 0.001465, // V - INT_ADC_3_3V 0.001465, // V - INT_ADC_5V_LOGIC 0.073240, // mA - INT_ADC_PRIMARY_ALARM_CURRENT_LG 0.007106, // V - INT_ADC_24V_ACTUATORS 0.007106, // V - INT_ADC_BACKUP_V }; // ********** private data ********** static adcData_t adcRawReadings[ NUM_OF_INT_ADC_CHANNELS ]; ///< Buffer holds latest adc channel readings. static U32 adcRawReadingsCount = 0; ///< Readings count for raw readings buffer. static U16 adcReadings[ NUM_OF_INT_ADC_CHANNELS ][ SIZE_OF_ROLLING_AVG ]; ///< Holds samples for each channel for a rolling average. static U32 adcReadingsIdx[ NUM_OF_INT_ADC_CHANNELS ]; ///< Index for next reading in each rolling average array. static U32 adcReadingsTotals[ NUM_OF_INT_ADC_CHANNELS ]; ///< Rolling total for each channel - used to calc average. static U32 adcReadingsAvgs[ NUM_OF_INT_ADC_CHANNELS ]; ///< Rolling average for each channel. // ********** private function prototypes ********** /*********************************************************************//** * @brief * The initInternalADC function initializes the InternalADC unit. * @details \b Inputs: none * @details \b Outputs: InternalADC unit is initialized. * @return none *************************************************************************/ void initInternalADC( void ) { U32 c,r; // Zero all adc values and stats adcRawReadingsCount = 0; for ( c = 0; c < NUM_OF_INT_ADC_CHANNELS; c++ ) { adcRawReadings[ c ].id = 0; adcRawReadings[ c ].value = 0; adcReadingsIdx[ c ] = 0; adcReadingsTotals[ c ] = 0; adcReadingsAvgs[ c ] = 0; for ( r = 0; r < SIZE_OF_ROLLING_AVG; r++ ) { adcReadings[ c ][ r ] = 0; } } // Enable interrupt when all channels converted adcEnableNotification( adcREG1, adcGROUP1 ); } /*********************************************************************//** * @brief * The adcNotification function handles an ADC conversion complete interrupt. * All channel readings in the FIFO are retrieved. * @details \b Inputs: ADC FIFO * @details \b Outputs: adcRawReadingsCount, adcRawReadings[] * @param adc pointer to the ADC1 controller * @param group ADC channel group ID * @return none *************************************************************************/ void adcNotification( adcBASE_t *adc, uint32 group ) { if ( adcGROUP1 == group ) { adcRawReadingsCount = adcGetData( adcREG1, adcGROUP1, adcRawReadings ); } } /*********************************************************************//** * @brief * The execInternalADC function processes the last set of raw ADC channel * readings and kicks off the next conversion of ADC channels. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if raw readings count exceeds * ADC channel count * @details \b Inputs: adcRawReadingsCount, adcRawReadings[] * @details \b Outputs: adcReadings[][], adcReadingsIdx[], adcReadingsTotals[], adcReadingsAvgs[] * @return none *************************************************************************/ void execInternalADC( void ) { U32 i; if ( adcRawReadingsCount < NUM_OF_INT_ADC_CHANNELS ) { // Process readings from last conversion for ( i = 0; i < adcRawReadingsCount; i++ ) { U32 ch = ADC_CHANNEL_NUM_TO_CHANNEL_ID[ adcRawReadings[ i ].id ]; adcReadingsTotals[ ch ] -= adcReadings[ ch ][ adcReadingsIdx[ ch ] ]; adcReadings[ ch ][ adcReadingsIdx[ ch ] ] = adcRawReadings[i].value; adcReadingsTotals[ ch ] += adcRawReadings[ i ].value; adcReadingsAvgs[ ch ] = adcReadingsTotals[ ch ] >> ROLLING_AVG_SHIFT_DIVIDER; adcReadingsIdx[ ch ] = INC_WRAP( adcReadingsIdx[ ch ], 0, SIZE_OF_ROLLING_AVG - 1 ); } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_DATA_OVERRUN, adcRawReadingsCount ) } // Start an adc channel group conversion adcStartConversion( adcREG1, adcGROUP1 ); } /*********************************************************************//** * @brief * The getIntADCReading function gets the latest average reading for a given * channel. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given channel invalid. * @details \b Inputs: adcReadingsAvgs[] * @details \b Outputs: none * @param channel adc channel to retrieve a reading for * @return The rolling averaged reading for the given channel *************************************************************************/ U16 getIntADCReading( INT_ADC_CHANNEL_T channel ) { U16 result = 0; if ( channel < NUM_OF_INT_ADC_CHANNELS ) { result = adcReadingsAvgs[ channel ]; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED1, channel ) } return result; } /*********************************************************************//** * @brief * The getIntADCVoltageConverted function gets the latest average voltage * (converted per transfer function) for a given channel. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given channel invalid * @details \b Inputs: adcReadingsAvgs[], ADC_CHANNEL_READ_TO_UNITS[] * @details \b Outputs: none * @param channel The ADC channel to retrieve a converted voltage for * @return The rolling averaged, converted voltage for the given channel *************************************************************************/ F32 getIntADCVoltageConverted( INT_ADC_CHANNEL_T channel ) { F32 result = 0.0; if ( channel < NUM_OF_INT_ADC_CHANNELS ) { result = (F32)adcReadingsAvgs[ channel ] * ADC_CHANNEL_READ_TO_UNITS[ channel ]; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED2, channel ) } return result; } /**@}*/