TLE92466ED Driver 2.0.0
API reference
Loading...
Searching...
No Matches
Public Member Functions | Static Public Attributes | Protected Member Functions | Protected Attributes | List of all members
tle92466ed::SpiInterface< Derived > Class Template Reference

CRTP-based Communication Interface template class. More...

#include <tle92466ed_spi_interface.hpp>

Public Member Functions

CommResult< void > Init () noexcept
 Initialize the hardware interface.
 
CommResult< void > Deinit () noexcept
 Deinitialize the hardware interface.
 
CommResult< uint32_t > Transfer32 (uint32_t tx_data) noexcept
 Transfer 32-bit data via SPI (full-duplex)
 
CommResult< void > TransferMulti (std::span< const uint32_t > tx_data, std::span< uint32_t > rx_data) noexcept
 Transfer multiple 32-bit words via SPI in one CS assertion window.
 
CommResult< void > Delay (uint32_t microseconds) noexcept
 Delay for specified duration.
 
CommResult< void > Configure (const SPIConfig &config) noexcept
 Configure SPI parameters.
 
bool IsReady () const noexcept
 Check if hardware is ready for communication.
 
CommError GetLastError () const noexcept
 Get the last error that occurred.
 
CommResult< void > ClearErrors () noexcept
 Clear any pending errors.
 
CommResult< void > GpioSet (CtrlPin pin, GpioSignal signal) noexcept
 Set GPIO control pin signal state (output control).
 
CommResult< GpioSignal > GpioRead (CtrlPin pin) noexcept
 Read GPIO control pin signal state (input state).
 
CommResult< void > GpioSetActive (CtrlPin pin) noexcept
 Set GPIO pin to active state (convenience method).
 
CommResult< void > GpioSetInactive (CtrlPin pin) noexcept
 Set GPIO pin to inactive state (convenience method).
 
void Log (LogLevel level, const char *tag, const char *format,...) noexcept
 Log a message with specified severity level and tag.
 
CommResult< uint32_t > Read (uint16_t address, bool verify_crc=true) noexcept
 Read a register from the TLE92466ED (High-Level API)
 
CommResult< void > ReadMulti (std::span< const uint16_t > addresses, std::span< uint32_t > values, uint16_t &valid_mask) noexcept
 Read several registers in ONE pipelined chain.
 
CommResult< void > Write (uint16_t address, uint16_t value, bool verify_crc=true) noexcept
 Write a register to the TLE92466ED (High-Level API)
 
uint8_t LastCriticalFaultFlags () const noexcept
 Fault byte from the most recent critical-fault reply frame.
 
bool SawCriticalFault () const noexcept
 True once a critical-fault reply frame has been decoded.
 
 SpiInterface (const SpiInterface &)=delete
 Prevent copying.
 
SpiInterface & operator= (const SpiInterface &)=delete
 

Static Public Attributes

static constexpr size_t kMaxPipelinedReads = 12
 Largest burst ReadMulti will issue in one CS-session chain.
 

Protected Member Functions

 SpiInterface ()=default
 Protected constructor to prevent direct instantiation.
 
 SpiInterface (SpiInterface &&) noexcept=default
 Allow moving.
 
SpiInterface & operator= (SpiInterface &&) noexcept=default
 
void NoteCriticalFault (const SPIFrame &frame) noexcept
 Latch a critical-fault reply so callers can report the cause.
 
 ~SpiInterface ()=default
 Protected destructor.
 

Protected Attributes

uint8_t last_critical_fault_flags_ {0}
 
bool saw_critical_fault_ {false}
 

Detailed Description

template<typename Derived>
class tle92466ed::SpiInterface< Derived >

CRTP-based Communication Interface template class.

This template class provides a hardware-agnostic interface for SPI communication using the CRTP (Curiously Recurring Template Pattern) for compile-time polymorphism. Platform-specific implementations should inherit from this template with themselves as the template parameter.

Benefits of CRTP:

The CommInterface uses modern C++20/23 features including:

32-Bit SPI Communication:
The TLE92466ED requires 32-bit SPI frames. Implementations must:
  • Transfer 4 bytes (32 bits) per transaction
  • Maintain MSB-first byte order
  • Support full-duplex operation
  • Calculate and verify CRC-8 (SAE J1850)
