Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -ra19a676d1e67bb3e1aca9e9bba49727f9d5f8b38 -r7c8ec681f8c5dc44674893b5c3924a6203f2c8d0 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision a19a676d1e67bb3e1aca9e9bba49727f9d5f8b38) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 7c8ec681f8c5dc44674893b5c3924a6203f2c8d0) @@ -26,10 +26,11 @@ #include "Dialysis.h" #include "ModeTreatment.h" #include "PresOccl.h" -#include "WatchdogMgmt.h" +#include "SafetyShutdown.h" +#include "SystemComm.h" #include "SystemCommMessages.h" #include "Utilities.h" -#include "SystemComm.h" +#include "WatchdogMgmt.h" #include "RTC.h" // ********** private definitions ********** @@ -118,17 +119,33 @@ typedef struct { - DG_RESERVOIR_ID_T resID; + U32 resID; U32 setFillToVolumeMl; U32 setDrainToVolumeMl; } DG_RESERVOIRS_DATA_PAYLOAD_T; typedef struct { F32 volume_mL; - UF_ADJ_T adjustType; + U32 adjustType; } UF_SETTINGS_CHANGE_CONFIRMATION_PAYLOAD_T; +typedef struct +{ + F32 TPi; + F32 TPo; + F32 TD1; + F32 TD2; + F32 TRo; + F32 TDi; + F32 HtrPrimThermo; + F32 HtrTrimThermo; + F32 HtrPrimColdJunc; + F32 HtrTrimColdJunc; + F32 HtrPrimInternal; + F32 HtrTrimInternal; +} DG_TEMPERATURES_T; + #pragma pack(pop) // ********** private data ********** @@ -206,6 +223,7 @@ data[ msgSize++ ] = 0; } +#ifndef DISABLE_ACK_ERRORS // if ACK required, add to pending ACK list if ( TRUE == ackReq ) { @@ -215,6 +233,7 @@ SET_ALARM_WITH_1_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) } } +#endif if ( FALSE == error ) { @@ -325,40 +344,42 @@ * @details * Inputs : none * Outputs : UF change settings response msg constructed and queued. - * @param accepted : alarm status record + * @param accepted : T/F - are settings ok? * @param reason : reason rejected (if not accepted) - * @param volume_mL : alarm status record - * @param time_min : alarm status record - * @param ufRate_mL_min : alarm status record - * @param timeDiff : alarm status record - * @param rateDiff : alarm status record + * @param volume_mL : UF volume (in mL) + * @param time_min : treatment duration (in minutes) + * @param ufRate_mL_min : UF rate (in mL/min) + * @param timeDiff : change in treatment duration (in minutes) + * @param rateDiff : change in UF rate (in mL/min) + * @param oldUFRate_mL_min : the UF rate prior to this change (in mL/min) * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendChangeUFSettingsResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min, S32 timeDiff, F32 rateDiff ) +BOOL sendChangeUFSettingsResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min, S32 timeDiff, F32 rateDiff, F32 oldUFRate_mL_min ) { BOOL result; - F32 volume_L = volume_mL / (F32)ML_PER_LITER; MESSAGE_T msg; U08 *payloadPtr = msg.payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_USER_UF_SETTINGS_CHANGE_RESPONSE; - msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ) + sizeof( F32 ) + sizeof( U32 ) + sizeof( U32 ) + sizeof( F32 ) + sizeof ( F32 ); + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ) + sizeof( F32 ) + sizeof( U32 ) + sizeof( S32 ) + sizeof( F32 ) + sizeof( F32 ) + sizeof( F32 ); memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); payloadPtr += sizeof( BOOL ); memcpy( payloadPtr, &reason, sizeof( U32) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &volume_L, sizeof( F32 ) ); + memcpy( payloadPtr, &volume_mL, sizeof( F32 ) ); payloadPtr += sizeof( F32 ); memcpy( payloadPtr, &time_min, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &timeDiff, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &timeDiff, sizeof( S32 ) ); + payloadPtr += sizeof( S32 ); memcpy( payloadPtr, &ufRate_mL_min, sizeof( F32 ) ); payloadPtr += sizeof( F32 ); memcpy( payloadPtr, &rateDiff, sizeof( F32 ) ); + payloadPtr += sizeof( F32 ); + memcpy( payloadPtr, &oldUFRate_mL_min, sizeof( F32 ) ); // 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_HD_2_UI, ACK_REQUIRED ); @@ -368,22 +389,63 @@ /************************************************************************* * @brief + * The sendChangeUFSettingsResponse function constructs a UF change settings \n + * option response to the UI and queues the msg for transmit on the appropriate CAN \n + * channel. + * @details + * Inputs : none + * Outputs : UF change settings option response msg constructed and queued. + * @param accepted : T/F - are settings ok? + * @param reason : reason rejected (if not accepted) + * @param volume_mL : UF volume (in mL) + * @param time_min : treatment duration (in minutes) + * @param ufRate_mL_min : UF rate (in mL/min) + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendChangeUFSettingsOptionResponse( BOOL accepted, U32 reason, F32 volume_mL, U32 time_min, F32 ufRate_mL_min ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_USER_UF_SETTINGS_CHANGE_CONFIRMATION_RESPONSE; + msg.hdr.payloadLen = sizeof( BOOL ) + sizeof( U32 ) + sizeof( F32 ) + sizeof( U32 ) + sizeof( F32 ); + + memcpy( payloadPtr, &accepted, sizeof( BOOL ) ); + payloadPtr += sizeof( BOOL ); + memcpy( payloadPtr, &reason, sizeof( U32) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &volume_mL, sizeof( F32 ) ); + payloadPtr += sizeof( F32 ); + memcpy( payloadPtr, &time_min, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &ufRate_mL_min, sizeof( F32 ) ); + + // 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_HD_2_UI, ACK_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief * The sendChangeTreatmentDurationResponse function constructs a treatment \n * duration change response to the UI and queues the msg for transmit on the \n * appropriate CAN channel. * @details * Inputs : none * Outputs : treatment duration change settings response msg constructed and queued. - * @param accepted : alarm status record + * @param accepted : T/F - are settings ok? * @param reason : reason rejected (if not accepted) - * @param time_min : alarm status record - * @param volume_mL : alarm status record + * @param time_min : treatment duration (in minutes). + * @param volume_mL : UF volume (in mL). * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL sendChangeTreatmentDurationResponse( BOOL accepted, U32 reason, U32 time_min, F32 volume_mL ) { BOOL result; - F32 volume_L = volume_mL / (F32)ML_PER_LITER; MESSAGE_T msg; U08 *payloadPtr = msg.payload; @@ -398,7 +460,7 @@ payloadPtr += sizeof( U32 ); memcpy( payloadPtr, &time_min, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &volume_L, sizeof( F32 ) ); + memcpy( payloadPtr, &volume_mL, sizeof( F32 ) ); // 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_HD_2_UI, ACK_REQUIRED ); @@ -414,7 +476,7 @@ * @details * Inputs : none * Outputs : Blood & dialysate rate change response msg constructed and queued. - * @param accepted : alarm status record + * @param accepted : T/F - are settings ok? * @param reason : reason code for rejection or unused if accepted * @param bloodRate : new blood flow rate * @param dialRate : new dialysate flow rate @@ -460,7 +522,7 @@ * @param maxDialRate : Maximum dialysate flow rate (in mL/min). * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendTreatmentParamsRangesToUI( U32 minTime, U32 maxTime, U32 minUFVol, U32 maxUFVol, U32 minDialRate, U32 maxDialRate ) +BOOL sendTreatmentParamsRangesToUI( U32 minTime, U32 maxTime, F32 minUFVol, F32 maxUFVol, U32 minDialRate, U32 maxDialRate ) { BOOL result; MESSAGE_T msg; @@ -469,16 +531,16 @@ // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_TREATMENT_PARAM_CHANGE_RANGES; - msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ) + sizeof( U32 ); + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ) + sizeof( F32 ) + sizeof( F32 ) + sizeof( U32 ) + sizeof( U32 ); memcpy( payloadPtr, &minTime, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); memcpy( payloadPtr, &maxTime, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &minUFVol, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); - memcpy( payloadPtr, &maxUFVol, sizeof( U32 ) ); - payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &minUFVol, sizeof( F32 ) ); + payloadPtr += sizeof( F32 ); + memcpy( payloadPtr, &maxUFVol, sizeof( F32 ) ); + payloadPtr += sizeof( F32 ); memcpy( payloadPtr, &minDialRate, sizeof( U32 ) ); payloadPtr += sizeof( U32 ); memcpy( payloadPtr, &maxDialRate, sizeof( U32 ) ); @@ -531,7 +593,7 @@ * @param activeReservoir : reservoir ID to set as active. * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendDGSwitchReservoirCommand( DG_RESERVOIR_ID_T activeReservoir ) +BOOL sendDGSwitchReservoirCommand( U32 activeReservoir ) { BOOL result; MESSAGE_T msg; @@ -540,9 +602,9 @@ // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_SWITCH_RESERVOIR_CMD; - msg.hdr.payloadLen = sizeof( DG_RESERVOIR_ID_T ); + msg.hdr.payloadLen = sizeof( U32 ); - memcpy( payloadPtr, &activeReservoir, sizeof( DG_RESERVOIR_ID_T ) ); + memcpy( payloadPtr, &activeReservoir, sizeof( U32 ) ); // 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_HD_2_DG, ACK_REQUIRED ); @@ -639,6 +701,36 @@ /************************************************************************* * @brief + * The sendDGStartStopTrimmerHeaterCommand function constructs a DG start/stop \n + * trimmer heater command message and queues the msg for transmit on the \n + * appropriate CAN channel. + * @details + * Inputs : none + * Outputs : DG start/stop trimmer heater command msg constructed and queued. + * @param start : TRUE indicates start heater, FALSE indicates stop heater. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD; + msg.hdr.payloadLen = sizeof( BOOL ); + + memcpy( payloadPtr, &start, sizeof( BOOL ) ); + + // 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_HD_2_DG, ACK_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief * The sendDGSampleWaterCommand function constructs a DG sample water command \n * message and queues the msg for transmit on the appropriate CAN channel. * @details @@ -1063,7 +1155,7 @@ * @param mode : current HD operation mode. * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL broadcastHDOperationMode( U32 mode ) +BOOL broadcastHDOperationMode( U32 mode, U32 subMode ) { BOOL result; MESSAGE_T msg; @@ -1072,16 +1164,39 @@ // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_HD_OP_MODE; - msg.hdr.payloadLen = sizeof( U32 ); + msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); memcpy( payloadPtr, &mode, sizeof( U32 ) ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &subMode, sizeof( U32 ) ); // 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_HD_BROADCAST, ACK_NOT_REQUIRED ); return result; } +#ifdef EMC_TEST_BUILD +BOOL broadcastCANErrorCount( U32 count ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_CAN_ERROR_COUNT; + msg.hdr.payloadLen = sizeof( U32 ); + + memcpy( payloadPtr, &count, sizeof( U32 ) ); + + // 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_HD_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} +#endif + // *********************************************************************** // **************** Message Handling Helper Functions ******************** // *********************************************************************** @@ -1157,10 +1272,34 @@ result = setNewLoadCellReadings( payload.res1PrimaryLoadCell, payload.res1BackupLoadCell, payload.res2PrimaryLoadCell, payload.res2BackupLoadCell ); } // TODO - what to do if invalid payload length? + // TODO - how to know if DG stops sending these? } /************************************************************************* * @brief + * The handleDGTemperatureData function handles a temperature readings \n + * broadcast message from the DG. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleDGTemperatureData( MESSAGE_T *message ) +{ + if ( message->hdr.payloadLen == sizeof(DG_TEMPERATURES_T) ) + { + DG_TEMPERATURES_T payload; + + memcpy( &payload, message->payload, sizeof(DG_TEMPERATURES_T) ); + setDialysateTemperatureReadings( payload.TDi, payload.TRo ); + } + // TODO - what to do if invalid payload length? + // TODO - how to know if DG stops sending these? +} + +/************************************************************************* + * @brief * The handleROPumpData function handles an RO pump data broadcast \n * message from the DG. * @details @@ -1242,7 +1381,7 @@ DG_RESERVOIRS_DATA_PAYLOAD_T payload; memcpy( &payload, message->payload, sizeof(DG_RESERVOIRS_DATA_PAYLOAD_T) ); - setDGReservoirsData( payload.resID, payload.setFillToVolumeMl, payload.setDrainToVolumeMl ); + setDGReservoirsData( (DG_RESERVOIR_ID_T)payload.resID, payload.setFillToVolumeMl, payload.setDrainToVolumeMl ); } // TODO - what to do if invalid payload length? } @@ -1397,13 +1536,17 @@ *************************************************************************/ void handleDGOpMode( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof(U32) ) + U32 payloadSize = sizeof(U32) + sizeof(U32); + + if ( message->hdr.payloadLen == payloadSize ) { - U32 mode; + U32 mode, subMode; memcpy( &mode, message->payload, sizeof(U32) ); + memcpy( &subMode, &message->payload[sizeof(U32)], sizeof(U32) ); - setDGOpMode( mode ); + setDGOpMode( mode, subMode ); + checkInFromDG(); // TODO - here until we implement DG check-in w/ HD broadcast } else { @@ -1425,18 +1568,21 @@ MESSAGE_T msg; U08 major = (U08)HD_VERSION_MAJOR; U08 minor = (U08)HD_VERSION_MINOR; + U08 micro = (U08)HD_VERSION_MICRO; U16 build = (U16)HD_VERSION_BUILD; U08 *payloadPtr = msg.payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_HD_VERSION; - msg.hdr.payloadLen = sizeof( U08 ) + sizeof( U08 ) + sizeof( U16 ); + msg.hdr.payloadLen = sizeof( U08 ) + sizeof( U08 ) + sizeof( U08 ) + sizeof( U16 ); memcpy( payloadPtr, &major, sizeof( U08 ) ); payloadPtr += sizeof( U08 ); memcpy( payloadPtr, &minor, sizeof( U08 ) ); payloadPtr += sizeof( U08 ); + memcpy( payloadPtr, µ, sizeof( U08 ) ); + payloadPtr += sizeof( U08 ); memcpy( payloadPtr, &build, sizeof( U16 ) ); // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer @@ -2017,3 +2163,15 @@ * @return none *************************************************************************/ DATA_ARRAY_OVERRIDE_HANDLER_FUNC_F32( F32, handleTestDialOutLoadCellWeightOverrideRequest, testSetDialOutLoadCellWeightOverride, testResetDialOutLoadCellWeightOverride ) + +/************************************************************************* + * @brief + * The handleTestHDSafetyShutdownOverrideRequest function handles a \n + * request to override the safety shutdown signal. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +DATA_OVERRIDE_HANDLER_FUNC_U32( U32, handleTestHDSafetyShutdownOverrideRequest, testSetSafetyShutdownOverride, testResetSafetyShutdownOverride )