esp8266 SPI duplex transfers

I’ve been working with the esp8266 spi driver by MetalPhreak located here. One of the issues I’ve found is that duplex transfers (where you want to both send and receive at the same time) don’t work correctly. If you attempt to call spi_transaction specifying 8 dout_bits and 8 din_bits 16 clocks will be sent (IIRC a receive followed by a transmit).

The misunderstanding is likely down to the fact that the esp8266 has very little documentation. And the SPI registers aren’t documented at all. However the Arduino guys seem to have figured it out and it works correctly in the Arduino IDE board pack for the esp8266.

The trick is to set the SPI_USER register just so. There are 3 bits which control the direction of transfer SPI_USR_MOSI, SPI_USR_MISO and SPI_DOUTDIN (bits 27,28 and 0). In order to send and receive you need to set SPI_DOUTDIN and SPI_USR_MOSI but NOT SPI_USR_MISO. At least that’s what’s worked for me.

I made the following modification to spi_transaction to fix this. Change the line reading:

if(din_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);}

to

  if((din_bits) && (dout_bits)) {
    SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN);
  } else {
    if(din_bits) {SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);}
  }

I’ll probably submit a pull request once I’ve made all the changes required for my project. But in this meantime this should work.