Software SPI

Software SPI is likely to be of use only for ESP8266, but is enabled for all architectures.

The ESP8266 can manage a minimum of about 70ns between bit edges, with a maximum of about 1.8 MBit/s at normal CPU clock frequency or 2.5 MHz if CPU clock set to fast.

Build variables

SPISOFT_DELAY_VARIABLE

default: 0 (disabled)

This setting must be enabled in order to use SPISoft::setDelay(). The base clock speed (i.e. delay=0) is reduced to about 1.4 MBit/s (2.1 MBit/s for fast CPU).

The appropriate delay factor can be provided in the SPISoft constructor, or by calling SPISoft::setDelay().

With the ESP8266, then the appropriate delay factor is calculated automatically from the speed passed in SPISettings. This will override any previously set delay factor. Use a speed of 0 to use the manually configured delay value.

SPISOFT_DELAY_FIXED

default: 0 (disabled) maximum: 10

Adds the requested number of ‘NOP’ CPU instructions to every clock transition.

Has less impact than enabling variable delays.

Use variable delays if 10 is insufficient.

Will be ignored if variable delays are enabled.

Performance

The following information has been obtained by measurement. The test application was built using:

make SPISOFT_CALIBRATE=1 SPISOFT_DELAY_VARIABLE=1 CPU_FAST=0

then flashed to an ESP-12F. An oscilliscope was hooked up to the SCK output and the maximum frequency at each delay setting noted. (Not too awkward, just note down the frequency each time the figure changes.)

Entering these into the spisoft.ods spreadsheet allows the values to be charted and co-efficients calculated.

Curiously values from 8 upward form a straight line so we can calculate those. Smaller values are non-linear so a small lookup table is used.

Repeat for CPU_FAST=1.

Note that these figures are concerned with maximum (i.e. burst) frequencies at each delay setting, since that is what devices are sensitive to.

80 MHz CPU

../../../../_images/spisoft-80.png

.

Frequency (kHz)

Delay

Variable

Fixed

0

1357

2288

1

1315

1869

2

1215

1824

3

1129

1780

4

1055

1744

5

990

1709

6

932

1639

7

881

1575

8

819

1511

9

743

1462

10

680

1408

11

626

1338

12

578

1294

20

367

30

251

40

192

50

155

60

129

70

112

80

98

90

87

100

79

160 MHz CPU

../../../../_images/spisoft-160.png

.

Frequency (kHz)

Delay

Variable

Fixed

0

2133

2857

1

2126

2510

2

2106

2500

3

1958

2439

4

1861

2429

5

1745

2372

6

1668

2353

7

1573

2294

8

1482

2283

9

1357

2242

10

1250

2222

11

1160

2174

12

1081

2165

20

702

30

488

40

374

50

303

60

255

70

220

80

193

90

172

100

156

API Documentation

class SPISoft : public SPIBase
#include <SPISoft.h>

Software-based SPI master.

Intended for ESP8266 due to limited I/O but will work on any architecture.

Constructors

SPISoft()

Default constructor uses same pins as hardware SPI.

inline SPISoft(uint8_t miso, uint8_t mosi, uint8_t sck, uint8_t delay = 0)

Specify pins to use plus optional delay.

Delay is ignored if code is not compiled with SPISOFT_DELAY < 0.

inline SPISoft(const SpiPins &pins, uint8_t delay = 0)

Specify pins plus optional delay.

SPISoft(uint8_t delay)

Use default pins but provide a delay.

Public Functions

virtual bool begin() override

Initialize the SPI bus by setting SCK and MOSI to outputs, pulling SCK and MOSI low.

inline virtual void end() override

Disable the SPI bus (leaving pin modes unchanged).

virtual void endTransaction() override

Stop using the SPI bus. Normally this is called after de-asserting the chip select, to allow other libraries to use the SPI bus.

virtual uint32_t transfer32(uint32_t val, uint8_t bits = 32) override

Send/receive a word of variable size.

Word is transferred either MSB first (bits-1) or LSB first (bit 0) depending on the currently applied bitOrder setting.

Parameters
  • val – Word to send

  • bits – Size of word

virtual void transfer(uint8_t *buffer, size_t size) override

Send/receive a variable-length block of data.

Parameters
  • buffer – IN: The data to send; OUT: The received data

  • size – Number of bytes to transfer

inline void setDelay(uint8_t delay)

Set delay factor for the SCK signal. Impacts SPI speed.

Requires code to be compiled with SPISOFT_DELAY < 0.

ESP8266 only: The delay will be automatically calculated for a requested clock speed when begin() or beginTransaction() are called. To use only the manually programmed delay, set the clock speed to zero.

inline virtual bool loopback(bool enable) override

For testing, tie MISO <-> MOSI internally.

Note: Not included in std Arduino lib