85#ifndef COMPONENT_HANDLER_TMC9660_HANDLER_H_
86#define COMPONENT_HANDLER_TMC9660_HANDLER_H_
94#include "core/hf-core-drivers/external/hf-tmc9660-driver/inc/tmc9660.hpp"
95#include "core/hf-core-drivers/external/hf-tmc9660-driver/inc/tmc9660_comm_interface.hpp"
96#include "base/BaseGpio.h"
97#include "base/BaseAdc.h"
98#include "base/BaseTemperature.h"
99#include "base/BaseSpi.h"
100#include "base/BaseUart.h"
101#include "RtosMutex.h"
129 BaseGpio&
get(tmc9660::TMC9660CtrlPin pin)
noexcept {
131 case tmc9660::TMC9660CtrlPin::RST:
return rst;
132 case tmc9660::TMC9660CtrlPin::DRV_EN:
return drv_en;
133 case tmc9660::TMC9660CtrlPin::FAULTN:
return faultn;
134 case tmc9660::TMC9660CtrlPin::WAKE:
return wake;
140 const BaseGpio&
get(tmc9660::TMC9660CtrlPin pin)
const noexcept {
142 case tmc9660::TMC9660CtrlPin::RST:
return rst;
143 case tmc9660::TMC9660CtrlPin::DRV_EN:
return drv_en;
144 case tmc9660::TMC9660CtrlPin::FAULTN:
return faultn;
145 case tmc9660::TMC9660CtrlPin::WAKE:
return wake;
204 BaseGpio& faultn, BaseGpio& wake,
205 bool rst_active_high =
true,
bool drv_en_active_high =
true,
206 bool faultn_active_low =
false,
bool wake_active_low =
false)
noexcept;
218 bool spiTransferTMCL(std::array<uint8_t, 8>& tx, std::array<uint8_t, 8>& rx)
noexcept;
227 std::array<uint8_t, 8>& tx2, std::array<uint8_t, 8>& rx2,
228 uint32_t gap_us)
noexcept;
248 bool gpioSet(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal signal)
noexcept;
260 bool gpioRead(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal& signal)
noexcept;
269 void debugLog(
int level,
const char* tag,
const char* format, va_list args)
noexcept;
275 void delayMs(uint32_t ms)
noexcept;
285 void delayUs(uint32_t us)
noexcept;
302 uint32_t
rawTmclProbe(std::array<uint8_t, 8>& tx, std::array<uint8_t, 8>& rx,
303 uint32_t timeout_ms)
noexcept;
346 BaseGpio& faultn, BaseGpio& wake,
347 bool rst_active_high =
true,
bool drv_en_active_high =
true,
348 bool faultn_active_low =
false,
bool wake_active_low =
false)
noexcept;
358 bool uartSendTMCL(
const std::array<uint8_t, 9>& data)
noexcept;
374 std::array<uint8_t, 8>& rx)
noexcept;
377 bool gpioSet(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal signal)
noexcept;
380 bool gpioRead(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal& signal)
noexcept;
383 void debugLog(
int level,
const char* tag,
const char* format, va_list args)
noexcept;
386 void delayMs(uint32_t ms)
noexcept;
389 void delayUs(uint32_t us)
noexcept;
505 using DriverVariant = std::variant<std::monostate, SpiDriver*, UartDriver*>;
561 BaseGpio& faultn, BaseGpio& wake,
579 BaseGpio& faultn, BaseGpio& wake,
632 bool Initialize(
bool performReset = true,
bool retrieveBootloaderInfo = true,
633 bool failOnVerifyError = false);
693 ~Gpio() noexcept override = default;
720 hf_gpio_err_t
SetDirectionImpl(hf_gpio_direction_t direction) noexcept override;
726 hf_gpio_err_t
SetPullModeImpl(hf_gpio_pull_mode_t mode) noexcept override;
729 hf_gpio_err_t
SetPinLevelImpl(hf_gpio_level_t level) noexcept override;
732 hf_gpio_err_t
GetPinLevelImpl(hf_gpio_level_t& level) noexcept override;
738 hf_gpio_err_t
GetDirectionImpl(hf_gpio_direction_t& direction) const noexcept override;
741 hf_gpio_err_t
GetOutputModeImpl(hf_gpio_output_mode_t& mode) const noexcept override;
749 hf_gpio_direction_t
direction_ = hf_gpio_direction_t::HF_GPIO_DIRECTION_OUTPUT;
778 class
Adc : public BaseAdc {
787 ~Adc() noexcept override = default;
809 hf_u8_t GetMaxChannels() const noexcept override;
816 bool IsChannelAvailable(hf_channel_id_t channel_id) const noexcept override;
826 hf_adc_err_t ReadChannelV(hf_channel_id_t channel_id,
float& channel_reading_v,
827 hf_u8_t numOfSamplesToAvg = 1,
828 hf_time_t timeBetweenSamples = 0) noexcept override;
838 hf_adc_err_t ReadChannelCount(hf_channel_id_t channel_id, hf_u32_t& channel_reading_count,
839 hf_u8_t numOfSamplesToAvg = 1,
840 hf_time_t timeBetweenSamples = 0) noexcept override;
851 hf_adc_err_t ReadChannel(hf_channel_id_t channel_id, hf_u32_t& channel_reading_count,
852 float& channel_reading_v, hf_u8_t numOfSamplesToAvg = 1,
853 hf_time_t timeBetweenSamples = 0) noexcept override;
863 hf_adc_err_t ReadMultipleChannels(const hf_channel_id_t* channel_ids, hf_u8_t num_channels,
864 hf_u32_t* readings,
float* voltages) noexcept override;
867 hf_adc_err_t GetStatistics(hf_adc_statistics_t& statistics) noexcept override;
870 hf_adc_err_t GetDiagnostics(hf_adc_diagnostics_t& diagnostics) noexcept override;
873 hf_adc_err_t ResetStatistics() noexcept override;
876 hf_adc_err_t ResetDiagnostics() noexcept override;
891 hf_adc_err_t ReadAinChannel(uint8_t ain_channel, hf_u32_t& raw_value,
float& voltage) noexcept;
900 hf_adc_err_t ReadCurrentSenseChannel(uint8_t current_channel, hf_u32_t& raw_value,
float& voltage) noexcept;
909 hf_adc_err_t ReadVoltageChannel(uint8_t voltage_channel, hf_u32_t& raw_value,
float& voltage) noexcept;
918 hf_adc_err_t ReadTemperatureChannel(uint8_t temp_channel, hf_u32_t& raw_value,
float& voltage) noexcept;
927 hf_adc_err_t ReadMotorDataChannel(uint8_t motor_channel, hf_u32_t& raw_value,
float& voltage) noexcept;
933 mutable RtosMutex mutex_;
934 mutable hf_adc_statistics_t statistics_;
935 mutable hf_adc_diagnostics_t diagnostics_;
936 std::atomic<hf_adc_err_t> last_error_;
939 hf_adc_err_t ValidateChannelId(hf_channel_id_t channel_id) const noexcept;
953 hf_adc_err_t ReadChannelLocked(hf_channel_id_t channel_id,
954 hf_u32_t& raw,
float& voltage) noexcept;
957 hf_adc_err_t UpdateStatistics(hf_adc_err_t result, uint64_t start_time_us) noexcept;
960 uint64_t GetCurrentTimeUs() const noexcept;
963 void UpdateDiagnostics(hf_adc_err_t error) noexcept;
966 const
char* GetChannelTypeString(hf_channel_id_t channel_id) const noexcept;
1012 hf_temp_err_t ReadTemperatureCelsiusImpl(
float* temperature_celsius) noexcept override;
1019 hf_temp_err_t GetSensorInfo(hf_temp_sensor_info_t* info) const noexcept override;
1025 hf_u32_t GetCapabilities() const noexcept override;
1031 mutable RtosMutex mutex_;
1032 mutable hf_temp_statistics_t statistics_;
1033 mutable hf_temp_diagnostics_t diagnostics_;
1034 std::atomic<hf_temp_err_t> last_error_;
1037 hf_temp_err_t UpdateStatistics(hf_temp_err_t result, uint64_t start_time_us) noexcept;
1040 uint64_t GetCurrentTimeUs() const noexcept;
1043 void UpdateDiagnostics(hf_temp_err_t error) noexcept;
1064 Gpio*
gpio(uint8_t gpioNumber) noexcept;
1194 return std::monostate{};
1205 return std::monostate{};
1230 template <
typename Func>
1235 if constexpr (std::is_void_v<ReturnType>) {
1238 return ReturnType{};
1246 if constexpr (std::is_void_v<ReturnType>) {
1249 return ReturnType{};
1254 template <
typename Func>
1256 using ReturnType =
decltype(func(std::as_const(*
spi_driver_)));
1259 if (!self->EnsureInitializedLocked()) {
1260 if constexpr (std::is_void_v<ReturnType>) {
1263 return ReturnType{};
1271 if constexpr (std::is_void_v<ReturnType>) {
1274 return ReturnType{};
1300 template <typename Func>
1308 if constexpr (std::is_void_v<ReturnType>) {
1311 return ReturnType{};
Concrete SPI communication adapter for TMC9660 using BaseSpi and BaseGpio.
Definition Tmc9660Handler.h:182
bool hostSpiTransferTMCLPair(std::array< uint8_t, 8 > &tx1, std::array< uint8_t, 8 > &rx1, std::array< uint8_t, 8 > &tx2, std::array< uint8_t, 8 > &rx2, uint32_t gap_us) noexcept
Two TMCL soft-CS frames under one bus lock (cmd + NO_OP / reply).
Definition Tmc9660Handler.cpp:185
void delayMs(uint32_t ms) noexcept
Delay execution for the specified number of milliseconds.
Definition Tmc9660Handler.cpp:243
uint32_t transportDiag() const noexcept
Last BaseSpi error observed by any TMCL/bootloader transfer.
Definition Tmc9660Handler.h:295
Tmc9660CtrlPins ctrl_pins_
Host-side control pin references.
Definition Tmc9660Handler.h:307
bool spiTransferBootloader(std::array< uint8_t, 5 > &tx, std::array< uint8_t, 5 > &rx) noexcept
Perform a 5-byte full-duplex SPI transfer for bootloader mode.
Definition Tmc9660Handler.cpp:218
BaseSpi & spi_
SPI bus interface (not owned).
Definition Tmc9660Handler.h:306
bool spiTransferTMCL(std::array< uint8_t, 8 > &tx, std::array< uint8_t, 8 > &rx) noexcept
Perform an 8-byte full-duplex SPI transfer for TMCL parameter mode.
Definition Tmc9660Handler.cpp:171
bool gpioRead(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal &signal) noexcept
Read a TMC9660 control pin's current logical signal state.
Definition Tmc9660Handler.cpp:234
uint32_t last_spi_err_
Last hf_spi_err_t from Transfer/TransferChain.
Definition Tmc9660Handler.h:308
void debugLog(int level, const char *tag, const char *format, va_list args) noexcept
Route TMC9660 driver debug output to the HardFOC Logger.
Definition Tmc9660Handler.cpp:239
bool gpioSet(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal signal) noexcept
Set a TMC9660 control pin to a given logical signal state.
Definition Tmc9660Handler.cpp:229
uint32_t rawTmclProbe(std::array< uint8_t, 8 > &tx, std::array< uint8_t, 8 > &rx, uint32_t timeout_ms) noexcept
Single-shot raw 8-byte transfer with caller-chosen bus-lock timeout.
Definition Tmc9660Handler.cpp:207
void delayUs(uint32_t us) noexcept
Delay execution for the specified number of microseconds.
Definition Tmc9660Handler.cpp:244
Concrete UART communication adapter for TMC9660 using BaseUart and BaseGpio.
Definition Tmc9660Handler.h:330
void delayUs(uint32_t us) noexcept
Delay execution for the specified number of microseconds.
Definition Tmc9660Handler.cpp:318
bool uartTransferBootloader(const std::array< uint8_t, 8 > &tx, std::array< uint8_t, 8 > &rx) noexcept
Perform an 8-byte UART bootloader transfer (send + receive).
Definition Tmc9660Handler.cpp:287
bool uartReceiveTMCL(std::array< uint8_t, 9 > &data) noexcept
Receive a 9-byte TMCL reply datagram over UART.
Definition Tmc9660Handler.cpp:275
void debugLog(int level, const char *tag, const char *format, va_list args) noexcept
Route TMC9660 driver debug output to the HardFOC Logger.
Definition Tmc9660Handler.cpp:313
bool uartSendTMCL(const std::array< uint8_t, 9 > &data) noexcept
Send a 9-byte TMCL datagram over UART.
Definition Tmc9660Handler.cpp:261
uint32_t reply_timeout_ms_
see setReplyTimeoutMs
Definition Tmc9660Handler.h:407
uint32_t replyTimeoutMs() const noexcept
Definition Tmc9660Handler.h:402
Tmc9660CtrlPins ctrl_pins_
Host-side control pin references.
Definition Tmc9660Handler.h:406
bool gpioSet(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal signal) noexcept
Set a TMC9660 control pin to a given logical signal state.
Definition Tmc9660Handler.cpp:303
void setReplyTimeoutMs(uint32_t ms) noexcept
How long a TMCL reply may take before the exchange fails.
Definition Tmc9660Handler.h:401
void delayMs(uint32_t ms) noexcept
Delay execution for the specified number of milliseconds.
Definition Tmc9660Handler.cpp:317
BaseUart & uart_
UART bus interface (not owned).
Definition Tmc9660Handler.h:405
bool gpioRead(tmc9660::TMC9660CtrlPin pin, tmc9660::GpioSignal &signal) noexcept
Read a TMC9660 control pin's current logical signal state.
Definition Tmc9660Handler.cpp:308
Delegation wrapper that adapts Tmc9660Handler::Adc for external ownership.
Definition Tmc9660AdcWrapper.h:63
BaseAdc adapter for all TMC9660 ADC channels.
Definition Tmc9660Handler.h:778
~Adc() noexcept override=default
Default destructor.
BaseGpio adapter for a single TMC9660 internal GPIO channel.
Definition Tmc9660Handler.h:683
hf_gpio_pull_mode_t GetPullModeImpl() const noexcept override
Returns FLOATING (TMC9660 pull is set via bootloader config).
Definition Tmc9660Handler.cpp:575
const char * GetDescription() const noexcept override
Returns a description string like "TMC9660 GPIO17".
Definition Tmc9660Handler.cpp:585
bool IsPinAvailable() const noexcept override
Check if this GPIO number is a valid TMC9660 pin (17 or 18).
Definition Tmc9660Handler.cpp:579
hf_gpio_err_t SetPinLevelImpl(hf_gpio_level_t level) noexcept override
Write HIGH or LOW to the TMC9660 GPIO pin via the driver.
Definition Tmc9660Handler.cpp:528
uint8_t gpioNumber_
TMC9660 internal GPIO pin number.
Definition Tmc9660Handler.h:747
hf_gpio_err_t SetOutputModeImpl(hf_gpio_output_mode_t mode) noexcept override
Set output mode. Only PUSH_PULL is supported.
Definition Tmc9660Handler.cpp:563
hf_gpio_err_t GetPinLevelImpl(hf_gpio_level_t &level) noexcept override
Read the current level of the TMC9660 GPIO pin via the driver.
Definition Tmc9660Handler.cpp:539
bool Initialize() noexcept override
Initialize the GPIO pin (configures as output by default on the TMC9660).
Definition Tmc9660Handler.cpp:519
hf_gpio_err_t SetPullModeImpl(hf_gpio_pull_mode_t mode) noexcept override
Set pull mode. Only FLOATING is supported.
Definition Tmc9660Handler.cpp:569
hf_gpio_direction_t direction_
Current direction.
Definition Tmc9660Handler.h:749
hf_gpio_err_t GetDirectionImpl(hf_gpio_direction_t &direction) const noexcept override
Returns the current configured direction (INPUT or OUTPUT).
Definition Tmc9660Handler.cpp:587
hf_gpio_err_t GetOutputModeImpl(hf_gpio_output_mode_t &mode) const noexcept override
Returns PUSH_PULL.
Definition Tmc9660Handler.cpp:592
bool Deinitialize() noexcept override
Deinitialize (no-op; TMC9660 GPIO persists until device reset).
Definition Tmc9660Handler.cpp:526
hf_gpio_err_t SetDirectionImpl(hf_gpio_direction_t direction) noexcept override
Set pin direction (INPUT or OUTPUT supported).
Definition Tmc9660Handler.cpp:550
Tmc9660Handler & parent_
Owning handler instance.
Definition Tmc9660Handler.h:746
~Gpio() noexcept override=default
Default destructor.
char description_[32]
Human-readable description (e.g., "TMC9660 GPIO17").
Definition Tmc9660Handler.h:748
hf_u8_t GetMaxPins() const noexcept override
Returns 2 (GPIO17 and GPIO18 are exposed).
Definition Tmc9660Handler.cpp:583
BaseTemperature adapter for the TMC9660 internal chip temperature sensor.
Definition Tmc9660Handler.h:987
~Temperature() noexcept override=default
Default destructor.
Unified, non-templated handler for a single TMC9660 motor controller device.
Definition Tmc9660Handler.h:491
bool use_spi_
true = SPI communication active, false = UART.
Definition Tmc9660Handler.h:1319
std::variant< std::monostate, SpiDriver *, UartDriver * > DriverVariant
Non-owning variant holding either driver type or empty (monostate).
Definition Tmc9660Handler.h:505
Temperature * temperature() noexcept
Get the Temperature wrapper.
Definition Tmc9660Handler.cpp:473
auto visitDriverInternal(Func &&func) noexcept
Internal no-lock visitDriver for use from already-locked contexts.
Definition Tmc9660Handler.h:1301
std::unique_ptr< UartDriver > uart_driver_
TMC9660 driver for UART mode (or nullptr).
Definition Tmc9660Handler.h:1332
Adc * adc() noexcept
Get the ADC wrapper.
Definition Tmc9660Handler.cpp:469
std::variant< std::monostate, const SpiDriver *, const UartDriver * > ConstDriverVariant
Const version of DriverVariant.
Definition Tmc9660Handler.h:508
bool IsDriverReady() const noexcept
Check if the TMC9660 driver has been initialized and is ready.
Definition Tmc9660Handler.cpp:451
uint8_t device_address_
7-bit TMCL device address.
Definition Tmc9660Handler.h:1346
const tmc9660::BootloaderConfig * bootCfg_
Bootloader config (not owned; must outlive handler).
Definition Tmc9660Handler.h:1345
Gpio * gpio(uint8_t gpioNumber) noexcept
Get the GPIO wrapper for a TMC9660 internal GPIO pin.
Definition Tmc9660Handler.cpp:459
std::unique_ptr< SpiDriver > spi_driver_
TMC9660 driver for SPI mode (or nullptr).
Definition Tmc9660Handler.h:1331
void SetTmclReplyTimeoutMs(uint32_t ms) noexcept
TMCL reply window for UART transfers (HalUartTmc9660Comm::setReplyTimeoutMs).
Definition Tmc9660Handler.h:655
std::unique_ptr< HalUartTmc9660Comm > uart_comm_
UART communication adapter (or nullptr).
Definition Tmc9660Handler.h:1325
static const tmc9660::BootloaderConfig kDefaultBootConfig
Default bootloader configuration based on TMC9660-3PH-EVAL board settings.
Definition Tmc9660Handler.h:28
auto visitDriver(Func &&func) noexcept
Execute a function on the underlying typed TMC9660 driver.
Definition Tmc9660Handler.h:1231
Adc & AdcInstance() noexcept
The always-present Adc instance, without the bring-up attempt adc() makes.
Definition Tmc9660Handler.h:1294
bool EnsureInitialized() noexcept
Ensure driver is initialized (lazy init entrypoint).
Definition Tmc9660Handler.cpp:439
tmc9660::TMC9660< HalSpiTmc9660Comm > SpiDriver
TMC9660 driver instantiated with SPI communication.
Definition Tmc9660Handler.h:499
tmc9660::TMC9660< HalUartTmc9660Comm > UartDriver
TMC9660 driver instantiated with UART communication.
Definition Tmc9660Handler.h:502
std::unique_ptr< Temperature > temperatureWrapper_
Chip temperature wrapper.
Definition Tmc9660Handler.h:1340
bool EnsureInitializedLocked() noexcept
Ensure initialized while handler_mutex_ is already held.
Definition Tmc9660Handler.cpp:444
bool boot_ok_
true only after bootloaderInit Success.
Definition Tmc9660Handler.h:1347
SpiDriver * driverViaSpi() noexcept
Get the TMC9660 driver instance connected via SPI (nullptr if using UART).
Definition Tmc9660Handler.cpp:485
std::array< std::unique_ptr< Gpio >, 2 > gpioWrappers_
GPIO17 [0] and GPIO18 [1].
Definition Tmc9660Handler.h:1338
auto visitDriver(Func &&func) const noexcept
Const overload of visitDriver().
Definition Tmc9660Handler.h:1255
RtosMutex handler_mutex_
Recursive mutex for thread-safe access.
Definition Tmc9660Handler.h:1352
std::unique_ptr< Adc > adcWrapper_
Multi-channel ADC wrapper.
Definition Tmc9660Handler.h:1339
std::unique_ptr< HalSpiTmc9660Comm > spi_comm_
SPI communication adapter (or nullptr).
Definition Tmc9660Handler.h:1324
DriverVariant GetDriver() noexcept
Get the active driver pointer without requiring visitor usage.
Definition Tmc9660Handler.h:1187
UartDriver * driverViaUart() noexcept
Get the TMC9660 driver instance connected via UART (nullptr if using SPI).
Definition Tmc9660Handler.cpp:497
tmc9660::CommMode GetCommMode() const noexcept
Get the communication mode in use (SPI or UART).
Definition Tmc9660Handler.cpp:481
~Tmc9660Handler() noexcept
Destructor. Releases the driver, communication adapter, and all wrappers.
bool Initialize(bool performReset=true, bool retrieveBootloaderInfo=true, bool failOnVerifyError=false)
Initialize the TMC9660 device.
Definition Tmc9660Handler.cpp:377
void DumpDiagnostics() noexcept
Dump comprehensive diagnostics to the system log.
Definition Tmc9660Handler.cpp:1013
ConstDriverVariant GetDriver() const noexcept
Const overload of GetDriver().
Definition Tmc9660Handler.h:1198
const tmc9660::BootloaderConfig * bootConfig() const noexcept
Get the bootloader configuration in use.
Definition Tmc9660Handler.h:1099
Shared helper holding the four TMC9660 host-side control pin references.
Definition Tmc9660Handler.h:122
BaseGpio & wake
WAKE control pin GPIO (not owned).
Definition Tmc9660Handler.h:126
const BaseGpio & get(tmc9660::TMC9660CtrlPin pin) const noexcept
Resolve a TMC9660CtrlPin enum (const).
Definition Tmc9660Handler.h:140
BaseGpio & faultn
FAULTN status pin GPIO (not owned).
Definition Tmc9660Handler.h:125
BaseGpio & get(tmc9660::TMC9660CtrlPin pin) noexcept
Resolve a TMC9660CtrlPin enum to the corresponding BaseGpio reference.
Definition Tmc9660Handler.h:129
BaseGpio & rst
RST control pin GPIO (not owned).
Definition Tmc9660Handler.h:123
BaseGpio & drv_en
DRV_EN control pin GPIO (not owned).
Definition Tmc9660Handler.h:124