Adafruit 2.8" TFT Touch Shield for Arduino for Teensy 3.1

Status
Not open for further replies.

KurtE

Senior Member+
For the heck of it, I purchased one of these, to use to try out on my Teensy 3.1 breakout board that has Arduino Headers.

This display uses the Adafruit_ILI9341 library, which did not compile. I have the impression that it might work the the converted ILI9340 library, but when I tried it did not work. That was before I figured out that the display I received was DOA. Adafruit promptly sent me a replacement, which I then verified that it worked with an Arduino UNO, which it did.

So then I modified the ILI9341 library with similar changes that were in the ILI9340 library and now have the display working. The shield uses standard SPI pins 9-11 (or you can cut some jumpers and solder other jumpers to use SPI out of ISP connector, to use with Leonaro and Megas). It uses Pin 8 as CS

Next thing to try was the touch screen. This uses the library Adafruit_STMPE610, which I downloaded and it compiles... So tried the Sample Paint program which fails to Init the touch screen. Looking at the STMPE610 documentation, it states the maximum speed for SPI communications is 1mhz. On their shield the CS for this chip is Pin 6.

Looking at the both libraries, it looks like the Display wants to run SPI at 8mhz (SPI_CLOCK_DIV2 on __AVR__, /11 on DUE) and as I mentioned above the TS wants to run at 1mhz (SPI_CLOCK_DIV16 on __AVR__, /84 on DUE)

Question what is the best way to handle this with Teensy 3? Right now with display I simply am not setting the speed (like in 9340 code base), and that appears to work.

Suggestions? Should I use predefined dividers like avr?

Windows 7, Teensydino 1.18, Arduino 1.0.5...

Thanks
Kurt
 
Question what is the best way to handle this with Teensy 3? Right now with display I simply am not setting the speed (like in 9340 code base), and that appears to work.

I've been working on a contribution to Arduino for their SPI library, to add an API that allows conflicting SPI device to work together easily. I've also been talking with Adafruit about patching their libraries, once this becomes officially part of Arduino.

I'm hopeful it'll appear in Arduino 1.5.7 and I'll put it into Teensyduino 1.19 or 1.20.

You did ask what the "best" way is! ;)

I recently purchased this exact Adafruit product for testing. I can't possible do anything with it before Maker Faire. I do plan to have a fix for this in June. If the Arduino folks don't accept the SPI library contribution, I'll come up with a Teensy-only solution. That that won't happen until at least early June.
 
As a quick hack, you might try deleting all the Due stuff from their library. Teensy has excellent compatibility with libraries designed for AVR chips.
 
Thanks,

I think I have a version that appears to work. Probably needs lots of testing, but ran graphics test and touch paint both on my Teensy 3.1 and on Uno.

For SPI speed, everywhere it set the speed, I #ifdef for TEENSY_CORE and set the speed like it did for __AVR__

Kurt
 

Attachments

  • AdaFruit 2.8 touchscreen.zip
    31.9 KB · Views: 736
Update: next test is the spitftbitmap test, which tries to read an image from the on board (display board) microsd. The CS pin is pin 4 on the SPI buss. The call to SD.begin(SD_CS) is failing. Now to try to localize down where...

Edit: Traced through different parts. It is failing when sdVolume class call sdcard's readblock. Looking through some of this,
my guess is there may be issues with: mixing implementations of SPI in program.

That is: Display code (and potentially touch screen) is using the spi.h/cpp files which is going through the Arduino like emulation of SPI, where it looks like, the sd code is maybe going in and using the real hardware SPI...

Note: also example listfiles under SD also failed same way. (I edited to match the CS=4). Wonder if maybe it would work with SD adapters on default of 10?
 
Last edited:
Well after playing with the sd library for awhile and not having much luck here, I finally figured out that the sd library is not the same as sdfat library. That was after reading the later posts in the thread: http://forum.pjrc.com/threads/25582...interrupts-and-main-program?p=47270#post47270

So I downloaded latest released sdfat library code, made the edits, that Paul suggested. I then modified the Adafruit example program sditftbitmap program to use the SDFat classes and the like. Not sure If what I did was the best way to use the library or not, but: ;)
Teensy-Adafruit-2.8-TFT-SDF.jpg

Not sure if anyone would like to see the modified sketch or not, but I have included it just in case:
 

Attachments

  • spitftbitmap-140508a.zip
    3 KB · Views: 542
