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..fe720b16 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.cpp @@ -0,0 +1,71 @@ +// ====================================================================== +// \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) {} + +MagnetorquerManager ::~MagnetorquerManager() {} + +// ---------------------------------------------------------------------- +// Helper methods +// ---------------------------------------------------------------------- + +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..4) + if (faceIdx >= 5) { + this->log_WARNING_LO_InvalidFaceIndex(); + return; + } + + const struct device* dev = this->m_devices[faceIdx]; + if (!device_is_ready(dev)) { + this->log_WARNING_HI_DeviceNotReady(); + return; + } + + drv2605_haptic_config(dev, DRV2605_HAPTICS_SOURCE_ROM, (union drv2605_config_data*)&this->rom); +} + +void MagnetorquerManager ::START_PLAYBACK_TEST2_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, U8 faceIdx) { + // Validate face index (0..4) + if (faceIdx >= 5) { + this->log_WARNING_LO_InvalidFaceIndex(); + 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(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 new file mode 100644 index 00000000..39811975 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.fpp @@ -0,0 +1,60 @@ +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 { + + @ Event for reporting DRV2605 not ready error + event DeviceNotReady() severity warning high format "DRV2605 device not ready" throttle 5 + + @ Event to report an invalid face index passed in + event InvalidFaceIndex() severity warning low format "The faceIdx should be between 0-4" + + @ 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) + + @ 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) + + @ Input port to set magnetorquer values + sync input port SetMagnetorquers: SetMagnetorquers + + ############################################################################### + # 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..ce81ad90 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/MagnetorquerManager.hpp @@ -0,0 +1,50 @@ +// ====================================================================== +// \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(); + + //! 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[5]); + + private: + //! 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 + +#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..52138636 --- /dev/null +++ b/FprimeZephyrReference/Components/Drv/MagnetorquerManager/docs/sdd.md @@ -0,0 +1,134 @@ +# Drv::MagnetorquerManager + +The Magnetorquer Manager component interfaces with the five DRV2605 devices on a PROVES CubeSat to control the current of the magnetorquers. + +## Usage Examples + +This component is designed to be used by the detumble service to be able to detumble the cubesat when launched. + +### Diagrams + +```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 + +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 + +```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 | +| ---------------- | ------------------------------------------------------------------------------------------- | +| SetMagnetorquers | Input port that takes in an array (I32[5]) and applies each value to the corresponding face | + +## Sequence Diagrams + +### 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 | +| -------------------- | ------------------------------------------------------------------------------------------------ | +| 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. | + +## Events + +| 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 | +| ---------- | ------------- | +| 11/11/2025 | Initial Draft | diff --git a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md index 51d9dec6..be6aa23c 100644 --- a/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md +++ b/FprimeZephyrReference/Components/LoadSwitch/docs/sdd.md @@ -18,36 +18,35 @@ async `Reset` input which toggles the switch (off, short delay, on). ### Commands -| Name | Description | Implementation notes | -|---|---|---| -| TURN_ON | Turn on the associated power rail | `TURN_ON_cmdHandler` sets the gpio via `gpioSet_out(0, Fw::Logic::HIGH)`, emits `StatusChanged` (ON), updates `IsOn` telemetry, replies OK. | +| Name | Description | Implementation notes | +| -------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| TURN_ON | Turn on the associated power rail | `TURN_ON_cmdHandler` sets the gpio via `gpioSet_out(0, Fw::Logic::HIGH)`, emits `StatusChanged` (ON), updates `IsOn` telemetry, replies OK. | | TURN_OFF | Turn off the associated power rail | `TURN_OFF_cmdHandler` sets the gpio via `gpioSet_out(0, Fw::Logic::LOW)`, emits `StatusChanged` (OFF), updates `IsOn` telemetry, replies OK. | ### Telemetry -| Name | Type | Description | -|---|---:|---| +| Name | Type | Description | +| ---- | ----: | ------------------------------------------------------------------ | | IsOn | Fw.On | Current power state; written after commands and on Reset handling. | ### Events -| Name | Severity | ID | Format | -|---|---|---:|---| -| StatusChanged | activity high | 1 | "Load switch state changed to {}" | +| Name | Severity | ID | Format | +| ------------- | ------------- | --: | --------------------------------- | +| StatusChanged | activity high | 1 | "Load switch state changed to {}" | The component logs the `StatusChanged` event whenever the switch transitions due to a command or a Reset. ### Ports -| Port name | Direction | Port type | Notes | -|---|---|---|---| -| gpioSet | output | Drv.GpioWrite | Used to write the physical GPIO. Implementation always uses index 0 (`gpioSet_out(0, ...)`). | -| Reset | input (async) | Fw.Signal | Causes the component to perform a hardware reset sequence: LOW -> wait 100ms -> HIGH. | - +| Port name | Direction | Port type | Notes | +| --------- | ------------- | ------------- | -------------------------------------------------------------------------------------------- | +| gpioSet | output | Drv.GpioWrite | Used to write the physical GPIO. Implementation always uses index 0 (`gpioSet_out(0, ...)`). | +| Reset | input (async) | Fw.Signal | Causes the component to perform a hardware reset sequence: LOW -> wait 100ms -> HIGH. | ## Change Log -| Date | Description | -|---|---| -| 10-22-2025 | Sarah, Kevin, and MoMata's first commit | +| Date | Description | +| ---------- | ---------------------------------------------------------------------------------------------------------------------- | +| 10-22-2025 | Sarah, Kevin, and MoMata's first commit | | 11-07-2025 | Updated SDD to match implementation in `LoadSwitch.cpp/.hpp/.fpp` (commands, telemetry, event, ports, reset behavior). | diff --git a/FprimeZephyrReference/ReferenceDeployment/Main.cpp b/FprimeZephyrReference/ReferenceDeployment/Main.cpp index 6b5187a8..2cd31ae6 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Main.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Main.cpp @@ -17,6 +17,13 @@ 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)); +// Magnetorquer devices +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)); + int main(int argc, char* argv[]) { // ** DO NOT REMOVE **// // @@ -32,6 +39,11 @@ int main(int argc, char* argv[]) { inputs.uartDevice = serial; inputs.lsm6dsoDevice = lsm6dso; inputs.lis2mdlDevice = lis2mdl; + 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.baudRate = 115200; // Setup, cycle, and teardown topology diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp index 8e2b3d5d..3f39dc33 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopology.cpp @@ -112,6 +112,7 @@ void setupTopology(const TopologyState& state) { lis2mdlManager.configure(state.lis2mdlDevice); ina219SysManager.configure(state.ina219SysDevice); ina219SolManager.configure(state.ina219SolDevice); + magnetorquerManager.configure(state.drv2605Devices); } void startRateGroups() { diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp index fbd19532..da49f1dc 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/ReferenceDeploymentTopologyDefs.hpp @@ -79,6 +79,7 @@ struct TopologyState { const device* ina219SolDevice; //!< device path for solar panel ina219 const device* lsm6dsoDevice; //!< LSM6DSO device path for accelerometer/gyroscope const device* lis2mdlDevice; //!< LIS2MDL device path for magnetometer + const device* drv2605Devices[5]; //!< Array of DRV2605 devices (5) }; namespace PingEntries = ::PingEntries; diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp index 0a15aa7d..6c27bc2a 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/instances.fpp @@ -135,4 +135,5 @@ module ReferenceDeployment { instance startupManager: Components.StartupManager base id 0x1003F000 + instance magnetorquerManager: Drv.MagnetorquerManager base id 0x10040000 } diff --git a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp index 225bfcd3..aae6d744 100644 --- a/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp +++ b/FprimeZephyrReference/ReferenceDeployment/Top/topology.fpp @@ -66,6 +66,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 87746b0b..f4c27bdc 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,180 @@ zephyr_udc0: &usbd { lsb-microamp = <61>; 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>; + + 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>; + }; + + face4_drv2605: drv2605@5a { + compatible = "ti,drv2605"; + status = "okay"; + reg = <0x5a>; + 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>; + }; + }; + + 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>; + }; + }; + }; }; diff --git a/prj.conf b/prj.conf index a422ba52..72461cee 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 @@ -36,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=20 +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' @@ -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