Steven Mahasin / Mbed 2 deprecated DreamDungeon

Dependencies:   mbed MotionSensor

Files at this revision

API Documentation at this revision

Comitter:
el17sm
Date:
Sun May 05 18:04:43 2019 +0000
Parent:
29:6b8411bb040a
Child:
31:ab24d028ddfd
Commit message:
Title Screen done;

Changed in this revision

Entity/Player/Player.cpp Show annotated file Show diff for this revision Revisions of this file
Entity/Player/Player.h Show annotated file Show diff for this revision Revisions of this file
FXOS8700Q/FXOS8700Q.cpp Show diff for this revision Revisions of this file
FXOS8700Q/FXOS8700Q.h Show diff for this revision Revisions of this file
FXOS8700Q/MotionSensor.lib Show diff for this revision Revisions of this file
Gamepad/Gamepad.cpp Show diff for this revision Revisions of this file
Gamepad/Gamepad.h Show diff for this revision Revisions of this file
N5110/Bitmap.cpp Show diff for this revision Revisions of this file
N5110/Bitmap.h Show diff for this revision Revisions of this file
N5110/N5110.cpp Show diff for this revision Revisions of this file
N5110/N5110.h Show diff for this revision Revisions of this file
Peripherals/FXOS8700Q/FXOS8700Q.cpp Show annotated file Show diff for this revision Revisions of this file
Peripherals/FXOS8700Q/FXOS8700Q.h Show annotated file Show diff for this revision Revisions of this file
Peripherals/FXOS8700Q/MotionSensor.lib Show annotated file Show diff for this revision Revisions of this file
Peripherals/Gamepad/Gamepad.cpp Show annotated file Show diff for this revision Revisions of this file
Peripherals/Gamepad/Gamepad.h Show annotated file Show diff for this revision Revisions of this file
Peripherals/N5110/Bitmap.cpp Show annotated file Show diff for this revision Revisions of this file
Peripherals/N5110/Bitmap.h Show annotated file Show diff for this revision Revisions of this file
Peripherals/N5110/N5110.cpp Show annotated file Show diff for this revision Revisions of this file
Peripherals/N5110/N5110.h Show annotated file Show diff for this revision Revisions of this file
Room/Room.cpp Show diff for this revision Revisions of this file
Room/Room.h Show diff for this revision Revisions of this file
RoomEngine/Room/Room.cpp Show annotated file Show diff for this revision Revisions of this file
RoomEngine/Room/Room.h Show annotated file Show diff for this revision Revisions of this file
RoomEngine/RoomEngine.cpp Show annotated file Show diff for this revision Revisions of this file
RoomEngine/RoomEngine.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
sprites.h Show annotated file Show diff for this revision Revisions of this file
--- a/Entity/Player/Player.cpp	Sat May 04 15:39:20 2019 +0000
+++ b/Entity/Player/Player.cpp	Sun May 05 18:04:43 2019 +0000
@@ -58,6 +58,14 @@
 // Functions
 void Player::move(float mapped_x, float mapped_y, int * map, bool * doorways)
 {
+    move_player(mapped_x, mapped_y, map, doorways);
+    move_bullets();
+    increment_frames(mapped_x, mapped_y);
+    invulnerability_counter++;
+}
+
+void Player::move_player(float mapped_x, float mapped_y, int * map, bool * doorways)
+{
     if(!entity_to_map_collision_test(position.x + velocity*mapped_x, position.y, map, doorways)) {
         position.x += velocity*mapped_x;
     }
@@ -65,6 +73,19 @@
         position.y -= velocity*mapped_y;
     }
     moving = false;
+}
+
+void Player::move_bullets()
+{
+    for (int i = 0; i < bullets_max; i++) {
+        if (valid_bullets[i]) {
+            bullets_array[i]->move(get_bullet_speed(), 0, 0, (bool *) 0);
+        }
+    }
+}
+
+void Player::increment_frames(float mapped_x, float mapped_y)
+{
     if (abs(mapped_x) + abs(mapped_y) > 0.1f) {
         moving = true;
         if (mapped_y < 0 && abs(mapped_y) > abs(mapped_x)) {
@@ -85,7 +106,6 @@
         frame.count = 0;
     }
     frame.number = (frame.count/8) % frame.max;
-    invulnerability_counter++;
 }
 
 void Player::take_damage(int damage)
@@ -101,6 +121,48 @@
         hp = 5;
     }
 }
