MCUFRIEND ILI9340 display issues
Closed this issue · 6 comments
My screen is made by MCUFRIEND. It is an 2,4" ILI9340 TFT display with 8-bit bus and analog touch-sensor in a form of Arduino-compatible shell.
When I use sdrive-max-v12b2.zip, I can pass the screen calibration, but then the app doesn't react on touch (but it wakes up from screen saver on touch), colors are correct.
If I use sdrive-max-v12b3.zip, the image is mirrored, but the app does respond to the touch.
I always get sdrive.atr not found, but I on v12b3 I can browse the SD Card, and I see this file in the root directory. Card is FAT32 formatted 4GB micro-SDHC class 4.
Output from diagnose_Touchpins.ino is as follows:
Testing : (A1, D7) = 35
Testing : (A2, D6) = 25
Diagnosing as:-
YP,YM: (A1, D7) = 35
XM,XP: (A2, D6) = 25
Output from TouchScreen_Calibr_native.ino (from Arduino MCUFRIEND_kbv library) is:
const int XP=6,XM=A2,YP=A1,YM=7; //240x320 ID=0x9340
const int TS_LEFT=789,TS_RT=132,TS_TOP=397,TS_BOT=531;
PORTRAIT CALIBRATION 240 x 320
x = map(p.x, LEFT=789, RT=132, 0, 240)
y = map(p.y, TOP=397, BOT=531, 0, 320)
Touch Pin Wiring XP=6 XM=A2 YP=A1 YM=7
LANDSCAPE CALIBRATION 320 x 240
x = map(p.y, LEFT=397, RT=531, 0, 320)
y = map(p.x, TOP=132, BOT=789, 0, 240)
Update: when I upload firmware using Arduino bootloader, the sdrive.atr is loaded correctly from the SD-Card at boot. Apparently, without the bootloader, the firmware tries to access the SD-Card before it is ready.
I have complied v12 branch with ILI9329i profile, but I have changed in display.c
TFT_write(0x08) -> TFT_write(0x48)
TFT_write(0xd8) -> TFT_write(0x98)
...and the screen and touchscreen seem to work ok.
Actually a better patch is:
#ifdef INVERSE
delay_ms(200);
// TFT_write_cmd(ILI9341_RESET);
TFT_write_cmd(ILI9341_DISPLAY_INVERSION_ON);
// TFT_write(0x00);
#endif
#if defined HX8347G || defined HX8347I || defined HX8347D
//set later after scroll init
//TFT_write_cmd(0x01); //scroll mode on
//TFT_write(0x08);
TFT_write_cmd(0x17); //COLMOD 16bit
TFT_write(0x05);
TFT_write_cmd(0x18); //frame rate idle/normal 50Hz/60Hz
TFT_write(0x34);
TFT_write_cmd(0x19); //enable oscillator
TFT_write(0x01);
TFT_write_cmd(0x1f); //set power on and exit standby mode
TFT_write(0xd4);
//TFT_write_cmd(0x36); //characteristic SS, GS, BGR
//TFT_write(0x00);
TFT_write_cmd(0x28); //gate output and display on
TFT_write(0x3c);
//TFT_write_cmd(0x22); //GRAM
#else
TFT_write_cmd(ILI9341_PIXEL_FORMAT);
TFT_write(0x55);
TFT_write_cmd(ILI9341_SLEEP_OUT);
delay_ms(100);
//TFT_write_cmd(ILI9341_DISPLAY_ON);
//TFT_write_cmd(ILI9341_GRAM);
#endif
So basically, for DISPLAY, you've got 3 options:
- ILI NORMAL
- ILI INVERTED
- HX
... and 2 for TOUCH:
- defined(HX8347G) || defined(ILI9329)
- other
...but the naming there is misleading, as it doesn't depend on chipset, but rather on shield version, and you could have any display on any shield...
Great work. Would you consider adding support for a different type of controller? RM68090
I think, this is also done with the new touchscreen autodetection firmware v12c.
...actually I have found a better "patch", as I find out that my display really is ILI3940 which supports scrolling, and the only problem is differently "wired" touchscreen:
void waitTouch() {
setIdling();
#if defined(HX8347G) || defined(ILI9329) || defined(ILI9340)
PCMSK2 |= (1<<XM); //select interrupt pin
PCICR |= (1<<PCIE2); //interrupt enable
#else
PCMSK0 |= (1<<XM); //select interrupt pin
PCICR |= (1<<PCIE0); //interrupt enable
#endif
SMCR = (1<<SM1) | (1<<SM0) | (1<<SE); //power save mode, sleep enable
sleep_cpu();
SMCR = 0; //disable
#if defined(HX8347G) || defined(ILI9329) || defined(ILI9340)
PCICR &= ~(1<<PCIE2); //interrupt disable
#else
PCICR &= ~(1<<PCIE0); //interrupt disable
#endif
restorePorts();
}
struct TSPoint getPoint () {
cli(); //disable interrupts
setIdling();
#if defined(HX8347G) || defined(ILI9329i) || defined(ILI9340)
p.x = map(readTouch(1), TS_MINX, TS_MAXX, 0, MAX_X);
p.y = map(readTouch(0), TS_MINY, TS_MAXY, 0, MAX_Y);
#else
p.x = map(readTouch(0), TS_MINX, TS_MAXX, 0, MAX_X);
p.y = map(readTouch(1), TS_MINY, TS_MAXY, 0, MAX_Y);
#endif
restorePorts();
sei();
return(p);
}
struct TSPoint getRawPoint () {
cli();
setIdling();
#if defined(HX8347G) || defined(ILI9329i) || defined(ILI9340)
p.x = readTouch(1);
p.y = readTouch(0);
#else
p.x = readTouch(0);
p.y = readTouch(1);
#endif
restorePorts();
sei();
return(p);
}