598 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			598 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/**
 | 
						|
  * @file GC9A01.c
 | 
						|
  *
 | 
						|
 **/
 | 
						|
 | 
						|
 | 
						|
/*********************
 | 
						|
 *      INCLUDES
 | 
						|
 *********************/
 | 
						|
#include "GC9A01.h"
 | 
						|
#if USE_GC9A01
 | 
						|
 | 
						|
#include <stdbool.h>
 | 
						|
#include <stddef.h>
 | 
						|
#include <string.h>
 | 
						|
 | 
						|
#include LV_DRV_DISP_INCLUDE
 | 
						|
#include LV_DRV_DELAY_INCLUDE
 | 
						|
 | 
						|
/*********************
 | 
						|
 *      DEFINES
 | 
						|
 *********************/
 | 
						|
#ifndef GC9A01_XSTART
 | 
						|
#define GC9A01_XSTART   	0
 | 
						|
#endif
 | 
						|
#ifndef GC9A01_YSTART
 | 
						|
#define GC9A01_YSTART   	0
 | 
						|
#endif
 | 
						|
 | 
						|
#define GC9A01_CMD_MODE		0
 | 
						|
#define GC9A01_DATA_MODE     	1
 | 
						|
 | 
						|
#define GC9A01_HOR_RES  	240
 | 
						|
#define GC9A01_VER_RES  	240
 | 
						|
 | 
						|
/* GC9A01 Commands that we know of.  Limited documentation */
 | 
						|
#define GC9A01_INVOFF		0x20
 | 
						|
#define GC9A01_INVON		0x21
 | 
						|
#define GC9A01_DISPON		0x29
 | 
						|
#define GC9A01_CASET		0x2A
 | 
						|
#define GC9A01_RASET		0x2B
 | 
						|
#define GC9A01_RAMWR		0x2C
 | 
						|
#define GC9A01_COLMOD		0x3A
 | 
						|
#define GC9A01_MADCTL		0x36
 | 
						|
#define GC9A01_MADCTL_MY  	0x80
 | 
						|
#define GC9A01_MADCTL_MX  	0x40
 | 
						|
#define GC9A01_MADCTL_MV  	0x20
 | 
						|
#define GC9A01_MADCTL_RGB 	0x00
 | 
						|
#define GC9A01_DISFNCTRL	0xB6
 | 
						|
 | 
						|
/**********************
 | 
						|
 *      TYPEDEFS
 | 
						|
 **********************/
 | 
						|
 | 
						|
/* Init script function */
 | 
						|
struct GC9A01_function {
 | 
						|
	uint16_t cmd;
 | 
						|
	uint16_t data;
 | 
						|
};
 | 
						|
 | 
						|
/* Init script commands */
 | 
						|
enum GC9A01_cmd {
 | 
						|
	GC9A01_START,
 | 
						|
	GC9A01_END,
 | 
						|
	GC9A01_CMD,
 | 
						|
	GC9A01_DATA,
 | 
						|
	GC9A01_DELAY
 | 
						|
};
 | 
						|
 | 
						|
/**********************
 | 
						|
 *  STATIC PROTOTYPES
 | 
						|
 **********************/
 | 
						|
static void GC9A01_command(uint8_t cmd);
 | 
						|
static void GC9A01_data(uint8_t data);
 | 
						|
static void GC9A01_set_addr_win(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1);
 | 
						|
 | 
						|
/**********************
 | 
						|
 *  STATIC VARIABLES
 | 
						|
 **********************/
 | 
						|
// Documentation on op codes for GC9A01 are very hard to find.
 | 
						|
// Will document should they be found.
 | 
						|
