/************************************************************************** * * Copyright (c) 2024-2026 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 Switches.c * * @author (last) N/A * @date (last) N/A * * @author (original) Steve Jarpe * @date (original) 22 May 2026 * ***************************************************************************/ #include "FpgaDD.h" #include "Messaging.h" //#include "NVDataMgmt.h" #include "Switches.h" #include "TaskGeneral.h" #include "Timers.h" #include "MsgDefs.h" /** * @addtogroup Switches * @{ */ // ********** private definitions ********** #define SWITCHES_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the switches data is published on the CAN bus. #define SWITCHES_DEBOUNCE_TIME_MS ( MS_PER_SECOND / 4 ) ///< Switches FPGA status check interval. #define DATA_PUBLISH_COUNTER_START_COUNT 90 ///< Data publish counter start count. // ********** private data ********** static U32 switchesDataPublicationCounter; ///< Switches data publication counter. static OVERRIDE_U32_T switchesDataPublishInterval; ///< Interval (in ms) at which to publish switches data to CAN bus. static OVERRIDE_U32_T switchesStatus[ NUM_OF_SWITCHES ]; ///< Debounced switch states. static U32 switchDebounceStartTimes[ NUM_OF_SWITCHES ]; ///< Switch debounce start times. // ********** private function prototypes ********** static void publishSwitchesData( void ); /*********************************************************************//** * @brief * The initSwitches function initializes the switches unit. * @details \b Inputs: none * @details \b Outputs: Switches monitor unit initialized * @return none *************************************************************************/ void initSwitches( void ) { U32 i; switchesDataPublicationCounter = DATA_PUBLISH_COUNTER_START_COUNT; switchesDataPublishInterval.data = SWITCHES_DATA_PUB_INTERVAL; switchesDataPublishInterval.ovData = SWITCHES_DATA_PUB_INTERVAL; switchesDataPublishInterval.ovInitData = 0; switchesDataPublishInterval.override = OVERRIDE_RESET; // Initialize all the switches for ( i = 0; i < NUM_OF_SWITCHES; i++ ) { switchesStatus[ i ].data = (U32)STATE_CLOSED; switchesStatus[ i ].ovData = (U32)STATE_CLOSED; switchesStatus[ i ].ovInitData = (U32)STATE_CLOSED; switchesStatus[ i ].override = OVERRIDE_RESET; switchDebounceStartTimes[ i ] = 0; } } /*********************************************************************//** * @brief * The execSwitches function executes the switches monitor executive. * Switch state changes are debounced for 250ms before formalizing them. * @details \b Inputs: switchesStatus[], switchDebounceStartTimes[] * @details \b Outputs: switchesStatus[], switchDebounceStartTimes[] * @return none *************************************************************************/ void execSwitches( void ) { U32 i; OPN_CLS_STATE_T currentSwitchStates[ NUM_OF_SWITCHES ]; // Get current state of each switch currentSwitchStates[ D101_SWCH ] = ( FALSE == getD101HDFCapConnectorStatus() ? STATE_OPEN : STATE_CLOSED ); currentSwitchStates[ D102_SWCH ] = ( FALSE == getD102HDFCapConnectorStatus() ? STATE_OPEN : STATE_CLOSED ); currentSwitchStates[ D103_SWCH ] = ( FALSE == getD103HDFCapParkedStatus() ? STATE_OPEN : STATE_CLOSED ); // Debounce each switch for ( i = 0; i < NUM_OF_SWITCHES; i++ ) { #ifndef _RELEASE_ // if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SWITCHES_MONITOR ) ) // { // switchesStatus[ i ].status.data = STATE_CLOSED; // } // else #endif { // Check if the current switch status is not the same as the recorded data if ( (U32)currentSwitchStates[ i ] != switchesStatus[ i ].data ) { // If the debounce time is 0, start the timer if ( 0 == switchDebounceStartTimes[ i ] ) { switchDebounceStartTimes[ i ] = getMSTimerCount(); } // If the debounce time has been elapsed, update the switch status to the new status else if ( TRUE == didTimeout( switchDebounceStartTimes[ i ], SWITCHES_DEBOUNCE_TIME_MS ) ) { // If the bit is 0, the door switch is open, because it is normally open switch switchDebounceStartTimes[ i ] = 0; switchesStatus[ i ].data = currentSwitchStates[ i ]; } } else { switchDebounceStartTimes[ i ] = 0; } } } // Handle publishing switches data publishSwitchesData(); } /*********************************************************************//** * @brief * The getSwitchState function returns the state of a given switch. * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given switch ID is invalid. * @details \b Inputs: switchesStatus * @details \b Outputs: switchesStatus * @param switchId ID of switch to get state for * @return switch state of given switch *************************************************************************/ OPN_CLS_STATE_T getSwitchState( SWITCH_T switchId ) { U32 state = 0; if ( switchId < NUM_OF_SWITCHES ) { state = getU32OverrideValue( &switchesStatus[ switchId ] ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DD_INVALID_SWITCH_ID, (U32)switchId ) } return (OPN_CLS_STATE_T)state; } /*********************************************************************//** * @brief * The publishSwitchesData function broadcasts the switches data at the * publication interval. * @details \b Message \b Sent: MSG_ID_DD_SWITCHES_DATA * @details \b Inputs: switchesDataPublicationCounter, switchesStatus[] * @details \b Outputs: switchesDataPublicationCounter * @return none *************************************************************************/ static void publishSwitchesData( void ) { if ( ++switchesDataPublicationCounter >= getU32OverrideValue( &switchesDataPublishInterval ) ) { SWITCHES_DATA_T data; switchesDataPublicationCounter = 0; data.d101Sw1 = (U32)getSwitchState( D101_SWCH ); data.d102Sw2 = (U32)getSwitchState( D102_SWCH ); data.d103CapParked = (U32)getSwitchState( D103_SWCH ); broadcastData( MSG_ID_DD_SWITCHES_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( SWITCHES_DATA_T ) ); //broadcastData( MSG_ID_TD_BATTERY_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( SWITCHES_DATA_T ) ); } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSwitchesDataPublishIntervalOverride function overrides the interval * at which the DD switches data is published. * @details \b Inputs: none * @details \b Outputs: switchesDataPublishInterval * @param message Override message from Dialin which includes the interval * (in ms) to override the switches broadcast interval to. * @return TRUE if override request is successful, FALSE if not *************************************************************************/ BOOL testSwitchesDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &switchesDataPublishInterval, TASK_GENERAL_INTERVAL ); return result; } /*********************************************************************//** * @brief * The testSwitchOverride function overrides the state for a given switch. * @details \b Inputs: none * @details \b Outputs: switchesStatus[] * @param message Override message from Dialin which includes an ID of * the switch to override and the state to override the switch to. * @return TRUE if override request is successful, FALSE if not *************************************************************************/ BOOL testSwitchOverride( MESSAGE_T *message ) { BOOL result = u32ArrayOverride( message, &switchesStatus[0], NUM_OF_SWITCHES - 1, 0, NUM_OF_OPN_CLS_STATES - 1 ); return result; } /**@}*/