Example Implementation:
class MyPlatformCommInterface : public tle92466ed::SpiInterface<MyPlatformCommInterface> {
public:
CommResult<uint32_t> Transfer32(uint32_t data) noexcept {
uint32_t result = spi_transfer_32bit(data);
if (spi_error()) {
return tle::unexpected(CommError::TransferError);
}
return result;
}
// ... implement other required methods
};
CRTP-based Communication Interface template class.
Definition tle92466ed_spi_interface.hpp:429
Expected type — holds either a value of type T or an error of type E.
Definition tle92466ed_expected.hpp:82
Wrapper for an error value (mirrors std::unexpected)
Definition tle92466ed_expected.hpp:56
Thread Safety:
Implementations must ensure thread-safety for multi-threaded environments.
Hardware Requirements:
  • SPI peripheral capable of 32-bit transfers (or 4x 8-bit)
  • Maximum frequency: 8 MHz (f_SCK, datasheet 5.1.4 Table 18; no minimum is specified)
  • CSN high for at least 600 ns between frames (t_CSN_TD)
  • Support for SPI Mode 1 (CPOL=0, CPHA=1)
  • CRC calculation capability (hardware or software)
Template Parameters
DerivedThe derived class type (CRTP pattern)

Constructor & Destructor Documentation

◆ SpiInterface() [1/3]

template<typename Derived >
tle92466ed::SpiInterface< Derived >::SpiInterface ( const SpiInterface< Derived > &  )
delete

Prevent copying.

◆ SpiInterface() [2/3]

template<typename Derived >
tle92466ed::SpiInterface< Derived >::SpiInterface ( )
protecteddefault

Protected constructor to prevent direct instantiation.

This class can only be instantiated through derived classes.

◆ SpiInterface() [3/3]

template<typename Derived >
tle92466ed::SpiInterface< Derived >::SpiInterface ( SpiInterface< Derived > &&  )
protecteddefaultnoexcept

Allow moving.

◆ ~SpiInterface()

template<typename Derived >
tle92466ed::SpiInterface< Derived >::~SpiInterface ( )
protecteddefault

Protected destructor.

Note
Derived classes can have public destructors

Member Function Documentation

◆ ClearErrors()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::ClearErrors ( )
inlinenoexcept

Clear any pending errors.

Resets the error state. Should be called after handling an error condition and before retrying operations.

Returns
CommResult<void> Success or error code

◆ Configure()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::Configure ( const SPIConfig &  config)
inlinenoexcept

Configure SPI parameters.

Updates the SPI configuration. Can be called at runtime to adjust communication parameters.

Parameters
[in]configNew SPI configuration
Returns
CommResult<void> Success or error code
Return values
CommError::InvalidParameterInvalid configuration
TLE92466ED SPI Requirements:
  • Frequency: up to 8 MHz (datasheet 5.1.4 Table 18)
  • Mode: 1 (CPOL=0, CPHA=1) - Data sampled on falling edge of SCK, shifted on rising edge
  • Bit order: MSB first
  • Frame size: 32 bits (4 bytes)

◆ Deinit()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::Deinit ( )
inlinenoexcept

Deinitialize the hardware interface.

Releases hardware resources and disables the SPI peripheral. Should be called when the driver is no longer needed.

Returns
CommResult<void> Success or error code

◆ Delay()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::Delay ( uint32_t  microseconds)
inlinenoexcept

Delay for specified duration.

Provides a hardware-specific delay implementation. Required for timing constraints such as reset pulse width and power-up delays.

Parameters
[in]microsecondsDuration to delay in microseconds
Returns
CommResult<void> Success or error code
Timing Requirements:
  • Reset pulse width: minimum 1µs
  • Power-up delay: minimum 1ms

◆ GetLastError()

template<typename Derived >
CommError tle92466ed::SpiInterface< Derived >::GetLastError ( ) const
inlinenoexcept

Get the last error that occurred.

Retrieves the most recent error code. Useful for debugging and error recovery.

Returns
CommError The last error code

◆ GpioRead()

template<typename Derived >
CommResult< GpioSignal > tle92466ed::SpiInterface< Derived >::GpioRead ( CtrlPin  pin)
inlinenoexcept

