Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rc429cf7f50851acbaca6e800957ef44cc1fa2162 -r4cc579577062113856fd266cb65b1ccbe33bb596 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision c429cf7f50851acbaca6e800957ef44cc1fa2162) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 4cc579577062113856fd266cb65b1ccbe33bb596) @@ -8,7 +8,7 @@ * @file DGInterface.c * * @author (last) Dara Navaei -* @date (last) 07-Nov-2022 +* @date (last) 02-Dec-2022 * * @author (original) Sean * @date (original) 08-Apr-2020 @@ -37,18 +37,18 @@ // ********** private definitions ********** -#define START_DG_CMD TRUE ///< Parameter for DG start/stop command function. True = start. -#define STOP_DG_CMD FALSE ///< Parameter for DG start/stop command function. False = stop. +#define START_DG_CMD TRUE ///< Parameter for DG start/stop command function. True = start. +#define STOP_DG_CMD FALSE ///< Parameter for DG start/stop command function. False = stop. -#define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. +#define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. -#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 2.0F ///< Dialysate temperature out of target tolerance C. -#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. -#define DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C 46.0F ///< Dialysate high safety temperature limit in C. -#define DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature high safety timeout in milliseconds. -#define DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C 42.0F ///< Dialysate low safety temperature limit in C. -#define DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature low safety timeout in milliseconds. -#define DG_DATA_FRESHNESS_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< DG data freshness timeout (in ms). +#define DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C 2.0F ///< Dialysate temperature out of target tolerance C. +#define DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ( 300 * MS_PER_SECOND ) ///< Dialysate temperature out of target timeout in milliseconds. +#define DIALYSATE_TEMP_HIGH_SAFETY_LIMIT_C 46.0F ///< Dialysate high safety temperature limit in C. +#define DIALYSATE_TEMP_HIGH_SAFETY_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Dialysate temperature high safety timeout in milliseconds. +#define DIALYSATE_TEMP_LOW_SAFETY_LIMIT_C 42.0F ///< Dialysate low safety temperature limit in C. +#define DIALYSATE_TEMP_LOW_SAFETY_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Dialysate temperature low safety timeout in milliseconds. +#define DG_DATA_FRESHNESS_TIMEOUT_MS ( 3 * MS_PER_SECOND ) ///< DG data freshness timeout (in ms). // ********** private data ********** @@ -1091,7 +1091,6 @@ { hasCommandResp = TRUE; memcpy( cmdRespPtr, &dgCmdResp[ commandID ], sizeof( DG_CMD_RESPONSE_T ) ); - dgCmdResp[ commandID ].commandID = DG_CMD_NONE; } return hasCommandResp; Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r5ce2656c662525e10acd1e55f16f7aca5ce9b4d6 -r4cc579577062113856fd266cb65b1ccbe33bb596 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 5ce2656c662525e10acd1e55f16f7aca5ce9b4d6) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 4cc579577062113856fd266cb65b1ccbe33bb596) @@ -48,6 +48,7 @@ #define DISINFECTS_DATA_PUB_INTERVAL ( 1 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Disinfects data publish interval in counts. #define DISINFECTS_TIME_INTERVAL_S ( 2 * SECONDS_IN_A_DAY ) ///< HD/DG 2-day service interval in seconds. +#define FLUSH_TIME_INTERVAL_S ( 30 * SEC_PER_MIN * MS_PER_SECOND ) ///< Flush time interval in seconds. // ********** private data ********** @@ -969,27 +970,44 @@ static BOOL isDGDisinfectValid( void ) { DG_SERVICE_AND_USAGE_DATA_T data; - BOOL status = TRUE; + BOOL status = FALSE; getHDVersionDGServiceAndUsageData( &data ); if ( TRUE == data.isDGUsageInfoAviable ) { - if ( TRUE == data.dgUsageInfo.isDisinfected ) - { - U32 chemDisElapsedTimeS = getRTCTimestamp() - data.dgUsageInfo.lastChemicalDisDateEpoch; - BOOL hasChemDisBeenExpired = ( chemDisElapsedTimeS > DISINFECTS_TIME_INTERVAL_S ? TRUE : FALSE ); - U32 heatDisElapsedTimeS = getRTCTimestamp() - data.dgUsageInfo.lastHeatDisDateEpoch; - BOOL hasHeatDisBeenExpired = ( heatDisElapsedTimeS > DISINFECTS_TIME_INTERVAL_S ? TRUE : FALSE ); + HD_USAGE_INFO_RECORD_T usageRecord; + getNVRecord2Driver( GET_USAGE_RECORD, (U08*)&usageRecord, sizeof( HD_USAGE_INFO_RECORD_T ), 0, ALARM_ID_NO_ALARM ); - if ( ( TRUE == hasChemDisBeenExpired ) && ( TRUE == hasHeatDisBeenExpired ) ) - { - status = FALSE; - } - } - else + U32 lastChemCompleteDate = data.dgUsageInfo.lastChemDisCompleteDateEpoch; + U32 lastChemFlushCompleteDate = data.dgUsageInfo.lastChemDisFlushCompleteDateEpoch; + U32 lastHeatCompleteDate = data.dgUsageInfo.lastHeatDisCompleteDateEpoch; + U32 lastFlushCompleteDate = data.dgUsageInfo.lastBasicFlushCompleteDateEpoch; + U32 lastStartTxTimeDate = usageRecord.txLastStartTimeEpoch; + + // Last Treatment Start < Last Heat Disinfect Complete or Last Treatment Start < Last Chem Disinfect Complete so it means at least a heat disinfect + // or a chemical disinfect has been done since the last treatment + BOOL hasDisBeenDone = ( ( ( lastStartTxTimeDate < lastChemCompleteDate ) || ( lastStartTxTimeDate < lastHeatCompleteDate ) ) ? TRUE : FALSE ); + + // Last Chem Disinfect Complete < Current Time – Chem Disinfect Interval, so the chemical disinfect that has been done has not been expired + BOOL isChemDisValid = ( lastChemCompleteDate < ( getRTCTimestamp() - DISINFECTS_TIME_INTERVAL_S ) ? TRUE : FALSE ); + + // Last Heat Disinfect Complete < Current Time – Heat Disinfect Interval, so the heat disinfect that has been done has not been expired + BOOL isHeatDisValid = ( lastHeatCompleteDate < ( getRTCTimestamp() - DISINFECTS_TIME_INTERVAL_S ) ? TRUE : FALSE ); + + // Last Chem Flush Complete < Last Chem Disinfect Start, so after running a chemical disinfect, a chemical disinfect flush has been done + BOOL isChemFlushComplete = ( lastChemFlushCompleteDate > lastChemCompleteDate ? TRUE : FALSE ); + + // If either of the basic flush, heat disinfect, or chemical disinfect flush have been done within the interval, it means the filters have been flushed + BOOL isBasicFlushValid = ( lastFlushCompleteDate < ( getRTCTimestamp() - FLUSH_TIME_INTERVAL_S ) ? TRUE : TRUE ); + BOOL isHeatDisFlushValid = ( lastHeatCompleteDate < ( getRTCTimestamp() - FLUSH_TIME_INTERVAL_S ) ? TRUE : TRUE ); + BOOL isChemFlushValid = ( lastChemFlushCompleteDate < ( getRTCTimestamp() - FLUSH_TIME_INTERVAL_S ) ? TRUE : TRUE ); + BOOL isFlushValid = ( isBasicFlushValid || isHeatDisFlushValid || isChemFlushValid ); + + // If all of the above conditions are true, it means we can start a treatment + if ( ( TRUE == hasDisBeenDone ) && ( TRUE == isChemDisValid ) && ( TRUE == isHeatDisValid ) && ( TRUE == isChemFlushComplete ) && ( TRUE == isFlushValid ) ) { - status = FALSE; + status = TRUE; } } @@ -1016,7 +1034,7 @@ if ( TRUE == dgData.isDGServiceRecordAvailable ) { - U32 dgSrvcElapsedTimeS = getRTCTimestamp() - dgData.dgServiceRecord.lastServiceDateEpoch; + U32 dgSrvcElapsedTimeS = getRTCTimestamp() - dgData.dgServiceRecord.lastServiceEpochDate; BOOL hasDGSrvcBeenExpired = ( dgSrvcElapsedTimeS > SERVICE_TIME_INTERVAL_S ? TRUE : FALSE ); U32 hdSrvcElapsedTimeS = getRTCTimestamp() - hdServiceRecord.lastServiceEpochDate; BOOL hasHDSrvcBeenExpied = ( hdSrvcElapsedTimeS > SERVICE_TIME_INTERVAL_S ? TRUE : FALSE ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r044d8892373acc5545020aab894cd1943c4d7449 -r4cc579577062113856fd266cb65b1ccbe33bb596 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 044d8892373acc5545020aab894cd1943c4d7449) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 4cc579577062113856fd266cb65b1ccbe33bb596) @@ -900,7 +900,7 @@ U16 msgID; memcpy( &msgID, (U08*)&pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); pendingAckList[ i ].used = FALSE; // Take pending message off of list } } @@ -1163,6 +1163,10 @@ handleUIConfirmationResponse( message ); break; + case MSG_ID_HD_SET_SERVICE_TIME: + handleSetHDServiceTime( message ); + break; + // NOTE: this always must be the last case case MSG_ID_TESTER_LOGIN_REQUEST: handleTesterLogInRequest( message ); @@ -1688,6 +1692,10 @@ handleTestDialOutSetPWM( message ); break; + case MSG_ID_HD_NV_RECORD_CRC_OVERRIDE: + handleTestHDNVRecordCRCOverride( message ); + break; + // The default cannot be reached in VectorCAST since the cases are run in a for loop default: // Unrecognized message ID received - ignore Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r044d8892373acc5545020aab894cd1943c4d7449 -r4cc579577062113856fd266cb65b1ccbe33bb596 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 044d8892373acc5545020aab894cd1943c4d7449) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 4cc579577062113856fd266cb65b1ccbe33bb596) @@ -3224,7 +3224,7 @@ payloadPtr += sizeof( U32 ); memcpy( payloadPtr, &service.serviceIntervalSeconds, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &dgData.dgServiceRecord.lastServiceDateEpoch, sizeof( U32 ) ); + memcpy( payloadPtr, &dgData.dgServiceRecord.lastServiceEpochDate, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); memcpy( payloadPtr, &dgData.dgServiceRecord.serviceIntervalSeconds, sizeof( U32 ) ); } @@ -7111,6 +7111,45 @@ } /*********************************************************************//** + * @brief + * The sendHDUsageRecord function sends out the HD service record. + * @details Inputs: none + * @details Outputs: HD system record msg constructed and queued + * @param msgCurrNum: current payload number + * @param msgTotalNum: total number of payloads + * @param length: buffer length to be written + * @param srvcRcrdAddress: start address of the usage record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendHDUsageRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* sysRcrdAddress ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SEND_USAGE_INFO_RECORD; + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + length; + + memcpy( payloadPtr, &payloadCurrNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &payloadTotalNum, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, &length, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + + memcpy( payloadPtr, sysRcrdAddress, length ); + + // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_PC, ACK_NOT_REQUIRED ); + + return result; +} + +/*********************************************************************//** * @brief * The handleUIServiceModeRequest function handles a request to enter service * mode. @@ -7130,10 +7169,9 @@ { if ( ( MODE_STAN == currentMode ) || ( MODE_FAUL == currentMode ) ) { - requestNewOperationMode( MODE_SERV ); - if ( (DG_MODE_STAN == currentDGMode) || (DG_MODE_FAUL == currentDGMode) ) + if ( ( DG_MODE_STAN == currentDGMode ) || ( DG_MODE_FAUL == currentDGMode ) ) { status = TRUE; cmdSetDGToServiceMode(); @@ -7272,11 +7310,11 @@ *************************************************************************/ void handleDGServiceScheduleData( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof( HD_VERSION_DG_SERVICE_RECORD_T ) ) + if ( message->hdr.payloadLen == sizeof( DG_SERVICE_RECORD_T ) ) { - HD_VERSION_DG_SERVICE_RECORD_T payload; + DG_SERVICE_RECORD_T payload; - memcpy( &payload, message->payload, sizeof( HD_VERSION_DG_SERVICE_RECORD_T ) ); + memcpy( &payload, message->payload, sizeof( DG_SERVICE_RECORD_T ) ); setHDVersionDGServiceRecord( &payload ); } } @@ -7292,16 +7330,37 @@ *************************************************************************/ void handleDGUsageInfoData( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof( HD_VERSION_DG_USAGE_INFO_T ) ) + if ( message->hdr.payloadLen == sizeof( DG_USAGE_INFO_RECORD_T ) ) { - HD_VERSION_DG_USAGE_INFO_T payload; + DG_USAGE_INFO_RECORD_T payload; - memcpy( &payload, message->payload, sizeof( HD_VERSION_DG_USAGE_INFO_T ) ); + memcpy( &payload, message->payload, sizeof( DG_USAGE_INFO_RECORD_T ) ); setHDVersionDGUsageInfo( &payload ); } } /*********************************************************************//** + * @brief + * The handleSetHDServiceTime function sets the HD service time once the + * command is received from UI + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetHDServiceTime( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( 0 == message->hdr.payloadLen ) + { + result = setServiceTime(); + } + + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_UI, result ); +} + +/*********************************************************************//** * @brief * The handleGetHDUsageInfoRecord function handles a request to get the HD * usage information record. @@ -7615,4 +7674,29 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** +* @brief +* The handleTestHDNVRecordCRCOverride function handles a request to override +* the selected NV record's CRC. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleTestHDNVRecordCRCOverride( MESSAGE_T *message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // verify payload length + if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + result = testSetNVRecordCRCOverride( payload.index, (U16)payload.state.u32 ); + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r044d8892373acc5545020aab894cd1943c4d7449 -r4cc579577062113856fd266cb65b1ccbe33bb596 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 044d8892373acc5545020aab894cd1943c4d7449) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 4cc579577062113856fd266cb65b1ccbe33bb596) @@ -431,6 +431,9 @@ // MSG_ID_HD_SET_SW_CONFIG_RECORD void handleSetHDSoftwareConfigRecord( MESSAGE_T *message ); +// MSG_ID_HD_SEND_USAGE_INFO_RECORD +BOOL sendHDUsageRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* sysRcrdAddress ); + // MSG_ID_HD_SEND_ALARMS_COMMAND void handleResendAllAlarmsCommand( MESSAGE_T* message ); @@ -455,6 +458,9 @@ // MSG_ID_DG_USAGE_DATA void handleDGUsageInfoData( MESSAGE_T *message ); +// MSG_ID_HD_SET_SERVICE_TIME +void handleSetHDServiceTime( MESSAGE_T *message ); + // *********** public test support message functions ********** // MSG_TESTER_LOG_IN @@ -845,6 +851,9 @@ // MSG_ID_HD_DIAL_OUT_SET_PWM void handleTestDialOutSetPWM( MESSAGE_T* message ); +// MSG_ID_HD_NV_RECORD_CRC_OVERRIDE +void handleTestHDNVRecordCRCOverride( MESSAGE_T *message ); + /**@}*/ #endif