Tomahawkmissile
Posts: 2
Joined: Tue Nov 14, 2017 3:58 am

Help with ILI9225 display

Tue Nov 14, 2017 4:27 am

Hello everyone, for about a month and a half now I have been experiencing this weird issue with my four ILI9225 displays that I bought on Amazon a while back. I have tried to make my own display driver for these screens (and essentially took bits and pieces from different libraries on GitHub), but it doesn't seem to work. When I compile my code and run it via software SPI (because I have 4 of these and cannot run them all off of hardware SPI), the entire screen just fills with randomized colored pixels (similar to the static on a TV, but in color). Now, before you say that the screens could be defective, I have gotten them working, but only on my Arduino with a library and on my Raspberry Pi with another library. I would really prefer to try make my own driver for these, so please do not just tell me to use a library from the internet. Thanks in advance for any help!

Pardon my C++ skills, as I only began about two months ago. :)

And here's my code (C++), and I will also include images of the display

Code: Select all

#include <iostream>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <mcp23017.h>

typedef unsigned char uint8_t;
typedef unsigned short uint16_t;

int LCD_SDI = 20;
int LCD_CLK = 21;
int LCD_RS = 19;
int LCD_RESET = 16;
int LCD_CS = 13;
//LED backlight
int LED_LIGHT = 100;

int ILI9225C_HEIGHT=220;
int ILI9225C_WIDTH=176;

uint16_t maxX=176;
uint16_t maxY=220;

uint8_t orientation;

uint16_t getMaxX() {
	return maxX;
}
uint16_t getMaxY() {
	return maxY;
}
void swap(uint16_t &a, uint16_t &b) {
	uint16_t w = a;
	a = b;
	b = w;
}
uint16_t getColor(uint8_t red8, uint8_t green8, uint8_t blue8) {
	return (red8 >> 3) << 11 | (green8 >> 2) << 5 | (blue8 >> 3);
}
void splitColor(uint16_t rgb, uint8_t &red, uint8_t &green, uint8_t &blue) {
	red   = (rgb & 0b1111100000000000) >> 11 << 3;
	green = (rgb & 0b0000011111100000) >>  5 << 2;
	blue  = (rgb & 0b0000000000011111)       << 3;
}
void write(uint8_t data) {
	for(uint8_t bit = 0x80; bit; bit >>= 1) {
		if(data & bit) {
			digitalWrite(LCD_SDI, 1); 
		} else {
			digitalWrite(LCD_SDI, 0); 
		}
		digitalWrite(LCD_CLK, 1);
		digitalWrite(LCD_CLK, 0);
	}
}
void writeCommand(uint8_t hi, uint8_t lo) {
	digitalWrite(LCD_RS,0);
	digitalWrite(LCD_CS,0);
	write(hi);
	write(lo);
	digitalWrite(LCD_CS,1);
}
void writeData(uint8_t hi, uint8_t lo) {
	digitalWrite(LCD_RS,1);
	digitalWrite(LCD_CS,0);
	write(hi);
	write(lo);
	digitalWrite(LCD_CS,1);
}
void writeRegister(uint16_t reg, uint16_t data) {
	writeCommand(reg>>8,reg&255);
	writeData(data>>8,data&255);
}
void orientCoordinates(uint16_t &x1, uint16_t &y1) {
	switch (orientation) {
	case 0:
		break;
	case 1:
		y1 = maxY - y1 -1;
		swap(x1, y1);
		break;
	case 2:
		x1 = maxX - x1 -1;
		y1 = maxY - y1 -1;
		break;
	case 3:
		x1 = maxX - x1 -1;
		swap(x1, y1);
		break;
	}
}
void setWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
	orientCoordinates(x0, y0);
	orientCoordinates(x1, y1);

	if (x1<x0) swap(x0, x1);
	if (y1<y0) swap(y0, y1);

	writeRegister(0x36,x1);
	writeRegister(0x37,x0);

	writeRegister(0x38,y1);
	writeRegister(0x39,y0);

	writeRegister(0x20,x0);
	writeRegister(0x21,y0);

	writeCommand(0x00,0x22);
}
void invert(bool flag) {
	writeCommand(0x00,flag ? 0x21 : 0x20);
}
void setBacklight(bool flag) {
	digitalWrite(LED_LIGHT, flag);
}
void setDisplay(bool flag) {
	if (flag) {
		writeRegister(0x00FF, 0x0000);
		writeRegister(0x0010, 0x0000);
		delay(50);
		writeRegister(0x0007, 0x1017);
		delay(200);
	} else {
		writeRegister(0x00ff, 0x0000);
		writeRegister(0x0007, 0x0000);
		delay(50);
		writeRegister(0x0010, 0x0003);
		delay(200);
	}
}
void setOrientation(uint8_t orientation) {
	orientation = orientation % 4;
	switch (orientation) {
	case 0:
		maxX = 176;
		maxY = 220;
		break;
	case 1:
		maxX = 220;
		maxY = 176;
		break;
	case 2:
		maxX = 176;
		maxY = 220;
		break;
	case 3:
		maxX = 220;
		maxY = 176	;
		break;
	}
}
uint8_t getOrientation() {
	return orientation;
}
void drawPixel(uint16_t x1, uint16_t y1, uint16_t color) {
	setWindow(x1, y1, x1+1, y1+1);
	orientCoordinates(x1, y1);
	writeRegister(color>>8,color&255);
}
void fillRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) {
	setWindow(x1,y1,x2,y2);
	orientCoordinates(x1,y1);
	writeData(color>>8,color&255);
}
void fill(uint16_t color) {
	fillRectangle(0,0,maxX,maxY,color);
}

