TMC5160 Driver
API reference
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"
12#include "../tmc51x0_comm_interface.hpp"
13
14namespace tmc51x0 {
15
115template <typename CommType, size_t MaxDevices = 8> class TMC51x0DaisyChain {
116public:
129 explicit TMC51x0DaisyChain(CommType &comm, uint8_t num_onboard_devices,
130 uint32_t f_clk = ClockFreq::DEFAULT_F_CLK) noexcept
131 : comm_(comm), num_onboard_devices_(num_onboard_devices),
132 num_active_devices_(num_onboard_devices) {
133 (void)f_clk;
134 // Validate num_onboard_devices
135 if (num_onboard_devices == 0 || num_onboard_devices > MaxDevices) {
138 }
139
140 // Create onboard TMC51x0 instances, one per device
141 // Each device has its position (0, 1, 2, ...) set in constructor
142 for (uint8_t i = 0; i < num_onboard_devices_; ++i) {
143 drivers_[i].emplace(comm_, i); // TMC51x0(comm, daisy_chain_position)
144 }
145
146 // Initialize extra device slots as empty
147 for (size_t i = num_onboard_devices_; i < MaxDevices; ++i) {
148 drivers_[i].reset();
149 }
150
151 // CRITICAL: Set the total chain length on the SpiCommInterface
152 // This enables proper response extraction using datasheet formula
153 // 40ยท(n-k+1)
155 }
156
161 [[nodiscard]] uint8_t GetNumOnboardDevices() const noexcept {
163 }
164
169 [[nodiscard]] uint8_t GetNumActiveDevices() const noexcept {
170 return num_active_devices_;
171 }
172
177 [[nodiscard]] constexpr size_t GetMaxCapacity() const noexcept {
178 return MaxDevices;
179 }
180
186 [[nodiscard]] bool IsDeviceActive(uint8_t index) const noexcept {
187 if (index >= MaxDevices) {
188 return false;
189 }
190 return drivers_[index].has_value();
191 }
192
210 Result<void> AddDevice(uint8_t position) noexcept {
211 // Validate position
212 if (position < num_onboard_devices_ || position >= MaxDevices) {
214 }
215
216 // Check if slot is already occupied
217 if (drivers_[position].has_value()) {
219 }
220
221 // Enforce sequential positioning: cannot skip positions
222 // All positions before this one (starting from num_onboard_devices) must be
223 // filled
224 for (uint8_t i = num_onboard_devices_; i < position; ++i) {
225 if (!drivers_[i].has_value()) {
226 return Result<void>(
227 ErrorCode::INVALID_STATE); // Cannot skip positions in daisy chain
228 }
229 }
230
231 // Create device instance at specified position
232 drivers_[position].emplace(comm_, position);
234
235 // Update chain length on SpiCommInterface
237
238 return Result<void>();
239 }
240
257 Result<void> RemoveDevice(uint8_t position) noexcept {
258 // Cannot remove onboard devices
259 if (position < num_onboard_devices_) {
261 }
262
263 // Validate position
264 if (position >= MaxDevices) {
266 }
267
268 // Check if slot is actually active
269 if (!drivers_[position].has_value()) {
271 }
272
273 // Enforce sequential removal: can only remove from the end
274 // Check if there are any devices after this position
275 for (size_t i = position + 1; i < MaxDevices; ++i) {
276 if (drivers_[i].has_value()) {
277 return Result<void>(
278 ErrorCode::INVALID_STATE); // Cannot remove device in the middle of
279 // the chain
280 }
281 }
282
283 // Remove device
284 drivers_[position].reset();
286
287 // Update chain length on SpiCommInterface
289
290 return Result<void>();
291 }
292
302 [[nodiscard]] TMC51x0<CommType> &operator[](uint8_t index) noexcept {
303 return drivers_[index].value();
304 }
305
311 [[nodiscard]] const TMC51x0<CommType> &
312 operator[](uint8_t index) const noexcept {
313 return drivers_[index].value();
314 }
315
322 InitializeAll(const DriverConfig &config = DriverConfig()) noexcept {
323 for (size_t i = 0; i < MaxDevices; ++i) {
324 if (drivers_[i].has_value()) {
325 auto result = drivers_[i]->Initialize(config);
326 if (!result) {
327 return result; // Return first error
328 }
329 }
330 }
331 return Result<void>();
332 }
333
334private:
342 void UpdateChainLength() noexcept {
343 // Find the highest active device position
344 uint8_t max_position = 0;
345 for (size_t i = 0; i < MaxDevices; ++i) {
346 if (drivers_[i].has_value()) {
347 max_position = static_cast<uint8_t>(i);
348 }
349 }
350
351 // Total chain length is max_position + 1 (0-indexed to 1-indexed)
352 uint8_t total_length = max_position + 1;
353 comm_.SetDaisyChainLength(total_length);
354 }
355
356 CommType &comm_;
358 uint8_t
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:257
uint8_t GetNumActiveDevices() const noexcept
Get the total number of active devices (onboard + extra)
Definition tmc51x0_daisy_chain.hpp:169
void UpdateChainLength() noexcept
Update the chain length on SpiCommInterface.
Definition tmc51x0_daisy_chain.hpp:342
uint8_t num_onboard_devices_
Number of onboard devices (fixed)
Definition tmc51x0_daisy_chain.hpp:357
uint8_t num_active_devices_
Total number of active devices (onboard + extra)
Definition tmc51x0_daisy_chain.hpp:359
const TMC51x0< CommType > & operator[](uint8_t index) const noexcept
Const access to individual TMC51x0 driver by index.
Definition tmc51x0_daisy_chain.hpp:312
Result< void > AddDevice(uint8_t position) noexcept
Add an extra device at the specified position.
Definition tmc51x0_daisy_chain.hpp:210
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:129
TMC51x0< CommType > & operator[](uint8_t index) noexcept
Access individual TMC51x0 driver by index.
Definition tmc51x0_daisy_chain.hpp:302
CommType & comm_
Shared SPI communication interface.
Definition tmc51x0_daisy_chain.hpp:356
bool IsDeviceActive(uint8_t index) const noexcept
Check if a device slot is active (has a device instance)
Definition tmc51x0_daisy_chain.hpp:186
uint8_t GetNumOnboardDevices() const noexcept
Get the number of onboard devices (fixed at construction)
Definition tmc51x0_daisy_chain.hpp:161
constexpr size_t GetMaxCapacity() const noexcept
Get the maximum capacity (onboard + extra devices)
Definition tmc51x0_daisy_chain.hpp:177
Result< void > InitializeAll(const DriverConfig &config=DriverConfig()) noexcept
Initialize all active devices with the same configuration.
Definition tmc51x0_daisy_chain.hpp:322
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_config_builder.hpp:75
@ INVALID_STATE
Operation not valid in current state.
@ INVALID_VALUE
Invalid parameter value.
Driver initialization configuration structure.
Definition tmc51x0_types.hpp:2870