HardFOC Vortex V1 HAL
Unified HAL API for the HardFOC Vortex motor-control platform (ESP32-C6, TMC9660)
Loading...
Searching...
No Matches
MotorController.h
Go to the documentation of this file.
1#ifndef COMPONENT_HANDLER_MOTOR_CONTROLLER_H_
2#define COMPONENT_HANDLER_MOTOR_CONTROLLER_H_
3
4#include "handlers/tmc9660/Tmc9660Handler.h"
6#include "RtosMutex.h"
8#include <span>
9#include <array>
10#include <atomic>
11#include <optional>
12
41 BaseGpio& rst;
42 BaseGpio& drv_en;
43 BaseGpio& faultn;
44 BaseGpio& wake;
45};
46
47//==============================================================================
48// MOTOR MECHANICAL FRAME (gearbox / output shaft mapping)
49//==============================================================================
50
76
82 bool invert_output{false};
83};
84
85//==============================================================================
86// DRIVE OBSERVABILITY TYPES (see api_helpers/Tmc9660DriveObservability.h)
87//==============================================================================
88
97
100 uint32_t batches{0};
101 uint32_t accesses{0};
102 uint32_t failed_accesses{0};
103 uint32_t last_batch_us{0};
104 uint32_t max_batch_us{0};
105};
106
107//==============================================================================
108// MOTOR CONTROLLER ERROR CODES
109//==============================================================================
110
131
139enum class Tmc9660HostSpiGateMode : uint8_t {
140 Disabled = 0,
142};
143
149constexpr const char* MotorErrorToString(MotorError error) noexcept {
150 switch (error) {
151 case MotorError::SUCCESS: return "Success";
152 case MotorError::NOT_INITIALIZED: return "Not initialized";
153 case MotorError::INITIALIZATION_FAILED: return "Initialization failed";
154 case MotorError::DEVICE_ALREADY_EXISTS: return "Device already exists";
155 case MotorError::DEVICE_NOT_FOUND: return "Device not found";
156 case MotorError::INVALID_DEVICE_INDEX: return "Invalid device index";
157 case MotorError::CANNOT_DELETE_ONBOARD: return "Cannot delete onboard device";
158 case MotorError::DEPENDENCY_NOT_READY: return "Dependency not ready";
159 case MotorError::COMMUNICATION_FAILED: return "Communication failed";
160 case MotorError::INVALID_PARAMETER: return "Invalid parameter";
161 case MotorError::HANDLER_CREATION_FAILED: return "Handler creation failed";
162 case MotorError::MUTEX_LOCK_FAILED: return "Mutex lock failed";
163 default: return "Unknown error";
164 }
165}
166
167//==============================================================================
168// MOTOR CONTROLLER DIAGNOSTICS
169//==============================================================================
170
193
208public:
209 static constexpr uint8_t MAX_TMC9660_DEVICES = 4;
210 static constexpr uint8_t ONBOARD_TMC9660_INDEX = 0;
211 static constexpr uint8_t EXTERNAL_DEVICE_1_INDEX = 2;
212 static constexpr uint8_t EXTERNAL_DEVICE_2_INDEX = 3;
213public:
218 static MotorController& GetInstance() noexcept;
219
220 //**************************************************************************//
221 //** DEVICE MANAGEMENT METHODS **//
222 //**************************************************************************//
223
228 bool EnsureInitialized() noexcept {
229 if (!initialized_.load(std::memory_order_acquire)) {
230 RtosUniqueLock<RtosMutex> lock(deviceMutex_);
231 if (!initialized_.load(std::memory_order_relaxed)) {
232 initialized_.store(Initialize(), std::memory_order_release);
233 }
234 }
235 return initialized_.load(std::memory_order_acquire);
236 }
237
242 inline bool IsInitialized() const noexcept { return initialized_.load(std::memory_order_acquire); }
243
248 bool Deinitialize() noexcept;
249
254 [[nodiscard]] MotorError GetLastError() const noexcept { return last_error_.load(std::memory_order_acquire); }
255
261 [[nodiscard]] MotorError GetSystemDiagnostics(MotorSystemDiagnostics& diagnostics) const noexcept;
262
273
278 [[nodiscard]] std::optional<tmc9660::CommMode> TryGetOnboardCommMode() const noexcept;
279
280 //**************************************************************************//
281 //** TMCL SPI TIMING (BENCH TUNING) **//
282 //**************************************************************************//
283
304 [[nodiscard]] MotorError SetTmclSpiTiming(const tmc9660::TmclSpiTiming& timing,
305 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
306
311 [[nodiscard]] MotorError GetTmclSpiTiming(tmc9660::TmclSpiTiming& timing,
312 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) const noexcept;
313
319 [[nodiscard]] MotorError GetTmclSpiStats(tmc9660::TmclSpiStats& stats,
320 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
321
326 [[nodiscard]] MotorError ResetTmclSpiStats(uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
327
328 //**************************************************************************//
329 //** DRIVE OBSERVABILITY: BATCH ACCESS, TELEMETRY, DIAGNOSTICS **//
330 //**************************************************************************//
331 // Every call below is one (or, for an image, a few) pipelined TMCL batch, sent through the
332 // handler's visitDriver() while this manager's device lock is held. A device that is not
333 // active returns DEVICE_NOT_FOUND; one whose bring-up did not succeed returns NOT_INITIALIZED
334 // (no call here starts a bootloader bring-up). COMMUNICATION_FAILED means at least one access
335 // was not answered REPLY_OK; per-element results are in the items / snapshot / result.
336
341 [[nodiscard]] MotorError ReadParameters(std::span<MotorParameterAccess> items,
342 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
343
345 [[nodiscard]] MotorError WriteParameters(std::span<MotorParameterAccess> items,
346 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
347
356 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
357
365 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
366
368 [[nodiscard]] MotorError ClearLatchedFaults(uint32_t general_errors, uint32_t gate_driver_errors,
369 uint32_t adc_status,
370 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
371
378 [[nodiscard]] MotorError ApplyParameterImage(std::span<const MotorParameterWrite> image,
379 const MotorApplyOptions& options, MotorApplyResult& result,
380 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
381
383 [[nodiscard]] MotorError GetAccessStats(MotorAccessStats& stats,
384 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) const noexcept;
385
387 void ResetAccessStats(uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
388
389 //**************************************************************************//
390 //** HANDLER AND DRIVER MANAGEMENT **//
391 //**************************************************************************//
392
399 Tmc9660Handler* handler(uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
400
419 template <typename Func>
420 auto visitDriver(Func&& func, uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept {
421 // Hold the device lock for the whole visit, so the slot cannot be deleted underneath it;
422 // the handler takes its own lock inside (order: deviceMutex_ -> handler mutex).
423 MutexLockGuard lock(deviceMutex_);
424 Tmc9660Handler* h = (deviceIndex < MAX_TMC9660_DEVICES && deviceActive_[deviceIndex] &&
425 tmcHandlers_[deviceIndex])
426 ? &*tmcHandlers_[deviceIndex]
427 : nullptr;
428 if (h) {
429 return h->visitDriver(std::forward<Func>(func));
430 }
431 // Driver not available - return default
432 using ReturnType = decltype(h->visitDriver(std::forward<Func>(func)));
433 if constexpr (std::is_void_v<ReturnType>) {
434 return;
435 } else {
436 return ReturnType{};
437 }
438 }
439
440 //**************************************************************************//
441 //** MECHANICAL FRAME / GEARBOX (Motor <-> Load) **//
442 //**************************************************************************//
443
456 bool setMotorMechanics(const MotorMechanics& mech,
457 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
458
463 [[nodiscard]] MotorMechanics getMotorMechanics(
464 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) const noexcept;
465
466 //**************************************************************************//
467 //** MOTOR-FRAME COMMANDS (rotor-side, raw chip frame) **//
468 //**************************************************************************//
469
478 bool setMotorVelocity(double value, ::tmc9660::units::VelocityUnit unit,
479 ::tmc9660::units::MotorContext const& ctx,
480 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
481
483 bool getMotorVelocity(double& out_value, ::tmc9660::units::VelocityUnit unit,
484 ::tmc9660::units::MotorContext const& ctx,
485 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
486
488 bool setMotorPosition(double value, ::tmc9660::units::PositionUnit unit,
489 ::tmc9660::units::MotorContext const& ctx,
490 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
491
493 bool getMotorPosition(double& out_value, ::tmc9660::units::PositionUnit unit,
494 ::tmc9660::units::MotorContext const& ctx,
495 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
496
497 //**************************************************************************//
498 //** LOAD-FRAME COMMANDS (output-shaft frame, gearbox-aware) **//
499 //**************************************************************************//
500
513 bool setLoadVelocity(double value, ::tmc9660::units::VelocityUnit unit,
514 ::tmc9660::units::MotorContext const& ctx,
515 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
516
518 bool getLoadVelocity(double& out_value, ::tmc9660::units::VelocityUnit unit,
519 ::tmc9660::units::MotorContext const& ctx,
520 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
521
523 bool setLoadPosition(double value, ::tmc9660::units::PositionUnit unit,
524 ::tmc9660::units::MotorContext const& ctx,
525 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
526
528 bool getLoadPosition(double& out_value, ::tmc9660::units::PositionUnit unit,
529 ::tmc9660::units::MotorContext const& ctx,
530 uint8_t deviceIndex = ONBOARD_TMC9660_INDEX) noexcept;
531
532 //**************************************************************************//
533 //** DEVICES MANAGEMENT METHODS **//
534 //**************************************************************************//
535
546 [[nodiscard]] MotorError CreateOnboardDevice(BaseSpi& spiInterface,
547 uint8_t address,
548 const Tmc9660ControlPins& pins,
549 const tmc9660::BootloaderConfig* bootCfg = nullptr) noexcept;
550
561 [[nodiscard]] MotorError CreateOnboardDevice(BaseUart& uartInterface,
562 uint8_t address,
563 const Tmc9660ControlPins& pins,
564 const tmc9660::BootloaderConfig* bootCfg = nullptr) noexcept;
565
576 [[nodiscard]] MotorError CreateExternalDevice(uint8_t csDeviceIndex,
577 SpiDeviceId spiDeviceId,
578 uint8_t address,
579 const Tmc9660ControlPins& pins,
580 const tmc9660::BootloaderConfig* bootCfg = nullptr) noexcept;
581
592 [[nodiscard]] MotorError CreateExternalDevice(uint8_t csDeviceIndex,
593 BaseUart& uartInterface,
594 uint8_t address,
595 const Tmc9660ControlPins& pins,
596 const tmc9660::BootloaderConfig* bootCfg = nullptr) noexcept;
597
604 [[nodiscard]] MotorError DeleteExternalDevice(uint8_t csDeviceIndex) noexcept;
605
611 uint8_t GetDeviceCount() const noexcept;
612
618 bool IsDeviceValid(uint8_t deviceIndex) const noexcept;
619
625 bool IsExternalSlotAvailable(uint8_t csDeviceIndex) const noexcept;
626
632 void GetActiveDeviceIndices(std::array<uint8_t, MAX_TMC9660_DEVICES>& out, size_t& count) const noexcept;
633
639 size_t InitializeAllDevices(std::array<bool, MAX_TMC9660_DEVICES>& results) noexcept;
640
645 void GetInitializationStatus(std::array<bool, MAX_TMC9660_DEVICES>& status) const noexcept;
646
651 void DumpStatistics() const noexcept;
652
653private:
655 ~MotorController() = default;
657 MotorController& operator=(const MotorController&) = delete;
658
668 bool Initialize();
669
675 bool IsExternalDeviceIndex(uint8_t csDeviceIndex) const noexcept;
676
682 void UpdateLastError(MotorError error, int deviceIndex = -1) noexcept;
683
685 void configureOnboardHostBusBeforeHandlerInitLocked(uint8_t device_index) noexcept;
686
689
691 void applyTmclSpiTimingLocked(uint8_t device_index) noexcept;
692
702 template <typename Fn>
703 MotorError withReadyDriverLocked(uint8_t device_index, Fn&& fn) noexcept {
704 if (device_index >= MAX_TMC9660_DEVICES || !deviceActive_[device_index] || !tmcHandlers_[device_index]) {
706 }
707 // Never start a bootloader bring-up from an observability call: only drivers that are up.
708 if (!tmcHandlers_[device_index]->IsDriverReady()) {
710 }
711 bool ran = false;
712 tmcHandlers_[device_index]->visitDriver([&](auto& driver) {
713 ran = true;
714 fn(driver);
715 });
717 }
718
720 void recordBatchLocked(uint8_t device_index, size_t accesses, size_t failed, uint32_t duration_us) noexcept;
721
722 template <typename Fn>
723 bool withSpiDriverLocked(uint8_t device_index, Fn&& fn) noexcept {
724 // A handler that is not up would run its full bootloader init inside visitDriver(); that
725 // belongs to the init paths (PCAL SPI mux first), so only ready drivers are touched here.
726 if (device_index >= MAX_TMC9660_DEVICES || !deviceActive_[device_index] || !tmcHandlers_[device_index] ||
727 !tmcHandlers_[device_index]->IsDriverReady()) {
728 return false;
729 }
730 bool ran = false;
731 tmcHandlers_[device_index]->visitDriver([&](auto& driver) {
732 if constexpr (std::is_same_v<std::decay_t<decltype(driver)>, Tmc9660Handler::SpiDriver>) {
733 ran = true;
734 fn(driver);
735 }
736 });
737 return ran;
738 }
739
741 std::array<std::optional<Tmc9660Handler>, MAX_TMC9660_DEVICES> tmcHandlers_;
742 std::array<bool, MAX_TMC9660_DEVICES> deviceInitialized_;
743 std::array<bool, MAX_TMC9660_DEVICES> deviceActive_;
744 std::array<std::atomic<uint32_t>, MAX_TMC9660_DEVICES> deviceErrorCounts_{};
745 std::array<MotorMechanics, MAX_TMC9660_DEVICES> mechanics_{};
746 std::array<tmc9660::TmclSpiTiming, MAX_TMC9660_DEVICES> tmclSpiTiming_{};
747 std::array<MotorAccessStats, MAX_TMC9660_DEVICES> accessStats_{};
748
750 std::atomic<bool> initialized_;
751 std::atomic<MotorError> last_error_{MotorError::SUCCESS};
752 mutable RtosMutex deviceMutex_;
753};
754
755//==============================================================================
756// CONVENIENCE
757//==============================================================================
758
763[[nodiscard]] inline MotorController& GetMotorController() noexcept {
765}
766
767#endif // COMPONENT_HANDLER_MOTOR_CONTROLLER_H_
Communication channels manager for the HardFOC Vortex V1 platform.
SpiDeviceId
SPI device identifiers for the Vortex V1 board.
Definition CommChannelsManager.h:113
constexpr const char * MotorErrorToString(MotorError error) noexcept
Convert MotorError to a human-readable string.
Definition MotorController.h:149
MotorController & GetMotorController() noexcept
Convenience accessor — equivalent to MotorController::GetInstance().
Definition MotorController.h:763
MotorError
Motor controller manager error codes for consistent error reporting.
Definition MotorController.h:117
@ NOT_INITIALIZED
Manager not yet initialised.
@ MUTEX_LOCK_FAILED
RTOS mutex acquire timed out.
@ INVALID_DEVICE_INDEX
Device index out of valid range.
@ DEPENDENCY_NOT_READY
Required dependency not initialised.
@ HANDLER_CREATION_FAILED
Heap allocation or handler init failed.
@ COMMUNICATION_FAILED
A bus-level transfer failed.
@ DEVICE_ALREADY_EXISTS
A device already occupies this slot.
@ CANNOT_DELETE_ONBOARD
Onboard device (index 0) cannot be deleted.
@ DEVICE_NOT_FOUND
No active device at the given index.
@ SUCCESS
Operation completed successfully.
@ INITIALIZATION_FAILED
Device initialisation failed.
@ INVALID_PARAMETER
Null pointer or out-of-range argument.
Tmc9660HostSpiGateMode
Vortex-style host SPI steering to the onboard TMC9660 (PCAL95555 outputs).
Definition MotorController.h:139
@ EnabledForHostSpiMotor
Host SPI to TMC9660 (PCAL_TMC_SPI_COMM_EN asserted).
@ Disabled
SPI mux released (UART motor path / idle).
TMC9660 telemetry snapshots, fault decoding and parameter-image apply for MotorController.
Singleton managing multiple TMC9660 motor controllers on Vortex V1.
Definition MotorController.h:207
MotorError ResetTmclSpiStats(uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Reset the SPI TMCL transport counters.
Definition MotorController.cpp:497
void recordBatchLocked(uint8_t device_index, size_t accesses, size_t failed, uint32_t duration_us) noexcept
Account one batch in accessStats_. Caller holds deviceMutex_.
Definition MotorController.cpp:516
bool withSpiDriverLocked(uint8_t device_index, Fn &&fn) noexcept
Definition MotorController.h:723
MotorError DeleteExternalDevice(uint8_t csDeviceIndex) noexcept
Delete an external TMC9660 device.
Definition MotorController.cpp:261
MotorError GetSystemDiagnostics(MotorSystemDiagnostics &diagnostics) const noexcept
Fill a diagnostics snapshot with current system state.
Definition MotorController.cpp:670
MotorError ApplyParameterImage(std::span< const MotorParameterWrite > image, const MotorApplyOptions &options, MotorApplyResult &result, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Apply a parameter image (MOTOR_TYPE first), optionally only where the chip differs and with read-back...
Definition MotorController.cpp:627
static constexpr uint8_t EXTERNAL_DEVICE_2_INDEX
External device 2 index (EXT_GPIO_CS_2)
Definition MotorController.h:212
MotorError ClearLatchedFaults(uint32_t general_errors, uint32_t gate_driver_errors, uint32_t adc_status, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Clear latched (write-1-to-clear) bits of the general error, gate-driver and ADC words.
Definition MotorController.cpp:606
MotorError GetLastError() const noexcept
Get the most recent error code.
Definition MotorController.h:254
MotorError CreateExternalDevice(uint8_t csDeviceIndex, SpiDeviceId spiDeviceId, uint8_t address, const Tmc9660ControlPins &pins, const tmc9660::BootloaderConfig *bootCfg=nullptr) noexcept
Create an external TMC9660 device on specified CS line (SPI).
Definition MotorController.cpp:160
void DumpStatistics() const noexcept
Dump comprehensive system statistics to log as INFO level. Logs all device statistics,...
Definition MotorController.cpp:699
static MotorController & GetInstance() noexcept
Get the singleton instance.
Definition MotorController.cpp:11
static constexpr uint8_t ONBOARD_TMC9660_INDEX
Onboard TMC9660 device index (SPI2_CS_TMC9660)
Definition MotorController.h:210
size_t InitializeAllDevices(std::array< bool, MAX_TMC9660_DEVICES > &results) noexcept
Initialize all active devices.
Definition MotorController.cpp:347
bool setMotorPosition(double value, ::tmc9660::units::PositionUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Command target position in motor frame.
Definition MotorController.cpp:846
std::array< tmc9660::TmclSpiTiming, MAX_TMC9660_DEVICES > tmclSpiTiming_
Per-device SPI TMCL timing.
Definition MotorController.h:746
void ResetAccessStats(uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Zero the access accounting of one device.
Definition MotorController.cpp:658
std::array< std::optional< Tmc9660Handler >, MAX_TMC9660_DEVICES > tmcHandlers_
Handlers in place (no heap): a slot is emplaced by Create*Device() and reset on delete/deinit.
Definition MotorController.h:741
bool setLoadVelocity(double value, ::tmc9660::units::VelocityUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Command target velocity in the load (output-shaft) frame.
Definition MotorController.cpp:874
std::optional< tmc9660::CommMode > TryGetOnboardCommMode() const noexcept
Physical comm mode for the onboard handler (slot 0), if present.
Definition MotorController.cpp:403
std::array< std::atomic< uint32_t >, MAX_TMC9660_DEVICES > deviceErrorCounts_
Per-device error counters.
Definition MotorController.h:744
std::array< bool, MAX_TMC9660_DEVICES > deviceInitialized_
Definition MotorController.h:742
std::array< bool, MAX_TMC9660_DEVICES > deviceActive_
Track which devices are active.
Definition MotorController.h:743
std::array< MotorAccessStats, MAX_TMC9660_DEVICES > accessStats_
Per-device TMCL access accounting.
Definition MotorController.h:747
bool getMotorPosition(double &out_value, ::tmc9660::units::PositionUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Read actual position in motor frame.
Definition MotorController.cpp:855
MotorError WriteParameters(std::span< MotorParameterAccess > items, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Write several axis parameters in pipelined batches (SAP); per-element status in items.
Definition MotorController.cpp:559
bool IsDeviceValid(uint8_t deviceIndex) const noexcept
Check if a device index is valid and has an active device.
Definition MotorController.cpp:303
bool setMotorVelocity(double value, ::tmc9660::units::VelocityUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Command target velocity in the motor (rotor) frame.
Definition MotorController.cpp:828
void UpdateLastError(MotorError error, int deviceIndex=-1) noexcept
Store a new error code and update per-device counter.
Definition MotorController.cpp:378
MotorError ReadTelemetry(MotorTelemetrySet set, MotorTelemetrySnapshot &snapshot, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Refresh a caller-owned telemetry snapshot from one batch.
Definition MotorController.cpp:573
void GetActiveDeviceIndices(std::array< uint8_t, MAX_TMC9660_DEVICES > &out, size_t &count) const noexcept
Get indices of all active devices.
Definition MotorController.cpp:318
MotorError CreateOnboardDevice(BaseSpi &spiInterface, uint8_t address, const Tmc9660ControlPins &pins, const tmc9660::BootloaderConfig *bootCfg=nullptr) noexcept
Create the onboard TMC9660 device using an SPI interface.
Definition MotorController.cpp:82
std::array< MotorMechanics, MAX_TMC9660_DEVICES > mechanics_
Per-device mechanical mapping (default 1:1)
Definition MotorController.h:745
MotorError SetTmclSpiTiming(const tmc9660::TmclSpiTiming &timing, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Set the SPI TMCL handshake timing for one TMC9660.
Definition MotorController.cpp:457
bool IsExternalDeviceIndex(uint8_t csDeviceIndex) const noexcept
Validate if CS device index is for external device.
Definition MotorController.cpp:286
void configureOnboardHostBusBeforeHandlerInitLocked(uint8_t device_index) noexcept
Definition MotorController.cpp:389
void applyTmclSpiTimingLocked(uint8_t device_index) noexcept
Definition MotorController.cpp:451
bool Initialize()
Initialize all registered motor controller devices.
Definition MotorController.cpp:24
uint8_t GetDeviceCount() const noexcept
Get the number of active TMC9660 devices.
Definition MotorController.cpp:291
void GetInitializationStatus(std::array< bool, MAX_TMC9660_DEVICES > &status) const noexcept
Get initialization status of all device slots.
Definition MotorController.cpp:366
bool Deinitialize() noexcept
Shut down all motor controller devices and release resources.
Definition MotorController.cpp:54
Tmc9660Handler * handler(uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Get access to Tmc9660Handler by device index.
Definition MotorController.cpp:333
MotorError GetTmclSpiTiming(tmc9660::TmclSpiTiming &timing, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) const noexcept
SPI TMCL timing stored for a slot (the driver defaults unless changed).
Definition MotorController.cpp:473
auto visitDriver(Func &&func, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Visit the underlying typed TMC9660 driver by device index.
Definition MotorController.h:420
MotorError applyOnboardTmc9660HostSpiGateModeLocked(Tmc9660HostSpiGateMode mode) noexcept
Definition MotorController.cpp:411
bool getLoadPosition(double &out_value, ::tmc9660::units::PositionUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Read actual position expressed in the load frame.
Definition MotorController.cpp:916
MotorError withReadyDriverLocked(uint8_t device_index, Fn &&fn) noexcept
Run fn on the SPI driver of a ready device, through the handler (handler lock held).
Definition MotorController.h:703
bool getLoadVelocity(double &out_value, ::tmc9660::units::VelocityUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Read actual velocity expressed in the load frame.
Definition MotorController.cpp:887
MotorError ReadParameters(std::span< MotorParameterAccess > items, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Read several axis parameters in pipelined batches (GAP).
Definition MotorController.cpp:545
bool EnsureInitialized() noexcept
Initialise all registered motor controllers if not already done.
Definition MotorController.h:228
MotorError ReadDriveDiagnostics(MotorDriveDiagnostics &out, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Read the four status words (289/299/300/301) in one batch and decode them.
Definition MotorController.cpp:586
static constexpr uint8_t MAX_TMC9660_DEVICES
Maximum supported TMC9660 devices (board + external)
Definition MotorController.h:209
bool IsExternalSlotAvailable(uint8_t csDeviceIndex) const noexcept
Check if an external device slot is available for creation.
Definition MotorController.cpp:308
bool onboardDeviceCreated_
Track if onboard device has been created.
Definition MotorController.h:749
RtosMutex deviceMutex_
RTOS mutex for thread-safe device access.
Definition MotorController.h:752
bool IsInitialized() const noexcept
Check whether the motor controller subsystem has been initialised.
Definition MotorController.h:242
MotorError GetAccessStats(MotorAccessStats &stats, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) const noexcept
TMCL access accounting of one device (batches, accesses, failures, batch latency).
Definition MotorController.cpp:649
static constexpr uint8_t EXTERNAL_DEVICE_1_INDEX
External device 1 index (EXT_GPIO_CS_1)
Definition MotorController.h:211
std::atomic< MotorError > last_error_
Most recent error code.
Definition MotorController.h:751
bool setMotorMechanics(const MotorMechanics &mech, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Set the mechanical mapping (gearbox + direction) for a device.
Definition MotorController.cpp:809
MotorMechanics getMotorMechanics(uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) const noexcept
Read back the currently configured mechanical mapping.
Definition MotorController.cpp:818
bool setLoadPosition(double value, ::tmc9660::units::PositionUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Command target position in the load frame (gearbox-aware).
Definition MotorController.cpp:903
std::atomic< bool > initialized_
Track if system has been initialized.
Definition MotorController.h:750
MotorError GetTmclSpiStats(tmc9660::TmclSpiStats &stats, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
SPI TMCL transport counters (frames, NOT_READY re-sends, stale replies, failures).
Definition MotorController.cpp:482
bool getMotorVelocity(double &out_value, ::tmc9660::units::VelocityUnit unit, ::tmc9660::units::MotorContext const &ctx, uint8_t deviceIndex=ONBOARD_TMC9660_INDEX) noexcept
Read actual velocity in motor frame.
Definition MotorController.cpp:837
MotorError ApplyOnboardTmc9660HostSpiGateMode(Tmc9660HostSpiGateMode mode) noexcept
Drive the onboard TMC9660 host SPI mux (PCAL_TMC_SPI_COMM_EN) on Vortex.
Definition MotorController.cpp:665
TelemetrySet
Which signals one ReadTelemetry() call fetches.
Definition Tmc9660DriveObservability.h:152
TelemetryField
The telemetry signals a snapshot carries (design §1.3, tiers C/F/S).
Definition Tmc9660DriveObservability.h:117
TMCL access accounting per device (every batch MotorController sends on the device's behalf).
Definition MotorController.h:99
uint32_t accesses
TMCL accesses in those batches.
Definition MotorController.h:101
uint32_t failed_accesses
Accesses not answered REPLY_OK.
Definition MotorController.h:102
uint32_t last_batch_us
Duration of the latest batch.
Definition MotorController.h:103
uint32_t max_batch_us
Longest batch since the last reset.
Definition MotorController.h:104
uint32_t batches
Batches sent (one per telemetry / diagnostics / parameter call)
Definition MotorController.h:100
Mechanical mapping between the motor (rotor) frame and the load (output-shaft) frame.
Definition MotorController.h:69
bool invert_output
Definition MotorController.h:82
double gear_ratio_motor_to_output
Definition MotorController.h:75
Per-device snapshot (indexed 0..MAX_TMC9660_DEVICES-1)
Definition MotorController.h:185
bool initialized
Definition MotorController.h:187
uint32_t error_count
Cumulative errors for this slot.
Definition MotorController.h:188
bool active
Definition MotorController.h:186
System-level diagnostics snapshot for motor controller health monitoring.
Definition MotorController.h:177
bool system_healthy
true when all active devices are initialized
Definition MotorController.h:178
static constexpr uint8_t kMaxDevices
Definition MotorController.h:190
bool system_initialized
MotorController::IsInitialized()
Definition MotorController.h:179
DeviceSnapshot devices[kMaxDevices]
Definition MotorController.h:191
uint8_t active_device_count
Number of active device slots.
Definition MotorController.h:180
uint8_t initialized_device_count
Number of successfully initialized devices.
Definition MotorController.h:181
MotorError last_error
Most recent error code.
Definition MotorController.h:182
Bundle of host-side GPIO references for TMC9660 control pins.
Definition MotorController.h:40
BaseGpio & rst
RST pin (output) - hardware reset.
Definition MotorController.h:41
BaseGpio & faultn
FAULTN pin (input) - fault status.
Definition MotorController.h:43
BaseGpio & drv_en
DRV_EN pin (output) - driver enable.
Definition MotorController.h:42
BaseGpio & wake
WAKE pin (output) - wake from hibernation.
Definition MotorController.h:44
How ApplyParameterImage() works.
Definition Tmc9660DriveObservability.h:437
What ApplyParameterImage() did.
Definition Tmc9660DriveObservability.h:443
The four TMC9660 status words, decoded (design §1.5). Raw words are kept for anything not named.
Definition Tmc9660DriveObservability.h:284
Caller-owned snapshot, refreshed in place by MotorController::ReadTelemetry().
Definition Tmc9660DriveObservability.h:166
One axis-parameter access in a batch (MCU- and transport-neutral copy of the driver's type).
Definition Tmc9660DriveObservability.h:52
One entry of a parameter image (design §4.1, the TMC image).
Definition Tmc9660DriveObservability.h:431