Not sure how many are trying this stuff out, but did find an issue with my STMPE library updates that I did not do a SPI.begin() in the init code for the Teensy case. Did not find it before as my test programs also use the display library (first) which did the call to the SPI.begin... Fixed it so the example touch program works on teensy 3.1 (after you edit it to use SPI instead of I2C)

If anyone would like to try it out, I decided to fork the official sources and uploaded my changes to my github fork: https://github.com/KurtE/Adafruit_STMPE610

Kurt
 
For the fun of it, I decided to try to add the FAST spi code to my version of the ILI9341 driver, which by itself appears to work pretty well. But the 2.8" TFT shield also has touch support as well and the CS for this is not one of the 9 IO pins that can be a CS with the fast support. So it needs to run with the slower SPI mode. I added a hack to the constructor to force it to use the teensy SPI library code mode, which works well with the Touch.

However I prefer having the fast drawing of the fast SPI mode. So I started hacking some support into my test program which is code I extracted from a simple DIY remote control I was experimenting with awhile ago (using a 4D systems touch...), code is nothing special, but at least it draws some ugly buttons some text and sliders. I did some hacking that after I init the display I save some information away (CORE_PIN(9-13)_CONFIG, SPI0_CTAR0, SPIO_HSPI), I then init the touch screen and again save away those values. Then I restore the displays version and then before calling the touch screen stuff I restore that set... Before switching away from the Display version of these registers, I try to wait until the queue of outputs is 0, I probably may need to check some of the other flags to really verify completed, but from what I can tell, it appears to be working :)

I put an updated copy of my WIP of the Adafruit_ILI9341 up on my fork of it: https://github.com/KurtE/Adafruit_ILI9341 It needs some additional work done. Like I would like to be able to scroll some text. At minimum could try to read a pixel and write it to new location...

The code for my current test stuff is nothing I am proud with, but posted here in case anyone else would like to play along. Would also appreciate any suggestions on clean way to work with multiple devices where some work with the fast SPI support and others do not.

Edit: Note in test program right now most buttons do nothing, except the Up/Dn buttons, go through a couple of different screens. Also clicking in sliders and dragging moves the sliders up and down. Will only keep the change if last touch event is within the logical object.

Kurt
 

Attachments

  • Teensy_Adafruit_Touch_Test-140526b.zip
    17.9 KB · Views: 369
For the fun of it, I am trying to get reading information from the display. With the build I put up on github, that uses the fast SPI code, I disabled the readcommand8 function, which for example is called in the graphicstest, at startup to show some information like:
Code:
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
The SPI library code is able to get this information:
Code:
int8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) {
   digitalWrite(_dc, LOW); // command
   digitalWrite(_cs, LOW);
   spiwrite(0xD9);  // woo sekret command?
   digitalWrite(_dc, HIGH); // data
   spiwrite(0x10 + index);
   digitalWrite(_cs, HIGH);

   digitalWrite(_dc, LOW);
//   digitalWrite(_sclk, LOW);
   digitalWrite(_cs, LOW);
   spiwrite(c);
 
   digitalWrite(_dc, HIGH);
   uint8_t r = spiread();
   digitalWrite(_cs, HIGH);
   return r;
}
So I am trying to get it to work, when I am going in fast mode...
The code in that case I think should be something like:
Code:
int8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) {
   if (hwSPI) {
       writecommand(0xD9); // sekret command
       writedata(0x10 + index);
       writecommand(c);
       return  readdata();
   } 
   digitalWrite(_dc, LOW); // command
   digitalWrite(_cs, LOW);
   spiwrite(0xD9);  // woo sekret command?
   digitalWrite(_dc, HIGH); // data
   spiwrite(0x10 + index);
   digitalWrite(_cs, HIGH);

   digitalWrite(_dc, LOW);
//   digitalWrite(_sclk, LOW);
   digitalWrite(_cs, LOW);
   spiwrite(c);
 
   digitalWrite(_dc, HIGH);
   uint8_t r = spiread();
   digitalWrite(_cs, HIGH);
   return r;
#else
    return 0;
#endif   
}

Note: The above still works when in my constructor I force the code to use the SPI library instead of the fast stuff.

