Index: firmware/App/Modes/FPModes/FPOperationModes.c =================================================================== diff -u -r89c8709e3b27648926fbb20f25c9a67cbeb99adc -r336f6c49e05f515ca1250e0fd9ea97e5f5b5f11c --- firmware/App/Modes/FPModes/FPOperationModes.c (.../FPOperationModes.c) (revision 89c8709e3b27648926fbb20f25c9a67cbeb99adc) +++ firmware/App/Modes/FPModes/FPOperationModes.c (.../FPOperationModes.c) (revision 336f6c49e05f515ca1250e0fd9ea97e5f5b5f11c) @@ -7,8 +7,8 @@ * * @file FPOperationModes.c * -* @author (last) “rkallala” -* @date (last) 15-Jan-2026 +* @author (last) Michael Garthwaite +* @date (last) 17-Apr-2026 * * @author (original) Michael Garthwaite * @date (original) 08-Sep-2025 @@ -49,6 +49,8 @@ static U32 current4thLevelState; ///< current 4th level state. static BOOL isDeviceDefeatured; ///< bool to determine defeatured status static BOOL isBoostInstalled; ///< bool to determine boost pump status +static U32 testRequestedSubMode; ///< Requested operation sub mode from dialin. +static BOOL testChangeSubMode; ///< Flag to determine change operation sub mode request status. /// Interval (in task intervals) at which to publish operation mode data to CAN bus. static OVERRIDE_U32_T opModePublishInterval = { BROADCAST_TD_OP_MODE_INTERVAL, BROADCAST_TD_OP_MODE_INTERVAL, BROADCAST_TD_OP_MODE_INTERVAL, 0 }; @@ -70,6 +72,8 @@ static FP_OP_MODE_T arbitrateModeRequest( void ); static void transitionToNewOperationMode( FP_OP_MODE_T newMode ); static void broadcastOperationMode( void ); +static void testRequestNewFPOperationSubMode( void ); +static BOOL testValidateSubModeChangeRequest( FP_OP_MODE_T reqMode, U32 reqSubMode ); /*********************************************************************//** * @brief @@ -97,6 +101,8 @@ broadcastModeIntervalCtr = DATA_PUBLISH_COUNTER_START_COUNT; isDeviceDefeatured = FALSE; isBoostInstalled = FALSE; + testRequestedSubMode = 0; + testChangeSubMode = FALSE; transitionToNewOperationMode( FP_MODE_INIT ); @@ -126,10 +132,15 @@ // Any new mode requests? newMode = arbitrateModeRequest(); // Will return current mode if no pending requests - newMode = MODE_TRANSITION_TABLE[ currentMode ][ newMode ]; + if ( isTestingActivated() != TRUE ) + { + // if the test configuration is not enabled check for the legality of the transition request + newMode = MODE_TRANSITION_TABLE[ currentMode ][ newMode ]; + } + // Is requested new mode valid and legal at this time? - if ( ( newMode >= FP_MODE_NLEG ) && ( isTestingActivated() != TRUE ) ) + if ( newMode >= FP_MODE_NLEG ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_FP_SOFTWARE_FAULT, FP_FAULT_ID_OP_MODES_ILLEGAL_MODE_TRANSITION_REQUESTED, newMode ) newMode = currentMode; @@ -144,6 +155,12 @@ currentMode = newMode; // sendOperationStatusEvent(); } + // Is sub mode change request active? + if ( TRUE == testChangeSubMode ) + { + testChangeSubMode = FALSE; + testRequestNewFPOperationSubMode(); + } // Mode specific processing to be done continuously switch ( currentMode ) @@ -177,7 +194,7 @@ break; case FP_MODE_DEGP: - currentSubMode = execPreGenPMode(); + currentSubMode = execGenPermeateDefeaturedMode(); break; default: @@ -403,11 +420,22 @@ * @brief * The isFPDefeatured function returns if the Leahi device is defeatured. * @details \b Inputs: none - * @details \b Outputs: none + * @details \b Outputs: isDeviceDefeatured * @return TRUE if FP device is de-featured, FALSE if not. *************************************************************************/ BOOL isFPDefeatured( void ) { + // TODO decide whether we need this test config even after NVM is defined + if ( TRUE == getTestConfigStatus( TEST_CONFIG_FP_ENABLE_DEFEATURE ) ) + { + isDeviceDefeatured = TRUE; + } + // TODO remove the else if after NVM implementation. Value is read from NV memory no need to reset + else if ( TRUE != getTestConfigStatus( TEST_CONFIG_FP_ENABLE_DEFEATURE ) ) + { + isDeviceDefeatured = FALSE; + } + // TODO - pull status from NV mem. return isDeviceDefeatured; } @@ -417,11 +445,22 @@ * The isBoostPumpInstalled function returns if the Leahi device * has a boost pump installed. * @details \b Inputs: none - * @details \b Outputs: none + * @details \b Outputs: isBoostInstalled * @return TRUE if FP device is contains a boost pump, FALSE if not. *************************************************************************/ BOOL isBoostPumpInstalled( void ) { + // TODO decide whether we need this test config even after NVM is defined + if ( TRUE == getTestConfigStatus( TEST_CONFIG_FP_ENABLE_BOOST_PUMP ) ) + { + isBoostInstalled = TRUE; + } + // TODO remove the else if after NVM implementation. Value is read from NV memory no need to reset + else if ( TRUE != getTestConfigStatus( TEST_CONFIG_FP_ENABLE_BOOST_PUMP ) ) + { + isBoostInstalled = FALSE; + } + // TODO - pull status from NV mem. return isBoostInstalled; } @@ -597,4 +636,175 @@ return result; } +/*********************************************************************//** + * @brief + * The testGetFPBoostPumpInstallStatus function return whether FP Boost Pump + * is installed or not. + * @details \b Inputs: none + * @details \b Outputs: none + * @details \b Message: \b Sent: MSG_ID_FP_BOOST_PUMP_INSTALL_STATUS_RESPONSE + * @param message request message from Dialin for FP boost pump install status. + * @return TRUE if request is successful, FALSE if not + *************************************************************************/ +BOOL testGetFPBoostPumpInstallStatus( MESSAGE_T *message ) +{ + BOOL result = FALSE; + FP_BOOST_PUMP_INSTALL_STATUS_PAYLOAD_T data; + + data.isFPBoostPumpInstalled = isBoostPumpInstalled(); + result = sendMessage( MSG_ID_FP_BOOST_PUMP_INSTALL_STATUS_RESPONSE, COMM_BUFFER_OUT_DD_CAN_PC, (U08*)&data, sizeof(FP_BOOST_PUMP_INSTALL_STATUS_PAYLOAD_T) ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetFPOperationSubMode function will transition to a given + * sub mode if the transition is legal. + * @details \b Inputs: currentMode, currentSubMode + * @details \b Outputs: modeRequest[], testRequestedSubMode, testChangeSubMode + * @param message message from Dialin which includes the sub mode to + * transition to. + * @return TRUE if request successful, FALSE if not + *************************************************************************/ +BOOL testSetFPOperationSubMode( MESSAGE_T *message ) +{ + OP_MODE_PAYLOAD_T payload; + BOOL result = FALSE; + + // Verify message payload length is valid + if ( sizeof( OP_MODE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + FP_OP_MODE_T reqMode; + U32 reqSubMode; + + memcpy( (U08*)(&payload), message->payload, sizeof( OP_MODE_PAYLOAD_T ) ); + + reqMode = (FP_OP_MODE_T)payload.opMode; + reqSubMode = payload.subMode; + + if ( reqMode < NUM_OF_FP_MODES ) + { + // verify if the requested submode transition is possible + result = testValidateSubModeChangeRequest( reqMode, reqSubMode ); + + // send the sub mode change request only if the requested transition is valid + if ( TRUE == result ) + { + // request new operation mode and sub mode if the requested operation mode is not current mode + if ( currentMode != reqMode ) + { + requestNewFPOperationMode( reqMode ); + testRequestedSubMode = reqSubMode; + testChangeSubMode = TRUE; + } + // request submode change only as the requested operation mode is current mode and requested sub mode is not current sub mode + else if ( currentSubMode != reqSubMode ) + { + testRequestedSubMode = reqSubMode; + testChangeSubMode = TRUE; + } + } + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testValidateSubModeChangeRequest function validates the + * requested sub mode change is acceptable or not. + * operation sub mode. + * @details \b Inputs: none + * @details \b Outputs: none + * @param reqMode FP operation mode enumeration + * @param reqSubMode operation sub mode requested + * @return TRUE if request is legal, FALSE if not. + *************************************************************************/ +static BOOL testValidateSubModeChangeRequest( FP_OP_MODE_T reqMode, U32 reqSubMode ) +{ + BOOL result = FALSE; + + switch ( reqMode ) + { + case FP_MODE_PGEN: + result = testValidatePreGenPChangeReq( reqSubMode ); + break; + + case FP_MODE_GENP: + result = testValidateGenPermeateChangeReq( reqSubMode ); + break; + + case FP_MODE_DPGP: + result = testValidatePreGenPDefeaturedChangeReq( reqSubMode ); + break; + + case FP_MODE_DEGP: + result = testValidateGenPDefeaturedChangeReq( reqSubMode ); + break; + + case FP_MODE_FAUL: + result = testValidateFaultChangeReq( reqSubMode ); + break; + + case FP_MODE_STAN: + result = testValidateStandbyChangeReq( reqSubMode ); + break; + + // No need to validate the request for the following modes as it is not supported + case FP_MODE_SERV: + case FP_MODE_INIT: + default: + // result is already FALSE. Do nothing for modes that do not support jump to sub-mode + break; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testRequestNewFPOperationSubMode function requests transition to a new + * operation sub mode. + * @details \b Inputs: currentMode, testRequestedSubMode + * @details \b Outputs: none + * @return none + *************************************************************************/ +static void testRequestNewFPOperationSubMode( void ) +{ + switch ( currentMode ) + { + case FP_MODE_PGEN: + testSignalNewPreGenPSubMode( testRequestedSubMode ); + break; + + case FP_MODE_GENP: + testSignalNewGenPermeateSubMode( testRequestedSubMode ); + break; + + case FP_MODE_DPGP: + testSignalNewPreGenPDefeaturedSubMode( testRequestedSubMode ); + break; + + case FP_MODE_DEGP: + testSignalNewGenPDefeaturedSubMode( testRequestedSubMode ); + break; + + case FP_MODE_FAUL: + testSignalNewFaultSubMode( testRequestedSubMode ); + break; + + case FP_MODE_STAN: + testSignalNewStandbySubMode( testRequestedSubMode ); + break; + + case FP_MODE_SERV: + case FP_MODE_INIT: + default: + // do nothing for modes that do not support jump to sub-mode + break; + } +} + /**@}*/