Adding UC8173 driver

This commit is contained in:
Joel Bodenmann 2017-02-02 17:07:59 +01:00
parent f57f6be212
commit 50c89877c3
7 changed files with 852 additions and 0 deletions

View File

@ -0,0 +1,121 @@
#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H
#include "nrf_gpio.h"
#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#define PIN_CS 29
#define PIN_SCK 3
#define PIN_MOSI 4
#define PIN_DC 12
#define PIN_RESET 11
#define PIN_BUSY 27
#define SPI_INSTANCE 0
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);
static GFXINLINE bool_t init_board(GDisplay* g)
{
nrf_drv_spi_config_t spi_config;
ret_code_t err = NRF_SUCCESS;
(void)g;
// Initialize RESET pin
nrf_gpio_cfg_output(PIN_RESET);
// Initialize RESET pin
nrf_gpio_cfg_output(PIN_DC);
// Initialize BUSY pin
nrf_gpio_cfg_input(PIN_BUSY, NRF_GPIO_PIN_NOPULL);
// Initialize RESET pin
nrf_gpio_cfg_output(PIN_CS);
// Initialize SPI
spi_config.sck_pin = PIN_SCK;
spi_config.mosi_pin = PIN_MOSI;
spi_config.miso_pin = NRF_DRV_SPI_PIN_NOT_USED;
spi_config.ss_pin = NRF_DRV_SPI_PIN_NOT_USED; // We have to control the CS line ourself for burst writes > 255 bytes
spi_config.irq_priority = APP_IRQ_PRIORITY_LOW;
spi_config.orc = 0xFF;
spi_config.frequency = NRF_DRV_SPI_FREQ_4M;
spi_config.mode = NRF_DRV_SPI_MODE_0;
spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST;
err = nrf_drv_spi_init(&spi, &spi_config, 0);
if (err != NRF_SUCCESS) {
return FALSE;
}
return TRUE;
}
static GFXINLINE void post_init_board(GDisplay* g)
{
(void)g;
}
static GFXINLINE void setpin_reset(GDisplay* g, bool_t state)
{
(void)g;
if (state) {
nrf_gpio_pin_set(PIN_RESET);
} else {
nrf_gpio_pin_clear(PIN_RESET);
}
}
static GFXINLINE bool_t getpin_busy(GDisplay* g)
{
(void)g;
if (nrf_gpio_pin_read(PIN_BUSY) == 1) {
return TRUE;
} else {
return FALSE;
}
}
static GFXINLINE void acquire_bus(GDisplay* g)
{
(void)g;
nrf_gpio_pin_clear(PIN_CS);
}
static GFXINLINE void release_bus(GDisplay* g)
{
(void)g;
nrf_gpio_pin_set(PIN_CS);
}
static GFXINLINE void write_cmd(GDisplay* g, uint8_t cmd)
{
(void)g;
nrf_gpio_pin_clear(PIN_DC);
nrf_drv_spi_transfer(&spi, &cmd, 1, 0, 0);
}
static GFXINLINE void write_data(GDisplay* g, uint8_t data)
{
(void)g;
nrf_gpio_pin_set(PIN_DC);
nrf_drv_spi_transfer(&spi, &data, 1, 0, 0);
}
static GFXINLINE void write_data_burst(GDisplay* g, uint8_t* data, uint8_t length)
{
(void)g;
nrf_gpio_pin_set(PIN_DC);
nrf_drv_spi_transfer(&spi, data, length, 0, 0);
}
#endif /* _GDISP_LLD_BOARD_H */

View File

@ -17,6 +17,7 @@ FEATURE: Added GDISP_IMAGE_GIF_BLIT_BUFFER_SIZE configuration option
FIX: Fixed extra dots when drawing anti-aliased fonts with wordwrap FIX: Fixed extra dots when drawing anti-aliased fonts with wordwrap
FEATURE: Increase non-UTF8 font support to 0 to 255 rather than just the true ascii set FEATURE: Increase non-UTF8 font support to 0 to 255 rather than just the true ascii set
FEATURE: Added Fb24bpp driver for RGB888 and BGR888 packed framebuffer displays FEATURE: Added Fb24bpp driver for RGB888 and BGR888 packed framebuffer displays
FEATURE: Added UC8173 driver
*** Release 2.7 *** *** Release 2.7 ***