Where the Write command code in the hardware spi mode does:
Code:
void Adafruit_ILI9341::writecommand(uint8_t c)
{
	if (hwSPI) {
		SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0);
		while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
	} else {
...
WriteData is also similar:
Code:
void Adafruit_ILI9341::writedata(uint8_t c)
{
	if (hwSPI) {
		SPI0.PUSHR = c | (pcs_data << 16) | SPI_PUSHR_CTAS(0);
		while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
	} else {
...
Both of the above is used (as well as the writedata16) to display stuff. What new stuff I am adding is the readdata. Which I currently have as:
Code:
uint8_t Adafruit_ILI9341::readdata(void) {
  uint8_t r;
  if (hwSPI) {
       // Try to work directly with SPI registers...
       // First wait until output queue is empty
        uint16_t wTimeout = 0xffff;
        while (((SPI0.SR) & (15 << 12)) && (--wTimeout)) ; // wait until empty
        
//       	SPI0_MCR |= SPI_MCR_CLR_RXF; // discard any received data
//		SPI0_SR = SPI_SR_TCF;
        
        // Transfer a 0 out... 
        writedata(0);   
        
        // Now wait until completed. 
        wTimeout = 0xffff;
        while (((SPI0.SR) & (15 << 12)) && (--wTimeout)) ; // wait until empty
        r = SPI0.POPR;  // get the received byte... should check for it first...
    } else {
...
With the fast mode, the above code (and several variations), does not return the data and corrupts the output to the display. I should note that I also added code in the begin function to now initialize the MISO IO pin to: CORE_PIN12_CONFIG = PORT_PCR_MUX(2);

Some of the stuff I am still figuring out from the hardware manual is how best to do this. Should I at the start of the readdata, clear the received data? Is there a good way to know appropriate time to do so? i.e. do I need to wait until output queue is empty? Any other flags? Should I try instead to simply disable the read fifo? ... Could it also simply be that the display can not respond quickly enough on a query (12mhz)? Could it be that the display does not like that in the fast mode the CS line is toggled for each byte (or in the case of write16 each two bytes?) where the SPIlibrary code appears to do it around the command write and datawrite, likewise command write and the datawrite (read)... All things to experiment with.

Anyone else try this type of stuff?

Thanks
Kurt
 
Again not sure if anyone else is interested in this, but made progress :)

First thing I figured out, is that the display did not like having the CS change between the two bytes. Not sure if the first command was the issue or only on the command where the display actually returned data, but fixed this by passing the SPI_PUSHR_CONT flag on the SPI0.pushr assignments.
Also in order to get the data correctly I not only had to wait until the output queue was empty, but also until it said the operation completed. So I now have it returning the register data now, and the display works properly after the calls to retrieve the data. Currently that part of the code looks like:
Code:
uint8_t Adafruit_ILI9341::readcommand8(uint8_t c, uint8_t index) {
  if (hwSPI) {
    uint16_t wTimeout = 0xffff;
    uint8_t r;
    while (((SPI0.SR) & (15 << 12)) && (--wTimeout)) ; // wait until empty
    
    // Make sure the last frame has been sent...
    SPI0.SR = SPI_SR_TCF;   // dlear it out;
    wTimeout = 0xffff;
    while (!((SPI0.SR) & SPI_SR_TCF) && (--wTimeout)) ; // wait until it says the last frame completed

    // clear out any current received bytes
    wTimeout = 0x10;    // should not go more than 4...
    while ((((SPI0.SR) >> 4) & 0xf) && (--wTimeout))  {
        r = SPI0.POPR;
    }
    
    //writecommand(0xD9); // sekret command
	SPI0.PUSHR = 0xD9 | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
	while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full

    // writedata(0x10 + index);
	SPI0.PUSHR = (0x10 + index) | (pcs_data << 16) | SPI_PUSHR_CTAS(0);
	while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full

    // writecommand(c);
   	SPI0.PUSHR = c | (pcs_command << 16) | SPI_PUSHR_CTAS(0) | SPI_PUSHR_CONT;
	while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full

    // readdata
	SPI0.PUSHR = 0 | (pcs_data << 16) | SPI_PUSHR_CTAS(0);
	while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
        
    // Now wait until completed. 
    wTimeout = 0xffff;
    while (((SPI0.SR) & (15 << 12)) && (--wTimeout)) ; // wait until empty

    // Make sure the last frame has been sent...
    SPI0.SR = SPI_SR_TCF;   // dlear it out;
    wTimeout = 0xffff;
    while (!((SPI0.SR) & SPI_SR_TCF) && (--wTimeout)) ; // wait until it says the last frame completed

    wTimeout = 0x10;    // should not go more than 4...
    // lets get all of the values on the FIFO
    while ((((SPI0.SR) >> 4) & 0xf) && (--wTimeout))  {
        r = SPI0.POPR;
    }
    return r;  // get the received byte... should check for it first...

  } 
... (other case)
Note: will probably remove some of the checks for queue full as I previously emptied the queue...

Kurt
 
Question for myself and others: What is the difference between the ILI9340 (used in 2.2" display) and the ILI9341 (used in 2.8" display)? I did a slight edit between the two original drivers up on Adafruit (renamed ILI9341 and ILI9340 to ILI934X in both set of files) and then used winmerge to look at the differences and other than changes associated with support for Arduino Due and Teensy, did not notice any functional differences. So tried graphics test from ILI9341 on 2.2" display and it works...

Also I also purchased one of the 2.8" TFT breakout boards from Adafruit, which I am also playing with. Will be interesting to compare the differences in touch code between the Shield using STMPE chip versus using 4 IO pins on Teensy to directly do the touch processing.

Kurt
 
thanks for posting this! helped me get the 2.8" working since i had the same problems, along with sumoboy's faster spi display library i should be able to use this display almost as well as a gLCD that referesh's much faster then the stock ILI9340 library
 
As you mentioned, you can use sumoboy's driver as well. Likewise I believe you can use the ILI9341 driver on your ILI9340 display as well. At least with the Adafruit displays. When searching the web, it looks like the ILI9341 is a replacement for the discontinued ILI9340 chip (at least that is what it sounds like with different reports I found including: https://www.displaytech-us.com/news/ili9340-based-tft-modules-be-discontinued-0 .

With the Adafruit drivers, for example other than not having the first pass of Teensy compatibility stuff merged in to the 940 driver and likewise not having some of the Arduino Due stuff in it, the init code appears to be identical functionally. From winmerge:
Code:
 //if(cmdList) commandList(cmdList); 		 //if(cmdList) commandList(cmdList);
	   		  
	 writecommand(0xEF); 		 writecommand(0xEF);
	 writedata(0x03); 		 writedata(0x03);
	 writedata(0x80); 		 writedata(0x80);
	 writedata(0x02); 		 writedata(0x02);
	  		 
	 writecommand(0xCF);    		 writecommand(0xCF);   
	 writedata(0x00);   		 writedata(0x00);  
	 writedata(0XC1);   		 writedata(0XC1);  
	 writedata(0X30);   		 writedata(0X30);  
	  		 
	 writecommand(0xED);    		 writecommand(0xED);   
	 writedata(0x64);   		 writedata(0x64);  
	 writedata(0x03);   		 writedata(0x03);  
	 writedata(0X12);   		 writedata(0X12);  
	 writedata(0X81);   		 writedata(0X81);  
	  		 
	 writecommand(0xE8);    		 writecommand(0xE8);   
	 writedata(0x85);   		 writedata(0x85);  
	 writedata(0x00);   		 writedata(0x00);  
	 writedata(0x78);   		 writedata(0x78);  
	  		 
	 writecommand(0xCB);    		 writecommand(0xCB);   
	 writedata(0x39);   		 writedata(0x39);  
	 writedata(0x2C);   		 writedata(0x2C);  
	 writedata(0x00);   		 writedata(0x00);  
	 writedata(0x34);   		 writedata(0x34);  
	 writedata(0x02);   		 writedata(0x02);  
	  		 
	 writecommand(0xF7);    		 writecommand(0xF7);   
	 writedata(0x20);   		 writedata(0x20);  
	  		 
	 writecommand(0xEA);    		 writecommand(0xEA);   
	 writedata(0x00);   		 writedata(0x00);  
	 writedata(0x00);   		 writedata(0x00);  
	  		 
	 writecommand(ILI934X_PWCTR1);    //Power control 		 writecommand(ILI934X_PWCTR1);    //Power control
	 writedata(0x23);   //VRH[5:0] 		 writedata(0x23);   //VRH[5:0]
	  		 
	 writecommand(ILI934X_PWCTR2);    //Power control 		 writecommand(ILI934X_PWCTR2);    //Power control
	 writedata(0x10);   //SAP[2:0];BT[3:0] 		 writedata(0x10);   //SAP[2:0];BT[3:0]
	  		 
	 writecommand(ILI934X_VMCTR1);    //VCM control 		 writecommand(ILI934X_VMCTR1);    //VCM control
	 writedata(0x3e); //�Աȶȵ���  		 writedata(0x3e); //¶Ô±È¶Èµ÷½Ú 
	 writedata(0x28);   		 writedata(0x28);  
	   		  
	 writecommand(ILI934X_VMCTR2);    //VCM control2 		 writecommand(ILI934X_VMCTR2);    //VCM control2
	 writedata(0x86);  //-- 		 writedata(0x86);  //--
	  		 
	 writecommand(ILI934X_MADCTL);    // Memory Access Control 		 writecommand(ILI934X_MADCTL);    // Memory Access Control
	 writedata(ILI934X_MADCTL_MX | ILI934X_MADCTL_BGR);  		 writedata(0x48); 
	  		 
	 writecommand(ILI934X_PIXFMT);      		 writecommand(ILI934X_PIXFMT);     
	 writedata(0x55);   		 writedata(0x55);  
	   		  
	 writecommand(ILI934X_FRMCTR1);      		 writecommand(ILI934X_FRMCTR1);     
	 writedata(0x00);    		 writedata(0x00);   
	 writedata(0x18);   		 writedata(0x18);  
	  		 
	 writecommand(ILI934X_DFUNCTR);    // Display Function Control 		 writecommand(ILI934X_DFUNCTR);    // Display Function Control
	 writedata(0x08);   		 writedata(0x08);  
	 writedata(0x82); 		 writedata(0x82);
	 writedata(0x27);    		 writedata(0x27);   
	  		 
	 writecommand(0xF2);    // 3Gamma Function Disable 		 writecommand(0xF2);    // 3Gamma Function Disable
	 writedata(0x00);   		 writedata(0x00);  
	  		 
	 writecommand(ILI934X_GAMMASET);    //Gamma curve selected 		 writecommand(ILI934X_GAMMASET);    //Gamma curve selected
	 writedata(0x01);   		 writedata(0x01);  
	  		 
	 writecommand(ILI934X_GMCTRP1);    //Set Gamma 		 writecommand(ILI934X_GMCTRP1);    //Set Gamma
	 writedata(0x0F);   		 writedata(0x0F);  
	 writedata(0x31);   		 writedata(0x31);  
	 writedata(0x2B);   		 writedata(0x2B);  
	 writedata(0x0C);   		 writedata(0x0C);  
	 writedata(0x0E);   		 writedata(0x0E);  
	 writedata(0x08);   		 writedata(0x08);  
	 writedata(0x4E);   		 writedata(0x4E);  
	 writedata(0xF1);   		 writedata(0xF1);  
	 writedata(0x37);   		 writedata(0x37);  
	 writedata(0x07);   		 writedata(0x07);  
	 writedata(0x10);   		 writedata(0x10);  
	 writedata(0x03);   		 writedata(0x03);  
	 writedata(0x0E);   		 writedata(0x0E);  
	 writedata(0x09);   		 writedata(0x09);  
	 writedata(0x00);   		 writedata(0x00);  
	   		  
	 writecommand(ILI934X_GMCTRN1);    //Set Gamma 		 writecommand(ILI934X_GMCTRN1);    //Set Gamma
	 writedata(0x00);   		 writedata(0x00);  
	 writedata(0x0E);   		 writedata(0x0E);  
	 writedata(0x14);   		 writedata(0x14);  
	 writedata(0x03);   		 writedata(0x03);  
	 writedata(0x11);   		 writedata(0x11);  
	 writedata(0x07);   		 writedata(0x07);  
	 writedata(0x31);   		 writedata(0x31);  
	 writedata(0xC1);   		 writedata(0xC1);  
	 writedata(0x48);   		 writedata(0x48);  
	 writedata(0x08);   		 writedata(0x08);  
	 writedata(0x0F);   		 writedata(0x0F);  
	 writedata(0x0C);   		 writedata(0x0C);  
	 writedata(0x31);   		 writedata(0x31);  
	 writedata(0x36);   		 writedata(0x36);  
	 writedata(0x0F);   		 writedata(0x0F);  
	  		 
	 writecommand(ILI934X_SLPOUT);    //Exit Sleep 		 writecommand(ILI934X_SLPOUT);    //Exit Sleep
	 delay(120);           		 delay(120);          
	 writecommand(ILI934X_DISPON);    //Display on 		 writecommand(ILI934X_DISPON);    //Display on
	  		 
	} 		}
I know the above is probably hard to read from this report, 940 is on left, 941 on right. The only thing I see in the winmerge is a garbled comment is different and there is a case in one where a constant is used, where the other side use the #define values. Note: I edited both set of files to rename stuff from ILI9340_ or ILI9341_ to ILI934X_ as to make comparison easier...

Kurt
 
Well after playing with the sd library for awhile and not having much luck here, I finally figured out that the sd library is not the same as sdfat library. That was after reading the later posts in the thread: http://forum.pjrc.com/threads/25582...interrupts-and-main-program?p=47270#post47270

So I downloaded latest released sdfat library code, made the edits, that Paul suggested. I then modified the Adafruit example program sditftbitmap program to use the SDFat classes and the like. Not sure If what I did was the best way to use the library or not, but: ;)
View attachment 1956

Not sure if anyone would like to see the modified sketch or not, but I have included it just in case:

i wasn't able to get this to build, how did you get it to compile with just SDFat.h ? i usualy use SD.begin(cs, speed) instead of init when i just import SDFat.h and SDFatUtil.h

Code:
spitftbitmap_kurte:5: error: 'SdFile' was not declared in this scope
spitftbitmap_kurte:5: error: 'f' was not declared in this scope
spitftbitmap_kurte:6: error: 'SdFile' was not declared in this scope
spitftbitmap_kurte:6: error: 'f' was not declared in this scope
spitftbitmap_kurte:1: error: 'u' does not name a type
spitftbitmap_kurte.ino: In function 'void bmpDraw(char*, uint8_t, uint16_t)':
spitftbitmap_kurte:117: error: 'read16' cannot be used as a function
spitftbitmap_kurte:118: error: 'read32' cannot be used as a function
spitftbitmap_kurte:119: error: 'read32' cannot be used as a function
spitftbitmap_kurte:120: error: 'read32' cannot be used as a function
spitftbitmap_kurte:123: error: 'read32' cannot be used as a function
spitftbitmap_kurte:124: error: 'read32' cannot be used as a function
spitftbitmap_kurte:125: error: 'read32' cannot be used as a function
spitftbitmap_kurte:126: error: 'read16' cannot be used as a function
spitftbitmap_kurte:127: error: 'read16' cannot be used as a function
spitftbitmap_kurte:129: error: 'read32' cannot be used as a function
spitftbitmap_kurte.ino: In function 'uint16_t read16(SdFile&)':
spitftbitmap_kurte:203: error: 'uint16_t read16(SdFile&)' redeclared as different kind of symbol
spitftbitmap_kurte:5: error: previous declaration of 'uint16_t read16'
spitftbitmap_kurte.ino: In function 'uint32_t read32(SdFile&)':
spitftbitmap_kurte:210: error: 'uint32_t read32(SdFile&)' redeclared as different kind of symbol
spitftbitmap_kurte:6: error: previous declaration of 'uint32_t read32'
 
I am not sure, but I think I had compile errors like this before, and there was a conflict between an SDFAT library that was installed in my Arduino install in the libraries folder versus the updated SDFAT library which I downloaded and installed in the libraries folder of my sketchbook/libraries folder. So you may want to check for that.

Also I was later able to get the SD library to work, by updating one line in the SD library as I believe that there is a bug with the how it chooses the SPI speed...

Kurt
 
yes, with half speed it works now, i'm also working on using the touch screen, but i've discovered a bug...

when drawPixel is called it generates garbage touch events

Code:
loop() {

  drawPixel(anyX, anyY, anyColour);

  if (!ts.bufferEmpty()) {   
    // Retrieve a point  
    TS_Point p = ts.getPoint(); 

    Serial.print(F("original touch at "));
    Serial.print(p.x);
    Serial.print(F(", "));
    Serial.print(p.y);

    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
    int y = tft.height() - p.x;
    int x = p.y;

    Serial.print(F(" -> mapped to "));
    Serial.print(x);
    Serial.print(F(", "));
    Serial.println(y);
 }

}

outputs this as soon as the program starts

Code:
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
...


and when the screen is actually touched, it seems to echo it back over and over generating more garbage that's much harder to filter out.
Code:
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 5, 2854 -> mapped to 237, 247
original touch at 4, 91 -> mapped to -5, 247
original touch at 1, 320 -> mapped to 14, 248
original touch at 2, 1553 -> mapped to 123, 247
original touch at 1458, 1553 -> mapped to 123, 158 //the actual touch on the screen
original touch at 1458, 1553 -> mapped to 123, 158
original touch at 5, 2854 -> mapped to 237, 247
origiginal touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 0, 0 -> mapped to -13, 248
original touch at 1, 1558 -> mapped to 123, 248
original touch at 5, 2838 -> mapped to 235, 247
original touch at 3, 347 -> mapped to 17, 247
original touch at 1, 1585 -> mapped to 125, 248
original touch at 1, 1558 -> mapped to 123, 248
original touch at 5, 2838 -> mapped to 235, 247
original touch at 1457, 1558 -> mapped to 123, 158
original touch at 5, 2838 -> mapped to 235, 247
original touch at 3, 347 -> mapped to 17, 247
original touch at 1, 1585 -> mapped to 125, 248
original touch at 1, 1558 -> mapped to 123, 248
original touch at 5, 2838 -> mapped to 235, 247
.... continues outputing gibberish touch's forever and doesn't go back to 0,0 touch's

i'm going to try using ILI9340 and see if the problem is also there, since there's some differences in the drawPixel unless they end up being the same once compiled for the Teensy

full code here:
Code:
//This example implements a simple sliding On/Off button. The example
// demonstrates drawing and touch operations.
//
//Thanks to Adafruit forums member Asteroid for the original sketch!
//
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <Time.h>

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

boolean RecordOn = false;

#define FRAME_X 210
#define FRAME_Y 180
#define FRAME_W 100
#define FRAME_H 50

#define REDBUTTON_X FRAME_X
#define REDBUTTON_Y FRAME_Y
#define REDBUTTON_W (FRAME_W/2)
#define REDBUTTON_H FRAME_H

#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W)
#define GREENBUTTON_Y FRAME_Y
#define GREENBUTTON_W (FRAME_W/2)
#define GREENBUTTON_H FRAME_H

const uint8_t sdCS = 2;
SdFat sd;

uint8_t checkBit = 0;

void drawFrame()
{
  tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, ILI9341_BLACK);
}

void redBtn()
{ 
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_RED);
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_BLUE);
  drawFrame();
  tft.setCursor(GREENBUTTON_X + 6 , GREENBUTTON_Y + (GREENBUTTON_H/2));
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.println("ON");
  RecordOn = false;
}

