kbr-net/sdrive-max

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);
}