diff --git a/Makefile b/Makefile
index 25aed4fba44dc04cc6135957bdf4ef990126420b..c50eb5c4c3a8843bfdb5182f068e1b052feb1eb7 100644
--- a/Makefile
+++ b/Makefile
@@ -28,6 +28,7 @@ drivers/display_mp3v2.cpp              \
 drivers/event_mp3v2.cpp                \
 drivers/resfs_mp3v2.cpp                \
 drivers/display_strive.cpp             \
+drivers/display_st7735.cpp             \
 drivers/display_oledboard2.cpp         \
 drivers/event_strive.cpp               \
 drivers/display_redbull_v2.cpp         \
diff --git a/drivers/display_st7735.cpp b/drivers/display_st7735.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8beb6bdc439489358d4f0b51f57b713c29899b7f
--- /dev/null
+++ b/drivers/display_st7735.cpp
@@ -0,0 +1,411 @@
+/***************************************************************************
+ *   Copyright (C) 2013 by Salaorni Davide, Velati Matteo                  *
+ *                                                                         *
+ *   This program 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 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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.                          *
+ *                                                                         *
+ *   As a special exception, if other files instantiate templates or use   *
+ *   macros or inline functions from this file, or you compile this file   *
+ *   and link it with other works to produce a work based on this file,    *
+ *   this file does not by itself cause the resulting work to be covered   *
+ *   by the GNU General Public License. However the source code for this   *
+ *   file must still be made available in accordance with the GNU General  *
+ *   Public License. This exception does not invalidate any other reasons  *
+ *   why a work based on this file might be covered by the GNU General     *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
+ ***************************************************************************/
+
+#include "display_st7735.h"
+#include "miosix.h"
+#include <cstdarg>
+
+using namespace std;
+using namespace miosix;
+
+#ifdef _BOARD_STM32F4DISCOVERY
+
+namespace mxgui {
+    
+/**
+ * Function to attach the display we are using.
+ */
+void registerDisplayHook(DisplayManager& dm) {
+    dm.registerDisplay(&DisplayImpl::instance());
+}
+
+/**
+ * Init sequence for the correct functioning of the ST7735 display
+ */
+const unsigned char initST7735b[] = {
+    0x3A, 0X01, 0x05,                   // ST7735_COLMOD, color mode: 16-bit/pixel
+    0xB1, 0x03, 0x00, 0x06, 0x03,       // ST7735_FRMCTR1, normal mode frame rate
+    0xB6, 0x02, 0x15, 0x02,             // ST7735_DISSET5, display settings
+    0xB4, 0x01, 0x00,                   // ST7735_INVCTR, line inversion active
+    0xC0, 0x02, 0x02, 0x70,             // ST7735_PWCTR1, default (4.7V, 1.0 uA)
+    0xC1, 0x01, 0x05,                   // ST7735_PWCTR2, default (VGH=14.7V, VGL=-7.35V)
+    0xC3, 0x02, 0x02, 0x07,             // ST7735_PWCTR4, bclk/2, opamp current small and medium low
+    0xC5, 0x02, 0x3C, 0x38,             // ST7735_VMCTR1, VCOMH=4V VCOML=-1.1
+    0xFC, 0x02, 0x11, 0x15,             // ST7735_PWCTR6, power control (partial mode+idle)
+    0xE0, 0x10,                         // ST7735_GMCTRP1, Gamma adjustments (pos. polarity)
+        0x09, 0x16, 0x09, 0x20,         // (Not entirely necessary, but provides
+        0x21, 0x1B, 0x13, 0x19,         // accurate colors)
+        0x17, 0x15, 0x1E, 0x2B,
+        0x04, 0x05, 0x02, 0x0E,
+    0xE1, 0x10,                         // ST7735_GMCTRN1, Gamma adjustments (neg. polarity)
+        0x0B, 0x14, 0x08, 0x1E,         // (Not entirely necessary, but provides
+        0x22, 0x1D, 0x18, 0x1E,         // accurate colors)
+        0x1B, 0x1A, 0x24, 0x2B,
+        0x06, 0x06, 0x02, 0x0F,
+    0x13,                               // ST7735_NORON, normal display mode on
+    0x00
+};
+
+/**
+ * Class DisplayImpl
+ */
+DisplayImpl& DisplayImpl::instance() {
+    static DisplayImpl instance;
+    return instance;
+}
+
+void DisplayImpl::doTurnOn() {
+    writeReg(0x29);     //ST7735_DISPON 
+    delayMs(150);
+}
+
+void DisplayImpl::doTurnOff() {
+    writeReg(0x28);     //ST7735_DISPOFF 
+    delayMs(150);
+}
+
+void DisplayImpl::doSetBrightness(int brt) {
+    //No function to set brightness for this display
+}
+
+pair<short int, short int> DisplayImpl::doGetSize() const {
+    return make_pair(height, width);
+}
+
+void DisplayImpl::write(Point p, const char *text) {
+    font.draw(*this, textColor, p, text);
+}
+
+void DisplayImpl::clippedWrite(Point p, Point a,  Point b, const char *text) {
+    font.clippedDraw(*this, textColor, p, a, b, text);
+}
+
+void DisplayImpl::clear(Color color) {
+    clear(Point(0,0), Point(width-1, height-1), color);
+}
+
+void DisplayImpl::clear(Point p1, Point p2, Color color) {
+    unsigned char lsb = color & 0xFF;
+    unsigned char msb = (color >> 8) & 0xFF;
+
+    imageWindow(p1, p2);
+    int numPixels = (p2.x() - p1.x() + 1) * (p2.y() - p1.y() + 1);
+
+    SPITransaction t;
+    writeRamBegin();
+
+    //Send data to write on GRAM
+    for(int i=0; i < numPixels; i++) {
+        writeRam(msb);
+        writeRam(lsb);
+    }
+}
+
+void DisplayImpl::beginPixel() {
+    imageWindow(Point(0,0), Point(width-1, height-1));
+}
+
+void DisplayImpl::setPixel(Point p, Color color) {
+    unsigned char lsb = color & 0xFF;
+    unsigned char msb = (color >> 8) & 0xFF;
+
+    setCursor(p);
+    SPITransaction t;
+    writeRamBegin();
+    writeRam(msb);
+    writeRam(lsb);
+}
+
+void DisplayImpl::line(Point a, Point b, Color color) {
+    unsigned char lsb = color & 0xFF;
+    unsigned char msb = (color >> 8) & 0xFF;
+
+    //Horizontal line speed optimization
+    if(a.y() == b.y())
+    {
+        imageWindow(Point(min(a.x(), b.x()), a.y()), Point(max(a.x(), b.x()), a.y()));
+        int numPixels = abs(a.x() - b.x());
+
+        SPITransaction t;
+        writeRamBegin();
+
+        //Send data to write on GRAM
+        for(int i=0; i <= numPixels; i++) {
+            writeRam(msb);
+            writeRam(lsb);
+        }
+        return;
+    }
+    //Vertical line speed optimization
+    if(a.x() == b.x())
+    {
+        textWindow(Point(a.x(), min(a.y(), b.y())), Point(a.x(), max(a.y(), b.y())));
+        int numPixels = abs(a.y() - b.y());
+
+        SPITransaction t;
+        writeRamBegin();
+
+        //Send data to write on GRAM
+        for(int i=0; i <= numPixels; i++) {
+            writeRam(msb);
+            writeRam(lsb);
+        }
+        return;
+    }
+    //General case, always works but it is much slower due to the display
+    //not having fast random access to pixels
+    Line::draw(*this, a, b, color);
+}
+
+void DisplayImpl::scanLine(Point p, const Color *colors, unsigned short length) {
+    unsigned char lsb = 0x00;
+    unsigned char msb = 0x00;
+
+    if(p.x() + length > width) { return; }
+    imageWindow(p, Point(width - 1, p.y()));
+
+    SPITransaction t;
+    writeRamBegin();
+
+    //Send data to write on GRAM
+    for(int i=0; i < length; i++) {
+        lsb = colors[i] & 0xFF;
+        msb = (colors[i] >> 8) & 0xFF;
+
+        writeRam(msb);
+        writeRam(lsb);
+    }
+}
+
+Color *DisplayImpl::getScanLineBuffer() {
+    if(buffer == 0) buffer = new Color[getWidth()];
+    return buffer;
+}
+
+void DisplayImpl::scanLineBuffer(Point p, unsigned short length) {
+    scanLine(p, buffer, length);
+}
+
+void DisplayImpl::drawImage(Point p, const ImageBase& img) {
+    short int xEnd = p.x() + img.getWidth() - 1;
+    short int yEnd = p.y() + img.getHeight() - 1;
+    if(xEnd >= width || yEnd >= height) { return; }
+
+    const unsigned short *imgData = img.getData();
+    if(imgData != 0)
+    {
+        unsigned char lsb = 0x00;
+        unsigned char msb = 0x00;
+
+        //Optimized version for memory-loaded images
+        imageWindow(p, Point(xEnd, yEnd));
+        int numPixels = img.getHeight() * img.getWidth();
+
+        SPITransaction t;
+        writeRamBegin();
+
+        for(int i=0; i <= numPixels; i++)
+        {
+            lsb = imgData[i] & 0xFF;
+            msb = (imgData[i] >> 8) & 0xFF;
+            writeRam(msb);
+            writeRam(lsb);
+        }
+    }
+    else { img.draw(*this,p); }
+}
+
+void DisplayImpl::clippedDrawImage(Point p, Point a, Point b, const ImageBase& img) {
+    img.clippedDraw(*this,p,a,b);
+}
+
+void DisplayImpl::drawRectangle(Point a, Point b, Color c) {
+    line(a,Point(b.x(), a.y()), c);
+    line(Point(b.x(), a.y()), b, c);
+    line(b,Point(a.x(), b.y()), c);
+    line(Point(a.x(), b.y()), a, c);
+}
+
+void DisplayImpl::window(Point p1, Point p2, bool swap) {
+    #ifdef MXGUI_ORIENTATION_VERTICAL
+        char caset_offset = 2;
+        char raset_offset = 1;
+    #else //MXGUI_ORIENTATION_HORIZONTAL
+        char caset_offset = 1;
+        char raset_offset = 2;
+    #endif
+
+    //Setting column bounds, ST7735_CASET (adding offset)
+    unsigned char buff_caset[4];
+    buff_caset[0] = (p1.x()+caset_offset)>>8 & 255;
+    buff_caset[1] = (p1.x()+caset_offset) & 255;
+    buff_caset[2] = (p2.x()+caset_offset)>>8 & 255;
+    buff_caset[3] = (p2.x()+caset_offset) & 255;
+
+    //Setting row bounds, ST7735_RASET (adding offset)
+    unsigned char buff_raset[4];
+    buff_raset[0] = (p1.y()+raset_offset)>>8 & 255;
+    buff_raset[1] = (p1.y()+raset_offset) & 255;
+    buff_raset[2] = (p2.y()+raset_offset)>>8 & 255;
+    buff_raset[3] = (p2.y()+raset_offset) & 255;
+
+    // For drawing texts, swap the caset and raset buffers
+    if (swap){
+        writeReg(0x2A, buff_raset, sizeof(buff_raset));
+        writeReg(0x2B, buff_caset, sizeof(buff_caset));
+    }
+    else {
+        writeReg(0x2A, buff_caset, sizeof(buff_caset));
+        writeReg(0x2B, buff_raset, sizeof(buff_raset));
+    }
+}
+
+void DisplayImpl::update() {
+    // Useless for ST7735 display
+}
+
+DisplayImpl::pixel_iterator
+DisplayImpl::begin(Point p1, Point p2, IteratorDirection d) {
+        if(p1.x()<0 || p1.y()<0 || p2.x()<0 || p2.y()<0) {
+            return pixel_iterator();
+        }
+        if(p1.x() >= width || p1.y() >= height || p2.x() >= width || p2.y() >= height) {
+            return pixel_iterator();
+        }
+        if(p2.x() < p1.x() || p2.y() < p1.y()) {
+            return pixel_iterator();
+        }
+
+        if(d == DR) { textWindow(p1, p2); }
+        else { imageWindow(p1, p2); }
+
+        SPITransaction t;
+        writeRamBegin();
+
+        unsigned int numPixels = (p2.x() - p1.x() + 1) * (p2.y() - p1.y() + 1);
+        return pixel_iterator(numPixels);
+}
+
+//Destructor
+DisplayImpl::~DisplayImpl() {
+    if(buffer) delete[] buffer;
+}
+
+//Constructor
+DisplayImpl::DisplayImpl(): buffer(0) {
+    {
+        FastInterruptDisableLock dLock;
+
+        RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
+        SPI2->CR1 = 0;
+        SPI2->CR1 = SPI_CR1_SSM     //Software cs
+                  | SPI_CR1_SSI     //Hardware cs internally tied high
+                  | SPI_CR1_BR_0    //clock divider: 4  ->  10,5 MHz -> 95 ns
+                  | SPI_CR1_MSTR    //Master mode
+                  | SPI_CR1_SPE;    //SPI enabled
+
+        scl::mode(Mode::ALTERNATE);     scl::alternateFunction(5);
+        sda::mode(Mode::ALTERNATE);     sda::alternateFunction(5);
+        // GPIO software controlled
+        csx::mode(Mode::OUTPUT);
+        dcx::mode(Mode::OUTPUT);
+        resx::mode(Mode::OUTPUT);
+    }
+    
+    csx::high();
+    dcx::high();
+
+    // POWER ON SEQUENCE: HW RESET -> SW RESET -> SLPOUT
+    resx::high();
+    delayMs(150);
+    resx::low();
+    delayMs(150);
+    resx::high();
+    delayMs(150);
+
+    writeReg(0x01);    // ST7735_SWRESET
+    delayMs(150);
+    writeReg(0x11);    // ST7735_SLPOUT
+    delayMs(150);
+
+    sendCmds(initST7735b);
+
+    doTurnOn();
+    setFont(droid11);
+    setTextColor(make_pair(white, black));
+}
+
+/**
+ * Write only commands with one parameter.
+ */
+void DisplayImpl::writeReg(unsigned char reg, unsigned char data)
+{
+    SPITransaction t;
+    {
+        CommandTransaction c;
+        writeRam(reg);
+    }
+    writeRam(data);
+}
+
+/**
+ * Write commands with more parameters.
+ */
+void DisplayImpl::writeReg(unsigned char reg, const unsigned char *data, int len)
+{
+     SPITransaction t;
+    {
+        CommandTransaction c;
+        writeRam(reg);
+    }
+    if(data)
+    {
+        for(int i = 0; i < len; i++) {
+            writeRam(*data++);
+        }
+    }
+}
+
+/**
+ * Send commands of 8 bits to the MCU of the display.
+ */
+void DisplayImpl::sendCmds(const unsigned char *cmds) {
+    while(*cmds)
+    {
+        unsigned char cmd = *cmds++;
+        unsigned char numArgs = *cmds++;
+        writeReg(cmd, cmds, numArgs);
+        cmds += numArgs;
+        delayUs(1);
+    }
+}
+
+} //mxgui
+
+#else
+#warning "This SPI driver has only been tested on an STM32F4DISCOVERY"
+#endif //_BOARD_STM32F4DISCOVERY
diff --git a/drivers/display_st7735.h b/drivers/display_st7735.h
new file mode 100644
index 0000000000000000000000000000000000000000..f5fa19e7d4862bd967973066adeb4a8dd29c1c1d
--- /dev/null
+++ b/drivers/display_st7735.h
@@ -0,0 +1,468 @@
+/***************************************************************************
+ *   Copyright (C) 2013 by Salaorni Davide, Velati Matteo                  *
+ *                                                                         *
+ *   This program 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 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program 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.                          *
+ *                                                                         *
+ *   As a special exception, if other files instantiate templates or use   *
+ *   macros or inline functions from this file, or you compile this file   *
+ *   and link it with other works to produce a work based on this file,    *
+ *   this file does not by itself cause the resulting work to be covered   *
+ *   by the GNU General Public License. However the source code for this   *
+ *   file must still be made available in accordance with the GNU General  *
+ *   Public License. This exception does not invalidate any other reasons  *
+ *   why a work based on this file might be covered by the GNU General     *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
+ ***************************************************************************/
+
+#ifndef MXGUI_LIBRARY
+#error "This is header is private, it can be used only within mxgui."
+#error "If your code depends on a private header, it IS broken."
+#endif //MXGUI_LIBRARY
+
+#ifndef DISPLAY_ST7735H
+#define DISPLAY_ST7735H
+
+#ifdef _BOARD_STM32F4DISCOVERY
+
+#include <config/mxgui_settings.h>
+#include "display.h"
+#include "point.h"
+#include "color.h"
+#include "font.h"
+#include "image.h"
+#include "iterator_direction.h"
+#include "misc_inst.h"
+#include "line.h"
+#include "miosix.h"
+#include <cstdio>
+#include <cstring>
+#include <algorithm>
+
+using namespace std;
+using namespace miosix;
+
+namespace mxgui {
+
+#ifndef MXGUI_COLOR_DEPTH_16_BIT
+#error The ST7735 driver requires a color depth 16 per pixel
+#endif
+
+//Hardware mapping
+typedef Gpio<GPIOB_BASE, 13> scl;   //PB13,  SPI1_SCK (af5)
+typedef Gpio<GPIOB_BASE, 15> sda;   //PB15,  SPI1_MOSI (af5)
+typedef Gpio<GPIOB_BASE, 4> csx;    //PB4,   free I/O pin
+typedef Gpio<GPIOC_BASE, 6> resx;   //PC6,   free I/O pin
+typedef Gpio<GPIOA_BASE, 8> dcx;    //PA8,   free I/O pin, used only in 4-line SPI
+
+//A falling edge of CSX enables the SPI transaction
+class SPITransaction
+{
+public:
+    SPITransaction()  { csx::low();  }
+    ~SPITransaction() { csx::high(); }
+};
+
+//A falling edge on DCX means that the transmitted byte is a command
+class CommandTransaction
+{
+public:
+    CommandTransaction()  { dcx::low();  }
+    ~CommandTransaction() { dcx::high(); }
+};
+
+class DisplayImpl : public Display
+{
+public:
+    /**
+     * \return an instance to this class(singleton)
+     */
+    static DisplayImpl& instance();
+
+    /**
+     * Turn the display On after it has been turned Off.
+     * Display initial state On.
+     */
+    void doTurnOn() override;
+
+    /**
+     * Turn the display Off. It can be later turned back On.
+     */
+    void doTurnOff() override;
+
+    /**
+     * Set display brightness. Depending on the underlying driver,
+     * may do nothing.
+     * \param brt from 0 to 100
+     */
+    void doSetBrightness(int brt) override;
+
+    /**
+     * \return a pair with the display height and width
+     */
+    std::pair<short int, short int> doGetSize() const override;
+
+    /**
+     * Write text to the display. If text is too long it will be truncated
+     * \param p point where the upper left corner of the text will be printed
+     * \param text, text to print.
+     */
+    void write(Point p, const char *text) override;
+
+    /**
+     * Write part of text to the display
+     * \param p point of the upper left corner where the text will be drawn.
+     * Negative coordinates are allowed, as long as the clipped view has
+     * positive or zero coordinates
+     * \param a Upper left corner of clipping rectangle
+     * \param b Lower right corner of clipping rectangle
+     * \param text text to write
+     */
+    void clippedWrite(Point p, Point a,  Point b, const char *text) override;
+
+    /**
+     * Clear the Display. The screen will be filled with the desired color
+     * \param color fill color
+     */
+    void clear(Color color) override;
+
+    /**
+     * Clear an area of the screen
+     * \param p1 upper left corner of area to clear
+     * \param p2 lower right corner of area to clear
+     * \param color fill color
+     */
+    void clear(Point p1, Point p2, Color color) override;
+
+    /**
+     * This member function is used on some target displays to reset the
+     * drawing window to its default value. You have to call beginPixel() once
+     * before calling setPixel(). You can then make any number of calls to
+     * setPixel() without calling beginPixel() again, as long as you don't
+     * call any other member function in this class. If you call another
+     * member function, for example line(), you have to call beginPixel() again
+     * before calling setPixel().
+     */
+    void beginPixel() override;
+
+    /**
+     * Draw a pixel with desired color. 
+     * \param p point where to draw pixel
+     * \param color pixel color
+     */
+    void setPixel(Point p, Color color) override;
+
+    /**
+     * Draw a line between point a and point b, with color c
+     * \param a first point
+     * \param b second point
+     * \param c line color
+     */
+    void line(Point a, Point b, Color color) override;
+
+    /**
+     * Draw an horizontal line on screen.
+     * Instead of line(), this member function takes an array of colors to be
+     * able to individually set pixel colors of a line.
+     * \param p starting point of the line
+     * \param colors an array of pixel colors whoase size must be b.x()-a.x()+1
+     * \param length length of colors array.
+     * p.x()+length must be <= display.width()
+     */
+    void scanLine(Point p, const Color *colors, unsigned short length) override;
+
+    /**
+     * \return a buffer of length equal to this->getWidth() that can be used to
+     * render a scanline.
+     */
+    Color *getScanLineBuffer() override;
+
+    /**
+     * Draw the content of the last getScanLineBuffer() on an horizontal line
+     * on the screen.
+     * \param p starting point of the line
+     * \param length length of colors array.
+     * p.x()+length must be <= display.width()
+     */
+    void scanLineBuffer(Point p, unsigned short length) override;
+
+    /**
+     * Draw an image on the screen
+     * \param p point of the upper left corner where the image will be drawn
+     * \param i image to draw
+     */
+    void drawImage(Point p, const ImageBase& img) override;
+
+    /**
+     * Draw part of an image on the screen
+     * \param p point of the upper left corner where the image will be drawn.
+     * Negative coordinates are allowed, as long as the clipped view has
+     * positive or zero coordinates
+     * \param a Upper left corner of clipping rectangle
+     * \param b Lower right corner of clipping rectangle
+     * \param img Image to draw
+     */
+    void clippedDrawImage(Point p, Point a, Point b, const ImageBase& img) override;
+
+     /**
+     * Draw a rectangle (not filled) with the desired color
+     * \param a upper left corner of the rectangle
+     * \param b lower right corner of the rectangle
+     * \param c color of the line
+     */
+    void drawRectangle(Point a, Point b, Color c) override;
+
+     /**
+     * Make all changes done to the display since the last call to update()
+     * visible.
+     */
+    void update() override;
+
+    /**
+     * Pixel iterator. A pixel iterator is an output iterator that allows to
+     * define a window on the display and write to its pixels.
+     */
+    class pixel_iterator
+    {
+    public:
+        /**
+         * Default constructor, results in an invalid iterator.
+         */
+        pixel_iterator(): pixelLeft(0) {}
+
+        /**
+         * Set a pixel and move the pointer to the next one
+         * \param color color to set the current pixel
+         * \return a reference to this
+         */
+        pixel_iterator& operator= (Color color)
+        {
+            pixelLeft--;
+
+            unsigned char lsb = color & 0xFF;
+            unsigned char msb = (color >> 8) & 0xFF;
+
+            SPITransaction t;
+            writeRam(msb);
+            writeRam(lsb);
+
+            return *this;
+        }
+
+        /**
+         * Compare two pixel_iterators for equality.
+         * They are equal if they point to the same location.
+         */
+        bool operator== (const pixel_iterator& itr)
+        {
+            return this->pixelLeft==itr.pixelLeft;
+        }
+
+        /**
+         * Compare two pixel_iterators for inequality.
+         * They different if they point to different locations.
+         */
+        bool operator!= (const pixel_iterator& itr)
+        {
+            return this->pixelLeft!=itr.pixelLeft;
+        }
+
+        /**
+         * \return a reference to this.
+         */
+        pixel_iterator& operator* () { return *this; }
+
+        /**
+         * \return a reference to this. Does not increment pixel pointer.
+         */
+        pixel_iterator& operator++ () { return *this; }
+
+        /**
+         * \return a reference to this. Does not increment pixel pointer.
+         */
+        pixel_iterator& operator++ (int) { return *this; }
+
+        /**
+         * Must be called if not all pixels of the required window are going
+         * to be written.
+         */
+        void invalidate() {}
+
+    private:
+        /**
+         * Constructor
+         * \param pixelLeft number of remaining pixels
+         */
+        pixel_iterator(unsigned int pixelLeft): pixelLeft(pixelLeft) {}
+
+        unsigned int pixelLeft; ///< How many pixels are left to draw
+
+        friend class DisplayImpl; //Needs access to ctor
+    };
+
+    /**
+     * Specify a window on screen and return an object that allows to write
+     * its pixels.
+     * Note: a call to begin() will invalidate any previous iterator.
+     * \param p1 upper left corner of window
+     * \param p2 lower right corner (included)
+     * \param d increment direction
+     * \return a pixel iterator
+     */
+    pixel_iterator begin(Point p1, Point p2, IteratorDirection d);
+
+    /**
+     * \return an iterator which is one past the last pixel in the pixel
+     * specified by begin. Behaviour is undefined if called before calling
+     * begin()
+     */
+    pixel_iterator end() const
+    {
+        // Default ctor: pixelLeft is zero
+        return pixel_iterator();
+    }
+
+    /**
+     * Destructor
+     */
+    ~DisplayImpl() override;
+
+private:
+
+    #if defined MXGUI_ORIENTATION_VERTICAL
+        static const short int width    = 128;
+        static const short int height   = 160;
+    #elif defined MXGUI_ORIENTATION_HORIZONTAL
+        static const short int width    = 160;
+        static const short int height   = 128;
+    #else
+        #error Orientation not defined
+    #endif
+
+    /**
+     * Constructor.
+     * Do not instantiate objects of this type directly from application code.
+     */
+    DisplayImpl();
+
+    /**
+     * Set cursor to desired location
+     * \param point where to set cursor (0<=x<=127, 0<=y<=159)
+     */
+    static inline void setCursor(Point p)
+    {
+        window(p, p, false);
+    }
+
+    /**
+     *  Register 0x36: MADCTL 
+     *       bit 7------0
+     *        4: |||||+--  MH horizontal referesh (0 L-to-R, 1 R-to-L)
+     *        8: ||||+---  RGB BRG order (0 for RGB)
+     *       16: |||+----  ML vertical refesh (0 T-to-B, 1 B-to-T)
+     *       32: ||+-----  MV row column exchange (1 for X-Y exchange)
+     *       64: |+------  MX column address order (1 for mirror X axis)
+     *      128: +-------  MY row address order (1 for mirror Y axis)
+     */
+
+    /**
+     * Set a hardware window on the screen, optimized for writing text.
+     * The GRAM increment will be set to up-to-down first, then left-to-right
+     * which is the correct increment to draw fonts
+     * \param p1 upper left corner of the window
+     * \param p2 lower right corner of the window
+     */
+    static inline void textWindow(Point p1, Point p2)
+    {
+        #ifdef MXGUI_ORIENTATION_VERTICAL
+            writeReg (0x36, 0xE0);      // MADCTL:  MX + MY + MV
+            window(p1, p2, true);
+        #else //MXGUI_ORIENTATION_HORIZONTAL
+            writeReg (0x36, 0x80);      // MADCTL:  MY
+            window(p1, p2, true);
+        #endif
+    }
+
+    /**
+     * Set a hardware window on the screen, optimized for drawing images.
+     * The GRAM increment will be set to left-to-right first, then up-to-down
+     * which is the correct increment to draw images
+     * \param p1 upper left corner of the window
+     * \param p2 lower right corner of the window
+     */
+    static inline void imageWindow(Point p1, Point p2)
+    {
+        #ifdef MXGUI_ORIENTATION_VERTICAL
+            writeReg (0x36, 0xC0);      // MADCTL:  MX + MY
+            window(p1, p2, false);
+        #else //MXGUI_ORIENTATION_HORIZONTAL
+            writeReg (0x36, 0xA0);      // MADCTL:  MY + MV
+            window(p1, p2, false);
+        #endif
+    }
+
+    /**
+     * Common part of all window commands
+     */
+    static void window(Point p1, Point p2, bool swap);
+
+    /**
+     * Sends command 0x2C to signal the start of data sending
+     */
+    static void writeRamBegin()
+    {
+        CommandTransaction c;
+        writeRam(0x2C);     //ST7735_RAMWR, to write the GRAM
+    }
+
+    /**
+     * Used to send pixel data to the display's RAM, and also to send commands.
+     * The SPI chip select must be low before calling this member function
+     * \param data data to write
+     */
+    static unsigned char writeRam(unsigned char data)
+    {
+        SPI2->DR = data;
+        while((SPI2->SR & SPI_SR_RXNE) == 0) ;
+        return SPI2->DR; //Note: reading back SPI2->DR is necessary.
+    }
+
+    /**
+     * Write data to a display register
+     * \param reg which register?
+     * \param data data to write
+     */
+    static void writeReg(unsigned char reg, unsigned char data);
+
+    /**
+     * Write data to a display register
+     * \param reg which register?
+     * \param data data to write, if null only reg will be written (zero arg cmd)
+     * \param len length of data, number of argument bytes
+     */
+    static void writeReg(unsigned char reg, const unsigned char *data=0, int len=1);
+
+    /**
+     * Send multiple commands to the display MCU (we use to send init sequence)
+     * \param cmds static array containing the commands
+     */
+    static void sendCmds(const unsigned char *cmds);
+
+    Color *buffer;          //< For scanLineBuffer
+};
+
+} //namespace mxgui
+
+#endif //_BOARD_STM32F4DISCOVERY
+
+#endif //DISPLAY_ST7735H