ugfx/drivers/gdisp/ILI9225/gdisp_lld_ili9225.c

383 lines
13 KiB
C

/*
* Created by Oleg Gerasimov <ogerasimov@gmail.com>
* 10.08.2016
*/
#include "gfx.h"
#if GFX_USE_GDISP
#if defined(GDISP_SCREEN_HEIGHT) || defined(GDISP_SCREEN_HEIGHT)
#if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
#elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
COMPILER_WARNING("GDISP: This low level driver does not support setting a screen size. It is being ignored.")
#endif
#undef GDISP_SCREEN_WIDTH
#undef GDISP_SCREEN_HEIGHT
#endif
#define GDISP_DRIVER_VMT GDISPVMT_ILI9225
#include "gdisp_lld_config.h"
#include "src/gdisp/gdisp_driver.h"
#include "board_ILI9225.h"
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
#ifndef GDISP_SCREEN_HEIGHT
#define GDISP_SCREEN_HEIGHT 220
#endif
#ifndef GDISP_SCREEN_WIDTH
#define GDISP_SCREEN_WIDTH 176
#endif
#ifndef GDISP_INITIAL_CONTRAST
#define GDISP_INITIAL_CONTRAST 100
#endif
#ifndef GDISP_INITIAL_BACKLIGHT
#define GDISP_INITIAL_BACKLIGHT 100
#endif
#include "drivers/gdisp/ILI9225/ili9225.h"
// Some common routines and macros
#define dummy_read(g) { volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
#define write_reg(g, reg, data) { write_cmd(g, reg); write_data(g, data); }
// Serial write data for fast fill.
#ifndef write_data_repeat
#define write_data_repeat(g, data, count) { int i; for (i = 0; i < count; ++i) write_data (g, data) }
#endif
LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
// No private area for this controller
g->priv = 0;
// Initialise the board interface
init_board(g);
// Hardware reset
setpin_reset(g, TRUE);
gfxSleepMilliseconds(20);
setpin_reset(g, FALSE);
gfxSleepMilliseconds(20);
// Get the bus for the following initialisation commands
acquire_bus(g);
write_reg(g, ILI9225_POWER_CTRL1, 0x0000); // Set SAP,DSTB,STB
write_reg(g, ILI9225_POWER_CTRL2, 0x0000); // Set APON,PON,AON,VCI1EN,VC
write_reg(g, ILI9225_POWER_CTRL3, 0x0000); // Set BT,DC1,DC2,DC3
write_reg(g, ILI9225_POWER_CTRL4, 0x0000); // Set GVDD
write_reg(g, ILI9225_POWER_CTRL5, 0x0000); // Set VCOMH/VCOML voltage
gfxSleepMilliseconds(40);
// Power-on sequence
write_reg(g, ILI9225_POWER_CTRL2, 0x0018); // Set APON,PON,AON,VCI1EN,VC
write_reg(g, ILI9225_POWER_CTRL3, 0x6121); // Set BT,DC1,DC2,DC3
write_reg(g, ILI9225_POWER_CTRL4, 0x006F); // Set GVDD /*007F 0088 */
write_reg(g, ILI9225_POWER_CTRL5, 0x495F); // Set VCOMH/VCOML voltage
write_reg(g, ILI9225_POWER_CTRL1, 0x0F00); // Set SAP,DSTB,STB
gfxSleepMilliseconds(10);
write_reg(g, ILI9225_POWER_CTRL2, 0x103B); // Set APON,PON,AON,VCI1EN,VC
gfxSleepMilliseconds(50);
write_reg(g, ILI9225_DRIVER_OUTPUT_CTRL, 0x011C); // set the display line number and display direction
write_reg(g, ILI9225_LCD_AC_DRIVING_CTRL, 0x0100); // set 1 line inversion
write_reg(g, ILI9225_ENTRY_MODE, 0x1030); // set GRAM write direction and BGR=1.
write_reg(g, ILI9225_DISP_CTRL1, 0x0000); // Display off
write_reg(g, ILI9225_BLANK_PERIOD_CTRL1, 0x0808); // set the back porch and front porch
write_reg(g, ILI9225_FRAME_CYCLE_CTRL, 0x1100); // set the clocks number per line
write_reg(g, ILI9225_INTERFACE_CTRL, 0x0000); // CPU interface
write_reg(g, ILI9225_OSC_CTRL, 0x0D01); // Set Osc /*0e01*/
write_reg(g, ILI9225_VCI_RECYCLING, 0x0020); // Set VCI recycling
write_reg(g, ILI9225_RAM_ADDR_SET1, 0x0000); // RAM Address
write_reg(g, ILI9225_RAM_ADDR_SET2, 0x0000); // RAM Address
// Set GRAM area
write_reg(g, ILI9225_GATE_SCAN_CTRL, 0x0000);
write_reg(g, ILI9225_VERTICAL_SCROLL_CTRL1, 0x00DB);
write_reg(g, ILI9225_VERTICAL_SCROLL_CTRL2, 0x0000);
write_reg(g, ILI9225_VERTICAL_SCROLL_CTRL3, 0x0000);
write_reg(g, ILI9225_PARTIAL_DRIVING_POS1, 0x00DB);
write_reg(g, ILI9225_PARTIAL_DRIVING_POS2, 0x0000);
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR1, 0x00AF);
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR2, 0x0000);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR1, 0x00DB);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR2, 0x0000);
// Set GAMMA curve
write_reg(g, ILI9225_GAMMA_CTRL1, 0x0000);
write_reg(g, ILI9225_GAMMA_CTRL2, 0x0808);
write_reg(g, ILI9225_GAMMA_CTRL3, 0x080A);
write_reg(g, ILI9225_GAMMA_CTRL4, 0x000A);
write_reg(g, ILI9225_GAMMA_CTRL5, 0x0A08);
write_reg(g, ILI9225_GAMMA_CTRL6, 0x0808);
write_reg(g, ILI9225_GAMMA_CTRL7, 0x0000);
write_reg(g, ILI9225_GAMMA_CTRL8, 0x0A00);
write_reg(g, ILI9225_GAMMA_CTRL9, 0x0710);
write_reg(g, ILI9225_GAMMA_CTRL10, 0x0710);
write_reg(g, ILI9225_DISP_CTRL1, 0x0012);
gfxSleepMilliseconds(50);
write_reg(g, ILI9225_DISP_CTRL1, 0x1017);
release_bus(g);
// Finish Init
post_init_board(g);
/* Turn on the back-light */
set_backlight(g, GDISP_INITIAL_BACKLIGHT);
/* Initialise the GDISP structure */
g->g.Width = GDISP_SCREEN_WIDTH;
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Orientation = GDISP_ROTATE_0;
g->g.Powermode = powerOn;
g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
g->g.Contrast = GDISP_INITIAL_CONTRAST;
return TRUE;
}
static void set_cursor(GDisplay *g) {
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
case GDISP_ROTATE_180:
write_reg(g, ILI9225_RAM_ADDR_SET1, g->p.x);
write_reg(g, ILI9225_RAM_ADDR_SET2, g->p.y);
break;
case GDISP_ROTATE_90:
case GDISP_ROTATE_270:
write_reg(g, ILI9225_RAM_ADDR_SET1, g->p.y);
write_reg(g, ILI9225_RAM_ADDR_SET2, g->p.x);
break;
}
write_cmd (g, ILI9225_GRAM_DATA_REG);
}
static void set_viewport(GDisplay *g) {
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
case GDISP_ROTATE_180:
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR2, g->p.x);
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR1, g->p.x + g->p.cx - 1);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR2, g->p.y);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR1, g->p.y + g->p.cy - 1);
break;
case GDISP_ROTATE_90:
case GDISP_ROTATE_270:
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR2, g->p.y);
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR1, g->p.y + g->p.cy - 1);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR2, g->p.x);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR1, g->p.x + g->p.cx - 1);
break;
}
}
// temporary variables for saving viewport
static int svx,svy,svcx,svcy,ws;
#if GDISP_HARDWARE_STREAM_WRITE
LLDSPEC void gdisp_lld_write_start(GDisplay *g) {
acquire_bus(g);
set_viewport(g);
// save viewport
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
case GDISP_ROTATE_180:
svx = g->p.x; svy = g->p.y; svcx = g->p.cx; svcy = g->p.cy;
break;
case GDISP_ROTATE_90:
case GDISP_ROTATE_270:
svx = g->p.y; svy = g->p.x; svcx = g->p.cy; svcy = g->p.cx;
break;
}
ws++;
}
LLDSPEC void gdisp_lld_write_color(GDisplay *g) {
LLDCOLOR_TYPE c;
c = gdispColor2Native(g->p.color);
write_data(g, c );
}
LLDSPEC void gdisp_lld_write_stop(GDisplay *g) {
release_bus(g);
if (ws)
ws--;
}
LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
set_cursor(g);
}
#endif
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
set_cursor(g);
gdisp_lld_write_color (g);
}
#if GDISP_HARDWARE_FILLS
LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
LLDCOLOR_TYPE c = gdispColor2Native(g->p.color);
acquire_bus(g);
// Set view port if drawing more than 1 line, or write not started
if (g->p.cy != 1 || !ws)
set_viewport(g);
set_cursor(g);
write_data_repeat (g,c,g->p.cx*g->p.cy);
// Restore view port if write started and drawed more than 1 line
if (g->p.cy != 1 && ws)
{
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR2, svx);
write_reg(g, ILI9225_HORIZONTAL_WINDOW_ADDR1, svx + svcx - 1);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR2, svy);
write_reg(g, ILI9225_VERTICAL_WINDOW_ADDR1, svy + svcy - 1);
}
release_bus(g);
}
#endif // GDISP_HARDWARE_FILLS
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay *g) {
switch(g->p.x) {
case GDISP_CONTROL_POWER:
if (g->g.Powermode == (powermode_t)g->p.ptr)
return;
switch((powermode_t)g->p.ptr) {
case powerOff:
acquire_bus(g);
write_reg(g, ILI9225_DISP_CTRL1, 0x0000); // Display off
write_reg(g, ILI9225_POWER_CTRL1, 0x0000); // Set SAP,DSTB,STB
write_reg(g, ILI9225_POWER_CTRL2, 0x0000); // Set APON,PON,AON,VCI1EN,VC
write_reg(g, ILI9225_POWER_CTRL3, 0x0000); // Set BT,DC1,DC2,DC3
write_reg(g, ILI9225_POWER_CTRL4, 0x0000); // Set GVDD
write_reg(g, ILI9225_POWER_CTRL5, 0x0000); // Set VCOMH/VCOML voltage
release_bus();
set_backlight(g, 0);
break;
case powerSleep:
case powerDeepSleep:
acquire_bus(g);
write_reg(g, ILI9225_DISP_CTRL1, 0x0000); // Display off
write_reg(g, ILI9225_POWER_CTRL1, 0x0000); // Set SAP,DSTB,STB
write_reg(g, ILI9225_POWER_CTRL2, 0x0000); // Set APON,PON,AON,VCI1EN,VC
write_reg(g, ILI9225_POWER_CTRL3, 0x0000); // Set BT,DC1,DC2,DC3
write_reg(g, ILI9225_POWER_CTRL4, 0x0000); // Set GVDD
gfxSleepMilliseconds(40);
write_reg(g, ILI9225_POWER_CTRL1, 0x0004); // Set SAP,DSTB,STB
release_bus(g);
set_backlight(g, 0);
break;
case powerOn:
acquire_bus(g);
write_reg(g, ILI9225_POWER_CTRL1, 0x0000); // Set SAP,DSTB,STB
write_reg(g, ILI9225_POWER_CTRL2, 0x0000); // Set APON,PON,AON,VCI1EN,VC
write_reg(g, ILI9225_POWER_CTRL3, 0x0000); // Set BT,DC1,DC2,DC3
write_reg(g, ILI9225_POWER_CTRL4, 0x0000); // Set GVDD
write_reg(g, ILI9225_POWER_CTRL5, 0x0000); // Set VCOMH/VCOML voltage
gfxSleepMilliseconds(40);
// Power-on sequence
write_reg(g, ILI9225_POWER_CTRL2, 0x0018); // Set APON,PON,AON,VCI1EN,VC
write_reg(g, ILI9225_POWER_CTRL3, 0x6121); // Set BT,DC1,DC2,DC3
write_reg(g, ILI9225_POWER_CTRL4, 0x006F); // Set GVDD /*007F 0088 */
write_reg(g, ILI9225_POWER_CTRL5, 0x495F); // Set VCOMH/VCOML voltage
write_reg(g, ILI9225_POWER_CTRL1, 0x0F00); // Set SAP,DSTB,STB
gfxSleepMilliseconds(10);
write_reg(g, ILI9225_POWER_CTRL2, 0x103B); // Set APON,PON,AON,VCI1EN,VC
gfxSleepMilliseconds(50);
write_reg(g, ILI9225_DRIVER_OUTPUT_CTRL, 0x011C); // set the display line number and display direction
write_reg(g, ILI9225_LCD_AC_DRIVING_CTRL, 0x0100); // set 1 line inversion
write_reg(g, ILI9225_ENTRY_MODE, 0x1030); // set GRAM write direction and BGR=1.
write_reg(g, ILI9225_DISP_CTRL1, 0x0000); // Display off
write_reg(g, ILI9225_BLANK_PERIOD_CTRL1, 0x0808); // set the back porch and front porch
write_reg(g, ILI9225_FRAME_CYCLE_CTRL, 0x1100); // set the clocks number per line
write_reg(g, ILI9225_INTERFACE_CTRL, 0x0000); // CPU interface
write_reg(g, ILI9225_OSC_CTRL, 0x0D01); // Set Osc /*0e01*/
write_reg(g, ILI9225_VCI_RECYCLING, 0x0020); // Set VCI recycling
// Set GRAM area
write_reg(g, ILI9225_GATE_SCAN_CTRL, 0x0000);
write_reg(g, ILI9225_VERTICAL_SCROLL_CTRL1, 0x00DB);
write_reg(g, ILI9225_VERTICAL_SCROLL_CTRL2, 0x0000);
write_reg(g, ILI9225_VERTICAL_SCROLL_CTRL3, 0x0000);
write_reg(g, ILI9225_PARTIAL_DRIVING_POS1, 0x00DB);
write_reg(g, ILI9225_PARTIAL_DRIVING_POS2, 0x0000);
write_reg(g, ILI9225_DISP_CTRL1, 0x0012);
gfxSleepMilliseconds(50);
write_reg(g, ILI9225_DISP_CTRL1, 0x1017);
release_bus(g);
set_backlight(g, g->g.Backlight);
break;
default:
return;
}
g->g.Powermode = (powermode_t)g->p.ptr;
return;
case GDISP_CONTROL_ORIENTATION:
if (g->g.Orientation == (orientation_t)g->p.ptr)
return;
switch((orientation_t)g->p.ptr) {
case GDISP_ROTATE_0: // correct
acquire_bus(g);
write_reg(g, ILI9225_DRIVER_OUTPUT_CTRL, 0x011C);
write_reg(g, ILI9225_ENTRY_MODE, 0x1030);
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Width = GDISP_SCREEN_WIDTH;
release_bus(g);
break;
case GDISP_ROTATE_90:
acquire_bus(g);
write_reg(g, ILI9225_DRIVER_OUTPUT_CTRL, 0x031C);
write_reg(g, ILI9225_ENTRY_MODE, 0x1038);
g->g.Height = GDISP_SCREEN_WIDTH;
g->g.Width = GDISP_SCREEN_HEIGHT;
release_bus(g);
break;
case GDISP_ROTATE_180:
acquire_bus(g);
write_reg(g, ILI9225_DRIVER_OUTPUT_CTRL, 0x021C);
write_reg(g, ILI9225_ENTRY_MODE, 0x1030);
g->g.Height = GDISP_SCREEN_HEIGHT;
g->g.Width = GDISP_SCREEN_WIDTH;
release_bus(g);
break;
case GDISP_ROTATE_270:
acquire_bus(g);
write_reg(g, ILI9225_DRIVER_OUTPUT_CTRL, 0x001C);
write_reg(g, ILI9225_ENTRY_MODE, 0x1038);
g->g.Height = GDISP_SCREEN_WIDTH;
g->g.Width = GDISP_SCREEN_HEIGHT;
release_bus(g);
break;
default:
return;
}
g->g.Orientation = (orientation_t)g->p.ptr;
return;
case GDISP_CONTROL_BACKLIGHT:
if ((unsigned)g->p.ptr > 100)
g->p.ptr = (void *)100;
set_backlight(g, (unsigned)g->p.ptr);
g->g.Backlight = (unsigned)g->p.ptr;
return;
default:
return;
}
}
#endif
#endif /* GFX_USE_GDISP */