Index: firmware/.settings/org.eclipse.core.resources.prefs =================================================================== diff -u -r73d8423edc56daed591bc0b3f7baee5540aea423 -r766e65a173747dd60a9faae1cac228cd5f8a55a6 --- firmware/.settings/org.eclipse.core.resources.prefs (.../org.eclipse.core.resources.prefs) (revision 73d8423edc56daed591bc0b3f7baee5540aea423) +++ firmware/.settings/org.eclipse.core.resources.prefs (.../org.eclipse.core.resources.prefs) (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -1,6 +1,8 @@ eclipse.preferences.version=1 encoding//Debug/App/Controllers/subdir_rules.mk=UTF-8 encoding//Debug/App/Controllers/subdir_vars.mk=UTF-8 +encoding//Debug/App/Drivers/subdir_rules.mk=UTF-8 +encoding//Debug/App/Drivers/subdir_vars.mk=UTF-8 encoding//Debug/App/Modes/subdir_rules.mk=UTF-8 encoding//Debug/App/Modes/subdir_vars.mk=UTF-8 encoding//Debug/App/Monitors/subdir_rules.mk=UTF-8 Index: firmware/App/Drivers/CpldIO.h =================================================================== diff -u --- firmware/App/Drivers/CpldIO.h (revision 0) +++ firmware/App/Drivers/CpldIO.h (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -0,0 +1,76 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file CpldIO.h +* +* @author (last) Sean +* @date (last) 07-Aug-2024 +* +* @author (original) Sean +* @date (original) 07-Aug-2024 +* +***************************************************************************/ + +#ifndef __CPLD_IO_H__ +#define __CPLD_IO_H__ + +#include "TDCommon.h" + +/** + * @defgroup CPLD_IO CPLD_IO + * @brief The CPLD IO module provides definitions and GPIO pin access macros + * to provide low-level GPIO interface to CPLD. + * + * @addtogroup CPLD_IO + * @{ + */ + +// ********** public definitions ********** + +// GIO port A pin assignments for pins connected to CPLD +#define OFF_BUTTON_GIO_PORT_PIN 0U ///< GPIO pin ID on port A for off button input signal. +#define STOP_BUTTON_GIO_PORT_PIN 1U ///< GPIO pin ID on port A for stop button input signal. +#define SAFETY_GIO_PORT_PIN 3U ///< GPIO pin ID on port A for safety shutdown output signal + +// GIO port B pin assignments for pins connected to CPLD +#define OFF_REQUEST_GIO_PORT_PIN 0U ///< GPIO pin ID on port B for power off request output signal. +#define WD_PET_GIO_PORT_PIN 1U ///< GPIO pin ID on port B for watchdog pet output signal. +#define WD_EXP_GIO_PORT_PIN 2U ///< GPIO pin ID on port B for watchdog expired input signal. + +// MIBSPI5 port pin assignments for pins connected to CPLD +#define GREEN_SPI5_PORT_MASK 0x00000200 ///< (CLK - re-purposed as output GPIO) for green alarm lamp signal. +#define BLUE_SPI5_PORT_MASK 0x00000400 ///< (SIMO[0] - re-purposed as output GPIO) for blue alarm lamp signal. +#define RED_SPI5_PORT_MASK 0x00000800 ///< (SOMI[0] - re-purposed as output GPIO) for red alarm lamp signal. +#define AC_PRESENT_SPI5_PORT_MASK 0x00000001 ///< (SOMI[0] - re-purposed as output GPIO) for red alarm lamp signal. + +// CPLD pin I/O macros +#define GET_OFF() (PIN_SIGNAL_STATE_T)(gioGetBit(gioPORTA, OFF_BUTTON_GIO_PORT_PIN)) ///< Macro to get off button signal state. +#define GET_STOP() (PIN_SIGNAL_STATE_T)(gioGetBit(gioPORTA, STOP_BUTTON_GIO_PORT_PIN)) ///< Macro to get stop button signal state. +#define GET_WD_EXP() (PIN_SIGNAL_STATE_T)(gioGetBit(gioPORTB, WD_EXP_GIO_PORT_PIN)) ///< Macro to get watchdog expired signal state. +#define GET_AC_PRESENT() (PIN_SIGNAL_STATE_T)(mibspiREG5->PC2 & AC_PRESENT_SPI5_PORT_MASK) ///< Macro to get A/C power present signal state. + +#define TGL_WD_PET() gioToggleBit( gioPORTB, WD_PET_GIO_PORT_PIN ) ///< Macro to toggle watchdog pet signal state. +#define TGL_OFF_REQ() gioToggleBit( gioPORTB, OFF_REQUEST_GIO_PORT_PIN) ///< Macro to toggle power off request signal state. +#define SET_WD_PET() gioSetBit( gioPORTB, WD_PET_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) ///< Macro to set watchdog pet signal state high. +#define SET_OFF_REQ() gioSetBit( gioPORTB, OFF_REQUEST_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) ///< Macro to set power off request signal state high. +#define SET_GREEN() {mibspiREG5->PC3 |= GREEN_SPI5_PORT_MASK;} ///< Macro to set green alarm lamp signal state high. +#define SET_BLUE() {mibspiREG5->PC3 |= BLUE_SPI5_PORT_MASK;} ///< Macro to set blue alarm lamp signal state high. +#define SET_RED() {mibspiREG5->PC3 |= RED_SPI5_PORT_MASK;} ///< Macro to set red alarm lamp signal state high. + +#define CLR_WD_PET() gioSetBit( gioPORTB, WD_PET_GIO_PORT_PIN, PIN_SIGNAL_LOW ) ///< Macro to set watchdog pet signal state low. +#define CLR_OFF_REQ() gioSetBit( gioPORTB, OFF_REQUEST_GIO_PORT_PIN, PIN_SIGNAL_LOW ) ///< Macro to set power off request signal state low. +#define CLR_GREEN() {mibspiREG5->PC3 &= ~GREEN_SPI5_PORT_MASK;} ///< Macro to set green alarm lamp signal state low. +#define CLR_BLUE() {mibspiREG5->PC3 &= ~BLUE_SPI5_PORT_MASK;} ///< Macro to set blue alarm lamp signal state low. +#define CLR_RED() {mibspiREG5->PC3 &= ~RED_SPI5_PORT_MASK;} ///< Macro to set red alarm lamp signal state low. + +// CPLD pin I/O macros +#define SET_SAFETY_SHUTDOWN() gioSetBit( gioPORTB, SAFETY_GIO_PORT_PIN, PIN_SIGNAL_HIGH ) +#define CLR_SAFETY_SHUTDOWN() gioSetBit( gioPORTB, SAFETY_GIO_PORT_PIN, PIN_SIGNAL_LOW ) + +/**@}*/ + +#endif Index: firmware/App/Drivers/InternalADC.c =================================================================== diff -u --- firmware/App/Drivers/InternalADC.c (revision 0) +++ firmware/App/Drivers/InternalADC.c (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -0,0 +1,232 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file InternalADC.c +* +* @author (last) Sean +* @date (last) 07-Aug-2024 +* +* @author (original) Sean +* @date (original) 07-Aug-2024 +* +***************************************************************************/ + +#include "adc.h" + +#include "InternalADC.h" + +/** + * @addtogroup InternalADC + * @{ + */ + +// ********** private definitions ********** + +#define MAX_ADC_CHANNELS 24 ///< ADC supports up to 24 channels. +#define SIZE_OF_ROLLING_AVG 8 ///< Samples in rolling average calculations. +#define ROLLING_AVG_SHIFT_DIVIDER 3 ///< Rolling average shift divider. + +/// Mapping from enumerated used ADC channel to processor channel ID. +const INT_ADC_CHANNEL_T ADC_CHANNEL_NUM_TO_CHANNEL_ID[ MAX_ADC_CHANNELS ] = +{ + INT_ADC_AVAILABLE_1, // 0 + INT_ADC_PS_THERMISTOR, // 1 + INT_ADC_PBA_ADC_REF, // 2 + INT_ADC_24V_ACTUATORS_REG, // 3 + INT_ADC_1_2V_PROCESSOR, // 4 + INT_ADC_5V_SENSORS, // 5 + INT_ADC_DUMMY, // 6 + INT_ADC_AVAILABLE_2, // 7 + INT_ADC_PRIMARY_ALARM_CURRENT_HG, // 8 + INT_ADC_NOT_USED, // 9 + INT_ADC_BOARD_THERMISTOR, // 10 + INT_ADC_1_25_FPGA_ADC_REF, // 11 + INT_ADC_3_3V, // 12 + INT_ADC_5V_LOGIC, // 13 + INT_ADC_PRIMARY_ALARM_CURRENT_LG, // 14 + INT_ADC_NOT_USED, // 15 + INT_ADC_BLOOD_PUMP_SPEED, // 16 + INT_ADC_BLOOD_PUMP_MOTOR_CURRENT, // 17 + INT_ADC_AVAILABLE_3, // 18 + INT_ADC_AVAILABLE_4, // 19 + INT_ADC_NOT_USED, // 20 + INT_ADC_NOT_USED, // 21 + INT_ADC_24V_ACTUATORS, // 22 + INT_ADC_NOT_USED_2 // 23 +}; + +const F32 ADC_CHANNEL_READ_TO_UNITS[ NUM_OF_INT_ADC_CHANNELS ] = +{ + 0.0, // - INT_ADC_NOT_USED + 1.601601, // RPM - INT_ADC_BLOOD_PUMP_SPEED + 0.003002, // A - INT_ADC_BLOOD_PUMP_MOTOR_CURRENT + 1.601601, // V - INT_ADC_AVAILABLE_1 + 0.003002, // V - INT_ADC_AVAILABLE_2 + 1.601601, // V - INT_ADC_AVAILABLE_3 + 0.003002, // V - INT_ADC_AVAILABLE_4 + 0.001221, // V - INT_ADC_PS_THERMISTOR + 0.001465, // V - INT_ADC_REFIN_1 + 0.009420, // V - INT_ADC_24V_ACTUATORS_REG + 0.000733, // V - INT_ADC_1_2V_PROCESSOR + 0.001465, // V - INT_ADC_5V_SENSORS + 0.014650, // mA - INT_ADC_PRIMARY_ALARM_CURRENT_HG + 0.001221, // V - INT_ADC_BOARD_THERMISTOR + 0.000733, // V - INT_ADC_1_25_FPGA_ADC_REF + 0.001465, // V - INT_ADC_3_3V + 0.001465, // V - INT_ADC_5V_LOGIC + 0.073240, // mA - INT_ADC_PRIMARY_ALARM_CURRENT_LG + 0.007106, // V - INT_ADC_24V_ACTUATORS + 0.0, // - INT_ADC_NOT_USED_2 + 0.000000, // V - INT_ADC_DUMMY +}; + +// ********** private data ********** + +static adcData_t adcRawReadings[ NUM_OF_INT_ADC_CHANNELS ]; ///< Buffer holds latest adc channel readings. +static U32 adcRawReadingsCount = 0; ///< Readings count for raw readings buffer. + +static U16 adcReadings[ NUM_OF_INT_ADC_CHANNELS ][ SIZE_OF_ROLLING_AVG ]; ///< Holds samples for each channel for a rolling average. +static U32 adcReadingsIdx[ NUM_OF_INT_ADC_CHANNELS ]; ///< Index for next reading in each rolling average array. +static U32 adcReadingsTotals[ NUM_OF_INT_ADC_CHANNELS ]; ///< Rolling total for each channel - used to calc average. +static U32 adcReadingsAvgs[ NUM_OF_INT_ADC_CHANNELS ]; ///< Rolling average for each channel. + +// ********** private function prototypes ********** + +/*********************************************************************//** + * @brief + * The initInternalADC function initializes the InternalADC module. + * @details Inputs: none + * @details Outputs: InternalADC module is initialized. + * @return none + *************************************************************************/ +void initInternalADC( void ) +{ + U32 c,r; + + // Zero all adc values and stats + adcRawReadingsCount = 0; + for ( c = 0; c < NUM_OF_INT_ADC_CHANNELS; c++ ) + { + adcRawReadings[ c ].id = 0; + adcRawReadings[ c ].value = 0; + adcReadingsIdx[ c ] = 0; + adcReadingsTotals[ c ] = 0; + adcReadingsAvgs[ c ] = 0; + for ( r = 0; r < SIZE_OF_ROLLING_AVG; r++ ) + { + adcReadings[ c ][ r ] = 0; + } + } + + // Enable interrupt when all channels converted + adcEnableNotification( adcREG1, adcGROUP1 ); +} + +/*********************************************************************//** + * @brief + * The adcNotification function handles an ADC conversion complete interrupt. + * All channel readings in the FIFO are retrieved. + * @details Inputs: ADC FIFO + * @details Outputs: adcRawReadingsCount, adcRawReadings[] + * @param adc pointer to the ADC1 controller + * @param group ADC channel group ID + * @return none + *************************************************************************/ +void adcNotification( adcBASE_t *adc, uint32 group ) +{ + if ( adcGROUP1 == group ) + { + adcRawReadingsCount = adcGetData( adcREG1, adcGROUP1, adcRawReadings ); + } +} + +/*********************************************************************//** + * @brief + * The execInternalADC function processes the last set of raw ADC channel + * readings and kicks off the next conversion of ADC channels. + * @details Inputs: adcRawReadingsCount, adcRawReadings[] + * @details Outputs: adcReadings[][], adcReadingsIdx[], adcReadingsTotals[], adcReadingsAvgs[] + * @return none + *************************************************************************/ +void execInternalADC( void ) +{ + U32 i; + + if ( adcRawReadingsCount < NUM_OF_INT_ADC_CHANNELS ) + { + // Process readings from last conversion + for ( i = 0; i < adcRawReadingsCount; i++ ) + { + U32 ch = ADC_CHANNEL_NUM_TO_CHANNEL_ID[ adcRawReadings[ i ].id ]; + + adcReadingsTotals[ ch ] -= adcReadings[ ch ][ adcReadingsIdx[ ch ] ]; + adcReadings[ ch ][ adcReadingsIdx[ ch ] ] = adcRawReadings[i].value; + adcReadingsTotals[ ch ] += adcRawReadings[ i ].value; + adcReadingsAvgs[ ch ] = adcReadingsTotals[ ch ] >> ROLLING_AVG_SHIFT_DIVIDER; + adcReadingsIdx[ ch ] = INC_WRAP( adcReadingsIdx[ ch ], 0, SIZE_OF_ROLLING_AVG - 1 ); + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_DATA_OVERRUN, adcRawReadingsCount ) + } + + // Start an adc channel group conversion + adcStartConversion( adcREG1, adcGROUP1 ); +} + +/*********************************************************************//** + * @brief + * The getIntADCReading function gets the latest average reading for a given + * channel. + * @details Inputs: adcReadingsAvgs[] + * @details Outputs: none + * @param channel adc channel to retrieve a reading for + * @return average reading for the given channel + *************************************************************************/ +U16 getIntADCReading( INT_ADC_CHANNEL_T channel ) +{ + U16 result = 0; + + if ( channel < NUM_OF_INT_ADC_CHANNELS ) + { + result = adcReadingsAvgs[ channel ]; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED1, channel ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getIntADCVoltageConverted function gets the latest average voltage + * (converted per transfer function) for a given channel. + * @details Inputs: adcReadingsAvgs[], ADC_CHANNEL_READ_TO_UNITS[] + * @details Outputs: none + * @param channel adc channel to retrieve a converted voltage for + * @return average converted voltage for the given channel + *************************************************************************/ +F32 getIntADCVoltageConverted( INT_ADC_CHANNEL_T channel ) +{ + F32 result = 0.0; + + if ( channel < NUM_OF_INT_ADC_CHANNELS ) + { + result = (F32)adcReadingsAvgs[ channel ] * ADC_CHANNEL_READ_TO_UNITS[ channel ]; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED2, channel ) + } + + return result; +} + +/**@}*/ Index: firmware/App/Drivers/InternalADC.h =================================================================== diff -u --- firmware/App/Drivers/InternalADC.h (revision 0) +++ firmware/App/Drivers/InternalADC.h (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -0,0 +1,75 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file InternalADC.h +* +* @author (last) Sean +* @date (last) 07-Aug-2024 +* +* @author (original) Sean +* @date (original) 07-Aug-2024 +* +***************************************************************************/ + +#ifndef __INT_ADC_H__ +#define __INT_ADC_H__ + +#include "TDCommon.h" + +/** + * @defgroup InternalADC InternalADC + * @brief The internal ADC module provides functions for reading the sampled + * internal ADC channel data. + * + * @addtogroup InternalADC + * @{ + */ + +// ********** public definitions ********** + +#define INT_ADC_BITS_PER_CHANNEL 12 ///< Internal ADC channels are 12-bit. +#define INT_ADC_FULL_SCALE_BITS 4096 ///< Internal ADC has 4096 full scale counts per channel. +#define INT_ADC_ZERO 1998 ///< For signed 2's compliment data, zero is here. +#define INT_ADC_REF_V 3.0F ///< Internal ADC reference voltage is 3.0V. + +/// Enumeration of internal ADC channels that are used. +typedef enum Int_ADC_Channels +{ + INT_ADC_NOT_USED = 0, ///< Not used + INT_ADC_BLOOD_PUMP_SPEED, ///< Internal ADC channel for blood pump speed + INT_ADC_BLOOD_PUMP_MOTOR_CURRENT, ///< Internal ADC channel for blood pump current + INT_ADC_AVAILABLE_1, ///< Internal ADC channel for + INT_ADC_AVAILABLE_2, ///< Internal ADC channel for + INT_ADC_AVAILABLE_3, ///< Internal ADC channel for + INT_ADC_AVAILABLE_4, ///< Internal ADC channel for + INT_ADC_PS_THERMISTOR, ///< Internal ADC channel for power supply temperature + INT_ADC_PBA_ADC_REF, ///< Internal ADC channel for reference voltage to PBA ADC channel) + INT_ADC_24V_ACTUATORS_REG, ///< Internal ADC channel for 24V regen (diode drop) to actuators + INT_ADC_1_2V_PROCESSOR, ///< Internal ADC channel for 1.2V to processor + INT_ADC_5V_SENSORS, ///< Internal ADC channel for 5V to sensors + INT_ADC_PRIMARY_ALARM_CURRENT_HG, ///< Internal ADC channel for primary alarm audio current high gain + INT_ADC_BOARD_THERMISTOR, ///< Internal ADC channel for PCB temperature + INT_ADC_1_25_FPGA_ADC_REF, ///< Internal ADC channel for FPGA ADC reference voltage + INT_ADC_3_3V, ///< Internal ADC channel for 3.3V + INT_ADC_5V_LOGIC, ///< Internal ADC channel for 5V to logic + INT_ADC_PRIMARY_ALARM_CURRENT_LG, ///< Internal ADC channel for primary alarm audio current low gain + INT_ADC_24V_ACTUATORS, ///< Internal ADC channel for 24V to actuators + INT_ADC_NOT_USED_2, ///< Not used + INT_ADC_DUMMY, ///< Internal ADC channel - not used, needed to get even number of channels + NUM_OF_INT_ADC_CHANNELS ///< Number of used internal ADC channels. +} INT_ADC_CHANNEL_T; + +// ********** public function prototypes ********** + +void initInternalADC( void ); +void execInternalADC( void ); +U16 getIntADCReading( INT_ADC_CHANNEL_T channel ); +F32 getIntADCVoltageConverted( INT_ADC_CHANNEL_T channel ); + +/**@}*/ + +#endif Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -rf688e0f8bded1f0a687437e3136cfba8b14f87b6 -r766e65a173747dd60a9faae1cac228cd5f8a55a6 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision f688e0f8bded1f0a687437e3136cfba8b14f87b6) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -97,6 +97,10 @@ SW_FAULT_ID_WATCHDOG_INVALID_SELF_TEST_STATE = 66, SW_FAULT_ID_WATCHDOG_INVALID_TASK = 67, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_FOR_START_TIME = 68, + SW_FAULT_ID_INT_ADC_DATA_OVERRUN = 69, + SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED1 = 70, + SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED2 = 71, + SW_FAULT_ID_SAFETY_SHUTDOWN_INVALID_SELF_TEST_STATE = 72, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/AlarmMgmtTD.c =================================================================== diff -u -rf688e0f8bded1f0a687437e3136cfba8b14f87b6 -r766e65a173747dd60a9faae1cac228cd5f8a55a6 --- firmware/App/Services/AlarmMgmtTD.c (.../AlarmMgmtTD.c) (revision f688e0f8bded1f0a687437e3136cfba8b14f87b6) +++ firmware/App/Services/AlarmMgmtTD.c (.../AlarmMgmtTD.c) (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -18,6 +18,7 @@ #include "mibspi.h" #include "AlarmLamp.h" +#include "AlarmMgmtTD.h" //#include "CPLD.h" //#include "FPGA.h" //#include "InternalADC.h" Index: firmware/App/Services/CpldInterface.c =================================================================== diff -u --- firmware/App/Services/CpldInterface.c (revision 0) +++ firmware/App/Services/CpldInterface.c (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -0,0 +1,432 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file CPLD.c +* +* @author (last) Sean +* @date (last) 07-Aug-2024 +* +* @author (original) Sean +* @date (original) 07-Aug-2024 +* +***************************************************************************/ + +#include "gio.h" +#include "mibspi.h" + +#include "CpldIO.h" +#include "CpldInterface.h" +#include "Messaging.h" +#include "Timers.h" + +/** + * @addtogroup CPLD_Interface + * @{ + */ + +// ********** private definitions ********** + +#define SAFETY_SHUTDOWN_POST_TIMEOUT_MS 500 ///< Safety shutdown POST test timeout (in ms). +#define SAFETY_SHUTDOWN_RECOVERY_TIME_MS 500 ///< After safety shutdown POST test, wait this long (in ms) to recover before moving on. + +#define MAX_24V_LEVEL_ON_SAFETY_SHUTDOWN 5.0F ///< Maximum voltage on 24V line when safety shutdown asserted. +#define MIN_24V_LEVEL_ON_SAFETY_RECOVER 22.6F ///< Minimum voltage on 24V line when safety shutdown is recovered. +#define MIN_BACKUP_ALARM_CURRENT_MA 200.0F ///< Minimum backup alarm audio current (in mA) detected when safety shutdown asserted. +#define MAX_BACKUP_ALARM_CURRENT_MA 10.0F ///< Maximum backup alarm audio current (in mA) detected when safety shutdown is recovered. + +#define SAFETY_POST_24V_INITIAL 0 ///< Safety shutdown POST failed because 24V was out before safety line pulled. +#define SAFETY_POST_24V_NOT_CUT 1 ///< Safety shutdown POST failed because 24V was not cut when safety line pulled. +#define SAFETY_POST_NO_24V_RESTORE 2 ///< Safety shutdown POST failed because 24V was not restored when safety line reset. + +/// Enumeration of safety shutdown self-test states. +typedef enum Safety_Shutdown_Self_Test_States +{ + SAFETY_SHUTDOWN_SELF_TEST_STATE_START = 0, ///< Safety shutdown self-test start state + SAFETY_SHUTDOWN_SELF_TEST_STATE_IN_PROGRESS, ///< Safety shutdown self-test in progress state + SAFETY_SHUTDOWN_SELF_TEST_STATE_RECOVER, ///< Safety shutdown self-test recovery state + SAFETY_SHUTDOWN_SELF_TEST_STATE_COMPLETE, ///< Safety shutdown self-test completed state + NUM_OF_SAFETY_SHUTDOWN_SELF_TEST_STATES ///< Number of safety shutdown self-test states +} SAFETY_SHUTDOWN_SELF_TEST_STATE_T; + +// ********** private data ********** + +static BOOL safetyShutdownActivated; ///< Status of safety shutdown signal. +static BOOL safetyShutdownOverrideResetState; ///< Natural status of safety shutdown signal. Used to restore state on override reset. +static SAFETY_SHUTDOWN_SELF_TEST_STATE_T safetyShutdownSelfTestState; ///< Current safety shutdown self-test state. +static SELF_TEST_STATUS_T safetyShutdownSelfTestStatus; ///< Safety shutdown self-test preliminary status. +static U32 safetyShutdownSelfTestTimerCount; ///< Safety shutdown self-test state timer counter. + +/*********************************************************************//** + * @brief + * The initCPLD function initializes the CPLD module. All outputs to CPLD + * (watchdog pet, off request, and alarm lamp LEDs) are set to low. + * @details Inputs: none + * @details Outputs: CPLD module signal outputs set to initial states. + * @return none + *************************************************************************/ +void initCPLD( void ) +{ + // Initialize watchdog pet output low (inactive) + CLR_WD_PET(); + + // Initialize power off request output low (inactive) + CLR_OFF_REQ(); + + // Initialize alarm lamp color LED outputs low (off) + CLR_GREEN(); + CLR_RED(); + CLR_BLUE(); + + // Initialize safety shutdown + CLR_SAFETY_SHUTDOWN(); + safetyShutdownActivated = FALSE; + safetyShutdownOverrideResetState = FALSE; + safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_START; + safetyShutdownSelfTestStatus = SELF_TEST_STATUS_IN_PROGRESS; + safetyShutdownSelfTestTimerCount = 0; +} + +/*********************************************************************//** + * @brief + * The toggleCPLDWatchdog function toggles the watchdog pet signal to CPLD. + * @details Inputs: none + * @details Outputs: watchdog pet signal toggled. + * @return none + *************************************************************************/ +void toggleCPLDWatchdog( void ) +{ + TGL_WD_PET(); +} + +/*********************************************************************//** + * @brief + * The getCPLDWatchdogExpired function determines the current signal level + * on the watchdog expired pin from the CPLD. + * @details Inputs: Signal from CPLD on watchdog expired pin. + * @details Outputs: none + * @return level (LOW or HIGH) + *************************************************************************/ +PIN_SIGNAL_STATE_T getCPLDWatchdogExpired( void ) +{ + PIN_SIGNAL_STATE_T level = GET_WD_EXP(); + + return level; +} + +/*********************************************************************//** + * @brief + * The getCPLDACPowerLossDetected function determines whether the CPLD is + * reporting A/C power has been lost. + * @details Inputs: Signal from CPLD on A/C presence pin. + * @details Outputs: none + * @return TRUE if A/C power loss is detected, FALSE if not + *************************************************************************/ +BOOL getCPLDACPowerLossDetected( void ) +{ + PIN_SIGNAL_STATE_T acLevel = GET_AC_PRESENT(); + BOOL acLost = ( PIN_SIGNAL_HIGH == acLevel ? FALSE : TRUE ); + + return acLost; +} + +/*********************************************************************//** + * @brief + * The setCPLDLampGreen function sets the alarm lamp green signal to CPLD + * to given level. + * @details Inputs: none + * @details Outputs: alarm lamp green signal set to given level. + * @param level LOW or HIGH + * @return none + *************************************************************************/ +void setCPLDLampGreen( PIN_SIGNAL_STATE_T level ) +{ + if ( level == PIN_SIGNAL_HIGH ) + { + SET_GREEN(); + } + else + { + CLR_GREEN(); + } +} + +/*********************************************************************//** + * @brief + * The setCPLDLampBlue function sets the alarm lamp blue signal to CPLD + * to given level. + * @details Inputs: none + * @details Outputs: alarm lamp blue signal set to given level. + * @param level LOW or HIGH + * @return none + *************************************************************************/ +void setCPLDLampBlue( PIN_SIGNAL_STATE_T level ) +{ + if ( level == PIN_SIGNAL_HIGH ) + { + SET_BLUE(); + } + else + { + CLR_BLUE(); + } +} + +/*********************************************************************//** + * @brief + * The setCPLDLampRed function sets the alarm lamp red signal to CPLD + * to given level. + * @details Inputs: none + * @details Outputs: alarm lamp red signal set to given level. + * @param level LOW or HIGH + * @return none + *************************************************************************/ +void setCPLDLampRed( PIN_SIGNAL_STATE_T level ) +{ + if ( level == PIN_SIGNAL_HIGH ) + { + SET_RED(); + } + else + { + CLR_RED(); + } +} + +/*********************************************************************//** + * @brief + * The toggleCPLDOffRequest function toggles the off request signal to CPLD. + * The off request signal must be toggled 4 times, once every 50 ms, in order + * for the CPLD to accept the off request sequence and initiate system power + * down. + * @details Inputs: none + * @details Outputs: off request signal toggled. + * @return none + *************************************************************************/ +void toggleCPLDOffRequest( void ) +{ + TGL_OFF_REQ(); +} + +/*********************************************************************//** + * @brief + * The getCPLDOffButton function determines the current signal level + * on the off button pin from the CPLD. + * @details Inputs: Signal from CPLD on off button pin. + * @details Outputs: none + * @return level (LOW or HIGH) + *************************************************************************/ +PIN_SIGNAL_STATE_T getCPLDOffButton( void ) +{ + PIN_SIGNAL_STATE_T level = GET_OFF(); + + return level; +} + +/*********************************************************************//** + * @brief + * The getCPLDStopButton function determines the current signal level + * on the stop button pin from the CPLD. + * @details Inputs: Signal from CPLD on off button pin. + * @details Outputs: none + * @return level (LOW or HIGH) + *************************************************************************/ +PIN_SIGNAL_STATE_T getCPLDStopButton( void ) +{ + PIN_SIGNAL_STATE_T level = GET_STOP(); + + return level; +} + +/*********************************************************************//** + * @brief + * The activateSafetyShutdown function activates the safety shutdown signal. + * @details Inputs: none + * @details Outputs: Safety Shutdown signal output set to active state. + * @return none + *************************************************************************/ +void activateSafetyShutdown( void ) +{ + safetyShutdownActivated = TRUE; + SET_SAFETY_SHUTDOWN(); +// SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SAFETY_LINE, 1, 0 ) +} + +/*********************************************************************//** + * @brief + * The isSafetyShutdownActivated function returns whether the safety shutdown + * signal has been activated. + * @details Inputs: none + * @details Outputs: none + * @return safetyShutdownActivated + *************************************************************************/ +BOOL isSafetyShutdownActivated( void ) +{ + return safetyShutdownActivated; +} + +/*********************************************************************//** + * @brief + * The execSafetyShutdownTest function executes the safety shutdown test. + * This function should be called periodically until a pass or fail + * result is returned. + * @details Inputs: safetyShutdownSelfTestState + * @details Outputs: safetyShutdownSelfTestState + * @return in progress, passed, or failed + *************************************************************************/ +SELF_TEST_STATUS_T execSafetyShutdownTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + switch ( safetyShutdownSelfTestState ) + { + case SAFETY_SHUTDOWN_SELF_TEST_STATE_START: + { +// F32 v24 = getIntADCVoltageConverted( INT_ADC_24V_ACTUATORS ); +// +// safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_IN_PROGRESS; +// +// // Verify 24V is up +// if ( v24 < MIN_24V_LEVEL_ON_SAFETY_RECOVER ) +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SAFETY_SHUTDOWN_POST_TEST_FAILED, (F32)SAFETY_POST_24V_INITIAL, v24 ) +// safetyShutdownSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } + safetyShutdownSelfTestTimerCount = getMSTimerCount(); + activateSafetyShutdown(); + } + break; + + case SAFETY_SHUTDOWN_SELF_TEST_STATE_IN_PROGRESS: + if ( TRUE == didTimeout( safetyShutdownSelfTestTimerCount, SAFETY_SHUTDOWN_POST_TIMEOUT_MS ) ) + { +// F32 v24 = getIntADCVoltageConverted( INT_ADC_24V_ACTUATORS ); +// F32 audioCurrent = getFPGABackupAlarmAudioCurrent(); +// +// // Verify 24V is down when w.d. expired +// if ( v24 > MAX_24V_LEVEL_ON_SAFETY_SHUTDOWN ) +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SAFETY_SHUTDOWN_POST_TEST_FAILED, (F32)SAFETY_POST_24V_NOT_CUT, v24 ) +// safetyShutdownSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } + safetyShutdownSelfTestTimerCount = getMSTimerCount(); + CLR_SAFETY_SHUTDOWN(); + safetyShutdownActivated = FALSE; + safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_RECOVER; + } + break; + + case SAFETY_SHUTDOWN_SELF_TEST_STATE_RECOVER: + if ( TRUE == didTimeout( safetyShutdownSelfTestTimerCount, SAFETY_SHUTDOWN_RECOVERY_TIME_MS ) ) + { +// F32 v24 = getIntADCVoltageConverted( INT_ADC_24V_ACTUATORS ); +// F32 audioCurrent = getFPGABackupAlarmAudioCurrent(); +// +// // Verify 24V is down when w.d. recovered +// if ( v24 < MIN_24V_LEVEL_ON_SAFETY_RECOVER ) +// { +// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SAFETY_SHUTDOWN_POST_TEST_FAILED, (F32)SAFETY_POST_NO_24V_RESTORE, v24 ) +// safetyShutdownSelfTestStatus = SELF_TEST_STATUS_FAILED; +// } +// else +// { +// safetyShutdownSelfTestStatus = SELF_TEST_STATUS_PASSED; +// } + safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_COMPLETE; + result = safetyShutdownSelfTestStatus; + } + break; + + case SAFETY_SHUTDOWN_SELF_TEST_STATE_COMPLETE: + // If we get called in this state, assume we are doing self-test again + result = SELF_TEST_STATUS_IN_PROGRESS; + safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_START; + break; + + default: + result = SELF_TEST_STATUS_FAILED; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_SAFETY_SHUTDOWN_INVALID_SELF_TEST_STATE, safetyShutdownSelfTestState ) + break; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The resetSafetyShutdownPOSTState function resets safety shutdown POST state. + * @details Inputs: none + * @details Outputs: safetyShutdownSelfTestState + * @return none + *************************************************************************/ +void resetSafetyShutdownPOSTState( void ) +{ + safetyShutdownSelfTestState = SAFETY_SHUTDOWN_SELF_TEST_STATE_START; +} + +/*********************************************************************//** + * @brief + * The testSetSafetyShutdownOverride function overrides the HD safety + * shutdown. + * @details Inputs: none + * @details Outputs: HD safety shutdown overridden + * @param value TRUE to activate safety shutdown, FALSE to de-activate it. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSafetyShutdownOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + // Remember natural state before override so we can reset + safetyShutdownOverrideResetState = safetyShutdownActivated; + // Override safety shutdown signal + if ( value > 0 ) + { + activateSafetyShutdown(); + } + else + { + safetyShutdownActivated = FALSE; + CLR_SAFETY_SHUTDOWN(); + } + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSafetyShutdownOverride function resets the override of the + * HD safety shutdown. + * @details Inputs: none + * @details Outputs: shutdown override reset + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSafetyShutdownOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + if ( TRUE == safetyShutdownOverrideResetState ) + { + activateSafetyShutdown(); + } + else + { + safetyShutdownActivated = FALSE; + CLR_SAFETY_SHUTDOWN(); + } + result = TRUE; + } + + return result; +} + +/**@}*/ Index: firmware/App/Services/CpldInterface.h =================================================================== diff -u --- firmware/App/Services/CpldInterface.h (revision 0) +++ firmware/App/Services/CpldInterface.h (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -0,0 +1,67 @@ +/************************************************************************** +* +* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file CPLD.h +* +* @author (last) Sean +* @date (last) 07-Aug-2024 +* +* @author (original) Sean +* @date (original) 07-Aug-2024 +* +***************************************************************************/ + +#ifndef __CPLD_H__ +#define __CPLD_H__ + +#include "TDCommon.h" + +/** + * @defgroup CPLD_Interface CPLD_Interface + * @brief The CPLD interface module provides functions to interface with the + * CPLD (watchdog, safety, alarm lamp, off/stop buttons, power off request). + * + * @addtogroup CPLD_Interface + * @{ + */ + +// ********** public definitions ********** + +/// Safety shutdown broadcast data +typedef struct +{ + U32 isSafetyShutdownActivated; ///< Is safety shutdown active boolean flag +} TD_SAFETY_SHUTDOWN_DATA_T; + +// ********** public function prototypes ********** + +void initCPLD( void ); + +void toggleCPLDWatchdog( void ); +PIN_SIGNAL_STATE_T getCPLDWatchdogExpired( void ); + +void setCPLDLampGreen( PIN_SIGNAL_STATE_T level ); +void setCPLDLampBlue( PIN_SIGNAL_STATE_T level ); +void setCPLDLampRed( PIN_SIGNAL_STATE_T level ); + +void toggleCPLDOffRequest( void ); +PIN_SIGNAL_STATE_T getCPLDOffButton( void ); +PIN_SIGNAL_STATE_T getCPLDStopButton( void ); + +BOOL getCPLDACPowerLossDetected( void ); + +void activateSafetyShutdown( void ); +BOOL isSafetyShutdownActivated( void ); +SELF_TEST_STATUS_T execSafetyShutdownTest( void ); +void resetSafetyShutdownPOSTState( void ); + +BOOL testSetSafetyShutdownOverride( U32 value ); +BOOL testResetSafetyShutdownOverride( void ); + +/**@}*/ + +#endif Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r3321a6fc6f08b731cfe3dafaa618f93b32acaf45 -r766e65a173747dd60a9faae1cac228cd5f8a55a6 --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 3321a6fc6f08b731cfe3dafaa618f93b32acaf45) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -262,10 +262,10 @@ * @brief * The getMsgHandler function finds the appropriate handler function * for the given message. - * @details Inputs: MSG_FUNCTION_HANDLER_LOOKUP[], - * @details Outputs: Appropriate message handler function called - * @param message Incoming message to handle - * @return none + * @details Inputs: MSG_FUNCTION_HANDLER_LOOKUP[], MSG_FUNCTION_HANDLERS[] + * @details Outputs: none + * @param msgID ID of message to find handler function for + * @return pointer to appropriate function to handle given message *************************************************************************/ static MsgFuncPtr getMsgHandler( U16 msgID ) { @@ -288,7 +288,7 @@ * @brief * The handleIncomingMessage function calls the appropriate handler function * for the given message. - * @details Inputs: + * @details Inputs: none * @details Outputs: Appropriate message handler function called * @param message Incoming message to handle * @return none @@ -315,7 +315,10 @@ // ACK/NAK request if ( message->hdr.msgID < MSG_ID_FIRST_TD_TESTER_MESSAGE ) { - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, respBuffer, ack ); + if ( respBuffer != COMM_BUFFER_NOT_USED ) + { + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, respBuffer, ack ); + } } else { Index: firmware/source/sys_main.c =================================================================== diff -u -r73d8423edc56daed591bc0b3f7baee5540aea423 -r766e65a173747dd60a9faae1cac228cd5f8a55a6 --- firmware/source/sys_main.c (.../sys_main.c) (revision 73d8423edc56daed591bc0b3f7baee5540aea423) +++ firmware/source/sys_main.c (.../sys_main.c) (revision 766e65a173747dd60a9faae1cac228cd5f8a55a6) @@ -63,7 +63,10 @@ #include "rti.h" #include "TDCommon.h" +#include "CpldInterface.h" +#include "DDInterface.h" #include "FpgaTD.h" +#include "InternalADC.h" #include "Interrupts.h" #include "MsgQueues.h" #include "OperationModes.h" @@ -162,15 +165,15 @@ // Initialize alarm manager initAlarmMgmt(); // Initialize drivers -// initCPLD(); -// initInternalADC(); + initCPLD(); + initInternalADC(); // initBattery(); // Initialize async interrupt handlers initInterrupts(); // Initialize services initTestConfigs(); initCommBuffers(); -// initDDInterface(); + initDDInterface(); // initIntegrity(); initFpgaTD(); initMsgQueues();