HF-TMC51x0 Driver (TMC5130 & TMC5160) 0.1.0-dev
Hardware Agnostic C++ Driver for the TMC51x0 (TMC5130 & TMC5160)
Loading...
Searching...
No Matches
tmc51x0_daisy_chain.hpp
Go to the documentation of this file.
1
6#pragma once
7#include <array>
8#include <cstdint>
9#include <optional>
10
11#include "../tmc51x0.hpp"
13
14namespace tmc51x0 {
15
115template <typename CommType, size_t MaxDevices = 8> class TMC51x0DaisyChain {
116public:
128 explicit TMC51x0DaisyChain(CommType &comm, uint8_t num_onboard_devices,
129 uint32_t f_clk = ClockFreq::DEFAULT_F_CLK) noexcept
130 : comm_(comm), num_onboard_devices_(num_onboard_devices),
131 num_active_devices_(num_onboard_devices), f_clk_(f_clk) {
132 // Validate num_onboard_devices
133 if (num_onboard_devices == 0 || num_onboard_devices > MaxDevices) {
136 }
137
138 // Create onboard TMC51x0 instances, one per device
139 // Each device has its position (0, 1, 2, ...) set in constructor
140 for (uint8_t i = 0; i < num_onboard_devices_; ++i) {
141 drivers_[i] = std::make_optional<TMC51x0<CommType>>(comm_, f_clk_, i);
142 }
143
144 // Initialize extra device slots as empty
145 for (size_t i = num_onboard_devices_; i < MaxDevices; ++i) {
146 drivers_[i] = std::nullopt;
147 }
148
149 // CRITICAL: Set the total chain length on the SpiCommInterface
150 // This enables proper response extraction using datasheet formula
151 // 40ยท(n-k+1)
153 }
154
159 [[nodiscard]] uint8_t GetNumOnboardDevices() const noexcept {
161 }
162
167 [[nodiscard]] uint8_t GetNumActiveDevices() const noexcept {
168 return num_active_devices_;
169 }
170
175 [[nodiscard]] constexpr size_t GetMaxCapacity() const noexcept {
176 return MaxDevices;
177 }
178
184 [[nodiscard]] bool IsDeviceActive(uint8_t index) const noexcept {
185 if (index >= MaxDevices) {
187 }
188 return drivers_[index].has_value();
189 }
190
208 Result<void> AddDevice(uint8_t position) noexcept {
209 // Validate position
210 if (position < num_onboard_devices_ || position >= MaxDevices) {
212 }
213
214 // Check if slot is already occupied
215 if (drivers_[position].has_value()) {
217 }
218
219 // Enforce sequential positioning: cannot skip positions
220 // All positions before this one (starting from num_onboard_devices) must be
221 // filled
222 for (uint8_t i = num_onboard_devices_; i < position; ++i) {
223 if (!drivers_[i].has_value()) {
224 return Result<void>(
225 ErrorCode::INVALID_STATE); // Cannot skip positions in daisy chain
226 }
227 }
228
229 // Create device instance at specified position
230 drivers_[position] =
231 std::make_optional<TMC51x0<CommType>>(comm_, f_clk_, position);
233
234 // Update chain length on SpiCommInterface
236
237 return Result<void>();
238 }
239
256 Result<void> RemoveDevice(uint8_t position) noexcept {
257 // Cannot remove onboard devices
258 if (position < num_onboard_devices_) {
260 }
261
262 // Validate position
263 if (position >= MaxDevices) {
265 }
266
267 // Check if slot is actually active
268 if (!drivers_[position].has_value()) {
270 }
271
272 // Enforce sequential removal: can only remove from the end
273 // Check if there are any devices after this position
274 for (size_t i = position + 1; i < MaxDevices; ++i) {
275 if (drivers_[i].has_value()) {
276 return Result<void>(
277 ErrorCode::INVALID_STATE); // Cannot remove device in the middle of
278 // the chain
279 }
280 }
281
282 // Remove device
283 drivers_[position] = std::nullopt;
285
286 // Update chain length on SpiCommInterface
288
289 return Result<void>();
290 }
291
301 [[nodiscard]] TMC51x0<CommType> &operator[](uint8_t index) noexcept {
302 return drivers_[index].value();
303 }
304
310 [[nodiscard]] const TMC51x0<CommType> &
311 operator[](uint8_t index) const noexcept {
312 return drivers_[index].value();
313 }
314
321 InitializeAll(const DriverConfig &config = DriverConfig()) noexcept {
322 for (size_t i = 0; i < MaxDevices; ++i) {
323 if (drivers_[i].has_value()) {
324 auto result = drivers_[i]->Initialize(config);
325 if (!result) {
326 return result; // Return first error
327 }
328 }
329 }
330 return Result<void>();
331 }
332
333private:
341 void UpdateChainLength() noexcept {
342 // Find the highest active device position
343 uint8_t max_position = 0;
344 for (size_t i = 0; i < MaxDevices; ++i) {
345 if (drivers_[i].has_value()) {
346 max_position = static_cast<uint8_t>(i);
347 }
348 }
349
350 // Total chain length is max_position + 1 (0-indexed to 1-indexed)
351 uint8_t total_length = max_position + 1;
352 comm_.SetDaisyChainLength(total_length);
353 }
354
355 CommType &comm_;
357 uint8_t
359 uint32_t f_clk_;
360 std::array<std::optional<TMC51x0<CommType>>, MaxDevices>
362};
363
364} // namespace tmc51x0
Result type for operations that return a value.
Definition tmc51x0_result.hpp:90
High-level manager for multiple TMC51x0 drivers in a daisy-chain configuration.
Definition tmc51x0_daisy_chain.hpp:115
std::array< std::optional< TMC51x0< CommType > >, MaxDevices > drivers_
TMC51x0 driver instances (optional for dynamic devices)
Definition tmc51x0_daisy_chain.hpp:361
Result< void > RemoveDevice(uint8_t position) noexcept
Remove an extra device at the specified position.
Definition tmc51x0_daisy_chain.hpp:256
uint8_t GetNumActiveDevices() const noexcept
Get the total number of active devices (onboard + extra)
Definition tmc51x0_daisy_chain.hpp:167
void UpdateChainLength() noexcept
Update the chain length on SpiCommInterface.
Definition tmc51x0_daisy_chain.hpp:341
uint8_t num_onboard_devices_
Number of onboard devices (fixed)
Definition tmc51x0_daisy_chain.hpp:356
uint8_t num_active_devices_
Total number of active devices (onboard + extra)
Definition tmc51x0_daisy_chain.hpp:358
const TMC51x0< CommType > & operator[](uint8_t index) const noexcept
Const access to individual TMC51x0 driver by index.
Definition tmc51x0_daisy_chain.hpp:311
Result< void > AddDevice(uint8_t position) noexcept
Add an extra device at the specified position.
Definition tmc51x0_daisy_chain.hpp:208
TMC51x0DaisyChain(CommType &comm, uint8_t num_onboard_devices, uint32_t f_clk=ClockFreq::DEFAULT_F_CLK) noexcept
Construct a daisy-chain manager.
Definition tmc51x0_daisy_chain.hpp:128
uint32_t f_clk_
TMC51x0 clock frequency.
Definition tmc51x0_daisy_chain.hpp:359
TMC51x0< CommType > & operator[](uint8_t index) noexcept
Access individual TMC51x0 driver by index.
Definition tmc51x0_daisy_chain.hpp:301
CommType & comm_
Shared SPI communication interface.
Definition tmc51x0_daisy_chain.hpp:355
bool IsDeviceActive(uint8_t index) const noexcept
Check if a device slot is active (has a device instance)
Definition tmc51x0_daisy_chain.hpp:184
uint8_t GetNumOnboardDevices() const noexcept
Get the number of onboard devices (fixed at construction)
Definition tmc51x0_daisy_chain.hpp:159
constexpr size_t GetMaxCapacity() const noexcept
Get the maximum capacity (onboard + extra devices)
Definition tmc51x0_daisy_chain.hpp:175
Result< void > InitializeAll(const DriverConfig &config=DriverConfig()) noexcept
Initialize all active devices with the same configuration.
Definition tmc51x0_daisy_chain.hpp:321
Main class representing a TMC51x0 stepper motor driver (TMC5130 & TMC5160)
Definition tmc51x0.hpp:119
constexpr uint32_t DEFAULT_F_CLK
Typical internal clock frequency in Hz (12 MHz)
Definition tmc51x0_types.hpp:16
Definition tmc51x0_register_defs.cpp:10
@ INVALID_STATE
Operation not valid in current state.
@ INVALID_VALUE
Invalid parameter value.
Driver initialization configuration structure.
Definition tmc51x0_types.hpp:2870
Main TMC51x0 stepper motor driver interface and subsystem classes.
Communication interfaces for TMC51x0 stepper motor driver using SPI and UART.