This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

USB2ANY: Multibyte I2C Transactions

Part Number: USB2ANY

Tool/software:

Hi,

Does USB2Any support multibyte I2C transactions?

Example:

Working Case : I2C Write (Slave Addr, Reg Addr, Data (1byte)) 

Expected Case : I2C Write (Slave Addr, Reg Addr, Data (n-bytes))

Thanks,

Katie

  • Revision History:

    • 19 JUL 2024 - Initial version
    • 25 SEP 2024 - MultiRegisterRead has a STOP -> START behavior, not a repeated-START behavior; rearrange and redraw some diagrams; better efficiency guidance; add revision history so edits are tracked; rearrange response below for better context

    Does USB2Any support multibyte I2C transactions?

    It does, provided you use the multibyte variants of the I2C APIs.

    USB2ANY includes several API variants that have subtly different I2C transaction signatures. Refer to the legend and diagrams below.


    • int u2aI2C_RawRead(U2A_HANDLE handle, UInt16 I2C_Address, Byte nBytes, Byte *Data):
      • Controller STARTs, controller begins a read transaction, target ACKs
      • Target writes nBytes bytes of data, controller ACKs each byte, controller STOPs
    • Notes:
      • Returns number of bytes read on success, or a negative error code on failure
      • nBytes must be <= 51 (USB2ANY uses 64-byte HID packets, of which 10 bytes are header, and 3 bytes are API arguments in the payload for the u2aI2C_RawRead API)

    • int u2aI2C_RawWrite(U2A_HANDLE handle, UInt16 I2C_Address, Byte nBytes, Byte *Data):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • Controller writes nBytes bytes of *Data, target ACKs each byte, controller STOPs
    • Notes:
      • Returns 0 on success, or a negative error code on failure
      • nBytes must be <= 51 (USB2ANY uses 64-byte HID packets, of which 10 bytes are header, and 3 bytes are API arguments in the payload for the u2aI2C_RawWrite API)

    • int u2aI2C_RegisterRead(U2A_HANDLE handle, UInt16 I2C_Address, Byte RegisterAddress):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • Controller writes one-byte RegisterAddress, target ACKs, controller STOPs
      • Controller STARTs, controller begins a read transaction for target at I2C_Address, target ACKs
      • Target writes one byte of data, controller ACKs, controller STOPs
    • Notes:
      • Returns one-byte data value cast to int on success, or a negative error code on failure
      • No repeated start between write and read transfers


    • int u2aI2C_RegisterWrite(U2A_HANDLE handle, UInt16 I2C_Address, Byte RegisterAddress, Byte Value):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • Controller writes one-byte RegisterAddress, target ACKs
      • Controller writes one-byte Value, target ACKs, controller STOPs
    • Notes:
      • Returns 0 on success, or a negative error code on failure

    • int u2aI2C_MultiRegisterRead(U2A_HANDLE handle, UInt16 I2C_Address, Byte StartingRegisterAddress, Byte nBytes, Byte *Data):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • Controller writes one-byte StartingRegisterAddress, target ACKs, controller STOPs
      • Controller STARTs, controller begins a read transaction for target at I2C_Address, target ACKs
      • Target writes nBytes bytes of *Data, controller ACKs each byte, controller STOPs
    • Notes:
      • Returns number of bytes read on success, or a negative error code on failure
      • No repeated start between write and read transfers
      • nBytes must be <= 50 (USB2ANY uses 64-byte HID packets, of which 10 bytes are header, and 4 bytes are API arguments in the payload for the u2aI2C_MultiRegisterRead API)


    • int u2aI2C_MultiRegisterWrite(U2A_HANDLE handle, UInt16 I2C_Address, Byte StartingRegisterAddress, Byte nBytes, Byte *Data):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • Controller writes one-byte StartingRegisterAddress, target ACKs
      • Controller writes nBytes bytes of *Data, target ACKs each byte, controller STOPs
    • Notes:
      • Returns zero on success, or a negative error code on failure
      • nBytes must be <= 50 (USB2ANY uses 64-byte HID packets, of which 10 bytes are header, and 4 bytes are API arguments in the payload for the u2aI2C_MultiRegisterWrite API)
      • The payload efficiency of u2aI2C_MultiRegisterWrite is strictly less than u2aI2C_RawWrite. There is no reason to use this function instead of u2aI2C_RawWrite if the user can construct their own buffer with the target register address included in the *Data payload.

    • int u2aI2C_InternalRead(U2A_HANDLE handle, UInt16 I2C_Address, UInt16 InternalAddress, Byte IntAddrSize, UInt16 nBytes, Byte *Data):
      • Controller starts, controller begins a write transaction for target at I2C_Address, target ACKs
      • If IntAddrSize == 0:
        • Target writes nBytes bytes of *Data, controller ACKs each byte, controller STOPs
      • If IntAddrSize == 1:
        • Controller writes least-significant byte of InternalAddress, target ACKs
        • Controller repeated-STARTs, controller begins a read transaction, target ACKs
        • Target writes nBytes bytes of *Data, controller ACKs each byte, controller STOPs
      • If IntAddrSize == 2:
        • Controller writes two-byte InternalAddress (as big-endian), target ACKs each byte
        • Controller repeated-STARTs, controller begins a read transaction, target ACKs
        • Target writes nBytes bytes of *Data, controller ACKs each byte, controller STOPs
    • Notes:
      • Returns number of bytes read on success, or a negative error code on failure
      • Repeated-START between write and read segments of transfer (for IntAddrSize > 0)
      • nBytes must be <= 47 (USB2ANY uses 64-byte HID packets, of which 10 bytes are header, and 7 bytes are API arguments in the payload for the u2aI2C_InternalRead API)
      • For some reason, nBytes in InternalRead/InternalWrite arguments are UInt16, even though the value can never be greater than 47. I think at one point the API was supposed to handle a much-larger buffer using on-board memory and an alternative, non-HID channel, but this is just speculation on my part.
      • The payload efficiency of u2aI2C_InternalRead is strictly less than u2aI2C_RawRead or u2aI2C_MultiRegisterRead. There is no reason to use u2aI2C_InternalRead instead of u2aI2C_RawRead for IntAddrSize == 0. However, the presence of a repeated START makes u2aI2C_InternalRead behaviorally distinct from u2aI2C_MultiRegisterRead, so in some circumstances u2aI2C_InternalRead may be the better option for IntAddrSize == 1.


    • int u2aI2C_InternalWrite(U2A_HANDLE handle, UInt16 I2C_Address, UInt16 InternalAddress, Byte IntAddrSize, UInt16 nBytes, Byte *Data):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • If IntAddrSize == 0:
        • Controller writes nBytes bytes of *Data, target ACKs each byte, controller STOPs
      • If IntAddrSize == 1:
        • Controller writes least-significant byte of InternalAddress, target ACKs
        • Controller writes nBytes bytes of *Data, target ACKs each byte, controller STOPs
      • If IntAddrSize == 2:
        • Controller writes two-byte InternalAddress (as big-endian), target ACKs each byte
        • Controller writes nBytes bytes of *Data, target ACKs each byte, controller STOPs
    • Notes:
      • Returns 0 on success, or a negative error code on failure
      • nBytes must be <= 47 (USB2ANY uses 64-byte HID packets, of which 10 bytes are header, and 7 bytes are API arguments in the payload for the u2aI2C_InternalWrite API)
      • For some reason, nBytes in InternalRead/InternalWrite arguments are UInt16, even though the value can never be greater than 47. I think at one point the API was supposed to handle a much-larger buffer using on-board memory and an alternative, non-HID channel, but this is just speculation on my part.
      • The payload efficiency of u2aI2C_InternalWrite is strictly less than u2aI2C_RawWrite or u2aI2C_MultiRegisterWrite, even though the behavior for zero-byte and one-byte register addresses (respectively) is otherwise identical. There is no reason to use this function instead of u2aI2C_RawWrite if the user can construct their own buffer with the target register address included in the *Data payload.


    • int u2aI2C_BlockWriteBlockRead(U2A_HANDLE handle, UInt16 I2C_Address, Byte nWriteBytes, Byte *WriteData, Byte nReadBytes, Byte *ReadData):
      • Controller STARTs, controller begins a write transaction for target at I2C_Address, target ACKs
      • Controller writes nWriteBytes bytes of *WriteData, target ACKs each byte
      • Controller repeated-STARTs, controller begins a read transaction for target at I2C_Address, target ACKs
      • Target writes nReadBytes bytes of *ReadData, controller ACKs each byte, controller STOPs
    • Notes:
      • Returns 0 on success, or a negative error code on failure
      • nWriteBytes + nReadBytes must be <= 32. Why? Who knows... the firmware contains a comment stating this is "per spec", but the spec is helpfully absent from the source repository. Presumably someone needed this functionality.