SPI

Functionality overview

Red Pitaya SPI does not use the standard cpol and cpha parameters, instead the mode can be one of the following:

  • LISL - Low idle level, sample on leading edge - equivalent to cpol=0, cpha=0

  • LIST - Low idle level, sample on trailing edge - equivalent to cpol=0, cpha=1

  • HISL - High idle level, sample on leading edge - equivalent to cpol=1, cpha=0

  • HIST - High idle level, sample on trailing edge - equivalent to cpol=1, cpha=1

../../../_images/SPI_modes.png

Figure 3.11 SPI modes (Image source)

The SPI commands feature three different function to configure the buffers for messages (using SCPI commands for explanation, but the same applies to the API commands).

  • SPI:MSG<n>:TX<m>:RX - Creates both the read (receive) and write (send) buffers for the specified message.

  • SPI:MSG<n>:TX<m> - Creates only the write buffer for the specified message. Deletes any previously created read buffer for the same message.

  • SPI:MSG<n>:RX<m> - Creates only the read buffer for the specified message. Deletes any previously created write buffer for the same message.

In the background (API commands) all the commands call the same function rp_SPI_SetBufferForMessage() which initializes the data for both the buffers for sending and receiving at the same time. Calling the function multiple times for the same message will delete the previous buffers and create new ones. This means that to create both the buffers for sending and receiving you have to use the SPI:MSG<n>:TX<m>:RX command. Calling the SPI:MSG<n>:TX<m> command and then the SPI:MSG<n>:RX<m> command will first create the buffer for sending (and not initialize the receiving buffer), then the second command will delete the previously created buffer for sending and create a new one for receiving. Consequently, it is impossible to create both the buffers for sending and receiving using a sequence of SPI:MSG<n>:TX<m> and SPI:MSG<n>:RX<m> commands as one of the buffers will never be initialized, resulting in an error when trying to read or write data (for SCPI commands this can result in an infinite loop when attempting to read the data from a nonexisting buffer).

Adding the :CS suffix (or setting the cs_change to true) to the command will toggle the CS line after sending/receiving the message. For most basic applications this is not needed.

Important notes

  • The SPI device path on Gen 2 boards is “/dev/spidev2.0” instead of the classic “/dev/spidev1.0”.

Code examples

Here are some examples of how to use the SPI commands on Red Pitaya:

Parameters and command table