Read GPIO control pin signal state (input state).

Reads the current state of TLE92466ED control pins (FAULTN). The implementation must map physical levels to ACTIVE/INACTIVE based on board design.

Parameters
pinControl pin to read (FAULTN)
Returns
CommResult<GpioSignal> Pin signal state (ACTIVE or INACTIVE) or error
Return values
CommError::InvalidParameterInvalid pin (only FAULTN can be read)
CommError::HardwareNotReadyHardware not initialized
Pin Behavior:
  • FAULTN (active low): ACTIVE = fault detected (GPIO LOW), INACTIVE = no fault (GPIO HIGH)
Note
Only FAULTN can be read. RESN and EN are output-only.

◆ GpioSet()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::GpioSet ( CtrlPin  pin,
GpioSignal  signal 
)
inlinenoexcept

Set GPIO control pin signal state (output control).

Controls the state of TLE92466ED control pins (RESN, EN). The implementation must map ACTIVE/INACTIVE to the appropriate physical levels based on board design.

Parameters
pinControl pin to set (RESN or EN)
signalThe desired signal state (ACTIVE or INACTIVE)
Returns
CommResult<void> Success or error code
Return values
CommError::InvalidParameterInvalid pin or signal
CommError::HardwareNotReadyHardware not initialized
Pin Behavior:
  • RESN (active low): ACTIVE = not in reset (GPIO HIGH), INACTIVE = in reset (GPIO LOW)
  • EN (active high): ACTIVE = enabled (GPIO HIGH), INACTIVE = disabled (GPIO LOW)
Note
RESN must be ACTIVE for SPI communication to work.
EN only affects output channels, not SPI communication.

◆ GpioSetActive()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::GpioSetActive ( CtrlPin  pin)
inlinenoexcept

Set GPIO pin to active state (convenience method).

Parameters
pinThe control pin to set active
Returns
CommResult<void> Success or error code

◆ GpioSetInactive()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::GpioSetInactive ( CtrlPin  pin)
inlinenoexcept

Set GPIO pin to inactive state (convenience method).

Parameters
pinThe control pin to set inactive
Returns
CommResult<void> Success or error code

◆ Init()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::Init ( )
inlinenoexcept

Initialize the hardware interface.

This function should initialize the SPI peripheral, configure GPIO pins, and prepare the hardware for communication. It should be called before any other CommInterface functions.

Returns
CommResult<void> Success or error code
Return values
CommError::NoneInitialization successful
CommError::HardwareNotReadyHardware initialization failed
CommError::InvalidParameterInvalid configuration

◆ IsReady()

template<typename Derived >
bool tle92466ed::SpiInterface< Derived >::IsReady ( ) const
inlinenoexcept

Check if hardware is ready for communication.

Verifies that the hardware interface is initialized and ready for SPI transactions.

Returns
true if ready, false otherwise

◆ LastCriticalFaultFlags()

template<typename Derived >
uint8_t tle92466ed::SpiInterface< Derived >::LastCriticalFaultFlags ( ) const
inlinenoexcept

Fault byte from the most recent critical-fault reply frame.

A reply with reply_mode == 10B is the device reporting that its own supplies/clocks are unusable; the payload byte says which (see CriticalFaultFlags). Read() / Write() surface that as CommError::BusError, which on its own is indistinguishable from a bus glitch — this accessor preserves why the device refused to answer.

Returns
Last fault byte, or 0 if no critical-fault frame has been seen.
Note
Zero is also a meaningful fault byte (all supply-OK bits clear); pair with SawCriticalFault.

◆ Log()

template<typename Derived >
void tle92466ed::SpiInterface< Derived >::Log ( LogLevel  level,
const char *  tag,
const char *  format,
  ... 
)
inlinenoexcept

Log a message with specified severity level and tag.

Platform-specific logging implementation. The driver uses this to log diagnostic information, errors, warnings, and debug messages.

Parameters
levelLog severity level
tagTag/component name for the log message (e.g., "TLE92466ED")
formatFormat string (printf-style)
...Variable arguments for format string
Note
Implementations should use platform-specific logging (e.g., ESP_LOG for ESP32)
The format string and arguments follow printf-style formatting

