ArduinoCore-API icon indicating copy to clipboard operation
ArduinoCore-API copied to clipboard

Suggest adding SPI_writeAnything to SPI library

Open nickgammon opened this issue 8 years ago • 7 comments

I have the following small template library on my page about SPI ( http://www.gammon.com.au/spi ):

template <typename T> unsigned int SPI_writeAnything (const T& value)
  {
    const byte * p = (const byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          SPI.transfer(*p++);
    return i;
  }  // end of SPI_writeAnything

template <typename T> unsigned int SPI_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = SPI.transfer (0);
    return i;
  }  // end of SPI_readAnything


template <typename T> unsigned int SPI_readAnything_ISR(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    *p++ = SPDR;  // get first byte
    for (i = 1; i < sizeof value; i++)
          *p++ = SPI.transfer (0);
    return i;
  }  // end of SPI_readAnything_ISR  

The function SPI_readAnything_ISR is for using inside an ISR, as it directly accesses SPDR.

It has been suggested to me that I request that you include this in the standard SPI library (SPI.h). This lets you more easily send things like floats or structs via SPI. For example:

  float fnum = 42.666;
  digitalWrite(SS, LOW);  
  SPI_writeAnything (fnum);
  digitalWrite(SS, HIGH);

Being a template function it won't add any bloat unless you actually use it.

Related request: https://github.com/arduino/Arduino/issues/3691

nickgammon avatar Aug 17 '15 21:08 nickgammon

@nickgammon Does the example really work? There is a missing <float> I believe. Guess you had the same problem as I with the quoting in markdown.

BW: C++ allows overloading so the naming is a bit "old fashion" :)

mikaelpatel avatar Aug 17 '15 23:08 mikaelpatel

Does the example really work?

It works as-is. The template deduces the type from the argument type (fnum is float). Try it yourself.

C++ allows overloading so the naming is a bit "old fashion"

It is named after the EEPROMWriteAnything template library in: http://playground.arduino.cc/Code/EEPROMWriteAnything

I left off the "write" part because it also reads.

nickgammon avatar Aug 17 '15 23:08 nickgammon

@nickgammon The definition is an "anything" but the usage is a specific type. It is good practice to be explicit even if the compiler does the type deduction. The notation write<float>(fnum) if easier to understand than writeAnything(fnum).

mikaelpatel avatar Aug 17 '15 23:08 mikaelpatel

Yes, but there is already a "write" function.

nickgammon avatar Aug 18 '15 02:08 nickgammon

Are you suggesting it as a templated overload of the standard write? I suppose that could work, so I will leave that to the library implementers which approach they would prefer.

nickgammon avatar Aug 18 '15 02:08 nickgammon

@nickgammon Yes, I am suggesting overloading write to force explicit type when using the template function. Also I would like to suggest optimizing the transfer as there is plenty of cycles to perform the data fetch/store while busy waiting for the hardware.

mikaelpatel avatar Aug 18 '15 08:08 mikaelpatel

@nickgammon BW: This topic and the suggested read function variant for ISR has given me some insight to improving the Cosa SPI library. The ISR/Slave mode is poorly supported. Thanks!

mikaelpatel avatar Aug 18 '15 08:08 mikaelpatel