Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r25aab138cab85b53eef7d37f48d2a06985e93fbc -reb4c5e64b4e8338fa5d747ce0930ca0d12d0a043 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 25aab138cab85b53eef7d37f48d2a06985e93fbc) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision eb4c5e64b4e8338fa5d747ce0930ca0d12d0a043) @@ -1,914 +1,575 @@ -/************************************************************************** - * - * Copyright (c) 2019-2020 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 SystemComm.c - * - * @date 10-Oct-2019 - * @author S. Nash - * - * @brief SystemComm service module. Provides system message communication \n - * functionality. Messages can be queued for transmission. Incoming messages \n - * are processed. - * - **************************************************************************/ - -#include // for memcpy() - -#include "DrainPump.h" -#include "LoadCell.h" -#include "MsgQueues.h" -#include "OperationModes.h" -#include "Reservoirs.h" -#include "ROPump.h" -#include "RTC.h" -#include "SystemComm.h" -#include "Utilities.h" -#include "WatchdogMgmt.h" -#include "SystemCommMessages.h" - -// ********** private definitions ********** - -#define ACK_REQUIRED TRUE -#define ACK_NOT_REQUIRED FALSE - -#pragma pack(push,1) - -typedef struct -{ - U32 alarmState; // 0 = no alarms, 1 = low priority, 2 = medium priority, 3 = high priority - U32 alarmTop; // ID of top active alarm - U32 escalatesIn; // seconds - U32 silenceExpiresIn; // seconds - U16 alarmsFlags; // bit flags: 1 = true, 0 = false for each bit -} ALARM_COMP_STATUS_PAYLOAD_T; - -typedef struct -{ - U32 treatmentTimePrescribedinSec; - U32 treatmentTimeElapsedinSec; - U32 treatmentTimeRemaininginSec; -} TREATMENT_TIME_DATA_T; - -typedef struct -{ - F32 loadCellA1inGram; - F32 loadCellA2inGram; - F32 loadCellB1inGram; - F32 loadCellB2inGram; -} LOAD_CELL_DATA_T; - -typedef struct -{ - U32 setROPumpPressure; - F32 measROFlowRate; - F32 roPumpPWM; -} RO_PUMP_DATA_T; - -typedef struct -{ - U32 setDrainPumpSpeed; - F32 drainPumpPWM; -} DRAIN_PUMP_DATA_T; - -typedef struct -{ - F32 roPumpInletPressure; - F32 roPumpOutletPressure; - F32 drainPumpInletPressure; - F32 drainPumpOutletPressure; -} PRESSURES_DATA_T; - -typedef struct -{ - U32 activeReservoir; - U32 fillToVolumeMl; - U32 drainToVolumeMl; -} RESERVOIR_DATA_T; - -#pragma pack(pop) - -// ********** private data ********** - -static BOOL testerLoggedIn = FALSE; -static volatile U16 nextSeqNo = 1; - -// ********** private function prototypes ********** - -static U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); -static BOOL sendTestAckResponseMsg( MSG_ID_T msgID, BOOL ack ); -static BOOL sendAckResponseMsg( MSG_ID_T msgID, COMM_BUFFER_T buffer, BOOL ack ); - -/************************************************************************* - * @brief serializeMessage - * The serializeMessage function serializes a given message into a given \n - * array of bytes. A sequence # is added to the message here and the ACK \n - * bit of the sequence # is set if ACK is required per parameter. A sync byte \n - * is inserted at the beginning of the message and an 8-bit CRC is appended to \n - * the end of the message. The message is queued for transmission in the given buffer. - * @details - * Inputs : none - * Outputs : given data array populated with serialized message data and queued for transmit. - * @param msg : message to serialize - * @param buffer : outgoing buffer that message should be queued in - * @param ackReq : is an acknowledgement from receiver required? - * @return size (in bytes) of serialized message populated in given data array. - *************************************************************************/ -static U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ) -{ - BOOL result = 0; - BOOL error = FALSE; - U32 msgSize = 0; - U32 sizeMod, sizePad; - U32 i; - U08 crc; - U08 data[ MAX_ACK_MSG_SIZE ]; // byte array to populate with message data - - // prefix data with message sync byte - data[ msgSize++ ] = MESSAGE_SYNC_BYTE; - - // set sequence # and ACK bit (unless this is an ACK to a received message) - if ( msg.hdr.msgID != MSG_ID_ACK ) - { - // thread protect next sequence # access & increment - _disable_IRQ(); - msg.hdr.seqNo = nextSeqNo; - nextSeqNo = INC_WRAP( nextSeqNo, MIN_MSG_SEQ_NO, MAX_MSG_SEQ_NO ); - _enable_IRQ(); - if ( TRUE == ackReq ) - { - msg.hdr.seqNo *= -1; - } - } - - // calculate message CRC - crc = crc8( (U08*)(&msg), sizeof( MESSAGE_HEADER_T ) + msg.hdr.payloadLen ); - - // serialize message header data - memcpy( &data[ msgSize ], &( msg.hdr ), sizeof( MESSAGE_HEADER_T ) ); - msgSize += sizeof( MESSAGE_HEADER_T ); - - // serialize message payload (only used bytes per payloadLen field) - memcpy( &data[ msgSize ], &( msg.payload ), msg.hdr.payloadLen ); - msgSize += msg.hdr.payloadLen; - - // add 8-bit CRC - data[ msgSize++ ] = crc; - - // pad with zero bytes to get length a multiple of CAN_MESSAGE_PAYLOAD_SIZE (8) - sizeMod = msgSize % CAN_MESSAGE_PAYLOAD_SIZE; - sizePad = ( sizeMod == 0 ? 0 : CAN_MESSAGE_PAYLOAD_SIZE - sizeMod ); - for ( i = 0; i < sizePad; i++ ) - { - data[ msgSize++ ] = 0; - } - - // if ACK required, add to pending ACK list - if ( TRUE == ackReq ) - { - if ( FALSE == addMsgToPendingACKList( &msg, buffer, data, msgSize ) ) - { - error = TRUE; - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) - } - } - - if ( FALSE == error ) - { - // add serialized message data to appropriate out-going comm buffer - result = addToCommBuffer( buffer, data, msgSize ); - } - - return result; -} - -/************************************************************************* - * @brief sendACKMsg - * The sendACKMsg function constructs and queues for transmit an ACK message \n - * for a given received message. - * @details - * Inputs : none - * Outputs : ACK message queued for transmit on broadcast CAN channel. - * @param message : message to send an ACK for - * @return TRUE if ACK message queued successfully, FALSE if not - *************************************************************************/ -BOOL sendACKMsg( MESSAGE_T *message ) -{ - BOOL result; - MESSAGE_T msg; - - // create a message record - blankMessage( &msg ); - // send ACK back with same seq. #, but w/o ACK bit - msg.hdr.seqNo = message->hdr.seqNo * -1; - // ACK messages always have this ID - msg.hdr.msgID = MSG_ID_ACK; - // ACK messages always have no payload - msg.hdr.payloadLen = 0; - - // serialize and queue the message for transmit on broadcast channel - result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief sendTestAckResponseMsg - * The sendTestAckResponseMsg function constructs a simple response \n - * message for a handled test message and queues it for transmit on the \n - * appropriate UART channel. - * @details - * Inputs : none - * Outputs : response message constructed and queued for transmit. - * @param msgID : ID of handled message that we are responding to - * @param buffer : outgoing buffer that message should be queued in - * @param ack : TRUE if test message was handled successfully, FALSE if not - * @return TRUE if response message successfully queued for transmit, FALSE if not - *************************************************************************/ -static BOOL sendAckResponseMsg( MSG_ID_T msgID, COMM_BUFFER_T buffer, BOOL ack ) -{ - BOOL result; - MESSAGE_T msg; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = msgID; - msg.hdr.payloadLen = sizeof( U08 ); - msg.payload[ 0 ] = (U08)ack; - - // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer - result = serializeMessage( msg, buffer, ACK_NOT_REQUIRED ); - - return result; -} - -// *********************************************************************** -// ***************** Message Sending Helper Functions ******************** -// *********************************************************************** - -/************************************************************************* - * @brief broadcastAlarmTriggered - * The broadcastAlarmTriggered function constructs an alarm triggered msg to \n - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details - * Inputs : none - * Outputs : alarm triggered msg constructed and queued. - * @param alarm : ID of alarm triggered - * @param almData1 : 1st data associated with alarm - * @param almData2 : 2nd data associated with alarm - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAlarmTriggered( U16 alarm, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_ALARM_TRIGGERED; - msg.hdr.payloadLen = sizeof( U16 ) + sizeof( ALARM_DATA_T ) + sizeof( ALARM_DATA_T ); - - memcpy( payloadPtr, &alarm, sizeof( U16 ) ); - payloadPtr += sizeof( U16 ); - memcpy( payloadPtr, &almData1, sizeof( ALARM_DATA_T ) ); - payloadPtr += sizeof( ALARM_DATA_T ); - memcpy( payloadPtr, &almData2, sizeof( ALARM_DATA_T ) ); - - // 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_DG_ALARM, ACK_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief broadcastAlarmCleared - * The broadcastAlarmCleared function constructs an alarm cleared msg to be \n - * broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details - * Inputs : none - * Outputs : alarm cleared msg constructed and queued. - * @param alarm : ID of alarm cleared - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastAlarmCleared( U16 alarm ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_ALARM_CLEARED; - msg.hdr.payloadLen = sizeof( U16 ); - - memcpy( payloadPtr, &alarm, sizeof( U16 ) ); - - // 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_DG_ALARM, ACK_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief broadcastRTCEpoch - * The broadcastRTCEpoch function constructs an epoch msg to \n - * be broadcast and queues the msg for transmit on the appropriate CAN channel. - * @details - * Inputs : none - * Outputs : RTC time and date in epoch - * @param epoch : Current time and date in epoch - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastRTCEpoch( U32 epoch ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_RTC_EPOCH; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &epoch, 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief - * The broadcastDGHDOperationMode function constructs a DG operation mode \n - * broadcast message and queues the msg for transmit on the appropriate CAN channel. - * @details - * Inputs : none - * Outputs : DG operation mode msg constructed and queued - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastDGOperationMode( U32 mode ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DG_OP_MODE; - msg.hdr.payloadLen = sizeof( U32 ); - - memcpy( payloadPtr, &mode, 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief - * The broadcastLoadCellData function sends out load cell data. - * @details - * Inputs : none - * Outputs : load cell data msg constructed and queued - * @param loadCellA1 : load cell A 1 data in grams. - * @param loadCellA2 : load cell A 2 data in grams. - * @param loadCellB1 : load cell B 1 data in grams. - * @param loadCellB2 : load cell B 2 data in grams. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastLoadCellData( F32 loadCellA1, F32 loadCellA2, F32 loadCellB1, F32 loadCellB2 ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - LOAD_CELL_DATA_T payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_LOAD_CELL_READINGS; - msg.hdr.payloadLen = sizeof( LOAD_CELL_DATA_T ); - - payload.loadCellA1inGram = loadCellA1; - payload.loadCellA2inGram = loadCellA2; - payload.loadCellB1inGram = loadCellB1; - payload.loadCellB2inGram = loadCellB2; - - memcpy( payloadPtr, &payload, sizeof( LOAD_CELL_DATA_T ) ); - - // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief - * The broadcastROPumpData function sends out RO pump data. - * @details - * Inputs : none - * Outputs : RO pump data msg constructed and queued - * @param tgtPressure : target pressure for RO pump in PSI. - * @param measFlow : measure RO flow rate in LPM. - * @param setPWM : set PWM duty cycle in %. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastROPumpData( U32 tgtPressure, F32 measFlow, F32 setPWM ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - RO_PUMP_DATA_T payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_RO_PUMP_DATA; - msg.hdr.payloadLen = sizeof( RO_PUMP_DATA_T ); - - payload.setROPumpPressure = tgtPressure; - payload.measROFlowRate = measFlow; - payload.roPumpPWM = setPWM; - - memcpy( payloadPtr, &payload, sizeof( RO_PUMP_DATA_T ) ); - - // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief - * The broadcastDrainPumpData function sends out RO pump data. - * @details - * Inputs : none - * Outputs : Drain pump data msg constructed and queued - * @param tgtSpeed : target speed for drain pump in RPM. - * @param setPWM : set PWM duty cycle in %. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastDrainPumpData( U32 tgtSpeed, F32 setPWM ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - DRAIN_PUMP_DATA_T payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DRAIN_PUMP_DATA; - msg.hdr.payloadLen = sizeof( DRAIN_PUMP_DATA_T ); - - payload.setDrainPumpSpeed = tgtSpeed; - payload.drainPumpPWM = setPWM; - - memcpy( payloadPtr, &payload, sizeof( DRAIN_PUMP_DATA_T ) ); - - // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief - * The broadcastPressureSensorsData function sends out DG pressure data. - * @details - * Inputs : none - * Outputs : Pressure data msg constructed and queued - * @param measROIn : measured RO pump inlet pressure in PSI. - * @param measROOut : measured RO pump outlet pressure in PSI. - * @param measDrainIn : measured Drain pump inlet pressure in PSI. - * @param measDrainOut : measured Drain pump outlet pressure in PSI. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastPressureSensorsData( F32 measROIn, F32 measROOut, F32 measDrainIn, F32 measDrainOut ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - PRESSURES_DATA_T payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DG_PRESSURES_DATA; - msg.hdr.payloadLen = sizeof( PRESSURES_DATA_T ); - - payload.roPumpInletPressure = measROIn; - payload.roPumpOutletPressure = measROOut; - payload.drainPumpInletPressure = measDrainIn; - payload.drainPumpOutletPressure = measDrainOut; - - memcpy( payloadPtr, &payload, sizeof( PRESSURES_DATA_T ) ); - - // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -/************************************************************************* - * @brief - * The broadcastReservoirData function broadcasts the DG reservoir data. - * @details - * Inputs : none - * Outputs : Reservoir data msg constructed and queued - * @param resID : ID of currently active reservoir. - * @param fillToVol : Current target fill to volume for inactive reservoir. - * @param drainToVol : Current target drain to volume for inactive reservoir. - * @return TRUE if msg successfully queued for transmit, FALSE if not - *************************************************************************/ -BOOL broadcastReservoirData( U32 resID, U32 fillToVol, U32 drainToVol ) -{ - BOOL result; - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - RESERVOIR_DATA_T payload; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DG_PRESSURES_DATA; - msg.hdr.payloadLen = sizeof( RESERVOIR_DATA_T ); - - payload.activeReservoir = resID; - payload.fillToVolumeMl = fillToVol; - payload.drainToVolumeMl = drainToVol; - - memcpy( payloadPtr, &payload, sizeof( RESERVOIR_DATA_T ) ); - - // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); - - return result; -} - -// *********************************************************************** -// **************** Message Handling Helper Functions ******************** -// *********************************************************************** - -/************************************************************************* - * @brief - * The handlePowerOffWarning function handles a power off warning message \n - * from the HD. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handlePowerOffWarning( MESSAGE_T *message ) -{ - // TODO - signal modules that require a warning -} - -/************************************************************************* - * @brief - * The handleSetDialysateTemperatureCmd function handles a dialysate temperature \n - * set points message from the HD. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetDialysateTemperatureCmd( MESSAGE_T *message ) -{ - // TODO - parse and send temp targets to heaters module -} - -/************************************************************************* - * @brief - * The handleFWVersionCmd function handles a FW version request message. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleFWVersionCmd( MESSAGE_T *message ) -{ - MESSAGE_T msg; - U08 *payloadPtr = msg.payload; - U08 major = (U08)DG_VERSION_MAJOR; - U08 minor = (U08)DG_VERSION_MINOR; - U16 build = (U16)DG_VERSION_BUILD; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = MSG_ID_DG_VERSION; - msg.hdr.payloadLen = sizeof( U08 ) + sizeof( U08 ) + sizeof( U16 ); - - memcpy( payloadPtr, &major, sizeof( U08 ) ); - payloadPtr += sizeof( U08 ); - memcpy( payloadPtr, &minor, 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 - serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); -} - -/************************************************************************* - * @brief - * The handleSwitchReservoirCmd function handles a switch reservoirs command \n - * from the HD. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSwitchReservoirCmd( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - if ( message->hdr.payloadLen == sizeof(U32) ) - { - U32 reservoirID; - - result = TRUE; - memcpy( &reservoirID, message->payload, sizeof(U32) ); - setActiveReservoir( (RESERVOIR_ID_T)reservoirID ); - } - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); -} - -/************************************************************************* - * @brief - * The handleFillCmd function handles a fill command from the HD. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleFillCmd( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - if ( message->hdr.payloadLen == sizeof(U32) ) - { - U32 fillToVolumeMl; - - result = TRUE; - memcpy( &fillToVolumeMl, message->payload, sizeof(U32) ); - startFill( fillToVolumeMl ); - } - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); -} - -/************************************************************************* - * @brief - * The handleDrainCmd function handles a drain command from the HD. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleDrainCmd( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - if ( message->hdr.payloadLen == sizeof(U32) ) - { - U32 drainToVolMl; - - result = TRUE; - memcpy( &drainToVolMl, message->payload, sizeof(U32) ); - - startDrain( drainToVolMl ); - } - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); -} - -/************************************************************************* - * @brief - * The handleStartStopTreatmentMsg function handles a treatment start/stop \n - * message from the HD. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleStartStopTreatmentMsg( MESSAGE_T *message ) -{ - BOOL result = FALSE; - - if ( message->hdr.payloadLen == sizeof(U32) ) - { - BOOL startingTreatment; - - result = TRUE; - memcpy( &startingTreatment, message->payload, sizeof(U32) ); - - if ( MODE_STAN == getCurrentOperationMode() && TRUE == startingTreatment ) - { - requestNewOperationMode( MODE_CIRC ); - } - else if ( MODE_CIRC == getCurrentOperationMode() && FALSE == startingTreatment ) - { - requestNewOperationMode( MODE_STAN ); - } - else - { - result = FALSE; - } - } - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); -} - -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ - - -/************************************************************************* - * @brief sendDebugData - * The sendDebugData function sends debug data out to the PC port. - * @details - * Inputs : none - * Outputs : PC serial port - * @param dbgData : Pointer to debug data - * @param len : # of bytes of debug data - * @return TRUE if debug data was successfully queued for transmit, FALSE if not - *************************************************************************/ -#ifdef DEBUG_ENABLED -BOOL sendDebugData( U08 *dbgData, U32 len ) -{ - BOOL result; - - // add serialized message data to appropriate comm buffer - result = addToCommBuffer( COMM_BUFFER_OUT_UART_PC, dbgData, len ); - - return result; -} -#endif - -/************************************************************************* - * @brief isTestingActivated - * The isTestingActivated function determines whether a tester has successfully \n - * logged in to activate testing functionality. - * @details - * Inputs : testerLoggedIn - * Outputs : none - * @param none - * @return TRUE if a tester has logged in to activate testing, FALSE if not - *************************************************************************/ -BOOL isTestingActivated( void ) -{ - return testerLoggedIn; -} - -/************************************************************************* - * @brief sendTestAckResponseMsg - * The sendTestAckResponseMsg function constructs a simple response \n - * message for a handled test message and queues it for transmit on the \n - * appropriate UART channel. - * @details - * Inputs : none - * Outputs : response message constructed and queued for transmit. - * @param msgID : ID of handled message that we are responding to - * @param ack : TRUE if test message was handled successfully, FALSE if not - * @return TRUE if response message successfully queued for transmit, FALSE if not - *************************************************************************/ -static BOOL sendTestAckResponseMsg( MSG_ID_T msgID, BOOL ack ) -{ - BOOL result; - MESSAGE_T msg; - - // create a message record - blankMessage( &msg ); - msg.hdr.msgID = msgID; - msg.hdr.payloadLen = sizeof( U08 ); - msg.payload[ 0 ] = (U08)ack; - - // 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 handleTesterLogInRequest - * The handleTesterLogInRequest function handles a request to login as a \n - * tester. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleTesterLogInRequest( MESSAGE_T *message ) -{ - // verify pass code - // TODO - placeholder - how do we want to authenticate tester? - if ( ( 3 == message->hdr.payloadLen ) && ( 0x31 == message->payload[ 0 ] ) && ( 0x32 == message->payload[ 1 ] ) && ( 0x33 == message->payload[ 2 ] ) ) - { - testerLoggedIn = TRUE; - } - else - { - testerLoggedIn = FALSE; - } - // respond to would be tester - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, testerLoggedIn ); -} - -/************************************************************************* - * @brief - * The handleTestDGMessageRequest function handles a request to add a \n - * DG message to the received message queue. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleTestDGMessageRequest( MESSAGE_T *message ) -{ - MESSAGE_WRAPPER_T dgMessage; - U32 msgLen = (U32)(message->hdr.payloadLen); - U08 *msgBytes = (U08*)(&(dgMessage)); - BOOL result; - - memcpy( msgBytes, message->payload, msgLen ); - - // add HD message to received message queue - result = addToMsgQueue( MSG_Q_IN, &dgMessage ); - - // respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} - -/************************************************************************* - * @brief handleTestWatchdogCheckInStateOverrideRequest - * The handleTestWatchdogCheckInStateOverrideRequest function handles a \n - * request to override the check-in status of a given task. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -DATA_ARRAY_OVERRIDE_HANDLER_FUNC_U32( BOOL, handleTestWatchdogCheckInStateOverrideRequest, testSetWatchdogTaskCheckInOverride, testResetWatchdogTaskCheckInOverride ) - -/************************************************************************* - * @brief handleTestAlarmStateOverrideRequest - * The handleTestAlarmStateOverrideRequest function handles a request to \n - * override the active status of a given alarm. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -DATA_ARRAY_OVERRIDE_HANDLER_FUNC_U32( BOOL, handleTestAlarmStateOverrideRequest, testSetAlarmStateOverride, testResetAlarmStateOverride ) - -/************************************************************************* - * @brief - * The handleTestLoadCellOverrideRequest function handles a request to \n - * override the value read from the given load cell. - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -DATA_ARRAY_OVERRIDE_HANDLER_FUNC_U32( BOOL, handleTestLoadCellOverrideRequest, testSetLoadCellOverride, testResetLoadCellOverride ) - -/************************************************************************* - * @brief handleSetRTCTimestamp - * The handleSetRTCTimestamp function handles a request to write time and - * date to RTC - * @details - * Inputs : none - * Outputs : message handled - * @param message : a pointer to the message to handle - * @return none - *************************************************************************/ -void handleSetRTCTimestamp( MESSAGE_T *message ) -{ - BOOL result; - U08 seconds = message->payload[0]; - U08 minutes = message->payload[1]; - U08 hours = message->payload[2]; - U08 days = message->payload[3]; - U08 months = message->payload[4]; - U32 years; - memcpy(&years, &message->payload[5], sizeof(U32)); - - // TODO: Change setRTCTimestamp to return a boolean for this - result = TRUE; - - setRTCTimestamp( seconds, minutes, hours, days, months, years ); - - // respond to request - sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); -} +/************************************************************************** + * + * Copyright (c) 2019-2020 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 SystemComm.c + * + * @date 10-Oct-2019 + * @author S. Nash + * + * @brief SystemComm service module. Provides system message communication \n + * functionality. Messages can be queued for transmission. Incoming messages \n + * are processed. + * + **************************************************************************/ + +#include // for memcpy() + +#include "MsgQueues.h" +#include "WatchdogMgmt.h" +#include "SystemCommMessages.h" +#include "Utilities.h" +#include "SystemComm.h" +#include "RTC.h" +#include "LoadCell.h" + +// ********** private definitions ********** + +#define ACK_REQUIRED TRUE +#define ACK_NOT_REQUIRED FALSE + +#pragma pack(push,1) + +typedef struct +{ + U32 alarmState; // 0 = no alarms, 1 = low priority, 2 = medium priority, 3 = high priority + U32 alarmTop; // ID of top active alarm + U32 escalatesIn; // seconds + U32 silenceExpiresIn; // seconds + U16 alarmsFlags; // bit flags: 1 = true, 0 = false for each bit +} ALARM_COMP_STATUS_PAYLOAD_T; + +typedef struct +{ + U32 treatmentTimePrescribedinSec; + U32 treatmentTimeElapsedinSec; + U32 treatmentTimeRemaininginSec; +} TREATMENT_TIME_DATA_T; + +typedef struct +{ + F32 loadCellA1inGram; + F32 loadCellA2inGram; + F32 loadCellB1inGram; + F32 loadCellB2inGram; +} LOAD_CELL_DATA_T; + +#pragma pack(pop) + +// ********** private data ********** + +static BOOL testerLoggedIn = FALSE; +static volatile U16 nextSeqNo = 1; + +// ********** private function prototypes ********** + +static U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); +static BOOL sendTestAckResponseMsg( MSG_ID_T msgID, BOOL ack ); + +/************************************************************************* + * @brief serializeMessage + * The serializeMessage function serializes a given message into a given \n + * array of bytes. A sequence # is added to the message here and the ACK \n + * bit of the sequence # is set if ACK is required per parameter. A sync byte \n + * is inserted at the beginning of the message and an 8-bit CRC is appended to \n + * the end of the message. The message is queued for transmission in the given buffer. + * @details + * Inputs : none + * Outputs : given data array populated with serialized message data and queued for transmit. + * @param msg : message to serialize + * @param buffer : outgoing buffer that message should be queued in + * @param ackReq : is an acknowledgement from receiver required? + * @return size (in bytes) of serialized message populated in given data array. + *************************************************************************/ +static U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ) +{ + BOOL result = 0; + BOOL error = FALSE; + U32 msgSize = 0; + U32 sizeMod, sizePad; + U32 i; + U08 crc; + U08 data[ MAX_ACK_MSG_SIZE ]; // byte array to populate with message data + + // prefix data with message sync byte + data[ msgSize++ ] = MESSAGE_SYNC_BYTE; + + // set sequence # and ACK bit (unless this is an ACK to a received message) + if ( msg.hdr.msgID != MSG_ID_ACK ) + { + // thread protect next sequence # access & increment + _disable_IRQ(); + msg.hdr.seqNo = nextSeqNo; + nextSeqNo = INC_WRAP( nextSeqNo, MIN_MSG_SEQ_NO, MAX_MSG_SEQ_NO ); + _enable_IRQ(); + if ( TRUE == ackReq ) + { + msg.hdr.seqNo *= -1; + } + } + + // calculate message CRC + crc = crc8( (U08*)(&msg), sizeof( MESSAGE_HEADER_T ) + msg.hdr.payloadLen ); + + // serialize message header data + memcpy( &data[ msgSize ], &( msg.hdr ), sizeof( MESSAGE_HEADER_T ) ); + msgSize += sizeof( MESSAGE_HEADER_T ); + + // serialize message payload (only used bytes per payloadLen field) + memcpy( &data[ msgSize ], &( msg.payload ), msg.hdr.payloadLen ); + msgSize += msg.hdr.payloadLen; + + // add 8-bit CRC + data[ msgSize++ ] = crc; + + // pad with zero bytes to get length a multiple of CAN_MESSAGE_PAYLOAD_SIZE (8) + sizeMod = msgSize % CAN_MESSAGE_PAYLOAD_SIZE; + sizePad = ( sizeMod == 0 ? 0 : CAN_MESSAGE_PAYLOAD_SIZE - sizeMod ); + for ( i = 0; i < sizePad; i++ ) + { + data[ msgSize++ ] = 0; + } + + // if ACK required, add to pending ACK list + if ( TRUE == ackReq ) + { + if ( FALSE == addMsgToPendingACKList( &msg, buffer, data, msgSize ) ) + { + error = TRUE; + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL ) + } + } + + if ( FALSE == error ) + { + // add serialized message data to appropriate out-going comm buffer + result = addToCommBuffer( buffer, data, msgSize ); + } + + return result; +} + +/************************************************************************* + * @brief sendACKMsg + * The sendACKMsg function constructs and queues for transmit an ACK message \n + * for a given received message. + * @details + * Inputs : none + * Outputs : ACK message queued for transmit on broadcast CAN channel. + * @param message : message to send an ACK for + * @return TRUE if ACK message queued successfully, FALSE if not + *************************************************************************/ +BOOL sendACKMsg( MESSAGE_T *message ) +{ + BOOL result; + MESSAGE_T msg; + + // create a message record + blankMessage( &msg ); + // send ACK back with same seq. #, but w/o ACK bit + msg.hdr.seqNo = message->hdr.seqNo * -1; + // ACK messages always have this ID + msg.hdr.msgID = MSG_ID_ACK; + // ACK messages always have no payload + msg.hdr.payloadLen = 0; + + // serialize and queue the message for transmit on broadcast channel + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +// *********************************************************************** +// ********************* MSG_ID_OFF_BUTTON_PRESS ************************* +// *********************************************************************** + +/************************************************************************* + * @brief broadcastAlarmTriggered + * The broadcastAlarmTriggered function constructs an alarm triggered msg to \n + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details + * Inputs : none + * Outputs : alarm triggered msg constructed and queued. + * @param alarm : ID of alarm triggered + * @param almData1 : 1st data associated with alarm + * @param almData2 : 2nd data associated with alarm + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastAlarmTriggered( U16 alarm, ALARM_DATA_T almData1, ALARM_DATA_T almData2 ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_ALARM_TRIGGERED; + msg.hdr.payloadLen = sizeof( U16 ) + sizeof( ALARM_DATA_T ) + sizeof( ALARM_DATA_T ); + + memcpy( payloadPtr, &alarm, sizeof( U16 ) ); + payloadPtr += sizeof( U16 ); + memcpy( payloadPtr, &almData1, sizeof( ALARM_DATA_T ) ); + payloadPtr += sizeof( ALARM_DATA_T ); + memcpy( payloadPtr, &almData2, sizeof( ALARM_DATA_T ) ); + + // 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_DG_ALARM, ACK_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief broadcastAlarmCleared + * The broadcastAlarmCleared function constructs an alarm cleared msg to be \n + * broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details + * Inputs : none + * Outputs : alarm cleared msg constructed and queued. + * @param alarm : ID of alarm cleared + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastAlarmCleared( U16 alarm ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_ALARM_CLEARED; + msg.hdr.payloadLen = sizeof( U16 ); + + memcpy( payloadPtr, &alarm, sizeof( U16 ) ); + + // 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_DG_ALARM, ACK_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief broadcastRTCEpoch + * The broadcastRTCEpoch function constructs an epoch msg to \n + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details + * Inputs : none + * Outputs : RTC time and date in epoch + * @param epoch : Current time and date in epoch + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastRTCEpoch( U32 epoch ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_RTC_EPOCH; + msg.hdr.payloadLen = sizeof( U32 ); + + memcpy( payloadPtr, &epoch, 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_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief + * The broadcastTreatmentTime function constructs a treatment time msg to \n + * be broadcast and queues the msg for transmit on the appropriate CAN channel. + * @details + * Inputs : none + * Outputs : treatment time data msg constructed and queued + * @param secsTotTreatment : Total treatment time prescribed (in seconds). + * @param secsElapsed : Treatment time elapsed (in seconds). + * @param secsRemaining : Treatment time remaining (in seconds). + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastTreatmentTime( U32 secsTotTreatment, U32 secsElapsed, U32 secsRemaining ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + TREATMENT_TIME_DATA_T payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_TREATMENT_TIME; + msg.hdr.payloadLen = sizeof( TREATMENT_TIME_DATA_T ); + + payload.treatmentTimePrescribedinSec = secsTotTreatment; + payload.treatmentTimeElapsedinSec = secsElapsed; + payload.treatmentTimeRemaininginSec = secsRemaining; + + memcpy( payloadPtr, &payload, sizeof( TREATMENT_TIME_DATA_T ) ); + + // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief + * The broadcastLoadCellData function sends out load cell data. + * @details + * Inputs : load cell data + * Outputs : load cell data msg constructed and queued + * @param loadCellA1 : load cell A 1 data in grams. + * @param loadCellA2 : load cell A 2 data in grams. + * @param loadCellB1 : load cell B 1 data in grams. + * @param loadCellB2 : load cell B 2 data in grams. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastLoadCellData( F32 loadCellA1, F32 loadCellA2, F32 loadCellB1, F32 loadCellB2 ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + LOAD_CELL_DATA_T payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_LOAD_CELL_READINGS; + msg.hdr.payloadLen = sizeof( LOAD_CELL_DATA_T ); + + payload.loadCellA1inGram = loadCellA1; + payload.loadCellA2inGram = loadCellA2; + payload.loadCellB1inGram = loadCellB1; + payload.loadCellB2inGram = loadCellB2; + + memcpy( payloadPtr, &payload, sizeof( LOAD_CELL_DATA_T ) ); + + // 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_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief + * The handleFWVersionCmd function handles a FW version request message. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleFWVersionCmd( MESSAGE_T *message ) +{ + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + U08 major = (U08)DG_VERSION_MAJOR; + U08 minor = (U08)DG_VERSION_MINOR; + U16 build = (U16)DG_VERSION_BUILD; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_VERSION; + msg.hdr.payloadLen = sizeof( U08 ) + sizeof( U08 ) + sizeof( U16 ); + + memcpy( payloadPtr, &major, sizeof( U08 ) ); + payloadPtr += sizeof( U08 ); + memcpy( payloadPtr, &minor, 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 + serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/************************************************************************* + * @brief sendDebugData + * The sendDebugData function sends debug data out to the PC port. + * @details + * Inputs : none + * Outputs : PC serial port + * @param dbgData : Pointer to debug data + * @param len : # of bytes of debug data + * @return TRUE if debug data was successfully queued for transmit, FALSE if not + *************************************************************************/ +#ifdef DEBUG_ENABLED +BOOL sendDebugData( U08 *dbgData, U32 len ) +{ + BOOL result; + + // add serialized message data to appropriate comm buffer + result = addToCommBuffer( COMM_BUFFER_OUT_UART_PC, dbgData, len ); + + return result; +} +#endif + +/************************************************************************* + * @brief isTestingActivated + * The isTestingActivated function determines whether a tester has successfully \n + * logged in to activate testing functionality. + * @details + * Inputs : testerLoggedIn + * Outputs : none + * @param none + * @return TRUE if a tester has logged in to activate testing, FALSE if not + *************************************************************************/ +BOOL isTestingActivated( void ) +{ + return testerLoggedIn; +} + +/************************************************************************* + * @brief sendTestAckResponseMsg + * The sendTestAckResponseMsg function constructs a simple response \n + * message for a handled test message and queues it for transmit on the \n + * appropriate UART channel. + * @details + * Inputs : none + * Outputs : response message constructed and queued for transmit. + * @param msgID : ID of handled message that we are responding to + * @param ack : TRUE if test message was handled successfully, FALSE if not + * @return TRUE if response message successfully queued for transmit, FALSE if not + *************************************************************************/ +static BOOL sendTestAckResponseMsg( MSG_ID_T msgID, BOOL ack ) +{ + BOOL result; + MESSAGE_T msg; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = msgID; + msg.hdr.payloadLen = sizeof( U08 ); + msg.payload[ 0 ] = (U08)ack; + + // 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 handleTesterLogInRequest + * The handleTesterLogInRequest function handles a request to login as a \n + * tester. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTesterLogInRequest( MESSAGE_T *message ) +{ + // verify pass code + // TODO - placeholder - how do we want to authenticate tester? + if ( ( 3 == message->hdr.payloadLen ) && ( 0x31 == message->payload[ 0 ] ) && ( 0x32 == message->payload[ 1 ] ) && ( 0x33 == message->payload[ 2 ] ) ) + { + testerLoggedIn = TRUE; + } + else + { + testerLoggedIn = FALSE; + } + // respond to would be tester + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, testerLoggedIn ); +} + +/************************************************************************* + * @brief + * The handleTestDGMessageRequest function handles a request to add a \n + * DG message to the received message queue. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestDGMessageRequest( MESSAGE_T *message ) +{ + MESSAGE_WRAPPER_T dgMessage; + U32 msgLen = (U32)(message->hdr.payloadLen); + U08 *msgBytes = (U08*)(&(dgMessage)); + BOOL result; + + memcpy( msgBytes, message->payload, msgLen ); + + // add HD message to received message queue + result = addToMsgQueue( MSG_Q_IN, &dgMessage ); + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/************************************************************************* + * @brief handleTestWatchdogCheckInStateOverrideRequest + * The handleTestWatchdogCheckInStateOverrideRequest function handles a \n + * request to override the check-in status of a given task. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +DATA_ARRAY_OVERRIDE_HANDLER_FUNC_U32( BOOL, handleTestWatchdogCheckInStateOverrideRequest, testSetWatchdogTaskCheckInOverride, testResetWatchdogTaskCheckInOverride ) + +/************************************************************************* + * @brief handleTestAlarmStateOverrideRequest + * The handleTestAlarmStateOverrideRequest function handles a request to \n + * override the active status of a given alarm. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +DATA_ARRAY_OVERRIDE_HANDLER_FUNC_U32( BOOL, handleTestAlarmStateOverrideRequest, testSetAlarmStateOverride, testResetAlarmStateOverride ) + +/************************************************************************* + * @brief + * The handleTestLoadCellOverrideRequest function handles a request to \n + * override the value read from the given load cell. + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +DATA_ARRAY_OVERRIDE_HANDLER_FUNC_U32( BOOL, handleTestLoadCellOverrideRequest, testSetLoadCellOverride, testResetLoadCellOverride ) + +/************************************************************************* + * @brief handleSetRTCTimestamp + * The handleSetRTCTimestamp function handles a request to write time and + * date to RTC + * @details + * Inputs : none + * Outputs : message handled + * @param message : a pointer to the message to handle + * @return none + *************************************************************************/ +void handleSetRTCTimestamp( MESSAGE_T *message ) +{ + BOOL result; + U08 seconds = message->payload[0]; + U08 minutes = message->payload[1]; + U08 hours = message->payload[2]; + U08 days = message->payload[3]; + U08 months = message->payload[4]; + U32 years; + memcpy(&years, &message->payload[5], sizeof(U32)); + + // TODO: Change setRTCTimestamp to return a boolean for this + result = TRUE; + + setRTCTimestamp( seconds, minutes, hours, days, months, years ); + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +}