Index: firmware/App/Services/DDInterface.c =================================================================== diff -u -r3518e8a088c32e75c0c8960d5e629a7401095feb -r6f02ff4686ec9dfc60247e9ed3fc9c5cc7771543 --- firmware/App/Services/DDInterface.c (.../DDInterface.c) (revision 3518e8a088c32e75c0c8960d5e629a7401095feb) +++ firmware/App/Services/DDInterface.c (.../DDInterface.c) (revision 6f02ff4686ec9dfc60247e9ed3fc9c5cc7771543) @@ -1,27 +1,25 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 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 (last) Varshini Nagabooshanam +* @date (last) 26-Jan-2026 * -* @author (original) Sean -* @date (original) 30-Jul-2024 +* @author (original) Sean Nash +* @date (original) 01-Aug-2024 * ***************************************************************************/ -#include // To check for NaN - -#include "DDDefs.h" #include "DDInterface.h" +#include "MessagePayloads.h" #include "Messaging.h" #include "ModeInitPOST.h" -#include "OperationModes.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommTD.h" #include "TaskGeneral.h" @@ -38,15 +36,19 @@ // ********** private data ********** -// DG status -static DD_OP_MODE_T ddCurrentOpMode; ///< Current DD operation mode. -static U32 ddSubMode; ///< Current state (sub-mode) of current DG operation mode. -static BOOL ddStartCommandSent; ///< Flag indicates command to start DG has been sent. -static BOOL ddStarted; ///< Flag indicates whether we have commanded the DD to start or stop. +// DD status +static DD_OP_MODE_T ddCurrentOpMode; ///< Current DD operation mode. +static U32 ddSubMode; ///< Current state (sub-mode) of current DD operation mode. +static F32 dialysatePressure; ///< Current dialysate pressure reported by DD. +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 +static BOOL ddOpModeDataFreshFlag; ///< Flag to signal the handleDDOpMode() to process fresh dd op mode data. +static BOOL ddDialysatePressureFreshFlag; ///< Flag to signal -// DG command response +static DIALYSATE_DELIVERY_REQ_PAYLOAD_T dialysateDeliveryCmdSet; ///< Set of dialysate delivery parameters to send to the DD during treatment. + +// DD command response static DD_CMD_RESPONSE_T ddCmdResp[ NUM_OF_DD_COMMANDS ]; ///< Keep the latest DD command response for each command. // ********** private function prototypes ********** @@ -65,12 +67,15 @@ { 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; + ddCurrentOpMode = DD_MODE_INIT; + ddSubMode = 0; + dialysatePressure = 0.0F; + ddOpModeDataFreshFlag = FALSE; + ddDialysatePressureFreshFlag = FALSE; + + resetDDInterface(); + // initialize DD command response for ( i = 0; i < NUM_OF_DD_COMMANDS; i++ ) { @@ -82,28 +87,50 @@ // initPersistentAlarm( ALARM_ID_TD_DD_NEW_OPERATION_MODE_MESSAGE_NOT_RECEIVE, DD_DATA_FRESHNESS_TIMEOUT_MS, DD_DATA_FRESHNESS_TIMEOUT_MS ); } +/*********************************************************************//** + * @brief + * The resetDDInterface function resets the DDInterface unit before starting + * a new treatment work flow. + * @details \b Inputs: none + * @details \b Outputs: DDInterface unit reset. + * @return none + *************************************************************************/ +void resetDDInterface( void ) +{ + ddStarted = FALSE; + ddStartCommandSent = FALSE; + + dialysateDeliveryCmdSet.start = FALSE; + dialysateDeliveryCmdSet.dialRate = 0.0F; + dialysateDeliveryCmdSet.ufRate = 0.0F; + dialysateDeliveryCmdSet.dialTemp = 0.0F; + dialysateDeliveryCmdSet.bypassDialyzer = TRUE; + dialysateDeliveryCmdSet.acidType = 0; + dialysateDeliveryCmdSet.bicarbType = 0; +} + /**********************************************************************//** * @brief - * The checkDGDataFreshness function checks the freshness of data coming from + * The checkDDDataFreshness 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 + * @param ddFreshDataFlag 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 ) +static void checkDDDataFreshness( ALARM_ID_T alarmID, BOOL *ddFreshDataFlag ) { - if ( TRUE == *dgFreshDataFlag ) + if ( TRUE == *ddFreshDataFlag ) { - *dgFreshDataFlag = FALSE; + *ddFreshDataFlag = FALSE; checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); } else - { // Alarm if not receiving DG fresh data message in timely manner + { // Alarm if not receiving DD fresh data message in timely manner if ( TRUE == isDDCommunicating() ) { checkPersistentAlarm( alarmID, TRUE, 0.0, 0.0 ); @@ -117,7 +144,7 @@ /*********************************************************************//** * @brief - * The execDGInterfaceMonitor function executes the DD Interface monitoring + * The execDDInterfaceMonitor 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 @@ -126,7 +153,7 @@ 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 ) ) @@ -136,8 +163,8 @@ // } // Check to see if DD has restarted - checkDDRestart(); - } +// checkDDRestart(); +// } } /*********************************************************************//** @@ -154,7 +181,7 @@ /*********************************************************************//** * @brief - * The getDGSubMode function gets the latest reported DD operating sub-mode. + * The getDDSubMode function gets the latest reported DD operating sub-mode. * @details \b Inputs: ddSubMode * @details \b Outputs: none * @return Latest reported DD operating sub-mode. @@ -171,33 +198,218 @@ * @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 + * @param message Pointer to the DD operation mode broadcast message + * @return TRUE if message handled successfully, FALSE if not *************************************************************************/ -void setDDOpMode( U32 opMode, U32 subMode ) +BOOL setDDOpMode( MESSAGE_T *message ) { - if ( opMode < NUM_OF_DD_MODES ) + BOOL result = FALSE; + U32 opMode, subMode; + + // parse message payload + memcpy( &opMode, &message->payload[ 0 ], sizeof( U32 ) ); + memcpy( &subMode, &message->payload[ sizeof( U32 ) ], sizeof( U32 ) ); + + if ( ( message->hdr.payloadLen == sizeof( OP_MODE_PAYLOAD_T ) ) && ( opMode < NUM_OF_DD_MODES ) ) { - // reset POST passed flag if DG restarted or faulted or went to service mode + // reset POST passed flag if DD 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 + // update DD op mode and sub-mode ddCurrentOpMode = (DD_OP_MODE_T)opMode; ddSubMode = subMode; + result = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DD_OPERATING_MODE, opMode ); } ddOpModeDataFreshFlag = TRUE; + + return result; } /*********************************************************************//** * @brief + * The getDialysatePressure function gets the latest reported dialysate + * pressure. + * @details \b Inputs: dialysatePressure + * @details \b Outputs: none + * @return Latest reported dialysate pressure. + *************************************************************************/ +F32 getDialysatePressure( void ) +{ + return dialysatePressure; +} + +/*********************************************************************//** + * @brief + * The setDialysatePressure function sets the latest dialysate pressure + * reported by the DD sub-system. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if message invalid. + * @details \b Inputs: none + * @details \b Outputs: dialysatePressure, ddDialysatePressureFreshFlag + * @param message Pointer to the DD pressure data broadcast message + * @return TRUE if message handled successfully, FALSE if not + *************************************************************************/ +BOOL setDialysatePressure( MESSAGE_T *message ) +{ + BOOL result = FALSE; + DD_PRESSURE_DATA_T payload; + + // parse message payload + memcpy( &payload, &message->payload[ 0 ], sizeof( DD_PRESSURE_DATA_T ) ); + + if ( message->hdr.payloadLen == sizeof( DD_PRESSURE_DATA_T ) ) + { + // update dialysate pressure + dialysatePressure = payload.d41Pressure; + result = TRUE; + } + else + { +#ifndef TEST_UI_ONLY + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_DD_PRESSURE_DATA, (U32)message->hdr.payloadLen ); +#endif + } + + ddDialysatePressureFreshFlag = TRUE; + + return result; +} + +/*********************************************************************//** + * @brief + * The cmdStartGenerateDialysate function sends a generate dialysate command + * to the DD with a given set of details. DD will transition to dialysate + * delivery mode if it hasn't already. + * @details \b Inputs: none + * @details \b Outputs: dialysateDeliveryCmdSet + * @details \b Message \b Sent: Start/continue generate dialysate command. + * @param qd Target dialysate flow rate (Qd). + * @param quf Target ultrafiltration rate (Quf). + * @param dialTemp Target dialysate temperature in deg C. + * @param bypass Flag indicating whether dialyzer should be bypassed. + * @param acid Type of acid concentrate used. + * @param bicarb Type of bicarbonate concentrate used. + * @return none + *************************************************************************/ +void cmdStartGenerateDialysate( F32 qd, F32 quf, F32 dialTemp, BOOL bypass, ACID_CONCENTRATE_TYPE_T acid, BICARB_CONCENTRATE_TYPE_T bicarb ) +{ + dialysateDeliveryCmdSet.start = TRUE; + dialysateDeliveryCmdSet.dialRate = qd; + dialysateDeliveryCmdSet.ufRate = quf; + dialysateDeliveryCmdSet.dialTemp = dialTemp; + dialysateDeliveryCmdSet.bypassDialyzer = bypass; + dialysateDeliveryCmdSet.acidType = (U32)acid; + dialysateDeliveryCmdSet.bicarbType = (U32)bicarb; + +#ifndef TEST_UI_ONLY + sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&dialysateDeliveryCmdSet), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +#endif + ddStartCommandSent = TRUE; +} + +/*********************************************************************//** + * @brief + * The cmdChangeQd function sends a generate dialysate command to the DD + * with a given new dialysate rate. + * @details \b Inputs: none + * @details \b Outputs: dialysateDeliveryCmdSet + * @details \b Message \b Sent: Continue generate dialysate command w/ new Qd. + * @param qd Target dialysate flow rate (Qd). + * @return none + *************************************************************************/ +void cmdChangeQd( F32 qd ) +{ + if ( TRUE == dialysateDeliveryCmdSet.start ) + { + dialysateDeliveryCmdSet.dialRate = qd; +#ifndef TEST_UI_ONLY + sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&dialysateDeliveryCmdSet), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +#endif + } + else + { + // TODO - s/w fault? + } +} + +/*********************************************************************//** + * @brief + * The cmdChangeQuf function sends a generate dialysate command to the DD + * with a given new ultrafiltration rate. + * @details \b Inputs: none + * @details \b Outputs: dialysateDeliveryCmdSet + * @details \b Message \b Sent: Continue generate dialysate command w/ new Quf. + * @param quf Target ultrafiltration flow rate (in L/hr). + * @return none + *************************************************************************/ +void cmdChangeQuf( F32 quf ) +{ + if ( TRUE == dialysateDeliveryCmdSet.start ) + { + dialysateDeliveryCmdSet.ufRate = quf; +#ifndef TEST_UI_ONLY + sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&dialysateDeliveryCmdSet), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +#endif + } + else + { + // TODO - s/w fault? + } +} + +/*********************************************************************//** + * @brief + * The cmdBypassDialyzer function sends a generate dialysate command to the DD + * with a given flag indicating whether dialyzer should be bypassed. + * @details \b Inputs: none + * @details \b Outputs: dialysateDeliveryCmdSet + * @details \b Message \b Sent: Continue generate dialysate command w/ new + * dialyzer bypass flag. + * @param bypass Flag indicating whether dialyzer should be bypassed. + * @return none + *************************************************************************/ +void cmdBypassDialyzer( BOOL bypass ) +{ + if ( TRUE == dialysateDeliveryCmdSet.start ) + { + dialysateDeliveryCmdSet.bypassDialyzer = bypass; +#ifndef TEST_UI_ONLY + sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&dialysateDeliveryCmdSet), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +#endif + } + else + { + // TODO - s/w fault? + } +} + +/*********************************************************************//** + * @brief + * The cmdStopGenerateDialysate function sends a stop generate dialysate command + * to the DD. DD will transition back to standby mode. + * @details \b Inputs: none + * @details \b Outputs: dialysateDeliveryCmdSet + * @details \b Message \b Sent: Stop generate dialysate command. + * @return none + *************************************************************************/ +void cmdStopGenerateDialysate( void ) +{ + memset( &dialysateDeliveryCmdSet, 0, sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); + dialysateDeliveryCmdSet.start = FALSE; + +#ifndef TEST_UI_ONLY + sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&dialysateDeliveryCmdSet), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +#endif +} + +/*********************************************************************//** + * @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. @@ -282,8 +494,8 @@ // if ( TRUE == ddStarted ) // { -// if ( ( DG_MODE_FAUL != ddCurrentOpMode ) && ( DG_MODE_GEND != ddCurrentOpMode ) && -// ( DG_MODE_FILL != ddCurrentOpMode ) && ( DG_MODE_DRAI != ddCurrentOpMode ) ) +// if ( ( DD_MODE_FAUL != ddCurrentOpMode ) && ( DD_MODE_GEND != ddCurrentOpMode ) && +// ( DD_MODE_FILL != ddCurrentOpMode ) && ( DD_MODE_DRAI != ddCurrentOpMode ) ) // { // activateAlarmNoData( ALARM_ID_TD_DD_RESTARTED_FAULT ); // ddStarted = FALSE; // do not want to re-trigger alarm after alarm is cleared