void clear() {
	uint8_t old = orientation;
	setOrientation(0);
	fillRectangle(0,0,maxX,maxY,0x0);
	setOrientation(old);
}
void init() {

	wiringPiSetupGpio();
	mcp23017Setup(100,0x20);
	
	pinMode(LCD_SDI,OUTPUT);
	pinMode(LCD_CLK,OUTPUT);
	pinMode(LCD_RS,OUTPUT);
	pinMode(LCD_RESET,OUTPUT);
	pinMode(LCD_CS,OUTPUT);
	pinMode(LED_LIGHT,OUTPUT);
	
	digitalWrite(LED_LIGHT, 0);
	digitalWrite(LCD_RESET, 0);
	digitalWrite(LCD_RS, 0);
	digitalWrite(LCD_CS, 1);
	digitalWrite(LCD_SDI, 0);
	digitalWrite(LCD_CLK, 1);
	
	delay(50);

	digitalWrite(LCD_RESET, 1); // Pull the reset pin high to release the ILI9225C from the reset status
	delay(1); 
	digitalWrite(LCD_RESET, 0); // Pull the reset pin low to reset ILI9225
	delay(10);
	digitalWrite(LCD_RESET, 1); // Pull the reset pin high to release the ILI9225C from the reset status
	delay(50);
	
	writeRegister(0x10, 0x0000); // Set SAP,DSTB,STB
	writeRegister(0x11, 0x0000); // Set APON,PON,AON,VCI1EN,VC
	writeRegister(0x12, 0x0000); // Set BT,DC1,DC2,DC3
	writeRegister(0x13, 0x0000); // Set GVDD
	writeRegister(0x14, 0x0000); // Set VCOMH/VCOML voltage
	delay(40); 
	
	// Power-on sequence
	writeRegister(0x11, 0x0018); // Set APON,PON,AON,VCI1EN,VC
	writeRegister(0x12, 0x6121); // Set BT,DC1,DC2,DC3
	writeRegister(0x13, 0x006F); // Set GVDD   007F 0088
	writeRegister(0x14, 0x495F); // Set VCOMH/VCOML voltage
	writeRegister(0x10, 0x0800); // Set SAP,DSTB,STB
	delay(10);
	writeRegister(0x11, 0x103B); // Set APON,PON,AON,VCI1EN,VC
	delay(50);
	
	writeRegister(0x01, 0x011C); // set the display line number and display direction
	writeRegister(0x02, 0x0100); // set 1 line inversion
	writeRegister(0x03, 0x1030); // set GRAM write direction and BGR=1.
	writeRegister(0x07, 0x0000); // Display off
	writeRegister(0x08, 0x0808); // set the back porch and front porch
	writeRegister(0x0B, 0x1100); // set the clocks number per line
	writeRegister(0x0C, 0x0000); // CPU interface
	writeRegister(0x0F, 0x0D01); // Set Osc  0e01
	writeRegister(0x15, 0x0020); // Set VCI recycling
	writeRegister(0x20, 0x0000); // RAM Address
	writeRegister(0x21, 0x0000); // RAM Address
	
	// GRAM area
	writeRegister(0x30, 0x0000); 
	writeRegister(0x31, 0x00DB); 
	writeRegister(0x32, 0x0000); 
	writeRegister(0x33, 0x0000); 
	writeRegister(0x34, 0x00DB); 
	writeRegister(0x35, 0x0000); 
	writeRegister(0x36, 0x00AF); 
	writeRegister(0x37, 0x0000); 
	writeRegister(0x38, 0x00DB);
	writeRegister(0x39, 0x0000); 

	// Gamma 2.2 
	writeRegister(0x50, 0x0000); 
	writeRegister(0x51, 0x0808); 
	writeRegister(0x52, 0x080A); 
	writeRegister(0x53, 0x000A); 
	writeRegister(0x54, 0x0A08); 
	writeRegister(0x55, 0x0808); 
	writeRegister(0x56, 0x0000); 
	writeRegister(0x57, 0x0A00); 
	writeRegister(0x58, 0x0710); 
	writeRegister(0x59, 0x0710);
	
	writeRegister(0x07, 0x0012);
	delay(50); 
	writeRegister(0x07, 0x1017);
	
	setBacklight(true);
	setOrientation(0);
	
	clear();
}
void shutdown() {
	setDisplay(false);
	setBacklight(false);
}
void display() {
	drawPixel(87,110,0x0);
}
int main() {
	init();
	delay(100);
	display();
}
Images (files were too large to upload here):
https://www.dropbox.com/s/9bb3bguvixh69 ... 1.JPG?dl=0
https://www.dropbox.com/s/om576mj7qu0px ... 4.JPG?dl=0

