Index: firmware/App/Services/DDInterface.c =================================================================== diff -u -rf6aa1ffddb85a233371e3e7e4d7c0c0eb3e61493 -r6f02ff4686ec9dfc60247e9ed3fc9c5cc7771543 --- firmware/App/Services/DDInterface.c (.../DDInterface.c) (revision f6aa1ffddb85a233371e3e7e4d7c0c0eb3e61493) +++ firmware/App/Services/DDInterface.c (.../DDInterface.c) (revision 6f02ff4686ec9dfc60247e9ed3fc9c5cc7771543) @@ -1,25 +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 "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" @@ -36,17 +36,19 @@ // ********** private data ********** -// DG status -static DD_OP_MODE_T ddCurrentOpMode; ///< Current DD operation mode. +// 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 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; ///< 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,16 +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; - dialysatePressure = 0.0F; - ddStartCommandSent = FALSE; + ddCurrentOpMode = DD_MODE_INIT; + ddSubMode = 0; + dialysatePressure = 0.0F; - ddOpModeDataFreshFlag = FALSE; - ddDialysatePressureFreshFlag = FALSE; + ddOpModeDataFreshFlag = FALSE; + ddDialysatePressureFreshFlag = FALSE; + resetDDInterface(); + // initialize DD command response for ( i = 0; i < NUM_OF_DD_COMMANDS; i++ ) { @@ -86,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 ); @@ -121,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 @@ -158,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. @@ -235,20 +258,22 @@ BOOL setDialysatePressure( MESSAGE_T *message ) { BOOL result = FALSE; - DD_PRESSURE_TEMP_DATA_T payload; + DD_PRESSURE_DATA_T payload; // parse message payload - memcpy( &payload, &message->payload[ 0 ], sizeof( DD_PRESSURE_TEMP_DATA_T ) ); + memcpy( &payload, &message->payload[ 0 ], sizeof( DD_PRESSURE_DATA_T ) ); - if ( message->hdr.payloadLen == sizeof( DD_PRESSURE_TEMP_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; @@ -262,7 +287,7 @@ * 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: 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). @@ -274,72 +299,117 @@ *************************************************************************/ void cmdStartGenerateDialysate( F32 qd, F32 quf, F32 dialTemp, BOOL bypass, ACID_CONCENTRATE_TYPE_T acid, BICARB_CONCENTRATE_TYPE_T bicarb ) { - DIALYSATE_DELIVERY_REQ_PAYLOAD_T payload; + dialysateDeliveryCmdSet.start = TRUE; + dialysateDeliveryCmdSet.dialRate = qd; + dialysateDeliveryCmdSet.ufRate = quf; + dialysateDeliveryCmdSet.dialTemp = dialTemp; + dialysateDeliveryCmdSet.bypassDialyzer = bypass; + dialysateDeliveryCmdSet.acidType = (U32)acid; + dialysateDeliveryCmdSet.bicarbType = (U32)bicarb; - payload.start = TRUE; - payload.dialRate = qd; - payload.ufRate = quf; - payload.dialTemp = dialTemp; - payload.bypassDialyzer = bypass; - payload.acidType = (U32)acid; - payload.bicarbType = (U32)bicarb; - - sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&payload), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +#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 cmdStopGenerateDialysate function sends a stop generate dialysate command - * to the DD. DD will transition back to standby mode. + * The cmdChangeQd function sends a generate dialysate command to the DD + * with a given new dialysate rate. * @details \b Inputs: none - * @details \b Outputs: none - * @details \b Message \b Sent: Stop generate dialysate command. + * @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 cmdStopGenerateDialysate( void ) +void cmdChangeQd( F32 qd ) { - DIALYSATE_DELIVERY_REQ_PAYLOAD_T payload; + 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? + } +} - memset( &payload, 0, sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); - payload.start = FALSE; - - sendMessage( MSG_ID_DD_GEN_DIALYSATE_REQUEST_DATA, COMM_BUFFER_OUT_CAN_TD_2_DD, (U08*)(&payload), sizeof( DIALYSATE_DELIVERY_REQ_PAYLOAD_T ) ); +/*********************************************************************//** + * @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 checkDDDataFreshness function checks to verify that needed data from - * the DD sub-system is coming regularly to keep the data fresh. - * @details Alarm: Data freshness alarm triggered if fresh data not received - * within 2 seconds of last data broadcast. - * @details Inputs: none - * @details Outputs: ddFreshDataFlag set to FALSE - * @param alarm ID of alarm to check - * @param ddFreshDataFlag flag indicating whether data is fresh - * @return None + * 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 *************************************************************************/ -static void checkDDDataFreshness( ALARM_ID_T alarmID, BOOL *ddFreshDataFlag ) +void cmdBypassDialyzer( BOOL bypass ) { - if ( TRUE == *ddFreshDataFlag ) + if ( TRUE == dialysateDeliveryCmdSet.start ) { - *ddFreshDataFlag = FALSE; - checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); + 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 - { // Alarm if not receiving DD fresh data message in timely manner - if ( TRUE == isDDCommunicating() ) - { - checkPersistentAlarm( alarmID, TRUE, 0.0, 0.0 ); - } - else - { - checkPersistentAlarm( alarmID, FALSE, 0.0, 0.0 ); - } + { + // 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. @@ -424,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