|
HF-TMC51x0 Driver (TMC5130 & TMC5160) 0.1.0-dev
Hardware Agnostic C++ Driver for the TMC51x0 (TMC5130 & TMC5160)
|
CRTP-based SPI implementation of TMC5160CommInterface. More...
#include <tmc51x0_comm_interface.hpp>
Public Member Functions | |
| SpiCommInterface () noexcept | |
| Construct SPI communication interface. | |
| void | SetDaisyChainLength (uint8_t total_length) noexcept |
| Set the total number of devices in the daisy chain. | |
| uint8_t | GetDaisyChainLength () const noexcept |
| Get the total number of devices in the daisy chain. | |
| uint8_t | AutoDetectChainLength (uint8_t max_devices=8) noexcept |
| Auto-detect the daisy chain length by sending a unique command that loops back. | |
| CommMode | GetMode () const noexcept |
| Get communication mode (always SPI for this interface) | |
| Result< void > | SpiTransfer (const uint8_t *tx, uint8_t *rx, size_t length) noexcept |
| Low-level SPI transfer for register read/write. | |
| Result< uint32_t > | ReadRegister (uint8_t address, uint8_t daisy_chain_position=0) noexcept |
| Read a 32-bit register via SPI. | |
| Result< void > | WriteRegister (uint8_t address, uint32_t value, uint8_t daisy_chain_position=0) noexcept |
| Write a 32-bit register via SPI. | |
| SpiCommInterface (const SpiCommInterface &)=delete | |
| SpiCommInterface & | operator= (const SpiCommInterface &)=delete |
Public Member Functions inherited from tmc51x0::CommInterface< Derived > | |
| CommInterface () noexcept=default | |
| Construct communication interface. | |
| CommMode | GetMode () const noexcept |
| Get the underlying communication mode used by this interface. | |
| Result< uint32_t > | ReadRegister (uint8_t address, uint8_t address_param=0) noexcept |
| Read a 32-bit register from the TMC5160. | |
| Result< void > | WriteRegister (uint8_t address, uint32_t value, uint8_t address_param=0) noexcept |
| Write a 32-bit register to the TMC5160. | |
| Result< void > | GpioSet (TMC51x0CtrlPin pin, GpioSignal signal) noexcept |
| Set GPIO pin signal state (output control) | |
| Result< GpioSignal > | GpioRead (TMC51x0CtrlPin pin) noexcept |
| Read GPIO pin signal state (input state) | |
| Result< void > | GpioSetActive (TMC51x0CtrlPin pin) noexcept |
| Set GPIO pin to active state (convenience method) | |
| Result< void > | GpioSetInactive (TMC51x0CtrlPin pin) noexcept |
| Set GPIO pin to inactive state (convenience method) | |
| void | DelayMs (uint32_t ms) noexcept |
| Delay execution for specified milliseconds. | |
| void | DelayUs (uint32_t us) noexcept |
| Delay execution for specified microseconds. | |
| Result< void > | SetPowerEnabled (bool enabled) noexcept |
| Enable/disable power to the TMC51x0 (optional) | |
| Result< void > | PowerCycle (uint32_t power_off_ms=20, uint32_t power_on_settle_ms=20) noexcept |
| Power-cycle the TMC51x0 (optional) | |
| Result< void > | SetClkFreq (uint32_t frequency_hz) noexcept |
| Set external clock frequency on CLK pin (optional) | |
| CommInterface (const CommInterface &)=delete | |
| CommInterface & | operator= (const CommInterface &)=delete |
| void | LogDebug (int level, const char *tag, const char *format,...) noexcept |
| Public debug logging wrapper for external classes. | |
| void | LogDebug (LogLevel level, const char *tag, const char *format,...) noexcept |
| LogDebug overload that accepts the driver-native LogLevel enum. | |
Static Public Attributes | |
| static constexpr size_t | kSpiScratchBytes |
Protected Member Functions | |
| ~SpiCommInterface ()=default | |
| Protected destructor. | |
| SpiCommInterface (SpiCommInterface &&)=default | |
| SpiCommInterface & | operator= (SpiCommInterface &&)=default |
Protected Member Functions inherited from tmc51x0::CommInterface< Derived > | |
| void | DebugLog (int level, const char *tag, const char *format, va_list args) noexcept |
| Debug logging function for detailed debugging information. | |
| ~CommInterface ()=default | |
| Protected destructor. | |
| CommInterface (CommInterface &&)=default | |
| CommInterface & | operator= (CommInterface &&)=default |
Protected Attributes | |
| uint8_t | total_chain_length_ |
| Total number of devices in the daisy chain. | |
| uint8_t | user_specified_chain_length_ {0} |
| bool | chain_length_verified_ {false} |
Private Member Functions | |
| Result< void > | EnsureChainLengthKnown (uint8_t daisy_chain_position, const char *context) noexcept |
| Ensure chain length is known and verified for daisy-chain operations. | |
Private Attributes | |
| std::array< uint8_t, kSpiScratchBytes > | tx_scratch_ {} |
| std::array< uint8_t, kSpiScratchBytes > | rx_scratch_ {} |
| uint32_t | drv_err_log_count_ {0} |
CRTP-based SPI implementation of TMC5160CommInterface.
Uses a 4-wire SPI bus (mode 3) to exchange 40-bit datagrams per datasheet section 4.1. The implementation uses 8 bytes (64 bits) for convenience, which is acceptable per datasheet as additional bits beyond 40 are shifted through an internal shift register for daisy-chaining. Data is sent MSB-first, big-endian.
SPI Datagram Structure (40 bits):
Byte structure (MSB transmitted first):
Response (40 bits):
Read access (pipelined per datasheet section 4.1.1):
Write access:
SPI Signals (per datasheet section 4.2):
Timing (per datasheet section 4.3):
The TMC5160 supports daisy-chaining multiple chips on a single SPI bus per datasheet section 4.2. Each chip has an internal 40-bit shift register. Data on SDI is continuously shifted out on SDO with a 40-clock cycle delay, allowing data to propagate through the chain.
Hardware Setup for Daisy-Chaining:
How Daisy-Chaining Works:
Response Reading (per datasheet):
CRITICAL: Chain Length MUST Always Be Known
Sending vs Receiving Calculations:
Chain Length Requirements:
daisy_chain_position > 0 and chain length is unknown, it is automatically detecteddaisy_chain_position == 0), chain length defaults to 1Auto-Detection on First Access:
daisy_chain_position > 0 and chain length is unknown, it is automatically detected on the first ReadRegister() or WriteRegister() callAutoDetectChainLength() which sends a unique command that loops backVerification of User-Specified Length:
SetDaisyChainLength(n), the specified length is verified against auto-detected length on first accessWhy This Matters:
For multi-chip simultaneous communication:
Architecture:
Example usage:
| Derived | The derived class type (CRTP pattern) |
|
inlinenoexcept |
Construct SPI communication interface.
Note: Pin active level configuration is handled by the derived class. The base class only deals with abstract signals (ACTIVE/INACTIVE).
|
protecteddefault |
Protected destructor.
|
protecteddefault |
|
delete |
|
inlinenoexcept |
Auto-detect the daisy chain length by sending a unique command that loops back.
This method sends a command with a unique, recognizable pattern to position (max_devices+1), which is beyond the last device. The command will shift through all devices and loop back to the MCU via the last device's SDO. By searching for our exact command pattern in the received data, we can determine the actual chain length.
Algorithm:
| max_devices | Maximum number of devices to probe (default: 8, max: 255) |
|
inlineprivatenoexcept |
Ensure chain length is known and verified for daisy-chain operations.
| daisy_chain_position | Position in daisy chain (0 = first chip/single chip) |
| context | Context string for logging (e.g., "ReadRegister", "WriteRegister") |
This function handles:
|
inlinenoexcept |
Get the total number of devices in the daisy chain.
|
inlinenoexcept |
Get communication mode (always SPI for this interface)
|
delete |
|
protecteddefault |
|
inlinenoexcept |
Read a 32-bit register via SPI.
| address | Register address (0x00-0x73) |
| value | Reference to store the read value |
| daisy_chain_position | Position in daisy chain (0 = first chip/single chip, default: 0) Specifies which chip in the chain to address |
This method handles both single-chip and daisy-chain modes:
Daisy-Chain Transfer Logic:
CRITICAL: Chain length MUST be known for correct operation
Sending (Command Transmission):
Receiving (Response Extraction):
Transfer Size Calculation:
Auto-Detection and Verification:
daisy_chain_position > 0 and chain length is unknown (total_chain_length_ == 0), chain length is automatically detected on first accessSetDaisyChainLength(), it is verified against auto-detected length on first accessArchitecture Note: This SpiCommInterface instance can be shared by multiple TMC5160 drivers on the same SPI bus. Each TMC5160 instance has its own daisy_chain_position_ and passes it as a parameter when calling ReadRegister() or WriteRegister().
CSN is handled automatically by the SPI hardware or derived class implementation. For daisy-chaining, all chips share the same CSN (tied together).
|
inlinenoexcept |
Set the total number of devices in the daisy chain.
| total_length | Total number of devices in the chain (1 = single chip, 2 = two chips, etc.) Set to 0 to disable daisy-chain mode (single chip, default) |
|
inlinenoexcept |
Low-level SPI transfer for register read/write.
| tx | Buffer containing bytes to transmit |
| rx | Buffer to receive bytes from device |
| length | Number of bytes to transfer |
|
inlinenoexcept |
Write a 32-bit register via SPI.
| address | Register address (0x00-0x73) |
| value | 32-bit value to write |
| daisy_chain_position | Position in daisy chain (0 = first chip/single chip, default: 0) Specifies which chip in the chain to address |
This method handles both single-chip and daisy-chain modes:
Daisy-Chain Transfer Logic: Same as ReadRegister() - see ReadRegister() documentation for detailed explanation.
Key Points:
Auto-Detection and Verification: Same as ReadRegister() - chain length is auto-detected on first access if needed, and user-specified length is verified against detected length. If detection fails, operation returns false.
Architecture Note: This SpiCommInterface instance can be shared by multiple TMC5160 drivers on the same SPI bus. Each TMC5160 instance has its own daisy_chain_position_ and passes it as a parameter when calling ReadRegister() or WriteRegister().
CSN is handled automatically by the SPI hardware or derived class implementation. For daisy-chaining, all chips share the same CSN (tied together).
|
protected |
Flag to track if chain length has been verified via auto-detection
|
private |
|
staticconstexpr |
|
private |
|
protected |
Total number of devices in the daisy chain.
0 = unknown/single chip (uses simplified approach) >0 = total number of devices (uses datasheet formula 40·(n-k))
This is CRITICAL for proper response extraction. When set correctly, ReadRegister and WriteRegister use the optimal datasheet formula. Total number of devices in daisy chain (0 = unknown/single chip)
|
private |
|
protected |
User-specified chain length (0 = not specified, >0 = user value)