2.8" TFT LCD Screen changing pin to free AttachInterrupt pin (UNO)

Hello,

I am completely new to this forum.
I have been playing around with Arduino for a few months now and so far haven't had any difficulties.
A week ago, I acquired a LCD TFT Touchscreen. (I am using the supplied Adafruit_GFX, Adafruit_TFTLCD, TouchScreen, and MCUFRIEND_kbv libraries from Kuman)
Now, I am currently trying to implement this in a photoelectric guard project of mine.
Sadly, the LCD Shield uses both pins (2 & 3), which can be used for the Arduino AttachInterrupt function on the Arduino Uno.

As I see it, there are two options for me:

  1. I could use an Arduino MEGA. This would be significantly slower than the UNO version though. Additionally, the MEGA uses more space, which would not be necessary for this project.

  2. Try to change the pin layout on the Arduino. Since I am designing an expansion-Shield for the Photoelectric guard anyway, I could easily remap the pins (for example mapping LCD_D2 from the LCD Shield to Arduino pin 10 instead of pin 2). According to this Adafruit tutorial, this is possible in the pin_magic.h file of the Adafruit_TFTLCD library. I did not find any comments as to how exactly this would work though (as one might see I am not the most advanced programmer). As also stated in the tutorial, the adjusting of pins would evidently slow down the Arduino too.

The questions I have are:

  1. How much slower would a Arduino UNO version with the one remapped pin be?
  2. How does one have to adjust the pin_magic.h file for the Arduino to use pin 10 (instead of the default pin 2) for the LCD_D2 pin?

Thank you in advance.

The MCUFRIEND_kbv version appears to be v2.9.1 which is pretty old. (Library Manager has v2.9.5)

MCUFRIEND_kbv is different to Adafruit_TFTLCD.

Yes it is possible to hack your shield to move LCD_D2 to a different pin. I do not advise it.
Others have asked the same question. And I have provided suitable SPECIALs for MCUFRIEND_kbv.

David.

Hello David,

Thanks a lot for the quick reply!

I know that MCUFRIEND_kbv is something different from the Adafruit_TFTLCD library. I just thought that the one uses the other.

How come you don't recommend to remap the pins? Is it much slower or does it make the workflow unstable?
Would you recommend using the Arduino MEGA version instead? (Or buying a touchscreen specifically optimized for the MEGA)

I tried updating MCUFRIEND_kbv to the newest version, though this results in only black and white stripes on the display. I concluded that Kuman must have edited your library somehow... (I can investigate further tomorrow)

Thanks again,
Nils

It looks as if Kuman uses a UC8230 controller. And MCUFRIEND_kbv v2.9.1 certainly did not support UC8230.

The current v2.9.5 Release does support UC8230
You must delete the existing MCUFRIEND_kbv directory from libraries

Then install current library from the Library Manager.
There are some notes in extras/mcufriend_howto.txt

Add the following block to utility/mcufriend_special.h
define USE_SPECIAL in utility/mcufriend_shield.h, define USE_D2_ON_D10

//################################ LCD_D2 on D10 ######################################
#define USE_D2_ON_D10
#elif defined(__AVR_ATmega328P__) && defined(USE_D2_ON_D10)
#warning USE_D2_ON_D10
#define RD_PORT PORTC
#define RD_PIN  0
#define WR_PORT PORTC
#define WR_PIN  1
#define CD_PORT PORTC
#define CD_PIN  2
#define CS_PORT PORTC
#define CS_PIN  3
#define RESET_PORT PORTC
#define RESET_PIN  4

#define BMASK         0x07              //more intuitive style for mixed Ports
#define DMASK         0xF8              //does exactly the same as previous
#define write_8(x)    { PORTB = (PORTB & ~BMASK) | ((x) & BMASK); PORTD = (PORTD & ~DMASK) | ((x) & DMASK); }
#define read_8()      ( ((PINB & BMASK) | (PIND & DMASK) )
#define setWriteDir() { DDRB |=  BMASK; DDRD |=  DMASK; }
#define setReadDir()  { DDRB &= ~BMASK; DDRD &= ~DMASK; }
#define write8(x)     { write_8(x); WR_STROBE; }
#define write16(x)    { uint8_t h = (x)>>8, l = x; write8(h); write8(l); }
#define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
#define READ_16(dst)  { uint8_t hi; READ_8(hi); READ_8(dst); dst |= (hi << 8); }

#define PIN_LOW(p, b)        (p) &= ~(1<<(b))
#define PIN_HIGH(p, b)       (p) |= (1<<(b))
#define PIN_OUTPUT(p, b)     *(&p-1) |= (1<<(b))

I do not advise hacking shields. Surely it is easier to use a Pin_Change interrupt on A5.

David.

Thanks you for your reply, David.

Your newer versions of MCUFRIEND_kbv don't seem to work for my TFT Screen. (Yes, I did completely delete my library and reinstall using the Library Manager)

I did not know about the Pin_Change interrupt. This definitely looks like a better idea. I will try that later!

Just adding "#define USE_SPECIAL" to utility/mcufriend_shield.h and the code you posted to utility/mcufriend_special.h results in several errors. As far as I can judge, these are caused by redifinitions (i.e. of read_8). Do I have to uncomment something in the other files?

Since I would like to update MCUFRIEND_kbv, I will try to work on that first. I found the thread where you added initial support for UC8230 and will post my problem there first, adressing the issues of this thread afterwards.

