A simple yet powerful library for controlling graphical displays. Multiple display controllers are supported using inheritance.

Dependents:   mbed_rifletool Hexi_Bubble_Game Hexi_Catch-the-dot_Game Hexi_Acceleromagnetic_Synth

NOTE: This library is in beta right now. As far as I know, everything here works, but there are many features that are lacking so far. Most notably containers, button handling, and display drivers other than the SSD1306.

Files at this revision

API Documentation at this revision

Comitter:
neilt6
Date:
Fri Mar 14 19:17:44 2014 +0000
Parent:
0:b876cf091464
Child:
2:bbfc18022ee5
Commit message:
Added rudimentary ILI9341 support, and SPI support for SSD1306

Changed in this revision

Abstracts/Canvas.cpp Show annotated file Show diff for this revision Revisions of this file
Abstracts/Canvas.h Show annotated file Show diff for this revision Revisions of this file
Abstracts/Control.cpp Show annotated file Show diff for this revision Revisions of this file
Abstracts/Control.h Show annotated file Show diff for this revision Revisions of this file
Abstracts/Display.cpp Show annotated file Show diff for this revision Revisions of this file
Abstracts/Display.h Show annotated file Show diff for this revision Revisions of this file
Abstracts/Image.cpp Show annotated file Show diff for this revision Revisions of this file
Abstracts/Image.h Show annotated file Show diff for this revision Revisions of this file
Controls/TextBox.cpp Show annotated file Show diff for this revision Revisions of this file
Controls/TextBox.h Show annotated file Show diff for this revision Revisions of this file
Decoders/BitmapImage.cpp Show annotated file Show diff for this revision Revisions of this file
Decoders/BitmapImage.h Show annotated file Show diff for this revision Revisions of this file
Decoders/Font.cpp Show annotated file Show diff for this revision Revisions of this file
Decoders/Font.h Show annotated file Show diff for this revision Revisions of this file
Drivers/ILI9341.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/ILI9341.h Show annotated file Show diff for this revision Revisions of this file
Drivers/SSD1306.cpp Show diff for this revision Revisions of this file
Drivers/SSD1306.h Show diff for this revision Revisions of this file
Drivers/SSD1306_I2C.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/SSD1306_I2C.h Show annotated file Show diff for this revision Revisions of this file
Drivers/SSD1306_SPI.cpp Show annotated file Show diff for this revision Revisions of this file
Drivers/SSD1306_SPI.h Show annotated file Show diff for this revision Revisions of this file
NeatGUI.h Show annotated file Show diff for this revision Revisions of this file
--- a/Abstracts/Canvas.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Canvas.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -276,7 +276,7 @@
     fillCircleHelper(x+r, y + r, r, 2, h - 2 * r - 1, c);
 }
 
-void Canvas::drawImage(Image *img, int x, int y)
+void Canvas::drawImage(Image* img, int x, int y)
 {
     for (int j = 0; j < img->height(); j++) {
         for (int i = 0; i < img->width(); i++) {
@@ -285,7 +285,7 @@
     }
 }
 
-int Canvas::drawChar(char c, Font *fnt, int x, int y)
+int Canvas::drawChar(char c, Font* fnt, int x, int y)
 {
     //Get the character glyph
     BitmapImage glyph = fnt->glyph(c);
@@ -297,7 +297,7 @@
     return glyph.width();
 }
 
-void Canvas::drawString(const char *str, Font *fnt, int x, int y)
+void Canvas::drawString(const char* str, Font* fnt, int x, int y)
 {
     int cursX = 0;
     int cursY = 0;
@@ -326,7 +326,7 @@
     }
 }
 
-void Canvas::drawString(const char *str, Font *fnt, int x, int y, int w, int h)
+void Canvas::drawString(const char* str, Font* fnt, int x, int y, int w, int h)
 {
     int cursX = 0;
     int cursY = 0;
@@ -419,12 +419,12 @@
     }
 }
 
-int Canvas::width(void)
+int Canvas::width()
 {
     return m_Width;
 }
 
-int Canvas::height(void)
+int Canvas::height()
 {
     return m_Height;
 }
--- a/Abstracts/Canvas.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Canvas.h	Fri Mar 14 19:17:44 2014 +0000
@@ -166,7 +166,7 @@
      * @param x The starting X coordinate.
      * @param y The starting Y coordinate.
      */
-    void drawImage(Image *img, int x, int y);
+    void drawImage(Image* img, int x, int y);
 
     /** Draw a character at the specified coordinates without wrapping
      *
@@ -177,7 +177,7 @@
      *
      * @returns The width of the drawn character.
      */
-    int drawChar(char c, Font *fnt, int x, int y);
+    int drawChar(char c, Font* fnt, int x, int y);
 
     /** Draw a string at the specified coordinates without wrapping
      *
@@ -186,7 +186,7 @@
      * @param x The starting X coordinate.
      * @param y The starting Y coordinate.
      */
-    void drawString(const char *str, Font *fnt, int x, int y);
+    void drawString(const char* str, Font* fnt, int x, int y);
 
     /** Draw a string within the specified rectangle with wrapping
      *
@@ -197,19 +197,19 @@
      * @param w The width of the bounding rectangle.
      * @param h The height of the bounding rectangle.
      */
-    void drawString(const char *str, Font *fnt, int x, int y, int w, int h);
+    void drawString(const char* str, Font* fnt, int x, int y, int w, int h);
 
     /** Get the width of the canvas
      *
      * @returns The width of the canvas.
      */
-    int width(void);
+    int width();
 
     /** Get the height of the canvas
      *
      * @returns The height of the canvas.
      */
-    int height(void);
+    int height();
 
 protected:
     //The canvas width/height
--- a/Abstracts/Control.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Control.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -32,7 +32,7 @@
     m_Invalid = true;
 }
 
-void Control::paint(Canvas *canvas)
+void Control::paint(Canvas* canvas)
 {
     //Fill the control's content and padding area
     canvas->fillRect(contentPosX() - m_Padding, contentPosY() - m_Padding , contentWidth() + m_Padding * 2, contentHeight() + m_Padding * 2, m_BgColor);
@@ -49,7 +49,7 @@
     m_Invalid = false;
 }
 
-int Control::posX(void)
+int Control::posX()
 {
     return m_X;
 }
@@ -63,7 +63,7 @@
     m_Invalid = true;
 }
 
-int Control::posY(void)
+int Control::posY()
 {
     return m_Y;
 }
@@ -77,7 +77,7 @@
     m_Invalid = true;
 }
 
-int Control::width(void)
+int Control::width()
 {
     return m_Width;
 }
@@ -91,7 +91,7 @@
     m_Invalid = true;
 }
 
-int Control::height(void)
+int Control::height()
 {
     return m_Height;
 }
@@ -105,7 +105,7 @@
     m_Invalid = true;
 }
 
-int Control::margin(void)
+int Control::margin()
 {
     return m_Margin;
 }
@@ -119,7 +119,7 @@
     m_Invalid = true;
 }
 
-int Control::border(void)
+int Control::border()
 {
     return m_Border;
 }
@@ -133,7 +133,7 @@
     m_Invalid = true;
 }
 
-int Control::padding(void)
+int Control::padding()
 {
     return m_Padding;
 }
@@ -147,27 +147,27 @@
     m_Invalid = true;
 }
 
-int Control::contentPosX(void)
+int Control::contentPosX()
 {
     return m_X + m_Margin + m_Border + m_Padding;
 }
 
-int Control::contentPosY(void)
+int Control::contentPosY()
 {
     return m_Y + m_Margin + m_Border + m_Padding;
 }
 
