From 6e4437255b603b5b25360481507099dd9b92f942 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 6 Sep 2013 12:29:06 +1000
Subject: GDISP revamp - stage 1 New low level driver interface: Only Win32
 ported currently Significant reduction in GDISP stack usage Improved
 performance particularly for native streaming drivers New circle, ellipse,
 arc routines (draw and fill) that are significantly more efficient and don't
 overdraw New arc draw algorithm that measures angles correctly. New arc fill
 algorithm for that actually works without overdrawing or gaps. Much more to
 come...

---
 drivers/multiple/Win32/gdisp_lld.c        | 346 +++++++++++++-----------------
 drivers/multiple/Win32/gdisp_lld_config.h |  22 +-
 2 files changed, 162 insertions(+), 206 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 0bac0fde..91b86616 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -17,6 +17,13 @@
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
+#include "gdisp/lld/gdisp_lld.h"
+
+// Declare our driver object
+GDISPDriver	GDISP_Win32;
+
+#define GC	(&GDISP_Win32)
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -45,9 +52,6 @@
 	#include "ginput/lld/mouse.h"
 #endif
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-
 /*===========================================================================*/
 /* Driver local routines    .                                                */
 /*===========================================================================*/
@@ -329,86 +333,59 @@ bool_t gdisp_lld_init(void) {
 		Sleep(1);
 
 	/* Initialise the GDISP structure to match */
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = 100;
-	GDISP.Contrast = 50;
-	GDISP.Width = wWidth;
-	GDISP.Height = wHeight;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	GC->g.Orientation = GDISP_ROTATE_0;
+	GC->g.Powermode = powerOn;
+	GC->g.Backlight = 100;
+	GC->g.Contrast = 50;
+	GC->g.Width = wWidth;
+	GC->g.Height = wHeight;
 	return TRUE;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	HDC dc;
-	#if WIN32_USE_MSG_REDRAW
-		RECT	rect;
-	#endif
-	#if GDISP_NEED_CONTROL
-		coord_t	t;
-	#endif
-
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		// Clip pre orientation change
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-
-	#if GDISP_NEED_CONTROL
-		switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-			break;
-		case GDISP_ROTATE_90:
-			t = GDISP.Height - 1 - y;
-			y = x;
-			x = t;
-			break;
-		case GDISP_ROTATE_180:
-			x = GDISP.Width - 1 - x;
-			y = GDISP.Height - 1 - y;
-			break;
-		case GDISP_ROTATE_270:
-			t = GDISP.Width - 1 - x;
-			x = y;
-			y = t;
-			break;
-		}
-	#endif
+#if GDISP_HARDWARE_DRAWPIXEL
+	void gdisp_lld_draw_pixel(void) {
+		HDC			dcScreen;
+		int			x, y;
+		COLORREF	color;
 	
-	// Draw the pixel in the buffer
-	color = COLOR2BGR(color);
-	SetPixel(dcBuffer, x, y, color);
+		color = COLOR2BGR(GC->p.color);
 	
-	#if WIN32_USE_MSG_REDRAW
-		rect.left = x; rect.right = x+1;
-		rect.top = y; rect.bottom = y+1;
-		InvalidateRect(winRootWindow, &rect, FALSE);
-		UpdateWindow(winRootWindow);
-	#else
-		// Draw the pixel again directly on the screen.
-		// This is cheaper than invalidating a single pixel in the window
-		dc = GetDC(winRootWindow);
-		SetPixel(dc, x, y, color);
-		ReleaseDC(winRootWindow, dc);
-	#endif
-}
+		#if GDISP_NEED_CONTROL
+			switch(GC->g.Orientation) {
+			case GDISP_ROTATE_0:
+				x = GC->p.x;
+				y = GC->p.y;
+				break;
+			case GDISP_ROTATE_90:
+				x = GC->g.Height - 1 - GC->p.y;
+				y = GC->p.x;
+				break;
+			case GDISP_ROTATE_180:
+				x = GC->g.Width - 1 - GC->p.x;
+				y = GC->g.Height - 1 - GC->p.y;
+				break;
+			case GDISP_ROTATE_270:
+				x = GC->p.y;
+				y = GC->g.Width - 1 - GC->p.x;
+				break;
+			}
+		#else
+			x = GC->p.x;
+			y = GC->p.y;
+		#endif
+
+		// Draw the pixel on the screen and in the buffer.
+		dcScreen = GetDC(winRootWindow);
+		SetPixel(dcScreen, x, y, color);
+		SetPixel(dcBuffer, x, y, color);
+		ReleaseDC(winRootWindow, dcScreen);
+	}
+#endif
 
 /* ---- Optional Routines ---- */
 
-#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__)
+#if 0
+#if GDISP_HARDWARE_LINES
 	/**
 	 * @brief   Draw a line.
 	 * @note    Optional - The high level driver can emulate using software.
@@ -439,57 +416,57 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 		#endif
 
 		#if GDISP_NEED_CONTROL
-			switch(GDISP.Orientation) {
+			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
 				#if GDISP_NEED_CLIP
 					// Clip post orientation change
-					if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
-						clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1);
+					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
+						clip = CreateRectRgn(GC->g.clipx0, GC->g.clipy0, GC->g.clipx1, GC->g.clipy1);
 				#endif
 				break;
 			case GDISP_ROTATE_90:
-				t = GDISP.Height - 1 - y0;
+				t = GC->g.Height - 1 - y0;
 				y0 = x0;
 				x0 = t;
-				t = GDISP.Height - 1 - y1;
+				t = GC->g.Height - 1 - y1;
 				y1 = x1;
 				x1 = t;
 				#if GDISP_NEED_CLIP
 					// Clip post orientation change
-					if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
-						clip = CreateRectRgn(GDISP.Height-1-GDISP.clipy1, GDISP.clipx0, GDISP.Height-1-GDISP.clipy0, GDISP.clipx1);
+					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
+						clip = CreateRectRgn(GC->g.Height-1-GC->g.clipy1, GC->g.clipx0, GC->g.Height-1-GC->g.clipy0, GC->g.clipx1);
 				#endif
 				break;
 			case GDISP_ROTATE_180:
-				x0 = GDISP.Width - 1 - x0;
-				y0 = GDISP.Height - 1 - y0;
-				x1 = GDISP.Width - 1 - x1;
-				y1 = GDISP.Height - 1 - y1;
+				x0 = GC->g.Width - 1 - x0;
+				y0 = GC->g.Height - 1 - y0;
+				x1 = GC->g.Width - 1 - x1;
+				y1 = GC->g.Height - 1 - y1;
 				#if GDISP_NEED_CLIP
 					// Clip post orientation change
-					if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
-						clip = CreateRectRgn(GDISP.Width-1-GDISP.clipx1, GDISP.Height-1-GDISP.clipy1, GDISP.Width-1-GDISP.clipx0, GDISP.Height-1-GDISP.clipy0);
+					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
+						clip = CreateRectRgn(GC->g.Width-1-GC->g.clipx1, GC->g.Height-1-GC->g.clipy1, GC->g.Width-1-GC->g.clipx0, GC->g.Height-1-GC->g.clipy0);
 				#endif
 				break;
 			case GDISP_ROTATE_270:
-				t = GDISP.Width - 1 - x0;
+				t = GC->g.Width - 1 - x0;
 				x0 = y0;
 				y0 = t;
-				t = GDISP.Width - 1 - x1;
+				t = GC->g.Width - 1 - x1;
 				x1 = y1;
 				y1 = t;
 				#if GDISP_NEED_CLIP
 					// Clip post orientation change
-					if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
-						clip = CreateRectRgn(GDISP.clipy0, GDISP.Width-1-GDISP.clipx1, GDISP.clipy1, GDISP.Width-1-GDISP.clipx0);
+					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
+						clip = CreateRectRgn(GC->g.clipy0, GC->g.Width-1-GC->g.clipx1, GC->g.clipy1, GC->g.Width-1-GC->g.clipx0);
 				#endif
 				break;
 			}
 		#else
 			#if GDISP_NEED_CLIP
 				clip = NULL;
-				if (GDISP.clipx0 != 0 || GDISP.clipy0 != 0 || GDISP.clipx1 != GDISP.Width || GDISP.clipy1 != GDISP.Height)
-					clip = CreateRectRgn(GDISP.clipx0, GDISP.clipy0, GDISP.clipx1, GDISP.clipy1);
+				if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
+					clip = CreateRectRgn(GC->g.clipx0, GC->g.clipy0, GC->g.clipx1, GC->g.clipy1);
 			#endif
 		#endif
 	
@@ -535,85 +512,58 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 		}
 	}
 #endif
+#endif
 
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		HDC dc;
-		RECT rect;
-		HBRUSH hbr;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			// Clip pre orientation change
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
+#if GDISP_HARDWARE_FILLS
+	void gdisp_lld_fill_area(void) {
+		HDC			dcScreen;
+		RECT		rect;
+		HBRUSH		hbr;
+		COLORREF	color;
 
+		color = COLOR2BGR(GC->p.color);
 		#if GDISP_NEED_CONTROL
-			switch(GDISP.Orientation) {
+			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
-				rect.top = y;
-				rect.bottom = rect.top+cy;
-				rect.left = x;
-				rect.right = rect.left+cx;
+				rect.top = GC->p.y;
+				rect.bottom = rect.top + GC->p.cy;
+				rect.left = GC->p.x;
+				rect.right = rect.left + GC->p.cx;
 				break;
 			case GDISP_ROTATE_90:
-				rect.top = x;
-				rect.bottom = rect.top+cx;
-				rect.right = GDISP.Height - y;
-				rect.left = rect.right-cy;
+				rect.top = GC->p.x;
+				rect.bottom = rect.top + GC->p.cx;
+				rect.right = GC->g.Height - GC->p.y;
+				rect.left = rect.right - GC->p.cy;
 				break;
 			case GDISP_ROTATE_180:
-				rect.bottom = GDISP.Height - y;
-				rect.top = rect.bottom-cy;
-				rect.right = GDISP.Width - x;
-				rect.left = rect.right-cx;
+				rect.bottom = GC->g.Height - GC->p.y;
+				rect.top = rect.bottom - GC->p.cy;
+				rect.right = GC->g.Width - GC->p.x;
+				rect.left = rect.right - GC->p.cx;
 				break;
 			case GDISP_ROTATE_270:
-				rect.bottom = GDISP.Width - x;
-				rect.top = rect.bottom-cx;
-				rect.left = y;
-				rect.right = rect.left+cy;
+				rect.bottom = GC->g.Width - GC->p.x;
+				rect.top = rect.bottom - GC->p.cx;
+				rect.left = GC->p.y;
+				rect.right = rect.left + GC->p.cy;
 				break;
 			}
 		#else
-			rect.top = y;
-			rect.bottom = rect.top+cy;
-			rect.left = x;
-			rect.right = rect.left+cx;
+			rect.top = GC->p.y;
+			rect.bottom = rect.top + GC->p.cy;
+			rect.left = GC->p.x;
+			rect.right = rect.left + GC->p.cx;
 		#endif
 
-		color = COLOR2BGR(color);
 		hbr = CreateSolidBrush(color);
 
-		if (hbr) {
-			// Fill the area
-			FillRect(dcBuffer, &rect, hbr);
-
-			#if WIN32_USE_MSG_REDRAW
-				InvalidateRect(winRootWindow, &rect, FALSE);
-				UpdateWindow(winRootWindow);
-			#else
-				// Filling the area directly on the screen is likely to be cheaper than invalidating it
-				dc = GetDC(winRootWindow);
-				FillRect(dc, &rect, hbr);
-				ReleaseDC(winRootWindow, dc);
-			#endif
+		dcScreen = GetDC(winRootWindow);
+		FillRect(dcScreen, &rect, hbr);
+		FillRect(dcBuffer, &rect, hbr);
+		ReleaseDC(winRootWindow, dcScreen);
 
-			DeleteObject(hbr);
-		}
+		DeleteObject(hbr);
 	}
 #endif
 
@@ -626,7 +576,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 		coord_t	i, j;
 
 		// Shortcut.
-		if (GDISP.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx)
+		if (GC->g.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx)
 			return (pixel_t *)buffer;
 		
 		// Allocate the destination buffer
@@ -635,7 +585,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 			return 0;
 		
 		// Copy the bits we need
-		switch(GDISP.Orientation) {
+		switch(GC->g.Orientation) {
 		case GDISP_ROTATE_0:
 			for(dst = dstbuf, src = buffer+srcx, j = 0; j < cy; j++)
 				for(i = 0; i < cx; i++, src += srccx - cx)
@@ -665,7 +615,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 	}
 #endif
 	
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+#if GDISP_HARDWARE_BITFILLS
 	/**
 	 * @brief   Fill an area with a bitmap.
 	 * @note    Optional - The high level driver can emulate using software.
@@ -687,12 +637,12 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 
 		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
 			// Clip pre orientation change
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
+			if (x < GC->g.clipx0) { cx -= GC->g.clipx0 - x; srcx += GC->g.clipx0 - x; x = GC->g.clipx0; }
+			if (y < GC->g.clipy0) { cy -= GC->g.clipy0 - y; srcy += GC->g.clipy0 - y; y = GC->g.clipy0; }
 			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
+			if (cx <= 0 || cy <= 0 || x >= GC->g.clipx1 || y >= GC->g.clipy1) return;
+			if (x+cx > GC->g.clipx1)	cx = GC->g.clipx1 - x;
+			if (y+cy > GC->g.clipy1)	cy = GC->g.clipy1 - y;
 		#endif
 
 		// Make everything relative to the start of the line
@@ -719,7 +669,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 			srcimg = rotateimg(cx, cy, srcx, srccx, buffer);
 			if (!srcimg) return;
 			
-			switch(GDISP.Orientation) {
+			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
 				bmpInfo.bV4Width = cx;
 				bmpInfo.bV4Height = -cy; /* top-down image */
@@ -733,21 +683,21 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				bmpInfo.bV4Height = -cx; /* top-down image */
 				rect.top = x;
 				rect.bottom = rect.top+cx;
-				rect.right = GDISP.Height - y;
+				rect.right = GC->g.Height - y;
 				rect.left = rect.right-cy;
 				break;
 			case GDISP_ROTATE_180:
 				bmpInfo.bV4Width = cx;
 				bmpInfo.bV4Height = -cy; /* top-down image */
-				rect.bottom = GDISP.Height - y;
+				rect.bottom = GC->g.Height - y;
 				rect.top = rect.bottom-cy;
-				rect.right = GDISP.Width - x;
+				rect.right = GC->g.Width - x;
 				rect.left = rect.right-cx;
 				break;
 			case GDISP_ROTATE_270:
 				bmpInfo.bV4Width = cy;
 				bmpInfo.bV4Height = -cx; /* top-down image */
-				rect.bottom = GDISP.Width - x;
+				rect.bottom = GC->g.Width - x;
 				rect.top = rect.bottom-cx;
 				rect.left = y;
 				rect.right = rect.left+cy;
@@ -793,24 +743,24 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 
 		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
 			// Clip pre orientation change
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+			if (x < 0 || x >= GC->g.Width || y < 0 || y >= GC->g.Height) return 0;
 		#endif
 
 		#if GDISP_NEED_CONTROL
-			switch(GDISP.Orientation) {
+			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
 				break;
 			case GDISP_ROTATE_90:
-				t = GDISP.Height - 1 - y;
+				t = GC->g.Height - 1 - y;
 				y = x;
 				x = t;
 				break;
 			case GDISP_ROTATE_180:
-				x = GDISP.Width - 1 - x;
-				y = GDISP.Height - 1 - y;
+				x = GC->g.Width - 1 - x;
+				y = GC->g.Height - 1 - y;
 				break;
 			case GDISP_ROTATE_270:
-				t = GDISP.Width - 1 - x;
+				t = GC->g.Width - 1 - x;
 				x = y;
 				y = t;
 				break;
@@ -842,11 +792,11 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 		
 		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
 			// Clip pre orientation change
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
+			if (x < GC->g.clipx0) { cx -= GC->g.clipx0 - x; x = GC->g.clipx0; }
+			if (y < GC->g.clipy0) { cy -= GC->g.clipy0 - y; y = GC->g.clipy0; }
+			if (!lines || cx <= 0 || cy <= 0 || x >= GC->g.clipx1 || y >= GC->g.clipy1) return;
+			if (x+cx > GC->g.clipx1)	cx = GC->g.clipx1 - x;
+			if (y+cy > GC->g.clipy1)	cy = GC->g.clipy1 - y;
 		#endif
 		
 		if (lines > cy) lines = cy;
@@ -856,7 +806,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 		hbr = CreateSolidBrush(bgcolor);
 
 		#if GDISP_NEED_CONTROL
-			switch(GDISP.Orientation) {
+			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
 				rect.top = y;
 				rect.bottom = rect.top+cy;
@@ -867,13 +817,13 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 			case GDISP_ROTATE_90:
 				rect.top = x;
 				rect.bottom = rect.top+cx;
-				rect.right = GDISP.Height - y;
+				rect.right = GC->g.Height - y;
 				rect.left = rect.right-cy;
 				goto horizontal_scroll;
 			case GDISP_ROTATE_180:
-				rect.bottom = GDISP.Height - y;
+				rect.bottom = GC->g.Height - y;
 				rect.top = rect.bottom-cy;
-				rect.right = GDISP.Width - x;
+				rect.right = GC->g.Width - x;
 				rect.left = rect.right-cx;
 			vertical_scroll:
 				srect.left = frect.left = rect.left;
@@ -891,7 +841,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 					ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
 				break;
 			case GDISP_ROTATE_270:
-				rect.bottom = GDISP.Width - x;
+				rect.bottom = GC->g.Width - x;
 				rect.top = rect.bottom-cx;
 				rect.left = y;
 				rect.right = rect.left+cy;
@@ -963,36 +913,36 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 	void gdisp_lld_control(unsigned what, void *value) {
 		switch(what) {
 		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
+			if (GC->g.Orientation == (gdisp_orientation_t)value)
 				return;
 			switch((gdisp_orientation_t)value) {
 				case GDISP_ROTATE_0:
-					GDISP.Width = wWidth;
-					GDISP.Height = wHeight;
+					GC->g.Width = wWidth;
+					GC->g.Height = wHeight;
 					break;
 				case GDISP_ROTATE_90:
-					GDISP.Height = wWidth;
-					GDISP.Width = wHeight;
+					GC->g.Height = wWidth;
+					GC->g.Width = wHeight;
 					break;
 				case GDISP_ROTATE_180:
-					GDISP.Width = wWidth;
-					GDISP.Height = wHeight;
+					GC->g.Width = wWidth;
+					GC->g.Height = wHeight;
 					break;
 				case GDISP_ROTATE_270:
-					GDISP.Height = wWidth;
-					GDISP.Width = wHeight;
+					GC->g.Height = wWidth;
+					GC->g.Width = wHeight;
 					break;
 				default:
 					return;
 			}
 
 			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
+				GC->g.clipx0 = 0;
+				GC->g.clipy0 = 0;
+				GC->g.clipx1 = GC->g.Width;
+				GC->g.clipy1 = GC->g.Height;
 			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
+			GC->g.Orientation = (gdisp_orientation_t)value;
 			return;
 /*
 		case GDISP_CONTROL_POWER:
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index b6fa874a..357febe4 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -22,14 +22,20 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"Win32"
-
-#define GDISP_HARDWARE_LINES			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			TRUE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
-#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_DRIVER_NAME				"Win32"
+#define GDISP_DRIVER_STRUCT				GDISP_Win32
+
+#define GDISP_HARDWARE_STREAM			FALSE
+#define GDISP_HARDWARE_STREAM_END		FALSE
+#define GDISP_HARDWARE_DRAWPIXEL		TRUE
+#define GDISP_HARDWARE_CLEARS			FALSE
+#define GDISP_HARDWARE_FILLS			TRUE
+//#define GDISP_HARDWARE_BITFILLS			TRUE
+//#define GDISP_HARDWARE_SCROLL			TRUE
+//#define GDISP_HARDWARE_PIXELREAD		TRUE
+//#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_HARDWARE_QUERY			FALSE
+#define GDISP_HARDWARE_CLIP				FALSE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
 
-- 
cgit v1.2.3


From b25ac5e667d98f2915831a74707f6ec198a4498b Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 18 Sep 2013 23:46:37 +1000
Subject: Scrolling emulation when not supported by hardware Start of new
 multiple display support GDISP performance optimisations Documentation
 updates Win32 driver updates

---
 drivers/multiple/Win32/gdisp_lld.c        | 503 ++++++++----------------------
 drivers/multiple/Win32/gdisp_lld_config.h |  15 +-
 2 files changed, 135 insertions(+), 383 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 91b86616..d6c6b2fb 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -8,22 +8,15 @@
 /**
  * @file    drivers/multiple/Win32/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for Win32.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
 
+#define GDISP_LLD_DECLARATIONS
 #include "gdisp/lld/gdisp_lld.h"
 
-// Declare our driver object
-GDISPDriver	GDISP_Win32;
-
-#define GC	(&GDISP_Win32)
-
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -41,10 +34,6 @@ GDISPDriver	GDISP_Win32;
 #if GINPUT_NEED_TOGGLE
 	/* Include toggle support code */
 	#include "ginput/lld/toggle.h"
-
-	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
-		{0,	0xFF, 0x00, 0},
-	};
 #endif
 
 #if GINPUT_NEED_MOUSE
@@ -298,19 +287,13 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
 /**
- * @brief   Low level GDISP driver initialisation.
+ * @brief   Low level GDISP driver initialization.
  * @return	TRUE if successful, FALSE on error.
  *
  * @notapi
  */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	RECT			rect;
 	gfxThreadHandle	hth;
 
@@ -333,45 +316,45 @@ bool_t gdisp_lld_init(void) {
 		Sleep(1);
 
 	/* Initialise the GDISP structure to match */
-	GC->g.Orientation = GDISP_ROTATE_0;
-	GC->g.Powermode = powerOn;
-	GC->g.Backlight = 100;
-	GC->g.Contrast = 50;
-	GC->g.Width = wWidth;
-	GC->g.Height = wHeight;
+	g->g.Orientation = GDISP_ROTATE_0;
+	g->g.Powermode = powerOn;
+	g->g.Backlight = 100;
+	g->g.Contrast = 50;
+	g->g.Width = wWidth;
+	g->g.Height = wHeight;
 	return TRUE;
 }
 
 #if GDISP_HARDWARE_DRAWPIXEL
-	void gdisp_lld_draw_pixel(void) {
+	LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) {
 		HDC			dcScreen;
 		int			x, y;
 		COLORREF	color;
 	
-		color = COLOR2BGR(GC->p.color);
+		color = COLOR2BGR(g->p.color);
 	
 		#if GDISP_NEED_CONTROL
-			switch(GC->g.Orientation) {
+			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
-				x = GC->p.x;
-				y = GC->p.y;
+				x = g->p.x;
+				y = g->p.y;
 				break;
 			case GDISP_ROTATE_90:
-				x = GC->g.Height - 1 - GC->p.y;
-				y = GC->p.x;
+				x = g->g.Height - 1 - g->p.y;
+				y = g->p.x;
 				break;
 			case GDISP_ROTATE_180:
-				x = GC->g.Width - 1 - GC->p.x;
-				y = GC->g.Height - 1 - GC->p.y;
+				x = g->g.Width - 1 - g->p.x;
+				y = g->g.Height - 1 - g->p.y;
 				break;
 			case GDISP_ROTATE_270:
-				x = GC->p.y;
-				y = GC->g.Width - 1 - GC->p.x;
+				x = g->p.y;
+				y = g->g.Width - 1 - g->p.x;
 				break;
 			}
 		#else
-			x = GC->p.x;
-			y = GC->p.y;
+			x = g->p.x;
+			y = g->p.y;
 		#endif
 
 		// Draw the pixel on the screen and in the buffer.
@@ -384,176 +367,46 @@ bool_t gdisp_lld_init(void) {
 
 /* ---- Optional Routines ---- */
 
-#if 0
-#if GDISP_HARDWARE_LINES
-	/**
-	 * @brief   Draw a line.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x0, y0   The start of the line
-	 * @param[in] x1, y1   The end of the line
-	 * @param[in] color    The color of the line
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_draw_line(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) {
-		POINT p;
-		HPEN pen;
-		HDC dc;
-		HGDIOBJ old;
-		#if GDISP_NEED_CLIP
-			HRGN	clip;
-		#endif
-		#if WIN32_USE_MSG_REDRAW
-			RECT	rect;
-		#endif
-		#if GDISP_NEED_CONTROL
-			coord_t	t;
-		#endif
-
-		#if GDISP_NEED_CLIP
-			clip = NULL;
-		#endif
-
-		#if GDISP_NEED_CONTROL
-			switch(GC->g.Orientation) {
-			case GDISP_ROTATE_0:
-				#if GDISP_NEED_CLIP
-					// Clip post orientation change
-					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
-						clip = CreateRectRgn(GC->g.clipx0, GC->g.clipy0, GC->g.clipx1, GC->g.clipy1);
-				#endif
-				break;
-			case GDISP_ROTATE_90:
-				t = GC->g.Height - 1 - y0;
-				y0 = x0;
-				x0 = t;
-				t = GC->g.Height - 1 - y1;
-				y1 = x1;
-				x1 = t;
-				#if GDISP_NEED_CLIP
-					// Clip post orientation change
-					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
-						clip = CreateRectRgn(GC->g.Height-1-GC->g.clipy1, GC->g.clipx0, GC->g.Height-1-GC->g.clipy0, GC->g.clipx1);
-				#endif
-				break;
-			case GDISP_ROTATE_180:
-				x0 = GC->g.Width - 1 - x0;
-				y0 = GC->g.Height - 1 - y0;
-				x1 = GC->g.Width - 1 - x1;
-				y1 = GC->g.Height - 1 - y1;
-				#if GDISP_NEED_CLIP
-					// Clip post orientation change
-					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
-						clip = CreateRectRgn(GC->g.Width-1-GC->g.clipx1, GC->g.Height-1-GC->g.clipy1, GC->g.Width-1-GC->g.clipx0, GC->g.Height-1-GC->g.clipy0);
-				#endif
-				break;
-			case GDISP_ROTATE_270:
-				t = GC->g.Width - 1 - x0;
-				x0 = y0;
-				y0 = t;
-				t = GC->g.Width - 1 - x1;
-				x1 = y1;
-				y1 = t;
-				#if GDISP_NEED_CLIP
-					// Clip post orientation change
-					if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
-						clip = CreateRectRgn(GC->g.clipy0, GC->g.Width-1-GC->g.clipx1, GC->g.clipy1, GC->g.Width-1-GC->g.clipx0);
-				#endif
-				break;
-			}
-		#else
-			#if GDISP_NEED_CLIP
-				clip = NULL;
-				if (GC->g.clipx0 != 0 || GC->g.clipy0 != 0 || GC->g.clipx1 != GC->g.Width || GC->g.clipy1 != GC->g.Height)
-					clip = CreateRectRgn(GC->g.clipx0, GC->g.clipy0, GC->g.clipx1, GC->g.clipy1);
-			#endif
-		#endif
-	
-		color = COLOR2BGR(color);
-		pen = CreatePen(PS_SOLID, 1, color);
-		if (pen) {
-			// Draw the line in the buffer
-			#if GDISP_NEED_CLIP
-				if (clip) SelectClipRgn(dcBuffer, clip);
-			#endif
-			old = SelectObject(dcBuffer, pen);
-			MoveToEx(dcBuffer, x0, y0, &p);
-			LineTo(dcBuffer, x1, y1);
-			SelectObject(dcBuffer, old);
-			SetPixel(dcBuffer, x1, y1, color);
-			#if GDISP_NEED_CLIP
-				if (clip) SelectClipRgn(dcBuffer, NULL);
-			#endif
-
-			#if WIN32_USE_MSG_REDRAW
-				rect.left = x0; rect.right = x1+1;
-				rect.top = y0; rect.bottom = y1+1;
-				InvalidateRect(winRootWindow, &rect, FALSE);
-				UpdateWindow(winRootWindow);
-			#else
-				// Redrawing the line on the screen is cheaper than invalidating the whole rectangular area
-				dc = GetDC(winRootWindow);
-				#if GDISP_NEED_CLIP
-					if (clip) SelectClipRgn(dc, clip);
-				#endif
-				old = SelectObject(dc, pen);
-				MoveToEx(dc, x0, y0, &p);
-				LineTo(dc, x1, y1);
-				SelectObject(dc, old);
-				SetPixel(dc, x1, y1, color);
-				#if GDISP_NEED_CLIP
-					if (clip) SelectClipRgn(dc, NULL);
-				#endif
-				ReleaseDC(winRootWindow, dc);
-			#endif
-
-			DeleteObject(pen);
-		}
-	}
-#endif
-#endif
-
 #if GDISP_HARDWARE_FILLS
-	void gdisp_lld_fill_area(void) {
+	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
 		HDC			dcScreen;
 		RECT		rect;
 		HBRUSH		hbr;
 		COLORREF	color;
 
-		color = COLOR2BGR(GC->p.color);
+		color = COLOR2BGR(g->p.color);
 		#if GDISP_NEED_CONTROL
-			switch(GC->g.Orientation) {
+			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
-				rect.top = GC->p.y;
-				rect.bottom = rect.top + GC->p.cy;
-				rect.left = GC->p.x;
-				rect.right = rect.left + GC->p.cx;
+				rect.top = g->p.y;
+				rect.bottom = rect.top + g->p.cy;
+				rect.left = g->p.x;
+				rect.right = rect.left + g->p.cx;
 				break;
 			case GDISP_ROTATE_90:
-				rect.top = GC->p.x;
-				rect.bottom = rect.top + GC->p.cx;
-				rect.right = GC->g.Height - GC->p.y;
-				rect.left = rect.right - GC->p.cy;
+				rect.top = g->p.x;
+				rect.bottom = rect.top + g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right - g->p.cy;
 				break;
 			case GDISP_ROTATE_180:
-				rect.bottom = GC->g.Height - GC->p.y;
-				rect.top = rect.bottom - GC->p.cy;
-				rect.right = GC->g.Width - GC->p.x;
-				rect.left = rect.right - GC->p.cx;
+				rect.bottom = g->g.Height - g->p.y;
+				rect.top = rect.bottom - g->p.cy;
+				rect.right = g->g.Width - g->p.x;
+				rect.left = rect.right - g->p.cx;
 				break;
 			case GDISP_ROTATE_270:
-				rect.bottom = GC->g.Width - GC->p.x;
-				rect.top = rect.bottom - GC->p.cx;
-				rect.left = GC->p.y;
-				rect.right = rect.left + GC->p.cy;
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom - g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left + g->p.cy;
 				break;
 			}
 		#else
-			rect.top = GC->p.y;
-			rect.bottom = rect.top + GC->p.cy;
-			rect.left = GC->p.x;
-			rect.right = rect.left + GC->p.cx;
+			rect.top = g->p.y;
+			rect.bottom = rect.top + g->p.cy;
+			rect.left = g->p.x;
+			rect.right = rect.left + g->p.cx;
 		#endif
 
 		hbr = CreateSolidBrush(color);
@@ -567,7 +420,7 @@ bool_t gdisp_lld_init(void) {
 	}
 #endif
 
-#if (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL) || defined(__DOXYGEN__)
+#if 0 && (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL)
 	static pixel_t *rotateimg(coord_t cx, coord_t cy, coord_t srcx, coord_t srccx, const pixel_t *buffer) {
 		pixel_t	*dstbuf;
 		pixel_t	*dst;
@@ -615,7 +468,7 @@ bool_t gdisp_lld_init(void) {
 	}
 #endif
 	
-#if GDISP_HARDWARE_BITFILLS
+#if 0 && GDISP_HARDWARE_BITFILLS
 	/**
 	 * @brief   Fill an area with a bitmap.
 	 * @note    Optional - The high level driver can emulate using software.
@@ -628,23 +481,13 @@ bool_t gdisp_lld_init(void) {
 	 *
 	 * @notapi
 	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
+	void gdisp_lld_blit_area(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
 		BITMAPV4HEADER bmpInfo;
 		RECT	rect;
 		#if GDISP_NEED_CONTROL
 			pixel_t	*srcimg;
 		#endif
 
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			// Clip pre orientation change
-			if (x < GC->g.clipx0) { cx -= GC->g.clipx0 - x; srcx += GC->g.clipx0 - x; x = GC->g.clipx0; }
-			if (y < GC->g.clipy0) { cy -= GC->g.clipy0 - y; srcy += GC->g.clipy0 - y; y = GC->g.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GC->g.clipx1 || y >= GC->g.clipy1) return;
-			if (x+cx > GC->g.clipx1)	cx = GC->g.clipx1 - x;
-			if (y+cy > GC->g.clipy1)	cy = GC->g.clipy1 - y;
-		#endif
-
 		// Make everything relative to the start of the line
 		buffer += srccx*srcy;
 		srcy = 0;
@@ -724,225 +567,142 @@ bool_t gdisp_lld_init(void) {
 	}
 #endif
 
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 * @return	The color of the specified pixel.
-	 *
-	 * @param[in] x, y     The start of the text
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
-		#if GDISP_NEED_CONTROL
-			coord_t		t;
-		#endif
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			// Clip pre orientation change
-			if (x < 0 || x >= GC->g.Width || y < 0 || y >= GC->g.Height) return 0;
-		#endif
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
+		COLORREF	color;
 
 		#if GDISP_NEED_CONTROL
-			switch(GC->g.Orientation) {
+			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
+				color = GetPixel(dcBuffer, g->p.x, g->p.y);
 				break;
 			case GDISP_ROTATE_90:
-				t = GC->g.Height - 1 - y;
-				y = x;
-				x = t;
+				color = GetPixel(dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
 				break;
 			case GDISP_ROTATE_180:
-				x = GC->g.Width - 1 - x;
-				y = GC->g.Height - 1 - y;
+				color = GetPixel(dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
 				break;
 			case GDISP_ROTATE_270:
-				t = GC->g.Width - 1 - x;
-				x = y;
-				y = t;
+				color = GetPixel(dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
 				break;
 			}
+		#else
+			color = GetPixel(dcBuffer, g->p.x, g->p.y);
 		#endif
 		
-		color = GetPixel(dcBuffer, x, y);
 		return BGR2COLOR(color);
 	}
 #endif
 
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		RECT	rect, frect, srect;
-		HBRUSH	hbr;
-		
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			// Clip pre orientation change
-			if (x < GC->g.clipx0) { cx -= GC->g.clipx0 - x; x = GC->g.clipx0; }
-			if (y < GC->g.clipy0) { cy -= GC->g.clipy0 - y; y = GC->g.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GC->g.clipx1 || y >= GC->g.clipy1) return;
-			if (x+cx > GC->g.clipx1)	cx = GC->g.clipx1 - x;
-			if (y+cy > GC->g.clipy1)	cy = GC->g.clipy1 - y;
-		#endif
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+	void gdisp_lld_vertical_scroll(GDISPDriver *g) {
+		HDC			dcScreen;
+		RECT		rect;
+		coord_t		lines;
 		
-		if (lines > cy) lines = cy;
-		else if (-lines > cy) lines = -cy;
-
-		bgcolor = COLOR2BGR(bgcolor);
-		hbr = CreateSolidBrush(bgcolor);
-
 		#if GDISP_NEED_CONTROL
 			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
-				rect.top = y;
-				rect.bottom = rect.top+cy;
-				rect.left = x;
-				rect.right = rect.left+cx;
-				lines = -lines;
+				rect.top = g->p.y;
+				rect.bottom = rect.top+g->p.cy;
+				rect.left = g->p.x;
+				rect.right = rect.left+g->p.cx;
+				lines = -g->p.y1;
 				goto vertical_scroll;
 			case GDISP_ROTATE_90:
-				rect.top = x;
-				rect.bottom = rect.top+cx;
-				rect.right = GC->g.Height - y;
-				rect.left = rect.right-cy;
+				rect.top = g->p.x;
+				rect.bottom = rect.top+g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right-g->p.cy;
+				lines = g->p.y1;
 				goto horizontal_scroll;
 			case GDISP_ROTATE_180:
-				rect.bottom = GC->g.Height - y;
-				rect.top = rect.bottom-cy;
-				rect.right = GC->g.Width - x;
-				rect.left = rect.right-cx;
+				rect.bottom = g->g.Height - g->p.y;
+				rect.top = rect.bottom-g->p.cy;
+				rect.right = GC->g.Width - g->p.x;
+				rect.left = rect.right-g->p.cx;
+				lines = g->p.y1;
 			vertical_scroll:
-				srect.left = frect.left = rect.left;
-				srect.right = frect.right = rect.right;
 				if (lines > 0) {
-					srect.top = frect.top = rect.top;
-					frect.bottom = rect.top+lines;
-					srect.bottom = rect.bottom-lines;
+					rect.bottom -= lines;
 				} else {
-					srect.bottom = frect.bottom = rect.bottom;
-					frect.top = rect.bottom+lines;
-					srect.top = rect.top-lines;
+					rect.top -= lines;
+				}
+				if (g->p.cy >= lines && g->p.cy >= -lines) {
+					dcScreen = GetDC(winRootWindow);
+					ScrollDC(dcBuffer, 0, lines, &rect, 0, 0, 0);
+					ScrollDC(dcScreen, 0, lines, &rect, 0, 0, 0);
+					ReleaseDC(winRootWindow, dcScreen);
 				}
-				if (cy >= lines && cy >= -lines)
-					ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
 				break;
 			case GDISP_ROTATE_270:
-				rect.bottom = GC->g.Width - x;
-				rect.top = rect.bottom-cx;
-				rect.left = y;
-				rect.right = rect.left+cy;
-				lines = -lines;
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom-g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left+g->p.cy;
+				lines = -g->p.y1;
 			horizontal_scroll:
-				srect.top = frect.top = rect.top;
-				srect.bottom = frect.bottom = rect.bottom;
 				if (lines > 0) {
-					srect.left = frect.left = rect.left;
-					frect.right = rect.left+lines;
-					srect.right = rect.right-lines;
+					rect.right -= lines;
 				} else {
-					srect.right = frect.right = rect.right;
-					frect.left = rect.right+lines;
-					srect.left = rect.left-lines;
+					rect.left -= lines;
+				}
+				if (g->p.cy >= lines && g->p.cy >= -lines) {
+					dcScreen = GetDC(winRootWindow);
+					ScrollDC(dcBuffer, lines, 0, &rect, 0, 0, 0);
+					ScrollDC(dcScreen, lines, 0, &rect, 0, 0, 0);
+					ReleaseDC(winRootWindow, dcScreen);
 				}
-				if (cy >= lines && cy >= -lines)
-					ScrollDC(dcBuffer, lines, 0, &srect, 0, 0, 0);
 				break;
 			}
 		#else
-			rect.top = y;
-			rect.bottom = rect.top+cy;
-			rect.left = x;
-			rect.right = rect.left+cx;
-			lines = -lines;
-			srect.left = frect.left = rect.left;
-			srect.right = frect.right = rect.right;
+			rect.top = g->p.y;
+			rect.bottom = rect.top+g->p.cy;
+			rect.left = g->p.x;
+			rect.right = rect.left+g->p.cx;
+			lines = -g->p.y1;
 			if (lines > 0) {
-				srect.top = frect.top = rect.top;
-				frect.bottom = rect.top+lines;
-				srect.bottom = rect.bottom-lines;
+				rect.bottom -= lines;
 			} else {
-				srect.bottom = frect.bottom = rect.bottom;
-				frect.top = rect.bottom+lines;
-				srect.top = rect.top-lines;
+				rect.top -= lines;
+			}
+			if (g->p.cy >= lines && g->p.cy >= -lines) {
+				dcScreen = GetDC(winRootWindow);
+				ScrollDC(dcBuffer, 0, lines, &rect, 0, 0, 0);
+				ScrollDC(dcScreen, 0, lines, &rect, 0, 0, 0);
+				ReleaseDC(winRootWindow, dcScreen);
 			}
-			if (cy >= lines && cy >= -lines)
-				ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
 		#endif
-		
-		if (hbr)
-			FillRect(dcBuffer, &frect, hbr);
-		InvalidateRect(winRootWindow, &rect, FALSE);
-		UpdateWindow(winRootWindow);
 	}
 #endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @detail	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+		switch(g->p.x) {
 		case GDISP_CONTROL_ORIENTATION:
-			if (GC->g.Orientation == (gdisp_orientation_t)value)
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-			switch((gdisp_orientation_t)value) {
+			switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
-					GC->g.Width = wWidth;
-					GC->g.Height = wHeight;
+					g->g.Width = wWidth;
+					g->g.Height = wHeight;
 					break;
 				case GDISP_ROTATE_90:
-					GC->g.Height = wWidth;
-					GC->g.Width = wHeight;
+					g->g.Height = wWidth;
+					g->g.Width = wHeight;
 					break;
 				case GDISP_ROTATE_180:
-					GC->g.Width = wWidth;
-					GC->g.Height = wHeight;
+					g->g.Width = wWidth;
+					g->g.Height = wHeight;
 					break;
 				case GDISP_ROTATE_270:
-					GC->g.Height = wWidth;
-					GC->g.Width = wHeight;
+					g->g.Height = wWidth;
+					g->g.Width = wHeight;
 					break;
 				default:
 					return;
 			}
-
-			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GC->g.clipx0 = 0;
-				GC->g.clipy0 = 0;
-				GC->g.clipx1 = GC->g.Width;
-				GC->g.clipy1 = GC->g.Height;
-			#endif
-			GC->g.Orientation = (gdisp_orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 /*
 		case GDISP_CONTROL_POWER:
@@ -954,25 +714,22 @@ bool_t gdisp_lld_init(void) {
 #endif
 
 #if GINPUT_NEED_MOUSE
-
 	void ginput_lld_mouse_init(void) {}
-
 	void ginput_lld_mouse_get_reading(MouseReading *pt) {
 		pt->x = mousex;
 		pt->y = mousey > wHeight ? wHeight : mousey;
 		pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
 		pt->buttons = mousebuttons;
 	}
-
 #endif /* GINPUT_NEED_MOUSE */
 
 #if GINPUT_NEED_TOGGLE
-
+	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
+		{0,	0xFF, 0x00, 0},
+	};
 	void ginput_lld_toggle_init(const GToggleConfig *ptc) { (void) ptc; }
 	unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { (void) ptc; return toggles; }
-
 #endif /* GINPUT_NEED_MOUSE */
 
 #endif /* GFX_USE_GDISP */
-/** @} */
 
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index 357febe4..4a526f07 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -25,19 +25,14 @@
 #define GDISP_DRIVER_NAME				"Win32"
 #define GDISP_DRIVER_STRUCT				GDISP_Win32
 
-#define GDISP_HARDWARE_STREAM			FALSE
-#define GDISP_HARDWARE_STREAM_END		FALSE
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
-#define GDISP_HARDWARE_CLEARS			FALSE
 #define GDISP_HARDWARE_FILLS			TRUE
+#define GDISP_HARDWARE_PIXELREAD		TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
 //#define GDISP_HARDWARE_BITFILLS			TRUE
-//#define GDISP_HARDWARE_SCROLL			TRUE
-//#define GDISP_HARDWARE_PIXELREAD		TRUE
-//#define GDISP_HARDWARE_CONTROL			TRUE
-#define GDISP_HARDWARE_QUERY			FALSE
-#define GDISP_HARDWARE_CLIP				FALSE
-
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
+#define GDISP_HARDWARE_SCROLL			TRUE
+
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From 973e34089e33f06cfd9ed560db968870e22c2b8a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 24 Sep 2013 16:10:15 +1000
Subject: GDISP streaming bug fixes Win32 bitmap support Win32 Rotation is back
 to front. Need to check touch and other drivers.

---
 drivers/multiple/Win32/gdisp_lld.c        | 192 ++++++++++++++----------------
 drivers/multiple/Win32/gdisp_lld_config.h |   2 +-
 2 files changed, 88 insertions(+), 106 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index d6c6b2fb..0f1a0b03 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -340,16 +340,16 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				y = g->p.y;
 				break;
 			case GDISP_ROTATE_90:
-				x = g->g.Height - 1 - g->p.y;
-				y = g->p.x;
+				x = g->p.y;
+				y = g->g.Width - 1 - g->p.x;
 				break;
 			case GDISP_ROTATE_180:
 				x = g->g.Width - 1 - g->p.x;
 				y = g->g.Height - 1 - g->p.y;
 				break;
 			case GDISP_ROTATE_270:
-				x = g->p.y;
-				y = g->g.Width - 1 - g->p.x;
+				x = g->g.Height - 1 - g->p.y;
+				y = g->p.x;
 				break;
 			}
 		#else
@@ -384,10 +384,10 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.right = rect.left + g->p.cx;
 				break;
 			case GDISP_ROTATE_90:
-				rect.top = g->p.x;
-				rect.bottom = rect.top + g->p.cx;
-				rect.right = g->g.Height - g->p.y;
-				rect.left = rect.right - g->p.cy;
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom - g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left + g->p.cy;
 				break;
 			case GDISP_ROTATE_180:
 				rect.bottom = g->g.Height - g->p.y;
@@ -396,10 +396,10 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.left = rect.right - g->p.cx;
 				break;
 			case GDISP_ROTATE_270:
-				rect.bottom = g->g.Width - g->p.x;
-				rect.top = rect.bottom - g->p.cx;
-				rect.left = g->p.y;
-				rect.right = rect.left + g->p.cy;
+				rect.top = g->p.x;
+				rect.bottom = rect.top + g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right - g->p.cy;
 				break;
 			}
 		#else
@@ -420,8 +420,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	}
 #endif
 
-#if 0 && (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL)
-	static pixel_t *rotateimg(coord_t cx, coord_t cy, coord_t srcx, coord_t srccx, const pixel_t *buffer) {
+#if GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL
+	static pixel_t *rotateimg(GDISPDriver *g, const pixel_t *buffer) {
 		pixel_t	*dstbuf;
 		pixel_t	*dst;
 		const pixel_t	*src;
@@ -429,37 +429,37 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		coord_t	i, j;
 
 		// Shortcut.
-		if (GC->g.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx)
+		if (g->g.Orientation == GDISP_ROTATE_0 && g->p.x1 == 0 && g->p.cx == g->p.x2)
 			return (pixel_t *)buffer;
 		
 		// Allocate the destination buffer
-		sz = (size_t)cx * (size_t)cy;
+		sz = (size_t)g->p.cx * (size_t)g->p.cy;
 		if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
 			return 0;
 		
 		// Copy the bits we need
-		switch(GC->g.Orientation) {
+		switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
-			for(dst = dstbuf, src = buffer+srcx, j = 0; j < cy; j++)
-				for(i = 0; i < cx; i++, src += srccx - cx)
+			for(dst = dstbuf, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx)
+				for(i = 0; i < g->p.cx; i++)
 					*dst++ = *src++;
 			break;
 		case GDISP_ROTATE_90:
-			for(src = buffer+srcx, j = 0; j < cy; j++) {
-				dst = dstbuf+cy-j-1;
-				for(i = 0; i < cx; i++, src += srccx - cx, dst += cy)
+			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
+				dst = dstbuf+sz-g->p.cy+j;
+				for(i = 0; i < g->p.cx; i++, dst -= g->p.cy)
 					*dst = *src++;
 			}
 			break;
 		case GDISP_ROTATE_180:
-			for(dst = dstbuf+sz, src = buffer+srcx, j = 0; j < cy; j++)
-				for(i = 0; i < cx; i++, src += srccx - cx)
+			for(dst = dstbuf+sz, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx)
+				for(i = 0; i < g->p.cx; i++)
 					*--dst = *src++;
 			break;
 		case GDISP_ROTATE_270:
-			for(src = buffer+srcx, j = 0; j < cy; j++) {
-				dst = dstbuf+sz-cy+j;
-				for(i = 0; i < cx; i++, src += srccx - cx, dst -= cy)
+			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
+				dst = dstbuf+g->p.cy-j-1;
+				for(i = 0; i < g->p.cx; i++, dst += g->p.cy)
 					*dst = *src++;
 			}
 			break;
@@ -468,34 +468,24 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	}
 #endif
 	
-#if 0 && GDISP_HARDWARE_BITFILLS
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
+#if GDISP_HARDWARE_BITFILLS
+	void gdisp_lld_blit_area(GDISPDriver *g) {
 		BITMAPV4HEADER bmpInfo;
-		RECT	rect;
+		HDC			dcScreen;
+		pixel_t	*	buffer;
 		#if GDISP_NEED_CONTROL
-			pixel_t	*srcimg;
+			RECT		rect;
+			pixel_t	*	srcimg;
 		#endif
 
 		// Make everything relative to the start of the line
-		buffer += srccx*srcy;
-		srcy = 0;
+		buffer = g->p.ptr;
+		buffer += g->p.x2*g->p.y1;
 		
 		memset(&bmpInfo, 0, sizeof(bmpInfo));
 		bmpInfo.bV4Size = sizeof(bmpInfo);
 		bmpInfo.bV4Planes = 1;
-		bmpInfo.bV4BitCount = 32;
+		bmpInfo.bV4BitCount = sizeof(pixel_t)*8;
 		bmpInfo.bV4AlphaMask = 0;
 		bmpInfo.bV4RedMask		= RGB2COLOR(255,0,0);
 		bmpInfo.bV4GreenMask	= RGB2COLOR(0,255,0);
@@ -508,62 +498,60 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		bmpInfo.bV4CSType = 0; //LCS_sRGB;
 
 		#if GDISP_NEED_CONTROL
-			bmpInfo.bV4SizeImage = (cy*cx) * sizeof(pixel_t);
-			srcimg = rotateimg(cx, cy, srcx, srccx, buffer);
+			bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
+			srcimg = rotateimg(g, buffer);
 			if (!srcimg) return;
 			
-			switch(GC->g.Orientation) {
+			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
-				bmpInfo.bV4Width = cx;
-				bmpInfo.bV4Height = -cy; /* top-down image */
-				rect.top = y;
-				rect.bottom = rect.top+cy;
-				rect.left = x;
-				rect.right = rect.left+cx;
+				bmpInfo.bV4Width = g->p.cx;
+				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
+				rect.top = g->p.y;
+				rect.bottom = rect.top+g->p.cy;
+				rect.left = g->p.x;
+				rect.right = rect.left+g->p.cx;
 				break;
 			case GDISP_ROTATE_90:
-				bmpInfo.bV4Width = cy;
-				bmpInfo.bV4Height = -cx; /* top-down image */
-				rect.top = x;
-				rect.bottom = rect.top+cx;
-				rect.right = GC->g.Height - y;
-				rect.left = rect.right-cy;
+				bmpInfo.bV4Width = g->p.cy;
+				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom-g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left+g->p.cy;
 				break;
 			case GDISP_ROTATE_180:
-				bmpInfo.bV4Width = cx;
-				bmpInfo.bV4Height = -cy; /* top-down image */
-				rect.bottom = GC->g.Height - y;
-				rect.top = rect.bottom-cy;
-				rect.right = GC->g.Width - x;
-				rect.left = rect.right-cx;
+				bmpInfo.bV4Width = g->p.cx;
+				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
+				rect.bottom = g->g.Height-1 - g->p.y;
+				rect.top = rect.bottom-g->p.cy;
+				rect.right = g->g.Width - g->p.x;
+				rect.left = rect.right-g->p.cx;
 				break;
 			case GDISP_ROTATE_270:
-				bmpInfo.bV4Width = cy;
-				bmpInfo.bV4Height = -cx; /* top-down image */
-				rect.bottom = GC->g.Width - x;
-				rect.top = rect.bottom-cx;
-				rect.left = y;
-				rect.right = rect.left+cy;
+				bmpInfo.bV4Width = g->p.cy;
+				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
+				rect.top = g->p.x;
+				rect.bottom = rect.top+g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right-g->p.cy;
 				break;
 			}
+			dcScreen = GetDC(winRootWindow);
 			SetDIBitsToDevice(dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-			if (srcimg != (pixel_t *)buffer)
+			SetDIBitsToDevice(dcScreen, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+			ReleaseDC(winRootWindow, dcScreen);
+			if (srcimg != buffer)
 				free(srcimg);
 			
 		#else
-			bmpInfo.bV4Width = srccx;
-			bmpInfo.bV4Height = -cy; /* top-down image */
-			bmpInfo.bV4SizeImage = (cy*srccx) * sizeof(pixel_t);
-			rect.top = y;
-			rect.bottom = rect.top+cy;
-			rect.left = x;
-			rect.right = rect.left+cx;
-			SetDIBitsToDevice(dcBuffer, x, y, cx, cy, srcx, 0, 0, cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+			bmpInfo.bV4Width = g->p.x2;
+			bmpInfo.bV4Height = -g->p.cy; /* top-down image */
+			bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
+			dcScreen = GetDC(winRootWindow);
+			SetDIBitsToDevice(dcBuffer, g->p.x, g->p.y, g->p.cx, g->p.cy, g->p.x1, 0, 0, g->p.cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+			SetDIBitsToDevice(dcScreen, g->p.x, g->p.y, g->p.cx, g->p.cy, g->p.x1, 0, 0, g->p.cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+			ReleaseDC(winRootWindow, dcScreen);
 		#endif
-
-		// Invalidate the region to get it on the screen.
-		InvalidateRect(winRootWindow, &rect, FALSE);
-		UpdateWindow(winRootWindow);
 	}
 #endif
 
@@ -577,13 +565,13 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				color = GetPixel(dcBuffer, g->p.x, g->p.y);
 				break;
 			case GDISP_ROTATE_90:
-				color = GetPixel(dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
+				color = GetPixel(dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
 				break;
 			case GDISP_ROTATE_180:
 				color = GetPixel(dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
 				break;
 			case GDISP_ROTATE_270:
-				color = GetPixel(dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
+				color = GetPixel(dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
 				break;
 			}
 		#else
@@ -610,11 +598,11 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				lines = -g->p.y1;
 				goto vertical_scroll;
 			case GDISP_ROTATE_90:
-				rect.top = g->p.x;
-				rect.bottom = rect.top+g->p.cx;
-				rect.right = g->g.Height - g->p.y;
-				rect.left = rect.right-g->p.cy;
-				lines = g->p.y1;
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom-g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left+g->p.cy;
+				lines = -g->p.y1;
 				goto horizontal_scroll;
 			case GDISP_ROTATE_180:
 				rect.bottom = g->g.Height - g->p.y;
@@ -636,11 +624,11 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				}
 				break;
 			case GDISP_ROTATE_270:
-				rect.bottom = g->g.Width - g->p.x;
-				rect.top = rect.bottom-g->p.cx;
-				rect.left = g->p.y;
-				rect.right = rect.left+g->p.cy;
-				lines = -g->p.y1;
+				rect.top = g->p.x;
+				rect.bottom = rect.top+g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right-g->p.cy;
+				lines = g->p.y1;
 			horizontal_scroll:
 				if (lines > 0) {
 					rect.right -= lines;
@@ -684,17 +672,11 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				return;
 			switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
-					g->g.Width = wWidth;
-					g->g.Height = wHeight;
-					break;
-				case GDISP_ROTATE_90:
-					g->g.Height = wWidth;
-					g->g.Width = wHeight;
-					break;
 				case GDISP_ROTATE_180:
 					g->g.Width = wWidth;
 					g->g.Height = wHeight;
 					break;
+				case GDISP_ROTATE_90:
 				case GDISP_ROTATE_270:
 					g->g.Height = wWidth;
 					g->g.Width = wHeight;
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index 4a526f07..b8a030ef 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -29,7 +29,7 @@
 #define GDISP_HARDWARE_FILLS			TRUE
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
-//#define GDISP_HARDWARE_BITFILLS			TRUE
+#define GDISP_HARDWARE_BITFILLS			TRUE
 #define GDISP_HARDWARE_SCROLL			TRUE
 
 #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
-- 
cgit v1.2.3


From 30154560b6f588c42032bce94152676c3756124e Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 25 Sep 2013 17:17:05 +1000
Subject: Rename a macro and fix some bugs

---
 drivers/multiple/Win32/gdisp_lld.c | 6 ------
 1 file changed, 6 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 0f1a0b03..f55f3700 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -287,12 +287,6 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/**
- * @brief   Low level GDISP driver initialization.
- * @return	TRUE if successful, FALSE on error.
- *
- * @notapi
- */
 LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	RECT			rect;
 	gfxThreadHandle	hth;
-- 
cgit v1.2.3


From 5eabbaf7bf34463b52fb8deb96ff6df0f5a851ec Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 25 Sep 2013 17:18:18 +1000
Subject: Nokia6610 streaming driver. Orientation not supported yet in this new
 driver version.

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             | 347 +++++++++++----------
 .../Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h |  24 +-
 .../gdisp/Nokia6610GE8/gdisp_lld_board_template.h  |  14 +
 drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h      |   8 +-
 4 files changed, 222 insertions(+), 171 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index ba5178d8..e16c6d5c 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -15,18 +15,40 @@
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
+
+/**
+ * This is for the EPSON (GE8) controller driving a Nokia6610 color LCD display.
+ * Note that there is also a PHILIPS (GE12) controller for the same display that this code
+ * does not support.
+ *
+ * The controller drives a 132x132 display but a 1 pixel surround is not visible
+ * which gives a visible area of 130x130.
+ *
+ * This controller does not support reading back over the SPI interface.
+ * Additionally, the Olimex board doesn't even connect the pin.
+ *
+ * The hardware is capable of doing full width vertical scrolls aligned
+ * on a 4 line boundary however that is not sufficient to support general vertical scrolling.
+ * We also can't manually do read/modify scrolling because we can't read in SPI mode.
+ *
+ * The controller has some quirkyness when operating in other than rotation 0 mode.
+ * When any direction is decremented it starts at location 0 rather than the end of
+ * the area.
+ *
+ * Some of the more modern controllers have a broken command set. If you have one of these
+ * you will recognise it by the colors being off on anything drawn after an odd (as opposed to
+ * even) pixel count area being drawn. If so then set GDISP_GE8_BROKEN_CONTROLLER to TRUE
+ * on your gdisp_lld_board.h file.
+ */
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
 
-#include "GE8.h"
-
-/* This controller is only ever used with a 130 x 130 display */
 #if defined(GDISP_SCREEN_HEIGHT)
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
 	#undef GDISP_SCREEN_HEIGHT
@@ -35,17 +57,40 @@
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
 	#undef GDISP_SCREEN_WIDTH
 #endif
-#define GDISP_SCREEN_HEIGHT		130
-#define GDISP_SCREEN_WIDTH		130
 
-#define GDISP_SCAN_LINES		132		/* 130 lines + 2 invisible lines */
-#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
-#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
-#define GDISP_SLEEP_SIZE		32		/* Sleep mode window lines */
-#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2)
+#include "GE8.h"
+#include "gdisp_lld_board.h"
 
-#define GDISP_INITIAL_CONTRAST	38
-#define GDISP_INITIAL_BACKLIGHT	100
+#define GDISP_SCAN_LINES			132
+
+// Set parameters if they are not already set
+#ifndef GDISP_GE8_BROKEN_CONTROLLER
+	#define GDISP_GE8_BROKEN_CONTROLLER		TRUE
+#endif
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		130
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		130
+#endif
+#ifndef GDISP_RAM_X_OFFSET
+	#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_RAM_Y_OFFSET
+	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_SLEEP_SIZE
+	#define GDISP_SLEEP_SIZE		32		/* Sleep mode window lines */
+#endif
+#ifndef GDISP_SLEEP_POS
+	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2)
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	38
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver exported variables.                                                */
@@ -55,12 +100,18 @@
 /* Driver local variables.                                                   */
 /*===========================================================================*/
 
+static color_t savecolor;
+#if GDISP_GE8_BROKEN_CONTROLLER
+	static color_t firstcolor;
+#endif
+
+#define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_RUNBYTE	(GDISP_FLG_DRIVER<<1)
+
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
-
 // Some macros just to make reading the code easier
 #define delayms(ms)						gfxSleepMilliseconds(ms)
 #define write_data2(d1, d2)				{ write_data(d1); write_data(d2); }
@@ -71,29 +122,6 @@
 #define write_cmd3(cmd, d1, d2, d3)		{ write_cmd(cmd); write_data3(d1, d2, d3); }
 #define write_cmd4(cmd, d1, d2, d3, d4)	{ write_cmd(cmd); write_data4(d1, d2, d3, d4); }
 
-// Set the drawing window on the controller.
-// An inline function has been used here incase the parameters have side effects with the internal calculations.
-static __inline void setviewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-			write_cmd2(CASET, GDISP_RAM_X_OFFSET+x, GDISP_RAM_X_OFFSET+x+cx-1);			// Column address set
-			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+y, GDISP_RAM_Y_OFFSET+y+cy-1);			// Page address set
-			break;
-		case GDISP_ROTATE_90:
-			write_cmd2(CASET, GDISP_RAM_X_OFFSET+GDISP.Height-y-cy, GDISP_RAM_X_OFFSET+GDISP.Height-y-1);
-			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+x, GDISP_RAM_Y_OFFSET+x+cx-1);
-			break;
-		case GDISP_ROTATE_180:
-			write_cmd2(CASET, GDISP_RAM_X_OFFSET+GDISP.Width-x-cx, GDISP_RAM_X_OFFSET+GDISP.Width-x-1);
-			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+GDISP.Height-y-cy, GDISP_RAM_Y_OFFSET+GDISP.Height-y-1);
-			break;
-		case GDISP_ROTATE_270:
-			write_cmd2(CASET, GDISP_RAM_X_OFFSET+y, GDISP_RAM_X_OFFSET+y+cy-1);
-			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+GDISP.Width-x-cx, GDISP_RAM_Y_OFFSET+GDISP.Width-x-1);
-			break;
-	}
-}
-
 /*===========================================================================*/
 /* Driver interrupt handlers.                                                */
 /*===========================================================================*/
@@ -102,12 +130,7 @@ static __inline void setviewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/**
- * @brief   Low level GDISP driver initialisation.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
 	init_board();
 
@@ -147,43 +170,115 @@ bool_t gdisp_lld_init(void) {
 	set_backlight(GDISP_INITIAL_BACKLIGHT);
 
 	/* Initialise the GDISP structure to match */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	g->g.Orientation = GDISP_ROTATE_0;
+	g->g.Powermode = powerOn;
+	g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
+	g->g.Contrast = GDISP_INITIAL_CONTRAST;
+	g->g.Width = GDISP_SCREEN_WIDTH;
+	g->g.Height = GDISP_SCREEN_HEIGHT;
 	return TRUE;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
+LLDSPEC	void gdisp_lld_stream_start(GDISPDriver *g) {
 	acquire_bus();
-	setviewport(x, y, 1, 1);
-	write_cmd3(RAMWR, 0, (color>>8) & 0x0F, color & 0xFF);
-	release_bus();
+	#if GDISP_NEED_CONTROL
+		switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+				write_cmd(RAMWR);
+				break;
+			case GDISP_ROTATE_90:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
+				write_cmd(RAMWR);
+				break;
+			case GDISP_ROTATE_180:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-1);
+				write_cmd(RAMWR);
+				break;
+			case GDISP_ROTATE_270:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y+g->p.cy-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-1);
+				write_cmd(RAMWR);
+				break;
+		}
+	#else
+		write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+		write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+		write_cmd(RAMWR);
+	#endif
+	g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
 }
 
+LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
+	//write_data2(((g->p.color >> 8)&0xFF), (g->p.color & 0xFF));
+
+	#if GDISP_GE8_BROKEN_CONTROLLER
+		if (!(g->flags & GDISP_FLG_RUNBYTE)) {
+			firstcolor = g->p.color;
+			g->flags |= GDISP_FLG_RUNBYTE;
+		}
+	#endif
+	if ((g->flags & GDISP_FLG_ODDBYTE)) {
+		// Write the pair of pixels to the display
+		write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+		g->flags &= ~GDISP_FLG_ODDBYTE;
+	} else {
+		savecolor = g->p.color;
+		g->flags |= GDISP_FLG_ODDBYTE;
+	}
+}
+
+#if GDISP_HARDWARE_STREAM_STOP
+	LLDSPEC	void gdisp_lld_stream_stop(GDISPDriver *g) {
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			#if GDISP_GE8_BROKEN_CONTROLLER
+				/**
+				 * We have a real problem here - we need to write a singular pixel
+				 * Methods that are supposed to work...
+				 * 1/ Write the pixel (2 bytes) and then send a NOP command. This doesn't work, the pixel doesn't get written
+				 * 		and it is maintained in the latch where it causes problems for the next window.
+				 * 2/ Just write a dummy extra pixel as stuff beyond the window gets discarded. This doesn't work as contrary to
+				 * 		the documentation the buffer wraps and the first pixel gets overwritten.
+				 * 3/ Put the controller in 16 bits per pixel Type B mode where each pixel is performed by writing two bytes. This
+				 * 		also doesn't work as the controller refuses to enter Type B mode (it stays in Type A mode).
+				 *
+				 * These methods might work on some controllers - just not on the one of the broken versions.
+				 *
+				 * For these broken controllers:
+				 * 	We know we can wrap to the first byte (just overprint it) if we are at the end of the stream area.
+				 * 	If not, we need to create a one pixel by one pixel window to fix this - Uuch. Fortunately this should only happen if the
+				 * 	user application uses the streaming calls and then terminates the stream early or after buffer wrap.
+				 * 	Since this is such an unlikely situation we just don't handle it.
+				 */
+				write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((firstcolor >> 8) & 0x0F)), (firstcolor & 0xFF));
+			#else
+				write_data2(((savecolor >> 4) & 0xFF), ((savecolor << 4) & 0xF0));
+				write_cmd(NOP);
+			#endif
+		}
+
+		release_bus();
+	}
+#endif
+
+#if 0
+	void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
+		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+			if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+		#endif
+		acquire_bus();
+		setviewport(x, y, 1, 1);
+		write_cmd3(RAMWR, 0, (color>>8) & 0x0F, color & 0xFF);
+		release_bus();
+	}
+#endif
+
 /* ---- Optional Routines ---- */
 
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
+#if 0 && GDISP_HARDWARE_FILLS
 	/**
 	 * @brief   Fill an area with a color.
 	 *
@@ -216,7 +311,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 	}
 #endif
 
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
+#if 0 && GDISP_HARDWARE_BITFILLS
 	/**
 	 * @brief   Fill an area with a bitmap.
 	 *
@@ -343,8 +438,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 
 				/* Get the next pixel */
 				switch(pnum++ & 1) {
-				case 0:		c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);				break;
-				case 1:		c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	p += 3;		break;
+				case 0:		c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);				break;
+				case 1:		c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	p += 3;		break;
 				}
 
 				/* Check for line or buffer wrapping */
@@ -369,80 +464,20 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 	}
 #endif
 
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The start of the text
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		/* NOT IMPLEMENTED */
-		/* This controller does not support reading back over the SPI interface.
-		 * Additionally, the Olimex board doesn't even connect the pin.
-		 */
-	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		/* NOT IMPLEMENTED */
-		/**
-		 * The hardware is capable of doing full width vertical scrolls aligned
-		 * on a 4 line boundary however that is not sufficient to support this routine.
-		 *
-		 * We also can't manually do read/modify scrolling because we can't read in SPI mode.
-		 */
-	}
-#endif
-
-#if GDISP_HARDWARE_CONTROL || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
+#if 0 && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
 		/* The hardware is capable of supporting...
 		 * 	GDISP_CONTROL_POWER				- supported
 		 * 	GDISP_CONTROL_ORIENTATION		- supported
 		 * 	GDISP_CONTROL_BACKLIGHT			- supported
 		 * 	GDISP_CONTROL_CONTRAST			- supported
 		 */
-		switch(what) {
+		switch(g->p.x) {
 		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
 				return;
 			acquire_bus();
-			switch((gdisp_powermode_t)value) {
+			switch((powermode_t)g->p.ptr) {
 				case powerOff:
 					set_backlight(0);									// Turn off the backlight
 					write_cmd(DISOFF);									// Turn off the display
@@ -485,13 +520,13 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 					return;
 			}
 			release_bus();
-			GDISP.Powermode = (gdisp_powermode_t)value;
+			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
 		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
 			acquire_bus();
-			switch((gdisp_orientation_t)value) {
+			switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
 					write_cmd3(DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
 					GDISP.Height = GDISP_SCREEN_HEIGHT;
@@ -517,25 +552,19 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 					return;
 			}
 			release_bus();
-			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 		case GDISP_CONTROL_BACKLIGHT:
-			if ((unsigned)value > 100) value = (void *)100;
-			set_backlight((unsigned)value);
-			GDISP.Backlight = (unsigned)value;
+			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
+			set_backlight((unsigned)g->p.ptr);
+			g->g.Backlight = (unsigned)g->p.ptr;
 			return;
 		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)value > 100) value = (void *)100;
+			if ((unsigned)value > 100) g->p.ptr = (void *)100;
 			acquire_bus();
-			write_cmd2(VOLCTR, (unsigned)value, 0x03);
+			write_cmd2(VOLCTR, (unsigned)g->p.ptr, 0x03);
 			release_bus();
-			GDISP.Contrast = (unsigned)value;
+			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
 		}
 	}
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
index 90a1277b..8afc3573 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
@@ -16,6 +16,20 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_GE8_BROKEN_CONTROLLER		FALSE	// Uncomment this out if you have a controller thats not window wrap broken.
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_SIZE					32		// The size of the sleep mode partial display
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			38		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
 // ******************************************************
 // Pointers to AT91SAM7X256 peripheral data structures
 // ******************************************************
@@ -98,14 +112,10 @@ static inline void init_board(void) {
 	pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
 
 	// Fixed mode
-	pSPI->SPI_CR      = 0x81;               //SPI Enable, Sowtware reset
+	pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
 	pSPI->SPI_CR      = 0x01;               //SPI Enable
-
-	//pSPI->SPI_MR      = 0xE0019;            //Master mode, fixed select, disable decoder, FDIV=1 (MCK), PCS=1110
-	pSPI->SPI_MR      = 0xE0011;          //Master mode, fixed select, disable decoder, FDIV=0 (MCK), PCS=1110
-
-	//pSPI->SPI_CSR[0]  = 0x01010C11;           //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/32*12 = 125kHz
-	pSPI->SPI_CSR[0]  = 0x01010311;        //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz if using commented MR line above
+	pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
+	pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
 
 	/* Display backlight control at 100% */
 	pwmRunning = FALSE;
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
index a1fa6050..43cc4830 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
@@ -16,6 +16,20 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_GE8_BROKEN_CONTROLLER		FALSE	// Uncomment this out if you have a controller thats not window wrap broken.
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_SIZE					32		// The size of the sleep mode partial display
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			38		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
 /**
  * @brief   Initialise the board for the display.
  * @notes	Performs the following functions:
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
index 1a748684..e6834d13 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -23,14 +23,12 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"Nokia6610GE8"
+#define GDISP_DRIVER_STRUCT				GDISP_Nokia6610GE8
 
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
+#define GDISP_HARDWARE_STREAM			TRUE
+#define GDISP_HARDWARE_STREAM_STOP		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_SOFTWARE_TEXTFILLDRAW		FALSE
-#define GDISP_SOFTWARE_TEXTBLITCOLUMN	FALSE
-
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
 /* This driver supports both packed and unpacked pixel formats and line formats.
  * 	By default we leave these as FALSE.
-- 
cgit v1.2.3


From a8688eef3923dd85afb02a5bb4761a572c0cfc51 Mon Sep 17 00:00:00 2001
From: Petteri Aimonen <jpa@git.mail.kapsi.fi>
Date: Tue, 24 Sep 2013 22:15:55 +0300
Subject: Add driver for ED060SC4 e-ink display panel

---
 drivers/gdisp/ED060SC4/ed060sc4.h                 |  16 +
 drivers/gdisp/ED060SC4/example_schematics.png     | Bin 0 -> 305333 bytes
 drivers/gdisp/ED060SC4/gdisp_lld.c                | 606 ++++++++++++++++++++++
 drivers/gdisp/ED060SC4/gdisp_lld.mk               |   2 +
 drivers/gdisp/ED060SC4/gdisp_lld_board_example.h  | 127 +++++
 drivers/gdisp/ED060SC4/gdisp_lld_board_template.h |  83 +++
 drivers/gdisp/ED060SC4/gdisp_lld_config.h         |  27 +
 drivers/gdisp/ED060SC4/readme.txt                 |  85 +++
 8 files changed, 946 insertions(+)
 create mode 100644 drivers/gdisp/ED060SC4/ed060sc4.h
 create mode 100644 drivers/gdisp/ED060SC4/example_schematics.png
 create mode 100644 drivers/gdisp/ED060SC4/gdisp_lld.c
 create mode 100644 drivers/gdisp/ED060SC4/gdisp_lld.mk
 create mode 100644 drivers/gdisp/ED060SC4/gdisp_lld_board_example.h
 create mode 100644 drivers/gdisp/ED060SC4/gdisp_lld_board_template.h
 create mode 100644 drivers/gdisp/ED060SC4/gdisp_lld_config.h
 create mode 100644 drivers/gdisp/ED060SC4/readme.txt

(limited to 'drivers')

diff --git a/drivers/gdisp/ED060SC4/ed060sc4.h b/drivers/gdisp/ED060SC4/ed060sc4.h
new file mode 100644
index 00000000..8a38f135
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/ed060sc4.h
@@ -0,0 +1,16 @@
+/*
+ * 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 _ED060SC4_H_
+#define _ED060SC4_H_
+
+#include "gfx.h"
+
+/* Control command for flushing all data to display. */
+#define GDISP_CONTROL_FLUSH (GDISP_CONTROL_LLD + 0)
+
+#endif
diff --git a/drivers/gdisp/ED060SC4/example_schematics.png b/drivers/gdisp/ED060SC4/example_schematics.png
new file mode 100644
index 00000000..0d9d095f
Binary files /dev/null and b/drivers/gdisp/ED060SC4/example_schematics.png differ
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld.c b/drivers/gdisp/ED060SC4/gdisp_lld.c
new file mode 100644
index 00000000..fcc03944
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/gdisp_lld.c
@@ -0,0 +1,606 @@
+/*
+ * 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
+ */
+
+/* Low-level E-ink panel driver routines for ED060SC4. */
+
+#include "gfx.h"
+#include "ed060sc4.h"
+
+#if GFX_USE_GDISP
+
+#include "gdisp/lld/emulation.c"
+
+/* =================================
+ *      Default configuration
+ * ================================= */
+
+#ifndef GDISP_SCREEN_HEIGHT
+#       define GDISP_SCREEN_HEIGHT 600
+#endif
+
+#ifndef GDISP_SCREEN_WIDTH
+#       define GDISP_SCREEN_WIDTH 800
+#endif
+
+/* Number of pixels per byte */
+#ifndef EINK_PPB
+#       define EINK_PPB 4
+#endif
+
+/* Delay for generating clock pulses.
+ * Unit is approximate clock cycles of the CPU (0 to 15).
+ * This should be atleast 50 ns.
+ */
+#ifndef EINK_CLOCKDELAY
+#       define EINK_CLOCKDELAY 0
+#endif
+
+/* Width of one framebuffer block.
+ * Must be divisible by EINK_PPB and evenly divide GDISP_SCREEN_WIDTH. */
+#ifndef EINK_BLOCKWIDTH
+#       define EINK_BLOCKWIDTH 20
+#endif
+
+/* Height of one framebuffer block.
+ * Must evenly divide GDISP_SCREEN_WIDTH. */
+#ifndef EINK_BLOCKHEIGHT
+#       define EINK_BLOCKHEIGHT 20
+#endif
+
+/* Number of block buffers to use for framebuffer emulation. */
+#ifndef EINK_NUMBUFFERS
+#       define EINK_NUMBUFFERS 40
+#endif
+
+/* Do a "blinking" clear, i.e. clear to opposite polarity first.
+ * This reduces the image persistence. */
+#ifndef EINK_BLINKCLEAR
+#       define EINK_BLINKCLEAR TRUE
+#endif
+
+/* Number of passes to use when clearing the display */
+#ifndef EINK_CLEARCOUNT
+#       define EINK_CLEARCOUNT 10
+#endif
+
+/* Number of passes to use when writing to the display */
+#ifndef EINK_WRITECOUNT
+#       define EINK_WRITECOUNT 4
+#endif
+
+/* ====================================
+ *      Lower level driver functions
+ * ==================================== */
+
+#include "gdisp_lld_board.h"
+
+/** Delay between signal changes, to give time for IO pins to change state. */
+static inline void clockdelay()
+{
+	#if EINK_CLOCKDELAY & 1
+	asm("nop");
+	#endif
+	#if EINK_CLOCKDELAY & 2
+	asm("nop");
+	asm("nop");
+	#endif
+	#if EINK_CLOCKDELAY & 4
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	#endif
+	#if EINK_CLOCKDELAY & 8
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	#endif
+}
+
+/** Fast vertical clock pulse for gate driver, used during initializations */
+static void vclock_quick()
+{
+	setpin_ckv(TRUE);
+	eink_delay(1);
+	setpin_ckv(FALSE);
+	eink_delay(4);
+}
+
+/** Horizontal clock pulse for clocking data into source driver */
+static void hclock()
+{
+	clockdelay();
+	setpin_cl(TRUE);
+	clockdelay();
+	setpin_cl(FALSE);
+}
+
+/** Start a new vertical gate driver scan from top.
+ * Note: Does not clear any previous bits in the shift register,
+ *       so you should always scan through the whole display before
+ *       starting a new scan.
+ */
+static void vscan_start()
+{
+	setpin_gmode(TRUE);
+	vclock_quick();
+	setpin_spv(FALSE);
+	vclock_quick();
+	setpin_spv(TRUE);
+	vclock_quick();
+}
+
+/** Waveform for strobing a row of data onto the display.
+ * Attempts to minimize the leaking of color to other rows by having
+ * a long idle period after a medium-length strobe period.
+ */
+static void vscan_write()
+{
+	setpin_ckv(TRUE);
+	setpin_oe(TRUE);
+	eink_delay(5);
+	setpin_oe(FALSE);
+	setpin_ckv(FALSE);
+	eink_delay(200);
+}
+
+/** Waveform used when clearing the display. Strobes a row of data to the
+ * screen, but does not mind some of it leaking to other rows.
+ */
+static void vscan_bulkwrite()
+{
+	setpin_ckv(TRUE);
+	eink_delay(20);
+	setpin_ckv(FALSE);
+	eink_delay(200);
+}
+
+/** Waveform for skipping a vertical row without writing anything.
+ * Attempts to minimize the amount of change in any row.
+ */
+static void vscan_skip()
+{
+	setpin_ckv(TRUE);
+	eink_delay(1);
+	setpin_ckv(FALSE);
+	eink_delay(100);
+}
+
+/** Stop the vertical scan. The significance of this escapes me, but it seems
+ * necessary or the next vertical scan may be corrupted.
+ */
+static void vscan_stop()
+{
+	setpin_gmode(FALSE);
+	vclock_quick();
+	vclock_quick();
+	vclock_quick();
+	vclock_quick();
+	vclock_quick();
+}
+
+/** Start updating the source driver data (from left to right). */
+static void hscan_start()
+{
+	/* Disable latching and output enable while we are modifying the row. */
+	setpin_le(FALSE);
+	setpin_oe(FALSE);
+	
+	/* The start pulse should remain low for the duration of the row. */
+	setpin_sph(FALSE);
+}
+
+/** Write data to the horizontal row. */
+static void hscan_write(const uint8_t *data, int count)
+{
+	while (count--)
+	{
+		/* Set the next byte on the data pins */
+		setpins_data(*data++);
+		
+		/* Give a clock pulse to the shift register */
+		hclock();
+	}
+}
+
+/** Finish and transfer the row to the source drivers.
+ * Does not set the output enable, so the drivers are not yet active. */
+static void hscan_stop()
+{
+	/* End the scan */
+	setpin_sph(TRUE);
+	hclock();
+	
+	/* Latch the new data */
+	setpin_le(TRUE);
+	clockdelay();
+	setpin_le(FALSE);
+}
+
+/** Turn on the power to the E-Ink panel, observing proper power sequencing. */
+static void power_on()
+{
+	unsigned i;
+	
+	/* First the digital power supply and signal levels. */
+	setpower_vdd(TRUE);
+	setpin_le(FALSE);
+	setpin_oe(FALSE);
+	setpin_cl(FALSE);
+	setpin_sph(TRUE);
+	setpins_data(0);
+	setpin_ckv(FALSE);
+	setpin_gmode(FALSE);
+	setpin_spv(TRUE);
+	
+	/* Min. 100 microsecond delay after digital supply */
+	gfxSleepMicroseconds(100);
+	
+	/* Then negative voltages and min. 1000 microsecond delay. */
+	setpower_vneg(TRUE);
+	gfxSleepMicroseconds(1000);
+	
+	/* Finally the positive voltages. */
+	setpower_vpos(TRUE);
+	
+	/* Clear the vscan shift register */
+	vscan_start();
+	for (i = 0; i < GDISP_SCREEN_HEIGHT; i++)
+		vclock_quick();
+	vscan_stop();
+}
+
+/** Turn off the power, observing proper power sequencing. */
+static void power_off()
+{
+	/* First the high voltages */
+	setpower_vpos(FALSE);
+	setpower_vneg(FALSE);
+	
+	/* Wait for any capacitors to drain */
+	gfxSleepMilliseconds(100);
+	
+	/* Then put all signals and digital supply to ground. */
+	setpin_le(FALSE);
+	setpin_oe(FALSE);
+	setpin_cl(FALSE);
+	setpin_sph(FALSE);
+	setpins_data(0);
+	setpin_ckv(FALSE);
+	setpin_gmode(FALSE);
+	setpin_spv(FALSE);
+	setpower_vdd(FALSE);
+}
+
+/* ====================================
+ *      Framebuffer emulation layer
+ * ==================================== */
+
+#if EINK_PPB == 4
+#define PIXELMASK 3
+#define PIXEL_WHITE 2
+#define PIXEL_BLACK 1
+#define BYTE_WHITE 0xAA
+#define BYTE_BLACK 0x55
+#else
+#error Unsupported EINK_PPB value.
+#endif
+
+#if GDISP_SCREEN_HEIGHT % EINK_BLOCKHEIGHT != 0
+#error GDISP_SCREEN_HEIGHT must be evenly divisible by EINK_BLOCKHEIGHT
+#endif
+
+#if GDISP_SCREEN_WIDTH % EINK_BLOCKWIDTH != 0
+#error GDISP_SCREEN_WIDTH must be evenly divisible by EINK_BLOCKWIDTH
+#endif
+
+#if EINK_BLOCKWIDTH % EINK_PPB != 0
+#error EINK_BLOCKWIDTH must be evenly divisible by EINK_PPB
+#endif
+
+#if EINK_NUMBUFFERS > 254
+#error EINK_NUMBUFFERS must be at most 254.
+#endif
+
+#define BLOCKS_Y (GDISP_SCREEN_HEIGHT / EINK_BLOCKHEIGHT)
+#define BLOCKS_X (GDISP_SCREEN_WIDTH / EINK_BLOCKWIDTH)
+#define WIDTH_BYTES (EINK_BLOCKWIDTH / EINK_PPB)
+
+/* Buffers that store the data for a small area of the display. */
+typedef struct {
+	uint8_t data[EINK_BLOCKHEIGHT][WIDTH_BYTES];
+} block_t;
+
+static uint8_t g_next_block; /* Index of the next free block buffer. */
+static block_t g_blocks[EINK_NUMBUFFERS];
+
+/* Map that stores the buffers associated to each area of the display.
+ * Value of 0 means that the block is not allocated.
+ * Other values are the index in g_blocks + 1.
+ */
+static uint8_t g_blockmap[BLOCKS_Y][BLOCKS_X]; 
+
+/** Check if the row contains any allocated blocks. */
+static bool_t blocks_on_row(unsigned by)
+{
+	unsigned bx;
+	for (bx = 0; bx < BLOCKS_X; bx++)
+	{
+		if (g_blockmap[by][bx] != 0)
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/** Write out a block row. */
+static void write_block_row(unsigned by)
+{
+	unsigned bx, dy, dx;
+	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+	{
+		hscan_start();
+		for (bx = 0; bx < BLOCKS_X; bx++)
+		{
+			if (g_blockmap[by][bx] == 0)
+			{
+				for (dx = 0; dx < WIDTH_BYTES; dx++)
+				{
+					const uint8_t dummy = 0;
+					hscan_write(&dummy, 1);
+				}
+			}
+			else
+			{
+				block_t *block = &g_blocks[g_blockmap[by][bx] - 1];
+				hscan_write(&block->data[dy][0], WIDTH_BYTES);
+			}
+		}
+		hscan_stop();
+		
+		vscan_write();
+	}
+}
+
+/** Clear the block map, i.e. deallocate all blocks */
+static void clear_block_map()
+{
+	unsigned bx, by;
+	for (by = 0; by < BLOCKS_Y; by++)
+	{
+		for (bx = 0; bx < BLOCKS_X; bx++)
+		{
+			g_blockmap[by][bx] = 0;
+		}
+	}
+	
+	g_next_block = 0;
+}
+
+/** Flush all the buffered rows to display. */
+static void flush_buffers()
+{
+	unsigned by, dy, i;
+	
+	for (i = 0; i < EINK_WRITECOUNT; i++)
+	{
+		vscan_start();
+		
+		for (by = 0; by < BLOCKS_Y; by++)
+		{
+			if (!blocks_on_row(by))
+			{
+				/* Skip the whole row of blocks. */
+				for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+				{
+					vscan_skip();
+				}
+			}
+			else
+			{
+				/* Write out the blocks. */
+				write_block_row(by);
+			}
+		}
+		
+		vscan_stop();
+	}
+	
+	clear_block_map();
+}
+
+/** Initialize a newly allocated block. */
+static void zero_block(block_t *block)
+{
+	unsigned dx, dy;
+	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+	{
+		for (dx = 0; dx < WIDTH_BYTES; dx++)
+		{
+			block->data[dy][dx] = 0;
+		}
+	}
+}
+
+/** Allocate a buffer
+ * Automatically flushes if all buffers are full. */
+static block_t *alloc_buffer(unsigned bx, unsigned by)
+{
+	block_t *result;
+	if (g_blockmap[by][bx] == 0)
+	{
+		if (g_next_block >= EINK_NUMBUFFERS)
+		{
+			flush_buffers();
+		}
+		
+		result = &g_blocks[g_next_block];
+		g_blockmap[by][bx] = g_next_block + 1;
+		g_next_block++;
+		zero_block(result);
+		return result;
+	}
+	else
+	{
+		result = &g_blocks[g_blockmap[by][bx] - 1];
+		return result;
+	}
+}
+
+/* ===============================
+ *         Public functions
+ * =============================== */
+
+bool_t gdisp_lld_init(void)
+{
+	init_board();
+	
+	/* Make sure that all the pins are in "off" state.
+	 * Having any pin high could cause voltage leaking to the
+	 * display, which in turn causes the image to leak slowly away.
+	 */
+	power_off();
+	
+	clear_block_map();
+	
+	/* Initialize the global GDISP structure */
+	GDISP.Width = GDISP_SCREEN_WIDTH;
+	GDISP.Height = GDISP_SCREEN_HEIGHT;
+	GDISP.Orientation = GDISP_ROTATE_0;
+	GDISP.Powermode = powerOff;
+	GDISP.Backlight = 0;
+	GDISP.Contrast = 0;
+	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
+	GDISP.clipx0 = 0;
+	GDISP.clipy0 = 0;
+	GDISP.clipx1 = GDISP.Width;
+	GDISP.clipy1 = GDISP.Height;
+	#endif
+	
+	return TRUE;
+}
+
+void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color)
+{
+	block_t *block;
+	uint8_t byte;
+	unsigned bx, by, dx, dy;
+	uint8_t bitpos;
+	
+	bx = x / EINK_BLOCKWIDTH;
+	by = y / EINK_BLOCKHEIGHT;
+	dx = x % EINK_BLOCKWIDTH;
+	dy = y % EINK_BLOCKHEIGHT;
+	
+	if (bx < 0 || bx >= BLOCKS_X || by < 0 || by >= BLOCKS_Y)
+		return;
+	
+	block = alloc_buffer(bx, by);
+	
+	bitpos = (6 - 2 * (dx % EINK_PPB));
+	byte = block->data[dy][dx / EINK_PPB];
+	byte &= ~(PIXELMASK << bitpos);
+	if (color)
+	{
+		byte |= PIXEL_WHITE << bitpos;
+	}
+	else
+	{
+		byte |= PIXEL_BLACK << bitpos;   
+	}
+	block->data[dy][dx / EINK_PPB] = byte;
+}
+
+#if !GDISP_NEED_CONTROL
+#error You must enable GDISP_NEED_CONTROL for the E-Ink driver.
+#endif
+
+void gdisp_lld_control(unsigned what, void *value) {
+	gdisp_powermode_t newmode;
+	
+	switch(what)
+	{
+		case GDISP_CONTROL_POWER:
+			newmode = (gdisp_powermode_t)value;
+			
+			if (GDISP.Powermode == newmode)
+				return;
+			
+			if (newmode == powerOn)
+			{
+				power_on();
+			}
+			else
+			{
+				flush_buffers();
+				power_off();
+			}
+			GDISP.Powermode = newmode;
+			break;
+			
+		case GDISP_CONTROL_FLUSH:
+			flush_buffers();
+			break;
+	}
+}
+
+/* ===============================
+ *       Accelerated routines
+ * =============================== */
+
+#if GDISP_HARDWARE_CLEARS
+
+static void subclear(color_t color)
+{
+	unsigned x, y;
+	uint8_t byte;
+	
+	hscan_start();
+	byte = color ? BYTE_WHITE : BYTE_BLACK;
+	for (x = 0; x < GDISP_SCREEN_WIDTH; x++)
+	{
+		hscan_write(&byte, 1);
+	}
+	hscan_stop();
+	
+	setpin_oe(TRUE);
+	vscan_start();
+	for (y = 0; y < GDISP_SCREEN_HEIGHT; y++)
+	{
+		vscan_bulkwrite();
+	}
+	vscan_stop();
+	setpin_oe(FALSE);
+}
+
+void gdisp_lld_clear(color_t color)
+{
+	unsigned i;
+	clear_block_map();
+	
+	if (EINK_BLINKCLEAR)
+	{
+		subclear(!color);
+		gfxSleepMilliseconds(50);
+	}
+	
+	for (i = 0; i < EINK_CLEARCOUNT; i++)
+	{
+		subclear(color);
+		gfxSleepMilliseconds(10);
+	}
+	
+}
+#endif
+
+#endif
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld.mk b/drivers/gdisp/ED060SC4/gdisp_lld.mk
new file mode 100644
index 00000000..d5c1492f
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/gdisp_lld.mk
@@ -0,0 +1,2 @@
+GFXSRC += $(GFXLIB)/drivers/gdisp/ED060SC4/gdisp_lld.c
+GFXINC += $(GFXLIB)/drivers/gdisp/ED060SC4
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h b/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h
new file mode 100644
index 00000000..98f05ee8
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h
@@ -0,0 +1,127 @@
+/*
+ * 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
+ */
+
+/* Board interface definitions for ED060SC4 PrimeView E-ink panel.
+ * 
+ * This file corresponds to the connections shown in example_schematics.png,
+ * and is designed to interface with ChibiOS/RT.
+ * 
+ * Please note that this file has never been tested in exactly this pin
+ * configuration, because the actual boards I have are slightly different.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#include <hal.h>
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOB_EINK_VDD      0
+#define GPIOB_EINK_GMODE    1
+#define GPIOB_EINK_SPV      2
+#define GPIOB_EINK_CKV      3
+#define GPIOB_EINK_CL       4
+#define GPIOB_EINK_LE       5
+#define GPIOB_EINK_OE       6
+#define GPIOB_EINK_SPH      7
+#define GPIOB_EINK_D0       8
+#define GPIOB_EINK_D1       9
+#define GPIOB_EINK_D2       10
+#define GPIOB_EINK_D3       11
+#define GPIOB_EINK_D4       12
+#define GPIOB_EINK_D5       13
+#define GPIOB_EINK_D6       14
+#define GPIOB_EINK_D7       15
+
+#define GPIOC_SMPS_CTRL     13
+#define GPIOC_VPOS_CTRL     14
+#define GPIOC_VNEG_CTRL     15
+
+
+/* Set up IO pins for the panel connection. */
+static inline void init_board(void) {
+	/* Main SMPS power control, active low
+	 * (open collector so that MOSFET gate can be pulled up to Vbat) */
+	palWritePad(GPIOC, GPIOC_SMPS_CTRL, true);
+	palSetPadMode(GPIOC, GPIOC_SMPS_CTRL, PAL_MODE_OUTPUT_OPENDRAIN);
+	
+	/* Power control for the positive & negative side */
+	palWritePad(GPIOC, GPIOC_VPOS_CTRL, false);
+	palSetPadMode(GPIOC, GPIOC_VPOS_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
+	palWritePad(GPIOC, GPIOC_VNEG_CTRL, false);
+	palSetPadMode(GPIOC, GPIOC_VNEG_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
+	
+	/* Main data bus */
+	palWritePort(GPIOB, 0);
+	palSetGroupMode(GPIOB, 0xFFFF, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
+/* Delay for display waveforms. Should be an accurate microsecond delay. */
+static void eink_delay(int us)
+{
+	halPolledDelay(US2RTT(us));
+}
+
+/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */
+static inline void setpower_vdd(bool_t on) {
+	palWritePad(GPIOB, GPIOB_SMPS_CTRL, !on);
+	palWritePad(GPIOA, GPIOA_EINK_VDD, on);
+}
+
+/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */
+static inline void setpower_vneg(bool_t on) {
+	palWritePad(GPIOA, GPIOA_VNEG_CTRL, on);
+}
+
+/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */
+static inline void setpower_vpos(bool_t on) {
+	palWritePad(GPIOA, GPIOA_VPOS_CTRL, on);
+}
+
+/* Set the state of the LE (source driver Latch Enable) pin. */
+static inline void setpin_le(bool_t on) {
+	palWritePad(GPIOB, GPIOB_EINK_LE, on);
+}
+
+/* Set the state of the OE (source driver Output Enable) pin. */
+static inline void setpin_oe(bool_t on) {
+	palWritePad(GPIOB, GPIOB_EINK_OE, on);
+}
+
+/* Set the state of the CL (source driver Clock) pin. */
+static inline void setpin_cl(bool_t on) {
+	palWritePad(GPIOB, GPIOB_EINK_CL, on);
+}
+
+/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */
+static inline void setpin_sph(bool_t on) {
+	palWritePad(GPIOB, GPIOB_EINK_SPH, on);
+}
+
+/* Set the state of the D0-D7 (source driver Data) pins. */
+static inline void setpins_data(uint8_t value) {
+	palWriteGroup(GPIOB, 0xFF, GPIOB_EINK_D0, value);
+}
+
+/* Set the state of the CKV (gate driver Clock Vertical) pin. */
+static inline void setpin_ckv(bool_t on) {
+	palWritePad(GPIOB, GPIOB_EINK_CKV, on);
+}
+
+/* Set the state of the GMODE (gate driver Gate Mode) pin. */
+static inline void setpin_gmode(bool_t on) {
+	palWritePad(GPIOC, GPIOC_EINK_GMODE, on);
+}
+
+/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */
+static inline void setpin_spv(bool_t on) {
+	palWritePad(GPIOB, GPIOB_EINK_SPV, on);
+}
+
+#endif
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h b/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h
new file mode 100644
index 00000000..68129bf8
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h
@@ -0,0 +1,83 @@
+/*
+ * 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
+ */
+
+/* Board interface definitions for ED060SC4 PrimeView E-ink panel.
+ * 
+ * You should implement the following functions to define the interface to
+ * the panel on your board.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/* Set up IO pins for the panel connection. */
+static inline void init_board(void) {
+	#error Unimplemented
+}
+
+/* Delay for display waveforms. Should be an accurate microsecond delay. */
+static void eink_delay(int us)
+{
+	#error Unimplemented
+}
+
+/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */
+static inline void setpower_vdd(bool_t on) {
+	#error Unimplemented
+}
+
+/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */
+static inline void setpower_vneg(bool_t on) {
+	#error Unimplemented
+}
+
+/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */
+static inline void setpower_vpos(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the LE (source driver Latch Enable) pin. */
+static inline void setpin_le(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the OE (source driver Output Enable) pin. */
+static inline void setpin_oe(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the CL (source driver Clock) pin. */
+static inline void setpin_cl(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */
+static inline void setpin_sph(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the D0-D7 (source driver Data) pins. */
+static inline void setpins_data(uint8_t value) {
+	#error Unimplemented
+}
+
+/* Set the state of the CKV (gate driver Clock Vertical) pin. */
+static inline void setpin_ckv(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the GMODE (gate driver Gate Mode) pin. */
+static inline void setpin_gmode(bool_t on) {
+	#error Unimplemented
+}
+
+/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */
+static inline void setpin_spv(bool_t on) {
+	#error Unimplemented
+}
+
+#endif
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_config.h b/drivers/gdisp/ED060SC4/gdisp_lld_config.h
new file mode 100644
index 00000000..befd997c
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_config.h
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+/* Supported features of the driver for ED060SC4 PrimeView E-Ink panel. */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_NAME               "ED060SC4"
+#define GDISP_HARDWARE_CLEARS           TRUE
+#define GDISP_HARDWARE_FILLS            FALSE
+#define GDISP_HARDWARE_BITFILLS         FALSE
+#define GDISP_HARDWARE_SCROLL           FALSE
+#define GDISP_HARDWARE_PIXELREAD        FALSE
+#define GDISP_HARDWARE_CONTROL          TRUE
+
+#define GDISP_PIXELFORMAT               GDISP_PIXELFORMAT_MONO
+
+#endif
+
+#endif
diff --git a/drivers/gdisp/ED060SC4/readme.txt b/drivers/gdisp/ED060SC4/readme.txt
new file mode 100644
index 00000000..5409d810
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/readme.txt
@@ -0,0 +1,85 @@
+1. Introduction
+
+This is a driver for ED060SC4 800x600 e-ink display panel manufactured by
+Prime View. Note that this driver uses a direct connection to the panel from
+the processor; it does not use a separate controller chip between the processor
+and the panel.
+
+To use the driver, you need to be able to control the following signals from
+your processor:
+
+Gate driver: SPV, CKV, GMODE.
+Source driver: CL, LE, OE, SPH, D0-D7.
+Power supply: +-15V, +22V, -20V, digital Vdd
+
+The file "example_schematics.png" shows how to connect the signals to e.g. a
+STM32L151 microcontroller. It also includes an example circuit for providing
+the panel supply voltages.
+
+Note that the larger panels (such as the 800x600) consist of multiple segments
+with separate gate driver signals. These can be daisy chained as shown in the
+example schematic.
+
+
+
+
+2. Frame buffer emulation
+
+Because there is not enough memory to store a full frame buffer on the
+processor, this driver emulates a frame buffer by storing the display data in
+blocks. It will buffer up to EINK_NUMBUFFERS blocks and then write them to the
+screen. The following #defines control the buffering. Larger numbers will
+result in faster drawing, but also use more RAM on the processor:
+
+#define EINK_BLOCKWIDTH 20    // Width of a single block in buffer
+#define EINK_BLOCKHEIGHT 20   // Height of a single block in buffers
+#define EINK_NUMBUFFERS 40    // Number of blocks to buffer
+
+After drawing your images, you should flush the buffers using the following
+command:
+
+    #include <ed060sc4.h>
+    gdispControl(GDISP_CONTROL_FLUSH, 0);
+
+The buffers are also flushed whenever you turn the display off using:
+
+    gdispSetPowerMode(powerOff);
+
+
+
+3. Display clearing and writing waveforms
+
+This driver does not know the official Prime View waveforms for driving the
+display, mostly because those are trade secrets and not publicly available.
+Instead, it uses reverse engineered waveforms that are mostly functional.
+
+The following #defines control the waveforms:
+
+#define EINK_BLINKCLEAR TRUE      // Clear to opposite color first
+#define EINK_CLEARCOUNT 10        // Number of sweeps to clear the display
+#define EINK_WRITECOUNT 4         // Number of sweeps when writing to display
+
+Increasing the clearcount and writecount can improve contrast, but will also
+slow down the drawing and use more power.
+
+
+
+4. Clock speeds
+
+Because the driver bit bangs the display, the clock frequency of the processor
+is quite significant. This is controlled by EINK_CLOCKDELAY variable. Set it
+so that the delay is atleast 50 nanoseconds.
+
+
+
+5. Support for other kinds of panels
+
+Most of the Prime View panels should work using this driver, but only ED060SC4
+has been tested so far. Some points of consideration:
+
+- Some displays may use 4 bits per pixel. The driver currently assumes 2 bits
+  per pixel.
+- Larger displays may require some other way of daisy chaining than shown in
+  the example schematics.
+
+  
-- 
cgit v1.2.3


From 5541e6a96c34fbb5bdfe4a491e8acb1107d290ce Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 25 Sep 2013 17:28:49 +1000
Subject: Nokia6610 streaming driver orientation is NOT supported yet

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
index e6834d13..93debcd1 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 
 #define GDISP_HARDWARE_STREAM			TRUE
 #define GDISP_HARDWARE_STREAM_STOP		TRUE
-#define GDISP_HARDWARE_CONTROL			TRUE
+//#define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
 /* This driver supports both packed and unpacked pixel formats and line formats.
-- 
cgit v1.2.3


From c71a227efdfc7c9dbb65259b6d010333a07193c6 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 27 Sep 2013 01:38:37 +1000
Subject: Nokia6610 GE8 driver: Orientation support and fixes for some
 controller nasties

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c        | 340 +++++++++++++-------------
 drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h |  15 +-
 2 files changed, 181 insertions(+), 174 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index e16c6d5c..e51e780f 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -37,12 +37,19 @@
  *
  * The controller has some quirkyness when operating in other than rotation 0 mode.
  * When any direction is decremented it starts at location 0 rather than the end of
- * the area.
+ * the area. Whilst this can be handled when we know the specific operation (pixel, fill, blit)
+ * it cannot be handled in a generic stream operation. So, when orientation support is turned
+ * on (and needed) we use complex operation specific routines instead of simple streaming
+ * routines. This has a (small) performance penalty and a significant code size penalty so
+ * don't turn on orientation support unless you really need it.
  *
  * Some of the more modern controllers have a broken command set. If you have one of these
  * you will recognise it by the colors being off on anything drawn after an odd (as opposed to
  * even) pixel count area being drawn. If so then set GDISP_GE8_BROKEN_CONTROLLER to TRUE
- * on your gdisp_lld_board.h file.
+ * on your gdisp_lld_board.h file. The price is that streaming calls that are completed
+ * without exactly the window size write operations and where the number of write operations
+ * is odd (rather than even), it will draw an extra pixel. If this is important to you, turn on
+ * orientation support and the streaming operations will be emulated (as described above).
  */
 
 /*===========================================================================*/
@@ -100,9 +107,11 @@
 /* Driver local variables.                                                   */
 /*===========================================================================*/
 
-static color_t savecolor;
-#if GDISP_GE8_BROKEN_CONTROLLER
-	static color_t firstcolor;
+#if GDISP_HARDWARE_STREAM
+	static color_t savecolor;
+	#if GDISP_GE8_BROKEN_CONTROLLER
+		static color_t firstcolor;
+	#endif
 #endif
 
 #define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
@@ -122,10 +131,6 @@ static color_t savecolor;
 #define write_cmd3(cmd, d1, d2, d3)		{ write_cmd(cmd); write_data3(d1, d2, d3); }
 #define write_cmd4(cmd, d1, d2, d3, d4)	{ write_cmd(cmd); write_data4(d1, d2, d3, d4); }
 
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
@@ -179,59 +184,36 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	return TRUE;
 }
 
-LLDSPEC	void gdisp_lld_stream_start(GDISPDriver *g) {
-	acquire_bus();
-	#if GDISP_NEED_CONTROL
-		switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-				write_cmd(RAMWR);
-				break;
-			case GDISP_ROTATE_90:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
-				write_cmd(RAMWR);
-				break;
-			case GDISP_ROTATE_180:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-1);
-				write_cmd(RAMWR);
-				break;
-			case GDISP_ROTATE_270:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y+g->p.cy-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-1);
-				write_cmd(RAMWR);
-				break;
-		}
-	#else
+#if GDISP_HARDWARE_STREAM
+	LLDSPEC	void gdisp_lld_stream_start(GDISPDriver *g) {
+		acquire_bus();
 		write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
 		write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
 		write_cmd(RAMWR);
-	#endif
-	g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
-}
-
-LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
-	//write_data2(((g->p.color >> 8)&0xFF), (g->p.color & 0xFF));
+		g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
+	}
+#endif
 
-	#if GDISP_GE8_BROKEN_CONTROLLER
-		if (!(g->flags & GDISP_FLG_RUNBYTE)) {
-			firstcolor = g->p.color;
-			g->flags |= GDISP_FLG_RUNBYTE;
+#if GDISP_HARDWARE_STREAM
+	LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
+		#if GDISP_GE8_BROKEN_CONTROLLER
+			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
+				firstcolor = g->p.color;
+				g->flags |= GDISP_FLG_RUNBYTE;
+			}
+		#endif
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			// Write the pair of pixels to the display
+			write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+			g->flags &= ~GDISP_FLG_ODDBYTE;
+		} else {
+			savecolor = g->p.color;
+			g->flags |= GDISP_FLG_ODDBYTE;
 		}
-	#endif
-	if ((g->flags & GDISP_FLG_ODDBYTE)) {
-		// Write the pair of pixels to the display
-		write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
-		g->flags &= ~GDISP_FLG_ODDBYTE;
-	} else {
-		savecolor = g->p.color;
-		g->flags |= GDISP_FLG_ODDBYTE;
 	}
-}
+#endif
 
-#if GDISP_HARDWARE_STREAM_STOP
+#if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_STOP
 	LLDSPEC	void gdisp_lld_stream_stop(GDISPDriver *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			#if GDISP_GE8_BROKEN_CONTROLLER
@@ -264,69 +246,73 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 	}
 #endif
 
-#if 0
-	void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-		#endif
+#if GDISP_HARDWARE_DRAWPIXEL
+	void gdisp_lld_draw_pixel(GDISPDriver *g) {
 		acquire_bus();
-		setviewport(x, y, 1, 1);
-		write_cmd3(RAMWR, 0, (color>>8) & 0x0F, color & 0xFF);
+		switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x);			// Column address set
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y);			// Page address set
+				break;
+			case GDISP_ROTATE_90:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x);
+				break;
+			case GDISP_ROTATE_180:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y);
+				break;
+			case GDISP_ROTATE_270:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x);
+				break;
+		}
+		write_cmd3(RAMWR, 0, (g->p.color>>8) & 0x0F, g->p.color & 0xFF);
 		release_bus();
 	}
 #endif
 
 /* ---- Optional Routines ---- */
 
-#if 0 && GDISP_HARDWARE_FILLS
-	/**
-	 * @brief   Fill an area with a color.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
+#if GDISP_HARDWARE_FILLS
+	void gdisp_lld_fill_area(GDISPDriver *g) {
 		unsigned tuples;
 
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		tuples = (cx*cy+1)>>1;				// With an odd sized area we over-print by one pixel.
+		tuples = (g->p.cx*g->p.cy+1)>>1;	// With an odd sized area we over-print by one pixel.
 											// This extra pixel overwrites the first pixel (harmless as it is the same colour)
 
 		acquire_bus();
-		setviewport(x, y, cx, cy);
+		switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+				break;
+			case GDISP_ROTATE_90:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y+g->p.cy-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-1);
+				break;
+			case GDISP_ROTATE_180:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-1);
+				break;
+			case GDISP_ROTATE_270:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
+				break;
+		}
 		write_cmd(RAMWR);
 		while(tuples--)
-			write_data3(((color >> 4) & 0xFF), (((color << 4) & 0xF0)|((color >> 8) & 0x0F)), (color & 0xFF));
+			write_data3(((g->p.color >> 4) & 0xFF), (((g->p.color << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
 		release_bus();
 	}
 #endif
 
-#if 0 && GDISP_HARDWARE_BITFILLS
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 *
-	 * @param[in] x, y			The start filled area
-	 * @param[in] cx, cy		The width and height to be filled
-	 * @param[in] srcx, srcy	The bitmap position to start the fill from
-	 * @param[in] srccx			The width of a line in the bitmap.
-	 * @param[in] buffer		The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t		lg;
-		color_t		c1, c2;
-		unsigned	tuples;
+#if GDISP_HARDWARE_BITFILLS
+	void gdisp_lld_blit_area(GDISPDriver *g) {
+		coord_t			lg, x, y;
+		color_t			c1, c2;
+		unsigned		tuples;
+		const pixel_t	*buffer;
 		#if GDISP_PACKED_PIXELS
 			unsigned		pnum, pstart;
 			const uint8_t	*p;
@@ -334,19 +320,29 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 			const pixel_t	*p;
 		#endif
 
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
+		tuples = (g->p.cx * g->p.cy + 1)>>1;
+		buffer = (const pixel_t *)g->p.ptr;
 
 		/* Set up the data window to transfer */
-		tuples = (cx * cy + 1)>>1;
 		acquire_bus();
-		setviewport(x, y, cx, cy);
+		switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+				break;
+			case GDISP_ROTATE_90:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y+g->p.cy-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-1);
+				break;
+			case GDISP_ROTATE_180:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-1);
+				break;
+			case GDISP_ROTATE_270:
+				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-1);
+				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
+				break;
+		}
 		write_cmd(RAMWR);
 
 		/*
@@ -356,30 +352,30 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 		 * memory write. The controller always starts with column 0 and then decrements
 		 * to column cx-1, cx-2 etc. We therefore have to write-out the last bitmap line first.
 		 */
-		switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:		x = 0;		y = 0;		break;
-		case GDISP_ROTATE_90:		x = 0;		y = cy-1;	break;
-		case GDISP_ROTATE_180:		x = cx-1;	y = cy-1;	break;
-		case GDISP_ROTATE_270:		x = cx-1;	y = 0;		break;
+		switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:		x = 0;			y = 0;			break;
+		case GDISP_ROTATE_90:		x = g->p.cx-1;	y = 0;			break;
+		case GDISP_ROTATE_180:		x = g->p.cx-1;	y = g->p.cy-1;	break;
+		case GDISP_ROTATE_270:		x = 0;			y = g->p.cy-1;	break;
 		}
 
 		#if !GDISP_PACKED_PIXELS
 			// Although this controller uses packed pixels we support unpacked pixel
 			//  formats in this blit by packing the data as we feed it to the controller.
 
-			lg = srccx - cx;						// The buffer gap between lines
-			buffer += srcy * srccx + srcx;			// The buffer start position
-			p = buffer + srccx*y + x;				// Adjustment for controller craziness
+			lg = g->p.x2 - g->p.cx;					// The buffer gap between lines
+			buffer += g->p.y1 * g->p.x2 + g->p.x1;	// The buffer start position
+			p = buffer + g->p.x2*y + x;				// Adjustment for controller craziness
 
 			while(tuples--) {
 				/* Get a pixel */
 				c1 = *p++;
 
 				/* Check for line or buffer wrapping */
-				if (++x >= cx) {
+				if (++x >= g->p.cx) {
 					x = 0;
 					p += lg;
-					if (++y >= cy) {
+					if (++y >= g->p.cy) {
 						y = 0;
 						p = buffer;
 					}
@@ -389,10 +385,10 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 				c2 = *p++;
 
 				/* Check for line or buffer wrapping */
-				if (++x >= cx) {
+				if (++x >= g->p.cx) {
 					x = 0;
 					p += lg;
-					if (++y >= cy) {
+					if (++y >= g->p.cy) {
 						y = 0;
 						p = buffer;
 					}
@@ -409,13 +405,13 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 			// There are 2 pixels per 3 bytes
 
 			#if !GDISP_PACKED_LINES
-				srccx = (srccx + 1) & ~1;
+				srccx = (g->p.x2 + 1) & ~1;
 			#endif
-			pstart = srcy * srccx + srcx;												// The starting pixel number
+			pstart = g->p.y1 * g->p.x2 + g->p.x1;										// The starting pixel number
 			buffer = (const pixel_t)(((const uint8_t *)buffer) + ((pstart>>1) * 3));	// The buffer start position
-			lg = ((srccx-cx)>>1)*3;														// The buffer gap between lines
-			pnum = pstart + srccx*y + x;												// Adjustment for controller craziness
-			p = ((const uint8_t *)buffer) + (((srccx*y + x)>>1)*3);						// Adjustment for controller craziness
+			lg = ((g->p.x2-g->p.cx)>>1)*3;												// The buffer gap between lines
+			pnum = pstart + g->p.x2*y + x;												// Adjustment for controller craziness
+			p = ((const uint8_t *)buffer) + (((g->p.x2*y + x)>>1)*3);					// Adjustment for controller craziness
 
 			while (tuples--) {
 				/* Get a pixel */
@@ -425,11 +421,11 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 				}
 
 				/* Check for line or buffer wrapping */
-				if (++x >= cx) {
+				if (++x >= g->p.cx) {
 					x = 0;
 					p += lg;
-					pnum += srccx - cx;
-					if (++y >= cy) {
+					pnum += g->p.x2 - g->p.cx;
+					if (++y >= g->p.cy) {
 						y = 0;
 						p = (const uint8_t *)buffer;
 						pnum = pstart;
@@ -443,11 +439,11 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 				}
 
 				/* Check for line or buffer wrapping */
-				if (++x >= cx) {
+				if (++x >= g->p.cx) {
 					x = 0;
 					p += lg;
-					pnum += srccx - cx;
-					if (++y >= cy) {
+					pnum += g->p.x2 - g->p.cx;
+					if (++y >= g->p.cy) {
 						y = 0;
 						p = (const uint8_t *)buffer;
 						pnum = pstart;
@@ -464,7 +460,7 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 	}
 #endif
 
-#if 0 && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
 	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
 		/* The hardware is capable of supporting...
 		 * 	GDISP_CONTROL_POWER				- supported
@@ -489,27 +485,27 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 					write_cmd(OSCON);									// Internal oscillator on
 					write_cmd(SLPOUT);									// Sleep out
 					write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(VOLCTR, GDISP.Contrast, 0x03);			// Voltage control (contrast setting)
+					write_cmd2(VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
 					delayms(100);										// Allow power supply to stabilise
 					write_cmd(DISON);									// Turn on the display
 					write_cmd(PTLOUT);									// Remove sleep window
-					set_backlight(GDISP.Backlight);						// Turn on the backlight
+					set_backlight(g->g.Backlight);						// Turn on the backlight
 					break;
 				case powerSleep:
 					write_cmd(OSCON);									// Internal oscillator on
 					write_cmd(SLPOUT);									// Sleep out
 					write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(VOLCTR, GDISP.Contrast, 0x03);			// Voltage control (contrast setting)
+					write_cmd2(VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
 					delayms(100);										// Allow power supply to stabilise
 					write_cmd(DISON);									// Turn on the display
 					write_cmd2(PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
-					set_backlight(GDISP.Backlight);						// Turn on the backlight
+					set_backlight(g->g.Backlight);						// Turn on the backlight
 					break;
 				case powerDeepSleep:
 					write_cmd(OSCON);									// Internal oscillator on
 					write_cmd(SLPOUT);									// Sleep out
 					write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(VOLCTR, GDISP.Contrast, 0x03);			// Voltage control (contrast setting)
+					write_cmd2(VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
 					delayms(100);										// Allow power supply to stabilise
 					write_cmd(DISON);									// Turn on the display
 					write_cmd2(PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
@@ -522,45 +518,47 @@ LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
 			release_bus();
 			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
-		case GDISP_CONTROL_ORIENTATION:
-			if (g->g.Orientation == (orientation_t)g->p.ptr)
-				return;
-			acquire_bus();
-			switch((orientation_t)g->p.ptr) {
-				case GDISP_ROTATE_0:
-					write_cmd3(DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
-					GDISP.Height = GDISP_SCREEN_HEIGHT;
-					GDISP.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_90:
-					write_cmd3(DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
-					GDISP.Height = GDISP_SCREEN_WIDTH;
-					GDISP.Width = GDISP_SCREEN_HEIGHT;
-					break;
-				case GDISP_ROTATE_180:
-					write_cmd3(DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
-					GDISP.Height = GDISP_SCREEN_HEIGHT;
-					GDISP.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_270:
-					write_cmd3(DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
-					GDISP.Height = GDISP_SCREEN_WIDTH;
-					GDISP.Width = GDISP_SCREEN_HEIGHT;
-					break;
-				default:
-					release_bus();
+		#if GDISP_NOKIA_ORIENTATION
+			case GDISP_CONTROL_ORIENTATION:
+				if (g->g.Orientation == (orientation_t)g->p.ptr)
 					return;
-			}
-			release_bus();
-			g->g.Orientation = (orientation_t)g->p.ptr;
-			return;
+				acquire_bus();
+				switch((orientation_t)g->p.ptr) {
+					case GDISP_ROTATE_0:
+						write_cmd3(DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
+						g->g.Height = GDISP_SCREEN_HEIGHT;
+						g->g.Width = GDISP_SCREEN_WIDTH;
+						break;
+					case GDISP_ROTATE_90:
+						write_cmd3(DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
+						g->g.Height = GDISP_SCREEN_WIDTH;
+						g->g.Width = GDISP_SCREEN_HEIGHT;
+						break;
+					case GDISP_ROTATE_180:
+						write_cmd3(DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
+						g->g.Height = GDISP_SCREEN_HEIGHT;
+						g->g.Width = GDISP_SCREEN_WIDTH;
+						break;
+					case GDISP_ROTATE_270:
+						write_cmd3(DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
+						g->g.Height = GDISP_SCREEN_WIDTH;
+						g->g.Width = GDISP_SCREEN_HEIGHT;
+						break;
+					default:
+						release_bus();
+						return;
+				}
+				release_bus();
+				g->g.Orientation = (orientation_t)g->p.ptr;
+				return;
+		#endif
 		case GDISP_CONTROL_BACKLIGHT:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			set_backlight((unsigned)g->p.ptr);
 			g->g.Backlight = (unsigned)g->p.ptr;
 			return;
 		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)value > 100) g->p.ptr = (void *)100;
+			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			acquire_bus();
 			write_cmd2(VOLCTR, (unsigned)g->p.ptr, 0x03);
 			release_bus();
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
index 93debcd1..5e950895 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -25,9 +25,18 @@
 #define GDISP_DRIVER_NAME				"Nokia6610GE8"
 #define GDISP_DRIVER_STRUCT				GDISP_Nokia6610GE8
 
-#define GDISP_HARDWARE_STREAM			TRUE
-#define GDISP_HARDWARE_STREAM_STOP		TRUE
-//#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_NOKIA_ORIENTATION				TRUE
+
+#if GDISP_NOKIA_ORIENTATION && GDISP_NEED_CONTROL
+	#define GDISP_HARDWARE_CONTROL			TRUE
+	#define GDISP_HARDWARE_DRAWPIXEL		TRUE
+	#define GDISP_HARDWARE_FILLS			TRUE
+	#define GDISP_HARDWARE_BITFILLS			TRUE
+#else
+	#define GDISP_HARDWARE_CONTROL			TRUE
+	#define GDISP_HARDWARE_STREAM			TRUE
+	#define GDISP_HARDWARE_STREAM_STOP		TRUE
+#endif
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
 /* This driver supports both packed and unpacked pixel formats and line formats.
-- 
cgit v1.2.3


From 3b8f14e2c8f03bcddfc1c274462bb46bc189c808 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sat, 28 Sep 2013 02:24:09 +0200
Subject: SSD1289 Area fill fix

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index a47fb17e..a55dd467 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -92,7 +92,7 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
 			write_reg(0x46, (y+cy-1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
+			write_reg(0x44, (((y+cy-1) << 8) & 0xFF00 ) | (y & 0x00FF));
 			write_reg(0x45, x & 0x01FF);
 			write_reg(0x46, (x+cx-1) & 0x01FF);
 			break;
-- 
cgit v1.2.3


From 6499da5be310f8f3ef8f2d11dfcfb662499c8c17 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 00:05:07 +1000
Subject: SSD1289 streaming driver (untested) X streaming driver (untested)
 Nokia6610 fixes Read pixel streaming support for low level driver.

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             |  22 +-
 drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h      |   7 +-
 drivers/gdisp/SSD1289/gdisp_lld.c                  | 425 ++++-----------------
 .../SSD1289/gdisp_lld_board_firebullstm32f103.h    |  42 +-
 .../SSD1289/gdisp_lld_board_st_stm32f4_discovery.h |  63 ++-
 drivers/gdisp/SSD1289/gdisp_lld_board_template.h   |  37 +-
 drivers/gdisp/SSD1289/gdisp_lld_config.h           |  17 +-
 drivers/multiple/Win32/gdisp_lld.c                 |   4 +-
 drivers/multiple/X/gdisp_lld.c                     | 136 ++++---
 drivers/multiple/X/gdisp_lld_config.h              |  11 +-
 10 files changed, 290 insertions(+), 474 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index e51e780f..bcccef80 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -107,7 +107,7 @@
 /* Driver local variables.                                                   */
 /*===========================================================================*/
 
-#if GDISP_HARDWARE_STREAM
+#if GDISP_HARDWARE_STREAM_WRITE
 	static color_t savecolor;
 	#if GDISP_GE8_BROKEN_CONTROLLER
 		static color_t firstcolor;
@@ -184,18 +184,15 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	return TRUE;
 }
 
-#if GDISP_HARDWARE_STREAM
-	LLDSPEC	void gdisp_lld_stream_start(GDISPDriver *g) {
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
 		write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
 		write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
 		write_cmd(RAMWR);
 		g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
 	}
-#endif
-
-#if GDISP_HARDWARE_STREAM
-	LLDSPEC	void gdisp_lld_stream_color(GDISPDriver *g) {
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
 		#if GDISP_GE8_BROKEN_CONTROLLER
 			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
 				firstcolor = g->p.color;
@@ -211,10 +208,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
-#endif
-
-#if GDISP_HARDWARE_STREAM && GDISP_HARDWARE_STREAM_STOP
-	LLDSPEC	void gdisp_lld_stream_stop(GDISPDriver *g) {
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			#if GDISP_GE8_BROKEN_CONTROLLER
 				/**
@@ -247,7 +241,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #if GDISP_HARDWARE_DRAWPIXEL
-	void gdisp_lld_draw_pixel(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) {
 		acquire_bus();
 		switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
@@ -275,7 +269,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 /* ---- Optional Routines ---- */
 
 #if GDISP_HARDWARE_FILLS
-	void gdisp_lld_fill_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
 		unsigned tuples;
 
 		tuples = (g->p.cx*g->p.cy+1)>>1;	// With an odd sized area we over-print by one pixel.
@@ -308,7 +302,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #if GDISP_HARDWARE_BITFILLS
-	void gdisp_lld_blit_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
 		coord_t			lg, x, y;
 		color_t			c1, c2;
 		unsigned		tuples;
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
index 5e950895..a9e11e03 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -25,7 +25,9 @@
 #define GDISP_DRIVER_NAME				"Nokia6610GE8"
 #define GDISP_DRIVER_STRUCT				GDISP_Nokia6610GE8
 
-#define GDISP_NOKIA_ORIENTATION				TRUE
+#ifndef GDISP_NOKIA_ORIENTATION
+	#define GDISP_NOKIA_ORIENTATION			TRUE
+#endif
 
 #if GDISP_NOKIA_ORIENTATION && GDISP_NEED_CONTROL
 	#define GDISP_HARDWARE_CONTROL			TRUE
@@ -34,8 +36,7 @@
 	#define GDISP_HARDWARE_BITFILLS			TRUE
 #else
 	#define GDISP_HARDWARE_CONTROL			TRUE
-	#define GDISP_HARDWARE_STREAM			TRUE
-	#define GDISP_HARDWARE_STREAM_STOP		TRUE
+	#define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #endif
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index a55dd467..84ffa6d1 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -17,8 +17,8 @@
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -52,7 +52,7 @@ static inline void set_cursor(coord_t x, coord_t y) {
 	 * Reg 0x004F is 9 bit
 	 * Use a bit mask to make sure they are not set too high
 	 */
-	switch(GDISP.Orientation) {
+	switch(g->g.Orientation) {
 		case GDISP_ROTATE_180:
 			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-x) & 0x00FF);
 			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-y) & 0x01FF);
@@ -85,14 +85,14 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
 	 * 		0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
 	 */
 
-	switch(GDISP.Orientation) {
+	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 			write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (x & 0x00FF));
 			write_reg(0x45, y & 0x01FF);
 			write_reg(0x46, (y+cy-1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(0x44, (((y+cy-1) << 8) & 0xFF00 ) | (y & 0x00FF));
+			write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
 			write_reg(0x45, x & 0x01FF);
 			write_reg(0x46, (x+cx-1) & 0x01FF);
 			break;
@@ -112,7 +112,7 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
 }
 
 static inline void reset_viewport(void) {
-	set_viewport(0, 0, GDISP.Width, GDISP.Height);
+	set_viewport(0, 0, g->g.Width, g->g.Height);
 }
 
 /*===========================================================================*/
@@ -123,18 +123,7 @@ static inline void reset_viewport(void) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
 	init_board();
 
@@ -196,365 +185,103 @@ bool_t gdisp_lld_init(void) {
 	set_backlight(GDISP_INITIAL_BACKLIGHT);
 
    /* Initialise the GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	
-	acquire_bus();
-	set_cursor(x, y);
-	write_reg(0x0022, color);
-	release_bus();
-}
-
-/* ---- Optional Routines ---- */
-/*
-	All the below routines are optional.
-	Defining them will increase speed but everything
-	will work if they are not defined.
-	If you are not using a routine - turn it off using
-	the appropriate GDISP_HARDWARE_XXXX macro.
-	Don't bother coding for obvious similar routines if
-	there is no performance penalty as the emulation software
-	makes a good job of using similar routines.
-		eg. If gfillarea() is defined there is little
-			point in defining clear() unless the
-			performance bonus is significant.
-	For good performance it is suggested to implement
-		fillarea() and blitarea().
-*/
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Clear the display.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] color    The color of the pixel
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_clear(color_t color) {
-		unsigned area;
-
-		area = GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT;
-
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
-		reset_viewport();
-		set_cursor(0, 0);
-
+		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
 		stream_start();
-
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-            uint8_t i;
-            dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
-            dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-            for (i = area/65535; i; i--) {
-                dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-                dmaStreamEnable(GDISP_DMA_STREAM);
-                dmaWaitCompletion(GDISP_DMA_STREAM);
-            }
-            dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-            dmaStreamEnable(GDISP_DMA_STREAM);
-            dmaWaitCompletion(GDISP_DMA_STREAM);
-        #else
-            uint32_t index;
-            for(index = 0; index < area; index++)
-                write_data(color);
-        #endif  //#ifdef GDISP_USE_DMA
-
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+		write_data(color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		stream_stop();
 		release_bus();
 	}
 #endif
 
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		unsigned area;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		area = cx*cy;
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
+		uint16_t	dummy;
 
 		acquire_bus();
-		set_viewport(x, y, cx, cy);
+		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
 		stream_start();
-
-        #if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-            uint8_t i;
-            dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
-            dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-            for (i = area/65535; i; i--) {
-                dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-                dmaStreamEnable(GDISP_DMA_STREAM);
-                dmaWaitCompletion(GDISP_DMA_STREAM);
-            }
-            dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-            dmaStreamEnable(GDISP_DMA_STREAM);
-            dmaWaitCompletion(GDISP_DMA_STREAM);
-        #else
-            uint32_t index;
-            for(index = 0; index < area; index++)
-                write_data(color);
-        #endif  //#ifdef GDISP_USE_DMA
-
+		setreadmode();
+		dummy = read_data();		// dummy read
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
+		return read_data();
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
+		setwritemode();
 		stream_stop();
 		release_bus();
 	}
 #endif
 
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		buffer += srcx + srcy * srccx;
-
+#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
 		acquire_bus();
-		set_viewport(x, y, cx, cy);
+		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
 		stream_start();
-
-        #if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-            uint32_t area = cx*cy;
-            uint8_t i;
-            dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-            dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-            for (i = area/65535; i; i--) {
-                dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-                dmaStreamEnable(GDISP_DMA_STREAM);
-                dmaWaitCompletion(GDISP_DMA_STREAM);
-            }
-            dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-            dmaStreamEnable(GDISP_DMA_STREAM);
-            dmaWaitCompletion(GDISP_DMA_STREAM);
-        #else
-            coord_t endx, endy;
-            uint32_t lg;
-            endx = srcx + cx;
-            endy = y + cy;
-            lg = srccx - cx;
-            for(; y < endy; y++, buffer += lg)
-                for(x=srcx; x < endx; x++)
-                    write_data(*buffer++);
-        #endif  //#ifdef GDISP_USE_DMA
-
+		dma_with_noinc(&color, g->p.cx*g->p.cy)
 		stream_stop();
 		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The pixel to be read
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
+#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
+		pixel_t		*buffer;
+		coord_t		ycnt;
 
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
+		buffer = (pixel_t *)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
 
 		acquire_bus();
-		set_cursor(x, y);
+		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
 		stream_start();
 
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0 ;
-
-		color = read_data();			// dummy read
-		color = read_data();
-
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-
-		stream_stop();
-		release_bus();
-
-		return color;
-	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, gap, abslines, j;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		abslines = lines < 0 ? -lines : lines;
-
-		acquire_bus();
-		if ((coord_t)abslines >= cy) {
-			abslines = cy;
-			gap = 0;
+		if (g->p.x2 == g->p.cx) {
+			dma_with_inc(buffer, g->p.cx*g->p.cy);
 		} else {
-			gap = cy - abslines;
-			for(i = 0; i < gap; i++) {
-				if(lines > 0) {
-					row0 = y + i + lines;
-					row1 = y + i;
-				} else {
-					row0 = (y - i - 1) + lines;
-					row1 = (y - i - 1);
-				}
-
-				/* read row0 into the buffer and then write at row1*/
-				set_viewport(x, row0, cx, 1);
-				stream_start();
-
-				/* FSMC timing */
-				FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0 ;
-
-				j = read_data();			// dummy read
-				for (j = 0; (coord_t)j < cx; j++)
-					buf[j] = read_data();
-
-				/* FSMC timing */
-				FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-
-				stream_stop();
-
-				set_viewport(x, row1, cx, 1);
-				stream_start();
-				for (j = 0; (coord_t)j < cx; j++)
-					write_data(buf[j]);
-				stream_stop();
-			}
+			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
+				dma_with_inc(buffer, g->p.cy);
 		}
-
-		/* fill the remaining gap */
-		set_viewport(x, lines > 0 ? (y+(coord_t)gap) : y, cx, abslines);
-		stream_start();
-		gap = cx*abslines;
-		for(i = 0; i < gap; i++) write_data(bgcolor);
 		stream_stop();
 		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+		switch(g->p.x) {
 		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
 				return;
-			switch((gdisp_powermode_t)value) {
+			switch((powermode_t)g->p.ptr) {
 			case powerOff:
 				acquire_bus();
 				write_reg(0x0010, 0x0000);	// leave sleep mode
 				write_reg(0x0007, 0x0000);	// halt operation
-				write_reg(0x0000, 0x0000);	// turn off oszillator
-				write_reg(0x0010, 0x0001);	// enter sleepmode
+				write_reg(0x0000, 0x0000);	// turn off oscillator
+				write_reg(0x0010, 0x0001);	// enter sleep mode
 				release_bus();
 				break;
 			case powerOn:
 				acquire_bus();
 				write_reg(0x0010, 0x0000);	// leave sleep mode
 				release_bus();
-				if (GDISP.Powermode != powerSleep)
+				if (g->g.Powermode != powerSleep)
 					gdisp_lld_init();
 				break;
 			case powerSleep:
@@ -565,20 +292,20 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 			default:
 				return;
 			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
+			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
 		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-			switch((gdisp_orientation_t)value) {
+			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
 				acquire_bus();
 				write_reg(0x0001, 0x2B3F);
 				/* ID = 11 AM = 0 */
 				write_reg(0x0011, 0x6070);
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_90:
 				acquire_bus();
@@ -586,8 +313,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				/* ID = 11 AM = 1 */
 				write_reg(0x0011, 0x6078);
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
 				acquire_bus();
@@ -595,8 +322,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				/* ID = 01 AM = 0 */
 				write_reg(0x0011, 0x6040);
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
 				acquire_bus();
@@ -604,31 +331,23 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				/* ID = 01 AM = 1 */
 				write_reg(0x0011, 0x6048);
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			default:
 				return;
 			}
-			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
+			g->g.Orientation = (orientation_t)value;
 			return;
         case GDISP_CONTROL_BACKLIGHT:
-            if ((unsigned)value > 100)
-            value = (void *)100;
-            set_backlight((unsigned)value);
-            GDISP.Backlight = (unsigned)value;
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+            set_backlight((unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
             return;
+		//case GDISP_CONTROL_CONTRAST:
         default:
             return;
-/*
-		case GDISP_CONTROL_CONTRAST:
-*/
 		}
 	}
 #endif
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h b/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
index 38d9e04d..e55e7cd1 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
@@ -112,7 +112,28 @@ static inline void write_data(uint16_t data) {
 	CLR_WR; SET_WR;
 }
 
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+	// change pin mode to digital input
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
+	CLR_RD;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+	// change pin mode back to digital output
+	SET_RD;
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
 /**
  * @brief   Read data from the lcd.
  *
@@ -123,22 +144,13 @@ static inline void write_data(uint16_t data) {
  * @notapi
  */
 static inline uint16_t read_data(void) {
-	uint16_t	value;
-	
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-
-	CLR_RD;
-	value = palReadPort(GPIOE);
-	value = palReadPort(GPIOE);
-	SET_RD;
-
-	// change pin mode back to digital output
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	
-	return value;
+	return palReadPort(GPIOE);
 }
 #endif
 
+#if defined(GDISP_USE_DMA)
+	#error "GDISP - SSD1289: The GPIO interface does not support DMA"
+#endif
+
 #endif /* _GDISP_LLD_BOARD_H */
 /** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h b/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
index 9d46d64b..7097347b 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
@@ -18,10 +18,7 @@
 
 #define GDISP_REG              ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
 #define GDISP_RAM              ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
-
-#define GDISP_USE_FSMC
-#define GDISP_USE_DMA
-#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
+#define GDISP_DMA_STREAM		STM32_DMA2_STREAM6
 
 const unsigned char FSMC_Bank = 0;
 
@@ -55,20 +52,22 @@ static inline void init_board(void) {
 		/* FSMC setup for F1/F3 */
 		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
 
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			#error "DMA not implemented for F1/F3 Devices"
+		#if defined(GDISP_USE_DMA)
+			#error "GDISP: SSD1289 - DMA not implemented for F1/F3 Devices"
 		#endif
 	#elif defined(STM32F4XX) || defined(STM32F2XX)
 		/* STM32F2-F4 FSMC init */
 		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
 
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+		#if defined(GDISP_USE_DMA)
 			if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) gfxExit();
 			dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
 			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		#else
+			#warning "GDISP: SSD1289 - DMA is supported for F2/F4 Devices. Define GDISP_USE_DMA in your gfxconf.h to turn this on for better performance."
 		#endif
 	#else
-		#error "FSMC not implemented for this device"
+		#error "GDISP: SSD1289 - FSMC not implemented for this device"
 	#endif
 
 	/* set pins to FSMC mode */
@@ -155,17 +154,61 @@ static inline void write_index(uint16_t index) { GDISP_REG = index; }
  */
 static inline void write_data(uint16_t data) { GDISP_RAM = data; }
 
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
+}
+
 /**
  * @brief   Read data from the lcd.
  *
  * @return	The data from the lcd
  * @note	The chip select may need to be asserted/de-asserted
  * 			around the actual spi read
- * 
+ *
  * @notapi
  */
 static inline uint16_t read_data(void) { return GDISP_RAM; }
+
+#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
+	/**
+	 * @brief	Transfer data using DMA but don't increment the source address
+	 */
+	static inline dma_with_noinc(color_t *buffer, int area) {
+		dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+		dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		for (; area > 0; area -= 65535) {
+			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
+			dmaStreamEnable(GDISP_DMA_STREAM);
+			dmaWaitCompletion(GDISP_DMA_STREAM);
+		}
+	}
+
+	/**
+	 * @brief	Transfer data using DMA incrementing the source address
+	 */
+	static inline dma_with_inc(color_t *buffer, int area) {
+        dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+        dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		for (; area > 0; area -= 65535) {
+			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
+			dmaStreamEnable(GDISP_DMA_STREAM);
+			dmaWaitCompletion(GDISP_DMA_STREAM);
+		}
+	}
 #endif
 
 #endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_template.h b/drivers/gdisp/SSD1289/gdisp_lld_board_template.h
index e5d10355..8b55bed3 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_board_template.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_board_template.h
@@ -87,7 +87,24 @@ static inline void write_data(uint16_t data) {
 
 }
 
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+
+}
+
 /**
  * @brief   Read data from the lcd.
  *
@@ -100,6 +117,24 @@ static inline void write_data(uint16_t data) {
 static inline uint16_t read_data(void) {
 
 }
+
+/**
+ * The below section you can replace with #error if your interface doesn't support DMA
+ */
+#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
+	//#error "GDISP - SSD1289: This interface does not support DMA"
+
+	/**
+	 * @brief	Transfer data using DMA but don't increment the source address
+	 */
+	static inline dma_with_noinc(color_t *buffer, int area) {
+	}
+
+	/**
+	 * @brief	Transfer data using DMA incrementing the source address
+	 */
+	static inline dma_with_inc(color_t *buffer, int area) {
+	}
 #endif
 
 #endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index 989cc3af..9c00ce39 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -23,13 +23,16 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"SSD1289"
-
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			TRUE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
-#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_DRIVER_STRUCT				GDISP_SSD1289
+
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
+
+#if defined(GDISP_USE_DMA)
+	#define GDISP_HARDWARE_FILLS		TRUE
+	#define GDISP_HARDWARE_BITFILLS		TRUE
+#endif
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
 
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index f55f3700..41141a90 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -463,7 +463,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 	
 #if GDISP_HARDWARE_BITFILLS
-	void gdisp_lld_blit_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
 		BITMAPV4HEADER bmpInfo;
 		HDC			dcScreen;
 		pixel_t	*	buffer;
@@ -577,7 +577,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
-	void gdisp_lld_vertical_scroll(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
 		HDC			dcScreen;
 		RECT		rect;
 		coord_t		lines;
diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index 13368bc1..9c6a7123 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -14,6 +14,9 @@
 
 #if GFX_USE_GDISP
 
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
+
 /**
  * Our color model - Default or 24 bit only.
  *
@@ -25,26 +28,23 @@
 	#define GDISP_FORCE_24BIT	FALSE
 #endif
 
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		480
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		640
+#endif
+
 #if GINPUT_NEED_MOUSE
 	/* Include mouse support code */
 	#include "ginput/lld/mouse.h"
 #endif
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <stdio.h>
 #include <stdlib.h>
 
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		480
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		640
-#endif
-
 Display			*dis;
 int				scr;
 Window			win;
@@ -130,7 +130,7 @@ static int FatalXIOError(Display *d) {
 	exit(0);
 }
 
-bool_t gdisp_lld_init(void)
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 {
 	XSizeHints				*pSH;
 	XSetWindowAttributes	xa;
@@ -212,69 +212,81 @@ bool_t gdisp_lld_init(void)
 	gfxThreadClose(hth);
 	
     /* Initialise the GDISP structure to match */
-    GDISP.Orientation = GDISP_ROTATE_0;
-    GDISP.Powermode = powerOn;
-    GDISP.Backlight = 100;
-    GDISP.Contrast = 50;
-    GDISP.Width = GDISP_SCREEN_WIDTH;
-    GDISP.Height = GDISP_SCREEN_HEIGHT;
-    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-            GDISP.clipx0 = 0;
-            GDISP.clipy0 = 0;
-            GDISP.clipx1 = GDISP.Width;
-            GDISP.clipy1 = GDISP.Height;
-    #endif
+    g->g.Orientation = g->g_ROTATE_0;
+    g->g.Powermode = powerOn;
+    g->g.Backlight = 100;
+    g->g.Contrast = 50;
+    g->g.Width = GDISP_SCREEN_WIDTH;
+    g->g.Height = GDISP_SCREEN_HEIGHT;
     return TRUE;
 }
 
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color)
+LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 {
 	XColor	col;
 
-   #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-        // Clip pre orientation change
-        if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-    #endif
-
-	col.red = RED_OF(color) << 8;
-	col.green = GREEN_OF(color) << 8;
-	col.blue = BLUE_OF(color) << 8;
+	col.red = RED_OF(g->p.color) << 8;
+	col.green = GREEN_OF(g->p.color) << 8;
+	col.blue = BLUE_OF(g->p.color) << 8;
 	XAllocColor(dis, cmap, &col);
 	XSetForeground(dis, gc, col.pixel);
-	XDrawPoint(dis, pix, gc, (int)x, (int)y );
-	XDrawPoint(dis, win, gc, (int)x, (int)y );
+	XDrawPoint(dis, pix, gc, (int)g->p.x, (int)g->p.y );
+	XDrawPoint(dis, win, gc, (int)g->p.x, (int)g->p.y );
 	XFlush(dis);
 }
 
-void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-	XColor	col;
-	
-    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-        // Clip pre orientation change
-        if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-        if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-        if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-        if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-        if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-    #endif
-
-	col.red = RED_OF(color) << 8;
-	col.green = GREEN_OF(color) << 8;
-	col.blue = BLUE_OF(color) << 8;
-	XAllocColor(dis, cmap, &col);
-	XSetForeground(dis, gc, col.pixel);
-	XFillRectangle(dis, pix, gc, x, y, cx, cy);
-	XFillRectangle(dis, win, gc, x, y, cx, cy);
-	XFlush(dis);
-}
+#if GDISP_HARDWARE_FILLS
+	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
+		XColor	col;
+
+		col.red = RED_OF(g->p.color) << 8;
+		col.green = GREEN_OF(g->p.color) << 8;
+		col.blue = BLUE_OF(g->p.color) << 8;
+		XAllocColor(dis, cmap, &col);
+		XSetForeground(dis, gc, col.pixel);
+		XFillRectangle(dis, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		XFillRectangle(dis, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		XFlush(dis);
+	}
+#endif
+
+#if 0 && GDISP_HARDWARE_BITFILLS
+	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
+		// Start of Bitblit code
+
+		//XImage			bitmap;
+		//pixel_t			*bits;
+		//	bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
+		//	bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
+		//				0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
+		//				0, 0);
+	}
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
+		XColor	color;
+		XImage *img;
 
-// Start of Bitblit code
-//XImage			bitmap;
-//pixel_t			*bits;
-//	bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
-//	bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
-//				0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
-//				0, 0);
+		img = XGetImage (dis, pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
+		color->pixel = XGetPixel (img, 0, 0);
+		XFree(img);
+		XQueryColor(dis, cmap, &color);
+		return RGB2COLOR(c.red>>8, c.green>>8, c.blue>>8);
+	}
+#endif
+
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+	LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
+		if (g->p.y1 > 0) {
+			XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
+			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
+		} else {
+			XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y-lines, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+		}
+	}
+#endif
 
 #if GINPUT_NEED_MOUSE
 
diff --git a/drivers/multiple/X/gdisp_lld_config.h b/drivers/multiple/X/gdisp_lld_config.h
index 0cacc4f8..0bd76a2c 100644
--- a/drivers/multiple/X/gdisp_lld_config.h
+++ b/drivers/multiple/X/gdisp_lld_config.h
@@ -23,17 +23,14 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME			"Linux emulator - X11"
+#define GDISP_DRIVER_STRUCT				GDISP_X11
 
-#define GDISP_HARDWARE_CLEARS			FALSE
+#define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_FILLS			TRUE
 #define GDISP_HARDWARE_BITFILLS			FALSE
-#define GDISP_HARDWARE_SCROLL			FALSE
-#define GDISP_HARDWARE_PIXELREAD		FALSE
+#define GDISP_HARDWARE_SCROLL			TRUE
+#define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			FALSE
-#define GDISP_HARDWARE_CIRCLES			FALSE
-#define GDISP_HARDWARE_CIRCLEFILLS		FALSE
-#define GDISP_HARDWARE_ARCS				FALSE
-#define GDISP_HARDWARE_ARCFILLS			FALSE
 
 #define GDISP_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
 
-- 
cgit v1.2.3


From 0f7777395b30ea8cec02b3230ed250eee7d34f16 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sun, 29 Sep 2013 18:23:22 +0200
Subject: GDISP X driver fixes

---
 drivers/multiple/X/gdisp_lld.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index 9c6a7123..0e5e03b4 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -131,7 +131,6 @@ static int FatalXIOError(Display *d) {
 }
 
 LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
-{
 	XSizeHints				*pSH;
 	XSetWindowAttributes	xa;
 	XTextProperty			WindowTitle;
@@ -212,7 +211,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	gfxThreadClose(hth);
 	
     /* Initialise the GDISP structure to match */
-    g->g.Orientation = g->g_ROTATE_0;
+    g->g.Orientation = GDISP_ROTATE_0;
     g->g.Powermode = powerOn;
     g->g.Backlight = 100;
     g->g.Contrast = 50;
@@ -269,10 +268,10 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 		XImage *img;
 
 		img = XGetImage (dis, pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
-		color->pixel = XGetPixel (img, 0, 0);
+		color.pixel = XGetPixel (img, 0, 0);
 		XFree(img);
 		XQueryColor(dis, cmap, &color);
-		return RGB2COLOR(c.red>>8, c.green>>8, c.blue>>8);
+		return RGB2COLOR(color.red>>8, color.green>>8, color.blue>>8);
 	}
 #endif
 
-- 
cgit v1.2.3


From 3b1b5a4208ab8c29c9bb2f6eb448fd60e6cfe490 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sun, 29 Sep 2013 18:43:59 +0200
Subject: SSD1289 fixes

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 84ffa6d1..72db9914 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -47,7 +47,7 @@
 #define delay(us)					gfxSleepMicroseconds(us)
 #define delayms(ms)					gfxSleepMilliseconds(ms)
 
-static inline void set_cursor(coord_t x, coord_t y) {
+static inline void set_cursor(GDISPDriver* g, coord_t x, coord_t y) {
 	/* Reg 0x004E is an 8 bit value
 	 * Reg 0x004F is 9 bit
 	 * Use a bit mask to make sure they are not set too high
@@ -72,7 +72,7 @@ static inline void set_cursor(coord_t x, coord_t y) {
 	}
 }
 
-static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+static void set_viewport(GDISPDriver* g, coord_t x, coord_t y, coord_t cx, coord_t cy) {
 
 	//set_cursor(x, y);
 
@@ -108,11 +108,11 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
 			break;
 	}
 
-	set_cursor(x, y);
+	set_cursor(g, x, y);
 }
 
-static inline void reset_viewport(void) {
-	set_viewport(0, 0, g->g.Width, g->g.Height);
+static inline void reset_viewport(GDISPDriver* g) {
+	set_viewport(g, 0, 0, g->g.Width, g->g.Height);
 }
 
 /*===========================================================================*/
@@ -197,11 +197,11 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #if GDISP_HARDWARE_STREAM_WRITE
 	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
-		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
+		set_viewport(g, g->p.x, g->p.y, g->p.cx, g->p.cy);
 		stream_start();
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
-		write_data(color);
+		write_data(g->p.color);
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		stream_stop();
@@ -214,7 +214,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		uint16_t	dummy;
 
 		acquire_bus();
-		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
+		set_viewport(g, g->p.x, g->p.y, g->p.cx, g->p.cy);
 		stream_start();
 		setreadmode();
 		dummy = read_data();		// dummy read
-- 
cgit v1.2.3


From fdb74b412a01668795802840efe90ece3773478a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 01:21:10 +1000
Subject: More SSD1289 orientation fixes and tidy-up

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 94 +++++++++++++++------------------------
 1 file changed, 36 insertions(+), 58 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 72db9914..2fe5a1e4 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -47,35 +47,7 @@
 #define delay(us)					gfxSleepMicroseconds(us)
 #define delayms(ms)					gfxSleepMilliseconds(ms)
 
-static inline void set_cursor(GDISPDriver* g, coord_t x, coord_t y) {
-	/* Reg 0x004E is an 8 bit value
-	 * Reg 0x004F is 9 bit
-	 * Use a bit mask to make sure they are not set too high
-	 */
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_180:
-			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-x) & 0x00FF);
-			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-y) & 0x01FF);
-			break;
-		case GDISP_ROTATE_0:
-			write_reg(0x004e, x & 0x00FF);
-			write_reg(0x004f, y & 0x01FF);
-			break;
-		case GDISP_ROTATE_270:
-			write_reg(0x004e, y & 0x00FF);
-			write_reg(0x004f, x & 0x01FF);
-			break;
-		case GDISP_ROTATE_90:
-			write_reg(0x004e, (GDISP_SCREEN_WIDTH - y - 1) & 0x00FF);
-			write_reg(0x004f, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF);
-			break;
-	}
-}
-
-static void set_viewport(GDISPDriver* g, coord_t x, coord_t y, coord_t cx, coord_t cy) {
-
-	//set_cursor(x, y);
-
+static void set_viewport(GDISPDriver* g) {
 	/* Reg 0x44 - Horizontal RAM address position
 	 * 		Upper Byte - HEA
 	 * 		Lower Byte - HSA
@@ -84,35 +56,41 @@ static void set_viewport(GDISPDriver* g, coord_t x, coord_t y, coord_t cx, coord
 	 * 		Lower 9 bits gives 0-511 range in each value
 	 * 		0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
 	 */
-
+	/* Reg 0x004E is an 8 bit value
+	 * Reg 0x004F is 9 bit
+	 * Use a bit mask to make sure they are not set too high
+	 */
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
-			write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (x & 0x00FF));
-			write_reg(0x45, y & 0x01FF);
-			write_reg(0x46, (y+cy-1) & 0x01FF);
+			write_reg(0x44, (((g->p.x+g->p.cx-1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+			write_reg(0x45, g->p.y & 0x01FF);
+			write_reg(0x46, (g->p.y+g->p.cy-1) & 0x01FF);
+			write_reg(0x004e, g->p.x & 0x00FF);
+			write_reg(0x004f, g->p.y & 0x01FF);
 			break;
-		case GDISP_ROTATE_270:
-			write_reg(0x44, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
-			write_reg(0x45, x & 0x01FF);
-			write_reg(0x46, (x+cx-1) & 0x01FF);
+		case GDISP_ROTATE_90:
+			write_reg(0x44, (((g->p.y+g->p.cy-1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
+			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.x+g->p.cx)) & 0x01FF);
+			write_reg(0x46, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
+			write_reg(0x004e, g->p.y & 0x00FF);
+			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(0x44, (((GDISP_SCREEN_WIDTH-x-1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (x+cx)) & 0x00FF));
-			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(y+cy)) & 0x01FF);
-			write_reg(0x46, (GDISP_SCREEN_HEIGHT-y-1) & 0x01FF);
+			write_reg(0x44, (((GDISP_SCREEN_WIDTH-g->p.x-1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
+			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
+			write_reg(0x46, (GDISP_SCREEN_HEIGHT-g->p.y-1) & 0x01FF);
+			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
+			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
 			break;
-		case GDISP_ROTATE_90:
-			write_reg(0x44, (((GDISP_SCREEN_WIDTH - y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (y+cy)) & 0x00FF));
-			write_reg(0x45, (GDISP_SCREEN_HEIGHT - (x+cx)) & 0x01FF);
-			write_reg(0x46, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF);
+		case GDISP_ROTATE_270:
+			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
+			write_reg(0x44, (((GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH-(g->p.y+g->p.cy)) & 0x00FF));
+			write_reg(0x45, g->p.x & 0x01FF);
+			write_reg(0x46, (g->p.x+g->p.cx-1) & 0x01FF);
+			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
+			write_reg(0x004f, g->p.x & 0x01FF);
 			break;
 	}
-
-	set_cursor(g, x, y);
-}
-
-static inline void reset_viewport(GDISPDriver* g) {
-	set_viewport(g, 0, 0, g->g.Width, g->g.Height);
 }
 
 /*===========================================================================*/
@@ -197,7 +175,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #if GDISP_HARDWARE_STREAM_WRITE
 	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
-		set_viewport(g, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		set_viewport(g);
 		stream_start();
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
@@ -214,7 +192,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		uint16_t	dummy;
 
 		acquire_bus();
-		set_viewport(g, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		set_viewport(g);
 		stream_start();
 		setreadmode();
 		dummy = read_data();		// dummy read
@@ -232,7 +210,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
 	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
 		acquire_bus();
-		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
+		set_viewport(g);
 		stream_start();
 		dma_with_noinc(&color, g->p.cx*g->p.cy)
 		stream_stop();
@@ -248,7 +226,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		buffer = (pixel_t *)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
 
 		acquire_bus();
-		set_viewport(g->p.x, g->p.y, g->p.cx, g->p.cy);
+		set_viewport(g);
 		stream_start();
 
 		if (g->p.x2 == g->p.cx) {
@@ -310,8 +288,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			case GDISP_ROTATE_90:
 				acquire_bus();
 				write_reg(0x0001, 0x293F);
-				/* ID = 11 AM = 1 */
-				write_reg(0x0011, 0x6078);
+				/* ID = 01 AM = 1 */
+				write_reg(0x0011, 0x6048);
 				release_bus();
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
@@ -328,8 +306,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			case GDISP_ROTATE_270:
 				acquire_bus();
 				write_reg(0x0001, 0x293F);
-				/* ID = 01 AM = 1 */
-				write_reg(0x0011, 0x6048);
+				/* ID = 11 AM = 1 */
+				write_reg(0x0011, 0x6078);
 				release_bus();
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
-- 
cgit v1.2.3


From 39c10335a38c5ebd13613c5d3d433a0682fc2a6c Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 02:11:03 +1000
Subject: Scolling fix in X driver and removal of compiler warning.

---
 drivers/multiple/X/gdisp_lld.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index 0e5e03b4..c60e2085 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -60,8 +60,6 @@ int				depth;
 #endif
 
 static void ProcessEvent(void) {
-	XColor	col;
-
 	switch(evt.type) {
 	case Expose:
 		XCopyArea(dis, pix, win, gc,
@@ -282,7 +280,7 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
 		} else {
 			XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
-			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y-lines, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y-g->p.y1, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
 		}
 	}
 #endif
-- 
cgit v1.2.3


From 3480001a799fe072b264bac58cca4d176b05ce3a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 13:33:35 +1000
Subject: More orientation fixes for SSD1289. Orientation is now supported
 purely in RAM addressing direction which means the orientation of the display
 can be changed without affecting existing information on the display. Drawing
 then occurs in the new orientation.

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 16 ++++++----------
 1 file changed, 6 insertions(+), 10 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 2fe5a1e4..68cdf675 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -76,9 +76,9 @@ static void set_viewport(GDISPDriver* g) {
 			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(0x44, (((GDISP_SCREEN_WIDTH-g->p.x-1) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
+			write_reg(0x44, (((GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
 			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
-			write_reg(0x46, (GDISP_SCREEN_HEIGHT-g->p.y-1) & 0x01FF);
+			write_reg(0x46, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
 			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
 			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
 			break;
@@ -278,7 +278,6 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
 				acquire_bus();
-				write_reg(0x0001, 0x2B3F);
 				/* ID = 11 AM = 0 */
 				write_reg(0x0011, 0x6070);
 				release_bus();
@@ -287,17 +286,15 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				break;
 			case GDISP_ROTATE_90:
 				acquire_bus();
-				write_reg(0x0001, 0x293F);
 				/* ID = 01 AM = 1 */
-				write_reg(0x0011, 0x6048);
+				write_reg(0x0011, 0x6058);
 				release_bus();
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
 				acquire_bus();
-				write_reg(0x0001, 0x2B3F);
-				/* ID = 01 AM = 0 */
+				/* ID = 00 AM = 0 */
 				write_reg(0x0011, 0x6040);
 				release_bus();
 				g->g.Height = GDISP_SCREEN_HEIGHT;
@@ -305,9 +302,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				break;
 			case GDISP_ROTATE_270:
 				acquire_bus();
-				write_reg(0x0001, 0x293F);
-				/* ID = 11 AM = 1 */
-				write_reg(0x0011, 0x6078);
+				/* ID = 10 AM = 1 */
+				write_reg(0x0011, 0x6068);
 				release_bus();
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
-- 
cgit v1.2.3


From 2c11cc3b942f2e3413a93f86d11db23c8cf6b1a7 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 13:39:39 +1000
Subject: SSD1289 tidy up

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 68cdf675..5743afc0 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -42,8 +42,6 @@
 
 // Some common routines and macros
 #define write_reg(reg, data)		{ write_index(reg); write_data(data); }
-#define stream_start()				write_index(0x0022);
-#define stream_stop()
 #define delay(us)					gfxSleepMicroseconds(us)
 #define delayms(ms)					gfxSleepMilliseconds(ms)
 
@@ -55,9 +53,8 @@ static void set_viewport(GDISPDriver* g) {
 	 * Reg 0x45,0x46 - Vertical RAM address position
 	 * 		Lower 9 bits gives 0-511 range in each value
 	 * 		0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
-	 */
-	/* Reg 0x004E is an 8 bit value
-	 * Reg 0x004F is 9 bit
+	 * Reg 0x004E is an 8 bit value - start x position
+	 * Reg 0x004F is 9 bit - start y position
 	 * Use a bit mask to make sure they are not set too high
 	 */
 	switch(g->g.Orientation) {
@@ -91,6 +88,7 @@ static void set_viewport(GDISPDriver* g) {
 			write_reg(0x004f, g->p.x & 0x01FF);
 			break;
 	}
+	write_index(0x0022);
 }
 
 /*===========================================================================*/
@@ -176,13 +174,11 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
 		set_viewport(g);
-		stream_start();
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
 		write_data(g->p.color);
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
-		stream_stop();
 		release_bus();
 	}
 #endif
@@ -193,7 +189,6 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 		acquire_bus();
 		set_viewport(g);
-		stream_start();
 		setreadmode();
 		dummy = read_data();		// dummy read
 	}
@@ -202,7 +197,6 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
 		setwritemode();
-		stream_stop();
 		release_bus();
 	}
 #endif
@@ -211,9 +205,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
 		acquire_bus();
 		set_viewport(g);
-		stream_start();
 		dma_with_noinc(&color, g->p.cx*g->p.cy)
-		stream_stop();
 		release_bus();
 	}
 #endif
@@ -227,15 +219,12 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 		acquire_bus();
 		set_viewport(g);
-		stream_start();
-
 		if (g->p.x2 == g->p.cx) {
 			dma_with_inc(buffer, g->p.cx*g->p.cy);
 		} else {
 			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
 				dma_with_inc(buffer, g->p.cy);
 		}
-		stream_stop();
 		release_bus();
 	}
 #endif
-- 
cgit v1.2.3


From dd54d42f004adfb54f8512ee8ea61b884e855672 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 15:40:52 +1000
Subject: Allow initial driver settings to be overridden by the board file

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c |  2 +-
 drivers/gdisp/SSD1289/gdisp_lld.c      | 12 +++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index bcccef80..a41ab3c9 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -65,8 +65,8 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#include "GE8.h"
 #include "gdisp_lld_board.h"
+#include "GE8.h"
 
 #define GDISP_SCAN_LINES			132
 
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 5743afc0..c724e80b 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -19,6 +19,7 @@
 
 #define GDISP_LLD_DECLARATIONS
 #include "gdisp/lld/gdisp_lld.h"
+#include "gdisp_lld_board.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -30,16 +31,17 @@
 #ifndef GDISP_SCREEN_WIDTH
 	#define GDISP_SCREEN_WIDTH		240
 #endif
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
-
 // Some common routines and macros
 #define write_reg(reg, data)		{ write_index(reg); write_data(data); }
 #define delay(us)					gfxSleepMicroseconds(us)
-- 
cgit v1.2.3


From 07f96ec3ee34fd4b4fffe2e6afbe50e982555fcb Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 15:41:32 +1000
Subject: HX8347D driver ported to new streaming structure (untested)

---
 drivers/gdisp/HX8347D/HX8347D.h                    |   2 +-
 drivers/gdisp/HX8347D/gdisp_lld.c                  | 446 +++++----------------
 .../HX8347D/gdisp_lld_board_st_stm32f4_discovery.h | 155 ++++---
 drivers/gdisp/HX8347D/gdisp_lld_board_template.h   |  49 +--
 drivers/gdisp/HX8347D/gdisp_lld_config.h           |   7 +-
 5 files changed, 192 insertions(+), 467 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/HX8347D.h b/drivers/gdisp/HX8347D/HX8347D.h
index b35dda12..280cd748 100644
--- a/drivers/gdisp/HX8347D/HX8347D.h
+++ b/drivers/gdisp/HX8347D/HX8347D.h
@@ -33,7 +33,7 @@
 #define HX8347D_REG_PSLL                0x0b    /* Partial area start row low */
 #define HX8347D_REG_PELH                0x0c    /* Partial area end row high */
 #define HX8347D_REG_PELL                0x0d    /* Partial area end row low */
-#define HX8347D_REG_TFAH                0x0e    /* Vertical srcoll top fixed area high */
+#define HX8347D_REG_TFAH                0x0e    /* Vertical scroll top fixed area high */
 #define HX8347D_REG_TFAL                0x0f    /* Vertical scroll top fixed area low */
 
 #define HX8347D_REG_VSAH                0x10    /* Vertical scroll height area high */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
index bcb6dfc0..a1e2c15b 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.c
+++ b/drivers/gdisp/HX8347D/gdisp_lld.c
@@ -15,12 +15,11 @@
 
 #include "gfx.h"
 
-#include "HX8347D.h"
-
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
+#include "gdisp_lld_board.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -32,74 +31,44 @@
 #ifndef GDISP_SCREEN_WIDTH
 	#define GDISP_SCREEN_WIDTH		240
 #endif
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	50
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
-
-// Some common routines and macros
-#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
-#define write_ram(color1, color2)   { write_index(0x22); write_ram8(color1,color2); }
-#define stream_start()				{ write_index(0x22); spiStart(&SPID1, &spi1cfg2);      }
-#define stream_stop()               {while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));palSetPad(GPIOA, 4);spiStart(&SPID1, &spi1cfg1); }
-#define delay(us)					gfxSleepMicroseconds(us)
-#define delayms(ms)					gfxSleepMilliseconds(ms)
-
-static inline void set_cursor(coord_t x, coord_t y) {
-			write_reg(HX8347D_REG_SCL, (uint8_t) x);
-		    write_reg(HX8347D_REG_SCH, (uint8_t) (x >> 8));
-		    write_reg(HX8347D_REG_SPL, (uint8_t) y);
-		    write_reg(HX8347D_REG_SPH, (uint8_t) (y >> 8));
-}
-
-static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-		    write_reg(HX8347D_REG_SCL, (uint8_t) x);
-		    write_reg(HX8347D_REG_SCH, (uint8_t) (x >> 8));
-		    write_reg(HX8347D_REG_ECL, (uint8_t) (x + cx -1));
-		    write_reg(HX8347D_REG_ECH, (uint8_t) ((x + cx -1) >> 8));
-		    write_reg(HX8347D_REG_SPL, (uint8_t) y);
-		    write_reg(HX8347D_REG_SPH, (uint8_t) (y >> 8));
-		    write_reg(HX8347D_REG_EPL, (uint8_t) (y + cy -1));
-		    write_reg(HX8347D_REG_EPH, (uint8_t) ((y + cy -1) >> 8));
-}
+#include "HX8347D.h"
 
-static inline void reset_viewport(void) {
-	set_viewport(0, 0, GDISP.Width, GDISP.Height);
+static inline void set_viewport(GDISPDriver* g) {
+	write_reg(HX8347D_REG_SCL, (uint8_t) g->p.x);
+	write_reg(HX8347D_REG_SCH, (uint8_t) (g->p.x >> 8));
+	write_reg(HX8347D_REG_ECL, (uint8_t) (g->p.x + g->p.cx -1));
+	write_reg(HX8347D_REG_ECH, (uint8_t) ((g->p.x + g->p.cx -1) >> 8));
+	write_reg(HX8347D_REG_SPL, (uint8_t) g->p.y);
+	write_reg(HX8347D_REG_SPH, (uint8_t) (g->p.y >> 8));
+	write_reg(HX8347D_REG_EPL, (uint8_t) (g->p.y + g->p.cy -1));
+	write_reg(HX8347D_REG_EPH, (uint8_t) ((g->p.y + g->p.cy -1) >> 8));
+	write_index(HX8347D_REG_SRAMWC);
 }
 
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
 	init_board();
 
 	// Hardware reset
 	setpin_reset(TRUE);
-	delayms(1);
+	gfxSleepMilliseconds(1);
 	setpin_reset(FALSE);
-	delayms(5);
+	gfxSleepMilliseconds(5);
 
 	// Get the bus for the following initialisation commands
 	acquire_bus();
@@ -154,329 +123,104 @@ bool_t gdisp_lld_init(void) {
 	write_reg(HX8347D_REG_OSCCL, 0x01);                  /* OSC Control 2                        */
 	write_reg(HX8347D_REG_DMODE, 0x00);                  /* Display Mode Control                 */
 	write_reg(HX8347D_REG_PWC6, 0x88);                   /* Power Control 6                      */
-	delayms(5);                                          /* Delay 5 ms                           */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
 	write_reg(HX8347D_REG_PWC6, 0x80);                   /* Power Control 6                      */
-	delayms(5);                                          /* Delay 5 ms                           */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
 	write_reg(HX8347D_REG_PWC6, 0x90);                   /* Power Control 6                      */
-	delayms(5);                                          /* Delay 5 ms                           */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
 	write_reg(HX8347D_REG_PWC6, 0xD0);                   /* Power Control 6                      */
-	delayms(5);                                          /* Delay 5 ms                           */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
 	write_reg(HX8347D_REG_COLMOD, 0x05);                 /* Colmod 16Bit/Pixel                   */
 	write_reg(HX8347D_REG_PCH, 0x00);                    /* Panel Characteristic                 */
 	write_reg(HX8347D_REG_DC3, 0x38);                    /* Display Control 3                    */
-	delayms(40);
+	gfxSleepMilliseconds(40);                            /* Delay 40 ms                          */
 	write_reg(HX8347D_REG_DC3, 0x3C);                    /* Display Control 3                    */
 	write_reg(HX8347D_REG_MAC, 0x08);                    /* Memory access control                */
 
-	write_reg(HX8347D_REG_SCL, 0x00);
-	write_reg(HX8347D_REG_SCH, 0x00);
-	write_reg(HX8347D_REG_ECL, 0xef);
-	write_reg(HX8347D_REG_ECH, 0x00);
-	write_reg(HX8347D_REG_SPL, 0x00);
-	write_reg(HX8347D_REG_SPH, 0x00);
-	write_reg(HX8347D_REG_EPL, 0x3f);
-	write_reg(HX8347D_REG_EPH, 0x01);
-
  	// Release the bus
 	release_bus();
 
 	/* Turn on the backlight */
 	set_backlight(GDISP_INITIAL_BACKLIGHT);
 
-   /* Initialise the GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	/* 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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	
-	acquire_bus();
-	set_cursor(x, y);
-	write_ram((color >> 8) & 0xFF, color & 0xFF);
-	release_bus();
-}
-
-/* ---- Optional Routines ---- */
-/*
-	All the below routines are optional.
-	Defining them will increase speed but everything
-	will work if they are not defined.
-	If you are not using a routine - turn it off using
-	the appropriate GDISP_HARDWARE_XXXX macro.
-	Don't bother coding for obvious similar routines if
-	there is no performance penalty as the emulation software
-	makes a good job of using similar routines.
-		eg. If gfillarea() is defined there is little
-			point in defining clear() unless the
-			performance bonus is significant.
-	For good performance it is suggested to implement
-		fillarea() and blitarea().
-*/
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Clear the display.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] color    The color of the pixel
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_clear(color_t color) {
-		unsigned i;
-
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
-		reset_viewport();
-		stream_start();
-		for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
-		  write_ram16(color);
-		stream_stop();
-		release_bus();
+		set_viewport(g);
+		busmode16();
 	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		unsigned i, area;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		area = cx*cy;
-
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-		for(i = 0; i < area; i++)
-		  write_ram16(color);
-		stream_stop();
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+		write_ram16(g->p.color);
 	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t endx, endy;
-		unsigned lg;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-
-		endx = srcx + cx;
-		endy = y + cy;
-		lg = srccx - cx;
-		buffer += srcx + srcy * srccx;
-		for(; y < endy; y++, buffer += lg)
-			for(x=srcx; x < endx; x++)
-				write_data(*buffer++);
-		stream_stop();
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
+		busmode8();
 		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The pixel to be read
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
-}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, abslines, j;
-		static int gap;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-	}
-#endif
-
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief	Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT		- Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
-			case GDISP_CONTROL_ORIENTATION:
-				if (GDISP.Orientation == (gdisp_orientation_t)value)
-					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						acquire_bus();
-						write_reg(HX8347D_REG_MAC, 0x08);                    /* Memory access control */
-		                write_reg(HX8347D_REG_ECL, 0xef);
-		                write_reg(HX8347D_REG_ECH, 0x00);
-		                write_reg(HX8347D_REG_EPL, 0x3f);
-		                write_reg(HX8347D_REG_EPH, 0x01);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_90:
-						acquire_bus();
-						write_reg(HX8347D_REG_MAC, 0x68);                    /* Memory access control */
-                        write_reg(HX8347D_REG_ECL, 0x3f);
-                        write_reg(HX8347D_REG_ECH, 0x01);
-                        write_reg(HX8347D_REG_EPL, 0xef);
-                        write_reg(HX8347D_REG_EPH, 0x00);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-
-					case GDISP_ROTATE_180:
-						acquire_bus();
-						write_reg(HX8347D_REG_MAC, 0xc8);                    /* Memory access control */
-		                write_reg(HX8347D_REG_ECL, 0xef);
-		                write_reg(HX8347D_REG_ECH, 0x00);
-		                write_reg(HX8347D_REG_EPL, 0x3f);
-		                write_reg(HX8347D_REG_EPH, 0x01);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_270:
-						acquire_bus();
-						write_reg(HX8347D_REG_MAC, 0xa8);                    /* Memory access control */
-                        write_reg(HX8347D_REG_ECL, 0x3f);
-                        write_reg(HX8347D_REG_ECH, 0x01);
-                        write_reg(HX8347D_REG_EPL, 0xef);
-                        write_reg(HX8347D_REG_EPH, 0x00);
-						release_bus();
-                        GDISP.Height = GDISP_SCREEN_WIDTH;
-                        GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-
-					default:
-						return;
-				}
-
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
-				return;
-
-			case GDISP_CONTROL_BACKLIGHT:
-				if ((unsigned)value > 100)
-					value = (void *)100;
-				set_backlight((unsigned)value);
-				GDISP.Backlight = (unsigned)value;
-				return;
-
-			default:
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+		switch(g->p.x) {
+		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();
+					write_reg(HX8347D_REG_MAC, 0x08);                    /* Memory access control */
+					release_bus();
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_90:
+					acquire_bus();
+					write_reg(HX8347D_REG_MAC, 0x68);                    /* Memory access control */
+					release_bus();
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				case GDISP_ROTATE_180:
+					acquire_bus();
+					write_reg(HX8347D_REG_MAC, 0xc8);                    /* Memory access control */
+					release_bus();
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_270:
+					acquire_bus();
+					write_reg(HX8347D_REG_MAC, 0xa8);                    /* Memory access control */
+					release_bus();
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				default:
+					return;
+			}
+			g->g.Orientation = (orientation_t)value;
+			return;
+        case GDISP_CONTROL_BACKLIGHT:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+            set_backlight((unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		default:
+			return;
 		}
 	}
 #endif
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h b/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
index 984b92dd..8365fe74 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
+++ b/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
@@ -16,21 +16,31 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
-#define SET_RST		palSetPad(GPIOB, 8);
-#define CLR_RST		palClearPad(GPIOB, 8);
+// Overrides
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	50
+#endif
+
+/* Pin assignments */
+#define SET_RST		palSetPad(GPIOB, 8)
+#define CLR_RST		palClearPad(GPIOB, 8)
+#define SET_DATA	palSetPad(GPIOB, 9)
+#define CLR_DATA	palClearPad(GPIOB, 9)
+#define SET_CS		palSetPad(GPIOA, 4)
+#define CLR_CS		palClearPad(GPIOA, 4)
 
 /* PWM configuration structure. We use timer 4 channel 2 (orange LED on board). */
 static const PWMConfig pwmcfg = {
-  1000000,		/* 1 MHz PWM clock frequency. */
-  100,			/* PWM period is 100 cycles. */
-  NULL,
-  {
-   {PWM_OUTPUT_ACTIVE_HIGH, NULL},
-   {PWM_OUTPUT_ACTIVE_HIGH, NULL},
-   {PWM_OUTPUT_ACTIVE_HIGH, NULL},
-   {PWM_OUTPUT_ACTIVE_HIGH, NULL}
-  },
-  0
+	1000000,		/* 1 MHz PWM clock frequency. */
+	100,			/* PWM period is 100 cycles. */
+	NULL,
+	{
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
+	},
+	0
 };
 
 /*
@@ -38,12 +48,12 @@ static const PWMConfig pwmcfg = {
  * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
  * The slave select line is the pin 4 on the port GPIOA.
  */
-static const SPIConfig spi1cfg1 = {
-  NULL,
-  /* HW dependent part.*/
-  GPIOA,
-  4,
-  0 //SPI_CR1_BR_0
+static const SPIConfig spi1cfg_8bit = {
+	NULL,
+	/* HW dependent part.*/
+	GPIOA,
+	4,
+	0 //SPI_CR1_BR_0
 };
 
 /*
@@ -51,48 +61,42 @@ static const SPIConfig spi1cfg1 = {
  * Speed 42MHz, CPHA=0, CPOL=0, 16bits frames, MSb transmitted first.
  * The slave select line is the pin 4 on the port GPIOA.
  */
-static const SPIConfig spi1cfg2 = {
-  NULL,
-  /* HW dependent part.*/
-  GPIOA,
-  4,
-  SPI_CR1_DFF //SPI_CR1_BR_0
+static const SPIConfig spi1cfg_16bit = {
+	NULL,
+	/* HW dependent part.*/
+	GPIOA,
+	4,
+	SPI_CR1_DFF //SPI_CR1_BR_0
 };
 
 /**
  * @brief   Initialise the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
+ * @notes	This board definition uses GPIO and SPI. It assumes exclusive access to these GPIO pins but not necessarily the SPI port.
  *
  * @notapi
  */
 static inline void init_board(void) {
-
 	/* Display backlight control */
 	/* TIM4 is an alternate function 2 (AF2) */
 	pwmStart(&PWMD4, &pwmcfg);
 	palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
 	pwmEnableChannel(&PWMD4, 1, 100);
 
-	palSetPadMode(GPIOB,  8, PAL_MODE_OUTPUT_PUSHPULL |
-	                               PAL_STM32_OSPEED_HIGHEST);           /* RST    */
-	palSetPadMode(GPIOB,  9, PAL_MODE_OUTPUT_PUSHPULL |
-	                               PAL_STM32_OSPEED_HIGHEST);           /* RS     */
+	palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RST    */
+	palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RS     */
 	/*
-	   * Initializes the SPI driver 1. The SPI1 signals are routed as follow:
-	   * PB12 - NSS.
-	   * PB13 - SCK.
-	   * PB14 - MISO.
-	   * PB15 - MOSI.
-	   */
-	  spiStart(&SPID1, &spi1cfg1);
-	  palSetPad(GPIOA, 4);
-	  palSetPadMode(GPIOA,  4, PAL_MODE_OUTPUT_PUSHPULL |
-	                           PAL_STM32_OSPEED_HIGHEST);           /* NSS.     */
-	  palSetPadMode(GPIOA,  5, PAL_MODE_ALTERNATE(5) |
-	                           PAL_STM32_OSPEED_HIGHEST);           /* SCK.     */
-	  palSetPadMode(GPIOA,  6, PAL_MODE_ALTERNATE(5));              /* MISO.    */
-	  palSetPadMode(GPIOA,  7, PAL_MODE_ALTERNATE(5) |
-	                           PAL_STM32_OSPEED_HIGHEST);           /* MOSI.    */
+	 * Initializes the SPI driver 1. The SPI1 signals are routed as follow:
+	 * PB12 - NSS.
+	 * PB13 - SCK.
+	 * PB14 - MISO.
+	 * PB15 - MOSI.
+	 */
+	SET_CS; SET_DATA;
+	spiStart(&SPID1, &spi1cfg_8bit);
+	palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* NSS.     */
+	palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* SCK.     */
+	palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));										/* MISO.    */
+	palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* MOSI.    */
 
 }
 
@@ -124,79 +128,70 @@ static inline void set_backlight(uint8_t percent) {
 
 /**
  * @brief   Take exclusive control of the bus
- * @note	Not needed, not implemented
- *
  * @notapi
  */
 static inline void acquire_bus(void) {
 	spiAcquireBus(&SPID1);
+    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));		// Safety
+	CLR_CS;
 }
 
 /**
  * @brief   Release exclusive control of the bus
- * @note	Not needed, not implemented
- *
  * @notapi
  */
 static inline void release_bus(void) {
+	SET_CS;
 	spiReleaseBus(&SPID1);
 }
 
 /**
- * @brief   Send data to the index register.
+ * @brief   Set the bus in 16 bit mode
+ * @notapi
+ */
+static inline void busmode16(void) {
+	spiStart(&SPID1, &spi1cfg_16bit);
+}
+
+/**
+ * @brief   Set the bus in 8 bit mode (the default)
+ * @notapi
+ */
+static inline void busmode8(void) {
+	spiStart(&SPID1, &spi1cfg_8bit);
+}
+
+/**
+ * @brief   Set which index register to use.
  *
  * @param[in] index		The index register to set
  *
  * @notapi
  */
 static inline void write_index(uint8_t cmd) {
-    palClearPad(GPIOB, 9);
-    palClearPad(GPIOA, 4);
-    while((SPI1->SR & SPI_SR_TXE) == 0);
+    CLR_DATA;
     SPI1->DR = cmd;
     while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-    palSetPad(GPIOB, 9);
+    SET_DATA;
 }
 
 /**
- * @brief   Send data to the lcd.
+ * @brief   Send a command to the lcd.
  *
  * @param[in] data		The data to send
  *
  * @notapi
  */
-static inline void write_data(uint8_t data) {
+static inline void write_reg(uint8_t cmd, uint8_t data) {
+	write_index(cmd);
     SPI1->DR = data;
     while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-    palSetPad(GPIOA, 4);
-}
-
-static inline void write_ram8(uint8_t data1, uint8_t data2) {
-    SPI1->DR = data1;
-    while((SPI1->SR & SPI_SR_TXE) == 0);
-    SPI1->DR = data2;
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-    palSetPad(GPIOA, 4);
 }
 
 static inline void write_ram16(uint16_t data) {
-    while((SPI1->SR & SPI_SR_TXE) == 0);
     SPI1->DR      = data;
+    while((SPI1->SR & SPI_SR_TXE) == 0);
 }
 
-#if GDISP_HARDWARE_READPIXEL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- *
- * @notapi
- */
-static inline uint16_t read_data(void) {
-}
-#endif
-
 #endif /* _GDISP_LLD_BOARD_H */
 /** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_board_template.h b/drivers/gdisp/HX8347D/gdisp_lld_board_template.h
index 295a7997..d3b71d97 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld_board_template.h
+++ b/drivers/gdisp/HX8347D/gdisp_lld_board_template.h
@@ -18,8 +18,6 @@
 
 /**
  * @brief   Initialise the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- *
  * @notapi
  */
 static inline void init_board(void) {
@@ -50,8 +48,6 @@ static inline void set_backlight(uint8_t percent) {
 
 /**
  * @brief   Take exclusive control of the bus
- * @note	Not needed, not implemented
- *
  * @notapi
  */
 static inline void acquire_bus(void) {
@@ -60,8 +56,6 @@ static inline void acquire_bus(void) {
 
 /**
  * @brief   Release exclusive control of the bus
- * @note	Not needed, not implemented
- *
  * @notapi
  */
 static inline void release_bus(void) {
@@ -69,51 +63,46 @@ static inline void release_bus(void) {
 }
 
 /**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
+ * @brief   Set the bus in 16 bit mode
  * @notapi
  */
-static inline void write_index(uint8_t cmd) {
+static inline void busmode16(void) {
 
 }
 
 /**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- *
+ * @brief   Set the bus in 8 bit mode (the default)
  * @notapi
  */
-static inline void write_data(uint8_t data) {
-
-
-
-}
-
-static inline void write_ram8(uint8_t data1, uint8_t data2) {
+static inline void busmode8(void) {
 
 }
 
-static inline void write_ram16(uint16_t data) {
+/**
+ * @brief   Set which index register to use.
+ *
+ * @param[in] index		The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(uint8_t cmd) {
 
 }
 
-#if GDISP_HARDWARE_READPIXEL || defined(__DOXYGEN__)
 /**
- * @brief   Read data from the lcd.
+ * @brief   Send a command to the lcd.
  *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
+ * @param[in] data		The data to send
  *
  * @notapi
  */
-static inline uint16_t read_data(void) {
+static inline void write_reg(uint8_t cmd, uint8_t data) {
+
+}
+
+static inline void write_ram16(uint16_t data) {
 
 }
-#endif
 
 #endif /* _GDISP_LLD_BOARD_H */
 /** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_config.h b/drivers/gdisp/HX8347D/gdisp_lld_config.h
index 7bf47ade..a5a8e2b8 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld_config.h
+++ b/drivers/gdisp/HX8347D/gdisp_lld_config.h
@@ -23,12 +23,9 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"HX8347D"
+#define GDISP_DRIVER_STRUCT				GDISP_HX8347D
 
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			FALSE
-#define GDISP_HARDWARE_PIXELREAD		FALSE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-- 
cgit v1.2.3


From fd01f1a4f3569e84884c46388e2e3df7e1647365 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 16:25:46 +1000
Subject: ILI9320 driver ported to streaming interface.

---
 drivers/gdisp/ILI9320/gdisp_lld.c                  | 752 +++++++--------------
 .../ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h   |  19 +-
 .../ILI9320/gdisp_lld_board_olimex_stm32_lcd.h     |  18 +-
 drivers/gdisp/ILI9320/gdisp_lld_board_template.h   |  20 +-
 drivers/gdisp/ILI9320/gdisp_lld_config.h           |  12 +-
 5 files changed, 301 insertions(+), 520 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index c432cd35..8dc529dd 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -8,19 +8,14 @@
 /**
  * @file    drivers/gdisp/ILI9320/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9320 display.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#if GFX_USE_GDISP
 
-#include "gdisp_lld_board.h"
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -36,15 +31,20 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_SCREEN_WIDTH		240
-#define GDISP_SCREEN_HEIGHT		320
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
+#include "gdisp_lld_board.h"
 
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver local variables.                                                   */
@@ -54,531 +54,293 @@ uint32_t DISPLAY_CODE;
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
-static inline void lld_lcdDelay(uint16_t us) {
-	gfxSleepMicroseconds(us);
-}
-
-static inline void lld_lcdWriteIndex(uint16_t index) {
-	gdisp_lld_write_index(index);
-}
-
-static inline void lld_lcdWriteData(uint16_t data) {
-	gdisp_lld_write_data(data);
-}
-
-static inline void lld_lcdWriteReg(uint16_t lcdReg, uint16_t lcdRegValue) {
-	gdisp_lld_write_index(lcdReg);
-	gdisp_lld_write_data(lcdRegValue);
-}
-
-static inline uint16_t lld_lcdReadData(void) {
-	return gdisp_lld_read_data();
-}
 
-static inline uint16_t lld_lcdReadReg(uint16_t lcdReg) {
-    volatile uint16_t dummy;
-
-    gdisp_lld_write_index(lcdReg);
-    dummy = lld_lcdReadData();
-    (void)dummy;
-
-    return lld_lcdReadData();
-}
-
-static inline void lld_lcdWriteStreamStart(void) {
-	lld_lcdWriteIndex(0x0022);
-}
-	
-static inline void lld_lcdWriteStreamStop(void) {
+#define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
+#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
 
-}
-
-static inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) {
-	uint16_t i;
-
-	for(i = 0; i < size; i++)
-		lld_lcdWriteData(buffer[i]);
-}
-
-static inline void lld_lcdReadStreamStart(void) {
-	lld_lcdWriteIndex(0x0022);
-}
-
-static inline void lld_lcdReadStreamStop(void) {
-
-}
-
-static inline void lld_lcdReadStream(uint16_t *buffer, size_t size) {
-	uint16_t i;
-	volatile uint16_t dummy;
-
-	dummy = lld_lcdReadData();
-	(void)dummy;
+static void set_viewport(uint16_t x, uint16_t y, uint16_t cx, uint16_t cy) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(0x0050, x);
+			write_reg(0x0051, x + cx - 1);
+			write_reg(0x0052, y);
+			write_reg(0x0053, y + cy - 1);
+			write_reg(0x0020, x);
+			write_reg(0x0021, y);
+			break;
 
-	for(i = 0; i < size; i++)
-		buffer[i] = lld_lcdReadData();
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(0x0050, y);
+			write_reg(0x0051, y + cy - 1);
+			write_reg(0x0052, x);
+			write_reg(0x0053, x + cx - 1);
+			write_reg(0x0020, y);
+			write_reg(0x0021, x);
+			break;
+	}
+	write_index(0x0022);
 }
 
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
-	gdisp_lld_init_board();
+	init_board();
 
 	/* Hardware reset */
-	gdisp_lld_reset_pin(TRUE);
-	lld_lcdDelay(1000);
-	gdisp_lld_reset_pin(FALSE);
-	lld_lcdDelay(1000);
-
-    DISPLAY_CODE = lld_lcdReadReg(0);
-    lld_lcdWriteReg(0x0000, 0x0001); //start Int. osc
-    lld_lcdDelay(500);
-    lld_lcdWriteReg(0x0001, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
-    lld_lcdWriteReg(0x0002, 0x0700); //select  the line inversion
-    lld_lcdWriteReg(0x0003, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
-    lld_lcdWriteReg(0x0004, 0x0000); //Resize control(No resizing)
-    lld_lcdWriteReg(0x0008, 0x0202); //front and back porch 2 lines
-    lld_lcdWriteReg(0x0009, 0x0000); //select normal scan
-    lld_lcdWriteReg(0x000A, 0x0000); //display control 4
-    lld_lcdWriteReg(0x000C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,     
-    lld_lcdWriteReg(0x000D, 0x0000); //Frame marker position
-    lld_lcdWriteReg(0x000F, 0x0000); //selects clk, enable and sync signal polarity,
-    lld_lcdWriteReg(0x0010, 0x0000); //  
-    lld_lcdWriteReg(0x0011, 0x0000); //power control 2 reference voltages = 1:1,
-    lld_lcdWriteReg(0x0012, 0x0000); //power control 3 VRH
-    lld_lcdWriteReg(0x0013, 0x0000); //power control 4 VCOM amplitude
-    lld_lcdDelay(500);
-    lld_lcdWriteReg(0x0010, 0x17B0); //power control 1 BT,AP
-    lld_lcdWriteReg(0x0011, 0x0137); //power control 2 DC,VC
-    lld_lcdDelay(500);
-    lld_lcdWriteReg(0x0012, 0x0139); //power control 3 VRH
-    lld_lcdDelay(500);
-    lld_lcdWriteReg(0x0013, 0x1d00); //power control 4 vcom amplitude
-    lld_lcdWriteReg(0x0029, 0x0011); //power control 7 VCOMH
-    lld_lcdDelay(500);
-    lld_lcdWriteReg(0x0030, 0x0007);
-    lld_lcdWriteReg(0x0031, 0x0403);
-    lld_lcdWriteReg(0x0032, 0x0404);
-    lld_lcdWriteReg(0x0035, 0x0002);
-    lld_lcdWriteReg(0x0036, 0x0707);
-    lld_lcdWriteReg(0x0037, 0x0606);
-    lld_lcdWriteReg(0x0038, 0x0106);
-    lld_lcdWriteReg(0x0039, 0x0007);
-    lld_lcdWriteReg(0x003c, 0x0700);
-    lld_lcdWriteReg(0x003d, 0x0707);
-    lld_lcdWriteReg(0x0020, 0x0000); //starting Horizontal GRAM Address
-    lld_lcdWriteReg(0x0021, 0x0000); //starting Vertical GRAM Address
-    lld_lcdWriteReg(0x0050, 0x0000); //Horizontal GRAM Start Position
-    lld_lcdWriteReg(0x0051, 0x00EF); //Horizontal GRAM end Position
-    lld_lcdWriteReg(0x0052, 0x0000); //Vertical GRAM Start Position
-    lld_lcdWriteReg(0x0053, 0x013F); //Vertical GRAM end Position
+	setpin_reset(TRUE);
+	gfxSleepMicroseconds(1000);
+	setpin_reset(FALSE);
+	gfxSleepMicroseconds(1000);
+
+	acquire_bus();
+	write_index(0);				// Get controller version
+	dummy_read();
+    DISPLAY_CODE = read_data();
+    write_reg(0x0000, 0x0001); //start Int. osc
+    gfxSleepMicroseconds(500);
+    write_reg(0x0001, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
+    write_reg(0x0002, 0x0700); //select  the line inversion
+    write_reg(0x0003, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
+    write_reg(0x0004, 0x0000); //Resize control(No resizing)
+    write_reg(0x0008, 0x0202); //front and back porch 2 lines
+    write_reg(0x0009, 0x0000); //select normal scan
+    write_reg(0x000A, 0x0000); //display control 4
+    write_reg(0x000C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
+    write_reg(0x000D, 0x0000); //Frame marker position
+    write_reg(0x000F, 0x0000); //selects clk, enable and sync signal polarity,
+    write_reg(0x0010, 0x0000); //
+    write_reg(0x0011, 0x0000); //power control 2 reference voltages = 1:1,
+    write_reg(0x0012, 0x0000); //power control 3 VRH
+    write_reg(0x0013, 0x0000); //power control 4 VCOM amplitude
+    gfxSleepMicroseconds(500);
+    write_reg(0x0010, 0x17B0); //power control 1 BT,AP
+    write_reg(0x0011, 0x0137); //power control 2 DC,VC
+    gfxSleepMicroseconds(500);
+    write_reg(0x0012, 0x0139); //power control 3 VRH
+    gfxSleepMicroseconds(500);
+    write_reg(0x0013, 0x1d00); //power control 4 vcom amplitude
+    write_reg(0x0029, 0x0011); //power control 7 VCOMH
+    gfxSleepMicroseconds(500);
+    write_reg(0x0030, 0x0007);
+    write_reg(0x0031, 0x0403);
+    write_reg(0x0032, 0x0404);
+    write_reg(0x0035, 0x0002);
+    write_reg(0x0036, 0x0707);
+    write_reg(0x0037, 0x0606);
+    write_reg(0x0038, 0x0106);
+    write_reg(0x0039, 0x0007);
+    write_reg(0x003c, 0x0700);
+    write_reg(0x003d, 0x0707);
+    write_reg(0x0020, 0x0000); //starting Horizontal GRAM Address
+    write_reg(0x0021, 0x0000); //starting Vertical GRAM Address
+    write_reg(0x0050, 0x0000); //Horizontal GRAM Start Position
+    write_reg(0x0051, 0x00EF); //Horizontal GRAM end Position
+    write_reg(0x0052, 0x0000); //Vertical GRAM Start Position
+    write_reg(0x0053, 0x013F); //Vertical GRAM end Position
 	switch (DISPLAY_CODE) {   
 		case 0x9320:
-        	lld_lcdWriteReg(0x0060, 0x2700); //starts scanning from G1, and 320 drive lines
+        	write_reg(0x0060, 0x2700); //starts scanning from G1, and 320 drive lines
         	break;
       	case 0x9325:
-     		lld_lcdWriteReg(0x0060, 0xA700); //starts scanning from G1, and 320 drive lines
+     		write_reg(0x0060, 0xA700); //starts scanning from G1, and 320 drive lines
 			break;
 	}
 
-    lld_lcdWriteReg(0x0061, 0x0001); //fixed base display
-    lld_lcdWriteReg(0x006a, 0x0000); //no scroll
-    lld_lcdWriteReg(0x0090, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
-    lld_lcdWriteReg(0x0092, 0x0000); //set gate output non-overlap period=0
-    lld_lcdWriteReg(0x0093, 0x0003); //set Source Output Position=3
-    lld_lcdWriteReg(0x0095, 0x0110); //RGB interface(Clocks per line period=16 clocks)
-    lld_lcdWriteReg(0x0097, 0x0110); //set Gate Non-overlap Period 0 locksc
-    lld_lcdWriteReg(0x0098, 0x0110); //
-    lld_lcdWriteReg(0x0007, 0x0173); //display On
+    write_reg(0x0061, 0x0001); //fixed base display
+    write_reg(0x006a, 0x0000); //no scroll
+    write_reg(0x0090, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
+    write_reg(0x0092, 0x0000); //set gate output non-overlap period=0
+    write_reg(0x0093, 0x0003); //set Source Output Position=3
+    write_reg(0x0095, 0x0110); //RGB interface(Clocks per line period=16 clocks)
+    write_reg(0x0097, 0x0110); //set Gate Non-overlap Period 0 locksc
+    write_reg(0x0098, 0x0110); //
+    write_reg(0x0007, 0x0173); //display On
+    release_bus();
 
 	// Turn on the backlight
-	gdisp_lld_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(GDISP_INITIAL_BACKLIGHT);
 	
     /* Initialise the GDISP structure */
-    GDISP.Width = GDISP_SCREEN_WIDTH;
-    GDISP.Height = GDISP_SCREEN_HEIGHT;
-    GDISP.Orientation = GDISP_ROTATE_0;
-    GDISP.Powermode = powerOn;
-    GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-    GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-	GDISP.clipx0 = 0;
-	GDISP.clipy0 = 0;
-	GDISP.clipx1 = GDISP.Width;
-	GDISP.clipy1 = GDISP.Height;
-    #endif
-
+    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 lld_lcdSetCursor(uint16_t x, uint16_t y) {
-
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-			lld_lcdWriteReg(0x0020, x);
-			lld_lcdWriteReg(0x0021, y);
-			break;
-
-		case GDISP_ROTATE_90:
-			lld_lcdWriteReg(0x0020, y);
-			lld_lcdWriteReg(0x0021, x);
-			break;
-
-		case GDISP_ROTATE_180:
-			lld_lcdWriteReg(0x0020, x);
-			lld_lcdWriteReg(0x0021, y);
-			break;
-
-		case GDISP_ROTATE_270:
-			lld_lcdWriteReg(0x0020, y);
-			lld_lcdWriteReg(0x0021, x);
-			break;
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
+		acquire_bus();
+		set_viewport(g);
 	}
-}
-
-static void lld_lcdSetViewPort(uint16_t x, uint16_t y, uint16_t cx, uint16_t cy) {
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-			lld_lcdWriteReg(0x0050, x);
-			lld_lcdWriteReg(0x0051, x + cx - 1);
-			lld_lcdWriteReg(0x0052, y);
-			lld_lcdWriteReg(0x0053, y + cy - 1);
-			break;
-
-		case GDISP_ROTATE_90:
-			lld_lcdWriteReg(0x0050, y);
-			lld_lcdWriteReg(0x0051, y + cy - 1);
-			lld_lcdWriteReg(0x0052, x);
-			lld_lcdWriteReg(0x0053, x + cx - 1);
-			break;
-
-		case GDISP_ROTATE_180:
-			lld_lcdWriteReg(0x0050, x);
-			lld_lcdWriteReg(0x0051, x + cx - 1);
-			lld_lcdWriteReg(0x0052, y);
-			lld_lcdWriteReg(0x0053, y + cy - 1);
-			break;
-
-		case GDISP_ROTATE_270:
-			lld_lcdWriteReg(0x0050, y);
-			lld_lcdWriteReg(0x0051, y + cy - 1);
-			lld_lcdWriteReg(0x0052, x);
-			lld_lcdWriteReg(0x0053, x + cx - 1);
-			break;
-	}
-
-	lld_lcdSetCursor(x, y);
-}
-
-static inline void lld_lcdResetViewPort(void) { 
-    switch(GDISP.Orientation) {
-        case GDISP_ROTATE_0:
-        case GDISP_ROTATE_180:
-            lld_lcdSetViewPort(0, 0, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
-            break;
-        case GDISP_ROTATE_90:
-        case GDISP_ROTATE_270:
-           	lld_lcdSetViewPort(0, 0, GDISP_SCREEN_HEIGHT, GDISP_SCREEN_WIDTH);
-            break;
-    }
-}
-
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-        if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-    #endif
-    lld_lcdSetCursor(x, y);
-    lld_lcdWriteReg(0x0022, color);
-}
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	void gdisp_lld_clear(color_t color) {
-	    unsigned i;
-
-	    lld_lcdSetCursor(0, 0);
-	    lld_lcdWriteStreamStart();
-
-	    for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
-	    	lld_lcdWriteData(color);
-
-	    lld_lcdWriteStreamStop();
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+		write_data(g->p.color);
 	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		unsigned i, area;
-
-		area = cx*cy;
-		lld_lcdSetViewPort(x, y, cx, cy);
-		lld_lcdWriteStreamStart();
-		for(i = 0; i < area; i++)
-			lld_lcdWriteData(color);
-		lld_lcdWriteStreamStop();
-		lld_lcdResetViewPort();
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
+		release_bus();
 	}
 #endif
 
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t endx, endy;
-		unsigned lg;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		lld_lcdSetViewPort(x, y, cx, cy);
-		lld_lcdWriteStreamStart();
-
-		endx = srcx + cx;
-		endy = y + cy;
-		lg = srccx - cx;
-		buffer += srcx + srcy * srccx;
-		for(; y < endy; y++, buffer += lg)
-			for(x=srcx; x < endx; x++)
-				lld_lcdWriteData(*buffer++);
-		lld_lcdWriteStreamStop();
-		lld_lcdResetViewPort();
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
+		acquire_bus();
+		set_viewport(g);
+		setreadmode();
+		dummy_read();
 	}
-#endif
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
-
-		lld_lcdSetCursor(x, y);
-		lld_lcdWriteStreamStart();
-
-		color = lld_lcdReadData();
-		color = lld_lcdReadData();
-
-		lld_lcdWriteStreamStop();
-
-		return color;
+	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
+		return read_data();
 	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, gap, abslines;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		abslines = lines < 0 ? -lines : lines;
-
-		if (abslines >= cy) {
-			abslines = cy;
-			gap = 0;
-		} else {
-			gap = cy - abslines;
-			for(i = 0; i < gap; i++) {
-				if(lines > 0) {
-					row0 = y + i + lines;
-					row1 = y + i;
-				} else {
-					row0 = (y - i - 1) + lines;
-					row1 = (y - i - 1);
-				}
-
-				/* read row0 into the buffer and then write at row1*/
-				lld_lcdSetViewPort(x, row0, cx, 1);
-				lld_lcdReadStreamStart();
-				lld_lcdReadStream(buf, cx);
-				lld_lcdReadStreamStop();
-
-				lld_lcdSetViewPort(x, row1, cx, 1);
-				lld_lcdWriteStreamStart();
-				lld_lcdWriteStream(buf, cx);
-				lld_lcdWriteStreamStop();
-			}
-		}
-
-		/* fill the remaining gap */
-		lld_lcdSetViewPort(x, lines > 0 ? (y+gap) : y, cx, abslines);
-		lld_lcdWriteStreamStart();
-		gap = cx*abslines;
-		for(i = 0; i < gap; i++) lld_lcdWriteData(bgcolor);
-		lld_lcdWriteStreamStop();
-		lld_lcdResetViewPort();
+	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
+		setwritemode();
+		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
-			case GDISP_CONTROL_POWER:
-				if(GDISP.Powermode == (gdisp_powermode_t)value)
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *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();
+					write_reg(0x0007, 0x0000);
+					write_reg(0x0010, 0x0000);
+					write_reg(0x0011, 0x0000);
+					write_reg(0x0012, 0x0000);
+					write_reg(0x0013, 0x0000);
+					release_bus();
+
+					set_backlight(0);
+					break;
+
+				case powerOn:
+					//*************Power On sequence ******************//
+					acquire_bus();
+					write_reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+					write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+					write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					gfxSleepMicroseconds(2000);            /* Dis-charge capacitor power voltage */
+					write_reg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+					write_reg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					gfxSleepMicroseconds(500);
+					write_reg(0x0012, 0x013C); /* VREG1OUT voltage */
+					gfxSleepMicroseconds(500);
+					write_reg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+					write_reg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
+					gfxSleepMicroseconds(500);
+					write_reg(0x0007, 0x0173); /* 262K color and display ON */
+					release_bus();
+
+					set_backlight(g->g.Backlight);
+					if(g->g.Powermode != powerSleep || g->g.Powermode != powerDeepSleep)
+						gdisp_lld_init();
+					break;
+
+				case powerSleep:
+					acquire_bus();
+					write_reg(0x0007, 0x0000); /* display OFF */
+					write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+					write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
+					write_reg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					release_bus();
+
+					set_backlight(0);
+					break;
+
+				case powerDeepSleep:
+					acquire_bus();
+					write_reg(0x0007, 0x0000); /* display OFF */
+					write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+					write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
+					write_reg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					release_bus();
+
+					set_backlight(0);
+					break;
+
+				default:
 					return;
-				switch((gdisp_powermode_t)value) {
-					case powerOff:
-						acquire_bus();
-						lld_lcdWriteReg(0x0007, 0x0000);
-						lld_lcdWriteReg(0x0010, 0x0000);
-						lld_lcdWriteReg(0x0011, 0x0000);
-						lld_lcdWriteReg(0x0012, 0x0000);
-						lld_lcdWriteReg(0x0013, 0x0000);
-						release_bus();
-
-						gdisp_lld_backlight(0);
-						break;
-			
-					case powerOn:
-						//*************Power On sequence ******************//
-						acquire_bus();
-						lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-						lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-						lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
-						lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-						lld_lcdDelay(2000);            /* Dis-charge capacitor power voltage */
-						lld_lcdWriteReg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-						lld_lcdWriteReg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
-						lld_lcdDelay(500);
-						lld_lcdWriteReg(0x0012, 0x013C); /* VREG1OUT voltage */
-						lld_lcdDelay(500);
-						lld_lcdWriteReg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
-						lld_lcdWriteReg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
-						lld_lcdDelay(500);
-						lld_lcdWriteReg(0x0007, 0x0173); /* 262K color and display ON */
-						release_bus();
-
-						gdisp_lld_backlight(GDISP.Backlight);
-						if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
-							gdisp_lld_init();
-						break;
-	
-					case powerSleep:
-						acquire_bus();
-	             		lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
-	                   	lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-	                  	lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-	                  	lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
-	                  	lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-	                  	lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
-	                   	lld_lcdWriteReg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */				
-						release_bus();
-
-						gdisp_lld_backlight(0);
-						break;
-
-					case powerDeepSleep:
-						acquire_bus();
-					    lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
-					    lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					    lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-	   					lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
-	   					lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-	   					lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
-	  					lld_lcdWriteReg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-	  					release_bus();
-
-						gdisp_lld_backlight(0);
-						break;
-
-					default:
-						return;
 				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
+				g->g.Powermode = (powermode_t)g->p.ptr;
 				return;
 
 			case GDISP_CONTROL_ORIENTATION:
-				if(GDISP.Orientation == (gdisp_orientation_t)value)
+				if (g->g.Orientation == (orientation_t)g->p.ptr)
 					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_90:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-			
-					case GDISP_ROTATE_180:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
+				switch((orientation_t)g->p.ptr) {
+				case GDISP_ROTATE_0:
+					acquire_bus();
+					write_reg(0x0001, 0x0100);
+					write_reg(0x0003, 0x1038);
+					write_reg(0x0060, 0x2700);
+					release_bus();
+
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_90:
+					acquire_bus();
+					write_reg(0x0001, 0x0100);
+					write_reg(0x0003, 0x1030);
+					write_reg(0x0060, 0x2700);
+					release_bus();
+
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				case GDISP_ROTATE_180:
+					acquire_bus();
+					write_reg(0x0001, 0x0000);
+					write_reg(0x0003, 0x1030);
+					write_reg(0x0060, 0x2700);
+					release_bus();
+
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_270:
+					acquire_bus();
+					write_reg(0x0001, 0x0000);
+					write_reg(0x0003, 0x1038);
+					write_reg(0x0060, 0xA700);
+					release_bus();
+
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
 		
-					case GDISP_ROTATE_270:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						lld_lcdWriteReg(0x0060, 0xA700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-			
-					default:
-						return;
+				default:
+					return;
 				}
-			
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
+				g->g.Orientation = (orientation_t)value;
 				return;
 
-			case GDISP_CONTROL_BACKLIGHT:
-				if((unsigned)value > 100) value = (void *)100;
-				gdisp_lld_backlight((unsigned)value);
-				GDISP.Backlight = (unsigned)value;
-				break;
-			
+	        case GDISP_CONTROL_BACKLIGHT:
+	            if ((unsigned)g->p.ptr > 100)
+	            	g->p.ptr = (void *)100;
+	            set_backlight((unsigned)g->p.ptr);
+	            g->g.Backlight = (unsigned)g->p.ptr;
+	            return;
 			default:
 				return;
 		}
 	}
-
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
index 177a7cd8..faa54a3e 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
@@ -20,7 +20,7 @@
 #define noinline __attribute__((noinline))
 #endif
 
-static void gdisp_lld_init_board(void) {
+static void init_board(void) {
   // RST
   palSetPadMode(IOPORTA, 7, PAL_MODE_OUTPUT);
   palClearPad(IOPORTA, 7);
@@ -56,14 +56,14 @@ static void gdisp_lld_init_board(void) {
 
 #define PmpWaitBusy()   do {} while (PMMODEbits.BUSY)
 
-static noinline void gdisp_lld_reset_pin(bool_t state) {
+static noinline void setpin_reset(bool_t state) {
   if (state)
     palClearPad(IOPORTA, 7);
   else
     palSetPad(IOPORTA, 7);
 }
 
-static noinline void gdisp_lld_write_index(uint16_t data) {
+static noinline void write_index(uint16_t data) {
   volatile uint16_t dummy;
 
   PmpWaitBusy();
@@ -76,18 +76,24 @@ static noinline void gdisp_lld_write_index(uint16_t data) {
   (void)dummy;
 }
 
-static noinline void gdisp_lld_write_data(uint16_t data) {
+static noinline void write_data(uint16_t data) {
   PMDIN = data;
   PmpWaitBusy();
 }
 
-static noinline uint16_t gdisp_lld_read_data(void) {
+static inline void setreadmode(void) {
+}
+
+static inline void setwritemode(void) {
+}
+
+static noinline uint16_t read_data(void) {
   PmpWaitBusy();
   return PMDIN;
 }
 
 /* if not available, just ignore the argument and return */
-static void gdisp_lld_backlight(uint8_t percentage) {
+static void set_backlight(uint8_t percentage) {
   if (percentage)
     palClearPad(IOPORTD, 3);
   else
@@ -101,6 +107,7 @@ static inline void acquire_bus(void) {
 static inline void release_bus(void) {
   /* Nothing to do here since LCD is the only device on that bus */
 }
+
 #endif /* GDISP_LLD_BOARD_H */
 /** @} */
 
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
index 0d9f8364..1662385a 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
@@ -19,7 +19,7 @@
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
 
-static inline void gdisp_lld_init_board(void) {
+static inline void init_board(void) {
 	/* FSMC setup for F1 */
 	rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
 
@@ -41,7 +41,7 @@ static inline void gdisp_lld_init_board(void) {
     FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
 }
 
-static inline void gdisp_lld_reset_pin(bool_t state) {
+static inline void setpin_reset(bool_t state) {
 	if(state)
 		palClearPad(GPIOE, GPIOE_TFT_RST);
 	else
@@ -56,19 +56,25 @@ static inline void release_bus(void) {
 			/* Nothing to do here since LCD is the only device on that bus */
 }
 
-static inline void gdisp_lld_write_index(uint16_t reg) {
+static inline void write_index(uint16_t reg) {
 	GDISP_REG = reg;
 }
 
-static inline void gdisp_lld_write_data(uint16_t data) {
+static inline void write_data(uint16_t data) {
 	GDISP_RAM = data;
 }
 
-static inline uint16_t gdisp_lld_read_data(void) {
+static inline void setreadmode(void) {
+}
+
+static inline void setwritemode(void) {
+}
+
+static inline uint16_t read_data(void) {
 	return GDISP_RAM;
 }
 
-static inline void gdisp_lld_backlight(uint8_t percent) {
+static inline void set_backlight(uint8_t percent) {
 	if(percent == 100)
 		palClearPad(GPIOD, GPIOD_TFT_LIGHT);
 	else
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_template.h b/drivers/gdisp/ILI9320/gdisp_lld_board_template.h
index dafaec48..201b3630 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_template.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_template.h
@@ -16,11 +16,11 @@
 #ifndef GDISP_LLD_BOARD_H
 #define GDISP_LLD_BOARD_H
 
-static inline void gdisp_lld_init_board(void) {
+static inline void init_board(void) {
 
 }
 
-static inline void gdisp_lld_reset_pin(bool_t state) {
+static inline void setpin_reset(bool_t state) {
 
 }
 
@@ -32,19 +32,27 @@ static inline void release_bus(void) {
 
 }
 
-static inline void gdisp_lld_write_index(uint16_t data) {
+static inline void write_index(uint16_t data) {
 
 }
 
-static inline void gdisp_lld_write_data(uint16_t data) {
+static inline void write_data(uint16_t data) {
 
 }
 
-static inline uint16_t gdisp_lld_read_data(void) {
+static inline void setreadmode(void) {
 
 }
 
-static inline uint16_t gdisp_lld_backlight(uint8_t percentage) {
+static inline void setwritemode(void) {
+
+}
+
+static inline uint16_t read_data(void) {
+
+}
+
+static inline uint16_t set_backlight(uint8_t percentage) {
 
 }
 
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
index 4907c6b8..7cf7457a 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -23,13 +23,11 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"ILI9320"
-
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			FALSE
-#define GDISP_HARDWARE_SCROLL			FALSE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
-#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_DRIVER_STRUCT				GDISP_ILI9320
+
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
 
-- 
cgit v1.2.3


From c132a5bb8ada70bc0a77832033ee6fd68293ceea Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 17:04:13 +1000
Subject: Tidy up some code so it looks more standard accross drivers

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c | 14 ++---
 drivers/gdisp/SSD1289/gdisp_lld.c      | 99 ++++++++++++++++------------------
 2 files changed, 53 insertions(+), 60 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index a41ab3c9..ce0400d1 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -17,9 +17,6 @@
 
 #if GFX_USE_GDISP
 
-#define GDISP_LLD_DECLARATIONS
-#include "gdisp/lld/gdisp_lld.h"
-
 /**
  * This is for the EPSON (GE8) controller driving a Nokia6610 color LCD display.
  * Note that there is also a PHILIPS (GE12) controller for the same display that this code
@@ -52,10 +49,6 @@
  * orientation support and the streaming operations will be emulated (as described above).
  */
 
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
 #if defined(GDISP_SCREEN_HEIGHT)
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
 	#undef GDISP_SCREEN_HEIGHT
@@ -65,7 +58,14 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
 #include "gdisp_lld_board.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
 #include "GE8.h"
 
 #define GDISP_SCAN_LINES			132
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index c724e80b..7ec2b590 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -8,14 +8,11 @@
 /**
  * @file    drivers/gdisp/SSD1289/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
 
 #define GDISP_LLD_DECLARATIONS
 #include "gdisp/lld/gdisp_lld.h"
@@ -43,9 +40,8 @@
 /*===========================================================================*/
 
 // Some common routines and macros
+#define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
 #define write_reg(reg, data)		{ write_index(reg); write_data(data); }
-#define delay(us)					gfxSleepMicroseconds(us)
-#define delayms(ms)					gfxSleepMilliseconds(ms)
 
 static void set_viewport(GDISPDriver* g) {
 	/* Reg 0x44 - Horizontal RAM address position
@@ -107,54 +103,54 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 	// Hardware reset
 	setpin_reset(TRUE);
-	delayms(20);
+	gfxSleepMilliseconds(20);
 	setpin_reset(FALSE);
-	delayms(20);
+	gfxSleepMilliseconds(20);
 
 	// Get the bus for the following initialisation commands
 	acquire_bus();
 	
-	write_reg(0x0000,0x0001);		delay(5);
-	write_reg(0x0003,0xA8A4);    	delay(5);
-	write_reg(0x000C,0x0000);    	delay(5);
-	write_reg(0x000D,0x080C);    	delay(5);
-    write_reg(0x000E,0x2B00);    	delay(5);
-    write_reg(0x001E,0x00B0);    	delay(5);
-	write_reg(0x0001,0x2B3F);		delay(5);
-    write_reg(0x0002,0x0600);    	delay(5);
-    write_reg(0x0010,0x0000);    	delay(5);
-    write_reg(0x0011,0x6070);    	delay(5);
-    write_reg(0x0005,0x0000);    	delay(5);
-    write_reg(0x0006,0x0000);    	delay(5);
-    write_reg(0x0016,0xEF1C);    	delay(5);
-    write_reg(0x0017,0x0003);    	delay(5);
-    write_reg(0x0007,0x0133);    	delay(5);
-    write_reg(0x000B,0x0000);    	delay(5);
-    write_reg(0x000F,0x0000);    	delay(5);
-    write_reg(0x0041,0x0000);    	delay(5);
-    write_reg(0x0042,0x0000);    	delay(5);
-    write_reg(0x0048,0x0000);    	delay(5);
-    write_reg(0x0049,0x013F);    	delay(5);
-    write_reg(0x004A,0x0000);    	delay(5);
-    write_reg(0x004B,0x0000);    	delay(5);
-    write_reg(0x0044,0xEF00);    	delay(5);
-    write_reg(0x0045,0x0000);    	delay(5);
-    write_reg(0x0046,0x013F);    	delay(5);
-    write_reg(0x0030,0x0707);    	delay(5);
-    write_reg(0x0031,0x0204);    	delay(5);
-    write_reg(0x0032,0x0204);    	delay(5);
-    write_reg(0x0033,0x0502);    	delay(5);
-    write_reg(0x0034,0x0507);    	delay(5);
-    write_reg(0x0035,0x0204);    	delay(5);
-    write_reg(0x0036,0x0204);    	delay(5);
-    write_reg(0x0037,0x0502);    	delay(5);
-    write_reg(0x003A,0x0302);    	delay(5);
-    write_reg(0x003B,0x0302);    	delay(5);
-    write_reg(0x0023,0x0000);    	delay(5);
-    write_reg(0x0024,0x0000);    	delay(5);
-    write_reg(0x0025,0x8000);    	delay(5);
-    write_reg(0x004f,0x0000);		delay(5);
-    write_reg(0x004e,0x0000);		delay(5);
+	write_reg(0x0000,0x0001);		gfxSleepMicroseconds(5);
+	write_reg(0x0003,0xA8A4);    	gfxSleepMicroseconds(5);
+	write_reg(0x000C,0x0000);    	gfxSleepMicroseconds(5);
+	write_reg(0x000D,0x080C);    	gfxSleepMicroseconds(5);
+    write_reg(0x000E,0x2B00);    	gfxSleepMicroseconds(5);
+    write_reg(0x001E,0x00B0);    	gfxSleepMicroseconds(5);
+	write_reg(0x0001,0x2B3F);		gfxSleepMicroseconds(5);
+    write_reg(0x0002,0x0600);    	gfxSleepMicroseconds(5);
+    write_reg(0x0010,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0011,0x6070);    	gfxSleepMicroseconds(5);
+    write_reg(0x0005,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0006,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0016,0xEF1C);    	gfxSleepMicroseconds(5);
+    write_reg(0x0017,0x0003);    	gfxSleepMicroseconds(5);
+    write_reg(0x0007,0x0133);    	gfxSleepMicroseconds(5);
+    write_reg(0x000B,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x000F,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0041,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0042,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0048,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0049,0x013F);    	gfxSleepMicroseconds(5);
+    write_reg(0x004A,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x004B,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0044,0xEF00);    	gfxSleepMicroseconds(5);
+    write_reg(0x0045,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0046,0x013F);    	gfxSleepMicroseconds(5);
+    write_reg(0x0030,0x0707);    	gfxSleepMicroseconds(5);
+    write_reg(0x0031,0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(0x0032,0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(0x0033,0x0502);    	gfxSleepMicroseconds(5);
+    write_reg(0x0034,0x0507);    	gfxSleepMicroseconds(5);
+    write_reg(0x0035,0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(0x0036,0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(0x0037,0x0502);    	gfxSleepMicroseconds(5);
+    write_reg(0x003A,0x0302);    	gfxSleepMicroseconds(5);
+    write_reg(0x003B,0x0302);    	gfxSleepMicroseconds(5);
+    write_reg(0x0023,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0024,0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(0x0025,0x8000);    	gfxSleepMicroseconds(5);
+    write_reg(0x004f,0x0000);		gfxSleepMicroseconds(5);
+    write_reg(0x004e,0x0000);		gfxSleepMicroseconds(5);
 
  	// Release the bus
 	release_bus();
@@ -187,12 +183,10 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 #if GDISP_HARDWARE_STREAM_READ
 	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
-		uint16_t	dummy;
-
 		acquire_bus();
 		set_viewport(g);
 		setreadmode();
-		dummy = read_data();		// dummy read
+		dummy_read();
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
 		return read_data();
@@ -318,4 +312,3 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
-- 
cgit v1.2.3


From 7d95523946fe5bdacc6f92a2bad715f0bc492920 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 17:05:06 +1000
Subject: ILI9325 driver ported to streaming interface

---
 drivers/gdisp/ILI9320/gdisp_lld.c                  |  13 +-
 drivers/gdisp/ILI9325/gdisp_lld.c                  | 737 +++++++--------------
 .../gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h  |  50 +-
 drivers/gdisp/ILI9325/gdisp_lld_board_template.h   |  90 ++-
 drivers/gdisp/ILI9325/gdisp_lld_config.h           |  12 +-
 5 files changed, 386 insertions(+), 516 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index 8dc529dd..d8bc411a 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -14,13 +14,6 @@
 
 #if GFX_USE_GDISP
 
-#define GDISP_LLD_DECLARATIONS
-#include "gdisp/lld/gdisp_lld.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
 /* This controller is only ever used with a 240 x 320 display */
 #if defined(GDISP_SCREEN_HEIGHT)
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
@@ -31,8 +24,14 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
 #include "gdisp_lld_board.h"
 
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
 #ifndef GDISP_SCREEN_HEIGHT
 	#define GDISP_SCREEN_HEIGHT		320
 #endif
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index d47adb3a..a30bea44 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -17,15 +17,6 @@
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-
-#include "gdisp_lld_board.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
 /* This controller is only ever used with a 240 x 320 display */
 #if defined(GDISP_SCREEN_HEIGHT)
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
@@ -36,16 +27,27 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_SCREEN_WIDTH		240
-#define GDISP_SCREEN_HEIGHT		320
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
+#include "gdisp_lld_board.h"
 
 /*===========================================================================*/
-/* Driver exported variables.                                                */
+/* Driver local definitions.                                                 */
 /*===========================================================================*/
 
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
 /*===========================================================================*/
 /* Driver local variables.                                                   */
 /*===========================================================================*/
@@ -54,524 +56,281 @@ uint32_t DISPLAY_CODE;
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
-static inline void lld_lcdDelay(uint16_t us) {
-	gfxSleepMicroseconds(us);
-}
-
-static inline void lld_lcdWriteIndex(uint16_t index) {
-	gdisp_lld_write_index(index);
-}
-
-static inline void lld_lcdWriteData(uint16_t data) {
-	gdisp_lld_write_data(data);
-}
-
-static inline void lld_lcdWriteReg(uint16_t lcdReg, uint16_t lcdRegValue) {
-	gdisp_lld_write_index(lcdReg);
-	gdisp_lld_write_data(lcdRegValue);
-}
 
-static inline uint16_t lld_lcdReadData(void) {
-	return gdisp_lld_read_data();
-}
-
-static inline uint16_t lld_lcdReadReg(uint16_t lcdReg) {
-    volatile uint16_t dummy;
-
-    gdisp_lld_write_index(lcdReg);
-    dummy = lld_lcdReadData();
-    (void)dummy;
-
-    return lld_lcdReadData();
-}
-
-static inline void lld_lcdWriteStreamStart(void) {
-	lld_lcdWriteIndex(0x0022);
-}
-	
-static inline void lld_lcdWriteStreamStop(void) {
+// Some common routines and macros
+#define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
+#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
 
-}
-
-static inline void lld_lcdWriteStream(uint16_t *buffer, uint16_t size) {
-	uint16_t i;
-
-	for(i = 0; i < size; i++)
-		lld_lcdWriteData(buffer[i]);
-}
-
-static inline void lld_lcdReadStreamStart(void) {
-	lld_lcdWriteIndex(0x0022);
-}
-
-static inline void lld_lcdReadStreamStop(void) {
-
-}
-
-static inline void lld_lcdReadStream(uint16_t *buffer, size_t size) {
-	uint16_t i;
-	volatile uint16_t dummy;
-
-	dummy = lld_lcdReadData();
-	(void)dummy;
+static void set_viewport(GDISPDriver* g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(0x0050, x);
+			write_reg(0x0051, x + cx - 1);
+			write_reg(0x0052, y);
+			write_reg(0x0053, y + cy - 1);
+			write_reg(0x0020, x);
+			write_reg(0x0021, y);
+			break;
 
-	for(i = 0; i < size; i++)
-		buffer[i] = lld_lcdReadData();
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(0x0050, y);
+			write_reg(0x0051, y + cy - 1);
+			write_reg(0x0052, x);
+			write_reg(0x0053, x + cx - 1);
+			write_reg(0x0020, y);
+			write_reg(0x0021, x);
+			break;
+	}
+    write_reg(0x0022, color);
 }
 
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
-	gdisp_lld_init_board();
+	init_board();
 
 	/* Hardware reset */
-	gdisp_lld_reset_pin(TRUE);
-	lld_lcdDelay(1000);
-	gdisp_lld_reset_pin(FALSE);
-	lld_lcdDelay(1000);
+	setpin_reset(TRUE);
+	gfxSleepMicroseconds(1000);
+	setpin_reset(FALSE);
+	gfxSleepMicroseconds(1000);
 
-	DISPLAY_CODE = lld_lcdReadReg(0);
+	acquire_bus();
+	write_index(0);				// Get controller version
+	dummy_read();
+    DISPLAY_CODE = read_data();
 
 	// chinese code starts here
-	lld_lcdWriteReg(0x0000,0x0001);
-	lld_lcdDelay(10);
-
-	lld_lcdWriteReg(0x0015,0x0030);
-	lld_lcdWriteReg(0x0011,0x0040);
-	lld_lcdWriteReg(0x0010,0x1628);
-	lld_lcdWriteReg(0x0012,0x0000);
-	lld_lcdWriteReg(0x0013,0x104d);
-	lld_lcdDelay(10);
-	lld_lcdWriteReg(0x0012,0x0010);
-	lld_lcdDelay(10);
-	lld_lcdWriteReg(0x0010,0x2620);
-	lld_lcdWriteReg(0x0013,0x344d); //304d
-	lld_lcdDelay(10);
-
-	lld_lcdWriteReg(0x0001,0x0100);
-	lld_lcdWriteReg(0x0002,0x0300);
-	lld_lcdWriteReg(0x0003,0x1038);//0x1030
-	lld_lcdWriteReg(0x0008,0x0604);
-	lld_lcdWriteReg(0x0009,0x0000);
-	lld_lcdWriteReg(0x000A,0x0008);
-
-	lld_lcdWriteReg(0x0041,0x0002);
-	lld_lcdWriteReg(0x0060,0x2700);
-	lld_lcdWriteReg(0x0061,0x0001);
-	lld_lcdWriteReg(0x0090,0x0182);
-	lld_lcdWriteReg(0x0093,0x0001);
-	lld_lcdWriteReg(0x00a3,0x0010);
-	lld_lcdDelay(10);
+	write_reg(0x0000,0x0001);
+	gfxSleepMilliseconds(10);
+
+	write_reg(0x0015,0x0030);
+	write_reg(0x0011,0x0040);
+	write_reg(0x0010,0x1628);
+	write_reg(0x0012,0x0000);
+	write_reg(0x0013,0x104d);
+	gfxSleepMilliseconds(10);
+	write_reg(0x0012,0x0010);
+	gfxSleepMilliseconds(10);
+	write_reg(0x0010,0x2620);
+	write_reg(0x0013,0x344d); //304d
+	gfxSleepMilliseconds(10);
+
+	write_reg(0x0001,0x0100);
+	write_reg(0x0002,0x0300);
+	write_reg(0x0003,0x1038);//0x1030
+	write_reg(0x0008,0x0604);
+	write_reg(0x0009,0x0000);
+	write_reg(0x000A,0x0008);
+
+	write_reg(0x0041,0x0002);
+	write_reg(0x0060,0x2700);
+	write_reg(0x0061,0x0001);
+	write_reg(0x0090,0x0182);
+	write_reg(0x0093,0x0001);
+	write_reg(0x00a3,0x0010);
+	gfxSleepMilliseconds(10);
 
 	//################# void Gamma_Set(void) ####################//
-	lld_lcdWriteReg(0x30,0x0000);		
-	lld_lcdWriteReg(0x31,0x0502);		
-	lld_lcdWriteReg(0x32,0x0307);		
-	lld_lcdWriteReg(0x33,0x0305);		
-	lld_lcdWriteReg(0x34,0x0004);		
-	lld_lcdWriteReg(0x35,0x0402);		
-	lld_lcdWriteReg(0x36,0x0707);		
-	lld_lcdWriteReg(0x37,0x0503);		
-	lld_lcdWriteReg(0x38,0x1505);		
-	lld_lcdWriteReg(0x39,0x1505);
-	lld_lcdDelay(10);
+	write_reg(0x30,0x0000);
+	write_reg(0x31,0x0502);
+	write_reg(0x32,0x0307);
+	write_reg(0x33,0x0305);
+	write_reg(0x34,0x0004);
+	write_reg(0x35,0x0402);
+	write_reg(0x36,0x0707);
+	write_reg(0x37,0x0503);
+	write_reg(0x38,0x1505);
+	write_reg(0x39,0x1505);
+	gfxSleepMilliseconds(10);
 
 	//################## void Display_ON(void) ####################//
-	lld_lcdWriteReg(0x0007,0x0001);
-	lld_lcdDelay(10);
-	lld_lcdWriteReg(0x0007,0x0021);
-	lld_lcdWriteReg(0x0007,0x0023);
-	lld_lcdDelay(10);
-	lld_lcdWriteReg(0x0007,0x0033);
-	lld_lcdDelay(10);
-	lld_lcdWriteReg(0x0007,0x0133);
+	write_reg(0x0007,0x0001);
+	gfxSleepMilliseconds(10);
+	write_reg(0x0007,0x0021);
+	write_reg(0x0007,0x0023);
+	gfxSleepMilliseconds(10);
+	write_reg(0x0007,0x0033);
+	gfxSleepMilliseconds(10);
+	write_reg(0x0007,0x0133);
 
 	// chinese code ends here
 
 	// Turn on the backlight
-	gdisp_lld_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(GDISP_INITIAL_BACKLIGHT);
 	
     /* Initialise the GDISP structure */
-    GDISP.Width = GDISP_SCREEN_WIDTH;
-    GDISP.Height = GDISP_SCREEN_HEIGHT;
-    GDISP.Orientation = GDISP_ROTATE_0;
-    GDISP.Powermode = powerOn;
-    GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-    GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-	GDISP.clipx0 = 0;
-	GDISP.clipy0 = 0;
-	GDISP.clipx1 = GDISP.Width;
-	GDISP.clipy1 = GDISP.Height;
-    #endif
+    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 lld_lcdSetCursor(uint16_t x, uint16_t y) {
-
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-			lld_lcdWriteReg(0x0020, x);
-			lld_lcdWriteReg(0x0021, y);
-			break;
-
-		case GDISP_ROTATE_90:
-			lld_lcdWriteReg(0x0020, y);
-			lld_lcdWriteReg(0x0021, x);
-			break;
-
-		case GDISP_ROTATE_180:
-			lld_lcdWriteReg(0x0020, x);
-			lld_lcdWriteReg(0x0021, y);
-			break;
-
-		case GDISP_ROTATE_270:
-			lld_lcdWriteReg(0x0020, y);
-			lld_lcdWriteReg(0x0021, x);
-			break;
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
+		acquire_bus();
+		set_viewport(g);
 	}
-}
-
-static void lld_lcdSetViewPort(uint16_t x, uint16_t y, uint16_t cx, uint16_t cy) {
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-			lld_lcdWriteReg(0x0050, x);
-			lld_lcdWriteReg(0x0051, x + cx - 1);
-			lld_lcdWriteReg(0x0052, y);
-			lld_lcdWriteReg(0x0053, y + cy - 1);
-			break;
-
-		case GDISP_ROTATE_90:
-			lld_lcdWriteReg(0x0050, y);
-			lld_lcdWriteReg(0x0051, y + cy - 1);
-			lld_lcdWriteReg(0x0052, x);
-			lld_lcdWriteReg(0x0053, x + cx - 1);
-			break;
-
-		case GDISP_ROTATE_180:
-			lld_lcdWriteReg(0x0050, x);
-			lld_lcdWriteReg(0x0051, x + cx - 1);
-			lld_lcdWriteReg(0x0052, y);
-			lld_lcdWriteReg(0x0053, y + cy - 1);
-			break;
-
-		case GDISP_ROTATE_270:
-			lld_lcdWriteReg(0x0050, y);
-			lld_lcdWriteReg(0x0051, y + cy - 1);
-			lld_lcdWriteReg(0x0052, x);
-			lld_lcdWriteReg(0x0053, x + cx - 1);
-			break;
-
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+		write_data(g->p.color);
 	}
-
-	lld_lcdSetCursor(x, y);
-}
-
-static inline void lld_lcdResetViewPort(void) { 
-    switch(GDISP.Orientation) {
-        case GDISP_ROTATE_0:
-        case GDISP_ROTATE_180:
-            lld_lcdSetViewPort(0, 0, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
-            break;
-        case GDISP_ROTATE_90:
-        case GDISP_ROTATE_270:
-           	lld_lcdSetViewPort(0, 0, GDISP_SCREEN_HEIGHT, GDISP_SCREEN_WIDTH);
-            break;
-    }
-}
-
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-        if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-    #endif
-    lld_lcdSetCursor(x, y);
-    lld_lcdWriteReg(0x0022, color);
-}
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	void gdisp_lld_clear(color_t color) {
-	    unsigned i;
-
-	    lld_lcdSetCursor(0, 0);
-	    lld_lcdWriteStreamStart();
-
-	    for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
-	    	lld_lcdWriteData(color);
-
-	    lld_lcdWriteStreamStop();
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
+		release_bus();
 	}
 #endif
 
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		unsigned i, area;
-
-		area = cx*cy;
-		lld_lcdSetViewPort(x, y, cx, cy);
-		lld_lcdWriteStreamStart();
-		for(i = 0; i < area; i++)
-			lld_lcdWriteData(color);
-		lld_lcdWriteStreamStop();
-		lld_lcdResetViewPort();
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
+		acquire_bus();
+		set_viewport(g);
+		setreadmode();
+		dummy_read();
 	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t endx, endy;
-		unsigned lg;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		lld_lcdSetViewPort(x, y, cx, cy);
-		lld_lcdWriteStreamStart();
-
-		endx = srcx + cx;
-		endy = y + cy;
-		lg = srccx - cx;
-		buffer += srcx + srcy * srccx;
-		for(; y < endy; y++, buffer += lg)
-			for(x=srcx; x < endx; x++)
-				lld_lcdWriteData(*buffer++);
-		lld_lcdWriteStreamStop();
-		lld_lcdResetViewPort();
+	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
+		return read_data();
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
+		setwritemode();
+		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
-
-		lld_lcdSetCursor(x, y);
-		lld_lcdWriteStreamStart();
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *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();
+				write_reg(0x0007, 0x0000);
+				write_reg(0x0010, 0x0000);
+				write_reg(0x0011, 0x0000);
+				write_reg(0x0012, 0x0000);
+				write_reg(0x0013, 0x0000);
+				release_bus();
+				set_backlight(0);
+				break;
 
-		color = lld_lcdReadData();
-		color = lld_lcdReadData();
+			case powerOn:
+				//*************Power On sequence ******************//
+				acquire_bus();
+				write_reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+				write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+				write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				gfxSleepMilliseconds(200);            /* Dis-charge capacitor power voltage */
+				write_reg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+				write_reg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				gfxSleepMilliseconds(50);
+				write_reg(0x0012, 0x013C); /* VREG1OUT voltage */
+				gfxSleepMilliseconds(50);
+				write_reg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+				write_reg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
+				gfxSleepMilliseconds(50);
+				write_reg(0x0007, 0x0173); /* 262K color and display ON */
+				release_bus();
+				set_backlight(g->g.Backlight);
+				break;
 
-		lld_lcdWriteStreamStop();
+			case powerSleep:
+				acquire_bus();
+				write_reg(0x0007, 0x0000); /* display OFF */
+				write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+				write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
+				write_reg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				release_bus();
+				gdisp_lld_backlight(0);
+				break;
 
-		return color;
-	}
-#endif
+			case powerDeepSleep:
+				acquire_bus();
+				write_reg(0x0007, 0x0000); /* display OFF */
+				write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
+				write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
+				write_reg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				release_bus();
+				gdisp_lld_backlight(0);
+				break;
 
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, gap, abslines;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		abslines = lines < 0 ? -lines : lines;
-
-		if (abslines >= cy) {
-			abslines = cy;
-			gap = 0;
-		} else {
-			gap = cy - abslines;
-			for(i = 0; i < gap; i++) {
-				if(lines > 0) {
-					row0 = y + i + lines;
-					row1 = y + i;
-				} else {
-					row0 = (y - i - 1) + lines;
-					row1 = (y - i - 1);
-				}
-
-				/* read row0 into the buffer and then write at row1*/
-				lld_lcdSetViewPort(x, row0, cx, 1);
-				lld_lcdReadStreamStart();
-				lld_lcdReadStream(buf, cx);
-				lld_lcdReadStreamStop();
-
-				lld_lcdSetViewPort(x, row1, cx, 1);
-				lld_lcdWriteStreamStart();
-				lld_lcdWriteStream(buf, cx);
-				lld_lcdWriteStreamStop();
+			default:
+				return;
 			}
-		}
-
-		/* fill the remaining gap */
-		lld_lcdSetViewPort(x, lines > 0 ? (y+gap) : y, cx, abslines);
-		lld_lcdWriteStreamStart();
-		gap = cx*abslines;
-		for(i = 0; i < gap; i++) lld_lcdWriteData(bgcolor);
-		lld_lcdWriteStreamStop();
-		lld_lcdResetViewPort();
-	}
-#endif
-
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
-			case GDISP_CONTROL_POWER:
-				if(GDISP.Powermode == (gdisp_powermode_t)value)
-					return;
-				switch((gdisp_powermode_t)value) {
-					case powerOff:
-						acquire_bus();
-						lld_lcdWriteReg(0x0007, 0x0000);
-						lld_lcdWriteReg(0x0010, 0x0000);
-						lld_lcdWriteReg(0x0011, 0x0000);
-						lld_lcdWriteReg(0x0012, 0x0000);
-						lld_lcdWriteReg(0x0013, 0x0000);
-						release_bus();
-
-						gdisp_lld_backlight(0);
-						break;
+			g->g.Powermode = (powermode_t)g->p.ptr;
+			return;
 			
-					case powerOn:
-						//*************Power On sequence ******************//
-						acquire_bus();
-						lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-						lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-						lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
-						lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-						lld_lcdDelay(2000);            /* Dis-charge capacitor power voltage */
-						lld_lcdWriteReg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-						lld_lcdWriteReg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
-						lld_lcdDelay(500);
-						lld_lcdWriteReg(0x0012, 0x013C); /* VREG1OUT voltage */
-						lld_lcdDelay(500);
-						lld_lcdWriteReg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
-						lld_lcdWriteReg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
-						lld_lcdDelay(500);
-						lld_lcdWriteReg(0x0007, 0x0173); /* 262K color and display ON */
-						release_bus();
-
-						gdisp_lld_backlight(GDISP.Backlight);
-						if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
-							gdisp_lld_init();
-						break;
-	
-					case powerSleep:
-						acquire_bus();
-	             		lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
-	                   	lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-	                  	lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-	                  	lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
-	                  	lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-	                  	lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
-	                   	lld_lcdWriteReg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-	                  	release_bus();
-
-						gdisp_lld_backlight(0);
-						break;
-
-					case powerDeepSleep:
-						acquire_bus();
-					    lld_lcdWriteReg(0x0007, 0x0000); /* display OFF */
-					    lld_lcdWriteReg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					    lld_lcdWriteReg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-	   					lld_lcdWriteReg(0x0012, 0x0000); /* VREG1OUT voltage */
-	   					lld_lcdWriteReg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
-	   					lld_lcdDelay(2000); /* Dis-charge capacitor power voltage */
-	  					lld_lcdWriteReg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-	  					release_bus();
-
-						gdisp_lld_backlight(0);
-						break;
-
-					default:
-						return;
-				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
+		case GDISP_CONTROL_ORIENTATION:
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-
-			case GDISP_CONTROL_ORIENTATION:
-				if(GDISP.Orientation == (gdisp_orientation_t)value)
+			switch((orientation_t)g->p.ptr) {
+				case GDISP_ROTATE_0:
+					acquire_bus();
+					write_reg(0x0001, 0x0100);
+					write_reg(0x0003, 0x1038);
+					write_reg(0x0060, 0x2700);
+					release_bus();
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_90:
+					acquire_bus();
+					write_reg(0x0001, 0x0000);
+					write_reg(0x0003, 0x1030);
+					write_reg(0x0060, 0x2700);
+					release_bus();
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				case GDISP_ROTATE_180:
+					acquire_bus();
+					write_reg(0x0001, 0x0000);
+					write_reg(0x0003, 0x1038);
+					write_reg(0x0060, 0xa700);
+					release_bus();
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+	
+				case GDISP_ROTATE_270:
+					acquire_bus();
+					write_reg(0x0001, 0x0100);
+					write_reg(0x0003, 0x1030);
+					write_reg(0x0060, 0xA700);
+					release_bus();
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				default:
 					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_90:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-			
-					case GDISP_ROTATE_180:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						lld_lcdWriteReg(0x0060, 0xa700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-		
-					case GDISP_ROTATE_270:
-						acquire_bus();
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						lld_lcdWriteReg(0x0060, 0xA700);
-						release_bus();
-
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-			
-					default:
-						return;
-				}
-			
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
-				return;
+			}
 
-			case GDISP_CONTROL_BACKLIGHT:
-				if((unsigned)value > 100) value = (void *)100;
-				gdisp_lld_backlight((unsigned)value);
-				GDISP.Backlight = (unsigned)value;
-				break;
+			g->g.Orientation = (orientation_t)value;
+			return;
 			
-			default:
-				return;
+        case GDISP_CONTROL_BACKLIGHT:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+            set_backlight((unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+		
+		default:
+			return;
 		}
 	}
 
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h b/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
index 3c2cc78b..3e2c269b 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
@@ -32,7 +32,7 @@
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
 
-static inline void gdisp_lld_init_board(void) {
+static inline void init_board(void) {
 	/* FSMC setup for F1 */
 	rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
 
@@ -55,27 +55,63 @@ static inline void gdisp_lld_init_board(void) {
 	
 }
 
-static inline void gdisp_lld_reset_pin(bool_t state) {
+static inline void setpin_reset(bool_t state) {
 	if(state)
 		palClearPad(GPIOE, GPIOE_TFT_RST);
 	else
 		palSetPad(GPIOE, GPIOE_TFT_RST);
 }
 
-static inline void gdisp_lld_write_index(uint16_t reg) {
+static inline void write_index(uint16_t reg) {
 	GDISP_REG = reg;
 }
 
-static inline void gdisp_lld_write_data(uint16_t data) {
+static inline void write_data(uint16_t data) {
 	GDISP_RAM = data;
 }
 
-static inline uint16_t gdisp_lld_read_data(void) {
+static inline uint16_t read_data(void) {
 	return GDISP_RAM;
 }
 
-static inline void gdisp_lld_backlight(uint8_t percent) {
-	percent=percent;	// avoid a warning
+static inline void set_backlight(uint8_t percent) {
+	(void)percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static inline void acquire_bus(void) {
+
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static inline void release_bus(void) {
+
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+
 }
 
 #endif /* GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_template.h b/drivers/gdisp/ILI9325/gdisp_lld_board_template.h
index 2dd346a3..c07b4ba1 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_board_template.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_board_template.h
@@ -16,27 +16,105 @@
 #ifndef GDISP_LLD_BOARD_H
 #define GDISP_LLD_BOARD_H
 
-static inline void gdisp_lld_init_board(void) {
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @notapi
+ */
+static inline void init_board(void) {
+
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(bool_t state) {
 
 }
 
-static inline void gdisp_lld_reset_pin(bool_t state) {
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] percent		0 to 100%
+ *
+ * @notapi
+ */
+static inline void set_backlight(uint8_t percent) {
 
 }
 
-static inline void gdisp_lld_write_index(uint16_t data) {
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static inline void acquire_bus(void) {
 
 }
 
-static inline void gdisp_lld_write_data(uint16_t data) {
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static inline void release_bus(void) {
 
 }
 
-static inline uint16_t gdisp_lld_read_data(void) {
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] index		The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(uint16_t index) {
 
 }
 
-static inline uint16_t gdisp_lld_backlight(uint8_t percentage) {
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] data		The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(uint16_t data) {
+
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+
+}
+
+/**
+ * @brief   Read data from the lcd.
+ *
+ * @return	The data from the lcd
+ * @note	The chip select may need to be asserted/de-asserted
+ * 			around the actual spi read
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(void) {
 
 }
 
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_config.h b/drivers/gdisp/ILI9325/gdisp_lld_config.h
index ac07173c..572b8361 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_config.h
@@ -23,13 +23,11 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"ILI9325"
-
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			FALSE
-#define GDISP_HARDWARE_SCROLL			FALSE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
-#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_DRIVER_STRUCT				GDISP_ILI9325
+
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
 
-- 
cgit v1.2.3


From 9413f04672b80baec6781b4f2058cdf6e167cd55 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 30 Sep 2013 17:31:58 +1000
Subject: Driver ILI9481 ported to streaming driver

---
 drivers/gdisp/ILI9481/gdisp_lld.c                  | 455 ++++-----------------
 .../ILI9481/gdisp_lld_board_firebullstm32f103.h    |  29 +-
 drivers/gdisp/ILI9481/gdisp_lld_board_template.h   |  20 +-
 drivers/gdisp/ILI9481/gdisp_lld_config.h           |   8 +-
 drivers/gdisp/SSD1289/gdisp_lld.c                  |   3 +
 5 files changed, 131 insertions(+), 384 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9481/gdisp_lld.c b/drivers/gdisp/ILI9481/gdisp_lld.c
index cb407dce..a70b7c03 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.c
+++ b/drivers/gdisp/ILI9481/gdisp_lld.c
@@ -9,21 +9,11 @@
  * @file    drivers/gdisp/ILI9481/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for
  * 			the ILI9481 and compatible HVGA display
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
+#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."
@@ -34,55 +24,40 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_SCREEN_HEIGHT		480
-#define GDISP_SCREEN_WIDTH		320
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
+#include "gdisp_lld_board.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
 
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		480
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		320
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
-
 // Some common routines and macros
-#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
-#define stream_start()				write_index(0x2C);
-#define stream_stop()
-#define delay(us)					gfxSleepMicroseconds(us)
-#define delayms(ms)					gfxSleepMilliseconds(ms)
-
-static inline void set_cursor(coord_t x, coord_t y) {
-	write_index(0x2A);
-	write_data((x >> 8));
-	write_data((uint8_t) x);
-	write_data((x) >> 8);
-	write_data((uint8_t) (x));
-
-	write_index(0x2B);
-	write_data((y >> 8));
-	write_data((uint8_t) y);
-	write_data((y) >> 8);
-	write_data((uint8_t) (y));
-}
-
-static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-	write_index(0x2A);
-	write_data((x >> 8));
-	write_data((uint8_t) x);
-	write_data((x + cx - 1) >> 8);
-	write_data((uint8_t) (x + cx - 1));
-
-	write_index(0x2B);
-	write_data((y >> 8));
-	write_data((uint8_t) y);
-	write_data((y + cy - 1) >> 8);
-	write_data((uint8_t) (y + cy - 1));
-}
-
-static inline void reset_viewport(void) {
-	set_viewport(0, 0, GDISP.Width, GDISP.Height);
+#define dummy_read()						{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
+#define write_reg(reg, data)				{ write_index(reg); write_data(data); }
+#define write_reg2x16(reg, data1, data2)	{ write_index(reg); write_data((data1)>>8); write_data((uint8_t)(data1)); write_data((data2)>>8); write_data((uint8_t)(data2));}
+
+static void set_viewport(GDISPDriver* g) {
+	write_reg2x16(0x2A, g->p.x, g->p.x + g->p.cx - 1);
+	write_reg2x16(0x2B, g->p.y, g->p.y + g->p.cy - 1);
+	write_index(0x2C);
 }
 
 /*===========================================================================*/
@@ -93,33 +68,21 @@ static inline void reset_viewport(void) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
 	init_board();
 
 	/* Hardware reset */
 	setpin_reset(TRUE);
-	delayms(20);
+	gfxSleepMilliseconds(20);
 	setpin_reset(FALSE);
-	delayms(20);
+	gfxSleepMilliseconds(20);
 
 	/* Get the bus for the following initialisation commands */
 	acquire_bus();
 
 	/* Enable Access to all Manufacturer commands (0xB0 and higher opcodes) */
-	write_index(0xB0);
-	write_data(0x00);
+	write_reg(0xB0, 0x00);
 
 	/* Frame Memory Access and Interface Setting */
 	write_index(0xB3);
@@ -131,8 +94,7 @@ bool_t gdisp_lld_init(void) {
 	/* Display Mode and Frame Memory Write Mode Setting (B4h) */
 	/* Use internal clock for synchronization */
 	/* Use DBI interface (only DB0-17, no HSYNC, VSYNC or CLK) */
-	write_index(0xB4);
-	write_data(0x00);
+	write_reg(0xB4, 0x00);
 
 	/* Internal Backlight Control */
 /*	write_index(0xB9); 	/*PWM Settings for Brightness Control */
@@ -167,8 +129,7 @@ bool_t gdisp_lld_init(void) {
 	write_data(0x01);
 
 	/* Interface Setting */
-	write_index(0xC6);
-	write_data(0x02);
+	write_reg(0xC6, 0x02);
 
 	/* Gamma Setting - should be changed if using a different panel */
 	write_index(0xC8);
@@ -184,13 +145,11 @@ bool_t gdisp_lld_init(void) {
 	write_data(0x60); /*0x23 */
 
 	/* Address Mode setting */
-	write_index(0x36);
-	write_data(0x00);
+	write_reg(0x36, 0x00);
 
 	/* Set Pixel Format = 16 bits per pixel */
 	/* The driver supports upto 24 bits per pixel, with dither */
-	write_index(0x3A);
-	write_data(0x55);
+	write_reg(0x3A, 0x55);
 
 	/* Exit Idle Mode */
 	write_index(0x38);
@@ -216,11 +175,11 @@ bool_t gdisp_lld_init(void) {
 
 	/* Exit Sleep Mode */
 	write_index(0x11);
-	delay(150);
+	gfxSleepMilliseconds(150);
 
 	/* Display ON  */
 	write_index(0x29);
-	delay(30);
+	gfxSleepMilliseconds(30);
 
  	/* Release the bus */
 	release_bus();
@@ -228,297 +187,62 @@ bool_t gdisp_lld_init(void) {
 	/* Turn on the back-light */
 	set_backlight(GDISP_INITIAL_BACKLIGHT);
 
-   /* Initialise the GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	/* 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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	
-	acquire_bus();
-
-	set_cursor(x, y);
-	write_reg(0x002c, color);
-
-	release_bus();
-}
-
-/* ---- Optional Routines ---- */
-/*
-	All the below routines are optional.
-	Defining them will increase speed but everything
-	will work if they are not defined.
-	If you are not using a routine - turn it off using
-	the appropriate GDISP_HARDWARE_XXXX macro.
-	Don't bother coding for obvious similar routines if
-	there is no performance penalty as the emulation software
-	makes a good job of using similar routines.
-		eg. If gfillarea() is defined there is little
-			point in defining clear() unless the
-			performance bonus is significant.
-	For good performance it is suggested to implement
-		fillarea() and blitarea().
-*/
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Clear the display.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] color    The color of the pixel
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_clear(color_t color) {
-		unsigned i;
-
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
-		reset_viewport();
-		stream_start();
-		for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
-			write_data(color);
-		stream_stop();
-		release_bus();
+		set_viewport(g);
 	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		unsigned i, area;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		area = cx*cy;
-
-		acquire_bus();
-
-		set_viewport(x, y, cx, cy);
-
-		stream_start();
-		for(i = 0; i < area; i++)
-			write_data(color);
-		stream_stop();
-
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+		write_data(g->p.color);
 	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t endx, endy;
-		unsigned lg;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-
-		endx = srcx + cx;
-		endy = y + cy;
-		lg = srccx - cx;
-		buffer += srcx + srcy * srccx;
-		for(; y < endy; y++, buffer += lg)
-			for(x=srcx; x < endx; x++)
-				write_data(*buffer++);
-		stream_stop();
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The pixel to be read
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
-
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
 		acquire_bus();
-		set_cursor(x, y);
-		stream_start();
-		color = read_data();			// dummy read
-		color = read_data();
-		stream_stop();
-		release_bus();
-
-		return color;
+		set_viewport(g);
+		setreadmode();
+		dummy_read();
 	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, gap, abslines, j;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		abslines = lines < 0 ? -lines : lines;
-
-		acquire_bus();
-		if ((coord_t)abslines >= cy) {
-			abslines = cy;
-			gap = 0;
-		} else {
-			gap = cy - abslines;
-			for(i = 0; i < gap; i++) {
-				if(lines > 0) {
-					row0 = y + i + lines;
-					row1 = y + i;
-				} else {
-					row0 = (y - i - 1) + lines;
-					row1 = (y - i - 1);
-				}
-
-				/* read row0 into the buffer and then write at row1*/
-				set_viewport(x, row0, cx, 1);
-				stream_start();
-				j = read_data();			// dummy read
-				for (j = 0; (coord_t)j < cx; j++)
-					buf[j] = read_data();
-				stream_stop();
-
-				set_viewport(x, row1, cx, 1);
-				stream_start();
-				for (j = 0; (coord_t)j < cx; j++)
-					write_data(buf[j]);
-				stream_stop();
-			}
-		}
-
-		/* fill the remaining gap */
-		set_viewport(x, lines > 0 ? (y+(coord_t)gap) : y, cx, abslines);
-		stream_start();
-		gap = cx*abslines;
-		for(i = 0; i < gap; i++) write_data(bgcolor);
-		stream_stop();
+	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
+		return read_data();
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
+		setwritemode();
 		release_bus();
 	}
 #endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+		switch(g->p.x) {
 		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
 				return;
-			switch((gdisp_powermode_t)value) {
+			switch((powermode_t)g->p.ptr) {
 			case powerOff:
-			  acquire_bus();
-			  write_reg(0x0010, 0x0001);	/* enter sleep mode */
-			  release_bus();
+				acquire_bus();
+				write_reg(0x0010, 0x0001);	/* enter sleep mode */
+				release_bus();
 				break;
 			case powerOn:
 				acquire_bus();
 				write_reg(0x0010, 0x0000);	/* leave sleep mode */
 				release_bus();
-				if (GDISP.Powermode != powerSleep)
+				if (g->g.Powermode != powerSleep)
 					gdisp_lld_init();
 				break;
 			case powerSleep:
@@ -529,12 +253,13 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 			default:
 				return;
 			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
+			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
+
 		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-			switch((gdisp_orientation_t)value) {
+			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
 				acquire_bus();
 
@@ -542,8 +267,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				write_reg(0x36, 0x00);	/* X and Y axes non-inverted */
 
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_90:
 				acquire_bus();
@@ -552,8 +277,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				write_reg(0x36, 0x20);	/* Invert X and Y axes */
 
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
 				acquire_bus();
@@ -562,8 +287,8 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				write_reg(0x36, 0x00);	/* X and Y axes non-inverted */
 
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
 				acquire_bus();
@@ -572,24 +297,18 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				write_reg(0x36, 0x20);	/* Invert X and Y axes */
 
 				release_bus();
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			default:
 				return;
 			}
-			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
+			g->g.Orientation = (orientation_t)value;
 			return;
-/*
-		case GDISP_CONTROL_BACKLIGHT:
-		case GDISP_CONTROL_CONTRAST:
-*/
+        //case GDISP_CONTROL_BACKLIGHT:
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
 		}
 	}
 #endif
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h b/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
index cef9911d..7270cdaf 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
+++ b/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
@@ -113,7 +113,26 @@ static inline void write_data(uint16_t data) {
 	CLR_WR; SET_WR;
 }
 
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+	// change pin mode to digital input
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+	// change pin mode back to digital output
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
 /**
  * @brief   Read data from the lcd.
  *
@@ -126,20 +145,12 @@ static inline void write_data(uint16_t data) {
 static inline uint16_t read_data(void) {
 	uint16_t	value;
 	
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-
 	CLR_RD;
 	value = palReadPort(GPIOE);
-	value = palReadPort(GPIOE);
 	SET_RD;
-
-	// change pin mode back to digital output
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
 	
 	return value;
 }
-#endif
 
 #endif /* _GDISP_LLD_BOARD_H */
 /** @} */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_board_template.h b/drivers/gdisp/ILI9481/gdisp_lld_board_template.h
index 1bbcf282..e35f0c27 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld_board_template.h
+++ b/drivers/gdisp/ILI9481/gdisp_lld_board_template.h
@@ -88,7 +88,24 @@ static inline void write_data(uint16_t data) {
 
 }
 
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @notapi
+ */
+static inline void setreadmode(void) {
+
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @notapi
+ */
+static inline void setwritemode(void) {
+
+}
+
 /**
  * @brief   Read data from the lcd.
  *
@@ -101,7 +118,6 @@ static inline void write_data(uint16_t data) {
 static inline uint16_t read_data(void) {
 
 }
-#endif
 
 #endif /* _GDISP_LLD_BOARD_H */
 /** @} */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_config.h b/drivers/gdisp/ILI9481/gdisp_lld_config.h
index 79fea9f3..c41edd6b 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9481/gdisp_lld_config.h
@@ -24,12 +24,10 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"ILI9481"
+#define GDISP_DRIVER_STRUCT				GDISP_ILI9481
 
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			TRUE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 7ec2b590..d2808604 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -257,6 +257,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			}
 			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
+
 		case GDISP_CONTROL_ORIENTATION:
 			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
@@ -298,12 +299,14 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			}
 			g->g.Orientation = (orientation_t)value;
 			return;
+
         case GDISP_CONTROL_BACKLIGHT:
             if ((unsigned)g->p.ptr > 100)
             	g->p.ptr = (void *)100;
             set_backlight((unsigned)g->p.ptr);
             g->g.Backlight = (unsigned)g->p.ptr;
             return;
+
 		//case GDISP_CONTROL_CONTRAST:
         default:
             return;
-- 
cgit v1.2.3


From 77872d856086241f671dd7b265c9869ed0c54984 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 1 Oct 2013 21:11:42 +1000
Subject: Nokia6610 GE12 driver ported to streaming. Also added orientation and
 power control. Untested.

---
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c            | 547 ++++++---------------
 .../gdisp_lld_board_olimexsam7ex256.h              |  90 +++-
 .../gdisp/Nokia6610GE12/gdisp_lld_board_template.h |  18 +-
 drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h     |  11 +-
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             |  46 +-
 5 files changed, 256 insertions(+), 456 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index a991a9a6..441ac82d 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -17,17 +17,6 @@
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-/* Controller definitions */
-#include "GE12.h"
-
-/* This controller is only ever used with a 132 x 132 display */
 #if defined(GDISP_SCREEN_HEIGHT)
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
 	#undef GDISP_SCREEN_HEIGHT
@@ -36,11 +25,43 @@
 	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
 	#undef GDISP_SCREEN_WIDTH
 #endif
-#define GDISP_SCREEN_HEIGHT		132
-#define GDISP_SCREEN_WIDTH		132
 
-#define GDISP_INITIAL_CONTRAST	38
-#define GDISP_INITIAL_BACKLIGHT	100
+#define GDISP_LLD_DECLARATIONS
+#include "gdisp/lld/gdisp_lld.h"
+#include "gdisp_lld_board.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#include "GE12.h"
+
+#define GDISP_SCAN_LINES			132
+#define GDISP_SLEEP_SIZE			32		/* Sleep mode window lines - this must be 32 on this controller */
+
+// Set parameters if they are not already set
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		130
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		130
+#endif
+#ifndef GDISP_RAM_X_OFFSET
+	#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_RAM_Y_OFFSET
+	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
+#endif
+#endif
+#ifndef GDISP_SLEEP_POS
+	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2 & ~3)
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver exported variables.                                                */
@@ -50,12 +71,14 @@
 /* Driver local variables.                                                   */
 /*===========================================================================*/
 
+static color_t savecolor;
+
+#define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
+
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
-
 // Some macros just to make reading the code easier
 #define delayms(ms)					gfxSleepMilliseconds(ms)
 #define write_data2(d1, d2)			{ write_data(d1); write_data(d2); }
@@ -64,33 +87,11 @@
 #define write_cmd2(cmd, d1, d2)		{ write_cmd(cmd); write_data2(d1, d2); }
 #define write_cmd3(cmd, d1, d2, d3)	{ write_cmd(cmd); write_data3(d1, d2, d3); }
 
-// A very common thing to do.
-// An inline function has been used here incase the parameters have side effects with the internal calculations.
-static inline void setviewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-	write_cmd2(CASET, x, x+cx-1);			// Column address set
-	write_cmd2(PASET, y, y+cy-1);			// Page address set
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
 	init_board();
 
@@ -100,402 +101,142 @@ bool_t gdisp_lld_init(void) {
 	setpin_reset(FALSE);
 	delayms(20);
 
-	// Get the bus for the following initialisation commands
 	acquire_bus();
-	
-	// UNTESTED
-	#if 1
-		write_cmd(SLEEPOUT);								// Sleep out
-		write_cmd(INVON);									// Inversion on: seems to be required for this controller
-		write_cmd1(COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
-		write_cmd1(MADCTL, 0xC8);							// Memory access controler - 0xC0 = mirror x and y, reverse rgb
-		write_cmd1(SETCON, GDISP_INITIAL_CONTRAST);			// Write contrast
-		delayms(20);
-		write_cmd(DISPON);									// Display On
-	#else
-		// Alternative
-		write_cmd(SOFTRST);								// Software Reset
-		delayms(20);
-		write_cmd(INITESC);								// Initial escape
-		delayms(20);
-		write_cmd1(REFSET, 0x00);						// Refresh set
-		write_cmd(DISPCTRL);							// Set Display control - really 7 bytes of data
-			write_data(128);								// Set the lenght of one selection term
-			write_data(128);								// Set N inversion -> no N inversion
-			write_data(134);								// Set frame frequence and bias rate -> 2 devision of frequency and 1/8 bias, 1/67 duty, 96x67 size
-			write_data(84);									// Set duty parameter
-			write_data(69);									// Set duty parameter
-			write_data(82);									// Set duty parameter
-			write_data(67);									// Set duty parameter
-		write_cmd(GRAYSCALE0);							// Grey scale 0 position set - really 15 bytes of data
-			write_data(1);									// GCP1 - gray lavel to be output when the RAM data is "0001"
-			write_data(2);									// GCP2 - gray lavel to be output when the RAM data is "0010"
-			write_data(4);									// GCP3 - gray lavel to be output when the RAM data is "0011"
-			write_data(8);									// GCP4 - gray lavel to be output when the RAM data is "0100"
-			write_data(16);									// GCP5 - gray lavel to be output when the RAM data is "0101"
-			write_data(30);									// GCP6 - gray lavel to be output when the RAM data is "0110"
-			write_data(40);									// GCP7 - gray lavel to be output when the RAM data is "0111"
-			write_data(50);									// GCP8 - gray lavel to be output when the RAM data is "1000"
-			write_data(60);									// GCP9 - gray lavel to be output when the RAM data is "1001"
-			write_data(70);									// GCP10 - gray lavel to be output when the RAM data is "1010"
-			write_data(80);									// GCP11 - gray lavel to be output when the RAM data is "1011"
-			write_data(90);									// GCP12 - gray lavel to be output when the RAM data is "1100"
-			write_data(100);								// GCP13 - gray lavel to be output when the RAM data is "1101"
-			write_data(110);								// GCP14 - gray lavel to be output when the RAM data is "1110"
-			write_data(127);								// GCP15 - gray lavel to be output when the RAM data is "1111"
-		write_cmd1(GAMMA, 0x01);						// Gamma curve set - select gray scale - GRAYSCALE 0 or GREYSCALE 1 - Select grey scale 0
-		write_cmd1(COMMONDRV, 0x00);					// Command driver output - Set COM1-COM41 side come first, normal mod
-		write_cmd(NORMALMODE);							// Set Normal mode (my)
-		// write_cmd(INVERSIONOFF);						// Inversion off
-		write_cmd2(COLADDRSET, 0, 131);					// Column address set
-		write_cmd2(PAGEADDRSET, 0, 131);				// Page address set
-		write_cmd1(ACCESSCTRL, 0x40);					// Memory access controler - 0x40 horizontal
-		// write_data(0x20);								// vertical
-		write_cmd1(PWRCTRL, 0x04);						// Power control - Internal resistance, V1OUT -> high power mode, oscilator devision rate
-		write_cmd(SLEEPOUT);							// Sleep out
-		write_cmd(VOLTCTRL);							// Voltage control - voltage control and write contrast define LCD electronic volume
-		// write_data(0x7f);								//  full voltage control
-		// write_data(0x03);								//  must be "1"
-		write_cmd1(CONTRAST, GDISP_INITIAL_CONTRAST);	// Write contrast
-		delayms(20);
-		write_cmd(TEMPGRADIENT);						// Temperature gradient - really 14 bytes of data
-		for(i=0; i<14; i++)
-			write_data(0);
-		write_cmd(BOOSTVON);							// Booster voltage ON
-		write_cmd(DISPLAYON);							// Finally - Display On
-	#endif
-
-	// Release the bus
+	write_cmd(SLEEPOUT);								// Sleep out
+	write_cmd1(COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
+	write_cmd1(MADCTL, 0x00);							// Memory access controller
+	write_cmd1(SETCON, 127*GDISP_INITIAL_CONTRAST/100-64);			// Write contrast
+	delayms(20);
 	release_bus();
 	
 	/* Turn on the back-light */
 	set_backlight(GDISP_INITIAL_BACKLIGHT);
 
 	/* Initialise the GDISP structure to match */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	acquire_bus();
-	setviewport(x, y, 1, 1);
-	write_cmd3(RAMWR, 0, (color>>8) & 0x0F, color & 0xFF);
-	release_bus();
-}
-
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		unsigned i, tuples;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		tuples = (cx*cy+1)/2;				// With an odd sized area we over-print by one pixel.
-											// This extra pixel is ignored by the controller.
-
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
 		acquire_bus();
-		setviewport(x, y, cx, cy);
+		write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+		write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
 		write_cmd(RAMWR);
-		for(i=0; i < tuples; i++)
-			write_data3(((color >> 4) & 0xFF), (((color << 4) & 0xF0)|((color >> 8) & 0x0F)), (color & 0xFF));
-		release_bus();
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t endx, endy, lg;
-		color_t	c1, c2;
-		#if GDISP_PACKED_PIXELS
-			coord_t pos;
-			const uint8_t *p;
-		#endif
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		/* What are our end points */
-		endx = srcx + cx;
-		endy = y + cy;
-
-		acquire_bus();
-		setviewport(x, y, cx, cy);
-		write_cmd(RAMWR);
-
-		#if !GDISP_PACKED_PIXELS
-			// Although this controller uses packed pixels we support unpacked pixel
-			//  formats in this blit by packing the data as we feed it to the controller.
-			lg = srccx - cx;
-			buffer += srcy * srccx + srcx;
-			x = srcx;
-			while (1) {
-				/* Get a pixel */
-				c1 = *buffer++;
-				if (++x >= endx) {
-					if (++y >= endy) {
-						/* Odd pixel at end */
-						write_data3(0, ((c1 >> 8) & 0x0F), (c1 & 0xFF));
-						break;
-					}
-					x = srcx;
-					buffer += lg;
-				}
-				/* Get the next pixel */
-				c2 = *buffer++;
-				write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
-				if (++x >= endx) {
-					if (++y >= endy)
-						break;
-					x = srcx;
-					buffer += lg;
-				}
-			}
-
-		#else
-
-			// Although this controller uses packed pixels, we may have to feed it into
-			//  the controller with different packing to the source bitmap
-			#if !GDISP_PACKED_LINES
-				srccx = (srccx + 1) & ~1;
-			#endif
-			pos = srcy*srccx;
-			lg = (srccx - cx)/2*3;
-			p = ((const uint8_t *)buffer) + ((pos+srcx)/2 * 3);
-
-			x = srcx;
-			while (1) {
-				/* Get a pixel */
-				switch((pos+x)&1) {
-				case 0:		c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);	break;
-				case 1:		c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	break;
-				}
-				if (++x >= endx) {
-					if (++y >= endy) {
-						/* Odd pixel at end */
-						write_data3(0, ((c1 >> 8) & 0x0F), (c1 & 0xFF));
-						break;
-					}
-					x = srcx;
-					p += lg;
-					pos += srccx;
-				}
-				/* Get the next pixel */
-				switch((pos+x)&1) {
-				case 0:		c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);	break;
-				case 1:		c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	break;
-				}
-				write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
-				if (++x >= endx) {
-					if (++y >= endy)
-						break;
-					x = srcx;
-					p += lg;
-					pos += srccx;
-				}
-			}
-		#endif
-		release_bus();
+		g->flags &= ~GDISP_FLG_ODDBYTE;
 	}
-#endif
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The start of the text
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		/* NOT IMPLEMENTED */
-		/* Some board hardware might support this in the future.
-		 * The Olimex board doesn't.
-		 */
+	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			// Write the pair of pixels to the display
+			write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+			g->flags &= ~GDISP_FLG_ODDBYTE;
+		} else {
+			savecolor = g->p.color;
+			g->flags |= GDISP_FLG_ODDBYTE;
+		}
 	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		/* NOT IMPLEMENTED */
-		/* The hardware seems capable of doing this.
-		 * It is just really complex so we leave it out for now.
-		 */
+	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			write_data2(((savecolor >> 4) & 0xFF), ((savecolor << 4) & 0xF0));
+			write_cmd(NOP);
+		}
+		release_bus();
 	}
 #endif
 
-#if GDISP_HARDWARE_CONTROL || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
 		/* The hardware is capable of supporting...
-		 * 	GDISP_CONTROL_POWER				- not implemented yet
-		 * 	GDISP_CONTROL_ORIENTATION		- not implemented yet
-		 * 	GDISP_CONTROL_BACKLIGHT			- supported (the OlimexSAM7EX256 board.h currently only implements off/on although PWM is supported by the hardware)
+		 * 	GDISP_CONTROL_POWER				- supported
+		 * 	GDISP_CONTROL_ORIENTATION		- supported
+		 * 	GDISP_CONTROL_BACKLIGHT			- supported
 		 * 	GDISP_CONTROL_CONTRAST			- supported
 		 */
-		switch(what) {
-#if 0
-		// NOT IMPLEMENTED YET
+		switch(g->p.x) {
 		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
+				return;
+			switch((powermode_t)g->p.ptr) {
+			case powerOff:
+				acquire_bus();
+				write_cmd(SLEEPIN);
+				release_bus();
+				break;
+			case powerOn:
+				acquire_bus();
+				write_cmd(SLEEPOUT);
+				delayms(20);
+				write_cmd(NORON);							// Set Normal mode (my)
+				release_bus();
+				break;
+			case powerSleep:
+				acquire_bus();
+				write_cmd(SLEEPOUT);
+				delayms(20);
+				write_cmd2(PTLAR, GDISP_SLEEP_POS, GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)
+				write_cmd(PTLON);
+				release_bus();
+				break;
+			default:
 				return;
-			switch((gdisp_powermode_t)value) {
-				case powerOff:
-					// 	Code here
-					break;
-				case powerOn:
-					// 	Code here
-					/* You may need this ---
-					 *	if (GDISP.Powermode != powerSleep)
-					 *		gdisp_lld_init();
-					 */
-					break;
-				case powerSleep:
-					/* 	Code here */
-					break;
-				default:
-					return;
 			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
+			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
-#endif
-#if 0
-		// NOT IMPLEMENTED YET
+
 		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
+				return;
+			switch((orientation_t)g->p.ptr) {
+			case GDISP_ROTATE_0:
+				acquire_bus();
+				write_cmd1(MADCTL, 0x00);
+				release_bus();
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus();
+				write_cmd1(MADCTL, 0xA0);					// MY, MX, V, LAO, RGB, X, X, X
+				release_bus();
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus();
+				write_cmd1(MADCTL, 0xC0);
+				release_bus();
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus();
+				write_cmd1(MADCTL, 0x60);
+				release_bus();
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			default:
 				return;
-	//		WriteSpiData(0x48); // no mirror Y (temporary to satisfy Olimex bmptoarray utility)
-	//		WriteSpiData(0xC8); // restore to (mirror x and y, reverse rgb)
-			switch((gdisp_orientation_t)value) {
-				case GDISP_ROTATE_0:
-					// 	Code here
-					GDISP.Height = GDISP_SCREEN_HEIGHT;
-					GDISP.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_90:
-					// 	Code here
-					GDISP.Height = GDISP_SCREEN_WIDTH;
-					GDISP.Width = GDISP_SCREEN_HEIGHT;
-					break;
-				case GDISP_ROTATE_180:
-					// 	Code here
-					GDISP.Height = GDISP_SCREEN_HEIGHT;
-					GDISP.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_270:
-					// 	Code here
-					GDISP.Height = GDISP_SCREEN_WIDTH;
-					GDISP.Width = GDISP_SCREEN_HEIGHT;
-					break;
-				default:
-					return;
 			}
-			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
-#endif
+
 		case GDISP_CONTROL_BACKLIGHT:
-			if ((unsigned)value > 100) value = (void *)100;
-			set_backlight((unsigned)value);
-			GDISP.Backlight = (unsigned)value;
+			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
+			set_backlight((unsigned)g->p.ptr);
+			g->g.Backlight = (unsigned)g->p.ptr;
 			return;
 		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)value > 100) value = (void *)100;
+			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			acquire_bus();
-			write_cmd1(CONTRAST,(unsigned)value);
+			write_cmd1(CONTRAST,(unsigned)127*g->p.ptr/100-64);
 			release_bus();
-			GDISP.Contrast = (unsigned)value;
+			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
 		}
 	}
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
index ce0f7362..c8215c75 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
@@ -1,12 +1,12 @@
-/*
- * 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
- */
+/*
+ * 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
+ */
 
 /**
- * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
+ * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
  * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
  *
  * @addtogroup GDISP
@@ -16,14 +16,46 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
 // ******************************************************
 // Pointers to AT91SAM7X256 peripheral data structures
 // ******************************************************
-volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
-volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
-volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
-volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
-volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
+static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
+static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
+static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
+static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
+static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
+
+/* The PWM backlight control is non-linear on this board.
+ * We pick values here that make it look a bit more linear.
+ */
+#define PWM_TOP_VALUE		500
+#define PWM_BOTTOM_VALUE	200
+
+#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
+
+/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
+static const PWMConfig pwmcfg = {
+  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
+  1000,			/* PWM period is 1000 cycles. */
+  NULL,
+  {
+   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
+  },
+};
+
+static bool_t pwmRunning = FALSE;
 
 /**
  * @brief   Initialise the board for the display.
@@ -78,14 +110,14 @@ static inline void init_board(void) {
 	pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
 
 	// Fixed mode
-	pSPI->SPI_CR      = 0x81;               //SPI Enable, Sowtware reset
+	pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
 	pSPI->SPI_CR      = 0x01;               //SPI Enable
+	pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
+	pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
 
-	//pSPI->SPI_MR      = 0xE0019;            //Master mode, fixed select, disable decoder, FDIV=1 (MCK), PCS=1110
-	pSPI->SPI_MR      = 0xE0011;          //Master mode, fixed select, disable decoder, FDIV=0 (MCK), PCS=1110
-
-	//pSPI->SPI_CSR[0]  = 0x01010C11;           //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/32*12 = 125kHz
-	pSPI->SPI_CSR[0]  = 0x01010311;        //9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/8 = 6MHz if using commented MR line above
+	/* Display backlight control at 100% */
+	pwmRunning = FALSE;
+	palSetPad(IOPORT2, PIOB_LCD_BL);
 }
 
 /**
@@ -113,10 +145,28 @@ static inline void setpin_reset(bool_t state) {
  * @notapi
  */
 static inline void set_backlight(uint8_t percent) {
-	if (percent)
+	if (percent == 100) {
+		/* Turn the pin on - No PWM */
+		if (pwmRunning) {
+			pwmStop(&PWMD2);
+			pwmRunning = FALSE;
+		}
 		palSetPad(IOPORT2, PIOB_LCD_BL);
-	else
+	} else if (percent == 0) {
+		/* Turn the pin off - No PWM */
+		if (pwmRunning) {
+			pwmStop(&PWMD2);
+			pwmRunning = FALSE;
+		}
 		palClearPad(IOPORT2, PIOB_LCD_BL);
+	} else {
+		/* Use the PWM */
+		if (!pwmRunning) {
+			pwmStart(&PWMD2, &pwmcfg);
+			pwmRunning = TRUE;
+		}
+		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
+	}
 }
 
 /**
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
index a1fa6050..d3594434 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
@@ -6,8 +6,8 @@
  */
 
 /**
- * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Nokia6610 GE8 display.
+ * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the Nokia6610 GE12 display.
  *
  * @addtogroup GDISP
  * @{
@@ -16,6 +16,18 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
 /**
  * @brief   Initialise the board for the display.
  * @notes	Performs the following functions:
@@ -95,7 +107,7 @@ static inline void write_data(uint16_t data) {
 
 }
 
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
+#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL
 /**
  * @brief   Read data from the lcd.
  *
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
index 57b8b916..edbf3290 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
@@ -23,13 +23,10 @@
 /*===========================================================================*/
 
 #define GDISP_DRIVER_NAME				"Nokia6610GE12"
-
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_CONTROL			TRUE
-
-#define GDISP_SOFTWARE_TEXTFILLDRAW		FALSE
-#define GDISP_SOFTWARE_TEXTBLITCOLUMN	FALSE
+#define GDISP_DRIVER_STRUCT				GDISP_Nokia6610GE12
+
+#define GDISP_HARDWARE_CONTROL			TRUE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
 /* This driver supports both packed and unpacked pixel formats and line formats.
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index ce0400d1..3f535369 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -518,29 +518,29 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 					return;
 				acquire_bus();
 				switch((orientation_t)g->p.ptr) {
-					case GDISP_ROTATE_0:
-						write_cmd3(DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
-						g->g.Height = GDISP_SCREEN_HEIGHT;
-						g->g.Width = GDISP_SCREEN_WIDTH;
-						break;
-					case GDISP_ROTATE_90:
-						write_cmd3(DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
-						g->g.Height = GDISP_SCREEN_WIDTH;
-						g->g.Width = GDISP_SCREEN_HEIGHT;
-						break;
-					case GDISP_ROTATE_180:
-						write_cmd3(DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
-						g->g.Height = GDISP_SCREEN_HEIGHT;
-						g->g.Width = GDISP_SCREEN_WIDTH;
-						break;
-					case GDISP_ROTATE_270:
-						write_cmd3(DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
-						g->g.Height = GDISP_SCREEN_WIDTH;
-						g->g.Width = GDISP_SCREEN_HEIGHT;
-						break;
-					default:
-						release_bus();
-						return;
+				case GDISP_ROTATE_0:
+					write_cmd3(DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+				case GDISP_ROTATE_90:
+					write_cmd3(DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+				case GDISP_ROTATE_180:
+					write_cmd3(DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+				case GDISP_ROTATE_270:
+					write_cmd3(DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+				default:
+					release_bus();
+					return;
 				}
 				release_bus();
 				g->g.Orientation = (orientation_t)g->p.ptr;
-- 
cgit v1.2.3


From 8408e020b4a80f40ccbc15378a85fa2ce09da361 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 2 Oct 2013 00:56:57 +1000
Subject: Compile error fix. Nokia GE8 - scale contrast correctly.

---
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c                      | 1 -
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c                       | 8 ++++----
 drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h | 2 +-
 3 files changed, 5 insertions(+), 6 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index 441ac82d..c8071917 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -52,7 +52,6 @@
 #ifndef GDISP_RAM_Y_OFFSET
 	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
 #endif
-#endif
 #ifndef GDISP_SLEEP_POS
 	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2 & ~3)
 #endif
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index 3f535369..d3e30d0e 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -93,7 +93,7 @@
 	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2)
 #endif
 #ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	38
+	#define GDISP_INITIAL_CONTRAST	60
 #endif
 #ifndef GDISP_INITIAL_BACKLIGHT
 	#define GDISP_INITIAL_BACKLIGHT	100
@@ -162,8 +162,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 															// P1: 0x00 = page address normal, column address normal, address scan in column direction
 															// P2: 0x00 = RGB sequence (default value)
 															// P3: 0x02 = 4 bits per colour (Type A)
-	write_cmd2(VOLCTR, GDISP_INITIAL_CONTRAST, 0x03);	// Voltage control (contrast setting)
-															// P1 = Contrast
+	write_cmd2(VOLCTR, 63*GDISP_INITIAL_CONTRAST/100, 0x03);	// Voltage control (contrast setting)
+															// P1 = Contrast (0..63)
 															// P2 = 3 resistance ratio (only value that works)
 	delayms(100);										// Allow power supply to stabilise
 	write_cmd(DISON);									// Turn on the display
@@ -554,7 +554,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		case GDISP_CONTROL_CONTRAST:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			acquire_bus();
-			write_cmd2(VOLCTR, (unsigned)g->p.ptr, 0x03);
+			write_cmd2(VOLCTR, 63*(unsigned)g->p.ptr/100, 0x03);
 			release_bus();
 			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
index 8afc3573..4eeea62f 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
@@ -227,7 +227,7 @@ static inline void write_data(uint16_t data) {
  */
 static inline uint16_t read_data(void) {
 	#error "gdispNokia6610GE8: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board"
-	return 0;
+	return pSPI->SPI_RDR;
 }
 #endif
 
-- 
cgit v1.2.3


From d7d02395d0c1afe27bc39eeddc17899084c72de9 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 2 Oct 2013 16:30:06 +1000
Subject: Updates to ported drivers to support new optimisation method.
 Includes Bug fixes.

---
 drivers/gdisp/ILI9320/gdisp_lld.c        | 43 ++++++++++++++++++++++----------
 drivers/gdisp/ILI9320/gdisp_lld_config.h |  1 +
 drivers/gdisp/ILI9325/gdisp_lld.c        | 42 +++++++++++++++++++++----------
 drivers/gdisp/ILI9325/gdisp_lld_config.h |  1 +
 drivers/gdisp/SSD1289/gdisp_lld.c        | 37 ++++++++++++++++++++-------
 drivers/gdisp/SSD1289/gdisp_lld_config.h |  1 +
 6 files changed, 90 insertions(+), 35 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index d8bc411a..68081b96 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -57,31 +57,43 @@ uint32_t DISPLAY_CODE;
 #define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
 #define write_reg(reg, data)		{ write_index(reg); write_data(data); }
 
-static void set_viewport(uint16_t x, uint16_t y, uint16_t cx, uint16_t cy) {
+static void set_cursor(GDISPDriver *g) {
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 		case GDISP_ROTATE_180:
-			write_reg(0x0050, x);
-			write_reg(0x0051, x + cx - 1);
-			write_reg(0x0052, y);
-			write_reg(0x0053, y + cy - 1);
-			write_reg(0x0020, x);
-			write_reg(0x0021, y);
+			write_reg(0x0020, g->p.x);
+			write_reg(0x0021, g->p.y);
 			break;
 
 		case GDISP_ROTATE_90:
 		case GDISP_ROTATE_270:
-			write_reg(0x0050, y);
-			write_reg(0x0051, y + cy - 1);
-			write_reg(0x0052, x);
-			write_reg(0x0053, x + cx - 1);
-			write_reg(0x0020, y);
-			write_reg(0x0021, x);
+			write_reg(0x0020, g->p.y);
+			write_reg(0x0021, g->p.x);
 			break;
 	}
 	write_index(0x0022);
 }
 
+static void set_viewport(GDISPDriver *g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(0x0050, g->p.x);
+			write_reg(0x0051, g->p.x + g->p.cx - 1);
+			write_reg(0x0052, g->p.y);
+			write_reg(0x0053, g->p.y + g->p.cy - 1);
+			break;
+
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(0x0050, g->p.y);
+			write_reg(0x0051, g->p.y + g->p.cy - 1);
+			write_reg(0x0052, g->p.x);
+			write_reg(0x0053, g->p.x + g->p.cx - 1);
+			break;
+	}
+}
+
 LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	/* Initialise your display */
 	init_board();
@@ -181,12 +193,17 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		release_bus();
 	}
+	LLDSPEC void gdisp_lld_write_pos(GDISPDriver *g) {
+		set_cursor(g);
+	}
+	#endif
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
 	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
 		acquire_bus();
 		set_viewport(g);
+		set_cursor(g);
 		setreadmode();
 		dummy_read();
 	}
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
index 7cf7457a..02533e8b 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -27,6 +27,7 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index a30bea44..4795887e 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -61,29 +61,41 @@ uint32_t DISPLAY_CODE;
 #define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
 #define write_reg(reg, data)		{ write_index(reg); write_data(data); }
 
+static void set_cursor(GDISPDriver *g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(0x0020, g->p.x);
+			write_reg(0x0021, g->p.y);
+			break;
+
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(0x0020, g->p.y);
+			write_reg(0x0021, g->p.x);
+			break;
+	}
+	write_index(0x0022);
+}
+
 static void set_viewport(GDISPDriver* g) {
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 		case GDISP_ROTATE_180:
-			write_reg(0x0050, x);
-			write_reg(0x0051, x + cx - 1);
-			write_reg(0x0052, y);
-			write_reg(0x0053, y + cy - 1);
-			write_reg(0x0020, x);
-			write_reg(0x0021, y);
+			write_reg(0x0050, g->p.x);
+			write_reg(0x0051, g->p.x + g->p.cx - 1);
+			write_reg(0x0052, g->p.y);
+			write_reg(0x0053, g->p.y + g->p.cy - 1);
 			break;
 
 		case GDISP_ROTATE_90:
 		case GDISP_ROTATE_270:
-			write_reg(0x0050, y);
-			write_reg(0x0051, y + cy - 1);
-			write_reg(0x0052, x);
-			write_reg(0x0053, x + cx - 1);
-			write_reg(0x0020, y);
-			write_reg(0x0021, x);
+			write_reg(0x0050, g->p.y);
+			write_reg(0x0051, g->p.y + g->p.cy - 1);
+			write_reg(0x0052, g->p.x);
+			write_reg(0x0053, g->p.x + g->p.cx - 1);
 			break;
 	}
-    write_reg(0x0022, color);
 }
 
 LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
@@ -182,12 +194,16 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		release_bus();
 	}
+	LLDSPEC void gdisp_lld_write_pos(GDISPDriver *g) {
+		set_cursor(g);
+	}
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
 	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
 		acquire_bus();
 		set_viewport(g);
+		set_cursor(g);
 		setreadmode();
 		dummy_read();
 	}
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_config.h b/drivers/gdisp/ILI9325/gdisp_lld_config.h
index 572b8361..aabf768f 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_config.h
@@ -27,6 +27,7 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index d2808604..09122d2f 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -43,6 +43,28 @@
 #define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
 #define write_reg(reg, data)		{ write_index(reg); write_data(data); }
 
+static void set_cursor(GDISPDriver *g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			write_reg(0x004e, g->p.x & 0x00FF);
+			write_reg(0x004f, g->p.y & 0x01FF);
+			break;
+		case GDISP_ROTATE_90:
+			write_reg(0x004e, g->p.y & 0x00FF);
+			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
+			break;
+		case GDISP_ROTATE_180:
+			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
+			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
+			break;
+		case GDISP_ROTATE_270:
+			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
+			write_reg(0x004f, g->p.x & 0x01FF);
+			break;
+	}
+	write_index(0x0022);
+}
+
 static void set_viewport(GDISPDriver* g) {
 	/* Reg 0x44 - Horizontal RAM address position
 	 * 		Upper Byte - HEA
@@ -60,33 +82,24 @@ static void set_viewport(GDISPDriver* g) {
 			write_reg(0x44, (((g->p.x+g->p.cx-1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
 			write_reg(0x45, g->p.y & 0x01FF);
 			write_reg(0x46, (g->p.y+g->p.cy-1) & 0x01FF);
-			write_reg(0x004e, g->p.x & 0x00FF);
-			write_reg(0x004f, g->p.y & 0x01FF);
 			break;
 		case GDISP_ROTATE_90:
 			write_reg(0x44, (((g->p.y+g->p.cy-1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
 			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.x+g->p.cx)) & 0x01FF);
 			write_reg(0x46, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
-			write_reg(0x004e, g->p.y & 0x00FF);
-			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
 			write_reg(0x44, (((GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
 			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
 			write_reg(0x46, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
-			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
-			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
 			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
 			write_reg(0x44, (((GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH-(g->p.y+g->p.cy)) & 0x00FF));
 			write_reg(0x45, g->p.x & 0x01FF);
 			write_reg(0x46, (g->p.x+g->p.cx-1) & 0x01FF);
-			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
-			write_reg(0x004f, g->p.x & 0x01FF);
 			break;
 	}
-	write_index(0x0022);
 }
 
 /*===========================================================================*/
@@ -179,12 +192,16 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
 		release_bus();
 	}
+	LLDSPEC void gdisp_lld_stream_pos(GDISPDriver *g) {
+		set_cursor(g);
+	}
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
 	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
 		acquire_bus();
 		set_viewport(g);
+		set_cursor(g);
 		setreadmode();
 		dummy_read();
 	}
@@ -201,6 +218,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
 		acquire_bus();
 		set_viewport(g);
+		set_cursor(g);
 		dma_with_noinc(&color, g->p.cx*g->p.cy)
 		release_bus();
 	}
@@ -215,6 +233,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 		acquire_bus();
 		set_viewport(g);
+		set_cursor(g);
 		if (g->p.x2 == g->p.cx) {
 			dma_with_inc(buffer, g->p.cx*g->p.cy);
 		} else {
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index 9c00ce39..fc04a798 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -27,6 +27,7 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #if defined(GDISP_USE_DMA)
-- 
cgit v1.2.3


From d22bc07e7adf459b2b83fcd0e5bd6475c18e1e9a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 12 Oct 2013 13:24:40 +1000
Subject: Multiple displays across one or more controllers is now fully
 supported. Only the Win32 driver supports this so far. Other drivers are
 currently broken due to API changes and will be fixed.

---
 drivers/multiple/Win32/gdisp_lld.c                | 739 ++++++++++++++--------
 drivers/multiple/Win32/gdisp_lld_config.h         |   7 +-
 drivers/multiple/Win32/ginput_lld_toggle_config.h |  15 +-
 drivers/multiple/X/gdisp_lld_config.h             |   9 +-
 4 files changed, 503 insertions(+), 267 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 41141a90..65627e1c 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -9,12 +9,11 @@
  * @file    drivers/multiple/Win32/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for Win32.
  */
-
 #include "gfx.h"
 
 #if GFX_USE_GDISP
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_Win32
 #include "gdisp/lld/gdisp_lld.h"
 
 #include <stdio.h>
@@ -31,51 +30,80 @@
 	#define GDISP_SCREEN_HEIGHT	480
 #endif
 
+#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_HASTOGGLE			(GDISP_FLG_DRIVER<<1)
+#define GDISP_FLG_HASMOUSE			(GDISP_FLG_DRIVER<<2)
+
 #if GINPUT_NEED_TOGGLE
 	/* Include toggle support code */
 	#include "ginput/lld/toggle.h"
 #endif
 
+#if GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888
+	#error "GDISP Win32: This driver currently only supports the RGB888 pixel format."
+#endif
+
 #if GINPUT_NEED_MOUSE
 	/* Include mouse support code */
 	#include "ginput/lld/mouse.h"
 #endif
 
+// Setting this to TRUE delays updating the screen
+// to the windows paint routine. Due to the
+// drawing lock this does not add as much speed
+// as might be expected but it is still faster in
+// all tested circumstances and for all operations
+// even draw_pixel().
+// This is probably due to drawing operations being
+// combined as the update regions are merged.
+#define GDISP_WIN32_USE_INDIRECT_UPDATE		TRUE
+
+// How far extra windows should be offset from the first.
+#define DISPLAY_X_OFFSET		50
+#define DISPLAY_Y_OFFSET		50
+
+static DWORD			winThreadId;
+static ATOM				winClass;
+static volatile bool_t	QReady;
+static HANDLE			drawMutex;
+
+
 /*===========================================================================*/
 /* Driver local routines    .                                                */
 /*===========================================================================*/
 
-#define WIN32_USE_MSG_REDRAW	FALSE
 #if GINPUT_NEED_TOGGLE
 	#define WIN32_BUTTON_AREA		16
 #else
 	#define WIN32_BUTTON_AREA		0
 #endif
 
-#define APP_NAME "GDISP"
+#define APP_NAME "uGFX"
 
 #define COLOR2BGR(c)	((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF))
 #define BGR2COLOR(c)	COLOR2BGR(c)
 
-static HWND winRootWindow = NULL;
-static HDC dcBuffer = NULL;
-static HBITMAP dcBitmap = NULL;
-static HBITMAP dcOldBitmap;
-static volatile bool_t isReady = FALSE;
-static coord_t	wWidth, wHeight;
+typedef struct winPriv {
+	HWND			hwnd;
+	HDC				dcBuffer;
+	HBITMAP			dcBitmap;
+	HBITMAP 		dcOldBitmap;
+	#if GINPUT_NEED_MOUSE
+		coord_t		mousex, mousey;
+		uint16_t	mousebuttons;
+	#endif
+	#if GINPUT_NEED_TOGGLE
+		uint8_t		toggles;
+	#endif
+} winPriv;
 
-#if GINPUT_NEED_MOUSE
-	static coord_t	mousex, mousey;
-	static uint16_t	mousebuttons;
-#endif
-#if GINPUT_NEED_TOGGLE
-	static uint8_t	toggles = 0;
-#endif
 
 static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
 {
-	HDC			dc;
-	PAINTSTRUCT	ps;
+	HDC				dc;
+	PAINTSTRUCT		ps;
+	GDisplay *		g;
+	winPriv *		priv;
 	#if GINPUT_NEED_TOGGLE
 		HBRUSH		hbrOn, hbrOff;
 		HPEN		pen;
@@ -88,86 +116,135 @@ static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
 
 	switch (Msg) {
 	case WM_CREATE:
+		// Get our GDisplay structure and attach it to the window
+		g = (GDisplay *)((LPCREATESTRUCT)lParam)->lpCreateParams;
+		priv = (winPriv *)g->priv;
+		SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g);
+
+		// Fill in the private area
+		priv->hwnd = hWnd;
+		dc = GetDC(hWnd);
+		priv->dcBitmap = CreateCompatibleBitmap(dc, g->g.Width, g->g.Height);
+		priv->dcBuffer = CreateCompatibleDC(dc);
+		ReleaseDC(hWnd, dc);
+		priv->dcOldBitmap = SelectObject(priv->dcBuffer, priv->dcBitmap);
+
+		// Mark the window as ready to go
+		g->flags |= GDISP_FLG_READY;
 		break;
-	case WM_LBUTTONDOWN:
-		#if GINPUT_NEED_MOUSE
-			if ((coord_t)HIWORD(lParam) < wHeight) {
-				mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
+
+	#if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE
+		case WM_LBUTTONDOWN:
+			// Get our GDisplay structure
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+
+			// Handle mouse down on the window
+			#if GINPUT_NEED_MOUSE
+				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+					priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
+					goto mousemove;
+				}
+			#endif
+
+			// Handle mouse down on the toggle area
+			#if GINPUT_NEED_TOGGLE
+				if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
+					bit = 1 << ((coord_t)LOWORD(lParam)*8/g->g.Width);
+					priv->toggles ^= bit;
+					rect.left = 0;
+					rect.right = GDISP_SCREEN_WIDTH;
+					rect.top = GDISP_SCREEN_HEIGHT;
+					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
+					InvalidateRect(hWnd, &rect, FALSE);
+					UpdateWindow(hWnd);
+					#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
+						ginputToggleWakeup();
+					#endif
+				}
+			#endif
+			break;
+
+		case WM_LBUTTONUP:
+			// Get our GDisplay structure
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+
+			// Handle mouse up on the toggle area
+			#if GINPUT_NEED_TOGGLE
+				if ((g->flags & GDISP_FLG_HASTOGGLE)) {
+					if ((priv->toggles & 0x0F)) {
+						priv->toggles &= ~0x0F;
+						rect.left = 0;
+						rect.right = GDISP_SCREEN_WIDTH;
+						rect.top = GDISP_SCREEN_HEIGHT;
+						rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
+						InvalidateRect(hWnd, &rect, FALSE);
+						UpdateWindow(hWnd);
+						#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
+							ginputToggleWakeup();
+						#endif
+					}
+				}
+			#endif
+
+			// Handle mouse up on the window
+			#if GINPUT_NEED_MOUSE
+				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+					priv->mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
+					goto mousemove;
+				}
+			#endif
+			break;
+	#endif
+
+	#if GINPUT_NEED_MOUSE
+		case WM_MBUTTONDOWN:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
 				goto mousemove;
 			}
-		#endif
-		#if GINPUT_NEED_TOGGLE
-			bit = 1 << ((coord_t)LOWORD(lParam)*8/wWidth);
-			toggles ^= bit;
-			rect.left = 0;
-			rect.right = wWidth;
-			rect.top = wHeight;
-			rect.bottom = wHeight + WIN32_BUTTON_AREA;
-			InvalidateRect(hWnd, &rect, FALSE);
-			UpdateWindow(hWnd);
-			#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
-				ginputToggleWakeup();
-			#endif
-		#endif
-		break;
-	case WM_LBUTTONUP:
-		#if GINPUT_NEED_TOGGLE
-			if ((toggles & 0x0F)) {
-				toggles &= ~0x0F;
-				rect.left = 0;
-				rect.right = wWidth;
-				rect.top = wHeight;
-				rect.bottom = wHeight + WIN32_BUTTON_AREA;
-				InvalidateRect(hWnd, &rect, FALSE);
-				UpdateWindow(hWnd);
-				#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
-					ginputToggleWakeup();
-				#endif
+			break;
+		case WM_MBUTTONUP:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
+				goto mousemove;
 			}
-		#endif
-		#if GINPUT_NEED_MOUSE
-			if ((coord_t)HIWORD(lParam) < wHeight) {
-				mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
+			break;
+		case WM_RBUTTONDOWN:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
 				goto mousemove;
 			}
-		#endif
-		break;
-#if GINPUT_NEED_MOUSE
-	case WM_MBUTTONDOWN:
-		if ((coord_t)HIWORD(lParam) < wHeight) {
-			mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
-			goto mousemove;
-		}
-		break;
-	case WM_MBUTTONUP:
-		if ((coord_t)HIWORD(lParam) < wHeight) {
-			mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
-			goto mousemove;
-		}
-		break;
-	case WM_RBUTTONDOWN:
-		if ((coord_t)HIWORD(lParam) < wHeight) {
-			mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
-			goto mousemove;
-		}
-		break;
-	case WM_RBUTTONUP:
-		if ((coord_t)HIWORD(lParam) < wHeight) {
-			mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
-			goto mousemove;
-		}
-		break;
-	case WM_MOUSEMOVE:
-		if ((coord_t)HIWORD(lParam) >= wHeight)
 			break;
-	mousemove:
-		mousex = (coord_t)LOWORD(lParam); 
-		mousey = (coord_t)HIWORD(lParam); 
-		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
-			ginputMouseWakeup();
-		#endif
-		break;
-#endif
+		case WM_RBUTTONUP:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
+				goto mousemove;
+			}
+			break;
+		case WM_MOUSEMOVE:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT || !(g->flags & GDISP_FLG_HASMOUSE))
+				break;
+		mousemove:
+			priv->mousex = (coord_t)LOWORD(lParam);
+			priv->mousey = (coord_t)HIWORD(lParam);
+			#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+				ginputMouseWakeup();
+			#endif
+			break;
+	#endif
+
 	case WM_SYSKEYDOWN:
 	case WM_KEYDOWN:
 	case WM_SYSKEYUP:
@@ -178,26 +255,41 @@ static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
 	case WM_SYSCHAR:
 	case WM_SYSDEADCHAR:
 		break;
+
+	case WM_ERASEBKGND:
+		// Pretend we have erased the background.
+		// We know we don't really need to do this as we
+		// redraw the entire surface in the WM_PAINT handler.
+		return TRUE;
+
 	case WM_PAINT:
+		// Get our GDisplay structure
+		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+		priv = (winPriv *)g->priv;
+
+		// Paint the main window area
+		WaitForSingleObject(drawMutex, INFINITE);
 		dc = BeginPaint(hWnd, &ps);
 		BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
 			ps.rcPaint.right - ps.rcPaint.left,
-			(ps.rcPaint.bottom > wHeight ? wHeight : ps.rcPaint.bottom) - ps.rcPaint.top,
-			dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
+			(ps.rcPaint.bottom > GDISP_SCREEN_HEIGHT ? GDISP_SCREEN_HEIGHT : ps.rcPaint.bottom) - ps.rcPaint.top,
+			priv->dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
+
+		// Paint the toggle area
 		#if GINPUT_NEED_TOGGLE
-			if (ps.rcPaint.bottom >= wHeight) {
+			if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
 				pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black));
 				hbrOn = CreateSolidBrush(COLOR2BGR(Blue));
 				hbrOff = CreateSolidBrush(COLOR2BGR(Gray));
 				old = SelectObject(dc, pen);
-				MoveToEx(dc, 0, wHeight, &p);
-				LineTo(dc, wWidth, wHeight);
+				MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p);
+				LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
 				for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) {
 					rect.left = pos;
-					rect.right = pos + wWidth/8;
-					rect.top = wHeight;
-					rect.bottom = wHeight + WIN32_BUTTON_AREA;
-					FillRect(dc, &rect, (toggles & bit) ? hbrOn : hbrOff);
+					rect.right = pos + GDISP_SCREEN_WIDTH/8;
+					rect.top = GDISP_SCREEN_HEIGHT;
+					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
+					FillRect(dc, &rect, (priv->toggles & bit) ? hbrOn : hbrOff);
 					if (pos > 0) {
 						MoveToEx(dc, rect.left, rect.top, &p);
 						LineTo(dc, rect.left, rect.bottom);
@@ -209,74 +301,75 @@ static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
 			}
 		#endif
 		EndPaint(hWnd, &ps);
+		ReleaseMutex(drawMutex);
 		break;
+
 	case WM_DESTROY:
+		// Get our GDisplay structure
+		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+		priv = (winPriv *)g->priv;
+
+		// Restore the window and free our bitmaps
+		SelectObject(priv->dcBuffer, priv->dcOldBitmap);
+		DeleteDC(priv->dcBuffer);
+		DeleteObject(priv->dcBitmap);
+
+		// Cleanup the private area
+		gfxFree(priv);
+
+		// Quit the application
 		PostQuitMessage(0);
-		SelectObject(dcBuffer, dcOldBitmap);
-		DeleteDC(dcBuffer);
-		DeleteObject(dcBitmap);
-		winRootWindow = NULL;
+
+		// Actually the above doesn't work (who knows why)
+		ExitProcess(0);
 		break;
+
 	default:
 		return DefWindowProc(hWnd, Msg, wParam, lParam);
 	}
 	return 0;
 }
 
-static void InitWindow(void) {
-	HANDLE hInstance;
-	WNDCLASS wc;
-	RECT	rect;
-	HDC		dc;
-
-	hInstance = GetModuleHandle(NULL);
-
-	wc.style           = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
-	wc.lpfnWndProc     = (WNDPROC)myWindowProc;
-	wc.cbClsExtra      = 0;
-	wc.cbWndExtra      = 0;
-	wc.hInstance       = hInstance;
-	wc.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
-	wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
-	wc.hbrBackground   = GetStockObject(WHITE_BRUSH);
-	wc.lpszMenuName    = NULL;
-	wc.lpszClassName   = APP_NAME;
-	RegisterClass(&wc);
-
-	rect.top = 0; rect.bottom = wHeight+WIN32_BUTTON_AREA;
-	rect.left = 0; rect.right = wWidth;
-	AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
-	winRootWindow = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0, 0,
-			rect.right-rect.left, rect.bottom-rect.top, 0, 0, hInstance, NULL);
-	assert(winRootWindow != NULL);
-
-
-	GetClientRect(winRootWindow, &rect);
-	wWidth = rect.right-rect.left;
-	wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA;
-
-	dc = GetDC(winRootWindow);
-	dcBitmap = CreateCompatibleBitmap(dc, wWidth, wHeight);
-	dcBuffer = CreateCompatibleDC(dc);
-	ReleaseDC(winRootWindow, dc);
-	dcOldBitmap = SelectObject(dcBuffer, dcBitmap);
-
-	ShowWindow(winRootWindow, SW_SHOW);
-	UpdateWindow(winRootWindow);
-	isReady = TRUE;
-}
-
 static DECLARE_THREAD_STACK(waWindowThread, 1024);
 static DECLARE_THREAD_FUNCTION(WindowThread, param) {
 	(void)param;
 	MSG msg;
 
-	InitWindow();
+	// Establish this thread as a message queue thread
+	winThreadId = GetCurrentThreadId();
+	PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+	QReady = TRUE;
+
 	do {
 		gfxSleepMilliseconds(1);
 		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-			TranslateMessage(&msg);
-			DispatchMessage(&msg);
+			// Is this our special thread message to create a new window?
+			if (!msg.hwnd && msg.message == WM_USER) {
+				RECT		rect;
+				GDisplay	*g;
+
+				g = (GDisplay *)msg.lParam;
+
+				// Set the window rectangle
+				rect.top = 0; rect.bottom = g->g.Height;
+				rect.left = 0; rect.right = g->g.Width;
+				#if GINPUT_NEED_TOGGLE
+					if ((g->flags & GDISP_FLG_HASTOGGLE))
+						rect.bottom += WIN32_BUTTON_AREA;
+				#endif
+				AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
+
+				// Create the window
+				msg.hwnd = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_BORDER, msg.wParam*DISPLAY_X_OFFSET, msg.wParam*DISPLAY_Y_OFFSET,
+								rect.right-rect.left, rect.bottom-rect.top, 0, 0,
+								GetModuleHandle(NULL), g);
+				assert(msg.hwnd != NULL);
+
+			// Or just a normal window message
+			} else {
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
+			}
 		}
 	} while (msg.message != WM_QUIT);
 	ExitProcess(0);
@@ -287,44 +380,89 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
-	RECT			rect;
-	gfxThreadHandle	hth;
-
-	/* Set the window dimensions */
-	GetWindowRect(GetDesktopWindow(), &rect);
-	wWidth = rect.right - rect.left;
-	wHeight = rect.bottom - rect.top - WIN32_BUTTON_AREA;
-	if (wWidth > GDISP_SCREEN_WIDTH)
-		wWidth = GDISP_SCREEN_WIDTH;
-	if (wHeight > GDISP_SCREEN_HEIGHT)
-		wHeight = GDISP_SCREEN_HEIGHT;
-
-	/* Initialise the window */
-	if (!(hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0))) {
-		fprintf(stderr, "Cannot create window thread\n");
-		exit(-1);
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+	winPriv	*	priv;
+	char		buf[132];
+
+	// Initialise the window thread and the window class (if it hasn't been done already)
+	if (!QReady) {
+		gfxThreadHandle	hth;
+		WNDCLASS		wc;
+
+		// Create the draw mutex
+		drawMutex = CreateMutex(NULL, FALSE, NULL);
+
+		// Create the thread
+		hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0);
+		assert(hth != NULL);
+		gfxThreadClose(hth);
+
+		wc.style           = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
+		wc.lpfnWndProc     = (WNDPROC)myWindowProc;
+		wc.cbClsExtra      = 0;
+		wc.cbWndExtra      = 0;
+		wc.hInstance       = GetModuleHandle(NULL);
+		wc.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
+		wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
+		wc.hbrBackground   = GetStockObject(WHITE_BRUSH);
+		wc.lpszMenuName    = NULL;
+		wc.lpszClassName   = APP_NAME;
+		winClass = RegisterClass(&wc);
+		assert(winClass != 0);
+
+		// Wait for our thread to be ready
+		while (!QReady)
+			Sleep(1);
 	}
-	gfxThreadClose(hth);
-	while (!isReady)
-		Sleep(1);
 
-	/* Initialise the GDISP structure to match */
+	// Initialise the GDISP structure
 	g->g.Orientation = GDISP_ROTATE_0;
 	g->g.Powermode = powerOn;
 	g->g.Backlight = 100;
 	g->g.Contrast = 50;
-	g->g.Width = wWidth;
-	g->g.Height = wHeight;
+	g->g.Width = GDISP_SCREEN_WIDTH;
+	g->g.Height = GDISP_SCREEN_HEIGHT;
+
+	// Turn on toggles for the first GINPUT_TOGGLE_CONFIG_ENTRIES windows
+	#if GINPUT_NEED_TOGGLE
+		if (display < GINPUT_TOGGLE_CONFIG_ENTRIES)
+			g->flags |= GDISP_FLG_HASTOGGLE;
+	#endif
+
+	// Only turn on mouse on the first window for now
+	#if GINPUT_NEED_MOUSE
+		if (!display)
+			g->flags |= GDISP_FLG_HASMOUSE;
+	#endif
+
+	// Create a private area for this window
+	priv = (winPriv *)gfxAlloc(sizeof(winPriv));
+	assert(priv != NULL);
+	memset(priv, 0, sizeof(winPriv));
+	g->priv = priv;
+
+	// Create the window in the message thread
+	PostThreadMessage(winThreadId, WM_USER, (WPARAM)display, (LPARAM)g);
+
+	// Wait for the window creation to complete (for safety)
+	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
+		Sleep(1);
+
+	sprintf(buf, APP_NAME " - %u", display+1);
+	SetWindowText(priv->hwnd, buf);
+	ShowWindow(priv->hwnd, SW_SHOW);
+	UpdateWindow(priv->hwnd);
+
 	return TRUE;
 }
 
 #if GDISP_HARDWARE_DRAWPIXEL
-	LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) {
-		HDC			dcScreen;
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		winPriv	*	priv;
 		int			x, y;
 		COLORREF	color;
 	
+		priv = g->priv;
 		color = COLOR2BGR(g->p.color);
 	
 		#if GDISP_NEED_CONTROL
@@ -352,23 +490,41 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		#endif
 
 		// Draw the pixel on the screen and in the buffer.
-		dcScreen = GetDC(winRootWindow);
-		SetPixel(dcScreen, x, y, color);
-		SetPixel(dcBuffer, x, y, color);
-		ReleaseDC(winRootWindow, dcScreen);
+		WaitForSingleObject(drawMutex, INFINITE);
+		SetPixel(priv->dcBuffer, x, y, color);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			{
+				RECT	r;
+				r.left = g->p.x; r.right = g->p.x+1;
+				r.top = g->p.y; r.bottom = g->p.y+1;
+				InvalidateRect(priv->hwnd, &r, FALSE);
+			}
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				SetPixel(dc, x, y, color);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
 	}
 #endif
 
 /* ---- Optional Routines ---- */
 
 #if GDISP_HARDWARE_FILLS
-	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
-		HDC			dcScreen;
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		winPriv	*	priv;
 		RECT		rect;
 		HBRUSH		hbr;
 		COLORREF	color;
 
+		priv = g->priv;
 		color = COLOR2BGR(g->p.color);
+		hbr = CreateSolidBrush(color);
+
 		#if GDISP_NEED_CONTROL
 			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
@@ -403,29 +559,34 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			rect.right = rect.left + g->p.cx;
 		#endif
 
-		hbr = CreateSolidBrush(color);
 
-		dcScreen = GetDC(winRootWindow);
-		FillRect(dcScreen, &rect, hbr);
-		FillRect(dcBuffer, &rect, hbr);
-		ReleaseDC(winRootWindow, dcScreen);
+		WaitForSingleObject(drawMutex, INFINITE);
+		FillRect(priv->dcBuffer, &rect, hbr);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			InvalidateRect(priv->hwnd, &rect, FALSE);
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				FillRect(dc, &rect, hbr);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
 
 		DeleteObject(hbr);
 	}
 #endif
 
 #if GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL
-	static pixel_t *rotateimg(GDISPDriver *g, const pixel_t *buffer) {
+	static pixel_t *rotateimg(GDisplay *g, const pixel_t *buffer) {
 		pixel_t	*dstbuf;
 		pixel_t	*dst;
 		const pixel_t	*src;
 		size_t	sz;
 		coord_t	i, j;
 
-		// Shortcut.
-		if (g->g.Orientation == GDISP_ROTATE_0 && g->p.x1 == 0 && g->p.cx == g->p.x2)
-			return (pixel_t *)buffer;
-		
 		// Allocate the destination buffer
 		sz = (size_t)g->p.cx * (size_t)g->p.cy;
 		if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
@@ -433,11 +594,6 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		
 		// Copy the bits we need
 		switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			for(dst = dstbuf, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx)
-				for(i = 0; i < g->p.cx; i++)
-					*dst++ = *src++;
-			break;
 		case GDISP_ROTATE_90:
 			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
 				dst = dstbuf+sz-g->p.cy+j;
@@ -463,16 +619,14 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 	
 #if GDISP_HARDWARE_BITFILLS
-	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
-		BITMAPV4HEADER bmpInfo;
-		HDC			dcScreen;
-		pixel_t	*	buffer;
-		#if GDISP_NEED_CONTROL
-			RECT		rect;
-			pixel_t	*	srcimg;
-		#endif
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
+		winPriv	*		priv;
+		pixel_t	*		buffer;
+		RECT			rect;
+		BITMAPV4HEADER	bmpInfo;
 
 		// Make everything relative to the start of the line
+		priv = g->priv;
 		buffer = g->p.ptr;
 		buffer += g->p.x2*g->p.y1;
 		
@@ -492,13 +646,10 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		bmpInfo.bV4CSType = 0; //LCS_sRGB;
 
 		#if GDISP_NEED_CONTROL
-			bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
-			srcimg = rotateimg(g, buffer);
-			if (!srcimg) return;
-			
 			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
-				bmpInfo.bV4Width = g->p.cx;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
+				bmpInfo.bV4Width = g->p.x2;
 				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
 				rect.top = g->p.y;
 				rect.bottom = rect.top+g->p.cy;
@@ -506,6 +657,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.right = rect.left+g->p.cx;
 				break;
 			case GDISP_ROTATE_90:
+				if (!(buffer = rotateimg(g, buffer))) return;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
 				bmpInfo.bV4Width = g->p.cy;
 				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
 				rect.bottom = g->g.Width - g->p.x;
@@ -514,6 +667,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.right = rect.left+g->p.cy;
 				break;
 			case GDISP_ROTATE_180:
+				if (!(buffer = rotateimg(g, buffer))) return;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
 				bmpInfo.bV4Width = g->p.cx;
 				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
 				rect.bottom = g->g.Height-1 - g->p.y;
@@ -522,6 +677,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.left = rect.right-g->p.cx;
 				break;
 			case GDISP_ROTATE_270:
+				if (!(buffer = rotateimg(g, buffer))) return;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
 				bmpInfo.bV4Width = g->p.cy;
 				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
 				rect.top = g->p.x;
@@ -530,58 +687,78 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.left = rect.right-g->p.cy;
 				break;
 			}
-			dcScreen = GetDC(winRootWindow);
-			SetDIBitsToDevice(dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-			SetDIBitsToDevice(dcScreen, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, srcimg, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-			ReleaseDC(winRootWindow, dcScreen);
-			if (srcimg != buffer)
-				free(srcimg);
-			
 		#else
+			bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
 			bmpInfo.bV4Width = g->p.x2;
 			bmpInfo.bV4Height = -g->p.cy; /* top-down image */
-			bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
-			dcScreen = GetDC(winRootWindow);
-			SetDIBitsToDevice(dcBuffer, g->p.x, g->p.y, g->p.cx, g->p.cy, g->p.x1, 0, 0, g->p.cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-			SetDIBitsToDevice(dcScreen, g->p.x, g->p.y, g->p.cx, g->p.cy, g->p.x1, 0, 0, g->p.cy, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-			ReleaseDC(winRootWindow, dcScreen);
+			rect.top = g->p.y;
+			rect.bottom = rect.top+g->p.cy;
+			rect.left = g->p.x;
+			rect.right = rect.left+g->p.cx;
+		#endif
+
+		WaitForSingleObject(drawMutex, INFINITE);
+		SetDIBitsToDevice(priv->dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			InvalidateRect(priv->hwnd, &rect, FALSE);
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				SetDIBitsToDevice(dc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
+
+		#if GDISP_NEED_CONTROL
+			if (buffer != (pixel_t *)g->p.ptr)
+				free(srcimg);
 		#endif
 	}
 #endif
 
 #if GDISP_HARDWARE_PIXELREAD
-	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
+	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		winPriv	*	priv;
 		COLORREF	color;
 
+		priv = g->priv;
+
+		WaitForSingleObject(drawMutex, INFINITE);
 		#if GDISP_NEED_CONTROL
 			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
-				color = GetPixel(dcBuffer, g->p.x, g->p.y);
+				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
 				break;
 			case GDISP_ROTATE_90:
-				color = GetPixel(dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
+				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
 				break;
 			case GDISP_ROTATE_180:
-				color = GetPixel(dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
+				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
 				break;
 			case GDISP_ROTATE_270:
-				color = GetPixel(dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
+				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
 				break;
 			}
 		#else
-			color = GetPixel(dcBuffer, g->p.x, g->p.y);
+			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
 		#endif
+		ReleaseMutex(drawMutex);
 		
 		return BGR2COLOR(color);
 	}
 #endif
 
 #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
-	LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
-		HDC			dcScreen;
+	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
+		winPriv	*	priv;
 		RECT		rect;
 		coord_t		lines;
 		
+		priv = g->priv;
+
 		#if GDISP_NEED_CONTROL
 			switch(GC->g.Orientation) {
 			case GDISP_ROTATE_0:
@@ -611,10 +788,20 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 					rect.top -= lines;
 				}
 				if (g->p.cy >= lines && g->p.cy >= -lines) {
-					dcScreen = GetDC(winRootWindow);
-					ScrollDC(dcBuffer, 0, lines, &rect, 0, 0, 0);
-					ScrollDC(dcScreen, 0, lines, &rect, 0, 0, 0);
-					ReleaseDC(winRootWindow, dcScreen);
+					WaitForSingleObject(drawMutex, INFINITE);
+					ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
+					#if GDISP_WIN32_USE_INDIRECT_UPDATE
+						ReleaseMutex(drawMutex);
+						InvalidateRect(priv->hwnd, &rect, FALSE);
+					#else
+						{
+							HDC		dc;
+							dc = GetDC(priv->hwnd);
+							ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
+							ReleaseDC(priv->hwnd, dc);
+							ReleaseMutex(drawMutex);
+						}
+					#endif
 				}
 				break;
 			case GDISP_ROTATE_270:
@@ -630,10 +817,20 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 					rect.left -= lines;
 				}
 				if (g->p.cy >= lines && g->p.cy >= -lines) {
-					dcScreen = GetDC(winRootWindow);
-					ScrollDC(dcBuffer, lines, 0, &rect, 0, 0, 0);
-					ScrollDC(dcScreen, lines, 0, &rect, 0, 0, 0);
-					ReleaseDC(winRootWindow, dcScreen);
+					WaitForSingleObject(drawMutex, INFINITE);
+					ScrollDC(priv->dcBuffer, lines, 0, &rect, 0, 0, 0);
+					#if GDISP_WIN32_USE_INDIRECT_UPDATE
+						ReleaseMutex(drawMutex);
+						InvalidateRect(priv->hwnd, &rect, FALSE);
+					#else
+						{
+							HDC		dc;
+							dc = GetDC(priv->hwnd);
+							ScrollDC(dc, lines, 0, &rect, 0, 0, 0);
+							ReleaseDC(priv->hwnd, dc);
+							ReleaseMutex(drawMutex);
+						}
+					#endif
 				}
 				break;
 			}
@@ -649,17 +846,27 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				rect.top -= lines;
 			}
 			if (g->p.cy >= lines && g->p.cy >= -lines) {
-				dcScreen = GetDC(winRootWindow);
-				ScrollDC(dcBuffer, 0, lines, &rect, 0, 0, 0);
-				ScrollDC(dcScreen, 0, lines, &rect, 0, 0, 0);
-				ReleaseDC(winRootWindow, dcScreen);
+				WaitForSingleObject(drawMutex, INFINITE);
+				ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
+				#if GDISP_WIN32_USE_INDIRECT_UPDATE
+					ReleaseMutex(drawMutex);
+					InvalidateRect(priv->hwnd, &rect, FALSE);
+				#else
+					{
+						HDC		dc;
+						dc = GetDC(priv->hwnd);
+						ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
+						ReleaseDC(priv->hwnd, dc);
+						ReleaseMutex(drawMutex);
+					}
+				#endif
 			}
 		#endif
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
 		switch(g->p.x) {
 		case GDISP_CONTROL_ORIENTATION:
 			if (g->g.Orientation == (orientation_t)g->p.ptr)
@@ -667,13 +874,13 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 			switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
 				case GDISP_ROTATE_180:
-					g->g.Width = wWidth;
-					g->g.Height = wHeight;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					g->g.Height = GDISP_SCREEN_HEIGHT;
 					break;
 				case GDISP_ROTATE_90:
 				case GDISP_ROTATE_270:
-					g->g.Height = wWidth;
-					g->g.Width = wHeight;
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
 				default:
 					return;
@@ -692,20 +899,38 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #if GINPUT_NEED_MOUSE
 	void ginput_lld_mouse_init(void) {}
 	void ginput_lld_mouse_get_reading(MouseReading *pt) {
-		pt->x = mousex;
-		pt->y = mousey > wHeight ? wHeight : mousey;
-		pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
-		pt->buttons = mousebuttons;
+		GDisplay *g;
+
+		g = GDISP_WIN32;
+		pt->x = g->priv->mousex;
+		pt->y = g->priv->mousey > g->g.Height ? g->g.Height : mousey;
+		pt->z = (g->priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
+		pt->buttons = g->priv->mousebuttons;
 	}
 #endif /* GINPUT_NEED_MOUSE */
 
 #if GINPUT_NEED_TOGGLE
-	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
-		{0,	0xFF, 0x00, 0},
-	};
-	void ginput_lld_toggle_init(const GToggleConfig *ptc) { (void) ptc; }
-	unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) { (void) ptc; return toggles; }
-#endif /* GINPUT_NEED_MOUSE */
+	#if GINPUT_TOGGLE_CONFIG_ENTRIES > GDISP_DRIVER_COUNT_WIN32
+		#error "GDISP Win32: GINPUT_TOGGLE_CONFIG_ENTRIES must not be greater than GDISP_DRIVER_COUNT_WIN32"
+	#endif
+
+	GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES];
+
+	void ginput_lld_toggle_init(const GToggleConfig *ptc) {
+		// Save the associated window struct
+		ptc->id = &GDISP_WIN32[ptc - GInputToggleConfigTable];
+
+		// We have 8 buttons per window.
+		ptc->mask = 0xFF;
+
+		// No inverse or special mode
+		ptc->invert = 0x00;
+		ptc->mode = 0;
+	}
+	unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) {
+		return ((GDisplay *)(ptc->id))->priv->toggles;
+	}
+#endif /* GINPUT_NEED_TOGGLE */
 
 #endif /* GFX_USE_GDISP */
 
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index b8a030ef..5720eaed 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -16,15 +16,12 @@
 #ifndef _GDISP_LLD_CONFIG_H
 #define _GDISP_LLD_CONFIG_H
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
 
 /*===========================================================================*/
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"Win32"
-#define GDISP_DRIVER_STRUCT				GDISP_Win32
-
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_FILLS			TRUE
 #define GDISP_HARDWARE_PIXELREAD		TRUE
@@ -32,7 +29,7 @@
 #define GDISP_HARDWARE_BITFILLS			TRUE
 #define GDISP_HARDWARE_SCROLL			TRUE
 
-#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
+#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/multiple/Win32/ginput_lld_toggle_config.h b/drivers/multiple/Win32/ginput_lld_toggle_config.h
index 2e61d073..dd0c9b5c 100644
--- a/drivers/multiple/Win32/ginput_lld_toggle_config.h
+++ b/drivers/multiple/Win32/ginput_lld_toggle_config.h
@@ -20,9 +20,16 @@
 
 #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
 
-#define GINPUT_TOGGLE_POLL_PERIOD		TIME_INFINITE	// We are interrupt driven (or polled - ether works here)
-#define GINPUT_TOGGLE_NUM_PORTS			8			// The total number of toggle inputs
-#define GINPUT_TOGGLE_CONFIG_ENTRIES	1			// The total number of GToggleConfig entries
+#define GINPUT_TOGGLE_POLL_PERIOD		TIME_INFINITE	// We are interrupt driven (or polled - either works here)
+
+// This driver is unique in that it can support 8 buttons per window across multiple windows.
+// GINPUT_TOGGLE_CONFIG_ENTRIES just must be less than the number of GDISP windows (GDISP_DRIVER_COUNT_WIN32).
+#ifndef GINPUT_TOGGLE_CONFIG_ENTRIES
+	#define GINPUT_TOGGLE_CONFIG_ENTRIES	1			// The total number of GToggleConfig entries
+#endif
+
+// The total number of toggle inputs
+#define GINPUT_TOGGLE_NUM_PORTS		(8 * GINPUT_TOGGLE_CONFIG_ENTRIES)
 
 #define GINPUT_TOGGLE_SW1			0				// Switch 1	- Toggle
 #define GINPUT_TOGGLE_SW2			1				// Switch 2	- Toggle
@@ -33,6 +40,8 @@
 #define GINPUT_TOGGLE_MOMENTARY2	5				// Switch 6	- Momentary
 #define GINPUT_TOGGLE_MOMENTARY3	6				// Switch 7	- Momentary
 #define GINPUT_TOGGLE_MOMENTARY4	7				// Switch 8	- Momentary
+
+// This pattern of switch and momentary action is repeated across all windows.
 
 #endif	/* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */
 
diff --git a/drivers/multiple/X/gdisp_lld_config.h b/drivers/multiple/X/gdisp_lld_config.h
index 0bd76a2c..7c04b1b9 100644
--- a/drivers/multiple/X/gdisp_lld_config.h
+++ b/drivers/multiple/X/gdisp_lld_config.h
@@ -22,7 +22,12 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME			"Linux emulator - X11"
+#ifndef GDISP_DRIVER_COUNT_X11
+	#define GDISP_DRIVER_COUNT_X11	1
+#endif
+#define GDISP_DRIVER_COUNT				GDISP_DRIVER_COUNT_X11
+
+#define GDISP_DRIVER_NAME				"Linux emulator - X11"
 #define GDISP_DRIVER_STRUCT				GDISP_X11
 
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
@@ -32,7 +37,7 @@
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			FALSE
 
-#define GDISP_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
+#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From 75ed6842750ac4c43964604905a8459384dfdb65 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 12 Oct 2013 22:38:12 +1000
Subject: Multiple display update for X11 driver. Untested.

---
 drivers/multiple/X/gdisp_lld.c        | 170 ++++++++++++++++++++--------------
 drivers/multiple/X/gdisp_lld_config.h |   8 --
 2 files changed, 103 insertions(+), 75 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index c60e2085..9478d22a 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -14,7 +14,7 @@
 
 #if GFX_USE_GDISP
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_X11
 #include "gdisp/lld/gdisp_lld.h"
 
 /**
@@ -35,6 +35,8 @@
 	#define GDISP_SCREEN_WIDTH		640
 #endif
 
+#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
+
 #if GINPUT_NEED_MOUSE
 	/* Include mouse support code */
 	#include "ginput/lld/mouse.h"
@@ -45,24 +47,37 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-Display			*dis;
-int				scr;
-Window			win;
-Pixmap			pix;
-XEvent			evt;
-GC 				gc;
-Colormap		cmap;
-XVisualInfo		vis;
-int				depth;
+static bool_t			initdone;
+static Display			*dis;
+static int				scr;
+static XEvent			evt;
+static Colormap			cmap;
+static XVisualInfo		vis;
+static int				depth;
+static XContext			cxt;
 #if GINPUT_NEED_MOUSE
 	coord_t			mousex, mousey;
 	uint16_t		mousebuttons;
 #endif
 
-static void ProcessEvent(void) {
+typedef struct xPriv {
+	Pixmap			pix;
+	GC 				gc;
+	Window			win;
+} xPriv;
+
+static void ProcessEvent(GDisplay *g, xPriv *priv) {
 	switch(evt.type) {
+	case MapNotify:
+		XSelectInput(dis, evt.xmap.window, StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+		g->flags |= GDISP_FLG_READY;
+		break;
+	case UnmapNotify:
+		XCloseDisplay(dis);
+		exit(0);
+		break;
 	case Expose:
-		XCopyArea(dis, pix, win, gc,
+		XCopyArea(dis, pix, evt.xexpose.window, priv->gc,
 			evt.xexpose.x, evt.xexpose.y,
 			evt.xexpose.width, evt.xexpose.height,   
 			evt.xexpose.x, evt.xexpose.y);
@@ -108,13 +123,15 @@ static void ProcessEvent(void) {
 /* this is the X11 thread which keeps track of all events */
 static DECLARE_THREAD_STACK(waXThread, 1024);
 static DECLARE_THREAD_FUNCTION(ThreadX, arg) {
+	GDisplay	*g;
 	(void)arg;
 
 	while(1) {
 		gfxSleepMilliseconds(100);
 		while(XPending(dis)) {
 			XNextEvent(dis, &evt);
-			ProcessEvent();
+			XFindContext(ev.xany.display, ev.xany.window, cxt, (XPointer*)&g);
+			ProcessEvent(g, (xPriv *)g->priv);
 		}
 	}
 	return 0;
@@ -128,50 +145,76 @@ static int FatalXIOError(Display *d) {
 	exit(0);
 }
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 	XSizeHints				*pSH;
 	XSetWindowAttributes	xa;
 	XTextProperty			WindowTitle;
 	char *					WindowTitleText;
-	gfxThreadHandle			hth;
+	xPriv					*priv;
 
-	#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
-		XInitThreads();
-	#endif
+	if (!initdone) {
+		gfxThreadHandle			hth;
 
-	dis = XOpenDisplay(NULL);
-	scr = DefaultScreen(dis);
+		initdone = TRUE;
+		#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
+			XInitThreads();
+		#endif
 
-	#if GDISP_FORCE_24BIT	
-		if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) {
-			fprintf(stderr, "Your display has no TrueColor mode\n");
+		dis = XOpenDisplay(NULL);
+		scr = DefaultScreen(dis);
+		cxt = XUniqueContext();
+		XSetIOErrorHandler(FatalXIOError);
+
+		#if GDISP_FORCE_24BIT
+			if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) {
+				fprintf(stderr, "Your display has no TrueColor mode\n");
+				XCloseDisplay(dis);
+				return FALSE;
+			}
+			cmap = XCreateColormap(dis, RootWindow(dis, scr),
+					vis.visual, AllocNone);
+		#else
+			vis.visual = CopyFromParent;
+			vis.depth = DefaultDepth(dis, scr);
+			cmap = DefaultColormap(dis, scr);
+		#endif
+		fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth);
+
+		if (!(hth = gfxThreadCreate(waXThread, sizeof(waXThread), HIGH_PRIORITY, ThreadX, 0))) {
+			fprintf(stderr, "Cannot start X Thread\n");
 			XCloseDisplay(dis);
-			return FALSE;
+			exit(0);
 		}
-		cmap = XCreateColormap(dis, RootWindow(dis, scr),
-				vis.visual, AllocNone);
-	#else
-		vis.visual = CopyFromParent;
-		vis.depth = DefaultDepth(dis, scr);
-		cmap = DefaultColormap(dis, scr);
-	#endif
-	fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth);
+		#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
+			pthread_detach(hth);
+		#endif
+		gfxThreadClose(hth);
+	}
+
+	g->priv = gfxAlloc(sizeof(xPriv));
+	priv = (xPriv *)g->priv;
 
 	xa.colormap = cmap;
 	xa.border_pixel = 0xFFFFFF;
 	xa.background_pixel = 0x000000;
 	
-	win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16,
+	priv->win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16,
 			GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
 			0, vis.depth, InputOutput, vis.visual,
 			CWBackPixel|CWColormap|CWBorderPixel, &xa);
 	XSync(dis, TRUE);
 	
-	WindowTitleText = "GFX";
-	XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
-	XSetWMName(dis, win, &WindowTitle);
-	XSetWMIconName(dis, win, &WindowTitle);
-	XSync(dis, TRUE);
+	XSaveContext(dis, win, cxt, (XPointer)g);
+
+	{
+		char					buf[132];
+		sprintf(buf, "uGFX - %u", display+1);
+		WindowTitleText = buf;
+		XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
+		XSetWMName(dis, win, &WindowTitle);
+		XSetWMIconName(dis, win, &WindowTitle);
+		XSync(dis, TRUE);
+	}
 			
 	pSH = XAllocSizeHints();
 	pSH->flags = PSize | PMinSize | PMaxSize;
@@ -181,34 +224,22 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	XFree(pSH);
 	XSync(dis, TRUE);
 	
-	pix = XCreatePixmap(dis, win, 
+	priv->pix = XCreatePixmap(dis, win,
 				GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth);
 	XSync(dis, TRUE);
 
-	gc = XCreateGC(dis, win, 0, 0);
+	priv->gc = XCreateGC(dis, win, 0, 0);
 	XSetBackground(dis, gc, BlackPixel(dis, scr));
 	XSync(dis, TRUE);
 
 	XSelectInput(dis, win, StructureNotifyMask);
 	XMapWindow(dis, win);
-	do { XNextEvent(dis, &evt); } while (evt.type != MapNotify);
 
-	/* start the X11 thread */
-	XSetIOErrorHandler(FatalXIOError);
-	XSelectInput(dis, win,
-		ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+	// Wait for the window creation to complete (for safety)
+	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
+		gfxSleepMilliseconds(100);
 
-	if (!(hth = gfxThreadCreate(waXThread, sizeof(waXThread), HIGH_PRIORITY, ThreadX, 0))) {
-		fprintf(stderr, "Cannot start X Thread\n");
-		XCloseDisplay(dis);
-		exit(0);
-	}
-	#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
-		pthread_detach(hth);
-	#endif
-	gfxThreadClose(hth);
-	
-    /* Initialise the GDISP structure to match */
+	/* Initialise the GDISP structure to match */
     g->g.Orientation = GDISP_ROTATE_0;
     g->g.Powermode = powerOn;
     g->g.Backlight = 100;
@@ -220,29 +251,31 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 {
+	xPriv	priv = (xPriv *)g->priv;
 	XColor	col;
 
 	col.red = RED_OF(g->p.color) << 8;
 	col.green = GREEN_OF(g->p.color) << 8;
 	col.blue = BLUE_OF(g->p.color) << 8;
 	XAllocColor(dis, cmap, &col);
-	XSetForeground(dis, gc, col.pixel);
-	XDrawPoint(dis, pix, gc, (int)g->p.x, (int)g->p.y );
-	XDrawPoint(dis, win, gc, (int)g->p.x, (int)g->p.y );
+	XSetForeground(dis, priv->gc, col.pixel);
+	XDrawPoint(dis, priv->pix, priv->gc, (int)g->p.x, (int)g->p.y );
+	XDrawPoint(dis, priv->win, priv->gc, (int)g->p.x, (int)g->p.y );
 	XFlush(dis);
 }
 
 #if GDISP_HARDWARE_FILLS
 	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
+		xPriv	priv = (xPriv *)g->priv;
 		XColor	col;
 
 		col.red = RED_OF(g->p.color) << 8;
 		col.green = GREEN_OF(g->p.color) << 8;
 		col.blue = BLUE_OF(g->p.color) << 8;
 		XAllocColor(dis, cmap, &col);
-		XSetForeground(dis, gc, col.pixel);
-		XFillRectangle(dis, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
-		XFillRectangle(dis, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		XSetForeground(dis, priv->gc, col.pixel);
+		XFillRectangle(dis, priv->pix, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		XFillRectangle(dis, priv->win, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
 		XFlush(dis);
 	}
 #endif
@@ -262,10 +295,11 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 
 #if GDISP_HARDWARE_PIXELREAD
 	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
+		xPriv	priv = (xPriv *)g->priv;
 		XColor	color;
 		XImage *img;
 
-		img = XGetImage (dis, pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
+		img = XGetImage (dis, priv->pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
 		color.pixel = XGetPixel (img, 0, 0);
 		XFree(img);
 		XQueryColor(dis, cmap, &color);
@@ -275,12 +309,14 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 
 #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
 	LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
+		xPriv	priv = (xPriv *)g->priv;
+
 		if (g->p.y1 > 0) {
-			XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
-			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
+			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
+			XCopyArea(dis, priv->pix, priv->win, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
 		} else {
-			XCopyArea(dis, pix, pix, gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
-			XCopyArea(dis, pix, win, gc, g->p.x, g->p.y-g->p.y1, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+			XCopyArea(dis, priv->pix, priv->win, priv->gc, g->p.x, g->p.y-g->p.y1, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
 		}
 	}
 #endif
diff --git a/drivers/multiple/X/gdisp_lld_config.h b/drivers/multiple/X/gdisp_lld_config.h
index 7c04b1b9..b58a3d54 100644
--- a/drivers/multiple/X/gdisp_lld_config.h
+++ b/drivers/multiple/X/gdisp_lld_config.h
@@ -22,14 +22,6 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#ifndef GDISP_DRIVER_COUNT_X11
-	#define GDISP_DRIVER_COUNT_X11	1
-#endif
-#define GDISP_DRIVER_COUNT				GDISP_DRIVER_COUNT_X11
-
-#define GDISP_DRIVER_NAME				"Linux emulator - X11"
-#define GDISP_DRIVER_STRUCT				GDISP_X11
-
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_FILLS			TRUE
 #define GDISP_HARDWARE_BITFILLS			FALSE
-- 
cgit v1.2.3


From 769766aa4ad4d35a8aa94ff5cf2df2b88549d426 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 12 Oct 2013 23:36:27 +1000
Subject: X11 multiple display now tested

---
 drivers/multiple/X/gdisp_lld.c | 41 ++++++++++++++++++++---------------------
 1 file changed, 20 insertions(+), 21 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index 9478d22a..c87308f2 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -53,7 +53,6 @@ static int				scr;
 static XEvent			evt;
 static Colormap			cmap;
 static XVisualInfo		vis;
-static int				depth;
 static XContext			cxt;
 #if GINPUT_NEED_MOUSE
 	coord_t			mousex, mousey;
@@ -77,7 +76,7 @@ static void ProcessEvent(GDisplay *g, xPriv *priv) {
 		exit(0);
 		break;
 	case Expose:
-		XCopyArea(dis, pix, evt.xexpose.window, priv->gc,
+		XCopyArea(dis, priv->pix, evt.xexpose.window, priv->gc,
 			evt.xexpose.x, evt.xexpose.y,
 			evt.xexpose.width, evt.xexpose.height,   
 			evt.xexpose.x, evt.xexpose.y);
@@ -130,7 +129,7 @@ static DECLARE_THREAD_FUNCTION(ThreadX, arg) {
 		gfxSleepMilliseconds(100);
 		while(XPending(dis)) {
 			XNextEvent(dis, &evt);
-			XFindContext(ev.xany.display, ev.xany.window, cxt, (XPointer*)&g);
+			XFindContext(evt.xany.display, evt.xany.window, cxt, (XPointer*)&g);
 			ProcessEvent(g, (xPriv *)g->priv);
 		}
 	}
@@ -204,15 +203,15 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 			CWBackPixel|CWColormap|CWBorderPixel, &xa);
 	XSync(dis, TRUE);
 	
-	XSaveContext(dis, win, cxt, (XPointer)g);
+	XSaveContext(dis, priv->win, cxt, (XPointer)g);
 
 	{
 		char					buf[132];
 		sprintf(buf, "uGFX - %u", display+1);
 		WindowTitleText = buf;
 		XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
-		XSetWMName(dis, win, &WindowTitle);
-		XSetWMIconName(dis, win, &WindowTitle);
+		XSetWMName(dis, priv->win, &WindowTitle);
+		XSetWMIconName(dis, priv->win, &WindowTitle);
 		XSync(dis, TRUE);
 	}
 			
@@ -220,20 +219,20 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 	pSH->flags = PSize | PMinSize | PMaxSize;
 	pSH->min_width = pSH->max_width = pSH->base_width = GDISP_SCREEN_WIDTH;
 	pSH->min_height = pSH->max_height = pSH->base_height = GDISP_SCREEN_HEIGHT;
-	XSetWMNormalHints(dis, win, pSH);
+	XSetWMNormalHints(dis, priv->win, pSH);
 	XFree(pSH);
 	XSync(dis, TRUE);
 	
-	priv->pix = XCreatePixmap(dis, win,
+	priv->pix = XCreatePixmap(dis, priv->win,
 				GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth);
 	XSync(dis, TRUE);
 
-	priv->gc = XCreateGC(dis, win, 0, 0);
-	XSetBackground(dis, gc, BlackPixel(dis, scr));
+	priv->gc = XCreateGC(dis, priv->win, 0, 0);
+	XSetBackground(dis, priv->gc, BlackPixel(dis, scr));
 	XSync(dis, TRUE);
 
-	XSelectInput(dis, win, StructureNotifyMask);
-	XMapWindow(dis, win);
+	XSelectInput(dis, priv->win, StructureNotifyMask);
+	XMapWindow(dis, priv->win);
 
 	// Wait for the window creation to complete (for safety)
 	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
@@ -249,9 +248,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
     return TRUE;
 }
 
-LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
+LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g)
 {
-	xPriv	priv = (xPriv *)g->priv;
+	xPriv *	priv = (xPriv *)g->priv;
 	XColor	col;
 
 	col.red = RED_OF(g->p.color) << 8;
@@ -265,8 +264,8 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 }
 
 #if GDISP_HARDWARE_FILLS
-	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
-		xPriv	priv = (xPriv *)g->priv;
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		xPriv *	priv = (xPriv *)g->priv;
 		XColor	col;
 
 		col.red = RED_OF(g->p.color) << 8;
@@ -281,7 +280,7 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 #endif
 
 #if 0 && GDISP_HARDWARE_BITFILLS
-	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
 		// Start of Bitblit code
 
 		//XImage			bitmap;
@@ -294,8 +293,8 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 #endif
 
 #if GDISP_HARDWARE_PIXELREAD
-	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDISPDriver *g) {
-		xPriv	priv = (xPriv *)g->priv;
+	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		xPriv *	priv = (xPriv *)g->priv;
 		XColor	color;
 		XImage *img;
 
@@ -308,8 +307,8 @@ LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g)
 #endif
 
 #if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
-	LLDSPEC void gdisp_lld_vertical_scroll(GDISPDriver *g) {
-		xPriv	priv = (xPriv *)g->priv;
+	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
+		xPriv *	priv = (xPriv *)g->priv;
 
 		if (g->p.y1 > 0) {
 			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
-- 
cgit v1.2.3


From 86a57349128197f58cf3f103e9adf9c2c348d418 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 16 Oct 2013 01:39:56 +1000
Subject: Multiple controller support can now auto-detect hardware capabilities
 at run-time. Specific hardware support can still be turned off or on via
 macros in gfxconf.h to improve efficiency. Multiple Display demo updated to
 match.

---
 drivers/multiple/Win32/gdisp_lld.c | 1 +
 drivers/multiple/X/gdisp_lld.c     | 1 +
 2 files changed, 2 insertions(+)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 65627e1c..dae92821 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -14,6 +14,7 @@
 #if GFX_USE_GDISP
 
 #define GDISP_DRIVER_VMT			GDISPVMT_Win32
+#include "../drivers/multiple/Win32/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
 
 #include <stdio.h>
diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index c87308f2..fc573c87 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -15,6 +15,7 @@
 #if GFX_USE_GDISP
 
 #define GDISP_DRIVER_VMT			GDISPVMT_X11
+#include "../drivers/multiple/X/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
 
 /**
-- 
cgit v1.2.3


From bc79e65ffa90162111675f8e7d3dbd302011a23c Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 17 Oct 2013 14:55:10 +1000
Subject: Tiday up driver makefiles

---
 drivers/multiple/Win32/gdisp_lld.mk |  5 +----
 drivers/multiple/Win32/readme.txt   | 13 +++++++------
 drivers/multiple/X/gdisp_lld.mk     |  5 +----
 3 files changed, 9 insertions(+), 14 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.mk b/drivers/multiple/Win32/gdisp_lld.mk
index b116088b..081d8dda 100644
--- a/drivers/multiple/Win32/gdisp_lld.mk
+++ b/drivers/multiple/Win32/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC +=	$(GFXLIB)/drivers/multiple/Win32/gdisp_lld.c
-
-# Required include directories
 GFXINC +=	$(GFXLIB)/drivers/multiple/Win32
+GFXSRC +=	$(GFXLIB)/drivers/multiple/Win32/gdisp_lld.c
diff --git a/drivers/multiple/Win32/readme.txt b/drivers/multiple/Win32/readme.txt
index 7ff8546c..353f5a5b 100644
--- a/drivers/multiple/Win32/readme.txt
+++ b/drivers/multiple/Win32/readme.txt
@@ -1,14 +1,15 @@
 To use this driver:
 
-This driver is special in that it implements both the gdisp low level driver
-and a touchscreen driver.
+This driver is special in that it implements both the gdisp low level driver,
+optionally a touchscreen driver, and optionally a toggle driver.
 
 1. Add in your gfxconf.h:
 	a) #define GFX_USE_GDISP			TRUE
-	b) #define GFX_USE_GINPUT			TRUE
-		#define GINPUT_USE_MOUSE		TRUE
+	b) Optionally #define GFX_USE_GINPUT			TRUE
+					#define GINPUT_USE_MOUSE		TRUE
+					#define GINPUT_USE_TOGGLE		TRUE
 	c) Any optional high level driver defines (see gdisp.h) eg: GDISP_NEED_MULTITHREAD
-	d) All of the following (with appropriate values):
+	d) Optionally the following (with appropriate values):
 		#define GDISP_SCREEN_WIDTH	640
 		#define GDISP_SCREEN_HEIGHT	480
 
@@ -17,5 +18,5 @@ and a touchscreen driver.
 	include $(GFXLIB)/gfx.mk
 	include $(GFXLIB)/drivers/multiple/Win32/gdisp_lld.mk
 
-3. Modify your makefile to add -lgdi32 to the DLIBS line. i.e.
+3. Modify your makefile to add -lws2_32 and -lgdi32 to the DLIBS line. i.e.
 	DLIBS = -lws2_32 -lgdi32
diff --git a/drivers/multiple/X/gdisp_lld.mk b/drivers/multiple/X/gdisp_lld.mk
index 1a4fc4d7..e7b9daef 100644
--- a/drivers/multiple/X/gdisp_lld.mk
+++ b/drivers/multiple/X/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/multiple/X/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/multiple/X
+GFXSRC += $(GFXLIB)/drivers/multiple/X/gdisp_lld.c
-- 
cgit v1.2.3


From e1744e59ab70ced14a76ff133c50504f8e2a68af Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 17 Oct 2013 14:57:47 +1000
Subject: SSD1289 driver updated for multiple display support

---
 .../SSD1289/board_SSD1289_firebullstm32f103.h      | 107 +++++++++
 .../gdisp/SSD1289/board_SSD1289_stm32f4discovery.h | 169 +++++++++++++
 drivers/gdisp/SSD1289/board_SSD1289_template.h     | 172 +++++++++++++
 drivers/gdisp/SSD1289/gdisp_lld.c                  | 266 +++++++++++----------
 drivers/gdisp/SSD1289/gdisp_lld.mk                 |   5 +-
 .../SSD1289/gdisp_lld_board_firebullstm32f103.h    | 156 ------------
 .../SSD1289/gdisp_lld_board_st_stm32f4_discovery.h | 215 -----------------
 drivers/gdisp/SSD1289/gdisp_lld_board_template.h   | 141 -----------
 drivers/gdisp/SSD1289/gdisp_lld_config.h           |   3 -
 9 files changed, 584 insertions(+), 650 deletions(-)
 create mode 100644 drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
 create mode 100644 drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
 create mode 100644 drivers/gdisp/SSD1289/board_SSD1289_template.h
 delete mode 100644 drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
 delete mode 100644 drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
 delete mode 100644 drivers/gdisp/SSD1289/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
new file mode 100644
index 00000000..fb541df5
--- /dev/null
+++ b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
@@ -0,0 +1,107 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define SET_CS		palSetPad(GPIOD, 12);
+#define CLR_CS		palClearPad(GPIOD, 12);
+#define SET_RS		palSetPad(GPIOD, 13);
+#define CLR_RS		palClearPad(GPIOD, 13);
+#define SET_WR		palSetPad(GPIOD, 14);
+#define CLR_WR		palClearPad(GPIOD, 14);
+#define SET_RD		palSetPad(GPIOD, 15);
+#define CLR_RD		palClearPad(GPIOD, 15);
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+		palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
+
+		// Configure the pins to a well know state
+		SET_RS;
+		SET_RD;
+		SET_WR;
+		CLR_CS;
+	}
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+	/* Nothing to do here - reset pin tied to Vcc */
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+	/* Nothing to do here - Backlight always on */
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	palWritePort(GPIOE, index);
+	CLR_RS; CLR_WR; SET_WR; SET_RS;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	palWritePort(GPIOE, data);
+	CLR_WR; SET_WR;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+	// change pin mode to digital input
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
+	CLR_RD;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+	// change pin mode back to digital output
+	SET_RD;
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	return palReadPort(GPIOE);
+}
+#endif
+
+#if defined(GDISP_USE_DMA)
+	#error "GDISP - SSD1289: The GPIO interface does not support DMA"
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
new file mode 100644
index 00000000..5a44e631
--- /dev/null
+++ b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
@@ -0,0 +1,169 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define GDISP_REG              ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
+#define GDISP_RAM              ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
+#define GDISP_DMA_STREAM		STM32_DMA2_STREAM6
+#define FSMC_BANK				0
+
+/* PWM configuration structure. We use timer 3 channel 3 */
+static const PWMConfig pwmcfg = {
+  100000,       /* 100 kHz PWM clock frequency. */
+  100,          /* PWM period is 100 cycles. */
+  NULL,
+  {
+   {PWM_OUTPUT_DISABLED, NULL},
+   {PWM_OUTPUT_DISABLED, NULL},
+   {PWM_OUTPUT_ACTIVE_HIGH, NULL},
+   {PWM_OUTPUT_DISABLED, NULL}
+  },
+  0
+};
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 *
+		 * Performs the following functions:
+		 *		1. initialise the io port used by the display
+		 *		2. initialise the reset pin (initial state not-in-reset)
+		 *		3. initialise the chip select pin (initial state not-active)
+		 *		4. initialise the backlight pin (initial state back-light off)
+		 */
+
+		#if defined(STM32F1XX) || defined(STM32F3XX)
+			/* FSMC setup for F1/F3 */
+			rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+			#if defined(GDISP_USE_DMA)
+				#error "GDISP: SSD1289 - DMA not implemented for F1/F3 Devices"
+			#endif
+		#elif defined(STM32F4XX) || defined(STM32F2XX)
+			/* STM32F2-F4 FSMC init */
+			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+			#if defined(GDISP_USE_DMA)
+				if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) gfxExit();
+				dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
+				dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+			#else
+				#warning "GDISP: SSD1289 - DMA is supported for F2/F4 Devices. Define GDISP_USE_DMA in your gfxconf.h to turn this on for better performance."
+			#endif
+		#else
+			#error "GDISP: SSD1289 - FSMC not implemented for this device"
+		#endif
+
+		/* set pins to FSMC mode */
+		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+							(1 << 13) | (1 << 14) | (1 << 15), 0};
+
+		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+		/* FSMC timing */
+		FSMC_Bank1->BTCR[FSMC_BANK+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
+
+		/* Bank1 NOR/SRAM control register configuration
+		 * This is actually not needed as already set by default after reset */
+		FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+
+		/* Display backlight control */
+		/* TIM3 is an alternate function 2 (AF2) */
+		pwmStart(&PWMD3, &pwmcfg);
+		palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATE(2));
+		pwmEnableChannel(&PWMD3, 2, 100);
+	}
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+    pwmEnableChannel(&PWMD3, 2, percent);
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+	FSMC_Bank1->BTCR[FSMC_BANK+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+	FSMC_Bank1->BTCR[FSMC_BANK+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return GDISP_RAM;
+}
+
+#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
+	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+		dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+		dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		for (; area > 0; area -= 65535) {
+			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
+			dmaStreamEnable(GDISP_DMA_STREAM);
+			dmaWaitCompletion(GDISP_DMA_STREAM);
+		}
+	}
+
+	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+        dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+        dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		for (; area > 0; area -= 65535) {
+			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
+			dmaStreamEnable(GDISP_DMA_STREAM);
+			dmaWaitCompletion(GDISP_DMA_STREAM);
+		}
+	}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_template.h b/drivers/gdisp/SSD1289/board_SSD1289_template.h
new file mode 100644
index 00000000..552c93a0
--- /dev/null
+++ b/drivers/gdisp/SSD1289/board_SSD1289_template.h
@@ -0,0 +1,172 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1289/board_SSD1289_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] display	The display number on this controller (0..n)
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g, unsigned display) {
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @note	The chip select may need to be asserted/de-asserted
+ * 			around the actual spi read
+ * 
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+
+}
+
+/**
+ * The below section you can replace with #error if your interface doesn't support DMA
+ */
+#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
+	//#error "GDISP - SSD1289: This interface does not support DMA"
+
+	/**
+	 * @brief	Transfer data using DMA but don't increment the source address
+	 *
+	 * @param[in] g				The GDisplay structure
+	 * @param[in] buffer		The source buffer location
+	 * @param[in] area			The number of pixels to transfer
+	 *
+	 * @notapi
+	 */
+	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
+	}
+
+	/**
+	 * @brief	Transfer data using DMA incrementing the source address
+	 *
+	 * @param[in] g				The GDisplay structure
+	 * @param[in] buffer		The source buffer location
+	 * @param[in] area			The number of pixels to transfer
+	 *
+	 * @notapi
+	 */
+	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
+	}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 09122d2f..3779578d 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -14,9 +14,11 @@
 
 #if GFX_USE_GDISP
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1289
+#include "../drivers/gdisp/SSD1289/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_SSD1289.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -40,32 +42,37 @@
 /*===========================================================================*/
 
 // Some common routines and macros
-#define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
-#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
+#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
 
-static void set_cursor(GDISPDriver *g) {
+static void set_cursor(GDisplay *g) {
+	/*
+	 * Reg 0x004E is an 8 bit value - start x position
+	 * Reg 0x004F is 9 bit - start y position
+	 * Use a bit mask to make sure they are not set too high
+	 */
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
-			write_reg(0x004e, g->p.x & 0x00FF);
-			write_reg(0x004f, g->p.y & 0x01FF);
+			write_reg(g, 0x4e, g->p.x & 0x00FF);
+			write_reg(g, 0x4f, g->p.y & 0x01FF);
 			break;
 		case GDISP_ROTATE_90:
-			write_reg(0x004e, g->p.y & 0x00FF);
-			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
+			write_reg(g, 0x4e, g->p.y & 0x00FF);
+			write_reg(g, 0x4f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
-			write_reg(0x004f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
+			write_reg(g, 0x4e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
+			write_reg(g, 0x4f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(0x004e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
-			write_reg(0x004f, g->p.x & 0x01FF);
+			write_reg(g, 0x4e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
+			write_reg(g, 0x4f, g->p.x & 0x01FF);
 			break;
 	}
-	write_index(0x0022);
+	write_index(g, 0x22);
 }
 
-static void set_viewport(GDISPDriver* g) {
+static void set_viewport(GDisplay* g) {
 	/* Reg 0x44 - Horizontal RAM address position
 	 * 		Upper Byte - HEA
 	 * 		Lower Byte - HSA
@@ -73,31 +80,28 @@ static void set_viewport(GDISPDriver* g) {
 	 * Reg 0x45,0x46 - Vertical RAM address position
 	 * 		Lower 9 bits gives 0-511 range in each value
 	 * 		0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
-	 * Reg 0x004E is an 8 bit value - start x position
-	 * Reg 0x004F is 9 bit - start y position
 	 * Use a bit mask to make sure they are not set too high
 	 */
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
-			write_reg(0x44, (((g->p.x+g->p.cx-1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
-			write_reg(0x45, g->p.y & 0x01FF);
-			write_reg(0x46, (g->p.y+g->p.cy-1) & 0x01FF);
+			write_reg(g, 0x44, (((g->p.x+g->p.cx-1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+			write_reg(g, 0x45, g->p.y & 0x01FF);
+			write_reg(g, 0x46, (g->p.y+g->p.cy-1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_90:
-			write_reg(0x44, (((g->p.y+g->p.cy-1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
-			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.x+g->p.cx)) & 0x01FF);
-			write_reg(0x46, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
+			write_reg(g, 0x44, (((g->p.y+g->p.cy-1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
+			write_reg(g, 0x45, (GDISP_SCREEN_HEIGHT-(g->p.x+g->p.cx)) & 0x01FF);
+			write_reg(g, 0x46, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(0x44, (((GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
-			write_reg(0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
-			write_reg(0x46, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
+			write_reg(g, 0x44, (((GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
+			write_reg(g, 0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
+			write_reg(g, 0x46, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
-			write_reg(0x44, (((GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH-(g->p.y+g->p.cy)) & 0x00FF));
-			write_reg(0x45, g->p.x & 0x01FF);
-			write_reg(0x46, (g->p.x+g->p.cx-1) & 0x01FF);
+			write_reg(g, 0x44, (((GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH-(g->p.y+g->p.cy)) & 0x00FF));
+			write_reg(g, 0x45, g->p.x & 0x01FF);
+			write_reg(g, 0x46, (g->p.x+g->p.cx-1) & 0x01FF);
 			break;
 	}
 }
@@ -110,66 +114,66 @@ static void set_viewport(GDISPDriver* g) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 	/* Initialise your display */
-	init_board();
+	init_board(g, display);
 
 	// Hardware reset
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	gfxSleepMilliseconds(20);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	gfxSleepMilliseconds(20);
 
 	// Get the bus for the following initialisation commands
-	acquire_bus();
+	acquire_bus(g);
 	
-	write_reg(0x0000,0x0001);		gfxSleepMicroseconds(5);
-	write_reg(0x0003,0xA8A4);    	gfxSleepMicroseconds(5);
-	write_reg(0x000C,0x0000);    	gfxSleepMicroseconds(5);
-	write_reg(0x000D,0x080C);    	gfxSleepMicroseconds(5);
-    write_reg(0x000E,0x2B00);    	gfxSleepMicroseconds(5);
-    write_reg(0x001E,0x00B0);    	gfxSleepMicroseconds(5);
-	write_reg(0x0001,0x2B3F);		gfxSleepMicroseconds(5);
-    write_reg(0x0002,0x0600);    	gfxSleepMicroseconds(5);
-    write_reg(0x0010,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0011,0x6070);    	gfxSleepMicroseconds(5);
-    write_reg(0x0005,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0006,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0016,0xEF1C);    	gfxSleepMicroseconds(5);
-    write_reg(0x0017,0x0003);    	gfxSleepMicroseconds(5);
-    write_reg(0x0007,0x0133);    	gfxSleepMicroseconds(5);
-    write_reg(0x000B,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x000F,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0041,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0042,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0048,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0049,0x013F);    	gfxSleepMicroseconds(5);
-    write_reg(0x004A,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x004B,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0044,0xEF00);    	gfxSleepMicroseconds(5);
-    write_reg(0x0045,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0046,0x013F);    	gfxSleepMicroseconds(5);
-    write_reg(0x0030,0x0707);    	gfxSleepMicroseconds(5);
-    write_reg(0x0031,0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(0x0032,0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(0x0033,0x0502);    	gfxSleepMicroseconds(5);
-    write_reg(0x0034,0x0507);    	gfxSleepMicroseconds(5);
-    write_reg(0x0035,0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(0x0036,0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(0x0037,0x0502);    	gfxSleepMicroseconds(5);
-    write_reg(0x003A,0x0302);    	gfxSleepMicroseconds(5);
-    write_reg(0x003B,0x0302);    	gfxSleepMicroseconds(5);
-    write_reg(0x0023,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0024,0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(0x0025,0x8000);    	gfxSleepMicroseconds(5);
-    write_reg(0x004f,0x0000);		gfxSleepMicroseconds(5);
-    write_reg(0x004e,0x0000);		gfxSleepMicroseconds(5);
+	write_reg(g, 0x00, 0x0001);		gfxSleepMicroseconds(5);
+	write_reg(g, 0x03, 0xA8A4);    	gfxSleepMicroseconds(5);
+	write_reg(g, 0x0C, 0x0000);    	gfxSleepMicroseconds(5);
+	write_reg(g, 0x0D, 0x080C);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x0E, 0x2B00);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x1E, 0x00B0);    	gfxSleepMicroseconds(5);
+	write_reg(g, 0x01, 0x2B3F);		gfxSleepMicroseconds(5);
+    write_reg(g, 0x02, 0x0600);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x10, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x11, 0x6070);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x05, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x06, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x16, 0xEF1C);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x17, 0x0003);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x07, 0x0133);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x0B, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x0F, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x41, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x42, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x48, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x49, 0x013F);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x4A, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x4B, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x44, 0xEF00);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x45, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x46, 0x013F);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x30, 0x0707);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x31, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x32, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x33, 0x0502);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x34, 0x0507);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x35, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x36, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x37, 0x0502);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x3A, 0x0302);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x3B, 0x0302);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x23, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x24, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x25, 0x8000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x4f, 0x0000);		gfxSleepMicroseconds(5);
+    write_reg(g, 0x4e, 0x0000);		gfxSleepMicroseconds(5);
 
  	// Release the bus
-	release_bus();
+	release_bus(g);
 	
 	/* Turn on the back-light */
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
    /* Initialise the GDISP structure */
 	g->g.Width = GDISP_SCREEN_WIDTH;
@@ -182,94 +186,94 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
-		write_data(g->p.color);
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
 	}
-	LLDSPEC void gdisp_lld_stream_pos(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
 		set_cursor(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
-		setreadmode();
-		dummy_read();
+		setreadmode(g);
+		dummy_read(g);
 	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
-		return read_data();
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
 	}
-	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
-		setwritemode();
-		release_bus();
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
-	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
-		dma_with_noinc(&color, g->p.cx*g->p.cy)
-		release_bus();
+		dma_with_noinc(g, &color, g->p.cx*g->p.cy)
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
-	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
 		pixel_t		*buffer;
 		coord_t		ycnt;
 
 		buffer = (pixel_t *)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
 
-		acquire_bus();
+		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
 		if (g->p.x2 == g->p.cx) {
-			dma_with_inc(buffer, g->p.cx*g->p.cy);
+			dma_with_inc(g, buffer, g->p.cx*g->p.cy);
 		} else {
 			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
-				dma_with_inc(buffer, g->p.cy);
+				dma_with_inc(g, buffer, g->p.cy);
 		}
-		release_bus();
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	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();
-				write_reg(0x0010, 0x0000);	// leave sleep mode
-				write_reg(0x0007, 0x0000);	// halt operation
-				write_reg(0x0000, 0x0000);	// turn off oscillator
-				write_reg(0x0010, 0x0001);	// enter sleep mode
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0000);	// leave sleep mode
+				write_reg(g, 0x07, 0x0000);	// halt operation
+				write_reg(g, 0x00, 0x0000);	// turn off oscillator
+				write_reg(g, 0x10, 0x0001);	// enter sleep mode
+				release_bus(g);
 				break;
 			case powerOn:
-				acquire_bus();
-				write_reg(0x0010, 0x0000);	// leave sleep mode
-				release_bus();
-				if (g->g.Powermode != powerSleep)
-					gdisp_lld_init();
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0000);	// leave sleep mode
+				write_reg(g, 0x00, 0x0001);	// turn on oscillator
+				gfxSleepMicroseconds(5);
+				release_bus(g);
 				break;
 			case powerSleep:
-				acquire_bus();
-				write_reg(0x0010, 0x0001);	// enter sleep mode
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0001);	// enter sleep mode
+				release_bus(g);
 				break;
 			default:
 				return;
@@ -282,34 +286,34 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				return;
 			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
-				acquire_bus();
+				acquire_bus(g);
 				/* ID = 11 AM = 0 */
-				write_reg(0x0011, 0x6070);
-				release_bus();
+				write_reg(g, 0x11, 0x6070);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_90:
-				acquire_bus();
+				acquire_bus(g);
 				/* ID = 01 AM = 1 */
-				write_reg(0x0011, 0x6058);
-				release_bus();
+				write_reg(0x11, 0x6058);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
-				acquire_bus();
+				acquire_bus(g);
 				/* ID = 00 AM = 0 */
-				write_reg(0x0011, 0x6040);
-				release_bus();
+				write_reg(0x11, 0x6040);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
-				acquire_bus();
+				acquire_bus(g);
 				/* ID = 10 AM = 1 */
-				write_reg(0x0011, 0x6068);
-				release_bus();
+				write_reg(g, 0x11, 0x6068);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
@@ -322,7 +326,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
         case GDISP_CONTROL_BACKLIGHT:
             if ((unsigned)g->p.ptr > 100)
             	g->p.ptr = (void *)100;
-            set_backlight((unsigned)g->p.ptr);
+            set_backlight(g, (unsigned)g->p.ptr);
             g->g.Backlight = (unsigned)g->p.ptr;
             return;
 
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.mk b/drivers/gdisp/SSD1289/gdisp_lld.mk
index e340a7dc..564610eb 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.mk
+++ b/drivers/gdisp/SSD1289/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1289/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/SSD1289
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1289/gdisp_lld.c
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h b/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
deleted file mode 100644
index e55e7cd1..00000000
--- a/drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1289/gdisp_lld_board_firebullstm32f103.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#define SET_CS		palSetPad(GPIOD, 12);
-#define CLR_CS		palClearPad(GPIOD, 12);
-#define SET_RS		palSetPad(GPIOD, 13);
-#define CLR_RS		palClearPad(GPIOD, 13);
-#define SET_WR		palSetPad(GPIOD, 14);
-#define CLR_WR		palClearPad(GPIOD, 14);
-#define SET_RD		palSetPad(GPIOD, 15);
-#define CLR_RD		palClearPad(GPIOD, 15);
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- *
- * @notapi
- */
-static inline void init_board(void) {
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
-	
-	// Configure the pins to a well know state
-	SET_RS;
-	SET_RD;
-	SET_WR;
-	CLR_CS;
-}
-
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	(void) state;
-	/* Nothing to do here - reset pin tied to Vcc */
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	(void) percent;
-	/* Nothing to do here - Backlight always on */
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-	palWritePort(GPIOE, index);
-	CLR_RS; CLR_WR; SET_WR; SET_RS;
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	palWritePort(GPIOE, data);
-	CLR_WR; SET_WR;
-}
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-	CLR_RD;
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-	// change pin mode back to digital output
-	SET_RD;
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	return palReadPort(GPIOE);
-}
-#endif
-
-#if defined(GDISP_USE_DMA)
-	#error "GDISP - SSD1289: The GPIO interface does not support DMA"
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h b/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
deleted file mode 100644
index 7097347b..00000000
--- a/drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1289/gdisp_lld_board_st_stm32f4_discovery.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#define GDISP_REG              ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
-#define GDISP_RAM              ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
-#define GDISP_DMA_STREAM		STM32_DMA2_STREAM6
-
-const unsigned char FSMC_Bank = 0;
-
-/* PWM configuration structure. We use timer 3 channel 3 */
-static const PWMConfig pwmcfg = {
-  100000,       /* 100 kHz PWM clock frequency. */
-  100,          /* PWM period is 100 cycles. */
-  NULL,
-  {
-   {PWM_OUTPUT_DISABLED, NULL},
-   {PWM_OUTPUT_DISABLED, NULL},
-   {PWM_OUTPUT_ACTIVE_HIGH, NULL},
-   {PWM_OUTPUT_DISABLED, NULL}
-  },
-  0
-};
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the io port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-	#if defined(STM32F1XX) || defined(STM32F3XX)
-		/* FSMC setup for F1/F3 */
-		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA)
-			#error "GDISP: SSD1289 - DMA not implemented for F1/F3 Devices"
-		#endif
-	#elif defined(STM32F4XX) || defined(STM32F2XX)
-		/* STM32F2-F4 FSMC init */
-		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA)
-			if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) gfxExit();
-			dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		#else
-			#warning "GDISP: SSD1289 - DMA is supported for F2/F4 Devices. Define GDISP_USE_DMA in your gfxconf.h to turn this on for better performance."
-		#endif
-	#else
-		#error "GDISP: SSD1289 - FSMC not implemented for this device"
-	#endif
-
-	/* set pins to FSMC mode */
-	IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-							(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-	IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-						(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-	palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-	palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-	/* FSMC timing */
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-
-	/* Bank1 NOR/SRAM control register configuration
-	 * This is actually not needed as already set by default after reset */
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-
-	/* Display backlight control */
-	/* TIM3 is an alternate function 2 (AF2) */
-	pwmStart(&PWMD3, &pwmcfg);
-	palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATE(2));
-	pwmEnableChannel(&PWMD3, 2, 100);
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	(void) state;
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent       0 to 100%
- *
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-    pwmEnableChannel(&PWMD3, 2, percent);
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) { GDISP_REG = index; }
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) { GDISP_RAM = data; }
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- *
- * @notapi
- */
-static inline uint16_t read_data(void) { return GDISP_RAM; }
-
-#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
-	/**
-	 * @brief	Transfer data using DMA but don't increment the source address
-	 */
-	static inline dma_with_noinc(color_t *buffer, int area) {
-		dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-		dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		for (; area > 0; area -= 65535) {
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		}
-	}
-
-	/**
-	 * @brief	Transfer data using DMA incrementing the source address
-	 */
-	static inline dma_with_inc(color_t *buffer, int area) {
-        dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-        dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		for (; area > 0; area -= 65535) {
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		}
-	}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_board_template.h b/drivers/gdisp/SSD1289/gdisp_lld_board_template.h
deleted file mode 100644
index 8b55bed3..00000000
--- a/drivers/gdisp/SSD1289/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1289/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Initialise the board for the display.
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-
-/**
- * The below section you can replace with #error if your interface doesn't support DMA
- */
-#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
-	//#error "GDISP - SSD1289: This interface does not support DMA"
-
-	/**
-	 * @brief	Transfer data using DMA but don't increment the source address
-	 */
-	static inline dma_with_noinc(color_t *buffer, int area) {
-	}
-
-	/**
-	 * @brief	Transfer data using DMA incrementing the source address
-	 */
-	static inline dma_with_inc(color_t *buffer, int area) {
-	}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index fc04a798..84e518d2 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -22,9 +22,6 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"SSD1289"
-#define GDISP_DRIVER_STRUCT				GDISP_SSD1289
-
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_STREAM_POS		TRUE
-- 
cgit v1.2.3


From 8fb676f73b8f53da4464cf8780dea337c22220f6 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 17 Oct 2013 17:33:04 +1000
Subject: Added a post_init_board() routine to SSD1289 to allow bus timings to
 be changed after controller initialisation is complete.

---
 drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h |  4 ++++
 drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h  |  4 ++++
 drivers/gdisp/SSD1289/board_SSD1289_template.h          | 10 ++++++++++
 drivers/gdisp/SSD1289/gdisp_lld.c                       |  3 +++
 4 files changed, 21 insertions(+)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
index fb541df5..df7594f8 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
@@ -48,6 +48,10 @@ static inline void init_board(GDisplay *g, unsigned display) {
 	}
 }
 
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
 static inline void setpin_reset(GDisplay *g, bool_t state) {
 	(void) g;
 	(void) state;
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
index 5a44e631..84082089 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
@@ -98,6 +98,10 @@ static inline void init_board(GDisplay *g, unsigned display) {
 	}
 }
 
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
 static inline void setpin_reset(GDisplay *g, bool_t state) {
 	(void) g;
 	(void) state;
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_template.h b/drivers/gdisp/SSD1289/board_SSD1289_template.h
index 552c93a0..941950b3 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_template.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_template.h
@@ -30,6 +30,16 @@
 static inline void init_board(GDisplay *g, unsigned display) {
 }
 
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+}
+
 /**
  * @brief   Set or clear the lcd reset pin.
  *
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 3779578d..dca11d5d 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -169,6 +169,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
     write_reg(g, 0x4f, 0x0000);		gfxSleepMicroseconds(5);
     write_reg(g, 0x4e, 0x0000);		gfxSleepMicroseconds(5);
 
+    // Finish Init
+    post_init_board(g);
+
  	// Release the bus
 	release_bus(g);
 	
-- 
cgit v1.2.3


From 8210418402dba694026de4c1945e824a9841fc66 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 17 Oct 2013 17:33:56 +1000
Subject: Driver RA8875 converted to new driver format.

---
 drivers/gdisp/RA8875/board_RA8875_marlin.h      | 102 ++++
 drivers/gdisp/RA8875/board_RA8875_template.h    | 140 ++++++
 drivers/gdisp/RA8875/gdisp_lld.c                | 622 +++++++++---------------
 drivers/gdisp/RA8875/gdisp_lld.mk               |   6 +-
 drivers/gdisp/RA8875/gdisp_lld_board_marlin.h   | 193 --------
 drivers/gdisp/RA8875/gdisp_lld_board_template.h | 119 -----
 drivers/gdisp/RA8875/gdisp_lld_config.h         |  11 +-
 7 files changed, 474 insertions(+), 719 deletions(-)
 create mode 100644 drivers/gdisp/RA8875/board_RA8875_marlin.h
 create mode 100644 drivers/gdisp/RA8875/board_RA8875_template.h
 delete mode 100644 drivers/gdisp/RA8875/gdisp_lld_board_marlin.h
 delete mode 100644 drivers/gdisp/RA8875/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
new file mode 100644
index 00000000..0d675833
--- /dev/null
+++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h
@@ -0,0 +1,102 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/RA8875/gdisp_lld_board_marlin.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the RA8875 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define GDISP_RAM              (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */
+#define GDISP_REG              (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */
+#define FSMC_BANK				4
+
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+
+		/* set pins to FSMC mode */
+		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 8) |
+								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+							(1 << 13) | (1 << 14) | (1 << 15), 0};
+
+		IOBus busG = {GPIOG, (1 << 10), 0};
+
+		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+		palSetBusMode(&busG, PAL_MODE_ALTERNATE(12));
+
+		/* FSMC timing */
+		FSMC_Bank1->BTCR[FSMC_BANK+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
+				| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
+				| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
+
+		/* Bank1 NOR/SRAM control register configuration
+		 * This is actually not needed as already set by default after reset */
+		FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+
+	/* FSMC delay reduced as the controller now runs at full speed */
+	FSMC_Bank1->BTCR[2+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
+	FSMC_Bank1->BTCR[2] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+}
+
+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_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return GDISP_RAM;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/RA8875/board_RA8875_template.h b/drivers/gdisp/RA8875/board_RA8875_template.h
new file mode 100644
index 00000000..f60067f2
--- /dev/null
+++ b/drivers/gdisp/RA8875/board_RA8875_template.h
@@ -0,0 +1,140 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1963/gdisp_lld_board_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] display	The display number on this controller (0..n)
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g, unsigned display) {
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @note	The chip select may need to be asserted/de-asserted
+ * 			around the actual spi read
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
index 397c933a..b8072f51 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ b/drivers/gdisp/RA8875/gdisp_lld.c
@@ -8,22 +8,98 @@
 /**
  * @file    drivers/gdisp/RA8875/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_DRIVER_VMT			GDISPVMT_RA8875
+#include "../drivers/gdisp/RA8875/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+/* include the users board interface */
+#include "board_ra8875.h"
 
-#include "ra8875.h"
+/* include our hardware definitions */
+#include "../drivers/gdisp/RA8875/ra8875.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
 
-/* include the board abstraction */
-#include "gdisp_lld_board.h"
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		272
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		480
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	74
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some common routines and macros
+#define dummy_read(g)					{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg8(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+#define write_reg16(g, reg, data)		{ write_index(g, reg); write_data(g, data); write_index(g, reg+1); write_data(g, (data)>>8); }
+#define write_reg8x2(g, reg, d1, d2)	{ write_index(g, reg); write_data(g, d1); write_data(g, d2); }
+
+static inline void set_cursor(GDisplay *g) {
+	write_reg16(g, 0x46, g->p.x);
+	write_reg16(g, 0x48, g->p.y);
+	write_index(g, RA8875_WRITE_MEMORY_START);
+}
+
+static inline void set_viewport(GDisplay* g) {
+	write_reg16(g, 0x30, g->p.x);				//HSAW0 & HSAW1
+	write_reg16(g, 0x34, g->p.x+g->p.cx-1);		//HEAW0 & HEAW1
+	write_reg16(g, 0x32, g->p.y);				//VSAW0 & VSAW1
+	write_reg16(g, 0x36, g->p.y+g->p.cy-1);		//VEAW0 & VEAW1
+}
+
+// On this controller the back-light is controlled by the controllers internal PWM
+//	which is why it is in this file rather than the board file.
+static inline void set_backlight(GDisplay* g, uint8_t percent) {
+	uint8_t temp;
+
+	//Work in progress: the RA8875 has a built-in PWM, its output can
+	//be used by a Dynamic Background Control or by a host (user)
+
+	// Enable PWM1
+	write_index(g, 0x8a);						//MCLR
+	setreadmode(g);
+	temp = read_data(g);
+	setwritemode(g);
+	temp |= 1<<7 ;
+	write_data(g, temp);
+
+	// PWM1 function select
+	write_index(g, 0x8a);						//MCLR
+	setreadmode(g);
+	temp = read_data(g);
+	setwritemode(g);
+	temp &= ~(1<<4);
+	write_data(g, temp);
+
+	// PWM1 Clock ratio
+	write_index(g, 0x8a);						//MCLR
+	setreadmode(g);
+	temp = read_data(g);
+	setwritemode(g);
+	temp &= 0xf0;
+	temp |= 0x0b & 0x0f;
+	write_data(g, temp);
+
+	// PWM1 Write duty cycle
+	write_reg8(g, 0x8b, 54+percent);			// PTNO: Also change percent to range from 0x00 to 0xFF
+}
 
 /*===========================================================================*/
 /* Driver interrupt handlers.                                                */
@@ -33,417 +109,175 @@
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+	/* Initialise your display */
+	init_board(g, display);
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
 
-/**
- * @brief   Low level GDISP driver initialisation.
- * @return	TRUE if successful, FALSE on error.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
-	/* Initialise the display */
-	init_board();
-
-	/* soft reset */
-	write_index(0x01);
-	write_data(0x01);
-	write_data(0x00);
-	gfxSleepMilliseconds(1);
-
-	/* Driver PLL config 480x272*/
-	write_index(0x88);
-	write_data(0x08);
-	gfxSleepMilliseconds(1);
-	 write_index(0x89);
-	write_data(0x02);
-	gfxSleepMilliseconds(1);
-
-	write_index(0x10);	//SYSR   bit[4:3]=00 256 color  bit[2:1]=  00 8bit MPU interface
-	write_data(0x0F);	// if 16bit MCU interface   and 65k color display
-
-	write_index(0x04);	//set PCLK invers
-	write_data(0x82);
-	gfxSleepMilliseconds(1);
-
-	//Horizontal set
-	write_index(0x14); //HDWR//Horizontal Display Width Setting Bit[6:0]
-	write_data(0x3B);//Horizontal display width(pixels) = (HDWR + 1)*8
-    write_index(0x15); //Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR)
-    write_data(0x00);//Horizontal Non-Display Period Fine Tuning(HNDFT) [3:0]
-    write_index(0x16); //HNDR//Horizontal Non-Display Period Bit[4:0]
-    write_data(0x01);//Horizontal Non-Display Period (pixels) = (HNDR + 1)*8
-    write_index(0x17); //HSTR//HSYNC Start Position[4:0]
-    write_data(0x00);//HSYNC Start Position(PCLK) = (HSTR + 1)*8
-    write_index(0x18); //HPWR//HSYNC Polarity ,The period width of HSYNC.
-    write_data(0x05);//HSYNC Width [4:0]   HSYNC Pulse width(PCLK) = (HPWR + 1)*8
-
-    //Vertical set
-    write_index(0x19); //VDHR0 //Vertical Display Height Bit [7:0]
-    write_data(0x0f); //Vertical pixels = VDHR + 1
-    write_index(0x1a); //VDHR1 //Vertical Display Height Bit [8]
-    write_data(0x01); //Vertical pixels = VDHR + 1
-    write_index(0x1b);  //VNDR0 //Vertical Non-Display Period Bit [7:0]
-    write_data(0x02);  //VSYNC Start Position(PCLK) = (VSTR + 1)
-    write_index(0x1c);  //VNDR1 //Vertical Non-Display Period Bit [8]
-    write_data(0x00); //Vertical Non-Display area = (VNDR + 1)
-    write_index(0x1d); //VSTR0 //VSYNC Start Position[7:0]
-    write_data(0x07);//VSYNC Start Position(PCLK) = (VSTR + 1)
-    write_index(0x1e); //VSTR1 //VSYNC Start Position[8]
-    write_data(0x00);//VSYNC Start Position(PCLK) = (VSTR + 1)
-    write_index(0x1f);    //VPWR //VSYNC Polarity ,VSYNC Pulse Width[6:0]
-    write_data(0x09);   //VSYNC Pulse Width(PCLK) = (VPWR + 1)
-
-	//Active window  set
-	//setting active window X
-    write_index(0x30); //Horizontal Start Point 0 of Active Window (HSAW0)
-    write_data(0x00); //Horizontal Start Point of Active Window [7:0]
-    write_index(0x31); //Horizontal Start Point 1 of Active Window (HSAW1)
-    write_data(0x00); //Horizontal Start Point of Active Window [9:8]
-    write_index(0x34); //Horizontal End Point 0 of Active Window (HEAW0)
-    write_data(0xDF); //Horizontal End Point of Active Window [7:0]
-    write_index(0x35); //Horizontal End Point 1 of Active Window (HEAW1)
-    write_data(0x01); //Horizontal End Point of Active Window [9:8]
-
-	//setting active window Y
-    write_index(0x32); //Vertical Start Point 0 of Active Window (VSAW0)
-    write_data(0x00); //Vertical Start Point of Active Window [7:0]
-    write_index(0x33); //Vertical Start Point 1 of Active Window (VSAW1)
-    write_data(0x00); //Vertical Start Point of Active Window [8]
-    write_index(0x36); //Vertical End Point of Active Window 0 (VEAW0)
-    write_data(0x0F); //Vertical End Point of Active Window [7:0]
-    write_index(0x37); //Vertical End Point of Active Window 1 (VEAW1)
-    write_data(0x01); //Vertical End Point of Active Window [8]
+	// Get the bus for the following initialisation commands
+	acquire_bus(g);
 
-	// Display ON
-	write_index(0x01);	//PWRR
-	write_data(0x80);
+	// Soft reset
+	write_reg8x2(g, 0x01, 0x01, 0x00);	gfxSleepMilliseconds(1);
 
-	// GPO0 DISP high
-	write_index(0x13);	//GPO
-	write_data(0x01);
+	// PLL config
+	write_reg8(g, 0x88, 0x08);			gfxSleepMilliseconds(1);
+	write_reg8(g, 0x89, 0x02);			gfxSleepMilliseconds(1);
 
-	set_backlight(0x80);	//set to 90% brightness
-	
-	post_init_board();
-
-	/* Initialise the GDISP structure to match */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = 100;
-	GDISP.Contrast = 50;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	write_reg8(g, 0x10, 0x0F);			//SYSR   bit[4:3]=00 256 color  bit[2:1]=  00 8bit MPU interface
+										//		 0x0F = 16bit MCU interface and 65k color display
 
-	return TRUE;
-}
+	write_reg8(g, 0x04, 0x82);			gfxSleepMilliseconds(1);	//set PCLK inverse
 
-void gdisp_lld_setwindow(coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
-	/* We don't need to validate here as the LLD routines will validate first.
-	 *
-	 * #if GDISP_NEED_VALIDATION
-	 * 	if (x0 >= GDISP.Width || y0 >= GDISP.Height || x0 < 0 || y0 < 0) return;
-	 * 	else if (x1 >= GDISP.Width || y1 >= GDISP.Height || y1 < 0 || y2 < 0) return;
-	 * #endif
-	*/
-
-	//setting active window X
-	write_index(0x30);	//HSAW0
-	write_data(x0);
-	write_index(0x31);	//HSAW1
-	write_data(x0>>8);
-
-	write_index(0x34);	//HEAW0
-	write_data(x1);
-	write_index(0x35);	//HEAW1
-	write_data(x1>>8);
-
-	//setting active window Y
-	write_index(0x32);	//VSAW0
-	write_data(y0);
-	write_index(0x33);	//VSAW1
-	write_data(y0>>8);
-
-	write_index(0x36);	//VEAW0
-	write_data(y1);
-	write_index(0x37);	//VEAW1
-	write_data(y1>>8);
-
-	write_index(0x46);
-	write_data(x0);
-	write_index(0x47);
-	write_data(x0>>8);
-
-	write_index(0x48);
-	write_data(y0);
-	write_index(0x49);
-	write_data(y0>>8);
-}
+	// Horizontal set
+	write_reg8(g, 0x14, GDISP_SCREEN_WIDTH/8-1);	//HDWR: Horizontal Display Width Setting Bit[6:0] - pixels = (HDWR + 1)*8
+    write_reg8(g, 0x15, 0x00);						//Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR) - HNDFT = [3:0]
+    write_reg8(g, 0x16, 0x01);						//HNDR: Horizontal Non-Display Period Bit[4:0] - pixels = (HNDR + 1)*8
+    write_reg8(g, 0x17, 0x00);						//HSTR: HSYNC Start Position[4:0] - Position(PCLK) = (HSTR + 1)*8
+    write_reg8(g, 0x18, 0x05);						//HPWR: HSYNC Polarity, The period width of HSYNC. Width [4:0] width(PCLK) = (HPWR + 1)*8
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-	if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	
-	gdisp_lld_setwindow(x, y, x, y);
-	write_index(RA8875_WRITE_MEMORY_START);
-	write_data(color);
-}
+    // Vertical set
+    write_reg16(g, 0x19, GDISP_SCREEN_HEIGHT-1);	//VDHR0,1: Vertical Display Height = VDHR + 1
+    write_reg16(g, 0x1b, 0x0002);					//VNDR0,1: Vertical Non-Display Period Bit = (VSTR + 1)
+    write_reg16(g, 0x1d, 0x0007);					//VSTR0,1: VSYNC Start Position = (VSTR + 1)
+    write_reg8(g, 0x1f, 0x09);						//VPWR: VSYNC Polarity, VSYNC Pulse Width[6:0] - Width(PCLK) = (VPWR + 1)
 
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		uint32_t area;
-    
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-		
-		area = cx*cy;
-
-		gdisp_lld_setwindow(x, y, x+cx-1, y+cy-1);
-		write_index(RA8875_WRITE_MEMORY_START);
-
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint8_t i;
-			dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);  
-			for (i = area/65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			}
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			uint32_t index;
-			for(index = 0; index < area; index++)
-				write_data(color);
-		#endif  //#ifdef GDISP_USE_DMA
-}
-#endif
+	// Active window  set
+	write_reg16(g, 0x30, 0);						//HSAW0 & HSAW1
+	write_reg16(g, 0x34, GDISP_SCREEN_WIDTH-1);		//HEAW0 & HEAW1
+	write_reg16(g, 0x32, 0);						//VSAW0 & VSAW1
+	write_reg16(g, 0x36, GDISP_SCREEN_HEIGHT-1);	//VEAW0 & VEAW1
 
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-			
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
+	// Display ON
+	write_reg8(g, 0x01, 0x80);						//PWRR
 
-		gdisp_lld_setwindow(x, y, x+cx-1, y+cy-1);
-		write_index(RA8875_WRITE_MEMORY_START);
-
-		buffer += srcx + srcy * srccx;
-      
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint32_t area = cx*cy;
-			uint8_t i;
-			dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);  
-			for (i = area/65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			} 
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			coord_t endx, endy;
-			uint32_t lg;
-			endx = srcx + cx;
-			endy = y + cy;
-			lg = srccx - cx;
-			for(; y < endy; y++, buffer += lg)
-				for(x=srcx; x < endx; x++)
-					write_data(*buffer++);
-		#endif  //#ifdef GDISP_USE_DMA
-	}
-#endif
+	// GPO0 DISP high
+	write_reg8(g, 0x13, 0x01);						//GPO
 
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-		/* NOT IMPLEMENTED YET */
-		
-		/*
-		uint16_t size = x1 - x0 ;
-
-		write_index(SSD1963_SET_SCROLL_AREA);
-		write_data((x0 >> 8) & 0xFF);
-		write_data((x0 >> 0) & 0xFF);
-		write_data((size >> 8) & 0xFF);
-		write_data((size >> 0) & 0xFF);
-		write_data(((lcd_height-x1) >> 8) & 0xFF);
-		write_data(((lcd_height-x1) >> 0) & 0xFF);
-
-		write_index(SSD1963_SET_SCROLL_START);
-		write_data((lines >> 8) & 0xFF);
-		write_data((lines >> 0) & 0xFF);
-		*/
-	}
+	// Set initial back-light
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 	
+	// Change timings for faster access
+	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);
+		set_viewport(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+		set_cursor(g);
+	}
 #endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		/* NOT IMPLEMENTED YET */
-		switch(what) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
+		#if 0
 			case GDISP_CONTROL_POWER:
-				if (GDISP.Powermode == (gdisp_powermode_t)value)
+				if (g->g.Powermode == (powermode_t)g->p.ptr)
+					return;
+				switch((powermode_t)g->p.ptr) {
+				case powerOff:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				case powerOn:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				case powerSleep:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				default:
 					return;
-				switch((gdisp_powermode_t)value) {
-					case powerOff:
-						/* ToDo */
-						break;
-					case powerOn:
-						/* ToDo */
-						break;
-					case powerSleep:
-						/* ToDo */
-						break;
-					default:
-						return;
 				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
+				g->g.Powermode = (powermode_t)g->p.ptr;
 				return;
+		#endif
+
+		#if 0
 			case GDISP_CONTROL_ORIENTATION:
-				if (GDISP.Orientation == (gdisp_orientation_t)value)
+				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;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-					case GDISP_ROTATE_90:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-					case GDISP_ROTATE_180:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-					case GDISP_ROTATE_270:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-					default:
-						return;
 				}
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-					GDISP.clipx0 = 0;
-					GDISP.clipy0 = 0;
-					GDISP.clipx1 = GDISP.Width;
-					GDISP.clipy1 = GDISP.Height;
-				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
+				g->g.Orientation = (orientation_t)value;
 				return;
-			case GDISP_CONTROL_BACKLIGHT:
-				set_backlight((uint8_t )value);
-				//gdisp_lld_bg_dimmer(54 + ((uint8_t)value) << 1);//turn 0..100% in 54..255
-				return;
-/*
-			case GDISP_CONTROL_CONTRAST:
-*/
+		#endif
+
+        case GDISP_CONTROL_BACKLIGHT:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+			acquire_bus(g);
+            set_backlight(g, (unsigned)g->p.ptr);
+			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/RA8875/gdisp_lld.mk b/drivers/gdisp/RA8875/gdisp_lld.mk
index 471b7e83..7ac03624 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.mk
+++ b/drivers/gdisp/RA8875/gdisp_lld.mk
@@ -1,6 +1,2 @@
-# List the required driver.
-GFXSRC +=	$(GFXLIB)/drivers/gdisp/RA8875/gdisp_lld.c
-
-# Required include directories
 GFXINC +=	$(GFXLIB)/drivers/gdisp/RA8875
-
+GFXSRC +=	$(GFXLIB)/drivers/gdisp/RA8875/gdisp_lld.c
diff --git a/drivers/gdisp/RA8875/gdisp_lld_board_marlin.h b/drivers/gdisp/RA8875/gdisp_lld_board_marlin.h
deleted file mode 100644
index 072ba32e..00000000
--- a/drivers/gdisp/RA8875/gdisp_lld_board_marlin.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/RA8875/gdisp_lld_board_marlin.h
- * @brief   GDISP Graphic Driver subsystem board interface for the RA8875 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/* Using FSMC A16 as RS */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */
-#define GDISP_REG              (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-	GDISP_REG = index;
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return  The data from the lcd
- * @note The chip select may need to be asserted/de-asserted
- *          around the actual spi read
- *
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	return GDISP_RAM;
-}
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the io port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-	const unsigned char FSMC_Bank = 4;
-	
-	#if defined(STM32F1XX) || defined(STM32F3XX)
-		/* FSMC setup for F1/F3 */
-		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			#error "DMA not implemented for F1/F3 Devices"
-		#endif
-	#elif defined(STM32F4XX) || defined(STM32F2XX)
-		/* STM32F2-F4 FSMC init */
-		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) chSysHalt();
-			dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);  
-		#endif
-	#else
-		#error "FSMC not implemented for this device"
-	#endif
-
-	/* set pins to FSMC mode */
-	IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 8) |
-							(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-	IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-						(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-   IOBus busG = {GPIOG, (1 << 10), 0};
-
-	palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-	palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-   palSetBusMode(&busG, PAL_MODE_ALTERNATE(12));
-	
-	/* FSMC timing */
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
-			| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
-			| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
-
-	/* Bank1 NOR/SRAM control register configuration
-	 * This is actually not needed as already set by default after reset */
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-static inline void post_init_board(void) {
-	const unsigned char FSMC_Bank = 2;
-	/* FSMC delay reduced as the controller now runs at full speed */
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	(void) state;
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-	//duty_cycle is 00..FF
-	//Work in progress: the RA8875 has a built-in PWM, its output can
-	//be used by a Dynamic Background Control or by a host (user)
-
-   uint8_t temp, temp1;
-   // Enable PWM1
-   write_index(0x8a);//MCLR
-   temp = read_data();
-   temp |= 1<<7 ;
-   write_data(temp);
-
-   // PWM1 function select
-   write_index(0x8a);//MCLR
-   temp = read_data();
-   temp &= ~(1<<4);
-   write_data(temp);
-
-   // PWM1 Clock ratio
-   temp1= 0x0b&0x0f;
-   write_index(0x8a);//MCLR
-   temp = read_data();
-   temp &= 0xf0;
-   temp |= temp1 ;
-   write_data(temp);
-
-   // Write duty cycle
-   write_index(0x8b);//PTNO
-   write_data(percent);
-   // PWM1 duty cycle
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here */
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/RA8875/gdisp_lld_board_template.h b/drivers/gdisp/RA8875/gdisp_lld_board_template.h
deleted file mode 100644
index a11c11ab..00000000
--- a/drivers/gdisp/RA8875/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-/**
- * @brief   Initialise the board for the display.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	
-}
-
-static inline void post_init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-__inline void write_stream(uint16_t *buffer, uint16_t size) {
-
-}
-
-__inline void read_stream(uint16_t *buffer, size_t size) {
-
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/RA8875/gdisp_lld_config.h b/drivers/gdisp/RA8875/gdisp_lld_config.h
index f49c3e03..ae290245 100644
--- a/drivers/gdisp/RA8875/gdisp_lld_config.h
+++ b/drivers/gdisp/RA8875/gdisp_lld_config.h
@@ -22,14 +22,9 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"RA8875"
-
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILL			TRUE
-#define GDISP_HARDWARE_READPIXEL		TRUE
-
-/* Maybe someday soon */
-#define GDISP_HARDWARE_SCROLL			FALSE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-- 
cgit v1.2.3


From 3cacf9cee22806c6b7c814fdff9ae93dcac1c884 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 17 Oct 2013 17:38:44 +1000
Subject: Remove unnecessary file from RA8875 driver.

---
 drivers/gdisp/RA8875/gdisp_lld.c |  5 +----
 drivers/gdisp/RA8875/ra8875.h    | 18 ------------------
 2 files changed, 1 insertion(+), 22 deletions(-)
 delete mode 100644 drivers/gdisp/RA8875/ra8875.h

(limited to 'drivers')

diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
index b8072f51..4c146321 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ b/drivers/gdisp/RA8875/gdisp_lld.c
@@ -21,9 +21,6 @@
 /* include the users board interface */
 #include "board_ra8875.h"
 
-/* include our hardware definitions */
-#include "../drivers/gdisp/RA8875/ra8875.h"
-
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
@@ -54,7 +51,7 @@
 static inline void set_cursor(GDisplay *g) {
 	write_reg16(g, 0x46, g->p.x);
 	write_reg16(g, 0x48, g->p.y);
-	write_index(g, RA8875_WRITE_MEMORY_START);
+	write_index(g, 0x02);
 }
 
 static inline void set_viewport(GDisplay* g) {
diff --git a/drivers/gdisp/RA8875/ra8875.h b/drivers/gdisp/RA8875/ra8875.h
deleted file mode 100644
index 43210b66..00000000
--- a/drivers/gdisp/RA8875/ra8875.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * 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 RA8875_H
-#define RA8875_H
-
-#define mHIGH(x) (x >> 8)
-#define mLOW(x) (x & 0xFF)
-
-#define RA8875_WRITE_MEMORY_START		0x0002
-#define RA8875_READ_MEMORY_START		0x0002
-
-#endif
-
-- 
cgit v1.2.3


From 257f7364f8722af721e8b4ee10d75839486e8ae1 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 15:56:30 +1000
Subject: Update some doxygen documentation

---
 drivers/gdisp/RA8875/board_RA8875_marlin.h   | 2 +-
 drivers/gdisp/RA8875/board_RA8875_template.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
index 0d675833..95fb7f9d 100644
--- a/drivers/gdisp/RA8875/board_RA8875_marlin.h
+++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h
@@ -6,7 +6,7 @@
  */
 
 /**
- * @file    drivers/gdisp/RA8875/gdisp_lld_board_marlin.h
+ * @file    drivers/gdisp/RA8875/board_RA8875_marlin.h
  * @brief   GDISP Graphic Driver subsystem board interface for the RA8875 display.
  */
 
diff --git a/drivers/gdisp/RA8875/board_RA8875_template.h b/drivers/gdisp/RA8875/board_RA8875_template.h
index f60067f2..564f60c0 100644
--- a/drivers/gdisp/RA8875/board_RA8875_template.h
+++ b/drivers/gdisp/RA8875/board_RA8875_template.h
@@ -6,8 +6,8 @@
  */
 
 /**
- * @file    drivers/gdisp/SSD1963/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
+ * @file    drivers/gdisp/SSD1963/board_RA8875_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the RA8875 display.
  *
  * @addtogroup GDISP
  * @{
-- 
cgit v1.2.3


From c4ae7fd6c830bca85ac7c1c6da6e806dec4accdb Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 15:57:13 +1000
Subject: Convert HX8437D driver to new format

---
 .../gdisp/HX8347D/board_HX8347D_stm32f4discovery.h | 163 +++++++++++++++++
 drivers/gdisp/HX8347D/board_HX8347D_template.h     | 150 +++++++++++++++
 drivers/gdisp/HX8347D/gdisp_lld.c                  | 201 +++++++++++----------
 drivers/gdisp/HX8347D/gdisp_lld.mk                 |   5 +-
 .../HX8347D/gdisp_lld_board_st_stm32f4_discovery.h | 197 --------------------
 drivers/gdisp/HX8347D/gdisp_lld_board_template.h   | 109 -----------
 drivers/gdisp/HX8347D/gdisp_lld_config.h           |   3 -
 7 files changed, 416 insertions(+), 412 deletions(-)
 create mode 100644 drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
 create mode 100644 drivers/gdisp/HX8347D/board_HX8347D_template.h
 delete mode 100644 drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
 delete mode 100644 drivers/gdisp/HX8347D/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
new file mode 100644
index 00000000..0fe5ded3
--- /dev/null
+++ b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
@@ -0,0 +1,163 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
+ * @brief   GDISP Graphic Driver subsystem board SPI interface for the HX8347D display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+
+/* Pin assignments */
+#define SET_RST		palSetPad(GPIOB, 8)
+#define CLR_RST		palClearPad(GPIOB, 8)
+#define SET_DATA	palSetPad(GPIOB, 9)
+#define CLR_DATA	palClearPad(GPIOB, 9)
+#define SET_CS		palSetPad(GPIOA, 4)
+#define CLR_CS		palClearPad(GPIOA, 4)
+
+/* PWM configuration structure. We use timer 4 channel 2 (orange LED on board). */
+static const PWMConfig pwmcfg = {
+	1000000,		/* 1 MHz PWM clock frequency. */
+	100,			/* PWM period is 100 cycles. */
+	NULL,
+	{
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
+	},
+	0
+};
+
+/*
+ * SPI1 configuration structure.
+ * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
+ * The slave select line is the pin 4 on the port GPIOA.
+ */
+static const SPIConfig spi1cfg_8bit = {
+	NULL,
+	/* HW dependent part.*/
+	GPIOA,
+	4,
+	0 //SPI_CR1_BR_0
+};
+
+/*
+ * SPI1 configuration structure.
+ * Speed 42MHz, CPHA=0, CPOL=0, 16bits frames, MSb transmitted first.
+ * The slave select line is the pin 4 on the port GPIOA.
+ */
+static const SPIConfig spi1cfg_16bit = {
+	NULL,
+	/* HW dependent part.*/
+	GPIOA,
+	4,
+	SPI_CR1_DFF //SPI_CR1_BR_0
+};
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+
+		/* Display backlight control */
+		/* TIM4 is an alternate function 2 (AF2) */
+		pwmStart(&PWMD4, &pwmcfg);
+		palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
+		pwmEnableChannel(&PWMD4, 1, 100);
+
+		palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RST    */
+		palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RS     */
+		/*
+		 * Initializes the SPI driver 1. The SPI1 signals are routed as follow:
+		 * PB12 - NSS.
+		 * PB13 - SCK.
+		 * PB14 - MISO.
+		 * PB15 - MOSI.
+		 */
+		SET_CS; SET_DATA;
+		spiStart(&SPID1, &spi1cfg_8bit);
+		palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* NSS.     */
+		palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* SCK.     */
+		palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));										/* MISO.    */
+		palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* MOSI.    */
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if (state) {
+		CLR_RST;
+	} else {
+		SET_RST;
+	}
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	pwmEnableChannel(&PWMD4, 1, percent);
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+	spiAcquireBus(&SPID1);
+    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));		// Safety
+	CLR_CS;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+	SET_CS;
+	spiReleaseBus(&SPID1);
+}
+
+static inline void busmode16(GDisplay *g) {
+	(void) g;
+	spiStart(&SPID1, &spi1cfg_16bit);
+}
+
+static inline void busmode8(GDisplay *g) {
+	(void) g;
+	spiStart(&SPID1, &spi1cfg_8bit);
+}
+
+static inline void write_index(GDisplay *g, uint8_t index) {
+	(void) g;
+    CLR_DATA;
+    SPI1->DR = cmd;
+    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
+    SET_DATA;
+}
+
+static inline void write_data(GDisplay *g, uint8_t data) {
+	(void) g;
+    SPI1->DR = data;
+    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
+}
+
+static inline void write_ram16(GDisplay *g, uint16_t data) {
+	(void) g;
+    SPI1->DR      = data;
+    while((SPI1->SR & SPI_SR_TXE) == 0);
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/HX8347D/board_HX8347D_template.h b/drivers/gdisp/HX8347D/board_HX8347D_template.h
new file mode 100644
index 00000000..6084d1bf
--- /dev/null
+++ b/drivers/gdisp/HX8347D/board_HX8347D_template.h
@@ -0,0 +1,150 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/HX8347D/board_HX8347D_template.h
+ * @brief   GDISP Graphic Driver subsystem board SPI interface for the HX8347D display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] display	The display number on this controller (0..n)
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g, unsigned display) {
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ *
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Set the bus in 16 bit mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void busmode16(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Set the bus in 8 bit mode (the default)
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void busmode8(GDisplay *g) {
+
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint8_t index) {
+
+}
+
+/**
+ * @brief   Send 8 bits of data to the lcd.
+ * @pre		The bus is in 8 bit mode
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint8_t data) {
+
+}
+
+/**
+ * @brief   Send 16 bits of data to the lcd.
+ * @pre		The bus is in 16 bit mode
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_ram16(GDisplay *g, uint16_t data) {
+
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
index a1e2c15b..19d1b822 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.c
+++ b/drivers/gdisp/HX8347D/gdisp_lld.c
@@ -8,18 +8,17 @@
 /**
  * @file    drivers/gdisp/HX8347D/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for the HX8347D display.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_HX8347D
+#include "../drivers/gdisp/HX8347D/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_HX8347D.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -42,106 +41,111 @@
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "HX8347D.h"
-
-static inline void set_viewport(GDISPDriver* g) {
-	write_reg(HX8347D_REG_SCL, (uint8_t) g->p.x);
-	write_reg(HX8347D_REG_SCH, (uint8_t) (g->p.x >> 8));
-	write_reg(HX8347D_REG_ECL, (uint8_t) (g->p.x + g->p.cx -1));
-	write_reg(HX8347D_REG_ECH, (uint8_t) ((g->p.x + g->p.cx -1) >> 8));
-	write_reg(HX8347D_REG_SPL, (uint8_t) g->p.y);
-	write_reg(HX8347D_REG_SPH, (uint8_t) (g->p.y >> 8));
-	write_reg(HX8347D_REG_EPL, (uint8_t) (g->p.y + g->p.cy -1));
-	write_reg(HX8347D_REG_EPH, (uint8_t) ((g->p.y + g->p.cy -1) >> 8));
-	write_index(HX8347D_REG_SRAMWC);
+#include "../drivers/gdisp/HX8347D/HX8347D.h"
+
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+
+static inline void set_viewport(GDisplay* g) {
+	write_reg(g, HX8347D_REG_SCL, g->p.x);
+	write_reg(g, HX8347D_REG_SCH, g->p.x >> 8);
+	write_reg(g, HX8347D_REG_ECL, g->p.x + g->p.cx -1);
+	write_reg(g, HX8347D_REG_ECH, (g->p.x + g->p.cx -1) >> 8);
+	write_reg(g, HX8347D_REG_SPL, g->p.y);
+	write_reg(g, HX8347D_REG_SPH, g->p.y >> 8);
+	write_reg(g, HX8347D_REG_EPL, g->p.y + g->p.cy -1);
+	write_reg(g, HX8347D_REG_EPH, (g->p.y + g->p.cy -1) >> 8);
+	write_index(g, HX8347D_REG_SRAMWC);
 }
 
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 	/* Initialise your display */
-	init_board();
+	init_board(g, display);
 
 	// Hardware reset
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	gfxSleepMilliseconds(1);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	gfxSleepMilliseconds(5);
 
 	// Get the bus for the following initialisation commands
-	acquire_bus();
+	acquire_bus(g);
 
 	/* Start Initial Sequence ----------------------------------------------------*/
-	write_reg(HX8347D_REG_STBAH, 0x00);                 /* Reset Power Control 1                */
-	write_reg(HX8347D_REG_STBAL, 0x20);                 /* Power Control 2                      */
-	write_reg(HX8347D_REG_PTBAH, 0x0C);                 /* Power Control 1                      */
-	write_reg(HX8347D_REG_PTBAL, 0xC4);                 /* Power Control 2                      */
-	write_reg(HX8347D_REG_OPONN, 0x40);                 /* Source OPON_N                        */
-	write_reg(HX8347D_REG_OPONI, 0x38);                 /* Source OPON_I                        */
-	write_reg(HX8347D_REG_DC2, 0xA3);                   /* Display Control 2                    */
+	write_reg(g, HX8347D_REG_STBAH, 0x00);                 /* Reset Power Control 1                */
+	write_reg(g, HX8347D_REG_STBAL, 0x20);                 /* Power Control 2                      */
+	write_reg(g, HX8347D_REG_PTBAH, 0x0C);                 /* Power Control 1                      */
+	write_reg(g, HX8347D_REG_PTBAL, 0xC4);                 /* Power Control 2                      */
+	write_reg(g, HX8347D_REG_OPONN, 0x40);                 /* Source OPON_N                        */
+	write_reg(g, HX8347D_REG_OPONI, 0x38);                 /* Source OPON_I                        */
+	write_reg(g, HX8347D_REG_DC2, 0xA3);                   /* Display Control 2                    */
 
 	/* Power On sequence ---------------------------------------------------------*/
-	write_reg(HX8347D_REG_PWC2, 0x1B);                  /* Power Control 2                      */
-	write_reg(HX8347D_REG_PWC1, 0x01);                  /* Power Control 1                      */
-	write_reg(HX8347D_REG_VMH, 0x2F);                   /* Vcom Control 2                       */
-	write_reg(HX8347D_REG_VML, 0x57);                   /* Vcom Control 3                       */
-	write_reg(HX8347D_REG_VMF, 0x8D);                   /* Vcom Control 1                       */
+	write_reg(g, HX8347D_REG_PWC2, 0x1B);                  /* Power Control 2                      */
+	write_reg(g, HX8347D_REG_PWC1, 0x01);                  /* Power Control 1                      */
+	write_reg(g, HX8347D_REG_VMH, 0x2F);                   /* Vcom Control 2                       */
+	write_reg(g, HX8347D_REG_VML, 0x57);                   /* Vcom Control 3                       */
+	write_reg(g, HX8347D_REG_VMF, 0x8D);                   /* Vcom Control 1                       */
 
 	/* Gamma settings  -----------------------------------------------------------*/
-	write_reg(HX8347D_REG_VRP0,0x01);   //   default setup
-	write_reg(HX8347D_REG_VRP1,0x0e);   //
-	write_reg(HX8347D_REG_VRP2,0x11);   //
-	write_reg(HX8347D_REG_VRP3,0x1a);   //
-	write_reg(HX8347D_REG_VRP4,0x18);   //
-	write_reg(HX8347D_REG_VRP5,0x24);   //
-	write_reg(HX8347D_REG_PRP0,0x15);   //
-	write_reg(HX8347D_REG_PRP1,0x65);   //
-	write_reg(HX8347D_REG_PKP0,0x0b);   //
-	write_reg(HX8347D_REG_PKP1,0x18);   //
-	write_reg(HX8347D_REG_PKP2,0x19);   //
-	write_reg(HX8347D_REG_PKP3,0x1a);   //
-	write_reg(HX8347D_REG_PKP4,0x18);   //
-	write_reg(HX8347D_REG_VRN0,0x1b);   //
-	write_reg(HX8347D_REG_VRN1,0x27);   //
-	write_reg(HX8347D_REG_VRN2,0x25);   //
-	write_reg(HX8347D_REG_VRN3,0x2e);   //
-	write_reg(HX8347D_REG_VRN4,0x31);   //
-	write_reg(HX8347D_REG_VRN5,0x3e);   //
-	write_reg(HX8347D_REG_PRN0,0x1a);   //
-	write_reg(HX8347D_REG_PRN1,0x6a);   //
-	write_reg(HX8347D_REG_PKN0,0x07);   //
-	write_reg(HX8347D_REG_PKN1,0x05);   //
-	write_reg(HX8347D_REG_PKN2,0x06);   //
-	write_reg(HX8347D_REG_PKN3,0x0b);   //
-	write_reg(HX8347D_REG_PKN4,0x14);   //
-	write_reg(HX8347D_REG_CGM,0xcc);    //
+	write_reg(g, HX8347D_REG_VRP0, 0x01);   //   default setup
+	write_reg(g, HX8347D_REG_VRP1, 0x0e);   //
+	write_reg(g, HX8347D_REG_VRP2, 0x11);   //
+	write_reg(g, HX8347D_REG_VRP3, 0x1a);   //
+	write_reg(g, HX8347D_REG_VRP4, 0x18);   //
+	write_reg(g, HX8347D_REG_VRP5, 0x24);   //
+	write_reg(g, HX8347D_REG_PRP0, 0x15);   //
+	write_reg(g, HX8347D_REG_PRP1, 0x65);   //
+	write_reg(g, HX8347D_REG_PKP0, 0x0b);   //
+	write_reg(g, HX8347D_REG_PKP1, 0x18);   //
+	write_reg(g, HX8347D_REG_PKP2, 0x19);   //
+	write_reg(g, HX8347D_REG_PKP3, 0x1a);   //
+	write_reg(g, HX8347D_REG_PKP4, 0x18);   //
+	write_reg(g, HX8347D_REG_VRN0, 0x1b);   //
+	write_reg(g, HX8347D_REG_VRN1, 0x27);   //
+	write_reg(g, HX8347D_REG_VRN2, 0x25);   //
+	write_reg(g, HX8347D_REG_VRN3, 0x2e);   //
+	write_reg(g, HX8347D_REG_VRN4, 0x31);   //
+	write_reg(g, HX8347D_REG_VRN5, 0x3e);   //
+	write_reg(g, HX8347D_REG_PRN0, 0x1a);   //
+	write_reg(g, HX8347D_REG_PRN1, 0x6a);   //
+	write_reg(g, HX8347D_REG_PKN0, 0x07);   //
+	write_reg(g, HX8347D_REG_PKN1, 0x05);   //
+	write_reg(g, HX8347D_REG_PKN2, 0x06);   //
+	write_reg(g, HX8347D_REG_PKN3, 0x0b);   //
+	write_reg(g, HX8347D_REG_PKN4, 0x14);   //
+	write_reg(g, HX8347D_REG_CGM, 0xcc);    //
 
 	/* Power + Osc ---------------------------------------------------------------*/
-	write_reg(HX8347D_REG_OSCCH, 0x36);                  /* OSC Control 1                        */
-	write_reg(HX8347D_REG_OSCCL, 0x01);                  /* OSC Control 2                        */
-	write_reg(HX8347D_REG_DMODE, 0x00);                  /* Display Mode Control                 */
-	write_reg(HX8347D_REG_PWC6, 0x88);                   /* Power Control 6                      */
+	write_reg(g, HX8347D_REG_OSCCH, 0x36);               /* OSC Control 1                        */
+	write_reg(g, HX8347D_REG_OSCCL, 0x01);               /* OSC Control 2                        */
+	write_reg(g, HX8347D_REG_DMODE, 0x00);               /* Display Mode Control                 */
+	write_reg(g, HX8347D_REG_PWC6, 0x88);                /* Power Control 6                      */
 	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(HX8347D_REG_PWC6, 0x80);                   /* Power Control 6                      */
+	write_reg(g, HX8347D_REG_PWC6, 0x80);                /* Power Control 6                      */
 	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(HX8347D_REG_PWC6, 0x90);                   /* Power Control 6                      */
+	write_reg(g, HX8347D_REG_PWC6, 0x90);                /* Power Control 6                      */
 	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(HX8347D_REG_PWC6, 0xD0);                   /* Power Control 6                      */
+	write_reg(g, HX8347D_REG_PWC6, 0xD0);                /* Power Control 6                      */
 	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(HX8347D_REG_COLMOD, 0x05);                 /* Colmod 16Bit/Pixel                   */
-	write_reg(HX8347D_REG_PCH, 0x00);                    /* Panel Characteristic                 */
-	write_reg(HX8347D_REG_DC3, 0x38);                    /* Display Control 3                    */
+	write_reg(g, HX8347D_REG_COLMOD, 0x05);              /* Colmod 16Bit/Pixel                   */
+	write_reg(g, HX8347D_REG_PCH, 0x00);                 /* Panel Characteristic                 */
+	write_reg(g, HX8347D_REG_DC3, 0x38);                 /* Display Control 3                    */
 	gfxSleepMilliseconds(40);                            /* Delay 40 ms                          */
-	write_reg(HX8347D_REG_DC3, 0x3C);                    /* Display Control 3                    */
-	write_reg(HX8347D_REG_MAC, 0x08);                    /* Memory access control                */
+	write_reg(g, HX8347D_REG_DC3, 0x3C);                 /* Display Control 3                    */
+	write_reg(g, HX8347D_REG_MAC, 0x08);                 /* Memory access control                */
+
+    // Finish Init
+    post_init_board(g);
 
  	// Release the bus
-	release_bus();
+	release_bus(g);
 
 	/* Turn on the backlight */
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
 	/* Initialise the GDISP structure */
 	g->g.Width = GDISP_SCREEN_WIDTH;
@@ -154,55 +158,55 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
-		busmode16();
+		busmode16(g);
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
-		write_ram16(g->p.color);
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_ram16(g, g->p.color);
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
-		busmode8();
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		busmode8(g);
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
 		switch(g->p.x) {
 		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();
-					write_reg(HX8347D_REG_MAC, 0x08);                    /* Memory access control */
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0x08);                    /* Memory access control */
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 
 				case GDISP_ROTATE_90:
-					acquire_bus();
-					write_reg(HX8347D_REG_MAC, 0x68);                    /* Memory access control */
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0x68);                    /* Memory access control */
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
 
 				case GDISP_ROTATE_180:
-					acquire_bus();
-					write_reg(HX8347D_REG_MAC, 0xc8);                    /* Memory access control */
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0xc8);                    /* Memory access control */
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 
 				case GDISP_ROTATE_270:
-					acquire_bus();
-					write_reg(HX8347D_REG_MAC, 0xa8);                    /* Memory access control */
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0xa8);                    /* Memory access control */
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
@@ -215,7 +219,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
         case GDISP_CONTROL_BACKLIGHT:
             if ((unsigned)g->p.ptr > 100)
             	g->p.ptr = (void *)100;
-            set_backlight((unsigned)g->p.ptr);
+            set_backlight(g, (unsigned)g->p.ptr);
             g->g.Backlight = (unsigned)g->p.ptr;
             return;
 
@@ -226,4 +230,3 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.mk b/drivers/gdisp/HX8347D/gdisp_lld.mk
index fed905e1..72d9cf75 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.mk
+++ b/drivers/gdisp/HX8347D/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/HX8347D/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/HX8347D
+GFXSRC += $(GFXLIB)/drivers/gdisp/HX8347D/gdisp_lld.c
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h b/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
deleted file mode 100644
index 8365fe74..00000000
--- a/drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/HX8347D/gdisp_lld_board_st_stm32f4_discovery.h
- * @brief   GDISP Graphic Driver subsystem board SPI interface for the HX8347D display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// Overrides
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	50
-#endif
-
-/* Pin assignments */
-#define SET_RST		palSetPad(GPIOB, 8)
-#define CLR_RST		palClearPad(GPIOB, 8)
-#define SET_DATA	palSetPad(GPIOB, 9)
-#define CLR_DATA	palClearPad(GPIOB, 9)
-#define SET_CS		palSetPad(GPIOA, 4)
-#define CLR_CS		palClearPad(GPIOA, 4)
-
-/* PWM configuration structure. We use timer 4 channel 2 (orange LED on board). */
-static const PWMConfig pwmcfg = {
-	1000000,		/* 1 MHz PWM clock frequency. */
-	100,			/* PWM period is 100 cycles. */
-	NULL,
-	{
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
-	},
-	0
-};
-
-/*
- * SPI1 configuration structure.
- * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
- * The slave select line is the pin 4 on the port GPIOA.
- */
-static const SPIConfig spi1cfg_8bit = {
-	NULL,
-	/* HW dependent part.*/
-	GPIOA,
-	4,
-	0 //SPI_CR1_BR_0
-};
-
-/*
- * SPI1 configuration structure.
- * Speed 42MHz, CPHA=0, CPOL=0, 16bits frames, MSb transmitted first.
- * The slave select line is the pin 4 on the port GPIOA.
- */
-static const SPIConfig spi1cfg_16bit = {
-	NULL,
-	/* HW dependent part.*/
-	GPIOA,
-	4,
-	SPI_CR1_DFF //SPI_CR1_BR_0
-};
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	This board definition uses GPIO and SPI. It assumes exclusive access to these GPIO pins but not necessarily the SPI port.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	/* Display backlight control */
-	/* TIM4 is an alternate function 2 (AF2) */
-	pwmStart(&PWMD4, &pwmcfg);
-	palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
-	pwmEnableChannel(&PWMD4, 1, 100);
-
-	palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RST    */
-	palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RS     */
-	/*
-	 * Initializes the SPI driver 1. The SPI1 signals are routed as follow:
-	 * PB12 - NSS.
-	 * PB13 - SCK.
-	 * PB14 - MISO.
-	 * PB15 - MOSI.
-	 */
-	SET_CS; SET_DATA;
-	spiStart(&SPID1, &spi1cfg_8bit);
-	palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* NSS.     */
-	palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* SCK.     */
-	palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));										/* MISO.    */
-	palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* MOSI.    */
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- *
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	if (state) {
-		CLR_RST;
-	} else {
-		SET_RST;
-	}
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- *
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	pwmEnableChannel(&PWMD4, 1, percent);
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @notapi
- */
-static inline void acquire_bus(void) {
-	spiAcquireBus(&SPID1);
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));		// Safety
-	CLR_CS;
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @notapi
- */
-static inline void release_bus(void) {
-	SET_CS;
-	spiReleaseBus(&SPID1);
-}
-
-/**
- * @brief   Set the bus in 16 bit mode
- * @notapi
- */
-static inline void busmode16(void) {
-	spiStart(&SPID1, &spi1cfg_16bit);
-}
-
-/**
- * @brief   Set the bus in 8 bit mode (the default)
- * @notapi
- */
-static inline void busmode8(void) {
-	spiStart(&SPID1, &spi1cfg_8bit);
-}
-
-/**
- * @brief   Set which index register to use.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint8_t cmd) {
-    CLR_DATA;
-    SPI1->DR = cmd;
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-    SET_DATA;
-}
-
-/**
- * @brief   Send a command to the lcd.
- *
- * @param[in] data		The data to send
- *
- * @notapi
- */
-static inline void write_reg(uint8_t cmd, uint8_t data) {
-	write_index(cmd);
-    SPI1->DR = data;
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-}
-
-static inline void write_ram16(uint16_t data) {
-    SPI1->DR      = data;
-    while((SPI1->SR & SPI_SR_TXE) == 0);
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_board_template.h b/drivers/gdisp/HX8347D/gdisp_lld_board_template.h
deleted file mode 100644
index d3b71d97..00000000
--- a/drivers/gdisp/HX8347D/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/HX8347D/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board SPI interface for the HX8347D display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Initialise the board for the display.
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- *
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- *
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Set the bus in 16 bit mode
- * @notapi
- */
-static inline void busmode16(void) {
-
-}
-
-/**
- * @brief   Set the bus in 8 bit mode (the default)
- * @notapi
- */
-static inline void busmode8(void) {
-
-}
-
-/**
- * @brief   Set which index register to use.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint8_t cmd) {
-
-}
-
-/**
- * @brief   Send a command to the lcd.
- *
- * @param[in] data		The data to send
- *
- * @notapi
- */
-static inline void write_reg(uint8_t cmd, uint8_t data) {
-
-}
-
-static inline void write_ram16(uint16_t data) {
-
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_config.h b/drivers/gdisp/HX8347D/gdisp_lld_config.h
index a5a8e2b8..48801f55 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld_config.h
+++ b/drivers/gdisp/HX8347D/gdisp_lld_config.h
@@ -22,9 +22,6 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"HX8347D"
-#define GDISP_DRIVER_STRUCT				GDISP_HX8347D
-
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-- 
cgit v1.2.3


From 66d2d279674852f9c8631e1eb6a82f68b01778c1 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 16:43:09 +1000
Subject: Fix compile error

---
 drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
index 0fe5ded3..4899baa5 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
@@ -143,7 +143,7 @@ static inline void busmode8(GDisplay *g) {
 static inline void write_index(GDisplay *g, uint8_t index) {
 	(void) g;
     CLR_DATA;
-    SPI1->DR = cmd;
+    SPI1->DR = index;
     while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
     SET_DATA;
 }
-- 
cgit v1.2.3


From c9311d9851c28f555a26de8757d7aca9caa255d3 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 16:44:56 +1000
Subject: Changed board_XXXX_template.h so that it can be directly copied to
 board_XXXX.h in the project directory and it will compile with stub
 functions.

---
 drivers/gdisp/HX8347D/board_HX8347D_template.h | 26 +++++++++++++--------
 drivers/gdisp/SSD1289/board_SSD1289_template.h | 32 ++++++++++++++++++--------
 2 files changed, 40 insertions(+), 18 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/board_HX8347D_template.h b/drivers/gdisp/HX8347D/board_HX8347D_template.h
index 6084d1bf..528fb027 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_template.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_template.h
@@ -28,6 +28,8 @@
  * @notapi
  */
 static inline void init_board(GDisplay *g, unsigned display) {
+	(void) g;
+	(void) display;
 }
 
 /**
@@ -38,6 +40,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
  * @notapi
  */
 static inline void post_init_board(GDisplay *g) {
+	(void) g;
 }
 
 /**
@@ -49,7 +52,8 @@ static inline void post_init_board(GDisplay *g) {
  * @notapi
  */
 static inline void setpin_reset(GDisplay *g, bool_t state) {
-
+	(void) g;
+	(void) state;
 }
 
 /**
@@ -61,7 +65,8 @@ static inline void setpin_reset(GDisplay *g, bool_t state) {
  * @notapi
  */
 static inline void set_backlight(GDisplay *g, uint8_t percent) {
-
+	(void) g;
+	(void) percent;
 }
 
 /**
@@ -72,7 +77,7 @@ static inline void set_backlight(GDisplay *g, uint8_t percent) {
  * @notapi
  */
 static inline void acquire_bus(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -83,7 +88,7 @@ static inline void acquire_bus(GDisplay *g) {
  * @notapi
  */
 static inline void release_bus(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -94,7 +99,7 @@ static inline void release_bus(GDisplay *g) {
  * @notapi
  */
 static inline void busmode16(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -105,7 +110,7 @@ static inline void busmode16(GDisplay *g) {
  * @notapi
  */
 static inline void busmode8(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -117,7 +122,8 @@ static inline void busmode8(GDisplay *g) {
  * @notapi
  */
 static inline void write_index(GDisplay *g, uint8_t index) {
-
+	(void) g;
+	(void) index;
 }
 
 /**
@@ -130,7 +136,8 @@ static inline void write_index(GDisplay *g, uint8_t index) {
  * @notapi
  */
 static inline void write_data(GDisplay *g, uint8_t data) {
-
+	(void) g;
+	(void) data;
 }
 
 /**
@@ -143,7 +150,8 @@ static inline void write_data(GDisplay *g, uint8_t data) {
  * @notapi
  */
 static inline void write_ram16(GDisplay *g, uint16_t data) {
-
+	(void) g;
+	(void) data;
 }
 
 #endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_template.h b/drivers/gdisp/SSD1289/board_SSD1289_template.h
index 941950b3..db841c2c 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_template.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_template.h
@@ -28,6 +28,8 @@
  * @notapi
  */
 static inline void init_board(GDisplay *g, unsigned display) {
+	(void) g;
+	(void) display;
 }
 
 /**
@@ -38,6 +40,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
  * @notapi
  */
 static inline void post_init_board(GDisplay *g) {
+	(void) g;
 }
 
 /**
@@ -49,7 +52,8 @@ static inline void post_init_board(GDisplay *g) {
  * @notapi
  */
 static inline void setpin_reset(GDisplay *g, bool_t state) {
-
+	(void) g;
+	(void) state;
 }
 
 /**
@@ -61,7 +65,8 @@ static inline void setpin_reset(GDisplay *g, bool_t state) {
  * @notapi
  */
 static inline void set_backlight(GDisplay *g, uint8_t percent) {
-
+	(void) g;
+	(void) percent;
 }
 
 /**
@@ -72,7 +77,7 @@ static inline void set_backlight(GDisplay *g, uint8_t percent) {
  * @notapi
  */
 static inline void acquire_bus(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -83,7 +88,7 @@ static inline void acquire_bus(GDisplay *g) {
  * @notapi
  */
 static inline void release_bus(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -95,7 +100,8 @@ static inline void release_bus(GDisplay *g) {
  * @notapi
  */
 static inline void write_index(GDisplay *g, uint16_t index) {
-
+	(void) g;
+	(void) index;
 }
 
 /**
@@ -107,7 +113,8 @@ static inline void write_index(GDisplay *g, uint16_t index) {
  * @notapi
  */
 static inline void write_data(GDisplay *g, uint16_t data) {
-
+	(void) g;
+	(void) data;
 }
 
 /**
@@ -118,7 +125,7 @@ static inline void write_data(GDisplay *g, uint16_t data) {
  * @notapi
  */
 static inline void setreadmode(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -129,7 +136,7 @@ static inline void setreadmode(GDisplay *g) {
  * @notapi
  */
 static inline void setwritemode(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -144,7 +151,8 @@ static inline void setwritemode(GDisplay *g) {
  * @notapi
  */
 static inline uint16_t read_data(GDisplay *g) {
-
+	(void) g;
+	return 0;
 }
 
 /**
@@ -163,6 +171,9 @@ static inline uint16_t read_data(GDisplay *g) {
 	 * @notapi
 	 */
 	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+		(void) buffer;
+		(void) area;
 	}
 
 	/**
@@ -175,6 +186,9 @@ static inline uint16_t read_data(GDisplay *g) {
 	 * @notapi
 	 */
 	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+		(void) buffer;
+		(void) area;
 	}
 #endif
 
-- 
cgit v1.2.3


From 9eabf4576df62d87de18a42090e3ae9133a320de Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 16:45:35 +1000
Subject: Convert ILI9320 driver to new format

---
 .../ILI9320/board_ILI9320_olimex_pic32mx_lcd.h     | 129 ++++++++
 .../gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h | 103 +++++++
 drivers/gdisp/ILI9320/board_ILI9320_template.h     | 159 ++++++++++
 drivers/gdisp/ILI9320/gdisp_lld.c                  | 325 +++++++++++----------
 drivers/gdisp/ILI9320/gdisp_lld.mk                 |   5 +-
 .../ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h   | 113 -------
 .../ILI9320/gdisp_lld_board_olimex_stm32_lcd.h     |  86 ------
 drivers/gdisp/ILI9320/gdisp_lld_board_template.h   |  61 ----
 drivers/gdisp/ILI9320/gdisp_lld_config.h           |   3 -
 9 files changed, 558 insertions(+), 426 deletions(-)
 create mode 100644 drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
 create mode 100644 drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
 create mode 100644 drivers/gdisp/ILI9320/board_ILI9320_template.h
 delete mode 100644 drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
 delete mode 100644 drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
 delete mode 100644 drivers/gdisp/ILI9320/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
new file mode 100644
index 00000000..81d493ed
--- /dev/null
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
@@ -0,0 +1,129 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+#ifndef noinline
+#define noinline __attribute__((noinline))
+#endif
+
+static void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+
+		// RST
+		palSetPadMode(IOPORTA, 7, PAL_MODE_OUTPUT);
+		palClearPad(IOPORTA, 7);
+
+		// RS
+		palSetPadMode(IOPORTA, 10, PAL_MODE_OUTPUT);
+		palSetPad(IOPORTA, 10);
+
+		// CS
+		palSetPadMode(IOPORTA, 9, PAL_MODE_OUTPUT);
+		palClearPad(IOPORTA, 9);
+
+		// Backlight
+		palSetPadMode(IOPORTD, 3, PAL_MODE_OUTPUT);
+		palSetPad(IOPORTD, 3);
+
+		// PMP setup
+		PMMODE = 0;
+		PMAEN = 0;
+		PMCON = 0;
+		PMMODEbits.MODE = 2;
+		PMMODEbits.WAITB = 0;
+		PMMODEbits.WAITM = 1;
+		PMMODEbits.WAITE = 0;
+		PMCONbits.CSF = 0;
+		PMCONbits.PTRDEN = 1;
+		PMCONbits.PTWREN = 1;
+		PMMODEbits.MODE16 = 1;
+		PMCONbits.PMPEN = 1;
+
+		palClearPad(IOPORTA, 9);
+	}
+}
+
+#define PmpWaitBusy()   do {} while (PMMODEbits.BUSY)
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static noinline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if (state)
+		palClearPad(IOPORTA, 7);
+	else
+		palSetPad(IOPORTA, 7);
+}
+
+static void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	if (percentage)
+		palClearPad(IOPORTD, 3);
+	else
+		palSetPad(IOPORTD, 3);
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static noinline void write_index(GDisplay *g, uint16_t index) {
+	volatile uint16_t dummy;
+	(void) g;
+
+	PmpWaitBusy();
+	palClearPad(IOPORTA, 10);
+	PMDIN = index;
+	PmpWaitBusy();
+	palSetPad(IOPORTA, 10);
+
+	dummy = PMDIN;
+	(void)dummy;
+}
+
+static noinline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	PMDIN = data;
+	PmpWaitBusy();
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+static noinline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	PmpWaitBusy();
+	return PMDIN;
+}
+
+#endif /* GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
new file mode 100644
index 00000000..df02a716
--- /dev/null
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
@@ -0,0 +1,103 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9320 display.
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM              (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+
+		/* FSMC setup for F1 */
+		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+		/* set pin modes */
+		IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0};
+		IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0};
+		palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+		palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+		palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL);
+
+		/* FSMC timing */
+		FSMC_Bank1->BTCR[0+1] = (6) | (10 << 8) | (10 << 16);
+
+		/* Bank1 NOR/SRAM control register configuration
+		 * This is actually not needed as already set by default after reset */
+		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if(state)
+		palClearPad(GPIOE, GPIOE_TFT_RST);
+	else
+		palSetPad(GPIOE, GPIOE_TFT_RST);
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	if(percent)
+		palClearPad(GPIOD, GPIOD_TFT_LIGHT);
+	else
+		palSetPad(GPIOD, GPIOD_TFT_LIGHT);
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return GDISP_RAM;
+}
+
+#endif /* GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_template.h b/drivers/gdisp/ILI9320/board_ILI9320_template.h
new file mode 100644
index 00000000..ead9aee0
--- /dev/null
+++ b/drivers/gdisp/ILI9320/board_ILI9320_template.h
@@ -0,0 +1,159 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9320/board_ILI9320_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] display	The display number on this controller (0..n)
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g, unsigned display) {
+	(void) g;
+	(void) display;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ *
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @note	The chip select may need to be asserted/de-asserted
+ * 			around the actual spi read
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return 0;
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index 68081b96..228cbb09 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -24,9 +24,11 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1289
+#include "../drivers/gdisp/ILI9320/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_ILI9320.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -48,129 +50,137 @@
 /*===========================================================================*/
 /* Driver local variables.                                                   */
 /*===========================================================================*/
-uint32_t DISPLAY_CODE;
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
-#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
+#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
 
-static void set_cursor(GDISPDriver *g) {
+static void set_cursor(GDisplay *g) {
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 		case GDISP_ROTATE_180:
-			write_reg(0x0020, g->p.x);
-			write_reg(0x0021, g->p.y);
+			write_reg(g, 0x20, g->p.x);
+			write_reg(g, 0x21, g->p.y);
 			break;
 
 		case GDISP_ROTATE_90:
 		case GDISP_ROTATE_270:
-			write_reg(0x0020, g->p.y);
-			write_reg(0x0021, g->p.x);
+			write_reg(g, 0x20, g->p.y);
+			write_reg(g, 0x21, g->p.x);
 			break;
 	}
-	write_index(0x0022);
+	write_index(g, 0x22);
 }
 
-static void set_viewport(GDISPDriver *g) {
+static void set_viewport(GDisplay *g) {
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 		case GDISP_ROTATE_180:
-			write_reg(0x0050, g->p.x);
-			write_reg(0x0051, g->p.x + g->p.cx - 1);
-			write_reg(0x0052, g->p.y);
-			write_reg(0x0053, g->p.y + g->p.cy - 1);
+			write_reg(g, 0x50, g->p.x);
+			write_reg(g, 0x51, g->p.x + g->p.cx - 1);
+			write_reg(g, 0x52, g->p.y);
+			write_reg(g, 0x53, g->p.y + g->p.cy - 1);
 			break;
 
 		case GDISP_ROTATE_90:
 		case GDISP_ROTATE_270:
-			write_reg(0x0050, g->p.y);
-			write_reg(0x0051, g->p.y + g->p.cy - 1);
-			write_reg(0x0052, g->p.x);
-			write_reg(0x0053, g->p.x + g->p.cx - 1);
+			write_reg(g, 0x50, g->p.y);
+			write_reg(g, 0x51, g->p.y + g->p.cy - 1);
+			write_reg(g, 0x52, g->p.x);
+			write_reg(g, 0x53, g->p.x + g->p.cx - 1);
 			break;
 	}
 }
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+	uint16_t cver;
+
 	/* Initialise your display */
-	init_board();
+	init_board(g, display);
 
 	/* Hardware reset */
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	gfxSleepMicroseconds(1000);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	gfxSleepMicroseconds(1000);
 
-	acquire_bus();
-	write_index(0);				// Get controller version
-	dummy_read();
-    DISPLAY_CODE = read_data();
-    write_reg(0x0000, 0x0001); //start Int. osc
+	acquire_bus(g);
+	write_index(g, 0);				// Get controller version
+	setreadmode(g);
+	dummy_read(g);
+    cver = read_data(g);
+	setwritemode(g);
+    write_reg(g, 0x00, 0x0001); //start Int. osc
     gfxSleepMicroseconds(500);
-    write_reg(0x0001, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
-    write_reg(0x0002, 0x0700); //select  the line inversion
-    write_reg(0x0003, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
-    write_reg(0x0004, 0x0000); //Resize control(No resizing)
-    write_reg(0x0008, 0x0202); //front and back porch 2 lines
-    write_reg(0x0009, 0x0000); //select normal scan
-    write_reg(0x000A, 0x0000); //display control 4
-    write_reg(0x000C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
-    write_reg(0x000D, 0x0000); //Frame marker position
-    write_reg(0x000F, 0x0000); //selects clk, enable and sync signal polarity,
-    write_reg(0x0010, 0x0000); //
-    write_reg(0x0011, 0x0000); //power control 2 reference voltages = 1:1,
-    write_reg(0x0012, 0x0000); //power control 3 VRH
-    write_reg(0x0013, 0x0000); //power control 4 VCOM amplitude
+    write_reg(g, 0x01, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
+    write_reg(g, 0x02, 0x0700); //select  the line inversion
+    write_reg(g, 0x03, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
+    write_reg(g, 0x04, 0x0000); //Resize control(No resizing)
+    write_reg(g, 0x08, 0x0202); //front and back porch 2 lines
+    write_reg(g, 0x09, 0x0000); //select normal scan
+    write_reg(g, 0x0A, 0x0000); //display control 4
+    write_reg(g, 0x0C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
+    write_reg(g, 0x0D, 0x0000); //Frame marker position
+    write_reg(g, 0x0F, 0x0000); //selects clk, enable and sync signal polarity,
+    write_reg(g, 0x10, 0x0000); //
+    write_reg(g, 0x11, 0x0000); //power control 2 reference voltages = 1:1,
+    write_reg(g, 0x12, 0x0000); //power control 3 VRH
+    write_reg(g, 0x13, 0x0000); //power control 4 VCOM amplitude
     gfxSleepMicroseconds(500);
-    write_reg(0x0010, 0x17B0); //power control 1 BT,AP
-    write_reg(0x0011, 0x0137); //power control 2 DC,VC
+    write_reg(g, 0x10, 0x17B0); //power control 1 BT,AP
+    write_reg(g, 0x11, 0x0137); //power control 2 DC,VC
     gfxSleepMicroseconds(500);
-    write_reg(0x0012, 0x0139); //power control 3 VRH
+    write_reg(g, 0x12, 0x0139); //power control 3 VRH
     gfxSleepMicroseconds(500);
-    write_reg(0x0013, 0x1d00); //power control 4 vcom amplitude
-    write_reg(0x0029, 0x0011); //power control 7 VCOMH
+    write_reg(g, 0x13, 0x1d00); //power control 4 vcom amplitude
+    write_reg(g, 0x29, 0x0011); //power control 7 VCOMH
     gfxSleepMicroseconds(500);
-    write_reg(0x0030, 0x0007);
-    write_reg(0x0031, 0x0403);
-    write_reg(0x0032, 0x0404);
-    write_reg(0x0035, 0x0002);
-    write_reg(0x0036, 0x0707);
-    write_reg(0x0037, 0x0606);
-    write_reg(0x0038, 0x0106);
-    write_reg(0x0039, 0x0007);
-    write_reg(0x003c, 0x0700);
-    write_reg(0x003d, 0x0707);
-    write_reg(0x0020, 0x0000); //starting Horizontal GRAM Address
-    write_reg(0x0021, 0x0000); //starting Vertical GRAM Address
-    write_reg(0x0050, 0x0000); //Horizontal GRAM Start Position
-    write_reg(0x0051, 0x00EF); //Horizontal GRAM end Position
-    write_reg(0x0052, 0x0000); //Vertical GRAM Start Position
-    write_reg(0x0053, 0x013F); //Vertical GRAM end Position
-	switch (DISPLAY_CODE) {   
+    write_reg(g, 0x30, 0x0007);
+    write_reg(g, 0x31, 0x0403);
+    write_reg(g, 0x32, 0x0404);
+    write_reg(g, 0x35, 0x0002);
+    write_reg(g, 0x36, 0x0707);
+    write_reg(g, 0x37, 0x0606);
+    write_reg(g, 0x38, 0x0106);
+    write_reg(g, 0x39, 0x0007);
+    write_reg(g, 0x3c, 0x0700);
+    write_reg(g, 0x3d, 0x0707);
+    write_reg(g, 0x20, 0x0000); //starting Horizontal GRAM Address
+    write_reg(g, 0x21, 0x0000); //starting Vertical GRAM Address
+    write_reg(g, 0x50, 0x0000); //Horizontal GRAM Start Position
+    write_reg(g, 0x51, 0x00EF); //Horizontal GRAM end Position
+    write_reg(g, 0x52, 0x0000); //Vertical GRAM Start Position
+    write_reg(g, 0x53, 0x013F); //Vertical GRAM end Position
+	switch (cver) {
 		case 0x9320:
-        	write_reg(0x0060, 0x2700); //starts scanning from G1, and 320 drive lines
+        	write_reg(g, 0x60, 0x2700); //starts scanning from G1, and 320 drive lines
         	break;
       	case 0x9325:
-     		write_reg(0x0060, 0xA700); //starts scanning from G1, and 320 drive lines
+     		write_reg(g, 0x60, 0xA700); //starts scanning from G1, and 320 drive lines
 			break;
 	}
 
-    write_reg(0x0061, 0x0001); //fixed base display
-    write_reg(0x006a, 0x0000); //no scroll
-    write_reg(0x0090, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
-    write_reg(0x0092, 0x0000); //set gate output non-overlap period=0
-    write_reg(0x0093, 0x0003); //set Source Output Position=3
-    write_reg(0x0095, 0x0110); //RGB interface(Clocks per line period=16 clocks)
-    write_reg(0x0097, 0x0110); //set Gate Non-overlap Period 0 locksc
-    write_reg(0x0098, 0x0110); //
-    write_reg(0x0007, 0x0173); //display On
-    release_bus();
+    write_reg(g, 0x61, 0x0001); //fixed base display
+    write_reg(g, 0x6a, 0x0000); //no scroll
+    write_reg(g, 0x90, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
+    write_reg(g, 0x92, 0x0000); //set gate output non-overlap period=0
+    write_reg(g, 0x93, 0x0003); //set Source Output Position=3
+    write_reg(g, 0x95, 0x0110); //RGB interface(Clocks per line period=16 clocks)
+    write_reg(g, 0x97, 0x0110); //set Gate Non-overlap Period 0 locksc
+    write_reg(g, 0x98, 0x0110); //
+    write_reg(g, 0x07, 0x0173); //display On
+
+    // Finish Init
+    post_init_board(g);
+
+  	// Release the bus
+ 	release_bus(g);
 
 	// Turn on the backlight
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 	
     /* Initialise the GDISP structure */
     g->g.Width = GDISP_SCREEN_WIDTH;
@@ -183,108 +193,105 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
-		write_data(g->p.color);
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
 	}
-	LLDSPEC void gdisp_lld_write_pos(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
 		set_cursor(g);
 	}
-	#endif
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
-		setreadmode();
-		dummy_read();
+		setreadmode(g);
+		dummy_read(g);
 	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
-		return read_data();
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
 	}
-	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
-		setwritemode();
-		release_bus();
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	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();
-					write_reg(0x0007, 0x0000);
-					write_reg(0x0010, 0x0000);
-					write_reg(0x0011, 0x0000);
-					write_reg(0x0012, 0x0000);
-					write_reg(0x0013, 0x0000);
-					release_bus();
-
-					set_backlight(0);
+					acquire_bus(g);
+					write_reg(g, 0x07, 0x0000);
+					write_reg(g, 0x10, 0x0000);
+					write_reg(g, 0x11, 0x0000);
+					write_reg(g, 0x12, 0x0000);
+					write_reg(g, 0x13, 0x0000);
+					release_bus(g);
+
+					set_backlight(g, 0);
 					break;
 
 				case powerOn:
 					//*************Power On sequence ******************//
-					acquire_bus();
-					write_reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-					write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
-					write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					acquire_bus(g);
+					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
 					gfxSleepMicroseconds(2000);            /* Dis-charge capacitor power voltage */
-					write_reg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-					write_reg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+					write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
 					gfxSleepMicroseconds(500);
-					write_reg(0x0012, 0x013C); /* VREG1OUT voltage */
+					write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
 					gfxSleepMicroseconds(500);
-					write_reg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
-					write_reg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
+					write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+					write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
 					gfxSleepMicroseconds(500);
-					write_reg(0x0007, 0x0173); /* 262K color and display ON */
-					release_bus();
+					write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
+					release_bus(g);
 
-					set_backlight(g->g.Backlight);
-					if(g->g.Powermode != powerSleep || g->g.Powermode != powerDeepSleep)
-						gdisp_lld_init();
+					set_backlight(g, g->g.Backlight);
 					break;
 
 				case powerSleep:
-					acquire_bus();
-					write_reg(0x0007, 0x0000); /* display OFF */
-					write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
-					write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					acquire_bus(g);
+					write_reg(g, 0x07, 0x0000); /* display OFF */
+					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
 					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
-					write_reg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					release_bus();
+					write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					release_bus(g);
 
-					set_backlight(0);
+					set_backlight(g, 0);
 					break;
 
 				case powerDeepSleep:
-					acquire_bus();
-					write_reg(0x0007, 0x0000); /* display OFF */
-					write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
-					write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					acquire_bus(g);
+					write_reg(g, 0x07, 0x0000); /* display OFF */
+					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
 					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
-					write_reg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					release_bus();
+					write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					release_bus(g);
 
-					set_backlight(0);
+					set_backlight(g, 0);
 					break;
 
 				default:
@@ -298,44 +305,44 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 					return;
 				switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
-					acquire_bus();
-					write_reg(0x0001, 0x0100);
-					write_reg(0x0003, 0x1038);
-					write_reg(0x0060, 0x2700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
 
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 
 				case GDISP_ROTATE_90:
-					acquire_bus();
-					write_reg(0x0001, 0x0100);
-					write_reg(0x0003, 0x1030);
-					write_reg(0x0060, 0x2700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
 
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
 
 				case GDISP_ROTATE_180:
-					acquire_bus();
-					write_reg(0x0001, 0x0000);
-					write_reg(0x0003, 0x1030);
-					write_reg(0x0060, 0x2700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
 
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 
 				case GDISP_ROTATE_270:
-					acquire_bus();
-					write_reg(0x0001, 0x0000);
-					write_reg(0x0003, 0x1038);
-					write_reg(0x0060, 0xA700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0xA700);
+					release_bus(g);
 
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
@@ -350,7 +357,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 	        case GDISP_CONTROL_BACKLIGHT:
 	            if ((unsigned)g->p.ptr > 100)
 	            	g->p.ptr = (void *)100;
-	            set_backlight((unsigned)g->p.ptr);
+	            set_backlight(g, (unsigned)g->p.ptr);
 	            g->g.Backlight = (unsigned)g->p.ptr;
 	            return;
 			default:
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.mk b/drivers/gdisp/ILI9320/gdisp_lld.mk
index bcdd3230..656f5930 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9320/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9320
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.c
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
deleted file mode 100644
index faa54a3e..00000000
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld_board_olimex_pic32mx_lcd.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-#ifndef noinline
-#define noinline __attribute__((noinline))
-#endif
-
-static void init_board(void) {
-  // RST
-  palSetPadMode(IOPORTA, 7, PAL_MODE_OUTPUT);
-  palClearPad(IOPORTA, 7);
-
-  // RS
-  palSetPadMode(IOPORTA, 10, PAL_MODE_OUTPUT);
-  palSetPad(IOPORTA, 10);
-
-  // CS
-  palSetPadMode(IOPORTA, 9, PAL_MODE_OUTPUT);
-  palClearPad(IOPORTA, 9);
-
-  // Backlight
-  palSetPadMode(IOPORTD, 3, PAL_MODE_OUTPUT);
-  palSetPad(IOPORTD, 3);
-
-  // PMP setup
-  PMMODE = 0;
-  PMAEN = 0;
-  PMCON = 0;
-  PMMODEbits.MODE = 2;
-  PMMODEbits.WAITB = 0;
-  PMMODEbits.WAITM = 1;
-  PMMODEbits.WAITE = 0;
-  PMCONbits.CSF = 0;
-  PMCONbits.PTRDEN = 1;
-  PMCONbits.PTWREN = 1;
-  PMMODEbits.MODE16 = 1;
-  PMCONbits.PMPEN = 1;
-
-  palClearPad(IOPORTA, 9);
-}
-
-#define PmpWaitBusy()   do {} while (PMMODEbits.BUSY)
-
-static noinline void setpin_reset(bool_t state) {
-  if (state)
-    palClearPad(IOPORTA, 7);
-  else
-    palSetPad(IOPORTA, 7);
-}
-
-static noinline void write_index(uint16_t data) {
-  volatile uint16_t dummy;
-
-  PmpWaitBusy();
-  palClearPad(IOPORTA, 10);
-  PMDIN = data;
-  PmpWaitBusy();
-  palSetPad(IOPORTA, 10);
-
-  dummy = PMDIN;
-  (void)dummy;
-}
-
-static noinline void write_data(uint16_t data) {
-  PMDIN = data;
-  PmpWaitBusy();
-}
-
-static inline void setreadmode(void) {
-}
-
-static inline void setwritemode(void) {
-}
-
-static noinline uint16_t read_data(void) {
-  PmpWaitBusy();
-  return PMDIN;
-}
-
-/* if not available, just ignore the argument and return */
-static void set_backlight(uint8_t percentage) {
-  if (percentage)
-    palClearPad(IOPORTD, 3);
-  else
-    palSetPad(IOPORTD, 3);
-}
-
-static inline void acquire_bus(void) {
-  /* Nothing to do here since LCD is the only device on that bus */
-}
-
-static inline void release_bus(void) {
-  /* Nothing to do here since LCD is the only device on that bus */
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
deleted file mode 100644
index 1662385a..00000000
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9320 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
-
-static inline void init_board(void) {
-	/* FSMC setup for F1 */
-	rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-    /* set pin modes */
-    IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0}; 
-    IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0}; 
-    palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-    palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-	palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL);
-
-    const unsigned char FSMC_Bank = 0;
-
-    /* FSMC timing */
-    FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
-
-    /* Bank1 NOR/SRAM control register configuration
-     * This is actually not needed as already set by default after reset */
-    FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-static inline void setpin_reset(bool_t state) {
-	if(state)
-		palClearPad(GPIOE, GPIOE_TFT_RST);
-	else
-		palSetPad(GPIOE, GPIOE_TFT_RST);
-}
-
-static inline void acquire_bus(void) {
-			/* Nothing to do here since LCD is the only device on that bus */
-}
-
-static inline void release_bus(void) {
-			/* Nothing to do here since LCD is the only device on that bus */
-}
-
-static inline void write_index(uint16_t reg) {
-	GDISP_REG = reg;
-}
-
-static inline void write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(void) {
-}
-
-static inline void setwritemode(void) {
-}
-
-static inline uint16_t read_data(void) {
-	return GDISP_RAM;
-}
-
-static inline void set_backlight(uint8_t percent) {
-	if(percent == 100)
-		palClearPad(GPIOD, GPIOD_TFT_LIGHT);
-	else
-		palSetPad(GPIOD, GPIOD_TFT_LIGHT);
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_template.h b/drivers/gdisp/ILI9320/gdisp_lld_board_template.h
deleted file mode 100644
index 201b3630..00000000
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9320 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-static inline void init_board(void) {
-
-}
-
-static inline void setpin_reset(bool_t state) {
-
-}
-
-static inline void acquire_bus(void) {
-
-}
-
-static inline void release_bus(void) {
-
-}
-
-static inline void write_index(uint16_t data) {
-
-}
-
-static inline void write_data(uint16_t data) {
-
-}
-
-static inline void setreadmode(void) {
-
-}
-
-static inline void setwritemode(void) {
-
-}
-
-static inline uint16_t read_data(void) {
-
-}
-
-static inline uint16_t set_backlight(uint8_t percentage) {
-
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
index 02533e8b..3c5c7484 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -22,9 +22,6 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"ILI9320"
-#define GDISP_DRIVER_STRUCT				GDISP_ILI9320
-
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_STREAM_POS		TRUE
-- 
cgit v1.2.3


From a3714ae7c4438d6b3247c45a1c8fe3f217a9a2af Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 17:07:26 +1000
Subject: Bug fix ILI9320 driver

---
 drivers/gdisp/ILI9320/gdisp_lld.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index 228cbb09..3747b3d7 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -24,7 +24,7 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_DRIVER_VMT			GDISPVMT_SSD1289
+#define GDISP_DRIVER_VMT			GDISPVMT_ILI9320
 #include "../drivers/gdisp/ILI9320/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
 
-- 
cgit v1.2.3


From 313956b2154875e479735a17468af7013d4d6de6 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 17:07:53 +1000
Subject: Remove incorrect comment.

---
 drivers/gdisp/SSD1289/board_SSD1289_template.h | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/board_SSD1289_template.h b/drivers/gdisp/SSD1289/board_SSD1289_template.h
index db841c2c..b24789ea 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_template.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_template.h
@@ -145,9 +145,6 @@ static inline void setwritemode(GDisplay *g) {
  *
  * @param[in] g				The GDisplay structure
  *
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
  * @notapi
  */
 static inline uint16_t read_data(GDisplay *g) {
-- 
cgit v1.2.3


From 668afded53f3e35f73126808688fbf659cf1a63c Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 17:08:21 +1000
Subject: Convert ILI9325 driver to new format

---
 .../gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h    | 117 ++++++++
 drivers/gdisp/ILI9325/board_ILI9325_template.h     | 157 +++++++++++
 drivers/gdisp/ILI9325/gdisp_lld.c                  | 302 +++++++++++----------
 drivers/gdisp/ILI9325/gdisp_lld.mk                 |   5 +-
 .../gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h  | 119 --------
 drivers/gdisp/ILI9325/gdisp_lld_board_template.h   | 123 ---------
 drivers/gdisp/ILI9325/gdisp_lld_config.h           |   3 -
 7 files changed, 429 insertions(+), 397 deletions(-)
 create mode 100644 drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
 create mode 100644 drivers/gdisp/ILI9325/board_ILI9325_template.h
 delete mode 100644 drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
 delete mode 100644 drivers/gdisp/ILI9325/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
new file mode 100644
index 00000000..ed697b6f
--- /dev/null
+++ b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
@@ -0,0 +1,117 @@
+/*
+ * 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
+ */
+
+/*
+	driver quickly hacked together from a chinese sourcecode that came
+	with the board and existing ili9320 code by Chris van Dongen (sjaak)
+	(sjaak2002 at msn.com)
+	
+	Also added rotation for 180 and 270 degrees and minor tweaks to
+	setcursor
+	
+	Added code comes without warranty and free bugs. Feel free to use 
+	or misuse the added code :D
+*/
+
+
+/**
+ * @file    drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+
+		/* FSMC setup for F1 */
+		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+
+		/* set pin modes */
+	/*	IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0};
+		IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0};
+		palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+		palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
+		palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL); */
+
+		const unsigned char FSMC_Bank = 0;
+
+		/* FSMC timing */
+		FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
+
+		/* Bank1 NOR/SRAM control register configuration
+		 * This is actually not needed as already set by default after reset */
+		FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if(state)
+		palClearPad(GPIOE, GPIOE_TFT_RST);
+	else
+		palSetPad(GPIOE, GPIOE_TFT_RST);
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void)percent;
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return GDISP_RAM;
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_template.h b/drivers/gdisp/ILI9325/board_ILI9325_template.h
new file mode 100644
index 00000000..4d54ba34
--- /dev/null
+++ b/drivers/gdisp/ILI9325/board_ILI9325_template.h
@@ -0,0 +1,157 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9325/gdisp_lld_board_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] display	The display number on this controller (0..n)
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g, unsigned display) {
+	(void) g;
+	(void) display;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ *
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return 0;
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index 4795887e..42acdc46 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -8,9 +8,6 @@
 /**
  * @file    drivers/gdisp/ILI9325/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9325 display.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
@@ -27,9 +24,11 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_ILI9325
+#include "../drivers/gdisp/ILI9325/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_ILI9325.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -51,126 +50,135 @@
 /*===========================================================================*/
 /* Driver local variables.                                                   */
 /*===========================================================================*/
-uint32_t DISPLAY_CODE;
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
 // Some common routines and macros
-#define dummy_read()				{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
-#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
+#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
 
-static void set_cursor(GDISPDriver *g) {
+static void set_cursor(GDisplay *g) {
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 		case GDISP_ROTATE_180:
-			write_reg(0x0020, g->p.x);
-			write_reg(0x0021, g->p.y);
+			write_reg(g, 0x20, g->p.x);
+			write_reg(g, 0x21, g->p.y);
 			break;
 
 		case GDISP_ROTATE_90:
 		case GDISP_ROTATE_270:
-			write_reg(0x0020, g->p.y);
-			write_reg(0x0021, g->p.x);
+			write_reg(g, 0x20, g->p.y);
+			write_reg(g, 0x21, g->p.x);
 			break;
 	}
-	write_index(0x0022);
+	write_index(g, 0x22);
 }
 
-static void set_viewport(GDISPDriver* g) {
+static void set_viewport(GDisplay* g) {
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 		case GDISP_ROTATE_180:
-			write_reg(0x0050, g->p.x);
-			write_reg(0x0051, g->p.x + g->p.cx - 1);
-			write_reg(0x0052, g->p.y);
-			write_reg(0x0053, g->p.y + g->p.cy - 1);
+			write_reg(g, 0x50, g->p.x);
+			write_reg(g, 0x51, g->p.x + g->p.cx - 1);
+			write_reg(g, 0x52, g->p.y);
+			write_reg(g, 0x53, g->p.y + g->p.cy - 1);
 			break;
 
 		case GDISP_ROTATE_90:
 		case GDISP_ROTATE_270:
-			write_reg(0x0050, g->p.y);
-			write_reg(0x0051, g->p.y + g->p.cy - 1);
-			write_reg(0x0052, g->p.x);
-			write_reg(0x0053, g->p.x + g->p.cx - 1);
+			write_reg(g, 0x50, g->p.y);
+			write_reg(g, 0x51, g->p.y + g->p.cy - 1);
+			write_reg(g, 0x52, g->p.x);
+			write_reg(g, 0x53, g->p.x + g->p.cx - 1);
 			break;
 	}
 }
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+	uint16_t cver;
+
 	/* Initialise your display */
-	init_board();
+	init_board(g, display);
 
 	/* Hardware reset */
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	gfxSleepMicroseconds(1000);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	gfxSleepMicroseconds(1000);
 
-	acquire_bus();
-	write_index(0);				// Get controller version
-	dummy_read();
-    DISPLAY_CODE = read_data();
+	acquire_bus(g);
+	write_index(g, 0);				// Get controller version
+	setreadmode(g);
+	dummy_read(g);
+    cver = read_data(g);
+    setwritemode(g);
 
 	// chinese code starts here
-	write_reg(0x0000,0x0001);
+	write_reg(g, 0x00, 0x0001);
 	gfxSleepMilliseconds(10);
 
-	write_reg(0x0015,0x0030);
-	write_reg(0x0011,0x0040);
-	write_reg(0x0010,0x1628);
-	write_reg(0x0012,0x0000);
-	write_reg(0x0013,0x104d);
+	write_reg(g, 0x15, 0x0030);
+	write_reg(g, 0x11, 0x0040);
+	write_reg(g, 0x10, 0x1628);
+	write_reg(g, 0x12, 0x0000);
+	write_reg(g, 0x13, 0x104d);
 	gfxSleepMilliseconds(10);
-	write_reg(0x0012,0x0010);
+	write_reg(g, 0x12, 0x0010);
 	gfxSleepMilliseconds(10);
-	write_reg(0x0010,0x2620);
-	write_reg(0x0013,0x344d); //304d
+	write_reg(g, 0x10, 0x2620);
+	write_reg(g, 0x13, 0x344d); //304d
 	gfxSleepMilliseconds(10);
 
-	write_reg(0x0001,0x0100);
-	write_reg(0x0002,0x0300);
-	write_reg(0x0003,0x1038);//0x1030
-	write_reg(0x0008,0x0604);
-	write_reg(0x0009,0x0000);
-	write_reg(0x000A,0x0008);
-
-	write_reg(0x0041,0x0002);
-	write_reg(0x0060,0x2700);
-	write_reg(0x0061,0x0001);
-	write_reg(0x0090,0x0182);
-	write_reg(0x0093,0x0001);
-	write_reg(0x00a3,0x0010);
+	write_reg(g, 0x01, 0x0100);
+	write_reg(g, 0x02, 0x0300);
+	write_reg(g, 0x03, 0x1038);//0x1030
+	write_reg(g, 0x08, 0x0604);
+	write_reg(g, 0x09, 0x0000);
+	write_reg(g, 0x0A, 0x0008);
+
+	write_reg(g, 0x41, 0x0002);
+	write_reg(g, 0x60, 0x2700);
+	write_reg(g, 0x61, 0x0001);
+	write_reg(g, 0x90, 0x0182);
+	write_reg(g, 0x93, 0x0001);
+	write_reg(g, 0xa3, 0x0010);
 	gfxSleepMilliseconds(10);
 
 	//################# void Gamma_Set(void) ####################//
-	write_reg(0x30,0x0000);
-	write_reg(0x31,0x0502);
-	write_reg(0x32,0x0307);
-	write_reg(0x33,0x0305);
-	write_reg(0x34,0x0004);
-	write_reg(0x35,0x0402);
-	write_reg(0x36,0x0707);
-	write_reg(0x37,0x0503);
-	write_reg(0x38,0x1505);
-	write_reg(0x39,0x1505);
+	write_reg(g, 0x30, 0x0000);
+	write_reg(g, 0x31, 0x0502);
+	write_reg(g, 0x32, 0x0307);
+	write_reg(g, 0x33, 0x0305);
+	write_reg(g, 0x34, 0x0004);
+	write_reg(g, 0x35, 0x0402);
+	write_reg(g, 0x36, 0x0707);
+	write_reg(g, 0x37, 0x0503);
+	write_reg(g, 0x38, 0x1505);
+	write_reg(g, 0x39, 0x1505);
 	gfxSleepMilliseconds(10);
 
 	//################## void Display_ON(void) ####################//
-	write_reg(0x0007,0x0001);
+	write_reg(g, 0x07, 0x0001);
 	gfxSleepMilliseconds(10);
-	write_reg(0x0007,0x0021);
-	write_reg(0x0007,0x0023);
+	write_reg(g, 0x07, 0x0021);
+	write_reg(g, 0x07, 0x0023);
 	gfxSleepMilliseconds(10);
-	write_reg(0x0007,0x0033);
+	write_reg(g, 0x07, 0x0033);
 	gfxSleepMilliseconds(10);
-	write_reg(0x0007,0x0133);
+	write_reg(g, 0x07, 0x0133);
 
 	// chinese code ends here
 
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(g);
+
 	// Turn on the backlight
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 	
     /* Initialise the GDISP structure */
     g->g.Width = GDISP_SCREEN_WIDTH;
@@ -184,101 +192,101 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
-		write_data(g->p.color);
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
 	}
-	LLDSPEC void gdisp_lld_write_pos(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
 		set_cursor(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
-		setreadmode();
-		dummy_read();
+		setreadmode(g);
+		dummy_read(g);
 	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
-		return read_data();
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
 	}
-	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
-		setwritemode();
-		release_bus();
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	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();
-				write_reg(0x0007, 0x0000);
-				write_reg(0x0010, 0x0000);
-				write_reg(0x0011, 0x0000);
-				write_reg(0x0012, 0x0000);
-				write_reg(0x0013, 0x0000);
-				release_bus();
-				set_backlight(0);
+				acquire_bus(g);
+				write_reg(g, 0x07, 0x0000);
+				write_reg(g, 0x10, 0x0000);
+				write_reg(g, 0x11, 0x0000);
+				write_reg(g, 0x12, 0x0000);
+				write_reg(g, 0x13, 0x0000);
+				release_bus(g);
+				set_backlight(g, 0);
 				break;
 
 			case powerOn:
 				//*************Power On sequence ******************//
-				acquire_bus();
-				write_reg(0x0010, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-				write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
-				write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
 				gfxSleepMilliseconds(200);            /* Dis-charge capacitor power voltage */
-				write_reg(0x0010, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-				write_reg(0x0011, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+				write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
 				gfxSleepMilliseconds(50);
-				write_reg(0x0012, 0x013C); /* VREG1OUT voltage */
+				write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
 				gfxSleepMilliseconds(50);
-				write_reg(0x0013, 0x0E00); /* VDV[4:0] for VCOM amplitude */
-				write_reg(0x0029, 0x0009); /* VCM[4:0] for VCOMH */
+				write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+				write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
 				gfxSleepMilliseconds(50);
-				write_reg(0x0007, 0x0173); /* 262K color and display ON */
-				release_bus();
-				set_backlight(g->g.Backlight);
+				write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
+				release_bus(g);
+				set_backlight(g, g->g.Backlight);
 				break;
 
 			case powerSleep:
-				acquire_bus();
-				write_reg(0x0007, 0x0000); /* display OFF */
-				write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
-				write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				acquire_bus(g);
+				write_reg(g, 0x07, 0x0000); /* display OFF */
+				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
 				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
-				write_reg(0x0010, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				release_bus();
-				gdisp_lld_backlight(0);
+				write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				release_bus(g);
+				gdisp_lld_backlight(g, 0);
 				break;
 
 			case powerDeepSleep:
-				acquire_bus();
-				write_reg(0x0007, 0x0000); /* display OFF */
-				write_reg(0x0010, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				write_reg(0x0011, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				write_reg(0x0012, 0x0000); /* VREG1OUT voltage */
-				write_reg(0x0013, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				acquire_bus(g);
+				write_reg(g, 0x07, 0x0000); /* display OFF */
+				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
 				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
-				write_reg(0x0010, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				release_bus();
-				gdisp_lld_backlight(0);
+				write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				release_bus(g);
+				gdisp_lld_backlight(g, 0);
 				break;
 
 			default:
@@ -292,41 +300,41 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				return;
 			switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
-					acquire_bus();
-					write_reg(0x0001, 0x0100);
-					write_reg(0x0003, 0x1038);
-					write_reg(0x0060, 0x2700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 
 				case GDISP_ROTATE_90:
-					acquire_bus();
-					write_reg(0x0001, 0x0000);
-					write_reg(0x0003, 0x1030);
-					write_reg(0x0060, 0x2700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
 
 				case GDISP_ROTATE_180:
-					acquire_bus();
-					write_reg(0x0001, 0x0000);
-					write_reg(0x0003, 0x1038);
-					write_reg(0x0060, 0xa700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0xa700);
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 	
 				case GDISP_ROTATE_270:
-					acquire_bus();
-					write_reg(0x0001, 0x0100);
-					write_reg(0x0003, 0x1030);
-					write_reg(0x0060, 0xA700);
-					release_bus();
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0xA700);
+					release_bus(g);
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
@@ -341,7 +349,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
         case GDISP_CONTROL_BACKLIGHT:
             if ((unsigned)g->p.ptr > 100)
             	g->p.ptr = (void *)100;
-            set_backlight((unsigned)g->p.ptr);
+            set_backlight(g, (unsigned)g->p.ptr);
             g->g.Backlight = (unsigned)g->p.ptr;
             return;
 		
@@ -353,5 +361,3 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.mk b/drivers/gdisp/ILI9325/gdisp_lld.mk
index b5061324..61565164 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9325/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9325/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9325
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9325/gdisp_lld.c
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h b/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
deleted file mode 100644
index 3e2c269b..00000000
--- a/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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
- */
-
-/*
-	driver quickly hacked together from a chinese sourcecode that came
-	with the board and existing ili9320 code by Chris van Dongen (sjaak)
-	(sjaak2002 at msn.com)
-	
-	Also added rotation for 180 and 270 degrees and minor tweaks to
-	setcursor
-	
-	Added code comes without warranty and free bugs. Feel free to use 
-	or misuse the added code :D
-*/
-
-
-/**
- * @file    drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
-
-static inline void init_board(void) {
-	/* FSMC setup for F1 */
-	rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-    /* set pin modes */
-/*	IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0}; 
-    IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0}; 
-    palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-    palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-	palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL); */
-
-    const unsigned char FSMC_Bank = 0;
-
-    /* FSMC timing */
-    FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
-
-    /* Bank1 NOR/SRAM control register configuration
-     * This is actually not needed as already set by default after reset */
-    FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-	
-}
-
-static inline void setpin_reset(bool_t state) {
-	if(state)
-		palClearPad(GPIOE, GPIOE_TFT_RST);
-	else
-		palSetPad(GPIOE, GPIOE_TFT_RST);
-}
-
-static inline void write_index(uint16_t reg) {
-	GDISP_REG = reg;
-}
-
-static inline void write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-static inline uint16_t read_data(void) {
-	return GDISP_RAM;
-}
-
-static inline void set_backlight(uint8_t percent) {
-	(void)percent;
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_template.h b/drivers/gdisp/ILI9325/gdisp_lld_board_template.h
deleted file mode 100644
index c07b4ba1..00000000
--- a/drivers/gdisp/ILI9325/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9325/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-/**
- * @brief   Initialise the board for the display.
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- *
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- *
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- *
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- *
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_config.h b/drivers/gdisp/ILI9325/gdisp_lld_config.h
index aabf768f..8c586c78 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_config.h
@@ -22,9 +22,6 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"ILI9325"
-#define GDISP_DRIVER_STRUCT				GDISP_ILI9325
-
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_STREAM_POS		TRUE
-- 
cgit v1.2.3


From 29cf77746c973f63b694a3b56008173eb208939e Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 17:10:15 +1000
Subject: Fix doxygen comments.

---
 drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h | 4 +---
 drivers/gdisp/ILI9325/board_ILI9325_template.h      | 2 +-
 2 files changed, 2 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
index ed697b6f..166ebc33 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
@@ -19,7 +19,7 @@
 
 
 /**
- * @file    drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
+ * @file    drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
  * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
  */
 
@@ -113,5 +113,3 @@ static inline uint16_t read_data(GDisplay *g) {
 }
 
 #endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_template.h b/drivers/gdisp/ILI9325/board_ILI9325_template.h
index 4d54ba34..7b067293 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_template.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_template.h
@@ -6,7 +6,7 @@
  */
 
 /**
- * @file    drivers/gdisp/ILI9325/gdisp_lld_board_template.h
+ * @file    drivers/gdisp/ILI9325/board_ILI9325_template.h
  * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
  *
  * @addtogroup GDISP
-- 
cgit v1.2.3


From 443d14c21f10fea9b0c6fc5559ec4c6b31f99546 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 18 Oct 2013 17:29:27 +1000
Subject: Convert driver ILI9481 to new format

---
 .../ILI9481/board_ILI9481_firebullstm32f103.h      | 109 +++++++++
 drivers/gdisp/ILI9481/board_ILI9481_template.h     | 157 +++++++++++++
 drivers/gdisp/ILI9481/gdisp_lld.c                  | 245 +++++++++++----------
 drivers/gdisp/ILI9481/gdisp_lld.mk                 |   5 +-
 .../ILI9481/gdisp_lld_board_firebullstm32f103.h    | 156 -------------
 drivers/gdisp/ILI9481/gdisp_lld_board_template.h   | 123 -----------
 drivers/gdisp/ILI9481/gdisp_lld_config.h           |   3 -
 7 files changed, 392 insertions(+), 406 deletions(-)
 create mode 100644 drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
 create mode 100644 drivers/gdisp/ILI9481/board_ILI9481_template.h
 delete mode 100644 drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
 delete mode 100644 drivers/gdisp/ILI9481/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
new file mode 100644
index 00000000..6614d578
--- /dev/null
+++ b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
@@ -0,0 +1,109 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
+ * @brief   GDISP Graphics Driver subsystem low level driver source for
+ * 			the ILI9481 and compatible HVGA display
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define SET_CS		palSetPad(GPIOD, 12);
+#define CLR_CS		palClearPad(GPIOD, 12);
+#define SET_RS		palSetPad(GPIOD, 13);
+#define CLR_RS		palClearPad(GPIOD, 13);
+#define SET_WR		palSetPad(GPIOD, 14);
+#define CLR_WR		palClearPad(GPIOD, 14);
+#define SET_RD		palSetPad(GPIOD, 15);
+#define CLR_RD		palClearPad(GPIOD, 15);
+
+static inline void init_board(GDisplay *g, unsigned display) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	if (display == 0) {
+
+		/**
+		 * Set up for Display 0
+		 */
+		palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
+
+		// Configure the pins to a well know state
+		SET_RS;
+		SET_RD;
+		SET_WR;
+		CLR_CS;
+	}
+}
+
+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 set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	palWritePort(GPIOE, index);
+	CLR_RS; CLR_WR; SET_WR; SET_RS;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	palWritePort(GPIOE, data);
+	CLR_WR; SET_WR;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+	// change pin mode to digital input
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+	// change pin mode back to digital output
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	uint16_t	value;
+	(void) g;
+	
+	CLR_RD;
+	value = palReadPort(GPIOE);
+	SET_RD;
+	
+	return value;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_template.h b/drivers/gdisp/ILI9481/board_ILI9481_template.h
new file mode 100644
index 00000000..f3f8bbb7
--- /dev/null
+++ b/drivers/gdisp/ILI9481/board_ILI9481_template.h
@@ -0,0 +1,157 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9481/board_ILI9481_template.h
+ * @brief   GDISP Graphics Driver subsystem low level driver source for
+ * 			the ILI9481 and compatible HVGA display
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] display	The display number on this controller (0..n)
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g, unsigned display) {
+	(void) g;
+	(void) display;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return 0;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.c b/drivers/gdisp/ILI9481/gdisp_lld.c
index a70b7c03..06a9e681 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.c
+++ b/drivers/gdisp/ILI9481/gdisp_lld.c
@@ -24,9 +24,11 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_ILI9481
+#include "../drivers/gdisp/ILI9481/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_ILI9481.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -50,14 +52,14 @@
 /*===========================================================================*/
 
 // Some common routines and macros
-#define dummy_read()						{ volatile uint16_t dummy; dummy = read_data(); (void) dummy; }
-#define write_reg(reg, data)				{ write_index(reg); write_data(data); }
-#define write_reg2x16(reg, data1, data2)	{ write_index(reg); write_data((data1)>>8); write_data((uint8_t)(data1)); write_data((data2)>>8); write_data((uint8_t)(data2));}
-
-static void set_viewport(GDISPDriver* g) {
-	write_reg2x16(0x2A, g->p.x, g->p.x + g->p.cx - 1);
-	write_reg2x16(0x2B, g->p.y, g->p.y + g->p.cy - 1);
-	write_index(0x2C);
+#define dummy_read(g)						{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)				{ write_index(g, reg); write_data(g, data); }
+#define write_reg2x16(g, reg, data1, data2)	{ write_index(g, reg); write_data(g, (data1)>>8); write_data(g, (uint8_t)(data1)); write_data(g, (data2)>>8); write_data(g, (uint8_t)(data2));}
+
+static void set_viewport(GDisplay* g) {
+	write_reg2x16(g, 0x2A, g->p.x, g->p.x + g->p.cx - 1);
+	write_reg2x16(g, 0x2B, g->p.y, g->p.y + g->p.cy - 1);
+	write_index(g, 0x2C);
 }
 
 /*===========================================================================*/
@@ -68,124 +70,127 @@ static void set_viewport(GDISPDriver* g) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 	/* Initialise your display */
-	init_board();
+	init_board(g, display);
 
 	/* Hardware reset */
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	gfxSleepMilliseconds(20);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	gfxSleepMilliseconds(20);
 
 	/* Get the bus for the following initialisation commands */
-	acquire_bus();
+	acquire_bus(g);
 
 	/* Enable Access to all Manufacturer commands (0xB0 and higher opcodes) */
-	write_reg(0xB0, 0x00);
+	write_reg(g, 0xB0, 0x00);
 
 	/* Frame Memory Access and Interface Setting */
-	write_index(0xB3);
-	write_data(0x02);
-	write_data(0x00);
-	write_data(0x00);
-	write_data(0x10);
+	write_index(g, 0xB3);
+	write_data(g, 0x02);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x10);
 
 	/* Display Mode and Frame Memory Write Mode Setting (B4h) */
 	/* Use internal clock for synchronization */
 	/* Use DBI interface (only DB0-17, no HSYNC, VSYNC or CLK) */
-	write_reg(0xB4, 0x00);
+	write_reg(g, 0xB4, 0x00);
 
 	/* Internal Backlight Control */
-/*	write_index(0xB9); 	/*PWM Settings for Brightness Control */
-/*	write_data(0x01);	/* Disabled by default. */
-/*	write_data(0xFF);	/*0xFF = Max brightness */
-/*	write_data(0xFF);
-/*	write_data(0x18);
+/*	write_index(g, 0xB9); 	// PWM Settings for Brightness Control
+	write_data(g, 0x01);	// Disabled by default.
+	write_data(g, 0xFF);	// 0xFF = Max brightness
+	write_data(g, 0xFF);
+	write_data(g, 0x18); */
 
 	/* Panel Driving settings */
-	write_index(0xC0);
-	write_data(0x03);
-	write_data(0x3B);
-	write_data(0x00);
-	write_data(0x00);
-	write_data(0x00);
-	write_data(0x01);
-	write_data(0x00);	/* NW */
-	write_data(0x43);
+	write_index(g, 0xC0);
+	write_data(g, 0x03);
+	write_data(g, 0x3B);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x01);
+	write_data(g, 0x00);	/* NW */
+	write_data(g, 0x43);
 
 	/* Display timings in Operating Mode */
-	write_index(0xC1);
-	write_data(0x08);
-	write_data(0x15);	/* CLOCK */
-	write_data(0x08);
-	write_data(0x08);
+	write_index(g, 0xC1);
+	write_data(g, 0x08);
+	write_data(g, 0x15);	/* CLOCK */
+	write_data(g, 0x08);
+	write_data(g, 0x08);
 
 	/* S/VCOM/Gate Driving timing setting */
-	write_index(0xC4);
-	write_data(0x15);
-	write_data(0x03);
-	write_data(0x03);
-	write_data(0x01);
+	write_index(g, 0xC4);
+	write_data(g, 0x15);
+	write_data(g, 0x03);
+	write_data(g, 0x03);
+	write_data(g, 0x01);
 
 	/* Interface Setting */
-	write_reg(0xC6, 0x02);
+	write_reg(g, 0xC6, 0x02);
 
 	/* Gamma Setting - should be changed if using a different panel */
-	write_index(0xC8);
-	write_data(0x0C);
-	write_data(0x05);
-	write_data(0x0A); /*0X12 */
-	write_data(0x6B); /*0x7D */
-	write_data(0x04);
-	write_data(0x06); /*0x08 */
-	write_data(0x15); /*0x0A */
-	write_data(0x10);
-	write_data(0x00);
-	write_data(0x60); /*0x23 */
+	write_index(g, 0xC8);
+	write_data(g, 0x0C);
+	write_data(g, 0x05);
+	write_data(g, 0x0A); /*0X12 */
+	write_data(g, 0x6B); /*0x7D */
+	write_data(g, 0x04);
+	write_data(g, 0x06); /*0x08 */
+	write_data(g, 0x15); /*0x0A */
+	write_data(g, 0x10);
+	write_data(g, 0x00);
+	write_data(g, 0x60); /*0x23 */
 
 	/* Address Mode setting */
-	write_reg(0x36, 0x00);
+	write_reg(g, 0x36, 0x00);
 
 	/* Set Pixel Format = 16 bits per pixel */
 	/* The driver supports upto 24 bits per pixel, with dither */
-	write_reg(0x3A, 0x55);
+	write_reg(g, 0x3A, 0x55);
 
 	/* Exit Idle Mode */
-	write_index(0x38);
+	write_index(g, 0x38);
 
 	/* Power Setting */
-	write_index(0xD0);
-	write_data(0x07);
-	write_data(0x07); 	/* VCI = VCI1 */
-	write_data(0x14);	/* VRH 0x1D */
-	write_data(0xA2);	/* BT 0x06 */
+	write_index(g, 0xD0);
+	write_data(g, 0x07);
+	write_data(g, 0x07); 	/* VCI = VCI1 */
+	write_data(g, 0x14);	/* VRH 0x1D */
+	write_data(g, 0xA2);	/* BT 0x06 */
 
 	/* VCOM Setting */
-	write_index(0xD1);
-	write_data(0x03);
-	write_data(0x5A);	/* VCM  0x5A */
-	write_data(0x10);	/* VDV */
+	write_index(g, 0xD1);
+	write_data(g, 0x03);
+	write_data(g, 0x5A);	/* VCM  0x5A */
+	write_data(g, 0x10);	/* VDV */
 
 	/* Power Setting for Normal Mode  */
-	write_index(0xD2);
-	write_data(0x03);
-	write_data(0x04);	/* 0x24  */
-	write_data(0x04);
+	write_index(g, 0xD2);
+	write_data(g, 0x03);
+	write_data(g, 0x04);	/* 0x24  */
+	write_data(g, 0x04);
 
 	/* Exit Sleep Mode */
-	write_index(0x11);
+	write_index(g, 0x11);
 	gfxSleepMilliseconds(150);
 
 	/* Display ON  */
-	write_index(0x29);
+	write_index(g, 0x29);
 	gfxSleepMilliseconds(30);
 
- 	/* Release the bus */
-	release_bus();
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(g);
 	
 	/* Turn on the back-light */
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
 	/* Initialise the GDISP structure */
 	g->g.Width = GDISP_SCREEN_WIDTH;
@@ -198,57 +203,57 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
-		write_data(g->p.color);
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
-		release_bus();
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDISPDriver *g) {
-		acquire_bus();
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
 		set_viewport(g);
-		setreadmode();
-		dummy_read();
+		setreadmode(g);
+		dummy_read(g);
 	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDISPDriver *g) {
-		return read_data();
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
 	}
-	LLDSPEC	void gdisp_lld_read_stop(GDISPDriver *g) {
-		setwritemode();
-		release_bus();
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	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();
-				write_reg(0x0010, 0x0001);	/* enter sleep mode */
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
+				release_bus(g);
 				break;
 			case powerOn:
-				acquire_bus();
-				write_reg(0x0010, 0x0000);	/* leave sleep mode */
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
+				release_bus(g);
 				if (g->g.Powermode != powerSleep)
 					gdisp_lld_init();
 				break;
 			case powerSleep:
-				acquire_bus();
-				write_reg(0x0010, 0x0001);	/* enter sleep mode */
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
+				release_bus(g);
 				break;
 			default:
 				return;
@@ -261,42 +266,42 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				return;
 			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
-				acquire_bus();
+				acquire_bus(g);
 
-				write_reg(0xC0, 0x03);
-				write_reg(0x36, 0x00);	/* X and Y axes non-inverted */
+				write_reg(g, 0xC0, 0x03);
+				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
 
-				release_bus();
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_90:
-				acquire_bus();
+				acquire_bus(g);
 
-				write_reg(0xC0, 0x02);
-				write_reg(0x36, 0x20);	/* Invert X and Y axes */
+				write_reg(g, 0xC0, 0x02);
+				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
 
-				release_bus();
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
-				acquire_bus();
+				acquire_bus(g);
 
-				write_reg(0xC0, 0x06);
-				write_reg(0x36, 0x00);	/* X and Y axes non-inverted */
+				write_reg(g, 0xC0, 0x06);
+				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
 
-				release_bus();
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
-				acquire_bus();
+				acquire_bus(g);
 
-				write_reg(0xC0, 0x07);
-				write_reg(0x36, 0x20);	/* Invert X and Y axes */
+				write_reg(g, 0xC0, 0x07);
+				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
 
-				release_bus();
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.mk b/drivers/gdisp/ILI9481/gdisp_lld.mk
index b0b3f533..6af4d1f8 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9481/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9481/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9481
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9481/gdisp_lld.c
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h b/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
deleted file mode 100644
index 7270cdaf..00000000
--- a/drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9481/gdisp_lld_board_firebullstm32f103.h
- * @brief   GDISP Graphics Driver subsystem low level driver source for
- * 			the ILI9481 and compatible HVGA display
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#define SET_CS		palSetPad(GPIOD, 12);
-#define CLR_CS		palClearPad(GPIOD, 12);
-#define SET_RS		palSetPad(GPIOD, 13);
-#define CLR_RS		palClearPad(GPIOD, 13);
-#define SET_WR		palSetPad(GPIOD, 14);
-#define CLR_WR		palClearPad(GPIOD, 14);
-#define SET_RD		palSetPad(GPIOD, 15);
-#define CLR_RD		palClearPad(GPIOD, 15);
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- *
- * @notapi
- */
-static inline void init_board(void) {
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
-	
-	// Configure the pins to a well know state
-	SET_RS;
-	SET_RD;
-	SET_WR;
-	CLR_CS;
-}
-
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	(void) state;
-	/* Nothing to do here - reset pin tied to Vcc */
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	(void) percent;
-	/* Nothing to do here - Backlight always on */
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-	palWritePort(GPIOE, index);
-	CLR_RS; CLR_WR; SET_WR; SET_RS;
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	palWritePort(GPIOE, data);
-	CLR_WR; SET_WR;
-}
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-	// change pin mode back to digital output
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	uint16_t	value;
-	
-	CLR_RD;
-	value = palReadPort(GPIOE);
-	SET_RD;
-	
-	return value;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_board_template.h b/drivers/gdisp/ILI9481/gdisp_lld_board_template.h
deleted file mode 100644
index e35f0c27..00000000
--- a/drivers/gdisp/ILI9481/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9481/gdisp_lld_board_template.h
- * @brief   GDISP Graphics Driver subsystem low level driver source for
- * 			the ILI9481 and compatible HVGA display
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Initialise the board for the display.
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-/**
- * @brief   Set the bus in read mode
- *
- * @notapi
- */
-static inline void setreadmode(void) {
-
-}
-
-/**
- * @brief   Set the bus back into write mode
- *
- * @notapi
- */
-static inline void setwritemode(void) {
-
-}
-
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_config.h b/drivers/gdisp/ILI9481/gdisp_lld_config.h
index c41edd6b..4a33d110 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9481/gdisp_lld_config.h
@@ -23,9 +23,6 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"ILI9481"
-#define GDISP_DRIVER_STRUCT				GDISP_ILI9481
-
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
-- 
cgit v1.2.3


From 87a6af81f4edd9f638238d785aae716749a7fc13 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 15:36:05 +1000
Subject: Change to gdisp low level driver API. Display number is now in the
 GDriver structure (It was required for a Nokia driver).

---
 .../gdisp/HX8347D/board_HX8347D_stm32f4discovery.h | 11 ++++------
 drivers/gdisp/HX8347D/board_HX8347D_template.h     |  4 +---
 drivers/gdisp/HX8347D/gdisp_lld.c                  |  4 ++--
 .../ILI9320/board_ILI9320_olimex_pic32mx_lcd.h     | 11 ++++------
 .../gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h | 11 ++++------
 drivers/gdisp/ILI9320/board_ILI9320_template.h     |  4 +---
 drivers/gdisp/ILI9320/gdisp_lld.c                  |  4 ++--
 .../gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h    | 11 ++++------
 drivers/gdisp/ILI9325/board_ILI9325_template.h     |  4 +---
 drivers/gdisp/ILI9325/gdisp_lld.c                  |  4 ++--
 .../ILI9481/board_ILI9481_firebullstm32f103.h      | 10 ++++-----
 drivers/gdisp/ILI9481/board_ILI9481_template.h     |  4 +---
 drivers/gdisp/ILI9481/gdisp_lld.c                  |  4 ++--
 drivers/gdisp/RA8875/board_RA8875_marlin.h         | 11 ++++------
 drivers/gdisp/RA8875/board_RA8875_template.h       | 25 ++++++++++++----------
 drivers/gdisp/RA8875/gdisp_lld.c                   |  4 ++--
 .../SSD1289/board_SSD1289_firebullstm32f103.h      | 10 ++++-----
 .../gdisp/SSD1289/board_SSD1289_stm32f4discovery.h |  9 ++++----
 drivers/gdisp/SSD1289/board_SSD1289_template.h     |  4 +---
 drivers/gdisp/SSD1289/gdisp_lld.c                  |  4 ++--
 drivers/multiple/Win32/gdisp_lld.c                 | 10 ++++-----
 drivers/multiple/X/gdisp_lld.c                     |  4 ++--
 22 files changed, 70 insertions(+), 97 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
index 4899baa5..daabe75d 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
@@ -64,17 +64,13 @@ static const SPIConfig spi1cfg_16bit = {
 	SPI_CR1_DFF //SPI_CR1_BR_0
 };
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
-
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		/* Display backlight control */
 		/* TIM4 is an alternate function 2 (AF2) */
 		pwmStart(&PWMD4, &pwmcfg);
@@ -96,6 +92,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* SCK.     */
 		palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));										/* MISO.    */
 		palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* MOSI.    */
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/HX8347D/board_HX8347D_template.h b/drivers/gdisp/HX8347D/board_HX8347D_template.h
index 528fb027..58fd9338 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_template.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_template.h
@@ -20,16 +20,14 @@
  * @brief   Initialise the board for the display.
  *
  * @param[in] g			The GDisplay structure
- * @param[in] display	The display number on this controller (0..n)
  *
  * @note	Set the g->priv member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
  */
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 	(void) g;
-	(void) display;
 }
 
 /**
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
index 19d1b822..8cdbb781 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.c
+++ b/drivers/gdisp/HX8347D/gdisp_lld.c
@@ -61,9 +61,9 @@ static inline void set_viewport(GDisplay* g) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise your display */
-	init_board(g, display);
+	init_board(g);
 
 	// Hardware reset
 	setpin_reset(g, TRUE);
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
index 81d493ed..cf101aaf 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
@@ -17,17 +17,13 @@
 #define noinline __attribute__((noinline))
 #endif
 
-static void init_board(GDisplay *g, unsigned display) {
+static void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
-
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		// RST
 		palSetPadMode(IOPORTA, 7, PAL_MODE_OUTPUT);
 		palClearPad(IOPORTA, 7);
@@ -59,6 +55,7 @@ static void init_board(GDisplay *g, unsigned display) {
 		PMCONbits.PMPEN = 1;
 
 		palClearPad(IOPORTA, 9);
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
index df02a716..4738db61 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
@@ -18,17 +18,13 @@
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
-
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		/* FSMC setup for F1 */
 		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
 
@@ -46,6 +42,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		/* Bank1 NOR/SRAM control register configuration
 		 * This is actually not needed as already set by default after reset */
 		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_template.h b/drivers/gdisp/ILI9320/board_ILI9320_template.h
index ead9aee0..4725e1eb 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_template.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_template.h
@@ -20,16 +20,14 @@
  * @brief   Initialise the board for the display.
  *
  * @param[in] g			The GDisplay structure
- * @param[in] display	The display number on this controller (0..n)
  *
  * @note	Set the g->priv member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
  */
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 	(void) g;
-	(void) display;
 }
 
 /**
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index 3747b3d7..d4639617 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -95,11 +95,11 @@ static void set_viewport(GDisplay *g) {
 	}
 }
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	uint16_t cver;
 
 	/* Initialise your display */
-	init_board(g, display);
+	init_board(g);
 
 	/* Hardware reset */
 	setpin_reset(g, TRUE);
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
index 166ebc33..ae9e96fc 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
@@ -31,17 +31,13 @@
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
-
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		/* FSMC setup for F1 */
 		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
 
@@ -61,6 +57,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		/* Bank1 NOR/SRAM control register configuration
 		 * This is actually not needed as already set by default after reset */
 		FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_template.h b/drivers/gdisp/ILI9325/board_ILI9325_template.h
index 7b067293..65ab5704 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_template.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_template.h
@@ -20,16 +20,14 @@
  * @brief   Initialise the board for the display.
  *
  * @param[in] g			The GDisplay structure
- * @param[in] display	The display number on this controller (0..n)
  *
  * @note	Set the g->priv member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
  */
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 	(void) g;
-	(void) display;
 }
 
 /**
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index 42acdc46..8a4b8603 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -96,11 +96,11 @@ static void set_viewport(GDisplay* g) {
 	}
 }
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	uint16_t cver;
 
 	/* Initialise your display */
-	init_board(g, display);
+	init_board(g);
 
 	/* Hardware reset */
 	setpin_reset(g, TRUE);
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
index 6614d578..9933d17b 100644
--- a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
+++ b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
@@ -25,16 +25,13 @@
 #define SET_RD		palSetPad(GPIOD, 15);
 #define CLR_RD		palClearPad(GPIOD, 15);
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
 		palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
 		palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
@@ -46,6 +43,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		SET_RD;
 		SET_WR;
 		CLR_CS;
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_template.h b/drivers/gdisp/ILI9481/board_ILI9481_template.h
index f3f8bbb7..8dcee19c 100644
--- a/drivers/gdisp/ILI9481/board_ILI9481_template.h
+++ b/drivers/gdisp/ILI9481/board_ILI9481_template.h
@@ -21,16 +21,14 @@
  * @brief   Initialise the board for the display.
  *
  * @param[in] g			The GDisplay structure
- * @param[in] display	The display number on this controller (0..n)
  *
  * @note	Set the g->priv member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
  */
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 	(void) g;
-	(void) display;
 }
 
 /**
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.c b/drivers/gdisp/ILI9481/gdisp_lld.c
index 06a9e681..fc00be10 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.c
+++ b/drivers/gdisp/ILI9481/gdisp_lld.c
@@ -70,9 +70,9 @@ static void set_viewport(GDisplay* g) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise your display */
-	init_board(g, display);
+	init_board(g);
 
 	/* Hardware reset */
 	setpin_reset(g, TRUE);
diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
index 95fb7f9d..88523060 100644
--- a/drivers/gdisp/RA8875/board_RA8875_marlin.h
+++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h
@@ -20,17 +20,13 @@
 #define FSMC_BANK				4
 
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
-
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		/* set pins to FSMC mode */
 		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 8) |
 								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
@@ -52,6 +48,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		/* Bank1 NOR/SRAM control register configuration
 		 * This is actually not needed as already set by default after reset */
 		FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/RA8875/board_RA8875_template.h b/drivers/gdisp/RA8875/board_RA8875_template.h
index 564f60c0..32d12de5 100644
--- a/drivers/gdisp/RA8875/board_RA8875_template.h
+++ b/drivers/gdisp/RA8875/board_RA8875_template.h
@@ -20,14 +20,14 @@
  * @brief   Initialise the board for the display.
  *
  * @param[in] g			The GDisplay structure
- * @param[in] display	The display number on this controller (0..n)
  *
  * @note	Set the g->priv member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
  */
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
+	(void) g;
 }
 
 /**
@@ -38,6 +38,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
  * @notapi
  */
 static inline void post_init_board(GDisplay *g) {
+	(void) g;
 }
 
 /**
@@ -49,7 +50,8 @@ static inline void post_init_board(GDisplay *g) {
  * @notapi
  */
 static inline void setpin_reset(GDisplay *g, bool_t state) {
-
+	(void) g;
+	(void) state;
 }
 
 /**
@@ -60,7 +62,7 @@ static inline void setpin_reset(GDisplay *g, bool_t state) {
  * @notapi
  */
 static inline void acquire_bus(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -71,7 +73,7 @@ static inline void acquire_bus(GDisplay *g) {
  * @notapi
  */
 static inline void release_bus(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -83,7 +85,8 @@ static inline void release_bus(GDisplay *g) {
  * @notapi
  */
 static inline void write_index(GDisplay *g, uint16_t index) {
-
+	(void) g;
+	(void) index;
 }
 
 /**
@@ -95,7 +98,8 @@ static inline void write_index(GDisplay *g, uint16_t index) {
  * @notapi
  */
 static inline void write_data(GDisplay *g, uint16_t data) {
-
+	(void) g;
+	(void) data;
 }
 
 /**
@@ -106,7 +110,7 @@ static inline void write_data(GDisplay *g, uint16_t data) {
  * @notapi
  */
 static inline void setreadmode(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -117,7 +121,7 @@ static inline void setreadmode(GDisplay *g) {
  * @notapi
  */
 static inline void setwritemode(GDisplay *g) {
-
+	(void) g;
 }
 
 /**
@@ -132,9 +136,8 @@ static inline void setwritemode(GDisplay *g) {
  * @notapi
  */
 static inline uint16_t read_data(GDisplay *g) {
-
+	(void) g;
 }
 
 #endif /* _GDISP_LLD_BOARD_H */
 /** @} */
-
diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
index 4c146321..6697d9fd 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ b/drivers/gdisp/RA8875/gdisp_lld.c
@@ -106,9 +106,9 @@ static inline void set_backlight(GDisplay* g, uint8_t percent) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise your display */
-	init_board(g, display);
+	init_board(g);
 
 	// Hardware reset
 	setpin_reset(g, TRUE);
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
index df7594f8..338d9799 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
@@ -24,16 +24,13 @@
 #define SET_RD		palSetPad(GPIOD, 15);
 #define CLR_RD		palClearPad(GPIOD, 15);
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
-		/**
-		 * Set up for Display 0
-		 */
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
 		palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
 		palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
@@ -45,6 +42,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		SET_RD;
 		SET_WR;
 		CLR_CS;
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
index 84082089..d1e23c4a 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
@@ -34,16 +34,14 @@ static const PWMConfig pwmcfg = {
   0
 };
 
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
 	g->priv = 0;
 
-	if (display == 0) {
-
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
 		/**
-		 * Set up for Display 0
-		 *
 		 * Performs the following functions:
 		 *		1. initialise the io port used by the display
 		 *		2. initialise the reset pin (initial state not-in-reset)
@@ -95,6 +93,7 @@ static inline void init_board(GDisplay *g, unsigned display) {
 		pwmStart(&PWMD3, &pwmcfg);
 		palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATE(2));
 		pwmEnableChannel(&PWMD3, 2, 100);
+		break;
 	}
 }
 
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_template.h b/drivers/gdisp/SSD1289/board_SSD1289_template.h
index b24789ea..8bef95b9 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_template.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_template.h
@@ -20,16 +20,14 @@
  * @brief   Initialise the board for the display.
  *
  * @param[in] g			The GDisplay structure
- * @param[in] display	The display number on this controller (0..n)
  *
  * @note	Set the g->priv member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
  */
-static inline void init_board(GDisplay *g, unsigned display) {
+static inline void init_board(GDisplay *g) {
 	(void) g;
-	(void) display;
 }
 
 /**
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index dca11d5d..b376083c 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -114,9 +114,9 @@ static void set_viewport(GDisplay* g) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise your display */
-	init_board(g, display);
+	init_board(g);
 
 	// Hardware reset
 	setpin_reset(g, TRUE);
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index dae92821..6c2e7f33 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -381,7 +381,7 @@ static DECLARE_THREAD_FUNCTION(WindowThread, param) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	winPriv	*	priv;
 	char		buf[132];
 
@@ -426,13 +426,13 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 
 	// Turn on toggles for the first GINPUT_TOGGLE_CONFIG_ENTRIES windows
 	#if GINPUT_NEED_TOGGLE
-		if (display < GINPUT_TOGGLE_CONFIG_ENTRIES)
+		if (g->controllerdisplay < GINPUT_TOGGLE_CONFIG_ENTRIES)
 			g->flags |= GDISP_FLG_HASTOGGLE;
 	#endif
 
 	// Only turn on mouse on the first window for now
 	#if GINPUT_NEED_MOUSE
-		if (!display)
+		if (!g->controllerdisplay)
 			g->flags |= GDISP_FLG_HASMOUSE;
 	#endif
 
@@ -443,13 +443,13 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 	g->priv = priv;
 
 	// Create the window in the message thread
-	PostThreadMessage(winThreadId, WM_USER, (WPARAM)display, (LPARAM)g);
+	PostThreadMessage(winThreadId, WM_USER, (WPARAM)g->controllerdisplay, (LPARAM)g);
 
 	// Wait for the window creation to complete (for safety)
 	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
 		Sleep(1);
 
-	sprintf(buf, APP_NAME " - %u", display+1);
+	sprintf(buf, APP_NAME " - %u", g->systemdisplay+1);
 	SetWindowText(priv->hwnd, buf);
 	ShowWindow(priv->hwnd, SW_SHOW);
 	UpdateWindow(priv->hwnd);
diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index fc573c87..188724ed 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -145,7 +145,7 @@ static int FatalXIOError(Display *d) {
 	exit(0);
 }
 
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	XSizeHints				*pSH;
 	XSetWindowAttributes	xa;
 	XTextProperty			WindowTitle;
@@ -208,7 +208,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g, unsigned display) {
 
 	{
 		char					buf[132];
-		sprintf(buf, "uGFX - %u", display+1);
+		sprintf(buf, "uGFX - %u", g->systemdisplay+1);
 		WindowTitleText = buf;
 		XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
 		XSetWMName(dis, priv->win, &WindowTitle);
-- 
cgit v1.2.3


From e9895b5d14714683b1a98f8d24028d94e22b4bb5 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 15:38:00 +1000
Subject: Convert Nokia6610GE12 driver to new format.

---
 .../board_Nokia6610GE12_olimexsam7ex256.h          | 225 ++++++++++++++++++++
 .../Nokia6610GE12/board_Nokia6610GE12_template.h   | 131 ++++++++++++
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c            | 138 ++++++------
 drivers/gdisp/Nokia6610GE12/gdisp_lld.mk           |   5 +-
 .../gdisp_lld_board_olimexsam7ex256.h              | 233 ---------------------
 .../gdisp/Nokia6610GE12/gdisp_lld_board_template.h | 126 -----------
 drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h     |   8 -
 7 files changed, 428 insertions(+), 438 deletions(-)
 create mode 100644 drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
 create mode 100644 drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
 delete mode 100644 drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
 delete mode 100644 drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
new file mode 100644
index 00000000..e0f8e988
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
@@ -0,0 +1,225 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE8/board_Nokia6610GE12_olimexsam7ex256.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+
+// ******************************************************
+// Pointers to AT91SAM7X256 peripheral data structures
+// ******************************************************
+static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
+static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
+static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
+static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
+static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
+
+/* The PWM backlight control is non-linear on this board.
+ * We pick values here that make it look a bit more linear.
+ */
+#define PWM_TOP_VALUE		500
+#define PWM_BOTTOM_VALUE	200
+
+#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
+
+/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
+static const PWMConfig pwmcfg = {
+  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
+  1000,			/* PWM period is 1000 cycles. */
+  NULL,
+  {
+   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
+  },
+};
+
+static bool_t pwmRunning = FALSE;
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		// *********************************************************************************************
+		// InitSpi( )
+		//
+		// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
+		//
+		// I/O ports used:	PA2  = LCD Reset (set to low to reset)
+		//					PA12 = LCD chip select (set to low to select the LCD chip)
+		//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
+		//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+		//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
+		//					PB20 = backlight control (normally PWM control, 1 = full on)
+		//
+		// *********************************************************************************************}
+
+		/* This code should really use the ChibiOS driver for these functions */
+
+		// Pin for backlight
+		pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
+		pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output
+
+		// Reset pin
+		pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
+		pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output
+
+		// CS pin - this seems to be ignored
+		// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
+		// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output
+
+		// Init SPI0
+		// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
+		// BIT12 = PA12 -> SPI0_NPCS0 chip select
+		// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
+		// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+		// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
+		pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+		pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+		pPIOA->PIO_BSR = 0;
+
+		//enable the clock of SPI
+		pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
+
+		// Fixed mode
+		pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
+		pSPI->SPI_CR      = 0x01;               //SPI Enable
+		pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
+		pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
+
+		/* Display backlight control at 100% */
+		pwmRunning = FALSE;
+		palSetPad(IOPORT2, PIOB_LCD_BL);
+		break;
+	}
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if (state)
+		palClearPad(IOPORT1, PIOA_LCD_RESET);
+	else
+		palSetPad(IOPORT1, PIOA_LCD_RESET);
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ * @note	For now 0% turns the backlight off, anything else the backlight is on.
+ *			While the hardware supports PWM backlight control, we are not using it
+ *			yet.
+ *
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+
+	if (percent == 100) {
+		/* Turn the pin on - No PWM */
+		if (pwmRunning) {
+			pwmStop(&PWMD2);
+			pwmRunning = FALSE;
+		}
+		palSetPad(IOPORT2, PIOB_LCD_BL);
+	} else if (percent == 0) {
+		/* Turn the pin off - No PWM */
+		if (pwmRunning) {
+			pwmStop(&PWMD2);
+			pwmRunning = FALSE;
+		}
+		palClearPad(IOPORT2, PIOB_LCD_BL);
+	} else {
+		/* Use the PWM */
+		if (!pwmRunning) {
+			pwmStart(&PWMD2, &pwmcfg);
+			pwmRunning = TRUE;
+		}
+		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
+	}
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+	/* Nothing to do for this board as the LCD is the only device on the SPI port */
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+	// Nothing to do for this board as the LCD is the only device on the SPI port
+}
+
+/**
+ * @brief   Send an 8 bit command to the lcd.
+ *
+ * @param[in] cmd		The command to send
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t cmd) {
+	(void) g;
+
+	// wait for the previous transfer to complete
+	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+	// send the command
+	pSPI->SPI_TDR = cmd & 0xFF;
+}
+
+/**
+ * @brief   Send an 8 bit data to the lcd.
+ *
+ * @param[in] data		The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+
+	// wait for the previous transfer to complete
+	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+	// send the data
+	pSPI->SPI_TDR = data | 0x0100;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
new file mode 100644
index 00000000..b4d39918
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
@@ -0,0 +1,131 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the Nokia6610 GE12 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index c8071917..d190c91a 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -8,14 +8,11 @@
 /**
  * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE12 display.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#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."
@@ -26,9 +23,11 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_Nokia6610GE12
+#include "../drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_Nokia6610GE12.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -70,46 +69,52 @@
 /* Driver local variables.                                                   */
 /*===========================================================================*/
 
-static color_t savecolor;
+static color_t savecolor[GDISP_TOTAL_DISPLAYS];
 
-#define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_ODDBYTE				(GDISP_FLG_DRIVER<<0)
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
 // Some macros just to make reading the code easier
-#define delayms(ms)					gfxSleepMilliseconds(ms)
-#define write_data2(d1, d2)			{ write_data(d1); write_data(d2); }
-#define write_data3(d1, d2, d3)		{ write_data(d1); write_data(d2); write_data(d3); }
-#define write_cmd1(cmd, d1)			{ write_cmd(cmd); write_data(d1); }
-#define write_cmd2(cmd, d1, d2)		{ write_cmd(cmd); write_data2(d1, d2); }
-#define write_cmd3(cmd, d1, d2, d3)	{ write_cmd(cmd); write_data3(d1, d2, d3); }
+#define delayms(ms)						gfxSleepMilliseconds(ms)
+#define write_data2(g, d1, d2)			{ write_data(g, d1); write_data(g, d2); }
+#define write_data3(g, d1, d2, d3)		{ write_data(g, d1); write_data(g, d2); write_data(g, d3); }
+#define write_reg(g, cmd, d1)			{ write_index(g, cmd); write_data(g, d1); }
+#define write_reg2(g, cmd, d1, d2)		{ write_index(g, cmd); write_data2(g, d1, d2); }
+#define write_reg3(g, cmd, d1, d2, d3)	{ write_index(g, cmd); write_data3(g, d1, d2, d3); }
+
+static inline void set_viewport(GDisplay* g) {
+	write_reg2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+	write_reg2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+	write_index(g, RAMWR);
+}
 
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise your display */
-	init_board();
+	init_board(g);
 
 	// Hardware reset
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	delayms(20);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	delayms(20);
 
-	acquire_bus();
-	write_cmd(SLEEPOUT);								// Sleep out
-	write_cmd1(COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
-	write_cmd1(MADCTL, 0x00);							// Memory access controller
-	write_cmd1(SETCON, 127*GDISP_INITIAL_CONTRAST/100-64);			// Write contrast
+	acquire_bus(g);
+	write_index(g, SLEEPOUT);								// Sleep out
+	write_reg(g, COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
+	write_reg(g, MADCTL, 0x00);							// Memory access controller
+	write_reg(g, SETCON, 127*GDISP_INITIAL_CONTRAST/100-64);			// Write contrast
 	delayms(20);
-	release_bus();
+	release_bus(g);
 	
 	/* Turn on the back-light */
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
 	/* Initialise the GDISP structure to match */
 	g->g.Width = GDISP_SCREEN_WIDTH;
@@ -122,34 +127,34 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
-		write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-		write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-		write_cmd(RAMWR);
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
 		g->flags &= ~GDISP_FLG_ODDBYTE;
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			// Write the pair of pixels to the display
-			write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+			write_data3(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF),
+					(((savecolor[g->controllerdisplay] << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
+					(g->p.color & 0xFF));
 			g->flags &= ~GDISP_FLG_ODDBYTE;
 		} else {
-			savecolor = g->p.color;
+			savecolor[g->controllerdisplay] = g->p.color;
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
-			write_data2(((savecolor >> 4) & 0xFF), ((savecolor << 4) & 0xF0));
-			write_cmd(NOP);
+			write_data2(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF), ((savecolor[g->controllerdisplay] << 4) & 0xF0));
+			write_index(g, NOP);
 		}
-		release_bus();
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
 		/* The hardware is capable of supporting...
 		 * 	GDISP_CONTROL_POWER				- supported
 		 * 	GDISP_CONTROL_ORIENTATION		- supported
@@ -162,24 +167,24 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				return;
 			switch((powermode_t)g->p.ptr) {
 			case powerOff:
-				acquire_bus();
-				write_cmd(SLEEPIN);
-				release_bus();
+				acquire_bus(g);
+				write_index(g, SLEEPIN);
+				release_bus(g);
 				break;
 			case powerOn:
-				acquire_bus();
-				write_cmd(SLEEPOUT);
+				acquire_bus(g);
+				write_index(g, SLEEPOUT);
 				delayms(20);
-				write_cmd(NORON);							// Set Normal mode (my)
-				release_bus();
+				write_index(g, NORON);							// Set Normal mode (my)
+				release_bus(g);
 				break;
 			case powerSleep:
-				acquire_bus();
-				write_cmd(SLEEPOUT);
+				acquire_bus(g);
+				write_index(g, SLEEPOUT);
 				delayms(20);
-				write_cmd2(PTLAR, GDISP_SLEEP_POS, GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)
-				write_cmd(PTLON);
-				release_bus();
+				write_reg2(g, PTLAR, GDISP_SLEEP_POS, GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)
+				write_index(g, PTLON);
+				release_bus(g);
 				break;
 			default:
 				return;
@@ -192,30 +197,30 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				return;
 			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
-				acquire_bus();
-				write_cmd1(MADCTL, 0x00);
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0x00);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_90:
-				acquire_bus();
-				write_cmd1(MADCTL, 0xA0);					// MY, MX, V, LAO, RGB, X, X, X
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0xA0);					// MY, MX, V, LAO, RGB, X, X, X
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
-				acquire_bus();
-				write_cmd1(MADCTL, 0xC0);
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0xC0);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
-				acquire_bus();
-				write_cmd1(MADCTL, 0x60);
-				release_bus();
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0x60);
+				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
@@ -227,14 +232,14 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 
 		case GDISP_CONTROL_BACKLIGHT:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
-			set_backlight((unsigned)g->p.ptr);
+			set_backlight(g, (unsigned)g->p.ptr);
 			g->g.Backlight = (unsigned)g->p.ptr;
 			return;
 		case GDISP_CONTROL_CONTRAST:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
-			acquire_bus();
-			write_cmd1(CONTRAST,(unsigned)127*g->p.ptr/100-64);
-			release_bus();
+			acquire_bus(g);
+			write_reg(g, CONTRAST,(unsigned)127*g->p.ptr/100-64);
+			release_bus(g);
 			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
 		}
@@ -242,4 +247,3 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk b/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
index 575d52a3..892665d5 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12
+GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
deleted file mode 100644
index c8215c75..00000000
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_olimexsam7ex256.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/*
- * Set various display properties. These properties mostly depend on the exact controller chip you get.
- * The defaults should work for most controllers.
- */
-//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
-//#define GDISP_SCREEN_WIDTH				130		// The visible display width
-//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
-//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
-//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
-//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
-//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
-
-// ******************************************************
-// Pointers to AT91SAM7X256 peripheral data structures
-// ******************************************************
-static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
-static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
-static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
-static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
-static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
-
-/* The PWM backlight control is non-linear on this board.
- * We pick values here that make it look a bit more linear.
- */
-#define PWM_TOP_VALUE		500
-#define PWM_BOTTOM_VALUE	200
-
-#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
-
-/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
-static const PWMConfig pwmcfg = {
-  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
-  1000,			/* PWM period is 1000 cycles. */
-  NULL,
-  {
-   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
-  },
-};
-
-static bool_t pwmRunning = FALSE;
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the spi port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-	// *********************************************************************************************
-	// InitSpi( )
-	//
-	// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
-	//
-	// I/O ports used:	PA2  = LCD Reset (set to low to reset)
-	//					PA12 = LCD chip select (set to low to select the LCD chip)
-	//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
-	//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-	//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
-	//					PB20 = backlight control (normally PWM control, 1 = full on)
-	//
-	// *********************************************************************************************}
-
-	/* This code should really use the ChibiOS driver for these functions */
-
-	// Pin for backlight
-	pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
-	pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output
-
-	// Reset pin
-	pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
-	pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output
-
-	// CS pin - this seems to be ignored
-	// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
-	// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output
-
-	// Init SPI0
-	// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
-	// BIT12 = PA12 -> SPI0_NPCS0 chip select
-	// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
-	// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-	// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
-	pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-	pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-	pPIOA->PIO_BSR = 0;
-
-	//enable the clock of SPI
-	pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
-
-	// Fixed mode
-	pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
-	pSPI->SPI_CR      = 0x01;               //SPI Enable
-	pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
-	pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
-
-	/* Display backlight control at 100% */
-	pwmRunning = FALSE;
-	palSetPad(IOPORT2, PIOB_LCD_BL);
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	if (state)
-		palClearPad(IOPORT1, PIOA_LCD_RESET);
-	else
-		palSetPad(IOPORT1, PIOA_LCD_RESET);
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @note	For now 0% turns the backlight off, anything else the backlight is on.
- *			While the hardware supports PWM backlight control, we are not using it
- *			yet.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	if (percent == 100) {
-		/* Turn the pin on - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palSetPad(IOPORT2, PIOB_LCD_BL);
-	} else if (percent == 0) {
-		/* Turn the pin off - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palClearPad(IOPORT2, PIOB_LCD_BL);
-	} else {
-		/* Use the PWM */
-		if (!pwmRunning) {
-			pwmStart(&PWMD2, &pwmcfg);
-			pwmRunning = TRUE;
-		}
-		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
-	}
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do for this board as the LCD is the only device on the SPI port */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	// Nothing to do for this board as the LCD is the only device on the SPI port
-}
-
-/**
- * @brief   Send an 8 bit command to the lcd.
- *
- * @param[in] cmd		The command to send
- *
- * @notapi
- */
-static inline void write_cmd(uint16_t cmd) {
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the command
-	pSPI->SPI_TDR = cmd & 0xFF;
-}
-
-/**
- * @brief   Send an 8 bit data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the data
-	pSPI->SPI_TDR = data | 0x0100;
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	#error "gdispNokia6610GE12: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board"
-	return 0;
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
deleted file mode 100644
index d3594434..00000000
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Nokia6610 GE12 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/*
- * Set various display properties. These properties mostly depend on the exact controller chip you get.
- * The defaults should work for most controllers.
- */
-//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
-//#define GDISP_SCREEN_WIDTH				130		// The visible display width
-//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
-//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
-//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
-//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
-//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the spi port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @note	For now 0% turns the backlight off, anything else the backlight is on.
- *			While the hardware supports PWM backlight control, we are not using it
- *			yet.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send an 8 bit command to the lcd.
- *
- * @param[in] cmd		The command to send
- *
- * @notapi
- */
-static inline void write_cmd(uint16_t cmd) {
-
-}
-
-/**
- * @brief   Send an 8 bit data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
index edbf3290..73f505be 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
@@ -22,18 +22,10 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"Nokia6610GE12"
-#define GDISP_DRIVER_STRUCT				GDISP_Nokia6610GE12
-
 #define GDISP_HARDWARE_CONTROL			TRUE
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
-/* This driver supports both packed and unpacked pixel formats and line formats.
- * 	By default we leave these as FALSE.
- */
-#define GDISP_PACKED_PIXELS				FALSE
-#define GDISP_PACKED_LINES				FALSE
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From ad416c32b3558b56c8462dbcadfe1c0520479a1f Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 16:33:13 +1000
Subject: Small fix to the Nokia6610GE12 driver

---
 .../board_Nokia6610GE12_olimexsam7ex256.h          | 47 ++--------------------
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c            |  5 +++
 2 files changed, 9 insertions(+), 43 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
index e0f8e988..7aad94d3 100644
--- a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
@@ -118,13 +118,10 @@ static inline void init_board(GDisplay *g) {
 	}
 }
 
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
 static inline void setpin_reset(GDisplay *g, bool_t state) {
 	(void) g;
 	if (state)
@@ -133,16 +130,6 @@ static inline void setpin_reset(GDisplay *g, bool_t state) {
 		palSetPad(IOPORT1, PIOA_LCD_RESET);
 }
 
-/**
- * @brief   Set the lcd back-light level.
- * @note	For now 0% turns the backlight off, anything else the backlight is on.
- *			While the hardware supports PWM backlight control, we are not using it
- *			yet.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
 static inline void set_backlight(GDisplay *g, uint8_t percent) {
 	(void) g;
 
@@ -170,33 +157,14 @@ static inline void set_backlight(GDisplay *g, uint8_t percent) {
 	}
 }
 
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
 static inline void acquire_bus(GDisplay *g) {
 	(void) g;
-	/* Nothing to do for this board as the LCD is the only device on the SPI port */
 }
 
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
 static inline void release_bus(GDisplay *g) {
 	(void) g;
-	// Nothing to do for this board as the LCD is the only device on the SPI port
 }
 
-/**
- * @brief   Send an 8 bit command to the lcd.
- *
- * @param[in] cmd		The command to send
- *
- * @notapi
- */
 static inline void write_index(GDisplay *g, uint16_t cmd) {
 	(void) g;
 
@@ -206,13 +174,6 @@ static inline void write_index(GDisplay *g, uint16_t cmd) {
 	pSPI->SPI_TDR = cmd & 0xFF;
 }
 
-/**
- * @brief   Send an 8 bit data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
 static inline void write_data(GDisplay *g, uint16_t data) {
 	(void) g;
 
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index d190c91a..9aa5ac53 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -106,11 +106,16 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	delayms(20);
 
 	acquire_bus(g);
+
 	write_index(g, SLEEPOUT);								// Sleep out
 	write_reg(g, COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
 	write_reg(g, MADCTL, 0x00);							// Memory access controller
 	write_reg(g, SETCON, 127*GDISP_INITIAL_CONTRAST/100-64);			// Write contrast
 	delayms(20);
+
+    // Finish Init
+    post_init_board(g);
+
 	release_bus(g);
 	
 	/* Turn on the back-light */
-- 
cgit v1.2.3


From b6986f5b169631fb76c8cb191807321c3ac04f7a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 16:33:56 +1000
Subject: Convert Nokia6610GE8 driver to the new format.

---
 .../board_Nokia6610GE8_olimexsam7ex256.h           | 195 ++++++++++++++
 .../Nokia6610GE8/board_Nokia6610GE8_template.h     | 131 ++++++++++
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             | 284 ++++++++++-----------
 drivers/gdisp/Nokia6610GE8/gdisp_lld.mk            |   5 +-
 .../Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h | 235 -----------------
 .../gdisp/Nokia6610GE8/gdisp_lld_board_template.h  | 128 ----------
 drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h      |  13 +-
 7 files changed, 464 insertions(+), 527 deletions(-)
 create mode 100644 drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
 create mode 100644 drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
 delete mode 100644 drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
 delete mode 100644 drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
new file mode 100644
index 00000000..ebd038d5
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
@@ -0,0 +1,195 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_GE8_BROKEN_CONTROLLER		FALSE	// Uncomment this out if you have a controller thats not window wrap broken.
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_SIZE					32		// The size of the sleep mode partial display
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			38		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+
+// ******************************************************
+// Pointers to AT91SAM7X256 peripheral data structures
+// ******************************************************
+static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
+static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
+static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
+static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
+static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
+
+/* The PWM backlight control is non-linear on this board.
+ * We pick values here that make it look a bit more linear.
+ */
+#define PWM_TOP_VALUE		500
+#define PWM_BOTTOM_VALUE	200
+
+#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
+
+/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
+static const PWMConfig pwmcfg = {
+  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
+  1000,			/* PWM period is 1000 cycles. */
+  NULL,
+  {
+   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
+  },
+};
+
+static bool_t pwmRunning = FALSE;
+
+/**
+ * @brief   Initialise the board for the display.
+ * @notes	Performs the following functions:
+ *			1. initialise the spi port used by your display
+ *			2. initialise the reset pin (initial state not-in-reset)
+ *			3. initialise the chip select pin (initial state not-active)
+ *			4. initialise the backlight pin (initial state back-light off)
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		// *********************************************************************************************
+		// InitSpi( )
+		//
+		// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
+		//
+		// I/O ports used:	PA2  = LCD Reset (set to low to reset)
+		//					PA12 = LCD chip select (set to low to select the LCD chip)
+		//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
+		//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+		//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
+		//					PB20 = backlight control (normally PWM control, 1 = full on)
+		//
+		// *********************************************************************************************}
+
+		/* This code should really use the ChibiOS driver for these functions */
+
+		// Pin for backlight
+		pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
+		pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output
+
+		// Reset pin
+		pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
+		pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output
+
+		// CS pin - this seems to be ignored
+		// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
+		// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output
+
+		// Init SPI0
+		// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
+		// BIT12 = PA12 -> SPI0_NPCS0 chip select
+		// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
+		// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
+		// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
+		pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+		pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
+		pPIOA->PIO_BSR = 0;
+
+		//enable the clock of SPI
+		pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
+
+		// Fixed mode
+		pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
+		pSPI->SPI_CR      = 0x01;               //SPI Enable
+		pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
+		pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
+
+		/* Display backlight control at 100% */
+		pwmRunning = FALSE;
+		palSetPad(IOPORT2, PIOB_LCD_BL);
+		break;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if (state)
+		palClearPad(IOPORT1, PIOA_LCD_RESET);
+	else
+		palSetPad(IOPORT1, PIOA_LCD_RESET);
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	if (percent == 100) {
+		/* Turn the pin on - No PWM */
+		if (pwmRunning) {
+			pwmStop(&PWMD2);
+			pwmRunning = FALSE;
+		}
+		palSetPad(IOPORT2, PIOB_LCD_BL);
+	} else if (percent == 0) {
+		/* Turn the pin off - No PWM */
+		if (pwmRunning) {
+			pwmStop(&PWMD2);
+			pwmRunning = FALSE;
+		}
+		palClearPad(IOPORT2, PIOB_LCD_BL);
+	} else {
+		/* Use the PWM */
+		if (!pwmRunning) {
+			pwmStart(&PWMD2, &pwmcfg);
+			pwmRunning = TRUE;
+		}
+		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
+	}
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	// wait for the previous transfer to complete
+	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+	// send the command
+	pSPI->SPI_TDR = index & 0xFF;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	// wait for the previous transfer to complete
+	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
+	// send the data
+	pSPI->SPI_TDR = data | 0x0100;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
new file mode 100644
index 00000000..93689abc
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
@@ -0,0 +1,131 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the Nokia6610 GE12 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/*
+ * Set various display properties. These properties mostly depend on the exact controller chip you get.
+ * The defaults should work for most controllers.
+ */
+//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
+//#define GDISP_SCREEN_WIDTH				130		// The visible display width
+//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
+//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
+//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
+//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
+//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index d3e30d0e..4906ee78 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -58,9 +58,11 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_LLD_DECLARATIONS
+#define GDISP_DRIVER_VMT			GDISPVMT_Nokia6610GE8
+#include "../drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
-#include "gdisp_lld_board.h"
+
+#include "board_Nokia6610GE8.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -108,9 +110,9 @@
 /*===========================================================================*/
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	static color_t savecolor;
+	static color_t savecolor[GDISP_TOTAL_DISPLAYS];
 	#if GDISP_GE8_BROKEN_CONTROLLER
-		static color_t firstcolor;
+		static color_t firstcolor[GDISP_TOTAL_DISPLAYS];
 	#endif
 #endif
 
@@ -122,57 +124,86 @@
 /*===========================================================================*/
 
 // Some macros just to make reading the code easier
-#define delayms(ms)						gfxSleepMilliseconds(ms)
-#define write_data2(d1, d2)				{ write_data(d1); write_data(d2); }
-#define write_data3(d1, d2, d3)			{ write_data(d1); write_data(d2); write_data(d3); }
-#define write_data4(d1, d2, d3, d4)		{ write_data(d1); write_data(d2); write_data(d3); write_data(d4); }
-#define write_cmd1(cmd, d1)				{ write_cmd(cmd); write_data(d1); }
-#define write_cmd2(cmd, d1, d2)			{ write_cmd(cmd); write_data2(d1, d2); }
-#define write_cmd3(cmd, d1, d2, d3)		{ write_cmd(cmd); write_data3(d1, d2, d3); }
-#define write_cmd4(cmd, d1, d2, d3, d4)	{ write_cmd(cmd); write_data4(d1, d2, d3, d4); }
-
+#define delayms(ms)							gfxSleepMilliseconds(ms)
+#define write_data2(g, d1, d2)				{ write_data(g, d1); write_data(g, d2); }
+#define write_data3(g, d1, d2, d3)			{ write_data(g, d1); write_data(g, d2); write_data(g, d3); }
+#define write_data4(g, d1, d2, d3, d4)		{ write_data(g, d1); write_data(g, d2); write_data(g, d3); write_data(g, d4); }
+#define write_cmd1(g, cmd, d1)				{ write_index(g, cmd); write_data(g, d1); }
+#define write_cmd2(g, cmd, d1, d2)			{ write_index(g, cmd); write_data2(g, d1, d2); }
+#define write_cmd3(g, cmd, d1, d2, d3)		{ write_index(g, cmd); write_data3(g, d1, d2, d3); }
+#define write_cmd4(g, cmd, d1, d2, d3, d4)	{ write_index(g, cmd); write_data4(g, d1, d2, d3, d4); }
+
+static inline void set_viewport(GDisplay* g) {
+	#if GDISP_NOKIA_ORIENTATION && GDISP_NEED_CONTROL
+		switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x);			// Column address set
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y);			// Page address set
+				break;
+			case GDISP_ROTATE_90:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y);
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x);
+				break;
+			case GDISP_ROTATE_180:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x);
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y);
+				break;
+			case GDISP_ROTATE_270:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y);
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x);
+				break;
+		}
+	#else
+		write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+		write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+	#endif
+	write_index(g, RAMWR);
+}
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise your display */
-	init_board();
+	init_board(g);
 
 	// Hardware reset
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	delayms(20);
-	setpin_reset(FALSE);
+	setpin_reset(g, FALSE);
 	delayms(20);
 
 	// Get the bus for the following initialisation commands
-	acquire_bus();
+	acquire_bus(g);
 	
-	write_cmd4(DISCTL, 0x00, GDISP_SCAN_LINES/4-1, 0x0A, 0x00);	// Display control - How the controller drives the LCD
+	write_cmd4(g, DISCTL, 0x00, GDISP_SCAN_LINES/4-1, 0x0A, 0x00);	// Display control - How the controller drives the LCD
 															// P1: 0x00 = 2 divisions, switching period=8 (default)
 															// P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
 															// P3: 0x0A = standard inverse highlight, inversion every frame
 															// P4: 0x00 = dispersion on
-	write_cmd1(COMSCN, 0x01);							// COM scan - How the LCD is connected to the controller
+	write_cmd1(g, COMSCN, 0x01);							// COM scan - How the LCD is connected to the controller
 															// P1: 0x01 = Scan 1->80, 160<-81
-	write_cmd(OSCON);									// Internal oscillator ON
-	write_cmd(SLPOUT);									// Sleep out
-	write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-	write_cmd3(DATCTL, 0x00, 0x00, 0x02);				// Data control
+	write_index(g, OSCON);									// Internal oscillator ON
+	write_index(g, SLPOUT);									// Sleep out
+	write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+	write_cmd3(g, DATCTL, 0x00, 0x00, 0x02);				// Data control
 															// P1: 0x00 = page address normal, column address normal, address scan in column direction
 															// P2: 0x00 = RGB sequence (default value)
 															// P3: 0x02 = 4 bits per colour (Type A)
-	write_cmd2(VOLCTR, 63*GDISP_INITIAL_CONTRAST/100, 0x03);	// Voltage control (contrast setting)
+	write_cmd2(g, VOLCTR, 63*GDISP_INITIAL_CONTRAST/100, 0x03);	// Voltage control (contrast setting)
 															// P1 = Contrast (0..63)
 															// P2 = 3 resistance ratio (only value that works)
 	delayms(100);										// Allow power supply to stabilise
-	write_cmd(DISON);									// Turn on the display
+	write_index(g, DISON);									// Turn on the display
+
+    // Finish Init
+    post_init_board(g);
 
 	// Release the bus
-	release_bus();
+	release_bus(g);
 	
 	/* Turn on the back-light */
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
 	/* Initialise the GDISP structure to match */
 	g->g.Orientation = GDISP_ROTATE_0;
@@ -185,30 +216,30 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 }
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDISPDriver *g) {
-		acquire_bus();
-		write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-		write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-		write_cmd(RAMWR);
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
 		g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
 	}
-	LLDSPEC	void gdisp_lld_write_color(GDISPDriver *g) {
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		#if GDISP_GE8_BROKEN_CONTROLLER
 			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
-				firstcolor = g->p.color;
+				firstcolor[g->controllerdisplay] = g->p.color;
 				g->flags |= GDISP_FLG_RUNBYTE;
 			}
 		#endif
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			// Write the pair of pixels to the display
-			write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+			write_data3(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF),
+					(((savecolor[g->controllerdisplay] << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
+					(g->p.color & 0xFF));
 			g->flags &= ~GDISP_FLG_ODDBYTE;
 		} else {
-			savecolor = g->p.color;
+			savecolor[g->controllerdisplay] = g->p.color;
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
-	LLDSPEC	void gdisp_lld_write_stop(GDISPDriver *g) {
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			#if GDISP_GE8_BROKEN_CONTROLLER
 				/**
@@ -229,80 +260,47 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				 * 	user application uses the streaming calls and then terminates the stream early or after buffer wrap.
 				 * 	Since this is such an unlikely situation we just don't handle it.
 				 */
-				write_data3(((savecolor >> 4) & 0xFF), (((savecolor << 4) & 0xF0)|((firstcolor >> 8) & 0x0F)), (firstcolor & 0xFF));
+				write_data3(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF),
+						(((savecolor[g->controllerdisplay] << 4) & 0xF0)|((firstcolor[g->controllerdisplay] >> 8) & 0x0F)),
+						(firstcolor[g->controllerdisplay] & 0xFF));
 			#else
-				write_data2(((savecolor >> 4) & 0xFF), ((savecolor << 4) & 0xF0));
-				write_cmd(NOP);
+				write_data2(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF), ((savecolor[g->controllerdisplay] << 4) & 0xF0));
+				write_index(g, NOP);
 			#endif
 		}
 
-		release_bus();
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_DRAWPIXEL
-	LLDSPEC void gdisp_lld_draw_pixel(GDISPDriver *g) {
-		acquire_bus();
-		switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x);			// Column address set
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y);			// Page address set
-				break;
-			case GDISP_ROTATE_90:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x);
-				break;
-			case GDISP_ROTATE_180:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y);
-				break;
-			case GDISP_ROTATE_270:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x);
-				break;
-		}
-		write_cmd3(RAMWR, 0, (g->p.color>>8) & 0x0F, g->p.color & 0xFF);
-		release_bus();
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		write_data3(g, 0, (g->p.color>>8) & 0x0F, g->p.color & 0xFF);
+		release_bus(g);
 	}
 #endif
 
 /* ---- Optional Routines ---- */
 
 #if GDISP_HARDWARE_FILLS
-	LLDSPEC void gdisp_lld_fill_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
 		unsigned tuples;
 
 		tuples = (g->p.cx*g->p.cy+1)>>1;	// With an odd sized area we over-print by one pixel.
 											// This extra pixel overwrites the first pixel (harmless as it is the same colour)
 
-		acquire_bus();
-		switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-				break;
-			case GDISP_ROTATE_90:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y+g->p.cy-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-1);
-				break;
-			case GDISP_ROTATE_180:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-1);
-				break;
-			case GDISP_ROTATE_270:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
-				break;
-		}
-		write_cmd(RAMWR);
+		acquire_bus(g);
+		set_viewport(g);
 		while(tuples--)
-			write_data3(((g->p.color >> 4) & 0xFF), (((g->p.color << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
-		release_bus();
+			write_data3(g, ((g->p.color >> 4) & 0xFF), (((g->p.color << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_BITFILLS
-	LLDSPEC void gdisp_lld_blit_area(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
 		coord_t			lg, x, y;
 		color_t			c1, c2;
 		unsigned		tuples;
@@ -318,26 +316,8 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		buffer = (const pixel_t *)g->p.ptr;
 
 		/* Set up the data window to transfer */
-		acquire_bus();
-		switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-				break;
-			case GDISP_ROTATE_90:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y+g->p.cy-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_Y_OFFSET+g->g.Width-g->p.x-1);
-				break;
-			case GDISP_ROTATE_180:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-g->p.cx, GDISP_RAM_X_OFFSET+g->g.Width-g->p.x-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_Y_OFFSET+g->g.Height-g->p.y-1);
-				break;
-			case GDISP_ROTATE_270:
-				write_cmd2(CASET, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-g->p.cy, GDISP_RAM_X_OFFSET+g->g.Height-g->p.y-1);
-				write_cmd2(PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x+g->p.cx-1);
-				break;
-		}
-		write_cmd(RAMWR);
+		acquire_bus(g);
+		set_viewport(g);
 
 		/*
 		 * Due to the way the Nokia6610 handles a decrementing column or page,
@@ -389,7 +369,7 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				}
 
 				/* Write the pair of pixels to the display */
-				write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
 			}
 
 		#else
@@ -445,17 +425,17 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 				}
 
 				/* Write the pair of pixels to the display */
-				write_data3(((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
 			}
 		#endif
 
 		/* All done */
-		release_bus();
+		release_bus(g);
 	}
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDISPDriver *g) {
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
 		/* The hardware is capable of supporting...
 		 * 	GDISP_CONTROL_POWER				- supported
 		 * 	GDISP_CONTROL_ORIENTATION		- supported
@@ -466,96 +446,96 @@ LLDSPEC bool_t gdisp_lld_init(GDISPDriver *g) {
 		case GDISP_CONTROL_POWER:
 			if (g->g.Powermode == (powermode_t)g->p.ptr)
 				return;
-			acquire_bus();
+			acquire_bus(g);
 			switch((powermode_t)g->p.ptr) {
 				case powerOff:
-					set_backlight(0);									// Turn off the backlight
-					write_cmd(DISOFF);									// Turn off the display
-					write_cmd1(PWRCTR, 0x00);							// Power control - all off
-					write_cmd(SLPIN);									// Sleep in
-					write_cmd(OSCOFF);									// Internal oscillator off
+					set_backlight(g, 0);									// Turn off the backlight
+					write_index(g, DISOFF);									// Turn off the display
+					write_cmd1(g, PWRCTR, 0x00);							// Power control - all off
+					write_index(g, SLPIN);									// Sleep in
+					write_index(g, OSCOFF);									// Internal oscillator off
 					break;
 				case powerOn:
-					write_cmd(OSCON);									// Internal oscillator on
-					write_cmd(SLPOUT);									// Sleep out
-					write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
+					write_index(g, OSCON);									// Internal oscillator on
+					write_index(g, SLPOUT);									// Sleep out
+					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
 					delayms(100);										// Allow power supply to stabilise
-					write_cmd(DISON);									// Turn on the display
-					write_cmd(PTLOUT);									// Remove sleep window
-					set_backlight(g->g.Backlight);						// Turn on the backlight
+					write_index(g, DISON);									// Turn on the display
+					write_index(g, PTLOUT);									// Remove sleep window
+					set_backlight(g, g->g.Backlight);						// Turn on the backlight
 					break;
 				case powerSleep:
-					write_cmd(OSCON);									// Internal oscillator on
-					write_cmd(SLPOUT);									// Sleep out
-					write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
+					write_index(g, OSCON);									// Internal oscillator on
+					write_index(g, SLPOUT);									// Sleep out
+					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
 					delayms(100);										// Allow power supply to stabilise
-					write_cmd(DISON);									// Turn on the display
-					write_cmd2(PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
-					set_backlight(g->g.Backlight);						// Turn on the backlight
+					write_index(g, DISON);									// Turn on the display
+					write_cmd2(g, PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
+					set_backlight(g, g->g.Backlight);						// Turn on the backlight
 					break;
 				case powerDeepSleep:
-					write_cmd(OSCON);									// Internal oscillator on
-					write_cmd(SLPOUT);									// Sleep out
-					write_cmd1(PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
+					write_index(g, OSCON);									// Internal oscillator on
+					write_index(g, SLPOUT);									// Sleep out
+					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
 					delayms(100);										// Allow power supply to stabilise
-					write_cmd(DISON);									// Turn on the display
-					write_cmd2(PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
-					set_backlight(0);									// Turn off the backlight
+					write_index(g, DISON);									// Turn on the display
+					write_cmd2(g, PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
+					set_backlight(g, 0);									// Turn off the backlight
 					break;
 				default:
-					release_bus();
+					release_bus(g);
 					return;
 			}
-			release_bus();
+			release_bus(g);
 			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
 		#if GDISP_NOKIA_ORIENTATION
 			case GDISP_CONTROL_ORIENTATION:
 				if (g->g.Orientation == (orientation_t)g->p.ptr)
 					return;
-				acquire_bus();
+				acquire_bus(g);
 				switch((orientation_t)g->p.ptr) {
 				case GDISP_ROTATE_0:
-					write_cmd3(DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
+					write_cmd3(g, DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 				case GDISP_ROTATE_90:
-					write_cmd3(DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
+					write_cmd3(g, DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
 				case GDISP_ROTATE_180:
-					write_cmd3(DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
+					write_cmd3(g, DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
 					g->g.Height = GDISP_SCREEN_HEIGHT;
 					g->g.Width = GDISP_SCREEN_WIDTH;
 					break;
 				case GDISP_ROTATE_270:
-					write_cmd3(DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
+					write_cmd3(g, DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
 					g->g.Height = GDISP_SCREEN_WIDTH;
 					g->g.Width = GDISP_SCREEN_HEIGHT;
 					break;
 				default:
-					release_bus();
+					release_bus(g);
 					return;
 				}
-				release_bus();
+				release_bus(g);
 				g->g.Orientation = (orientation_t)g->p.ptr;
 				return;
 		#endif
 		case GDISP_CONTROL_BACKLIGHT:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
-			set_backlight((unsigned)g->p.ptr);
+			set_backlight(g, (unsigned)g->p.ptr);
 			g->g.Backlight = (unsigned)g->p.ptr;
 			return;
 		case GDISP_CONTROL_CONTRAST:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
-			acquire_bus();
-			write_cmd2(VOLCTR, 63*(unsigned)g->p.ptr/100, 0x03);
-			release_bus();
+			acquire_bus(g);
+			write_cmd2(g, VOLCTR, 63*(unsigned)g->p.ptr/100, 0x03);
+			release_bus(g);
 			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
 		}
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk b/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
index 3e1f1851..28c57fd6 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8
+GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
deleted file mode 100644
index 4eeea62f..00000000
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld_board_olimexsam7ex256.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/*
- * Set various display properties. These properties mostly depend on the exact controller chip you get.
- * The defaults should work for most controllers.
- */
-//#define GDISP_GE8_BROKEN_CONTROLLER		FALSE	// Uncomment this out if you have a controller thats not window wrap broken.
-//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
-//#define GDISP_SCREEN_WIDTH				130		// The visible display width
-//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
-//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
-//#define GDISP_SLEEP_SIZE					32		// The size of the sleep mode partial display
-//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
-//#define GDISP_INITIAL_CONTRAST			38		// The initial contrast percentage
-//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
-
-// ******************************************************
-// Pointers to AT91SAM7X256 peripheral data structures
-// ******************************************************
-static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
-static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
-static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
-static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
-static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
-
-/* The PWM backlight control is non-linear on this board.
- * We pick values here that make it look a bit more linear.
- */
-#define PWM_TOP_VALUE		500
-#define PWM_BOTTOM_VALUE	200
-
-#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
-
-/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
-static const PWMConfig pwmcfg = {
-  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
-  1000,			/* PWM period is 1000 cycles. */
-  NULL,
-  {
-   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
-  },
-};
-
-static bool_t pwmRunning = FALSE;
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the spi port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-	// *********************************************************************************************
-	// InitSpi( )
-	//
-	// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
-	//
-	// I/O ports used:	PA2  = LCD Reset (set to low to reset)
-	//					PA12 = LCD chip select (set to low to select the LCD chip)
-	//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
-	//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-	//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
-	//					PB20 = backlight control (normally PWM control, 1 = full on)
-	//
-	// *********************************************************************************************}
-
-	/* This code should really use the ChibiOS driver for these functions */
-
-	// Pin for backlight
-	pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
-	pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output
-
-	// Reset pin
-	pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
-	pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output
-
-	// CS pin - this seems to be ignored
-	// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
-	// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output
-
-	// Init SPI0
-	// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
-	// BIT12 = PA12 -> SPI0_NPCS0 chip select
-	// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
-	// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-	// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
-	pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-	pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-	pPIOA->PIO_BSR = 0;
-
-	//enable the clock of SPI
-	pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
-
-	// Fixed mode
-	pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
-	pSPI->SPI_CR      = 0x01;               //SPI Enable
-	pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
-	pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
-
-	/* Display backlight control at 100% */
-	pwmRunning = FALSE;
-	palSetPad(IOPORT2, PIOB_LCD_BL);
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	if (state)
-		palClearPad(IOPORT1, PIOA_LCD_RESET);
-	else
-		palSetPad(IOPORT1, PIOA_LCD_RESET);
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @note	For now 0% turns the backlight off, anything else the backlight is on.
- *			While the hardware supports PWM backlight control, we are not using it
- *			yet.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	if (percent == 100) {
-		/* Turn the pin on - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palSetPad(IOPORT2, PIOB_LCD_BL);
-	} else if (percent == 0) {
-		/* Turn the pin off - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palClearPad(IOPORT2, PIOB_LCD_BL);
-	} else {
-		/* Use the PWM */
-		if (!pwmRunning) {
-			pwmStart(&PWMD2, &pwmcfg);
-			pwmRunning = TRUE;
-		}
-		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
-	}
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do for this board as the LCD is the only device on the SPI port */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	// Nothing to do for this board as the LCD is the only device on the SPI port
-}
-
-/**
- * @brief   Send an 8 bit command to the lcd.
- *
- * @param[in] cmd		The command to send
- *
- * @notapi
- */
-static inline void write_cmd(uint16_t cmd) {
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the command
-	pSPI->SPI_TDR = cmd & 0xFF;
-}
-
-/**
- * @brief   Send an 8 bit data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the data
-	pSPI->SPI_TDR = data | 0x0100;
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	#error "gdispNokia6610GE8: GDISP_HARDWARE_READPIXEL and GDISP_HARDWARE_SCROLL are not supported on this board"
-	return pSPI->SPI_RDR;
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
deleted file mode 100644
index 43cc4830..00000000
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Nokia6610 GE8 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/*
- * Set various display properties. These properties mostly depend on the exact controller chip you get.
- * The defaults should work for most controllers.
- */
-//#define GDISP_GE8_BROKEN_CONTROLLER		FALSE	// Uncomment this out if you have a controller thats not window wrap broken.
-//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
-//#define GDISP_SCREEN_WIDTH				130		// The visible display width
-//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
-//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
-//#define GDISP_SLEEP_SIZE					32		// The size of the sleep mode partial display
-//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
-//#define GDISP_INITIAL_CONTRAST			38		// The initial contrast percentage
-//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the spi port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @note	For now 0% turns the backlight off, anything else the backlight is on.
- *			While the hardware supports PWM backlight control, we are not using it
- *			yet.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send an 8 bit command to the lcd.
- *
- * @param[in] cmd		The command to send
- *
- * @notapi
- */
-static inline void write_cmd(uint16_t cmd) {
-
-}
-
-/**
- * @brief   Send an 8 bit data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
index a9e11e03..70a57d12 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -22,9 +22,11 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"Nokia6610GE8"
-#define GDISP_DRIVER_STRUCT				GDISP_Nokia6610GE8
-
+/* This driver has problems with other orientations and requires significantly
+ * extra code to handle them. By default we turn this on (only if the GDISP_NEED_CONTROL
+ * is turned on). If you are worried about code size and don't need orientation support
+ * define GDISP_NOKIA_ORIENTATION as false.
+ */
 #ifndef GDISP_NOKIA_ORIENTATION
 	#define GDISP_NOKIA_ORIENTATION			TRUE
 #endif
@@ -40,11 +42,6 @@
 #endif
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
-/* This driver supports both packed and unpacked pixel formats and line formats.
- * 	By default we leave these as FALSE.
- */
-#define GDISP_PACKED_PIXELS				FALSE
-#define GDISP_PACKED_LINES				FALSE
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From 6ac1710dc5a73c62d2cb4a36cf99525b4ce63c65 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 16:45:01 +1000
Subject: Converted TestStub driver to new format.

---
 drivers/gdisp/TestStub/gdisp_lld.c        | 106 +++++++-----------------------
 drivers/gdisp/TestStub/gdisp_lld.mk       |   5 +-
 drivers/gdisp/TestStub/gdisp_lld_config.h |   8 +--
 3 files changed, 26 insertions(+), 93 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c
index e5167989..f9c421f5 100644
--- a/drivers/gdisp/TestStub/gdisp_lld.c
+++ b/drivers/gdisp/TestStub/gdisp_lld.c
@@ -8,17 +8,15 @@
 /**
  * @file    drivers/gdisp/TestStub/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source (stub).
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_DRIVER_VMT			GDISPVMT_TestStub
+#include "../drivers/gdisp/TestStub/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
 
 #ifndef GDISP_SCREEN_HEIGHT
 	#define GDISP_SCREEN_HEIGHT		128
@@ -26,93 +24,35 @@
 #ifndef GDISP_SCREEN_WIDTH
 	#define GDISP_SCREEN_WIDTH		128
 #endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Initialise the GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOff;
-	GDISP.Backlight = 100;
-	GDISP.Contrast = 50;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
+	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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	(void)x;
-	(void)y;
-	(void)color;
-}
-
-/* ---- Optional Routines ---- */
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The start of the text
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		(void)x;
-		(void)y;
-
-		return 0;
+#if GDISP_HARDWARE_DRAWPIXEL
+	void gdisp_lld_draw_pixel(GDisplay *g) {
+		(void) g;
 	}
 #endif
 
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		(void)x;
-		(void)y;
-		(void)cx;
-		(void)cy;
-		(void)lines;
-		(void)bgcolor;
+#if GDISP_HARDWARE_PIXELREAD
+	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		(void) g;
+		return 0;
 	}
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/gdisp/TestStub/gdisp_lld.mk b/drivers/gdisp/TestStub/gdisp_lld.mk
index 5f35be9d..9394ee9d 100644
--- a/drivers/gdisp/TestStub/gdisp_lld.mk
+++ b/drivers/gdisp/TestStub/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/TestStub/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/TestStub
+GFXSRC += $(GFXLIB)/drivers/gdisp/TestStub/gdisp_lld.c
diff --git a/drivers/gdisp/TestStub/gdisp_lld_config.h b/drivers/gdisp/TestStub/gdisp_lld_config.h
index 38c55992..adb6c8b4 100644
--- a/drivers/gdisp/TestStub/gdisp_lld_config.h
+++ b/drivers/gdisp/TestStub/gdisp_lld_config.h
@@ -22,14 +22,10 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"TestStub"
-
-#define GDISP_HARDWARE_SCROLL			GDISP_NEED_SCROLL
-#define GDISP_HARDWARE_PIXELREAD		GDISP_NEED_PIXELREAD
+#define GDISP_HARDWARE_DRAWPIXEL		TRUE
+#define GDISP_HARDWARE_PIXELREAD		TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-#define GDISP_PACKED_PIXELS				FALSE
-#define GDISP_PACKED_LINES				FALSE
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From 9a8b5b416358bbc95ffdd5b287190f0369908c1a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 17:58:18 +1000
Subject: Fix White spacing

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index b376083c..840a1753 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -178,7 +178,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* Turn on the back-light */
 	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
-   /* Initialise the GDISP structure */
+	/* Initialise the GDISP structure */
 	g->g.Width = GDISP_SCREEN_WIDTH;
 	g->g.Height = GDISP_SCREEN_HEIGHT;
 	g->g.Orientation = GDISP_ROTATE_0;
-- 
cgit v1.2.3


From 929dbabf689ff2ad688dc3a3748faeb3bd351698 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 19 Oct 2013 17:58:57 +1000
Subject: Convert S6D1121 driver to new format

---
 drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h  |  91 +++
 drivers/gdisp/S6D1121/board_S6D1121_template.h     | 154 +++++
 drivers/gdisp/S6D1121/gdisp_lld.c                  | 627 +++++++--------------
 drivers/gdisp/S6D1121/gdisp_lld.mk                 |   5 +-
 .../gdisp/S6D1121/gdisp_lld_board_olimex_e407.h    |  81 ---
 drivers/gdisp/S6D1121/gdisp_lld_board_template.h   | 106 ----
 drivers/gdisp/S6D1121/gdisp_lld_config.h           |  10 +-
 7 files changed, 448 insertions(+), 626 deletions(-)
 create mode 100644 drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
 create mode 100644 drivers/gdisp/S6D1121/board_S6D1121_template.h
 delete mode 100644 drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
 delete mode 100644 drivers/gdisp/S6D1121/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
new file mode 100644
index 00000000..ec367183
--- /dev/null
+++ b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
@@ -0,0 +1,91 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the S6D1121 display
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->priv to that structure.
+#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
+	g->priv = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		/* STM32F4 FSMC init */
+		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+		/* set pins to FSMC mode */
+		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+							(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+							(1 << 13) | (1 << 14) | (1 << 15), 0};
+
+		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+		/* FSMC timing */
+		FSMC_Bank1->BTCR[0+1] = (6) | (10 << 8) | (10 << 16);
+
+		/* Bank1 NOR/SRAM control register configuration */
+		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+		break;
+	}
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return GDISP_RAM;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/S6D1121/board_S6D1121_template.h b/drivers/gdisp/S6D1121/board_S6D1121_template.h
new file mode 100644
index 00000000..41c8b199
--- /dev/null
+++ b/drivers/gdisp/S6D1121/board_S6D1121_template.h
@@ -0,0 +1,154 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/S6D1121/board_S6D1121_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the S6D1121 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return 0;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c
index e570c1e8..8b6a956c 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld.c
+++ b/drivers/gdisp/S6D1121/gdisp_lld.c
@@ -17,13 +17,6 @@
 
 #if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
 #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
@@ -33,525 +26,303 @@
 	#undef GDISP_SCREEN_WIDTH
 #endif
 
-#define GDISP_SCREEN_HEIGHT		320
-#define GDISP_SCREEN_WIDTH		240
+#define GDISP_DRIVER_VMT			GDISPVMT_S6D1121
+#include "../drivers/gdisp/S6D1121/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
 
-#define GDISP_INITIAL_CONTRAST 		50
-#define GDISP_INITIAL_BACKLIGHT 	100
+#include "board_S6D1121.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
 
 /* Some common routines and macros */
-#define write_reg(reg, data)        { write_index(reg); write_data(data); }
-#define stream_start()              write_index(0x0022);
-#define stream_stop()
+#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
 #define delay(us)                   gfxSleepMicroseconds(us)
 #define delayms(ms)                 gfxSleepMilliseconds(ms)
 
-static inline void set_cursor(coord_t x, coord_t y) {
+static inline void set_cursor(GDisplay *g) {
     /* R20h - 8 bit
      * R21h - 9 bit
      */
-    switch(GDISP.Orientation) {
+    switch(g->g.Orientation) {
         case GDISP_ROTATE_0:
-            write_reg(0x0020, x & 0x00FF);
-            write_reg(0x0021, y & 0x01FF);
+            write_reg(g, 0x20, g->p.x & 0x00FF);
+            write_reg(g, 0x21, g->p.y & 0x01FF);
             break;
         case GDISP_ROTATE_90:
-            /* Note X has already been mirrored, so we do it directly */
-            write_reg(0x0020, y & 0x00FF);
-            write_reg(0x0021, x & 0x01FF);
+            write_reg(g, 0x20, g->p.y & 0x00FF);
+            write_reg(g, 0x21, (GDISP_SCREEN_HEIGHT - 1 - g->p.x) & 0x01FF);
             break;
         case GDISP_ROTATE_180:
-            write_reg(0x0020, (GDISP_SCREEN_WIDTH - 1 - x) & 0x00FF);
-            write_reg(0x0021, (GDISP_SCREEN_HEIGHT - 1 - y) & 0x01FF);
+            write_reg(g, 0x20, (GDISP_SCREEN_WIDTH - 1 - g->p.x) & 0x00FF);
+            write_reg(g, 0x21, (GDISP_SCREEN_HEIGHT - 1 - g->p.y) & 0x01FF);
             break;
         case GDISP_ROTATE_270:
-            write_reg(0x0020, (GDISP_SCREEN_WIDTH - 1 - y) & 0x00FF);
-            write_reg(0x0021, (GDISP_SCREEN_HEIGHT - 1 - x) & 0x01FF);
+            write_reg(g, 0x20, (GDISP_SCREEN_WIDTH - 1 - g->p.y) & 0x00FF);
+            write_reg(g, 0x21, g->p.x & 0x01FF);
             break;
-    } 
+    }
+    write_index(g, 0x22);
 }
 
-static inline void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+static inline void set_viewport(GDisplay *g) {
     /* HSA / HEA are 8 bit
      * VSA / VEA are 9 bit
      * use masks 0x00FF and 0x01FF to enforce this
      */
 
-    switch(GDISP.Orientation) {
+    switch(g->g.Orientation) {
         case GDISP_ROTATE_0:
-            write_reg(0x46, (((x + cx - 1) << 8) & 0xFF00 ) | 
-                                      (x & 0x00FF));
-
-            write_reg(0x48, y & 0x01FF);
-            write_reg(0x47, (y + cy - 1) & 0x01FF);
+            write_reg(g, 0x46, (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+            write_reg(g, 0x48, g->p.y & 0x01FF);
+            write_reg(g, 0x47, (g->p.y + g->p.cy - 1) & 0x01FF);
             break;
         case GDISP_ROTATE_90:
-            write_reg(0x46, (((y + cy - 1) << 8) & 0xFF00) |
-                                      (y & 0x00FF));
-
-            write_reg(0x48, x & 0x01FF);
-            write_reg(0x47, (x + cx - 1) & 0x01FF);
+            write_reg(g, 0x46, (((g->p.y + g->p.cy - 1) << 8) & 0xFF00) | (g->p.y & 0x00FF));
+            write_reg(g, 0x48, (GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x01FF);
+            write_reg(g, 0x47, (GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x01FF);
             break;
         case GDISP_ROTATE_180:
-            write_reg(0x46, (((GDISP_SCREEN_WIDTH - x - 1) & 0x00FF) << 8) |
-                                      ((GDISP_SCREEN_WIDTH - (x + cx)) & 0x00FF));
-            write_reg(0x48, (GDISP_SCREEN_HEIGHT - (y + cy)) & 0x01FF);
-            write_reg(0x47, (GDISP_SCREEN_HEIGHT- y - 1) & 0x01FF);
+            write_reg(g, 0x46, (((GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x00FF) << 8) |
+                                      ((GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x00FF));
+            write_reg(g, 0x48, (GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x01FF);
+            write_reg(g, 0x47, (GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x01FF);
             break;
         case GDISP_ROTATE_270:
-            write_reg(0x46, (((GDISP_SCREEN_WIDTH - y - 1) & 0x00FF) << 8) |
-                                      ((GDISP_SCREEN_WIDTH - (y + cy)) & 0x00FF));
-            write_reg(0x48, (GDISP_SCREEN_HEIGHT - (x + cx)) & 0x01FF);
-            write_reg(0x47, (GDISP_SCREEN_HEIGHT - x - 1) & 0x01FF);
+            write_reg(g, 0x46, (((GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x00FF) << 8) |
+                                      ((GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x00FF));
+            write_reg(g, 0x48, g->p.x & 0x01FF);
+            write_reg(g, 0x47, (g->p.x + g->p.cx - 1) & 0x01FF);
             break;
     }   
-
-    set_cursor(x, y);
 }
 
-static inline void reset_viewport(void) {
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-		case GDISP_ROTATE_180:
-			set_viewport(0, 0, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
-			break;
-		case GDISP_ROTATE_90:
-		case GDISP_ROTATE_270:
-			set_viewport(0, 0, GDISP_SCREEN_HEIGHT, GDISP_SCREEN_WIDTH);
-			break;
-	}
-}
-
-bool_t gdisp_lld_init(void) {
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	/* initialize the hardware */
-	init_board();
+	init_board(g);
 
 	/* Hardware reset */
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	delayms(20);
-	setpin_reset(TRUE);
+	setpin_reset(g, TRUE);
 	delayms(20);
 
 	/* Get the bus for the following initialisation commands */
-	acquire_bus();
+	acquire_bus(g);
 
-	write_reg(0x11,0x2004);
-	write_reg(0x13,0xCC00);
-	write_reg(0x15,0x2600);
-	write_reg(0x14,0x252A);
-	write_reg(0x12,0x0033);
-	write_reg(0x13,0xCC04);
+	write_reg(g, 0x11, 0x2004);
+	write_reg(g, 0x13, 0xCC00);
+	write_reg(g, 0x15, 0x2600);
+	write_reg(g, 0x14, 0x252A);
+	write_reg(g, 0x12, 0x0033);
+	write_reg(g, 0x13, 0xCC04);
 
 	delayms(1);
 
-	write_reg(0x13,0xCC06);
+	write_reg(g, 0x13, 0xCC06);
 
 	delayms(1);
 
-	write_reg(0x13,0xCC4F);
+	write_reg(g, 0x13, 0xCC4F);
 
 	delayms(1);
 
-	write_reg(0x13,0x674F);
-	write_reg(0x11,0x2003);
+	write_reg(g, 0x13, 0x674F);
+	write_reg(g, 0x11, 0x2003);
 
 	delayms(1);
 
 	// Gamma Setting
-	write_reg(0x30,0x2609);
-	write_reg(0x31,0x242C);
-	write_reg(0x32,0x1F23);
-	write_reg(0x33,0x2425);
-	write_reg(0x34,0x2226);
-	write_reg(0x35,0x2523);
-	write_reg(0x36,0x1C1A);
-	write_reg(0x37,0x131D);
-	write_reg(0x38,0x0B11);
-	write_reg(0x39,0x1210);
-	write_reg(0x3A,0x1315);
-	write_reg(0x3B,0x3619);
-	write_reg(0x3C,0x0D00);
-	write_reg(0x3D,0x000D);
-
-	write_reg(0x16,0x0007);
-	write_reg(0x02,0x0013);
-	write_reg(0x03,0x0003);
-	write_reg(0x01,0x0127);
+	write_reg(g, 0x30, 0x2609);
+	write_reg(g, 0x31, 0x242C);
+	write_reg(g, 0x32, 0x1F23);
+	write_reg(g, 0x33, 0x2425);
+	write_reg(g, 0x34, 0x2226);
+	write_reg(g, 0x35, 0x2523);
+	write_reg(g, 0x36, 0x1C1A);
+	write_reg(g, 0x37, 0x131D);
+	write_reg(g, 0x38, 0x0B11);
+	write_reg(g, 0x39, 0x1210);
+	write_reg(g, 0x3A, 0x1315);
+	write_reg(g, 0x3B, 0x3619);
+	write_reg(g, 0x3C, 0x0D00);
+	write_reg(g, 0x3D, 0x000D);
+
+	write_reg(g, 0x16, 0x0007);
+	write_reg(g, 0x02, 0x0013);
+	write_reg(g, 0x03, 0x0003);
+	write_reg(g, 0x01, 0x0127);
 
 	delayms(1);
 
-	write_reg(0x08,0x0303);
-	write_reg(0x0A,0x000B);
-	write_reg(0x0B,0x0003);
-	write_reg(0x0C,0x0000);
-	write_reg(0x41,0x0000);
-	write_reg(0x50,0x0000);
-	write_reg(0x60,0x0005);
-	write_reg(0x70,0x000B);
-	write_reg(0x71,0x0000);
-	write_reg(0x78,0x0000);
-	write_reg(0x7A,0x0000);
-	write_reg(0x79,0x0007);
-	write_reg(0x07,0x0051);
+	write_reg(g, 0x08, 0x0303);
+	write_reg(g, 0x0A, 0x000B);
+	write_reg(g, 0x0B, 0x0003);
+	write_reg(g, 0x0C, 0x0000);
+	write_reg(g, 0x41, 0x0000);
+	write_reg(g, 0x50, 0x0000);
+	write_reg(g, 0x60, 0x0005);
+	write_reg(g, 0x70, 0x000B);
+	write_reg(g, 0x71, 0x0000);
+	write_reg(g, 0x78, 0x0000);
+	write_reg(g, 0x7A, 0x0000);
+	write_reg(g, 0x79, 0x0007);
+	write_reg(g, 0x07, 0x0051);
 
 	delayms(1);
 
-	write_reg(0x07,0x0053);
-	write_reg(0x79,0x0000);
-
-	reset_viewport();
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
-
-	/* Now initialise the GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = 100;
-	GDISP.Contrast = 50;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
-	return TRUE;
-}
+	write_reg(g, 0x07,0x0053);
+	write_reg(g, 0x79,0x0000);
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-
-	acquire_bus();
-	set_cursor(x, y);
-	write_reg(0x0022, color);
-	release_bus();
-}
+    // Finish Init
+    post_init_board(g);
 
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Clear the display.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] color    The color of the pixel
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_clear(color_t color) {
-	    unsigned i;
-
-		acquire_bus();
-	    set_cursor(0, 0);
-	    stream_start();
-
-	    for(i = 0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT; i++)
-	    	write_data(color);
-
-	    stream_stop();
-		release_bus();
-	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		unsigned i, area;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
+ 	// Release the bus
+	release_bus(g);
 
-		area = cx*cy;
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-		for(i = 0; i < area; i++)
-			write_data(color);
-		stream_stop();
-		reset_viewport();
-		release_bus();
-	}
-#endif
+	/* Turn on the back-light */
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-		coord_t endx, endy;
-		unsigned lg;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
+	/* 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;
+}
 
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-
-		endx = srcx + cx;
-		endy = y + cy;
-		lg = srccx - cx;
-		buffer += srcx + srcy * srccx;
-		for(; y < endy; y++, buffer += lg)
-			for(x=srcx; x < endx; x++)
-				write_data(*buffer++);
-		stream_stop();
-		reset_viewport();
-		release_bus();
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
 	}
-#endif
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The start of the text
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		/* This routine is marked "DO NOT USE" in the original
-		 *  GLCD driver. We just keep our GDISP_HARDWARE_READPIXEL
-		 *  turned off for now.
-		 */
-		color_t color;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
-
-		aquire_bus();
-		set_cursor(x, y);
-		stream_start();
-
-		color = lld_lcdReadData();
-		color = lld_lcdReadData();
-
-		stream_stop();
-		release_bus();
-
-		return color;
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+		set_cursor(g);
 	}
 #endif
 
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		/* This is marked as "TODO: Test this" in the original GLCD driver.
-		 * For now we just leave the GDISP_HARDWARE_SCROLL off.
-		 */
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, gap, abslines;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		abslines = lines < 0 ? -lines : lines;
-
-		acquire_bus();
-		if (abslines >= cy) {
-			abslines = cy;
-			gap = 0;
-		} else {
-			gap = cy - abslines;
-			for(i = 0; i < gap; i++) {
-				if(lines > 0) {
-					row0 = y + i + lines;
-					row1 = y + i;
-				} else {
-					row0 = (y - i - 1) + lines;
-					row1 = (y - i - 1);
-				}
-
-				/* read row0 into the buffer and then write at row1*/
-				set_viewport(x, row0, cx, 1);
-				lld_lcdReadStreamStart();
-				lld_lcdReadStream(buf, cx);
-				lld_lcdReadStreamStop();
-
-				set_viewport(x, row1, cx, 1);
-				stream_start();
-				write_data(buf, cx);
-				stream_stop();
-			}
-		}
-
-		/* fill the remaining gap */
-		set_viewport(x, lines > 0 ? (y+gap) : y, cx, abslines);
-		stream_start();
-		gap = cx*abslines;
-		for(i = 0; i < gap; i++) write_data(bgcolor);
-		stream_stop();
-		reset_viewport();
-		release_bus();
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
 	}
 #endif
 
-#if GDISP_HARDWARE_CONTROL || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
-		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
-				return;
-			switch((gdisp_powermode_t)value) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
+		#if 0
+			case GDISP_CONTROL_POWER:
+				if (g->g.Powermode == (powermode_t)g->p.ptr)
+					return;
+				switch((powermode_t)g->p.ptr) {
 				case powerOff:
-					/* 	Code here */
-					/* break; */
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
 				case powerOn:
-					/* 	Code here */
-					/* You may need this ---
-						if (GDISP.Powermode != powerSleep)
-							gdisp_lld_init();
-					*/
-					/* break; */
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
 				case powerSleep:
-					/* 	Code here */
-					/* break; */
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
 				default:
 					return;
-			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
-			return;
+				}
+				g->g.Powermode = (powermode_t)g->p.ptr;
+				return;
+		#endif
+
 		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-			switch((gdisp_orientation_t)value) {
+			switch((orientation_t)g->p.ptr) {
 			case GDISP_ROTATE_0:
-				acquire_bus();
-				write_reg(0x0001,0x0127);
-				write_reg(0x03, 0b0011);
-				release_bus();
-
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b0011);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_90:
-				acquire_bus();
-				write_reg(0x0001,0x0027);
-				write_reg(0x0003, 0b1011);
-				release_bus();
-
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b1001);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
-				acquire_bus();
-				write_reg(0x0001,0x0127);
-				write_reg(0x0003, 0b0000);
-				release_bus();
-
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b0000);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
-				acquire_bus();
-				write_reg(0x0001,0x0027);
-				write_reg(0x0003, 0b1000);
-				release_bus();
-
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b1010);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			default:
 				return;
 			}
-			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
+			g->g.Orientation = (orientation_t)value;
 			return;
-/*
-		case GDISP_CONTROL_BACKLIGHT:
-		case GDISP_CONTROL_CONTRAST:
-*/
+
+        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;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
 		}
 	}
 #endif
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.mk b/drivers/gdisp/S6D1121/gdisp_lld.mk
index 07f9c380..f5f067b7 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld.mk
+++ b/drivers/gdisp/S6D1121/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/S6D1121/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/S6D1121
+GFXSRC += $(GFXLIB)/drivers/gdisp/S6D1121/gdisp_lld.c
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h b/drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
deleted file mode 100644
index 0ce843b4..00000000
--- a/drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/S6D1121/gdisp_lld_board_olimex_e407.h
- * @brief   GDISP Graphic Driver subsystem board interface for the S6D1121 display
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
-
-static inline void init_board(void) {
-	int FSMC_Bank = 0;
-
-	/* STM32F4 FSMC init */
-	rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-	/* set pins to FSMC mode */
-	IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
- 						(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-	IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-						(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-	palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-	palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-	/* FSMC timing */
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
-
-	/* Bank1 NOR/SRAM control register configuration */
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;	
-}
-
-static inline void setpin_reset(bool_t state) {
-	(void)state;
-
-	/* Nothing to do here */
-}
-
-static inline void set_backlight(uint8_t percent) {
-	(void)percent;
-
-	/* Nothing to do here */
-}
-
-static inline void acquire_bus(void) {
-	/* Nothing to do here */
-}
-
-static inline void release_bus(void) {
-	/* Nothing to do here */
-}
-
-static inline void write_index(uint16_t index) {
-	GDISP_REG = index;
-}
-
-static inline void write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-static inline uint16_t read_data(void) {
-	return GDISP_RAM;
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_board_template.h b/drivers/gdisp/S6D1121/gdisp_lld_board_template.h
deleted file mode 100644
index f123bd06..00000000
--- a/drivers/gdisp/S6D1121/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/S6D1121/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the S6D1121 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Initialise the board for the display.
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_config.h b/drivers/gdisp/S6D1121/gdisp_lld_config.h
index bace096c..839bbf9d 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld_config.h
+++ b/drivers/gdisp/S6D1121/gdisp_lld_config.h
@@ -22,13 +22,9 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"S6D1121"
-
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			TRUE
-#define GDISP_HARDWARE_PIXELREAD		FALSE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-- 
cgit v1.2.3


From 0b9db701a1d52c8a6d63ca692619b0dde47805d1 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 21 Oct 2013 13:34:55 +1000
Subject: Fix missing case in gdispStreamStop(). Add support for controllers
 that need flushing. Add both automatic and manual flushing (via the
 gdispFlush() method)

---
 drivers/multiple/Win32/gdisp_lld.c        | 9 +++++++++
 drivers/multiple/Win32/gdisp_lld_config.h | 4 ++++
 2 files changed, 13 insertions(+)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 6c2e7f33..011f8e74 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -457,6 +457,15 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	return TRUE;
 }
 
+#if GDISP_HARDWARE_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		winPriv	*	priv;
+
+		priv = g->priv;
+		UpdateWindow(priv->hwnd);
+	}
+#endif
+
 #if GDISP_HARDWARE_DRAWPIXEL
 	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
 		winPriv	*	priv;
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index 5720eaed..f6544eb4 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -22,6 +22,10 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
+// Calling gdispGFlush() is optional for this driver but can be used by the
+//	application to force a display update. eg after streaming.
+
+#define GDISP_HARDWARE_FLUSH			TRUE
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_FILLS			TRUE
 #define GDISP_HARDWARE_PIXELREAD		TRUE
-- 
cgit v1.2.3


From 0535c67eab412e72223bc06a528c5bf7cd4aeb22 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 21 Oct 2013 15:13:10 +1000
Subject: Add support for a driver private area (as well as a board private
 area)

---
 .../gdisp/HX8347D/board_HX8347D_stm32f4discovery.h |  4 +--
 drivers/gdisp/HX8347D/gdisp_lld.c                  |  5 +++-
 .../ILI9320/board_ILI9320_olimex_pic32mx_lcd.h     |  4 +--
 .../gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h |  4 +--
 drivers/gdisp/ILI9320/gdisp_lld.c                  |  5 +++-
 .../gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h    |  4 +--
 drivers/gdisp/ILI9325/gdisp_lld.c                  |  5 +++-
 .../ILI9481/board_ILI9481_firebullstm32f103.h      |  4 +--
 drivers/gdisp/ILI9481/gdisp_lld.c                  |  5 +++-
 .../board_Nokia6610GE12_olimexsam7ex256.h          |  4 +--
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c            | 17 +++++++----
 .../board_Nokia6610GE8_olimexsam7ex256.h           |  4 +--
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             | 35 ++++++++++++++--------
 drivers/gdisp/RA8875/board_RA8875_marlin.h         |  4 +--
 drivers/gdisp/RA8875/gdisp_lld.c                   |  5 +++-
 drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h  |  4 +--
 drivers/gdisp/S6D1121/gdisp_lld.c                  |  5 +++-
 .../SSD1289/board_SSD1289_firebullstm32f103.h      |  4 +--
 .../gdisp/SSD1289/board_SSD1289_stm32f4discovery.h |  4 +--
 drivers/gdisp/SSD1289/gdisp_lld.c                  |  5 +++-
 drivers/gdisp/TestStub/gdisp_lld.c                 |  3 ++
 drivers/multiple/Win32/gdisp_lld.c                 |  1 +
 drivers/multiple/X/gdisp_lld.c                     |  1 +
 23 files changed, 88 insertions(+), 48 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
index daabe75d..708e1a06 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
@@ -66,8 +66,8 @@ static const SPIConfig spi1cfg_16bit = {
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
index 8cdbb781..3851c8e1 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.c
+++ b/drivers/gdisp/HX8347D/gdisp_lld.c
@@ -62,7 +62,10 @@ static inline void set_viewport(GDisplay* g) {
 /*===========================================================================*/
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	// Hardware reset
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
index cf101aaf..5315127b 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
@@ -19,8 +19,8 @@
 
 static void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
index 4738db61..8e79009a 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
@@ -20,8 +20,8 @@
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index d4639617..bf82a88a 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -98,7 +98,10 @@ static void set_viewport(GDisplay *g) {
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	uint16_t cver;
 
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	/* Hardware reset */
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
index ae9e96fc..02949605 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
@@ -33,8 +33,8 @@
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index 8a4b8603..6bb649b1 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -99,7 +99,10 @@ static void set_viewport(GDisplay* g) {
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	uint16_t cver;
 
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	/* Hardware reset */
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
index 9933d17b..52d8afda 100644
--- a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
+++ b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
@@ -27,8 +27,8 @@
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.c b/drivers/gdisp/ILI9481/gdisp_lld.c
index fc00be10..5af12986 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.c
+++ b/drivers/gdisp/ILI9481/gdisp_lld.c
@@ -71,7 +71,10 @@ static void set_viewport(GDisplay* g) {
 /*===========================================================================*/
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	/* Hardware reset */
diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
index 7aad94d3..05a48e47 100644
--- a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
@@ -59,8 +59,8 @@ static bool_t pwmRunning = FALSE;
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index 9aa5ac53..25f26c69 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -69,7 +69,9 @@
 /* Driver local variables.                                                   */
 /*===========================================================================*/
 
-static color_t savecolor[GDISP_TOTAL_DISPLAYS];
+// Use the priv pointer itself to save our color. This save allocating ram for it
+//	and works provided sizeof(color_t) <= sizeof(void *)
+#define savecolor(g)					((color_t)g->priv)
 
 #define GDISP_FLG_ODDBYTE				(GDISP_FLG_DRIVER<<0)
 
@@ -96,7 +98,10 @@ static inline void set_viewport(GDisplay* g) {
 /*===========================================================================*/
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	// Hardware reset
@@ -140,18 +145,18 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			// Write the pair of pixels to the display
-			write_data3(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF),
-					(((savecolor[g->controllerdisplay] << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
+			write_data3(g, ((savecolor(g) >> 4) & 0xFF),
+					(((savecolor(g) << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
 					(g->p.color & 0xFF));
 			g->flags &= ~GDISP_FLG_ODDBYTE;
 		} else {
-			savecolor[g->controllerdisplay] = g->p.color;
+			savecolor(g) = g->p.color;
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
-			write_data2(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF), ((savecolor[g->controllerdisplay] << 4) & 0xF0));
+			write_data2(g, ((savecolor(g) >> 4) & 0xFF), ((savecolor(g) << 4) & 0xF0));
 			write_index(g, NOP);
 		}
 		release_bus(g);
diff --git a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
index ebd038d5..6cbcc5ab 100644
--- a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
@@ -71,8 +71,8 @@ static bool_t pwmRunning = FALSE;
  */
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index 4906ee78..1bc7282a 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -110,10 +110,13 @@
 /*===========================================================================*/
 
 #if GDISP_HARDWARE_STREAM_WRITE
-	static color_t savecolor[GDISP_TOTAL_DISPLAYS];
-	#if GDISP_GE8_BROKEN_CONTROLLER
-		static color_t firstcolor[GDISP_TOTAL_DISPLAYS];
-	#endif
+	typedef struct dvrPriv {
+		color_t			savecolor;
+		#if GDISP_GE8_BROKEN_CONTROLLER
+			color_t		firstcolor;
+		#endif
+	} dvrPriv;
+	#define PRIV		((dvrPriv *)g->priv)
 #endif
 
 #define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
@@ -164,7 +167,13 @@ static inline void set_viewport(GDisplay* g) {
 /*===========================================================================*/
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* Initialise your display */
+	#if GDISP_HARDWARE_STREAM_WRITE
+		g->priv = gfxAlloc(sizeof(dvrPriv));
+	#else
+		g->priv = 0;
+	#endif
+
+	// Initialise the board interface
 	init_board(g);
 
 	// Hardware reset
@@ -224,18 +233,18 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		#if GDISP_GE8_BROKEN_CONTROLLER
 			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
-				firstcolor[g->controllerdisplay] = g->p.color;
+				PRIV->firstcolor = g->p.color;
 				g->flags |= GDISP_FLG_RUNBYTE;
 			}
 		#endif
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			// Write the pair of pixels to the display
-			write_data3(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF),
-					(((savecolor[g->controllerdisplay] << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
+			write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
+					(((PRIV->savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
 					(g->p.color & 0xFF));
 			g->flags &= ~GDISP_FLG_ODDBYTE;
 		} else {
-			savecolor[g->controllerdisplay] = g->p.color;
+			PRIV->savecolor = g->p.color;
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
@@ -260,11 +269,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				 * 	user application uses the streaming calls and then terminates the stream early or after buffer wrap.
 				 * 	Since this is such an unlikely situation we just don't handle it.
 				 */
-				write_data3(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF),
-						(((savecolor[g->controllerdisplay] << 4) & 0xF0)|((firstcolor[g->controllerdisplay] >> 8) & 0x0F)),
-						(firstcolor[g->controllerdisplay] & 0xFF));
+				write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
+						(((PRIV->savecolor << 4) & 0xF0)|((PRIV->firstcolor >> 8) & 0x0F)),
+						(PRIV->firstcolor & 0xFF));
 			#else
-				write_data2(g, ((savecolor[g->controllerdisplay] >> 4) & 0xFF), ((savecolor[g->controllerdisplay] << 4) & 0xF0));
+				write_data2(g, ((PRIV->savecolor >> 4) & 0xFF), ((PRIV->savecolor << 4) & 0xF0));
 				write_index(g, NOP);
 			#endif
 		}
diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
index 88523060..da90d8f3 100644
--- a/drivers/gdisp/RA8875/board_RA8875_marlin.h
+++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h
@@ -22,8 +22,8 @@
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
index 6697d9fd..7916ef3b 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ b/drivers/gdisp/RA8875/gdisp_lld.c
@@ -107,7 +107,10 @@ static inline void set_backlight(GDisplay* g, uint8_t percent) {
 /*===========================================================================*/
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	// Hardware reset
diff --git a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
index ec367183..4f8d2f58 100644
--- a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
+++ b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
@@ -20,8 +20,8 @@
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c
index 8b6a956c..f7e12591 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld.c
+++ b/drivers/gdisp/S6D1121/gdisp_lld.c
@@ -117,7 +117,10 @@ static inline void set_viewport(GDisplay *g) {
 }
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* initialize the hardware */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	/* Hardware reset */
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
index 338d9799..3277a902 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
@@ -26,8 +26,8 @@
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
index d1e23c4a..81ce0512 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
@@ -36,8 +36,8 @@ static const PWMConfig pwmcfg = {
 
 static inline void init_board(GDisplay *g) {
 
-	// As we are not using multiple displays we set g->priv to NULL as we don't use it.
-	g->priv = 0;
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
 
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 840a1753..698d3cfc 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -115,7 +115,10 @@ static void set_viewport(GDisplay* g) {
 /*===========================================================================*/
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* Initialise your display */
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
 	init_board(g);
 
 	// Hardware reset
diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c
index f9c421f5..1a5ad81f 100644
--- a/drivers/gdisp/TestStub/gdisp_lld.c
+++ b/drivers/gdisp/TestStub/gdisp_lld.c
@@ -32,6 +32,9 @@
 #endif
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	/* No board interface and no private driver area */
+	g->priv = g->board = 0;
+
 	/* Initialise the GDISP structure */
 	g->g.Width = GDISP_SCREEN_WIDTH;
 	g->g.Height = GDISP_SCREEN_HEIGHT;
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 011f8e74..3ce50633 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -441,6 +441,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	assert(priv != NULL);
 	memset(priv, 0, sizeof(winPriv));
 	g->priv = priv;
+	g->board = 0;			// no board interface for this controller
 
 	// Create the window in the message thread
 	PostThreadMessage(winThreadId, WM_USER, (WPARAM)g->controllerdisplay, (LPARAM)g);
diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
index 188724ed..c9beb821 100644
--- a/drivers/multiple/X/gdisp_lld.c
+++ b/drivers/multiple/X/gdisp_lld.c
@@ -193,6 +193,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 	g->priv = gfxAlloc(sizeof(xPriv));
 	priv = (xPriv *)g->priv;
+	g->board = 0;					// No board interface for this driver
 
 	xa.colormap = cmap;
 	xa.border_pixel = 0xFFFFFF;
-- 
cgit v1.2.3


From 0698fd28c03e20704376cf6c97f373ba9c5e8c4b Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 21 Oct 2013 17:11:07 +1000
Subject: Comment fixes.

---
 drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h            | 2 +-
 drivers/gdisp/HX8347D/board_HX8347D_template.h                    | 2 +-
 drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h            | 2 +-
 drivers/gdisp/ILI9320/board_ILI9320_template.h                    | 2 +-
 drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h               | 2 +-
 drivers/gdisp/ILI9325/board_ILI9325_template.h                    | 2 +-
 drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h           | 2 +-
 drivers/gdisp/ILI9481/board_ILI9481_template.h                    | 2 +-
 drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h | 2 +-
 drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h        | 2 +-
 drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h   | 2 +-
 drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h          | 2 +-
 drivers/gdisp/RA8875/board_RA8875_marlin.h                        | 2 +-
 drivers/gdisp/RA8875/board_RA8875_template.h                      | 2 +-
 drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h                 | 2 +-
 drivers/gdisp/S6D1121/board_S6D1121_template.h                    | 2 +-
 drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h           | 2 +-
 drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h            | 2 +-
 drivers/gdisp/SSD1289/board_SSD1289_template.h                    | 2 +-
 19 files changed, 19 insertions(+), 19 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
index 708e1a06..df287477 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
@@ -14,7 +14,7 @@
 #define _GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 
 /* Pin assignments */
 #define SET_RST		palSetPad(GPIOB, 8)
diff --git a/drivers/gdisp/HX8347D/board_HX8347D_template.h b/drivers/gdisp/HX8347D/board_HX8347D_template.h
index 58fd9338..57ec75f6 100644
--- a/drivers/gdisp/HX8347D/board_HX8347D_template.h
+++ b/drivers/gdisp/HX8347D/board_HX8347D_template.h
@@ -21,7 +21,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
index 8e79009a..bca5caf8 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
@@ -14,7 +14,7 @@
 #define GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
 
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_template.h b/drivers/gdisp/ILI9320/board_ILI9320_template.h
index 4725e1eb..6f5ad16d 100644
--- a/drivers/gdisp/ILI9320/board_ILI9320_template.h
+++ b/drivers/gdisp/ILI9320/board_ILI9320_template.h
@@ -21,7 +21,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
index 02949605..60508c1a 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
@@ -27,7 +27,7 @@
 #define GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
 
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_template.h b/drivers/gdisp/ILI9325/board_ILI9325_template.h
index 65ab5704..07c2fdee 100644
--- a/drivers/gdisp/ILI9325/board_ILI9325_template.h
+++ b/drivers/gdisp/ILI9325/board_ILI9325_template.h
@@ -21,7 +21,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
index 52d8afda..17bc554d 100644
--- a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
+++ b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
@@ -15,7 +15,7 @@
 #define _GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define SET_CS		palSetPad(GPIOD, 12);
 #define CLR_CS		palClearPad(GPIOD, 12);
 #define SET_RS		palSetPad(GPIOD, 13);
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_template.h b/drivers/gdisp/ILI9481/board_ILI9481_template.h
index 8dcee19c..7824c936 100644
--- a/drivers/gdisp/ILI9481/board_ILI9481_template.h
+++ b/drivers/gdisp/ILI9481/board_ILI9481_template.h
@@ -22,7 +22,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
index 05a48e47..5b9ff6f6 100644
--- a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
@@ -26,7 +26,7 @@
 //#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 
 // ******************************************************
 // Pointers to AT91SAM7X256 peripheral data structures
diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
index b4d39918..160c9278 100644
--- a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
+++ b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_template.h
@@ -33,7 +33,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
index 6cbcc5ab..12dbc9a5 100644
--- a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
+++ b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
@@ -28,7 +28,7 @@
 //#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 
 // ******************************************************
 // Pointers to AT91SAM7X256 peripheral data structures
diff --git a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
index 93689abc..28fc9f70 100644
--- a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
+++ b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_template.h
@@ -33,7 +33,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
index da90d8f3..e6c19d34 100644
--- a/drivers/gdisp/RA8875/board_RA8875_marlin.h
+++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h
@@ -14,7 +14,7 @@
 #define _GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define GDISP_RAM              (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */
 #define GDISP_REG              (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */
 #define FSMC_BANK				4
diff --git a/drivers/gdisp/RA8875/board_RA8875_template.h b/drivers/gdisp/RA8875/board_RA8875_template.h
index 32d12de5..fce05129 100644
--- a/drivers/gdisp/RA8875/board_RA8875_template.h
+++ b/drivers/gdisp/RA8875/board_RA8875_template.h
@@ -21,7 +21,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
index 4f8d2f58..e0bb8e26 100644
--- a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
+++ b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
@@ -14,7 +14,7 @@
 #define _GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
 #define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
 
diff --git a/drivers/gdisp/S6D1121/board_S6D1121_template.h b/drivers/gdisp/S6D1121/board_S6D1121_template.h
index 41c8b199..04742f56 100644
--- a/drivers/gdisp/S6D1121/board_S6D1121_template.h
+++ b/drivers/gdisp/S6D1121/board_S6D1121_template.h
@@ -21,7 +21,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
index 3277a902..2a7ffe1e 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
@@ -14,7 +14,7 @@
 #define _GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define SET_CS		palSetPad(GPIOD, 12);
 #define CLR_CS		palClearPad(GPIOD, 12);
 #define SET_RS		palSetPad(GPIOD, 13);
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
index 81ce0512..866311dc 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
@@ -14,7 +14,7 @@
 #define _GDISP_LLD_BOARD_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->priv to that structure.
+//	set g->board to that structure.
 #define GDISP_REG              ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
 #define GDISP_RAM              ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
 #define GDISP_DMA_STREAM		STM32_DMA2_STREAM6
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_template.h b/drivers/gdisp/SSD1289/board_SSD1289_template.h
index 8bef95b9..7c9cd757 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_template.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_template.h
@@ -21,7 +21,7 @@
  *
  * @param[in] g			The GDisplay structure
  *
- * @note	Set the g->priv member to whatever is appropriate. For multiple
+ * @note	Set the g->board member to whatever is appropriate. For multiple
  * 			displays this might be a pointer to the appropriate register set.
  *
  * @notapi
-- 
cgit v1.2.3


From 1b3297aeaebdfec5bf8c507ed88445585a0952de Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 21 Oct 2013 17:11:46 +1000
Subject: Fix a bug in Contrast handling in the Nokia drivers

---
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c | 4 ++--
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index 25f26c69..ef8cd043 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -115,7 +115,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	write_index(g, SLEEPOUT);								// Sleep out
 	write_reg(g, COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
 	write_reg(g, MADCTL, 0x00);							// Memory access controller
-	write_reg(g, SETCON, 127*GDISP_INITIAL_CONTRAST/100-64);			// Write contrast
+	write_reg(g, SETCON, 128*GDISP_INITIAL_CONTRAST/101-64);			// Write contrast
 	delayms(20);
 
     // Finish Init
@@ -248,7 +248,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		case GDISP_CONTROL_CONTRAST:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			acquire_bus(g);
-			write_reg(g, CONTRAST,(unsigned)127*g->p.ptr/100-64);
+			write_reg(g, CONTRAST,(unsigned)128*g->p.ptr/101-64);
 			release_bus(g);
 			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index 1bc7282a..f724ee42 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -199,7 +199,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 															// P1: 0x00 = page address normal, column address normal, address scan in column direction
 															// P2: 0x00 = RGB sequence (default value)
 															// P3: 0x02 = 4 bits per colour (Type A)
-	write_cmd2(g, VOLCTR, 63*GDISP_INITIAL_CONTRAST/100, 0x03);	// Voltage control (contrast setting)
+	write_cmd2(g, VOLCTR, 64*GDISP_INITIAL_CONTRAST/101, 0x03);	// Voltage control (contrast setting)
 															// P1 = Contrast (0..63)
 															// P2 = 3 resistance ratio (only value that works)
 	delayms(100);										// Allow power supply to stabilise
@@ -543,7 +543,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		case GDISP_CONTROL_CONTRAST:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			acquire_bus(g);
-			write_cmd2(g, VOLCTR, 63*(unsigned)g->p.ptr/100, 0x03);
+			write_cmd2(g, VOLCTR, 64*(unsigned)g->p.ptr/101, 0x03);
 			release_bus(g);
 			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
-- 
cgit v1.2.3


From f4b9f0bcfeb5a71cf5b46073cc30f6e496c23dc2 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 21 Oct 2013 17:12:48 +1000
Subject: Convert SSD1306 driver to new driver format. This driver requires the
 new flush operation.

---
 drivers/gdisp/SSD1306/board_SSD1306_i2c.h          | 121 ++++
 drivers/gdisp/SSD1306/board_SSD1306_spi.h          | 122 ++++
 drivers/gdisp/SSD1306/board_SSD1306_template.h     | 116 ++++
 drivers/gdisp/SSD1306/gdisp_lld.c                  | 729 +++++----------------
 drivers/gdisp/SSD1306/gdisp_lld.mk                 |   5 +-
 .../gdisp/SSD1306/gdisp_lld_board_example_i2c.h    | 137 ----
 .../gdisp/SSD1306/gdisp_lld_board_example_spi.h    | 139 ----
 drivers/gdisp/SSD1306/gdisp_lld_board_template.h   |  74 ---
 drivers/gdisp/SSD1306/gdisp_lld_config.h           |  14 +-
 9 files changed, 520 insertions(+), 937 deletions(-)
 create mode 100644 drivers/gdisp/SSD1306/board_SSD1306_i2c.h
 create mode 100644 drivers/gdisp/SSD1306/board_SSD1306_spi.h
 create mode 100644 drivers/gdisp/SSD1306/board_SSD1306_template.h
 delete mode 100644 drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h
 delete mode 100644 drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h
 delete mode 100644 drivers/gdisp/SSD1306/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
new file mode 100644
index 00000000..c89562e0
--- /dev/null
+++ b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
@@ -0,0 +1,121 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1306/board_SSD1306_i2c.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1306 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#define GDISP_BUS_MAX_TRANSFER_SIZE		64
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->board to that structure.
+#define SSD1306_RESET_PORT		GPIOB
+#define SSD1306_RESET_PIN		5
+
+/**
+ * The default slave address is 0x3D, (talking about
+ * only the real address part here) and the slave
+ * address can be changed to 0x3C by soldering the
+ * SA0 pads on the bottom side of the module.
+ *
+ * b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
+ * --------------------------------------
+ * 0  | 1  | 1  | 1  | 1  | 0  |SA0 | R/W
+ */
+#define SSD1306_I2C_ADDRESS   	0x3D
+#define SSD1306_SDA_PORT		GPIOB
+#define SSD1306_SDA_PIN			7
+#define SSD1306_SCL_PORT		GPIOB
+#define SSD1306_SCL_PIN			6
+#define SET_RST					palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
+#define CLR_RST					palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
+
+// I2C configuration structure.
+static I2CConfig i2cconfig;
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		// RESET pin.
+		palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
+
+
+		/*
+		 * Initializes the I2C driver 1. The I2C1 signals are routed as follows:
+		 * PB6 - SCL.
+		 * PB7 - SDA.
+		 * Timing value comes from ST I2C config tool (xls):
+		 * 0x00901D2B;		// 100kHz Standard Mode
+		 * 0x00300444;		// 100kHz Fast Mode
+		 * 0x0030020A;		// 400kHz Fast Mode
+		 * 0x00100002;		// 800kHz Fast Mode +
+		 */
+		i2cconfig.timingr = 0x00100002;		// 800kHz Fast Mode+
+		i2cInit();
+		palSetPadMode(SSD1306_SCL_PORT, SSD1306_SCL_PIN, PAL_MODE_ALTERNATE(1));
+		palSetPadMode(SSD1306_SDA_PORT, SSD1306_SDA_PIN, PAL_MODE_ALTERNATE(1));
+		break;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if(state)
+		CLR_RST
+	else
+		SET_RST
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+	i2cAcquireBus(&I2CD1);
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+	i2cReleaseBus(&I2CD1);
+}
+
+static inline void write_cmd(GDisplay *g, uint8_t cmd) {
+	uint8_t command[2];
+	(void) g;
+
+	command[0] = 0x00;		// Co = 0, D/C = 0
+	command[1] = cmd;
+
+	i2cStart(&I2CD1, &i2cconfig);
+	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 2, NULL, 0, MS2ST(10));
+	i2cStop(&I2CD1);
+}
+
+static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
+	uint8_t command[1];
+	(void) g;
+
+	command[0] = 0x40; 		// Co = 0, D/C = 1
+
+	i2cStart(&I2CD1, &i2cconfig);
+	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 1, NULL, 0, MS2ST(10));
+	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, data, NULL, length, MS2ST(10));
+	i2cStop(&I2CD1);
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+
+
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_spi.h b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
new file mode 100644
index 00000000..e206a517
--- /dev/null
+++ b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
@@ -0,0 +1,122 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1306/board_SSD1306_spi.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1306 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#define GDISP_BUS_MAX_TRANSFER_SIZE		64
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->board to that structure.
+#define SSD1306_RESET_PORT		GPIOB
+#define SSD1306_RESET_PIN		5
+#define SSD1306_MISO_PORT		GPIOB
+#define SSD1306_MISO_PIN		8
+#define SSD1306_MOSI_PORT		GPIOB
+#define SSD1306_MOSI_PIN		7
+#define SSD1306_SCK_PORT		GPIOB
+#define SSD1306_SCK_PIN			6
+#define SSD1306_CS_PORT			GPIOB
+#define SSD1306_CS_PIN			5
+#define SET_RST					palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
+#define CLR_RST					palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
+
+/*
+ * SPI1 configuration structure.
+ * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
+ * The slave select line is the pin 4 on the port GPIOA.
+ */
+static const SPIConfig spi1config = {
+	NULL,
+	/* HW dependent part.*/
+	SSD1306_MISO_PORT,
+	SSD1306_MISO_PIN,
+	0
+	//SPI_CR1_BR_0
+};
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		// RESET pin.
+		palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
+
+		spiInit();
+		palSetPadMode(SSD1306_MISO_PORT, SSD1306_MISO_PIN, 	PAL_MODE_ALTERNATE(1)|
+															PAL_STM32_OSPEED_HIGHEST);
+		palSetPadMode(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN, 	PAL_MODE_ALTERNATE(1)|
+															PAL_STM32_OSPEED_HIGHEST);
+		palSetPadMode(SSD1306_SCK_PORT,  SSD1306_SCK_PIN,  	PAL_MODE_ALTERNATE(1)|
+															PAL_STM32_OSPEED_HIGHEST);
+		palSetPad(SSD1306_CS_PORT, SSD1306_CS_PIN);
+		palSetPadMode(SSD1306_CS_PORT,   SSD1306_CS_PIN,   	PAL_MODE_ALTERNATE(1)|
+															PAL_STM32_OSPEED_HIGHEST);
+		break;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if(state)
+		CLR_RST
+	else
+		SET_RST
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+	spiAcquireBus(&SPID1);
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+	spiReleaseBus(&SPID1);
+}
+
+static inline void write_cmd(GDisplay *g, uint8_t cmd) {
+	uint8_t command[2];
+
+	command[0] = 0x00;		// Co = 0, D/C = 0
+	command[1] = cmd;
+
+	spiStart(&SPID1, &spi1config);
+	spiSelect(&SPID1);
+	spiStartSend(&SPID1, 2, command);
+	spiUnselect(&SPID1);
+	spiStop(&SPID1);
+}
+
+static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
+	uint8_t command[1];
+	(void) g;
+
+	command[0] = 0x40; 		// Co = 0, D/C = 1
+
+	spiStart(&SPID1, &spi1config);
+	spiSelect(&SPID1);
+	spiStartSend(&SPID1, 1, command);
+	spiStartSend(&SPID1, length, data);
+	spiUnselect(&SPID1);
+	spiStop(&SPID1);
+}
+
+
+#endif /* _GDISP_LLD_BOARD_H */
+
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_template.h b/drivers/gdisp/SSD1306/board_SSD1306_template.h
new file mode 100644
index 00000000..ec7f44f5
--- /dev/null
+++ b/drivers/gdisp/SSD1306/board_SSD1306_template.h
@@ -0,0 +1,116 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1306/board_SSD1306_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1306 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   How many bytes to write in one operation when updating the display.
+ * @note	The screen size (in bytes) must evenly divide by this number.
+ *
+ * @notapi
+ */
+#define GDISP_BUS_MAX_TRANSFER_SIZE		64
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->board member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send a command to the controller.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] cmd			The command to send *
+ *
+ * @notapi
+ */
+static inline void write_cmd(GDisplay *g, uint8_t cmd) {
+	(void) g;
+	(void) cmd;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
+	(void) g;
+	(void) data;
+	(void) length;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c
index 5f337b54..36ba9686 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.c
+++ b/drivers/gdisp/SSD1306/gdisp_lld.c
@@ -5,642 +5,219 @@
  *              http://ugfx.org/license.html
  */
 
-#include "gfx.h"
+/**
+ * @file    drivers/gdisp/SSD1306/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1306 display.
+ */
 
-#include "SSD1306.h"
+#include "gfx.h"
 
 #if GFX_USE_GDISP || defined(__DOXYGEN__)
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1306
+#include "../drivers/gdisp/SSD1306/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_SSD1306.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
 
 #ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		64
+	#define GDISP_SCREEN_HEIGHT		64		// This controller should support 32 (untested) or 64
 #endif
 #ifndef GDISP_SCREEN_WIDTH
 	#define GDISP_SCREEN_WIDTH		128
 #endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	100
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
-#define GDISP_INITIAL_CONTRAST		0xFF
+#define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
+
+#include "SSD1306.h"
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-// Include wiring specific header
-#include "gdisp_lld_board_example_i2c.h"
+// Some common routines and macros
+#define RAM(g)							((uint8_t *)g->priv)
+#define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); }
+#define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
 
 // Some common routines and macros
 #define delay(us)					gfxSleepMicroseconds(us)
 #define delayms(ms)					gfxSleepMilliseconds(ms)
 
-// The memory buffer for the display
-static uint8_t gdisp_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8];
-
-/** Set the display to normal or inverse.
- *  @param[in] value 0 for normal mode, or 1 for inverse mode.
- *  @notapi
- */
-static void invert_display(uint8_t i) {
-	write_cmd(i ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
-}
-
-/** Turn the whole display off.
- *	Sends the display to sleep, but leaves RAM intact.
- *	@notapi
- */
-static void display_off(){
-	write_cmd(SSD1306_DISPLAYOFF);
-}
-
-/** Turn the whole display on.
- * 	Wakes up this display following a sleep() call.
- *	@notapi
- */
-static void display_on()	{
-	write_cmd(SSD1306_DISPLAYON);
-}
-
-/** Set the vertical shift by COM.
- * 	@param[in] value The number of rows to shift, from 0 - 63.
- *	@notapi
-*/
-static void set_display_offset(unsigned char value) {
-	write_cmd(SSD1306_SETDISPLAYOFFSET);
-	write_cmd(value & 0x3F);
-}
-
-/** Set the display contrast.
- *  @param[in] value The contrast, from 1 to 256.
- *	@notapi
- */
-static void set_contrast(unsigned char value) {
-	write_cmd(SSD1306_SETCONTRAST);
-	write_cmd(value);
-}
-
-/** Set the display start line.  This is the line at which the display will start rendering.
- *  @param[in] value A value from 0 to 63 denoting the line to start at.
- *	@notapi
- */
-static void set_display_start_line(unsigned char value) {
-	write_cmd(SSD1306_SETSTARTLINE | value);
-}
-
-/** Set the segment remap state.  This allows the module to be addressed as if flipped horizontally.
- * NOTE: Changing this setting has no effect on data already in the module's GDDRAM.
- * @param[in] value 0 = column address 0 = segment 0 (the default), 1 = column address 127 = segment 0 (flipped).
- *	@notapi
- */
-static void set_segment_remap(unsigned char value) {
-	write_cmd(value ? SSD1306_SEGREMAP+1 : SSD1306_SEGREMAP);
-}
-
-/** Set the multiplex ratio.
- *  @param[in] value MUX will be set to (value+1). Valid values range from 15 to 63 - MUX 16 to 64.
- *	@notapi
- */
-static void set_multiplex_ratio(unsigned char value) {
-	write_cmd(SSD1306_SETMULTIPLEX);
-	write_cmd(value & 0x3F);
-}
-
-/** Set COM output scan direction.  If the display is active, this will immediately vertically
- * flip the display.
- * @param[in] value 0 = Scan from COM0 (default), 1 = reversed (scan from COM[N-1]).
- *	@notapi
- */
-static void set_com_output_scan_direction(unsigned char value) {
-	write_cmd(value ? SSD1306_COMSCANDEC : SSD1306_COMSCANINC);
-}
-
-static void set_com_pins_hardware_configuration(unsigned char sequential, unsigned char lr_remap)	{
-	write_cmd(SSD1306_SETCOMPINS);
-	write_cmd(0x02 | ((sequential & 1) << 4) | ((lr_remap & 1) << 5));
-}
-
-/** Flip display content horizontally.
- * 	NOTE: This only flips display content, but doesn't turn the char writing around.
- * 		  You have to unmirror everything manually.
- * 	@param[in] value 0 = column address 0 = segment 0 (the default), 1 = column address 127 = segment 0 (flipped).
- *	@notapi
- */
-static void flip_display(unsigned char enable) {
-	if( enable && GDISP.Orientation == GDISP_ROTATE_0) {
-		set_com_output_scan_direction(0);
-		set_segment_remap(0);
-		GDISP.Orientation = GDISP_ROTATE_0;
-	}
-	if( !enable && GDISP.Orientation == GDISP_ROTATE_180) {
-		set_com_output_scan_direction(1);
-		set_segment_remap(1);
-		GDISP.Orientation = GDISP_ROTATE_180;
-	}
-	else
-		return;
-}
-
-/** Perform a "no operation".
- *	@notapi
- */
-static void nop() {
-	write_cmd(0xE3);
-}
-
-/** Page Addressing Mode: Set the column start address register for
- * 	page addressing mode.
- *	@param[in] address The address (full byte).
- *	@notapi
- */
-static void set_start_address_pam(unsigned char address)
-{
-	// "Set Lower Column Start Address for Page Addressing Mode"
-	write_cmd(address & 0x0F);
-
-	// "Set Higher Column Start Address for Page Addressing Mode"
-	write_cmd((address << 4) & 0x0F);
-}
-
-/** Set memory addressing mode to the given value.
- *	@param[in] mode 0 for Horizontal addressing mode,\n 1 for Vertical addressing mode,\n or 2 for Page addressing mode (PAM).  2 is the default.
- *	@notapi
- */
-static void set_memory_addressing_mode(unsigned char mode)
-{
-	write_cmd(SSD1306_MEMORYMODE);
-	write_cmd(mode & 0x3);
-}
-
-/** Set column address range for horizontal/vertical addressing mode.
- *	 @param[in] start Column start address, 0 - 127.
- *	 @param[in] end Column end address, 0 - 127.
- *	@notapi
- */
-static void set_column_address_hvam(unsigned char start, unsigned char end)
-{
-	write_cmd(SSD1306_HV_COLUMN_ADDRESS);
-	write_cmd(start & 0x7F);
-	write_cmd(end & 0x7F);
-}
-
-/** Set page start and end address for horizontal/vertical addressing mode.
- * 	@param[in] start The start page, 0 - 7.
- *	@param[in] end The end page, 0 - 7.
- *	@notapi
- */
-static void set_page_address_hvam(unsigned char start, unsigned char end)
-{
-	write_cmd(SSD1306_HV_PAGE_ADDRESS);
-	write_cmd(start & 0x07);
-	write_cmd(end & 0x07);
-}
-
-/** Set the GDDRAM page start address for page addressing mode.
- *	@param[in] address The start page, 0 - 7.
- *	@notapi
- */
-static void set_page_start_pam(unsigned char address)
-{
-	write_cmd(SSD1306_PAM_PAGE_START | (address & 0x07));
-}
-
-/** Set the display clock divide ratio and the oscillator frequency.
- * 	@param[in] ratio The divide ratio, default is 0.
- *	@param[in] frequency The oscillator frequency, 0 - 127. Default is 8.
- *	@notapi
- */
-static void set_display_clock_ratio_and_frequency(unsigned char ratio, unsigned char frequency)
-{
-	write_cmd(SSD1306_SETDISPLAYCLOCKDIV);
-	write_cmd((ratio & 0x0F) | ((frequency & 0x0F) << 4));
-}
-
-/** Set the precharge period.
- * 	@param[in] phase1 Phase 1 period in DCLK clocks.  1 - 15, default is 2.
- *	@param[in] phase2 Phase 2 period in DCLK clocks.  1 - 15, default is 2.
- *	@notapi
- */
-static void set_precharge_period(unsigned char phase1, unsigned char phase2)
-{
-	write_cmd(SSD1306_SETPRECHARGE);
-	write_cmd((phase1 & 0x0F) | ((phase2 & 0x0F ) << 4));
-}
-
-/** Set the Vcomh deselect level.
- *	@param[in] level @p 0 = 0.65 x Vcc, @p 1 = 0.77 x Vcc (default), @p 2 = 0.83 x Vcc.
- *	@notapi
- */
-static void set_vcomh_deselect_level(unsigned char level)
-{
-	write_cmd(SSD1306_SETVCOMDETECT);
-	write_cmd((level & 0x03) << 4);
-}
-
-/** Enable/disable charge pump.
- *	@param[in] enable 0 to disable, 1 to enable the internal charge pump.
- *	@notapi
- */
-static void set_charge_pump(unsigned char enable)
-{
-	write_cmd(SSD1306_ENABLE_CHARGE_PUMP);
-	write_cmd(enable ? 0x14 : 0x10);
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
 /*===========================================================================*/
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
 /**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
-	// Initialize your display
-	init_board();
-
-	// Hardware reset.
-	setpin_reset(TRUE);
-	delayms(1);
-	setpin_reset(FALSE);
-	delayms(10);
-	setpin_reset(TRUE);
-
-	// Get the bus for the following initialization commands.
-	acquire_bus();
-
-	display_off();
-	set_display_clock_ratio_and_frequency(0, 8);
-	#if GDISP_SCREEN_HEIGHT == 64
-		set_multiplex_ratio(0x3F);			// 1/64 duty
-	#endif
-	#if GDISP_SCREEN_HEIGHT == 32
-		set_multiplex_ratio(0x1F); 			// 1/32 duty
-	#endif
-	set_precharge_period(0xF, 0x01);		//
-	set_display_offset(0);					//
-	set_display_start_line(0);					//
-	set_charge_pump(1);						// Enable internal charge pump.
-	set_memory_addressing_mode(0); 			// horizontal addressing mode; across then down //act like ks0108 (horizontal addressing mode)
-	set_segment_remap(1);					//
-	set_com_output_scan_direction(1);		//
+ * As this controller can't update on a pixel boundary we need to maintain the
+ * the entire display surface in memory so that we can do the necessary bit
+ * operations. Fortunately it is a small display in monochrome.
+ * 64 * 128 / 8 = 1024 bytes.
+ */
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	// The private area is the display surface.
+	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
+
+	// Initialise the board interface
+	init_board(g);
+
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
+
+	acquire_bus(g);
+
+	write_cmd(g, SSD1306_DISPLAYOFF);
+	write_cmd2(g, SSD1306_SETDISPLAYCLOCKDIV, 0x80);
+	write_cmd2(g, SSD1306_SETMULTIPLEX, GDISP_SCREEN_HEIGHT-1);
+	write_cmd2(g, SSD1306_SETPRECHARGE, 0x1F);
+	write_cmd2(g, SSD1306_SETDISPLAYOFFSET, 0);
+	write_cmd(g, SSD1306_SETSTARTLINE | 0);
+	write_cmd2(g, SSD1306_ENABLE_CHARGE_PUMP, 0x14);
+	write_cmd2(g, SSD1306_MEMORYMODE, 0);
+	write_cmd(g, SSD1306_SEGREMAP+1);
+	write_cmd(g, SSD1306_COMSCANDEC);
 	#if GDISP_SCREEN_HEIGHT == 64
-		set_com_pins_hardware_configuration(1, 0);
-	#endif
-	#if GDISP_SCREEN_HEIGHT == 32
-		set_com_pins_hardware_configuration(0, 1);
-	#endif
-	set_contrast(GDISP_INITIAL_CONTRAST);	// Set initial contrast.
-	set_vcomh_deselect_level(1);			//
-	display_on();							// Turn on OLED panel.
-	invert_display(0);						// Disable Inversion of display.
-	set_column_address_hvam(0, 127);		//
-	set_page_address_hvam(0, 7);			//
-
-	release_bus();
-
-	gdisp_lld_display();
-
-    // Initialize the GDISP structure
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
+		write_cmd2(g, SSD1306_SETCOMPINS, 0x12);
+	#else
+		write_cmd2(g, SSD1306_SETCOMPINS, 0x22);
 	#endif
+	write_cmd2(g, SSD1306_SETCONTRAST, (uint8_t)(GDISP_INITIAL_CONTRAST*256/101));	// Set initial contrast.
+	write_cmd2(g, SSD1306_SETVCOMDETECT, 0x10);
+	write_cmd(g, SSD1306_DISPLAYON);
+	write_cmd(g, SSD1306_NORMALDISPLAY);
+	write_cmd3(g, SSD1306_HV_COLUMN_ADDRESS, 0, GDISP_SCREEN_WIDTH-1);
+	write_cmd3(g, SSD1306_HV_PAGE_ADDRESS, 0, GDISP_SCREEN_HEIGHT/8-1);
+
+    // 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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-
-	if (color == SSD1306_WHITE)
-		gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] |=  (1<<y%8);
-	else
-		gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] &= ~(1<<y%8);
-}
-
-void gdisp_lld_display() {
-	set_display_start_line(0);
+#if GDISP_HARDWARE_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		unsigned	i;
 
-	/* We're sending half a line in one X-mission.*/
-	uint8_t command[GDISP_SCREEN_WIDTH/2],
-			cmdLength = sizeof(command)/sizeof(command[0]),
-			parts = GDISP_SCREEN_WIDTH/cmdLength;
-
-	for(int i=0; i<GDISP_SCREEN_HEIGHT/8; i++){
-		for(int j = 0; j<parts; j++){
-			memmove(command, &gdisp_buffer[i*GDISP_SCREEN_WIDTH + j*cmdLength], cmdLength);
-			write_data(command, cmdLength);
-		}
-	}
-}
-
-/* ---- Optional Routines ---- */
-/*
-	All the below routines are optional.
-	Defining them will increase speed but everything
-	will work if they are not defined.
-	If you are not using a routine - turn it off using
-	the appropriate GDISP_HARDWARE_XXXX macro.
-	Don't bother coding for obvious similar routines if
-	there is no performance penalty as the emulation software
-	makes a good job of using similar routines.
-		eg. If gfillarea() is defined there is little
-			point in defining clear() unless the
-			performance bonus is significant.
-	For good performance it is suggested to implement
-		fillarea() and blitarea().
-*/
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivalent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		/* See datasheet table T10-1 for this*/
-		uint8_t fHeight = (uint8_t)gdispGetFontMetric(gwinGetDefaultFont(), fontLineSpacing);
-		set_multiplex_ratio(GDISP_SCREEN_HEIGHT - fHeight+1);
-		set_display_offset(fHeight-2);
-
-		/* Scrolling animation.*/
-		for(int i=0; i<fHeight; i++){
-			set_display_start_line(i);
-			gfxSleepMilliseconds(10);
-		}
-
-		/* Shift buffer up a font line.*/
-		for (int i = 0; i < GDISP_SCREEN_WIDTH*(GDISP_SCREEN_HEIGHT/8-1); i++) {
-			gdisp_buffer[i]  = gdisp_buffer[i+GDISP_SCREEN_WIDTH*(fHeight/8)] >> fHeight % 8;
-			gdisp_buffer[i] |= gdisp_buffer[i+GDISP_SCREEN_WIDTH*(fHeight/8 + 1)] << (8 - fHeight%8);
-		}
+		// Don't flush if we don't need it.
+		if (!(g->flags & GDISP_FLG_NEEDFLUSH))
+			return;
 
-		/* Clear last page.*/
-		memset( &gdisp_buffer[GDISP_SCREEN_HEIGHT*GDISP_SCREEN_WIDTH/8 - GDISP_SCREEN_WIDTH*2], SSD1306_BLACK, GDISP_SCREEN_WIDTH*2);
+		write_cmd(g, SSD1306_SETSTARTLINE | 0);
 
-		/* Update display.*/
-		gdisp_lld_display();
+		for(i=0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT/8; i+=GDISP_BUS_MAX_TRANSFER_SIZE)
+			write_data(g, RAM(g)+i, GDISP_BUS_MAX_TRANSFER_SIZE);
 	}
+#endif
 
-	/**
-	 * @warning Implementation only fully supports left and right...some command issues here.
-	 * Activate a scroll for rows start through stop.
-	 * Hint, the display is 16 rows tall. To scroll the whole display, run:
-	 * @code
-	 * display.scrollright(0x00, 0x0F)
-	 * @endcode
-	 * @param[in] start The start of the area to be scrolled
-	 * @param[in] stop	The size of the area to be scrolled
-	 * @param[in] dir	direction of scrolling
-	 * 					[left, right, up, down, up_right, up_left, down_left, down_right]
-	 * @note    Optional. *
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_start_scroll(uint8_t dir, uint8_t start, uint8_t stop, uint8_t interval){
-//		if(dir == GDISP_SCROLL_RIGHT || GDISP_SCROLL_LEFT || GDISP_SCROLL_UP) {
-//			switch (dir) {
-//				case GDISP_SCROLL_RIGHT:
-//					write_cmd(SSD1306_SCROLL_HORIZONTAL_RIGHT);
-//					break;
-//				case GDISP_SCROLL_LEFT:
-//					write_cmd(SSD1306_SCROLL_HORIZONTAL_LEFT);
-//					break;
-//			}
-//			write_cmd(0X00);			// Dummy byte.
-//			write_cmd(start & 0x07);	// Define start page address.
-//			switch (interval) {			// Set time interval between each scroll step (5 frames)
-//			        case   2: write_cmd(0x07); break; // 111b
-//			        case   3: write_cmd(0x04); break; // 100b
-//			        case   4: write_cmd(0x05); break; // 101b
-//			        case   5: write_cmd(0x00); break; // 000b
-//			        case  25: write_cmd(0x06); break; // 110b
-//			        case  64: write_cmd(0x01); break; // 001b
-//			        case 128: write_cmd(0x02); break; // 010b
-//			        case 256: write_cmd(0x03); break; // 011b
-//			        default:
-//			            // default to 2 frame interval
-//			            write_cmd(0x07); break;
-//			    }
-//			write_cmd(stop & 0x07);		// Define stop page address
-//			write_cmd(0X01);			// Set vertical scrolling offset as no row.
-//			write_cmd(0XFF);			// Undocumented but needed.
-//			write_cmd(SSD1306_SCROLL_ACTIVATE);
-//		}
-//		else if(dir == GDISP_SCROLL_UP || GDISP_SCROLL_DOWN) {
-//			switch (dir) {
-//				case GDISP_SCROLL_UP:
-//					gdisp_lld_set_vertical_scroll_area(0x00, GDISP_SCREEN_HEIGHT);
-//					write_cmd(SSD1306_SCROLL_VERTICAL_AND_HORIZONTAL_RIGHT);
-//					break;
-//
-//				case GDISP_SCROLL_DOWN:
-//					gdisp_lld_set_vertical_scroll_area(0x00, GDISP_SCREEN_HEIGHT);
-//					write_cmd(SSD1306_SCROLL_VERTICAL_AND_HORIZONTAL_LEFT);
-//					break;
-//			}
-//			write_cmd(0X00);		// Dummy byte.
-//			write_cmd(start);		// Define start page address.
-//			write_cmd(0X00);		// Set time interval between each scroll step (5 frames)
-//			write_cmd(stop);		// Define stop page address
-//			write_cmd(0X01);		// Set vertical scrolling offset as no row.
-//			write_cmd(SSD1306_SCROLL_ACTIVATE);
-//			gdisp_lld_set_vertical_scroll_area(0x00, GDISP_SCREEN_HEIGHT-10);
-//			write_cmd(SSD1306_SCROLL_VERTICAL_AND_HORIZONTAL_RIGHT);
-//			write_cmd(0X00);		// Dummy byte.
-//			write_cmd(start);		// Define start page address.
-//			write_cmd(0X00);		// Set time interval between each scroll step (5 frames)
-//			write_cmd(stop);		// Define stop page address
-//			write_cmd(0X03);		// Set vertical scrolling offset as no row.
-//			write_cmd(SSD1306_SCROLL_ACTIVATE);
-//		}
+#if GDISP_HARDWARE_DRAWPIXEL
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		if (g->p.color != Black)
+			RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] |=  (1<<(g->p.y&7));
+		else
+			RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] &=  ~(1<<(g->p.y&7));
+		g->flags |= GDISP_FLG_NEEDFLUSH;
 	}
+#endif
 
-	/**
-	 * Sets vertical scroll area of display.
-	 * @param[in] start The start of the area to be scrolled [y coordinate]
-	 * @param[in] stop	The size of the area to be scrolled [y coordinate]
-	 * @note    Optional. *
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_set_vertical_scroll_area(uint8_t start, uint8_t stop){
-		write_cmd(SSD1306_SCROLL_SET_VERTICAL_SCROLL_AREA);
-		write_cmd(start);
-		write_cmd(stop);
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		return (RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] & (1<<(g->p.y&7))) ? White : Black;
 	}
+#endif
 
-	/** Deactivate the continuous scroll set up with start_horizontal_scroll() or
-	 *  start_vertical_and_horizontal_scroll().
-	 *	@see set_horizontal_scroll, set_vertical_and_horizontal_scroll
-	 * 	@notapi
-	 */
-	void gdisp_lld_stop_scroll(void){
-		write_cmd(SSD1306_SCROLL_DEACTIVATE);
-	}
-#endif	// GDISP_NEED_SCROLL
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-	    #if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-	        if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-	        if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-	        if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	        if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-	        if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-	    #endif
-
-		for(int i=x; i<x+cx; i++) {
-			for(int j=y; j<y+cy; j++) {
-				gdisp_lld_draw_pixel(i,j,color);
-			}
-		}
-	}
-#endif 	// GDISP_HARDWARE_FILLS
-
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details Unsupported control codes are ignored.
-	 * @note    The value parameter should always be typecast to (void *).
-	 * @note    There are some predefined and some specific to the low level driver.
-	 * @note    GDISP_CONTROL_POWER         - Takes a gdisp_powermode_t
-	 *          GDISP_CONTROL_ORIENTATION   - Takes a gdisp_orientation_t
-	 *          GDISP_CONTROL_BACKLIGHT 	- Takes an int from 0 to 100. For a driver
-	 *                                        that only supports off/on anything other
-	 *                                        than zero is on.
-	 *          GDISP_CONTROL_CONTRAST      - Takes an int from 0 to 100.
-	 *          GDISP_CONTROL_LLD           - Low level driver control constants start at
-	 *                                        this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value 	The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
 		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
 				return;
-			switch((gdisp_powermode_t)value) {
+			switch((powermode_t)g->p.ptr) {
 			case powerOff:
-				display_off();
 			case powerSleep:
-				display_off();
 			case powerDeepSleep:
-				display_off();
+				acquire_bus(g);
+				write_cmd(g, SSD1306_DISPLAYOFF);
+				release_bus(g);
+				break;
 			case powerOn:
-				display_on();
+				acquire_bus(g);
+				write_cmd(g, SSD1306_DISPLAYON);
+				release_bus(g);
 			default:
 				return;
 			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
+			g->g.Powermode = (powermode_t)g->p.ptr;
 			return;
+
 		case GDISP_CONTROL_ORIENTATION:
-				if (GDISP.Orientation == (gdisp_orientation_t)value)
-					return;
-				switch((gdisp_orientation_t)value) {
-				case GDISP_ROTATE_0:
-					flip_display(0);
-					GDISP.Height = GDISP_SCREEN_HEIGHT;
-					GDISP.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_180:
-					flip_display(1);
-					GDISP.Height = GDISP_SCREEN_HEIGHT;
-					GDISP.Width = GDISP_SCREEN_WIDTH;
-					break;
-				default:
-					return;
-				}
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-					GDISP.clipx0 = 0;
-					GDISP.clipy0 = 0;
-					GDISP.clipx1 = GDISP.Width;
-					GDISP.clipy1 = GDISP.Height;
-				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-		case GDISP_CONTROL_CONTRAST:
-				if ((unsigned)value > 100)
-					value = (void *)100;
-				if (GDISP.Contrast == (uint8_t)((float)((uint8_t)value) * 256.0/100.0) )
-					return;
-				set_contrast((uint8_t)((float)((uint8_t)value) * 256.0/100.0) );
-				GDISP.Contrast = (unsigned)value;
+			switch((orientation_t)g->p.ptr) {
+			case GDISP_ROTATE_0:
+				acquire_bus(g);
+				write_cmd(g, SSD1306_COMSCANDEC);
+				write_cmd(g, SSD1306_SEGREMAP+1);
+				GDISP.Height = GDISP_SCREEN_HEIGHT;
+				GDISP.Width = GDISP_SCREEN_WIDTH;
+				release_bus(g);
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				write_cmd(g, SSD1306_COMSCANINC);
+				write_cmd(g, SSD1306_SEGREMAP);
+				GDISP.Height = GDISP_SCREEN_HEIGHT;
+				GDISP.Width = GDISP_SCREEN_WIDTH;
+				release_bus(g);
+				break;
+			default:
 				return;
+			}
+			g->g.Orientation = (orientation_t)value;
+			return;
+
+		case GDISP_CONTROL_CONTRAST:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+			acquire_bus(g);
+			write_cmd2(g, SSD1306_SETCONTRAST, (((uint16_t)value)<<8)/101);
+			release_bus(g);
+            g->g.Contrast = (unsigned)g->p.ptr;
+			return;
+
+		// Our own special controller code to inverse the display
+		// 0 = normal, 1 = inverse
+		case GDISP_CONTROL_INVERT:
+			acquire_bus(g);
+			write_cmd(g, g->p.ptr ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
+			release_bus(g);
+			return;
 		}
 	}
 #endif // GDISP_NEED_CONTROL
 
-/**
- * Let the display blink several times by means of invert and invert back.
- * @param	num		number of blink cycles to do
- * @param	speed	milliseconds to wait between toggling inversion
- * @param	wait	milliseconds to wait before start of all blink cycles and after finishing blink cycles
- * @notapi
- */
- void gdisp_lld_display_blink(uint8_t num, uint16_t speed, uint16_t wait){
-	uint8_t	 inv = 0;
-
-	gfxSleepMilliseconds(wait);
-	for(int i=0; i<2*num; i++) {
-		inv ^= 1;
-		invert_display(inv);
-		gfxSleepMilliseconds(speed);
-	}
-	gfxSleepMilliseconds(wait);
-}
-
 #endif // GFX_USE_GDISP
-/** @} */
 
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.mk b/drivers/gdisp/SSD1306/gdisp_lld.mk
index 2a2e1364..ad320292 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.mk
+++ b/drivers/gdisp/SSD1306/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/SSD1306
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h b/drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h
deleted file mode 100644
index 0e7e153a..00000000
--- a/drivers/gdisp/SSD1306/gdisp_lld_board_example_i2c.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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
-
-#define SSD1306_RESET_PORT		GPIOB
-#define SSD1306_RESET_PIN		5
-
-/**
- * The default slave address is 0x3D, (talking about
- * only the real address part here) and the slave
- * address can be changed to 0x3C by soldering the
- * SA0 pads on the bottom side of the module.
- *
- * b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
- * --------------------------------------
- * 0  | 1  | 1  | 1  | 1  | 0  |SA0 | R/W
- */
-#define SSD1306_I2C_ADDRESS   	0x3D
-#define SSD1306_SDA_PORT		GPIOB
-#define SSD1306_SDA_PIN			7
-#define SSD1306_SCL_PORT		GPIOB
-#define SSD1306_SCL_PIN			6
-#define SET_RST					palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-#define CLR_RST					palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-int8_t vccstate;
-int32_t row_offset = 0;
-
-// I2C configuration structure.
-static I2CConfig i2cconfig;
-
-
-/**
- * @brief   Initialize the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- * @notapi
- */
-static inline void init_board(void) {
-
-	// RESET pin.
-	palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
-
-
-	/*
-	 * Initializes the I2C driver 1. The I2C1 signals are routed as follows:
-	 * PB6 - SCL.
-	 * PB7 - SDA.
-	 * Timing value comes from ST I2C config tool (xls):
-	 * 0x00901D2B;		// 100kHz Standard Mode
-	 * 0x00300444;		// 100kHz Fast Mode
-	 * 0x0030020A;		// 400kHz Fast Mode
-	 * 0x00100002;		// 800kHz Fast Mode +
-	 */
-	i2cconfig.timingr = 0x00100002;		// 800kHz Fast Mode+
-	i2cInit();
-	palSetPadMode(SSD1306_SCL_PORT, SSD1306_SCL_PIN, PAL_MODE_ALTERNATE(1));
-	palSetPadMode(SSD1306_SDA_PORT, SSD1306_SDA_PIN, PAL_MODE_ALTERNATE(1));
-	vccstate = SSD1306_SWITCHCAPVCC;
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	if(state)
-		SET_RST
-	else
-		CLR_RST
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @param[in] percent		0 to 100%
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	// Since we are on OLED no backlight needed
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @notapi
- */
-static inline void acquire_bus(void) {
-		i2cAcquireBus(&I2CD1);
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @notapi
- */
-static inline void release_bus(void) {
-		i2cReleaseBus(&I2CD1);
-}
-
-/**
- * @brief   Send command to the display.
- * @param[in] cmd	The command to send *
- * @notapi
- */
-static inline void write_cmd(uint8_t cmd) {
-	uint8_t command[] = { 0x00, 		// Co = 0, D/C = 0
-						  cmd 		},
-						  txLength = sizeof(command)/sizeof(command[0]),
-						  rxLength = 0;
-	i2cStart(&I2CD1, &i2cconfig);
-	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, txLength, NULL, rxLength, MS2ST(10));
-	i2cStop(&I2CD1);
-}
-
-/**
- * @brief   Send data to the display.
- * @param[in] data	The data to send
- * @notapi
- */
-static inline void write_data(uint8_t* data, uint16_t length) {
-	uint8_t command[length+1],
-			txLength = length+1,
-			rxLength = 0;
-	command[0] = 0x40; 		// Co = 0, D/C = 1
-	memmove(&command[1], data, length);
-
-	i2cStart(&I2CD1, &i2cconfig);
-	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, txLength, NULL, rxLength, MS2ST(10));
-	i2cStop(&I2CD1);
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h b/drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h
deleted file mode 100644
index 232cd58c..00000000
--- a/drivers/gdisp/SSD1306/gdisp_lld_board_example_spi.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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
-
-#define SSD1306_RESET_PORT		GPIOB
-#define SSD1306_RESET_PIN		5
-#define SSD1306_MISO_PORT		GPIOB
-#define SSD1306_MISO_PIN		8
-#define SSD1306_MOSI_PORT		GPIOB
-#define SSD1306_MOSI_PIN		7
-#define SSD1306_SCK_PORT		GPIOB
-#define SSD1306_SCK_PIN			6
-#define SSD1306_CS_PORT			GPIOB
-#define SSD1306_CS_PIN			5
-#define SET_RST					palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-#define CLR_RST					palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-int8_t vccstate;
-int32_t row_offset = 0;
-
-/*
- * SPI1 configuration structure.
- * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
- * The slave select line is the pin 4 on the port GPIOA.
- */
-static const SPIConfig spi1config = {
-	NULL,
-	/* HW dependent part.*/
-	SSD1306_MISO_PORT,
-	SSD1306_MISO_PIN,
-	0
-	//SPI_CR1_BR_0
-};
-
-/**
- * @brief   Initialize the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- * @notapi
- */
-static inline void init_board(void) {
-
-	// RESET pin.
-	palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
-
-	spiInit();
-	palSetPadMode(SSD1306_MISO_PORT, SSD1306_MISO_PIN, 	PAL_MODE_ALTERNATE(1)|
-														PAL_STM32_OSPEED_HIGHEST);
-	palSetPadMode(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN, 	PAL_MODE_ALTERNATE(1)|
-														PAL_STM32_OSPEED_HIGHEST);
-	palSetPadMode(SSD1306_SCK_PORT,  SSD1306_SCK_PIN,  	PAL_MODE_ALTERNATE(1)|
-														PAL_STM32_OSPEED_HIGHEST);
-	palSetPad(SSD1306_CS_PORT, SSD1306_CS_PIN);
-	palSetPadMode(SSD1306_CS_PORT,   SSD1306_CS_PIN,   	PAL_MODE_ALTERNATE(1)|
-														PAL_STM32_OSPEED_HIGHEST);
-	vccstate = SSD1306_SWITCHCAPVCC;
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	if(state)
-		SET_RST
-	else
-		CLR_RST
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @param[in] percent		0 to 100%
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	// Since we are on OLED no backlight needed
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @notapi
- */
-static inline void acquire_bus(void) {
-	spiAcquireBus(&SPID1);
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @notapi
- */
-static inline void release_bus(void) {
-	spiReleaseBus(&SPID1);
-}
-
-/**
- * @brief   Send command to the display.
- * @param[in] cmd	The command to send *
- * @notapi
- */
-static inline void write_cmd(uint8_t cmd) {
-	uint8_t command[] = { 0x00, 		// Co = 0, D/C = 0
-			cmd 		},
-			txLength = sizeof(command)/sizeof(command[0]),
-			rxLength = 0;
-
-	spiStart(&SPID1, &spi1config);
-	spiSelect(&SPID1);
-	spiStartSend(&SPID1, txLength, command);
-	spiUnselect(&SPID1);
-	spiStop(&SPID1);
-}
-
-/**
- * @brief   Send data to the display.
- * @param[in] data	The data to send
- * @notapi
- */
-static inline void write_data(uint8_t* data, uint16_t length) {
-	uint8_t command[length+1],
-			txLength = length+1;
-	command[0] = 0x40; 		// Co = 0, D/C = 1
-	memmove(&command[1], data, length);
-
-	spiStart(&SPID1, &spi1config);
-	spiSelect(&SPID1);
-	spiStartSend(&SPID1, txLength, command);
-	spiUnselect(&SPID1);
-	spiStop(&SPID1);
-}
-
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_board_template.h b/drivers/gdisp/SSD1306/gdisp_lld_board_template.h
deleted file mode 100644
index 48028e83..00000000
--- a/drivers/gdisp/SSD1306/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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
-
-/**
- * @brief   Initialize the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @param[in] percent		0 to 100%
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	// Since we are on OLED no backlight needed
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send command to the display.
- * @param[in] cmd	The command to send *
- * @notapi
- */
-static inline void write_cmd(uint8_t cmd) {
-
-}
-
-/**
- * @brief   Send data to the display.
- * @param[in] data	The data to send
- * @notapi
- */
-static inline void write_data(uint8_t* data, uint16_t length) {
-
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_config.h b/drivers/gdisp/SSD1306/gdisp_lld_config.h
index f0efc18e..8580f933 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1306/gdisp_lld_config.h
@@ -14,17 +14,17 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"SSD1306"
-
-#define GDISP_HARDWARE_CLEARS			FALSE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			FALSE
-#define GDISP_HARDWARE_SCROLL			TRUE
-#define GDISP_HARDWARE_PIXELREAD		FALSE
+#define GDISP_HARDWARE_FLUSH			TRUE		// This controller requires flushing
+#define GDISP_HARDWARE_DRAWPIXEL		TRUE
+#define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_MONO
 
+// This controller supports a special gdispControl() to inverse the display.
+// Pass a parameter of 1 for inverse and 0 for normal.
+#define GDISP_CONTROL_INVERSE			(GDISP_CONTROL_LLD+0)
+
 #endif	/* GFX_USE_GDISP */
 
 #endif	/* _GDISP_LLD_CONFIG_H */
-- 
cgit v1.2.3


From 4e8d2569d638c232cb4c15926cf72e2fb42404d5 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 21 Oct 2013 19:38:15 +1000
Subject: Convert SSD1963 driver to new format. Intergrate the old panel
 include file into the board file.

---
 drivers/gdisp/SSD1963/board_SSD1963_fsmc.h         | 105 ++++
 drivers/gdisp/SSD1963/board_SSD1963_gpio.h         | 102 ++++
 drivers/gdisp/SSD1963/board_SSD1963_template.h     | 148 ++++++
 drivers/gdisp/SSD1963/gdisp_lld.c                  | 592 ++++++++-------------
 drivers/gdisp/SSD1963/gdisp_lld.mk                 |   6 +-
 .../gdisp/SSD1963/gdisp_lld_board_example_fsmc.h   | 177 ------
 .../gdisp/SSD1963/gdisp_lld_board_example_gpio.h   | 191 -------
 drivers/gdisp/SSD1963/gdisp_lld_board_template.h   | 115 ----
 drivers/gdisp/SSD1963/gdisp_lld_config.h           |  10 +-
 drivers/gdisp/SSD1963/gdisp_lld_panel_example.h    |  74 ---
 drivers/gdisp/SSD1963/ssd1963.h                    |   5 -
 11 files changed, 583 insertions(+), 942 deletions(-)
 create mode 100644 drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
 create mode 100644 drivers/gdisp/SSD1963/board_SSD1963_gpio.h
 create mode 100644 drivers/gdisp/SSD1963/board_SSD1963_template.h
 delete mode 100644 drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h
 delete mode 100644 drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h
 delete mode 100644 drivers/gdisp/SSD1963/gdisp_lld_board_template.h
 delete mode 100644 drivers/gdisp/SSD1963/gdisp_lld_panel_example.h

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h b/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
new file mode 100644
index 00000000..6c7119a4
--- /dev/null
+++ b/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
@@ -0,0 +1,105 @@
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+static const LCD_Parameters	DisplayTimings[] = {
+	// You need one of these array elements per display
+	{
+		480, 272,								// Panel width and height
+		2, 2, 41,								// Horizontal Timings (back porch, front porch, pulse)
+		CALC_PERIOD(480,2,2,41),				// Total Horizontal Period (calculated from above line)
+		2, 2, 10,								// Vertical Timings (back porch, front porch, pulse)
+		CALC_PERIOD(272,2,2,10),				// Total Vertical Period (calculated from above line)
+		CALC_FPR(480,272,2,2,41,2,2,10,60ULL)	// FPR - the 60ULL is the frames per second. Note the ULL!
+	},
+};
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->board to that structure.
+
+/* Using FSMC A16 as RS */
+#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
+#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		#if defined(STM32F1XX) || defined(STM32F3XX)
+			/* FSMC setup for F1/F3 */
+			rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
+		#elif defined(STM32F4XX) || defined(STM32F2XX)
+			/* STM32F2-F4 FSMC init */
+			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+		#else
+			#error "FSMC not implemented for this device"
+		#endif
+
+		/* set pins to FSMC mode */
+		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+							(1 << 13) | (1 << 14) | (1 << 15), 0};
+	
+		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+		/* FSMC timing */
+		FSMC_Bank1->BTCR[0+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
+				| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
+				| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
+	
+		/* Bank1 NOR/SRAM control register configuration
+		 * This is actually not needed as already set by default after reset */
+		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+		break;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+	/* FSMC delay reduced as the controller now runs at full speed */
+	FSMC_Bank1->BTCR[0+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
+	FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
+}
+
+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_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+
diff --git a/drivers/gdisp/SSD1963/board_SSD1963_gpio.h b/drivers/gdisp/SSD1963/board_SSD1963_gpio.h
new file mode 100644
index 00000000..0b9c0135
--- /dev/null
+++ b/drivers/gdisp/SSD1963/board_SSD1963_gpio.h
@@ -0,0 +1,102 @@
+/*
+ * 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://chibios-gfx.com/license.html
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1963/board_SSD1963_gpio.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+static const LCD_Parameters	DisplayTimings[] = {
+	// You need one of these array elements per display
+	{
+		480, 272,								// Panel width and height
+		2, 2, 41,								// Horizontal Timings (back porch, front porch, pulse)
+		CALC_PERIOD(480,2,2,41),				// Total Horizontal Period (calculated from above line)
+		2, 2, 10,								// Vertical Timings (back porch, front porch, pulse)
+		CALC_PERIOD(272,2,2,10),				// Total Vertical Period (calculated from above line)
+		CALC_FPR(480,272,2,2,41,2,2,10,60ULL)	// FPR - the 60ULL is the frames per second. Note the ULL!
+	},
+};
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->board to that structure.
+
+/**
+ * @brief	The GPIO pin config
+ *
+ * @details	This block of defines tell your driver how you wired your display
+ *			controller to your MCU. Please change them accordingly.
+ */
+#define GDISP_CMD_PORT		GPIOC
+#define GDISP_DATA_PORT		GPIOD
+#define GDISP_CS			0
+#define GDISP_RS			1
+#define GDISP_WR			2
+#define GDISP_RD			3
+
+#define Set_CS		palSetPad(GDISP_CMD_PORT, GDISP_CS);
+#define Clr_CS		palClearPad(GDISP_CMD_PORT, GDISP_CS);
+#define Set_RS		palSetPad(GDISP_CMD_PORT, GDISP_RS);
+#define Clr_RS		palClearPad(GDISP_CMD_PORT, GDISP_RS);
+#define Set_WR		palSetPad(GDISP_CMD_PORT, GDISP_WR);
+#define Clr_WR		palClearPad(GDISP_CMD_PORT, GDISP_WR);
+#define Set_RD		palSetPad(GDISP_CMD_PORT, GDISP_RD);
+#define Clr_RD		palClearPad(GDISP_CMD_PORT, GDISP_RD);
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		IOBus busCMD = {GDISP_CMD_PORT, (1 << GDISP_CS) | (1 << GDISP_RS) | (1 << GDISP_WR) | (1 << GDISP_RD), 0};
+		IOBus busDATA = {GDISP_CMD_PORT, 0xFFFFF, 0};
+		palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL);
+		palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL);
+		break;
+	}
+}
+
+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;
+	Set_CS;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+	Clr_CS;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	Set_RS; Clr_RD; Set_WR;
+	palWritePort(GDISP_DATA_PORT, index);
+	Clr_WR;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	Clr_RS; Clr_RD; Set_WR;
+	palWritePort(GDISP_DATA_PORT, data);
+	Clr_WR;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+
diff --git a/drivers/gdisp/SSD1963/board_SSD1963_template.h b/drivers/gdisp/SSD1963/board_SSD1963_template.h
new file mode 100644
index 00000000..5e1999b8
--- /dev/null
+++ b/drivers/gdisp/SSD1963/board_SSD1963_template.h
@@ -0,0 +1,148 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1963/board_SSD1963_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief	LCD panel specs
+ *
+ * @note	The timings need to follow the datasheet for your particular TFT/LCD screen
+ * 			(the actual screen, not the controller).
+ * @note	Datasheets normally use a specific set of timings and acronyms, their value refers
+ * 			to the number of pixel clocks. Non-display periods refer to pulses/timings that occur
+ * 			before or after the timings that actually put pixels on the screen. Display periods
+ * 			refer to pulses/timings that directly put pixels on the screen.
+ * @note	HDP: Horizontal Display Period, normally the width - 1<br>
+ * 			HT: Horizontal Total period (display + non-display)<br>
+ * 			HPS: non-display period between the start of the horizontal sync (LLINE) signal
+ * 				and the first display data<br>
+ * 			LPS: horizontal sync pulse (LLINE) start location in pixel clocks<br>
+ * 			HPW: Horizontal sync Pulse Width<br>
+ * 			VDP: Vertical Display period, normally height - 1<br>
+ * 			VT: Vertical Total period (display + non-display)<br>
+ * 			VPS: non-display period in lines between the start of the frame and the first display
+ * 				data in number of lines<br>
+ * 			FPS: vertical sync pulse (LFRAME) start location in lines.<br>
+ * 			VPW: Vertical sync Pulse Width
+ * @note	Here's how to convert them:<br>
+ * 				SCREEN_HSYNC_FRONT_PORCH = ( HT - HPS ) - GDISP_SCREEN_WIDTH<br>
+ * 				SCREEN_HSYNC_PULSE = HPW<br>
+ * 				SCREEN_HSYNC_BACK_PORCH = HPS - HPW<br>
+ * 				SCREEN_VSYNC_FRONT_PORCH = ( VT - VPS ) - GDISP_SCREEN_HEIGHT<br>
+ * 				SCREEN_VSYNC_PULSE = VPW<br>
+ * 				SCREEN_VSYNC_BACK_PORCH = VPS - LPS<br>
+ */
+
+static const LCD_Parameters	DisplayTimings[] = {
+	// You need one of these array elements per display
+	{
+		480, 272,								// Panel width and height
+		2, 2, 41,								// Horizontal Timings (back porch, front porch, pulse)
+		CALC_PERIOD(480,2,2,41),				// Total Horizontal Period (calculated from above line)
+		2, 2, 10,								// Vertical Timings (back porch, front porch, pulse)
+		CALC_PERIOD(272,2,2,10),				// Total Vertical Period (calculated from above line)
+		CALC_FPR(480,272,2,2,41,2,2,10,60ULL)	// FPR - the 60ULL is the frames per second. Note the ULL!
+	},
+};
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->board member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c
index 39889731..11240568 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld.c
+++ b/drivers/gdisp/SSD1963/gdisp_lld.c
@@ -8,24 +8,81 @@
 /**
  * @file    drivers/gdisp/SSD1963/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1963
+#include "../drivers/gdisp/SSD1963/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#define CALC_PERIOD(w,b,f,p)				(p+b+w+f)
+#define CALC_FPR(w,h,hb,hf,hp,vb,vf,vp,fps)	((fps * CALC_PERIOD(w,hb,hf,hp) * CALC_PERIOD(h,vb,vf,vp) * 1048576)/100000000)
+
+typedef struct LCD_Parameters {
+	coord_t		width, height;					// Panel width and height
+	uint16_t	hbporch;						// Horizontal Back Porch
+	uint16_t	hfporch;						// Horizontal Front Porch
+	uint16_t	hpulse;							// Horizontal Pulse
+	uint16_t	hperiod;						// Horizontal Period (Total)
+	uint16_t	vbporch;						// Vertical Back Porch
+	uint16_t	vfporch;						// Vertical Front Porch
+	uint16_t	vpulse;							// Vertical Pulse
+	uint16_t	vperiod;						// Vertical Period (Total)
+	uint32_t	fpr;							// Calculated FPR
+} LCD_Parameters;
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#include "board_SSD1963.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	90
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
 
 #include "ssd1963.h"
 
-/* All the board specific code should go in these include file so the driver
- * can be ported to another board just by creating a suitable file.
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+#define write_data16(g, data)		{ write_data(g, (data)>>8); write_data(g, (data) & 0xFF); }
+
+static inline void set_viewport(GDisplay* g) {
+	write_index(g, SSD1963_SET_PAGE_ADDRESS);
+	write_data16(g, g->p.y);
+	write_data16(g, g->p.y+g->p.cy-1);
+	write_index(g, SSD1963_SET_COLUMN_ADDRESS);
+	write_data16(g, g->p.x);
+	write_data16(g, g->p.x+g->p.cx-1);
+	write_index(g, SSD1963_WRITE_MEMORY_START);
+}
+
+/**
+ * The backlight is controlled by the controller.
  */
-#include "gdisp_lld_board.h"
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	//duty_cycle is 00..FF
+	//Work in progress: the SSD1963 has a built-in PWM, its output can
+	//be used by a Dynamic Background Control or by a host (user)
+	//Check your LCD's hardware, the PWM connection is default left open and instead
+	//connected to a LED connection on the breakout board
+	write_index(g, SSD1963_SET_PWM_CONF);		//set PWM for BackLight
+	write_data(g, 0x01);
+	write_data(g, (55+percent*2) & 0x00FF);
+	write_data(g, 0x01);						//controlled by host (not DBC), enabled
+	write_data(g, 0xFF);
+	write_data(g, 0x60);						//don't let it go too dark, avoid a useless LCD
+	write_data(g, 0x0F);						//prescaler ???
+}
 
 /*===========================================================================*/
 /* Driver interrupt handlers.                                                */
@@ -35,393 +92,194 @@
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	LCD_Parameters *	lcdp;
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
+	// The private area for this controller is the LCD timings
+	lcdp = (void *)&DisplayTimings[g->controllerdisplay];
+	g->priv = lcdp;
 
-/**
- * @brief   Low level GDISP driver initialisation.
- * @return	TRUE if successful, FALSE on error.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
-	/* Initialise the display */
+	// Initialise the board interface
+	init_board(g);
+
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
 
-	init_board();
+	// Get the bus for the following initialisation commands
+	acquire_bus(g);
 	
-	write_index(SSD1963_SOFT_RESET);	
-	gfxSleepMicroseconds(100);
+	write_index(g, SSD1963_SOFT_RESET);
+	gfxSleepMilliseconds(5);
 
 	/* Driver PLL config */
-	write_index(SSD1963_SET_PLL_MN);
-	write_data(35);								 // PLLclk = REFclk (10Mhz) * 36 (360Mhz)
-	write_data(2);								 // SYSclk = PLLclk / 3  (120MHz)
-	write_data(4);								 // Apply calculation bit, else it is ignored
-
-	write_index(SSD1963_SET_PLL);					// Enable PLL
-	write_data(0x01);
-	gfxSleepMicroseconds(200);
-
-	write_index(SSD1963_SET_PLL);					// Use PLL
-	write_data(0x03);
-	gfxSleepMicroseconds(200);
-
-	write_index(SSD1963_SOFT_RESET);	
-	gfxSleepMicroseconds(100);
+	write_index(g, SSD1963_SET_PLL_MN);
+	write_data(g, 35);								// PLLclk = REFclk (10Mhz) * 36 (360Mhz)
+	write_data(g, 2);								// SYSclk = PLLclk / 3  (120MHz)
+	write_data(g, 4);								// Apply calculation bit, else it is ignored
+	write_reg(g, SSD1963_SET_PLL, 0x01);			// Enable PLL
+	gfxSleepMilliseconds(5);
+	write_reg(g, SSD1963_SET_PLL, 0x03);			// Use PLL
+	gfxSleepMilliseconds(5);
+	write_index(g, SSD1963_SOFT_RESET);
+	gfxSleepMilliseconds(5);
 
 	/* Screen size */
-	write_index(SSD1963_SET_GDISP_MODE);
-//	write_data(0x0000);
-	write_data(0b00011000); //Enabled dithering
-	write_data(0x0000);
-	write_data(mHIGH((GDISP_SCREEN_WIDTH+1)));
-	write_data((GDISP_SCREEN_WIDTH+1));
-	write_data(mHIGH((GDISP_SCREEN_HEIGHT+1)));
-	write_data((GDISP_SCREEN_HEIGHT+1));
-	write_data(0x0000);
-
-	write_index(SSD1963_SET_PIXEL_DATA_INTERFACE);
-	write_data(SSD1963_PDI_16BIT565);
+	write_index(g, SSD1963_SET_GDISP_MODE);
+	write_data(g, 0x18);							//Enabled dithering
+	write_data(g, 0x00);
+	write_data16(g, lcdp->width-1);
+	write_data16(g, lcdp->height-1);
+	write_data(g, 0x00);							// RGB
+
+	write_reg(g, SSD1963_SET_PIXEL_DATA_INTERFACE, SSD1963_PDI_16BIT565);
 
 	/* LCD Clock specs */
-	write_index(SSD1963_SET_LSHIFT_FREQ);
-	write_data((GDISP_FPR >> 16) & 0xFF);
-	write_data((GDISP_FPR >> 8) & 0xFF);
-	write_data(GDISP_FPR & 0xFF);
-
-	write_index(SSD1963_SET_HORI_PERIOD);
-	write_data(mHIGH(SCREEN_HSYNC_PERIOD));
-	write_data(mLOW(SCREEN_HSYNC_PERIOD));
-	write_data(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
-	write_data(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
-	write_data(SCREEN_HSYNC_PULSE);
-	write_data(0x00);
-	write_data(0x00);
-	write_data(0x00);
-
-	write_index(SSD1963_SET_VERT_PERIOD);
-	write_data(mHIGH(SCREEN_VSYNC_PERIOD));
-	write_data(mLOW(SCREEN_VSYNC_PERIOD));
-	write_data(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
-	write_data(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
-	write_data(SCREEN_VSYNC_PULSE);
-	write_data(0x00);
-	write_data(0x00);
+	write_index(g, SSD1963_SET_LSHIFT_FREQ);
+	write_data(g, (lcdp->fpr >> 16) & 0xFF);
+	write_data(g, (lcdp->fpr >> 8) & 0xFF);
+	write_data(g, lcdp->fpr & 0xFF);
+
+	write_index(g, SSD1963_SET_HORI_PERIOD);
+	write_data16(g, lcdp->hperiod);
+	write_data16(g, lcdp->hpulse + lcdp->hbporch);
+	write_data(g, lcdp->hpulse);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+
+	write_index(g, SSD1963_SET_VERT_PERIOD);
+	write_data16(g, lcdp->vperiod);
+	write_data16(g, lcdp->vpulse + lcdp->vbporch);
+	write_data(g, lcdp->vpulse);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
 
 	/* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel (during front/back porch) */
-	write_index(SSD1963_SET_TEAR_ON);
-	write_data(0x0000);
+	write_reg(g, SSD1963_SET_TEAR_ON, 0x00);
 
 	/* Turn on */
-	write_index(SSD1963_SET_DISPLAY_ON);
+	write_index(g, SSD1963_SET_DISPLAY_ON);
 	
-	set_backlight(0xE5);//set to 90% brightness
-	
-	post_init_board();
-
-	/* Initialise the GDISP structure to match */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = 100;
-	GDISP.Contrast = 50;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
-
+	/* Turn on the back-light */
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+
+	// Finish Init
+	post_init_board(g);
+
+	// Release the bus
+	release_bus(g);
+
+	/* Initialise the GDISP structure */
+	g->g.Width = lcdp->width;
+	g->g.Height = lcdp->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;
 }
 
-void gdisp_lld_setwindow(coord_t x0, coord_t y0, coord_t x1, coord_t y1) {
-	/* We don't need to validate here as the LLD routines will validate first.
-	 *
-	 * #if GDISP_NEED_VALIDATION
-	 * 	if (x0 >= GDISP.Width || y0 >= GDISP.Height || x0 < 0 || y0 < 0) return;
-	 * 	else if (x1 >= GDISP.Width || y1 >= GDISP.Height || y1 < 0 || y2 < 0) return;
-	 * #endif
-	*/
-	write_index(SSD1963_SET_PAGE_ADDRESS);
-	write_data((y0 >> 8) & 0xFF);
-	write_data((y0 >> 0) & 0xFF);
-	write_data((y1 >> 8) & 0xFF);
-	write_data((y1 >> 0) & 0xFF);
-	write_index(SSD1963_SET_COLUMN_ADDRESS);
-	write_data((x0 >> 8) & 0xFF);
-	write_data((x0 >> 0) & 0xFF);
-	write_data((x1 >> 8) & 0xFF);
-	write_data((x1 >> 0) & 0xFF);
-}
-
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-	if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	
-	gdisp_lld_setwindow(x, y, x, y);
-	write_index(SSD1963_WRITE_MEMORY_START);
-	write_data(color);
-}
-
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		uint32_t area;
-    
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-		
-		area = cx*cy;
-
-		gdisp_lld_setwindow(x, y, x+cx-1, y+cy-1);
-		write_index(SSD1963_WRITE_MEMORY_START);
-
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint8_t i;
-			dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);  
-			for (i = area/65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			}
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			uint32_t index;
-			for(index = 0; index < area; index++)
-				write_data(color);
-		#endif  //#ifdef GDISP_USE_DMA
-}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-			
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		gdisp_lld_setwindow(x, y, x+cx-1, y+cy-1);
-		write_index(SSD1963_WRITE_MEMORY_START);
-
-		buffer += srcx + srcy * srccx;
-      
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint32_t area = cx*cy;
-			uint8_t i;
-			dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);  
-			for (i = area/65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			} 
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area%65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			coord_t endx, endy;
-			uint32_t lg;
-			endx = srcx + cx;
-			endy = y + cy;
-			lg = srccx - cx;
-			for(; y < endy; y++, buffer += lg)
-				for(x=srcx; x < endx; x++)
-					write_data(*buffer++);
-		#endif  //#ifdef GDISP_USE_DMA
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
 	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-		/* NOT IMPLEMENTED YET */
-		
-		/*
-		uint16_t size = x1 - x0 ;
-
-		write_index(SSD1963_SET_SCROLL_AREA);
-		write_data((x0 >> 8) & 0xFF);
-		write_data((x0 >> 0) & 0xFF);
-		write_data((size >> 8) & 0xFF);
-		write_data((size >> 0) & 0xFF);
-		write_data(((lcd_height-x1) >> 8) & 0xFF);
-		write_data(((lcd_height-x1) >> 0) & 0xFF);
-
-		write_index(SSD1963_SET_SCROLL_START);
-		write_data((lines >> 8) & 0xFF);
-		write_data((lines >> 0) & 0xFF);
-		*/
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
 	}
-	
 #endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT -	 Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 * 			GDISP_CONTROL_CONTRAST		- Takes an int from 0 to 100.
-	 * 			GDISP_CONTROL_LLD			- Low level driver control constants start at
-	 * 											this value.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		/* NOT IMPLEMENTED YET */
-		switch(what) {
-			case GDISP_CONTROL_POWER:
-				if (GDISP.Powermode == (gdisp_powermode_t)value)
-					return;
-				switch((gdisp_powermode_t)value) {
-					case powerOff:
-						write_index(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
-						gfxSleepMilliseconds(5);
-						write_index(SSD1963_SET_DISPLAY_OFF);
-						write_index(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
-						break;
-					case powerOn:
-						read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep
-						read_reg(0x0000); gfxSleepMilliseconds(5);
-						if (GDISP.Powermode != powerSleep)
-							gdisp_lld_init();
-						write_index(SSD1963_SET_DISPLAY_ON);
-	
-						break;
-					case powerSleep:
-						write_index(SSD1963_SET_DISPLAY_OFF);
-						write_index(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
-						gfxSleepMilliseconds(5);
-						break;
-					default:
-						return;
-				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
+// Not implemented yet.
+#if 0 && 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;
-			case GDISP_CONTROL_ORIENTATION:
-				if (GDISP.Orientation == (gdisp_orientation_t)value)
+			switch((powermode_t)g->p.ptr) {
+				case powerOff:
+					acquire_bus(g);
+					write_index(g, SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
+					gfxSleepMilliseconds(5);
+					write_index(g, SSD1963_SET_DISPLAY_OFF);
+					write_index(g, SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
+					release_bus(g);
+					break;
+				case powerOn:
+					acquire_bus(g);
+					read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep
+					read_reg(0x0000); gfxSleepMilliseconds(5);
+					write_index(g, SSD1963_SET_DISPLAY_ON);
+					release_bus(g);
+					break;
+				case powerSleep:
+					acquire_bus(g);
+					write_index(g, SSD1963_SET_DISPLAY_OFF);
+					write_index(g, SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
+					release_bus(g);
+					break;
+				default:
 					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-					case GDISP_ROTATE_90:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-					case GDISP_ROTATE_180:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-					case GDISP_ROTATE_270:
-						/* 	Code here */
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-					default:
-						return;
-				}
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-					GDISP.clipx0 = 0;
-					GDISP.clipy0 = 0;
-					GDISP.clipx1 = GDISP.Width;
-					GDISP.clipy1 = GDISP.Height;
-				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
+			}
+			g->g.Powermode = (powermode_t)g->p.ptr;
+			return;
+
+		case GDISP_CONTROL_ORIENTATION:
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
-			case GDISP_CONTROL_BACKLIGHT:
-				gdisp_lld_bg_dimmer(54 + ((uint8_t)value) << 1);//turn 0..100% in 54..255
+			case GDISP_ROTATE_0:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->height;
+				g->g.Width = ((LCD_Parameters *)g->priv)->width;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->width;
+				g->g.Width = ((LCD_Parameters *)g->priv)->height;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->height;
+				g->g.Width = ((LCD_Parameters *)g->priv)->width;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->width;
+				g->g.Width = ((LCD_Parameters *)g->priv)->height;
+				break;
+			default:
 				return;
-/*
-			case GDISP_CONTROL_CONTRAST:
-*/
+			}
+			g->g.Orientation = (orientation_t)value;
+			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;
+
+		//case GDISP_CONTROL_CONTRAST:
+		default:
+			return;
 		}
 	}
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
 
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.mk b/drivers/gdisp/SSD1963/gdisp_lld.mk
index c2ce22b6..ad406898 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld.mk
+++ b/drivers/gdisp/SSD1963/gdisp_lld.mk
@@ -1,6 +1,2 @@
-# List the required driver.
-GFXSRC +=	$(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.c
-
-# Required include directories
 GFXINC +=	$(GFXLIB)/drivers/gdisp/SSD1963
-
+GFXSRC +=	$(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.c
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h b/drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h
deleted file mode 100644
index a2c296b9..00000000
--- a/drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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://chibios-gfx.com/license.html
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld_board_example_fsmc.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
- *
- * @details	This file demonstrates how to interface an SSD1963 based display to an
- *			STM32 microcontroller using ChibiOS/RT.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/* Using FSMC A16 as RS */
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-	GDISP_REG = index;
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the io port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-	const unsigned char FSMC_Bank = 0;
-	
-	#if defined(STM32F1XX) || defined(STM32F3XX)
-		/* FSMC setup for F1/F3 */
-		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			#error "DMA not implemented for F1/F3 Devices"
-		#endif
-	#elif defined(STM32F4XX) || defined(STM32F2XX)
-		/* STM32F2-F4 FSMC init */
-		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) gfxExit();
-			dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);  
-		#endif
-	#else
-		#error "FSMC not implemented for this device"
-	#endif
-
-<	/* set pins to FSMC mode */
-	IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-							(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-	IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-						(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-	palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-	palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-	
-	/* FSMC timing */
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
-			| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
-			| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
-
-	/* Bank1 NOR/SRAM control register configuration
-	 * This is actually not needed as already set by default after reset */
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-static inline void post_init_board(void) {
-	const unsigned char FSMC_Bank = 0;
-	/* FSMC delay reduced as the controller now runs at full speed */
-	FSMC_Bank1->BTCR[FSMC_Bank+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	(void) state;
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	//duty_cycle is 00..FF
-	//Work in progress: the SSD1963 has a built-in PWM, its output can
-	//be used by a Dynamic Background Control or by a host (user)
-	//Check your LCD's hardware, the PWM connection is default left open and instead
-	//connected to a LED connection on the breakout board
-	write_index(SSD1963_SET_PWM_CONF);//set PWM for BackLight
-	write_data(0x0001);
-	write_data(percent & 0x00FF);
-	write_data(0x0001);//controlled by host (not DBC), enabled
-	write_data(0x00FF);
-	write_data(0x0060);//don't let it go too dark, avoid a useless LCD
-	write_data(0x000F);//prescaler ???
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here */
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	 return GDISP_RAM;
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h b/drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h
deleted file mode 100644
index 38f5b2a5..00000000
--- a/drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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://chibios-gfx.com/license.html
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld_board_example_gpio.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
- *
- * @brief	This file demonstrates how to interface an SSD1963 based display using
- *			a GPIO interface of an STM32 out of ChibiOS/RT.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief	The GPIO pin config
- *
- * @details	This block of defines tell your driver how you wired your display
- *			controller to your MCU. Please change them accordingly.
- */
-#define GDISP_CMD_PORT		GPIOC
-#define GDISP_DATA_PORT		GPIOD
-#define GDISP_CS			0
-#define GDISP_RS			1
-#define GDISP_WR			2
-#define GDISP_RD			3
-
-#define Set_CS		palSetPad(GDISP_CMD_PORT, GDISP_CS);
-#define Clr_CS		palClearPad(GDISP_CMD_PORT, GDISP_CS);
-#define Set_RS		palSetPad(GDISP_CMD_PORT, GDISP_RS);
-#define Clr_RS		palClearPad(GDISP_CMD_PORT, GDISP_RS);
-#define Set_WR		palSetPad(GDISP_CMD_PORT, GDISP_WR);
-#define Clr_WR		palClearPad(GDISP_CMD_PORT, GDISP_WR);
-#define Set_RD		palSetPad(GDISP_CMD_PORT, GDISP_RD);
-#define Clr_RD		palClearPad(GDISP_CMD_PORT, GDISP_RD);
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-	Set_CS; Set_RS; Set_WR; Clr_RD;
-
-	palWritePort(GDISP_DATA_PORT, index);
-
-	Clr_CS;
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	Set_CS; Clr_RS; Set_WR; Clr_RD;
-
-	palWritePort(GDISP_DATA_PORT, data);
-
-	Clr_CS;
-}
-
-/**
- * @brief   Initialise the board for the display.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	IOBus busCMD = {GDISP_CMD_PORT, (1 << GDISP_CS) | (1 << GDISP_RS) | (1 << GDISP_WR) | (1 << GDISP_RD), 0};
-	IOBus busDATA = {GDISP_CMD_PORT, 0xFFFFF, 0};
-	palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-static inline void post_init_board(void) {
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	/* optional */
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	//duty_cycle is 00..FF
-	//Work in progress: the SSD1963 has a built-in PWM, its output can
-	//be used by a Dynamic Background Control or by a host (user)
-	//Check your LCD's hardware, the PWM connection is default left open and instead
-	//connected to a LED connection on the breakout board
-	write_index(SSD1963_SET_PWM_CONF);//set PWM for BackLight
-	write_data(0x0001);
-	write_data(percent & 0x00FF);
-	write_data(0x0001);//controlled by host (not DBC), enabled
-	write_data(0x00FF);
-	write_data(0x0060);//don't let it go too dark, avoid a useless LCD
-	write_data(0x000F);//prescaler ???
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here */
-}
-
-__inline void write_stream(uint16_t *buffer, uint16_t size) {
-	uint16_t i;
-
-	Set_CS; Clr_RS; Set_WR; Clr_RD;
-
-	for (i = 0; i < size; i++) {
-		Set_WR;
-		palWritePort(GDISP_DATA_PORT, buffer[i]);
-		Clr_WR;
-	}
-
-	Clr_CS;
-}
-
-__inline void read_stream(uint16_t *buffer, size_t size) {
-	uint16_t i;
-	
-	Set_CS; Clr_RS; Clr_WR; Set_RD;
-	
-	for (i = 0; i < size; i++) {
-		Set_RD;
-		buffer[i] = palReadPort(GDISP_DATA_PORT);
-		Clr_RD;
-	}
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	uint16_t data;
-
-	Set_CS; Clr_RS; Clr_WR; Set_RD;
-	
-	data = palReadPort(GDISP_DATA_PORT); 
-
-	Clr_CS;
-
-	return data;
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_board_template.h b/drivers/gdisp/SSD1963/gdisp_lld_board_template.h
deleted file mode 100644
index 44cd3712..00000000
--- a/drivers/gdisp/SSD1963/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- * 
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the io port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-static inline void post_init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * 
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- * 
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- * 
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_config.h b/drivers/gdisp/SSD1963/gdisp_lld_config.h
index 70eec579..054d72b8 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1963/gdisp_lld_config.h
@@ -22,14 +22,8 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"SSD1963"
-#define GDISP_LLD(x)					gdisp_lld_##x##_SSD1963
-
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS		TRUE
-/* Maybe someday soon */
-#define GDISP_HARDWARE_SCROLL			FALSE
-#define GDISP_HARDWARE_CONTROL		FALSE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+//#define GDISP_HARDWARE_CONTROL			TRUE			// Not Yet.
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
 
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_panel_example.h b/drivers/gdisp/SSD1963/gdisp_lld_panel_example.h
deleted file mode 100644
index 72095495..00000000
--- a/drivers/gdisp/SSD1963/gdisp_lld_panel_example.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld_panel_example.h
- * @brief   TFT LCD panel properties.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_PANEL_H
-#define _GDISP_LLD_PANEL_H
-
-/* LCD panel specs */
-
-/* The timings need to follow the datasheet for your particular TFT/LCD screen (the actual screen, not the controller)
-*** Datasheets normally use a specific set of timings and acronyms, their value refers to the number of pixel clocks
-** Non-display periods refer to pulses/timings that occur before or after the timings that actually put pixels on the screen
-** Display periods refer to pulses/timings that directly put pixels on the screen
-HDP: Horizontal Display Period, normally the width - 1
-HT: Horizontal Total period (display + non-display)
-HPS: non-display period between the start of the horizontal sync (LLINE) signal and the first display data
-LPS: horizontal sync pulse (LLINE) start location in pixel clocks
-HPW: Horizontal sync Pulse Width
-VDP: Vertical Display period, normally height - 1
-VT: Vertical Total period (display + non-display)
-VPS: non-display period in lines between the start of the frame and the first display data in number of lines
-FPS: vertical sync pulse (LFRAME) start location in lines. 
-VPW: Vertical sync Pulse Width
-
-*** Here's how to convert them:
-HPS = SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH
-HT - HPS = GDISP_SCREEN_WIDTH + SCREEN_HSYNC_FRONT_PORCH
-=> 	SCREEN_HSYNC_FRONT_PORCH = ( HT - HPS ) - GDISP_SCREEN_WIDTH
-	SCREEN_HSYNC_PULSE = HPW
-	SCREEN_HSYNC_BACK_PORCH = HPS - HPW
-	SCREEN_HSYNC_PERIOD = HT
-	
-VPS = SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH
-VT - VPS = GDISP_SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH
-=>	SCREEN_VSYNC_FRONT_PORCH = ( VT - VPS ) - GDISP_SCREEN_HEIGHT
-	SCREEN_VSYNC_PULSE = VPW
-	SCREEN_VSYNC_BACK_PORCH = VPS - LPS
-	SCREEN_VSYNC_PERIOD = VT
-*/
-
-#define SCREEN_FPS 60ULL
-
-//The following values are for a 4.3" TFT LCD
-
-#define GDISP_SCREEN_WIDTH 480
-#define GDISP_SCREEN_HEIGHT 272
-
-#define SCREEN_HSYNC_BACK_PORCH		2
-#define SCREEN_HSYNC_FRONT_PORCH	2
-#define SCREEN_HSYNC_PULSE			41
-
-#define SCREEN_VSYNC_BACK_PORCH		2
-#define SCREEN_VSYNC_FRONT_PORCH	2
-#define SCREEN_VSYNC_PULSE			10
-
-#define	SCREEN_HSYNC_PERIOD	(SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH + GDISP_SCREEN_WIDTH  + SCREEN_HSYNC_FRONT_PORCH)
-#define	SCREEN_VSYNC_PERIOD	(SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH + GDISP_SCREEN_HEIGHT + SCREEN_VSYNC_FRONT_PORCH)
-
-#define SCREEN_PCLK	(SCREEN_HSYNC_PERIOD * SCREEN_VSYNC_PERIOD * SCREEN_FPS)
-#define GDISP_FPR		((SCREEN_PCLK * 1048576)/100000000)
-
-#endif
-/** @} */
diff --git a/drivers/gdisp/SSD1963/ssd1963.h b/drivers/gdisp/SSD1963/ssd1963.h
index 46369be6..be328775 100644
--- a/drivers/gdisp/SSD1963/ssd1963.h
+++ b/drivers/gdisp/SSD1963/ssd1963.h
@@ -8,11 +8,6 @@
 #ifndef SSD1963_H
 #define SSD1963_H
 
-#include "gdisp_lld_panel.h"
-
-#define mHIGH(x) (x >> 8)
-#define mLOW(x) (x & 0xFF)
-
 /* SSD1963 commands */
 
 #define SSD1963_NOP						0x0000
-- 
cgit v1.2.3


From 459fbf6781bca48471ea8dc1cfbbd2a0700ee2e1 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Mon, 21 Oct 2013 13:47:59 +0200
Subject: fixes

---
 drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h | 1 -
 1 file changed, 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
index 2a7ffe1e..99d37299 100644
--- a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+++ b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
@@ -99,7 +99,6 @@ static inline void setwritemode(GDisplay *g) {
 static inline uint16_t read_data(GDisplay *g) {
 	return palReadPort(GPIOE);
 }
-#endif
 
 #if defined(GDISP_USE_DMA)
 	#error "GDISP - SSD1289: The GPIO interface does not support DMA"
-- 
cgit v1.2.3


From f285a24a9030e0119739330f4246b4141fa3ba5e Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Mon, 21 Oct 2013 14:27:29 +0200
Subject: SSD1289 fixes

---
 drivers/gdisp/SSD1289/gdisp_lld.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 698d3cfc..510f1560 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -302,7 +302,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			case GDISP_ROTATE_90:
 				acquire_bus(g);
 				/* ID = 01 AM = 1 */
-				write_reg(0x11, 0x6058);
+				write_reg(g, 0x11, 0x6058);
 				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
@@ -310,7 +310,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			case GDISP_ROTATE_180:
 				acquire_bus(g);
 				/* ID = 00 AM = 0 */
-				write_reg(0x11, 0x6040);
+				write_reg(g, 0x11, 0x6040);
 				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
@@ -326,7 +326,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			default:
 				return;
 			}
-			g->g.Orientation = (orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 
         case GDISP_CONTROL_BACKLIGHT:
-- 
cgit v1.2.3


From 86ae017301c62d8495707d46708bcc65568539d7 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Mon, 21 Oct 2013 15:40:40 +0200
Subject: Porting SSD2219 driver - WORK IN PROGRES!!!!

---
 drivers/gdisp/SSD2119/gdisp_lld.c | 345 ++++++++++++++++++++++----------------
 1 file changed, 198 insertions(+), 147 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD2119/gdisp_lld.c b/drivers/gdisp/SSD2119/gdisp_lld.c
index de97d805..548d2dd1 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld.c
+++ b/drivers/gdisp/SSD2119/gdisp_lld.c
@@ -17,10 +17,12 @@
 
 #include "ssd2119.h"
 
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+#if GFX_USE_GDISP
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD2119
+#include "../drivers/gdisp/SSD2119/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+#include "board_SSD2119.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
@@ -32,51 +34,48 @@
 #ifndef GDISP_SCREEN_WIDTH
 	#define GDISP_SCREEN_WIDTH		320
 #endif
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
-#include "gdisp_lld_board.h"
-
 // Some common routines and macros
-#define write_reg(reg, data)		{ write_index(reg); write_data(data); }
-#define stream_start()				write_index(SSD2119_REG_RAM_DATA);
-#define stream_stop()
-#define delay(us)					gfxSleepMicroseconds(us)
-#define delayms(ms)					gfxSleepMilliseconds(ms)
+#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
 
-static inline void set_cursor(coord_t x, coord_t y) {
+static void set_cursor(GDisplay* g) {
 	/* Reg SSD2119_REG_X_RAM_ADDR is 9 bit value
 	 * Reg SSD2119_REG_Y_RAM_ADDR is an 8 bit
 	 * Use a bit mask to make sure they are not set too high
 	 */
-	switch(GDISP.Orientation) {
+	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
-			write_reg(SSD2119_REG_X_RAM_ADDR, x & 0x01FF);
-			write_reg(SSD2119_REG_Y_RAM_ADDR, y & 0x00FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.x & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.y & 0x00FF);
 			break;
 		case GDISP_ROTATE_90:
-			write_reg(SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - y - 1) & 0x01FF);
-			write_reg(SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - x - 1) & 0x00FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - g->p.y - 1) & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - g->p.x - 1) & 0x00FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - 1 - x) & 0x01FF);
-			write_reg(SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - 1 - y) & 0x00FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - 1 - g->p.x) & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - 1 - g->p.y) & 0x00FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(SSD2119_REG_X_RAM_ADDR, y & 0x01FF);
-			write_reg(SSD2119_REG_Y_RAM_ADDR, x & 0x00FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.y & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.x & 0x00FF);
 			break;
 	}
 }
 
-static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-
-	set_cursor(x, y);
+static void set_viewport(GDisplay* g) {
+	set_cursor(g->p.x, g->p.y);
 
 	/* Reg 0x44 - Vertical RAM address position
 	 * 		Upper Byte - VEA
@@ -87,34 +86,34 @@ static void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
 	 * 		0 <= HSA <= HEA <= 0x13F
 	 */
 
-	switch(GDISP.Orientation) {
+	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
-			write_reg(SSD2119_REG_V_RAM_POS,   (((y + cy - 1) << 8) & 0xFF00 ) | (y & 0x00FF));
-			write_reg(SSD2119_REG_H_RAM_START, (x & 0x01FF));
-			write_reg(SSD2119_REG_H_RAM_END,   (x + cx - 1) & 0x01FF);
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.y + g->p.cy - 1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (g->p.x & 0x01FF));
+			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.x + g->p.cx - 1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_90:
-			write_reg(SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT - x - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (x + cx)) & 0x00FF));
-			write_reg(SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (y + cy)) & 0x01FF);
-			write_reg(SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH - y - 1) & 0x01FF);
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT - g->p.x - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x01FF);
+			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH - g->p.y - 1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT - y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (y + cy)) & 0x00FF));
-			write_reg(SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (x + cx)) & 0x01FF);
-			write_reg(SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH - x - 1) & 0x01FF);
+			write_reg(SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT - g->p.y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x00FF));
+			write_reg(SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x01FF);
+			write_reg(SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH - g->p.x - 1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(SSD2119_REG_V_RAM_POS,   (((x + cx - 1) << 8) & 0xFF00 ) | (x & 0x00FF));
-			write_reg(SSD2119_REG_H_RAM_START, (y & 0x01FF));
-			write_reg(SSD2119_REG_H_RAM_END,   (y + cy - 1) & 0x01FF);
+			write_reg(SSD2119_REG_V_RAM_POS,   (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+			write_reg(SSD2119_REG_H_RAM_START, (g->p.y & 0x01FF));
+			write_reg(SSD2119_REG_H_RAM_END,   (g->p.y + g->p.cy - 1) & 0x01FF);
 			break;
 	}
 
-	set_cursor(x, y);
+	set_cursor(g->p.x, g->p.y);
 }
 
-static inline void reset_viewport(void) {
-	set_viewport(0, 0, GDISP.Width, GDISP.Height);
+static inline void reset_viewport(GDisplay* g) {
+	set_viewport(0, 0, g->g.Width, g->g.Height);
 }
 
 /*===========================================================================*/
@@ -125,144 +124,196 @@ static inline void reset_viewport(void) {
 /* Driver exported functions.                                                */
 /*===========================================================================*/
 
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
+LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
+	// no private area for this controller
+	g->priv = 0;
 
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
-	/* Initialise your display */
+	// initialise the board interface
 	init_board();
 
 	// Hardware reset
-	setpin_reset(TRUE);
-	delayms(20);
-	setpin_reset(FALSE);
-	delayms(20);
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
 
 	// Get the bus for the following initialisation commands
-	acquire_bus();
+	acquire_bus(g);
 
 	// Enter sleep mode (if we are not already there).
-	write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0001);
-	delay(5);
+	write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0001);
+	gfxSleepMicroseconds(5);
 
 	// Set initial power parameters.
-	write_reg(SSD2119_REG_PWR_CTRL_5, 0x00B2);
-	delay(5);
-	write_reg(SSD2119_REG_VCOM_OTP_1, 0x0006);
-	delay(5);
+	write_reg(g, SSD2119_REG_PWR_CTRL_5, 0x00B2);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_VCOM_OTP_1, 0x0006);
+	gfxSleepMicroseconds(5);
 
 	// Start the oscillator.
-	write_reg(SSD2119_REG_OSC_START, 0x0001);
-	delay(5);
+	write_reg(g, SSD2119_REG_OSC_START, 0x0001);
+	gfxSleepMicroseconds(5);
 
 	// Set pixel format and basic display orientation (scanning direction).
-	write_reg(SSD2119_REG_OUTPUT_CTRL, 0x30EF);
-	delay(5);
-	write_reg(SSD2119_REG_LCD_DRIVE_AC_CTRL, 0x0600);
-	delay(5);
+	write_reg(g, SSD2119_REG_OUTPUT_CTRL, 0x30EF);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_LCD_DRIVE_AC_CTRL, 0x0600);
+	gfxSleepMicroseconds(5);
 
 	// Exit sleep mode.
-	write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);
-	delay(5);
+	write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0000);
+	gfxSleepMicroseconds(5);
 
 	// Configure pixel color format and MCU interface parameters.
-	write_reg(SSD2119_REG_ENTRY_MODE, 0x6830); // ENTRY_MODE_DEFAULT
-	delay(5);
+	write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6830); // ENTRY_MODE_DEFAULT
+	gfxSleepMicroseconds(5);
 
 	// Set analog parameters.
-	write_reg(SSD2119_REG_SLEEP_MODE_2, 0x0999);
-	delay(5);
-	write_reg(SSD2119_REG_ANALOG_SET, 0x3800);
-	delay(5);
+	write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_ANALOG_SET, 0x3800);
+	gfxSleepMicroseconds(5);
 
 	// Enable the display.
-	write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0033);
-	delay(5);
+	write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0033);
+	gfxSleepMicroseconds(5);
 
 	// Set VCIX2 voltage to 6.1V.
-	write_reg(SSD2119_REG_PWR_CTRL_2, 0x0005);
-	delay(5);
+	write_reg(g, SSD2119_REG_PWR_CTRL_2, 0x0005);
+	gfxSleepMicroseconds(5);
 
 	// Configure gamma correction.
-	write_reg(SSD2119_REG_GAMMA_CTRL_1, 0x0000);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_2, 0x0303);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_3, 0x0407);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_4, 0x0301);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_5, 0x0301);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_6, 0x0403);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_7, 0x0707);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_8, 0x0400);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_9, 0x0a00);
-	delay(5);
-	write_reg(SSD2119_REG_GAMMA_CTRL_10, 0x1000);
-	delay(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_1, 0x0000);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_2, 0x0303);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_3, 0x0407);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_4, 0x0301);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_5, 0x0301);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_6, 0x0403);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_7, 0x0707);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_8, 0x0400);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_9, 0x0a00);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_10, 0x1000);
+	gfxSleepMicroseconds(5);
 
 	// Configure Vlcd63 and VCOMl.
-	write_reg(SSD2119_REG_PWR_CTRL_3, 0x000A);
-	delay(5);
-	write_reg(SSD2119_REG_PWR_CTRL_4, 0x2E00);
-	delay(5);
+	write_reg(g, SSD2119_REG_PWR_CTRL_3, 0x000A);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_PWR_CTRL_4, 0x2E00);
+	gfxSleepMicroseconds(5);
 
 	// Set the display size and ensure that the GRAM window is set to allow access to the full display buffer.
-	write_reg(SSD2119_REG_V_RAM_POS, (GDISP_SCREEN_HEIGHT - 1) << 8);
-	delay(5);
-	write_reg(SSD2119_REG_H_RAM_START, 0x0000);
-	delay(5);
-	write_reg(SSD2119_REG_H_RAM_END, GDISP_SCREEN_WIDTH - 1);
-	delay(5);
-
-	write_reg(SSD2119_REG_X_RAM_ADDR, 0x00);
-	delay(5);
-	write_reg(SSD2119_REG_Y_RAM_ADDR, 0x00);
-	delay(5);
+	write_reg(g, SSD2119_REG_V_RAM_POS, (GDISP_SCREEN_HEIGHT - 1) << 8);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_H_RAM_START, 0x0000);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_H_RAM_END, GDISP_SCREEN_WIDTH - 1);
+	gfxSleepMicroseconds(5);
+
+	write_reg(g, SSD2119_REG_X_RAM_ADDR, 0x00);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_Y_RAM_ADDR, 0x00);
+	gfxSleepMicroseconds(5);
 
 	// Release the bus
-	release_bus();
+	release_bus(g);
 
-	/* Turn on the backlight */
-	set_backlight(GDISP_INITIAL_BACKLIGHT);
+	// Turn on the backlight
+	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;
 
-	/* Initialise the GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOn;
-	GDISP.Backlight = GDISP_INITIAL_BACKLIGHT;
-	GDISP.Contrast = GDISP_INITIAL_CONTRAST;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		GDISP.clipx0 = 0;
-		GDISP.clipy0 = 0;
-		GDISP.clipx1 = GDISP.Width;
-		GDISP.clipy1 = GDISP.Height;
-	#endif
 	return TRUE;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC void gdisp_lld_write_start(GDisplay* g) {
+		acquire_bus(g);
+		set_viewport(g);
+	}
+	LLDSPEC void gdisp_lld_write_color(GDisplay* g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC void gdisp_lld_write_stop(GDisplay* g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay* g) {
+		set_cursor(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC void gdisp_lld_read_start(GDisplay* g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		set_readmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC color_t gdisp_lld_read_color(GDisplay* g) {
+		return read_data(g);
+	}
+	LLDSPEC void gdisp_lld_read_stop(GDisplay* g) {
+		set_writemode(g);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_fill_area(GDisplay* g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);	
+		dma_with_noinc(g, &color, g->p.cx * g->p.cy);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
+		pixel_t*	buffer;
+		coord_t		ynct;
+
+		buffer = (pixel_t*)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
+
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+
+		if (g->p.x2 == g->p.cx) {
+			dma_with_inc(g, buffer, g->p.cx * g->p.cy);
+		} else {
+			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
+				dma_with_inc(g, buffer, g->p.cy);
+		}
+
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay* g) {
+		// ....
+	}
+#endif
+
+
+//////////////////////// OLD STUFF FROM HERE ////////////////////////////////////////////////////
+
 void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
 		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
@@ -584,14 +635,14 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 							write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);	// Leave sleep mode
 							write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0033);	// Display on
 							release_bus();
-							delayms(170);
+							gfxSleepMilliseconds(170);
 						} else if (GDISP.Powermode == powerDeepSleep) {
 							acquire_bus();
 							write_reg(SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
 							write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);	// Leave sleep mode
 							write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0033);	// Display on
 							release_bus();
-							delayms(170);
+							gfxSleepMilliseconds(170);
 						} else {
 							acquire_bus();
 							write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);	// Leave sleep mode
@@ -607,7 +658,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 						write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0000);	// Display off
 						release_bus();
 						set_backlight(0);
-						delayms(25);
+						gfxSleepMilliseconds(25);
 						break;
 
 					case powerDeepSleep:
@@ -617,7 +668,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 						write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0000);	// Display off
 						release_bus();
 						set_backlight(0);
-						delayms(25);
+						gfxSleepMilliseconds(25);
 						break;
 
 					default:
-- 
cgit v1.2.3


From 22b59b8b4f50fb543770e68f70f2d9dbe48d7221 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 22 Oct 2013 09:19:22 +1000
Subject: Test for SSD 1289 driver bug.

---
 drivers/gdisp/SSD1289/gdisp_lld.c        | 11 ++++++++---
 drivers/gdisp/SSD1289/gdisp_lld_config.h |  2 +-
 2 files changed, 9 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 510f1560..f600b305 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -195,6 +195,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
 		acquire_bus(g);
 		set_viewport(g);
+		#if !GDISP_HARDWARE_STREAM_POS
+			set_cursor(g);
+		#endif
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		write_data(g, g->p.color);
@@ -202,9 +205,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
 	}
-	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-		set_cursor(g);
-	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			set_cursor(g);
+		}
+	#endif
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index 84e518d2..f8743a2b 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -24,7 +24,7 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
-#define GDISP_HARDWARE_STREAM_POS		TRUE
+//#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #if defined(GDISP_USE_DMA)
-- 
cgit v1.2.3


From 27b5383c1bcec9a8b45328bf051ee0624d0d1102 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 22 Oct 2013 15:52:31 +1000
Subject: Fix typos in drivers

---
 drivers/gdisp/HX8347D/gdisp_lld.c | 3 ++-
 drivers/gdisp/ILI9320/gdisp_lld.c | 2 +-
 drivers/gdisp/ILI9325/gdisp_lld.c | 3 +--
 drivers/gdisp/ILI9481/gdisp_lld.c | 2 +-
 drivers/gdisp/RA8875/gdisp_lld.c  | 2 +-
 drivers/gdisp/S6D1121/gdisp_lld.c | 2 +-
 drivers/gdisp/SSD1306/gdisp_lld.c | 2 +-
 drivers/gdisp/SSD1963/gdisp_lld.c | 2 +-
 drivers/gdisp/SSD2119/gdisp_lld.c | 2 +-
 9 files changed, 10 insertions(+), 10 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
index 3851c8e1..ab976db0 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.c
+++ b/drivers/gdisp/HX8347D/gdisp_lld.c
@@ -217,8 +217,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				default:
 					return;
 			}
-			g->g.Orientation = (orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
+
         case GDISP_CONTROL_BACKLIGHT:
             if ((unsigned)g->p.ptr > 100)
             	g->p.ptr = (void *)100;
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index bf82a88a..6d7815cb 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -354,7 +354,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				default:
 					return;
 				}
-				g->g.Orientation = (orientation_t)value;
+				g->g.Orientation = (orientation_t)g->p.ptr;
 				return;
 
 	        case GDISP_CONTROL_BACKLIGHT:
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index 6bb649b1..75b4cd13 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -346,7 +346,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 					return;
 			}
 
-			g->g.Orientation = (orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 			
         case GDISP_CONTROL_BACKLIGHT:
@@ -360,7 +360,6 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			return;
 		}
 	}
-
 #endif
 
 #endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.c b/drivers/gdisp/ILI9481/gdisp_lld.c
index 5af12986..49e28b23 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.c
+++ b/drivers/gdisp/ILI9481/gdisp_lld.c
@@ -311,7 +311,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			default:
 				return;
 			}
-			g->g.Orientation = (orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
         //case GDISP_CONTROL_BACKLIGHT:
 		//case GDISP_CONTROL_CONTRAST:
diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
index 7916ef3b..b0508b58 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ b/drivers/gdisp/RA8875/gdisp_lld.c
@@ -260,7 +260,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				default:
 					return;
 				}
-				g->g.Orientation = (orientation_t)value;
+				g->g.Orientation = (orientation_t)g->p.ptr;
 				return;
 		#endif
 
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c
index f7e12591..df9f01a7 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld.c
+++ b/drivers/gdisp/S6D1121/gdisp_lld.c
@@ -313,7 +313,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			default:
 				return;
 			}
-			g->g.Orientation = (orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 
         case GDISP_CONTROL_BACKLIGHT:
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c
index 36ba9686..b0834193 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.c
+++ b/drivers/gdisp/SSD1306/gdisp_lld.c
@@ -196,7 +196,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			default:
 				return;
 			}
-			g->g.Orientation = (orientation_t)value;
+			g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 
 		case GDISP_CONTROL_CONTRAST:
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c
index 11240568..b94c1a40 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld.c
+++ b/drivers/gdisp/SSD1963/gdisp_lld.c
@@ -264,7 +264,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			default:
 				return;
 			}
-			g->g.Orientation = (orientation_t)value;
+		g->g.Orientation = (orientation_t)g->p.ptr;
 			return;
 
 		case GDISP_CONTROL_BACKLIGHT:
diff --git a/drivers/gdisp/SSD2119/gdisp_lld.c b/drivers/gdisp/SSD2119/gdisp_lld.c
index 548d2dd1..e3a2329a 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld.c
+++ b/drivers/gdisp/SSD2119/gdisp_lld.c
@@ -735,7 +735,7 @@ void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
 				GDISP.clipx1 = GDISP.Width;
 				GDISP.clipy1 = GDISP.Height;
 				#endif
-				GDISP.Orientation = (gdisp_orientation_t)value;
+				g->g.Orientation = (orientation_t)g->p.ptr;
 				return;
 
 			case GDISP_CONTROL_BACKLIGHT:
-- 
cgit v1.2.3


From 5e9e1a36ab3685ba9e50fa52fe2a8c7bf02ac094 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 22 Oct 2013 18:38:56 +1000
Subject: Convert SSD2119 to new driver format

---
 .../gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h  | 173 ++++++
 drivers/gdisp/SSD2119/board_SSD2119_template.h     | 191 +++++++
 drivers/gdisp/SSD2119/gdisp_lld.c                  | 590 +++++----------------
 drivers/gdisp/SSD2119/gdisp_lld.mk                 |   5 +-
 .../SSD2119/gdisp_lld_board_embest_dmstf4bb.h      | 193 -------
 drivers/gdisp/SSD2119/gdisp_lld_board_template.h   | 109 ----
 drivers/gdisp/SSD2119/gdisp_lld_config.h           |  15 +-
 7 files changed, 491 insertions(+), 785 deletions(-)
 create mode 100644 drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
 create mode 100644 drivers/gdisp/SSD2119/board_SSD2119_template.h
 delete mode 100644 drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h
 delete mode 100644 drivers/gdisp/SSD2119/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h b/drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
new file mode 100644
index 00000000..927e93a4
--- /dev/null
+++ b/drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
@@ -0,0 +1,173 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
+ * @brief   GDISP Graphic Driver subsystem board FSMC interface for the SSD2119 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->board to that structure.
+
+/* Using FSMC A19 (PE3) as DC */
+#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* DC = 0 */
+#define GDISP_RAM (*((volatile uint16_t *) 0x60100000)) /* DC = 1 */
+#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
+
+#define SET_RST palSetPad(GPIOD, 3);
+#define CLR_RST palClearPad(GPIOD, 3);
+
+/*
+ * PWM configuration structure. We use timer 4 channel 2 (orange LED on board).
+ * The reason for so high clock is that with any lower, onboard coil is squeaking.
+ * The major disadvantage of this clock is a lack of linearity between PWM duty
+ * cycle width and brightness. In fact only with low preset one sees any change
+ * (eg. duty cycle between 1-20). Feel free to adjust this, maybe only my board
+ * behaves like this. According to the G5126 datesheet (backlight LED driver)
+ * the PWM frequency should be somewhere between 200 Hz to 200 kHz.
+ */
+static const PWMConfig pwmcfg = {
+	1000000,       /* 1 MHz PWM clock frequency. */
+	100,           /* PWM period is 100 cycles. */
+	NULL,
+	{
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
+		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
+	},
+	0
+};
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		#if defined(STM32F4XX) || defined(STM32F2XX)
+			/* STM32F4 FSMC init */
+			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+			#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
+				if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL))
+					gfxExit();
+				dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
+				dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+			#endif
+		#else
+			#error "FSMC not implemented for this device"
+		#endif
+
+		/* Group pins */
+		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
+								(1 << 9) | (1 << 10) | (1 << 14) | (1 << 15), 0};
+
+		IOBus busE = {GPIOE, (1 << 3) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+								(1 << 13) | (1 << 14) | (1 << 15), 0};
+
+		/* FSMC is an alternate function 12 (AF12) */
+		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+
+		/* FSMC timing register configuration */
+		FSMC_Bank1->BTCR[0 + 1] = (FSMC_BTR1_ADDSET_2 | FSMC_BTR1_ADDSET_1) \
+				| (FSMC_BTR1_DATAST_2 | FSMC_BTR1_DATAST_1) \
+				| FSMC_BTR1_BUSTURN_0;
+
+		/* Bank1 NOR/PSRAM control register configuration
+		 * Write enable, memory databus width set to 16 bit, memory bank enable */
+		FSMC_Bank1->BTCR[0] = FSMC_BCR1_WREN | FSMC_BCR1_MWID_0 | FSMC_BCR1_MBKEN;
+
+		/* Display backlight control */
+		/* TIM4 is an alternate function 2 (AF2) */
+		pwmStart(&PWMD4, &pwmcfg);
+		palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
+		pwmEnableChannel(&PWMD4, 1, 100);
+		break;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if (state) {
+		CLR_RST;
+	} else {
+		SET_RST;
+	}
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	pwmEnableChannel(&PWMD4, 1, percent);
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	GDISP_REG = index;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	GDISP_RAM = data;
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return GDISP_RAM;
+}
+
+#if defined(GDISP_USE_DMA)
+	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+		dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+		dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		for (; area > 0; area -= 65535) {
+			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
+			dmaStreamEnable(GDISP_DMA_STREAM);
+			dmaWaitCompletion(GDISP_DMA_STREAM);
+		}
+	}
+
+	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+        dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
+        dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
+		for (; area > 0; area -= 65535) {
+			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
+			dmaStreamEnable(GDISP_DMA_STREAM);
+			dmaWaitCompletion(GDISP_DMA_STREAM);
+		}
+	}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+
diff --git a/drivers/gdisp/SSD2119/board_SSD2119_template.h b/drivers/gdisp/SSD2119/board_SSD2119_template.h
new file mode 100644
index 00000000..b4c6341d
--- /dev/null
+++ b/drivers/gdisp/SSD2119/board_SSD2119_template.h
@@ -0,0 +1,191 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD2119/board_SSD2119_template.h
+ * @brief   GDISP Graphic Driver subsystem board template for the SSD2119 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->board member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ *
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return 0;
+}
+
+/**
+ * The below section you can replace with #error if your interface doesn't support DMA
+ */
+#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
+	//#error "GDISP - SSD2119: This interface does not support DMA"
+
+	/**
+	 * @brief	Transfer data using DMA but don't increment the source address
+	 *
+	 * @param[in] g				The GDisplay structure
+	 * @param[in] buffer		The source buffer location
+	 * @param[in] area			The number of pixels to transfer
+	 *
+	 * @notapi
+	 */
+	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+		(void) buffer;
+		(void) area;
+	}
+
+	/**
+	 * @brief	Transfer data using DMA incrementing the source address
+	 *
+	 * @param[in] g				The GDisplay structure
+	 * @param[in] buffer		The source buffer location
+	 * @param[in] area			The number of pixels to transfer
+	 *
+	 * @notapi
+	 */
+	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
+		(void) g;
+		(void) buffer;
+		(void) area;
+	}
+#endif
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/SSD2119/gdisp_lld.c b/drivers/gdisp/SSD2119/gdisp_lld.c
index e3a2329a..df05fc2c 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld.c
+++ b/drivers/gdisp/SSD2119/gdisp_lld.c
@@ -8,20 +8,16 @@
 /**
  * @file    drivers/gdisp/SSD2119/gdisp_lld.c
  * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD2119 display.
- *
- * @addtogroup GDISP
- * @{
  */
 
 #include "gfx.h"
 
-#include "ssd2119.h"
-
 #if GFX_USE_GDISP
 
 #define GDISP_DRIVER_VMT			GDISPVMT_SSD2119
 #include "../drivers/gdisp/SSD2119/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
+
 #include "board_SSD2119.h"
 
 /*===========================================================================*/
@@ -41,6 +37,8 @@
 	#define GDISP_INITIAL_BACKLIGHT	100
 #endif
 
+#include "ssd2119.h"
+
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
@@ -60,23 +58,22 @@ static void set_cursor(GDisplay* g) {
 			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.y & 0x00FF);
 			break;
 		case GDISP_ROTATE_90:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - g->p.y - 1) & 0x01FF);
-			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - g->p.x - 1) & 0x00FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.y & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x00FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH - 1 - g->p.x) & 0x01FF);
-			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT - 1 - g->p.y) & 0x00FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x00FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.y & 0x01FF);
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x01FF);
 			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.x & 0x00FF);
 			break;
 	}
+	write_index(g, SSD2119_REG_RAM_DATA);
 }
 
 static void set_viewport(GDisplay* g) {
-	set_cursor(g->p.x, g->p.y);
-
 	/* Reg 0x44 - Vertical RAM address position
 	 * 		Upper Byte - VEA
 	 * 		Lower Byte - VSA
@@ -85,7 +82,6 @@ static void set_viewport(GDisplay* g) {
 	 * 		Lower 9 bits gives 0-511 range in each value, HSA and HEA respectively
 	 * 		0 <= HSA <= HEA <= 0x13F
 	 */
-
 	switch(g->g.Orientation) {
 		case GDISP_ROTATE_0:
 			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.y + g->p.cy - 1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
@@ -93,27 +89,21 @@ static void set_viewport(GDisplay* g) {
 			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.x + g->p.cx - 1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_90:
-			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT - g->p.x - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x00FF));
-			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x01FF);
-			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH - g->p.y - 1) & 0x01FF);
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (g->p.y & 0x01FF));
+			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.y + g->p.cy - 1) & 0x01FF);
 			break;
 		case GDISP_ROTATE_180:
-			write_reg(SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT - g->p.y - 1) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x00FF));
-			write_reg(SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x01FF);
-			write_reg(SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH - g->p.x - 1) & 0x01FF);
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x01FF);
+			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x01FF);
 			break;
 		case GDISP_ROTATE_270:
-			write_reg(SSD2119_REG_V_RAM_POS,   (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
-			write_reg(SSD2119_REG_H_RAM_START, (g->p.y & 0x01FF));
-			write_reg(SSD2119_REG_H_RAM_END,   (g->p.y + g->p.cy - 1) & 0x01FF);
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x01FF);
+			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x01FF);
 			break;
 	}
-
-	set_cursor(g->p.x, g->p.y);
-}
-
-static inline void reset_viewport(GDisplay* g) {
-	set_viewport(0, 0, g->g.Width, g->g.Height);
 }
 
 /*===========================================================================*/
@@ -129,7 +119,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 	g->priv = 0;
 
 	// initialise the board interface
-	init_board();
+	init_board(g);
 
 	// Hardware reset
 	setpin_reset(g, TRUE);
@@ -223,20 +213,22 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 	write_reg(g, SSD2119_REG_Y_RAM_ADDR, 0x00);
 	gfxSleepMicroseconds(5);
 
-	// Release the bus
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
 	release_bus(g);
 
-	// Turn on the backlight
+	/* Turn on the back-light */
 	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
 
-	// Initialise the GDISP structure
+	/* 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;
 }
 
@@ -261,14 +253,14 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
-		set_readmode(g);
+		setreadmode(g);
 		dummy_read(g);
 	}
 	LLDSPEC color_t gdisp_lld_read_color(GDisplay* g) {
 		return read_data(g);
 	}
 	LLDSPEC void gdisp_lld_read_stop(GDisplay* g) {
-		set_writemode(g);
+		setwritemode(g);
 		release_bus(g);
 	}
 #endif
@@ -278,7 +270,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);	
-		dma_with_noinc(g, &color, g->p.cx * g->p.cy);
+		dma_with_noinc(g, &g->p.color, g->p.cx * g->p.cy);
 		release_bus(g);
 	}
 #endif
@@ -306,450 +298,104 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 #endif
 
 #if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDisplay* g) {
-		// ....
-	}
-#endif
-
-
-//////////////////////// OLD STUFF FROM HERE ////////////////////////////////////////////////////
-
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-		if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-	#endif
-	
-	acquire_bus();
-	set_cursor(x, y);
-	write_reg(SSD2119_REG_RAM_DATA, color);
-	release_bus();
-}
-
-/* ---- Optional Routines ---- */
-/*
-	All the below routines are optional.
-	Defining them will increase speed but everything
-	will work if they are not defined.
-	If you are not using a routine - turn it off using
-	the appropriate GDISP_HARDWARE_XXXX macro.
-	Don't bother coding for obvious similar routines if
-	there is no performance penalty as the emulation software
-	makes a good job of using similar routines.
-		eg. If gfillarea() is defined there is little
-			point in defining clear() unless the
-			performance bonus is significant.
-	For good performance it is suggested to implement
-		fillarea() and blitarea().
-*/
-
-#if GDISP_HARDWARE_CLEARS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Clear the display.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] color    The color of the pixel
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_clear(color_t color) {
-		unsigned area;
-
-		area = GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT;
-
-		acquire_bus();
-		reset_viewport();
-		set_cursor(0, 0);
-		stream_start();
-
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint8_t i;
-			dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-			for (i = area / 65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			}
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area % 65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			uint32_t index;
-			for(index = 0; index < area; index++)
-				write_data(color);
-		#endif // defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-
-		stream_stop();
-		release_bus();
-	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a color.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] color    The color of the fill
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_fill_area(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
-		unsigned area;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		area = cx*cy;
-
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint8_t i;
-				dmaStreamSetPeripheral(GDISP_DMA_STREAM, &color);
-				dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-			for (i = area / 65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			}
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area % 65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			uint32_t index;
-			for(index = 0; index < area; index++)
-				write_data(color);
-		#endif // defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-
-		stream_stop();
-		release_bus();
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	/**
-	 * @brief   Fill an area with a bitmap.
-	 * @note    Optional - The high level driver can emulate using software.
-	 *
-	 * @param[in] x, y     The start filled area
-	 * @param[in] cx, cy   The width and height to be filled
-	 * @param[in] srcx, srcy   The bitmap position to start the fill from
-	 * @param[in] srccx    The width of a line in the bitmap.
-	 * @param[in] buffer   The pixels to use to fill the area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_blit_area_ex(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) {
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; srcx += GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; srcy += GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (srcx+cx > srccx)		cx = srccx - srcx;
-			if (cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1)	cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1)	cy = GDISP.clipy1 - y;
-		#endif
-
-		buffer += srcx + srcy * srccx;
-
-		acquire_bus();
-		set_viewport(x, y, cx, cy);
-		stream_start();
-
-		#if defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			uint32_t area = cx * cy;
-			uint8_t i;
-			dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-			for (i = area / 65535; i; i--) {
-				dmaStreamSetTransactionSize(GDISP_DMA_STREAM, 65535);
-				dmaStreamEnable(GDISP_DMA_STREAM);
-				dmaWaitCompletion(GDISP_DMA_STREAM);
-			}
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area % 65535);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		#else
-			coord_t endx, endy;
-			uint32_t lg;
-			endx = srcx + cx;
-			endy = y + cy;
-			lg = srccx - cx;
-			for(; y < endy; y++, buffer += lg)
-				for(x=srcx; x < endx; x++)
-					write_data(*buffer++);
-		#endif // defined(GDISP_USE_FSMC) && defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-
-		stream_stop();
-		release_bus();
-	}
-#endif
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Get the color of a particular pixel.
-	 * @note    Optional.
-	 * @note    If x,y is off the screen, the result is undefined.
-	 *
-	 * @param[in] x, y     The pixel to be read
-	 *
-	 * @notapi
-	 */
-	color_t gdisp_lld_get_pixel_color(coord_t x, coord_t y) {
-		color_t color;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
-		#endif
-
-		acquire_bus();
-		set_cursor(x, y);
-		stream_start();
-
-		color = read_data(); // dummy read
-		color = read_data();
-
-		stream_stop();
-		release_bus();
-
-		return color;
-	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	/**
-	 * @brief   Scroll vertically a section of the screen.
-	 * @note    Optional.
-	 * @note    If x,y + cx,cy is off the screen, the result is undefined.
-	 * @note    If lines is >= cy, it is equivelent to a area fill with bgcolor.
-	 *
-	 * @param[in] x, y     The start of the area to be scrolled
-	 * @param[in] cx, cy   The size of the area to be scrolled
-	 * @param[in] lines    The number of lines to scroll (Can be positive or negative)
-	 * @param[in] bgcolor  The color to fill the newly exposed area.
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_vertical_scroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) {
-		static color_t buf[((GDISP_SCREEN_HEIGHT > GDISP_SCREEN_WIDTH ) ? GDISP_SCREEN_HEIGHT : GDISP_SCREEN_WIDTH)];
-		coord_t row0, row1;
-		unsigned i, gap, abslines, j;
-
-		#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-			if (x < GDISP.clipx0) { cx -= GDISP.clipx0 - x; x = GDISP.clipx0; }
-			if (y < GDISP.clipy0) { cy -= GDISP.clipy0 - y; y = GDISP.clipy0; }
-			if (!lines || cx <= 0 || cy <= 0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
-			if (x+cx > GDISP.clipx1) cx = GDISP.clipx1 - x;
-			if (y+cy > GDISP.clipy1) cy = GDISP.clipy1 - y;
-		#endif
-
-		abslines = lines < 0 ? -lines : lines;
-
-		acquire_bus();
-		if ((coord_t)abslines >= cy) {
-			abslines = cy;
-			gap = 0;
-		} else {
-			gap = cy - abslines;
-			for(i = 0; i < gap; i++) {
-				if(lines > 0) {
-					row0 = y + i + lines;
-					row1 = y + i;
-				} else {
-					row0 = (y - i - 1) + lines;
-					row1 = (y - i - 1);
-				}
-
-				/* read row0 into the buffer and then write at row1*/
-				set_viewport(x, row0, cx, 1);
-				stream_start();
-
-				j = read_data(); // dummy read
-				for (j = 0; (coord_t)j < cx; j++)
-					buf[j] = read_data();
-
-				stream_stop();
-
-				set_viewport(x, row1, cx, 1);
-				stream_start();
-				for (j = 0; (coord_t)j < cx; j++)
-					write_data(buf[j]);
-				stream_stop();
-			}
-		}
-
-		/* fill the remaining gap */
-		set_viewport(x, lines > 0 ? (y+(coord_t)gap) : y, cx, abslines);
-		stream_start();
-		gap = cx*abslines;
-		for(i = 0; i < gap; i++) write_data(bgcolor);
-		stream_stop();
-		release_bus();
-	}
-#endif
-
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	/**
-	 * @brief	Driver Control
-	 * @details	Unsupported control codes are ignored.
-	 * @note	The value parameter should always be typecast to (void *).
-	 * @note	There are some predefined and some specific to the low level driver.
-	 * @note	GDISP_CONTROL_POWER			- Takes a gdisp_powermode_t
-	 * 			GDISP_CONTROL_ORIENTATION	- Takes a gdisp_orientation_t
-	 * 			GDISP_CONTROL_BACKLIGHT		- Takes an int from 0 to 100. For a driver
-	 * 											that only supports off/on anything other
-	 * 											than zero is on.
-	 *
-	 * @param[in] what		What to do.
-	 * @param[in] value		The value to use (always cast to a void *).
-	 *
-	 * @notapi
-	 */
-	void gdisp_lld_control(unsigned what, void *value) {
-		switch(what) {
-			case GDISP_CONTROL_POWER:
-				if (GDISP.Powermode == (gdisp_powermode_t)value)
-					return;
-				switch((gdisp_powermode_t)value) {
-					case powerOff:
-						acquire_bus();
-						write_reg(SSD2119_REG_SLEEP_MODE_1,	0x0001);	// Enter sleep mode
-						write_reg(SSD2119_REG_DISPLAY_CTRL,	0x0000);	// Display off
-						write_reg(SSD2119_REG_OSC_START,	0x0000);	// Turn off oscillator
-						release_bus();
-						set_backlight(0);
-						break;
-
-					case powerOn:
-						if (GDISP.Powermode == powerSleep) {
-							acquire_bus();
-							write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);	// Leave sleep mode
-							write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0033);	// Display on
-							release_bus();
-							gfxSleepMilliseconds(170);
-						} else if (GDISP.Powermode == powerDeepSleep) {
-							acquire_bus();
-							write_reg(SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
-							write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);	// Leave sleep mode
-							write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0033);	// Display on
-							release_bus();
-							gfxSleepMilliseconds(170);
-						} else {
-							acquire_bus();
-							write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0000);	// Leave sleep mode
-							release_bus();
-							gdisp_lld_init();
-						}
-						set_backlight(100);
-						break;
-
-					case powerSleep:
-						acquire_bus();
-						write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0001);	// Enter sleep mode
-						write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0000);	// Display off
-						release_bus();
-						set_backlight(0);
-						gfxSleepMilliseconds(25);
-						break;
-
-					case powerDeepSleep:
-						acquire_bus();
-						write_reg(SSD2119_REG_SLEEP_MODE_1, 0x0001);	// Enter sleep mode
-						write_reg(SSD2119_REG_SLEEP_MODE_2, 0x2999);	// Enable deep sleep function
-						write_reg(SSD2119_REG_DISPLAY_CTRL, 0x0000);	// Display off
-						release_bus();
-						set_backlight(0);
-						gfxSleepMilliseconds(25);
-						break;
-
-					default:
-						return;
-				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
+	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;
-
-			case GDISP_CONTROL_ORIENTATION:
-				if (GDISP.Orientation == (gdisp_orientation_t)value)
-					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						acquire_bus();
-						/* TB = 0 */
-						write_reg(SSD2119_REG_OUTPUT_CTRL, 0x30EF);
-						/* ID = 11 AM = 0 */
-						write_reg(SSD2119_REG_ENTRY_MODE, 0x6830);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_90:
-						acquire_bus();
-						/* TB = 1 */
-						write_reg(SSD2119_REG_OUTPUT_CTRL, 0x32EF);
-						/* ID = 10 AM = 1 */
-						write_reg(SSD2119_REG_ENTRY_MODE, 0x6828);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-
-					case GDISP_ROTATE_180:
-						acquire_bus();
-						/* TB = 0 */
-						write_reg(SSD2119_REG_OUTPUT_CTRL, 0x30EF);
-						/* ID = 00 AM = 0 */
-						write_reg(SSD2119_REG_ENTRY_MODE, 0x6800);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_270:
-						acquire_bus();
-						/* TB = 1 */
-						write_reg(SSD2119_REG_OUTPUT_CTRL, 0x32EF);
-						/* ID = 01 AM = 1 */
-						write_reg(SSD2119_REG_ENTRY_MODE, 0x6818);
-						release_bus();
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-
-					default:
-						return;
-				}
-
-				#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION
-				GDISP.clipx0 = 0;
-				GDISP.clipy0 = 0;
-				GDISP.clipx1 = GDISP.Width;
-				GDISP.clipy1 = GDISP.Height;
-				#endif
-				g->g.Orientation = (orientation_t)g->p.ptr;
+			switch((powermode_t)g->p.ptr) {
+			case powerOff:
+			case powerDeepSleep:
+				acquire_bus(g);
+				write_reg(g, SSD2119_REG_SLEEP_MODE_1,	0x0001);	// Enter sleep mode
+				write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x2999);		// Enable deep sleep function
+				write_reg(g, SSD2119_REG_DISPLAY_CTRL,	0x0000);	// Display off
+				if ((powermode_t)g->p.ptr == powerOff)
+					write_reg(g, SSD2119_REG_OSC_START,	0x0000);	// Turn off oscillator
+				release_bus(g);
+				set_backlight(g, 0);
+				break;
+			case powerSleep:
+				acquire_bus(g);
+				write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0001);		// Enter sleep mode
+				write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0000);		// Display off
+				release_bus(g);
+				set_backlight(g, 0);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				if (g->g.Powermode == powerOff) {
+					write_reg(g, SSD2119_REG_OSC_START, 0x0001);	// Start the oscillator
+					gfxSleepMicroseconds(5);
+					write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
+				} else if (g->g.Powermode == powerDeepSleep)
+					write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
+				write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0000);		// Leave sleep mode
+				write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0033);		// Display on
+				release_bus(g);
+				gfxSleepMicroseconds(25);
+				set_backlight(g, g->g.Backlight);
+				break;
+			default:
 				return;
+			}
+			g->g.Powermode = (powermode_t)g->p.ptr;
+			return;
 
-			case GDISP_CONTROL_BACKLIGHT:
-				if ((unsigned)value > 100)
-					value = (void *)100;
-				set_backlight((unsigned)value);
-				GDISP.Backlight = (unsigned)value;
+		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);
+				/* ID = 11 AM = 0 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6830);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				/* ID = 01 AM = 1 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6818);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				/* ID = 00 AM = 0 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6800);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				/* ID = 10 AM = 1 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6828);
+				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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
 		}
 	}
 #endif
 
 #endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/gdisp/SSD2119/gdisp_lld.mk b/drivers/gdisp/SSD2119/gdisp_lld.mk
index e9c70efb..46807f62 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld.mk
+++ b/drivers/gdisp/SSD2119/gdisp_lld.mk
@@ -1,5 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/SSD2119/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/SSD2119
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD2119/gdisp_lld.c
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h b/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h
deleted file mode 100644
index 126cd960..00000000
--- a/drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD2119/gdisp_lld_board_embest_dmstf4bb.h
- * @brief   GDISP Graphic Driver subsystem board FSMC interface for the SSD2119 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/* This board file uses only FSMC, so don't undefine this. */
-#define GDISP_USE_FSMC
-/* But it is OK to disable DMA use. */
-#define GDISP_USE_DMA
-#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
-
-/* Using FSMC A19 (PE3) as DC */
-#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* DC = 0 */
-#define GDISP_RAM (*((volatile uint16_t *) 0x60100000)) /* DC = 1 */
-
-#define SET_RST palSetPad(GPIOD, 3);
-#define CLR_RST palClearPad(GPIOD, 3);
-
-/*
- * PWM configuration structure. We use timer 4 channel 2 (orange LED on board).
- * The reason for so high clock is that with any lower, onboard coil is squeaking.
- * The major disadvantage of this clock is a lack of linearity between PWM duty
- * cycle width and brightness. In fact only with low preset one sees any change
- * (eg. duty cycle between 1-20). Feel free to adjust this, maybe only my board
- * behaves like this. According to the G5126 datesheet (backlight LED driver)
- * the PWM frequency should be somewhere between 200 Hz to 200 kHz.
- */
-static const PWMConfig pwmcfg = {
-	1000000,       /* 1 MHz PWM clock frequency. */
-	100,           /* PWM period is 100 cycles. */
-	NULL,
-	{
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
-	},
-	0
-};
-
-/**
- * @brief   Initialise the board for the display.
- * @notes   This board definition uses GPIO and assumes exclusive access to these GPIO pins
- *
- * @notapi
- */
-static inline void init_board(void) {
-	unsigned char FSMC_Bank;
-
-	#ifndef GDISP_USE_FSMC
-		#error "This board uses only FSMC, please define GDISP_USE_FSMC"
-	#endif
-
-	#if defined(STM32F4XX) || defined(STM32F2XX)
-		/* STM32F4 FSMC init */
-		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-		#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-			if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL))
-				gfxExit();
-			dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
-			dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		#endif
-	#else
-		#error "FSMC not implemented for this device"
-	#endif
-
-	/* Group pins */
-	IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-							(1 << 9) | (1 << 10) | (1 << 14) | (1 << 15), 0};
-
-	IOBus busE = {GPIOE, (1 << 3) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-							(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-	/* FSMC is an alternate function 12 (AF12) */
-	palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-	palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-	FSMC_Bank = 0;
-	/* FSMC timing register configuration */
-	FSMC_Bank1->BTCR[FSMC_Bank + 1] = (FSMC_BTR1_ADDSET_2 | FSMC_BTR1_ADDSET_1) \
-			| (FSMC_BTR1_DATAST_2 | FSMC_BTR1_DATAST_1) \
-			| FSMC_BTR1_BUSTURN_0;
-
-	/* Bank1 NOR/PSRAM control register configuration
-	 * Write enable, memory databus width set to 16 bit, memory bank enable */
-	FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_WREN | FSMC_BCR1_MWID_0 | FSMC_BCR1_MBKEN;
-
-	/* Display backlight control */
-	/* TIM4 is an alternate function 2 (AF2) */
-	pwmStart(&PWMD4, &pwmcfg);
-	palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
-	pwmEnableChannel(&PWMD4, 1, 100);
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- *
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-	if (state) {
-		CLR_RST;
-	} else {
-		SET_RST;
-	}
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- *
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-	pwmEnableChannel(&PWMD4, 1, percent);
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @note	Not needed, not implemented
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @note	Not needed, not implemented
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-	GDISP_REG = index;
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- *
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- *
- * @notapi
- */
-static inline uint16_t read_data(void) {
-	return GDISP_RAM;
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_board_template.h b/drivers/gdisp/SSD2119/gdisp_lld_board_template.h
deleted file mode 100644
index 2e4d53df..00000000
--- a/drivers/gdisp/SSD2119/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD2119/gdisp_lld_board_template.h
- * @brief   GDISP Graphic Driver subsystem board template for the SSD2119 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/**
- * @brief   Initialise the board for the display.
- * @notes   This board definition uses GPIO and assumes exclusive access to these GPIO pins
- *
- * @notapi
- */
-static inline void init_board(void) {
-
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- *
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- *
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-
-}
-
-/**
- * @brief   Set the lcd back-light level.
- *
- * @param[in] percent		0 to 100%
- *
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @note	Not needed, not implemented
- *
- * @notapi
- */
-static inline void acquire_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @note	Not needed, not implemented
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	/* Nothing to do here since LCD is the only device on that bus */
-}
-
-/**
- * @brief   Send data to the index register.
- *
- * @param[in] index		The index register to set
- *
- * @notapi
- */
-static inline void write_index(uint16_t index) {
-
-}
-
-/**
- * @brief   Send data to the lcd.
- *
- * @param[in] data		The data to send
- *
- * @notapi
- */
-static inline void write_data(uint16_t data) {
-
-}
-
-#if GDISP_HARDWARE_READPIXEL || GDISP_HARDWARE_SCROLL || defined(__DOXYGEN__)
-/**
- * @brief   Read data from the lcd.
- *
- * @return	The data from the lcd
- * @note	The chip select may need to be asserted/de-asserted
- * 			around the actual spi read
- *
- * @notapi
- */
-static inline uint16_t read_data(void) {
-
-}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_config.h b/drivers/gdisp/SSD2119/gdisp_lld_config.h
index 3ad247e6..5d81057c 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD2119/gdisp_lld_config.h
@@ -22,15 +22,16 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME				"SSD2119"
-
-#define GDISP_HARDWARE_CLEARS			TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			TRUE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+#define GDISP_HARDWARE_STREAM_READ		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
+#if defined(GDISP_USE_DMA)
+	#define GDISP_HARDWARE_FILLS		TRUE
+	#define GDISP_HARDWARE_BITFILLS		TRUE
+#endif
+
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
-- 
cgit v1.2.3


From 299cb353afcb1f43b8d209db80e9d186b62d9a3d Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 22 Oct 2013 19:52:54 +1000
Subject: Bug fixes to SSD1306. Orientation in all directions is also now
 supported.

---
 drivers/gdisp/SSD1306/gdisp_lld.c | 79 +++++++++++++++++++++++++++++----------
 1 file changed, 59 insertions(+), 20 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c
index b0834193..079c9256 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.c
+++ b/drivers/gdisp/SSD1306/gdisp_lld.c
@@ -51,8 +51,11 @@
 #define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
 
 // Some common routines and macros
-#define delay(us)					gfxSleepMicroseconds(us)
-#define delayms(ms)					gfxSleepMilliseconds(ms)
+#define delay(us)			gfxSleepMicroseconds(us)
+#define delayms(ms)			gfxSleepMilliseconds(ms)
+
+#define xyaddr(x, y)		((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
+#define xybit(y)			(1<<((y)&7))
 
 /*===========================================================================*/
 /* Driver exported functions.                                                */
@@ -135,17 +138,57 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 #if GDISP_HARDWARE_DRAWPIXEL
 	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			x = g->p.x;
+			break;
+		}
 		if (g->p.color != Black)
-			RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] |=  (1<<(g->p.y&7));
+			RAM(g)[xyaddr(x, y)] |= xybit(y);
 		else
-			RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] &=  ~(1<<(g->p.y&7));
+			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
 		g->flags |= GDISP_FLG_NEEDFLUSH;
 	}
 #endif
 
 #if GDISP_HARDWARE_PIXELREAD
 	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
-		return (RAM(g)[g->p.x + (g->p.y>>3)*GDISP_SCREEN_WIDTH] & (1<<(g->p.y&7))) ? White : Black;
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			y = g->p.x;
+			break;
+		}
+		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
 	}
 #endif
 
@@ -167,6 +210,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				acquire_bus(g);
 				write_cmd(g, SSD1306_DISPLAYON);
 				release_bus(g);
+				break;
 			default:
 				return;
 			}
@@ -177,21 +221,16 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			if (g->g.Orientation == (orientation_t)g->p.ptr)
 				return;
 			switch((orientation_t)g->p.ptr) {
+			/* Rotation is handled by the drawing routines */
 			case GDISP_ROTATE_0:
-				acquire_bus(g);
-				write_cmd(g, SSD1306_COMSCANDEC);
-				write_cmd(g, SSD1306_SEGREMAP+1);
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
-				release_bus(g);
-				break;
 			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				write_cmd(g, SSD1306_COMSCANINC);
-				write_cmd(g, SSD1306_SEGREMAP);
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
-				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+			case GDISP_ROTATE_270:
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			default:
 				return;
@@ -203,14 +242,14 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
             if ((unsigned)g->p.ptr > 100)
             	g->p.ptr = (void *)100;
 			acquire_bus(g);
-			write_cmd2(g, SSD1306_SETCONTRAST, (((uint16_t)value)<<8)/101);
+			write_cmd2(g, SSD1306_SETCONTRAST, (((unsigned)g->p.ptr)<<8)/101);
 			release_bus(g);
             g->g.Contrast = (unsigned)g->p.ptr;
 			return;
 
 		// Our own special controller code to inverse the display
 		// 0 = normal, 1 = inverse
-		case GDISP_CONTROL_INVERT:
+		case GDISP_CONTROL_INVERSE:
 			acquire_bus(g);
 			write_cmd(g, g->p.ptr ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
 			release_bus(g);
-- 
cgit v1.2.3


From 92b00e125cf8d7754e12fd05e0a2cdfd6550af07 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 22 Oct 2013 19:53:39 +1000
Subject: Convert ST7565 driver to new driver format.

---
 drivers/gdisp/ST7565/board_ST7565_template.h    | 108 ++++++
 drivers/gdisp/ST7565/gdisp_lld.c                | 435 ++++++++++++------------
 drivers/gdisp/ST7565/gdisp_lld.mk               |   6 +-
 drivers/gdisp/ST7565/gdisp_lld_board_template.h |  82 -----
 drivers/gdisp/ST7565/gdisp_lld_config.h         |  11 +-
 5 files changed, 328 insertions(+), 314 deletions(-)
 create mode 100644 drivers/gdisp/ST7565/board_ST7565_template.h
 delete mode 100644 drivers/gdisp/ST7565/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ST7565/board_ST7565_template.h b/drivers/gdisp/ST7565/board_ST7565_template.h
new file mode 100644
index 00000000..aef6cf2b
--- /dev/null
+++ b/drivers/gdisp/ST7565/board_ST7565_template.h
@@ -0,0 +1,108 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ST7565/board_ST7565_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ST7565 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->board member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ *
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send a command to the controller.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] cmd			The command to send *
+ *
+ * @notapi
+ */
+static inline void write_cmd(GDisplay *g, uint8_t cmd) {
+	(void) g;
+	(void) cmd;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ *
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
+	(void) g;
+	(void) data;
+	(void) length;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/ST7565/gdisp_lld.c b/drivers/gdisp/ST7565/gdisp_lld.c
index 960b1389..bd8c7b74 100644
--- a/drivers/gdisp/ST7565/gdisp_lld.c
+++ b/drivers/gdisp/ST7565/gdisp_lld.c
@@ -5,265 +5,258 @@
  *              http://ugfx.org/license.html
  */
 
-#include "gfx.h"
+/**
+ * @file    drivers/gdisp/ST7565/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ST7565 display.
+ */
 
-#if GFX_USE_GDISP || defined(__DOXYGEN__)
+#include "gfx.h"
 
+#if GFX_USE_GDISP
 
-/* Include the emulation code for things we don't support */
-#include "gdisp/lld/emulation.c"
-#include "st7565.h"
-#include "gdisp_lld_board.h"
+#define GDISP_DRIVER_VMT			GDISPVMT_ST7565
+#include "../drivers/gdisp/ST7565/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
 
+#include "board_ST7565.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
 /*===========================================================================*/
 
 #ifndef GDISP_SCREEN_HEIGHT
-#define GDISP_SCREEN_HEIGHT		64
+	#define GDISP_SCREEN_HEIGHT		64
 #endif
 #ifndef GDISP_SCREEN_WIDTH
-#define GDISP_SCREEN_WIDTH		128
+	#define GDISP_SCREEN_WIDTH		128
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	51
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
 #endif
 
-#define GDISP_INITIAL_CONTRAST		0xFF
+#define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
+
+#include "st7565.h"
 
 /*===========================================================================*/
 /* Driver local functions.                                                   */
 /*===========================================================================*/
 
 // Some common routines and macros
-#define delay(us)         gfxSleepMicroseconds(us)
-#define delay_ms(ms)      gfxSleepMilliseconds(ms)
+#define RAM(g)							((uint8_t *)g->priv)
+#define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); }
+#define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
 
-// The memory buffer for the display
-static uint8_t gdisp_buffer[GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8];
+// Some common routines and macros
+#define delay(us)			gfxSleepMicroseconds(us)
+#define delay_ms(ms)		gfxSleepMilliseconds(ms)
 
-/** Set the display to normal or inverse.
- *  @param[in] value 0 for normal mode, or 1 for inverse mode.
- *  @notapi
- */
-static void invert_display(uint8_t i) {
-  write_cmd(i ? ST7565_INVERT_DISPLAY : ST7565_POSITIVE_DISPLAY);
-}
+#define xyaddr(x, y)		((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
+#define xybit(y)			(1<<((y)&7))
 
-/** Turn the whole display off.
- *	Sends the display to sleep, but leaves RAM intact.
- *	@notapi
- */
-static void display_off(void) {
-  write_cmd(ST7565_DISPLAY_OFF);
-}
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
 
-/** Turn the whole display on.
- * 	Wakes up this display following a sleep() call.
- *	@notapi
+/**
+ * As this controller can't update on a pixel boundary we need to maintain the
+ * the entire display surface in memory so that we can do the necessary bit
+ * operations. Fortunately it is a small display in monochrome.
+ * 64 * 128 / 8 = 1024 bytes.
  */
-static void display_on(void) {
-  write_cmd(ST7565_DISPLAY_ON);
-}
 
-/** Set the display contrast.
- *  @param[in] value The contrast, from 1 to 63.
- *	@notapi
- */
-static void set_contrast(uint8_t value) {
-  write_cmd(ST7565_CONTRAST);
-  write_cmd(value & 0x3F);
-}
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	// The private area is the display surface.
+	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
 
-/** Set the display start line.  This is the line at which the display will start rendering.
- *  @param[in] value A value from 0 to 63 denoting the line to start at.
- *	@notapi
- */
-static void set_display_start_line(unsigned char value) {
-  write_cmd(ST7565_START_LINE | value);
-}
+	// Initialise the board interface
+	init_board(g);
 
-static void gdisp_lld_display(void) {
-  uint8_t p;
-  set_display_start_line(0);
-
-  for (p = 0; p < 8; p++) {
-    write_cmd(ST7565_PAGE | p);
-    write_cmd(ST7565_COLUMN_MSB | 0);
-    write_cmd(ST7565_COLUMN_LSB | 0);
-    write_cmd(ST7565_RMW);
-    write_data(&gdisp_buffer[p * GDISP_SCREEN_WIDTH], GDISP_SCREEN_WIDTH);
-  }
-}
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
 
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
+	acquire_bus(g);
 
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
+	write_cmd(g, ST7565_LCD_BIAS_7);
+	write_cmd(g, ST7565_ADC_NORMAL);
+	write_cmd(g, ST7565_COM_SCAN_INC);
+	write_cmd(g, ST7565_START_LINE | 0);
 
-/* ---- Required Routines ---- */
-/*
- The following 2 routines are required.
- All other routines are optional.
- */
+	write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101);
+	write_cmd(g, ST7565_RESISTOR_RATIO | 0x3);
 
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t gdisp_lld_init(void) {
-  // Initialize your display
-  init_board();
-
-  // Hardware reset.
-  setpin_reset(TRUE);
-  delay_ms(10);
-  setpin_reset(FALSE);
-  delay_ms(1);
-
-  write_cmd(ST7565_LCD_BIAS_7);
-  write_cmd(ST7565_ADC_NORMAL);
-  write_cmd(ST7565_COM_SCAN_INC);
-  set_display_start_line(0);
-
-  set_contrast(32);
-  write_cmd(ST7565_RESISTOR_RATIO | 0x3);
-
-  // turn on voltage converter (VC=1, VR=0, VF=0)
-  write_cmd(ST7565_POWER_CONTROL | 0x04);
-  delay_ms(50);
-  // turn on voltage regulator (VC=1, VR=1, VF=0)
-  write_cmd(ST7565_POWER_CONTROL | 0x06);
-  delay_ms(50);
-  // turn on voltage follower (VC=1, VR=1, VF=1)
-  write_cmd(ST7565_POWER_CONTROL | 0x07);
-  delay_ms(50);
-
-  display_on();
-  write_cmd(ST7565_ALLON_NORMAL);
-  invert_display(0);// Disable Inversion of display.
-
-  write_cmd(ST7565_RMW);
-  gdisp_lld_display();
-
-  // Initialize the GDISP structure
-  GDISP.Width = GDISP_SCREEN_WIDTH;
-  GDISP.Height = GDISP_SCREEN_HEIGHT;
-  GDISP.Orientation = GDISP_ROTATE_0;
-  GDISP.Powermode = powerOn;
-  GDISP.Contrast = 50;
-#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-  GDISP.clipx0 = 0;
-  GDISP.clipy0 = 0;
-  GDISP.clipx1 = GDISP.Width;
-  GDISP.clipy1 = GDISP.Height;
-#endif
-  return TRUE;
+	// turn on voltage converter (VC=1, VR=0, VF=0)
+	write_cmd(g, ST7565_POWER_CONTROL | 0x04);
+	delay_ms(50);
+
+	// turn on voltage regulator (VC=1, VR=1, VF=0)
+	write_cmd(g, ST7565_POWER_CONTROL | 0x06);
+	delay_ms(50);
+
+	// turn on voltage follower (VC=1, VR=1, VF=1)
+	write_cmd(g, ST7565_POWER_CONTROL | 0x07);
+	delay_ms(50);
+
+	write_cmd(g, ST7565_DISPLAY_ON);
+	write_cmd(g, ST7565_ALLON_NORMAL);
+	write_cmd(g, ST7565_POSITIVE_DISPLAY);	// Disable Inversion of display.
+
+	write_cmd(g, ST7565_RMW);
+
+    // 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;
 }
 
-/**
- * @brief   Draws a pixel on the display.
- *
- * @param[in] x        X location of the pixel
- * @param[in] y        Y location of the pixel
- * @param[in] color    The color of the pixel
- *
- * @notapi
- */
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color) {
-#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-  if (x < GDISP.clipx0 || y < GDISP.clipy0 || x >= GDISP.clipx1 || y >= GDISP.clipy1) return;
+#if GDISP_HARDWARE_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		unsigned	p;
+
+		// Don't flush if we don't need it.
+		if (!(g->flags & GDISP_FLG_NEEDFLUSH))
+			return;
+
+		acquire_bus(g);
+		for (p = 0; p < 8; p++) {
+			write_cmd(g, ST7565_PAGE | p);
+			write_cmd(g, ST7565_COLUMN_MSB | 0);
+			write_cmd(g, ST7565_COLUMN_LSB | 0);
+			write_cmd(g, ST7565_RMW);
+			write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH);
+		}
+		release_bus(g);
+	}
 #endif
 
-  if (color == 1)
-  gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] |= (1<<y%8);
-  else
-  gdisp_buffer[x+ (y/8)*GDISP_SCREEN_WIDTH] &= ~(1<<y%8);
-}
+#if GDISP_HARDWARE_DRAWPIXEL
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			y = g->p.x;
+			break;
+		}
+		if (g->p.color != Black)
+			RAM(g)[xyaddr(x, y)] |= xybit(y);
+		else
+			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
+		g->flags |= GDISP_FLG_NEEDFLUSH;
+	}
+#endif
 
-/* ---- Optional Routines ---- */
-/*
- All the below routines are optional.
- Defining them will increase speed but everything
- will work if they are not defined.
- If you are not using a routine - turn it off using
- the appropriate GDISP_HARDWARE_XXXX macro.
- Don't bother coding for obvious similar routines if
- there is no performance penalty as the emulation software
- makes a good job of using similar routines.
- eg. If gfillarea() is defined there is little
- point in defining clear() unless the
- performance bonus is significant.
- For good performance it is suggested to implement
- fillarea() and blitarea().
- */
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			x = g->p.x;
+			break;
+		}
+		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
+	}
+#endif
 
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-/**
- * @brief   Driver Control
- * @details Unsupported control codes are ignored.
- * @note    The value parameter should always be typecast to (void *).
- * @note    There are some predefined and some specific to the low level driver.
- * @note    GDISP_CONTROL_POWER         - Takes a gdisp_powermode_t
- *          GDISP_CONTROL_ORIENTATION   - Takes a gdisp_orientation_t
- *          GDISP_CONTROL_BACKLIGHT 	- Takes an int from 0 to 100. For a driver
- *                                        that only supports off/on anything other
- *                                        than zero is on.
- *          GDISP_CONTROL_CONTRAST      - Takes an int from 0 to 100.
- *          GDISP_CONTROL_LLD           - Low level driver control constants start at
- *                                        this value.
- *
- * @param[in] what		What to do.
- * @param[in] value 	The value to use (always cast to a void *).
- *
- * @notapi
- */
-void gdisp_lld_control(unsigned what, void *value) {
-  switch(what) {
-    case GDISP_CONTROL_POWER:
-      if (GDISP.Powermode == (gdisp_powermode_t)value)
-        return;
-
-      switch((gdisp_powermode_t)value) {
-        case powerOff:
-          display_off();
-          break;
-        case powerSleep:
-          display_off();
-          break;
-        case powerDeepSleep:
-          display_off();
-          break;
-        case powerOn:
-          display_on();
-          break;
-        default:
-          return;
-      }
-      GDISP.Powermode = (gdisp_powermode_t)value;
-      return;
-
-    case GDISP_CONTROL_BACKLIGHT:
-      set_backlight((uint8_t)(size_t)value);
-      return;
-
-    case GDISP_CONTROL_CONTRAST:
-      if ((unsigned)value > 100) value = (void*)100;
-      if (GDISP.Contrast == (uint8_t)((float)((size_t)value) * 63.0/100.0))
-        return;
-      set_contrast((uint8_t)((float)((size_t)value) * 63.0/100.0) );
-      GDISP.Contrast = (unsigned)value;
-      return;
-
-    case GDISP_CONTROL_LLD_FLUSH:
-      gdisp_lld_display();
-      return;
-  }
-}
+#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, ST7565_DISPLAY_OFF);
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_cmd(g, ST7565_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) {
+			/* Rotation is handled by the drawing routines */
+			case GDISP_ROTATE_0:
+			case GDISP_ROTATE_180:
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+			case GDISP_ROTATE_270:
+				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_CONTRAST:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+			acquire_bus(g);
+			write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F);
+			release_bus(g);
+            g->g.Contrast = (unsigned)g->p.ptr;
+			return;
+		}
+	}
 #endif // GDISP_NEED_CONTROL
 
 #endif // GFX_USE_GDISP
-/** @} */
-
diff --git a/drivers/gdisp/ST7565/gdisp_lld.mk b/drivers/gdisp/ST7565/gdisp_lld.mk
index cd925824..cf0896e6 100644
--- a/drivers/gdisp/ST7565/gdisp_lld.mk
+++ b/drivers/gdisp/ST7565/gdisp_lld.mk
@@ -1,6 +1,2 @@
-# List the required driver.
-GFXSRC += $(GFXLIB)/drivers/gdisp/ST7565/gdisp_lld.c
-
-# Required include directories
 GFXINC += $(GFXLIB)/drivers/gdisp/ST7565
-
+GFXSRC += $(GFXLIB)/drivers/gdisp/ST7565/gdisp_lld.c
diff --git a/drivers/gdisp/ST7565/gdisp_lld_board_template.h b/drivers/gdisp/ST7565/gdisp_lld_board_template.h
deleted file mode 100644
index 2f40ccc7..00000000
--- a/drivers/gdisp/ST7565/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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
-
-/**
- * @brief   Initialize the board for the display.
- * @notes	This board definition uses GPIO and assumes exclusive access to these GPIO pins
- * @notapi
- */
-static inline void init_board(void) {
-  /* Configure SPI bus here. Up to 10Mhz, SPI Mode = 3 (CPOL = 1, CPHA = 0) */
-  /* Configure A0, !CS, !RST pin for output */
-}
-
-/**
- * @brief   Set or clear the lcd reset pin.
- * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
- * @notapi
- */
-static inline void setpin_reset(bool_t state) {
-  /* Set !CS to low */
-  if (state) {
-    /* Set !RST to low */
-  } else {
-    /* Set !RST to high */
-  }
-}
-
-/**
- * @brief   Set the lcd back-light level.
- * @param[in] percent		0 to 100%
- * @notapi
- */
-static inline void set_backlight(uint8_t percent) {
-
-}
-
-/**
- * @brief   Take exclusive control of the bus
- * @notapi
- */
-static inline void acquire_bus(void) {
-
-}
-
-/**
- * @brief   Release exclusive control of the bus
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Send command to the display.
- * @param[in] cmd	The command to send
- * @notapi
- */
-static inline void write_cmd(uint8_t cmd) {
-  /* Set A0 to low */
-  /* Transmit cmd over SPI */
-}
-
-/**
- * @brief   Send data to the display.
- * @param[in] data	The data to send
- * @notapi
- */
-static inline void write_data(uint8_t* data, uint16_t length) {
-  /* Set A0 to high */
-  /* Transmit data for length over SPI. DMA is recommended. */
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/gdisp/ST7565/gdisp_lld_config.h b/drivers/gdisp/ST7565/gdisp_lld_config.h
index 8d26a0aa..632dc431 100644
--- a/drivers/gdisp/ST7565/gdisp_lld_config.h
+++ b/drivers/gdisp/ST7565/gdisp_lld_config.h
@@ -14,13 +14,12 @@
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
 
-#define GDISP_DRIVER_NAME         "ST7565"
+#define GDISP_HARDWARE_FLUSH			TRUE		// This controller requires flushing
+#define GDISP_HARDWARE_DRAWPIXEL		TRUE
+#define GDISP_HARDWARE_PIXELREAD		TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_HARDWARE_CONTROL    TRUE
-
-#define GDISP_PIXELFORMAT         GDISP_PIXELFORMAT_MONO
-
-#define GDISP_CONTROL_LLD_FLUSH   (GDISP_CONTROL_LLD + 1)
+#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_MONO
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From c353b6e9b01393c3c90632c97b4da0a315645b8e Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 23 Oct 2013 01:33:43 +1000
Subject: Remove superflous defines

---
 drivers/gdisp/SSD1306/SSD1306.h | 3 ---
 drivers/gdisp/ST7565/st7565.h   | 3 ---
 2 files changed, 6 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1306/SSD1306.h b/drivers/gdisp/SSD1306/SSD1306.h
index 38507d48..47ca39e4 100644
--- a/drivers/gdisp/SSD1306/SSD1306.h
+++ b/drivers/gdisp/SSD1306/SSD1306.h
@@ -8,9 +8,6 @@
 #ifndef _SSD1306_H
 #define _SSD1306_H
 
-#define SSD1306_BLACK 0
-#define SSD1306_WHITE 1
-
 #define SSD1306_SETCONTRAST 			0x81
 #define SSD1306_DISPLAYALLON_RESUME 	0xA4
 #define SSD1306_DISPLAYALLON 			0xA5
diff --git a/drivers/gdisp/ST7565/st7565.h b/drivers/gdisp/ST7565/st7565.h
index b1f43f6b..9542dd3f 100644
--- a/drivers/gdisp/ST7565/st7565.h
+++ b/drivers/gdisp/ST7565/st7565.h
@@ -8,9 +8,6 @@
 #ifndef _ST7565_H
 #define _ST7565_H
 
-#define ST7565_BLACK 0
-#define ST7565_WHITE 1
-
 #define ST7565_CONTRAST             0x81
 #define ST7565_ALLON_NORMAL         0xA4
 #define ST7565_ALLON                0xA5
-- 
cgit v1.2.3


From 5f17570ebcba8998757cdcb2df0a92a6215b7448 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Wed, 23 Oct 2013 01:34:56 +1000
Subject: Convert ED060SC4 to new driver format

---
 drivers/gdisp/ED060SC4/board_ED060SC4_example.h   | 143 ++++++
 drivers/gdisp/ED060SC4/board_ED060SC4_template.h  | 202 ++++++++
 drivers/gdisp/ED060SC4/ed060sc4.h                 |  16 -
 drivers/gdisp/ED060SC4/gdisp_lld.c                | 579 +++++++++++-----------
 drivers/gdisp/ED060SC4/gdisp_lld.mk               |   2 +-
 drivers/gdisp/ED060SC4/gdisp_lld_board_example.h  | 127 -----
 drivers/gdisp/ED060SC4/gdisp_lld_board_template.h |  83 ----
 drivers/gdisp/ED060SC4/gdisp_lld_config.h         |   7 +-
 drivers/gdisp/ED060SC4/readme.txt                 |   3 +-
 9 files changed, 648 insertions(+), 514 deletions(-)
 create mode 100644 drivers/gdisp/ED060SC4/board_ED060SC4_example.h
 create mode 100644 drivers/gdisp/ED060SC4/board_ED060SC4_template.h
 delete mode 100644 drivers/gdisp/ED060SC4/ed060sc4.h
 delete mode 100644 drivers/gdisp/ED060SC4/gdisp_lld_board_example.h
 delete mode 100644 drivers/gdisp/ED060SC4/gdisp_lld_board_template.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ED060SC4/board_ED060SC4_example.h b/drivers/gdisp/ED060SC4/board_ED060SC4_example.h
new file mode 100644
index 00000000..cb5a92b8
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/board_ED060SC4_example.h
@@ -0,0 +1,143 @@
+/*
+ * 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
+ */
+
+/* Board interface definitions for ED060SC4 PrimeView E-ink panel.
+ * 
+ * This file corresponds to the connections shown in example_schematics.png,
+ * and is designed to interface with ChibiOS/RT.
+ * 
+ * Please note that this file has never been tested in exactly this pin
+ * configuration, because the actual boards I have are slightly different.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+#include <hal.h>
+
+/*
+ * IO pins assignments.
+ */
+#define GPIOB_EINK_VDD      0
+#define GPIOB_EINK_GMODE    1
+#define GPIOB_EINK_SPV      2
+#define GPIOB_EINK_CKV      3
+#define GPIOB_EINK_CL       4
+#define GPIOB_EINK_LE       5
+#define GPIOB_EINK_OE       6
+#define GPIOB_EINK_SPH      7
+#define GPIOB_EINK_D0       8
+#define GPIOB_EINK_D1       9
+#define GPIOB_EINK_D2       10
+#define GPIOB_EINK_D3       11
+#define GPIOB_EINK_D4       12
+#define GPIOB_EINK_D5       13
+#define GPIOB_EINK_D6       14
+#define GPIOB_EINK_D7       15
+
+#define GPIOC_SMPS_CTRL     13
+#define GPIOC_VPOS_CTRL     14
+#define GPIOC_VNEG_CTRL     15
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		/* Main SMPS power control, active low
+		 * (open collector so that MOSFET gate can be pulled up to Vbat) */
+		palWritePad(GPIOC, GPIOC_SMPS_CTRL, true);
+		palSetPadMode(GPIOC, GPIOC_SMPS_CTRL, PAL_MODE_OUTPUT_OPENDRAIN);
+
+		/* Power control for the positive & negative side */
+		palWritePad(GPIOC, GPIOC_VPOS_CTRL, false);
+		palSetPadMode(GPIOC, GPIOC_VPOS_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
+		palWritePad(GPIOC, GPIOC_VNEG_CTRL, false);
+		palSetPadMode(GPIOC, GPIOC_VNEG_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
+
+		/* Main data bus */
+		palWritePort(GPIOB, 0);
+		palSetGroupMode(GPIOB, 0xFFFF, 0, PAL_MODE_OUTPUT_PUSHPULL);
+		break;
+	}
+}
+
+/* Delay for display waveforms. Should be an accurate microsecond delay. */
+static void eink_delay(int us) {
+	halPolledDelay(US2RTT(us));
+}
+
+/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */
+static inline void setpower_vdd(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_SMPS_CTRL, !on);
+	palWritePad(GPIOA, GPIOA_EINK_VDD, on);
+}
+
+/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */
+static inline void setpower_vneg(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOA, GPIOA_VNEG_CTRL, on);
+}
+
+/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */
+static inline void setpower_vpos(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOA, GPIOA_VPOS_CTRL, on);
+}
+
+/* Set the state of the LE (source driver Latch Enable) pin. */
+static inline void setpin_le(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_EINK_LE, on);
+}
+
+/* Set the state of the OE (source driver Output Enable) pin. */
+static inline void setpin_oe(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_EINK_OE, on);
+}
+
+/* Set the state of the CL (source driver Clock) pin. */
+static inline void setpin_cl(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_EINK_CL, on);
+}
+
+/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */
+static inline void setpin_sph(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_EINK_SPH, on);
+}
+
+/* Set the state of the D0-D7 (source driver Data) pins. */
+static inline void setpins_data(GDisplay *g, uint8_t value) {
+	(void) g;
+	palWriteGroup(GPIOB, 0xFF, GPIOB_EINK_D0, value);
+}
+
+/* Set the state of the CKV (gate driver Clock Vertical) pin. */
+static inline void setpin_ckv(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_EINK_CKV, on);
+}
+
+/* Set the state of the GMODE (gate driver Gate Mode) pin. */
+static inline void setpin_gmode(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOC, GPIOC_EINK_GMODE, on);
+}
+
+/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */
+static inline void setpin_spv(GDisplay *g, bool_t on) {
+	(void) g;
+	palWritePad(GPIOB, GPIOB_EINK_SPV, on);
+}
+
+#endif
diff --git a/drivers/gdisp/ED060SC4/board_ED060SC4_template.h b/drivers/gdisp/ED060SC4/board_ED060SC4_template.h
new file mode 100644
index 00000000..6d71a986
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/board_ED060SC4_template.h
@@ -0,0 +1,202 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ST7565/board_ST7565_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ST7565 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief	Optional parameters that can be put in this file.
+ * @note	The values listed below are the defaults.
+ *
+ * @note	#define GDISP_SCREEN_HEIGHT		600
+ * @note	#define GDISP_SCREEN_WIDTH		800
+ *
+ * @note	Number of pixels per byte<br>
+ * 			#define EINK_PPB				4
+ *
+ * @note	Delay for generating clock pulses.
+ *			Unit is approximate clock cycles of the CPU (0 to 15).
+ *			This should be atleast 50 ns.<br>
+ *			#define EINK_CLOCKDELAY			0
+ *
+ * @note	Width of one framebuffer block.
+ *			Must be divisible by EINK_PPB and evenly divide GDISP_SCREEN_WIDTH.<br>
+ *			#define EINK_BLOCKWIDTH			20
+ *
+ * @note
+ * @note	Height of one framebuffer block.
+ *			Must evenly divide GDISP_SCREEN_WIDTH.<br>
+ *			#define EINK_BLOCKHEIGHT		20
+ *
+ * @note	Number of block buffers to use for framebuffer emulation.<br>
+ * 			#define EINK_NUMBUFFERS			40
+ *
+ * @note	Do a "blinking" clear, i.e. clear to opposite polarity first.
+ *			This reduces the image persistence.<br>
+ *			#define EINK_BLINKCLEAR			TRUE
+ *
+ * @note	Number of passes to use when clearing the display<br>
+ *			#define EINK_CLEARCOUNT			10
+ *
+ * @note	Number of passes to use when writing to the display<br>
+ *			#define EINK_WRITECOUNT			4
+ */
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->board member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief	Delay for display waveforms. Should be an accurate microsecond delay.
+ *
+ * @param[in] us		The number of microseconds
+ */
+static void eink_delay(int us) {
+	(void) us;
+}
+
+/**
+ * @brief	Turn the E-ink panel Vdd supply (+3.3V) on or off.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpower_vdd(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Turn the E-ink panel negative supplies (-15V, -20V) on or off.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpower_vneg(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Turn the E-ink panel positive supplies (-15V, -20V) on or off.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpower_vpos(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the LE (source driver Latch Enable) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_le(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the OE (source driver Output Enable) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_oe(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the CL (source driver Clock) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_cl(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the SPH (source driver Start Pulse Horizontal) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_sph(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the D0-D7 (source driver Data) pins.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] value		The byte to write
+ */
+static inline void setpins_data(GDisplay *g, uint8_t value) {
+	(void) g;
+	(void) value;
+}
+
+/**
+ * @brief	Set the state of the CKV (gate driver Clock Vertical) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_ckv(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the GMODE (gate driver Gate Mode) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_gmode(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+/**
+ * @brief	Set the state of the SPV (gate driver Start Pulse Vertical) pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] on		On or off
+ */
+static inline void setpin_spv(GDisplay *g, bool_t on) {
+	(void) g;
+	(void) on;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/ED060SC4/ed060sc4.h b/drivers/gdisp/ED060SC4/ed060sc4.h
deleted file mode 100644
index 8a38f135..00000000
--- a/drivers/gdisp/ED060SC4/ed060sc4.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * 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 _ED060SC4_H_
-#define _ED060SC4_H_
-
-#include "gfx.h"
-
-/* Control command for flushing all data to display. */
-#define GDISP_CONTROL_FLUSH (GDISP_CONTROL_LLD + 0)
-
-#endif
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld.c b/drivers/gdisp/ED060SC4/gdisp_lld.c
index fcc03944..14e7f88a 100644
--- a/drivers/gdisp/ED060SC4/gdisp_lld.c
+++ b/drivers/gdisp/ED060SC4/gdisp_lld.c
@@ -5,30 +5,35 @@
  *              http://ugfx.org/license.html
  */
 
-/* Low-level E-ink panel driver routines for ED060SC4. */
+/**
+ * @file    drivers/gdisp/ED060SC4/gdisp_lld.c
+ * @brief   GDISP Graphics Driver for the E-ink panel ED060SC4.
+ */
 
 #include "gfx.h"
-#include "ed060sc4.h"
 
 #if GFX_USE_GDISP
 
-#include "gdisp/lld/emulation.c"
+#define GDISP_DRIVER_VMT			GDISPVMT_ED060SC4
+#include "../drivers/gdisp/ED060SC4/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ED060SC4.h"
 
-/* =================================
- *      Default configuration
- * ================================= */
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
 
 #ifndef GDISP_SCREEN_HEIGHT
-#       define GDISP_SCREEN_HEIGHT 600
+	#define GDISP_SCREEN_HEIGHT		600
 #endif
-
 #ifndef GDISP_SCREEN_WIDTH
-#       define GDISP_SCREEN_WIDTH 800
+	#define GDISP_SCREEN_WIDTH		800
 #endif
 
 /* Number of pixels per byte */
 #ifndef EINK_PPB
-#       define EINK_PPB 4
+	#define EINK_PPB 4
 #endif
 
 /* Delay for generating clock pulses.
@@ -36,50 +41,50 @@
  * This should be atleast 50 ns.
  */
 #ifndef EINK_CLOCKDELAY
-#       define EINK_CLOCKDELAY 0
+	#define EINK_CLOCKDELAY 0
 #endif
 
 /* Width of one framebuffer block.
  * Must be divisible by EINK_PPB and evenly divide GDISP_SCREEN_WIDTH. */
 #ifndef EINK_BLOCKWIDTH
-#       define EINK_BLOCKWIDTH 20
+	#define EINK_BLOCKWIDTH 20
 #endif
 
 /* Height of one framebuffer block.
  * Must evenly divide GDISP_SCREEN_WIDTH. */
 #ifndef EINK_BLOCKHEIGHT
-#       define EINK_BLOCKHEIGHT 20
+	#define EINK_BLOCKHEIGHT 20
 #endif
 
 /* Number of block buffers to use for framebuffer emulation. */
 #ifndef EINK_NUMBUFFERS
-#       define EINK_NUMBUFFERS 40
+	#define EINK_NUMBUFFERS 40
 #endif
 
 /* Do a "blinking" clear, i.e. clear to opposite polarity first.
  * This reduces the image persistence. */
 #ifndef EINK_BLINKCLEAR
-#       define EINK_BLINKCLEAR TRUE
+	#define EINK_BLINKCLEAR TRUE
 #endif
 
 /* Number of passes to use when clearing the display */
 #ifndef EINK_CLEARCOUNT
-#       define EINK_CLEARCOUNT 10
+	#define EINK_CLEARCOUNT 10
 #endif
 
 /* Number of passes to use when writing to the display */
 #ifndef EINK_WRITECOUNT
-#       define EINK_WRITECOUNT 4
+	#define EINK_WRITECOUNT 4
 #endif
 
-/* ====================================
- *      Lower level driver functions
- * ==================================== */
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
 
-#include "gdisp_lld_board.h"
+#define PRIV(g)		((drvPriv *)g->priv)
 
 /** Delay between signal changes, to give time for IO pins to change state. */
-static inline void clockdelay()
+static inline void clockdelay(void)
 {
 	#if EINK_CLOCKDELAY & 1
 	asm("nop");
@@ -107,21 +112,21 @@ static inline void clockdelay()
 }
 
 /** Fast vertical clock pulse for gate driver, used during initializations */
-static void vclock_quick()
+static void vclock_quick(GDisplay *g)
 {
-	setpin_ckv(TRUE);
+	setpin_ckv(g, TRUE);
 	eink_delay(1);
-	setpin_ckv(FALSE);
+	setpin_ckv(g, FALSE);
 	eink_delay(4);
 }
 
 /** Horizontal clock pulse for clocking data into source driver */
-static void hclock()
+static void hclock(GDisplay *g)
 {
 	clockdelay();
-	setpin_cl(TRUE);
+	setpin_cl(g, TRUE);
 	clockdelay();
-	setpin_cl(FALSE);
+	setpin_cl(g, FALSE);
 }
 
 /** Start a new vertical gate driver scan from top.
@@ -129,156 +134,156 @@ static void hclock()
  *       so you should always scan through the whole display before
  *       starting a new scan.
  */
-static void vscan_start()
+static void vscan_start(GDisplay *g)
 {
-	setpin_gmode(TRUE);
-	vclock_quick();
-	setpin_spv(FALSE);
-	vclock_quick();
-	setpin_spv(TRUE);
-	vclock_quick();
+	setpin_gmode(g, TRUE);
+	vclock_quick(g);
+	setpin_spv(g, FALSE);
+	vclock_quick(g);
+	setpin_spv(g, TRUE);
+	vclock_quick(g);
 }
 
 /** Waveform for strobing a row of data onto the display.
  * Attempts to minimize the leaking of color to other rows by having
  * a long idle period after a medium-length strobe period.
  */
-static void vscan_write()
+static void vscan_write(GDisplay *g)
 {
-	setpin_ckv(TRUE);
-	setpin_oe(TRUE);
+	setpin_ckv(g, TRUE);
+	setpin_oe(g, TRUE);
 	eink_delay(5);
-	setpin_oe(FALSE);
-	setpin_ckv(FALSE);
+	setpin_oe(g, FALSE);
+	setpin_ckv(g, FALSE);
 	eink_delay(200);
 }
 
 /** Waveform used when clearing the display. Strobes a row of data to the
  * screen, but does not mind some of it leaking to other rows.
  */
-static void vscan_bulkwrite()
+static void vscan_bulkwrite(GDisplay *g)
 {
-	setpin_ckv(TRUE);
+	setpin_ckv(g, TRUE);
 	eink_delay(20);
-	setpin_ckv(FALSE);
+	setpin_ckv(g, FALSE);
 	eink_delay(200);
 }
 
 /** Waveform for skipping a vertical row without writing anything.
  * Attempts to minimize the amount of change in any row.
  */
-static void vscan_skip()
+static void vscan_skip(GDisplay *g)
 {
-	setpin_ckv(TRUE);
+	setpin_ckv(g, TRUE);
 	eink_delay(1);
-	setpin_ckv(FALSE);
+	setpin_ckv(g, FALSE);
 	eink_delay(100);
 }
 
 /** Stop the vertical scan. The significance of this escapes me, but it seems
  * necessary or the next vertical scan may be corrupted.
  */
-static void vscan_stop()
+static void vscan_stop(GDisplay *g)
 {
-	setpin_gmode(FALSE);
-	vclock_quick();
-	vclock_quick();
-	vclock_quick();
-	vclock_quick();
-	vclock_quick();
+	setpin_gmode(g, FALSE);
+	vclock_quick(g);
+	vclock_quick(g);
+	vclock_quick(g);
+	vclock_quick(g);
+	vclock_quick(g);
 }
 
 /** Start updating the source driver data (from left to right). */
-static void hscan_start()
+static void hscan_start(GDisplay *g)
 {
 	/* Disable latching and output enable while we are modifying the row. */
-	setpin_le(FALSE);
-	setpin_oe(FALSE);
+	setpin_le(g, FALSE);
+	setpin_oe(g, FALSE);
 	
 	/* The start pulse should remain low for the duration of the row. */
-	setpin_sph(FALSE);
+	setpin_sph(g, FALSE);
 }
 
 /** Write data to the horizontal row. */
-static void hscan_write(const uint8_t *data, int count)
+static void hscan_write(GDisplay *g, const uint8_t *data, int count)
 {
 	while (count--)
 	{
 		/* Set the next byte on the data pins */
-		setpins_data(*data++);
+		setpins_data(g, *data++);
 		
 		/* Give a clock pulse to the shift register */
-		hclock();
+		hclock(g);
 	}
 }
 
 /** Finish and transfer the row to the source drivers.
  * Does not set the output enable, so the drivers are not yet active. */
-static void hscan_stop()
+static void hscan_stop(GDisplay *g)
 {
 	/* End the scan */
-	setpin_sph(TRUE);
-	hclock();
+	setpin_sph(g, TRUE);
+	hclock(g);
 	
 	/* Latch the new data */
-	setpin_le(TRUE);
+	setpin_le(g, TRUE);
 	clockdelay();
-	setpin_le(FALSE);
+	setpin_le(g, FALSE);
 }
 
 /** Turn on the power to the E-Ink panel, observing proper power sequencing. */
-static void power_on()
+static void power_on(GDisplay *g)
 {
 	unsigned i;
 	
 	/* First the digital power supply and signal levels. */
-	setpower_vdd(TRUE);
-	setpin_le(FALSE);
-	setpin_oe(FALSE);
-	setpin_cl(FALSE);
-	setpin_sph(TRUE);
-	setpins_data(0);
-	setpin_ckv(FALSE);
-	setpin_gmode(FALSE);
-	setpin_spv(TRUE);
+	setpower_vdd(g, TRUE);
+	setpin_le(g, FALSE);
+	setpin_oe(g, FALSE);
+	setpin_cl(g, FALSE);
+	setpin_sph(g, TRUE);
+	setpins_data(g, 0);
+	setpin_ckv(g, FALSE);
+	setpin_gmode(g, FALSE);
+	setpin_spv(g, TRUE);
 	
 	/* Min. 100 microsecond delay after digital supply */
 	gfxSleepMicroseconds(100);
 	
 	/* Then negative voltages and min. 1000 microsecond delay. */
-	setpower_vneg(TRUE);
+	setpower_vneg(g, TRUE);
 	gfxSleepMicroseconds(1000);
 	
 	/* Finally the positive voltages. */
-	setpower_vpos(TRUE);
+	setpower_vpos(g, TRUE);
 	
 	/* Clear the vscan shift register */
-	vscan_start();
+	vscan_start(g);
 	for (i = 0; i < GDISP_SCREEN_HEIGHT; i++)
-		vclock_quick();
-	vscan_stop();
+		vclock_quick(g);
+	vscan_stop(g);
 }
 
 /** Turn off the power, observing proper power sequencing. */
-static void power_off()
+static void power_off(GDisplay *g)
 {
 	/* First the high voltages */
-	setpower_vpos(FALSE);
-	setpower_vneg(FALSE);
+	setpower_vpos(g, FALSE);
+	setpower_vneg(g, FALSE);
 	
 	/* Wait for any capacitors to drain */
 	gfxSleepMilliseconds(100);
 	
 	/* Then put all signals and digital supply to ground. */
-	setpin_le(FALSE);
-	setpin_oe(FALSE);
-	setpin_cl(FALSE);
-	setpin_sph(FALSE);
-	setpins_data(0);
-	setpin_ckv(FALSE);
-	setpin_gmode(FALSE);
-	setpin_spv(FALSE);
-	setpower_vdd(FALSE);
+	setpin_le(g, FALSE);
+	setpin_oe(g, FALSE);
+	setpin_cl(g, FALSE);
+	setpin_sph(g, FALSE);
+	setpins_data(g, 0);
+	setpin_ckv(g, FALSE);
+	setpin_gmode(g, FALSE);
+	setpin_spv(g, FALSE);
+	setpower_vdd(g, FALSE);
 }
 
 /* ====================================
@@ -286,56 +291,58 @@ static void power_off()
  * ==================================== */
 
 #if EINK_PPB == 4
-#define PIXELMASK 3
-#define PIXEL_WHITE 2
-#define PIXEL_BLACK 1
-#define BYTE_WHITE 0xAA
-#define BYTE_BLACK 0x55
+	#define PIXELMASK 3
+	#define PIXEL_WHITE 2
+	#define PIXEL_BLACK 1
+	#define BYTE_WHITE 0xAA
+	#define BYTE_BLACK 0x55
 #else
-#error Unsupported EINK_PPB value.
+	#error Unsupported EINK_PPB value.
 #endif
 
 #if GDISP_SCREEN_HEIGHT % EINK_BLOCKHEIGHT != 0
-#error GDISP_SCREEN_HEIGHT must be evenly divisible by EINK_BLOCKHEIGHT
+	#error GDISP_SCREEN_HEIGHT must be evenly divisible by EINK_BLOCKHEIGHT
 #endif
 
 #if GDISP_SCREEN_WIDTH % EINK_BLOCKWIDTH != 0
-#error GDISP_SCREEN_WIDTH must be evenly divisible by EINK_BLOCKWIDTH
+	#error GDISP_SCREEN_WIDTH must be evenly divisible by EINK_BLOCKWIDTH
 #endif
 
 #if EINK_BLOCKWIDTH % EINK_PPB != 0
-#error EINK_BLOCKWIDTH must be evenly divisible by EINK_PPB
+	#error EINK_BLOCKWIDTH must be evenly divisible by EINK_PPB
 #endif
 
 #if EINK_NUMBUFFERS > 254
-#error EINK_NUMBUFFERS must be at most 254.
+	#error EINK_NUMBUFFERS must be at most 254.
 #endif
 
-#define BLOCKS_Y (GDISP_SCREEN_HEIGHT / EINK_BLOCKHEIGHT)
-#define BLOCKS_X (GDISP_SCREEN_WIDTH / EINK_BLOCKWIDTH)
-#define WIDTH_BYTES (EINK_BLOCKWIDTH / EINK_PPB)
+#define BLOCKS_Y		(GDISP_SCREEN_HEIGHT / EINK_BLOCKHEIGHT)
+#define BLOCKS_X		(GDISP_SCREEN_WIDTH / EINK_BLOCKWIDTH)
+#define WIDTH_BYTES		(EINK_BLOCKWIDTH / EINK_PPB)
 
 /* Buffers that store the data for a small area of the display. */
 typedef struct {
 	uint8_t data[EINK_BLOCKHEIGHT][WIDTH_BYTES];
 } block_t;
 
-static uint8_t g_next_block; /* Index of the next free block buffer. */
-static block_t g_blocks[EINK_NUMBUFFERS];
+typedef struct drvPriv {
+	uint8_t g_next_block; /* Index of the next free block buffer. */
+	block_t g_blocks[EINK_NUMBUFFERS];
 
-/* Map that stores the buffers associated to each area of the display.
- * Value of 0 means that the block is not allocated.
- * Other values are the index in g_blocks + 1.
- */
-static uint8_t g_blockmap[BLOCKS_Y][BLOCKS_X]; 
+	/* Map that stores the buffers associated to each area of the display.
+	 * Value of 0 means that the block is not allocated.
+	 * Other values are the index in g_blocks + 1.
+	 */
+	uint8_t g_blockmap[BLOCKS_Y][BLOCKS_X];
+} drvPriv;
 
 /** Check if the row contains any allocated blocks. */
-static bool_t blocks_on_row(unsigned by)
+static bool_t blocks_on_row(GDisplay *g, unsigned by)
 {
 	unsigned bx;
 	for (bx = 0; bx < BLOCKS_X; bx++)
 	{
-		if (g_blockmap[by][bx] != 0)
+		if (PRIV(g)->g_blockmap[by][bx] != 0)
 		{
 			return TRUE;
 		}
@@ -344,79 +351,47 @@ static bool_t blocks_on_row(unsigned by)
 }
 
 /** Write out a block row. */
-static void write_block_row(unsigned by)
+static void write_block_row(GDisplay *g, unsigned by)
 {
 	unsigned bx, dy, dx;
 	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
 	{
-		hscan_start();
+		hscan_start(g);
 		for (bx = 0; bx < BLOCKS_X; bx++)
 		{
-			if (g_blockmap[by][bx] == 0)
+			if (PRIV(g)->g_blockmap[by][bx] == 0)
 			{
 				for (dx = 0; dx < WIDTH_BYTES; dx++)
 				{
 					const uint8_t dummy = 0;
-					hscan_write(&dummy, 1);
+					hscan_write(g, &dummy, 1);
 				}
 			}
 			else
 			{
-				block_t *block = &g_blocks[g_blockmap[by][bx] - 1];
-				hscan_write(&block->data[dy][0], WIDTH_BYTES);
+				block_t *block = &PRIV(g)->g_blocks[PRIV(g)->g_blockmap[by][bx] - 1];
+				hscan_write(g, &block->data[dy][0], WIDTH_BYTES);
 			}
 		}
-		hscan_stop();
+		hscan_stop(g);
 		
-		vscan_write();
+		vscan_write(g);
 	}
 }
 
 /** Clear the block map, i.e. deallocate all blocks */
-static void clear_block_map()
+static void clear_block_map(GDisplay *g)
 {
 	unsigned bx, by;
 	for (by = 0; by < BLOCKS_Y; by++)
 	{
 		for (bx = 0; bx < BLOCKS_X; bx++)
 		{
-			g_blockmap[by][bx] = 0;
-		}
-	}
-	
-	g_next_block = 0;
-}
-
-/** Flush all the buffered rows to display. */
-static void flush_buffers()
-{
-	unsigned by, dy, i;
-	
-	for (i = 0; i < EINK_WRITECOUNT; i++)
-	{
-		vscan_start();
-		
-		for (by = 0; by < BLOCKS_Y; by++)
-		{
-			if (!blocks_on_row(by))
-			{
-				/* Skip the whole row of blocks. */
-				for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
-				{
-					vscan_skip();
-				}
-			}
-			else
-			{
-				/* Write out the blocks. */
-				write_block_row(by);
-			}
+			PRIV(g)->g_blockmap[by][bx] = 0;
 		}
-		
-		vscan_stop();
 	}
 	
-	clear_block_map();
+	PRIV(g)->g_next_block = 0;
 }
 
 /** Initialize a newly allocated block. */
@@ -434,173 +409,217 @@ static void zero_block(block_t *block)
 
 /** Allocate a buffer
  * Automatically flushes if all buffers are full. */
-static block_t *alloc_buffer(unsigned bx, unsigned by)
+static block_t *alloc_buffer(GDisplay *g, unsigned bx, unsigned by)
 {
 	block_t *result;
-	if (g_blockmap[by][bx] == 0)
+	drvPriv *priv;
+
+	priv = PRIV(g);
+	if (priv->g_blockmap[by][bx] == 0)
 	{
-		if (g_next_block >= EINK_NUMBUFFERS)
-		{
-			flush_buffers();
-		}
+		if (priv->g_next_block >= EINK_NUMBUFFERS)
+			gdisp_lld_flush(g);
 		
-		result = &g_blocks[g_next_block];
-		g_blockmap[by][bx] = g_next_block + 1;
-		g_next_block++;
+		result = &priv->g_blocks[priv->g_next_block];
+		priv->g_blockmap[by][bx] = priv->g_next_block + 1;
+		priv->g_next_block++;
 		zero_block(result);
 		return result;
 	}
 	else
 	{
-		result = &g_blocks[g_blockmap[by][bx] - 1];
+		result = &priv->g_blocks[priv->g_blockmap[by][bx] - 1];
 		return result;
 	}
 }
 
-/* ===============================
- *         Public functions
- * =============================== */
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
 
-bool_t gdisp_lld_init(void)
-{
-	init_board();
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	g->priv = gfxAlloc(sizeof(drvPriv));
+
+	init_board(g);
 	
 	/* Make sure that all the pins are in "off" state.
 	 * Having any pin high could cause voltage leaking to the
 	 * display, which in turn causes the image to leak slowly away.
 	 */
-	power_off();
-	
-	clear_block_map();
+	power_off(g);
 	
-	/* Initialize the global GDISP structure */
-	GDISP.Width = GDISP_SCREEN_WIDTH;
-	GDISP.Height = GDISP_SCREEN_HEIGHT;
-	GDISP.Orientation = GDISP_ROTATE_0;
-	GDISP.Powermode = powerOff;
-	GDISP.Backlight = 0;
-	GDISP.Contrast = 0;
-	#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
-	GDISP.clipx0 = 0;
-	GDISP.clipy0 = 0;
-	GDISP.clipx1 = GDISP.Width;
-	GDISP.clipy1 = GDISP.Height;
-	#endif
+	clear_block_map(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 = 100;
+	g->g.Contrast = 100;
 	return TRUE;
 }
 
-void gdisp_lld_draw_pixel(coord_t x, coord_t y, color_t color)
-{
-	block_t *block;
-	uint8_t byte;
-	unsigned bx, by, dx, dy;
-	uint8_t bitpos;
-	
-	bx = x / EINK_BLOCKWIDTH;
-	by = y / EINK_BLOCKHEIGHT;
-	dx = x % EINK_BLOCKWIDTH;
-	dy = y % EINK_BLOCKHEIGHT;
-	
-	if (bx < 0 || bx >= BLOCKS_X || by < 0 || by >= BLOCKS_Y)
-		return;
-	
-	block = alloc_buffer(bx, by);
-	
-	bitpos = (6 - 2 * (dx % EINK_PPB));
-	byte = block->data[dy][dx / EINK_PPB];
-	byte &= ~(PIXELMASK << bitpos);
-	if (color)
-	{
-		byte |= PIXEL_WHITE << bitpos;
-	}
-	else
-	{
-		byte |= PIXEL_BLACK << bitpos;   
-	}
-	block->data[dy][dx / EINK_PPB] = byte;
-}
+#if GDISP_HARDWARE_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		unsigned by, dy, i;
+
+		for (i = 0; i < EINK_WRITECOUNT; i++) {
+			vscan_start(g);
+
+			for (by = 0; by < BLOCKS_Y; by++) {
+				if (!blocks_on_row(g, by)) {
+					/* Skip the whole row of blocks. */
+					for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+						vscan_skip(g);
+				} else {
+					/* Write out the blocks. */
+					write_block_row(g, by);
+				}
+			}
+
+			vscan_stop(g);
+		}
 
-#if !GDISP_NEED_CONTROL
-#error You must enable GDISP_NEED_CONTROL for the E-Ink driver.
+		clear_block_map(g);
+	}
 #endif
 
-void gdisp_lld_control(unsigned what, void *value) {
-	gdisp_powermode_t newmode;
+#if GDISP_HARDWARE_DRAWPIXEL
+	void gdisp_lld_draw_pixel(GDisplay *g) {
+		block_t *block;
+		uint8_t byte;
+		unsigned bx, by, dx, dy;
+		uint8_t bitpos;
+
+		switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			bx = g->p.x / EINK_BLOCKWIDTH;
+			dx = g->p.x % EINK_BLOCKWIDTH;
+			by = g->p.y / EINK_BLOCKHEIGHT;
+			dy = g->p.y % EINK_BLOCKHEIGHT;
+			break;
+		case GDISP_ROTATE_90:
+			bx = g->p.y / EINK_BLOCKWIDTH;
+			dx = g->p.y % EINK_BLOCKWIDTH;
+			by = (GDISP_SCREEN_HEIGHT-1 - g->p.x) / EINK_BLOCKHEIGHT;
+			dy = (GDISP_SCREEN_HEIGHT-1 - g->p.x) % EINK_BLOCKHEIGHT;
+			break;
+		case GDISP_ROTATE_180:
+			bx = (GDISP_SCREEN_WIDTH-1 - g->p.x) / EINK_BLOCKWIDTH;
+			dx = (GDISP_SCREEN_WIDTH-1 - g->p.x) % EINK_BLOCKWIDTH;
+			by = (GDISP_SCREEN_HEIGHT-1 - g->p.y) / EINK_BLOCKHEIGHT;
+			dy = (GDISP_SCREEN_HEIGHT-1 - g->p.y) % EINK_BLOCKHEIGHT;
+			break;
+		case GDISP_ROTATE_270:
+			bx = (GDISP_SCREEN_WIDTH-1 - g->p.y) / EINK_BLOCKWIDTH;
+			dx = (GDISP_SCREEN_WIDTH-1 - g->p.y) % EINK_BLOCKWIDTH;
+			by = g->p.x / EINK_BLOCKHEIGHT;
+			dy = g->p.x % EINK_BLOCKHEIGHT;
+			break;
+		}
+
+		block = alloc_buffer(g, bx, by);
+
+		bitpos = (6 - 2 * (dx % EINK_PPB));
+		byte = block->data[dy][dx / EINK_PPB];
+		byte &= ~(PIXELMASK << bitpos);
+		if (g->p.color != Black)
+			byte |= PIXEL_WHITE << bitpos;
+		else
+			byte |= PIXEL_BLACK << bitpos;
+		block->data[dy][dx / EINK_PPB] = byte;
+	}
+#endif
 	
-	switch(what)
-	{
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
 		case GDISP_CONTROL_POWER:
-			newmode = (gdisp_powermode_t)value;
-			
-			if (GDISP.Powermode == newmode)
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
+				return;
+			switch((powermode_t)g->p.ptr) {
+			case powerOff:
+			case powerSleep:
+			case powerDeepSleep:
+				gdisp_lld_flush(g);
+				power_off(g);
+				break;
+			case powerOn:
+				power_on(g);
+				break;
+			default:
 				return;
-			
-			if (newmode == powerOn)
-			{
-				power_on();
 			}
-			else
-			{
-				flush_buffers();
-				power_off();
+			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:
+			case GDISP_ROTATE_180:
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+			case GDISP_ROTATE_270:
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			default:
+				return;
 			}
-			GDISP.Powermode = newmode;
-			break;
+			g->g.Orientation = (orientation_t)g->p.ptr;
+			return;
 			
-		case GDISP_CONTROL_FLUSH:
-			flush_buffers();
-			break;
+		default:
+			return;
+		}
 	}
-}
+#endif
 
 /* ===============================
  *       Accelerated routines
  * =============================== */
 
 #if GDISP_HARDWARE_CLEARS
+	static void subclear(GDisplay *g, color_t color) {
+		unsigned x, y;
+		uint8_t byte;
 
-static void subclear(color_t color)
-{
-	unsigned x, y;
-	uint8_t byte;
-	
-	hscan_start();
-	byte = color ? BYTE_WHITE : BYTE_BLACK;
-	for (x = 0; x < GDISP_SCREEN_WIDTH; x++)
-	{
-		hscan_write(&byte, 1);
+		hscan_start(g);
+		byte = color ? BYTE_WHITE : BYTE_BLACK;
+		for (x = 0; x < GDISP_SCREEN_WIDTH; x++)
+		{
+			hscan_write(g, &byte, 1);
+		}
+		hscan_stop(g);
+
+		setpin_oe(g, TRUE);
+		vscan_start(g);
+		for (y = 0; y < GDISP_SCREEN_HEIGHT; y++)
+			vscan_bulkwrite(g);
+		vscan_stop(g);
+		setpin_oe(g, FALSE);
 	}
-	hscan_stop();
 	
-	setpin_oe(TRUE);
-	vscan_start();
-	for (y = 0; y < GDISP_SCREEN_HEIGHT; y++)
-	{
-		vscan_bulkwrite();
-	}
-	vscan_stop();
-	setpin_oe(FALSE);
-}
+	void gdisp_lld_clear(GDisplay *g) {
+		unsigned i;
 
-void gdisp_lld_clear(color_t color)
-{
-	unsigned i;
-	clear_block_map();
-	
-	if (EINK_BLINKCLEAR)
-	{
-		subclear(!color);
-		gfxSleepMilliseconds(50);
-	}
-	
-	for (i = 0; i < EINK_CLEARCOUNT; i++)
-	{
-		subclear(color);
-		gfxSleepMilliseconds(10);
+		clear_block_map(g);
+
+		if (EINK_BLINKCLEAR) {
+			subclear(g, !g->p.color);
+			gfxSleepMilliseconds(50);
+		}
+
+		for (i = 0; i < EINK_CLEARCOUNT; i++) {
+			subclear(g, g->p.color);
+			gfxSleepMilliseconds(10);
+		}
 	}
-	
-}
 #endif
 
-#endif
+#endif	// GFX_USE_GDISP
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld.mk b/drivers/gdisp/ED060SC4/gdisp_lld.mk
index d5c1492f..fc62da03 100644
--- a/drivers/gdisp/ED060SC4/gdisp_lld.mk
+++ b/drivers/gdisp/ED060SC4/gdisp_lld.mk
@@ -1,2 +1,2 @@
-GFXSRC += $(GFXLIB)/drivers/gdisp/ED060SC4/gdisp_lld.c
 GFXINC += $(GFXLIB)/drivers/gdisp/ED060SC4
+GFXSRC += $(GFXLIB)/drivers/gdisp/ED060SC4/gdisp_lld.c
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h b/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h
deleted file mode 100644
index 98f05ee8..00000000
--- a/drivers/gdisp/ED060SC4/gdisp_lld_board_example.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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
- */
-
-/* Board interface definitions for ED060SC4 PrimeView E-ink panel.
- * 
- * This file corresponds to the connections shown in example_schematics.png,
- * and is designed to interface with ChibiOS/RT.
- * 
- * Please note that this file has never been tested in exactly this pin
- * configuration, because the actual boards I have are slightly different.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#include <hal.h>
-
-/*
- * IO pins assignments.
- */
-#define GPIOB_EINK_VDD      0
-#define GPIOB_EINK_GMODE    1
-#define GPIOB_EINK_SPV      2
-#define GPIOB_EINK_CKV      3
-#define GPIOB_EINK_CL       4
-#define GPIOB_EINK_LE       5
-#define GPIOB_EINK_OE       6
-#define GPIOB_EINK_SPH      7
-#define GPIOB_EINK_D0       8
-#define GPIOB_EINK_D1       9
-#define GPIOB_EINK_D2       10
-#define GPIOB_EINK_D3       11
-#define GPIOB_EINK_D4       12
-#define GPIOB_EINK_D5       13
-#define GPIOB_EINK_D6       14
-#define GPIOB_EINK_D7       15
-
-#define GPIOC_SMPS_CTRL     13
-#define GPIOC_VPOS_CTRL     14
-#define GPIOC_VNEG_CTRL     15
-
-
-/* Set up IO pins for the panel connection. */
-static inline void init_board(void) {
-	/* Main SMPS power control, active low
-	 * (open collector so that MOSFET gate can be pulled up to Vbat) */
-	palWritePad(GPIOC, GPIOC_SMPS_CTRL, true);
-	palSetPadMode(GPIOC, GPIOC_SMPS_CTRL, PAL_MODE_OUTPUT_OPENDRAIN);
-	
-	/* Power control for the positive & negative side */
-	palWritePad(GPIOC, GPIOC_VPOS_CTRL, false);
-	palSetPadMode(GPIOC, GPIOC_VPOS_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
-	palWritePad(GPIOC, GPIOC_VNEG_CTRL, false);
-	palSetPadMode(GPIOC, GPIOC_VNEG_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
-	
-	/* Main data bus */
-	palWritePort(GPIOB, 0);
-	palSetGroupMode(GPIOB, 0xFFFF, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-/* Delay for display waveforms. Should be an accurate microsecond delay. */
-static void eink_delay(int us)
-{
-	halPolledDelay(US2RTT(us));
-}
-
-/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */
-static inline void setpower_vdd(bool_t on) {
-	palWritePad(GPIOB, GPIOB_SMPS_CTRL, !on);
-	palWritePad(GPIOA, GPIOA_EINK_VDD, on);
-}
-
-/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */
-static inline void setpower_vneg(bool_t on) {
-	palWritePad(GPIOA, GPIOA_VNEG_CTRL, on);
-}
-
-/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */
-static inline void setpower_vpos(bool_t on) {
-	palWritePad(GPIOA, GPIOA_VPOS_CTRL, on);
-}
-
-/* Set the state of the LE (source driver Latch Enable) pin. */
-static inline void setpin_le(bool_t on) {
-	palWritePad(GPIOB, GPIOB_EINK_LE, on);
-}
-
-/* Set the state of the OE (source driver Output Enable) pin. */
-static inline void setpin_oe(bool_t on) {
-	palWritePad(GPIOB, GPIOB_EINK_OE, on);
-}
-
-/* Set the state of the CL (source driver Clock) pin. */
-static inline void setpin_cl(bool_t on) {
-	palWritePad(GPIOB, GPIOB_EINK_CL, on);
-}
-
-/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */
-static inline void setpin_sph(bool_t on) {
-	palWritePad(GPIOB, GPIOB_EINK_SPH, on);
-}
-
-/* Set the state of the D0-D7 (source driver Data) pins. */
-static inline void setpins_data(uint8_t value) {
-	palWriteGroup(GPIOB, 0xFF, GPIOB_EINK_D0, value);
-}
-
-/* Set the state of the CKV (gate driver Clock Vertical) pin. */
-static inline void setpin_ckv(bool_t on) {
-	palWritePad(GPIOB, GPIOB_EINK_CKV, on);
-}
-
-/* Set the state of the GMODE (gate driver Gate Mode) pin. */
-static inline void setpin_gmode(bool_t on) {
-	palWritePad(GPIOC, GPIOC_EINK_GMODE, on);
-}
-
-/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */
-static inline void setpin_spv(bool_t on) {
-	palWritePad(GPIOB, GPIOB_EINK_SPV, on);
-}
-
-#endif
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h b/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h
deleted file mode 100644
index 68129bf8..00000000
--- a/drivers/gdisp/ED060SC4/gdisp_lld_board_template.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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
- */
-
-/* Board interface definitions for ED060SC4 PrimeView E-ink panel.
- * 
- * You should implement the following functions to define the interface to
- * the panel on your board.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/* Set up IO pins for the panel connection. */
-static inline void init_board(void) {
-	#error Unimplemented
-}
-
-/* Delay for display waveforms. Should be an accurate microsecond delay. */
-static void eink_delay(int us)
-{
-	#error Unimplemented
-}
-
-/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */
-static inline void setpower_vdd(bool_t on) {
-	#error Unimplemented
-}
-
-/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */
-static inline void setpower_vneg(bool_t on) {
-	#error Unimplemented
-}
-
-/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */
-static inline void setpower_vpos(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the LE (source driver Latch Enable) pin. */
-static inline void setpin_le(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the OE (source driver Output Enable) pin. */
-static inline void setpin_oe(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the CL (source driver Clock) pin. */
-static inline void setpin_cl(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */
-static inline void setpin_sph(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the D0-D7 (source driver Data) pins. */
-static inline void setpins_data(uint8_t value) {
-	#error Unimplemented
-}
-
-/* Set the state of the CKV (gate driver Clock Vertical) pin. */
-static inline void setpin_ckv(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the GMODE (gate driver Gate Mode) pin. */
-static inline void setpin_gmode(bool_t on) {
-	#error Unimplemented
-}
-
-/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */
-static inline void setpin_spv(bool_t on) {
-	#error Unimplemented
-}
-
-#endif
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_config.h b/drivers/gdisp/ED060SC4/gdisp_lld_config.h
index befd997c..d7e836c9 100644
--- a/drivers/gdisp/ED060SC4/gdisp_lld_config.h
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_config.h
@@ -12,12 +12,9 @@
 
 #if GFX_USE_GDISP
 
-#define GDISP_DRIVER_NAME               "ED060SC4"
+#define GDISP_HARDWARE_FLUSH			TRUE		// This controller requires flushing
+#define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_CLEARS           TRUE
-#define GDISP_HARDWARE_FILLS            FALSE
-#define GDISP_HARDWARE_BITFILLS         FALSE
-#define GDISP_HARDWARE_SCROLL           FALSE
-#define GDISP_HARDWARE_PIXELREAD        FALSE
 #define GDISP_HARDWARE_CONTROL          TRUE
 
 #define GDISP_PIXELFORMAT               GDISP_PIXELFORMAT_MONO
diff --git a/drivers/gdisp/ED060SC4/readme.txt b/drivers/gdisp/ED060SC4/readme.txt
index 5409d810..852a0010 100644
--- a/drivers/gdisp/ED060SC4/readme.txt
+++ b/drivers/gdisp/ED060SC4/readme.txt
@@ -38,8 +38,7 @@ result in faster drawing, but also use more RAM on the processor:
 After drawing your images, you should flush the buffers using the following
 command:
 
-    #include <ed060sc4.h>
-    gdispControl(GDISP_CONTROL_FLUSH, 0);
+    gdispFlush();
 
 The buffers are also flushed whenever you turn the display off using:
 
-- 
cgit v1.2.3


From 8c1a37b59eef97c1e713a4ae24459f3af82b65f2 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 24 Oct 2013 11:30:17 +1000
Subject: Add functions to the Win32 GDISP driver to enable full testing of the
 streaming driver interface.

---
 drivers/multiple/Win32/gdisp_lld.c        | 260 ++++++++++++++++++++++++++----
 drivers/multiple/Win32/gdisp_lld_config.h |  22 ++-
 2 files changed, 250 insertions(+), 32 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 3ce50633..876168c3 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -17,38 +17,15 @@
 #include "../drivers/multiple/Win32/gdisp_lld_config.h"
 #include "gdisp/lld/gdisp_lld.h"
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <windows.h>
-#include <wingdi.h>
-#include <assert.h>
-
 #ifndef GDISP_SCREEN_WIDTH
 	#define GDISP_SCREEN_WIDTH	640
 #endif
 #ifndef GDISP_SCREEN_HEIGHT
 	#define GDISP_SCREEN_HEIGHT	480
 #endif
-
-#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
-#define GDISP_FLG_HASTOGGLE			(GDISP_FLG_DRIVER<<1)
-#define GDISP_FLG_HASMOUSE			(GDISP_FLG_DRIVER<<2)
-
-#if GINPUT_NEED_TOGGLE
-	/* Include toggle support code */
-	#include "ginput/lld/toggle.h"
-#endif
-
 #if GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888
 	#error "GDISP Win32: This driver currently only supports the RGB888 pixel format."
 #endif
-
-#if GINPUT_NEED_MOUSE
-	/* Include mouse support code */
-	#include "ginput/lld/mouse.h"
-#endif
-
 // Setting this to TRUE delays updating the screen
 // to the windows paint routine. Due to the
 // drawing lock this does not add as much speed
@@ -57,18 +34,46 @@
 // even draw_pixel().
 // This is probably due to drawing operations being
 // combined as the update regions are merged.
+// The only time you might want to turn this off is
+// if you are debugging drawing and want to see each
+// pixel as it is set.
 #define GDISP_WIN32_USE_INDIRECT_UPDATE		TRUE
+//#define GDISP_WIN32_USE_INDIRECT_UPDATE		FALSE
 
-// How far extra windows should be offset from the first.
+// How far extra windows (multiple displays) should be offset from the first.
 #define DISPLAY_X_OFFSET		50
 #define DISPLAY_Y_OFFSET		50
 
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <wingdi.h>
+#include <assert.h>
+
+#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_HASTOGGLE			(GDISP_FLG_DRIVER<<1)
+#define GDISP_FLG_HASMOUSE			(GDISP_FLG_DRIVER<<2)
+#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+	#define GDISP_FLG_WSTREAM			(GDISP_FLG_DRIVER<<3)
+	#define GDISP_FLG_WRAPPED			(GDISP_FLG_DRIVER<<4)
+#endif
+
+#if GINPUT_NEED_TOGGLE
+	/* Include toggle support code */
+	#include "ginput/lld/toggle.h"
+#endif
+
+#if GINPUT_NEED_MOUSE
+	/* Include mouse support code */
+	#include "ginput/lld/mouse.h"
+#endif
+
 static DWORD			winThreadId;
 static ATOM				winClass;
 static volatile bool_t	QReady;
 static HANDLE			drawMutex;
 
-
 /*===========================================================================*/
 /* Driver local routines    .                                                */
 /*===========================================================================*/
@@ -96,6 +101,10 @@ typedef struct winPriv {
 	#if GINPUT_NEED_TOGGLE
 		uint8_t		toggles;
 	#endif
+	#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+		coord_t		x0, y0, x1, y1;
+		coord_t		x, y;
+	#endif
 } winPriv;
 
 
@@ -441,6 +450,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	assert(priv != NULL);
 	memset(priv, 0, sizeof(winPriv));
 	g->priv = priv;
+	#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+		// Initialise with an invalid window
+		g->flags &= ~GDISP_FLG_WSTREAM;
+	#endif
 	g->board = 0;			// no board interface for this controller
 
 	// Create the window in the message thread
@@ -467,6 +480,199 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	}
 #endif
 
+#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+	void BAD_PARAMETER(const char *msg) {
+		volatile int a;
+		// This is really just a point for us to set the debugger
+		a = 0;
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		winPriv	*	priv;
+
+		if (g->flags & GDISP_FLG_WSTREAM)
+			BAD_PARAMETER("write_start: already in streaming mode");
+		if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
+			BAD_PARAMETER("write_start: bad window parameter");
+
+		priv = g->priv;
+		priv->x0 = g->p.x;	priv->x1 = g->p.x + g->p.cx - 1;
+		priv->y0 = g->p.y;	priv->y1 = g->p.y + g->p.cy - 1;
+		#if GDISP_HARDWARE_STREAM_POS
+			priv->x = g->p.x-1;			// Make sure these values are invalid (for testing)
+			priv->y = g->p.y-1;
+		#else
+			priv->x = g->p.x;
+			priv->y = g->p.y;
+		#endif
+		g->flags |= GDISP_FLG_WSTREAM;
+		g->flags &= ~GDISP_FLG_WRAPPED;
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		winPriv	*	priv;
+		int			x, y;
+		COLORREF	color;
+
+		priv = g->priv;
+		color = COLOR2BGR(g->p.color);
+
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("write_color: not in streaming mode");
+		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
+			BAD_PARAMETER("write_color: cursor outside streaming area");
+		if (g->flags & GDISP_FLG_WRAPPED) {
+			BAD_PARAMETER("write_color: Warning - Area wrapped.");
+			g->flags &= ~GDISP_FLG_WRAPPED;
+		}
+
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				x = priv->x;
+				y = priv->y;
+				break;
+			case GDISP_ROTATE_90:
+				x = priv->y;
+				y = g->g.Width - 1 - priv->x;
+				break;
+			case GDISP_ROTATE_180:
+				x = g->g.Width - 1 - priv->x;
+				y = g->g.Height - 1 - priv->y;
+				break;
+			case GDISP_ROTATE_270:
+				x = g->g.Height - 1 - priv->y;
+				y = priv->x;
+				break;
+			}
+		#else
+			x = priv->x;
+			y = priv->y;
+		#endif
+
+		// Draw the pixel on the screen and in the buffer.
+		WaitForSingleObject(drawMutex, INFINITE);
+		SetPixel(priv->dcBuffer, x, y, color);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			{
+				RECT	r;
+				r.left = x; r.right = x+1;
+				r.top = y; r.bottom = y+1;
+				InvalidateRect(priv->hwnd, &r, FALSE);
+			}
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				SetPixel(dc, x, y, color);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
+
+		// Update the cursor
+		if (++priv->x > priv->x1) {
+			priv->x = priv->x0;
+			if (++priv->y > priv->y1) {
+				g->flags |= GDISP_FLG_WRAPPED;
+				priv->y = priv->y0;
+			}
+		}
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("write_stop: not in streaming mode");
+		g->flags &= ~GDISP_FLG_WSTREAM;
+	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			winPriv	*	priv;
+
+			priv = g->priv;
+
+			if (!(g->flags & GDISP_FLG_WSTREAM))
+				BAD_PARAMETER("write_pos: not in streaming mode");
+			if (g->p.x < priv->x0 || g->p.x > priv->x1 || g->p.y < priv->y0 || g->p.y > priv->y1)
+				BAD_PARAMETER("write_color: new cursor outside streaming area");
+			priv->x = g->p.x;
+			priv->y = g->p.y;
+		}
+	#endif
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		winPriv	*	priv;
+
+		if (g->flags & GDISP_FLG_WSTREAM)
+			BAD_PARAMETER("read_start: already in streaming mode");
+		if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
+			BAD_PARAMETER("read_start: bad window parameter");
+
+		priv = g->priv;
+		priv->x0 = g->p.x;	priv->x1 = g->p.x + g->p.cx - 1;
+		priv->y0 = g->p.y;	priv->y1 = g->p.y + g->p.cy - 1;
+		priv->x = g->p.x;
+		priv->y = g->p.y;
+		g->flags |= GDISP_FLG_WSTREAM;
+		g->flags &= ~GDISP_FLG_WRAPPED;
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		winPriv	*	priv;
+		COLORREF	color;
+
+		priv = g->priv;
+
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("read_color: not in streaming mode");
+		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
+			BAD_PARAMETER("read_color: cursor outside streaming area");
+		if (g->flags & GDISP_FLG_WRAPPED) {
+			BAD_PARAMETER("read_color: Warning - Area wrapped.");
+			g->flags &= ~GDISP_FLG_WRAPPED;
+		}
+
+		WaitForSingleObject(drawMutex, INFINITE);
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+				break;
+			case GDISP_ROTATE_90:
+				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
+				break;
+			case GDISP_ROTATE_180:
+				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
+				break;
+			case GDISP_ROTATE_270:
+				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
+				break;
+			}
+		#else
+			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+		#endif
+		ReleaseMutex(drawMutex);
+
+		// Update the cursor
+		if (++priv->x > priv->x1) {
+			priv->x = priv->x0;
+			if (++priv->y > priv->y1) {
+				g->flags |= GDISP_FLG_WRAPPED;
+				priv->y = priv->y0;
+			}
+		}
+
+		return BGR2COLOR(color);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("write_stop: not in streaming mode");
+		g->flags &= ~GDISP_FLG_WSTREAM;
+	}
+#endif
+
 #if GDISP_HARDWARE_DRAWPIXEL
 	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
 		winPriv	*	priv;
@@ -507,8 +713,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			ReleaseMutex(drawMutex);
 			{
 				RECT	r;
-				r.left = g->p.x; r.right = g->p.x+1;
-				r.top = g->p.y; r.bottom = g->p.y+1;
+				r.left = x; r.right = x+1;
+				r.top = y; r.bottom = y+1;
 				InvalidateRect(priv->hwnd, &r, FALSE);
 			}
 		#else
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index f6544eb4..e2fc3de4 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -26,12 +26,24 @@
 //	application to force a display update. eg after streaming.
 
 #define GDISP_HARDWARE_FLUSH			TRUE
-#define GDISP_HARDWARE_DRAWPIXEL		TRUE
-#define GDISP_HARDWARE_FILLS			TRUE
-#define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
-#define GDISP_HARDWARE_BITFILLS			TRUE
-#define GDISP_HARDWARE_SCROLL			TRUE
+
+//#define GDISP_WIN32_STREAMING_TEST
+#ifdef GDISP_WIN32_STREAMING_TEST
+	// These streaming routines are here only to debug the high level gdisp
+	//	code for streaming controllers. They are slow, inefficient and have
+	//	lots of debugging turned on.
+	#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+	#define GDISP_HARDWARE_STREAM_READ		TRUE
+	#define GDISP_HARDWARE_STREAM_POS		TRUE
+#else
+	// The proper way on the Win32. These routines are nice and fast.
+	#define GDISP_HARDWARE_DRAWPIXEL		TRUE
+	#define GDISP_HARDWARE_FILLS			TRUE
+	#define GDISP_HARDWARE_PIXELREAD		TRUE
+	#define GDISP_HARDWARE_BITFILLS			TRUE
+	#define GDISP_HARDWARE_SCROLL			TRUE
+#endif
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
 
-- 
cgit v1.2.3


From 4a5506df0a36a61b13c01b0173523a2ce31b5fb9 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 24 Oct 2013 11:32:46 +1000
Subject: Fixes to GDISP for streaming drivers. Turn optimisation back on for
 SSD1289 driver

---
 drivers/gdisp/SSD1289/gdisp_lld_config.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index f8743a2b..84e518d2 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -24,7 +24,7 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
-//#define GDISP_HARDWARE_STREAM_POS		TRUE
+#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #if defined(GDISP_USE_DMA)
-- 
cgit v1.2.3


From 90ad93c41fa86534479f7006ec2c3956da9eac3c Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 24 Oct 2013 11:59:41 +1000
Subject: Updates to SSD1306 driver to raise thread priority during flushing.

---
 drivers/gdisp/SSD1306/board_SSD1306_i2c.h | 15 +++++++++++++--
 drivers/gdisp/SSD1306/board_SSD1306_spi.h | 13 ++++++++++++-
 drivers/gdisp/SSD1306/gdisp_lld.c         |  2 +-
 3 files changed, 26 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
index c89562e0..69c054f5 100644
--- a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
+++ b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
@@ -41,6 +41,10 @@
 // I2C configuration structure.
 static I2CConfig i2cconfig;
 
+#if GFX_USE_OS_CHIBIOS
+	static int32_t thdPriority = 0;
+#endif
+
 static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->board to NULL as we don't use it.
@@ -62,10 +66,10 @@ static inline void init_board(GDisplay *g) {
 		 * 0x0030020A;		// 400kHz Fast Mode
 		 * 0x00100002;		// 800kHz Fast Mode +
 		 */
-		i2cconfig.timingr = 0x00100002;		// 800kHz Fast Mode+
-		i2cInit();
 		palSetPadMode(SSD1306_SCL_PORT, SSD1306_SCL_PIN, PAL_MODE_ALTERNATE(1));
 		palSetPadMode(SSD1306_SDA_PORT, SSD1306_SDA_PIN, PAL_MODE_ALTERNATE(1));
+		i2cconfig.timingr = 0x00100002;		// 800kHz Fast Mode+
+		i2cInit();
 		break;
 	}
 }
@@ -84,11 +88,18 @@ static inline void setpin_reset(GDisplay *g, bool_t state) {
 
 static inline void acquire_bus(GDisplay *g) {
 	(void) g;
+	#if GFX_USE_OS_CHIBIOS
+		thdPriority = (int32_t)chThdGetPriority();
+		chThdSetPriority(HIGHPRIO);
+	#endif
 	i2cAcquireBus(&I2CD1);
 }
 
 static inline void release_bus(GDisplay *g) {
 	(void) g;
+	#if GFX_USE_OS_CHIBIOS
+		chThdSetPriority(thdPriority);
+	#endif
 	i2cReleaseBus(&I2CD1);
 }
 
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_spi.h b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
index e206a517..476c51bf 100644
--- a/drivers/gdisp/SSD1306/board_SSD1306_spi.h
+++ b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
@@ -44,6 +44,10 @@ static const SPIConfig spi1config = {
 	//SPI_CR1_BR_0
 };
 
+#if GFX_USE_OS_CHIBIOS
+	static int32_t thdPriority = 0;
+#endif
+
 static inline void init_board(GDisplay *g) {
 
 	// As we are not using multiple displays we set g->board to NULL as we don't use it.
@@ -54,7 +58,6 @@ static inline void init_board(GDisplay *g) {
 		// RESET pin.
 		palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
 
-		spiInit();
 		palSetPadMode(SSD1306_MISO_PORT, SSD1306_MISO_PIN, 	PAL_MODE_ALTERNATE(1)|
 															PAL_STM32_OSPEED_HIGHEST);
 		palSetPadMode(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN, 	PAL_MODE_ALTERNATE(1)|
@@ -64,6 +67,7 @@ static inline void init_board(GDisplay *g) {
 		palSetPad(SSD1306_CS_PORT, SSD1306_CS_PIN);
 		palSetPadMode(SSD1306_CS_PORT,   SSD1306_CS_PIN,   	PAL_MODE_ALTERNATE(1)|
 															PAL_STM32_OSPEED_HIGHEST);
+		spiInit();
 		break;
 	}
 }
@@ -82,11 +86,18 @@ static inline void setpin_reset(GDisplay *g, bool_t state) {
 
 static inline void acquire_bus(GDisplay *g) {
 	(void) g;
+	#if GFX_USE_OS_CHIBIOS
+		thdPriority = (int32_t)chThdGetPriority();
+		chThdSetPriority(HIGHPRIO);
+	#endif
 	spiAcquireBus(&SPID1);
 }
 
 static inline void release_bus(GDisplay *g) {
 	(void) g;
+	#if GFX_USE_OS_CHIBIOS
+		chThdSetPriority(thdPriority);
+	#endif
 	spiReleaseBus(&SPID1);
 }
 
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c
index 079c9256..81b3b692 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.c
+++ b/drivers/gdisp/SSD1306/gdisp_lld.c
@@ -12,7 +12,7 @@
 
 #include "gfx.h"
 
-#if GFX_USE_GDISP || defined(__DOXYGEN__)
+#if GFX_USE_GDISP
 
 #define GDISP_DRIVER_VMT			GDISPVMT_SSD1306
 #include "../drivers/gdisp/SSD1306/gdisp_lld_config.h"
-- 
cgit v1.2.3


From 0b5fccd2c3a8d0022e662d393bf856e6bfa13702 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Thu, 24 Oct 2013 16:53:07 +1000
Subject: GDISP Win32 driver bug fix

---
 drivers/multiple/Win32/gdisp_lld.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 876168c3..7d7abb06 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -73,6 +73,9 @@ static DWORD			winThreadId;
 static ATOM				winClass;
 static volatile bool_t	QReady;
 static HANDLE			drawMutex;
+#if GINPUT_NEED_MOUSE
+	static GDisplay *	mouseDisplay;
+#endif
 
 /*===========================================================================*/
 /* Driver local routines    .                                                */
@@ -441,8 +444,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 	// Only turn on mouse on the first window for now
 	#if GINPUT_NEED_MOUSE
-		if (!g->controllerdisplay)
+		if (!g->controllerdisplay) {
+			mouseDisplay = g;
 			g->flags |= GDISP_FLG_HASMOUSE;
+		}
 	#endif
 
 	// Create a private area for this window
@@ -811,6 +816,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		
 		// Copy the bits we need
 		switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			return 0;					// not handled as it doesn't need to be.
 		case GDISP_ROTATE_90:
 			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
 				dst = dstbuf+sz-g->p.cy+j;
@@ -931,7 +938,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 		#if GDISP_NEED_CONTROL
 			if (buffer != (pixel_t *)g->p.ptr)
-				free(srcimg);
+				free(buffer);
 		#endif
 	}
 #endif
@@ -977,7 +984,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		priv = g->priv;
 
 		#if GDISP_NEED_CONTROL
-			switch(GC->g.Orientation) {
+			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
 				rect.top = g->p.y;
 				rect.bottom = rect.top+g->p.cy;
@@ -995,7 +1002,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			case GDISP_ROTATE_180:
 				rect.bottom = g->g.Height - g->p.y;
 				rect.top = rect.bottom-g->p.cy;
-				rect.right = GC->g.Width - g->p.x;
+				rect.right = g->g.Width - g->p.x;
 				rect.left = rect.right-g->p.cx;
 				lines = g->p.y1;
 			vertical_scroll:
@@ -1116,13 +1123,16 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 #if GINPUT_NEED_MOUSE
 	void ginput_lld_mouse_init(void) {}
 	void ginput_lld_mouse_get_reading(MouseReading *pt) {
-		GDisplay *g;
+		GDisplay *	g;
+		winPriv	*	priv;
+
+		g = mouseDisplay;
+		priv = g->priv;
 
-		g = GDISP_WIN32;
-		pt->x = g->priv->mousex;
-		pt->y = g->priv->mousey > g->g.Height ? g->g.Height : mousey;
-		pt->z = (g->priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
-		pt->buttons = g->priv->mousebuttons;
+		pt->x = priv->mousex;
+		pt->y = priv->mousey > g->g.Height ? g->g.Height : priv->mousey;
+		pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
+		pt->buttons = priv->mousebuttons;
 	}
 #endif /* GINPUT_NEED_MOUSE */
 
-- 
cgit v1.2.3


From f3f7eba73cb199c0222440ea50052b77975f170a Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Thu, 24 Oct 2013 14:08:35 +0200
Subject: fixed board file name (all the others are upper case as well)

---
 drivers/gdisp/RA8875/gdisp_lld.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
index b0508b58..fb81c43a 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ b/drivers/gdisp/RA8875/gdisp_lld.c
@@ -19,7 +19,7 @@
 #include "gdisp/lld/gdisp_lld.h"
 
 /* include the users board interface */
-#include "board_ra8875.h"
+#include "board_RA8875.h"
 
 /*===========================================================================*/
 /* Driver local definitions.                                                 */
-- 
cgit v1.2.3


From af3963d341f14fd46a2eaa26f53f44de641299dc Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Thu, 24 Oct 2013 14:49:00 +0200
Subject: fixed RA8875 board file for marlin

---
 drivers/gdisp/RA8875/board_RA8875_marlin.h | 64 ++++++++++++++++++------------
 1 file changed, 39 insertions(+), 25 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
index e6c19d34..b1d55a92 100644
--- a/drivers/gdisp/RA8875/board_RA8875_marlin.h
+++ b/drivers/gdisp/RA8875/board_RA8875_marlin.h
@@ -10,52 +10,62 @@
  * @brief   GDISP Graphic Driver subsystem board interface for the RA8875 display.
  */
 
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
+#ifndef _BOARD_RA8875_H
+#define _BOARD_RA8875_H
 
 // For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
+// set g->board to that structure.
 #define GDISP_RAM              (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */
 #define GDISP_REG              (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */
 #define FSMC_BANK				4
 
 
 static inline void init_board(GDisplay *g) {
-
 	// As we are not using multiple displays we set g->board to NULL as we don't use it.
 	g->board = 0;
 
 	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* set pins to FSMC mode */
-		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 8) |
-								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+		// setup for display 0
+		case 0: {		
+
+			// enable the FSMC peripheral
+			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
+
+			// setup the pin modes for FSMC
+			IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 8) |
+									(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
+
+			IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
+								(1 << 13) | (1 << 14) | (1 << 15), 0};
+
+			IOBus busG = {GPIOG, (1 << 10), 0};
 
-		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-							(1 << 13) | (1 << 14) | (1 << 15), 0};
+			palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
+			palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
+			palSetBusMode(&busG, PAL_MODE_ALTERNATE(12));
 
-		IOBus busG = {GPIOG, (1 << 10), 0};
+			// FSMC timing
+			FSMC_Bank1->BTCR[FSMC_BANK+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
+					| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
+					| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
 
-		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-		palSetBusMode(&busG, PAL_MODE_ALTERNATE(12));
+			// Bank1 NOR/SRAM control register configuration
+			// This is actually not needed as already set by default after reset
+			FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
 
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[FSMC_BANK+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
-				| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
-				| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
+			break;
+		}
 
-		/* Bank1 NOR/SRAM control register configuration
-		 * This is actually not needed as already set by default after reset */
-		FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-		break;
+		// marlin does not have any secondary display so far
+		default:
+			break;
 	}
 }
 
 static inline void post_init_board(GDisplay *g) {
 	(void) g;
-
-	/* FSMC delay reduced as the controller now runs at full speed */
+	
+	// FSMC delay reduced as the controller now runs at full speed
 	FSMC_Bank1->BTCR[2+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
 	FSMC_Bank1->BTCR[2] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
 }
@@ -75,11 +85,13 @@ static inline void release_bus(GDisplay *g) {
 
 static inline void write_index(GDisplay *g, uint16_t index) {
 	(void) g;
+
 	GDISP_REG = index;
 }
 
 static inline void write_data(GDisplay *g, uint16_t data) {
 	(void) g;
+
 	GDISP_RAM = data;
 }
 
@@ -93,7 +105,9 @@ static inline void setwritemode(GDisplay *g) {
 
 static inline uint16_t read_data(GDisplay *g) {
 	(void) g;
+
 	return GDISP_RAM;
 }
 
-#endif /* _GDISP_LLD_BOARD_H */
+#endif /* _BOARD_RA8875_H */
+
-- 
cgit v1.2.3


From e0b2406da613b02fce6af8aead160e43301a3852 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Fri, 25 Oct 2013 14:39:56 +1000
Subject: Fix SSD1306 driver and board files to allow for seamless transfer of
 the command byte with the page line data without copying the data on to the
 stack.

---
 drivers/gdisp/SSD1306/board_SSD1306_i2c.h      |  9 +++------
 drivers/gdisp/SSD1306/board_SSD1306_spi.h      |  9 ++++-----
 drivers/gdisp/SSD1306/board_SSD1306_template.h |  6 +++---
 drivers/gdisp/SSD1306/gdisp_lld.c              | 26 ++++++++++++++++++++++----
 4 files changed, 32 insertions(+), 18 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
index 69c054f5..449d47ba 100644
--- a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
+++ b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
@@ -13,7 +13,8 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
-#define GDISP_BUS_MAX_TRANSFER_SIZE		64
+// The command byte to put on the front of each page line
+#define SSD1306_PAGE_PREFIX		0x40			 		// Co = 0, D/C = 1
 
 // For a multiple display configuration we would put all this in a structure and then
 //	set g->board to that structure.
@@ -116,14 +117,10 @@ static inline void write_cmd(GDisplay *g, uint8_t cmd) {
 }
 
 static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
-	uint8_t command[1];
 	(void) g;
 
-	command[0] = 0x40; 		// Co = 0, D/C = 1
-
 	i2cStart(&I2CD1, &i2cconfig);
-	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 1, NULL, 0, MS2ST(10));
-	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, data, NULL, length, MS2ST(10));
+	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, data, length, NULL, 0, MS2ST(10));
 	i2cStop(&I2CD1);
 }
 
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_spi.h b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
index 476c51bf..5b481630 100644
--- a/drivers/gdisp/SSD1306/board_SSD1306_spi.h
+++ b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
@@ -13,7 +13,8 @@
 #ifndef _GDISP_LLD_BOARD_H
 #define _GDISP_LLD_BOARD_H
 
-#define GDISP_BUS_MAX_TRANSFER_SIZE		64
+// The command byte to put on the front of each page line
+#define SSD1306_PAGE_PREFIX		0x40			 		// Co = 0, D/C = 1
 
 // For a multiple display configuration we would put all this in a structure and then
 //	set g->board to that structure.
@@ -49,10 +50,12 @@ static const SPIConfig spi1config = {
 #endif
 
 static inline void init_board(GDisplay *g) {
+	unsigned	i;
 
 	// As we are not using multiple displays we set g->board to NULL as we don't use it.
 	g->board = 0;
 
+
 	switch(g->controllerdisplay) {
 	case 0:											// Set up for Display 0
 		// RESET pin.
@@ -115,14 +118,10 @@ static inline void write_cmd(GDisplay *g, uint8_t cmd) {
 }
 
 static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
-	uint8_t command[1];
 	(void) g;
 
-	command[0] = 0x40; 		// Co = 0, D/C = 1
-
 	spiStart(&SPID1, &spi1config);
 	spiSelect(&SPID1);
-	spiStartSend(&SPID1, 1, command);
 	spiStartSend(&SPID1, length, data);
 	spiUnselect(&SPID1);
 	spiStop(&SPID1);
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_template.h b/drivers/gdisp/SSD1306/board_SSD1306_template.h
index ec7f44f5..5b4bd05c 100644
--- a/drivers/gdisp/SSD1306/board_SSD1306_template.h
+++ b/drivers/gdisp/SSD1306/board_SSD1306_template.h
@@ -17,12 +17,12 @@
 #define _GDISP_LLD_BOARD_H
 
 /**
- * @brief   How many bytes to write in one operation when updating the display.
- * @note	The screen size (in bytes) must evenly divide by this number.
+ * @brief   Optional: A byte to prefix on each display page line.
+ * @note	If not defined then no byte is prefixed on each page line.
  *
  * @notapi
  */
-#define GDISP_BUS_MAX_TRANSFER_SIZE		64
+//#define SSD1306_PAGE_PREFIX		0x40
 
 /**
  * @brief   Initialise the board for the display.
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c
index 81b3b692..390a9282 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.c
+++ b/drivers/gdisp/SSD1306/gdisp_lld.c
@@ -36,6 +36,13 @@
 #ifndef GDISP_INITIAL_BACKLIGHT
 	#define GDISP_INITIAL_BACKLIGHT	100
 #endif
+#ifdef SSD1306_PAGE_PREFIX
+	#define SSD1306_PAGE_WIDTH		(GDISP_SCREEN_WIDTH+1)
+	#define SSD1306_PAGE_OFFSET		1
+#else
+	#define SSD1306_PAGE_WIDTH		GDISP_SCREEN_WIDTH
+	#define SSD1306_PAGE_OFFSET		0
+#endif
 
 #define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
 
@@ -54,7 +61,7 @@
 #define delay(us)			gfxSleepMicroseconds(us)
 #define delayms(ms)			gfxSleepMilliseconds(ms)
 
-#define xyaddr(x, y)		((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
+#define xyaddr(x, y)		(SSD1306_PAGE_OFFSET + (x) + ((y)>>3)*SSD1306_PAGE_WIDTH)
 #define xybit(y)			(1<<((y)&7))
 
 /*===========================================================================*/
@@ -70,7 +77,18 @@
 
 LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	// The private area is the display surface.
-	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
+	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH);
+
+	// Fill in the prefix command byte on each page line of the display buffer
+	// We can do it during initialisation as this byte is never overwritten.
+	#ifdef SSD1306_PAGE_PREFIX
+		{
+			unsigned	i;
+
+			for(i=0; i < GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH; i+=SSD1306_PAGE_WIDTH)
+				RAM(g)[i] = SSD1306_PAGE_PREFIX;
+		}
+	#endif
 
 	// Initialise the board interface
 	init_board(g);
@@ -131,8 +149,8 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 		write_cmd(g, SSD1306_SETSTARTLINE | 0);
 
-		for(i=0; i < GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT/8; i+=GDISP_BUS_MAX_TRANSFER_SIZE)
-			write_data(g, RAM(g)+i, GDISP_BUS_MAX_TRANSFER_SIZE);
+		for(i=0; i < GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH; i+=SSD1306_PAGE_WIDTH)
+			write_data(g, RAM(g)+i, SSD1306_PAGE_WIDTH);
 	}
 #endif
 
-- 
cgit v1.2.3


From 9f1e3716812ed9e922af020498c36cadad49819d Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Sat, 26 Oct 2013 21:32:55 +1000
Subject: Compile fix for GE12

---
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index ef8cd043..c04b4cf9 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -71,7 +71,7 @@
 
 // Use the priv pointer itself to save our color. This save allocating ram for it
 //	and works provided sizeof(color_t) <= sizeof(void *)
-#define savecolor(g)					((color_t)g->priv)
+#define savecolor(g)					(*(color_t *)&g->priv)
 
 #define GDISP_FLG_ODDBYTE				(GDISP_FLG_DRIVER<<0)
 
-- 
cgit v1.2.3


From 2112074e79cf4d9cf4c40f358af3b6280f389148 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sat, 26 Oct 2013 14:59:52 +0200
Subject: Nokia6610GE8 compiler warning

---
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c | 4 ++++
 1 file changed, 4 insertions(+)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index f724ee42..e0cfb997 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -328,6 +328,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		acquire_bus(g);
 		set_viewport(g);
 
+		/* to surpress compiler warnings */
+		x = 0;
+		y = 0;
+
 		/*
 		 * Due to the way the Nokia6610 handles a decrementing column or page,
 		 * we have to make adjustments as to where it is actually drawing from in the bitmap.
-- 
cgit v1.2.3


From a756806b77fc431c9515041fc83dbc06c2854b56 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sat, 26 Oct 2013 14:59:52 +0200
Subject: Compile Fix for Nokia6610GE12

---
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index c04b4cf9..d1086c46 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -248,7 +248,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		case GDISP_CONTROL_CONTRAST:
 			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
 			acquire_bus(g);
-			write_reg(g, CONTRAST,(unsigned)128*g->p.ptr/101-64);
+			write_reg(g, SETCON,(unsigned)128*(unsigned)g->p.ptr/101-64);
 			release_bus(g);
 			g->g.Contrast = (unsigned)g->p.ptr;
 			return;
-- 
cgit v1.2.3


From aca01e68a2b28d7027673dfb098155c119afdacc Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sat, 26 Oct 2013 17:51:27 +0200
Subject: whitespaces

---
 drivers/gdisp/ILI9320/gdisp_lld.mk       |  4 +--
 drivers/gdisp/ILI9320/gdisp_lld_config.h | 52 ++++++++++++++++----------------
 2 files changed, 28 insertions(+), 28 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.mk b/drivers/gdisp/ILI9320/gdisp_lld.mk
index 656f5930..071e7c02 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9320/gdisp_lld.mk
@@ -1,2 +1,2 @@
-GFXINC += $(GFXLIB)/drivers/gdisp/ILI9320
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.c
+GFXINC += $(GFXLIB)/drivers/gdisp/ILI9320
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.c
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
index 3c5c7484..861b3a1b 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -4,33 +4,33 @@
  *
  *              http://ugfx.org/license.html
  */
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld_config.h
- * @brief   GDISP Graphic Driver subsystem low level driver header for the ILI9320 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_CONFIG_H
-#define GDISP_LLD_CONFIG_H
-
-#if GFX_USE_GDISP
-
-/*===========================================================================*/
-/* Driver hardware support.                                                  */
-/*===========================================================================*/
-
+
+/**
+ * @file    drivers/gdisp/ILI9320/gdisp_lld_config.h
+ * @brief   GDISP Graphic Driver subsystem low level driver header for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_CONFIG_H
+#define GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support.                                                  */
+/*===========================================================================*/
+
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
-
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-
-#endif	/* GFX_USE_GDISP */
-
-#endif	/* _GDISP_LLD_CONFIG_H */
-/** @} */
-
+
+#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+
+#endif	/* GFX_USE_GDISP */
+
+#endif	/* _GDISP_LLD_CONFIG_H */
+/** @} */
+
-- 
cgit v1.2.3


From 579a7806716a08cbcc6829ea26eff3c15519a932 Mon Sep 17 00:00:00 2001
From: Joel Bodenmann <joel@unormal.org>
Date: Sat, 26 Oct 2013 17:52:49 +0200
Subject: Test fix for ILI9320 driver.

---
 drivers/gdisp/ILI9320/gdisp_lld.c        | 11 ++++++++---
 drivers/gdisp/ILI9320/gdisp_lld_config.h |  2 +-
 2 files changed, 9 insertions(+), 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index 6d7815cb..a18c2d82 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -199,6 +199,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
 		acquire_bus(g);
 		set_viewport(g);
+		#if !GDISP_HARDWARE_STREAM_POS
+			set_cursor(g);
+		#endif
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		write_data(g, g->p.color);
@@ -206,9 +209,11 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
 	}
-	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-		set_cursor(g);
-	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			set_cursor(g);
+		}
+	#endif
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
index 861b3a1b..1a1f139f 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -24,7 +24,7 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_STREAM_READ		TRUE
-#define GDISP_HARDWARE_STREAM_POS		TRUE
+//#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-- 
cgit v1.2.3


From 9e5ed28f98e7b0b3dbd46df7a62568dbaffab92a Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 28 Oct 2013 10:48:09 +1000
Subject: New ILI9341 driver - not working fully yet (some display issues)

---
 drivers/gdisp/ILI9341/ILI9341.h                  |  87 ++++++
 drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h | 130 ++++++++
 drivers/gdisp/ILI9341/board_ILI9341_template.h   | 154 ++++++++++
 drivers/gdisp/ILI9341/gdisp_lld.c                | 373 +++++++++++++++++++++++
 drivers/gdisp/ILI9341/gdisp_lld.mk               |   2 +
 drivers/gdisp/ILI9341/gdisp_lld_config.h         |  36 +++
 6 files changed, 782 insertions(+)
 create mode 100644 drivers/gdisp/ILI9341/ILI9341.h
 create mode 100644 drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
 create mode 100644 drivers/gdisp/ILI9341/board_ILI9341_template.h
 create mode 100644 drivers/gdisp/ILI9341/gdisp_lld.c
 create mode 100644 drivers/gdisp/ILI9341/gdisp_lld.mk
 create mode 100644 drivers/gdisp/ILI9341/gdisp_lld_config.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9341/ILI9341.h b/drivers/gdisp/ILI9341/ILI9341.h
new file mode 100644
index 00000000..bace6907
--- /dev/null
+++ b/drivers/gdisp/ILI9341/ILI9341.h
@@ -0,0 +1,87 @@
+
+#define LCD_VERTICAL_MAX        		320
+#define LCD_HORIZONTAL_MAX      		240
+
+#define ILI9341_DEVICE_CODE_READ_REG    0x00
+#define ILI9341_SOFT_RESET_REG			0x01
+#define ILI9341_IDENTINFO_R_REG			0x04
+#define ILI9341_STATUS_R_REG			0x09
+#define ILI9341_POWERMODE_R_REG			0x0A
+#define ILI9341_MADCTL_R_REG			0x0B
+#define ILI9341_PIXFORMAT_R_REG			0x0C
+#define ILI9341_IMGFORMAT_R_REG			0x0D
+#define ILI9341_SIGMODE_R_REG			0x0E
+#define ILI9341_SD_RESULT_R_REG			0x0F
+#define ILI9341_SLEEP_ENTER_REG			0x10
+#define ILI9341_SLEEP_OUT_REG			0x11
+#define ILI9341_PARTIALMODE_REG			0x12
+#define ILI9341_NORDISPMODE_REG			0x13
+#define ILI9341_INVERSIONOFF_REG		0x20
+#define ILI9341_INVERSIONON_REG			0x21
+#define ILI9341_GAMMASET_REG			0x26
+#define ILI9341_DISPLAYOFF_REG			0x28
+#define ILI9341_DISPLAYON_REG			0x29
+#define ILI9341_COLADDRSET_REG			0x2A
+#define ILI9341_PAGEADDRSET_REG			0x2B
+#define ILI9341_MEMORYWRITE_REG			0x2C
+#define ILI9341_COLORSET_REG			0x2D
+#define ILI9341_MEMORYREAD_REG			0x2E
+#define ILI9341_PARTIALAREA_REG			0x30
+#define ILI9341_VERTSCROLL_REG			0x33
+#define ILI9341_TEAREFFECTLINEOFF_REG	0x34
+#define ILI9341_TEAREFFECTLINEON_REG	0x35
+#define ILI9341_MEMACCESS_REG			0x36
+#define ILI9341_VERSCRSRART_REG			0x37
+#define ILI9341_IDLEMODEOFF_REG			0x38
+#define ILI9341_IDLEMODEON_REG			0x39
+#define ILI9341_PIXFORMATSET_REG		0x3A
+#define ILI9341_WRITEMEMCONTINUE_REG	0x3C
+#define ILI9341_READMEMCONTINUE_REG		0x3E
+#define ILI9341_SETTEATSCAN_REG			0x44
+#define ILI9341_GETSCANLINE_REG			0x45
+#define ILI9341_WRITEBRIGHT_REG			0x51
+#define ILI9341_READBRIGHT_REG			0x52
+#define ILI9341_WRITECTRL_REG			0x53
+#define ILI9341_READCTRL_REG			0x54
+#define ILI9341_WRITECABC_REG			0x55
+#define ILI9341_READCABC_REG			0x56
+#define ILI9341_WRITECABCMB_REG			0x5E
+#define ILI9341_READCABCMB_REG			0x5F
+#define ILI9341_RGB_ISCTL_REG			0xB0
+#define ILI9341_FRAMECTL_NOR_REG		0xB1
+#define ILI9341_FRAMECTL_IDLE_REG		0xB2
+#define ILI9341_FRAMECTL_PARTIAL_REG	0xB3
+#define ILI9341_INVERCTL_REG			0xB4
+#define ILI9341_BLANKPORCTL_REG			0xB5
+#define ILI9341_FUNCTONCTL_REG			0xB6
+#define ILI9341_ENTRYMODE_REG			0xB7
+#define ILI9341_BLIGHTCTL1_REG			0xB8
+#define ILI9341_BLIGHTCTL2_REG			0xB9
+#define ILI9341_BLIGHTCTL3_REG			0xBA
+#define ILI9341_BLIGHTCTL4_REG			0xBB
+#define ILI9341_BLIGHTCTL5_REG			0xBC
+#define ILI9341_BLIGHTCTL7_REG			0xBE
+#define ILI9341_BLIGHTCTL8_REG			0xBF
+#define ILI9341_POWERCTL1_REG			0xC0
+#define ILI9341_POWERCTL2_REG			0xC1
+#define ILI9341_VCOMCTL1_REG			0xC5
+#define ILI9341_VCOMCTL2_REG			0xC7
+#define ILI9341_POWERCTLA_REG			0xCB
+#define ILI9341_POWERCTLB_REG			0xCF
+#define ILI9341_NVMEMWRITE_REG			0xD0
+#define ILI9341_NVMEMPROTECTKEY_REG		0xD1
+#define ILI9341_NVMEMSTATUS_REG			0xD2
+#define ILI9341_READID4_REG				0xD3
+#define ILI9341_READID1_REG				0xDA
+#define ILI9341_READID2_REG				0xDB
+#define ILI9341_READID3_REG				0xDC
+#define ILI9341_POSGAMMACORRECTION_REG	0xE0
+#define ILI9341_NEGGAMMACORRECTION_REG	0xE1
+#define ILI9341_DIGGAMCTL1_REG			0xE2
+#define ILI9341_DIGGAMCTL2_REG			0xE3
+#define ILI9341_DIVTIMCTL_A_REG			0xE8
+#define ILI9341_DIVTIMCTL_B_REG			0xEA
+#define ILI9341_POWONSEQCTL_REG			0xED
+#define ILI9341_ENABLE_3G_REG			0xF2
+#define ILI9341_INTERFCTL_REG			0xF6
+#define ILI9341_PUMPRATIOCTL_REG		0xF7
diff --git a/drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h b/drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
new file mode 100644
index 00000000..a0eed13b
--- /dev/null
+++ b/drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
@@ -0,0 +1,130 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9341 display.
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+// For a multiple display configuration we would put all this in a structure and then
+//	set g->board to that structure.
+#define SET_CS    palSetPad(GPIOE, GPIOE_LCD_CS);
+#define CLR_CS    palClearPad(GPIOE, GPIOE_LCD_CS);
+#define SET_RS    palSetPad(GPIOE, GPIOE_LCD_RS);
+#define CLR_RS    palClearPad(GPIOE, GPIOE_LCD_RS);
+#define SET_WR    palSetPad(GPIOE, GPIOE_PMWR);
+#define CLR_WR    palClearPad(GPIOE, GPIOE_PMWR);
+#define SET_RD    palSetPad(GPIOE, GPIOE_PMRD);
+#define CLR_RD    palClearPad(GPIOE, GPIOE_PMRD);
+
+static inline void init_board(GDisplay *g) {
+
+	// As we are not using multiple displays we set g->board to NULL as we don't use it.
+	g->board = 0;
+
+	switch(g->controllerdisplay) {
+	case 0:											// Set up for Display 0
+		/* Configure the pins to a well know state */
+		SET_RS;
+		SET_RD;
+		SET_WR;
+		CLR_CS;
+
+		/* Hardware reset */
+		palSetPad(GPIOE, GPIOE_LCD_RST);
+		chThdSleepMilliseconds(100);
+		palClearPad(GPIOE, GPIOE_LCD_RST);
+		chThdSleepMilliseconds(100);
+		palSetPad(GPIOE, GPIOE_LCD_RST);
+		chThdSleepMilliseconds(100);
+		break;
+	}
+}
+
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	if(state) {
+		// reset lcd
+		palClearPad(GPIOE, GPIOE_LCD_RST);
+	} else {
+		palSetPad(GPIOE, GPIOE_LCD_RST);
+	}
+}
+
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	// TODO: can probably pwm this
+	if(percent) {
+		// turn back light on
+		palSetPad(GPIOE, GPIOE_LCD_BLED);
+	} else {
+		// turn off
+		palClearPad(GPIOE, GPIOE_LCD_BLED);
+	}
+}
+
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Short delay
+ *
+ * @param[in] dly		Length of delay
+ *
+ * @notapi
+ */
+static inline void ili9341_delay(uint16_t dly) {
+  static uint16_t i;
+  for(i = 0; i < dly; i++)
+    asm("nop");
+}
+
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	palWriteGroup(GPIOE, 0x00FF, 0, index);
+	CLR_RS; CLR_WR; ili9341_delay(1); SET_WR; ili9341_delay(1); SET_RS;
+}
+
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	palWriteGroup(GPIOE, 0x00FF, 0, data);
+	CLR_WR; ili9341_delay(1); SET_WR; ili9341_delay(1);
+}
+
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+	// change pin mode to digital input
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
+}
+
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+	// change pin mode back to digital output
+	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
+}
+
+static inline uint16_t read_data(GDisplay *g) {
+	CLR_RD;
+	value = palReadPort(GPIOE);
+	value = palReadPort(GPIOE);
+	SET_RD;
+	return value;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9341/board_ILI9341_template.h b/drivers/gdisp/ILI9341/board_ILI9341_template.h
new file mode 100644
index 00000000..b8f55dc1
--- /dev/null
+++ b/drivers/gdisp/ILI9341/board_ILI9341_template.h
@@ -0,0 +1,154 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9341/board_ILI9341_template.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9341 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_BOARD_H
+#define _GDISP_LLD_BOARD_H
+
+/**
+ * @brief   Initialise the board for the display.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @note	Set the g->board member to whatever is appropriate. For multiple
+ * 			displays this might be a pointer to the appropriate register set.
+ *
+ * @notapi
+ */
+static inline void init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   After the initialisation.
+ *
+ * @param[in] g			The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void post_init_board(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set or clear the lcd reset pin.
+ *
+ * @param[in] g			The GDisplay structure
+ * @param[in] state		TRUE = lcd in reset, FALSE = normal operation
+ * 
+ * @notapi
+ */
+static inline void setpin_reset(GDisplay *g, bool_t state) {
+	(void) g;
+	(void) state;
+}
+
+/**
+ * @brief   Set the lcd back-light level.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] percent		0 to 100%
+ * 
+ * @notapi
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	(void) g;
+	(void) percent;
+}
+
+/**
+ * @brief   Take exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void acquire_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Release exclusive control of the bus
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void release_bus(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Send data to the index register.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] index			The index register to set
+ *
+ * @notapi
+ */
+static inline void write_index(GDisplay *g, uint16_t index) {
+	(void) g;
+	(void) index;
+}
+
+/**
+ * @brief   Send data to the lcd.
+ *
+ * @param[in] g				The GDisplay structure
+ * @param[in] data			The data to send
+ * 
+ * @notapi
+ */
+static inline void write_data(GDisplay *g, uint16_t data) {
+	(void) g;
+	(void) data;
+}
+
+/**
+ * @brief   Set the bus in read mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setreadmode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Set the bus back into write mode
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline void setwritemode(GDisplay *g) {
+	(void) g;
+}
+
+/**
+ * @brief   Read data from the lcd.
+ * @return	The data from the lcd
+ *
+ * @param[in] g				The GDisplay structure
+ *
+ * @notapi
+ */
+static inline uint16_t read_data(GDisplay *g) {
+	(void) g;
+	return 0;
+}
+
+#endif /* _GDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gdisp/ILI9341/gdisp_lld.c b/drivers/gdisp/ILI9341/gdisp_lld.c
new file mode 100644
index 00000000..e5c4b7d0
--- /dev/null
+++ b/drivers/gdisp/ILI9341/gdisp_lld.c
@@ -0,0 +1,373 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9341/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for
+ * 			the ILI9341 and compatible HVGA display
+ */
+
+#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_ILI9341
+#include "../drivers/gdisp/ILI9341/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ILI9341.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+#include "../drivers/gdisp/ILI9341/ILI9341.h"
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// 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_index(g, reg); write_data(g, data); }
+#define write_data16(g, data)		{ write_data(g, data >> 8); write_data(g, (uint8_t)data); }
+#define delay(us)					gfxSleepMicroseconds(us)
+#define delayms(ms)					gfxSleepMilliseconds(ms)
+
+static inline void set_cursor(GDisplay *g) {
+	write_index(g, 0x2A);
+	write_data(g, (g->p.x >> 8));
+	write_data(g, (uint8_t) g->p.x);
+	write_data(g, (g->p.x) >> 8);
+	write_data(g, (uint8_t) (g->p.x));
+
+	write_index(g, 0x2B);
+	write_data(g, (g->p.y >> 8));
+	write_data(g, (uint8_t) g->p.y);
+	write_data(g, (g->p.y) >> 8);
+	write_data(g, (uint8_t) (g->p.y));
+
+	write_index(g, 0x2C);
+}
+
+static void set_viewport(GDisplay *g) {
+	write_index(g, 0x2A);
+	write_data(g, (g->p.x >> 8));
+	write_data(g, (uint8_t) g->p.x);
+	write_data(g, (g->p.x + g->p.cx - 1) >> 8);
+	write_data(g, (uint8_t) (g->p.x + g->p.cx - 1));
+
+	write_index(g, 0x2B);
+	write_data(g, (g->p.y >> 8));
+	write_data(g, (uint8_t) g->p.y);
+	write_data(g, (g->p.y + g->p.cy - 1) >> 8);
+	write_data(g, (uint8_t) (g->p.y + g->p.cy - 1));
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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_index(g, 0x01); //software reset
+	chThdSleepMilliseconds(5);
+	write_index(g, 0x28);
+	// display off
+	//---------------------------------------------------------
+	// magic?
+	write_index(g, 0xcf);
+	write_data(g, 0x00);
+	write_data(g, 0x83);
+	write_data(g, 0x30);
+
+	write_index(g, 0xed);
+	write_data(g, 0x64);
+	write_data(g, 0x03);
+	write_data(g, 0x12);
+	write_data(g, 0x81);
+	write_index(g, 0xe8);
+	write_data(g, 0x85);
+	write_data(g, 0x01);
+	write_data(g, 0x79);
+	write_index(g, 0xcb);
+	write_data(g, 0x39);
+	write_data(g, 0x2c);
+	write_data(g, 0x00);
+	write_data(g, 0x34);
+	write_data(g, 0x02);
+	write_index(g, 0xf7);
+	write_data(g, 0x20);
+	write_index(g, 0xea);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	//------------power control------------------------------
+	write_index(g, 0xc0); //power control
+	write_data(g, 0x26);
+	write_index(g, 0xc1); //power control
+	write_data(g, 0x11);
+	//--------------VCOM
+	write_index(g, 0xc5); //vcom control
+	write_data(g, 0x35);//35
+	write_data(g, 0x3e);//3E
+	write_index(g, 0xc7); //vcom control
+	write_data(g, 0xbe); // 0x94
+	//------------memory access control------------------------
+	write_index(g, 0x36);
+	// memory access control
+	write_data(g, 0x48); //0048 my,mx,mv,ml,BGR,mh,0.0
+	write_index(g, 0x3a); // pixel format set
+	write_data(g, 0x55);//16bit /pixel
+	//----------------- frame rate------------------------------
+	write_index(g, 0xb1);
+	// frame rate
+	write_data(g, 0x00);
+	write_data(g, 0x1B); //70
+	//----------------Gamma---------------------------------
+	write_index(g, 0xf2); // 3Gamma Function Disable
+	write_data(g, 0x08);
+	write_index(g, 0x26);
+	write_data(g, 0x01); // gamma set 4 gamma curve 01/02/04/08
+
+	write_index(g, 0xE0); //positive gamma correction
+	write_data(g, 0x1f);
+	write_data(g, 0x1a);
+	write_data(g, 0x18);
+	write_data(g, 0x0a);
+	write_data(g, 0x0f);
+	write_data(g, 0x06);
+	write_data(g, 0x45);
+	write_data(g, 0x87);
+	write_data(g, 0x32);
+	write_data(g, 0x0a);
+	write_data(g, 0x07);
+	write_data(g, 0x02);
+	write_data(g, 0x07);
+	write_data(g, 0x05);
+	write_data(g, 0x00);
+	write_index(g, 0xE1); //negamma correction
+	write_data(g, 0x00);
+	write_data(g, 0x25);
+	write_data(g, 0x27);
+	write_data(g, 0x05);
+	write_data(g, 0x10);
+	write_data(g, 0x09);
+	write_data(g, 0x3a);
+	write_data(g, 0x78);
+	write_data(g, 0x4d);
+	write_data(g, 0x05);
+	write_data(g, 0x18);
+	write_data(g, 0x0d);
+	write_data(g, 0x38);
+	write_data(g, 0x3a);
+	write_data(g, 0x1f);
+	//--------------ddram ---------------------
+	write_index(g, 0x2a);
+	// column set
+	// size = 239
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0xEF);
+	write_index(g, 0x2b);
+	// page address set
+	// size = 319
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x01);
+	write_data(g, 0x3F);
+	// write_index(g, 0x34);
+	//write_index(g, 0x35);
+	// tearing effect off
+	// tearing effect on
+	// write_index(g, 0xb4); // display inversion
+	// write_data(g, 0x00);
+	write_index(g, 0xb7); //entry mode set
+	write_data(g, 0x07);
+	//-----------------display---------------------
+	write_index(g, 0xb6);
+	// display function control
+	write_data(g, 0x0a);
+	write_data(g, 0x82);
+	write_data(g, 0x27);
+	write_data(g, 0x00);
+	write_index(g, 0x11); //sleep out
+	chThdSleepMilliseconds(100);
+	write_index(g, 0x29); // display on
+	chThdSleepMilliseconds(100);
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		#if !GDISP_HARDWARE_STREAM_POS
+			set_cursor(g);
+		#endif
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data16(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			set_cursor(g);
+		}
+	#endif
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		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_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
+				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);
+				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				write_reg(g, 0x36, 0x80);	/* X and Y axes non-inverted */
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				write_reg(g, 0x36, 0xE0);	/* Invert X and Y axes */
+				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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9341/gdisp_lld.mk b/drivers/gdisp/ILI9341/gdisp_lld.mk
new file mode 100644
index 00000000..8c44fc85
--- /dev/null
+++ b/drivers/gdisp/ILI9341/gdisp_lld.mk
@@ -0,0 +1,2 @@
+GFXINC += $(GFXLIB)/drivers/gdisp/ILI9341
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9341/gdisp_lld.c
diff --git a/drivers/gdisp/ILI9341/gdisp_lld_config.h b/drivers/gdisp/ILI9341/gdisp_lld_config.h
new file mode 100644
index 00000000..8246934d
--- /dev/null
+++ b/drivers/gdisp/ILI9341/gdisp_lld_config.h
@@ -0,0 +1,36 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9481/gdisp_lld_config.h
+ * @brief   GDISP Graphics Driver subsystem low level driver source for
+ * 			the ILI9481 and compatible HVGA display
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef _GDISP_LLD_CONFIG_H
+#define _GDISP_LLD_CONFIG_H
+
+#if GFX_USE_GDISP
+
+/*===========================================================================*/
+/* Driver hardware support.                                                  */
+/*===========================================================================*/
+
+#define GDISP_HARDWARE_STREAM_WRITE		TRUE
+//#define GDISP_HARDWARE_STREAM_READ		TRUE
+//#define GDISP_HARDWARE_STREAM_POS		TRUE
+#define GDISP_HARDWARE_CONTROL			TRUE
+
+#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+
+#endif	/* GFX_USE_GDISP */
+
+#endif	/* _GDISP_LLD_CONFIG_H */
+/** @} */
-- 
cgit v1.2.3


From b05a29f830008ab0e9a36d8384ed7cf4ea3fb18b Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 28 Oct 2013 11:03:39 +1000
Subject: Rename GDISP driver files to prevent problems when compiling for
 multiple controllers on platforms that put all generated object files into a
 single directory.

---
 drivers/gdisp/ED060SC4/gdisp_lld.c                 |  625 -----------
 drivers/gdisp/ED060SC4/gdisp_lld.mk                |    2 +-
 drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c        |  625 +++++++++++
 drivers/gdisp/HX8347D/gdisp_lld.c                  |  236 ----
 drivers/gdisp/HX8347D/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c          |  236 ++++
 drivers/gdisp/ILI9320/gdisp_lld.c                  |  377 -------
 drivers/gdisp/ILI9320/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c          |  377 +++++++
 drivers/gdisp/ILI9325/gdisp_lld.c                  |  365 ------
 drivers/gdisp/ILI9325/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c          |  365 ++++++
 drivers/gdisp/ILI9341/gdisp_lld.c                  |  373 -------
 drivers/gdisp/ILI9341/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c          |  373 +++++++
 drivers/gdisp/ILI9481/gdisp_lld.c                  |  325 ------
 drivers/gdisp/ILI9481/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c          |  325 ++++++
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c            |  259 -----
 drivers/gdisp/Nokia6610GE12/gdisp_lld.mk           |    2 +-
 .../gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c  |  259 +++++
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             |  559 ----------
 drivers/gdisp/Nokia6610GE8/gdisp_lld.mk            |    2 +-
 .../gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c    |  559 ++++++++++
 drivers/gdisp/RA8875/gdisp_lld.c                   |  283 -----
 drivers/gdisp/RA8875/gdisp_lld.mk                  |    2 +-
 drivers/gdisp/RA8875/gdisp_lld_RA8875.c            |  283 +++++
 drivers/gdisp/S6D1121/gdisp_lld.c                  |  335 ------
 drivers/gdisp/S6D1121/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c          |  335 ++++++
 drivers/gdisp/SSD1289/gdisp_lld.c                  |  351 ------
 drivers/gdisp/SSD1289/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c          |  351 ++++++
 drivers/gdisp/SSD1306/gdisp_lld.c                  |  280 -----
 drivers/gdisp/SSD1306/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c          |  280 +++++
 drivers/gdisp/SSD1963/gdisp_lld.c                  |  285 -----
 drivers/gdisp/SSD1963/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c          |  285 +++++
 drivers/gdisp/SSD2119/gdisp_lld.c                  |  401 -------
 drivers/gdisp/SSD2119/gdisp_lld.mk                 |    2 +-
 drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c          |  401 +++++++
 drivers/gdisp/ST7565/gdisp_lld.c                   |  262 -----
 drivers/gdisp/ST7565/gdisp_lld.mk                  |    2 +-
 drivers/gdisp/ST7565/gdisp_lld_ST7565.c            |  262 +++++
 drivers/gdisp/TestStub/gdisp_lld.c                 |   61 -
 drivers/gdisp/TestStub/gdisp_lld.mk                |    2 +-
 drivers/gdisp/TestStub/gdisp_lld_TestStub.c        |   61 +
 drivers/multiple/Win32/gdisp_lld.c                 | 1163 --------------------
 drivers/multiple/Win32/gdisp_lld.mk                |    2 +-
 drivers/multiple/Win32/gdisp_lld_Win32.c           | 1163 ++++++++++++++++++++
 drivers/multiple/X/gdisp_lld.c                     |  340 ------
 drivers/multiple/X/gdisp_lld.mk                    |    2 +-
 drivers/multiple/X/gdisp_lld_X.c                   |  340 ++++++
 54 files changed, 6898 insertions(+), 6898 deletions(-)
 delete mode 100644 drivers/gdisp/ED060SC4/gdisp_lld.c
 create mode 100644 drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
 delete mode 100644 drivers/gdisp/HX8347D/gdisp_lld.c
 create mode 100644 drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
 delete mode 100644 drivers/gdisp/ILI9320/gdisp_lld.c
 create mode 100644 drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
 delete mode 100644 drivers/gdisp/ILI9325/gdisp_lld.c
 create mode 100644 drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
 delete mode 100644 drivers/gdisp/ILI9341/gdisp_lld.c
 create mode 100644 drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
 delete mode 100644 drivers/gdisp/ILI9481/gdisp_lld.c
 create mode 100644 drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
 delete mode 100644 drivers/gdisp/Nokia6610GE12/gdisp_lld.c
 create mode 100644 drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
 delete mode 100644 drivers/gdisp/Nokia6610GE8/gdisp_lld.c
 create mode 100644 drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
 delete mode 100644 drivers/gdisp/RA8875/gdisp_lld.c
 create mode 100644 drivers/gdisp/RA8875/gdisp_lld_RA8875.c
 delete mode 100644 drivers/gdisp/S6D1121/gdisp_lld.c
 create mode 100644 drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
 delete mode 100644 drivers/gdisp/SSD1289/gdisp_lld.c
 create mode 100644 drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
 delete mode 100644 drivers/gdisp/SSD1306/gdisp_lld.c
 create mode 100644 drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
 delete mode 100644 drivers/gdisp/SSD1963/gdisp_lld.c
 create mode 100644 drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
 delete mode 100644 drivers/gdisp/SSD2119/gdisp_lld.c
 create mode 100644 drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
 delete mode 100644 drivers/gdisp/ST7565/gdisp_lld.c
 create mode 100644 drivers/gdisp/ST7565/gdisp_lld_ST7565.c
 delete mode 100644 drivers/gdisp/TestStub/gdisp_lld.c
 create mode 100644 drivers/gdisp/TestStub/gdisp_lld_TestStub.c
 delete mode 100644 drivers/multiple/Win32/gdisp_lld.c
 create mode 100644 drivers/multiple/Win32/gdisp_lld_Win32.c
 delete mode 100644 drivers/multiple/X/gdisp_lld.c
 create mode 100644 drivers/multiple/X/gdisp_lld_X.c

(limited to 'drivers')

diff --git a/drivers/gdisp/ED060SC4/gdisp_lld.c b/drivers/gdisp/ED060SC4/gdisp_lld.c
deleted file mode 100644
index 14e7f88a..00000000
--- a/drivers/gdisp/ED060SC4/gdisp_lld.c
+++ /dev/null
@@ -1,625 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ED060SC4/gdisp_lld.c
- * @brief   GDISP Graphics Driver for the E-ink panel ED060SC4.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_ED060SC4
-#include "../drivers/gdisp/ED060SC4/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_ED060SC4.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		600
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		800
-#endif
-
-/* Number of pixels per byte */
-#ifndef EINK_PPB
-	#define EINK_PPB 4
-#endif
-
-/* Delay for generating clock pulses.
- * Unit is approximate clock cycles of the CPU (0 to 15).
- * This should be atleast 50 ns.
- */
-#ifndef EINK_CLOCKDELAY
-	#define EINK_CLOCKDELAY 0
-#endif
-
-/* Width of one framebuffer block.
- * Must be divisible by EINK_PPB and evenly divide GDISP_SCREEN_WIDTH. */
-#ifndef EINK_BLOCKWIDTH
-	#define EINK_BLOCKWIDTH 20
-#endif
-
-/* Height of one framebuffer block.
- * Must evenly divide GDISP_SCREEN_WIDTH. */
-#ifndef EINK_BLOCKHEIGHT
-	#define EINK_BLOCKHEIGHT 20
-#endif
-
-/* Number of block buffers to use for framebuffer emulation. */
-#ifndef EINK_NUMBUFFERS
-	#define EINK_NUMBUFFERS 40
-#endif
-
-/* Do a "blinking" clear, i.e. clear to opposite polarity first.
- * This reduces the image persistence. */
-#ifndef EINK_BLINKCLEAR
-	#define EINK_BLINKCLEAR TRUE
-#endif
-
-/* Number of passes to use when clearing the display */
-#ifndef EINK_CLEARCOUNT
-	#define EINK_CLEARCOUNT 10
-#endif
-
-/* Number of passes to use when writing to the display */
-#ifndef EINK_WRITECOUNT
-	#define EINK_WRITECOUNT 4
-#endif
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#define PRIV(g)		((drvPriv *)g->priv)
-
-/** Delay between signal changes, to give time for IO pins to change state. */
-static inline void clockdelay(void)
-{
-	#if EINK_CLOCKDELAY & 1
-	asm("nop");
-	#endif
-	#if EINK_CLOCKDELAY & 2
-	asm("nop");
-	asm("nop");
-	#endif
-	#if EINK_CLOCKDELAY & 4
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	#endif
-	#if EINK_CLOCKDELAY & 8
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	asm("nop");
-	#endif
-}
-
-/** Fast vertical clock pulse for gate driver, used during initializations */
-static void vclock_quick(GDisplay *g)
-{
-	setpin_ckv(g, TRUE);
-	eink_delay(1);
-	setpin_ckv(g, FALSE);
-	eink_delay(4);
-}
-
-/** Horizontal clock pulse for clocking data into source driver */
-static void hclock(GDisplay *g)
-{
-	clockdelay();
-	setpin_cl(g, TRUE);
-	clockdelay();
-	setpin_cl(g, FALSE);
-}
-
-/** Start a new vertical gate driver scan from top.
- * Note: Does not clear any previous bits in the shift register,
- *       so you should always scan through the whole display before
- *       starting a new scan.
- */
-static void vscan_start(GDisplay *g)
-{
-	setpin_gmode(g, TRUE);
-	vclock_quick(g);
-	setpin_spv(g, FALSE);
-	vclock_quick(g);
-	setpin_spv(g, TRUE);
-	vclock_quick(g);
-}
-
-/** Waveform for strobing a row of data onto the display.
- * Attempts to minimize the leaking of color to other rows by having
- * a long idle period after a medium-length strobe period.
- */
-static void vscan_write(GDisplay *g)
-{
-	setpin_ckv(g, TRUE);
-	setpin_oe(g, TRUE);
-	eink_delay(5);
-	setpin_oe(g, FALSE);
-	setpin_ckv(g, FALSE);
-	eink_delay(200);
-}
-
-/** Waveform used when clearing the display. Strobes a row of data to the
- * screen, but does not mind some of it leaking to other rows.
- */
-static void vscan_bulkwrite(GDisplay *g)
-{
-	setpin_ckv(g, TRUE);
-	eink_delay(20);
-	setpin_ckv(g, FALSE);
-	eink_delay(200);
-}
-
-/** Waveform for skipping a vertical row without writing anything.
- * Attempts to minimize the amount of change in any row.
- */
-static void vscan_skip(GDisplay *g)
-{
-	setpin_ckv(g, TRUE);
-	eink_delay(1);
-	setpin_ckv(g, FALSE);
-	eink_delay(100);
-}
-
-/** Stop the vertical scan. The significance of this escapes me, but it seems
- * necessary or the next vertical scan may be corrupted.
- */
-static void vscan_stop(GDisplay *g)
-{
-	setpin_gmode(g, FALSE);
-	vclock_quick(g);
-	vclock_quick(g);
-	vclock_quick(g);
-	vclock_quick(g);
-	vclock_quick(g);
-}
-
-/** Start updating the source driver data (from left to right). */
-static void hscan_start(GDisplay *g)
-{
-	/* Disable latching and output enable while we are modifying the row. */
-	setpin_le(g, FALSE);
-	setpin_oe(g, FALSE);
-	
-	/* The start pulse should remain low for the duration of the row. */
-	setpin_sph(g, FALSE);
-}
-
-/** Write data to the horizontal row. */
-static void hscan_write(GDisplay *g, const uint8_t *data, int count)
-{
-	while (count--)
-	{
-		/* Set the next byte on the data pins */
-		setpins_data(g, *data++);
-		
-		/* Give a clock pulse to the shift register */
-		hclock(g);
-	}
-}
-
-/** Finish and transfer the row to the source drivers.
- * Does not set the output enable, so the drivers are not yet active. */
-static void hscan_stop(GDisplay *g)
-{
-	/* End the scan */
-	setpin_sph(g, TRUE);
-	hclock(g);
-	
-	/* Latch the new data */
-	setpin_le(g, TRUE);
-	clockdelay();
-	setpin_le(g, FALSE);
-}
-
-/** Turn on the power to the E-Ink panel, observing proper power sequencing. */
-static void power_on(GDisplay *g)
-{
-	unsigned i;
-	
-	/* First the digital power supply and signal levels. */
-	setpower_vdd(g, TRUE);
-	setpin_le(g, FALSE);
-	setpin_oe(g, FALSE);
-	setpin_cl(g, FALSE);
-	setpin_sph(g, TRUE);
-	setpins_data(g, 0);
-	setpin_ckv(g, FALSE);
-	setpin_gmode(g, FALSE);
-	setpin_spv(g, TRUE);
-	
-	/* Min. 100 microsecond delay after digital supply */
-	gfxSleepMicroseconds(100);
-	
-	/* Then negative voltages and min. 1000 microsecond delay. */
-	setpower_vneg(g, TRUE);
-	gfxSleepMicroseconds(1000);
-	
-	/* Finally the positive voltages. */
-	setpower_vpos(g, TRUE);
-	
-	/* Clear the vscan shift register */
-	vscan_start(g);
-	for (i = 0; i < GDISP_SCREEN_HEIGHT; i++)
-		vclock_quick(g);
-	vscan_stop(g);
-}
-
-/** Turn off the power, observing proper power sequencing. */
-static void power_off(GDisplay *g)
-{
-	/* First the high voltages */
-	setpower_vpos(g, FALSE);
-	setpower_vneg(g, FALSE);
-	
-	/* Wait for any capacitors to drain */
-	gfxSleepMilliseconds(100);
-	
-	/* Then put all signals and digital supply to ground. */
-	setpin_le(g, FALSE);
-	setpin_oe(g, FALSE);
-	setpin_cl(g, FALSE);
-	setpin_sph(g, FALSE);
-	setpins_data(g, 0);
-	setpin_ckv(g, FALSE);
-	setpin_gmode(g, FALSE);
-	setpin_spv(g, FALSE);
-	setpower_vdd(g, FALSE);
-}
-
-/* ====================================
- *      Framebuffer emulation layer
- * ==================================== */
-
-#if EINK_PPB == 4
-	#define PIXELMASK 3
-	#define PIXEL_WHITE 2
-	#define PIXEL_BLACK 1
-	#define BYTE_WHITE 0xAA
-	#define BYTE_BLACK 0x55
-#else
-	#error Unsupported EINK_PPB value.
-#endif
-
-#if GDISP_SCREEN_HEIGHT % EINK_BLOCKHEIGHT != 0
-	#error GDISP_SCREEN_HEIGHT must be evenly divisible by EINK_BLOCKHEIGHT
-#endif
-
-#if GDISP_SCREEN_WIDTH % EINK_BLOCKWIDTH != 0
-	#error GDISP_SCREEN_WIDTH must be evenly divisible by EINK_BLOCKWIDTH
-#endif
-
-#if EINK_BLOCKWIDTH % EINK_PPB != 0
-	#error EINK_BLOCKWIDTH must be evenly divisible by EINK_PPB
-#endif
-
-#if EINK_NUMBUFFERS > 254
-	#error EINK_NUMBUFFERS must be at most 254.
-#endif
-
-#define BLOCKS_Y		(GDISP_SCREEN_HEIGHT / EINK_BLOCKHEIGHT)
-#define BLOCKS_X		(GDISP_SCREEN_WIDTH / EINK_BLOCKWIDTH)
-#define WIDTH_BYTES		(EINK_BLOCKWIDTH / EINK_PPB)
-
-/* Buffers that store the data for a small area of the display. */
-typedef struct {
-	uint8_t data[EINK_BLOCKHEIGHT][WIDTH_BYTES];
-} block_t;
-
-typedef struct drvPriv {
-	uint8_t g_next_block; /* Index of the next free block buffer. */
-	block_t g_blocks[EINK_NUMBUFFERS];
-
-	/* Map that stores the buffers associated to each area of the display.
-	 * Value of 0 means that the block is not allocated.
-	 * Other values are the index in g_blocks + 1.
-	 */
-	uint8_t g_blockmap[BLOCKS_Y][BLOCKS_X];
-} drvPriv;
-
-/** Check if the row contains any allocated blocks. */
-static bool_t blocks_on_row(GDisplay *g, unsigned by)
-{
-	unsigned bx;
-	for (bx = 0; bx < BLOCKS_X; bx++)
-	{
-		if (PRIV(g)->g_blockmap[by][bx] != 0)
-		{
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-/** Write out a block row. */
-static void write_block_row(GDisplay *g, unsigned by)
-{
-	unsigned bx, dy, dx;
-	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
-	{
-		hscan_start(g);
-		for (bx = 0; bx < BLOCKS_X; bx++)
-		{
-			if (PRIV(g)->g_blockmap[by][bx] == 0)
-			{
-				for (dx = 0; dx < WIDTH_BYTES; dx++)
-				{
-					const uint8_t dummy = 0;
-					hscan_write(g, &dummy, 1);
-				}
-			}
-			else
-			{
-				block_t *block = &PRIV(g)->g_blocks[PRIV(g)->g_blockmap[by][bx] - 1];
-				hscan_write(g, &block->data[dy][0], WIDTH_BYTES);
-			}
-		}
-		hscan_stop(g);
-		
-		vscan_write(g);
-	}
-}
-
-/** Clear the block map, i.e. deallocate all blocks */
-static void clear_block_map(GDisplay *g)
-{
-	unsigned bx, by;
-	for (by = 0; by < BLOCKS_Y; by++)
-	{
-		for (bx = 0; bx < BLOCKS_X; bx++)
-		{
-			PRIV(g)->g_blockmap[by][bx] = 0;
-		}
-	}
-	
-	PRIV(g)->g_next_block = 0;
-}
-
-/** Initialize a newly allocated block. */
-static void zero_block(block_t *block)
-{
-	unsigned dx, dy;
-	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
-	{
-		for (dx = 0; dx < WIDTH_BYTES; dx++)
-		{
-			block->data[dy][dx] = 0;
-		}
-	}
-}
-
-/** Allocate a buffer
- * Automatically flushes if all buffers are full. */
-static block_t *alloc_buffer(GDisplay *g, unsigned bx, unsigned by)
-{
-	block_t *result;
-	drvPriv *priv;
-
-	priv = PRIV(g);
-	if (priv->g_blockmap[by][bx] == 0)
-	{
-		if (priv->g_next_block >= EINK_NUMBUFFERS)
-			gdisp_lld_flush(g);
-		
-		result = &priv->g_blocks[priv->g_next_block];
-		priv->g_blockmap[by][bx] = priv->g_next_block + 1;
-		priv->g_next_block++;
-		zero_block(result);
-		return result;
-	}
-	else
-	{
-		result = &priv->g_blocks[priv->g_blockmap[by][bx] - 1];
-		return result;
-	}
-}
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	g->priv = gfxAlloc(sizeof(drvPriv));
-
-	init_board(g);
-	
-	/* Make sure that all the pins are in "off" state.
-	 * Having any pin high could cause voltage leaking to the
-	 * display, which in turn causes the image to leak slowly away.
-	 */
-	power_off(g);
-	
-	clear_block_map(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 = 100;
-	g->g.Contrast = 100;
-	return TRUE;
-}
-
-#if GDISP_HARDWARE_FLUSH
-	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
-		unsigned by, dy, i;
-
-		for (i = 0; i < EINK_WRITECOUNT; i++) {
-			vscan_start(g);
-
-			for (by = 0; by < BLOCKS_Y; by++) {
-				if (!blocks_on_row(g, by)) {
-					/* Skip the whole row of blocks. */
-					for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
-						vscan_skip(g);
-				} else {
-					/* Write out the blocks. */
-					write_block_row(g, by);
-				}
-			}
-
-			vscan_stop(g);
-		}
-
-		clear_block_map(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_DRAWPIXEL
-	void gdisp_lld_draw_pixel(GDisplay *g) {
-		block_t *block;
-		uint8_t byte;
-		unsigned bx, by, dx, dy;
-		uint8_t bitpos;
-
-		switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			bx = g->p.x / EINK_BLOCKWIDTH;
-			dx = g->p.x % EINK_BLOCKWIDTH;
-			by = g->p.y / EINK_BLOCKHEIGHT;
-			dy = g->p.y % EINK_BLOCKHEIGHT;
-			break;
-		case GDISP_ROTATE_90:
-			bx = g->p.y / EINK_BLOCKWIDTH;
-			dx = g->p.y % EINK_BLOCKWIDTH;
-			by = (GDISP_SCREEN_HEIGHT-1 - g->p.x) / EINK_BLOCKHEIGHT;
-			dy = (GDISP_SCREEN_HEIGHT-1 - g->p.x) % EINK_BLOCKHEIGHT;
-			break;
-		case GDISP_ROTATE_180:
-			bx = (GDISP_SCREEN_WIDTH-1 - g->p.x) / EINK_BLOCKWIDTH;
-			dx = (GDISP_SCREEN_WIDTH-1 - g->p.x) % EINK_BLOCKWIDTH;
-			by = (GDISP_SCREEN_HEIGHT-1 - g->p.y) / EINK_BLOCKHEIGHT;
-			dy = (GDISP_SCREEN_HEIGHT-1 - g->p.y) % EINK_BLOCKHEIGHT;
-			break;
-		case GDISP_ROTATE_270:
-			bx = (GDISP_SCREEN_WIDTH-1 - g->p.y) / EINK_BLOCKWIDTH;
-			dx = (GDISP_SCREEN_WIDTH-1 - g->p.y) % EINK_BLOCKWIDTH;
-			by = g->p.x / EINK_BLOCKHEIGHT;
-			dy = g->p.x % EINK_BLOCKHEIGHT;
-			break;
-		}
-
-		block = alloc_buffer(g, bx, by);
-
-		bitpos = (6 - 2 * (dx % EINK_PPB));
-		byte = block->data[dy][dx / EINK_PPB];
-		byte &= ~(PIXELMASK << bitpos);
-		if (g->p.color != Black)
-			byte |= PIXEL_WHITE << bitpos;
-		else
-			byte |= PIXEL_BLACK << bitpos;
-		block->data[dy][dx / EINK_PPB] = byte;
-	}
-#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:
-				gdisp_lld_flush(g);
-				power_off(g);
-				break;
-			case powerOn:
-				power_on(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:
-			case GDISP_ROTATE_180:
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-			case GDISP_ROTATE_270:
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			default:
-				return;
-			}
-			g->g.Orientation = (orientation_t)g->p.ptr;
-			return;
-			
-		default:
-			return;
-		}
-	}
-#endif
-
-/* ===============================
- *       Accelerated routines
- * =============================== */
-
-#if GDISP_HARDWARE_CLEARS
-	static void subclear(GDisplay *g, color_t color) {
-		unsigned x, y;
-		uint8_t byte;
-
-		hscan_start(g);
-		byte = color ? BYTE_WHITE : BYTE_BLACK;
-		for (x = 0; x < GDISP_SCREEN_WIDTH; x++)
-		{
-			hscan_write(g, &byte, 1);
-		}
-		hscan_stop(g);
-
-		setpin_oe(g, TRUE);
-		vscan_start(g);
-		for (y = 0; y < GDISP_SCREEN_HEIGHT; y++)
-			vscan_bulkwrite(g);
-		vscan_stop(g);
-		setpin_oe(g, FALSE);
-	}
-	
-	void gdisp_lld_clear(GDisplay *g) {
-		unsigned i;
-
-		clear_block_map(g);
-
-		if (EINK_BLINKCLEAR) {
-			subclear(g, !g->p.color);
-			gfxSleepMilliseconds(50);
-		}
-
-		for (i = 0; i < EINK_CLEARCOUNT; i++) {
-			subclear(g, g->p.color);
-			gfxSleepMilliseconds(10);
-		}
-	}
-#endif
-
-#endif	// GFX_USE_GDISP
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld.mk b/drivers/gdisp/ED060SC4/gdisp_lld.mk
index fc62da03..0c78e1a7 100644
--- a/drivers/gdisp/ED060SC4/gdisp_lld.mk
+++ b/drivers/gdisp/ED060SC4/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/ED060SC4
-GFXSRC += $(GFXLIB)/drivers/gdisp/ED060SC4/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c b/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
new file mode 100644
index 00000000..14e7f88a
--- /dev/null
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
@@ -0,0 +1,625 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ED060SC4/gdisp_lld.c
+ * @brief   GDISP Graphics Driver for the E-ink panel ED060SC4.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_ED060SC4
+#include "../drivers/gdisp/ED060SC4/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ED060SC4.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		600
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		800
+#endif
+
+/* Number of pixels per byte */
+#ifndef EINK_PPB
+	#define EINK_PPB 4
+#endif
+
+/* Delay for generating clock pulses.
+ * Unit is approximate clock cycles of the CPU (0 to 15).
+ * This should be atleast 50 ns.
+ */
+#ifndef EINK_CLOCKDELAY
+	#define EINK_CLOCKDELAY 0
+#endif
+
+/* Width of one framebuffer block.
+ * Must be divisible by EINK_PPB and evenly divide GDISP_SCREEN_WIDTH. */
+#ifndef EINK_BLOCKWIDTH
+	#define EINK_BLOCKWIDTH 20
+#endif
+
+/* Height of one framebuffer block.
+ * Must evenly divide GDISP_SCREEN_WIDTH. */
+#ifndef EINK_BLOCKHEIGHT
+	#define EINK_BLOCKHEIGHT 20
+#endif
+
+/* Number of block buffers to use for framebuffer emulation. */
+#ifndef EINK_NUMBUFFERS
+	#define EINK_NUMBUFFERS 40
+#endif
+
+/* Do a "blinking" clear, i.e. clear to opposite polarity first.
+ * This reduces the image persistence. */
+#ifndef EINK_BLINKCLEAR
+	#define EINK_BLINKCLEAR TRUE
+#endif
+
+/* Number of passes to use when clearing the display */
+#ifndef EINK_CLEARCOUNT
+	#define EINK_CLEARCOUNT 10
+#endif
+
+/* Number of passes to use when writing to the display */
+#ifndef EINK_WRITECOUNT
+	#define EINK_WRITECOUNT 4
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#define PRIV(g)		((drvPriv *)g->priv)
+
+/** Delay between signal changes, to give time for IO pins to change state. */
+static inline void clockdelay(void)
+{
+	#if EINK_CLOCKDELAY & 1
+	asm("nop");
+	#endif
+	#if EINK_CLOCKDELAY & 2
+	asm("nop");
+	asm("nop");
+	#endif
+	#if EINK_CLOCKDELAY & 4
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	#endif
+	#if EINK_CLOCKDELAY & 8
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	asm("nop");
+	#endif
+}
+
+/** Fast vertical clock pulse for gate driver, used during initializations */
+static void vclock_quick(GDisplay *g)
+{
+	setpin_ckv(g, TRUE);
+	eink_delay(1);
+	setpin_ckv(g, FALSE);
+	eink_delay(4);
+}
+
+/** Horizontal clock pulse for clocking data into source driver */
+static void hclock(GDisplay *g)
+{
+	clockdelay();
+	setpin_cl(g, TRUE);
+	clockdelay();
+	setpin_cl(g, FALSE);
+}
+
+/** Start a new vertical gate driver scan from top.
+ * Note: Does not clear any previous bits in the shift register,
+ *       so you should always scan through the whole display before
+ *       starting a new scan.
+ */
+static void vscan_start(GDisplay *g)
+{
+	setpin_gmode(g, TRUE);
+	vclock_quick(g);
+	setpin_spv(g, FALSE);
+	vclock_quick(g);
+	setpin_spv(g, TRUE);
+	vclock_quick(g);
+}
+
+/** Waveform for strobing a row of data onto the display.
+ * Attempts to minimize the leaking of color to other rows by having
+ * a long idle period after a medium-length strobe period.
+ */
+static void vscan_write(GDisplay *g)
+{
+	setpin_ckv(g, TRUE);
+	setpin_oe(g, TRUE);
+	eink_delay(5);
+	setpin_oe(g, FALSE);
+	setpin_ckv(g, FALSE);
+	eink_delay(200);
+}
+
+/** Waveform used when clearing the display. Strobes a row of data to the
+ * screen, but does not mind some of it leaking to other rows.
+ */
+static void vscan_bulkwrite(GDisplay *g)
+{
+	setpin_ckv(g, TRUE);
+	eink_delay(20);
+	setpin_ckv(g, FALSE);
+	eink_delay(200);
+}
+
+/** Waveform for skipping a vertical row without writing anything.
+ * Attempts to minimize the amount of change in any row.
+ */
+static void vscan_skip(GDisplay *g)
+{
+	setpin_ckv(g, TRUE);
+	eink_delay(1);
+	setpin_ckv(g, FALSE);
+	eink_delay(100);
+}
+
+/** Stop the vertical scan. The significance of this escapes me, but it seems
+ * necessary or the next vertical scan may be corrupted.
+ */
+static void vscan_stop(GDisplay *g)
+{
+	setpin_gmode(g, FALSE);
+	vclock_quick(g);
+	vclock_quick(g);
+	vclock_quick(g);
+	vclock_quick(g);
+	vclock_quick(g);
+}
+
+/** Start updating the source driver data (from left to right). */
+static void hscan_start(GDisplay *g)
+{
+	/* Disable latching and output enable while we are modifying the row. */
+	setpin_le(g, FALSE);
+	setpin_oe(g, FALSE);
+	
+	/* The start pulse should remain low for the duration of the row. */
+	setpin_sph(g, FALSE);
+}
+
+/** Write data to the horizontal row. */
+static void hscan_write(GDisplay *g, const uint8_t *data, int count)
+{
+	while (count--)
+	{
+		/* Set the next byte on the data pins */
+		setpins_data(g, *data++);
+		
+		/* Give a clock pulse to the shift register */
+		hclock(g);
+	}
+}
+
+/** Finish and transfer the row to the source drivers.
+ * Does not set the output enable, so the drivers are not yet active. */
+static void hscan_stop(GDisplay *g)
+{
+	/* End the scan */
+	setpin_sph(g, TRUE);
+	hclock(g);
+	
+	/* Latch the new data */
+	setpin_le(g, TRUE);
+	clockdelay();
+	setpin_le(g, FALSE);
+}
+
+/** Turn on the power to the E-Ink panel, observing proper power sequencing. */
+static void power_on(GDisplay *g)
+{
+	unsigned i;
+	
+	/* First the digital power supply and signal levels. */
+	setpower_vdd(g, TRUE);
+	setpin_le(g, FALSE);
+	setpin_oe(g, FALSE);
+	setpin_cl(g, FALSE);
+	setpin_sph(g, TRUE);
+	setpins_data(g, 0);
+	setpin_ckv(g, FALSE);
+	setpin_gmode(g, FALSE);
+	setpin_spv(g, TRUE);
+	
+	/* Min. 100 microsecond delay after digital supply */
+	gfxSleepMicroseconds(100);
+	
+	/* Then negative voltages and min. 1000 microsecond delay. */
+	setpower_vneg(g, TRUE);
+	gfxSleepMicroseconds(1000);
+	
+	/* Finally the positive voltages. */
+	setpower_vpos(g, TRUE);
+	
+	/* Clear the vscan shift register */
+	vscan_start(g);
+	for (i = 0; i < GDISP_SCREEN_HEIGHT; i++)
+		vclock_quick(g);
+	vscan_stop(g);
+}
+
+/** Turn off the power, observing proper power sequencing. */
+static void power_off(GDisplay *g)
+{
+	/* First the high voltages */
+	setpower_vpos(g, FALSE);
+	setpower_vneg(g, FALSE);
+	
+	/* Wait for any capacitors to drain */
+	gfxSleepMilliseconds(100);
+	
+	/* Then put all signals and digital supply to ground. */
+	setpin_le(g, FALSE);
+	setpin_oe(g, FALSE);
+	setpin_cl(g, FALSE);
+	setpin_sph(g, FALSE);
+	setpins_data(g, 0);
+	setpin_ckv(g, FALSE);
+	setpin_gmode(g, FALSE);
+	setpin_spv(g, FALSE);
+	setpower_vdd(g, FALSE);
+}
+
+/* ====================================
+ *      Framebuffer emulation layer
+ * ==================================== */
+
+#if EINK_PPB == 4
+	#define PIXELMASK 3
+	#define PIXEL_WHITE 2
+	#define PIXEL_BLACK 1
+	#define BYTE_WHITE 0xAA
+	#define BYTE_BLACK 0x55
+#else
+	#error Unsupported EINK_PPB value.
+#endif
+
+#if GDISP_SCREEN_HEIGHT % EINK_BLOCKHEIGHT != 0
+	#error GDISP_SCREEN_HEIGHT must be evenly divisible by EINK_BLOCKHEIGHT
+#endif
+
+#if GDISP_SCREEN_WIDTH % EINK_BLOCKWIDTH != 0
+	#error GDISP_SCREEN_WIDTH must be evenly divisible by EINK_BLOCKWIDTH
+#endif
+
+#if EINK_BLOCKWIDTH % EINK_PPB != 0
+	#error EINK_BLOCKWIDTH must be evenly divisible by EINK_PPB
+#endif
+
+#if EINK_NUMBUFFERS > 254
+	#error EINK_NUMBUFFERS must be at most 254.
+#endif
+
+#define BLOCKS_Y		(GDISP_SCREEN_HEIGHT / EINK_BLOCKHEIGHT)
+#define BLOCKS_X		(GDISP_SCREEN_WIDTH / EINK_BLOCKWIDTH)
+#define WIDTH_BYTES		(EINK_BLOCKWIDTH / EINK_PPB)
+
+/* Buffers that store the data for a small area of the display. */
+typedef struct {
+	uint8_t data[EINK_BLOCKHEIGHT][WIDTH_BYTES];
+} block_t;
+
+typedef struct drvPriv {
+	uint8_t g_next_block; /* Index of the next free block buffer. */
+	block_t g_blocks[EINK_NUMBUFFERS];
+
+	/* Map that stores the buffers associated to each area of the display.
+	 * Value of 0 means that the block is not allocated.
+	 * Other values are the index in g_blocks + 1.
+	 */
+	uint8_t g_blockmap[BLOCKS_Y][BLOCKS_X];
+} drvPriv;
+
+/** Check if the row contains any allocated blocks. */
+static bool_t blocks_on_row(GDisplay *g, unsigned by)
+{
+	unsigned bx;
+	for (bx = 0; bx < BLOCKS_X; bx++)
+	{
+		if (PRIV(g)->g_blockmap[by][bx] != 0)
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+/** Write out a block row. */
+static void write_block_row(GDisplay *g, unsigned by)
+{
+	unsigned bx, dy, dx;
+	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+	{
+		hscan_start(g);
+		for (bx = 0; bx < BLOCKS_X; bx++)
+		{
+			if (PRIV(g)->g_blockmap[by][bx] == 0)
+			{
+				for (dx = 0; dx < WIDTH_BYTES; dx++)
+				{
+					const uint8_t dummy = 0;
+					hscan_write(g, &dummy, 1);
+				}
+			}
+			else
+			{
+				block_t *block = &PRIV(g)->g_blocks[PRIV(g)->g_blockmap[by][bx] - 1];
+				hscan_write(g, &block->data[dy][0], WIDTH_BYTES);
+			}
+		}
+		hscan_stop(g);
+		
+		vscan_write(g);
+	}
+}
+
+/** Clear the block map, i.e. deallocate all blocks */
+static void clear_block_map(GDisplay *g)
+{
+	unsigned bx, by;
+	for (by = 0; by < BLOCKS_Y; by++)
+	{
+		for (bx = 0; bx < BLOCKS_X; bx++)
+		{
+			PRIV(g)->g_blockmap[by][bx] = 0;
+		}
+	}
+	
+	PRIV(g)->g_next_block = 0;
+}
+
+/** Initialize a newly allocated block. */
+static void zero_block(block_t *block)
+{
+	unsigned dx, dy;
+	for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+	{
+		for (dx = 0; dx < WIDTH_BYTES; dx++)
+		{
+			block->data[dy][dx] = 0;
+		}
+	}
+}
+
+/** Allocate a buffer
+ * Automatically flushes if all buffers are full. */
+static block_t *alloc_buffer(GDisplay *g, unsigned bx, unsigned by)
+{
+	block_t *result;
+	drvPriv *priv;
+
+	priv = PRIV(g);
+	if (priv->g_blockmap[by][bx] == 0)
+	{
+		if (priv->g_next_block >= EINK_NUMBUFFERS)
+			gdisp_lld_flush(g);
+		
+		result = &priv->g_blocks[priv->g_next_block];
+		priv->g_blockmap[by][bx] = priv->g_next_block + 1;
+		priv->g_next_block++;
+		zero_block(result);
+		return result;
+	}
+	else
+	{
+		result = &priv->g_blocks[priv->g_blockmap[by][bx] - 1];
+		return result;
+	}
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	g->priv = gfxAlloc(sizeof(drvPriv));
+
+	init_board(g);
+	
+	/* Make sure that all the pins are in "off" state.
+	 * Having any pin high could cause voltage leaking to the
+	 * display, which in turn causes the image to leak slowly away.
+	 */
+	power_off(g);
+	
+	clear_block_map(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 = 100;
+	g->g.Contrast = 100;
+	return TRUE;
+}
+
+#if GDISP_HARDWARE_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		unsigned by, dy, i;
+
+		for (i = 0; i < EINK_WRITECOUNT; i++) {
+			vscan_start(g);
+
+			for (by = 0; by < BLOCKS_Y; by++) {
+				if (!blocks_on_row(g, by)) {
+					/* Skip the whole row of blocks. */
+					for (dy = 0; dy < EINK_BLOCKHEIGHT; dy++)
+						vscan_skip(g);
+				} else {
+					/* Write out the blocks. */
+					write_block_row(g, by);
+				}
+			}
+
+			vscan_stop(g);
+		}
+
+		clear_block_map(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_DRAWPIXEL
+	void gdisp_lld_draw_pixel(GDisplay *g) {
+		block_t *block;
+		uint8_t byte;
+		unsigned bx, by, dx, dy;
+		uint8_t bitpos;
+
+		switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			bx = g->p.x / EINK_BLOCKWIDTH;
+			dx = g->p.x % EINK_BLOCKWIDTH;
+			by = g->p.y / EINK_BLOCKHEIGHT;
+			dy = g->p.y % EINK_BLOCKHEIGHT;
+			break;
+		case GDISP_ROTATE_90:
+			bx = g->p.y / EINK_BLOCKWIDTH;
+			dx = g->p.y % EINK_BLOCKWIDTH;
+			by = (GDISP_SCREEN_HEIGHT-1 - g->p.x) / EINK_BLOCKHEIGHT;
+			dy = (GDISP_SCREEN_HEIGHT-1 - g->p.x) % EINK_BLOCKHEIGHT;
+			break;
+		case GDISP_ROTATE_180:
+			bx = (GDISP_SCREEN_WIDTH-1 - g->p.x) / EINK_BLOCKWIDTH;
+			dx = (GDISP_SCREEN_WIDTH-1 - g->p.x) % EINK_BLOCKWIDTH;
+			by = (GDISP_SCREEN_HEIGHT-1 - g->p.y) / EINK_BLOCKHEIGHT;
+			dy = (GDISP_SCREEN_HEIGHT-1 - g->p.y) % EINK_BLOCKHEIGHT;
+			break;
+		case GDISP_ROTATE_270:
+			bx = (GDISP_SCREEN_WIDTH-1 - g->p.y) / EINK_BLOCKWIDTH;
+			dx = (GDISP_SCREEN_WIDTH-1 - g->p.y) % EINK_BLOCKWIDTH;
+			by = g->p.x / EINK_BLOCKHEIGHT;
+			dy = g->p.x % EINK_BLOCKHEIGHT;
+			break;
+		}
+
+		block = alloc_buffer(g, bx, by);
+
+		bitpos = (6 - 2 * (dx % EINK_PPB));
+		byte = block->data[dy][dx / EINK_PPB];
+		byte &= ~(PIXELMASK << bitpos);
+		if (g->p.color != Black)
+			byte |= PIXEL_WHITE << bitpos;
+		else
+			byte |= PIXEL_BLACK << bitpos;
+		block->data[dy][dx / EINK_PPB] = byte;
+	}
+#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:
+				gdisp_lld_flush(g);
+				power_off(g);
+				break;
+			case powerOn:
+				power_on(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:
+			case GDISP_ROTATE_180:
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+			case GDISP_ROTATE_270:
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			default:
+				return;
+			}
+			g->g.Orientation = (orientation_t)g->p.ptr;
+			return;
+			
+		default:
+			return;
+		}
+	}
+#endif
+
+/* ===============================
+ *       Accelerated routines
+ * =============================== */
+
+#if GDISP_HARDWARE_CLEARS
+	static void subclear(GDisplay *g, color_t color) {
+		unsigned x, y;
+		uint8_t byte;
+
+		hscan_start(g);
+		byte = color ? BYTE_WHITE : BYTE_BLACK;
+		for (x = 0; x < GDISP_SCREEN_WIDTH; x++)
+		{
+			hscan_write(g, &byte, 1);
+		}
+		hscan_stop(g);
+
+		setpin_oe(g, TRUE);
+		vscan_start(g);
+		for (y = 0; y < GDISP_SCREEN_HEIGHT; y++)
+			vscan_bulkwrite(g);
+		vscan_stop(g);
+		setpin_oe(g, FALSE);
+	}
+	
+	void gdisp_lld_clear(GDisplay *g) {
+		unsigned i;
+
+		clear_block_map(g);
+
+		if (EINK_BLINKCLEAR) {
+			subclear(g, !g->p.color);
+			gfxSleepMilliseconds(50);
+		}
+
+		for (i = 0; i < EINK_CLEARCOUNT; i++) {
+			subclear(g, g->p.color);
+			gfxSleepMilliseconds(10);
+		}
+	}
+#endif
+
+#endif	// GFX_USE_GDISP
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.c b/drivers/gdisp/HX8347D/gdisp_lld.c
deleted file mode 100644
index ab976db0..00000000
--- a/drivers/gdisp/HX8347D/gdisp_lld.c
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/HX8347D/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the HX8347D display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_HX8347D
-#include "../drivers/gdisp/HX8347D/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_HX8347D.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#include "../drivers/gdisp/HX8347D/HX8347D.h"
-
-#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
-
-static inline void set_viewport(GDisplay* g) {
-	write_reg(g, HX8347D_REG_SCL, g->p.x);
-	write_reg(g, HX8347D_REG_SCH, g->p.x >> 8);
-	write_reg(g, HX8347D_REG_ECL, g->p.x + g->p.cx -1);
-	write_reg(g, HX8347D_REG_ECH, (g->p.x + g->p.cx -1) >> 8);
-	write_reg(g, HX8347D_REG_SPL, g->p.y);
-	write_reg(g, HX8347D_REG_SPH, g->p.y >> 8);
-	write_reg(g, HX8347D_REG_EPL, g->p.y + g->p.cy -1);
-	write_reg(g, HX8347D_REG_EPH, (g->p.y + g->p.cy -1) >> 8);
-	write_index(g, HX8347D_REG_SRAMWC);
-}
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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(1);
-	setpin_reset(g, FALSE);
-	gfxSleepMilliseconds(5);
-
-	// Get the bus for the following initialisation commands
-	acquire_bus(g);
-
-	/* Start Initial Sequence ----------------------------------------------------*/
-	write_reg(g, HX8347D_REG_STBAH, 0x00);                 /* Reset Power Control 1                */
-	write_reg(g, HX8347D_REG_STBAL, 0x20);                 /* Power Control 2                      */
-	write_reg(g, HX8347D_REG_PTBAH, 0x0C);                 /* Power Control 1                      */
-	write_reg(g, HX8347D_REG_PTBAL, 0xC4);                 /* Power Control 2                      */
-	write_reg(g, HX8347D_REG_OPONN, 0x40);                 /* Source OPON_N                        */
-	write_reg(g, HX8347D_REG_OPONI, 0x38);                 /* Source OPON_I                        */
-	write_reg(g, HX8347D_REG_DC2, 0xA3);                   /* Display Control 2                    */
-
-	/* Power On sequence ---------------------------------------------------------*/
-	write_reg(g, HX8347D_REG_PWC2, 0x1B);                  /* Power Control 2                      */
-	write_reg(g, HX8347D_REG_PWC1, 0x01);                  /* Power Control 1                      */
-	write_reg(g, HX8347D_REG_VMH, 0x2F);                   /* Vcom Control 2                       */
-	write_reg(g, HX8347D_REG_VML, 0x57);                   /* Vcom Control 3                       */
-	write_reg(g, HX8347D_REG_VMF, 0x8D);                   /* Vcom Control 1                       */
-
-	/* Gamma settings  -----------------------------------------------------------*/
-	write_reg(g, HX8347D_REG_VRP0, 0x01);   //   default setup
-	write_reg(g, HX8347D_REG_VRP1, 0x0e);   //
-	write_reg(g, HX8347D_REG_VRP2, 0x11);   //
-	write_reg(g, HX8347D_REG_VRP3, 0x1a);   //
-	write_reg(g, HX8347D_REG_VRP4, 0x18);   //
-	write_reg(g, HX8347D_REG_VRP5, 0x24);   //
-	write_reg(g, HX8347D_REG_PRP0, 0x15);   //
-	write_reg(g, HX8347D_REG_PRP1, 0x65);   //
-	write_reg(g, HX8347D_REG_PKP0, 0x0b);   //
-	write_reg(g, HX8347D_REG_PKP1, 0x18);   //
-	write_reg(g, HX8347D_REG_PKP2, 0x19);   //
-	write_reg(g, HX8347D_REG_PKP3, 0x1a);   //
-	write_reg(g, HX8347D_REG_PKP4, 0x18);   //
-	write_reg(g, HX8347D_REG_VRN0, 0x1b);   //
-	write_reg(g, HX8347D_REG_VRN1, 0x27);   //
-	write_reg(g, HX8347D_REG_VRN2, 0x25);   //
-	write_reg(g, HX8347D_REG_VRN3, 0x2e);   //
-	write_reg(g, HX8347D_REG_VRN4, 0x31);   //
-	write_reg(g, HX8347D_REG_VRN5, 0x3e);   //
-	write_reg(g, HX8347D_REG_PRN0, 0x1a);   //
-	write_reg(g, HX8347D_REG_PRN1, 0x6a);   //
-	write_reg(g, HX8347D_REG_PKN0, 0x07);   //
-	write_reg(g, HX8347D_REG_PKN1, 0x05);   //
-	write_reg(g, HX8347D_REG_PKN2, 0x06);   //
-	write_reg(g, HX8347D_REG_PKN3, 0x0b);   //
-	write_reg(g, HX8347D_REG_PKN4, 0x14);   //
-	write_reg(g, HX8347D_REG_CGM, 0xcc);    //
-
-	/* Power + Osc ---------------------------------------------------------------*/
-	write_reg(g, HX8347D_REG_OSCCH, 0x36);               /* OSC Control 1                        */
-	write_reg(g, HX8347D_REG_OSCCL, 0x01);               /* OSC Control 2                        */
-	write_reg(g, HX8347D_REG_DMODE, 0x00);               /* Display Mode Control                 */
-	write_reg(g, HX8347D_REG_PWC6, 0x88);                /* Power Control 6                      */
-	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(g, HX8347D_REG_PWC6, 0x80);                /* Power Control 6                      */
-	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(g, HX8347D_REG_PWC6, 0x90);                /* Power Control 6                      */
-	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(g, HX8347D_REG_PWC6, 0xD0);                /* Power Control 6                      */
-	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
-	write_reg(g, HX8347D_REG_COLMOD, 0x05);              /* Colmod 16Bit/Pixel                   */
-	write_reg(g, HX8347D_REG_PCH, 0x00);                 /* Panel Characteristic                 */
-	write_reg(g, HX8347D_REG_DC3, 0x38);                 /* Display Control 3                    */
-	gfxSleepMilliseconds(40);                            /* Delay 40 ms                          */
-	write_reg(g, HX8347D_REG_DC3, 0x3C);                 /* Display Control 3                    */
-	write_reg(g, HX8347D_REG_MAC, 0x08);                 /* Memory access control                */
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(g);
-
-	/* Turn on the backlight */
-	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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		busmode16(g);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_ram16(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		busmode8(g);
-		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_ORIENTATION:
-			if (g->g.Orientation == (orientation_t)g->p.ptr)
-				return;
-			switch((orientation_t)g->p.ptr) {
-				case GDISP_ROTATE_0:
-					acquire_bus(g);
-					write_reg(g, HX8347D_REG_MAC, 0x08);                    /* Memory access control */
-					release_bus(g);
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-
-				case GDISP_ROTATE_90:
-					acquire_bus(g);
-					write_reg(g, HX8347D_REG_MAC, 0x68);                    /* Memory access control */
-					release_bus(g);
-					g->g.Height = GDISP_SCREEN_WIDTH;
-					g->g.Width = GDISP_SCREEN_HEIGHT;
-					break;
-
-				case GDISP_ROTATE_180:
-					acquire_bus(g);
-					write_reg(g, HX8347D_REG_MAC, 0xc8);                    /* Memory access control */
-					release_bus(g);
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-
-				case GDISP_ROTATE_270:
-					acquire_bus(g);
-					write_reg(g, HX8347D_REG_MAC, 0xa8);                    /* Memory access control */
-					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;
-            set_backlight(g, (unsigned)g->p.ptr);
-            g->g.Backlight = (unsigned)g->p.ptr;
-            return;
-
-		default:
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/HX8347D/gdisp_lld.mk b/drivers/gdisp/HX8347D/gdisp_lld.mk
index 72d9cf75..581e53e7 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld.mk
+++ b/drivers/gdisp/HX8347D/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/HX8347D
-GFXSRC += $(GFXLIB)/drivers/gdisp/HX8347D/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c b/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
new file mode 100644
index 00000000..fecf115c
--- /dev/null
+++ b/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
@@ -0,0 +1,236 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/HX8347D/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the HX8347D display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_HX8347D
+#include "../drivers/gdisp/HX8347D/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_HX8347D.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#include "../drivers/gdisp/HX8347D/HX8347D.h"
+
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+
+static inline void set_viewport(GDisplay* g) {
+	write_reg(g, HX8347D_REG_SCL, g->p.x);
+	write_reg(g, HX8347D_REG_SCH, g->p.x >> 8);
+	write_reg(g, HX8347D_REG_ECL, g->p.x + g->p.cx -1);
+	write_reg(g, HX8347D_REG_ECH, (g->p.x + g->p.cx -1) >> 8);
+	write_reg(g, HX8347D_REG_SPL, g->p.y);
+	write_reg(g, HX8347D_REG_SPH, g->p.y >> 8);
+	write_reg(g, HX8347D_REG_EPL, g->p.y + g->p.cy -1);
+	write_reg(g, HX8347D_REG_EPH, (g->p.y + g->p.cy -1) >> 8);
+	write_index(g, HX8347D_REG_SRAMWC);
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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(1);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(5);
+
+	// Get the bus for the following initialisation commands
+	acquire_bus(g);
+
+	/* Start Initial Sequence ----------------------------------------------------*/
+	write_reg(g, HX8347D_REG_STBAH, 0x00);                 /* Reset Power Control 1                */
+	write_reg(g, HX8347D_REG_STBAL, 0x20);                 /* Power Control 2                      */
+	write_reg(g, HX8347D_REG_PTBAH, 0x0C);                 /* Power Control 1                      */
+	write_reg(g, HX8347D_REG_PTBAL, 0xC4);                 /* Power Control 2                      */
+	write_reg(g, HX8347D_REG_OPONN, 0x40);                 /* Source OPON_N                        */
+	write_reg(g, HX8347D_REG_OPONI, 0x38);                 /* Source OPON_I                        */
+	write_reg(g, HX8347D_REG_DC2, 0xA3);                   /* Display Control 2                    */
+
+	/* Power On sequence ---------------------------------------------------------*/
+	write_reg(g, HX8347D_REG_PWC2, 0x1B);                  /* Power Control 2                      */
+	write_reg(g, HX8347D_REG_PWC1, 0x01);                  /* Power Control 1                      */
+	write_reg(g, HX8347D_REG_VMH, 0x2F);                   /* Vcom Control 2                       */
+	write_reg(g, HX8347D_REG_VML, 0x57);                   /* Vcom Control 3                       */
+	write_reg(g, HX8347D_REG_VMF, 0x8D);                   /* Vcom Control 1                       */
+
+	/* Gamma settings  -----------------------------------------------------------*/
+	write_reg(g, HX8347D_REG_VRP0, 0x01);   //   default setup
+	write_reg(g, HX8347D_REG_VRP1, 0x0e);   //
+	write_reg(g, HX8347D_REG_VRP2, 0x11);   //
+	write_reg(g, HX8347D_REG_VRP3, 0x1a);   //
+	write_reg(g, HX8347D_REG_VRP4, 0x18);   //
+	write_reg(g, HX8347D_REG_VRP5, 0x24);   //
+	write_reg(g, HX8347D_REG_PRP0, 0x15);   //
+	write_reg(g, HX8347D_REG_PRP1, 0x65);   //
+	write_reg(g, HX8347D_REG_PKP0, 0x0b);   //
+	write_reg(g, HX8347D_REG_PKP1, 0x18);   //
+	write_reg(g, HX8347D_REG_PKP2, 0x19);   //
+	write_reg(g, HX8347D_REG_PKP3, 0x1a);   //
+	write_reg(g, HX8347D_REG_PKP4, 0x18);   //
+	write_reg(g, HX8347D_REG_VRN0, 0x1b);   //
+	write_reg(g, HX8347D_REG_VRN1, 0x27);   //
+	write_reg(g, HX8347D_REG_VRN2, 0x25);   //
+	write_reg(g, HX8347D_REG_VRN3, 0x2e);   //
+	write_reg(g, HX8347D_REG_VRN4, 0x31);   //
+	write_reg(g, HX8347D_REG_VRN5, 0x3e);   //
+	write_reg(g, HX8347D_REG_PRN0, 0x1a);   //
+	write_reg(g, HX8347D_REG_PRN1, 0x6a);   //
+	write_reg(g, HX8347D_REG_PKN0, 0x07);   //
+	write_reg(g, HX8347D_REG_PKN1, 0x05);   //
+	write_reg(g, HX8347D_REG_PKN2, 0x06);   //
+	write_reg(g, HX8347D_REG_PKN3, 0x0b);   //
+	write_reg(g, HX8347D_REG_PKN4, 0x14);   //
+	write_reg(g, HX8347D_REG_CGM, 0xcc);    //
+
+	/* Power + Osc ---------------------------------------------------------------*/
+	write_reg(g, HX8347D_REG_OSCCH, 0x36);               /* OSC Control 1                        */
+	write_reg(g, HX8347D_REG_OSCCL, 0x01);               /* OSC Control 2                        */
+	write_reg(g, HX8347D_REG_DMODE, 0x00);               /* Display Mode Control                 */
+	write_reg(g, HX8347D_REG_PWC6, 0x88);                /* Power Control 6                      */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
+	write_reg(g, HX8347D_REG_PWC6, 0x80);                /* Power Control 6                      */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
+	write_reg(g, HX8347D_REG_PWC6, 0x90);                /* Power Control 6                      */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
+	write_reg(g, HX8347D_REG_PWC6, 0xD0);                /* Power Control 6                      */
+	gfxSleepMilliseconds(5);                             /* Delay 5 ms                           */
+	write_reg(g, HX8347D_REG_COLMOD, 0x05);              /* Colmod 16Bit/Pixel                   */
+	write_reg(g, HX8347D_REG_PCH, 0x00);                 /* Panel Characteristic                 */
+	write_reg(g, HX8347D_REG_DC3, 0x38);                 /* Display Control 3                    */
+	gfxSleepMilliseconds(40);                            /* Delay 40 ms                          */
+	write_reg(g, HX8347D_REG_DC3, 0x3C);                 /* Display Control 3                    */
+	write_reg(g, HX8347D_REG_MAC, 0x08);                 /* Memory access control                */
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(g);
+
+	/* Turn on the backlight */
+	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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		busmode16(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_ram16(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		busmode8(g);
+		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_ORIENTATION:
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
+				return;
+			switch((orientation_t)g->p.ptr) {
+				case GDISP_ROTATE_0:
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0x08);                    /* Memory access control */
+					release_bus(g);
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_90:
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0x68);                    /* Memory access control */
+					release_bus(g);
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				case GDISP_ROTATE_180:
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0xc8);                    /* Memory access control */
+					release_bus(g);
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_270:
+					acquire_bus(g);
+					write_reg(g, HX8347D_REG_MAC, 0xa8);                    /* Memory access control */
+					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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		default:
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
deleted file mode 100644
index a18c2d82..00000000
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9320 display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-/* This controller is only ever used with a 240 x 320 display */
-#if defined(GDISP_SCREEN_HEIGHT)
-	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
-	#undef GDISP_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_ILI9320
-#include "../drivers/gdisp/ILI9320/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_ILI9320.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
-#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
-
-static void set_cursor(GDisplay *g) {
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-		case GDISP_ROTATE_180:
-			write_reg(g, 0x20, g->p.x);
-			write_reg(g, 0x21, g->p.y);
-			break;
-
-		case GDISP_ROTATE_90:
-		case GDISP_ROTATE_270:
-			write_reg(g, 0x20, g->p.y);
-			write_reg(g, 0x21, g->p.x);
-			break;
-	}
-	write_index(g, 0x22);
-}
-
-static void set_viewport(GDisplay *g) {
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-		case GDISP_ROTATE_180:
-			write_reg(g, 0x50, g->p.x);
-			write_reg(g, 0x51, g->p.x + g->p.cx - 1);
-			write_reg(g, 0x52, g->p.y);
-			write_reg(g, 0x53, g->p.y + g->p.cy - 1);
-			break;
-
-		case GDISP_ROTATE_90:
-		case GDISP_ROTATE_270:
-			write_reg(g, 0x50, g->p.y);
-			write_reg(g, 0x51, g->p.y + g->p.cy - 1);
-			write_reg(g, 0x52, g->p.x);
-			write_reg(g, 0x53, g->p.x + g->p.cx - 1);
-			break;
-	}
-}
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	uint16_t cver;
-
-	// No private area for this controller
-	g->priv = 0;
-
-	// Initialise the board interface
-	init_board(g);
-
-	/* Hardware reset */
-	setpin_reset(g, TRUE);
-	gfxSleepMicroseconds(1000);
-	setpin_reset(g, FALSE);
-	gfxSleepMicroseconds(1000);
-
-	acquire_bus(g);
-	write_index(g, 0);				// Get controller version
-	setreadmode(g);
-	dummy_read(g);
-    cver = read_data(g);
-	setwritemode(g);
-    write_reg(g, 0x00, 0x0001); //start Int. osc
-    gfxSleepMicroseconds(500);
-    write_reg(g, 0x01, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
-    write_reg(g, 0x02, 0x0700); //select  the line inversion
-    write_reg(g, 0x03, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
-    write_reg(g, 0x04, 0x0000); //Resize control(No resizing)
-    write_reg(g, 0x08, 0x0202); //front and back porch 2 lines
-    write_reg(g, 0x09, 0x0000); //select normal scan
-    write_reg(g, 0x0A, 0x0000); //display control 4
-    write_reg(g, 0x0C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
-    write_reg(g, 0x0D, 0x0000); //Frame marker position
-    write_reg(g, 0x0F, 0x0000); //selects clk, enable and sync signal polarity,
-    write_reg(g, 0x10, 0x0000); //
-    write_reg(g, 0x11, 0x0000); //power control 2 reference voltages = 1:1,
-    write_reg(g, 0x12, 0x0000); //power control 3 VRH
-    write_reg(g, 0x13, 0x0000); //power control 4 VCOM amplitude
-    gfxSleepMicroseconds(500);
-    write_reg(g, 0x10, 0x17B0); //power control 1 BT,AP
-    write_reg(g, 0x11, 0x0137); //power control 2 DC,VC
-    gfxSleepMicroseconds(500);
-    write_reg(g, 0x12, 0x0139); //power control 3 VRH
-    gfxSleepMicroseconds(500);
-    write_reg(g, 0x13, 0x1d00); //power control 4 vcom amplitude
-    write_reg(g, 0x29, 0x0011); //power control 7 VCOMH
-    gfxSleepMicroseconds(500);
-    write_reg(g, 0x30, 0x0007);
-    write_reg(g, 0x31, 0x0403);
-    write_reg(g, 0x32, 0x0404);
-    write_reg(g, 0x35, 0x0002);
-    write_reg(g, 0x36, 0x0707);
-    write_reg(g, 0x37, 0x0606);
-    write_reg(g, 0x38, 0x0106);
-    write_reg(g, 0x39, 0x0007);
-    write_reg(g, 0x3c, 0x0700);
-    write_reg(g, 0x3d, 0x0707);
-    write_reg(g, 0x20, 0x0000); //starting Horizontal GRAM Address
-    write_reg(g, 0x21, 0x0000); //starting Vertical GRAM Address
-    write_reg(g, 0x50, 0x0000); //Horizontal GRAM Start Position
-    write_reg(g, 0x51, 0x00EF); //Horizontal GRAM end Position
-    write_reg(g, 0x52, 0x0000); //Vertical GRAM Start Position
-    write_reg(g, 0x53, 0x013F); //Vertical GRAM end Position
-	switch (cver) {
-		case 0x9320:
-        	write_reg(g, 0x60, 0x2700); //starts scanning from G1, and 320 drive lines
-        	break;
-      	case 0x9325:
-     		write_reg(g, 0x60, 0xA700); //starts scanning from G1, and 320 drive lines
-			break;
-	}
-
-    write_reg(g, 0x61, 0x0001); //fixed base display
-    write_reg(g, 0x6a, 0x0000); //no scroll
-    write_reg(g, 0x90, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
-    write_reg(g, 0x92, 0x0000); //set gate output non-overlap period=0
-    write_reg(g, 0x93, 0x0003); //set Source Output Position=3
-    write_reg(g, 0x95, 0x0110); //RGB interface(Clocks per line period=16 clocks)
-    write_reg(g, 0x97, 0x0110); //set Gate Non-overlap Period 0 locksc
-    write_reg(g, 0x98, 0x0110); //
-    write_reg(g, 0x07, 0x0173); //display On
-
-    // Finish Init
-    post_init_board(g);
-
-  	// Release the bus
- 	release_bus(g);
-
-	// Turn on the backlight
-	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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		#if !GDISP_HARDWARE_STREAM_POS
-			set_cursor(g);
-		#endif
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-	#if GDISP_HARDWARE_STREAM_POS
-		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-			set_cursor(g);
-		}
-	#endif
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		setwritemode(g);
-		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:
-					acquire_bus(g);
-					write_reg(g, 0x07, 0x0000);
-					write_reg(g, 0x10, 0x0000);
-					write_reg(g, 0x11, 0x0000);
-					write_reg(g, 0x12, 0x0000);
-					write_reg(g, 0x13, 0x0000);
-					release_bus(g);
-
-					set_backlight(g, 0);
-					break;
-
-				case powerOn:
-					//*************Power On sequence ******************//
-					acquire_bus(g);
-					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
-					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
-					gfxSleepMicroseconds(2000);            /* Dis-charge capacitor power voltage */
-					write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-					write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					gfxSleepMicroseconds(500);
-					write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
-					gfxSleepMicroseconds(500);
-					write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
-					write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
-					gfxSleepMicroseconds(500);
-					write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
-					release_bus(g);
-
-					set_backlight(g, g->g.Backlight);
-					break;
-
-				case powerSleep:
-					acquire_bus(g);
-					write_reg(g, 0x07, 0x0000); /* display OFF */
-					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
-					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
-					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
-					write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					release_bus(g);
-
-					set_backlight(g, 0);
-					break;
-
-				case powerDeepSleep:
-					acquire_bus(g);
-					write_reg(g, 0x07, 0x0000); /* display OFF */
-					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
-					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
-					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
-					write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-					release_bus(g);
-
-					set_backlight(g, 0);
-					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);
-					write_reg(g, 0x01, 0x0100);
-					write_reg(g, 0x03, 0x1038);
-					write_reg(g, 0x60, 0x2700);
-					release_bus(g);
-
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-
-				case GDISP_ROTATE_90:
-					acquire_bus(g);
-					write_reg(g, 0x01, 0x0100);
-					write_reg(g, 0x03, 0x1030);
-					write_reg(g, 0x60, 0x2700);
-					release_bus(g);
-
-					g->g.Height = GDISP_SCREEN_WIDTH;
-					g->g.Width = GDISP_SCREEN_HEIGHT;
-					break;
-
-				case GDISP_ROTATE_180:
-					acquire_bus(g);
-					write_reg(g, 0x01, 0x0000);
-					write_reg(g, 0x03, 0x1030);
-					write_reg(g, 0x60, 0x2700);
-					release_bus(g);
-
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-
-				case GDISP_ROTATE_270:
-					acquire_bus(g);
-					write_reg(g, 0x01, 0x0000);
-					write_reg(g, 0x03, 0x1038);
-					write_reg(g, 0x60, 0xA700);
-					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;
-	            set_backlight(g, (unsigned)g->p.ptr);
-	            g->g.Backlight = (unsigned)g->p.ptr;
-	            return;
-			default:
-				return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9320/gdisp_lld.mk b/drivers/gdisp/ILI9320/gdisp_lld.mk
index 071e7c02..d61fbc33 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9320/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9320
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c b/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
new file mode 100644
index 00000000..a18c2d82
--- /dev/null
+++ b/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
@@ -0,0 +1,377 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9320/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9320 display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+/* This controller is only ever used with a 240 x 320 display */
+#if defined(GDISP_SCREEN_HEIGHT)
+	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+	#undef GDISP_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_ILI9320
+#include "../drivers/gdisp/ILI9320/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ILI9320.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#define dummy_read(g)				{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+
+static void set_cursor(GDisplay *g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(g, 0x20, g->p.x);
+			write_reg(g, 0x21, g->p.y);
+			break;
+
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(g, 0x20, g->p.y);
+			write_reg(g, 0x21, g->p.x);
+			break;
+	}
+	write_index(g, 0x22);
+}
+
+static void set_viewport(GDisplay *g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(g, 0x50, g->p.x);
+			write_reg(g, 0x51, g->p.x + g->p.cx - 1);
+			write_reg(g, 0x52, g->p.y);
+			write_reg(g, 0x53, g->p.y + g->p.cy - 1);
+			break;
+
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(g, 0x50, g->p.y);
+			write_reg(g, 0x51, g->p.y + g->p.cy - 1);
+			write_reg(g, 0x52, g->p.x);
+			write_reg(g, 0x53, g->p.x + g->p.cx - 1);
+			break;
+	}
+}
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	uint16_t cver;
+
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
+	init_board(g);
+
+	/* Hardware reset */
+	setpin_reset(g, TRUE);
+	gfxSleepMicroseconds(1000);
+	setpin_reset(g, FALSE);
+	gfxSleepMicroseconds(1000);
+
+	acquire_bus(g);
+	write_index(g, 0);				// Get controller version
+	setreadmode(g);
+	dummy_read(g);
+    cver = read_data(g);
+	setwritemode(g);
+    write_reg(g, 0x00, 0x0001); //start Int. osc
+    gfxSleepMicroseconds(500);
+    write_reg(g, 0x01, 0x0100); //Set SS bit (shift direction of outputs is from S720 to S1)
+    write_reg(g, 0x02, 0x0700); //select  the line inversion
+    write_reg(g, 0x03, 0x1038); //Entry mode(Horizontal : increment,Vertical : increment, AM=1)
+    write_reg(g, 0x04, 0x0000); //Resize control(No resizing)
+    write_reg(g, 0x08, 0x0202); //front and back porch 2 lines
+    write_reg(g, 0x09, 0x0000); //select normal scan
+    write_reg(g, 0x0A, 0x0000); //display control 4
+    write_reg(g, 0x0C, 0x0000); //system interface(2 transfer /pixel), internal sys clock,
+    write_reg(g, 0x0D, 0x0000); //Frame marker position
+    write_reg(g, 0x0F, 0x0000); //selects clk, enable and sync signal polarity,
+    write_reg(g, 0x10, 0x0000); //
+    write_reg(g, 0x11, 0x0000); //power control 2 reference voltages = 1:1,
+    write_reg(g, 0x12, 0x0000); //power control 3 VRH
+    write_reg(g, 0x13, 0x0000); //power control 4 VCOM amplitude
+    gfxSleepMicroseconds(500);
+    write_reg(g, 0x10, 0x17B0); //power control 1 BT,AP
+    write_reg(g, 0x11, 0x0137); //power control 2 DC,VC
+    gfxSleepMicroseconds(500);
+    write_reg(g, 0x12, 0x0139); //power control 3 VRH
+    gfxSleepMicroseconds(500);
+    write_reg(g, 0x13, 0x1d00); //power control 4 vcom amplitude
+    write_reg(g, 0x29, 0x0011); //power control 7 VCOMH
+    gfxSleepMicroseconds(500);
+    write_reg(g, 0x30, 0x0007);
+    write_reg(g, 0x31, 0x0403);
+    write_reg(g, 0x32, 0x0404);
+    write_reg(g, 0x35, 0x0002);
+    write_reg(g, 0x36, 0x0707);
+    write_reg(g, 0x37, 0x0606);
+    write_reg(g, 0x38, 0x0106);
+    write_reg(g, 0x39, 0x0007);
+    write_reg(g, 0x3c, 0x0700);
+    write_reg(g, 0x3d, 0x0707);
+    write_reg(g, 0x20, 0x0000); //starting Horizontal GRAM Address
+    write_reg(g, 0x21, 0x0000); //starting Vertical GRAM Address
+    write_reg(g, 0x50, 0x0000); //Horizontal GRAM Start Position
+    write_reg(g, 0x51, 0x00EF); //Horizontal GRAM end Position
+    write_reg(g, 0x52, 0x0000); //Vertical GRAM Start Position
+    write_reg(g, 0x53, 0x013F); //Vertical GRAM end Position
+	switch (cver) {
+		case 0x9320:
+        	write_reg(g, 0x60, 0x2700); //starts scanning from G1, and 320 drive lines
+        	break;
+      	case 0x9325:
+     		write_reg(g, 0x60, 0xA700); //starts scanning from G1, and 320 drive lines
+			break;
+	}
+
+    write_reg(g, 0x61, 0x0001); //fixed base display
+    write_reg(g, 0x6a, 0x0000); //no scroll
+    write_reg(g, 0x90, 0x0010); //set Clocks/Line =16, Internal Operation Clock Frequency=fosc/1,
+    write_reg(g, 0x92, 0x0000); //set gate output non-overlap period=0
+    write_reg(g, 0x93, 0x0003); //set Source Output Position=3
+    write_reg(g, 0x95, 0x0110); //RGB interface(Clocks per line period=16 clocks)
+    write_reg(g, 0x97, 0x0110); //set Gate Non-overlap Period 0 locksc
+    write_reg(g, 0x98, 0x0110); //
+    write_reg(g, 0x07, 0x0173); //display On
+
+    // Finish Init
+    post_init_board(g);
+
+  	// Release the bus
+ 	release_bus(g);
+
+	// Turn on the backlight
+	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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		#if !GDISP_HARDWARE_STREAM_POS
+			set_cursor(g);
+		#endif
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			set_cursor(g);
+		}
+	#endif
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		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:
+					acquire_bus(g);
+					write_reg(g, 0x07, 0x0000);
+					write_reg(g, 0x10, 0x0000);
+					write_reg(g, 0x11, 0x0000);
+					write_reg(g, 0x12, 0x0000);
+					write_reg(g, 0x13, 0x0000);
+					release_bus(g);
+
+					set_backlight(g, 0);
+					break;
+
+				case powerOn:
+					//*************Power On sequence ******************//
+					acquire_bus(g);
+					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					gfxSleepMicroseconds(2000);            /* Dis-charge capacitor power voltage */
+					write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+					write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					gfxSleepMicroseconds(500);
+					write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
+					gfxSleepMicroseconds(500);
+					write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+					write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
+					gfxSleepMicroseconds(500);
+					write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
+					release_bus(g);
+
+					set_backlight(g, g->g.Backlight);
+					break;
+
+				case powerSleep:
+					acquire_bus(g);
+					write_reg(g, 0x07, 0x0000); /* display OFF */
+					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
+					write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					release_bus(g);
+
+					set_backlight(g, 0);
+					break;
+
+				case powerDeepSleep:
+					acquire_bus(g);
+					write_reg(g, 0x07, 0x0000); /* display OFF */
+					write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+					write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+					write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
+					gfxSleepMicroseconds(2000); /* Dis-charge capacitor power voltage */
+					write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+					release_bus(g);
+
+					set_backlight(g, 0);
+					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);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
+
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_90:
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
+
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				case GDISP_ROTATE_180:
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
+
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_270:
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0xA700);
+					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;
+	            set_backlight(g, (unsigned)g->p.ptr);
+	            g->g.Backlight = (unsigned)g->p.ptr;
+	            return;
+			default:
+				return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
deleted file mode 100644
index 75b4cd13..00000000
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9325/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9325 display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-/* This controller is only ever used with a 240 x 320 display */
-#if defined(GDISP_SCREEN_HEIGHT)
-	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
-	#undef GDISP_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_ILI9325
-#include "../drivers/gdisp/ILI9325/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_ILI9325.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// 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_index(g, reg); write_data(g, data); }
-
-static void set_cursor(GDisplay *g) {
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-		case GDISP_ROTATE_180:
-			write_reg(g, 0x20, g->p.x);
-			write_reg(g, 0x21, g->p.y);
-			break;
-
-		case GDISP_ROTATE_90:
-		case GDISP_ROTATE_270:
-			write_reg(g, 0x20, g->p.y);
-			write_reg(g, 0x21, g->p.x);
-			break;
-	}
-	write_index(g, 0x22);
-}
-
-static void set_viewport(GDisplay* g) {
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-		case GDISP_ROTATE_180:
-			write_reg(g, 0x50, g->p.x);
-			write_reg(g, 0x51, g->p.x + g->p.cx - 1);
-			write_reg(g, 0x52, g->p.y);
-			write_reg(g, 0x53, g->p.y + g->p.cy - 1);
-			break;
-
-		case GDISP_ROTATE_90:
-		case GDISP_ROTATE_270:
-			write_reg(g, 0x50, g->p.y);
-			write_reg(g, 0x51, g->p.y + g->p.cy - 1);
-			write_reg(g, 0x52, g->p.x);
-			write_reg(g, 0x53, g->p.x + g->p.cx - 1);
-			break;
-	}
-}
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	uint16_t cver;
-
-	// No private area for this controller
-	g->priv = 0;
-
-	// Initialise the board interface
-	init_board(g);
-
-	/* Hardware reset */
-	setpin_reset(g, TRUE);
-	gfxSleepMicroseconds(1000);
-	setpin_reset(g, FALSE);
-	gfxSleepMicroseconds(1000);
-
-	acquire_bus(g);
-	write_index(g, 0);				// Get controller version
-	setreadmode(g);
-	dummy_read(g);
-    cver = read_data(g);
-    setwritemode(g);
-
-	// chinese code starts here
-	write_reg(g, 0x00, 0x0001);
-	gfxSleepMilliseconds(10);
-
-	write_reg(g, 0x15, 0x0030);
-	write_reg(g, 0x11, 0x0040);
-	write_reg(g, 0x10, 0x1628);
-	write_reg(g, 0x12, 0x0000);
-	write_reg(g, 0x13, 0x104d);
-	gfxSleepMilliseconds(10);
-	write_reg(g, 0x12, 0x0010);
-	gfxSleepMilliseconds(10);
-	write_reg(g, 0x10, 0x2620);
-	write_reg(g, 0x13, 0x344d); //304d
-	gfxSleepMilliseconds(10);
-
-	write_reg(g, 0x01, 0x0100);
-	write_reg(g, 0x02, 0x0300);
-	write_reg(g, 0x03, 0x1038);//0x1030
-	write_reg(g, 0x08, 0x0604);
-	write_reg(g, 0x09, 0x0000);
-	write_reg(g, 0x0A, 0x0008);
-
-	write_reg(g, 0x41, 0x0002);
-	write_reg(g, 0x60, 0x2700);
-	write_reg(g, 0x61, 0x0001);
-	write_reg(g, 0x90, 0x0182);
-	write_reg(g, 0x93, 0x0001);
-	write_reg(g, 0xa3, 0x0010);
-	gfxSleepMilliseconds(10);
-
-	//################# void Gamma_Set(void) ####################//
-	write_reg(g, 0x30, 0x0000);
-	write_reg(g, 0x31, 0x0502);
-	write_reg(g, 0x32, 0x0307);
-	write_reg(g, 0x33, 0x0305);
-	write_reg(g, 0x34, 0x0004);
-	write_reg(g, 0x35, 0x0402);
-	write_reg(g, 0x36, 0x0707);
-	write_reg(g, 0x37, 0x0503);
-	write_reg(g, 0x38, 0x1505);
-	write_reg(g, 0x39, 0x1505);
-	gfxSleepMilliseconds(10);
-
-	//################## void Display_ON(void) ####################//
-	write_reg(g, 0x07, 0x0001);
-	gfxSleepMilliseconds(10);
-	write_reg(g, 0x07, 0x0021);
-	write_reg(g, 0x07, 0x0023);
-	gfxSleepMilliseconds(10);
-	write_reg(g, 0x07, 0x0033);
-	gfxSleepMilliseconds(10);
-	write_reg(g, 0x07, 0x0133);
-
-	// chinese code ends here
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(g);
-
-	// Turn on the backlight
-	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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-		set_cursor(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		setwritemode(g);
-		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:
-				acquire_bus(g);
-				write_reg(g, 0x07, 0x0000);
-				write_reg(g, 0x10, 0x0000);
-				write_reg(g, 0x11, 0x0000);
-				write_reg(g, 0x12, 0x0000);
-				write_reg(g, 0x13, 0x0000);
-				release_bus(g);
-				set_backlight(g, 0);
-				break;
-
-			case powerOn:
-				//*************Power On sequence ******************//
-				acquire_bus(g);
-				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
-				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
-				gfxSleepMilliseconds(200);            /* Dis-charge capacitor power voltage */
-				write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
-				write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				gfxSleepMilliseconds(50);
-				write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
-				gfxSleepMilliseconds(50);
-				write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
-				write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
-				gfxSleepMilliseconds(50);
-				write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
-				release_bus(g);
-				set_backlight(g, g->g.Backlight);
-				break;
-
-			case powerSleep:
-				acquire_bus(g);
-				write_reg(g, 0x07, 0x0000); /* display OFF */
-				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
-				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
-				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
-				write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				release_bus(g);
-				gdisp_lld_backlight(g, 0);
-				break;
-
-			case powerDeepSleep:
-				acquire_bus(g);
-				write_reg(g, 0x07, 0x0000); /* display OFF */
-				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
-				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
-				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
-				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
-				write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
-				release_bus(g);
-				gdisp_lld_backlight(g, 0);
-				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);
-					write_reg(g, 0x01, 0x0100);
-					write_reg(g, 0x03, 0x1038);
-					write_reg(g, 0x60, 0x2700);
-					release_bus(g);
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-
-				case GDISP_ROTATE_90:
-					acquire_bus(g);
-					write_reg(g, 0x01, 0x0000);
-					write_reg(g, 0x03, 0x1030);
-					write_reg(g, 0x60, 0x2700);
-					release_bus(g);
-					g->g.Height = GDISP_SCREEN_WIDTH;
-					g->g.Width = GDISP_SCREEN_HEIGHT;
-					break;
-
-				case GDISP_ROTATE_180:
-					acquire_bus(g);
-					write_reg(g, 0x01, 0x0000);
-					write_reg(g, 0x03, 0x1038);
-					write_reg(g, 0x60, 0xa700);
-					release_bus(g);
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-	
-				case GDISP_ROTATE_270:
-					acquire_bus(g);
-					write_reg(g, 0x01, 0x0100);
-					write_reg(g, 0x03, 0x1030);
-					write_reg(g, 0x60, 0xA700);
-					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;
-            set_backlight(g, (unsigned)g->p.ptr);
-            g->g.Backlight = (unsigned)g->p.ptr;
-            return;
-		
-		default:
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9325/gdisp_lld.mk b/drivers/gdisp/ILI9325/gdisp_lld.mk
index 61565164..4dbda578 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9325/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9325
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9325/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c b/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
new file mode 100644
index 00000000..75b4cd13
--- /dev/null
+++ b/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
@@ -0,0 +1,365 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9325/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9325 display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+/* This controller is only ever used with a 240 x 320 display */
+#if defined(GDISP_SCREEN_HEIGHT)
+	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+	#undef GDISP_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_ILI9325
+#include "../drivers/gdisp/ILI9325/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ILI9325.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// 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_index(g, reg); write_data(g, data); }
+
+static void set_cursor(GDisplay *g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(g, 0x20, g->p.x);
+			write_reg(g, 0x21, g->p.y);
+			break;
+
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(g, 0x20, g->p.y);
+			write_reg(g, 0x21, g->p.x);
+			break;
+	}
+	write_index(g, 0x22);
+}
+
+static void set_viewport(GDisplay* g) {
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+		case GDISP_ROTATE_180:
+			write_reg(g, 0x50, g->p.x);
+			write_reg(g, 0x51, g->p.x + g->p.cx - 1);
+			write_reg(g, 0x52, g->p.y);
+			write_reg(g, 0x53, g->p.y + g->p.cy - 1);
+			break;
+
+		case GDISP_ROTATE_90:
+		case GDISP_ROTATE_270:
+			write_reg(g, 0x50, g->p.y);
+			write_reg(g, 0x51, g->p.y + g->p.cy - 1);
+			write_reg(g, 0x52, g->p.x);
+			write_reg(g, 0x53, g->p.x + g->p.cx - 1);
+			break;
+	}
+}
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	uint16_t cver;
+
+	// No private area for this controller
+	g->priv = 0;
+
+	// Initialise the board interface
+	init_board(g);
+
+	/* Hardware reset */
+	setpin_reset(g, TRUE);
+	gfxSleepMicroseconds(1000);
+	setpin_reset(g, FALSE);
+	gfxSleepMicroseconds(1000);
+
+	acquire_bus(g);
+	write_index(g, 0);				// Get controller version
+	setreadmode(g);
+	dummy_read(g);
+    cver = read_data(g);
+    setwritemode(g);
+
+	// chinese code starts here
+	write_reg(g, 0x00, 0x0001);
+	gfxSleepMilliseconds(10);
+
+	write_reg(g, 0x15, 0x0030);
+	write_reg(g, 0x11, 0x0040);
+	write_reg(g, 0x10, 0x1628);
+	write_reg(g, 0x12, 0x0000);
+	write_reg(g, 0x13, 0x104d);
+	gfxSleepMilliseconds(10);
+	write_reg(g, 0x12, 0x0010);
+	gfxSleepMilliseconds(10);
+	write_reg(g, 0x10, 0x2620);
+	write_reg(g, 0x13, 0x344d); //304d
+	gfxSleepMilliseconds(10);
+
+	write_reg(g, 0x01, 0x0100);
+	write_reg(g, 0x02, 0x0300);
+	write_reg(g, 0x03, 0x1038);//0x1030
+	write_reg(g, 0x08, 0x0604);
+	write_reg(g, 0x09, 0x0000);
+	write_reg(g, 0x0A, 0x0008);
+
+	write_reg(g, 0x41, 0x0002);
+	write_reg(g, 0x60, 0x2700);
+	write_reg(g, 0x61, 0x0001);
+	write_reg(g, 0x90, 0x0182);
+	write_reg(g, 0x93, 0x0001);
+	write_reg(g, 0xa3, 0x0010);
+	gfxSleepMilliseconds(10);
+
+	//################# void Gamma_Set(void) ####################//
+	write_reg(g, 0x30, 0x0000);
+	write_reg(g, 0x31, 0x0502);
+	write_reg(g, 0x32, 0x0307);
+	write_reg(g, 0x33, 0x0305);
+	write_reg(g, 0x34, 0x0004);
+	write_reg(g, 0x35, 0x0402);
+	write_reg(g, 0x36, 0x0707);
+	write_reg(g, 0x37, 0x0503);
+	write_reg(g, 0x38, 0x1505);
+	write_reg(g, 0x39, 0x1505);
+	gfxSleepMilliseconds(10);
+
+	//################## void Display_ON(void) ####################//
+	write_reg(g, 0x07, 0x0001);
+	gfxSleepMilliseconds(10);
+	write_reg(g, 0x07, 0x0021);
+	write_reg(g, 0x07, 0x0023);
+	gfxSleepMilliseconds(10);
+	write_reg(g, 0x07, 0x0033);
+	gfxSleepMilliseconds(10);
+	write_reg(g, 0x07, 0x0133);
+
+	// chinese code ends here
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(g);
+
+	// Turn on the backlight
+	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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+		set_cursor(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		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:
+				acquire_bus(g);
+				write_reg(g, 0x07, 0x0000);
+				write_reg(g, 0x10, 0x0000);
+				write_reg(g, 0x11, 0x0000);
+				write_reg(g, 0x12, 0x0000);
+				write_reg(g, 0x13, 0x0000);
+				release_bus(g);
+				set_backlight(g, 0);
+				break;
+
+			case powerOn:
+				//*************Power On sequence ******************//
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				gfxSleepMilliseconds(200);            /* Dis-charge capacitor power voltage */
+				write_reg(g, 0x10, 0x17B0); /* SAP, BT[3:0], AP, DSTB, SLP, STB */
+				write_reg(g, 0x11, 0x0147); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				gfxSleepMilliseconds(50);
+				write_reg(g, 0x12, 0x013C); /* VREG1OUT voltage */
+				gfxSleepMilliseconds(50);
+				write_reg(g, 0x13, 0x0E00); /* VDV[4:0] for VCOM amplitude */
+				write_reg(g, 0x29, 0x0009); /* VCM[4:0] for VCOMH */
+				gfxSleepMilliseconds(50);
+				write_reg(g, 0x07, 0x0173); /* 262K color and display ON */
+				release_bus(g);
+				set_backlight(g, g->g.Backlight);
+				break;
+
+			case powerSleep:
+				acquire_bus(g);
+				write_reg(g, 0x07, 0x0000); /* display OFF */
+				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
+				write_reg(g, 0x10, 0x0002); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				release_bus(g);
+				gdisp_lld_backlight(g, 0);
+				break;
+
+			case powerDeepSleep:
+				acquire_bus(g);
+				write_reg(g, 0x07, 0x0000); /* display OFF */
+				write_reg(g, 0x10, 0x0000); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				write_reg(g, 0x11, 0x0000); /* DC1[2:0], DC0[2:0], VC[2:0] */
+				write_reg(g, 0x12, 0x0000); /* VREG1OUT voltage */
+				write_reg(g, 0x13, 0x0000); /* VDV[4:0] for VCOM amplitude */
+				gfxSleepMilliseconds(200); /* Dis-charge capacitor power voltage */
+				write_reg(g, 0x10, 0x0004); /* SAP, BT[3:0], APE, AP, DSTB, SLP */
+				release_bus(g);
+				gdisp_lld_backlight(g, 0);
+				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);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+
+				case GDISP_ROTATE_90:
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0x2700);
+					release_bus(g);
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+
+				case GDISP_ROTATE_180:
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0000);
+					write_reg(g, 0x03, 0x1038);
+					write_reg(g, 0x60, 0xa700);
+					release_bus(g);
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+	
+				case GDISP_ROTATE_270:
+					acquire_bus(g);
+					write_reg(g, 0x01, 0x0100);
+					write_reg(g, 0x03, 0x1030);
+					write_reg(g, 0x60, 0xA700);
+					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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+		
+		default:
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9341/gdisp_lld.c b/drivers/gdisp/ILI9341/gdisp_lld.c
deleted file mode 100644
index e5c4b7d0..00000000
--- a/drivers/gdisp/ILI9341/gdisp_lld.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9341/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for
- * 			the ILI9341 and compatible HVGA display
- */
-
-#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_ILI9341
-#include "../drivers/gdisp/ILI9341/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_ILI9341.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-#include "../drivers/gdisp/ILI9341/ILI9341.h"
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// 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_index(g, reg); write_data(g, data); }
-#define write_data16(g, data)		{ write_data(g, data >> 8); write_data(g, (uint8_t)data); }
-#define delay(us)					gfxSleepMicroseconds(us)
-#define delayms(ms)					gfxSleepMilliseconds(ms)
-
-static inline void set_cursor(GDisplay *g) {
-	write_index(g, 0x2A);
-	write_data(g, (g->p.x >> 8));
-	write_data(g, (uint8_t) g->p.x);
-	write_data(g, (g->p.x) >> 8);
-	write_data(g, (uint8_t) (g->p.x));
-
-	write_index(g, 0x2B);
-	write_data(g, (g->p.y >> 8));
-	write_data(g, (uint8_t) g->p.y);
-	write_data(g, (g->p.y) >> 8);
-	write_data(g, (uint8_t) (g->p.y));
-
-	write_index(g, 0x2C);
-}
-
-static void set_viewport(GDisplay *g) {
-	write_index(g, 0x2A);
-	write_data(g, (g->p.x >> 8));
-	write_data(g, (uint8_t) g->p.x);
-	write_data(g, (g->p.x + g->p.cx - 1) >> 8);
-	write_data(g, (uint8_t) (g->p.x + g->p.cx - 1));
-
-	write_index(g, 0x2B);
-	write_data(g, (g->p.y >> 8));
-	write_data(g, (uint8_t) g->p.y);
-	write_data(g, (g->p.y + g->p.cy - 1) >> 8);
-	write_data(g, (uint8_t) (g->p.y + g->p.cy - 1));
-}
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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_index(g, 0x01); //software reset
-	chThdSleepMilliseconds(5);
-	write_index(g, 0x28);
-	// display off
-	//---------------------------------------------------------
-	// magic?
-	write_index(g, 0xcf);
-	write_data(g, 0x00);
-	write_data(g, 0x83);
-	write_data(g, 0x30);
-
-	write_index(g, 0xed);
-	write_data(g, 0x64);
-	write_data(g, 0x03);
-	write_data(g, 0x12);
-	write_data(g, 0x81);
-	write_index(g, 0xe8);
-	write_data(g, 0x85);
-	write_data(g, 0x01);
-	write_data(g, 0x79);
-	write_index(g, 0xcb);
-	write_data(g, 0x39);
-	write_data(g, 0x2c);
-	write_data(g, 0x00);
-	write_data(g, 0x34);
-	write_data(g, 0x02);
-	write_index(g, 0xf7);
-	write_data(g, 0x20);
-	write_index(g, 0xea);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	//------------power control------------------------------
-	write_index(g, 0xc0); //power control
-	write_data(g, 0x26);
-	write_index(g, 0xc1); //power control
-	write_data(g, 0x11);
-	//--------------VCOM
-	write_index(g, 0xc5); //vcom control
-	write_data(g, 0x35);//35
-	write_data(g, 0x3e);//3E
-	write_index(g, 0xc7); //vcom control
-	write_data(g, 0xbe); // 0x94
-	//------------memory access control------------------------
-	write_index(g, 0x36);
-	// memory access control
-	write_data(g, 0x48); //0048 my,mx,mv,ml,BGR,mh,0.0
-	write_index(g, 0x3a); // pixel format set
-	write_data(g, 0x55);//16bit /pixel
-	//----------------- frame rate------------------------------
-	write_index(g, 0xb1);
-	// frame rate
-	write_data(g, 0x00);
-	write_data(g, 0x1B); //70
-	//----------------Gamma---------------------------------
-	write_index(g, 0xf2); // 3Gamma Function Disable
-	write_data(g, 0x08);
-	write_index(g, 0x26);
-	write_data(g, 0x01); // gamma set 4 gamma curve 01/02/04/08
-
-	write_index(g, 0xE0); //positive gamma correction
-	write_data(g, 0x1f);
-	write_data(g, 0x1a);
-	write_data(g, 0x18);
-	write_data(g, 0x0a);
-	write_data(g, 0x0f);
-	write_data(g, 0x06);
-	write_data(g, 0x45);
-	write_data(g, 0x87);
-	write_data(g, 0x32);
-	write_data(g, 0x0a);
-	write_data(g, 0x07);
-	write_data(g, 0x02);
-	write_data(g, 0x07);
-	write_data(g, 0x05);
-	write_data(g, 0x00);
-	write_index(g, 0xE1); //negamma correction
-	write_data(g, 0x00);
-	write_data(g, 0x25);
-	write_data(g, 0x27);
-	write_data(g, 0x05);
-	write_data(g, 0x10);
-	write_data(g, 0x09);
-	write_data(g, 0x3a);
-	write_data(g, 0x78);
-	write_data(g, 0x4d);
-	write_data(g, 0x05);
-	write_data(g, 0x18);
-	write_data(g, 0x0d);
-	write_data(g, 0x38);
-	write_data(g, 0x3a);
-	write_data(g, 0x1f);
-	//--------------ddram ---------------------
-	write_index(g, 0x2a);
-	// column set
-	// size = 239
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0xEF);
-	write_index(g, 0x2b);
-	// page address set
-	// size = 319
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0x01);
-	write_data(g, 0x3F);
-	// write_index(g, 0x34);
-	//write_index(g, 0x35);
-	// tearing effect off
-	// tearing effect on
-	// write_index(g, 0xb4); // display inversion
-	// write_data(g, 0x00);
-	write_index(g, 0xb7); //entry mode set
-	write_data(g, 0x07);
-	//-----------------display---------------------
-	write_index(g, 0xb6);
-	// display function control
-	write_data(g, 0x0a);
-	write_data(g, 0x82);
-	write_data(g, 0x27);
-	write_data(g, 0x00);
-	write_index(g, 0x11); //sleep out
-	chThdSleepMilliseconds(100);
-	write_index(g, 0x29); // display on
-	chThdSleepMilliseconds(100);
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		#if !GDISP_HARDWARE_STREAM_POS
-			set_cursor(g);
-		#endif
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data16(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-	#if GDISP_HARDWARE_STREAM_POS
-		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-			set_cursor(g);
-		}
-	#endif
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		setwritemode(g);
-		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_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
-				release_bus(g);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
-				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);
-				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				write_reg(g, 0x36, 0x80);	/* X and Y axes non-inverted */
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-				write_reg(g, 0x36, 0xE0);	/* Invert X and Y axes */
-				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;
-            set_backlight(g, (unsigned)g->p.ptr);
-            g->g.Backlight = (unsigned)g->p.ptr;
-            return;
-
-		//case GDISP_CONTROL_CONTRAST:
-        default:
-            return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9341/gdisp_lld.mk b/drivers/gdisp/ILI9341/gdisp_lld.mk
index 8c44fc85..326b67ad 100644
--- a/drivers/gdisp/ILI9341/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9341/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9341
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9341/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
diff --git a/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c b/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
new file mode 100644
index 00000000..e5c4b7d0
--- /dev/null
+++ b/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
@@ -0,0 +1,373 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9341/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for
+ * 			the ILI9341 and compatible HVGA display
+ */
+
+#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_ILI9341
+#include "../drivers/gdisp/ILI9341/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ILI9341.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+#include "../drivers/gdisp/ILI9341/ILI9341.h"
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// 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_index(g, reg); write_data(g, data); }
+#define write_data16(g, data)		{ write_data(g, data >> 8); write_data(g, (uint8_t)data); }
+#define delay(us)					gfxSleepMicroseconds(us)
+#define delayms(ms)					gfxSleepMilliseconds(ms)
+
+static inline void set_cursor(GDisplay *g) {
+	write_index(g, 0x2A);
+	write_data(g, (g->p.x >> 8));
+	write_data(g, (uint8_t) g->p.x);
+	write_data(g, (g->p.x) >> 8);
+	write_data(g, (uint8_t) (g->p.x));
+
+	write_index(g, 0x2B);
+	write_data(g, (g->p.y >> 8));
+	write_data(g, (uint8_t) g->p.y);
+	write_data(g, (g->p.y) >> 8);
+	write_data(g, (uint8_t) (g->p.y));
+
+	write_index(g, 0x2C);
+}
+
+static void set_viewport(GDisplay *g) {
+	write_index(g, 0x2A);
+	write_data(g, (g->p.x >> 8));
+	write_data(g, (uint8_t) g->p.x);
+	write_data(g, (g->p.x + g->p.cx - 1) >> 8);
+	write_data(g, (uint8_t) (g->p.x + g->p.cx - 1));
+
+	write_index(g, 0x2B);
+	write_data(g, (g->p.y >> 8));
+	write_data(g, (uint8_t) g->p.y);
+	write_data(g, (g->p.y + g->p.cy - 1) >> 8);
+	write_data(g, (uint8_t) (g->p.y + g->p.cy - 1));
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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_index(g, 0x01); //software reset
+	chThdSleepMilliseconds(5);
+	write_index(g, 0x28);
+	// display off
+	//---------------------------------------------------------
+	// magic?
+	write_index(g, 0xcf);
+	write_data(g, 0x00);
+	write_data(g, 0x83);
+	write_data(g, 0x30);
+
+	write_index(g, 0xed);
+	write_data(g, 0x64);
+	write_data(g, 0x03);
+	write_data(g, 0x12);
+	write_data(g, 0x81);
+	write_index(g, 0xe8);
+	write_data(g, 0x85);
+	write_data(g, 0x01);
+	write_data(g, 0x79);
+	write_index(g, 0xcb);
+	write_data(g, 0x39);
+	write_data(g, 0x2c);
+	write_data(g, 0x00);
+	write_data(g, 0x34);
+	write_data(g, 0x02);
+	write_index(g, 0xf7);
+	write_data(g, 0x20);
+	write_index(g, 0xea);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	//------------power control------------------------------
+	write_index(g, 0xc0); //power control
+	write_data(g, 0x26);
+	write_index(g, 0xc1); //power control
+	write_data(g, 0x11);
+	//--------------VCOM
+	write_index(g, 0xc5); //vcom control
+	write_data(g, 0x35);//35
+	write_data(g, 0x3e);//3E
+	write_index(g, 0xc7); //vcom control
+	write_data(g, 0xbe); // 0x94
+	//------------memory access control------------------------
+	write_index(g, 0x36);
+	// memory access control
+	write_data(g, 0x48); //0048 my,mx,mv,ml,BGR,mh,0.0
+	write_index(g, 0x3a); // pixel format set
+	write_data(g, 0x55);//16bit /pixel
+	//----------------- frame rate------------------------------
+	write_index(g, 0xb1);
+	// frame rate
+	write_data(g, 0x00);
+	write_data(g, 0x1B); //70
+	//----------------Gamma---------------------------------
+	write_index(g, 0xf2); // 3Gamma Function Disable
+	write_data(g, 0x08);
+	write_index(g, 0x26);
+	write_data(g, 0x01); // gamma set 4 gamma curve 01/02/04/08
+
+	write_index(g, 0xE0); //positive gamma correction
+	write_data(g, 0x1f);
+	write_data(g, 0x1a);
+	write_data(g, 0x18);
+	write_data(g, 0x0a);
+	write_data(g, 0x0f);
+	write_data(g, 0x06);
+	write_data(g, 0x45);
+	write_data(g, 0x87);
+	write_data(g, 0x32);
+	write_data(g, 0x0a);
+	write_data(g, 0x07);
+	write_data(g, 0x02);
+	write_data(g, 0x07);
+	write_data(g, 0x05);
+	write_data(g, 0x00);
+	write_index(g, 0xE1); //negamma correction
+	write_data(g, 0x00);
+	write_data(g, 0x25);
+	write_data(g, 0x27);
+	write_data(g, 0x05);
+	write_data(g, 0x10);
+	write_data(g, 0x09);
+	write_data(g, 0x3a);
+	write_data(g, 0x78);
+	write_data(g, 0x4d);
+	write_data(g, 0x05);
+	write_data(g, 0x18);
+	write_data(g, 0x0d);
+	write_data(g, 0x38);
+	write_data(g, 0x3a);
+	write_data(g, 0x1f);
+	//--------------ddram ---------------------
+	write_index(g, 0x2a);
+	// column set
+	// size = 239
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0xEF);
+	write_index(g, 0x2b);
+	// page address set
+	// size = 319
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x01);
+	write_data(g, 0x3F);
+	// write_index(g, 0x34);
+	//write_index(g, 0x35);
+	// tearing effect off
+	// tearing effect on
+	// write_index(g, 0xb4); // display inversion
+	// write_data(g, 0x00);
+	write_index(g, 0xb7); //entry mode set
+	write_data(g, 0x07);
+	//-----------------display---------------------
+	write_index(g, 0xb6);
+	// display function control
+	write_data(g, 0x0a);
+	write_data(g, 0x82);
+	write_data(g, 0x27);
+	write_data(g, 0x00);
+	write_index(g, 0x11); //sleep out
+	chThdSleepMilliseconds(100);
+	write_index(g, 0x29); // display on
+	chThdSleepMilliseconds(100);
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		#if !GDISP_HARDWARE_STREAM_POS
+			set_cursor(g);
+		#endif
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data16(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			set_cursor(g);
+		}
+	#endif
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		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_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
+				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);
+				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				write_reg(g, 0x36, 0x80);	/* X and Y axes non-inverted */
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				write_reg(g, 0x36, 0xE0);	/* Invert X and Y axes */
+				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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.c b/drivers/gdisp/ILI9481/gdisp_lld.c
deleted file mode 100644
index 49e28b23..00000000
--- a/drivers/gdisp/ILI9481/gdisp_lld.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9481/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for
- * 			the ILI9481 and compatible HVGA display
- */
-
-#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_ILI9481
-#include "../drivers/gdisp/ILI9481/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_ILI9481.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		480
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		320
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// 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_index(g, reg); write_data(g, data); }
-#define write_reg2x16(g, reg, data1, data2)	{ write_index(g, reg); write_data(g, (data1)>>8); write_data(g, (uint8_t)(data1)); write_data(g, (data2)>>8); write_data(g, (uint8_t)(data2));}
-
-static void set_viewport(GDisplay* g) {
-	write_reg2x16(g, 0x2A, g->p.x, g->p.x + g->p.cx - 1);
-	write_reg2x16(g, 0x2B, g->p.y, g->p.y + g->p.cy - 1);
-	write_index(g, 0x2C);
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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);
-
-	/* Enable Access to all Manufacturer commands (0xB0 and higher opcodes) */
-	write_reg(g, 0xB0, 0x00);
-
-	/* Frame Memory Access and Interface Setting */
-	write_index(g, 0xB3);
-	write_data(g, 0x02);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0x10);
-
-	/* Display Mode and Frame Memory Write Mode Setting (B4h) */
-	/* Use internal clock for synchronization */
-	/* Use DBI interface (only DB0-17, no HSYNC, VSYNC or CLK) */
-	write_reg(g, 0xB4, 0x00);
-
-	/* Internal Backlight Control */
-/*	write_index(g, 0xB9); 	// PWM Settings for Brightness Control
-	write_data(g, 0x01);	// Disabled by default.
-	write_data(g, 0xFF);	// 0xFF = Max brightness
-	write_data(g, 0xFF);
-	write_data(g, 0x18); */
-
-	/* Panel Driving settings */
-	write_index(g, 0xC0);
-	write_data(g, 0x03);
-	write_data(g, 0x3B);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0x01);
-	write_data(g, 0x00);	/* NW */
-	write_data(g, 0x43);
-
-	/* Display timings in Operating Mode */
-	write_index(g, 0xC1);
-	write_data(g, 0x08);
-	write_data(g, 0x15);	/* CLOCK */
-	write_data(g, 0x08);
-	write_data(g, 0x08);
-
-	/* S/VCOM/Gate Driving timing setting */
-	write_index(g, 0xC4);
-	write_data(g, 0x15);
-	write_data(g, 0x03);
-	write_data(g, 0x03);
-	write_data(g, 0x01);
-
-	/* Interface Setting */
-	write_reg(g, 0xC6, 0x02);
-
-	/* Gamma Setting - should be changed if using a different panel */
-	write_index(g, 0xC8);
-	write_data(g, 0x0C);
-	write_data(g, 0x05);
-	write_data(g, 0x0A); /*0X12 */
-	write_data(g, 0x6B); /*0x7D */
-	write_data(g, 0x04);
-	write_data(g, 0x06); /*0x08 */
-	write_data(g, 0x15); /*0x0A */
-	write_data(g, 0x10);
-	write_data(g, 0x00);
-	write_data(g, 0x60); /*0x23 */
-
-	/* Address Mode setting */
-	write_reg(g, 0x36, 0x00);
-
-	/* Set Pixel Format = 16 bits per pixel */
-	/* The driver supports upto 24 bits per pixel, with dither */
-	write_reg(g, 0x3A, 0x55);
-
-	/* Exit Idle Mode */
-	write_index(g, 0x38);
-
-	/* Power Setting */
-	write_index(g, 0xD0);
-	write_data(g, 0x07);
-	write_data(g, 0x07); 	/* VCI = VCI1 */
-	write_data(g, 0x14);	/* VRH 0x1D */
-	write_data(g, 0xA2);	/* BT 0x06 */
-
-	/* VCOM Setting */
-	write_index(g, 0xD1);
-	write_data(g, 0x03);
-	write_data(g, 0x5A);	/* VCM  0x5A */
-	write_data(g, 0x10);	/* VDV */
-
-	/* Power Setting for Normal Mode  */
-	write_index(g, 0xD2);
-	write_data(g, 0x03);
-	write_data(g, 0x04);	/* 0x24  */
-	write_data(g, 0x04);
-
-	/* Exit Sleep Mode */
-	write_index(g, 0x11);
-	gfxSleepMilliseconds(150);
-
-	/* Display ON  */
-	write_index(g, 0x29);
-	gfxSleepMilliseconds(30);
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		setwritemode(g);
-		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:
-				acquire_bus(g);
-				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
-				release_bus(g);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
-				release_bus(g);
-				if (g->g.Powermode != powerSleep)
-					gdisp_lld_init();
-				break;
-			case powerSleep:
-				acquire_bus(g);
-				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
-				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);
-
-				write_reg(g, 0xC0, 0x03);
-				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
-
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-
-				write_reg(g, 0xC0, 0x02);
-				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
-
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-
-				write_reg(g, 0xC0, 0x06);
-				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
-
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-
-				write_reg(g, 0xC0, 0x07);
-				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
-
-				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:
-		//case GDISP_CONTROL_CONTRAST:
-        default:
-            return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/gdisp/ILI9481/gdisp_lld.mk b/drivers/gdisp/ILI9481/gdisp_lld.mk
index 6af4d1f8..8c971788 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld.mk
+++ b/drivers/gdisp/ILI9481/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/ILI9481
-GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9481/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c b/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
new file mode 100644
index 00000000..49e28b23
--- /dev/null
+++ b/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
@@ -0,0 +1,325 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ILI9481/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for
+ * 			the ILI9481 and compatible HVGA display
+ */
+
+#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_ILI9481
+#include "../drivers/gdisp/ILI9481/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ILI9481.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		480
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		320
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// 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_index(g, reg); write_data(g, data); }
+#define write_reg2x16(g, reg, data1, data2)	{ write_index(g, reg); write_data(g, (data1)>>8); write_data(g, (uint8_t)(data1)); write_data(g, (data2)>>8); write_data(g, (uint8_t)(data2));}
+
+static void set_viewport(GDisplay* g) {
+	write_reg2x16(g, 0x2A, g->p.x, g->p.x + g->p.cx - 1);
+	write_reg2x16(g, 0x2B, g->p.y, g->p.y + g->p.cy - 1);
+	write_index(g, 0x2C);
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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);
+
+	/* Enable Access to all Manufacturer commands (0xB0 and higher opcodes) */
+	write_reg(g, 0xB0, 0x00);
+
+	/* Frame Memory Access and Interface Setting */
+	write_index(g, 0xB3);
+	write_data(g, 0x02);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x10);
+
+	/* Display Mode and Frame Memory Write Mode Setting (B4h) */
+	/* Use internal clock for synchronization */
+	/* Use DBI interface (only DB0-17, no HSYNC, VSYNC or CLK) */
+	write_reg(g, 0xB4, 0x00);
+
+	/* Internal Backlight Control */
+/*	write_index(g, 0xB9); 	// PWM Settings for Brightness Control
+	write_data(g, 0x01);	// Disabled by default.
+	write_data(g, 0xFF);	// 0xFF = Max brightness
+	write_data(g, 0xFF);
+	write_data(g, 0x18); */
+
+	/* Panel Driving settings */
+	write_index(g, 0xC0);
+	write_data(g, 0x03);
+	write_data(g, 0x3B);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x01);
+	write_data(g, 0x00);	/* NW */
+	write_data(g, 0x43);
+
+	/* Display timings in Operating Mode */
+	write_index(g, 0xC1);
+	write_data(g, 0x08);
+	write_data(g, 0x15);	/* CLOCK */
+	write_data(g, 0x08);
+	write_data(g, 0x08);
+
+	/* S/VCOM/Gate Driving timing setting */
+	write_index(g, 0xC4);
+	write_data(g, 0x15);
+	write_data(g, 0x03);
+	write_data(g, 0x03);
+	write_data(g, 0x01);
+
+	/* Interface Setting */
+	write_reg(g, 0xC6, 0x02);
+
+	/* Gamma Setting - should be changed if using a different panel */
+	write_index(g, 0xC8);
+	write_data(g, 0x0C);
+	write_data(g, 0x05);
+	write_data(g, 0x0A); /*0X12 */
+	write_data(g, 0x6B); /*0x7D */
+	write_data(g, 0x04);
+	write_data(g, 0x06); /*0x08 */
+	write_data(g, 0x15); /*0x0A */
+	write_data(g, 0x10);
+	write_data(g, 0x00);
+	write_data(g, 0x60); /*0x23 */
+
+	/* Address Mode setting */
+	write_reg(g, 0x36, 0x00);
+
+	/* Set Pixel Format = 16 bits per pixel */
+	/* The driver supports upto 24 bits per pixel, with dither */
+	write_reg(g, 0x3A, 0x55);
+
+	/* Exit Idle Mode */
+	write_index(g, 0x38);
+
+	/* Power Setting */
+	write_index(g, 0xD0);
+	write_data(g, 0x07);
+	write_data(g, 0x07); 	/* VCI = VCI1 */
+	write_data(g, 0x14);	/* VRH 0x1D */
+	write_data(g, 0xA2);	/* BT 0x06 */
+
+	/* VCOM Setting */
+	write_index(g, 0xD1);
+	write_data(g, 0x03);
+	write_data(g, 0x5A);	/* VCM  0x5A */
+	write_data(g, 0x10);	/* VDV */
+
+	/* Power Setting for Normal Mode  */
+	write_index(g, 0xD2);
+	write_data(g, 0x03);
+	write_data(g, 0x04);	/* 0x24  */
+	write_data(g, 0x04);
+
+	/* Exit Sleep Mode */
+	write_index(g, 0x11);
+	gfxSleepMilliseconds(150);
+
+	/* Display ON  */
+	write_index(g, 0x29);
+	gfxSleepMilliseconds(30);
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		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:
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0000);	/* leave sleep mode */
+				release_bus(g);
+				if (g->g.Powermode != powerSleep)
+					gdisp_lld_init();
+				break;
+			case powerSleep:
+				acquire_bus(g);
+				write_reg(g, 0x0010, 0x0001);	/* enter sleep mode */
+				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);
+
+				write_reg(g, 0xC0, 0x03);
+				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
+
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+
+				write_reg(g, 0xC0, 0x02);
+				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
+
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+
+				write_reg(g, 0xC0, 0x06);
+				write_reg(g, 0x36, 0x00);	/* X and Y axes non-inverted */
+
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+
+				write_reg(g, 0xC0, 0x07);
+				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
+
+				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:
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
deleted file mode 100644
index d1086c46..00000000
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE12 display.
- */
-
-#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 GDISP_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_Nokia6610GE12
-#include "../drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_Nokia6610GE12.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#include "GE12.h"
-
-#define GDISP_SCAN_LINES			132
-#define GDISP_SLEEP_SIZE			32		/* Sleep mode window lines - this must be 32 on this controller */
-
-// Set parameters if they are not already set
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		130
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		130
-#endif
-#ifndef GDISP_RAM_X_OFFSET
-	#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
-#endif
-#ifndef GDISP_RAM_Y_OFFSET
-	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
-#endif
-#ifndef GDISP_SLEEP_POS
-	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2 & ~3)
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-// Use the priv pointer itself to save our color. This save allocating ram for it
-//	and works provided sizeof(color_t) <= sizeof(void *)
-#define savecolor(g)					(*(color_t *)&g->priv)
-
-#define GDISP_FLG_ODDBYTE				(GDISP_FLG_DRIVER<<0)
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// Some macros just to make reading the code easier
-#define delayms(ms)						gfxSleepMilliseconds(ms)
-#define write_data2(g, d1, d2)			{ write_data(g, d1); write_data(g, d2); }
-#define write_data3(g, d1, d2, d3)		{ write_data(g, d1); write_data(g, d2); write_data(g, d3); }
-#define write_reg(g, cmd, d1)			{ write_index(g, cmd); write_data(g, d1); }
-#define write_reg2(g, cmd, d1, d2)		{ write_index(g, cmd); write_data2(g, d1, d2); }
-#define write_reg3(g, cmd, d1, d2, d3)	{ write_index(g, cmd); write_data3(g, d1, d2, d3); }
-
-static inline void set_viewport(GDisplay* g) {
-	write_reg2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-	write_reg2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-	write_index(g, RAMWR);
-}
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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);
-	delayms(20);
-	setpin_reset(g, FALSE);
-	delayms(20);
-
-	acquire_bus(g);
-
-	write_index(g, SLEEPOUT);								// Sleep out
-	write_reg(g, COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
-	write_reg(g, MADCTL, 0x00);							// Memory access controller
-	write_reg(g, SETCON, 128*GDISP_INITIAL_CONTRAST/101-64);			// Write contrast
-	delayms(20);
-
-    // Finish Init
-    post_init_board(g);
-
-	release_bus(g);
-	
-	/* Turn on the back-light */
-	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
-
-	/* Initialise the GDISP structure to match */
-	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);
-		set_viewport(g);
-		g->flags &= ~GDISP_FLG_ODDBYTE;
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		if ((g->flags & GDISP_FLG_ODDBYTE)) {
-			// Write the pair of pixels to the display
-			write_data3(g, ((savecolor(g) >> 4) & 0xFF),
-					(((savecolor(g) << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
-					(g->p.color & 0xFF));
-			g->flags &= ~GDISP_FLG_ODDBYTE;
-		} else {
-			savecolor(g) = g->p.color;
-			g->flags |= GDISP_FLG_ODDBYTE;
-		}
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		if ((g->flags & GDISP_FLG_ODDBYTE)) {
-			write_data2(g, ((savecolor(g) >> 4) & 0xFF), ((savecolor(g) << 4) & 0xF0));
-			write_index(g, NOP);
-		}
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDisplay *g) {
-		/* The hardware is capable of supporting...
-		 * 	GDISP_CONTROL_POWER				- supported
-		 * 	GDISP_CONTROL_ORIENTATION		- supported
-		 * 	GDISP_CONTROL_BACKLIGHT			- supported
-		 * 	GDISP_CONTROL_CONTRAST			- supported
-		 */
-		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_index(g, SLEEPIN);
-				release_bus(g);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				write_index(g, SLEEPOUT);
-				delayms(20);
-				write_index(g, NORON);							// Set Normal mode (my)
-				release_bus(g);
-				break;
-			case powerSleep:
-				acquire_bus(g);
-				write_index(g, SLEEPOUT);
-				delayms(20);
-				write_reg2(g, PTLAR, GDISP_SLEEP_POS, GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)
-				write_index(g, PTLON);
-				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);
-				write_reg(g, MADCTL, 0x00);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-				write_reg(g, MADCTL, 0xA0);					// MY, MX, V, LAO, RGB, X, X, X
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				write_reg(g, MADCTL, 0xC0);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-				write_reg(g, MADCTL, 0x60);
-				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;
-			set_backlight(g, (unsigned)g->p.ptr);
-			g->g.Backlight = (unsigned)g->p.ptr;
-			return;
-		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
-			acquire_bus(g);
-			write_reg(g, SETCON,(unsigned)128*(unsigned)g->p.ptr/101-64);
-			release_bus(g);
-			g->g.Contrast = (unsigned)g->p.ptr;
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk b/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
index 892665d5..65781667 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12
-GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
new file mode 100644
index 00000000..d1086c46
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
@@ -0,0 +1,259 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE12 display.
+ */
+
+#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 GDISP_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_Nokia6610GE12
+#include "../drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_Nokia6610GE12.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#include "GE12.h"
+
+#define GDISP_SCAN_LINES			132
+#define GDISP_SLEEP_SIZE			32		/* Sleep mode window lines - this must be 32 on this controller */
+
+// Set parameters if they are not already set
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		130
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		130
+#endif
+#ifndef GDISP_RAM_X_OFFSET
+	#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_RAM_Y_OFFSET
+	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_SLEEP_POS
+	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2 & ~3)
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+// Use the priv pointer itself to save our color. This save allocating ram for it
+//	and works provided sizeof(color_t) <= sizeof(void *)
+#define savecolor(g)					(*(color_t *)&g->priv)
+
+#define GDISP_FLG_ODDBYTE				(GDISP_FLG_DRIVER<<0)
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some macros just to make reading the code easier
+#define delayms(ms)						gfxSleepMilliseconds(ms)
+#define write_data2(g, d1, d2)			{ write_data(g, d1); write_data(g, d2); }
+#define write_data3(g, d1, d2, d3)		{ write_data(g, d1); write_data(g, d2); write_data(g, d3); }
+#define write_reg(g, cmd, d1)			{ write_index(g, cmd); write_data(g, d1); }
+#define write_reg2(g, cmd, d1, d2)		{ write_index(g, cmd); write_data2(g, d1, d2); }
+#define write_reg3(g, cmd, d1, d2, d3)	{ write_index(g, cmd); write_data3(g, d1, d2, d3); }
+
+static inline void set_viewport(GDisplay* g) {
+	write_reg2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+	write_reg2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+	write_index(g, RAMWR);
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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);
+	delayms(20);
+	setpin_reset(g, FALSE);
+	delayms(20);
+
+	acquire_bus(g);
+
+	write_index(g, SLEEPOUT);								// Sleep out
+	write_reg(g, COLMOD, 0x03);							// Color Interface Pixel Format - 0x03 = 12 bits-per-pixel
+	write_reg(g, MADCTL, 0x00);							// Memory access controller
+	write_reg(g, SETCON, 128*GDISP_INITIAL_CONTRAST/101-64);			// Write contrast
+	delayms(20);
+
+    // Finish Init
+    post_init_board(g);
+
+	release_bus(g);
+	
+	/* Turn on the back-light */
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+
+	/* Initialise the GDISP structure to match */
+	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);
+		set_viewport(g);
+		g->flags &= ~GDISP_FLG_ODDBYTE;
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			// Write the pair of pixels to the display
+			write_data3(g, ((savecolor(g) >> 4) & 0xFF),
+					(((savecolor(g) << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
+					(g->p.color & 0xFF));
+			g->flags &= ~GDISP_FLG_ODDBYTE;
+		} else {
+			savecolor(g) = g->p.color;
+			g->flags |= GDISP_FLG_ODDBYTE;
+		}
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			write_data2(g, ((savecolor(g) >> 4) & 0xFF), ((savecolor(g) << 4) & 0xF0));
+			write_index(g, NOP);
+		}
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		/* The hardware is capable of supporting...
+		 * 	GDISP_CONTROL_POWER				- supported
+		 * 	GDISP_CONTROL_ORIENTATION		- supported
+		 * 	GDISP_CONTROL_BACKLIGHT			- supported
+		 * 	GDISP_CONTROL_CONTRAST			- supported
+		 */
+		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_index(g, SLEEPIN);
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_index(g, SLEEPOUT);
+				delayms(20);
+				write_index(g, NORON);							// Set Normal mode (my)
+				release_bus(g);
+				break;
+			case powerSleep:
+				acquire_bus(g);
+				write_index(g, SLEEPOUT);
+				delayms(20);
+				write_reg2(g, PTLAR, GDISP_SLEEP_POS, GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)
+				write_index(g, PTLON);
+				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);
+				write_reg(g, MADCTL, 0x00);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0xA0);					// MY, MX, V, LAO, RGB, X, X, X
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0xC0);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				write_reg(g, MADCTL, 0x60);
+				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;
+			set_backlight(g, (unsigned)g->p.ptr);
+			g->g.Backlight = (unsigned)g->p.ptr;
+			return;
+		case GDISP_CONTROL_CONTRAST:
+			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
+			acquire_bus(g);
+			write_reg(g, SETCON,(unsigned)128*(unsigned)g->p.ptr/101-64);
+			release_bus(g);
+			g->g.Contrast = (unsigned)g->p.ptr;
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
deleted file mode 100644
index e0cfb997..00000000
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ /dev/null
@@ -1,559 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE8 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-/**
- * This is for the EPSON (GE8) controller driving a Nokia6610 color LCD display.
- * Note that there is also a PHILIPS (GE12) controller for the same display that this code
- * does not support.
- *
- * The controller drives a 132x132 display but a 1 pixel surround is not visible
- * which gives a visible area of 130x130.
- *
- * This controller does not support reading back over the SPI interface.
- * Additionally, the Olimex board doesn't even connect the pin.
- *
- * The hardware is capable of doing full width vertical scrolls aligned
- * on a 4 line boundary however that is not sufficient to support general vertical scrolling.
- * We also can't manually do read/modify scrolling because we can't read in SPI mode.
- *
- * The controller has some quirkyness when operating in other than rotation 0 mode.
- * When any direction is decremented it starts at location 0 rather than the end of
- * the area. Whilst this can be handled when we know the specific operation (pixel, fill, blit)
- * it cannot be handled in a generic stream operation. So, when orientation support is turned
- * on (and needed) we use complex operation specific routines instead of simple streaming
- * routines. This has a (small) performance penalty and a significant code size penalty so
- * don't turn on orientation support unless you really need it.
- *
- * Some of the more modern controllers have a broken command set. If you have one of these
- * you will recognise it by the colors being off on anything drawn after an odd (as opposed to
- * even) pixel count area being drawn. If so then set GDISP_GE8_BROKEN_CONTROLLER to TRUE
- * on your gdisp_lld_board.h file. The price is that streaming calls that are completed
- * without exactly the window size write operations and where the number of write operations
- * is odd (rather than even), it will draw an extra pixel. If this is important to you, turn on
- * orientation support and the streaming operations will be emulated (as described above).
- */
-
-#if defined(GDISP_SCREEN_HEIGHT)
-	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
-	#undef GDISP_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_Nokia6610GE8
-#include "../drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_Nokia6610GE8.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#include "GE8.h"
-
-#define GDISP_SCAN_LINES			132
-
-// Set parameters if they are not already set
-#ifndef GDISP_GE8_BROKEN_CONTROLLER
-	#define GDISP_GE8_BROKEN_CONTROLLER		TRUE
-#endif
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		130
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		130
-#endif
-#ifndef GDISP_RAM_X_OFFSET
-	#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
-#endif
-#ifndef GDISP_RAM_Y_OFFSET
-	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
-#endif
-#ifndef GDISP_SLEEP_SIZE
-	#define GDISP_SLEEP_SIZE		32		/* Sleep mode window lines */
-#endif
-#ifndef GDISP_SLEEP_POS
-	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2)
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	60
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	typedef struct dvrPriv {
-		color_t			savecolor;
-		#if GDISP_GE8_BROKEN_CONTROLLER
-			color_t		firstcolor;
-		#endif
-	} dvrPriv;
-	#define PRIV		((dvrPriv *)g->priv)
-#endif
-
-#define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
-#define GDISP_FLG_RUNBYTE	(GDISP_FLG_DRIVER<<1)
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// Some macros just to make reading the code easier
-#define delayms(ms)							gfxSleepMilliseconds(ms)
-#define write_data2(g, d1, d2)				{ write_data(g, d1); write_data(g, d2); }
-#define write_data3(g, d1, d2, d3)			{ write_data(g, d1); write_data(g, d2); write_data(g, d3); }
-#define write_data4(g, d1, d2, d3, d4)		{ write_data(g, d1); write_data(g, d2); write_data(g, d3); write_data(g, d4); }
-#define write_cmd1(g, cmd, d1)				{ write_index(g, cmd); write_data(g, d1); }
-#define write_cmd2(g, cmd, d1, d2)			{ write_index(g, cmd); write_data2(g, d1, d2); }
-#define write_cmd3(g, cmd, d1, d2, d3)		{ write_index(g, cmd); write_data3(g, d1, d2, d3); }
-#define write_cmd4(g, cmd, d1, d2, d3, d4)	{ write_index(g, cmd); write_data4(g, d1, d2, d3, d4); }
-
-static inline void set_viewport(GDisplay* g) {
-	#if GDISP_NOKIA_ORIENTATION && GDISP_NEED_CONTROL
-		switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x);			// Column address set
-				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y);			// Page address set
-				break;
-			case GDISP_ROTATE_90:
-				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y);
-				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x);
-				break;
-			case GDISP_ROTATE_180:
-				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x);
-				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y);
-				break;
-			case GDISP_ROTATE_270:
-				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y);
-				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x);
-				break;
-		}
-	#else
-		write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
-		write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
-	#endif
-	write_index(g, RAMWR);
-}
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	#if GDISP_HARDWARE_STREAM_WRITE
-		g->priv = gfxAlloc(sizeof(dvrPriv));
-	#else
-		g->priv = 0;
-	#endif
-
-	// Initialise the board interface
-	init_board(g);
-
-	// Hardware reset
-	setpin_reset(g, TRUE);
-	delayms(20);
-	setpin_reset(g, FALSE);
-	delayms(20);
-
-	// Get the bus for the following initialisation commands
-	acquire_bus(g);
-	
-	write_cmd4(g, DISCTL, 0x00, GDISP_SCAN_LINES/4-1, 0x0A, 0x00);	// Display control - How the controller drives the LCD
-															// P1: 0x00 = 2 divisions, switching period=8 (default)
-															// P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
-															// P3: 0x0A = standard inverse highlight, inversion every frame
-															// P4: 0x00 = dispersion on
-	write_cmd1(g, COMSCN, 0x01);							// COM scan - How the LCD is connected to the controller
-															// P1: 0x01 = Scan 1->80, 160<-81
-	write_index(g, OSCON);									// Internal oscillator ON
-	write_index(g, SLPOUT);									// Sleep out
-	write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-	write_cmd3(g, DATCTL, 0x00, 0x00, 0x02);				// Data control
-															// P1: 0x00 = page address normal, column address normal, address scan in column direction
-															// P2: 0x00 = RGB sequence (default value)
-															// P3: 0x02 = 4 bits per colour (Type A)
-	write_cmd2(g, VOLCTR, 64*GDISP_INITIAL_CONTRAST/101, 0x03);	// Voltage control (contrast setting)
-															// P1 = Contrast (0..63)
-															// P2 = 3 resistance ratio (only value that works)
-	delayms(100);										// Allow power supply to stabilise
-	write_index(g, DISON);									// Turn on the display
-
-    // Finish Init
-    post_init_board(g);
-
-	// Release the bus
-	release_bus(g);
-	
-	/* Turn on the back-light */
-	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
-
-	/* Initialise the GDISP structure to match */
-	g->g.Orientation = GDISP_ROTATE_0;
-	g->g.Powermode = powerOn;
-	g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
-	g->g.Contrast = GDISP_INITIAL_CONTRAST;
-	g->g.Width = GDISP_SCREEN_WIDTH;
-	g->g.Height = GDISP_SCREEN_HEIGHT;
-	return TRUE;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		#if GDISP_GE8_BROKEN_CONTROLLER
-			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
-				PRIV->firstcolor = g->p.color;
-				g->flags |= GDISP_FLG_RUNBYTE;
-			}
-		#endif
-		if ((g->flags & GDISP_FLG_ODDBYTE)) {
-			// Write the pair of pixels to the display
-			write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
-					(((PRIV->savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
-					(g->p.color & 0xFF));
-			g->flags &= ~GDISP_FLG_ODDBYTE;
-		} else {
-			PRIV->savecolor = g->p.color;
-			g->flags |= GDISP_FLG_ODDBYTE;
-		}
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		if ((g->flags & GDISP_FLG_ODDBYTE)) {
-			#if GDISP_GE8_BROKEN_CONTROLLER
-				/**
-				 * We have a real problem here - we need to write a singular pixel
-				 * Methods that are supposed to work...
-				 * 1/ Write the pixel (2 bytes) and then send a NOP command. This doesn't work, the pixel doesn't get written
-				 * 		and it is maintained in the latch where it causes problems for the next window.
-				 * 2/ Just write a dummy extra pixel as stuff beyond the window gets discarded. This doesn't work as contrary to
-				 * 		the documentation the buffer wraps and the first pixel gets overwritten.
-				 * 3/ Put the controller in 16 bits per pixel Type B mode where each pixel is performed by writing two bytes. This
-				 * 		also doesn't work as the controller refuses to enter Type B mode (it stays in Type A mode).
-				 *
-				 * These methods might work on some controllers - just not on the one of the broken versions.
-				 *
-				 * For these broken controllers:
-				 * 	We know we can wrap to the first byte (just overprint it) if we are at the end of the stream area.
-				 * 	If not, we need to create a one pixel by one pixel window to fix this - Uuch. Fortunately this should only happen if the
-				 * 	user application uses the streaming calls and then terminates the stream early or after buffer wrap.
-				 * 	Since this is such an unlikely situation we just don't handle it.
-				 */
-				write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
-						(((PRIV->savecolor << 4) & 0xF0)|((PRIV->firstcolor >> 8) & 0x0F)),
-						(PRIV->firstcolor & 0xFF));
-			#else
-				write_data2(g, ((PRIV->savecolor >> 4) & 0xFF), ((PRIV->savecolor << 4) & 0xF0));
-				write_index(g, NOP);
-			#endif
-		}
-
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_DRAWPIXEL
-	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		write_data3(g, 0, (g->p.color>>8) & 0x0F, g->p.color & 0xFF);
-		release_bus(g);
-	}
-#endif
-
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_FILLS
-	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
-		unsigned tuples;
-
-		tuples = (g->p.cx*g->p.cy+1)>>1;	// With an odd sized area we over-print by one pixel.
-											// This extra pixel overwrites the first pixel (harmless as it is the same colour)
-
-		acquire_bus(g);
-		set_viewport(g);
-		while(tuples--)
-			write_data3(g, ((g->p.color >> 4) & 0xFF), (((g->p.color << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS
-	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
-		coord_t			lg, x, y;
-		color_t			c1, c2;
-		unsigned		tuples;
-		const pixel_t	*buffer;
-		#if GDISP_PACKED_PIXELS
-			unsigned		pnum, pstart;
-			const uint8_t	*p;
-		#else
-			const pixel_t	*p;
-		#endif
-
-		tuples = (g->p.cx * g->p.cy + 1)>>1;
-		buffer = (const pixel_t *)g->p.ptr;
-
-		/* Set up the data window to transfer */
-		acquire_bus(g);
-		set_viewport(g);
-
-		/* to surpress compiler warnings */
-		x = 0;
-		y = 0;
-
-		/*
-		 * Due to the way the Nokia6610 handles a decrementing column or page,
-		 * we have to make adjustments as to where it is actually drawing from in the bitmap.
-		 * For example, for 90 degree rotation the column is decremented on each
-		 * memory write. The controller always starts with column 0 and then decrements
-		 * to column cx-1, cx-2 etc. We therefore have to write-out the last bitmap line first.
-		 */
-		switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:		x = 0;			y = 0;			break;
-		case GDISP_ROTATE_90:		x = g->p.cx-1;	y = 0;			break;
-		case GDISP_ROTATE_180:		x = g->p.cx-1;	y = g->p.cy-1;	break;
-		case GDISP_ROTATE_270:		x = 0;			y = g->p.cy-1;	break;
-		}
-
-		#if !GDISP_PACKED_PIXELS
-			// Although this controller uses packed pixels we support unpacked pixel
-			//  formats in this blit by packing the data as we feed it to the controller.
-
-			lg = g->p.x2 - g->p.cx;					// The buffer gap between lines
-			buffer += g->p.y1 * g->p.x2 + g->p.x1;	// The buffer start position
-			p = buffer + g->p.x2*y + x;				// Adjustment for controller craziness
-
-			while(tuples--) {
-				/* Get a pixel */
-				c1 = *p++;
-
-				/* Check for line or buffer wrapping */
-				if (++x >= g->p.cx) {
-					x = 0;
-					p += lg;
-					if (++y >= g->p.cy) {
-						y = 0;
-						p = buffer;
-					}
-				}
-
-				/* Get the next pixel */
-				c2 = *p++;
-
-				/* Check for line or buffer wrapping */
-				if (++x >= g->p.cx) {
-					x = 0;
-					p += lg;
-					if (++y >= g->p.cy) {
-						y = 0;
-						p = buffer;
-					}
-				}
-
-				/* Write the pair of pixels to the display */
-				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
-			}
-
-		#else
-
-			// Although this controller uses packed pixels, we may have to feed it into
-			//  the controller with different packing to the source bitmap
-			// There are 2 pixels per 3 bytes
-
-			#if !GDISP_PACKED_LINES
-				srccx = (g->p.x2 + 1) & ~1;
-			#endif
-			pstart = g->p.y1 * g->p.x2 + g->p.x1;										// The starting pixel number
-			buffer = (const pixel_t)(((const uint8_t *)buffer) + ((pstart>>1) * 3));	// The buffer start position
-			lg = ((g->p.x2-g->p.cx)>>1)*3;												// The buffer gap between lines
-			pnum = pstart + g->p.x2*y + x;												// Adjustment for controller craziness
-			p = ((const uint8_t *)buffer) + (((g->p.x2*y + x)>>1)*3);					// Adjustment for controller craziness
-
-			while (tuples--) {
-				/* Get a pixel */
-				switch(pnum++ & 1) {
-				case 0:		c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);				break;
-				case 1:		c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	p += 3;		break;
-				}
-
-				/* Check for line or buffer wrapping */
-				if (++x >= g->p.cx) {
-					x = 0;
-					p += lg;
-					pnum += g->p.x2 - g->p.cx;
-					if (++y >= g->p.cy) {
-						y = 0;
-						p = (const uint8_t *)buffer;
-						pnum = pstart;
-					}
-				}
-
-				/* Get the next pixel */
-				switch(pnum++ & 1) {
-				case 0:		c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);				break;
-				case 1:		c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	p += 3;		break;
-				}
-
-				/* Check for line or buffer wrapping */
-				if (++x >= g->p.cx) {
-					x = 0;
-					p += lg;
-					pnum += g->p.x2 - g->p.cx;
-					if (++y >= g->p.cy) {
-						y = 0;
-						p = (const uint8_t *)buffer;
-						pnum = pstart;
-					}
-				}
-
-				/* Write the pair of pixels to the display */
-				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
-			}
-		#endif
-
-		/* All done */
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDisplay *g) {
-		/* The hardware is capable of supporting...
-		 * 	GDISP_CONTROL_POWER				- supported
-		 * 	GDISP_CONTROL_ORIENTATION		- supported
-		 * 	GDISP_CONTROL_BACKLIGHT			- supported
-		 * 	GDISP_CONTROL_CONTRAST			- supported
-		 */
-		switch(g->p.x) {
-		case GDISP_CONTROL_POWER:
-			if (g->g.Powermode == (powermode_t)g->p.ptr)
-				return;
-			acquire_bus(g);
-			switch((powermode_t)g->p.ptr) {
-				case powerOff:
-					set_backlight(g, 0);									// Turn off the backlight
-					write_index(g, DISOFF);									// Turn off the display
-					write_cmd1(g, PWRCTR, 0x00);							// Power control - all off
-					write_index(g, SLPIN);									// Sleep in
-					write_index(g, OSCOFF);									// Internal oscillator off
-					break;
-				case powerOn:
-					write_index(g, OSCON);									// Internal oscillator on
-					write_index(g, SLPOUT);									// Sleep out
-					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
-					delayms(100);										// Allow power supply to stabilise
-					write_index(g, DISON);									// Turn on the display
-					write_index(g, PTLOUT);									// Remove sleep window
-					set_backlight(g, g->g.Backlight);						// Turn on the backlight
-					break;
-				case powerSleep:
-					write_index(g, OSCON);									// Internal oscillator on
-					write_index(g, SLPOUT);									// Sleep out
-					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
-					delayms(100);										// Allow power supply to stabilise
-					write_index(g, DISON);									// Turn on the display
-					write_cmd2(g, PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
-					set_backlight(g, g->g.Backlight);						// Turn on the backlight
-					break;
-				case powerDeepSleep:
-					write_index(g, OSCON);									// Internal oscillator on
-					write_index(g, SLPOUT);									// Sleep out
-					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
-					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
-					delayms(100);										// Allow power supply to stabilise
-					write_index(g, DISON);									// Turn on the display
-					write_cmd2(g, PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
-					set_backlight(g, 0);									// Turn off the backlight
-					break;
-				default:
-					release_bus(g);
-					return;
-			}
-			release_bus(g);
-			g->g.Powermode = (powermode_t)g->p.ptr;
-			return;
-		#if GDISP_NOKIA_ORIENTATION
-			case GDISP_CONTROL_ORIENTATION:
-				if (g->g.Orientation == (orientation_t)g->p.ptr)
-					return;
-				acquire_bus(g);
-				switch((orientation_t)g->p.ptr) {
-				case GDISP_ROTATE_0:
-					write_cmd3(g, DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_90:
-					write_cmd3(g, DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
-					g->g.Height = GDISP_SCREEN_WIDTH;
-					g->g.Width = GDISP_SCREEN_HEIGHT;
-					break;
-				case GDISP_ROTATE_180:
-					write_cmd3(g, DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					break;
-				case GDISP_ROTATE_270:
-					write_cmd3(g, DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
-					g->g.Height = GDISP_SCREEN_WIDTH;
-					g->g.Width = GDISP_SCREEN_HEIGHT;
-					break;
-				default:
-					release_bus(g);
-					return;
-				}
-				release_bus(g);
-				g->g.Orientation = (orientation_t)g->p.ptr;
-				return;
-		#endif
-		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;
-		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
-			acquire_bus(g);
-			write_cmd2(g, VOLCTR, 64*(unsigned)g->p.ptr/101, 0x03);
-			release_bus(g);
-			g->g.Contrast = (unsigned)g->p.ptr;
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk b/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
index 28c57fd6..a61948b3 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8
-GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
new file mode 100644
index 00000000..e0cfb997
--- /dev/null
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
@@ -0,0 +1,559 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE8 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+/**
+ * This is for the EPSON (GE8) controller driving a Nokia6610 color LCD display.
+ * Note that there is also a PHILIPS (GE12) controller for the same display that this code
+ * does not support.
+ *
+ * The controller drives a 132x132 display but a 1 pixel surround is not visible
+ * which gives a visible area of 130x130.
+ *
+ * This controller does not support reading back over the SPI interface.
+ * Additionally, the Olimex board doesn't even connect the pin.
+ *
+ * The hardware is capable of doing full width vertical scrolls aligned
+ * on a 4 line boundary however that is not sufficient to support general vertical scrolling.
+ * We also can't manually do read/modify scrolling because we can't read in SPI mode.
+ *
+ * The controller has some quirkyness when operating in other than rotation 0 mode.
+ * When any direction is decremented it starts at location 0 rather than the end of
+ * the area. Whilst this can be handled when we know the specific operation (pixel, fill, blit)
+ * it cannot be handled in a generic stream operation. So, when orientation support is turned
+ * on (and needed) we use complex operation specific routines instead of simple streaming
+ * routines. This has a (small) performance penalty and a significant code size penalty so
+ * don't turn on orientation support unless you really need it.
+ *
+ * Some of the more modern controllers have a broken command set. If you have one of these
+ * you will recognise it by the colors being off on anything drawn after an odd (as opposed to
+ * even) pixel count area being drawn. If so then set GDISP_GE8_BROKEN_CONTROLLER to TRUE
+ * on your gdisp_lld_board.h file. The price is that streaming calls that are completed
+ * without exactly the window size write operations and where the number of write operations
+ * is odd (rather than even), it will draw an extra pixel. If this is important to you, turn on
+ * orientation support and the streaming operations will be emulated (as described above).
+ */
+
+#if defined(GDISP_SCREEN_HEIGHT)
+	#warning "GDISP: This low level driver does not support setting a screen size. It is being ignored."
+	#undef GDISP_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_Nokia6610GE8
+#include "../drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_Nokia6610GE8.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#include "GE8.h"
+
+#define GDISP_SCAN_LINES			132
+
+// Set parameters if they are not already set
+#ifndef GDISP_GE8_BROKEN_CONTROLLER
+	#define GDISP_GE8_BROKEN_CONTROLLER		TRUE
+#endif
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		130
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		130
+#endif
+#ifndef GDISP_RAM_X_OFFSET
+	#define GDISP_RAM_X_OFFSET		0		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_RAM_Y_OFFSET
+	#define GDISP_RAM_Y_OFFSET		2		/* Offset in RAM of visible area */
+#endif
+#ifndef GDISP_SLEEP_SIZE
+	#define GDISP_SLEEP_SIZE		32		/* Sleep mode window lines */
+#endif
+#ifndef GDISP_SLEEP_POS
+	#define GDISP_SLEEP_POS			((GDISP_SCAN_LINES-GDISP_SLEEP_SIZE)/2)
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	60
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	typedef struct dvrPriv {
+		color_t			savecolor;
+		#if GDISP_GE8_BROKEN_CONTROLLER
+			color_t		firstcolor;
+		#endif
+	} dvrPriv;
+	#define PRIV		((dvrPriv *)g->priv)
+#endif
+
+#define GDISP_FLG_ODDBYTE	(GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_RUNBYTE	(GDISP_FLG_DRIVER<<1)
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some macros just to make reading the code easier
+#define delayms(ms)							gfxSleepMilliseconds(ms)
+#define write_data2(g, d1, d2)				{ write_data(g, d1); write_data(g, d2); }
+#define write_data3(g, d1, d2, d3)			{ write_data(g, d1); write_data(g, d2); write_data(g, d3); }
+#define write_data4(g, d1, d2, d3, d4)		{ write_data(g, d1); write_data(g, d2); write_data(g, d3); write_data(g, d4); }
+#define write_cmd1(g, cmd, d1)				{ write_index(g, cmd); write_data(g, d1); }
+#define write_cmd2(g, cmd, d1, d2)			{ write_index(g, cmd); write_data2(g, d1, d2); }
+#define write_cmd3(g, cmd, d1, d2, d3)		{ write_index(g, cmd); write_data3(g, d1, d2, d3); }
+#define write_cmd4(g, cmd, d1, d2, d3, d4)	{ write_index(g, cmd); write_data4(g, d1, d2, d3, d4); }
+
+static inline void set_viewport(GDisplay* g) {
+	#if GDISP_NOKIA_ORIENTATION && GDISP_NEED_CONTROL
+		switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x);			// Column address set
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y);			// Page address set
+				break;
+			case GDISP_ROTATE_90:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.y, GDISP_RAM_X_OFFSET+g->p.y);
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_Y_OFFSET-1+g->g.Width-g->p.x);
+				break;
+			case GDISP_ROTATE_180:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x, GDISP_RAM_X_OFFSET-1+g->g.Width-g->p.x);
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_Y_OFFSET-1+g->g.Height-g->p.y);
+				break;
+			case GDISP_ROTATE_270:
+				write_cmd2(g, CASET, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y, GDISP_RAM_X_OFFSET-1+g->g.Height-g->p.y);
+				write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.x, GDISP_RAM_Y_OFFSET+g->p.x);
+				break;
+		}
+	#else
+		write_cmd2(g, CASET, GDISP_RAM_X_OFFSET+g->p.x, GDISP_RAM_X_OFFSET+g->p.x+g->p.cx-1);			// Column address set
+		write_cmd2(g, PASET, GDISP_RAM_Y_OFFSET+g->p.y, GDISP_RAM_Y_OFFSET+g->p.y+g->p.cy-1);			// Page address set
+	#endif
+	write_index(g, RAMWR);
+}
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	#if GDISP_HARDWARE_STREAM_WRITE
+		g->priv = gfxAlloc(sizeof(dvrPriv));
+	#else
+		g->priv = 0;
+	#endif
+
+	// Initialise the board interface
+	init_board(g);
+
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	delayms(20);
+	setpin_reset(g, FALSE);
+	delayms(20);
+
+	// Get the bus for the following initialisation commands
+	acquire_bus(g);
+	
+	write_cmd4(g, DISCTL, 0x00, GDISP_SCAN_LINES/4-1, 0x0A, 0x00);	// Display control - How the controller drives the LCD
+															// P1: 0x00 = 2 divisions, switching period=8 (default)
+															// P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
+															// P3: 0x0A = standard inverse highlight, inversion every frame
+															// P4: 0x00 = dispersion on
+	write_cmd1(g, COMSCN, 0x01);							// COM scan - How the LCD is connected to the controller
+															// P1: 0x01 = Scan 1->80, 160<-81
+	write_index(g, OSCON);									// Internal oscillator ON
+	write_index(g, SLPOUT);									// Sleep out
+	write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+	write_cmd3(g, DATCTL, 0x00, 0x00, 0x02);				// Data control
+															// P1: 0x00 = page address normal, column address normal, address scan in column direction
+															// P2: 0x00 = RGB sequence (default value)
+															// P3: 0x02 = 4 bits per colour (Type A)
+	write_cmd2(g, VOLCTR, 64*GDISP_INITIAL_CONTRAST/101, 0x03);	// Voltage control (contrast setting)
+															// P1 = Contrast (0..63)
+															// P2 = 3 resistance ratio (only value that works)
+	delayms(100);										// Allow power supply to stabilise
+	write_index(g, DISON);									// Turn on the display
+
+    // Finish Init
+    post_init_board(g);
+
+	// Release the bus
+	release_bus(g);
+	
+	/* Turn on the back-light */
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+
+	/* Initialise the GDISP structure to match */
+	g->g.Orientation = GDISP_ROTATE_0;
+	g->g.Powermode = powerOn;
+	g->g.Backlight = GDISP_INITIAL_BACKLIGHT;
+	g->g.Contrast = GDISP_INITIAL_CONTRAST;
+	g->g.Width = GDISP_SCREEN_WIDTH;
+	g->g.Height = GDISP_SCREEN_HEIGHT;
+	return TRUE;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		#if GDISP_GE8_BROKEN_CONTROLLER
+			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
+				PRIV->firstcolor = g->p.color;
+				g->flags |= GDISP_FLG_RUNBYTE;
+			}
+		#endif
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			// Write the pair of pixels to the display
+			write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
+					(((PRIV->savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
+					(g->p.color & 0xFF));
+			g->flags &= ~GDISP_FLG_ODDBYTE;
+		} else {
+			PRIV->savecolor = g->p.color;
+			g->flags |= GDISP_FLG_ODDBYTE;
+		}
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		if ((g->flags & GDISP_FLG_ODDBYTE)) {
+			#if GDISP_GE8_BROKEN_CONTROLLER
+				/**
+				 * We have a real problem here - we need to write a singular pixel
+				 * Methods that are supposed to work...
+				 * 1/ Write the pixel (2 bytes) and then send a NOP command. This doesn't work, the pixel doesn't get written
+				 * 		and it is maintained in the latch where it causes problems for the next window.
+				 * 2/ Just write a dummy extra pixel as stuff beyond the window gets discarded. This doesn't work as contrary to
+				 * 		the documentation the buffer wraps and the first pixel gets overwritten.
+				 * 3/ Put the controller in 16 bits per pixel Type B mode where each pixel is performed by writing two bytes. This
+				 * 		also doesn't work as the controller refuses to enter Type B mode (it stays in Type A mode).
+				 *
+				 * These methods might work on some controllers - just not on the one of the broken versions.
+				 *
+				 * For these broken controllers:
+				 * 	We know we can wrap to the first byte (just overprint it) if we are at the end of the stream area.
+				 * 	If not, we need to create a one pixel by one pixel window to fix this - Uuch. Fortunately this should only happen if the
+				 * 	user application uses the streaming calls and then terminates the stream early or after buffer wrap.
+				 * 	Since this is such an unlikely situation we just don't handle it.
+				 */
+				write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
+						(((PRIV->savecolor << 4) & 0xF0)|((PRIV->firstcolor >> 8) & 0x0F)),
+						(PRIV->firstcolor & 0xFF));
+			#else
+				write_data2(g, ((PRIV->savecolor >> 4) & 0xFF), ((PRIV->savecolor << 4) & 0xF0));
+				write_index(g, NOP);
+			#endif
+		}
+
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_DRAWPIXEL
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		write_data3(g, 0, (g->p.color>>8) & 0x0F, g->p.color & 0xFF);
+		release_bus(g);
+	}
+#endif
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_FILLS
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		unsigned tuples;
+
+		tuples = (g->p.cx*g->p.cy+1)>>1;	// With an odd sized area we over-print by one pixel.
+											// This extra pixel overwrites the first pixel (harmless as it is the same colour)
+
+		acquire_bus(g);
+		set_viewport(g);
+		while(tuples--)
+			write_data3(g, ((g->p.color >> 4) & 0xFF), (((g->p.color << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_BITFILLS
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
+		coord_t			lg, x, y;
+		color_t			c1, c2;
+		unsigned		tuples;
+		const pixel_t	*buffer;
+		#if GDISP_PACKED_PIXELS
+			unsigned		pnum, pstart;
+			const uint8_t	*p;
+		#else
+			const pixel_t	*p;
+		#endif
+
+		tuples = (g->p.cx * g->p.cy + 1)>>1;
+		buffer = (const pixel_t *)g->p.ptr;
+
+		/* Set up the data window to transfer */
+		acquire_bus(g);
+		set_viewport(g);
+
+		/* to surpress compiler warnings */
+		x = 0;
+		y = 0;
+
+		/*
+		 * Due to the way the Nokia6610 handles a decrementing column or page,
+		 * we have to make adjustments as to where it is actually drawing from in the bitmap.
+		 * For example, for 90 degree rotation the column is decremented on each
+		 * memory write. The controller always starts with column 0 and then decrements
+		 * to column cx-1, cx-2 etc. We therefore have to write-out the last bitmap line first.
+		 */
+		switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:		x = 0;			y = 0;			break;
+		case GDISP_ROTATE_90:		x = g->p.cx-1;	y = 0;			break;
+		case GDISP_ROTATE_180:		x = g->p.cx-1;	y = g->p.cy-1;	break;
+		case GDISP_ROTATE_270:		x = 0;			y = g->p.cy-1;	break;
+		}
+
+		#if !GDISP_PACKED_PIXELS
+			// Although this controller uses packed pixels we support unpacked pixel
+			//  formats in this blit by packing the data as we feed it to the controller.
+
+			lg = g->p.x2 - g->p.cx;					// The buffer gap between lines
+			buffer += g->p.y1 * g->p.x2 + g->p.x1;	// The buffer start position
+			p = buffer + g->p.x2*y + x;				// Adjustment for controller craziness
+
+			while(tuples--) {
+				/* Get a pixel */
+				c1 = *p++;
+
+				/* Check for line or buffer wrapping */
+				if (++x >= g->p.cx) {
+					x = 0;
+					p += lg;
+					if (++y >= g->p.cy) {
+						y = 0;
+						p = buffer;
+					}
+				}
+
+				/* Get the next pixel */
+				c2 = *p++;
+
+				/* Check for line or buffer wrapping */
+				if (++x >= g->p.cx) {
+					x = 0;
+					p += lg;
+					if (++y >= g->p.cy) {
+						y = 0;
+						p = buffer;
+					}
+				}
+
+				/* Write the pair of pixels to the display */
+				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+			}
+
+		#else
+
+			// Although this controller uses packed pixels, we may have to feed it into
+			//  the controller with different packing to the source bitmap
+			// There are 2 pixels per 3 bytes
+
+			#if !GDISP_PACKED_LINES
+				srccx = (g->p.x2 + 1) & ~1;
+			#endif
+			pstart = g->p.y1 * g->p.x2 + g->p.x1;										// The starting pixel number
+			buffer = (const pixel_t)(((const uint8_t *)buffer) + ((pstart>>1) * 3));	// The buffer start position
+			lg = ((g->p.x2-g->p.cx)>>1)*3;												// The buffer gap between lines
+			pnum = pstart + g->p.x2*y + x;												// Adjustment for controller craziness
+			p = ((const uint8_t *)buffer) + (((g->p.x2*y + x)>>1)*3);					// Adjustment for controller craziness
+
+			while (tuples--) {
+				/* Get a pixel */
+				switch(pnum++ & 1) {
+				case 0:		c1 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);				break;
+				case 1:		c1 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	p += 3;		break;
+				}
+
+				/* Check for line or buffer wrapping */
+				if (++x >= g->p.cx) {
+					x = 0;
+					p += lg;
+					pnum += g->p.x2 - g->p.cx;
+					if (++y >= g->p.cy) {
+						y = 0;
+						p = (const uint8_t *)buffer;
+						pnum = pstart;
+					}
+				}
+
+				/* Get the next pixel */
+				switch(pnum++ & 1) {
+				case 0:		c2 = (((color_t)p[0]) << 4)|(((color_t)p[1])>>4);				break;
+				case 1:		c2 = (((color_t)p[1]&0x0F) << 8)|((color_t)p[1]);	p += 3;		break;
+				}
+
+				/* Check for line or buffer wrapping */
+				if (++x >= g->p.cx) {
+					x = 0;
+					p += lg;
+					pnum += g->p.x2 - g->p.cx;
+					if (++y >= g->p.cy) {
+						y = 0;
+						p = (const uint8_t *)buffer;
+						pnum = pstart;
+					}
+				}
+
+				/* Write the pair of pixels to the display */
+				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
+			}
+		#endif
+
+		/* All done */
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		/* The hardware is capable of supporting...
+		 * 	GDISP_CONTROL_POWER				- supported
+		 * 	GDISP_CONTROL_ORIENTATION		- supported
+		 * 	GDISP_CONTROL_BACKLIGHT			- supported
+		 * 	GDISP_CONTROL_CONTRAST			- supported
+		 */
+		switch(g->p.x) {
+		case GDISP_CONTROL_POWER:
+			if (g->g.Powermode == (powermode_t)g->p.ptr)
+				return;
+			acquire_bus(g);
+			switch((powermode_t)g->p.ptr) {
+				case powerOff:
+					set_backlight(g, 0);									// Turn off the backlight
+					write_index(g, DISOFF);									// Turn off the display
+					write_cmd1(g, PWRCTR, 0x00);							// Power control - all off
+					write_index(g, SLPIN);									// Sleep in
+					write_index(g, OSCOFF);									// Internal oscillator off
+					break;
+				case powerOn:
+					write_index(g, OSCON);									// Internal oscillator on
+					write_index(g, SLPOUT);									// Sleep out
+					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
+					delayms(100);										// Allow power supply to stabilise
+					write_index(g, DISON);									// Turn on the display
+					write_index(g, PTLOUT);									// Remove sleep window
+					set_backlight(g, g->g.Backlight);						// Turn on the backlight
+					break;
+				case powerSleep:
+					write_index(g, OSCON);									// Internal oscillator on
+					write_index(g, SLPOUT);									// Sleep out
+					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
+					delayms(100);										// Allow power supply to stabilise
+					write_index(g, DISON);									// Turn on the display
+					write_cmd2(g, PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
+					set_backlight(g, g->g.Backlight);						// Turn on the backlight
+					break;
+				case powerDeepSleep:
+					write_index(g, OSCON);									// Internal oscillator on
+					write_index(g, SLPOUT);									// Sleep out
+					write_cmd1(g, PWRCTR, 0x0F);							// Power control - reference voltage regulator on, circuit voltage follower on, BOOST ON
+					write_cmd2(g, VOLCTR, g->g.Contrast, 0x03);			// Voltage control (contrast setting)
+					delayms(100);										// Allow power supply to stabilise
+					write_index(g, DISON);									// Turn on the display
+					write_cmd2(g, PTLIN, GDISP_SLEEP_POS/4, (GDISP_SLEEP_POS+GDISP_SLEEP_SIZE)/4);	// Sleep Window
+					set_backlight(g, 0);									// Turn off the backlight
+					break;
+				default:
+					release_bus(g);
+					return;
+			}
+			release_bus(g);
+			g->g.Powermode = (powermode_t)g->p.ptr;
+			return;
+		#if GDISP_NOKIA_ORIENTATION
+			case GDISP_CONTROL_ORIENTATION:
+				if (g->g.Orientation == (orientation_t)g->p.ptr)
+					return;
+				acquire_bus(g);
+				switch((orientation_t)g->p.ptr) {
+				case GDISP_ROTATE_0:
+					write_cmd3(g, DATCTL, 0x00, 0x00, 0x02);	// P1: page normal, column normal, scan in column direction
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+				case GDISP_ROTATE_90:
+					write_cmd3(g, DATCTL, 0x05, 0x00, 0x02);	// P1: page reverse, column normal, scan in page direction
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+				case GDISP_ROTATE_180:
+					write_cmd3(g, DATCTL, 0x03, 0x00, 0x02);	// P1: page reverse, column reverse, scan in column direction
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					break;
+				case GDISP_ROTATE_270:
+					write_cmd3(g, DATCTL, 0x06, 0x00, 0x02);	// P1: page normal, column reverse, scan in page direction
+					g->g.Height = GDISP_SCREEN_WIDTH;
+					g->g.Width = GDISP_SCREEN_HEIGHT;
+					break;
+				default:
+					release_bus(g);
+					return;
+				}
+				release_bus(g);
+				g->g.Orientation = (orientation_t)g->p.ptr;
+				return;
+		#endif
+		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;
+		case GDISP_CONTROL_CONTRAST:
+			if ((unsigned)g->p.ptr > 100) g->p.ptr = (void *)100;
+			acquire_bus(g);
+			write_cmd2(g, VOLCTR, 64*(unsigned)g->p.ptr/101, 0x03);
+			release_bus(g);
+			g->g.Contrast = (unsigned)g->p.ptr;
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/RA8875/gdisp_lld.c b/drivers/gdisp/RA8875/gdisp_lld.c
deleted file mode 100644
index fb81c43a..00000000
--- a/drivers/gdisp/RA8875/gdisp_lld.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/RA8875/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-#define GDISP_DRIVER_VMT			GDISPVMT_RA8875
-#include "../drivers/gdisp/RA8875/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-/* include the users board interface */
-#include "board_RA8875.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		272
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		480
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	74
-#endif
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// Some common routines and macros
-#define dummy_read(g)					{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
-#define write_reg8(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
-#define write_reg16(g, reg, data)		{ write_index(g, reg); write_data(g, data); write_index(g, reg+1); write_data(g, (data)>>8); }
-#define write_reg8x2(g, reg, d1, d2)	{ write_index(g, reg); write_data(g, d1); write_data(g, d2); }
-
-static inline void set_cursor(GDisplay *g) {
-	write_reg16(g, 0x46, g->p.x);
-	write_reg16(g, 0x48, g->p.y);
-	write_index(g, 0x02);
-}
-
-static inline void set_viewport(GDisplay* g) {
-	write_reg16(g, 0x30, g->p.x);				//HSAW0 & HSAW1
-	write_reg16(g, 0x34, g->p.x+g->p.cx-1);		//HEAW0 & HEAW1
-	write_reg16(g, 0x32, g->p.y);				//VSAW0 & VSAW1
-	write_reg16(g, 0x36, g->p.y+g->p.cy-1);		//VEAW0 & VEAW1
-}
-
-// On this controller the back-light is controlled by the controllers internal PWM
-//	which is why it is in this file rather than the board file.
-static inline void set_backlight(GDisplay* g, uint8_t percent) {
-	uint8_t temp;
-
-	//Work in progress: the RA8875 has a built-in PWM, its output can
-	//be used by a Dynamic Background Control or by a host (user)
-
-	// Enable PWM1
-	write_index(g, 0x8a);						//MCLR
-	setreadmode(g);
-	temp = read_data(g);
-	setwritemode(g);
-	temp |= 1<<7 ;
-	write_data(g, temp);
-
-	// PWM1 function select
-	write_index(g, 0x8a);						//MCLR
-	setreadmode(g);
-	temp = read_data(g);
-	setwritemode(g);
-	temp &= ~(1<<4);
-	write_data(g, temp);
-
-	// PWM1 Clock ratio
-	write_index(g, 0x8a);						//MCLR
-	setreadmode(g);
-	temp = read_data(g);
-	setwritemode(g);
-	temp &= 0xf0;
-	temp |= 0x0b & 0x0f;
-	write_data(g, temp);
-
-	// PWM1 Write duty cycle
-	write_reg8(g, 0x8b, 54+percent);			// PTNO: Also change percent to range from 0x00 to 0xFF
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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);
-
-	// Soft reset
-	write_reg8x2(g, 0x01, 0x01, 0x00);	gfxSleepMilliseconds(1);
-
-	// PLL config
-	write_reg8(g, 0x88, 0x08);			gfxSleepMilliseconds(1);
-	write_reg8(g, 0x89, 0x02);			gfxSleepMilliseconds(1);
-
-	write_reg8(g, 0x10, 0x0F);			//SYSR   bit[4:3]=00 256 color  bit[2:1]=  00 8bit MPU interface
-										//		 0x0F = 16bit MCU interface and 65k color display
-
-	write_reg8(g, 0x04, 0x82);			gfxSleepMilliseconds(1);	//set PCLK inverse
-
-	// Horizontal set
-	write_reg8(g, 0x14, GDISP_SCREEN_WIDTH/8-1);	//HDWR: Horizontal Display Width Setting Bit[6:0] - pixels = (HDWR + 1)*8
-    write_reg8(g, 0x15, 0x00);						//Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR) - HNDFT = [3:0]
-    write_reg8(g, 0x16, 0x01);						//HNDR: Horizontal Non-Display Period Bit[4:0] - pixels = (HNDR + 1)*8
-    write_reg8(g, 0x17, 0x00);						//HSTR: HSYNC Start Position[4:0] - Position(PCLK) = (HSTR + 1)*8
-    write_reg8(g, 0x18, 0x05);						//HPWR: HSYNC Polarity, The period width of HSYNC. Width [4:0] width(PCLK) = (HPWR + 1)*8
-
-    // Vertical set
-    write_reg16(g, 0x19, GDISP_SCREEN_HEIGHT-1);	//VDHR0,1: Vertical Display Height = VDHR + 1
-    write_reg16(g, 0x1b, 0x0002);					//VNDR0,1: Vertical Non-Display Period Bit = (VSTR + 1)
-    write_reg16(g, 0x1d, 0x0007);					//VSTR0,1: VSYNC Start Position = (VSTR + 1)
-    write_reg8(g, 0x1f, 0x09);						//VPWR: VSYNC Polarity, VSYNC Pulse Width[6:0] - Width(PCLK) = (VPWR + 1)
-
-	// Active window  set
-	write_reg16(g, 0x30, 0);						//HSAW0 & HSAW1
-	write_reg16(g, 0x34, GDISP_SCREEN_WIDTH-1);		//HEAW0 & HEAW1
-	write_reg16(g, 0x32, 0);						//VSAW0 & VSAW1
-	write_reg16(g, 0x36, GDISP_SCREEN_HEIGHT-1);	//VEAW0 & VEAW1
-
-	// Display ON
-	write_reg8(g, 0x01, 0x80);						//PWRR
-
-	// GPO0 DISP high
-	write_reg8(g, 0x13, 0x01);						//GPO
-
-	// Set initial back-light
-	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
-	
-	// Change timings for faster access
-	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);
-		set_viewport(g);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-		set_cursor(g);
-	}
-#endif
-
-#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDisplay *g) {
-		switch(g->p.x) {
-		#if 0
-			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);
-					// TODO
-					release_bus(g);
-					break;
-				case powerOn:
-					acquire_bus(g);
-					// TODO
-					release_bus(g);
-					break;
-				case powerSleep:
-					acquire_bus(g);
-					// TODO
-					release_bus(g);
-					break;
-				default:
-					return;
-				}
-				g->g.Powermode = (powermode_t)g->p.ptr;
-				return;
-		#endif
-
-		#if 0
-			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;
-		#endif
-
-        case GDISP_CONTROL_BACKLIGHT:
-            if ((unsigned)g->p.ptr > 100)
-            	g->p.ptr = (void *)100;
-			acquire_bus(g);
-            set_backlight(g, (unsigned)g->p.ptr);
-			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/RA8875/gdisp_lld.mk b/drivers/gdisp/RA8875/gdisp_lld.mk
index 7ac03624..146cf255 100644
--- a/drivers/gdisp/RA8875/gdisp_lld.mk
+++ b/drivers/gdisp/RA8875/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC +=	$(GFXLIB)/drivers/gdisp/RA8875
-GFXSRC +=	$(GFXLIB)/drivers/gdisp/RA8875/gdisp_lld.c
+GFXSRC +=	$(GFXLIB)/drivers/gdisp/RA8875/gdisp_lld_RA8875.c
diff --git a/drivers/gdisp/RA8875/gdisp_lld_RA8875.c b/drivers/gdisp/RA8875/gdisp_lld_RA8875.c
new file mode 100644
index 00000000..fb81c43a
--- /dev/null
+++ b/drivers/gdisp/RA8875/gdisp_lld_RA8875.c
@@ -0,0 +1,283 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/RA8875/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#define GDISP_DRIVER_VMT			GDISPVMT_RA8875
+#include "../drivers/gdisp/RA8875/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+/* include the users board interface */
+#include "board_RA8875.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		272
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		480
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	74
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some common routines and macros
+#define dummy_read(g)					{ volatile uint16_t dummy; dummy = read_data(g); (void) dummy; }
+#define write_reg8(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+#define write_reg16(g, reg, data)		{ write_index(g, reg); write_data(g, data); write_index(g, reg+1); write_data(g, (data)>>8); }
+#define write_reg8x2(g, reg, d1, d2)	{ write_index(g, reg); write_data(g, d1); write_data(g, d2); }
+
+static inline void set_cursor(GDisplay *g) {
+	write_reg16(g, 0x46, g->p.x);
+	write_reg16(g, 0x48, g->p.y);
+	write_index(g, 0x02);
+}
+
+static inline void set_viewport(GDisplay* g) {
+	write_reg16(g, 0x30, g->p.x);				//HSAW0 & HSAW1
+	write_reg16(g, 0x34, g->p.x+g->p.cx-1);		//HEAW0 & HEAW1
+	write_reg16(g, 0x32, g->p.y);				//VSAW0 & VSAW1
+	write_reg16(g, 0x36, g->p.y+g->p.cy-1);		//VEAW0 & VEAW1
+}
+
+// On this controller the back-light is controlled by the controllers internal PWM
+//	which is why it is in this file rather than the board file.
+static inline void set_backlight(GDisplay* g, uint8_t percent) {
+	uint8_t temp;
+
+	//Work in progress: the RA8875 has a built-in PWM, its output can
+	//be used by a Dynamic Background Control or by a host (user)
+
+	// Enable PWM1
+	write_index(g, 0x8a);						//MCLR
+	setreadmode(g);
+	temp = read_data(g);
+	setwritemode(g);
+	temp |= 1<<7 ;
+	write_data(g, temp);
+
+	// PWM1 function select
+	write_index(g, 0x8a);						//MCLR
+	setreadmode(g);
+	temp = read_data(g);
+	setwritemode(g);
+	temp &= ~(1<<4);
+	write_data(g, temp);
+
+	// PWM1 Clock ratio
+	write_index(g, 0x8a);						//MCLR
+	setreadmode(g);
+	temp = read_data(g);
+	setwritemode(g);
+	temp &= 0xf0;
+	temp |= 0x0b & 0x0f;
+	write_data(g, temp);
+
+	// PWM1 Write duty cycle
+	write_reg8(g, 0x8b, 54+percent);			// PTNO: Also change percent to range from 0x00 to 0xFF
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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);
+
+	// Soft reset
+	write_reg8x2(g, 0x01, 0x01, 0x00);	gfxSleepMilliseconds(1);
+
+	// PLL config
+	write_reg8(g, 0x88, 0x08);			gfxSleepMilliseconds(1);
+	write_reg8(g, 0x89, 0x02);			gfxSleepMilliseconds(1);
+
+	write_reg8(g, 0x10, 0x0F);			//SYSR   bit[4:3]=00 256 color  bit[2:1]=  00 8bit MPU interface
+										//		 0x0F = 16bit MCU interface and 65k color display
+
+	write_reg8(g, 0x04, 0x82);			gfxSleepMilliseconds(1);	//set PCLK inverse
+
+	// Horizontal set
+	write_reg8(g, 0x14, GDISP_SCREEN_WIDTH/8-1);	//HDWR: Horizontal Display Width Setting Bit[6:0] - pixels = (HDWR + 1)*8
+    write_reg8(g, 0x15, 0x00);						//Horizontal Non-Display Period Fine Tuning Option Register (HNDFTR) - HNDFT = [3:0]
+    write_reg8(g, 0x16, 0x01);						//HNDR: Horizontal Non-Display Period Bit[4:0] - pixels = (HNDR + 1)*8
+    write_reg8(g, 0x17, 0x00);						//HSTR: HSYNC Start Position[4:0] - Position(PCLK) = (HSTR + 1)*8
+    write_reg8(g, 0x18, 0x05);						//HPWR: HSYNC Polarity, The period width of HSYNC. Width [4:0] width(PCLK) = (HPWR + 1)*8
+
+    // Vertical set
+    write_reg16(g, 0x19, GDISP_SCREEN_HEIGHT-1);	//VDHR0,1: Vertical Display Height = VDHR + 1
+    write_reg16(g, 0x1b, 0x0002);					//VNDR0,1: Vertical Non-Display Period Bit = (VSTR + 1)
+    write_reg16(g, 0x1d, 0x0007);					//VSTR0,1: VSYNC Start Position = (VSTR + 1)
+    write_reg8(g, 0x1f, 0x09);						//VPWR: VSYNC Polarity, VSYNC Pulse Width[6:0] - Width(PCLK) = (VPWR + 1)
+
+	// Active window  set
+	write_reg16(g, 0x30, 0);						//HSAW0 & HSAW1
+	write_reg16(g, 0x34, GDISP_SCREEN_WIDTH-1);		//HEAW0 & HEAW1
+	write_reg16(g, 0x32, 0);						//VSAW0 & VSAW1
+	write_reg16(g, 0x36, GDISP_SCREEN_HEIGHT-1);	//VEAW0 & VEAW1
+
+	// Display ON
+	write_reg8(g, 0x01, 0x80);						//PWRR
+
+	// GPO0 DISP high
+	write_reg8(g, 0x13, 0x01);						//GPO
+
+	// Set initial back-light
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+	
+	// Change timings for faster access
+	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);
+		set_viewport(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+		set_cursor(g);
+	}
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
+		#if 0
+			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);
+					// TODO
+					release_bus(g);
+					break;
+				case powerOn:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				case powerSleep:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				default:
+					return;
+				}
+				g->g.Powermode = (powermode_t)g->p.ptr;
+				return;
+		#endif
+
+		#if 0
+			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;
+		#endif
+
+        case GDISP_CONTROL_BACKLIGHT:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+			acquire_bus(g);
+            set_backlight(g, (unsigned)g->p.ptr);
+			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/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c
deleted file mode 100644
index df9f01a7..00000000
--- a/drivers/gdisp/S6D1121/gdisp_lld.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/S6D1121/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the S6d1121 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-#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_S6D1121
-#include "../drivers/gdisp/S6D1121/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_S6D1121.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-/* 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_index(g, reg); write_data(g, data); }
-#define delay(us)                   gfxSleepMicroseconds(us)
-#define delayms(ms)                 gfxSleepMilliseconds(ms)
-
-static inline void set_cursor(GDisplay *g) {
-    /* R20h - 8 bit
-     * R21h - 9 bit
-     */
-    switch(g->g.Orientation) {
-        case GDISP_ROTATE_0:
-            write_reg(g, 0x20, g->p.x & 0x00FF);
-            write_reg(g, 0x21, g->p.y & 0x01FF);
-            break;
-        case GDISP_ROTATE_90:
-            write_reg(g, 0x20, g->p.y & 0x00FF);
-            write_reg(g, 0x21, (GDISP_SCREEN_HEIGHT - 1 - g->p.x) & 0x01FF);
-            break;
-        case GDISP_ROTATE_180:
-            write_reg(g, 0x20, (GDISP_SCREEN_WIDTH - 1 - g->p.x) & 0x00FF);
-            write_reg(g, 0x21, (GDISP_SCREEN_HEIGHT - 1 - g->p.y) & 0x01FF);
-            break;
-        case GDISP_ROTATE_270:
-            write_reg(g, 0x20, (GDISP_SCREEN_WIDTH - 1 - g->p.y) & 0x00FF);
-            write_reg(g, 0x21, g->p.x & 0x01FF);
-            break;
-    }
-    write_index(g, 0x22);
-}
-
-static inline void set_viewport(GDisplay *g) {
-    /* HSA / HEA are 8 bit
-     * VSA / VEA are 9 bit
-     * use masks 0x00FF and 0x01FF to enforce this
-     */
-
-    switch(g->g.Orientation) {
-        case GDISP_ROTATE_0:
-            write_reg(g, 0x46, (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
-            write_reg(g, 0x48, g->p.y & 0x01FF);
-            write_reg(g, 0x47, (g->p.y + g->p.cy - 1) & 0x01FF);
-            break;
-        case GDISP_ROTATE_90:
-            write_reg(g, 0x46, (((g->p.y + g->p.cy - 1) << 8) & 0xFF00) | (g->p.y & 0x00FF));
-            write_reg(g, 0x48, (GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x01FF);
-            write_reg(g, 0x47, (GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x01FF);
-            break;
-        case GDISP_ROTATE_180:
-            write_reg(g, 0x46, (((GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x00FF) << 8) |
-                                      ((GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x00FF));
-            write_reg(g, 0x48, (GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x01FF);
-            write_reg(g, 0x47, (GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x01FF);
-            break;
-        case GDISP_ROTATE_270:
-            write_reg(g, 0x46, (((GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x00FF) << 8) |
-                                      ((GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x00FF));
-            write_reg(g, 0x48, g->p.x & 0x01FF);
-            write_reg(g, 0x47, (g->p.x + g->p.cx - 1) & 0x01FF);
-            break;
-    }   
-}
-
-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);
-	delayms(20);
-	setpin_reset(g, TRUE);
-	delayms(20);
-
-	/* Get the bus for the following initialisation commands */
-	acquire_bus(g);
-
-	write_reg(g, 0x11, 0x2004);
-	write_reg(g, 0x13, 0xCC00);
-	write_reg(g, 0x15, 0x2600);
-	write_reg(g, 0x14, 0x252A);
-	write_reg(g, 0x12, 0x0033);
-	write_reg(g, 0x13, 0xCC04);
-
-	delayms(1);
-
-	write_reg(g, 0x13, 0xCC06);
-
-	delayms(1);
-
-	write_reg(g, 0x13, 0xCC4F);
-
-	delayms(1);
-
-	write_reg(g, 0x13, 0x674F);
-	write_reg(g, 0x11, 0x2003);
-
-	delayms(1);
-
-	// Gamma Setting
-	write_reg(g, 0x30, 0x2609);
-	write_reg(g, 0x31, 0x242C);
-	write_reg(g, 0x32, 0x1F23);
-	write_reg(g, 0x33, 0x2425);
-	write_reg(g, 0x34, 0x2226);
-	write_reg(g, 0x35, 0x2523);
-	write_reg(g, 0x36, 0x1C1A);
-	write_reg(g, 0x37, 0x131D);
-	write_reg(g, 0x38, 0x0B11);
-	write_reg(g, 0x39, 0x1210);
-	write_reg(g, 0x3A, 0x1315);
-	write_reg(g, 0x3B, 0x3619);
-	write_reg(g, 0x3C, 0x0D00);
-	write_reg(g, 0x3D, 0x000D);
-
-	write_reg(g, 0x16, 0x0007);
-	write_reg(g, 0x02, 0x0013);
-	write_reg(g, 0x03, 0x0003);
-	write_reg(g, 0x01, 0x0127);
-
-	delayms(1);
-
-	write_reg(g, 0x08, 0x0303);
-	write_reg(g, 0x0A, 0x000B);
-	write_reg(g, 0x0B, 0x0003);
-	write_reg(g, 0x0C, 0x0000);
-	write_reg(g, 0x41, 0x0000);
-	write_reg(g, 0x50, 0x0000);
-	write_reg(g, 0x60, 0x0005);
-	write_reg(g, 0x70, 0x000B);
-	write_reg(g, 0x71, 0x0000);
-	write_reg(g, 0x78, 0x0000);
-	write_reg(g, 0x7A, 0x0000);
-	write_reg(g, 0x79, 0x0007);
-	write_reg(g, 0x07, 0x0051);
-
-	delayms(1);
-
-	write_reg(g, 0x07,0x0053);
-	write_reg(g, 0x79,0x0000);
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-		set_cursor(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		setwritemode(g);
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDisplay *g) {
-		switch(g->p.x) {
-		#if 0
-			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);
-					// TODO
-					release_bus(g);
-					break;
-				case powerOn:
-					acquire_bus(g);
-					// TODO
-					release_bus(g);
-					break;
-				case powerSleep:
-					acquire_bus(g);
-					// TODO
-					release_bus(g);
-					break;
-				default:
-					return;
-				}
-				g->g.Powermode = (powermode_t)g->p.ptr;
-				return;
-		#endif
-
-		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);
-				write_reg(g, 0x03, 0b0011);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-				write_reg(g, 0x03, 0b1001);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				write_reg(g, 0x03, 0b0000);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-				write_reg(g, 0x03, 0b1010);
-				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;
-            set_backlight(g, (unsigned)g->p.ptr);
-            g->g.Backlight = (unsigned)g->p.ptr;
-            return;
-
-		//case GDISP_CONTROL_CONTRAST:
-        default:
-            return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
-
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.mk b/drivers/gdisp/S6D1121/gdisp_lld.mk
index f5f067b7..583feb41 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld.mk
+++ b/drivers/gdisp/S6D1121/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/S6D1121
-GFXSRC += $(GFXLIB)/drivers/gdisp/S6D1121/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c b/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
new file mode 100644
index 00000000..cbaa7199
--- /dev/null
+++ b/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
@@ -0,0 +1,335 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/S6D1121/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the S6d1121 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#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_S6D1121
+#include "../drivers/gdisp/S6D1121/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_S6D1121.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+/* 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_index(g, reg); write_data(g, data); }
+#define delay(us)                   gfxSleepMicroseconds(us)
+#define delayms(ms)                 gfxSleepMilliseconds(ms)
+
+static inline void set_cursor(GDisplay *g) {
+    /* R20h - 8 bit
+     * R21h - 9 bit
+     */
+    switch(g->g.Orientation) {
+        case GDISP_ROTATE_0:
+            write_reg(g, 0x20, g->p.x & 0x00FF);
+            write_reg(g, 0x21, g->p.y & 0x01FF);
+            break;
+        case GDISP_ROTATE_90:
+            write_reg(g, 0x20, g->p.y & 0x00FF);
+            write_reg(g, 0x21, (GDISP_SCREEN_HEIGHT - 1 - g->p.x) & 0x01FF);
+            break;
+        case GDISP_ROTATE_180:
+            write_reg(g, 0x20, (GDISP_SCREEN_WIDTH - 1 - g->p.x) & 0x00FF);
+            write_reg(g, 0x21, (GDISP_SCREEN_HEIGHT - 1 - g->p.y) & 0x01FF);
+            break;
+        case GDISP_ROTATE_270:
+            write_reg(g, 0x20, (GDISP_SCREEN_WIDTH - 1 - g->p.y) & 0x00FF);
+            write_reg(g, 0x21, g->p.x & 0x01FF);
+            break;
+    }
+    write_index(g, 0x22);
+}
+
+static inline void set_viewport(GDisplay *g) {
+    /* HSA / HEA are 8 bit
+     * VSA / VEA are 9 bit
+     * use masks 0x00FF and 0x01FF to enforce this
+     */
+
+    switch(g->g.Orientation) {
+        case GDISP_ROTATE_0:
+            write_reg(g, 0x46, (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+            write_reg(g, 0x48, g->p.y & 0x01FF);
+            write_reg(g, 0x47, (g->p.y + g->p.cy - 1) & 0x01FF);
+            break;
+        case GDISP_ROTATE_90:
+            write_reg(g, 0x46, (((g->p.y + g->p.cy - 1) << 8) & 0xFF00) | (g->p.y & 0x00FF));
+            write_reg(g, 0x48, (GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x01FF);
+            write_reg(g, 0x47, (GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x01FF);
+            break;
+        case GDISP_ROTATE_180:
+            write_reg(g, 0x46, (((GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x00FF) << 8) |
+                                      ((GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x00FF));
+            write_reg(g, 0x48, (GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x01FF);
+            write_reg(g, 0x47, (GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x01FF);
+            break;
+        case GDISP_ROTATE_270:
+            write_reg(g, 0x46, (((GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x00FF) << 8) |
+                                      ((GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x00FF));
+            write_reg(g, 0x48, g->p.x & 0x01FF);
+            write_reg(g, 0x47, (g->p.x + g->p.cx - 1) & 0x01FF);
+            break;
+    }   
+}
+
+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);
+	delayms(20);
+	setpin_reset(g, TRUE);
+	delayms(20);
+
+	/* Get the bus for the following initialisation commands */
+	acquire_bus(g);
+
+	write_reg(g, 0x11, 0x2004);
+	write_reg(g, 0x13, 0xCC00);
+	write_reg(g, 0x15, 0x2600);
+	write_reg(g, 0x14, 0x252A);
+	write_reg(g, 0x12, 0x0033);
+	write_reg(g, 0x13, 0xCC04);
+
+	delayms(1);
+
+	write_reg(g, 0x13, 0xCC06);
+
+	delayms(1);
+
+	write_reg(g, 0x13, 0xCC4F);
+
+	delayms(1);
+
+	write_reg(g, 0x13, 0x674F);
+	write_reg(g, 0x11, 0x2003);
+
+	delayms(1);
+
+	// Gamma Setting
+	write_reg(g, 0x30, 0x2609);
+	write_reg(g, 0x31, 0x242C);
+	write_reg(g, 0x32, 0x1F23);
+	write_reg(g, 0x33, 0x2425);
+	write_reg(g, 0x34, 0x2226);
+	write_reg(g, 0x35, 0x2523);
+	write_reg(g, 0x36, 0x1C1A);
+	write_reg(g, 0x37, 0x131D);
+	write_reg(g, 0x38, 0x0B11);
+	write_reg(g, 0x39, 0x1210);
+	write_reg(g, 0x3A, 0x1315);
+	write_reg(g, 0x3B, 0x3619);
+	write_reg(g, 0x3C, 0x0D00);
+	write_reg(g, 0x3D, 0x000D);
+
+	write_reg(g, 0x16, 0x0007);
+	write_reg(g, 0x02, 0x0013);
+	write_reg(g, 0x03, 0x0003);
+	write_reg(g, 0x01, 0x0127);
+
+	delayms(1);
+
+	write_reg(g, 0x08, 0x0303);
+	write_reg(g, 0x0A, 0x000B);
+	write_reg(g, 0x0B, 0x0003);
+	write_reg(g, 0x0C, 0x0000);
+	write_reg(g, 0x41, 0x0000);
+	write_reg(g, 0x50, 0x0000);
+	write_reg(g, 0x60, 0x0005);
+	write_reg(g, 0x70, 0x000B);
+	write_reg(g, 0x71, 0x0000);
+	write_reg(g, 0x78, 0x0000);
+	write_reg(g, 0x7A, 0x0000);
+	write_reg(g, 0x79, 0x0007);
+	write_reg(g, 0x07, 0x0051);
+
+	delayms(1);
+
+	write_reg(g, 0x07,0x0053);
+	write_reg(g, 0x79,0x0000);
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+		set_cursor(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
+		#if 0
+			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);
+					// TODO
+					release_bus(g);
+					break;
+				case powerOn:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				case powerSleep:
+					acquire_bus(g);
+					// TODO
+					release_bus(g);
+					break;
+				default:
+					return;
+				}
+				g->g.Powermode = (powermode_t)g->p.ptr;
+				return;
+		#endif
+
+		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);
+				write_reg(g, 0x03, 0b0011);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b1001);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b0000);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				write_reg(g, 0x03, 0b1010);
+				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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
deleted file mode 100644
index f600b305..00000000
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1289/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_SSD1289
-#include "../drivers/gdisp/SSD1289/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_SSD1289.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// 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_index(g, reg); write_data(g, data); }
-
-static void set_cursor(GDisplay *g) {
-	/*
-	 * Reg 0x004E is an 8 bit value - start x position
-	 * Reg 0x004F is 9 bit - start y position
-	 * Use a bit mask to make sure they are not set too high
-	 */
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			write_reg(g, 0x4e, g->p.x & 0x00FF);
-			write_reg(g, 0x4f, g->p.y & 0x01FF);
-			break;
-		case GDISP_ROTATE_90:
-			write_reg(g, 0x4e, g->p.y & 0x00FF);
-			write_reg(g, 0x4f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
-			break;
-		case GDISP_ROTATE_180:
-			write_reg(g, 0x4e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
-			write_reg(g, 0x4f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
-			break;
-		case GDISP_ROTATE_270:
-			write_reg(g, 0x4e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
-			write_reg(g, 0x4f, g->p.x & 0x01FF);
-			break;
-	}
-	write_index(g, 0x22);
-}
-
-static void set_viewport(GDisplay* g) {
-	/* Reg 0x44 - Horizontal RAM address position
-	 * 		Upper Byte - HEA
-	 * 		Lower Byte - HSA
-	 * 		0 <= HSA <= HEA <= 0xEF
-	 * Reg 0x45,0x46 - Vertical RAM address position
-	 * 		Lower 9 bits gives 0-511 range in each value
-	 * 		0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
-	 * Use a bit mask to make sure they are not set too high
-	 */
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			write_reg(g, 0x44, (((g->p.x+g->p.cx-1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
-			write_reg(g, 0x45, g->p.y & 0x01FF);
-			write_reg(g, 0x46, (g->p.y+g->p.cy-1) & 0x01FF);
-			break;
-		case GDISP_ROTATE_90:
-			write_reg(g, 0x44, (((g->p.y+g->p.cy-1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
-			write_reg(g, 0x45, (GDISP_SCREEN_HEIGHT-(g->p.x+g->p.cx)) & 0x01FF);
-			write_reg(g, 0x46, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
-			break;
-		case GDISP_ROTATE_180:
-			write_reg(g, 0x44, (((GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
-			write_reg(g, 0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
-			write_reg(g, 0x46, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
-			break;
-		case GDISP_ROTATE_270:
-			write_reg(g, 0x44, (((GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH-(g->p.y+g->p.cy)) & 0x00FF));
-			write_reg(g, 0x45, g->p.x & 0x01FF);
-			write_reg(g, 0x46, (g->p.x+g->p.cx-1) & 0x01FF);
-			break;
-	}
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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, 0x00, 0x0001);		gfxSleepMicroseconds(5);
-	write_reg(g, 0x03, 0xA8A4);    	gfxSleepMicroseconds(5);
-	write_reg(g, 0x0C, 0x0000);    	gfxSleepMicroseconds(5);
-	write_reg(g, 0x0D, 0x080C);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x0E, 0x2B00);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x1E, 0x00B0);    	gfxSleepMicroseconds(5);
-	write_reg(g, 0x01, 0x2B3F);		gfxSleepMicroseconds(5);
-    write_reg(g, 0x02, 0x0600);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x10, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x11, 0x6070);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x05, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x06, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x16, 0xEF1C);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x17, 0x0003);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x07, 0x0133);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x0B, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x0F, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x41, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x42, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x48, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x49, 0x013F);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x4A, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x4B, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x44, 0xEF00);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x45, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x46, 0x013F);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x30, 0x0707);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x31, 0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x32, 0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x33, 0x0502);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x34, 0x0507);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x35, 0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x36, 0x0204);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x37, 0x0502);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x3A, 0x0302);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x3B, 0x0302);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x23, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x24, 0x0000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x25, 0x8000);    	gfxSleepMicroseconds(5);
-    write_reg(g, 0x4f, 0x0000);		gfxSleepMicroseconds(5);
-    write_reg(g, 0x4e, 0x0000);		gfxSleepMicroseconds(5);
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		#if !GDISP_HARDWARE_STREAM_POS
-			set_cursor(g);
-		#endif
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-	#if GDISP_HARDWARE_STREAM_POS
-		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-			set_cursor(g);
-		}
-	#endif
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		setwritemode(g);
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
-	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		dma_with_noinc(g, &color, g->p.cx*g->p.cy)
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
-	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
-		pixel_t		*buffer;
-		coord_t		ycnt;
-
-		buffer = (pixel_t *)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
-
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		if (g->p.x2 == g->p.cx) {
-			dma_with_inc(g, buffer, g->p.cx*g->p.cy);
-		} else {
-			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
-				dma_with_inc(g, buffer, g->p.cy);
-		}
-		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:
-				acquire_bus(g);
-				write_reg(g, 0x10, 0x0000);	// leave sleep mode
-				write_reg(g, 0x07, 0x0000);	// halt operation
-				write_reg(g, 0x00, 0x0000);	// turn off oscillator
-				write_reg(g, 0x10, 0x0001);	// enter sleep mode
-				release_bus(g);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				write_reg(g, 0x10, 0x0000);	// leave sleep mode
-				write_reg(g, 0x00, 0x0001);	// turn on oscillator
-				gfxSleepMicroseconds(5);
-				release_bus(g);
-				break;
-			case powerSleep:
-				acquire_bus(g);
-				write_reg(g, 0x10, 0x0001);	// enter sleep mode
-				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);
-				/* ID = 11 AM = 0 */
-				write_reg(g, 0x11, 0x6070);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-				/* ID = 01 AM = 1 */
-				write_reg(g, 0x11, 0x6058);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				/* ID = 00 AM = 0 */
-				write_reg(g, 0x11, 0x6040);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-				/* ID = 10 AM = 1 */
-				write_reg(g, 0x11, 0x6068);
-				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;
-            set_backlight(g, (unsigned)g->p.ptr);
-            g->g.Backlight = (unsigned)g->p.ptr;
-            return;
-
-		//case GDISP_CONTROL_CONTRAST:
-        default:
-            return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.mk b/drivers/gdisp/SSD1289/gdisp_lld.mk
index 564610eb..fd2713bc 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.mk
+++ b/drivers/gdisp/SSD1289/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/SSD1289
-GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1289/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c b/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
new file mode 100644
index 00000000..6692e7d7
--- /dev/null
+++ b/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
@@ -0,0 +1,351 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1289/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1289
+#include "../drivers/gdisp/SSD1289/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_SSD1289.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// 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_index(g, reg); write_data(g, data); }
+
+static void set_cursor(GDisplay *g) {
+	/*
+	 * Reg 0x004E is an 8 bit value - start x position
+	 * Reg 0x004F is 9 bit - start y position
+	 * Use a bit mask to make sure they are not set too high
+	 */
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			write_reg(g, 0x4e, g->p.x & 0x00FF);
+			write_reg(g, 0x4f, g->p.y & 0x01FF);
+			break;
+		case GDISP_ROTATE_90:
+			write_reg(g, 0x4e, g->p.y & 0x00FF);
+			write_reg(g, 0x4f, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
+			break;
+		case GDISP_ROTATE_180:
+			write_reg(g, 0x4e, (GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF);
+			write_reg(g, 0x4f, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
+			break;
+		case GDISP_ROTATE_270:
+			write_reg(g, 0x4e, (GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF);
+			write_reg(g, 0x4f, g->p.x & 0x01FF);
+			break;
+	}
+	write_index(g, 0x22);
+}
+
+static void set_viewport(GDisplay* g) {
+	/* Reg 0x44 - Horizontal RAM address position
+	 * 		Upper Byte - HEA
+	 * 		Lower Byte - HSA
+	 * 		0 <= HSA <= HEA <= 0xEF
+	 * Reg 0x45,0x46 - Vertical RAM address position
+	 * 		Lower 9 bits gives 0-511 range in each value
+	 * 		0 <= Reg(0x45) <= Reg(0x46) <= 0x13F
+	 * Use a bit mask to make sure they are not set too high
+	 */
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			write_reg(g, 0x44, (((g->p.x+g->p.cx-1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+			write_reg(g, 0x45, g->p.y & 0x01FF);
+			write_reg(g, 0x46, (g->p.y+g->p.cy-1) & 0x01FF);
+			break;
+		case GDISP_ROTATE_90:
+			write_reg(g, 0x44, (((g->p.y+g->p.cy-1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
+			write_reg(g, 0x45, (GDISP_SCREEN_HEIGHT-(g->p.x+g->p.cx)) & 0x01FF);
+			write_reg(g, 0x46, (GDISP_SCREEN_HEIGHT-1-g->p.x) & 0x01FF);
+			break;
+		case GDISP_ROTATE_180:
+			write_reg(g, 0x44, (((GDISP_SCREEN_WIDTH-1-g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH - (g->p.x+g->p.cx)) & 0x00FF));
+			write_reg(g, 0x45, (GDISP_SCREEN_HEIGHT-(g->p.y+g->p.cy)) & 0x01FF);
+			write_reg(g, 0x46, (GDISP_SCREEN_HEIGHT-1-g->p.y) & 0x01FF);
+			break;
+		case GDISP_ROTATE_270:
+			write_reg(g, 0x44, (((GDISP_SCREEN_WIDTH-1-g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_WIDTH-(g->p.y+g->p.cy)) & 0x00FF));
+			write_reg(g, 0x45, g->p.x & 0x01FF);
+			write_reg(g, 0x46, (g->p.x+g->p.cx-1) & 0x01FF);
+			break;
+	}
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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, 0x00, 0x0001);		gfxSleepMicroseconds(5);
+	write_reg(g, 0x03, 0xA8A4);    	gfxSleepMicroseconds(5);
+	write_reg(g, 0x0C, 0x0000);    	gfxSleepMicroseconds(5);
+	write_reg(g, 0x0D, 0x080C);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x0E, 0x2B00);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x1E, 0x00B0);    	gfxSleepMicroseconds(5);
+	write_reg(g, 0x01, 0x2B3F);		gfxSleepMicroseconds(5);
+    write_reg(g, 0x02, 0x0600);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x10, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x11, 0x6070);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x05, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x06, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x16, 0xEF1C);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x17, 0x0003);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x07, 0x0133);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x0B, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x0F, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x41, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x42, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x48, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x49, 0x013F);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x4A, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x4B, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x44, 0xEF00);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x45, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x46, 0x013F);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x30, 0x0707);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x31, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x32, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x33, 0x0502);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x34, 0x0507);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x35, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x36, 0x0204);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x37, 0x0502);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x3A, 0x0302);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x3B, 0x0302);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x23, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x24, 0x0000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x25, 0x8000);    	gfxSleepMicroseconds(5);
+    write_reg(g, 0x4f, 0x0000);		gfxSleepMicroseconds(5);
+    write_reg(g, 0x4e, 0x0000);		gfxSleepMicroseconds(5);
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		#if !GDISP_HARDWARE_STREAM_POS
+			set_cursor(g);
+		#endif
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			set_cursor(g);
+		}
+	#endif
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		return read_data(g);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		setwritemode(g);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		dma_with_noinc(g, &color, g->p.cx*g->p.cy)
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
+		pixel_t		*buffer;
+		coord_t		ycnt;
+
+		buffer = (pixel_t *)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
+
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		if (g->p.x2 == g->p.cx) {
+			dma_with_inc(g, buffer, g->p.cx*g->p.cy);
+		} else {
+			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
+				dma_with_inc(g, buffer, g->p.cy);
+		}
+		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:
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0000);	// leave sleep mode
+				write_reg(g, 0x07, 0x0000);	// halt operation
+				write_reg(g, 0x00, 0x0000);	// turn off oscillator
+				write_reg(g, 0x10, 0x0001);	// enter sleep mode
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0000);	// leave sleep mode
+				write_reg(g, 0x00, 0x0001);	// turn on oscillator
+				gfxSleepMicroseconds(5);
+				release_bus(g);
+				break;
+			case powerSleep:
+				acquire_bus(g);
+				write_reg(g, 0x10, 0x0001);	// enter sleep mode
+				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);
+				/* ID = 11 AM = 0 */
+				write_reg(g, 0x11, 0x6070);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				/* ID = 01 AM = 1 */
+				write_reg(g, 0x11, 0x6058);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				/* ID = 00 AM = 0 */
+				write_reg(g, 0x11, 0x6040);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				/* ID = 10 AM = 1 */
+				write_reg(g, 0x11, 0x6068);
+				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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.c b/drivers/gdisp/SSD1306/gdisp_lld.c
deleted file mode 100644
index 390a9282..00000000
--- a/drivers/gdisp/SSD1306/gdisp_lld.c
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1306/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1306 display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_SSD1306
-#include "../drivers/gdisp/SSD1306/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_SSD1306.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		64		// This controller should support 32 (untested) or 64
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		128
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	100
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-#ifdef SSD1306_PAGE_PREFIX
-	#define SSD1306_PAGE_WIDTH		(GDISP_SCREEN_WIDTH+1)
-	#define SSD1306_PAGE_OFFSET		1
-#else
-	#define SSD1306_PAGE_WIDTH		GDISP_SCREEN_WIDTH
-	#define SSD1306_PAGE_OFFSET		0
-#endif
-
-#define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
-
-#include "SSD1306.h"
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// Some common routines and macros
-#define RAM(g)							((uint8_t *)g->priv)
-#define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); }
-#define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
-
-// Some common routines and macros
-#define delay(us)			gfxSleepMicroseconds(us)
-#define delayms(ms)			gfxSleepMilliseconds(ms)
-
-#define xyaddr(x, y)		(SSD1306_PAGE_OFFSET + (x) + ((y)>>3)*SSD1306_PAGE_WIDTH)
-#define xybit(y)			(1<<((y)&7))
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-/**
- * As this controller can't update on a pixel boundary we need to maintain the
- * the entire display surface in memory so that we can do the necessary bit
- * operations. Fortunately it is a small display in monochrome.
- * 64 * 128 / 8 = 1024 bytes.
- */
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	// The private area is the display surface.
-	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH);
-
-	// Fill in the prefix command byte on each page line of the display buffer
-	// We can do it during initialisation as this byte is never overwritten.
-	#ifdef SSD1306_PAGE_PREFIX
-		{
-			unsigned	i;
-
-			for(i=0; i < GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH; i+=SSD1306_PAGE_WIDTH)
-				RAM(g)[i] = SSD1306_PAGE_PREFIX;
-		}
-	#endif
-
-	// Initialise the board interface
-	init_board(g);
-
-	// Hardware reset
-	setpin_reset(g, TRUE);
-	gfxSleepMilliseconds(20);
-	setpin_reset(g, FALSE);
-	gfxSleepMilliseconds(20);
-
-	acquire_bus(g);
-
-	write_cmd(g, SSD1306_DISPLAYOFF);
-	write_cmd2(g, SSD1306_SETDISPLAYCLOCKDIV, 0x80);
-	write_cmd2(g, SSD1306_SETMULTIPLEX, GDISP_SCREEN_HEIGHT-1);
-	write_cmd2(g, SSD1306_SETPRECHARGE, 0x1F);
-	write_cmd2(g, SSD1306_SETDISPLAYOFFSET, 0);
-	write_cmd(g, SSD1306_SETSTARTLINE | 0);
-	write_cmd2(g, SSD1306_ENABLE_CHARGE_PUMP, 0x14);
-	write_cmd2(g, SSD1306_MEMORYMODE, 0);
-	write_cmd(g, SSD1306_SEGREMAP+1);
-	write_cmd(g, SSD1306_COMSCANDEC);
-	#if GDISP_SCREEN_HEIGHT == 64
-		write_cmd2(g, SSD1306_SETCOMPINS, 0x12);
-	#else
-		write_cmd2(g, SSD1306_SETCOMPINS, 0x22);
-	#endif
-	write_cmd2(g, SSD1306_SETCONTRAST, (uint8_t)(GDISP_INITIAL_CONTRAST*256/101));	// Set initial contrast.
-	write_cmd2(g, SSD1306_SETVCOMDETECT, 0x10);
-	write_cmd(g, SSD1306_DISPLAYON);
-	write_cmd(g, SSD1306_NORMALDISPLAY);
-	write_cmd3(g, SSD1306_HV_COLUMN_ADDRESS, 0, GDISP_SCREEN_WIDTH-1);
-	write_cmd3(g, SSD1306_HV_PAGE_ADDRESS, 0, GDISP_SCREEN_HEIGHT/8-1);
-
-    // 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_FLUSH
-	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
-		unsigned	i;
-
-		// Don't flush if we don't need it.
-		if (!(g->flags & GDISP_FLG_NEEDFLUSH))
-			return;
-
-		write_cmd(g, SSD1306_SETSTARTLINE | 0);
-
-		for(i=0; i < GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH; i+=SSD1306_PAGE_WIDTH)
-			write_data(g, RAM(g)+i, SSD1306_PAGE_WIDTH);
-	}
-#endif
-
-#if GDISP_HARDWARE_DRAWPIXEL
-	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
-		coord_t		x, y;
-
-		switch(g->g.Orientation) {
-		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_HEIGHT-1 - g->p.y;
-			x = g->p.x;
-			break;
-		}
-		if (g->p.color != Black)
-			RAM(g)[xyaddr(x, y)] |= xybit(y);
-		else
-			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
-		g->flags |= GDISP_FLG_NEEDFLUSH;
-	}
-#endif
-
-#if GDISP_HARDWARE_PIXELREAD
-	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
-		coord_t		x, y;
-
-		switch(g->g.Orientation) {
-		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_HEIGHT-1 - g->p.y;
-			y = g->p.x;
-			break;
-		}
-		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
-	}
-#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, SSD1306_DISPLAYOFF);
-				release_bus(g);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				write_cmd(g, SSD1306_DISPLAYON);
-				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) {
-			/* Rotation is handled by the drawing routines */
-			case GDISP_ROTATE_0:
-			case GDISP_ROTATE_180:
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-			case GDISP_ROTATE_270:
-				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_CONTRAST:
-            if ((unsigned)g->p.ptr > 100)
-            	g->p.ptr = (void *)100;
-			acquire_bus(g);
-			write_cmd2(g, SSD1306_SETCONTRAST, (((unsigned)g->p.ptr)<<8)/101);
-			release_bus(g);
-            g->g.Contrast = (unsigned)g->p.ptr;
-			return;
-
-		// Our own special controller code to inverse the display
-		// 0 = normal, 1 = inverse
-		case GDISP_CONTROL_INVERSE:
-			acquire_bus(g);
-			write_cmd(g, g->p.ptr ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
-			release_bus(g);
-			return;
-		}
-	}
-#endif // GDISP_NEED_CONTROL
-
-#endif // GFX_USE_GDISP
-
diff --git a/drivers/gdisp/SSD1306/gdisp_lld.mk b/drivers/gdisp/SSD1306/gdisp_lld.mk
index ad320292..13df4230 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld.mk
+++ b/drivers/gdisp/SSD1306/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/SSD1306
-GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c b/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
new file mode 100644
index 00000000..bd3e386d
--- /dev/null
+++ b/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
@@ -0,0 +1,280 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1306/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1306 display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1306
+#include "../drivers/gdisp/SSD1306/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_SSD1306.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		64		// This controller should support 32 (untested) or 64
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		128
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	100
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+#ifdef SSD1306_PAGE_PREFIX
+	#define SSD1306_PAGE_WIDTH		(GDISP_SCREEN_WIDTH+1)
+	#define SSD1306_PAGE_OFFSET		1
+#else
+	#define SSD1306_PAGE_WIDTH		GDISP_SCREEN_WIDTH
+	#define SSD1306_PAGE_OFFSET		0
+#endif
+
+#define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
+
+#include "SSD1306.h"
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some common routines and macros
+#define RAM(g)							((uint8_t *)g->priv)
+#define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); }
+#define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
+
+// Some common routines and macros
+#define delay(us)			gfxSleepMicroseconds(us)
+#define delayms(ms)			gfxSleepMilliseconds(ms)
+
+#define xyaddr(x, y)		(SSD1306_PAGE_OFFSET + (x) + ((y)>>3)*SSD1306_PAGE_WIDTH)
+#define xybit(y)			(1<<((y)&7))
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * As this controller can't update on a pixel boundary we need to maintain the
+ * the entire display surface in memory so that we can do the necessary bit
+ * operations. Fortunately it is a small display in monochrome.
+ * 64 * 128 / 8 = 1024 bytes.
+ */
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	// The private area is the display surface.
+	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH);
+
+	// Fill in the prefix command byte on each page line of the display buffer
+	// We can do it during initialisation as this byte is never overwritten.
+	#ifdef SSD1306_PAGE_PREFIX
+		{
+			unsigned	i;
+
+			for(i=0; i < GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH; i+=SSD1306_PAGE_WIDTH)
+				RAM(g)[i] = SSD1306_PAGE_PREFIX;
+		}
+	#endif
+
+	// Initialise the board interface
+	init_board(g);
+
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
+
+	acquire_bus(g);
+
+	write_cmd(g, SSD1306_DISPLAYOFF);
+	write_cmd2(g, SSD1306_SETDISPLAYCLOCKDIV, 0x80);
+	write_cmd2(g, SSD1306_SETMULTIPLEX, GDISP_SCREEN_HEIGHT-1);
+	write_cmd2(g, SSD1306_SETPRECHARGE, 0x1F);
+	write_cmd2(g, SSD1306_SETDISPLAYOFFSET, 0);
+	write_cmd(g, SSD1306_SETSTARTLINE | 0);
+	write_cmd2(g, SSD1306_ENABLE_CHARGE_PUMP, 0x14);
+	write_cmd2(g, SSD1306_MEMORYMODE, 0);
+	write_cmd(g, SSD1306_SEGREMAP+1);
+	write_cmd(g, SSD1306_COMSCANDEC);
+	#if GDISP_SCREEN_HEIGHT == 64
+		write_cmd2(g, SSD1306_SETCOMPINS, 0x12);
+	#else
+		write_cmd2(g, SSD1306_SETCOMPINS, 0x22);
+	#endif
+	write_cmd2(g, SSD1306_SETCONTRAST, (uint8_t)(GDISP_INITIAL_CONTRAST*256/101));	// Set initial contrast.
+	write_cmd2(g, SSD1306_SETVCOMDETECT, 0x10);
+	write_cmd(g, SSD1306_DISPLAYON);
+	write_cmd(g, SSD1306_NORMALDISPLAY);
+	write_cmd3(g, SSD1306_HV_COLUMN_ADDRESS, 0, GDISP_SCREEN_WIDTH-1);
+	write_cmd3(g, SSD1306_HV_PAGE_ADDRESS, 0, GDISP_SCREEN_HEIGHT/8-1);
+
+    // 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_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		unsigned	i;
+
+		// Don't flush if we don't need it.
+		if (!(g->flags & GDISP_FLG_NEEDFLUSH))
+			return;
+
+		write_cmd(g, SSD1306_SETSTARTLINE | 0);
+
+		for(i=0; i < GDISP_SCREEN_HEIGHT/8 * SSD1306_PAGE_WIDTH; i+=SSD1306_PAGE_WIDTH)
+			write_data(g, RAM(g)+i, SSD1306_PAGE_WIDTH);
+	}
+#endif
+
+#if GDISP_HARDWARE_DRAWPIXEL
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			x = g->p.x;
+			break;
+		}
+		if (g->p.color != Black)
+			RAM(g)[xyaddr(x, y)] |= xybit(y);
+		else
+			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
+		g->flags |= GDISP_FLG_NEEDFLUSH;
+	}
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			y = g->p.x;
+			break;
+		}
+		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
+	}
+#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, SSD1306_DISPLAYOFF);
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_cmd(g, SSD1306_DISPLAYON);
+				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) {
+			/* Rotation is handled by the drawing routines */
+			case GDISP_ROTATE_0:
+			case GDISP_ROTATE_180:
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+			case GDISP_ROTATE_270:
+				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_CONTRAST:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+			acquire_bus(g);
+			write_cmd2(g, SSD1306_SETCONTRAST, (((unsigned)g->p.ptr)<<8)/101);
+			release_bus(g);
+            g->g.Contrast = (unsigned)g->p.ptr;
+			return;
+
+		// Our own special controller code to inverse the display
+		// 0 = normal, 1 = inverse
+		case GDISP_CONTROL_INVERSE:
+			acquire_bus(g);
+			write_cmd(g, g->p.ptr ? SSD1306_INVERTDISPLAY : SSD1306_NORMALDISPLAY);
+			release_bus(g);
+			return;
+		}
+	}
+#endif // GDISP_NEED_CONTROL
+
+#endif // GFX_USE_GDISP
+
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c
deleted file mode 100644
index b94c1a40..00000000
--- a/drivers/gdisp/SSD1963/gdisp_lld.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_SSD1963
-#include "../drivers/gdisp/SSD1963/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#define CALC_PERIOD(w,b,f,p)				(p+b+w+f)
-#define CALC_FPR(w,h,hb,hf,hp,vb,vf,vp,fps)	((fps * CALC_PERIOD(w,hb,hf,hp) * CALC_PERIOD(h,vb,vf,vp) * 1048576)/100000000)
-
-typedef struct LCD_Parameters {
-	coord_t		width, height;					// Panel width and height
-	uint16_t	hbporch;						// Horizontal Back Porch
-	uint16_t	hfporch;						// Horizontal Front Porch
-	uint16_t	hpulse;							// Horizontal Pulse
-	uint16_t	hperiod;						// Horizontal Period (Total)
-	uint16_t	vbporch;						// Vertical Back Porch
-	uint16_t	vfporch;						// Vertical Front Porch
-	uint16_t	vpulse;							// Vertical Pulse
-	uint16_t	vperiod;						// Vertical Period (Total)
-	uint32_t	fpr;							// Calculated FPR
-} LCD_Parameters;
-
-#include "board_SSD1963.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	90
-#endif
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#include "ssd1963.h"
-
-#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
-#define write_data16(g, data)		{ write_data(g, (data)>>8); write_data(g, (data) & 0xFF); }
-
-static inline void set_viewport(GDisplay* g) {
-	write_index(g, SSD1963_SET_PAGE_ADDRESS);
-	write_data16(g, g->p.y);
-	write_data16(g, g->p.y+g->p.cy-1);
-	write_index(g, SSD1963_SET_COLUMN_ADDRESS);
-	write_data16(g, g->p.x);
-	write_data16(g, g->p.x+g->p.cx-1);
-	write_index(g, SSD1963_WRITE_MEMORY_START);
-}
-
-/**
- * The backlight is controlled by the controller.
- */
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	//duty_cycle is 00..FF
-	//Work in progress: the SSD1963 has a built-in PWM, its output can
-	//be used by a Dynamic Background Control or by a host (user)
-	//Check your LCD's hardware, the PWM connection is default left open and instead
-	//connected to a LED connection on the breakout board
-	write_index(g, SSD1963_SET_PWM_CONF);		//set PWM for BackLight
-	write_data(g, 0x01);
-	write_data(g, (55+percent*2) & 0x00FF);
-	write_data(g, 0x01);						//controlled by host (not DBC), enabled
-	write_data(g, 0xFF);
-	write_data(g, 0x60);						//don't let it go too dark, avoid a useless LCD
-	write_data(g, 0x0F);						//prescaler ???
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	LCD_Parameters *	lcdp;
-
-	// The private area for this controller is the LCD timings
-	lcdp = (void *)&DisplayTimings[g->controllerdisplay];
-	g->priv = lcdp;
-
-	// 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_index(g, SSD1963_SOFT_RESET);
-	gfxSleepMilliseconds(5);
-
-	/* Driver PLL config */
-	write_index(g, SSD1963_SET_PLL_MN);
-	write_data(g, 35);								// PLLclk = REFclk (10Mhz) * 36 (360Mhz)
-	write_data(g, 2);								// SYSclk = PLLclk / 3  (120MHz)
-	write_data(g, 4);								// Apply calculation bit, else it is ignored
-	write_reg(g, SSD1963_SET_PLL, 0x01);			// Enable PLL
-	gfxSleepMilliseconds(5);
-	write_reg(g, SSD1963_SET_PLL, 0x03);			// Use PLL
-	gfxSleepMilliseconds(5);
-	write_index(g, SSD1963_SOFT_RESET);
-	gfxSleepMilliseconds(5);
-
-	/* Screen size */
-	write_index(g, SSD1963_SET_GDISP_MODE);
-	write_data(g, 0x18);							//Enabled dithering
-	write_data(g, 0x00);
-	write_data16(g, lcdp->width-1);
-	write_data16(g, lcdp->height-1);
-	write_data(g, 0x00);							// RGB
-
-	write_reg(g, SSD1963_SET_PIXEL_DATA_INTERFACE, SSD1963_PDI_16BIT565);
-
-	/* LCD Clock specs */
-	write_index(g, SSD1963_SET_LSHIFT_FREQ);
-	write_data(g, (lcdp->fpr >> 16) & 0xFF);
-	write_data(g, (lcdp->fpr >> 8) & 0xFF);
-	write_data(g, lcdp->fpr & 0xFF);
-
-	write_index(g, SSD1963_SET_HORI_PERIOD);
-	write_data16(g, lcdp->hperiod);
-	write_data16(g, lcdp->hpulse + lcdp->hbporch);
-	write_data(g, lcdp->hpulse);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-
-	write_index(g, SSD1963_SET_VERT_PERIOD);
-	write_data16(g, lcdp->vperiod);
-	write_data16(g, lcdp->vpulse + lcdp->vbporch);
-	write_data(g, lcdp->vpulse);
-	write_data(g, 0x00);
-	write_data(g, 0x00);
-
-	/* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel (during front/back porch) */
-	write_reg(g, SSD1963_SET_TEAR_ON, 0x00);
-
-	/* Turn on */
-	write_index(g, SSD1963_SET_DISPLAY_ON);
-	
-	/* Turn on the back-light */
-	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
-
-	// Finish Init
-	post_init_board(g);
-
-	// Release the bus
-	release_bus(g);
-
-	/* Initialise the GDISP structure */
-	g->g.Width = lcdp->width;
-	g->g.Height = lcdp->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);
-		set_viewport(g);
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		release_bus(g);
-	}
-#endif
-
-// Not implemented yet.
-#if 0 && 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_index(g, SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
-					gfxSleepMilliseconds(5);
-					write_index(g, SSD1963_SET_DISPLAY_OFF);
-					write_index(g, SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
-					release_bus(g);
-					break;
-				case powerOn:
-					acquire_bus(g);
-					read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep
-					read_reg(0x0000); gfxSleepMilliseconds(5);
-					write_index(g, SSD1963_SET_DISPLAY_ON);
-					release_bus(g);
-					break;
-				case powerSleep:
-					acquire_bus(g);
-					write_index(g, SSD1963_SET_DISPLAY_OFF);
-					write_index(g, SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
-					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;
-			case GDISP_ROTATE_0:
-				acquire_bus(g);
-				/* 	Code here */
-				release_bus(g);
-				g->g.Height = ((LCD_Parameters *)g->priv)->height;
-				g->g.Width = ((LCD_Parameters *)g->priv)->width;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-				/* 	Code here */
-				release_bus(g);
-				g->g.Height = ((LCD_Parameters *)g->priv)->width;
-				g->g.Width = ((LCD_Parameters *)g->priv)->height;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				/* 	Code here */
-				release_bus(g);
-				g->g.Height = ((LCD_Parameters *)g->priv)->height;
-				g->g.Width = ((LCD_Parameters *)g->priv)->width;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-				/* 	Code here */
-				release_bus(g);
-				g->g.Height = ((LCD_Parameters *)g->priv)->width;
-				g->g.Width = ((LCD_Parameters *)g->priv)->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;
-			set_backlight(g, (unsigned)g->p.ptr);
-			g->g.Backlight = (unsigned)g->p.ptr;
-			return;
-
-		//case GDISP_CONTROL_CONTRAST:
-		default:
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.mk b/drivers/gdisp/SSD1963/gdisp_lld.mk
index ad406898..f56f11de 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld.mk
+++ b/drivers/gdisp/SSD1963/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC +=	$(GFXLIB)/drivers/gdisp/SSD1963
-GFXSRC +=	$(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld.c
+GFXSRC +=	$(GFXLIB)/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c b/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
new file mode 100644
index 00000000..b94c1a40
--- /dev/null
+++ b/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
@@ -0,0 +1,285 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD1963/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD1963
+#include "../drivers/gdisp/SSD1963/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#define CALC_PERIOD(w,b,f,p)				(p+b+w+f)
+#define CALC_FPR(w,h,hb,hf,hp,vb,vf,vp,fps)	((fps * CALC_PERIOD(w,hb,hf,hp) * CALC_PERIOD(h,vb,vf,vp) * 1048576)/100000000)
+
+typedef struct LCD_Parameters {
+	coord_t		width, height;					// Panel width and height
+	uint16_t	hbporch;						// Horizontal Back Porch
+	uint16_t	hfporch;						// Horizontal Front Porch
+	uint16_t	hpulse;							// Horizontal Pulse
+	uint16_t	hperiod;						// Horizontal Period (Total)
+	uint16_t	vbporch;						// Vertical Back Porch
+	uint16_t	vfporch;						// Vertical Front Porch
+	uint16_t	vpulse;							// Vertical Pulse
+	uint16_t	vperiod;						// Vertical Period (Total)
+	uint32_t	fpr;							// Calculated FPR
+} LCD_Parameters;
+
+#include "board_SSD1963.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	90
+#endif
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#include "ssd1963.h"
+
+#define write_reg(g, reg, data)		{ write_index(g, reg); write_data(g, data); }
+#define write_data16(g, data)		{ write_data(g, (data)>>8); write_data(g, (data) & 0xFF); }
+
+static inline void set_viewport(GDisplay* g) {
+	write_index(g, SSD1963_SET_PAGE_ADDRESS);
+	write_data16(g, g->p.y);
+	write_data16(g, g->p.y+g->p.cy-1);
+	write_index(g, SSD1963_SET_COLUMN_ADDRESS);
+	write_data16(g, g->p.x);
+	write_data16(g, g->p.x+g->p.cx-1);
+	write_index(g, SSD1963_WRITE_MEMORY_START);
+}
+
+/**
+ * The backlight is controlled by the controller.
+ */
+static inline void set_backlight(GDisplay *g, uint8_t percent) {
+	//duty_cycle is 00..FF
+	//Work in progress: the SSD1963 has a built-in PWM, its output can
+	//be used by a Dynamic Background Control or by a host (user)
+	//Check your LCD's hardware, the PWM connection is default left open and instead
+	//connected to a LED connection on the breakout board
+	write_index(g, SSD1963_SET_PWM_CONF);		//set PWM for BackLight
+	write_data(g, 0x01);
+	write_data(g, (55+percent*2) & 0x00FF);
+	write_data(g, 0x01);						//controlled by host (not DBC), enabled
+	write_data(g, 0xFF);
+	write_data(g, 0x60);						//don't let it go too dark, avoid a useless LCD
+	write_data(g, 0x0F);						//prescaler ???
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	LCD_Parameters *	lcdp;
+
+	// The private area for this controller is the LCD timings
+	lcdp = (void *)&DisplayTimings[g->controllerdisplay];
+	g->priv = lcdp;
+
+	// 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_index(g, SSD1963_SOFT_RESET);
+	gfxSleepMilliseconds(5);
+
+	/* Driver PLL config */
+	write_index(g, SSD1963_SET_PLL_MN);
+	write_data(g, 35);								// PLLclk = REFclk (10Mhz) * 36 (360Mhz)
+	write_data(g, 2);								// SYSclk = PLLclk / 3  (120MHz)
+	write_data(g, 4);								// Apply calculation bit, else it is ignored
+	write_reg(g, SSD1963_SET_PLL, 0x01);			// Enable PLL
+	gfxSleepMilliseconds(5);
+	write_reg(g, SSD1963_SET_PLL, 0x03);			// Use PLL
+	gfxSleepMilliseconds(5);
+	write_index(g, SSD1963_SOFT_RESET);
+	gfxSleepMilliseconds(5);
+
+	/* Screen size */
+	write_index(g, SSD1963_SET_GDISP_MODE);
+	write_data(g, 0x18);							//Enabled dithering
+	write_data(g, 0x00);
+	write_data16(g, lcdp->width-1);
+	write_data16(g, lcdp->height-1);
+	write_data(g, 0x00);							// RGB
+
+	write_reg(g, SSD1963_SET_PIXEL_DATA_INTERFACE, SSD1963_PDI_16BIT565);
+
+	/* LCD Clock specs */
+	write_index(g, SSD1963_SET_LSHIFT_FREQ);
+	write_data(g, (lcdp->fpr >> 16) & 0xFF);
+	write_data(g, (lcdp->fpr >> 8) & 0xFF);
+	write_data(g, lcdp->fpr & 0xFF);
+
+	write_index(g, SSD1963_SET_HORI_PERIOD);
+	write_data16(g, lcdp->hperiod);
+	write_data16(g, lcdp->hpulse + lcdp->hbporch);
+	write_data(g, lcdp->hpulse);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+
+	write_index(g, SSD1963_SET_VERT_PERIOD);
+	write_data16(g, lcdp->vperiod);
+	write_data16(g, lcdp->vpulse + lcdp->vbporch);
+	write_data(g, lcdp->vpulse);
+	write_data(g, 0x00);
+	write_data(g, 0x00);
+
+	/* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel (during front/back porch) */
+	write_reg(g, SSD1963_SET_TEAR_ON, 0x00);
+
+	/* Turn on */
+	write_index(g, SSD1963_SET_DISPLAY_ON);
+	
+	/* Turn on the back-light */
+	set_backlight(g, GDISP_INITIAL_BACKLIGHT);
+
+	// Finish Init
+	post_init_board(g);
+
+	// Release the bus
+	release_bus(g);
+
+	/* Initialise the GDISP structure */
+	g->g.Width = lcdp->width;
+	g->g.Height = lcdp->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);
+		set_viewport(g);
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		release_bus(g);
+	}
+#endif
+
+// Not implemented yet.
+#if 0 && 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_index(g, SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
+					gfxSleepMilliseconds(5);
+					write_index(g, SSD1963_SET_DISPLAY_OFF);
+					write_index(g, SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
+					release_bus(g);
+					break;
+				case powerOn:
+					acquire_bus(g);
+					read_reg(0x0000); gfxSleepMilliseconds(5); // 2x Dummy reads to wake up from deep sleep
+					read_reg(0x0000); gfxSleepMilliseconds(5);
+					write_index(g, SSD1963_SET_DISPLAY_ON);
+					release_bus(g);
+					break;
+				case powerSleep:
+					acquire_bus(g);
+					write_index(g, SSD1963_SET_DISPLAY_OFF);
+					write_index(g, SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
+					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;
+			case GDISP_ROTATE_0:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->height;
+				g->g.Width = ((LCD_Parameters *)g->priv)->width;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->width;
+				g->g.Width = ((LCD_Parameters *)g->priv)->height;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->height;
+				g->g.Width = ((LCD_Parameters *)g->priv)->width;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				/* 	Code here */
+				release_bus(g);
+				g->g.Height = ((LCD_Parameters *)g->priv)->width;
+				g->g.Width = ((LCD_Parameters *)g->priv)->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;
+			set_backlight(g, (unsigned)g->p.ptr);
+			g->g.Backlight = (unsigned)g->p.ptr;
+			return;
+
+		//case GDISP_CONTROL_CONTRAST:
+		default:
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+
diff --git a/drivers/gdisp/SSD2119/gdisp_lld.c b/drivers/gdisp/SSD2119/gdisp_lld.c
deleted file mode 100644
index df05fc2c..00000000
--- a/drivers/gdisp/SSD2119/gdisp_lld.c
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD2119/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD2119 display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_SSD2119
-#include "../drivers/gdisp/SSD2119/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_SSD2119.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		240
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		320
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-#include "ssd2119.h"
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// 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_index(g, reg); write_data(g, data); }
-
-static void set_cursor(GDisplay* g) {
-	/* Reg SSD2119_REG_X_RAM_ADDR is 9 bit value
-	 * Reg SSD2119_REG_Y_RAM_ADDR is an 8 bit
-	 * Use a bit mask to make sure they are not set too high
-	 */
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.x & 0x01FF);
-			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.y & 0x00FF);
-			break;
-		case GDISP_ROTATE_90:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.y & 0x01FF);
-			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x00FF);
-			break;
-		case GDISP_ROTATE_180:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x01FF);
-			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x00FF);
-			break;
-		case GDISP_ROTATE_270:
-			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x01FF);
-			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.x & 0x00FF);
-			break;
-	}
-	write_index(g, SSD2119_REG_RAM_DATA);
-}
-
-static void set_viewport(GDisplay* g) {
-	/* Reg 0x44 - Vertical RAM address position
-	 * 		Upper Byte - VEA
-	 * 		Lower Byte - VSA
-	 * 		0 <= VSA <= VEA <= 0xEF
-	 * Reg 0x45,0x46 - Horizontal RAM address position
-	 * 		Lower 9 bits gives 0-511 range in each value, HSA and HEA respectively
-	 * 		0 <= HSA <= HEA <= 0x13F
-	 */
-	switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.y + g->p.cy - 1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
-			write_reg(g, SSD2119_REG_H_RAM_START, (g->p.x & 0x01FF));
-			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.x + g->p.cx - 1) & 0x01FF);
-			break;
-		case GDISP_ROTATE_90:
-			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x00FF));
-			write_reg(g, SSD2119_REG_H_RAM_START, (g->p.y & 0x01FF));
-			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.y + g->p.cy - 1) & 0x01FF);
-			break;
-		case GDISP_ROTATE_180:
-			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x00FF));
-			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x01FF);
-			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x01FF);
-			break;
-		case GDISP_ROTATE_270:
-			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
-			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x01FF);
-			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x01FF);
-			break;
-	}
-}
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-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);
-
-	// Enter sleep mode (if we are not already there).
-	write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0001);
-	gfxSleepMicroseconds(5);
-
-	// Set initial power parameters.
-	write_reg(g, SSD2119_REG_PWR_CTRL_5, 0x00B2);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_VCOM_OTP_1, 0x0006);
-	gfxSleepMicroseconds(5);
-
-	// Start the oscillator.
-	write_reg(g, SSD2119_REG_OSC_START, 0x0001);
-	gfxSleepMicroseconds(5);
-
-	// Set pixel format and basic display orientation (scanning direction).
-	write_reg(g, SSD2119_REG_OUTPUT_CTRL, 0x30EF);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_LCD_DRIVE_AC_CTRL, 0x0600);
-	gfxSleepMicroseconds(5);
-
-	// Exit sleep mode.
-	write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0000);
-	gfxSleepMicroseconds(5);
-
-	// Configure pixel color format and MCU interface parameters.
-	write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6830); // ENTRY_MODE_DEFAULT
-	gfxSleepMicroseconds(5);
-
-	// Set analog parameters.
-	write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_ANALOG_SET, 0x3800);
-	gfxSleepMicroseconds(5);
-
-	// Enable the display.
-	write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0033);
-	gfxSleepMicroseconds(5);
-
-	// Set VCIX2 voltage to 6.1V.
-	write_reg(g, SSD2119_REG_PWR_CTRL_2, 0x0005);
-	gfxSleepMicroseconds(5);
-
-	// Configure gamma correction.
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_1, 0x0000);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_2, 0x0303);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_3, 0x0407);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_4, 0x0301);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_5, 0x0301);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_6, 0x0403);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_7, 0x0707);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_8, 0x0400);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_9, 0x0a00);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_GAMMA_CTRL_10, 0x1000);
-	gfxSleepMicroseconds(5);
-
-	// Configure Vlcd63 and VCOMl.
-	write_reg(g, SSD2119_REG_PWR_CTRL_3, 0x000A);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_PWR_CTRL_4, 0x2E00);
-	gfxSleepMicroseconds(5);
-
-	// Set the display size and ensure that the GRAM window is set to allow access to the full display buffer.
-	write_reg(g, SSD2119_REG_V_RAM_POS, (GDISP_SCREEN_HEIGHT - 1) << 8);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_H_RAM_START, 0x0000);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_H_RAM_END, GDISP_SCREEN_WIDTH - 1);
-	gfxSleepMicroseconds(5);
-
-	write_reg(g, SSD2119_REG_X_RAM_ADDR, 0x00);
-	gfxSleepMicroseconds(5);
-	write_reg(g, SSD2119_REG_Y_RAM_ADDR, 0x00);
-	gfxSleepMicroseconds(5);
-
-    // Finish Init
-    post_init_board(g);
-
- 	// Release the bus
-	release_bus(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;
-}
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC void gdisp_lld_write_start(GDisplay* g) {
-		acquire_bus(g);
-		set_viewport(g);
-	}
-	LLDSPEC void gdisp_lld_write_color(GDisplay* g) {
-		write_data(g, g->p.color);
-	}
-	LLDSPEC void gdisp_lld_write_stop(GDisplay* g) {
-		release_bus(g);
-	}
-	LLDSPEC void gdisp_lld_write_pos(GDisplay* g) {
-		set_cursor(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC void gdisp_lld_read_start(GDisplay* g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-		setreadmode(g);
-		dummy_read(g);
-	}
-	LLDSPEC color_t gdisp_lld_read_color(GDisplay* g) {
-		return read_data(g);
-	}
-	LLDSPEC void gdisp_lld_read_stop(GDisplay* g) {
-		setwritemode(g);
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
-	LLDSPEC void gdisp_lld_fill_area(GDisplay* g) {
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);	
-		dma_with_noinc(g, &g->p.color, g->p.cx * g->p.cy);
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
-	LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
-		pixel_t*	buffer;
-		coord_t		ynct;
-
-		buffer = (pixel_t*)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
-
-		acquire_bus(g);
-		set_viewport(g);
-		set_cursor(g);
-
-		if (g->p.x2 == g->p.cx) {
-			dma_with_inc(g, buffer, g->p.cx * g->p.cy);
-		} else {
-			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
-				dma_with_inc(g, buffer, g->p.cy);
-		}
-
-		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 powerDeepSleep:
-				acquire_bus(g);
-				write_reg(g, SSD2119_REG_SLEEP_MODE_1,	0x0001);	// Enter sleep mode
-				write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x2999);		// Enable deep sleep function
-				write_reg(g, SSD2119_REG_DISPLAY_CTRL,	0x0000);	// Display off
-				if ((powermode_t)g->p.ptr == powerOff)
-					write_reg(g, SSD2119_REG_OSC_START,	0x0000);	// Turn off oscillator
-				release_bus(g);
-				set_backlight(g, 0);
-				break;
-			case powerSleep:
-				acquire_bus(g);
-				write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0001);		// Enter sleep mode
-				write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0000);		// Display off
-				release_bus(g);
-				set_backlight(g, 0);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				if (g->g.Powermode == powerOff) {
-					write_reg(g, SSD2119_REG_OSC_START, 0x0001);	// Start the oscillator
-					gfxSleepMicroseconds(5);
-					write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
-				} else if (g->g.Powermode == powerDeepSleep)
-					write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
-				write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0000);		// Leave sleep mode
-				write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0033);		// Display on
-				release_bus(g);
-				gfxSleepMicroseconds(25);
-				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:
-				acquire_bus(g);
-				/* ID = 11 AM = 0 */
-				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6830);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus(g);
-				/* ID = 01 AM = 1 */
-				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6818);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_WIDTH;
-				g->g.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus(g);
-				/* ID = 00 AM = 0 */
-				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6800);
-				release_bus(g);
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus(g);
-				/* ID = 10 AM = 1 */
-				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6828);
-				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;
-            set_backlight(g, (unsigned)g->p.ptr);
-            g->g.Backlight = (unsigned)g->p.ptr;
-            return;
-
-		//case GDISP_CONTROL_CONTRAST:
-        default:
-            return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/SSD2119/gdisp_lld.mk b/drivers/gdisp/SSD2119/gdisp_lld.mk
index 46807f62..921eaa2c 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld.mk
+++ b/drivers/gdisp/SSD2119/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/SSD2119
-GFXSRC += $(GFXLIB)/drivers/gdisp/SSD2119/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c b/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
new file mode 100644
index 00000000..df05fc2c
--- /dev/null
+++ b/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
@@ -0,0 +1,401 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/SSD2119/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD2119 display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_SSD2119
+#include "../drivers/gdisp/SSD2119/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_SSD2119.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		240
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		320
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+#include "ssd2119.h"
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// 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_index(g, reg); write_data(g, data); }
+
+static void set_cursor(GDisplay* g) {
+	/* Reg SSD2119_REG_X_RAM_ADDR is 9 bit value
+	 * Reg SSD2119_REG_Y_RAM_ADDR is an 8 bit
+	 * Use a bit mask to make sure they are not set too high
+	 */
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.x & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.y & 0x00FF);
+			break;
+		case GDISP_ROTATE_90:
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, g->p.y & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x00FF);
+			break;
+		case GDISP_ROTATE_180:
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, (GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x00FF);
+			break;
+		case GDISP_ROTATE_270:
+			write_reg(g, SSD2119_REG_X_RAM_ADDR, (GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x01FF);
+			write_reg(g, SSD2119_REG_Y_RAM_ADDR, g->p.x & 0x00FF);
+			break;
+	}
+	write_index(g, SSD2119_REG_RAM_DATA);
+}
+
+static void set_viewport(GDisplay* g) {
+	/* Reg 0x44 - Vertical RAM address position
+	 * 		Upper Byte - VEA
+	 * 		Lower Byte - VSA
+	 * 		0 <= VSA <= VEA <= 0xEF
+	 * Reg 0x45,0x46 - Horizontal RAM address position
+	 * 		Lower 9 bits gives 0-511 range in each value, HSA and HEA respectively
+	 * 		0 <= HSA <= HEA <= 0x13F
+	 */
+	switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.y + g->p.cy - 1) << 8) & 0xFF00 ) | (g->p.y & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (g->p.x & 0x01FF));
+			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.x + g->p.cx - 1) & 0x01FF);
+			break;
+		case GDISP_ROTATE_90:
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT-1 - g->p.x) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.x + g->p.cx)) & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (g->p.y & 0x01FF));
+			write_reg(g, SSD2119_REG_H_RAM_END,   (g->p.y + g->p.cy - 1) & 0x01FF);
+			break;
+		case GDISP_ROTATE_180:
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((GDISP_SCREEN_HEIGHT-1 - g->p.y) & 0x00FF) << 8) | ((GDISP_SCREEN_HEIGHT - (g->p.y + g->p.cy)) & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.x + g->p.cx)) & 0x01FF);
+			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH-1 - g->p.x) & 0x01FF);
+			break;
+		case GDISP_ROTATE_270:
+			write_reg(g, SSD2119_REG_V_RAM_POS,   (((g->p.x + g->p.cx - 1) << 8) & 0xFF00 ) | (g->p.x & 0x00FF));
+			write_reg(g, SSD2119_REG_H_RAM_START, (GDISP_SCREEN_WIDTH - (g->p.y + g->p.cy)) & 0x01FF);
+			write_reg(g, SSD2119_REG_H_RAM_END,   (GDISP_SCREEN_WIDTH-1 - g->p.y) & 0x01FF);
+			break;
+	}
+}
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+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);
+
+	// Enter sleep mode (if we are not already there).
+	write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0001);
+	gfxSleepMicroseconds(5);
+
+	// Set initial power parameters.
+	write_reg(g, SSD2119_REG_PWR_CTRL_5, 0x00B2);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_VCOM_OTP_1, 0x0006);
+	gfxSleepMicroseconds(5);
+
+	// Start the oscillator.
+	write_reg(g, SSD2119_REG_OSC_START, 0x0001);
+	gfxSleepMicroseconds(5);
+
+	// Set pixel format and basic display orientation (scanning direction).
+	write_reg(g, SSD2119_REG_OUTPUT_CTRL, 0x30EF);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_LCD_DRIVE_AC_CTRL, 0x0600);
+	gfxSleepMicroseconds(5);
+
+	// Exit sleep mode.
+	write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0000);
+	gfxSleepMicroseconds(5);
+
+	// Configure pixel color format and MCU interface parameters.
+	write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6830); // ENTRY_MODE_DEFAULT
+	gfxSleepMicroseconds(5);
+
+	// Set analog parameters.
+	write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_ANALOG_SET, 0x3800);
+	gfxSleepMicroseconds(5);
+
+	// Enable the display.
+	write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0033);
+	gfxSleepMicroseconds(5);
+
+	// Set VCIX2 voltage to 6.1V.
+	write_reg(g, SSD2119_REG_PWR_CTRL_2, 0x0005);
+	gfxSleepMicroseconds(5);
+
+	// Configure gamma correction.
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_1, 0x0000);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_2, 0x0303);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_3, 0x0407);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_4, 0x0301);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_5, 0x0301);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_6, 0x0403);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_7, 0x0707);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_8, 0x0400);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_9, 0x0a00);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_GAMMA_CTRL_10, 0x1000);
+	gfxSleepMicroseconds(5);
+
+	// Configure Vlcd63 and VCOMl.
+	write_reg(g, SSD2119_REG_PWR_CTRL_3, 0x000A);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_PWR_CTRL_4, 0x2E00);
+	gfxSleepMicroseconds(5);
+
+	// Set the display size and ensure that the GRAM window is set to allow access to the full display buffer.
+	write_reg(g, SSD2119_REG_V_RAM_POS, (GDISP_SCREEN_HEIGHT - 1) << 8);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_H_RAM_START, 0x0000);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_H_RAM_END, GDISP_SCREEN_WIDTH - 1);
+	gfxSleepMicroseconds(5);
+
+	write_reg(g, SSD2119_REG_X_RAM_ADDR, 0x00);
+	gfxSleepMicroseconds(5);
+	write_reg(g, SSD2119_REG_Y_RAM_ADDR, 0x00);
+	gfxSleepMicroseconds(5);
+
+    // Finish Init
+    post_init_board(g);
+
+ 	// Release the bus
+	release_bus(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;
+}
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC void gdisp_lld_write_start(GDisplay* g) {
+		acquire_bus(g);
+		set_viewport(g);
+	}
+	LLDSPEC void gdisp_lld_write_color(GDisplay* g) {
+		write_data(g, g->p.color);
+	}
+	LLDSPEC void gdisp_lld_write_stop(GDisplay* g) {
+		release_bus(g);
+	}
+	LLDSPEC void gdisp_lld_write_pos(GDisplay* g) {
+		set_cursor(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC void gdisp_lld_read_start(GDisplay* g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+		setreadmode(g);
+		dummy_read(g);
+	}
+	LLDSPEC color_t gdisp_lld_read_color(GDisplay* g) {
+		return read_data(g);
+	}
+	LLDSPEC void gdisp_lld_read_stop(GDisplay* g) {
+		setwritemode(g);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_fill_area(GDisplay* g) {
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);	
+		dma_with_noinc(g, &g->p.color, g->p.cx * g->p.cy);
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
+	LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
+		pixel_t*	buffer;
+		coord_t		ynct;
+
+		buffer = (pixel_t*)g->p.ptr + g->p.x1 + g->p.y1 * g->p.x2;
+
+		acquire_bus(g);
+		set_viewport(g);
+		set_cursor(g);
+
+		if (g->p.x2 == g->p.cx) {
+			dma_with_inc(g, buffer, g->p.cx * g->p.cy);
+		} else {
+			for (ycnt = g->p.cy; ycnt; ycnt--, buffer += g->p.x2)
+				dma_with_inc(g, buffer, g->p.cy);
+		}
+
+		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 powerDeepSleep:
+				acquire_bus(g);
+				write_reg(g, SSD2119_REG_SLEEP_MODE_1,	0x0001);	// Enter sleep mode
+				write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x2999);		// Enable deep sleep function
+				write_reg(g, SSD2119_REG_DISPLAY_CTRL,	0x0000);	// Display off
+				if ((powermode_t)g->p.ptr == powerOff)
+					write_reg(g, SSD2119_REG_OSC_START,	0x0000);	// Turn off oscillator
+				release_bus(g);
+				set_backlight(g, 0);
+				break;
+			case powerSleep:
+				acquire_bus(g);
+				write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0001);		// Enter sleep mode
+				write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0000);		// Display off
+				release_bus(g);
+				set_backlight(g, 0);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				if (g->g.Powermode == powerOff) {
+					write_reg(g, SSD2119_REG_OSC_START, 0x0001);	// Start the oscillator
+					gfxSleepMicroseconds(5);
+					write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
+				} else if (g->g.Powermode == powerDeepSleep)
+					write_reg(g, SSD2119_REG_SLEEP_MODE_2, 0x0999);	// Disable deep sleep function
+				write_reg(g, SSD2119_REG_SLEEP_MODE_1, 0x0000);		// Leave sleep mode
+				write_reg(g, SSD2119_REG_DISPLAY_CTRL, 0x0033);		// Display on
+				release_bus(g);
+				gfxSleepMicroseconds(25);
+				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:
+				acquire_bus(g);
+				/* ID = 11 AM = 0 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6830);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus(g);
+				/* ID = 01 AM = 1 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6818);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_WIDTH;
+				g->g.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus(g);
+				/* ID = 00 AM = 0 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6800);
+				release_bus(g);
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus(g);
+				/* ID = 10 AM = 1 */
+				write_reg(g, SSD2119_REG_ENTRY_MODE, 0x6828);
+				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;
+            set_backlight(g, (unsigned)g->p.ptr);
+            g->g.Backlight = (unsigned)g->p.ptr;
+            return;
+
+		//case GDISP_CONTROL_CONTRAST:
+        default:
+            return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/ST7565/gdisp_lld.c b/drivers/gdisp/ST7565/gdisp_lld.c
deleted file mode 100644
index bd8c7b74..00000000
--- a/drivers/gdisp/ST7565/gdisp_lld.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ST7565/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the ST7565 display.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_ST7565
-#include "../drivers/gdisp/ST7565/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#include "board_ST7565.h"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		64
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		128
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	51
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-#define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
-
-#include "st7565.h"
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-// Some common routines and macros
-#define RAM(g)							((uint8_t *)g->priv)
-#define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); }
-#define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
-
-// Some common routines and macros
-#define delay(us)			gfxSleepMicroseconds(us)
-#define delay_ms(ms)		gfxSleepMilliseconds(ms)
-
-#define xyaddr(x, y)		((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
-#define xybit(y)			(1<<((y)&7))
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-/**
- * As this controller can't update on a pixel boundary we need to maintain the
- * the entire display surface in memory so that we can do the necessary bit
- * operations. Fortunately it is a small display in monochrome.
- * 64 * 128 / 8 = 1024 bytes.
- */
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	// The private area is the display surface.
-	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
-
-	// Initialise the board interface
-	init_board(g);
-
-	// Hardware reset
-	setpin_reset(g, TRUE);
-	gfxSleepMilliseconds(20);
-	setpin_reset(g, FALSE);
-	gfxSleepMilliseconds(20);
-
-	acquire_bus(g);
-
-	write_cmd(g, ST7565_LCD_BIAS_7);
-	write_cmd(g, ST7565_ADC_NORMAL);
-	write_cmd(g, ST7565_COM_SCAN_INC);
-	write_cmd(g, ST7565_START_LINE | 0);
-
-	write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101);
-	write_cmd(g, ST7565_RESISTOR_RATIO | 0x3);
-
-	// turn on voltage converter (VC=1, VR=0, VF=0)
-	write_cmd(g, ST7565_POWER_CONTROL | 0x04);
-	delay_ms(50);
-
-	// turn on voltage regulator (VC=1, VR=1, VF=0)
-	write_cmd(g, ST7565_POWER_CONTROL | 0x06);
-	delay_ms(50);
-
-	// turn on voltage follower (VC=1, VR=1, VF=1)
-	write_cmd(g, ST7565_POWER_CONTROL | 0x07);
-	delay_ms(50);
-
-	write_cmd(g, ST7565_DISPLAY_ON);
-	write_cmd(g, ST7565_ALLON_NORMAL);
-	write_cmd(g, ST7565_POSITIVE_DISPLAY);	// Disable Inversion of display.
-
-	write_cmd(g, ST7565_RMW);
-
-    // 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_FLUSH
-	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
-		unsigned	p;
-
-		// Don't flush if we don't need it.
-		if (!(g->flags & GDISP_FLG_NEEDFLUSH))
-			return;
-
-		acquire_bus(g);
-		for (p = 0; p < 8; p++) {
-			write_cmd(g, ST7565_PAGE | p);
-			write_cmd(g, ST7565_COLUMN_MSB | 0);
-			write_cmd(g, ST7565_COLUMN_LSB | 0);
-			write_cmd(g, ST7565_RMW);
-			write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH);
-		}
-		release_bus(g);
-	}
-#endif
-
-#if GDISP_HARDWARE_DRAWPIXEL
-	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
-		coord_t		x, y;
-
-		switch(g->g.Orientation) {
-		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_HEIGHT-1 - g->p.y;
-			y = g->p.x;
-			break;
-		}
-		if (g->p.color != Black)
-			RAM(g)[xyaddr(x, y)] |= xybit(y);
-		else
-			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
-		g->flags |= GDISP_FLG_NEEDFLUSH;
-	}
-#endif
-
-#if GDISP_HARDWARE_PIXELREAD
-	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
-		coord_t		x, y;
-
-		switch(g->g.Orientation) {
-		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_HEIGHT-1 - g->p.y;
-			x = g->p.x;
-			break;
-		}
-		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
-	}
-#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, ST7565_DISPLAY_OFF);
-				release_bus(g);
-				break;
-			case powerOn:
-				acquire_bus(g);
-				write_cmd(g, ST7565_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) {
-			/* Rotation is handled by the drawing routines */
-			case GDISP_ROTATE_0:
-			case GDISP_ROTATE_180:
-				g->g.Height = GDISP_SCREEN_HEIGHT;
-				g->g.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-			case GDISP_ROTATE_270:
-				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_CONTRAST:
-            if ((unsigned)g->p.ptr > 100)
-            	g->p.ptr = (void *)100;
-			acquire_bus(g);
-			write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F);
-			release_bus(g);
-            g->g.Contrast = (unsigned)g->p.ptr;
-			return;
-		}
-	}
-#endif // GDISP_NEED_CONTROL
-
-#endif // GFX_USE_GDISP
diff --git a/drivers/gdisp/ST7565/gdisp_lld.mk b/drivers/gdisp/ST7565/gdisp_lld.mk
index cf0896e6..9f9c5408 100644
--- a/drivers/gdisp/ST7565/gdisp_lld.mk
+++ b/drivers/gdisp/ST7565/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/ST7565
-GFXSRC += $(GFXLIB)/drivers/gdisp/ST7565/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/ST7565/gdisp_lld_ST7565.c
diff --git a/drivers/gdisp/ST7565/gdisp_lld_ST7565.c b/drivers/gdisp/ST7565/gdisp_lld_ST7565.c
new file mode 100644
index 00000000..bd8c7b74
--- /dev/null
+++ b/drivers/gdisp/ST7565/gdisp_lld_ST7565.c
@@ -0,0 +1,262 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/ST7565/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ST7565 display.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_ST7565
+#include "../drivers/gdisp/ST7565/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#include "board_ST7565.h"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		64
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		128
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	51
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+#define GDISP_FLG_NEEDFLUSH			(GDISP_FLG_DRIVER<<0)
+
+#include "st7565.h"
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+// Some common routines and macros
+#define RAM(g)							((uint8_t *)g->priv)
+#define write_cmd2(g, cmd1, cmd2)		{ write_cmd(g, cmd1); write_cmd(g, cmd2); }
+#define write_cmd3(g, cmd1, cmd2, cmd3)	{ write_cmd(g, cmd1); write_cmd(g, cmd2); write_cmd(g, cmd3); }
+
+// Some common routines and macros
+#define delay(us)			gfxSleepMicroseconds(us)
+#define delay_ms(ms)		gfxSleepMilliseconds(ms)
+
+#define xyaddr(x, y)		((x) + ((y)>>3)*GDISP_SCREEN_WIDTH)
+#define xybit(y)			(1<<((y)&7))
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/**
+ * As this controller can't update on a pixel boundary we need to maintain the
+ * the entire display surface in memory so that we can do the necessary bit
+ * operations. Fortunately it is a small display in monochrome.
+ * 64 * 128 / 8 = 1024 bytes.
+ */
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	// The private area is the display surface.
+	g->priv = gfxAlloc(GDISP_SCREEN_HEIGHT * GDISP_SCREEN_WIDTH / 8);
+
+	// Initialise the board interface
+	init_board(g);
+
+	// Hardware reset
+	setpin_reset(g, TRUE);
+	gfxSleepMilliseconds(20);
+	setpin_reset(g, FALSE);
+	gfxSleepMilliseconds(20);
+
+	acquire_bus(g);
+
+	write_cmd(g, ST7565_LCD_BIAS_7);
+	write_cmd(g, ST7565_ADC_NORMAL);
+	write_cmd(g, ST7565_COM_SCAN_INC);
+	write_cmd(g, ST7565_START_LINE | 0);
+
+	write_cmd2(g, ST7565_CONTRAST, GDISP_INITIAL_CONTRAST*64/101);
+	write_cmd(g, ST7565_RESISTOR_RATIO | 0x3);
+
+	// turn on voltage converter (VC=1, VR=0, VF=0)
+	write_cmd(g, ST7565_POWER_CONTROL | 0x04);
+	delay_ms(50);
+
+	// turn on voltage regulator (VC=1, VR=1, VF=0)
+	write_cmd(g, ST7565_POWER_CONTROL | 0x06);
+	delay_ms(50);
+
+	// turn on voltage follower (VC=1, VR=1, VF=1)
+	write_cmd(g, ST7565_POWER_CONTROL | 0x07);
+	delay_ms(50);
+
+	write_cmd(g, ST7565_DISPLAY_ON);
+	write_cmd(g, ST7565_ALLON_NORMAL);
+	write_cmd(g, ST7565_POSITIVE_DISPLAY);	// Disable Inversion of display.
+
+	write_cmd(g, ST7565_RMW);
+
+    // 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_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		unsigned	p;
+
+		// Don't flush if we don't need it.
+		if (!(g->flags & GDISP_FLG_NEEDFLUSH))
+			return;
+
+		acquire_bus(g);
+		for (p = 0; p < 8; p++) {
+			write_cmd(g, ST7565_PAGE | p);
+			write_cmd(g, ST7565_COLUMN_MSB | 0);
+			write_cmd(g, ST7565_COLUMN_LSB | 0);
+			write_cmd(g, ST7565_RMW);
+			write_data(g, RAM(g) + (p*GDISP_SCREEN_WIDTH), GDISP_SCREEN_WIDTH);
+		}
+		release_bus(g);
+	}
+#endif
+
+#if GDISP_HARDWARE_DRAWPIXEL
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			y = g->p.x;
+			break;
+		}
+		if (g->p.color != Black)
+			RAM(g)[xyaddr(x, y)] |= xybit(y);
+		else
+			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
+		g->flags |= GDISP_FLG_NEEDFLUSH;
+	}
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		coord_t		x, y;
+
+		switch(g->g.Orientation) {
+		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_HEIGHT-1 - g->p.y;
+			x = g->p.x;
+			break;
+		}
+		return (RAM(g)[xyaddr(x, y)] & xybit(y)) ? White : Black;
+	}
+#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, ST7565_DISPLAY_OFF);
+				release_bus(g);
+				break;
+			case powerOn:
+				acquire_bus(g);
+				write_cmd(g, ST7565_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) {
+			/* Rotation is handled by the drawing routines */
+			case GDISP_ROTATE_0:
+			case GDISP_ROTATE_180:
+				g->g.Height = GDISP_SCREEN_HEIGHT;
+				g->g.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+			case GDISP_ROTATE_270:
+				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_CONTRAST:
+            if ((unsigned)g->p.ptr > 100)
+            	g->p.ptr = (void *)100;
+			acquire_bus(g);
+			write_cmd2(g, ST7565_CONTRAST, ((((unsigned)g->p.ptr)<<6)/101) & 0x3F);
+			release_bus(g);
+            g->g.Contrast = (unsigned)g->p.ptr;
+			return;
+		}
+	}
+#endif // GDISP_NEED_CONTROL
+
+#endif // GFX_USE_GDISP
diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c
deleted file mode 100644
index 1a5ad81f..00000000
--- a/drivers/gdisp/TestStub/gdisp_lld.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/TestStub/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source (stub).
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-#define GDISP_DRIVER_VMT			GDISPVMT_TestStub
-#include "../drivers/gdisp/TestStub/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		128
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		128
-#endif
-#ifndef GDISP_INITIAL_CONTRAST
-	#define GDISP_INITIAL_CONTRAST	50
-#endif
-#ifndef GDISP_INITIAL_BACKLIGHT
-	#define GDISP_INITIAL_BACKLIGHT	100
-#endif
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	/* No board interface and no private driver area */
-	g->priv = g->board = 0;
-
-	/* 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_DRAWPIXEL
-	void gdisp_lld_draw_pixel(GDisplay *g) {
-		(void) g;
-	}
-#endif
-
-#if GDISP_HARDWARE_PIXELREAD
-	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
-		(void) g;
-		return 0;
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
diff --git a/drivers/gdisp/TestStub/gdisp_lld.mk b/drivers/gdisp/TestStub/gdisp_lld.mk
index 9394ee9d..d8faa3e9 100644
--- a/drivers/gdisp/TestStub/gdisp_lld.mk
+++ b/drivers/gdisp/TestStub/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/gdisp/TestStub
-GFXSRC += $(GFXLIB)/drivers/gdisp/TestStub/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/gdisp/TestStub/gdisp_lld_TestStub.c
diff --git a/drivers/gdisp/TestStub/gdisp_lld_TestStub.c b/drivers/gdisp/TestStub/gdisp_lld_TestStub.c
new file mode 100644
index 00000000..1a5ad81f
--- /dev/null
+++ b/drivers/gdisp/TestStub/gdisp_lld_TestStub.c
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gdisp/TestStub/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source (stub).
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#define GDISP_DRIVER_VMT			GDISPVMT_TestStub
+#include "../drivers/gdisp/TestStub/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		128
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		128
+#endif
+#ifndef GDISP_INITIAL_CONTRAST
+	#define GDISP_INITIAL_CONTRAST	50
+#endif
+#ifndef GDISP_INITIAL_BACKLIGHT
+	#define GDISP_INITIAL_BACKLIGHT	100
+#endif
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	/* No board interface and no private driver area */
+	g->priv = g->board = 0;
+
+	/* 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_DRAWPIXEL
+	void gdisp_lld_draw_pixel(GDisplay *g) {
+		(void) g;
+	}
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		(void) g;
+		return 0;
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
deleted file mode 100644
index 7d7abb06..00000000
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ /dev/null
@@ -1,1163 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/multiple/Win32/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for Win32.
- */
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_Win32
-#include "../drivers/multiple/Win32/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH	640
-#endif
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT	480
-#endif
-#if GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888
-	#error "GDISP Win32: This driver currently only supports the RGB888 pixel format."
-#endif
-// Setting this to TRUE delays updating the screen
-// to the windows paint routine. Due to the
-// drawing lock this does not add as much speed
-// as might be expected but it is still faster in
-// all tested circumstances and for all operations
-// even draw_pixel().
-// This is probably due to drawing operations being
-// combined as the update regions are merged.
-// The only time you might want to turn this off is
-// if you are debugging drawing and want to see each
-// pixel as it is set.
-#define GDISP_WIN32_USE_INDIRECT_UPDATE		TRUE
-//#define GDISP_WIN32_USE_INDIRECT_UPDATE		FALSE
-
-// How far extra windows (multiple displays) should be offset from the first.
-#define DISPLAY_X_OFFSET		50
-#define DISPLAY_Y_OFFSET		50
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <windows.h>
-#include <wingdi.h>
-#include <assert.h>
-
-#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
-#define GDISP_FLG_HASTOGGLE			(GDISP_FLG_DRIVER<<1)
-#define GDISP_FLG_HASMOUSE			(GDISP_FLG_DRIVER<<2)
-#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
-	#define GDISP_FLG_WSTREAM			(GDISP_FLG_DRIVER<<3)
-	#define GDISP_FLG_WRAPPED			(GDISP_FLG_DRIVER<<4)
-#endif
-
-#if GINPUT_NEED_TOGGLE
-	/* Include toggle support code */
-	#include "ginput/lld/toggle.h"
-#endif
-
-#if GINPUT_NEED_MOUSE
-	/* Include mouse support code */
-	#include "ginput/lld/mouse.h"
-#endif
-
-static DWORD			winThreadId;
-static ATOM				winClass;
-static volatile bool_t	QReady;
-static HANDLE			drawMutex;
-#if GINPUT_NEED_MOUSE
-	static GDisplay *	mouseDisplay;
-#endif
-
-/*===========================================================================*/
-/* Driver local routines    .                                                */
-/*===========================================================================*/
-
-#if GINPUT_NEED_TOGGLE
-	#define WIN32_BUTTON_AREA		16
-#else
-	#define WIN32_BUTTON_AREA		0
-#endif
-
-#define APP_NAME "uGFX"
-
-#define COLOR2BGR(c)	((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF))
-#define BGR2COLOR(c)	COLOR2BGR(c)
-
-typedef struct winPriv {
-	HWND			hwnd;
-	HDC				dcBuffer;
-	HBITMAP			dcBitmap;
-	HBITMAP 		dcOldBitmap;
-	#if GINPUT_NEED_MOUSE
-		coord_t		mousex, mousey;
-		uint16_t	mousebuttons;
-	#endif
-	#if GINPUT_NEED_TOGGLE
-		uint8_t		toggles;
-	#endif
-	#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
-		coord_t		x0, y0, x1, y1;
-		coord_t		x, y;
-	#endif
-} winPriv;
-
-
-static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
-{
-	HDC				dc;
-	PAINTSTRUCT		ps;
-	GDisplay *		g;
-	winPriv *		priv;
-	#if GINPUT_NEED_TOGGLE
-		HBRUSH		hbrOn, hbrOff;
-		HPEN		pen;
-		RECT		rect;
-		HGDIOBJ		old;
-		POINT 		p;
-		coord_t		pos;
-		uint8_t		bit;
-	#endif
-
-	switch (Msg) {
-	case WM_CREATE:
-		// Get our GDisplay structure and attach it to the window
-		g = (GDisplay *)((LPCREATESTRUCT)lParam)->lpCreateParams;
-		priv = (winPriv *)g->priv;
-		SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g);
-
-		// Fill in the private area
-		priv->hwnd = hWnd;
-		dc = GetDC(hWnd);
-		priv->dcBitmap = CreateCompatibleBitmap(dc, g->g.Width, g->g.Height);
-		priv->dcBuffer = CreateCompatibleDC(dc);
-		ReleaseDC(hWnd, dc);
-		priv->dcOldBitmap = SelectObject(priv->dcBuffer, priv->dcBitmap);
-
-		// Mark the window as ready to go
-		g->flags |= GDISP_FLG_READY;
-		break;
-
-	#if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE
-		case WM_LBUTTONDOWN:
-			// Get our GDisplay structure
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-
-			// Handle mouse down on the window
-			#if GINPUT_NEED_MOUSE
-				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
-					priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
-					goto mousemove;
-				}
-			#endif
-
-			// Handle mouse down on the toggle area
-			#if GINPUT_NEED_TOGGLE
-				if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
-					bit = 1 << ((coord_t)LOWORD(lParam)*8/g->g.Width);
-					priv->toggles ^= bit;
-					rect.left = 0;
-					rect.right = GDISP_SCREEN_WIDTH;
-					rect.top = GDISP_SCREEN_HEIGHT;
-					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
-					InvalidateRect(hWnd, &rect, FALSE);
-					UpdateWindow(hWnd);
-					#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
-						ginputToggleWakeup();
-					#endif
-				}
-			#endif
-			break;
-
-		case WM_LBUTTONUP:
-			// Get our GDisplay structure
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-
-			// Handle mouse up on the toggle area
-			#if GINPUT_NEED_TOGGLE
-				if ((g->flags & GDISP_FLG_HASTOGGLE)) {
-					if ((priv->toggles & 0x0F)) {
-						priv->toggles &= ~0x0F;
-						rect.left = 0;
-						rect.right = GDISP_SCREEN_WIDTH;
-						rect.top = GDISP_SCREEN_HEIGHT;
-						rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
-						InvalidateRect(hWnd, &rect, FALSE);
-						UpdateWindow(hWnd);
-						#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
-							ginputToggleWakeup();
-						#endif
-					}
-				}
-			#endif
-
-			// Handle mouse up on the window
-			#if GINPUT_NEED_MOUSE
-				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
-					priv->mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
-					goto mousemove;
-				}
-			#endif
-			break;
-	#endif
-
-	#if GINPUT_NEED_MOUSE
-		case WM_MBUTTONDOWN:
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
-				priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
-				goto mousemove;
-			}
-			break;
-		case WM_MBUTTONUP:
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
-				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
-				goto mousemove;
-			}
-			break;
-		case WM_RBUTTONDOWN:
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
-				priv->mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
-				goto mousemove;
-			}
-			break;
-		case WM_RBUTTONUP:
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
-				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
-				goto mousemove;
-			}
-			break;
-		case WM_MOUSEMOVE:
-			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			priv = (winPriv *)g->priv;
-			if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT || !(g->flags & GDISP_FLG_HASMOUSE))
-				break;
-		mousemove:
-			priv->mousex = (coord_t)LOWORD(lParam);
-			priv->mousey = (coord_t)HIWORD(lParam);
-			#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
-				ginputMouseWakeup();
-			#endif
-			break;
-	#endif
-
-	case WM_SYSKEYDOWN:
-	case WM_KEYDOWN:
-	case WM_SYSKEYUP:
-	case WM_KEYUP:
-		break;
-	case WM_CHAR:
-	case WM_DEADCHAR:
-	case WM_SYSCHAR:
-	case WM_SYSDEADCHAR:
-		break;
-
-	case WM_ERASEBKGND:
-		// Pretend we have erased the background.
-		// We know we don't really need to do this as we
-		// redraw the entire surface in the WM_PAINT handler.
-		return TRUE;
-
-	case WM_PAINT:
-		// Get our GDisplay structure
-		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-		priv = (winPriv *)g->priv;
-
-		// Paint the main window area
-		WaitForSingleObject(drawMutex, INFINITE);
-		dc = BeginPaint(hWnd, &ps);
-		BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
-			ps.rcPaint.right - ps.rcPaint.left,
-			(ps.rcPaint.bottom > GDISP_SCREEN_HEIGHT ? GDISP_SCREEN_HEIGHT : ps.rcPaint.bottom) - ps.rcPaint.top,
-			priv->dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
-
-		// Paint the toggle area
-		#if GINPUT_NEED_TOGGLE
-			if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
-				pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black));
-				hbrOn = CreateSolidBrush(COLOR2BGR(Blue));
-				hbrOff = CreateSolidBrush(COLOR2BGR(Gray));
-				old = SelectObject(dc, pen);
-				MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p);
-				LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
-				for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) {
-					rect.left = pos;
-					rect.right = pos + GDISP_SCREEN_WIDTH/8;
-					rect.top = GDISP_SCREEN_HEIGHT;
-					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
-					FillRect(dc, &rect, (priv->toggles & bit) ? hbrOn : hbrOff);
-					if (pos > 0) {
-						MoveToEx(dc, rect.left, rect.top, &p);
-						LineTo(dc, rect.left, rect.bottom);
-					}
-				}
-				DeleteObject(hbrOn);
-				DeleteObject(hbrOff);
-				SelectObject(dc, old);
-			}
-		#endif
-		EndPaint(hWnd, &ps);
-		ReleaseMutex(drawMutex);
-		break;
-
-	case WM_DESTROY:
-		// Get our GDisplay structure
-		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-		priv = (winPriv *)g->priv;
-
-		// Restore the window and free our bitmaps
-		SelectObject(priv->dcBuffer, priv->dcOldBitmap);
-		DeleteDC(priv->dcBuffer);
-		DeleteObject(priv->dcBitmap);
-
-		// Cleanup the private area
-		gfxFree(priv);
-
-		// Quit the application
-		PostQuitMessage(0);
-
-		// Actually the above doesn't work (who knows why)
-		ExitProcess(0);
-		break;
-
-	default:
-		return DefWindowProc(hWnd, Msg, wParam, lParam);
-	}
-	return 0;
-}
-
-static DECLARE_THREAD_STACK(waWindowThread, 1024);
-static DECLARE_THREAD_FUNCTION(WindowThread, param) {
-	(void)param;
-	MSG msg;
-
-	// Establish this thread as a message queue thread
-	winThreadId = GetCurrentThreadId();
-	PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
-	QReady = TRUE;
-
-	do {
-		gfxSleepMilliseconds(1);
-		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
-			// Is this our special thread message to create a new window?
-			if (!msg.hwnd && msg.message == WM_USER) {
-				RECT		rect;
-				GDisplay	*g;
-
-				g = (GDisplay *)msg.lParam;
-
-				// Set the window rectangle
-				rect.top = 0; rect.bottom = g->g.Height;
-				rect.left = 0; rect.right = g->g.Width;
-				#if GINPUT_NEED_TOGGLE
-					if ((g->flags & GDISP_FLG_HASTOGGLE))
-						rect.bottom += WIN32_BUTTON_AREA;
-				#endif
-				AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
-
-				// Create the window
-				msg.hwnd = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_BORDER, msg.wParam*DISPLAY_X_OFFSET, msg.wParam*DISPLAY_Y_OFFSET,
-								rect.right-rect.left, rect.bottom-rect.top, 0, 0,
-								GetModuleHandle(NULL), g);
-				assert(msg.hwnd != NULL);
-
-			// Or just a normal window message
-			} else {
-				TranslateMessage(&msg);
-				DispatchMessage(&msg);
-			}
-		}
-	} while (msg.message != WM_QUIT);
-	ExitProcess(0);
-	return msg.wParam;
-}
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	winPriv	*	priv;
-	char		buf[132];
-
-	// Initialise the window thread and the window class (if it hasn't been done already)
-	if (!QReady) {
-		gfxThreadHandle	hth;
-		WNDCLASS		wc;
-
-		// Create the draw mutex
-		drawMutex = CreateMutex(NULL, FALSE, NULL);
-
-		// Create the thread
-		hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0);
-		assert(hth != NULL);
-		gfxThreadClose(hth);
-
-		wc.style           = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
-		wc.lpfnWndProc     = (WNDPROC)myWindowProc;
-		wc.cbClsExtra      = 0;
-		wc.cbWndExtra      = 0;
-		wc.hInstance       = GetModuleHandle(NULL);
-		wc.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
-		wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
-		wc.hbrBackground   = GetStockObject(WHITE_BRUSH);
-		wc.lpszMenuName    = NULL;
-		wc.lpszClassName   = APP_NAME;
-		winClass = RegisterClass(&wc);
-		assert(winClass != 0);
-
-		// Wait for our thread to be ready
-		while (!QReady)
-			Sleep(1);
-	}
-
-	// Initialise the GDISP structure
-	g->g.Orientation = GDISP_ROTATE_0;
-	g->g.Powermode = powerOn;
-	g->g.Backlight = 100;
-	g->g.Contrast = 50;
-	g->g.Width = GDISP_SCREEN_WIDTH;
-	g->g.Height = GDISP_SCREEN_HEIGHT;
-
-	// Turn on toggles for the first GINPUT_TOGGLE_CONFIG_ENTRIES windows
-	#if GINPUT_NEED_TOGGLE
-		if (g->controllerdisplay < GINPUT_TOGGLE_CONFIG_ENTRIES)
-			g->flags |= GDISP_FLG_HASTOGGLE;
-	#endif
-
-	// Only turn on mouse on the first window for now
-	#if GINPUT_NEED_MOUSE
-		if (!g->controllerdisplay) {
-			mouseDisplay = g;
-			g->flags |= GDISP_FLG_HASMOUSE;
-		}
-	#endif
-
-	// Create a private area for this window
-	priv = (winPriv *)gfxAlloc(sizeof(winPriv));
-	assert(priv != NULL);
-	memset(priv, 0, sizeof(winPriv));
-	g->priv = priv;
-	#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
-		// Initialise with an invalid window
-		g->flags &= ~GDISP_FLG_WSTREAM;
-	#endif
-	g->board = 0;			// no board interface for this controller
-
-	// Create the window in the message thread
-	PostThreadMessage(winThreadId, WM_USER, (WPARAM)g->controllerdisplay, (LPARAM)g);
-
-	// Wait for the window creation to complete (for safety)
-	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
-		Sleep(1);
-
-	sprintf(buf, APP_NAME " - %u", g->systemdisplay+1);
-	SetWindowText(priv->hwnd, buf);
-	ShowWindow(priv->hwnd, SW_SHOW);
-	UpdateWindow(priv->hwnd);
-
-	return TRUE;
-}
-
-#if GDISP_HARDWARE_FLUSH
-	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
-		winPriv	*	priv;
-
-		priv = g->priv;
-		UpdateWindow(priv->hwnd);
-	}
-#endif
-
-#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
-	void BAD_PARAMETER(const char *msg) {
-		volatile int a;
-		// This is really just a point for us to set the debugger
-		a = 0;
-	}
-#endif
-
-#if GDISP_HARDWARE_STREAM_WRITE
-	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
-		winPriv	*	priv;
-
-		if (g->flags & GDISP_FLG_WSTREAM)
-			BAD_PARAMETER("write_start: already in streaming mode");
-		if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
-			BAD_PARAMETER("write_start: bad window parameter");
-
-		priv = g->priv;
-		priv->x0 = g->p.x;	priv->x1 = g->p.x + g->p.cx - 1;
-		priv->y0 = g->p.y;	priv->y1 = g->p.y + g->p.cy - 1;
-		#if GDISP_HARDWARE_STREAM_POS
-			priv->x = g->p.x-1;			// Make sure these values are invalid (for testing)
-			priv->y = g->p.y-1;
-		#else
-			priv->x = g->p.x;
-			priv->y = g->p.y;
-		#endif
-		g->flags |= GDISP_FLG_WSTREAM;
-		g->flags &= ~GDISP_FLG_WRAPPED;
-	}
-	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		winPriv	*	priv;
-		int			x, y;
-		COLORREF	color;
-
-		priv = g->priv;
-		color = COLOR2BGR(g->p.color);
-
-		if (!(g->flags & GDISP_FLG_WSTREAM))
-			BAD_PARAMETER("write_color: not in streaming mode");
-		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
-			BAD_PARAMETER("write_color: cursor outside streaming area");
-		if (g->flags & GDISP_FLG_WRAPPED) {
-			BAD_PARAMETER("write_color: Warning - Area wrapped.");
-			g->flags &= ~GDISP_FLG_WRAPPED;
-		}
-
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				x = priv->x;
-				y = priv->y;
-				break;
-			case GDISP_ROTATE_90:
-				x = priv->y;
-				y = g->g.Width - 1 - priv->x;
-				break;
-			case GDISP_ROTATE_180:
-				x = g->g.Width - 1 - priv->x;
-				y = g->g.Height - 1 - priv->y;
-				break;
-			case GDISP_ROTATE_270:
-				x = g->g.Height - 1 - priv->y;
-				y = priv->x;
-				break;
-			}
-		#else
-			x = priv->x;
-			y = priv->y;
-		#endif
-
-		// Draw the pixel on the screen and in the buffer.
-		WaitForSingleObject(drawMutex, INFINITE);
-		SetPixel(priv->dcBuffer, x, y, color);
-		#if GDISP_WIN32_USE_INDIRECT_UPDATE
-			ReleaseMutex(drawMutex);
-			{
-				RECT	r;
-				r.left = x; r.right = x+1;
-				r.top = y; r.bottom = y+1;
-				InvalidateRect(priv->hwnd, &r, FALSE);
-			}
-		#else
-			{
-				HDC		dc;
-				dc = GetDC(priv->hwnd);
-				SetPixel(dc, x, y, color);
-				ReleaseDC(priv->hwnd, dc);
-				ReleaseMutex(drawMutex);
-			}
-		#endif
-
-		// Update the cursor
-		if (++priv->x > priv->x1) {
-			priv->x = priv->x0;
-			if (++priv->y > priv->y1) {
-				g->flags |= GDISP_FLG_WRAPPED;
-				priv->y = priv->y0;
-			}
-		}
-	}
-	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
-		if (!(g->flags & GDISP_FLG_WSTREAM))
-			BAD_PARAMETER("write_stop: not in streaming mode");
-		g->flags &= ~GDISP_FLG_WSTREAM;
-	}
-	#if GDISP_HARDWARE_STREAM_POS
-		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-			winPriv	*	priv;
-
-			priv = g->priv;
-
-			if (!(g->flags & GDISP_FLG_WSTREAM))
-				BAD_PARAMETER("write_pos: not in streaming mode");
-			if (g->p.x < priv->x0 || g->p.x > priv->x1 || g->p.y < priv->y0 || g->p.y > priv->y1)
-				BAD_PARAMETER("write_color: new cursor outside streaming area");
-			priv->x = g->p.x;
-			priv->y = g->p.y;
-		}
-	#endif
-#endif
-
-#if GDISP_HARDWARE_STREAM_READ
-	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
-		winPriv	*	priv;
-
-		if (g->flags & GDISP_FLG_WSTREAM)
-			BAD_PARAMETER("read_start: already in streaming mode");
-		if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
-			BAD_PARAMETER("read_start: bad window parameter");
-
-		priv = g->priv;
-		priv->x0 = g->p.x;	priv->x1 = g->p.x + g->p.cx - 1;
-		priv->y0 = g->p.y;	priv->y1 = g->p.y + g->p.cy - 1;
-		priv->x = g->p.x;
-		priv->y = g->p.y;
-		g->flags |= GDISP_FLG_WSTREAM;
-		g->flags &= ~GDISP_FLG_WRAPPED;
-	}
-	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		winPriv	*	priv;
-		COLORREF	color;
-
-		priv = g->priv;
-
-		if (!(g->flags & GDISP_FLG_WSTREAM))
-			BAD_PARAMETER("read_color: not in streaming mode");
-		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
-			BAD_PARAMETER("read_color: cursor outside streaming area");
-		if (g->flags & GDISP_FLG_WRAPPED) {
-			BAD_PARAMETER("read_color: Warning - Area wrapped.");
-			g->flags &= ~GDISP_FLG_WRAPPED;
-		}
-
-		WaitForSingleObject(drawMutex, INFINITE);
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
-				break;
-			case GDISP_ROTATE_90:
-				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
-				break;
-			case GDISP_ROTATE_180:
-				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
-				break;
-			case GDISP_ROTATE_270:
-				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
-				break;
-			}
-		#else
-			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
-		#endif
-		ReleaseMutex(drawMutex);
-
-		// Update the cursor
-		if (++priv->x > priv->x1) {
-			priv->x = priv->x0;
-			if (++priv->y > priv->y1) {
-				g->flags |= GDISP_FLG_WRAPPED;
-				priv->y = priv->y0;
-			}
-		}
-
-		return BGR2COLOR(color);
-	}
-	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
-		if (!(g->flags & GDISP_FLG_WSTREAM))
-			BAD_PARAMETER("write_stop: not in streaming mode");
-		g->flags &= ~GDISP_FLG_WSTREAM;
-	}
-#endif
-
-#if GDISP_HARDWARE_DRAWPIXEL
-	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
-		winPriv	*	priv;
-		int			x, y;
-		COLORREF	color;
-	
-		priv = g->priv;
-		color = COLOR2BGR(g->p.color);
-	
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				x = g->p.x;
-				y = g->p.y;
-				break;
-			case GDISP_ROTATE_90:
-				x = g->p.y;
-				y = g->g.Width - 1 - g->p.x;
-				break;
-			case GDISP_ROTATE_180:
-				x = g->g.Width - 1 - g->p.x;
-				y = g->g.Height - 1 - g->p.y;
-				break;
-			case GDISP_ROTATE_270:
-				x = g->g.Height - 1 - g->p.y;
-				y = g->p.x;
-				break;
-			}
-		#else
-			x = g->p.x;
-			y = g->p.y;
-		#endif
-
-		// Draw the pixel on the screen and in the buffer.
-		WaitForSingleObject(drawMutex, INFINITE);
-		SetPixel(priv->dcBuffer, x, y, color);
-		#if GDISP_WIN32_USE_INDIRECT_UPDATE
-			ReleaseMutex(drawMutex);
-			{
-				RECT	r;
-				r.left = x; r.right = x+1;
-				r.top = y; r.bottom = y+1;
-				InvalidateRect(priv->hwnd, &r, FALSE);
-			}
-		#else
-			{
-				HDC		dc;
-				dc = GetDC(priv->hwnd);
-				SetPixel(dc, x, y, color);
-				ReleaseDC(priv->hwnd, dc);
-				ReleaseMutex(drawMutex);
-			}
-		#endif
-	}
-#endif
-
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_FILLS
-	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
-		winPriv	*	priv;
-		RECT		rect;
-		HBRUSH		hbr;
-		COLORREF	color;
-
-		priv = g->priv;
-		color = COLOR2BGR(g->p.color);
-		hbr = CreateSolidBrush(color);
-
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				rect.top = g->p.y;
-				rect.bottom = rect.top + g->p.cy;
-				rect.left = g->p.x;
-				rect.right = rect.left + g->p.cx;
-				break;
-			case GDISP_ROTATE_90:
-				rect.bottom = g->g.Width - g->p.x;
-				rect.top = rect.bottom - g->p.cx;
-				rect.left = g->p.y;
-				rect.right = rect.left + g->p.cy;
-				break;
-			case GDISP_ROTATE_180:
-				rect.bottom = g->g.Height - g->p.y;
-				rect.top = rect.bottom - g->p.cy;
-				rect.right = g->g.Width - g->p.x;
-				rect.left = rect.right - g->p.cx;
-				break;
-			case GDISP_ROTATE_270:
-				rect.top = g->p.x;
-				rect.bottom = rect.top + g->p.cx;
-				rect.right = g->g.Height - g->p.y;
-				rect.left = rect.right - g->p.cy;
-				break;
-			}
-		#else
-			rect.top = g->p.y;
-			rect.bottom = rect.top + g->p.cy;
-			rect.left = g->p.x;
-			rect.right = rect.left + g->p.cx;
-		#endif
-
-
-		WaitForSingleObject(drawMutex, INFINITE);
-		FillRect(priv->dcBuffer, &rect, hbr);
-		#if GDISP_WIN32_USE_INDIRECT_UPDATE
-			ReleaseMutex(drawMutex);
-			InvalidateRect(priv->hwnd, &rect, FALSE);
-		#else
-			{
-				HDC		dc;
-				dc = GetDC(priv->hwnd);
-				FillRect(dc, &rect, hbr);
-				ReleaseDC(priv->hwnd, dc);
-				ReleaseMutex(drawMutex);
-			}
-		#endif
-
-		DeleteObject(hbr);
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL
-	static pixel_t *rotateimg(GDisplay *g, const pixel_t *buffer) {
-		pixel_t	*dstbuf;
-		pixel_t	*dst;
-		const pixel_t	*src;
-		size_t	sz;
-		coord_t	i, j;
-
-		// Allocate the destination buffer
-		sz = (size_t)g->p.cx * (size_t)g->p.cy;
-		if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
-			return 0;
-		
-		// Copy the bits we need
-		switch(g->g.Orientation) {
-		case GDISP_ROTATE_0:
-			return 0;					// not handled as it doesn't need to be.
-		case GDISP_ROTATE_90:
-			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
-				dst = dstbuf+sz-g->p.cy+j;
-				for(i = 0; i < g->p.cx; i++, dst -= g->p.cy)
-					*dst = *src++;
-			}
-			break;
-		case GDISP_ROTATE_180:
-			for(dst = dstbuf+sz, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx)
-				for(i = 0; i < g->p.cx; i++)
-					*--dst = *src++;
-			break;
-		case GDISP_ROTATE_270:
-			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
-				dst = dstbuf+g->p.cy-j-1;
-				for(i = 0; i < g->p.cx; i++, dst += g->p.cy)
-					*dst = *src++;
-			}
-			break;
-		}
-		return dstbuf;
-	}
-#endif
-	
-#if GDISP_HARDWARE_BITFILLS
-	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
-		winPriv	*		priv;
-		pixel_t	*		buffer;
-		RECT			rect;
-		BITMAPV4HEADER	bmpInfo;
-
-		// Make everything relative to the start of the line
-		priv = g->priv;
-		buffer = g->p.ptr;
-		buffer += g->p.x2*g->p.y1;
-		
-		memset(&bmpInfo, 0, sizeof(bmpInfo));
-		bmpInfo.bV4Size = sizeof(bmpInfo);
-		bmpInfo.bV4Planes = 1;
-		bmpInfo.bV4BitCount = sizeof(pixel_t)*8;
-		bmpInfo.bV4AlphaMask = 0;
-		bmpInfo.bV4RedMask		= RGB2COLOR(255,0,0);
-		bmpInfo.bV4GreenMask	= RGB2COLOR(0,255,0);
-		bmpInfo.bV4BlueMask		= RGB2COLOR(0,0,255);
-		bmpInfo.bV4V4Compression = BI_BITFIELDS;
-		bmpInfo.bV4XPelsPerMeter = 3078;
-		bmpInfo.bV4YPelsPerMeter = 3078;
-		bmpInfo.bV4ClrUsed = 0;
-		bmpInfo.bV4ClrImportant = 0;
-		bmpInfo.bV4CSType = 0; //LCS_sRGB;
-
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
-				bmpInfo.bV4Width = g->p.x2;
-				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
-				rect.top = g->p.y;
-				rect.bottom = rect.top+g->p.cy;
-				rect.left = g->p.x;
-				rect.right = rect.left+g->p.cx;
-				break;
-			case GDISP_ROTATE_90:
-				if (!(buffer = rotateimg(g, buffer))) return;
-				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
-				bmpInfo.bV4Width = g->p.cy;
-				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
-				rect.bottom = g->g.Width - g->p.x;
-				rect.top = rect.bottom-g->p.cx;
-				rect.left = g->p.y;
-				rect.right = rect.left+g->p.cy;
-				break;
-			case GDISP_ROTATE_180:
-				if (!(buffer = rotateimg(g, buffer))) return;
-				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
-				bmpInfo.bV4Width = g->p.cx;
-				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
-				rect.bottom = g->g.Height-1 - g->p.y;
-				rect.top = rect.bottom-g->p.cy;
-				rect.right = g->g.Width - g->p.x;
-				rect.left = rect.right-g->p.cx;
-				break;
-			case GDISP_ROTATE_270:
-				if (!(buffer = rotateimg(g, buffer))) return;
-				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
-				bmpInfo.bV4Width = g->p.cy;
-				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
-				rect.top = g->p.x;
-				rect.bottom = rect.top+g->p.cx;
-				rect.right = g->g.Height - g->p.y;
-				rect.left = rect.right-g->p.cy;
-				break;
-			}
-		#else
-			bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
-			bmpInfo.bV4Width = g->p.x2;
-			bmpInfo.bV4Height = -g->p.cy; /* top-down image */
-			rect.top = g->p.y;
-			rect.bottom = rect.top+g->p.cy;
-			rect.left = g->p.x;
-			rect.right = rect.left+g->p.cx;
-		#endif
-
-		WaitForSingleObject(drawMutex, INFINITE);
-		SetDIBitsToDevice(priv->dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-		#if GDISP_WIN32_USE_INDIRECT_UPDATE
-			ReleaseMutex(drawMutex);
-			InvalidateRect(priv->hwnd, &rect, FALSE);
-		#else
-			{
-				HDC		dc;
-				dc = GetDC(priv->hwnd);
-				SetDIBitsToDevice(dc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
-				ReleaseDC(priv->hwnd, dc);
-				ReleaseMutex(drawMutex);
-			}
-		#endif
-
-		#if GDISP_NEED_CONTROL
-			if (buffer != (pixel_t *)g->p.ptr)
-				free(buffer);
-		#endif
-	}
-#endif
-
-#if GDISP_HARDWARE_PIXELREAD
-	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
-		winPriv	*	priv;
-		COLORREF	color;
-
-		priv = g->priv;
-
-		WaitForSingleObject(drawMutex, INFINITE);
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
-				break;
-			case GDISP_ROTATE_90:
-				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
-				break;
-			case GDISP_ROTATE_180:
-				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
-				break;
-			case GDISP_ROTATE_270:
-				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
-				break;
-			}
-		#else
-			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
-		#endif
-		ReleaseMutex(drawMutex);
-		
-		return BGR2COLOR(color);
-	}
-#endif
-
-#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
-	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
-		winPriv	*	priv;
-		RECT		rect;
-		coord_t		lines;
-		
-		priv = g->priv;
-
-		#if GDISP_NEED_CONTROL
-			switch(g->g.Orientation) {
-			case GDISP_ROTATE_0:
-				rect.top = g->p.y;
-				rect.bottom = rect.top+g->p.cy;
-				rect.left = g->p.x;
-				rect.right = rect.left+g->p.cx;
-				lines = -g->p.y1;
-				goto vertical_scroll;
-			case GDISP_ROTATE_90:
-				rect.bottom = g->g.Width - g->p.x;
-				rect.top = rect.bottom-g->p.cx;
-				rect.left = g->p.y;
-				rect.right = rect.left+g->p.cy;
-				lines = -g->p.y1;
-				goto horizontal_scroll;
-			case GDISP_ROTATE_180:
-				rect.bottom = g->g.Height - g->p.y;
-				rect.top = rect.bottom-g->p.cy;
-				rect.right = g->g.Width - g->p.x;
-				rect.left = rect.right-g->p.cx;
-				lines = g->p.y1;
-			vertical_scroll:
-				if (lines > 0) {
-					rect.bottom -= lines;
-				} else {
-					rect.top -= lines;
-				}
-				if (g->p.cy >= lines && g->p.cy >= -lines) {
-					WaitForSingleObject(drawMutex, INFINITE);
-					ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
-					#if GDISP_WIN32_USE_INDIRECT_UPDATE
-						ReleaseMutex(drawMutex);
-						InvalidateRect(priv->hwnd, &rect, FALSE);
-					#else
-						{
-							HDC		dc;
-							dc = GetDC(priv->hwnd);
-							ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
-							ReleaseDC(priv->hwnd, dc);
-							ReleaseMutex(drawMutex);
-						}
-					#endif
-				}
-				break;
-			case GDISP_ROTATE_270:
-				rect.top = g->p.x;
-				rect.bottom = rect.top+g->p.cx;
-				rect.right = g->g.Height - g->p.y;
-				rect.left = rect.right-g->p.cy;
-				lines = g->p.y1;
-			horizontal_scroll:
-				if (lines > 0) {
-					rect.right -= lines;
-				} else {
-					rect.left -= lines;
-				}
-				if (g->p.cy >= lines && g->p.cy >= -lines) {
-					WaitForSingleObject(drawMutex, INFINITE);
-					ScrollDC(priv->dcBuffer, lines, 0, &rect, 0, 0, 0);
-					#if GDISP_WIN32_USE_INDIRECT_UPDATE
-						ReleaseMutex(drawMutex);
-						InvalidateRect(priv->hwnd, &rect, FALSE);
-					#else
-						{
-							HDC		dc;
-							dc = GetDC(priv->hwnd);
-							ScrollDC(dc, lines, 0, &rect, 0, 0, 0);
-							ReleaseDC(priv->hwnd, dc);
-							ReleaseMutex(drawMutex);
-						}
-					#endif
-				}
-				break;
-			}
-		#else
-			rect.top = g->p.y;
-			rect.bottom = rect.top+g->p.cy;
-			rect.left = g->p.x;
-			rect.right = rect.left+g->p.cx;
-			lines = -g->p.y1;
-			if (lines > 0) {
-				rect.bottom -= lines;
-			} else {
-				rect.top -= lines;
-			}
-			if (g->p.cy >= lines && g->p.cy >= -lines) {
-				WaitForSingleObject(drawMutex, INFINITE);
-				ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
-				#if GDISP_WIN32_USE_INDIRECT_UPDATE
-					ReleaseMutex(drawMutex);
-					InvalidateRect(priv->hwnd, &rect, FALSE);
-				#else
-					{
-						HDC		dc;
-						dc = GetDC(priv->hwnd);
-						ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
-						ReleaseDC(priv->hwnd, dc);
-						ReleaseMutex(drawMutex);
-					}
-				#endif
-			}
-		#endif
-	}
-#endif
-
-#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
-	LLDSPEC void gdisp_lld_control(GDisplay *g) {
-		switch(g->p.x) {
-		case GDISP_CONTROL_ORIENTATION:
-			if (g->g.Orientation == (orientation_t)g->p.ptr)
-				return;
-			switch((orientation_t)g->p.ptr) {
-				case GDISP_ROTATE_0:
-				case GDISP_ROTATE_180:
-					g->g.Width = GDISP_SCREEN_WIDTH;
-					g->g.Height = GDISP_SCREEN_HEIGHT;
-					break;
-				case GDISP_ROTATE_90:
-				case GDISP_ROTATE_270:
-					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_POWER:
-		case GDISP_CONTROL_BACKLIGHT:
-		case GDISP_CONTROL_CONTRAST:
-*/
-		}
-	}
-#endif
-
-#if GINPUT_NEED_MOUSE
-	void ginput_lld_mouse_init(void) {}
-	void ginput_lld_mouse_get_reading(MouseReading *pt) {
-		GDisplay *	g;
-		winPriv	*	priv;
-
-		g = mouseDisplay;
-		priv = g->priv;
-
-		pt->x = priv->mousex;
-		pt->y = priv->mousey > g->g.Height ? g->g.Height : priv->mousey;
-		pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
-		pt->buttons = priv->mousebuttons;
-	}
-#endif /* GINPUT_NEED_MOUSE */
-
-#if GINPUT_NEED_TOGGLE
-	#if GINPUT_TOGGLE_CONFIG_ENTRIES > GDISP_DRIVER_COUNT_WIN32
-		#error "GDISP Win32: GINPUT_TOGGLE_CONFIG_ENTRIES must not be greater than GDISP_DRIVER_COUNT_WIN32"
-	#endif
-
-	GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES];
-
-	void ginput_lld_toggle_init(const GToggleConfig *ptc) {
-		// Save the associated window struct
-		ptc->id = &GDISP_WIN32[ptc - GInputToggleConfigTable];
-
-		// We have 8 buttons per window.
-		ptc->mask = 0xFF;
-
-		// No inverse or special mode
-		ptc->invert = 0x00;
-		ptc->mode = 0;
-	}
-	unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) {
-		return ((GDisplay *)(ptc->id))->priv->toggles;
-	}
-#endif /* GINPUT_NEED_TOGGLE */
-
-#endif /* GFX_USE_GDISP */
-
diff --git a/drivers/multiple/Win32/gdisp_lld.mk b/drivers/multiple/Win32/gdisp_lld.mk
index 081d8dda..f9242380 100644
--- a/drivers/multiple/Win32/gdisp_lld.mk
+++ b/drivers/multiple/Win32/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC +=	$(GFXLIB)/drivers/multiple/Win32
-GFXSRC +=	$(GFXLIB)/drivers/multiple/Win32/gdisp_lld.c
+GFXSRC +=	$(GFXLIB)/drivers/multiple/Win32/gdisp_lld_Win32.c
diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c
new file mode 100644
index 00000000..7d7abb06
--- /dev/null
+++ b/drivers/multiple/Win32/gdisp_lld_Win32.c
@@ -0,0 +1,1163 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/multiple/Win32/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for Win32.
+ */
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_Win32
+#include "../drivers/multiple/Win32/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH	640
+#endif
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT	480
+#endif
+#if GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888
+	#error "GDISP Win32: This driver currently only supports the RGB888 pixel format."
+#endif
+// Setting this to TRUE delays updating the screen
+// to the windows paint routine. Due to the
+// drawing lock this does not add as much speed
+// as might be expected but it is still faster in
+// all tested circumstances and for all operations
+// even draw_pixel().
+// This is probably due to drawing operations being
+// combined as the update regions are merged.
+// The only time you might want to turn this off is
+// if you are debugging drawing and want to see each
+// pixel as it is set.
+#define GDISP_WIN32_USE_INDIRECT_UPDATE		TRUE
+//#define GDISP_WIN32_USE_INDIRECT_UPDATE		FALSE
+
+// How far extra windows (multiple displays) should be offset from the first.
+#define DISPLAY_X_OFFSET		50
+#define DISPLAY_Y_OFFSET		50
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <wingdi.h>
+#include <assert.h>
+
+#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
+#define GDISP_FLG_HASTOGGLE			(GDISP_FLG_DRIVER<<1)
+#define GDISP_FLG_HASMOUSE			(GDISP_FLG_DRIVER<<2)
+#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+	#define GDISP_FLG_WSTREAM			(GDISP_FLG_DRIVER<<3)
+	#define GDISP_FLG_WRAPPED			(GDISP_FLG_DRIVER<<4)
+#endif
+
+#if GINPUT_NEED_TOGGLE
+	/* Include toggle support code */
+	#include "ginput/lld/toggle.h"
+#endif
+
+#if GINPUT_NEED_MOUSE
+	/* Include mouse support code */
+	#include "ginput/lld/mouse.h"
+#endif
+
+static DWORD			winThreadId;
+static ATOM				winClass;
+static volatile bool_t	QReady;
+static HANDLE			drawMutex;
+#if GINPUT_NEED_MOUSE
+	static GDisplay *	mouseDisplay;
+#endif
+
+/*===========================================================================*/
+/* Driver local routines    .                                                */
+/*===========================================================================*/
+
+#if GINPUT_NEED_TOGGLE
+	#define WIN32_BUTTON_AREA		16
+#else
+	#define WIN32_BUTTON_AREA		0
+#endif
+
+#define APP_NAME "uGFX"
+
+#define COLOR2BGR(c)	((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF))
+#define BGR2COLOR(c)	COLOR2BGR(c)
+
+typedef struct winPriv {
+	HWND			hwnd;
+	HDC				dcBuffer;
+	HBITMAP			dcBitmap;
+	HBITMAP 		dcOldBitmap;
+	#if GINPUT_NEED_MOUSE
+		coord_t		mousex, mousey;
+		uint16_t	mousebuttons;
+	#endif
+	#if GINPUT_NEED_TOGGLE
+		uint8_t		toggles;
+	#endif
+	#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+		coord_t		x0, y0, x1, y1;
+		coord_t		x, y;
+	#endif
+} winPriv;
+
+
+static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+	HDC				dc;
+	PAINTSTRUCT		ps;
+	GDisplay *		g;
+	winPriv *		priv;
+	#if GINPUT_NEED_TOGGLE
+		HBRUSH		hbrOn, hbrOff;
+		HPEN		pen;
+		RECT		rect;
+		HGDIOBJ		old;
+		POINT 		p;
+		coord_t		pos;
+		uint8_t		bit;
+	#endif
+
+	switch (Msg) {
+	case WM_CREATE:
+		// Get our GDisplay structure and attach it to the window
+		g = (GDisplay *)((LPCREATESTRUCT)lParam)->lpCreateParams;
+		priv = (winPriv *)g->priv;
+		SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)g);
+
+		// Fill in the private area
+		priv->hwnd = hWnd;
+		dc = GetDC(hWnd);
+		priv->dcBitmap = CreateCompatibleBitmap(dc, g->g.Width, g->g.Height);
+		priv->dcBuffer = CreateCompatibleDC(dc);
+		ReleaseDC(hWnd, dc);
+		priv->dcOldBitmap = SelectObject(priv->dcBuffer, priv->dcBitmap);
+
+		// Mark the window as ready to go
+		g->flags |= GDISP_FLG_READY;
+		break;
+
+	#if GINPUT_NEED_MOUSE || GINPUT_NEED_TOGGLE
+		case WM_LBUTTONDOWN:
+			// Get our GDisplay structure
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+
+			// Handle mouse down on the window
+			#if GINPUT_NEED_MOUSE
+				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+					priv->mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
+					goto mousemove;
+				}
+			#endif
+
+			// Handle mouse down on the toggle area
+			#if GINPUT_NEED_TOGGLE
+				if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
+					bit = 1 << ((coord_t)LOWORD(lParam)*8/g->g.Width);
+					priv->toggles ^= bit;
+					rect.left = 0;
+					rect.right = GDISP_SCREEN_WIDTH;
+					rect.top = GDISP_SCREEN_HEIGHT;
+					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
+					InvalidateRect(hWnd, &rect, FALSE);
+					UpdateWindow(hWnd);
+					#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
+						ginputToggleWakeup();
+					#endif
+				}
+			#endif
+			break;
+
+		case WM_LBUTTONUP:
+			// Get our GDisplay structure
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+
+			// Handle mouse up on the toggle area
+			#if GINPUT_NEED_TOGGLE
+				if ((g->flags & GDISP_FLG_HASTOGGLE)) {
+					if ((priv->toggles & 0x0F)) {
+						priv->toggles &= ~0x0F;
+						rect.left = 0;
+						rect.right = GDISP_SCREEN_WIDTH;
+						rect.top = GDISP_SCREEN_HEIGHT;
+						rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
+						InvalidateRect(hWnd, &rect, FALSE);
+						UpdateWindow(hWnd);
+						#if GINPUT_TOGGLE_POLL_PERIOD == TIME_INFINITE
+							ginputToggleWakeup();
+						#endif
+					}
+				}
+			#endif
+
+			// Handle mouse up on the window
+			#if GINPUT_NEED_MOUSE
+				if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+					priv->mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
+					goto mousemove;
+				}
+			#endif
+			break;
+	#endif
+
+	#if GINPUT_NEED_MOUSE
+		case WM_MBUTTONDOWN:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;
+				goto mousemove;
+			}
+			break;
+		case WM_MBUTTONUP:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;
+				goto mousemove;
+			}
+			break;
+		case WM_RBUTTONDOWN:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;
+				goto mousemove;
+			}
+			break;
+		case WM_RBUTTONUP:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) < GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASMOUSE)) {
+				priv->mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;
+				goto mousemove;
+			}
+			break;
+		case WM_MOUSEMOVE:
+			g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			priv = (winPriv *)g->priv;
+			if ((coord_t)HIWORD(lParam) >= GDISP_SCREEN_HEIGHT || !(g->flags & GDISP_FLG_HASMOUSE))
+				break;
+		mousemove:
+			priv->mousex = (coord_t)LOWORD(lParam);
+			priv->mousey = (coord_t)HIWORD(lParam);
+			#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+				ginputMouseWakeup();
+			#endif
+			break;
+	#endif
+
+	case WM_SYSKEYDOWN:
+	case WM_KEYDOWN:
+	case WM_SYSKEYUP:
+	case WM_KEYUP:
+		break;
+	case WM_CHAR:
+	case WM_DEADCHAR:
+	case WM_SYSCHAR:
+	case WM_SYSDEADCHAR:
+		break;
+
+	case WM_ERASEBKGND:
+		// Pretend we have erased the background.
+		// We know we don't really need to do this as we
+		// redraw the entire surface in the WM_PAINT handler.
+		return TRUE;
+
+	case WM_PAINT:
+		// Get our GDisplay structure
+		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+		priv = (winPriv *)g->priv;
+
+		// Paint the main window area
+		WaitForSingleObject(drawMutex, INFINITE);
+		dc = BeginPaint(hWnd, &ps);
+		BitBlt(dc, ps.rcPaint.left, ps.rcPaint.top,
+			ps.rcPaint.right - ps.rcPaint.left,
+			(ps.rcPaint.bottom > GDISP_SCREEN_HEIGHT ? GDISP_SCREEN_HEIGHT : ps.rcPaint.bottom) - ps.rcPaint.top,
+			priv->dcBuffer, ps.rcPaint.left, ps.rcPaint.top, SRCCOPY);
+
+		// Paint the toggle area
+		#if GINPUT_NEED_TOGGLE
+			if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
+				pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black));
+				hbrOn = CreateSolidBrush(COLOR2BGR(Blue));
+				hbrOff = CreateSolidBrush(COLOR2BGR(Gray));
+				old = SelectObject(dc, pen);
+				MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p);
+				LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
+				for(pos = 0, bit=1; pos < wWidth; pos=rect.right, bit <<= 1) {
+					rect.left = pos;
+					rect.right = pos + GDISP_SCREEN_WIDTH/8;
+					rect.top = GDISP_SCREEN_HEIGHT;
+					rect.bottom = GDISP_SCREEN_HEIGHT + WIN32_BUTTON_AREA;
+					FillRect(dc, &rect, (priv->toggles & bit) ? hbrOn : hbrOff);
+					if (pos > 0) {
+						MoveToEx(dc, rect.left, rect.top, &p);
+						LineTo(dc, rect.left, rect.bottom);
+					}
+				}
+				DeleteObject(hbrOn);
+				DeleteObject(hbrOff);
+				SelectObject(dc, old);
+			}
+		#endif
+		EndPaint(hWnd, &ps);
+		ReleaseMutex(drawMutex);
+		break;
+
+	case WM_DESTROY:
+		// Get our GDisplay structure
+		g = (GDisplay *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+		priv = (winPriv *)g->priv;
+
+		// Restore the window and free our bitmaps
+		SelectObject(priv->dcBuffer, priv->dcOldBitmap);
+		DeleteDC(priv->dcBuffer);
+		DeleteObject(priv->dcBitmap);
+
+		// Cleanup the private area
+		gfxFree(priv);
+
+		// Quit the application
+		PostQuitMessage(0);
+
+		// Actually the above doesn't work (who knows why)
+		ExitProcess(0);
+		break;
+
+	default:
+		return DefWindowProc(hWnd, Msg, wParam, lParam);
+	}
+	return 0;
+}
+
+static DECLARE_THREAD_STACK(waWindowThread, 1024);
+static DECLARE_THREAD_FUNCTION(WindowThread, param) {
+	(void)param;
+	MSG msg;
+
+	// Establish this thread as a message queue thread
+	winThreadId = GetCurrentThreadId();
+	PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+	QReady = TRUE;
+
+	do {
+		gfxSleepMilliseconds(1);
+		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+			// Is this our special thread message to create a new window?
+			if (!msg.hwnd && msg.message == WM_USER) {
+				RECT		rect;
+				GDisplay	*g;
+
+				g = (GDisplay *)msg.lParam;
+
+				// Set the window rectangle
+				rect.top = 0; rect.bottom = g->g.Height;
+				rect.left = 0; rect.right = g->g.Width;
+				#if GINPUT_NEED_TOGGLE
+					if ((g->flags & GDISP_FLG_HASTOGGLE))
+						rect.bottom += WIN32_BUTTON_AREA;
+				#endif
+				AdjustWindowRect(&rect, WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU, 0);
+
+				// Create the window
+				msg.hwnd = CreateWindow(APP_NAME, "", WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_BORDER, msg.wParam*DISPLAY_X_OFFSET, msg.wParam*DISPLAY_Y_OFFSET,
+								rect.right-rect.left, rect.bottom-rect.top, 0, 0,
+								GetModuleHandle(NULL), g);
+				assert(msg.hwnd != NULL);
+
+			// Or just a normal window message
+			} else {
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
+			}
+		}
+	} while (msg.message != WM_QUIT);
+	ExitProcess(0);
+	return msg.wParam;
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	winPriv	*	priv;
+	char		buf[132];
+
+	// Initialise the window thread and the window class (if it hasn't been done already)
+	if (!QReady) {
+		gfxThreadHandle	hth;
+		WNDCLASS		wc;
+
+		// Create the draw mutex
+		drawMutex = CreateMutex(NULL, FALSE, NULL);
+
+		// Create the thread
+		hth = gfxThreadCreate(waWindowThread, sizeof(waWindowThread), HIGH_PRIORITY, WindowThread, 0);
+		assert(hth != NULL);
+		gfxThreadClose(hth);
+
+		wc.style           = CS_HREDRAW | CS_VREDRAW; // | CS_OWNDC;
+		wc.lpfnWndProc     = (WNDPROC)myWindowProc;
+		wc.cbClsExtra      = 0;
+		wc.cbWndExtra      = 0;
+		wc.hInstance       = GetModuleHandle(NULL);
+		wc.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
+		wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
+		wc.hbrBackground   = GetStockObject(WHITE_BRUSH);
+		wc.lpszMenuName    = NULL;
+		wc.lpszClassName   = APP_NAME;
+		winClass = RegisterClass(&wc);
+		assert(winClass != 0);
+
+		// Wait for our thread to be ready
+		while (!QReady)
+			Sleep(1);
+	}
+
+	// Initialise the GDISP structure
+	g->g.Orientation = GDISP_ROTATE_0;
+	g->g.Powermode = powerOn;
+	g->g.Backlight = 100;
+	g->g.Contrast = 50;
+	g->g.Width = GDISP_SCREEN_WIDTH;
+	g->g.Height = GDISP_SCREEN_HEIGHT;
+
+	// Turn on toggles for the first GINPUT_TOGGLE_CONFIG_ENTRIES windows
+	#if GINPUT_NEED_TOGGLE
+		if (g->controllerdisplay < GINPUT_TOGGLE_CONFIG_ENTRIES)
+			g->flags |= GDISP_FLG_HASTOGGLE;
+	#endif
+
+	// Only turn on mouse on the first window for now
+	#if GINPUT_NEED_MOUSE
+		if (!g->controllerdisplay) {
+			mouseDisplay = g;
+			g->flags |= GDISP_FLG_HASMOUSE;
+		}
+	#endif
+
+	// Create a private area for this window
+	priv = (winPriv *)gfxAlloc(sizeof(winPriv));
+	assert(priv != NULL);
+	memset(priv, 0, sizeof(winPriv));
+	g->priv = priv;
+	#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+		// Initialise with an invalid window
+		g->flags &= ~GDISP_FLG_WSTREAM;
+	#endif
+	g->board = 0;			// no board interface for this controller
+
+	// Create the window in the message thread
+	PostThreadMessage(winThreadId, WM_USER, (WPARAM)g->controllerdisplay, (LPARAM)g);
+
+	// Wait for the window creation to complete (for safety)
+	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
+		Sleep(1);
+
+	sprintf(buf, APP_NAME " - %u", g->systemdisplay+1);
+	SetWindowText(priv->hwnd, buf);
+	ShowWindow(priv->hwnd, SW_SHOW);
+	UpdateWindow(priv->hwnd);
+
+	return TRUE;
+}
+
+#if GDISP_HARDWARE_FLUSH
+	LLDSPEC void gdisp_lld_flush(GDisplay *g) {
+		winPriv	*	priv;
+
+		priv = g->priv;
+		UpdateWindow(priv->hwnd);
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
+	void BAD_PARAMETER(const char *msg) {
+		volatile int a;
+		// This is really just a point for us to set the debugger
+		a = 0;
+	}
+#endif
+
+#if GDISP_HARDWARE_STREAM_WRITE
+	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
+		winPriv	*	priv;
+
+		if (g->flags & GDISP_FLG_WSTREAM)
+			BAD_PARAMETER("write_start: already in streaming mode");
+		if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
+			BAD_PARAMETER("write_start: bad window parameter");
+
+		priv = g->priv;
+		priv->x0 = g->p.x;	priv->x1 = g->p.x + g->p.cx - 1;
+		priv->y0 = g->p.y;	priv->y1 = g->p.y + g->p.cy - 1;
+		#if GDISP_HARDWARE_STREAM_POS
+			priv->x = g->p.x-1;			// Make sure these values are invalid (for testing)
+			priv->y = g->p.y-1;
+		#else
+			priv->x = g->p.x;
+			priv->y = g->p.y;
+		#endif
+		g->flags |= GDISP_FLG_WSTREAM;
+		g->flags &= ~GDISP_FLG_WRAPPED;
+	}
+	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		winPriv	*	priv;
+		int			x, y;
+		COLORREF	color;
+
+		priv = g->priv;
+		color = COLOR2BGR(g->p.color);
+
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("write_color: not in streaming mode");
+		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
+			BAD_PARAMETER("write_color: cursor outside streaming area");
+		if (g->flags & GDISP_FLG_WRAPPED) {
+			BAD_PARAMETER("write_color: Warning - Area wrapped.");
+			g->flags &= ~GDISP_FLG_WRAPPED;
+		}
+
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				x = priv->x;
+				y = priv->y;
+				break;
+			case GDISP_ROTATE_90:
+				x = priv->y;
+				y = g->g.Width - 1 - priv->x;
+				break;
+			case GDISP_ROTATE_180:
+				x = g->g.Width - 1 - priv->x;
+				y = g->g.Height - 1 - priv->y;
+				break;
+			case GDISP_ROTATE_270:
+				x = g->g.Height - 1 - priv->y;
+				y = priv->x;
+				break;
+			}
+		#else
+			x = priv->x;
+			y = priv->y;
+		#endif
+
+		// Draw the pixel on the screen and in the buffer.
+		WaitForSingleObject(drawMutex, INFINITE);
+		SetPixel(priv->dcBuffer, x, y, color);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			{
+				RECT	r;
+				r.left = x; r.right = x+1;
+				r.top = y; r.bottom = y+1;
+				InvalidateRect(priv->hwnd, &r, FALSE);
+			}
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				SetPixel(dc, x, y, color);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
+
+		// Update the cursor
+		if (++priv->x > priv->x1) {
+			priv->x = priv->x0;
+			if (++priv->y > priv->y1) {
+				g->flags |= GDISP_FLG_WRAPPED;
+				priv->y = priv->y0;
+			}
+		}
+	}
+	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("write_stop: not in streaming mode");
+		g->flags &= ~GDISP_FLG_WSTREAM;
+	}
+	#if GDISP_HARDWARE_STREAM_POS
+		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
+			winPriv	*	priv;
+
+			priv = g->priv;
+
+			if (!(g->flags & GDISP_FLG_WSTREAM))
+				BAD_PARAMETER("write_pos: not in streaming mode");
+			if (g->p.x < priv->x0 || g->p.x > priv->x1 || g->p.y < priv->y0 || g->p.y > priv->y1)
+				BAD_PARAMETER("write_color: new cursor outside streaming area");
+			priv->x = g->p.x;
+			priv->y = g->p.y;
+		}
+	#endif
+#endif
+
+#if GDISP_HARDWARE_STREAM_READ
+	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
+		winPriv	*	priv;
+
+		if (g->flags & GDISP_FLG_WSTREAM)
+			BAD_PARAMETER("read_start: already in streaming mode");
+		if (g->p.cx <= 0 || g->p.cy <= 0 || g->p.x < 0 || g->p.y < 0 || g->p.x+g->p.cx > g->g.Width || g->p.y+g->p.cy > g->g.Height)
+			BAD_PARAMETER("read_start: bad window parameter");
+
+		priv = g->priv;
+		priv->x0 = g->p.x;	priv->x1 = g->p.x + g->p.cx - 1;
+		priv->y0 = g->p.y;	priv->y1 = g->p.y + g->p.cy - 1;
+		priv->x = g->p.x;
+		priv->y = g->p.y;
+		g->flags |= GDISP_FLG_WSTREAM;
+		g->flags &= ~GDISP_FLG_WRAPPED;
+	}
+	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
+		winPriv	*	priv;
+		COLORREF	color;
+
+		priv = g->priv;
+
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("read_color: not in streaming mode");
+		if (priv->x < priv->x0 || priv->x > priv->x1 || priv->y < priv->y0 || priv->y > priv->y1)
+			BAD_PARAMETER("read_color: cursor outside streaming area");
+		if (g->flags & GDISP_FLG_WRAPPED) {
+			BAD_PARAMETER("read_color: Warning - Area wrapped.");
+			g->flags &= ~GDISP_FLG_WRAPPED;
+		}
+
+		WaitForSingleObject(drawMutex, INFINITE);
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+				break;
+			case GDISP_ROTATE_90:
+				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
+				break;
+			case GDISP_ROTATE_180:
+				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
+				break;
+			case GDISP_ROTATE_270:
+				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
+				break;
+			}
+		#else
+			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+		#endif
+		ReleaseMutex(drawMutex);
+
+		// Update the cursor
+		if (++priv->x > priv->x1) {
+			priv->x = priv->x0;
+			if (++priv->y > priv->y1) {
+				g->flags |= GDISP_FLG_WRAPPED;
+				priv->y = priv->y0;
+			}
+		}
+
+		return BGR2COLOR(color);
+	}
+	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
+		if (!(g->flags & GDISP_FLG_WSTREAM))
+			BAD_PARAMETER("write_stop: not in streaming mode");
+		g->flags &= ~GDISP_FLG_WSTREAM;
+	}
+#endif
+
+#if GDISP_HARDWARE_DRAWPIXEL
+	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		winPriv	*	priv;
+		int			x, y;
+		COLORREF	color;
+	
+		priv = g->priv;
+		color = COLOR2BGR(g->p.color);
+	
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				x = g->p.x;
+				y = g->p.y;
+				break;
+			case GDISP_ROTATE_90:
+				x = g->p.y;
+				y = g->g.Width - 1 - g->p.x;
+				break;
+			case GDISP_ROTATE_180:
+				x = g->g.Width - 1 - g->p.x;
+				y = g->g.Height - 1 - g->p.y;
+				break;
+			case GDISP_ROTATE_270:
+				x = g->g.Height - 1 - g->p.y;
+				y = g->p.x;
+				break;
+			}
+		#else
+			x = g->p.x;
+			y = g->p.y;
+		#endif
+
+		// Draw the pixel on the screen and in the buffer.
+		WaitForSingleObject(drawMutex, INFINITE);
+		SetPixel(priv->dcBuffer, x, y, color);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			{
+				RECT	r;
+				r.left = x; r.right = x+1;
+				r.top = y; r.bottom = y+1;
+				InvalidateRect(priv->hwnd, &r, FALSE);
+			}
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				SetPixel(dc, x, y, color);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
+	}
+#endif
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_FILLS
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		winPriv	*	priv;
+		RECT		rect;
+		HBRUSH		hbr;
+		COLORREF	color;
+
+		priv = g->priv;
+		color = COLOR2BGR(g->p.color);
+		hbr = CreateSolidBrush(color);
+
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				rect.top = g->p.y;
+				rect.bottom = rect.top + g->p.cy;
+				rect.left = g->p.x;
+				rect.right = rect.left + g->p.cx;
+				break;
+			case GDISP_ROTATE_90:
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom - g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left + g->p.cy;
+				break;
+			case GDISP_ROTATE_180:
+				rect.bottom = g->g.Height - g->p.y;
+				rect.top = rect.bottom - g->p.cy;
+				rect.right = g->g.Width - g->p.x;
+				rect.left = rect.right - g->p.cx;
+				break;
+			case GDISP_ROTATE_270:
+				rect.top = g->p.x;
+				rect.bottom = rect.top + g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right - g->p.cy;
+				break;
+			}
+		#else
+			rect.top = g->p.y;
+			rect.bottom = rect.top + g->p.cy;
+			rect.left = g->p.x;
+			rect.right = rect.left + g->p.cx;
+		#endif
+
+
+		WaitForSingleObject(drawMutex, INFINITE);
+		FillRect(priv->dcBuffer, &rect, hbr);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			InvalidateRect(priv->hwnd, &rect, FALSE);
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				FillRect(dc, &rect, hbr);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
+
+		DeleteObject(hbr);
+	}
+#endif
+
+#if GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL
+	static pixel_t *rotateimg(GDisplay *g, const pixel_t *buffer) {
+		pixel_t	*dstbuf;
+		pixel_t	*dst;
+		const pixel_t	*src;
+		size_t	sz;
+		coord_t	i, j;
+
+		// Allocate the destination buffer
+		sz = (size_t)g->p.cx * (size_t)g->p.cy;
+		if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
+			return 0;
+		
+		// Copy the bits we need
+		switch(g->g.Orientation) {
+		case GDISP_ROTATE_0:
+			return 0;					// not handled as it doesn't need to be.
+		case GDISP_ROTATE_90:
+			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
+				dst = dstbuf+sz-g->p.cy+j;
+				for(i = 0; i < g->p.cx; i++, dst -= g->p.cy)
+					*dst = *src++;
+			}
+			break;
+		case GDISP_ROTATE_180:
+			for(dst = dstbuf+sz, src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx)
+				for(i = 0; i < g->p.cx; i++)
+					*--dst = *src++;
+			break;
+		case GDISP_ROTATE_270:
+			for(src = buffer+g->p.x1, j = 0; j < g->p.cy; j++, src += g->p.x2 - g->p.cx) {
+				dst = dstbuf+g->p.cy-j-1;
+				for(i = 0; i < g->p.cx; i++, dst += g->p.cy)
+					*dst = *src++;
+			}
+			break;
+		}
+		return dstbuf;
+	}
+#endif
+	
+#if GDISP_HARDWARE_BITFILLS
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
+		winPriv	*		priv;
+		pixel_t	*		buffer;
+		RECT			rect;
+		BITMAPV4HEADER	bmpInfo;
+
+		// Make everything relative to the start of the line
+		priv = g->priv;
+		buffer = g->p.ptr;
+		buffer += g->p.x2*g->p.y1;
+		
+		memset(&bmpInfo, 0, sizeof(bmpInfo));
+		bmpInfo.bV4Size = sizeof(bmpInfo);
+		bmpInfo.bV4Planes = 1;
+		bmpInfo.bV4BitCount = sizeof(pixel_t)*8;
+		bmpInfo.bV4AlphaMask = 0;
+		bmpInfo.bV4RedMask		= RGB2COLOR(255,0,0);
+		bmpInfo.bV4GreenMask	= RGB2COLOR(0,255,0);
+		bmpInfo.bV4BlueMask		= RGB2COLOR(0,0,255);
+		bmpInfo.bV4V4Compression = BI_BITFIELDS;
+		bmpInfo.bV4XPelsPerMeter = 3078;
+		bmpInfo.bV4YPelsPerMeter = 3078;
+		bmpInfo.bV4ClrUsed = 0;
+		bmpInfo.bV4ClrImportant = 0;
+		bmpInfo.bV4CSType = 0; //LCS_sRGB;
+
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
+				bmpInfo.bV4Width = g->p.x2;
+				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
+				rect.top = g->p.y;
+				rect.bottom = rect.top+g->p.cy;
+				rect.left = g->p.x;
+				rect.right = rect.left+g->p.cx;
+				break;
+			case GDISP_ROTATE_90:
+				if (!(buffer = rotateimg(g, buffer))) return;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
+				bmpInfo.bV4Width = g->p.cy;
+				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom-g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left+g->p.cy;
+				break;
+			case GDISP_ROTATE_180:
+				if (!(buffer = rotateimg(g, buffer))) return;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
+				bmpInfo.bV4Width = g->p.cx;
+				bmpInfo.bV4Height = -g->p.cy; /* top-down image */
+				rect.bottom = g->g.Height-1 - g->p.y;
+				rect.top = rect.bottom-g->p.cy;
+				rect.right = g->g.Width - g->p.x;
+				rect.left = rect.right-g->p.cx;
+				break;
+			case GDISP_ROTATE_270:
+				if (!(buffer = rotateimg(g, buffer))) return;
+				bmpInfo.bV4SizeImage = (g->p.cy*g->p.cx) * sizeof(pixel_t);
+				bmpInfo.bV4Width = g->p.cy;
+				bmpInfo.bV4Height = -g->p.cx; /* top-down image */
+				rect.top = g->p.x;
+				rect.bottom = rect.top+g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right-g->p.cy;
+				break;
+			}
+		#else
+			bmpInfo.bV4SizeImage = (g->p.cy*g->p.x2) * sizeof(pixel_t);
+			bmpInfo.bV4Width = g->p.x2;
+			bmpInfo.bV4Height = -g->p.cy; /* top-down image */
+			rect.top = g->p.y;
+			rect.bottom = rect.top+g->p.cy;
+			rect.left = g->p.x;
+			rect.right = rect.left+g->p.cx;
+		#endif
+
+		WaitForSingleObject(drawMutex, INFINITE);
+		SetDIBitsToDevice(priv->dcBuffer, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+		#if GDISP_WIN32_USE_INDIRECT_UPDATE
+			ReleaseMutex(drawMutex);
+			InvalidateRect(priv->hwnd, &rect, FALSE);
+		#else
+			{
+				HDC		dc;
+				dc = GetDC(priv->hwnd);
+				SetDIBitsToDevice(dc, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0, 0, 0, rect.bottom-rect.top, buffer, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);
+				ReleaseDC(priv->hwnd, dc);
+				ReleaseMutex(drawMutex);
+			}
+		#endif
+
+		#if GDISP_NEED_CONTROL
+			if (buffer != (pixel_t *)g->p.ptr)
+				free(buffer);
+		#endif
+	}
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		winPriv	*	priv;
+		COLORREF	color;
+
+		priv = g->priv;
+
+		WaitForSingleObject(drawMutex, INFINITE);
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+				break;
+			case GDISP_ROTATE_90:
+				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
+				break;
+			case GDISP_ROTATE_180:
+				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
+				break;
+			case GDISP_ROTATE_270:
+				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
+				break;
+			}
+		#else
+			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+		#endif
+		ReleaseMutex(drawMutex);
+		
+		return BGR2COLOR(color);
+	}
+#endif
+
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
+		winPriv	*	priv;
+		RECT		rect;
+		coord_t		lines;
+		
+		priv = g->priv;
+
+		#if GDISP_NEED_CONTROL
+			switch(g->g.Orientation) {
+			case GDISP_ROTATE_0:
+				rect.top = g->p.y;
+				rect.bottom = rect.top+g->p.cy;
+				rect.left = g->p.x;
+				rect.right = rect.left+g->p.cx;
+				lines = -g->p.y1;
+				goto vertical_scroll;
+			case GDISP_ROTATE_90:
+				rect.bottom = g->g.Width - g->p.x;
+				rect.top = rect.bottom-g->p.cx;
+				rect.left = g->p.y;
+				rect.right = rect.left+g->p.cy;
+				lines = -g->p.y1;
+				goto horizontal_scroll;
+			case GDISP_ROTATE_180:
+				rect.bottom = g->g.Height - g->p.y;
+				rect.top = rect.bottom-g->p.cy;
+				rect.right = g->g.Width - g->p.x;
+				rect.left = rect.right-g->p.cx;
+				lines = g->p.y1;
+			vertical_scroll:
+				if (lines > 0) {
+					rect.bottom -= lines;
+				} else {
+					rect.top -= lines;
+				}
+				if (g->p.cy >= lines && g->p.cy >= -lines) {
+					WaitForSingleObject(drawMutex, INFINITE);
+					ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
+					#if GDISP_WIN32_USE_INDIRECT_UPDATE
+						ReleaseMutex(drawMutex);
+						InvalidateRect(priv->hwnd, &rect, FALSE);
+					#else
+						{
+							HDC		dc;
+							dc = GetDC(priv->hwnd);
+							ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
+							ReleaseDC(priv->hwnd, dc);
+							ReleaseMutex(drawMutex);
+						}
+					#endif
+				}
+				break;
+			case GDISP_ROTATE_270:
+				rect.top = g->p.x;
+				rect.bottom = rect.top+g->p.cx;
+				rect.right = g->g.Height - g->p.y;
+				rect.left = rect.right-g->p.cy;
+				lines = g->p.y1;
+			horizontal_scroll:
+				if (lines > 0) {
+					rect.right -= lines;
+				} else {
+					rect.left -= lines;
+				}
+				if (g->p.cy >= lines && g->p.cy >= -lines) {
+					WaitForSingleObject(drawMutex, INFINITE);
+					ScrollDC(priv->dcBuffer, lines, 0, &rect, 0, 0, 0);
+					#if GDISP_WIN32_USE_INDIRECT_UPDATE
+						ReleaseMutex(drawMutex);
+						InvalidateRect(priv->hwnd, &rect, FALSE);
+					#else
+						{
+							HDC		dc;
+							dc = GetDC(priv->hwnd);
+							ScrollDC(dc, lines, 0, &rect, 0, 0, 0);
+							ReleaseDC(priv->hwnd, dc);
+							ReleaseMutex(drawMutex);
+						}
+					#endif
+				}
+				break;
+			}
+		#else
+			rect.top = g->p.y;
+			rect.bottom = rect.top+g->p.cy;
+			rect.left = g->p.x;
+			rect.right = rect.left+g->p.cx;
+			lines = -g->p.y1;
+			if (lines > 0) {
+				rect.bottom -= lines;
+			} else {
+				rect.top -= lines;
+			}
+			if (g->p.cy >= lines && g->p.cy >= -lines) {
+				WaitForSingleObject(drawMutex, INFINITE);
+				ScrollDC(priv->dcBuffer, 0, lines, &rect, 0, 0, 0);
+				#if GDISP_WIN32_USE_INDIRECT_UPDATE
+					ReleaseMutex(drawMutex);
+					InvalidateRect(priv->hwnd, &rect, FALSE);
+				#else
+					{
+						HDC		dc;
+						dc = GetDC(priv->hwnd);
+						ScrollDC(dc, 0, lines, &rect, 0, 0, 0);
+						ReleaseDC(priv->hwnd, dc);
+						ReleaseMutex(drawMutex);
+					}
+				#endif
+			}
+		#endif
+	}
+#endif
+
+#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
+	LLDSPEC void gdisp_lld_control(GDisplay *g) {
+		switch(g->p.x) {
+		case GDISP_CONTROL_ORIENTATION:
+			if (g->g.Orientation == (orientation_t)g->p.ptr)
+				return;
+			switch((orientation_t)g->p.ptr) {
+				case GDISP_ROTATE_0:
+				case GDISP_ROTATE_180:
+					g->g.Width = GDISP_SCREEN_WIDTH;
+					g->g.Height = GDISP_SCREEN_HEIGHT;
+					break;
+				case GDISP_ROTATE_90:
+				case GDISP_ROTATE_270:
+					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_POWER:
+		case GDISP_CONTROL_BACKLIGHT:
+		case GDISP_CONTROL_CONTRAST:
+*/
+		}
+	}
+#endif
+
+#if GINPUT_NEED_MOUSE
+	void ginput_lld_mouse_init(void) {}
+	void ginput_lld_mouse_get_reading(MouseReading *pt) {
+		GDisplay *	g;
+		winPriv	*	priv;
+
+		g = mouseDisplay;
+		priv = g->priv;
+
+		pt->x = priv->mousex;
+		pt->y = priv->mousey > g->g.Height ? g->g.Height : priv->mousey;
+		pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
+		pt->buttons = priv->mousebuttons;
+	}
+#endif /* GINPUT_NEED_MOUSE */
+
+#if GINPUT_NEED_TOGGLE
+	#if GINPUT_TOGGLE_CONFIG_ENTRIES > GDISP_DRIVER_COUNT_WIN32
+		#error "GDISP Win32: GINPUT_TOGGLE_CONFIG_ENTRIES must not be greater than GDISP_DRIVER_COUNT_WIN32"
+	#endif
+
+	GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES];
+
+	void ginput_lld_toggle_init(const GToggleConfig *ptc) {
+		// Save the associated window struct
+		ptc->id = &GDISP_WIN32[ptc - GInputToggleConfigTable];
+
+		// We have 8 buttons per window.
+		ptc->mask = 0xFF;
+
+		// No inverse or special mode
+		ptc->invert = 0x00;
+		ptc->mode = 0;
+	}
+	unsigned ginput_lld_toggle_getbits(const GToggleConfig *ptc) {
+		return ((GDisplay *)(ptc->id))->priv->toggles;
+	}
+#endif /* GINPUT_NEED_TOGGLE */
+
+#endif /* GFX_USE_GDISP */
+
diff --git a/drivers/multiple/X/gdisp_lld.c b/drivers/multiple/X/gdisp_lld.c
deleted file mode 100644
index c9beb821..00000000
--- a/drivers/multiple/X/gdisp_lld.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/multiple/X/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for X.
- */
-
-#include "gfx.h"
-
-#if GFX_USE_GDISP
-
-#define GDISP_DRIVER_VMT			GDISPVMT_X11
-#include "../drivers/multiple/X/gdisp_lld_config.h"
-#include "gdisp/lld/gdisp_lld.h"
-
-/**
- * Our color model - Default or 24 bit only.
- *
- * At present we don't define this as we don't need to.
- * It may however be useful later if we implement bitblits.
- * As this may be dead code we don't include it in gdisp/options.h
- */
-#ifndef GDISP_FORCE_24BIT	
-	#define GDISP_FORCE_24BIT	FALSE
-#endif
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		480
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		640
-#endif
-
-#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
-
-#if GINPUT_NEED_MOUSE
-	/* Include mouse support code */
-	#include "ginput/lld/mouse.h"
-#endif
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-static bool_t			initdone;
-static Display			*dis;
-static int				scr;
-static XEvent			evt;
-static Colormap			cmap;
-static XVisualInfo		vis;
-static XContext			cxt;
-#if GINPUT_NEED_MOUSE
-	coord_t			mousex, mousey;
-	uint16_t		mousebuttons;
-#endif
-
-typedef struct xPriv {
-	Pixmap			pix;
-	GC 				gc;
-	Window			win;
-} xPriv;
-
-static void ProcessEvent(GDisplay *g, xPriv *priv) {
-	switch(evt.type) {
-	case MapNotify:
-		XSelectInput(dis, evt.xmap.window, StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
-		g->flags |= GDISP_FLG_READY;
-		break;
-	case UnmapNotify:
-		XCloseDisplay(dis);
-		exit(0);
-		break;
-	case Expose:
-		XCopyArea(dis, priv->pix, evt.xexpose.window, priv->gc,
-			evt.xexpose.x, evt.xexpose.y,
-			evt.xexpose.width, evt.xexpose.height,   
-			evt.xexpose.x, evt.xexpose.y);
-		break;
-#if GINPUT_NEED_MOUSE
-	case ButtonPress:
-		mousex = evt.xbutton.x;
-		mousey = evt.xbutton.y;
-		switch(evt.xbutton.button){
-		case 1:	mousebuttons |= GINPUT_MOUSE_BTN_LEFT;		break;
-		case 2:	mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;	break;
-		case 3:	mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;		break;
-		case 4:	mousebuttons |= GINPUT_MOUSE_BTN_4;			break;
-		}
-		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
-			ginputMouseWakeup();
-		#endif
-		break;
-	case ButtonRelease:
-		mousex = evt.xbutton.x;
-		mousey = evt.xbutton.y;
-		switch(evt.xbutton.button){
-		case 1:	mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;		break;
-		case 2:	mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;	break;
-		case 3:	mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;	break;
-		case 4:	mousebuttons &= ~GINPUT_MOUSE_BTN_4;		break;
-		}
-		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
-			ginputMouseWakeup();
-		#endif
-		break;
-	case MotionNotify:
-		mousex = evt.xmotion.x;
-		mousey = evt.xmotion.y;
-		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
-			ginputMouseWakeup();
-		#endif
-		break;
-#endif
-	}
-}
-
-/* this is the X11 thread which keeps track of all events */
-static DECLARE_THREAD_STACK(waXThread, 1024);
-static DECLARE_THREAD_FUNCTION(ThreadX, arg) {
-	GDisplay	*g;
-	(void)arg;
-
-	while(1) {
-		gfxSleepMilliseconds(100);
-		while(XPending(dis)) {
-			XNextEvent(dis, &evt);
-			XFindContext(evt.xany.display, evt.xany.window, cxt, (XPointer*)&g);
-			ProcessEvent(g, (xPriv *)g->priv);
-		}
-	}
-	return 0;
-}
- 
-static int FatalXIOError(Display *d) {
-	(void) d;
-
-	/* The window has closed */
-	fprintf(stderr, "GFX Window closed!\n");
-	exit(0);
-}
-
-LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
-	XSizeHints				*pSH;
-	XSetWindowAttributes	xa;
-	XTextProperty			WindowTitle;
-	char *					WindowTitleText;
-	xPriv					*priv;
-
-	if (!initdone) {
-		gfxThreadHandle			hth;
-
-		initdone = TRUE;
-		#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
-			XInitThreads();
-		#endif
-
-		dis = XOpenDisplay(NULL);
-		scr = DefaultScreen(dis);
-		cxt = XUniqueContext();
-		XSetIOErrorHandler(FatalXIOError);
-
-		#if GDISP_FORCE_24BIT
-			if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) {
-				fprintf(stderr, "Your display has no TrueColor mode\n");
-				XCloseDisplay(dis);
-				return FALSE;
-			}
-			cmap = XCreateColormap(dis, RootWindow(dis, scr),
-					vis.visual, AllocNone);
-		#else
-			vis.visual = CopyFromParent;
-			vis.depth = DefaultDepth(dis, scr);
-			cmap = DefaultColormap(dis, scr);
-		#endif
-		fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth);
-
-		if (!(hth = gfxThreadCreate(waXThread, sizeof(waXThread), HIGH_PRIORITY, ThreadX, 0))) {
-			fprintf(stderr, "Cannot start X Thread\n");
-			XCloseDisplay(dis);
-			exit(0);
-		}
-		#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
-			pthread_detach(hth);
-		#endif
-		gfxThreadClose(hth);
-	}
-
-	g->priv = gfxAlloc(sizeof(xPriv));
-	priv = (xPriv *)g->priv;
-	g->board = 0;					// No board interface for this driver
-
-	xa.colormap = cmap;
-	xa.border_pixel = 0xFFFFFF;
-	xa.background_pixel = 0x000000;
-	
-	priv->win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16,
-			GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
-			0, vis.depth, InputOutput, vis.visual,
-			CWBackPixel|CWColormap|CWBorderPixel, &xa);
-	XSync(dis, TRUE);
-	
-	XSaveContext(dis, priv->win, cxt, (XPointer)g);
-
-	{
-		char					buf[132];
-		sprintf(buf, "uGFX - %u", g->systemdisplay+1);
-		WindowTitleText = buf;
-		XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
-		XSetWMName(dis, priv->win, &WindowTitle);
-		XSetWMIconName(dis, priv->win, &WindowTitle);
-		XSync(dis, TRUE);
-	}
-			
-	pSH = XAllocSizeHints();
-	pSH->flags = PSize | PMinSize | PMaxSize;
-	pSH->min_width = pSH->max_width = pSH->base_width = GDISP_SCREEN_WIDTH;
-	pSH->min_height = pSH->max_height = pSH->base_height = GDISP_SCREEN_HEIGHT;
-	XSetWMNormalHints(dis, priv->win, pSH);
-	XFree(pSH);
-	XSync(dis, TRUE);
-	
-	priv->pix = XCreatePixmap(dis, priv->win,
-				GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth);
-	XSync(dis, TRUE);
-
-	priv->gc = XCreateGC(dis, priv->win, 0, 0);
-	XSetBackground(dis, priv->gc, BlackPixel(dis, scr));
-	XSync(dis, TRUE);
-
-	XSelectInput(dis, priv->win, StructureNotifyMask);
-	XMapWindow(dis, priv->win);
-
-	// Wait for the window creation to complete (for safety)
-	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
-		gfxSleepMilliseconds(100);
-
-	/* Initialise the GDISP structure to match */
-    g->g.Orientation = GDISP_ROTATE_0;
-    g->g.Powermode = powerOn;
-    g->g.Backlight = 100;
-    g->g.Contrast = 50;
-    g->g.Width = GDISP_SCREEN_WIDTH;
-    g->g.Height = GDISP_SCREEN_HEIGHT;
-    return TRUE;
-}
-
-LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g)
-{
-	xPriv *	priv = (xPriv *)g->priv;
-	XColor	col;
-
-	col.red = RED_OF(g->p.color) << 8;
-	col.green = GREEN_OF(g->p.color) << 8;
-	col.blue = BLUE_OF(g->p.color) << 8;
-	XAllocColor(dis, cmap, &col);
-	XSetForeground(dis, priv->gc, col.pixel);
-	XDrawPoint(dis, priv->pix, priv->gc, (int)g->p.x, (int)g->p.y );
-	XDrawPoint(dis, priv->win, priv->gc, (int)g->p.x, (int)g->p.y );
-	XFlush(dis);
-}
-
-#if GDISP_HARDWARE_FILLS
-	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
-		xPriv *	priv = (xPriv *)g->priv;
-		XColor	col;
-
-		col.red = RED_OF(g->p.color) << 8;
-		col.green = GREEN_OF(g->p.color) << 8;
-		col.blue = BLUE_OF(g->p.color) << 8;
-		XAllocColor(dis, cmap, &col);
-		XSetForeground(dis, priv->gc, col.pixel);
-		XFillRectangle(dis, priv->pix, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
-		XFillRectangle(dis, priv->win, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
-		XFlush(dis);
-	}
-#endif
-
-#if 0 && GDISP_HARDWARE_BITFILLS
-	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
-		// Start of Bitblit code
-
-		//XImage			bitmap;
-		//pixel_t			*bits;
-		//	bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
-		//	bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
-		//				0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
-		//				0, 0);
-	}
-#endif
-
-#if GDISP_HARDWARE_PIXELREAD
-	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
-		xPriv *	priv = (xPriv *)g->priv;
-		XColor	color;
-		XImage *img;
-
-		img = XGetImage (dis, priv->pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
-		color.pixel = XGetPixel (img, 0, 0);
-		XFree(img);
-		XQueryColor(dis, cmap, &color);
-		return RGB2COLOR(color.red>>8, color.green>>8, color.blue>>8);
-	}
-#endif
-
-#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
-	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
-		xPriv *	priv = (xPriv *)g->priv;
-
-		if (g->p.y1 > 0) {
-			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
-			XCopyArea(dis, priv->pix, priv->win, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
-		} else {
-			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
-			XCopyArea(dis, priv->pix, priv->win, priv->gc, g->p.x, g->p.y-g->p.y1, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
-		}
-	}
-#endif
-
-#if GINPUT_NEED_MOUSE
-
-	void ginput_lld_mouse_init(void) {}
-
-	void ginput_lld_mouse_get_reading(MouseReading *pt) {
-		pt->x = mousex;
-		pt->y = mousey;
-		pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
-		pt->buttons = mousebuttons;
-	}
-
-#endif /* GINPUT_NEED_MOUSE */
-
-#endif /* GFX_USE_GDISP */
-/** @} */
-
diff --git a/drivers/multiple/X/gdisp_lld.mk b/drivers/multiple/X/gdisp_lld.mk
index e7b9daef..572a5b7d 100644
--- a/drivers/multiple/X/gdisp_lld.mk
+++ b/drivers/multiple/X/gdisp_lld.mk
@@ -1,2 +1,2 @@
 GFXINC += $(GFXLIB)/drivers/multiple/X
-GFXSRC += $(GFXLIB)/drivers/multiple/X/gdisp_lld.c
+GFXSRC += $(GFXLIB)/drivers/multiple/X/gdisp_lld_X.c
diff --git a/drivers/multiple/X/gdisp_lld_X.c b/drivers/multiple/X/gdisp_lld_X.c
new file mode 100644
index 00000000..c9beb821
--- /dev/null
+++ b/drivers/multiple/X/gdisp_lld_X.c
@@ -0,0 +1,340 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/multiple/X/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for X.
+ */
+
+#include "gfx.h"
+
+#if GFX_USE_GDISP
+
+#define GDISP_DRIVER_VMT			GDISPVMT_X11
+#include "../drivers/multiple/X/gdisp_lld_config.h"
+#include "gdisp/lld/gdisp_lld.h"
+
+/**
+ * Our color model - Default or 24 bit only.
+ *
+ * At present we don't define this as we don't need to.
+ * It may however be useful later if we implement bitblits.
+ * As this may be dead code we don't include it in gdisp/options.h
+ */
+#ifndef GDISP_FORCE_24BIT	
+	#define GDISP_FORCE_24BIT	FALSE
+#endif
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		480
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		640
+#endif
+
+#define GDISP_FLG_READY				(GDISP_FLG_DRIVER<<0)
+
+#if GINPUT_NEED_MOUSE
+	/* Include mouse support code */
+	#include "ginput/lld/mouse.h"
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static bool_t			initdone;
+static Display			*dis;
+static int				scr;
+static XEvent			evt;
+static Colormap			cmap;
+static XVisualInfo		vis;
+static XContext			cxt;
+#if GINPUT_NEED_MOUSE
+	coord_t			mousex, mousey;
+	uint16_t		mousebuttons;
+#endif
+
+typedef struct xPriv {
+	Pixmap			pix;
+	GC 				gc;
+	Window			win;
+} xPriv;
+
+static void ProcessEvent(GDisplay *g, xPriv *priv) {
+	switch(evt.type) {
+	case MapNotify:
+		XSelectInput(dis, evt.xmap.window, StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
+		g->flags |= GDISP_FLG_READY;
+		break;
+	case UnmapNotify:
+		XCloseDisplay(dis);
+		exit(0);
+		break;
+	case Expose:
+		XCopyArea(dis, priv->pix, evt.xexpose.window, priv->gc,
+			evt.xexpose.x, evt.xexpose.y,
+			evt.xexpose.width, evt.xexpose.height,   
+			evt.xexpose.x, evt.xexpose.y);
+		break;
+#if GINPUT_NEED_MOUSE
+	case ButtonPress:
+		mousex = evt.xbutton.x;
+		mousey = evt.xbutton.y;
+		switch(evt.xbutton.button){
+		case 1:	mousebuttons |= GINPUT_MOUSE_BTN_LEFT;		break;
+		case 2:	mousebuttons |= GINPUT_MOUSE_BTN_MIDDLE;	break;
+		case 3:	mousebuttons |= GINPUT_MOUSE_BTN_RIGHT;		break;
+		case 4:	mousebuttons |= GINPUT_MOUSE_BTN_4;			break;
+		}
+		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+			ginputMouseWakeup();
+		#endif
+		break;
+	case ButtonRelease:
+		mousex = evt.xbutton.x;
+		mousey = evt.xbutton.y;
+		switch(evt.xbutton.button){
+		case 1:	mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;		break;
+		case 2:	mousebuttons &= ~GINPUT_MOUSE_BTN_MIDDLE;	break;
+		case 3:	mousebuttons &= ~GINPUT_MOUSE_BTN_RIGHT;	break;
+		case 4:	mousebuttons &= ~GINPUT_MOUSE_BTN_4;		break;
+		}
+		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+			ginputMouseWakeup();
+		#endif
+		break;
+	case MotionNotify:
+		mousex = evt.xmotion.x;
+		mousey = evt.xmotion.y;
+		#if GINPUT_MOUSE_POLL_PERIOD == TIME_INFINITE
+			ginputMouseWakeup();
+		#endif
+		break;
+#endif
+	}
+}
+
+/* this is the X11 thread which keeps track of all events */
+static DECLARE_THREAD_STACK(waXThread, 1024);
+static DECLARE_THREAD_FUNCTION(ThreadX, arg) {
+	GDisplay	*g;
+	(void)arg;
+
+	while(1) {
+		gfxSleepMilliseconds(100);
+		while(XPending(dis)) {
+			XNextEvent(dis, &evt);
+			XFindContext(evt.xany.display, evt.xany.window, cxt, (XPointer*)&g);
+			ProcessEvent(g, (xPriv *)g->priv);
+		}
+	}
+	return 0;
+}
+ 
+static int FatalXIOError(Display *d) {
+	(void) d;
+
+	/* The window has closed */
+	fprintf(stderr, "GFX Window closed!\n");
+	exit(0);
+}
+
+LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
+	XSizeHints				*pSH;
+	XSetWindowAttributes	xa;
+	XTextProperty			WindowTitle;
+	char *					WindowTitleText;
+	xPriv					*priv;
+
+	if (!initdone) {
+		gfxThreadHandle			hth;
+
+		initdone = TRUE;
+		#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
+			XInitThreads();
+		#endif
+
+		dis = XOpenDisplay(NULL);
+		scr = DefaultScreen(dis);
+		cxt = XUniqueContext();
+		XSetIOErrorHandler(FatalXIOError);
+
+		#if GDISP_FORCE_24BIT
+			if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) {
+				fprintf(stderr, "Your display has no TrueColor mode\n");
+				XCloseDisplay(dis);
+				return FALSE;
+			}
+			cmap = XCreateColormap(dis, RootWindow(dis, scr),
+					vis.visual, AllocNone);
+		#else
+			vis.visual = CopyFromParent;
+			vis.depth = DefaultDepth(dis, scr);
+			cmap = DefaultColormap(dis, scr);
+		#endif
+		fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth);
+
+		if (!(hth = gfxThreadCreate(waXThread, sizeof(waXThread), HIGH_PRIORITY, ThreadX, 0))) {
+			fprintf(stderr, "Cannot start X Thread\n");
+			XCloseDisplay(dis);
+			exit(0);
+		}
+		#if GFX_USE_OS_LINUX || GFX_USE_OS_OSX
+			pthread_detach(hth);
+		#endif
+		gfxThreadClose(hth);
+	}
+
+	g->priv = gfxAlloc(sizeof(xPriv));
+	priv = (xPriv *)g->priv;
+	g->board = 0;					// No board interface for this driver
+
+	xa.colormap = cmap;
+	xa.border_pixel = 0xFFFFFF;
+	xa.background_pixel = 0x000000;
+	
+	priv->win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16,
+			GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
+			0, vis.depth, InputOutput, vis.visual,
+			CWBackPixel|CWColormap|CWBorderPixel, &xa);
+	XSync(dis, TRUE);
+	
+	XSaveContext(dis, priv->win, cxt, (XPointer)g);
+
+	{
+		char					buf[132];
+		sprintf(buf, "uGFX - %u", g->systemdisplay+1);
+		WindowTitleText = buf;
+		XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle);
+		XSetWMName(dis, priv->win, &WindowTitle);
+		XSetWMIconName(dis, priv->win, &WindowTitle);
+		XSync(dis, TRUE);
+	}
+			
+	pSH = XAllocSizeHints();
+	pSH->flags = PSize | PMinSize | PMaxSize;
+	pSH->min_width = pSH->max_width = pSH->base_width = GDISP_SCREEN_WIDTH;
+	pSH->min_height = pSH->max_height = pSH->base_height = GDISP_SCREEN_HEIGHT;
+	XSetWMNormalHints(dis, priv->win, pSH);
+	XFree(pSH);
+	XSync(dis, TRUE);
+	
+	priv->pix = XCreatePixmap(dis, priv->win,
+				GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth);
+	XSync(dis, TRUE);
+
+	priv->gc = XCreateGC(dis, priv->win, 0, 0);
+	XSetBackground(dis, priv->gc, BlackPixel(dis, scr));
+	XSync(dis, TRUE);
+
+	XSelectInput(dis, priv->win, StructureNotifyMask);
+	XMapWindow(dis, priv->win);
+
+	// Wait for the window creation to complete (for safety)
+	while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY))
+		gfxSleepMilliseconds(100);
+
+	/* Initialise the GDISP structure to match */
+    g->g.Orientation = GDISP_ROTATE_0;
+    g->g.Powermode = powerOn;
+    g->g.Backlight = 100;
+    g->g.Contrast = 50;
+    g->g.Width = GDISP_SCREEN_WIDTH;
+    g->g.Height = GDISP_SCREEN_HEIGHT;
+    return TRUE;
+}
+
+LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g)
+{
+	xPriv *	priv = (xPriv *)g->priv;
+	XColor	col;
+
+	col.red = RED_OF(g->p.color) << 8;
+	col.green = GREEN_OF(g->p.color) << 8;
+	col.blue = BLUE_OF(g->p.color) << 8;
+	XAllocColor(dis, cmap, &col);
+	XSetForeground(dis, priv->gc, col.pixel);
+	XDrawPoint(dis, priv->pix, priv->gc, (int)g->p.x, (int)g->p.y );
+	XDrawPoint(dis, priv->win, priv->gc, (int)g->p.x, (int)g->p.y );
+	XFlush(dis);
+}
+
+#if GDISP_HARDWARE_FILLS
+	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		xPriv *	priv = (xPriv *)g->priv;
+		XColor	col;
+
+		col.red = RED_OF(g->p.color) << 8;
+		col.green = GREEN_OF(g->p.color) << 8;
+		col.blue = BLUE_OF(g->p.color) << 8;
+		XAllocColor(dis, cmap, &col);
+		XSetForeground(dis, priv->gc, col.pixel);
+		XFillRectangle(dis, priv->pix, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		XFillRectangle(dis, priv->win, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy);
+		XFlush(dis);
+	}
+#endif
+
+#if 0 && GDISP_HARDWARE_BITFILLS
+	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
+		// Start of Bitblit code
+
+		//XImage			bitmap;
+		//pixel_t			*bits;
+		//	bits = malloc(vis.depth * GDISP_SCREEN_WIDTH * GDISP_SCREEN_HEIGHT);
+		//	bitmap = XCreateImage(dis, vis, vis.depth, ZPixmap,
+		//				0, bits, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT,
+		//				0, 0);
+	}
+#endif
+
+#if GDISP_HARDWARE_PIXELREAD
+	LLDSPEC	color_t gdisp_lld_get_pixel_color(GDisplay *g) {
+		xPriv *	priv = (xPriv *)g->priv;
+		XColor	color;
+		XImage *img;
+
+		img = XGetImage (dis, priv->pix, g->p.x, g->p.y, 1, 1, AllPlanes, XYPixmap);
+		color.pixel = XGetPixel (img, 0, 0);
+		XFree(img);
+		XQueryColor(dis, cmap, &color);
+		return RGB2COLOR(color.red>>8, color.green>>8, color.blue>>8);
+	}
+#endif
+
+#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
+	LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
+		xPriv *	priv = (xPriv *)g->priv;
+
+		if (g->p.y1 > 0) {
+			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y+g->p.y1, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
+			XCopyArea(dis, priv->pix, priv->win, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy-g->p.y1, g->p.x, g->p.y);
+		} else {
+			XCopyArea(dis, priv->pix, priv->pix, priv->gc, g->p.x, g->p.y, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+			XCopyArea(dis, priv->pix, priv->win, priv->gc, g->p.x, g->p.y-g->p.y1, g->p.cx, g->p.cy+g->p.y1, g->p.x, g->p.y-g->p.y1);
+		}
+	}
+#endif
+
+#if GINPUT_NEED_MOUSE
+
+	void ginput_lld_mouse_init(void) {}
+
+	void ginput_lld_mouse_get_reading(MouseReading *pt) {
+		pt->x = mousex;
+		pt->y = mousey;
+		pt->z = (mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 100 : 0;
+		pt->buttons = mousebuttons;
+	}
+
+#endif /* GINPUT_NEED_MOUSE */
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
-- 
cgit v1.2.3


From 737ac5be9743e37b80133706faf02e959e803459 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 28 Oct 2013 19:06:16 +1000
Subject: Create uGFX board directories which include example Makefiles.
 Currently only done for the Olimex-SAM7EX256 board.

---
 .../gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h |  33 ----
 drivers/gadc/AT91SAM7/gadc_lld_board_template.h    |  37 ++++
 drivers/gadc/AT91SAM7/gadc_lld_config.h            |  12 +-
 .../gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h |  47 -----
 drivers/gaudin/gadc/gaudin_lld_board_template.h    |  50 ++++++
 drivers/gaudin/gadc/gaudin_lld_config.h            |  11 +-
 .../board_Nokia6610GE12_olimexsam7ex256.h          | 186 --------------------
 .../board_Nokia6610GE8_olimexsam7ex256.h           | 195 ---------------------
 .../GADC/ginput_lld_dial_board_olimexsam7ex256.h   |  35 ----
 .../dial/GADC/ginput_lld_dial_board_template.h     |  36 ++++
 drivers/ginput/dial/GADC/ginput_lld_dial_config.h  |  11 +-
 .../toggle/Pal/ginput_lld_toggle_board_example.h   |  48 -----
 .../Pal/ginput_lld_toggle_board_olimexsam7ex256.h  |  44 -----
 .../toggle/Pal/ginput_lld_toggle_board_template.h  |  48 +++++
 .../ginput/toggle/Pal/ginput_lld_toggle_config.h   |  11 +-
 15 files changed, 179 insertions(+), 625 deletions(-)
 delete mode 100644 drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
 create mode 100644 drivers/gadc/AT91SAM7/gadc_lld_board_template.h
 delete mode 100644 drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
 create mode 100644 drivers/gaudin/gadc/gaudin_lld_board_template.h
 delete mode 100644 drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
 delete mode 100644 drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
 delete mode 100644 drivers/ginput/dial/GADC/ginput_lld_dial_board_olimexsam7ex256.h
 create mode 100644 drivers/ginput/dial/GADC/ginput_lld_dial_board_template.h
 delete mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
 delete mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
 create mode 100644 drivers/ginput/toggle/Pal/ginput_lld_toggle_board_template.h

(limited to 'drivers')

diff --git a/drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h b/drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
deleted file mode 100644
index 8f047015..00000000
--- a/drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
- * @brief   GADC Driver config file.
- *
- * @addtogroup GADC
- * @{
- */
-
-#ifndef _GADC_LLD_BOARD_OLIMEXSAM7EX256_H
-#define _GADC_LLD_BOARD_OLIMEXSAM7EX256_H
-
-#if GFX_USE_GADC
-
-/*===========================================================================*/
-/* Analogue devices on this board                                            */
-/*===========================================================================*/
-
-#define GADC_PHYSDEV_MICROPHONE			0x00000080
-#define GADC_PHYSDEV_DIAL				0x00000040
-#define GADC_PHYSDEV_TEMPERATURE		0x00000020
-
-#endif	/* GFX_USE_GADC */
-
-#endif	/* _GADC_LLD_BOARD_OLIMEXSAM7EX256_H */
-/** @} */
-
diff --git a/drivers/gadc/AT91SAM7/gadc_lld_board_template.h b/drivers/gadc/AT91SAM7/gadc_lld_board_template.h
new file mode 100644
index 00000000..045c0ed7
--- /dev/null
+++ b/drivers/gadc/AT91SAM7/gadc_lld_board_template.h
@@ -0,0 +1,37 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gadc/AT91SAM7/gadc_lld_board_template.h
+ * @brief   GADC Driver config file.
+ *
+ * @addtogroup GADC
+ * @{
+ */
+
+#ifndef _GADC_LLD_BOARD_H
+#define _GADC_LLD_BOARD_H
+
+#if GFX_USE_GADC
+
+/*===========================================================================*/
+/* Analogue devices on this board                                            */
+/*===========================================================================*/
+
+/**
+ * @brief	The physical devices that are accessible via GADC and their physical device numbers.
+ * @note	The numbers below are examples for this template file
+ */
+#define GADC_PHYSDEV_MICROPHONE			0x00000080
+#define GADC_PHYSDEV_DIAL				0x00000040
+#define GADC_PHYSDEV_TEMPERATURE		0x00000020
+
+#endif	/* GFX_USE_GADC */
+
+#endif	/* _GADC_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gadc/AT91SAM7/gadc_lld_config.h b/drivers/gadc/AT91SAM7/gadc_lld_config.h
index 8c6e1cc0..ba6cbda2 100644
--- a/drivers/gadc/AT91SAM7/gadc_lld_config.h
+++ b/drivers/gadc/AT91SAM7/gadc_lld_config.h
@@ -52,16 +52,8 @@
  */
 #define GADC_SAMPLE_FORMAT					ARRAY_DATA_10BITUNSIGNED
 
-/* Pull in board specific defines */
-#if defined(GADC_USE_CUSTOM_BOARD) && GADC_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gadc_lld_board.h"
-#elif defined(BOARD_OLIMEX_SAM7_EX256)
-	#include "gadc_lld_board_olimexsam7ex256.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "gadc_lld_board.h"
-#endif
+/* Include the user supplied board definitions */
+#include "gadc_lld_board.h"
 
 #endif	/* GFX_USE_GADC */
 
diff --git a/drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h b/drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
deleted file mode 100644
index a98f392c..00000000
--- a/drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gaudin/gadc/gaudin_lld_board_olimexsam7ex256.h
- * @brief   GAUDIN Driver board config file for the Olimex SAM7EX256 board
- *
- * @addtogroup GAUDIN
- * @{
- */
-
-#ifndef _GAUDIN_LLD_BOARD_OLIMEXSAM7EX256_H
-#define _GAUDIN_LLD_BOARD_OLIMEXSAM7EX256_H
-
-/*===========================================================================*/
-/* Audio inputs on this board                                                */
-/*===========================================================================*/
-
-/**
- * @brief	The number of audio channels supported by this driver
- */
-#define GAUDIN_NUM_CHANNELS					1
-
-/**
- * @brief	The list of audio channels and their uses
- * @{
- */
-#define	GAUDIN_MICROPHONE					0
-/** @} */
-
-/**
- * @brief	The following defines are for the low level driver use only
- * @{
- */
-#ifdef GAUDIN_LLD_IMPLEMENTATION
-	static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
-			GADC_PHYSDEV_MICROPHONE,
-			};
-#endif
-/** @} */
-
-#endif	/* _GAUDIN_LLD_BOARD_OLIMEXSAM7EX256_H */
-/** @} */
diff --git a/drivers/gaudin/gadc/gaudin_lld_board_template.h b/drivers/gaudin/gadc/gaudin_lld_board_template.h
new file mode 100644
index 00000000..89cc0c12
--- /dev/null
+++ b/drivers/gaudin/gadc/gaudin_lld_board_template.h
@@ -0,0 +1,50 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/gaudin/gadc/gaudin_lld_board_template.h
+ * @brief   GAUDIN Driver board config board file
+ *
+ * @addtogroup GAUDIN
+ * @{
+ */
+
+#ifndef _GAUDIN_LLD_BOARD_H
+#define _GAUDIN_LLD_BOARD_H
+
+/*===========================================================================*/
+/* Audio inputs on this board                                                */
+/*===========================================================================*/
+
+/**
+ * @brief	The number of audio channels supported by this driver
+ * @note	This is an example
+ */
+#define GAUDIN_NUM_CHANNELS					1
+
+/**
+ * @brief	The list of audio channels and their uses
+ * @note	This is an example
+ * @{
+ */
+#define	GAUDIN_MICROPHONE					0
+/** @} */
+
+/**
+ * @brief	The audio channel to GADC physical device assignment
+ * @note	This is an example
+ * @{
+ */
+#ifdef GAUDIN_LLD_IMPLEMENTATION
+	static uint32_t gaudin_lld_physdevs[GAUDIN_NUM_CHANNELS] = {
+			GADC_PHYSDEV_MICROPHONE,
+			};
+#endif
+/** @} */
+
+#endif	/* _GAUDIN_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/gaudin/gadc/gaudin_lld_config.h b/drivers/gaudin/gadc/gaudin_lld_config.h
index f10e0575..a9fd02ae 100644
--- a/drivers/gaudin/gadc/gaudin_lld_config.h
+++ b/drivers/gaudin/gadc/gaudin_lld_config.h
@@ -50,15 +50,8 @@ typedef adcsample_t		audin_sample_t;
  * For the GAUDIN driver that uses GADC - all the remaining config definitions are specific
  * to the board.
  */
-#if defined(GADC_USE_CUSTOM_BOARD) && GADC_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gaudin_lld_board.h"
-#elif defined(BOARD_OLIMEX_SAM7_EX256)
-	#include "gaudin_lld_board_olimexsam7ex256.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "gaudin_lld_board.h"
-#endif
+/* Include the user supplied board definitions */
+#include "gaudin_lld_board.h"
 
 #endif	/* GFX_USE_GAUDIN */
 
diff --git a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
deleted file mode 100644
index 5b9ff6f6..00000000
--- a/drivers/gdisp/Nokia6610GE12/board_Nokia6610GE12_olimexsam7ex256.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/board_Nokia6610GE12_olimexsam7ex256.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/*
- * Set various display properties. These properties mostly depend on the exact controller chip you get.
- * The defaults should work for most controllers.
- */
-//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
-//#define GDISP_SCREEN_WIDTH				130		// The visible display width
-//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
-//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
-//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
-//#define GDISP_INITIAL_CONTRAST			50		// The initial contrast percentage
-//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-
-// ******************************************************
-// Pointers to AT91SAM7X256 peripheral data structures
-// ******************************************************
-static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
-static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
-static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
-static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
-static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
-
-/* The PWM backlight control is non-linear on this board.
- * We pick values here that make it look a bit more linear.
- */
-#define PWM_TOP_VALUE		500
-#define PWM_BOTTOM_VALUE	200
-
-#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
-
-/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
-static const PWMConfig pwmcfg = {
-  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
-  1000,			/* PWM period is 1000 cycles. */
-  NULL,
-  {
-   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
-  },
-};
-
-static bool_t pwmRunning = FALSE;
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		// *********************************************************************************************
-		// InitSpi( )
-		//
-		// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
-		//
-		// I/O ports used:	PA2  = LCD Reset (set to low to reset)
-		//					PA12 = LCD chip select (set to low to select the LCD chip)
-		//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
-		//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-		//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
-		//					PB20 = backlight control (normally PWM control, 1 = full on)
-		//
-		// *********************************************************************************************}
-
-		/* This code should really use the ChibiOS driver for these functions */
-
-		// Pin for backlight
-		pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
-		pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output
-
-		// Reset pin
-		pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
-		pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output
-
-		// CS pin - this seems to be ignored
-		// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
-		// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output
-
-		// Init SPI0
-		// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
-		// BIT12 = PA12 -> SPI0_NPCS0 chip select
-		// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
-		// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-		// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
-		pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-		pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-		pPIOA->PIO_BSR = 0;
-
-		//enable the clock of SPI
-		pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
-
-		// Fixed mode
-		pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
-		pSPI->SPI_CR      = 0x01;               //SPI Enable
-		pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
-		pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
-
-		/* Display backlight control at 100% */
-		pwmRunning = FALSE;
-		palSetPad(IOPORT2, PIOB_LCD_BL);
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if (state)
-		palClearPad(IOPORT1, PIOA_LCD_RESET);
-	else
-		palSetPad(IOPORT1, PIOA_LCD_RESET);
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-
-	if (percent == 100) {
-		/* Turn the pin on - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palSetPad(IOPORT2, PIOB_LCD_BL);
-	} else if (percent == 0) {
-		/* Turn the pin off - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palClearPad(IOPORT2, PIOB_LCD_BL);
-	} else {
-		/* Use the PWM */
-		if (!pwmRunning) {
-			pwmStart(&PWMD2, &pwmcfg);
-			pwmRunning = TRUE;
-		}
-		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
-	}
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t cmd) {
-	(void) g;
-
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the command
-	pSPI->SPI_TDR = cmd & 0xFF;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the data
-	pSPI->SPI_TDR = data | 0x0100;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h b/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
deleted file mode 100644
index 12dbc9a5..00000000
--- a/drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/board_Nokia6610GE8_olimexsam7ex256.h
- * @brief   GDISP Graphic Driver subsystem board interface for the Olimex SAM7-EX256 board.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-/*
- * Set various display properties. These properties mostly depend on the exact controller chip you get.
- * The defaults should work for most controllers.
- */
-//#define GDISP_GE8_BROKEN_CONTROLLER		FALSE	// Uncomment this out if you have a controller thats not window wrap broken.
-//#define GDISP_SCREEN_HEIGHT				130		// The visible display height
-//#define GDISP_SCREEN_WIDTH				130		// The visible display width
-//#define GDISP_RAM_X_OFFSET				0		// The x offset of the visible area
-//#define GDISP_RAM_Y_OFFSET				2		// The y offset of the visible area
-//#define GDISP_SLEEP_SIZE					32		// The size of the sleep mode partial display
-//#define GDISP_SLEEP_POS					50		// The position of the sleep mode partial display
-//#define GDISP_INITIAL_CONTRAST			38		// The initial contrast percentage
-//#define GDISP_INITIAL_BACKLIGHT			100		// The initial backlight percentage
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-
-// ******************************************************
-// Pointers to AT91SAM7X256 peripheral data structures
-// ******************************************************
-static volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA;
-static volatile AT91PS_PIO pPIOB = AT91C_BASE_PIOB;
-static volatile AT91PS_SPI pSPI = AT91C_BASE_SPI0;
-static volatile AT91PS_PMC pPMC = AT91C_BASE_PMC;
-static volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_SPI0;
-
-/* The PWM backlight control is non-linear on this board.
- * We pick values here that make it look a bit more linear.
- */
-#define PWM_TOP_VALUE		500
-#define PWM_BOTTOM_VALUE	200
-
-#define PWM_VALUE(x)	(PWM_BOTTOM_VALUE+(PWM_TOP_VALUE-PWM_BOTTOM_VALUE)*(x)/100)
-
-/* PWM configuration structure. The LCD Backlight is on PWM1/PB20 ie PWM2/PIN1 in ChibiOS speak */
-static const PWMConfig pwmcfg = {
-  1000000,		/* 1 MHz PWM clock frequency. Ignored as we are using PWM_MCK_DIV_n */
-  1000,			/* PWM period is 1000 cycles. */
-  NULL,
-  {
-   {PWM_MCK_DIV_1 | PWM_OUTPUT_ACTIVE_HIGH | PWM_OUTPUT_PIN1 | PWM_DISABLEPULLUP_PIN1, NULL},
-  },
-};
-
-static bool_t pwmRunning = FALSE;
-
-/**
- * @brief   Initialise the board for the display.
- * @notes	Performs the following functions:
- *			1. initialise the spi port used by your display
- *			2. initialise the reset pin (initial state not-in-reset)
- *			3. initialise the chip select pin (initial state not-active)
- *			4. initialise the backlight pin (initial state back-light off)
- *
- * @notapi
- */
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		// *********************************************************************************************
-		// InitSpi( )
-		//
-		// Sets up SPI channel 0 for communications to Nokia 6610 LCD Display
-		//
-		// I/O ports used:	PA2  = LCD Reset (set to low to reset)
-		//					PA12 = LCD chip select (set to low to select the LCD chip)
-		//					PA16 = SPI0_MISO Master In - Slave Out (not used in LCD interface)
-		//					PA17 = SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-		//					PA18 = SPI0_SPCK Serial Clock (to LCD slave)
-		//					PB20 = backlight control (normally PWM control, 1 = full on)
-		//
-		// *********************************************************************************************}
-
-		/* This code should really use the ChibiOS driver for these functions */
-
-		// Pin for backlight
-		pPIOB->PIO_CODR   = PIOB_LCD_BL_MASK;    // Set PB20 to LOW
-		pPIOB->PIO_OER    = PIOB_LCD_BL_MASK;    // Configure PB20 as output
-
-		// Reset pin
-		pPIOA->PIO_SODR   = PIOA_LCD_RESET_MASK;     // Set PA2 to HIGH
-		pPIOA->PIO_OER    = PIOA_LCD_RESET_MASK;     // Configure PA2 as output
-
-		// CS pin - this seems to be ignored
-		// pPIOA->PIO_SODR   = 1<<12;     // Set PA2 to HIGH
-		// pPIOA->PIO_OER    = 1<<12;     // Configure PA2 as output
-
-		// Init SPI0
-		// Disable the following pins from PIO control (will be used instead by the SPI0 peripheral)
-		// BIT12 = PA12 -> SPI0_NPCS0 chip select
-		// BIT16 = PA16 -> SPI0_MISO Master In - Slave Out (not used in LCD interface)
-		// BIT17 = PA17 -> SPI0_MOSI Master Out - Slave In pin (Serial Data to LCD slave)
-		// BIT18 = PA18 -> SPI0_SPCK Serial Clock (to LCD slave)
-		pPIOA->PIO_PDR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-		pPIOA->PIO_ASR = (1<<12) | (1<<16) | (1<<17) | (1<<18);
-		pPIOA->PIO_BSR = 0;
-
-		//enable the clock of SPI
-		pPMC->PMC_PCER = 1 << AT91C_ID_SPI0;
-
-		// Fixed mode
-		pSPI->SPI_CR      = 0x81;               //SPI Enable, Software reset
-		pSPI->SPI_CR      = 0x01;               //SPI Enable
-		pSPI->SPI_MR      = 0xE0011;			//Master mode, fixed select, disable decoder, PCS=1110
-		pSPI->SPI_CSR[0]  = 0x01010311;			//9bit, CPOL=1, ClockPhase=0, SCLK = 48Mhz/3 = 16MHz
-
-		/* Display backlight control at 100% */
-		pwmRunning = FALSE;
-		palSetPad(IOPORT2, PIOB_LCD_BL);
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if (state)
-		palClearPad(IOPORT1, PIOA_LCD_RESET);
-	else
-		palSetPad(IOPORT1, PIOA_LCD_RESET);
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	if (percent == 100) {
-		/* Turn the pin on - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palSetPad(IOPORT2, PIOB_LCD_BL);
-	} else if (percent == 0) {
-		/* Turn the pin off - No PWM */
-		if (pwmRunning) {
-			pwmStop(&PWMD2);
-			pwmRunning = FALSE;
-		}
-		palClearPad(IOPORT2, PIOB_LCD_BL);
-	} else {
-		/* Use the PWM */
-		if (!pwmRunning) {
-			pwmStart(&PWMD2, &pwmcfg);
-			pwmRunning = TRUE;
-		}
-		pwmEnableChannel(&PWMD2, 0, PWM_VALUE(percent));
-	}
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the command
-	pSPI->SPI_TDR = index & 0xFF;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	// wait for the previous transfer to complete
-	while((pSPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
-	// send the data
-	pSPI->SPI_TDR = data | 0x0100;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/ginput/dial/GADC/ginput_lld_dial_board_olimexsam7ex256.h b/drivers/ginput/dial/GADC/ginput_lld_dial_board_olimexsam7ex256.h
deleted file mode 100644
index 09ca3dc0..00000000
--- a/drivers/ginput/dial/GADC/ginput_lld_dial_board_olimexsam7ex256.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/dial/GADC/ginput_lld_dial_board_olimexsam7ex256.h
- * @brief   GINPUT Dial Driver config file.
- *
- * @defgroup Dial Dial
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GINPUT_LLD_DIAL_BOARD_OLIMEXSAM7EX256_H
-#define _GINPUT_LLD_DIAL_BOARD_OLIMEXSAM7EX256_H
-
-#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
-
-/*===========================================================================*/
-/* Analogue devices on this board                                            */
-/*===========================================================================*/
-
-#define GINPUT_DIAL_NUM_PORTS			1
-#define GINPUT_DIAL_DEVICE0				GADC_PHYSDEV_DIAL
-#define GINPUT_DIAL_POLL_PERIOD			200
-#define GINPUT_DIAL_CYCLE_POLL			FALSE
-
-#endif	/* GFX_USE_GINPUT && GINPUT_NEED_DIAL */
-
-#endif	/* _GINPUT_LLD_DIAL_BOARD_OLIMEXSAM7EX256_H */
-/** @} */
-
diff --git a/drivers/ginput/dial/GADC/ginput_lld_dial_board_template.h b/drivers/ginput/dial/GADC/ginput_lld_dial_board_template.h
new file mode 100644
index 00000000..202b5386
--- /dev/null
+++ b/drivers/ginput/dial/GADC/ginput_lld_dial_board_template.h
@@ -0,0 +1,36 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/ginput/dial/GADC/ginput_lld_dial_board_template.h
+ * @brief   GINPUT Dial Driver config file.
+ *
+ * @defgroup Dial Dial
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GINPUT_LLD_DIAL_BOARD_H
+#define _GINPUT_LLD_DIAL_BOARD_H
+
+#if GFX_USE_GINPUT && GINPUT_NEED_DIAL
+
+/*===========================================================================*/
+/* Analogue devices on this board                                            */
+/*===========================================================================*/
+
+/* Example values */
+#define GINPUT_DIAL_NUM_PORTS			1
+#define GINPUT_DIAL_DEVICE0				GADC_PHYSDEV_DIAL
+#define GINPUT_DIAL_POLL_PERIOD			200
+#define GINPUT_DIAL_CYCLE_POLL			FALSE
+
+#endif	/* GFX_USE_GINPUT && GINPUT_NEED_DIAL */
+
+#endif	/* _GINPUT_LLD_DIAL_BOARD_H */
+/** @} */
+
diff --git a/drivers/ginput/dial/GADC/ginput_lld_dial_config.h b/drivers/ginput/dial/GADC/ginput_lld_dial_config.h
index 3dc7bfca..3e54b4ca 100644
--- a/drivers/ginput/dial/GADC/ginput_lld_dial_config.h
+++ b/drivers/ginput/dial/GADC/ginput_lld_dial_config.h
@@ -21,15 +21,8 @@
 
 #define GINPUT_DIAL_MAX_VALUE	((1<<GADC_BITS_PER_SAMPLE)-1)
 
-#if GINPUT_TOGGLE_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "ginput_lld_dial_board.h"
-#elif defined(BOARD_OLIMEX_SAM7_EX256)
-	#include "ginput_lld_dial_board_olimexsam7ex256.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "ginput_lld_dial_board.h"
-#endif
+/* Include the user supplied board definitions */
+#include "ginput_lld_dial_board.h"
 
 #endif	/* GFX_USE_GDISP && GINPUT_NEED_DIAL */
 
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
deleted file mode 100644
index e0a501df..00000000
--- a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/toggle/Pal/ginput_lld_toggle_board_example.h
- * @brief   GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the example board.
- *
- * @defgroup Toggle Toggle
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GDISP_LLD_TOGGLE_BOARD_H
-#define _GDISP_LLD_TOGGLE_BOARD_H
-
-#error "GINPUT Toggle Pal Driver: You need to define your board definitions"
-
-// The below are example values
-
-#define GINPUT_TOGGLE_NUM_PORTS			7			// The total number of toggle inputs
-#define GINPUT_TOGGLE_CONFIG_ENTRIES	2			// The total number of GToggleConfig entries
-
-#define GINPUT_TOGGLE_SW1			0				// Switch 1
-#define GINPUT_TOGGLE_SW2			1				// Switch 2
-#define GINPUT_TOGGLE_UP			2				// Joystick Up
-#define GINPUT_TOGGLE_DOWN			3				// Joystick Down
-#define GINPUT_TOGGLE_LEFT			4				// Joystick Left
-#define GINPUT_TOGGLE_RIGHT			5				// Joystick Right
-#define GINPUT_TOGGLE_CENTER		6				// Joystick Center
-
-#define GINPUT_TOGGLE_DECLARE_STRUCTURE()											\
-	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {	\
-		{AT91C_BASE_PIOB,								/* Switch 1 and Switch 2 */	\
-			PIOB_SW1_MASK|PIOB_SW2_MASK,											\
-			PIOB_SW1_MASK|PIOB_SW2_MASK,											\
-			PAL_MODE_INPUT},														\
-		{AT91C_BASE_PIOA,								/* B1..4 Joystick */		\
-			PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK,		\
-			PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK,		\
-			PAL_MODE_INPUT},														\
-	}
-
-#endif /* _GDISP_LLD_TOGGLE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
deleted file mode 100644
index 5861b6f5..00000000
--- a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/toggle/Pal/ginput_lld_toggle_board_olimexsam7ex256.h
- * @brief   GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the Olimex SAM7EX256 board.
- *
- * @defgroup Toggle Toggle
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GDISP_LLD_TOGGLE_BOARD_H
-#define _GDISP_LLD_TOGGLE_BOARD_H
-
-#define GINPUT_TOGGLE_NUM_PORTS			7			// The total number of toggle inputs
-#define GINPUT_TOGGLE_CONFIG_ENTRIES	2			// The total number of GToggleConfig entries
-
-#define GINPUT_TOGGLE_SW1			0				// Switch 1
-#define GINPUT_TOGGLE_SW2			1				// Switch 2
-#define GINPUT_TOGGLE_LEFT			2				// Joystick Left
-#define GINPUT_TOGGLE_DOWN			3				// Joystick Down
-#define GINPUT_TOGGLE_UP			4				// Joystick Up
-#define GINPUT_TOGGLE_RIGHT			5				// Joystick Right
-#define GINPUT_TOGGLE_CENTER		6				// Joystick Center
-
-#define GINPUT_TOGGLE_DECLARE_STRUCTURE()											\
-	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {	\
-		{AT91C_BASE_PIOB,								/* Switch 1 and Switch 2 */	\
-			PIOB_SW1_MASK|PIOB_SW2_MASK,											\
-			PIOB_SW1_MASK|PIOB_SW2_MASK,											\
-			PAL_MODE_INPUT},														\
-		{AT91C_BASE_PIOA,								/* B1..4 Joystick */		\
-			PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK,		\
-			PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK,		\
-			PAL_MODE_INPUT},														\
-	}
-
-#endif /* _GDISP_LLD_TOGGLE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_template.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_template.h
new file mode 100644
index 00000000..84038d16
--- /dev/null
+++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_board_template.h
@@ -0,0 +1,48 @@
+/*
+ * 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
+ */
+
+/**
+ * @file    drivers/ginput/toggle/Pal/ginput_lld_toggle_board_template.h
+ * @brief   GINPUT Toggle low level driver source for the ChibiOS PAL hardware on the example board.
+ *
+ * @defgroup Toggle Toggle
+ * @ingroup GINPUT
+ * @{
+ */
+
+#ifndef _GDISP_LLD_TOGGLE_BOARD_H
+#define _GDISP_LLD_TOGGLE_BOARD_H
+
+#error "GINPUT Toggle Pal Driver: You need to define your board definitions"
+
+// The below are example values
+
+#define GINPUT_TOGGLE_NUM_PORTS			7			// The total number of toggle inputs
+#define GINPUT_TOGGLE_CONFIG_ENTRIES	2			// The total number of GToggleConfig entries
+
+#define GINPUT_TOGGLE_SW1			0				// Switch 1
+#define GINPUT_TOGGLE_SW2			1				// Switch 2
+#define GINPUT_TOGGLE_UP			2				// Joystick Up
+#define GINPUT_TOGGLE_DOWN			3				// Joystick Down
+#define GINPUT_TOGGLE_LEFT			4				// Joystick Left
+#define GINPUT_TOGGLE_RIGHT			5				// Joystick Right
+#define GINPUT_TOGGLE_CENTER		6				// Joystick Center
+
+#define GINPUT_TOGGLE_DECLARE_STRUCTURE()											\
+	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {	\
+		{AT91C_BASE_PIOB,								/* Switch 1 and Switch 2 */	\
+			PIOB_SW1_MASK|PIOB_SW2_MASK,											\
+			PIOB_SW1_MASK|PIOB_SW2_MASK,											\
+			PAL_MODE_INPUT},														\
+		{AT91C_BASE_PIOA,								/* B1..4 Joystick */		\
+			PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK,		\
+			PIOA_B1_MASK|PIOA_B2_MASK|PIOA_B3_MASK|PIOA_B4_MASK|PIOA_B5_MASK,		\
+			PAL_MODE_INPUT},														\
+	}
+
+#endif /* _GDISP_LLD_TOGGLE_BOARD_H */
+/** @} */
diff --git a/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h b/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h
index e2bff490..84155956 100644
--- a/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h
+++ b/drivers/ginput/toggle/Pal/ginput_lld_toggle_config.h
@@ -19,15 +19,8 @@
 
 #if GFX_USE_GINPUT && GINPUT_NEED_TOGGLE
 
-#if GINPUT_TOGGLE_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "ginput_lld_toggle_board.h"
-#elif defined(BOARD_OLIMEX_SAM7_EX256)
-	#include "ginput_lld_toggle_board_olimexsam7ex256.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "ginput_lld_toggle_board.h"
-#endif
+/* Include the user supplied board definitions */
+#include "ginput_lld_toggle_board.h"
 
 #endif	/* GFX_USE_GDISP && GINPUT_NEED_TOGGLE */
 
-- 
cgit v1.2.3


From 555257933af6e7e3b106ac3589520b5dad45061b Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Mon, 28 Oct 2013 20:04:03 +1000
Subject: Clean up the driver directory structure by moving all board specific
 files into the boards sub-structure.

---
 drivers/gdisp/ED060SC4/board_ED060SC4_example.h    | 143 -----------------
 .../gdisp/HX8347D/board_HX8347D_stm32f4discovery.h | 160 -------------------
 .../ILI9320/board_ILI9320_olimex_pic32mx_lcd.h     | 126 ---------------
 .../gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h | 100 ------------
 .../gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h    | 112 -------------
 drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h   | 130 ----------------
 .../ILI9481/board_ILI9481_firebullstm32f103.h      | 107 -------------
 drivers/gdisp/RA8875/board_RA8875_marlin.h         | 113 --------------
 drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h  |  91 -----------
 .../SSD1289/board_SSD1289_firebullstm32f103.h      | 108 -------------
 .../gdisp/SSD1289/board_SSD1289_stm32f4discovery.h | 172 --------------------
 drivers/gdisp/SSD1306/board_SSD1306_i2c.h          | 129 ---------------
 drivers/gdisp/SSD1306/board_SSD1306_spi.h          | 132 ----------------
 drivers/gdisp/SSD1963/board_SSD1963_fsmc.h         | 105 -------------
 drivers/gdisp/SSD1963/board_SSD1963_gpio.h         | 102 ------------
 .../gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h  | 173 ---------------------
 .../ginput_lld_mouse_board_firebull_stm32f103.h    |  90 -----------
 .../ginput_lld_mouse_board_olimex_stm32_e407.h     |  90 -----------
 .../ginput_lld_mouse_board_st_stm32f4_discovery.h  |  90 -----------
 .../touch/FT5x06/ginput_lld_mouse_board_marlin.h   | 111 -------------
 drivers/ginput/touch/MCU/ginput_lld_mouse.c        |  10 +-
 .../ginput_lld_mouse_board_olimex_pic32mx_lcd.h    | 151 ------------------
 .../MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h  | 152 ------------------
 .../ginput_lld_mouse_board_embest_dmstf4bb.h       | 126 ---------------
 drivers/tdisp/HD44780/tdisp_lld.c                  |  10 +-
 .../tdisp/HD44780/tdisp_lld_board_olimex_e407.h    |  59 -------
 .../HD44780/tdisp_lld_board_st_stm32f4_discovery.h | 122 ---------------
 27 files changed, 2 insertions(+), 3012 deletions(-)
 delete mode 100644 drivers/gdisp/ED060SC4/board_ED060SC4_example.h
 delete mode 100644 drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
 delete mode 100644 drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
 delete mode 100644 drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
 delete mode 100644 drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
 delete mode 100644 drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
 delete mode 100644 drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
 delete mode 100644 drivers/gdisp/RA8875/board_RA8875_marlin.h
 delete mode 100644 drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
 delete mode 100644 drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
 delete mode 100644 drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
 delete mode 100644 drivers/gdisp/SSD1306/board_SSD1306_i2c.h
 delete mode 100644 drivers/gdisp/SSD1306/board_SSD1306_spi.h
 delete mode 100644 drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
 delete mode 100644 drivers/gdisp/SSD1963/board_SSD1963_gpio.h
 delete mode 100644 drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
 delete mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
 delete mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
 delete mode 100644 drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h
 delete mode 100644 drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_marlin.h
 delete mode 100644 drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h
 delete mode 100644 drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
 delete mode 100644 drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_embest_dmstf4bb.h
 delete mode 100644 drivers/tdisp/HD44780/tdisp_lld_board_olimex_e407.h
 delete mode 100644 drivers/tdisp/HD44780/tdisp_lld_board_st_stm32f4_discovery.h

(limited to 'drivers')

diff --git a/drivers/gdisp/ED060SC4/board_ED060SC4_example.h b/drivers/gdisp/ED060SC4/board_ED060SC4_example.h
deleted file mode 100644
index cb5a92b8..00000000
--- a/drivers/gdisp/ED060SC4/board_ED060SC4_example.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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
- */
-
-/* Board interface definitions for ED060SC4 PrimeView E-ink panel.
- * 
- * This file corresponds to the connections shown in example_schematics.png,
- * and is designed to interface with ChibiOS/RT.
- * 
- * Please note that this file has never been tested in exactly this pin
- * configuration, because the actual boards I have are slightly different.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-#include <hal.h>
-
-/*
- * IO pins assignments.
- */
-#define GPIOB_EINK_VDD      0
-#define GPIOB_EINK_GMODE    1
-#define GPIOB_EINK_SPV      2
-#define GPIOB_EINK_CKV      3
-#define GPIOB_EINK_CL       4
-#define GPIOB_EINK_LE       5
-#define GPIOB_EINK_OE       6
-#define GPIOB_EINK_SPH      7
-#define GPIOB_EINK_D0       8
-#define GPIOB_EINK_D1       9
-#define GPIOB_EINK_D2       10
-#define GPIOB_EINK_D3       11
-#define GPIOB_EINK_D4       12
-#define GPIOB_EINK_D5       13
-#define GPIOB_EINK_D6       14
-#define GPIOB_EINK_D7       15
-
-#define GPIOC_SMPS_CTRL     13
-#define GPIOC_VPOS_CTRL     14
-#define GPIOC_VNEG_CTRL     15
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* Main SMPS power control, active low
-		 * (open collector so that MOSFET gate can be pulled up to Vbat) */
-		palWritePad(GPIOC, GPIOC_SMPS_CTRL, true);
-		palSetPadMode(GPIOC, GPIOC_SMPS_CTRL, PAL_MODE_OUTPUT_OPENDRAIN);
-
-		/* Power control for the positive & negative side */
-		palWritePad(GPIOC, GPIOC_VPOS_CTRL, false);
-		palSetPadMode(GPIOC, GPIOC_VPOS_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
-		palWritePad(GPIOC, GPIOC_VNEG_CTRL, false);
-		palSetPadMode(GPIOC, GPIOC_VNEG_CTRL, PAL_MODE_OUTPUT_PUSHPULL);
-
-		/* Main data bus */
-		palWritePort(GPIOB, 0);
-		palSetGroupMode(GPIOB, 0xFFFF, 0, PAL_MODE_OUTPUT_PUSHPULL);
-		break;
-	}
-}
-
-/* Delay for display waveforms. Should be an accurate microsecond delay. */
-static void eink_delay(int us) {
-	halPolledDelay(US2RTT(us));
-}
-
-/* Turn the E-ink panel Vdd supply (+3.3V) on or off. */
-static inline void setpower_vdd(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_SMPS_CTRL, !on);
-	palWritePad(GPIOA, GPIOA_EINK_VDD, on);
-}
-
-/* Turn the E-ink panel negative supplies (-15V, -20V) on or off. */
-static inline void setpower_vneg(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOA, GPIOA_VNEG_CTRL, on);
-}
-
-/* Turn the E-ink panel positive supplies (-15V, -20V) on or off. */
-static inline void setpower_vpos(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOA, GPIOA_VPOS_CTRL, on);
-}
-
-/* Set the state of the LE (source driver Latch Enable) pin. */
-static inline void setpin_le(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_EINK_LE, on);
-}
-
-/* Set the state of the OE (source driver Output Enable) pin. */
-static inline void setpin_oe(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_EINK_OE, on);
-}
-
-/* Set the state of the CL (source driver Clock) pin. */
-static inline void setpin_cl(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_EINK_CL, on);
-}
-
-/* Set the state of the SPH (source driver Start Pulse Horizontal) pin. */
-static inline void setpin_sph(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_EINK_SPH, on);
-}
-
-/* Set the state of the D0-D7 (source driver Data) pins. */
-static inline void setpins_data(GDisplay *g, uint8_t value) {
-	(void) g;
-	palWriteGroup(GPIOB, 0xFF, GPIOB_EINK_D0, value);
-}
-
-/* Set the state of the CKV (gate driver Clock Vertical) pin. */
-static inline void setpin_ckv(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_EINK_CKV, on);
-}
-
-/* Set the state of the GMODE (gate driver Gate Mode) pin. */
-static inline void setpin_gmode(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOC, GPIOC_EINK_GMODE, on);
-}
-
-/* Set the state of the SPV (gate driver Start Pulse Vertical) pin. */
-static inline void setpin_spv(GDisplay *g, bool_t on) {
-	(void) g;
-	palWritePad(GPIOB, GPIOB_EINK_SPV, on);
-}
-
-#endif
diff --git a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h b/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
deleted file mode 100644
index df287477..00000000
--- a/drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/HX8347D/board_HX8347D_stm32f4discovery.h
- * @brief   GDISP Graphic Driver subsystem board SPI interface for the HX8347D display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-
-/* Pin assignments */
-#define SET_RST		palSetPad(GPIOB, 8)
-#define CLR_RST		palClearPad(GPIOB, 8)
-#define SET_DATA	palSetPad(GPIOB, 9)
-#define CLR_DATA	palClearPad(GPIOB, 9)
-#define SET_CS		palSetPad(GPIOA, 4)
-#define CLR_CS		palClearPad(GPIOA, 4)
-
-/* PWM configuration structure. We use timer 4 channel 2 (orange LED on board). */
-static const PWMConfig pwmcfg = {
-	1000000,		/* 1 MHz PWM clock frequency. */
-	100,			/* PWM period is 100 cycles. */
-	NULL,
-	{
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
-	},
-	0
-};
-
-/*
- * SPI1 configuration structure.
- * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
- * The slave select line is the pin 4 on the port GPIOA.
- */
-static const SPIConfig spi1cfg_8bit = {
-	NULL,
-	/* HW dependent part.*/
-	GPIOA,
-	4,
-	0 //SPI_CR1_BR_0
-};
-
-/*
- * SPI1 configuration structure.
- * Speed 42MHz, CPHA=0, CPOL=0, 16bits frames, MSb transmitted first.
- * The slave select line is the pin 4 on the port GPIOA.
- */
-static const SPIConfig spi1cfg_16bit = {
-	NULL,
-	/* HW dependent part.*/
-	GPIOA,
-	4,
-	SPI_CR1_DFF //SPI_CR1_BR_0
-};
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* Display backlight control */
-		/* TIM4 is an alternate function 2 (AF2) */
-		pwmStart(&PWMD4, &pwmcfg);
-		palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
-		pwmEnableChannel(&PWMD4, 1, 100);
-
-		palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RST    */
-		palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* RS     */
-		/*
-		 * Initializes the SPI driver 1. The SPI1 signals are routed as follow:
-		 * PB12 - NSS.
-		 * PB13 - SCK.
-		 * PB14 - MISO.
-		 * PB15 - MOSI.
-		 */
-		SET_CS; SET_DATA;
-		spiStart(&SPID1, &spi1cfg_8bit);
-		palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST);			/* NSS.     */
-		palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* SCK.     */
-		palSetPadMode(GPIOA, 6, PAL_MODE_ALTERNATE(5));										/* MISO.    */
-		palSetPadMode(GPIOA, 7, PAL_MODE_ALTERNATE(5)|PAL_STM32_OSPEED_HIGHEST);			/* MOSI.    */
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if (state) {
-		CLR_RST;
-	} else {
-		SET_RST;
-	}
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	pwmEnableChannel(&PWMD4, 1, percent);
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-	spiAcquireBus(&SPID1);
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));		// Safety
-	CLR_CS;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-	SET_CS;
-	spiReleaseBus(&SPID1);
-}
-
-static inline void busmode16(GDisplay *g) {
-	(void) g;
-	spiStart(&SPID1, &spi1cfg_16bit);
-}
-
-static inline void busmode8(GDisplay *g) {
-	(void) g;
-	spiStart(&SPID1, &spi1cfg_8bit);
-}
-
-static inline void write_index(GDisplay *g, uint8_t index) {
-	(void) g;
-    CLR_DATA;
-    SPI1->DR = index;
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-    SET_DATA;
-}
-
-static inline void write_data(GDisplay *g, uint8_t data) {
-	(void) g;
-    SPI1->DR = data;
-    while(((SPI1->SR & SPI_SR_TXE) == 0) || ((SPI1->SR & SPI_SR_BSY) != 0));
-}
-
-static inline void write_ram16(GDisplay *g, uint16_t data) {
-	(void) g;
-    SPI1->DR      = data;
-    while((SPI1->SR & SPI_SR_TXE) == 0);
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
deleted file mode 100644
index 5315127b..00000000
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9320/board_ILI9320_olimex_pic32mx_lcd.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-#ifndef noinline
-#define noinline __attribute__((noinline))
-#endif
-
-static void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		// RST
-		palSetPadMode(IOPORTA, 7, PAL_MODE_OUTPUT);
-		palClearPad(IOPORTA, 7);
-
-		// RS
-		palSetPadMode(IOPORTA, 10, PAL_MODE_OUTPUT);
-		palSetPad(IOPORTA, 10);
-
-		// CS
-		palSetPadMode(IOPORTA, 9, PAL_MODE_OUTPUT);
-		palClearPad(IOPORTA, 9);
-
-		// Backlight
-		palSetPadMode(IOPORTD, 3, PAL_MODE_OUTPUT);
-		palSetPad(IOPORTD, 3);
-
-		// PMP setup
-		PMMODE = 0;
-		PMAEN = 0;
-		PMCON = 0;
-		PMMODEbits.MODE = 2;
-		PMMODEbits.WAITB = 0;
-		PMMODEbits.WAITM = 1;
-		PMMODEbits.WAITE = 0;
-		PMCONbits.CSF = 0;
-		PMCONbits.PTRDEN = 1;
-		PMCONbits.PTWREN = 1;
-		PMMODEbits.MODE16 = 1;
-		PMCONbits.PMPEN = 1;
-
-		palClearPad(IOPORTA, 9);
-		break;
-	}
-}
-
-#define PmpWaitBusy()   do {} while (PMMODEbits.BUSY)
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static noinline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if (state)
-		palClearPad(IOPORTA, 7);
-	else
-		palSetPad(IOPORTA, 7);
-}
-
-static void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	if (percentage)
-		palClearPad(IOPORTD, 3);
-	else
-		palSetPad(IOPORTD, 3);
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static noinline void write_index(GDisplay *g, uint16_t index) {
-	volatile uint16_t dummy;
-	(void) g;
-
-	PmpWaitBusy();
-	palClearPad(IOPORTA, 10);
-	PMDIN = index;
-	PmpWaitBusy();
-	palSetPad(IOPORTA, 10);
-
-	dummy = PMDIN;
-	(void)dummy;
-}
-
-static noinline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	PMDIN = data;
-	PmpWaitBusy();
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-}
-
-static noinline uint16_t read_data(GDisplay *g) {
-	(void) g;
-	PmpWaitBusy();
-	return PMDIN;
-}
-
-#endif /* GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h b/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
deleted file mode 100644
index bca5caf8..00000000
--- a/drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9320/board_ILI9320_olimex_stm32_lcd.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9320 display.
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60100000)) /* RS = 1 */
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* FSMC setup for F1 */
-		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-		/* set pin modes */
-		IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0};
-		IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0};
-		palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-		palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-		palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL);
-
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[0+1] = (6) | (10 << 8) | (10 << 16);
-
-		/* Bank1 NOR/SRAM control register configuration
-		 * This is actually not needed as already set by default after reset */
-		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if(state)
-		palClearPad(GPIOE, GPIOE_TFT_RST);
-	else
-		palSetPad(GPIOE, GPIOE_TFT_RST);
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	if(percent)
-		palClearPad(GPIOD, GPIOD_TFT_LIGHT);
-	else
-		palSetPad(GPIOD, GPIOD_TFT_LIGHT);
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	(void) g;
-	return GDISP_RAM;
-}
-
-#endif /* GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h b/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
deleted file mode 100644
index 60508c1a..00000000
--- a/drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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
- */
-
-/*
-	driver quickly hacked together from a chinese sourcecode that came
-	with the board and existing ili9320 code by Chris van Dongen (sjaak)
-	(sjaak2002 at msn.com)
-	
-	Also added rotation for 180 and 270 degrees and minor tweaks to
-	setcursor
-	
-	Added code comes without warranty and free bugs. Feel free to use 
-	or misuse the added code :D
-*/
-
-
-/**
- * @file    drivers/gdisp/ILI9325/board_ILI9325_hy_stm32_100p.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* FSMC setup for F1 */
-		rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-		/* set pin modes */
-	/*	IOBus busD = {GPIOD, PAL_WHOLE_PORT, 0};
-		IOBus busE = {GPIOE, PAL_WHOLE_PORT, 0};
-		palSetBusMode(&busD, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-		palSetBusMode(&busE, PAL_MODE_STM32_ALTERNATE_PUSHPULL);
-		palSetPadMode(GPIOE, GPIOE_TFT_RST, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, GPIOD_TFT_LIGHT, PAL_MODE_OUTPUT_PUSHPULL); */
-
-		const unsigned char FSMC_Bank = 0;
-
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[FSMC_Bank+1] = (6) | (10 << 8) | (10 << 16);
-
-		/* Bank1 NOR/SRAM control register configuration
-		 * This is actually not needed as already set by default after reset */
-		FSMC_Bank1->BTCR[FSMC_Bank] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if(state)
-		palClearPad(GPIOE, GPIOE_TFT_RST);
-	else
-		palSetPad(GPIOE, GPIOE_TFT_RST);
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	(void)percent;
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	(void) g;
-	return GDISP_RAM;
-}
-
-#endif /* GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h b/drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
deleted file mode 100644
index a0eed13b..00000000
--- a/drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9341/board_ILI9341_mikromedia.h
- * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9341 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define SET_CS    palSetPad(GPIOE, GPIOE_LCD_CS);
-#define CLR_CS    palClearPad(GPIOE, GPIOE_LCD_CS);
-#define SET_RS    palSetPad(GPIOE, GPIOE_LCD_RS);
-#define CLR_RS    palClearPad(GPIOE, GPIOE_LCD_RS);
-#define SET_WR    palSetPad(GPIOE, GPIOE_PMWR);
-#define CLR_WR    palClearPad(GPIOE, GPIOE_PMWR);
-#define SET_RD    palSetPad(GPIOE, GPIOE_PMRD);
-#define CLR_RD    palClearPad(GPIOE, GPIOE_PMRD);
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* Configure the pins to a well know state */
-		SET_RS;
-		SET_RD;
-		SET_WR;
-		CLR_CS;
-
-		/* Hardware reset */
-		palSetPad(GPIOE, GPIOE_LCD_RST);
-		chThdSleepMilliseconds(100);
-		palClearPad(GPIOE, GPIOE_LCD_RST);
-		chThdSleepMilliseconds(100);
-		palSetPad(GPIOE, GPIOE_LCD_RST);
-		chThdSleepMilliseconds(100);
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if(state) {
-		// reset lcd
-		palClearPad(GPIOE, GPIOE_LCD_RST);
-	} else {
-		palSetPad(GPIOE, GPIOE_LCD_RST);
-	}
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	// TODO: can probably pwm this
-	if(percent) {
-		// turn back light on
-		palSetPad(GPIOE, GPIOE_LCD_BLED);
-	} else {
-		// turn off
-		palClearPad(GPIOE, GPIOE_LCD_BLED);
-	}
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-/**
- * @brief   Short delay
- *
- * @param[in] dly		Length of delay
- *
- * @notapi
- */
-static inline void ili9341_delay(uint16_t dly) {
-  static uint16_t i;
-  for(i = 0; i < dly; i++)
-    asm("nop");
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	palWriteGroup(GPIOE, 0x00FF, 0, index);
-	CLR_RS; CLR_WR; ili9341_delay(1); SET_WR; ili9341_delay(1); SET_RS;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	palWriteGroup(GPIOE, 0x00FF, 0, data);
-	CLR_WR; ili9341_delay(1); SET_WR; ili9341_delay(1);
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-	// change pin mode back to digital output
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	CLR_RD;
-	value = palReadPort(GPIOE);
-	value = palReadPort(GPIOE);
-	SET_RD;
-	return value;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h b/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
deleted file mode 100644
index 17bc554d..00000000
--- a/drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/ILI9481/board_ILI9481_firebullstm32f103.h
- * @brief   GDISP Graphics Driver subsystem low level driver source for
- * 			the ILI9481 and compatible HVGA display
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define SET_CS		palSetPad(GPIOD, 12);
-#define CLR_CS		palClearPad(GPIOD, 12);
-#define SET_RS		palSetPad(GPIOD, 13);
-#define CLR_RS		palClearPad(GPIOD, 13);
-#define SET_WR		palSetPad(GPIOD, 14);
-#define CLR_WR		palClearPad(GPIOD, 14);
-#define SET_RD		palSetPad(GPIOD, 15);
-#define CLR_RD		palClearPad(GPIOD, 15);
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
-
-		// Configure the pins to a well know state
-		SET_RS;
-		SET_RD;
-		SET_WR;
-		CLR_CS;
-		break;
-	}
-}
-
-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 set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	(void) percent;
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	palWritePort(GPIOE, index);
-	CLR_RS; CLR_WR; SET_WR; SET_RS;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	palWritePort(GPIOE, data);
-	CLR_WR; SET_WR;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-	// change pin mode back to digital output
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	uint16_t	value;
-	(void) g;
-	
-	CLR_RD;
-	value = palReadPort(GPIOE);
-	SET_RD;
-	
-	return value;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/RA8875/board_RA8875_marlin.h b/drivers/gdisp/RA8875/board_RA8875_marlin.h
deleted file mode 100644
index b1d55a92..00000000
--- a/drivers/gdisp/RA8875/board_RA8875_marlin.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/RA8875/board_RA8875_marlin.h
- * @brief   GDISP Graphic Driver subsystem board interface for the RA8875 display.
- */
-
-#ifndef _BOARD_RA8875_H
-#define _BOARD_RA8875_H
-
-// For a multiple display configuration we would put all this in a structure and then
-// set g->board to that structure.
-#define GDISP_RAM              (*((volatile uint16_t *) 0x68000000)) /* RS = 0 */
-#define GDISP_REG              (*((volatile uint16_t *) 0x68020000)) /* RS = 1 */
-#define FSMC_BANK				4
-
-
-static inline void init_board(GDisplay *g) {
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-		// setup for display 0
-		case 0: {		
-
-			// enable the FSMC peripheral
-			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-			// setup the pin modes for FSMC
-			IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 8) |
-									(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-			IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-								(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-			IOBus busG = {GPIOG, (1 << 10), 0};
-
-			palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-			palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-			palSetBusMode(&busG, PAL_MODE_ALTERNATE(12));
-
-			// FSMC timing
-			FSMC_Bank1->BTCR[FSMC_BANK+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
-					| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
-					| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
-
-			// Bank1 NOR/SRAM control register configuration
-			// This is actually not needed as already set by default after reset
-			FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-
-			break;
-		}
-
-		// marlin does not have any secondary display so far
-		default:
-			break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-	
-	// FSMC delay reduced as the controller now runs at full speed
-	FSMC_Bank1->BTCR[2+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-	FSMC_Bank1->BTCR[2] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-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_index(GDisplay *g, uint16_t index) {
-	(void) g;
-
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	(void) g;
-
-	return GDISP_RAM;
-}
-
-#endif /* _BOARD_RA8875_H */
-
diff --git a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h b/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
deleted file mode 100644
index e0bb8e26..00000000
--- a/drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/S6D1121/board_S6D1121_olimex_e407.h
- * @brief   GDISP Graphic Driver subsystem board interface for the S6D1121 display
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/* STM32F4 FSMC init */
-		rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-		/* set pins to FSMC mode */
-		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-							(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-							(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[0+1] = (6) | (10 << 8) | (10 << 16);
-
-		/* Bank1 NOR/SRAM control register configuration */
-		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-		break;
-	}
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	(void) state;
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	(void) percent;
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	(void) g;
-	return GDISP_RAM;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h b/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
deleted file mode 100644
index 99d37299..00000000
--- a/drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1289/board_SSD1289_firebullstm32f103.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define SET_CS		palSetPad(GPIOD, 12);
-#define CLR_CS		palClearPad(GPIOD, 12);
-#define SET_RS		palSetPad(GPIOD, 13);
-#define CLR_RS		palClearPad(GPIOD, 13);
-#define SET_WR		palSetPad(GPIOD, 14);
-#define CLR_WR		palClearPad(GPIOD, 14);
-#define SET_RD		palSetPad(GPIOD, 15);
-#define CLR_RD		palClearPad(GPIOD, 15);
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 12, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 13, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 14, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetPadMode(GPIOD, 15, PAL_MODE_OUTPUT_PUSHPULL);
-
-		// Configure the pins to a well know state
-		SET_RS;
-		SET_RD;
-		SET_WR;
-		CLR_CS;
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	(void) state;
-	/* Nothing to do here - reset pin tied to Vcc */
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	(void) percent;
-	/* Nothing to do here - Backlight always on */
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	palWritePort(GPIOE, index);
-	CLR_RS; CLR_WR; SET_WR; SET_RS;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	palWritePort(GPIOE, data);
-	CLR_WR; SET_WR;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-	// change pin mode to digital input
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_INPUT);
-	CLR_RD;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-	// change pin mode back to digital output
-	SET_RD;
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	return palReadPort(GPIOE);
-}
-
-#if defined(GDISP_USE_DMA)
-	#error "GDISP - SSD1289: The GPIO interface does not support DMA"
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-
diff --git a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h b/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
deleted file mode 100644
index 866311dc..00000000
--- a/drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1289/board_SSD1289_stm32f4discovery.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1289 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define GDISP_REG              ((volatile uint16_t *) 0x60000000)[0] /* RS = 0 */
-#define GDISP_RAM              ((volatile uint16_t *) 0x60020000)[0] /* RS = 1 */
-#define GDISP_DMA_STREAM		STM32_DMA2_STREAM6
-#define FSMC_BANK				0
-
-/* PWM configuration structure. We use timer 3 channel 3 */
-static const PWMConfig pwmcfg = {
-  100000,       /* 100 kHz PWM clock frequency. */
-  100,          /* PWM period is 100 cycles. */
-  NULL,
-  {
-   {PWM_OUTPUT_DISABLED, NULL},
-   {PWM_OUTPUT_DISABLED, NULL},
-   {PWM_OUTPUT_ACTIVE_HIGH, NULL},
-   {PWM_OUTPUT_DISABLED, NULL}
-  },
-  0
-};
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		/**
-		 * Performs the following functions:
-		 *		1. initialise the io port used by the display
-		 *		2. initialise the reset pin (initial state not-in-reset)
-		 *		3. initialise the chip select pin (initial state not-active)
-		 *		4. initialise the backlight pin (initial state back-light off)
-		 */
-
-		#if defined(STM32F1XX) || defined(STM32F3XX)
-			/* FSMC setup for F1/F3 */
-			rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-
-			#if defined(GDISP_USE_DMA)
-				#error "GDISP: SSD1289 - DMA not implemented for F1/F3 Devices"
-			#endif
-		#elif defined(STM32F4XX) || defined(STM32F2XX)
-			/* STM32F2-F4 FSMC init */
-			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-			#if defined(GDISP_USE_DMA)
-				if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL)) gfxExit();
-				dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
-				dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-			#else
-				#warning "GDISP: SSD1289 - DMA is supported for F2/F4 Devices. Define GDISP_USE_DMA in your gfxconf.h to turn this on for better performance."
-			#endif
-		#else
-			#error "GDISP: SSD1289 - FSMC not implemented for this device"
-		#endif
-
-		/* set pins to FSMC mode */
-		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-							(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[FSMC_BANK+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-
-		/* Bank1 NOR/SRAM control register configuration
-		 * This is actually not needed as already set by default after reset */
-		FSMC_Bank1->BTCR[FSMC_BANK] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-
-		/* Display backlight control */
-		/* TIM3 is an alternate function 2 (AF2) */
-		pwmStart(&PWMD3, &pwmcfg);
-		palSetPadMode(GPIOB, 0, PAL_MODE_ALTERNATE(2));
-		pwmEnableChannel(&PWMD3, 2, 100);
-		break;
-	}
-}
-
-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 set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-    pwmEnableChannel(&PWMD3, 2, percent);
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-	FSMC_Bank1->BTCR[FSMC_BANK+1] = FSMC_BTR1_ADDSET_3 | FSMC_BTR1_DATAST_3 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-	FSMC_Bank1->BTCR[FSMC_BANK+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0;		/* FSMC timing */
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	(void) g;
-	return GDISP_RAM;
-}
-
-#if defined(GDISP_USE_DMA) || defined(__DOXYGEN__)
-	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
-		(void) g;
-		dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-		dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		for (; area > 0; area -= 65535) {
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		}
-	}
-
-	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
-		(void) g;
-        dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-        dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		for (; area > 0; area -= 65535) {
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		}
-	}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h b/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
deleted file mode 100644
index 449d47ba..00000000
--- a/drivers/gdisp/SSD1306/board_SSD1306_i2c.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1306/board_SSD1306_i2c.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1306 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// The command byte to put on the front of each page line
-#define SSD1306_PAGE_PREFIX		0x40			 		// Co = 0, D/C = 1
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define SSD1306_RESET_PORT		GPIOB
-#define SSD1306_RESET_PIN		5
-
-/**
- * The default slave address is 0x3D, (talking about
- * only the real address part here) and the slave
- * address can be changed to 0x3C by soldering the
- * SA0 pads on the bottom side of the module.
- *
- * b7 | b6 | b5 | b4 | b3 | b2 | b1 | b0
- * --------------------------------------
- * 0  | 1  | 1  | 1  | 1  | 0  |SA0 | R/W
- */
-#define SSD1306_I2C_ADDRESS   	0x3D
-#define SSD1306_SDA_PORT		GPIOB
-#define SSD1306_SDA_PIN			7
-#define SSD1306_SCL_PORT		GPIOB
-#define SSD1306_SCL_PIN			6
-#define SET_RST					palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-#define CLR_RST					palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-
-// I2C configuration structure.
-static I2CConfig i2cconfig;
-
-#if GFX_USE_OS_CHIBIOS
-	static int32_t thdPriority = 0;
-#endif
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		// RESET pin.
-		palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
-
-
-		/*
-		 * Initializes the I2C driver 1. The I2C1 signals are routed as follows:
-		 * PB6 - SCL.
-		 * PB7 - SDA.
-		 * Timing value comes from ST I2C config tool (xls):
-		 * 0x00901D2B;		// 100kHz Standard Mode
-		 * 0x00300444;		// 100kHz Fast Mode
-		 * 0x0030020A;		// 400kHz Fast Mode
-		 * 0x00100002;		// 800kHz Fast Mode +
-		 */
-		palSetPadMode(SSD1306_SCL_PORT, SSD1306_SCL_PIN, PAL_MODE_ALTERNATE(1));
-		palSetPadMode(SSD1306_SDA_PORT, SSD1306_SDA_PIN, PAL_MODE_ALTERNATE(1));
-		i2cconfig.timingr = 0x00100002;		// 800kHz Fast Mode+
-		i2cInit();
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if(state)
-		CLR_RST
-	else
-		SET_RST
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-	#if GFX_USE_OS_CHIBIOS
-		thdPriority = (int32_t)chThdGetPriority();
-		chThdSetPriority(HIGHPRIO);
-	#endif
-	i2cAcquireBus(&I2CD1);
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-	#if GFX_USE_OS_CHIBIOS
-		chThdSetPriority(thdPriority);
-	#endif
-	i2cReleaseBus(&I2CD1);
-}
-
-static inline void write_cmd(GDisplay *g, uint8_t cmd) {
-	uint8_t command[2];
-	(void) g;
-
-	command[0] = 0x00;		// Co = 0, D/C = 0
-	command[1] = cmd;
-
-	i2cStart(&I2CD1, &i2cconfig);
-	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, command, 2, NULL, 0, MS2ST(10));
-	i2cStop(&I2CD1);
-}
-
-static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
-	(void) g;
-
-	i2cStart(&I2CD1, &i2cconfig);
-	i2cMasterTransmitTimeout(&I2CD1, SSD1306_I2C_ADDRESS, data, length, NULL, 0, MS2ST(10));
-	i2cStop(&I2CD1);
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-
-
diff --git a/drivers/gdisp/SSD1306/board_SSD1306_spi.h b/drivers/gdisp/SSD1306/board_SSD1306_spi.h
deleted file mode 100644
index 5b481630..00000000
--- a/drivers/gdisp/SSD1306/board_SSD1306_spi.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD1306/board_SSD1306_spi.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1306 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// The command byte to put on the front of each page line
-#define SSD1306_PAGE_PREFIX		0x40			 		// Co = 0, D/C = 1
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-#define SSD1306_RESET_PORT		GPIOB
-#define SSD1306_RESET_PIN		5
-#define SSD1306_MISO_PORT		GPIOB
-#define SSD1306_MISO_PIN		8
-#define SSD1306_MOSI_PORT		GPIOB
-#define SSD1306_MOSI_PIN		7
-#define SSD1306_SCK_PORT		GPIOB
-#define SSD1306_SCK_PIN			6
-#define SSD1306_CS_PORT			GPIOB
-#define SSD1306_CS_PIN			5
-#define SET_RST					palSetPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-#define CLR_RST					palClearPad(SSD1306_RESET_PORT, SSD1306_RESET_PIN);
-
-/*
- * SPI1 configuration structure.
- * Speed 42MHz, CPHA=0, CPOL=0, 8bits frames, MSb transmitted first.
- * The slave select line is the pin 4 on the port GPIOA.
- */
-static const SPIConfig spi1config = {
-	NULL,
-	/* HW dependent part.*/
-	SSD1306_MISO_PORT,
-	SSD1306_MISO_PIN,
-	0
-	//SPI_CR1_BR_0
-};
-
-#if GFX_USE_OS_CHIBIOS
-	static int32_t thdPriority = 0;
-#endif
-
-static inline void init_board(GDisplay *g) {
-	unsigned	i;
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		// RESET pin.
-		palSetPadMode(SSD1306_RESET_PORT, SSD1306_RESET_PIN, PAL_MODE_OUTPUT_PUSHPULL);
-
-		palSetPadMode(SSD1306_MISO_PORT, SSD1306_MISO_PIN, 	PAL_MODE_ALTERNATE(1)|
-															PAL_STM32_OSPEED_HIGHEST);
-		palSetPadMode(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN, 	PAL_MODE_ALTERNATE(1)|
-															PAL_STM32_OSPEED_HIGHEST);
-		palSetPadMode(SSD1306_SCK_PORT,  SSD1306_SCK_PIN,  	PAL_MODE_ALTERNATE(1)|
-															PAL_STM32_OSPEED_HIGHEST);
-		palSetPad(SSD1306_CS_PORT, SSD1306_CS_PIN);
-		palSetPadMode(SSD1306_CS_PORT,   SSD1306_CS_PIN,   	PAL_MODE_ALTERNATE(1)|
-															PAL_STM32_OSPEED_HIGHEST);
-		spiInit();
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if(state)
-		CLR_RST
-	else
-		SET_RST
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-	#if GFX_USE_OS_CHIBIOS
-		thdPriority = (int32_t)chThdGetPriority();
-		chThdSetPriority(HIGHPRIO);
-	#endif
-	spiAcquireBus(&SPID1);
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-	#if GFX_USE_OS_CHIBIOS
-		chThdSetPriority(thdPriority);
-	#endif
-	spiReleaseBus(&SPID1);
-}
-
-static inline void write_cmd(GDisplay *g, uint8_t cmd) {
-	uint8_t command[2];
-
-	command[0] = 0x00;		// Co = 0, D/C = 0
-	command[1] = cmd;
-
-	spiStart(&SPID1, &spi1config);
-	spiSelect(&SPID1);
-	spiStartSend(&SPID1, 2, command);
-	spiUnselect(&SPID1);
-	spiStop(&SPID1);
-}
-
-static inline void write_data(GDisplay *g, uint8_t* data, uint16_t length) {
-	(void) g;
-
-	spiStart(&SPID1, &spi1config);
-	spiSelect(&SPID1);
-	spiStartSend(&SPID1, length, data);
-	spiUnselect(&SPID1);
-	spiStop(&SPID1);
-}
-
-
-#endif /* _GDISP_LLD_BOARD_H */
-
diff --git a/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h b/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
deleted file mode 100644
index 6c7119a4..00000000
--- a/drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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://chibios-gfx.com/license.html
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/board_SSD1963_fsmc.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-static const LCD_Parameters	DisplayTimings[] = {
-	// You need one of these array elements per display
-	{
-		480, 272,								// Panel width and height
-		2, 2, 41,								// Horizontal Timings (back porch, front porch, pulse)
-		CALC_PERIOD(480,2,2,41),				// Total Horizontal Period (calculated from above line)
-		2, 2, 10,								// Vertical Timings (back porch, front porch, pulse)
-		CALC_PERIOD(272,2,2,10),				// Total Vertical Period (calculated from above line)
-		CALC_FPR(480,272,2,2,41,2,2,10,60ULL)	// FPR - the 60ULL is the frames per second. Note the ULL!
-	},
-};
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-
-/* Using FSMC A16 as RS */
-#define GDISP_REG              (*((volatile uint16_t *) 0x60000000)) /* RS = 0 */
-#define GDISP_RAM              (*((volatile uint16_t *) 0x60020000)) /* RS = 1 */
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		#if defined(STM32F1XX) || defined(STM32F3XX)
-			/* FSMC setup for F1/F3 */
-			rccEnableAHB(RCC_AHBENR_FSMCEN, 0);
-		#elif defined(STM32F4XX) || defined(STM32F2XX)
-			/* STM32F2-F4 FSMC init */
-			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-		#else
-			#error "FSMC not implemented for this device"
-		#endif
-
-		/* set pins to FSMC mode */
-		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-								(1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15), 0};
-
-		IOBus busE = {GPIOE, (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-							(1 << 13) | (1 << 14) | (1 << 15), 0};
-	
-		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-		/* FSMC timing */
-		FSMC_Bank1->BTCR[0+1] = (FSMC_BTR1_ADDSET_1 | FSMC_BTR1_ADDSET_3) \
-				| (FSMC_BTR1_DATAST_1 | FSMC_BTR1_DATAST_3) \
-				| (FSMC_BTR1_BUSTURN_1 | FSMC_BTR1_BUSTURN_3) ;
-	
-		/* Bank1 NOR/SRAM control register configuration
-		 * This is actually not needed as already set by default after reset */
-		FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-	/* FSMC delay reduced as the controller now runs at full speed */
-	FSMC_Bank1->BTCR[0+1] = FSMC_BTR1_ADDSET_0 | FSMC_BTR1_DATAST_2 | FSMC_BTR1_BUSTURN_0 ;
-	FSMC_Bank1->BTCR[0] = FSMC_BCR1_MWID_0 | FSMC_BCR1_WREN | FSMC_BCR1_MBKEN;
-}
-
-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_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	GDISP_RAM = data;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-
diff --git a/drivers/gdisp/SSD1963/board_SSD1963_gpio.h b/drivers/gdisp/SSD1963/board_SSD1963_gpio.h
deleted file mode 100644
index 0b9c0135..00000000
--- a/drivers/gdisp/SSD1963/board_SSD1963_gpio.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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://chibios-gfx.com/license.html
- */
-
-/**
- * @file    drivers/gdisp/SSD1963/board_SSD1963_gpio.h
- * @brief   GDISP Graphic Driver subsystem board interface for the SSD1963 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-static const LCD_Parameters	DisplayTimings[] = {
-	// You need one of these array elements per display
-	{
-		480, 272,								// Panel width and height
-		2, 2, 41,								// Horizontal Timings (back porch, front porch, pulse)
-		CALC_PERIOD(480,2,2,41),				// Total Horizontal Period (calculated from above line)
-		2, 2, 10,								// Vertical Timings (back porch, front porch, pulse)
-		CALC_PERIOD(272,2,2,10),				// Total Vertical Period (calculated from above line)
-		CALC_FPR(480,272,2,2,41,2,2,10,60ULL)	// FPR - the 60ULL is the frames per second. Note the ULL!
-	},
-};
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-
-/**
- * @brief	The GPIO pin config
- *
- * @details	This block of defines tell your driver how you wired your display
- *			controller to your MCU. Please change them accordingly.
- */
-#define GDISP_CMD_PORT		GPIOC
-#define GDISP_DATA_PORT		GPIOD
-#define GDISP_CS			0
-#define GDISP_RS			1
-#define GDISP_WR			2
-#define GDISP_RD			3
-
-#define Set_CS		palSetPad(GDISP_CMD_PORT, GDISP_CS);
-#define Clr_CS		palClearPad(GDISP_CMD_PORT, GDISP_CS);
-#define Set_RS		palSetPad(GDISP_CMD_PORT, GDISP_RS);
-#define Clr_RS		palClearPad(GDISP_CMD_PORT, GDISP_RS);
-#define Set_WR		palSetPad(GDISP_CMD_PORT, GDISP_WR);
-#define Clr_WR		palClearPad(GDISP_CMD_PORT, GDISP_WR);
-#define Set_RD		palSetPad(GDISP_CMD_PORT, GDISP_RD);
-#define Clr_RD		palClearPad(GDISP_CMD_PORT, GDISP_RD);
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		IOBus busCMD = {GDISP_CMD_PORT, (1 << GDISP_CS) | (1 << GDISP_RS) | (1 << GDISP_WR) | (1 << GDISP_RD), 0};
-		IOBus busDATA = {GDISP_CMD_PORT, 0xFFFFF, 0};
-		palSetBusMode(&busCMD, PAL_MODE_OUTPUT_PUSHPULL);
-		palSetBusMode(&busDATA, PAL_MODE_OUTPUT_PUSHPULL);
-		break;
-	}
-}
-
-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;
-	Set_CS;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-	Clr_CS;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	Set_RS; Clr_RD; Set_WR;
-	palWritePort(GDISP_DATA_PORT, index);
-	Clr_WR;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	Clr_RS; Clr_RD; Set_WR;
-	palWritePort(GDISP_DATA_PORT, data);
-	Clr_WR;
-}
-
-#endif /* _GDISP_LLD_BOARD_H */
-
diff --git a/drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h b/drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
deleted file mode 100644
index 927e93a4..00000000
--- a/drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/gdisp/SSD2119/board_SSD2119_embest_dmstf4bb.h
- * @brief   GDISP Graphic Driver subsystem board FSMC interface for the SSD2119 display.
- */
-
-#ifndef _GDISP_LLD_BOARD_H
-#define _GDISP_LLD_BOARD_H
-
-// For a multiple display configuration we would put all this in a structure and then
-//	set g->board to that structure.
-
-/* Using FSMC A19 (PE3) as DC */
-#define GDISP_REG (*((volatile uint16_t *) 0x60000000)) /* DC = 0 */
-#define GDISP_RAM (*((volatile uint16_t *) 0x60100000)) /* DC = 1 */
-#define GDISP_DMA_STREAM STM32_DMA2_STREAM6
-
-#define SET_RST palSetPad(GPIOD, 3);
-#define CLR_RST palClearPad(GPIOD, 3);
-
-/*
- * PWM configuration structure. We use timer 4 channel 2 (orange LED on board).
- * The reason for so high clock is that with any lower, onboard coil is squeaking.
- * The major disadvantage of this clock is a lack of linearity between PWM duty
- * cycle width and brightness. In fact only with low preset one sees any change
- * (eg. duty cycle between 1-20). Feel free to adjust this, maybe only my board
- * behaves like this. According to the G5126 datesheet (backlight LED driver)
- * the PWM frequency should be somewhere between 200 Hz to 200 kHz.
- */
-static const PWMConfig pwmcfg = {
-	1000000,       /* 1 MHz PWM clock frequency. */
-	100,           /* PWM period is 100 cycles. */
-	NULL,
-	{
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL},
-		{PWM_OUTPUT_ACTIVE_HIGH, NULL}
-	},
-	0
-};
-
-static inline void init_board(GDisplay *g) {
-
-	// As we are not using multiple displays we set g->board to NULL as we don't use it.
-	g->board = 0;
-
-	switch(g->controllerdisplay) {
-	case 0:											// Set up for Display 0
-		#if defined(STM32F4XX) || defined(STM32F2XX)
-			/* STM32F4 FSMC init */
-			rccEnableAHB3(RCC_AHB3ENR_FSMCEN, 0);
-
-			#if defined(GDISP_USE_DMA) && defined(GDISP_DMA_STREAM)
-				if (dmaStreamAllocate(GDISP_DMA_STREAM, 0, NULL, NULL))
-					gfxExit();
-				dmaStreamSetMemory0(GDISP_DMA_STREAM, &GDISP_RAM);
-				dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-			#endif
-		#else
-			#error "FSMC not implemented for this device"
-		#endif
-
-		/* Group pins */
-		IOBus busD = {GPIOD, (1 << 0) | (1 << 1) | (1 << 4) | (1 << 5) | (1 << 7) | (1 << 8) |
-								(1 << 9) | (1 << 10) | (1 << 14) | (1 << 15), 0};
-
-		IOBus busE = {GPIOE, (1 << 3) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 12) |
-								(1 << 13) | (1 << 14) | (1 << 15), 0};
-
-		/* FSMC is an alternate function 12 (AF12) */
-		palSetBusMode(&busD, PAL_MODE_ALTERNATE(12));
-		palSetBusMode(&busE, PAL_MODE_ALTERNATE(12));
-
-		/* FSMC timing register configuration */
-		FSMC_Bank1->BTCR[0 + 1] = (FSMC_BTR1_ADDSET_2 | FSMC_BTR1_ADDSET_1) \
-				| (FSMC_BTR1_DATAST_2 | FSMC_BTR1_DATAST_1) \
-				| FSMC_BTR1_BUSTURN_0;
-
-		/* Bank1 NOR/PSRAM control register configuration
-		 * Write enable, memory databus width set to 16 bit, memory bank enable */
-		FSMC_Bank1->BTCR[0] = FSMC_BCR1_WREN | FSMC_BCR1_MWID_0 | FSMC_BCR1_MBKEN;
-
-		/* Display backlight control */
-		/* TIM4 is an alternate function 2 (AF2) */
-		pwmStart(&PWMD4, &pwmcfg);
-		palSetPadMode(GPIOD, 13, PAL_MODE_ALTERNATE(2));
-		pwmEnableChannel(&PWMD4, 1, 100);
-		break;
-	}
-}
-
-static inline void post_init_board(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setpin_reset(GDisplay *g, bool_t state) {
-	(void) g;
-	if (state) {
-		CLR_RST;
-	} else {
-		SET_RST;
-	}
-}
-
-static inline void set_backlight(GDisplay *g, uint8_t percent) {
-	(void) g;
-	pwmEnableChannel(&PWMD4, 1, percent);
-}
-
-static inline void acquire_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void release_bus(GDisplay *g) {
-	(void) g;
-}
-
-static inline void write_index(GDisplay *g, uint16_t index) {
-	(void) g;
-	GDISP_REG = index;
-}
-
-static inline void write_data(GDisplay *g, uint16_t data) {
-	(void) g;
-	GDISP_RAM = data;
-}
-
-static inline void setreadmode(GDisplay *g) {
-	(void) g;
-}
-
-static inline void setwritemode(GDisplay *g) {
-	(void) g;
-}
-
-static inline uint16_t read_data(GDisplay *g) {
-	(void) g;
-	return GDISP_RAM;
-}
-
-#if defined(GDISP_USE_DMA)
-	static inline void dma_with_noinc(GDisplay *g, color_t *buffer, int area) {
-		(void) g;
-		dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-		dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		for (; area > 0; area -= 65535) {
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		}
-	}
-
-	static inline void dma_with_inc(GDisplay *g, color_t *buffer, int area) {
-		(void) g;
-        dmaStreamSetPeripheral(GDISP_DMA_STREAM, buffer);
-        dmaStreamSetMode(GDISP_DMA_STREAM, STM32_DMA_CR_PL(0) | STM32_DMA_CR_PINC | STM32_DMA_CR_PSIZE_HWORD | STM32_DMA_CR_MSIZE_HWORD | STM32_DMA_CR_DIR_M2M);
-		for (; area > 0; area -= 65535) {
-			dmaStreamSetTransactionSize(GDISP_DMA_STREAM, area > 65535 ? 65535 : area);
-			dmaStreamEnable(GDISP_DMA_STREAM);
-			dmaWaitCompletion(GDISP_DMA_STREAM);
-		}
-	}
-#endif
-
-#endif /* _GDISP_LLD_BOARD_H */
-
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
deleted file mode 100644
index ebcc26c7..00000000
--- a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_firebull_stm32f103.h
- * @brief   GINPUT ouch low level driver source for the ADS7843 on the FireBull STM32F103-FB board.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-static const SPIConfig spicfg = { 
-    NULL,
-	GPIOC, 
-    6,
-    /* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	spiStart(&SPID1, &spicfg);
-}
-
-/**
- * @brief   Check whether the surface is currently touched
- * @return	TRUE if the surface is currently touched
- *
- * @notapi
- */
-static inline bool_t getpin_pressed(void) {
-	return (!palReadPad(GPIOC, 4));
-}
-/**
- * @brief   Aquire the bus ready for readings
- *
- * @notapi
- */
-static inline void aquire_bus(void) {
-	spiAcquireBus(&SPID1);
-    //TOUCHSCREEN_SPI_PROLOGUE();
-    palClearPad(GPIOC, 6);
-}
-
-/**
- * @brief   Release the bus after readings
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	palSetPad(GPIOC, 6);
-	spiReleaseBus(&SPID1);
-    //TOUCHSCREEN_SPI_EPILOGUE();
-}
-
-/**
- * @brief   Read a value from touch controller
- * @return	The value read from the controller
- *
- * params[in] port	The controller port to read.
- *
- * @notapi
- */
-static inline uint16_t read_value(uint16_t port) {
-    static uint8_t txbuf[3] = {0};
-    static uint8_t rxbuf[3] = {0};
-    uint16_t ret;
-
-    txbuf[0] = port;
-
-    spiExchange(&SPID1, 3, txbuf, rxbuf);
-
-    ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3); 
-    
-	return ret;
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
deleted file mode 100644
index 01572f0d..00000000
--- a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
- * @brief   GINPUT Touch low level driver source for the ADS7843 on an Olimex STM32E407.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-static const SPIConfig spicfg = { 
-    NULL,
-	GPIOG, 
-    10,
-    /* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	spiStart(&SPID2, &spicfg);
-}
-
-/**
- * @brief   Check whether the surface is currently touched
- * @return	TRUE if the surface is currently touched
- *
- * @notapi
- */
-static inline bool_t getpin_pressed(void) {
-	return (!palReadPad(GPIOG, 0));
-}
-/**
- * @brief   Aquire the bus ready for readings
- *
- * @notapi
- */
-static inline void aquire_bus(void) {
-	spiAcquireBus(&SPID2);
-    //TOUCHSCREEN_SPI_PROLOGUE();
-    palClearPad(GPIOG, 10);
-}
-
-/**
- * @brief   Release the bus after readings
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	palSetPad(GPIOG, 10);
-	spiReleaseBus(&SPID2);
-    //TOUCHSCREEN_SPI_EPILOGUE();
-}
-
-/**
- * @brief   Read a value from touch controller
- * @return	The value read from the controller
- *
- * params[in] port	The controller port to read.
- *
- * @notapi
- */
-static inline uint16_t read_value(uint16_t port) {
-    static uint8_t txbuf[3] = {0};
-    static uint8_t rxbuf[3] = {0};
-    uint16_t ret;
-
-    txbuf[0] = port;
-
-    spiExchange(&SPID2, 3, txbuf, rxbuf);
-
-    ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3); 
-    
-	return ret;
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h b/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h
deleted file mode 100644
index 158934b6..00000000
--- a/drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_st_stm32f4_discovery.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/ADS7843/ginput_lld_mouse_board_olimex_stm32_e407.h
- * @brief   GINPUT Touch low level driver source for the ADS7843 on an Olimex STM32E407.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-static const SPIConfig spicfg = { 
-    NULL,
-	GPIOC,
-    4,
-    /* SPI_CR1_BR_2 |*/ SPI_CR1_BR_1 | SPI_CR1_BR_0,
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	spiStart(&SPID2, &spicfg);
-}
-
-/**
- * @brief   Check whether the surface is currently touched
- * @return	TRUE if the surface is currently touched
- *
- * @notapi
- */
-static inline bool_t getpin_pressed(void) {
-	return (!palReadPad(GPIOC, 5));
-}
-/**
- * @brief   Aquire the bus ready for readings
- *
- * @notapi
- */
-static inline void aquire_bus(void) {
-	spiAcquireBus(&SPID2);
-    //TOUCHSCREEN_SPI_PROLOGUE();
-    palClearPad(GPIOC, 4);
-}
-
-/**
- * @brief   Release the bus after readings
- *
- * @notapi
- */
-static inline void release_bus(void) {
-	palSetPad(GPIOC, 4);
-	spiReleaseBus(&SPID2);
-    //TOUCHSCREEN_SPI_EPILOGUE();
-}
-
-/**
- * @brief   Read a value from touch controller
- * @return	The value read from the controller
- *
- * params[in] port	The controller port to read.
- *
- * @notapi
- */
-static inline uint16_t read_value(uint16_t port) {
-    static uint8_t txbuf[3] = {0};
-    static uint8_t rxbuf[3] = {0};
-    uint16_t ret;
-
-    txbuf[0] = port;
-
-    spiExchange(&SPID2, 3, txbuf, rxbuf);
-
-    ret = (rxbuf[1] << 5) | (rxbuf[2] >> 3); 
-    
-	return ret;
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_marlin.h b/drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_marlin.h
deleted file mode 100644
index e3e18c24..00000000
--- a/drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_marlin.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/FT5x06/ginput_lld_mouse_board_marlin.h
- * @brief   GINPUT Touch low level driver source for the FT5x06.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-/* I2C interface #2 - Touchscreen controller */
-static const I2CConfig i2ccfg2 = {
-    OPMODE_I2C,
-    400000,
-    FAST_DUTY_CYCLE_2,
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static void init_board(void) {
-
-}
-
-
-/**
- * @brief	Write a value into a certain register
- *
- * @param[in] reg	The register address
- * @param[in] n		The amount of bytes (one or two)
- * @param[in] val	The value
- *
- * @notapi
- */
-static void write_reg(uint8_t reg, uint8_t n, uint16_t val) {
-	uint8_t txbuf[3];
-
-	i2cAcquireBus(&I2CD2);
-
-	txbuf[0] = reg;
-
-	if (n == 1) {
-		txbuf[1] = val;
-		i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 2, NULL, 0, MS2ST(FT5x06_TIMEOUT));
-	} else if (n == 2) {
-		txbuf[1] = ((val & 0xFF00) >> 8);
-		txbuf[2] = (val & 0x00FF);
-		i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 3, NULL, 0, MS2ST(FT5x06_TIMEOUT));
-	}
-	
-	i2cReleaseBus(&I2CD2);
-}
- 
-/**
- * @brief	Read the value of a certain register
- *
- * @param[in] reg	The register address
- * @param[in] n		The amount of bytes (one or two)
- *
- * @return Data read from device (one byte or two depending on n param)
- *
- * @notapi
- */
-static uint16_t read_reg(uint8_t reg, uint8_t n) {
-	uint8_t txbuf[1], rxbuf[2];
-	uint16_t ret;
-
-	rxbuf[0] = 0;
-	rxbuf[1] = 0;
-
-	i2cAcquireBus(&I2CD2);
-
-	txbuf[0] = reg;
-	i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 1, rxbuf, n, MS2ST(FT5x06_TIMEOUT));
-
-	if (n == 1) {
-		ret = rxbuf[0];
-	} else if (n == 2) {
-		ret = ((rxbuf[0] << 8) | (rxbuf[1] & 0xFF));
-	}
-
-	i2cReleaseBus(&I2CD2);
-
-	return ret;
-}
-
-static void read_reg_n(uint8_t reg, uint8_t n, uint8_t *rxbuf) {
-	uint8_t txbuf[1];
-
-	i2cAcquireBus(&I2CD2);
-
-	txbuf[0] = reg;
-	i2cMasterTransmitTimeout(&I2CD2, FT5x06_ADDR, txbuf, 1, rxbuf, n, MS2ST(FT5x06_TIMEOUT));
-
-	i2cReleaseBus(&I2CD2);
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
-
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse.c b/drivers/ginput/touch/MCU/ginput_lld_mouse.c
index 1bb7cd50..a64bf6cb 100644
--- a/drivers/ginput/touch/MCU/ginput_lld_mouse.c
+++ b/drivers/ginput/touch/MCU/ginput_lld_mouse.c
@@ -21,15 +21,7 @@
 
 #include "ginput/lld/mouse.h"
 
-#if defined(GINPUT_MOUSE_USE_CUSTOM_BOARD) && GINPUT_MOUSE_USE_CUSTOM_BOARD
-	#include "ginput_lld_mouse_board.h"
-#elif defined(BOARD_OLIMEX_STM32_LCD)
-	#include "ginput_lld_mouse_board_olimex_stm32_lcd.h"
-#elif defined(BOARD_OLIMEX_PIC32MX_LCD)
-	#include "ginput_lld_mouse_board_olimex_pic32mx_lcd.h"
-#else
-	#include "ginput_lld_mouse_board.h"
-#endif
+#include "ginput_lld_mouse_board.h"
 
 static uint16_t sampleBuf[7];
 static coord_t	lastx, lasty;
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h
deleted file mode 100644
index c4689ecb..00000000
--- a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_pic32mx_lcd.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
- * @brief   GINPUT Touch low level driver source for the MCU on the example board.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- *
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-static const ADCConfig ADCC = {
-  .vref = ADC_VREF_CFG_AVDD_AVSS,
-  .stime = 15,
-  .irq = EIC_IRQ_ADC,
-  .base = _ADC10_BASE_ADDRESS,
-};
-static struct ADCDriver ADCD;
-
-#define YNEG 13 // U
-#define XNEG 15 // R
-#define XPOS 12 // L
-#define YPOS 11 // D
-
-#define ADC_MAX 1023
-
-#define TOUCH_THRESHOULD 50
-
-static const ADCConversionGroup ADC_X_CG = {
-  .circular = FALSE,
-  .num_channels = 1,
-  .channels = 1 << XNEG,
-};
-
-static const ADCConversionGroup ADC_Y_CG = {
-  .circular = FALSE,
-  .num_channels = 1,
-  .channels = 1 << YPOS,
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static inline void init_board(void) {
-  adcObjectInit(&ADCD);
-  adcStart(&ADCD, &ADCC);
-}
-
-/**
- * @brief   Check whether the surface is currently touched
- * @return	TRUE if the surface is currently touched
- *
- * @notapi
- */
-static inline bool_t getpin_pressed(void) {
-  adcsample_t samples[2] = {0, };
-
-  // Set X+ to ground
-  palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
-  palClearPad(IOPORTB, XPOS);
-
-  // Set Y- to VCC
-  palSetPadMode(IOPORTB, YNEG, PAL_MODE_OUTPUT);
-  palSetPad(IOPORTB, YNEG);
-
-  palSetPadMode(IOPORTB, XNEG, PAL_MODE_INPUT_ANALOG);
-  palSetPadMode(IOPORTB, YPOS, PAL_MODE_INPUT_ANALOG);
-
-  adcConvert(&ADCD, &ADC_X_CG, &samples[0], 1);
-  adcConvert(&ADCD, &ADC_Y_CG, &samples[1], 1);
-
-  return (ADC_MAX - (samples[1] - samples[0])) > TOUCH_THRESHOULD;
-}
-
-/**
- * @brief   Aquire the bus ready for readings
- *
- * @notapi
- */
-static inline void aquire_bus(void) {
-}
-
-/**
- * @brief   Release the bus after readings
- *
- * @notapi
- */
-static inline void release_bus(void) {
-}
-
-/**
- * @brief   Read an x value from touch controller
- * @return	The value read from the controller
- *
- * @notapi
- */
-static inline uint16_t read_x_value(void) {
-  adcsample_t sample;
-
-  palSetPadMode(IOPORTB, XPOS, PAL_MODE_OUTPUT);
-  palSetPad(IOPORTB, XPOS);
-
-  palSetPadMode(IOPORTB, XNEG, PAL_MODE_OUTPUT);
-  palClearPad(IOPORTB, XNEG);
-
-  palSetPadMode(IOPORTB, YNEG, PAL_MODE_INPUT);
-
-  palSetPadMode(IOPORTB, YPOS, PAL_MODE_INPUT_ANALOG);
-
-  adcConvert(&ADCD, &ADC_Y_CG, &sample, 1);
-
-  return ADC_MAX - sample;
-}
-
-/**
- * @brief   Read an y value from touch controller
- * @return	The value read from the controller
- *
- * @notapi
- */
-static inline uint16_t read_y_value(void) {
-  adcsample_t sample;
-
-  palSetPadMode(IOPORTB, YNEG, PAL_MODE_OUTPUT);
-  palClearPad(IOPORTB, YNEG);
-
-  palSetPadMode(IOPORTB, YPOS, PAL_MODE_OUTPUT);
-  palSetPad(IOPORTB, YPOS);
-
-  palSetPadMode(IOPORTB, XPOS, PAL_MODE_INPUT);
-
-  palSetPadMode(IOPORTB, XNEG, PAL_MODE_INPUT_ANALOG);
-
-  adcConvert(&ADCD, &ADC_X_CG, &sample, 1);
-
-  return ADC_MAX - sample;
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h b/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
deleted file mode 100644
index 2cc58f3c..00000000
--- a/drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/MCU/ginput_lld_mouse_board_olimex_stm32_lcd.h
- * @brief   GINPUT Touch low level driver source for the MCU on the example board.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- *
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-#define ADC_NUM_CHANNELS   2
-#define ADC_BUF_DEPTH      1
-
-static const ADCConversionGroup adc_y_config = { 
-    FALSE,
-    ADC_NUM_CHANNELS,
-    NULL,
-    NULL,
-    0, 0,    
-    0, 0,    
-    ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
-    0,    
-    ADC_SQR3_SQ2_N(ADC_CHANNEL_IN12) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN13)
-};
-
-static const ADCConversionGroup adc_x_config = { 
-    FALSE,
-    ADC_NUM_CHANNELS,
-    NULL,
-    NULL,
-    0, 0,
-    0, 0,
-    ADC_SQR1_NUM_CH(ADC_NUM_CHANNELS),
-    0,  
-    ADC_SQR3_SQ2_N(ADC_CHANNEL_IN10) | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN11)
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static inline void init_board(void) {
-	adcStart(&ADCD1, NULL);
-}
-
-/**
- * @brief   Check whether the surface is currently touched
- * @return	TRUE if the surface is currently touched
- *
- * @notapi
- */
-static inline bool_t getpin_pressed(void) {
-    palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_PULLDOWN);
-    palSetPadMode(GPIOC, 1, PAL_MODE_INPUT);
-    palSetPadMode(GPIOC, 2, PAL_MODE_INPUT);
-    palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
-    palSetPad(GPIOC, 3);
-	
-	return palReadPad(GPIOC, 0);
-}
-
-/**
- * @brief   Aquire the bus ready for readings
- *
- * @notapi
- */
-static inline void aquire_bus(void) {
-
-}
-
-/**
- * @brief   Release the bus after readings
- *
- * @notapi
- */
-static inline void release_bus(void) {
-
-}
-
-/**
- * @brief   Read an x value from touch controller
- * @return	The value read from the controller
- *
- * @notapi
- */
-static inline uint16_t read_x_value(void) {
-	uint16_t val1, val2;
-    adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
-
-    palSetPadMode(GPIOC, 0, PAL_MODE_INPUT_ANALOG);
-    palSetPadMode(GPIOC, 1, PAL_MODE_INPUT_ANALOG);
-    palSetPadMode(GPIOC, 2, PAL_MODE_OUTPUT_PUSHPULL);
-    palSetPadMode(GPIOC, 3, PAL_MODE_OUTPUT_PUSHPULL);
-    
-	palSetPad(GPIOC, 2);
-    palClearPad(GPIOC, 3); 
-    gfxSleepMilliseconds(1);
-    adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);  
-    val1 = ((samples[0] + samples[1])/2);
-    
-	palClearPad(GPIOC, 2);
-    palSetPad(GPIOC, 3);
-    gfxSleepMilliseconds(1);
-    adcConvert(&ADCD1, &adc_x_config, samples, ADC_BUF_DEPTH);
-    val2 = ((samples[0] + samples[1])/2);
-    
-	return ((val1+((1<<12)-val2))/4);
-}
-
-/**
- * @brief   Read an y value from touch controller
- * @return	The value read from the controller
- *
- * @notapi
- */
-static inline uint16_t read_y_value(void) {
-	uint16_t val1, val2;
-    adcsample_t samples[ADC_NUM_CHANNELS * ADC_BUF_DEPTH];
-
-    palSetPadMode(GPIOC, 2, PAL_MODE_INPUT_ANALOG);
-    palSetPadMode(GPIOC, 3, PAL_MODE_INPUT_ANALOG);
-    palSetPadMode(GPIOC, 0, PAL_MODE_OUTPUT_PUSHPULL);
-    palSetPadMode(GPIOC, 1, PAL_MODE_OUTPUT_PUSHPULL);
-
-    palSetPad(GPIOC, 1);
-    palClearPad(GPIOC, 0);
-    gfxSleepMilliseconds(1);
-    adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
-    val1 = ((samples[0] + samples[1])/2);
-
-    palClearPad(GPIOC, 1);
-    palSetPad(GPIOC, 0);
-    gfxSleepMilliseconds(1);
-    adcConvert(&ADCD1, &adc_y_config, samples, ADC_BUF_DEPTH);
-    val2 = ((samples[0] + samples[1])/2);
-    
-	return ((val1+((1<<12)-val2))/4);
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
diff --git a/drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_embest_dmstf4bb.h b/drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_embest_dmstf4bb.h
deleted file mode 100644
index 7246378d..00000000
--- a/drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_embest_dmstf4bb.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/ginput/touch/STMPE811/ginput_lld_mouse_board_embest_dmstf4bb.h
- * @brief   GINPUT Touch low level driver source for the STMPE811 on the Embest DM-STF4BB board.
- *
- * @defgroup Mouse Mouse
- * @ingroup GINPUT
- * @{
- */
-
-#ifndef _GINPUT_LLD_MOUSE_BOARD_H
-#define _GINPUT_LLD_MOUSE_BOARD_H
-
-static const I2CConfig i2ccfg = {
-	OPMODE_I2C,
-	400000,
-	FAST_DUTY_CYCLE_2,
-};
-
-/**
- * @brief   Initialise the board for the touch.
- *
- * @notapi
- */
-static void init_board(void)
-{
-	palSetPadMode(GPIOC, 13, PAL_MODE_INPUT | PAL_STM32_PUDR_FLOATING);			/* TP IRQ */
-	palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN);	/* SCL */
-	palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN);	/* SDA */
-
-	i2cStart(&I2CD1, &i2ccfg);
-}
-
-/**
- * @brief   Check whether an interrupt is raised
- * @return	TRUE if there is an interrupt signal present
- *
- * @notapi
- */
-static inline bool_t getpin_irq(void) {
-	return (!(palReadPad(GPIOC, 13)));
-}
-
-/**
- * @brief	Write a value into a certain register
- *
- * @param[in] reg	The register address
- * @param[in] n		The amount of bytes (one or two)
- * @param[in] val	The value
- *
- * @notapi
- */
-static void write_reg(uint8_t reg, uint8_t n, uint16_t val)
-{
-	uint8_t txbuf[3];
-
-	i2cAcquireBus(&I2CD1);
-
-	txbuf[0] = reg;
-
-	if (n == 1) {
-		txbuf[1] = val;
-		i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 2, NULL, 0, MS2ST(STMPE811_TIMEOUT));
-	} else if (n == 2) {
-		txbuf[1] = ((val & 0xFF00) >> 8);
-		txbuf[2] = (val & 0x00FF);
-		i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 3, NULL, 0, MS2ST(STMPE811_TIMEOUT));
-	}
-	
-	i2cReleaseBus(&I2CD1);
-}
- 
-/**
- * @brief	Read the value of a certain register
- *
- * @param[in] reg	The register address
- * @param[in] n		The amount of bytes (one or two)
- *
- * @return Data read from device (one byte or two depending on n param)
- *
- * @notapi
- */
-static uint16_t read_reg(uint8_t reg, uint8_t n)
-{
-	uint8_t txbuf[1], rxbuf[2];
-	uint16_t ret;
-
-	rxbuf[0] = 0;
-	rxbuf[1] = 0;
-
-	i2cAcquireBus(&I2CD1);
-
-	txbuf[0] = reg;
-	i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 1, rxbuf, n, MS2ST(STMPE811_TIMEOUT));
-
-	if (n == 1) {
-		ret = rxbuf[0];
-	} else if (n == 2) {
-		ret = ((rxbuf[0] << 8) | (rxbuf[1] & 0xFF));
-	}
-
-	i2cReleaseBus(&I2CD1);
-
-	return ret;
-}
-
-static void read_reg_n(uint8_t reg, uint8_t n, uint8_t *rxbuf)
-{
-	uint8_t txbuf[1];
-
-	i2cAcquireBus(&I2CD1);
-
-	txbuf[0] = reg;
-	i2cMasterTransmitTimeout(&I2CD1, STMPE811_ADDR, txbuf, 1, rxbuf, n, MS2ST(STMPE811_TIMEOUT));
-
-	i2cReleaseBus(&I2CD1);
-}
-
-#endif /* _GINPUT_LLD_MOUSE_BOARD_H */
-/** @} */
diff --git a/drivers/tdisp/HD44780/tdisp_lld.c b/drivers/tdisp/HD44780/tdisp_lld.c
index 2232955c..7b731c34 100644
--- a/drivers/tdisp/HD44780/tdisp_lld.c
+++ b/drivers/tdisp/HD44780/tdisp_lld.c
@@ -17,15 +17,7 @@
 
 #if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/
 
-/* check first if the user has defined his/her own lowlevel-board file */
-#if defined(TDISP_USE_CUSTOM_BOARD) && TDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "tdisp_lld_board.h"
-#elif defined(BOARD_OLIMEX_STM32_E407)
-	#include "tdisp_lld_board_olimex_e407.h"
-#elif defined(BOARD_ST_STM32F4_DISCOVERY)
-	#include "tdisp_lld_board_example.h"
-#endif
+#include "tdisp_lld_board.h"
 
 /* Controller Specific Properties */
 #define CUSTOM_CHAR_COUNT		8
diff --git a/drivers/tdisp/HD44780/tdisp_lld_board_olimex_e407.h b/drivers/tdisp/HD44780/tdisp_lld_board_olimex_e407.h
deleted file mode 100644
index 7eda4e38..00000000
--- a/drivers/tdisp/HD44780/tdisp_lld_board_olimex_e407.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld_board_olimex_e407.h
- * @brief   TDISP driver subsystem board interface for the HD44780 display
- *
- * @addtogroup TDISP
- * @{
- */
-
-#ifndef _TDISP_LLD_BOARD_H
-#define _TDISP_LLD_BOARD_H
-
-/* Configure these to match the hardware connections on your board */
-#define BUS_4BITS	FALSE
-#define PORT_DATA	GPIOG
-#define PORT_CTRL	GPIOE
-#define PIN_RS		0
-#define PIN_RW		1
-#define PIN_EN		2
-
-static void init_board(void) {
-	palSetGroupMode(PORT_CTRL, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetGroupMode(PORT_DATA, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	palClearPad(PORT_CTRL, PIN_RW);
-}
-
-static void writeToLCD(uint8_t data) {
-	palWritePort(PORT_DATA, data);
-	palSetPad(PORT_CTRL, PIN_EN);
-	gfxSleepMicroseconds(1);
-	palClearPad(PORT_CTRL, PIN_EN);
-	gfxSleepMicroseconds(5);
-}
-
-static void write_cmd(uint8_t data) {
-	palClearPad(PORT_CTRL, PIN_RS);
-	#if BUS_4BITS
-		writeToLCD(data>>4);
-	#endif
-	writeToLCD(data);
-}
-
-static void write_data(uint8_t data) {
-	palSetPad(PORT_CTRL, PIN_RS);
-	#if BUS_4BITS
-		writeToLCD(data>>4);
-	#endif
-	writeToLCD(data);
-}
-
-#endif /* _TDISP_LLD_BOARD_H */
-/** @} */
-
diff --git a/drivers/tdisp/HD44780/tdisp_lld_board_st_stm32f4_discovery.h b/drivers/tdisp/HD44780/tdisp_lld_board_st_stm32f4_discovery.h
deleted file mode 100644
index e9a7ae33..00000000
--- a/drivers/tdisp/HD44780/tdisp_lld_board_st_stm32f4_discovery.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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
- */
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld_board_st_stm32f4_discovery.h
- * @brief   TDISP driver subsystem board interface for the HD44780 display
- *
- * @addtogroup TDISP
- * @{
- */
-
-#ifndef _TDISP_LLD_BOARD_H
-#define _TDISP_LLD_BOARD_H
-
-/* Configure these to match the hardware connections on your board */
-#define BUS_4BITS	TRUE
-
-/* Configure the bitoffset in the dataport so they match with the
- * hardware pins. An offset of 0 means bit0 stays at bit0 of the dataport.
- * If the offset is set to 3, bit0 of the nibble will be positioned at
- * P[A..G]3 of the hardware-port.
- */
-#define hardware_offset	3
-
-/* The port where the data is sent to. In the
- * low-leveldriver het hardware_offset is taken
- * into account. If for example the hardware_offset
- * is set to 3, then de data will be sent to
- * PE3, PE4, PE5 en PE6, if the dataport where GPIOE.
- */
-#define PORT_DATA	GPIOE
-
-/* The port used to controle the controle lines of
- * the display.
- */
-#define PORT_CTRL	GPIOD
-/* Pin to controle the R/S-line of the display */
-#define PIN_RS		0
-/* Pin to controle the EN-line of the display */
-#define PIN_EN		1
-/* Pin to controle the R/W-pin of the display.
- * If reading of the display is not used disable
- * reading in the gfxconf.h and put a dummy value here
- * as it will not be used.
- */
-#define PIN_RW		7
-
-
-static void init_board(void) {
-	/* Initialize the ports for data and controle-lines */
-	palSetGroupMode(PORT_CTRL, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetGroupMode(PORT_DATA, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	/* Set alle controle pins to low */
-	palClearPad(PORT_CTRL, PIN_RS);
-	palClearPad(PORT_CTRL, PIN_EN);
-	#if TDISP_NEED_READ
-	  palClearPad(PORT_CTRL, PIN_RW);
-	#endif
-}
-
-/* This is the low-level routine for sending the bits
- * to the LCD-display. This routine shifts
- * the bits so they match the hardware port.
- */
-static void writeToLCD(uint8_t data) {
-	palWritePort(PORT_DATA, data<<hardware_offset);
-	palSetPad(PORT_CTRL, PIN_EN);
-	gfxSleepMicroseconds(1);
-	palClearPad(PORT_CTRL, PIN_EN);
-	/* wait a little while so that de display can process the data */
-	gfxSleepMicroseconds(5);
-}
-
-/* Writes a command to the display. The
- * RS-line is pulled low and than the
- * data is send.
- */
-static void write_cmd(uint8_t data) {
-	palClearPad(PORT_CTRL, PIN_RS);
-	#if BUS_4BITS
-		/* first send the high-nibble */
-		writeToLCD(data>>4);
-	#endif
-	/* send the low-nibble */
-	#if BUS_4BITS
-		/* in 4-bit mode the high-nibble is zeroed out */
-		writeToLCD(data & 0x0F);
-	#else
-		writeToLCD(data);
-	#endif
-}
-
-// static void write_initcmd(uint8_t data) {
-//   write_cmd(data);
-// }
-
-/* Write data to the display. The
- * RS-line is pulled high and than the
- * data is send.
- */
-static void write_data(uint8_t data) {
-	palSetPad(PORT_CTRL, PIN_RS);
-	#if BUS_4BITS
-		/* first send the high-nibble */
-		writeToLCD(data>>4);
-	#endif
-	/* send the low-nibble */
-	#if BUS_4BITS
-		/* in 4-bit mode the high-nibble is zeroed out */
-		writeToLCD(data & 0x0F);
-	#else
-		writeToLCD(data);
-	#endif
-}
-
-#endif /* _TDISP_LLD_BOARD_H */
-/** @} */
-
-- 
cgit v1.2.3


From ffee80299d616f1b634eacb514fcd7b3e4dc1a02 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 29 Oct 2013 01:12:03 +1000
Subject: ILI9341 driver fixes

---
 drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c | 33 +++++--------------------------
 drivers/gdisp/ILI9341/gdisp_lld_config.h  |  1 -
 2 files changed, 5 insertions(+), 29 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c b/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
index e5c4b7d0..33ca68d4 100644
--- a/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
+++ b/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
@@ -60,22 +60,6 @@
 #define delay(us)					gfxSleepMicroseconds(us)
 #define delayms(ms)					gfxSleepMilliseconds(ms)
 
-static inline void set_cursor(GDisplay *g) {
-	write_index(g, 0x2A);
-	write_data(g, (g->p.x >> 8));
-	write_data(g, (uint8_t) g->p.x);
-	write_data(g, (g->p.x) >> 8);
-	write_data(g, (uint8_t) (g->p.x));
-
-	write_index(g, 0x2B);
-	write_data(g, (g->p.y >> 8));
-	write_data(g, (uint8_t) g->p.y);
-	write_data(g, (g->p.y) >> 8);
-	write_data(g, (uint8_t) (g->p.y));
-
-	write_index(g, 0x2C);
-}
-
 static void set_viewport(GDisplay *g) {
 	write_index(g, 0x2A);
 	write_data(g, (g->p.x >> 8));
@@ -259,9 +243,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_start(GDisplay *g) {
 		acquire_bus(g);
 		set_viewport(g);
-		#if !GDISP_HARDWARE_STREAM_POS
-			set_cursor(g);
-		#endif
+		write_index(g, 0x2C);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
 		write_data16(g, g->p.color);
@@ -269,18 +251,13 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
 	}
-	#if GDISP_HARDWARE_STREAM_POS
-		LLDSPEC void gdisp_lld_write_pos(GDisplay *g) {
-			set_cursor(g);
-		}
-	#endif
 #endif
 
 #if GDISP_HARDWARE_STREAM_READ
 	LLDSPEC	void gdisp_lld_read_start(GDisplay *g) {
 		acquire_bus(g);
 		set_viewport(g);
-		set_cursor(g);
+		write_index(g, 0x2E);
 		setreadmode(g);
 		dummy_read(g);
 	}
@@ -331,21 +308,21 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				break;
 			case GDISP_ROTATE_90:
 				acquire_bus(g);
-				write_reg(g, 0x36, 0x20);	/* Invert X and Y axes */
+				write_reg(g, 0x36, 0xE8);	/* Invert X and Y axes */
 				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
 				break;
 			case GDISP_ROTATE_180:
 				acquire_bus(g);
-				write_reg(g, 0x36, 0x80);	/* X and Y axes non-inverted */
+				write_reg(g, 0x36, 0x88);		/* X and Y axes non-inverted */
 				release_bus(g);
 				g->g.Height = GDISP_SCREEN_HEIGHT;
 				g->g.Width = GDISP_SCREEN_WIDTH;
 				break;
 			case GDISP_ROTATE_270:
 				acquire_bus(g);
-				write_reg(g, 0x36, 0xE0);	/* Invert X and Y axes */
+				write_reg(g, 0x36, 0x28);	/* Invert X and Y axes */
 				release_bus(g);
 				g->g.Height = GDISP_SCREEN_WIDTH;
 				g->g.Width = GDISP_SCREEN_HEIGHT;
diff --git a/drivers/gdisp/ILI9341/gdisp_lld_config.h b/drivers/gdisp/ILI9341/gdisp_lld_config.h
index 8246934d..ba9c05bc 100644
--- a/drivers/gdisp/ILI9341/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9341/gdisp_lld_config.h
@@ -25,7 +25,6 @@
 
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 //#define GDISP_HARDWARE_STREAM_READ		TRUE
-//#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
-- 
cgit v1.2.3


From 9b9a57c2c9dfdcfd96c04960e10f89e2a621e808 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 29 Oct 2013 20:25:41 +1000
Subject: Better debugging for Win32 driver

---
 drivers/multiple/Win32/gdisp_lld_Win32.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c
index 7d7abb06..65baf903 100644
--- a/drivers/multiple/Win32/gdisp_lld_Win32.c
+++ b/drivers/multiple/Win32/gdisp_lld_Win32.c
@@ -487,9 +487,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 #if GDISP_HARDWARE_STREAM_WRITE || GDISP_HARDWARE_STREAM_READ
 	void BAD_PARAMETER(const char *msg) {
-		volatile int a;
-		// This is really just a point for us to set the debugger
-		a = 0;
+		fprintf(stderr, "%s\n", msg);
 	}
 #endif
 
-- 
cgit v1.2.3


From ece5bcd6ab566dc3bef092e6a0b5260ba771bc85 Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 5 Nov 2013 00:36:54 +1000
Subject: Auto-generate pixel formats using macro's. Prepare for (but not yet
 complete) supporting a different high level GDISP pixel format to the low
 level driver format. This will be useful in multiple display scenario's where
 displays have different pixel formats.

---
 drivers/gdisp/ED060SC4/gdisp_lld_config.h      | 2 +-
 drivers/gdisp/HX8347D/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/ILI9320/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/ILI9325/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/ILI9341/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/ILI9481/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h | 2 +-
 drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h  | 2 +-
 drivers/gdisp/RA8875/gdisp_lld_config.h        | 2 +-
 drivers/gdisp/S6D1121/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/SSD1289/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/SSD1306/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/SSD1963/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/SSD2119/gdisp_lld_config.h       | 2 +-
 drivers/gdisp/ST7565/gdisp_lld_config.h        | 2 +-
 drivers/gdisp/TestStub/gdisp_lld_config.h      | 2 +-
 drivers/multiple/Win32/gdisp_lld_config.h      | 6 +++---
 drivers/multiple/X/gdisp_lld_config.h          | 2 +-
 18 files changed, 20 insertions(+), 20 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_config.h b/drivers/gdisp/ED060SC4/gdisp_lld_config.h
index d7e836c9..47e84779 100644
--- a/drivers/gdisp/ED060SC4/gdisp_lld_config.h
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_config.h
@@ -17,7 +17,7 @@
 #define GDISP_HARDWARE_CLEARS           TRUE
 #define GDISP_HARDWARE_CONTROL          TRUE
 
-#define GDISP_PIXELFORMAT               GDISP_PIXELFORMAT_MONO
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_MONO
 
 #endif
 
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_config.h b/drivers/gdisp/HX8347D/gdisp_lld_config.h
index 48801f55..ab4c8639 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld_config.h
+++ b/drivers/gdisp/HX8347D/gdisp_lld_config.h
@@ -25,7 +25,7 @@
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_config.h b/drivers/gdisp/ILI9320/gdisp_lld_config.h
index 1a1f139f..5709de50 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 //#define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_config.h b/drivers/gdisp/ILI9325/gdisp_lld_config.h
index 8c586c78..c40bd2b7 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 #define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/ILI9341/gdisp_lld_config.h b/drivers/gdisp/ILI9341/gdisp_lld_config.h
index ba9c05bc..668a06c9 100644
--- a/drivers/gdisp/ILI9341/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9341/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 //#define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_config.h b/drivers/gdisp/ILI9481/gdisp_lld_config.h
index 4a33d110..3f3a4834 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld_config.h
+++ b/drivers/gdisp/ILI9481/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 #define GDISP_HARDWARE_STREAM_READ		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
index 73f505be..19a455d8 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_config.h
@@ -25,7 +25,7 @@
 #define GDISP_HARDWARE_CONTROL			TRUE
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB444
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
index 70a57d12..1476dbcf 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_config.h
@@ -41,7 +41,7 @@
 	#define GDISP_HARDWARE_STREAM_WRITE		TRUE
 #endif
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
+#define GDISP_LLD_PIXELFORMAT				GDISP_PIXELFORMAT_RGB444
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/RA8875/gdisp_lld_config.h b/drivers/gdisp/RA8875/gdisp_lld_config.h
index ae290245..55a07839 100644
--- a/drivers/gdisp/RA8875/gdisp_lld_config.h
+++ b/drivers/gdisp/RA8875/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 #define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_config.h b/drivers/gdisp/S6D1121/gdisp_lld_config.h
index 839bbf9d..79e859bc 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld_config.h
+++ b/drivers/gdisp/S6D1121/gdisp_lld_config.h
@@ -27,7 +27,7 @@
 #define GDISP_HARDWARE_STREAM_POS		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index 84e518d2..4cf5fa5c 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -32,7 +32,7 @@
 	#define GDISP_HARDWARE_BITFILLS		TRUE
 #endif
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_config.h b/drivers/gdisp/SSD1306/gdisp_lld_config.h
index 8580f933..627de17b 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1306/gdisp_lld_config.h
@@ -19,7 +19,7 @@
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_MONO
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_MONO
 
 // This controller supports a special gdispControl() to inverse the display.
 // Pass a parameter of 1 for inverse and 0 for normal.
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_config.h b/drivers/gdisp/SSD1963/gdisp_lld_config.h
index 054d72b8..8ad94738 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1963/gdisp_lld_config.h
@@ -25,7 +25,7 @@
 #define GDISP_HARDWARE_STREAM_WRITE		TRUE
 //#define GDISP_HARDWARE_CONTROL			TRUE			// Not Yet.
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_config.h b/drivers/gdisp/SSD2119/gdisp_lld_config.h
index 5d81057c..a974c623 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD2119/gdisp_lld_config.h
@@ -32,7 +32,7 @@
 	#define GDISP_HARDWARE_BITFILLS		TRUE
 #endif
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/ST7565/gdisp_lld_config.h b/drivers/gdisp/ST7565/gdisp_lld_config.h
index 632dc431..f774e8fa 100644
--- a/drivers/gdisp/ST7565/gdisp_lld_config.h
+++ b/drivers/gdisp/ST7565/gdisp_lld_config.h
@@ -19,7 +19,7 @@
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_MONO
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_MONO
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/gdisp/TestStub/gdisp_lld_config.h b/drivers/gdisp/TestStub/gdisp_lld_config.h
index adb6c8b4..63471c6c 100644
--- a/drivers/gdisp/TestStub/gdisp_lld_config.h
+++ b/drivers/gdisp/TestStub/gdisp_lld_config.h
@@ -25,7 +25,7 @@
 #define GDISP_HARDWARE_DRAWPIXEL		TRUE
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB565
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index e2fc3de4..4985bc43 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -21,10 +21,10 @@
 /*===========================================================================*/
 /* Driver hardware support.                                                  */
 /*===========================================================================*/
-
+
 // Calling gdispGFlush() is optional for this driver but can be used by the
 //	application to force a display update. eg after streaming.
-
+
 #define GDISP_HARDWARE_FLUSH			TRUE
 #define GDISP_HARDWARE_CONTROL			TRUE
 
@@ -45,7 +45,7 @@
 	#define GDISP_HARDWARE_SCROLL			TRUE
 #endif
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
+#define GDISP_LLD_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
 
 #endif	/* GFX_USE_GDISP */
 
diff --git a/drivers/multiple/X/gdisp_lld_config.h b/drivers/multiple/X/gdisp_lld_config.h
index b58a3d54..631ecf46 100644
--- a/drivers/multiple/X/gdisp_lld_config.h
+++ b/drivers/multiple/X/gdisp_lld_config.h
@@ -29,7 +29,7 @@
 #define GDISP_HARDWARE_PIXELREAD		TRUE
 #define GDISP_HARDWARE_CONTROL			FALSE
 
-#define GDISP_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
+#define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB888
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3


From e35b76388cdc32e275962a19932c64a2ce0ee52d Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 5 Nov 2013 13:43:28 +1000
Subject: Fix to streaming read pixel for Win32 driver in emulation mode.

---
 drivers/multiple/Win32/gdisp_lld_Win32.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'drivers')

diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c
index 65baf903..6cbf9cd4 100644
--- a/drivers/multiple/Win32/gdisp_lld_Win32.c
+++ b/drivers/multiple/Win32/gdisp_lld_Win32.c
@@ -641,20 +641,20 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		#if GDISP_NEED_CONTROL
 			switch(g->g.Orientation) {
 			case GDISP_ROTATE_0:
-				color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+				color = GetPixel(priv->dcBuffer, priv->x, priv->y);
 				break;
 			case GDISP_ROTATE_90:
-				color = GetPixel(priv->dcBuffer, g->p.y, g->g.Width - 1 - g->p.x);
+				color = GetPixel(priv->dcBuffer, priv->y, g->g.Width - 1 - priv->x);
 				break;
 			case GDISP_ROTATE_180:
-				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - g->p.x, g->g.Height - 1 - g->p.y);
+				color = GetPixel(priv->dcBuffer, g->g.Width - 1 - priv->x, g->g.Height - 1 - priv->y);
 				break;
 			case GDISP_ROTATE_270:
-				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - g->p.y, g->p.x);
+				color = GetPixel(priv->dcBuffer, g->g.Height - 1 - priv->y, priv->x);
 				break;
 			}
 		#else
-			color = GetPixel(priv->dcBuffer, g->p.x, g->p.y);
+			color = GetPixel(priv->dcBuffer, priv->x, priv->y);
 		#endif
 		ReleaseMutex(drawMutex);
 
-- 
cgit v1.2.3


From a8e860678df38fdb44f94cacae52e8d54f4374ff Mon Sep 17 00:00:00 2001
From: inmarket <andrewh@inmarket.com.au>
Date: Tue, 5 Nov 2013 19:34:12 +1000
Subject: New GDISP now supports multiple controllers with different pixel
 formats. You can now have a main color display and a secondary monochrome
 display. You can now optionally set GDISP_PIXELFORMAT to any color or
 grayscale format for your application and the driver will internally convert
 to the display hardware format.

---
 drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c        |  2 +-
 drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c          |  2 +-
 drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c          |  7 ++--
 drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c          |  7 ++--
 drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c          |  7 ++--
 drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c          |  7 ++--
 .../gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c  | 13 +++++---
 .../gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c    | 39 ++++++++++++++--------
 drivers/gdisp/RA8875/gdisp_lld_RA8875.c            |  2 +-
 drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c          |  7 ++--
 drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c          | 16 +++++++--
 drivers/gdisp/SSD1289/gdisp_lld_config.h           |  7 ++--
 drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c          |  2 +-
 drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c          |  2 +-
 drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c          | 16 +++++++--
 drivers/gdisp/SSD2119/gdisp_lld_config.h           |  5 ++-
 drivers/gdisp/ST7565/gdisp_lld_ST7565.c            |  2 +-
 drivers/multiple/Win32/gdisp_lld_Win32.c           | 29 ++++++++--------
 drivers/multiple/Win32/gdisp_lld_config.h          | 12 +++++--
 19 files changed, 123 insertions(+), 61 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c b/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
index 14e7f88a..3ab1de79 100644
--- a/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
+++ b/drivers/gdisp/ED060SC4/gdisp_lld_ED060SC4.c
@@ -524,7 +524,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		bitpos = (6 - 2 * (dx % EINK_PPB));
 		byte = block->data[dy][dx / EINK_PPB];
 		byte &= ~(PIXELMASK << bitpos);
-		if (g->p.color != Black)
+		if (COLOR2NATIVE(g->p.color) != Black)
 			byte |= PIXEL_WHITE << bitpos;
 		else
 			byte |= PIXEL_BLACK << bitpos;
diff --git a/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c b/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
index fecf115c..4514b495 100644
--- a/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
+++ b/drivers/gdisp/HX8347D/gdisp_lld_HX8347D.c
@@ -167,7 +167,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		busmode16(g);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_ram16(g, g->p.color);
+		write_ram16(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		busmode8(g);
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c b/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
index a18c2d82..e65e0a77 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld_ILI9320.c
@@ -204,7 +204,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		#endif
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
@@ -225,7 +225,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		dummy_read(g);
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		setwritemode(g);
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c b/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
index 75b4cd13..ffd67cf7 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld_ILI9325.c
@@ -200,7 +200,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		set_viewport(g);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
@@ -219,7 +219,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		dummy_read(g);
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		setwritemode(g);
diff --git a/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c b/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
index 33ca68d4..2513c48d 100644
--- a/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
+++ b/drivers/gdisp/ILI9341/gdisp_lld_ILI9341.c
@@ -246,7 +246,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		write_index(g, 0x2C);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data16(g, g->p.color);
+		write_data16(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
@@ -262,7 +262,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		dummy_read(g);
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		setwritemode(g);
diff --git a/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c b/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
index 49e28b23..2b2f0917 100644
--- a/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
+++ b/drivers/gdisp/ILI9481/gdisp_lld_ILI9481.c
@@ -211,7 +211,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		set_viewport(g);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
@@ -226,7 +226,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		dummy_read(g);
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		setwritemode(g);
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
index d1086c46..28a2fceb 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld_Nokia6610GE12.c
@@ -70,8 +70,8 @@
 /*===========================================================================*/
 
 // Use the priv pointer itself to save our color. This save allocating ram for it
-//	and works provided sizeof(color_t) <= sizeof(void *)
-#define savecolor(g)					(*(color_t *)&g->priv)
+//	and works provided sizeof(uint16_t) <= sizeof(void *)
+#define savecolor(g)					(*(uint16_t *)&g->priv)
 
 #define GDISP_FLG_ODDBYTE				(GDISP_FLG_DRIVER<<0)
 
@@ -143,14 +143,17 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		g->flags &= ~GDISP_FLG_ODDBYTE;
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		uint16_t	c;
+
+		c = COLOR2NATIVE(g->p.color);
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			// Write the pair of pixels to the display
 			write_data3(g, ((savecolor(g) >> 4) & 0xFF),
-					(((savecolor(g) << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
-					(g->p.color & 0xFF));
+					(((savecolor(g) << 4) & 0xF0)|((c >> 8) & 0x0F)),
+					(c & 0xFF));
 			g->flags &= ~GDISP_FLG_ODDBYTE;
 		} else {
-			savecolor(g) = g->p.color;
+			savecolor(g) = c;
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
index e0cfb997..f6ce4278 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld_Nokia6610GE8.c
@@ -111,9 +111,9 @@
 
 #if GDISP_HARDWARE_STREAM_WRITE
 	typedef struct dvrPriv {
-		color_t			savecolor;
+		uint16_t			savecolor;
 		#if GDISP_GE8_BROKEN_CONTROLLER
-			color_t		firstcolor;
+			uint16_t		firstcolor;
 		#endif
 	} dvrPriv;
 	#define PRIV		((dvrPriv *)g->priv)
@@ -231,20 +231,23 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		g->flags &= ~(GDISP_FLG_ODDBYTE|GDISP_FLG_RUNBYTE);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
+		uint16_t	c;
+
+		c = COLOR2NATIVE(g->p.color);
 		#if GDISP_GE8_BROKEN_CONTROLLER
 			if (!(g->flags & GDISP_FLG_RUNBYTE)) {
-				PRIV->firstcolor = g->p.color;
+				PRIV->firstcolor = c;
 				g->flags |= GDISP_FLG_RUNBYTE;
 			}
 		#endif
 		if ((g->flags & GDISP_FLG_ODDBYTE)) {
 			// Write the pair of pixels to the display
 			write_data3(g, ((PRIV->savecolor >> 4) & 0xFF),
-					(((PRIV->savecolor << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)),
-					(g->p.color & 0xFF));
+					(((PRIV->savecolor << 4) & 0xF0)|((c >> 8) & 0x0F)),
+					(c & 0xFF));
 			g->flags &= ~GDISP_FLG_ODDBYTE;
 		} else {
-			PRIV->savecolor = g->p.color;
+			PRIV->savecolor = c;
 			g->flags |= GDISP_FLG_ODDBYTE;
 		}
 	}
@@ -284,9 +287,12 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 #if GDISP_HARDWARE_DRAWPIXEL
 	LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
+		uint16_t	c;
+
+		c = COLOR2NATIVE(g->p.color);
 		acquire_bus(g);
 		set_viewport(g);
-		write_data3(g, 0, (g->p.color>>8) & 0x0F, g->p.color & 0xFF);
+		write_data3(g, 0, (c>>8) & 0x0F, c & 0xFF);
 		release_bus(g);
 	}
 #endif
@@ -295,15 +301,17 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 #if GDISP_HARDWARE_FILLS
 	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
-		unsigned tuples;
+		unsigned	tuples;
+		uint16_t	c;
 
 		tuples = (g->p.cx*g->p.cy+1)>>1;	// With an odd sized area we over-print by one pixel.
 											// This extra pixel overwrites the first pixel (harmless as it is the same colour)
 
+		c = COLOR2NATIVE(g->p.color);
 		acquire_bus(g);
 		set_viewport(g);
 		while(tuples--)
-			write_data3(g, ((g->p.color >> 4) & 0xFF), (((g->p.color << 4) & 0xF0)|((g->p.color >> 8) & 0x0F)), (g->p.color & 0xFF));
+			write_data3(g, ((c >> 4) & 0xFF), (((c << 4) & 0xF0)|((c >> 8) & 0x0F)), (c & 0xFF));
 		release_bus(g);
 	}
 #endif
@@ -311,7 +319,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 #if GDISP_HARDWARE_BITFILLS
 	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
 		coord_t			lg, x, y;
-		color_t			c1, c2;
+		uint16_t		c1, c2;
 		unsigned		tuples;
 		const pixel_t	*buffer;
 		#if GDISP_PACKED_PIXELS
@@ -328,7 +336,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		acquire_bus(g);
 		set_viewport(g);
 
-		/* to surpress compiler warnings */
+		/* to suppress compiler warnings */
 		x = 0;
 		y = 0;
 
@@ -356,7 +364,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 			while(tuples--) {
 				/* Get a pixel */
-				c1 = *p++;
+				c1 = COLOR2NATIVE(*p++);
 
 				/* Check for line or buffer wrapping */
 				if (++x >= g->p.cx) {
@@ -369,7 +377,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				}
 
 				/* Get the next pixel */
-				c2 = *p++;
+				c2 = COLOR2NATIVE(*p++);
 
 				/* Check for line or buffer wrapping */
 				if (++x >= g->p.cx) {
@@ -385,7 +393,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
 			}
 
-		#else
+		#elif GDISP_PIXELFORMAT == GDISP_LLD_PIXELFORMAT
 
 			// Although this controller uses packed pixels, we may have to feed it into
 			//  the controller with different packing to the source bitmap
@@ -440,6 +448,9 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 				/* Write the pair of pixels to the display */
 				write_data3(g, ((c1 >> 4) & 0xFF), (((c1 << 4) & 0xF0)|((c2 >> 8) & 0x0F)), (c2 & 0xFF));
 			}
+
+		#else
+			#error "Packed pixels is broken if you are not running native pixel format"
 		#endif
 
 		/* All done */
diff --git a/drivers/gdisp/RA8875/gdisp_lld_RA8875.c b/drivers/gdisp/RA8875/gdisp_lld_RA8875.c
index fb81c43a..d28670c6 100644
--- a/drivers/gdisp/RA8875/gdisp_lld_RA8875.c
+++ b/drivers/gdisp/RA8875/gdisp_lld_RA8875.c
@@ -184,7 +184,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		set_viewport(g);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
diff --git a/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c b/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
index cbaa7199..cca9d67e 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
+++ b/drivers/gdisp/S6D1121/gdisp_lld_S6D1121.c
@@ -221,7 +221,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		set_viewport(g);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
@@ -240,7 +240,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		dummy_read(g);
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		setwritemode(g);
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c b/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
index 6692e7d7..a33b6564 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld_SSD1289.c
@@ -200,7 +200,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		#endif
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
@@ -221,7 +221,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		dummy_read(g);
 	}
 	LLDSPEC	color_t gdisp_lld_read_color(GDisplay *g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		setwritemode(g);
@@ -231,15 +234,22 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 
 #if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
 	LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
+		uint16_t	c;
+
+		c = COLOR2NATIVE(g->p.color);
 		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);
-		dma_with_noinc(g, &color, g->p.cx*g->p.cy)
+		dma_with_noinc(g, &c, g->p.cx*g->p.cy)
 		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
+	#if GDISP_PIXELFORMAT != GDISP_LLD_PIXELFORMAT
+		#error "GDISP: SSD1289: BitBlit is only available in RGB565 pixel format"
+	#endif
+
 	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
 		pixel_t		*buffer;
 		coord_t		ycnt;
diff --git a/drivers/gdisp/SSD1289/gdisp_lld_config.h b/drivers/gdisp/SSD1289/gdisp_lld_config.h
index 4cf5fa5c..a9166553 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD1289/gdisp_lld_config.h
@@ -28,8 +28,11 @@
 #define GDISP_HARDWARE_CONTROL			TRUE
 
 #if defined(GDISP_USE_DMA)
-	#define GDISP_HARDWARE_FILLS		TRUE
-	#define GDISP_HARDWARE_BITFILLS		TRUE
+	#define GDISP_HARDWARE_FILLS		TRUE
+	#if !defined(GDISP_PIXELFORMAT) || GDISP_PIXELFORMAT == 0x2565
+		// Hardware BitBlts are only supported in native pixel format on this controller
+		#define GDISP_HARDWARE_BITFILLS		TRUE
+	#endif
 #endif
 
 #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
diff --git a/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c b/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
index bd3e386d..b72ba781 100644
--- a/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
+++ b/drivers/gdisp/SSD1306/gdisp_lld_SSD1306.c
@@ -176,7 +176,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			x = g->p.x;
 			break;
 		}
-		if (g->p.color != Black)
+		if (COLOR2NATIVE(g->p.color) != Black)
 			RAM(g)[xyaddr(x, y)] |= xybit(y);
 		else
 			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
diff --git a/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c b/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
index b94c1a40..eb1b9b15 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
+++ b/drivers/gdisp/SSD1963/gdisp_lld_SSD1963.c
@@ -188,7 +188,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		set_viewport(g);
 	}
 	LLDSPEC	void gdisp_lld_write_color(GDisplay *g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC	void gdisp_lld_write_stop(GDisplay *g) {
 		release_bus(g);
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c b/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
index df05fc2c..9594ff95 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
+++ b/drivers/gdisp/SSD2119/gdisp_lld_SSD2119.c
@@ -238,7 +238,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 		set_viewport(g);
 	}
 	LLDSPEC void gdisp_lld_write_color(GDisplay* g) {
-		write_data(g, g->p.color);
+		write_data(g, COLOR2NATIVE(g->p.color));
 	}
 	LLDSPEC void gdisp_lld_write_stop(GDisplay* g) {
 		release_bus(g);
@@ -257,7 +257,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 		dummy_read(g);
 	}
 	LLDSPEC color_t gdisp_lld_read_color(GDisplay* g) {
-		return read_data(g);
+		uint16_t	data;
+
+		data = read_data(g);
+		return NATIVE2COLOR(data);
 	}
 	LLDSPEC void gdisp_lld_read_stop(GDisplay* g) {
 		setwritemode(g);
@@ -267,15 +270,22 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay* g) {
 
 #if GDISP_HARDWARE_FILLS && defined(GDISP_USE_DMA)
 	LLDSPEC void gdisp_lld_fill_area(GDisplay* g) {
+		uint16_t	c;
+
+		c = COLOR2NATIVE(g->p.color);
 		acquire_bus(g);
 		set_viewport(g);
 		set_cursor(g);	
-		dma_with_noinc(g, &g->p.color, g->p.cx * g->p.cy);
+		dma_with_noinc(g, &c, g->p.cx * g->p.cy);
 		release_bus(g);
 	}
 #endif
 
 #if GDISP_HARDWARE_BITFILLS && defined(GDISP_USE_DMA)
+	#if GDISP_PIXELFORMAT != GDISP_LLD_PIXELFORMAT
+		#error "GDISP: SSD2119: BitBlit is only available in RGB565 pixel format"
+	#endif
+
 	LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
 		pixel_t*	buffer;
 		coord_t		ynct;
diff --git a/drivers/gdisp/SSD2119/gdisp_lld_config.h b/drivers/gdisp/SSD2119/gdisp_lld_config.h
index a974c623..ec034bef 100644
--- a/drivers/gdisp/SSD2119/gdisp_lld_config.h
+++ b/drivers/gdisp/SSD2119/gdisp_lld_config.h
@@ -29,7 +29,10 @@
 
 #if defined(GDISP_USE_DMA)
 	#define GDISP_HARDWARE_FILLS		TRUE
-	#define GDISP_HARDWARE_BITFILLS		TRUE
+	#if !defined(GDISP_PIXELFORMAT) || GDISP_PIXELFORMAT == 0x2565
+		// Hardware BitBlts are only supported in native pixel format on this controller
+		#define GDISP_HARDWARE_BITFILLS		TRUE
+	#endif
 #endif
 
 #define GDISP_LLD_PIXELFORMAT			GDISP_PIXELFORMAT_RGB565
diff --git a/drivers/gdisp/ST7565/gdisp_lld_ST7565.c b/drivers/gdisp/ST7565/gdisp_lld_ST7565.c
index bd8c7b74..2bb5406f 100644
--- a/drivers/gdisp/ST7565/gdisp_lld_ST7565.c
+++ b/drivers/gdisp/ST7565/gdisp_lld_ST7565.c
@@ -167,7 +167,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			y = g->p.x;
 			break;
 		}
-		if (g->p.color != Black)
+		if (COLOR2NATIVE(g->p.color) != Black)
 			RAM(g)[xyaddr(x, y)] |= xybit(y);
 		else
 			RAM(g)[xyaddr(x, y)] &= ~xybit(y);
diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c
index 6cbf9cd4..9484c823 100644
--- a/drivers/multiple/Win32/gdisp_lld_Win32.c
+++ b/drivers/multiple/Win32/gdisp_lld_Win32.c
@@ -23,9 +23,7 @@
 #ifndef GDISP_SCREEN_HEIGHT
 	#define GDISP_SCREEN_HEIGHT	480
 #endif
-#if GDISP_PIXELFORMAT != GDISP_PIXELFORMAT_RGB888
-	#error "GDISP Win32: This driver currently only supports the RGB888 pixel format."
-#endif
+
 // Setting this to TRUE delays updating the screen
 // to the windows paint routine. Due to the
 // drawing lock this does not add as much speed
@@ -89,9 +87,6 @@ static HANDLE			drawMutex;
 
 #define APP_NAME "uGFX"
 
-#define COLOR2BGR(c)	((((c) & 0xFF)<<16)|((c) & 0xFF00)|(((c)>>16) & 0xFF))
-#define BGR2COLOR(c)	COLOR2BGR(c)
-
 typedef struct winPriv {
 	HWND			hwnd;
 	HDC				dcBuffer;
@@ -291,9 +286,9 @@ static LRESULT myWindowProc(HWND hWnd,	UINT Msg, WPARAM wParam, LPARAM lParam)
 		// Paint the toggle area
 		#if GINPUT_NEED_TOGGLE
 			if (ps.rcPaint.bottom >= GDISP_SCREEN_HEIGHT && (g->flags & GDISP_FLG_HASTOGGLE)) {
-				pen = CreatePen(PS_SOLID, 1, COLOR2BGR(Black));
-				hbrOn = CreateSolidBrush(COLOR2BGR(Blue));
-				hbrOff = CreateSolidBrush(COLOR2BGR(Gray));
+				pen = CreatePen(PS_SOLID, 1, COLOR2NATIVE(Black));
+				hbrOn = CreateSolidBrush(COLOR2NATIVE(Blue));
+				hbrOff = CreateSolidBrush(COLOR2NATIVE(Gray));
 				old = SelectObject(dc, pen);
 				MoveToEx(dc, 0, GDISP_SCREEN_HEIGHT, &p);
 				LineTo(dc, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT);
@@ -519,7 +514,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		COLORREF	color;
 
 		priv = g->priv;
-		color = COLOR2BGR(g->p.color);
+		color = COLOR2NATIVE(g->p.color);
 
 		if (!(g->flags & GDISP_FLG_WSTREAM))
 			BAD_PARAMETER("write_color: not in streaming mode");
@@ -667,7 +662,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 			}
 		}
 
-		return BGR2COLOR(color);
+		return NATIVE2COLOR(color);
 	}
 	LLDSPEC	void gdisp_lld_read_stop(GDisplay *g) {
 		if (!(g->flags & GDISP_FLG_WSTREAM))
@@ -683,7 +678,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		COLORREF	color;
 	
 		priv = g->priv;
-		color = COLOR2BGR(g->p.color);
+		color = COLOR2NATIVE(g->p.color);
 	
 		#if GDISP_NEED_CONTROL
 			switch(g->g.Orientation) {
@@ -742,7 +737,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		COLORREF	color;
 
 		priv = g->priv;
-		color = COLOR2BGR(g->p.color);
+		color = COLOR2NATIVE(g->p.color);
 		hbr = CreateSolidBrush(color);
 
 		#if GDISP_NEED_CONTROL
@@ -841,6 +836,10 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 #endif
 	
 #if GDISP_HARDWARE_BITFILLS
+	#if COLOR_SYSTEM != GDISP_COLORSYSTEM_TRUECOLOR || COLOR_TYPE_BITS <= 8
+		#error "GDISP Win32: This driver's bitblit currently only supports true-color with bit depths > 8 bits."
+	#endif
+
 	LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
 		winPriv	*		priv;
 		pixel_t	*		buffer;
@@ -855,7 +854,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		memset(&bmpInfo, 0, sizeof(bmpInfo));
 		bmpInfo.bV4Size = sizeof(bmpInfo);
 		bmpInfo.bV4Planes = 1;
-		bmpInfo.bV4BitCount = sizeof(pixel_t)*8;
+		bmpInfo.bV4BitCount = COLOR_TYPE_BITS;
 		bmpInfo.bV4AlphaMask = 0;
 		bmpInfo.bV4RedMask		= RGB2COLOR(255,0,0);
 		bmpInfo.bV4GreenMask	= RGB2COLOR(0,255,0);
@@ -969,7 +968,7 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) {
 		#endif
 		ReleaseMutex(drawMutex);
 		
-		return BGR2COLOR(color);
+		return NATIVE2COLOR(color);
 	}
 #endif
 
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index 4985bc43..1554161b 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -41,11 +41,19 @@
 	#define GDISP_HARDWARE_DRAWPIXEL		TRUE
 	#define GDISP_HARDWARE_FILLS			TRUE
 	#define GDISP_HARDWARE_PIXELREAD		TRUE
-	#define GDISP_HARDWARE_BITFILLS			TRUE
 	#define GDISP_HARDWARE_SCROLL			TRUE
+
+	// Bit-blits on Win32 are currently only supported for True-Color bit-depths greater than 8 bits
+	// Note: At the time this file is included we have not calculated all our color
+	//			definitions so we need to do this by hand.
+	#if !defined(GDISP_PIXELFORMAT)
+		#define GDISP_HARDWARE_BITFILLS			TRUE
+	#elif (GDISP_PIXELFORMAT & 0x2000) && (((GDISP_PIXELFORMAT & 0x0F00)>>8)+((GDISP_PIXELFORMAT & 0x00F0)>>4)+((GDISP_PIXELFORMAT & 0x000F))) > 8
+		#define GDISP_HARDWARE_BITFILLS			TRUE
+	#endif
 #endif
 
-#define GDISP_LLD_PIXELFORMAT				GDISP_PIXELFORMAT_RGB888
+#define GDISP_LLD_PIXELFORMAT				GDISP_PIXELFORMAT_BGR888
 
 #endif	/* GFX_USE_GDISP */
 
-- 
cgit v1.2.3