void greenBtn()
{
  tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, ILI9341_GREEN);
  tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_BLUE);
  drawFrame();
  tft.setCursor(REDBUTTON_X + 6 , REDBUTTON_Y + (REDBUTTON_H/2));
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(2);
  tft.println("OFF");
  RecordOn = true;
}

time_t getTeensy3Time() { return Teensy3Clock.get(); }

// User provided date time callback function
void dateTime(uint16_t* date, uint16_t* time) {
  time_t now();
  *date = FAT_DATE(year(), month(), day());
  *time = FAT_TIME(hour(), minute(), second());
}

void setup(void)
{
  Serial.begin(9600);
  while (!Serial) {}

  tft.begin();

  //setup teensy clock
  setSyncProvider(getTeensy3Time);

  while (!ts.begin()) { 
    Serial.println("Unable to start touchscreen.");
    delay(500);
  }
  Serial.println("Touchscreen started.");

  SdFile::dateTimeCallback(dateTime);
  while (!sd.begin(sdCS, SPI_HALF_SPEED)) {
    tft.println(F("Insert microSD card"));
    Serial.println(F("Insert microSD card"));
    delay(500);

  }

  tft.fillScreen(ILI9341_BLUE);
  // origin = left,top landscape (USB left upper)
  tft.setRotation(1); 
  redBtn();
}