-int Control::contentWidth(void)
+int Control::contentWidth()
 {
     return m_Width - (m_Margin + m_Border + m_Padding) * 2;
 }
 
-int Control::contentHeight(void)
+int Control::contentHeight()
 {
     return m_Height - (m_Margin + m_Border + m_Padding) * 2;
 }
 
-unsigned int Control::foreColor(void)
+unsigned int Control::foreColor()
 {
     return m_FgColor;
 }
@@ -181,7 +181,7 @@
     m_Invalid = true;
 }
 
-unsigned int Control::backColor(void)
+unsigned int Control::backColor()
 {
     return m_BgColor;
 }
@@ -195,12 +195,12 @@
     m_Invalid = true;
 }
 
-const char *Control::text(void)
+const char* Control::text()
 {
     return m_Text;
 }
 
-void Control::text(const char *text)
+void Control::text(const char* text)
 {
     //Update the value
     m_Text = text;
@@ -209,12 +209,12 @@
     m_Invalid = true;
 }
 
-Font *Control::font(void)
+Font* Control::font()
 {
     return m_Font;
 }
 
-void Control::font(Font *fnt)
+void Control::font(Font* fnt)
 {
     //Update the value
     m_Font = fnt;
@@ -223,12 +223,12 @@
     m_Invalid = true;
 }
 
-bool Control::invalid(void)
+bool Control::invalid()
 {
     return m_Invalid;
 }
 
-void Control::invalidate(void)
+void Control::invalidate()
 {
     m_Invalid = true;
 }
--- a/Abstracts/Control.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Control.h	Fri Mar 14 19:17:44 2014 +0000
@@ -45,7 +45,7 @@
      *
      * @returns The X coordinate of the control.
      */
-    int posX(void);
+    int posX();
 
     /** Set the X coordinate of the control
     *
@@ -57,7 +57,7 @@
      *
      * @returns The Y coordinate of the control.
      */
-    int posY(void);
+    int posY();
 
     /** Set the Y coordinate of the control
     *
@@ -69,7 +69,7 @@
      *
      * @returns The width of the control.
      */
-    int width(void);
+    int width();
 
     /** Set the width of the control
     *
@@ -81,7 +81,7 @@
      *
      * @returns The height of the control.
      */
-    int height(void);
+    int height();
 
     /** Set the height of the control
     *
@@ -93,7 +93,7 @@
      *
      * @returns The current margin width.
      */
-    int margin(void);
+    int margin();
 
     /** Set the margin width
     *
@@ -105,7 +105,7 @@
      *
      * @returns The current border width.
      */
-    int border(void);
+    int border();
 
     /** Set the border width
     *
@@ -117,7 +117,7 @@
      *
      * @returns The current padding width.
      */
-    int padding(void);
+    int padding();
 
     /** Set the padding width
     *
@@ -129,31 +129,31 @@
      *
      * @returns The X coordinate of the control's content area.
      */
-    int contentPosX(void);
+    int contentPosX();
 
     /** Get the Y coordinate of the control's content area
      *
      * @returns The Y coordinate of the control's content area.
      */
-    int contentPosY(void);
+    int contentPosY();
 
     /** Get the width of the control's content area
      *
      * @returns The width of the control's content area.
      */
-    int contentWidth(void);
+    int contentWidth();
 
     /** Get the height of the control's content area
      *
      * @returns The height of the control's content area.
      */
-    int contentHeight(void);
+    int contentHeight();
 
     /** Get the foreground color
     *
     * @returns The foreground color as a 32-bit ARGB value.
     */
-    unsigned int foreColor(void);
+    unsigned int foreColor();
 
     /** Set the foreground color
     *
@@ -165,7 +165,7 @@
     *
     * @returns The background color as a 32-bit ARGB value.
     */
-    unsigned int backColor(void);
+    unsigned int backColor();
 
     /** Set the background color
     *
@@ -177,41 +177,41 @@
      *
      * @returns The current text of the control.
      */
-    const char *text(void);
+    const char* text();
 
     /** Set the text of the control
     *
     * @param text The new text.
     */
-    void text(const char *text);
+    void text(const char* text);
 
     /** Get the current font of the control
      *
      * @returns The current font of the control.
      */
-    Font *font(void);
+    Font* font();
 
     /** Set the font of the control
     *
     * @param fnt The new font.
     */
-    void font(Font *fnt);
+    void font(Font* fnt);
 
     /** Determine whether the control needs to be repainted
      *
      * @returns Whether or not the control needs to be repainted.
      */
-    bool invalid(void);
+    bool invalid();
 
     /** Mark this control as invalid
      */
-    void invalidate(void);
+    void invalidate();
 
 protected:
     int m_X, m_Y, m_Width, m_Height, m_Margin, m_Border, m_Padding;
     unsigned int m_FgColor, m_BgColor;
-    const char *m_Text;
-    Font *m_Font;
+    const char* m_Text;
+    Font* m_Font;
     bool m_Invalid;
 };
 
--- a/Abstracts/Display.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Display.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -21,12 +21,12 @@
     m_State = NOT_INITIALIZED;
 }
 
-void Display::finalize(void)
+void Display::finalize()
 {
     //Do nothing by default, the super class should override this if needed
 }
 
-Display::State Display::state(void)
+Display::State Display::state()
 {
     //Return the display's state
     return m_State;
--- a/Abstracts/Display.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Display.h	Fri Mar 14 19:17:44 2014 +0000
@@ -47,17 +47,17 @@
      *   'true' if the device exists on the bus,
      *   'false' if the device doesn't exist on the bus.
      */
-    virtual bool open(void) = 0;
+    virtual bool open() = 0;
 
     /** Finalize any writes to the Display
      */
-    virtual void finalize(void);
+    virtual void finalize();
 
     /** Get the current state of the Display
      *
      * @returns The current state as a State enum.
      */
-    virtual Display::State state(void);
+    virtual Display::State state();
 
     /** Set the state of the Display
      *
--- a/Abstracts/Image.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Image.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -22,12 +22,12 @@
     m_Height = h;
 }
 
-int Image::width(void)
+int Image::width()
 {
     return m_Width;
 }
 
-int Image::height(void)
+int Image::height()
 {
     return m_Height;
 }
--- a/Abstracts/Image.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Abstracts/Image.h	Fri Mar 14 19:17:44 2014 +0000
@@ -45,13 +45,13 @@
      *
      * @returns The image width.
      */
-    int width(void);
+    int width();
 
     /** Get the image height
      *
      * @returns The image height.
      */
-    int height(void);
+    int height();
 
 protected:
     //The image width/height
--- a/Controls/TextBox.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Controls/TextBox.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -26,7 +26,7 @@
     backColor(0xFF000000);
 }
 
-void TextBox::paint(Canvas *canvas)
+void TextBox::paint(Canvas* canvas)
 {
     //Paint the base class
     Control::paint(canvas);
--- a/Controls/TextBox.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Controls/TextBox.h	Fri Mar 14 19:17:44 2014 +0000
@@ -41,7 +41,7 @@
     *
     * @param canvas Pointer to the canvas to paint on.
     */
-    virtual void paint(Canvas *canvas);
+    virtual void paint(Canvas* canvas);
 };
 
 #endif
--- a/Decoders/BitmapImage.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Decoders/BitmapImage.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -16,21 +16,21 @@
 
 #include "BitmapImage.h"
 
-BitmapImage::BitmapImage(const char *table) : Image(table[0] * 0xFF + table[1], table[2] * 0xFF + table[3])
+BitmapImage::BitmapImage(const char* table) : Image(table[0] * 0xFF + table[1], table[2] * 0xFF + table[3])
 {
     m_ImageTable = table;
     m_FgColor = 0xFFFFFFFF;
     m_BgColor = 0x00000000;
 }
 