Parameter options:

  • <mode> = {LISL, LIST, HISL, HIST} Default: LISL

  • <cs_mode> = {NORMAL, HIGH} Default: NORMAL

  • <bits> = {7, 8} Default: 8

  • <speed> = {1...100000000} Default: 50000000

  • <data> = {XXX, ... | #HXX, ... | #QXXX, ... | #BXXXXXXXX, ... } Array of data separated by commas

    • XXX = Dec format

    • #HXX = Hex format

    • #QXXX = Oct format

    • #BXXXXXXXX = Bin format

Available Jupyter and API macros:

  • SPI mode - RP_SPI_MODE_LISL, RP_SPI_MODE_LIST, RP_SPI_MODE_HISL, RP_SPI_MODE_HIST

  • SPI bit order - RP_SPI_ORDER_BIT_MSB, RP_SPI_ORDER_BIT_LSB

  • SPI state - RP_SPI_STATE_NOT, RP_SPI_STATE_READY

  • SPI CS mode - RP_SPI_CS_NORMAL, RP_SPI_CS_HIGH

SCPI

API, Jupyter

DESCRIPTION

ECOSYSTEM

SPI:INIT
Example:
SPI:INIT

C++: rp_SPI_Init()

Python: rp_SPI_Init()

Initializes the API for working with SPI.

1.04-18 and up

SPI:INIT:DEV <path>
Example:
SPI:INIT:DEV "/dev/spidev1.0"

C++: rp_SPI_InitDevice(const char *device)

Python: rp_SPI_InitDevice(<device>)

Initializes the API for working with SPI. <path> - Path to the SPI device.
On some boards, it may be different from the standard: /dev/spidev1.0

Shoulld be set to /dev/spidev2.0 on Gen 2 boards.

1.04-18 and up

SPI:RELEASE
Example:

SPI:RELEASE
C++: rp_SPI_Release()

Python: rp_SPI_Release()

Releases all used resources.

1.04-18 and up

SPI:SETtings:DEFault
Example:
SPI:SETtings:DEFault

C++: rp_SPI_SetDefaultSettings()

Python: rp_SPI_SetDefaultSettings()

Sets the settings for SPI to default values.

1.04-18 and up

SPI:SETtings:SET
Example:
SPI:SETtings:SET

C++: rp_SPI_SetSettings()

Python: rp_SPI_SetSettings()

Sets the specified settings for SPI.
Executed after specifying the parameters of communication.


1.04-18 and up

SPI:SETtings:GET
Example:
SPI:SETtings:GET

C++: rp_SPI_GetSettings()

Python: rp_SPI_GetSettings()

Gets the specified SPI settings.

1.04-18 and up

SPI:SETtings:MODE <mode>
Example:
SPI:SETtings:MODE LIST


C++: rp_SPI_SetMode(rp_spi_mode_t mode)

Python: rp_SPI_SetMode(<mode>)


Sets the mode for SPI.
- LISL = Low idle level, Sample on leading edge
- LIST = Low idle level, Sample on trailing edge
- HISL = High idle level, Sample on leading edge
- HIST = High idle level, Sample on trailing edge

1.04-18 and up

SPI:SETtings:MODE? > <mode>
Example:
SPI:SETtings:MODE? > LIST

C++: rp_SPI_GetMode(rp_spi_mode_t *mode)

Python: rp_SPI_GetMode()

Gets the specified mode for SPI.

1.04-18 and up

SPI:SETtings:CSMODE <cs_mode>
Example:
SPI:SETtings:CSMODE NORMAL


C++: rp_SPI_SetCSMode(rp_spi_cs_mode_t cs_mode)

Python: rp_SPI_SetCSMode(<cs_mode>)


Sets the mode for CS.
- NORMAL = After the message is transmitted,
the CS line is set to the HIGH state.
- HIGH = After the message has been transmitted,
the CS line is set to the LOW state.

2.00-18 and up

SPI:SETtings:CSMODE? > <cs_mode>
Example:
SPI:SETtings:CSMODE? > NORMAL

C++: rp_SPI_GetCSMode(rp_spi_cs_mode_t *cs_mode)

Python: rp_SPI_GetCSMode()

Gets the specified CS mode for SPI.

2.00-18 and up

- (NA)



C++: rp_SPI_SetOrderBit(rp_spi_order_bit_t order)

Python: rp_SPI_SetOrderBit(<order>)

Set SPI bit order.

2.04-35 and up

- (NA)



C++: rp_SPI_GetOrderBit(rp_spi_order_bit_t *order)

Python: rp_SPI_GetOrderBit()

Get SPI bit order.

2.04-35 and up

SPI:SETtings:SPEED <speed>
Example:
SPI:SETtings:SPEED 1000000

C++: rp_SPI_SetSpeed(int speed)

Python: rp_SPI_SetSpeed(<speed>)

Sets the speed of the SPI connection.

1.04-18 and up

SPI:SETings:SPEED? > <speed>
Example:
SPI:SETtings:SPEED? > 1000000

C++: rp_SPI_GetSpeed(int *speed)

Python: rp_SPI_GetSpeed()

Gets the speed of the SPI connection.

1.04-18 and up

SPI:SETtings:WORD <bits>
Example:
SPI:SETtings:WORD 8

C++: rp_SPI_SetWordLen(int len)

Python: rp_SPI_SetWordLen(<len>)

Specifies the length of the word in bits. Must be greater than or equal to 7.

1.04-18 and up

SPI:SETtings:WORD? > <bits>
Example:
SPI:SETtings:WORD? > 8

C++: rp_SPI_GetWordLen(int *len)

Python: rp_SPI_GetWordLen()

Returns the length of a word.

1.04-18 and up

SPI:MSG:CREATE <n>
Example:
SPI:MSG:CREATE 1
C++: rp_SPI_CreateMessage(size_t len)

Python: rp_SPI_CreateMessage(<len>)

Creates a message queue for SPI (reserves the space for data buffers)
Once created, they need to be initialized.
<n> - The number of messages in the queue.
The message queue can operate within a single CS state switch.

1.04-18 and up

SPI:MSG:DEL
Example:
SPI:MSG:DEL

C++: rp_SPI_DestroyMessage()

Python: rp_SPI_DestroyMessage()

Deletes all messages and data buffers allocated for them.

1.04-18 and up

SPI:MSG:SIZE? > <n>
Example:
SPI:MSG:SIZE? > 1

C++: rp_SPI_GetMessageLen(size_t *len)

Python: rp_SPI_GetMessageLen()

Returns the length of the message queue.

1.04-18 and up

SPI:MSG<n>:TX<m> <data>
SPI:MSG<n>:TX<m>:CS <data>
Example:
SPI:MSG0:TX4 1,2,3,4
SPI:MSG1:TX3:CS 2,3,4

C++: rp_SPI_SetBufferForMessage(size_t msg,const uint8_t *tx_buffer,bool init_rx_buffer,size_t len, bool cs_change)

Python: rp_SPI_SetBufferForMessage(<msg>, <tx_buffer>, <init_rx_buffer>, <len>, <cs_change>)



Sets data for the write buffer for the specified message.
CS - Toggles CS state after sending/receiving this message.
<n> - index of message 0 <= n < msg queue size.
<m> - TX buffer length.
Sends <m> ‘bytes’ from message <n>. No data is received.

1.04-18 and up

SPI:MSG<n>:TX<m>:RX <data>
SPI:MSG<n>:TX<m>:RX:CS <data>
Example:
SPI:MSG0:TX4:RX 1,2,3,4
SPI:MSG1:TX3:RX:CS 2,3,4



C++: rp_SPI_SetBufferForMessage(size_t msg,const uint8_t *tx_buffer,bool init_rx_buffer,size_t len, bool cs_change)

Python: rp_SPI_SetBufferForMessage(<msg>, <tx_buffer>, <init_rx_buffer>, <len>, <cs_change>)





Sets data for the read and write buffers for the specified message.
CS - Toggles CS state after sending/receiving this message.
<n> - index of message 0 <= n < msg queue size.
<m> - TX buffer length.
The read buffer is also created with the same length and initialized with zeros.

Sends <m> ‘bytes’ from message <n> and receives the same amount of data
from the dataline

1.04-18 and up

SPI:MSG<n>:RX<m>
SPI:MSG<n>:RX<m>:CS
Example:
SPI:MSG0:RX4
SPI:MSG1:RX5:CS


C++: rp_SPI_SetBufferForMessage(size_t msg,const uint8_t *tx_buffer,bool init_rx_buffer,size_t len, bool cs_change)

Python: rp_SPI_SetBufferForMessage(<msg>, <tx_buffer>, <init_rx_buffer>, <len>, <cs_change>)




Initializes a buffer for reading the specified message.
CS - Toggles CS state after receiving message.
<n> - index of message 0 <= n < msg queue size.
<m> - RX buffer length.

Receives <m> ‘bytes’ into message <n>. No data is transmitted.

1.04-18 and up

SPI:MSG<n>:RX? > <data>
Example:
SPI:MSG1:RX? > {2,4,5}

C++: rp_SPI_GetRxBuffer(size_t msg, const uint8_t **buffer, size_t *len)

Python: rp_SPI_GetRxBuffer(<msg>)

Returns a read buffer for the specified message.

1.04-18 and up

SPI:MSG<n>:TX? > <data>
Example:
SPI:MSG1:TX? > {2,4,5}

C++: rp_SPI_GetTxBuffer(size_t msg, const uint8_t **buffer, size_t *len)

Python: rp_SPI_GetTxBuffer(<msg>)

Returns the write buffer for the specified message.

1.04-18 and up

SPI:MSG<n>:CS? > ON|OFF
Example:
SPI:MSG1:CS? > ON

C++: rp_SPI_GetCSChangeState(size_t msg, bool *cs_change)

Python: rp_SPI_GetCSChangeState(<msg>)

Returns the setting for CS mode for the specified message.

1.04-18 and up

SPI:PASS
Example:
SPI:PASS

C++: rp_SPI_ReadWrite()

Python: rp_SPI_ReadWrite()

Sends the prepared messages to the SPI device.

1.04-18 and up

- (NA)



C++: NA

Python: Buffer(<size>)

Creates a buffer for sending and receiving data.

2.04-35 and up