View File

@ -0,0 +1,224 @@
#ifndef _UC8173_H
#define _UC8173_H
#include "gfx.h"
#define DATA_MASK 0x0100
#define DCX_CMD 0x0000
#define DCX_DATA 0x0001
#define MASTER 0x00
#define SLAVE 0x01
#define MAS_SLA 0x02
#define BLACK 0x00
#define WHITE 0x01
#define RED 0x02
#define PSR 0x0000
#define PWR 0x0001
#define POF 0x0002
#define PFS 0x0003
#define PON 0x0004
#define PMES 0x0005
#define BTST 0x0006
#define DSLP 0x0007
#define SLP 0x0008
#define DTM1 0x0010
#define DRF 0x0012
#define DTM2 0x0013
#define DTMW 0x0014
#define DTM3 0x0015
#define DTM4 0x0016
#define LUT_KWVCOM 0x0020
#define LUT_RVCOM 0x0021
#define LUT_KW 0x0022
#define LUT_RR 0x0023
#define LUT_RK 0x0024
#define LUT_RW 0x0025
#define LUT_FT 0x0026
#define LPRD 0x0030
#define TSC 0x0040
#define TSE 0x0041
#define TSW 0x0042
#define TSR 0x0043
#define PBC 0x0044
#define CDI 0x0050
#define LPD 0x0051
#define TRES 0x0061
#define GDS 0x0062
#define GBS 0x0063
#define GSS 0x0064
#define REV 0x0070
#define FLG 0x0071
#define AMV 0x0080
#define VV 0x0081
#define VDCS 0x0082
#define EDS 0x0083
#define VBDS 0x0084
#define PGM 0x00A0
#define APG 0x00A1
#define ROTP 0x00A2
#define CCSET 0x00E0
#define PWS 0x00E3
#define LVSEL 0x00E4
#define TSSET 0x00E5
#define DF 0x00DF
#define Initial_23_16 0x00
#define Initial_15_0 0x0000 // 1K
#define Temperature 0x001000
#define Temperature0_23_16 0x00
#define Temperature0_15_0 0x0400 // 1K
#define Temperature1_23_16 0x00
#define Temperature1_15_0 0x0800
#define Temperature2_23_16 0x00
#define Temperature2_15_0 0x0C00
#define Temperature3_23_16 0x00
#define Temperature3_15_0 0x1000
#define Temperature4_23_16 0x00
#define Temperature4_15_0 0x1400
#define Temperature5_23_16 0x00
#define Temperature5_15_0 0x1800
#define Temperature6_23_16 0x00
#define Temperature6_15_0 0x1C00
#define Temperature7_23_16 0x00
#define Temperature7_15_0 0x2000
#define Temperature8_23_16 0x00
#define Temperature8_15_0 0x2400
#define Temperature9_23_16 0x00
#define Temperature9_15_0 0x2800
#define Temperature10_23_16 0x00
#define Temperature10_15_0 0x2C00
#define Image_Start 0x003000
#define Initial_Counter 64
#define Temperature_LUT_Counter 672
static uint8_t _lut_none[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t _lut_temperature[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x29, 0xa9, 0xa9, 0xa8,
0x29, 0xa9, 0xa9, 0xa8, 0x29, 0xa9,
0xa9, 0xa8, 0x29, 0xa9, 0xa9, 0xa8,
0x29, 0xa9, 0xa9, 0xa8, 0x29, 0xa9,
0xa9, 0xa8, 0x29, 0xa9, 0xa9, 0xa0,
0x29, 0xa9, 0x29, 0xa0, 0x28, 0xa9,
0x21, 0x80, 0x28, 0xa9, 0x05, 0x80,
0x28, 0xa1, 0x05, 0x04, 0x28, 0x80,
0x05, 0x14, 0x08, 0x00, 0x15, 0x54,
0x00, 0x04, 0x04, 0x54, 0x02, 0x54,
0x14, 0x54, 0x02, 0x56, 0x14, 0x54,
0x06, 0x56, 0x56, 0x54, 0x06, 0x56,
0x56, 0x54, 0x16, 0x56, 0x56, 0x54,
0x16, 0x56, 0x56, 0x54, 0x16, 0x56,
0x52, 0x50, 0x16, 0x56, 0x52, 0x50,
0x16, 0x56, 0x52, 0x50, 0x16, 0x52,
0x52, 0x50, 0x16, 0x52, 0x52, 0x50,
0x12, 0x52, 0x52, 0x40, 0x12, 0x52,
0x52, 0x40, 0x1a, 0x4a, 0x4a, 0x48,
0x2a, 0x6a, 0x6a, 0x68, 0x2a, 0x6a,
0x6a, 0x68, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x50, 0x55,
0x5a, 0x55, 0x5a, 0x5a, 0x00, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#endif // _UC8173_H

View File

@ -0,0 +1,56 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GDISP_LLD_BOARD_H
#define _GDISP_LLD_BOARD_H
static GFXINLINE void init_board(GDisplay* g)
{
(void) g;
}
static GFXINLINE void post_init_board(GDisplay* g)
{
(void) g;
}
static GFXINLINE void setpin_reset(GDisplay* g, bool_t state)
{
(void) g;
(void) state;
}
static GFXINLINE void acquire_bus(GDisplay* g)
{
(void) g;
}
static GFXINLINE void release_bus(GDisplay* g)
{
(void) g;
}
static GFXINLINE void write_cmd(GDisplay* g, uint8_t cmd)
{
(void) g;
(void) cmd;
}
static GFXINLINE void write_data(GDisplay* g, uint8_t data)
{
(void) g;
(void) data;
}
static GFXINLINE void write_data_burst(GDisplay* g, uint8_t* data, uint16_t length)
{
(void) g;
(void) data;
(void) length;
}
#endif /* _GDISP_LLD_BOARD_H */

View File

@ -0,0 +1,2 @@
GFXINC += $(GFXLIB)/drivers/gdisp/UC8173
GFXSRC += $(GFXLIB)/drivers/gdisp/UC8173/gdisp_lld_UC8173.c

View File

@ -0,0 +1,419 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#include "gfx.h"
#if GFX_USE_GDISP
#define GDISP_DRIVER_VMT GDISPVMT_UC8173
#include "gdisp_lld_config.h"
#include "../../../src/gdisp/gdisp_driver.h"
#include "UC8173.h"
#include "board_UC8173.h"
#if defined(GDISP_SCREEN_WIDTH)
#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
#define GDISP_SCREEN_WIDTH 240
#endif
#if defined(GDISP_SCREEN_HEIGHT)
#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
#define GDISP_SCREEN_HEIGHT 240
#endif
#ifndef GDISP_SCREEN_HEIGHT
#define GDISP_SCREEN_HEIGHT 240
#endif
#ifndef GDISP_SCREEN_WIDTH
#define GDISP_SCREEN_WIDTH 240
#endif
#define PRIV(g) ((UC8173_Private*)((g)->priv))
#define FRAMEBUFFER(g) (PRIV(g)->framebuffer)
#define GDISP_FLG_NEEDFLUSH (GDISP_FLG_DRIVER << 0)
#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_MONO
#define LINE_BYTES (GDISP_SCREEN_WIDTH/8)
#define WRITEBUFCMD DTM4
#define xyaddr(x, y) (((x)>>3) + ((y) * LINE_BYTES))
//#define xybit(x, c) ((c) << ((x) & 7)) // This one has the wrong order of the pixels inside the byte
#define xybit(x, c) ((c) << (7-((x) & 7)))
#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_GRAY4
#define LINE_BYTES (GDISP_SCREEN_WIDTH/4)
#define WRITEBUFCMD DTM2 // NOT SURE THIS IS RIGHT - MAY NEED TO USE DTM0 and then send a refresh???
#define xyaddr(x, y) (((x)>>2) + ((y) * LINE_BYTES))
//#define xybit(x, c) ((c) << (((x) & 3)<<1)) // This one has the wrong order of the pixels inside the byte
#define xybit(x, c) ((c) << (6-((x) & 3)<<1))
#else
#error "UC8173: Unsupported driver color format"
#endif
typedef struct UC8173_Private {
coord_t flushWindowX;
coord_t flushWindowY;
coord_t flushWindowWidth;
coord_t flushWindowHeight;
uint8_t* framebuffer;
} UC8173_Private;
// This function rounds a given integer up to a specified multiple. Note, multiple must be a power of 2!
static GFXINLINE void _roundUp(coord_t* numToRound, uint8_t multiple)
{
*numToRound = (*numToRound + multiple - 1) & ~(multiple - 1);
}
static GFXINLINE void _wait_for_busy_high(GDisplay* g)
{
while (!getpin_busy(g));
}
static GFXINLINE void _wait_for_busy_low(GDisplay* g)
{
while (getpin_busy(g));
}
static void _load_lut(GDisplay* g, uint32_t LUT, uint8_t* LUT_Value)
{
int i,counter;
int MODE = 2;
if(MODE == 0)
counter = 512; //512
else
counter = 42;
if(LUT == 0x26)
counter = 128;
write_cmd(g, LUT);
for(i = 0; i < counter; i++) {
write_data(g, *LUT_Value);
LUT_Value++;
}
}
void _load_lut2(GDisplay* g, uint32_t LUT, uint8_t* LUT_Value, uint32_t LUT_Counter)
{
uint32_t i;
write_cmd(g, LUT);
for (i = 0; i < LUT_Counter; i++) {
write_data(g, *LUT_Value);
LUT_Value++;
}
}
static void _upload_Temperature_LUT(GDisplay* g)
{
_load_lut2(g, LUT_KWVCOM, &_lut_temperature[0], 32);
_load_lut2(g, LUT_KW, &_lut_temperature[32], 512);
_load_lut2(g, LUT_FT, &_lut_temperature[544], 128);
}
static void _clear_lut(GDisplay* g)
{
write_cmd(g, PON);
_wait_for_busy_high(g);
_load_lut(g, LUT_KW, _lut_none);
_load_lut(g, LUT_KWVCOM, _lut_none);
write_cmd(g, POF);
_wait_for_busy_low(g);
}
static void _invertFramebuffer(GDisplay* g)
{
uint32_t i;
for (i = 0; i < LINE_BYTES*GDISP_SCREEN_HEIGHT; i++) {
FRAMEBUFFER(g)[i] = ~(FRAMEBUFFER(g)[i]);
}
// We should flush these changes to the display controller framebuffer at some point
g->flags |= GDISP_FLG_NEEDFLUSH;
}
LLDSPEC bool_t gdisp_lld_init(GDisplay* g)
{
// Allocate the private area plus the framebuffer
g->priv = gfxAlloc(sizeof(UC8173_Private) + LINE_BYTES*GDISP_SCREEN_HEIGHT);
if (!g->priv) {
return FALSE;
}
// Initialize the private area
PRIV(g)->flushWindowX = 0;
PRIV(g)->flushWindowY = 0;
PRIV(g)->flushWindowWidth = GDISP_SCREEN_WIDTH;
PRIV(g)->flushWindowHeight = GDISP_SCREEN_HEIGHT;
PRIV(g)->framebuffer = (uint8_t*)(PRIV(g) + offsetof(UC8173_Private, framebuffer));
// Initialise the board interface
if (!init_board(g)) {
return FALSE;
}
// Hardware reset
setpin_reset(g, FALSE);
gfxSleepMilliseconds(100);
setpin_reset(g, TRUE);
gfxSleepMilliseconds(1000);
// Acquire the bus
acquire_bus(g);
// Booster soft-start
write_cmd(g, BTST);
write_data(g, 0x17); //0x17
write_data(g, 0x97); //0x97
write_data(g, 0x20); //0x20
// Power settings
write_cmd(g, PWR);
write_data(g, 0x03);
write_data(g, 0x00);
write_data(g, 0x2B); //1C 2B
write_data(g, 0x2B); //1C 2B
write_data(g, 0x00);
// Power-on
write_cmd(g, PON);
_wait_for_busy_high(g);
// Panel setting register
write_cmd(g, PSR);
write_data(g, 0x0F); //0x0B
write_data(g, 0x86); //0x86
// Power-off sequence
write_cmd(g, PFS);
write_data(g, 0x00);
// PLL control
write_cmd(g, LPRD);
write_data(g, 0x25);
// Internal temperature sensor enable
write_cmd(g, TSE);
write_data(g, 0x00); // Use internal temperature sensor
// VCOM and data interval settings
write_cmd(g, CDI);
write_data(g, 0xE1);
write_data(g, 0x20);
write_data(g, 0x10);
// Set display panel resolution
write_cmd(g, TRES);
write_data(g, 0xEF);
write_data(g, 0x00);
write_data(g, 0xEF);
// Undocumented register, taken from sample code
write_cmd(g, GDS);
write_data(g, 0xA9);
write_data(g, 0xA9);
write_data(g, 0xEB);
write_data(g, 0xEB);
write_data(g, 0x02);
// Auto measure VCOM
write_cmd(g, AMV);
write_data(g, 0x11); // 5 seconds, enabled
_wait_for_busy_high(g);
// Get current VCOM value
// write_cmd(g, VV);
// unsigned char vcom_temp = spi_9b_get();
// vcom_temp = vcom_temp + 4;
// Auto_VCOM = vcom_temp;
// VCM_DC setting
write_cmd(g, VDCS);
write_data(g, 0x12); // Write vcom_temp here
// Undocumented register, taken from sample code
write_cmd(g, VBDS);
write_data(g, 0x22);
// Undocumented register, taken from sample code
write_cmd(g, LVSEL);
write_data(g, 0x02);
// Undocumented register, taken from sample code
write_cmd(g, GBS);
write_data(g, 0x02);
write_data(g, 0x02);
// Undocumented register, taken from sample code
write_cmd(g, GSS);
write_data(g, 0x02);
write_data(g, 0x02);
// Undocumented register, taken from sample code
write_cmd(g, DF); // For REGAL (???)
write_data(g, 0x1F);
// Clear the look-up table
_clear_lut(g);
// Finish Init
post_init_board(g);
// Release the bus
release_bus(g);
// 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 = 0;
g->g.Contrast = 0;
return TRUE;
}
#if GDISP_HARDWARE_FLUSH
LLDSPEC void gdisp_lld_flush(GDisplay* g)
{
coord_t y;
// Don't flush unless we really need to
if (!(g->flags & GDISP_FLG_NEEDFLUSH)) {
return;
}
// Round the flushing window width and height up to the next multiple of four
_roundUp(&(PRIV(g)->flushWindowWidth), 4);
_roundUp(&(PRIV(g)->flushWindowWidth), 4);
// Acquire the bus to communicate with the display controller
acquire_bus(g);
// Upload the new temperature LUT
_upload_Temperature_LUT(g);
// Setup the window
write_cmd(g, DTMW);
write_data(g, (uint8_t)((PRIV(g)->flushWindowX >> 0) & 0xFF));
write_data(g, (uint8_t)((PRIV(g)->flushWindowY >> 8) & 0x03));
write_data(g, (uint8_t)((PRIV(g)->flushWindowY >> 0) & 0xFF));
write_data(g, (uint8_t)((((PRIV(g)->flushWindowWidth)-1) >> 0) & 0xFF));
write_data(g, (uint8_t)((((PRIV(g)->flushWindowHeight)-1) >> 8) & 0x03));
write_data(g, (uint8_t)((((PRIV(g)->flushWindowHeight)-1) >> 0) & 0xFF));
// Dump our framebuffer
// Note: The display controller doesn't allow changing the vertical scanning direction
// so we have to manually send the lines "the other way around" here.
write_cmd(g, WRITEBUFCMD);
for (y = GDISP_SCREEN_HEIGHT-1; y >= 0; y--) {
write_data_burst(g, FRAMEBUFFER(g)+y*LINE_BYTES, LINE_BYTES);
}
// Power-up the DC/DC converter to update the display panel
write_cmd(g, PON);
_wait_for_busy_high(g);
// Refresh the panel contents
write_cmd(g, DRF);
write_data(g, 0x08); // Enable REGAL function
write_data(g, 0x00);
write_data(g, 0x00);
write_data(g, 0x00);
write_data(g, 0xEF);
write_data(g, 0x00);
write_data(g, 0xEF);
_wait_for_busy_high(g);
// Power-down the DC/DC converter to make all the low-power pussys happy
write_cmd(g, POF);
_wait_for_busy_low(g);
// Release the bus again
release_bus(g);
// Clear the 'need-flushing' flag
g->flags &=~ GDISP_FLG_NEEDFLUSH;
}
#endif
#if GDISP_HARDWARE_DRAWPIXEL
LLDSPEC void gdisp_lld_draw_pixel(GDisplay* g)
{
coord_t x, y;
LLDCOLOR_TYPE *p;
// Handle the different possible orientations
switch(g->g.Orientation) {
default:
case GDISP_ROTATE_0:
x = g->p.x;
y = g->p.y;
break;
case GDISP_ROTATE_90:
x = g->p.y;
y = GDISP_SCREEN_HEIGHT-1 - g->p.x;
break;
case GDISP_ROTATE_180:
x = GDISP_SCREEN_WIDTH-1 - g->p.x;
y = GDISP_SCREEN_HEIGHT-1 - g->p.y;
break;
case GDISP_ROTATE_270:
x = GDISP_SCREEN_WIDTH-1 - g->p.y;
y = g->p.x;
break;
}
// Modify the framebuffer content
p = &FRAMEBUFFER(g)[xyaddr(x,y)];
*p &=~ xybit(x, LLDCOLOR_MASK());
*p |= xybit(x, gdispColor2Native(g->p.color));
//#warning ToDo
// There appears to be an issue in the silicone, still talking to the manufacturer about this one. Update will follow!
#if 0
// Update the flush window region
if (g->flags & GDISP_FLG_NEEDFLUSH) {
if (x < PRIV(g)->flushWindowX)
PRIV(g)->flushWindowX = x;
if (y < PRIV(g)->flushWindowY)
PRIV(g)->flushWindowY = y;
if (x > PRIV(g)->flushWindowX + PRIV(g)->flushWindowWidth)
PRIV(g)->flushWindowWidth =
} else {
PRIV(g)->flushWindowX = x;
PRIV(g)->flushWindowY = y;
PRIV(g)->flushWindowWidth = 1;
PRIV(g)->flushWindowHeight = 1;
}
#else
PRIV(g)->flushWindowX = 0;
PRIV(g)->flushWindowY = 0;
PRIV(g)->flushWindowWidth = GDISP_SCREEN_WIDTH;
PRIV(g)->flushWindowHeight = GDISP_SCREEN_HEIGHT;
#endif
// We should flush these changes to the display controller framebuffer at some point
g->flags |= GDISP_FLG_NEEDFLUSH;
}
#endif
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
LLDSPEC void gdisp_lld_control(GDisplay* g) {
switch(g->p.x) {
case GDISP_CONTROL_INVERT:
_invertFramebuffer(g);
break;
default:
break;
}
}
#endif
#endif // GFX_USE_GDISP

View File

@ -0,0 +1,29 @@
/*
* This file is subject to the terms of the GFX License. If a copy of
* the license was not distributed with this file, you can obtain one at:
*
* http://ugfx.org/license.html
*/
#ifndef _GDISP_LLD_CONFIG_H
#define _GDISP_LLD_CONFIG_H
#if GFX_USE_GDISP
/*===========================================================================*/
/* Driver hardware support. */
/*===========================================================================*/
#define GDISP_HARDWARE_FLUSH TRUE
#define GDISP_HARDWARE_DRAWPIXEL TRUE
#define GDISP_HARDWARE_PIXELREAD FALSE
#define GDISP_HARDWARE_CONTROL TRUE
#define GDISP_HARDWARE_FILLS FALSE
#define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_MONO
#define GDISP_CONTROL_INVERT (GDISP_CONTROL_LLD+0)
#endif /* GFX_USE_GDISP */
#endif /* _GDISP_LLD_CONFIG_H */