static struct GC9A01_function GC9A01_cfg_script[] = {
 | 
						|
	{ GC9A01_START, GC9A01_START},
 | 
						|
	{ GC9A01_CMD, 0xEF},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xEB},
 | 
						|
	{ GC9A01_DATA, 0x14},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xFE}, // Inter Register Enable1
 | 
						|
	{ GC9A01_CMD, 0xEF}, // Inter Register Enable2
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xEB},
 | 
						|
	{ GC9A01_DATA, 0x14},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x84},
 | 
						|
	{ GC9A01_DATA, 0x40},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x85},
 | 
						|
	{ GC9A01_DATA, 0xFF},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x86},
 | 
						|
	{ GC9A01_DATA, 0xFF},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x87},
 | 
						|
	{ GC9A01_DATA, 0xFF},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x88},
 | 
						|
	{ GC9A01_DATA, 0x0A},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x89},
 | 
						|
	{ GC9A01_DATA, 0x21},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x8A},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x8B},
 | 
						|
	{ GC9A01_DATA, 0x80},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x8C},
 | 
						|
	{ GC9A01_DATA, 0x01},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x8D},
 | 
						|
	{ GC9A01_DATA, 0x01},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x8E},
 | 
						|
	{ GC9A01_DATA, 0xFF},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x8F},
 | 
						|
	{ GC9A01_DATA, 0xFF},
 | 
						|
 | 
						|
	{ GC9A01_CMD, GC9A01_DISFNCTRL}, // Display Function Control
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
 | 
						|
	{ GC9A01_CMD, GC9A01_MADCTL}, // Memory Access Control
 | 
						|
	{ GC9A01_DATA, 0x48}, // Set the display direction 0,1,2,3	four directions
 | 
						|
 | 
						|
	{ GC9A01_CMD, GC9A01_COLMOD}, // COLMOD: Pixel Format Set
 | 
						|
	{ GC9A01_DATA, 0x05}, // 16 Bits per pixel
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x90},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xBD},
 | 
						|
	{ GC9A01_DATA, 0x06},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xBC},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xFF},
 | 
						|
	{ GC9A01_DATA, 0x60},
 | 
						|
	{ GC9A01_DATA, 0x01},
 | 
						|
	{ GC9A01_DATA, 0x04},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xC3}, // Power Control 2
 | 
						|
	{ GC9A01_DATA, 0x13},
 | 
						|
	{ GC9A01_CMD, 0xC4}, // Power Control 3
 | 
						|
	{ GC9A01_DATA, 0x13},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xC9}, // Power Control 4
 | 
						|
	{ GC9A01_DATA, 0x22},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xBE},
 | 
						|
	{ GC9A01_DATA, 0x11},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xE1},
 | 
						|
	{ GC9A01_DATA, 0x10},
 | 
						|
	{ GC9A01_DATA, 0x0E},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xDF},
 | 
						|
	{ GC9A01_DATA, 0x21},
 | 
						|
	{ GC9A01_DATA, 0x0C},
 | 
						|
	{ GC9A01_DATA, 0x02},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xF0}, // SET_GAMMA1
 | 
						|
	{ GC9A01_DATA, 0x45},
 | 
						|
	{ GC9A01_DATA, 0x09},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x26},
 | 
						|
	{ GC9A01_DATA, 0x2A},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xF1}, // SET_GAMMA2
 | 
						|
	{ GC9A01_DATA, 0x43},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x72},
 | 
						|
	{ GC9A01_DATA, 0x36},
 | 
						|
	{ GC9A01_DATA, 0x37},
 | 
						|
	{ GC9A01_DATA, 0x6F},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xF2}, // SET_GAMMA3
 | 
						|
	{ GC9A01_DATA, 0x45},
 | 
						|
	{ GC9A01_DATA, 0x09},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x26},
 | 
						|
	{ GC9A01_DATA, 0x2A},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xF3}, // SET_GAMMA4
 | 
						|
	{ GC9A01_DATA, 0x43},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x72},
 | 
						|
	{ GC9A01_DATA, 0x36},
 | 
						|
	{ GC9A01_DATA, 0x37},
 | 
						|
	{ GC9A01_DATA, 0x6F},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xED},
 | 
						|
	{ GC9A01_DATA, 0x1B},
 | 
						|
	{ GC9A01_DATA, 0x0B},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xAE},
 | 
						|
	{ GC9A01_DATA, 0x77},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xCD},
 | 
						|
	{ GC9A01_DATA, 0x63},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x07},
 | 
						|
	{ GC9A01_DATA, 0x07},
 | 
						|
	{ GC9A01_DATA, 0x04},
 | 
						|
	{ GC9A01_DATA, 0x0E},
 | 
						|
	{ GC9A01_DATA, 0x0F},
 | 
						|
	{ GC9A01_DATA, 0x09},
 | 
						|
	{ GC9A01_DATA, 0x07},
 | 
						|
	{ GC9A01_DATA, 0x08},
 | 
						|
	{ GC9A01_DATA, 0x03},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0xE8},
 | 
						|
	{ GC9A01_DATA, 0x34},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x62},
 | 
						|
	{ GC9A01_DATA, 0x18},
 | 
						|
	{ GC9A01_DATA, 0x0D},
 | 
						|
	{ GC9A01_DATA, 0x71},
 | 
						|
	{ GC9A01_DATA, 0xED},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x18},
 | 
						|
	{ GC9A01_DATA, 0x0F},
 | 
						|
	{ GC9A01_DATA, 0x71},
 | 
						|
	{ GC9A01_DATA, 0xEF},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x63},
 | 
						|
	{ GC9A01_DATA, 0x18},
 | 
						|
	{ GC9A01_DATA, 0x11},
 | 
						|
	{ GC9A01_DATA, 0x71},
 | 
						|
	{ GC9A01_DATA, 0xF1},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x18},
 | 
						|
	{ GC9A01_DATA, 0x13},
 | 
						|
	{ GC9A01_DATA, 0x71},
 | 
						|
	{ GC9A01_DATA, 0xF3},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
	{ GC9A01_DATA, 0x70},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x64},
 | 
						|
	{ GC9A01_DATA, 0x28},
 | 
						|
	{ GC9A01_DATA, 0x29},
 | 
						|
	{ GC9A01_DATA, 0xF1},
 | 
						|
	{ GC9A01_DATA, 0x01},
 | 
						|
	{ GC9A01_DATA, 0xF1},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x07},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x66},
 | 
						|
	{ GC9A01_DATA, 0x3C},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0xCD},
 | 
						|
	{ GC9A01_DATA, 0x67},
 | 
						|
	{ GC9A01_DATA, 0x45},
 | 
						|
	{ GC9A01_DATA, 0x45},
 | 
						|
	{ GC9A01_DATA, 0x10},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x67},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x3C},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x01},
 | 
						|
	{ GC9A01_DATA, 0x54},
 | 
						|
	{ GC9A01_DATA, 0x10},
 | 
						|
	{ GC9A01_DATA, 0x32},
 | 
						|
	{ GC9A01_DATA, 0x98},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x74},
 | 
						|
	{ GC9A01_DATA, 0x10},
 | 
						|
	{ GC9A01_DATA, 0x85},
 | 
						|
	{ GC9A01_DATA, 0x80},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
	{ GC9A01_DATA, 0x4E},
 | 
						|
	{ GC9A01_DATA, 0x00},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x98},
 | 
						|
	{ GC9A01_DATA, 0x3E},
 | 
						|
	{ GC9A01_DATA, 0x07},
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x35}, // Tearing Effect Line ON
 | 
						|
	{ GC9A01_CMD, 0x21}, // Display Inversion ON
 | 
						|
 | 
						|
	{ GC9A01_CMD, 0x11}, // Sleep Out Mode
 | 
						|
	{ GC9A01_DELAY, 120},
 | 
						|
	{ GC9A01_CMD, GC9A01_DISPON}, // Display ON
 | 
						|
	{ GC9A01_DELAY, 255},
 | 
						|
	{ GC9A01_END, GC9A01_END},
 | 
						|
};
 | 
						|
 | 
						|
