Hi Paul,
I have also done some playing with the faster ili9341 driver and trying to enable the fifo, and as I mentioned, some of the register status values were not clear. Can detect when there is room in the queue, and when the output queue is empty and nearly empty, but was unclear if the empty was just for the fifo or had it shifted out the last bits of the last byte to output....
defragster - The issue, is timing when the CS and the DC(Data/Command) IO pins are changed as related to the data lines (Clk, MISO, MOSI). Example suppose you wish to set a pixel, the code for this turns in to:
Code:
ILI9341_t3::drawPixel(int16_t x, int16_t y, uint16_t color) {
writecommand_cont(ILI9341_CASET); // Column addr set
writedata16_cont(x); // XSTART
writedata16_cont(x); // XEND
writecommand_cont(ILI9341_PASET); // Row addr set
writedata16_cont(y); // YSTART
writedata16_cont(y); // YEND
writecommand_cont(ILI9341_RAMWR);
writedata16_last(color);
}
I won't go into the full details about above, except: each time you go from command to data or data to command, the DC line changes, likewise the _cont says to continue holding the CS line and last says we will release CS after the write. Also 16 is a write of 16 bits versus 8 bits (On the 3.1, each one of these writes translate to one entry in the fifo queue, which encodes both the CS and the DC changes as part of the queue entry. The only waiting is after we add an item to the queue, we wait until the queue is not full... With this the system is doing all of the work for changing the DC and CS pins at the right time.
Now with the LC, we have to wait until the output queue is completely empty (last bit output) and then do the change of the DC and/or CS pins through digitalWrite() or hopefully faster equivalent.
will assume queue empty when I try to output: ILI9341_CASET command as probably previous command cleared queue. So we set CS and DC, push it on the queue, then we go to write the X values out, DC changes, so we have to wait until queue is empty, then clear DC and push the 16 bits of X twice (start and end), then we need to wait until those bytes are output, set DC, push PASET, wait, clear DC, push 4 bytes for Y...
So in the above: we probably have to wait for the queue to empty at least 6 times, where we change DC and/or CS. Each time we do this, there will be a gap of time when SPI pins are not outputting something.
However I still think there can be some pretty big wins. For example in things like fill rect. The code to do this is more or less identical to the draw pixel, except we output two different X's and Y's instead of the same ones twice and then after the ILI9341_CASET, we call: writedata16_cont(color); (w*h -1) times then writedata16_last(color); So would have the same number of IO pin state changes. So again things like: fill screen, fill rect, horizontal line, vertical line, write rect, text with background color specified, ... All should be pretty fast. However things that draw random lines, text with transparency ... Will not gain much speed over standard ILI9341 driver.
Hope that makes sense?
Paul: in the ST7735 driver I have this done like:
Code:
void Adafruit_ST7735::writecommand(uint8_t c)
{
*rsport &= ~rspinmask;
*csport &= ~cspinmask;
//Serial.print("C ");
spiwrite(c);
*csport |= cspinmask;
}
Which I personally don't like, as *csport & ~cspinmask is a two step process. Read the current state of N pins (8), change the state of 1 of them and write it back. Now if something like an interrupt changes the state of one of the 8 pins after I did the read but before the write, this code would stomp on it... I am pretty sure I can change this to keep two registers (set/clear) and do this atomic?
Edit: I think this is off topic and create a new thread as this is not specific to Arduino 1.6 and probably deserves it's own thread:
https://forum.pjrc.com/threads/27981-ILI9241_t3-support-for-Teensy-LC?p=67013#post67013