void loop()
{
  // See if there's any  touch data for us
  if (!ts.bufferEmpty())
  {   
    // Retrieve a point  
    TS_Point p = ts.getPoint(); 
    // Scale using the calibration #'s
    // and rotate coordinate system
    Serial.print(F("original touch at "));
    Serial.print(p.x);
    Serial.print(F(", "));
    Serial.print(p.y);

    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
    int y = tft.height() - p.x;
    int x = p.y;

    Serial.print(F(" -> mapped to "));
    Serial.print(x);
    Serial.print(F(", "));
    Serial.println(y);

    if (RecordOn)
    {
      if((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) {
        if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) {
          Serial.println("Red btn hit"); 
          redBtn();
        }
      }
    }
    else //Record is off (RecordOn == false)
    {
      if((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) {
        if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) {
          Serial.println("Green btn hit"); 
          greenBtn();
        }
      }
    }

    //Serial.println(RecordOn);
  }  

  if (checkBit<100) {
    // tft.fillRect(158, 220, 30, 8, ILI9341_CYAN);
    tft.drawPixel(158, 220, ILI9341_CYAN);
    checkBit++;
  }
  else if (checkBit<199) {
    // tft.fillRect(158, 220, 30, 8, ILI9341_YELLOW);
    tft.drawPixel(158, 220, ILI9341_YELLOW);
    checkBit++;
  }
  else {
    // tft.fillRect(158, 220, 30, 8, ILI9341_YELLOW);
    tft.drawPixel(158, 220, ILI9341_YELLOW);
    checkBit = 0;
  }

  // if (checkBit<100) {
  //   tft.setTextColor(ILI9341_CYAN);
  //   checkBit++;
  // }
  // else if (checkBit<199) {
  //   tft.setTextColor(ILI9341_YELLOW);
  //   checkBit++;
  // }
  // else {
  //   tft.setTextColor(ILI9341_YELLOW);
  //   checkBit = 0;
  // }
  // tft.setCursor(15, 22);
  // tft.print("break");
}
 