+
+bool Player::update_bullets(int * map, bool * doorways)
+{
+    bool result = false;
+    for (int i = 0; i < bullets_max; i++) {
+        if((valid_bullets[i]) && (bullets_array[i]->out_of_bounds_check(map, doorways))) {
+            valid_bullets[i] = false;
+            delete bullets_array[i];
+            result = true;
+        }
+    }
+    return result;
+}
+
+void Player::draw(N5110 &lcd)
+{
+    draw_player(lcd);
+    draw_bullets(lcd);
+}
+
+void Player::draw_player(N5110 &lcd)
+{
+    lcd.drawSpriteTransparent(position.x-sprite_size.offset_x,
+                              position.y-sprite_size.offset_y,
+                              sprite_size.height,
+                              sprite_size.width,
+                              get_frame());
+}
+
+void Player::draw_bullets(N5110 &lcd)
+{
+    for (int i = 0; i < bullets_max; i++) {
+        if (valid_bullets[i]) {
+            lcd.drawSpriteTransparent(bullets_array[i]->get_pos_x()-bullets_array[i]->get_offset_x(),
+                                      bullets_array[i]->get_pos_y()-bullets_array[i]->get_offset_y(),
+                                      bullets_array[i]->get_sprite_height(),
+                                      bullets_array[i]->get_sprite_width(),
+                                      bullets_array[i]->get_frame());
+        }
+    }
+}
+
 void Player::delete_bullets()
 {
     for (int i = 0; i < bullets_max; i++) {
--- a/Entity/Player/Player.h	Sat May 04 15:39:20 2019 +0000
+++ b/Entity/Player/Player.h	Sun May 05 18:04:43 2019 +0000
@@ -2,6 +2,7 @@
 #define PLAYER_H
 #include "Entity.h"
 #include "Bullets.h"
+#include "N5110.h"
 
 const int bullets_max = 20;
 
@@ -16,6 +17,11 @@
     const static int invulnerability_period = 50;
     int invulnerability_counter;
     
+    // Private Functions
+    void move_bullets();
+    void move_player(float mapped_x, float mapped_y, int * map, bool * doorways);
+    void increment_frames(float mapped_x, float mapped_y);
+    
 public:
     // Constructors
     Player(float pos_x, float pos_y);
@@ -33,6 +39,10 @@
     virtual void move(float, float, int * map, bool * doorways);
     virtual void take_damage(int damage);
     virtual int * get_frame();
+    bool update_bullets(int * map, bool * doorways);
+    void draw(N5110 &lcd);
+    void draw_player(N5110 &lcd);
+    void draw_bullets(N5110 &lcd);
     void delete_bullets();
     void buttons(bool button_A, bool button_B, bool button_Y, bool button_X);
 
--- a/FXOS8700Q/FXOS8700Q.cpp	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/* FXOS8700Q sensor driver
- * Copyright (c) 2014-2015 ARM Limited
- *
- * 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 "FXOS8700Q.h"
-
-const uint16_t uint14_max = 0x3FFF;
-void static inline normalize_14bits(int16_t &x)
-{
-    x = ((x) > (uint14_max/2)) ? (x - uint14_max) : (x);
-}
-
-static int16_t dummy_int16_t = 0;
-static float dummy_float = 0.0f;
-
-FXOS8700Q::FXOS8700Q(I2C &i2c, uint8_t addr)
-{
-    _i2c = &i2c;
-    _addr = addr;
-    // activate the peripheral
-    uint8_t data[2] = {FXOS8700Q_CTRL_REG1, 0x00};
-    _i2c->frequency(400000);
-    writeRegs(data, 2);
-    data[0] = FXOS8700Q_M_CTRL_REG1;
-    data[1] = 0x1F;
-    writeRegs(data, 2);
-    data[0] = FXOS8700Q_M_CTRL_REG2;
-    data[1] = 0x20;
-    writeRegs(data, 2);
-    data[0] = FXOS8700Q_XYZ_DATA_CFG;
-    data[1] = 0x00;
-    writeRegs(data, 2);
-    data[0] = FXOS8700Q_CTRL_REG1;
-    data[1] = 0x1C;
-    writeRegs(data, 2);
-}
-
-FXOS8700Q::~FXOS8700Q()
-{
-    _i2c = 0;
-    _addr = 0;
-}
-
-void FXOS8700Q::readRegs(uint8_t addr, uint8_t *data, uint32_t len) const
-{
-    uint8_t t[1] = {addr};
-    _i2c->write(_addr, (char *)t, sizeof(t), true);
-    _i2c->read(_addr, (char *)data, len);
-}
-
-uint8_t FXOS8700Q::whoAmI() const
-{
-    uint8_t who_am_i = 0;
-    readRegs(FXOS8700Q_WHOAMI, &who_am_i, sizeof(who_am_i));
-    return who_am_i;
-}
-
-void FXOS8700Q::writeRegs(uint8_t * data, uint32_t len) const
-{
-    _i2c->write(_addr, (char *)data, len);
-}
-
-
-int16_t FXOS8700Q::getSensorAxis(uint8_t addr) const
-{
-    uint8_t res[2];
-    readRegs(addr, res, sizeof(res));
-    return static_cast<int16_t>((res[0] << 8) | res[1]);
-}
-
-void FXOS8700Q::enable(void) const
-{
-    uint8_t data[2];
-    readRegs(FXOS8700Q_CTRL_REG1, &data[1], 1);
-    data[1] |= 0x01;
-    data[0] = FXOS8700Q_CTRL_REG1;
-    writeRegs(data, sizeof(data));
-}
-
-void FXOS8700Q::disable(void) const
-{
-    uint8_t data[2];
-    readRegs(FXOS8700Q_CTRL_REG1, &data[1], 1);
-    data[1] &= 0xFE;
-    data[0] = FXOS8700Q_CTRL_REG1;
-    writeRegs(data, sizeof(data));
-}
-
-uint32_t FXOS8700Q::dataReady(void) const
-{
-    uint8_t stat = 0;
-    readRegs(FXOS8700Q_STATUS, &stat, 1);
-    return (uint32_t)stat;
-}
-
-uint32_t FXOS8700Q::sampleRate(uint32_t frequency) const
-{
-    return(50); // for now sample rate is fixed at 50Hz
-}
-
-int16_t FXOS8700QAccelerometer::getX(int16_t &x = dummy_int16_t) const
-{
-    x = getSensorAxis(FXOS8700Q_OUT_X_MSB) >> 2;
-    normalize_14bits(x);
-    return x;
-}
-
-int16_t FXOS8700QAccelerometer::getY(int16_t &y = dummy_int16_t) const
-{
-    y = getSensorAxis(FXOS8700Q_OUT_Y_MSB) >> 2;
-    normalize_14bits(y);
-    return y;
-}
-
-int16_t FXOS8700QAccelerometer::getZ(int16_t &z = dummy_int16_t) const
-{
-    z = getSensorAxis(FXOS8700Q_OUT_Z_MSB) >> 2;
-    normalize_14bits(z);
-    return z;
-}
-
-float FXOS8700QAccelerometer::getX(float &x = dummy_float) const
-{
-    int16_t val = getSensorAxis(FXOS8700Q_OUT_X_MSB) >> 2;
-    normalize_14bits(val);
-    x = val / 4096.0f;
-    return x;
-}
-
-float FXOS8700QAccelerometer::getY(float &y = dummy_float) const
-{
-    int16_t val = getSensorAxis(FXOS8700Q_OUT_Y_MSB) >> 2;
-    normalize_14bits(val);
-    y = val / 4096.0f;
-    return y;
-}
-
-float FXOS8700QAccelerometer::getZ(float &z = dummy_float) const
-{
-    int16_t val = getSensorAxis(FXOS8700Q_OUT_Z_MSB) >> 2;
-    normalize_14bits(val);
-    z = val / 4096.0f;
-    return z;
-}
-
-void FXOS8700QAccelerometer::getAxis(motion_data_counts_t &xyz) const
-{
-    uint8_t res[6];
-    readRegs(FXOS8700Q_OUT_X_MSB, res, sizeof(res));
-    xyz.x = static_cast<int16_t>((res[0] << 8) | res[1]) >> 2;
-    xyz.y = static_cast<int16_t>((res[2] << 8) | res[3]) >> 2;
-    xyz.z = static_cast<int16_t>((res[4] << 8) | res[5]) >> 2;
-    normalize_14bits(xyz.x);
-    normalize_14bits(xyz.y);
-    normalize_14bits(xyz.z);
-}
-
-void FXOS8700QAccelerometer::getAxis(motion_data_units_t &xyz) const
-{
-    motion_data_counts_t _xyz;
-    FXOS8700QAccelerometer::getAxis(_xyz);
-    xyz.x = _xyz.x / 4096.0f;
-    xyz.y = _xyz.y / 4096.0f;
-    xyz.z = _xyz.z / 4096.0f;
-}
-
-int16_t FXOS8700QMagnetometer::getX(int16_t &x = dummy_int16_t) const
-{
-    x = getSensorAxis(FXOS8700Q_M_OUT_X_MSB);
-    return x;
-}
-
-int16_t FXOS8700QMagnetometer::getY(int16_t &y = dummy_int16_t) const
-{
-    y = getSensorAxis(FXOS8700Q_M_OUT_Y_MSB);
-    return y;
-}
-
-int16_t FXOS8700QMagnetometer::getZ(int16_t &z = dummy_int16_t) const
-{
-    z = getSensorAxis(FXOS8700Q_M_OUT_Z_MSB);
-    return z;
-}
-
-float FXOS8700QMagnetometer::getX(float &x = dummy_float) const
-{
-    x = static_cast<float>(getSensorAxis(FXOS8700Q_M_OUT_X_MSB)) * 0.1f;
-    return x;
-}
-
-float FXOS8700QMagnetometer::getY(float &y = dummy_float) const
-{
-    y = static_cast<float>(getSensorAxis(FXOS8700Q_M_OUT_Y_MSB)) * 0.1f;
-    return y;
-}
-
-float FXOS8700QMagnetometer::getZ(float &z = dummy_float) const
-{
-    z = static_cast<float>(getSensorAxis(FXOS8700Q_M_OUT_Z_MSB)) * 0.1f;
-    return z;
-}
-
-void FXOS8700QMagnetometer::getAxis(motion_data_counts_t &xyz) const
-{
-    uint8_t res[6];
-    readRegs(FXOS8700Q_M_OUT_X_MSB, res, sizeof(res));
-    xyz.x = (res[0] << 8) | res[1];
-    xyz.y = (res[2] << 8) | res[3];
-    xyz.z = (res[4] << 8) | res[5];
-}
-
-void FXOS8700QMagnetometer::getAxis(motion_data_units_t &xyz) const
-{
-    motion_data_counts_t _xyz;
-    FXOS8700QMagnetometer::getAxis(_xyz);
-    xyz.x = static_cast<float>(_xyz.x * 0.1f);
-    xyz.y = static_cast<float>(_xyz.y * 0.1f);
-    xyz.z = static_cast<float>(_xyz.z * 0.1f);
-}
--- a/FXOS8700Q/FXOS8700Q.h	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/* FXOS8700Q sensor driver
- * Copyright (c) 2014-2015 ARM Limited
- *
- * 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 FXOS8700Q_H
-#define FXOS8700Q_H
-
-#include "mbed.h"
-#include "MotionSensor.h"
-
-// FXOS8700CQ I2C address
-#define FXOS8700CQ_SLAVE_ADDR0 (0x1E<<1) // with pins SA0=0, SA1=0
-#define FXOS8700CQ_SLAVE_ADDR1 (0x1D<<1) // with pins SA0=1, SA1=0
-#define FXOS8700CQ_SLAVE_ADDR2 (0x1C<<1) // with pins SA0=0, SA1=1
-#define FXOS8700CQ_SLAVE_ADDR3 (0x1F<<1) // with pins SA0=1, SA1=1
-// FXOS8700CQ internal register addresses
-#define FXOS8700Q_STATUS 0x00
-#define FXOS8700Q_OUT_X_MSB 0x01
-#define FXOS8700Q_OUT_Y_MSB 0x03
-#define FXOS8700Q_OUT_Z_MSB 0x05
-#define FXOS8700Q_M_OUT_X_MSB 0x33
-#define FXOS8700Q_M_OUT_Y_MSB 0x35
-#define FXOS8700Q_M_OUT_Z_MSB 0x37
-#define FXOS8700Q_WHOAMI 0x0D
-#define FXOS8700Q_XYZ_DATA_CFG 0x0E
-#define FXOS8700Q_CTRL_REG1 0x2A
-#define FXOS8700Q_M_CTRL_REG1 0x5B
-#define FXOS8700Q_M_CTRL_REG2 0x5C
-#define FXOS8700Q_WHOAMI_VAL 0xC7
-
-
-/** FXOS8700Q accelerometer example
-    @code
-    #include "mbed.h"
-    #include "FXOS8700Q.h"
-    I2C i2c(PTE25, PTE24);
-    FXOS8700QAccelerometer acc(i2c, FXOS8700CQ_SLAVE_ADDR1);    // Configured for the FRDM-K64F with onboard sensors
-    FXOS8700QMagnetometer mag(i2c, FXOS8700CQ_SLAVE_ADDR1);
-    int main(void)
-    {
-        motion_data_units_t acc_data, mag_data;
-        motion_data_counts_t acc_raw, mag_raw;
-        float faX, faY, faZ, fmX, fmY, fmZ, tmp_float;
-        int16_t raX, raY, raZ, rmX, rmY, rmZ, tmp_int;
-        acc.enable();
-        mag.enable();
-        while (true) {
-            // counts based results
-            acc.getAxis(acc_raw);
-            mag.getAxis(mag_raw);
-            acc.getX(raX);
-            acc.getY(raY);
-            acc.getZ(raZ);
-            mag.getX(rmX);
-            mag.getY(rmY);
-            mag.getZ(rmZ);
-            // unit based results
-            acc.getAxis(acc_data);
-            mag.getAxis(mag_data);
-            acc.getX(faX);
-            acc.getY(faY);
-            acc.getZ(faZ);
-            mag.getX(fmX);
-            mag.getY(fmY);
-            mag.getZ(fmZ);
-            wait(0.1f);
-        }
-    }
-    @endcode
- */
-
-/** FXOS8700Q driver class
- */
-class FXOS8700Q : public MotionSensor
-{
-public:
-
-    /** Read a device register
-        @param addr The address to read from
-        @param data The data to read from it
-        @param len The amount of data to read from it
-        @return 0 if successful, negative number otherwise
-     */
-    void readRegs(uint8_t addr, uint8_t *data, uint32_t len) const;
-
-    /** Read the ID from a whoAmI register
-        @return The device whoAmI register contents
-     */
-    uint8_t whoAmI(void) const;
-
-    virtual void enable(void) const;
-    virtual void disable(void) const;
-    virtual uint32_t sampleRate(uint32_t frequency) const;
-    virtual uint32_t dataReady(void) const;
-
-protected:
-    I2C *_i2c;
-    uint8_t _addr;
-    
-    /** FXOS8700Q constructor
-        @param i2c a configured i2c object
-        @param addr addr of the I2C peripheral as wired
-     */
-    FXOS8700Q(I2C &i2c, uint8_t addr);
-
-    /** FXOS8700Q deconstructor
-     */
-    ~FXOS8700Q();
-    
-    void writeRegs(uint8_t *data, uint32_t len) const;
-    int16_t getSensorAxis(uint8_t addr) const;
-};
-
-/** FXOS8700QAccelerometer interface
- */
-class FXOS8700QAccelerometer : public FXOS8700Q
-{
-public:
-
-    FXOS8700QAccelerometer(I2C &i2c, uint8_t addr) : FXOS8700Q(i2c, addr) {}
-
-    virtual int16_t getX(int16_t &x) const;
-    virtual int16_t getY(int16_t &y) const;
-    virtual int16_t getZ(int16_t &z) const;
-    virtual float getX(float &x) const;
-    virtual float getY(float &y) const;
-    virtual float getZ(float &z) const;
-    virtual void getAxis(motion_data_counts_t &xyz) const;
-    virtual void getAxis(motion_data_units_t &xyz) const;
-
-};
-
-/** FXOS8700QMagnetometer interface
- */
-class FXOS8700QMagnetometer : public FXOS8700Q
-{
-public:
-
-    FXOS8700QMagnetometer(I2C &i2c, uint8_t addr) : FXOS8700Q(i2c, addr) {}
-
-    virtual int16_t getX(int16_t &x) const;
-    virtual int16_t getY(int16_t &y) const;
-    virtual int16_t getZ(int16_t &z) const;
-    virtual float getX(float &x) const;
-    virtual float getY(float &y) const;
-    virtual float getZ(float &z) const;
-    virtual void getAxis(motion_data_counts_t &xyz) const;
-    virtual void getAxis(motion_data_units_t &xyz) const;
-
-};
-
-#endif
--- a/FXOS8700Q/MotionSensor.lib	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/teams/components/code/MotionSensor/#226520fc09bf
--- a/Gamepad/Gamepad.cpp	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,391 +0,0 @@
-#include "Gamepad.h"
-
-#include "mbed.h"
-
-//////////// constructor/destructor ////////////
-Gamepad::Gamepad()
-    :
-    _led1(new PwmOut(PTA1)),
-    _led2(new PwmOut(PTA2)),
-    _led3(new PwmOut(PTC2)),
-    _led4(new PwmOut(PTC3)),
-    _led5(new PwmOut(PTC4)),
-    _led6(new PwmOut(PTD3)),
-
-    _button_A(new InterruptIn(PTB9)),
-    _button_B(new InterruptIn(PTD0)),
-    _button_X(new InterruptIn(PTC17)),
-    _button_Y(new InterruptIn(PTC12)),
-    _button_L(new InterruptIn(PTB18)),
-    _button_R(new InterruptIn(PTB3)),
-    _button_back(new InterruptIn(PTB19)),
-    _button_start(new InterruptIn(PTC5)),
-    _button_joystick(new InterruptIn(PTC16)),
-
-    _vert(new AnalogIn(PTB10)),
-    _horiz(new AnalogIn(PTB11)),
-
-    _buzzer(new PwmOut(PTC10)),
-    _pot(new AnalogIn(PTB2)),
-
-    _timeout(new Timeout()),
-
-    _event_state(0),
-
-    _x0(0),
-    _y0(0)
-{}
-
-Gamepad::~Gamepad()
-{
-    delete _led1,_led2,_led3,_led4,_led5,_led6;
-    delete _button_A,_button_B,_button_joystick,_vert,_horiz;
-    delete _button_X,_button_Y,_button_back,_button_start;
-    delete _button_L,_button_R, _buzzer, _pot, _timeout;
-}
-
-///////////////// public methods /////////////////
-
-void Gamepad::init()
-{
-    leds_off();
-    init_buttons();
-
-    // read centred values of joystick
-    _x0 = _horiz->read();
-    _y0 = _vert->read();
-
-    // clear all flags
-    _event_state = 0;
-}
-
-void Gamepad::leds_off()
-{
-    leds(0.0);
-}
-
-void Gamepad::leds_on()
-{
-    leds(1.0);
-}
-
-void Gamepad::leds(float val) const
-{
-    if (val < 0.0f) {
-        val = 0.0f;
-    }
-    if (val > 1.0f) {
-        val = 1.0f;
-    }
-
-    // leds are active-low, so subtract from 1.0
-    // 0.0 corresponds to fully-off, 1.0 to fully-on
-    val = 1.0f - val;
-
-    _led1->write(val);
-    _led2->write(val);
-    _led3->write(val);
-    _led4->write(val);
-    _led5->write(val);
-    _led6->write(val);
-}
-
-void Gamepad::led(int n,float val) const
-{
-    // ensure they are within vlaid range
-    if (val < 0.0f) {
-        val = 0.0f;
-    }
-    if (val > 1.0f) {
-        val = 1.0f;
-    }
-
-    switch (n) {
-
-        // check for valid LED number and set value
-
-        case 1:
-            _led1->write(1.0f-val);   // active-low so subtract from 1
-            break;
-        case 2:
-            _led2->write(1.0f-val);   // active-low so subtract from 1
-            break;
-        case 3:
-            _led3->write(1.0f-val);   // active-low so subtract from 1
-            break;
-        case 4:
-            _led4->write(1.0f-val);   // active-low so subtract from 1
-            break;
-        case 5:
-            _led5->write(1.0f-val);   // active-low so subtract from 1
-            break;
-        case 6:
-            _led6->write(1.0f-val);   // active-low so subtract from 1
-            break;
-
-    }
-}
-
-float Gamepad::read_pot() const
-{
-    return _pot->read();
-}
-
-void Gamepad::tone(float frequency, float duration)
-{
-    _buzzer->period(1.0f/frequency);
-    _buzzer->write(0.5);  // 50% duty cycle - square wave
-    _timeout->attach(callback(this, &Gamepad::tone_off), duration );
-}
-
-bool Gamepad::check_event(GamepadEvent const id)
-{
-    // Check whether event flag is set
-    if (_event_state[id]) {
-//        _event_state.reset(id);  // clear flag
-        return true;
-    } else {
-        return false;
-    }
-}
-
-// this method gets the magnitude of the joystick movement
-float Gamepad::get_mag()
-{
-    Polar p = get_polar();
-    return p.mag;
-}
-
-// this method gets the angle of joystick movement (0 to 360, 0 North)
-float Gamepad::get_angle()
-{
-    Polar p = get_polar();
-    return p.angle;
-}
-
-Direction Gamepad::get_direction()
-{
-    float angle = get_angle();  // 0 to 360, -1 for centred
-
-    Direction d;
-    // partition 360 into segments and check which segment the angle is in
-    if (angle < 0.0f) {
-        d = CENTRE;   // check for -1.0 angle
-    } else if (angle < 22.5f) {  // then keep going in 45 degree increments
-        d = N;
-    } else if (angle < 67.5f) {
-        d = NE;
-    } else if (angle < 112.5f) {
-        d = E;
-    } else if (angle < 157.5f) {
-        d = SE;
-    } else if (angle < 202.5f) {
-        d = S;
-    } else if (angle < 247.5f) {
-        d = SW;
-    } else if (angle < 292.5f) {
-        d = W;
-    } else if (angle < 337.5f) {
-        d = NW;
-    } else {
-        d = N;
-    }
-
-    return d;
-}
-
-///////////////////// private methods ////////////////////////
-
-void Gamepad::tone_off()
-{
-    // called after timeout
-    _buzzer->write(0.0);
-}
-
-void Gamepad::init_buttons()
-{
-    // turn on pull-downs as other side of button is connected to 3V3
-    // button is 0 when not pressed and 1 when pressed
-    _button_A->mode(PullDown);
-    _button_B->mode(PullDown);
-    _button_X->mode(PullDown);
-    _button_Y->mode(PullDown);
-    _button_back->mode(PullDown);
-    _button_start->mode(PullDown);
-    _button_L->mode(PullDown);
-    _button_R->mode(PullDown);
-    _button_joystick->mode(PullDown);
-    // therefore setup rising edge interrupts
-    _button_A->rise(callback(this,&Gamepad::a_isr));
-    _button_B->rise(callback(this,&Gamepad::b_isr));
-    _button_X->rise(callback(this,&Gamepad::x_isr));
-    _button_Y->rise(callback(this,&Gamepad::y_isr));
-    _button_L->rise(callback(this,&Gamepad::l_isr));
-    _button_R->rise(callback(this,&Gamepad::r_isr));
-    _button_start->rise(callback(this,&Gamepad::start_isr));
-    _button_back->rise(callback(this,&Gamepad::back_isr));
-    _button_joystick->rise(callback(this,&Gamepad::joy_isr));
-    // therefore setup falling edge interrupts
-    _button_A->fall(callback(this,&Gamepad::a_reset_isr));
-    _button_B->fall(callback(this,&Gamepad::b_reset_isr));
-    _button_X->fall(callback(this,&Gamepad::x_reset_isr));
-    _button_Y->fall(callback(this,&Gamepad::y_reset_isr));
-    _button_L->fall(callback(this,&Gamepad::l_reset_isr));
-    _button_R->fall(callback(this,&Gamepad::r_reset_isr));
-    _button_start->fall(callback(this,&Gamepad::start_reset_isr));
-    _button_back->fall(callback(this,&Gamepad::back_reset_isr));
-    _button_joystick->fall(callback(this,&Gamepad::joy_reset_isr));
-}
-
-// button interrupts ISRs
-// Each of these simply sets the appropriate event bit in the _event_state
-// variable
-void Gamepad::a_isr()
-{
-    _event_state.set(A_PRESSED);
-}
-void Gamepad::b_isr()
-{
-    _event_state.set(B_PRESSED);
-}
-void Gamepad::x_isr()
-{
-    _event_state.set(X_PRESSED);
-}
-void Gamepad::y_isr()
-{
-    _event_state.set(Y_PRESSED);
-}
-void Gamepad::l_isr()
-{
-    _event_state.set(L_PRESSED);
-}
-void Gamepad::r_isr()
-{
-    _event_state.set(R_PRESSED);
-}
-void Gamepad::back_isr()
-{
-    _event_state.set(BACK_PRESSED);
-}
-void Gamepad::start_isr()
-{
-    _event_state.set(START_PRESSED);
-}
-void Gamepad::joy_isr()
-{
-    _event_state.set(JOY_PRESSED);
-}
-
-// button interrupts ISRs
-// Each of these simply resets the appropriate event bit in the _event_state
-// variable
-void Gamepad::a_reset_isr()
-{
-    _event_state.reset(A_PRESSED);
-}
-void Gamepad::b_reset_isr()
-{
-    _event_state.reset(B_PRESSED);
-}
-void Gamepad::x_reset_isr()
-{
-    _event_state.reset(X_PRESSED);
-}
-void Gamepad::y_reset_isr()
-{
-    _event_state.reset(Y_PRESSED);
-}
-void Gamepad::l_reset_isr()
-{
-    _event_state.reset(L_PRESSED);
-}
-void Gamepad::r_reset_isr()
-{
-    _event_state.reset(R_PRESSED);
-}
-void Gamepad::back_reset_isr()
-{
-    _event_state.reset(BACK_PRESSED);
-}
-void Gamepad::start_reset_isr()
-{
-    _event_state.reset(START_PRESSED);
-}
-void Gamepad::joy_reset_isr()
-{
-    _event_state.reset(JOY_PRESSED);
-}
-
-// get raw joystick coordinate in range -1 to 1
-// Direction (x,y)
-// North     (0,1)
-// East      (1,0)
-// South     (0,-1)
-// West      (-1,0)
-Vector2D Gamepad::get_coord()
-{
-    // read() returns value in range 0.0 to 1.0 so is scaled and centre value
-    // substracted to get values in the range -1.0 to 1.0
-    float x = 2.0f*( _horiz->read() - _x0 );
-    float y = 2.0f*( _vert->read()  - _y0 );
-
-    // Note: the x value here is inverted to ensure the positive x is to the
-    // right. This is simply due to how the potentiometer on the joystick
-    // I was using was connected up. It could have been corrected in hardware
-    // by swapping the power supply pins. Instead it is done in software so may
-    // need to be changed depending on your wiring setup
-
-    Vector2D coord = {-x,y};
-    return coord;
-}
-
-// This maps the raw x,y coord onto a circular grid.
-// See:  http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html
-Vector2D Gamepad::get_mapped_coord()
-{
-    Vector2D coord = get_coord();
-
-    // do the transformation
-    float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f);
-    float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f);
-
-    Vector2D mapped_coord = {x,y};
-    return mapped_coord;
-}
-
-// this function converts the mapped coordinates into polar form
-Polar Gamepad::get_polar()
-{
-    // get the mapped coordinate
-    Vector2D coord = get_mapped_coord();
-
-    // at this point, 0 degrees (i.e. x-axis) will be defined to the East.
-    // We want 0 degrees to correspond to North and increase clockwise to 359
-    // like a compass heading, so we need to swap the axis and invert y
-    float x = coord.y;
-    float y = coord.x;
-
-    float mag = sqrt(x*x+y*y);  // pythagoras
-    float angle = RAD2DEG*atan2(y,x);
-    // angle will be in range -180 to 180, so add 360 to negative angles to
-    // move to 0 to 360 range
-    if (angle < 0.0f) {
-        angle+=360.0f;
-    }
-
-    // the noise on the ADC causes the values of x and y to fluctuate slightly
-    // around the centred values. This causes the random angle values to get
-    // calculated when the joystick is centred and untouched. This is also when
-    // the magnitude is very small, so we can check for a small magnitude and then
-    // set the angle to -1. This will inform us when the angle is invalid and the
-    // joystick is centred
-
-    if (mag < TOL) {
-        mag = 0.0f;
-        angle = -1.0f;
-    }
-
-    Polar p = {mag,angle};
-    return p;
-}
\ No newline at end of file
--- a/Gamepad/Gamepad.h	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-#ifndef GAMEPAD_H
-#define GAMEPAD_H
-
-#include <bitset>
-
-// Forward declaration of the classes that we use from the mbed library
-// This avoids the need for us to include the huge mbed.h header inside our
-// own library API
-namespace mbed
-{
-class AnalogIn;
-class InterruptIn;
-class PwmOut;
-class Timeout;
-}
-
-#define TOL 0.1f
-#define RAD2DEG 57.2957795131f
-
-/** Enum for direction */
-enum Direction {
-    CENTRE,  /**< joystick centred */
-    N,       /**< pushed North (0)*/
-    NE,      /**< pushed North-East (45) */
-    E,       /**< pushed East (90) */
-    SE,      /**< pushed South-East (135) */
-    S,       /**< pushed South (180) */
-    SW,      /**< pushed South-West (225) */
-    W,       /**< pushed West (270) */
-    NW       /**< pushed North-West (315) */
-};
-
-/** Vector 2D struct */
-struct Vector2D {
-    float x; /**< float for x value */
-    float y; /**< float for y value */
-};
-
-/** Polar coordinate struct */
-struct Polar {
-    float mag;  /**< float for magnitude */
-    float angle; /**< float for angle (in degrees) */
-};
-
-/** Gamepad Class
- * @brief Library for interfacing with ELEC2645 Gamepad PCB, University of Leeds
- * @author Dr Craig A. Evans
- * @author Dr Alex Valavanis
- */
-class Gamepad
-{
-public:
-    /** Gamepad events
-     * @brief List of events that can be registered on the gamepad
-     */
-    enum GamepadEvent {
-        A_PRESSED,     ///< Button A has been pressed
-        B_PRESSED,     ///< Button B has been pressed
-        X_PRESSED,     ///< Button X has been pressed
-        Y_PRESSED,     ///< Button Y has been pressed
-        L_PRESSED,     ///< Button L has been pressed
-        R_PRESSED,     ///< Button R has been pressed
-        BACK_PRESSED,  ///< Button "Back" has been pressed
-        START_PRESSED, ///< Button "Start" has been pressed
-        JOY_PRESSED,   ///< Joystick button has been pressed
-        N_EVENTS       ///< A dummy flag that marks the end of the list
-    };
-
-private:
-    mbed::PwmOut *_led1;
-    mbed::PwmOut *_led2;
-    mbed::PwmOut *_led3;
-    mbed::PwmOut *_led4;
-    mbed::PwmOut *_led5;
-    mbed::PwmOut *_led6;
-
-    mbed::InterruptIn *_button_A;
-    mbed::InterruptIn *_button_B;
-    mbed::InterruptIn *_button_X;
-    mbed::InterruptIn *_button_Y;
-    mbed::InterruptIn *_button_L;
-    mbed::InterruptIn *_button_R;
-    mbed::InterruptIn *_button_back;
-    mbed::InterruptIn *_button_start;
-    mbed::InterruptIn *_button_joystick;
-
-    mbed::AnalogIn *_vert;
-    mbed::AnalogIn *_horiz;
-
-    mbed::PwmOut   *_buzzer;
-    mbed::AnalogIn *_pot;
-
-    mbed::Timeout *_timeout;
-
-    std::bitset<N_EVENTS> _event_state; ///< A binary list of buttons that has been pressed
-
-    // centred x,y values
-    float _x0;
-    float _y0;
-
-public:
-    /** Constructor */
-    Gamepad();
-
-    /** Destructor */
-    ~Gamepad();
-
-    /** Initialise all peripherals and configure interrupts */
-    void init();
-
-    /** Turn all LEDs on */
-    void leds_on();
-
-    /** Turn all LEDs off */
-    void leds_off();
-
-    /** Set all LEDs to duty-cycle
-    *@param value in range 0.0 to 1.0
-    */
-    void leds(float val) const;
-
-    /** Set LED to duty-cycle
-    *@param led number (0 to 5)
-    *@param value in range 0.0 to 1.0
-    */
-    void led(int n,float val) const;
-
-    /** Read potentiometer
-    *@returns potentiometer value in range 0.0 to 1.0
-    */
-    float read_pot() const;
-
-    /** Play tone on piezo
-    * @param frequency in Hz
-    * @param duration of tone in seconds
-    */
-    void tone(float frequency, float duration);
-
-    /**
-     * @brief Check whether an event flag has been set and clear it
-     * @param id[in] The ID of the event to test
-     * @return true if the event occurred
-     */
-    bool check_event(GamepadEvent const id);
-
-    /**
-     * @brief   Get the raw binary event state
-     * @return  The event state as a binary code
-     * @details The check_event() function is likely to be more useful than
-     *          this, for testing whether a given event has occurred. It can be
-     *          useful for debugging via the terminal, however, for example:
-     *          @code
-     *          std::cout << gamepad.get_raw_event_state() << std::endl;
-     *          @endcode
-     */
-    inline std::bitset<N_EVENTS> get_raw_event_state() const
-    {
-        return _event_state;
-    }
-
-    /** Get magnitude of joystick movement
-    * @returns value in range 0.0 to 1.0
-    */
-    float get_mag();
-
-    /** Get angle of joystick movement
-    * @returns value in range 0.0 to 359.9. 0.0 corresponds to N, 180.0 to S. -1.0 is central
-    */
-    float get_angle();
-
-    /** Gets joystick direction
-    * @returns an enum: CENTRE, N, NE, E, SE, S, SW, W, NW,
-    */
-    Direction get_direction();    // N,NE,E,SE etc.
-
-    /** Gets raw cartesian co-ordinates of joystick
-    * @returns a struct with x,y members, each in the range 0.0 to 1.0
-    */
-    Vector2D get_coord();         // cartesian co-ordinates x,y
-
-    /** Gets cartesian coordinates mapped to circular grid
-    * @returns a struct with x,y members, each in the range 0.0 to 1.0
-    */
-    Vector2D get_mapped_coord();  // x,y mapped to circle
-
-    /** Gets polar coordinates of the joystick
-    * @returns a struct contains mag and angle
-    */
-    Polar get_polar();            // mag and angle in struct form
-
-private:
-    void init_buttons();
-    void tone_off();
-
-    void a_reset_isr();
-    void b_reset_isr();
-    void x_reset_isr();
-    void y_reset_isr();
-    void l_reset_isr();
-    void r_reset_isr();
-    void back_reset_isr();
-    void start_reset_isr();
-    void joy_reset_isr();
-
-    void a_isr();
-    void b_isr();
-    void x_isr();
-    void y_isr();
-    void l_isr();
-    void r_isr();
-    void back_isr();
-    void start_isr();
-    void joy_isr();
-};
-
-#endif
\ No newline at end of file
--- a/N5110/Bitmap.cpp	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-#include "Bitmap.h"
-
-#include <iostream>
-
-#include "N5110.h"
-
-Bitmap::Bitmap(int const               *contents,
-               unsigned int const       height,
-               unsigned int const       width)
-    :
-    _contents(std::vector<int>(height*width)),
-    _height(height),
-    _width(width)
-{
-    // Perform a quick sanity check of the dimensions
-    if (_contents.size() != height * width) {
-        std::cerr << "Contents of bitmap has size " << _contents.size()
-                  << " pixels, but its dimensions were specified as "
-                  << width << " * " << height << " = " << width * height << std::endl;
-    }
-
-    for(unsigned int i = 0; i < height*width; ++i) _contents[i] = contents[i];
-}
-
-/**
- * @returns the value of the pixel at the given position
- */
-int Bitmap::get_pixel(unsigned int const row,
-                      unsigned int const column) const
-{
-    // First check that row and column indices are within bounds
-    if(column >= _width || row >= _height)
-    {
-        std::cerr << "The requested pixel with index " << row << "," << column
-                  << "is outside the bitmap dimensions: " << _width << ","
-                  << _height << std::endl;
-    }
-
-    // Now return the pixel value, using row-major indexing
-    return _contents[row * _width + column];
-}
-
-/**
- * @brief Prints the contents of the bitmap to the terminal
- */
-void Bitmap::print() const
-{
-    for (unsigned int row = 0; row < _height; ++row)
-    {
-        // Print each element of the row
-        for (unsigned int column = 0; column < _width; ++column)
-        {
-            int pixel = get_pixel(row, column);
-            std::cout << pixel;
-        }
-
-        // And then terminate with a new-line character
-        std::cout << std::endl;
-    }
-}
-
-/**
- * @brief Renders the contents of the bitmap onto an N5110 screen
- *
- * @param[in] lcd The screen to use for rendering
- * @param[in] x0  The horizontal position in pixels at which to render the bitmap
- * @param[in] y0  The vertical position in pixels at which to render the bitmap
- *
- * @details Note that x0, y0 gives the location of the top-left of the bitmap on
- *          the screen.
- *          This function only updates the buffer on the screen.  You still need
- *          to refresh the screen in order to actually see the bitmap.
- */
-void Bitmap::render(N5110 &lcd,
-                    unsigned int const x0,
-                    unsigned int const y0) const
-{
-    // Loop through each row of the bitmap image
-    for (unsigned int bitmap_row = 0; bitmap_row < _height; ++bitmap_row)
-    {
-        // Row index on the screen for rendering the row of pixels
-        unsigned int screen_row = y0 + bitmap_row;
-                
-        // Render each pixel in the row
-        for (unsigned int bitmap_col = 0; bitmap_col < _width; ++bitmap_col)
-        {
-            // Column index on the screen for rendering this pixel
-            int screen_col = x0 + bitmap_col;
-
-            // Find the required value of the pixel at the given location within
-            // the bitmap data and then write it to the LCD screen
-            int pixel = get_pixel(bitmap_row, bitmap_col);
-            lcd.setPixel(screen_col, screen_row, pixel);
-        }
-    }
-}
\ No newline at end of file
--- a/N5110/Bitmap.h	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-#ifndef BITMAP_H
-#define BITMAP_H
-
-#include <vector>
-
-// Forward declarations
-class N5110;
-
-/**
- * @brief  A black & white bitmap that can be rendered on an N5110 screen
- * @author Alex Valavanis <a.valavanis@leeds.ac.uk>
- * 
- * @code
-  // First declare the pixel map data using '1' for black,
-  // or '0' for white pixels
-  static int sprite_data[] = {
-    0,0,1,0,0,
-    0,1,1,1,0,
-    0,0,1,0,0,
-    0,1,1,1,0,
-    1,1,1,1,1,
-    1,1,1,1,1,
-    1,1,0,1,1,
-    1,1,0,1,1
-  };
-
-  // Instantiate the Bitmap object using the data above
-  Bitmap sprite(sprite_data, 8, 5); // Specify rows and columns in sprite
-  
-  // We can render the bitmap wherever we want on the screen
-  sprite.render(lcd, 20, 6); // x and y locations for rendering
-  sprite.render(lcd, 30, 10);
-  
-  // We can also print its values to the terminal
-  sprite.print();
- * @endcode
- */
-class Bitmap
-{
-private:
-    /**
-     * @brief The contents of the drawing, with pixels stored in row-major order
-     * @details '1' represents a black pixel; '0' represents white
-     */
-    std::vector<int> _contents;
-    
-    unsigned int _height; ///< The height of the drawing in pixels
-    unsigned int _width;  ///< The width of the drawing in pixels
-    
-public:
-    Bitmap(int const          *contents,
-           unsigned int const  height,
-           unsigned int const  width);
-
-    int get_pixel(unsigned int const row,
-                  unsigned int const column) const;
-
-    void print() const;
-
-    void render(N5110 &lcd,
-                unsigned int const x0,
-                unsigned int const y0) const;
-};
-
-#endif // BITMAP_H
\ No newline at end of file
--- a/N5110/N5110.cpp	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,530 +0,0 @@
-#include "mbed.h"
-#include "N5110.h"
-
-// overloaded constructor includes power pin - LCD Vcc connected to GPIO pin
-// this constructor works fine with LPC1768 - enough current sourced from GPIO
-// to power LCD. Doesn't work well with K64F.
-N5110::N5110(PinName const pwrPin,
-             PinName const scePin,
-             PinName const rstPin,
-             PinName const dcPin,
-             PinName const mosiPin,
-             PinName const sclkPin,
-             PinName const ledPin)
-    :
-    _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
-    _led(new PwmOut(ledPin)),
-    _pwr(new DigitalOut(pwrPin)),
-    _sce(new DigitalOut(scePin)),
-    _rst(new DigitalOut(rstPin)),
-    _dc(new DigitalOut(dcPin))
-{}
-
-// overloaded constructor does not include power pin - LCD Vcc must be tied to +3V3
-// Best to use this with K64F as the GPIO hasn't sufficient output current to reliably
-// drive the LCD.
-N5110::N5110(PinName const scePin,
-             PinName const rstPin,
-             PinName const dcPin,
-             PinName const mosiPin,
-             PinName const sclkPin,
-             PinName const ledPin)
-    :
-    _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
-    _led(new PwmOut(ledPin)),
-    _pwr(NULL), // pwr not needed so null it to be safe
-    _sce(new DigitalOut(scePin)),
-    _rst(new DigitalOut(rstPin)),
-    _dc(new DigitalOut(dcPin))
-{}
-
-N5110::~N5110()
-{
-    delete _spi;
-
-    if(_pwr) {
-        delete _pwr;
-    }
-
-    delete _led;
-    delete _sce;
-    delete _rst;
-    delete _dc;
-}
-
-// initialise function - powers up and sends the initialisation commands
-void N5110::init()
-{
-    turnOn();     // power up
-    reset();      // reset LCD - must be done within 100 ms
-    initSPI();    
-    
-    setContrast(0.55);  // this may need tuning (say 0.4 to 0.6)
-    setBias(3);   // datasheet - 48:1 mux - don't mess with if you don't know what you're doing! (0 to 7)
-    setTempCoefficient(0); // datasheet - may need increasing (range 0 to 3) at very low temperatures
-    normalMode();  // normal video mode by default
-    
-    clearRAM();      // RAM is undefined at power-up so clear to be sure
-    clear();   // clear buffer
-    setBrightness(0.5);
-}
-
-// sets normal video mode (black on white)
-void N5110::normalMode()
-{
-    sendCommand(0b00100000);   // basic instruction
-    sendCommand(0b00001100);  // normal video mode- datasheet
-}
-
-// sets normal video mode (white on black)
-void N5110::inverseMode()
-{
-    sendCommand(0b00100000);   // basic instruction
-    sendCommand(0b00001101);   // inverse video mode - datasheet
-}
-
-// function to power up the LCD and backlight - only works when using GPIO to power
-void N5110::turnOn()
-{
-    if (_pwr != NULL) {
-        _pwr->write(1);  // apply power
-    }
-}
-
-// function to power down LCD
-void N5110::turnOff()
-{
-    clear(); // clear buffer
-    refresh();
-    setBrightness(0.0);  // turn backlight off
-    clearRAM();   // clear RAM to ensure specified current consumption
-    // send command to ensure we are in basic mode
-    
-    sendCommand(0b00100000); // basic mode
-    sendCommand(0b00001000); // clear display
-    sendCommand(0b00100001); // extended mode
-    sendCommand(0b00100100); // power down
-    
-    // if we are powering the LCD using the GPIO then make it low to turn off
-    if (_pwr != NULL) {
-        wait_ms(10);  // small delay and then turn off the power pin
-        _pwr->write(0);  // turn off power
-    }
-
-}
-
-// function to change LED backlight brightness
-void N5110::setBrightness(float brightness)
-{
-    // check whether brightness is within range
-    if (brightness < 0.0f)
-        brightness = 0.0f;
-    if (brightness > 1.0f)
-        brightness = 1.0f;
-    // set PWM duty cycle
-    _led->write(brightness);
-}
-
-void N5110::setContrast(float contrast) {
-    
-    // enforce limits
-    if (contrast > 1.0f)
-        contrast = 1.0f;
-    else if (contrast < 0.0f)
-        contrast = 0.0;
-    
-    // convert to char in range 0 to 127 (i.e. 6 bits)
-    char ic = char(contrast*127.0f);
-    
-    sendCommand(0b00100001);  // extended instruction set
-    sendCommand(0b10000000 | ic);   // set Vop (which controls contrast)
-    sendCommand(0b00100000);  // back to basic instruction set
-}
-
-void N5110::setTempCoefficient(char tc) {
-    
-    // enforce limits
-    if (tc>3) {
-        tc=3;
-    }
-    
-    // temperature coefficient may need increasing at low temperatures
-
-    sendCommand(0b00100001);  // extended instruction set
-    sendCommand(0b00000100 | tc);
-    sendCommand(0b00100000);  // back to basic instruction set
-}
-    
-void N5110::setBias(char bias) {
-    
-    // from data sheet
-    // bias      mux rate
-    // 0        1:100
-    // 1        1:80
-    // 2        1:65
-    // 3        1:48   (default)
-    // 4        1:40/1:34
-    // 5        1:24
-    // 6        1:18/1:16
-    // 7        1:10/1:9/1:8
-    
-    // enforce limits
-    if (bias>7) {
-        bias=7;
-    }
-        
-    sendCommand(0b00100001);  // extended mode instruction
-    sendCommand(0b00010000 | bias);  
-    sendCommand(0b00100000); // end of extended mode instruction
-}
-
-// pulse the active low reset line
-void N5110::reset()
-{
-    _rst->write(0);  // reset the LCD
-    _rst->write(1);
-}
-
-// function to initialise SPI peripheral
-void N5110::initSPI()
-{
-    _spi->format(8,1);    // 8 bits, Mode 1 - polarity 0, phase 1 - base value of clock is 0, data captured on falling edge/propagated on rising edge
-    _spi->frequency(4000000);  // maximum of screen is 4 MHz
-}
-
-// send a command to the display
-void N5110::sendCommand(unsigned char command)
-{
-    _dc->write(0);  // set DC low for command
-    _sce->write(0); // set CE low to begin frame
-    _spi->write(command);  // send command
-    _dc->write(1);  // turn back to data by default
-    _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
-}
-
-// send data to the display at the current XY address
-// dc is set to 1 (i.e. data) after sending a command and so should
-// be the default mode.
-void N5110::sendData(unsigned char data)
-{
-    _sce->write(0);   // set CE low to begin frame
-    _spi->write(data);
-    _sce->write(1);  // set CE high to end frame (expected for transmission of single byte)
-}
-
-// this function writes 0 to the 504 bytes to clear the RAM
-void N5110::clearRAM()
-{
-    _sce->write(0);  //set CE low to begin frame
-    for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
-        _spi->write(0x00);  // send 0's
-    }
-    _sce->write(1); // set CE high to end frame
-}
-
-// function to set the XY address in RAM for subsequenct data write
-void N5110::setXYAddress(unsigned int const x,
-                         unsigned int const y)
-{
-    if (x<WIDTH && y<HEIGHT) {  // check within range
-        sendCommand(0b00100000);  // basic instruction
-        sendCommand(0b10000000 | x);  // send addresses to display with relevant mask
-        sendCommand(0b01000000 | y);
-    }
-}
-
-// These functions are used to set, clear and get the value of pixels in the display
-// Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x).  The refresh()
-// function must be called after set and clear in order to update the display
-void N5110::setPixel(unsigned int const x,
-                     unsigned int const y,
-                     bool const         state)
-{
-    if (x<WIDTH && y<HEIGHT) {  // check within range
-        // calculate bank and shift 1 to required position in the data byte
-        if(state) buffer[x][y/8] |= (1 << y%8);
-        else      buffer[x][y/8] &= ~(1 << y%8);
-    }
-}
-
-void N5110::clearPixel(unsigned int const x,
-                       unsigned int const y)
-{
-    if (x<WIDTH && y<HEIGHT) {  // check within range
-        // calculate bank and shift 1 to required position (using bit clear)
-        buffer[x][y/8] &= ~(1 << y%8);
-    }
-}
-
-int N5110::getPixel(unsigned int const x,
-                    unsigned int const y) const
-{
-    if (x<WIDTH && y<HEIGHT) {  // check within range
-        // return relevant bank and mask required bit
-
-        int pixel = (int) buffer[x][y/8] & (1 << y%8);
-
-        if (pixel)
-            return 1;
-        else
-            return 0;
-    }
-
-    return 0;
-
-}
-
-// function to refresh the display
-void N5110::refresh()
-{
-    setXYAddress(0,0);  // important to set address back to 0,0 before refreshing display
-    // address auto increments after printing string, so buffer[0][0] will not coincide
-    // with top-left pixel after priting string
-
-    _sce->write(0);  //set CE low to begin frame
-
-    for(int j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
-        for(int i = 0; i < WIDTH; i++) {
-            _spi->write(buffer[i][j]);  // send buffer
-        }
-    }
-    _sce->write(1); // set CE high to end frame
-
-}
-
-// fills the buffer with random bytes.  Can be used to test the display.
-// The rand() function isn't seeded so it probably creates the same pattern everytime
-void N5110::randomiseBuffer()
-{
-    int i,j;
-    for(j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
-        for(i = 0; i < WIDTH; i++) {
-            buffer[i][j] = rand()%256;  // generate random byte
-        }
-    }
-
-}
-
-// function to print 5x7 font
-void N5110::printChar(char const          c,
-                      unsigned int const  x,
-                      unsigned int const  y)
-{
-    if (y<BANKS) {  // check if printing in range of y banks
-
-        for (int i = 0; i < 5 ; i++ ) {
-            int pixel_x = x+i;
-            if (pixel_x > WIDTH-1)  // ensure pixel isn't outside the buffer size (0 - 83)
-                break;
-            buffer[pixel_x][y] = font5x7[(c - 32)*5 + i];
-            // array is offset by 32 relative to ASCII, each character is 5 pixels wide
-        }
-
-    }
-}
-
-// function to print string at specified position
-void N5110::printString(const char         *str,
-                        unsigned int const  x,
-                        unsigned int const  y)
-{
-    if (y<BANKS) {  // check if printing in range of y banks
-
-        int n = 0 ; // counter for number of characters in string
-        // loop through string and print character
-        while(*str) {
-
-            // writes the character bitmap data to the buffer, so that
-            // text and pixels can be displayed at the same time
-            for (int i = 0; i < 5 ; i++ ) {
-                int pixel_x = x+i+n*6;
-                if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83)
-                    break;
-                buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i];
-            }
-            str++;  // go to next character in string
-            n++;    // increment index
-        }
-    }
-}
-
-// function to clear the screen buffer
-void N5110::clear()
-{
-    memset(buffer,0,sizeof(buffer));
-}
-
-// function to plot array on display
-void N5110::plotArray(float const array[])
-{
-    for (int i=0; i<WIDTH; i++) {  // loop through array
-        // elements are normalised from 0.0 to 1.0, so multiply
-        // by 47 to convert to pixel range, and subtract from 47
-        // since top-left is 0,0 in the display geometry
-        setPixel(i,47 - int(array[i]*47.0f),true);
-    }
-
-}
-
-// function to draw circle
-void N5110:: drawCircle(unsigned int const x0,
-                        unsigned int const y0,
-                        unsigned int const radius,
-                        FillType const     fill)
-{
-    // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
-    int x = radius;
-    int y = 0;
-    int radiusError = 1-x;
-
-    while(x >= y) {
-
-        // if transparent, just draw outline
-        if (fill == FILL_TRANSPARENT) {
-            setPixel( x + x0,  y + y0,true);
-            setPixel(-x + x0,  y + y0,true);
-            setPixel( y + x0,  x + y0,true);
-            setPixel(-y + x0,  x + y0,true);
-            setPixel(-y + x0, -x + y0,true);
-            setPixel( y + x0, -x + y0,true);
-            setPixel( x + x0, -y + y0,true);
-            setPixel(-x + x0, -y + y0,true);
-        } else {  // drawing filled circle, so draw lines between points at same y value
-
-            int type = (fill==FILL_BLACK) ? 1:0;  // black or white fill
-
-            drawLine(x+x0,y+y0,-x+x0,y+y0,type);
-            drawLine(y+x0,x+y0,-y+x0,x+y0,type);
-            drawLine(y+x0,-x+y0,-y+x0,-x+y0,type);
-            drawLine(x+x0,-y+y0,-x+x0,-y+y0,type);
-        }
-
-        y++;
-        if (radiusError<0) {
-            radiusError += 2 * y + 1;
-        } else {
-            x--;
-            radiusError += 2 * (y - x) + 1;
-        }
-    }
-
-}
-
-void N5110::drawLine(unsigned int const x0,
-                     unsigned int const y0,
-                     unsigned int const x1,
-                     unsigned int const y1,
-                     unsigned int const type)
-{
-    // Note that the ranges can be negative so we have to turn the input values
-    // into signed integers first
-    int const y_range = static_cast<int>(y1) - static_cast<int>(y0);
-    int const x_range = static_cast<int>(x1) - static_cast<int>(x0);
-
-    // if dotted line, set step to 2, else step is 1
-    unsigned int const step = (type==2) ? 2:1;
-
-    // make sure we loop over the largest range to get the most pixels on the display
-    // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
-    // or else we'll only end up with 1 pixel in the x column
-    if ( abs(x_range) > abs(y_range) ) {
-
-        // ensure we loop from smallest to largest or else for-loop won't run as expected
-        unsigned int const start = x_range > 0 ? x0:x1;
-        unsigned int const stop =  x_range > 0 ? x1:x0;
-
-        // loop between x pixels
-        for (unsigned int x = start; x<= stop ; x+=step) {
-            // do linear interpolation
-            int const dx = static_cast<int>(x)-static_cast<int>(x0);
-            unsigned int const y = y0 + y_range * dx / x_range;
-
-            // If the line type is '0', this will clear the pixel
-            // If it is '1' or '2', the pixel will be set
-            setPixel(x,y, type);
-        }
-    } else {
-
-        // ensure we loop from smallest to largest or else for-loop won't run as expected
-        unsigned int const start = y_range > 0 ? y0:y1;
-        unsigned int const stop =  y_range > 0 ? y1:y0;
-
-        for (unsigned int y = start; y<= stop ; y+=step) {
-            // do linear interpolation
-            int const dy = static_cast<int>(y)-static_cast<int>(y0);
-            unsigned int const x = x0 + x_range * dy / y_range;
-
-            // If the line type is '0', this will clear the pixel
-            // If it is '1' or '2', the pixel will be set
-            setPixel(x,y, type);
-        }
-    }
-
-}
-
-void N5110::drawRect(unsigned int const x0,
-                     unsigned int const y0,
-                     unsigned int const width,
-                     unsigned int const height,
-                     FillType const     fill)
-{
-    if (fill == FILL_TRANSPARENT) { // transparent, just outline
-        drawLine(x0,y0,x0+(width-1),y0,1);  // top
-        drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),1);  // bottom
-        drawLine(x0,y0,x0,y0+(height-1),1);  // left
-        drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),1);  // right
-    } else { // filled rectangle
-        int type = (fill==FILL_BLACK) ? 1:0;  // black or white fill
-        for (int y = y0; y<y0+height; y++) {  // loop through rows of rectangle
-            drawLine(x0,y,x0+(width-1),y,type);  // draw line across screen
-        }
-    }
-}
-
-void N5110::drawSprite(int x0,
-                       int y0,
-                       int nrows,
-                       int ncols,
-                       int *sprite)
-{
-    for (int i = 0; i < nrows; i++) {
-        for (int j = 0 ; j < ncols ; j++) {
-
-            int pixel = *((sprite+i*ncols)+j);
-            if (pixel == 2) {
-                pixel = 0;
-            }
-            setPixel(x0+j,y0+i, pixel);
-        }
-    }
-}
-
-void N5110::drawSpriteTransparent(int x0,
-                                  int y0,
-                                  int nrows,
-                                  int ncols,
-                                  int *sprite)
-{
-    for (int i = 0; i < nrows; i++) {
-        for (int j = 0 ; j < ncols ; j++) {
-
-            int pixel = *((sprite+i*ncols)+j);
-            if (pixel != 0) {
-                if (pixel == 2) {
-                    pixel = 0;
-                }
-                setPixel(x0+j,y0+i, pixel);
-            }
-        }
-    }
-}
-
-int * N5110::readScreen()
-{
-    for (unsigned int i = 0; i < WIDTH; i++) {
-        for (unsigned int j = 0; j < HEIGHT; j++) {
-            screen_array[j][i] = getPixel(i, j);
-        }
-    }
-    return * screen_array;
-}
\ No newline at end of file
--- a/N5110/N5110.h	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,543 +0,0 @@
-#ifndef N5110_H
-#define N5110_H
-
-#include "mbed.h"
-
-// number of pixels on display
-#define WIDTH 84
-#define HEIGHT 48
-#define BANKS 6
-
-/// Fill types for 2D shapes
-enum FillType {
-    FILL_TRANSPARENT, ///< Transparent with outline
-    FILL_BLACK,       ///< Filled black
-    FILL_WHITE,       ///< Filled white (no outline)
-};
-
-/** N5110 Class
-@brief Library for interfacing with Nokia 5110 LCD display (https://www.sparkfun.com/products/10168) using the hardware SPI on the mbed.
-@brief The display is powered from a GPIO pin meaning it can be controlled via software.  The LED backlight is also software-controllable (via PWM pin).
-@brief Can print characters and strings to the display using the included 5x7 font.
-@brief The library also implements a screen buffer so that individual pixels on the display (84 x 48) can be set, cleared and read.
-@brief The library can print primitive shapes (lines, circles, rectangles)
-@brief Acknowledgements to Chris Yan's Nokia_5110 Library.
-
-@brief Revision 1.3
-
-@author Craig A. Evans
-@date   7th February 2017
-
-@code
-
-#include "mbed.h"
-#include "N5110.h"
-
-//      rows,cols
-int sprite[8][5] =   {
-    { 0,0,1,0,0 },
-    { 0,1,1,1,0 },
-    { 0,0,1,0,0 },
-    { 0,1,1,1,0 },
-    { 1,1,1,1,1 },
-    { 1,1,1,1,1 },
-    { 1,1,0,1,1 },
-    { 1,1,0,1,1 },
-};
-
-//    VCC,SCE,RST,D/C,MOSI,SCLK,LED
-//N5110 lcd(p7,p8,p9,p10,p11,p13,p21);  // LPC1768 - pwr from GPIO
-N5110 lcd(p8,p9,p10,p11,p13,p21);  // LPC1768 - powered from +3V3 - JP1 in 2/3 position
-//N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11);  // K64F - pwr from 3V3
-
-int main()
-{
-    // first need to initialise display
-    lcd.init();
-    
-    // change set contrast in range 0.0 to 1.0
-    // 0.4 appears to be a good starting point
-    lcd.setContrast(0.4);
-
-    while(1) {
-
-        // these are default settings so not strictly needed
-        lcd.normalMode();      // normal colour mode
-        lcd.setBrightness(0.5); // put LED backlight on 50%
-
-        lcd.clear();
-        // x origin, y origin, rows, cols, sprite
-        lcd.drawSprite(20,6,8,5,(int *)sprite);
-        lcd.refresh();
-        wait(5.0);
-
-        lcd.clear(); // clear buffer at start of every loop
-        // can directly print strings at specified co-ordinates (must be less than 84 pixels to fit on display)
-        lcd.printString("Hello, World!",0,0);
-
-        char buffer[14];  // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
-        // so can display a string of a maximum 14 characters in length
-        // or create formatted strings - ensure they aren't more than 14 characters long
-        int temperature = 27;
-        int length = sprintf(buffer,"T = %2d C",temperature); // print formatted data to buffer
-        // it is important the format specifier ensures the length will fit in the buffer
-        if (length <= 14)  // if string will fit on display (assuming printing at x=0)
-            lcd.printString(buffer,0,1);           // display on screen
-
-        float pressure = 1012.3;  // same idea with floats
-        length = sprintf(buffer,"P = %.2f mb",pressure);
-        if (length <= 14)
-            lcd.printString(buffer,0,2);
-
-        // can also print individual characters at specified place
-        lcd.printChar('X',5,3);
-
-        // draw a line across the display at y = 40 pixels (origin top-left)
-        for (int i = 0; i < WIDTH; i++) {
-            lcd.setPixel(i,40,true);
-        }
-        // need to refresh display after setting pixels or writing strings
-        lcd.refresh();
-        wait(5.0);
-
-        // can check status of pixel using getPixel(x,y);
-        lcd.clear();  // clear buffer
-        lcd.setPixel(2,2,true);  // set random pixel in buffer
-        lcd.refresh();
-        wait(1.0);
-
-        int pixel_to_test = lcd.getPixel(2,2);
-
-        if ( pixel_to_test ) {
-            lcd.printString("2,2 is set",0,4);
-        }
-
-        // this one shouldn't be set
-        lcd.setPixel(3,3,false);  // clear random pixel in buffer
-        lcd.refresh();
-        pixel_to_test = lcd.getPixel(3,3);
-
-        if ( pixel_to_test == 0 ) {
-            lcd.printString("3,3 is clear",0,5);
-        }
-
-        lcd.refresh();
-        wait(4.0);
-
-        lcd.clear();            // clear buffer
-        lcd.inverseMode();      // invert colours
-        lcd.setBrightness(1.0); // put LED backlight on full
-
-        float array[84];
-
-        for (int i = 0; i < 84; i++) {
-            array[i] = 0.5 + 0.5*sin(i*2*3.14/84);
-        }
-
-        // can also plot graphs - 84 elements only
-        // values must be in range 0.0 - 1.0
-        lcd.plotArray(array);
-        lcd.refresh();
-        wait(5.0);
-
-        lcd.clear();
-        lcd.normalMode();      // normal colour mode back
-        lcd.setBrightness(0.5); // put LED backlight on 50%
-
-        // example of drawing lines
-        for (int x = 0; x < WIDTH ; x+=10) {
-            // x0,y0,x1,y1,type 0-white,1-black,2-dotted
-            lcd.drawLine(0,0,x,HEIGHT,2);
-        }
-        lcd.refresh();  // refresh after drawing shapes
-        wait(5.0);
-
-
-        lcd.clear();
-        // example of how to draw circles
-        lcd.drawCircle(WIDTH/2,HEIGHT/2,20,FILL_BLACK);  // x,y,radius,black fill
-        lcd.drawCircle(WIDTH/2,HEIGHT/2,10,FILL_WHITE);  // x,y,radius,white fill
-        lcd.drawCircle(WIDTH/2,HEIGHT/2,30,FILL_TRANSPARENT);  // x,y,radius,transparent with outline
-        lcd.refresh();  // refresh after drawing shapes
-        wait(5.0);
-
-        lcd.clear();
-        // example of how to draw rectangles
-        //          origin x,y,width,height,type
-        lcd.drawRect(10,10,50,30,FILL_BLACK);  // filled black rectangle
-        lcd.drawRect(15,15,20,10,FILL_WHITE);  // filled white rectange (no outline)
-        lcd.drawRect(2,2,70,40,FILL_TRANSPARENT);    // transparent, just outline
-        lcd.refresh();  // refresh after drawing shapes
-        wait(5.0);
-
-    }
-}
-
-
-@endcode
-*/
-class N5110
-{
-private:
-// objects
-    SPI         *_spi;
-    PwmOut      *_led;
-    DigitalOut  *_pwr;
-    DigitalOut  *_sce;
-    DigitalOut  *_rst;
-    DigitalOut  *_dc;
-
-// variables
-    unsigned char buffer[84][6];  // screen buffer - the 6 is for the banks - each one is 8 bits;
-    int screen_array[48][84];
-
-public:
-    /** Create a N5110 object connected to the specified pins
-    *
-    * @param pwr  Pin connected to Vcc on the LCD display (pin 1)
-    * @param sce  Pin connected to chip enable (pin 3)
-    * @param rst  Pin connected to reset (pin 4)
-    * @param dc   Pin connected to data/command select (pin 5)
-    * @param mosi Pin connected to data input (MOSI) (pin 6)
-    * @param sclk Pin connected to serial clock (SCLK) (pin 7)
-    * @param led  Pin connected to LED backlight (must be PWM) (pin 8)
-    *
-    */
-    N5110(PinName const pwrPin,
-          PinName const scePin,
-          PinName const rstPin,
-          PinName const dcPin,
-          PinName const mosiPin,
-          PinName const sclkPin,
-          PinName const ledPin);
-
-    /** Create a N5110 object connected to the specified pins (Vcc to +3V3)
-    *
-    * @param sce  Pin connected to chip enable (pin 3)
-    * @param rst  Pin connected to reset (pin 4)
-    * @param dc   Pin connected to data/command select (pin 5)
-    * @param mosi Pin connected to data input (MOSI) (pin 6)
-    * @param sclk Pin connected to serial clock (SCLK) (pin 7)
-    * @param led  Pin connected to LED backlight (must be PWM) (pin 8)
-    *
-    */
-    N5110(PinName const scePin,
-          PinName const rstPin,
-          PinName const dcPin,
-          PinName const mosiPin,
-          PinName const sclkPin,
-          PinName const ledPin);
-
-    /**
-     * Free allocated memory when object goes out of scope
-     */
-    ~N5110();
-
-    /** Initialise display
-    *
-    *   Powers up the display and turns on backlight (50% brightness default).
-    *   Sets the display up in horizontal addressing mode and with normal video mode.
-    */
-    void init();
-
-    /** Turn off
-    *
-    *   Powers down the display and turns of the backlight.
-    *   Needs to be reinitialised before being re-used.
-    */
-    void turnOff();
-
-    /** Clear
-    *
-    *   Clears the screen buffer.
-    */
-    void clear();
-
-    /** Set screen constrast
-    *   @param constrast - float in range 0.0 to 1.0 (0.40 to 0.60 is usually a good value)
-    */
-    void setContrast(float contrast);
-    
-    /** Turn on normal video mode (default)
-    *  Black on white
-    */
-    void normalMode();
-
-    /** Turn on inverse video mode (default)
-    *  White on black
-    */
-    void inverseMode();
-
-    /** Set Brightness
-    *
-    *   Sets brightness of LED backlight.
-    *   @param brightness - float in range 0.0 to 1.0
-    */
-    void setBrightness(float const brightness);
-
-    /** Print String
-    *
-    *   Prints a string of characters to the screen buffer. String is cut-off after the 83rd pixel.
-    *   @param x - the column number (0 to 83)
-    *   @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row
-    */
-    void printString(char const         *str,
-                     unsigned int const  x,
-                     unsigned int const  y);
-
-    /** Print Character
-    *
-    *   Sends a character to the screen buffer.  Printed at the specified location. Character is cut-off after the 83rd pixel.
-    *   @param  c - the character to print. Can print ASCII as so printChar('C').
-    *   @param x - the column number (0 to 83)
-    *   @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row
-    */
-    void printChar(char const         c,
-                   unsigned int const x,
-                   unsigned int const y);
-
-    /**
-    * @brief Set a Pixel
-    *
-    * @param x     The x co-ordinate of the pixel (0 to 83)
-    * @param y     The y co-ordinate of the pixel (0 to 47)
-    * @param state The state of the pixel [true=black (default), false=white]
-    *
-    * @details This function sets the state of a pixel in the screen buffer.
-    *          The third parameter can be omitted,
-    */
-    void setPixel(unsigned int const x,
-                  unsigned int const y,
-                  bool const         state = true);
-
-    /**
-    *  @brief Clear a Pixel
-    *
-    *   @param  x - the x co-ordinate of the pixel (0 to 83)
-    *   @param  y - the y co-ordinate of the pixel (0 to 47)
-    *
-    *   @details This function clears pixel in the screen buffer
-    *
-    *   @deprecated Use setPixel(x, y, false) instead
-    */
-    void clearPixel(unsigned int const x,
-                    unsigned int const y)
-    __attribute__((deprecated("Use setPixel(x,y,false) instead")));
-
-    /** Get a Pixel
-    *
-    *   This function gets the status of a pixel in the screen buffer.
-    *   @param  x - the x co-ordinate of the pixel (0 to 83)
-    *   @param  y - the y co-ordinate of the pixel (0 to 47)
-    *   @returns
-    *       0           - pixel is clear
-    *       1    - pixel is set
-    */
-    int getPixel(unsigned int const x,
-                 unsigned int const y) const;
-
-    /** Refresh display
-    *
-    *   This functions sends the screen buffer to the display.
-    */
-    void refresh();
-
-    /** Randomise buffer
-    *
-    *   This function fills the buffer with random data.  Can be used to test the display.
-    *   A call to refresh() must be made to update the display to reflect the change in pixels.
-    *   The seed is not set and so the generated pattern will probably be the same each time.
-    *   TODO: Randomise the seed - maybe using the noise on the AnalogIn pins.
-    */
-    void randomiseBuffer();
-
-    /** Plot Array
-    *
-    *   This function plots a one-dimensional array in the buffer.
-    *   @param array[] - y values of the plot. Values should be normalised in the range 0.0 to 1.0. First 84 plotted.
-    */
-    void plotArray(float const array[]);
-
-    /** Draw Circle
-    *
-    *   This function draws a circle at the specified origin with specified radius in the screen buffer
-    *   Uses the midpoint circle algorithm.
-    *   @see http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
-    *   @param  x0     - x-coordinate of centre
-    *   @param  y0     - y-coordinate of centre
-    *   @param  radius - radius of circle in pixels
-    *   @param  fill   - fill-type for the shape
-    */
-    void drawCircle(unsigned int const x0,
-                    unsigned int const y0,
-                    unsigned int const radius,
-                    FillType const     fill);
-
-    /** Draw Line
-    *
-    *   This function draws a line between the specified points using linear interpolation.
-    *   @param  x0 - x-coordinate of first point
-    *   @param  y0 - y-coordinate of first point
-    *   @param  x1 - x-coordinate of last point
-    *   @param  y1 - y-coordinate of last point
-    *   @param  type - 0 white,1 black,2 dotted
-    */
-    void drawLine(unsigned int const x0,
-                  unsigned int const y0,
-                  unsigned int const x1,
-                  unsigned int const y1,
-                  unsigned int const type);
-
-    /** Draw Rectangle
-    *
-    *   This function draws a rectangle.
-    *   @param  x0 - x-coordinate of origin (top-left)
-    *   @param  y0 - y-coordinate of origin (top-left)
-    *   @param  width - width of rectangle
-    *   @param  height - height of rectangle
-    *   @param  fill   - fill-type for the shape
-    */
-    void drawRect(unsigned int const x0,
-                  unsigned int const y0,
-                  unsigned int const width,
-                  unsigned int const height,
-                  FillType const     fill);
-
-    /** Draw Sprite
-    *
-    *   This function draws a sprite as defined in a 2D array
-    *   @param  x0 - x-coordinate of origin (top-left)
-    *   @param  y0 - y-coordinate of origin (top-left)
-    *   @param  nrows - number of rows in sprite
-    *   @param  ncols - number of columns in sprite
-    *   @param  sprite - 2D array representing the sprite
-    */
-    void drawSprite(int x0,
-                    int y0,
-                    int nrows,
-                    int ncols,
-                    int *sprite);
-    
-    void drawSpriteTransparent(int x0,
-                               int y0,
-                               int nrows,
-                               int ncols,
-                               int *sprite);
-                               
-    int * readScreen();
-
-
-private:
-// methods
-    void setXYAddress(unsigned int const x,
-                      unsigned int const y);
-    void initSPI();
-    void turnOn();
-    void reset();
-    void clearRAM();
-    void sendCommand(unsigned char command);
-    void sendData(unsigned char data);
-    void setTempCoefficient(char tc);  // 0 to 3
-    void setBias(char bias);  // 0 to 7
-};
-
-const unsigned char font5x7[480] = {
-    0x00, 0x00, 0x00, 0x00, 0x00,// (space)
-    0x00, 0x00, 0x5F, 0x00, 0x00,// !
-    0x00, 0x07, 0x00, 0x07, 0x00,// "
-    0x14, 0x7F, 0x14, 0x7F, 0x14,// #
-    0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
-    0x23, 0x13, 0x08, 0x64, 0x62,// %
-    0x36, 0x49, 0x55, 0x22, 0x50,// &
-    0x00, 0x05, 0x03, 0x00, 0x00,// '
-    0x00, 0x1C, 0x22, 0x41, 0x00,// (
-    0x00, 0x41, 0x22, 0x1C, 0x00,// )
-    0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
-    0x08, 0x08, 0x3E, 0x08, 0x08,// +
-    0x00, 0x50, 0x30, 0x00, 0x00,// ,
-    0x08, 0x08, 0x08, 0x08, 0x08,// -
-    0x00, 0x60, 0x60, 0x00, 0x00,// .
-    0x20, 0x10, 0x08, 0x04, 0x02,// /
-    0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
-    0x00, 0x42, 0x7F, 0x40, 0x00,// 1
-    0x42, 0x61, 0x51, 0x49, 0x46,// 2
-    0x21, 0x41, 0x45, 0x4B, 0x31,// 3
-    0x18, 0x14, 0x12, 0x7F, 0x10,// 4
-    0x27, 0x45, 0x45, 0x45, 0x39,// 5
-    0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
-    0x01, 0x71, 0x09, 0x05, 0x03,// 7
-    0x36, 0x49, 0x49, 0x49, 0x36,// 8
-    0x06, 0x49, 0x49, 0x29, 0x1E,// 9
-    0x00, 0x36, 0x36, 0x00, 0x00,// :
-    0x00, 0x56, 0x36, 0x00, 0x00,// ;
-    0x00, 0x08, 0x14, 0x22, 0x41,// <
-    0x14, 0x14, 0x14, 0x14, 0x14,// =
-    0x41, 0x22, 0x14, 0x08, 0x00,// >
-    0x02, 0x01, 0x51, 0x09, 0x06,// ?
-    0x32, 0x49, 0x79, 0x41, 0x3E,// @
-    0x7E, 0x11, 0x11, 0x11, 0x7E,// A
-    0x7F, 0x49, 0x49, 0x49, 0x36,// B
-    0x3E, 0x41, 0x41, 0x41, 0x22,// C
-    0x7F, 0x41, 0x41, 0x22, 0x1C,// D
-    0x7F, 0x49, 0x49, 0x49, 0x41,// E
-    0x7F, 0x09, 0x09, 0x01, 0x01,// F
-    0x3E, 0x41, 0x41, 0x51, 0x32,// G
-    0x7F, 0x08, 0x08, 0x08, 0x7F,// H
-    0x00, 0x41, 0x7F, 0x41, 0x00,// I
-    0x20, 0x40, 0x41, 0x3F, 0x01,// J
-    0x7F, 0x08, 0x14, 0x22, 0x41,// K
-    0x7F, 0x40, 0x40, 0x40, 0x40,// L
-    0x7F, 0x02, 0x04, 0x02, 0x7F,// M
-    0x7F, 0x04, 0x08, 0x10, 0x7F,// N
-    0x3E, 0x41, 0x41, 0x41, 0x3E,// O
-    0x7F, 0x09, 0x09, 0x09, 0x06,// P
-    0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
-    0x7F, 0x09, 0x19, 0x29, 0x46,// R
-    0x46, 0x49, 0x49, 0x49, 0x31,// S
-    0x01, 0x01, 0x7F, 0x01, 0x01,// T
-    0x3F, 0x40, 0x40, 0x40, 0x3F,// U
-    0x1F, 0x20, 0x40, 0x20, 0x1F,// V
-    0x7F, 0x20, 0x18, 0x20, 0x7F,// W
-    0x63, 0x14, 0x08, 0x14, 0x63,// X
-    0x03, 0x04, 0x78, 0x04, 0x03,// Y
-    0x61, 0x51, 0x49, 0x45, 0x43,// Z
-    0x00, 0x00, 0x7F, 0x41, 0x41,// [
-    0x02, 0x04, 0x08, 0x10, 0x20,// "\"
-    0x41, 0x41, 0x7F, 0x00, 0x00,// ]
-    0x04, 0x02, 0x01, 0x02, 0x04,// ^
-    0x40, 0x40, 0x40, 0x40, 0x40,// _
-    0x00, 0x01, 0x02, 0x04, 0x00,// `
-    0x20, 0x54, 0x54, 0x54, 0x78,// a
-    0x7F, 0x48, 0x44, 0x44, 0x38,// b
-    0x38, 0x44, 0x44, 0x44, 0x20,// c
-    0x38, 0x44, 0x44, 0x48, 0x7F,// d
-    0x38, 0x54, 0x54, 0x54, 0x18,// e
-    0x08, 0x7E, 0x09, 0x01, 0x02,// f
-    0x08, 0x14, 0x54, 0x54, 0x3C,// g
-    0x7F, 0x08, 0x04, 0x04, 0x78,// h
-    0x00, 0x44, 0x7D, 0x40, 0x00,// i
-    0x20, 0x40, 0x44, 0x3D, 0x00,// j
-    0x00, 0x7F, 0x10, 0x28, 0x44,// k
-    0x00, 0x41, 0x7F, 0x40, 0x00,// l
-    0x7C, 0x04, 0x18, 0x04, 0x78,// m
-    0x7C, 0x08, 0x04, 0x04, 0x78,// n
-    0x38, 0x44, 0x44, 0x44, 0x38,// o
-    0x7C, 0x14, 0x14, 0x14, 0x08,// p
-    0x08, 0x14, 0x14, 0x18, 0x7C,// q
-    0x7C, 0x08, 0x04, 0x04, 0x08,// r
-    0x48, 0x54, 0x54, 0x54, 0x20,// s
-    0x04, 0x3F, 0x44, 0x40, 0x20,// t
-    0x3C, 0x40, 0x40, 0x20, 0x7C,// u
-    0x1C, 0x20, 0x40, 0x20, 0x1C,// v
-    0x3C, 0x40, 0x30, 0x40, 0x3C,// w
-    0x44, 0x28, 0x10, 0x28, 0x44,// x
-    0x0C, 0x50, 0x50, 0x50, 0x3C,// y
-    0x44, 0x64, 0x54, 0x4C, 0x44,// z
-    0x00, 0x08, 0x36, 0x41, 0x00,// {
-    0x00, 0x00, 0x7F, 0x00, 0x00,// |
-    0x00, 0x41, 0x36, 0x08, 0x00,// }
-    0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
-    0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
-};
-
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/FXOS8700Q/FXOS8700Q.cpp	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,231 @@
+/* FXOS8700Q sensor driver
+ * Copyright (c) 2014-2015 ARM Limited
+ *
+ * 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 "FXOS8700Q.h"
+
+const uint16_t uint14_max = 0x3FFF;
+void static inline normalize_14bits(int16_t &x)
+{
+    x = ((x) > (uint14_max/2)) ? (x - uint14_max) : (x);
+}
+
+static int16_t dummy_int16_t = 0;
+static float dummy_float = 0.0f;
+
+FXOS8700Q::FXOS8700Q(I2C &i2c, uint8_t addr)
+{
+    _i2c = &i2c;
+    _addr = addr;
+    // activate the peripheral
+    uint8_t data[2] = {FXOS8700Q_CTRL_REG1, 0x00};
+    _i2c->frequency(400000);
+    writeRegs(data, 2);
+    data[0] = FXOS8700Q_M_CTRL_REG1;
+    data[1] = 0x1F;
+    writeRegs(data, 2);
+    data[0] = FXOS8700Q_M_CTRL_REG2;
+    data[1] = 0x20;
+    writeRegs(data, 2);
+    data[0] = FXOS8700Q_XYZ_DATA_CFG;
+    data[1] = 0x00;
+    writeRegs(data, 2);
+    data[0] = FXOS8700Q_CTRL_REG1;
+    data[1] = 0x1C;
+    writeRegs(data, 2);
+}
+
+FXOS8700Q::~FXOS8700Q()
+{
+    _i2c = 0;
+    _addr = 0;
+}
+
+void FXOS8700Q::readRegs(uint8_t addr, uint8_t *data, uint32_t len) const
+{
+    uint8_t t[1] = {addr};
+    _i2c->write(_addr, (char *)t, sizeof(t), true);
+    _i2c->read(_addr, (char *)data, len);
+}
+
+uint8_t FXOS8700Q::whoAmI() const
+{
+    uint8_t who_am_i = 0;
+    readRegs(FXOS8700Q_WHOAMI, &who_am_i, sizeof(who_am_i));
+    return who_am_i;
+}
+
+void FXOS8700Q::writeRegs(uint8_t * data, uint32_t len) const
+{
+    _i2c->write(_addr, (char *)data, len);
+}
+
+
+int16_t FXOS8700Q::getSensorAxis(uint8_t addr) const
+{
+    uint8_t res[2];
+    readRegs(addr, res, sizeof(res));
+    return static_cast<int16_t>((res[0] << 8) | res[1]);
+}
+
+void FXOS8700Q::enable(void) const
+{
+    uint8_t data[2];
+    readRegs(FXOS8700Q_CTRL_REG1, &data[1], 1);
+    data[1] |= 0x01;
+    data[0] = FXOS8700Q_CTRL_REG1;
+    writeRegs(data, sizeof(data));
+}
+
+void FXOS8700Q::disable(void) const
+{
+    uint8_t data[2];
+    readRegs(FXOS8700Q_CTRL_REG1, &data[1], 1);
+    data[1] &= 0xFE;
+    data[0] = FXOS8700Q_CTRL_REG1;
+    writeRegs(data, sizeof(data));
+}
+
+uint32_t FXOS8700Q::dataReady(void) const
+{
+    uint8_t stat = 0;
+    readRegs(FXOS8700Q_STATUS, &stat, 1);
+    return (uint32_t)stat;
+}
+
+uint32_t FXOS8700Q::sampleRate(uint32_t frequency) const
+{
+    return(50); // for now sample rate is fixed at 50Hz
+}
+
+int16_t FXOS8700QAccelerometer::getX(int16_t &x = dummy_int16_t) const
+{
+    x = getSensorAxis(FXOS8700Q_OUT_X_MSB) >> 2;
+    normalize_14bits(x);
+    return x;
+}
+
+int16_t FXOS8700QAccelerometer::getY(int16_t &y = dummy_int16_t) const
+{
+    y = getSensorAxis(FXOS8700Q_OUT_Y_MSB) >> 2;
+    normalize_14bits(y);
+    return y;
+}
+
+int16_t FXOS8700QAccelerometer::getZ(int16_t &z = dummy_int16_t) const
+{
+    z = getSensorAxis(FXOS8700Q_OUT_Z_MSB) >> 2;
+    normalize_14bits(z);
+    return z;
+}
+
+float FXOS8700QAccelerometer::getX(float &x = dummy_float) const
+{
+    int16_t val = getSensorAxis(FXOS8700Q_OUT_X_MSB) >> 2;
+    normalize_14bits(val);
+    x = val / 4096.0f;
+    return x;
+}
+
+float FXOS8700QAccelerometer::getY(float &y = dummy_float) const
+{
+    int16_t val = getSensorAxis(FXOS8700Q_OUT_Y_MSB) >> 2;
+    normalize_14bits(val);
+    y = val / 4096.0f;
+    return y;
+}
+
+float FXOS8700QAccelerometer::getZ(float &z = dummy_float) const
+{
+    int16_t val = getSensorAxis(FXOS8700Q_OUT_Z_MSB) >> 2;
+    normalize_14bits(val);
+    z = val / 4096.0f;
+    return z;
+}
+
+void FXOS8700QAccelerometer::getAxis(motion_data_counts_t &xyz) const
+{
+    uint8_t res[6];
+    readRegs(FXOS8700Q_OUT_X_MSB, res, sizeof(res));
+    xyz.x = static_cast<int16_t>((res[0] << 8) | res[1]) >> 2;
+    xyz.y = static_cast<int16_t>((res[2] << 8) | res[3]) >> 2;
+    xyz.z = static_cast<int16_t>((res[4] << 8) | res[5]) >> 2;
+    normalize_14bits(xyz.x);
+    normalize_14bits(xyz.y);
+    normalize_14bits(xyz.z);
+}
+
+void FXOS8700QAccelerometer::getAxis(motion_data_units_t &xyz) const
+{
+    motion_data_counts_t _xyz;
+    FXOS8700QAccelerometer::getAxis(_xyz);
+    xyz.x = _xyz.x / 4096.0f;
+    xyz.y = _xyz.y / 4096.0f;
+    xyz.z = _xyz.z / 4096.0f;
+}
+
+int16_t FXOS8700QMagnetometer::getX(int16_t &x = dummy_int16_t) const
+{
+    x = getSensorAxis(FXOS8700Q_M_OUT_X_MSB);
+    return x;
+}
+
+int16_t FXOS8700QMagnetometer::getY(int16_t &y = dummy_int16_t) const
+{
+    y = getSensorAxis(FXOS8700Q_M_OUT_Y_MSB);
+    return y;
+}
+
+int16_t FXOS8700QMagnetometer::getZ(int16_t &z = dummy_int16_t) const
+{
+    z = getSensorAxis(FXOS8700Q_M_OUT_Z_MSB);
+    return z;
+}
+
+float FXOS8700QMagnetometer::getX(float &x = dummy_float) const
+{
+    x = static_cast<float>(getSensorAxis(FXOS8700Q_M_OUT_X_MSB)) * 0.1f;
+    return x;
+}
+
+float FXOS8700QMagnetometer::getY(float &y = dummy_float) const
+{
+    y = static_cast<float>(getSensorAxis(FXOS8700Q_M_OUT_Y_MSB)) * 0.1f;
+    return y;
+}
+
+float FXOS8700QMagnetometer::getZ(float &z = dummy_float) const
+{
+    z = static_cast<float>(getSensorAxis(FXOS8700Q_M_OUT_Z_MSB)) * 0.1f;
+    return z;
+}
+
+void FXOS8700QMagnetometer::getAxis(motion_data_counts_t &xyz) const
+{
+    uint8_t res[6];
+    readRegs(FXOS8700Q_M_OUT_X_MSB, res, sizeof(res));
+    xyz.x = (res[0] << 8) | res[1];
+    xyz.y = (res[2] << 8) | res[3];
+    xyz.z = (res[4] << 8) | res[5];
+}
+
+void FXOS8700QMagnetometer::getAxis(motion_data_units_t &xyz) const
+{
+    motion_data_counts_t _xyz;
+    FXOS8700QMagnetometer::getAxis(_xyz);
+    xyz.x = static_cast<float>(_xyz.x * 0.1f);
+    xyz.y = static_cast<float>(_xyz.y * 0.1f);
+    xyz.z = static_cast<float>(_xyz.z * 0.1f);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/FXOS8700Q/FXOS8700Q.h	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,164 @@
+/* FXOS8700Q sensor driver
+ * Copyright (c) 2014-2015 ARM Limited
+ *
+ * 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 FXOS8700Q_H
+#define FXOS8700Q_H
+
+#include "mbed.h"
+#include "MotionSensor.h"
+
+// FXOS8700CQ I2C address
+#define FXOS8700CQ_SLAVE_ADDR0 (0x1E<<1) // with pins SA0=0, SA1=0
+#define FXOS8700CQ_SLAVE_ADDR1 (0x1D<<1) // with pins SA0=1, SA1=0
+#define FXOS8700CQ_SLAVE_ADDR2 (0x1C<<1) // with pins SA0=0, SA1=1
+#define FXOS8700CQ_SLAVE_ADDR3 (0x1F<<1) // with pins SA0=1, SA1=1
+// FXOS8700CQ internal register addresses
+#define FXOS8700Q_STATUS 0x00
+#define FXOS8700Q_OUT_X_MSB 0x01
+#define FXOS8700Q_OUT_Y_MSB 0x03
+#define FXOS8700Q_OUT_Z_MSB 0x05
+#define FXOS8700Q_M_OUT_X_MSB 0x33
+#define FXOS8700Q_M_OUT_Y_MSB 0x35
+#define FXOS8700Q_M_OUT_Z_MSB 0x37
+#define FXOS8700Q_WHOAMI 0x0D
+#define FXOS8700Q_XYZ_DATA_CFG 0x0E
+#define FXOS8700Q_CTRL_REG1 0x2A
+#define FXOS8700Q_M_CTRL_REG1 0x5B
+#define FXOS8700Q_M_CTRL_REG2 0x5C
+#define FXOS8700Q_WHOAMI_VAL 0xC7
+
+
+/** FXOS8700Q accelerometer example
+    @code
+    #include "mbed.h"
+    #include "FXOS8700Q.h"
+    I2C i2c(PTE25, PTE24);
+    FXOS8700QAccelerometer acc(i2c, FXOS8700CQ_SLAVE_ADDR1);    // Configured for the FRDM-K64F with onboard sensors
+    FXOS8700QMagnetometer mag(i2c, FXOS8700CQ_SLAVE_ADDR1);
+    int main(void)
+    {
+        motion_data_units_t acc_data, mag_data;
+        motion_data_counts_t acc_raw, mag_raw;
+        float faX, faY, faZ, fmX, fmY, fmZ, tmp_float;
+        int16_t raX, raY, raZ, rmX, rmY, rmZ, tmp_int;
+        acc.enable();
+        mag.enable();
+        while (true) {
+            // counts based results
+            acc.getAxis(acc_raw);
+            mag.getAxis(mag_raw);
+            acc.getX(raX);
+            acc.getY(raY);
+            acc.getZ(raZ);
+            mag.getX(rmX);
+            mag.getY(rmY);
+            mag.getZ(rmZ);
+            // unit based results
+            acc.getAxis(acc_data);
+            mag.getAxis(mag_data);
+            acc.getX(faX);
+            acc.getY(faY);
+            acc.getZ(faZ);
+            mag.getX(fmX);
+            mag.getY(fmY);
+            mag.getZ(fmZ);
+            wait(0.1f);
+        }
+    }
+    @endcode
+ */
+
+/** FXOS8700Q driver class
+ */
+class FXOS8700Q : public MotionSensor
+{
+public:
+
+    /** Read a device register
+        @param addr The address to read from
+        @param data The data to read from it
+        @param len The amount of data to read from it
+        @return 0 if successful, negative number otherwise
+     */
+    void readRegs(uint8_t addr, uint8_t *data, uint32_t len) const;
+
+    /** Read the ID from a whoAmI register
+        @return The device whoAmI register contents
+     */
+    uint8_t whoAmI(void) const;
+
+    virtual void enable(void) const;
+    virtual void disable(void) const;
+    virtual uint32_t sampleRate(uint32_t frequency) const;
+    virtual uint32_t dataReady(void) const;
+
+protected:
+    I2C *_i2c;
+    uint8_t _addr;
+    
+    /** FXOS8700Q constructor
+        @param i2c a configured i2c object
+        @param addr addr of the I2C peripheral as wired
+     */
+    FXOS8700Q(I2C &i2c, uint8_t addr);
+
+    /** FXOS8700Q deconstructor
+     */
+    ~FXOS8700Q();
+    
+    void writeRegs(uint8_t *data, uint32_t len) const;
+    int16_t getSensorAxis(uint8_t addr) const;
+};
+
+/** FXOS8700QAccelerometer interface
+ */
+class FXOS8700QAccelerometer : public FXOS8700Q
+{
+public:
+
+    FXOS8700QAccelerometer(I2C &i2c, uint8_t addr) : FXOS8700Q(i2c, addr) {}
+
+    virtual int16_t getX(int16_t &x) const;
+    virtual int16_t getY(int16_t &y) const;
+    virtual int16_t getZ(int16_t &z) const;
+    virtual float getX(float &x) const;
+    virtual float getY(float &y) const;
+    virtual float getZ(float &z) const;
+    virtual void getAxis(motion_data_counts_t &xyz) const;
+    virtual void getAxis(motion_data_units_t &xyz) const;
+
+};
+
+/** FXOS8700QMagnetometer interface
+ */
+class FXOS8700QMagnetometer : public FXOS8700Q
+{
+public:
+
+    FXOS8700QMagnetometer(I2C &i2c, uint8_t addr) : FXOS8700Q(i2c, addr) {}
+
+    virtual int16_t getX(int16_t &x) const;
+    virtual int16_t getY(int16_t &y) const;
+    virtual int16_t getZ(int16_t &z) const;
+    virtual float getX(float &x) const;
+    virtual float getY(float &y) const;
+    virtual float getZ(float &z) const;
+    virtual void getAxis(motion_data_counts_t &xyz) const;
+    virtual void getAxis(motion_data_units_t &xyz) const;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/FXOS8700Q/MotionSensor.lib	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/components/code/MotionSensor/#226520fc09bf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/Gamepad/Gamepad.cpp	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,391 @@
+#include "Gamepad.h"
+
+#include "mbed.h"
+
+//////////// constructor/destructor ////////////
+Gamepad::Gamepad()
+    :
+    _led1(new PwmOut(PTA1)),
+    _led2(new PwmOut(PTA2)),
+    _led3(new PwmOut(PTC2)),
+    _led4(new PwmOut(PTC3)),
+    _led5(new PwmOut(PTC4)),
+    _led6(new PwmOut(PTD3)),
+
+    _button_A(new InterruptIn(PTB9)),
+    _button_B(new InterruptIn(PTD0)),
+    _button_X(new InterruptIn(PTC17)),
+    _button_Y(new InterruptIn(PTC12)),
+    _button_L(new InterruptIn(PTB18)),
+    _button_R(new InterruptIn(PTB3)),
+    _button_back(new InterruptIn(PTB19)),
+    _button_start(new InterruptIn(PTC5)),
+    _button_joystick(new InterruptIn(PTC16)),
+
+    _vert(new AnalogIn(PTB10)),
+    _horiz(new AnalogIn(PTB11)),
+
+    _buzzer(new PwmOut(PTC10)),
+    _pot(new AnalogIn(PTB2)),
+
+    _timeout(new Timeout()),
+
+    _event_state(0),
+
+    _x0(0),
+    _y0(0)
+{}
+
+Gamepad::~Gamepad()
+{
+    delete _led1,_led2,_led3,_led4,_led5,_led6;
+    delete _button_A,_button_B,_button_joystick,_vert,_horiz;
+    delete _button_X,_button_Y,_button_back,_button_start;
+    delete _button_L,_button_R, _buzzer, _pot, _timeout;
+}
+
+///////////////// public methods /////////////////
+
+void Gamepad::init()
+{
+    leds_off();
+    init_buttons();
+
+    // read centred values of joystick
+    _x0 = _horiz->read();
+    _y0 = _vert->read();
+
+    // clear all flags
+    _event_state = 0;
+}
+
+void Gamepad::leds_off()
+{
+    leds(0.0);
+}
+
+void Gamepad::leds_on()
+{
+    leds(1.0);
+}
+
+void Gamepad::leds(float val) const
+{
+    if (val < 0.0f) {
+        val = 0.0f;
+    }
+    if (val > 1.0f) {
+        val = 1.0f;
+    }
+
+    // leds are active-low, so subtract from 1.0
+    // 0.0 corresponds to fully-off, 1.0 to fully-on
+    val = 1.0f - val;
+
+    _led1->write(val);
+    _led2->write(val);
+    _led3->write(val);
+    _led4->write(val);
+    _led5->write(val);
+    _led6->write(val);
+}
+
+void Gamepad::led(int n,float val) const
+{
+    // ensure they are within vlaid range
+    if (val < 0.0f) {
+        val = 0.0f;
+    }
+    if (val > 1.0f) {
+        val = 1.0f;
+    }
+
+    switch (n) {
+
+        // check for valid LED number and set value
+
+        case 1:
+            _led1->write(1.0f-val);   // active-low so subtract from 1
+            break;
+        case 2:
+            _led2->write(1.0f-val);   // active-low so subtract from 1
+            break;
+        case 3:
+            _led3->write(1.0f-val);   // active-low so subtract from 1
+            break;
+        case 4:
+            _led4->write(1.0f-val);   // active-low so subtract from 1
+            break;
+        case 5:
+            _led5->write(1.0f-val);   // active-low so subtract from 1
+            break;
+        case 6:
+            _led6->write(1.0f-val);   // active-low so subtract from 1
+            break;
+
+    }
+}
+
+float Gamepad::read_pot() const
+{
+    return _pot->read();
+}
+
+void Gamepad::tone(float frequency, float duration)
+{
+    _buzzer->period(1.0f/frequency);
+    _buzzer->write(0.5);  // 50% duty cycle - square wave
+    _timeout->attach(callback(this, &Gamepad::tone_off), duration );
+}
+
+bool Gamepad::check_event(GamepadEvent const id)
+{
+    // Check whether event flag is set
+    if (_event_state[id]) {
+//        _event_state.reset(id);  // clear flag
+        return true;
+    } else {
+        return false;
+    }
+}
+
+// this method gets the magnitude of the joystick movement
+float Gamepad::get_mag()
+{
+    Polar p = get_polar();
+    return p.mag;
+}
+
+// this method gets the angle of joystick movement (0 to 360, 0 North)
+float Gamepad::get_angle()
+{
+    Polar p = get_polar();
+    return p.angle;
+}
+
+Direction Gamepad::get_direction()
+{
+    float angle = get_angle();  // 0 to 360, -1 for centred
+
+    Direction d;
+    // partition 360 into segments and check which segment the angle is in
+    if (angle < 0.0f) {
+        d = CENTRE;   // check for -1.0 angle
+    } else if (angle < 22.5f) {  // then keep going in 45 degree increments
+        d = N;
+    } else if (angle < 67.5f) {
+        d = NE;
+    } else if (angle < 112.5f) {
+        d = E;
+    } else if (angle < 157.5f) {
+        d = SE;
+    } else if (angle < 202.5f) {
+        d = S;
+    } else if (angle < 247.5f) {
+        d = SW;
+    } else if (angle < 292.5f) {
+        d = W;
+    } else if (angle < 337.5f) {
+        d = NW;
+    } else {
+        d = N;
+    }
+
+    return d;
+}
+
+///////////////////// private methods ////////////////////////
+
+void Gamepad::tone_off()
+{
+    // called after timeout
+    _buzzer->write(0.0);
+}
+
+void Gamepad::init_buttons()
+{
+    // turn on pull-downs as other side of button is connected to 3V3
+    // button is 0 when not pressed and 1 when pressed
+    _button_A->mode(PullDown);
+    _button_B->mode(PullDown);
+    _button_X->mode(PullDown);
+    _button_Y->mode(PullDown);
+    _button_back->mode(PullDown);
+    _button_start->mode(PullDown);
+    _button_L->mode(PullDown);
+    _button_R->mode(PullDown);
+    _button_joystick->mode(PullDown);
+    // therefore setup rising edge interrupts
+    _button_A->rise(callback(this,&Gamepad::a_isr));
+    _button_B->rise(callback(this,&Gamepad::b_isr));
+    _button_X->rise(callback(this,&Gamepad::x_isr));
+    _button_Y->rise(callback(this,&Gamepad::y_isr));
+    _button_L->rise(callback(this,&Gamepad::l_isr));
+    _button_R->rise(callback(this,&Gamepad::r_isr));
+    _button_start->rise(callback(this,&Gamepad::start_isr));
+    _button_back->rise(callback(this,&Gamepad::back_isr));
+    _button_joystick->rise(callback(this,&Gamepad::joy_isr));
+    // therefore setup falling edge interrupts
+    _button_A->fall(callback(this,&Gamepad::a_reset_isr));
+    _button_B->fall(callback(this,&Gamepad::b_reset_isr));
+    _button_X->fall(callback(this,&Gamepad::x_reset_isr));
+    _button_Y->fall(callback(this,&Gamepad::y_reset_isr));
+    _button_L->fall(callback(this,&Gamepad::l_reset_isr));
+    _button_R->fall(callback(this,&Gamepad::r_reset_isr));
+    _button_start->fall(callback(this,&Gamepad::start_reset_isr));
+    _button_back->fall(callback(this,&Gamepad::back_reset_isr));
+    _button_joystick->fall(callback(this,&Gamepad::joy_reset_isr));
+}
+
+// button interrupts ISRs
+// Each of these simply sets the appropriate event bit in the _event_state
+// variable
+void Gamepad::a_isr()
+{
+    _event_state.set(A_PRESSED);
+}
+void Gamepad::b_isr()
+{
+    _event_state.set(B_PRESSED);
+}
+void Gamepad::x_isr()
+{
+    _event_state.set(X_PRESSED);
+}
+void Gamepad::y_isr()
+{
+    _event_state.set(Y_PRESSED);
+}
+void Gamepad::l_isr()
+{
+    _event_state.set(L_PRESSED);
+}
+void Gamepad::r_isr()
+{
+    _event_state.set(R_PRESSED);
+}
+void Gamepad::back_isr()
+{
+    _event_state.set(BACK_PRESSED);
+}
+void Gamepad::start_isr()
+{
+    _event_state.set(START_PRESSED);
+}
+void Gamepad::joy_isr()
+{
+    _event_state.set(JOY_PRESSED);
+}
+
+// button interrupts ISRs
+// Each of these simply resets the appropriate event bit in the _event_state
+// variable
+void Gamepad::a_reset_isr()
+{
+    _event_state.reset(A_PRESSED);
+}
+void Gamepad::b_reset_isr()
+{
+    _event_state.reset(B_PRESSED);
+}
+void Gamepad::x_reset_isr()
+{
+    _event_state.reset(X_PRESSED);
+}
+void Gamepad::y_reset_isr()
+{
+    _event_state.reset(Y_PRESSED);
+}
+void Gamepad::l_reset_isr()
+{
+    _event_state.reset(L_PRESSED);
+}
+void Gamepad::r_reset_isr()
+{
+    _event_state.reset(R_PRESSED);
+}
+void Gamepad::back_reset_isr()
+{
+    _event_state.reset(BACK_PRESSED);
+}
+void Gamepad::start_reset_isr()
+{
+    _event_state.reset(START_PRESSED);
+}
+void Gamepad::joy_reset_isr()
+{
+    _event_state.reset(JOY_PRESSED);
+}
+
+// get raw joystick coordinate in range -1 to 1
+// Direction (x,y)
+// North     (0,1)
+// East      (1,0)
+// South     (0,-1)
+// West      (-1,0)
+Vector2D Gamepad::get_coord()
+{
+    // read() returns value in range 0.0 to 1.0 so is scaled and centre value
+    // substracted to get values in the range -1.0 to 1.0
+    float x = 2.0f*( _horiz->read() - _x0 );
+    float y = 2.0f*( _vert->read()  - _y0 );
+
+    // Note: the x value here is inverted to ensure the positive x is to the
+    // right. This is simply due to how the potentiometer on the joystick
+    // I was using was connected up. It could have been corrected in hardware
+    // by swapping the power supply pins. Instead it is done in software so may
+    // need to be changed depending on your wiring setup
+
+    Vector2D coord = {-x,y};
+    return coord;
+}
+
+// This maps the raw x,y coord onto a circular grid.
+// See:  http://mathproofs.blogspot.co.uk/2005/07/mapping-square-to-circle.html
+Vector2D Gamepad::get_mapped_coord()
+{
+    Vector2D coord = get_coord();
+
+    // do the transformation
+    float x = coord.x*sqrt(1.0f-pow(coord.y,2.0f)/2.0f);
+    float y = coord.y*sqrt(1.0f-pow(coord.x,2.0f)/2.0f);
+
+    Vector2D mapped_coord = {x,y};
+    return mapped_coord;
+}
+
+// this function converts the mapped coordinates into polar form
+Polar Gamepad::get_polar()
+{
+    // get the mapped coordinate
+    Vector2D coord = get_mapped_coord();
+
+    // at this point, 0 degrees (i.e. x-axis) will be defined to the East.
+    // We want 0 degrees to correspond to North and increase clockwise to 359
+    // like a compass heading, so we need to swap the axis and invert y
+    float x = coord.y;
+    float y = coord.x;
+
+    float mag = sqrt(x*x+y*y);  // pythagoras
+    float angle = RAD2DEG*atan2(y,x);
+    // angle will be in range -180 to 180, so add 360 to negative angles to
+    // move to 0 to 360 range
+    if (angle < 0.0f) {
+        angle+=360.0f;
+    }
+
+    // the noise on the ADC causes the values of x and y to fluctuate slightly
+    // around the centred values. This causes the random angle values to get
+    // calculated when the joystick is centred and untouched. This is also when
+    // the magnitude is very small, so we can check for a small magnitude and then
+    // set the angle to -1. This will inform us when the angle is invalid and the
+    // joystick is centred
+
+    if (mag < TOL) {
+        mag = 0.0f;
+        angle = -1.0f;
+    }
+
+    Polar p = {mag,angle};
+    return p;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/Gamepad/Gamepad.h	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,216 @@
+#ifndef GAMEPAD_H
+#define GAMEPAD_H
+
+#include <bitset>
+
+// Forward declaration of the classes that we use from the mbed library
+// This avoids the need for us to include the huge mbed.h header inside our
+// own library API
+namespace mbed
+{
+class AnalogIn;
+class InterruptIn;
+class PwmOut;
+class Timeout;
+}
+
+#define TOL 0.1f
+#define RAD2DEG 57.2957795131f
+
+/** Enum for direction */
+enum Direction {
+    CENTRE,  /**< joystick centred */
+    N,       /**< pushed North (0)*/
+    NE,      /**< pushed North-East (45) */
+    E,       /**< pushed East (90) */
+    SE,      /**< pushed South-East (135) */
+    S,       /**< pushed South (180) */
+    SW,      /**< pushed South-West (225) */
+    W,       /**< pushed West (270) */
+    NW       /**< pushed North-West (315) */
+};
+
+/** Vector 2D struct */
+struct Vector2D {
+    float x; /**< float for x value */
+    float y; /**< float for y value */
+};
+
+/** Polar coordinate struct */
+struct Polar {
+    float mag;  /**< float for magnitude */
+    float angle; /**< float for angle (in degrees) */
+};
+
+/** Gamepad Class
+ * @brief Library for interfacing with ELEC2645 Gamepad PCB, University of Leeds
+ * @author Dr Craig A. Evans
+ * @author Dr Alex Valavanis
+ */
+class Gamepad
+{
+public:
+    /** Gamepad events
+     * @brief List of events that can be registered on the gamepad
+     */
+    enum GamepadEvent {
+        A_PRESSED,     ///< Button A has been pressed
+        B_PRESSED,     ///< Button B has been pressed
+        X_PRESSED,     ///< Button X has been pressed
+        Y_PRESSED,     ///< Button Y has been pressed
+        L_PRESSED,     ///< Button L has been pressed
+        R_PRESSED,     ///< Button R has been pressed
+        BACK_PRESSED,  ///< Button "Back" has been pressed
+        START_PRESSED, ///< Button "Start" has been pressed
+        JOY_PRESSED,   ///< Joystick button has been pressed
+        N_EVENTS       ///< A dummy flag that marks the end of the list
+    };
+
+private:
+    mbed::PwmOut *_led1;
+    mbed::PwmOut *_led2;
+    mbed::PwmOut *_led3;
+    mbed::PwmOut *_led4;
+    mbed::PwmOut *_led5;
+    mbed::PwmOut *_led6;
+
+    mbed::InterruptIn *_button_A;
+    mbed::InterruptIn *_button_B;
+    mbed::InterruptIn *_button_X;
+    mbed::InterruptIn *_button_Y;
+    mbed::InterruptIn *_button_L;
+    mbed::InterruptIn *_button_R;
+    mbed::InterruptIn *_button_back;
+    mbed::InterruptIn *_button_start;
+    mbed::InterruptIn *_button_joystick;
+
+    mbed::AnalogIn *_vert;
+    mbed::AnalogIn *_horiz;
+
+    mbed::PwmOut   *_buzzer;
+    mbed::AnalogIn *_pot;
+
+    mbed::Timeout *_timeout;
+
+    std::bitset<N_EVENTS> _event_state; ///< A binary list of buttons that has been pressed
+
+    // centred x,y values
+    float _x0;
+    float _y0;
+
+public:
+    /** Constructor */
+    Gamepad();
+
+    /** Destructor */
+    ~Gamepad();
+
+    /** Initialise all peripherals and configure interrupts */
+    void init();
+
+    /** Turn all LEDs on */
+    void leds_on();
+
+    /** Turn all LEDs off */
+    void leds_off();
+
+    /** Set all LEDs to duty-cycle
+    *@param value in range 0.0 to 1.0
+    */
+    void leds(float val) const;
+
+    /** Set LED to duty-cycle
+    *@param led number (0 to 5)
+    *@param value in range 0.0 to 1.0
+    */
+    void led(int n,float val) const;
+
+    /** Read potentiometer
+    *@returns potentiometer value in range 0.0 to 1.0
+    */
+    float read_pot() const;
+
+    /** Play tone on piezo
+    * @param frequency in Hz
+    * @param duration of tone in seconds
+    */
+    void tone(float frequency, float duration);
+
+    /**
+     * @brief Check whether an event flag has been set and clear it
+     * @param id[in] The ID of the event to test
+     * @return true if the event occurred
+     */
+    bool check_event(GamepadEvent const id);
+
+    /**
+     * @brief   Get the raw binary event state
+     * @return  The event state as a binary code
+     * @details The check_event() function is likely to be more useful than
+     *          this, for testing whether a given event has occurred. It can be
+     *          useful for debugging via the terminal, however, for example:
+     *          @code
+     *          std::cout << gamepad.get_raw_event_state() << std::endl;
+     *          @endcode
+     */
+    inline std::bitset<N_EVENTS> get_raw_event_state() const
+    {
+        return _event_state;
+    }
+
+    /** Get magnitude of joystick movement
+    * @returns value in range 0.0 to 1.0
+    */
+    float get_mag();
+
+    /** Get angle of joystick movement
+    * @returns value in range 0.0 to 359.9. 0.0 corresponds to N, 180.0 to S. -1.0 is central
+    */
+    float get_angle();
+
+    /** Gets joystick direction
+    * @returns an enum: CENTRE, N, NE, E, SE, S, SW, W, NW,
+    */
+    Direction get_direction();    // N,NE,E,SE etc.
+
+    /** Gets raw cartesian co-ordinates of joystick
+    * @returns a struct with x,y members, each in the range 0.0 to 1.0
+    */
+    Vector2D get_coord();         // cartesian co-ordinates x,y
+
+    /** Gets cartesian coordinates mapped to circular grid
+    * @returns a struct with x,y members, each in the range 0.0 to 1.0
+    */
+    Vector2D get_mapped_coord();  // x,y mapped to circle
+
+    /** Gets polar coordinates of the joystick
+    * @returns a struct contains mag and angle
+    */
+    Polar get_polar();            // mag and angle in struct form
+
+private:
+    void init_buttons();
+    void tone_off();
+
+    void a_reset_isr();
+    void b_reset_isr();
+    void x_reset_isr();
+    void y_reset_isr();
+    void l_reset_isr();
+    void r_reset_isr();
+    void back_reset_isr();
+    void start_reset_isr();
+    void joy_reset_isr();
+
+    void a_isr();
+    void b_isr();
+    void x_isr();
+    void y_isr();
+    void l_isr();
+    void r_isr();
+    void back_isr();
+    void start_isr();
+    void joy_isr();
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/N5110/Bitmap.cpp	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,96 @@
+#include "Bitmap.h"
+
+#include <iostream>
+
+#include "N5110.h"
+
+Bitmap::Bitmap(int const               *contents,
+               unsigned int const       height,
+               unsigned int const       width)
+    :
+    _contents(std::vector<int>(height*width)),
+    _height(height),
+    _width(width)
+{
+    // Perform a quick sanity check of the dimensions
+    if (_contents.size() != height * width) {
+        std::cerr << "Contents of bitmap has size " << _contents.size()
+                  << " pixels, but its dimensions were specified as "
+                  << width << " * " << height << " = " << width * height << std::endl;
+    }
+
+    for(unsigned int i = 0; i < height*width; ++i) _contents[i] = contents[i];
+}
+
+/**
+ * @returns the value of the pixel at the given position
+ */
+int Bitmap::get_pixel(unsigned int const row,
+                      unsigned int const column) const
+{
+    // First check that row and column indices are within bounds
+    if(column >= _width || row >= _height)
+    {
+        std::cerr << "The requested pixel with index " << row << "," << column
+                  << "is outside the bitmap dimensions: " << _width << ","
+                  << _height << std::endl;
+    }
+
+    // Now return the pixel value, using row-major indexing
+    return _contents[row * _width + column];
+}
+
+/**
+ * @brief Prints the contents of the bitmap to the terminal
+ */
+void Bitmap::print() const
+{
+    for (unsigned int row = 0; row < _height; ++row)
+    {
+        // Print each element of the row
+        for (unsigned int column = 0; column < _width; ++column)
+        {
+            int pixel = get_pixel(row, column);
+            std::cout << pixel;
+        }
+
+        // And then terminate with a new-line character
+        std::cout << std::endl;
+    }
+}
+
+/**
+ * @brief Renders the contents of the bitmap onto an N5110 screen
+ *
+ * @param[in] lcd The screen to use for rendering
+ * @param[in] x0  The horizontal position in pixels at which to render the bitmap
+ * @param[in] y0  The vertical position in pixels at which to render the bitmap
+ *
+ * @details Note that x0, y0 gives the location of the top-left of the bitmap on
+ *          the screen.
+ *          This function only updates the buffer on the screen.  You still need
+ *          to refresh the screen in order to actually see the bitmap.
+ */
+void Bitmap::render(N5110 &lcd,
+                    unsigned int const x0,
+                    unsigned int const y0) const
+{
+    // Loop through each row of the bitmap image
+    for (unsigned int bitmap_row = 0; bitmap_row < _height; ++bitmap_row)
+    {
+        // Row index on the screen for rendering the row of pixels
+        unsigned int screen_row = y0 + bitmap_row;
+                
+        // Render each pixel in the row
+        for (unsigned int bitmap_col = 0; bitmap_col < _width; ++bitmap_col)
+        {
+            // Column index on the screen for rendering this pixel
+            int screen_col = x0 + bitmap_col;
+
+            // Find the required value of the pixel at the given location within
+            // the bitmap data and then write it to the LCD screen
+            int pixel = get_pixel(bitmap_row, bitmap_col);
+            lcd.setPixel(screen_col, screen_row, pixel);
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/N5110/Bitmap.h	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,65 @@
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include <vector>
+
+// Forward declarations
+class N5110;
+
+/**
+ * @brief  A black & white bitmap that can be rendered on an N5110 screen
+ * @author Alex Valavanis <a.valavanis@leeds.ac.uk>
+ * 
+ * @code
+  // First declare the pixel map data using '1' for black,
+  // or '0' for white pixels
+  static int sprite_data[] = {
+    0,0,1,0,0,
+    0,1,1,1,0,
+    0,0,1,0,0,
+    0,1,1,1,0,
+    1,1,1,1,1,
+    1,1,1,1,1,
+    1,1,0,1,1,
+    1,1,0,1,1
+  };
+
+  // Instantiate the Bitmap object using the data above
+  Bitmap sprite(sprite_data, 8, 5); // Specify rows and columns in sprite
+  
+  // We can render the bitmap wherever we want on the screen
+  sprite.render(lcd, 20, 6); // x and y locations for rendering
+  sprite.render(lcd, 30, 10);
+  
+  // We can also print its values to the terminal
+  sprite.print();
+ * @endcode
+ */
+class Bitmap
+{
+private:
+    /**
+     * @brief The contents of the drawing, with pixels stored in row-major order
+     * @details '1' represents a black pixel; '0' represents white
+     */
+    std::vector<int> _contents;
+    
+    unsigned int _height; ///< The height of the drawing in pixels
+    unsigned int _width;  ///< The width of the drawing in pixels
+    
+public:
+    Bitmap(int const          *contents,
+           unsigned int const  height,
+           unsigned int const  width);
+
+    int get_pixel(unsigned int const row,
+                  unsigned int const column) const;
+
+    void print() const;
+
+    void render(N5110 &lcd,
+                unsigned int const x0,
+                unsigned int const y0) const;
+};
+
+#endif // BITMAP_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/N5110/N5110.cpp	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,530 @@
+#include "mbed.h"
+#include "N5110.h"
+
+// overloaded constructor includes power pin - LCD Vcc connected to GPIO pin
+// this constructor works fine with LPC1768 - enough current sourced from GPIO
+// to power LCD. Doesn't work well with K64F.
+N5110::N5110(PinName const pwrPin,
+             PinName const scePin,
+             PinName const rstPin,
+             PinName const dcPin,
+             PinName const mosiPin,
+             PinName const sclkPin,
+             PinName const ledPin)
+    :
+    _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
+    _led(new PwmOut(ledPin)),
+    _pwr(new DigitalOut(pwrPin)),
+    _sce(new DigitalOut(scePin)),
+    _rst(new DigitalOut(rstPin)),
+    _dc(new DigitalOut(dcPin))
+{}
+
+// overloaded constructor does not include power pin - LCD Vcc must be tied to +3V3
+// Best to use this with K64F as the GPIO hasn't sufficient output current to reliably
+// drive the LCD.
+N5110::N5110(PinName const scePin,
+             PinName const rstPin,
+             PinName const dcPin,
+             PinName const mosiPin,
+             PinName const sclkPin,
+             PinName const ledPin)
+    :
+    _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise
+    _led(new PwmOut(ledPin)),
+    _pwr(NULL), // pwr not needed so null it to be safe
+    _sce(new DigitalOut(scePin)),
+    _rst(new DigitalOut(rstPin)),
+    _dc(new DigitalOut(dcPin))
+{}
+
+N5110::~N5110()
+{
+    delete _spi;
+
+    if(_pwr) {
+        delete _pwr;
+    }
+
+    delete _led;
+    delete _sce;
+    delete _rst;
+    delete _dc;
+}
+
+// initialise function - powers up and sends the initialisation commands
+void N5110::init()
+{
+    turnOn();     // power up
+    reset();      // reset LCD - must be done within 100 ms
+    initSPI();    
+    
+    setContrast(0.55);  // this may need tuning (say 0.4 to 0.6)
+    setBias(3);   // datasheet - 48:1 mux - don't mess with if you don't know what you're doing! (0 to 7)
+    setTempCoefficient(0); // datasheet - may need increasing (range 0 to 3) at very low temperatures
+    normalMode();  // normal video mode by default
+    
+    clearRAM();      // RAM is undefined at power-up so clear to be sure
+    clear();   // clear buffer
+    setBrightness(0.5);
+}
+
+// sets normal video mode (black on white)
+void N5110::normalMode()
+{
+    sendCommand(0b00100000);   // basic instruction
+    sendCommand(0b00001100);  // normal video mode- datasheet
+}
+
+// sets normal video mode (white on black)
+void N5110::inverseMode()
+{
+    sendCommand(0b00100000);   // basic instruction
+    sendCommand(0b00001101);   // inverse video mode - datasheet
+}
+
+// function to power up the LCD and backlight - only works when using GPIO to power
+void N5110::turnOn()
+{
+    if (_pwr != NULL) {
+        _pwr->write(1);  // apply power
+    }
+}
+
+// function to power down LCD
+void N5110::turnOff()
+{
+    clear(); // clear buffer
+    refresh();
+    setBrightness(0.0);  // turn backlight off
+    clearRAM();   // clear RAM to ensure specified current consumption
+    // send command to ensure we are in basic mode
+    
+    sendCommand(0b00100000); // basic mode
+    sendCommand(0b00001000); // clear display
+    sendCommand(0b00100001); // extended mode
+    sendCommand(0b00100100); // power down
+    
+    // if we are powering the LCD using the GPIO then make it low to turn off
+    if (_pwr != NULL) {
+        wait_ms(10);  // small delay and then turn off the power pin
+        _pwr->write(0);  // turn off power
+    }
+
+}
+
+// function to change LED backlight brightness
+void N5110::setBrightness(float brightness)
+{
+    // check whether brightness is within range
+    if (brightness < 0.0f)
+        brightness = 0.0f;
+    if (brightness > 1.0f)
+        brightness = 1.0f;
+    // set PWM duty cycle
+    _led->write(brightness);
+}
+
+void N5110::setContrast(float contrast) {
+    
+    // enforce limits
+    if (contrast > 1.0f)
+        contrast = 1.0f;
+    else if (contrast < 0.0f)
+        contrast = 0.0;
+    
+    // convert to char in range 0 to 127 (i.e. 6 bits)
+    char ic = char(contrast*127.0f);
+    
+    sendCommand(0b00100001);  // extended instruction set
+    sendCommand(0b10000000 | ic);   // set Vop (which controls contrast)
+    sendCommand(0b00100000);  // back to basic instruction set
+}
+
+void N5110::setTempCoefficient(char tc) {
+    
+    // enforce limits
+    if (tc>3) {
+        tc=3;
+    }
+    
+    // temperature coefficient may need increasing at low temperatures
+
+    sendCommand(0b00100001);  // extended instruction set
+    sendCommand(0b00000100 | tc);
+    sendCommand(0b00100000);  // back to basic instruction set
+}
+    
+void N5110::setBias(char bias) {
+    
+    // from data sheet
+    // bias      mux rate
+    // 0        1:100
+    // 1        1:80
+    // 2        1:65
+    // 3        1:48   (default)
+    // 4        1:40/1:34
+    // 5        1:24
+    // 6        1:18/1:16
+    // 7        1:10/1:9/1:8
+    
+    // enforce limits
+    if (bias>7) {
+        bias=7;
+    }
+        
+    sendCommand(0b00100001);  // extended mode instruction
+    sendCommand(0b00010000 | bias);  
+    sendCommand(0b00100000); // end of extended mode instruction
+}
+
+// pulse the active low reset line
+void N5110::reset()
+{
+    _rst->write(0);  // reset the LCD
+    _rst->write(1);
+}
+
+// function to initialise SPI peripheral
+void N5110::initSPI()
+{
+    _spi->format(8,1);    // 8 bits, Mode 1 - polarity 0, phase 1 - base value of clock is 0, data captured on falling edge/propagated on rising edge
+    _spi->frequency(4000000);  // maximum of screen is 4 MHz
+}
+
+// send a command to the display
+void N5110::sendCommand(unsigned char command)
+{
+    _dc->write(0);  // set DC low for command
+    _sce->write(0); // set CE low to begin frame
+    _spi->write(command);  // send command
+    _dc->write(1);  // turn back to data by default
+    _sce->write(1); // set CE high to end frame (expected for transmission of single byte)
+}
+
+// send data to the display at the current XY address
+// dc is set to 1 (i.e. data) after sending a command and so should
+// be the default mode.
+void N5110::sendData(unsigned char data)
+{
+    _sce->write(0);   // set CE low to begin frame
+    _spi->write(data);
+    _sce->write(1);  // set CE high to end frame (expected for transmission of single byte)
+}
+
+// this function writes 0 to the 504 bytes to clear the RAM
+void N5110::clearRAM()
+{
+    _sce->write(0);  //set CE low to begin frame
+    for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
+        _spi->write(0x00);  // send 0's
+    }
+    _sce->write(1); // set CE high to end frame
+}
+
+// function to set the XY address in RAM for subsequenct data write
+void N5110::setXYAddress(unsigned int const x,
+                         unsigned int const y)
+{
+    if (x<WIDTH && y<HEIGHT) {  // check within range
+        sendCommand(0b00100000);  // basic instruction
+        sendCommand(0b10000000 | x);  // send addresses to display with relevant mask
+        sendCommand(0b01000000 | y);
+    }
+}
+
+// These functions are used to set, clear and get the value of pixels in the display
+// Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x).  The refresh()
+// function must be called after set and clear in order to update the display
+void N5110::setPixel(unsigned int const x,
+                     unsigned int const y,
+                     bool const         state)
+{
+    if (x<WIDTH && y<HEIGHT) {  // check within range
+        // calculate bank and shift 1 to required position in the data byte
+        if(state) buffer[x][y/8] |= (1 << y%8);
+        else      buffer[x][y/8] &= ~(1 << y%8);
+    }
+}
+
+void N5110::clearPixel(unsigned int const x,
+                       unsigned int const y)
+{
+    if (x<WIDTH && y<HEIGHT) {  // check within range
+        // calculate bank and shift 1 to required position (using bit clear)
+        buffer[x][y/8] &= ~(1 << y%8);
+    }
+}
+
+int N5110::getPixel(unsigned int const x,
+                    unsigned int const y) const
+{
+    if (x<WIDTH && y<HEIGHT) {  // check within range
+        // return relevant bank and mask required bit
+
+        int pixel = (int) buffer[x][y/8] & (1 << y%8);
+
+        if (pixel)
+            return 1;
+        else
+            return 0;
+    }
+
+    return 0;
+
+}
+
+// function to refresh the display
+void N5110::refresh()
+{
+    setXYAddress(0,0);  // important to set address back to 0,0 before refreshing display
+    // address auto increments after printing string, so buffer[0][0] will not coincide
+    // with top-left pixel after priting string
+
+    _sce->write(0);  //set CE low to begin frame
+
+    for(int j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
+        for(int i = 0; i < WIDTH; i++) {
+            _spi->write(buffer[i][j]);  // send buffer
+        }
+    }
+    _sce->write(1); // set CE high to end frame
+
+}
+
+// fills the buffer with random bytes.  Can be used to test the display.
+// The rand() function isn't seeded so it probably creates the same pattern everytime
+void N5110::randomiseBuffer()
+{
+    int i,j;
+    for(j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
+        for(i = 0; i < WIDTH; i++) {
+            buffer[i][j] = rand()%256;  // generate random byte
+        }
+    }
+
+}
+
+// function to print 5x7 font
+void N5110::printChar(char const          c,
+                      unsigned int const  x,
+                      unsigned int const  y)
+{
+    if (y<BANKS) {  // check if printing in range of y banks
+
+        for (int i = 0; i < 5 ; i++ ) {
+            int pixel_x = x+i;
+            if (pixel_x > WIDTH-1)  // ensure pixel isn't outside the buffer size (0 - 83)
+                break;
+            buffer[pixel_x][y] = font5x7[(c - 32)*5 + i];
+            // array is offset by 32 relative to ASCII, each character is 5 pixels wide
+        }
+
+    }
+}
+
+// function to print string at specified position
+void N5110::printString(const char         *str,
+                        unsigned int const  x,
+                        unsigned int const  y)
+{
+    if (y<BANKS) {  // check if printing in range of y banks
+
+        int n = 0 ; // counter for number of characters in string
+        // loop through string and print character
+        while(*str) {
+
+            // writes the character bitmap data to the buffer, so that
+            // text and pixels can be displayed at the same time
+            for (int i = 0; i < 5 ; i++ ) {
+                int pixel_x = x+i+n*6;
+                if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83)
+                    break;
+                buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i];
+            }
+            str++;  // go to next character in string
+            n++;    // increment index
+        }
+    }
+}
+
+// function to clear the screen buffer
+void N5110::clear()
+{
+    memset(buffer,0,sizeof(buffer));
+}
+
+// function to plot array on display
+void N5110::plotArray(float const array[])
+{
+    for (int i=0; i<WIDTH; i++) {  // loop through array
+        // elements are normalised from 0.0 to 1.0, so multiply
+        // by 47 to convert to pixel range, and subtract from 47
+        // since top-left is 0,0 in the display geometry
+        setPixel(i,47 - int(array[i]*47.0f),true);
+    }
+
+}
+
+// function to draw circle
+void N5110:: drawCircle(unsigned int const x0,
+                        unsigned int const y0,
+                        unsigned int const radius,
+                        FillType const     fill)
+{
+    // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
+    int x = radius;
+    int y = 0;
+    int radiusError = 1-x;
+
+    while(x >= y) {
+
+        // if transparent, just draw outline
+        if (fill == FILL_TRANSPARENT) {
+            setPixel( x + x0,  y + y0,true);
+            setPixel(-x + x0,  y + y0,true);
+            setPixel( y + x0,  x + y0,true);
+            setPixel(-y + x0,  x + y0,true);
+            setPixel(-y + x0, -x + y0,true);
+            setPixel( y + x0, -x + y0,true);
+            setPixel( x + x0, -y + y0,true);
+            setPixel(-x + x0, -y + y0,true);
+        } else {  // drawing filled circle, so draw lines between points at same y value
+
+            int type = (fill==FILL_BLACK) ? 1:0;  // black or white fill
+
+            drawLine(x+x0,y+y0,-x+x0,y+y0,type);
+            drawLine(y+x0,x+y0,-y+x0,x+y0,type);
+            drawLine(y+x0,-x+y0,-y+x0,-x+y0,type);
+            drawLine(x+x0,-y+y0,-x+x0,-y+y0,type);
+        }
+
+        y++;
+        if (radiusError<0) {
+            radiusError += 2 * y + 1;
+        } else {
+            x--;
+            radiusError += 2 * (y - x) + 1;
+        }
+    }
+
+}
+
+void N5110::drawLine(unsigned int const x0,
+                     unsigned int const y0,
+                     unsigned int const x1,
+                     unsigned int const y1,
+                     unsigned int const type)
+{
+    // Note that the ranges can be negative so we have to turn the input values
+    // into signed integers first
+    int const y_range = static_cast<int>(y1) - static_cast<int>(y0);
+    int const x_range = static_cast<int>(x1) - static_cast<int>(x0);
+
+    // if dotted line, set step to 2, else step is 1
+    unsigned int const step = (type==2) ? 2:1;
+
+    // make sure we loop over the largest range to get the most pixels on the display
+    // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
+    // or else we'll only end up with 1 pixel in the x column
+    if ( abs(x_range) > abs(y_range) ) {
+
+        // ensure we loop from smallest to largest or else for-loop won't run as expected
+        unsigned int const start = x_range > 0 ? x0:x1;
+        unsigned int const stop =  x_range > 0 ? x1:x0;
+
+        // loop between x pixels
+        for (unsigned int x = start; x<= stop ; x+=step) {
+            // do linear interpolation
+            int const dx = static_cast<int>(x)-static_cast<int>(x0);
+            unsigned int const y = y0 + y_range * dx / x_range;
+
+            // If the line type is '0', this will clear the pixel
+            // If it is '1' or '2', the pixel will be set
+            setPixel(x,y, type);
+        }
+    } else {
+
+        // ensure we loop from smallest to largest or else for-loop won't run as expected
+        unsigned int const start = y_range > 0 ? y0:y1;
+        unsigned int const stop =  y_range > 0 ? y1:y0;
+
+        for (unsigned int y = start; y<= stop ; y+=step) {
+            // do linear interpolation
+            int const dy = static_cast<int>(y)-static_cast<int>(y0);
+            unsigned int const x = x0 + x_range * dy / y_range;
+
+            // If the line type is '0', this will clear the pixel
+            // If it is '1' or '2', the pixel will be set
+            setPixel(x,y, type);
+        }
+    }
+
+}
+
+void N5110::drawRect(unsigned int const x0,
+                     unsigned int const y0,
+                     unsigned int const width,
+                     unsigned int const height,
+                     FillType const     fill)
+{
+    if (fill == FILL_TRANSPARENT) { // transparent, just outline
+        drawLine(x0,y0,x0+(width-1),y0,1);  // top
+        drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),1);  // bottom
+        drawLine(x0,y0,x0,y0+(height-1),1);  // left
+        drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),1);  // right
+    } else { // filled rectangle
+        int type = (fill==FILL_BLACK) ? 1:0;  // black or white fill
+        for (int y = y0; y<y0+height; y++) {  // loop through rows of rectangle
+            drawLine(x0,y,x0+(width-1),y,type);  // draw line across screen
+        }
+    }
+}
+
+void N5110::drawSprite(int x0,
+                       int y0,
+                       int nrows,
+                       int ncols,
+                       int *sprite)
+{
+    for (int i = 0; i < nrows; i++) {
+        for (int j = 0 ; j < ncols ; j++) {
+
+            int pixel = *((sprite+i*ncols)+j);
+            if (pixel == 2) {
+                pixel = 0;
+            }
+            setPixel(x0+j,y0+i, pixel);
+        }
+    }
+}
+
+void N5110::drawSpriteTransparent(int x0,
+                                  int y0,
+                                  int nrows,
+                                  int ncols,
+                                  int *sprite)
+{
+    for (int i = 0; i < nrows; i++) {
+        for (int j = 0 ; j < ncols ; j++) {
+
+            int pixel = *((sprite+i*ncols)+j);
+            if (pixel != 0) {
+                if (pixel == 2) {
+                    pixel = 0;
+                }
+                setPixel(x0+j,y0+i, pixel);
+            }
+        }
+    }
+}
+
+int * N5110::readScreen()
+{
+    for (unsigned int i = 0; i < WIDTH; i++) {
+        for (unsigned int j = 0; j < HEIGHT; j++) {
+            screen_array[j][i] = getPixel(i, j);
+        }
+    }
+    return * screen_array;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Peripherals/N5110/N5110.h	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,543 @@
+#ifndef N5110_H
+#define N5110_H
+
+#include "mbed.h"
+
+// number of pixels on display
+#define WIDTH 84
+#define HEIGHT 48
+#define BANKS 6
+
+/// Fill types for 2D shapes
+enum FillType {
+    FILL_TRANSPARENT, ///< Transparent with outline
+    FILL_BLACK,       ///< Filled black
+    FILL_WHITE,       ///< Filled white (no outline)
+};
+
+/** N5110 Class
+@brief Library for interfacing with Nokia 5110 LCD display (https://www.sparkfun.com/products/10168) using the hardware SPI on the mbed.
+@brief The display is powered from a GPIO pin meaning it can be controlled via software.  The LED backlight is also software-controllable (via PWM pin).
+@brief Can print characters and strings to the display using the included 5x7 font.
+@brief The library also implements a screen buffer so that individual pixels on the display (84 x 48) can be set, cleared and read.
+@brief The library can print primitive shapes (lines, circles, rectangles)
+@brief Acknowledgements to Chris Yan's Nokia_5110 Library.
+
+@brief Revision 1.3
+
+@author Craig A. Evans
+@date   7th February 2017
+
+@code
+
+#include "mbed.h"
+#include "N5110.h"
+
+//      rows,cols
+int sprite[8][5] =   {
+    { 0,0,1,0,0 },
+    { 0,1,1,1,0 },
+    { 0,0,1,0,0 },
+    { 0,1,1,1,0 },
+    { 1,1,1,1,1 },
+    { 1,1,1,1,1 },
+    { 1,1,0,1,1 },
+    { 1,1,0,1,1 },
+};
+
+//    VCC,SCE,RST,D/C,MOSI,SCLK,LED
+//N5110 lcd(p7,p8,p9,p10,p11,p13,p21);  // LPC1768 - pwr from GPIO
+N5110 lcd(p8,p9,p10,p11,p13,p21);  // LPC1768 - powered from +3V3 - JP1 in 2/3 position
+//N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11);  // K64F - pwr from 3V3
+
+int main()
+{
+    // first need to initialise display
+    lcd.init();
+    
+    // change set contrast in range 0.0 to 1.0
+    // 0.4 appears to be a good starting point
+    lcd.setContrast(0.4);
+
+    while(1) {
+
+        // these are default settings so not strictly needed
+        lcd.normalMode();      // normal colour mode
+        lcd.setBrightness(0.5); // put LED backlight on 50%
+
+        lcd.clear();
+        // x origin, y origin, rows, cols, sprite
+        lcd.drawSprite(20,6,8,5,(int *)sprite);
+        lcd.refresh();
+        wait(5.0);
+
+        lcd.clear(); // clear buffer at start of every loop
+        // can directly print strings at specified co-ordinates (must be less than 84 pixels to fit on display)
+        lcd.printString("Hello, World!",0,0);
+
+        char buffer[14];  // each character is 6 pixels wide, screen is 84 pixels (84/6 = 14)
+        // so can display a string of a maximum 14 characters in length
+        // or create formatted strings - ensure they aren't more than 14 characters long
+        int temperature = 27;
+        int length = sprintf(buffer,"T = %2d C",temperature); // print formatted data to buffer
+        // it is important the format specifier ensures the length will fit in the buffer
+        if (length <= 14)  // if string will fit on display (assuming printing at x=0)
+            lcd.printString(buffer,0,1);           // display on screen
+
+        float pressure = 1012.3;  // same idea with floats
+        length = sprintf(buffer,"P = %.2f mb",pressure);
+        if (length <= 14)
+            lcd.printString(buffer,0,2);
+
+        // can also print individual characters at specified place
+        lcd.printChar('X',5,3);
+
+        // draw a line across the display at y = 40 pixels (origin top-left)
+        for (int i = 0; i < WIDTH; i++) {
+            lcd.setPixel(i,40,true);
+        }
+        // need to refresh display after setting pixels or writing strings
+        lcd.refresh();
+        wait(5.0);
+
+        // can check status of pixel using getPixel(x,y);
+        lcd.clear();  // clear buffer
+        lcd.setPixel(2,2,true);  // set random pixel in buffer
+        lcd.refresh();
+        wait(1.0);
+
+        int pixel_to_test = lcd.getPixel(2,2);
+
+        if ( pixel_to_test ) {
+            lcd.printString("2,2 is set",0,4);
+        }
+
+        // this one shouldn't be set
+        lcd.setPixel(3,3,false);  // clear random pixel in buffer
+        lcd.refresh();
+        pixel_to_test = lcd.getPixel(3,3);
+
+        if ( pixel_to_test == 0 ) {
+            lcd.printString("3,3 is clear",0,5);
+        }
+
+        lcd.refresh();
+        wait(4.0);
+
+        lcd.clear();            // clear buffer
+        lcd.inverseMode();      // invert colours
+        lcd.setBrightness(1.0); // put LED backlight on full
+
+        float array[84];
+
+        for (int i = 0; i < 84; i++) {
+            array[i] = 0.5 + 0.5*sin(i*2*3.14/84);
+        }
+
+        // can also plot graphs - 84 elements only
+        // values must be in range 0.0 - 1.0
+        lcd.plotArray(array);
+        lcd.refresh();
+        wait(5.0);
+
+        lcd.clear();
+        lcd.normalMode();      // normal colour mode back
+        lcd.setBrightness(0.5); // put LED backlight on 50%
+
+        // example of drawing lines
+        for (int x = 0; x < WIDTH ; x+=10) {
+            // x0,y0,x1,y1,type 0-white,1-black,2-dotted
+            lcd.drawLine(0,0,x,HEIGHT,2);
+        }
+        lcd.refresh();  // refresh after drawing shapes
+        wait(5.0);
+
+
+        lcd.clear();
+        // example of how to draw circles
+        lcd.drawCircle(WIDTH/2,HEIGHT/2,20,FILL_BLACK);  // x,y,radius,black fill
+        lcd.drawCircle(WIDTH/2,HEIGHT/2,10,FILL_WHITE);  // x,y,radius,white fill
+        lcd.drawCircle(WIDTH/2,HEIGHT/2,30,FILL_TRANSPARENT);  // x,y,radius,transparent with outline
+        lcd.refresh();  // refresh after drawing shapes
+        wait(5.0);
+
+        lcd.clear();
+        // example of how to draw rectangles
+        //          origin x,y,width,height,type
+        lcd.drawRect(10,10,50,30,FILL_BLACK);  // filled black rectangle
+        lcd.drawRect(15,15,20,10,FILL_WHITE);  // filled white rectange (no outline)
+        lcd.drawRect(2,2,70,40,FILL_TRANSPARENT);    // transparent, just outline
+        lcd.refresh();  // refresh after drawing shapes
+        wait(5.0);
+
+    }
+}
+
+
+@endcode
+*/
+class N5110
+{
+private:
+// objects
+    SPI         *_spi;
+    PwmOut      *_led;
+    DigitalOut  *_pwr;
+    DigitalOut  *_sce;
+    DigitalOut  *_rst;
+    DigitalOut  *_dc;
+
+// variables
+    unsigned char buffer[84][6];  // screen buffer - the 6 is for the banks - each one is 8 bits;
+    int screen_array[48][84];
+
+public:
+    /** Create a N5110 object connected to the specified pins
+    *
+    * @param pwr  Pin connected to Vcc on the LCD display (pin 1)
+    * @param sce  Pin connected to chip enable (pin 3)
+    * @param rst  Pin connected to reset (pin 4)
+    * @param dc   Pin connected to data/command select (pin 5)
+    * @param mosi Pin connected to data input (MOSI) (pin 6)
+    * @param sclk Pin connected to serial clock (SCLK) (pin 7)
+    * @param led  Pin connected to LED backlight (must be PWM) (pin 8)
+    *
+    */
+    N5110(PinName const pwrPin,
+          PinName const scePin,
+          PinName const rstPin,
+          PinName const dcPin,
+          PinName const mosiPin,
+          PinName const sclkPin,
+          PinName const ledPin);
+
+    /** Create a N5110 object connected to the specified pins (Vcc to +3V3)
+    *
+    * @param sce  Pin connected to chip enable (pin 3)
+    * @param rst  Pin connected to reset (pin 4)
+    * @param dc   Pin connected to data/command select (pin 5)
+    * @param mosi Pin connected to data input (MOSI) (pin 6)
+    * @param sclk Pin connected to serial clock (SCLK) (pin 7)
+    * @param led  Pin connected to LED backlight (must be PWM) (pin 8)
+    *
+    */
+    N5110(PinName const scePin,
+          PinName const rstPin,
+          PinName const dcPin,
+          PinName const mosiPin,
+          PinName const sclkPin,
+          PinName const ledPin);
+
+    /**
+     * Free allocated memory when object goes out of scope
+     */
+    ~N5110();
+
+    /** Initialise display
+    *
+    *   Powers up the display and turns on backlight (50% brightness default).
+    *   Sets the display up in horizontal addressing mode and with normal video mode.
+    */
+    void init();
+
+    /** Turn off
+    *
+    *   Powers down the display and turns of the backlight.
+    *   Needs to be reinitialised before being re-used.
+    */
+    void turnOff();
+
+    /** Clear
+    *
+    *   Clears the screen buffer.
+    */
+    void clear();
+
+    /** Set screen constrast
+    *   @param constrast - float in range 0.0 to 1.0 (0.40 to 0.60 is usually a good value)
+    */
+    void setContrast(float contrast);
+    
+    /** Turn on normal video mode (default)
+    *  Black on white
+    */
+    void normalMode();
+
+    /** Turn on inverse video mode (default)
+    *  White on black
+    */
+    void inverseMode();
+
+    /** Set Brightness
+    *
+    *   Sets brightness of LED backlight.
+    *   @param brightness - float in range 0.0 to 1.0
+    */
+    void setBrightness(float const brightness);
+
+    /** Print String
+    *
+    *   Prints a string of characters to the screen buffer. String is cut-off after the 83rd pixel.
+    *   @param x - the column number (0 to 83)
+    *   @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row
+    */
+    void printString(char const         *str,
+                     unsigned int const  x,
+                     unsigned int const  y);
+
+    /** Print Character
+    *
+    *   Sends a character to the screen buffer.  Printed at the specified location. Character is cut-off after the 83rd pixel.
+    *   @param  c - the character to print. Can print ASCII as so printChar('C').
+    *   @param x - the column number (0 to 83)
+    *   @param y - the row number (0 to 5) - the display is split into 6 banks - each bank can be considered a row
+    */
+    void printChar(char const         c,
+                   unsigned int const x,
+                   unsigned int const y);
+
+    /**
+    * @brief Set a Pixel
+    *
+    * @param x     The x co-ordinate of the pixel (0 to 83)
+    * @param y     The y co-ordinate of the pixel (0 to 47)
+    * @param state The state of the pixel [true=black (default), false=white]
+    *
+    * @details This function sets the state of a pixel in the screen buffer.
+    *          The third parameter can be omitted,
+    */
+    void setPixel(unsigned int const x,
+                  unsigned int const y,
+                  bool const         state = true);
+
+    /**
+    *  @brief Clear a Pixel
+    *
+    *   @param  x - the x co-ordinate of the pixel (0 to 83)
+    *   @param  y - the y co-ordinate of the pixel (0 to 47)
+    *
+    *   @details This function clears pixel in the screen buffer
+    *
+    *   @deprecated Use setPixel(x, y, false) instead
+    */
+    void clearPixel(unsigned int const x,
+                    unsigned int const y)
+    __attribute__((deprecated("Use setPixel(x,y,false) instead")));
+
+    /** Get a Pixel
+    *
+    *   This function gets the status of a pixel in the screen buffer.
+    *   @param  x - the x co-ordinate of the pixel (0 to 83)
+    *   @param  y - the y co-ordinate of the pixel (0 to 47)
+    *   @returns
+    *       0           - pixel is clear
+    *       1    - pixel is set
+    */
+    int getPixel(unsigned int const x,
+                 unsigned int const y) const;
+
+    /** Refresh display
+    *
+    *   This functions sends the screen buffer to the display.
+    */
+    void refresh();
+
+    /** Randomise buffer
+    *
+    *   This function fills the buffer with random data.  Can be used to test the display.
+    *   A call to refresh() must be made to update the display to reflect the change in pixels.
+    *   The seed is not set and so the generated pattern will probably be the same each time.
+    *   TODO: Randomise the seed - maybe using the noise on the AnalogIn pins.
+    */
+    void randomiseBuffer();
+
+    /** Plot Array
+    *
+    *   This function plots a one-dimensional array in the buffer.
+    *   @param array[] - y values of the plot. Values should be normalised in the range 0.0 to 1.0. First 84 plotted.
+    */
+    void plotArray(float const array[]);
+
+    /** Draw Circle
+    *
+    *   This function draws a circle at the specified origin with specified radius in the screen buffer
+    *   Uses the midpoint circle algorithm.
+    *   @see http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
+    *   @param  x0     - x-coordinate of centre
+    *   @param  y0     - y-coordinate of centre
+    *   @param  radius - radius of circle in pixels
+    *   @param  fill   - fill-type for the shape
+    */
+    void drawCircle(unsigned int const x0,
+                    unsigned int const y0,
+                    unsigned int const radius,
+                    FillType const     fill);
+
+    /** Draw Line
+    *
+    *   This function draws a line between the specified points using linear interpolation.
+    *   @param  x0 - x-coordinate of first point
+    *   @param  y0 - y-coordinate of first point
+    *   @param  x1 - x-coordinate of last point
+    *   @param  y1 - y-coordinate of last point
+    *   @param  type - 0 white,1 black,2 dotted
+    */
+    void drawLine(unsigned int const x0,
+                  unsigned int const y0,
+                  unsigned int const x1,
+                  unsigned int const y1,
+                  unsigned int const type);
+
+    /** Draw Rectangle
+    *
+    *   This function draws a rectangle.
+    *   @param  x0 - x-coordinate of origin (top-left)
+    *   @param  y0 - y-coordinate of origin (top-left)
+    *   @param  width - width of rectangle
+    *   @param  height - height of rectangle
+    *   @param  fill   - fill-type for the shape
+    */
+    void drawRect(unsigned int const x0,
+                  unsigned int const y0,
+                  unsigned int const width,
+                  unsigned int const height,
+                  FillType const     fill);
+
+    /** Draw Sprite
+    *
+    *   This function draws a sprite as defined in a 2D array
+    *   @param  x0 - x-coordinate of origin (top-left)
+    *   @param  y0 - y-coordinate of origin (top-left)
+    *   @param  nrows - number of rows in sprite
+    *   @param  ncols - number of columns in sprite
+    *   @param  sprite - 2D array representing the sprite
+    */
+    void drawSprite(int x0,
+                    int y0,
+                    int nrows,
+                    int ncols,
+                    int *sprite);
+    
+    void drawSpriteTransparent(int x0,
+                               int y0,
+                               int nrows,
+                               int ncols,
+                               int *sprite);
+                               
+    int * readScreen();
+
+
+private:
+// methods
+    void setXYAddress(unsigned int const x,
+                      unsigned int const y);
+    void initSPI();
+    void turnOn();
+    void reset();
+    void clearRAM();
+    void sendCommand(unsigned char command);
+    void sendData(unsigned char data);
+    void setTempCoefficient(char tc);  // 0 to 3
+    void setBias(char bias);  // 0 to 7
+};
+
+const unsigned char font5x7[480] = {
+    0x00, 0x00, 0x00, 0x00, 0x00,// (space)
+    0x00, 0x00, 0x5F, 0x00, 0x00,// !
+    0x00, 0x07, 0x00, 0x07, 0x00,// "
+    0x14, 0x7F, 0x14, 0x7F, 0x14,// #
+    0x24, 0x2A, 0x7F, 0x2A, 0x12,// $
+    0x23, 0x13, 0x08, 0x64, 0x62,// %
+    0x36, 0x49, 0x55, 0x22, 0x50,// &
+    0x00, 0x05, 0x03, 0x00, 0x00,// '
+    0x00, 0x1C, 0x22, 0x41, 0x00,// (
+    0x00, 0x41, 0x22, 0x1C, 0x00,// )
+    0x08, 0x2A, 0x1C, 0x2A, 0x08,// *
+    0x08, 0x08, 0x3E, 0x08, 0x08,// +
+    0x00, 0x50, 0x30, 0x00, 0x00,// ,
+    0x08, 0x08, 0x08, 0x08, 0x08,// -
+    0x00, 0x60, 0x60, 0x00, 0x00,// .
+    0x20, 0x10, 0x08, 0x04, 0x02,// /
+    0x3E, 0x51, 0x49, 0x45, 0x3E,// 0
+    0x00, 0x42, 0x7F, 0x40, 0x00,// 1
+    0x42, 0x61, 0x51, 0x49, 0x46,// 2
+    0x21, 0x41, 0x45, 0x4B, 0x31,// 3
+    0x18, 0x14, 0x12, 0x7F, 0x10,// 4
+    0x27, 0x45, 0x45, 0x45, 0x39,// 5
+    0x3C, 0x4A, 0x49, 0x49, 0x30,// 6
+    0x01, 0x71, 0x09, 0x05, 0x03,// 7
+    0x36, 0x49, 0x49, 0x49, 0x36,// 8
+    0x06, 0x49, 0x49, 0x29, 0x1E,// 9
+    0x00, 0x36, 0x36, 0x00, 0x00,// :
+    0x00, 0x56, 0x36, 0x00, 0x00,// ;
+    0x00, 0x08, 0x14, 0x22, 0x41,// <
+    0x14, 0x14, 0x14, 0x14, 0x14,// =
+    0x41, 0x22, 0x14, 0x08, 0x00,// >
+    0x02, 0x01, 0x51, 0x09, 0x06,// ?
+    0x32, 0x49, 0x79, 0x41, 0x3E,// @
+    0x7E, 0x11, 0x11, 0x11, 0x7E,// A
+    0x7F, 0x49, 0x49, 0x49, 0x36,// B
+    0x3E, 0x41, 0x41, 0x41, 0x22,// C
+    0x7F, 0x41, 0x41, 0x22, 0x1C,// D
+    0x7F, 0x49, 0x49, 0x49, 0x41,// E
+    0x7F, 0x09, 0x09, 0x01, 0x01,// F
+    0x3E, 0x41, 0x41, 0x51, 0x32,// G
+    0x7F, 0x08, 0x08, 0x08, 0x7F,// H
+    0x00, 0x41, 0x7F, 0x41, 0x00,// I
+    0x20, 0x40, 0x41, 0x3F, 0x01,// J
+    0x7F, 0x08, 0x14, 0x22, 0x41,// K
+    0x7F, 0x40, 0x40, 0x40, 0x40,// L
+    0x7F, 0x02, 0x04, 0x02, 0x7F,// M
+    0x7F, 0x04, 0x08, 0x10, 0x7F,// N
+    0x3E, 0x41, 0x41, 0x41, 0x3E,// O
+    0x7F, 0x09, 0x09, 0x09, 0x06,// P
+    0x3E, 0x41, 0x51, 0x21, 0x5E,// Q
+    0x7F, 0x09, 0x19, 0x29, 0x46,// R
+    0x46, 0x49, 0x49, 0x49, 0x31,// S
+    0x01, 0x01, 0x7F, 0x01, 0x01,// T
+    0x3F, 0x40, 0x40, 0x40, 0x3F,// U
+    0x1F, 0x20, 0x40, 0x20, 0x1F,// V
+    0x7F, 0x20, 0x18, 0x20, 0x7F,// W
+    0x63, 0x14, 0x08, 0x14, 0x63,// X
+    0x03, 0x04, 0x78, 0x04, 0x03,// Y
+    0x61, 0x51, 0x49, 0x45, 0x43,// Z
+    0x00, 0x00, 0x7F, 0x41, 0x41,// [
+    0x02, 0x04, 0x08, 0x10, 0x20,// "\"
+    0x41, 0x41, 0x7F, 0x00, 0x00,// ]
+    0x04, 0x02, 0x01, 0x02, 0x04,// ^
+    0x40, 0x40, 0x40, 0x40, 0x40,// _
+    0x00, 0x01, 0x02, 0x04, 0x00,// `
+    0x20, 0x54, 0x54, 0x54, 0x78,// a
+    0x7F, 0x48, 0x44, 0x44, 0x38,// b
+    0x38, 0x44, 0x44, 0x44, 0x20,// c
+    0x38, 0x44, 0x44, 0x48, 0x7F,// d
+    0x38, 0x54, 0x54, 0x54, 0x18,// e
+    0x08, 0x7E, 0x09, 0x01, 0x02,// f
+    0x08, 0x14, 0x54, 0x54, 0x3C,// g
+    0x7F, 0x08, 0x04, 0x04, 0x78,// h
+    0x00, 0x44, 0x7D, 0x40, 0x00,// i
+    0x20, 0x40, 0x44, 0x3D, 0x00,// j
+    0x00, 0x7F, 0x10, 0x28, 0x44,// k
+    0x00, 0x41, 0x7F, 0x40, 0x00,// l
+    0x7C, 0x04, 0x18, 0x04, 0x78,// m
+    0x7C, 0x08, 0x04, 0x04, 0x78,// n
+    0x38, 0x44, 0x44, 0x44, 0x38,// o
+    0x7C, 0x14, 0x14, 0x14, 0x08,// p
+    0x08, 0x14, 0x14, 0x18, 0x7C,// q
+    0x7C, 0x08, 0x04, 0x04, 0x08,// r
+    0x48, 0x54, 0x54, 0x54, 0x20,// s
+    0x04, 0x3F, 0x44, 0x40, 0x20,// t
+    0x3C, 0x40, 0x40, 0x20, 0x7C,// u
+    0x1C, 0x20, 0x40, 0x20, 0x1C,// v
+    0x3C, 0x40, 0x30, 0x40, 0x3C,// w
+    0x44, 0x28, 0x10, 0x28, 0x44,// x
+    0x0C, 0x50, 0x50, 0x50, 0x3C,// y
+    0x44, 0x64, 0x54, 0x4C, 0x44,// z
+    0x00, 0x08, 0x36, 0x41, 0x00,// {
+    0x00, 0x00, 0x7F, 0x00, 0x00,// |
+    0x00, 0x41, 0x36, 0x08, 0x00,// }
+    0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
+    0x08, 0x1C, 0x2A, 0x08, 0x08 // <-
+};
+
+#endif
\ No newline at end of file
--- a/Room/Room.cpp	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-#include "Room.h"
-
-// Constructor
-Room::Room(int no_of_enemies)
-{
-    for (int id = 0; id < MAX_ENEMIES; id++)
-    {
-        valid_enemies[id] = id < no_of_enemies;
-        if (id < no_of_enemies) {
-            enemies_type[id] = rand() % 2;
-            _enemy_coord[id][0] = 11 + (rand() % 60);
-            _enemy_coord[id][1] = 18 + (rand() % 19);
-        }
-    }
-    
-    _room_type = 0;
-    _doorways[0] = true;
-    _doorways[1] = true;
-    _doorways[2] = true;
-    _doorways[3] = true;
-}
-
-// Deconstructor
-Room::~Room()
-{
-    terminate();
-}
-
-// Accessors
-int * Room::get_current_map_2d(){
-    return ((int *)level_map[_room_type][0]);
-}
-
-bool * Room::get_doorways(){
-    return (bool *)_doorways;
-}
-
-// Functions
-void Room::load()
-{
-    for (int id = 0; id < MAX_ENEMIES; id++) {
-        if (valid_enemies[id]) {
-            switch(enemies_type[id]){
-                case 0 :
-                    enemies[id] = new Headless(_enemy_coord[id][0], _enemy_coord[id][1]);
-                    break;
-                case 1 :
-                    enemies[id] = new Snake(_enemy_coord[id][0], _enemy_coord[id][1]);
-                    break;
-            }
-//            for every enemy
-//            if (collision) {
-//                relocate enemy
-//                goto back
-//            }
-        }
-    }
-}
-
-void Room::unload()
-{
-    for (int i = 0; i < MAX_ENEMIES; i++) {
-        if (valid_enemies[i]) {
-            delete enemies[i];
-        }
-    };
-}
-
-void Room::draw_room(N5110 &lcd)
-{
-    lcd.drawSprite(0, 0, screen_height, screen_width, (int *)level_map[_room_type][1]); // drawing 3d map
-    //draw_walls(lcd);
-    
-}
-
-void Room::draw_walls(N5110 &lcd)
-{
-    if(_doorways[0]) { // N
-        lcd.drawSprite(36, 0, 12, 10, (int *)wall_n);
-    }
-    if(_doorways[1]) { // E
-        lcd.drawSprite(81, 15, 3, 11, (int *)wall_x[0]);
-    }
-    if(_doorways[2]) { // S
-        lcd.drawSprite(36, 45, 12, 3, (int *)wall_s);
-    }
-    if(_doorways[3]) { // W
-        lcd.drawSprite(0, 15, 3, 11, (int *)wall_x[1]);
-    }
-}
-
-void Room::draw_room_overlay(N5110 &lcd)
-{
-    lcd.drawSpriteTransparent(0, 0, screen_height, screen_width, (int *)level_map[_room_type][2]); // drawing 3d map overlay
-    //draw_walls_overlay(lcd);
-}
-
-void Room::draw_walls_overlay(N5110 &lcd)
-{
-    if(_doorways[0]) { // N
-        lcd.drawSpriteTransparent(36, 0, 12, 10, (int *)wall_n);
-    }
-    if(_doorways[1]) { // E
-        lcd.drawSpriteTransparent(81, 15, 3, 11, (int *)wall_x[0]);
-    }
-    if(_doorways[2]) { // S
-        lcd.drawSpriteTransparent(36, 45, 12, 3, (int *)wall_s);
-    }
-    if(_doorways[3]) { // W
-        lcd.drawSpriteTransparent(0, 15, 3, 11, (int *)wall_x[1]);
-    }
-}
\ No newline at end of file
--- a/Room/Room.h	Sat May 04 15:39:20 2019 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-#ifndef ROOM_H
-#define ROOM_H
-#include "sprites.h"
-
-#include "Entity.h"
-#include "Player.h"
-#include "Headless.h"
-#include "Snake.h"
-
-#include "N5110.h"
-
-#define MAX_ENEMIES 10
-
-class Room // contains the type of room, number of enemies inside it, the doorways existing in the room, functions to spawn enemies
-{
-private:
-    bool _doorways[4];
-    int _room_type;
-    int _enemy_coord[MAX_ENEMIES][2]; //  _enemy_coord[EnemyID][x/y]
-    
-    // Functions
-    void draw_walls(N5110 &lcd);
-    void draw_walls_overlay(N5110 &lcd);
-    
-public:
-    // Constructors
-    Room(int no_of_enemies);
-    // Deconstructors
-    ~Room();
-    
-    // Accessors
-    int * get_current_map_2d();
-    bool * get_doorways();
-    
-    // Functions
-    void load();
-    void unload();
-    void draw_room(N5110 &lcd);
-    void draw_room_overlay(N5110 &lcd);
-    
-    // Variables
-    Entity *enemies[MAX_ENEMIES];
-    bool valid_enemies[MAX_ENEMIES];
-    int enemies_type[MAX_ENEMIES];
-};
-
-const int wall_x[2][11][3] = { // [E/W][Size_Y][Size_X]
-    {   // E
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-        {1,2,2},
-    },
-    {   // W
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-        {2,2,1},
-    }
-};
-
-const int wall_n[10][12] = { // [Size_Y][Size_X] 
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {1,1,1,1,1,1,1,1,1,1,1,1,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {0,0,0,0,0,0,0,0,0,0,0,0,},
-    {1,1,1,1,1,1,1,1,1,1,1,1,},
-};
-
-const int wall_s[3][12] = { // [Size_Y][Size_X]
-    {1,1,1,1,1,1,1,1,1,1,1,1,},
-    {2,2,2,2,2,2,2,2,2,2,2,2,},
-    {2,2,2,2,2,2,2,2,2,2,2,2,},
-};
-
-#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RoomEngine/Room/Room.cpp	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,112 @@
+#include "Room.h"
+
+// Constructor
+Room::Room(int no_of_enemies)
+{
+    for (int id = 0; id < MAX_ENEMIES; id++)
+    {
+        valid_enemies[id] = id < no_of_enemies;
+        if (id < no_of_enemies) {
+            enemies_type[id] = rand() % 2;
+            _enemy_coord[id][0] = 15 + (rand() % 52);
+            _enemy_coord[id][1] = 14 + (rand() % 11);
+        }
+    }
+    
+    _room_type = 0;
+    _doorways[0] = true;
+    _doorways[1] = true;
+    _doorways[2] = true;
+    _doorways[3] = true;
+}
+
+// Deconstructor
+Room::~Room()
+{
+    terminate();
+}
+
+// Accessors
+int * Room::get_current_map_2d(){
+    return ((int *)level_map[_room_type][0]);
+}
+
+bool * Room::get_doorways(){
+    return (bool *)_doorways;
+}
+
+// Functions
+void Room::load()
+{
+    for (int id = 0; id < MAX_ENEMIES; id++) {
+        if (valid_enemies[id]) {
+            switch(enemies_type[id]){
+                case 0 :
+                    enemies[id] = new Headless(_enemy_coord[id][0], _enemy_coord[id][1]);
+                    break;
+                case 1 :
+                    enemies[id] = new Snake(_enemy_coord[id][0], _enemy_coord[id][1]);
+                    break;
+            }
+//            for every enemy
+//            if (collision) {
+//                relocate enemy
+//                goto back
+//            }
+        }
+    }
+}
+
+void Room::unload()
+{
+    for (int i = 0; i < MAX_ENEMIES; i++) {
+        if (valid_enemies[i]) {
+            delete enemies[i];
+        }
+    };
+}
+
+void Room::draw_room(N5110 &lcd)
+{
+    lcd.drawSprite(0, 0, screen_height, screen_width, (int *)level_map[_room_type][1]); // drawing 3d map
+    //draw_walls(lcd);
+    
+}
+
+void Room::draw_walls(N5110 &lcd)
+{
+    if(_doorways[0]) { // N
+        lcd.drawSprite(36, 0, 12, 10, (int *)wall_n);
+    }
+    if(_doorways[1]) { // E
+        lcd.drawSprite(81, 15, 3, 11, (int *)wall_x[0]);
+    }
+    if(_doorways[2]) { // S
+        lcd.drawSprite(36, 45, 12, 3, (int *)wall_s);
+    }
+    if(_doorways[3]) { // W
+        lcd.drawSprite(0, 15, 3, 11, (int *)wall_x[1]);
+    }
+}
+
+void Room::draw_room_overlay(N5110 &lcd)
+{
+    lcd.drawSpriteTransparent(0, 0, screen_height, screen_width, (int *)level_map[_room_type][2]); // drawing 3d map overlay
+    //draw_walls_overlay(lcd);
+}
+
+void Room::draw_walls_overlay(N5110 &lcd)
+{
+    if(_doorways[0]) { // N
+        lcd.drawSpriteTransparent(36, 0, 12, 10, (int *)wall_n);
+    }
+    if(_doorways[1]) { // E
+        lcd.drawSpriteTransparent(81, 15, 3, 11, (int *)wall_x[0]);
+    }
+    if(_doorways[2]) { // S
+        lcd.drawSpriteTransparent(36, 45, 12, 3, (int *)wall_s);
+    }
+    if(_doorways[3]) { // W
+        lcd.drawSpriteTransparent(0, 15, 3, 11, (int *)wall_x[1]);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RoomEngine/Room/Room.h	Sun May 05 18:04:43 2019 +0000
@@ -0,0 +1,95 @@
+#ifndef ROOM_H
+#define ROOM_H
+#include "sprites.h"
+
+#include "Entity.h"
+#include "Player.h"
+#include "Headless.h"
+#include "Snake.h"
+
+#include "N5110.h"
+
+#define MAX_ENEMIES 10
+
+class Room // contains the type of room, number of enemies inside it, the doorways existing in the room, functions to spawn enemies
+{
+private:
+    bool _doorways[4];
+    int _room_type;
+    int _enemy_coord[MAX_ENEMIES][2]; //  _enemy_coord[EnemyID][x/y]
+    
+    // Functions
+    void draw_walls(N5110 &lcd);
+    void draw_walls_overlay(N5110 &lcd);
+    
+public:
+    // Constructors
+    Room(int no_of_enemies);
+    // Deconstructors
+    ~Room();
+    
+    // Accessors
+    int * get_current_map_2d();
+    bool * get_doorways();
+    
+    // Functions
+    void load();
+    void unload();
+    void draw_room(N5110 &lcd);
+    void draw_room_overlay(N5110 &lcd);
+    
+    // Variables
+    Entity *enemies[MAX_ENEMIES];
+    bool valid_enemies[MAX_ENEMIES];
+    int enemies_type[MAX_ENEMIES];
+};
+
+const int wall_x[2][11][3] = { // [E/W][Size_Y][Size_X]
+    {   // E
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+        {1,2,2},
+    },
+    {   // W
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+        {2,2,1},
+    }
+};
+
+const int wall_n[10][12] = { // [Size_Y][Size_X] 
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {1,1,1,1,1,1,1,1,1,1,1,1,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {0,0,0,0,0,0,0,0,0,0,0,0,},
+    {1,1,1,1,1,1,1,1,1,1,1,1,},
+};
+
+const int wall_s[3][12] = { // [Size_Y][Size_X]
+    {1,1,1,1,1,1,1,1,1,1,1,1,},
+    {2,2,2,2,2,2,2,2,2,2,2,2,},
+    {2,2,2,2,2,2,2,2,2,2,2,2,},
+};
+
+#endif
\ No newline at end of file
--- a/RoomEngine/RoomEngine.cpp	Sat May 04 15:39:20 2019 +0000
+++ b/RoomEngine/RoomEngine.cpp	Sun May 05 18:04:43 2019 +0000
@@ -1,8 +1,10 @@
 #include "RoomEngine.h"
-RoomEngine::RoomEngine()
+
+RoomEngine::RoomEngine(float global_contrast)
 {
     _room_x = 5;
     _room_y = 5;
+    _global_contrast = global_contrast;
 }
 
 RoomEngine::~RoomEngine()
@@ -39,7 +41,11 @@
         }
         move_player();
         render(lcd, gamepad);
-        lcd.setContrast(0.75 - (i * 0.005));
+        if (0.75 - (i * 0.005) > _global_contrast) {
+            lcd.setContrast(0.75 - (i * 0.005));
+        } else {
+            lcd.setContrast(_global_contrast);
+        }
     }
 }
 
@@ -64,8 +70,9 @@
         }
         move_player();
         render(lcd, gamepad);
-        lcd.setContrast(0.5 + (i * 0.005));
+        lcd.setContrast(_global_contrast + (i * 0.005));
     }
