Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -r3c471c54d27025f8f53e1a46a7d67faab1fac108 -r4367d33e7788b9ebbd436c55b53df9ee7cfc5faa --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 3c471c54d27025f8f53e1a46a7d67faab1fac108) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 4367d33e7788b9ebbd436c55b53df9ee7cfc5faa) @@ -7,8 +7,8 @@ * * @file Rinseback.c * -* @author (last) Sean Nash -* @date (last) 12-Nov-2021 +* @author (last) Dara Navaei +* @date (last) 03-Mar-2022 * * @author (original) Sean Nash * @date (original) 20-Jan-2021 @@ -37,7 +37,7 @@ // ********** private definitions ********** -#define TARGET_RINSEBACK_VOLUME_ML 300.0 ///< Target rinseback volume to deliver back to the patient (in mL). TODO - get from Systems when available +#define TUBING_RINSEBACK_VOLUME_ML 80.0 ///< Target rinseback volume to deliver back to the patient (in mL). #define MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML 300.0 ///< Maximum total additional rinseback volume allowed : all additionals (in mL). #define MAX_RINSEBACK_VOLUME_ERROR_ML 60.0 ///< Maximum error in total additional rinseback volume (20% of total). #define TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML 10.0 ///< Target rinseback volume for an additional volume request (in mL). @@ -64,6 +64,7 @@ static U32 rinsebackRate_mL_min; ///< Rinseback rate to use/adjust for this current rinseback only. static U32 rinsebackTimerCtr; ///< Timer counter for time spent in rinseback sub-mode. +static F32 rinsebackTargetVolume_mL; ///< Calculated target rinseback volume (based on selected dialyzer and fixed tubing volume). static OVERRIDE_F32_T cumulativeRinsebackVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative rinseback volume (in mL) from measured blood flow rate. static F32 expectedRinsebackVolume_mL = 0.0; ///< Total cumulative rinseback volume (in mL) expected based on target blood flow rate. static F32 targetRinsebackVolumePlusAdditional_mL; ///< Target rinseback volume w/ additional volume(s) added (in mL). @@ -125,14 +126,16 @@ { rinsebackState = RINSEBACK_STOP_INIT_STATE; rinsebackRate_mL_min = getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); - targetRinsebackVolumePlusAdditional_mL = TARGET_RINSEBACK_VOLUME_ML; + rinsebackTargetVolume_mL = TUBING_RINSEBACK_VOLUME_ML + (F32)getDialyzerBloodVolume(); + targetRinsebackVolumePlusAdditional_mL = rinsebackTargetVolume_mL; rinsebackTimerCtr = 0; cumulativeRinsebackVolume_mL.data = 0.0; expectedRinsebackVolume_mL = 0.0; additionalRinsebackVolume_mL = 0.0; totalAdditionalRinsebackVolume_mL = 0.0; rinsebackAdditionalTimerCtr = 0; rinsebackPublishTimerCtr = 0; + rinsebackTargetVolume_mL = 300.0; resetRinsebackFlags(); } @@ -378,7 +381,7 @@ result = RINSEBACK_STOP_STATE; } // Has rinseback completed? - else if ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) + else if ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); @@ -398,16 +401,15 @@ setupForRinsebackStopOrPause(); result = RINSEBACK_PAUSED_STATE; } -#ifndef DISABLE_PUMP_FLOW_CHECKS // Is rinseback taking too long? - else if ( fabs( expectedRinsebackVolume_mL - getRinsebackVolume() ) > MAX_RINSEBACK_VOLUME_ERROR_ML ) + else if ( ( fabs( expectedRinsebackVolume_mL - getRinsebackVolume() ) > MAX_RINSEBACK_VOLUME_ERROR_ML ) && + ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PUMP_FLOW_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); activateAlarmNoData( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE ); result = RINSEBACK_STOP_STATE; } -#endif // Otherwise, continue rinseback else { // Has user requested rate change? @@ -482,20 +484,20 @@ RINSEBACK_STATE_T result = RINSEBACK_STOP_STATE; // Have we been in this stopped state for too long w/o having delivered full blood volume back to patient? - if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) ) + if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( getRinsebackVolume() < rinsebackTargetVolume_mL ) ) { signalGoToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); } // Have we been in this stopped state for too long despite having delivered full blood volume back to patient? - else if ( ( rinsebackTimerCtr > MAX_RINSEBACK_DONE_TIME ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) + else if ( ( rinsebackTimerCtr > MAX_RINSEBACK_DONE_TIME ) && ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { signalGoToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); clearAlarm( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); } // Have we been in this stopped state for too long despite having delivered full blood volume back to patient? - else if ( ( RINSEBACK_DONE_WARNING_TIME == rinsebackTimerCtr ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) + else if ( ( RINSEBACK_DONE_WARNING_TIME == rinsebackTimerCtr ) && ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { activateAlarmNoData( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); } @@ -507,7 +509,7 @@ { additionalRinsebackRequested = FALSE; // deliver additional rinseback volume only if max volume not reached and max time not reached - if ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) + if ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { rinsebackAdditionalTimerCtr = 0; additionalRinsebackVolume_mL = 0.0; @@ -580,7 +582,7 @@ { setupForRinsebackStopOrPause(); // If this additional rinseback volume has brought us to "full" rinseback volume, set flag - if ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) + if ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) { setRinsebackIsCompleted( TRUE ); } @@ -896,7 +898,7 @@ { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } - else if ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) + else if ( getRinsebackVolume() < rinsebackTargetVolume_mL ) { *rejReason = REQUEST_REJECT_REASON_RINSEBACK_NOT_COMPLETED; } @@ -982,7 +984,7 @@ { RINSEBACK_DATA_PAYLOAD_T data; U32 timeout = MAX_RINSEBACK_TIME / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - U32 countdown = ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ? MAX_RINSEBACK_DONE_TIME : MAX_RINSEBACK_TIME ); + U32 countdown = ( getRinsebackVolume() >= rinsebackTargetVolume_mL ? MAX_RINSEBACK_DONE_TIME : MAX_RINSEBACK_TIME ); countdown -= rinsebackTimerCtr; // Handle countdown past zero @@ -996,7 +998,7 @@ data.targetRinsebackVolumeMl = rinsebackTargetVolume_mL; rinsebackPublishTimerCtr = 0; // If we have completed rinseback, timeout is no longer in force - indicate by zeroing timeout. Also include any additionals to target. - if ( ( rinsebackState > RINSEBACK_PAUSED_STATE ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) + if ( ( rinsebackState > RINSEBACK_PAUSED_STATE ) && ( getRinsebackVolume() >= rinsebackTargetVolume_mL ) ) { data.targetRinsebackVolumeMl = targetRinsebackVolumePlusAdditional_mL; timeout = MAX_RINSEBACK_DONE_TIME / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -re563a0a85eec61711f32cbbb8ff977168fc09954 -r4367d33e7788b9ebbd436c55b53df9ee7cfc5faa --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e563a0a85eec61711f32cbbb8ff977168fc09954) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 4367d33e7788b9ebbd436c55b53df9ee7cfc5faa) @@ -7,8 +7,8 @@ * * @file SystemCommMessages.c * -* @author (last) Michael Garthwaite -* @date (last) 18-Feb-2022 +* @author (last) Dara Navaei +* @date (last) 03-Mar-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -151,18 +151,19 @@ { data[ msgSize++ ] = 0; } - - #ifndef DISABLE_ACK_ERRORS - // If ACK required, add to pending ACK list - if ( TRUE == ackReq ) + + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ACK_ERRORS ) != SW_CONFIG_ENABLE_VALUE ) { - if ( FALSE == addMsgToPendingACKList( &msg, buffer, data, msgSize ) ) + // If ACK required, add to pending ACK list + if ( TRUE == ackReq ) { - error = TRUE; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) - } + if ( FALSE == addMsgToPendingACKList( &msg, buffer, data, msgSize ) ) + { + error = TRUE; + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) + } + } } - #endif if ( FALSE == error ) { @@ -1979,6 +1980,7 @@ } } + #ifdef EMC_TEST_BUILD BOOL broadcastCANErrorCount( U32 count ) { @@ -3101,7 +3103,12 @@ void handleHDSerialNumberRequest( void ) { MESSAGE_T msg; - HD_SYSTEM_RECORD_T system = getHDSystemRecord(); + HD_SYSTEM_RECORD_T system; + + // Get the system's record. There are no arrays of system to check and also, raise no alarm since the system record + // has been already checked in POST + getNVRecord2Driver( GET_SYS_RECORD, (U08*)&system, sizeof( HD_SYSTEM_RECORD_T ), 0, ALARM_ID_NO_ALARM ); + U08 *payloadPtr = msg.payload; // Create a message record @@ -3153,7 +3160,10 @@ void handleHDServiceScheduleRequest( MESSAGE_T *message ) { MESSAGE_T msg; - HD_SERVICE_RECORD_T payload = getHDServiceRecord(); + HD_SERVICE_RECORD_T service; + + getNVRecord2Driver( GET_SRV_RECORD, (U08*)&service, sizeof( HD_SERVICE_RECORD_T ), 0, ALARM_ID_NO_ALARM ); + U08 *payloadPtr = msg.payload; // Create a message record @@ -3162,9 +3172,9 @@ msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); // Fill message payload - memcpy( payloadPtr, &payload.lastServiceEpochDate, sizeof( U32 ) ); + memcpy( payloadPtr, &service.lastServiceEpochDate, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &payload.serviceIntervalSeconds, sizeof( U32 ) ); + memcpy( payloadPtr, &service.serviceIntervalSeconds, sizeof( U32 ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_UI, ACK_REQUIRED ); @@ -5374,7 +5384,7 @@ memcpy(&payloadLength, payloadPtr, sizeof(U32)); payloadPtr += sizeof(U32); - status = setCalibrationRecord( currentMessage, totalMessages, payloadLength, payloadPtr ); + status = receiveRecordFromDialin( NVDATAMGMT_CALIBRATION_RECORD, currentMessage, totalMessages, payloadLength, payloadPtr ); // Respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); @@ -5399,7 +5409,7 @@ // Tester must be logged in if ( TRUE == isTestingActivated() ) { - result = getCalibrationRecord(); + result = sendRecordToDialin( NVDATAMGMT_CALIBRATION_RECORD ); } } @@ -5554,7 +5564,7 @@ memcpy(&payloadLength, payloadPtr, sizeof(U32)); payloadPtr += sizeof(U32); - status = setSystemRecord( currentMessage, totalMessages, payloadLength, payloadPtr ); + status = receiveRecordFromDialin( NVDATAMGMT_SYSTEM_RECORD, currentMessage, totalMessages, payloadLength, payloadPtr ); // Respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); @@ -5579,7 +5589,7 @@ // Tester must be logged in if ( TRUE == isTestingActivated() ) { - result = getSystemRecord(); + result = sendRecordToDialin( NVDATAMGMT_SYSTEM_RECORD ); } } @@ -5670,7 +5680,7 @@ // Tester must be logged in if ( TRUE == isTestingActivated() ) { - result = getServiceRecord(); + result = sendRecordToDialin( NVDATAMGMT_SERVICE_RECORD ); } } @@ -5736,7 +5746,7 @@ memcpy(&payloadLength, payloadPtr, sizeof(U32)); payloadPtr += sizeof(U32); - status = setServiceRecord( currentMessage, totalMessages, payloadLength, payloadPtr ); + status = receiveRecordFromDialin( NVDATAMGMT_SERVICE_RECORD, currentMessage, totalMessages, payloadLength, payloadPtr ); // Respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); @@ -6791,17 +6801,17 @@ *************************************************************************/ void handleTestFansRPMAlarmStartTimeOffsetOverrideRequest( MESSAGE_T *message ) { - TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + TEST_OVERRIDE_PAYLOAD_T payload; BOOL result = FALSE; // verify payload length - if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) { - memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); if ( FALSE == payload.reset ) { - result = testSetFanRPMAlarmStartTimeOffsetOverride( payload.state.u32, payload.index ); + result = testSetFanRPMAlarmStartTimeOffsetOverride( payload.state.u32 ); } else { @@ -6815,6 +6825,39 @@ /*********************************************************************//** * @brief + * The handleSetFansDutyCycleOverrideRequest function handles a + * request to override the fans duty cycle. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetFansDutyCycleOverrideRequest( MESSAGE_T *message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // verify payload length + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + + if ( FALSE == payload.reset ) + { + result = testSetFansDutyCycleOverride( payload.state.f32 ); + } + else + { + result = testResetFansDutyCycleOverride(); + } + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** + * @brief * The handleTestCurrentTreamtmentParametersRequest function handles a * request to retrieve the current treatment parameters. * @details Inputs: none @@ -6857,4 +6900,106 @@ return serializeMessage(msg, COMM_BUFFER_OUT_CAN_PC, ACK_REQUIRED ); } +/*********************************************************************//** + * @brief + * The sendHDSWConfigRecord function sends out the HD software configuration record. + * @details Inputs: none + * @details Outputs: HD software configuration record msg constructed and queued + * @param msgCurrNum: current payload number + * @param msgTotalNum: total number of payloads + * @param length: buffer length to be written + * @param swRcrdAddress: start address of the software configuration record + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendHDSWConfigRecord( U32 payloadCurrNum, U32 payloadTotalNum, U32 length, U08* swRcrdAddress ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // Create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_HD_SEND_SW_CONFIG_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, swRcrdAddress, 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 handleGetHDSoftwareConfigRecord function handles a request to get the HD +* software configuration record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleGetHDSoftwareConfigRecord( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // verify payload length + if ( 0 == message->hdr.payloadLen ) + { + // Tester must be logged in + if ( TRUE == isTestingActivated() ) + { + result = sendRecordToDialin( NVDATAMGMT_SW_CONFIG_RECORD ); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** +* @brief +* The handleSetHDSoftwareConfigRecord function handles a request to set the HD +* software configuration record. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +void handleSetHDSoftwareConfigRecord( MESSAGE_T *message ) +{ + U32 currentMessage; + U32 totalMessages; + U32 payloadLength; + + BOOL status = FALSE; + U08* payloadPtr = message->payload; + + if ( message->hdr.payloadLen >= ( sizeof(currentMessage) + sizeof(totalMessages) + sizeof(payloadLength) ) ) + { + memcpy(¤tMessage, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&totalMessages, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + memcpy(&payloadLength, payloadPtr, sizeof(U32)); + payloadPtr += sizeof(U32); + + status = receiveRecordFromDialin( NVDATAMGMT_SW_CONFIG_RECORD, currentMessage, totalMessages, payloadLength, payloadPtr ); + } + + // Respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, status ); +} + /**@}*/