/************************************************************************** * * 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 SystemCommMessages.c * * @author (last) Quang Nguyen * @date (last) 26-Aug-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include // for memcpy() #include "reg_system.h" #include "Accel.h" #include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "DrainPump.h" #include "FPGA.h" #include "Heaters.h" #include "LoadCell.h" #include "MessagePayloads.h" #include "ModeStandby.h" #include "ModeRecirculate.h" #include "MsgQueues.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" #include "Reservoirs.h" #include "ROPump.h" #include "RTC.h" #include "SystemComm.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TemperatureSensors.h" #include "Utilities.h" #include "Valves.h" #include "WatchdogMgmt.h" /** * @addtogroup SystemCommMessages * @{ */ // ********** private definitions ********** #define ACK_REQUIRED TRUE ///< Require an ACK. #define ACK_NOT_REQUIRED FALSE ///< Not require an ACK. #ifdef DEBUG_ENABLED #define DEBUG_EVENT_MAX_TEXT_LEN 40 #endif // ********** private data ********** static BOOL testerLoggedIn = FALSE; ///< Flag indicates whether tester logged in or not. static volatile U16 nextSeqNo = 1; ///< Next sequence number. // ********** 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 * The serializeMessage function serializes a given message into a given * array of bytes. A sequence # is added to the message here and the ACK * bit of the sequence # is set if ACK is required per parameter. A sync byte * is inserted at the beginning of the message and an 8-bit CRC is appended to * the end of the message. The message is queued for transmission in the given buffer. * @details Inputs: none * @details 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 = FALSE; 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_DG_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 * The sendACKMsg function constructs and queues for transmit an ACK message * for a given received message. * @details Inputs: none * @details 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 * The sendTestAckResponseMsg function constructs a simple response message for * a handled test message and queues it for transmit on the appropriate UART channel. * @details Inputs: none * @details 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 * The broadcastAlarmTriggered function constructs an alarm triggered msg to * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details 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 * The broadcastAlarmCleared function constructs an alarm cleared msg to be * broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details 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 * The broadcastAccelData function constructs an accelerometer data msg to * be broadcast and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: accelerometer data broadcast msg constructed and queued. * @param x X axis vector magnitude (in g) * @param y Y axis vector magnitude (in g) * @param z Z axis vector magnitude (in g) * @param xm max X axis vector magnitude (in g) * @param ym max Y axis vector magnitude (in g) * @param zm max Z axis vector magnitude (in g) * @param xt X axis tilt (in degrees) * @param yt Y axis tilt (in degrees) * @param zt Z axis tilt (in degrees) * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastAccelData( F32 x, F32 y, F32 z, F32 xm, F32 ym, F32 zm, F32 xt, F32 yt, F32 zt ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; ACCEL_DATA_PAYLOAD_T payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_ACCELEROMETER_DATA; msg.hdr.payloadLen = sizeof( ACCEL_DATA_PAYLOAD_T ); payload.x = x; payload.y = y; payload.z = z; payload.xMax = xm; payload.yMax = ym; payload.zMax = zm; payload.xTilt = xt; payload.yTilt = yt; payload.zTilt = zt; memcpy( payloadPtr, &payload, sizeof( ACCEL_DATA_PAYLOAD_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 broadcastRTCEpoch function constructs an epoch msg to be broadcast * and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details 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 * broadcast message and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: DG operation mode msg constructed and queued * @param mode current operation mode of the DG. * @param subMode current sub-mode of the current operation mode of the DG. * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastDGOperationMode( U32 mode, U32 subMode ) { 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 ) + 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_DG_BROADCAST, ACK_NOT_REQUIRED ); return result; } /*********************************************************************//** * @brief * The broadcastLoadCellData function sends out load cell data. * @details Inputs: none * @details 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 broadcastValvesStates function sends out DG valves states. * @details Inputs: none * @details Outputs: Valves states msg constructed and queued * @param valvesStates valves states * refer to setFPGAValveStates function in FPGA.c for details * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastValvesStates( U16 valvesStates ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_VALVES_STATES; msg.hdr.payloadLen = sizeof( U16 ); memcpy( payloadPtr, &valvesStates, 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_BROADCAST, ACK_NOT_REQUIRED ); return result; } /*********************************************************************//** * @brief * The broadcastHeatersData function sends out DG heaters data * @details Inputs: heaters data * @details Outputs: heatears data msg constructed and queued * @param mainPrimaryDC main primary heater duty cycle * @param smallPrimaryDC small primary heater duty cycle * @param trimmerDC trimmer heater duty cycle * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastHeatersData ( U32 mainPrimaryDC, U32 smallPrimaryDC, U32 trimmerDC ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; HEATERS_DATA_T payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_HEATERS_DATA; msg.hdr.payloadLen = sizeof( HEATERS_DATA_T ); payload.mainPrimayHeaterDC = mainPrimaryDC; payload.smallPrimaryHeaterDC = smallPrimaryDC; payload.trimmerHeaterDC = trimmerDC; memcpy( payloadPtr, &payload, sizeof( HEATERS_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 * @details 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 drain pump data. * @details Inputs: none * @details Outputs: Drain pump data msg constructed and queued * @param tgtSpeed target speed for drain pump in RPM * @param dac set DAC value * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastDrainPumpData( U32 tgtSpeed, U32 dac ) { 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.dacValue = dac; 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 broadcastConcentratePumpData function sends out concentrate pumps' data. * @details Inputs: none * @details Outputs: concentrate pump data msg constructed and queued * @param cp1TgtSpeed target speed for concentrate pump CP1 * @param measuredCP1Speed measured speed for concentrate pump CP1 using hall sense * @param cp2TgtSpeed target speed for concentrate pump CP2 * @param measuredCP2Speed measured speed for concentrate pump CP2 using hall sense * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastConcentratePumpData( void * concentratePumpDataPtr ) { BOOL result; MESSAGE_T msg; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_CONCENTRATE_PUMP_DATA; msg.hdr.payloadLen = sizeof( CONCENTRATE_PUMP_DATA_T ); memcpy( &msg.payload, concentratePumpDataPtr, sizeof( CONCENTRATE_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 * @details 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 * @details 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_RESERVOIR_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; } /*********************************************************************//** * @brief * The broadcastTemperatureSensorsData function sends out DG temperature * sensors data. * @details Inputs: none * @details Outputs: temperature sensors data message constructed and queued * @param sensorsValue sensors value array * @param byteLength payload length in bytes * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastTemperatureSensorsData ( U08 *sensorsValue, U32 byteLength ) { BOOL result; MESSAGE_T msg; U08 *payloadPtr = msg.payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_TEMPERATURE_DATA; msg.hdr.payloadLen = byteLength; memcpy( payloadPtr, sensorsValue, byteLength ); // 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 broadcastConductivityData function sends out conductivity data. * @details Inputs: none * @details Outputs: conductivity data message constructed and queued * @param roRejectionRatio RO rejection ratio * @param cpi water inlet conductivity data * @param cpo water outlet conductivity data * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ BOOL broadcastConductivityData( void * conductivityDataPtr ) { BOOL result; MESSAGE_T msg; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_CONDUCTIVITY_DATA; msg.hdr.payloadLen = sizeof( CONDUCTIVITY_DATA_T ); memcpy( &msg.payload, conductivityDataPtr, sizeof( CONDUCTIVITY_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 * from the HD. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handlePowerOffWarning( MESSAGE_T *message ) { if ( message->hdr.payloadLen == 0 ) { signalPowerOffWarning(); } } /*********************************************************************//** * @brief * The handleSetDialysateTemperatureCmd function handles a dialysate temperature * set points message from the HD. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleSetDialysateTemperatureCmd( MESSAGE_T *message ) { BOOL result = FALSE; if ( message->hdr.payloadLen == sizeof( TARGET_TEMPS_PAYLOAD_T ) ) { TARGET_TEMPS_PAYLOAD_T payload; result = TRUE; memcpy( &payload, message->payload, sizeof( TARGET_TEMPS_PAYLOAD_T ) ); setPrimaryHeaterTargetTemperature( payload.targetPrimaryHeaterTemp ); setTrimmerHeaterTargetTemperature( payload.targetTrimmerHeaterTemp ); } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } /*********************************************************************//** * @brief * The handleFWVersionCmd function handles a FW version request message. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleFWVersionCmd( MESSAGE_T *message ) { MESSAGE_T msg; DG_VERSIONS_T payload; U08 *payloadPtr = msg.payload; // populate payload payload.major = (U08)DG_VERSION_MAJOR; payload.minor = (U08)DG_VERSION_MINOR; payload.micro = (U08)DG_VERSION_MICRO; payload.build = (U16)DG_VERSION_BUILD; getFPGAVersions( &payload.fpgaId, &payload.fpgaMajor, &payload.fpgaMinor, &payload.fpgaLab ); // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_VERSION; msg.hdr.payloadLen = sizeof( DG_VERSIONS_T ); // fill message payload memcpy( payloadPtr, &payload, sizeof( DG_VERSIONS_T ) ); // 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 * from the HD. * @details Inputs: none * @details 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 ) ) { RESERVOIR_ID_T reservoirID; U32 resID; result = TRUE; memcpy( &resID, message->payload, sizeof( U32 ) ); reservoirID = (RESERVOIR_ID_T)resID; setActiveReservoirCmd( 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 * @details 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 ) ); startFillCmd( 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 * @details 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( DRAIN_CMD_T ) ) { DRAIN_CMD_T drainCmd; result = TRUE; memcpy( &drainCmd, message->payload, sizeof( DRAIN_CMD_T ) ); startDrainCmd( drainCmd ); } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } /*********************************************************************//** * @brief * The handleStartStopTreatmentMsg function handles a treatment start/stop * message from the HD. * @details Inputs: none * @details 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; memcpy( &startingTreatment, message->payload, sizeof( U32 ) ); if ( DG_MODE_STAN == getCurrentOperationMode() && TRUE == startingTreatment ) { result = requestDGStart(); } else if ( DG_MODE_CIRC == getCurrentOperationMode() && FALSE == startingTreatment ) { result = requestDGStop(); } } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } /*********************************************************************//** * @brief * The handleStartStopTrimmerHeaterCmd function handles a trimmer heater start/stop * command message from the HD. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleStartStopTrimmerHeaterCmd( MESSAGE_T *message ) { BOOL result = FALSE; if ( message->hdr.payloadLen == sizeof( U32 ) ) { BOOL startingHeater; memcpy( &startingHeater, message->payload, sizeof( U32 ) ); if ( TRUE == startingHeater ) { result = startTrimmerHeaterCmd(); } else { result = stopTrimmerHeaterCmd(); } } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } /*********************************************************************//** * @brief * The handleSampleWaterCmd function handles a sample water command from the HD. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleSampleWaterCmd( MESSAGE_T *message ) { BOOL result = FALSE; if ( message->hdr.payloadLen == 0 ) { if ( DG_MODE_STAN == getCurrentOperationMode() ) { result = requestWaterSample(); } } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); } /*********************************************************************//** * @brief * The handleSetRTCTimestamp function handles a request to write time and * date to RTC * @details Inputs: none * @details 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 )); result = setRTCTimestamp( seconds, minutes, hours, days, months, years ); // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleStartStopPrimaryHeater function handles a request start or * stop the primary heater * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return result *************************************************************************/ BOOL handleStartStopPrimaryHeater( MESSAGE_T * message ) { BOOL result = FALSE; if ( message->hdr.payloadLen == sizeof( U32 ) ) { BOOL startingHeater; memcpy( &startingHeater, message->payload, sizeof( U32 ) ); if ( TRUE == startingHeater ) { result = startPrimaryHeater(); } else { stopPrimaryHeater(); result = TRUE; } } sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ #ifdef DEBUG_ENABLED /*********************************************************************//** * @brief * The sendDebugData function sends debug data out to the PC port. * @details * @details Inputs: none * @details Outputs: PC serial port * @param dbgData Pointer to debug data * @param len number of bytes of debug data * @return TRUE if debug data was successfully queued for transmit, FALSE if not *************************************************************************/ 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; } /*********************************************************************//** * @brief * The sendDebugDataToUI function sends debug string to the UI for logging. * @details * @details Inputs: none * @details Outputs: Message constructed and queued for transmit * @param str Pointer to debug string * @return none *************************************************************************/ void sendDebugDataToUI( U08 *str ) { MESSAGE_T msg; U32 txtLen = strlen( (char*)str ); U08 *payloadPtr = msg.payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_DG_DEBUG_EVENT; msg.hdr.payloadLen = DEBUG_EVENT_MAX_TEXT_LEN + 1; // add 1 byte for null terminator if ( txtLen <= DEBUG_EVENT_MAX_TEXT_LEN ) { memcpy( payloadPtr, str, txtLen + 1 ); // 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_2_UI, ACK_NOT_REQUIRED ); } } #endif /*********************************************************************//** * @brief * The isTestingActivated function determines whether a tester has successfully * logged in to activate testing functionality. * @details Inputs: testerLoggedIn * @details Outputs: none * @return TRUE if a tester has logged in to activate testing, FALSE if not *************************************************************************/ BOOL isTestingActivated( void ) { return testerLoggedIn; } /*********************************************************************//** * @brief * The sendTestAckResponseMsg function constructs a simple response message for * a handled test message and queues it for transmit on the appropriate UART channel. * @details Inputs: none * @details 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 * The handleTesterLogInRequest function handles a request to login as a tester. * @details Inputs: none * @details 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 handleTestWatchdogCheckInStateOverrideRequest function handles a * request to override the check-in status of a given task. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestWatchdogCheckInStateOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetWatchdogTaskCheckInOverride( payload.index, (BOOL)(payload.state.u32) ); } else { result = testResetWatchdogTaskCheckInOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestAlarmStateOverrideRequest function handles a request to * override the active status of a given alarm. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestAlarmStateOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetAlarmStateOverride( payload.index, payload.state.u32 ); } else { result = testResetAlarmStateOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestLoadCellOverrideRequest function handles a request to * override the value read from the given load cell. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestLoadCellOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetLoadCellOverride( payload.index, payload.state.f32 ); } else { result = testResetLoadCellOverride( payload.index ); } } //respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestTemperatureSensorsOverrideRequest function handles a * request to override a temperatures sensor's value. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestTemperatureSensorsOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetMeasuredTemperatureOverride( payload.index, payload.state.f32 ); } else { result = testResetMeasuredTemperatureOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestTemperatureSensorsDataPublishOverrideRequest function handles * a request to override the publish interval of temperature sensors data. * @details * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestTemperatureSensorsDataPublishOverrideRequest( 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 = testSetTemperatureSensorsPublishIntervalOverride( payload.state.u32 ); } else { result = testResetTemperatureSensorsPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestHeatersDataPublishOverrideRequest function handles * a request to override the publish interval of heaters data. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestHeatersDataPublishOverrideRequest( 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 = testSetHeatersPublishIntervalOverride( payload.state.u32 ); } else { result = testResetHeatersPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestLoadCellDataBroadcastIntervalOverrideRequest function handles * a request to override the broadcast interval for load cell data. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestLoadCellDataBroadcastIntervalOverrideRequest( 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 = testSetLoadCellDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetLoadCellDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestPressureSensorOverrideRequest function handles a request to * override the value read from the given pressure sensor. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestPressureSensorOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetDGPressureSensorOverride( payload.index, payload.state.f32 ); } else { result = testResetDGPressureSensorOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestPressureDataBroadcastIntervalOverrideRequest function handles * a request to override the broadcast interval for load cell data. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestPressureDataBroadcastIntervalOverrideRequest( 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 = testSetPressuresDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetPressuresDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestROPumpSetPointOverrideRequest function handles a request to * override the RO pump pressure set point (in PSI). * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestROPumpSetPointOverrideRequest( 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 = testSetTargetROPumpPressureOverride( payload.state.u32 ); } else { result = testResetTargetROPumpPressureOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestROMeasuredFlowOverrideRequest function handles a request to * override the RO flow rate. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestROMeasuredFlowOverrideRequest( 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 = testSetMeasuredROFlowRateOverride( payload.state.f32 ); } else { result = testResetMeasuredROFlowRateOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestROPumpDataBroadcastIntervalOverrideRequest function handles * a request to override the broadcast interval for RO pump data. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestROPumpDataBroadcastIntervalOverrideRequest( 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 = testSetROPumpDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetROPumpDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestDrainPumpSetPointOverrideRequest function handles a request to * override the drain pump speed set point (in RPM). * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestDrainPumpSetPointOverrideRequest( 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 = testSetTargetDrainPumpSpeedOverride( payload.state.u32 ); } else { result = testResetTargetDrainPumpSpeedOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestDrainPumpDataBroadcastIntervalOverrideRequest function handles * a request to override the broadcast interval for drain pump data. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestDrainPumpDataBroadcastIntervalOverrideRequest( 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 = testSetDrainPumpDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetDrainPumpDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestValveStateOverrideRequest function handles a request to * override the state value read from the given valve. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestValveStateOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetValveStateOverride( payload.index, payload.state.u32 ); } else { result = testResetValveStateOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestValvesStatesPublishIntervalOverrideRequest function handles * a request to override the publish interval of valves states from the given valve. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestValvesStatesPublishIntervalOverrideRequest( 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 = testSetValvesStatesPublishIntervalOverride( payload.state.u32 ); } else { result = testResetValvesStatesPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestDGSafetyShutdownOverrideRequest function handles a * request to override the safety shutdown signal. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestDGSafetyShutdownOverrideRequest( 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 = testSetSafetyShutdownOverride( payload.state.u32 ); } else { result = testResetSafetyShutdownOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestDGAccelOverrideRequest function handles a request to * override the measured accelerometer sensor readings. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestDGAccelOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetAccelAxisOverride( payload.index, payload.state.f32 ); } else { result = testResetAccelAxisOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestDGAccelMaxOverrideRequest function handles a request to * override the measured accelerometer sensor maximum readings. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestDGAccelMaxOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetAccelMaxOverride( payload.index, payload.state.f32 ); } else { result = testResetAccelMaxOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestDGAccelBroadcastIntervalOverrideRequest function handles a * request to override the broadcast interval for accelerometer data messages. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestDGAccelBroadcastIntervalOverrideRequest( 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 = testSetAccelDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetAccelDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleSetAccelCalibration function handles a request to set * accelerometer calibration factors. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleSetAccelCalibration( MESSAGE_T *message ) { BOOL result = FALSE; if ( message->hdr.payloadLen == sizeof( ACCEL_CAL_PAYLOAD_T ) ) { ACCEL_CAL_PAYLOAD_T payload; memcpy( &payload, message->payload, sizeof( ACCEL_CAL_PAYLOAD_T ) ); result = setAccelCalibration( payload.xOffset, payload.yOffset, payload.zOffset ); } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestSetConductivityOverrideRequest function handles a * request to override a conductivity sensor's value * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestSetConductivityOverrideRequest( 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 ) ); if ( FALSE == payload.reset ) { result = testSetConductivityOverride( payload.index, payload.state.f32 ); } else { result = testResetConductivityOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleTestSetConductivityDataPublishIntervalOverrideRequest function * handles a request to override the publish interval of conductivity sensors data * @details * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleTestSetConductivityDataPublishIntervalOverrideRequest( 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 = testSetConductivityDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetConductivityDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleDGSoftwareResetRequest function handles a request to * perform a software reset on DG. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleDGSoftwareResetRequest( MESSAGE_T *message ) { BOOL result = FALSE; // verify payload length if ( 0 == message->hdr.payloadLen ) { // tester must be logged in if ( TRUE == isTestingActivated() ) { result = TRUE; // reset will prevent this from getting transmitted systemREG1->SYSECR = ( 0x2 << 14 ); // reset processor } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleConcentratePumpMeasuredSpeedOverride function handles a request * to override a concentrate pump measured speed value. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleConcentratePumpMeasuredSpeedOverride( 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 ) ); if ( FALSE == payload.reset ) { result = testSetConcentratePumpMeasuredSpeedOverride( payload.index, payload.state.f32 ); } else { result = testResetConcentratePumpMeasuredSpeedOverride( payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleSetConcentratePumpTargetSpeed function handles a request to * override a concentrate pump's target speed value. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleSetConcentratePumpTargetSpeed( 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 = testSetConcentratePumpTargetSpeedOverride( payload.index, payload.state.f32 ); } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleConcentratePumpStateChangeRequest function handles a request to * change the concentrate pumps' state. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleConcentratePumpStateChangeRequest( 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 ) && ( TRUE == isTestingActivated() ) ) { result = TRUE; memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); if ( ( BOOL )payload.state.u32 ) { requestConcentratePumpsOn( ( CONCENTRATE_PUMPS_T )payload.index ); } else { requestConcentratePumpsOff( ( CONCENTRATE_PUMPS_T )payload.index ); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /*********************************************************************//** * @brief * The handleConcentratePumpPublishIntervalOverride function handles a request * to override a concentrate pump's publish interval value. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle * @return none *************************************************************************/ void handleConcentratePumpPublishIntervalOverride( 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 = testSetConcentratePumpDataPublishIntervalOverride( payload.state.u32 ); } else { result = testResetConcentratePumpDataPublishIntervalOverride(); } } // respond to request sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } /**@}*/