From a563640a1434312c2b891a11d49158bd266b9ba1 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Wed, 8 Oct 2025 21:07:17 -0400 Subject: [PATCH 01/38] Add load switch component --- .../Components/CMakeLists.txt | 1 + .../Components/LoadSwitch/CMakeLists.txt | 36 ++++++++++ .../Components/LoadSwitch/LoadSwitch.cpp | 28 ++++++++ .../Components/LoadSwitch/LoadSwitch.fpp | 60 +++++++++++++++++ .../Components/LoadSwitch/LoadSwitch.hpp | 42 ++++++++++++ .../Components/LoadSwitch/docs/sdd.md | 67 +++++++++++++++++++ 6 files changed, 234 insertions(+) create mode 100644 FprimeZephyrReference/Components/LoadSwitch/CMakeLists.txt create mode 100644 FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp create mode 100644 FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp create mode 100644 FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp create mode 100644 FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md diff --git a/FprimeZephyrReference/Components/CMakeLists.txt b/FprimeZephyrReference/Components/CMakeLists.txt index b881a4a6..186ac4e0 100644 --- a/FprimeZephyrReference/Components/CMakeLists.txt +++ b/FprimeZephyrReference/Components/CMakeLists.txt @@ -8,3 +8,4 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/NullPrmDb/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Watchdog") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Burnwire/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/BootloaderTrigger/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/LoadSwitch/") diff --git a/FprimeZephyrReference/Components/LoadSwitch/CMakeLists.txt b/FprimeZephyrReference/Components/LoadSwitch/CMakeLists.txt new file mode 100644 index 00000000..5be47b2d --- /dev/null +++ b/FprimeZephyrReference/Components/LoadSwitch/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/LoadSwitch.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/LoadSwitch.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/LoadSwitch.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/LoadSwitchTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/LoadSwitchTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp new file mode 100644 index 00000000..7476eba7 --- /dev/null +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -0,0 +1,28 @@ +// ====================================================================== +// \title LoadSwitch.cpp +// \author kyang25 +// \brief cpp file for LoadSwitch component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp" + +namespace Components { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +LoadSwitch ::LoadSwitch(const char* const compName) : LoadSwitchComponentBase(compName) {} + +LoadSwitch ::~LoadSwitch() {} + +// ---------------------------------------------------------------------- +// Handler implementations for commands +// ---------------------------------------------------------------------- + +void LoadSwitch ::TODO_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { + // TODO + this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); +} + +} // namespace Components diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp new file mode 100644 index 00000000..32ce8d7e --- /dev/null +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp @@ -0,0 +1,60 @@ +module Components { + @ A generic load switch for controlling power to components + active component LoadSwitch { + + # One async command/port is required for active components + # This should be overridden by the developers with a useful command/port + @ TODO + async command TODO opcode 0 + + ############################################################################## + #### Uncomment the following examples to start customizing your component #### + ############################################################################## + + # @ Example async command + # async command COMMAND_NAME(param_name: U32) + + # @ Example telemetry counter + # telemetry ExampleCounter: U64 + + # @ Example event + # event ExampleStateEvent(example_state: Fw.On) severity activity high id 0 format "State set to {}" + + # @ Example port: receiving calls from the rate group + # sync input port run: Svc.Sched + + # @ Example parameter + # param PARAMETER_NAME: U32 + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending command registrations + command reg port cmdRegOut + + @ Port for receiving commands + command recv port cmdIn + + @ Port for sending command responses + command resp port cmdResponseOut + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + } +} \ No newline at end of file diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp new file mode 100644 index 00000000..ae2e61d4 --- /dev/null +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp @@ -0,0 +1,42 @@ +// ====================================================================== +// \title LoadSwitch.hpp +// \author kyang25 +// \brief hpp file for LoadSwitch component implementation class +// ====================================================================== + +#ifndef Components_LoadSwitch_HPP +#define Components_LoadSwitch_HPP + +#include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitchComponentAc.hpp" + +namespace Components { + +class LoadSwitch final : public LoadSwitchComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct LoadSwitch object + LoadSwitch(const char* const compName //!< The component name + ); + + //! Destroy LoadSwitch object + ~LoadSwitch(); + + private: + // ---------------------------------------------------------------------- + // Handler implementations for commands + // ---------------------------------------------------------------------- + + //! Handler implementation for command TODO + //! + //! TODO + void TODO_cmdHandler(FwOpcodeType opCode, //!< The opcode + U32 cmdSeq //!< The command sequence number + ) override; +}; + +} // namespace Components + +#endif diff --git a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md new file mode 100644 index 00000000..ccd6de36 --- /dev/null +++ b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md @@ -0,0 +1,67 @@ +# Components::LoadSwitch + +A generic load switch for controlling power to components + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +| Name | Description | +|-------|--------------------------------------| +| Off | No power to the component | +| On | Power supplied to the component | +| Error | An error occurred in the load switch | + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file From 5d5648faba04dcca61c5d1a31c46c573ebe884a6 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Wed, 22 Oct 2025 20:11:39 -0400 Subject: [PATCH 02/38] Fix tables --- FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md index ccd6de36..92c0064d 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md +++ b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md @@ -50,13 +50,11 @@ Add sequence diagrams here |---|---| ## Unit Tests -Add unit test descriptions in the chart below | Name | Description | Output | Coverage | |---|---|---|---| |---|---|---|---| ## Requirements -Add requirements in the chart below | Name | Description | Validation | |---|---|---| |---|---|---| From 8f00e037a3783a5b4ab39be9f86b8792d92dd479 Mon Sep 17 00:00:00 2001 From: sarah Date: Wed, 22 Oct 2025 20:33:26 -0400 Subject: [PATCH 03/38] Sarah Kevin MoMata Squad Load Switch --- .../Components/LoadSwitch/LoadSwitch.fpp | 5 +++++ .../Components/LoadSwitch/docs/sdd.md | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp index 32ce8d7e..de5f76a0 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp @@ -13,15 +13,20 @@ module Components { # @ Example async command # async command COMMAND_NAME(param_name: U32) + async command TURN_ON() + async command TURN_OFF() # @ Example telemetry counter # telemetry ExampleCounter: U64 + telemetry IsOn: Fw.On # @ Example event # event ExampleStateEvent(example_state: Fw.On) severity activity high id 0 format "State set to {}" + event StatusChanged($state: Fw.On) severity activity high id 1 format "Load switch state changed to {}" # @ Example port: receiving calls from the rate group # sync input port run: Svc.Sched + output port Status: Fw.On # @ Example parameter # param PARAMETER_NAME: U32 diff --git a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md index 92c0064d..0537abb4 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md +++ b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md @@ -9,7 +9,7 @@ Add usage examples here Add diagrams here ### Typical Usage -And the typical usage of the component here +The load switch would be used whenever a sensor is to be turned on or off. ## Class Diagram Add a class diagram here @@ -17,7 +17,7 @@ Add a class diagram here ## Port Descriptions | Name | Description | |---|---| -|---|---| +| Status | Boolean value displaying whether the load switch is on or not. | ## Component States | Name | Description | @@ -37,17 +37,18 @@ Add sequence diagrams here ## Commands | Name | Description | |---|---| -|---|---| +| On | Turn on power to the component | +| Off | Turn off power to the component | ## Events | Name | Description | |---|---| -|---|---| +| StatusChanged | Emits event whenever the status of the load switch changes | ## Telemetry | Name | Description | |---|---| -|---|---| +| IsOn | Returns whether the load switch is supplying power to the component or not | ## Unit Tests | Name | Description | Output | Coverage | @@ -62,4 +63,4 @@ Add sequence diagrams here ## Change Log | Date | Description | |---|---| -|---| Initial Draft | \ No newline at end of file +| 10-22-2025 | Sarah, Kevin, and MoMata's first commit | \ No newline at end of file From 628fcbe5e4bbabddeb7fdafb68025c0298890e11 Mon Sep 17 00:00:00 2001 From: sarah Date: Wed, 22 Oct 2025 20:42:09 -0400 Subject: [PATCH 04/38] Sarah Kevin and MoMata fixed a bug --- FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp index de5f76a0..b6167b85 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp @@ -4,8 +4,6 @@ module Components { # One async command/port is required for active components # This should be overridden by the developers with a useful command/port - @ TODO - async command TODO opcode 0 ############################################################################## #### Uncomment the following examples to start customizing your component #### @@ -26,7 +24,7 @@ module Components { # @ Example port: receiving calls from the rate group # sync input port run: Svc.Sched - output port Status: Fw.On + output port Status: Drv.GpioRead # @ Example parameter # param PARAMETER_NAME: U32 From 91b25fe9bbbccc5929a3cc4d70defe65b15bb15a Mon Sep 17 00:00:00 2001 From: sarah Date: Wed, 22 Oct 2025 20:43:39 -0400 Subject: [PATCH 05/38] Commit farming --- .../Components/LoadSwitch/LoadSwitch.cpp | 9 +++++++-- .../Components/LoadSwitch/LoadSwitch.hpp | 17 ++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp index 7476eba7..a4c28a8d 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -1,6 +1,6 @@ // ====================================================================== // \title LoadSwitch.cpp -// \author kyang25 +// \author sarah // \brief cpp file for LoadSwitch component implementation class // ====================================================================== @@ -20,7 +20,12 @@ LoadSwitch ::~LoadSwitch() {} // Handler implementations for commands // ---------------------------------------------------------------------- -void LoadSwitch ::TODO_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { +void LoadSwitch ::TURN_ON_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { + // TODO + this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); +} + +void LoadSwitch ::TURN_OFF_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { // TODO this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); } diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp index ae2e61d4..92e5dc3d 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp @@ -1,6 +1,6 @@ // ====================================================================== // \title LoadSwitch.hpp -// \author kyang25 +// \author sarah // \brief hpp file for LoadSwitch component implementation class // ====================================================================== @@ -29,12 +29,15 @@ class LoadSwitch final : public LoadSwitchComponentBase { // Handler implementations for commands // ---------------------------------------------------------------------- - //! Handler implementation for command TODO - //! - //! TODO - void TODO_cmdHandler(FwOpcodeType opCode, //!< The opcode - U32 cmdSeq //!< The command sequence number - ) override; + //! Handler implementation for command TURN_ON + void TURN_ON_cmdHandler(FwOpcodeType opCode, //!< The opcode + U32 cmdSeq //!< The command sequence number + ) override; + + //! Handler implementation for command TURN_OFF + void TURN_OFF_cmdHandler(FwOpcodeType opCode, //!< The opcode + U32 cmdSeq //!< The command sequence number + ) override; }; } // namespace Components From 076bf65e67e655de525ade13b85b4d8a2a27f7b0 Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Wed, 22 Oct 2025 21:13:52 -0400 Subject: [PATCH 06/38] Added mcp23017 to v5 dtsi --- .../proves_flight_control_board_v5.dtsi | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 397708c7..41715c98 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -137,4 +137,20 @@ zephyr_udc0: &usbd { lsb-microamp = <100>; label = "INA219"; }; + mcp23017: mcp23017@20 { + compatible = "microchip,mcp23017"; + reg = <0x20>; + gpio-controller; + #gpio-cells = <2>; + + // GPIO line names for traceability + gpio-line-names = "FACE4_ENABLE", "FACE0_ENABLE", "FACE1_ENABLE", "FACE2_ENABLE", + "FACE3_ENABLE", "FACE5_ENABLE", "READONLY", "CHARGE", + "ENABLE_Heater", "PAYLOAD_PWR_ENABLE", "FIRE_DEPLOY2_B", "PAYLOAD_BATT_ENABLE", + "RF2_IO2", "RF2_IO1", "RF2_IO0", "RF2_IO3"; + + reset-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + + ngpios = <16>; + }; }; From 24a2e97777035706e14dd9e7eef9e49ebf97cb4b Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Thu, 23 Oct 2025 12:53:24 -0400 Subject: [PATCH 07/38] Rough initial implementation + add to topology --- .../Components/LoadSwitch/LoadSwitch.cpp | 16 ++++++++++++++-- .../Components/LoadSwitch/LoadSwitch.hpp | 11 +++++++++++ .../Top/ReferenceDeploymentPackets.fppi | 4 ++++ .../Top/ReferenceDeploymentTopology.cpp | 3 +++ .../ReferenceDeployment/Top/instances.fpp | 5 +++++ .../ReferenceDeployment/Top/topology.fpp | 2 ++ 6 files changed, 39 insertions(+), 2 deletions(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp index a4c28a8d..c8420616 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -21,13 +21,25 @@ LoadSwitch ::~LoadSwitch() {} // ---------------------------------------------------------------------- void LoadSwitch ::TURN_ON_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { - // TODO + gpio_pin_set(m_device, m_pinNum, 1); + this->log_ACTIVITY_HI_StatusChanged(Fw::On::ON); + // I think some code needed to send this status to the port as well this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); } void LoadSwitch ::TURN_OFF_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { - // TODO + gpio_pin_set(m_device, m_pinNum, 0); + this->log_ACTIVITY_HI_StatusChanged(Fw::On::OFF); + // I think some code needed to send this status to the port as well this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK); } + +// This is meant to be used in Topology.cpp to configure the pin and device +void LoadSwitch ::pin_configuration(const struct device* device, uint8_t pinNum) { + this->m_pinNum = pinNum; + this->m_device = device; + gpio_pin_configure(m_device, m_pinNum, GPIO_OUTPUT_INACTIVE); +} + } // namespace Components diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp index 92e5dc3d..585e193d 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp @@ -8,6 +8,7 @@ #define Components_LoadSwitch_HPP #include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitchComponentAc.hpp" +#include namespace Components { @@ -24,6 +25,12 @@ class LoadSwitch final : public LoadSwitchComponentBase { //! Destroy LoadSwitch object ~LoadSwitch(); + // ---------------------------------------------------------------------- + // Configuration Meant to be used in ***Topology.cpp + // ---------------------------------------------------------------------- + + void pin_configuration(const struct device* device, uint8_t pinNum); + private: // ---------------------------------------------------------------------- // Handler implementations for commands @@ -38,6 +45,10 @@ class LoadSwitch final : public LoadSwitchComponentBase { void TURN_OFF_cmdHandler(FwOpcodeType opCode, //!< The opcode U32 cmdSeq //!< The command sequence number ) override; + + uint8_t m_pinNum; + static const struct device* m_device; + }; } // namespace Components diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi index 4c2e3fc1..566f68a1 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi @@ -55,7 +55,11 @@ telemetry packets ReferenceDeploymentPackets { } + } omit { + # Needs to be added appropriately later + loadSwitch1.IsOn + CdhCore.cmdDisp.CommandErrors # Only has one library, no custom versions CdhCore.version.LibraryVersion02 diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index 21306966..156660ee 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -16,6 +16,8 @@ static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), gpios); static const struct gpio_dt_spec burnwire0Gpio = GPIO_DT_SPEC_GET(DT_NODELABEL(burnwire0), gpios); static const struct gpio_dt_spec burnwire1Gpio = GPIO_DT_SPEC_GET(DT_NODELABEL(burnwire1), gpios); +static const struct device *mcp23017_dev = DEVICE_DT_GET(DT_NODELABEL(mcp23017)); + // Allows easy reference to objects in FPP/autocoder required namespaces using namespace ReferenceDeployment; @@ -59,6 +61,7 @@ void configureTopology() { gpioDriver.open(ledGpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire0.open(burnwire0Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire1.open(burnwire1Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); + loadSwitch1.pin_configuration(mcp23017_dev, 0); // Pin 0 on MCP23017 } // Public functions for use in main program are namespaced with deployment name ReferenceDeployment diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index bdbb36a8..133cc7d3 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -35,6 +35,11 @@ module ReferenceDeployment { queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 4 + + instance loadSwitch1: Components.LoadSwitch base id 0x10003000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 # ---------------------------------------------------------------------- # Queued component instances diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 89626e35..3a25a838 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -42,6 +42,8 @@ module ReferenceDeployment { instance comSplitterTelemetry # For UART sideband communication instance comDriver + + instance loadSwitch1 # ---------------------------------------------------------------------- # Pattern graph specifiers From 3761180c517bcd262c6dd8deb908e352f62ea0b4 Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Thu, 23 Oct 2025 12:56:14 -0400 Subject: [PATCH 08/38] Ion even know any mane --- FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp index c8420616..ed53998b 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -8,6 +8,7 @@ namespace Components { +const struct device* LoadSwitch::m_device = nullptr; // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- From b9e831bfc85fd22707cc3c19b0c2442bcb2d7eb3 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Sun, 2 Nov 2025 13:05:18 -0600 Subject: [PATCH 09/38] rename to DetumbleManager --- .github/copilot-instructions.md | 63 +++++++++++++++- .../Components/CMakeLists.txt | 2 +- .../CMakeLists.txt | 10 +-- .../DetumbleManager.cpp} | 12 +-- .../DetumbleManager.fpp} | 2 +- .../DetumbleManager.hpp} | 20 ++--- .../Components/DetumbleManager/docs/sdd.md | 73 +++++++++++++++++++ .../Components/ImuManager/docs/sdd.md | 69 ------------------ .../ReferenceDeployment/Top/instances.fpp | 2 +- .../ReferenceDeployment/Top/topology.fpp | 14 ++-- 10 files changed, 166 insertions(+), 101 deletions(-) rename FprimeZephyrReference/Components/{ImuManager => DetumbleManager}/CMakeLists.txt (72%) rename FprimeZephyrReference/Components/{ImuManager/ImuManager.cpp => DetumbleManager/DetumbleManager.cpp} (67%) rename FprimeZephyrReference/Components/{ImuManager/ImuManager.fpp => DetumbleManager/DetumbleManager.fpp} (96%) rename FprimeZephyrReference/Components/{ImuManager/ImuManager.hpp => DetumbleManager/DetumbleManager.hpp} (63%) create mode 100644 FprimeZephyrReference/Components/DetumbleManager/docs/sdd.md delete mode 100644 FprimeZephyrReference/Components/ImuManager/docs/sdd.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 458d52eb..516d6c99 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,6 +1,7 @@ # Proves Core Reference Project - Copilot Instructions ## Project Overview + This is a reference software implementation for the [Proves Kit](https://docs.proveskit.space/en/latest/), combining F Prime (NASA's flight software framework) with Zephyr RTOS to create firmware for embedded flight control boards. The project targets ARM Cortex-M microcontrollers, specifically RP2350 (Raspberry Pi Pico 2) and STM32 boards. **Repository Size**: ~450MB (primarily from Zephyr workspace and F Prime submodules) @@ -11,20 +12,25 @@ This is a reference software implementation for the [Proves Kit](https://docs.pr ## Critical Build Prerequisites ### System Dependencies + Before any build steps, ensure you have: + - Python 3.13+ (specified in `.python-version`) - F Prime system requirements: https://fprime.jpl.nasa.gov/latest/docs/getting-started/installing-fprime/#system-requirements - Zephyr dependencies: https://docs.zephyrproject.org/latest/develop/getting_started/index.html#install-dependencies - **NOTE**: Only install dependencies; do NOT run Zephyr's full setup (handled by Makefile) ### Build Tool: UV Package Manager + This project uses **UV** (v0.8.13) for Python environment management. It is automatically downloaded by the Makefile. + - Do NOT use `pip` or `python -m venv` directly - Always use `make` targets which invoke UV internally ## Build & Test Workflow ### First-Time Setup (Complete Sequence) + Run these commands **in order** from the repository root. The entire setup takes ~5-10 minutes: ```bash @@ -47,6 +53,7 @@ make build **IMPORTANT**: The `make` command (default target) runs all of the above automatically. **Alternative Zephyr Setup**: The new Makefile structure provides more granular Zephyr control: + ```bash # Complete Zephyr setup (equivalent to zephyr-setup) make zephyr @@ -62,24 +69,28 @@ make zephyr-sdk # Install SDK ### Development Workflow **After making code changes**: + ```bash # Always run build (it calls generate-if-needed automatically) make build ``` **When to run generate explicitly**: + - After modifying `.fpp` files (F Prime component definitions) - After changing CMakeLists.txt files - After modifying core F Prime package files - Command: `make generate` ### Linting & Formatting + ```bash # Run all pre-commit checks (REQUIRED before committing) make fmt ``` This runs: + - `clang-format` (C/C++ formatting) - `cpplint` (C++ style checking using `cpplint.cfg`) - `ruff` (Python linting and formatting) @@ -107,6 +118,7 @@ make test-integration ``` **Test Framework Details**: + - **Location**: `FprimeZephyrReference/test/int/` - **Framework**: pytest with fprime-gds testing API - **Test Files**: @@ -117,12 +129,14 @@ make test-integration - **Communication**: Tests communicate with the board via GDS over UART **Test Prerequisites**: + 1. Board must be connected via USB (appears as CDC ACM device) 2. Firmware must be flashed and running 3. GDS must be running and connected to the board 4. Board must be in operational state (not in bootloader mode) **Test Examples**: + - **Watchdog Tests**: Start/stop watchdog, verify transition counting - **IMU Tests**: Send telemetry packets, verify acceleration data - **RTC Tests**: Set/get time, verify time synchronization @@ -130,6 +144,7 @@ make test-integration ## Project Structure ### Repository Root Files + ``` CMakeLists.txt # Top-level CMake configuration CMakePresets.json # CMake presets for Zephyr build @@ -144,13 +159,14 @@ requirements.txt # Python dependencies ``` ### Directory Structure + ``` FprimeZephyrReference/ ├── Components/ # Custom F Prime components │ ├── BootloaderTrigger/ │ ├── Drv/ # Driver components (IMU, RTC, sensor managers) │ ├── FatalHandler/ -│ ├── ImuManager/ +│ ├── DetumbleManager/ │ └── Watchdog/ ├── ReferenceDeployment/ │ ├── Main.cpp # Application entry point @@ -181,6 +197,7 @@ docs/ ### Key Architecture Points **F Prime + Zephyr Integration**: + - F Prime components defined in `.fpp` files (autocoded to C++) - Zephyr handles RTOS, drivers, and hardware abstraction - Main entry point: `FprimeZephyrReference/ReferenceDeployment/Main.cpp` @@ -191,9 +208,11 @@ docs/ ## Board Variations & Hardware Configuration ### Available Board Versions + The project supports multiple variants of the PROVES Flight Control Board, all based on the RP2350 (Raspberry Pi Pico 2) microcontroller: **Base Board (`proves_flight_control_board_v5`)**: + - Common hardware definition shared by all variants - Defines sensors: LSM6DSO (IMU), LIS2MDL (magnetometer), INA219 (current sensor) - LoRa radio: SX1276 with SPI interface @@ -202,12 +221,14 @@ The project supports multiple variants of the PROVES Flight Control Board, all b - Watchdog LED on GPIO 23 (base configuration) **Variant C (`proves_flight_control_board_v5c`)**: + - **Key Difference**: Watchdog LED moved to GPIO 24 - LoRa DIO pins: GPIO 13 and GPIO 12 (different from base) - USB Product ID: "PROVES Flight Control Board v5c" - As we develop, probably other differences will be noticed **Variant D (`proves_flight_control_board_v5d`)**: + - **Key Difference**: Uses base board configuration (LED on GPIO 23) - LoRa DIO pins: GPIO 14 and GPIO 13 (base configuration) - USB Product ID: "PROVES Flight Control Board v5d" @@ -215,12 +236,14 @@ The project supports multiple variants of the PROVES Flight Control Board, all b - **Default Board**: This is the default in `settings.ini` ### Board Selection + - **Default**: Set in `settings.ini` (`BOARD=proves_flight_control_board_v5d/rp2350a/m33`) - **Override**: Use CMake option `-DBOARD=//` - **Available SOCs**: `rp2350a` (Raspberry Pi Pico 2) - **Available Cores**: `m33` (ARM Cortex-M33) **Component Types**: + - `.fpp` files: F Prime component definitions (autocoded) - `.cpp/.hpp` files: Implementation code - `CMakeLists.txt` in each component: Build registration @@ -228,6 +251,7 @@ The project supports multiple variants of the PROVES Flight Control Board, all b ## Build System Details ### Generated Artifacts Location + ``` build-fprime-automatic-zephyr/ # F Prime + Zephyr build cache build-artifacts/ @@ -237,6 +261,7 @@ build-artifacts/ ``` ### CMake Configuration + - **Toolchain**: `lib/fprime-zephyr/cmake/toolchain/zephyr.cmake` - **Build Type**: Release - **Board Root**: Repository root (custom board definitions in `boards/`) @@ -245,6 +270,7 @@ build-artifacts/ - `FPRIME_ENABLE_AUTOCODER_UTS=OFF` (no autocoder unit tests) ### Makefile Targets Reference + ```bash make help # Show all available targets make submodules # Initialize git submodules @@ -266,6 +292,7 @@ make minimize-uv-cache # Minimize UV cache (CI optimization) ``` **Zephyr-Specific Targets** (from `lib/makelib/zephyr.mk`): + ```bash make zephyr # Complete Zephyr setup (config + workspace + export + deps + SDK) make zephyr-config # Configure west @@ -283,6 +310,7 @@ make clean-zephyr-sdk # Remove Zephyr SDK ### CI/CD Pipeline (`.github/workflows/ci.yaml`) **Jobs**: + 1. **Lint**: Runs `make fmt` (pre-commit checks) 2. **Build**: Full build with caching - Caches: bin tools, submodules, Python venv, Zephyr workspace @@ -290,6 +318,7 @@ make clean-zephyr-sdk # Remove Zephyr SDK - Uploads: `build-artifacts/zephyr.uf2` and dictionary JSON **Critical for CI Success**: + - Always run `make fmt` before pushing - Ensure code builds with `make build` locally - Integration tests are NOT run in CI (require hardware) @@ -297,29 +326,39 @@ make clean-zephyr-sdk # Remove Zephyr SDK ## Common Issues & Workarounds ### Issue: Build Fails with "west not found" + **Solution**: Run `make zephyr-setup` to install west and Zephyr SDK. ### Issue: "No such file or directory: fprime-util" + **Solution**: Run `make fprime-venv` to create virtual environment with dependencies. ### Issue: CMake cache errors after changing board configuration + **Solution**: Run `make clean` followed by `make generate build`. ### Issue: USB device not detected on board + **Workaround**: The board may need to be put into bootloader mode. Use the new bootloader target: + ```bash make bootloader ``` + This automatically detects if the board is already in bootloader mode and triggers it if needed. See board-specific guides in `docs/additional-resources/board-list.md`. ### Issue: Integration tests fail to connect + **Solution**: Ensure GDS is running (`make gds`) and board is connected. Check serial port in GDS output. ### Issue: Build times out (>2 minutes) + **Solution**: First build takes 3-5 minutes. Subsequent builds are faster (~30 seconds). Use `timeout: 300` for initial builds. ### Issue: Flashing firmware to board + **Different boards require different methods**: + - **RP2040/RP2350**: Copy `.uf2` file to board's USB mass storage ```bash cp build-artifacts/zephyr.uf2 /Volumes/RPI-RP2 # macOS @@ -334,6 +373,7 @@ This automatically detects if the board is already in bootloader mode and trigge ## File Modification Guidelines ### When modifying F Prime components: + 1. Edit `.fpp` files for interface changes (ports, commands, telemetry, events) 2. Edit `.cpp/.hpp` files for implementation 3. Run `make generate` to regenerate autocoded files @@ -346,6 +386,7 @@ This automatically detects if the board is already in bootloader mode and trigge The `ReferenceDeploymentTopology` is the central coordination point for the F Prime application: **Key Files**: + - `FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp` - Main topology implementation - `FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp` - FPP topology definition - `FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp` - Component instances @@ -359,12 +400,14 @@ static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), ``` **DT_NODE Explanation**: + - `DT_NODELABEL(led0)` - References the `led0` node from device tree - `GPIO_DT_SPEC_GET()` - Extracts GPIO specification (port, pin, flags) - Device tree defines hardware mapping: `led0: led0 { gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; }` - Board variants override these mappings (e.g., v5c uses GPIO 24, v5d uses GPIO 23) **Topology Initialization Sequence**: + 1. `initComponents()` - Initialize all F Prime components 2. `setBaseIds()` - Set component ID offsets 3. `connectComponents()` - Wire component ports together @@ -374,16 +417,19 @@ static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), 7. `startTasks()` - Start active component tasks **Hardware Integration**: + - Topology bridges F Prime components with Zephyr device drivers - Uses device tree nodes to access sensors, GPIO, UART, etc. - Board-specific configurations handled through device tree overlays ### When modifying topology: + 1. Edit `FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp` for new component instances 2. Edit `FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp` for connections 3. Run `make generate build` ### When adding new components: + 1. Create component directory under `FprimeZephyrReference/Components/` 2. Add `CMakeLists.txt` with `register_fprime_library()` or `register_fprime_module()` 3. Add component to parent `CMakeLists.txt` with `add_fprime_subdirectory()` @@ -395,24 +441,28 @@ static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), The `ReferenceDeploymentTopology` serves as the central coordinator that bridges F Prime components with Zephyr hardware drivers through Device Tree nodes. **Key Topology Files**: + - `FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp` - Main implementation - `FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp` - FPP topology definition - `FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp` - Component instances - `FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp` - Type definitions **DT_NODE Usage Pattern**: + ```cpp // Example from ReferenceDeploymentTopology.cpp static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), gpios); ``` **How DT_NODE Works**: + 1. **Device Tree Definition**: Hardware is defined in `.dts` files (e.g., `led0: led0 { gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; }`) 2. **DT_NODELABEL**: References the device tree node by label (`led0`) 3. **GPIO_DT_SPEC_GET**: Extracts GPIO specification (port, pin, flags) at compile time 4. **Board Variants**: Different boards override these mappings (v5c uses GPIO 24, v5d uses GPIO 23) **Topology Initialization Sequence**: + ```cpp void setupTopology(const TopologyState& state) { initComponents(state); // 1. Initialize F Prime components @@ -426,6 +476,7 @@ void setupTopology(const TopologyState& state) { ``` **Hardware Integration Points**: + - **GPIO Access**: `GPIO_DT_SPEC_GET(DT_NODELABEL(led0), gpios)` for LED control - **UART Communication**: Device tree defines CDC ACM UART for console/GDS - **Sensor Access**: I2C/SPI devices defined in device tree (LSM6DSO, LIS2MDL, etc.) @@ -433,12 +484,14 @@ void setupTopology(const TopologyState& state) { **Adding Hardware-Accessing Components**: When creating components that need hardware access: + 1. Define device tree nodes in board `.dts` files 2. Use `DT_NODELABEL()` and `GPIO_DT_SPEC_GET()` in component code 3. Add component to topology in `instances.fpp` and `topology.fpp` 4. Configure hardware access in `ReferenceDeploymentTopology.cpp` ### When modifying board configuration: + 1. Edit `settings.ini` to change default board 2. Or use CMake option: `cmake -DBOARD=` 3. Board definitions are in `boards/bronco_space/` @@ -447,13 +500,16 @@ When creating components that need hardware access: ## Additional Repository Information ### Build Artifacts & Outputs + - **Firmware Binary**: `build-artifacts/zephyr.uf2` (for RP2040/RP2350 boards) - **Firmware Hex**: `build-artifacts/zephyr.hex` (for STM32 boards) - **Dictionary**: `build-artifacts/zephyr/fprime-zephyr-deployment/dict/ReferenceDeploymentTopologyDictionary.json` - **Build Cache**: `build-fprime-automatic-zephyr/` (F Prime + Zephyr build directory) ### Component Architecture + The project includes several custom F Prime components: + - **Watchdog**: Hardware watchdog management with LED indication - **IMU Manager**: LSM6DSO 6-axis IMU sensor management - **LIS2MDL Manager**: 3-axis magnetometer management @@ -462,6 +518,7 @@ The project includes several custom F Prime components: - **Fatal Handler**: System error handling and recovery ### Development Environment + - **Python Version**: 3.13+ (specified in `.python-version`) - **Package Manager**: UV v0.8.13 (automatically downloaded) - **Virtual Environment**: `fprime-venv/` (created by Makefile) @@ -469,12 +526,15 @@ The project includes several custom F Prime components: - **West Workspace**: `.west/` (Zephyr workspace configuration) ### Git Submodules + The repository uses three main submodules: + - `lib/fprime/` - F Prime framework (NASA's flight software framework) - `lib/fprime-zephyr/` - F Prime-Zephyr integration layer - `lib/zephyr-workspace/` - Zephyr RTOS workspace ### Configuration Files + - `settings.ini` - F Prime project settings and default board - `prj.conf` - Zephyr project configuration (USB, I2C, SPI, sensors) - `CMakePresets.json` - CMake presets for different build configurations @@ -485,6 +545,7 @@ The repository uses three main submodules: ## Trust These Instructions These instructions are comprehensive and validated. **Only search for additional information if**: + - Instructions are incomplete for your specific task - You encounter errors not covered in "Common Issues" - You need board-specific flashing instructions (see docs/) diff --git a/FprimeZephyrReference/Components/CMakeLists.txt b/FprimeZephyrReference/Components/CMakeLists.txt index 26405d0b..10386918 100644 --- a/FprimeZephyrReference/Components/CMakeLists.txt +++ b/FprimeZephyrReference/Components/CMakeLists.txt @@ -3,7 +3,7 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Drv/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ComDelay/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FatalHandler") -add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/ImuManager/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/DetumbleManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/NullPrmDb/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Watchdog") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Burnwire/") diff --git a/FprimeZephyrReference/Components/ImuManager/CMakeLists.txt b/FprimeZephyrReference/Components/DetumbleManager/CMakeLists.txt similarity index 72% rename from FprimeZephyrReference/Components/ImuManager/CMakeLists.txt rename to FprimeZephyrReference/Components/DetumbleManager/CMakeLists.txt index 19006128..bf6c13b9 100644 --- a/FprimeZephyrReference/Components/ImuManager/CMakeLists.txt +++ b/FprimeZephyrReference/Components/DetumbleManager/CMakeLists.txt @@ -16,9 +16,9 @@ register_fprime_library( AUTOCODER_INPUTS - "${CMAKE_CURRENT_LIST_DIR}/ImuManager.fpp" + "${CMAKE_CURRENT_LIST_DIR}/DetumbleManager.fpp" SOURCES - "${CMAKE_CURRENT_LIST_DIR}/ImuManager.cpp" + "${CMAKE_CURRENT_LIST_DIR}/DetumbleManager.cpp" # DEPENDS # MyPackage_MyOtherModule ) @@ -26,10 +26,10 @@ register_fprime_library( ### Unit Tests ### # register_fprime_ut( # AUTOCODER_INPUTS -# "${CMAKE_CURRENT_LIST_DIR}/ImuManager.fpp" +# "${CMAKE_CURRENT_LIST_DIR}/DetumbleManager.fpp" # SOURCES -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ImuManagerTestMain.cpp" -# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ImuManagerTester.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/DetumbleManagerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/DetumbleManagerTester.cpp" # DEPENDS # STest # For rules-based testing # UT_AUTO_HELPERS diff --git a/FprimeZephyrReference/Components/ImuManager/ImuManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp similarity index 67% rename from FprimeZephyrReference/Components/ImuManager/ImuManager.cpp rename to FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index 24e520a7..a2e2794a 100644 --- a/FprimeZephyrReference/Components/ImuManager/ImuManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -1,9 +1,9 @@ // ====================================================================== -// \title ImuManager.cpp -// \brief cpp file for ImuManager component implementation class +// \title DetumbleManager.cpp +// \brief cpp file for DetumbleManager component implementation class // ====================================================================== -#include "FprimeZephyrReference/Components/ImuManager/ImuManager.hpp" +#include "FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp" #include @@ -13,15 +13,15 @@ namespace Components { // Component construction and destruction // ---------------------------------------------------------------------- -ImuManager ::ImuManager(const char* const compName) : ImuManagerComponentBase(compName) {} +DetumbleManager ::DetumbleManager(const char* const compName) : DetumbleManagerComponentBase(compName) {} -ImuManager ::~ImuManager() {} +DetumbleManager ::~DetumbleManager() {} // ---------------------------------------------------------------------- // Handler implementations for typed input ports // ---------------------------------------------------------------------- -void ImuManager ::run_handler(FwIndexType portNum, U32 context) { +void DetumbleManager ::run_handler(FwIndexType portNum, U32 context) { // Read from Lsm6dsoManager this->accelerationGet_out(0); this->angularVelocityGet_out(0); diff --git a/FprimeZephyrReference/Components/ImuManager/ImuManager.fpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp similarity index 96% rename from FprimeZephyrReference/Components/ImuManager/ImuManager.fpp rename to FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp index ae6973c2..131d5304 100644 --- a/FprimeZephyrReference/Components/ImuManager/ImuManager.fpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp @@ -1,6 +1,6 @@ module Components { @ IMU Manager Component for F Prime FSW framework. - passive component ImuManager { + passive component DetumbleManager { sync input port run: Svc.Sched @ Port for sending accelerationGet calls to the LSM6DSO Driver diff --git a/FprimeZephyrReference/Components/ImuManager/ImuManager.hpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp similarity index 63% rename from FprimeZephyrReference/Components/ImuManager/ImuManager.hpp rename to FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp index 14bec238..63dfb48e 100644 --- a/FprimeZephyrReference/Components/ImuManager/ImuManager.hpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp @@ -1,26 +1,26 @@ // ====================================================================== -// \title ImuManager.hpp -// \brief hpp file for ImuManager component implementation class +// \title DetumbleManager.hpp +// \brief hpp file for DetumbleManager component implementation class // ====================================================================== -#ifndef Components_ImuManager_HPP -#define Components_ImuManager_HPP +#ifndef Components_DetumbleManager_HPP +#define Components_DetumbleManager_HPP -#include "FprimeZephyrReference/Components/ImuManager/ImuManagerComponentAc.hpp" +#include "FprimeZephyrReference/Components/DetumbleManager/DetumbleManagerComponentAc.hpp" namespace Components { -class ImuManager final : public ImuManagerComponentBase { +class DetumbleManager final : public DetumbleManagerComponentBase { public: // ---------------------------------------------------------------------- // Component construction and destruction // ---------------------------------------------------------------------- - //! Construct ImuManager object - ImuManager(const char* const compName); + //! Construct DetumbleManager object + DetumbleManager(const char* const compName); - //! Destroy ImuManager object - ~ImuManager(); + //! Destroy DetumbleManager object + ~DetumbleManager(); private: // ---------------------------------------------------------------------- diff --git a/FprimeZephyrReference/Components/DetumbleManager/docs/sdd.md b/FprimeZephyrReference/Components/DetumbleManager/docs/sdd.md new file mode 100644 index 00000000..56d94e4a --- /dev/null +++ b/FprimeZephyrReference/Components/DetumbleManager/docs/sdd.md @@ -0,0 +1,73 @@ +# Components::DetumbleManager + +The IMU Manager (Inertial Measurement Unit) component provides sensor data related to motion and orientation of the craft. It interfaces with two drivers: the LIS2MDL Manager and the LSM6DSO Driver which provide acceleration, angular velocity, magnetic field, and temperature measurements. + +## Usage Examples + +The IMU Manager component is designed to be scheduled periodically to trigger collection of sensor data and telemetering. It operates as a passive component that responds to scheduler calls. + +### Typical Usage + +1. The component is instantiated and initialized during system startup +2. The scheduler calls the `run` port at regular intervals +3. On each run call, the component: + - Fetches sensor data from both the LIS2MDL Manager and LSM6DSO Driver + - Outputs telemetry for acceleration, angular velocity, magnetic field, and temperature + +## Class Diagram + +```mermaid +classDiagram + namespace Components { + class DetumbleManagerComponentBase { + <> + } + class DetumbleManager { + + DetumbleManager(const char* compName) + + ~DetumbleManager() + - run_handler(FwIndexType portNum, U32 context): void + } + } + DetumbleManagerComponentBase <|-- DetumbleManager : inherits +``` + +## Port Descriptions + +| Name | Type | Description | +| ------------------ | ---------- | ---------------------------------------------------------- | +| run | sync input | Scheduler port that triggers sensor data collection | +| accelerationGet | output | Port for calling accelerationGet on the LSM6DSO Manager | +| angularVelocityGet | output | Port for calling angularVelocityGet on the LSM6DSO Manager | +| magneticFieldGet | output | Port for calling magneticFieldGet on the LIS2MDL Manager | +| temperatureGet | output | Port for calling temperatureGet on the LSM6DSO Manager | +| timeCaller | time get | Port for requesting current system time | + +## Sequence Diagrams + +```mermaid +sequenceDiagram + participant Scheduler + participant IMU Manager + participant LIS2MDL Manager + participant LSM6DSO Manager + + Scheduler-->>IMU Manager: run + IMU Manager->>LSM6DSO Manager: AccelerationGet + IMU Manager->>LSM6DSO Manager: AngularVelocityGet + IMU Manager->>LSM6DSO Manager: TemperatureGet + IMU Manager->>LIS2MDL Manager: MagneticFieldGet +``` + +## Requirements + +| Name | Description | Validation | +| ---------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | +| Sensor Data Collection | The component shall trigger data collection from both LSM6DSO and LIS2MDL sensors when run is called | Verify all sensor manager output ports are called | +| Periodic Operation | The component shall operate as a scheduled component responding to scheduler calls | Verify component responds correctly to scheduler input | + +## Change Log + +| Date | Description | +| --------- | --------------------------------------------------------------------- | +| 2025-9-9 | Initial IMU Manager component | +| 2025-9-18 | Extracted Zephyr calls to discrete LIS2MDL Manager and LSM6DSO Driver | diff --git a/FprimeZephyrReference/Components/ImuManager/docs/sdd.md b/FprimeZephyrReference/Components/ImuManager/docs/sdd.md deleted file mode 100644 index db12b255..00000000 --- a/FprimeZephyrReference/Components/ImuManager/docs/sdd.md +++ /dev/null @@ -1,69 +0,0 @@ -# Components::ImuManager - -The IMU Manager (Inertial Measurement Unit) component provides sensor data related to motion and orientation of the craft. It interfaces with two drivers: the LIS2MDL Manager and the LSM6DSO Driver which provide acceleration, angular velocity, magnetic field, and temperature measurements. - -## Usage Examples - -The IMU Manager component is designed to be scheduled periodically to trigger collection of sensor data and telemetering. It operates as a passive component that responds to scheduler calls. - -### Typical Usage - -1. The component is instantiated and initialized during system startup -2. The scheduler calls the `run` port at regular intervals -3. On each run call, the component: - - Fetches sensor data from both the LIS2MDL Manager and LSM6DSO Driver - - Outputs telemetry for acceleration, angular velocity, magnetic field, and temperature - -## Class Diagram - -```mermaid -classDiagram - namespace Components { - class ImuManagerComponentBase { - <> - } - class ImuManager { - + ImuManager(const char* compName) - + ~ImuManager() - - run_handler(FwIndexType portNum, U32 context): void - } - } - ImuManagerComponentBase <|-- ImuManager : inherits -``` - -## Port Descriptions -| Name | Type | Description | -|---|---|---| -| run | sync input | Scheduler port that triggers sensor data collection | -| accelerationGet | output | Port for calling accelerationGet on the LSM6DSO Manager | -| angularVelocityGet | output | Port for calling angularVelocityGet on the LSM6DSO Manager | -| magneticFieldGet | output | Port for calling magneticFieldGet on the LIS2MDL Manager | -| temperatureGet | output | Port for calling temperatureGet on the LSM6DSO Manager | -| timeCaller | time get | Port for requesting current system time | - -## Sequence Diagrams -```mermaid -sequenceDiagram - participant Scheduler - participant IMU Manager - participant LIS2MDL Manager - participant LSM6DSO Manager - - Scheduler-->>IMU Manager: run - IMU Manager->>LSM6DSO Manager: AccelerationGet - IMU Manager->>LSM6DSO Manager: AngularVelocityGet - IMU Manager->>LSM6DSO Manager: TemperatureGet - IMU Manager->>LIS2MDL Manager: MagneticFieldGet -``` - -## Requirements -| Name | Description | Validation | -|---|---|---| -| Sensor Data Collection | The component shall trigger data collection from both LSM6DSO and LIS2MDL sensors when run is called | Verify all sensor manager output ports are called | -| Periodic Operation | The component shall operate as a scheduled component responding to scheduler calls | Verify component responds correctly to scheduler input | - -## Change Log -| Date | Description | -|---|---| -| 2025-9-9 | Initial IMU Manager component | -| 2025-9-18 | Extracted Zephyr calls to discrete LIS2MDL Manager and LSM6DSO Driver | diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 26eebbf7..242bde3b 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -64,7 +64,7 @@ module ReferenceDeployment { instance rtcManager: Drv.RtcManager base id 0x10016000 - instance imuManager: Components.ImuManager base id 0x10017000 + instance DetumbleManager: Components.DetumbleManager base id 0x10017000 instance lis2mdlManager: Drv.Lis2mdlManager base id 0x10018000 diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index ec3bcfb5..a0afeeff 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -32,7 +32,7 @@ module ReferenceDeployment { instance watchdog instance prmDb instance rtcManager - instance imuManager + instance DetumbleManager instance lis2mdlManager instance lsm6dsoManager instance bootloaderTrigger @@ -132,7 +132,7 @@ module ReferenceDeployment { rateGroup1Hz.RateGroupMemberOut[2] -> ComCcsds.commsBufferManager.schedIn rateGroup1Hz.RateGroupMemberOut[3] -> CdhCore.tlmSend.Run rateGroup1Hz.RateGroupMemberOut[4] -> watchdog.run - rateGroup1Hz.RateGroupMemberOut[5] -> imuManager.run + rateGroup1Hz.RateGroupMemberOut[5] -> DetumbleManager.run rateGroup1Hz.RateGroupMemberOut[6] -> comDelay.run rateGroup1Hz.RateGroupMemberOut[7] -> burnwire.schedIn rateGroup1Hz.RateGroupMemberOut[8] -> antennaDeployer.schedIn @@ -155,11 +155,11 @@ module ReferenceDeployment { antennaDeployer.burnStop -> burnwire.burnStop } - connections imuManager { - imuManager.accelerationGet -> lsm6dsoManager.accelerationGet - imuManager.angularVelocityGet -> lsm6dsoManager.angularVelocityGet - imuManager.magneticFieldGet -> lis2mdlManager.magneticFieldGet - imuManager.temperatureGet -> lsm6dsoManager.temperatureGet + connections DetumbleManager { + DetumbleManager.accelerationGet -> lsm6dsoManager.accelerationGet + DetumbleManager.angularVelocityGet -> lsm6dsoManager.angularVelocityGet + DetumbleManager.magneticFieldGet -> lis2mdlManager.magneticFieldGet + DetumbleManager.temperatureGet -> lsm6dsoManager.temperatureGet } } } From 674ef1820df3fb8ceabc9b60303f1f365760d140 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 13:44:02 -0600 Subject: [PATCH 10/38] add bdotdetumble component --- .../Drv/BDotDetumble/BDotDetumble.cpp | 69 +++++++++++++++++++ .../Drv/BDotDetumble/BDotDetumble.fpp | 35 ++++++++++ .../Drv/BDotDetumble/BDotDetumble.hpp | 42 +++++++++++ .../Drv/BDotDetumble/CMakeLists.txt | 36 ++++++++++ .../Components/Drv/BDotDetumble/docs/sdd.md | 66 ++++++++++++++++++ .../Components/Drv/CMakeLists.txt | 1 + 6 files changed, 249 insertions(+) create mode 100644 FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp create mode 100644 FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp create mode 100644 FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp create mode 100644 FprimeZephyrReference/Components/Drv/BDotDetumble/CMakeLists.txt create mode 100644 FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp new file mode 100644 index 00000000..d5c1a5a3 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp @@ -0,0 +1,69 @@ +// ====================================================================== +// \title BDotDetumble.cpp +// \author aychar +// \brief cpp file for BDotDetumble component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp" + +#include + +namespace Drv { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +BDotDetumble ::BDotDetumble(const char* const compName) : BDotDetumbleComponentBase(compName) {} + +BDotDetumble ::~BDotDetumble() {} + +Drv::DipoleMoment dipoleMomentGet_handler(const FwIndexType portNum, + const Drv::MagneticField currMagField, + const Drv::MagneticField prevMagField) { + F32 magnitude = getMagnitude(currMagField); + if (magnitude < 1e-6) { + return; // Figure out how I should handle the return here. + } + + if (currMagField.timestamp <= prevMagField.timestamp) { + return; // Also figure out the return here. + } + + F64* dB_dtArr = dB_dt(currMagField, prevMagField); + if (dB_dtArr == nullptr) { + return; // Yeah just figure out how to properly raise error/return nothing. + } + + F64 moment_x = this->gain * dB_dtArr[0] / magnitude; + F64 moment_y = this->gain * dB_dtArr[1] / magnitude; + F64 moment_z = this->gain * dB_dtArr[2] / magnitude; + + delete[] dB_dtArr; + + return Drv::DipoleMoment(moment_x, moment_y, moment_z); +} + +F32 getMagnitude(const Drv::MagneticField magField) { + return sqrt(f64_square(magField.x) + f64_square(magField.y) + f64_square(magField.z)); +} + +F64* dB_dt(const Drv::MagneticField currMagField, const Drv::MagneticField prevMagField) { + I64 dt = currMagField.timestamp - prevMagField.timestamp; + if (dt < 1e-6) { + return nullptr; + } + + F64 dBx_dt = (currMagField.x - prevMagField.x) / dt; + F64 dBy_dt = (currMagField.y - prevMagField.y) / dt; + F64 dBz_dt = (currMagField.z - prevMagField.z) / dt; + + F64* arr = new F64[3]; + arr[0] = dBx_dt; + arr[1] = dBy_dt; + arr[2] = dBz_dt; + + return arr; +} + +} // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp new file mode 100644 index 00000000..fe0086e0 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp @@ -0,0 +1,35 @@ +module Drv { + port DipoleMomentGet -> DipoleMoment +} + +module Drv { + @ Component for F Prime FSW framework. + passive component BDotDetumble { + + sync input port dipoleMomentGet: DipoleMomentGet + + telemetry DipoleMoment: DipoleMoment + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + } +} diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp new file mode 100644 index 00000000..2c1f5a1f --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp @@ -0,0 +1,42 @@ +// ====================================================================== +// \title BDotDetumble.hpp +// \author aychar +// \brief hpp file for BDotDetumble component implementation class +// ====================================================================== + +#ifndef Drv_BDotDetumble_HPP +#define Drv_BDotDetumble_HPP + +#include "FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumbleComponentAc.hpp" +#include "FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp" + +namespace Drv { + +class BDotDetumble final : public BDotDetumbleComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct BDotDetumble object + BDotDetumble(const char* const compName //!< The component name + ); + + //! Destroy BDotDetumble object + ~BDotDetumble(); + + // Get the current dipole moment + Drv::DipoleMoment dipoleMomentGet_handler(const FwIndexType portNum) override; + + private: + F64 gain = 1.0; + + // Get magnitude + F32 getMagnitude(const Drv::MagneticField magField); + + // Get the time derivative of the magnetic field + F64* dB_dt(const Drv::MagneticField currMagField, const Drv::MagneticField prevMagField); + +} // namespace Drv + +#endif diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/CMakeLists.txt b/FprimeZephyrReference/Components/Drv/BDotDetumble/CMakeLists.txt new file mode 100644 index 00000000..fe05923c --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/BDotDetumble.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/BDotDetumble.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/BDotDetumble.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/BDotDetumbleTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/BDotDetumbleTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md b/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md new file mode 100644 index 00000000..093f1cae --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md @@ -0,0 +1,66 @@ +# Drv::BDotDetumble + +Component for F Prime FSW framework. + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/FprimeZephyrReference/Components/Drv/CMakeLists.txt b/FprimeZephyrReference/Components/Drv/CMakeLists.txt index 69454247..a3a1a4f1 100644 --- a/FprimeZephyrReference/Components/Drv/CMakeLists.txt +++ b/FprimeZephyrReference/Components/Drv/CMakeLists.txt @@ -3,3 +3,4 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lis2mdlManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lsm6dsoManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/RtcManager") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/BDotDetumble/") From e7d0f6b9710b62e9d6fa3b0088710839c162f14a Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 13:44:14 -0600 Subject: [PATCH 11/38] add f64_square helper function --- FprimeZephyrReference/Components/Drv/Helpers/Helpers.cpp | 4 ++++ FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/FprimeZephyrReference/Components/Drv/Helpers/Helpers.cpp b/FprimeZephyrReference/Components/Drv/Helpers/Helpers.cpp index fac9e1f0..210d58c4 100644 --- a/FprimeZephyrReference/Components/Drv/Helpers/Helpers.cpp +++ b/FprimeZephyrReference/Components/Drv/Helpers/Helpers.cpp @@ -13,4 +13,8 @@ F64 sensor_value_to_f64(const struct sensor_value& val) { return val.val1 + (val.val2 / 1000000.0f); } +F64 f64_square(float num) { + return num * num; +} + } // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp b/FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp index 02c9325d..a478465f 100644 --- a/FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp +++ b/FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp @@ -14,6 +14,9 @@ namespace Drv { //! Convert a Zephyr sensor_value to an Fprime F64 F64 sensor_value_to_f64(const struct sensor_value& val); +//! Square a float +F64 f64_square(float num); + } // namespace Drv #endif From b012930e88f1070b520f5fdb19c13b677fd0e27c Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 13:44:47 -0600 Subject: [PATCH 12/38] add timestamp to MagneticField for dipole moment calculation --- .../Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp | 5 +++-- FprimeZephyrReference/Components/Drv/Types/Types.fpp | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp index e0b133f5..6bad5d23 100644 --- a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp +++ b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp @@ -5,6 +5,7 @@ #include "FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.hpp" +#include #include namespace Drv { @@ -40,8 +41,8 @@ Drv::MagneticField Lis2mdlManager ::magneticFieldGet_handler(FwIndexType portNum sensor_channel_get(dev, SENSOR_CHAN_MAGN_Y, &y); sensor_channel_get(dev, SENSOR_CHAN_MAGN_Z, &z); - Drv::MagneticField magnetic_readings = - Drv::MagneticField(Drv::sensor_value_to_f64(x), Drv::sensor_value_to_f64(y), Drv::sensor_value_to_f64(z)); + Drv::MagneticField magnetic_readings = Drv::MagneticField(Drv::sensor_value_to_f64(x), Drv::sensor_value_to_f64(y), + Drv::sensor_value_to_f64(z), k_uptime_get()); this->tlmWrite_MagneticField(magnetic_readings); diff --git a/FprimeZephyrReference/Components/Drv/Types/Types.fpp b/FprimeZephyrReference/Components/Drv/Types/Types.fpp index e129beea..f6bdf4e8 100644 --- a/FprimeZephyrReference/Components/Drv/Types/Types.fpp +++ b/FprimeZephyrReference/Components/Drv/Types/Types.fpp @@ -19,5 +19,12 @@ module Drv { x: F64 @< Magnetic field in gauss in the X direction. y: F64 @< Magnetic field in gauss in the Y direction. z: F64 @< Magnetic field in gauss in the Z direction. + timestamp: I64 @< Time the magnetic field struct was created. Used for dB_dt calculation. + } + + struct DipoleMoment { + x: F64 + y: F64 + z: F64 } } From 2a35c646f40977d8045e26ac43cb3c60e1ae69d2 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 15:30:55 -0600 Subject: [PATCH 13/38] Implemented BDotDetumble --- .../DetumbleManager/DetumbleManager.cpp | 14 ++++++++ .../DetumbleManager/DetumbleManager.hpp | 7 ++++ .../Drv/BDotDetumble/BDotDetumble.cpp | 32 +++++++++---------- .../Drv/BDotDetumble/BDotDetumble.fpp | 5 ++- .../Drv/BDotDetumble/BDotDetumble.hpp | 11 ++++--- .../Drv/Lis2mdlManager/Lis2mdlManager.cpp | 2 +- .../Components/Drv/Types/Types.fpp | 1 + 7 files changed, 49 insertions(+), 23 deletions(-) diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index a2e2794a..3b13c7e3 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -30,4 +30,18 @@ void DetumbleManager ::run_handler(FwIndexType portNum, U32 context) { // Read from Lis2mdlManager this->magneticFieldGet_out(0); } + +bool DetumbleManager::executeControlStep() { + Drv::MagneticField mgField = this->magneticFieldGet_out(0); + if (this->prevMgField == this->EMPTY_MG_FIELD) { + this->prevMgField = mgField; + } + + Drv::DipoleMoment dpMoment = this->dipoleMomentGet_handler(0, mgField, this->prevMgField); + // Then check if its null/empty whatever here, need to figure that out. + this->prevMgField = mgField; + + // Then apply the dipole moment here, gonna have to figure that out. + return true; +} } // namespace Components diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp index 63dfb48e..82d99f1a 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp @@ -31,6 +31,13 @@ class DetumbleManager final : public DetumbleManagerComponentBase { void run_handler(FwIndexType portNum, //!< The port number U32 context //!< The call order ) override; + + // Variables + Drv::MagneticField EMPTY_MG_FIELD = Drv::MagneticField{0.0, 0.0, 0.0}; + Drv::MagneticField prevMgField = Drv::MagneticField{0.0, 0.0, 0.0}; + + // Functions + bool executeControlStep(); }; } // namespace Components diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp index d5c1a5a3..c7148925 100644 --- a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp @@ -18,21 +18,21 @@ BDotDetumble ::BDotDetumble(const char* const compName) : BDotDetumbleComponentB BDotDetumble ::~BDotDetumble() {} -Drv::DipoleMoment dipoleMomentGet_handler(const FwIndexType portNum, - const Drv::MagneticField currMagField, - const Drv::MagneticField prevMagField) { - F32 magnitude = getMagnitude(currMagField); +Drv::DipoleMoment BDotDetumble::dipoleMomentGet_handler(const FwIndexType portNum, + const Drv::MagneticField& currMagField, + const Drv::MagneticField& prevMagField) { + F64 magnitude = this->getMagnitude(currMagField); if (magnitude < 1e-6) { - return; // Figure out how I should handle the return here. + return Drv::DipoleMoment(); } - if (currMagField.timestamp <= prevMagField.timestamp) { - return; // Also figure out the return here. + if (currMagField.get_timestamp() <= prevMagField.get_timestamp()) { + return Drv::DipoleMoment(); } - F64* dB_dtArr = dB_dt(currMagField, prevMagField); + F64* dB_dtArr = this->dB_dt(currMagField, prevMagField); if (dB_dtArr == nullptr) { - return; // Yeah just figure out how to properly raise error/return nothing. + return Drv::DipoleMoment(); } F64 moment_x = this->gain * dB_dtArr[0] / magnitude; @@ -44,19 +44,19 @@ Drv::DipoleMoment dipoleMomentGet_handler(const FwIndexType portNum, return Drv::DipoleMoment(moment_x, moment_y, moment_z); } -F32 getMagnitude(const Drv::MagneticField magField) { - return sqrt(f64_square(magField.x) + f64_square(magField.y) + f64_square(magField.z)); +F64 BDotDetumble::getMagnitude(const Drv::MagneticField magField) { + return sqrt(f64_square(magField.get_x()) + f64_square(magField.get_y()) + f64_square(magField.get_z())); } -F64* dB_dt(const Drv::MagneticField currMagField, const Drv::MagneticField prevMagField) { - I64 dt = currMagField.timestamp - prevMagField.timestamp; +F64* BDotDetumble::dB_dt(const Drv::MagneticField currMagField, const Drv::MagneticField prevMagField) { + I64 dt = currMagField.get_timestamp() - prevMagField.get_timestamp(); if (dt < 1e-6) { return nullptr; } - F64 dBx_dt = (currMagField.x - prevMagField.x) / dt; - F64 dBy_dt = (currMagField.y - prevMagField.y) / dt; - F64 dBz_dt = (currMagField.z - prevMagField.z) / dt; + F64 dBx_dt = (currMagField.get_x() - prevMagField.get_x()) / dt; + F64 dBy_dt = (currMagField.get_y() - prevMagField.get_y()) / dt; + F64 dBz_dt = (currMagField.get_z() - prevMagField.get_z()) / dt; F64* arr = new F64[3]; arr[0] = dBx_dt; diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp index fe0086e0..275bca0f 100644 --- a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.fpp @@ -1,5 +1,8 @@ module Drv { - port DipoleMomentGet -> DipoleMoment + port DipoleMomentGet( + currMagField: MagneticField + prevMagField: MagneticField + ) -> DipoleMoment } module Drv { diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp index 2c1f5a1f..c9a6c1f3 100644 --- a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp @@ -26,17 +26,18 @@ class BDotDetumble final : public BDotDetumbleComponentBase { ~BDotDetumble(); // Get the current dipole moment - Drv::DipoleMoment dipoleMomentGet_handler(const FwIndexType portNum) override; + Drv::DipoleMoment dipoleMomentGet_handler(const FwIndexType portNum, + const Drv::MagneticField& currMagField, + const Drv::MagneticField& prevMagField) override; private: F64 gain = 1.0; // Get magnitude - F32 getMagnitude(const Drv::MagneticField magField); + F64 getMagnitude(Drv::MagneticField magField); // Get the time derivative of the magnetic field - F64* dB_dt(const Drv::MagneticField currMagField, const Drv::MagneticField prevMagField); - + F64* dB_dt(Drv::MagneticField currMagField, Drv::MagneticField prevMagField); +}; } // namespace Drv - #endif diff --git a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp index 6bad5d23..1cc62df8 100644 --- a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp +++ b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp @@ -27,7 +27,7 @@ Lis2mdlManager ::~Lis2mdlManager() {} Drv::MagneticField Lis2mdlManager ::magneticFieldGet_handler(FwIndexType portNum) { if (!device_is_ready(dev)) { this->log_WARNING_HI_DeviceNotReady(); - return Drv::MagneticField(0.0, 0.0, 0.0); + return Drv::MagneticField(0.0, 0.0, 0.0, k_uptime_get()); } this->log_WARNING_HI_DeviceNotReady_ThrottleClear(); diff --git a/FprimeZephyrReference/Components/Drv/Types/Types.fpp b/FprimeZephyrReference/Components/Drv/Types/Types.fpp index f6bdf4e8..bb032758 100644 --- a/FprimeZephyrReference/Components/Drv/Types/Types.fpp +++ b/FprimeZephyrReference/Components/Drv/Types/Types.fpp @@ -22,6 +22,7 @@ module Drv { timestamp: I64 @< Time the magnetic field struct was created. Used for dB_dt calculation. } + @ Calculated dipole moment from the B-Dot algorithm. struct DipoleMoment { x: F64 y: F64 From 2e459444e406c5db4d31657fef02d7d8977f1586 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 16:19:59 -0600 Subject: [PATCH 14/38] few fixes --- .../Components/DetumbleManager/DetumbleManager.cpp | 8 ++++++-- .../Components/DetumbleManager/DetumbleManager.fpp | 5 ++++- .../Components/DetumbleManager/DetumbleManager.hpp | 6 ++++-- .../Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index 3b13c7e3..55a71f51 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -37,8 +37,12 @@ bool DetumbleManager::executeControlStep() { this->prevMgField = mgField; } - Drv::DipoleMoment dpMoment = this->dipoleMomentGet_handler(0, mgField, this->prevMgField); - // Then check if its null/empty whatever here, need to figure that out. + Drv::DipoleMoment dpMoment = this->dipoleMomentGet_out(0, mgField, this->prevMgField); + if (dpMoment == this->EMPTY_DP_MOMENT) { + // Log some kinda error + return false; + } + this->prevMgField = mgField; // Then apply the dipole moment here, gonna have to figure that out. diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp index 131d5304..04cbcce7 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp @@ -1,5 +1,5 @@ module Components { - @ IMU Manager Component for F Prime FSW framework. + @ Detumble Manager Component for F Prime FSW framework. passive component DetumbleManager { sync input port run: Svc.Sched @@ -15,6 +15,9 @@ module Components { @ Port for sending temperatureGet calls to the LSM6DSO Driver output port temperatureGet: Drv.TemperatureGet + @ Port for sending dipoleMomentGet calls to the BDotDetumble Component + output port dipoleMomentGet: Drv.DipoleMomentGet + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp index 82d99f1a..d3b37403 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp @@ -33,8 +33,10 @@ class DetumbleManager final : public DetumbleManagerComponentBase { ) override; // Variables - Drv::MagneticField EMPTY_MG_FIELD = Drv::MagneticField{0.0, 0.0, 0.0}; - Drv::MagneticField prevMgField = Drv::MagneticField{0.0, 0.0, 0.0}; + Drv::MagneticField EMPTY_MG_FIELD = Drv::MagneticField(0.0, 0.0, 0.0, -1); + Drv::MagneticField prevMgField = Drv::MagneticField(0.0, 0.0, 0.0, -1); + + Drv::DipoleMoment EMPTY_DP_MOMENT = Drv::DipoleMoment(0.0, 0.0, 0.0); // Functions bool executeControlStep(); diff --git a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp index 1cc62df8..551f579e 100644 --- a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp +++ b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp @@ -27,7 +27,7 @@ Lis2mdlManager ::~Lis2mdlManager() {} Drv::MagneticField Lis2mdlManager ::magneticFieldGet_handler(FwIndexType portNum) { if (!device_is_ready(dev)) { this->log_WARNING_HI_DeviceNotReady(); - return Drv::MagneticField(0.0, 0.0, 0.0, k_uptime_get()); + return Drv::MagneticField(0.0, 0.0, 0.0, -1); } this->log_WARNING_HI_DeviceNotReady_ThrottleClear(); From 3fec032d319372e918a1503ac7a6403e61a6ff75 Mon Sep 17 00:00:00 2001 From: Michael Pham <61564344+Mikefly123@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:25:28 -0800 Subject: [PATCH 15/38] Working Device Tree (But F Prime Crash) --- .../Components/LoadSwitch/LoadSwitch.cpp | 1 + .../Components/LoadSwitch/LoadSwitch.hpp | 4 +- .../proves_flight_control_board_v5.dtsi | 112 +++++++++++++++++- 3 files changed, 115 insertions(+), 2 deletions(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp index 351e2ea5..e92b1aea 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -5,6 +5,7 @@ // ====================================================================== #include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp" +#include namespace Components { diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp index bb4288b3..12d79c01 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp @@ -7,9 +7,11 @@ #ifndef Components_LoadSwitch_HPP #define Components_LoadSwitch_HPP -#include #include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitchComponentAc.hpp" +// Forward declare Zephyr types to avoid header conflicts +struct device; + namespace Components { class LoadSwitch final : public LoadSwitchComponentBase { diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 4aa68723..d4db1c0d 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -178,8 +178,118 @@ zephyr_udc0: &usbd { "ENABLE_Heater", "PAYLOAD_PWR_ENABLE", "FIRE_DEPLOY2_B", "PAYLOAD_BATT_ENABLE", "RF2_IO2", "RF2_IO1", "RF2_IO0", "RF2_IO3"; - reset-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + reset-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; ngpios = <16>; }; }; + +// GPIO Expander IO +/ { + + // Define the GPIO outputs based on your schematic + gpio_outputs { + compatible = "gpio-leds"; // Using gpio-leds as a convenient container + + face4_enable: face4-enable { + + gpios = <&mcp23017 8 GPIO_ACTIVE_HIGH>; // GPB0 + label = "FACE4_ENABLE"; + }; + + face0_enable: face0-enable { + + gpios = <&mcp23017 9 GPIO_ACTIVE_HIGH>; // GPB1 + label = "FACE0_ENABLE"; + }; + + face1_enable: face1-enable { + + gpios = <&mcp23017 10 GPIO_ACTIVE_HIGH>; // GPB2 + label = "FACE1_ENABLE"; + }; + + face2_enable: face2-enable { + + gpios = <&mcp23017 11 GPIO_ACTIVE_HIGH>; // GPB3 + label = "FACE2_ENABLE"; + }; + + face3_enable: face3-enable { + + gpios = <&mcp23017 12 GPIO_ACTIVE_HIGH>; // GPB4 + label = "FACE3_ENABLE"; + }; + + face5_enable: face5-enable { + + gpios = <&mcp23017 13 GPIO_ACTIVE_HIGH>; // GPB5 + label = "FACE5_ENABLE"; + }; + + enable_heater: enable-heater { + + gpios = <&mcp23017 0 GPIO_ACTIVE_HIGH>; // GPA0 + label = "ENABLE_Heater"; + }; + + payload_pwr_enable: payload-pwr-enable { + + gpios = <&mcp23017 1 GPIO_ACTIVE_HIGH>; // GPA1 + label = "PAYLOAD_PWR_ENABLE"; + }; + + fire_deploy2_b: fire-deploy2-b { + + gpios = <&mcp23017 2 GPIO_ACTIVE_HIGH>; // GPA2 + label = "FIRE_DEPLOY2_B"; + }; + + payload_batt_enable: payload-batt-enable { + + gpios = <&mcp23017 3 GPIO_ACTIVE_HIGH>; // GPA3 + label = "PAYLOAD_BATT_ENABLE"; + }; + }; + + // Define GPIO inputs + gpio_inputs { + compatible = "gpio-keys"; + + charge: charge { + + gpios = <&mcp23017 16 GPIO_ACTIVE_HIGH>; // GPB7 + label = "CHARGE"; + }; + + readonly: readonly { + + gpios = <&mcp23017 15 GPIO_ACTIVE_HIGH>; // GPB6 + label = "READONLY"; + }; + + rf2_io2: rf2-io2 { + + gpios = <&mcp23017 4 GPIO_ACTIVE_HIGH>; // GPA4 + label = "RF2_IO2"; + }; + + rf2_io1: rf2-io1 { + + gpios = <&mcp23017 5 GPIO_ACTIVE_HIGH>; // GPA5 + label = "RF2_IO1"; + }; + + rf2_io0: rf2-io0 { + + gpios = <&mcp23017 6 GPIO_ACTIVE_HIGH>; // GPA6 + label = "RF2_IO0"; + }; + + rf2_io3: rf2-io3 { + + gpios = <&mcp23017 7 GPIO_ACTIVE_HIGH>; // GPA7 + label = "RF2_IO3"; + }; + }; +}; From 09c61fdc4284ec3690e3e7b4dddcc035de2f93fa Mon Sep 17 00:00:00 2001 From: Michael Pham <61564344+Mikefly123@users.noreply.github.com> Date: Mon, 3 Nov 2025 14:33:58 -0800 Subject: [PATCH 16/38] Update CommandDispatcherImplCfg.hpp Fixed the Crashes! --- .../project/config/CommandDispatcherImplCfg.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp b/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp index ab88a46b..350367d4 100644 --- a/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp +++ b/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp @@ -11,7 +11,7 @@ // Define configuration values for dispatcher enum { - CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 50, // !< The size of the table holding opcodes to dispatch + CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 100, // !< The size of the table holding opcodes to dispatch CMD_DISPATCHER_SEQUENCER_TABLE_SIZE = 10, // !< The size of the table holding commands in progress }; From 59fcadb101b83dc8f1f6db9f827cfce3a4850288 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 17:49:36 -0600 Subject: [PATCH 17/38] add setDipoleMoment function --- .../DetumbleManager/DetumbleManager.cpp | 23 +++++++++++++++++ .../DetumbleManager/DetumbleManager.hpp | 25 ++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index 55a71f51..745b2061 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -7,6 +7,9 @@ #include +#include +#include + namespace Components { // ---------------------------------------------------------------------- @@ -48,4 +51,24 @@ bool DetumbleManager::executeControlStep() { // Then apply the dipole moment here, gonna have to figure that out. return true; } +void DetumbleManager::setDipoleMoment(Drv::DipoleMoment dpMoment) { + // Convert dipole moment to (unlimited) current + F64 unlimited_x = dpMoment.get_x() / (this->COIL_NUM_TURNS_X_Y * this->COIL_AREA_X_Y); + F64 unlimited_y = dpMoment.get_y() / (this->COIL_NUM_TURNS_X_Y * this->COIL_AREA_X_Y); + F64 unlimited_z = dpMoment.get_z() / (this->COIL_NUM_TURNS_Z * this->COIL_AREA_Z); + + // Limit current for each axis to max coil current + F64 limited_x = std::min(std::fabs(unlimited_x), this->COIL_MAX_CURRENT_X_Y) * (unlimited_x >= 0 ? 1.0f : -1.0f); + F64 limited_y = std::min(std::fabs(unlimited_y), this->COIL_MAX_CURRENT_X_Y) * (unlimited_y >= 0 ? 1.0f : -1.0f); + F64 limited_z = std::min(std::fabs(unlimited_z), this->COIL_MAX_CURRENT_Z) * (unlimited_z >= 0 ? 1.0f : -1.0f); + + F64 x1 = limited_x; + F64 x2 = -limited_x; + F64 y1 = limited_y; + F64 y2 = -limited_y; + F64 z1 = limited_z; + + // Apply values to magnetorquers here +} + } // namespace Components diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp index d3b37403..bc1484ee 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp @@ -8,6 +8,8 @@ #include "FprimeZephyrReference/Components/DetumbleManager/DetumbleManagerComponentAc.hpp" +#include + namespace Components { class DetumbleManager final : public DetumbleManagerComponentBase { @@ -32,14 +34,31 @@ class DetumbleManager final : public DetumbleManagerComponentBase { U32 context //!< The call order ) override; - // Variables + // Constants Drv::MagneticField EMPTY_MG_FIELD = Drv::MagneticField(0.0, 0.0, 0.0, -1); - Drv::MagneticField prevMgField = Drv::MagneticField(0.0, 0.0, 0.0, -1); - Drv::DipoleMoment EMPTY_DP_MOMENT = Drv::DipoleMoment(0.0, 0.0, 0.0); + const double PI = 3.14159265358979323846; + + // Proves V3 Magnetorquer Information + F64 COIL_VOLTAGE = 3.3; + F64 COIL_NUM_TURNS_X_Y = 48; + F64 COIL_LENGTH_X_Y = 0.053; + F64 COIL_WIDTH_X_Y = 0.045; + F64 COIL_AREA_X_Y = this->COIL_LENGTH_X_Y * this->COIL_WIDTH_X_Y; + F64 COIL_RESISTANCE_X_Y = 57.2; + F64 COIL_MAX_CURRENT_X_Y = this->COIL_VOLTAGE / this->COIL_RESISTANCE_X_Y; + I64 COIL_NUM_TURNS_Z = 153; + F64 COIL_DIAMETER_Z = 0.05755; + F64 COIL_AREA_Z = this->PI * powf(this->COIL_DIAMETER_Z / 2, 2.0); + F64 COIL_RESISTANCE_Z = 248.8; + F64 COIL_MAX_CURRENT_Z = this->COIL_VOLTAGE / this->COIL_RESISTANCE_Z; + + // Variables + Drv::MagneticField prevMgField = Drv::MagneticField(0.0, 0.0, 0.0, -1); // Functions bool executeControlStep(); + void setDipoleMoment(Drv::DipoleMoment dpMoment); }; } // namespace Components From f1ca87dd9906d384006e6a209a6006763263d3bf Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Mon, 3 Nov 2025 18:20:05 -0600 Subject: [PATCH 18/38] . --- .../Components/DetumbleManager/DetumbleManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index 745b2061..d28f80b2 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -48,7 +48,8 @@ bool DetumbleManager::executeControlStep() { this->prevMgField = mgField; - // Then apply the dipole moment here, gonna have to figure that out. + this->setDipoleMoment(dpMoment); + return true; } void DetumbleManager::setDipoleMoment(Drv::DipoleMoment dpMoment) { From b5544e72a29ec50fe48ecca11732e4597469210a Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Tue, 4 Nov 2025 11:13:29 -0500 Subject: [PATCH 19/38] Update Submodules --- lib/fprime | 2 +- lib/fprime-zephyr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fprime b/lib/fprime index 064b6455..626473fc 160000 --- a/lib/fprime +++ b/lib/fprime @@ -1 +1 @@ -Subproject commit 064b64553f1c0dce5afd43453bbf58993004e1e2 +Subproject commit 626473fc4e89e491d43ad95bb0d1b7727014c80d diff --git a/lib/fprime-zephyr b/lib/fprime-zephyr index 11c2a109..dc83bef6 160000 --- a/lib/fprime-zephyr +++ b/lib/fprime-zephyr @@ -1 +1 @@ -Subproject commit 11c2a109c0225745237c46a0f45902ffc598500b +Subproject commit dc83bef61c25c65d3854cf65b045daf42a6a58f9 From 5351c58c7df7578d7488d40d5ccc28142590a07a Mon Sep 17 00:00:00 2001 From: Michael Pham <61564344+Mikefly123@users.noreply.github.com> Date: Tue, 4 Nov 2025 16:42:40 -0800 Subject: [PATCH 20/38] Revert "Update Submodules" This reverts commit b5544e72a29ec50fe48ecca11732e4597469210a. --- lib/fprime | 2 +- lib/fprime-zephyr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fprime b/lib/fprime index 626473fc..064b6455 160000 --- a/lib/fprime +++ b/lib/fprime @@ -1 +1 @@ -Subproject commit 626473fc4e89e491d43ad95bb0d1b7727014c80d +Subproject commit 064b64553f1c0dce5afd43453bbf58993004e1e2 diff --git a/lib/fprime-zephyr b/lib/fprime-zephyr index dc83bef6..11c2a109 160000 --- a/lib/fprime-zephyr +++ b/lib/fprime-zephyr @@ -1 +1 @@ -Subproject commit dc83bef61c25c65d3854cf65b045daf42a6a58f9 +Subproject commit 11c2a109c0225745237c46a0f45902ffc598500b From 46e660460cc7cb7e39e6d7aae99335afd88a27be Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Wed, 5 Nov 2025 20:35:23 -0500 Subject: [PATCH 21/38] Add Reset port functionality --- .../Components/LoadSwitch/LoadSwitch.cpp | 10 ++++++++++ .../Components/LoadSwitch/LoadSwitch.fpp | 5 +++++ .../Components/LoadSwitch/LoadSwitch.hpp | 13 +++++++++++++ 3 files changed, 28 insertions(+) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp index e92b1aea..b61ff198 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -18,6 +18,16 @@ LoadSwitch ::LoadSwitch(const char* const compName) : LoadSwitchComponentBase(co LoadSwitch ::~LoadSwitch() {} +// ---------------------------------------------------------------------- +// Handler implementations for typed input ports +// ---------------------------------------------------------------------- + +void LoadSwitch ::Reset_handler(FwIndexType portNum) { + gpio_pin_set(m_device, m_pinNum, 0); + k_sleep(K_MSEC(100)); + gpio_pin_set(m_device, m_pinNum, 1); +} + // ---------------------------------------------------------------------- // Handler implementations for commands // ---------------------------------------------------------------------- diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp index ff564b24..d00d49b1 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp @@ -26,6 +26,11 @@ module Components { # sync input port run: Svc.Sched output port Status: Drv.GpioRead + + # Input that will be used by other components if they want to force a reset + # (off and on again) of the load switch + async input port Reset: Fw.Signal + # @ Example parameter # param PARAMETER_NAME: U32 diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp index 12d79c01..bc94e4ea 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp @@ -8,6 +8,7 @@ #define Components_LoadSwitch_HPP #include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitchComponentAc.hpp" +#include // Forward declare Zephyr types to avoid header conflicts struct device; @@ -48,6 +49,18 @@ class LoadSwitch final : public LoadSwitchComponentBase { U32 cmdSeq //!< The command sequence number ) override; + // ---------------------------------------------------------------------- + // Handler implementations for typed input ports + // ---------------------------------------------------------------------- + + //! Handler implementation for Reset + void Reset_handler(FwIndexType portNum //!< The port number + ) override; + + // ---------------------------------------------------------------------- + // Member variables + // ---------------------------------------------------------------------- + uint8_t m_pinNum; static const struct device* m_device; }; From 98326f2630f9f875847e97ddab3fc6714d498337 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:54:13 -0500 Subject: [PATCH 22/38] Add remaining load switch instances --- .../Top/ReferenceDeploymentTopology.cpp | 9 ++++- .../ReferenceDeployment/Top/instances.fpp | 37 ++++++++++++++++++- .../ReferenceDeployment/Top/topology.fpp | 9 ++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index 7f242a01..da089523 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -61,7 +61,14 @@ void configureTopology() { gpioDriver.open(ledGpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire0.open(burnwire0Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire1.open(burnwire1Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); - loadSwitch1.pin_configuration(mcp23017_dev, 0); // Pin 0 on MCP23017 + face4LoadSwitch.pin_configuration(mcp23017_dev, 0); // Pin 0 on MCP23017 + face0LoadSwitch.pin_configuration(mcp23017_dev, 1); // Pin 1 on MCP23017 + face1LoadSwitch.pin_configuration(mcp23017_dev, 2); // Pin 2 on MCP23017 + face2LoadSwitch.pin_configuration(mcp23017_dev, 3); // Pin 3 on MCP23017 + face3LoadSwitch.pin_configuration(mcp23017_dev, 4); // Pin 4 on MCP23017 + face5LoadSwitch.pin_configuration(mcp23017_dev, 5); // Pin 5 on MCP23017 + payloadPowerLoadSwitch.pin_configuration(mcp23017_dev, 7); // Pin 7 on MCP23017 + payloadBatteryLoadSwitch.pin_configuration(mcp23017_dev, 9); // Pin 9 on MCP23017 } // Public functions for use in main program are namespaced with deployment name ReferenceDeployment diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 19d28754..f98c69b6 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -37,7 +37,42 @@ module ReferenceDeployment { stack size Default.STACK_SIZE \ priority 4 - instance loadSwitch1: Components.LoadSwitch base id 0x10004000 \ + instance face4LoadSwitch: Components.LoadSwitch base id 0x10014000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance face0LoadSwitch: Components.LoadSwitch base id 0x10010000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance face1LoadSwitch: Components.LoadSwitch base id 0x10011000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance face2LoadSwitch: Components.LoadSwitch base id 0x10012000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance face3LoadSwitch: Components.LoadSwitch base id 0x10013000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance face5LoadSwitch: Components.LoadSwitch base id 0x10015000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance payloadPowerLoadSwitch: Components.LoadSwitch base id 0x10016000 \ + queue size Default.QUEUE_SIZE \ + stack size Default.STACK_SIZE \ + priority 5 + + instance payloadBatteryLoadSwitch: Components.LoadSwitch base id 0x10017000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 9b0cd82b..d96a5013 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -44,7 +44,14 @@ module ReferenceDeployment { # For UART sideband communication instance comDriver - instance loadSwitch1 + instance face4LoadSwitch + instance face0LoadSwitch + instance face1LoadSwitch + instance face2LoadSwitch + instance face3LoadSwitch + instance face5LoadSwitch + instance payloadPowerLoadSwitch + instance payloadBatteryLoadSwitch instance fsSpace From 9c72d7a550bcec6c6c16b4cfe0a7f1fb5451f502 Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Wed, 5 Nov 2025 21:11:02 -0500 Subject: [PATCH 23/38] Small updates to extra loadSwitch instances, update max packets - Max packets from 8 to 9 --- .../Top/ReferenceDeploymentPackets.fppi | 13 ++++++++++--- .../ReferenceDeployment/Top/instances.fpp | 18 +++++++++--------- .../project/config/TlmPacketizerCfg.hpp | 2 +- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi index e3097dab..ec186e21 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentPackets.fppi @@ -61,11 +61,18 @@ telemetry packets ReferenceDeploymentPackets { ReferenceDeployment.antennaDeployer.LastDistance } + packet LoadSwitches id 9 group 4 { + ReferenceDeployment.face4LoadSwitch.IsOn + ReferenceDeployment.face0LoadSwitch.IsOn + ReferenceDeployment.face1LoadSwitch.IsOn + ReferenceDeployment.face2LoadSwitch.IsOn + ReferenceDeployment.face3LoadSwitch.IsOn + ReferenceDeployment.face5LoadSwitch.IsOn + ReferenceDeployment.payloadPowerLoadSwitch.IsOn + ReferenceDeployment.payloadBatteryLoadSwitch.IsOn + } } omit { - # Needs to be added appropriately later - loadSwitch1.IsOn - CdhCore.cmdDisp.CommandErrors # Only has one library, no custom versions CdhCore.version.LibraryVersion02 diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index f98c69b6..016dee51 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -37,47 +37,47 @@ module ReferenceDeployment { stack size Default.STACK_SIZE \ priority 4 - instance face4LoadSwitch: Components.LoadSwitch base id 0x10014000 \ + instance face4LoadSwitch: Components.LoadSwitch base id 0x10003000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance face0LoadSwitch: Components.LoadSwitch base id 0x10010000 \ + instance face0LoadSwitch: Components.LoadSwitch base id 0x10004000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance face1LoadSwitch: Components.LoadSwitch base id 0x10011000 \ + instance face1LoadSwitch: Components.LoadSwitch base id 0x10005000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance face2LoadSwitch: Components.LoadSwitch base id 0x10012000 \ + instance face2LoadSwitch: Components.LoadSwitch base id 0x10006000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance face3LoadSwitch: Components.LoadSwitch base id 0x10013000 \ + instance face3LoadSwitch: Components.LoadSwitch base id 0x10007000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance face5LoadSwitch: Components.LoadSwitch base id 0x10015000 \ + instance face5LoadSwitch: Components.LoadSwitch base id 0x10008000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance payloadPowerLoadSwitch: Components.LoadSwitch base id 0x10016000 \ + instance payloadPowerLoadSwitch: Components.LoadSwitch base id 0x10009000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance payloadBatteryLoadSwitch: Components.LoadSwitch base id 0x10017000 \ + instance payloadBatteryLoadSwitch: Components.LoadSwitch base id 0x1000A000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 - instance prmDb: Svc.PrmDb base id 0x10003000 \ + instance prmDb: Svc.PrmDb base id 0x1000B000 \ queue size Default.QUEUE_SIZE \ stack size Default.STACK_SIZE \ priority 5 diff --git a/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp b/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp index 3c11895d..e86a06c9 100644 --- a/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp +++ b/FprimeZephyrReference/project/config/TlmPacketizerCfg.hpp @@ -16,7 +16,7 @@ #include namespace Svc { -static const FwChanIdType MAX_PACKETIZER_PACKETS = 8; +static const FwChanIdType MAX_PACKETIZER_PACKETS = 9; static const FwChanIdType TLMPACKETIZER_NUM_TLM_HASH_SLOTS = 15; // !< Number of slots in the hash table. // Works best when set to about twice the number of components producing telemetry From d7fce15cb716d9acb0ec37453beee03042a3b4a5 Mon Sep 17 00:00:00 2001 From: Moises Mata Date: Wed, 5 Nov 2025 21:13:19 -0500 Subject: [PATCH 24/38] Remove output read port, add output write port --- FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp index d00d49b1..8a166d55 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp @@ -24,7 +24,11 @@ module Components { # @ Example port: receiving calls from the rate group # sync input port run: Svc.Sched - output port Status: Drv.GpioRead + #output port Status: Drv.GpioRead + #We will not be putting a Drv.GpioRead port here, we are using the Gpio Driver component which has this already! + + @ Port sending calls to the GPIO driver + output port gpioSet: Drv.GpioWrite # Input that will be used by other components if they want to force a reset From c633bf9a993ca1afb24e638eb15f5a1e75344feb Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Wed, 5 Nov 2025 20:55:09 -0600 Subject: [PATCH 25/38] add magnetorquer component --- .../Components/Drv/CMakeLists.txt | 1 + .../Drv/MagnetorquerManager/CMakeLists.txt | 36 ++++++++++ .../MagnetorquerManager.cpp | 42 ++++++++++++ .../MagnetorquerManager.fpp | 57 ++++++++++++++++ .../MagnetorquerManager.hpp | 44 +++++++++++++ .../Drv/MagnetorquerManager/docs/sdd.md | 66 +++++++++++++++++++ .../ReferenceDeployment/Top/instances.fpp | 2 + .../ReferenceDeployment/Top/topology.fpp | 1 + .../proves_flight_control_board_v5.dtsi | 26 ++++++++ prj.conf | 6 ++ 10 files changed, 281 insertions(+) create mode 100644 FprimeZephyrReference/Components/Drv/MagnetorquerManager/CMakeLists.txt create mode 100644 FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp create mode 100644 FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp create mode 100644 FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp create mode 100644 FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md diff --git a/FprimeZephyrReference/Components/Drv/CMakeLists.txt b/FprimeZephyrReference/Components/Drv/CMakeLists.txt index efcd2f90..793c22a4 100644 --- a/FprimeZephyrReference/Components/Drv/CMakeLists.txt +++ b/FprimeZephyrReference/Components/Drv/CMakeLists.txt @@ -3,3 +3,4 @@ add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lis2mdlManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Lsm6dsoManager/") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/RtcManager") add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Types/") +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/MagnetorquerManager/") diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/CMakeLists.txt b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/CMakeLists.txt new file mode 100644 index 00000000..92da00df --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/CMakeLists.txt @@ -0,0 +1,36 @@ +#### +# F Prime CMakeLists.txt: +# +# SOURCES: list of source files (to be compiled) +# AUTOCODER_INPUTS: list of files to be passed to the autocoders +# DEPENDS: list of libraries that this module depends on +# +# More information in the F´ CMake API documentation: +# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/ +# +#### + +# Module names are derived from the path from the nearest project/library/framework +# root when not specifically overridden by the developer. i.e. The module defined by +# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`. + +register_fprime_library( + AUTOCODER_INPUTS + "${CMAKE_CURRENT_LIST_DIR}/MagnetorquerManager.fpp" + SOURCES + "${CMAKE_CURRENT_LIST_DIR}/MagnetorquerManager.cpp" +# DEPENDS +# MyPackage_MyOtherModule +) + +### Unit Tests ### +# register_fprime_ut( +# AUTOCODER_INPUTS +# "${CMAKE_CURRENT_LIST_DIR}/MagnetorquerManager.fpp" +# SOURCES +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/MagnetorquerManagerTestMain.cpp" +# "${CMAKE_CURRENT_LIST_DIR}/test/ut/MagnetorquerManagerTester.cpp" +# DEPENDS +# STest # For rules-based testing +# UT_AUTO_HELPERS +# ) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp new file mode 100644 index 00000000..453947a6 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp @@ -0,0 +1,42 @@ +// ====================================================================== +// \title MagnetorquerManager.cpp +// \author aychar +// \brief cpp file for MagnetorquerManager component implementation class +// ====================================================================== + +#include "FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp" + +#include +#include + +namespace Drv { + +// ---------------------------------------------------------------------- +// Component construction and destruction +// ---------------------------------------------------------------------- + +MagnetorquerManager ::MagnetorquerManager(const char* const compName) : MagnetorquerManagerComponentBase(compName) { + dev = device_get_binding("DRV2605"); +} + +MagnetorquerManager ::~MagnetorquerManager() {} + +void MagnetorquerManager ::START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { + if (!device_is_ready(dev)) { + this->log_WARNING_HI_DeviceNotReady(); + return; + } + drv2605_haptic_config(this->dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&this->rom); +} + +void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { + if (!device_is_ready(dev)) { + this->log_WARNING_HI_DeviceNotReady(); + return; + } + + struct drv2605_rom_data rom2 = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {50, 0, 0, 0, 0, 0, 0, 0}}; + drv2605_haptic_config(this->dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&rom2); +} + +} // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp new file mode 100644 index 00000000..62e23685 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp @@ -0,0 +1,57 @@ +module Drv { + @ Component for F Prime FSW framework. + passive component MagnetorquerManager { + + @ Event for reporting DRV2605 not ready error + event DeviceNotReady() severity warning high format "DRV2605 device not ready" throttle 5 + + @ Start DRV2605 playback with effect #47 + sync command START_PLAYBACK_TEST() + + @ Start DRV2605 playback with effect #50 + sync command START_PLAYBACK_TEST2() + + # @ Example telemetry counter + # telemetry ExampleCounter: U64 + + # @ Example event + # event ExampleStateEvent(example_state: Fw.On) severity activity high id 0 format "State set to {}" + + # @ Example port: receiving calls from the rate group + # sync input port run: Svc.Sched + + # @ Example parameter + # param PARAMETER_NAME: U32 + + ############################################################################### + # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # + ############################################################################### + @ Port for requesting the current time + time get port timeCaller + + @ Port for sending command registrations + command reg port cmdRegOut + + @ Port for receiving commands + command recv port cmdIn + + @ Port for sending command responses + command resp port cmdResponseOut + + @ Port for sending textual representation of events + text event port logTextOut + + @ Port for sending events to downlink + event port logOut + + @ Port for sending telemetry channels to downlink + telemetry port tlmOut + + @ Port to return the value of a parameter + param get port prmGetOut + + @Port to set the value of a parameter + param set port prmSetOut + + } +} diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp new file mode 100644 index 00000000..7ed6ce28 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp @@ -0,0 +1,44 @@ +// ====================================================================== +// \title MagnetorquerManager.hpp +// \author aychar +// \brief hpp file for MagnetorquerManager component implementation class +// ====================================================================== + +#ifndef Drv_MagnetorquerManager_HPP +#define Drv_MagnetorquerManager_HPP + +#include "FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManagerComponentAc.hpp" + +#include +#include +#include + +#include + +namespace Drv { + +class MagnetorquerManager final : public MagnetorquerManagerComponentBase { + public: + // ---------------------------------------------------------------------- + // Component construction and destruction + // ---------------------------------------------------------------------- + + //! Construct MagnetorquerManager object + MagnetorquerManager(const char* const compName //!< The component name + ); + + //! Destroy MagnetorquerManager object + ~MagnetorquerManager(); + + private: + //! Zephyr device to store initialized DRV2605 + const struct device* dev; + struct drv2605_rom_data rom = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {47, 0, 0, 0, 0, 0, 0, 0}}; + + void START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override; + void START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override; +}; + +} // namespace Drv + +#endif diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md new file mode 100644 index 00000000..43ec4dc8 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md @@ -0,0 +1,66 @@ +# Drv::MagnetorquerManager + +Component for F Prime FSW framework. + +## Usage Examples +Add usage examples here + +### Diagrams +Add diagrams here + +### Typical Usage +And the typical usage of the component here + +## Class Diagram +Add a class diagram here + +## Port Descriptions +| Name | Description | +|---|---| +|---|---| + +## Component States +Add component states in the chart below +| Name | Description | +|---|---| +|---|---| + +## Sequence Diagrams +Add sequence diagrams here + +## Parameters +| Name | Description | +|---|---| +|---|---| + +## Commands +| Name | Description | +|---|---| +|---|---| + +## Events +| Name | Description | +|---|---| +|---|---| + +## Telemetry +| Name | Description | +|---|---| +|---|---| + +## Unit Tests +Add unit test descriptions in the chart below +| Name | Description | Output | Coverage | +|---|---|---|---| +|---|---|---|---| + +## Requirements +Add requirements in the chart below +| Name | Description | Validation | +|---|---|---| +|---|---|---| + +## Change Log +| Date | Description | +|---|---| +|---| Initial Draft | \ No newline at end of file diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 4cf1dbf9..5aa0f8fa 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -95,4 +95,6 @@ module ReferenceDeployment { instance ina219SysManager: Drv.Ina219Manager base id 0x10032000 instance ina219SolManager: Drv.Ina219Manager base id 0x10033000 + + instance magnetorquerManager: Drv.MagnetorquerManager base id 0x10034000 } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 79169a2e..cd5d82b8 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -47,6 +47,7 @@ module ReferenceDeployment { instance powerMonitor instance ina219SysManager instance ina219SolManager + instance magnetorquerManager # ---------------------------------------------------------------------- diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 363ac07c..8a5ced71 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -163,6 +163,32 @@ zephyr_udc0: &usbd { lsb-microamp = <61>; label = "INA219 sol"; }; + + tca9548a: tca9548a@70 { + compatible = "ti,tca9548a"; + reg = <0x70>; + #address-cells = <1>; + #size-cells = <0>; + label = "TCA9548A"; + + tca_channel0: channel@0 { + compatible = "ti,tca9548a-channel"; + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + + drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "DRV2605"; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + }; + }; }; diff --git a/prj.conf b/prj.conf index b1e35675..e4f3cf9b 100644 --- a/prj.conf +++ b/prj.conf @@ -28,6 +28,9 @@ CONFIG_GPIO=y CONFIG_LED=y CONFIG_PWM=n CONFIG_I2C=y +# I2C multiplexer (TCA9548A) priority configuration +CONFIG_I2C_TCA954X_ROOT_INIT_PRIO=70 +CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO=71 CONFIG_SPI=y CONFIG_PINCTRL=y CONFIG_ASSERT=y @@ -65,3 +68,6 @@ CONFIG_FAT_FILESYSTEM_ELM=y CONFIG_FS_FATFS_EXFAT=y CONFIG_FS_FATFS_MOUNT_MKFS=y CONFIG_FS_FATFS_FSTAB_AUTOMOUNT=y + +CONFIG_HAPTICS=y +CONFIG_HAPTICS_DRV2605=y From b456c1d818a666d80a4fae97b3416966a5a1a30d Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Wed, 5 Nov 2025 21:03:33 -0600 Subject: [PATCH 26/38] switch to use new device initialization pattern --- .../MagnetorquerManager.cpp | 20 ++++++++++++------- .../MagnetorquerManager.hpp | 5 ++++- .../ReferenceDeployment/Main.cpp | 2 ++ .../Top/ReferenceDeploymentTopology.cpp | 1 + .../Top/ReferenceDeploymentTopologyDefs.hpp | 13 ++++++------ 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp index 453947a6..4ae87c25 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp @@ -15,28 +15,34 @@ namespace Drv { // Component construction and destruction // ---------------------------------------------------------------------- -MagnetorquerManager ::MagnetorquerManager(const char* const compName) : MagnetorquerManagerComponentBase(compName) { - dev = device_get_binding("DRV2605"); -} +MagnetorquerManager ::MagnetorquerManager(const char* const compName) : MagnetorquerManagerComponentBase(compName) {} MagnetorquerManager ::~MagnetorquerManager() {} +// ---------------------------------------------------------------------- +// Helper methods +// ---------------------------------------------------------------------- + +void MagnetorquerManager ::configure(const struct device* dev) { + this->m_dev = dev; +} + void MagnetorquerManager ::START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { - if (!device_is_ready(dev)) { + if (!device_is_ready(this->m_dev)) { this->log_WARNING_HI_DeviceNotReady(); return; } - drv2605_haptic_config(this->dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&this->rom); + drv2605_haptic_config(this->m_dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&this->rom); } void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { - if (!device_is_ready(dev)) { + if (!device_is_ready(this->m_dev)) { this->log_WARNING_HI_DeviceNotReady(); return; } struct drv2605_rom_data rom2 = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {50, 0, 0, 0, 0, 0, 0, 0}}; - drv2605_haptic_config(this->dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&rom2); + drv2605_haptic_config(this->m_dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&rom2); } } // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp index 7ed6ce28..68a4480b 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp @@ -30,9 +30,12 @@ class MagnetorquerManager final : public MagnetorquerManagerComponentBase { //! Destroy MagnetorquerManager object ~MagnetorquerManager(); + //! Configure the DRV2605 device + void configure(const struct device* dev); + private: //! Zephyr device to store initialized DRV2605 - const struct device* dev; + const struct device* m_dev; struct drv2605_rom_data rom = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {47, 0, 0, 0, 0, 0, 0, 0}}; void START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override; diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index 6b5187a8..b5b6aafa 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -16,6 +16,7 @@ const struct device* serial = DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0)); const struct device* lora = DEVICE_DT_GET(DT_NODELABEL(lora0)); const struct device* lsm6dso = DEVICE_DT_GET(DT_NODELABEL(lsm6dso0)); const struct device* lis2mdl = DEVICE_DT_GET(DT_NODELABEL(lis2mdl0)); +const struct device* drv2605 = device_get_binding("DRV2605"); int main(int argc, char* argv[]) { // ** DO NOT REMOVE **// @@ -32,6 +33,7 @@ int main(int argc, char* argv[]) { inputs.uartDevice = serial; inputs.lsm6dsoDevice = lsm6dso; inputs.lis2mdlDevice = lis2mdl; + inputs.drv2605Device = drv2605; inputs.baudRate = 115200; // Setup, cycle, and teardown topology diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index 0580479a..12dd0814 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -92,6 +92,7 @@ void setupTopology(const TopologyState& state) { lis2mdlManager.configure(state.lis2mdlDevice); ina219SysManager.configure(state.ina219SysDevice); ina219SolManager.configure(state.ina219SolDevice); + magnetorquerManager.configure(state.drv2605Device); } void startRateGroups() { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index fc9fe0ce..71146aa3 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -69,12 +69,13 @@ namespace ReferenceDeployment { * autocoder. The contents are entirely up to the definition of the project. This deployment uses subtopologies. */ struct TopologyState { - const device* ina219SysDevice; //!< device path for battery board ina219 - const device* ina219SolDevice; //!< device path for solar panel ina219 - const device* uartDevice; //!< UART device path for communication - const device* loraDevice; //!< LoRa device path for communication - const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope - const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer + const device* ina219SysDevice; //!< device path for battery board ina219 + const device* ina219SolDevice; //!< device path for solar panel ina219 + const device* uartDevice; //!< UART device path for communication + const device* loraDevice; //!< LoRa device path for communication + const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope + const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer + const device* drv2605Device; U32 baudRate; //!< Baud rate for UART communication CdhCore::SubtopologyState cdhCore; //!< Subtopology state for CdhCore ComCcsds::SubtopologyState comCcsds; //!< Subtopology state for ComCcsds From 7ee7e146b026c3058d552915f8bf3f02700f7f9b Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Fri, 7 Nov 2025 14:05:37 -0600 Subject: [PATCH 27/38] increase command limit --- .../project/config/CommandDispatcherImplCfg.hpp | 2 +- .../proves_flight_control_board_v5.dtsi | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp b/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp index ab88a46b..5af97d4c 100644 --- a/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp +++ b/FprimeZephyrReference/project/config/CommandDispatcherImplCfg.hpp @@ -11,7 +11,7 @@ // Define configuration values for dispatcher enum { - CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 50, // !< The size of the table holding opcodes to dispatch + CMD_DISPATCHER_DISPATCH_TABLE_SIZE = 60, // !< The size of the table holding opcodes to dispatch CMD_DISPATCHER_SEQUENCER_TABLE_SIZE = 10, // !< The size of the table holding commands in progress }; diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 8a5ced71..22f75c96 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -164,9 +164,9 @@ zephyr_udc0: &usbd { label = "INA219 sol"; }; - tca9548a: tca9548a@70 { + tca9548a: tca9548a@77 { compatible = "ti,tca9548a"; - reg = <0x70>; + reg = <0x77>; #address-cells = <1>; #size-cells = <0>; label = "TCA9548A"; From bdb62026c3ce92a7378b4bc8ba5b33a3bb0504d1 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Fri, 7 Nov 2025 14:45:27 -0600 Subject: [PATCH 28/38] update dtsi --- .../proves_flight_control_board_v5.dtsi | 165 +++++++++++++++++- 1 file changed, 162 insertions(+), 3 deletions(-) diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 22f75c96..35ed3949 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -164,30 +164,189 @@ zephyr_udc0: &usbd { label = "INA219 sol"; }; + tca9548a: tca9548a@77 { compatible = "ti,tca9548a"; + status = "okay"; reg = <0x77>; #address-cells = <1>; #size-cells = <0>; label = "TCA9548A"; + reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; - tca_channel0: channel@0 { + i2c_mux@0 { compatible = "ti,tca9548a-channel"; + label = "face0_i2c"; reg = <0>; #address-cells = <1>; #size-cells = <0>; + face0_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + + face0_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE0_DRV2605"; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + }; + + i2c_mux@1 { + compatible = "ti,tca9548a-channel"; + label = "face1_i2c"; + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + face1_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + + face1_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE1_DRV2605"; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + }; + + i2c_mux@2 { + compatible = "ti,tca9548a-channel"; + label = "face2_i2c"; + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + face2_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + + face2_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE2_DRV2605"; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + }; + + i2c_mux@3 { + compatible = "ti,tca9548a-channel"; + label = "face3_i2c"; + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + face3_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + + face3_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE3_DRV2605"; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + }; + + i2c_mux@4 { + compatible = "ti,tca9548a-channel"; + label = "battery_i2c"; + reg = <4>; + #address-cells = <1>; + #size-cells = <0>; + batt_cell1_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + batt_cell2_temp_sens: tmp112@73 { + compatible = "ti,tmp112"; + reg = <0x73>; + }; + batt_cell3_temp_sens: tmp112@74 { + compatible = "ti,tmp112"; + reg = <0x74>; + }; + batt_cell4_temp_sens: tmp112@75 { + compatible = "ti,tmp112"; + reg = <0x75>; + }; + }; + + i2c_mux@5 { + compatible = "ti,tca9548a-channel"; + label = "face4_i2c"; + reg = <5>; + #address-cells = <1>; + #size-cells = <0>; + face4_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; - drv2605: drv2605@5a { + face4_drv2605: drv2605@5a { compatible = "ti,drv2605"; status = "okay"; reg = <0x5a>; - label = "DRV2605"; + label = "FACE4_DRV2605"; actuator-mode = "LRA"; loop-gain = "HIGH"; feedback-brake-factor = "2X"; }; }; + + i2c_mux@6 { + compatible = "ti,tca9548a-channel"; + label = "face5_i2c"; + reg = <6>; + #address-cells = <1>; + #size-cells = <0>; + face5_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + + face5_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + label = "FACE5_DRV2605"; + + actuator-mode = "LRA"; + loop-gain = "HIGH"; + feedback-brake-factor = "2X"; + }; + }; + + i2c_mux@7 { + compatible = "ti,tca9548a-channel"; + label = "top_i2c"; + reg = <7>; + #address-cells = <1>; + #size-cells = <0>; + top_temp_sens: tmp112@72 { + compatible = "ti,tmp112"; + reg = <0x72>; + }; + }; }; }; From d47659372ca994f8f40b36be283ff4a702e55d07 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Fri, 7 Nov 2025 15:28:13 -0600 Subject: [PATCH 29/38] update everything to handle multiple devices initialized --- .../MagnetorquerManager.cpp | 33 ++++++++++++++----- .../MagnetorquerManager.fpp | 10 +++--- .../MagnetorquerManager.hpp | 11 ++++--- .../ReferenceDeployment/Main.cpp | 16 +++++++-- .../Top/ReferenceDeploymentTopology.cpp | 2 +- .../Top/ReferenceDeploymentTopologyDefs.hpp | 14 ++++---- 6 files changed, 60 insertions(+), 26 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp index 4ae87c25..971a1985 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp @@ -23,26 +23,43 @@ MagnetorquerManager ::~MagnetorquerManager() {} // Helper methods // ---------------------------------------------------------------------- -void MagnetorquerManager ::configure(const struct device* dev) { - this->m_dev = dev; +void MagnetorquerManager ::configure(const struct device* const devices[6]) { + for (int i = 0; i < 6; ++i) { + this->m_devices[i] = devices[i]; + } } -void MagnetorquerManager ::START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { - if (!device_is_ready(this->m_dev)) { +void MagnetorquerManager ::START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) { + // Validate face index (0..5) + if (faceIdx >= 6) { + this->log_WARNING_HI_DeviceNotReady(); + return; + } + + const struct device* dev = this->m_devices[faceIdx]; + if (!device_is_ready(dev)) { this->log_WARNING_HI_DeviceNotReady(); return; } - drv2605_haptic_config(this->m_dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&this->rom); + + drv2605_haptic_config(dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&this->rom); } -void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) { - if (!device_is_ready(this->m_dev)) { +void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) { + // Validate face index (0..5) + if (faceIdx >= 6) { + this->log_WARNING_HI_DeviceNotReady(); + return; + } + + const struct device* dev = this->m_devices[faceIdx]; + if (!device_is_ready(dev)) { this->log_WARNING_HI_DeviceNotReady(); return; } struct drv2605_rom_data rom2 = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {50, 0, 0, 0, 0, 0, 0, 0}}; - drv2605_haptic_config(this->m_dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&rom2); + drv2605_haptic_config(dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&rom2); } } // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp index 62e23685..222f9bb0 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp @@ -5,11 +5,13 @@ module Drv { @ Event for reporting DRV2605 not ready error event DeviceNotReady() severity warning high format "DRV2605 device not ready" throttle 5 - @ Start DRV2605 playback with effect #47 - sync command START_PLAYBACK_TEST() + @ Start DRV2605 playback on a device with effect #47 on a specific face + @ faceIdx: index of the face to actuate (valid range: 0..5) + sync command START_PLAYBACK_TEST(faceIdx: U8) - @ Start DRV2605 playback with effect #50 - sync command START_PLAYBACK_TEST2() + @ Start DRV2605 playback on a device with effect #50 on a specific face + @ faceIdx: index of the face to actuate (valid range: 0..5) + sync command START_PLAYBACK_TEST2(faceIdx: U8) # @ Example telemetry counter # telemetry ExampleCounter: U64 diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp index 68a4480b..460ef2df 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp @@ -31,15 +31,18 @@ class MagnetorquerManager final : public MagnetorquerManagerComponentBase { ~MagnetorquerManager(); //! Configure the DRV2605 device - void configure(const struct device* dev); + // Accept an array of six pointers to const device objects. The pointers themselves are const + // to match callers that provide const device* const* types. + void configure(const struct device* const devices[6]); private: //! Zephyr device to store initialized DRV2605 - const struct device* m_dev; + const struct device* m_devices[6]; struct drv2605_rom_data rom = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {47, 0, 0, 0, 0, 0, 0, 0}}; - void START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override; - void START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq) override; + // Command handlers updated to accept a face index (0..5) + void START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) override; + void START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) override; }; } // namespace Drv diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index b5b6aafa..43c9c073 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -16,7 +16,14 @@ const struct device* serial = DEVICE_DT_GET(DT_NODELABEL(cdc_acm_uart0)); const struct device* lora = DEVICE_DT_GET(DT_NODELABEL(lora0)); const struct device* lsm6dso = DEVICE_DT_GET(DT_NODELABEL(lsm6dso0)); const struct device* lis2mdl = DEVICE_DT_GET(DT_NODELABEL(lis2mdl0)); -const struct device* drv2605 = device_get_binding("DRV2605"); + +// Magnetorquer devices +const struct device* face0_drv2605 = device_get_binding("FACE0_DRV2605"); +const struct device* face1_drv2605 = device_get_binding("FACE1_DRV2605"); +const struct device* face2_drv2605 = device_get_binding("FACE2_DRV2605"); +const struct device* face3_drv2605 = device_get_binding("FACE3_DRV2605"); +const struct device* face4_drv2605 = device_get_binding("FACE4_DRV2605"); +const struct device* face5_drv2605 = device_get_binding("FACE5_DRV2605"); int main(int argc, char* argv[]) { // ** DO NOT REMOVE **// @@ -33,7 +40,12 @@ int main(int argc, char* argv[]) { inputs.uartDevice = serial; inputs.lsm6dsoDevice = lsm6dso; inputs.lis2mdlDevice = lis2mdl; - inputs.drv2605Device = drv2605; + inputs.drv2605Devices[0] = face0_drv2605; + inputs.drv2605Devices[1] = face1_drv2605; + inputs.drv2605Devices[2] = face2_drv2605; + inputs.drv2605Devices[3] = face3_drv2605; + inputs.drv2605Devices[4] = face4_drv2605; + inputs.drv2605Devices[5] = face5_drv2605; inputs.baudRate = 115200; // Setup, cycle, and teardown topology diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index 12dd0814..43296dd7 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -92,7 +92,7 @@ void setupTopology(const TopologyState& state) { lis2mdlManager.configure(state.lis2mdlDevice); ina219SysManager.configure(state.ina219SysDevice); ina219SolManager.configure(state.ina219SolDevice); - magnetorquerManager.configure(state.drv2605Device); + magnetorquerManager.configure(state.drv2605Devices); } void startRateGroups() { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index 71146aa3..ff27f01b 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -69,13 +69,13 @@ namespace ReferenceDeployment { * autocoder. The contents are entirely up to the definition of the project. This deployment uses subtopologies. */ struct TopologyState { - const device* ina219SysDevice; //!< device path for battery board ina219 - const device* ina219SolDevice; //!< device path for solar panel ina219 - const device* uartDevice; //!< UART device path for communication - const device* loraDevice; //!< LoRa device path for communication - const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope - const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer - const device* drv2605Device; + const device* ina219SysDevice; //!< device path for battery board ina219 + const device* ina219SolDevice; //!< device path for solar panel ina219 + const device* uartDevice; //!< UART device path for communication + const device* loraDevice; //!< LoRa device path for communication + const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope + const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer + const device* drv2605Devices[6]; //!< Array of drv2605 devices (6) U32 baudRate; //!< Baud rate for UART communication CdhCore::SubtopologyState cdhCore; //!< Subtopology state for CdhCore ComCcsds::SubtopologyState comCcsds; //!< Subtopology state for ComCcsds From 194a67a5ed6255315c509e863282351757e063d2 Mon Sep 17 00:00:00 2001 From: Michael Pham <61564344+Mikefly123@users.noreply.github.com> Date: Fri, 7 Nov 2025 14:38:37 -0800 Subject: [PATCH 30/38] Hello World --- .../Top/ReferenceDeploymentTopology.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index 86e2791f..6571a0e5 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -61,14 +61,14 @@ void configureTopology() { gpioDriver.open(ledGpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire0.open(burnwire0Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); gpioBurnwire1.open(burnwire1Gpio, Zephyr::ZephyrGpioDriver::GpioConfiguration::OUT); - face4LoadSwitch.pin_configuration(mcp23017_dev, 0); // Pin 0 on MCP23017 - face0LoadSwitch.pin_configuration(mcp23017_dev, 1); // Pin 1 on MCP23017 - face1LoadSwitch.pin_configuration(mcp23017_dev, 2); // Pin 2 on MCP23017 - face2LoadSwitch.pin_configuration(mcp23017_dev, 3); // Pin 3 on MCP23017 - face3LoadSwitch.pin_configuration(mcp23017_dev, 4); // Pin 4 on MCP23017 - face5LoadSwitch.pin_configuration(mcp23017_dev, 5); // Pin 5 on MCP23017 - payloadPowerLoadSwitch.pin_configuration(mcp23017_dev, 7); // Pin 7 on MCP23017 - payloadBatteryLoadSwitch.pin_configuration(mcp23017_dev, 9); // Pin 9 on MCP23017 + face4LoadSwitch.pin_configuration(mcp23017_dev, 8); + face0LoadSwitch.pin_configuration(mcp23017_dev, 9); + face1LoadSwitch.pin_configuration(mcp23017_dev, 10); + face2LoadSwitch.pin_configuration(mcp23017_dev, 11); + face3LoadSwitch.pin_configuration(mcp23017_dev, 12); + face5LoadSwitch.pin_configuration(mcp23017_dev, 13); + payloadPowerLoadSwitch.pin_configuration(mcp23017_dev, 1); + payloadBatteryLoadSwitch.pin_configuration(mcp23017_dev, 3); } // Public functions for use in main program are namespaced with deployment name ReferenceDeployment From 455800442d72efb7ffd799b938a5fe2e5d88b6c2 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Tue, 11 Nov 2025 13:45:29 -0600 Subject: [PATCH 31/38] bump thread count and switch to use DT_NODELABEL --- FprimeZephyrReference/ReferenceDeployment/Main.cpp | 12 ++++++------ prj.conf | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index 43c9c073..289581e8 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -18,12 +18,12 @@ const struct device* lsm6dso = DEVICE_DT_GET(DT_NODELABEL(lsm6dso0)); const struct device* lis2mdl = DEVICE_DT_GET(DT_NODELABEL(lis2mdl0)); // Magnetorquer devices -const struct device* face0_drv2605 = device_get_binding("FACE0_DRV2605"); -const struct device* face1_drv2605 = device_get_binding("FACE1_DRV2605"); -const struct device* face2_drv2605 = device_get_binding("FACE2_DRV2605"); -const struct device* face3_drv2605 = device_get_binding("FACE3_DRV2605"); -const struct device* face4_drv2605 = device_get_binding("FACE4_DRV2605"); -const struct device* face5_drv2605 = device_get_binding("FACE5_DRV2605"); +const struct device* face0_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face0_drv2605)); +const struct device* face1_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face1_drv2605)); +const struct device* face2_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face2_drv2605)); +const struct device* face3_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face3_drv2605)); +const struct device* face4_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face4_drv2605)); +const struct device* face5_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face5_drv2605)); int main(int argc, char* argv[]) { // ** DO NOT REMOVE **// diff --git a/prj.conf b/prj.conf index e4f3cf9b..72461cee 100644 --- a/prj.conf +++ b/prj.conf @@ -39,7 +39,7 @@ CONFIG_DYNAMIC_THREAD=y CONFIG_KERNEL_MEM_POOL=y CONFIG_DYNAMIC_THREAD_ALLOC=n CONFIG_DYNAMIC_THREAD_PREFER_POOL=y -CONFIG_DYNAMIC_THREAD_POOL_SIZE=15 +CONFIG_DYNAMIC_THREAD_POOL_SIZE=24 # Num threads in the thread pool CONFIG_DYNAMIC_THREAD_STACK_SIZE=8192 # Size of thread stack in thread pool, must be >= Thread Pool size in F' From 30f9f13744d3adc087d0b30c90898a528f0d053f Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Tue, 11 Nov 2025 14:44:10 -0600 Subject: [PATCH 32/38] switch to using 5 drv2605 and define wip function to set magnetorquers --- .../MagnetorquerManager.cpp | 22 ++++++++----- .../MagnetorquerManager.fpp | 33 ++++++++++--------- .../MagnetorquerManager.hpp | 8 +++-- .../ReferenceDeployment/Main.cpp | 2 -- .../Top/ReferenceDeploymentTopologyDefs.hpp | 2 +- .../proves_flight_control_board_v5.dtsi | 11 ------- 6 files changed, 37 insertions(+), 41 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp index 971a1985..fe720b16 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp @@ -23,16 +23,16 @@ MagnetorquerManager ::~MagnetorquerManager() {} // Helper methods // ---------------------------------------------------------------------- -void MagnetorquerManager ::configure(const struct device* const devices[6]) { - for (int i = 0; i < 6; ++i) { +void MagnetorquerManager ::configure(const struct device* const devices[5]) { + for (int i = 0; i < 5; ++i) { this->m_devices[i] = devices[i]; } } void MagnetorquerManager ::START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) { - // Validate face index (0..5) - if (faceIdx >= 6) { - this->log_WARNING_HI_DeviceNotReady(); + // Validate face index (0..4) + if (faceIdx >= 5) { + this->log_WARNING_LO_InvalidFaceIndex(); return; } @@ -46,9 +46,9 @@ void MagnetorquerManager ::START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U } void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) { - // Validate face index (0..5) - if (faceIdx >= 6) { - this->log_WARNING_HI_DeviceNotReady(); + // Validate face index (0..4) + if (faceIdx >= 5) { + this->log_WARNING_LO_InvalidFaceIndex(); return; } @@ -62,4 +62,10 @@ void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, drv2605_haptic_config(dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&rom2); } +void MagnetorquerManager ::SetMagnetorquers_handler(const FwIndexType portNum, const Drv::InputArray& value) { + // TODO(hrfarmer): Once its possible to properly interact with the DRV2605, I'll figure out how to + // determine how the passed in amps should translate to a specific pattern(s) that should be ran. + return; +} + } // namespace Drv diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp index 222f9bb0..39811975 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp @@ -1,3 +1,10 @@ +module Drv { + array InputArray = [5] I32; + port SetMagnetorquers( + value: InputArray @< Amp value for each face in the order x1, x2, y1, y2, z1 + ) +} + module Drv { @ Component for F Prime FSW framework. passive component MagnetorquerManager { @@ -5,25 +12,19 @@ module Drv { @ Event for reporting DRV2605 not ready error event DeviceNotReady() severity warning high format "DRV2605 device not ready" throttle 5 - @ Start DRV2605 playback on a device with effect #47 on a specific face - @ faceIdx: index of the face to actuate (valid range: 0..5) - sync command START_PLAYBACK_TEST(faceIdx: U8) - - @ Start DRV2605 playback on a device with effect #50 on a specific face - @ faceIdx: index of the face to actuate (valid range: 0..5) - sync command START_PLAYBACK_TEST2(faceIdx: U8) - - # @ Example telemetry counter - # telemetry ExampleCounter: U64 + @ Event to report an invalid face index passed in + event InvalidFaceIndex() severity warning low format "The faceIdx should be between 0-4" - # @ Example event - # event ExampleStateEvent(example_state: Fw.On) severity activity high id 0 format "State set to {}" + @ Start DRV2605 playback on a device with effect #47 on a specific face + @ faceIdx: index of the face to actuate (valid range: 0..4) + sync command START_PLAYBACK_TEST(faceIdx: U8) - # @ Example port: receiving calls from the rate group - # sync input port run: Svc.Sched + @ Start DRV2605 playback on a device with effect #50 on a specific face + @ faceIdx: index of the face to actuate (valid range: 0..4) + sync command START_PLAYBACK_TEST2(faceIdx: U8) - # @ Example parameter - # param PARAMETER_NAME: U32 + @ Input port to set magnetorquer values + sync input port SetMagnetorquers: SetMagnetorquers ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp index 460ef2df..b6397776 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp @@ -33,16 +33,18 @@ class MagnetorquerManager final : public MagnetorquerManagerComponentBase { //! Configure the DRV2605 device // Accept an array of six pointers to const device objects. The pointers themselves are const // to match callers that provide const device* const* types. - void configure(const struct device* const devices[6]); + void configure(const struct device* const devices[5]); private: - //! Zephyr device to store initialized DRV2605 - const struct device* m_devices[6]; + //! Zephyr device to store initialized DRV2605 devices + const struct device* m_devices[5]; struct drv2605_rom_data rom = {.library = DRV2605_LIBRARY_TS2200_A, .seq_regs = {47, 0, 0, 0, 0, 0, 0, 0}}; // Command handlers updated to accept a face index (0..5) void START_PLAYBACK_TEST_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) override; void START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) override; + + void SetMagnetorquers_handler(const FwIndexType portNum, const Drv::InputArray& value) override; }; } // namespace Drv diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index 289581e8..2cd31ae6 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -23,7 +23,6 @@ const struct device* face1_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face1_drv2605)); const struct device* face2_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face2_drv2605)); const struct device* face3_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face3_drv2605)); const struct device* face4_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face4_drv2605)); -const struct device* face5_drv2605 = DEVICE_DT_GET(DT_NODELABEL(face5_drv2605)); int main(int argc, char* argv[]) { // ** DO NOT REMOVE **// @@ -45,7 +44,6 @@ int main(int argc, char* argv[]) { inputs.drv2605Devices[2] = face2_drv2605; inputs.drv2605Devices[3] = face3_drv2605; inputs.drv2605Devices[4] = face4_drv2605; - inputs.drv2605Devices[5] = face5_drv2605; inputs.baudRate = 115200; // Setup, cycle, and teardown topology diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index ff27f01b..112a138d 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -75,7 +75,7 @@ struct TopologyState { const device* loraDevice; //!< LoRa device path for communication const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer - const device* drv2605Devices[6]; //!< Array of drv2605 devices (6) + const device* drv2605Devices[5]; //!< Array of DRV2605 devices (5) U32 baudRate; //!< Baud rate for UART communication CdhCore::SubtopologyState cdhCore; //!< Subtopology state for CdhCore ComCcsds::SubtopologyState comCcsds; //!< Subtopology state for ComCcsds diff --git a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi index 6d07cf69..21672f1f 100644 --- a/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi +++ b/boards/bronco_space/proves_flight_control_board_v5/proves_flight_control_board_v5.dtsi @@ -323,17 +323,6 @@ zephyr_udc0: &usbd { compatible = "ti,tmp112"; reg = <0x72>; }; - - face5_drv2605: drv2605@5a { - compatible = "ti,drv2605"; - status = "okay"; - reg = <0x5a>; - label = "FACE5_DRV2605"; - - actuator-mode = "LRA"; - loop-gain = "HIGH"; - feedback-brake-factor = "2X"; - }; }; i2c_mux@7 { From 62fa54d23c355977dd457366c4e26e6e932d67ea Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Tue, 11 Nov 2025 15:49:51 -0600 Subject: [PATCH 33/38] sdd --- .../Drv/MagnetorquerManager/docs/sdd.md | 142 +++++++++++++----- 1 file changed, 105 insertions(+), 37 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md index 43ec4dc8..6a5ba55f 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md @@ -1,66 +1,134 @@ # Drv::MagnetorquerManager -Component for F Prime FSW framework. +The Magnetorquer Manager component interfaces with the five DRV2605 devices on a PROVES CubeSat to control the current of the magnetorquers. ## Usage Examples -Add usage examples here + +This component is designed to be used by the detumble service to be able to detumble the cubesat when launched. ### Diagrams -Add diagrams here + +```mermaid +graph LR + A[Detumble Service] -->|SetMagnetorquers| B[MagnetorquerManager] + B -->|Configure| C[DRV2605 Device 0
X1 Face] + B -->|Configure| D[DRV2605 Device 1
X2 Face] + B -->|Configure| E[DRV2605 Device 2
Y1 Face] + B -->|Configure| F[DRV2605 Device 3
Y2 Face] + B -->|Configure| G[DRV2605 Device 4
Z1 Face] +``` ### Typical Usage -And the typical usage of the component here + +1. The component is instantiated and initialized during system startup +2. The detumble service calls the `SetMagnetorquers` input port. +3. On each call, the component: + - Takes in an `InputArray` parameter of 5 I32 for the amps for each face. + - Translates the passed in values to a sequence value from the DRV2605 library. + - Runs the sequence for each device. ## Class Diagram -Add a class diagram here + +```mermaid +classDiagram + class MagnetorquerManager { + -device* m_devices[5] + +configure(devices[5]) + +SetMagnetorquers_handler(portNum, value) + +START_PLAYBACK_TEST_cmdHandler(opCode, cmdSeq, faceIdx) + +START_PLAYBACK_TEST2_cmdHandler(opCode, cmdSeq, faceIdx) + } + + class MagnetorquerManagerComponentBase { + <> + } + + class DRV2605 { + <> + +device_is_ready() + +drv2605_haptic_config() + } + + MagnetorquerManager --|> MagnetorquerManagerComponentBase + MagnetorquerManager --> DRV2605 : uses (5 devices) +``` ## Port Descriptions -| Name | Description | -|---|---| -|---|---| -## Component States -Add component states in the chart below -| Name | Description | -|---|---| -|---|---| +| Name | Description | +| ---------------- | ------------------------------------------------------------------------------------------- | +| SetMagnetorquers | Input port that takes in an array (I32[5]) and applies each value to the cooresponding face | ## Sequence Diagrams -Add sequence diagrams here -## Parameters -| Name | Description | -|---|---| -|---|---| +### SetMagnetorquers Operation + +```mermaid +sequenceDiagram + participant DS as Detumble Service + participant MM as MagnetorquerManager + participant DRV as DRV2605 Devices + + DS->>MM: SetMagnetorquers([x1, x2, y1, y2, z1]) + Note over MM: Validate input array + Note over MM: Translate amps to sequences + loop For each face (0-4) + MM->>DRV: Check device_is_ready() + alt Device Ready + MM->>DRV: drv2605_haptic_config(sequence) + else Device Not Ready + MM->>MM: log_WARNING_HI_DeviceNotReady() + end + end + MM-->>DS: Return +``` + +### Test Command Operation + +```mermaid +sequenceDiagram + participant GS as Ground Station + participant MM as MagnetorquerManager + participant DRV as DRV2605 Device + + GS->>MM: START_PLAYBACK_TEST(faceIdx) + MM->>MM: Validate faceIdx (0-4) + alt Invalid faceIdx + MM->>MM: log_WARNING_LO_InvalidFaceIndex() + else Valid faceIdx + MM->>DRV: device_is_ready() + alt Device Ready + MM->>DRV: drv2605_haptic_config(effect #47) + else Device Not Ready + MM->>MM: log_WARNING_HI_DeviceNotReady() + end + end + MM-->>GS: Command Response +``` ## Commands -| Name | Description | -|---|---| -|---|---| -## Events -| Name | Description | -|---|---| -|---|---| +| Name | Description | +| -------------------- | ------------------------------------------------------------------------------------------------- | +| START_PLAYBACK_TEST | Start DRV2605 playback on a device with effect #47 on a specific face (faceIdx: 0-4). Test only. | +| START_PLAYBACK_TEST2 | Start DRV2605 playback on a device with effect #50 on a specific face (faceIdx: 0-4). Test only. | -## Telemetry -| Name | Description | -|---|---| -|---|---| +## Events -## Unit Tests -Add unit test descriptions in the chart below -| Name | Description | Output | Coverage | -|---|---|---|---| -|---|---|---|---| +| Name | Description | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| DeviceNotReady | Output whenever a magnetorquer is attempted to be used while it is not initialized. | +| InvalidFaceIndex | Output whenever one of the manual test comamands are ran with an invalid face index (will be removed if/when the test commands are removed) | ## Requirements + Add requirements in the chart below | Name | Description | Validation | |---|---|---| |---|---|---| ## Change Log -| Date | Description | -|---|---| -|---| Initial Draft | \ No newline at end of file + +| Date | Description | +| ---------- | ------------- | +| 11/11/2025 | Initial Draft | From 9d8554f647415c5dc2a909951d62d02d3597021b Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Tue, 11 Nov 2025 15:58:14 -0600 Subject: [PATCH 34/38] format --- .../Drv/MagnetorquerManager/MagnetorquerManager.hpp | 4 +--- FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp | 1 + FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp | 6 +++--- FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp index b6397776..ce81ad90 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp @@ -8,13 +8,11 @@ #define Drv_MagnetorquerManager_HPP #include "FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManagerComponentAc.hpp" - #include +#include #include #include -#include - namespace Drv { class MagnetorquerManager final : public MagnetorquerManagerComponentBase { diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp index b61ff198..5dbca3e3 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.cpp @@ -5,6 +5,7 @@ // ====================================================================== #include "FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp" + #include namespace Components { diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp index 8a166d55..4d52e08a 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.fpp @@ -26,12 +26,12 @@ module Components { # sync input port run: Svc.Sched #output port Status: Drv.GpioRead #We will not be putting a Drv.GpioRead port here, we are using the Gpio Driver component which has this already! - + @ Port sending calls to the GPIO driver output port gpioSet: Drv.GpioWrite - - # Input that will be used by other components if they want to force a reset + + # Input that will be used by other components if they want to force a reset # (off and on again) of the load switch async input port Reset: Fw.Signal diff --git a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp index bc94e4ea..d8d917d2 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp +++ b/FprimeZephyrReference/Components/LoadSwitch/LoadSwitch.hpp @@ -56,7 +56,7 @@ class LoadSwitch final : public LoadSwitchComponentBase { //! Handler implementation for Reset void Reset_handler(FwIndexType portNum //!< The port number ) override; - + // ---------------------------------------------------------------------- // Member variables // ---------------------------------------------------------------------- From 211446cb16aed29985d94f1b906544d8b500b5b4 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Tue, 11 Nov 2025 16:00:42 -0600 Subject: [PATCH 35/38] i cant spell --- .../Components/Drv/MagnetorquerManager/docs/sdd.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md index 6a5ba55f..52138636 100644 --- a/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md @@ -57,7 +57,7 @@ classDiagram | Name | Description | | ---------------- | ------------------------------------------------------------------------------------------- | -| SetMagnetorquers | Input port that takes in an array (I32[5]) and applies each value to the cooresponding face | +| SetMagnetorquers | Input port that takes in an array (I32[5]) and applies each value to the corresponding face | ## Sequence Diagrams @@ -108,8 +108,8 @@ sequenceDiagram ## Commands -| Name | Description | -| -------------------- | ------------------------------------------------------------------------------------------------- | +| Name | Description | +| -------------------- | ------------------------------------------------------------------------------------------------ | | START_PLAYBACK_TEST | Start DRV2605 playback on a device with effect #47 on a specific face (faceIdx: 0-4). Test only. | | START_PLAYBACK_TEST2 | Start DRV2605 playback on a device with effect #50 on a specific face (faceIdx: 0-4). Test only. | From d3fb83122100f4fe64c3a5b3c8fc0b06330d6ded Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Tue, 11 Nov 2025 16:43:49 -0600 Subject: [PATCH 36/38] fix build errors --- .../Components/Drv/BDotDetumble/BDotDetumble.cpp | 3 ++- .../Components/Drv/BDotDetumble/BDotDetumble.hpp | 1 - .../Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp index c7148925..6d21d750 100644 --- a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.cpp @@ -45,7 +45,8 @@ Drv::DipoleMoment BDotDetumble::dipoleMomentGet_handler(const FwIndexType portNu } F64 BDotDetumble::getMagnitude(const Drv::MagneticField magField) { - return sqrt(f64_square(magField.get_x()) + f64_square(magField.get_y()) + f64_square(magField.get_z())); + return sqrt((magField.get_x() * magField.get_x()) + (magField.get_y() * magField.get_y()) + + (magField.get_z() * magField.get_z())); } F64* BDotDetumble::dB_dt(const Drv::MagneticField currMagField, const Drv::MagneticField prevMagField) { diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp index c9a6c1f3..a00745e0 100644 --- a/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumble.hpp @@ -8,7 +8,6 @@ #define Drv_BDotDetumble_HPP #include "FprimeZephyrReference/Components/Drv/BDotDetumble/BDotDetumbleComponentAc.hpp" -#include "FprimeZephyrReference/Components/Drv/Helpers/Helpers.hpp" namespace Drv { diff --git a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp index 45c76dfd..f66e9470 100644 --- a/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp +++ b/FprimeZephyrReference/Components/Drv/Lis2mdlManager/Lis2mdlManager.cpp @@ -48,8 +48,8 @@ Drv::MagneticField Lis2mdlManager ::magneticFieldGet_handler(FwIndexType portNum sensor_channel_get(this->m_dev, SENSOR_CHAN_MAGN_Y, &y); sensor_channel_get(this->m_dev, SENSOR_CHAN_MAGN_Z, &z); - Drv::MagneticField magnetic_readings = - Drv::MagneticField(sensor_value_to_double(&x), sensor_value_to_double(&y), sensor_value_to_double(&z)); + Drv::MagneticField magnetic_readings = Drv::MagneticField(sensor_value_to_double(&x), sensor_value_to_double(&y), + sensor_value_to_double(&z), k_uptime_get()); this->tlmWrite_MagneticField(magnetic_readings); From 71efb6bded6cefa36542df1932c05530e3409760 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Wed, 12 Nov 2025 16:25:39 -0600 Subject: [PATCH 37/38] runtime loop draft --- .../DetumbleManager/DetumbleManager.cpp | 32 +++++++++++++------ .../DetumbleManager/DetumbleManager.fpp | 31 ++++++++++++++++++ .../DetumbleManager/DetumbleManager.hpp | 4 +-- .../ReferenceDeployment/Top/topology.fpp | 4 ++- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index d28f80b2..45542862 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -6,7 +6,6 @@ #include "FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp" #include - #include #include @@ -25,13 +24,28 @@ DetumbleManager ::~DetumbleManager() {} // ---------------------------------------------------------------------- void DetumbleManager ::run_handler(FwIndexType portNum, U32 context) { - // Read from Lsm6dsoManager - this->accelerationGet_out(0); - this->angularVelocityGet_out(0); - this->temperatureGet_out(0); - - // Read from Lis2mdlManager - this->magneticFieldGet_out(0); + U32 currTime = this->timeGet_out(0); + + if (this->paramGet_DETUMBLE_RUNNING()) { + // Check if we've hit the max time detumble can run + if (currTime - this->paramGet_START_TIME() <= this->paramGet_MAX_TIME()) { + bool res = this->executeControlStep(); + if (!res) { + // Log some error + continue; + } + } else { + // Max iterations reached, disable detumble for now + this->paramSet_DETUMBLE_RUNNING(false); + this->paramSet_LAST_COMPLETED(currTime); + } + } else { + // Check if the cooldown has ended, and start if so. + if (currTime - this->paramGet_LAST_COMPLETED() >= this->paramGet_COOLDOWN()) { + this->paramSet_DETUMBLE_RUNNING(true); + this->paramSet_START_TIME(currTime); + } + } } bool DetumbleManager::executeControlStep() { @@ -69,7 +83,7 @@ void DetumbleManager::setDipoleMoment(Drv::DipoleMoment dpMoment) { F64 y2 = -limited_y; F64 z1 = limited_z; - // Apply values to magnetorquers here + this->magnetorquersSet_out(0, {x1, x2, y1, y2, z1}); } } // namespace Components diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp index 04cbcce7..8a6a6fed 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp @@ -1,8 +1,36 @@ module Components { @ Detumble Manager Component for F Prime FSW framework. passive component DetumbleManager { + + @ Parameter for storing if detumble is currently running + param DETUMBLE_RUNNING: bool default true \ + id 1 + + @ Parameter for storing the rotational threshold for detumble to be enabled (default 12 deg/s) + param ROTATIONAL_THRESHOLD: F32 default 12.0 \ + id 2 + + @ Parameter for storing the max amount of time an iteration can run + param MAX_TIME: U32 default 10800 \ + id 3 + + @ Parameter for storing the cooldown after a detumble run finishes (in seconds) + param COOLDOWN: U32 default 600 \ + id 4 + + @ Parameter for storing the RTC time that a detumble run was completed/interrupted + param LAST_COMPLETED: U32 default 0 \ + id 5 + + param START_TIME: U32 default 0 \ + id 6 + + @ Run loop sync input port run: Svc.Sched + @ Port for getting the current time from the RTC + output port timeGet: Drv.TimeGet + @ Port for sending accelerationGet calls to the LSM6DSO Driver output port accelerationGet: Drv.AccelerationGet @@ -18,6 +46,9 @@ module Components { @ Port for sending dipoleMomentGet calls to the BDotDetumble Component output port dipoleMomentGet: Drv.DipoleMomentGet + @ Port for sending SetMagnetorquers calls to the MagnetorquerManager Component + output port magnetorquersSet: Drv.SetMagnetorquers + ############################################################################### # Standard AC Ports: Required for Channels, Events, Commands, and Parameters # ############################################################################### diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp index bc1484ee..26f685d7 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp @@ -6,10 +6,10 @@ #ifndef Components_DetumbleManager_HPP #define Components_DetumbleManager_HPP -#include "FprimeZephyrReference/Components/DetumbleManager/DetumbleManagerComponentAc.hpp" - #include +#include "FprimeZephyrReference/Components/DetumbleManager/DetumbleManagerComponentAc.hpp" + namespace Components { class DetumbleManager final : public DetumbleManagerComponentBase { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 6db524ae..bc9f68b8 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -137,6 +137,7 @@ module ReferenceDeployment { rateGroup10Hz.RateGroupMemberOut[0] -> comDriver.schedIn rateGroup10Hz.RateGroupMemberOut[1] -> ComCcsdsUart.aggregator.timeout rateGroup10Hz.RateGroupMemberOut[2] -> ComCcsds.aggregator.timeout + rateGroup10Hz.RateGroupMemberOut[3] -> DetumbleManager.run # Slow rate (1Hz) rate group rateGroupDriver.CycleOut[Ports_RateGroups.rateGroup1Hz] -> rateGroup1Hz.CycleIn @@ -145,7 +146,6 @@ module ReferenceDeployment { rateGroup1Hz.RateGroupMemberOut[2] -> ComCcsds.commsBufferManager.schedIn rateGroup1Hz.RateGroupMemberOut[3] -> CdhCore.tlmSend.Run rateGroup1Hz.RateGroupMemberOut[4] -> watchdog.run - rateGroup1Hz.RateGroupMemberOut[5] -> DetumbleManager.run rateGroup1Hz.RateGroupMemberOut[6] -> comDelay.run rateGroup1Hz.RateGroupMemberOut[7] -> burnwire.schedIn rateGroup1Hz.RateGroupMemberOut[8] -> antennaDeployer.schedIn @@ -170,10 +170,12 @@ module ReferenceDeployment { } connections DetumbleManager { + DetumbleManager.timeGet -> rtcManager.timeGetPort DetumbleManager.accelerationGet -> lsm6dsoManager.accelerationGet DetumbleManager.angularVelocityGet -> lsm6dsoManager.angularVelocityGet DetumbleManager.magneticFieldGet -> lis2mdlManager.magneticFieldGet DetumbleManager.temperatureGet -> lsm6dsoManager.temperatureGet + DetumbleManager.magnetorquersSet -> magnetorquerManager.SetMagnetorquers } connections sysPowerMonitor { From d8ab348c2d1d55081af2d78357d2f7c0462c8d66 Mon Sep 17 00:00:00 2001 From: hrfarmer Date: Wed, 12 Nov 2025 19:32:34 -0600 Subject: [PATCH 38/38] runtime loop draft 2 --- .../DetumbleManager/DetumbleManager.cpp | 56 ++++++++++++++----- .../DetumbleManager/DetumbleManager.fpp | 38 +++++++------ .../DetumbleManager/DetumbleManager.hpp | 7 ++- .../Components/Drv/BDotDetumble/docs/sdd.md | 2 +- .../ReferenceDeployment/Top/topology.fpp | 1 - 5 files changed, 70 insertions(+), 34 deletions(-) diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp index 45542862..fe31268d 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.cpp @@ -24,26 +24,46 @@ DetumbleManager ::~DetumbleManager() {} // ---------------------------------------------------------------------- void DetumbleManager ::run_handler(FwIndexType portNum, U32 context) { - U32 currTime = this->timeGet_out(0); + U32 currTime = this->getTime().getSeconds(); - if (this->paramGet_DETUMBLE_RUNNING()) { + // I'm not checking the value of isValid for paramGet calls since all of the parameters have a + // default value, but maybe there should still be specific logging for if the default parameter + // was used and retrieval failed. + Fw::ParamValid isValid; + + if (this->detumbleRunning) { // Check if we've hit the max time detumble can run - if (currTime - this->paramGet_START_TIME() <= this->paramGet_MAX_TIME()) { + U32 maxTime = this->paramGet_MAX_TIME(isValid); + if (currTime - this->startTime <= maxTime) { bool res = this->executeControlStep(); if (!res) { // Log some error - continue; + } + + this->iterations++; + + // Every 10 iterations (every second), check if the rotation per second is less than 12 degrees + if (this->iterations % 10 == 0) { + Drv::AngularVelocity angVel = this->angularVelocityGet_out(0); + F64 rotationRate = this->getAngularVelocityMagnitude(angVel); + + F64 threshold = this->paramGet_ROTATIONAL_THRESHOLD(isValid); + if (rotationRate < threshold) { + // Rotation is below threshold - can stop detumbling + this->detumbleRunning = false; + this->lastCompleted = currTime; + } } } else { - // Max iterations reached, disable detumble for now - this->paramSet_DETUMBLE_RUNNING(false); - this->paramSet_LAST_COMPLETED(currTime); + // Max time reached, disable detumble for now + this->detumbleRunning = false; + this->lastCompleted = currTime; } } else { // Check if the cooldown has ended, and start if so. - if (currTime - this->paramGet_LAST_COMPLETED() >= this->paramGet_COOLDOWN()) { - this->paramSet_DETUMBLE_RUNNING(true); - this->paramSet_START_TIME(currTime); + if (currTime - this->lastCompleted >= this->paramGet_COOLDOWN(isValid)) { + this->detumbleRunning = true; + this->startTime = currTime; } } } @@ -61,7 +81,6 @@ bool DetumbleManager::executeControlStep() { } this->prevMgField = mgField; - this->setDipoleMoment(dpMoment); return true; @@ -73,9 +92,9 @@ void DetumbleManager::setDipoleMoment(Drv::DipoleMoment dpMoment) { F64 unlimited_z = dpMoment.get_z() / (this->COIL_NUM_TURNS_Z * this->COIL_AREA_Z); // Limit current for each axis to max coil current - F64 limited_x = std::min(std::fabs(unlimited_x), this->COIL_MAX_CURRENT_X_Y) * (unlimited_x >= 0 ? 1.0f : -1.0f); - F64 limited_y = std::min(std::fabs(unlimited_y), this->COIL_MAX_CURRENT_X_Y) * (unlimited_y >= 0 ? 1.0f : -1.0f); - F64 limited_z = std::min(std::fabs(unlimited_z), this->COIL_MAX_CURRENT_Z) * (unlimited_z >= 0 ? 1.0f : -1.0f); + F64 limited_x = std::fmin(std::fabs(unlimited_x), this->COIL_MAX_CURRENT_X_Y) * (unlimited_x >= 0 ? 1.0 : -1.0); + F64 limited_y = std::fmin(std::fabs(unlimited_y), this->COIL_MAX_CURRENT_X_Y) * (unlimited_y >= 0 ? 1.0 : -1.0); + F64 limited_z = std::fmin(std::fabs(unlimited_z), this->COIL_MAX_CURRENT_Z) * (unlimited_z >= 0 ? 1.0 : -1.0); F64 x1 = limited_x; F64 x2 = -limited_x; @@ -86,4 +105,13 @@ void DetumbleManager::setDipoleMoment(Drv::DipoleMoment dpMoment) { this->magnetorquersSet_out(0, {x1, x2, y1, y2, z1}); } +F64 DetumbleManager::getAngularVelocityMagnitude(const Drv::AngularVelocity& angVel) { + // Calculate magnitude in rad/s + F64 magRadPerSec = + std::sqrt(angVel.get_x() * angVel.get_x() + angVel.get_y() * angVel.get_y() + angVel.get_z() * angVel.get_z()); + + // Convert rad/s to deg/s + return magRadPerSec * 180.0 / this->PI; +} + } // namespace Components diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp index 8a6a6fed..77a751a9 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.fpp @@ -2,35 +2,21 @@ module Components { @ Detumble Manager Component for F Prime FSW framework. passive component DetumbleManager { - @ Parameter for storing if detumble is currently running - param DETUMBLE_RUNNING: bool default true \ - id 1 - @ Parameter for storing the rotational threshold for detumble to be enabled (default 12 deg/s) param ROTATIONAL_THRESHOLD: F32 default 12.0 \ - id 2 + id 1 @ Parameter for storing the max amount of time an iteration can run param MAX_TIME: U32 default 10800 \ - id 3 + id 2 @ Parameter for storing the cooldown after a detumble run finishes (in seconds) param COOLDOWN: U32 default 600 \ - id 4 - - @ Parameter for storing the RTC time that a detumble run was completed/interrupted - param LAST_COMPLETED: U32 default 0 \ - id 5 - - param START_TIME: U32 default 0 \ - id 6 + id 3 @ Run loop sync input port run: Svc.Sched - @ Port for getting the current time from the RTC - output port timeGet: Drv.TimeGet - @ Port for sending accelerationGet calls to the LSM6DSO Driver output port accelerationGet: Drv.AccelerationGet @@ -54,5 +40,23 @@ module Components { ############################################################################### @ Port for requesting the current time time get port timeCaller + + @ Port for getting parameters + param get port prmGetOut + + @ Port for setting parameters + param set port prmSetOut + + @ Port for sending command registrations + command reg port cmdRegOut + + @ Port for receiving commands + command recv port cmdIn + + @ Port for sending command responses + command resp port cmdResponseOut + + + } } diff --git a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp index 26f685d7..692398c8 100644 --- a/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp +++ b/FprimeZephyrReference/Components/DetumbleManager/DetumbleManager.hpp @@ -49,16 +49,21 @@ class DetumbleManager final : public DetumbleManagerComponentBase { F64 COIL_MAX_CURRENT_X_Y = this->COIL_VOLTAGE / this->COIL_RESISTANCE_X_Y; I64 COIL_NUM_TURNS_Z = 153; F64 COIL_DIAMETER_Z = 0.05755; - F64 COIL_AREA_Z = this->PI * powf(this->COIL_DIAMETER_Z / 2, 2.0); + F64 COIL_AREA_Z = this->PI * pow(this->COIL_DIAMETER_Z / 2, 2.0); F64 COIL_RESISTANCE_Z = 248.8; F64 COIL_MAX_CURRENT_Z = this->COIL_VOLTAGE / this->COIL_RESISTANCE_Z; // Variables Drv::MagneticField prevMgField = Drv::MagneticField(0.0, 0.0, 0.0, -1); + int iterations = 0; + U32 startTime = 0; + U32 lastCompleted = 0; + bool detumbleRunning = true; // Functions bool executeControlStep(); void setDipoleMoment(Drv::DipoleMoment dpMoment); + F64 getAngularVelocityMagnitude(const Drv::AngularVelocity& angVel); }; } // namespace Components diff --git a/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md b/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md index 093f1cae..528b8114 100644 --- a/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md +++ b/FprimeZephyrReference/Components/Drv/BDotDetumble/docs/sdd.md @@ -63,4 +63,4 @@ Add requirements in the chart below ## Change Log | Date | Description | |---|---| -|---| Initial Draft | \ No newline at end of file +|---| Initial Draft | diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index bc9f68b8..02a4ea14 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -170,7 +170,6 @@ module ReferenceDeployment { } connections DetumbleManager { - DetumbleManager.timeGet -> rtcManager.timeGetPort DetumbleManager.accelerationGet -> lsm6dsoManager.accelerationGet DetumbleManager.angularVelocityGet -> lsm6dsoManager.angularVelocityGet DetumbleManager.magneticFieldGet -> lis2mdlManager.magneticFieldGet