/************************************************************************** * * Copyright (c) 2021-2023 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) Dara Navaei * @date (last) 28-Sep-2022 * * @author (original) Dara Navaei * @date (original) 24-Jul-2021 * ***************************************************************************/ #include "FPGA.h" #include "MessageSupport.h" #include "Switches.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.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 debounce time in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 7 ///< Data publish counter start count. /// Switch status structure typedef struct { OVERRIDE_U32_T status; ///< Switch status. U32 debounceStartTime; ///< Debounce start time. } SWITCH_STATUS_T; // ********** private data ********** static U32 switchesDataPublicationCounter; ///< Switches data publication counter. static OVERRIDE_U32_T switchesDataPublishInterval = { SWITCHES_DATA_PUB_INTERVAL, SWITCHES_DATA_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish switches data to CAN bus. static SWITCH_STATUS_T switchesStatus[ NUM_OF_CAPS ]; ///< Switches status array. // ********** private function prototypes ********** static void publishSwitchesData( void ); /*********************************************************************//** * @brief * The initSwitches function initializes the switches module. * @details Inputs: none * @details Outputs: switchesDataPublicationCounter, switchStatus * @return none *************************************************************************/ void initSwitches( void ) { U08 i; switchesDataPublicationCounter = DATA_PUBLISH_COUNTER_START_COUNT; // Initialize all the switches for ( i = 0; i < NUM_OF_CAPS; i++ ) { switchesStatus[ i ].status.data = (U32)STATE_CLOSED; switchesStatus[ i ].status.ovData = (U32)STATE_CLOSED; switchesStatus[ i ].status.ovInitData = (U32)STATE_CLOSED; switchesStatus[ i ].status.override = OVERRIDE_RESET; switchesStatus[ i ].debounceStartTime = 0; } } /*********************************************************************//** * @brief * The execSwitches function executes the switches executive. * @details Inputs: switchesStatus * @details Outputs: switchStatus * @return none *************************************************************************/ void execSwitches( void ) { U08 i; U08 currentSwitchStatus = 0; for ( i = 0; i < NUM_OF_CAPS; i++ ) { // Get the current switch status switch ( i ) { case CONCENTRATE_CAP: currentSwitchStatus = ( getFPGAConcentrateCapStatus() != 0 ? STATE_OPEN : STATE_CLOSED ); break; case DIALYSATE_CAP: currentSwitchStatus = ( getFPGADialysateCapStatus() != 0 ? STATE_OPEN : STATE_CLOSED ); break; #ifndef _VECTORCAST_ default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_SWITCH_SELECTED, i ); break; #endif } // Check if the current switch status is not the same as the recorded data if ( currentSwitchStatus != switchesStatus[ i ].status.data ) { // If the debounce time is 0, start the timer if ( 0 == switchesStatus[ i ].debounceStartTime ) { switchesStatus[ i ].debounceStartTime = getMSTimerCount(); } // If the debounce time has been elapsed, update the switch status to the new status else if ( TRUE == didTimeout( switchesStatus[ i ].debounceStartTime, SWITCHES_DEBOUNCE_TIME_MS ) ) { switch ( i ) { case CONCENTRATE_CAP: SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_CONCENTRATE_CAP_SWITCH_CHANGE, (U32)switchesStatus[ i ].status.data, (U32)currentSwitchStatus ); break; case DIALYSATE_CAP: SEND_EVENT_WITH_2_U32_DATA( DG_EVENT_DIALYSATE_CAP_SWITCH_CHANGE, (U32)switchesStatus[ i ].status.data, (U32)currentSwitchStatus ); break; #ifndef _VECTORCAST_ default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_SWITCH_SELECTED, i ); break; #endif } switchesStatus[ i ].debounceStartTime = 0; switchesStatus[ i ].status.data = currentSwitchStatus; } } else { switchesStatus[ i ].debounceStartTime = 0; } } publishSwitchesData(); } /*********************************************************************//** * @brief * The getSwitchStatus function returns the status of the called switch. * @details Inputs: switchStatus * @details Outputs: switchStatus * @param switchId which is the switch that its status is requested * @return switch status *************************************************************************/ OPN_CLS_STATE_T getSwitchStatus( CAP_T switchId ) { U32 status = 0; if ( switchId < NUM_OF_CAPS ) { // Assume there is no override status = switchesStatus[ switchId ].status.data; if ( OVERRIDE_KEY == switchesStatus[ switchId ].status.override ) { status = switchesStatus[ switchId ].status.ovData; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_INVALID_SWITCH_ID, (U32)switchId ) } return (OPN_CLS_STATE_T)status; } // ********** private functions ********** /*********************************************************************//** * @brief * The publishSwitchesData function broadcasts the switches data at the * publication interval. * @details Inputs: switchesDataPublicationCounter * @details Outputs: switchesDataPublicationCounter * @return none *************************************************************************/ static void publishSwitchesData( void ) { if ( ++switchesDataPublicationCounter >= getU32OverrideValue( &switchesDataPublishInterval ) ) { SWITCHES_DATA_T data; data.concentrateCap = (U32)getSwitchStatus( CONCENTRATE_CAP ); data.dialysateCap = (U32)getSwitchStatus( DIALYSATE_CAP ); switchesDataPublicationCounter = 0; broadcastData( MSG_ID_DG_SWITCHES_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( SWITCHES_DATA_T ) ); } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetSwitchesDataPublishIntervalOverride function overrides * the switches publish data interval. * @details Inputs: switchesDataPublishInterval * @details Outputs: switchesDataPublishInterval * @param value switches data broadcast interval (in ms) to override * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetSwitchesDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 interval = value / TASK_GENERAL_INTERVAL; result = TRUE; switchesDataPublishInterval.ovData = interval; switchesDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetSwitchesDataPublishIntervalOverrid function resets * the override value of switches publish data interval. * @details Inputs: switchesDataPublishInterval * @details Outputs: switchesDataPublishInterval * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetSwitchesDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; switchesDataPublishInterval.override = OVERRIDE_RESET; switchesDataPublishInterval.ovData = switchesDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetSwitchesStatusOverride function sets the override status * for a specific switch. * @details Inputs: none * @details Outputs: switchStatus * @param switchId switch index * @param status switch status to override if testing is activated * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetSwitchesStatusOverride( U32 switchId, U32 status ) { BOOL result = FALSE; if ( switchId < NUM_OF_CAPS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; switchesStatus[ switchId ].status.ovData = status; switchesStatus[ switchId ].status.override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetSwitchesStatusOverride function resets the override * status of a specified switch. * @details Inputs: none * @details Outputs: switchStatus * @param switchId switch index * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetSwitchesStatusOverride( U32 switchId ) { BOOL result = FALSE; if ( switchId < NUM_OF_CAPS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; switchesStatus[ switchId ].status.override = OVERRIDE_RESET; switchesStatus[ switchId ].status.ovData = switchesStatus[ switchId ].status.ovInitData; } } return result; } /**@}*/