From f1d75f32becd3583c1eab3baf32b0448b7100156 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 7 Apr 2015 23:23:01 +1000
Subject: SSD1331 OLED display controller driver - accelerated including scroll
 support.

---
 drivers/gdisp/SSD1331/SSD1331.h                |  89 +++++++
 drivers/gdisp/SSD1331/board_SSD1331_template.h |  42 ++++
 drivers/gdisp/SSD1331/driver.mk                |   2 +
 drivers/gdisp/SSD1331/gdisp_lld_SSD1331.c      | 329 +++++++++++++++++++++++++
 drivers/gdisp/SSD1331/gdisp_lld_config.h       |  31 +++
 5 files changed, 493 insertions(+)
 create mode 100644 drivers/gdisp/SSD1331/SSD1331.h
 create mode 100644 drivers/gdisp/SSD1331/board_SSD1331_template.h
 create mode 100644 drivers/gdisp/SSD1331/driver.mk
 create mode 100644 drivers/gdisp/SSD1331/gdisp_lld_SSD1331.c
 create mode 100644 drivers/gdisp/SSD1331/gdisp_lld_config.h

(limited to 'drivers/gdisp/SSD1331')

diff --git a/drivers/gdisp/SSD1331/SSD1331.h b/drivers/gdisp/SSD1331/SSD1331.h
new file mode 100644
index 00000000..a30dcdcf
--- /dev/null
+++ b/drivers/gdisp/SSD1331/SSD1331.h
@@ -0,0 +1,89 @@
+#ifndef SSD1331_H
+#define SSD1331_H
+
+#define SSD1331_COLUMN_ADDRESS					0x15		// 2 data: startx endx
+#define SSD1331_ROW_ADDRESS         	        0x75		// 2 data: starty endy
+#define SSD1331_CONTRAST_A						0x81		// 1 data: 0 - 255 default=128
+#define SSD1331_CONTRAST_B						0x82		// 1 data: 0 - 255 default=128
+#define SSD1331_CONTRAST_C						0x83		// 1 data: 0 - 255 default=128
+#define SSD1331_BRIGHTNESS						0x87		// 1 data: 0 - 15  default=15
+#define SSD1331_PRECHARGE_A						0x8A		// 1 data: 0 - 255 default=128
+#define SSD1331_PRECHARGE_B						0x8B		// 1 data: 0 - 255 default=128
+#define SSD1331_PRECHARGE_C						0x8C		// 1 data: 0 - 255 default=128
+#define SSD1331_MODE							0xA0		// 1 data:-        default=0x40
+	#define SSD1331_MODE_VINC						0x01
+	#define SSD1331_MODE_COLUMN_REVERSE				0x02
+	#define SSD1331_MODE_BGR						0x04		// if 1 then A=Blue,B=Green,C=Red
+	#define SSD1331_MODE_COM_SWAPLR					0x08
+	#define SSD1331_MODE_COM_REVERSE				0x10
+	#define SSD1331_MODE_COM_SPLIT					0x20
+	#define SSD1331_MODE_8_BIT						0x00
+	#define SSD1331_MODE_16_BIT						0x40
+	#define SSD1331_MODE_16_BIT2					0x80
+#define SSD1331_START_LINE						0xA1		// 1 data: liney default=0
+#define SSD1331_COM_OFFSET						0xA2		// 1 data: liney default=0
+#define SSD1331_PIXELS_NORMAL					0xA4		// 0 data - default
+#define SSD1331_PIXELS_FILL						0xA5		// 0 data
+#define SSD1331_PIXELS_OFF						0xA6		// 0 data
+#define SSD1331_DISPLAY_INVERSE					0xA7		// 0 data
+#define SSD1331_MULTIPLEX						0xA8		// 1 data: 15-63 default=63
+#define SSD1331_DIM								0xAB		// 5 data:
+															//		0x00 - Reserved
+															//		ContrastA 0 - 255 default=0?
+															//		ContrastB 0 - 255 default=0?
+															//		ContrastC 0 - 255 default=0?
+															//		Precharge 0 - 31 default=0?
+#define SSD1331_RESET							0xAD		// 1 data:
+	#define SSD1331_RESET_ON						0x8F	//		Reset - default
+	#define SSD1331_RESET_OFF						0x8E	//		Normal
+#define SSD1331_DISPLAY_OFF						0xAE		// 0 data - default
+#define SSD1331_DISPLAY_DIM						0xAC		// 0 data
+#define SSD1331_DISPLAY_ON						0xAF		// 0 data
+#define SSD1331_POWER							0xB0		// 1 data:
+	#define SSD1331_POWER_ON						0x0B	//		Normal Operation
+	#define SSD1331_POWER_OFF						0x1A	//		Power Save - default
+#define SSD1331_PHASE_PERIOD					0xB1		// 1 data: Phase 1 bit0-3 1-15, Phase 2 bit4-7 1-15 default=0x74
+#define SSD1331_CLOCKS							0xB3		// 1 data: Divide bit0-3 + 1, Freq bits4-7 default=0xD0
+#define SSD1331_GRAYSCALE						0xB8		// 32 data: each 1-125 default=1,5,9...121,125
+#define SSD1331_GRAYSCALE_LINEAR				0xB9		// 0 data
+#define SSD1331_PRECHARGE_VOLTAGE				0xBB		// 1 data: 0 - 62 (even only) default=62
+#define SSD1331_NOP								0xBC		// 0 data
+#define SSD1331_NOP1							0xBD		// 0 data
+#define SSD1331_NOP2							0xE3		// 0 data
+#define SSD1331_DESELECT_VOLTAGE				0xBE		// 1 data: 0 - 62 (even only) default=62
+#define SSD1331_LOCK							0xFD		// 1 data:
+	#define SSD1331_LOCK_ON							0x16	//		Lock MCU
+	#define SSD1331_LOCK_OFF						0x12	//		Unlock MCU - default
+
+#define SSD1331_DRAW_LINE						0x21		// 7 data:
+															//		startx, starty,
+															//		endx, endy,
+															//		C, B, A			- 6 bits each
+#define SSD1331_DRAW_RECT						0x22		// 10 data:
+															//		startx, starty,
+															//		endx, endy,
+															//		C, B, A			- line color 6 bits each
+															//		C, B, A			- fill color 6 bits each
+#define SSD1331_DRAW_COPY						0x23		// 6 data:
+															//		startx, starty,
+															//		endx, endy,
+															//		newx, newy
+#define SSD1331_DIM_AREA						0x24		// 4 data:
+															//		startx, starty,
+															//		endx, endy
+#define SSD1331_DRAW_CLEAR						0x25		// 4 data:
+															//		startx, starty,
+															//		endx, endy
+#define SSD1331_DRAW_MODE						0x26		// 1 data:
+	#define SSD1331_DRAW_FILLRECT					0x01	//		Fill Rectangle Draws
+	#define SSD1331_COPY_REVERSE					0x10	//		Reverse colors when copying
+#define SSD1331_SCROLL							0x27		// 5 data:
+															//		0 - 95	columns horizontal scroll
+															//		starty
+															//		cy
+															//		0 - 63 rows vertical scroll
+															//		time 0 = 6 frames, 1 = 10 frames, 2 = 100 frames, 3 = 200 frames
+#define SSD1331_SCROLL_STOP						0x2E		// 0 data
+#define SSD1331_SCROLL_START					0x2F		// 0 data
+
+#endif // SSD1331_H
diff --git a/drivers/gdisp/SSD1331/board_SSD1331_template.h b/drivers/gdisp/SSD1331/board_SSD1331_template.h
new file mode 100644
index 00000000..1f202936
--- /dev/null
+++ b/drivers/gdisp/SSD1331/board_SSD1331_template.h
@@ -0,0 +1,42 @@
+/*
+ * 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 inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_cmd(GDisplay *g, uint8_t index) {
+	(void) g;
+	(void) index;
+}
+
+static inline void write_data(GDisplay *g, uint8_t data) {
+	(void) g;
+	(void) data;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/SSD1331/driver.mk b/drivers/gdisp/SSD1331/driver.mk
new file mode 100644
index 00000000..b729431f
--- /dev/null
+++ b/drivers/gdisp/SSD1331/driver.mk
@@ -0,0 +1,2 @@
+GFXINC += $(GFXLIB)/drivers/gdisp/SSD1331
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1331/gdisp_lld_SSD1331.c
diff --git a/drivers/gdisp/SSD1331/gdisp_lld_SSD1331.c b/drivers/gdisp/SSD1331/gdisp_lld_SSD1331.c
new file mode 100644
index 00000000..d53fa27e
--- /dev/null
+++ b/drivers/gdisp/SSD1331/gdisp_lld_SSD1331.c
@@ -0,0 +1,329 @@
+/*
+ * 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
+
+#if defined(GDISP_SCREEN_HEIGHT)
+	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+	#undef GISP_SCREEN_HEIGHT
+#endif
+#if defined(GDISP_SCREEN_WIDTH)
+	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+	#undef GDISP_SCREEN_WIDTH
+#endif
+
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1331
+#include "gdisp_lld_config.h"
+#include "src/gdisp/gdisp_driver.h"
+
+#include "board_SSD1331.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		64
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		96
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	100
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	32
+#endif
+
+#include "SSD1331.h"
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some common routines and macros
+#define write_reg(g, reg, data)		{ write_cmd(g, reg); write_data(g, data); }
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+static const initdata[] = {
+	SSD1331_DISPLAY_OFF,
+	SSD1331_START_LINE, 0x00,
+	SSD1331_COM_OFFSET, 0x00,
+	SSD1331_PIXELS_NORMAL,
+	SSD1331_MULTIPLEX, 0x3F,
+	SSD1331_RESET, SSD1331_RESET_OFF,
+	SSD1331_POWER, SSD1331_POWER_ON,
+	SSD1331_PHASE_PERIOD, 0x31,
+	SSD1331_CLOCKS, 0xF0,
+	SSD1331_PRECHARGE_A, 0x64,
+	SSD1331_PRECHARGE_B, 0x78,
+	SSD1331_PRECHARGE_C, 0x64,
+	SSD1331_PRECHARGE_VOLTAGE, 0x3A,
+	SSD1331_DESELECT_VOLTAGE, 0x3E,
+	SSD1331_CONTRAST_A, 0x91,
+	SSD1331_CONTRAST_B, 0x50,
+	SSD1331_CONTRAST_C, 0x7D,
+	SSD1331_BRIGHTNESS, (GDISP_INITIAL_BACKLIGHT*10)/63,
+	#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565
+		SSD1331_MODE, SSD1331_MODE_16_BIT|SSD1331_MODE_COM_SPLIT,
+	#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_BGR565
+		SSD1331_MODE, SSD1331_MODE_16_BIT|SSD1331_MODE_COM_SPLIT|SSD1331_MODE_BGR,
+	#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB332
+		SSD1331_MODE, SSD1331_MODE_8_BIT|SSD1331_MODE_COM_SPLIT,
+	#elif GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_BGR332
+		SSD1331_MODE, SSD1331_MODE_8_BIT|SSD1331_MODE_COM_SPLIT|SSD1331_MODE_BGR,
+	#else
+		#error "SSD1331: Invalid color format"
+	#endif
+	SSD1331_DRAW_MODE, SSD1331_DRAW_FILLRECT,
+};
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	int		i;
+
+	// 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);
+
+	for(i=0;i<sizeof(initdata);i++)
+		write_cmd(g, initdata[i]);
+
+	gfxSleepMilliseconds(2);
+	write_cmd(g, SSD1331_DISPLAY_ON);
+
+	release_bus(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 = GDISP_INITIAL_BACKLIGHT;
+	g->g.Contrast = GDISP_INITIAL_CONTRAST;
+	return TRUE;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		write_cmd(g, SSD1331_COLUMN_ADDRESS);
+		write_cmd(g, g->p.x);
+		write_cmd(g, g->p.x + g->p.cx - 1);
+		write_cmd(g, SSD1331_ROW_ADDRESS);
+		write_cmd(g, g->p.y);
+		write_cmd(g, g->p.y + g->p.cy - 1);
+	}
+	#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 || GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_BGR565
+		LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+			LLDCOLOR_TYPE	c;
+
+			c = gdispColor2Native(g->p.color);
+			write_data(g, c >> 8);
+			write_data(g, c);
+		}
+	#else
+		LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+			write_data(g, gdispColor2Native(g->p.color));
+		}
+	#endif
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_FILLS
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		uint8_t		a6, b6, c6;
+
+		acquire_bus(g);
+
+		if (g->p.color == Black) {
+			// Use clear window command
+			write_cmd(g, SSD1331_DRAW_CLEAR);
+			write_cmd(g, g->p.x);
+			write_cmd(g, g->p.y);
+			write_cmd(g, g->p.x + g->p.cx - 1);
+			write_cmd(g, g->p.y + g->p.cy - 1);
+			release_bus(g);
+			return;
+		}
+
+		#if GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB565 || GDISP_LLD_PIXELFORMAT == GDISP_PIXELFORMAT_RGB322
+			c6 = RED_OF(g->p.color) >> 2;
+			#if COLOR_BITS_R < 5
+				if (c6 & 0x20) c6 |= (1<<(6-COLOR_BITS_R))-1;
+			#endif
+			b6 = GREEN_OF(g->p.color) >> 2;
+			#if COLOR_BITS_G < 6
+				if (b6 & 0x20) b6 |= (1<<(6-COLOR_BITS_G))-1;
+			#endif
+			a6 = BLUE_OF(g->p.color) >> 2;
+			#if COLOR_BITS_B < 5
+				if (a6 & 0x20) a6 |= (1<<(6-COLOR_BITS_B))-1;
+			#endif
+		#else
+			c6 = BLUE_OF(g->p.color) >> 2;
+			#if COLOR_BITS_B < 5
+				if (c6 & 0x20) c6 |= (1<<(6-COLOR_BITS_B))-1;
+			#endif
+			b6 = GREEN_OF(g->p.color) >> 2;
+			#if COLOR_BITS_G < 6
+				if (b6 & 0x20) b6 |= (1<<(6-COLOR_BITS_G))-1;
+			#endif
+			a6 = RED_OF(g->p.color) >> 2;
+			#if COLOR_BITS_R < 5
+				if (a6 & 0x20) a6 |= (1<<(6-COLOR_BITS_R))-1;
+			#endif
+		#endif
+		if (g->p.cx == 1 || g->p.cy == 1) {
+			// Use Line command
+			write_cmd(g, SSD1331_DRAW_LINE);
+			write_cmd(g, g->p.x);
+			write_cmd(g, g->p.y);
+			write_cmd(g, g->p.x + g->p.cx - 1);
+			write_cmd(g, g->p.y + g->p.cy - 1);
+		} else {
+			// Use Rectangle command
+
+			write_cmd(g, SSD1331_DRAW_RECT);
+			write_cmd(g, g->p.x);
+			write_cmd(g, g->p.y);
+			write_cmd(g, g->p.x + g->p.cx - 1);
+			write_cmd(g, g->p.y + g->p.cy - 1);
+			//outline
+			write_cmd(g, c6);
+			write_cmd(g, b6);
+			write_cmd(g, a6);
+			//fill
+		}
+
+		write_cmd(g, c6);
+		write_cmd(g, b6);
+		write_cmd(g, a6);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
+		acquire_bus(g);
+		write_cmd(g, SSD1331_DRAW_COPY);
+		write_cmd(g, g->p.x);
+		write_cmd(g, g->p.y);
+		write_cmd(g, g->p.x + g->p.cx - 1);
+		write_cmd(g, g->p.y + g->p.cy - 1);
+		write_cmd(g, g->p.x);
+		write_cmd(g, g->p.y - lines);
+		release_bus(g);
+	}
+#endif
+
+#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:
+			case powerSleep:
+			case powerDeepSleep:
+				acquire_bus(g);
+				write_cmd(g, SSD1331_DISPLAY_OFF);
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_cmd(g, SSD1331_DISPLAY_ON);
+				release_bus(g);
+				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:
+				acquire_bus(g);
+				//TODO
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				//TODO
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				//TODO
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				//TODO
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				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;
+			acquire_bus(g);
+            write_cmd(g, SSD1331_BRIGHTNESS);
+            write_cmd(g, ((unsigned)g->p.ptr*10)/63);
+			release_bus(g);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/SSD1331/gdisp_lld_config.h b/drivers/gdisp/SSD1331/gdisp_lld_config.h
new file mode 100644
index 00000000..d941f714
--- /dev/null
+++ b/drivers/gdisp/SSD1331/gdisp_lld_config.h
@@ -0,0 +1,31 @@
+/*
+ * 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.                                                  */
+/*===========================================================================*/
+
+// This controller supports some optimized drawing routines - but no read (at least with SPI interfacing)
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_FILLS			TRUE
+#define GDISP_HARDWARE_SCROLL			TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
+
+// This driver supports 4 pixel formats - pick the one you want.
+//#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_BGR565
+//#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB332
+//#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_BGR332
+
+#endif	/* GFX_USE_GDISP */
+
+#endif	/* _GDISP_LLD_CONFIG_H */
-- 
cgit v1.2.3