-BitmapImage::BitmapImage(const char *table, unsigned int fg_color) : Image(table[0] * 0xFF + table[1], table[2] * 0xFF + table[3])
+BitmapImage::BitmapImage(const char* table, unsigned int fg_color) : Image(table[0] * 0xFF + table[1], table[2] * 0xFF + table[3])
 {
     m_ImageTable = table;
     m_FgColor = fg_color;
     m_BgColor = 0x00000000;
 }
 
-BitmapImage::BitmapImage(const char *table, unsigned int fg_color, unsigned int bg_color) : Image(table[0] * 0xFF + table[1], table[2] * 0xFF + table[3])
+BitmapImage::BitmapImage(const char* table, unsigned int fg_color, unsigned int bg_color) : Image(table[0] * 0xFF + table[1], table[2] * 0xFF + table[3])
 {
     m_ImageTable = table;
     m_FgColor = fg_color;
@@ -58,7 +58,7 @@
         return m_BgColor;
 }
 
-unsigned int BitmapImage::foreground(void)
+unsigned int BitmapImage::foreground()
 {
     return m_FgColor;
 }
@@ -68,7 +68,7 @@
     m_FgColor = c;
 }
 
-unsigned int BitmapImage::background(void)
+unsigned int BitmapImage::background()
 {
     return m_BgColor;
 }
@@ -78,7 +78,7 @@
     m_BgColor = c;
 }
 
