16-bit SPI implementation on ARM platform


#1

Hi David,

How do you feel about implementing 16bit spi transfers ? (preferably on ARM boards)
Something like (write-word) and (read-word).

transfer() and transfer16() are both a standard function in the spi lib.
It would be nice to have , because many tft displays with spi interface
require a 16 bit value to tranfer for sending data to the display (16bit RGB)
for example the ILI9341.
I’m using a workaround now by implementing a ‘fake’ CS
something like this :

(digitalwrite 10 low)
(with-spi (9,4000,0,0) 
(write-byte HH str)
(write-byte LL str))
(digitalwrite 10 high)

10 is the real CS pin , as 9 is the fake CS pin
pin 9 is therefore lost , it can not be used for something else.

Kind regards,
Ronny


#2

Hi Ronny,

Thanks for the suggestion. Streams are handled in a uniform way in uLisp, allowing you to use any input/output command with any stream, such as I2C, SPI, or Serial. However, all the streams are currently 8-bit, so 16-bit SPI transfers couldn’t be integrated with the existing functionality.

If you need these I therefore suggest you add them as separate uLisp functions; see Adding your own functions. I think it should be very straightforward; for example, write-word will look something like:

object *fn_writeword (object *args, object *env) {
  (void) env;
  int word = checkinteger(WRITEWORD, first(args));
  return number(transfer16(word));
}

The checkinteger() call converts the first Lisp argument to an integer (and gives an error if it isn’t an integer), and the number() call converts the integer returned by transfer16() to a Lisp integer object.

Ask if you need more help.
Regards, David


#3

Hi David ,

Thanks for the code.
It seems to work fine , although I did not test it on my display , just on the logic.
One small correction , its ‘SPI.transfer16’ not tranfer16 . :-)
One more question , how would you code it for a read ?
something like (read-word) ?
I guess the last line should be something like :
return number(transfer16()); ?

Kind regards ,
Ronny


#4

Doesn’t an SPI transfer do a write and a read simultaneously? In that case you’d just need one routine you could call transfer-word. If you just want to read you could call it with 0 and get the result.


#5

Hi David ,

Yes it is , but I want to have both like (write-byte) and (read-byte)
Can I do this ?

object *fn_readword (object *args, object *env) {
  (void) env;
  // int word = checkinteger(WRITEWORD, first(args));
  return number(transfer16());
}

Kind regards,
Ronny


#6

Hi Ronny,

Yes, exactly, although to avoid a warning message you should add:

object *fn_readword (object *args, object *env) {
  (void) args, (void) env;
  return number(transfer16());
}

Regards,
David


#7

Hi David ,

Thanks.
It looks that transfer16() gives an error , I changed it to transfer16(0xffff) and then it’s ok.
This still keeps it transparent regarding read and write 16

Regards,
Ronny