Last edited:
no problem with ILI9340, i think it's something with the writedata16, not really sure what i'm look at here though

Code:
// ILI9340
void Adafruit_ILI9340::writedata(uint8_t c) {
  SET_BIT(dcport,  dcpinmask);
  //digitalWrite(_dc, HIGH);
  CLEAR_BIT(clkport, clkpinmask);
  //digitalWrite(_sclk, LOW);
  CLEAR_BIT(csport, cspinmask);
  //digitalWrite(_cs, LOW);
  
  spiwrite(c);

  //digitalWrite(_cs, HIGH);
  SET_BIT(csport, cspinmask);
}

Code:
// ILI9341 teensy version.... i think
void Adafruit_ILI9341::writedata16(uint16_t d)
{
	if (hwSPI) {
		SPI0.PUSHR = d | (pcs_data << 16) | SPI_PUSHR_CTAS(1);
		while (((SPI0.SR) & (15 << 12)) > (3 << 12)) ; // wait if FIFO full
	} else {
        //Serial.print("SPI data: ");
        //Serial.print(d, HEX);
		*rspin = 1;
        *clkpin = 0;
		*cspin = 0;
		spiwrite(d >> 8);
		spiwrite(d);
		*cspin = 1;
        //Serial.println(" completed");
	}
}
 