Nils.

I haven't gotten the SPECIAL working yet.

part #17 of the mcufriend_how_to.txt states:

  1. If you do not have a standard Uno Shield, you can add a SPECIAL to the mcufriend_special.h
    Edit mcufriend_shield.h: #define USE_SPECIAL
    Edit mcufriend_special.h: e.g. #define USE_MEGA_16BIT_SHIELD
    If your "special" is write-only, the library can not read the ID. It always returns 0xD3D3

I have:

  1. uncommented the #define USE_SPECIAL in utilities/mcufriend_shield.h.
  2. added #define USE_D2_ON_D10 at the beginning of utilities/mcufriend_special.h.
  3. changed the "#if 0" to an "#if 1"
  4. added your code to the end of the "#if 1" part of the mcufriend_special.h (right before the last #else - see attached file)

Somehow I have a feeling that I am making some terribly simple mistake with the # structure of c++.

Nils.

P.S. How come you don't advise hacking the hardware shield?

mcufriend_special.h (42.6 KB)

You have added the #define USE_D2_ON_D10 to the right place.
I would comment out the #define USE_MY_BLUEPILL because I should not have left it in the Release.

You should not alter the #if 0 .. #elif  .. #elif ... sequence.
You have added your new case block to the right place.

Take a piece of paper and write down a simple #if 0 .. #elif  .. #elif .. #endif sequence
Trace it by hand.
The Preprocessor will select the first #if that succeeds.

It is a very neat way to add conditional code. Using #if 0 .. #elif  .. #elif .. #endif instead of #if .. #elif .. #endif means that every block looks the same. The #if 0 simply acts as a dummy. It can never be true.

David.

First, I tried leaving the #if 0 unchanged, but this also just results in the errors:

This is what the Arduino IDE says:

In file included from /Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_shield.h:3:0,
                 from /Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:28:
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1022:2: warning: #warning USE_D2_ON_D10 [-Wcpp]
 #warning USE_D2_ON_D10
  ^
In file included from /Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:28:0:
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_shield.h:5:2: warning: #warning WE ARE USING A SPECIAL CUSTOM DRIVER [-Wcpp]
 #warning WE ARE USING A SPECIAL CUSTOM DRIVER
  ^
In file included from /Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_shield.h:3:0,
                 from /Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:28:
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp: In function 'uint16_t read16bits()':
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:126:5: note: in expansion of macro 'READ_8'
     READ_8(ret);
     ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:129:5: note: in expansion of macro 'READ_8'
     READ_8(lo);
     ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp: In member function 'int16_t MCUFRIEND_kbv::readGRAM(int16_t, int16_t, uint16_t*, int16_t, int16_t)':
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:272:13: note: in expansion of macro 'READ_8'
             READ_8(r);
             ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1043:37: note: in expansion of macro 'READ_8'
 #define READ_16(dst)  { uint8_t hi; READ_8(hi); READ_8(dst); dst |= (hi << 8); }
                                     ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:274:13: note: in expansion of macro 'READ_16'
             READ_16(dummy);
             ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1043:49: note: in expansion of macro 'READ_8'
 #define READ_16(dst)  { uint8_t hi; READ_8(hi); READ_8(dst); dst |= (hi << 8); }
                                                 ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:274:13: note: in expansion of macro 'READ_16'
             READ_16(dummy);
             ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:276:26: note: in expansion of macro 'READ_8'
   if (_lcd_ID == 0x1511) READ_8(r);   //extra dummy for R61511
                          ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:279:17: note: in expansion of macro 'READ_8'
                 READ_8(r);
                 ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:280:17: note: in expansion of macro 'READ_8'
                 READ_8(g);
                 ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:281:17: note: in expansion of macro 'READ_8'
                 READ_8(b);
                 ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1043:37: note: in expansion of macro 'READ_8'
 #define READ_16(dst)  { uint8_t hi; READ_8(hi); READ_8(dst); dst |= (hi << 8); }
                                     ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:287:17: note: in expansion of macro 'READ_16'
                 READ_16(ret);
                 ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1042:50: error: expected ')' before ';' token
 #define READ_8(dst)   { RD_STROBE; dst = read_8(); RD_IDLE; }
                                                  ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/utility/mcufriend_special.h:1043:49: note: in expansion of macro 'READ_8'
 #define READ_16(dst)  { uint8_t hi; READ_8(hi); READ_8(dst); dst |= (hi << 8); }
                                                 ^
/Users/Myself/Documents/Arduino/libraries/MCUFRIEND_kbv/MCUFRIEND_kbv.cpp:287:17: note: in expansion of macro 'READ_16'
                 READ_16(ret);
                 ^
exit status 1
Error compiling for board Arduino/Genuino Uno.

Nils.

My apologies. I tried it for myself. And got your errors.

The problem is down to unmatched parentheses:

#define read_8()      ( (PINB & BMASK) | (PIND & DMASK) )

That is what happens when I just type a SPECIAL into the Browser.

Removing the unwanted left-parenthesis made it compile ok.
You should just get two orange Warnings now.

Untested on real hardware. I wait to hear from you.

David.

Thanks.

No apologies needed!
That fixed it.
Running nice now :slight_smile:

Btw, I really like your library. Thanks for it too! :wink:

I will try the Pin_Change interrupt next and asses which way to use (since I have to make a shield for the photoelectric guard anyway, I am still unsure which version to use).

I can confirm now, that it works on real hardware ^^

cheers and thanks again,

Nils.