/**********************
 | 
						|
 *      MACROS
 | 
						|
 **********************/
 | 
						|
 | 
						|
/**********************
 | 
						|
 *   GLOBAL FUNCTIONS
 | 
						|
 **********************/
 | 
						|
 | 
						|
/**
 | 
						|
 * Write a command to the GC9A01
 | 
						|
 * @param cmd the command
 | 
						|
 */
 | 
						|
static void GC9A01_command(uint8_t cmd)
 | 
						|
{
 | 
						|
	LV_DRV_DISP_CMD_DATA(GC9A01_CMD_MODE);
 | 
						|
	LV_DRV_DISP_SPI_WR_BYTE(cmd);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Write data to the GC9A01
 | 
						|
 * @param data the data
 | 
						|
 */
 | 
						|
static void GC9A01_data(uint8_t data)
 | 
						|
{
 | 
						|
	LV_DRV_DISP_CMD_DATA(GC9A01_DATA_MODE);
 | 
						|
	LV_DRV_DISP_SPI_WR_BYTE(data);
 | 
						|
}
 | 
						|
 | 
						|
static int GC9A01_data_array(uint8_t *buf, uint32_t len)
 | 
						|
{
 | 
						|
	uint8_t *pt = buf;
 | 
						|
 | 
						|
	for (uint32_t lp = 0; lp < len; lp++, pt++)
 | 
						|
	{
 | 
						|
		LV_DRV_DISP_SPI_WR_BYTE(*pt);
 | 
						|
	}
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int GC9A01_databuf(uint32_t len, uint8_t *buf)
 | 
						|
{
 | 
						|
	uint32_t byte_left = len;
 | 
						|
	uint8_t *pt = buf;
 | 
						|
 | 
						|
	while (byte_left)
 | 
						|
	{
 | 
						|
		if (byte_left > 64)
 | 
						|
		{
 | 
						|
			LV_DRV_DISP_SPI_WR_ARRAY((char*)pt, 64);
 | 
						|
			byte_left = byte_left - 64;
 | 
						|
			pt = pt + 64;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			LV_DRV_DISP_SPI_WR_ARRAY((char*)pt, byte_left);
 | 
						|
			byte_left=0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
// hard reset of the tft controller
 | 
						|
// ----------------------------------------------------------
 | 
						|
static void GC9A01_hard_reset( void )
 | 
						|
{
 | 
						|
    LV_DRV_DISP_SPI_CS(0); // Low to listen to us
 | 
						|
 | 
						|
    LV_DRV_DISP_RST(1);
 | 
						|
    LV_DRV_DELAY_MS(50);
 | 
						|
    LV_DRV_DISP_RST(0);
 | 
						|
    LV_DRV_DELAY_MS(50);
 | 
						|
    LV_DRV_DISP_RST(1);
 | 
						|
    LV_DRV_DELAY_MS(50);
 | 
						|
}
 | 
						|
 | 
						|
// Configuration of the tft controller
 | 
						|
// ----------------------------------------------------------
 | 
						|
static void GC9A01_run_cfg_script(void)
 | 
						|
{
 | 
						|
	int i = 0;
 | 
						|
	int end_script = 0;
 | 
						|
 | 
						|
	do {
 | 
						|
		switch (GC9A01_cfg_script[i].cmd)
 | 
						|
		{
 | 
						|
			case GC9A01_START:
 | 
						|
				break;
 | 
						|
			case GC9A01_CMD:
 | 
						|
				GC9A01_command( GC9A01_cfg_script[i].data & 0xFF );
 | 
						|
				break;
 | 
						|
			case GC9A01_DATA:
 | 
						|
				GC9A01_data( GC9A01_cfg_script[i].data & 0xFF );
 | 
						|
				break;
 | 
						|
			case GC9A01_DELAY:
 | 
						|
        LV_DRV_DELAY_MS(GC9A01_cfg_script[i].data);
 | 
						|
				break;
 | 
						|
			case GC9A01_END:
 | 
						|
				end_script = 1;
 | 
						|
		}
 | 
						|
		i++;
 | 
						|
	} while (!end_script);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
 | 
						|
  // Rudimentary clipping
 | 
						|
  if((x >= GC9A01_HOR_RES) || (y >= GC9A01_VER_RES)) return;
 | 
						|
  if((y+h-1) >= GC9A01_VER_RES) h = GC9A01_VER_RES - y;
 | 
						|
 | 
						|
	LV_DRV_DISP_SPI_CS(0); // Listen to us
 | 
						|
 | 
						|
  GC9A01_set_addr_win(x, y, x, y + h - 1);
 | 
						|
 | 
						|
  uint8_t hi = color >> 8, lo = color;
 | 
						|
 | 
						|
  while (h--) {
 | 
						|
    GC9A01_data(hi);
 | 
						|
    GC9A01_data(lo);
 | 
						|
  }
 | 
						|
 | 
						|
	LV_DRV_DISP_SPI_CS(1);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
 | 
						|
  // Rudimentary clipping
 | 
						|
  if((x >= GC9A01_HOR_RES) || (y >= GC9A01_VER_RES)) return;
 | 
						|
  if((x+w-1) >= GC9A01_HOR_RES)  w = GC9A01_HOR_RES - x;
 | 
						|
 | 
						|
	LV_DRV_DISP_SPI_CS(0); // Listen to us
 | 
						|
 | 
						|
  GC9A01_set_addr_win(x, y, x + w - 1, y);
 | 
						|
 | 
						|
  uint8_t hi = color >> 8, lo = color;
 | 
						|
 | 
						|
  while (w--) {
 | 
						|
    GC9A01_data(hi);
 | 
						|
    GC9A01_data(lo);
 | 
						|
  }
 | 
						|
 | 
						|
	LV_DRV_DISP_SPI_CS(1);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Pass 8-bit (each) R,G,B, get back 16-bit packed color
 | 
						|
uint16_t GC9A01_Color565(uint8_t r, uint8_t g, uint8_t b) {
 | 
						|
  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_invertDisplay(bool i)
 | 
						|
{
 | 
						|
  GC9A01_command(i ? GC9A01_INVON : GC9A01_INVOFF);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_drawPixel(int16_t x, int16_t y, uint16_t color)
 | 
						|
{
 | 
						|
  if((x < 0) ||(x >= GC9A01_HOR_RES) || (y < 0) || (y >= GC9A01_VER_RES)) return;
 | 
						|
 | 
						|
	LV_DRV_DISP_SPI_CS(0); // Listen to us
 | 
						|
  GC9A01_set_addr_win(x, y, x, y);
 | 
						|
 | 
						|
  uint8_t hi = color >> 8, lo = color;
 | 
						|
 | 
						|
	GC9A01_data(hi);
 | 
						|
	GC9A01_data(lo);
 | 
						|
 | 
						|
	LV_DRV_DISP_SPI_CS(1);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_fillScreen(uint16_t color) {
 | 
						|
	GC9A01_fillRect(0, 0,  GC9A01_HOR_RES, GC9A01_VER_RES, color);
 | 
						|
}
 | 
						|
 | 
						|
// fill a rectangle
 | 
						|
void GC9A01_fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
 | 
						|
  // rudimentary clipping (drawChar w/big text requires this)
 | 
						|
  if((x >= GC9A01_HOR_RES) || (y >= GC9A01_VER_RES)) return;
 | 
						|
  if((x + w - 1) >= GC9A01_HOR_RES)  w = GC9A01_HOR_RES  - x;
 | 
						|
  if((y + h - 1) >= GC9A01_VER_RES) h = GC9A01_VER_RES - y;
 | 
						|
 | 
						|
  LV_DRV_DISP_SPI_CS(0);  // Listen to us
 | 
						|
 | 
						|
  GC9A01_set_addr_win(x, y, x + w - 1, y + h - 1);
 | 
						|
 | 
						|
	uint8_t hi = color >> 8, lo = color;
 | 
						|
 | 
						|
  for (y = h; y > 0; y--)
 | 
						|
  {
 | 
						|
    for (x = w; x > 0; x--)
 | 
						|
    {
 | 
						|
      GC9A01_data(hi);
 | 
						|
      GC9A01_data(lo);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  LV_DRV_DISP_SPI_CS(1);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_setRotation(uint8_t m) {
 | 
						|
 | 
						|
  GC9A01_command(GC9A01_MADCTL);
 | 
						|
  m %= 4; // can't be higher than 3
 | 
						|
  switch (m) {
 | 
						|
   case 0:
 | 
						|
     GC9A01_data(GC9A01_MADCTL_MX | GC9A01_MADCTL_MY | GC9A01_MADCTL_RGB);
 | 
						|
 | 
						|
    //  _xstart = _colstart;
 | 
						|
    //  _ystart = _rowstart;
 | 
						|
     break;
 | 
						|
   case 1:
 | 
						|
     GC9A01_data(GC9A01_MADCTL_MY | GC9A01_MADCTL_MV | GC9A01_MADCTL_RGB);
 | 
						|
 | 
						|
    //  _ystart = _colstart;
 | 
						|
    //  _xstart = _rowstart;
 | 
						|
     break;
 | 
						|
  case 2:
 | 
						|
     GC9A01_data(GC9A01_MADCTL_RGB);
 | 
						|
 | 
						|
    //  _xstart = _colstart;
 | 
						|
    //  _ystart = _rowstart;
 | 
						|
     break;
 | 
						|
 | 
						|
   case 3:
 | 
						|
     GC9A01_data(GC9A01_MADCTL_MX | GC9A01_MADCTL_MV | GC9A01_MADCTL_RGB);
 | 
						|
 | 
						|
    //  _ystart = _colstart;
 | 
						|
    //  _xstart = _rowstart;
 | 
						|
     break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Initialize the GC9A01
 | 
						|
 */
 | 
						|
int GC9A01_init(void)
 | 
						|
{
 | 
						|
	GC9A01_hard_reset();
 | 
						|
	GC9A01_run_cfg_script();
 | 
						|
 | 
						|
	// GC9A01_fillScreen(0x0000); // Black
 | 
						|
	// GC9A01_fillScreen(0xFFFF); // White
 | 
						|
	GC9A01_fillScreen(0xAAAA); // ?
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static void GC9A01_set_addr_win(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)
 | 
						|
{
 | 
						|
  uint16_t x_start = x0 + GC9A01_XSTART, x_end = x1 + GC9A01_XSTART;
 | 
						|
  uint16_t y_start = y0 + GC9A01_YSTART, y_end = y1 + GC9A01_YSTART;
 | 
						|
 | 
						|
  GC9A01_command(GC9A01_CASET); // Column addr set
 | 
						|
  GC9A01_data(x_start >> 8);
 | 
						|
  GC9A01_data(x_start & 0xFF);     // XSTART
 | 
						|
  GC9A01_data(x_end >> 8);
 | 
						|
  GC9A01_data(x_end & 0xFF);     // XEND
 | 
						|
 | 
						|
  GC9A01_command(GC9A01_RASET); // Row addr set
 | 
						|
  GC9A01_data(y_start >> 8);
 | 
						|
  GC9A01_data(y_start & 0xFF);     // YSTART
 | 
						|
  GC9A01_data(y_end >> 8);
 | 
						|
  GC9A01_data(y_end & 0xFF);     // YEND
 | 
						|
 | 
						|
  GC9A01_command(GC9A01_RAMWR);
 | 
						|
}
 | 
						|
 | 
						|
void GC9A01_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t *color_p)
 | 
						|
{
 | 
						|
  LV_DRV_DISP_SPI_CS(0); // Listen to us
 | 
						|
 | 
						|
  GC9A01_set_addr_win(area->x1, area->y1, area->x2, area->y2);
 | 
						|
  int32_t len = (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2;
 | 
						|
 | 
						|
  LV_DRV_DISP_CMD_DATA(GC9A01_DATA_MODE);
 | 
						|
  LV_DRV_DISP_SPI_WR_ARRAY((char*)color_p, len);
 | 
						|
 | 
						|
  LV_DRV_DISP_SPI_CS(1);
 | 
						|
  lv_disp_flush_ready(disp_drv);         /* Indicate you are ready with the flushing*/
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 |