The problem is when we use the FAST SPI mode, and mix it with things that use the SPI library, they clobber each other.

I have some calls and the like in some test cases that work around it, a few others have done the same (like thread: http://forum.pjrc.com/threads/26013...erals?p=50475&highlight=spi+restore#post50475 ), and Paul is hopefully going to have a standardized way to do it in the next release.

There are a couple of optional arguments on my creator, which the last one can force it to use SPI library. Like:
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, 0, true);

This will be slower, but they both use SPI and work better (unchanged) with each other.

Kurt
 
Yes, there is an official solution. It's been fully integrated into the software. This thread is old info.

Since the older message on this thread, Adafruit merged my SPI transaction patches to both the ILI9341 and STMPE610.

I have personally tested this display with Teensy 3.1. It works fine. ILI9341 & STMPE610 conflicts, at least on Teensy 3.1 and other boards that support SPI transactions, are a thing of the past.

Arduino 1.0.7 still hasn't been released.... but when it comes out, all the Arduino brand boards will support SPI transactions too.
 
hi all.
I have same display and find out it has chip st7781.
which library (example) will work with this display?
thx
 
From what I can tell, you are using a simple carrier board for the T3.1, which I believe is running all of the wires needed to control the Adafruit 2.8" display in particular:
Pins 9-13. Plus the 5v pin and ground. What I can not tell is if you also have connections for the touch screen cs (8) or the Sdcard (4?).

Sorry don't have time right now to go through your firmware. If it were me the things I would do include:
a) verify I have connectivity between the T3.1 IO pins and the corresponding IO pins on the shield (hand held meter)
b) I would use a Logic Analyzer to see what signals you are actually getting. (but that is cheating)
c) Try some standard libraries and test programs. Use either the real default library: Adafruit_ILI9341 library or the faster ILI9341_t3 library, with the graphic test program that are examples of those libraries. Do they work?

d) pull out something like an Arduino UNO to see if it works (this eliminates that the display is defective).

good Luck
 
Status
Not open for further replies.
Back
Top