◆ NoteCriticalFault()

template<typename Derived >
void tle92466ed::SpiInterface< Derived >::NoteCriticalFault ( const SPIFrame &  frame)
inlineprotectednoexcept

Latch a critical-fault reply so callers can report the cause.

◆ operator=() [1/2]

template<typename Derived >
SpiInterface & tle92466ed::SpiInterface< Derived >::operator= ( const SpiInterface< Derived > &  )
delete

◆ operator=() [2/2]

template<typename Derived >
SpiInterface & tle92466ed::SpiInterface< Derived >::operator= ( SpiInterface< Derived > &&  )
protecteddefaultnoexcept

◆ Read()

template<typename Derived >
CommResult< uint32_t > tle92466ed::SpiInterface< Derived >::Read ( uint16_t  address,
bool  verify_crc = true 
)
inlinenoexcept

Read a register from the TLE92466ED (High-Level API)

Parameters
addressRegister address (10-bit, 0x000-0x3FF)
verify_crcIf true, verify CRC in response (default: true)
Returns
CommResult<uint32_t> Register value (16-bit or 22-bit depending on reply mode) or error

This function handles the complete read operation:

  • Constructs the read frame with address
  • Calculates and adds CRC
  • Performs first SPI transfer (sends command, receives dummy data)
  • Performs second SPI transfer (sends dummy command, receives actual response)
  • Parses the response based on reply mode
  • Verifies CRC if requested
Note
Pipelined reply: frame 1 transmits the read command (MISO is not yet valid for that address); frame 2 is a dummy read that clocks out the latched reply. Both frames are sent via TransferMulti() in one CS window — adapters must not split them on shared buses.
Replies are validated, not trusted. A reply is accepted only if its CRC checks out and its reply mode matches the width the register is defined to answer with (ExpectedReplyFor). Reads are retried until one qualifies. An unreadable register therefore returns an error instead of a plausible-looking value.
Warning
verify_crc no longer disables validation; it is kept only for API compatibility. Callers that passed false were the reason corrupt and stale frames were decoded as register content.
Return values
CommError::CRCErrorFrames arrived but none were well formed.
CommError::NoReplyMISO was idle for every attempt.
Note
Frame construction and CRC calculation are handled automatically. External code should typically use the Driver API; this method is available for advanced use cases.

◆ ReadMulti()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::ReadMulti ( std::span< const uint16_t >  addresses,
std::span< uint32_t >  values,
uint16_t &  valid_mask 
)
inlinenoexcept

Read several registers in ONE pipelined chain.

Parameters
[in]addressesRegister addresses, at most kMaxPipelinedReads.
[out]valuesDecoded register contents, same length as addresses. Entries whose reply failed validation are left as 0.
[out]valid_maskBit i set when values[i] is trustworthy. Never null-checked away: callers must inspect it.
Returns
Success when the chain transferred; individual replies may still have been rejected, which valid_mask reports.

The device answers each command on the NEXT CS window, so a burst of N reads needs N+2 frames — one leading dummy to absorb whatever reply was outstanding, the N commands, and one trailing dummy to clock out the last reply. Reply i therefore lands in frame i+2.

That is the whole point of this call: Read spends 3 frames per register because it opens and closes the pipeline every time, so N reads cost 3N frames. Here they cost N+2 — for the six-channel FB_DC/FB_I_AVG sweep that is 14 frames instead of 36, inside one bus-ownership window.

Replies are validated exactly as in Read (CRC plus the reply width ExpectedReplyFor defines for that address). No retry is attempted: re-running the whole burst to recover one bad frame costs more than the caller re-reading that single register with Read, and a desynchronised chain fails validation wholesale rather than returning plausible garbage.

Warning
The adapter's TransferMulti must keep one bus-ownership window across the entire chain. An adapter that falls back to per-frame transfers breaks the pipeline; the reply validation will reject the results rather than let them through.

◆ SawCriticalFault()

template<typename Derived >
bool tle92466ed::SpiInterface< Derived >::SawCriticalFault ( ) const
inlinenoexcept

True once a critical-fault reply frame has been decoded.

◆ Transfer32()

