ILI 9341 Parallel Library

Status
Not open for further replies.

awesome101

Well-known member
So I found a library for the STM32 on GitHub that interfaces with the ILI9341 display using the 8080 interface (https://github.com/iwalpola/Adafruit_ILI9341_8bit_STM). I ported this over to the Teensy 3.2 by using Port C bits 0 - 7 for the data bits (LCD_D0 - LCD_D7). This means I used pins 15, 22, 23, 9, 10, 13, 11, 12 for the LCD bits 0, 1, 2, 3, 4, 5, 6, and 7 accordingly; LCD_RD is 21, LCD_WR is 20, LCD_RS is 19, LCD_CS is 18, and LCD_RST is 17. For some reason when I run the example sketch, the display just starts flashing randomly. The Serial Monitor tells the following information:
Display Power Mode: 0x2
MADCTL Mode: 0x3
Pixel Format: 0x2
Image Format: 0x3
Device ID: 0x3030303

Here is my GitHub with the easy-to-understand code for the library and the sketch:
https://github.com/LudumDareDevelopment/Teensy-ILI9341-8-bit-Parallel-Library/tree/master

I think I'm really close to getting this to work. If anyone has any suggestions/fixes, feel free to share them.
 
First let me say I know little about the teensy and nothing about the LCD, but I did work in the computer industry for 20 years where reading data sheets was an important part of the job.

Code:
#define RD_ACTIVE    digitalWriteFast(TFT_RD, HIGH);

#define RD_IDLE      digitalWriteFast(TFT_RD, LOW);

#define WR_ACTIVE    digitalWriteFast(TFT_WR, HIGH);

#define WR_IDLE      digitalWriteFast(TFT_WR, LOW);

#define CD_COMMAND   digitalWriteFast(TFT_RS, HIGH);

#define CD_DATA      digitalWriteFast(TFT_RS, LOW);

#define CS_ACTIVE    digitalWriteFast(TFT_CS, HIGH);

#define CS_IDLE      digitalWriteFast(TFT_CS, LOW);

These all look inverted from what they should be. They should all idle High. A strobe brings the line low and returns it to high.
Check page 28 of the data sheet. ( Edit: your cmmand and data are probably correct. I didn't look at those )

Code:
GPIOC_PSOR = 0;
  GPIOC_PCOR = 0;
  for (uint8_t b = 0; b < 8; b++) {
	  if (bitRead(c, b)) {
		  GPIOC_PSOR |= (1 << b);
	  } else {
		  GPIOC_PCOR |= (1 << b);
	  }
  }

The whole idea of a parallel interface is to not do things like the above.
GPIOC_PDOR = c; if no other bits in the C register? Or you could xor your data c with PDOR, mask out any bits you don't want to change and write the toggle register.
GPIOC_PTOR = (GPIOC_PDOR ^ c ) & 0xff;
 
Last edited:
Awesome!! Welcome to pjrc.

David Prentiss at Arduino has done a ton of work with the MCUfriend 8bit parallel tfts. I opted out of these due to the support and the amount of wiring needed to get it work which is almost double what you need for spi. Plus there are a ton of working spi libraries and gadgets. I would check out the tft's found here at the pjrc store. They are listed at a fair price and there is a ton of support to back them up.

If you just have to use MCUfriend how ever I will help you set it up like the regular GameRiot libraries for gaming. Its some thing I should do any way if I want every thing to be compatible as promised. Plus I have a couple that aren't being used and a teensy3.2 and esp32.

First I would try to download the mcu friend library which is teensy compatible and run a couple demos. Get to know how it works. I spent way to much time on that part!!!! Email me if you need me.....

I got you man!!! Give me a day, two at most. This is the fun part!!
 
Last edited:
Thanks duhjoker. The problem is I think I can get the library working without having to buy another LCD. If it takes too long to get this to work, I'll buy the SPI version. Today I'm going to fix my inverse defines and try to get my TFT ID correctly
 
If it were me, I would probably start of simple and see if that works...
That is instead of touching the registers directly, just use something like digitalWriteFast, could be something as simplistic as:
Code:
digitalWriteFast(TFT_B0, bitRead(c, 0) ? HIGH, LOW);   // may have to change which is high and which is low.
digitalWriteFast(TFT_B1, bitRead(c, 1) ? HIGH, LOW); 
...
digitalWriteFast(TFT_B7, bitRead(c, 7) ? HIGH, LOW);

I think there is probably issues with current stuff that looks like:
Code:
GPIOC_PSOR = 0;
  GPIOC_PCOR = 0;
  for (uint8_t b = 0; b < 8; b++) {
	  if (bitRead(c, b)) {
		  GPIOC_PSOR |= (1 << b);
	  } else {
		  GPIOC_PCOR |= (1 << b);
	  }
  }
That is you are actually reading and writing to the different port registers for each bit. That is PCOR is setup to clear those bits that are set (1) in the write. The read will always return 0, likewise for PSOR.

So at a minimum dont use |=, just use =... Also writing the 0 to them does nothing...

Or maybe you could do some simple bit hacks... something like:
Code:
GPIOC_PSOR = c;   
GPIOC_PCOR = (!c & 0xff);
Again depending on High vs low... may need to swap PSOR and PCOR in above.


If you wish to touch all of the pins at one, there is the PDOR register, but that will touch all 32 bits. You can always read, mask or in... But you can run into issues if there are other pins used on that port and interrupts happen...
 
I'm not using the hardware registers anymore. I replaced all of them with pinMode and digitalWrite for testing purposes.
 
Ok I found an error. In my write8() function I say digitalWrite(D0 + b, HIGH) but that won't work because D0-D7 don't increase by one.
 
I'm starting to think this is a hardware problem. The MCUFriend LCD is for the Arduino and therefore requires 5V for pin voltage. Would it still work with Teensy 3.2?
 
So I'm using David's library and running the register id program which gives me 0 as the id. I think something is wrong with the lcd.
 
Yess!!! I finally got the LCD to work! I studied the datasheet on page 31 and realized after the TFT_WR strobe I had to negate all the data bit pins. Now all I have to do is optimize the library by using hardware registers (if someone could help me with that that would be great).
 
Took a quick look... Actually downloaded and edited such that all lines are not 3 line between each line.

As far as speed goes. My earlier stuff might work...
GPIOC_PSOR = c;
GPIOC_PCOR = (!c & 0xff);

vs the 8 digitalWriteFast calls...

Also wonder why in places like write8special, why after you do the strobe, you set all of the data lines to LOW... Probably could remove those calls and speed some stuff up....
But if all o fthem are on Port C bits... could do this probably by GPIOC_PCOR = 0xff; // should clear all 8 lower bits (IO pins)
 
According to the data sheet on page 31, I have to set the bits to zero because otherwise it won't work. As for speed. the problem is I can't find any documentation for these hardware registers. In addition I've heard that digitalWriteFast is just as fast as hardware registers? Would changing the digitalWrites to hardware boost my performance by a lot?
 
digitalWriteFast with constants will convert each of these accesses to a simple

Your digitalWriteFast(D0, bitRead(c, 0) ? HIGH: LOW);
Where D0 is defined as 15

Will resolve to something like:
Code:
if (c&1) 
    CORE_PIN15_PORTSET = CORE_PIN15_BITMASK;
else
    CORE_PIN15_PORTCLEAR = CORE_PIN15_BITMASK;

Which since pin15 is C0...
This translates into
Code:
if (c&1) 
    GPIOC_PSOR = 1<<0;
else
    GPIOC_PCOR = 1<<0;

So yes it does update one bit the same way as mentioned.
And assuming D0..D7 maps to C0..C7
Then the
Code:
GPIOC_PSOR = c;
GPIOC_PCOR = (!c & 0xff);
Should work...

I would be surprised if you had to set all B0-B7, my guess is that you might need to do this maybe at the end of when you unassert CS, but... Could be wrong.
Also for speed, I would probably inline some of the functions like WR_STROBE.

Edit forgot to mention, you can download the datasheets for all the teensy boards up at: https://pjrc.com/teensy/datasheets.html
 
Ok KurtE. I added your code into the library and now for some reason it's not working even though it should be. Any ideas?
 
I assume you left in the code for pinMode? And again I did not walk through all of your IO pins

Also I may have mistyped... Meant to put: GPIOC_PCOR = (~c & 0xff);
 
Ok I changed GPIOC_PCOR = (~c & 0xff); but still doesn't work. As for PinMode I use that for the LCD control pins which are on a different GPIO port. I doubt this would cause it to not work?
 
Status
Not open for further replies.
Back
Top