/************************************************************************** * * 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) Vinayakam Mani * @date (last) 13-Aug-2024 * * @author (original) Vinayakam Mani * @date (original) 13-Aug-2024 * ***************************************************************************/ #include "adc.h" #include "InternalADC.h" /** * @addtogroup InternalADC * @{ */ // ********** private definitions ********** #define MAX_ADC_CHANNELS 24 ///< DG internal ADC supports up to 24 channels. #define SIZE_OF_ROLLING_AVG 16 ///< Number of DG internal ADC samples in rolling average calculations for each channel. #define ROLLING_AVG_SHIFT_DIVIDER 4 ///< Rolling average shift divider for DG internal ADC readings. /// ADC channel number to ADC channel ID (enumeration) look-up table. const INT_ADC_CHANNEL_T adcChannelNum2ChannelId[ MAX_ADC_CHANNELS ] = { INT_ADC_RO_PUMP_INLET_PRESSURE, // 0 INT_ADC_RO_PUMP_OUTLET_PRESSURE, // 1 INT_ADC_DRAIN_PUMP_OUTLET_PRESSURE, // 2 INT_ADC_DRAIN_PUMP_INLET_PRESSURE, // 3 INT_ADC_MAIN_24_VOLTS, // 4 INT_ADC_FPGA_1_8_VOLTS, // 5 INT_ADC_FPGA_1_VOLT, // 6 INT_ADC_SENSORS_3_3_VOLTS, // 7 INT_ADC_PROCESSOR_1_8_VOLTS, // 8 INT_ADC_POWER_SUPPLY_GATE_DRIVER, // 9 INT_ADC_SENSORS_5_VOLTS, // 10 INT_ADC_LOGIC_5_VOLTS, // 11 INT_ADC_3_3_VOLTS, // 12 INT_ADC_RO_PUMP_FEEDBACK_DUTY_CYCLE, // 13 INT_ADC_AVAILABLE_CHANNEL, // 14 INT_ADC_PROCESSOR_1_2_VOLTS, // 15 INT_ADC_REFERENCE_VOLTAGE, // 16 INT_ADC_TRIMMER_HEATER_24_VOLTS, // 17 INT_ADC_SECONDARY_HEATER_24_VOLTS, // 18 INT_ADC_REF_IN1, // 19 INT_ADC_REF_IN2, // 20 INT_ADC_BOARD_THERMISTOR, // 21 INT_ADC_POWER_SUPPLY_1_THERMISTOR, // 22 INT_ADC_MAIN_NON_ISOLATED_24_VOLTS, // 23 }; /// ADC channel read to units look-up table. const F32 ADC_CHANNEL_READ_TO_UNITS[ NUM_OF_INT_ADC_CHANNELS ] = { 0.0, // - INT_ADC_NOT_USED 0.06438104, // PSIA- INT_ADC_RO_PUMP_INLET_PRESSURE 0.06438104, // PSIA- INT_ADC_RO_PUMP_OUTLET_PRESSURE 0.06438104, // PSIA- INT_ADC_DRAIN_PUMP_OUTLET_PRESSURE 0.06438104, // PSIA- INT_ADC_DRAIN_PUMP_INLET_PRESSURE 0.00073242, // V - INT_ADC_RO_PUMP_FEEDBACK_DUTY_CYCLE 1.0, // ? - INT_ADC_AVAILABLE_CHANNEL 0.00763285, // V - INT_ADC_TRIMMER_HEATER_24_VOLTS (varies inversely with PWM) 0.00700441, // V - INT_ADC_SECONDARY_HEATER_24_VOLTS (varies inversely with PWM for secondary element) 0.001221, // V - INT_ADC_BOARD_THERMISTOR 0.0007326, // V - INT_ADC_FPGA_1_8_VOLTS 0.0007326, // V - INT_ADC_FPGA_1_VOLT 0.0007326, // V - INT_ADC_PROCESSOR_1_8_VOLTS 0.0007326, // V - INT_ADC_PROCESSOR_1_2_VOLTS 0.00117296, // V - INT_ADC_SENSORS_3_3_VOLTS 0.0014652, // V - INT_ADC_SENSORS_5_VOLTS 0.00700441, // V - INT_ADC_MAIN_24_VOLTS 0.0014652, // V - INT_ADC_LOGIC_5_VOLTS 0.00117296, // V - INT_ADC_3_3_VOLTS 0.00117296, // V - INT_ADC_REFERENCE_VOLTAGE (3V) 0.0014652, // V - INT_ADC_REF_IN1 (3V) 0.0014652, // V - INT_ADC_REF_IN2 (3V) 0.001221, // V - INT_ADC_POWER_SUPPLY_1_THERMISTOR 0.00700441, // V - INT_ADC_MAIN_NON_ISOLATED_24_VOLTS 0.00304608 // V - INT_ADC_POWER_SUPPLY_GATE_DRIVER (5V) }; // ********** 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 ]; ///< Buffer 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 buffer. static U32 adcReadingsTotals[ NUM_OF_INT_ADC_CHANNELS ]; ///< Rolling sum for each ADC channel - used to calc average. static U32 adcReadingsAvgs[ NUM_OF_INT_ADC_CHANNELS ]; ///< Rolling average for each ADC channel. /*********************************************************************//** * @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 Inputs: adcRawReadingsCount, adcRawReadings[] * @details \b Outputs: adcReadings[][], adcReadingsIdx[], adcReadingsTotals[], adcReadingsAvgs[] * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid ADC channel number * processed. * @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++ ) { if ( adcRawReadings[ i ].id < NUM_OF_INT_ADC_CHANNELS ) { U32 ch = adcChannelNum2ChannelId[ 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_DD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_INT_ADC_CHANNEL_NUMBER, adcRawReadings[ i ].id ) } } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_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 Inputs: adcReadingsAvgs[] * @details \b Outputs: none * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid ADC channel requested. * @param channel adc channel to retrieve a reading for * @return average 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_DD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED, channel ) } return result; } /*********************************************************************//** * @brief * The getIntADCVoltageConverted function gets the latest average voltage * (converted per transfer function) for a given channel. * @details \b Inputs: adcReadingsAvgs[], ADC_CHANNEL_READ_TO_UNITS[] * @details \b Outputs: none * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when invalid ADC channel requested. * @param channel adc channel to retrieve a converted voltage for * @return average 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_DD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED, channel ) } return result; } /**@}*/