aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJoel Bodenmann <joel@embedded.pro>2017-02-02 17:07:59 +0100
committerJoel Bodenmann <joel@embedded.pro>2017-02-02 17:07:59 +0100
commit50c89877c36b5f588d33f1098c2ea000a88e8407 (patch)
tree0e6db372e1fe686fc0d63bfdf0cb917f766e1718 /drivers
parentf57f6be212c779635a6ab9b80dcec3d1778ce8ba (diff)
downloaduGFX-50c89877c36b5f588d33f1098c2ea000a88e8407.tar.gz
uGFX-50c89877c36b5f588d33f1098c2ea000a88e8407.tar.bz2
uGFX-50c89877c36b5f588d33f1098c2ea000a88e8407.zip
Adding UC8173 driver
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gdisp/UC8173/UC8173.h224
-rw-r--r--drivers/gdisp/UC8173/board_UC8173_template.h56
-rw-r--r--drivers/gdisp/UC8173/driver.mk2
-rw-r--r--drivers/gdisp/UC8173/gdisp_lld_UC8173.c419
-rw-r--r--drivers/gdisp/UC8173/gdisp_lld_config.h29
5 files changed, 730 insertions, 0 deletions
diff --git a/drivers/gdisp/UC8173/UC8173.h b/drivers/gdisp/UC8173/UC8173.h
new file mode 100644
index 00000000..04063d5d
--- /dev/null
+++ b/drivers/gdisp/UC8173/UC8173.h
@@ -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
diff --git a/drivers/gdisp/UC8173/board_UC8173_template.h b/drivers/gdisp/UC8173/board_UC8173_template.h
new file mode 100644
index 00000000..f16205f4
--- /dev/null
+++ b/drivers/gdisp/UC8173/board_UC8173_template.h
@@ -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 */
diff --git a/drivers/gdisp/UC8173/driver.mk b/drivers/gdisp/UC8173/driver.mk
new file mode 100644
index 00000000..eebcd0b9
--- /dev/null
+++ b/drivers/gdisp/UC8173/driver.mk
@@ -0,0 +1,2 @@
+GFXINC += $(GFXLIB)/drivers/gdisp/UC8173
+GFXSRC += $(GFXLIB)/drivers/gdisp/UC8173/gdisp_lld_UC8173.c
diff --git a/drivers/gdisp/UC8173/gdisp_lld_UC8173.c b/drivers/gdisp/UC8173/gdisp_lld_UC8173.c
new file mode 100644
index 00000000..75a4a237
--- /dev/null
+++ b/drivers/gdisp/UC8173/gdisp_lld_UC8173.c
@@ -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
diff --git a/drivers/gdisp/UC8173/gdisp_lld_config.h b/drivers/gdisp/UC8173/gdisp_lld_config.h
new file mode 100644
index 00000000..e10928eb
--- /dev/null
+++ b/drivers/gdisp/UC8173/gdisp_lld_config.h
@@ -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 */