Monday, February 18, 2013

Arduino Due SPI Display - Nearly Defeated

I have been working over a week on trying to get an Adafruit SPI driven display to work on the Arduino Due.  No, it still does not work and I'm not happy.
The Due SPI interface has fairly incomplete documentation.  From the clock divider function call having do documentation on divisors to supposed support for more than 8 bit transfers (but zero documentation on that).

So writing an interface with native function calls is pretty much moot at this point.

On the Arduino Uno, most high performance code manipulated processor registers to get the speeds necessary for pumping out the data to a display fast enough to see in real time.  It turns out direct register calls work with Due also.  The best example is the gLCD Library by Tom Carpenter documented in this forum post.  Pretty good stuff but once you get to AVR/Uno normal and high speed, Due normal and high speed, the complexity rises exponentially.

My work has been to splice the initialization and display write code into the Adafruit HX8340B library.  Not an easy task after mastering the Due blink sketch.

First you have to make the original code Due compatible.  This involves compiler directives to detect a Due target platform.  The Due does not have some features of the originals.  The following is to move data that an AVR places in Program Memory (PROGMEM) into the more ample RAM of the Due (and the fact that PROGMEM is not handled like the AVR on the Due if at all):

#ifdef __SAM3X8E__
#define PROGMEM static
#define pgm_read_byte(x)        (*((char *)x))
#define prog_uchar uint8_t
#include <avr/pgmspace.h>

This should work with #ifdef _LIB_SAM_ also but I have issues with that consistently working.

Then there is adding code for SPI again with #ifdef modifiers to put in Due code instead of AVR code where necessary.  Pretty complex.

Where I have bogged down is:
  1. Are Arduino SPI calls necessary for direct register (probably yes), so is a divisor of 21 for 4 MHz (84/21=4)?  No documentation.
  2. The gLCD library and Adafruit library have different handshakes for starting to enable the signal lines. I'd trust Adafruit did theirs right.
  3. Setting pinMode for SPI data lines causes the code to hang.  Are these needed and if so how to not have them hang.  A real debugger would help.
So at this point I'm setting the work aside.  I can post some code on Github if anyone wishes to review things.

If I get creative, I'll probably do two things:

  1. Fire up my DSO Nano scope - I haven't used it yet but I should to see what pins are doing.  An 8 bit 100 MHz logic analyzer would be preferable but I don't have one.
  2. Start at the basics - get just the Due code running - probably by starting with basic SPI oerations, then building on that.  It would be better to have a real simple SPI device to do this on that gives clear indications of operation rather than the complex display I have.  Ideas?