forked from juj/fbcp-ili9341
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ili9488.cpp
174 lines (154 loc) · 6.02 KB
/
ili9488.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include "config.h"
#if defined(ILI9488)
#include "spi.h"
#include <memory.h>
#include <stdio.h>
void InitILI9488()
{
// If a Reset pin is defined, toggle it briefly high->low->high to enable the device. Some devices do not have a reset pin, in which case compile with GPIO_TFT_RESET_PIN left undefined.
#if defined(GPIO_TFT_RESET_PIN) && GPIO_TFT_RESET_PIN >= 0
printf("Resetting ili9488 display at reset GPIO pin %d\n", GPIO_TFT_RESET_PIN);
SET_GPIO_MODE(GPIO_TFT_RESET_PIN, 1);
SET_GPIO(GPIO_TFT_RESET_PIN);
usleep(120 * 1000);
CLEAR_GPIO(GPIO_TFT_RESET_PIN);
usleep(120 * 1000);
SET_GPIO(GPIO_TFT_RESET_PIN);
usleep(120 * 1000);
#endif
// Do the initialization with a very low SPI bus speed, so that it will succeed even if the bus speed chosen by the user is too high.
spi->clk = 34;
__sync_synchronize();
BEGIN_SPI_COMMUNICATION();
{
//0xE0 - PGAMCTRL Positive Gamma Control
SPI_TRANSFER(0xE0, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F);
//0xE1 - NGAMCTRL Negative Gamma Control
SPI_TRANSFER(0xE1, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F);
// 0xC0 Power Control 1
SPI_TRANSFER(0xC0, 0x17, 0x15);
// 0xC1 Power Control 2
SPI_TRANSFER(0xC1, 0x41);
// 0xC5 VCOM Control
SPI_TRANSFER(0xC5, 0x00, 0x12, 0x80);
// Memory access control. Determines display orientation,
// display color filter and refresh order/direction.
#define MADCTL_HORIZONTAL_REFRESH_ORDER (1<<2)
#define MADCTL_BGR_PIXEL_ORDER (1<<3)
#define MADCTL_VERTICAL_REFRESH_ORDER (1<<4)
#define MADCTL_ROW_COLUMN_EXCHANGE (1<<5)
#define MADCTL_COLUMN_ADDRESS_ORDER_SWAP (1<<6)
#define MADCTL_ROW_ADDRESS_ORDER_SWAP (1<<7)
#define MADCTL_ROTATE_180_DEGREES (MADCTL_COLUMN_ADDRESS_ORDER_SWAP | MADCTL_ROW_ADDRESS_ORDER_SWAP)
uint8_t madctl(0);
#ifndef DISPLAY_SWAP_BGR
madctl |= MADCTL_BGR_PIXEL_ORDER;
#endif
#if defined(DISPLAY_FLIP_ORIENTATION_IN_HARDWARE)
madctl |= MADCTL_ROW_COLUMN_EXCHANGE;
#endif
#ifdef DISPLAY_ROTATE_180_DEGREES
madctl ^= MADCTL_ROTATE_180_DEGREES;
#endif
//
// Shifted value of bits [7:5] (MY - ROW_ADDRESS_ORDER_SWAP, MX - COLUMN_ADDRESS_ORDER_SWAP, MV ROW_COLUMN_EXCHANGE)
// and their resulting effect on the orientation of the image
// relative to the physical screen:
// 0x40 0 deg (W = 320, H = 480, FPC connector at bottom)
// 0x20 90 deg (W = 480, H = 320, FPC connector on right)
// 0x80 180 deg (W = 320, H = 480, FPC connector on top)
// 0xE0 270 deg (W = 480, H = 320, FPC connector on left)
// 0x36 Memory Access Control - sets display rotation.
SPI_TRANSFER(0x36, madctl);
// 0x3A Interface Pixel Format (bit depth color space)
SPI_TRANSFER(0x3A, 0x66);
// 0xB0 Interface Mode Control
SPI_TRANSFER(0xB0, 0x80);
// 0xB1 Frame Rate Control (in Normal Mode/Full Colors)
SPI_TRANSFER(0xB1, 0xA0);
// The display inversion is controlled by two registers:
// 0xB4 determines how the LEDs are swapped.See page 224 of the datasheet:
// The different values are:
// 0x00 Column inversion.
// 0x01 1 dot inversion.
// 0x02 2 dot inversion.
// 0x20/0x21 engage and disengage the inversion itself.
//
// I could not find a difference is using the three different
// settings for 0xB4. It is left at 0x02 since that is what
// the original test value was set to.
#ifdef DISPLAY_INVERT_COLORS
// 0xB4 Display Inversion Control.
SPI_TRANSFER(0xB4, 0x02);
// 0x21 Display Inversion ON.
SPI_TRANSFER(0x21);
#else
// 0xB4 Display Inversion Control.
SPI_TRANSFER(0xB4, 0x02);
// 0x20 Display Inversion OFF.
SPI_TRANSFER(0x20);
#endif
// 0xB6 Display Function Control.
SPI_TRANSFER(0xB6, 0x02, 0x02);
// 0xE9 Set Image Function.
SPI_TRANSFER(0xE9, 0x00);
// 0xF7 Adjuist Control 3
SPI_TRANSFER(0xF7, 0xA9, 0x51, 0x2C, 0x82);
// 0x11 Exit Sleep Mode. (Sleep OUT)
SPI_TRANSFER(0x11);
usleep(120*1000);
// 0x29 Display ON.
SPI_TRANSFER(0x29);
// 0x38 Idle Mode OFF.
SPI_TRANSFER(0x38);
// 0x13 Normal Display Mode ON.
SPI_TRANSFER(0x13);
#if defined(GPIO_TFT_BACKLIGHT) && defined(BACKLIGHT_CONTROL)
printf("Setting TFT backlight on at pin %d\n", GPIO_TFT_BACKLIGHT);
TurnBacklightOn();
#endif
ClearScreen();
}
#ifndef USE_DMA_TRANSFERS // For DMA transfers, keep SPI CS & TA active.
END_SPI_COMMUNICATION();
#endif
// And speed up to the desired operation speed finally after init is done.
usleep(10 * 1000); // Delay a bit before restoring CLK, or otherwise this has been observed to cause the display not init if done back to back after the clear operation above.
spi->clk = SPI_BUS_CLOCK_DIVISOR;
}
void TurnBacklightOff()
{
#if defined(GPIO_TFT_BACKLIGHT) && defined(BACKLIGHT_CONTROL)
SET_GPIO_MODE(GPIO_TFT_BACKLIGHT, 0x01); // Set backlight pin to digital 0/1 output mode (0x01) in case it had been PWM controlled
CLEAR_GPIO(GPIO_TFT_BACKLIGHT); // And turn the backlight off.
#endif
}
void TurnBacklightOn()
{
#if defined(GPIO_TFT_BACKLIGHT) && defined(BACKLIGHT_CONTROL)
SET_GPIO_MODE(GPIO_TFT_BACKLIGHT, 0x01); // Set backlight pin to digital 0/1 output mode (0x01) in case it had been PWM controlled
SET_GPIO(GPIO_TFT_BACKLIGHT); // And turn the backlight on.
#endif
}
void TurnDisplayOff()
{
TurnBacklightOff();
QUEUE_SPI_TRANSFER(0x28/*Display OFF*/);
QUEUE_SPI_TRANSFER(0x10/*Enter Sleep Mode*/);
usleep(120*1000); // Sleep off can be sent 120msecs after entering sleep mode the earliest, so synchronously sleep here for that duration to be safe.
}
void TurnDisplayOn()
{
TurnBacklightOff();
QUEUE_SPI_TRANSFER(0x11/*Sleep Out*/);
usleep(120 * 1000);
QUEUE_SPI_TRANSFER(0x29/*Display ON*/);
usleep(120 * 1000);
TurnBacklightOn();
}
void DeinitSPIDisplay()
{
ClearScreen();
TurnDisplayOff();
}
#endif