Index: firmware/.launches/HD.launch =================================================================== diff -u -r636c8e7083577ed918d06255423784ca47271a88 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/.launches/HD.launch (.../HD.launch) (revision 636c8e7083577ed918d06255423784ca47271a88) +++ firmware/.launches/HD.launch (.../HD.launch) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -1,5 +1,11 @@ + + + + + + @@ -36,4 +42,5 @@ + Index: firmware/App/Common.h =================================================================== diff -u -r620104f4a9e3148575703981a3063b9605b6e9b8 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/App/Common.h (.../Common.h) (revision 620104f4a9e3148575703981a3063b9605b6e9b8) +++ firmware/App/Common.h (.../Common.h) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -88,18 +88,18 @@ // **** Common Macros **** -#define CAP(v,u) ((v) > (u) ? (u) : (v)) -#define RANGE(v,l,u) ((v) > (u) ? (u) : ((v) < (l) ? (l) : (v))) -#define INC_WRAP(v,l,u) ((v) == (u) ? (l) : ((v)+1)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define CAP(v, u) ((v) > (u) ? (u) : (v)) +#define RANGE(v, l, u) ((v) > (u) ? (u) : ((v) < (l) ? (l) : (v))) +#define INC_WRAP(v, l, u) ((v) == (u) ? (l) : ((v) + 1)) +#define MAX(a, b) ((a) < (b) ? (b) : (a)) +#define MIN(a, b) ((a) > (b) ? (b) : (a)) #define GET_LSB_OF_WORD(w) ((U08)((w) & MASK_OFF_MSB)) #define GET_MSB_OF_WORD(w) ((U08)(((w) >> SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_MSB)) #define GET_LSW_OF_LONG(l) ((U16)((l) & MASK_OFF_MSW)) #define GET_MSW_OF_LONG(l) ((U16)(((l) >> SHIFT_16_BITS_FOR_WORD_SHIFT) & MASK_OFF_MSW)) -#define MAKE_WORD_OF_BYTES(h,l) ((((U16)(h) << SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_LSB) | ((U16)(l) & MASK_OFF_MSB)) -#define MAKE_LONG_OF_WORDS(h,l) ((((U32)(h) << SHIFT_16_BITS_FOR_WORD_SHIFT) & MASK_OFF_LSW) | ((U32)(l) & MASK_OFF_MSW)) -#define GET_TOGGLE(v,l,h) ((v) == (l) ? (h) : (l)) +#define MAKE_WORD_OF_BYTES(h, l) ((((U16)(h) << SHIFT_8_BITS_FOR_BYTE_SHIFT) & MASK_OFF_LSB) | ((U16)(l) & MASK_OFF_MSB)) +#define MAKE_LONG_OF_WORDS(h, l) ((((U32)(h) << SHIFT_16_BITS_FOR_WORD_SHIFT) & MASK_OFF_LSW) | ((U32)(l) & MASK_OFF_MSW)) +#define GET_TOGGLE(v, l, h) ((v) == (l) ? (h) : (l)) #define SET_ALARM_WITH_1_U32_DATA(a,d1) { \ ALARM_DATA_T dat1; \ Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r620104f4a9e3148575703981a3063b9605b6e9b8 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 620104f4a9e3148575703981a3063b9605b6e9b8) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -133,6 +133,9 @@ static void stopBloodPump( void ); static void releaseBloodPumpStop( void ); static void setBloodPumpDirection( MOTOR_DIR_T dir ); +static void publishBloodFlowData( void ); +static void checkBloodPumpDirection( void ); +static void checkBloodPumpMCCurrent( void ); static DATA_GET_PROTOTYPE( U32, getPublishBloodFlowDataInterval ); /************************************************************************* @@ -183,7 +186,6 @@ bloodPumpDirection = dir; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed bloodPumpPWMDutyCyclePct = BP_PWM_FROM_ML_PER_MIN((F32)flowRate); // ~ 8% per 100 mL/min with a 10% zero offset added in (e.g. 100 mL/min = 8+10 = 18%) - bloodPumpPWMDutyCyclePct = MIN(bloodPumpPWMDutyCyclePct,MAX_BLOOD_PUMP_PWM_DUTY_CYCLE); // limit pwm duty cycle to controller maximum // reset flow control stats bpFlowError = 0.0; bpFlowErrorSum = 0.0; @@ -241,8 +243,7 @@ { U16 bpRPM = getIntADCReading( INT_ADC_BLOOD_PUMP_SPEED ); U16 bpmA = getIntADCReading( INT_ADC_BLOOD_PUMP_MOTOR_CURRENT ); - F32 bpFlow = getFPGABloodFlow(); // TODO - change to avg. blood flow when available from FPGA - MOTOR_DIR_T bpMCDir; + F32 bpFlow = getFPGABloodFlow(); adcBloodPumpSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpRPM)) * BP_SPEED_ADC_TO_RPM_FACTOR; adcBloodPumpCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * BP_CURRENT_ADC_TO_MA_FACTOR; @@ -256,71 +257,12 @@ // don't start enforcing checks until out of init/POST mode if ( getCurrentOperationMode() != MODE_INIT ) { - if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) - { - // check set direction vs. direction from sign of motor controller speed - bpMCDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); - if ( bloodPumpDirectionSet != bpMCDir ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) - } - } - - // check motor controller current thresholds as appropriate - if ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) - { - F32 bpCurr = fabs( getMeasuredBloodPumpCurrent() ); - - if ( bpCurr > BP_MAX_CURR_WHEN_STOPPED_MA ) - { - bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpCurrent() ); - } - } - else - { - bpCurrErrorDurationCtr = 0; - } - } - else // pump s/b running - { - F32 bpCurr = fabs( getMeasuredBloodPumpCurrent() ); - - if ( ( bpCurr < BP_MIN_CURR_WHEN_RUNNING_MA ) || ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ) ) - { - bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; - if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) - { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpCurrent() ); - } - } - else - { - bpCurrErrorDurationCtr = 0; - } - } + checkBloodPumpDirection(); + checkBloodPumpMCCurrent(); } // publish blood flow data on interval - if ( ++bloodFlowDataPublicationTimerCounter > getPublishBloodFlowDataInterval() ) - { - S32 flowStPt = (S32)getTargetBloodFlowRate(); - F32 measFlow = getMeasuredBloodFlowRate(); - F32 measSpd = getMeasuredBloodPumpSpeed(); - F32 measCurr = getMeasuredBloodPumpCurrent(); -#ifdef DEBUG_ENABLED - // TODO - temporary debug code - remove later - S32 pwm = (S32)( 100.0 * bloodPumpPWMDutyCyclePctSet ); - char debugFlowStr[256]; - - sprintf( debugFlowStr, "Target Flow:%5d, Meas. Flow:%5d, Speed:%5d RPM, Current:%5d mA, PWM:%5d \n", flowStPt, (S32)measFlow, (S32)measSpd, (S32)measCurr, pwm ); - sendDebugData( (U08*)debugFlowStr, strlen(debugFlowStr) ); -#endif - broadcastBloodFlowData( flowStPt, measFlow, measSpd, measCurr ); - bloodFlowDataPublicationTimerCounter = 0; - } + publishBloodFlowData(); } /************************************************************************* @@ -498,7 +440,6 @@ bpFlowErrorSum += bpFlowError; iTerm = RANGE( bpFlowErrorSum, BP_MIN_ERROR_SUM, BP_MAX_ERROR_SUM ); iTerm *= BP_I_COEFFICIENT; - iTerm = RANGE( iTerm, BP_MIN_PWM_DC_DELTA, BP_MAX_PWM_DC_DELTA ); // compute new PWM duty cycle % for blood pump motor newPWM = bloodPumpPWMDutyCyclePctSet + pTerm + iTerm; newPWM = RANGE( newPWM, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, MAX_BLOOD_PUMP_PWM_DUTY_CYCLE ); @@ -633,6 +574,114 @@ DATA_GET( F32, getMeasuredBloodPumpCurrent, adcBloodPumpCurrentmA ) /************************************************************************* + * @brief publishBloodFlowData + * The publishBloodFlowData function publishes blood flow data at the set \n + * interval. + * @details + * Inputs : target flow rate, measured flow rate, measured MC speed, \n + * measured MC current + * Outputs : Blood flow data is published to CAN bus. + * @param none + * @return none + *************************************************************************/ +static void publishBloodFlowData( void ) +{ + // publish blood flow data on interval + if ( ++bloodFlowDataPublicationTimerCounter > getPublishBloodFlowDataInterval() ) + { + S32 flowStPt = (S32)getTargetBloodFlowRate(); + F32 measFlow = getMeasuredBloodFlowRate(); + F32 measSpd = getMeasuredBloodPumpSpeed(); + F32 measCurr = getMeasuredBloodPumpCurrent(); +#ifdef DEBUG_ENABLED + // TODO - temporary debug code - remove later + S32 pwm = (S32)( 100.0 * bloodPumpPWMDutyCyclePctSet ); + char debugFlowStr[256]; + + sprintf( debugFlowStr, "Target Flow:%5d, Meas. Flow:%5d, Speed:%5d RPM, Current:%5d mA, PWM:%5d \n", flowStPt, (S32)measFlow, (S32)measSpd, (S32)measCurr, pwm ); + sendDebugData( (U08*)debugFlowStr, strlen(debugFlowStr) ); +#endif + broadcastBloodFlowData( flowStPt, measFlow, measSpd, measCurr ); + bloodFlowDataPublicationTimerCounter = 0; + } +} + +/************************************************************************* + * @brief checkBloodPumpDirection + * The checkBloodPumpDirection function checks the set direction vs. \n + * the direction implied by the sign of the measured MC speed. + * @details + * Inputs : + * Outputs : + * @param none + * @return none + *************************************************************************/ +static void checkBloodPumpDirection( void ) +{ + MOTOR_DIR_T bpMCDir; + + if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) + { + // check set direction vs. direction from sign of motor controller speed + bpMCDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); + if ( bloodPumpDirectionSet != bpMCDir ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) + } + } +} + +/************************************************************************* + * @brief checkBloodPumpMCCurrent + * The checkBloodPumpMCCurrent function checks the measured MC current vs. \n + * the set state of the blood pump (stopped or running). + * @details + * Inputs : + * Outputs : + * @param none + * @return none + *************************************************************************/ +static void checkBloodPumpMCCurrent( void ) +{ + F32 bpCurr; + + // blood pump should be off + if ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) + { + bpCurr = fabs( getMeasuredBloodPumpCurrent() ); + if ( bpCurr > BP_MAX_CURR_WHEN_STOPPED_MA ) + { + bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; + if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpCurrent() ); + } + } + else + { + bpCurrErrorDurationCtr = 0; + } + } + // blood pump should be running + else + { + bpCurr = fabs( getMeasuredBloodPumpCurrent() ); + if ( ( bpCurr < BP_MIN_CURR_WHEN_RUNNING_MA ) || ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ) ) + { + bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; + if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpCurrent() ); + } + } + else + { + bpCurrErrorDurationCtr = 0; + } + } +} + +/************************************************************************* * @brief execBloodFlowTest * The execBloodFlowTest function executes the state machine for the \n * BloodFlow self test. Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r620104f4a9e3148575703981a3063b9605b6e9b8 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 620104f4a9e3148575703981a3063b9605b6e9b8) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -386,44 +386,47 @@ * according to the current state of alarms. * @details * Inputs : none - * Outputs : none + * Outputs : Alarm lamp patter set according to current alarms status. * @param none * @return none *************************************************************************/ static void setAlarmLampAndAudio( void ) { - switch ( alarmStatus.alarmsState ) + if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) { - case ALARM_PRIORITY_NONE: - requestAlarmLampPattern( LAMP_PATTERN_OK ); - // TODO - no audio - break; + switch ( alarmStatus.alarmsState ) + { + case ALARM_PRIORITY_NONE: + requestAlarmLampPattern( LAMP_PATTERN_OK ); + // TODO - no audio + break; - case ALARM_PRIORITY_LOW: - requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); - // TODO - low priority audio - break; + case ALARM_PRIORITY_LOW: + requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); + // TODO - low priority audio + break; - case ALARM_PRIORITY_MEDIUM: - requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); - // TODO - medium priority audio - break; + case ALARM_PRIORITY_MEDIUM: + requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); + // TODO - medium priority audio + break; - case ALARM_PRIORITY_HIGH: - if ( TRUE == alarmTable[alarmStatus.alarmTop].alarmIsFault ) - { - requestAlarmLampPattern( LAMP_PATTERN_FAULT ); - } - else - { - requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); - } - // TODO - high priority audio - break; + case ALARM_PRIORITY_HIGH: + if ( TRUE == alarmTable[alarmStatus.alarmTop].alarmIsFault ) + { + requestAlarmLampPattern( LAMP_PATTERN_FAULT ); + } + else + { + requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); + } + // TODO - high priority audio + break; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) - break; + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) + break; + } } } Index: firmware/App/Tasks/TaskBG.c =================================================================== diff -u -r8e53754325653805a454de6d82c0c8ca90e068a0 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 8e53754325653805a454de6d82c0c8ca90e068a0) +++ firmware/App/Tasks/TaskBG.c (.../TaskBG.c) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -15,6 +15,7 @@ **************************************************************************/ #include "Common.h" +#include "SafetyShutdown.h" #include "SystemComm.h" #include "Timers.h" #include "WatchdogMgmt.h" @@ -56,7 +57,8 @@ if ( TRUE == didTimeout( startUICommTimeout, MAX_TIME_FOR_UI_TO_COMMUNICATE_MS ) ) { activateAlarmNoData( ALARM_ID_UI_COMM_POST_FAILED ); - checkInFromUI(); // pretend we got something from UI to unlock task processing of HD + activateSafetyShutdown(); // TODO - for now, possibly remove later + //checkInFromUI(); // pretend we got something from UI to unlock task processing of HD } } } Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -r070554b23739bf16ea2bf9528ebabda1ce0ffeb3 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 070554b23739bf16ea2bf9528ebabda1ce0ffeb3) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -32,8 +32,6 @@ // ********** private data ********** -static BOOL uiHasCheckedIn = FALSE; - /************************************************************************* * @brief taskGeneral * The taskGeneral function handles the scheduled General Task interrupt.\n @@ -54,7 +52,7 @@ execSystemCommRx(); // prevent most processing until UI has started communicating - if ( TRUE == uiHasCheckedIn ) + if ( TRUE == uiCommunicated() ) { // control blood pump execBloodFlowController(); @@ -87,10 +85,6 @@ // manage data to be transmitted to other sub-systems execSystemCommTx(); } - else - { - uiHasCheckedIn = uiCommunicated(); - } // toggle GPIO to indicate general task has executed // gioToggleBit( gioPORTB, 1 ); Index: firmware/App/Tasks/TaskPriority.c =================================================================== diff -u -rd9cc76524777a12ba77b58ce95416dddfb032997 -r941afbaab7fc86f40fa49f9d110d481f65b44b68 --- firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision d9cc76524777a12ba77b58ce95416dddfb032997) +++ firmware/App/Tasks/TaskPriority.c (.../TaskPriority.c) (revision 941afbaab7fc86f40fa49f9d110d481f65b44b68) @@ -24,8 +24,6 @@ #include "WatchdogMgmt.h" #include "TaskPriority.h" -static BOOL uiHasCheckedIn = FALSE; - /************************************************************************* * @brief taskPriority * The taskPriority function handles the scheduled Priority Task interrupt. @@ -37,7 +35,7 @@ void taskPriority( void ) { // prevent most processing until UI has started communicating - if ( TRUE == uiHasCheckedIn ) + if ( TRUE == uiCommunicated() ) { // 1st pass for FPGA execFPGAIn(); @@ -55,10 +53,6 @@ execFPGAOut(); } - else - { - uiHasCheckedIn = uiCommunicated(); - } // check in with watchdog manager checkInWithWatchdogMgmt( TASK_PRIORITY );