+    lcd.setContrast(0.75);
 }
 
 void RoomEngine::update_current_room()
@@ -255,9 +262,7 @@
 {
     for (int i = 0; i < bullets_max; i++) {
         if (player->valid_bullets[i]) {
-            if (player->bullets_array[i]->out_of_bounds_check(room->get_current_map_2d(), room->get_doorways())) {
-                player->valid_bullets[i] = false;
-                delete player->bullets_array[i];
+            if (player->update_bullets(room->get_current_map_2d(), room->get_doorways())) {
             } else {
                 for (int j = 0; j < MAX_ENEMIES; j++) {
                     if (room->valid_enemies[j] && (entity_collision(*player->bullets_array[i], *room->enemies[j]))) {
@@ -307,7 +312,6 @@
 {
     move_player();
     move_enemies();
-    move_bullets();
 }
 
 void RoomEngine::move_player()
@@ -326,22 +330,13 @@
     }
     // Entity Collision Repulsion
     for (int i = 0; i < MAX_ENEMIES; i++) {
-        if (room->valid_enemies[i]) {
+        if (room->valid_enemies[i] && !room->enemies[i]->is_damaged_by_collision()) {
             room->enemies[i]->position_add_x(entity_move_check_x(room->enemies[i], room->enemies, MAX_ENEMIES, i, room->valid_enemies));
             room->enemies[i]->position_add_y(entity_move_check_y(room->enemies[i], room->enemies, MAX_ENEMIES, i, room->valid_enemies));
         }
     }
 }
 
-void RoomEngine::move_bullets()
-{
-    for (int i = 0; i < bullets_max; i++) {
-        if (player->valid_bullets[i]) {
-            player->bullets_array[i]->move(player->get_bullet_speed(), 0, 0, room->get_doorways());
-        }
-    }
-}
-
 void RoomEngine::update_player_position(int side)
 {
     switch(side) {
@@ -421,24 +416,14 @@
 {   
     room->draw_room(lcd);
     //lcd.drawSprite(0,0,screen_height,screen_width,(int *)level_map[1]);
-    draw_player(lcd);
+    player->draw(lcd);
     draw_enemies(lcd);
-    draw_bullets(lcd);
     room->draw_room_overlay(lcd);
     if (_L) {
         draw_health(lcd);
     }
 }
 
-void RoomEngine::draw_player(N5110 &lcd)
-{
-    lcd.drawSpriteTransparent(player->get_pos_x()-player->get_offset_x(),
-                              player->get_pos_y()-player->get_offset_y(),
-                              player->get_sprite_height(),
-                              player->get_sprite_width(),
-                              player->get_frame());
-}
-
 void RoomEngine::draw_enemies(N5110 &lcd)
 {
     for (int i = 0; i < MAX_ENEMIES; i++) {
@@ -452,19 +437,6 @@
     }
 }
 
-void RoomEngine::draw_bullets(N5110 &lcd)
-{
-    for (int i = 0; i < bullets_max; i++) {
-        if (player->valid_bullets[i]) {
-            lcd.drawSpriteTransparent(player->bullets_array[i]->get_pos_x()-player->bullets_array[i]->get_offset_x(),
-                                      player->bullets_array[i]->get_pos_y()-player->bullets_array[i]->get_offset_y(),
-                                      player->bullets_array[i]->get_sprite_height(),
-                                      player->bullets_array[i]->get_sprite_width(),
-                                      player->bullets_array[i]->get_frame());
-        }
-    }
-}
-
 void RoomEngine::draw_health(N5110 &lcd)
 {
     for (int i = 0; i < player->get_hp(); i++){
--- a/RoomEngine/RoomEngine.h	Sat May 04 15:39:20 2019 +0000
+++ b/RoomEngine/RoomEngine.h	Sun May 05 18:04:43 2019 +0000
@@ -13,7 +13,7 @@
 class RoomEngine
 {
 public:
-    RoomEngine();
+    RoomEngine(float global_contrast);
     ~RoomEngine();
     void load(Player &current_player, Room *current_room);
     void entrance_scene(N5110 &lcd, Gamepad &gamepad);
@@ -42,6 +42,8 @@
     int _room_x;
     int _room_y;
     
+    float _global_contrast;
+    
     Room *room;
     Player *player;
     
@@ -63,16 +65,13 @@
     void move();
     void move_player();
     void move_enemies();
-    void move_bullets();
     void update_player_position(int side);
     
     void minimap_detection(N5110 &lcd, Gamepad &gamepad);
     void pause_detection(N5110 &lcd, Gamepad &gamepad);
     
     void draw(N5110 &lcd);
-    void draw_player(N5110 &lcd);
     void draw_enemies(N5110 &lcd);
-    void draw_bullets(N5110 &lcd);
     void draw_health(N5110 &lcd);
     
 };
--- a/main.cpp	Sat May 04 15:39:20 2019 +0000
+++ b/main.cpp	Sun May 05 18:04:43 2019 +0000
@@ -19,6 +19,7 @@
 #include "Headless.h"
 #include "Snake.h"
 #include "RoomEngine.h"
+#include <time.h> 
 
 #define INSIDE 4
 #define MAX_ROOMS_MAP_X 11
@@ -35,17 +36,100 @@
 int main()
 {
     // Initialize
+    float global_contrast = 0.5;
     lcd.init();
-    lcd.setContrast(0.5);
+    lcd.setContrast(global_contrast); 
     gamepad.init();
+    Room *rooms[MAX_ROOMS_MAP_Y][MAX_ROOMS_MAP_X];
     
     while(1) { // Gameloop
-        srand(2);
+        int title_count = 0;
+        int cursor_timer = 20;
+        int title_option = 0;
+        Player demo_player(5, 36);
+        while(1){  // Title Screen Loop
+            title_option = 0;
+            while(!gamepad.check_event(Gamepad::A_PRESSED)){ 
+                lcd.clear();
+                lcd.drawSprite(11, 4, 15, 44, (int *)title_name_0);
+                lcd.drawSpriteTransparent(19, 14, 17, 53, (int *)title_name_1);
+                lcd.drawCircle(79, 7, 10, FILL_BLACK);
+                lcd.drawCircle(81, 5, 8, FILL_WHITE);
+                lcd.drawSprite(56, 6, 11, 5, (int *)star_sprite[abs(((title_count/20) % 7) - 3)]);
+                lcd.drawSprite(12, 34, 8, 8, (int *)button_A_sprite);
+                lcd.drawSprite(22, 37, 3, 2, (int *)arrow_left_sprite);
+                lcd.drawSprite(59, 37, 3, 2, (int *)arrow_right_sprite);
+                lcd.drawSprite(69, 31, 12, 6, (int *)sprite_player[(title_count/40) % 4][(title_count/10) % 4]);
+                lcd.drawSprite(26, 35, 9, 32, (int *)title_options_sprite[title_option]);
+                lcd.refresh();
+                
+                if ((gamepad.get_direction() == 3) && (cursor_timer > 20)) {    // Detect Joystick going right
+                    cursor_timer = 0;
+                    if (title_option >= 3) {
+                        title_option = 0;
+                    } else {
+                        title_option++;
+                    }
+                } else if ((gamepad.get_direction() == 7) && (cursor_timer > 20)) { // Detect Joystick going left
+                    cursor_timer = 0;
+                    if (title_option <= 0) {
+                        title_option = 3;
+                    } else {
+                        title_option--;
+                    }
+                }
+                
+                cursor_timer++;
+                title_count++;
+                wait_ms(1000/40); // 1s/framerate
+            }
+            while(gamepad.check_event(Gamepad::A_PRESSED)){}
+            if(title_option == 0) {
+                break;
+            } else if (title_option == 1) {
+                while(!gamepad.check_event(Gamepad::A_PRESSED)) {
+                    global_contrast = gamepad.read_pot();
+                    lcd.setContrast(global_contrast);
+                    lcd.clear();
+                    lcd.printString("Set contrast", 0, 0);
+                    lcd.printString("using the", 0, 1);
+                    lcd.printString("potentiometer", 0, 2);
+                    demo_player.draw(lcd);
+                    lcd.refresh();
+                    demo_player.move(1, 0, (int *)level_map[0][0], (bool *)sprite_transparent_player);
+                    demo_player.buttons(false, true, false, false);
+                    demo_player.update_bullets((int *)level_map[0][0], (bool *)sprite_transparent_player);
+                    if(demo_player.get_pos_x() >= 84){
+                        demo_player.set_position(-6 ,demo_player.get_pos_y());
+                    }
+                    wait_ms(1000/40);
+                }
+                wait(0.05);
+                while(gamepad.check_event(Gamepad::A_PRESSED)) {
+                }
+            } else if (title_option == 2) {
+                lcd.clear();
+                lcd.setContrast(global_contrast);
+                lcd.printString("Made by:", 0, 0);
+                lcd.printString("Steven Mahasin", 0, 1);
+                lcd.printString("201192939", 0, 2);
+                lcd.refresh();
+                wait(0.05);
+                while(!gamepad.check_event(Gamepad::A_PRESSED)) {
+                }
+                wait(0.05);
+                while(gamepad.check_event(Gamepad::A_PRESSED)) {
+                }
+            } else if (title_option == 3) {
+                
+            }
+        }
+        demo_player.~Player();
+        srand(title_count);
         Player player(39, 27);
-        RoomEngine room_engine;
+        RoomEngine room_engine(global_contrast);
+        
         while(1) {  // Floor Loop 
-            Room *rooms[MAX_ROOMS_MAP_Y][MAX_ROOMS_MAP_X];
-            
             for (int i = 0; i < MAX_ROOMS_MAP_X; i++) {
                 for (int j = 0; j < MAX_ROOMS_MAP_Y; j++) {
                     rooms[j][i] = new Room(2);
@@ -72,20 +156,23 @@
                 room_engine.update_current_room();
             }
         }
-        gameover: {
-            lcd.clear();
-            lcd.setContrast(0.5);
-            lcd.printString("Game Over", 0, 0);
-            lcd.printString("Retry?", 0, 1);
-            lcd.refresh();
+        gameover : {
+            while(1){   // Game Over Screen Loop
+                lcd.clear();
+                lcd.setContrast(global_contrast);
+                lcd.printString("Game Over", 0, 0);
+                lcd.printString("Retry?", 0, 1);
+                lcd.refresh();
+                wait(0.05);
+                while(!gamepad.check_event(Gamepad::A_PRESSED)) {
+                }
+                wait(0.05);
+                while(gamepad.check_event(Gamepad::A_PRESSED)) {
+                }
+                break;
+            }
             room_engine.~RoomEngine();
             player.~Player();
-            wait(0.05);
-            while(!gamepad.check_event(Gamepad::A_PRESSED)) {
-            }
-            wait(0.05);
-            while(gamepad.check_event(Gamepad::A_PRESSED)) {
-            }
         }
     }
 }
\ No newline at end of file
--- a/sprites.h	Sat May 04 15:39:20 2019 +0000
+++ b/sprites.h	Sun May 05 18:04:43 2019 +0000
@@ -3,7 +3,132 @@
 const int screen_width = 84;
 const int screen_height = 48;
 
-const int pause_sprite[9][45] ={
+const int star_sprite[4][11][5] = {    // star_sprite[frame][Size_Y][Size_X]
+    {
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,1,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0}
+    },
+    {
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,1,1,1,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0}
+    },
+    {
+        {0,0,0,0,0},
+        {0,0,0,0,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,1,1,1,0},
+        {1,1,1,1,1},
+        {0,1,1,1,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,0,0,0,0},
+        {0,0,0,0,0}
+    },
+    {
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,1,1,1,0},
+        {0,1,1,1,0},
+        {1,1,1,1,1},
+        {0,1,1,1,0},
+        {0,1,1,1,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0},
+        {0,0,1,0,0}
+    }
+};
+
+const int title_options_sprite[4][9][32] = {
+    {
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,1,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    },
+    {
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,1,0,0,1,0,1,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0,1,1,1,0,0,1,1,0,0},
+        {0,0,1,0,0,1,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,0,0,0},
+        {0,0,1,0,0,1,0,1,0,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,0,1,1,0,0},
+        {0,0,0,1,1,0,0,1,1,0,0,0,1,1,0,0,1,0,0,1,1,1,0,1,0,1,0,1,1,0,0,0},
+        {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    },
+    {
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0},
+        {0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,0,0},
+        {0,0,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,0},
+        {0,0,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,0,0},
+        {0,0,0,0,0,1,1,1,0,1,0,0,0,1,1,1,0,1,1,1,0,0,1,0,0,0,1,1,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    },
+    {
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {1,0,0,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,1,0,0,1,1,0,0,0,1,0},
+        {1,1,1,1,0,0,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,1,0,1,0,1,0,1,0,1},
+        {1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,1,0,1,0,0,0,1,1,0},
+        {1,0,0,1,0,0,1,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,1,1,1},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    }
+};
+
+const int arrow_right_sprite[3][2] = {
+    {1,0},
+    {1,1},
+    {1,0}
+};
+const int arrow_left_sprite[3][2] = {
+    {0,1},
+    {1,1},
+    {0,1}
+};
+
+const int button_A_sprite[8][8] = {
+    {0,0,1,1,1,1,0,0},
+    {0,1,1,1,1,1,1,0},
+    {1,1,1,0,0,1,1,1},
+    {1,1,0,1,1,0,1,1},
+    {1,1,0,0,0,0,1,1},
+    {1,1,0,1,1,0,1,1},
+    {0,1,1,1,1,1,1,0},
+    {0,0,1,1,1,1,0,0}
+};
+
+
+const int pause_sprite[9][45] = {
     {0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,},
     {1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,},
     {0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,0,0,},
@@ -15,6 +140,44 @@
     {0,1,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,1,0,0,1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,},
 };
 
+const int title_name_0[15][44] = {
+    {0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,1,0,0,1,0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,0},
+    {0,0,0,1,1,1,0,0,1,1,0,1,1,1,1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0},
+    {0,0,1,1,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0},
+    {0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0},
+    {0,0,0,1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0},
+    {0,0,1,1,1,1,1,0,1,1,0,0,1,1,0,0,0,0,0,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,0,1,1,0,1,1,0,1,1,0},
+    {0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1,0,1,0,0,1,1,1,1,1,0,1,0,1,1,1,0,1,1,0,1,1,1},
+    {1,1,0,0,0,0,1,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,1,0,0,1,0,1,1,0,1,1,0,0,0,1,0,0,0,1,0,0,1,0},
+    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+};
+
+const int title_name_1[17][53] = {
+    {0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,0,0,1,0,0},
+    {0,0,0,1,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,1,0,0,0,1,1,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,0},
+    {0,0,1,1,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,1,1,0,1,1,0,0,1,1,0,1,1,0},
+    {0,1,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0},
+    {0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0},
+    {0,0,0,1,0,0,0,0,1,1,0,0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0},
+    {0,0,1,1,1,1,1,0,1,1,0,0,1,1,0,1,1,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,0,0,0,1,1,0,1,1,0,0,1,1,0,1,1,0},
+    {0,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,0,1,1,1,0,1,0,1,1,0,1,1,0,1,1,1,0,1,1,1},
+    {1,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1,1,0,1,0,1,0,0,1,1,0,0,0,1,1,0,0,0,0,1,0,0,0,1,0},
+    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+    {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
+};
+
 const int level_map[1][3][48][84] = { // map[map number][2d/3d/overlay][y][x]
     {
         {