-int BitmapImage::bytesPerLine(void)
+int BitmapImage::bytesPerLine()
 {
     int bpl;
 
--- a/Decoders/BitmapImage.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Decoders/BitmapImage.h	Fri Mar 14 19:17:44 2014 +0000
@@ -30,14 +30,14 @@
      *
      * @param table Pointer to the image table.
      */
-    BitmapImage(const char *table);
+    BitmapImage(const char* table);
 
     /** Create a BitmapImage object from the specified image table with the specified foreground, and an alpha background
      *
      * @param table Pointer to the image table.
      * @param fg_color The foreground color as a 32-bit ARGB value.
      */
-    BitmapImage(const char *table, unsigned int fg_color);
+    BitmapImage(const char* table, unsigned int fg_color);
 
     /** Create a BitmapImage object from the specified image table with the specified foreground and background colors
      *
@@ -45,7 +45,7 @@
      * @param fg_color The foreground color as a 32-bit ARGB value.
      * @param bg_color The background color as a 32-bit ARGB value.
      */
-    BitmapImage(const char *table, unsigned int fg_color, unsigned int bg_color);
+    BitmapImage(const char* table, unsigned int fg_color, unsigned int bg_color);
 
     /** Get the pixel at the specified coordinates
     *
@@ -60,7 +60,7 @@
     *
     * @returns The foreground color as a 32-bit ARGB value.
     */
-    unsigned int foreground(void);
+    unsigned int foreground();
 
     /** Set the foreground color
     *
@@ -72,7 +72,7 @@
     *
     * @returns The background color as a 32-bit ARGB value.
     */
-    unsigned int background(void);
+    unsigned int background();
 
     /** Set the background color
     *
@@ -82,12 +82,12 @@
 
 protected:
     //Pointer to the image table
-    const char *m_ImageTable;
+    const char* m_ImageTable;
 
     //The foreground and background colors
     unsigned int m_FgColor, m_BgColor;
 
-    int bytesPerLine(void);
+    int bytesPerLine();
 };
 
 #endif
--- a/Decoders/Font.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ b/Decoders/Font.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -16,13 +16,13 @@
 
 #include "Font.h"
 
-Font::Font(const char *table)
+Font::Font(const char* table)
 {
     m_FontTable = table;
     m_Color = 0xFFFFFFFF;
 }
 
-Font::Font(const char *table, unsigned int color)
+Font::Font(const char* table, unsigned int color)
 {
     m_FontTable = table;
     m_Color = color;
@@ -48,7 +48,7 @@
     }
 }
 
-unsigned int Font::color(void)
+unsigned int Font::color()
 {
     return m_Color;
 }
@@ -58,12 +58,12 @@
     m_Color = c;
 }
 
-int Font::height(void)
+int Font::height()
 {
     return m_FontTable[1];
 }
 
-int Font::measureString(const char *str)
+int Font::measureString(const char* str)
 {
     int i = 0;
     int slen = 0;
@@ -77,7 +77,7 @@
     return slen;
 }
 
-int Font::measureWord(const char *str)
+int Font::measureWord(const char* str)
 {
     int i = 0;
     int wlen = 0;
--- a/Decoders/Font.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/Decoders/Font.h	Fri Mar 14 19:17:44 2014 +0000
@@ -30,14 +30,14 @@
      *
      * @param table Pointer to the font table.
      */
-    Font(const char *table);
+    Font(const char* table);
 
     /** Create a Font object with the specified color
      *
      * @param table Pointer to the font table.
      * @param color Color for the font as a 32-bit ARGB value.
      */
-    Font(const char *table, unsigned int color);
+    Font(const char* table, unsigned int color);
 
     /** Get the glyph Image for the specified character
      *
@@ -49,7 +49,7 @@
      *
      * @returns The current Font color as a 32-bit ARGB value.
      */
-    unsigned int color(void);
+    unsigned int color();
 
     /** Set the Font color
      *
@@ -61,7 +61,7 @@
      *
      * @returns The height of the Font glyphs.
      */
-    int height(void);
+    int height();
 
     /** Measures the width of a string in pixels if drawn with this font
      *
@@ -69,7 +69,7 @@
      *
      * @returns The width of the string in pixels.
      */
-    int measureString(const char *str);
+    int measureString(const char* str);
 
     /** Measures the width of the next word in a string (separated by whitespace) in pixels if drawn with this font
      *
@@ -77,10 +77,10 @@
      *
      * @returns The width of the next word in pixels.
      */
-    int measureWord(const char *str);
+    int measureWord(const char* str);
 
 protected:
-    const char *m_FontTable;
+    const char* m_FontTable;
     unsigned int m_Color;
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/ILI9341.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -0,0 +1,283 @@
+/* NeatGUI Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ILI9341.h"
+
+ILI9341::ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc) : Display(240, 320), m_SPI(mosi, miso, sclk), m_CS(cs), m_DC(dc)
+{
+    //Set the control pins to a known state
+    m_CS = 1;
+    m_DC = 1;
+
+    //Set the SPI format to 8-bit
+    m_SPI.format(8, 3);
+
+    //Set the SPI frequency to 10MHz
+    m_SPI.frequency(10000000);
+}
+
+bool ILI9341::open()
+{
+    writeCommand(0x01);
+    wait_ms(5);
+
+    writeCommand(0xCF);
+    writeData8(0x00);
+    writeData8(0x8B);
+    writeData8(0X30);
+
+    writeCommand(0xED);
+    writeData8(0x67);
+    writeData8(0x03);
+    writeData8(0X12);
+    writeData8(0X81);
+
+    writeCommand(0xE8);
+    writeData8(0x85);
+    writeData8(0x10);
+    writeData8(0x7A);
+
+    writeCommand(0xCB);
+    writeData8(0x39);
+    writeData8(0x2C);
+    writeData8(0x00);
+    writeData8(0x34);
+    writeData8(0x02);
+
+    writeCommand(0xF7);
+    writeData8(0x20);
+
+    writeCommand(0xEA);
+    writeData8(0x00);
+    writeData8(0x00);
+
+    writeCommand(0xC0);                                                      /* Power control                */
+    writeData8(0x1B);                                                   /* VRH[5:0]                     */
+
+    writeCommand(0xC1);                                                      /* Power control                */
+    writeData8(0x10);                                                   /* SAP[2:0];BT[3:0]             */
+
+    writeCommand(0xC5);                                                      /* VCM control                  */
+    writeData8(0x3F);
+    writeData8(0x3C);
+
+    writeCommand(0xC7);                                                      /* VCM control2                 */
+    writeData8(0XB7);
+
+    writeCommand(0x36);                                                      /* Memory Access Control        */
+    writeData8(0x08);
+
+    writeCommand(0x3A);
+    writeData8(0x55);
+
+    writeCommand(0xB1);
+    writeData8(0x00);
+    writeData8(0x1B);
+
+    writeCommand(0xB6);                                                      /* Display Function Control     */
+    writeData8(0x0A);
+    writeData8(0xA2);
+
+
+    writeCommand(0xF2);                                                      /* 3Gamma Function Disable      */
+    writeData8(0x00);
+
+    writeCommand(0x26);                                                      /* Gamma curve selected         */
+    writeData8(0x01);
+
+    writeCommand(0xE0);                                                      /* Set Gamma                    */
+    writeData8(0x0F);
+    writeData8(0x2A);
+    writeData8(0x28);
+    writeData8(0x08);
+    writeData8(0x0E);
+    writeData8(0x08);
+    writeData8(0x54);
+    writeData8(0XA9);
+    writeData8(0x43);
+    writeData8(0x0A);
+    writeData8(0x0F);
+    writeData8(0x00);
+    writeData8(0x00);
+    writeData8(0x00);
+    writeData8(0x00);
+
+    writeCommand(0XE1);                                                      /* Set Gamma                    */
+    writeData8(0x00);
+    writeData8(0x15);
+    writeData8(0x17);
+    writeData8(0x07);
+    writeData8(0x11);
+    writeData8(0x06);
+    writeData8(0x2B);
+    writeData8(0x56);
+    writeData8(0x3C);
+    writeData8(0x05);
+    writeData8(0x10);
+    writeData8(0x0F);
+    writeData8(0x3F);
+    writeData8(0x3F);
+    writeData8(0x0F);
+
+    writeCommand(0x11);                                                      /* Exit Sleep                   */
+    wait_ms(120);
+    writeCommand(0x29);                                                      /* Display on                   */
+
+    //Probe for the ILI9341 using a Zero Length Transfer
+    /*if (!m_I2C.write(m_Addr, NULL, 0)) {
+        //Init sequence for 128x64 OLED module
+        writeCommand(CMD_DISPLAYOFF);
+        writeCommand(CMD_SETDISPLAYCLOCKDIV);
+        writeCommand(0x80);
+        writeCommand(CMD_SETMULTIPLEX);
+        writeCommand(0x3F);
+        writeCommand(CMD_SETDISPLAYOFFSET);
+        writeCommand(0x0);
+        writeCommand(CMD_SETSTARTLINE | 0x0);
+        writeCommand(CMD_CHARGEPUMP);
+        writeCommand(CMD_CHARGEPUMPON);
+        writeCommand(CMD_MEMORYMODE);
+        writeCommand(0x00);
+        writeCommand(CMD_SEGREMAP | 0x1);
+        writeCommand(CMD_COMSCANDEC);
+        writeCommand(CMD_SETCOMPINS);
+        writeCommand(0x12);
+        writeCommand(CMD_SETCONTRAST);
+        writeCommand(0xCF);
+        writeCommand(CMD_SETPRECHARGE);
+        writeCommand(0xF1);
+        writeCommand(CMD_SETVCOMDETECT);
+        writeCommand(0x40);
+        writeCommand(CMD_DISPLAYALLON_RESUME);
+        writeCommand(CMD_NORMALDISPLAY);
+
+        //Return success
+        return true;
+    } else {
+        //Return failure
+        return false;
+    }*/
+
+    return true;
+}
+
+void ILI9341::finalize()
+{
+    //Select low col 0, hi col 0, line 0
+    //writeCommand(CMD_SETLOWCOLUMN | 0x0);
+    //writeCommand(CMD_SETHIGHCOLUMN | 0x0);
+    //writeCommand(CMD_SETSTARTLINE | 0x0);
+
+    //Make sure the first byte in the buffer is the control byte
+    //m_Buffer[0] = CONTROL_DATA;
+
+    //Write the buffer
+    //m_I2C.write(m_Addr, m_Buffer, 1025);
+}
+
+Display::State ILI9341::state()
+{
+    //Return the base class's state
+    return Display::state();
+}
+
+void ILI9341::state(State s)
+{
+    //Check what the requested state is
+    if (s == Display::DISPLAY_ON) {
+        //Turn the display on
+        //writeCommand(CMD_DISPLAYON);
+    } else if (s == Display::DISPLAY_OFF) {
+        //Turn the display off
+        //writeCommand(CMD_DISPLAYOFF);
+    }
+
+    //Update the base class
+    Display::state(s);
+}
+
+void ILI9341::drawPixel(int x, int y, unsigned int c)
+{
+    //Range check the pixel
+    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
+        return;
+    
+    //TODO: Clean up this code!!!
+    
+    //Set the column
+    writeCommand(0x2A);
+    writeData16(x);
+    writeData16(x);
+    
+    //Set the page
+    writeCommand(0x2B);
+    writeData16(y);
+    writeData16(y);
+    
+    //Don't know what this does...
+    writeCommand(0x2C);
+    
+    //Woohoo, send the pixel!!!
+    writeData16(c);
+    
+    //TODO: Clean up this code!!!
+}
+
+void ILI9341::writeCommand(char command)
+{
+    //Pull DC low for Command
+    m_DC = 0;
+
+    //Pull CS low to select the TFT
+    m_CS = 0;
+
+    //Write the command byte
+    m_SPI.write(command);
+
+    //Pull CS high to end the transfer
+    m_CS = 1;
+}
+
+void ILI9341::writeData8(char data)
+{
+    //Pull DC high for Data
+    m_DC = 1;
+
+    //Pull CS low to select the TFT
+    m_CS = 0;
+
+    //Write the data byte
+    m_SPI.write(data);
+
+    //Pull CS high to end the transfer
+    m_CS = 1;
+}
+
+void ILI9341::writeData16(unsigned short data)
+{
+    //Pull DC high for Data
+    m_DC = 1;
+
+    //Pull CS low to select the TFT
+    m_CS = 0;
+
+    //Write the 2 data bytes
+    m_SPI.write((char)(data >> 8));
+    m_SPI.write((char)data);
+
+    //Pull CS high to end the transfer
+    m_CS = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/ILI9341.h	Fri Mar 14 19:17:44 2014 +0000
@@ -0,0 +1,119 @@
+/* NeatGUI Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ILI9341_H
+#define ILI9241_H
+
+#include "mbed.h"
+#include "Display.h"
+
+/** ILI9341 class.
+ *  Used for controlling an ILI9341-based TFT display.
+ */
+class ILI9341 : public Display
+{
+public:
+    /** Create an ILI9341 object connected to the specified SPI pins with the specified /CS and DC pins
+     *
+     * @param mosi The SPI data out pin.
+     * @param miso The SPI data in pin.
+     * @param sclk The SPI clock pin.
+     * @param sclk The SPI chip select pin.
+     * @param sclk The data/command pin.
+     */
+    ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc);
+
+    /** Probe for the ILI9341 and initialize it if present
+     *
+     * @returns
+     *   'true' if the device exists on the bus,
+     *   'false' if the device doesn't exist on the bus.
+     */
+    virtual bool open();
+
+    /** Send the buffer to the ILI9341
+     */
+    virtual void finalize();
+
+    /** Get the current state of the ILI9341
+     *
+     * @returns The current state as a Display::State enum.
+     */
+    virtual Display::State state();
+
+    /** Set the state of the ILI9341
+     *
+     * @param mode The new state as a Display::State enum.
+     */
+    virtual void state(State s);
+
+    //void display();
+
+    /** Draw a single pixel at the specified coordinates
+    *
+    * @param x The X coordinate.
+    * @param y The Y coordinate.
+    * @param c The color of the pixel as a 32-bit ARGB value.
+    */
+    virtual void drawPixel(int x, int y, unsigned int c);
+
+private:
+    //Commands
+    /*enum Command {
+        CMD_SETCONTRAST                             = 0x81,
+        CMD_DISPLAYALLON_RESUME                     = 0xA4,
+        CMD_DISPLAYALLON                            = 0xA5,
+        CMD_NORMALDISPLAY                           = 0xA6,
+        CMD_INVERTDISPLAY                           = 0xA7,
+        CMD_DISPLAYOFF                              = 0xAE,
+        CMD_DISPLAYON                               = 0xAF,
+        CMD_SETDISPLAYOFFSET                        = 0xD3,
+        CMD_SETCOMPINS                              = 0xDA,
+        CMD_SETVCOMDETECT                           = 0xDB,
+        CMD_SETDISPLAYCLOCKDIV                      = 0xD5,
+        CMD_SETPRECHARGE                            = 0xD9,
+        CMD_SETMULTIPLEX                            = 0xA8,
+        CMD_SETLOWCOLUMN                            = 0x00,
+        CMD_SETHIGHCOLUMN                           = 0x10,
+        CMD_SETSTARTLINE                            = 0x40,
+        CMD_MEMORYMODE                              = 0x20,
+        CMD_COMSCANINC                              = 0xC0,
+        CMD_COMSCANDEC                              = 0xC8,
+        CMD_SEGREMAP                                = 0xA0,
+        CMD_CHARGEPUMP                              = 0x8D,
+        CMD_CHARGEPUMPON                            = 0x14,
+        CMD_CHARGEPUMPOFF                           = 0x10,
+        CMD_ACTIVATE_SCROLL                         = 0x2F,
+        CMD_DEACTIVATE_SCROLL                       = 0x2E,
+        CMD_SET_VERTICAL_SCROLL_AREA                = 0xA3,
+        CMD_RIGHT_HORIZONTAL_SCROLL                 = 0x26,
+        CMD_LEFT_HORIZONTAL_SCROLL                  = 0x27,
+        CMD_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL    = 0x29,
+        CMD_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL     = 0x2A
+    };*/
+
+    //Interface variables
+    SPI m_SPI;
+    DigitalOut m_CS;
+    DigitalOut m_DC;
+
+    //Command and data helpers
+    void writeCommand(char command);
+    void writeData8(char data);
+    void writeData16(unsigned short data);
+};
+
+#endif
--- a/Drivers/SSD1306.cpp	Fri Aug 30 17:09:18 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/* NeatGUI Library
- * Copyright (c) 2013 Neil Thiessen
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "SSD1306.h"
-
-SSD1306::SSD1306(PinName sda, PinName scl, Address addr) : Display(128, 64), m_I2C(sda, scl)
-{
-    //Set the internal device address
-    m_Addr = (int)addr;
-
-    //Set the I2C frequency to 400kHz
-    m_I2C.frequency(400000);
-}
-
-bool SSD1306::open(void)
-{
-    //Probe for the SSD1306 using a Zero Length Transfer
-    if (!m_I2C.write(m_Addr, NULL, 0)) {
-        //Init sequence for 128x64 OLED module
-        writeCommand(CMD_DISPLAYOFF);
-        writeCommand(CMD_SETDISPLAYCLOCKDIV);
-        writeCommand(0x80);
-        writeCommand(CMD_SETMULTIPLEX);
-        writeCommand(0x3F);
-        writeCommand(CMD_SETDISPLAYOFFSET);
-        writeCommand(0x0);
-        writeCommand(CMD_SETSTARTLINE | 0x0);
-        writeCommand(CMD_CHARGEPUMP);
-        writeCommand(CMD_CHARGEPUMPON);
-        writeCommand(CMD_MEMORYMODE);
-        writeCommand(0x00);
-        writeCommand(CMD_SEGREMAP | 0x1);
-        writeCommand(CMD_COMSCANDEC);
-        writeCommand(CMD_SETCOMPINS);
-        writeCommand(0x12);
-        writeCommand(CMD_SETCONTRAST);
-        writeCommand(0xCF);
-        writeCommand(CMD_SETPRECHARGE);
-        writeCommand(0xF1);
-        writeCommand(CMD_SETVCOMDETECT);
-        writeCommand(0x40);
-        writeCommand(CMD_DISPLAYALLON_RESUME);
-        writeCommand(CMD_NORMALDISPLAY);
-
-        //Return success
-        return true;
-    } else {
-        //Return failure
-        return false;
-    }
-}
-
-void SSD1306::finalize(void)
-{
-    //Select low col 0, hi col 0, line 0
-    writeCommand(CMD_SETLOWCOLUMN | 0x0);
-    writeCommand(CMD_SETHIGHCOLUMN | 0x0);
-    writeCommand(CMD_SETSTARTLINE | 0x0);
-
-    //Make sure the first byte in the buffer is the control byte
-    m_Buffer[0] = CONTROL_DATA;
-
-    //Write the buffer
-    m_I2C.write(m_Addr, m_Buffer, 1025);
-}
-
-Display::State SSD1306::state(void)
-{
-    //Return the base class's state
-    return Display::state();
-}
-
-void SSD1306::state(State s)
-{
-    //Check what the requested state is
-    if (s == Display::DISPLAY_ON) {
-        //Turn the display on
-        writeCommand(CMD_DISPLAYON);
-    } else if (s == Display::DISPLAY_OFF) {
-        //Turn the display off
-        writeCommand(CMD_DISPLAYOFF);
-    }
-
-    //Update the base class
-    Display::state(s);
-}
-
-void SSD1306::drawPixel(int x, int y, unsigned int c)
-{
-    //Range check the pixel
-    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
-        return;
-
-    //Make sure the color is fully opaque
-    if ((c >> 24) != 255)
-        return;
-
-    //Determine the pixel byte index
-    unsigned short byteIndex = x + (y / 8) * width();
-
-    //HACK: Fix the whole 1025 byte i2c buffer thing
-    byteIndex++;
-
-    //Set or clear the pixel
-    if ((c & 0x00FFFFFF) > 0)
-        m_Buffer[byteIndex] |= (1 << (y % 8));
-    else
-        m_Buffer[byteIndex] &= ~(1 << (y % 8));
-}
-
-void SSD1306::writeCommand(char command)
-{
-    //Create a temporary buffer
-    char buff[2];
-
-    //Load the control byte and 8-bit command
-    buff[0] = CONTROL_COMMAND;
-    buff[1] = command;
-
-    //Write the command
-    m_I2C.write(m_Addr, buff, 2);
-}
-
-void SSD1306::writeData(char data)
-{
-    //Create a temporary buffer
-    char buff[2];
-
-    //Load the control byte and 8-bit data
-    buff[0] = CONTROL_DATA;
-    buff[1] = data;
-
-    //Write the data
-    m_I2C.write(m_Addr, buff, 2);
-}
--- a/Drivers/SSD1306.h	Fri Aug 30 17:09:18 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/* NeatGUI Library
- * Copyright (c) 2013 Neil Thiessen
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef SSD1306_H
-#define SSD1306_H
-
-#include "mbed.h"
-#include "Display.h"
-
-/** SSD1306 class.
- *  Used for controlling an SSD1306-based OLED display.
- */
-class SSD1306 : public Display
-{
-public:
-    /** Represents the different I2C address possibilities for the SSD1306
-     */
-    enum Address {
-        ADDRESS_0 = (0x3C << 1),    /**< SA0 pin = 0 */
-        ADDRESS_1 = (0x3D << 1),    /**< SA0 pin = 1 */
-    };
-
-    /** Create an SSD1306 object connected to the specified I2C pins with the specified I2C slave address
-     *
-     * @param sda The I2C data pin.
-     * @param scl The I2C clock pin.
-     * @param addr The I2C slave address.
-     */
-    SSD1306(PinName sda, PinName scl, Address addr);
-
-    /** Create an SSD1306 object connected to the specified SPI pins with the specified /CS and DC pins
-     *
-     * @param mosi The SPI data out pin.
-     * @param miso The SPI data in pin.
-     * @param sclk The SPI clock pin.
-     * @param sclk The SPI chip select pin.
-     * @param sclk The data/command pin.
-     */
-    //SSD1306(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc);
-
-    /** Probe for the SSD1306 and initialize it if present
-     *
-     * @returns
-     *   'true' if the device exists on the bus,
-     *   'false' if the device doesn't exist on the bus.
-     */
-    virtual bool open(void);
-
-    /** Send the buffer to the SSD1306
-     */
-    virtual void finalize(void);
-
-    /** Get the current state of the SSD1306
-     *
-     * @returns The current state as a Display::State enum.
-     */
-    virtual Display::State state(void);
-
-    /** Set the state of the SSD1306
-     *
-     * @param mode The new state as a Display::State enum.
-     */
-    virtual void state(State s);
-
-    //void display(void);
-
-    /** Draw a single pixel at the specified coordinates
-    *
-    * @param x The X coordinate.
-    * @param y The Y coordinate.
-    * @param c The color of the pixel as a 32-bit ARGB value.
-    */
-    virtual void drawPixel(int x, int y, unsigned int c);
-
-private:
-    //Commands
-    enum Command {
-        CMD_SETCONTRAST                             = 0x81,
-        CMD_DISPLAYALLON_RESUME                     = 0xA4,
-        CMD_DISPLAYALLON                            = 0xA5,
-        CMD_NORMALDISPLAY                           = 0xA6,
-        CMD_INVERTDISPLAY                           = 0xA7,
-        CMD_DISPLAYOFF                              = 0xAE,
-        CMD_DISPLAYON                               = 0xAF,
-        CMD_SETDISPLAYOFFSET                        = 0xD3,
-        CMD_SETCOMPINS                              = 0xDA,
-        CMD_SETVCOMDETECT                           = 0xDB,
-        CMD_SETDISPLAYCLOCKDIV                      = 0xD5,
-        CMD_SETPRECHARGE                            = 0xD9,
-        CMD_SETMULTIPLEX                            = 0xA8,
-        CMD_SETLOWCOLUMN                            = 0x00,
-        CMD_SETHIGHCOLUMN                           = 0x10,
-        CMD_SETSTARTLINE                            = 0x40,
-        CMD_MEMORYMODE                              = 0x20,
-        CMD_COMSCANINC                              = 0xC0,
-        CMD_COMSCANDEC                              = 0xC8,
-        CMD_SEGREMAP                                = 0xA0,
-        CMD_CHARGEPUMP                              = 0x8D,
-        CMD_CHARGEPUMPON                            = 0x14,
-        CMD_CHARGEPUMPOFF                           = 0x10,
-        CMD_ACTIVATE_SCROLL                         = 0x2F,
-        CMD_DEACTIVATE_SCROLL                       = 0x2E,
-        CMD_SET_VERTICAL_SCROLL_AREA                = 0xA3,
-        CMD_RIGHT_HORIZONTAL_SCROLL                 = 0x26,
-        CMD_LEFT_HORIZONTAL_SCROLL                  = 0x27,
-        CMD_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL    = 0x29,
-        CMD_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL     = 0x2A
-    };
-
-    //Control bytes for the I2C interface
-    enum I2CControlByte {
-        CONTROL_COMMAND = 0x00,
-        CONTROL_DATA    = 0x40
-    };
-
-    //I2C interface variables
-    I2C m_I2C;
-    int m_Addr;
-
-    //Back buffer
-    char m_Buffer[1025];
-
-    //Command and data helpers
-    void writeCommand(char command);
-    void writeData(char data);
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/SSD1306_I2C.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -0,0 +1,145 @@
+/* NeatGUI Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SSD1306_I2C.h"
+
+SSD1306_I2C::SSD1306_I2C(PinName sda, PinName scl, Address addr) : Display(128, 64), m_I2C(sda, scl), m_ADDR((int)addr)
+{
+    //Set the I2C frequency to 400kHz
+    m_I2C.frequency(400000);
+}
+
+bool SSD1306_I2C::open()
+{
+    //Probe for the SSD1306 using a Zero Length Transfer
+    if (!m_I2C.write(m_ADDR, NULL, 0)) {
+        //Init sequence for 128x64 OLED module
+        writeCommand(CMD_DISPLAYOFF);
+        writeCommand(CMD_SETDISPLAYCLOCKDIV);
+        writeCommand(0x80);
+        writeCommand(CMD_SETMULTIPLEX);
+        writeCommand(0x3F);
+        writeCommand(CMD_SETDISPLAYOFFSET);
+        writeCommand(0x0);
+        writeCommand(CMD_SETSTARTLINE | 0x0);
+        writeCommand(CMD_CHARGEPUMP);
+        writeCommand(CMD_CHARGEPUMPON);
+        writeCommand(CMD_MEMORYMODE);
+        writeCommand(0x00);
+        writeCommand(CMD_SEGREMAP | 0x1);
+        writeCommand(CMD_COMSCANDEC);
+        writeCommand(CMD_SETCOMPINS);
+        writeCommand(0x12);
+        writeCommand(CMD_SETCONTRAST);
+        writeCommand(0xCF);
+        writeCommand(CMD_SETPRECHARGE);
+        writeCommand(0xF1);
+        writeCommand(CMD_SETVCOMDETECT);
+        writeCommand(0x40);
+        writeCommand(CMD_DISPLAYALLON_RESUME);
+        writeCommand(CMD_NORMALDISPLAY);
+
+        //Return success
+        return true;
+    } else {
+        //Return failure
+        return false;
+    }
+}
+
+void SSD1306_I2C::finalize()
+{
+    //Select low col 0, hi col 0, line 0
+    writeCommand(CMD_SETLOWCOLUMN | 0x0);
+    writeCommand(CMD_SETHIGHCOLUMN | 0x0);
+    writeCommand(CMD_SETSTARTLINE | 0x0);
+
+    //Make sure the first byte in the buffer is the control byte
+    m_Buffer[0] = CONTROL_DATA;
+
+    //Write the buffer
+    m_I2C.write(m_ADDR, m_Buffer, 1025);
+}
+
+Display::State SSD1306_I2C::state()
+{
+    //Return the base class's state
+    return Display::state();
+}
+
+void SSD1306_I2C::state(State s)
+{
+    //Check what the requested state is
+    if (s == Display::DISPLAY_ON) {
+        //Turn the display on
+        writeCommand(CMD_DISPLAYON);
+    } else if (s == Display::DISPLAY_OFF) {
+        //Turn the display off
+        writeCommand(CMD_DISPLAYOFF);
+    }
+
+    //Update the base class
+    Display::state(s);
+}
+
+void SSD1306_I2C::drawPixel(int x, int y, unsigned int c)
+{
+    //Range check the pixel
+    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
+        return;
+
+    //Make sure the color is fully opaque
+    if ((c >> 24) != 255)
+        return;
+
+    //Determine the pixel byte index
+    unsigned short byteIndex = x + (y / 8) * width();
+
+    //HACK: Fix the whole 1025 byte i2c buffer thing
+    byteIndex++;
+
+    //Set or clear the pixel
+    if ((c & 0x00FFFFFF) > 0)
+        m_Buffer[byteIndex] |= (1 << (y % 8));
+    else
+        m_Buffer[byteIndex] &= ~(1 << (y % 8));
+}
+
+void SSD1306_I2C::writeCommand(char command)
+{
+    //Create a temporary buffer
+    char buff[2];
+
+    //Load the control byte and 8-bit command
+    buff[0] = CONTROL_COMMAND;
+    buff[1] = command;
+
+    //Write the command
+    m_I2C.write(m_ADDR, buff, 2);
+}
+
+void SSD1306_I2C::writeData(char data)
+{
+    //Create a temporary buffer
+    char buff[2];
+
+    //Load the control byte and 8-bit data
+    buff[0] = CONTROL_DATA;
+    buff[1] = data;
+
+    //Write the data
+    m_I2C.write(m_ADDR, buff, 2);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/SSD1306_I2C.h	Fri Mar 14 19:17:44 2014 +0000
@@ -0,0 +1,141 @@
+/* NeatGUI Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SSD1306_I2C_H
+#define SSD1306_I2C_H
+
+#include "mbed.h"
+#include "Display.h"
+
+/** SSD1306_I2C class.
+ *  Used for controlling an SSD1306-based OLED display connected to i2c.
+ */
+class SSD1306_I2C : public Display
+{
+public:
+    /** Represents the different I2C address possibilities for the SSD1306
+     */
+    enum Address {
+        ADDRESS_0 = (0x3C << 1),    /**< SA0 pin = 0 */
+        ADDRESS_1 = (0x3D << 1),    /**< SA0 pin = 1 */
+    };
+
+    /** Create an SSD1306 object connected to the specified I2C pins with the specified I2C slave address
+     *
+     * @param sda The I2C data pin.
+     * @param scl The I2C clock pin.
+     * @param addr The I2C slave address.
+     */
+    SSD1306_I2C(PinName sda, PinName scl, Address addr);
+
+    /** Create an SSD1306 object connected to the specified SPI pins with the specified /CS and DC pins
+     *
+     * @param mosi The SPI data out pin.
+     * @param miso The SPI data in pin.
+     * @param sclk The SPI clock pin.
+     * @param sclk The SPI chip select pin.
+     * @param sclk The data/command pin.
+     */
+    //SSD1306_SPI(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc);
+
+    /** Probe for the SSD1306 and initialize it if present
+     *
+     * @returns
+     *   'true' if the device exists on the bus,
+     *   'false' if the device doesn't exist on the bus.
+     */
+    virtual bool open();
+
+    /** Send the buffer to the SSD1306
+     */
+    virtual void finalize();
+
+    /** Get the current state of the SSD1306
+     *
+     * @returns The current state as a Display::State enum.
+     */
+    virtual Display::State state();
+
+    /** Set the state of the SSD1306
+     *
+     * @param mode The new state as a Display::State enum.
+     */
+    virtual void state(State s);
+
+    //void display();
+
+    /** Draw a single pixel at the specified coordinates
+    *
+    * @param x The X coordinate.
+    * @param y The Y coordinate.
+    * @param c The color of the pixel as a 32-bit ARGB value.
+    */
+    virtual void drawPixel(int x, int y, unsigned int c);
+
+private:
+    //Commands
+    enum Command {
+        CMD_SETCONTRAST                             = 0x81,
+        CMD_DISPLAYALLON_RESUME                     = 0xA4,
+        CMD_DISPLAYALLON                            = 0xA5,
+        CMD_NORMALDISPLAY                           = 0xA6,
+        CMD_INVERTDISPLAY                           = 0xA7,
+        CMD_DISPLAYOFF                              = 0xAE,
+        CMD_DISPLAYON                               = 0xAF,
+        CMD_SETDISPLAYOFFSET                        = 0xD3,
+        CMD_SETCOMPINS                              = 0xDA,
+        CMD_SETVCOMDETECT                           = 0xDB,
+        CMD_SETDISPLAYCLOCKDIV                      = 0xD5,
+        CMD_SETPRECHARGE                            = 0xD9,
+        CMD_SETMULTIPLEX                            = 0xA8,
+        CMD_SETLOWCOLUMN                            = 0x00,
+        CMD_SETHIGHCOLUMN                           = 0x10,
+        CMD_SETSTARTLINE                            = 0x40,
+        CMD_MEMORYMODE                              = 0x20,
+        CMD_COMSCANINC                              = 0xC0,
+        CMD_COMSCANDEC                              = 0xC8,
+        CMD_SEGREMAP                                = 0xA0,
+        CMD_CHARGEPUMP                              = 0x8D,
+        CMD_CHARGEPUMPON                            = 0x14,
+        CMD_CHARGEPUMPOFF                           = 0x10,
+        CMD_ACTIVATE_SCROLL                         = 0x2F,
+        CMD_DEACTIVATE_SCROLL                       = 0x2E,
+        CMD_SET_VERTICAL_SCROLL_AREA                = 0xA3,
+        CMD_RIGHT_HORIZONTAL_SCROLL                 = 0x26,
+        CMD_LEFT_HORIZONTAL_SCROLL                  = 0x27,
+        CMD_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL    = 0x29,
+        CMD_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL     = 0x2A
+    };
+
+    //Control bytes for the I2C interface
+    enum I2CControlByte {
+        CONTROL_COMMAND = 0x00,
+        CONTROL_DATA    = 0x40
+    };
+
+    //I2C interface variables
+    I2C m_I2C;
+    const int m_ADDR;
+
+    //Back buffer
+    char m_Buffer[1025];
+
+    //Command and data helpers
+    void writeCommand(char command);
+    void writeData(char data);
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/SSD1306_SPI.cpp	Fri Mar 14 19:17:44 2014 +0000
@@ -0,0 +1,147 @@
+/* NeatGUI Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SSD1306_SPI.h"
+
+SSD1306_SPI::SSD1306_SPI(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc) : Display(128, 64), m_SPI(mosi, miso, sclk), m_CS(cs), m_DC(dc)
+{
+    //Deselect the display
+    m_CS = 1;
+
+    //Set the SPI format to 8 bit data, high steady state clock, second edge capture
+    m_SPI.format(8, 3);
+
+    //Set the SPI frequency to 10MHz
+    m_SPI.frequency(10000000);
+}
+
+bool SSD1306_SPI::open()
+{
+    //Init sequence for 128x64 OLED module
+    writeCommand(CMD_DISPLAYOFF);
+    writeCommand(CMD_SETDISPLAYCLOCKDIV);
+    writeCommand(0x80);
+    writeCommand(CMD_SETMULTIPLEX);
+    writeCommand(0x3F);
+    writeCommand(CMD_SETDISPLAYOFFSET);
+    writeCommand(0x0);
+    writeCommand(CMD_SETSTARTLINE | 0x0);
+    writeCommand(CMD_CHARGEPUMP);
+    writeCommand(CMD_CHARGEPUMPON);
+    writeCommand(CMD_MEMORYMODE);
+    writeCommand(0x00);
+    writeCommand(CMD_SEGREMAP | 0x1);
+    writeCommand(CMD_COMSCANDEC);
+    writeCommand(CMD_SETCOMPINS);
+    writeCommand(0x12);
+    writeCommand(CMD_SETCONTRAST);
+    writeCommand(0xCF);
+    writeCommand(CMD_SETPRECHARGE);
+    writeCommand(0xF1);
+    writeCommand(CMD_SETVCOMDETECT);
+    writeCommand(0x40);
+    writeCommand(CMD_DISPLAYALLON_RESUME);
+    writeCommand(CMD_NORMALDISPLAY);
+
+    //Return success
+    return true;
+}
+
+void SSD1306_SPI::finalize()
+{
+    //Select low col 0, hi col 0, line 0
+    writeCommand(CMD_SETLOWCOLUMN | 0x0);
+    writeCommand(CMD_SETHIGHCOLUMN | 0x0);
+    writeCommand(CMD_SETSTARTLINE | 0x0);
+
+    //Set DC to data and select the chip
+    m_DC = 1;
+    m_CS = 0;
+
+    //Write the entire buffer at once
+    for (int i = 0; i < 1024; i++)
+        m_SPI.write(m_Buffer[i]);
+
+    //Deselect the chip
+    m_CS = 1;
+}
+
+Display::State SSD1306_SPI::state()
+{
+    //Return the base class's state
+    return Display::state();
+}
+
+void SSD1306_SPI::state(State s)
+{
+    //Check what the requested state is
+    if (s == Display::DISPLAY_ON) {
+        //Turn the display on
+        writeCommand(CMD_DISPLAYON);
+    } else if (s == Display::DISPLAY_OFF) {
+        //Turn the display off
+        writeCommand(CMD_DISPLAYOFF);
+    }
+
+    //Update the base class
+    Display::state(s);
+}
+
+void SSD1306_SPI::drawPixel(int x, int y, unsigned int c)
+{
+    //Range check the pixel
+    if ((x < 0) || (x >= width()) || (y < 0) || (y >= height()))
+        return;
+
+    //Make sure the color is fully opaque
+    if ((c >> 24) != 255)
+        return;
+
+    //Determine the pixel byte index
+    unsigned short byteIndex = x + (y / 8) * width();
+
+    //Set or clear the pixel
+    if ((c & 0x00FFFFFF) > 0)
+        m_Buffer[byteIndex] |= (1 << (y % 8));
+    else
+        m_Buffer[byteIndex] &= ~(1 << (y % 8));
+}
+
+void SSD1306_SPI::writeCommand(char command)
+{
+    //Set DC to command and select the display
+    m_DC = 0;
+    m_CS = 0;
+
+    //Write the command byte
+    m_SPI.write(command);
+
+    //Deselect the display
+    m_CS = 1;
+}
+
+void SSD1306_SPI::writeData(char data)
+{
+    //Set DC to data and select the display
+    m_DC = 1;
+    m_CS = 0;
+
+    //Write the data byte
+    m_SPI.write(data);
+
+    //Deselect the display
+    m_CS = 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Drivers/SSD1306_SPI.h	Fri Mar 14 19:17:44 2014 +0000
@@ -0,0 +1,122 @@
+/* NeatGUI Library
+ * Copyright (c) 2013 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SSD1306_SPI_H
+#define SSD1306_SPI_H
+
+#include "mbed.h"
+#include "Display.h"
+
+/** SSD1306_SPI class.
+ *  Used for controlling an SSD1306-based OLED display connected to SPI.
+ */
+class SSD1306_SPI : public Display
+{
+public:
+
+    /** Create an SSD1306 object connected to the specified SPI pins with the specified /CS and DC pins
+     *
+     * @param mosi The SPI data out pin.
+     * @param miso The SPI data in pin.
+     * @param sclk The SPI clock pin.
+     * @param sclk The SPI chip select pin.
+     * @param sclk The data/command pin.
+     */
+    SSD1306_SPI(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName dc);
+
+    /** Probe for the SSD1306 and initialize it if present
+     *
+     * @returns
+     *   'true' if the device exists on the bus,
+     *   'false' if the device doesn't exist on the bus.
+     */
+    virtual bool open();
+
+    /** Send the buffer to the SSD1306
+     */
+    virtual void finalize();
+
+    /** Get the current state of the SSD1306
+     *
+     * @returns The current state as a Display::State enum.
+     */
+    virtual Display::State state();
+
+    /** Set the state of the SSD1306
+     *
+     * @param mode The new state as a Display::State enum.
+     */
+    virtual void state(State s);
+
+    //void display();
+
+    /** Draw a single pixel at the specified coordinates
+    *
+    * @param x The X coordinate.
+    * @param y The Y coordinate.
+    * @param c The color of the pixel as a 32-bit ARGB value.
+    */
+    virtual void drawPixel(int x, int y, unsigned int c);
+
+private:
+    //Commands
+    enum Command {
+        CMD_SETCONTRAST                             = 0x81,
+        CMD_DISPLAYALLON_RESUME                     = 0xA4,
+        CMD_DISPLAYALLON                            = 0xA5,
+        CMD_NORMALDISPLAY                           = 0xA6,
+        CMD_INVERTDISPLAY                           = 0xA7,
+        CMD_DISPLAYOFF                              = 0xAE,
+        CMD_DISPLAYON                               = 0xAF,
+        CMD_SETDISPLAYOFFSET                        = 0xD3,
+        CMD_SETCOMPINS                              = 0xDA,
+        CMD_SETVCOMDETECT                           = 0xDB,
+        CMD_SETDISPLAYCLOCKDIV                      = 0xD5,
+        CMD_SETPRECHARGE                            = 0xD9,
+        CMD_SETMULTIPLEX                            = 0xA8,
+        CMD_SETLOWCOLUMN                            = 0x00,
+        CMD_SETHIGHCOLUMN                           = 0x10,
+        CMD_SETSTARTLINE                            = 0x40,
+        CMD_MEMORYMODE                              = 0x20,
+        CMD_COMSCANINC                              = 0xC0,
+        CMD_COMSCANDEC                              = 0xC8,
+        CMD_SEGREMAP                                = 0xA0,
+        CMD_CHARGEPUMP                              = 0x8D,
+        CMD_CHARGEPUMPON                            = 0x14,
+        CMD_CHARGEPUMPOFF                           = 0x10,
+        CMD_ACTIVATE_SCROLL                         = 0x2F,
+        CMD_DEACTIVATE_SCROLL                       = 0x2E,
+        CMD_SET_VERTICAL_SCROLL_AREA                = 0xA3,
+        CMD_RIGHT_HORIZONTAL_SCROLL                 = 0x26,
+        CMD_LEFT_HORIZONTAL_SCROLL                  = 0x27,
+        CMD_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL    = 0x29,
+        CMD_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL     = 0x2A
+    };
+
+    //SPI interface variables
+    SPI m_SPI;
+    DigitalOut m_CS;
+    DigitalOut m_DC;
+
+    //Back buffer
+    char m_Buffer[1024];
+
+    //Command and data helpers
+    void writeCommand(char command);
+    void writeData(char data);
+};
+
+#endif
--- a/NeatGUI.h	Fri Aug 30 17:09:18 2013 +0000
+++ b/NeatGUI.h	Fri Mar 14 19:17:44 2014 +0000
@@ -31,6 +31,8 @@
 #include "Font.h"
 
 //Drivers
-#include "SSD1306.h"
+#include "ILI9341.h"
+#include "SSD1306_I2C.h"
+#include "SSD1306_SPI.h"
 
 #endif