dave j
Posts: 116
Joined: Mon Mar 05, 2012 2:19 pm

Re: Help with ILI9225 display

Wed Nov 15, 2017 11:52 am

First of all, if you haven't proved your software SPI implementation works by writing to a known working SPI implementation (e.g. one on your Arduino) ensure that it does - trying to debug two things at once needlessly complicates things.

As to your screen code.

Your drawPixel function defines a window that is 2 pixels square. It also uses writeRegister rather than writeData.

Your fillRectangle function only writes one pixel to the screen. You need to write a value for every you define by the window - so (x2-x1+1)*(y2-y1+1) pixels.

User avatar
[email protected]
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Re: Help with ILI9225 display

Wed Nov 15, 2017 3:13 pm

Two things - firstly I'd try one screen with the hardware SPI, then if that works, then you can use all 4 with the hardware SPI by using alternative CE pins and manually setting those pins rather than let the hardware use the hardware CE pins. (I do this to let me run 3 SPI Thermocouple amplifiers off the SPI interface)

Secondly, your clock pulse is going to be very tiny and very asymetric (which may not be an issue) I'd stick in a delay between the edges of the clock pulse - the Pi can toggle a pin on/off much faster than an Arduino can.

I think you may be able to use hardware SPI with more CE pins now too - someone mentioned a device tree overlay that might do it - I'm not 100% sure though.

-Gordon
--
Gordons projects: https://projects.drogon.net/

Tomahawkmissile
Posts: 2
Joined: Tue Nov 14, 2017 3:58 am

Re: Help with ILI9225 display

Thu Nov 16, 2017 12:24 am

First and foremost, thank you for helping me :D

So, to Dave's response...

You are correct, as I have not verified my SPI implementation. However, I am pretty sure it is correct because I essentially took the main write function from other libraries (It still could be wrong though). Regardless, I will double check its integrity right now. Also, I just fixed the issue with the other functions.


Now, about Gordon's response...

I have gotten all displays to work properly on hardware SPI on both my Arduino and Raspberry Pi. However, I used other libraries for this. I will check out your recommendation though. :)
About the clock pulses, I just tried that and all it seemed to do was slow down writes a lot.

After fixing the issues suggested, the problem persists. I am thinking it could be something to do with the initialization sequence, as I am getting different information from different libraries on how to correctly initialize this screen. Also, I believe I have singled out the line that causes this error. I added debug messages before and after it and I am 100% sure this line does it.

Code: Select all

writeRegister(0x07, 0x1017);

smarbos
Posts: 1
Joined: Sun Jan 07, 2018 10:40 pm

Re: Help with ILI9225 display

Sun Jan 07, 2018 10:42 pm

Hello! Have you any update about the driver for the ILI9225?
Im strugling to get this to work and I think Im a little bit lost.
THank you for your time!

Return to “C/C++”