Index: firmware/.launches/DG.launch =================================================================== diff -u -r439894cb0508e69af3ece09ae57a62feac09e3f2 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/.launches/DG.launch (.../DG.launch) (revision 439894cb0508e69af3ece09ae57a62feac09e3f2) +++ firmware/.launches/DG.launch (.../DG.launch) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -1,9 +1,13 @@ + + + + @@ -13,4 +17,5 @@ + Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -r2851a8bc8f6180634f47b96feb00e4c0054252d3 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 2851a8bc8f6180634f47b96feb00e4c0054252d3) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -54,9 +54,10 @@ /// Enumeration of drain pump states. typedef enum DrainPump_States { - DRAIN_PUMP_OFF_STATE = 0, ///< Drain pump off state. - DRAIN_PUMP_CONTROL_TO_TARGET_STATE, ///< Drain pump control to target state. - NUM_OF_DRAIN_PUMP_STATES ///< Number of drain pump states. + DRAIN_PUMP_OFF_STATE = 0, ///< Drain pump off state + DRAIN_PUMP_OPEN_LOOP_STATE, ///< Drain pump open loop state + DRAIN_PUMP_CONTROL_TO_TARGET_STATE, ///< Drain pump control to target state + NUM_OF_DRAIN_PUMP_STATES ///< Number of drain pump states } DRAIN_PUMP_STATE_T; /// Enumeration of drain pump self test states. @@ -85,16 +86,18 @@ static BOOL isDrainPumpOn = FALSE; ///< Drain pump is currently running static U32 drainPumpDAC = 0; ///< initial drain pump DAC value static U32 drainPumpDACSet = 0; ///< currently set drain pump DAC value -static PUMP_CONTROL_MODE_T drainPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< requested drain pump control mode. -static PUMP_CONTROL_MODE_T drainPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< currently set drain pump control mode. +static PUMP_CONTROL_MODE_T drainPumpControlMode = PUMP_CONTROL_MODE_OPEN_LOOP; ///< requested drain pump control mode. +static PUMP_CONTROL_MODE_T drainPumpControlModeSet = PUMP_CONTROL_MODE_OPEN_LOOP; ///< currently set drain pump control mode. static OVERRIDE_U32_T drainPumpDataPublishInterval = { DRAIN_PUMP_DATA_PUB_INTERVAL, DRAIN_PUMP_DATA_PUB_INTERVAL, 0, 0 }; ///< interval (in ms) at which to publish RO flow data to CAN bus. static OVERRIDE_U32_T targetDrainPumpSpeed = { 0, 0, 0, 0 }; ///< Target RO pressure (in PSI). static U32 drainControlTimerCounter = 0; ///< determines when to perform control on drain pump static DRAIN_PUMP_SELF_TEST_STATE_T drainPumpSelfTestState = DRAIN_PUMP_SELF_TEST_STATE_START; ///< current drain pump self test state -static U32 drainPumpSelfTestTimerCount = 0; ///< timer counter for drain pump self test +static U32 drainPumpSelfTestTimerCount = 0; ///< timer counter for drain pump self test + +static BOOL hasClosedLoopBeenRequested = FALSE; // ********** private function prototypes ********** @@ -237,24 +240,43 @@ #endif #endif - // if we've been given a pressure, transition to control to target state - if ( getTargetDrainPumpSpeed() > 0 ) + // if we've been given a pressure, transition to open loop state + // as it will not be controlling and it will just run + if ( getTargetDrainPumpSpeed() > 0 && !hasClosedLoopBeenRequested ) { // set drain pump enable pin SET_DRAIN_PUMP_ENABLE(); // set drain pump control mode drainPumpControlModeSet = drainPumpControlMode; // Check if drain pump mode is closed loop - if ( drainPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) - { - resetPIController( PI_CONTROLLER_ID_DRAIN_PUMP, MIN_DRAIN_PUMP_RPM_TARGET ); - } + //if ( drainPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) + //{ + // resetPIController( PI_CONTROLLER_ID_DRAIN_PUMP, MIN_DRAIN_PUMP_RPM_TARGET ); + //} // set drain pump DAC drainPumpDACSet = drainPumpDAC; setFPGADrainPumpSpeed( drainPumpDACSet ); // set pump to on isDrainPumpOn = TRUE; - result = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; + result = DRAIN_PUMP_OPEN_LOOP_STATE; + } + + if ( hasClosedLoopBeenRequested ) + { + // set drain pump enable pin + SET_DRAIN_PUMP_ENABLE(); + // set drain pump control mode + drainPumpControlModeSet = drainPumpControlMode; + + + resetPIController( PI_CONTROLLER_ID_DRAIN_PUMP, MIN_DRAIN_PUMP_RPM_TARGET ); + + // set drain pump DAC + drainPumpDACSet = drainPumpDAC; + setFPGADrainPumpSpeed( drainPumpDACSet ); + // set pump to on + isDrainPumpOn = TRUE; + result = DRAIN_PUMP_CONTROL_TO_TARGET_STATE; } return result; Index: firmware/App/Controllers/DrainPump.h =================================================================== diff -u -rbe5079c95b05c303878763b458dc0854a600317e -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Controllers/DrainPump.h (.../DrainPump.h) (revision be5079c95b05c303878763b458dc0854a600317e) +++ firmware/App/Controllers/DrainPump.h (.../DrainPump.h) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -39,7 +39,10 @@ void execDrainPumpMonitor( void ); void execDrainPumpController( void ); -BOOL setDrainPumpTargetSpeed( U32 rpm, PUMP_CONTROL_MODE_T mode ); +BOOL setDrainPumpTargetSpeed( U32 rpm, PUMP_CONTROL_MODE_T mode ); + + + void signalDrainPumpHardStop( void ); SELF_TEST_STATUS_T execDrainPumpTest( void ); Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r2851a8bc8f6180634f47b96feb00e4c0054252d3 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 2851a8bc8f6180634f47b96feb00e4c0054252d3) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -65,17 +65,18 @@ #define RO_FLOW_ADC_TO_LPM_FACTOR 10909.0909 ///< conversion factor from ADC counts to LPM (liters/min) for RO flow rate (multiply this by inverse of FPGA reading). #define ROP_FLOW_TO_PWM_DC(flow) ((F32)(flow / 1000)) //TODO dara ///< Initial conversion factor from target flow rate to PWM duty cycle estimate -#define ROP_RAMP_UP_P_COEFFICIENT 0.009 //TODO dara -#define ROP_RAMP_UP_I_COEFFICIENT 0.00 //TODO dara -#define ROP_FLOW_TARGET_TOLERANCE 20U //TODO dara ///< Tolerance in between the target flow rate and the actual flow rate in mL +#define ROP_RAMP_UP_P_COEFFICIENT 0.0 //TODO dara +#define ROP_RAMP_UP_I_COEFFICIENT 0.09 //TODO dara +#define ROP_FLOW_TARGET_TOLERANCE 0.1 //TODO dara ///< Tolerance in between the target flow rate and the actual flow rate in mL /// Enumeration of RO pump states. typedef enum ROPump_States { - RO_PUMP_OFF_STATE = 0, ///< RO pump off state. - RO_PUMP_RAMP_UP_STATE, ///< RO pump ramp up to target flow rate state. - RO_PUMP_CONTROL_TO_TARGET_STATE, ///< RO pump control to target pressure state. - NUM_OF_RO_PUMP_STATES ///< Number of RO pump states. + RO_PUMP_OFF_STATE = 0, ///< RO pump off state + RO_PUMP_OPEN_LOOP_STATE, ///< RO pump open loop state + RO_PUMP_RAMP_UP_STATE, ///< RO pump ramp up to target flow rate state + RO_PUMP_CONTROL_TO_TARGET_STATE, ///< RO pump control to target pressure state + NUM_OF_RO_PUMP_STATES ///< Number of RO pump states } RO_PUMP_STATE_T; /// Enumeration of RO pump self test states. @@ -91,7 +92,12 @@ // pin assignments for pump test DIP switch 0 #define RO_PUMP_TEST_SPI5_PORT_MASK 0x00000100 // (ENA - re-purposed as input GPIO) // dialIn pump stop and direction macros -#define GET_DIP_SW0_TEST() ( ( mibspiREG5->PC2 & RO_PUMP_TEST_SPI5_PORT_MASK ) != 0 ) +#define GET_DIP_SW0_TEST() ( ( mibspiREG5->PC2 & RO_PUMP_TEST_SPI5_PORT_MASK ) != 0 ) + +// TODO: Remove the below code. FOR TESTING ONLY +#define PRIMARY_HEATER_MIBSPI1_PORT_MASK 0x00000002 // (CS1 - re-purposed as input GPIO) +#define TOGGLEPUMP() (( mibspiREG1->PC2 & PRIMARY_HEATER_MIBSPI1_PORT_MASK ) != 0) +//TODO: Remove the above code. FOR TESTING ONLY // ********** private data ********** @@ -105,7 +111,7 @@ //static OVERRIDE_U32_T roPumpDataPublishInterval = { 0, 0, 0, 0 }; //From branch Remove ///< interval (in ms) at which to publish RO flow data to CAN bus. //static OVERRIDE_U32_T targetROPumpPressure = { 0, 0, 0, 0 }; //From branch ///< Target RO pressure (in PSI). //TODO remove -static OVERRIDE_U32_T targetROPumpFlowRate = { 0, 0, 0, 0 }; //From Branch ///< Target RO flow rate (in LPM_) // TODO dara +static OVERRIDE_F32_T targetROPumpFlowRate = { 0, 0, 0, 0 }; //From Branch ///< Target RO flow rate (in LPM_) // TODO dara static OVERRIDE_U32_T roPumpDataPublishInterval = { RO_PUMP_DATA_PUB_INTERVAL, RO_PUMP_DATA_PUB_INTERVAL, 0, 0 }; ///< interval (in ms) at which to publish RO flow data to CAN bus. static OVERRIDE_U32_T targetROPumpPressure = { 0, 0, 0, 0 }; ///< Target RO pressure (in PSI). static OVERRIDE_F32_T measuredROFlowRateLPM = { 0.0, 0.0, 0.0, 0 }; ///< measured RO flow rate (in LPM). @@ -148,7 +154,7 @@ MIN_RO_PUMP_PWM_DUTY_CYCLE, MAX_RO_PUMP_PWM_DUTY_CYCLE ); // Initialize the P controller during ramp up - initializePIController( P_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_PWM_DUTY_CYCLE, + initializePIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_PWM_DUTY_CYCLE, ROP_RAMP_UP_P_COEFFICIENT, ROP_RAMP_UP_I_COEFFICIENT, MIN_RO_PUMP_PWM_DUTY_CYCLE, MAX_RO_PUMP_PWM_DUTY_CYCLE ); } @@ -190,15 +196,15 @@ return result; } -BOOL setROPumpTargetFlowRate( U32 roFlowRate, PUMP_CONTROL_MODE_T mode ) +BOOL setROPumpTargetFlowRate( F32 roFlowRate ) { BOOL result = FALSE; - if ( roFlowRate < MAX_RO_FLOWRATE && roFlowRate >= MIN_RO_FLOWRATE ) + if ( roFlowRate < MAX_RO_FLOWRATE_LPM && roFlowRate >= MIN_RO_FLOWRATE_LPM ) { targetROPumpFlowRate.data = roFlowRate; - roPumpControlMode = mode; - roPumpPWMDutyCyclePct = ROP_FLOW_TO_PWM_DC( roFlowRate ); + roPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; + roPumpPWMDutyCyclePct = roFlowRate; } else // requested pressure out of range { @@ -218,7 +224,7 @@ *************************************************************************/ void signalROPumpHardStop( void ) { - targetROPumpPressure.data = 0; + targetROPumpFlowRate.data = 0; stopROPump(); roPumpState = RO_PUMP_OFF_STATE; roPumpPWMDutyCyclePct = 0.0; @@ -283,6 +289,9 @@ { case RO_PUMP_OFF_STATE: roPumpState = handleROPumpOffState(); + break; + + case RO_PUMP_OPEN_LOOP_STATE: break; case RO_PUMP_RAMP_UP_STATE: @@ -349,17 +358,18 @@ #endif } #endif -#endif +#endif - // If there is a + // If there is a flow, transition to P controller to get + // the corresponding pressure of that flow if ( getTargetROPumpFlowRate() > 0 ) { roPumpControlModeSet = roPumpControlMode; // set initial PWM duty cycle - roPumpPWMDutyCyclePctSet = roPumpPWMDutyCyclePct; + roPumpPWMDutyCyclePctSet = ROP_FLOW_TO_PWM_DC( getTargetROPumpFlowRate() ); setROPumpControlSignalPWM( roPumpPWMDutyCyclePctSet ); // reset controller - resetPIController( P_CONTROLLER_ID_RO_PUMP_RAMP_UP, roPumpPWMDutyCyclePctSet ); + resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, roPumpPWMDutyCyclePctSet ); // set pump to on isROPumpOn = TRUE; result = RO_PUMP_RAMP_UP_STATE; @@ -378,7 +388,8 @@ // set pump to on isROPumpOn = TRUE; result = RO_PUMP_CONTROL_TO_TARGET_STATE; - }*/ + }*/ + return result; } @@ -401,14 +412,14 @@ if ( fabs( actualFlowRate - targetFlowRate ) > ROP_FLOW_TARGET_TOLERANCE ) { - F32 newPWM = runPIController( P_CONTROLLER_ID_RO_PUMP_RAMP_UP, targetFlowRate, actualFlowRate ); + F32 newPWM = runPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, targetFlowRate, actualFlowRate ); roPumpPWMDutyCyclePctSet = newPWM; setROPumpControlSignalPWM( newPWM ); } else { // Reset the P controller for the flow rate - resetPIController( P_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_PWM_DUTY_CYCLE ); + resetPIController( I_CONTROLLER_ID_RO_PUMP_RAMP_UP, MIN_RO_PUMP_PWM_DUTY_CYCLE ); tgtROPumpPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); roPumpControlModeSet = roPumpControlMode; @@ -442,18 +453,22 @@ // control at set interval if ( ++roControlTimerCounter >= ROP_CONTROL_INTERVAL ) { - if ( roPumpControlModeSet == PUMP_CONTROL_MODE_CLOSED_LOOP ) - { - F32 tgtPres = tgtROPumpPressure; - F32 actPres = measuredROPumpPressure; - F32 newPWM; + F32 actualPressure = getMeasuredDGPressure( PRESSURE_SENSOR_RO_PUMP_OUTLET ); + + //if ( OVERRIDE_KEY == targetROPumpFlowRate.override ) + //{ + // targetFlowRate = targetROPumpFlowRate.ovData; + //} + F32 newPWM = runPIController( PI_CONTROLLER_ID_RO_PUMP, tgtROPumpPressure, actualPressure ); + roPumpPWMDutyCyclePctSet = newPWM; + setROPumpControlSignalPWM( newPWM ); -#ifndef EMC_TEST_BUILD +/*#ifndef EMC_TEST_BUILD newPWM = runPIController( PI_CONTROLLER_ID_RO_PUMP, tgtPres, actPres ); roPumpPWMDutyCyclePctSet = newPWM; setROPumpControlSignalPWM( newPWM ); -#endif - } +#endif*/ + roControlTimerCounter = 0; } @@ -537,9 +552,9 @@ * @return the current target RO pressure (in PSI). *************************************************************************/ //U32 getTargetROPumpPressure( void ) -U32 getTargetROPumpFlowRate( void ) +F32 getTargetROPumpFlowRate( void ) { - U32 result = targetROPumpFlowRate.data; + F32 result = targetROPumpFlowRate.data; if ( OVERRIDE_KEY == targetROPumpFlowRate.override ) { @@ -692,7 +707,7 @@ return result; } -BOOL testSetTargetROPumpFlowRateOverride( U32 value ) +BOOL testSetTargetROPumpFlowRateOverride( F32 value ) { BOOL result = FALSE; @@ -701,7 +716,7 @@ targetROPumpFlowRate.ovInitData = targetROPumpFlowRate.data; // backup current target pressure targetROPumpFlowRate.ovData = value; targetROPumpFlowRate.override = OVERRIDE_KEY; - result = setROPumpTargetFlowRate( value, roPumpControlMode ); + result = setROPumpTargetFlowRate( value ); } return result; @@ -717,7 +732,7 @@ targetROPumpFlowRate.override = OVERRIDE_RESET; targetROPumpFlowRate.ovInitData = 0; targetROPumpFlowRate.ovData = 0; - result = setROPumpTargetFlowRate( targetROPumpFlowRate.data, roPumpControlMode ); + result = setROPumpTargetFlowRate( targetROPumpFlowRate.data ); } return result; Index: firmware/App/Controllers/ROPump.h =================================================================== diff -u -rbe5079c95b05c303878763b458dc0854a600317e -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision be5079c95b05c303878763b458dc0854a600317e) +++ firmware/App/Controllers/ROPump.h (.../ROPump.h) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -33,8 +33,8 @@ #define MAX_RO_PRESSURE 140 ///< Maximum target RO outlet pressure (in PSI). //TODO remove #define MIN_RO_PRESSURE 100 ///< Minimum target RO outlet pressure (in PSI). //TODO remove -#define MAX_RO_FLOWRATE 2000 //TODO dara -#define MIN_RO_FLOWRATE 300 //TODO dara +#define MAX_RO_FLOWRATE_LPM 1.2 //TODO dara +#define MIN_RO_FLOWRATE_LPM 0.2 //TODO dara // ********** public function prototypes ********** @@ -44,22 +44,22 @@ BOOL setROPumpTargetPressure( U32 roPressure, PUMP_CONTROL_MODE_T mode ); //TODO remove -BOOL setROPumpTargetFlowRate( U32 roFlowRate, PUMP_CONTROL_MODE_T mode ); +BOOL setROPumpTargetFlowRate( F32 roFlowRate ); void signalROPumpHardStop( void ); BOOL isReverseOsmosisPumpOn( void ); SELF_TEST_STATUS_T execROPumpTest( void ); -DATA_GET_PROTOTYPE( U32, getTargetROPumpFlowRate ); //TODO change +DATA_GET_PROTOTYPE( F32, getTargetROPumpFlowRate ); //TODO change DATA_GET_PROTOTYPE( F32, getMeasuredROFlowRate ); BOOL testSetROPumpDataPublishIntervalOverride( U32 value ); BOOL testResetROPumpDataPublishIntervalOverride( void ); BOOL testSetTargetROPumpPressureOverride( U32 value ); //TODO remove BOOL testResetTargetROPumpPressureOverride( void ); //TODO remove -BOOL testSetTargetROPumpFlowRateOverride( U32 value ); +BOOL testSetTargetROPumpFlowRateOverride( F32 value ); BOOL testResetTargetROPumpFlowRateOverride( void ); BOOL testSetMeasuredROFlowRateOverride( F32 value ); Index: firmware/App/DGCommon.h =================================================================== diff -u -r3f3729899d6811c763bc8e5ef9baf54a2d5c9cfe -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 3f3729899d6811c763bc8e5ef9baf54a2d5c9cfe) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -36,9 +36,9 @@ // #define TASK_TIMING_OUTPUT_ENABLED 1 // re-purposes drain pump enable pin for task timing // #define BETA_V1_BUILD 1 // #define DISABLE_HEATERS_AND_TEMPS 1 - #define ENABLE_DIP_SWITCHES 1 - #define EMC_TEST_BUILD 1 - #define ALARMS_DEBUG 1 +// #define ENABLE_DIP_SWITCHES 1 +// #define EMC_TEST_BUILD 1 +// #define ALARMS_DEBUG 1 // #define HEATERS_DEBUG 1 // #define PRESSURES_DEBUG 1 #include Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -rbe5079c95b05c303878763b458dc0854a600317e -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision be5079c95b05c303878763b458dc0854a600317e) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -37,11 +37,13 @@ #define HEAT_DISINFECTION_TARGET_TEMP 85U ///< Heat disinfection target temperature #define HEAT_DISINFECTION_OVERALL_TIME 60U ///< Heat disinfection overall time in minutes -#define HEAT_DISINFECTION_RECIRC_PATH_TIME 5U -#define HEAT_DISINFECTION_FLUSH_TIME 3U +#define HEAT_DISINFECTION_RECIRC_PATH_TIME_MINS 5U +#define HEAT_DISINFECTION_FLUSH_TIME_MINS 3U +#define HEAT_DISINFECTION_OVERALL_TIME_MINS 30U -#define DRAIN_PUMP_TARGET_RPM 2800U -#define RO_PUMP_TARGET_PRESSURE 110U +#define DRAIN_PUMP_TARGET_DELTA_PRESSURE 0U +#define DRAIN_PUMP_TARGET_RPM 2800U +#define RO_PUMP_TARGET_FLOW_RATE_LPM 0.9 // ********** private data ********** @@ -54,7 +56,8 @@ static void setActuatorsToStop( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStart( void ); -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacuateDialysate( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir1( void ); +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir2( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWater( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectHeatWater( void ); static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectRecirculationPath( void ); @@ -102,17 +105,20 @@ *************************************************************************/ U32 execHeatDisinfectMode( void ) { - // execute current heat disinfect state switch ( heatDisinfectionState ) { case DG_HEAT_DISINFECT_STATE_START: heatDisinfectionState = handleHeatDisinfectStart(); break; - case DG_HEAT_DISINFECT_STATE_EVACUATE_DIALYSATE: - heatDisinfectionState = handleHeatDisinfectEvacuateDialysate(); + case DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1: + heatDisinfectionState = handleHeatDisinfectEvacDialysateReservoir1(); break; + case DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_2: + heatDisinfectionState = handleHeatDisinfectEvacDialysateReservoir2(); + break; + case DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER: heatDisinfectionState = handleHeatDisinfectFillWithWater(); break; @@ -174,9 +180,10 @@ *************************************************************************/ void startDGHeatDisinfect( void ) { - // make sure DG is not in the middle of something and it is in standby + // NOTE: make sure DG is not in the middle of something and it is in standby // - transitionToHeatDisinfectMode(); // Call request start heat disinfect + initHeatDisinfectMode(); + requestNewOperationMode( DG_MODE_HEAT ); } /*********************************************************************//** @@ -189,16 +196,49 @@ *************************************************************************/ void stopDGHeatDisinfect( void ) { - heatDisinfectionState = DG_HEAT_DISINFECT_STATE_START; // request standby mode - setActuatorsToStop(); // Not needed + //heatDisinfectionState = DG_HEAT_DISINFECT_STATE_START; // request standby mode + setActuatorsToStop(); + requestNewOperationMode( DG_MODE_STAN ); } // ********** private function definitions ********** static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStart( void ) { - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_START; + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1; + setActuatorsToStop(); + + /*setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState ( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState ( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NC ); + setValveState ( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState ( VRF, VALVE_STATE_R1_C_TO_NC ); + + setROPumpTargetFlowRate( 0 ); + //setDrainPumpTargetSpeed( DRAIN_PUMP_TARGET_RPM, PUMP_CONTROL_MODE_OPEN_LOOP ); + stopInletUVReactor(); + stopOutletUVReactor(); + stopPrimaryHeater(); + stopTrimmerHeater();*/ + + //TODO FOR TESTING ONLY, REMOVE + state = DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH; + //TODO FOR TESTING ONLY, REMOVE + + return state; +} + +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir1( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVAC_DIALYSATE_RESERVOIR_1; + setValveState ( VPI, VALVE_STATE_OPEN ); setValveState ( VBF, VALVE_STATE_OPEN ); setValveState ( VSP, VALVE_STATE_CLOSED ); @@ -211,22 +251,21 @@ setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); - setROPumpTargetPressure( 0, PUMP_CONTROL_MODE_CLOSED_LOOP ); - setDrainPumpTargetSpeed( 0, PUMP_CONTROL_MODE_OPEN_LOOP ); + setROPumpTargetFlowRate( 0 ); + signalDrainPumpHardStop(); stopInletUVReactor(); stopOutletUVReactor(); stopPrimaryHeater(); stopTrimmerHeater(); return state; } -static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacuateDialysate( void ) + +static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectEvacDialysateReservoir2( void ) { - DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_EVACUATE_DIALYSATE; - return state; - } + static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectFillWithWater( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FILL_WITH_WATER; @@ -247,10 +286,33 @@ { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_RECIRC_PATH; - return state; + setValveState ( VPI, VALVE_STATE_OPEN ); + setValveState ( VBF, VALVE_STATE_OPEN ); + setValveState ( VSP, VALVE_STATE_CLOSED ); + setValveState ( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState ( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + //setValveState ( VDR, VALVE_STATE_RECIRC_C_TO_NC ); For the actual heat disinfection + setValveState ( VDR, VALVE_STATE_DRAIN_C_TO_NO ); // For sending the fluid to drain for pump testing + setValveState ( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState ( VRO, VALVE_STATE_R2_C_TO_NO ); + setValveState ( VRD, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState ( VRF, VALVE_STATE_R2_C_TO_NO ); + setROPumpTargetFlowRate( 0.7 ); + //setDrainPumpTargetSpeed( 0, PUMP_CONTROL_MODE_CLOSED_LOOP ); + //startInletUVReactor(); + //startOutletUVReactor(); + //startPrimaryHeater(); + //stopTrimmerHeater(); + // For debugging purposes only REMOVE + state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2; + // For debugging purposes only REMOVE + + return state; } + static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectReservoir1To2( void ) { DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_DISINFECT_RESERVOIR_1_TO_2; @@ -293,9 +355,8 @@ setValveState ( VPD, VALVE_STATE_DRAIN_C_TO_NC ); //TODO composition pumps - - setROPumpTargetPressure( 0, PUMP_CONTROL_MODE_CLOSED_LOOP ); - setDrainPumpTargetSpeed( 0, PUMP_CONTROL_MODE_OPEN_LOOP ); + signalROPumpHardStop(); + signalDrainPumpHardStop(); stopInletUVReactor(); stopOutletUVReactor(); stopPrimaryHeater(); Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -r8f5feed92f41a476d5656038bcdfe884e17bd593 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 8f5feed92f41a476d5656038bcdfe884e17bd593) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -55,7 +55,7 @@ /* FAUL */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* SERV */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* INIT */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, - /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_CIRC, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_NLEG, DG_MODE_CHEM }, + /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_CIRC, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM }, /* SOLO */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_NLEG }, /* CIRC */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_CIRC, DG_MODE_FILL, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* FILL */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_CIRC, DG_MODE_FILL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r8f5feed92f41a476d5656038bcdfe884e17bd593 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 8f5feed92f41a476d5656038bcdfe884e17bd593) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -229,7 +229,7 @@ // TODO Remove the below line // Initialize the valves - fpgaActuatorSetPoints.fpgaValveStates = 0x015F; + //fpgaActuatorSetPoints.fpgaValveStates = 0x015F; // TODO Remove the above line // initialize fpga comm buffers Index: firmware/App/Services/PIControllers.c =================================================================== diff -u -r53af4ddc318cc5299f15e3cc1ce506b166e6e156 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 53af4ddc318cc5299f15e3cc1ce506b166e6e156) +++ firmware/App/Services/PIControllers.c (.../PIControllers.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -57,7 +57,7 @@ { // Kp Ki uMax uMin ref meas err esw esum ctrl { 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, // PI_CONTROLLER_ID_RO_PUMP - { 0.0, 0.0, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, // P_CONTROLLER_ID_RO_PUMP_RAMP_UP + { 0.0, 0.0, 0.99, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, // I_CONTROLLER_ID_RO_PUMP_RAMP_UP { 0.0, 0.0, 3000, 300, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, // PI_CONTROLLER_ID_DRAIN_PUMP { 0.0, 0.0, 0.89, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }, // PI_CONTROLLER_ID_PRIMARY_HEATER { 0.0, 0.0, 0.50, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } // PI_CONTROLLER_ID_TRIMMER_HEATER Index: firmware/App/Services/PIControllers.h =================================================================== diff -u -rbe5079c95b05c303878763b458dc0854a600317e -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Services/PIControllers.h (.../PIControllers.h) (revision be5079c95b05c303878763b458dc0854a600317e) +++ firmware/App/Services/PIControllers.h (.../PIControllers.h) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -34,7 +34,7 @@ typedef enum ControllerList { PI_CONTROLLER_ID_RO_PUMP = 0, ///< RO Pump controller. - P_CONTROLLER_ID_RO_PUMP_RAMP_UP, ///< RO Pump controller during ramp up time. + I_CONTROLLER_ID_RO_PUMP_RAMP_UP, ///< RO Pump controller during ramp up time. PI_CONTROLLER_ID_DRAIN_PUMP, ///< Drain Pump controller. PI_CONTROLLER_ID_PRIMARY_HEATER, ///< Primary Heater controller. PI_CONTROLLER_ID_TRIMMER_HEATER, ///< Trimmer Heater controller. Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r53af4ddc318cc5299f15e3cc1ce506b166e6e156 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 53af4ddc318cc5299f15e3cc1ce506b166e6e156) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -14,1143 +14,1103 @@ * @date (original) 05-Nov-2019 * ***************************************************************************/ - -#include // for memcpy() - -#include "can.h" -#include "sci.h" -#include "sys_dma.h" - -#include "SystemComm.h" -#include "Comm.h" -#include "Interrupts.h" -#include "Timers.h" -#include "Utilities.h" -#include "SystemCommMessages.h" - -/** - * @addtogroup SystemComm - * @{ - */ -// ********** private definitions ********** - -#define NUM_OF_CAN_OUT_BUFFERS 5 ///< # of CAN buffers for transmit -#define NUM_OF_CAN_IN_BUFFERS 6 ///< # of CAN buffers for receiving -#ifndef DEBUG_ENABLED - #define NUM_OF_MSG_IN_BUFFERS 6 ///< # of Msg buffers for receiving -#else - #define NUM_OF_MSG_IN_BUFFERS 7 - #define SCI1_RECEIVE_DMA_REQUEST 30 - #define SCI1_TRANSMIT_DMA_REQUEST 31 -#endif - -#define CAN_XMIT_PACKET_TIMEOUT_MS 200 ///< if transmitted CAN frame does not cause a transmit complete interrupt within this time, re-send or move on -#define MAX_XMIT_RETRIES 5 ///< maximum number of retries on no transmit complete interrupt timeout - -#define HD_COMM_TIMEOUT_IN_MS 2000 ///< HD has not sent any broadcast messages for this much time - -#define MAX_COMM_CRC_FAILURES 5 ///< maximum number of CRC errors within window period before alarm -#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window - -#define MSG_NOT_ACKED_TIMEOUT_MS ( MS_PER_SECOND * 1 ) ///< maximum time for a Denali message that requires ACK to be ACK'd -#define MSG_NOT_ACKED_MAX_RETRIES 3 ///< maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm -#define PENDING_ACK_LIST_SIZE 25 ///< maximum number of Delanli messages that can be pending ACK at any given time - -#pragma pack(push, 1) +#include // for memcpy() -/// Record for transmitted message that is pending acknowledgement from receiver. -typedef struct -{ - BOOL used; - U16 seqNo; - U16 retries; - U32 timeStamp; - COMM_BUFFER_T channel; - U32 msgSize; - U08 msg[ MAX_ACK_MSG_SIZE ]; -} PENDING_ACK_RECORD_T; - -#pragma pack(pop) - -// ********** private data ********** +#include "can.h" +#include "sci.h" +#include "sys_dma.h" -/// Array of out-going CAN buffers. -const COMM_BUFFER_T CAN_OUT_BUFFERS[ NUM_OF_CAN_OUT_BUFFERS ] = -{ - COMM_BUFFER_OUT_CAN_DG_ALARM, - COMM_BUFFER_OUT_CAN_DG_2_HD, +#include "SystemComm.h" +#include "Comm.h" +#include "Interrupts.h" +#include "Timers.h" +#include "Utilities.h" +#include "SystemCommMessages.h" + +// ********** private definitions ********** + +#define NUM_OF_CAN_OUT_BUFFERS 4 // # of CAN buffers for transmit +#define NUM_OF_CAN_IN_BUFFERS 6 // # of CAN buffers for receiving +#ifndef DEBUG_ENABLED + #define NUM_OF_MSG_IN_BUFFERS 6 // # of Msg buffers for receiving +#else + #define NUM_OF_MSG_IN_BUFFERS 7 // # of Msg buffers for receiving - 1 is UART + #define SCI1_RECEIVE_DMA_REQUEST 30 + #define SCI1_TRANSMIT_DMA_REQUEST 31 +#endif + +#define CAN_XMIT_PACKET_TIMEOUT_MS 200 ///< if transmitted CAN frame does not cause a transmit complete interrupt within this time, re-send or move on + +#define HD_COMM_TIMEOUT_IN_MS 2000 + +#define MAX_COMM_CRC_FAILURES 5 +#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) + +#define MSG_NOT_ACKED_TIMEOUT_MS ( MS_PER_SECOND * 1 ) +#define MSG_NOT_ACKED_MAX_RETRIES 3 +#define PENDING_ACK_LIST_SIZE 25 + +#pragma pack(push, 1) + +typedef struct +{ + BOOL used; + U16 seqNo; + U16 retries; + U32 timeStamp; + COMM_BUFFER_T channel; + U32 msgSize; + U08 msg[ MAX_ACK_MSG_SIZE ]; +} PENDING_ACK_RECORD_T; + +#pragma pack(pop) + +// ********** private data ********** + +const COMM_BUFFER_T CAN_OUT_BUFFERS[ NUM_OF_CAN_OUT_BUFFERS ] = +{ + COMM_BUFFER_OUT_CAN_DG_ALARM, + COMM_BUFFER_OUT_CAN_DG_2_HD, COMM_BUFFER_OUT_CAN_DG_BROADCAST, - COMM_BUFFER_OUT_CAN_PC, - COMM_BUFFER_OUT_CAN_DG_2_UI -}; + COMM_BUFFER_OUT_CAN_PC +}; -/// Array of in-coming CAN buffers. -const COMM_BUFFER_T MSG_IN_BUFFERS[ NUM_OF_MSG_IN_BUFFERS ] = -{ - COMM_BUFFER_IN_CAN_HD_ALARM, - COMM_BUFFER_IN_CAN_UI_ALARM, - COMM_BUFFER_IN_CAN_HD_2_DG, - COMM_BUFFER_IN_CAN_HD_BROADCAST, - COMM_BUFFER_IN_CAN_UI_BROADCAST, - COMM_BUFFER_IN_CAN_PC, -#ifdef DEBUG_ENABLED - COMM_BUFFER_IN_UART_PC -#endif -}; +const COMM_BUFFER_T MSG_IN_BUFFERS[ NUM_OF_MSG_IN_BUFFERS ] = +{ + COMM_BUFFER_IN_CAN_HD_ALARM, + COMM_BUFFER_IN_CAN_UI_ALARM, + COMM_BUFFER_IN_CAN_HD_2_DG, + COMM_BUFFER_IN_CAN_HD_BROADCAST, + COMM_BUFFER_IN_CAN_UI_BROADCAST, + COMM_BUFFER_IN_CAN_PC, +#ifdef DEBUG_ENABLED + COMM_BUFFER_IN_UART_PC +#endif +}; -static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; ///< Keep last packet sent on CAN bus in case we need to re-send. -static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; ///< Keep channel last packet was sent on CAN bus in case we need to re-send. -static U32 lastCANPacketSentTimeStamp = 0; ///< Keep time last packet sent on CAN bus so we can timeout on transmission attempt. - -static PENDING_ACK_RECORD_T pendingAckList[ PENDING_ACK_LIST_SIZE ]; ///< list of outgoing messages that are awaiting an ACK - -static volatile BOOL dgIsOnlyCANNode = TRUE; ///< flag indicating whether DG is alone on CAN bus. -static U32 canXmitRetryCtr = 0; ///< counter for CAN transmit retries. -static volatile BOOL hdIsCommunicating = FALSE; ///< has HD sent a message since last check -static volatile U32 timeOfLastHDCheckIn = 0; ///< last time we received an HD broadcast - +static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; +static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; +static U32 lastCANPacketSentTimeStamp = 0; + #ifdef DEBUG_ENABLED - // debug buffers - static U08 pcXmitPacket[ 1024 ]; - static U08 pcRecvPacket[ PC_MESSAGE_PACKET_SIZE ] = { 0, 0, 0, 0, 0, 0, 0, 0 }; - // DMA control records - static g_dmaCTRL pcDMAXmitControlRecord; - static g_dmaCTRL pcDMARecvControlRecord; +static U08 pcXmitPacket[ 1024 ]; +static U08 pcRecvPacket[ PC_MESSAGE_PACKET_SIZE ] = { 0, 0, 0, 0, 0, 0, 0, 0 }; #endif -// ********** private function prototypes ********** - -static void clearCANXmitBuffers( void ); - -static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); -static U32 transmitNextCANPacket( void ); - -static void processIncomingData( void ); -static S32 parseMessageFromBuffer( U08 *data, U32 len ); -static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ); -static void processReceivedMessages( void ); -static void processReceivedMessage( MESSAGE_T *message ); - -static void checkForCommTimeouts( void ); -static void checkTooManyBadMsgCRCs( void ); - -static BOOL matchACKtoPendingACKList( S16 seqNo ); -static void checkPendingACKList( void ); - +static PENDING_ACK_RECORD_T pendingAckList[ PENDING_ACK_LIST_SIZE ]; // list of outgoing messages that are awaiting an ACK + +// DMA control records +static g_dmaCTRL pcDMAXmitControlRecord; // DMA transmit control record (UART-debug) +static g_dmaCTRL pcDMARecvControlRecord; // DMA receive control record (UART-debug) + +static volatile BOOL hdIsCommunicating = FALSE; // has HD sent a message since last check +static volatile U32 timeOfLastHDCheckIn = 0; // last time we received an HD broadcast + +static U32 badCRCTimeStamps[ MAX_COMM_CRC_FAILURES ]; // time of last five bad message CRCs (wrapping list) +static U32 badCRCListIdx = 0; // where next bad message CRC time stamp will go in list +static U32 badCRCListCount = 0; // # of bad CRCs in the list + +// ********** private function prototypes ********** + #ifdef DEBUG_ENABLED static void initUARTAndDMA( void ); static U32 transmitNextUARTPacket( void ); #endif -/*********************************************************************//** - * @brief - * The initSystemComm function initializes the SystemComm module. - * @details - * Inputs : none - * Outputs : SystemComm module initialized. - * @return none - *************************************************************************/ -void initSystemComm( void ) -{ - U32 i; - -#ifdef DEBUG_ENABLED - // initialize UART and DMA for PC communication - initUARTAndDMA(); -#endif - - // initialize bad message CRC time windowed count - initTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC, MAX_COMM_CRC_FAILURES, MAX_COMM_CRC_FAILURE_WINDOW_MS ); - // initialize pending ACK list - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - pendingAckList[ i ].used = FALSE; - } -} - -/*********************************************************************//** - * @brief - * The isHDCommunicating function determines whether the HD is communicating \n - * with the DG. - * @details - * Inputs : hdIsCommunicating - * Outputs : none - * @return TRUE if HD has broadcast since last call, FALSE if not - *************************************************************************/ -BOOL isHDCommunicating( void ) -{ - return hdIsCommunicating; + +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); +static U32 transmitNextCANPacket( void ); + +static void processIncomingData( void ); +static S32 parseMessageFromBuffer( U08 *data, U32 len ); +static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ); +static void processReceivedMessages( void ); +static void processReceivedMessage( MESSAGE_T *message ); + +static void checkForCommTimeouts( void ); +static void checkTooManyBadMsgCRCs( void ); + +static BOOL matchACKtoPendingACKList( S16 seqNo ); +static void checkPendingACKList( void ); + +/************************************************************************* + * @brief initSystemComm + * The initSystemComm function initializes the SystemComm module. + * @details + * Inputs : none + * Outputs : SystemComm module initialized. + * @param none + * @return none + *************************************************************************/ +void initSystemComm( void ) +{ + U32 i; + +#ifdef DEBUG_ENABLED + // initialize UART and DMA for PC communication + initUARTAndDMA(); +#endif + + // initialize bad message CRC list + for ( i = 0; i < MAX_COMM_CRC_FAILURES; i++ ) + { + badCRCTimeStamps[ i ] = 0; + } + + // initialize pending ACK list + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + pendingAckList[ i ].used = FALSE; + } } -/*********************************************************************//** +/************************************************************************* * @brief - * The isDGOnlyCANNode function determines whether the DG is the only node \n - * currently on the CAN bus. + * The isHDCommunicating function determines whether the HD is communicating \n + * with the DG. * @details - * Inputs : dgIsOnlyCANNode + * Inputs : hdIsCommunicating * Outputs : none - * @return TRUE if DG is only node on CAN bus, FALSE if not + * @param none + * @return TRUE if HD has broadcast since last call, FALSE if not *************************************************************************/ -BOOL isDGOnlyCANNode( void ) +BOOL isHDCommunicating( void ) { - return dgIsOnlyCANNode; -} - -/*********************************************************************//** - * @brief - * The execSystemCommRx function manages received data from other sub-systems. - * @details - * Inputs : none - * Outputs : Incoming frames processed. - * @return none - *************************************************************************/ -void execSystemCommRx( void ) -{ - // parse messages from comm buffers and queue them - processIncomingData(); - - // process received messages in the queue - processReceivedMessages(); - - // check for sub-system comm timeouts - checkForCommTimeouts(); - - // check ACK list for messages that need to be re-sent because they haven't been ACK'd - checkPendingACKList(); -} - -/*********************************************************************//** - * @brief - * The execSystemCommTx function manages data to be transmitted to other \n - * sub-systems. - * @details - * Inputs : none - * Outputs : Next outgoing frame transmitted. - * @return none - *************************************************************************/ -void execSystemCommTx( void ) -{ - // if CAN transmitter is idle, start transmitting any pending packets - if ( ( FALSE == dgIsOnlyCANNode ) && ( FALSE == isCAN1TransmitInProgress() ) ) - { - transmitNextCANPacket(); - } - else - { // generally, transmitter should not be busy at time of this function call - check timeout just in case so we don't get stuck waiting forever - if ( TRUE == didTimeout( lastCANPacketSentTimeStamp, CAN_XMIT_PACKET_TIMEOUT_MS ) ) + BOOL result = hdIsCommunicating; + + hdIsCommunicating = FALSE; + + return result; +} + +/************************************************************************* + * @brief execSystemCommRx + * The execSystemCommRx function manages received data from other sub-systems. + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void execSystemCommRx( void ) +{ + // parse messages from comm buffers and queue them + processIncomingData(); + + // process received messages in the queue + processReceivedMessages(); + + // check for sub-system comm timeouts + checkForCommTimeouts(); + + // check ACK list for messages that need to be re-sent because they haven't been ACK'd + checkPendingACKList(); +} + +/************************************************************************* + * @brief execSystemCommTx + * The execSystemCommTx function manages data to be transmitted to other \n + * sub-systems. + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +void execSystemCommTx( void ) +{ + // if CAN transmitter is idle, start transmitting any pending packets + if ( FALSE == isCAN1TransmitInProgress() ) + { + transmitNextCANPacket(); + } + else + { // generally, transmitter should not be busy at time of this function call - check timeout just in case so we don't get stuck waiting forever + if ( TRUE == didTimeout( lastCANPacketSentTimeStamp, CAN_XMIT_PACKET_TIMEOUT_MS ) ) { - // assume last packet was not successfully transmitted. Re-send last packet. - if ( ++canXmitRetryCtr <= MAX_XMIT_RETRIES ) + // TODO - depending on why we timed out, we may need to reset CAN controller??? + // assume last packet was not successfully transmitted. TODO - Re-send last packet? Or should we move on? + canTransmit( canREG1, lastCANPacketSentChannel, lastCANPacketSent ); + } + } + +#ifdef DEBUG_ENABLED + // if UART transmitter is idle, start transmitting any pending packets + if ( FALSE == isSCI1DMATransmitInProgress() ) + { + transmitNextUARTPacket(); + } +#endif +} + +/************************************************************************* + * @brief handleCANMsgInterrupt + * The handleCANMsgInterrupt function handles a CAN message interrupt. \n + * This may have occurred because a CAN packet transmission has completed \n + * or because a CAN packet has been received. The appropriate handler is \n + * called. + * @details + * Inputs : none + * Outputs : message interrupt handled + * @param srcCANBox : which CAN message box triggered this interrupt + * @return none + *************************************************************************/ +void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ) +{ + // message interrupt is for a transmit message box? + if ( TRUE == isCANBoxForXmit( srcCANBox ) ) + { + U32 bytesXmitted = transmitNextCANPacket(); + + if ( 0 == bytesXmitted ) + { + signalCANXmitsCompleted(); + } + } + else if ( TRUE == isCANBoxForRecv( srcCANBox ) ) + { + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + + // get CAN packet received on given CAN message box + if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) + { + U32 result = canGetData( canREG1, srcCANBox, data ); + + // if packet retrieved, add to buffer + if ( result != 0 ) { - canTransmit( canREG1, lastCANPacketSentChannel, lastCANPacketSent ); + // add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) + addToCommBuffer( srcCANBox, data, CAN_MESSAGE_PAYLOAD_SIZE ); + } + } + } + else + { + // shouldn't get here - not an active message box + // s/w fault? + } +} + +/************************************************************************* + * @brief handleUARTMsgRecvPacketInterrupt + * The handleUARTMsgRecvPacketInterrupt function handles a DMA UART receive \n + * packet completed interrupt. + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ #ifdef DEBUG_ENABLED - { - char debugStr[100]; - sprintf( debugStr, "SystemComm-DG resend Last Frame.\n" ); - sendDebugDataToUI( (U08*)debugStr ); - } +void handleUARTMsgRecvPacketInterrupt( void ) +{ + // buffer received packet + addToCommBuffer( COMM_BUFFER_IN_UART_PC, pcRecvPacket, PC_MESSAGE_PACKET_SIZE ); + // prepare to receive next packet + dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); + dmaSetChEnable( DMA_CH1, DMA_HW ); + setSCI1DMAReceiveInterrupt(); +} #endif + +/************************************************************************* + * @brief handleUARTMsgXmitPacketInterrupt + * The handleUARTMsgXmitPacketInterrupt function handles a DMA UART transmit \n + * packet completed interrupt. + * @details + * Inputs : none + * Outputs : none + * @param none + * @return none + *************************************************************************/ +#ifdef DEBUG_ENABLED +void handleUARTMsgXmitPacketInterrupt( void ) +{ + U32 bytesXmitted = transmitNextUARTPacket(); + + if ( 0 == bytesXmitted ) + { + signalSCI1XmitsCompleted(); + } +} +#endif + +/************************************************************************* + * @brief initUARTAndDMA + * The initUARTAndDMA function initializes the SCI1 peripheral and the DMA \n + * to go with it for PC communication. + * @details + * Inputs : none + * Outputs : SCI1 and DMA initialized + * @param none + * @return none + *************************************************************************/ +#ifdef DEBUG_ENABLED +static void initUARTAndDMA( void ) +{ + // Enable DMA block transfer complete interrupts + dmaEnableInterrupt( DMA_CH1, BTC ); + dmaEnableInterrupt( DMA_CH3, BTC ); + // assign DMA channels to h/w DMA requests + dmaReqAssign( DMA_CH1, SCI1_RECEIVE_DMA_REQUEST ); + dmaReqAssign( DMA_CH3, SCI1_TRANSMIT_DMA_REQUEST ); + // set DMA channel priorities + dmaSetPriority( DMA_CH1, HIGHPRIORITY ); + dmaSetPriority( DMA_CH3, LOWPRIORITY ); + + // initialize PC DMA Transmit Control Record + pcDMAXmitControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + pcDMAXmitControlRecord.DADD = (U32)(&(sciREG->TD)); // dest. is SCI2 xmit register + pcDMAXmitControlRecord.SADD = (U32)pcXmitPacket; // source + pcDMAXmitControlRecord.CHCTRL = 0; // no chaining + pcDMAXmitControlRecord.ELCNT = 1; // frame is 1 element + pcDMAXmitControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames + pcDMAXmitControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + pcDMAXmitControlRecord.WRSIZE = ACCESS_8_BIT; // + pcDMAXmitControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + pcDMAXmitControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed + pcDMAXmitControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment + pcDMAXmitControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + pcDMAXmitControlRecord.ELSOFFSET = 0; // not used + pcDMAXmitControlRecord.ELDOFFSET = 0; // not used + pcDMAXmitControlRecord.FRSOFFSET = 0; // not used + pcDMAXmitControlRecord.FRDOFFSET = 0; // not used + + // initialize PC DMA Receipt Control Record + pcDMARecvControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + pcDMARecvControlRecord.SADD = (U32)(&(sciREG->RD)); // source is SCI2 recv register + pcDMARecvControlRecord.DADD = (U32)pcRecvPacket; // transfer destination address + pcDMARecvControlRecord.CHCTRL = 0; // no chaining + pcDMARecvControlRecord.ELCNT = 1; // frame is 1 element + pcDMARecvControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames + pcDMARecvControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte + pcDMARecvControlRecord.WRSIZE = ACCESS_8_BIT; // + pcDMARecvControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer + pcDMARecvControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed + pcDMARecvControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment + pcDMARecvControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off + pcDMARecvControlRecord.ELDOFFSET = 0; // not used + pcDMARecvControlRecord.ELSOFFSET = 0; // not used + pcDMARecvControlRecord.FRDOFFSET = 0; // not used + pcDMARecvControlRecord.FRSOFFSET = 0; // not used + + // initiate PC packet receiving readiness via DMA + dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); + dmaSetChEnable( DMA_CH1, DMA_HW ); + setSCI1DMAReceiveInterrupt(); +} +#endif + +/************************************************************************* + * @brief isCANBoxForXmit + * The isCANBoxForXmit function determines whether a given CAN message box \n + * is configured for transmit. + * @details + * Inputs : CAN_OUT_BUFFERS[] + * Outputs : none + * @param srcCANBox : which CAN message box to check + * @return TRUE if the given CAN message box is configured for transmit, FALSE if not. + *************************************************************************/ +BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) +{ + BOOL result = FALSE; + U32 i; + + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + if ( CAN_OUT_BUFFERS[ i ] == srcCANBox ) + { + result = TRUE; + break; + } + } + + return result; +} + +/************************************************************************* + * @brief isCANBoxForRecv + * The isCANBoxForRecv function determines whether a given CAN message box \n + * is configured for receiving. + * @details + * Inputs : MSG_IN_BUFFERS[] + * Outputs : none + * @param srcCANBox : which CAN message box to check + * @return TRUE if the given CAN message box is configured for receiving, FALSE if not. + *************************************************************************/ +BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) +{ + BOOL result = FALSE; + U32 i; + + for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) + { + if ( MSG_IN_BUFFERS[ i ] == srcCANBox ) + { + result = TRUE; + break; + } + } + + return result; +} + +BOOL isDGOnlyCANNode( void ) +{ + return FALSE; +} + + +/************************************************************************* +********************** TRANSMIT SUPPORT FUNCTIONS ************************ +*************************************************************************/ + + +/************************************************************************* + * @brief findNextHighestPriorityCANPacketToTransmit + * The findNextHighestPriorityCANPacketToTransmit function gets the next \n + * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. \n + * @details + * Inputs : Output CAN Comm Buffer(s) + * Outputs : none + * @param msg : none + * @return buffer with highest priority CAN packet to transmit, \n + * COMM_BUFFER_NOT_USED if not CAN packets pending transmit found + *************************************************************************/ +static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) +{ + COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; + U32 i; + + // search for next priority CAN packet to transmit + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[ i ] ) >= CAN_MESSAGE_PAYLOAD_SIZE ) + { + result = CAN_OUT_BUFFERS[ i ]; + break; // found highest priority packet to transmit - we're done + } + } + + return result; +} + +/************************************************************************* + * @brief transmitNextCANPacket + * The transmitNextCANPacket function gets the next 8 byte packet and initiates \n + * a CAN transmit on the appropriate CAN channel. + * @details + * Inputs : Output CAN Comm Buffers + * Outputs : CAN packet transmit initiated. + * @param msg : none + * @return # of bytes transmitted + *************************************************************************/ +static U32 transmitNextCANPacket( void ) +{ + U32 result = 0; + COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); + + // if a buffer is found with a packet to transmit, get packet from buffer and transmit it + if ( buffer != COMM_BUFFER_NOT_USED ) + { + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_PAYLOAD_SIZE ); + CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned + + // if there's another CAN packet to send, send it + if ( dataSize == CAN_MESSAGE_PAYLOAD_SIZE ) + { + // we're transmitting another packet - signal transmitter is busy + signalCANXmitsInitiated(); + // remember packet data being transmitted here in case transmission fails and we need to re-send + memcpy( lastCANPacketSent, data, CAN_MESSAGE_PAYLOAD_SIZE ); + lastCANPacketSentChannel = mBox; + lastCANPacketSentTimeStamp = getMSTimerCount(); + if ( 0 != canTransmit( canREG1, mBox, data ) ) + { + result = CAN_MESSAGE_PAYLOAD_SIZE; } - // we must be only node on CAN bus - nobody is ACKing our transmitted frames else { - dgIsOnlyCANNode = TRUE; // set only CAN node flag - canXmitRetryCtr = MAX_XMIT_RETRIES; - signalCANXmitsCompleted(); // clear pending xmit flag - clearCANXmitBuffers(); // clear xmit buffers - nothing is going out right now + signalCANXmitsCompleted(); + // TODO - shouldn't get here, but let's see if we do + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, (U32)mBox ) + } + } + else + { // TODO - shouldn't get here - just testing - set first data to new s/w fault enum later + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, (U32)buffer, (U32)dataSize ) + } + } + + return result; +} + +/************************************************************************* + * @brief transmitNextUARTPacket + * The transmitNextUARTPacket function sets up and initiates a DMA transmit \n + * of the next packet pending transmit (if any) via UART. + * @details + * Inputs : Output UART Comm Buffer(s) + * Outputs : UART DMA transmit initiated. + * @param msg : none + * @return # of bytes transmitted + *************************************************************************/ #ifdef DEBUG_ENABLED +static U32 transmitNextUARTPacket( void ) +{ + U32 result = 0; + U32 dataPend = numberOfBytesInCommBuffer( COMM_BUFFER_OUT_UART_PC ); + + if ( dataPend > 0 ) + { + result = getFromCommBuffer( COMM_BUFFER_OUT_UART_PC, pcXmitPacket, dataPend ); + + // if there's data to transmit, transmit it + if ( result > 0 ) + { + signalSCI1XmitsInitiated(); + pcDMAXmitControlRecord.FRCNT = result; // set DMA transfer size + dmaSetCtrlPacket( DMA_CH3, pcDMAXmitControlRecord ); + dmaSetChEnable( DMA_CH3, DMA_HW ); + setSCI1DMATransmitInterrupt(); + } + } + + return result; +} +#endif + + +/************************************************************************* +********************** RECEIVE SUPPORT FUNCTIONS ************************* +*************************************************************************/ + + +/************************************************************************* + * @brief processIncomingData + * The processIncomingData function parses out messages from the Input \n + * Comm Buffers and adds them to the Received Message Queue. + * @details + * Inputs : Input Comm Buffers + * Outputs : Parsed message(s) added to Received Message Queue + * @param msg : none + * @return none + *************************************************************************/ +static void processIncomingData( void ) +{ + U08 data[ 512 ]; // message work space + U32 i; + BOOL badCRCDetected = FALSE; + + // queue any received messages + for ( i = 0; i < NUM_OF_MSG_IN_BUFFERS; i++ ) + { + BOOL messagesInBuffer = TRUE; // assume true at first to get into while loop + + while ( TRUE == messagesInBuffer ) + { + U32 numOfBytesInBuffer; + + // assume false so we don't get stuck in loop - only set to true if we find another complete message in buffer + messagesInBuffer = FALSE; + + // since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer + consumeBufferPaddingBeforeSync( MSG_IN_BUFFERS[ i ] ); + // do we have enough bytes in buffer for smallest message? + numOfBytesInBuffer = numberOfBytesInCommBuffer( MSG_IN_BUFFERS[ i ] ); + if ( numOfBytesInBuffer >= MESSAGE_OVERHEAD_SIZE ) + { // peek at minimum of all bytes available or max message size (+1 for sync byte) + U32 bytesPeeked = peekFromCommBuffer( MSG_IN_BUFFERS[ i ], data, MIN( numOfBytesInBuffer, sizeof( MESSAGE_WRAPPER_T ) + 1 ) ); + S32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); + + if ( msgSize > 0 ) // valid, complete message found? { - char debugStr[100]; - sprintf( debugStr, "SystemComm-DG is only node.\n" ); - sendDebugDataToUI( (U08*)debugStr ); + MESSAGE_WRAPPER_T rcvMsg; + U08 *dataPtr = data+1; // skip over sync byte + + // consume message (+sync byte) + msgSize = getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, msgSize + 1 ); + // convert received message data to a message and add to message queue + messagesInBuffer = TRUE; // keep processing this buffer + // blank the new message record + blankMessageInWrapper( &rcvMsg ); + // copy message header portion of message data to the new message + memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); + dataPtr += sizeof(MESSAGE_HEADER_T); + // copy message payload portion of message data to the new message + memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); + dataPtr += rcvMsg.msg.hdr.payloadLen; + // copy CRC portion of message data to the new message + rcvMsg.crc = *dataPtr; + // add new message to queue for later processing + addToMsgQueue( MSG_Q_IN, &rcvMsg ); + // if message from HD broadcast channel, update HD comm status + if ( COMM_BUFFER_IN_CAN_HD_BROADCAST == MSG_IN_BUFFERS[ i ] ) + { + hdIsCommunicating = TRUE; + timeOfLastHDCheckIn = getMSTimerCount(); + } } + else if ( -1 == msgSize ) // candidate message with bad CRC found? + { + badCRCDetected = TRUE; + getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, 1 ); // consume sync byte so we can re-sync + messagesInBuffer = TRUE; // keep processing this buffer + } // looks like there is a complete message in the comm buffer + } // enough data left in comm buffer to possibly be a complete message + } // while loop to get all complete messages for each comm buffer + } // for loop to check all comm buffers for messages + + // if any bad CRCs detected, see if too many + if ( TRUE == badCRCDetected ) + { + checkTooManyBadMsgCRCs(); + } +} + +/************************************************************************* + * @brief consumeBufferPaddingBeforeSync + * The consumeBufferPaddingBeforeSync function removes any bytes in a given \n + * buffer that lie before a sync byte. + * @details + * Inputs : none + * Outputs : none + * @param msg : buffer : the comm buffer to process + * @return none + *************************************************************************/ +static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ) +{ + U08 data; + U32 numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); + + // consume bytes out of buffer 1 at a time until we find the sync byte or it's empty + while ( numOfBytesInBuffer > 0 ) + { + peekFromCommBuffer( buffer, &data, 1 ); + if ( MESSAGE_SYNC_BYTE == data ) + { + break; // we found a sync - we're done + } + else // not a sync byte, so consume it + { + getFromCommBuffer( buffer, &data, 1 ); + numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); + } + } +} + +/************************************************************************* + * @brief parseMessageFromBuffer + * The parseMessageFromBuffer function looks for a complete message in a \n + * given buffer. If a message is found, its size is returned. + * @details + * Inputs : none + * Outputs : none + * @param data : pointer to byte array to search for a message + * @param len : # of bytes in the data to search + * @return size of message if found, zero if no complete message found, \n + * -1 if message found but CRC fails. + *************************************************************************/ +static S32 parseMessageFromBuffer( U08 *data, U32 len ) +{ + U32 i; + U32 payloadSize; + U32 msgSize; + S32 result = 0; + + for ( i = 0; i < len; i++ ) + { + // find sync byte + if ( MESSAGE_SYNC_BYTE == data[ i ] ) + { + U32 pos = i + 1; // skip past sync byte implemented + U32 remSize = len - pos; + + // if a minimum sized msg would fit in remaining, continue + if ( remSize >= MESSAGE_OVERHEAD_SIZE ) + { + payloadSize = data[ pos + sizeof(MESSAGE_HEADER_T) - sizeof(U08) ]; + msgSize = MESSAGE_OVERHEAD_SIZE + payloadSize; + // we now know the size of the message - we can now know if full message is contained in buffer + if ( msgSize <= remSize ) + { // check CRC to make sure it's a valid message + if ( data[i+msgSize] == crc8( &data[pos], msgSize - 1 ) ) + { + result = msgSize; // we found a complete, valid message of this size + } + else // CRC failed + { + result = -1; // we found a complete, invalid message + } + } + } + break; + } + } + + return result; +} + +/************************************************************************* + * @brief processReceivedMessages + * The processReceivedMessages function processes any messages in the \n + * received message queues. + * @details + * Inputs : Received Message Queues + * Outputs : Message(s) processed. + * @param msg : none + * @return none + *************************************************************************/ +static void processReceivedMessages( void ) +{ + BOOL isThereMsgRcvd = TRUE; // assume TRUE at first to get into while loop + MESSAGE_WRAPPER_T message; + + while ( TRUE == isThereMsgRcvd ) + { + // see if any messages received + isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN, &message ); + if ( TRUE == isThereMsgRcvd ) + { // CRC should be good because we checked it during parsing before adding to queue - but check it again for good measure + if ( message.crc == crc8( (U08*)(&message), sizeof(MESSAGE_HEADER_T) + message.msg.hdr.payloadLen ) ) + { + // if ACK, mark pending message ACK'd + if ( MSG_ID_ACK == message.msg.hdr.msgID ) + { + matchACKtoPendingACKList( message.msg.hdr.seqNo ); + } + else + { + // if received message requires ACK, queue one up + if ( message.msg.hdr.seqNo < 0 ) + { + sendACKMsg( &message.msg ); + } + // otherwise, process the received message + processReceivedMessage( &message.msg ); + } + } + else // CRC failed + { + checkTooManyBadMsgCRCs(); + } + } + } +} + +/************************************************************************* + * @brief checkForCommTimeouts + * The checkForCommTimeouts function checks for sub-system communication \n + * timeout errors. + * @details + * Inputs : timeOfLastDGCheckIn, timeOfLastUICheckIn + * Outputs : possibly a comm t/o alarm + * @param none + * @return none + *************************************************************************/ +static void checkForCommTimeouts( void ) +{ + if ( TRUE == didTimeout( timeOfLastHDCheckIn, HD_COMM_TIMEOUT_IN_MS ) ) + { + hdIsCommunicating = FALSE; +#ifndef DEBUG_ENABLED + activateAlarmNoData( ALARM_ID_HD_COMM_TIMEOUT ); // TODO - add this alarm if we're in middle of a treatment? or if in a mode that comm loss would impact badly? #endif - } - } - } - -#ifdef DEBUG_ENABLED - // if UART transmitter is idle, start transmitting any pending packets - if ( FALSE == isSCI1DMATransmitInProgress() ) - { - transmitNextUARTPacket(); - } -#endif -} - -/*********************************************************************//** - * @brief - * The handleCANMsgInterrupt function handles a CAN message interrupt. \n - * This may have occurred because a CAN packet transmission has completed \n - * or because a CAN packet has been received. The appropriate handler is \n - * called. - * @details - * Inputs : none - * Outputs : message interrupt handled - * @param srcCANBox : which CAN message box triggered this interrupt - * @return none - *************************************************************************/ -void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ) -{ - // message interrupt is for a transmit message box? - if ( TRUE == isCANBoxForXmit( srcCANBox ) ) - { - U32 bytesXmitted = transmitNextCANPacket(); - - if ( 0 == bytesXmitted ) - { - signalCANXmitsCompleted(); - } - } - else if ( TRUE == isCANBoxForRecv( srcCANBox ) ) - { - U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; - - // get CAN packet received on given CAN message box - if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) - { - U32 result = canGetData( canREG1, srcCANBox, data ); - - // if packet retrieved, add to buffer - if ( result != 0 ) - { - // add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) - addToCommBuffer( srcCANBox, data, CAN_MESSAGE_PAYLOAD_SIZE ); - } - } - } - else - { - // shouldn't get here - not an active message box - // s/w fault? - } -} - -/*********************************************************************//** - * @brief - * The handleUARTMsgRecvPacketInterrupt function handles a DMA UART receive \n - * packet completed interrupt. - * @details - * Inputs : none - * Outputs : none - * @return none - *************************************************************************/ -#ifdef DEBUG_ENABLED -void handleUARTMsgRecvPacketInterrupt( void ) -{ - // buffer received packet - addToCommBuffer( COMM_BUFFER_IN_UART_PC, pcRecvPacket, PC_MESSAGE_PACKET_SIZE ); - // prepare to receive next packet - dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); - dmaSetChEnable( DMA_CH1, DMA_HW ); - setSCI1DMAReceiveInterrupt(); -} -#endif - -/*********************************************************************//** - * @brief - * The handleUARTMsgXmitPacketInterrupt function handles a DMA UART transmit \n - * packet completed interrupt. - * @details - * Inputs : none - * Outputs : none - * @return none - *************************************************************************/ -#ifdef DEBUG_ENABLED -void handleUARTMsgXmitPacketInterrupt( void ) -{ - U32 bytesXmitted = transmitNextUARTPacket(); - - if ( 0 == bytesXmitted ) - { - signalSCI1XmitsCompleted(); - } -} -#endif - -/*********************************************************************//** - * @brief - * The initUARTAndDMA function initializes the SCI1 peripheral and the DMA \n - * to go with it for PC communication. - * @details - * Inputs : none - * Outputs : SCI1 and DMA initialized - * @return none - *************************************************************************/ -#ifdef DEBUG_ENABLED -static void initUARTAndDMA( void ) -{ - // Enable DMA block transfer complete interrupts - dmaEnableInterrupt( DMA_CH1, BTC ); - dmaEnableInterrupt( DMA_CH3, BTC ); - // assign DMA channels to h/w DMA requests - dmaReqAssign( DMA_CH1, SCI1_RECEIVE_DMA_REQUEST ); - dmaReqAssign( DMA_CH3, SCI1_TRANSMIT_DMA_REQUEST ); - // set DMA channel priorities - dmaSetPriority( DMA_CH1, HIGHPRIORITY ); - dmaSetPriority( DMA_CH3, LOWPRIORITY ); - - // initialize PC DMA Transmit Control Record - pcDMAXmitControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - pcDMAXmitControlRecord.DADD = (U32)(&(sciREG->TD)); // dest. is SCI2 xmit register - pcDMAXmitControlRecord.SADD = (U32)pcXmitPacket; // source - pcDMAXmitControlRecord.CHCTRL = 0; // no chaining - pcDMAXmitControlRecord.ELCNT = 1; // frame is 1 element - pcDMAXmitControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames - pcDMAXmitControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - pcDMAXmitControlRecord.WRSIZE = ACCESS_8_BIT; // - pcDMAXmitControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - pcDMAXmitControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed - pcDMAXmitControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment - pcDMAXmitControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - pcDMAXmitControlRecord.ELSOFFSET = 0; // not used - pcDMAXmitControlRecord.ELDOFFSET = 0; // not used - pcDMAXmitControlRecord.FRSOFFSET = 0; // not used - pcDMAXmitControlRecord.FRDOFFSET = 0; // not used - - // initialize PC DMA Receipt Control Record - pcDMARecvControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - pcDMARecvControlRecord.SADD = (U32)(&(sciREG->RD)); // source is SCI2 recv register - pcDMARecvControlRecord.DADD = (U32)pcRecvPacket; // transfer destination address - pcDMARecvControlRecord.CHCTRL = 0; // no chaining - pcDMARecvControlRecord.ELCNT = 1; // frame is 1 element - pcDMARecvControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames - pcDMARecvControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - pcDMARecvControlRecord.WRSIZE = ACCESS_8_BIT; // - pcDMARecvControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - pcDMARecvControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed - pcDMARecvControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment - pcDMARecvControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - pcDMARecvControlRecord.ELDOFFSET = 0; // not used - pcDMARecvControlRecord.ELSOFFSET = 0; // not used - pcDMARecvControlRecord.FRDOFFSET = 0; // not used - pcDMARecvControlRecord.FRSOFFSET = 0; // not used - - // initiate PC packet receiving readiness via DMA - dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); - dmaSetChEnable( DMA_CH1, DMA_HW ); - setSCI1DMAReceiveInterrupt(); -} -#endif - -/*********************************************************************//** - * @brief - * The isCANBoxForXmit function determines whether a given CAN message box \n - * is configured for transmit. - * @details - * Inputs : CAN_OUT_BUFFERS[] - * Outputs : none - * @param srcCANBox : which CAN message box to check - * @return TRUE if the given CAN message box is configured for transmit, FALSE if not. - *************************************************************************/ -BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) -{ - BOOL result = FALSE; - U32 i; - - for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) - { - if ( CAN_OUT_BUFFERS[ i ] == srcCANBox ) - { - result = TRUE; - break; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The isCANBoxForRecv function determines whether a given CAN message box \n - * is configured for receiving. - * @details - * Inputs : MSG_IN_BUFFERS[] - * Outputs : none - * @param srcCANBox : which CAN message box to check - * @return TRUE if the given CAN message box is configured for receiving, FALSE if not. - *************************************************************************/ -BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) -{ - BOOL result = FALSE; - U32 i; - - for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) - { - if ( MSG_IN_BUFFERS[ i ] == srcCANBox ) - { - result = TRUE; - break; - } - } - - return result; + } } -/*********************************************************************//** - * @brief - * The clearCANXmitBuffers function clears all CAN transmit buffers. +/************************************************************************* + * @brief checkTooManyBadMsgCRCs + * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs \n + * within a set period of time. Assumed function is being called when a new \n + * bad CRC is detected so a new bad CRC will be added to the list. * @details - * Inputs : CAN_OUT_BUFFERS[] - * Outputs : CAN transmit buffers cleared. + * Inputs : badCRCTimeStamps[], badCRCListIdx, badCRCListCount + * Outputs : possibly a "too many bad CRCs" alarm * @return none *************************************************************************/ -static void clearCANXmitBuffers( void ) +static void checkTooManyBadMsgCRCs( void ) { + U32 listTimeInMS; + + // replace oldest bad CRC in list with this new one + badCRCTimeStamps[ badCRCListIdx ] = getMSTimerCount(); + // move list index to next position (may wrap) + badCRCListIdx = INC_WRAP( badCRCListIdx, 0, MAX_COMM_CRC_FAILURES - 1 ); + // update list count + badCRCListCount = INC_CAP( badCRCListCount, MAX_COMM_CRC_FAILURES ); + // check if too many bad CRCs in window of time + listTimeInMS = calcTimeSince( badCRCTimeStamps[ badCRCListIdx ] ); + if ( ( badCRCListCount >= MAX_COMM_CRC_FAILURES ) && ( listTimeInMS <= MAX_COMM_CRC_FAILURE_WINDOW_MS ) ) + { + activateAlarmNoData( ALARM_ID_COMM_TOO_MANY_BAD_CRCS ); + } +} + +/************************************************************************* + * @brief addMsgToPendingACKList + * The addMsgToPendingACKList function adds a given message to the pending \n + * ACK list. Messages in this list will require receipt of an ACK message \n + * for this particular message within a limited time. + * @details + * Inputs : pendingAckList[] + * Outputs : pendingAckList[] + * @param msg : pointer to msg within the message data + * @param msgData : pointer to message data to add to pending ACK list + * @param len : # of bytes of message data + * @return TRUE if message added successfully, FALSE if not + *************************************************************************/ +BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ) +{ + BOOL result = FALSE; U32 i; - for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + // find first open slot in pending ACK list and add given msg data to it + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) { - clearBuffer( CAN_OUT_BUFFERS[ i ] ); + _disable_IRQ(); // slot selection needs interrupt protection + if ( FALSE == pendingAckList[ i ].used ) + { + S16 seqNo = msg->hdr.seqNo * -1; // remove ACK bit from seq # + + pendingAckList[ i ].used = TRUE; + _enable_IRQ(); + pendingAckList[ i ].seqNo = seqNo; + pendingAckList[ i ].channel = channel; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + pendingAckList[ i ].retries = MSG_NOT_ACKED_MAX_RETRIES; + pendingAckList[ i ].msgSize = len; + memcpy( pendingAckList[ i ].msg, msgData, len ); + result = TRUE; + break; + } + else + { + _enable_IRQ(); + } } -} - - -/************************************************************************* -********************** TRANSMIT SUPPORT FUNCTIONS ************************ -*************************************************************************/ - - -/*********************************************************************//** - * @brief - * The findNextHighestPriorityCANPacketToTransmit function gets the next \n - * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. \n - * @details - * Inputs : Output CAN Comm Buffer(s) - * Outputs : none - * @return buffer with highest priority CAN packet to transmit, \n - * COMM_BUFFER_NOT_USED if not CAN packets pending transmit found - *************************************************************************/ -static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) -{ - COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; - U32 i; - - // search for next priority CAN packet to transmit - for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) - { - if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[ i ] ) >= CAN_MESSAGE_PAYLOAD_SIZE ) - { - result = CAN_OUT_BUFFERS[ i ]; - break; // found highest priority packet to transmit - we're done - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The transmitNextCANPacket function gets the next 8 byte packet and initiates \n - * a CAN transmit on the appropriate CAN channel. - * @details - * Inputs : Output CAN Comm Buffers - * Outputs : CAN packet transmit initiated. - * @return # of bytes transmitted - *************************************************************************/ -static U32 transmitNextCANPacket( void ) -{ - U32 result = 0; - COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); - - // if a buffer is found with a packet to transmit, get packet from buffer and transmit it - if ( buffer != COMM_BUFFER_NOT_USED ) - { - U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; - U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_PAYLOAD_SIZE ); - CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned - - // if there's another CAN packet to send, send it - if ( dataSize == CAN_MESSAGE_PAYLOAD_SIZE ) - { - // we're transmitting another packet - signal transmitter is busy - signalCANXmitsInitiated(); - // remember packet data being transmitted here in case transmission fails and we need to re-send - memcpy( lastCANPacketSent, data, CAN_MESSAGE_PAYLOAD_SIZE ); - lastCANPacketSentChannel = mBox; - lastCANPacketSentTimeStamp = getMSTimerCount(); - if ( 0 != canTransmit( canREG1, mBox, data ) ) - { - result = CAN_MESSAGE_PAYLOAD_SIZE; - } - else - { - signalCANXmitsCompleted(); - // TODO - shouldn't get here, but let's see if we do - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, (U32)mBox ) - } - } - else - { // TODO - shouldn't get here - just testing - set first data to new s/w fault enum later - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, (U32)buffer, (U32)dataSize ) - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The transmitNextUARTPacket function sets up and initiates a DMA transmit \n - * of the next packet pending transmit (if any) via UART. - * @details - * Inputs : Output UART Comm Buffer(s) - * Outputs : UART DMA transmit initiated. - * @return # of bytes transmitted - *************************************************************************/ -#ifdef DEBUG_ENABLED -static U32 transmitNextUARTPacket( void ) -{ - U32 result = 0; - U32 dataPend = numberOfBytesInCommBuffer( COMM_BUFFER_OUT_UART_PC ); - - if ( dataPend > 0 ) - { - result = getFromCommBuffer( COMM_BUFFER_OUT_UART_PC, pcXmitPacket, dataPend ); - - // if there's data to transmit, transmit it - if ( result > 0 ) - { - signalSCI1XmitsInitiated(); - pcDMAXmitControlRecord.FRCNT = result; // set DMA transfer size - dmaSetCtrlPacket( DMA_CH3, pcDMAXmitControlRecord ); - dmaSetChEnable( DMA_CH3, DMA_HW ); - setSCI1DMATransmitInterrupt(); - } - } - - return result; -} -#endif - - -/************************************************************************* -********************** RECEIVE SUPPORT FUNCTIONS ************************* -*************************************************************************/ - - -/*********************************************************************//** - * @brief - * The processIncomingData function parses out messages from the Input \n - * Comm Buffers and adds them to the Received Message Queue. - * @details - * Inputs : Input Comm Buffers - * Outputs : Parsed message(s) added to Received Message Queue - * @return none - *************************************************************************/ -static void processIncomingData( void ) -{ - U08 data[ 512 ]; // message work space - U32 i; - BOOL badCRCDetected = FALSE; - - // queue any received messages - for ( i = 0; i < NUM_OF_MSG_IN_BUFFERS; i++ ) - { - BOOL messagesInBuffer = TRUE; // assume true at first to get into while loop - - while ( TRUE == messagesInBuffer ) - { - U32 numOfBytesInBuffer; - - // assume false so we don't get stuck in loop - only set to true if we find another complete message in buffer - messagesInBuffer = FALSE; - - // since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer - consumeBufferPaddingBeforeSync( MSG_IN_BUFFERS[ i ] ); - // do we have enough bytes in buffer for smallest message? - numOfBytesInBuffer = numberOfBytesInCommBuffer( MSG_IN_BUFFERS[ i ] ); - if ( numOfBytesInBuffer >= MESSAGE_OVERHEAD_SIZE ) - { // peek at minimum of all bytes available or max message size (+1 for sync byte) - U32 bytesPeeked = peekFromCommBuffer( MSG_IN_BUFFERS[ i ], data, MIN( numOfBytesInBuffer, sizeof( MESSAGE_WRAPPER_T ) + 1 ) ); - S32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); - - dgIsOnlyCANNode = FALSE; // if we're getting a message, we can't be alone - canXmitRetryCtr = 0; - if ( msgSize > 0 ) // valid, complete message found? - { - MESSAGE_WRAPPER_T rcvMsg; - U08 *dataPtr = data+1; // skip over sync byte - - // consume message (+sync byte) - msgSize = getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, msgSize + 1 ); - // convert received message data to a message and add to message queue - messagesInBuffer = TRUE; // keep processing this buffer - // blank the new message record - blankMessageInWrapper( &rcvMsg ); - // copy message header portion of message data to the new message - memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); - dataPtr += sizeof(MESSAGE_HEADER_T); - // copy message payload portion of message data to the new message - memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); - dataPtr += rcvMsg.msg.hdr.payloadLen; - // copy CRC portion of message data to the new message - rcvMsg.crc = *dataPtr; - // add new message to queue for later processing - addToMsgQueue( MSG_Q_IN, &rcvMsg ); - // if message from HD broadcast channel, update HD comm status - if ( COMM_BUFFER_IN_CAN_HD_BROADCAST == MSG_IN_BUFFERS[ i ] ) - { - hdIsCommunicating = TRUE; - timeOfLastHDCheckIn = getMSTimerCount(); - } - } - else if ( -1 == msgSize ) // candidate message with bad CRC found? - { - badCRCDetected = TRUE; - getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, 1 ); // consume sync byte so we can re-sync - messagesInBuffer = TRUE; // keep processing this buffer - } // looks like there is a complete message in the comm buffer - } // enough data left in comm buffer to possibly be a complete message - } // while loop to get all complete messages for each comm buffer - } // for loop to check all comm buffers for messages - - // if any bad CRCs detected, see if too many - if ( TRUE == badCRCDetected ) - { - checkTooManyBadMsgCRCs(); - } -} - -/*********************************************************************//** - * @brief - * The consumeBufferPaddingBeforeSync function removes any bytes in a given \n - * buffer that lie before a sync byte. - * @details - * Inputs : none - * Outputs : Any padding at front of comm buffer is consumed. - * @param msg : buffer : the comm buffer to process - * @return none - *************************************************************************/ -static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ) -{ - U08 data; - U32 numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); - - // consume bytes out of buffer 1 at a time until we find the sync byte or it's empty - while ( numOfBytesInBuffer > 0 ) - { - peekFromCommBuffer( buffer, &data, 1 ); - if ( MESSAGE_SYNC_BYTE == data ) - { - break; // we found a sync - we're done - } - else // not a sync byte, so consume it - { - getFromCommBuffer( buffer, &data, 1 ); - numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); - } - } -} - -/*********************************************************************//** - * @brief - * The parseMessageFromBuffer function looks for a complete message in a \n - * given buffer. If a message is found, its size is returned. - * @details - * Inputs : none - * Outputs : If a complete message can be found in buffer contents, it is parsed out. - * @param data : pointer to byte array to search for a message - * @param len : # of bytes in the data to search - * @return size of message if found, zero if no complete message found, \n - * -1 if message found but CRC fails. - *************************************************************************/ -static S32 parseMessageFromBuffer( U08 *data, U32 len ) -{ - U32 i; - U32 payloadSize; - U32 msgSize; - S32 result = 0; - - for ( i = 0; i < len; i++ ) - { - // find sync byte - if ( MESSAGE_SYNC_BYTE == data[ i ] ) - { - U32 pos = i + 1; // skip past sync byte implemented - U32 remSize = len - pos; - - // if a minimum sized msg would fit in remaining, continue - if ( remSize >= MESSAGE_OVERHEAD_SIZE ) - { - payloadSize = data[ pos + sizeof(MESSAGE_HEADER_T) - sizeof(U08) ]; - msgSize = MESSAGE_OVERHEAD_SIZE + payloadSize; - // we now know the size of the message - we can now know if full message is contained in buffer - if ( msgSize <= remSize ) - { // check CRC to make sure it's a valid message - if ( data[i+msgSize] == crc8( &data[pos], msgSize - 1 ) ) - { - result = msgSize; // we found a complete, valid message of this size - } - else // CRC failed - { - result = -1; // we found a complete, invalid message - } - } - } - break; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The processReceivedMessages function processes any messages in the \n - * received message queues. - * @details - * Inputs : Received Message Queues - * Outputs : Message(s) processed. - * @return none - *************************************************************************/ -static void processReceivedMessages( void ) -{ - BOOL isThereMsgRcvd = TRUE; // assume TRUE at first to get into while loop - MESSAGE_WRAPPER_T message; - - while ( TRUE == isThereMsgRcvd ) - { - // see if any messages received - isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN, &message ); - if ( TRUE == isThereMsgRcvd ) - { // CRC should be good because we checked it during parsing before adding to queue - but check it again for good measure - if ( message.crc == crc8( (U08*)(&message), sizeof(MESSAGE_HEADER_T) + message.msg.hdr.payloadLen ) ) - { - // if ACK, mark pending message ACK'd - if ( MSG_ID_ACK == message.msg.hdr.msgID ) - { - matchACKtoPendingACKList( message.msg.hdr.seqNo ); - } - else - { - // if received message requires ACK, queue one up - if ( message.msg.hdr.seqNo < 0 ) - { - sendACKMsg( &message.msg ); - } - // otherwise, process the received message - processReceivedMessage( &message.msg ); - } - } - else // CRC failed - { - checkTooManyBadMsgCRCs(); - } - } - } -} - -/*********************************************************************//** - * @brief - * The checkForCommTimeouts function checks for sub-system communication \n - * timeout errors. - * @details - * Inputs : timeOfLastDGCheckIn, timeOfLastUICheckIn - * Outputs : possibly a comm t/o alarm - * @return none - *************************************************************************/ -static void checkForCommTimeouts( void ) -{ - if ( TRUE == didTimeout( timeOfLastHDCheckIn, HD_COMM_TIMEOUT_IN_MS ) ) - { - hdIsCommunicating = FALSE; -#ifndef DEBUG_ENABLED - activateAlarmNoData( ALARM_ID_HD_COMM_TIMEOUT ); // TODO - add this alarm if we're in middle of a treatment? or if in a mode that comm loss would impact badly? -#endif - } -} - -/*********************************************************************//** - * @brief - * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs \n - * within a set period of time. Assumed function is being called when a new \n - * bad CRC is detected so a new bad CRC will be added to the list. - * @details - * Inputs : badCRCTimeStamps[], badCRCListIdx, badCRCListCount - * Outputs : possibly a "too many bad CRCs" alarm - * @return none - *************************************************************************/ -static void checkTooManyBadMsgCRCs( void ) + return result; +} + +/************************************************************************* + * @brief matchACKtoPendingACKList + * The matchACKtoPendingACKList function searches the pending ACK list to \n + * see if the sequence # from a received ACK msg matches any. If found, \n + * the list entry is removed. + * @details + * Inputs : pendingAckList[] + * Outputs : pendingAckList[] + * @param seqNo : sequence # to match to an entry in the list + * @return TRUE if a match was found, FALSE if not + *************************************************************************/ +static BOOL matchACKtoPendingACKList( S16 seqNo ) { - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC ) ) + BOOL result = FALSE; + U32 i; + + // find match + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_COMM_TOO_MANY_BAD_CRCS, 2 ); // 2 for DG - } -#ifdef DEBUG_ENABLED + if ( ( TRUE == pendingAckList[ i ].used ) && ( pendingAckList[ i ].seqNo == seqNo ) ) + { // remove message pending ACK from list + pendingAckList[ i ].used = FALSE; + result = TRUE; + break; + } + } + + return result; +} + +/************************************************************************* + * @brief checkPendingACKList + * The checkPendingACKList function searches the pending ACK list to \n + * see if any have expired. Any such messages will be queued for retransmission \n + * and if max retries reached a fault is triggered. + * @details + * Inputs : pendingAckList[] + * Outputs : pendingAckList[] + * @param none + * @return none + *************************************************************************/ +static void checkPendingACKList( void ) +{ + U32 i; + + // find expired messages pending ACK + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) { - char debugStr[100]; - sprintf( debugStr, "SystemComm-DG-Bad Msg CRC.\n" ); - sendDebugDataToUI( (U08*)debugStr ); + if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, MSG_NOT_ACKED_TIMEOUT_MS ) ) ) + { + if ( pendingAckList[ i ].retries > 0 ) + { // re-queue message for transmit + pendingAckList[ i ].retries--; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + addToCommBuffer( pendingAckList[ i ].channel, pendingAckList[ i ].msg, pendingAckList[ i ].msgSize ); + } + else + { + U16 msgID; + + memcpy( &msgID, &pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); + } + } } -#endif -} - -/*********************************************************************//** - * @brief - * The addMsgToPendingACKList function adds a given message to the pending \n - * ACK list. Messages in this list will require receipt of an ACK message \n - * for this particular message within a limited time. - * @details - * Inputs : pendingAckList[] - * Outputs : pendingAckList[] - * @param msg : pointer to msg within the message data - * @param msgData : pointer to message data to add to pending ACK list - * @param len : # of bytes of message data - * @return TRUE if message added successfully, FALSE if not - *************************************************************************/ -BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ) -{ - BOOL result = FALSE; - U32 i; - - // find first open slot in pending ACK list and add given msg data to it - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - _disable_IRQ(); // slot selection needs interrupt protection - if ( FALSE == pendingAckList[ i ].used ) - { - S16 seqNo = msg->hdr.seqNo * -1; // remove ACK bit from seq # - - pendingAckList[ i ].used = TRUE; - _enable_IRQ(); - pendingAckList[ i ].seqNo = seqNo; - pendingAckList[ i ].channel = channel; - pendingAckList[ i ].timeStamp = getMSTimerCount(); - pendingAckList[ i ].retries = MSG_NOT_ACKED_MAX_RETRIES; - pendingAckList[ i ].msgSize = len; - memcpy( pendingAckList[ i ].msg, msgData, len ); - result = TRUE; - break; - } - else - { - _enable_IRQ(); - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The matchACKtoPendingACKList function searches the pending ACK list to \n - * see if the sequence # from a received ACK msg matches any. If found, \n - * the list entry is removed. - * @details - * Inputs : pendingAckList[] - * Outputs : pendingAckList[] - * @param seqNo : sequence # to match to an entry in the list - * @return TRUE if a match was found, FALSE if not - *************************************************************************/ -static BOOL matchACKtoPendingACKList( S16 seqNo ) -{ - BOOL result = FALSE; - U32 i; - - // find match - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - if ( ( TRUE == pendingAckList[ i ].used ) && ( pendingAckList[ i ].seqNo == seqNo ) ) - { // remove message pending ACK from list - pendingAckList[ i ].used = FALSE; - result = TRUE; - break; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The checkPendingACKList function searches the pending ACK list to \n - * see if any have expired. Any such messages will be queued for retransmission \n - * and if max retries reached a fault is triggered. - * @details - * Inputs : pendingAckList[] - * Outputs : pendingAckList[] - * @return none - *************************************************************************/ -static void checkPendingACKList( void ) -{ - U32 i; - - // find expired messages pending ACK - for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) - { - if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, MSG_NOT_ACKED_TIMEOUT_MS ) ) ) - { - if ( pendingAckList[ i ].retries > 0 ) - { // re-queue message for transmit - pendingAckList[ i ].retries--; - pendingAckList[ i ].timeStamp = getMSTimerCount(); - addToCommBuffer( pendingAckList[ i ].channel, pendingAckList[ i ].msg, pendingAckList[ i ].msgSize ); - } - else - { - U16 msgID; - - memcpy( &msgID, &pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); - } - } - } -} - -/*********************************************************************//** - * @brief - * The processReceivedMessage function processes a given message. - * @details - * Inputs : none - * Outputs : message processed - * @param message : pointer to message to process - * @return none - *************************************************************************/ -static void processReceivedMessage( MESSAGE_T *message ) -{ - U16 msgID = message->hdr.msgID; - - // handle any messages from other sub-systems - switch ( msgID ) - { - case MSG_ID_POWER_OFF_WARNING: - handlePowerOffWarning( message ); - break; - - case MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS: - handleSetDialysateTemperatureCmd( message ); - break; - - case MSG_ID_REQUEST_FW_VERSIONS: - handleFWVersionCmd( message ); - break; - - case MSG_ID_DG_SWITCH_RESERVOIR_CMD: - handleSwitchReservoirCmd( message ); - break; - - case MSG_ID_DG_FILL_CMD: - handleFillCmd( message ); - break; - - case MSG_ID_DG_DRAIN_CMD: - handleDrainCmd( message ); - break; - - case MSG_ID_STARTING_STOPPING_TREATMENT_CMD: - handleStartStopTreatmentMsg( message ); - break; - - case MSG_ID_DG_SAMPLE_WATER_CMD: - handleSampleWaterCmd( message ); - break; - - case MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD: - handleStartStopTrimmerHeaterCmd( message ); - break; - - case MSG_ID_DG_START_STOP_HEAT_DISINFECT: - handleStartStopDGHeatDisinfect( message ); - break; - - case MSG_ID_DG_TESTER_LOGIN_REQUEST: - handleTesterLogInRequest( message ); - break; - - default: - // unrecognized message ID received - ok, ignore - may be a test message handled below - break; - } - - // handle any test messages if tester has logged in successfully - if ( ( msgID > MSG_ID_FIRST_DG_TESTER_MESSAGE ) && ( msgID <= END_OF_MSG_IDS ) && ( TRUE == isTestingActivated() ) ) - { - switch ( msgID ) - { - case MSG_ID_DG_ALARM_STATE_OVERRIDE: - handleTestAlarmStateOverrideRequest( message ); - break; - - case MSG_ID_DG_WATCHDOG_TASK_CHECKIN_OVERRIDE: - handleTestWatchdogCheckInStateOverrideRequest( message ); - break; - - case MSG_ID_DG_SET_RTC_DATE_TIME: - handleSetRTCTimestamp( message ); - break; - - case MSG_ID_START_STOP_PRIMARY_HEATER: - handleStartStopPrimaryHeater ( message ); - break; - - case MSG_ID_LOAD_CELL_OVERRIDE: - handleTestLoadCellOverrideRequest( message ); - break; - - case MSG_ID_LOAD_CELLL_SEND_INTERVAL_OVERRIDE: - handleTestLoadCellDataBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_PRESSURE_OVERRIDE: - handleTestPressureSensorOverrideRequest( message ); - break; - - case MSG_ID_PRESSURE_SEND_INTERVAL_OVERRIDE: - handleTestPressureDataBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_RO_PUMP_SET_PT_OVERRIDE: - handleTestROPumpSetPointOverrideRequest( message ); - break; - - case MSG_ID_RO_MEASURED_FLOW_OVERRIDE: - handleTestROMeasuredFlowOverrideRequest( message ); - break; - - case MSG_ID_RO_PUMP_SEND_INTERVAL_OVERRIDE: - handleTestROPumpDataBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_DRAIN_PUMP_SET_PT_OVERRIDE: - handleTestDrainPumpSetPointOverrideRequest( message ); - break; - - case MSG_ID_DRAIN_PUMP_SEND_INTERVAL_OVERRIDE: - handleTestDrainPumpDataBroadcastIntervalOverrideRequest( message ); - break; - - case MSG_ID_VALVE_STATE_OVERRIDE: - handleTestValveStateOverrideRequest( message ); - break; - - case MSG_ID_VALVES_STATES_PUBLISH_INTERVAL_OVERRIDE: - handleTestValvesStatesPublishIntervalOverrideRequest( message ); - break; - - case MSG_ID_DG_SAFETY_SHUTDOWN_OVERRIDE: - handleTestDGSafetyShutdownOverrideRequest( message ); - - case MSG_ID_TEMPERATURE_SENSORS_VALUE_OVERRIDE: - handleTestTemperatureSensorsOverrideRequest ( message ); - break; - - case MSG_ID_TEMPERATURE_SENSORS_PUBLISH_INTERVAL_OVERRIDE: - handleTestTemperatureSensorsDataPublishOverrideRequest ( message ); - break; - - case MSG_ID_HEATERS_PUBLISH_INTERVAL_ORVERRIDE: - handleTestHeatersDataPublishOverrideRequest ( message ); - break; - - default: - // TODO - unrecognized message ID received - ignore - break; - } - } -} +} -/**@}*/ +/************************************************************************* + * @brief processReceivedMessage + * The processReceivedMessage function processes a given message. + * @details + * Inputs : none + * Outputs : message processed + * @param message : pointer to message to process + * @return none + *************************************************************************/ +static void processReceivedMessage( MESSAGE_T *message ) +{ + U16 msgID = message->hdr.msgID; + + // handle any messages from other sub-systems + switch ( msgID ) + { + case MSG_ID_POWER_OFF_WARNING: + handlePowerOffWarning( message ); + break; + + case MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS: + handleSetDialysateTemperatureCmd( message ); + break; + + case MSG_ID_REQUEST_FW_VERSIONS: + handleFWVersionCmd( message ); + break; + + case MSG_ID_DG_SWITCH_RESERVOIR_CMD: + handleSwitchReservoirCmd( message ); + break; + + case MSG_ID_DG_FILL_CMD: + handleFillCmd( message ); + break; + + case MSG_ID_DG_DRAIN_CMD: + handleDrainCmd( message ); + break; + + case MSG_ID_STARTING_STOPPING_TREATMENT_CMD: + handleStartStopTreatmentMsg( message ); + break; + + case MSG_ID_DG_SAMPLE_WATER_CMD: + handleSampleWaterCmd( message ); + break; + + case MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD: + handleStartStopTrimmerHeaterCmd( message ); + break; + + case MSG_ID_DG_START_STOP_HEAT_DISINFECT: + handleStartStopDGHeatDisinfect( message ); + break; + + case MSG_ID_DG_TESTER_LOGIN_REQUEST: + handleTesterLogInRequest( message ); + break; + + default: + // unrecognized message ID received - ok, ignore - may be a test message handled below + break; + } + + // handle any test messages if tester has logged in successfully + if ( ( msgID > MSG_ID_FIRST_DG_TESTER_MESSAGE ) && ( msgID <= END_OF_MSG_IDS ) && ( TRUE == isTestingActivated() ) ) + { + switch ( msgID ) + { + case MSG_ID_DG_ALARM_STATE_OVERRIDE: + handleTestAlarmStateOverrideRequest( message ); + break; + + case MSG_ID_DG_WATCHDOG_TASK_CHECKIN_OVERRIDE: + handleTestWatchdogCheckInStateOverrideRequest( message ); + break; + + case MSG_ID_DG_SET_RTC_DATE_TIME: + handleSetRTCTimestamp( message ); + break; + + case MSG_ID_START_STOP_PRIMARY_HEATER: + handleStartStopPrimaryHeater ( message ); + break; + + case MSG_ID_LOAD_CELL_OVERRIDE: + handleTestLoadCellOverrideRequest( message ); + break; + + case MSG_ID_LOAD_CELLL_SEND_INTERVAL_OVERRIDE: + handleTestLoadCellDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_PRESSURE_OVERRIDE: + handleTestPressureSensorOverrideRequest( message ); + break; + + case MSG_ID_PRESSURE_SEND_INTERVAL_OVERRIDE: + handleTestPressureDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_RO_PUMP_SET_PT_OVERRIDE: + handleTestROPumpSetPointOverrideRequest( message ); + break; + + case MSG_ID_RO_MEASURED_FLOW_OVERRIDE: + handleTestROMeasuredFlowOverrideRequest( message ); + break; + + case MSG_ID_RO_PUMP_SEND_INTERVAL_OVERRIDE: + handleTestROPumpDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_DRAIN_PUMP_SET_PT_OVERRIDE: + handleTestDrainPumpSetPointOverrideRequest( message ); + break; + + case MSG_ID_DRAIN_PUMP_SEND_INTERVAL_OVERRIDE: + handleTestDrainPumpDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_VALVE_STATE_OVERRIDE: + handleTestValveStateOverrideRequest( message ); + break; + + case MSG_ID_VALVES_STATES_PUBLISH_INTERVAL_OVERRIDE: + handleTestValvesStatesPublishIntervalOverrideRequest( message ); + break; + + case MSG_ID_DG_SAFETY_SHUTDOWN_OVERRIDE: + handleTestDGSafetyShutdownOverrideRequest( message ); + + case MSG_ID_TEMPERATURE_SENSORS_VALUE_OVERRIDE: + handleTestTemperatureSensorsOverrideRequest ( message ); + break; + + case MSG_ID_TEMPERATURE_SENSORS_PUBLISH_INTERVAL_OVERRIDE: + handleTestTemperatureSensorsDataPublishOverrideRequest ( message ); + break; + + case MSG_ID_HEATERS_PUBLISH_INTERVAL_ORVERRIDE: + handleTestHeatersDataPublishOverrideRequest ( message ); + break; + + default: + // TODO - unrecognized message ID received - ignore + break; + } + } +} Index: firmware/App/Services/SystemComm.h =================================================================== diff -u -rdd70052b03eeb284223a4aade8567a4acec63efb -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Services/SystemComm.h (.../SystemComm.h) (revision dd70052b03eeb284223a4aade8567a4acec63efb) +++ firmware/App/Services/SystemComm.h (.../SystemComm.h) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -14,55 +14,47 @@ * @date (original) 05-Nov-2019 * ***************************************************************************/ - -#ifndef __SYSTEM_COMM_H__ -#define __SYSTEM_COMM_H__ - -#include "DGCommon.h" -#include "CommBuffers.h" -#include "MsgQueues.h" - -/** - * @defgroup SystemComm SystemComm - * @brief System communication module. Manages incoming and outgoing CAN frames. - * - * @addtogroup SystemComm - * @{ - */ -// ********** public definitions ********** - -#define MESSAGE_SYNC_BYTE 0xA5 ///< Denali message syncronization byte. - -#define CAN_MESSAGE_PAYLOAD_SIZE 8 ///< CAN frame payload size (in bytes). -#ifdef DEBUG_ENABLED - #define PC_MESSAGE_PACKET_SIZE 8 -#endif - -#define MSG_ID_ACK 0xFFFF ///< Denali message ID for acknowledging received messages (when required). -#define MSG_ACK_BIT 0x8000 ///< ACK bit in sequence number that indicates an ACK is required. -#define MAX_MSG_SEQ_NO 0x7FFF ///< Maximum sequence number for Denali message (then wraps to 1). -#define MIN_MSG_SEQ_NO 0x0001 ///< Minimum sequence number for Denali message. -#define MAX_ACK_MSG_SIZE ( sizeof( MESSAGE_WRAPPER_T ) + 1 + CAN_MESSAGE_PAYLOAD_SIZE ) ///< Maximum size (in bytes) of Denali message including full (wrapped) message + sync + any CAN padding) +#ifndef __SYSTEM_COMM_H__ +#define __SYSTEM_COMM_H__ -typedef COMM_BUFFER_T CAN_MESSAGE_BOX_T; ///< the CAN comm buffers align with the active CAN message boxes - -// ********** public function prototypes ********** - -void initSystemComm( void ); -void execSystemCommRx( void ); -void execSystemCommTx( void ); -void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ); -#ifdef DEBUG_ENABLED - void handleUARTMsgRecvPacketInterrupt( void ); - void handleUARTMsgXmitPacketInterrupt( void ); -#endif +#include "DGCommon.h" +#include "CommBuffers.h" +#include "MsgQueues.h" + +// ********** public definitions ********** + +#define MESSAGE_SYNC_BYTE 0xA5 + +#define CAN_MESSAGE_PAYLOAD_SIZE 8 +#ifdef DEBUG_ENABLED + #define PC_MESSAGE_PACKET_SIZE 8 +#endif + +#define MSG_ID_ACK 0xFFFF +#define MSG_ACK_BIT 0x8000 +#define MAX_MSG_SEQ_NO 0x7FFF +#define MIN_MSG_SEQ_NO 0x0001 +#define MAX_ACK_MSG_SIZE ( sizeof( MESSAGE_WRAPPER_T ) + 1 + CAN_MESSAGE_PAYLOAD_SIZE ) // must hold full (wrapped) message + sync + any CAN padding + +typedef COMM_BUFFER_T CAN_MESSAGE_BOX_T; // the first 12 comm buffers align with the 12 active CAN message boxes + +// ********** public function prototypes ********** + +void initSystemComm( void ); +void execSystemCommRx( void ); +void execSystemCommTx( void ); +void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ); +#ifdef DEBUG_ENABLED + void handleUARTMsgRecvPacketInterrupt( void ); + void handleUARTMsgXmitPacketInterrupt( void ); +#endif +BOOL isHDCommunicating( void ); +BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ); + BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ); BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ); -BOOL isHDCommunicating( void ); -BOOL isDGOnlyCANNode( void ); -BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ); -/**@}*/ - -#endif +BOOL isDGOnlyCANNode( void ); + +#endif Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r53af4ddc318cc5299f15e3cc1ce506b166e6e156 -r359cf587f2f935ef9f40a16d17c4105efa653c1d --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 53af4ddc318cc5299f15e3cc1ce506b166e6e156) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 359cf587f2f935ef9f40a16d17c4105efa653c1d) @@ -1268,7 +1268,7 @@ *************************************************************************/ //DATA_OVERRIDE_HANDLER_FUNC_U32( U32, handleTestROPumpSetPointOverrideRequest, testSetTargetROPumpPressureOverride, testResetTargetROPumpPressureOverride ) //Todo remove -DATA_OVERRIDE_HANDLER_FUNC_U32( U32, handleTestROPumpSetPointOverrideRequest, testSetTargetROPumpFlowRateOverride, testResetTargetROPumpFlowRateOverride ) +DATA_OVERRIDE_HANDLER_FUNC_U32( F32, handleTestROPumpSetPointOverrideRequest, testSetTargetROPumpFlowRateOverride, testResetTargetROPumpFlowRateOverride ) /************************************************************************* * @brief