template<typename Derived >
CommResult< uint32_t > tle92466ed::SpiInterface< Derived >::Transfer32 ( uint32_t  tx_data)
inlinenoexcept

Transfer 32-bit data via SPI (full-duplex)

Performs a full-duplex SPI transaction, simultaneously sending and receiving 32 bits of data. This is the primary communication method for the TLE92466ED.

The TLE92466ED requires 32-bit SPI frames with the following format:

  • Bits [31:24]: CRC-8 (SAE J1850)
  • Bits [23:17]: Register address (7 bits of 10-bit address)
  • Bit [16]: R/W (1=Write, 0=Read)
  • Bits [15:0]: Data (16 bits)
Parameters
[in]tx_dataThe 32-bit data to transmit
Returns
CommResult<uint32_t> Received 32-bit data or error
Return values
CommError::TransferErrorSPI transfer failed
CommError::TimeoutTransfer timeout
Timing Requirements:
  • CS must be asserted (low) before transfer and deasserted (high) after
  • CS must be held low during entire 32-bit transfer
  • CSN lead and lag time: at least 250 ns each (t_CSN_LEAD, t_CSN_LAG)
  • Minimum CS inactive time between transfers: 600 ns (t_CSN_TD)
  • SI sampled on the falling edge of SCK, SO shifted on the rising edge (mode 1) (datasheet 5.1.4 Table 18 and 5.2)
Note
Chip select (CS) management must be handled internally by this function. The implementation should assert CS before the transfer and deassert it after. CRC calculation is handled by the driver layer, not CommInterface.

◆ TransferMulti()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::TransferMulti ( std::span< const uint32_t >  tx_data,
std::span< uint32_t >  rx_data 
)
inlinenoexcept

Transfer multiple 32-bit words via SPI in one CS assertion window.

Performs consecutive full-duplex 32-bit transfers while CS remains asserted. The driver relies on this for pipelined register access: each Read() / Write() passes exactly two words (command frame, then dummy frame that clocks out the latched reply).

Parameters
[in]tx_dataSpan of transmit data (32-bit words)
[out]rx_dataSpan to store received data (32-bit words)
Returns
CommResult<void> Success or error code
Return values
CommError::InvalidParameterBuffer size mismatch
CommError::TransferErrorTransfer failed
Precondition
tx_data.size() == rx_data.size()
Both spans must be valid for the duration of the transfer
Warning
Platform requirement: on shared SPI buses, the adapter must keep CS asserted and must not yield bus ownership between the command and dummy frames of a pipelined read. Releasing the bus mid-pair is a common cause of all-zero or cross-slave corrupted register values (including inflated feedback currents).

◆ Write()

template<typename Derived >
CommResult< void > tle92466ed::SpiInterface< Derived >::Write ( uint16_t  address,
uint16_t  value,
bool  verify_crc = true 
)
inlinenoexcept

Write a register to the TLE92466ED (High-Level API)

Parameters
addressRegister address (10-bit, 0x000-0x3FF)
valueData value to write (16-bit)
verify_crcIf true, verify CRC in response (default: true)
Returns
CommResult<void> Success or error

This function handles the complete write operation:

  • Constructs the write frame with address and data
  • Calculates and adds CRC
  • Performs first SPI transfer (sends command, receives dummy data)
  • Performs second SPI transfer (sends dummy command, receives actual response)
  • Verifies CRC if requested
Note
Writes use the same two-frame pipeline as reads: frame 1 sends the write command; frame 2 clocks out the status reply. Both frames must stay in one TransferMulti() CS window on shared buses.
Frame construction and CRC calculation are handled automatically.

Member Data Documentation

◆ kMaxPipelinedReads

template<typename Derived >
constexpr size_t tle92466ed::SpiInterface< Derived >::kMaxPipelinedReads = 12
staticconstexpr

Largest burst ReadMulti will issue in one CS-session chain.

◆ last_critical_fault_flags_

template<typename Derived >
uint8_t tle92466ed::SpiInterface< Derived >::last_critical_fault_flags_ {0}
protected

◆ saw_critical_fault_

template<typename Derived >
bool tle92466ed::SpiInterface< Derived >::saw_critical_fault_ {false}
protected

The documentation for this class was generated from the following file: