From 1985906bea97a015d6e035ebb3f91b6e4f94aff1 Mon Sep 17 00:00:00 2001
From: Andrew Hannam <andrewh@inmarket.com.au>
Date: Sat, 19 Jan 2013 03:00:05 +1000
Subject: TDISP cleanup

Seperate High level and low level code better
Implement tdispControl
Cleanup
---
 drivers/tdisp/HD44780/tdisp_lld.c               | 317 ++++++++++++------------
 drivers/tdisp/HD44780/tdisp_lld_board_example.h | 112 ++++-----
 drivers/tdisp/HD44780/tdisp_lld_board_unknown.h |  71 ++++++
 drivers/tdisp/HD44780/tdisp_lld_config.h        |  45 ----
 4 files changed, 283 insertions(+), 262 deletions(-)
 create mode 100644 drivers/tdisp/HD44780/tdisp_lld_board_unknown.h
 delete mode 100644 drivers/tdisp/HD44780/tdisp_lld_config.h

(limited to 'drivers')

diff --git a/drivers/tdisp/HD44780/tdisp_lld.c b/drivers/tdisp/HD44780/tdisp_lld.c
index d0f4af0d..8a9c886f 100644
--- a/drivers/tdisp/HD44780/tdisp_lld.c
+++ b/drivers/tdisp/HD44780/tdisp_lld.c
@@ -1,153 +1,164 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld.c
- * @brief   TDISP driver subsystem low level driver source for the HD44780 display
- *
- * @addtogroup TDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/
-
-#include "tdisp_lld_board_example.h"
-
-static void _writeData(uint8_t data) {
-	write_bus(data);
-	
-	setpin_e(TRUE);
-	chThdSleepMicroseconds(1);
-	setpin_e(FALSE);
-	chThdSleepMicroseconds(5);
-}
-
-void tdisp_lld_write_cmd(uint8_t data) {
-	setpin_rs(FALSE);
-	setpin_rw(FALSE);
-
-	#if TDISP_NEED_4BIT_MODE
-	_writeData(data>>4);
-	#endif
-	_writeData(data);
-}
-
-void tdisp_lld_write_data(uint8_t data) {
-	setpin_rs(TRUE);
-	setpin_rw(FALSE);
-
-	#if TDISP_NEED_4BIT_MODE
-	_writeData(data>>4);
-	#endif
-	_writeData(data);
-}
-
-bool_t tdisp_lld_init(void) { 
-	/* initialise MCU hardware */
-	init_board();
-
-	/* wait some time */
-	chThdSleepMilliseconds(50);
-
-	tdisp_lld_write_cmd(0x38);
-	chThdSleepMilliseconds(64);
-
-	tdisp_lld_write_cmd(0x0f);	
-	chThdSleepMicroseconds(50);
-
-	tdisp_lld_write_cmd(0x01);
-	chThdSleepMilliseconds(5);
-
-	tdisp_lld_write_cmd(0x06);
-	chThdSleepMicroseconds(50);
-
-	return TRUE;
-}
-
-void tdisp_lld_set_cursor(coord_t col, coord_t row) {
-	uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
-
-	if(row >= TDISP_ROWS)
-		row = TDISP_ROWS - 1;
-
-	tdisp_lld_write_cmd(0x80 | (col + row_offsets[row]));
-}
-
-void tdisp_lld_create_char(uint8_t address, char *charmap) {
-	uint8_t i;
-
-	/* make sure we don't write somewhere we're not supposed to */
-	address &= TDISP_MAX_CUSTOM_CHARS;
-
-	tdisp_lld_write_cmd(0x40 | (address << 3));
-
-	for(i = 0; i < 8; i++) {
-		tdisp_lld_write_data(charmap[i]);
-	}
-}
-
-void tdisp_lld_clear(void) {
-	tdisp_lld_write_cmd(0x01);
-}
-
-void tdisp_lld_home(void) {
-	tdisp_lld_write_cmd(0x02);
-}
-
-void tdisp_lld_control(uint16_t what, void *value) {
-	(void)what;
-	(void)value;
-/*
-	switch(attributes) {
-		case TDISP_ON:
-			_displaycontrol |= 0x04;
-			tdisp_lld_write_cmd(0x08 | _displaycontrol);
-			break;
-		case TDISP_OFF:
-			_displaycontrol &=~ 0x04;
-			tdisp_lld_write_cmd(0x08 | _displaycontrol);
-			break;
-		case TDISP_CURSOR_ON:
-			_displaycontrol |= 0x02;
-			tdisp_lld_write_cmd(0x08 | _displaycontrol);
-			break;
-		case TDISP_CURSOR_OFF:
-			_displaycontrol &=~ 0x02;
-			tdisp_lld_write_cmd(0x08 | _displaycontrol);
-			break;
-		case TDISP_CURSOR_BLINK_ON:
-			_displaycontrol |= 0x00;
-			tdisp_lld_write_cmd(0x08 | _displaycontrol);
-			break;
-		case TDISP_CURSOR_BLINK_OFF:
-			_displaycontrol &=~ 0x00;
-			tdisp_lld_write_cmd(0x08 | _displaycontrol);
-			break;
-	}
-*/
-}
-
-#endif /* GFX_USE_TDISP */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/tdisp/HD44780/tdisp_lld.c
+ * @brief   TDISP driver subsystem low level driver source for the HD44780 display
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/
+
+/* The user may override the default display size */
+#ifndef TDISP_COLUMNS
+	#define TDISP_COLUMNS		16
+#endif
+#ifndef TDISP_ROWS
+	#define TDISP_ROWS			2
+#endif
+
+/* Controller Specific Properties */
+#define CUSTOM_CHAR_COUNT		8
+#define CUSTOM_CHAR_XBITS		5
+#define CUSTOM_CHAR_YBITS		8
+
+/* Define the properties of our controller */
+tdispStruct	TDISP = {
+		TDISP_COLUMNS, TDISP_ROWS,				/* cols, rows */
+		CUSTOM_CHAR_XBITS, CUSTOM_CHAR_YBITS,	/* charBitsX, charBitsY */
+		CUSTOM_CHAR_COUNT						/* maxCustomChars */
+		};
+
+/* Include the hardware interface details */
+#if defined(TDISP_USE_CUSTOM_BOARD) && TDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "tdisp_lld_board.h"
+#elif defined(BOARD_UNKNOWN)
+	#include "gdisp_lld_board_unknown.h"
+#else
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#endif
+
+/* Our display control */
+#define DISPLAY_ON		0x04
+#define CURSOR_ON		0x02
+#define CURSOR_BLINK	0x01
+
+static uint8_t	displaycontrol;
+
+
+bool_t tdisp_lld_init(void) { 
+	/* initialise hardware */
+	init_board();
+
+	/* wait some time */
+	chThdSleepMilliseconds(50);
+
+	write_cmd(0x38);
+	chThdSleepMilliseconds(64);
+
+	displaycontrol = DISPLAY_ON | CURSOR_ON | CURSOR_BLINK;		// The default displaycontrol
+	write_cmd(0x08 | displaycontrol);
+	chThdSleepMicroseconds(50);
+
+	write_cmd(0x01);					// Clear the screen
+	chThdSleepMilliseconds(5);
+
+	write_cmd(0x06);
+	chThdSleepMicroseconds(50);
+
+	return TRUE;
+}
+
+void tdisp_lld_clear(void) {
+	write_cmd(0x01);
+}
+
+void tdisp_lld_draw_char(char c) {
+	write_data(c);
+}
+
+void tdisp_lld_set_cursor(coord_t col, coord_t row) {
+	static const uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+
+	/*
+	 *  Short-cut:
+	 *
+	 *  If x and y = 0 then use the home command.
+	 *
+	 *  Note: There is probably no advantage as both commands are a single byte
+	 */
+//	if (col == 0 && row == 0) {
+//		write_cmd(0x02);
+//		return;
+//	}
+
+	write_cmd(0x80 | (col + row_offsets[row]));
+}
+
+void tdisp_lld_create_char(uint8_t address, uint8_t *charmap) {
+	int i;
+
+	write_cmd(0x40 | (address << 3));
+	for(i = 0; i < CUSTOM_CHAR_YBITS; i++)
+		write_data(charmap[i]);
+}
+
+void tdisp_lld_control(uint16_t what, void *value) {
+	switch(what) {
+		case TDISP_CTRL_BACKLIGHT:
+			if ((uint8_t)value)
+				displaycontrol |= DISPLAY_ON;
+			else
+				displaycontrol &= ~DISPLAY_ON;
+			write_cmd(0x08 | displaycontrol);
+			break;
+		case TDISP_CTRL_CURSOR:
+			switch((cursorshape)value) {
+			case cursorOff:
+				displaycontrol &= ~CURSOR_ON;
+				break;
+			case cursorBlock:
+			case cursorUnderline:
+			case cursorBar:
+				displaycontrol = (displaycontrol | CURSOR_ON) & ~CURSOR_BLINK;
+				break;
+			case cursorBlinkingBlock:
+			case cursorBlinkingUnderline:
+			case cursorBlinkingBar:
+			default:
+				displaycontrol |= (CURSOR_ON | CURSOR_BLINK);
+				break;
+			}
+			write_cmd(0x08 | displaycontrol);
+			break;
+	}
+}
+
+#endif /* GFX_USE_TDISP */
+/** @} */
+
diff --git a/drivers/tdisp/HD44780/tdisp_lld_board_example.h b/drivers/tdisp/HD44780/tdisp_lld_board_example.h
index 3f5c47d7..37463d37 100644
--- a/drivers/tdisp/HD44780/tdisp_lld_board_example.h
+++ b/drivers/tdisp/HD44780/tdisp_lld_board_example.h
@@ -1,64 +1,48 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld_board_example.h
- * @brief   TDISP driver subsystem board interface for the HD44780 display
- *
- * @addtogroup TDISP
- * @{
- */
-
-#ifndef _TDISP_LLD_BOARD_H
-#define _TDISP_LLD_BOARD_H
-
-void init_board(void) {
-	palSetGroupMode(GPIOE, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-	palSetGroupMode(GPIOG, PAL_WHOLE_PORT, 0, PAL_MODE_OUTPUT_PUSHPULL);
-}
-
-void setpin_e(bool_t state) {
-	if(state)
-		palSetPad(GPIOE, 2);
-	else
-		palClearPad(GPIOE, 2);
-}
-
-void setpin_rs(bool_t state) {
-	if(state)
-		palSetPad(GPIOE, 0);
-	else
-		palClearPad(GPIOE, 0);
-}
-
-void setpin_rw(bool_t state) {
-	if(state)
-		palSetPad(GPIOE, 1);
-	else
-		palClearPad(GPIOE, 1);
-}
-
-void write_bus(uint8_t data) {
-	palWritePort(GPIOG, data);
-}
-
-#endif /* _TDISP_LLD_BOARD_H */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/tdisp/HD44780/tdisp_lld_board_example.h
+ * @brief   TDISP driver subsystem board interface for the HD44780 display
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#ifndef _TDISP_LLD_BOARD_H
+#define _TDISP_LLD_BOARD_H
+
+static void init_board(void) {
+	/* Code here */
+	#error "tdispHD44780: You must supply a definition for init_board for your board"
+}
+
+static void write_cmd(uint8_t data) {
+	/* Code here */
+	#error "tdispHD44780: You must supply a definition for write_cmd for your board"
+}
+
+static void write_data(uint8_t data) {
+	/* Code here */
+	#error "tdispHD44780: You must supply a definition for write_data for your board"
+}
+
+#endif /* _TDISP_LLD_BOARD_H */
+/** @} */
diff --git a/drivers/tdisp/HD44780/tdisp_lld_board_unknown.h b/drivers/tdisp/HD44780/tdisp_lld_board_unknown.h
new file mode 100644
index 00000000..381dc52b
--- /dev/null
+++ b/drivers/tdisp/HD44780/tdisp_lld_board_unknown.h
@@ -0,0 +1,71 @@
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/tdisp/HD44780/tdisp_lld_board_unknown.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);
+	chThdSleepMicroseconds(1);
+	palClearPad(PORT_CTRL, PIN_EN);
+	chThdSleepMicroseconds(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_config.h b/drivers/tdisp/HD44780/tdisp_lld_config.h
deleted file mode 100644
index 3b37cd70..00000000
--- a/drivers/tdisp/HD44780/tdisp_lld_config.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld_config.h
- * @brief   TDISP Driver subsystem low level driver header for the HD44780 display.
- *
- * @addtogroup TDISP
- * @{
- */
-
-#ifndef _TDISP_LLD_CONFIG_H
-#define _TDISP_LLD_CONFIG_H
-
-#if GFX_USE_TDISP
-
-/*===========================================================================*/
-/* Driver hardware support.                                                  */
-/*===========================================================================*/
-
-#define TDISP_DRIVER_NAME				"HD44780"
-
-#define TDISP_MAX_CUSTOM_CHARS			0x07
-
-#endif	/* GFX_USE_TDISP */
-
-#endif	/* _TDISP_LLD_CONFIG_H */
-/** @} */
-- 
cgit v1.2.3


From 9329b22086c4b3dde58de9e598808f04c20d6f49 Mon Sep 17 00:00:00 2001
From: Andrew Hannam <andrewh@inmarket.com.au>
Date: Mon, 18 Feb 2013 17:29:08 +1000
Subject: Fix compile error in GDISP

Fix compile error with wrongly named include file
Revert lld_gdisp naming convention to gdisp_lld to fix problem and be
consitant with all other low level drivers.
---
 drivers/gdisp/ILI9320/gdisp_lld.c                  | 1140 +++++------
 drivers/gdisp/ILI9320/gdisp_lld_board_example.h    |  118 +-
 .../ILI9320/gdisp_lld_board_olimex_stm32_lcd.h     |  170 +-
 drivers/gdisp/ILI9325/gdisp_lld.c                  | 1160 +++++------
 drivers/gdisp/ILI9325/gdisp_lld_board_example.h    |  118 +-
 .../gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h  |  192 +-
 drivers/gdisp/Nokia6610GE12/gdisp_lld.c            | 1056 +++++-----
 drivers/gdisp/Nokia6610GE8/gdisp_lld.c             |  966 ++++-----
 drivers/gdisp/S6D1121/gdisp_lld.c                  | 1142 +++++------
 drivers/gdisp/SSD1289/gdisp_lld.c                  | 1166 +++++------
 drivers/gdisp/SSD1963/gdisp_lld.c                  | 1226 ++++++------
 drivers/gdisp/TestStub/gdisp_lld.c                 |  266 +--
 drivers/multiple/Win32/gdisp_lld.c                 | 2052 ++++++++++----------
 13 files changed, 5386 insertions(+), 5386 deletions(-)

(limited to 'drivers')

diff --git a/drivers/gdisp/ILI9320/gdisp_lld.c b/drivers/gdisp/ILI9320/gdisp_lld.c
index 6a324cd4..d8c5be86 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld.c
+++ b/drivers/gdisp/ILI9320/gdisp_lld.c
@@ -1,570 +1,570 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9320 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#elif defined(BOARD_OLIMEX_STM32_LCD)
-	#include "gdisp_lld_board_olimex_stm32_lcd.h"
-#else
-	#include "gdisp_lld_board.h"
-#endif
-
-/*===========================================================================*/
-/* 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."
-	#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_SCREEN_WIDTH		240
-#define GDISP_SCREEN_HEIGHT		320
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-uint32_t DISPLAY_CODE;
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-static __inline void lld_lcdDelay(uint16_t us) {
-    chThdSleepMicroseconds(us);
-}
-
-static __inline void lld_lcdWriteIndex(uint16_t index) {
-	lld_gdisp_write_index(index);
-}
-
-static __inline void lld_lcdWriteData(uint16_t data) {
-	lld_gdisp_write_data(data);
-}
-
-static __inline void lld_lcdWriteReg(uint16_t lcdReg, uint16_t lcdRegValue) {
-	lld_gdisp_write_index(lcdReg);
-	lld_gdisp_write_data(lcdRegValue);
-}
-
-static __inline uint16_t lld_lcdReadData(void) {
-	/* fix this! */
-	//return lld_gdisp_read_data;
-	return GDISP_RAM;
-}
-
-static __inline uint16_t lld_lcdReadReg(uint16_t lcdReg) {
-    volatile uint16_t dummy;
-
-    lld_gdisp_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) {
-
-}
-
-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;
-
-	for(i = 0; i < size; i++)
-		buffer[i] = lld_lcdReadData();
-}
-
-bool_t lld_gdisp_init(void) {
-	/* Initialise your display */
-	lld_gdisp_init_board();
-
-	/* Hardware reset */
-	lld_gdisp_reset_pin(TRUE);
-	lld_lcdDelay(1000);
-	lld_gdisp_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
-	switch (DISPLAY_CODE) {   
-		case 0x9320:
-        	lld_lcdWriteReg(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
-			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
-
-	// Turn on the backlight
-	lld_gdisp_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
-
-	return TRUE;
-}
-
-static void lld_lcdSetCursor(uint16_t x, uint16_t y) {
-    uint32_t addr;
-
-    addr = y * 0x100 + x;
-
-	switch(GDISP.Orientation) {
-		case GDISP_ROTATE_0:
-    		lld_lcdWriteReg(0x0020, addr & 0xff);   /* low addr */
-    		lld_lcdWriteReg(0x0021, (addr >> 8) & 0x1ff); /* high addr */
-			break;
-
-		case GDISP_ROTATE_90:
-            lld_lcdWriteReg(0x0020, (addr >> 8) & 0x1ff);   /* low addr */
-            lld_lcdWriteReg(0x0021, addr & 0xff); /* high addr */
-			break;
-
-		case GDISP_ROTATE_180:
-			break;
-
-		case GDISP_ROTATE_270:
-			break;
-	}
-}
-
-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:
-			break;
-
-		case GDISP_ROTATE_270:
-			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 lld_gdisp_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 lld_gdisp_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();
-	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	void lld_gdisp_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();
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	void lld_gdisp_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();
-	}
-#endif
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	color_t lld_gdisp_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;
-	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	void lld_gdisp_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();
-	}
-#endif
-
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	void lld_gdisp_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:
-						lld_lcdWriteReg(0x0007, 0x0000);
-						lld_lcdWriteReg(0x0010, 0x0000);
-						lld_lcdWriteReg(0x0011, 0x0000);
-						lld_lcdWriteReg(0x0012, 0x0000);
-						lld_lcdWriteReg(0x0013, 0x0000);
-						lld_gdisp_backlight(0);
-						break;
-			
-					case powerOn:
-						//*************Power On sequence ******************//
-						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 */	
-						lld_gdisp_backlight(GDISP.Backlight);
-						if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
-							lld_gdisp_init();
-						break;
-	
-					case powerSleep:
-	             		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 */				
-						lld_gdisp_backlight(0);
-						break;
-
-					case powerDeepSleep:
-					    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 */
-						lld_gdisp_backlight(0);
-						break;
-
-					default:
-						return;
-				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
-				return;
-
-			case GDISP_CONTROL_ORIENTATION:
-				if(GDISP.Orientation == (gdisp_orientation_t)value)
-					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_90:
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-			
-					case GDISP_ROTATE_180:
-						/* ToDo */
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-		
-					case GDISP_ROTATE_270:
-						/* ToDo */
-						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;
-				lld_gdisp_backlight((unsigned)value);
-				GDISP.Backlight = (unsigned)value;
-				break;
-			
-			default:
-				return;
-		}
-	}
-
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/ILI9320/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9320 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_STM32_LCD)
+	#include "gdisp_lld_board_olimex_stm32_lcd.h"
+#else
+	#include "gdisp_lld_board.h"
+#endif
+
+/*===========================================================================*/
+/* 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."
+	#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_SCREEN_WIDTH		240
+#define GDISP_SCREEN_HEIGHT		320
+
+#define GDISP_INITIAL_CONTRAST	50
+#define GDISP_INITIAL_BACKLIGHT	100
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+uint32_t DISPLAY_CODE;
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+static __inline void lld_lcdDelay(uint16_t us) {
+    chThdSleepMicroseconds(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) {
+	/* fix this! */
+	//return gdisp_lld_read_data;
+	return GDISP_RAM;
+}
+
+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) {
+
+}
+
+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;
+
+	for(i = 0; i < size; i++)
+		buffer[i] = lld_lcdReadData();
+}
+
+bool_t gdisp_lld_init(void) {
+	/* Initialise your display */
+	gdisp_lld_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
+	switch (DISPLAY_CODE) {   
+		case 0x9320:
+        	lld_lcdWriteReg(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
+			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
+
+	// Turn on the backlight
+	gdisp_lld_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
+
+	return TRUE;
+}
+
+static void lld_lcdSetCursor(uint16_t x, uint16_t y) {
+    uint32_t addr;
+
+    addr = y * 0x100 + x;
+
+	switch(GDISP.Orientation) {
+		case GDISP_ROTATE_0:
+    		lld_lcdWriteReg(0x0020, addr & 0xff);   /* low addr */
+    		lld_lcdWriteReg(0x0021, (addr >> 8) & 0x1ff); /* high addr */
+			break;
+
+		case GDISP_ROTATE_90:
+            lld_lcdWriteReg(0x0020, (addr >> 8) & 0x1ff);   /* low addr */
+            lld_lcdWriteReg(0x0021, addr & 0xff); /* high addr */
+			break;
+
+		case GDISP_ROTATE_180:
+			break;
+
+		case GDISP_ROTATE_270:
+			break;
+	}
+}
+
+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:
+			break;
+
+		case GDISP_ROTATE_270:
+			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();
+	}
+#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();
+	}
+#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();
+	}
+#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;
+	}
+#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();
+	}
+#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:
+						lld_lcdWriteReg(0x0007, 0x0000);
+						lld_lcdWriteReg(0x0010, 0x0000);
+						lld_lcdWriteReg(0x0011, 0x0000);
+						lld_lcdWriteReg(0x0012, 0x0000);
+						lld_lcdWriteReg(0x0013, 0x0000);
+						gdisp_lld_backlight(0);
+						break;
+			
+					case powerOn:
+						//*************Power On sequence ******************//
+						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 */	
+						gdisp_lld_backlight(GDISP.Backlight);
+						if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
+							gdisp_lld_init();
+						break;
+	
+					case powerSleep:
+	             		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 */				
+						gdisp_lld_backlight(0);
+						break;
+
+					case powerDeepSleep:
+					    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 */
+						gdisp_lld_backlight(0);
+						break;
+
+					default:
+						return;
+				}
+				GDISP.Powermode = (gdisp_powermode_t)value;
+				return;
+
+			case GDISP_CONTROL_ORIENTATION:
+				if(GDISP.Orientation == (gdisp_orientation_t)value)
+					return;
+				switch((gdisp_orientation_t)value) {
+					case GDISP_ROTATE_0:
+						lld_lcdWriteReg(0x0001, 0x0100);
+						lld_lcdWriteReg(0x0003, 0x1038);
+						GDISP.Height = GDISP_SCREEN_HEIGHT;
+						GDISP.Width = GDISP_SCREEN_WIDTH;
+						break;
+
+					case GDISP_ROTATE_90:
+						lld_lcdWriteReg(0x0001, 0x0000);
+						lld_lcdWriteReg(0x0003, 0x1030);
+						GDISP.Height = GDISP_SCREEN_WIDTH;
+						GDISP.Width = GDISP_SCREEN_HEIGHT;
+						break;
+			
+					case GDISP_ROTATE_180:
+						/* ToDo */
+						GDISP.Height = GDISP_SCREEN_HEIGHT;
+						GDISP.Width = GDISP_SCREEN_WIDTH;
+						break;
+		
+					case GDISP_ROTATE_270:
+						/* ToDo */
+						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;
+			
+			default:
+				return;
+		}
+	}
+
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9320/gdisp_lld_board_example.h b/drivers/gdisp/ILI9320/gdisp_lld_board_example.h
index f07b34c6..0f4def57 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_example.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_example.h
@@ -1,59 +1,59 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/ILI9320/gdisp_lld_board_example.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 lld_gdisp_init_board(void) {
-	#error "ILI9320: You must implement the init_board routine for your board"
-}
-
-static __inline void lld_gdisp_reset_pin(bool_t state) {
-	#error "ILI9320: You must implement setpin_reset routine for your board"
-}
-
-static __inline void lld_gdisp_write_index(uint16_t data) {
-	#error "ILI9320: You must implement write_index routine for your board"
-}
-
-static __inline void lld_gdisp_write_data(uint16_t data) {
-	#error "ILI9320: You must implement write_data routine for your board"
-}
-
-static __inline uint16_t lld_gdisp_read_data(void) {
-	#error "ILI9320: You must implement read_data routine for your board"
-}
-
-/* if not available, just ignore the argument and return */
-static __inline uint16_t lld_gdisp_backlight(uint8_t percentage) {
-	#error "ILI9320: You must implement set_backlight routine for your board"
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/ILI9320/gdisp_lld_board_example.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 gdisp_lld_init_board(void) {
+	#error "ILI9320: You must implement the init_board routine for your board"
+}
+
+static __inline void gdisp_lld_reset_pin(bool_t state) {
+	#error "ILI9320: You must implement setpin_reset routine for your board"
+}
+
+static __inline void gdisp_lld_write_index(uint16_t data) {
+	#error "ILI9320: You must implement write_index routine for your board"
+}
+
+static __inline void gdisp_lld_write_data(uint16_t data) {
+	#error "ILI9320: You must implement write_data routine for your board"
+}
+
+static __inline uint16_t gdisp_lld_read_data(void) {
+	#error "ILI9320: You must implement read_data routine for your board"
+}
+
+/* if not available, just ignore the argument and return */
+static __inline uint16_t gdisp_lld_backlight(uint8_t percentage) {
+	#error "ILI9320: You must implement set_backlight routine for your board"
+}
+
+#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 d2d54ce9..2bdf367a 100644
--- a/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
+++ b/drivers/gdisp/ILI9320/gdisp_lld_board_olimex_stm32_lcd.h
@@ -1,85 +1,85 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @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 lld_gdisp_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 lld_gdisp_reset_pin(bool_t state) {
-	if(state)
-		palClearPad(GPIOE, GPIOE_TFT_RST);
-	else
-		palSetPad(GPIOE, GPIOE_TFT_RST);
-}
-
-static __inline void lld_gdisp_write_index(uint16_t reg) {
-	GDISP_REG = reg;
-}
-
-static __inline void lld_gdisp_write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-static __inline uint16_t lld_gdisp_read_data(void) {
-	return GDISP_RAM;
-}
-
-static __inline void lld_gdisp_backlight(uint8_t percent) {
-	if(percent == 100)
-		palClearPad(GPIOD, GPIOD_TFT_LIGHT);
-	else
-		palSetPad(GPIOD, GPIOD_TFT_LIGHT);
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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 gdisp_lld_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 gdisp_lld_reset_pin(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) {
+	GDISP_REG = reg;
+}
+
+static __inline void gdisp_lld_write_data(uint16_t data) {
+	GDISP_RAM = data;
+}
+
+static __inline uint16_t gdisp_lld_read_data(void) {
+	return GDISP_RAM;
+}
+
+static __inline void gdisp_lld_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/ILI9325/gdisp_lld.c b/drivers/gdisp/ILI9325/gdisp_lld.c
index e9500cc5..187c54c6 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld.c
+++ b/drivers/gdisp/ILI9325/gdisp_lld.c
@@ -1,580 +1,580 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/ILI9325/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9325 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#elif defined(BOARD_HY_STM32_100P)
-	#include "gdisp_lld_board_hy_stm32_100p.h"
-#else
-	#include "gdisp_lld_board.h"
-#endif
-
-/*===========================================================================*/
-/* 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."
-	#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_SCREEN_WIDTH		240
-#define GDISP_SCREEN_HEIGHT		320
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-uint32_t DISPLAY_CODE;
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-static __inline void lld_lcdDelay(uint16_t us) {
-    chThdSleepMicroseconds(us);
-}
-
-static __inline void lld_lcdWriteIndex(uint16_t index) {
-	lld_gdisp_write_index(index);
-}
-
-static __inline void lld_lcdWriteData(uint16_t data) {
-	lld_gdisp_write_data(data);
-}
-
-static __inline void lld_lcdWriteReg(uint16_t lcdReg, uint16_t lcdRegValue) {
-	lld_gdisp_write_index(lcdReg);
-	lld_gdisp_write_data(lcdRegValue);
-}
-
-static __inline uint16_t lld_lcdReadData(void) {
-	/* fix this! */
-	//return lld_gdisp_read_data;
-	return GDISP_RAM;
-}
-
-static __inline uint16_t lld_lcdReadReg(uint16_t lcdReg) {
-    volatile uint16_t dummy;
-
-    lld_gdisp_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) {
-
-}
-
-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;
-
-	for(i = 0; i < size; i++)
-		buffer[i] = lld_lcdReadData();
-}
-
-bool_t lld_gdisp_init(void) {
-	/* Initialise your display */
-	lld_gdisp_init_board();
-
-	/* Hardware reset */
-	lld_gdisp_reset_pin(TRUE);
-	lld_lcdDelay(1000);
-	lld_gdisp_reset_pin(FALSE);
-	lld_lcdDelay(1000);
-
-	// 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);
-
-	//################# 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);
-
-	//################## 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);
-
-	// chinese code ends here
-
-	// Turn on the backlight
-	lld_gdisp_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
-
-	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;
-	}
-}
-
-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 lld_gdisp_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 lld_gdisp_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();
-	}
-#endif
-
-#if GDISP_HARDWARE_FILLS || defined(__DOXYGEN__)
-	void lld_gdisp_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();
-	}
-#endif
-
-#if GDISP_HARDWARE_BITFILLS || defined(__DOXYGEN__)
-	void lld_gdisp_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();
-	}
-#endif
-
-#if (GDISP_NEED_PIXELREAD && GDISP_HARDWARE_PIXELREAD) || defined(__DOXYGEN__)
-	color_t lld_gdisp_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;
-	}
-#endif
-
-#if (GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL) || defined(__DOXYGEN__)
-	void lld_gdisp_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();
-	}
-#endif
-
-#if (GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL) || defined(__DOXYGEN__)
-	void lld_gdisp_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:
-						lld_lcdWriteReg(0x0007, 0x0000);
-						lld_lcdWriteReg(0x0010, 0x0000);
-						lld_lcdWriteReg(0x0011, 0x0000);
-						lld_lcdWriteReg(0x0012, 0x0000);
-						lld_lcdWriteReg(0x0013, 0x0000);
-						lld_gdisp_backlight(0);
-						break;
-			
-					case powerOn:
-						//*************Power On sequence ******************//
-						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 */	
-						lld_gdisp_backlight(GDISP.Backlight);
-						if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
-							lld_gdisp_init();
-						break;
-	
-					case powerSleep:
-	             		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 */				
-						lld_gdisp_backlight(0);
-						break;
-
-					case powerDeepSleep:
-					    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 */
-						lld_gdisp_backlight(0);
-						break;
-
-					default:
-						return;
-				}
-				GDISP.Powermode = (gdisp_powermode_t)value;
-				return;
-
-			case GDISP_CONTROL_ORIENTATION:
-				if(GDISP.Orientation == (gdisp_orientation_t)value)
-					return;
-				switch((gdisp_orientation_t)value) {
-					case GDISP_ROTATE_0:
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-
-					case GDISP_ROTATE_90:
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						lld_lcdWriteReg(0x0060, 0x2700);
-						GDISP.Height = GDISP_SCREEN_WIDTH;
-						GDISP.Width = GDISP_SCREEN_HEIGHT;
-						break;
-			
-					case GDISP_ROTATE_180:
-						lld_lcdWriteReg(0x0001, 0x0000);
-						lld_lcdWriteReg(0x0003, 0x1038);
-						lld_lcdWriteReg(0x0060, 0xa700);
-						GDISP.Height = GDISP_SCREEN_HEIGHT;
-						GDISP.Width = GDISP_SCREEN_WIDTH;
-						break;
-		
-					case GDISP_ROTATE_270:
-						lld_lcdWriteReg(0x0001, 0x0100);
-						lld_lcdWriteReg(0x0003, 0x1030);
-						lld_lcdWriteReg(0x0060, 0xA700);
-						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;
-				lld_gdisp_backlight((unsigned)value);
-				GDISP.Backlight = (unsigned)value;
-				break;
-			
-			default:
-				return;
-		}
-	}
-
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/ILI9325/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#elif defined(BOARD_HY_STM32_100P)
+	#include "gdisp_lld_board_hy_stm32_100p.h"
+#else
+	#include "gdisp_lld_board.h"
+#endif
+
+/*===========================================================================*/
+/* 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."
+	#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_SCREEN_WIDTH		240
+#define GDISP_SCREEN_HEIGHT		320
+
+#define GDISP_INITIAL_CONTRAST	50
+#define GDISP_INITIAL_BACKLIGHT	100
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+uint32_t DISPLAY_CODE;
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+static __inline void lld_lcdDelay(uint16_t us) {
+    chThdSleepMicroseconds(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) {
+	/* fix this! */
+	//return gdisp_lld_read_data;
+	return GDISP_RAM;
+}
+
+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) {
+
+}
+
+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;
+
+	for(i = 0; i < size; i++)
+		buffer[i] = lld_lcdReadData();
+}
+
+bool_t gdisp_lld_init(void) {
+	/* Initialise your display */
+	gdisp_lld_init_board();
+
+	/* Hardware reset */
+	gdisp_lld_reset_pin(TRUE);
+	lld_lcdDelay(1000);
+	gdisp_lld_reset_pin(FALSE);
+	lld_lcdDelay(1000);
+
+	// 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);
+
+	//################# 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);
+
+	//################## 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);
+
+	// chinese code ends here
+
+	// Turn on the backlight
+	gdisp_lld_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
+
+	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;
+	}
+}
+
+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();
+	}
+#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();
+	}
+#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();
+	}
+#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;
+	}
+#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();
+	}
+#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:
+						lld_lcdWriteReg(0x0007, 0x0000);
+						lld_lcdWriteReg(0x0010, 0x0000);
+						lld_lcdWriteReg(0x0011, 0x0000);
+						lld_lcdWriteReg(0x0012, 0x0000);
+						lld_lcdWriteReg(0x0013, 0x0000);
+						gdisp_lld_backlight(0);
+						break;
+			
+					case powerOn:
+						//*************Power On sequence ******************//
+						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 */	
+						gdisp_lld_backlight(GDISP.Backlight);
+						if(GDISP.Powermode != powerSleep || GDISP.Powermode != powerDeepSleep)
+							gdisp_lld_init();
+						break;
+	
+					case powerSleep:
+	             		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 */				
+						gdisp_lld_backlight(0);
+						break;
+
+					case powerDeepSleep:
+					    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 */
+						gdisp_lld_backlight(0);
+						break;
+
+					default:
+						return;
+				}
+				GDISP.Powermode = (gdisp_powermode_t)value;
+				return;
+
+			case GDISP_CONTROL_ORIENTATION:
+				if(GDISP.Orientation == (gdisp_orientation_t)value)
+					return;
+				switch((gdisp_orientation_t)value) {
+					case GDISP_ROTATE_0:
+						lld_lcdWriteReg(0x0001, 0x0100);
+						lld_lcdWriteReg(0x0003, 0x1038);
+						lld_lcdWriteReg(0x0060, 0x2700);
+						GDISP.Height = GDISP_SCREEN_HEIGHT;
+						GDISP.Width = GDISP_SCREEN_WIDTH;
+						break;
+
+					case GDISP_ROTATE_90:
+						lld_lcdWriteReg(0x0001, 0x0000);
+						lld_lcdWriteReg(0x0003, 0x1030);
+						lld_lcdWriteReg(0x0060, 0x2700);
+						GDISP.Height = GDISP_SCREEN_WIDTH;
+						GDISP.Width = GDISP_SCREEN_HEIGHT;
+						break;
+			
+					case GDISP_ROTATE_180:
+						lld_lcdWriteReg(0x0001, 0x0000);
+						lld_lcdWriteReg(0x0003, 0x1038);
+						lld_lcdWriteReg(0x0060, 0xa700);
+						GDISP.Height = GDISP_SCREEN_HEIGHT;
+						GDISP.Width = GDISP_SCREEN_WIDTH;
+						break;
+		
+					case GDISP_ROTATE_270:
+						lld_lcdWriteReg(0x0001, 0x0100);
+						lld_lcdWriteReg(0x0003, 0x1030);
+						lld_lcdWriteReg(0x0060, 0xA700);
+						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;
+			
+			default:
+				return;
+		}
+	}
+
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/ILI9325/gdisp_lld_board_example.h b/drivers/gdisp/ILI9325/gdisp_lld_board_example.h
index 547952ee..80adf6ab 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_board_example.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_board_example.h
@@ -1,59 +1,59 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/ILI9325/gdisp_lld_board_example.h
- * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#ifndef GDISP_LLD_BOARD_H
-#define GDISP_LLD_BOARD_H
-
-static __inline void lld_gdisp_init_board(void) {
-	#error "ILI9325: You must implement the init_board routine for your board"
-}
-
-static __inline void lld_gdisp_reset_pin(bool_t state) {
-	#error "ILI9325: You must implement setpin_reset routine for your board"
-}
-
-static __inline void lld_gdisp_write_index(uint16_t data) {
-	#error "ILI9325: You must implement write_index routine for your board"
-}
-
-static __inline void lld_gdisp_write_data(uint16_t data) {
-	#error "ILI9325: You must implement write_data routine for your board"
-}
-
-static __inline uint16_t lld_gdisp_read_data(void) {
-	#error "ILI9325: You must implement read_data routine for your board"
-}
-
-/* if not available, just ignore the argument and return */
-static __inline uint16_t lld_gdisp_backlight(uint8_t percentage) {
-	#error "ILI9325: You must implement set_backlight routine for your board"
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/ILI9325/gdisp_lld_board_example.h
+ * @brief   GDISP Graphic Driver subsystem board interface for the ILI9325 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#ifndef GDISP_LLD_BOARD_H
+#define GDISP_LLD_BOARD_H
+
+static __inline void gdisp_lld_init_board(void) {
+	#error "ILI9325: You must implement the init_board routine for your board"
+}
+
+static __inline void gdisp_lld_reset_pin(bool_t state) {
+	#error "ILI9325: You must implement setpin_reset routine for your board"
+}
+
+static __inline void gdisp_lld_write_index(uint16_t data) {
+	#error "ILI9325: You must implement write_index routine for your board"
+}
+
+static __inline void gdisp_lld_write_data(uint16_t data) {
+	#error "ILI9325: You must implement write_data routine for your board"
+}
+
+static __inline uint16_t gdisp_lld_read_data(void) {
+	#error "ILI9325: You must implement read_data routine for your board"
+}
+
+/* if not available, just ignore the argument and return */
+static __inline uint16_t gdisp_lld_backlight(uint8_t percentage) {
+	#error "ILI9325: You must implement set_backlight routine for your board"
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
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 94d418b0..a9e61dcb 100644
--- a/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
+++ b/drivers/gdisp/ILI9325/gdisp_lld_board_hy_stm32_100p.h
@@ -1,96 +1,96 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/*
-	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 lld_gdisp_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 lld_gdisp_reset_pin(bool_t state) {
-	if(state)
-		palClearPad(GPIOE, GPIOE_TFT_RST);
-	else
-		palSetPad(GPIOE, GPIOE_TFT_RST);
-}
-
-static __inline void lld_gdisp_write_index(uint16_t reg) {
-	GDISP_REG = reg;
-}
-
-static __inline void lld_gdisp_write_data(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-static __inline uint16_t lld_gdisp_read_data(void) {
-	return GDISP_RAM;
-}
-
-static __inline void lld_gdisp_backlight(uint8_t percent) {
-	percent=percent;	// avoid a warning
-}
-
-#endif /* GDISP_LLD_BOARD_H */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+	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 gdisp_lld_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 gdisp_lld_reset_pin(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) {
+	GDISP_REG = reg;
+}
+
+static __inline void gdisp_lld_write_data(uint16_t data) {
+	GDISP_RAM = data;
+}
+
+static __inline uint16_t gdisp_lld_read_data(void) {
+	return GDISP_RAM;
+}
+
+static __inline void gdisp_lld_backlight(uint8_t percent) {
+	percent=percent;	// avoid a warning
+}
+
+#endif /* GDISP_LLD_BOARD_H */
+/** @} */
+
diff --git a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
index 6ce7b581..ee9a5fc7 100644
--- a/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE12/gdisp_lld.c
@@ -1,528 +1,528 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE12 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-/*===========================================================================*/
-/* 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
-#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_SCREEN_HEIGHT		132
-#define GDISP_SCREEN_WIDTH		132
-
-#define GDISP_INITIAL_CONTRAST	38
-#define GDISP_INITIAL_BACKLIGHT	100
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#elif defined(BOARD_OLIMEX_SAM7_EX256)
-	#include "gdisp_lld_board_olimexsam7ex256.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#endif
-
-// Some macros just to make reading the code easier
-#define delayms(ms)					chThdSleepMilliseconds(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); }
-
-// 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 lld_gdisp_init(void) {
-	/* Initialise your display */
-	init_board();
-
-	// Hardware reset
-	setpin_reset(TRUE);
-	delayms(20);
-	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
-	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
-	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 lld_gdisp_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 lld_gdisp_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.
-
-		acquire_bus();
-		setviewport(x, y, cx, cy);
-		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 lld_gdisp_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();
-	}
-#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 lld_gdisp_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.
-		 */
-	}
-#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 lld_gdisp_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.
-		 */
-	}
-#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 lld_gdisp_control(unsigned what, void *value) {
-		/* 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_CONTRAST			- supported
-		 */
-		switch(what) {
-#if 0
-		// NOT IMPLEMENTED YET
-		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
-				return;
-			switch((gdisp_powermode_t)value) {
-				case powerOff:
-					// 	Code here
-					break;
-				case powerOn:
-					// 	Code here
-					/* You may need this ---
-					 *	if (GDISP.Powermode != powerSleep)
-					 *		lld_gdisp_init();
-					 */
-					break;
-				case powerSleep:
-					/* 	Code here */
-					break;
-				default:
-					return;
-			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
-			return;
-#endif
-#if 0
-		// NOT IMPLEMENTED YET
-		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
-				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;
-			return;
-#endif
-		case GDISP_CONTROL_BACKLIGHT:
-			if ((unsigned)value > 100) value = (void *)100;
-			set_backlight((unsigned)value);
-			GDISP.Backlight = (unsigned)value;
-			return;
-		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)value > 100) value = (void *)100;
-			acquire_bus();
-			write_cmd1(CONTRAST,(unsigned)value);
-			release_bus();
-			GDISP.Contrast = (unsigned)value;
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE12/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE12 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+/*===========================================================================*/
+/* 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
+#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_SCREEN_HEIGHT		132
+#define GDISP_SCREEN_WIDTH		132
+
+#define GDISP_INITIAL_CONTRAST	38
+#define GDISP_INITIAL_BACKLIGHT	100
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_SAM7_EX256)
+	#include "gdisp_lld_board_olimexsam7ex256.h"
+#else
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#endif
+
+// Some macros just to make reading the code easier
+#define delayms(ms)					chThdSleepMilliseconds(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); }
+
+// 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) {
+	/* Initialise your display */
+	init_board();
+
+	// Hardware reset
+	setpin_reset(TRUE);
+	delayms(20);
+	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
+	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
+	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.
+
+		acquire_bus();
+		setviewport(x, y, cx, cy);
+		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();
+	}
+#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.
+		 */
+	}
+#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.
+		 */
+	}
+#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) {
+		/* 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_CONTRAST			- supported
+		 */
+		switch(what) {
+#if 0
+		// NOT IMPLEMENTED YET
+		case GDISP_CONTROL_POWER:
+			if (GDISP.Powermode == (gdisp_powermode_t)value)
+				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;
+			return;
+#endif
+#if 0
+		// NOT IMPLEMENTED YET
+		case GDISP_CONTROL_ORIENTATION:
+			if (GDISP.Orientation == (gdisp_orientation_t)value)
+				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;
+			return;
+#endif
+		case GDISP_CONTROL_BACKLIGHT:
+			if ((unsigned)value > 100) value = (void *)100;
+			set_backlight((unsigned)value);
+			GDISP.Backlight = (unsigned)value;
+			return;
+		case GDISP_CONTROL_CONTRAST:
+			if ((unsigned)value > 100) value = (void *)100;
+			acquire_bus();
+			write_cmd1(CONTRAST,(unsigned)value);
+			release_bus();
+			GDISP.Contrast = (unsigned)value;
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
index 006c964b..079900aa 100644
--- a/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+++ b/drivers/gdisp/Nokia6610GE8/gdisp_lld.c
@@ -1,483 +1,483 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE8 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#include "GE8.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
-#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_SCREEN_HEIGHT		132
-#define GDISP_SCREEN_WIDTH		132
-
-#define GDISP_INITIAL_CONTRAST	38
-#define GDISP_INITIAL_BACKLIGHT	100
-
-/*===========================================================================*/
-/* Driver exported variables.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local variables.                                                   */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#elif defined(BOARD_OLIMEX_SAM7_EX256)
-	#include "gdisp_lld_board_olimexsam7ex256.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#endif
-
-// Some macros just to make reading the code easier
-#define delayms(ms)					chThdSleepMilliseconds(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); }
-
-// 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 lld_gdisp_init(void) {
-	/* Initialise your display */
-	init_board();
-
-	// Hardware reset
-	setpin_reset(TRUE);
-	delayms(20);
-	setpin_reset(FALSE);
-	delayms(20);
-
-	// Get the bus for the following initialisation commands
-	acquire_bus();
-	
-	write_cmd3(DISCTL, 0x00, 0x20, 0x00);				// Display control
-															// P1: 0x00 = 2 divisions, switching period=8 (default)
-															// P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
-															// P3: 0x00 = no inversely highlighted lines
-	write_cmd1(COMSCN, 0x01);							// COM scan		P1: 0x01 = Scan 1->80, 160<-81
-	write_cmd(OSCON);									// Internal oscilator 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, 0x48, 0x00, 0x02);				// Data control
-															// P1: 0x01 = page address inverted, column address normal, address scan in column direction
-															// P2: 0x00 = RGB sequence (default value)
-															// P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A)
-	write_cmd2(VOLCTR, GDISP_INITIAL_CONTRAST, 0x03);	// Voltage control (contrast setting)
-															// P1 = Contrast
-															// P2 = 3 resistance ratio (only value that works)
-	delayms(100);						// allow power supply to stabilize
-	write_cmd(DISON);									// Turn on the display
-
-	// Release the bus
-	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
-	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 lld_gdisp_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 lld_gdisp_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.
-
-		acquire_bus();
-		setviewport(x, y, cx, cy);
-		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 lld_gdisp_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();
-	}
-#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 lld_gdisp_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.
-		 */
-	}
-#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 lld_gdisp_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.
-		 */
-	}
-#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 lld_gdisp_control(unsigned what, void *value) {
-		/* 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_CONTRAST			- supported
-		 */
-		switch(what) {
-#if 0
-		// NOT IMPLEMENTED YET
-		case GDISP_CONTROL_POWER:
-			if (GDISP.Powermode == (gdisp_powermode_t)value)
-				return;
-			switch((gdisp_powermode_t)value) {
-				case powerOff:
-					// 	Code here
-					break;
-				case powerOn:
-					// 	Code here
-					/* You may need this ---
-					 *	if (GDISP.Powermode != powerSleep)
-					 *		lld_gdisp_init();
-					 */
-					break;
-				case powerSleep:
-					/* 	Code here */
-					break;
-				default:
-					return;
-			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
-			return;
-#endif
-#if 0
-		// NOT IMPLEMENTED YET
-		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
-				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;
-			return;
-#endif
-		case GDISP_CONTROL_BACKLIGHT:
-			if ((unsigned)value > 100) value = (void *)100;
-			set_backlight((unsigned)value);
-			GDISP.Backlight = (unsigned)value;
-			return;
-		case GDISP_CONTROL_CONTRAST:
-			if ((unsigned)value > 100) value = (void *)100;
-			acquire_bus();
-			write_cmd2(VOLCTR, (unsigned)value, 0x03);
-			release_bus();
-			GDISP.Contrast = (unsigned)value;
-			return;
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/Nokia6610GE8/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the Nokia6610 GE8 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#include "GE8.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
+#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_SCREEN_HEIGHT		132
+#define GDISP_SCREEN_WIDTH		132
+
+#define GDISP_INITIAL_CONTRAST	38
+#define GDISP_INITIAL_BACKLIGHT	100
+
+/*===========================================================================*/
+/* Driver exported variables.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local variables.                                                   */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_SAM7_EX256)
+	#include "gdisp_lld_board_olimexsam7ex256.h"
+#else
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#endif
+
+// Some macros just to make reading the code easier
+#define delayms(ms)					chThdSleepMilliseconds(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); }
+
+// 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) {
+	/* Initialise your display */
+	init_board();
+
+	// Hardware reset
+	setpin_reset(TRUE);
+	delayms(20);
+	setpin_reset(FALSE);
+	delayms(20);
+
+	// Get the bus for the following initialisation commands
+	acquire_bus();
+	
+	write_cmd3(DISCTL, 0x00, 0x20, 0x00);				// Display control
+															// P1: 0x00 = 2 divisions, switching period=8 (default)
+															// P2: 0x20 = nlines/4 - 1 = 132/4 - 1 = 32)
+															// P3: 0x00 = no inversely highlighted lines
+	write_cmd1(COMSCN, 0x01);							// COM scan		P1: 0x01 = Scan 1->80, 160<-81
+	write_cmd(OSCON);									// Internal oscilator 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, 0x48, 0x00, 0x02);				// Data control
+															// P1: 0x01 = page address inverted, column address normal, address scan in column direction
+															// P2: 0x00 = RGB sequence (default value)
+															// P3: 0x02 = Grayscale -> 16 (selects 12-bit color, type A)
+	write_cmd2(VOLCTR, GDISP_INITIAL_CONTRAST, 0x03);	// Voltage control (contrast setting)
+															// P1 = Contrast
+															// P2 = 3 resistance ratio (only value that works)
+	delayms(100);						// allow power supply to stabilize
+	write_cmd(DISON);									// Turn on the display
+
+	// Release the bus
+	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
+	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.
+
+		acquire_bus();
+		setviewport(x, y, cx, cy);
+		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();
+	}
+#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.
+		 */
+	}
+#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.
+		 */
+	}
+#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) {
+		/* 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_CONTRAST			- supported
+		 */
+		switch(what) {
+#if 0
+		// NOT IMPLEMENTED YET
+		case GDISP_CONTROL_POWER:
+			if (GDISP.Powermode == (gdisp_powermode_t)value)
+				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;
+			return;
+#endif
+#if 0
+		// NOT IMPLEMENTED YET
+		case GDISP_CONTROL_ORIENTATION:
+			if (GDISP.Orientation == (gdisp_orientation_t)value)
+				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;
+			return;
+#endif
+		case GDISP_CONTROL_BACKLIGHT:
+			if ((unsigned)value > 100) value = (void *)100;
+			set_backlight((unsigned)value);
+			GDISP.Backlight = (unsigned)value;
+			return;
+		case GDISP_CONTROL_CONTRAST:
+			if ((unsigned)value > 100) value = (void *)100;
+			acquire_bus();
+			write_cmd2(VOLCTR, (unsigned)value, 0x03);
+			release_bus();
+			GDISP.Contrast = (unsigned)value;
+			return;
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/S6D1121/gdisp_lld.c b/drivers/gdisp/S6D1121/gdisp_lld.c
index 863e5e46..c4523999 100644
--- a/drivers/gdisp/S6D1121/gdisp_lld.c
+++ b/drivers/gdisp/S6D1121/gdisp_lld.c
@@ -1,571 +1,571 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/S6D1121/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the S6d1121 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-/*===========================================================================*/
-/* 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
-#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_SCREEN_HEIGHT		320
-#define GDISP_SCREEN_WIDTH		240
-
-#define GDISP_INITIAL_CONTRAST 		50
-#define GDISP_INITIAL_BACKLIGHT 	100
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#elif defined(BOARD_OLIMEX_STM32_E407)
-	#include "gdisp_lld_board_olimex_e407.h"
-#else
-	#include "gdisp_lld_board.h"
-#endif
-
-/* 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)                   chThdSleepMicroseconds(us)
-#define delayms(ms)                 chThdSleepMilliseconds(ms)
-
-static __inline void set_cursor(coord_t x, coord_t y) {
-    /* R20h - 8 bit
-     * R21h - 9 bit
-     */
-    switch(GDISP.Orientation) {
-        case GDISP_ROTATE_0:
-            write_reg(0x0020, x & 0x00FF);
-            write_reg(0x0021, 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);
-            break;
-        case GDISP_ROTATE_180:
-            write_reg(0x0020, (GDISP_SCREEN_WIDTH - 1 - x) & 0x00FF);
-            write_reg(0x0021, (GDISP_SCREEN_HEIGHT - 1 - 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);
-            break;
-    } 
-}
-
-static __inline void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-    /* HSA / HEA are 8 bit
-     * VSA / VEA are 9 bit
-     * use masks 0x00FF and 0x01FF to enforce this
-     */
-
-    switch(GDISP.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);
-            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);
-            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);
-            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);
-            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 lld_gdisp_init(void) {
-	/* initialize the hardware */
-	init_board();
-
-	/* Hardware reset */
-	setpin_reset(TRUE);
-	delayms(20);
-	setpin_reset(TRUE);
-	delayms(20);
-
-	/* Get the bus for the following initialisation commands */
-	acquire_bus();
-
-	write_reg(0x11,0x2004);
-	write_reg(0x13,0xCC00);
-	write_reg(0x15,0x2600);
-	write_reg(0x14,0x252A);
-	write_reg(0x12,0x0033);
-	write_reg(0x13,0xCC04);
-
-	delayms(1);
-
-	write_reg(0x13,0xCC06);
-
-	delayms(1);
-
-	write_reg(0x13,0xCC4F);
-
-	delayms(1);
-
-	write_reg(0x13,0x674F);
-	write_reg(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);
-
-	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);
-
-	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;
-}
-
-/**
- * @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 lld_gdisp_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 ---- */
-
-#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 lld_gdisp_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 lld_gdisp_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();
-		reset_viewport();
-		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 lld_gdisp_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();
-		reset_viewport();
-		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 start of the text
-	 *
-	 * @notapi
-	 */
-	color_t lld_gdisp_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;
-	}
-#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 lld_gdisp_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();
-	}
-#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 lld_gdisp_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:
-					/* 	Code here */
-					/* break; */
-				case powerOn:
-					/* 	Code here */
-					/* You may need this ---
-						if (GDISP.Powermode != powerSleep)
-							lld_gdisp_init();
-					*/
-					/* break; */
-				case powerSleep:
-					/* 	Code here */
-					/* break; */
-				default:
-					return;
-			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
-			return;
-		case GDISP_CONTROL_ORIENTATION:
-			if (GDISP.Orientation == (gdisp_orientation_t)value)
-				return;
-			switch((gdisp_orientation_t)value) {
-			case GDISP_ROTATE_0:
-				write_reg(0x0001,0x0127);
-				write_reg(0x03, 0b0011);
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				write_reg(0x0001,0x0027);
-				write_reg(0x0003, 0b1011);
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				write_reg(0x0001,0x0127);
-				write_reg(0x0003, 0b0000);
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				write_reg(0x0001,0x0027);
-				write_reg(0x0003, 0b1000);
-				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:
-		case GDISP_CONTROL_CONTRAST:
-*/
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/S6D1121/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the S6d1121 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+/*===========================================================================*/
+/* 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
+#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_SCREEN_HEIGHT		320
+#define GDISP_SCREEN_WIDTH		240
+
+#define GDISP_INITIAL_CONTRAST 		50
+#define GDISP_INITIAL_BACKLIGHT 	100
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#elif defined(BOARD_OLIMEX_STM32_E407)
+	#include "gdisp_lld_board_olimex_e407.h"
+#else
+	#include "gdisp_lld_board.h"
+#endif
+
+/* 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)                   chThdSleepMicroseconds(us)
+#define delayms(ms)                 chThdSleepMilliseconds(ms)
+
+static __inline void set_cursor(coord_t x, coord_t y) {
+    /* R20h - 8 bit
+     * R21h - 9 bit
+     */
+    switch(GDISP.Orientation) {
+        case GDISP_ROTATE_0:
+            write_reg(0x0020, x & 0x00FF);
+            write_reg(0x0021, 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);
+            break;
+        case GDISP_ROTATE_180:
+            write_reg(0x0020, (GDISP_SCREEN_WIDTH - 1 - x) & 0x00FF);
+            write_reg(0x0021, (GDISP_SCREEN_HEIGHT - 1 - 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);
+            break;
+    } 
+}
+
+static __inline void set_viewport(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+    /* HSA / HEA are 8 bit
+     * VSA / VEA are 9 bit
+     * use masks 0x00FF and 0x01FF to enforce this
+     */
+
+    switch(GDISP.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);
+            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);
+            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);
+            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);
+            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) {
+	/* initialize the hardware */
+	init_board();
+
+	/* Hardware reset */
+	setpin_reset(TRUE);
+	delayms(20);
+	setpin_reset(TRUE);
+	delayms(20);
+
+	/* Get the bus for the following initialisation commands */
+	acquire_bus();
+
+	write_reg(0x11,0x2004);
+	write_reg(0x13,0xCC00);
+	write_reg(0x15,0x2600);
+	write_reg(0x14,0x252A);
+	write_reg(0x12,0x0033);
+	write_reg(0x13,0xCC04);
+
+	delayms(1);
+
+	write_reg(0x13,0xCC06);
+
+	delayms(1);
+
+	write_reg(0x13,0xCC4F);
+
+	delayms(1);
+
+	write_reg(0x13,0x674F);
+	write_reg(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);
+
+	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);
+
+	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;
+}
+
+/**
+ * @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 ---- */
+
+#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
+
+		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
+
+#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();
+		reset_viewport();
+		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 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;
+	}
+#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();
+	}
+#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) {
+				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;
+			return;
+		case GDISP_CONTROL_ORIENTATION:
+			if (GDISP.Orientation == (gdisp_orientation_t)value)
+				return;
+			switch((gdisp_orientation_t)value) {
+			case GDISP_ROTATE_0:
+				write_reg(0x0001,0x0127);
+				write_reg(0x03, 0b0011);
+				GDISP.Height = GDISP_SCREEN_HEIGHT;
+				GDISP.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				write_reg(0x0001,0x0027);
+				write_reg(0x0003, 0b1011);
+				GDISP.Height = GDISP_SCREEN_WIDTH;
+				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				write_reg(0x0001,0x0127);
+				write_reg(0x0003, 0b0000);
+				GDISP.Height = GDISP_SCREEN_HEIGHT;
+				GDISP.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				write_reg(0x0001,0x0027);
+				write_reg(0x0003, 0b1000);
+				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:
+		case GDISP_CONTROL_CONTRAST:
+*/
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
+
diff --git a/drivers/gdisp/SSD1289/gdisp_lld.c b/drivers/gdisp/SSD1289/gdisp_lld.c
index 96fb94e6..de6edfe8 100644
--- a/drivers/gdisp/SSD1289/gdisp_lld.c
+++ b/drivers/gdisp/SSD1289/gdisp_lld.c
@@ -1,583 +1,583 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/SSD1289/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-/*===========================================================================*/
-/* Driver local definitions.                                                 */
-/*===========================================================================*/
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-
-#define GDISP_INITIAL_CONTRAST	50
-#define GDISP_INITIAL_BACKLIGHT	100
-
-/*===========================================================================*/
-/* Driver local functions.                                                   */
-/*===========================================================================*/
-
-#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#elif defined(BOARD_FIREBULL_STM32_F103)
-	#include "gdisp_lld_board_firebullstm32f103.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#endif
-
-// 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)					chThdSleepMicroseconds(us)
-#define delayms(ms)					chThdSleepMilliseconds(ms)
-
-static __inline void set_cursor(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(GDISP.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(coord_t x, coord_t y, coord_t cx, coord_t cy) {
-
-	set_cursor(x, y);
-
-	/* 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
-	 */
-
-	switch(GDISP.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, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
-			write_reg(0x45, x & 0x01FF);
-			write_reg(0x46, (x+cx-1) & 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);
-			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);
-			break;
-	}
-
-	set_cursor(x, y);
-}
-
-static __inline void reset_viewport(void) {
-	set_viewport(0, 0, GDISP.Width, GDISP.Height);
-}
-
-/*===========================================================================*/
-/* 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 lld_gdisp_init(void) {
-	/* Initialise your display */
-	init_board();
-
-	// Hardware reset
-	setpin_reset(TRUE);
-	delayms(20);
-	setpin_reset(FALSE);
-	delayms(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);
-
- 	// Release the bus
-	release_bus();
-	
-	/* 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
-	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 lld_gdisp_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 lld_gdisp_clear(color_t color) {
-		unsigned i;
-
-		acquire_bus();
-		reset_viewport();
-		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 lld_gdisp_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();
-	}
-#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 lld_gdisp_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();
-		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 lld_gdisp_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 lld_gdisp_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 (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; j < cx; j++)
-					buf[j] = read_data();
-				stream_stop();
-
-				set_viewport(x, row1, cx, 1);
-				stream_start();
-				for (j = 0; j < cx; j++)
-					write_data(buf[j]);
-				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();
-		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 lld_gdisp_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(0x0010, 0x0000);	// leave sleep mode
-				write_reg(0x0007, 0x0000);	// halt operation
-				write_reg(0x0000, 0x0000);	// turn off oszillator
-				write_reg(0x0010, 0x0001);	// enter sleepmode
-				release_bus();
-				break;
-			case powerOn:
-				acquire_bus();
-				write_reg(0x0010, 0x0000);	// leave sleep mode
-				release_bus();
-				if (GDISP.Powermode != powerSleep)
-					lld_gdisp_init();
-				break;
-			case powerSleep:
-				acquire_bus();
-				write_reg(0x0010, 0x0001);	// enter sleep mode
-				release_bus();
-				break;
-			default:
-				return;
-			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
-			return;
-		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(0x0001, 0x2B3F);
-				/* ID = 11 AM = 0 */
-				write_reg(0x0011, 0x6070);
-				release_bus();
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_90:
-				acquire_bus();
-				write_reg(0x0001, 0x293F);
-				/* ID = 11 AM = 1 */
-				write_reg(0x0011, 0x6078);
-				release_bus();
-				GDISP.Height = GDISP_SCREEN_WIDTH;
-				GDISP.Width = GDISP_SCREEN_HEIGHT;
-				break;
-			case GDISP_ROTATE_180:
-				acquire_bus();
-				write_reg(0x0001, 0x2B3F);
-				/* ID = 01 AM = 0 */
-				write_reg(0x0011, 0x6040);
-				release_bus();
-				GDISP.Height = GDISP_SCREEN_HEIGHT;
-				GDISP.Width = GDISP_SCREEN_WIDTH;
-				break;
-			case GDISP_ROTATE_270:
-				acquire_bus();
-				write_reg(0x0001, 0x293F);
-				/* ID = 01 AM = 1 */
-				write_reg(0x0011, 0x6048);
-				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:
-		case GDISP_CONTROL_CONTRAST:
-*/
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/SSD1289/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for the SSD1289 display.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+/*===========================================================================*/
+/* Driver local definitions.                                                 */
+/*===========================================================================*/
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+
+#define GDISP_INITIAL_CONTRAST	50
+#define GDISP_INITIAL_BACKLIGHT	100
+
+/*===========================================================================*/
+/* Driver local functions.                                                   */
+/*===========================================================================*/
+
+#if defined(GDISP_USE_CUSTOM_BOARD) && GDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#elif defined(BOARD_FIREBULL_STM32_F103)
+	#include "gdisp_lld_board_firebullstm32f103.h"
+#else
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#endif
+
+// 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)					chThdSleepMicroseconds(us)
+#define delayms(ms)					chThdSleepMilliseconds(ms)
+
+static __inline void set_cursor(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(GDISP.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(coord_t x, coord_t y, coord_t cx, coord_t cy) {
+
+	set_cursor(x, y);
+
+	/* 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
+	 */
+
+	switch(GDISP.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, (((x+cx-1) << 8) & 0xFF00 ) | (y & 0x00FF));
+			write_reg(0x45, x & 0x01FF);
+			write_reg(0x46, (x+cx-1) & 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);
+			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);
+			break;
+	}
+
+	set_cursor(x, y);
+}
+
+static __inline void reset_viewport(void) {
+	set_viewport(0, 0, GDISP.Width, GDISP.Height);
+}
+
+/*===========================================================================*/
+/* 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) {
+	/* Initialise your display */
+	init_board();
+
+	// Hardware reset
+	setpin_reset(TRUE);
+	delayms(20);
+	setpin_reset(FALSE);
+	delayms(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);
+
+ 	// Release the bus
+	release_bus();
+	
+	/* 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
+	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 i;
+
+		acquire_bus();
+		reset_viewport();
+		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
+
+		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();
+	}
+#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();
+		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 (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; j < cx; j++)
+					buf[j] = read_data();
+				stream_stop();
+
+				set_viewport(x, row1, cx, 1);
+				stream_start();
+				for (j = 0; j < cx; j++)
+					write_data(buf[j]);
+				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();
+		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) {
+		case GDISP_CONTROL_POWER:
+			if (GDISP.Powermode == (gdisp_powermode_t)value)
+				return;
+			switch((gdisp_powermode_t)value) {
+			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
+				release_bus();
+				break;
+			case powerOn:
+				acquire_bus();
+				write_reg(0x0010, 0x0000);	// leave sleep mode
+				release_bus();
+				if (GDISP.Powermode != powerSleep)
+					gdisp_lld_init();
+				break;
+			case powerSleep:
+				acquire_bus();
+				write_reg(0x0010, 0x0001);	// enter sleep mode
+				release_bus();
+				break;
+			default:
+				return;
+			}
+			GDISP.Powermode = (gdisp_powermode_t)value;
+			return;
+		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(0x0001, 0x2B3F);
+				/* ID = 11 AM = 0 */
+				write_reg(0x0011, 0x6070);
+				release_bus();
+				GDISP.Height = GDISP_SCREEN_HEIGHT;
+				GDISP.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_90:
+				acquire_bus();
+				write_reg(0x0001, 0x293F);
+				/* ID = 11 AM = 1 */
+				write_reg(0x0011, 0x6078);
+				release_bus();
+				GDISP.Height = GDISP_SCREEN_WIDTH;
+				GDISP.Width = GDISP_SCREEN_HEIGHT;
+				break;
+			case GDISP_ROTATE_180:
+				acquire_bus();
+				write_reg(0x0001, 0x2B3F);
+				/* ID = 01 AM = 0 */
+				write_reg(0x0011, 0x6040);
+				release_bus();
+				GDISP.Height = GDISP_SCREEN_HEIGHT;
+				GDISP.Width = GDISP_SCREEN_WIDTH;
+				break;
+			case GDISP_ROTATE_270:
+				acquire_bus();
+				write_reg(0x0001, 0x293F);
+				/* ID = 01 AM = 1 */
+				write_reg(0x0011, 0x6048);
+				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:
+		case GDISP_CONTROL_CONTRAST:
+*/
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/SSD1963/gdisp_lld.c b/drivers/gdisp/SSD1963/gdisp_lld.c
index 0b676ebc..4044d8d0 100644
--- a/drivers/gdisp/SSD1963/gdisp_lld.c
+++ b/drivers/gdisp/SSD1963/gdisp_lld.c
@@ -1,613 +1,613 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/SSD1963/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		320
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		240
-#endif
-
-/* 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.
- */
-//#if defined(BOARD_YOURBOARDNAME)
-//	#include "gdisp_lld_board_yourboardname.h"
-//#else
-//	/* Include the user supplied board definitions */
-//	#include "gdisp_lld_board.h"
-//#endif
-
-/*===========================================================================*/
-/* Driver interrupt handlers.                                                */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-#include "ssd1963.h"
-
-
-#if defined(GDISP_USE_FSMC)
-__inline void GDISP_LLD(writeindex)(uint8_t cmd) {
-  GDISP_REG = cmd;
-}
-
-__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) {
-	GDISP_REG = lcdReg;
-	GDISP_RAM = lcdRegValue;
-}
-
-__inline void GDISP_LLD(writedata)(uint16_t data) {
-	GDISP_RAM = data;
-}
-
-__inline uint16_t GDISP_LLD(readdata)(void) {
-	return (GDISP_RAM);
-}
-
-__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) {
-	GDISP_REG = lcdReg;
-	return (GDISP_RAM);
-}
-
-__inline void GDISP_LLD(writestreamstart)(void) {
-	GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START);
-}
-
-__inline void GDISP_LLD(readstreamstart)(void) {
-	GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START);
-}
-
-__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) {
-	uint16_t i;
-	for(i = 0; i < size; i++)
-		GDISP_RAM = buffer[i];
-}
-
-__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) {
-	uint16_t i;
-
-	for(i = 0; i < size; i++) {
-		buffer[i] = GDISP_RAM;
-	}
-}
-
-#elif defined(GDISP_USE_GPIO)
-
-__inline void GDISP_LLD(writeindex)(uint8_t cmd) {
-	Set_CS; Set_RS; Set_WR; Clr_RD;
-	palWritePort(GDISP_DATA_PORT, cmd);
-	Clr_CS;
-}
-
-__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) {
-	Set_CS; Set_RS; Set_WR; Clr_RD;
-	palWritePort(GDISP_DATA_PORT, lcdReg);
-	Clr_RS;
-	palWritePort(GDISP_DATA_PORT, lcdRegValue);
-	Clr_CS;
-}
-__inline void GDISP_LLD(writedata)(uint16_t data) {
-	Set_CS; Clr_RS; Set_WR; Clr_RD;
-	palWritePort(GDISP_DATA_PORT, data);
-	Clr_CS;
-}
-
-__inline uint16_t GDISP_LLD(readdata)(void) {
-	Set_CS; Clr_RS; Clr_WR; Set_RD;
-	uint16_t data = palReadPort(GDISP_DATA_PORT); 
-	Clr_CS;
-	return data;
-}
-
-__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) {
-	Set_CS; Set_RS; Clr_WR; Set_RD;
-	palWritePort(GDISP_DATA_PORT, lcdReg);
-	Clr_RS;
-	uint16_t data = palReadPort(GDISP_DATA_PORT);
-	Clr_CS;
-	return data;
-}
-
-__inline void GDISP_LLD(writestreamstart)(void) {
-	GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START);
-}
-
-__inline void GDISP_LLD(readstreamstart)(void) {
-	GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START);
-}
-
-__inline void GDISP_LLD(writestream)(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 GDISP_LLD(readstream)(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;
-	}
-}
-#endif
-
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialisation.
- * @return	TRUE if successful, FALSE on error.
- *
- * @notapi
- */
-bool_t lld_gdisp_init(void) {
-	/* Initialise the display */
-
-#if defined(GDISP_USE_FSMC)
-	
-	#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 << 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));
-	
-	const unsigned char FSMC_Bank = 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) ;
-
-	/* 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;
-	
-#elif defined(GDISP_USE_GPIO)
-	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);
-	
-#else
-	#error "Please define GDISP_USE_FSMC or GDISP_USE_GPIO"
-#endif	
-	GDISP_LLD(writeindex)(SSD1963_SOFT_RESET);	
-	chThdSleepMicroseconds(100);
-
-	/* Driver PLL config */
-	GDISP_LLD(writeindex)(SSD1963_SET_PLL_MN);
-	GDISP_LLD(writedata)(35);								 // PLLclk = REFclk (10Mhz) * 36 (360Mhz)
-	GDISP_LLD(writedata)(2);								 // SYSclk = PLLclk / 3  (120MHz)
-	GDISP_LLD(writedata)(4);								 // Apply calculation bit, else it is ignored
-
-	GDISP_LLD(writeindex)(SSD1963_SET_PLL);					// Enable PLL
-	GDISP_LLD(writedata)(0x01);
-	chThdSleepMicroseconds(200);
-
-	GDISP_LLD(writeindex)(SSD1963_SET_PLL);					// Use PLL
-	GDISP_LLD(writedata)(0x03);
-	chThdSleepMicroseconds(200);
-
-	GDISP_LLD(writeindex)(SSD1963_SOFT_RESET);	
-	chThdSleepMicroseconds(100);
-
-	/* Screen size */
-	GDISP_LLD(writeindex)(SSD1963_SET_GDISP_MODE);
-//	GDISP_LLD(writedata)(0x0000);
-	GDISP_LLD(writedata)(0b00011000); //Enabled dithering
-	GDISP_LLD(writedata)(0x0000);
-	GDISP_LLD(writedata)(mHIGH((GDISP_SCREEN_WIDTH+1)));
-	GDISP_LLD(writedata)((GDISP_SCREEN_WIDTH+1));
-	GDISP_LLD(writedata)(mHIGH((GDISP_SCREEN_HEIGHT+1)));
-	GDISP_LLD(writedata)((GDISP_SCREEN_HEIGHT+1));
-	GDISP_LLD(writedata)(0x0000);
-
-	GDISP_LLD(writeindex)(SSD1963_SET_PIXEL_DATA_INTERFACE);
-	GDISP_LLD(writedata)(SSD1963_PDI_16BIT565);
-
-	/* LCD Clock specs */
-	GDISP_LLD(writeindex)(SSD1963_SET_LSHIFT_FREQ);
-	GDISP_LLD(writedata)((GDISP_FPR >> 16) & 0xFF);
-	GDISP_LLD(writedata)((GDISP_FPR >> 8) & 0xFF);
-	GDISP_LLD(writedata)(GDISP_FPR & 0xFF);
-
-	GDISP_LLD(writeindex)(SSD1963_SET_HORI_PERIOD);
-	GDISP_LLD(writedata)(mHIGH(SCREEN_HSYNC_PERIOD));
-	GDISP_LLD(writedata)(mLOW(SCREEN_HSYNC_PERIOD));
-	GDISP_LLD(writedata)(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
-	GDISP_LLD(writedata)(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
-	GDISP_LLD(writedata)(SCREEN_HSYNC_PULSE);
-	GDISP_LLD(writedata)(0x00);
-	GDISP_LLD(writedata)(0x00);
-	GDISP_LLD(writedata)(0x00);
-
-	GDISP_LLD(writeindex)(SSD1963_SET_VERT_PERIOD);
-	GDISP_LLD(writedata)(mHIGH(SCREEN_VSYNC_PERIOD));
-	GDISP_LLD(writedata)(mLOW(SCREEN_VSYNC_PERIOD));
-	GDISP_LLD(writedata)(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
-	GDISP_LLD(writedata)(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
-	GDISP_LLD(writedata)(SCREEN_VSYNC_PULSE);
-	GDISP_LLD(writedata)(0x00);
-	GDISP_LLD(writedata)(0x00);
-
-	/* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel */
-	GDISP_LLD(writeindex)(SSD1963_SET_TEAR_ON);
-	GDISP_LLD(writedata)(0x0000);
-
-	/* Turn on */
-	GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON);
-	#if defined(GDISP_USE_FSMC)
-		/* 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;
-	#endif
-
-	/* 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
-
-	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
-	*/
-	GDISP_LLD(writeindex)(SSD1963_SET_PAGE_ADDRESS);
-	GDISP_LLD(writedata)((y0 >> 8) & 0xFF);
-	GDISP_LLD(writedata)((y0 >> 0) & 0xFF);
-	GDISP_LLD(writedata)((y1 >> 8) & 0xFF);
-	GDISP_LLD(writedata)((y1 >> 0) & 0xFF);
-	GDISP_LLD(writeindex)(SSD1963_SET_COLUMN_ADDRESS);
-	GDISP_LLD(writedata)((x0 >> 8) & 0xFF);
-	GDISP_LLD(writedata)((x0 >> 0) & 0xFF);
-	GDISP_LLD(writedata)((x1 >> 8) & 0xFF);
-	GDISP_LLD(writedata)((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 lld_gdisp_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);
-	GDISP_LLD(writestreamstart)();
-	GDISP_LLD(writedata)(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 lld_gdisp_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
-		
-		uint32_t area;
-		area = cx*cy;
-
-		GDISP_LLD(setwindow)(x, y, x+cx-1, y+cy-1);
-		GDISP_LLD(writestreamstart)();
-
-		#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++)
-				GDISP_LLD(writedata)(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 lld_gdisp_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);
-		GDISP_LLD(writestreamstart)();
-
-		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;
-			unsigned lg;
-			endx = srcx + cx;
-			endy = y + cy;
-			lg = srccx - cx;
-			for(; y < endy; y++, buffer += lg)
-				for(x=srcx; x < endx; x++)
-					GDISP_LLD(writedata)(*buffer++);
-		#endif  //#ifdef GDISP_USE_DMA
-	}
-#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 lld_gdisp_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 ;
-
-		lld_lcdWriteIndex(SSD1963_SET_SCROLL_AREA);
-		lld_lcdWriteData((x0 >> 8) & 0xFF);
-		lld_lcdWriteData((x0 >> 0) & 0xFF);
-		lld_lcdWriteData((size >> 8) & 0xFF);
-		lld_lcdWriteData((size >> 0) & 0xFF);
-		lld_lcdWriteData(((lcd_height-x1) >> 8) & 0xFF);
-		lld_lcdWriteData(((lcd_height-x1) >> 0) & 0xFF);
-
-		lld_lcdWriteIndex(SSD1963_SET_SCROLL_START);
-		lld_lcdWriteData((lines >> 8) & 0xFF);
-		lld_lcdWriteData((lines >> 0) & 0xFF);
-		*/
-	}
-	
-#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 lld_gdisp_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:
-					GDISP_LLD(writeindex)(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
-					chThdSleepMicroseconds(5000);
-					GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF);
-					GDISP_LLD(writeindex)(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
-					break;
-				case powerOn:
-					GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); // 2x Dummy reads to wake up from deep sleep
-					GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000);
-					if (GDISP.Powermode != powerSleep)
-						lld_gdisp_init();
-					GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON);
-
-					break;
-				case powerSleep:
-					GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF);
-					GDISP_LLD(writeindex)(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
-					chThdSleepMicroseconds(5000);
-					break;
-				default:
-					return;
-			}
-			GDISP.Powermode = (gdisp_powermode_t)value;
-			return;
-			case GDISP_CONTROL_ORIENTATION:
-				if (GDISP.Orientation == (gdisp_orientation_t)value)
-					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;
-			return;
-/*
-		case GDISP_CONTROL_BACKLIGHT:
-		case GDISP_CONTROL_CONTRAST:
-*/
-		}
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/SSD1963/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		320
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		240
+#endif
+
+/* 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.
+ */
+//#if defined(BOARD_YOURBOARDNAME)
+//	#include "gdisp_lld_board_yourboardname.h"
+//#else
+//	/* Include the user supplied board definitions */
+//	#include "gdisp_lld_board.h"
+//#endif
+
+/*===========================================================================*/
+/* Driver interrupt handlers.                                                */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+#include "ssd1963.h"
+
+
+#if defined(GDISP_USE_FSMC)
+__inline void GDISP_LLD(writeindex)(uint8_t cmd) {
+  GDISP_REG = cmd;
+}
+
+__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) {
+	GDISP_REG = lcdReg;
+	GDISP_RAM = lcdRegValue;
+}
+
+__inline void GDISP_LLD(writedata)(uint16_t data) {
+	GDISP_RAM = data;
+}
+
+__inline uint16_t GDISP_LLD(readdata)(void) {
+	return (GDISP_RAM);
+}
+
+__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) {
+	GDISP_REG = lcdReg;
+	return (GDISP_RAM);
+}
+
+__inline void GDISP_LLD(writestreamstart)(void) {
+	GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START);
+}
+
+__inline void GDISP_LLD(readstreamstart)(void) {
+	GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START);
+}
+
+__inline void GDISP_LLD(writestream)(uint16_t *buffer, uint16_t size) {
+	uint16_t i;
+	for(i = 0; i < size; i++)
+		GDISP_RAM = buffer[i];
+}
+
+__inline void GDISP_LLD(readstream)(uint16_t *buffer, size_t size) {
+	uint16_t i;
+
+	for(i = 0; i < size; i++) {
+		buffer[i] = GDISP_RAM;
+	}
+}
+
+#elif defined(GDISP_USE_GPIO)
+
+__inline void GDISP_LLD(writeindex)(uint8_t cmd) {
+	Set_CS; Set_RS; Set_WR; Clr_RD;
+	palWritePort(GDISP_DATA_PORT, cmd);
+	Clr_CS;
+}
+
+__inline void GDISP_LLD(writereg)(uint16_t lcdReg,uint16_t lcdRegValue) {
+	Set_CS; Set_RS; Set_WR; Clr_RD;
+	palWritePort(GDISP_DATA_PORT, lcdReg);
+	Clr_RS;
+	palWritePort(GDISP_DATA_PORT, lcdRegValue);
+	Clr_CS;
+}
+__inline void GDISP_LLD(writedata)(uint16_t data) {
+	Set_CS; Clr_RS; Set_WR; Clr_RD;
+	palWritePort(GDISP_DATA_PORT, data);
+	Clr_CS;
+}
+
+__inline uint16_t GDISP_LLD(readdata)(void) {
+	Set_CS; Clr_RS; Clr_WR; Set_RD;
+	uint16_t data = palReadPort(GDISP_DATA_PORT); 
+	Clr_CS;
+	return data;
+}
+
+__inline uint8_t GDISP_LLD(readreg)(uint8_t lcdReg) {
+	Set_CS; Set_RS; Clr_WR; Set_RD;
+	palWritePort(GDISP_DATA_PORT, lcdReg);
+	Clr_RS;
+	uint16_t data = palReadPort(GDISP_DATA_PORT);
+	Clr_CS;
+	return data;
+}
+
+__inline void GDISP_LLD(writestreamstart)(void) {
+	GDISP_LLD(writeindex)(SSD1963_WRITE_MEMORY_START);
+}
+
+__inline void GDISP_LLD(readstreamstart)(void) {
+	GDISP_LLD(writeindex)(SSD1963_READ_MEMORY_START);
+}
+
+__inline void GDISP_LLD(writestream)(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 GDISP_LLD(readstream)(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;
+	}
+}
+#endif
+
+/* ---- Required Routines ---- */
+/*
+	The following 2 routines are required.
+	All other routines are optional.
+*/
+
+/**
+ * @brief   Low level GDISP driver initialisation.
+ * @return	TRUE if successful, FALSE on error.
+ *
+ * @notapi
+ */
+bool_t gdisp_lld_init(void) {
+	/* Initialise the display */
+
+#if defined(GDISP_USE_FSMC)
+	
+	#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 << 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));
+	
+	const unsigned char FSMC_Bank = 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) ;
+
+	/* 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;
+	
+#elif defined(GDISP_USE_GPIO)
+	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);
+	
+#else
+	#error "Please define GDISP_USE_FSMC or GDISP_USE_GPIO"
+#endif	
+	GDISP_LLD(writeindex)(SSD1963_SOFT_RESET);	
+	chThdSleepMicroseconds(100);
+
+	/* Driver PLL config */
+	GDISP_LLD(writeindex)(SSD1963_SET_PLL_MN);
+	GDISP_LLD(writedata)(35);								 // PLLclk = REFclk (10Mhz) * 36 (360Mhz)
+	GDISP_LLD(writedata)(2);								 // SYSclk = PLLclk / 3  (120MHz)
+	GDISP_LLD(writedata)(4);								 // Apply calculation bit, else it is ignored
+
+	GDISP_LLD(writeindex)(SSD1963_SET_PLL);					// Enable PLL
+	GDISP_LLD(writedata)(0x01);
+	chThdSleepMicroseconds(200);
+
+	GDISP_LLD(writeindex)(SSD1963_SET_PLL);					// Use PLL
+	GDISP_LLD(writedata)(0x03);
+	chThdSleepMicroseconds(200);
+
+	GDISP_LLD(writeindex)(SSD1963_SOFT_RESET);	
+	chThdSleepMicroseconds(100);
+
+	/* Screen size */
+	GDISP_LLD(writeindex)(SSD1963_SET_GDISP_MODE);
+//	GDISP_LLD(writedata)(0x0000);
+	GDISP_LLD(writedata)(0b00011000); //Enabled dithering
+	GDISP_LLD(writedata)(0x0000);
+	GDISP_LLD(writedata)(mHIGH((GDISP_SCREEN_WIDTH+1)));
+	GDISP_LLD(writedata)((GDISP_SCREEN_WIDTH+1));
+	GDISP_LLD(writedata)(mHIGH((GDISP_SCREEN_HEIGHT+1)));
+	GDISP_LLD(writedata)((GDISP_SCREEN_HEIGHT+1));
+	GDISP_LLD(writedata)(0x0000);
+
+	GDISP_LLD(writeindex)(SSD1963_SET_PIXEL_DATA_INTERFACE);
+	GDISP_LLD(writedata)(SSD1963_PDI_16BIT565);
+
+	/* LCD Clock specs */
+	GDISP_LLD(writeindex)(SSD1963_SET_LSHIFT_FREQ);
+	GDISP_LLD(writedata)((GDISP_FPR >> 16) & 0xFF);
+	GDISP_LLD(writedata)((GDISP_FPR >> 8) & 0xFF);
+	GDISP_LLD(writedata)(GDISP_FPR & 0xFF);
+
+	GDISP_LLD(writeindex)(SSD1963_SET_HORI_PERIOD);
+	GDISP_LLD(writedata)(mHIGH(SCREEN_HSYNC_PERIOD));
+	GDISP_LLD(writedata)(mLOW(SCREEN_HSYNC_PERIOD));
+	GDISP_LLD(writedata)(mHIGH((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
+	GDISP_LLD(writedata)(mLOW((SCREEN_HSYNC_PULSE + SCREEN_HSYNC_BACK_PORCH)));
+	GDISP_LLD(writedata)(SCREEN_HSYNC_PULSE);
+	GDISP_LLD(writedata)(0x00);
+	GDISP_LLD(writedata)(0x00);
+	GDISP_LLD(writedata)(0x00);
+
+	GDISP_LLD(writeindex)(SSD1963_SET_VERT_PERIOD);
+	GDISP_LLD(writedata)(mHIGH(SCREEN_VSYNC_PERIOD));
+	GDISP_LLD(writedata)(mLOW(SCREEN_VSYNC_PERIOD));
+	GDISP_LLD(writedata)(mHIGH((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
+	GDISP_LLD(writedata)(mLOW((SCREEN_VSYNC_PULSE + SCREEN_VSYNC_BACK_PORCH)));
+	GDISP_LLD(writedata)(SCREEN_VSYNC_PULSE);
+	GDISP_LLD(writedata)(0x00);
+	GDISP_LLD(writedata)(0x00);
+
+	/* Tear effect indicator ON. This is used to tell the host MCU when the driver is not refreshing the panel */
+	GDISP_LLD(writeindex)(SSD1963_SET_TEAR_ON);
+	GDISP_LLD(writedata)(0x0000);
+
+	/* Turn on */
+	GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON);
+	#if defined(GDISP_USE_FSMC)
+		/* 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;
+	#endif
+
+	/* 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
+
+	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
+	*/
+	GDISP_LLD(writeindex)(SSD1963_SET_PAGE_ADDRESS);
+	GDISP_LLD(writedata)((y0 >> 8) & 0xFF);
+	GDISP_LLD(writedata)((y0 >> 0) & 0xFF);
+	GDISP_LLD(writedata)((y1 >> 8) & 0xFF);
+	GDISP_LLD(writedata)((y1 >> 0) & 0xFF);
+	GDISP_LLD(writeindex)(SSD1963_SET_COLUMN_ADDRESS);
+	GDISP_LLD(writedata)((x0 >> 8) & 0xFF);
+	GDISP_LLD(writedata)((x0 >> 0) & 0xFF);
+	GDISP_LLD(writedata)((x1 >> 8) & 0xFF);
+	GDISP_LLD(writedata)((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);
+	GDISP_LLD(writestreamstart)();
+	GDISP_LLD(writedata)(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) {
+    
+		#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
+		
+		uint32_t area;
+		area = cx*cy;
+
+		GDISP_LLD(setwindow)(x, y, x+cx-1, y+cy-1);
+		GDISP_LLD(writestreamstart)();
+
+		#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++)
+				GDISP_LLD(writedata)(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);
+		GDISP_LLD(writestreamstart)();
+
+		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;
+			unsigned lg;
+			endx = srcx + cx;
+			endy = y + cy;
+			lg = srccx - cx;
+			for(; y < endy; y++, buffer += lg)
+				for(x=srcx; x < endx; x++)
+					GDISP_LLD(writedata)(*buffer++);
+		#endif  //#ifdef GDISP_USE_DMA
+	}
+#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 ;
+
+		lld_lcdWriteIndex(SSD1963_SET_SCROLL_AREA);
+		lld_lcdWriteData((x0 >> 8) & 0xFF);
+		lld_lcdWriteData((x0 >> 0) & 0xFF);
+		lld_lcdWriteData((size >> 8) & 0xFF);
+		lld_lcdWriteData((size >> 0) & 0xFF);
+		lld_lcdWriteData(((lcd_height-x1) >> 8) & 0xFF);
+		lld_lcdWriteData(((lcd_height-x1) >> 0) & 0xFF);
+
+		lld_lcdWriteIndex(SSD1963_SET_SCROLL_START);
+		lld_lcdWriteData((lines >> 8) & 0xFF);
+		lld_lcdWriteData((lines >> 0) & 0xFF);
+		*/
+	}
+	
+#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:
+					GDISP_LLD(writeindex)(SSD1963_EXIT_SLEEP_MODE); // leave sleep mode
+					chThdSleepMicroseconds(5000);
+					GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF);
+					GDISP_LLD(writeindex)(SSD1963_SET_DEEP_SLEEP); // enter deep sleep mode
+					break;
+				case powerOn:
+					GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000); // 2x Dummy reads to wake up from deep sleep
+					GDISP_LLD(readreg)(0x0000); chThdSleepMicroseconds(5000);
+					if (GDISP.Powermode != powerSleep)
+						gdisp_lld_init();
+					GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_ON);
+
+					break;
+				case powerSleep:
+					GDISP_LLD(writeindex)(SSD1963_SET_DISPLAY_OFF);
+					GDISP_LLD(writeindex)(SSD1963_ENTER_SLEEP_MODE); // enter sleep mode
+					chThdSleepMicroseconds(5000);
+					break;
+				default:
+					return;
+			}
+			GDISP.Powermode = (gdisp_powermode_t)value;
+			return;
+			case GDISP_CONTROL_ORIENTATION:
+				if (GDISP.Orientation == (gdisp_orientation_t)value)
+					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;
+			return;
+/*
+		case GDISP_CONTROL_BACKLIGHT:
+		case GDISP_CONTROL_CONTRAST:
+*/
+		}
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/gdisp/TestStub/gdisp_lld.c b/drivers/gdisp/TestStub/gdisp_lld.c
index be323912..a1f3de3e 100644
--- a/drivers/gdisp/TestStub/gdisp_lld.c
+++ b/drivers/gdisp/TestStub/gdisp_lld.c
@@ -1,133 +1,133 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/gdisp/TestStub/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source (stub).
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.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"
-
-#ifndef GDISP_SCREEN_HEIGHT
-	#define GDISP_SCREEN_HEIGHT		128
-#endif
-#ifndef GDISP_SCREEN_WIDTH
-	#define GDISP_SCREEN_WIDTH		128
-#endif
-
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialization.
- *
- * @notapi
- */
-bool_t lld_gdisp_init(void) {
-	/* 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
-	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 lld_gdisp_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 lld_gdisp_get_pixel_color(coord_t x, coord_t y) {
-		(void)x;
-		(void)y;
-
-		return 0;
-	}
-#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 lld_gdisp_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;
-	}
-#endif
-
-#endif /* GFX_USE_GDISP */
-/** @} */
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gdisp/TestStub/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source (stub).
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.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"
+
+#ifndef GDISP_SCREEN_HEIGHT
+	#define GDISP_SCREEN_HEIGHT		128
+#endif
+#ifndef GDISP_SCREEN_WIDTH
+	#define GDISP_SCREEN_WIDTH		128
+#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) {
+	/* 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
+	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;
+	}
+#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;
+	}
+#endif
+
+#endif /* GFX_USE_GDISP */
+/** @} */
diff --git a/drivers/multiple/Win32/gdisp_lld.c b/drivers/multiple/Win32/gdisp_lld.c
index 8a46abc9..220776d2 100644
--- a/drivers/multiple/Win32/gdisp_lld.c
+++ b/drivers/multiple/Win32/gdisp_lld.c
@@ -1,1026 +1,1026 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/multiple/Win32/gdisp_lld.c
- * @brief   GDISP Graphics Driver subsystem low level driver source for Win32.
- *
- * @addtogroup GDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
-
-#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
-
-#if GINPUT_NEED_TOGGLE
-	/* Include toggle support code */
-	#include "ginput/lld/toggle.h"
-
-	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
-		{0,	0xFF, 0x00, PAL_MODE_INPUT},
-	};
-#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"
-
-/*===========================================================================*/
-/* 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 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;
-
-#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;
-	#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:
-		break;
-	case WM_LBUTTONDOWN:
-		#if GINPUT_NEED_MOUSE
-			if ((coord_t)HIWORD(lParam) < wHeight) {
-				mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
-				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 & 0xF0)) {
-				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
-			}
-		#endif
-		#if GINPUT_NEED_MOUSE
-			if ((coord_t)HIWORD(lParam) < wHeight) {
-				mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
-				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_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_PAINT:
-		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);
-		#if GINPUT_NEED_TOGGLE
-			if (ps.rcPaint.bottom >= wHeight) {
-				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);
-				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);
-					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);
-		break;
-	case WM_DESTROY:
-		PostQuitMessage(0);
-		SelectObject(dcBuffer, dcOldBitmap);
-		DeleteDC(dcBuffer);
-		DeleteObject(dcBitmap);
-		winRootWindow = NULL;
-		break;
-	default:
-		return DefWindowProc(hWnd, Msg, wParam, lParam);
-	}
-	return 0;
-}
-
-static DWORD WINAPI WindowThread(LPVOID lpParameter) {
-	(void)lpParameter;
-	
-	MSG msg;
-	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;
-
-	while(GetMessage(&msg, NULL, 0, 0) > 0) {
-		TranslateMessage(&msg);
-		DispatchMessage(&msg);
-	}
-	ExitProcess(0);
-	return msg.wParam;
-}
-
-/*===========================================================================*/
-/* Driver exported functions.                                                */
-/*===========================================================================*/
-
-/* ---- Required Routines ---- */
-/*
-	The following 2 routines are required.
-	All other routines are optional.
-*/
-
-/**
- * @brief   Low level GDISP driver initialisation.
- * @return	TRUE if successful, FALSE on error.
- *
- * @notapi
- */
-bool_t lld_gdisp_init(void) {
-	RECT rect;
-
-	/* 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 */
-	CreateThread(0, 0, WindowThread, 0, 0, 0);
-	while (!isReady)
-		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
-	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 lld_gdisp_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
-	
-	// Draw the pixel in the buffer
-	color = COLOR2BGR(color);
-	SetPixel(dcBuffer, x, y, 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
-}
-
-/* ---- Optional Routines ---- */
-
-#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__)
-	/**
-	 * @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 lld_gdisp_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(GDISP.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);
-				#endif
-				break;
-			case GDISP_ROTATE_90:
-				t = GDISP.Height - 1 - y0;
-				y0 = x0;
-				x0 = t;
-				t = GDISP.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);
-				#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;
-				#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);
-				#endif
-				break;
-			case GDISP_ROTATE_270:
-				t = GDISP.Width - 1 - x0;
-				x0 = y0;
-				y0 = t;
-				t = GDISP.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);
-				#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);
-			#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
-
-#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 lld_gdisp_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_NEED_CONTROL
-			switch(GDISP.Orientation) {
-			case GDISP_ROTATE_0:
-				rect.top = y;
-				rect.bottom = rect.top+cy;
-				rect.left = x;
-				rect.right = rect.left+cx;
-				break;
-			case GDISP_ROTATE_90:
-				rect.top = x;
-				rect.bottom = rect.top+cx;
-				rect.right = GDISP.Height - y;
-				rect.left = rect.right-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;
-				break;
-			case GDISP_ROTATE_270:
-				rect.bottom = GDISP.Width - x;
-				rect.top = rect.bottom-cx;
-				rect.left = y;
-				rect.right = rect.left+cy;
-				break;
-			}
-		#else
-			rect.top = y;
-			rect.bottom = rect.top+cy;
-			rect.left = x;
-			rect.right = rect.left+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
-
-			DeleteObject(hbr);
-		}
-	}
-#endif
-
-#if (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL) || defined(__DOXYGEN__)
-	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;
-		const pixel_t	*src;
-		size_t	sz;
-		coord_t	i, j;
-
-		// Shortcut.
-		if (GDISP.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx)
-			return (pixel_t *)buffer;
-		
-		// Allocate the destination buffer
-		sz = (size_t)cx * (size_t)cy;
-		if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
-			return 0;
-		
-		// Copy the bits we need
-		switch(GDISP.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)
-					*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)
-					*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)
-					*--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)
-					*dst = *src++;
-			}
-			break;
-		}
-		return dstbuf;
-	}
-#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 lld_gdisp_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) {
-		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 < 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
-
-		// Make everything relative to the start of the line
-		buffer += srccx*srcy;
-		srcy = 0;
-		
-		memset(&bmpInfo, 0, sizeof(bmpInfo));
-		bmpInfo.bV4Size = sizeof(bmpInfo);
-		bmpInfo.bV4Planes = 1;
-		bmpInfo.bV4BitCount = 32;
-		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
-			bmpInfo.bV4SizeImage = (cy*cx) * sizeof(pixel_t);
-			srcimg = rotateimg(cx, cy, srcx, srccx, buffer);
-			if (!srcimg) return;
-			
-			switch(GDISP.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;
-				break;
-			case GDISP_ROTATE_90:
-				bmpInfo.bV4Width = cy;
-				bmpInfo.bV4Height = -cx; /* top-down image */
-				rect.top = x;
-				rect.bottom = rect.top+cx;
-				rect.right = GDISP.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.top = rect.bottom-cy;
-				rect.right = GDISP.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.top = rect.bottom-cx;
-				rect.left = y;
-				rect.right = rect.left+cy;
-				break;
-			}
-			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)
-				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);
-		#endif
-
-		// Invalidate the region to get it on the screen.
-		InvalidateRect(winRootWindow, &rect, FALSE);
-		UpdateWindow(winRootWindow);
-	}
-#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 lld_gdisp_get_pixel_color(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;
-		#endif
-
-		#if GDISP_NEED_CONTROL
-			switch(GDISP.Orientation) {
-			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
-		
-		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 lld_gdisp_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 < 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
-		
-		if (lines > cy) lines = cy;
-		else if (-lines > cy) lines = -cy;
-
-		bgcolor = COLOR2BGR(bgcolor);
-		hbr = CreateSolidBrush(bgcolor);
-
-		#if GDISP_NEED_CONTROL
-			switch(GDISP.Orientation) {
-			case GDISP_ROTATE_0:
-				rect.top = y;
-				rect.bottom = rect.top+cy;
-				rect.left = x;
-				rect.right = rect.left+cx;
-				lines = -lines;
-				goto vertical_scroll;
-			case GDISP_ROTATE_90:
-				rect.top = x;
-				rect.bottom = rect.top+cx;
-				rect.right = GDISP.Height - y;
-				rect.left = rect.right-cy;
-				goto horizontal_scroll;
-			case GDISP_ROTATE_180:
-				rect.bottom = GDISP.Height - y;
-				rect.top = rect.bottom-cy;
-				rect.right = GDISP.Width - x;
-				rect.left = rect.right-cx;
-			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;
-				} else {
-					srect.bottom = frect.bottom = rect.bottom;
-					frect.top = rect.bottom+lines;
-					srect.top = rect.top-lines;
-				}
-				if (cy >= lines && cy >= -lines)
-					ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
-				break;
-			case GDISP_ROTATE_270:
-				rect.bottom = GDISP.Width - x;
-				rect.top = rect.bottom-cx;
-				rect.left = y;
-				rect.right = rect.left+cy;
-				lines = -lines;
-			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;
-				} else {
-					srect.right = frect.right = rect.right;
-					frect.left = rect.right+lines;
-					srect.left = rect.left-lines;
-				}
-				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;
-			if (lines > 0) {
-				srect.top = frect.top = rect.top;
-				frect.bottom = rect.top+lines;
-				srect.bottom = rect.bottom-lines;
-			} else {
-				srect.bottom = frect.bottom = rect.bottom;
-				frect.top = rect.bottom+lines;
-				srect.top = rect.top-lines;
-			}
-			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 lld_gdisp_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:
-					GDISP.Width = wWidth;
-					GDISP.Height = wHeight;
-					break;
-				case GDISP_ROTATE_90:
-					GDISP.Height = wWidth;
-					GDISP.Width = wHeight;
-					break;
-				case GDISP_ROTATE_180:
-					GDISP.Width = wWidth;
-					GDISP.Height = wHeight;
-					break;
-				case GDISP_ROTATE_270:
-					GDISP.Height = wWidth;
-					GDISP.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;
-			#endif
-			GDISP.Orientation = (gdisp_orientation_t)value;
-			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) {
-		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
-
-	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 */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/multiple/Win32/gdisp_lld.c
+ * @brief   GDISP Graphics Driver subsystem low level driver source for Win32.
+ *
+ * @addtogroup GDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GDISP /*|| defined(__DOXYGEN__)*/
+
+#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
+
+#if GINPUT_NEED_TOGGLE
+	/* Include toggle support code */
+	#include "ginput/lld/toggle.h"
+
+	const GToggleConfig GInputToggleConfigTable[GINPUT_TOGGLE_CONFIG_ENTRIES] = {
+		{0,	0xFF, 0x00, PAL_MODE_INPUT},
+	};
+#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"
+
+/*===========================================================================*/
+/* 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 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;
+
+#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;
+	#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:
+		break;
+	case WM_LBUTTONDOWN:
+		#if GINPUT_NEED_MOUSE
+			if ((coord_t)HIWORD(lParam) < wHeight) {
+				mousebuttons |= GINPUT_MOUSE_BTN_LEFT;
+				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 & 0xF0)) {
+				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
+			}
+		#endif
+		#if GINPUT_NEED_MOUSE
+			if ((coord_t)HIWORD(lParam) < wHeight) {
+				mousebuttons &= ~GINPUT_MOUSE_BTN_LEFT;
+				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_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_PAINT:
+		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);
+		#if GINPUT_NEED_TOGGLE
+			if (ps.rcPaint.bottom >= wHeight) {
+				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);
+				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);
+					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);
+		break;
+	case WM_DESTROY:
+		PostQuitMessage(0);
+		SelectObject(dcBuffer, dcOldBitmap);
+		DeleteDC(dcBuffer);
+		DeleteObject(dcBitmap);
+		winRootWindow = NULL;
+		break;
+	default:
+		return DefWindowProc(hWnd, Msg, wParam, lParam);
+	}
+	return 0;
+}
+
+static DWORD WINAPI WindowThread(LPVOID lpParameter) {
+	(void)lpParameter;
+	
+	MSG msg;
+	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;
+
+	while(GetMessage(&msg, NULL, 0, 0) > 0) {
+		TranslateMessage(&msg);
+		DispatchMessage(&msg);
+	}
+	ExitProcess(0);
+	return msg.wParam;
+}
+
+/*===========================================================================*/
+/* Driver exported functions.                                                */
+/*===========================================================================*/
+
+/* ---- Required Routines ---- */
+/*
+	The following 2 routines are required.
+	All other routines are optional.
+*/
+
+/**
+ * @brief   Low level GDISP driver initialisation.
+ * @return	TRUE if successful, FALSE on error.
+ *
+ * @notapi
+ */
+bool_t gdisp_lld_init(void) {
+	RECT rect;
+
+	/* 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 */
+	CreateThread(0, 0, WindowThread, 0, 0, 0);
+	while (!isReady)
+		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
+	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
+	
+	// Draw the pixel in the buffer
+	color = COLOR2BGR(color);
+	SetPixel(dcBuffer, x, y, 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
+}
+
+/* ---- Optional Routines ---- */
+
+#if GDISP_HARDWARE_LINES || defined(__DOXYGEN__)
+	/**
+	 * @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(GDISP.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);
+				#endif
+				break;
+			case GDISP_ROTATE_90:
+				t = GDISP.Height - 1 - y0;
+				y0 = x0;
+				x0 = t;
+				t = GDISP.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);
+				#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;
+				#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);
+				#endif
+				break;
+			case GDISP_ROTATE_270:
+				t = GDISP.Width - 1 - x0;
+				x0 = y0;
+				y0 = t;
+				t = GDISP.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);
+				#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);
+			#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
+
+#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_NEED_CONTROL
+			switch(GDISP.Orientation) {
+			case GDISP_ROTATE_0:
+				rect.top = y;
+				rect.bottom = rect.top+cy;
+				rect.left = x;
+				rect.right = rect.left+cx;
+				break;
+			case GDISP_ROTATE_90:
+				rect.top = x;
+				rect.bottom = rect.top+cx;
+				rect.right = GDISP.Height - y;
+				rect.left = rect.right-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;
+				break;
+			case GDISP_ROTATE_270:
+				rect.bottom = GDISP.Width - x;
+				rect.top = rect.bottom-cx;
+				rect.left = y;
+				rect.right = rect.left+cy;
+				break;
+			}
+		#else
+			rect.top = y;
+			rect.bottom = rect.top+cy;
+			rect.left = x;
+			rect.right = rect.left+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
+
+			DeleteObject(hbr);
+		}
+	}
+#endif
+
+#if (GDISP_HARDWARE_BITFILLS && GDISP_NEED_CONTROL) || defined(__DOXYGEN__)
+	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;
+		const pixel_t	*src;
+		size_t	sz;
+		coord_t	i, j;
+
+		// Shortcut.
+		if (GDISP.Orientation == GDISP_ROTATE_0 && srcx == 0 && cx == srccx)
+			return (pixel_t *)buffer;
+		
+		// Allocate the destination buffer
+		sz = (size_t)cx * (size_t)cy;
+		if (!(dstbuf = (pixel_t *)malloc(sz * sizeof(pixel_t))))
+			return 0;
+		
+		// Copy the bits we need
+		switch(GDISP.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)
+					*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)
+					*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)
+					*--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)
+					*dst = *src++;
+			}
+			break;
+		}
+		return dstbuf;
+	}
+#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) {
+		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 < 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
+
+		// Make everything relative to the start of the line
+		buffer += srccx*srcy;
+		srcy = 0;
+		
+		memset(&bmpInfo, 0, sizeof(bmpInfo));
+		bmpInfo.bV4Size = sizeof(bmpInfo);
+		bmpInfo.bV4Planes = 1;
+		bmpInfo.bV4BitCount = 32;
+		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
+			bmpInfo.bV4SizeImage = (cy*cx) * sizeof(pixel_t);
+			srcimg = rotateimg(cx, cy, srcx, srccx, buffer);
+			if (!srcimg) return;
+			
+			switch(GDISP.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;
+				break;
+			case GDISP_ROTATE_90:
+				bmpInfo.bV4Width = cy;
+				bmpInfo.bV4Height = -cx; /* top-down image */
+				rect.top = x;
+				rect.bottom = rect.top+cx;
+				rect.right = GDISP.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.top = rect.bottom-cy;
+				rect.right = GDISP.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.top = rect.bottom-cx;
+				rect.left = y;
+				rect.right = rect.left+cy;
+				break;
+			}
+			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)
+				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);
+		#endif
+
+		// Invalidate the region to get it on the screen.
+		InvalidateRect(winRootWindow, &rect, FALSE);
+		UpdateWindow(winRootWindow);
+	}
+#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_VALIDATION || GDISP_NEED_CLIP
+			// Clip pre orientation change
+			if (x < 0 || x >= GDISP.Width || y < 0 || y >= GDISP.Height) return 0;
+		#endif
+
+		#if GDISP_NEED_CONTROL
+			switch(GDISP.Orientation) {
+			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
+		
+		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 < 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
+		
+		if (lines > cy) lines = cy;
+		else if (-lines > cy) lines = -cy;
+
+		bgcolor = COLOR2BGR(bgcolor);
+		hbr = CreateSolidBrush(bgcolor);
+
+		#if GDISP_NEED_CONTROL
+			switch(GDISP.Orientation) {
+			case GDISP_ROTATE_0:
+				rect.top = y;
+				rect.bottom = rect.top+cy;
+				rect.left = x;
+				rect.right = rect.left+cx;
+				lines = -lines;
+				goto vertical_scroll;
+			case GDISP_ROTATE_90:
+				rect.top = x;
+				rect.bottom = rect.top+cx;
+				rect.right = GDISP.Height - y;
+				rect.left = rect.right-cy;
+				goto horizontal_scroll;
+			case GDISP_ROTATE_180:
+				rect.bottom = GDISP.Height - y;
+				rect.top = rect.bottom-cy;
+				rect.right = GDISP.Width - x;
+				rect.left = rect.right-cx;
+			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;
+				} else {
+					srect.bottom = frect.bottom = rect.bottom;
+					frect.top = rect.bottom+lines;
+					srect.top = rect.top-lines;
+				}
+				if (cy >= lines && cy >= -lines)
+					ScrollDC(dcBuffer, 0, lines, &srect, 0, 0, 0);
+				break;
+			case GDISP_ROTATE_270:
+				rect.bottom = GDISP.Width - x;
+				rect.top = rect.bottom-cx;
+				rect.left = y;
+				rect.right = rect.left+cy;
+				lines = -lines;
+			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;
+				} else {
+					srect.right = frect.right = rect.right;
+					frect.left = rect.right+lines;
+					srect.left = rect.left-lines;
+				}
+				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;
+			if (lines > 0) {
+				srect.top = frect.top = rect.top;
+				frect.bottom = rect.top+lines;
+				srect.bottom = rect.bottom-lines;
+			} else {
+				srect.bottom = frect.bottom = rect.bottom;
+				frect.top = rect.bottom+lines;
+				srect.top = rect.top-lines;
+			}
+			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) {
+		case GDISP_CONTROL_ORIENTATION:
+			if (GDISP.Orientation == (gdisp_orientation_t)value)
+				return;
+			switch((gdisp_orientation_t)value) {
+				case GDISP_ROTATE_0:
+					GDISP.Width = wWidth;
+					GDISP.Height = wHeight;
+					break;
+				case GDISP_ROTATE_90:
+					GDISP.Height = wWidth;
+					GDISP.Width = wHeight;
+					break;
+				case GDISP_ROTATE_180:
+					GDISP.Width = wWidth;
+					GDISP.Height = wHeight;
+					break;
+				case GDISP_ROTATE_270:
+					GDISP.Height = wWidth;
+					GDISP.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;
+			#endif
+			GDISP.Orientation = (gdisp_orientation_t)value;
+			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) {
+		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
+
+	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 */
+/** @} */
+
-- 
cgit v1.2.3


From 2ed57aea77103e864c25f2478ef7fc43352163f0 Mon Sep 17 00:00:00 2001
From: Andrew Hannam <andrewh@inmarket.com.au>
Date: Mon, 18 Feb 2013 17:31:49 +1000
Subject: TDISP to take ROWS and COLUMNS from board file

TDISP to take ROWS and COLUMNS from board file
---
 drivers/tdisp/HD44780/tdisp_lld.c               | 328 ++++++++++++------------
 drivers/tdisp/HD44780/tdisp_lld_board_example.h | 109 ++++----
 2 files changed, 225 insertions(+), 212 deletions(-)

(limited to 'drivers')

diff --git a/drivers/tdisp/HD44780/tdisp_lld.c b/drivers/tdisp/HD44780/tdisp_lld.c
index 8a9c886f..32b2b8c9 100644
--- a/drivers/tdisp/HD44780/tdisp_lld.c
+++ b/drivers/tdisp/HD44780/tdisp_lld.c
@@ -1,164 +1,164 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld.c
- * @brief   TDISP driver subsystem low level driver source for the HD44780 display
- *
- * @addtogroup TDISP
- * @{
- */
-
-#include "ch.h"
-#include "hal.h"
-#include "gfx.h"
-
-#if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/
-
-/* The user may override the default display size */
-#ifndef TDISP_COLUMNS
-	#define TDISP_COLUMNS		16
-#endif
-#ifndef TDISP_ROWS
-	#define TDISP_ROWS			2
-#endif
-
-/* Controller Specific Properties */
-#define CUSTOM_CHAR_COUNT		8
-#define CUSTOM_CHAR_XBITS		5
-#define CUSTOM_CHAR_YBITS		8
-
-/* Define the properties of our controller */
-tdispStruct	TDISP = {
-		TDISP_COLUMNS, TDISP_ROWS,				/* cols, rows */
-		CUSTOM_CHAR_XBITS, CUSTOM_CHAR_YBITS,	/* charBitsX, charBitsY */
-		CUSTOM_CHAR_COUNT						/* maxCustomChars */
-		};
-
-/* Include the hardware interface details */
-#if defined(TDISP_USE_CUSTOM_BOARD) && TDISP_USE_CUSTOM_BOARD
-	/* Include the user supplied board definitions */
-	#include "tdisp_lld_board.h"
-#elif defined(BOARD_UNKNOWN)
-	#include "gdisp_lld_board_unknown.h"
-#else
-	/* Include the user supplied board definitions */
-	#include "gdisp_lld_board.h"
-#endif
-
-/* Our display control */
-#define DISPLAY_ON		0x04
-#define CURSOR_ON		0x02
-#define CURSOR_BLINK	0x01
-
-static uint8_t	displaycontrol;
-
-
-bool_t tdisp_lld_init(void) { 
-	/* initialise hardware */
-	init_board();
-
-	/* wait some time */
-	chThdSleepMilliseconds(50);
-
-	write_cmd(0x38);
-	chThdSleepMilliseconds(64);
-
-	displaycontrol = DISPLAY_ON | CURSOR_ON | CURSOR_BLINK;		// The default displaycontrol
-	write_cmd(0x08 | displaycontrol);
-	chThdSleepMicroseconds(50);
-
-	write_cmd(0x01);					// Clear the screen
-	chThdSleepMilliseconds(5);
-
-	write_cmd(0x06);
-	chThdSleepMicroseconds(50);
-
-	return TRUE;
-}
-
-void tdisp_lld_clear(void) {
-	write_cmd(0x01);
-}
-
-void tdisp_lld_draw_char(char c) {
-	write_data(c);
-}
-
-void tdisp_lld_set_cursor(coord_t col, coord_t row) {
-	static const uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
-
-	/*
-	 *  Short-cut:
-	 *
-	 *  If x and y = 0 then use the home command.
-	 *
-	 *  Note: There is probably no advantage as both commands are a single byte
-	 */
-//	if (col == 0 && row == 0) {
-//		write_cmd(0x02);
-//		return;
-//	}
-
-	write_cmd(0x80 | (col + row_offsets[row]));
-}
-
-void tdisp_lld_create_char(uint8_t address, uint8_t *charmap) {
-	int i;
-
-	write_cmd(0x40 | (address << 3));
-	for(i = 0; i < CUSTOM_CHAR_YBITS; i++)
-		write_data(charmap[i]);
-}
-
-void tdisp_lld_control(uint16_t what, void *value) {
-	switch(what) {
-		case TDISP_CTRL_BACKLIGHT:
-			if ((uint8_t)value)
-				displaycontrol |= DISPLAY_ON;
-			else
-				displaycontrol &= ~DISPLAY_ON;
-			write_cmd(0x08 | displaycontrol);
-			break;
-		case TDISP_CTRL_CURSOR:
-			switch((cursorshape)value) {
-			case cursorOff:
-				displaycontrol &= ~CURSOR_ON;
-				break;
-			case cursorBlock:
-			case cursorUnderline:
-			case cursorBar:
-				displaycontrol = (displaycontrol | CURSOR_ON) & ~CURSOR_BLINK;
-				break;
-			case cursorBlinkingBlock:
-			case cursorBlinkingUnderline:
-			case cursorBlinkingBar:
-			default:
-				displaycontrol |= (CURSOR_ON | CURSOR_BLINK);
-				break;
-			}
-			write_cmd(0x08 | displaycontrol);
-			break;
-	}
-}
-
-#endif /* GFX_USE_TDISP */
-/** @} */
-
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/tdisp/HD44780/tdisp_lld.c
+ * @brief   TDISP driver subsystem low level driver source for the HD44780 display
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_TDISP /*|| defined(__DOXYGEN__)*/
+
+/* Include the hardware interface details */
+#if defined(TDISP_USE_CUSTOM_BOARD) && TDISP_USE_CUSTOM_BOARD
+	/* Include the user supplied board definitions */
+	#include "tdisp_lld_board.h"
+#elif defined(BOARD_UNKNOWN)
+	#include "gdisp_lld_board_unknown.h"
+#else
+	/* Include the user supplied board definitions */
+	#include "gdisp_lld_board.h"
+#endif
+
+/* The user may override the default display size */
+#ifndef TDISP_COLUMNS
+	#define TDISP_COLUMNS		16
+#endif
+#ifndef TDISP_ROWS
+	#define TDISP_ROWS			2
+#endif
+
+/* Controller Specific Properties */
+#define CUSTOM_CHAR_COUNT		8
+#define CUSTOM_CHAR_XBITS		5
+#define CUSTOM_CHAR_YBITS		8
+
+/* Define the properties of our controller */
+tdispStruct	TDISP = {
+		TDISP_COLUMNS, TDISP_ROWS,				/* cols, rows */
+		CUSTOM_CHAR_XBITS, CUSTOM_CHAR_YBITS,	/* charBitsX, charBitsY */
+		CUSTOM_CHAR_COUNT						/* maxCustomChars */
+		};
+
+/* Our display control */
+#define DISPLAY_ON		0x04
+#define CURSOR_ON		0x02
+#define CURSOR_BLINK	0x01
+
+static uint8_t	displaycontrol;
+
+
+bool_t tdisp_lld_init(void) { 
+	/* initialise hardware */
+	init_board();
+
+	/* wait some time */
+	chThdSleepMilliseconds(50);
+
+	write_cmd(0x38);
+	chThdSleepMilliseconds(64);
+
+	displaycontrol = DISPLAY_ON | CURSOR_ON | CURSOR_BLINK;		// The default displaycontrol
+	write_cmd(0x08 | displaycontrol);
+	chThdSleepMicroseconds(50);
+
+	write_cmd(0x01);					// Clear the screen
+	chThdSleepMilliseconds(5);
+
+	write_cmd(0x06);
+	chThdSleepMicroseconds(50);
+
+	return TRUE;
+}
+
+void tdisp_lld_clear(void) {
+	write_cmd(0x01);
+}
+
+void tdisp_lld_draw_char(char c) {
+	write_data(c);
+}
+
+void tdisp_lld_set_cursor(coord_t col, coord_t row) {
+	static const uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+
+	/*
+	 *  Short-cut:
+	 *
+	 *  If x and y = 0 then use the home command.
+	 *
+	 *  Note: There is probably no advantage as both commands are a single byte
+	 */
+//	if (col == 0 && row == 0) {
+//		write_cmd(0x02);
+//		return;
+//	}
+
+	write_cmd(0x80 | (col + row_offsets[row]));
+}
+
+void tdisp_lld_create_char(uint8_t address, uint8_t *charmap) {
+	int i;
+
+	write_cmd(0x40 | (address << 3));
+	for(i = 0; i < CUSTOM_CHAR_YBITS; i++)
+		write_data(charmap[i]);
+}
+
+void tdisp_lld_control(uint16_t what, void *value) {
+	switch(what) {
+		case TDISP_CTRL_BACKLIGHT:
+			if ((uint8_t)value)
+				displaycontrol |= DISPLAY_ON;
+			else
+				displaycontrol &= ~DISPLAY_ON;
+			write_cmd(0x08 | displaycontrol);
+			break;
+		case TDISP_CTRL_CURSOR:
+			switch((cursorshape)value) {
+			case cursorOff:
+				displaycontrol &= ~CURSOR_ON;
+				break;
+			case cursorBlock:
+			case cursorUnderline:
+			case cursorBar:
+				displaycontrol = (displaycontrol | CURSOR_ON) & ~CURSOR_BLINK;
+				break;
+			case cursorBlinkingBlock:
+			case cursorBlinkingUnderline:
+			case cursorBlinkingBar:
+			default:
+				displaycontrol |= (CURSOR_ON | CURSOR_BLINK);
+				break;
+			}
+			write_cmd(0x08 | displaycontrol);
+			break;
+	}
+}
+
+#endif /* GFX_USE_TDISP */
+/** @} */
+
diff --git a/drivers/tdisp/HD44780/tdisp_lld_board_example.h b/drivers/tdisp/HD44780/tdisp_lld_board_example.h
index 37463d37..1b41f0c3 100644
--- a/drivers/tdisp/HD44780/tdisp_lld_board_example.h
+++ b/drivers/tdisp/HD44780/tdisp_lld_board_example.h
@@ -1,48 +1,61 @@
-/*
-    ChibiOS/GFX - Copyright (C) 2012
-                 Joel Bodenmann aka Tectu <joel@unormal.org>
-
-    This file is part of ChibiOS/GFX.
-
-    ChibiOS/GFX is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 3 of the License, or
-    (at your option) any later version.
-
-    ChibiOS/GFX is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file    drivers/tdisp/HD44780/tdisp_lld_board_example.h
- * @brief   TDISP driver subsystem board interface for the HD44780 display
- *
- * @addtogroup TDISP
- * @{
- */
-
-#ifndef _TDISP_LLD_BOARD_H
-#define _TDISP_LLD_BOARD_H
-
-static void init_board(void) {
-	/* Code here */
-	#error "tdispHD44780: You must supply a definition for init_board for your board"
-}
-
-static void write_cmd(uint8_t data) {
-	/* Code here */
-	#error "tdispHD44780: You must supply a definition for write_cmd for your board"
-}
-
-static void write_data(uint8_t data) {
-	/* Code here */
-	#error "tdispHD44780: You must supply a definition for write_data for your board"
-}
-
-#endif /* _TDISP_LLD_BOARD_H */
-/** @} */
+/*
+    ChibiOS/GFX - Copyright (C) 2012
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/tdisp/HD44780/tdisp_lld_board_example.h
+ * @brief   TDISP driver subsystem board interface for the HD44780 display
+ *
+ * @addtogroup TDISP
+ * @{
+ */
+
+#ifndef _TDISP_LLD_BOARD_H
+#define _TDISP_LLD_BOARD_H
+
+/**
+ * The board may override the default display size.
+ * Uncomment the below if your board needs a non-standard size.
+ */
+/*
+#ifndef TDISP_COLUMNS
+	#define TDISP_COLUMNS		16
+#endif
+#ifndef TDISP_ROWS
+	#define TDISP_ROWS			2
+#endif
+*/
+
+static void init_board(void) {
+	/* Code here */
+	#error "tdispHD44780: You must supply a definition for init_board for your board"
+}
+
+static void write_cmd(uint8_t data) {
+	/* Code here */
+	#error "tdispHD44780: You must supply a definition for write_cmd for your board"
+}
+
+static void write_data(uint8_t data) {
+	/* Code here */
+	#error "tdispHD44780: You must supply a definition for write_data for your board"
+}
+
+#endif /* _TDISP_LLD_BOARD_H */
+/** @} */
-- 
cgit v1.2.3


From 9bec5967b293d6c23c9d7e9338d8ece4873f6eac Mon Sep 17 00:00:00 2001
From: Andrew Hannam <andrewh@inmarket.com.au>
Date: Mon, 18 Feb 2013 17:33:35 +1000
Subject: GADC implementation with demo program

Also includes driver for AT91SAM7 cpu
---
 drivers/gadc/AT91SAM7/gadc_lld.c                   | 102 +++++++++++++++++++++
 drivers/gadc/AT91SAM7/gadc_lld.mk                  |   5 +
 .../gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h |  46 ++++++++++
 drivers/gadc/AT91SAM7/gadc_lld_config.h            |  78 ++++++++++++++++
 4 files changed, 231 insertions(+)
 create mode 100644 drivers/gadc/AT91SAM7/gadc_lld.c
 create mode 100644 drivers/gadc/AT91SAM7/gadc_lld.mk
 create mode 100644 drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
 create mode 100644 drivers/gadc/AT91SAM7/gadc_lld_config.h

(limited to 'drivers')

diff --git a/drivers/gadc/AT91SAM7/gadc_lld.c b/drivers/gadc/AT91SAM7/gadc_lld.c
new file mode 100644
index 00000000..4b3c6cae
--- /dev/null
+++ b/drivers/gadc/AT91SAM7/gadc_lld.c
@@ -0,0 +1,102 @@
+/*
+    ChibiOS/GFX - Copyright (C) 2012, 2013
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file    include/gadc/lld/gadc_lld.c
+ * @brief   GADC - Periodic ADC driver source file for the AT91SAM7 cpu.
+ *
+ * @defgroup Driver Driver
+ * @ingroup GADC
+ * @{
+ */
+
+#include "ch.h"
+#include "hal.h"
+#include "gfx.h"
+
+#if GFX_USE_GADC
+
+#include "gadc/lld/gadc_lld.h"
+
+static ADCConversionGroup acg = {
+		FALSE,					// circular
+		1,						// num_channels
+		GADC_ISR_CompleteI,		// end_cb
+		GADC_ISR_ErrorI,		// error_cb
+		0,						// channelselects
+		0,						// trigger
+		0,						// frequency
+		};
+
+void gadc_lld_init(void) {
+	adcStart(&ADCD1, NULL);
+}
+
+size_t gadc_lld_samples_per_conversion(uint32_t physdev) {
+	size_t	cnt;
+	int		i;
+
+	/* The AT91SAM7 has AD0..7 - physdev is a bitmap of those channels */
+	for(cnt = 0, i = 0; i < 8; i++, physdev >>= 1)
+		if (physdev & 0x01)
+			cnt++;
+	return cnt;
+}
+
+void gadc_lld_start_timer(uint32_t physdev, uint32_t frequency) {
+	(void) physdev;
+	/**
+	 * The AT91SAM7 ADC driver supports triggering the ADC using a timer without having to implement
+	 * an interrupt handler for the timer. The driver also initialises the timer correctly for us.
+	 * Because we aren't trapping the interrupt ourselves we can't increment GADC_Timer_Missed if an
+	 * interrupt is missed.
+	 */
+	acg.frequency = frequency;
+}
+
+void gadc_lld_stop_timer(uint32_t physdev) {
+	(void) physdev;
+	if ((acg.trigger & ~ADC_TRIGGER_SOFTWARE) == ADC_TRIGGER_TIMER)
+		adcStop(&ADCD1);
+}
+
+void gadc_lld_adc_timerI(GadcLldTimerData *pgtd) {
+	/**
+	 *  We don't need to calculate num_channels because the AT91SAM7 ADC does this for us.
+	 */
+	acg.channelselects = pgtd->physdev;
+	acg.trigger = pgtd->now ? (ADC_TRIGGER_TIMER|ADC_TRIGGER_SOFTWARE) : ADC_TRIGGER_TIMER;
+
+	adcStartConversionI(&ADCD1, &acg, pgtd->buffer, pgtd->count);
+
+	/* Next time assume the same (still running) timer */
+	acg.frequency = 0;
+}
+
+void gadc_lld_adc_nontimerI(GadcLldNonTimerData *pgntd) {
+	/**
+	 *  We don't need to calculate num_channels because the AT91SAM7 ADC does this for us.
+	 */
+	acg.channelselects = pgntd->physdev;
+	acg.trigger = ADC_TRIGGER_SOFTWARE;
+	adcStartConversionI(&ADCD1, &acg, pgntd->buffer, 1);
+}
+
+#endif /* GFX_USE_GADC */
+/** @} */
diff --git a/drivers/gadc/AT91SAM7/gadc_lld.mk b/drivers/gadc/AT91SAM7/gadc_lld.mk
new file mode 100644
index 00000000..001d44b1
--- /dev/null
+++ b/drivers/gadc/AT91SAM7/gadc_lld.mk
@@ -0,0 +1,5 @@
+# List the required driver.
+GFXSRC += $(GFXLIB)/drivers/gadc/AT91SAM7/gadc_lld.c
+
+# Required include directories
+GFXINC += $(GFXLIB)/drivers/gadc/AT91SAM7
diff --git a/drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h b/drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
new file mode 100644
index 00000000..6f23db17
--- /dev/null
+++ b/drivers/gadc/AT91SAM7/gadc_lld_board_olimexsam7ex256.h
@@ -0,0 +1,46 @@
+/*
+    ChibiOS/GFX - Copyright (C) 2012, 2013
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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_config.h b/drivers/gadc/AT91SAM7/gadc_lld_config.h
new file mode 100644
index 00000000..882573c8
--- /dev/null
+++ b/drivers/gadc/AT91SAM7/gadc_lld_config.h
@@ -0,0 +1,78 @@
+/*
+    ChibiOS/GFX - Copyright (C) 2012, 2013
+                 Joel Bodenmann aka Tectu <joel@unormal.org>
+
+    This file is part of ChibiOS/GFX.
+
+    ChibiOS/GFX is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    ChibiOS/GFX is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file    drivers/gadc/AT91SAM7/gadc_lld_config.h
+ * @brief   GADC Driver config file.
+ *
+ * @addtogroup GADC
+ * @{
+ */
+
+#ifndef GADC_LLD_CONFIG_H
+#define GADC_LLD_CONFIG_H
+
+#if GFX_USE_GADC
+
+/*===========================================================================*/
+/* Driver hardware support.                                                  */
+/*===========================================================================*/
+
+/**
+ * @brief	ChibiOS has a nasty bug in its _adc_isr_full_code() routine (defined in adc.h as a macro).
+ * 			Do we have the version of ChibiOS with this bug.
+ * @detail	Set to TRUE if ChibiOS has this bug.
+ * @note	Fixed in ChibiOS 2.4.4stable and 2.5.2unstable (and the repository from 18th Feb 2013)
+ * @note	This bug prevents us re-calling adcStartConversionI() from with the ISR even though
+ * 			it is clearly designed to handle it. For some reason (on this micro) the high speed timer
+ * 			is not affected only the single sample low speed timer. In that situation we wait until
+ * 			we get back to thread land. This is terrible for the accuracy of the high speed timer
+ * 			but what can we do (other than fix the bug).
+ * @note	For the AT91SAM7 ADC driver, it post-dates the finding of the bug so we safely
+ * 			say that the bug doesn't exist for this driver.
+ */
+#define ADC_ISR_FULL_CODE_BUG				FALSE
+
+/**
+ * @brief	The maximum sample frequency supported by this CPU
+ */
+#define GADC_MAX_SAMPLE_FREQUENCY			132000
+
+/**
+ * @brief	The number of bits in a sample
+ */
+#define GADC_BITS_PER_SAMPLE				AT91_ADC1_RESOLUTION
+
+/* 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
+
+#endif	/* GFX_USE_GADC */
+
+#endif	/* _GDISP_LLD_CONFIG_H */
+/** @} */
+
-- 
cgit v1.2.3