/************************************************************************** * * 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 DDInterface.c * * @author (last) Sean * @date (last) 30-Jul-2024 * * @author (original) Sean * @date (original) 30-Jul-2024 * ***************************************************************************/ #include "DDInterface.h" #include "Messaging.h" #include "ModeInitPOST.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommTD.h" #include "TaskGeneral.h" #include "Timers.h" /** * @addtogroup DDInterface * @{ */ // ********** private definitions ********** #define DD_DATA_FRESHNESS_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< DD data freshness timeout (in ms). // ********** private data ********** // DG status static DD_OP_MODE_T ddCurrentOpMode; ///< Current DD operation mode. static U32 ddSubMode; ///< Current state (sub-mode) of current DD operation mode. static BOOL ddStartCommandSent; ///< Flag indicates command to start DD has been sent. static BOOL ddStarted; ///< Flag indicates whether we have commanded the DD to start or stop. static BOOL ddOpModeDataFreshFlag = FALSE; ///< Flag to signal the handleDDOpMode() to process fresh dd op mode data // DG command response static DD_CMD_RESPONSE_T ddCmdResp[ NUM_OF_DD_COMMANDS ]; ///< Keep the latest DD command response for each command. // ********** private function prototypes ********** static void checkDDRestart( void ); static void checkDDDataFreshness( ALARM_ID_T alarmID, BOOL *ddFreshDataFlag ); /*********************************************************************//** * @brief * The initDDInterface function initializes the DDInterface unit. * @details \b Inputs: none * @details \b Outputs: DDInterface unit initialized. * @return none *************************************************************************/ void initDDInterface( void ) { U32 i; // NOTE: the active reservoir is set to reservoir 1 since DG will send active reservoir 1 as active on power up ddStarted = FALSE; ddCurrentOpMode = DD_MODE_INIT; ddSubMode = 0; ddStartCommandSent = FALSE; // initialize DD command response for ( i = 0; i < NUM_OF_DD_COMMANDS; i++ ) { ddCmdResp[ i ].commandID = DD_CMD_NONE; ddCmdResp[ i ].rejected = TRUE; ddCmdResp[ i ].rejectCode = DD_CMD_REQUEST_REJECT_REASON_NONE; } // initPersistentAlarm( ALARM_ID_TD_DD_NEW_OPERATION_MODE_MESSAGE_NOT_RECEIVE, DD_DATA_FRESHNESS_TIMEOUT_MS, DD_DATA_FRESHNESS_TIMEOUT_MS ); } /**********************************************************************//** * @brief * The checkDGDataFreshness function checks the freshness of data coming from * the DD sub-system. * @details \b Alarm: Given alarm is triggered if DD is communicating but has * not published new data for too long. * @details \b Inputs: DD communicating flag * @details \b Outputs: none * @param alarm ID of alarm to check * @param dgFreshDataFlag Pointer to flag indicating whether new data has been * received since last time this function has seen it. * @return None *************************************************************************/ static void checkDGDataFreshness( ALARM_ID_T alarmID, BOOL *dgFreshDataFlag ) { if ( TRUE == *dgFreshDataFlag ) { *dgFreshDataFlag = FALSE; checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); } else { // Alarm if not receiving DG fresh data message in timely manner if ( TRUE == isDDCommunicating() ) { checkPersistentAlarm( alarmID, TRUE, 0.0, 0.0 ); } else { checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); } } } /*********************************************************************//** * @brief * The execDGInterfaceMonitor function executes the DD Interface monitoring * function. Ensures DD is sending fresh data in a timely manner. * @details \b Inputs: ddOpModeDataFreshFlag * @details \b Outputs: ddOpModeDataFreshFlag * @return none *************************************************************************/ void execDDInterfaceMonitor( void ) { // if ( getCPLDACPowerLossDetected() != TRUE ) { // Trigger alarm if not receiving new DD op mode message in timely manner // checkDDDataFreshness( ALARM_ID_TD_DD_NEW_OPERATION_MODE_MESSAGE_NOT_RECEIVE, &ddOpModeDataFreshFlag ); // if ( TRUE == isAlarmActive( ALARM_ID_TD_DD_NEW_OPERATION_MODE_MESSAGE_NOT_RECEIVE ) ) // { // // we don't want to keep thinking DD is in a useful mode - set it to fault mode until DD is able to report its' true mode status // setDDOpMode( DD_MODE_FAUL, 0 ); // } // Check to see if DD has restarted checkDDRestart(); } } /*********************************************************************//** * @brief * The getDDOpMode function gets the current latest reported DD operating mode. * @details \b Inputs: ddCurrentOpMode * @details \b Outputs: none * @return Latest reported DD operating mode. *************************************************************************/ DD_OP_MODE_T getDDOpMode( void ) { return ddCurrentOpMode; } /*********************************************************************//** * @brief * The getDGSubMode function gets the latest reported DD operating sub-mode. * @details \b Inputs: ddSubMode * @details \b Outputs: none * @return Latest reported DD operating sub-mode. *************************************************************************/ U32 getDDSubMode( void ) { return ddSubMode; } /*********************************************************************//** * @brief * The setDDOpMode function sets the latest DD operating mode reported by * the DD (called by DD published message handler). * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if reported DD mode is invalid. * @details \b Inputs: none * @details \b Outputs: ddCurrentOpMode, ddSubMode, ddOpModeDataFreshFlag * @param opMode The operating mode reported by DD * @param subMode The sub-mode of operating mode reported by DD * @return none *************************************************************************/ void setDDOpMode( U32 opMode, U32 subMode ) { if ( opMode < NUM_OF_DD_MODES ) { // reset POST passed flag if DG restarted or faulted or went to service mode if ( ( opMode < DD_MODE_STAN ) && ( ddCurrentOpMode >= DD_MODE_STAN ) ) { signalDDPOSTFinalResult( FALSE ); } // update DG op mode and sub-mode ddCurrentOpMode = (DD_OP_MODE_T)opMode; ddSubMode = subMode; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DD_OPERATING_MODE, opMode ); } ddOpModeDataFreshFlag = TRUE; } /*********************************************************************//** * @brief * The handleDDCommandResponse function processes the latest DD command response. * @details \b Alarm: ALARM_ID_TD_DD_COMMAND_INVALID_PARAMETER_FAULT if reported * response indicates DD rejected command due to invalid parameter. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if reported response is to an * invalid command. * @details \b Inputs: none * @details \b Outputs: ddCmdResp[] * @param ddCmdRespPtr Pointer to the received DD command response * @return none *************************************************************************/ void handleDDCommandResponse( DD_CMD_RESPONSE_T *ddCmdRespPtr ) { if ( ddCmdRespPtr->commandID < NUM_OF_DD_COMMANDS ) { if ( DD_CMD_NONE != ddCmdRespPtr->commandID ) { memcpy( &ddCmdResp[ ddCmdRespPtr->commandID ], ddCmdRespPtr, sizeof( DD_CMD_RESPONSE_T ) ); } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_DD_INVALID_COMMAND_RESPONSE_ID, ddCmdRespPtr->commandID ); } if ( TRUE == ddCmdRespPtr->rejected ) { switch ( ddCmdRespPtr->rejectCode ) { case DD_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER: // SET_ALARM_WITH_1_U32_DATA( ALARM_ID_TD_DD_COMMAND_INVALID_PARAMETER_FAULT, ddCmdRespPtr->commandID ); break; case DD_CMD_REQUEST_REJECT_REASON_NONE: case DD_CMD_REQUEST_REJECT_REASON_INVALID_MODE: default: // Our state machines will detect and handle DD mode out of sync break; } } } /*********************************************************************//** * @brief * The getDDCommandResponse function gets the latest command response from DD. * @details \b Inputs: ddCmdResp[] * @details \b Outputs: cmdRespPtr reference variable is set to the received * command response. * @param commandID ID of specific command that caller wants a response to * @param cmdRespPtr Pointer to command response record to populate with received * response * @return TRUE if a response was received for the given command, FALSE if not. *************************************************************************/ BOOL getDDCommandResponse( U32 commandID, DD_CMD_RESPONSE_T *cmdRespPtr ) { BOOL hasCommandResp = FALSE; if ( commandID == ddCmdResp[ commandID ].commandID ) { hasCommandResp = TRUE; memcpy( cmdRespPtr, &ddCmdResp[ commandID ], sizeof( DD_CMD_RESPONSE_T ) ); } return hasCommandResp; } /*********************************************************************//** * @brief * The checkDDRestart function checks to see if the DD sub-system has restarted * after an operation was started by TD. * @details \b Alarm: ALARM_ID_TD_DD_RESTARTED_FAULT if DD has restarted unexpectedly. * @details \b Inputs: ddStartCommandSent, ddStarted, ddCurrentOpMode * @details \b Outputs: ddStartCommandSent, ddStarted * @return none *************************************************************************/ static void checkDDRestart( void ) { if ( ( ddStartCommandSent == TRUE ) && ( DD_MODE_GEND == ddCurrentOpMode ) ) { ddStartCommandSent = FALSE; ddStarted = TRUE; } // if ( TRUE == ddStarted ) // { // if ( ( DG_MODE_FAUL != ddCurrentOpMode ) && ( DG_MODE_GEND != ddCurrentOpMode ) && // ( DG_MODE_FILL != ddCurrentOpMode ) && ( DG_MODE_DRAI != ddCurrentOpMode ) ) // { // activateAlarmNoData( ALARM_ID_TD_DD_RESTARTED_FAULT ); // ddStarted = FALSE; // do not want to re-trigger alarm after alarm is cleared // } // } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /**@}*/