Jonne Valola / PokittoLib Featured

Dependents:   YATTT sd_map_test cPong SnowDemo ... more

PokittoLib

Library for programming Pokitto hardware

How to Use

  1. Import this library to online compiler (see button "import" on the right hand side
  2. DO NOT import mbed-src anymore, a better version is now included inside PokittoLib
  3. Change My_settings.h according to your project
  4. Start coding!

Files at this revision

API Documentation at this revision

Comitter:
Pokitto
Date:
Tue Jan 30 10:41:47 2018 +0000
Parent:
30:796f9611d2ac
Child:
32:6d5a63b6d5b6
Commit message:
Sound output improvements added: louder, clearer, faster!

Changed in this revision

POKITTO_CORE/GBcompatibility.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/Localization.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/Macros_LCD.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoBacklight.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoBacklight.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoBattery.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoBattery.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoButtons.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoButtons.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoConsole.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoConsole.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoCore.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoCore.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoDisk.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoDisk.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoDisplay.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoDisplay.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoFakeavr.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoFonts.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoGlobs.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoItoa.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoItoa.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoLogos.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoLogos.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoPalette.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoPalettes.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoSound.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoSound.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/PokittoTimer.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_CORE/binary.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWButtons.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWButtons.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWLCD.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWLCD.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWSound.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/HWSound.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/PokittoClock.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/PokittoEEPROM.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/PokittoHW.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/Pokitto_extport.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/Pokitto_extport.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/SoftwareI2C.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/SoftwareI2C.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/iap.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_HW/iap.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_envfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_helpers.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_mixfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_osc.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_oscfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_song.h Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_songfuncs.cpp Show annotated file Show diff for this revision Revisions of this file
POKITTO_LIBS/Synth/Synth_wavefuncs.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/GBcompatibility.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,184 @@
+#ifndef GBCOMPATIBILITY_H
+#define GBCOMPATIBILITY_H
+
+/*
+ * (C) Copyright 2014 Aurélien Rodot. All rights reserved.
+ *
+ * This file is part of the Gamebuino Library (http://gamebuino.com)
+ *
+ * The Gamebuino Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+
+
+#ifndef SETTINGS_C
+#define	SETTINGS_C
+
+#include "binary.h"
+
+#define _BV(bit) (1 << (bit)) //jonne
+
+#define NOROT 0
+#define ROTCCW 1
+#define ROT180 2
+#define ROTCW 3
+
+//colors
+#define WHITE 0
+#define BLACK 1
+#define GRAY 2
+#define INVERT 255
+
+//for extended bitmap function :
+#define NOROT 0
+#define ROTCCW 1
+#define ROT180 2
+#define ROTCW 3
+#define NOFLIP 0
+#define FLIPH 1
+#define FLIPV 2
+#define FLIPVH 3
+
+
+
+
+//SETTINGS YOU CAN EDIT
+
+#define NUM_CHANNELS 1 //number of sound channels, between 0 and 4
+#define DISPLAY_ROT NOROT //set to NOROT, ROTCCW, ROT180 or ROTCW. Can be used to play in portrait mode.
+#define ENABLE_GUI 1 //enable menu, keyboard, pop-up, volume adjust functions
+#define ENABLE_BITMAPS 1 //will replace bitmaps with rectangles if disabled
+#define ENABLE_GRAYSCALE 1 //allows the use of the GRAY color
+#define EXTENDED_NOTE_RANGE 0 //allows the use of notes above A 5... please avoid that they sound really bad
+
+//not really useful
+#define ENABLE_BATTERY 1 //disable battery monitoring
+#define ENABLE_BACKLIGHT 1 //disable automatic back-light
+
+//IT'S STRONGLY ADVISED TO LEAVE THE FOLLOWING SETTINGS ALONE
+
+//defaults values of settings which can be adjusted on each Gamebuino using settings.hex
+#define SCR_CONTRAST 60
+#define START_MENU_TIMER 255 //40 = 40 frames (2sec) before start menu is skipped, 0 = no start menu, 255 = start menu until you press A
+
+//addresses of settings stored in the program memory
+#define SETTINGS_PAGE ((const char *)(0x7800-128))
+#define SETTINGS_TOKEN 			0xC001
+#define OFFSET_CURRENTGAME		2
+#define OFFSET_USERNAME			11
+#define USERNAME_LENGTH			10
+#define OFFSET_CONTRAST			22
+#define OFFSET_BACKLIGHT_MIN	23
+#define OFFSET_BACKLIGHT_MAX	24
+#define OFFSET_LIGHT_MIN		25
+#define OFFSET_LIGHT_MAX		27
+#define OFFSET_VOLUME_MAX		29
+#define OFFSET_VOLUME_DEFAULT	30
+#define OFFSET_START_MENU_TIMER	31
+#define OFFSET_BATTERY_CRITIC	32
+#define OFFSET_BATTERY_LOW		34
+#define OFFSET_BATTERY_MED		36
+#define OFFSET_BATTERY_FULL		38
+
+//GUI
+#define KEYBOARD_W 16
+#define KEYBOARD_H 8
+
+//sound
+#define VOLUME_CHANNEL_MAX 255/NUM_CHANNELS/7/9 //7=instrument volume 9=note volume
+
+//battery voltage monitor
+#define BAT_PIN 6 //was A6
+#define NUM_LVL 4
+#define BAT_LVL_CRITIC  3500
+#define BAT_LVL_LOW		3550
+#define BAT_LVL_MED		3700
+#define BAT_LVL_FULL	3900
+
+//SD card
+#define SD_CS 10
+
+//screens back light
+#define BACKLIGHT_PIN 5
+//auto back-light levels
+#define BACKLIGHT_MIN 0
+#define BACKLIGHT_MAX 255
+
+//ambient light sensor
+#define AMBIENTLIGHT_PIN A7
+//auto back-light levels
+#define AMBIENTLIGHT_MIN 800 //800
+#define AMBIENTLIGHT_MAX 980 //1000
+#define AMBIENTLIGHT_SMOOTHING 16
+
+//number of buttons
+#define NUM_BTN         7
+//buttons ID
+#if DISPLAY_ROT == 0
+	#define BTN_UP      1
+	#define BTN_RIGHT   2
+	#define BTN_DOWN    3
+	#define BTN_LEFT    0
+#elif DISPLAY_ROT == ROTCCW
+	#define BTN_UP      2
+	#define BTN_RIGHT   3
+	#define BTN_DOWN    0
+	#define BTN_LEFT    1
+#elif DISPLAY_ROT == ROT180
+	#define BTN_UP      3
+	#define BTN_RIGHT   0
+	#define BTN_DOWN    1
+	#define BTN_LEFT    2
+#elif DISPLAY_ROT == ROTCW
+	#define BTN_UP      0
+	#define BTN_RIGHT   1
+	#define BTN_DOWN    2
+	#define BTN_LEFT    3
+#endif
+#define BTN_A           4
+#define BTN_B           5
+#define BTN_C           6
+
+#define BTN_LEFT_PIN 0
+#define BTN_UP_PIN 1
+#define BTN_RIGHT_PIN 2
+#define BTN_DOWN_PIN 3
+#define BTN_A_PIN 4
+#define BTN_B_PIN 5
+#define BTN_C_PIN 6
+
+
+
+#endif /*  */
+
+const uint16_t startupSound[] = {0x0005,0x3089,0x208,0x238,0x7849,0x1468,0x0000};
+
+const uint8_t gamebuinoLogo[]  =
+{
+	84,10, //width and height
+	B00000011, B11100001, B10000001, B10000110, B01111111, B00111110, B00011000, B01101101, B10000011, B00001111, B00001111,
+	B00001110, B00000001, B10000011, B10000110, B01100000, B00110011, B00011000, B01101101, B11000011, B00011001, B10001111,
+	B00011000, B00000011, B11000011, B10001110, B01100000, B00110011, B00011000, B01101101, B11100011, B00110000, B11001111,
+	B00011000, B00000011, B11000011, B10011110, B01100000, B00110110, B00110000, B11001101, B11100011, B01100000, B11001111,
+	B00110000, B00000110, B11000111, B10011110, B01111110, B00111110, B00110000, B11001101, B10110011, B01100000, B11001111,
+	B00110000, B00001100, B11000110, B11110110, B01100000, B00110011, B00110000, B11011001, B10110110, B01100000, B11001111,
+	B00110011, B11001111, B11001100, B11110110, B01100000, B01100001, B10110000, B11011011, B00011110, B01100000, B11001111,
+	B00110000, B11011000, B01101100, B11100110, B11000000, B01100001, B10110000, B11011011, B00011110, B01100001, B10001111,
+	B00011001, B10011000, B01101100, B11000110, B11000000, B01100011, B10110001, B10011011, B00001110, B00110011, B00001111,
+	B00001111, B10110000, B01111000, B11000110, B11111111, B01111110, B00011111, B00011011, B00000110, B00011110, B00001111,
+};
+
+#endif // GBCOMPATIBILITY_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/Localization.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,48 @@
+/**************************************************************************/
+/*!
+    @file     Localization.h
+    @author   Hannu Viitala
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2017, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef LOCALIZATION_H
+#define LOCALIZATION_H
+
+//** Localized strings of the Pokitto SW  */
+
+// Texts
+#define STR_OK "OK"
+#define STR_CANCEL "CANCEL"
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/Macros_LCD.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,105 @@
+/**************************************************************************/
+/*!
+    @file     Macros_LCD.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2015, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef LCDMACROS_H
+#define LCDMACROS_H
+
+/**************************************************************************/
+/**                          PINS AND PORTS                              **/
+/**************************************************************************/
+
+#if POK_BOARDREV == 1
+/** 2-layer board version 1.3 **/
+ #define LCD_CD_PORT           0
+ #define LCD_CD_PIN            2
+ #define LCD_WR_PORT           1
+ #define LCD_WR_PIN            23
+ #define LCD_RD_PORT           1
+ #define LCD_RD_PIN            24
+ #define LCD_RES_PORT          1
+ #define LCD_RES_PIN           28
+#else
+/** 4-layer board version 2.1 **/
+ #define LCD_CD_PORT           0
+ #define LCD_CD_PIN            2
+ #define LCD_WR_PORT           1
+ #define LCD_WR_PIN            12
+ #define LCD_RD_PORT           1
+ #define LCD_RD_PIN            24
+ #define LCD_RES_PORT          1
+ #define LCD_RES_PIN           0
+#endif
+
+/**************************************************************************/
+/**                          LCD CONTROL MACROS                          **/
+/**************************************************************************/
+
+#define CLR_RESET LPC_GPIO_PORT->CLR[LCD_RES_PORT] = 1 << LCD_RES_PIN; //RST = (0); // Clear pin
+#define SET_RESET LPC_GPIO_PORT->SET[LCD_RES_PORT] = 1 << LCD_RES_PIN; // RST = (1); // Set pin
+
+#define CLR_CD  LPC_GPIO_PORT->CLR[LCD_CD_PORT] = 1 << LCD_CD_PIN; // RS = (0); // Clear pin
+#define SET_CD LPC_GPIO_PORT->SET[LCD_CD_PORT] = 1 << LCD_CD_PIN; // RS = (1); // Set pin
+
+#define CLR_WR { LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN; __asm("nop");}//WR = (0); // Clear pin
+#define SET_WR LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN; //WR = (1); // Set pin
+
+#define CLR_RD LPC_GPIO_PORT->CLR[LCD_RD_PORT] = 1 << LCD_RD_PIN; //RD = (0); // Clear pin
+#define SET_RD LPC_GPIO_PORT->SET[LCD_RD_PORT] = 1 << LCD_RD_PIN; //RD = (1); // Set pin
+
+#define SET_CS  //CS tied to ground
+#define CLR_CS
+
+#define CLR_CS_CD_SET_RD_WR {CLR_CD; SET_RD; SET_WR;}
+#define CLR_CS_SET_CD_RD_WR {SET_CD; SET_RD; SET_WR;}
+#define SET_CD_RD_WR {SET_CD; SET_RD; SET_WR;}
+#define SET_WR_CS SET_WR;
+
+#define SET_MASK_P2 LPC_GPIO_PORT->MASK[2] = ~(0x7FFF8); //mask P2_3 ...P2_18
+#define CLR_MASK_P2 LPC_GPIO_PORT->MASK[2] = 0; // all on
+
+/**************************************************************************/
+/**                          OTHER MACROS                                **/
+/**************************************************************************/
+
+#define write_command w_cmd_16
+#define write_data w_data_16
+
+#define AB_JUMP 1024 // jump one 1-bit Arduboy screen forward to get next color bit
+#define GB_JUMP 504 // jump one 1-bit Gamebuino screen forward to get next color bit
+
+#endif // LCDMACROS_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoBacklight.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,59 @@
+/**************************************************************************/
+/*!
+    @file     PokittoBacklight.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoBacklight.h"
+
+using namespace Pokitto;
+
+bool Backlight::automatic;
+uint16_t Backlight::ambientLight;
+uint8_t Backlight::backlightValue;
+uint8_t Backlight::backlightMin, Backlight::backlightMax;
+uint16_t Backlight::ambientLightMin, Backlight::ambientLightMax;
+
+void Backlight::begin() {
+
+}
+
+void Backlight::set(uint8_t value) {
+
+}
+
+void Backlight::update() {
+
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoBacklight.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,60 @@
+/**************************************************************************/
+/*!
+    @file     PokittoBacklight.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POKITTO_BACKLIGHT
+#define POKITTO_BACKLIGHT
+
+#include <stdint.h>
+
+namespace Pokitto {
+/** This class controls the backlight of the Pokitto LCD display
+ *
+ */
+class Backlight {
+public:
+    static void begin();
+    static void set(uint8_t value);
+    static void update();
+    static bool automatic;
+    static uint16_t ambientLight;
+    static uint8_t backlightValue;
+	static uint8_t backlightMin, backlightMax;
+	static uint16_t ambientLightMin, ambientLightMax;
+};
+}
+#endif // POKITTO_BACKLIGHT
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoBattery.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,56 @@
+/**************************************************************************/
+/*!
+    @file     PokittoBattery.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoBattery.h"
+
+using namespace Pokitto;
+
+bool Battery::show;
+uint8_t  Battery::level;
+uint16_t Battery::voltage;
+uint16_t Battery::thresholds[NUM_LVL];
+uint8_t  Battery::nextUpdate;
+
+void Battery::begin() {
+
+}
+
+void Battery::update() {
+    //ToDo - make a real function
+    level=0xFF; //full battery all the time
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoBattery.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,63 @@
+/**************************************************************************/
+/*!
+    @file     PokittoBattery.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+#ifndef POKITTOBATTERY_H
+#define POKITTOBATTERY_H
+
+#include <stdint.h>
+#include "Pokitto_settings.h"
+#include "GBcompatibility.h"
+#include "PokittoGlobs.h"
+
+
+namespace Pokitto {
+
+class Battery {
+public:
+    static void begin();
+    static void update();
+	static bool show;
+    static uint8_t  level;
+    static uint16_t voltage;
+    static uint16_t thresholds[NUM_LVL];
+    static uint8_t  nextUpdate;
+};
+}
+
+#endif //POKITTOBATTERY_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoButtons.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,263 @@
+/**************************************************************************/
+/*!
+    @file     PokittoButtons.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoCore.h"
+
+using namespace Pokitto;
+
+uint8_t Buttons::pins[NUM_BTN];
+uint8_t Buttons::states[NUM_BTN];
+uint8_t Buttons::buttons_state;
+uint8_t Buttons::buttons_held;
+uint8_t Buttons::buttons_released; // from LSB up,down,left,right,a,b,c
+uint16_t Buttons::cHWLongPress = CHWLONGPRESSTIMEOUT;
+
+
+void Buttons::begin() {
+    #ifndef POK_SIM
+    Pokitto::initButtons();
+    #endif // POK_SIM
+}
+
+void Buttons::update() {
+    #if POK_USE_CONSOLE
+    if (console.conscounter) return;
+    #endif // POK_USE_CONSOLE
+    #ifndef POK_SIM
+        /** HARDWARE CODE **/
+    for (uint8_t thisButton = 0; thisButton < NUM_BTN; thisButton++) {
+        if (Pokitto::heldStates[thisButton]) { //if button pressed
+            states[thisButton]++; //increase button hold time
+        } else {
+            if (states[thisButton] == 0)//button idle
+                continue;
+            if (states[thisButton] == 0xFF)//if previously released
+                states[thisButton] = 0; //set to idle
+            else
+                states[thisButton] = 0xFF; //button just released
+        }
+        }
+    #else
+        /** POK_SIM code **/
+        simulator.pollButtons();
+        for (uint8_t thisButton = 0; thisButton < NUM_BTN; thisButton++) {
+        uint8_t temp=0;
+        switch (thisButton) {
+        case 0:
+            temp = simulator.leftHeld(); break;
+        case 1:
+            temp = simulator.upHeld(); break;
+        case 2:
+            temp = simulator.rightHeld(); break;
+        case 3:
+            temp = simulator.downHeld(); break;
+        case 4:
+            temp = simulator.aHeld(); break;
+        case 5:
+            temp = simulator.bHeld(); break;
+        case 6:
+            temp = simulator.cHeld(); break;
+        default:
+            break;
+        }
+
+        if (temp == HIGH) { //if button pressed
+            states[thisButton]++; //increase button hold time
+        } else {
+            if (states[thisButton] == 0)//button idle
+                continue;
+            if (states[thisButton] == 0xFF)//if previously released
+                states[thisButton] = 0; //set to idle
+            else
+                states[thisButton] = 0xFF; //button just released
+        }
+        }
+
+        #endif // POK_SIM
+}
+
+/*
+ * Returns true when 'button' is pressed.
+ * The button has to be released for it to be triggered again.
+ */
+bool Buttons::pressed(uint8_t button) {
+    if (states[button] == 1)
+        return true;
+    else
+        return false;
+}
+
+/*
+ * return true if 'button' is released
+ */
+bool Buttons::released(uint8_t button) {
+    if (states[button] == 0xFF)
+        return true;
+    else
+        return false;
+}
+
+/**
+ * returns true ONCE when 'button' is held for 'time' frames
+ * @param button The button's ID
+ * @param time How much frames button must be held, between 1 and 254.
+ * @return true when 'button' is held for 'time' frames
+ */
+bool Buttons::held(uint8_t button, uint8_t time){
+    if(states[button] == (time+1))
+        return true;
+    else
+        return false;
+}
+
+/**
+ * returns true every 'period' frames when 'button' is held
+ * @param button The button's ID
+ * @param period How much frames button must be held, between 1 and 254.
+ * @return true if the button is held for the given time
+ */
+bool Buttons::repeat(uint8_t button, uint8_t period) {
+    if (period <= 1) {
+        if ((states[button] != 0xFF) && (states[button]))
+            return true;
+    } else {
+        if ((states[button] != 0xFF) && ((states[button] % period) == 1))
+            return true;
+    }
+    return false;
+}
+
+/**
+ *
+ * @param button The button's ID
+ * @return The number of frames during which the button has been held.
+ */
+uint8_t Buttons::timeHeld(uint8_t button){
+    if(states[button] != 0xFF)
+        return states[button];
+    else
+        return 0;
+
+}
+
+void Buttons::pollButtons() {
+    #ifdef POK_SIM
+    simulator.pollButtons();
+    #else
+    uint8_t buttons_state_old = buttons_state;
+    buttons_state = 0; // clear all
+    if (upBtn()) buttons_state |= (1<<UPBIT);
+    if (downBtn()) buttons_state |= (1<<DOWNBIT);
+    if (leftBtn()) buttons_state |= (1<<LEFTBIT);
+    if (rightBtn()) buttons_state |= (1<<RIGHTBIT);
+    if (aBtn()) buttons_state |= (1<<ABIT);
+    if (bBtn()) buttons_state |= (1<<BBIT);
+    if (cBtn()) buttons_state |= (1<<CBIT);
+    buttons_held = buttons_state & buttons_state_old; // only if both 1, end result is 1
+    buttons_released = ~buttons_state & buttons_state_old; // if now zero, then 1 AND previous 1 = 1
+    #endif // POK_SIM
+}
+
+uint8_t Buttons::aBtn() {
+    #ifdef POK_SIM
+    return simulator.aBtn();
+    #else
+    return Pokitto::heldStates[BTN_A];
+    #endif // POK_SIM
+}
+
+
+uint8_t Buttons::bBtn() {
+    #ifdef POK_SIM
+    return simulator.bBtn();
+    #else
+    return Pokitto::heldStates[BTN_B];
+    #endif // POK_SIM
+}
+
+uint8_t Buttons::cBtn() {
+    uint8_t c;
+    #ifdef POK_SIM
+    c = simulator.cBtn();
+    #else
+    c = Pokitto::heldStates[BTN_C];
+    #endif // POK_SIM
+    return c;
+}
+
+uint8_t Buttons::leftBtn() {
+    #ifdef POK_SIM
+    return simulator.leftBtn();
+    #else
+    return Pokitto::heldStates[BTN_LEFT];
+    #endif // POK_SIM
+}
+
+uint8_t Buttons::rightBtn() {
+    #ifdef POK_SIM
+    return simulator.rightBtn();
+    #else
+    return Pokitto::heldStates[BTN_RIGHT];
+    #endif // POK_SIM
+}
+
+uint8_t Buttons::upBtn() {
+    #ifdef POK_SIM
+    return simulator.upBtn();
+    #else
+    return Pokitto::heldStates[BTN_UP];
+    #endif // POK_SIM
+}
+
+uint8_t Buttons::downBtn() {
+    #ifdef POK_SIM
+    return simulator.downBtn();
+    #else
+    return Pokitto::heldStates[BTN_DOWN];
+    #endif // POK_SIM
+}
+
+
+
+
+
+
+
+
+//** EOF **//
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoButtons.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/*!
+    @file     PokittoButtons.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+#ifndef POKITTOBUTTONS_H
+#define POKITTOBUTTONS_H
+
+#include <stdint.h>
+#include "Pokitto_settings.h"
+#include "GBcompatibility.h"
+#include "PokittoGlobs.h"
+
+#ifndef POK_SIM
+    #include "HWButtons.h"
+    #define CHWLONGPRESSTIMEOUT 100
+#else
+    #include "PokittoSimulator.h"
+    #define CHWLONGPRESSTIMEOUT 1000
+#endif // POK_SIM
+
+
+namespace Pokitto {
+
+class Buttons {
+public:
+    // Original functions
+    static uint8_t buttons_state, buttons_held, buttons_released;
+    static void initButtons();
+    static void pollButtons();
+    static uint8_t leftBtn();
+    static uint8_t rightBtn();
+    static uint8_t upBtn();
+    static uint8_t downBtn();
+    static uint8_t aBtn();
+    static uint8_t bBtn();
+    static uint8_t cBtn();
+    static uint8_t leftHeld();
+    static uint8_t rightHeld();
+    static uint8_t upHeld();
+    static uint8_t downHeld();
+    static uint8_t aHeld();
+    static uint8_t bHeld();
+    static uint8_t cHeld();
+
+    static uint8_t leftReleased();
+    static uint8_t rightReleased();
+    static uint8_t upReleased();
+    static uint8_t downReleased();
+    static uint8_t aReleased();
+    static uint8_t bReleased();
+    static uint8_t cReleased();
+
+    // GB compatibility functions
+	static void begin();
+    static void update();
+    static bool pressed(uint8_t button);
+    static bool released(uint8_t button);
+    static bool held(uint8_t button, uint8_t time);
+    static bool repeat(uint8_t button, uint8_t period);
+    static uint8_t timeHeld(uint8_t button);
+    static uint8_t pins[NUM_BTN];
+    static uint8_t states[NUM_BTN];
+    static uint8_t heldStates[NUM_BTN]; // additional, not GB based
+private:
+    static uint16_t cHWLongPress; //forced hardware detection of C long press
+};
+
+}
+
+#endif // POKITTOBUTTONS_H
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoConsole.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,314 @@
+/**************************************************************************/
+/*!
+    @file     PokittoConsole.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoGlobs.h"
+#include "PokittoConsole.h"
+#include "PokittoFonts.h"
+#include "PokittoDisplay.h"
+
+Pokitto::Console pConsole;
+
+using namespace Pokitto;
+
+consmsg Console::msgbuf[CONSOLEBUFSIZE];
+uint8_t Console::conslast;
+uint8_t Console::consfirst;
+uint8_t Console::conspointer;
+uint16_t Console::conscounter;
+uint16_t Console::color;
+Display* Console::_display;
+uint8_t Console::mode;
+uint8_t Console::visible;
+unsigned char* Console::font;
+
+Console::Console() {
+    conslast=consfirst=conspointer=conscounter=0;
+    color=0xFFFF;
+    font=(unsigned char*)fontMini;
+    #if POK_CONSOLE_VISIBLE_AT_STARTUP > 0
+        mode=CONS_OVERLAY|CONS_VISIBLE;
+    #else
+        mode=CONS_OVERLAY;//|CONS_VISIBLE;
+    #endif
+}
+
+void Console::Toggle() {
+    if (!conscounter) // conscounter is a debounce feature for console toggle
+    {
+        mode ^= CONS_VISIBLE;
+        conscounter = CONS_TIMEOUT;
+    }
+}
+
+
+void Console::AddMessage(uint8_t source, uint8_t msgtype) {
+    AddMessage(source,msgtype, V_NONE,0);
+}
+
+
+void Console::AddMessage(uint8_t type, char* stringptr) {
+    AddMessage(MSOURCE_USER,type,V_STRING, (uint32_t) stringptr);
+}
+
+
+void Console::AddMessage(uint8_t msgtype, uint8_t valtype, uint32_t val) {
+    AddMessage(MSOURCE_USER,msgtype,valtype,val);
+}
+
+void Console::AddMessage(uint8_t source, uint8_t msgtype, uint8_t valtype, uint32_t val) {
+    consmsg c;
+    c.msgsource = source;
+    c.msgtype = msgtype;
+    c.valtype = valtype;
+    c.val = val;
+    msgbuf[conslast] = c;
+    conslast++;
+    if (conslast==CONSOLEBUFSIZE) conslast = 0; // wrap around the buffer
+    consfirst = conslast + 1;
+    if (consfirst == CONSOLEBUFSIZE) consfirst = 0;
+}
+
+void Console::Last() {
+    conspointer = conslast;
+}
+
+void Console::RemoveLast() {
+    Last();
+    Previous();
+    msgbuf[conspointer].msgsource = MSOURCE_USER;
+    msgbuf[conspointer].msgtype = MSG_OK;
+    msgbuf[conspointer].val = 0;
+    msgbuf[conspointer].valtype = 0;
+    conslast = conspointer;
+}
+
+void Console::First() {
+    consmsg c;
+    uint16_t outofbounds=0;
+    conspointer = consfirst;
+    c=GetMessage();
+    while (!c.msgsource) {
+        Next();
+        c=GetMessage();
+        outofbounds++;
+        if (outofbounds==CONSOLEBUFSIZE) {
+            conspointer = consfirst;
+            break;
+        }
+    }
+}
+
+void Console::Previous() {
+    if (conspointer==0) conspointer = CONSOLEBUFSIZE-1;
+    else conspointer--;
+}
+
+void Console::Next() {
+    if (conspointer==CONSOLEBUFSIZE-1) conspointer = 0;
+    else conspointer++;
+}
+
+consmsg Console::GetMessage() {
+    return msgbuf[conspointer];
+}
+
+void Console::PrintMessage() {
+    consmsg c = msgbuf[conspointer];
+    switch (c.msgsource) {
+    case MSOURCE_APP:
+        _display->print("App:");break;
+    case MSOURCE_BATT:
+        _display->print("Batt:");break;
+    case MSOURCE_BTNA:
+        _display->print("A:");break;
+    case MSOURCE_BTNB:
+        _display->print("B:");break;
+    case MSOURCE_BTNC:
+        _display->print("C:");break;
+    case MSOURCE_BTNU:
+        _display->print("Up:");break;
+    case MSOURCE_BTND:
+        _display->print("Down:");break;
+    case MSOURCE_BTNL:
+        _display->print("Left:");break;
+    case MSOURCE_BTNR:
+        _display->print("Right:");break;
+    case MSOURCE_LCD:
+        _display->print("LCD:");break;
+    case MSOURCE_SD:
+        _display->print("SD:");break;
+    case MSOURCE_SOUND:
+        _display->print("Sound:");break;
+    case MSOURCE_TIMER:
+        _display->print("Timer:");break;
+    case MSOURCE_USER:
+        _display->print("User:");break;
+    case MSOURCE_COLLISION:
+        _display->print("Hit:");break;
+    default:
+        return;
+    }
+
+    switch (c.msgtype) {
+    case MSG_OK:
+        _display->print("OK ");break;
+    case MSG_INIT_OK:
+        _display->print("INIT OK ");break;
+    case MSG_INIT_FAIL:
+        _display->print("INIT FAIL ");break;
+    case MSG_WARNING:
+        _display->print("WARNING ");break;
+    case MSG_FATAL:
+        _display->print("FATAL ");break;
+    case MSG_GFX_MODE_CHANGE:
+        _display->print("MODE ");break;
+    case MSG_GFX_MODE_INVALID:
+        _display->print("INVALID!");break;
+    case MSG_NOT_ENOUGH_MEM:
+       _display->print("NOT ENOUGH MEM ");break;
+    case MSG_UP:
+        _display->print("KEYUP");break;
+    case MSG_DOWN:
+        _display->print("KEYDOWN");break;
+    case MSG_BREAK:
+        _display->print("BREAK ");break;
+    case MSG_YESNO:
+        _display->print("YES(A)/NO(B)");break;
+    case MSG_YES:
+        _display->print("YES");break;
+    case MSG_NO:
+        _display->print("NO");break;
+    case MSG_OBJECT:
+        _display->print("OBJ1: ");break;
+    case MSG_OBJECT2:
+        _display->print("OBJ2: ");break;
+    default:
+        _display->print(" ");
+    }
+
+    switch (c.valtype) {
+    case V_NONE:
+        _display->println();break;
+    case V_UINT8:
+        _display->println((uint16_t)c.val);break;
+    case V_INT8:
+        _display->println((int16_t)c.val);break;
+    case V_UINT16:
+        _display->println((uint16_t)c.val);break;
+    case V_INT16:
+        _display->println((int16_t)c.val);break;
+    case V_UINT32:
+        _display->println((uint32_t)c.val);break;
+    case V_INT32:
+        _display->println((int32_t)c.val);break;
+    case V_FLOAT:
+        _display->println((float)c.val);break;
+    case V_STRING:
+        _display->println((char*)c.val);break;
+    default:
+        _display->println();
+    }
+
+    if (c.msgtype == MSG_BREAK || c.msgtype == MSG_YESNO) {
+        #ifndef POK_SIM
+        __disable_irq();    // Disable Interrupts
+        #else
+        pauseAudio(1);
+        visible = false; // avoid loop in loop inside refreshDisplay
+        simulator.wait_ms(300);
+        #endif
+        int rval=0;
+        while(!rval) {
+                _buttons->pollButtons();
+                #ifdef POK_SIM
+                    simulator.refreshDisplay();
+                #endif // POK_SIM
+                if (_buttons->aBtn()) rval = 1;
+                if (_buttons->bBtn()) rval = -1;
+                }
+        /* now remove this message to prevent it from rerunning */
+        if (c.msgtype == MSG_YESNO) {
+            int8_t* v;
+            v = (int8_t*) c.val; //c.val is a pointer to the memory location that receives answer
+            *v = rval; // return value through pointer
+            msgbuf[conspointer].msgsource = MSOURCE_USER;
+            if (rval==1) msgbuf[conspointer].msgtype = MSG_YES;
+            else msgbuf[conspointer].msgtype = MSG_NO;
+        } else msgbuf[conspointer].msgsource = MSOURCE_NULL;
+
+        #ifndef POK_SIM
+        __enable_irq();     // Enable Interrupts
+        #else
+        pauseAudio(0);
+        visible = true;
+        #endif
+    }
+}
+
+void Console::Draw() {
+    unsigned char* oldfont;
+    int16_t oldx,oldy;
+    uint16_t oldcolor;
+    uint8_t oldsize;
+    bool oldenable;
+    oldfont = (unsigned char*) _display->font;
+    oldx = _display->cursorX;
+    oldy = _display->cursorY;
+    oldcolor = _display->directcolor;
+    oldsize = _display->fontSize;
+    if (!(mode & CONS_OVERLAY)) _display->clearLCD();
+    _display->setFont(font5x7);
+    _display->fontSize=1;
+    _display->setCursor(0,0);
+    _display->directcolor=color;
+    First();
+    while(conspointer!=conslast) {
+        PrintMessage();
+        Next();
+        if (GetMessage().msgsource==MSOURCE_NULL) break;
+    }
+    _display->font = oldfont;
+    _display->fontSize = oldsize;
+    _display->cursorX = oldx;
+    _display->cursorY = oldy;
+    _display->directcolor = oldcolor;
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoConsole.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,161 @@
+/**************************************************************************/
+/*!
+    @file     PokittoConsole.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POKITTO_CONSOLE_H
+#define POKITTO_CONSOLE_H
+
+#include "Pokitto_settings.h"
+#include "PokittoButtons.h"
+#include <stdint.h>
+
+struct consmsg {
+  uint32_t val;
+  uint8_t valtype;
+  uint8_t msgsource;
+  uint8_t msgtype;
+};
+
+/** VAL TYPES **/
+#define V_UINT8     0
+#define V_INT8      1
+#define V_UINT16    2
+#define V_INT16     3
+#define V_UINT32    4
+#define V_INT32     5
+#define V_FLOAT     6
+#define V_STRING    7
+#define V_NONE      8
+
+/** MESSAGE TYPE **/
+#define MSG_NULL        0
+#define MSG_OK          1
+#define MSG_WARNING     2
+#define MSG_FATAL       255
+#define MSG_INIT_OK     3
+#define MSG_INIT_FAIL   4
+#define MSG_NOT_ENOUGH_MEM  5
+#define MSG_GFX_MODE_CHANGE 6
+#define MSG_GFX_MODE_INVALID 7
+#define MSG_UP          8
+#define MSG_DOWN        9
+#define MSG_PRINT       10
+#define MSG_BREAK       11
+#define MSG_YESNO       12
+#define MSG_YES         13
+#define MSG_NO          14
+#define MSG_OBJECT      15
+#define MSG_OBJECT2     16
+
+/** MESSAGE SOURCE **/
+#define MSOURCE_NULL    0
+#define MSOURCE_SD      1
+#define MSOURCE_LCD     2
+#define MSOURCE_SOUND   3
+#define MSOURCE_TIMER   4
+#define MSOURCE_BTNA    5
+#define MSOURCE_BTNB    6
+#define MSOURCE_BTNC    7
+#define MSOURCE_BTNU    8
+#define MSOURCE_BTND    9
+#define MSOURCE_BTNL    10
+#define MSOURCE_BTNR    11
+#define MSOURCE_BATT    12
+#define MSOURCE_APP     13
+#define MSOURCE_USER    14
+#define MSOURCE_COLLISION 15
+
+/** CONSOLE MODES **/
+#define CONS_OVERLAY    0x1
+#define CONS_PAUSE      0x2
+#define CONS_STEP       0x4
+#define CONS_VISIBLE    0x8
+
+
+/** CONSOLE DEBOUNCE **/
+#define CONS_TIMEOUT   20
+extern uint16_t conscounter;
+
+
+
+namespace Pokitto {
+
+class Display;
+
+class Console {
+public:
+    /** Console class constructor */
+    Console();
+
+    static uint8_t mode;
+    static uint8_t visible;
+    static unsigned char* font;
+    static void Toggle();
+    static void AddMessage(uint8_t, uint8_t, uint8_t, uint32_t);
+    static void AddMessage(uint8_t, uint8_t);
+    static void AddMessage(uint8_t, char*);
+    static void AddMessage(uint8_t, uint8_t, uint32_t);
+    static void Last();
+    static void First();
+    static void RemoveLast();
+    static void Previous();
+    static void Next();
+    static consmsg GetMessage();
+    static void PrintMessage();
+    static void Purge();
+    static void Draw(); // pokConsole
+
+private:
+    /** Message buffer */
+    static consmsg msgbuf[CONSOLEBUFSIZE];
+    static uint8_t conslast;
+    static uint8_t consfirst;
+    static uint8_t conspointer;
+public:
+    static uint16_t conscounter;
+    static uint16_t color;
+    static Display* _display;
+    static Buttons* _buttons;
+};
+
+
+} // namespace
+
+// this is the console used by the core if POK_USE_CONSOLE is nonzero
+extern Pokitto::Console console;
+
+#endif // POKITTO_CONSOLE_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoCore.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,1296 @@
+/**************************************************************************/
+/*!
+    @file     PokittoCore.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoCore.h"
+#include "Pokitto_settings.h"
+#include "PokittoConsole.h"
+#include "PokittoFonts.h"
+#include "PokittoTimer.h"
+#include "PokittoLogos.h"
+#include <stdlib.h>
+#ifndef DISABLEAVRMIN
+#define max(a,b) ((a)>(b)?(a):(b))
+#endif // DISABLEAVRMIN
+
+char selectedfile[25];
+
+//#define F
+#ifdef __ARMCC_VERSION
+typedef void (*func_t)(void);
+#endif
+
+#ifndef POK_SIM
+#include "iap.h"
+/** start the user application
+* https://community.nxp.com/thread/417695
+*
+*/
+void start_application(unsigned long app_link_location){
+    //asm(" ldr sp, [r0,#0]");
+    //asm(" ldr pc, [r0,#4]");
+    //This code is not valid for the Cortex-m0+ instruction set.
+    // The equivalent for this (as used by the KL26) is
+__disable_irq();// Start by disabling interrupts, before changing interrupt vectors
+
+// delete buttons
+//pokDeleteButtons();
+
+// completely kill button interrupts in preparation for reset
+LPC_PINT->IENR = 0;
+LPC_PINT->IENF = 0;
+
+SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk & ~(SysTick_CTRL_ENABLE_Msk); //disable systick
+LPC_SYSCON->PDRUNCFG     |=  (1 << 10);       /* Power-down USB PHY         */
+LPC_SYSCON->PDRUNCFG     |=  (1 <<  8);       /* Power-down USB PLL         */
+
+// reset clock source to IRC
+LPC_SYSCON->MAINCLKUEN    = 0x01;             /* Update MCLK Clock Source   */
+LPC_SYSCON->MAINCLKUEN    = 0x00;             /* Toggle Update Register     */
+while (LPC_SYSCON->MAINCLKUEN & 0x01);     /* Wait Until Updated         */
+// switch clock selection to IRC
+LPC_SYSCON->MAINCLKSEL    = 0;             /* Select Clock Source        */
+LPC_SYSCON->MAINCLKUEN    = 0x01;             /* Update MCLK Clock Source   */
+LPC_SYSCON->MAINCLKUEN    = 0x00;             /* Toggle Update Register     */
+while (LPC_SYSCON->MAINCLKUEN & 0x01);     /* Wait Until Updated         */
+//disable PLL clock output
+LPC_SYSCON->SYSPLLCLKUEN = 0;
+while (LPC_SYSCON->SYSPLLCLKUEN & 0x00);
+LPC_SYSCON->SYSPLLCTRL = 0;
+
+//kill peripherals
+LPC_SYSCON->MAINCLKSEL = 0;
+LPC_SYSCON->PRESETCTRL = 0; //disable all peripherals
+
+//power down PLL
+volatile uint32_t tmp;
+tmp = (LPC_SYSCON->PDRUNCFG & 0x000025FFL);
+tmp |= ((1<<7) & 0x000025FFL);
+LPC_SYSCON->PDRUNCFG = (tmp | 0x0000C800L); /* Power-down SYSPLL          */
+
+//Chip_Clock_SetMainClockSource(SYSCTL_MAINCLKSRC_IRC); //switch to IRC
+
+// clear all gpio states
+LPC_GPIO_PORT->PIN[0] = 0;
+LPC_GPIO_PORT->PIN[1] = 0;
+LPC_GPIO_PORT->PIN[2] = 0;
+
+SCB->VTOR = app_link_location;//APPL_ADDRESS; /* Change vector table address */
+#ifndef __ARMCC_VERSION
+asm(" mov r0, %[address]"::[address] "r" (app_link_location));
+asm(" ldr r1, [r0,#0]"); // get the stack pointer value from the program's reset vector
+asm(" mov sp, r1");      // copy the value to the stack pointer
+asm(" ldr r0, [r0,#4]"); // get the program counter value from the program's reset vector
+asm(" blx r0");          // jump to the' start address
+#else
+uint32_t *app_loc = (uint32_t*)app_link_location;
+__set_MSP (app_loc[0]);
+((func_t)(app_loc[1]))();
+#endif
+}
+#endif
+
+// returns a random integar between 0 and maxVal
+int random(int maxVal)
+{
+  return random( 0, maxVal);
+}
+
+// returns a random integar between minVal and maxVal
+int random(int minVal, int maxVal)
+{
+  // int rand(void); included by default from newlib
+  return rand() % (maxVal-minVal+1) + minVal;
+}
+
+using namespace Pokitto;
+
+bool Core::run_state; // this definition needed
+
+/** Components */
+Backlight Core::backlight;
+Buttons Core::buttons;
+Battery Core::battery;
+#if POK_ENABLE_SOUND > 0
+Sound Core::sound;
+#endif
+Display Core::display;
+
+//GB Related
+uint8_t Core::startMenuTimer;
+uint8_t Core::timePerFrame;
+uint32_t Core::nextFrameMillis;
+uint32_t Core::frameCount;
+const char* Core::popupText;
+uint8_t Core::popupTimeLeft;
+uint16_t Core::frameDurationMicros;
+uint32_t Core::frameStartMicros, Core::frameEndMicros;
+uint8_t Core::volbar_visible=0;
+
+uint32_t Core::fps_counter;
+uint32_t Core::fps_refreshtime;
+uint32_t Core::fps_frameCount;
+
+Core::Core() {
+
+}
+
+
+int Core::updateLoader (uint32_t version, uint32_t jumpaddress) {
+    #ifndef POK_SIM
+    uint32_t counter=0;
+    uint8_t data[256];
+    /** prepare the flash writing **/
+    float progress=0;
+    int opg=-1;
+    uint32_t fsize=0;
+    fileEnd(); //
+    fsize = fileGetPosition();
+    if (fsize>0x40000-jumpaddress) fsize = 0x40000-jumpaddress; // shouldn't happen!!
+    fileRewind();
+    display.println("PLEASE WAIT");
+    while (1) {
+        //if (counter >= fsize-0x200) {
+        //    display.println("gotcha");
+        //}
+        if (counter >= fsize) {
+                break;
+        }
+        opg=progress;
+        if (fileReadBytes(&data[0],0x100)<0x100) {
+                if (fsize-counter>0x100) {
+                        display.println("ERROR READING LOA.DER FILE");
+                        return 1; // 1 means error
+                }
+        }
+        if (CopyPageToFlash(jumpaddress+counter,data)) {
+                    display.println("FLASH WRITE ERROR");
+                    return 1;
+        } else {
+            counter += 0x100;
+            display.print(".");
+        }
+        }
+        #endif // POK_SIM
+    return 0; //success
+}
+
+void Core::showWarning() {
+    display.enableDirectPrinting(true);
+    display.directbgcolor = COLOR_BLACK;
+    display.clearLCD();
+    display.directcolor = COLOR_RED;
+    display.setFont(fntC64UIGfx);
+    display.adjustCharStep = 0;
+    display.adjustLineStep = 0;
+    display.setCursor(10*8,9);
+    display.print("WARNING!");
+    display.directcolor = COLOR_WHITE;
+    display.setCursor(5*8,4*9);
+    display.print("LOUD SOUND THROUGH");
+    display.setCursor(2*8,5*9);
+    display.print("HEADPHONES COULD DAMAGE");
+    display.setCursor(7*8,6*9);
+    display.print("YOUR HEARING.");
+    display.setCursor(5*8,8*9);
+    display.print("USE "); display.directcolor = COLOR_GREEN;
+    display.print("0-100% VOLUME");
+    display.directcolor = COLOR_WHITE;
+    display.setCursor(5*8,9*9);
+    display.print("FOR LISTENING WITH");
+    display.setCursor(8*8,10*9);
+    display.print("HEADPHONES");
+    display.setCursor(5*8,12*9);
+    display.print("USE "); display.directcolor = COLOR_RED;
+    display.print("> 100% VOLUME"); display.directcolor = COLOR_GREEN;
+    display.directcolor = COLOR_WHITE;
+    display.setCursor(1*8,13*9);
+    display.print("ONLY FOR LISTENING VIA THE");
+    display.setCursor(5*8,14*9);
+    display.print("BUILT-IN SPEAKER");
+    display.setCursor(5*8,17*9);
+    display.print("PRESS ");display.directcolor = COLOR_GREEN;
+    display.print("C ");display.directcolor = COLOR_WHITE;
+    display.print("TO ACCEPT");
+    while (!buttons.cBtn()) {
+        wait(100);
+    }
+    display.clearLCD();
+    display.enableDirectPrinting(false);
+}
+
+void Core::jumpToLoader() {
+    //display.setFont(font5x7);
+    //display.adjustCharStep=1;
+    //display.adjustLineStep=2;
+    display.fontSize=1;
+    display.directbgcolor=COLOR_BLACK;
+    display.directcolor=COLOR_GREEN;
+    display.clearLCD();
+    display.setCursor(0,0);
+    display.enableDirectPrinting(true);
+    #ifdef POK_SIM
+    display.println("LOADER IS NOT AVAILABLE ON THE SIMULATOR. PRESS A TO RETURN.");
+    #else
+    uint32_t* bootinfo;
+    uint32_t bootversion=0, sdversion=0, sdjump=0;
+    bool flashloader=false, checkforboot=true;
+    //check for loa.der on SD card
+    #if POK_ENABLE_LOADER_UPDATES > 0
+    pokInitSD();
+    if (fileOpen("LOA.DER", FILE_MODE_BINARY)==0) {
+        //LOA.DER found on SD
+        fileEnd(); // go to end
+        fileSeekRelative(-8); //rewind 8 bytes
+        uint32_t* tptr = &sdversion;
+        fileReadBytes((uint8_t*)tptr,4); //read version number of loader on SD card
+        tptr = &sdjump;
+        fileReadBytes((uint8_t*)tptr,4); //read jump address of loader on sd card
+        fileRewind();
+    }
+    #endif
+    //now start searching for bootkey
+    while (checkforboot)
+    {
+    checkforboot=false; flashloader=false;
+    bootinfo = (uint32_t*)0x3FFF4;
+    if (*bootinfo != 0xB007AB1E) bootinfo = (uint32_t*)0x3FF04; //allow couple of alternative locations
+    if (*bootinfo != 0xB007AB1E) bootinfo = (uint32_t*)0x3FE04; //allow couple of alternative locations
+    if (*bootinfo != 0xB007AB1E) bootinfo = (uint32_t*)0x3F004; //for futureproofing
+    if (*bootinfo != 0xB007AB1E) {
+        // no bootkey found at all
+        display.directcolor=COLOR_YELLOW;
+        display.println("NO LOADER INSTALLED");
+        if (sdversion==0 || sdjump < 0x38000) {
+                //file open of loader failed
+                display.println("NO VALID LOA.DER ON SD");
+                display.println("");
+                display.directcolor=COLOR_GREEN;
+                display.println("PUT LOA.DER ON SD & REBOOT");
+        } else flashloader=true;
+    } else {
+        //loader was found
+        //check if we should update the loader
+        display.directcolor=COLOR_CYAN;
+        display.print("LOADER V.");
+        display.directcolor=COLOR_WHITE;
+        display.println(*(bootinfo+1));
+        #if POK_ENABLE_LOADER_UPDATES
+        if (sdversion>(*(bootinfo+1))) flashloader=true;
+        else start_application(*(bootinfo+2)); //never returns
+        #else
+        start_application(*(bootinfo+2)); //never returns
+        #endif
+    }
+    // update loader if it was requested
+    if(flashloader) {
+            display.directcolor=COLOR_MAGENTA;
+            display.print("NEW LOADER ON SD V.");
+            display.directcolor=COLOR_WHITE;
+            display.println(sdversion);
+            display.directcolor=COLOR_GREEN;
+            display.println("UPDATE LOADER?\n(UP=YES, DOWN=CANCEL)");
+            while(1) {
+                    if (buttons.upBtn()) {
+                        if (updateLoader(sdversion,sdjump)) {
+                            display.println("PUT LOA.DER ON SD AND RETRY");
+                        } else {
+                        display.println("SUCCESS!!");
+                        checkforboot=true; //recheck
+                        }
+                    break;
+                    }
+                    if (buttons.downBtn()) return;
+            }
+    } // if flashloader
+    } // while checkforboot
+    #endif // POK_SIM
+    while (!buttons.aBtn()) {
+        buttons.pollButtons();
+        if (buttons.aBtn()) {
+            while (buttons.aBtn()) {
+                buttons.pollButtons();
+            }
+            return;
+        }
+    }
+}
+
+void Core::askLoader() {
+    display.enableDirectPrinting(true);
+    display.directbgcolor = COLOR_BLACK;
+    display.clearLCD();
+    display.directcolor = COLOR_RED;
+    display.setFont(fntC64UIGfx);
+    display.fontSize=1;
+    display.adjustCharStep = 0;
+    display.adjustLineStep = 0;
+    display.directcolor=COLOR_GREEN;
+    display.set_cursor(12*8,6*8);
+    display.print("ijkl");
+    display.set_cursor(12*8,7*8);
+    display.print("mnop");
+    display.set_cursor(12*8,8*8);
+    display.print("qrst");
+    display.set_cursor(12*8,9*8);
+    display.print("uvwx");
+    display.set_cursor(5*8,12*8);
+    display.print("PRESS");
+    display.directcolor=COLOR_WHITE;
+    display.print(" C ");
+    display.directcolor=COLOR_GREEN;
+    display.print("FOR LOADER");
+    display.directcolor=COLOR_WHITE;
+    display.fontSize=2;
+    int countd=POK_LOADER_COUNTDOWN; uint16_t c2 = getTime();
+    while (countd) {
+        buttons.pollButtons();
+        display.set_cursor(13*8,15*8);
+        display.print(countd);
+        if (getTime()>c2+1000) {
+            c2=getTime();
+            countd--;
+        }
+        if (cBtn()) {while (cBtn()) buttons.pollButtons();jumpToLoader();countd=0;}
+        if (aBtn()) {while (aBtn()) buttons.pollButtons();countd=0;}
+        if (bBtn()) {while (bBtn()) buttons.pollButtons();countd=0;}
+    }
+    display.fontSize=1;
+    display.clearLCD();
+    display.enableDirectPrinting(false);
+}
+
+
+void Core::drawvolbar(int x, int y, int level, bool text) {
+    uint16_t oldcol = display.directcolor;
+    if (text) display.directRectangle(0,0,50,50,COLOR_BLACK);
+    display.directcolor = COLOR_GREEN;
+    if (text) {
+            bool temp = display.isDirectPrintingEnabled();
+            display.enableDirectPrinting(true);
+            display.print(x-1,y-20,(int)sound.getVolume());
+            display.print("  ");
+            display.enableDirectPrinting(temp);
+    }
+    if (level<12) display.directcolor = COLOR_GRAY_80;
+    display.directBitmap(x,y,Pokitto_volumebar,1,1);
+    if (level<24) display.directcolor = COLOR_GRAY_80;
+    display.directBitmap(x+8,y,Pokitto_volumebar,1,1);
+    display.directBitmap(x+8,y-4,Pokitto_volumebar,1,1);
+    display.directcolor = COLOR_RED;
+    if (level<48) display.directcolor = COLOR_GRAY_80;
+    display.directBitmap(x+16,y,Pokitto_volumebar,1,1);
+    display.directBitmap(x+16,y-4,Pokitto_volumebar,1,1);
+    display.directBitmap(x+16,y-8,Pokitto_volumebar,1,1);
+
+    if (level<96) {
+            display.directcolor = COLOR_GRAY_80;
+    }
+    display.directBitmap(x+24,y,Pokitto_volumebar,1,1);
+    display.directBitmap(x+24,y-4,Pokitto_volumebar,1,1);
+    display.directBitmap(x+24,y-8,Pokitto_volumebar,1,1);
+    display.directBitmap(x+24,y-12,Pokitto_volumebar,1,1);
+    if (level<160) {
+            display.directcolor = COLOR_GRAY_80;
+    }
+    display.directBitmap(x+32,y,Pokitto_volumebar,1,1);
+    display.directBitmap(x+32,y-4,Pokitto_volumebar,1,1);
+    display.directBitmap(x+32,y-8,Pokitto_volumebar,1,1);
+    display.directBitmap(x+32,y-12,Pokitto_volumebar,1,1);
+    display.directBitmap(x+32,y-16,Pokitto_volumebar,1,1);
+    display.directcolor = oldcol;
+}
+
+
+#ifdef POK_SIM
+#define VINCMULT 1
+#else
+#define VINCMULT 50
+#endif //POK_SIM
+void Core::setVolLimit() {
+    display.enableDirectPrinting(true);
+    display.adjustCharStep = 0;
+    //sound.setMaxVol(VOLUME_HEADPHONE_MAX);
+    int dstate=1;
+    bool wipe = true;
+    float vol = sound.getVolume(); float tvol;
+    #ifndef POK_SIM
+    vol=eeprom_read_byte((uint16_t*)EESETTINGS_VOL);
+    #endif
+    if (vol>VOLUME_HEADPHONE_MAX) sound.setMaxVol(VOLUME_SPEAKER_MAX);
+    else sound.setMaxVol(VOLUME_HEADPHONE_MAX);
+    for (uint8_t t=0;t<vol;t++) {
+            sound.setVolume(t);
+    }
+    volbar_visible=0;
+    while (core.isRunning() && dstate){
+        switch (dstate) {
+        case 1:
+            //redraw
+            if (wipe) {
+            display.clearLCD();
+            display.directcolor = COLOR_WHITE;
+            display.setCursor(4*8,2*8);
+            display.print("SELECT VOLUME LIMIT");
+            display.setCursor(5*8,17*9);
+            display.print("PRESS ");
+            display.directcolor = COLOR_GREEN;
+            display.print("A");
+            display.directcolor = COLOR_WHITE;
+            display.print(" TO ACCEPT");
+            display.directcolor = COLOR_GREEN;
+            // draw frame below first
+            display.setCursor(0,11*8);
+            display.println(" abbbbbbbbbbbbbbbbbbbbbbbc");
+            display.println(" |                       |");
+            display.println(" |                       |");
+            display.println(" |                       |");
+            display.println(" |                       |");
+            display.println(" dbbbbbbbbbbbbbbbbbbbbbbbe");
+            } // wipe = true
+            display.setCursor(6*8,17*9);
+            if (sound.getVolume()-5<=VOLUME_HEADPHONE_MAX) display.directcolor = COLOR_WHITE;
+            else display.directcolor = COLOR_RED;
+            display.directBitmap(21*8-4,6*8,Pokitto_headphones,1,2);
+            display.setCursor(3*8,6*8+6);
+            display.print("HEADPHONES");
+            display.setCursor(3*8,8*8+2);
+            if (sound.getVolume()-8>VOLUME_HEADPHONE_MAX) display.print("TOO LOUD!");
+            else display.print("OK        ");
+            display.directcolor = COLOR_GREEN;
+            display.directBitmap(21*8-4,12*8,Pokitto_speaker,1,2);
+            display.setCursor(3*8,12*8+6);
+            display.print("VOLUME MAX");
+            display.setCursor(3*8,14*8+2);
+            tvol = (vol/float(VOLUME_HEADPHONE_MAX))*100;
+            if (tvol > 100 && tvol < 120) tvol=100;
+            if (sound.getVolume()-5>VOLUME_HEADPHONE_MAX) { display.directcolor=COLOR_RED;}
+            else display.directcolor=COLOR_GREEN;
+            display.print(int(sound.getVolume()));
+            //display.print(int(tvol));
+            display.print("  ");
+            display.directcolor=COLOR_GREEN;
+            drawvolbar(14*8,14*8+4+2,sound.getVolume(),false);
+            //display.setCursor(1,10);
+            //display.print(vol);
+            dstate=2; break;
+        case 2:
+            buttons.pollButtons();
+            if (aBtn()) {dstate=0;while(aBtn()){buttons.pollButtons();};break;}
+            if (rightBtn()) {
+                    if (vol >= VOLUME_HEADPHONE_MAX && vol < VOLUME_HEADPHONE_MAX+1 ) vol += 0.00025f*VINCMULT;
+                    else if (vol >= VOLUME_HEADPHONE_MAX) vol += 0.25f*VINCMULT;
+                    else vol += 0.05f*VINCMULT;
+                    if (vol > VOLUME_HEADPHONE_MAX + 20) {
+                            sound.setMaxVol(VOLUME_SPEAKER_MAX);
+                    }
+                    if (vol > VOLUME_SPEAKER_MAX) vol=VOLUME_SPEAKER_MAX;
+                    sound.setVolume(vol);
+                    dstate=1; wipe=false;
+                    break;
+                    }
+            if (leftBtn()) {
+                    if (vol >= VOLUME_HEADPHONE_MAX) vol -= 0.25f*VINCMULT;
+                    else vol -= 0.05f*VINCMULT;
+                    if (vol <= VOLUME_HEADPHONE_MAX) sound.setMaxVol(VOLUME_HEADPHONE_MAX);
+                    if (vol < 0) vol=0;
+                    sound.setVolume(vol);
+                    dstate=1; wipe=false;
+                    break;
+                    }
+            break;
+        }
+    }
+    #ifndef POK_SIM
+    if (vol != eeprom_read_byte((uint16_t*)EESETTINGS_VOL)) eeprom_write_byte((uint16_t*)EESETTINGS_VOL,(uint8_t)vol);
+    #endif
+    sound.setVolume(vol);
+    sound.volumeUp();
+}
+
+void Core::begin() {
+
+    init(); // original functions
+    timePerFrame = POK_FRAMEDURATION;
+	//nextFrameMillis = 0;
+	//frameCount = 0;
+	frameEndMicros = 1;
+	startMenuTimer = 255;
+	//read default settings from flash memory (set using settings.hex)
+	readSettings();
+	//init everything
+	backlight.begin();
+	backlight.set(BACKLIGHT_MAX);
+	buttons.begin();
+	buttons.update();
+	battery.begin();
+	display.begin();
+	#if POK_DISPLAYLOGO
+        showLogo();
+	#endif // POK_DISPLAYLOGO
+
+	display.enableDirectPrinting(true);
+    display.directbgcolor = COLOR_BLACK;
+    display.clearLCD();
+    display.setFont(fntC64UIGfx);
+
+    display.enableDirectPrinting(true);
+    display.directbgcolor = COLOR_BLACK;
+    display.directcolor = COLOR_GREEN;
+    display.clearLCD();
+    display.setFont(fntC64UIGfx);
+    display.adjustCharStep=0;
+    display.adjustLineStep=1;
+    #ifdef JUSTLOAD
+	jumpToLoader();
+	#endif
+
+    #ifndef DISABLE_LOADER
+    askLoader();
+    #endif
+
+	#ifndef DISABLE_SOUND_WARNING
+	//showWarning();
+	setVolLimit();
+	//sound.setVolume(sound.getVolume());//make sure we're at set volume before continue
+	sound.volumeUp();
+	#endif
+	display.enableDirectPrinting(false);
+	display.adjustCharStep=1;
+	display.adjustLineStep=1;
+	display.fontSize=1;
+	display.textWrap=true;
+	#if POK_GAMEBUINO_SUPPORT > 0
+	display.setFont(font5x7);
+	#else
+	display.setFont(fontC64);
+    #endif
+	#if POK_ENABLE_SOUND > 0
+        sound.begin();
+        sound.volumeUp();
+
+	//mute when B is held during start up or if battery is low
+	battery.update();
+	if(buttons.pressed(BTN_B) || (battery.level == 0)){
+		sound.setVolume(0);
+	}
+	else{ //play the startup sound on each channel for it to be louder
+		#if POK_GBSOUND > 0
+		#if(NUM_CHANNELS > 0)
+			sound.playPattern(startupSound, 0);
+		#endif
+		#if(NUM_CHANNELS > 1)
+			sound.playPattern(startupSound, 1);
+		#endif
+		#if(NUM_CHANNELS > 2)
+			sound.playPattern(startupSound, 2);
+		#endif
+		#if(NUM_CHANNELS > 3)
+			sound.playPattern(startupSound, 3);
+		#endif
+		#endif // POK_GBSOUND
+	}
+	#endif // POK ENABLE_SOUND
+}
+
+void Core::init() {
+    run_state = true;
+    display.enableDirectPrinting(false);
+    display.setFont(DEFAULT_FONT);
+    initClock();
+    initGPIO();
+    initButtons();
+    initRandom();
+    //initAudio();
+    //initDisplay();
+}
+
+void Core::init(uint8_t switches) {
+    run_state = true;
+    display.enableDirectPrinting(false);
+    display.setFont(DEFAULT_FONT);
+    initClock();
+    initGPIO();
+    initButtons();
+    initRandom();
+    //initAudio();
+    //initDisplay();
+}
+
+void Core::initButtons() {
+    #ifndef POK_SIM
+    Pokitto::initButtons();
+    #endif
+}
+
+bool Core::isRunning() {
+    #ifdef POK_SIM
+    run_state = simulator.isRunning();
+    #endif // POK_SIM
+    return run_state;
+}
+
+void Core::initDisplay() {
+    #if POK_DISPLAYLOGO > 0
+        showLogo();
+    #endif
+    #if POK_USE_CONSOLE > 0
+        console.AddMessage(MSOURCE_LCD,MSG_INIT_OK);
+    #endif
+}
+
+void Core::showLogo() {
+    uint32_t now;
+    uint8_t state=0; //jump directly to logo, bypass teeth
+    uint16_t counter=0, i=0;
+    uint16_t sc;
+    while (state < 255/6) {
+    now=getTime();
+    if (now>refreshtime) {
+            refreshtime=now+30;
+            switch (state) {
+            case 0:
+                /** POKITTO CLEAN **/
+                display.directbgcolor = COLOR_BLACK;
+                display.fillLCD(display.directbgcolor);
+                sc = COLOR_BLACK;
+                state++;
+                break;
+            case 1:
+                /** POKITTO FADE IN **/
+                display.directcolor = display.interpolateColor(sc, COLOR_GREEN, i);
+                display.directBitmap(POK_LCD_W/2 - (*Pokitto_logo/2),POK_LCD_H/2-(*(Pokitto_logo+1)/2),Pokitto_logo,1,1);
+                i += 28;
+                if (i>=0xFF) { state++; i=0;}
+                break;
+            case 2:
+                /** POKITTO WAIT **/
+                display.directcolor = COLOR_GREEN;
+                display.directBitmap(POK_LCD_W/2 - (*Pokitto_logo/2),POK_LCD_H/2-(*(Pokitto_logo+1)/2),Pokitto_logo,1,1);
+                i+= 0x3F;
+                if (i>0x3FF) state = 255;
+                break;
+            }
+            if(buttons.aBtn()) state=255;
+    }
+    }
+}
+
+void Core::readSettings() {
+    // ToDo
+        /*display.contrast = SCR_CONTRAST;
+		backlight.backlightMin = BACKLIGHT_MIN;
+		backlight.backlightMax = BACKLIGHT_MAX;
+		backlight.ambientLightMin = AMBIENTLIGHT_MIN;
+		backlight.ambientLightMax = AMBIENTLIGHT_MAX;
+*/
+		sound.setMaxVol(VOLUME_HEADPHONE_MAX);
+		sound.globalVolume = VOLUME_STARTUP;
+
+		startMenuTimer = START_MENU_TIMER;
+/*
+		battery.thresolds[0] = BAT_LVL_CRITIC;
+		battery.thresolds[1] = BAT_LVL_LOW;
+		battery.thresolds[2] = BAT_LVL_MED;
+		battery.thresolds[3] = BAT_LVL_FULL;*/
+}
+
+void Core::titleScreen(const char* name){
+	titleScreen(name, 0);
+}
+
+void Core::titleScreen(const uint8_t* logo){
+	titleScreen((""), logo);
+}
+
+void Core::titleScreen(){
+	titleScreen((""));
+}
+
+void Core::titleScreen(const char*  name, const uint8_t *logo){
+	display.setFont(font5x7);
+	if(startMenuTimer){
+		display.fontSize = 1;
+		display.textWrap = false;
+		display.persistence = false;
+		battery.show = false;
+		display.setColor(BLACK);
+		while(isRunning()){
+			if(update()){
+				uint8_t logoOffset = name[0]?display.fontHeight:0; //add an offset the logo when there is a name to display
+				//draw graphics
+				display.setColorDepth(1);
+				display.setColor(3);
+				//display.drawBitmap(0,0, gamebuinoLogo);
+				display.setColor(1);
+				if(logo){
+					display.drawBitmap(0, 12+logoOffset, logo);
+				}
+				display.cursorX = 0;
+				display.cursorY = 12;
+				display.print(name);
+
+				//A button
+				display.cursorX = LCDWIDTH - display.fontWidth*3 -1;
+				display.cursorY = LCDHEIGHT - display.fontHeight*3 - 3;
+				if((frameCount/16)%2)
+				  display.println(("\25 \20"));
+				else
+				  display.println(("\25\20 "));
+				//B button
+				display.cursorX = LCDWIDTH - display.fontWidth*3 - 1;
+				display.cursorY++;
+				if(sound.globalVolume)
+					display.println(("\26\23\24"));
+				else
+					display.println(("\26\23x"));
+				//C button
+				display.cursorX = LCDWIDTH - display.fontWidth*3 - 1;
+				display.cursorY++;
+				//display.println(F("\27SD"));
+
+				//toggle volume when B is pressed
+				if(buttons.pressed(BTN_B)){
+					sound.setVolume(sound.getVolume() + 1);
+					sound.playTick();
+				}
+				//leave the menu
+				if(buttons.pressed(BTN_A) || ((frameCount>=startMenuTimer)&&(startMenuTimer != 255))){
+					startMenuTimer = 255; //don't automatically skip the title screen next time it's displayed
+					sound.stopPattern(0);
+					sound.playOK();
+					break;
+				}
+				//flash the loader
+				//if(buttons.pressed(BTN_C))
+					// ToDo changeGame();
+			}
+		}
+		battery.show = true;
+	}
+}
+
+/**
+ * Update all the subsystems, like graphics, audio, events, etc.
+ * Note: the update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations,
+ * the x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels.
+ * The update rect is currently used for 220x176, 4 colors, screen mode only.
+ * @param useDirectMode True, if only direct screen drawing is used. False, if the screen buffer is drawn. Note: If sprites are enabled, they are drawn in both modes.
+ * @param updRectX The update rect.
+ * @param updRectY The update rect.
+ * @param updRectW The update rect.
+ * @param updRectH The update rect.
+ */
+bool Core::update(bool useDirectMode, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH) {
+
+    #if POK_STREAMING_MUSIC
+        sound.updateStream();
+    #endif
+
+    uint32_t now = getTime();
+	if ((((nextFrameMillis - now)) > timePerFrame) && frameEndMicros) { //if time to render a new frame is reached and the frame end has ran once
+		nextFrameMillis = now + timePerFrame;
+		frameCount++;
+
+		frameEndMicros = 0;
+		backlight.update();
+		buttons.update();
+		battery.update();
+
+        // FPS counter
+		#ifdef PROJ_USE_FPS_COUNTER
+        const uint32_t fpsInterval_ms = 1000*3;
+
+        fps_frameCount++;
+        if (now > fps_refreshtime) {
+            fps_counter = (1000*fps_frameCount) / (now - fps_refreshtime + fpsInterval_ms);
+            fps_refreshtime = now + fpsInterval_ms;
+            fps_frameCount = 0;
+        }
+        #endif
+
+		return true;
+
+	} else {
+		if (!frameEndMicros) { //runs once at the end of the frame
+			#if POK_ENABLE_SOUND > 0
+			sound.updateTrack();
+			sound.updatePattern();
+			sound.updateNote();
+			#endif
+			updatePopup();
+			displayBattery();
+
+            display.update(useDirectMode, updRectX, updRectY, updRectW, updRectH); //send the buffer to the screen
+
+            frameEndMicros = 1; //jonne
+
+		}
+		return false;
+	}
+}
+
+void Core::displayBattery(){
+#if (ENABLE_BATTERY > 0)
+	//display.setColor(BLACK, WHITE);
+	uint8_t ox,oy;
+	ox=display.cursorX;
+	oy=display.cursorY;
+	display.cursorX = LCDWIDTH-display.fontWidth+1;
+	display.cursorY = 0;
+	switch(battery.level){
+	case 0://battery critic, power down
+		sound.stopPattern();
+		backlight.set(0);
+		display.clear();
+		display.fontSize = 1;
+		display.print(("LOW BATTERY\n"));
+		display.print(battery.voltage);
+		display.print(("mV\n\nPLEASE\nTURN OFF"));
+		display.update();
+		break;
+	case 1: //empty battery
+		if((frameCount % 16) < 8) display.print('\7'); //blinking battery
+		else display.print('x');
+		break;
+	case 2://low battery
+	case 3://full battery
+	case 4://full battery
+		if(battery.show){
+			display.print(char(5+battery.level));
+		}
+		break;
+	default:
+		if(battery.show){
+			display.print('/');
+		}
+		break;
+	}
+display.cursorX = ox;
+display.cursorY = oy;
+#endif
+}
+
+char* Core::filemenu(char *ext) {
+    display.persistence = false;
+    uint16_t oldpal0=display.palette[0];
+    uint16_t oldpal1=display.palette[1];
+    uint16_t oldpal2=display.palette[2];
+    display.palette[2]=COLOR_GREEN;
+    display.palette[1]=COLOR_WHITE;
+    display.palette[0]=COLOR_BLACK;
+    uint8_t oldbg=display.bgcolor;
+    uint8_t oldfg=display.color;
+    display.color=1;
+    display.bgcolor=0;
+
+    int8_t activeItem = 0;
+	int16_t currentY = 100;
+	int16_t targetY = 0, rowh = display.fontHeight + 2;
+	boolean exit = false;
+
+	char* txt;
+
+
+	while (isRunning()) {
+		if (update()) {
+            getFirstFile(ext);
+			if (buttons.pressed(BTN_A) || buttons.pressed(BTN_B) || buttons.pressed(BTN_C)) {
+				exit = true; //time to exit menu !
+				targetY = - display.fontHeight * 10 - 2; //send the menu out of the screen
+				if (buttons.pressed(BTN_A)) {
+					//answer = activeItem;
+					sound.playOK();
+				} else {
+					sound.playCancel();
+				}
+			}
+			if (exit == false) {
+				if (buttons.repeat(BTN_DOWN,4)) {
+					activeItem++;
+					sound.playTick();
+				}
+				if (buttons.repeat(BTN_UP,4)) {
+					activeItem--;
+					sound.playTick();
+				}
+				//don't go out of the menu
+				//if (activeItem == length) activeItem = 0;
+				//if (activeItem < 0) activeItem = length - 1;
+                if (currentY>targetY) currentY-=16;
+                if (currentY<targetY) currentY=targetY;
+				//targetY = -rowh * activeItem + (rowh+4); //center the menu on the active item
+			} else { //exit :
+			    if (currentY>targetY) currentY-=16;
+                if (currentY<targetY) currentY=targetY;
+				if ((currentY - targetY) <= 1)
+				{
+				    display.bgcolor=oldbg;
+				    display.color=oldfg;
+				    display.palette[0] = oldpal0;
+				    display.palette[1] = oldpal1;
+				    display.palette[2] = oldpal2;
+				    return selectedfile;
+				}
+
+			}
+			//draw a fancy menu
+			//currentY = 0;//(currentY + targetY) / 2 + 5;
+			display.cursorX = 0;
+			display.cursorY = currentY;
+			display.textWrap = false;
+			uint16_t fc,bc;
+			fc = display.color;
+            bc = display.bgcolor;
+            //getFirstFile(ext);
+			for (int i = 0; i<20; i++) {
+				display.invisiblecolor=255;
+				display.cursorY = currentY + rowh * i;
+				if (i==3) display.color=1;
+				if (i == activeItem){
+					display.cursorX = 3;
+
+                    //display.fillRoundRect(0, currentY + display.fontHeight * activeItem - 2, LCDWIDTH, (display.fontHeight+3), 3);
+                    display.color=2;
+                    display.fillRect(0, currentY + rowh * activeItem - 2, LCDWIDTH, (rowh));
+                    display.setColor(0,2);
+				} else display.setColor(1,0);
+				//display.println((char*)*(const unsigned int*)(items+i));
+				//display.println((int)i);
+                txt = getNextFile(ext);
+                if (txt) {
+                        display.println(txt);
+                        if (i == activeItem) {
+                            strcpy(selectedfile,txt);
+                        }
+                } else i--;
+                display.setColor(1,0);
+			} // draw menu loop
+		} // update
+	}
+	return 0;
+}
+
+char* Core::filemenu() {
+    return filemenu("");
+}
+
+int8_t Core::menu(const char* const* items, uint8_t length) {
+#if (ENABLE_GUI > 0)
+	display.persistence = false;
+	int8_t activeItem = 0;
+	int16_t currentY = display.height;
+	int16_t targetY = 0, rowh = display.fontHeight + 2;
+	boolean exit = false;
+	int8_t answer = -1;
+	while (isRunning()) {
+		if (update()) {
+			if (buttons.pressed(BTN_A) || buttons.pressed(BTN_B) || buttons.pressed(BTN_C)) {
+				exit = true; //time to exit menu !
+				targetY = - display.fontHeight * length - 2; //send the menu out of the screen
+				if (buttons.pressed(BTN_A)) {
+					answer = activeItem;
+					sound.playOK();
+				} else {
+					sound.playCancel();
+				}
+			}
+			if (exit == false) {
+				if (buttons.repeat(BTN_DOWN,4)) {
+					activeItem++;
+					sound.playTick();
+				}
+				if (buttons.repeat(BTN_UP,4)) {
+					activeItem--;
+					sound.playTick();
+				}
+				//don't go out of the menu
+				if (activeItem == length) activeItem = 0;
+				if (activeItem < 0) activeItem = length - 1;
+
+				targetY = -rowh * activeItem + (rowh+4); //center the menu on the active item
+			} else { //exit :
+				if ((currentY - targetY) <= 1)
+				return (answer);
+			}
+			//draw a fancy menu
+			currentY = (currentY + targetY) / 2;
+			display.cursorX = 0;
+			display.cursorY = currentY;
+			display.textWrap = false;
+			uint16_t fc,bc;
+			fc = display.color;
+            bc = display.bgcolor;
+			for (byte i = 0; i < length; i++) {
+				display.cursorY = currentY + rowh * i;
+				if (i == activeItem){
+					display.cursorX = 3;
+
+                    //display.fillRoundRect(0, currentY + display.fontHeight * activeItem - 2, LCDWIDTH, (display.fontHeight+3), 3);
+                    display.fillRect(0, currentY + rowh * activeItem - 2, LCDWIDTH, (rowh));
+                    display.setColor(bc,fc);
+				} else display.setColor(fc,bc);
+
+				display.println((char*)*(const unsigned int*)(items+i));
+				display.setColor(fc,bc);
+			}
+
+		}
+	}
+#else
+	return 0;
+#endif
+	return 0;
+}
+
+void Core::keyboard(char* text, uint8_t length) {
+#if (ENABLE_GUI > 0)
+	display.persistence = false;
+	//memset(text, 0, length); //clear the text
+	text[length-1] = '\0';
+	//active character in the typing area
+	int8_t activeChar = 0;
+	//selected char on the keyboard
+	int8_t activeX = 0;
+	int8_t activeY = 2;
+	//position of the keyboard on the screen
+	int8_t currentX = LCDWIDTH;
+	int8_t currentY = LCDHEIGHT;
+	int8_t targetX = 0;
+	int8_t targetY = 0;
+
+	while (1) {
+		if (update()) {
+			//move the character selector
+			if (buttons.repeat(BTN_DOWN, 4)) {
+				activeY++;
+				sound.playTick();
+			}
+			if (buttons.repeat(BTN_UP, 4)) {
+				activeY--;
+				sound.playTick();
+			}
+			if (buttons.repeat(BTN_RIGHT, 4)) {
+				activeX++;
+				sound.playTick();
+			}
+			if (buttons.repeat(BTN_LEFT, 4)) {
+				activeX--;
+				sound.playTick();
+			}
+			//don't go out of the keyboard
+			if (activeX == KEYBOARD_W) activeX = 0;
+			if (activeX < 0) activeX = KEYBOARD_W - 1;
+			if (activeY == KEYBOARD_H) activeY = 0;
+			if (activeY < 0) activeY = KEYBOARD_H - 1;
+			//set the keyboard position on screen
+			targetX = -(display.fontWidth+1) * activeX + LCDWIDTH / 2 - 3;
+			targetY = -(display.fontHeight+1) * activeY + LCDHEIGHT / 2 - 4 - display.fontHeight;
+			//smooth the keyboard displacement
+			currentX = (targetX + currentX) / 2;
+			currentY = (targetY + currentY) / 2;
+			//type character
+			if (buttons.pressed(BTN_A)) {
+				if (activeChar < (length-1)) {
+					byte thisChar = activeX + KEYBOARD_W * activeY;
+					if((thisChar == 0)||(thisChar == 10)||(thisChar == 13)) //avoid line feed and carriage return
+					continue;
+					text[activeChar] = thisChar;
+					text[activeChar+1] = '\0';
+				}
+				activeChar++;
+				sound.playOK();
+				if (activeChar > length)
+				activeChar = length;
+			}
+			//erase character
+			if (buttons.pressed(BTN_B)) {
+				activeChar--;
+				sound.playCancel();
+				if (activeChar >= 0)
+				text[activeChar] = 0;
+				else
+				activeChar = 0;
+			}
+			//leave menu
+			if (buttons.pressed(BTN_C)) {
+				sound.playOK();
+				while (1) {
+					if (update()) {
+						//display.setCursor(0,0);
+						display.println(("You entered\n"));
+						display.print(text);
+						display.println(("\n\n\n\x15:okay \x16:edit"));
+						if(buttons.pressed(BTN_A)){
+							sound.playOK();
+							return;
+						}
+						if(buttons.pressed(BTN_B)){
+							sound.playCancel();
+							break;
+						}
+					}
+				}
+			}
+			//draw the keyboard
+			for (int8_t y = 0; y < KEYBOARD_H; y++) {
+				for (int8_t x = 0; x < KEYBOARD_W; x++) {
+					display.drawChar(currentX + x * (display.fontWidth+1), currentY + y * (display.fontHeight+1), x + y * KEYBOARD_W, 1);
+				}
+			}
+			//draw instruction
+			display.cursorX = currentX-display.fontWidth*6-2;
+			display.cursorY = currentY+1*(display.fontHeight+1);
+			display.print(("\25type"));
+
+			display.cursorX = currentX-display.fontWidth*6-2;
+			display.cursorY = currentY+2*(display.fontHeight+1);
+			display.print(("\26back"));
+
+			display.cursorX = currentX-display.fontWidth*6-2;
+			display.cursorY = currentY+3*(display.fontHeight+1);
+			display.print(("\27save"));
+
+			//erase some pixels around the selected character
+			display.setColor(WHITE);
+			display.drawFastHLine(currentX + activeX * (display.fontWidth+1) - 1, currentY + activeY * (display.fontHeight+1) - 2, 7);
+			//draw the selection rectangle
+			display.setColor(BLACK);
+			display.drawRoundRect(currentX + activeX * (display.fontWidth+1) - 2, currentY + activeY * (display.fontHeight+1) - 3, (display.fontWidth+2)+(display.fontWidth-1)%2, (display.fontHeight+5), 3);
+			//draw keyboard outline
+			//display.drawRoundRect(currentX - 6, currentY - 6, KEYBOARD_W * (display.fontWidth+1) + 12, KEYBOARD_H * (display.fontHeight+1) + 12, 8, BLACK);
+			//text field
+			display.drawFastHLine(0, LCDHEIGHT-display.fontHeight-2, LCDWIDTH);
+			display.setColor(WHITE);
+			display.fillRect(0, LCDHEIGHT-display.fontHeight-1, LCDWIDTH, display.fontHeight+1);
+			//typed text
+			display.cursorX = 0;
+			display.cursorY = LCDHEIGHT-display.fontHeight;
+			display.setColor(BLACK);
+			display.print(text);
+			//blinking cursor
+			if (((frameCount % 8) < 4) && (activeChar < (length-1)))
+			display.drawChar(display.fontWidth * activeChar, LCDHEIGHT-display.fontHeight, '_',1);
+		}
+	}
+#endif
+}
+
+void Core::popup(const char* text, uint8_t duration){
+#if (ENABLE_GUI > 0)
+	popupText = text;
+	popupTimeLeft = duration+12;
+#endif
+}
+
+void Core::updatePopup(){
+#if (ENABLE_GUI > 0)
+	if (popupTimeLeft){
+		uint8_t yOffset = 0;
+		if(popupTimeLeft<12){
+			yOffset = 12-popupTimeLeft;
+		}
+		display.fontSize = 1;
+		display.setColor(WHITE);
+		display.fillRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3);
+		display.setColor(BLACK);
+		display.drawRoundRect(0,LCDHEIGHT-display.fontHeight+yOffset-3,84,display.fontHeight+3,3);
+		display.cursorX = 4;
+		display.cursorY = LCDHEIGHT-display.fontHeight+yOffset-1;
+		display.print(popupText);
+		popupTimeLeft--;
+	}
+#endif
+}
+
+void Core::setFrameRate(uint8_t fps) {
+	timePerFrame = 1000 / fps;
+	sound.prescaler = fps / 20;
+	sound.prescaler = __avrmax(1, sound.prescaler);
+}
+
+void Core::pickRandomSeed(){
+        initRandom();
+}
+
+bool Core::collidePointRect(int16_t x1, int16_t y1 ,int16_t x2 ,int16_t y2, int16_t w, int16_t h){
+	if((x1>=x2)&&(x1<x2+w))
+	if((y1>=y2)&&(y1<y2+h))
+	return true;
+	return false;
+}
+
+bool Core::collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1 ,int16_t x2 ,int16_t y2, int16_t w2, int16_t h2){
+  return !( x2     >=  x1+w1  ||
+            x2+w2  <=  x1     ||
+            y2     >=  y1+h1  ||
+            y2+h2  <=  y1     );
+}
+
+bool Core::collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2){
+  int16_t w1 = pgm_read_byte(b1);
+  int16_t h1 = pgm_read_byte(b1 + 1);
+  int16_t w2 = pgm_read_byte(b2);
+  int16_t h2 = pgm_read_byte(b2 + 1);
+
+  if(collideRectRect(x1, y1, w1, h1, x2, y2, w2, h2) == false){
+    return false;
+  }
+
+  int16_t xmin = (x1>=x2)? 0 : x2-x1;
+  int16_t ymin = (y1>=y2)? 0 : y2-y1;
+  int16_t xmax = (x1+w1>=x2+w2)? x2+w2-x1 : w1;
+  int16_t ymax = (y1+h1>=y2+h2)? y2+h2-y1 : h1;
+  for(uint8_t y = ymin; y < ymax; y++){
+    for(uint8_t x = xmin; x < xmax; x++){
+      if(display.getBitmapPixel(b1, x, y) && display.getBitmapPixel(b2, x1+x-x2, y1+y-y2)){
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+
+//** EOF **//
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoCore.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,268 @@
+/**************************************************************************/
+/*!
+    @file     PokittoCore.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POKITTOCORE_H
+#define POKITTOCORE_H
+
+#include <stdint.h>
+#include <math.h>
+#ifndef POK_SIM
+    #include "pwmout_api.h"
+    #include "HWButtons.h"
+#else
+    #include "PokittoSimulator.h"
+#endif
+#if POK_USE_CONSOLE > 0
+    #include "PokittoConsole.h"
+#endif // POK_USE_CONSOLE
+#if POK_ENABLE_SD > 0
+    #include "PokittoDisk.h"
+#endif
+
+#include "PokittoFonts.h"
+#include "PokittoPalettes.h"
+#include "PokittoDisplay.h"
+#include "PokittoButtons.h"
+#include "PokittoBattery.h"
+#include "PokittoBacklight.h"
+#include "PokittoSound.h"
+#include "PokittoFakeavr.h"
+
+#define PALETTE_SIZE 256
+#define PI 3.141592741f
+
+// For GB compatibility
+#if PROJ_GAMEBUINO > 0
+extern void setup();
+extern void loop();
+#endif // PROJ_GAMEBUINO
+
+extern uint32_t* ptimer; // re-directed tick counter
+
+namespace Pokitto {
+
+/** Core class.
+ *  The Core class is a class consisting of static data and methods.
+ *  It handles the lowlevel hardware functions of the Pokitto.
+ *  It is declared as static to prevent several instances running at same time.
+ * Example:
+ * @code
+ * // A simple "Hello World!" program with Pokitto
+ *
+ * #include "Pokitto.h"
+ *
+ * Pokitto::Core myApp;
+ *
+ * int main() {
+ *     myApp.begin(); // This starts up the console (the display, buttons etc.)
+ *     while(myApp.isRunning()) {
+ *         if(myApp.Update()) {
+ *             myApp.display.print("Hello World!");
+ *         }
+ *     }
+ * }
+ * @endcode
+ */
+
+class Core
+{
+public:
+  /** Create a Core runtime instance
+  */
+  Core();
+
+  /** Backlight component of the Core runtime */
+  static Backlight backlight;
+  /** Buttons component of the Core runtime */
+  static Buttons buttons;
+  /** Battery component of the Core runtime */
+  static Battery battery;
+  /** Sound component of the Core runtime */
+  static Sound sound;
+  /** Display component of the Core runtime */
+  static Display display;
+
+  // EXCECUTION CONTROL
+public:
+  /** Initialize runtime (use this one) */
+  static void begin();
+  /** Initialize runtime (deprecated, avoid) */
+  static void init();
+  /** Initialize runtime with options (deprecated, avoid) */
+  static void init(uint8_t);
+  /** Return run state (1 = running, 0 = shutting down) */
+  static bool isRunning();
+  /** Stop running */
+  static void quit();
+private:
+  /** run_state is true as long as program is running */
+  static bool run_state;
+
+public:
+  // INITIALIZATION
+  /** Initialize display */
+  static void initDisplay();
+  /** Initialize random generator */
+  static void initRandom();
+  /** Initialize GPIO */
+  static void initGPIO();
+  /** Initialize LCD */
+  static void initLCD();
+  /** Initialize Audio */
+  static void initAudio();
+
+
+  // DISPLAY
+public:
+  /** Initialize backlight */
+  static void initBacklight();
+
+private:
+  /** Backlight PWM pointer */
+  #ifndef POK_SIM
+  static pwmout_t backlightpwm;
+  #endif
+
+  // TIMEKEEPING
+public:
+  /** Initialize runtime clock */
+  static void initClock();
+  /** Get value of time elapsed during program in milliseconds */
+  static uint32_t getTime();
+  /** Wait for n milliseconds */
+  static void wait(uint16_t);
+  /** FPS */
+  static uint32_t fps_counter;
+private:
+  /** Time of next refresh */
+  static uint32_t refreshtime;
+
+  // DIRECT TO SCREEN
+public:
+  /** Display Pokitto logo */
+  static void showLogo();
+  static void showWarning();
+  static void setVolLimit();
+
+// BUTTON INPUT HANDLING
+private:
+  static uint8_t heldStates[];
+public:
+  static void initButtons();
+  static void pollButtons();
+  static uint8_t leftBtn();
+  static uint8_t rightBtn();
+  static uint8_t upBtn();
+  static uint8_t downBtn();
+  static uint8_t aBtn();
+  static uint8_t bBtn();
+  static uint8_t cBtn();
+  static uint8_t leftHeld();
+  static uint8_t rightHeld();
+  static uint8_t upHeld();
+  static uint8_t downHeld();
+  static uint8_t aHeld();
+  static uint8_t bHeld();
+  static uint8_t cHeld();
+
+  static uint8_t leftReleased();
+  static uint8_t rightReleased();
+  static uint8_t upReleased();
+  static uint8_t downReleased();
+  static uint8_t aReleased();
+  static uint8_t bReleased();
+  static uint8_t cReleased();
+
+  // AUDIO RELATED
+  static uint8_t ampIsOn();
+  static void ampEnable(uint8_t);
+  static uint8_t soundbyte;
+
+  // GB RELATED
+public:
+    static void readSettings();
+    static void titleScreen(const char* name, const uint8_t *logo);
+	static void titleScreen(const char* name);
+	static void titleScreen(const uint8_t* logo);
+    static void titleScreen();
+    static bool update(bool useDirectMode=false, uint8_t updRectX=0, uint8_t updRectY=0, uint8_t updRectW=LCDWIDTH, uint8_t updRectH=LCDHEIGHT);
+    static uint32_t frameCount;
+    static int8_t menu(const char* const* items, uint8_t length);
+    static char* filemenu(char*);
+    static char* filemenu();
+    static void keyboard(char* text, uint8_t length);
+    static void popup(const char* text, uint8_t duration);
+    static void setFrameRate(uint8_t fps);
+	static void pickRandomSeed();
+
+	static uint8_t getCpuLoad();
+    static uint16_t getFreeRam();
+
+    static bool collidePointRect(int16_t x1, int16_t y1 ,int16_t x2 ,int16_t y2, int16_t w, int16_t h);
+	static bool collideRectRect(int16_t x1, int16_t y1, int16_t w1, int16_t h1 ,int16_t x2 ,int16_t y2, int16_t w2, int16_t h2);
+    static bool collideBitmapBitmap(int16_t x1, int16_t y1, const uint8_t* b1, int16_t x2, int16_t y2, const uint8_t* b2);
+
+private:
+    static uint8_t timePerFrame;
+    static uint32_t nextFrameMillis;
+    static void updatePopup();
+    static const char* popupText;
+    static uint8_t popupTimeLeft;
+    static void displayBattery();
+    static uint16_t frameDurationMicros;
+    static uint32_t frameStartMicros, frameEndMicros;
+    static uint8_t startMenuTimer;
+    static int updateLoader(uint32_t,uint32_t);
+    static uint32_t fps_refreshtime;
+    static uint32_t fps_frameCount;
+
+public:
+    static uint8_t volbar_visible;
+    static void drawvolbar(int,int,int, bool);
+    static void askLoader();
+    static void jumpToLoader();
+};
+
+// this is the instance used by the system
+extern Core core;
+
+
+}
+
+#endif // POKITTOCORE_H
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoDisk.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,295 @@
+/**************************************************************************/
+/*!
+    @file     Pokitto_disk.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#include "Pokitto.h"
+
+#define SD_MOSI_PORT   0
+#define SD_MISO_PORT   0
+#define SD_SCK_PORT    0
+#define SD_CS_PORT     0
+#define SD_MOSI_PIN   9
+#define SD_MISO_PIN   8
+#define SD_SCK_PIN    6
+#define SD_CS_PIN     7
+
+#if POK_ENABLE_SD > 0
+BYTE res;
+FATFS fs;            /* File system object */
+FATDIR dir;            /* Directory object */
+FILINFO fno;        /* File information */
+
+//static FATFS *FatFs;    /* Pointer to the file system object (logical drive) */
+
+bool diropened=false;
+
+#define SPEAKER 3
+//#define BUFFER_SIZE 256 // was 128
+#define SONGLENGTH 0x1BFBCD // 1072223
+#define FILESIZE 0x1BFBCD
+
+uint8_t filemode = FILE_MODE_UNINITIALIZED;
+char currentfile[15]; // holds current file's name
+
+SPI device(CONNECT_MOSI,CONNECT_MISO,CONNECT_SCK);
+//DigitalOut mmccs(CONNECT_CS);
+
+const char *get_filename_ext(const char *filename) {
+    const char *dot = strrchr(filename, '.');
+    if(!dot || dot == filename) return "";
+    return dot + 1;
+}
+
+__attribute__((section(".SD_Code"))) void initSDGPIO() {
+    LPC_GPIO_PORT->DIR[SD_MOSI_PORT] |= (1  << SD_MOSI_PIN );
+    LPC_GPIO_PORT->DIR[SD_MISO_PORT] |= (1  << SD_MISO_PIN );
+    LPC_GPIO_PORT->DIR[SD_SCK_PORT]  |= (1  << SD_SCK_PIN );
+    LPC_GPIO_PORT->DIR[SD_CS_PORT]   |= (1  << SD_CS_PIN );
+}
+
+__attribute__((section(".SD_Code"))) int pokInitSD() {
+    initSDGPIO();
+    res = disk_initialize();
+    res = (pf_mount(&fs));
+    res = pf_opendir(&dir,"");
+    if (res) diropened=false;
+    else diropened=true;
+    return res;
+}
+
+
+void emptyFname() {
+    for (int i=0; i<13; i++) fno.fname[i]=NULL;
+}
+
+/** PUBLIC FUNCTIONS **/
+
+char* getFirstDirEntry() {
+    res=0;
+    if (!diropened) {
+            pokInitSD();
+    }
+    res = pf_opendir(&dir,"");
+    emptyFname();
+    res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+    if (res) return 0;
+    while (res==0) { //while res is ok
+        if ((fno.fattrib & 0x02)==0) {
+                if (fno.fattrib & 0x10) {
+                    fno.fname[8]='.';
+                    fno.fname[9]='D';
+                    fno.fname[10]='I';
+                    fno.fname[11]='R';
+                    fno.fname[12]='\0';
+                }
+                return fno.fname;
+        }
+        emptyFname();
+        res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+        if (res==0 && dir.index==0) break;
+    }
+    return 0;
+}
+
+char* getNextDirEntry() {
+    if (!diropened) pokInitSD();
+    emptyFname();
+	res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+	if (res==0) {
+	        while (fno.fattrib & 0x02 && !res) {emptyFname(); res = pf_readdir(&dir,&fno);} //system/hidden file
+	        if (fno.fattrib & 0x10) {
+	                int a=12;
+                    while (a) {
+                            fno.fname[a] = fno.fname[a-1];
+                            a--;
+                    }
+                    if (fno.fname[0]) {
+                            fno.fname[0]='/';
+                            a=0;
+                            while (fno.fname[a]) a++;
+                            fno.fname[a]='/';
+                    }
+
+	                /*fno.fname[a++]='.';
+                    fno.fname[a++]='D';
+                    fno.fname[a++]='I';
+                    fno.fname[a++]='R';
+                    fno.fname[a]='\0';*/
+	        }
+	        return fno.fname;
+	}
+    return NULL;
+}
+
+char* getNextFile (char* ext){
+
+    if (!diropened) pokInitSD();
+	int a=1;
+	emptyFname();
+	res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+	while (res==0 || a) { //while there are entries and
+        if (dir.index==0) return 0; //end of list
+        a = strcmp((const char*)get_filename_ext(fno.fname),(const char*)ext); // returns 0 if strings are identical
+        if (strcmp(ext,"")==0 && (fno.fattrib & 0x10) == 0) a=0;
+        if (a == 0 && (fno.fattrib & 0x10) == 0) return fno.fname;
+        if (fno.fname[0]==NULL) return NULL; //end of files
+        //if (fno.fattrib&0x10) return NULL; //its a directory
+        emptyFname();
+        res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+	}
+return 0;
+}
+
+
+char* getNextFile() {
+    return getNextFile("");
+}
+
+char* getFirstFile(char* ext) {
+    res=0;
+    if (!diropened) {
+            pokInitSD();
+    }
+    res = pf_opendir(&dir,"");
+    emptyFname();
+    res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+    if (res) return 0;
+    while (res==0 || (fno.fattrib & 0x10) == 0) {
+        int a=0;
+        a = strcmp((const char*)get_filename_ext(fno.fname),(const char*)ext); // returns 0 if strings are identical
+        if (!strcmp(ext,"")) a=0;
+        if ( a == 0 && (fno.fattrib & 0x10) == 0) return fno.fname;
+        emptyFname();
+        res = pf_readdir(&dir,&fno); //returns 0 if everything is OK
+        if (fno.fname[0]==NULL) break; //end of directory reached, no files found
+        if (res==0 && dir.index==0) break;
+    }
+    return 0;
+}
+
+char* getFirstFile() {
+    return getFirstFile("");
+}
+
+int isThisFileOpen(char* buffer){
+    int a=0;
+    a = strcmp((const char*)buffer,(const char*)currentfile); // returns 0 if strings are identical
+    if ( a == 0 && filemode != FILE_MODE_FAILED) return 1;
+    return 0;
+}
+
+int fileOK() {
+    if (filemode != FILE_MODE_FAILED) return 1;
+    return 0;
+}
+
+uint8_t fileOpen(char* buffer, char fmode) {
+    int err;
+    if (filemode == FILE_MODE_UNINITIALIZED) {
+        int a = pf_mount(&fs);
+        if (a) return 1; // 1 means error in this context
+    }
+
+    filemode = fmode;
+    err = pf_open(buffer);
+    if (err==0) {
+            strcpy(currentfile,(const char*)buffer);
+            return 0; // 0 means all clear
+    }
+    // file open failed
+    filemode = FILE_MODE_FAILED;
+    return 1; // 1 means failed
+}
+
+void fileClose() {
+    filemode = FILE_MODE_UNINITIALIZED;
+    for (uint8_t i=0; i<15; i++) currentfile[i]=0;
+}
+
+int fileGetChar() {
+    BYTE buff[1];
+    WORD br;
+    int err = pf_read(buff, 1, &br);    /* Read data to the buff[] */
+    return buff[0];
+}
+
+void filePutChar(char c) {
+    WORD bw;
+    pf_write((const void*)&c, 1, &bw);
+    pf_write(0, 0, &bw);
+}
+
+void fileWriteBytes(uint8_t * b, uint16_t n) {
+    WORD bw;
+    pf_write((const void*)&b, n, &bw);
+    pf_write(0, 0, &bw);
+}
+
+uint16_t fileReadBytes(uint8_t * b, uint16_t n) {
+    WORD br;
+    pf_read(b, n, &br);    /* Read data to the buff[] */
+    return br;             /* Return number of bytes read */
+}
+
+void fileSeekAbsolute(long n) {
+    res = pf_lseek(n);
+}
+
+void fileSeekRelative(long n) {
+    if (n<0) if (fs.fptr < -n) n=-fs.fptr;
+    else if (n>0) if (fs.fptr+n > fs.fsize) n=fs.fsize-fs.fptr;
+    res = pf_lseek(fs.fptr + n);
+}
+
+void fileRewind() {
+  res = pf_lseek(0);
+}
+
+void fileEnd() {
+  res = pf_lseek(fs.fsize);
+}
+
+long int fileGetPosition() {
+    return fs.fptr;
+}
+
+uint8_t filePeek(long n) {
+    pf_lseek(n);
+    return fileGetChar();
+}
+
+void filePoke(long n, uint8_t c) {
+    pf_lseek(n);
+    filePutChar(c);
+}
+
+int dirOpen() {
+    return pf_opendir(&dir,"");
+}
+
+int dirUp() {
+
+return 0;
+}
+
+#endif // POK_ENABLE_SD
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoDisk.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,112 @@
+/**************************************************************************/
+/*!
+    @file     PokittoDisk.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+#ifndef POKITTO_DISK_H
+#define POKITTO_DISK_H
+
+#ifndef POK_SIM
+// real hardware disk driver
+#include "diskio.h"
+#include "pff.h"
+#include "connect.h"
+#include "mbed.h"
+extern BYTE res;
+extern FATFS fs;            /* File system object */
+extern FATDIR dir;            /* Directory object */
+extern FILINFO fno;        /* File information */
+extern SPI device;
+extern DigitalOut mmccs;
+
+/**************************************************************************/
+/**                          SD CONTROL MACROS                           **/
+/**************************************************************************/
+
+// CS ... #define CONNECT_CS      P0_7 //p13
+#define CLR_SD_CS LPC_GPIO_PORT->CLR[0] = (1 << 7)
+#define SET_SD_CS LPC_GPIO_PORT->SET[0] = (1 << 7)
+#define GET_SD_CS LPC_GPIO_PORT->PIN[0] & (1 << 7)
+
+#else
+// simulated disk driver
+#endif
+
+#include <stdint.h>
+
+
+
+extern int pokInitSD();
+
+// File IO modes
+#define FILE_MODE_APPEND 0x1
+#define FILE_MODE_OVERWRITE 0
+#define FILE_MODE_READONLY 0x2
+#define FILE_MODE_READWRITE 0
+#define FILE_MODE_BINARY 0x4
+#define FILE_MODE_ASCII 0
+#define FILE_MODE_FAILED 0x8
+#define FILE_MODE_UNINITIALIZED 0x10
+
+extern uint8_t fileOpen(char*, char);
+extern void fileClose();
+extern int fileGetChar();
+extern void filePutChar(char);
+extern void fileWriteBytes(uint8_t *, uint16_t);
+extern uint16_t fileReadBytes(uint8_t *, uint16_t);
+extern void fileSeekAbsolute(long);
+extern void fileSeekRelative(long);
+extern void fileRewind();
+extern void fileEnd();
+extern long int fileGetPosition();
+#define fileSetPosition(n)  (fileSeekAbsolute(n))
+extern uint8_t filePeek(long);
+extern void filePoke(long, uint8_t);
+extern char* getCurrentFileName ();
+extern char* getNextFile (char*);
+extern char* getNextFile ();
+extern char* getFirstFile(char*);
+extern char* getFirstFile();
+extern char* getFirstDirEntry();
+extern char* getNextDirEntry();
+extern int isThisFileOpen(char*);
+extern int fileOK();
+extern int dirOpen();
+extern int dirUp();
+
+#endif // POKITTO_DISK_H
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoDisplay.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,2348 @@
+/**************************************************************************/
+/*!
+    @file     PokittoDisplay.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+/* THE SEGMENT BELOW PERTAINS TO CIRCLE DRAWING FUNCTIONS ONLY
+*
+This is the core graphics library for all our displays, providing a common
+set of graphics primitives (points, lines, circles, etc.).  It needs to be
+paired with a hardware-specific library for each display device we carry
+(to handle the lower-level functions).
+Adafruit invests time and resources providing this open source code, please
+support Adafruit & open-source hardware by purchasing products from Adafruit!
+Copyright (c) 2013 Adafruit Industries.  All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "PokittoDisplay.h"
+#include "Pokitto_settings.h"
+#include "GBcompatibility.h"
+#include "PokittoCore.h"
+#include "PokittoSound.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifndef POK_SIM
+#include "HWLCD.h"
+#else
+#include "SimLCD.h"
+#endif
+
+Pokitto::Core core;
+Pokitto::Sound _pdsound;
+
+using namespace Pokitto;
+
+
+
+uint8_t* Display::m_scrbuf;
+uint8_t* Display::m_tileset;
+uint8_t* Display::m_tilebuf;
+uint8_t* Display::m_tilecolorbuf;
+uint8_t Display::m_mode, Display::m_colordepth;
+uint8_t Display::palOffset;
+SpriteInfo Display::m_sprites[SPRITE_COUNT];
+uint8_t Display::fontSize=1;
+int16_t Display::cursorX,Display::cursorY;
+uint16_t Display::m_w,Display::m_h;
+uint8_t Display::fontWidth, Display::fontHeight;
+bool Display::textWrap=true;
+
+uint8_t Display::persistence = 0;
+uint16_t Display::color = 1;
+uint16_t Display::bgcolor = 0;
+uint16_t Display::invisiblecolor = 17;
+uint16_t Display::directcolor=0xFFFF;
+uint16_t Display::directbgcolor=0x0;
+bool Display::directtextrotated=false;
+int16_t Display::clipX = 0;
+int16_t Display::clipY = 0;
+int16_t Display::clipW = LCDWIDTH;
+int16_t Display::clipH = LCDHEIGHT;
+
+uint16_t* Display::paletteptr;
+uint16_t Display::palette[PALETTE_SIZE];
+const unsigned char* Display::font;
+int8_t Display::adjustCharStep = 1;
+int8_t Display::adjustLineStep = 1;
+bool Display::fixedWidthFont = false;
+
+/** drawing canvas **/
+//uint8_t* Display::canvas; // points to the active buffer. if null, draw direct to screen
+
+/** screenbuffer **/
+uint8_t Display::bpp = POK_COLORDEPTH;
+#ifndef POK_TILEDMODE
+#if (POK_SCREENMODE == MODE_HI_MONOCHROME)
+    uint8_t Display::width = POK_LCD_W;
+    uint8_t Display::height = POK_LCD_H;
+    uint8_t Display::screenbuffer[((POK_LCD_H+1)*POK_LCD_W)*POK_COLORDEPTH/8]; // maximum resolution
+#elif (POK_SCREENMODE == MODE_HI_4COLOR)
+    uint8_t Display::width = POK_LCD_W;
+    uint8_t Display::height = POK_LCD_H;
+    uint8_t __attribute__((section (".bss"))) Display::screenbuffer[((POK_LCD_H)*POK_LCD_W)/4]; // maximum resolution
+#elif (POK_SCREENMODE == MODE_FAST_16COLOR)
+    uint8_t Display::width = POK_LCD_W/2;
+    uint8_t Display::height = POK_LCD_H/2;
+    uint8_t Display::screenbuffer[(((POK_LCD_H/2)+1)*POK_LCD_W/2)*POK_COLORDEPTH/8]; // half resolution
+#elif (POK_SCREENMODE == MODE_HI_16COLOR)
+    uint8_t Display::width = POK_LCD_W;
+    uint8_t Display::height = POK_LCD_H;
+    uint8_t Display::screenbuffer[POK_LCD_H*POK_LCD_W/2]; // 4 bits per pixel
+#elif (POK_SCREENMODE == MODE_LAMENES)
+    uint8_t Display::width = 128;
+    uint8_t Display::height = 120;
+    uint8_t Display::screenbuffer[((121)*128)*POK_COLORDEPTH/8]; // half resolution
+#elif (POK_SCREENMODE == MODE_GAMEBOY)
+    uint8_t Display::width = 160;
+    uint8_t Display::height = 144;
+    uint8_t Display::screenbuffer[160*144/4];
+#else
+    uint8_t Display::width = 84;
+    uint8_t Display::height = 48;
+    uint8_t Display::screenbuffer[128*64]; // not needed because Gamebuino and Arduboy have their own buffer
+#endif
+#else //Tiledmode
+#if (POK_SCREENMODE == MODE_TILED_1BIT)
+    uint8_t Display::width = POK_LCD_W;
+    uint8_t Display::height = POK_LCD_H;
+    uint8_t Display::screenbuffer[0];
+#else
+    uint8_t Display::width = POK_LCD_W;
+    uint8_t Display::height = POK_LCD_H;
+    uint8_t Display::screenbuffer[0];
+#endif
+#endif //tiledmode
+
+// RLE decoding
+#define RLE_ESC_EOL 0
+#define RLE_ESC_EOB 1
+#define RLE_ESC_OFFSET 2
+
+Display::Display() {
+    m_scrbuf = screenbuffer;
+    setDefaultPalette();
+    m_mode = 1; // direct printing on by default
+    m_w = POK_LCD_W;
+    m_h = POK_LCD_H;
+    setFont(DEFAULT_FONT);
+    invisiblecolor=17;
+    bgcolor=0;
+    if (POK_COLORDEPTH) m_colordepth = POK_COLORDEPTH;
+    else m_colordepth = 4;
+    #if POK_GAMEBUINO_SUPPORT
+    setColorDepth(1);
+    #endif // POK_GAMEBUINO_SUPPORT
+
+    // Reset sprites
+    m_tilecolorbuf = NULL; //!!HV
+    for (uint8_t s = 0; s < SPRITE_COUNT; s++) m_sprites[s].bitmapData = NULL;
+}
+
+uint16_t Display::getWidth() {
+    return width;
+}
+
+uint8_t Display::getNumberOfColors() {
+    return 1<<POK_COLORDEPTH;
+}
+
+uint16_t Display::getHeight() {
+    return height;
+}
+
+uint8_t Display::getColorDepth() {
+    return m_colordepth;
+}
+
+void Display::setColorDepth(uint8_t v) {
+    if (v > POK_COLORDEPTH) v=POK_COLORDEPTH;
+    m_colordepth = v;
+}
+
+void Display::clearLCD() {
+    lcdFillSurface(0);
+    setCursor(0,0); // old basic computer style
+}
+
+void Display::fillLCD(uint16_t c) {
+    lcdFillSurface(c);
+}
+
+void Display::directPixel(int16_t x, int16_t y, uint16_t color) {
+    if ((invisiblecolor < PALETTE_SIZE) && (invisiblecolor < 16) && (color == palette[invisiblecolor])) return;
+    lcdPixel(x,y,color);
+}
+
+void Display::directTile(int16_t x, int16_t y, int16_t x2, int16_t y2, uint16_t* gfx) {
+    lcdTile(x,y,x2,y2,gfx);
+}
+
+void Display::directRectangle(int16_t x, int16_t y,int16_t x2, int16_t y2, uint16_t color) {
+    lcdRectangle(x,y,x2,y2,color);
+}
+
+void Display::begin() {
+    lcdInit();
+}
+
+void Display::setCursor(int16_t x,int16_t y) {
+    cursorX = x;
+    cursorY = y;
+}
+
+/**
+ * Update the display.
+ * The update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations, the
+ * x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels.
+ * Note: The update rect is currently used for 220x176, 4 colors, screen mode only.
+ * @param useDirectMode True, if only direct screen drawing is used. False, if the screen buffer is drawn. Note: If sprites are enabled, they are drawn in both modes.
+ * @param updRectX The update rect.
+ * @param updRectY The update rect.
+ * @param updRectW The update rect.
+ * @param updRectH The update rect.
+ */
+void Display::update(bool useDirectDrawMode, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH) {
+
+    #if POK_SCREENMODE == MODE_HI_4COLOR
+    // If there is one or more sprites, use sprite enabled drawing.
+    if (m_sprites[0].bitmapData != NULL)
+        lcdRefreshMode1Spr(m_scrbuf, updRectX, updRectY, updRectW, updRectH, paletteptr, m_sprites, useDirectDrawMode);
+    else if (!useDirectDrawMode)
+        lcdRefreshMode1(m_scrbuf, updRectX, updRectY, updRectW, updRectH, paletteptr);
+    #endif
+
+    // For the screen modes that do not support sprites, return if the direct draw mode is used.
+    if (! useDirectDrawMode) {
+
+        #if POK_SCREENMODE == MODE_GAMEBOY
+        lcdRefreshModeGBC(m_scrbuf, paletteptr);
+        #endif
+
+        #if POK_SCREENMODE == MODE_HI_16COLOR
+        lcdRefreshMode3(m_scrbuf, paletteptr);
+        #endif
+
+        #if POK_SCREENMODE == MODE_FAST_16COLOR
+        lcdRefreshMode2(m_scrbuf, paletteptr);
+        #endif
+
+        #if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR
+        lcdRefreshGB(m_scrbuf, paletteptr);
+        #endif
+
+        #if POK_SCREENMODE == MODE_ARDUBOY_16COLOR
+        lcdRefreshAB(m_scrbuf, paletteptr);
+        #endif
+
+        #if POK_SCREENMODE == MODE_TILED_1BIT
+        lcdRefreshT1(m_tilebuf, m_tilecolorbuf, m_tileset, paletteptr);
+        #endif
+    }
+
+    if (!persistence) clear();
+
+    /** draw volume bar if visible **/
+    #if POK_SHOW_VOLUME > 0
+    if (core.volbar_visible) {
+            core.drawvolbar(4,20,_pdsound.getVolume(),true);
+            core.volbar_visible--;
+    }
+    #endif // POK_SHOW_VOLUME
+
+    /** draw FPS if visible **/
+    #ifdef PROJ_USE_FPS_COUNTER
+
+	// Store current state
+    bool temp = isDirectPrintingEnabled();
+    uint16_t oldcol = directcolor;
+    uint16_t oldinvisiblecolor = invisiblecolor;
+    uint16_t oldbgcol = directbgcolor;
+    bool olddirecttextrotated = directtextrotated;
+    int8_t oldadjustCharStep = adjustCharStep;
+    const unsigned char * oldFont = font;
+
+    // Print FPS
+    char str[16];
+    sprintf(str,"FPS:%d ", (int)core.fps_counter);
+    directcolor = COLOR_WHITE;
+    invisiblecolor = COLOR_BLACK;
+    directbgcolor = 0x0001; // Cannot be black as that is transparent color
+    directtextrotated = true;
+    adjustCharStep = 0;
+    setFont(fontC64);
+    enableDirectPrinting(true);
+    print(0,0, str);
+
+	// Restore state
+    enableDirectPrinting(temp);
+    directcolor = oldcol;
+    invisiblecolor =  oldinvisiblecolor;
+    directbgcolor = oldbgcol;
+    directtextrotated = olddirecttextrotated;
+    adjustCharStep = oldadjustCharStep;
+    setFont(font);
+    #endif
+}
+
+void Display::directBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t depth, uint8_t scale) {
+    uint8_t w = *bitmap;
+	uint8_t h = *(bitmap + 1);
+	bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
+    int16_t i, j;
+    int8_t byteNum, bitNum, byteWidth = (w + 7) >> 3;
+
+    if (depth == 1) {
+        for (i = 0; i < w; i++) {
+            byteNum = i / 8;
+            bitNum = i % 8;
+            for (j = 0; j < h; j++) {
+                if (*(bitmap + j * byteWidth + byteNum) & (0x80 >> bitNum)) { //0x80 = B10000000
+                    if (scale==1) directPixel(x + i, y + j,directcolor);
+                    else {
+                        directPixel(x + i + i, y + j + j,directcolor);
+                        directPixel(x + 1 + i + i, y + j + j,directcolor);
+                        directPixel(x + i + i, y + j + j + 1,directcolor);
+                        directPixel(x + i + i + 1 , y + j + j + 1,directcolor);
+                    }
+                }
+            }
+        }
+    } else if (depth == 4) {
+        for (j = 0; j < h; j+=1) {
+            for (i = 0; i < w; i+=2) {
+                uint16_t col = paletteptr[*bitmap>>4]; //higher nibble
+                if (scale==2) {
+                        directPixel(x + (i<<1), y + (j<<1),col);
+                        directPixel(x + (i<<1) + 1, y + (j<<1),col);
+                        directPixel(x + (i<<1) + 1, y + (j<<1) + 1,col);
+                        directPixel(x + (i<<1), y + (j<<1) + 1,col);
+                } else directPixel(x + i, y + j,col);
+                col = paletteptr[*bitmap&0xF]; // lower nibble
+                if (scale==2) {
+                        directPixel(x + (i<<1) + 2, y + (j<<1),col);
+                        directPixel(x + (i<<1) + 1 + 2, y + (j<<1),col);
+                        directPixel(x + (i<<1) + 1 + 2, y + (j<<1) + 1,col);
+                        directPixel(x + (i<<1) + 2 , y + (j<<1) + 1,col);
+                } else directPixel(x + i + 1, y + j,col);
+                bitmap++;
+            }
+        }
+    }
+
+}
+
+int Display::directChar(int16_t x, int16_t y, uint16_t index){
+    const uint8_t* bitmap = font;
+    uint8_t w = *bitmap;
+	uint8_t h = *(bitmap + 1);
+	uint8_t hbytes=0, xtra=1;
+	if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit
+	hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes
+	//bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
+	bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !)
+	//int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+    int8_t i, j, numBytes;
+    numBytes = *bitmap++; //first byte of char is the width in bytes
+    // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
+    uint16_t bitcolumn; //16 bits for 2x8 bit high characters
+
+	for (i = 0; i < numBytes; i++) {
+            bitcolumn = *bitmap++;
+            if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
+            for (j = 0; j < h; j++) {
+                if (bitcolumn&0x1) {
+                    if (fontSize==2) {
+                        directPixel(x + (i<<1)  , y + (j<<1),directcolor);
+                        directPixel(x + (i<<1)+1, y + (j<<1),directcolor);
+                        directPixel(x + (i<<1)  , y + (j<<1)+1,directcolor);
+                        directPixel(x + (i<<1)+1, y + (j<<1)+1,directcolor);
+                    } else {
+                        if(directtextrotated) directPixel(y + h - j - 1, x + i,directcolor);
+                        else directPixel(x + i, y + j,directcolor);
+                    }
+
+                } else if (directbgcolor != invisiblecolor) {
+                    if (fontSize==2) {
+                        directPixel(x + (i<<1)  , y + (j<<1),directbgcolor);
+                        directPixel(x + (i<<1)+1, y + (j<<1),directbgcolor);
+                        directPixel(x + (i<<1)  , y + (j<<1)+1,directbgcolor);
+                        directPixel(x + (i<<1)+1, y + (j<<1)+1,directbgcolor);
+                    } else {
+                        if(directtextrotated) directPixel(y + h - j - 1, x + i,directbgcolor);
+                        else directPixel(x + i, y + j,directbgcolor);
+                    }
+                }
+                bitcolumn>>=1;
+            }
+    }
+    return (numBytes+adjustCharStep)*fontSize; // for character stepping
+}
+
+int Display::bufferChar(int16_t x, int16_t y, uint16_t index){
+    const uint8_t* bitmap = font;
+    uint8_t w = *bitmap;
+	uint8_t h = *(bitmap + 1);
+	uint8_t hbytes=0, xtra=1;
+	if (h==8 || h==16) xtra=0; //don't add if exactly on byte limit
+	hbytes=(h>>3)+xtra; //GLCD fonts are arranged w+1 times h/8 bytes
+	//bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
+	bitmap = bitmap + 4 + index * (w * hbytes + 1); //add an offset to the pointer (fonts !)
+	//int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+    int8_t i, j, numBytes;
+    numBytes = *bitmap++; //first byte of char is the width in bytes
+    // GLCD fonts are arranged LSB = topmost pixel of char, so its easy to just shift through the column
+    uint16_t bitcolumn; //16 bits for 2x8 bit high characters
+
+	for (i = 0; i < numBytes; i++) {
+            bitcolumn = *bitmap++;
+            if (hbytes == 2) bitcolumn |= (*bitmap++)<<8; // add second byte for 16 bit high fonts
+            for (j = 0; j <= h; j++) { // was j<=h
+                #if PROJ_ARDUBOY > 0
+                if (bitcolumn&0x1) {
+                    drawPixel(x + i, y + 7 - j,color);
+                } else drawPixel(x + i, y + 7 - j,bgcolor);
+                bitcolumn>>=1;
+                #else
+                if (bitcolumn&0x1) {
+                    drawPixel(x + i, y + j,color);
+                } else drawPixel(x + i, y + j,bgcolor);
+                bitcolumn>>=1;
+                #endif // PROJ_ARDUBOY
+
+            }
+    }
+
+    return numBytes+adjustCharStep; // for character stepping
+}
+
+void Display::clear() {
+
+    uint8_t c=0;
+    c = bgcolor & (PALETTE_SIZE-1) ; //don't let palette go out of bounds
+    if (bpp==1 && bgcolor) c=0xFF; // bgcolor !=0, set all pixels
+    else if (bpp==2) {
+        c = bgcolor & 0x3;
+        c = c | (c << 2);
+        c = c | (c << 4);
+    } else {
+        c = (c & 0x0F) | (c << 4);
+    }
+    uint16_t j = sizeof(screenbuffer);
+    memset((void*)m_scrbuf,c,j);
+
+    setCursor(0,0);
+
+}
+
+void Display::scroll(int16_t pixelrows) {
+    uint16_t index = 0, index2=0,oc;
+    if (pixelrows==0) return;
+    if (pixelrows >= height) pixelrows=height-1;
+    if (bpp == 4) index2 = pixelrows*width/2;
+    else if (bpp == 2) index2 = pixelrows*width/4;
+    else return;
+    oc = color;
+    color = bgcolor;
+    if (pixelrows>0) {
+    for (uint16_t y=0;y<height-pixelrows;y++) {
+            for (uint16_t x=0;x<(width/8)*bpp;x++) screenbuffer[index++]=screenbuffer[index2++];
+    }
+    fillRect(0,cursorY,width,height);
+    } else {
+    for (uint16_t y=pixelrows;y<height;y++) {
+            for (uint16_t x=0;x<(width*bpp)/8;x++) screenbuffer[index2++]=screenbuffer[index++];
+    }
+    fillRect(0,0,width,pixelrows);
+    }
+    color=oc;
+}
+
+void Display::fillScreen(uint16_t c) {
+    c = c & (PALETTE_SIZE-1) ; //don't let palette go out of bounds
+    if (bpp==1 && c) c=0xFF; // set all pixels
+    else if (bpp==2) {
+        c = c & 0x3;
+        c = c | (c << 2);
+        c = c | (c << 4);
+    } else {
+        c = (c & 0x0F) | (c << 4);
+    }
+    memset((void*)m_scrbuf,c,sizeof(screenbuffer));
+}
+
+void Display::setDefaultPalette() {
+    #if PICOPALETTE
+        loadRGBPalette(palettePico);
+    #else
+        loadRGBPalette(POK_DEFAULT_PALETTE);
+    #endif //PICOPALETTE
+}
+
+void Display::setColor(uint8_t c) {
+    color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
+}
+
+void Display::setColor(uint8_t c,uint8_t bgc){
+    color = c & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
+    bgcolor = bgc & ((1<<POK_COLORDEPTH)-1); // cut out colors that go above palette limit
+}
+
+void Display::setInvisibleColor(uint16_t c){
+    invisiblecolor = c; // invisible color can have values beyond 255 for identification purposes
+}
+
+uint8_t Display::getColor() {
+    return color;
+}
+
+uint8_t Display::getBgColor() {
+    return bgcolor;
+}
+
+uint16_t Display::getInvisibleColor() {
+    return invisiblecolor;
+}
+
+void Display::setClipRect(int16_t x, int16_t y, int16_t w, int16_t h) {
+    clipX = x; clipY = y; clipW = w; clipH = h;
+}
+
+
+void Display::drawPixel(int16_t x,int16_t y, uint8_t col) {
+    if (col==invisiblecolor) return; // do not draw transparent pixels
+    if ((uint16_t)x >= width || (uint16_t)y >= height) return;
+    col &= (PALETTE_SIZE-1);
+
+    #if POK_COLORDEPTH == 8
+        m_scrbuf[x+width*y] = col;
+    #endif
+
+    #if POK_GAMEBUINO_SUPPORT >0
+
+	uint8_t c = col;
+	uint8_t ct = col;
+
+    uint16_t bitptr=0;
+    for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
+	c = ct & 1; // take the lowest bit of the color index number
+	if(c == 0){ //white - or actually "Clear bit"
+		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
+	} else { //black - or actually "Set bit"
+		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
+	}
+	ct >>=1; // shift to get next bit
+	bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
+    } // POK_COLOURDEPTH
+
+    #else
+    #if POK_COLORDEPTH == 1
+        if (col) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
+        m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
+    #elif POK_COLORDEPTH == 2
+        if (col) {
+                col &= 3;
+        }
+        uint16_t i = y*(width>>2) + (x>>2);
+        uint8_t pixel = m_scrbuf[i];
+        uint8_t column = x&0x03;
+        if (column==3) pixel = (pixel&0xFC)|(col); // bits 0-1
+        else if (column==2) pixel = (pixel&0xF3)|(col<<2); // bits 2-3
+        else if (column==1) pixel = (pixel&0xCF)|(col<<4); // bits 4-5
+        else pixel = (pixel&0x3F)|(col<<6); // bits 6-7
+        m_scrbuf[i] = pixel;
+    #elif POK_COLORDEPTH == 3
+    #elif POK_COLORDEPTH == 4
+    uint16_t i = y*(width>>1) + (x>>1);
+    uint8_t pixel = m_scrbuf[i];
+    if (x&1) pixel = (pixel&0xF0)|(col);
+    else pixel = (pixel&0x0F) | (col<<4);
+    m_scrbuf[i] = pixel;
+    #endif // POK_COLORDEPTH
+    #endif // POK_GAMEBUINO_SUPPORT
+}
+
+void Display::drawPixel(int16_t x,int16_t y) {
+    if ((uint16_t)x >= width || (uint16_t)y >= height) return;
+
+    #if POK_COLORDEPTH == 8
+        m_scrbuf[x+width*y] = color;
+    #endif
+
+    #if POK_GAMEBUINO_SUPPORT > 0
+
+	uint8_t c = color;
+	uint8_t ct = color;
+	if(ct == INVERT){
+	 ct = !getPixel(x, y); //jonne - was c = !getP...
+	}
+
+    uint16_t bitptr=0;
+    for (uint8_t cbit=0;cbit<POK_COLORDEPTH;cbit++) {
+	c = ct & 1; // take the lowest bit of the color index number
+	if(c == 0){ //white - or actually "Clear bit"
+    #if DISPLAY_ROT == NOROT
+		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] &= ~_BV(y % 8);
+    #elif DISPLAY_ROT == ROTCCW
+		m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV(x % 8);
+    #elif DISPLAY_ROT == ROT180
+		m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] &= ~_BV((LCDHEIGHT - y - 1) % 8);
+    #elif DISPLAY_ROT == ROTCW
+		m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitbtr] &= ~_BV((LCDWIDTH - x - 1) % 8);
+    #endif
+		//return; //jonne
+	} else { //black - or actually "Set bit"
+    #if DISPLAY_ROT == NOROT
+		m_scrbuf[x + (y / 8) * LCDWIDTH + bitptr] |= _BV(y % 8);
+    #elif DISPLAY_ROT == ROTCCW
+		m_scrbuf[LCDHEIGHT - y - 1 + (x / 8) * LCDWIDTH_NOROT + bitptr] |= _BV(x % 8);
+    #elif DISPLAY_ROT == ROT180
+		m_scrbuf[LCDWIDTH - x - 1 + ((LCDHEIGHT - y - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDHEIGHT - y - 1) % 8);
+    #elif DISPLAY_ROT == ROTCW
+		m_scrbuf[y + ((LCDWIDTH - x - 1) / 8) * LCDWIDTH_NOROT + bitptr] |= _BV((LCDWIDTH - x -1) % 8);
+    #endif
+		//return; //jonne
+	}
+	ct >>=1; // shift to get next bit
+	bitptr += POK_BITFRAME; // move one screen worth of buffer forward to get to the next color bit
+    } // POK_COLOURDEPTH
+
+    #else
+
+    /** NOT Gamebuino */
+    #if POK_COLORDEPTH == 1
+        if (color) {m_scrbuf[(y >> 3) * width + x] |= (0x80 >> (y & 7)); return;}
+        m_scrbuf[(y >> 3) * width + x] &= ~(0x80 >> (y & 7));
+    #elif POK_COLORDEPTH == 2
+        uint16_t i = y*(width>>2) + (x>>2);
+        uint8_t pixel = m_scrbuf[i];
+        uint8_t column = x&0x03;
+        if (column==3) pixel = (pixel&0xFC)|(color); // bits 0-1
+        else if (column==2) pixel = (pixel&0xF3)|(color<<2); // bits 2-3
+        else if (column==1) pixel = (pixel&0xCF)|(color<<4); // bits 4-5
+        else pixel = (pixel&0x3F)|(color<<6); // bits 6-7
+        m_scrbuf[i] = pixel;
+    #elif POK_COLORDEPTH == 3
+    #elif POK_COLORDEPTH == 4
+            uint16_t i = y*(width>>1) + (x>>1);
+            uint8_t pixel = m_scrbuf[i];
+            if (x&1) pixel = (pixel&0xF0)|(color);
+            else pixel = (pixel&0x0F) | (color<<4);
+            m_scrbuf[i] = pixel;
+    #endif // POK_COLORDEPTH
+    #endif // POK_GAMEBUINO_SUPPORT
+}
+
+uint8_t Display::getPixel(int16_t x,int16_t y) {
+    if ((uint16_t)x >= width || (uint16_t)y >= height) return 0;
+    #if POK_GAMEBUINO_SUPPORT
+    uint8_t color=0; //jonne
+	for (uint8_t cbit=0; cbit<POK_COLORDEPTH;cbit++) {
+    	color |= (m_scrbuf[x + (y / 8) * LCDWIDTH+POK_BITFRAME*cbit] >> (y % 8)) & 0x1 ; //jonne - added +504*cbit
+	}
+	return color;
+    #else
+    /** not gamebuino */
+    #if POK_COLORDEPTH == 1
+        return (m_scrbuf[(y >> 3) * width + x] & (0x80 >> (y & 7))) ? 1:0;
+    #elif POK_COLORDEPTH == 2
+        uint16_t i = y*(width>>2) + (x>>2);
+        uint8_t pixel = m_scrbuf[i];
+        uint8_t column = x&0x03;
+        if (column==0) return pixel & 0x03; // bits 0-1
+        else if (column==1) return (pixel & 0x0C)>>2; // bits 2-3
+        else if (column==2) return (pixel & 0x30)>>4; // bits 4-5
+        else return pixel>>6;; // bits 6-7
+    #elif POK_COLORDEPTH == 3
+    #elif POK_COLORDEPTH == 4
+    uint16_t i = y*(width>>1) + (x>>1);
+    uint8_t pixel = m_scrbuf[i];
+    if (x&1) return pixel & 0x0F;
+    else return pixel>>4;
+    #endif // POK_COLORDEPTH
+    #endif // POK_GAMEBUINO_SUPPORT
+}
+
+void Display::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) {
+    if ((uint16_t)x0 >= width || (uint16_t)y0 >= height || (uint16_t)x1 >= width || (uint16_t)y1 >= height ) {
+        if (clipLine (&x0,&y0,&x1,&y1)==0) return; // line out of bounds
+    }
+	if (x0 == x1)
+		drawColumn(x0,y0,y1);
+	else if (y0 == y1)
+		drawRow(x0,x1,y0);
+	else {
+		int e;
+		signed int dx,dy,j, temp;
+		signed char s1,s2, xchange;
+		signed int x,y;
+
+		x = x0;
+		y = y0;
+
+		//take absolute value
+		if (x1 < x0) {
+			dx = x0 - x1;
+			s1 = -1;
+		}
+		else if (x1 == x0) {
+			dx = 0;
+			s1 = 0;
+		}
+		else {
+			dx = x1 - x0;
+			s1 = 1;
+		}
+
+		if (y1 < y0) {
+			dy = y0 - y1;
+			s2 = -1;
+		}
+		else if (y1 == y0) {
+			dy = 0;
+			s2 = 0;
+		}
+		else {
+			dy = y1 - y0;
+			s2 = 1;
+		}
+
+		xchange = 0;
+
+		if (dy>dx) {
+			temp = dx;
+			dx = dy;
+			dy = temp;
+			xchange = 1;
+		}
+
+		e = ((int)dy<<1) - dx;
+
+		for (j=0; j<=dx; j++) {
+			drawPixel(x,y);
+
+			if (e>=0) {
+				if (xchange==1) x = x + s1;
+				else y = y + s2;
+				e = e - ((int)dx<<1);
+			}
+			if (xchange==1)
+				y = y + s2;
+			else
+				x = x + s1;
+			e = e + ((int)dy<<1);
+		}
+	}
+}
+
+uint8_t Display::clipLine(int16_t *x0, int16_t *y0, int16_t *x1, int16_t *y1){
+    // Check X bounds
+	if (*x1<*x0) {
+        //std::swap (*x1,*x0); // swap so that we dont have to check x1 also
+        swapWT(int16_t*,x1,x0);
+        //std::swap (*y1,*y0); // y needs to be swaaped also
+        swapWT(int16_t*,y1,y0);
+	}
+
+	if (*x0>=width) return 0; // whole line is out of bounds
+
+	// Clip against X0 = 0
+	if (*x0 < 0) {
+        if ( *x1 < 0) return 0; // nothing visible
+        int16_t dx = (*x1 - *x0);
+        int16_t dy = ((*y1 - *y0) << 8); // 8.8 fixed point calculation trick
+        int16_t m = dy/dx;
+        *y0 = *y0 + ((m*-*x0)>>8); // get y0 at boundary
+        *x0 = 0;
+	}
+
+	// Clip against x1 = 83
+	if (*x1 >= width) {
+        int16_t dx = (*x1 - *x0);
+        int16_t dy = ((*y1 - *y0) << 8); // 8.8 fixed point calculation trick
+        int16_t m = dy/dx;
+        //*y1 = *y1 + ((m*(*x1-XMAX))>>8); // get y0 at boundary
+        *y1 = *y1 + ((m*(width-1-*x1))>>8); // get y0 at boundary
+        *x1 = width-1;
+	}
+
+    // Check Y bounds
+	if (*y1<*y0) {
+        //std::swap (*x1,*x0); // swap so that we dont have to check x1 also
+        swapWT(int16_t*,x1,x0);
+        //std::swap (*y1,*y0); // y needs to be swaaped also
+        swapWT(int16_t*,y1,y0);
+	}
+
+	if (*y0>=height) return 0; // whole line is out of bounds
+
+    if (*y0 < 0) {
+        if ( *y1 < 0) return 0; // nothing visible
+        int16_t dx = (*x1 - *x0) << 8;
+        int16_t dy = (*y1 - *y0); // 8.8 fixed point calculation trick
+        int16_t m = dx/dy;
+        *x0 = *x0 + ((m*-*y0)>>8); // get x0 at boundary
+        *y0 = 0;
+	}
+
+    // Clip against y1 = 47
+	if (*y1 >= height) {
+        int16_t dx = (*x1 - *x0) << 8;
+        int16_t dy = (*y1 - *y0); // 8.8 fixed point calculation trick
+        int16_t m = dx/dy;
+        *x1 = *x1 + ((m*(height-1-*y1))>>8); // get y0 at boundary
+        //*x1 = *x1 + ((m*(*y1-YMAX))>>8); // get y0 at boundary
+        *y1 = height-1;
+	}
+	return 1; // clipped succesfully
+}
+
+void Display::map1BitColumn(int16_t x, int16_t sy, int16_t ey, const uint8_t* bitmap, uint16_t column){
+    if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds
+    if ((uint16_t)x>=width) return; //completely out of bounds
+    if (sy>ey) {
+            int y=sy;
+            sy=ey;
+            ey=y; // swap around so that x0 is less than x1
+    }
+    uint16_t bmw,bmh;
+    float texelstep, texelindex;
+    bmw = *(bitmap);
+    bmh = *(bitmap+1);
+    if (column>bmw-1) column=bmw-1;
+    bitmap += 2;
+    bitmap += column;
+    texelstep = (float)bmh/((float)ey-(float)sy);
+    texelindex = 0;
+    for (int y=sy; y <= ey; y++, texelindex += texelstep) {
+        uint8_t texel;
+        uint8_t currbyte, bit;
+        currbyte = texelindex / 8;
+        bit = 7-((uint16_t) texelindex & 0x7);
+        texel=*(bitmap+currbyte*bmw);
+        if (texel & (1<<bit)) drawPixel(x,y);
+        else if (bgcolor != invisiblecolor) drawPixel(x,y,bgcolor);
+    }
+};
+
+void Display::drawColumn(int16_t x, int16_t sy, int16_t ey){
+    if ((uint16_t)sy>=height && (uint16_t)ey>=height) return; //completely out of bounds
+    if ((uint16_t)x>=width) return; //completely out of bounds
+    if (sy>ey) {
+            int y=sy;
+            sy=ey;
+            ey=y; // swap around so that x0 is less than x1
+    }
+    for (int y=sy; y <= ey; y++) {
+        drawPixel(x,y);
+    }
+}
+
+void Display::drawRow(int16_t x0, int16_t x1, int16_t y){
+    if ((uint16_t)x0>=width && (uint16_t)x1>=width) return; //completely out of bounds
+    if ((uint16_t)y>=height) return; //completely out of bounds
+
+    if (x0>x1) {
+            int x=x0;
+            x0=x1;
+            x1=x; // swap around so that x0 is less than x1
+    }
+    for (int x=x0; x <= x1; x++) {
+        drawPixel(x,y);
+    }
+}
+
+void Display::drawFastVLine(int16_t x, int16_t y, int16_t h){
+    if (h<0) {y += h; h = -h;}
+    drawColumn(x,y,y+h);
+}
+
+void Display::drawFastHLine(int16_t x, int16_t y, int16_t w){
+    if (w<0) {x += w; w = -w;}
+    drawRow(x,x+w-1,y);
+}
+
+void Display::drawRectangle(int16_t x0, int16_t y0, int16_t w, int16_t h) {
+    drawColumn(x0,y0,y0+h);
+    drawColumn(x0+w,y0,y0+h);
+    drawRow(x0,x0+w,y0);
+    drawRow(x0,x0+w,y0+h);
+}
+
+void Display::fillRectangle(int16_t x0,int16_t y0, int16_t w, int16_t h){
+    int16_t x,y,x1,y1;
+    x1=x0+w;y1=y0+h;
+    if ((x0<0 && x1<0) || (x0>=width && x1 >=width)) return; //completely out of bounds
+    if ((y0<0 && y1<0) || (y0>=height && y1 >=height)) return; //completely out of bounds
+    if (x0>x1) {x=x1;x1=x0;}
+    else x=x0;
+    if (y0>y1) {y=y1;y1=y0;}
+    else y=y0;
+    if (x<0) x=0;
+    if (y<0) y=0;
+    for (;x<x1;x++) drawColumn(x,y,y1);
+}
+
+void Display::fillRect(int16_t x, int16_t y, int16_t w, int16_t h) {
+    fillRectangle(x,y,w,h);
+}
+
+void Display::drawRect(int16_t x, int16_t y, int16_t w, int16_t h) {
+    drawRectangle(x,y,w,h);
+}
+
+void Display::drawCircle(int16_t x0, int16_t y0, int16_t r) {
+    int16_t f = 1 - r;
+    int16_t ddF_x = 1;
+    int16_t ddF_y = -2 * r;
+    int16_t x = 0;
+    int16_t y = r;
+
+    drawPixel(x0, y0 + r);
+    drawPixel(x0, y0 - r);
+    drawPixel(x0 + r, y0);
+    drawPixel(x0 - r, y0);
+
+    while (x < y) {
+        if (f >= 0) {
+
+            y--;
+            ddF_y += 2;
+            f += ddF_y;
+        }
+        x++;
+        ddF_x += 2;
+        f += ddF_x;
+
+        drawPixel(x0 + x, y0 + y);
+        drawPixel(x0 - x, y0 + y);
+        drawPixel(x0 + x, y0 - y);
+        drawPixel(x0 - x, y0 - y);
+        drawPixel(x0 + y, y0 + x);
+        drawPixel(x0 - y, y0 + x);
+        drawPixel(x0 + y, y0 - x);
+        drawPixel(x0 - y, y0 - x);
+
+    }
+}
+
+void Display::drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername) {
+    int16_t f = 1 - r;
+    int16_t ddF_x = 1;
+    int16_t ddF_y = -2 * r;
+    int16_t x = 0;
+    int16_t y = r;
+
+    while (x < y) {
+        if (f >= 0) {
+            y--;
+            ddF_y += 2;
+            f += ddF_y;
+        }
+        x++;
+        ddF_x += 2;
+        f += ddF_x;
+        if (cornername & 0x4) {
+            drawPixel(x0 + x, y0 + y);
+            drawPixel(x0 + y, y0 + x);
+        }
+        if (cornername & 0x2) {
+            drawPixel(x0 + x, y0 - y);
+            drawPixel(x0 + y, y0 - x);
+        }
+        if (cornername & 0x8) {
+            drawPixel(x0 - y, y0 + x);
+            drawPixel(x0 - x, y0 + y);
+        }
+        if (cornername & 0x1) {
+
+            drawPixel(x0 - y, y0 - x);
+            drawPixel(x0 - x, y0 - y);
+        }
+    }
+}
+
+void Display::fillCircle(int16_t x0, int16_t y0, int16_t r) {
+    drawFastVLine(x0, y0 - r, 2 * r );
+    fillCircleHelper(x0, y0, r, 3, 0);
+}
+
+void Display::fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername, int16_t delta) {
+    int16_t f = 1 - r;
+    int16_t ddF_x = 1;
+    int16_t ddF_y = -2 * r;
+    int16_t x = 0;
+    int16_t y = r;
+
+    while (x < y) {
+        if (f >= 0) {
+            y--;
+            ddF_y += 2;
+            f += ddF_y;
+        }
+        x++;
+        ddF_x += 2;
+        f += ddF_x;
+
+        if (cornername & 0x1) {
+            drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne
+            drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne
+        }
+        if (cornername & 0x2) {
+
+            drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta-1); //added -1 here, jonne
+            drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta-1); //added -1 here, jonne
+        }
+    }
+}
+
+void Display::drawRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) {
+    if (r<2) {drawRectangle(x,y,w,h);return;}
+    // smarter version
+    drawFastHLine(x + r, y, w - 2 * r); // Top
+    drawFastHLine(x + r, y + h - 1, w - 2 * r); // Bottom
+    drawFastVLine(x, y + r, h - 2 * r); // Left
+    drawFastVLine(x + w - 1, y + r, h - 2 * r); // Right
+    // draw four corners
+    drawCircleHelper(x + r, y + r, r, 1);
+    drawCircleHelper(x + w - r - 1, y + r, r, 2);
+    drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4);
+    drawCircleHelper(x + r, y + h - r - 1, r, 8);
+}
+
+void Display::fillRoundRect(int16_t x, int16_t y, int16_t w,int16_t h, int16_t r) {
+    if (r<2) {fillRectangle(x,y,w,h);return;}
+    fillRectangle(x + r, y, w - 2 * r, h-1);
+    // draw four corners
+    fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1);
+    fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1);
+}
+
+void Display::drawTriangle(int16_t x0, int16_t y0,
+        int16_t x1, int16_t y1,
+        int16_t x2, int16_t y2) {
+    drawLine(x0, y0, x1, y1);
+    drawLine(x1, y1, x2, y2);
+    drawLine(x2, y2, x0, y0);
+}
+
+void Display::fillTriangle(int16_t x0, int16_t y0,
+        int16_t x1, int16_t y1,
+        int16_t x2, int16_t y2) {
+    int16_t a, b, y, last;
+
+    // Sort coordinates by Y order (y2 >= y1 >= y0)
+    if (y0 > y1) {
+        swapWT(int16_t,y0, y1);
+        swapWT(int16_t,x0, x1);
+    }
+    if (y1 > y2) {
+        swapWT(int16_t,y2, y1);
+        swapWT(int16_t,x2, x1);
+    }
+    if (y0 > y1) {
+        swapWT(int16_t,y0, y1);
+        swapWT(int16_t,x0, x1);
+    }
+
+    if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
+        a = b = x0;
+        if (x1 < a) a = x1;
+        else if (x1 > b) b = x1;
+        if (x2 < a) a = x2;
+        else if (x2 > b) b = x2;
+        drawFastHLine(a, y0, b - a + 1);
+        return;
+    }
+
+    int16_t
+    dx01 = x1 - x0,
+            dy01 = y1 - y0,
+            dx02 = x2 - x0,
+            dy02 = y2 - y0,
+            dx12 = x2 - x1,
+            dy12 = y2 - y1,
+            sa = 0,
+            sb = 0;
+
+    // For upper part of triangle, find scanline crossings for segments
+    // 0-1 and 0-2.  If y1=y2 (flat-bottomed triangle), the scanline y1
+    // is included here (and second loop will be skipped, avoiding a /0
+    // error there), otherwise scanline y1 is skipped here and handled
+    // in the second loop...which also avoids a /0 error here if y0=y1
+    // (flat-topped triangle).
+    if (y1 == y2) last = y1; // Include y1 scanline
+    else last = y1 - 1; // Skip it
+
+    for (y = y0; y <= last; y++) {
+        a = x0 + sa / dy01;
+        b = x0 + sb / dy02;
+        sa += dx01;
+        sb += dx02;
+        /* longhand:
+        a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
+        b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
+         */
+        if (a > b) swapWT(int16_t,a, b);
+        drawFastHLine(a, y, b - a + 1);
+    }
+
+    // For lower part of triangle, find scanline crossings for segments
+    // 0-2 and 1-2.  This loop is skipped if y1=y2.
+    sa = dx12 * (y - y1);
+    sb = dx02 * (y - y0);
+    for (; y <= y2; y++) {
+        a = x1 + sa / dy12;
+        b = x0 + sb / dy02;
+        sa += dx12;
+        sb += dx02;
+
+        if (a > b) swapWT(int16_t,a, b);
+        drawFastHLine(a, y, b - a + 1);
+    }
+}
+
+void Display::setFont(const unsigned char * f) {
+	font = f;
+	fontWidth = *(font)+1;
+	fontHeight = *(font + 1)+1;
+}
+
+void Display::drawMonoBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t index) {
+    uint8_t w = *bitmap;
+	uint8_t h = *(bitmap + 1);
+	uint8_t xtra=0;
+	if (w&0x7) xtra=1;
+	bitmap = bitmap + 3 + index * h * ((w>>3)+xtra); //add an offset to the pointer (fonts !)
+    #if POK_GAMEBUINO_SUPPORT > 0
+    int8_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+    for (i = 0; i < w; i++) {
+        byteNum = i / 8;
+        bitNum = i % 8;
+        for (j = 0; j < h; j++) {
+            uint8_t source = *(bitmap + j * byteWidth + byteNum);
+            if (source & (0x80 >> bitNum)) {
+                drawPixel(x + i, y + j);
+            }
+        }
+    }
+    #else
+    /** not gamebuino */
+    int8_t scrx,scry;
+    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+    int8_t bitptr;
+    for (scry = y; scry < y+h; scry+=1) {
+            if ((x&1)==0) { /** EVEN pixel starting line**/
+                for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) {
+                    uint8_t targetpixel = *scrptr;
+                    if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // upper nibble
+                    else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // upper nibble
+                    bitptr--;
+                    if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble
+                    else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble
+                    bitptr--;
+                    if (bitptr<0) { bitptr = 7; bitmap++; }
+                    *scrptr = targetpixel;
+                    scrptr++;
+                }
+            } else { /** ODD pixel starting line **/
+                for (scrx = x, bitptr=7; scrx < w+x; scrx+=2) {
+                    uint8_t targetpixel = *scrptr;
+                    // store higher nibble of source pixel in lower nibble of target
+                    if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF0) | color; // lower nibble
+                    else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF0) | bgcolor; // lower nibble
+                    *scrptr = targetpixel; // store
+                    bitptr--;scrptr++;targetpixel = *scrptr;
+                    // store lower nibble of source pixel in higher nibble of target
+                    if (*bitmap & (1<<bitptr)) targetpixel = (targetpixel & 0xF) | color<<4; // higher nibble
+                    else if (bgcolor != invisiblecolor) targetpixel = (targetpixel & 0xF) | bgcolor<<4; // higher nibble
+                    *scrptr = targetpixel; // store
+                    bitptr--; // do not increment scrptr here !
+                }
+            }
+            if (bitptr!=7) bitmap++; // force skip to next line
+            // increment the y jump in the scrptr
+            scrptr = scrptr + ((width - w)>>1);
+    }
+    #endif // POK_GAMEBUINO_SUPPORT
+}
+
+
+void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame)
+{
+    int16_t w = *bitmap;
+	int16_t h = *(bitmap + 1);
+	uint8_t framew = *(bitmap+2);
+    bitmap = bitmap + 3; //add an offset to the pointer to start after the width and height
+    /** visibility check */
+    if (y<-h || y>height) return; //invisible
+    if (x<-framew || x>width) return;  //invisible
+    /** 1 bpp mode */
+    if (m_colordepth<2) {
+    int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+    for (i = 0; i < w; i++) {
+        byteNum = i / 8;
+        bitNum = i % 8;
+        for (j = 0; j < h; j++) {
+            uint8_t source = *(bitmap + j * byteWidth + byteNum);
+            if (source & (0x80 >> bitNum)) {
+                drawPixel(x + i, y + j);
+            }
+        }
+    }
+
+    return;
+    }
+    /** 2 bpp mode */
+    if (m_colordepth<4) {
+    int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
+    for (i = 0; i < w; i++) {
+        byteNum = i / 4;
+        bitNum = (i % 4)<<1;
+        for (j = 0; j < h; j++) {
+            uint8_t source = *(bitmap + j * byteWidth + byteNum);
+            uint8_t output = (source & (0xC0 >> bitNum));
+            output >>= (6-bitNum);
+            if (output != invisiblecolor) {
+                setColor(output);
+                drawPixel(x + i, y + j);
+            }
+        }
+    }
+
+    return;
+    }
+    /** 4bpp fast version */
+	int16_t scrx,scry,xclip,xjump,scrxjump;
+    xclip=xjump=scrxjump=0;
+    bitmap += (framew*frame)>>1;
+    /** y clipping */
+    if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
+    else if (y+h>height) { h -=(y-height);}
+    /** x clipping */
+    xjump = (w-framew)>>1;
+    if (x<0) { xclip=(x&1)<<1; framew+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;}
+    else if (x+framew>width) {
+            xclip = (x&1)<<1;
+            scrxjump = x&1;
+            xjump=((x+framew-width)>>1)+scrxjump;
+            framew = width-x;}
+
+    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+    /** ONLY 4-bit mode for time being **/
+    for (scry = y; scry < y+h; scry+=1) {
+            if (scry>=height) return;
+            if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
+                for (scrx = x; scrx < framew+x-xclip; scrx+=2) {
+                    uint8_t sourcepixel = *bitmap;
+                    if (xclip) {
+                            sourcepixel <<=4;
+                            sourcepixel |= ((*(bitmap+1))>>4);
+                    }
+                    uint8_t targetpixel = *scrptr;
+                    if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0);
+                    if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F);
+                    *scrptr = targetpixel;
+                    bitmap++;
+                    scrptr++;
+                }
+                if (xclip){
+                    if (framew&1) {
+                        /**last pixel is odd pixel due to clipping & odd width*/
+                        uint8_t sourcepixel = *bitmap;
+                        if ((sourcepixel&0x0F) != invisiblecolor) {
+                            sourcepixel <<=4;
+                            uint8_t targetpixel = *scrptr;// & 0x0F;
+                            targetpixel |= sourcepixel;
+                            *scrptr = targetpixel;
+                        }
+                        //scrptr++;
+                    }
+                    bitmap++;
+                    scrptr++;
+                }
+                bitmap += xjump; // needed if x<0 clipping occurs
+            } else { /** ODD pixel starting line **/
+                for (scrx = x; scrx < framew+x-xclip; scrx+=2) {
+                    uint8_t sourcepixel = *bitmap;
+                    uint8_t targetpixel = *scrptr;
+                    // store higher nibble of source pixel in lower nibble of target
+                    if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
+                    *scrptr = targetpixel;
+                    scrptr++;
+                    targetpixel = *scrptr;
+                    // store lower nibble of source pixel in higher nibble of target
+                    if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4);
+                    *scrptr = targetpixel;
+                    bitmap++;
+                }
+                bitmap+=xjump;
+            }
+            // increment the y jump in the scrptr
+            scrptr = scrptr + ((width - framew)>>1)+scrxjump;
+    }
+}
+
+
+void Display::drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap)
+{
+    int16_t w = *bitmap;
+	int16_t h = *(bitmap + 1);
+    bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
+    drawBitmapData(x, y, w, h, bitmap);
+}
+
+void Display::drawBitmapData(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap) {
+    /** visibility check */
+    if (y<-h || y>height) return; //invisible
+    if (x<-w || x>width) return;  //invisible
+    /** 1 bpp mode */
+    if (m_colordepth<2) {
+    int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+    for (i = 0; i < w; i++) {
+        byteNum = i / 8;
+        bitNum = i % 8;
+        for (j = 0; j < h; j++) {
+            uint8_t source = *(bitmap + j * byteWidth + byteNum);
+            if (source & (0x80 >> bitNum)) {
+                drawPixel(x + i, y + j);
+            }
+        }
+    }
+
+    return;
+    }
+    /** 2 bpp mode */
+    if (m_colordepth<4) {
+        if(clipH > 0) {
+
+            // Clip
+            int16_t x1 = max(x, clipX);
+            int16_t x2 = min(x + w, clipX + clipW);
+            int16_t bmupdateX = x1 - x;
+            int16_t bmupdateX2 = x2 - x;
+            int16_t y1 = max(y, clipY);
+            int16_t y2 = min(y + h, clipY + clipH);
+            int16_t bmupdateY = y1 - y;
+            int16_t bmupdateY2 = y2 - y;
+
+            int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
+            for (i = bmupdateX; i < bmupdateX2; i++) {
+                byteNum = i / 4;
+                bitNum = (i % 4)<<1;
+                for (j = bmupdateY; j < bmupdateY2; j++) {
+                    uint8_t source = *(bitmap + (j * byteWidth) + byteNum);
+                    uint8_t output = (source & (0xC0 >> bitNum));
+                    output >>= (6-bitNum);
+                    if (output != invisiblecolor) {
+                        setColor(output);
+                        drawPixel(x + i, y + j);
+                    }
+                }
+            }
+        }
+        else {
+            int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
+            for (i = 0; i < w; i++) {
+                byteNum = i / 4;
+                bitNum = (i % 4)<<1;
+                for (j = 0; j < h; j++) {
+                    uint8_t source = *(bitmap + (j * byteWidth) + byteNum);
+                    uint8_t output = (source & (0xC0 >> bitNum));
+                    output >>= (6-bitNum);
+                    if (output != invisiblecolor) {
+                        setColor(output);
+                        drawPixel(x + i, y + j);
+                    }
+                }
+            }
+        }
+        return;
+    }
+    /** 4bpp fast version */
+	int16_t scrx,scry,xclip,xjump,scrxjump;
+    xclip=xjump=scrxjump=0;
+    /** y clipping */
+    if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
+    else if (y+h>height) { h -=(y-height);}
+    /** x clipping */
+    if (x<0) { xclip=(x&1)<<1; w+=x; xjump = ((-x)>>1); bitmap += xjump; x=0;}
+    else if (x+w>width) {
+            xclip = (x&1)<<1;
+            scrxjump = x&1;
+            xjump=((x+w-width)>>1)+scrxjump;
+            w = width-x;}
+
+    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+    /** ONLY 4-bit mode for time being **/
+    for (scry = y; scry < y+h; scry+=1) {
+            if (scry>=height) return;
+            if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
+                for (scrx = x; scrx < w+x-xclip; scrx+=2) {
+                    uint8_t sourcepixel = *bitmap;
+                    if (xclip) {
+                            sourcepixel <<=4;
+                            sourcepixel |= ((*(bitmap+1))>>4);
+                    }
+                    uint8_t targetpixel = *scrptr;
+                    if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0x0F) | (sourcepixel & 0xF0);
+                    if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F);
+                    *scrptr = targetpixel;
+                    bitmap++;
+                    scrptr++;
+                }
+                if (xclip){
+                    if (w&1) {
+                        /**last pixel is odd pixel due to clipping & odd width*/
+                        uint8_t sourcepixel = *bitmap;
+                        if ((sourcepixel&0x0F) != invisiblecolor) {
+                            sourcepixel <<=4;
+                            uint8_t targetpixel = *scrptr & 0x0F;
+                            targetpixel |= sourcepixel;
+                            *scrptr = targetpixel;
+                        }
+                        //scrptr++;
+                    }
+                    bitmap++;
+                    scrptr++;
+                }
+                bitmap += xjump; // needed if x<0 clipping occurs
+            } else { /** ODD pixel starting line **/
+                //for (scrx = x; scrx < w+x-xclip; scrx+=2) {
+                for (scrx = x; scrx < w+x-xclip; scrx+=2) {
+                    uint8_t sourcepixel = *bitmap;
+                    uint8_t targetpixel = *scrptr;
+                    // store higher nibble of source pixel in lower nibble of target
+                    if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel >> 4 );
+                    *scrptr = targetpixel;
+                    scrptr++;
+                    targetpixel = *scrptr;
+                    // store lower nibble of source pixel in higher nibble of target
+                    if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel << 4);
+                    *scrptr = targetpixel;
+                    bitmap++;
+                }
+                if (xclip){
+                    if (w&1) {
+                        /**last pixel is odd pixel due to clipping & odd width*/
+                        uint8_t sourcepixel = *bitmap;
+                        sourcepixel >>=4; //top nibble of sourcebyte from bitmap...
+                        if (sourcepixel != invisiblecolor) {
+                            uint8_t targetpixel = *scrptr & 0xF0; //...put into the low nibble of the target
+                            targetpixel |= sourcepixel;
+                            *scrptr = targetpixel;
+                        }
+                        //scrptr++;
+                    }
+                }
+                bitmap+=xjump;
+            }
+            // increment the y jump in the scrptr
+            scrptr = scrptr + ((width - w)>>1)+scrxjump;
+    }
+}
+
+void Display::drawRleBitmap(int16_t x, int16_t y, const uint8_t* rlebitmap)
+{
+    // ONLY can copy 4-bit bitmap to 4-bit screen mode for time being
+    #if (POK_SCREENMODE != MODE_FAST_16COLOR)
+    return;
+    #endif
+
+    int16_t w = *rlebitmap;
+	int16_t h = *(rlebitmap + 1);
+    rlebitmap = rlebitmap + 2; //add an offset to the pointer to start after the width and height
+
+    // visibility check
+    if (y<-h || y>height) return; //invisible
+    if (x<-w || x>width) return;  //invisible
+
+    // Clipping is not supported
+    if ((x < 0) || (x+w > width) || (y < 0) || (y+h > height)) return;
+
+    // Currently only support RLE bitmaps in 16 color mode.
+    if (m_colordepth != 4)  //
+        return;
+
+    // Go through each line.
+    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+    bool is_endofbitmap = false;
+    for (int16_t scry = y; scry < y+h && !is_endofbitmap;) {
+
+        // Process one line. Go through each pixel run and escape command in RLE data.
+        for (int16_t scrx = x;;) {
+            uint8_t rle_count = *rlebitmap++;
+
+            if (rle_count == 0) {
+
+               /* Escape or absolute mode */
+
+                uint8_t rle_escape_or_runsize = *rlebitmap++;
+                if ( rle_escape_or_runsize == RLE_ESC_EOL) {
+                    // End of line.
+                    break;
+                }
+                else if ( rle_escape_or_runsize == RLE_ESC_EOB) {
+                    // End of bitmap.
+                    is_endofbitmap = true;
+                    break;
+                }
+                else if ( rle_escape_or_runsize == RLE_ESC_OFFSET) {
+                    // Move position in target.
+                    // TODO: not tested yet.
+                    uint8_t xoffset = *rlebitmap++;
+                    uint8_t yoffset = *rlebitmap++;
+                    scrptr += (xoffset>1);
+                    scrx += xoffset;
+                    scrptr += yoffset*width;
+                    scry += yoffset;
+                 }
+                else {
+
+                    /* Absolute mode. Copy pixels from the source bitmap to the target screen. */
+
+                    int16_t runsize = rle_escape_or_runsize;
+                    uint8_t targetpixel = *scrptr;  // initial value
+                    uint8_t sourcepixel = *rlebitmap;  // initial value
+                    for( int16_t runx = 0; runx < runsize; ) {
+                        if (scrx&0x1)  { // screen pixel is in the low nibble
+                            if (runx&0x1) { // bitmap pixel is in the low nibble
+                                if ((sourcepixel&0x0F) != invisiblecolor)
+                                    targetpixel = (targetpixel&0xF0) | (sourcepixel&0x0F); // Copy low to low nibble.
+                                rlebitmap++;
+                            }
+                            else // bitmap pixel is in the high nibble
+                                if ((sourcepixel>>4) != invisiblecolor)
+                                    targetpixel = (targetpixel&0xF0) | (sourcepixel>>4); // Copy high to low nibble.
+
+                            // Copy the byte to the target.
+                            *scrptr = targetpixel;
+                            scrptr++;
+                        }
+                        else  { // screen pixel is in the high nibble
+                            targetpixel = *scrptr;
+                            sourcepixel = *rlebitmap;
+                            if (runx&0x1) { // bitmap pixel is sourcepixel = *rlebitmapin the low nibble
+                                if ((sourcepixel&0x0F) != invisiblecolor )
+                                    targetpixel = (targetpixel&0x0F) | ((sourcepixel<<4)&0xF0); // Copy low to high nibble.
+                                rlebitmap++;  // read the new source byte
+                            }
+                            else // bitmap pixel is in the high nibble
+                                if ((sourcepixel>>4) != invisiblecolor )
+                                    targetpixel = (targetpixel&0x0F) | (sourcepixel&0xF0); // Copy high to high nibble.
+                        }
+                        runx++;
+                        scrx++;
+                    }  // end for
+
+                     // If this is odd target index, copy the byte to the target.
+                    if (scrx&0x1) {
+                        *scrptr = targetpixel;
+                        scrptr++;
+                    }
+
+                    // In absolute mode the source size is always padded to the word boundary.
+                    if (runsize%4) {
+                        int16_t padpixcount = 4 - (runsize%4);
+                        rlebitmap += padpixcount>>1;  // skip n padding bytes
+                    }
+                }
+            }
+            else {
+
+                /* Encoded mode. Duplicate one pixel pair to the all required pixels on the target screen */
+
+                int16_t runsize = rle_count;
+                uint8_t clonepixelpair = *rlebitmap++;
+                uint8_t targetpixel = *scrptr;  // initial value
+                for( int16_t runx = 0;  runx < runsize; ) {
+                    if (scrx&0x1)  { // screen pixel is in the low nibble
+                        if (runx&0x1) { // bitmap pixel is in the low nibble
+                            if ((clonepixelpair&0x0F) != invisiblecolor)
+                                targetpixel = (targetpixel&0xF0) | (clonepixelpair&0x0F); // Copy low to low nibble.
+                        }
+                        else // bitmap pixel is in the high nibble
+                            if ((clonepixelpair>>4) != invisiblecolor)
+                                targetpixel = (targetpixel&0xF0) | (clonepixelpair>>4); // Copy high to low nibble.
+
+                        // Copy the byte to the target.
+                        *scrptr = targetpixel;
+                        scrptr++;
+                    }
+                    else  { // screen pixel is in the high nibble
+                        targetpixel = *scrptr;
+                        if (runx&0x1) {// bitmap pixel is in the low nibble
+                            if ((clonepixelpair&0x0F) != invisiblecolor )
+                                targetpixel = (targetpixel&0x0F) | ((clonepixelpair<<4)&0xF0); // Copy low to high nibble.
+                        }
+                        else // bitmap pixel is in the high nibble
+                            if ((clonepixelpair>>4) != invisiblecolor )
+                                targetpixel = (targetpixel&0x0F) | (clonepixelpair&0xF0); // Copy high to high nibble.
+                    }
+                    runx++;
+                    scrx++;
+
+                }  // end for
+
+                // If this is odd target index, copy the byte to the target.
+                if (scrx&0x1) {
+                    *scrptr = targetpixel;
+                    scrptr++;
+                 }
+            } // end if
+        }  // end while
+
+        // Increment the target screen pointer and index.
+        scrptr = scrptr + ((width - w)>>1);
+        scry++;
+    } // end for scry
+}
+
+void Display::drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap)
+{
+    int16_t w = *bitmap;
+	int16_t h = *(bitmap + 1);
+    bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
+    /** visibility check */
+    if (y<-h || y>height) return; //invisible
+    if (x<-w || x>width) return;  //invisible
+    /** 1 bpp mode */
+    if (m_colordepth<2) {
+    int16_t i, j, byteNum, bitNum, byteWidth = (w + 7) >> 3;
+    for (i = 0; i < w; i++) {
+        byteNum = i / 8;
+        bitNum = i % 8;
+        for (j = 0; j < h; j++) {
+            uint8_t source = *(bitmap + j * byteWidth + byteNum);
+            if (source & (0x80 >> bitNum)) {
+                drawPixel(x + w - i, y + j);
+            }
+        }
+    }
+
+    return;
+    }
+    /** 2 bpp mode */
+    if (m_colordepth<4) {
+    int16_t i, j, byteNum, bitNum, byteWidth = w >> 2;
+    for (i = 0; i < w; i++) {
+        byteNum = i / 4;
+        bitNum = (i % 4)<<1;
+        for (j = 0; j < h; j++) {
+            uint8_t source = *(bitmap + j * byteWidth + byteNum);
+            uint8_t output = (source & (0xC0 >> bitNum));
+            output >>= (6-bitNum);
+            if (output != invisiblecolor) {
+                setColor(output);
+                drawPixel(x + i, y + j);
+            }
+        }
+    }
+
+    return;
+    }
+    /** 4bpp fast version */
+	int16_t scrx,scry,xclip,xjump,scrxjump;
+    xclip=xjump=scrxjump=0;
+    /** y clipping */
+    if (y<0) { h+=y; bitmap -= y*(w>>1); y=0;}
+    else if (y+h>height) { h -=(y-height);}
+    /** x clipping */
+    bitmap += ((w>>1)-1); //inverted!
+    if (x<0) {
+            xclip=(x&1)<<1;
+            w+=x;
+            xjump = ((-x)>>1);
+            //bitmap += xjump; // do not clip left edge of source, as bitmap is inverted !
+            x=0;
+            }
+    else if (x+w>width) {
+            xclip = (x&1)<<1;
+            scrxjump = x&1;
+            xjump=((x+w-width)>>1)+scrxjump;
+            w = width-x;}
+
+    //uint8_t* scrptr = m_scrbuf + (y*(width>>1) + ((x+width)>>1));
+    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+    /** ONLY 4-bit mode for time being **/
+    for (scry = y; scry < y+h; scry+=1) {
+    //    for (scry = y; scry < y+2; scry+=1) {
+            if (scry>=height) return;
+            if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
+                //for (scrx = w+x-xclip-1; scrx >= x; scrx-=2) {
+                for (scrx = x; scrx < w+x-xclip; scrx+=2) {
+                    uint8_t sourcepixel = *(bitmap);
+                    if (xclip) {
+                            sourcepixel <<=4;
+                            sourcepixel |= ((*(bitmap-1))>>4);//inverted!
+                    }
+                    uint8_t targetpixel = *scrptr;
+                    // NIBBLES ARE INVERTED BECAUSE PICTURE IS FLIPPED !!!
+                    if ((sourcepixel>>4) != invisiblecolor ) targetpixel = (targetpixel&0xF0) | (sourcepixel>>4);
+                    if ((sourcepixel&0x0F) != invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel<<4);
+                    *scrptr = targetpixel;
+                    bitmap--;
+                    scrptr++;
+                }
+                bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
+                if (xclip){
+                    if (w&1) {
+                        /**last pixel is odd pixel due to clipping & odd width*/
+                        uint8_t sourcepixel = *bitmap;
+                        if ((sourcepixel&0x0F) != invisiblecolor) {
+                            sourcepixel <<=4;
+                            uint8_t targetpixel = *scrptr;// & 0x0F;
+                            targetpixel |= sourcepixel;
+                            *scrptr = targetpixel;
+                        }
+                        //scrptr++;
+                    }
+                    bitmap++;
+                    scrptr++;
+                }
+                bitmap += xjump; // needed if x<0 clipping occurs
+            } else { /** ODD pixel starting line **/
+                for (scrx = x; scrx < w+x-xclip; scrx+=2 ) {
+                    uint8_t sourcepixel = *bitmap;
+                    uint8_t targetpixel = *scrptr;
+                    // inverted !!! store lower nibble of source pixel in lower nibble of target
+                    if((sourcepixel&0x0F)!=invisiblecolor) targetpixel = (targetpixel & 0xF0) | (sourcepixel & 0x0F );
+                    *scrptr = targetpixel;
+                    scrptr++;
+                    targetpixel = *scrptr;
+                    // inverted ! store higher nibble of source pixel in higher nibble of target
+                    if((sourcepixel>>4)!=invisiblecolor) targetpixel = (targetpixel & 0x0F) | (sourcepixel & 0xF0);
+                    *scrptr = targetpixel;
+                    bitmap--;
+                }
+                bitmap += w; // w*2 >> 1 because inverted and because 2 pixels per byte!!
+                bitmap+=xjump;
+            }
+            // increment the y jump in the scrptr
+            scrptr = scrptr + ((width - w)>>1)+scrxjump;
+    }
+}
+
+void Display::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip) {
+#if PROJ_GAMEBUINO == 0
+    if (!flip) drawBitmap(x,y,bitmap);
+    else drawBitmapXFlipped(x,y,bitmap);
+#else
+	if((rotation == NOROT) && (flip == NOFLIP)){
+		drawBitmap(x,y,bitmap); //use the faster algorithm
+		return;
+	}
+	uint8_t w = bitmap[0];
+	uint8_t h = bitmap[1];
+	bitmap = bitmap + 2; //add an offset to the pointer to start after the width and height
+    int8_t i, j, //coordinates in the raw bitmap
+            k, l, //coordinates in the rotated/flipped bitmap
+            byteNum, bitNum, byteWidth = (w + 7) >> 3;
+
+    rotation %= 4;
+
+    for (i = 0; i < w; i++) {
+        byteNum = i / 8;
+        bitNum = i % 8;
+        for (j = 0; j < h; j++) {
+            if (bitmap[j * byteWidth + byteNum] & (B10000000 >> bitNum)) {
+                switch (rotation) {
+                    case NOROT: //no rotation
+                        k = i;
+                        l = j;
+                        break;
+                    case ROTCCW: //90° counter-clockwise
+                        k = j;
+                        l = w - i - 1;
+                        break;
+                    case ROT180: //180°
+                        k = w - i - 1;
+                        l = h - j - 1;
+                        break;
+                    case ROTCW: //90° clockwise
+                        k = h - j - 1;
+                        l = i;
+                        break;
+                }
+                if (flip) {
+                    flip %= 4;
+                    if (flip & B00000001) { //horizontal flip
+                        k = w - k;
+                    }
+                    if (flip & B00000010) { //vertical flip
+                        l = h - l;
+                    }
+                }
+                k += x; //place the bitmap on the screen
+                l += y;
+                drawPixel(k, l);
+            }
+        }
+    }
+#endif //PROJ_GAMEBUINO
+
+}
+
+uint8_t* Display::getBuffer() {
+    return m_scrbuf;
+}
+
+uint8_t Display::getBitmapPixel(const uint8_t* bitmap, uint16_t x, uint16_t y) {
+    uint16_t w = *bitmap;
+    uint8_t sourcebyte = bitmap[2+(y * ((w+7)>>3))+ (x>>3)];
+    return sourcebyte & (0x80>>(x&7));
+}
+
+int Display::print_char(uint8_t x, uint8_t y, unsigned char c) {
+	c -= font[2];
+	if (m_mode) return directChar(x,y,c);
+	return bufferChar(x,y,c);
+}
+
+void Display::drawChar(int8_t x, int8_t y, unsigned char c, uint8_t size) {
+	print_char(x,y,c);
+	return;
+}
+
+
+bool Display::isDirectPrintingEnabled() {
+    return m_mode;
+}
+
+void Display::enableDirectPrinting(uint8_t m) {
+    if (m) {
+            m_mode=true;
+            m_w = POK_LCD_W;
+            m_h = POK_LCD_H;
+    } else {
+            m_mode=false;
+            m_w = getWidth();
+            m_h = getHeight();
+    }
+}
+
+void Display::write(uint8_t c) {
+	int charstep=0;
+	if(font[3]) {
+        // only caps in this font
+        if (c>=97) c-=32;
+	}
+	switch(c) {
+		case '\0':			//null
+			break;
+		case '\n':			//line feed
+			cursorX = 0;
+			inc_txtline();
+			break;
+		case 8:				//backspace
+			cursorX -= font[0];
+			charstep=print_char(cursorX,cursorY,' ');
+			break;
+		case 13:			//carriage return
+			cursorX = 0;
+			break;
+		case 14:			//form feed new page(clear screen)
+			//clear_screen();
+			break;
+		default:
+			if (cursorX >= (m_w - font[0])) {
+				cursorX = 0;
+				if (textWrap) inc_txtline();
+				else return; // stop outputting text
+				charstep=print_char(cursorX,cursorY,c);
+			}
+			else
+				charstep=print_char(cursorX,cursorY,c);
+			if (c==' ' && adjustCharStep) charstep=(charstep>>1)+1;
+			cursorX += charstep;
+	}
+}
+
+void Display::inc_txtline() {
+	if (cursorY > m_h - 2*font[1]) //= (height - (font[1]+1)))
+		#if SCROLL_TEXT > 0
+		scroll(font[1] + adjustLineStep);
+		#else
+		cursorY = 0;
+		#endif
+	else
+		cursorY += font[1] + adjustLineStep;
+}
+
+/* default implementation: may be overridden */
+void Display::write(const char *str)
+{
+  while (*str)
+    write(*str++);
+}
+
+/* default implementation: may be overridden */
+void Display::write(const uint8_t *buffer, uint8_t size)
+{
+  while (size--)
+    write(*buffer++);
+}
+
+void Display::print(const char str[])
+{
+  write(str);
+}
+
+void Display::print(char c, int base)
+{
+  print((long) c, base);
+}
+
+void Display::print(unsigned char b, int base)
+{
+  print((unsigned long) b, base);
+}
+
+void Display::print(int n, int base)
+{
+  print((long) n, base);
+}
+
+void Display::print(unsigned int n, int base)
+{
+  print((unsigned long) n, base);
+}
+
+void Display::print(long n, int base)
+{
+  if (base == 0) {
+    write(n);
+  } else if (base == 10) {
+    if (n < 0) {
+      print('-');
+      n = -n;
+    }
+    printNumber(n, 10);
+  } else {
+    printNumber(n, base);
+  }
+}
+
+void Display::print(unsigned long n, int base)
+{
+  if (base == 0) write(n);
+  else printNumber(n, base);
+}
+
+void Display::print(double n, int digits)
+{
+  printFloat(n, digits);
+}
+
+void Display::println(void)
+{
+  print('\r');
+  print('\n');
+}
+
+void Display::println(const char c[])
+{
+  print(c);
+  println();
+}
+
+void Display::println(char c, int base)
+{
+  print(c, base);
+  println();
+}
+
+void Display::println(unsigned char b, int base)
+{
+  print(b, base);
+  println();
+}
+
+void Display::println(int n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Display::println(unsigned int n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Display::println(long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Display::println(unsigned long n, int base)
+{
+  print(n, base);
+  println();
+}
+
+void Display::println(double n, int digits)
+{
+  print(n, digits);
+  println();
+}
+
+void Display::set_cursor(uint8_t x, uint8_t y) {
+	cursorX = x;
+	cursorY = y;
+}
+
+void Display::print(uint8_t x, uint8_t y, const char str[]) {
+	cursorX = x;
+	cursorY = y;
+	write(str);
+
+}
+void Display::print(uint8_t x, uint8_t y, char c, int base) {
+	cursorX = x;
+	cursorY = y;
+	print((long) c, base);
+}
+void Display::print(uint8_t x, uint8_t y, unsigned char b, int base) {
+	cursorX = x;
+	cursorY = y;
+	print((unsigned long) b, base);
+}
+void Display::print(uint8_t x, uint8_t y, int n, int base) {
+	cursorX = x;
+	cursorY = y;
+	print((long) n, base);
+}
+void Display::print(uint8_t x, uint8_t y, unsigned int n, int base) {
+	cursorX = x;
+	cursorY = y;
+	print((unsigned long) n, base);
+}
+void Display::print(uint8_t x, uint8_t y, long n, int base) {
+	cursorX = x;
+	cursorY = y;
+	print(n,base);
+}
+void Display::print(uint8_t x, uint8_t y, unsigned long n, int base) {
+	cursorX = x;
+	cursorY = y;
+	print(n,base);
+}
+void Display::print(uint8_t x, uint8_t y, double n, int digits) {
+	cursorX = x;
+	cursorY = y;
+	print(n,digits);
+}
+
+void Display::println(uint8_t x, uint8_t y, const char c[])
+{
+	cursorX = x;
+	cursorY = y;
+	print(c);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, char c, int base)
+{
+	cursorX = x;
+	cursorY = y;
+	print(c, base);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, unsigned char b, int base)
+{
+	cursorX = x;
+	cursorY = y;
+	print(b, base);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, int n, int base)
+{
+	cursorX = x;
+	cursorY = y;
+	print(n, base);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, unsigned int n, int base)
+{
+	cursorX = x;
+	cursorY = y;
+	print(n, base);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, long n, int base)
+{
+	cursorX = x;
+	cursorY = y;
+	print(n, base);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, unsigned long n, int base)
+{
+	cursorX = x;
+	cursorY = y;
+	print(n, base);
+	println();
+}
+
+void Display::println(uint8_t x, uint8_t y, double n, int digits)
+{
+	cursorX = x;
+	cursorY = y;
+	print(n, digits);
+	println();
+}
+
+void Display::printNumber(unsigned long n, uint8_t base)
+{
+  unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
+  unsigned long i = 0;
+
+  if (n == 0) {
+    print('0');
+    return;
+  }
+
+  while (n > 0) {
+    buf[i++] = n % base;
+    n /= base;
+  }
+
+  for (; i > 0; i--)
+    print((char) (buf[i - 1] < 10 ?
+      '0' + buf[i - 1] :
+      'A' + buf[i - 1] - 10));
+}
+
+void Display::printFloat(double number, uint8_t digits)
+{
+  // Handle negative numbers
+  if (number < 0.0)
+  {
+     print('-');
+     number = -number;
+  }
+
+  // Round correctly so that print(1.999, 2) prints as "2.00"
+  double rounding = 0.5;
+  for (uint8_t i=0; i<digits; ++i)
+    rounding /= 10.0;
+
+  number += rounding;
+
+  // Extract the integer part of the number and print it
+  unsigned long int_part = (unsigned long)number;
+  double remainder = number - (double)int_part;
+  print(int_part);
+
+  // Print the decimal point, but only if there are digits beyond
+  if (digits > 0)
+    print(".");
+
+  // Extract digits from the remainder one at a time
+  while (digits-- > 0)
+  {
+    remainder *= 10.0;
+    int toPrint = int(remainder);
+    print(toPrint);
+    remainder -= toPrint;
+  }
+}
+
+void Display::draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap)
+{
+    int8_t scry;
+    uint8_t* scrptr = m_scrbuf + (y*(width>>1) + (x>>1));
+
+    /** ONLY 4-bit mode for time being **/
+
+            if ((x&1)==0) { /** EVEN pixel starting line, very simple, just copypaste **/
+                for (scry = y; scry < h+y; scry++) {
+                    uint8_t sourcepixel = *bitmap;
+                    uint8_t targetpixel = *scrptr;
+                    targetpixel = (targetpixel&0x0F) | (sourcepixel << 4);
+                    *scrptr = targetpixel;
+                    bitmap++;
+                    scrptr+=55;
+                }
+            } else { /** ODD pixel starting line **/
+                for (scry = y; scry < h+y; scry++) {
+                    uint8_t sourcepixel = *bitmap;
+                    uint8_t targetpixel = *scrptr;
+                    // store source pixel in lower nibble of target
+                    targetpixel = (targetpixel & 0xF0) | (sourcepixel);
+                    *scrptr = targetpixel;
+                    scrptr+=55;
+                    bitmap++;
+                }
+            }
+}
+
+/**
+ * Setup or disable the sprite. Note that enabled sprites must always have subsequent indices, starting from the index zero.
+ * You cannot have gaps in indices of enabled sprites.
+ * The max number of sprites can be changed by a SPRITE_COUNT define, the default is 4.
+ * Note: the sprites currently work only in the 220 x 176 x 2bpp mode.
+ * @param index The sprite index. The lower index is drawn first, i.e. is on bottom.
+ * @param bitmap A pointer to a 2bpp bitmap. A NULL value means that the sprite is disabled. The ownership is not transferred, so the caller must keep the bitmap alive.
+ * @param palette4x16bit Four color palette of 16bit elements. The first color value is considered as transparent. The palette is copied to the sprite struct, so the caller do not have to keep it alive.
+ * @param x The initial x
+ * @param y The initial y
+ * @param doResetDirtyRect (default=true) True, if the previous coordinates are reseted.
+ */
+void Display::setSpriteBitmap(uint8_t index, const uint8_t* bitmap,  const uint16_t* palette4x16bit, int16_t x, int16_t y, bool doResetDirtyRect ) {
+
+    setSprite(index, &(bitmap[2]), palette4x16bit, x, y, bitmap[0], bitmap[1], doResetDirtyRect);
+}
+
+/**
+ * Setup or disable the sprite. Note that enabled sprites must always have subsequent indices, starting from the index zero.
+ * You cannot have gaps in indices of enabled sprites.
+ * The max number of sprites can be changed by a SPRITE_COUNT define, the default is 4.
+ * Note: the sprites currently work only in the 220 x 176 x 2bpp mode.
+ * @param index The sprite index. The lower index is drawn first, i.e. is on bottom. Note that
+ * @param data A pointer to a 2bpp pixel data of size w x h. A NULL value means that the sprite is disabled. The ownership is not transferred, so the caller must keep the data alive.
+ * @param palette4x16bit Four color palette of 16bit elements. The first color value is considered as transparent. The palette is copied to the sprite struct, so the caller do not have to keep it alive.
+ * @param x The initial x
+ * @param y The initial y
+ * @param w Width
+ * @param h Height
+ */
+void Display::setSprite(uint8_t index, const uint8_t* data, const uint16_t* palette4x16bit, int16_t x, int16_t y, uint8_t w, uint8_t h, bool doResetDirtyRect ) {
+
+    if(index >= SPRITE_COUNT) return;
+    m_sprites[index].bitmapData = data;
+    m_sprites[index].x = x;
+    m_sprites[index].y = y;
+    if (doResetDirtyRect) {
+        m_sprites[index].oldx = x;
+        m_sprites[index].oldy = y;
+    }
+    m_sprites[index].w = w;
+    m_sprites[index].h = h;
+    memcpy(m_sprites[index].palette, palette4x16bit, 4*2);
+}
+
+/**
+ * Set the sprite position.
+ * @param index The sprite index
+ * @param x
+ * @param y
+ */
+void Display::setSpritePos(uint8_t index, int16_t x, int16_t y) {
+
+    if(index >= SPRITE_COUNT) return;
+    m_sprites[index].x = x;
+    m_sprites[index].y = y;
+}
+
+void Display::lcdRefresh(unsigned char* scr, bool useDirectDrawMode) {
+
+#if POK_SCREENMODE == MODE_HI_4COLOR
+    // If there is one or more sprites, use sprite enabled drawing.
+    if (m_sprites[0].bitmapData != NULL)
+        lcdRefreshMode1Spr(scr, 0, 0, LCDWIDTH, LCDHEIGHT, paletteptr, m_sprites, useDirectDrawMode);
+    else if (!useDirectDrawMode)
+        lcdRefreshMode1(m_scrbuf, 0, 0, LCDWIDTH, LCDHEIGHT, paletteptr);
+#endif
+
+    // For the screen modes that do not support sprites, return if the direct draw mode is used.
+    if (useDirectDrawMode) return;
+
+#if POK_SCREENMODE == MODE_GAMEBOY
+    lcdRefreshModeGBC(scr, paletteptr);
+#endif
+
+#if POK_SCREENMODE == MODE_FAST_16COLOR
+    lcdRefreshMode2(scr, paletteptr);
+#endif
+
+#if POK_SCREENMODE == MODE_GAMEBUINO_16COLOR
+    lcdRefreshGB(scr, paletteptr);
+#endif
+
+#if POK_SCREENMODE == MODE_ARDUBOY_16COLOR
+    lcdRefreshAB(scr, paletteptr);
+#endif
+
+}
+
+void Display::setFrameBufferTo(uint8_t* sb) {
+    m_scrbuf = sb;
+};
+
+void Display::setTileBufferTo(uint8_t* tb) {
+    m_tilebuf = tb;
+};
+
+void Display::loadTileset(const uint8_t* ts) {
+    m_tileset = (uint8_t*) ts;
+};
+
+void Display::setTile(uint16_t i, uint8_t t) {
+    if (!m_tilebuf) return;
+    m_tilebuf[i]=t;
+};
+
+
+/** Eof */
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoDisplay.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,430 @@
+/**************************************************************************/
+/*!
+    @file     PokittoDisplay.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+
+/* THE SEGMENT BELOW PERTAINS TO CIRCLE DRAWING FUNCTIONS ONLY
+*
+This is the core graphics library for all our displays, providing a common
+set of graphics primitives (points, lines, circles, etc.).  It needs to be
+paired with a hardware-specific library for each display device we carry
+(to handle the lower-level functions).
+Adafruit invests time and resources providing this open source code, please
+support Adafruit & open-source hardware by purchasing products from Adafruit!
+Copyright (c) 2013 Adafruit Industries.  All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+- Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+- Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef POKITTODISPLAY_H
+#define POKITTODISPLAY_H
+
+#include <stdint.h>
+#include "Pokitto_settings.h"
+#include "PokittoGlobs.h"
+#include "PokittoFonts.h"
+#include "PokittoPalettes.h"
+
+// Basic Color definitions
+#define	COLOR_BLACK                         (uint16_t)(0x0000)
+#define	COLOR_BLUE                          (uint16_t)(0x001F)
+#define	COLOR_RED                           (uint16_t)(0xF800)
+#define	COLOR_GREEN                         (uint16_t)(0x07E0)
+#define COLOR_CYAN                          (uint16_t)(0x07FF)
+#define COLOR_MAGENTA                       (uint16_t)(0xF81F)
+#define COLOR_YELLOW                        (uint16_t)(0xFFE0)
+#define COLOR_WHITE                         (uint16_t)(0xFFFF)
+
+// Grayscale Values
+#define COLOR_GRAY_15                       (uint16_t)(0x0861)    //  15  15  15
+#define COLOR_GRAY_30                       (uint16_t)(0x18E3)    //  30  30  30
+#define COLOR_GRAY_50                       (uint16_t)(0x3186)    //  50  50  50
+#define COLOR_GRAY_80                       (uint16_t)(0x528A)    //  80  80  80
+#define COLOR_GRAY_128                      (uint16_t)(0x8410)    // 128 128 128
+#define COLOR_GRAY_200                      (uint16_t)(0xCE59)    // 200 200 200
+#define COLOR_GRAY_225                      (uint16_t)(0xE71C)    // 225 225 225
+
+/** The tables below are palettes, that resemble the Pico 8 palette*/
+
+enum defcolors {
+    C_BLACK,
+    C_DARKBLUE,
+    C_PURPLE,
+    C_DARKGREEN,
+
+    C_BROWN,
+    C_DARKBROWN,
+    C_LIGHTGRAY,
+    C_WHITE,
+
+    C_RED,
+    C_ORANGE,
+    C_YELLOW,
+    C_GREEN,
+
+    C_BLUE,
+    C_DARKGRAY,
+    C_PINK,
+    C_PEACH
+};
+
+const uint16_t def565palette[16] = {
+    //kind of like pico8 palette
+    0,0x194a,0x792a,0x42a,
+    0xaa86,0x5aa9,0xc618,0xff9d,
+    0xf809,0xfd00,0xff84,0x72a,
+    0x2d7f,0x83b3,0xfbb5,0xfe75
+};
+
+#define PALETTE_SIZE 256
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+namespace Pokitto {
+
+class Display {
+public:
+    Display();
+
+    // PROPERTIES
+private:
+    static uint8_t* canvas;
+    static uint8_t bpp;
+    static uint8_t m_colordepth;
+public:
+    static uint8_t palOffset;
+    static uint8_t width;
+    static uint8_t height;
+    static uint8_t screenbuffer[];
+
+    // PROPERTIES
+    static void setColorDepth(uint8_t);
+    static uint8_t getColorDepth();
+    static uint8_t getBitsPerPixel();
+    static uint16_t getWidth();
+    static uint16_t getHeight();
+    static uint8_t getNumberOfColors();
+
+    // IMPORTANT PUBLIC STATE MEMBERS
+    /** Selected font */
+    static const unsigned char * font;
+    /** Set if screen is cleared between updates or not*/
+    static uint8_t persistence;
+    /** Selected drawing color */
+    static uint16_t color;
+    /** Selected background color */
+    static uint16_t bgcolor;
+    /** Selected invisible color */
+    static uint16_t invisiblecolor;
+    /** Direct unbuffered color */
+    static uint16_t directcolor;
+    /** Direct unbuffered background color */
+    static uint16_t directbgcolor;
+    /** Direct text rotated */
+    static bool directtextrotated;
+    /** clip rect on screen**/
+    static int16_t clipX;
+    static int16_t clipY;
+    static int16_t clipW;
+    static int16_t clipH;
+    /** set color with a command */
+    static void setColor(uint8_t);
+    /** set color and bgcolor with a command */
+    static void setColor(uint8_t,uint8_t);
+    /** set invisiblecolor with a command */
+    static void setInvisibleColor(uint16_t);
+    /** get color */
+    static uint8_t getColor();
+    /** get background color */
+    static uint8_t getBgColor();
+    /** get invisible color */
+    static uint16_t getInvisibleColor();
+    /** set clip rect on screen**/
+    static void setClipRect(int16_t x, int16_t y, int16_t w, int16_t h);
+
+    /** Initialize display */
+    static void begin();
+    /** Clear display buffer */
+    static void clear();
+    /** Scroll by x lines */
+    static void scroll(int16_t);
+    /** Fill display buffer */
+    static void fillScreen(uint16_t);
+    /** Send display buffer to display hardware */
+    static void update(bool useDirectMode=false, uint8_t updRectX=0, uint8_t updRectY=0, uint8_t updRectW=LCDWIDTH, uint8_t updRectH=LCDHEIGHT);
+    /** Forced update of LCD display memory with a given pixel buffer */
+    static void lcdRefresh(unsigned char*, bool useDirectMode=false);
+    /** Clear LCD hardware memory */
+    static void clearLCD();
+    /** Fill LCD hardware memory */
+    static void fillLCD(uint16_t);
+    /** Show Pokitto logo at startup*/
+    static void showLogo();
+    /** Point to another screenbuffer instead of the default one */
+    static void setFrameBufferTo(uint8_t*);
+
+    // COLORS AND PALETTE
+public:
+    /** set default palette */
+    static void setDefaultPalette();
+    /** master palette */
+    static uint16_t palette[PALETTE_SIZE];
+    /** runtime palette pointer */
+    static uint16_t *paletteptr;
+    /** convert RGB to 565 color value */
+    static uint16_t RGBto565(uint8_t,uint8_t,uint8_t);
+    /** linear interpolation between colors */
+    static uint16_t interpolateColor(uint16_t, uint16_t, uint8_t);
+    /** load an R,G,B triplet palette */
+    static void loadRGBPalette(const unsigned char*);
+    /** load a ready-made 565 palette */
+    static void load565Palette(const uint16_t*);
+    /** rotate palette by step */
+    static void rotatePalette(int8_t);
+    /** tween between two palettes **/
+    static void tweenPalette(uint16_t*, const uint16_t*, const uint16_t*, uint8_t);
+
+    // DIRECT DRAWING (NO BUFFERING)
+    /** Direct pixel (not through display buffer) */
+    static void directPixel(int16_t,int16_t,uint16_t);
+    /** Direct tile 16bit (not through display buffer) */
+	static void directTile(int16_t x, int16_t y, int16_t x2, int16_t y2, uint16_t* gfx);
+    /** Direct rectangle (not through display buffer) */
+    static void directRectangle(int16_t, int16_t,int16_t, int16_t, uint16_t);
+    /** Set the cursor for printing to a certain screen position */
+    static void setCursor(int16_t,int16_t);
+    /** direct bitmap to screen (no buffering) */
+    static void directBitmap(int16_t,int16_t,const uint8_t*, uint8_t,uint8_t);
+
+
+    // DRAWING METHODS
+    /** Draw pixel at various bit depths */
+    static void drawPixel(int16_t,int16_t);
+    /** Draw pixel with specific color index at various bit depths */
+    static void drawPixel(int16_t x,int16_t y, uint8_t col);
+    /** Get pixel at various bit depths */
+    static uint8_t getPixel(int16_t,int16_t);
+    /** Draw line **/
+    static void drawLine(int16_t,int16_t,int16_t,int16_t);
+    /** Clip line with screen boundaries, returns 0 if whole line is out of bounds */
+    static uint8_t clipLine(int16_t*, int16_t*, int16_t*, int16_t*);
+    /** Draw a column real fast */
+    static void drawColumn(int16_t, int16_t, int16_t);
+    /** Map a 1-bit column real fast */
+    static void map1BitColumn(int16_t, int16_t, int16_t, const uint8_t*, uint16_t);
+    /** Draw a row real fast */
+    static void drawRow(int16_t, int16_t, int16_t);
+    /** Legacy drawColumn name, for compatibility - macros are not OK because of scope problems */
+    static void drawFastVLine(int16_t, int16_t, int16_t);
+    /** Legacy drawRow name, for compatibility - macros are not OK because of scope problems */
+    static void drawFastHLine(int16_t, int16_t, int16_t);
+    /** Draw rectangle (edges only) */
+    static void drawRectangle(int16_t,int16_t,int16_t,int16_t);
+    /** Fill rectangle */
+    static void fillRectangle(int16_t,int16_t,int16_t,int16_t);
+    /** GB compatibility fillRect */
+    static void fillRect(int16_t x, int16_t y, int16_t w, int16_t h);
+    /** GB compatibility drawRect */
+    static void drawRect(int16_t x, int16_t y, int16_t w, int16_t h);
+
+    // Functions lifted from Adafruit GFX library (see PokittoDisplay.h for license //
+    /** Draw circle */
+    static void drawCircle(int16_t x0, int16_t y0, int16_t r);
+    /** Draw circle helper */
+	static void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername);
+	/** Fill circle */
+	static void fillCircle(int16_t x0, int16_t y0, int16_t r);
+	/** Fill circle helper*/
+	static void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint16_t cornername, int16_t delta);
+	/** draw triangle */
+	static void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
+	/** Fill triangle*/
+	static void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2);
+	/** Draw rounded rectangle */
+	static void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius);
+	/** Fill rounded rectangle */
+	static void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius);
+
+    // BITMAPS !
+    /** Draw monochromatic bitmap. Used in font rendering */
+    static void drawMonoBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t index);
+    /** Draw bitmap data*/
+    static void drawBitmapData(int16_t x, int16_t y, int16_t w, int16_t h, const uint8_t* bitmap);
+    /** Draw bitmap */
+    static void drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap);
+    /** Draw RLE bitmap */
+    static void drawRleBitmap(int16_t x, int16_t y, const uint8_t* bitmap);
+    /** Draw animated bitmap frame */
+    static void drawBitmap(int16_t x, int16_t y, const uint8_t* bitmap, uint8_t frame);
+    /** Draw bitmap flipped on x-axis*/
+    static void drawBitmapXFlipped(int16_t x, int16_t y, const uint8_t* bitmap);
+    /** Draw bitmap with options */
+    static void drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t rotation, uint8_t flip);
+    /** Get pointer to the screen buffer - GB compatibility */
+    static uint8_t* getBuffer();
+    /** Get pixel in a monochromatic bitmap - GB compatibility */
+    static uint8_t getBitmapPixel(const uint8_t*, uint16_t, uint16_t);
+    /** Optimized functions for drawing bit columns - used in raytracing */
+    static void draw4BitColumn(int16_t x, int16_t y, uint8_t h, uint8_t* bitmap);
+
+    // SPRITES
+    /* Setup or disable the sprite */
+    static void setSpriteBitmap(uint8_t index, const uint8_t* bitmap, const uint16_t* palette4x16bit, int16_t x, int16_t y, bool doResetDirtyRect=true );
+    /* Setup or disable the sprite */
+    static void setSprite(uint8_t index, const uint8_t* data, const uint16_t* palette4x16bit, int16_t x, int16_t y, uint8_t w, uint8_t h, bool doResetDirtyRect=true );
+    /* Set the sprite position */
+    static void setSpritePos(uint8_t index, int16_t x, int16_t y);
+
+    // PRINTING
+    /** direct character to screen (no buffering) */
+    static int directChar(int16_t, int16_t, uint16_t);
+    /** character to screenbuffer */
+    static int bufferChar(int16_t, int16_t, uint16_t);
+    /** set the active font */
+    static void setFont(const unsigned char * f);
+    /** font dimensions */
+    static uint8_t fontWidth, fontHeight;
+    /** text wrapping */
+    static bool textWrap;
+    /** GB compatibility drawChar */
+    static void drawChar(int8_t x, int8_t y, unsigned char c, uint8_t size);
+
+    static void enableDirectPrinting(uint8_t m);
+    static bool isDirectPrintingEnabled();
+    static int print_char(uint8_t x, uint8_t y, unsigned char c);
+    static void set_cursor(uint8_t, uint8_t);
+    static void write(uint8_t);
+    static void write(const char *str);
+    static void write(const uint8_t *buffer, uint8_t size);
+    static void print(const char[]);
+    static void print(char, int base = 0);
+    static void print(unsigned char, int base = 0);
+    static void print(int, int base = 10);
+    static void print(unsigned int, int base = 10);
+    static void print(long, int base = 10);
+    static void print(unsigned long, int base = 10);
+    static void print(double, int base = 2);
+    static void print(uint8_t, uint8_t, const char[]);
+    static void print(uint8_t, uint8_t, char, int = 0);
+    static void print(uint8_t, uint8_t, unsigned char, int = 0);
+    static void print(uint8_t, uint8_t, int, int = 10);
+    static void print(uint8_t, uint8_t, unsigned int, int = 10);
+    static void print(uint8_t, uint8_t, long, int = 10);
+    static void print(uint8_t, uint8_t, unsigned long, int = 10);
+    static void print(uint8_t, uint8_t, double, int = 2);
+    static void println(uint8_t, uint8_t, const char[]);
+    static void println(uint8_t, uint8_t, char, int = 0);
+    static void println(uint8_t, uint8_t, unsigned char, int = 0);
+    static void println(uint8_t, uint8_t, int, int = 10);
+    static void println(uint8_t, uint8_t, unsigned int, int = 10);
+    static void println(uint8_t, uint8_t, long, int = 10);
+    static void println(uint8_t, uint8_t, unsigned long, int = 10);
+    static void println(uint8_t, uint8_t, double, int = 2);
+    static void println(uint8_t, uint8_t);
+    static void println(const char[]);
+    static void println(char, int = 0);
+    static void println(unsigned char, int = 0);
+    static void println(int, int = 10);
+    static void println(unsigned int, int = 10);
+    static void println(long, int = 10 );
+    static void println(unsigned long, int = 10);
+    static void println(double, int = 2);
+    static void println(void);
+
+    static int16_t cursorX,cursorY;
+    static uint8_t fontSize;
+    static int8_t adjustCharStep, adjustLineStep;
+	static bool fixedWidthFont;
+
+    static void inc_txtline();
+    static void printNumber(unsigned long, uint8_t);
+    static void printFloat(double, uint8_t);
+
+    /** Tiled mode functions **/
+
+    static void loadTileset(const uint8_t*);
+
+    static void setTileBufferTo(uint8_t*);
+    static void clearTileBuffer();
+    static void shiftTileBuffer(int8_t,int8_t);
+
+    static void setTile(uint16_t,uint8_t);
+    static uint8_t getTile(uint16_t);
+    static uint8_t getTile(uint8_t,uint8_t);
+
+
+
+private:
+    static uint8_t m_mode;
+    static uint16_t m_w,m_h; // store these for faster access when switching printing modes
+    /** Pointer to screen buffer */
+    static uint8_t* m_scrbuf;
+    /** Pointer to tileset */
+    static uint8_t* m_tileset;
+    /** Pointer to tilebuffer */
+    static uint8_t* m_tilebuf;
+    /** Pointer to tilecolorbuffer */
+    static uint8_t* m_tilecolorbuf;
+    /** Sprites */
+    static SpriteInfo m_sprites[SPRITE_COUNT];  // Does not own sprite bitmaps
+};
+
+}
+
+#endif // POKITTODISPLAY_H
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoFakeavr.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,106 @@
+/**************************************************************************/
+/*!
+    @file     PokittoFakeavr.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef _POKITTO_FAKEAVR_H_
+#define _POKITTO_FAKEAVR_H_
+
+#include "PokittoItoa.h"
+#include "binary.h"
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef POK_SIM
+#include <stdbool.h>
+#else
+#include <stdbool.h>
+#endif // POK_SIM
+
+#define _BV(bit) (1 << (bit)) //jonne
+
+/** data types */
+#ifndef _RPCNDR_H
+typedef bool boolean;
+#endif
+typedef uint8_t byte;
+
+/** PROGMEM */
+#define PROGMEM
+//#define F
+
+/** AVR program memory string functions **/
+#define sprintf_P sprintf
+#define strstr_P strstr
+#define strcpy_P strcpy
+
+#define utoa pokItoa
+#define ultoa pokItoa
+
+/** PROGMEM hacks **/
+#define PROGMEM
+    #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
+    #ifndef WIN32
+    #define pgm_read_word(addr) (*(addr))
+    #else
+    #define pgm_read_word(addr) (*(const unsigned int *)(addr))
+    #endif // WIN32
+
+/** min max & others **/
+
+
+#ifndef DISABLEAVRMIN
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif // DISABLEAVRMIN
+#define __avrmax(a,b) ((a)>(b)?(a):(b))
+#define __avrmin(a,b) ((a)<(b)?(a):(b))
+#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
+#define min2(a,b) (((a)<(b))?(a):(b))
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void cli();
+void sei();
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoFonts.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,68 @@
+/**************************************************************************/
+/*!
+    @file     PokittoFonts.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POK_FONTS_H
+#define POK_FONTS_H
+
+#include "Pokitto_settings.h"
+
+extern const unsigned char fontMini[];
+extern const unsigned char fontDonut[];
+extern const unsigned char fontDragon[];
+extern const unsigned char fontKarateka[];
+extern const unsigned char fontKoubit[];
+extern const unsigned char fontRunes[];
+extern const unsigned char fontTight[];
+extern const unsigned char fontTiny[];
+extern const unsigned char fontAdventurer[];
+extern const unsigned char font5x7[];
+extern const unsigned char font3x5[];
+extern const unsigned char font3x3[];
+extern const unsigned char fontC64[];
+extern const unsigned char fntC64UIGfx[];
+extern const unsigned char fontZXSpec[];
+extern const unsigned char fontTIC806x6[];
+
+#if POK_GAMEBUINO_SUPPORT > 0
+#define DEFAULT_FONT font3x5
+#else
+#define DEFAULT_FONT font5x7
+#endif // POK_GAMEBUINO_SUPPORT
+
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoGlobs.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,91 @@
+/**************************************************************************/
+/*!
+    @file     PokittoGlobs.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POKITTO_GLOBS_H
+#define POKITTO_GLOBS_H
+
+#include <stdint.h>
+
+#ifdef POK_SIM
+    #include "SimLCD.h"
+    #include "SimSound.h"
+    #include "PokittoSimulator.h"
+#else
+    #include "mbed.h"
+    #include "HWLCD.h"
+    #include "HWSound.h"
+#endif // POK_SIM
+
+extern int random(int);
+extern int random(int,int);
+
+#define HIGH    1
+#define LOW     0
+
+#define swapWT(type, a, b)    \
+{               \
+    type _t_;   \
+    _t_ = a;    \
+    a = b;      \
+    b = _t_;    \
+}
+
+#define SAMPLE_RATE POK_AUD_FREQ //was 16000, was 57000
+#define NUMFRAMES 570 //1 ms before refresh was 357
+
+
+// TODO: move these into some suitable place
+extern void fakeISR();
+extern void audio_IRQ();
+extern void update_SDAudioStream();
+extern uint16_t soundbyte;
+
+#if POK_STREAMING_MUSIC
+    #define SPEAKER 3
+   // #define BUFFER_SIZE 512 //5120 // was 256
+    extern unsigned char buffers[][BUFFER_SIZE];
+    extern volatile int currentBuffer, oldBuffer;
+    extern volatile int bufindex, vol;
+    extern volatile unsigned char * currentPtr;
+    extern volatile unsigned char * endPtr;
+    extern int8_t streamvol;
+    extern uint32_t streamcounter;
+    extern uint8_t streamstep;
+#endif
+
+#endif // POKITTO_GLOBS_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoItoa.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,141 @@
+/**************************************************************************/
+/*!
+    @file     PokittoItoa.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoItoa.h"
+#include <string.h>
+#include <stdint.h>
+
+
+void pokItoa(uint16_t value, char *str, int base)
+{
+    /** pokItoa:  convert value n to characters
+     * Needed to emulate AVR LibC non-standard functions, this is a very fast version of itoa
+     *
+     * @param value unsigned integer to be converted
+     * @param *str pointer to string where function stores the result as characters
+     * @param base (not implemented in this function, base is always 10)
+     */
+
+    char *p = str;
+    uint8_t v;
+    if (value > 499)
+    {
+        if (value > 799)
+        {
+            if (value > 999)
+            {
+                // Treated as a special case as there
+                // are only 24 values above 999
+                *p++ = '1';
+                *p++ = '0';
+                uint8_t v = value - 1000;
+
+                if      (v > 19) { *p++ = '2'; v -= 20; }
+                else if (v >  9) { *p++ = '1'; v -= 10; }
+                else             { *p++ = '0'; }
+
+                *p++ = v + '0';
+                *p = 0;
+                return;
+            }
+
+            if (value > 899) { *p++ = '9'; v = value - 900; }
+            else             { *p++ = '8'; v = value - 800; }
+        }
+        else
+        {
+            if      (value > 699) { *p++ = '7'; v = value - 700; }
+            else if (value > 599) { *p++ = '6'; v = value - 600; }
+            else                  { *p++ = '5'; v = value - 500; }
+        }
+    }
+    else
+    {
+        if (value > 299)
+        {
+            if (value > 399) { *p++ = '4'; v = value - 400; }
+            else             { *p++ = '3'; v = value - 300; }
+        }
+        else
+        {
+            if      (value > 199) { *p++ = '2'; v = value - 200; }
+            else if (value >  99) { *p++ = '1'; v = value - 100; }
+            else                  {             v = value; }
+        }
+    }
+
+    if (v > 49)
+    {
+        if (v > 69)
+        {
+            if      (v > 89) { *p++ = '9'; v -= 90; }
+            else if (v > 79) { *p++ = '8'; v -= 80; }
+            else             { *p++ = '7'; v -= 70; }
+        }
+        else
+        {
+            if (v > 59) { *p++ = '6'; v -= 60; }
+            else        { *p++ = '5'; v -= 50; }
+        }
+    }
+    else
+    {
+        if (v > 19)
+        {
+            if      (v > 39) { *p++ = '4'; v -= 40; }
+            else if (v > 29) { *p++ = '3'; v -= 30; }
+            else             { *p++ = '2'; v -= 20; }
+        }
+        else
+        {
+            if      (v >  9)   { *p++ = '1'; v -= 10; }
+            else if (p != str) { *p++ = '0'; }
+        }
+    }
+
+    *p++ = v + '0';
+    *p = 0;
+}
+
+void pokUtoa(uint16_t value, char *str, int base) {
+    pokItoa(value,str,base);
+}
+
+void pokLtoa(long value, char *str, int base) {
+    pokItoa(value,str,base);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoItoa.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,51 @@
+/**************************************************************************/
+/*!
+    @file     PokittoItoa.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+#ifndef POKITTO_ITOA_H
+#define POKITTO_ITOA_H
+
+#include <stdint.h>
+
+/** MBED online compiler has no itoa or strrev **/
+
+extern void pokItoa(uint16_t, char*,int);
+extern void pokUtoa(int16_t, char*,int);
+extern void pokLtoa(long, char*,int);
+
+#endif // POKITTO_ITOA_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoLogos.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,115 @@
+/**************************************************************************/
+/*!
+    @file     PokittoLogos.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2015, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+#include "PokittoLogos.h"
+
+const uint8_t Pokitto_speaker[] = {
+16,16,
+0x00,0x00,0x01,0x00,0x03,0x00,0x05,0x04,0x09,0x12,0x71,0x4A,0x71,0x2A,0x71,0x2A,0x71,0x2A,0x71,0x2A,0x71,0x4A,0x09,0x12,0x05,0x04,0x03,0x00,0x01,0x00,0x00,0x00
+};
+
+const uint8_t Pokitto_headphones[] = {
+16,16,
+0x00,0x00,0x0F,0xF0,0x18,0x18,0x10,0x08,0x20,0x04,0x20,0x04,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x70,0x0E,0x20,0x04,0x00,0x04,0x00,0x08,0x00,0x04,0x00,0x08
+};
+
+const uint8_t Pokitto_volumebar[] = {
+4,4,
+0xE0,0xE0,0xE0,0xE0
+};
+
+const uint8_t Pokitto_logo[] = {
+184,56,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x84,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0x00,0x7F,0xC0,0x0F,0xF8,0x00,0x00,0x01,0x72,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF0,0x00,0x03,0xFC,0x00,0x7F,0xC0,0x1F,0xF0,0x00,0x00,0x01,0x4A,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xF0,0x00,0x07,0xFC,0x00,0x7F,0xC0,0x1F,0xF0,0x00,0x00,0x01,0x72,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x07,0xFC,0x00,0xFF,0x80,0x3F,0xE0,0x00,0x00,0x01,0x4A,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x0F,0xF8,0x00,0xFF,0x80,0x3F,0xE0,0x00,0x00,0x01,0x02,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x0F,0xF8,0x01,0xFF,0x00,0x7F,0xC0,0x00,0x00,0x00,0x84,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0x1F,0xF0,0x01,0xFF,0x00,0x7F,0xC0,0x00,0x00,0x00,0x78,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x1F,0xF0,0x03,0xFE,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0x00,0x3F,0xE0,0x03,0xFE,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x80,0x00,0x00,0x00,0x07,0xFC,0x01,0xFF,0x80,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0x00,0x00,0x00,0x00,0x07,0xFC,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0x00,0x00,0x00,0x00,0x0F,0xFC,0x03,0xFF,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x0F,0xFF,0xE0,0x01,0xFF,0xFC,0x03,0xFF,0xFF,0xFC,0xFF,0x9F,0xEF,0xFF,0xFB,0xFF,0xFF,0x0F,0xFF,0xE0,0x00,
+0x00,0x00,0xCF,0xFF,0xF0,0x09,0xFF,0xFE,0x03,0xFF,0xFF,0xFC,0xFF,0x9F,0xEF,0xFF,0xFB,0xFF,0xFE,0x27,0xFF,0xF0,0x00,
+0x00,0x01,0xCF,0xFF,0xF8,0x1D,0xFF,0xFF,0x03,0xFF,0xFF,0xF9,0xFF,0x3F,0xF7,0xFF,0xFD,0xFF,0xFE,0x67,0xFF,0xF8,0x00,
+0x00,0x01,0xEF,0xFF,0xFC,0x1D,0xFF,0xFF,0x03,0xFF,0xFF,0xF9,0xFF,0x3F,0xF7,0xFF,0xFD,0xFF,0xFC,0xF7,0xFF,0xFC,0x00,
+0x00,0x03,0xE7,0xFF,0xFC,0x3C,0xFF,0xFF,0x8B,0xFF,0xFF,0xF3,0xFE,0x3F,0xF3,0xFF,0xFC,0xFF,0xFC,0xF3,0xFF,0xFC,0x00,
+0x00,0x03,0xE7,0xFF,0xFC,0x3E,0xFF,0xFF,0x89,0xFF,0xFF,0xF3,0xFE,0x7F,0xFB,0xFF,0xFE,0xFF,0xF9,0xF3,0xFF,0xFC,0x00,
+0x00,0x07,0xF7,0xFF,0xFC,0x7E,0xFF,0xFF,0x99,0xFF,0xFF,0xF3,0xFE,0x7F,0xF9,0xFF,0xFE,0x7F,0xF9,0xFB,0xFF,0xFC,0x00,
+0x00,0x07,0xF3,0xFF,0xFC,0x7E,0x7F,0xFF,0x9D,0xFF,0xFF,0xE7,0xFC,0x7F,0xFC,0x7F,0xFF,0x1F,0xF3,0xF9,0xFF,0xFC,0x00,
+0x00,0x0F,0xF0,0x07,0xFC,0xFE,0x00,0xFF,0x3D,0xFE,0x00,0x07,0xFC,0x00,0xFF,0x00,0x3F,0xC0,0x03,0xF8,0x03,0xF8,0x00,
+0x00,0x0F,0xF0,0x07,0xF8,0xFE,0x00,0xFF,0x3C,0xFE,0x00,0x0F,0xF8,0x00,0xFF,0x80,0x3F,0xE0,0x07,0xF8,0x07,0xF8,0x00,
+0x00,0x0F,0xF0,0x0F,0xF9,0xFE,0x01,0xFE,0x7C,0xFE,0x00,0x0F,0xF8,0x01,0xFF,0x00,0x7F,0xE0,0x07,0xF8,0x07,0xF8,0x00,
+0x00,0x1F,0xE0,0x0F,0xF1,0xFC,0x01,0xFE,0x7E,0xFF,0x00,0x1F,0xF0,0x01,0xFF,0x00,0x7F,0xC0,0x0F,0xF0,0x0F,0xF0,0x00,
+0x00,0x1F,0xE0,0x1F,0xF3,0xFC,0x03,0xFC,0xFE,0x7F,0x00,0x1F,0xF0,0x03,0xFE,0x00,0xFF,0xC0,0x0F,0xF0,0x0F,0xF0,0x00,
+0x00,0x3F,0xC0,0x1F,0xE3,0xF8,0x03,0xFC,0xFE,0x7F,0x80,0x3F,0xE0,0x03,0xFE,0x00,0xFF,0x80,0x1F,0xE0,0x0F,0xE0,0x00,
+0x00,0x3F,0xC0,0x3F,0xE7,0xF8,0x07,0xF8,0xFF,0x3F,0x80,0x3F,0xE0,0x07,0xFE,0x00,0xFF,0x80,0x1F,0xE0,0x1F,0xE0,0x00,
+0x00,0x7F,0x80,0x3F,0xC7,0xF0,0x07,0xF9,0xFF,0x3F,0xC0,0x7F,0xC0,0x07,0xFC,0x01,0xFF,0x00,0x1F,0xC0,0x1F,0xC0,0x00,
+0x00,0x7F,0x80,0x7F,0xC7,0xF0,0x0F,0xF1,0xFF,0x1F,0xE0,0x7F,0xC0,0x0F,0xFC,0x01,0xFF,0x00,0x3F,0xC0,0x3F,0xC0,0x00,
+0x00,0x7F,0x80,0x7F,0x8F,0xF0,0x0F,0xF3,0xFE,0x1F,0xF0,0xFF,0x80,0x0F,0xF8,0x03,0xFE,0x00,0x3F,0x80,0x3F,0x80,0x00,
+0x00,0xFF,0x80,0x7F,0x8F,0xF0,0x0F,0xE3,0xFE,0x0F,0xF8,0xFF,0x80,0x0F,0xF8,0x03,0xFE,0x00,0x3F,0xC0,0x3F,0x80,0x00,
+0x00,0xFF,0xFE,0x7F,0x1F,0xFF,0xEF,0xE7,0xFC,0x0F,0xF9,0xFF,0x00,0x1F,0xF0,0x07,0xFC,0x00,0x7F,0xFF,0x3F,0x80,0x00,
+0x01,0xFF,0xFF,0x7E,0x1F,0xFF,0xE7,0xC7,0xFC,0x07,0xF9,0xFF,0x00,0x1F,0xF0,0x07,0xFC,0x00,0x7F,0xFF,0xBF,0x00,0x00,
+0x01,0xFF,0xFF,0x3E,0x1F,0xFF,0xE7,0xCF,0xF8,0x07,0xF9,0xFF,0x00,0x3F,0xE0,0x0F,0xF8,0x00,0x7F,0xFF,0x9E,0x00,0x00,
+0x01,0xFF,0xFF,0x3C,0x1F,0xFF,0xF7,0x87,0xF8,0x03,0xF3,0xFE,0x00,0x3F,0xE0,0x0F,0xF8,0x00,0x7F,0xFF,0x9E,0x00,0x00,
+0x03,0xFF,0xFF,0xB8,0x0F,0xFF,0xF3,0x07,0xF0,0x01,0xF3,0xFE,0x00,0x7F,0xC0,0x1F,0xF0,0x00,0x3F,0xFF,0xDC,0x00,0x00,
+0x03,0xFF,0xFF,0x98,0x0F,0xFF,0xF3,0x03,0xF0,0x00,0xE7,0xFC,0x00,0x7F,0xC0,0x1F,0xF0,0x00,0x3F,0xFF,0xCC,0x00,0x00,
+0x07,0xFF,0xFF,0x90,0x07,0xFF,0xFA,0x03,0xF0,0x00,0xE7,0xFC,0x00,0xFF,0x80,0x3F,0xF0,0x00,0x1F,0xFF,0xC8,0x00,0x00,
+0x07,0xFF,0xFF,0x80,0x03,0xFF,0xF8,0x00,0xE0,0x00,0x47,0xF8,0x00,0xFF,0x80,0x3F,0xE0,0x00,0x03,0xFF,0xC0,0x00,0x00,
+0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x0F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x1F,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoLogos.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,49 @@
+/**************************************************************************/
+/*!
+    @file     PokittoLogos.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2015, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POKITTO_LOGOS_H
+#define POKITTO_LOGOS_H
+
+#include <stdint.h>
+
+extern const uint8_t Pokitto_logo[];
+extern const uint8_t Pokitto_headphones[];
+extern const uint8_t Pokitto_speaker[];
+extern const uint8_t Pokitto_volumebar[];
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoPalette.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,127 @@
+/**************************************************************************/
+/*!
+    @file     PokittoPalette.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoDisplay.h"
+#include "Pokitto_settings.h"
+#include "GBcompatibility.h"
+#include <stdio.h>
+#include <string.h>
+
+#ifndef POK_SIM
+#include "HWLCD.h"
+#else
+#include "SimLCD.h"
+#endif
+
+using namespace Pokitto;
+
+
+void Display::loadRGBPalette(const unsigned char* p) {
+    for (int i=0;i<PALETTE_SIZE;i++) palette[i] = RGBto565(p[i*3], p[i*3+1],p[i*3+2]);
+    paletteptr = palette;
+}
+
+void Display::load565Palette(const uint16_t* p) {
+    for (int i=0;i<PALETTE_SIZE;i++) palette[i] = p[i];
+    paletteptr = palette;
+}
+
+void Display::rotatePalette(int8_t step) {
+    uint16_t tpal[PALETTE_SIZE];
+    if (step == 0) return;
+    step = 0-step;
+    if (step>0) {
+        for (int i=step;i<PALETTE_SIZE;i++) tpal[i]=palette[i-step]; // palette revolves up, new color 1 becomes old color 0
+        for (int i=0; i < step; i++) tpal[i]=palette[PALETTE_SIZE-step+i]; // overflow topmost values to bottom of new palette
+    } else {
+        for (int i=0;i<PALETTE_SIZE+step;i++)
+        {
+            tpal[i]=palette[i-step];
+            }// palette revolves down, new color 0 becomes old color 1
+        for (int i=0;i<-step; i++) {
+                tpal[PALETTE_SIZE+step+i]=palette[i];
+        }
+        // overflow bottom values to top of new palette
+    }
+    for (int i=0; i<PALETTE_SIZE;i++) palette[i] = tpal[i];
+}
+
+uint16_t Display::RGBto565(uint8_t R,uint8_t G,uint8_t B) {
+    uint16_t color;
+    color = B>>3;
+    color |= ((G >> 2) << 5);
+    color |= ((R >> 3) << 11);
+    return color;
+}
+
+uint16_t Display::interpolateColor(uint16_t c1, uint16_t c2, uint8_t factor) {
+    int16_t R,G,B;
+    int16_t dR,dG,dB;
+    uint16_t color;
+
+    B = (c1 & 0x1F);
+    dB = (c2 & 0x1F)-B;
+    dB = (dB*factor)>>8;
+    B += dB;
+    if (B<0) B = 0;
+
+    G = ((c1>>5) & 0x3F);
+    dG = ((c2>>5) & 0x3F)-G;
+    dG = (dG*factor)>>8;
+    G += dG;
+    if (G<0) G=0;
+
+    R = (c1>>11);
+    dR = (c2>>11)-R;
+    dR = (dR*factor)>>8;
+    R += dR;
+    if (R<0) R=0;
+
+    color = B;
+    color |= (G << 5);
+    color |= (R << 11);
+    return color;
+}
+
+void Display::tweenPalette(uint16_t* ram_pal, const uint16_t* pal_1, const uint16_t* pal_2, uint8_t factor) {
+    for (uint8_t i = 0; i<16 ; i++) {
+        ram_pal[i] = interpolateColor(pal_1[i],pal_2[i],factor);
+    }
+}
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoPalettes.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,25 @@
+#ifndef POK_PALETTES_H
+#define POK_PALETTES_H
+
+#include "Pokitto_settings.h"
+
+extern const unsigned char paletteDefault[];
+extern const unsigned char paletteCGA[];
+extern const unsigned char paletteNeon[];
+extern const unsigned char palettePico[];
+extern const unsigned char paletteCopper[];
+extern const unsigned char paletteAction[];
+extern const unsigned char paletteMagma[];
+extern const unsigned char paletteRainbow[];
+extern const unsigned char paletteMono[];
+extern const unsigned char paletteGameboy[];
+extern const unsigned char paletteZXSpec[];
+extern const unsigned char paletteDB16[];
+
+
+#define POK_DEFAULT_PALETTE paletteCGA
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoSound.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,915 @@
+/**************************************************************************/
+/*!
+    @file     PokittoSound.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+/*
+ * NOTE:
+ * API of the Pokitto Sound library is partially identical to the Gamebuino Sound API.
+ * Due to the difference in architecture (ARM Cortex-M0+ in mbed environment vs. 8-bit AVR)
+ * large parts are not identical. Most functions were rewritten, with only API remaining.
+ * We want to give attribution to the original author's project:
+ *
+ * License for Gamebuino-identical code:
+ *
+ * (C) Copyright 2014 Aur�lien Rodot. All rights reserved.
+ *
+ * This file is part of the Gamebuino Library (http://gamebuino.com)
+ *
+ * The Gamebuino Library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+#include "PokittoSound.h"
+#include "Pokitto_settings.h"
+#include "PokittoCore.h"
+#include "Synth.h"
+
+#ifndef POK_SIM
+#include "HWSound.h"
+#else
+#include "SimSound.h"
+#include "PokittoSimulator.h"
+#endif
+
+typedef uint8_t byte;
+
+using namespace Pokitto;
+
+Pokitto::Core _soundc;
+
+uint8_t Sound::prescaler;
+uint16_t Sound::globalVolume;
+uint16_t Sound::volumeMax = VOLUME_HEADPHONE_MAX;
+
+bool Sound::trackIsPlaying[NUM_CHANNELS];
+bool Sound::patternIsPlaying[NUM_CHANNELS];
+uint8_t Sound::outputPitch[NUM_CHANNELS];
+int8_t Sound::outputVolume[NUM_CHANNELS];
+
+uint16_t *Sound::trackData[NUM_CHANNELS];
+uint8_t Sound::trackCursor[NUM_CHANNELS];
+uint16_t **Sound::patternSet[NUM_CHANNELS];
+int8_t Sound::patternPitch[NUM_CHANNELS];
+
+// pattern data
+uint16_t *Sound::patternData[NUM_CHANNELS];
+uint16_t **Sound::instrumentSet[NUM_CHANNELS];
+bool Sound::patternLooping[NUM_CHANNELS];
+uint16_t Sound::patternCursor[NUM_CHANNELS];
+
+// note data
+uint8_t Sound::notePitch[NUM_CHANNELS];
+uint8_t Sound::noteDuration[NUM_CHANNELS];
+int8_t Sound::noteVolume[NUM_CHANNELS];
+bool Sound::notePlaying[NUM_CHANNELS];
+
+// commands data
+int8_t Sound::commandsCounter[NUM_CHANNELS];
+int8_t Sound::volumeSlideStepDuration[NUM_CHANNELS];
+int8_t Sound::volumeSlideStepSize[NUM_CHANNELS];
+uint8_t Sound::arpeggioStepDuration[NUM_CHANNELS];
+int8_t Sound::arpeggioStepSize[NUM_CHANNELS];
+uint8_t Sound::tremoloStepDuration[NUM_CHANNELS];
+int8_t Sound::tremoloStepSize[NUM_CHANNELS];
+
+// instrument data
+uint16_t *Sound::instrumentData[NUM_CHANNELS];
+uint8_t Sound::instrumentLength[NUM_CHANNELS]; //number of steps in the instrument
+uint8_t Sound::instrumentLooping[NUM_CHANNELS]; //how many steps to loop on when the last step of the instrument is reached
+uint16_t Sound::instrumentCursor[NUM_CHANNELS]; //which step is being played
+uint8_t Sound::instrumentNextChange[NUM_CHANNELS]; //how many frames before the next step
+
+//current step data
+int8_t Sound::stepVolume[NUM_CHANNELS];
+uint8_t Sound::stepPitch[NUM_CHANNELS];
+uint8_t Sound::chanVolumes[NUM_CHANNELS];
+
+#if (POK_ENABLE_SOUND < 1)
+ #define NUM_CHANNELS 0
+#endif
+
+#if(NUM_CHANNELS > 0)
+    #ifndef POK_SIM
+        uint8_t sbyte;
+    #else
+    uint8_t sbyte;
+    float pwm1;
+    #endif // POK_SIM
+
+//declare these variables globally for faster access
+uint8_t _rand = 1;
+uint8_t _chanCount[NUM_CHANNELS]; //counts until the next change of the waveform
+bool _chanState[NUM_CHANNELS]; //if the waveform is currently high or low
+uint8_t _chanHalfPeriod[NUM_CHANNELS]; //duration of half the period of the waveform
+uint8_t _chanOutputVolume[NUM_CHANNELS]; //amplitude of the outputted waveform
+uint8_t _chanOutput[NUM_CHANNELS]; //current value of the outputted waveform
+bool _chanNoise[NUM_CHANNELS]; //if a random value should be added to the waveform to generate noise
+
+#if POK_GBSOUND > 0
+const uint16_t squareWaveInstrument[]  = {0x0101, 0x03F7};
+const uint16_t noiseInstrument[]  = {0x0101, 0x03FF};
+const uint16_t* const defaultInstruments[]  = {squareWaveInstrument,noiseInstrument};
+
+const uint16_t playOKPattern[]  = {0x0005,0x138,0x168,0x0000};
+const uint16_t playCancelPattern[]  = {0x0005,0x168,0x138,0x0000};
+const uint16_t playTickP[]  = {0x0045,0x168,0x0000};
+#endif
+#if(EXTENDED_NOTE_RANGE > 0)
+//extended note range
+#define NUM_PITCH 59
+const uint8_t _halfPeriods[NUM_PITCH] = {246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,104,98,92,87,82,78,73,69,65,62,58,55,52,49,46,44,41,39,37,35,33,31,29,28,26,25,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6};
+#else
+//regular note range
+#define NUM_PITCH 36
+const uint8_t _halfPeriods[NUM_PITCH] = {246,232,219,207,195,184,174,164,155,146,138,130,123,116,110,104,98,92,87,82,78,73,69,65,62,58,55,52,49,46,44,41,39,37,35,33};
+#endif
+
+#endif
+
+void Pokitto::audio_IRQ() {
+    #if POK_STREAMING_MUSIC > 0
+        #if POK_STREAMFREQ_HALVE > 0
+        streamstep = 1-streamstep;
+        #else
+        streamstep=1;
+        #endif
+
+        streamstep &= streamon; //check if stream is on
+
+        if(streamvol && streamstep) {
+            uint8_t output = (*currentPtr++);
+            sbyte = output;
+        } else {
+            sbyte = 0; // duty cycle
+        }
+
+        if (currentPtr >= endPtr)
+        {
+        currentBuffer++;
+        if (currentBuffer==4) currentBuffer=0;
+        currentPtr = buffers[currentBuffer];
+        endPtr = currentPtr + BUFFER_SIZE;
+        }
+
+    #endif // POK_STREAMING_MUSIC
+    #if (NUM_CHANNELS > 0)
+	Sound::generateOutput();
+    #endif
+}
+
+void Sound::volumeUp() {
+    if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()+VOLUME_STEP*2);
+    else setVolume(getVolume()+VOLUME_STEP);
+}
+
+void Sound::volumeDown() {
+    if (globalVolume>VOLUME_HEADPHONE_MAX) setVolume(getVolume()-VOLUME_STEP*4);
+    else setVolume(getVolume()-VOLUME_STEP);
+}
+
+
+void Sound::setMaxVol(int16_t v) {
+    if (v < 0) v = 0; //prevent nasty wraparound
+    if (v > VOLUME_SPEAKER_MAX) {
+            v = VOLUME_SPEAKER_MAX;
+    }
+    volumeMax = v;
+    setVolume(globalVolume);
+}
+
+uint16_t Sound::getMaxVol() {
+    return volumeMax;
+}
+
+void Sound::updateStream() {
+    #if POK_STREAMING_MUSIC
+    if (oldBuffer != currentBuffer) {
+        if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE);
+        else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE);
+        else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE);
+        else fileReadBytes(&buffers[2][0],BUFFER_SIZE);
+        oldBuffer = currentBuffer;
+        streamcounter += BUFFER_SIZE;
+    }
+
+    #ifndef POK_SIM
+    if ( streamcounter > fs.fsize - (BUFFER_SIZE)) {
+    #else
+    if ( streamcounter > getFileLength() - (BUFFER_SIZE)) {
+    #endif
+        streamcounter=0;
+        #if POK_STREAM_LOOP > 0
+        fileRewind();
+        #endif
+        #ifndef POK_SIM
+        streamon=0;
+        #endif // POK_SIM
+    }
+    #endif
+}
+
+void Sound::begin() {
+#if POK_ENABLE_SOUND > 0
+soundInit();
+ampEnable(true);
+#endif
+#if (NUM_CHANNELS > 0)
+#if POK_ENABLE_SOUND > 0
+#if POK_GBSOUND > 0
+	prescaler = 1;
+	for(byte i=0; i<NUM_CHANNELS; i++){
+		chanVolumes[i] = VOLUME_CHANNEL_MAX;
+		changeInstrumentSet(defaultInstruments, i); //load default instruments. #0:square wave, #1: noise
+		command(CMD_INSTRUMENT, 0, 0, i); //set the default instrument to square wave
+	}
+#endif // POK_GBSOUND
+#endif //POK_ENABLE_SOUND
+#endif
+}
+
+void Sound::playTrack(const uint16_t* track, uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	stopTrack(channel);
+	trackCursor[channel] = 0;
+	trackData[channel] = (uint16_t*)track;
+	trackIsPlaying[channel] = true;
+#endif
+}
+
+void Sound::stopTrack(uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	trackIsPlaying[channel] = false;
+	stopPattern(channel);
+#endif
+}
+
+void Sound::stopTrack(){
+#if(NUM_CHANNELS > 0)
+	for(uint8_t i=0; i<NUM_CHANNELS; i++){
+		stopTrack(i);
+	}
+#endif
+}
+
+void Sound::updateTrack(uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	if(trackIsPlaying[channel] && !patternIsPlaying[channel]){
+		uint16_t data = pgm_read_word(trackData[channel] + trackCursor[channel]);
+		if(data == 0xFFFF){ //en of the track
+			trackIsPlaying[channel] = false;
+			return;
+		}
+		uint8_t patternID = data & 0xFF;
+		data >>= 8;
+		patternPitch[channel] = data;
+		playPattern((const uint16_t*)pgm_read_word(&(patternSet[channel][patternID])), channel);
+		trackCursor[channel] ++;
+	}
+#endif
+}
+
+void Sound::updateTrack(){
+#if(NUM_CHANNELS > 0)
+	for (uint8_t i=0; i<NUM_CHANNELS; i++){
+		updateTrack(i);
+	}
+#endif
+}
+
+void Sound::changePatternSet(const uint16_t* const* patterns, uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	patternSet[channel] = (uint16_t**)patterns;
+#endif
+}
+
+void Sound::playPattern(const uint16_t* pattern, uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	stopPattern(channel);
+	patternData[channel] = (uint16_t*)pattern;
+	patternCursor[channel] = 0;
+	patternIsPlaying[channel] = true;
+	noteVolume[channel] = 9;
+	//reinit commands
+	volumeSlideStepDuration[channel] = 0;
+	arpeggioStepDuration[channel] = 0;
+	tremoloStepDuration[channel] = 0;
+#endif
+}
+
+void Sound::updatePattern(){
+#if(NUM_CHANNELS > 0)
+	for (uint8_t i=0; i<NUM_CHANNELS; i++){
+		updatePattern(i);
+	}
+#endif
+}
+
+void Sound::changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	instrumentSet[channel] = (uint16_t**)instruments;
+#endif
+}
+
+void Sound::updatePattern(uint8_t i){
+#if(NUM_CHANNELS > 0)
+	if(i>=NUM_CHANNELS)
+		return;
+	if(patternIsPlaying[i]){
+		if(noteDuration[i]==0){//if the end of the previous note is reached
+
+			uint16_t data = pgm_read_word(patternCursor[i] + patternData[i]);
+
+			if(data == 0){ //end of the pattern reached
+				if(patternLooping[i] == true){
+					patternCursor[i] = 0;
+					data = pgm_read_word(patternCursor[i] + patternData[i]);
+				}
+				else{
+					patternIsPlaying[i] = false;
+					if(trackIsPlaying[i]){ //if this pattern is part of a track, get the next pattern
+						updateTrack(i);
+						data = pgm_read_word(patternCursor[i] + patternData[i]);
+					} else {
+						stopNote(i);
+						//Serial.print("pattern end\n");
+						return;
+					}
+				}
+			}
+
+			while (data & 0x0001){ //read all commands and instrument changes
+				data >>= 2;
+				//Serial.print("\ncmd\t");
+				uint8_t cmd = data & 0x0F;
+				data >>= 4;
+				uint8_t X = data & 0x1F;
+				data >>= 5;
+				int8_t Y = data - 16;
+				command(cmd,X,Y,i);
+				patternCursor[i]++;
+				data = pgm_read_word(patternCursor[i] + patternData[i]);
+			}
+			data >>= 2;
+
+			uint8_t pitch = data & 0x003F;
+			data >>= 6;
+
+			uint8_t duration = data;
+			if(pitch != 63){
+			}
+
+			playNote(pitch, duration, i);
+
+			patternCursor[i]++;
+		}
+	}
+#endif
+}
+
+void Sound::stopPattern(uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	stopNote(channel);
+	patternIsPlaying[channel] = false;
+#endif
+}
+
+void Sound::stopPattern(){
+#if(NUM_CHANNELS > 0)
+	for(uint8_t i=0; i<NUM_CHANNELS; i++){
+		stopPattern(i);
+	}
+#endif
+}
+
+void Sound::command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t i){
+#if(NUM_CHANNELS > 0)
+	if(i>=NUM_CHANNELS)
+		return;
+	switch(cmd){
+	case CMD_VOLUME: //volume
+	    X = constrain((int8_t)X, 0, 10);
+		noteVolume[i] = X;
+		break;
+	case CMD_INSTRUMENT: //instrument
+		instrumentData[i] = (uint16_t*)pgm_read_word(&(instrumentSet[i][X]));
+		instrumentLength[i] = pgm_read_word(&(instrumentData[i][0])) & 0x00FF; //8 LSB
+		instrumentLength[i] *= prescaler;
+		instrumentLooping[i] = min2((pgm_read_word(&(instrumentData[i][0])) >> 8), instrumentLength[i]); //8 MSB - check that the loop is shorter than the instrument length
+		instrumentLooping[i] *= prescaler;
+		break;
+	case CMD_SLIDE: //volume slide
+		volumeSlideStepDuration[i] = X * prescaler;
+		volumeSlideStepSize[i] = Y;
+		break;
+	case CMD_ARPEGGIO:
+		arpeggioStepDuration[i] = X * prescaler;
+		arpeggioStepSize[i] = Y;
+		break;
+	case CMD_TREMOLO:
+		tremoloStepDuration[i] = X * prescaler;
+		tremoloStepSize[i] = Y;
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
+void Sound::playNote(uint8_t pitch, uint8_t duration, uint8_t channel){
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	//set note
+	notePitch[channel] = pitch;
+	noteDuration[channel] = duration * prescaler;
+	//reinit vars
+	instrumentNextChange[channel] = 0;
+	instrumentCursor[channel] = 0;
+	notePlaying[channel] = true;
+	_chanState[channel] = true;
+	commandsCounter[channel] = 0;
+#endif
+}
+
+void Sound::stopNote(uint8_t channel) {
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	notePlaying[channel] = false;
+	//counters
+	noteDuration[channel] = 0;
+	instrumentCursor[channel] = 0;
+	commandsCounter[channel] = 0;
+	//output
+	_chanOutput[channel] = 0;
+	_chanOutputVolume[channel] = 0;
+	_chanState[channel] = false;
+	updateOutput();
+#endif
+}
+
+void Sound::stopNote() {
+#if(NUM_CHANNELS > 0)
+	for (uint8_t channel = 0; channel < NUM_CHANNELS; channel++) {
+		stopNote(channel);
+	}
+#endif
+}
+
+void Sound::updateNote() {
+#if(NUM_CHANNELS > 0)
+	for (uint8_t i = 0; i < NUM_CHANNELS; i++) {
+		updateNote(i);
+	}
+#endif
+}
+
+void Sound::updateNote(uint8_t i) {
+#if(NUM_CHANNELS > 0)
+	if(i>=NUM_CHANNELS)
+		return;
+	if (notePlaying[i]) {
+
+		if(noteDuration[i] == 0){
+			stopNote(i);
+			//Serial.println("note end");
+			return;
+		} else {
+			noteDuration[i]--;
+		}
+
+		if (instrumentNextChange[i] == 0) {
+
+			//read the step data from the progmem and decode it
+			uint16_t thisStep = pgm_read_word(&(instrumentData[i][1 + instrumentCursor[i]]));
+
+			stepVolume[i] = thisStep & 0x0007;
+			thisStep >>= 3;
+
+			uint8_t stepNoise = thisStep & 0x0001;
+			thisStep >>= 1;
+
+			uint8_t stepDuration = thisStep & 0x003F;
+			thisStep >>= 6;
+
+			stepPitch[i] = thisStep;
+
+			//apply the step settings
+			instrumentNextChange[i] = stepDuration * prescaler;
+
+			_chanNoise[i] = stepNoise;
+
+
+			instrumentCursor[i]++;
+
+			if (instrumentCursor[i] >= instrumentLength[i]) {
+				if (instrumentLooping[i]) {
+					instrumentCursor[i] = instrumentLength[i] - instrumentLooping[i];
+				} else {
+					stopNote(i);
+				}
+			}
+		}
+		instrumentNextChange[i]--;
+
+		commandsCounter[i]++;
+
+		//UPDATE VALUES
+		//pitch
+		outputPitch[i] = notePitch[i] + stepPitch[i] + patternPitch[i];
+		if(arpeggioStepDuration[i]){
+		  outputPitch[i] += commandsCounter[i] / arpeggioStepDuration[i] * arpeggioStepSize[i];
+		}
+		outputPitch[i] = (outputPitch[i] + NUM_PITCH) % NUM_PITCH; //wrap
+		//volume
+		outputVolume[i] = noteVolume[i];
+		if(volumeSlideStepDuration[i]){
+		  outputVolume[i] += commandsCounter[i] / volumeSlideStepDuration[i] * volumeSlideStepSize[i];
+		}
+		if(tremoloStepDuration[i]){
+			outputVolume[i] += ((commandsCounter[i]/tremoloStepDuration[i]) % 2) * tremoloStepSize[i];
+		}
+		outputVolume[i] = constrain(outputVolume[i], 0, 9);
+		if(notePitch[i] == 63){
+			outputVolume[i] = 0;
+		}
+		// jonnehw noInterrupts();
+		_chanHalfPeriod[i] = pgm_read_byte(_halfPeriods + outputPitch[i]);
+		_chanOutput[i] = _chanOutputVolume[i] = outputVolume[i] * (globalVolume>>GLOBVOL_SHIFT) * chanVolumes[i] * stepVolume[i];
+		//Serial.println(outputVolume[i]);
+		// jonnehw interrupts();
+	}
+#endif
+}
+
+void Sound::setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod) {
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	_chanHalfPeriod[channel] = halfPeriod;
+	_chanState[channel] = false;
+	_chanCount[channel] = 0;
+	updateOutput();
+#endif
+}
+
+
+void Sound::generateOutput() {
+#if(NUM_CHANNELS > 0)
+	bool outputChanged = false;
+	//no for loop here, for the performance sake (this function runs 15 000 times per second...)
+	//CHANNEL 0
+	if (_chanOutputVolume[0]) {
+		_chanCount[0]++;
+		if (_chanCount[0] >= _chanHalfPeriod[0]) {
+			outputChanged = true;
+			_chanState[0] = !_chanState[0];
+			_chanCount[0] = 0;
+			if (_chanNoise[0]) {
+				_rand = 67 * _rand + 71;
+				_chanOutput[0] = _rand % _chanOutputVolume[0];
+			}
+		}
+	}
+
+
+	//CHANNEL 1
+	#if (NUM_CHANNELS > 1)
+	if (_chanOutputVolume[1]) {
+		_chanCount[1]++;
+		if (_chanCount[1] >= _chanHalfPeriod[1]) {
+			outputChanged = true;
+			_chanState[1] = !_chanState[1];
+			_chanCount[1] = 0;
+			if (_chanNoise[1]) {
+				_rand = 67 * _rand + 71;
+				_chanOutput[1] = _rand % _chanOutputVolume[1];
+			}
+		}
+	}
+	#endif
+
+	//CHANNEL 2
+	#if (NUM_CHANNELS > 2)
+	if (_chanOutputVolume[2]) {
+		_chanCount[2]++;
+		if (_chanCount[2] >= _chanHalfPeriod[2]) {
+			outputChanged = true;
+			_chanState[2] = !_chanState[2];
+			_chanCount[2] = 0;
+			if (_chanNoise[2]) {
+				_rand = 67 * _rand + 71;
+				_chanOutput[2] = _rand % _chanOutputVolume[2];
+			}
+		}
+	}
+	#endif
+
+	//CHANNEL 3
+	#if (NUM_CHANNELS > 3)
+	if (_chanOutputVolume[3]) {
+		_chanCount[3]++;
+		if (_chanCount[3] >= _chanHalfPeriod[3]) {
+			outputChanged = true;
+			_chanState[3] = !_chanState[3];
+			_chanCount[3] = 0;
+			if (_chanNoise[3]) {
+				_rand = 67 * _rand + 71;
+				_chanOutput[3] = _rand % _chanOutputVolume[3];
+			}
+		}
+	}
+	#endif
+
+    #if POK_STREAMING_MUSIC
+        if (streamstep) {
+            outputChanged=true;
+        }
+    #endif
+
+	if (outputChanged) {
+		updateOutput();
+	}
+#endif
+}
+
+void Sound::updateOutput() {
+#if(NUM_CHANNELS > 0)
+	uint8_t output = 0;
+
+	//CHANNEL 0
+	if (_chanState[0]) {
+		output += _chanOutput[0];
+	}
+
+	//CHANNEL 1
+	#if (NUM_CHANNELS > 1)
+	if (_chanState[1]) {
+		output += _chanOutput[1];
+	}
+	#endif
+
+	//CHANNEL 2
+	#if (NUM_CHANNELS > 2)
+	if (_chanState[2]) {
+		output += _chanOutput[2];
+	}
+	#endif
+
+	//CHANNEL 3
+	#if (NUM_CHANNELS > 3)
+	if (_chanState[3]) {
+		output += _chanOutput[3];
+	}
+	#endif
+
+    #ifndef POK_SIM
+    #if POK_ENABLE_SOUND
+    /** HARDWARE **/
+
+        #if POK_STREAMING_MUSIC
+            if (streamstep) {
+                pwmout_write(&audiopwm,(float)sbyte/(float)255);
+            }
+        #endif
+            dac_write((uint8_t)output); //direct hardware mixing baby !
+    soundbyte = output;
+    #endif //POK_ENABLE_SOUND
+    #else
+    /** SIMULATOR **/
+        #if POK_STREAMING_MUSIC
+            if (streamstep) {
+                uint16_t o = output + sbyte;
+                output = o/2;
+            }
+        #endif
+        soundbyte = output;
+    #endif // POK_SIM
+#endif
+}
+
+void Sound::setPatternLooping(bool loop, uint8_t channel) {
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	patternLooping[channel] = loop;
+#endif
+}
+
+void Sound::playOK(){
+    #if POK_GBSOUND
+#if(NUM_CHANNELS > 0)
+	playPattern(playOKPattern,0);
+#endif
+#endif // POK_GBSOUND
+}
+
+void Sound::playCancel(){
+#if POK_GBSOUND
+#if(NUM_CHANNELS > 0)
+	playPattern(playCancelPattern,0);
+#endif
+#endif
+}
+
+void Sound::playTick(){
+#if POK_GBSOUND
+#if(NUM_CHANNELS > 0)
+	playPattern(playTickP,0);
+#endif
+#endif // POK_GBSOUND
+}
+
+void Sound::setVolume(int16_t volume) {
+//#if NUM_CHANNELS > 0
+	if (volume<0) volume = 0;
+	if (volume>volumeMax) volume = volumeMax;
+	globalVolume = volume; // % (volumeMax+1);
+	#ifndef POK_SIM
+	volume = (volume / 2)-10;
+	if (volume<0) volume = 0;
+	#if POK_ENABLE_SOUND > 0
+	setHWvolume(volume);
+	#endif
+	#endif
+	#if POK_SHOW_VOLUME > 0
+	_soundc.volbar_visible = VOLUMEBAR_TIMEOUT;
+	#endif
+//#endif
+}
+
+uint16_t Sound::getVolume() {
+//#if NUM_CHANNELS > 0
+	return globalVolume;
+//#else
+//	return 0;
+//#endif
+}
+
+void Sound::setVolume(int8_t volume, uint8_t channel) {
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return;
+	volume = (volume > VOLUME_CHANNEL_MAX) ? VOLUME_CHANNEL_MAX : volume;
+	volume = (volume < 0) ? 0 : volume;
+	chanVolumes[channel] = volume;
+#endif
+}
+
+uint8_t Sound::getVolume(uint8_t channel) {
+#if(NUM_CHANNELS > 0)
+	if(channel>=NUM_CHANNELS)
+		return 255;
+	return (chanVolumes[channel]);
+#else
+	return 0;
+#endif
+}
+
+void Sound::playTone(uint8_t os, int frq, uint8_t amp, uint8_t wav,uint8_t arpmode)
+{
+    if (wav>5) wav=0;
+    if (arpmode>MAX_ARPMODE) arpmode=MAX_ARPMODE;
+    if (os==1) setOSC(&osc1,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
+    else if (os==2) setOSC(&osc2,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
+    else if (os==3) setOSC(&osc3,1,wav,1,0,0,frq,amp,0,0,0,0,0,0,arpmode,0,0);
+}
+
+void Sound::playTone(uint8_t os, uint16_t frq, uint8_t volume, uint32_t duration)
+{
+    if (os==1) setOSC(&osc1,1,WSQUARE,frq,volume,duration);
+    else if (os==2) setOSC(&osc2,1,WTRI,frq,volume,duration);
+    else if (os==3) setOSC(&osc3,1,WTRI,frq,volume,duration);
+}
+
+uint8_t Sound::ampIsOn()
+{
+    #ifdef POK_SIM
+    return core.ampIsOn();
+    #else
+    #if POK_ENABLE_SOUND > 0
+    return Pokitto::ampIsOn();
+    #endif
+    #endif // POK_SIM
+    return 0;
+}
+
+void Sound::ampEnable(uint8_t v) {
+    #ifdef POK_SIM
+    core.ampEnable(v);
+    #else
+    #if POK_ENABLE_SOUND > 0
+    Pokitto::ampEnable(v);
+    #endif
+    #endif // POK_SIM
+
+}
+
+int Sound::playMusicStream(char* filename)
+{
+    return playMusicStream(filename,0);
+}
+
+int Sound::playMusicStream()
+{
+    #if POK_STREAMING_MUSIC >0
+    if (currentPtr) {
+            pokPlayStream();
+            return 1;
+    } else return 0; //no stream
+    #endif // POK_STREAMING_MUSIC
+}
+
+void Sound::pauseMusicStream() {
+    #if POK_ENABLE_SOUND > 0
+    pokPauseStream();
+    #endif
+}
+
+int Sound::playMusicStream(char* filename, uint8_t options)
+{
+    #if POK_STREAMING_MUSIC
+        uint8_t result;
+        result = pokInitSD();
+        if (!isThisFileOpen(filename)) {
+            fileClose(); // close any open files
+            result = fileOpen(filename,FILE_MODE_OVERWRITE | FILE_MODE_BINARY);
+        }
+
+        if (result) {
+                currentPtr = 0; // mark that no stream is available
+                return 0; // opening music file failed
+        }
+
+        fileReadBytes(&buffers[0][0],BUFFER_SIZE);
+        fileReadBytes(&buffers[1][0],BUFFER_SIZE);
+        fileReadBytes(&buffers[2][0],BUFFER_SIZE);
+        fileReadBytes(&buffers[3][0],BUFFER_SIZE);
+        currentBuffer = 0;
+        currentPtr = buffers[currentBuffer];
+        endPtr = currentPtr + BUFFER_SIZE;
+
+        //streaming = STR_PLAYING|options;
+
+        if (!options) pokPlayStream(); // activate stream
+    #endif //POK_STREAMING_MUSIC
+    return 1; // opening music file succeeded
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoSound.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,217 @@
+/**************************************************************************/
+/*!
+    @file     PokittoSound.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+
+#ifndef POKITTOSOUND_H
+#define POKITTOSOUND_H
+
+#include <stdint.h>
+#include "Pokitto_settings.h"
+#include "GBcompatibility.h"
+#include "PokittoFakeavr.h"
+#include "PokittoGlobs.h"
+
+extern void pokPauseStream();
+extern void pokPlayStream();
+extern uint8_t pokStreamPaused();
+
+//volume levels
+#define GLOBVOL_SHIFT 5 //shift global volume to allow for finer increments
+#ifndef MAX_VOL_TEST
+    #define VOLUME_SPEAKER_MAX 255 //((8<<GLOBVOL_SHIFT)-1)
+    #define VOLUME_HEADPHONE_MAX (1<<GLOBVOL_SHIFT)
+    #define VOLUME_STARTUP ((1<<GLOBVOL_SHIFT)/2)
+#else
+    #define VOLUME_SPEAKER_MAX ((8<<GLOBVOL_SHIFT)-1)
+    #define VOLUME_HEADPHONE_MAX VOLUME_SPEAKER_MAX
+    #define VOLUME_STARTUP VOLUME_SPEAKER_MAX
+#endif // MAXVOLTEST
+
+#ifdef POK_SIM
+#define VOLUME_STEP 1
+#else
+#define VOLUME_STEP 8
+#endif
+
+
+//commands
+#define CMD_VOLUME 0
+#define CMD_INSTRUMENT 1
+#define CMD_SLIDE 2
+#define CMD_ARPEGGIO 3
+#define CMD_TREMOLO 4
+
+#define STR_PLAYING 0x1
+#define STR_VISUALIZER  0x2
+#define STR_LOOP    0x4
+#define STR_PAUSED  0x8
+
+namespace Pokitto {
+
+/** Sound class.
+ *  The Sound class is an API-compatible version of the Gamebuino Sound API by Aurelien Rodot.
+ *  Because it is a class consisting of only static members, there is only 1 instance running,
+ *  no matter how many Sound classes are declared (see example below). This means sound can
+ *  be used through a simple Sound class object or as a member of the Core class.
+ *
+ */
+
+extern void audio_IRQ();  // audio interrupt
+
+class Sound {
+private:
+    static uint16_t volumeMax;
+public:
+	static void begin();
+
+	// Headphonemode
+	static void setMaxVol(int16_t);
+    static uint16_t getMaxVol();
+    static void volumeUp();
+    static void volumeDown();
+
+	// Original functions
+	static void updateStream();
+    static void playTone(uint8_t os, int frq, uint8_t amp, uint8_t wav,uint8_t arpmode);
+    static void playTone(uint8_t os, uint16_t freq, uint8_t volume, uint32_t duration);
+    static uint8_t ampIsOn();
+    static void ampEnable(uint8_t);
+    static int playMusicStream(char* filename, uint8_t options);
+    static int playMusicStream(char* filename);
+    static int playMusicStream();
+    static void pauseMusicStream();
+
+	// GB compatibility functions
+	static void playTrack(const uint16_t* track, uint8_t channel);
+	static void updateTrack(uint8_t channel);
+	static void updateTrack();
+	static void stopTrack(uint8_t channel);
+	static void stopTrack();
+	static void changePatternSet(const uint16_t* const* patterns, uint8_t channel);
+	static bool trackIsPlaying[NUM_CHANNELS];
+
+	static void playPattern(const uint16_t* pattern, uint8_t channel);
+	static void changeInstrumentSet(const uint16_t* const* instruments, uint8_t channel);
+	static void updatePattern(uint8_t i);
+	static void updatePattern();
+	static void setPatternLooping(bool loop, uint8_t channel);
+	static void stopPattern(uint8_t channel);
+	static void stopPattern();
+	static bool patternIsPlaying[NUM_CHANNELS];
+
+	static void command(uint8_t cmd, uint8_t X, int8_t Y, uint8_t i);
+	static void playNote(uint8_t pitch, uint8_t duration, uint8_t channel);
+	static void updateNote();
+	static void updateNote(uint8_t i);
+	static void stopNote(uint8_t channel);
+	static void stopNote();
+
+	static uint8_t outputPitch[NUM_CHANNELS];
+	static int8_t outputVolume[NUM_CHANNELS];
+
+	static void setMasterVolume(uint8_t);
+	static uint8_t GetMasterVolume();
+	static void setVolume(int16_t volume);
+	static uint16_t getVolume();
+	static void setVolume(int8_t volume, uint8_t channel);
+	static uint8_t getVolume(uint8_t channel);
+
+	static void playOK();
+	static void playCancel();
+	static void playTick();
+
+	static uint8_t prescaler;
+
+	static void setChannelHalfPeriod(uint8_t channel, uint8_t halfPeriod);
+
+	static void generateOutput(); //!\\ DO NOT USE
+	static uint16_t globalVolume;
+
+
+#if (NUM_CHANNELS > 0)
+	//tracks data
+	static uint16_t *trackData[NUM_CHANNELS];
+	static uint8_t trackCursor[NUM_CHANNELS];
+	static uint16_t **patternSet[NUM_CHANNELS];
+	static int8_t patternPitch[NUM_CHANNELS];
+
+	// pattern data
+	static uint16_t *patternData[NUM_CHANNELS];
+	static uint16_t **instrumentSet[NUM_CHANNELS];
+	static bool patternLooping[NUM_CHANNELS];
+	static uint16_t patternCursor[NUM_CHANNELS];
+
+	// note data
+	static uint8_t notePitch[NUM_CHANNELS];
+	static uint8_t noteDuration[NUM_CHANNELS];
+	static int8_t noteVolume[NUM_CHANNELS];
+	static bool notePlaying[NUM_CHANNELS];
+
+	// commands data
+	static int8_t commandsCounter[NUM_CHANNELS];
+	static int8_t volumeSlideStepDuration[NUM_CHANNELS];
+	static int8_t volumeSlideStepSize[NUM_CHANNELS];
+	static uint8_t arpeggioStepDuration[NUM_CHANNELS];
+	static int8_t arpeggioStepSize[NUM_CHANNELS];
+	static uint8_t tremoloStepDuration[NUM_CHANNELS];
+	static int8_t tremoloStepSize[NUM_CHANNELS];
+
+
+	// instrument data
+	static uint16_t *instrumentData[NUM_CHANNELS];
+	static uint8_t instrumentLength[NUM_CHANNELS]; //number of steps in the instrument
+	static uint8_t instrumentLooping[NUM_CHANNELS]; //how many steps to loop on when the last step of the instrument is reached
+	static uint16_t instrumentCursor[NUM_CHANNELS]; //which step is being played
+	static uint8_t instrumentNextChange[NUM_CHANNELS]; //how many frames before the next step
+
+	//current step data
+	static int8_t stepVolume[NUM_CHANNELS];
+	static uint8_t stepPitch[NUM_CHANNELS];
+
+	static uint8_t chanVolumes[NUM_CHANNELS];
+#endif
+	static void updateOutput();
+};
+
+}
+
+#endif // POKITTOSOUND_H
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/PokittoTimer.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,46 @@
+/**************************************************************************/
+/*!
+    @file     PokittoTimer.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef POKITTO_TIMER_H
+#define POKITTO_TIMER_H
+
+extern void pokInitTimer(void);
+extern unsigned int pokGetTime(void);
+extern void pokWaitms(uint16_t);
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_CORE/binary.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,517 @@
+#ifndef Binary_h
+#define Binary_h
+
+//jonne #define B0 0
+#define B00 0
+#define B000 0
+#define B0000 0
+#define B00000 0
+#define B000000 0
+#define B0000000 0
+#define B00000000 0
+//jonne #define B1 1
+#define B01 1
+#define B001 1
+#define B0001 1
+#define B00001 1
+#define B000001 1
+#define B0000001 1
+#define B00000001 1
+#define B10 2
+#define B010 2
+#define B0010 2
+#define B00010 2
+#define B000010 2
+#define B0000010 2
+#define B00000010 2
+#define B11 3
+#define B011 3
+#define B0011 3
+#define B00011 3
+#define B000011 3
+#define B0000011 3
+#define B00000011 3
+#define B100 4
+#define B0100 4
+#define B00100 4
+#define B000100 4
+#define B0000100 4
+#define B00000100 4
+#define B101 5
+#define B0101 5
+#define B00101 5
+#define B000101 5
+#define B0000101 5
+#define B00000101 5
+#define B110 6
+#define B0110 6
+#define B00110 6
+#define B000110 6
+#define B0000110 6
+#define B00000110 6
+#define B111 7
+#define B0111 7
+#define B00111 7
+#define B000111 7
+#define B0000111 7
+#define B00000111 7
+#define B1000 8
+#define B01000 8
+#define B001000 8
+#define B0001000 8
+#define B00001000 8
+#define B1001 9
+#define B01001 9
+#define B001001 9
+#define B0001001 9
+#define B00001001 9
+#define B1010 10
+#define B01010 10
+#define B001010 10
+#define B0001010 10
+#define B00001010 10
+#define B1011 11
+#define B01011 11
+#define B001011 11
+#define B0001011 11
+#define B00001011 11
+#define B1100 12
+#define B01100 12
+#define B001100 12
+#define B0001100 12
+#define B00001100 12
+#define B1101 13
+#define B01101 13
+#define B001101 13
+#define B0001101 13
+#define B00001101 13
+#define B1110 14
+#define B01110 14
+#define B001110 14
+#define B0001110 14
+#define B00001110 14
+#define B1111 15
+#define B01111 15
+#define B001111 15
+#define B0001111 15
+#define B00001111 15
+#define B10000 16
+#define B010000 16
+#define B0010000 16
+#define B00010000 16
+#define B10001 17
+#define B010001 17
+#define B0010001 17
+#define B00010001 17
+#define B10010 18
+#define B010010 18
+#define B0010010 18
+#define B00010010 18
+#define B10011 19
+#define B010011 19
+#define B0010011 19
+#define B00010011 19
+#define B10100 20
+#define B010100 20
+#define B0010100 20
+#define B00010100 20
+#define B10101 21
+#define B010101 21
+#define B0010101 21
+#define B00010101 21
+#define B10110 22
+#define B010110 22
+#define B0010110 22
+#define B00010110 22
+#define B10111 23
+#define B010111 23
+#define B0010111 23
+#define B00010111 23
+#define B11000 24
+#define B011000 24
+#define B0011000 24
+#define B00011000 24
+#define B11001 25
+#define B011001 25
+#define B0011001 25
+#define B00011001 25
+#define B11010 26
+#define B011010 26
+#define B0011010 26
+#define B00011010 26
+#define B11011 27
+#define B011011 27
+#define B0011011 27
+#define B00011011 27
+#define B11100 28
+#define B011100 28
+#define B0011100 28
+#define B00011100 28
+#define B11101 29
+#define B011101 29
+#define B0011101 29
+#define B00011101 29
+#define B11110 30
+#define B011110 30
+#define B0011110 30
+#define B00011110 30
+#define B11111 31
+#define B011111 31
+#define B0011111 31
+#define B00011111 31
+#define B100000 32
+#define B0100000 32
+#define B00100000 32
+#define B100001 33
+#define B0100001 33
+#define B00100001 33
+#define B100010 34
+#define B0100010 34
+#define B00100010 34
+#define B100011 35
+#define B0100011 35
+#define B00100011 35
+#define B100100 36
+#define B0100100 36
+#define B00100100 36
+#define B100101 37
+#define B0100101 37
+#define B00100101 37
+#define B100110 38
+#define B0100110 38
+#define B00100110 38
+#define B100111 39
+#define B0100111 39
+#define B00100111 39
+#define B101000 40
+#define B0101000 40
+#define B00101000 40
+#define B101001 41
+#define B0101001 41
+#define B00101001 41
+#define B101010 42
+#define B0101010 42
+#define B00101010 42
+#define B101011 43
+#define B0101011 43
+#define B00101011 43
+#define B101100 44
+#define B0101100 44
+#define B00101100 44
+#define B101101 45
+#define B0101101 45
+#define B00101101 45
+#define B101110 46
+#define B0101110 46
+#define B00101110 46
+#define B101111 47
+#define B0101111 47
+#define B00101111 47
+#define B110000 48
+#define B0110000 48
+#define B00110000 48
+#define B110001 49
+#define B0110001 49
+#define B00110001 49
+#define B110010 50
+#define B0110010 50
+#define B00110010 50
+#define B110011 51
+#define B0110011 51
+#define B00110011 51
+#define B110100 52
+#define B0110100 52
+#define B00110100 52
+#define B110101 53
+#define B0110101 53
+#define B00110101 53
+#define B110110 54
+#define B0110110 54
+#define B00110110 54
+#define B110111 55
+#define B0110111 55
+#define B00110111 55
+#define B111000 56
+#define B0111000 56
+#define B00111000 56
+#define B111001 57
+#define B0111001 57
+#define B00111001 57
+#define B111010 58
+#define B0111010 58
+#define B00111010 58
+#define B111011 59
+#define B0111011 59
+#define B00111011 59
+#define B111100 60
+#define B0111100 60
+#define B00111100 60
+#define B111101 61
+#define B0111101 61
+#define B00111101 61
+#define B111110 62
+#define B0111110 62
+#define B00111110 62
+#define B111111 63
+#define B0111111 63
+#define B00111111 63
+#define B1000000 64
+#define B01000000 64
+#define B1000001 65
+#define B01000001 65
+#define B1000010 66
+#define B01000010 66
+#define B1000011 67
+#define B01000011 67
+#define B1000100 68
+#define B01000100 68
+#define B1000101 69
+#define B01000101 69
+#define B1000110 70
+#define B01000110 70
+#define B1000111 71
+#define B01000111 71
+#define B1001000 72
+#define B01001000 72
+#define B1001001 73
+#define B01001001 73
+#define B1001010 74
+#define B01001010 74
+#define B1001011 75
+#define B01001011 75
+#define B1001100 76
+#define B01001100 76
+#define B1001101 77
+#define B01001101 77
+#define B1001110 78
+#define B01001110 78
+#define B1001111 79
+#define B01001111 79
+#define B1010000 80
+#define B01010000 80
+#define B1010001 81
+#define B01010001 81
+#define B1010010 82
+#define B01010010 82
+#define B1010011 83
+#define B01010011 83
+#define B1010100 84
+#define B01010100 84
+#define B1010101 85
+#define B01010101 85
+#define B1010110 86
+#define B01010110 86
+#define B1010111 87
+#define B01010111 87
+#define B1011000 88
+#define B01011000 88
+#define B1011001 89
+#define B01011001 89
+#define B1011010 90
+#define B01011010 90
+#define B1011011 91
+#define B01011011 91
+#define B1011100 92
+#define B01011100 92
+#define B1011101 93
+#define B01011101 93
+#define B1011110 94
+#define B01011110 94
+#define B1011111 95
+#define B01011111 95
+#define B1100000 96
+#define B01100000 96
+#define B1100001 97
+#define B01100001 97
+#define B1100010 98
+#define B01100010 98
+#define B1100011 99
+#define B01100011 99
+#define B1100100 100
+#define B01100100 100
+#define B1100101 101
+#define B01100101 101
+#define B1100110 102
+#define B01100110 102
+#define B1100111 103
+#define B01100111 103
+#define B1101000 104
+#define B01101000 104
+#define B1101001 105
+#define B01101001 105
+#define B1101010 106
+#define B01101010 106
+#define B1101011 107
+#define B01101011 107
+#define B1101100 108
+#define B01101100 108
+#define B1101101 109
+#define B01101101 109
+#define B1101110 110
+#define B01101110 110
+#define B1101111 111
+#define B01101111 111
+#define B1110000 112
+#define B01110000 112
+#define B1110001 113
+#define B01110001 113
+#define B1110010 114
+#define B01110010 114
+#define B1110011 115
+#define B01110011 115
+#define B1110100 116
+#define B01110100 116
+#define B1110101 117
+#define B01110101 117
+#define B1110110 118
+#define B01110110 118
+#define B1110111 119
+#define B01110111 119
+#define B1111000 120
+#define B01111000 120
+#define B1111001 121
+#define B01111001 121
+#define B1111010 122
+#define B01111010 122
+#define B1111011 123
+#define B01111011 123
+#define B1111100 124
+#define B01111100 124
+#define B1111101 125
+#define B01111101 125
+#define B1111110 126
+#define B01111110 126
+#define B1111111 127
+#define B01111111 127
+#define B10000000 128
+#define B10000001 129
+#define B10000010 130
+#define B10000011 131
+#define B10000100 132
+#define B10000101 133
+#define B10000110 134
+#define B10000111 135
+#define B10001000 136
+#define B10001001 137
+#define B10001010 138
+#define B10001011 139
+#define B10001100 140
+#define B10001101 141
+#define B10001110 142
+#define B10001111 143
+#define B10010000 144
+#define B10010001 145
+#define B10010010 146
+#define B10010011 147
+#define B10010100 148
+#define B10010101 149
+#define B10010110 150
+#define B10010111 151
+#define B10011000 152
+#define B10011001 153
+#define B10011010 154
+#define B10011011 155
+#define B10011100 156
+#define B10011101 157
+#define B10011110 158
+#define B10011111 159
+#define B10100000 160
+#define B10100001 161
+#define B10100010 162
+#define B10100011 163
+#define B10100100 164
+#define B10100101 165
+#define B10100110 166
+#define B10100111 167
+#define B10101000 168
+#define B10101001 169
+#define B10101010 170
+#define B10101011 171
+#define B10101100 172
+#define B10101101 173
+#define B10101110 174
+#define B10101111 175
+#define B10110000 176
+#define B10110001 177
+#define B10110010 178
+#define B10110011 179
+#define B10110100 180
+#define B10110101 181
+#define B10110110 182
+#define B10110111 183
+#define B10111000 184
+#define B10111001 185
+#define B10111010 186
+#define B10111011 187
+#define B10111100 188
+#define B10111101 189
+#define B10111110 190
+#define B10111111 191
+#define B11000000 192
+#define B11000001 193
+#define B11000010 194
+#define B11000011 195
+#define B11000100 196
+#define B11000101 197
+#define B11000110 198
+#define B11000111 199
+#define B11001000 200
+#define B11001001 201
+#define B11001010 202
+#define B11001011 203
+#define B11001100 204
+#define B11001101 205
+#define B11001110 206
+#define B11001111 207
+#define B11010000 208
+#define B11010001 209
+#define B11010010 210
+#define B11010011 211
+#define B11010100 212
+#define B11010101 213
+#define B11010110 214
+#define B11010111 215
+#define B11011000 216
+#define B11011001 217
+#define B11011010 218
+#define B11011011 219
+#define B11011100 220
+#define B11011101 221
+#define B11011110 222
+#define B11011111 223
+#define B11100000 224
+#define B11100001 225
+#define B11100010 226
+#define B11100011 227
+#define B11100100 228
+#define B11100101 229
+#define B11100110 230
+#define B11100111 231
+#define B11101000 232
+#define B11101001 233
+#define B11101010 234
+#define B11101011 235
+#define B11101100 236
+#define B11101101 237
+#define B11101110 238
+#define B11101111 239
+#define B11110000 240
+#define B11110001 241
+#define B11110010 242
+#define B11110011 243
+#define B11110100 244
+#define B11110101 245
+#define B11110110 246
+#define B11110111 247
+#define B11111000 248
+#define B11111001 249
+#define B11111010 250
+#define B11111011 251
+#define B11111100 252
+#define B11111101 253
+#define B11111110 254
+#define B11111111 255
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/HWButtons.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,128 @@
+/**************************************************************************/
+/*!
+    @file     HWButtons.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "HWButtons.h"
+#include "PokittoCore.h"
+#include "PokittoSound.h"
+#include "PokittoDisplay.h"
+
+Pokitto::Sound _s;
+Pokitto::Display _bd;
+
+using namespace mbed;
+
+InterruptIn ABtn(POK_BTN_A_PIN);
+InterruptIn BBtn(POK_BTN_B_PIN);
+InterruptIn CBtn(POK_BTN_C_PIN);
+InterruptIn UBtn(POK_BTN_UP_PIN);
+InterruptIn DBtn(POK_BTN_DOWN_PIN);
+InterruptIn LBtn(POK_BTN_LEFT_PIN);
+InterruptIn RBtn(POK_BTN_RIGHT_PIN);
+
+#define BS_IDLE 0
+#define BS_DOWN 1
+#define BS_UP 2
+
+uint8_t Pokitto::heldStates[NUM_BTN];
+
+void APressed() { Pokitto::heldStates[BTN_A] = 1; }
+void AReleased() { Pokitto::heldStates[BTN_A] = 0; }
+void BPressed() { Pokitto::heldStates[BTN_B] = 1; }
+void BReleased() { Pokitto::heldStates[BTN_B] = 0; }
+void CPressed() {
+    Pokitto::heldStates[BTN_C] = 1;
+    }
+void CReleased() { Pokitto::heldStates[BTN_C] = 0; }
+void UPressed() { Pokitto::heldStates[BTN_UP] = 1; }
+void UReleased() { Pokitto::heldStates[BTN_UP] = 0; }
+void DPressed() { Pokitto::heldStates[BTN_DOWN] = 1; }
+void DReleased() { Pokitto::heldStates[BTN_DOWN] = 0; }
+void RPressed() {
+    /* Hardware volume control */
+    if (Pokitto::heldStates[BTN_C]) _s.volumeUp();
+    else Pokitto::heldStates[BTN_RIGHT] = 1;
+    }
+void RReleased() { Pokitto::heldStates[BTN_RIGHT] = 0; }
+void LPressed() {
+    /* Hardware volume control */
+    if (Pokitto::heldStates[BTN_C]) _s.volumeDown();
+    else Pokitto::heldStates[BTN_LEFT] = 1;
+    }
+void LReleased() { Pokitto::heldStates[BTN_LEFT] = 0; }
+
+void Pokitto::initButtons() {
+  ABtn.fall(&AReleased);
+  ABtn.rise(&APressed);
+  BBtn.fall(&BReleased);
+  BBtn.rise(&BPressed);
+  CBtn.fall(&CReleased);
+  CBtn.rise(&CPressed);
+  UBtn.fall(&UReleased);
+  UBtn.rise(&UPressed);
+  DBtn.fall(&DReleased);
+  DBtn.rise(&DPressed);
+  LBtn.fall(&LReleased);
+  LBtn.rise(&LPressed);
+  RBtn.fall(&RReleased);
+  RBtn.rise(&RPressed);
+}
+
+uint8_t Pokitto::Core::aBtn() {
+    return Pokitto::heldStates[BTN_A];
+}
+
+uint8_t Pokitto::Core::bBtn() {
+    return Pokitto::heldStates[BTN_B];
+}
+
+uint8_t Pokitto::Core::cBtn() {
+    return Pokitto::heldStates[BTN_C];
+}
+
+uint8_t Pokitto::Core::upBtn() {
+    return Pokitto::heldStates[BTN_UP];
+}
+uint8_t Pokitto::Core::downBtn() {
+    return Pokitto::heldStates[BTN_DOWN];
+}
+
+uint8_t Pokitto::Core::leftBtn() {
+    return Pokitto::heldStates[BTN_LEFT];
+}
+uint8_t Pokitto::Core::rightBtn() {
+    return Pokitto::heldStates[BTN_RIGHT];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/HWButtons.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,62 @@
+/**************************************************************************/
+/*!
+    @file     HWButtons.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef HWBUTTONS_H
+#define HWBUTTONS_H
+
+#include "mbed.h"
+#include "Pokitto_settings.h"
+
+#define BTN_UP      1
+#define BTN_RIGHT   2
+#define BTN_DOWN    3
+#define BTN_LEFT    0
+#define BTN_A       4
+#define BTN_B       5
+#define BTN_C       6
+#define NUM_BTN     7
+
+namespace Pokitto {
+
+extern uint8_t heldStates[];
+extern void initButtons();
+extern void pollButtons();
+
+
+} // namespace Pokitto
+
+#endif //HWBUTTONS
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/HWLCD.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,1673 @@
+/**************************************************************************/
+/*!
+    @file     HWLCD.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "HWLCD.h" //HWLCD.h" #include "HWLCD.h"
+#include "Pokitto_settings.h"
+
+#ifndef DISABLEAVRMIN
+#define max(a,b) ((a)>(b)?(a):(b))
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif // DISABLEAVRMIN
+
+#define AB_JUMP 1024 // jump one 1-bit Arduboy screen forward to get next color bit
+#define GB_JUMP 504 // jump one 1-bit Gamebuino screen forward to get next color bit
+
+using namespace Pokitto;
+
+uint16_t prevdata=0; // if data does not change, do not adjust LCD bus lines
+
+#if POK_BOARDREV == 2
+    pwmout_t backlightpwm;
+#endif
+
+
+/**************************************************************************/
+/*!
+    @brief  set up the 16-bit bus
+*/
+/**************************************************************************/
+
+static inline void setup_data_16(uint16_t data)
+{
+    uint32_t p2=0;
+
+    if (data != prevdata) {
+
+    prevdata=data;
+
+    /** D0...D16 = P2_3 ... P2_18 **/
+    p2 = data << 3;
+
+    //__disable_irq();    // Disable Interrupts
+    SET_MASK_P2;
+    LPC_GPIO_PORT->MPIN[2] = p2; // write bits to port
+    CLR_MASK_P2;
+    //__enable_irq();     // Enable Interrupts
+    }
+}
+
+
+/**************************************************************************/
+/*!
+    @brief  Write a command to the lcd, 16-bit bus
+*/
+/**************************************************************************/
+inline void write_command_16(uint16_t data)
+{
+   CLR_CS; // select lcd
+   CLR_CD; // clear CD = command
+   SET_RD; // RD high, do not read
+   setup_data_16(data); // function that inputs the data into the relevant bus lines
+   CLR_WR;  // WR low
+   SET_WR;  // WR low, then high = write strobe
+   SET_CS; // de-select lcd
+}
+
+/**************************************************************************/
+/*!
+    @brief  Write data to the lcd, 16-bit bus
+*/
+/**************************************************************************/
+inline void write_data_16(uint16_t data)
+{
+   CLR_CS;
+   SET_CD;
+   SET_RD;
+   setup_data_16(data);
+   CLR_WR;
+   SET_WR;
+   SET_CS;
+}
+
+/**************************************************************************/
+/*!
+    @brief  Point to a (x,y) location in the LCD DRAM
+*/
+/**************************************************************************/
+static inline void setDRAMptr(uint8_t xptr, uint8_t yoffset)
+{
+    write_command(0x20);  // Vertical DRAM Address
+    write_data(yoffset);
+    write_command(0x21);  // Horizontal DRAM Address
+    write_data(xptr);  //
+    write_command(0x22); // write data to DRAM
+    CLR_CS_SET_CD_RD_WR;
+}
+
+void Pokitto::initBacklight() {
+    #if POK_BOARDREV == 2
+    pwmout_init(&backlightpwm,POK_BACKLIGHT_PIN);
+    pwmout_period_us(&backlightpwm,5);
+    pwmout_write(&backlightpwm,POK_BACKLIGHT_INITIALVALUE);
+    #endif
+}
+
+void Pokitto::setBacklight(float value) {
+    if (value>0.999f) value = 0.999f;
+    pwmout_write(&backlightpwm,value);
+}
+
+void Pokitto::lcdInit() {
+   initBacklight();
+
+   SET_RESET;
+   wait_ms(10);
+   CLR_RESET;
+   wait_ms(10);
+   SET_RESET;
+   wait_ms(10);
+  //************* Start Initial Sequence **********//
+    write_command(0x01); // driver output control, this also affects direction
+    write_data(0x11C); // originally: 0x11C 100011100 SS,NL4,NL3,NL2
+                        // NL4...0 is the number of scan lines to drive the screen !!!
+                        // so 11100 is 1c = 220 lines, correct
+                        // test 1: 0x1C 11100 SS=0,NL4,NL3,NL2 -> no effect
+                        // test 2: 0x31C 1100011100 GS=1,SS=1,NL4,NL3,NL2 -> no effect
+                        // test 3: 0x51C 10100011100 SM=1,GS=0,SS=1,NL4,NL3,NL2 -> no effect
+                        // test 4: 0x71C SM=1,GS=1,SS=1,NL4,NL3,NL2
+                        // test 5: 0x
+                        // seems to have no effect... is this perhaps only for RGB mode ?
+
+    write_command(0x02); // LCD driving control
+    write_data(0x0100); // INV = 1
+
+    write_command(0x03); // Entry mode... lets try if this affects the direction
+    write_data(0x1030); // originally 0x1030 1000000110000 BGR,ID1,ID0
+                        // test 1: 0x1038 1000000111000 BGR,ID1,ID0,AM=1 ->drawing DRAM horizontally
+                        // test 4: am=1, id0=0, id1=0, 1000000001000,0x1008 -> same as above, but flipped on long
+                        // test 2: am=0, id0=0, 1000000100000, 0x1020 -> flipped on long axis
+                        // test 3: am=0, id1=0, 1000000010000, 0x1010 -> picture flowed over back to screen
+
+
+    write_command(0x08); // Display control 2
+    write_data(0x0808); // 100000001000 FP2,BP2
+
+    write_command(0x0C); // RGB display interface
+    write_data(0x0000); // all off
+
+    write_command(0x0F); // Frame marker position
+    write_data(0x0001); // OSC_EN
+
+    write_command(0x20);  // Horizontal DRAM Address
+    write_data(0x0000);  // 0
+
+    write_command(0x21);  // Vertical DRAM Address
+    write_data(0x0000); // 0
+
+ //*************Power On sequence ****************//
+    write_command(0x10);
+    write_data(0x0000);
+
+    write_command(0x11);
+    write_data(0x1000);
+    wait_ms(10);
+//------------------------ Set GRAM area --------------------------------//
+    write_command(0x30); // Gate scan position
+    write_data(0x0000); // if GS=0, 00h=G1, else 00h=G220
+
+    write_command(0x31); // Vertical scroll control
+    write_data(0x00DB); // scroll start line 11011011 = 219
+
+    write_command(0x32); // Vertical scroll control
+    write_data(0x0000); // scroll end line 0
+
+    write_command(0x33); // Vertical scroll control
+    write_data(0x0000); // 0=vertical scroll disabled
+
+    write_command(0x34); // Partial screen driving control
+    write_data(0x00DB); // db = full screen (end)
+
+    write_command(0x35); // partial screen
+    write_data(0x0000); // 0 = start
+
+    write_command(0x36); // Horizontal and vertical RAM position
+    write_data(0x00AF); //end address 175
+
+    write_command(0x37);
+    write_data(0x0000); // start address 0
+
+    write_command(0x38);
+    write_data(0x00DB); //end address 219
+
+    write_command(0x39); // start address 0
+    write_data(0x0000);
+    wait_ms(10);
+    write_command(0xff); // start gamma register control
+    write_data(0x0003);
+
+// ----------- Adjust the Gamma  Curve ----------//
+    write_command(0x50);
+    write_data(0x0203);
+
+    write_command(0x051);
+    write_data(0x0A09);
+
+    write_command(0x52);
+    write_data(0x0005);
+
+    write_command(0x53);
+    write_data(0x1021);
+
+    write_command(0x54);
+    write_data(0x0602);
+
+    write_command(0x55);
+    write_data(0x0003);
+
+    write_command(0x56);
+    write_data(0x0703);
+
+    write_command(0x57);
+    write_data(0x0507);
+
+    write_command(0x58);
+    write_data(0x1021);
+
+    write_command(0x59);
+    write_data(0x0703);
+
+    write_command(0xB0);
+    write_data(0x2501);
+
+    write_command(0xFF);
+    write_data(0x0000);
+
+    write_command(0x07);
+    write_data(0x1017);
+    wait_ms(200);
+    write_command(0x22);
+
+    lcdClear();
+}
+
+void Pokitto::lcdSleep(void){
+   write_command(0xFF);
+   write_data(0x0000);
+
+   write_command(0x07);
+   write_data(0x0000);
+   wait_ms(50);
+   write_command(0x10);// Enter Standby mode
+   write_data(0x0003);
+   wait_ms(200);
+
+}
+
+void Pokitto::lcdWakeUp (void){
+
+   wait_ms(200);
+   write_command(0xFF);
+   write_data(0x0000);
+
+   write_command(0x10);// Exit Sleep/ Standby mode
+   write_data(0x0000);
+   wait_ms(50);
+   write_command(0x07);
+   write_data(0x0117);
+   wait_ms(200);
+  }
+
+void Pokitto::lcdFillSurface(uint16_t c) {
+    uint32_t i;
+    write_command(0x20);  // Horizontal DRAM Address
+    write_data(0x0000);  // 0
+    write_command(0x21);  // Vertical DRAM Address
+    write_data(0);
+    write_command(0x22); // write data to DRAM
+    setup_data_16(c);
+    CLR_CS_SET_CD_RD_WR;
+    for(i=0;i<220*176;i++)
+    {
+    CLR_WR;
+    SET_WR;
+    }
+}
+
+void Pokitto::lcdClear() {
+    uint32_t i;
+    write_command(0x20);  // Horizontal DRAM Address
+    write_data(0x0000);  // 0
+    write_command(0x21);  // Vertical DRAM Address
+    write_data(0);
+    write_command(0x22); // write data to DRAM
+    setup_data_16(0x0000);
+    CLR_CS_SET_CD_RD_WR;
+    for(i=0;i<220*176;i++)
+    {
+        CLR_WR;
+        SET_WR;
+    }
+}
+
+void Pokitto::lcdPixel(int16_t x, int16_t y, uint16_t color) {
+    if ((x < 0) || (x >= POK_LCD_W) || (y < 0) || (y >= POK_LCD_H))
+	return;
+	write_command(0x20);  // Horizontal DRAM Address
+    write_data(y);  // 0
+    write_command(0x21);  // Vertical DRAM Address
+    write_data(x);
+    write_command(0x22); // write data to DRAM
+    CLR_CS_SET_CD_RD_WR;
+    setup_data_16(color);
+    CLR_WR;SET_WR;
+}
+
+void Pokitto::setWindow(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
+	write_command(0x37); write_data(x1);
+	write_command(0x36); write_data(x2);
+	write_command(0x39); write_data(y1);
+	write_command(0x38); write_data(y2);
+	write_command(0x20); write_data(x1);
+	write_command(0x21); write_data(y1);
+}
+
+void Pokitto::lcdTile(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t* gfx){
+	int width=x1-x0;
+	int height=y1-y0;
+	if (x0 > POK_LCD_W) return;
+	if (y0 > POK_LCD_H) return;
+	if (x0 < 0) x0=0;
+	if (y0 < 0) y0=0;
+
+	setWindow(y0, x0, y1-1, x1-1);
+    write_command(0x22);
+
+    for (int x=0; x<=width*height-1;x++) {
+        write_data(gfx[x]);
+    }
+	setWindow(0, 0, 175, 219);
+}
+
+
+void Pokitto::lcdRectangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) {
+    	int16_t temp;
+	if (x0>x1) {temp=x0;x0=x1;x1=temp;}
+	if (y0>y1) {temp=y0;y0=y1;y1=temp;}
+	if (x0 > POK_LCD_W) return;
+	if (y0 > POK_LCD_H) return;
+    if (x1 > POK_LCD_W) x1=POK_LCD_W;
+	if (y1 > POK_LCD_H) y1=POK_LCD_W;
+	if (x0 < 0) x0=0;
+	if (y0 < 0) y0=0;
+
+	int16_t x,y;
+    for (x=x0; x<=x1;x++) {
+        write_command(0x20);  // Horizontal DRAM Address (=y on pokitto screen)
+        write_data(y0);
+        write_command(0x21);  // Vertical DRAM Address (=x on pokitto screen)
+        write_data(x);
+        write_command(0x22); // write data to DRAM
+
+        CLR_CS_SET_CD_RD_WR; // go to vram write mode
+
+
+        for (y=y0; y<y1;y++) {
+                setup_data_16(color); // setup the data (flat color = no change between pixels)
+                CLR_WR;SET_WR; //CLR_WR;SET_WR;//toggle writeline, pokitto screen writes a column up to down
+        }
+    }
+}
+
+/***
+ * Update the screen buffer of 220x176 pixels, 4 colors to LCD.
+ *
+ * The update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations, the
+ * x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels.
+ * Note: The update rect is currently used for 220x176, 4 colors, screen mode only.
+ * @param scrbuf The screen buffer.
+ * @param updRectX The update rect.
+ * @param updRectY The update rect.
+ * @param updRectW The update rect.
+ * @param updRectH The update rect.
+ * @param paletteptr The screen palette.
+*/
+void Pokitto::lcdRefreshMode1(uint8_t * scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr) {
+
+    uint16_t x,y,xptr;
+    uint16_t scanline[4][176]; // read 4 half-nibbles = 4 pixels at a time
+    uint8_t *d, yoffset=0;
+
+    // If not the full screen is updated, check the validity of the update rect.
+    if ( updRectX != 0 || updRectY != 0 ||updRectW != LCDWIDTH ||updRectH != LCDHEIGHT ) {
+        uint8_t org_screenx = updRectX;
+        updRectX &= 0xfc; // Make the value dividable by 4.
+        updRectW += org_screenx - updRectX;
+        updRectW = (updRectW + 3) & 0xfc; // Make the value dividable by 4, round up.
+
+        uint8_t org_screeny = updRectY;
+        updRectY &= 0xfc; // Make the value dividable by 4.
+        updRectH += org_screeny - updRectY;
+        updRectH = (updRectH + 7) & 0xf8; // Make the value dividable by 8 (because of loop unroll optimization), round up.
+    }
+
+
+    #ifdef PROJ_USE_FPS_COUNTER
+    xptr = 8;
+    setDRAMptr(8, 0);
+    #else
+    xptr = 0;
+    setDRAMptr(0, 0);
+    #endif
+
+    for (x=updRectX; x<updRectX+updRectW; x+=4) {
+        d = scrbuf+(x>>2);// point to beginning of line in data
+
+        /** find colours in one scanline **/
+        uint8_t s=0;
+        d += (updRectY * 220/4);
+        for (y=updRectY; y<updRectY+updRectH; y++) {
+            uint8_t tdata = *d;
+            uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble
+            uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble
+            uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble
+            uint8_t t = tdata & 0x03;// highest half-nibble
+
+            /** put nibble values in the scanlines **/
+            scanline[0][y] = paletteptr[t];
+            scanline[1][y] = paletteptr[t2];
+            scanline[2][y] = paletteptr[t3];
+            scanline[3][y] = paletteptr[t4];
+
+            d += 220/4; // jump to read byte directly below in screenbuffer
+        }
+
+        #ifdef PROJ_USE_FPS_COUNTER
+        if (x>=8 ) {
+        #else
+        {
+
+        #endif
+
+            // Draw 8 vertical pixels at a time for performance reasons
+            setDRAMptr(x, updRectY);
+            for (uint8_t s=updRectY; s<updRectY+updRectH;) {
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+            }
+            setDRAMptr(x+1, updRectY);
+            for (uint8_t s=updRectY; s<updRectY+updRectH;) {
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+            }
+            setDRAMptr(x+2, updRectY);
+            for (uint8_t s=updRectY; s<updRectY+updRectH;) {
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+            }
+            setDRAMptr(x+3, updRectY);
+            for (uint8_t s=updRectY; s<updRectY+updRectH;) {
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+            }
+        }
+    }
+
+    #ifdef POK_SIM
+    simulator.refreshDisplay();
+    #endif
+}
+
+// Copy sprite pixels to the scanline
+#define SPRITE_2BPP_INNER_LOOP(n)\
+\
+    /* If the sprite is enabled and contained in this vertical scanline, copy 4 pixels. */\
+    if (sprScanlineAddr[(n)] &&\
+        y >= sprites[(n)].y && y < sprites[(n)].y + sprites[(n)].h ) {\
+\
+        int16_t sprx = sprites[(n)].x;\
+        uint16_t s_data16b = 0;  /* sprite data, 2 bytes */\
+\
+        /* Get pixel block, 4 or 8 pixels horizontally. Use the predefined bitshift mode. */\
+        /* Note:it is cheapest to compare to 0 first. */\
+        if (sprScanlineBitshiftMode[(n)] == BITSHIFT_MODE_MIDDLE_BYTE) {\
+            s_data16b = *(sprScanlineAddr[(n)]);\
+            uint16_t leftByte = *(sprScanlineAddr[(n)]-1);\
+            s_data16b = (leftByte << 8) | s_data16b;\
+        }\
+        else if (sprScanlineBitshiftMode[(n)] == BITSHIFT_MODE_FIRST_BYTE) {\
+            s_data16b = *(sprScanlineAddr[(n)]);\
+        }\
+        else { /* BITSHIFT_MODE_LAST_BYTE */\
+            uint16_t leftByte = *(sprScanlineAddr[(n)]-1);\
+            s_data16b = (leftByte << 8) | s_data16b;\
+        }\
+\
+        /* Shift sprite pixels according to sprite x. After shifting we have only 4 pixels. */\
+        uint8_t shiftRight = (sprx&0x3) << 1;\
+        s_data16b = (s_data16b >> shiftRight);\
+\
+        /* Get individual pixels */\
+        uint8_t s_t4 = s_data16b & 0x03; s_data16b >>= 2; /* lowest half-nibble */\
+        uint8_t s_t3 = s_data16b & 0x03; s_data16b >>= 2; /* second lowest half-nibble */\
+        uint8_t s_t2 = s_data16b & 0x03; s_data16b >>= 2; /* second highest half-nibble */\
+        uint8_t s_t1 = s_data16b & 0x03;                  /* highest half-nibble */\
+\
+        /* Store pixels as 16-bit colors from the palette */\
+        if (s_t4 != transparentColor) p4 = sprites[(n)].palette[s_t4];\
+        if (s_t3 != transparentColor) p3 = sprites[(n)].palette[s_t3];\
+        if (s_t2 != transparentColor) p2 = sprites[(n)].palette[s_t2];\
+        if (s_t1 != transparentColor) p = sprites[(n)].palette[s_t1];\
+\
+        /* Advance scanline address */\
+        sprScanlineAddr[(n)] += (sprites[(n)].w >> 2);\
+    }
+
+// Loop unrolling macros
+#define UNROLLED_LOOP_1() SPRITE_2BPP_INNER_LOOP(0)
+#define UNROLLED_LOOP_2() UNROLLED_LOOP_1() SPRITE_2BPP_INNER_LOOP(1)
+#define UNROLLED_LOOP_3() UNROLLED_LOOP_2() SPRITE_2BPP_INNER_LOOP(2)
+#define UNROLLED_LOOP_4() UNROLLED_LOOP_3() SPRITE_2BPP_INNER_LOOP(3)
+#define UNROLLED_LOOP_5() UNROLLED_LOOP_4() SPRITE_2BPP_INNER_LOOP(4)
+#define UNROLLED_LOOP_6() UNROLLED_LOOP_5() SPRITE_2BPP_INNER_LOOP(5)
+#define UNROLLED_LOOP_7() UNROLLED_LOOP_6() SPRITE_2BPP_INNER_LOOP(6)
+#define UNROLLED_LOOP_8() UNROLLED_LOOP_7() SPRITE_2BPP_INNER_LOOP(7)
+#define UNROLLED_LOOP_9() UNROLLED_LOOP_8() SPRITE_2BPP_INNER_LOOP(8)
+#define UNROLLED_LOOP_10() UNROLLED_LOOP_9() SPRITE_2BPP_INNER_LOOP(9)
+#define UNROLLED_LOOP_11() UNROLLED_LOOP_10() SPRITE_2BPP_INNER_LOOP(10)
+#define UNROLLED_LOOP_12() UNROLLED_LOOP_11() SPRITE_2BPP_INNER_LOOP(11)
+#define UNROLLED_LOOP_13() UNROLLED_LOOP_12() SPRITE_2BPP_INNER_LOOP(12)
+#define UNROLLED_LOOP_14() UNROLLED_LOOP_13() SPRITE_2BPP_INNER_LOOP(13)
+#define UNROLLED_LOOP_15() UNROLLED_LOOP_14() SPRITE_2BPP_INNER_LOOP(14)
+#define UNROLLED_LOOP_16() UNROLLED_LOOP_15() SPRITE_2BPP_INNER_LOOP(15)
+#define UNROLLED_LOOP_N_(n) UNROLLED_LOOP_##n()
+#define UNROLLED_LOOP_N(n) UNROLLED_LOOP_N_(n)
+
+/***
+ * Update the screen buffer of 220x176 pixels, 4 colors and free size 4 color sprites to LCD.
+ *
+ * The update rect is used for drawing only part of the screen buffer to LCD. Because of speed optimizations, the
+ * x, y, and width of the update rect must be dividable by 4 pixels, and the height must be dividable by 8 pixels.
+ * Note: The update rect is currently used for 220x176, 4 colors, screen mode only.
+ * If drawSpritesOnly=true, only sprites are fully updated to LCD. However, the dirty rect of the screen buffer is
+ * drawn behind the sprite current and previous location.
+ * Note: Sprite is enabled if sprite.bitmapData is not NULL. Also all enabled sprites must be at the beginning of
+ * the sprites array. No gaps are allowed in the array.
+ * @param scrbuf The screen buffer.
+ * @param updRectX The update rect.
+ * @param updRectY The update rect.
+ * @param updRectW The update rect.
+ * @param updRectH The update rect.
+ * @param paletteptr The screen palette.
+ * @param sprites The sprite array.
+ * @param drawSpritesOnly True, if only sprites are drawn. False, if both sprites and the screen buffer are drawn.
+*/
+void Pokitto::lcdRefreshMode1Spr(
+    uint8_t * scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr,
+    SpriteInfo* sprites, bool drawSpritesOnly) {
+
+    // In direct mode draw only sprites and their dirty rects. Return now if there are no sprites
+    if (drawSpritesOnly && (sprites == NULL || sprites[0].bitmapData == NULL))
+        return;
+
+    uint16_t x,y;
+    uint16_t scanline[4][176]; // read 4 half-nibbles (= 4 pixels) at a time
+    const uint8_t transparentColor = 0;  // fixed palette index 0 for transparency
+
+    // If not the full screen is updated, check the validity of the update rect.
+    if ( updRectX != 0 || updRectY != 0 ||updRectW != LCDWIDTH ||updRectH != LCDHEIGHT ) {
+        uint8_t org_screenx = updRectX;
+        updRectX &= 0xfc; // Make the value dividable by 4.
+        updRectW += org_screenx - updRectX;
+        updRectW = (updRectW + 3) & 0xfc; // Make the value dividable by 4, round up.
+
+        uint8_t org_screeny = updRectY;
+        updRectY &= 0xfc; // Make the value dividable by 4.
+        updRectH += org_screeny - updRectY;
+        updRectH = (updRectH + 7) & 0xf8; // Make the value dividable by 8 (because of loop unroll optimization), round up.
+    }
+
+    // Calculate the current  amount of sprites
+    // Note: Sprites must be taken into use from index 0 upwards, because the first sprite with bitmapData==NULL is considered as the last sprite
+    uint8_t spriteCount = 0;
+    if (sprites != NULL)
+        for (;sprites[spriteCount].bitmapData != NULL && spriteCount < SPRITE_COUNT; spriteCount++);
+
+    // If drawing the screen buffer, set the start pos to LCD commands only here.
+    #ifdef PROJ_USE_FPS_COUNTER
+    if (!drawSpritesOnly) setDRAMptr(8, 0);
+    #else
+    if (!drawSpritesOnly) setDRAMptr(0, 0);
+    #endif
+
+    //*** GO THROUGH EACH VERTICAL GROUP OF 4 SCANLINES.***
+
+    for (x=0; x<LCDWIDTH; x+=4) {
+
+        uint8_t *screenBufScanlineAddr = scrbuf + (x>>2);// point to beginning of line in data
+
+        /*Prepare scanline start address for sprites that are visible in this vertical scanline. Sprite width cannot exceed the screen width*/
+        uint8_t *sprScanlineAddr[SPRITE_COUNT];  // Sprite start address for the scanline
+        uint8_t sprScanlineBitshiftMode[SPRITE_COUNT];  // Sprite bitshift mode for the scanline
+        const uint8_t BITSHIFT_MODE_MIDDLE_BYTE = 0;
+        const uint8_t BITSHIFT_MODE_FIRST_BYTE = 1;
+        const uint8_t BITSHIFT_MODE_LAST_BYTE = 2;
+        uint8_t scanlineMinY = 255; // Init to uninitialized value. Do not draw by default.
+        uint8_t scanlineMaxY = 0; // Init to uninitialized value. Do not draw by default.
+
+        //*** CALCULATE DIRTY RECTS AND RESOLVE WHICH SPRITES BELONG TO THIS SCANLINE GROUP ***
+
+        if (sprites != NULL) {
+
+            // Check all the sprites for this scanline. That is used for handling the given update rect
+            // Note that the last round is when (sprindex == spriteCount). That is used to add the screen buffer
+            // update rect to the dirty rect.
+            for (int sprindex = 0; sprindex <= spriteCount; sprindex++) {
+
+                int16_t sprx, spry, sprOldX, sprOldY;
+                uint8_t sprw, sprh;
+                bool isCurrentSpriteOutOfScreen = false;
+                bool isOldSpriteOutOfScreen = false;
+
+                if (sprindex < spriteCount) {
+
+                    sprx = sprites[sprindex].x;
+                    spry = sprites[sprindex].y;
+                    sprw = sprites[sprindex].w;
+                    sprh = sprites[sprindex].h;
+                    sprOldX = sprites[sprindex].oldx;
+                    sprOldY = sprites[sprindex].oldy;
+               }
+
+                // Handle the screen buffer update rect after all sprites
+                else if(!drawSpritesOnly){
+
+                    sprx = updRectX;
+                    spry = updRectY;
+                    sprw = updRectW;
+                    sprh = updRectH;
+                    sprOldX = updRectX;
+                    sprOldY = updRectY;
+                    isCurrentSpriteOutOfScreen = false;
+                    isOldSpriteOutOfScreen = false;
+                }
+
+                // Check for out-of-screen
+                if (sprx >= LCDWIDTH || spry >= LCDHEIGHT)
+                    isCurrentSpriteOutOfScreen = true;
+                if (sprOldX >= LCDWIDTH || sprOldY >= LCDHEIGHT)
+                    isOldSpriteOutOfScreen = true;
+
+                // Skip if current and old sprites are out-of-screen
+                if (isCurrentSpriteOutOfScreen && isOldSpriteOutOfScreen)
+                    continue;
+
+                // Detect the dirty rect x-span by combining the previous and current sprite position.
+                int16_t sprDirtyXMin = min(sprx, sprOldX);
+                int16_t sprDirtyXMax = max(sprx, sprOldX);
+                if (isCurrentSpriteOutOfScreen)
+                    sprDirtyXMax = sprOldX;
+                if (isOldSpriteOutOfScreen)
+                    sprDirtyXMax = sprx;
+
+                // Is current x inside the sprite combined dirty rect ?
+                int16_t sprDirtyXMaxEnd = sprDirtyXMax + sprw - 1 + 4; // Add 4 pixels to dirty rect width (needed?)
+                if (sprDirtyXMin <= x+3 && x <= sprDirtyXMaxEnd) {
+
+                    // *** COMBINE DIRTY RECTS FOR THIS SCANLINE GROUP ***
+
+                    // Dirty rect
+                    int16_t sprDirtyYMin = min(spry, sprOldY);
+                    sprDirtyYMin = max(sprDirtyYMin, 0);
+                    int16_t sprDirtyYMax = max(spry, sprOldY);
+                    if (isCurrentSpriteOutOfScreen)
+                        sprDirtyYMax = sprOldY;
+                    if (isOldSpriteOutOfScreen)
+                        sprDirtyYMax = spry;
+                    int16_t sprDirtyYMaxEnd = sprDirtyYMax + sprh - 1;
+                    sprDirtyYMaxEnd = min(sprDirtyYMaxEnd, LCDHEIGHT - 1);  // Should use LCDHEIGHT instead of screenH? Same with other screen* ?
+
+                    // Get the scanline min and max y values for drawing
+                    if (sprDirtyYMin < scanlineMinY)
+                        scanlineMinY = sprDirtyYMin;
+                    if (sprDirtyYMaxEnd > scanlineMaxY)
+                        scanlineMaxY = sprDirtyYMaxEnd;
+
+                   // *** PREPARE SPRITE FOR DRAWING ***
+
+                   // Check if the sprite should be active for this vertical scanline group.
+                    if (sprindex < spriteCount &&  // not for update rect
+                        !isCurrentSpriteOutOfScreen && //out-of-screen
+                        sprx <= x+3 && x < sprx + sprw) { // note: cover group of 4 pixels of the scanline (x+3)
+
+                        // Find the byte number in the sprite data
+                        int16_t byteNum = ((x+3) - sprx)>>2;
+
+                        // Get the start addres of the spite data in this scanline.
+                        sprScanlineAddr[sprindex] = const_cast<uint8_t*>(sprites[sprindex].bitmapData + byteNum);
+
+                        // If the sprite goes over the top, it must be clipped from the top.
+                        if(spry < 0)
+                            sprScanlineAddr[sprindex] += (-spry) * (sprw >> 2);
+
+                        // Select the bitshift mode for the blit algorithm
+                        if (byteNum == 0)
+                            sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_FIRST_BYTE;
+                        else if (byteNum >= (sprw >> 2))
+                            sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_LAST_BYTE;
+                        else
+                            sprScanlineBitshiftMode[sprindex] = BITSHIFT_MODE_MIDDLE_BYTE;
+                    }
+                    else
+                        sprScanlineAddr[sprindex] = NULL;  // Deactive sprite for this scanline
+                }
+                else
+                    sprScanlineAddr[sprindex] = NULL;  // Deactive sprite for this scanline
+            }
+        }
+
+        // *** ADJUST THE SCANLINE GROUP HEIGHT ***
+
+        // The height must dividable by 8. That is needed because later we copy 8 pixels at a time to the LCD.
+        if (scanlineMaxY - scanlineMinY + 1 > 0) {
+            uint8_t scanlineH = scanlineMaxY - scanlineMinY + 1;
+            uint8_t addW = 8 - (scanlineH & 0x7);
+
+            // if height is not dividable by 8, make it be.
+            if (addW != 0) {
+                if (scanlineMinY > addW )
+                    scanlineMinY -= addW;
+                else if( scanlineMaxY + addW < updRectY+updRectH)
+                    scanlineMaxY += addW;
+                else {
+                    // Draw full height scanline
+                    scanlineMinY = updRectY;
+                    scanlineMaxY = updRectY+updRectH-1;
+                }
+            }
+        }
+
+        // *** COMBINE THE SCANLINE GROUP OF THE SCREEN BUFFER AND ALL SPRITES ***
+
+        // Find colours in this group of 4 scanlines
+        screenBufScanlineAddr += (scanlineMinY * 220/4);
+        for (y=scanlineMinY; y<=scanlineMaxY; y++)
+        {
+            // get the screen buffer data first
+            uint8_t tdata = *screenBufScanlineAddr;
+            uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble
+            uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble
+            uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble
+            uint8_t t = tdata & 0x03;// highest half-nibble
+
+            // Convert to 16-bit colors in palette
+            uint16_t p = paletteptr[t];
+            uint16_t p2 = paletteptr[t2];
+            uint16_t p3 = paletteptr[t3];
+            uint16_t p4 = paletteptr[t4];
+
+            #if 0
+            // Dirty rect visual test
+            p = COLOR_BLUE >> (Core::frameCount % 5);
+            p2 = COLOR_BLUE >> (Core::frameCount % 5);
+            p3 = COLOR_BLUE >> (Core::frameCount % 5);
+            p4 = COLOR_BLUE >> (Core::frameCount % 5);
+            #endif
+
+            // Add active sprite pixels
+            if (sprites != NULL) {
+
+                // Use loop unrolling for speed optimization
+                UNROLLED_LOOP_N(SPRITE_COUNT)
+            }
+
+            // put the result nibble values in the scanline
+            scanline[0][y] = p;
+            scanline[1][y] = p2;
+            scanline[2][y] = p3;
+            scanline[3][y] = p4;
+
+            screenBufScanlineAddr += 220>>2; // jump to read byte directly below in screenbuffer
+        }
+
+        // *** DRAW THE SCANLINE GROUP TO LCD
+
+#ifdef PROJ_USE_FPS_COUNTER
+        if (x>=8 && scanlineMaxY - scanlineMinY +1 > 0) {
+#else
+        if (scanlineMaxY - scanlineMinY +1 > 0) {
+#endif
+            // Draw 8 vertical pixels at a time for performance reasons
+
+            setDRAMptr(x, scanlineMinY);
+            for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+            }
+
+            setDRAMptr(x+1, scanlineMinY);
+            for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+            }
+
+            setDRAMptr(x+2, scanlineMinY);
+            for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+            }
+
+            setDRAMptr(x+3, scanlineMinY);
+            for (uint8_t s=scanlineMinY;s<=scanlineMaxY;) {
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+                setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+            }
+        }
+    }
+
+    // Update old x and y for the sprites
+    if (sprites != NULL) {
+        for (int sprindex = 0; sprindex < spriteCount; sprindex++) {
+            sprites[sprindex].oldx = sprites[sprindex].x;
+            sprites[sprindex].oldy = sprites[sprindex].y;
+        }
+    }
+
+    #ifdef POK_SIM
+    simulator.refreshDisplay();
+    #endif
+}
+
+void Pokitto::lcdRefreshMode2(uint8_t * scrbuf, uint16_t* paletteptr) {
+uint16_t x,y;
+uint16_t scanline[2][88]; // read two nibbles = pixels at a time
+uint8_t *d;
+
+write_command(0x20);  // Horizontal DRAM Address
+write_data(0);  // 0
+write_command(0x21);  // Vertical DRAM Address
+write_data(0);
+write_command(0x22); // write data to DRAM
+CLR_CS_SET_CD_RD_WR;
+
+for(x=0;x<110;x+=2)
+  {
+    d = scrbuf+(x>>1);// point to beginning of line in data
+    /** find colours in one scanline **/
+    uint8_t s=0;
+    for(y=0;y<88;y++)
+    {
+    uint8_t t = *d >> 4; // higher nibble
+    uint8_t t2 = *d & 0xF; // lower nibble
+    /** higher nibble = left pixel in pixel pair **/
+    scanline[0][s] = paletteptr[t];
+    scanline[1][s++] = paletteptr[t2];
+    /** testing only **/
+    //scanline[0][s] = 0xFFFF*(s&1);
+    //scanline[1][s] = 0xFFFF*(!(s&1));
+    //s++;
+    /** until here **/
+    d+=110/2; // jump to read byte directly below in screenbuffer
+    }
+    s=0;
+    /** draw scanlines **/
+    /** leftmost scanline twice**/
+
+    for (s=0;s<88;) {
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+
+    for (s=0;s<88;) {
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+    /** rightmost scanline twice**/
+    //setDRAMptr(xptr++,yoffset);
+    for (s=0;s<88;) {
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+
+    for (s=0;s<88;) {
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+  }
+}
+
+void Pokitto::lcdRefreshMode3(uint8_t * scrbuf, uint16_t* paletteptr) {
+uint16_t x,y;
+uint16_t scanline[2][176]; // read two nibbles = pixels at a time
+uint8_t *d;
+
+write_command(0x20);  // Horizontal DRAM Address
+write_data(0);  // 0
+write_command(0x21);  // Vertical DRAM Address
+write_data(0);
+write_command(0x22); // write data to DRAM
+CLR_CS_SET_CD_RD_WR;
+
+for(x=0;x<220;x+=2)
+  {
+    d = scrbuf+(x>>1);// point to beginning of line in data
+    /** find colours in one scanline **/
+    uint8_t s=0;
+    for(y=0;y<176;y++)
+    {
+    uint8_t t = *d >> 4; // higher nibble
+    uint8_t t2 = *d & 0xF; // lower nibble
+    /** higher nibble = left pixel in pixel pair **/
+    scanline[0][s] = paletteptr[t];
+    scanline[1][s++] = paletteptr[t2];
+    /** testing only **/
+    //scanline[0][s] = 0xFFFF*(s&1);
+    //scanline[1][s] = 0xFFFF*(!(s&1));
+    //s++;
+    /** until here **/
+    d+=220/2; // jump to read byte directly below in screenbuffer
+    }
+    s=0;
+    /** draw scanlines **/
+    /** leftmost scanline**/
+
+    for (s=0;s<176;) {
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+    }
+
+    /** rightmost scanline**/
+    //setDRAMptr(xptr++,yoffset);
+    for (s=0;s<176;) {
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+    }
+  }
+}
+
+void Pokitto::lcdRefreshGB(uint8_t * scrbuf, uint16_t* paletteptr) {
+uint16_t x,y;
+uint16_t scanline[48];
+uint8_t * d;
+
+#if POK_STRETCH
+//uint16_t xptr = 8;
+#else
+//xptr = 26;
+#endif
+
+write_command(0x20);  // Horizontal DRAM Address
+write_data(0);  // 0
+write_command(0x21);  // Vertical DRAM Address
+write_data(0);
+write_command(0x22); // write data to DRAM
+CLR_CS_SET_CD_RD_WR;
+
+/** draw border **/
+    for (int s=0;s<5*176;) {
+            setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;s++;
+    }
+
+for(x=0;x<84;x++)
+  {
+
+        d = scrbuf + x;// point to beginning of line in data
+
+        /** find colours in one scanline **/
+        uint8_t s=0;
+        for(y=0;y<6;y++)
+            {
+            uint8_t t = *d;
+            #if POK_COLORDEPTH > 1
+            uint8_t t2 = *(d+504);
+            #endif
+            #if POK_COLORDEPTH > 2
+            uint8_t t3 = *(d+504+504);
+            #endif
+            #if POK_COLORDEPTH > 3
+            uint8_t t4 = *(d+504+504+504);
+            #endif
+            uint8_t paletteindex = 0;
+
+            /** bit 1 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x1);
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x1)) | ((t2 & 0x01)<<1);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2) | ((t4 & 0x1)<<3);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 2 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x2)>>1;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x2)>>1) | ((t2 & 0x02));
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1) | ((t4 & 0x2)<<2);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 3 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x4)>>2;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 4)>>2) | ((t2 & 0x04)>>1);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4) | ((t4 & 0x4)<<1);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 4 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x8)>>3;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x8)>>3) | ((t2 & 0x08)>>2);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1) | (t4 & 0x8);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 5 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x10)>>4;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2) | ((t4 & 0x10)>>1);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 6 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x20)>>5;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3) | ((t4 & 0x20)>>2);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 7 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x40)>>6;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) ;
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) | ((t4 & 0x40)>>3);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 8 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x80)>>7;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5) | ((t4 & 0x80)>>4);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            d+=84; // jump to byte directly below
+            }
+
+
+        /*write_command(0x20);  // Horizontal DRAM Address
+        write_data(0x10);  // 0
+        write_command(0x21);  // Vertical DRAM Address
+        write_data(xptr++);
+        write_command(0x22); // write data to DRAM
+        CLR_CS_SET_CD_RD_WR;*/
+        /** draw border **/
+        setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;        CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+
+        s=0;
+
+        /** draw scanlines **/
+        for (s=0;s<48;) {
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+        }
+        /** draw border **/
+        setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;        CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+
+
+        /*write_command(0x20);  // Horizontal DRAM Address
+        write_data(0x10);  // 0
+        write_command(0x21);  // Vertical DRAM Address
+        write_data(xptr++);
+        write_command(0x22); // write data to DRAM
+        CLR_CS_SET_CD_RD_WR;*/
+        /** draw border **/
+        setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;        CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+
+        for (s=0;s<48;) {
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+        }
+
+        /** draw border **/
+        setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;        CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+
+
+        #if POK_STRETCH
+        //if (x>16 && x<68)
+        if (x&2)// && x&2)
+        {
+            /*write_command(0x20);  // Horizontal DRAM Address
+            write_data(0x10);  // 0
+            write_command(0x21);  // Vertical DRAM Address
+            write_data(xptr++);
+            write_command(0x22); // write data to DRAM
+            CLR_CS_SET_CD_RD_WR;*/
+            /** draw border **/
+        setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;        CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+
+
+            for (s=0;s<48;) {
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+            }
+
+            /** draw border **/
+        setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;        CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;CLR_WR;SET_WR;
+
+        }
+        #endif
+    }
+    /** draw border **/
+    for (int s=0;s<5*176;) {
+            setup_data_16(COLOR_BLACK);CLR_WR;SET_WR;s++;
+    }
+}
+
+
+void Pokitto::lcdRefreshAB(uint8_t * scrbuf, uint16_t* paletteptr) {
+uint16_t x,y;
+uint16_t scanline[64];
+uint8_t *d;
+//lcdClear();
+#if POK_STRETCH
+uint16_t xptr = 14;
+uint8_t yoffset = 24;
+#else
+xptr = 0; //was 26
+#endif
+
+for(x=0;x<128;x++)
+  {
+    write_command(0x20);  // Horizontal DRAM Address
+    write_data(yoffset);  // 0
+    write_command(0x21);  // Vertical DRAM Address
+    write_data(xptr++);
+    write_command(0x22); // write data to DRAM
+    CLR_CS_SET_CD_RD_WR;
+    //setDRAMptr(xptr++,yoffset);
+
+        d = scrbuf + x;// point to beginning of line in data
+
+        /** find colours in one scanline **/
+        uint8_t s=0;
+        for(y=0;y<8;y++)
+            {
+            uint8_t t = *d;
+            #if POK_COLORDEPTH > 1
+            uint8_t t2 = *(d+AB_JUMP);
+            #endif // POK_COLORDEPTH
+            #if POK_COLORDEPTH > 2
+            uint8_t t3 = *(d+AB_JUMP+AB_JUMP);
+            #endif // POK_COLORDEPTH
+            #if POK_COLORDEPTH > 3
+            uint8_t t4 = *(d+AB_JUMP+AB_JUMP+AB_JUMP);
+            #endif // POK_COLORDEPTH
+            uint8_t paletteindex = 0;
+
+            /** bit 1 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x1);
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x1)) | ((t2 & 0x01)<<1);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = (t & 0x1) | ((t2 & 0x1)<<1) | ((t3 & 0x1)<<2) | ((t4 & 0x1)<<3);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 2 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x2)>>1;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x2)>>1) | ((t2 & 0x02));
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x2)>>1) | ((t2 & 0x2)) | ((t3 & 0x2)<<1) | ((t4 & 0x2)<<2);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 3 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x4)>>2;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 4)>>2) | ((t2 & 0x04)>>1);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x4)>>2) | ((t2 & 0x4)>>1) | (t3 & 0x4) | ((t4 & 0x4)<<1);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 4 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x8)>>3;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x8)>>3) | ((t2 & 0x08)>>2);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x8)>>3) | ((t2 & 0x8)>>2) | ((t3 & 0x8)>>1) | (t4 & 0x8);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 5 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x10)>>4;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x10)>>4) | ((t2 & 0x10)>>3) | ((t3 & 0x10)>>2) | ((t4 & 0x10)>>1);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 6 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x20)>>5;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x20)>>5) | ((t2 & 0x20)>>4) | ((t3 & 0x20)>>3) | ((t4 & 0x20)>>2);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 7 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x40)>>6;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) ;
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x40)>>6) | ((t2 & 0x40)>>5) | ((t3 & 0x40)>>4) | ((t4 & 0x40)>>3);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            /** bit 8 **/
+            #if POK_COLORDEPTH == 1
+            paletteindex = (t & 0x80)>>7;
+            #elif POK_COLORDEPTH == 2
+            paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6);
+            #elif POK_COLORDEPTH == 3
+            paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5);
+            #elif POK_COLORDEPTH == 4
+            paletteindex = ((t & 0x80)>>7) | ((t2 & 0x80)>>6) | ((t3 & 0x80)>>5) | ((t4 & 0x80)>>4);
+            #endif
+            scanline[s++] = paletteptr[paletteindex];
+
+            d+=128; // jump to byte directly below
+            }
+
+        s=0;
+
+        /** draw scanlines **/
+        for (s=0;s<64;) {
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        }
+
+        #if POK_STRETCH
+        if (x&1) {
+        write_command(0x20);  // Horizontal DRAM Address
+        write_data(yoffset);  // 0
+        write_command(0x21);  // Vertical DRAM Address
+        write_data(xptr++);
+        write_command(0x22); // write data to DRAM
+        CLR_CS_SET_CD_RD_WR;
+        //setDRAMptr(xptr++,yoffset);
+
+        for (s=0;s<64;) {
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        }
+        }
+        #endif
+    }
+}
+
+void Pokitto::lcdRefreshModeGBC(uint8_t * scrbuf, uint16_t* paletteptr) {
+uint16_t x,y,xptr;
+uint16_t scanline[4][144]; // read 4 half-nibbles = 4 pixels at a time
+uint8_t *d, yoffset=0;
+
+xptr = 0;
+setDRAMptr(xptr,yoffset);
+
+
+for(x=0;x<160;x+=4)
+  {
+    d = scrbuf+(x>>2);// point to beginning of line in data
+    /** find colours in one scanline **/
+    uint8_t s=0;
+    for(y=0;y<144;y++)
+    {
+    uint8_t tdata = *d;
+    uint8_t t4 = tdata & 0x03; tdata >>= 2;// lowest half-nibble
+    uint8_t t3 = tdata & 0x03; tdata >>= 2;// second lowest half-nibble
+    uint8_t t2 = tdata & 0x03; tdata >>= 2;// second highest half-nibble
+    uint8_t t = tdata & 0x03;// highest half-nibble
+
+    /** put nibble values in the scanlines **/
+
+    scanline[0][s] = paletteptr[t];
+    scanline[1][s] = paletteptr[t2];
+    scanline[2][s] = paletteptr[t3];
+    scanline[3][s++] = paletteptr[t4];
+
+     d+=160/4; // jump to read byte directly below in screenbuffer
+    }
+
+    s=0;
+    /** draw scanlines **/
+    for (s=0;s<144;) {
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;
+    }
+    setDRAMptr(++xptr,yoffset);
+    for (s=0;s<144;) {
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;
+    }
+    setDRAMptr(++xptr,yoffset);
+    for (s=0;s<144;) {
+        setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[2][s++]);CLR_WR;SET_WR;
+    }
+    setDRAMptr(++xptr,yoffset);
+    for (s=0;s<144;) {
+        setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+        setup_data_16(scanline[3][s++]);CLR_WR;SET_WR;
+    }
+    setDRAMptr(++xptr,yoffset);
+  }
+}
+
+
+void Pokitto::lcdRefreshT1(uint8_t* tilebuf, uint8_t* tilecolorbuf, uint8_t* tileset, uint16_t* paletteptr) {
+#ifdef POK_TILEMODE
+uint16_t x,y,data,xptr;
+uint16_t scanline[176];
+uint8_t yoffset=0, tilebyte, tileindex, tilex=0, tiley=0,xcount;
+
+
+if (!tileset) return;
+
+#if LCDWIDTH < POK_LCD_W
+xptr = (POK_LCD_W-LCDWIDTH)/2;
+#else
+xptr = 0;
+#endif
+#if LCDHEIGHT < POK_LCD_H
+yoffset = (POK_LCD_H-LCDHEIGHT)/2;
+#else
+yoffset = 0;
+#endif
+
+for(x=0, xcount=0 ;x<LCDWIDTH;x++,xcount++)  // loop through vertical columns
+  {
+    setDRAMptr(xptr++,yoffset); //point to VRAM
+
+        /** find colours in one scanline **/
+        uint8_t s=0, tiley=0;
+        //tileindex = tilebuf[tilex*POK_TILES_Y];
+        if (xcount==POK_TILE_W) {
+            tilex++;
+            xcount=0;
+        }
+
+        for(y=0;y<LCDHEIGHT;)
+        {
+            uint8_t tileval = tilebuf[tilex+tiley*POK_TILES_X]; //get tile number
+            uint16_t index = tileval*POK_TILE_W+xcount;
+            uint8_t tilebyte = tileset[index]; //get bitmap data
+            for (uint8_t ycount=0, bitcount=0; ycount<POK_TILE_H; ycount++, y++, bitcount++) {
+                if (bitcount==8) {
+                    bitcount=0;
+                    index += 176; //jump to byte below in the tileset bitmap
+                    tilebyte = tileset[index]; //get bitmap data
+                }
+                //tilebyte = tile[(tileindex>>4)+*POK_TILE_W]; //tilemaps are 16x16
+                //uint8_t paletteindex = ((tilebyte>>(bitcount&0x7)) & 0x1);
+                if (!tileval) scanline[s++] = COLOR_MAGENTA*((tilebyte>>bitcount)&0x1);//paletteptr[paletteindex];
+                else scanline[s++] = paletteptr[((tilebyte>>bitcount)&0x1)*tileval];//paletteptr[paletteindex];
+            }
+            tiley++; //move to next tile
+        }
+        s=0;
+
+        /** draw scanlines **/
+        for (s=0;s<LCDHEIGHT;) {
+            setup_data_16(scanline[s++]);CLR_WR;SET_WR;
+        }
+    }
+    #endif
+}
+
+
+void Pokitto::lcdRefreshMode13(uint8_t * scrbuf, uint16_t* paletteptr, uint8_t offset){
+uint16_t x,y;
+uint16_t scanline[2][110]; // read two nibbles = pixels at a time
+uint8_t *d;
+
+write_command(0x20); write_data(0);
+write_command(0x21); write_data(0);
+write_command(0x22);
+CLR_CS_SET_CD_RD_WR;
+
+for(x=0;x<110;x+=2)
+  {
+    d = scrbuf+x;// point to beginning of line in data
+    uint8_t s=0;
+    for(y=0;y<88;y++)
+    {
+        uint8_t t = *d;
+        uint8_t t1 = *(d+1);
+        scanline[0][s] = paletteptr[(t+offset)&255];
+        scanline[1][s++] = paletteptr[(t1+offset)&255];
+        d+=110; // jump to read byte directly below in screenbuffer
+    }
+    s=0;
+    for (s=0;s<88;) {
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+    for (s=0;s<88;) {
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[0][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+    for (s=0;s<88;) {
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+    for (s=0;s<88;) {
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+        setup_data_16(scanline[1][s++]);CLR_WR;SET_WR;CLR_WR;SET_WR;
+    }
+  }
+
+}
+
+
+
+
+void Pokitto::blitWord(uint16_t c) {
+    setup_data_16(c);CLR_WR;SET_WR;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/HWLCD.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,211 @@
+/**************************************************************************/
+/*!
+    @file     HWLCD.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#ifndef __HWLCD_H__
+#define __HWLCD_H__
+
+#include "mbed.h"
+#include "gpio_api.h"
+#include "pinmap.h"
+
+#define write_command write_command_16
+#define write_data write_data_16
+
+namespace Pokitto {
+
+struct SpriteInfo {
+    const uint8_t* bitmapData;
+    int16_t x;
+    int16_t y;
+    int16_t oldx;
+    int16_t oldy;
+    uint8_t w;
+    uint8_t h;
+    uint16_t palette[4];
+};
+
+extern void initBacklight();
+extern void setBacklight(float);
+extern void lcdFillSurface(uint16_t);
+extern void lcdPixel(int16_t x, int16_t y, uint16_t c);
+extern void setWindow(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
+extern void lcdTile(int16_t x0, int16_t y0, int16_t width, int16_t height, uint16_t* gfx);
+extern void lcdRectangle(int16_t x, int16_t y,int16_t x2, int16_t y2, uint16_t color);
+extern void lcdInit();
+extern void lcdSleep();
+extern void lcdWakeUp();
+extern void lcdRefresh(uint8_t *, uint16_t*);
+extern void lcdRefreshAB(uint8_t *, uint16_t*);
+extern void lcdRefreshGB(uint8_t *, uint16_t*);
+extern void lcdRefreshMode1(uint8_t* scrbuf, uint8_t updRectX, uint8_t updRectY, uint8_t updRectW, uint8_t updRectH, uint16_t* paletteptr);
+extern void lcdRefreshMode1Spr(uint8_t * scrbuf, uint8_t screenx, uint8_t screeny, uint8_t screenw, uint8_t screenh, uint16_t* paletteptr, Pokitto::SpriteInfo* sprites, bool drawSpritesOnly);
+extern void lcdRefreshMode2(uint8_t *, uint16_t*);
+extern void lcdRefreshMode3(uint8_t *, uint16_t*);
+extern void lcdRefreshModeGBC(uint8_t *, uint16_t*);
+extern void lcdRefreshMode13(uint8_t *, uint16_t*, uint8_t);
+
+/** Update LCD from 1-bit tile mode */
+extern void lcdRefreshT1(uint8_t*, uint8_t*, uint8_t*, uint16_t*);
+extern void lcdClear();
+extern void lcdFill(uint16_t);
+/** Blit one word of data*/
+extern void blitWord(uint16_t);
+
+/**************************************************************************/
+/**                          PINS AND PORTS                              **/
+/**************************************************************************/
+
+#if POK_BOARDREV == 1
+/** 2-layer board version 1.3 **/
+ #define LCD_CD_PORT           0
+ #define LCD_CD_PIN            2
+ #define LCD_WR_PORT           1
+ #define LCD_WR_PIN            23
+ #define LCD_RD_PORT           1
+ #define LCD_RD_PIN            24
+ #define LCD_RES_PORT          1
+ #define LCD_RES_PIN           28
+#else
+/** 4-layer board version 2.1 **/
+ #define LCD_CD_PORT           0
+ #define LCD_CD_PIN            2
+ #define LCD_WR_PORT           1
+ #define LCD_WR_PIN            12
+ #define LCD_RD_PORT           1
+ #define LCD_RD_PIN            24
+ #define LCD_RES_PORT          1
+ #define LCD_RES_PIN           0
+#endif
+
+/**************************************************************************/
+/**                          LCD CONTROL MACROS                          **/
+/**************************************************************************/
+
+#define CLR_RESET LPC_GPIO_PORT->CLR[LCD_RES_PORT] = 1 << LCD_RES_PIN; //RST = (0); // Clear pin
+#define SET_RESET LPC_GPIO_PORT->SET[LCD_RES_PORT] = 1 << LCD_RES_PIN; // RST = (1); // Set pin
+
+#define CLR_CD { LPC_GPIO_PORT->CLR[LCD_CD_PORT] = 1 << LCD_CD_PIN; } // RS = (0); // Clear pin
+#define SET_CD { LPC_GPIO_PORT->SET[LCD_CD_PORT] = 1 << LCD_CD_PIN; }// RS = (1); // Set pin
+
+#define CLR_WR { LPC_GPIO_PORT->CLR[LCD_WR_PORT] = 1 << LCD_WR_PIN; __asm("nop");__asm("nop");}//WR = (0); // Clear pin
+#define SET_WR LPC_GPIO_PORT->SET[LCD_WR_PORT] = 1 << LCD_WR_PIN; //WR = (1); // Set pin
+
+#define CLR_RD LPC_GPIO_PORT->CLR[LCD_RD_PORT] = 1 << LCD_RD_PIN; //RD = (0); // Clear pin
+#define SET_RD LPC_GPIO_PORT->SET[LCD_RD_PORT] = 1 << LCD_RD_PIN; //RD = (1); // Set pin
+
+#define SET_CS  //CS tied to ground
+#define CLR_CS
+
+#define CLR_CS_CD_SET_RD_WR {CLR_CD; SET_RD; SET_WR;}
+#define CLR_CS_SET_CD_RD_WR {SET_CD; SET_RD; SET_WR;}
+#define SET_CD_RD_WR {SET_CD; SET_RD; SET_WR;}
+#define SET_WR_CS SET_WR;
+
+#define SET_MASK_P2 LPC_GPIO_PORT->MASK[2] = ~(0x7FFF8); //mask P2_3 ...P2_18
+#define CLR_MASK_P2 LPC_GPIO_PORT->MASK[2] = 0; // all on
+
+
+
+/**************************************************************************/
+/**                          SETUP GPIO & DATA                           **/
+/**************************************************************************/
+
+static void setup_gpio()
+{
+    /** control lines **/
+    LPC_GPIO_PORT->DIR[LCD_CD_PORT] |= (1  << LCD_CD_PIN );
+    LPC_GPIO_PORT->DIR[LCD_WR_PORT] |= (1  << LCD_WR_PIN );
+    LPC_GPIO_PORT->DIR[LCD_RD_PORT] |= (1  << LCD_RD_PIN );
+    LPC_GPIO_PORT->DIR[LCD_RES_PORT] |= (1  << LCD_RES_PIN );
+    /** data lines **/
+    LPC_GPIO_PORT->DIR[2] |= (0xFFFF  << 3);  // P2_3...P2_18 as output
+
+    pin_mode(P2_3,PullNone); // turn off pull-up
+    pin_mode(P2_4,PullNone); // turn off pull-up
+    pin_mode(P2_5,PullNone); // turn off pull-up
+    pin_mode(P2_6,PullNone); // turn off pull-up
+
+    pin_mode(P2_7,PullNone); // turn off pull-up
+    pin_mode(P2_8,PullNone); // turn off pull-up
+    pin_mode(P2_9,PullNone); // turn off pull-up
+    pin_mode(P2_10,PullNone); // turn off pull-up
+
+    pin_mode(P2_11,PullNone); // turn off pull-up
+    pin_mode(P2_12,PullNone); // turn off pull-up
+    pin_mode(P2_13,PullNone); // turn off pull-up
+    pin_mode(P2_14,PullNone); // turn off pull-up
+
+    pin_mode(P2_15,PullNone); // turn off pull-up
+    pin_mode(P2_16,PullNone); // turn off pull-up
+    pin_mode(P2_17,PullNone); // turn off pull-up
+    pin_mode(P2_18,PullNone); // turn off pull-up
+}
+
+
+
+
+#define HI_BYTE(d) (LPC_GPIO->MPIN[1]= (d<<13)) //((d>>8)<<21))
+#define LO_BYTE(d) (LPC_GPIO->MPIN[1]= (d<<21)) //because of mask makes no difference
+
+// Macros to set data bus direction to input/output
+#define LCD_GPIO2DATA_SETINPUT  GPIO_GPIO2DIR &= ~LCD_DATA_MASK
+#define LCD_GPIO2DATA_SETOUTPUT GPIO_GPIO2DIR |= LCD_DATA_MASK
+
+
+// Basic Color definitions
+#define	COLOR_BLACK                         (uint16_t)(0x0000)
+#define	COLOR_BLUE                          (uint16_t)(0x001F)
+#define	COLOR_RED                           (uint16_t)(0xF800)
+#define	COLOR_GREEN                         (uint16_t)(0x07E0)
+#define COLOR_CYAN                          (uint16_t)(0x07FF)
+#define COLOR_MAGENTA                       (uint16_t)(0xF81F)
+#define COLOR_YELLOW                        (uint16_t)(0xFFE0)
+#define COLOR_WHITE                         (uint16_t)(0xFFFF)
+
+// Grayscale Values
+#define COLOR_GRAY_15                       (uint16_t)(0x0861)    //  15  15  15
+#define COLOR_GRAY_30                       (uint16_t)(0x18E3)    //  30  30  30
+#define COLOR_GRAY_50                       (uint16_t)(0x3186)    //  50  50  50
+#define COLOR_GRAY_80                       (uint16_t)(0x528A)    //  80  80  80
+#define COLOR_GRAY_128                      (uint16_t)(0x8410)    // 128 128 128
+#define COLOR_GRAY_200                      (uint16_t)(0xCE59)    // 200 200 200
+#define COLOR_GRAY_225                      (uint16_t)(0xE71C)    // 225 225 225
+
+
+} // namespace pokitto
+#endif // __HWLCD_H_
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/HWSound.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,445 @@
+/**************************************************************************/
+/*!
+    @file     HWSound.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "mbed.h"
+#include "HWSound.h"
+//#include "MCP4018.h"
+#include "SoftwareI2C.h"
+#include "Pokitto_settings.h"
+#include "PokittoDisk.h"
+#include "PokittoGlobs.h"
+#include "Synth.h"
+#include "timer_11u6x.h"
+#include "clock_11u6x.h"
+//#include "beat_11025.h"
+
+
+
+
+using namespace Pokitto;
+
+#ifndef POK_SIM
+pwmout_t* obj = &audiopwm;
+#endif
+
+/** Sound Variables **/
+#if (POK_STREAMING_MUSIC > 0)
+    unsigned char buffers[4][BUFFER_SIZE];
+    volatile int currentBuffer = 0, oldBuffer = 0;
+    volatile int bufindex = 0, vol=1;
+    volatile unsigned char * currentPtr;
+    volatile unsigned char * endPtr;
+    int8_t streamvol=3;
+    uint32_t streamcounter=0;
+    uint8_t streamstep=0;
+#endif
+
+#if POK_ENABLE_SOUND > 0
+	pwmout_t Pokitto::audiopwm; // this way (instead of PwmOut class) pwm doesn't start screaming until it is initialized !
+    //Ticker Pokitto::audio;
+
+using namespace Pokitto;
+
+/** stream output and status */
+uint8_t Pokitto::streambyte,Pokitto::streamon;
+
+uint8_t soundbuf[256], soundbufindex=0, Pokitto::HWvolume=0;
+bool volpotError=false; //test for broken MCP4018
+
+uint16_t soundbyte;
+
+
+#if POK_USE_DAC > 0
+#if POK_BOARDREV == 1
+ /** 2-layer board rev 1.3 **/
+ DigitalOut dac0(P1_6);
+ DigitalOut dac1(P1_0);
+ DigitalOut dac2(P1_16);
+ DigitalOut dac3(P0_19);
+ DigitalOut dac4(P0_17);
+ DigitalOut dac5(P1_12);
+ DigitalOut dac6(P1_15);
+ DigitalOut dac7(P1_8);
+#else
+ /** 4-layer board rev 2.1 **/
+ DigitalOut dac0(P1_28);
+ DigitalOut dac1(P1_29);
+ DigitalOut dac2(P1_30);
+ DigitalOut dac3(P1_31);
+ /* has daniel made a mistake ?*/
+ DigitalOut dac4(P2_20);
+ DigitalOut dac5(P2_21);
+ DigitalOut dac6(P2_22);
+ DigitalOut dac7(P2_23);
+
+ DigitalOut amp(P1_17);
+
+#endif // POK_BOARDREV
+#endif // POK_USE_DAC
+
+#if POK_BOARDREV == 2
+//MCP4018 volpot(P0_5,P0_4);
+
+/**
+ * @brief	Handle interrupt from 32-bit timer 0
+ * @return	Nothing
+ */
+
+uint32_t p=0;
+
+extern "C" void TIMER32_0_IRQHandler(void)
+{
+	if (Chip_TIMER_MatchPending(LPC_TIMER32_0, 1)) {
+		Chip_TIMER_ClearMatch(LPC_TIMER32_0, 1);
+		//pokSoundBufferedIRQ();
+		pokSoundIRQ();
+	}
+}
+
+
+void initHWvolumecontrol() {
+    HWvolume=0;
+   	volpotError=true;
+    //if (volpot.put(HWvolume)) volpotError=true; //try if MCP4018 answers
+    setHWvolume(VOLUME_STARTUP);
+}
+
+int Pokitto::setHWvolume(uint8_t v) {
+    HWvolume = 0x7F&v;
+    //if (!volpotError) return volpot.put(HWvolume); //use normal I2C
+    /* fallback method for broken MCP4018 */
+    SoftwareI2C swvolpot(P0_4, P0_5); //swapped SDA,SCL
+    swvolpot.write(0x5e,HWvolume);
+	return HWvolume;
+}
+
+uint8_t Pokitto::getHWvolume() {
+    return HWvolume;
+}
+
+void Pokitto::changeHWvolume(int8_t v) {
+    int temp  = HWvolume + v;
+    if (temp < 0) temp = 0; //prevent volume "looparound" than can make a massive crack
+    if (temp > 127) temp = 127;
+    setHWvolume(temp);
+}
+
+ uint8_t Pokitto::ampIsOn() {
+    return amp;
+ }
+
+ void Pokitto::ampEnable(uint8_t v) {
+    if (v>1) v=1; // limit against funny values
+    amp=v;
+ }
+#endif // POK_BOARDREV == 2
+
+void Pokitto::dac_write(uint8_t value) {
+    #if POK_USE_DAC > 0
+    #if POK_BOARDREV == 1 // was 1
+    if (value & 1) SET_DAC0 else CLR_DAC0;
+    value >>= 1;
+    if (value & 1) SET_DAC1 else CLR_DAC1;
+    value >>= 1;
+    if (value & 1) SET_DAC2 else CLR_DAC2;
+    value >>= 1;
+    if (value & 1) SET_DAC3 else CLR_DAC3;
+    value >>= 1;
+    if (value & 1) SET_DAC4 else CLR_DAC4;
+    value >>= 1;
+    if (value & 1) SET_DAC5 else CLR_DAC5;
+    value >>= 1;
+    if (value & 1) SET_DAC6 else CLR_DAC6;
+    value >>= 1;
+    if (value & 1) SET_DAC7 else CLR_DAC7;
+    #else
+    //uint32_t val;
+    //val = value<<28; //lower 4 bits go higher - because port mask is used, no AND is needed to clear bits
+    //val += value<<(15-4); //higher 4 bits go lower. No need to shift by 15 because bits are in the higher nibble
+    /* daniel has made a mistake with ports */
+    //val = ((value&0x70)<<(28-4)); //higher 4 bits go higher - because port mask is used, no AND is needed to clear bits
+    //val += value<<(15); //lower 4 bits go lower. No need to shift by 15 because bits are in the higher nibble
+    //SET_MASK_DAC;
+    //LPC_GPIO_PORT->MPIN[1] = val; // write bits to port
+    //CLR_MASK_DAC;
+    /* fixed here */
+    /*val=value;
+    SET_MASK_DAC_LO;
+    LPC_GPIO_PORT->MPIN[1] = val<<28; // write lower 4 bits to port
+    CLR_MASK_DAC_LO;
+    SET_MASK_DAC_HI;
+    LPC_GPIO_PORT->MPIN[2] = val<<(20-4); // write bits to port
+    CLR_MASK_DAC_HI; */
+    if (value & 1) SET_DAC0 else CLR_DAC0;
+    value >>= 1;
+    if (value & 1) SET_DAC1 else CLR_DAC1;
+    value >>= 1;
+    if (value & 1) SET_DAC2 else CLR_DAC2;
+    value >>= 1;
+    if (value & 1) SET_DAC3 else CLR_DAC3;
+    value >>= 1;
+    if (value & 1) SET_DAC4 else CLR_DAC4;
+    value >>= 1;
+    if (value & 1) SET_DAC5 else CLR_DAC5;
+    value >>= 1;
+    if (value & 1) SET_DAC6 else CLR_DAC6;
+    value >>= 1;
+    if (value & 1) SET_DAC7 else CLR_DAC7;
+    //CLR_MASK_DAC;
+    #endif // BOARDREV
+    #endif
+}
+
+/** SOUND INIT **/
+void Pokitto::soundInit() {
+    uint32_t timerFreq;
+    pwmout_init(&audiopwm,POK_AUD_PIN);
+    pwmout_period_us(&audiopwm,POK_AUD_PWM_US); //was 31us
+    pwmout_write(&audiopwm,0.1f);
+
+    #if POK_GBSOUND > 0
+    /** GAMEBUINO SOUND **/
+    audio.attach_us(&audio_IRQ, 1000000/(POK_AUD_FREQ>>0));
+    #else
+    /** NOT GAMEBUINO SOUND **/
+    //audio.attach_us(&pokSoundBufferedIRQ, 1000000/(POK_AUD_FREQ>>0));
+     /* Initialize 32-bit timer 0 clock */
+	Chip_TIMER_Init(LPC_TIMER32_0);
+
+    /* Timer rate is system clock rate */
+	timerFreq = Chip_Clock_GetSystemClockRate();
+
+	/* Timer setup for match and interrupt at TICKRATE_HZ */
+	Chip_TIMER_Reset(LPC_TIMER32_0);
+
+	/* Enable both timers to generate interrupts when time matches */
+	Chip_TIMER_MatchEnableInt(LPC_TIMER32_0, 1);
+
+    /* Setup 32-bit timer's duration (32-bit match time) */
+	Chip_TIMER_SetMatch(LPC_TIMER32_0, 1, (timerFreq / POK_AUD_FREQ));
+
+	/* Setup both timers to restart when match occurs */
+	Chip_TIMER_ResetOnMatchEnable(LPC_TIMER32_0, 1);
+
+	/* Start both timers */
+	Chip_TIMER_Enable(LPC_TIMER32_0);
+
+	/* Clear both timers of any pending interrupts */
+    #define TIMER_32_0_IRQn 18
+	NVIC_ClearPendingIRQ((IRQn_Type)TIMER_32_0_IRQn);
+
+    /* Redirect IRQ vector - Jonne*/
+    NVIC_SetVector((IRQn_Type)TIMER_32_0_IRQn, (uint32_t)&TIMER32_0_IRQHandler);
+
+	/* Enable both timer interrupts */
+	NVIC_EnableIRQ((IRQn_Type)TIMER_32_0_IRQn);
+    #endif // POK_GAMEBUINO_SUPPORT
+
+    //emptySong();
+    //emptyOscillators();
+    //emptyBlocks();
+    //emptyPatches();
+    #ifdef TEST_SOUND
+        testOsc();
+    #endif // TEST_SOUND
+    #if POK_BOARDREV == 2
+        initHWvolumecontrol();
+    #endif
+
+}
+
+
+uint8_t Pokitto::streamPaused() {
+    return !streamon;
+}
+
+void Pokitto::pauseStream() {
+    streamon=0;
+}
+
+void Pokitto::playStream() {
+    streamon=1;
+}
+
+
+void pokPauseStream() {
+    streamon=0;
+}
+
+void pokPlayStream() {
+    streamon=1;
+}
+
+
+
+void pokSoundBufferedIRQ() {
+           uint8_t output = soundbuf[soundbufindex++];
+           //if (p==sizeof(beat_11025_raw)) p=0;
+           //soundbuf[soundbufindex++] = output;
+           uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*output)>>8); //cut out float
+           obj->pwm->MATCHREL1 = t_on;
+}
+
+void pokSoundIRQ() {
+    //#define TICKY 0xFFFF //160
+    //#define INCY 409
+    uint8_t output=0;
+    //if (test==TICKY) test=0;
+    //if (test<(TICKY/2)) { tpin=1; pwmout_write(&audiopwm,(float)0/(float)255);}//dac_write(0);}
+    //else {tpin=0; pwmout_write(&audiopwm,(float)255/(float)255);}//dac_write(64);}
+    //test+=INCY;
+    //return;
+    #ifndef POK_SIM
+    pwmout_t* obj = &audiopwm;
+    #endif
+    #if POK_STREAMING_MUSIC > 0
+        #if POK_STREAMFREQ_HALVE
+        streamstep = 1-streamstep;
+        #else
+        streamstep = 1;
+        #endif // POK_STREAMFREQ_HALVE
+        streamstep &= streamon; // streamon is used to toggle SD music streaming on and off
+        if (streamstep) {
+            output = (*currentPtr++);
+            if(streamvol && streamon) {
+                output >>= 3-streamvol;
+                streambyte = output;
+            } else {
+                streambyte = 0; // duty cycle
+                output = 0;
+            }
+            if (currentPtr >= endPtr)
+            {
+            currentBuffer++;
+            if (currentBuffer==4) currentBuffer=0;
+            currentPtr = buffers[currentBuffer];
+            endPtr = currentPtr + BUFFER_SIZE;
+            }
+        }
+    #endif // POK_STREAMING_MUSIC
+
+    /** DO ADDITIONAL SOUND PROCESSING (NOT STREAM) OF SOUND HERE **/
+
+    #if POK_ENABLE_SYNTH
+        /** if song is being played from sd **/
+        if (playing) {
+                notetick++;
+                updatePlaybackSD(playerpos&7);
+        }
+        /** oscillators update **/
+        osc1.count += osc1.cinc + (osc1.pitchbend >> 4); // counts to 65535 and overflows to zero WAS 8 !
+        osc2.count += osc2.cinc + (osc2.pitchbend >> 4); // counts to 65535 and overflows to zero
+        osc3.count += osc3.cinc + (osc3.pitchbend >> 4); // counts to 65535 and overflows to zero
+        Marr[tick](); // call mixing function
+        --tick;
+
+        /** mixing oscillator output **/
+
+        uint16_t op = (uint16_t) ((osc1.output)*(osc1.vol>>8))>>9;// >> 2 osc1.vol Marr;
+        op += (uint16_t) ((osc2.output)*(osc2.vol>>8))>>9;// >> 2 osc1.vol Marr;
+        op += (uint16_t) ((osc3.output)*(osc3.vol>>8))>>9;// >> 2 osc1.vol Marr;
+        output = (uint8_t) op;
+
+    #endif // POK_ENABLE_SYNTH
+
+    #ifndef POK_SIM
+    /** HARDWARE **/
+        #if POK_ENABLE_SOUND > 0
+            #if POK_STREAMING_MUSIC > 0
+                /** sound is enabled, streaming is enabled */
+                #if POK_STREAM_TO_DAC > 0
+                    /** stream goes to DAC */
+                    #if POK_USE_DAC > 0
+                    if (streamstep) dac_write((uint8_t)streambyte); // duty cycle
+                    #endif // POK_USE_DAC
+                #else
+                    /** stream goes to PWM */
+                    if (streamstep) {
+                            //pwmout_write(&audiopwm,(float)streambyte/(float)255);
+                            uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*streambyte)>>8); //cut out float
+                            obj->pwm->MATCHREL1 = t_on;
+                            //dac_write((uint8_t)streambyte); // duty cycle
+                    }
+                #endif // POK_STREAM_TO_DAC
+            #endif // POK_STREAMING_MUSIC
+            #if POK_STREAM_TO_DAC > 0
+            /** synth goes to PWM */
+            //pwmout_write(&audiopwm,(float)output/(float)255);
+            uint32_t t_on = (uint32_t)(((obj->pwm->MATCHREL0)*output)>>8); //cut out float
+            obj->pwm->MATCHREL1 = t_on;
+            #else
+            dac_write((uint8_t)output);
+            #endif // decide where synth is output
+            soundbyte = (output+streambyte)>>1;
+            soundbuf[soundbufindex++]=soundbyte;
+        #endif //POK_ENABLE_SOUND
+    #endif // HARDWARE
+}
+
+
+void Pokitto::updateSDAudioStream() {
+    if (streamPaused()) return;
+
+    #if POK_STREAMING_MUSIC > 0
+    if (oldBuffer != currentBuffer) {
+        if (currentBuffer==0) fileReadBytes(&buffers[3][0],BUFFER_SIZE);
+        else if (currentBuffer==1) fileReadBytes(&buffers[0][0],BUFFER_SIZE);
+        else if (currentBuffer==2) fileReadBytes(&buffers[1][0],BUFFER_SIZE);
+        else fileReadBytes(&buffers[2][0],BUFFER_SIZE);
+        oldBuffer = currentBuffer;
+        streamcounter += BUFFER_SIZE;
+    } else return;
+
+    #ifndef POK_SIM
+    if ( streamcounter > fs.fsize - (BUFFER_SIZE*6)) {
+    #else
+    if ( streamcounter > getFileLength() - (BUFFER_SIZE*6)) {
+    #endif
+        streamcounter=0;
+        #if POK_STREAM_LOOP
+        fileRewind();
+        #else
+        pokPauseStream();
+        #endif
+    }
+    #endif
+}
+
+
+#endif // POK_ENABLE_SOUND
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/HWSound.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,163 @@
+/**************************************************************************/
+/*!
+    @file     HWSOUND.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+#ifndef HWSOUND_H
+#define HWSOUND_H
+
+#include "mbed.h"
+#include "Pokitto_settings.h"
+
+#define SPEAKER 3
+#define BUFFER_SIZE 512*4 //*8 //*8 // 512 // was 512 (works really well with crabator) was 256
+
+#if POK_BOARDREV == 1
+ /** 2-layer board rev 1.3 **/
+ #define DAC0_PORT   1
+ #define DAC0_PIN    6
+ #define DAC1_PORT   1
+ #define DAC1_PIN    0
+ #define DAC2_PORT   1
+ #define DAC2_PIN    16
+ #define DAC3_PORT   0
+ #define DAC3_PIN    19
+ #define DAC4_PORT   0
+ #define DAC4_PIN    17
+ #define DAC5_PORT   1
+ #define DAC5_PIN    12
+ #define DAC6_PORT   1
+ #define DAC6_PIN    15
+ #define DAC7_PORT   1
+ #define DAC7_PIN    8
+#else
+ /** 4-layer board rev 2.1 **/
+ #define DAC0_PORT   1
+ #define DAC0_PIN    28
+ #define DAC1_PORT   1
+ #define DAC1_PIN    29
+ #define DAC2_PORT   1
+ #define DAC2_PIN    30
+ #define DAC3_PORT   1
+ #define DAC3_PIN    31
+/** has daniel made a mistake with dac ? **/
+ #define DAC4_PORT   2
+ #define DAC4_PIN    20
+ #define DAC5_PORT   2
+ #define DAC5_PIN    21
+ #define DAC6_PORT   2
+ #define DAC6_PIN    22
+ #define DAC7_PORT   2
+ #define DAC7_PIN    23
+
+ /** MASK FOR FASTER DAC **/
+ #define SET_MASK_DAC LPC_GPIO_PORT->MASK[1] = ~(0xF0078000); //mask P1_15...P1_18 and P1_28...P1_31
+ #define CLR_MASK_DAC LPC_GPIO_PORT->MASK[1] = 0; // all on
+
+ /* fixing wrong pins from daniel*/
+ #define SET_MASK_DAC_LO LPC_GPIO_PORT->MASK[1] = ~(0xF0000000); //mask P1_28...P1_31
+ #define CLR_MASK_DAC_LO LPC_GPIO_PORT->MASK[1] = 0; // all on
+ #define SET_MASK_DAC_HI LPC_GPIO_PORT->MASK[2] = ~(0xF00000); //mask P2_20...P2_23
+ #define CLR_MASK_DAC_HI LPC_GPIO_PORT->MASK[2] = 0; // all on
+
+#endif
+
+#define CLR_DAC0 LPC_GPIO_PORT->CLR[DAC0_PORT] = 1UL << DAC0_PIN;
+#define SET_DAC0 LPC_GPIO_PORT->SET[DAC0_PORT] = 1UL << DAC0_PIN;
+#define CLR_DAC1 LPC_GPIO_PORT->CLR[DAC1_PORT] = 1UL << DAC1_PIN;
+#define SET_DAC1 LPC_GPIO_PORT->SET[DAC1_PORT] = 1UL << DAC1_PIN;
+#define CLR_DAC2 LPC_GPIO_PORT->CLR[DAC2_PORT] = 1UL << DAC2_PIN;
+#define SET_DAC2 LPC_GPIO_PORT->SET[DAC2_PORT] = 1UL << DAC2_PIN;
+#define CLR_DAC3 LPC_GPIO_PORT->CLR[DAC3_PORT] = 1UL << DAC3_PIN;
+#define SET_DAC3 LPC_GPIO_PORT->SET[DAC3_PORT] = 1UL << DAC3_PIN;
+#define CLR_DAC4 LPC_GPIO_PORT->CLR[DAC4_PORT] = 1UL << DAC4_PIN;
+#define SET_DAC4 LPC_GPIO_PORT->SET[DAC4_PORT] = 1UL << DAC4_PIN;
+#define CLR_DAC5 LPC_GPIO_PORT->CLR[DAC5_PORT] = 1UL << DAC5_PIN;
+#define SET_DAC5 LPC_GPIO_PORT->SET[DAC5_PORT] = 1UL << DAC5_PIN;
+#define CLR_DAC6 LPC_GPIO_PORT->CLR[DAC6_PORT] = 1UL << DAC6_PIN;
+#define SET_DAC6 LPC_GPIO_PORT->SET[DAC6_PORT] = 1UL << DAC6_PIN;
+#define CLR_DAC7 LPC_GPIO_PORT->CLR[DAC7_PORT] = 1UL << DAC7_PIN;
+#define SET_DAC7 LPC_GPIO_PORT->SET[DAC7_PORT] = 1UL << DAC7_PIN;
+
+/** the output holder **/
+extern uint16_t soundbyte;
+
+namespace Pokitto {
+
+
+/** stream output and status */
+extern uint8_t streambyte, streamon, HWvolume;
+
+extern float pwm2; //virtual pwm output
+
+extern void soundInit();
+extern void dac_write(uint8_t value);
+extern uint8_t ampIsOn();
+extern void ampEnable(uint8_t v);
+extern void audio_IRQ();
+extern void updateSDAudioStream();
+extern uint8_t streamPaused();
+extern void pauseStream();
+extern void playStream();
+extern int setHWvolume(uint8_t);
+extern uint8_t getHWvolume();
+extern void changeHWvolume(int8_t);
+
+extern pwmout_t audiopwm;
+extern uint8_t pokAmpIsOn();
+extern void pokAmpEnable(uint8_t);
+
+extern Ticker audio;
+
+extern void update_SDAudioStream();
+}
+
+
+extern void pokSoundIRQ();
+extern void pokSoundBufferedIRQ();
+
+#if POK_STREAMING_MUSIC > 0
+    extern unsigned char buffers[][BUFFER_SIZE];
+    extern volatile int currentBuffer, oldBuffer;
+    extern volatile int bufindex, vol;
+    extern volatile unsigned char * currentPtr;
+    extern volatile unsigned char * endPtr;
+    extern int8_t streamvol;
+    extern uint32_t streamcounter;
+    extern uint8_t streamstep;
+#endif
+
+#endif //HWSOUND_H
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/PokittoClock.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,82 @@
+/**************************************************************************/
+/*!
+    @file     PokittoClock.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2015, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoCore.h"
+#include "pinmap.h"
+#include "HWLCD.h"
+#include "Pokitto_settings.h"
+#include "wait_api.h"
+
+uint32_t pt_count=0;
+uint32_t* ptimer;
+
+extern "C" {
+void SysTick_Handler(void) {
+    //interrupt happens when systick has counted down to zero
+    #if PROJ_GAMEBOY > 0
+    uint32_t a;
+    a = *ptimer;
+    *ptimer = a + 1;
+    #endif
+    pt_count+=10;                        // increment counter
+}}
+
+using namespace Pokitto;
+
+uint32_t Core::refreshtime;
+
+void Core::initClock() {
+        // to get 1000 interrupts per second the reload value should be 48000
+    #if PROJ_GAMEBOY > 0
+    ptimer = &pt_count;
+    SysTick->LOAD = 480000-1;
+    #else
+    SysTick->LOAD = 480000-1;
+    #endif
+    SysTick->VAL  = 0;
+    SysTick->CTRL  = 4 | 2 | 1; //CLKSOURCE=CPU clock | TICKINT | ENABLE
+    pt_count = 0;
+}
+
+uint32_t Core::getTime() {
+    return pt_count;
+}
+
+void Core::wait(uint16_t ms) {
+    wait_ms(ms);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/PokittoEEPROM.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,147 @@
+/*
+  EEPROM.h - EEPROM library
+  Original Copyright (c) 2006 David A. Mellis.  All right reserved.
+  New version by Christopher Andrews 2015.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef EEPROM_h
+#define EEPROM_h
+
+#include <stdint.h>
+#include "iap.h"
+
+/***
+    EERef class.
+
+    This object references an EEPROM cell.
+    Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM.
+    This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell.
+***/
+
+struct EERef{
+
+    EERef( const int index )
+        : index( index )                 {}
+
+    //Access/read members.
+    uint8_t operator*() const            { return eeprom_read_byte( (uint16_t*) index ); }
+    operator const uint8_t() const       { return **this; }
+
+    //Assignment/write members.
+    EERef &operator=( const EERef &ref ) { return *this = *ref; }
+    EERef &operator=( uint8_t in )       { return eeprom_write_byte( (uint16_t*) index, in ), *this;  }
+    EERef &operator +=( uint8_t in )     { return *this = **this + in; }
+    EERef &operator -=( uint8_t in )     { return *this = **this - in; }
+    EERef &operator *=( uint8_t in )     { return *this = **this * in; }
+    EERef &operator /=( uint8_t in )     { return *this = **this / in; }
+    EERef &operator ^=( uint8_t in )     { return *this = **this ^ in; }
+    EERef &operator %=( uint8_t in )     { return *this = **this % in; }
+    EERef &operator &=( uint8_t in )     { return *this = **this & in; }
+    EERef &operator |=( uint8_t in )     { return *this = **this | in; }
+    EERef &operator <<=( uint8_t in )    { return *this = **this << in; }
+    EERef &operator >>=( uint8_t in )    { return *this = **this >> in; }
+
+    EERef &update( uint8_t in )          { return  in != *this ? *this = in : *this; }
+
+    /** Prefix increment/decrement **/
+    EERef& operator++()                  { return *this += 1; }
+    EERef& operator--()                  { return *this -= 1; }
+
+    /** Postfix increment/decrement **/
+    uint8_t operator++ (int){
+        uint8_t ret = **this;
+        return ++(*this), ret;
+    }
+
+    uint8_t operator-- (int){
+        uint8_t ret = **this;
+        return --(*this), ret;
+    }
+
+    int index; //Index of current EEPROM cell.
+};
+
+/***
+    EEPtr class.
+
+    This object is a bidirectional pointer to EEPROM cells represented by EERef objects.
+    Just like a normal pointer type, this can be dereferenced and repositioned using
+    increment/decrement operators.
+***/
+
+struct EEPtr{
+
+    EEPtr( const int index )
+        : index( index )                {}
+
+    operator const int() const          { return index; }
+    EEPtr &operator=( int in )          { return index = in, *this; }
+
+    //Iterator functionality.
+    bool operator!=( const EEPtr &ptr ) { return index != ptr.index; }
+    EERef operator*()                   { return index; }
+
+    /** Prefix & Postfix increment/decrement **/
+    EEPtr& operator++()                 { return ++index, *this; }
+    EEPtr& operator--()                 { return --index, *this; }
+    EEPtr operator++ (int)              { return index++; }
+    EEPtr operator-- (int)              { return index--; }
+
+    int index; //Index of current EEPROM cell.
+};
+
+/***
+    EEPROMClass class.
+
+    This object represents the entire EEPROM space.
+    It wraps the functionality of EEPtr and EERef into a basic interface.
+    This class is also 100% backwards compatible with earlier Arduino core releases.
+***/
+
+struct EEPROMClass{
+
+    //Basic user access methods.
+    EERef operator[]( const int idx )    { return idx; }
+    uint8_t read( int idx )              { return EERef( idx ); }
+    void write( int idx, uint8_t val )   { (EERef( idx )) = val; }
+    void update( int idx, uint8_t val )  { EERef( idx ).update( val ); }
+
+    //STL and C++11 iteration capability.
+    EEPtr begin()                        { return 0x00; }
+    EEPtr end()                          { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid.
+    uint16_t length()                    { return 0x1000; } // length for pokitto is 4kB
+
+    //Functionality to 'get' and 'put' objects to and from EEPROM.
+    template< typename T > T &get( int idx, T &t ){
+        EEPtr e = idx;
+        uint8_t *ptr = (uint8_t*) &t;
+        for( int count = sizeof(T) ; count ; --count, ++e )  *ptr++ = *e;
+        return t;
+    }
+
+    template< typename T > const T &put( int idx, const T &t ){
+        EEPtr e = idx;
+        const uint8_t *ptr = (const uint8_t*) &t;
+        for( int count = sizeof(T) ; count ; --count, ++e )  (*e).update( *ptr++ );
+        return t;
+    }
+};
+
+static EEPROMClass EEPROM;
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/PokittoHW.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,87 @@
+/**************************************************************************/
+/*!
+    @file     PokittoHW.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2015, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoCore.h"
+#include "pinmap.h"
+#include "HWLCD.h"
+
+
+using namespace Pokitto;
+
+
+void Core::quit() {
+    run_state = false;
+}
+
+void Core::initRandom() {
+    //TODO: hook random seed to battery level
+}
+
+void Core::initGPIO() {
+    /** control lines **/
+    LPC_GPIO_PORT->DIR[LCD_CD_PORT] |= (1  << LCD_CD_PIN );
+    LPC_GPIO_PORT->DIR[LCD_WR_PORT] |= (1  << LCD_WR_PIN );
+    LPC_GPIO_PORT->DIR[LCD_RD_PORT] |= (1  << LCD_RD_PIN );
+    LPC_GPIO_PORT->DIR[LCD_RES_PORT] |= (1  << LCD_RES_PIN );
+    /** data lines **/
+    LPC_GPIO_PORT->DIR[2] |= (0xFFFF  << 3);  // P2_3...P2_18 as output
+
+    pin_mode(P2_3,PullNone); // turn off pull-up
+    pin_mode(P2_4,PullNone); // turn off pull-up
+    pin_mode(P2_5,PullNone); // turn off pull-up
+    pin_mode(P2_6,PullNone); // turn off pull-up
+
+    pin_mode(P2_7,PullNone); // turn off pull-up
+    pin_mode(P2_8,PullNone); // turn off pull-up
+    pin_mode(P2_9,PullNone); // turn off pull-up
+    pin_mode(P2_10,PullNone); // turn off pull-up
+
+    pin_mode(P2_11,PullNone); // turn off pull-up
+    pin_mode(P2_12,PullNone); // turn off pull-up
+    pin_mode(P2_13,PullNone); // turn off pull-up
+    pin_mode(P2_14,PullNone); // turn off pull-up
+
+    pin_mode(P2_15,PullNone); // turn off pull-up
+    pin_mode(P2_16,PullNone); // turn off pull-up
+    pin_mode(P2_17,PullNone); // turn off pull-up
+    pin_mode(P2_18,PullNone); // turn off pull-up
+}
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/Pokitto_extport.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,96 @@
+/**************************************************************************/
+/*!
+    @file     Pokitto_extport.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#include "Pokitto.h"
+
+using namespace mbed; //needed for interruptin
+
+#if POK_USE_EXT > 0
+//#if POK_BOARDREV == 1
+ /** 2-layer board rev 1.3 **/
+//#else
+ /** 4-layer board rev 2.1 **/
+ //InterruptIn ext0(P1_19);
+ AnalogIn ext0(P1_19);
+ DigitalIn ext1(P0_11, PullUp);
+ //DigitalOut ext0(P1_19);
+ //DigitalOut ext1(P0_11);
+ DigitalOut ext2(P0_12);
+ DigitalOut ext3(P0_13);
+ DigitalOut ext4(P0_14);
+ DigitalOut ext5(P0_17);
+ DigitalOut ext6(P0_18);
+ DigitalOut ext7(P0_19);
+ DigitalOut ext8(P1_20);
+ DigitalOut ext9(P1_21);
+ DigitalOut ext10(P1_22);
+ DigitalOut ext11(P1_23);
+ DigitalOut ext12(P1_5);
+ DigitalOut ext13(P1_6);
+ DigitalOut ext14(P1_8);
+ DigitalOut ext15(P1_26);
+ DigitalOut ext16(P1_27);
+ DigitalOut ext17(P0_16);
+//#endif // POK_BOARDREV
+#endif // POK_USE_EXT
+
+
+
+void ext_write(uint32_t value) {
+    #if POK_USE_EXT > 0
+    if (value & 1) SET_EXT0 else CLR_EXT0;
+    value >>= 1;
+    if (value & 1) SET_EXT1 else CLR_EXT1;
+    value >>= 1;
+    if (value & 1) SET_EXT2 else CLR_EXT2;
+    value >>= 1;
+    if (value & 1) SET_EXT3 else CLR_EXT3;
+    value >>= 1;
+    if (value & 1) SET_EXT4 else CLR_EXT4;
+    value >>= 1;
+    if (value & 1) SET_EXT5 else CLR_EXT5;
+    value >>= 1;
+    if (value & 1) SET_EXT6 else CLR_EXT6;
+    value >>= 1;
+    if (value & 1) SET_EXT7 else CLR_EXT7;
+    value >>= 1;
+    if (value & 1) SET_EXT8 else CLR_EXT8;
+    value >>= 1;
+    if (value & 1) SET_EXT9 else CLR_EXT9;
+    value >>= 1;
+    if (value & 1) SET_EXT10 else CLR_EXT10;
+    value >>= 1;
+    if (value & 1) SET_EXT11 else CLR_EXT11;
+    value >>= 1;
+    if (value & 1) SET_EXT12 else CLR_EXT12;
+    value >>= 1;
+    if (value & 1) SET_EXT13 else CLR_EXT13;
+    value >>= 1;
+    if (value & 1) SET_EXT14 else CLR_EXT14;
+    value >>= 1;
+    if (value & 1) SET_EXT15 else CLR_EXT15;
+    value >>= 1;
+    if (value & 1) SET_EXT16 else CLR_EXT16;
+    value >>= 1;
+    if (value & 1) SET_EXT17 else CLR_EXT17;
+    #endif
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/Pokitto_extport.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,195 @@
+/**************************************************************************/
+/*!
+    @file     Pokitto_extport.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#ifndef POKITTO_EXTPORT_H
+#define POKITTO_EXTPORT_H
+
+#include "mbed.h"
+
+using namespace mbed; //interruptin
+
+#if POK_BOARDREV == 1
+ /** 2-layer board rev 1.3 **/
+ #define EXT0_PORT   1
+ #define EXT0_PIN    19
+ #define EXT1_PORT   0
+ #define EXT1_PIN    11
+ #define EXT2_PORT   0
+ #define EXT2_PIN    12
+ #define EXT3_PORT   0
+ #define EXT3_PIN    13
+ #define EXT4_PORT   0
+ #define EXT4_PIN    14
+ #define EXT5_PORT   0
+ #define EXT5_PIN    17
+ #define EXT6_PORT   0
+ #define EXT6_PIN    18
+ #define EXT7_PORT   0
+ #define EXT7_PIN    19
+ #define EXT8_PORT   1
+ #define EXT8_PIN    20
+ #define EXT9_PORT   1
+ #define EXT9_PIN    21
+ #define EXT10_PORT   1
+ #define EXT10_PIN    22
+ #define EXT11_PORT   1
+ #define EXT11_PIN    23
+ #define EXT12_PORT   1
+ #define EXT12_PIN    5
+ #define EXT13_PORT   1
+ #define EXT13_PIN    6
+ #define EXT14_PORT   1
+ #define EXT14_PIN    8
+ #define EXT15_PORT   0
+ #define EXT15_PIN    19
+ #define EXT16_PORT   0
+ #define EXT16_PIN    13
+ #define EXT17_PORT   0
+ #define EXT17_PIN    16
+#else
+ /** 4-layer board rev 2.1 **/
+ #define EXT0_PORT   1
+ #define EXT0_PIN    19
+ #define EXT1_PORT   0
+ #define EXT1_PIN    11
+ #define EXT2_PORT   0
+ #define EXT2_PIN    12
+ #define EXT3_PORT   0
+ #define EXT3_PIN    13
+ #define EXT4_PORT   0
+ #define EXT4_PIN    14
+ #define EXT5_PORT   0
+ #define EXT5_PIN    17
+ #define EXT6_PORT   0
+ #define EXT6_PIN    18
+ #define EXT7_PORT   0
+ #define EXT7_PIN    19
+ #define EXT8_PORT   1
+ #define EXT8_PIN    20
+ #define EXT9_PORT   1
+ #define EXT9_PIN    21
+ #define EXT10_PORT   1
+ #define EXT10_PIN    22
+ #define EXT11_PORT   1
+ #define EXT11_PIN    23
+ #define EXT12_PORT   1
+ #define EXT12_PIN    5
+ #define EXT13_PORT   1
+ #define EXT13_PIN    6
+ #define EXT14_PORT   1
+ #define EXT14_PIN    8
+ #define EXT15_PORT   0
+ #define EXT15_PIN    19
+ #define EXT16_PORT   0
+ #define EXT16_PIN    13
+ #define EXT17_PORT   0
+ #define EXT17_PIN    16
+
+ #define EXT0 	P1_19
+ #define EXT1	P0_11
+ #define EXT2	P0_12
+ #define EXT3	P0_13
+ #define EXT4	P0_14
+ #define EXT5	P0_17
+ #define EXT6	P0_18
+ #define EXT7	P0_19
+ #define EXT8	P1_20
+ #define EXT9	P1_21
+ #define EXT10	P1_22
+ #define EXT11	P1_23
+ #define EXT12	P1_5
+ #define EXT13	P1_6
+ #define EXT14	P1_8
+ #define EXT15	P1_26
+ #define EXT16	P1_27
+ #define EXT17	P0_16
+
+#endif // POK_BOARDREV
+
+#define CLR_EXT0 LPC_GPIO_PORT->CLR[EXT0_PORT] = 1 << EXT0_PIN;
+#define SET_EXT0 LPC_GPIO_PORT->SET[EXT0_PORT] = 1 << EXT0_PIN;
+#define CLR_EXT1 LPC_GPIO_PORT->CLR[EXT1_PORT] = 1 << EXT1_PIN;
+#define SET_EXT1 LPC_GPIO_PORT->SET[EXT1_PORT] = 1 << EXT1_PIN;
+#define CLR_EXT2 LPC_GPIO_PORT->CLR[EXT2_PORT] = 1 << EXT2_PIN;
+#define SET_EXT2 LPC_GPIO_PORT->SET[EXT2_PORT] = 1 << EXT2_PIN;
+#define CLR_EXT3 LPC_GPIO_PORT->CLR[EXT3_PORT] = 1 << EXT3_PIN;
+#define SET_EXT3 LPC_GPIO_PORT->SET[EXT3_PORT] = 1 << EXT3_PIN;
+#define CLR_EXT4 LPC_GPIO_PORT->CLR[EXT4_PORT] = 1 << EXT4_PIN;
+#define SET_EXT4 LPC_GPIO_PORT->SET[EXT4_PORT] = 1 << EXT4_PIN;
+#define CLR_EXT5 LPC_GPIO_PORT->CLR[EXT5_PORT] = 1 << EXT5_PIN;
+#define SET_EXT5 LPC_GPIO_PORT->SET[EXT5_PORT] = 1 << EXT5_PIN;
+#define CLR_EXT6 LPC_GPIO_PORT->CLR[EXT6_PORT] = 1 << EXT6_PIN;
+#define SET_EXT6 LPC_GPIO_PORT->SET[EXT6_PORT] = 1 << EXT6_PIN;
+#define CLR_EXT7 LPC_GPIO_PORT->CLR[EXT7_PORT] = 1 << EXT7_PIN;
+#define SET_EXT7 LPC_GPIO_PORT->SET[EXT7_PORT] = 1 << EXT7_PIN;
+#define CLR_EXT8 LPC_GPIO_PORT->CLR[EXT8_PORT] = 1 << EXT8_PIN;
+#define SET_EXT8 LPC_GPIO_PORT->SET[EXT8_PORT] = 1 << EXT8_PIN;
+#define CLR_EXT9 LPC_GPIO_PORT->CLR[EXT9_PORT] = 1 << EXT9_PIN;
+#define SET_EXT9 LPC_GPIO_PORT->SET[EXT9_PORT] = 1 << EXT9_PIN;
+#define CLR_EXT10 LPC_GPIO_PORT->CLR[EXT10_PORT] = 1 << EXT10_PIN;
+#define SET_EXT10 LPC_GPIO_PORT->SET[EXT10_PORT] = 1 << EXT10_PIN;
+#define CLR_EXT11 LPC_GPIO_PORT->CLR[EXT11_PORT] = 1 << EXT11_PIN;
+#define SET_EXT11 LPC_GPIO_PORT->SET[EXT11_PORT] = 1 << EXT11_PIN;
+#define CLR_EXT12 LPC_GPIO_PORT->CLR[EXT12_PORT] = 1 << EXT12_PIN;
+#define SET_EXT12 LPC_GPIO_PORT->SET[EXT12_PORT] = 1 << EXT12_PIN;
+#define CLR_EXT13 LPC_GPIO_PORT->CLR[EXT13_PORT] = 1 << EXT13_PIN;
+#define SET_EXT13 LPC_GPIO_PORT->SET[EXT13_PORT] = 1 << EXT13_PIN;
+#define CLR_EXT14 LPC_GPIO_PORT->CLR[EXT14_PORT] = 1 << EXT14_PIN;
+#define SET_EXT14 LPC_GPIO_PORT->SET[EXT14_PORT] = 1 << EXT14_PIN;
+#define CLR_EXT15 LPC_GPIO_PORT->CLR[EXT15_PORT] = 1 << EXT15_PIN;
+#define SET_EXT15 LPC_GPIO_PORT->SET[EXT15_PORT] = 1 << EXT15_PIN;
+#define CLR_EXT16 LPC_GPIO_PORT->CLR[EXT16_PORT] = 1 << EXT16_PIN;
+#define SET_EXT16 LPC_GPIO_PORT->SET[EXT16_PORT] = 1 << EXT16_PIN;
+#define CLR_EXT17 LPC_GPIO_PORT->CLR[EXT17_PORT] = 1 << EXT17_PIN;
+#define SET_EXT17 LPC_GPIO_PORT->SET[EXT17_PORT] = 1 << EXT17_PIN;
+
+#if POK_USE_EXT > 0
+//#if POK_BOARDREV == 1
+ /** 2-layer board rev 1.3 **/
+//#else
+ /** 4-layer board rev 2.1 **/
+ //extern InterruptIn ext0;
+ extern AnalogIn ext0;
+ extern DigitalIn ext1;
+ //DigitalOut ext0;
+ //DigitalOut ext1;
+ extern DigitalOut ext2;
+ extern DigitalOut ext3;
+ extern DigitalOut ext4;
+ extern DigitalOut ext5;
+ extern DigitalOut ext6;
+ extern DigitalOut ext7;
+ extern DigitalOut ext8;
+ extern DigitalOut ext9;
+ extern DigitalOut ext10;
+ extern DigitalOut ext11;
+ extern DigitalOut ext12;
+ extern DigitalOut ext13;
+ extern DigitalOut ext14;
+ extern DigitalOut ext15;
+ extern DigitalOut ext16;
+ extern DigitalOut ext17;
+//#endif // POK_BOARDREV
+#endif // POK_USE_EXT
+
+extern int turn;
+#endif // POKITTO_EXTPORT_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/SoftwareI2C.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,214 @@
+/*
+ * mbed Library to use a software master i2c interface on any GPIO pins
+ * Copyright (c) 2012 Christopher Pepper
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#include "SoftwareI2C.h"
+
+/**
+ * @brief Initializes interface
+ * @param sda GPIO pin to use as I2C SDA
+ * @param scl GPIO pin to use as I2C SCL
+ */
+
+SoftwareI2C::SoftwareI2C(PinName sda, PinName scl) : _sda(sda) , _scl(scl) {
+    _scl.output();
+    _scl.mode(OpenDrain);
+    _sda.output();
+    _sda.mode(OpenDrain);
+
+    _device_address = 0;
+    _frequency_delay = 1;
+
+    initialise();
+}
+
+SoftwareI2C::~SoftwareI2C() {
+
+}
+
+/**
+ * @brief Read 1 or more bytes from the I2C slave
+ * @param device_address The address of the device to read from
+ * @param data An allocated array to read the data into
+ * @param data_bytes Number of bytes to read (must be equal to or less then the allocated memory in data)
+ */
+void SoftwareI2C::read(uint8_t device_address, uint8_t* data, uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address | 0x01;
+    start();
+    putByte(device_address);
+    getAck();
+    for (int x = 0; x < data_bytes; ++x) {
+        data[x] = getByte();
+        if ( x < (data_bytes -1)) { //ack all but the final byte
+            giveAck();
+        }
+    }
+    stop();
+}
+
+/**
+ * @brief Write 1 or more bytes to the I2C slave
+ * @param device_address The address of the device to write to
+ * @param data An array to write the data from
+ * @param data_bytes Number of bytes to write from array
+ */
+void SoftwareI2C::write(uint8_t device_address, uint8_t* data,  uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    for ( int x = 0; x < data_bytes; ++x ) {
+        putByte(data[x]);
+        getAck();
+    }
+    stop();
+}
+
+/**
+ * @brief Write 1 byte to the I2C slave
+ * @param device_address The address of the device to write to
+ * @param byte The data to write
+ */
+void SoftwareI2C::write(uint8_t device_address, uint8_t byte) {
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    putByte(byte);
+    getAck();
+    stop();
+}
+
+/**
+ * @brief Read 1 or more bytes from the I2C slave at the specified memory address
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @param data The allocated array to read into
+ * @param data_bytes The number of bytes to read
+ */
+void SoftwareI2C::randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    if (!getAck()) {
+        return;
+    }
+    putByte(start_address);
+    if (!getAck()) {
+        return;
+    }
+
+    device_address=device_address | 0x01;
+    start();
+    putByte(device_address);
+    if (!getAck()) {
+        return;
+    }
+    for ( int x = 0; x < data_bytes; ++x) {
+        data[x] = getByte();
+        if (x != (data_bytes - 1)) giveAck();
+    }
+    stop();
+}
+
+/**
+ * @brief Write 1 byte to the I2C slave at the specified memory address
+ * @param device_address The address of the device to write to
+ * @param start_address The memory address to write to
+ * @param byte The data to write
+ */
+void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte) {
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    putByte(start_address);
+    getAck();
+    putByte(byte);
+    getAck();
+    stop();
+}
+
+/**
+ * @brief Write 1 or more bytes to the I2C slave at the specified memory address
+ * @param device_address The address of the device to write to
+ * @param start_address The memory address to write to
+ * @param data The data to write
+ * @param data_bytes The number of bytes to write
+ */
+void SoftwareI2C::randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes) {
+    if (data == 0 || data_bytes == 0) return;
+
+    device_address = device_address & 0xFE;
+    start();
+    putByte(device_address);
+    getAck();
+    putByte(start_address);
+    getAck();
+    for ( int x = 0; x <= data_bytes; ++x ) {
+        putByte(data[x]);
+        getAck();
+    }
+    stop();
+}
+
+/**
+ * @brief Read 2 bytes from the I2C slave at the specified memory address and return them as an 16bit unsigned integer
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @return MSB 16bit unsigned integer
+ */
+uint16_t SoftwareI2C::read16(uint8_t device_address, uint8_t start_address) {
+    uint8_t short_array[2] = {0, 0};
+    randomRead(device_address, start_address, short_array, 2 );
+    uint16_t value = 0;
+    value = short_array[0] << 8;
+    value |= short_array[1];
+
+    return value;
+}
+
+/**
+ * @brief Read 3 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @return MSB 32bit unsigned integer
+ */
+uint32_t SoftwareI2C::read24(uint8_t device_address, uint8_t start_address) {
+    uint8_t value_array[4] = {0, 0, 0};
+    randomRead(device_address, start_address, value_array, 3 );
+    uint32_t value = 0;
+    value = value_array[0] << 16;
+    value |= value_array[1] << 8;
+    value |= value_array[2];
+
+    return value;
+}
+
+/**
+ * @brief Read 4 bytes from the I2C slave at the specified memory address and return them as an 32bit unsigned integer
+ * @param device_address The address of the device to read from
+ * @param start_address The memory address to read from
+ * @return MSB 32bit unsigned integer
+ */
+uint32_t SoftwareI2C::read32(uint8_t device_address, uint8_t start_address) {
+    uint8_t value_array[4] = {0, 0, 0, 0};
+    randomRead(device_address, start_address, value_array, 4 );
+    uint32_t value = 0;
+    value = value_array[0] << 24;
+    value |= value_array[1] << 16;
+    value |= value_array[2] << 8;
+    value |= value_array[3];
+
+    return value;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/SoftwareI2C.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,146 @@
+/*
+ * mbed Library to use a software master i2c interface on any GPIO pins
+ * Copyright (c) 2012 Christopher Pepper
+ * Released under the MIT License: http://mbed.org/license/mit
+ */
+
+#ifndef _SOFTWARE_I2C_H_
+#define _SOFTWARE_I2C_H_
+
+#include "mbed.h"
+
+/**
+  * @brief SoftwareI2C class
+  */
+
+class SoftwareI2C {
+public:
+    SoftwareI2C(PinName sda, PinName scl);
+    ~SoftwareI2C();
+
+    void read(uint8_t device_address, uint8_t* data, uint8_t data_bytes);
+    void write(uint8_t device_address, uint8_t* data,  uint8_t data_bytes);
+    void write(uint8_t device_address, uint8_t byte);
+    void randomRead(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes);
+    void randomWrite(uint8_t device_address, uint8_t start_address, uint8_t* data, uint8_t data_bytes);
+    void randomWrite(uint8_t device_address, uint8_t start_address, uint8_t byte);
+
+    uint8_t read8(uint8_t device_address, uint8_t start_address);
+    uint16_t read16(uint8_t device_address, uint8_t start_address);
+    uint32_t read24(uint8_t device_address, uint8_t start_address);
+    uint32_t read32(uint8_t device_address, uint8_t start_address);
+
+    void setDeviceAddress(uint8_t address){
+        _device_address = address;
+    }
+
+    void setFrequency(uint32_t frequency){
+        _frequency_delay = 1000000 / frequency;
+    }
+
+    inline void initialise() {
+        _scl.output();
+        _sda.output();
+
+        _sda = 1;
+        _scl = 0;
+        wait_us(_frequency_delay);
+
+        for ( int n = 0; n <= 3; ++n ) {
+            stop();
+        }
+    }
+
+private:
+    inline void start() {
+        _sda.output();
+        wait_us(_frequency_delay);
+        _scl = 1;
+        _sda = 1;
+        wait_us(_frequency_delay);
+        _sda = 0;
+        wait_us(_frequency_delay);
+        _scl = 0;
+        wait_us(_frequency_delay);
+    }
+
+    inline void stop() {
+        _sda.output();
+        wait_us(_frequency_delay);
+        _sda = 0;
+        wait_us(_frequency_delay);
+        _scl = 1;
+        wait_us(_frequency_delay);
+        _sda = 1;
+    }
+
+    inline void putByte(uint8_t byte) {
+        _sda.output();
+        for ( int n = 8; n > 0; --n) {
+            wait_us(_frequency_delay);
+            _sda = byte & (1 << (n-1));
+            _scl = 1;
+            wait_us(_frequency_delay);
+            _scl = 0;
+        }
+        _sda = 1;
+    }
+
+    inline uint8_t getByte() {
+        uint8_t byte = 0;
+
+        _sda.input();          //release the data line
+        _sda.mode(OpenDrain);
+
+        wait_us(_frequency_delay);
+
+        for ( int n = 8; n > 0; --n ) {
+            _scl=1;            //set clock high
+            wait_us(_frequency_delay);
+            byte |= _sda << (n-1); //read the bit
+            wait_us(_frequency_delay);
+            _scl=0;            //set clock low
+            wait_us(_frequency_delay);
+        }
+
+        _sda.output();         //take data line back
+
+        return byte;
+    }
+
+    inline void giveAck() {
+        _sda.output();
+        wait_us(_frequency_delay);
+        _sda = 0;
+        _scl = 1;
+        wait_us(_frequency_delay);
+        _scl = 0;
+        _sda = 1;
+
+    }
+
+    inline bool getAck() {
+        _sda.output();
+        _sda = 1;
+        _scl = 1;
+        _sda.input();
+        _sda.mode(OpenDrain);
+        wait_us(_frequency_delay);
+        _scl = 0;
+
+        if(_sda != 0){return false;}
+
+        wait_us(_frequency_delay);
+        return true;
+    }
+
+    DigitalInOut _sda;
+    DigitalInOut _scl;
+
+    uint8_t _device_address;
+    uint32_t _frequency_delay;
+};
+
+#endif
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/iap.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,730 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <iap.h>
+#include "LPC11U6x.h"
+#include "PokittoDisk.h"
+
+#define TICKRATE_HZ (10)	/* 10 ticks per second */
+/* SystemTick Counter */
+static volatile uint32_t sysTick;
+
+/* LPC1347 IAP entry address */
+#define IAP_LOCATION 0x1fff1ff1
+
+#define last_sector_flash  0x00038000  //0x0000F000
+#define IAP_LAST_SECTOR 28 /* Page number 896 - 1023, 0x00038000 - 0x0003FFFF */
+#define IAP_NUM_BYTES_TO_WRITE 256
+#define WRITECOUNT (IAP_NUM_BYTES_TO_WRITE / 4) /* when data array is in uint32_t */
+
+#define IAP_PREWRRITE_CMD 50 /* Prepare sector for write operation command */
+#define IAP_WRISECTOR_CMD 51
+#define IAP_ERSSECTOR_CMD 52
+#define IAP_REPID_CMD 54
+
+/* IAP command variables */
+static unsigned int command[5], result[4];
+
+/* IAP entry function */
+typedef int (*IAP)(unsigned int[], unsigned int[]);
+IAP iap_entry = (IAP) IAP_LOCATION;
+
+int CopyPageToFlash (uint32_t address, uint8_t* data) {
+    IAP iap_call = (IAP) IAP_LOCATION;
+    uint32_t writecount=0;
+	__disable_irq();
+
+    unsigned int sector, page;
+    bool firstpage=false, erasepage=false;
+
+    //DEBUG//
+    //for (int i=0;i<256;i++) data[i]=0xBB;
+
+    /* Calculate sector based on address */
+    if (address < 0x18000) sector = address/0x1000; // sectors go in 4 k's
+    else if (address >= 0x38000) sector = 28;
+    else if (address >= 0x30000) sector = 27;
+    else if (address >= 0x28000) sector = 26;
+    else if (address >= 0x20000) sector = 25;
+    else sector = 24;
+
+    /* Check is it the first page in the sector */
+    if (sector<24) {
+        if (address == sector * 0x1000) firstpage = true;
+    } else {
+        if (address == (sector-24)*0x4000 + 0x18000) firstpage = true;
+    }
+
+	/* Prepare the sector for writing */
+	command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+	command[1] = sector;         							/* Start Sector Number */
+	command[2] = sector;		        					/* End Sector Number */
+	iap_call(command, result);
+    if (result[0]) return 1;
+
+    /* wipe pages when writing the loader */
+    if (address==0x39000) {
+            erasepage=true;
+    }
+
+    /* do sector erase only when writing first page of given sector */
+    if (firstpage) {
+        /* Erase the last sector */
+        command[0] = IAP_ERSSECTOR_CMD;	   					/* Erase command code*/
+        command[1] = sector;             						/* Start Sector Number */
+        command[2] = sector;            						/* End Sector Number */
+        command[3] = SystemCoreClock / 1000UL;	/* Core clock frequency in kHz */
+        iap_call(command, result);
+        if (result[0]) return 1;
+        /* Prepare to write/erase the last sector, needs to be done again because succesful erase re-locks sectors */
+        command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+        command[1] = sector;			            				/* Start Sector Number */
+        command[2] = sector;        							/* Start Sector Number */
+        iap_call(command, result);
+        if (result[0]) return 1;
+    }
+
+    /* page erase for bootloader area */
+    if (erasepage) {
+        command[0] = 59; //erase page command
+        command[1] = 896;
+        command[2] = 1023;
+        command[3] = SystemCoreClock / 1000UL;	/* Core clock frequency in kHz */
+        iap_call(command, result);
+        if (result[0]) return 1;
+        /* Prepare to write/erase the last sector, needs to be done again because succesful erase re-locks sectors */
+        command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+        command[1] = sector;			            				/* Start Sector Number */
+        command[2] = sector;        							/* Start Sector Number */
+        iap_call(command, result);
+        if (result[0]) return 1;
+    }
+
+	/* Write data to the sectors */
+	command[0] = IAP_WRISECTOR_CMD;						/* Write command code */
+	command[1] = (uint32_t) (uint32_t*) address;              		    /* Destination Flash Address */
+	command[2] = (uint32_t) data;	    				/* Source RAM Address */
+	command[3] = 0x100;             					/* Number of Bytes to be written */
+	command[4] = SystemCoreClock / 1000;				/* System clock frequency */
+	iap_call(command, result);
+    if (result[0]) return 1;
+
+	/* Re-enable interrupt mode */
+	__enable_irq();
+
+    return 0; /*succesful write*/
+
+}
+
+__attribute__((section(".IAP_Code"))) int HelloFromIAP() {
+    static uint32_t array_data[WRITECOUNT];
+    int i;
+    /* Initialize the array data to be written to FLASH */
+	for (i = 0; i < WRITECOUNT; i++) {
+		array_data[i] = 0xB007AB1E;
+	}
+
+    IAP iap_call = (IAP) IAP_LOCATION;
+    uint8_t teahupoo;
+    //readEEPROM(0,&teahupoo,1);
+    teahupoo++;
+    //writeEEPROM(0,&teahupoo,1);
+
+    /** open file **/
+    pokInitSD();
+    char fn[20];
+    char* now;
+    now = (char*)last_sector_flash;
+    switch (now[0]) {
+case 0xAA:
+    fn[0]='B';fn[1]='B';fn[2]='.';fn[3]='B';fn[4]='I';fn[5]='N';fn[6]='\0';break;
+case 0xBB:
+    fn[0]='C';fn[1]='C';fn[2]='.';fn[3]='B';fn[4]='I';fn[5]='N';fn[6]='\0';break;
+default:
+    fn[0]='A';fn[1]='A';fn[2]='.';fn[3]='B';fn[4]='I';fn[5]='N';fn[6]='\0';
+    }
+    if(fileOpen(fn,FILE_MODE_BINARY)) {
+            return 1;
+    } else {
+     for (i = 0; i < WRITECOUNT; i++) {
+		fileReadBytes((uint8_t*)&array_data[i],4);
+	 }
+    }
+
+
+    /** write sector in flash **/
+    /* Read Part Identification Number*/
+	command[0] = IAP_REPID_CMD;								/* Read ID command code */
+	iap_call(command, result);
+
+	__disable_irq();
+
+	/* Prepare to write/erase the last sector */
+	command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+	command[1] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[2] = IAP_LAST_SECTOR;							/* End Sector Number */
+	iap_call(command, result);
+	/* Erase the last sector */
+	command[0] = IAP_ERSSECTOR_CMD;						/* Erase command code*/
+	command[1] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[2] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[3] = SystemCoreClock / 1000UL;	/* Core clock frequency in kHz */
+	iap_call(command, result);
+	/* Prepare to write/erase the last sector */
+	command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+	command[1] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[2] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	iap_call(command, result);
+	/* Write to the last sector */
+	command[0] = IAP_WRISECTOR_CMD;								/* Write command code */
+	command[1] = (uint32_t) last_sector_flash;		        /* Destination Flash Address */
+	command[2] = (uint32_t) &array_data;					/* Source RAM Address */
+	command[3] = IAP_NUM_BYTES_TO_WRITE;					/* Number of Bytes to be written */
+	command[4] = SystemCoreClock / 1000;					/* System clock frequency */
+	iap_call(command, result);
+
+	/* Re-enable interrupt mode */
+	__enable_irq();
+
+
+    SCB->AIRCR = 0x05FA0004; //issue system reset
+    while(1); //should never come here
+    return teahupoo;
+}
+
+
+
+
+void IAPstacksave()
+{
+  /*need to save 32 top bytes of RAM to RAM1*/
+  #define RAM1_0 (*((volatile unsigned long *) 0x20000000))
+  #define RAM1_1 (*((volatile unsigned long *) 0x20000004))
+  #define RAM1_2 (*((volatile unsigned long *) 0x20000008))
+  #define RAM1_3 (*((volatile unsigned long *) 0x2000000C))
+  #define RAM1_4 (*((volatile unsigned long *) 0x20000010))
+  #define RAM1_5 (*((volatile unsigned long *) 0x20000014))
+  #define RAM1_6 (*((volatile unsigned long *) 0x20000018))
+  #define RAM1_7 (*((volatile unsigned long *) 0x2000001C))
+
+  uint32_t *saveloc = (uint32_t*)(0x10002000-0x20); // RAM top - 32 bytes
+  RAM1_0 = *saveloc++;
+  RAM1_1 = *saveloc++;
+  RAM1_2 = *saveloc++;
+  RAM1_3 = *saveloc++;
+  RAM1_4 = *saveloc++;
+  RAM1_5 = *saveloc++;
+  RAM1_6 = *saveloc++;
+  RAM1_7 = *saveloc;
+}
+
+
+char iaptest() {
+    static uint32_t array_data[WRITECOUNT];
+    int i;
+    /* Initialize the array data to be written to FLASH */
+	for (i = 0; i < WRITECOUNT; i++) {
+		array_data[i] = 0x11223340 + i;
+	}
+
+	/* Read Part Identification Number*/
+	command[0] = IAP_REPID_CMD;								/* Read ID command code */
+	iap_entry(command, result);
+
+	/* Reinvoke ISP mode so that reprogamming of Flash possible */
+	__disable_irq();
+
+	command[0] = IAP_REPID_CMD;
+	iap_entry(command, result);
+
+	/* Prepare to write/erase the last sector */
+	command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+	command[1] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[2] = IAP_LAST_SECTOR;							/* End Sector Number */
+	iap_entry(command, result);
+
+	/* Erase the last sector */
+	command[0] = IAP_ERSSECTOR_CMD;						/* Erase command code*/
+	command[1] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[2] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	iap_entry(command, result);
+
+	/* Prepare to write/erase the last sector */
+	command[0] = IAP_PREWRRITE_CMD;						/* Prepare to write/erase command code */
+	command[1] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	command[2] = IAP_LAST_SECTOR;							/* Start Sector Number */
+	iap_entry(command, result);
+
+	/* Write to the last sector */
+	command[0] = IAP_WRISECTOR_CMD;								/* Write command code */
+	command[1] = (uint32_t) last_sector_flash;		/* Destination Flash Address */
+	command[2] = (uint32_t) &array_data;					/* Source RAM Address */
+	command[3] = IAP_NUM_BYTES_TO_WRITE;					/* Number of Bytes to be written */
+	command[4] = SystemCoreClock / 1000;					/* System clock frequency */
+	iap_entry(command, result);
+
+	/* Re-enable interrupt mode */
+	__enable_irq();
+
+	//while (1) {
+	//	__WFI();
+	//}
+
+	return 0;
+
+}
+
+
+//1) EEprom Write
+//
+//Command code: 61
+//Param0: eeprom address (byte, half-word or word aligned)
+//Param1: RAM address (byte, half-word or word aligned)
+//Param2: Number of bytes to be written ( Byte, Half-words write are ok)
+//Param3: System Clock Frequency (CCLK) in kHz
+//
+//Return Code CMD_SUCCESS | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED
+__attribute__((section(".IAP_Code"))) void writeEEPROM( uint16_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount )
+{
+	unsigned int command[5], result[4];
+
+	command[0] = 61;
+	command[1] = (uint32_t) eeAddress;
+	command[2] = (uint32_t) buffAddress;
+	command[3] = byteCount;
+	command[4] = SystemCoreClock/1000;
+
+	/* Invoke IAP call...*/
+#if (EEPROM_PROFILE!=0)
+	LPC_CT32B0->TCR = 1;
+	__disable_irq();
+  	iap_entry(command, result);
+  	__enable_irq();
+	LPC_CT32B0->TCR = 0;
+#else
+    __disable_irq();
+	iap_entry(command, result);
+	__enable_irq();
+#endif
+	if (0 != result[0])
+	{
+		//Trap error
+		while(1);
+	}
+	return;
+}
+
+//2) EEprom Read
+//Command code: 62
+//Param0: eeprom address (byte, half-word or word aligned)
+//Param1: RAM address (byte, half-word or word aligned)
+//Param2: Number of bytes to be read ( Byte, Half-words read are ok)
+//Param3: System Clock Frequency (CCLK) in kHz
+//
+//Return Code CMD_SUCCESS | SRC_ADDR_NOT_MAPPED | DST_ADDR_NOT_MAPPED
+__attribute__((section(".IAP_Code"))) void readEEPROM( uint16_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount )
+{
+	unsigned int command[5], result[4];
+
+	command[0] = 62;
+	command[1] = (uint32_t) eeAddress;
+	command[2] = (uint32_t) buffAddress;
+	command[3] = byteCount;
+	command[4] = SystemCoreClock/1000;
+
+	/* Invoke IAP call...*/
+	__disable_irq();
+  	iap_entry( command, result);
+  	__enable_irq();
+	if (0 != result[0])
+	{
+		//Trap error
+		while(1);
+	}
+	return;
+}
+
+__attribute__((section(".IAP_Code"))) void IAPreadPartId( uint8_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount )
+{
+	unsigned int command[5], result[4];
+
+	command[0] = 62;
+	command[1] = (uint32_t) eeAddress;
+	command[2] = (uint32_t) buffAddress;
+	command[3] = byteCount;
+	command[4] = SystemCoreClock/1000;
+
+	/* Invoke IAP call...*/
+	__disable_irq();
+  	iap_entry( command, result);
+  	__enable_irq();
+	if (0 != result[0])
+	{
+		//Trap error
+		while(1);
+	}
+	return;
+}
+
+uint8_t eeprom_read_byte(uint16_t* index) {
+    uint8_t val;
+    readEEPROM(index,&val,1);
+    return val;
+}
+
+void eeprom_write_byte(uint16_t* index , uint8_t val) {
+    writeEEPROM(index,&val,1);
+}
+
+/*****************************************************************************
+ * $Id$
+ *
+ * Project: 	NXP LPC11U6x In Application Programming
+ *
+ * Description: Provides access to In-Application Programming (IAP) routines
+ * 			    contained within the bootROM sector of LPC11U6x devices.
+ *
+ * Copyright(C) 2010, NXP Semiconductor
+ * All rights reserved.
+ *
+ *****************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ *****************************************************************************/
+
+/* IAP Command Definitions */
+#define	IAP_CMD_PREPARE_SECTORS			  50
+#define	IAP_CMD_COPY_RAM_TO_FLASH		  51
+#define	IAP_CMD_ERASE_SECTORS			    52
+#define	IAP_CMD_BLANK_CHECK_SECTORS		53
+#define	IAP_CMD_READ_PART_ID			    54
+#define	IAP_CMD_READ_BOOT_ROM_VERSION	55
+#define	IAP_CMD_COMPARE					      56
+#define	IAP_CMD_REINVOKE_ISP			    57
+#define IAP_CMD_READ_UID              58
+
+#define IAP_CMD_ERASE_PAGE            59    //new
+
+/* IAP boot ROM location and access function */
+#define IAP_ROM_LOCATION				0x1FFF1FF1UL
+//#define IAP_EXECUTE_CMD(a, b)			((void (*)())(IAP_ROM_LOCATION))(a, b)
+
+__attribute__((section(".IAP_Code"))) void IAP_EXECUTE_CMD(uint32_t* a, uint32_t* b) {
+    void (*user_code_entry)(uint32_t*,uint32_t*);
+    uint32_t *p;
+    p = (uint32_t *)IAP_ROM_LOCATION;
+    user_code_entry = (void (*)(uint32_t*,uint32_t*))(*p);
+    user_code_entry(a, b);
+}
+
+
+/*****************************************************************************
+** Function name:	u32IAP_PrepareSectors
+**
+** Description:		Prepares sector(s) for erasing or write operations. This
+** 								command must be executed before executing the "Copy RAM to
+** 								Flash" or "Erase Sector(s)" commands.
+**
+** Parameters:		u32StartSector - Number of first sector to prepare.
+** 								u32EndSector - Number of last sector to prepare.
+**
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_PrepareSectors(uint32_t u32StartSector, uint32_t u32EndSector)
+{
+	uint32_t u32Status;
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	if (u32EndSector < u32StartSector)
+	{
+		u32Status = IAP_STA_INVALD_PARAM;
+	}
+	else
+	{
+		au32Command[0] = IAP_CMD_PREPARE_SECTORS;
+		au32Command[1] = u32StartSector;
+		au32Command[2] = u32EndSector;
+		__disable_irq();
+		IAP_EXECUTE_CMD(au32Command, au32Result);
+		__enable_irq();
+		u32Status = au32Result[0];
+	}
+	return u32Status;
+}
+
+/*****************************************************************************
+** Function name:	u32IAP_CopyRAMToFlash
+**
+** Description:		Program the flash memory with data stored in RAM.
+**
+** Parameters:	   	u32DstAddr - Destination Flash address, should be a 256
+**                               byte boundary.
+**			 		u32SrcAddr - Source RAM address, should be a word boundary
+**			 		u32Len     - Number of 8-bit bytes to write, must be a
+**			 					 multiple of 256.
+*
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_CopyRAMToFlash(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len)
+{
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	au32Command[0] = IAP_CMD_COPY_RAM_TO_FLASH;
+	au32Command[1] = u32DstAddr;
+	au32Command[2] = u32SrcAddr;
+	au32Command[3] = u32Len;
+	au32Command[4] = SystemCoreClock / 1000UL;	/* Core clock frequency in kHz */
+
+	IAP_EXECUTE_CMD(au32Command, au32Result);
+
+	return au32Result[0];
+}
+
+/*****************************************************************************
+** Function name:	u32IAP_EraseSectors
+**
+** Description:		Erase a sector or multiple sectors of on-chip Flash memory.
+**
+** Parameters:		u32StartSector - Number of first sector to erase.
+** 					u32EndSector - Number of last sector to erase.
+*
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_EraseSectors(uint32_t u32StartSector, uint32_t u32EndSector)
+{
+	uint32_t u32Status;
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	if (u32EndSector < u32StartSector)
+	{
+		u32Status = IAP_STA_INVALD_PARAM;
+	}
+	else
+	{
+		au32Command[0] = IAP_CMD_ERASE_SECTORS;
+		au32Command[1] = u32StartSector;
+		au32Command[2] = u32EndSector;
+		au32Command[3] = SystemCoreClock / 1000UL;	/* Core clock frequency in kHz */
+
+		IAP_EXECUTE_CMD(au32Command, au32Result);
+
+		u32Status = au32Result[0];
+	}
+	return u32Status;
+}
+
+/*****************************************************************************
+** Function name:	u32IAP_BlankCheckSectors
+**
+** Description:		Blank check a sector or multiple sectors of on-chip flash
+** 					memory.
+**
+** Parameters:		u32StartSector - Number of first sector to check.
+** 					u32EndSector - Number of last sector to check.
+** 					pu32Result[0] - Offset of the first non blank word location
+**                  if the Status Code is IAP_STA_SECTOR_NOT_BLANK.
+** 					pu32Result[1] - Contents of non blank word location.
+**
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_BlankCheckSectors(uint32_t u32StartSector, uint32_t u32EndSector, uint32_t *pu32Result)
+{
+	uint32_t u32Status;
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	if (u32EndSector < u32StartSector)
+	{
+		u32Status = IAP_STA_INVALD_PARAM;
+	}
+	else
+	{
+		au32Command[0] = IAP_CMD_BLANK_CHECK_SECTORS;
+		au32Command[1] = u32StartSector;
+		au32Command[2] = u32EndSector;
+
+		IAP_EXECUTE_CMD(au32Command, au32Result);
+
+		if (au32Result[0] == IAP_STA_SECTOR_NOT_BLANK)
+		{
+			*pu32Result       = au32Result[0];
+			*(pu32Result + 1) = au32Result[1];
+		}
+		u32Status = au32Result[0];
+	}
+	return u32Status;
+}
+
+/*****************************************************************************
+** Function name:	u32IAP_ReadPartID
+**
+** Description:		Read the part identification number.
+**
+** Parameters:		pu32PartID - Pointer to storage for part ID number.
+*
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_ReadPartID(uint32_t *pu32PartID)
+{
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	au32Command[0] = IAP_CMD_READ_PART_ID;
+	__disable_irq();
+	IAP_EXECUTE_CMD(au32Command, au32Result);
+	__enable_irq();
+	*pu32PartID = au32Result[1];
+
+	return au32Result[0];
+}
+
+/*****************************************************************************
+** Function name:	u32IAP_ReadBootVersion
+**
+** Description:		Read the boot code version number.
+**
+** Parameters:		pu32Major - Major version number in ASCII format.
+** 					pu32Minor - Minor version number in ASCII format.
+**
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major, uint32_t *pu32Minor)
+//uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major)
+{
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	au32Command[0] = IAP_CMD_READ_BOOT_ROM_VERSION;
+
+	IAP_EXECUTE_CMD(au32Command, au32Result);
+
+
+	*pu32Major = (au32Result[1] & 0x0000FF00UL) >> 8;
+	*pu32Minor = au32Result[1] & 0x000000FFUL;
+
+	return au32Result[0];
+}
+
+/*****************************************************************************
+** Function name:	u32IAP_Compare
+**
+** Description:		Compares the memory contents at two locations.
+**
+** Parameters:		u32Len - Number of bytes to compare, must be a multiple of 4.
+**					pu32Offset - Offset of the first mismatch if the Status Code is COMPARE_ERROR
+**
+** Returned value:	Status code returned by IAP ROM function.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_Compare(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t *pu32Offset)
+{
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	au32Command[0] = IAP_CMD_COMPARE;
+	au32Command[1] = u32DstAddr;
+	au32Command[2] = u32SrcAddr;
+	au32Command[3] = u32Len;
+
+	IAP_EXECUTE_CMD(au32Command, au32Result);
+
+	if (au32Result[0] == IAP_STA_COMPARE_ERROR)
+	{
+		if (pu32Offset != 0)
+		{
+			*pu32Offset = au32Result[1];
+		}
+	}
+	return au32Result[0];
+}
+
+/*****************************************************************************
+** Function name:	vIAP_ReinvokeISP
+**
+** Description:		Invoke the bootloader in ISP mode.
+**
+** Parameters:		None.
+*
+** Returned value:	None.
+**
+******************************************************************************/
+__attribute__((section(".IAP_Code"))) void vIAP_ReinvokeISP(void)
+{
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	au32Command[0] = IAP_CMD_REINVOKE_ISP;
+
+	IAP_EXECUTE_CMD(au32Command, au32Result);
+}
+
+// read UID
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_ReadUID(uint32_t * pu32UID)
+{
+	uint32_t au32Result[5];
+	uint32_t au32Command[5];
+
+	au32Command[0] = IAP_CMD_READ_UID;
+
+	IAP_EXECUTE_CMD(au32Command, au32Result);
+//	*pu32UID++ =  au32Result[1];
+//	*pu32UID++ =  au32Result[2];
+//	*pu32UID++ =  au32Result[3];
+//	*pu32UID =  au32Result[4];
+
+	*pu32UID =  au32Result[1];
+	*pu32UID++ =  au32Result[2];
+	*pu32UID++ =  au32Result[3];
+	*pu32UID++ =  au32Result[4];
+
+	return au32Result[0];
+
+}
+
+//IAP erase	Page  256B	 64K have 0-255 pages, page0-15 in sector 0,	32K have 0-127 pages, 128k have 0-511 pages,
+__attribute__((section(".IAP_Code"))) uint32_t u32IAP_ErasePage(uint32_t u32StartPage, uint32_t u32EndPage)
+{
+	uint32_t u32Status;
+	uint32_t au32Result[3];
+	uint32_t au32Command[5];
+
+	if (u32EndPage < u32StartPage)
+	{
+		u32Status = IAP_STA_INVALD_PARAM;
+	}
+	else
+	{
+		au32Command[0] = IAP_CMD_ERASE_PAGE;
+		au32Command[1] = u32StartPage;
+		au32Command[2] = u32EndPage;
+		au32Command[3] = SystemCoreClock / 1000UL;	/* Core clock frequency in kHz */
+
+		IAP_EXECUTE_CMD(au32Command, au32Result);
+
+		u32Status = au32Result[0];
+	}
+	return u32Status;
+}
+
+
+/*****************************************************************************
+ **                            End Of File
+ *****************************************************************************/
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_HW/iap.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,79 @@
+#ifndef IAP_H_INCLUDED
+#define IAP_H_INCLUDED
+
+extern int HelloFromIAP();
+extern int CopyPageToFlash(uint32_t,uint8_t*);
+extern char iaptest();
+extern void IAPstacksave();
+#define EEPROM_PROFILE 1
+extern void writeEEPROM( uint16_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount );
+extern void readEEPROM( uint16_t* eeAddress, uint8_t* buffAddress, uint32_t byteCount );
+extern uint8_t eeprom_read_byte(uint16_t*);
+extern void eeprom_write_byte(uint16_t*,uint8_t);
+
+/*****************************************************************************
+ * $Id$
+ *
+ * Project:		NXP LPC1100 Secondary Bootloader Example
+ *
+ * Description: Provides access to In-Application Programming (IAP) routines
+ * 			    		contained within the bootROM sector of LPC1100 devices.
+ *
+ * Copyright(C) 2010, NXP Semiconductor
+ * All rights reserved.
+ *
+ *****************************************************************************
+ * Software that is described herein is for illustrative purposes only
+ * which provides customers with programming information regarding the
+ * products. This software is supplied "AS IS" without any warranties.
+ * NXP Semiconductors assumes no responsibility or liability for the
+ * use of the software, conveys no license or title under any patent,
+ * copyright, or mask work right to the product. NXP Semiconductors
+ * reserves the right to make changes in the software without
+ * notification. NXP Semiconductors also make no representation or
+ * warranty that such application will be suitable for the specified
+ * use without further testing or modification.
+ *****************************************************************************/
+
+#include <stdint.h>
+
+/* IAP Command Status Codes */
+#define IAP_STA_CMD_SUCCESS 																0
+#define IAP_STA_INVALID_COMMAND 														1
+#define IAP_STA_SRC_ADDR_ERROR 															2
+#define IAP_STA_DST_ADDR_ERROR 															3
+#define IAP_STA_SRC_ADDR_NOT_MAPPED 												4
+#define IAP_STA_DST_ADDR_NOT_MAPPED 												5
+#define IAP_STA_COUNT_ERROR 																6
+#define IAP_STA_INVALID_SECTOR 															7
+#define IAP_STA_SECTOR_NOT_BLANK														8
+#define IAP_STA_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 		9
+#define IAP_STA_COMPARE_ERROR 															10
+#define IAP_STA_BUSY 																				11
+#define IAP_STA_INVALD_PARAM 																12
+
+/* Define the flash page size, this is the minimum amount of data can be written in one operation */
+#define IAP_FLASH_PAGE_SIZE_BYTES							256
+#define IAP_FLASH_PAGE_SIZE_WORDS							(IAP_FLASH_PAGE_SIZE_BYTES >> 2)
+
+void vIAP_ReinvokeISP(void);
+uint32_t u32IAP_ReadPartID(uint32_t *pu32PartID);
+uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major, uint32_t *pu32Minor);
+//uint32_t u32IAP_ReadBootVersion(uint32_t *pu32Major);
+uint32_t u32IAP_EraseSectors(uint32_t u32StartSector, uint32_t u32EndSector);
+uint32_t u32IAP_PrepareSectors(uint32_t u32StartSector, uint32_t u32EndSector);
+uint32_t u32IAP_CopyRAMToFlash(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len);
+uint32_t u32IAP_BlankCheckSectors(uint32_t u32StartSector, uint32_t u32EndSector, uint32_t *pu32Result);
+uint32_t u32IAP_Compare(uint32_t u32DstAddr, uint32_t u32SrcAddr, uint32_t u32Len, uint32_t *pu32Offset);
+uint32_t u32IAP_ReadUID(uint32_t * pu32UID);
+uint32_t u32IAP_ErasePage(uint32_t u32StartPage, uint32_t u32EndPage);
+
+/*****************************************************************************
+**                            End Of File
+******************************************************************************/
+
+
+
+#endif /* IAP_H_INCLUDED */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,66 @@
+/**************************************************************************/
+/*!
+    @file     Synth.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "Pokitto.h"
+#include "Synth.h"
+
+/** COMMON TO BOTH HW AND SIMULATED SOUND **/
+
+boolean playing=false; //external to share between player and synth
+boolean track1on = true, track2on = true, track3on = true, tableRefresh = false;
+
+uint8_t sequencepos=0, tempo = 120;
+long writeindex=0, readindex=0;
+uint16_t playerpos=0;
+long per = 1000*60/tempo/4; // ms per minute was 1000*60
+uint16_t samplespertick = (uint16_t)per*57, notetick; // samplespertick is a calculated value based on song speed. notetick is a counter
+long samplesperpattern=0;
+
+uint8_t tick=3; // loops between 3 channels. Tick 3 is used to calculate volume envelopes
+
+
+SONG song;
+OSC osc1,osc2,osc3;
+OSC patch[15];
+BLOCK block[1]; //30 blocks maximum
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,141 @@
+/**************************************************************************/
+/*!
+    @file     Synth.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#ifndef SYNTH_H
+#define SYNTH_H
+
+#include "Synth_osc.h"
+#include "Synth_song.h"
+
+
+/* PROPER WAY
+void f() {}
+
+int main()
+{
+    using FunctionPtr = void (*)();
+
+    FunctionPtr ptr = f;
+}
+*/
+
+#ifndef boolean
+typedef bool boolean;
+#endif
+
+//extern void fakeISR(); // was defined in Rboy_soundsim.h
+
+typedef void (*waveFunction)(OSC*);
+typedef void (*envFunction)(OSC*);
+typedef void (*mixFunction)();
+
+extern waveFunction Farr [];
+extern envFunction Earr [];
+extern mixFunction Marr []; // counts down
+extern mixFunction HWMarr []; // counts down
+/** COMMON TO BOTH HW AND SIM SOUND OUTPUT **/
+
+#define RBTRACKER_VERSION 0.03f
+
+#define WOFF     0
+#define WSQUARE  1
+#define WSAW     2
+#define WTRI     3
+#define WNOISE   4
+#define WSAMPLE  5
+#define WPNOISE  5
+
+#define OVERDRIVE 4
+
+#define ARPSTEPMAX 4 // was 5
+#define PATTERNLENGTH 64
+#define MAXPATTERNS 10
+#define MAXBLOCKS 30 // 10 *3
+
+#define VOLTICK 5
+#define ARPTICK 50 // 150 // was 200
+
+#define NUMWAVES 5
+#define NUMENVELOPES 3
+#define NUMMIXES 4
+
+extern void getNoteString(char *, uint8_t);
+
+extern void playNote(uint8_t,uint8_t,uint8_t);
+extern void makeSampleInstruments();
+
+extern void setPitch(int);
+extern void setWave(int);
+extern void setVolume(int);
+extern void initAudio();
+extern void testOsc();
+extern void terminateSound();
+extern void killSound();
+extern void startSound();
+extern void stopSound();
+extern void updatePlayback(); // from flash
+extern void updatePlaybackSD(uint8_t); // from SD
+extern void initStreams(uint8_t);
+extern void emptyOscillators();
+extern void emptyPatches();
+extern void emptyBlocks();
+extern void emptySong();
+extern int openSongFromSD(char *);
+extern void writeChunkToSD(uint8_t *);
+extern void readChunkFromSD(uint8_t *);
+
+
+extern boolean playing, track1on, track2on, track3on, tableRefresh;
+extern uint16_t playerpos;
+extern uint16_t samplespertick, notetick;
+extern long samplesperpattern;
+
+extern long readindex, writeindex;
+extern uint8_t tick, sequencepos;
+
+extern SONG song;
+extern OSC osc1,osc2,osc3;
+extern OSC patch[];
+extern BLOCK block[]; // array of blocks
+
+#define MAX_ARPMODE 16
+
+extern int8_t arptable[][5];
+
+extern uint16_t freqs[];
+//extern uint16_t cincs[];
+extern uint32_t cincs[];
+
+extern uint8_t xorshift8();
+extern uint16_t xorshift16();
+
+extern uint16_t noiseval;
+
+extern void setOSC(OSC*,byte, byte, byte, byte, byte,
+            uint8_t, uint8_t,
+            uint16_t, uint16_t, uint16_t, uint16_t,
+            int16_t, int16_t, uint8_t, uint8_t, uint8_t);
+
+extern void setOSC(OSC*,byte,byte,uint16_t, uint8_t, uint32_t);
+
+extern void waveoff(OSC*);
+#endif // SYNTH_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_envfuncs.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,93 @@
+/**************************************************************************/
+/*!
+    @file     Synth_envfuncs.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "Synth.h"
+
+/** ENVELOPE FUNCTIONS **/
+
+void noADSR(OSC* o){
+}
+
+void attackFunc(OSC* o){
+    if (o->adsrvol >= o->vol) {
+        if (o->decay) {
+            o->adsrvol = o->vol;
+            o->adsrphase = 2;
+        } else {
+            o->adsrvol = o->sustain;
+            o->adsrphase = 3;
+        }
+        return;
+    }
+    o->adsrvol += o->attack;
+}
+
+void decayFunc(OSC* o){
+    if (o->adsrvol >= o->sustain + o->decay) {
+        o->adsrvol -= o->decay;
+        return;
+    } else {
+        o->adsrvol = o->sustain;
+        o->adsrphase = 3;
+    }
+}
+
+void releaseFunc(OSC* o){
+    if (o->adsrvol > o->release) o->adsrvol -= o->release;
+    else o->adsrvol = 0;
+    if (!o->adsrvol) { // we have hit zero volume level
+        if (o->loop) {
+                if (o->attack) {
+                    o->adsrvol = 0;
+                } else {
+                    o->adsrvol = o->vol;
+                }
+                if (o->echo) o->echodiv++;
+                o->adsrphase = 1;
+                return;
+        }
+        else {
+                o->adsrphase = 0;
+                o->adsrvol = 0;
+                return;
+        }
+    }
+}
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_helpers.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,829 @@
+/**************************************************************************/
+/*!
+    @file     Synth_envfuncs.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#include "Pokitto.h"
+#include "Synth.h"
+#include "Pokitto_settings.h"
+
+#define PROGMEM
+    #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
+    #ifndef WIN32
+    #ifndef pgm_read_word
+    #define pgm_read_word(addr) (*(const unsigned short *)(addr))
+    #endif
+    #else
+    #define pgm_read_word(addr) (*(const unsigned int *)(addr))
+    #endif // WIN32
+
+// http://www.arklyffe.com/main/2010/08/29/xorshift-pseudorandom-number-generator/
+static uint8_t y8 = 1;
+static uint16_t y16 = 1;
+
+// returns values from 1 to 255 inclusive, period is 255
+uint8_t xorshift8(void) {
+    //y8 ^= (y8 << 7);
+    y8 ^= (y8 * 128);
+    y8 ^= (y8 >> 5);
+    //return y8 ^= (y8 << 3);
+    return y8 ^= (y8 * 8);
+}
+
+// returns values from 1 to 65535 inclusive, period is 65535
+uint16_t xorshift16(void) {
+    //y16 ^= (y16 << 13);
+    y16 ^= (y16 * 8192);
+    y16 ^= (y16 >> 9);
+    //return y16 ^= (y16 << 7);
+    return y16 ^= (y16 * 128);
+}
+
+
+int8_t arptable[MAX_ARPMODE][5] = {
+{0,0,0,0,0}, // Off
+{0,4,7,4,0}, // Major tonic, 3rd, 5th
+{0,3,7,3,0}, // Minor tonic, 3rd, 5th
+{0,1,0,-1,0}, // vibrato test
+{0,12,0,12,0}, // octave test
+{0,11,14,17,21}, // funky test
+};
+
+
+/** VITAL TABLES **/
+
+#if (POK_AUD_FREQ==8000)
+
+uint32_t cincs[] ={
+16573205	,	  // 0 - NOTE_B0
+17555679	,	  // 1 - NOTE_C1
+18602577	,	  // 2 - NOTE_CS1
+19708531	,	  // 3 - NOTE_D1
+20878910	,	  // 4 - NOTE_DS1
+22119082	,	  // 5 - NOTE_E1
+23434415	,	  // 6 - NOTE_F1
+24830280	,	  // 7 - NOTE_FS1
+26306675	,	  // 8 - NOTE_G1
+27868969	,	  // 9 - NOTE_GS1
+29527900	,	  // 10 - NOTE_A1
+31283468	,	  // 11 - NOTE_AS1
+33146410	,	  // 12 - NOTE_B1
+35116726	,	  // 13 - NOTE_C2
+37205154	,	  // 14 - NOTE_CS2
+39417062	,	  // 15 - NOTE_D2
+41757820	,	  // 16 - NOTE_DS2
+44243532	,	  // 17 - NOTE_E2
+46874199	,	  // 18 - NOTE_F2
+49660559	,	  // 19 - NOTE_FS2
+52613349	,	  // 20 - NOTE_G2
+55743307	,	  // 21 - NOTE_GS2
+59055800	,	  // 22 - NOTE_A2
+62566936	,	  // 23 - NOTE_AS2
+66287451	,	  // 24 - NOTE_B2
+70228084	,	  // 25 - NOTE_C3
+74404940	,	  // 26 - NOTE_CS3
+78828756	,	  // 27 - NOTE_D3
+83515639	,	  // 28 - NOTE_DS3
+88481695	,	  // 29 - NOTE_E3
+93743030	,	  // 30 - NOTE_F3
+99321119	,	  // 31 - NOTE_FS3
+105226699	,	  // 32 - NOTE_G3
+111481245	,	  // 33 - NOTE_GS3
+118111601	,	  // 34 - NOTE_A3
+125133872	,	  // 35 - NOTE_AS3
+132574903	,	  // 36 - NOTE_B3
+140461537	,	  // 37 - NOTE_C4
+148809879	,	  // 38 - NOTE_CS4
+157657512	,	  // 39 - NOTE_D4
+167036647	,	  // 40 - NOTE_DS4
+176968759	,	  // 41 - NOTE_E4
+187491429	,	  // 42 - NOTE_F4
+198636869	,	  // 43 - NOTE_FS4
+210453397	,	  // 44 - NOTE_G4
+222962490	,	  // 45 - NOTE_GS4
+236223201	,	  // 46 - NOTE_A4 // 440Hz
+250267744	,	  // 47 - NOTE_AS4
+265149806	,	  // 48 - NOTE_B4
+280917705	,	  // 49 - NOTE_C5
+297625127	,	  // 50 - NOTE_CS5
+315320393	,	  // 51 - NOTE_D5
+334067925	,	  // 52 - NOTE_DS5
+353932149	,	  // 53 - NOTE_E5
+374982857	,	  // 54 - NOTE_F5
+397279106	,	  // 55 - NOTE_FS5
+420901426	,	  // 56 - NOTE_G5
+445930348	,	  // 57 - NOTE_GS5
+472446402	,	  // 58 - NOTE_A5
+500540857	,	  // 59 - NOTE_AS5
+530304981	,	  // 60 - NOTE_B5
+561835409	,	  // 61 - NOTE_C6
+595244886	,	  // 62 - NOTE_CS6
+630640785	,	  // 63 - NOTE_D6
+668141219	,	  // 64 - NOTE_DS6
+707869666	,	  // 65 - NOTE_E6
+749960346	,	  // 66 - NOTE_F6
+794558212	,	  // 67 - NOTE_FS6
+841802852	,	  // 68 - NOTE_G6
+891860696	,	  // 69 - NOTE_GS6
+944892805	,	  // 70 - NOTE_A6
+1001081715	,	  // 71 - NOTE_AS6
+1060604593	,	  // 72 - NOTE_B6
+1123670819	,	  // 73 - NOTE_C7
+1190489772	,	  // 74 - NOTE_CS7
+1261281571	,	  // 75 - NOTE_D7
+1336282437	,	  // 76 - NOTE_DS7
+1415739332	,	  // 77 - NOTE_E7
+1499926060	,	  // 78 - NOTE_F7
+1589116424	,	  // 79 - NOTE_FS7
+1683605705	,	  // 80 - NOTE_G7
+1783721392	,	  // 81 - NOTE_GS7
+1889785610	,	  // 82 - NOTE_A7
+2002158060	,	  // 83 - NOTE_AS7
+2121214554	,	  // 84 - NOTE_B7
+2247347006	,	  // 85 - NOTE_C8
+2380979544	,	  // 86 - NOTE_CS8
+2522557773	,	  // 87 - NOTE_D8
+2672559505	,	  // 88 - NOTE_DS8
+};
+
+#elif (POK_AUD_FREQ==11025)
+
+uint32_t cincs[] ={
+12025908	,	  // 0 - NOTE_B0
+12738815	,	  // 1 - NOTE_C1
+13498469	,	  // 2 - NOTE_CS1
+14300975	,	  // 3 - NOTE_D1
+15150229	,	  // 4 - NOTE_DS1
+16050127	,	  // 5 - NOTE_E1
+17004564	,	  // 6 - NOTE_F1
+18017436	,	  // 7 - NOTE_FS1
+19088744	,	  // 8 - NOTE_G1
+20222381	,	  // 9 - NOTE_GS1
+21426141	,	  // 10 - NOTE_A1
+22700022	,	  // 11 - NOTE_AS1
+24051817	,	  // 12 - NOTE_B1
+25481525	,	  // 13 - NOTE_C2
+26996937	,	  // 14 - NOTE_CS2
+28601950	,	  // 15 - NOTE_D2
+30300459	,	  // 16 - NOTE_DS2
+32104150	,	  // 17 - NOTE_E2
+34013024	,	  // 18 - NOTE_F2
+36034873	,	  // 19 - NOTE_FS2
+38177487	,	  // 20 - NOTE_G2
+40448658	,	  // 21 - NOTE_GS2
+42852281	,	  // 22 - NOTE_A2
+45400044	,	  // 23 - NOTE_AS2
+48099738	,	  // 24 - NOTE_B2
+50959154	,	  // 25 - NOTE_C3
+53989979	,	  // 26 - NOTE_CS3
+57200004	,	  // 27 - NOTE_D3
+60600917	,	  // 28 - NOTE_DS3
+64204405	,	  // 29 - NOTE_E3
+68022153	,	  // 30 - NOTE_F3
+72069746	,	  // 31 - NOTE_FS3
+76354974	,	  // 32 - NOTE_G3
+80893420	,	  // 33 - NOTE_GS3
+85704563	,	  // 34 - NOTE_A3
+90800089	,	  // 35 - NOTE_AS3
+96199476	,	  // 36 - NOTE_B3
+101922203	,	  // 37 - NOTE_C4
+107979958	,	  // 38 - NOTE_CS4
+114400009	,	  // 39 - NOTE_D4
+121205730	,	  // 40 - NOTE_DS4
+128412705	,	  // 41 - NOTE_E4
+136048202	,	  // 42 - NOTE_F4
+144135596	,	  // 43 - NOTE_FS4
+152709948	,	  // 44 - NOTE_G4
+161786841	,	  // 45 - NOTE_GS4
+171409126	,	  // 46 - NOTE_A4 // 440Hz
+181600177	,	  // 47 - NOTE_AS4
+192398952	,	  // 48 - NOTE_B4
+203840511	,	  // 49 - NOTE_C5
+215963811	,	  // 50 - NOTE_CS5
+228803913	,	  // 51 - NOTE_D5
+242407565	,	  // 52 - NOTE_DS5
+256821514	,	  // 53 - NOTE_E5
+272096404	,	  // 54 - NOTE_F5
+288275088	,	  // 55 - NOTE_FS5
+305416001	,	  // 56 - NOTE_G5
+323577577	,	  // 57 - NOTE_GS5
+342818251	,	  // 58 - NOTE_A5
+363204250	,	  // 59 - NOTE_AS5
+384801800	,	  // 60 - NOTE_B5
+407681023	,	  // 61 - NOTE_C6
+431923727	,	  // 62 - NOTE_CS6
+457607826	,	  // 63 - NOTE_D6
+484819025	,	  // 64 - NOTE_DS6
+513646923	,	  // 65 - NOTE_E6
+544188913	,	  // 66 - NOTE_F6
+576550177	,	  // 67 - NOTE_FS6
+610832002	,	  // 68 - NOTE_G6
+647155154	,	  // 69 - NOTE_GS6
+685636502	,	  // 70 - NOTE_A6
+726408500	,	  // 71 - NOTE_AS6
+769599704	,	  // 72 - NOTE_B6
+815362045	,	  // 73 - NOTE_C7
+863847454	,	  // 74 - NOTE_CS7
+915215652	,	  // 75 - NOTE_D7
+969638050	,	  // 76 - NOTE_DS7
+1027293846	,	  // 77 - NOTE_E7
+1088381721	,	  // 78 - NOTE_F7
+1153100353	,	  // 79 - NOTE_FS7
+1221664003	,	  // 80 - NOTE_G7
+1294310307	,	  // 81 - NOTE_GS7
+1371273005	,	  // 82 - NOTE_A7
+1452813105	,	  // 83 - NOTE_AS7
+1539203304	,	  // 84 - NOTE_B7
+1630727986	,	  // 85 - NOTE_C8
+1727694908	,	  // 86 - NOTE_CS8
+1830427409	,	  // 87 - NOTE_D8
+1939272203	,	  // 88 - NOTE_DS8
+};
+
+#elif (POK_AUD_FREQ==16000)
+
+uint32_t cincs[] ={
+8286603	,	  // 0 - NOTE_B0
+8777839	,	  // 1 - NOTE_C1
+9301289	,	  // 2 - NOTE_CS1
+9854266	,	  // 3 - NOTE_D1
+10439455	,	  // 4 - NOTE_DS1
+11059541	,	  // 5 - NOTE_E1
+11717208	,	  // 6 - NOTE_F1
+12415140	,	  // 7 - NOTE_FS1
+13153337	,	  // 8 - NOTE_G1
+13934485	,	  // 9 - NOTE_GS1
+14763950	,	  // 10 - NOTE_A1
+15641734	,	  // 11 - NOTE_AS1
+16573205	,	  // 12 - NOTE_B1
+17558363	,	  // 13 - NOTE_C2
+18602577	,	  // 14 - NOTE_CS2
+19708531	,	  // 15 - NOTE_D2
+20878910	,	  // 16 - NOTE_DS2
+22121766	,	  // 17 - NOTE_E2
+23437100	,	  // 18 - NOTE_F2
+24830280	,	  // 19 - NOTE_FS2
+26306675	,	  // 20 - NOTE_G2
+27871653	,	  // 21 - NOTE_GS2
+29527900	,	  // 22 - NOTE_A2
+31283468	,	  // 23 - NOTE_AS2
+33143726	,	  // 24 - NOTE_B2
+35114042	,	  // 25 - NOTE_C3
+37202470	,	  // 26 - NOTE_CS3
+39414378	,	  // 27 - NOTE_D3
+41757820	,	  // 28 - NOTE_DS3
+44240847	,	  // 29 - NOTE_E3
+46871515	,	  // 30 - NOTE_F3
+49660559	,	  // 31 - NOTE_FS3
+52613349	,	  // 32 - NOTE_G3
+55740622	,	  // 33 - NOTE_GS3
+59055800	,	  // 34 - NOTE_A3
+62566936	,	  // 35 - NOTE_AS3
+66287451	,	  // 36 - NOTE_B3
+70230768	,	  // 37 - NOTE_C4
+74404940	,	  // 38 - NOTE_CS4
+78828756	,	  // 39 - NOTE_D4
+83518323	,	  // 40 - NOTE_DS4
+88484379	,	  // 41 - NOTE_E4
+93745714	,	  // 42 - NOTE_F4
+99318434	,	  // 43 - NOTE_FS4
+105226699	,	  // 44 - NOTE_G4
+111481245	,	  // 45 - NOTE_GS4
+118111601	,	  // 46 - NOTE_A4 // 440Hz
+125133872	,	  // 47 - NOTE_AS4
+132574903	,	  // 48 - NOTE_B4
+140458852	,	  // 49 - NOTE_C5
+148812564	,	  // 50 - NOTE_CS5
+157660196	,	  // 51 - NOTE_D5
+167033962	,	  // 52 - NOTE_DS5
+176966074	,	  // 53 - NOTE_E5
+187491429	,	  // 54 - NOTE_F5
+198639553	,	  // 55 - NOTE_FS5
+210450713	,	  // 56 - NOTE_G5
+222965174	,	  // 57 - NOTE_GS5
+236223201	,	  // 58 - NOTE_A5
+250270429	,	  // 59 - NOTE_AS5
+265152490	,	  // 60 - NOTE_B5
+280917705	,	  // 61 - NOTE_C6
+297622443	,	  // 62 - NOTE_CS6
+315320393	,	  // 63 - NOTE_D6
+334070609	,	  // 64 - NOTE_DS6
+353934833	,	  // 65 - NOTE_E6
+374980173	,	  // 66 - NOTE_F6
+397279106	,	  // 67 - NOTE_FS6
+420901426	,	  // 68 - NOTE_G6
+445930348	,	  // 69 - NOTE_GS6
+472446402	,	  // 70 - NOTE_A6
+500540857	,	  // 71 - NOTE_AS6
+530302296	,	  // 72 - NOTE_B6
+561835409	,	  // 73 - NOTE_C7
+595244886	,	  // 74 - NOTE_CS7
+630640785	,	  // 75 - NOTE_D7
+668141219	,	  // 76 - NOTE_DS7
+707869666	,	  // 77 - NOTE_E7
+749963030	,	  // 78 - NOTE_F7
+794558212	,	  // 79 - NOTE_FS7
+841802852	,	  // 80 - NOTE_G7
+891860696	,	  // 81 - NOTE_GS7
+944892805	,	  // 82 - NOTE_A7
+1001079030	,	  // 83 - NOTE_AS7
+1060607277	,	  // 84 - NOTE_B7
+1123673503	,	  // 85 - NOTE_C8
+1190489772	,	  // 86 - NOTE_CS8
+1261278886	,	  // 87 - NOTE_D8
+1336279753	,	  // 88 - NOTE_DS8
+};
+
+#elif (POK_AUD_FREQ==22050)
+
+uint32_t cincs[] ={
+6012954	,	  // 0 - NOTE_B0
+6369407	,	  // 1 - NOTE_C1
+6749234	,	  // 2 - NOTE_CS1
+7150488	,	  // 3 - NOTE_D1
+7575115	,	  // 4 - NOTE_DS1
+8025064	,	  // 5 - NOTE_E1
+8502282	,	  // 6 - NOTE_F1
+9008718	,	  // 7 - NOTE_FS1
+9544372	,	  // 8 - NOTE_G1
+10111191	,	  // 9 - NOTE_GS1
+10713070	,	  // 10 - NOTE_A1
+11350011	,	  // 11 - NOTE_AS1
+12025908	,	  // 12 - NOTE_B1
+12740762	,	  // 13 - NOTE_C2
+13498469	,	  // 14 - NOTE_CS2
+14300975	,	  // 15 - NOTE_D2
+15150229	,	  // 16 - NOTE_DS2
+16052075	,	  // 17 - NOTE_E2
+17006512	,	  // 18 - NOTE_F2
+18017436	,	  // 19 - NOTE_FS2
+19088744	,	  // 20 - NOTE_G2
+20224329	,	  // 21 - NOTE_GS2
+21426141	,	  // 22 - NOTE_A2
+22700022	,	  // 23 - NOTE_AS2
+24049869	,	  // 24 - NOTE_B2
+25479577	,	  // 25 - NOTE_C3
+26994989	,	  // 26 - NOTE_CS3
+28600002	,	  // 27 - NOTE_D3
+30300459	,	  // 28 - NOTE_DS3
+32102202	,	  // 29 - NOTE_E3
+34011077	,	  // 30 - NOTE_F3
+36034873	,	  // 31 - NOTE_FS3
+38177487	,	  // 32 - NOTE_G3
+40446710	,	  // 33 - NOTE_GS3
+42852281	,	  // 34 - NOTE_A3
+45400044	,	  // 35 - NOTE_AS3
+48099738	,	  // 36 - NOTE_B3
+50961102	,	  // 37 - NOTE_C4
+53989979	,	  // 38 - NOTE_CS4
+57200004	,	  // 39 - NOTE_D4
+60602865	,	  // 40 - NOTE_DS4
+64206352	,	  // 41 - NOTE_E4
+68024101	,	  // 42 - NOTE_F4
+72067798	,	  // 43 - NOTE_FS4
+76354974	,	  // 44 - NOTE_G4
+80893420	,	  // 45 - NOTE_GS4
+85704563	,	  // 46 - NOTE_A4 // 440Hz
+90800089	,	  // 47 - NOTE_AS4
+96199476	,	  // 48 - NOTE_B4
+101920256	,	  // 49 - NOTE_C5
+107981906	,	  // 50 - NOTE_CS5
+114401957	,	  // 51 - NOTE_D5
+121203782	,	  // 52 - NOTE_DS5
+128410757	,	  // 53 - NOTE_E5
+136048202	,	  // 54 - NOTE_F5
+144137544	,	  // 55 - NOTE_FS5
+152708000	,	  // 56 - NOTE_G5
+161788788	,	  // 57 - NOTE_GS5
+171409126	,	  // 58 - NOTE_A5
+181602125	,	  // 59 - NOTE_AS5
+192400900	,	  // 60 - NOTE_B5
+203840511	,	  // 61 - NOTE_C6
+215961863	,	  // 62 - NOTE_CS6
+228803913	,	  // 63 - NOTE_D6
+242409512	,	  // 64 - NOTE_DS6
+256823462	,	  // 65 - NOTE_E6
+272094456	,	  // 66 - NOTE_F6
+288275088	,	  // 67 - NOTE_FS6
+305416001	,	  // 68 - NOTE_G6
+323577577	,	  // 69 - NOTE_GS6
+342818251	,	  // 70 - NOTE_A6
+363204250	,	  // 71 - NOTE_AS6
+384799852	,	  // 72 - NOTE_B6
+407681023	,	  // 73 - NOTE_C7
+431923727	,	  // 74 - NOTE_CS7
+457607826	,	  // 75 - NOTE_D7
+484819025	,	  // 76 - NOTE_DS7
+513646923	,	  // 77 - NOTE_E7
+544190861	,	  // 78 - NOTE_F7
+576550177	,	  // 79 - NOTE_FS7
+610832002	,	  // 80 - NOTE_G7
+647155154	,	  // 81 - NOTE_GS7
+685636502	,	  // 82 - NOTE_A7
+726406553	,	  // 83 - NOTE_AS7
+769601652	,	  // 84 - NOTE_B7
+815363993	,	  // 85 - NOTE_C8
+863847454	,	  // 86 - NOTE_CS8
+915213704	,	  // 87 - NOTE_D8
+969636102	,	  // 88 - NOTE_DS8
+};
+
+
+#elif (POK_AUD_FREQ==32000)
+
+uint32_t cincs[] ={
+4143301	,	  // 0 - NOTE_B0
+4388920	,	  // 1 - NOTE_C1
+4650644	,	  // 2 - NOTE_CS1
+4927133	,	  // 3 - NOTE_D1
+5219727	,	  // 4 - NOTE_DS1
+5529770	,	  // 5 - NOTE_E1
+5858604	,	  // 6 - NOTE_F1
+6207570	,	  // 7 - NOTE_FS1
+6576669	,	  // 8 - NOTE_G1
+6967242	,	  // 9 - NOTE_GS1
+7381975	,	  // 10 - NOTE_A1
+7820867	,	  // 11 - NOTE_AS1
+8286603	,	  // 12 - NOTE_B1
+8779182	,	  // 13 - NOTE_C2
+9301289	,	  // 14 - NOTE_CS2
+9854266	,	  // 15 - NOTE_D2
+10439455	,	  // 16 - NOTE_DS2
+11060883	,	  // 17 - NOTE_E2
+11718550	,	  // 18 - NOTE_F2
+12415140	,	  // 19 - NOTE_FS2
+13153337	,	  // 20 - NOTE_G2
+13935827	,	  // 21 - NOTE_GS2
+14763950	,	  // 22 - NOTE_A2
+15641734	,	  // 23 - NOTE_AS2
+16571863	,	  // 24 - NOTE_B2
+17557021	,	  // 25 - NOTE_C3
+18601235	,	  // 26 - NOTE_CS3
+19707189	,	  // 27 - NOTE_D3
+20878910	,	  // 28 - NOTE_DS3
+22120424	,	  // 29 - NOTE_E3
+23435757	,	  // 30 - NOTE_F3
+24830280	,	  // 31 - NOTE_FS3
+26306675	,	  // 32 - NOTE_G3
+27870311	,	  // 33 - NOTE_GS3
+29527900	,	  // 34 - NOTE_A3
+31283468	,	  // 35 - NOTE_AS3
+33143726	,	  // 36 - NOTE_B3
+35115384	,	  // 37 - NOTE_C4
+37202470	,	  // 38 - NOTE_CS4
+39414378	,	  // 39 - NOTE_D4
+41759162	,	  // 40 - NOTE_DS4
+44242190	,	  // 41 - NOTE_E4
+46872857	,	  // 42 - NOTE_F4
+49659217	,	  // 43 - NOTE_FS4
+52613349	,	  // 44 - NOTE_G4
+55740622	,	  // 45 - NOTE_GS4
+59055800	,	  // 46 - NOTE_A4 // 440Hz
+62566936	,	  // 47 - NOTE_AS4
+66287451	,	  // 48 - NOTE_B4
+70229426	,	  // 49 - NOTE_C5
+74406282	,	  // 50 - NOTE_CS5
+78830098	,	  // 51 - NOTE_D5
+83516981	,	  // 52 - NOTE_DS5
+88483037	,	  // 53 - NOTE_E5
+93745714	,	  // 54 - NOTE_F5
+99319777	,	  // 55 - NOTE_FS5
+105225357	,	  // 56 - NOTE_G5
+111482587	,	  // 57 - NOTE_GS5
+118111601	,	  // 58 - NOTE_A5
+125135214	,	  // 59 - NOTE_AS5
+132576245	,	  // 60 - NOTE_B5
+140458852	,	  // 61 - NOTE_C6
+148811222	,	  // 62 - NOTE_CS6
+157660196	,	  // 63 - NOTE_D6
+167035305	,	  // 64 - NOTE_DS6
+176967417	,	  // 65 - NOTE_E6
+187490086	,	  // 66 - NOTE_F6
+198639553	,	  // 67 - NOTE_FS6
+210450713	,	  // 68 - NOTE_G6
+222965174	,	  // 69 - NOTE_GS6
+236223201	,	  // 70 - NOTE_A6
+250270429	,	  // 71 - NOTE_AS6
+265151148	,	  // 72 - NOTE_B6
+280917705	,	  // 73 - NOTE_C7
+297622443	,	  // 74 - NOTE_CS7
+315320393	,	  // 75 - NOTE_D7
+334070609	,	  // 76 - NOTE_DS7
+353934833	,	  // 77 - NOTE_E7
+374981515	,	  // 78 - NOTE_F7
+397279106	,	  // 79 - NOTE_FS7
+420901426	,	  // 80 - NOTE_G7
+445930348	,	  // 81 - NOTE_GS7
+472446402	,	  // 82 - NOTE_A7
+500539515	,	  // 83 - NOTE_AS7
+530303638	,	  // 84 - NOTE_B7
+561836751	,	  // 85 - NOTE_C8
+595244886	,	  // 86 - NOTE_CS8
+630639443	,	  // 87 - NOTE_D8
+668139876	,	  // 88 - NOTE_DS8
+};
+
+
+#elif (POK_AUD_FREQ==44100)
+
+uint32_t cincs[] ={
+3006477	,	  // 0 - NOTE_B0
+3184704	,	  // 1 - NOTE_C1
+3374617	,	  // 2 - NOTE_CS1
+3575244	,	  // 3 - NOTE_D1
+3787557	,	  // 4 - NOTE_DS1
+4012532	,	  // 5 - NOTE_E1
+4251141	,	  // 6 - NOTE_F1
+4504359	,	  // 7 - NOTE_FS1
+4772186	,	  // 8 - NOTE_G1
+5055595	,	  // 9 - NOTE_GS1
+5356535	,	  // 10 - NOTE_A1
+5675006	,	  // 11 - NOTE_AS1
+6012954	,	  // 12 - NOTE_B1
+6370381	,	  // 13 - NOTE_C2
+6749234	,	  // 14 - NOTE_CS2
+7150488	,	  // 15 - NOTE_D2
+7575115	,	  // 16 - NOTE_DS2
+8026038	,	  // 17 - NOTE_E2
+8503256	,	  // 18 - NOTE_F2
+9008718	,	  // 19 - NOTE_FS2
+9544372	,	  // 20 - NOTE_G2
+10112164	,	  // 21 - NOTE_GS2
+10713070	,	  // 22 - NOTE_A2
+11350011	,	  // 23 - NOTE_AS2
+12024935	,	  // 24 - NOTE_B2
+12739788	,	  // 25 - NOTE_C3
+13497495	,	  // 26 - NOTE_CS3
+14300001	,	  // 27 - NOTE_D3
+15150229	,	  // 28 - NOTE_DS3
+16051101	,	  // 29 - NOTE_E3
+17005538	,	  // 30 - NOTE_F3
+18017436	,	  // 31 - NOTE_FS3
+19088744	,	  // 32 - NOTE_G3
+20223355	,	  // 33 - NOTE_GS3
+21426141	,	  // 34 - NOTE_A3
+22700022	,	  // 35 - NOTE_AS3
+24049869	,	  // 36 - NOTE_B3
+25480551	,	  // 37 - NOTE_C4
+26994989	,	  // 38 - NOTE_CS4
+28600002	,	  // 39 - NOTE_D4
+30301433	,	  // 40 - NOTE_DS4
+32103176	,	  // 41 - NOTE_E4
+34012051	,	  // 42 - NOTE_F4
+36033899	,	  // 43 - NOTE_FS4
+38177487	,	  // 44 - NOTE_G4
+40446710	,	  // 45 - NOTE_GS4
+42852281	,	  // 46 - NOTE_A4 // 440Hz
+45400044	,	  // 47 - NOTE_AS4
+48099738	,	  // 48 - NOTE_B4
+50960128	,	  // 49 - NOTE_C5
+53990953	,	  // 50 - NOTE_CS5
+57200978	,	  // 51 - NOTE_D5
+60601891	,	  // 52 - NOTE_DS5
+64205378	,	  // 53 - NOTE_E5
+68024101	,	  // 54 - NOTE_F5
+72068772	,	  // 55 - NOTE_FS5
+76354000	,	  // 56 - NOTE_G5
+80894394	,	  // 57 - NOTE_GS5
+85704563	,	  // 58 - NOTE_A5
+90801063	,	  // 59 - NOTE_AS5
+96200450	,	  // 60 - NOTE_B5
+101920256	,	  // 61 - NOTE_C6
+107980932	,	  // 62 - NOTE_CS6
+114401957	,	  // 63 - NOTE_D6
+121204756	,	  // 64 - NOTE_DS6
+128411731	,	  // 65 - NOTE_E6
+136047228	,	  // 66 - NOTE_F6
+144137544	,	  // 67 - NOTE_FS6
+152708000	,	  // 68 - NOTE_G6
+161788788	,	  // 69 - NOTE_GS6
+171409126	,	  // 70 - NOTE_A6
+181602125	,	  // 71 - NOTE_AS6
+192399926	,	  // 72 - NOTE_B6
+203840511	,	  // 73 - NOTE_C7
+215961863	,	  // 74 - NOTE_CS7
+228803913	,	  // 75 - NOTE_D7
+242409512	,	  // 76 - NOTE_DS7
+256823462	,	  // 77 - NOTE_E7
+272095430	,	  // 78 - NOTE_F7
+288275088	,	  // 79 - NOTE_FS7
+305416001	,	  // 80 - NOTE_G7
+323577577	,	  // 81 - NOTE_GS7
+342818251	,	  // 82 - NOTE_A7
+363203276	,	  // 83 - NOTE_AS7
+384800826	,	  // 84 - NOTE_B7
+407681997	,	  // 85 - NOTE_C8
+431923727	,	  // 86 - NOTE_CS8
+457606852	,	  // 87 - NOTE_D8
+484818051	,	  // 88 - NOTE_DS8
+};
+
+
+
+#endif
+
+/** NOTE TO TEXT TABLES **/
+
+const char note_0[] PROGMEM = "B-0";  // 0 - NOTE_B0
+const char note_1[] PROGMEM = "C-1";  // 1 - NOTE_C1
+const char note_2[] PROGMEM = "C#1";  // 2 - NOTE_CS1
+const char note_3[] PROGMEM = "D-1";  // 3 - NOTE_D1
+const char note_4[] PROGMEM = "D#1";  // 4 - NOTE_DS1
+const char note_5[] PROGMEM = "E-1";  // 5 - NOTE_E1
+const char note_6[] PROGMEM = "F-1";  // 6 - NOTE_F1
+const char note_7[] PROGMEM = "F#1";  // 7 - NOTE_FS1
+const char note_8[] PROGMEM = "G-1";  // 8 - NOTE_G1
+const char note_9[] PROGMEM = "G#1";  // 9 - NOTE_GS1
+const char note_10[] PROGMEM = "A-1";  // 10 - NOTE_A1
+const char note_11[] PROGMEM = "A#1";  // 11 - NOTE_AS1
+const char note_12[] PROGMEM = "B-1";  // 12 - NOTE_B1
+const char note_13[] PROGMEM = "C-2";  // 2 - NOTE_C2
+const char note_14[] PROGMEM = "C#2";  // 2 - NOTE_CS2
+const char note_15[] PROGMEM = "D-2";  // 3 - NOTE_D2
+const char note_16[] PROGMEM = "D#2";  // 4 - NOTE_DS2
+const char note_17[] PROGMEM = "E-2";  // 5 - NOTE_E2
+const char note_18[] PROGMEM = "F-2";  // 6 - NOTE_F2
+const char note_19[] PROGMEM = "F#2";  // 7 - NOTE_FS2
+const char note_20[] PROGMEM = "G-2";  // 8 - NOTE_G2
+const char note_21[] PROGMEM = "G#2";  // 9 - NOTE_GS2
+const char note_22[] PROGMEM = "A-2";  // 20 - NOTE_A2
+const char note_23[] PROGMEM = "A#2";  // 22 - NOTE_AS2
+const char note_24[] PROGMEM = "B-2";  // 22 - NOTE_B2
+const char note_25[] PROGMEM = "C-3";  // 3 - NOTE_C3
+const char note_26[] PROGMEM = "C#3";  // 3 - NOTE_CS3
+const char note_27[] PROGMEM = "D-3";  // 3 - NOTE_D3
+const char note_28[] PROGMEM = "D#3";  // 4 - NOTE_DS3
+const char note_29[] PROGMEM = "E-3";  // 5 - NOTE_E3
+const char note_30[] PROGMEM = "F-3";  // 6 - NOTE_F3
+const char note_31[] PROGMEM = "F#3";  // 7 - NOTE_FS3
+const char note_32[] PROGMEM = "G-3";  // 8 - NOTE_G3
+const char note_33[] PROGMEM = "G#3";  // 9 - NOTE_GS3
+const char note_34[] PROGMEM = "A-3";  // 30 - NOTE_A3
+const char note_35[] PROGMEM = "A#3";  // 33 - NOTE_AS3
+const char note_36[] PROGMEM = "B-3";  // 33 - NOTE_B3
+const char note_37[] PROGMEM = "C-4";  // 4 - NOTE_C4
+const char note_38[] PROGMEM = "C#4";  // 4 - NOTE_CS4
+const char note_39[] PROGMEM = "D-4";  // 3 - NOTE_D4
+const char note_40[] PROGMEM = "D#4";  // 4 - NOTE_DS4
+const char note_41[] PROGMEM = "E-4";  // 5 - NOTE_E4
+const char note_42[] PROGMEM = "F-4";  // 6 - NOTE_F4
+const char note_43[] PROGMEM = "F#4";  // 7 - NOTE_FS4
+const char note_44[] PROGMEM = "G-4";  // 8 - NOTE_G4
+const char note_45[] PROGMEM = "G#4";  // 9 - NOTE_GS4
+const char note_46[] PROGMEM = "A-4";  // 40 - NOTE_A4
+const char note_47[] PROGMEM = "A#4";  // 44 - NOTE_AS4
+const char note_48[] PROGMEM = "B-4";  // 44 - NOTE_B4
+const char note_49[] PROGMEM = "C-5";  // 5 - NOTE_C5
+const char note_50[] PROGMEM = "C#5";  // 5 - NOTE_CS5
+const char note_51[] PROGMEM = "D-5";  // 3 - NOTE_D5
+const char note_52[] PROGMEM = "D#5";  // 4 - NOTE_DS5
+const char note_53[] PROGMEM = "E-5";  // 5 - NOTE_E5
+const char note_54[] PROGMEM = "F-5";  // 6 - NOTE_F5
+const char note_55[] PROGMEM = "F#5";  // 7 - NOTE_FS5
+const char note_56[] PROGMEM = "G-5";  // 8 - NOTE_G5
+const char note_57[] PROGMEM = "G#5";  // 9 - NOTE_GS5
+const char note_58[] PROGMEM = "A-5";  // 50 - NOTE_A5
+const char note_59[] PROGMEM = "A#5";  // 55 - NOTE_AS5
+const char note_60[] PROGMEM = "B-5";  // 55 - NOTE_B5
+const char note_61[] PROGMEM = "C-6";  // 6 - NOTE_C6
+const char note_62[] PROGMEM = "C#6";  // 6 - NOTE_CS6
+const char note_63[] PROGMEM = "D-6";  // 3 - NOTE_D6
+const char note_64[] PROGMEM = "D#6";  // 4 - NOTE_DS6
+const char note_65[] PROGMEM = "E-6";  // 5 - NOTE_E6
+const char note_66[] PROGMEM = "F-6";  // 6 - NOTE_F6
+const char note_67[] PROGMEM = "F#6";  // 7 - NOTE_FS6
+const char note_68[] PROGMEM = "G-6";  // 8 - NOTE_G6
+const char note_69[] PROGMEM = "G#6";  // 9 - NOTE_GS6
+const char note_70[] PROGMEM = "A-6";  // 60 - NOTE_A6
+const char note_71[] PROGMEM = "A#6";  // 66 - NOTE_AS6
+const char note_72[] PROGMEM = "B-6";  // 66 - NOTE_B6
+const char note_73[] PROGMEM = "C-7";  // 7 - NOTE_C7
+const char note_74[] PROGMEM = "C#7";  // 7 - NOTE_CS7
+const char note_75[] PROGMEM = "D-7";  // 3 - NOTE_D7
+const char note_76[] PROGMEM = "D#7";  // 4 - NOTE_DS7
+const char note_77[] PROGMEM = "E-7";  // 5 - NOTE_E7
+const char note_78[] PROGMEM = "F-7";  // 6 - NOTE_F7
+const char note_79[] PROGMEM = "F#7";  // 7 - NOTE_FS7
+const char note_80[] PROGMEM = "G-7";  // 8 - NOTE_G7
+const char note_81[] PROGMEM = "G#7";  // 9 - NOTE_GS7
+const char note_82[] PROGMEM = "A-7";  // 70 - NOTE_A7
+const char note_83[] PROGMEM = "A#7";  // 77 - NOTE_AS7
+const char note_84[] PROGMEM = "B-7";  // 77 - NOTE_B7
+const char note_85[] PROGMEM = "C-8";  // 8 - NOTE_C8
+const char note_86[] PROGMEM = "C#8";  // 8 - NOTE_CS8
+const char note_87[] PROGMEM = "D-8";  // 3 - NOTE_D8
+const char note_88[] PROGMEM = "D#8";  // 4 - NOTE_DS8
+
+const char* note_table[] PROGMEM = {
+ note_0,
+ note_1,
+ note_2,
+ note_3,
+ note_4,
+ note_5,
+ note_6,
+ note_7,
+ note_8,
+ note_9,
+ note_10,
+ note_11,
+ note_12,
+ note_13,
+ note_14,
+ note_15,
+ note_16,
+ note_17,
+ note_18,
+ note_19,
+ note_20,
+ note_21,
+ note_22,
+ note_23,
+ note_24,
+ note_25,
+ note_26,
+ note_27,
+ note_28,
+ note_29,
+ note_30,
+ note_31,
+ note_32,
+ note_33,
+ note_34,
+ note_35,
+ note_36,
+ note_37,
+ note_38,
+ note_39,
+ note_40,
+ note_41,
+ note_42,
+ note_43,
+ note_44,
+ note_45,
+ note_46,
+ note_47,
+ note_48,
+ note_49,
+ note_50,
+ note_51,
+ note_52,
+ note_53,
+ note_54,
+ note_55,
+ note_56,
+ note_57,
+ note_58,
+ note_59,
+ note_60,
+ note_61,
+ note_62,
+ note_63,
+ note_64,
+ note_65,
+ note_66,
+ note_67,
+ note_68,
+ note_69,
+ note_70,
+ note_71,
+ note_72,
+ note_73,
+ note_74,
+ note_75,
+ note_76,
+ note_77,
+ note_78,
+ note_79,
+ note_80,
+ note_81,
+ note_82,
+ note_83,
+ note_84,
+ note_85,
+ note_86,
+ note_87,
+ note_88,
+};
+
+void getNoteString(char * buffer, uint8_t i) {
+    if (i>88) strcpy(buffer,"@@@");
+    else strcpy(buffer, note_table[i]);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_mixfuncs.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,171 @@
+/**************************************************************************/
+/*!
+    @file     Synth_mixfuncs.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoGlobs.h"
+#include "Synth.h"
+
+/** MIXING FUNCTIONS **/
+
+char voltick=0; // i need to make volume changes even slower
+uint16_t arptick=0; // i need to make volume changes even slower
+int8_t bendtick = 0; // ditto for bend.
+
+
+void mix1(){
+    // Track 1
+    if (osc1.on) {
+    Farr[osc1.wave](&osc1);
+    #if PROJ_ARDUBOY > 0
+    if (osc1.duration) {
+        /**this is special for osc1 and is only used to emulate arduino Tone(); */
+        osc1.duration--;
+    } else osc1.on = 0;
+    #endif
+
+    #ifdef POK_SIM
+    soundbyte = (((osc1.output>>8) * (osc1.adsrvol >>8 )) >> 8) >> osc1.echodiv; // To output, shift back to 8-bit
+    if (osc1.overdrive) soundbyte *= OVERDRIVE;
+    if (osc1.kick ) soundbyte >>= 2;
+    osc1.output = soundbyte;
+    #else
+    //OCR2B = osc1.output>>8;
+    #if POK_ENABLE_SOUND > 0
+    soundbyte = (((osc1.output>>8) * (osc1.adsrvol >>8 )) >> 8) >> osc1.echodiv; // To output, shift back to 8-bit
+    if (osc1.overdrive) soundbyte *= OVERDRIVE;
+    if (osc1.kick ) soundbyte >>= 2;
+    osc1.output = soundbyte;
+    #endif
+    #endif
+    }
+}
+
+void mix2(){
+    // Track 2
+    if (osc2.on) {
+    Farr[osc2.wave](&osc2);
+    #ifdef POK_SIM
+    soundbyte = (((osc2.output>>8) * (osc2.adsrvol >>8 )) >> 8) >> osc2.echodiv;
+    if (osc2.overdrive) soundbyte *= OVERDRIVE;
+    if (osc2.kick ) soundbyte >>= 2;
+    osc2.output = soundbyte;
+    #else
+    //OCR2B = osc2.output>>8;
+    #if POK_ENABLE_SOUND > 0
+    soundbyte = (((osc2.output>>8) * (osc2.adsrvol >>8 )) >> 8) >> osc2.echodiv;
+    if (osc2.overdrive) soundbyte *= OVERDRIVE;
+    if (osc2.kick ) soundbyte >>= 2;
+    osc2.output = soundbyte;
+    #endif
+    #endif
+    }
+}
+
+void mix3(){
+    // Track 3
+    if (osc3.on) {
+    Farr[osc3.wave](&osc3);
+    #ifdef POK_SIM
+    soundbyte = (((osc3.output>>8) * (osc3.adsrvol >>8 )) >> 8) >> osc3.echodiv;
+    if (osc3.overdrive) soundbyte *= OVERDRIVE;
+    if (osc3.kick ) soundbyte >>= 2;
+    osc3.output = soundbyte;
+    #else
+    //OCR2B = osc3.output>>8;
+    #if POK_ENABLE_SOUND > 0
+    soundbyte = (((osc3.output>>8) * (osc3.adsrvol >>8 )) >> 8) >> osc3.echodiv;
+    if (osc3.overdrive) soundbyte *= OVERDRIVE;
+    if (osc3.kick ) soundbyte >>= 2;
+    osc3.output = soundbyte;
+    #endif
+    #endif
+    }
+}
+
+void updateEnvelopes(){
+    //calculate volume envelopes, I do this to save cpu power
+    if (arptick) --arptick;
+    else {
+            if (osc1.arpmode && osc1.on) {
+                osc1.cinc = cincs[osc1.tonic+arptable[osc1.arpmode][osc1.arpstep]];
+                osc1.arpstep++;
+                if (osc1.arpstep==ARPSTEPMAX) osc1.arpstep = 0;
+                arptick = ARPTICK << (3-osc1.arpspeed);
+            }
+            if (osc2.arpmode && osc2.on) {
+                osc2.cinc = cincs[osc2.tonic+arptable[osc2.arpmode][osc2.arpstep]];
+                osc2.arpstep++;
+                if (osc2.arpstep==ARPSTEPMAX) osc2.arpstep = 0;
+                arptick = ARPTICK << (3-osc2.arpspeed);
+            }
+            if (osc3.arpmode && osc3.on) {
+                osc3.cinc = cincs[osc3.tonic+arptable[osc3.arpmode][osc3.arpstep]];
+                osc3.arpstep++;
+                if (osc3.arpstep==ARPSTEPMAX) osc3.arpstep = 0;
+                arptick = ARPTICK << (3-osc3.arpspeed);
+            }
+
+    }
+
+    if (voltick) --voltick;
+    else {
+            bendtick = !bendtick;
+            if (osc1.on) Earr[osc1.adsrphase](&osc1);
+            if (bendtick) osc1.pitchbend += osc1.bendrate; //slow bend to every second beat
+            if (osc1.bendrate > 0 && osc1.pitchbend > osc1.maxbend) {
+                    osc1.pitchbend = osc1.maxbend;
+                    osc1.bendrate = 0; // STOP BENDING !
+            }
+            else if (osc1.bendrate < 0 && osc1.pitchbend < osc1.maxbend) {
+                    osc1.pitchbend = osc1.maxbend;
+                    osc1.bendrate = 0; // STOP BENDING !
+            }
+
+            if (osc2.on) Earr[osc2.adsrphase](&osc2);
+            if (bendtick) osc2.pitchbend += osc2.bendrate;
+            if (osc2.bendrate > 0 && osc2.pitchbend > osc2.maxbend) osc2.pitchbend = osc2.maxbend;
+            else if (osc2.bendrate < 0 && osc2.pitchbend < osc2.maxbend) osc2.pitchbend = osc2.maxbend;
+
+            if (osc3.on) Earr[osc3.adsrphase](&osc3);
+            if (bendtick) osc3.pitchbend += osc3.bendrate;
+            if (osc3.bendrate > 0 && osc3.pitchbend > osc3.maxbend) osc3.pitchbend = osc3.maxbend;
+            else if (osc3.bendrate < 0 && osc3.pitchbend < osc3.maxbend) osc3.pitchbend = osc3.maxbend;
+
+            voltick = VOLTICK;
+    }
+    tick = 4;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_osc.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,70 @@
+/**************************************************************************/
+/*!
+    @file     Synth_osc.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#ifndef SYNTH_OSC_H
+#define SYNTH_OSC_H
+
+#include "Pokitto.h"
+
+typedef uint8_t byte;
+
+struct OSC {
+  byte on;
+  byte wave;
+  byte loop;
+  byte echo;
+  byte echodiv;
+  byte adsr;
+  byte tonic;
+
+  //uint16_t count;
+  uint32_t count;
+
+  uint16_t vol;
+  //uint16_t cinc; // how much to add per cycle
+  uint32_t cinc; // how much to add per cycle
+  uint16_t output; // output is stored as  16 bit value and shifted before its put in OCR2B
+
+  uint8_t adsrphase;
+  uint16_t adsrvol;
+  uint16_t attack; // Attack change
+  uint16_t decay; // Attack change
+  uint16_t sustain; // Attack change
+  uint16_t release; // Attack change
+
+  int16_t pitchbend;   // bends cycle counter (more is higher pitch)
+  int16_t maxbend; // maximum bend before stopping
+  int16_t bendrate; // how much to bend by every cycle
+
+  uint8_t vibrate;
+  uint8_t arpmode;
+  uint8_t arpspeed;
+  uint8_t arpstep;
+  uint8_t overdrive;
+  uint8_t kick;
+
+  uint32_t duration;
+};
+
+
+
+#endif // SYNTH_OSC_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_oscfuncs.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,246 @@
+/**************************************************************************/
+/*!
+    @file     Synth_oscfuncs.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "Synth.h"
+
+/** OSCILLATOR FUNCTIONS **/
+
+void setOSC(OSC* o,byte on=1, byte wave=1, byte loop=0, byte echo=0, byte adsr=0,
+            uint8_t notenumber=25, uint8_t volume=127,
+            uint16_t attack=0, uint16_t decay=0, uint16_t sustain=0, uint16_t release=0,
+            int16_t maxbend=0, int16_t bendrate=0, uint8_t arpmode = 0, uint8_t overdrive=0, uint8_t kick=0){
+  //Serial.println("SetOsc "); osc1
+  o->on = on;
+  o->overdrive = overdrive;
+  o->kick = kick;
+  o->wave = wave;
+  o->loop = loop;
+  o->echo = echo; //echo shifts left 8 steps to zero
+  o->echodiv = 0;
+  o->adsr = adsr;
+  if (arpmode) {
+        if (arpmode < 4) {o->arpmode = 1; o->arpspeed = arpmode;}
+        else if (arpmode < 7) {o->arpmode = 2; o->arpspeed = arpmode-3;}
+        else if (arpmode < 10) {o->arpmode = 3; o->arpspeed = arpmode-6; } // vibrato trial
+        else if (arpmode < 13) {o->arpmode = 4; o->arpspeed = arpmode-9; } // octave trial
+        else if (arpmode < 16) {o->arpmode = 5; o->arpspeed = arpmode-12; } // funk trial*/
+  } else o->arpmode = 0;
+  o->arpstep = 0;
+  o->count = 0;
+  noiseval = xorshift16(); //random(0,0xFFFF);
+
+  o->cinc = cincs[notenumber]; // direct cinc from table, no calculation
+  o->tonic = notenumber; // save tonic for arpeggio use
+  if (wave == 2) o->cinc >>= 1; // correct pitch for saw wave
+  if (wave == 4) o->cinc <<= 1; // enable higher pitch for pure noise
+  o->vol = volume << 8;//volume;
+
+  if (adsr) {
+    o->attack = attack;
+    o->decay = decay;
+    o->sustain = sustain;
+    o->release = release;
+    o->adsrphase = 1;
+    if (!o->attack) o->adsrvol = o->vol; // start directly, no attack ramp
+    else o->adsrvol = 0;
+  } else {
+    o->attack = 0;
+    o->decay = 0;
+    o->sustain = 0;
+    o->release = 0;
+    o->adsrphase = 0;
+    o->adsrvol = o->vol; // will stay same all the time
+  }
+
+  if (bendrate != 0) {
+        o->bendrate = bendrate; // test value
+        o->pitchbend = 0;
+        o->maxbend = maxbend;
+  }
+}
+
+void setOSC(OSC* o,byte on, byte wave, uint16_t frq, uint8_t volume, uint32_t duration){
+  o->on = on;
+  o->overdrive = 0;
+  o->kick = 0;
+  o->wave = wave;
+  o->loop = 0;//1;
+  o->echo = 0;//1; //echo shifts left 8 steps to zero
+  o->echodiv = 0;
+  o->adsr = 0;//1;
+  o->attack = 0;//200;
+  o->decay = 0;//200;
+  o->sustain = 0;//20;
+  o->release = 0;//10;
+  o->adsrphase = 0;//1;
+  o->arpmode = 0;
+  o->count = 0;
+  noiseval = xorshift16(); //random(0,0xFFFF);
+  o->cinc = ((float)0xFFFFFFFF/(float)POK_AUD_FREQ)*frq;
+  if (wave == 2) o->cinc >>= 1; // correct pitch for saw wave
+  if (wave == 4) o->cinc <<= 1; // enable higher pitch for pure noise
+  o->vol = volume << 8;//volume;
+  o->adsrvol = o->vol;
+  o->duration = 0;//duration*100;
+  o->maxbend = 0;//-4000;
+  o->bendrate = 0;//1000;
+}
+
+
+
+void emptyOscillators(){
+    osc1.on = false; osc1.wave = 0; osc1.echo = 0; osc1.count = 0; osc1.cinc =0;
+    osc1.attack = 0; osc1.loop = 0; osc1.adsrphase = 1; osc1.adsr = 1; osc1.decay = 100;
+    osc1.pitchbend = 0; osc1.bendrate = 0; osc1.maxbend = 0; osc1.sustain = 0; osc1.release = 0;
+
+    osc2.on = false; osc2.wave = 0; osc2.echo = 0; osc2.count = 0; osc2.cinc =0;
+    osc2.attack = 0; osc2.loop = 0; osc2.adsrphase = 1; osc2.adsr = 1; osc2.decay = 100;
+    osc2.pitchbend = 0; osc2.bendrate = 0; osc2.maxbend = 0; osc2.sustain = 0; osc2.release = 0;
+
+    osc3.on = false; osc3.wave = 0; osc3.echo = 0; osc3.count = 0; osc3.cinc =0;
+    osc3.attack = 0; osc3.loop = 0; osc3.adsrphase = 1; osc3.adsr = 1; osc3.decay = 100;
+    osc3.pitchbend = 0; osc3.bendrate = 0; osc3.maxbend = 0; osc3.sustain = 0; osc3.release = 0;
+}
+
+
+void testOsc(){
+    setOSC(&osc1,1,WTRI,1,0,1,25,127,10,10,20,2,0,0,0,0,0); // C3 = 25
+    setOSC(&osc2,1,WTRI,1,0,1,29-12,63,2,1,20,2,0,0,14,0,0); // E3 = 29
+    setOSC(&osc3,1,WSAW,1,0,1,25,15,30,30,20,2,-1,-1000,12,0,0); // G3 = 32
+}
+
+void playNote(uint8_t oscnum, uint8_t notenum, uint8_t i) {
+    OSC* o;
+    if (oscnum == 1) o = &osc1; else if (oscnum == 2) o = &osc2; else o = &osc3;
+    setOSC(o,1,patch[i].wave,patch[i].loop,patch[i].echo,patch[i].adsr,notenum,patch[i].vol,
+                          patch[i].attack,patch[i].decay,patch[i].sustain,patch[i].release,
+                          patch[i].maxbend,patch[i].bendrate,patch[i].arpmode,patch[i].overdrive,patch[i].kick);
+}
+
+void makeSampleInstruments() {
+    /* sample instruments for testing */
+    patch[0].wave = WSQUARE;
+    patch[0].on = 1;
+    patch[0].vol = 127;
+    patch[0].loop = 0;
+    patch[0].echo = 0;
+
+    patch[0].adsr = 0;
+    patch[0].attack = 0;
+    patch[0].decay = 0;
+    patch[0].sustain = 0;
+    patch[0].release = 0;
+
+    patch[0].maxbend = -1000;
+    patch[0].bendrate = 100;
+    patch[0].arpmode = 3;
+    patch[0].overdrive = 0;
+    patch[0].kick = 0;
+
+    patch[1].wave = WSAW;
+    patch[1].on = 1;
+    patch[1].vol = 200;
+    patch[1].loop = 0;
+    patch[1].echo = 0;
+
+    patch[1].adsr = 0;
+    patch[1].attack = 0;
+    patch[1].decay = 0;
+    patch[1].sustain = 0;
+    patch[1].release = 0;
+
+    patch[1].maxbend = 0;
+    patch[1].bendrate = 0;
+    patch[1].arpmode = 1;
+    patch[1].overdrive = 0;
+    patch[1].kick = 0;
+
+    patch[2].wave = WTRI;
+    patch[2].on = 1;
+    patch[2].vol = 127;
+    patch[2].loop = 0;
+    patch[2].echo = 0;
+
+    patch[2].adsr = 1;
+    patch[2].attack = 10;
+    patch[2].decay = 0;
+    patch[2].sustain = 0;
+    patch[2].release = 0;
+
+    patch[2].maxbend = 0;
+    patch[2].bendrate = 0;
+    patch[2].arpmode = 1;
+    patch[2].overdrive = 0;
+    patch[2].kick = 0;
+
+    patch[3].wave = WNOISE;
+    patch[3].on = 1;
+    patch[3].vol = 127;
+    patch[3].loop = 1;
+    patch[3].echo = 1;
+
+    patch[3].adsr = 1;
+    patch[3].attack = 0;
+    patch[3].decay = 30;
+    patch[3].sustain = 30;
+    patch[3].release = 5;
+
+    patch[3].maxbend = 0;
+    patch[3].bendrate = 0;
+    patch[3].arpmode = 0;
+    patch[3].overdrive = 0;
+    patch[3].kick = 0;
+
+    patch[4].wave = WPNOISE;
+    patch[4].on = 1;
+    patch[4].vol = 127;
+    patch[4].loop = 0;
+    patch[4].echo = 0;
+
+    patch[4].adsr = 1;
+    patch[4].attack = 0;
+    patch[4].decay = 30;
+    patch[4].sustain = 30;
+    patch[4].release = 5;
+
+    patch[4].maxbend = 0;
+    patch[4].bendrate = 0;
+    patch[4].arpmode = 1;
+    patch[4].overdrive = 0;
+    patch[4].kick = 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_song.h	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,50 @@
+/**************************************************************************/
+/*!
+    @file     Synth_song.h
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Pokitto development stage library
+    Software License Agreement
+
+    Copyright (c) 2015, Jonne Valola ("Author")
+    All rights reserved.
+
+    This library is intended solely for the purpose of Pokitto development.
+
+    Redistribution and use in source and binary forms, with or without
+    modification requires written permission from Author.
+*/
+/**************************************************************************/
+
+#ifndef SYNTH_SONG_H
+#define SYNTH_SONG_H
+
+#define CHUNKSIZE 8*3*2 // 48 bytes
+//extern uint8_t chunk1[], chunk2[];
+extern uint8_t chunk[2][CHUNKSIZE];
+extern uint8_t cc; // current chunk
+
+struct SONG {
+    byte rb_version; // rbtracker version with which the song was created
+    uint16_t song_bpm; // song beats per minute
+    byte num_patches; // how many different instruments ie patches
+    byte num_channels; // how many channels are used by this song (1-3)
+    byte num_patterns; // how many different patterns are used
+    byte song_end;  // at what position song ends
+    int8_t song_loop; // where to loop at end of song. -1 means no loop
+    byte block_sequence[3][10]; //the sequence of blocks for each track
+    const uint8_t * instrument_stream[3]; //pointers to the instruments in the track streams
+    const uint8_t * note_stream[3]; //pointers to the notes in the track streams
+};
+
+struct BLOCK {
+    uint8_t notenumber[64]; // was 64
+    uint8_t instrument[64]; // was 64
+};
+
+
+#endif // SYNTH_SONG_H
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_songfuncs.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,247 @@
+/**************************************************************************/
+/*!
+    @file     Synth_songfuncs.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "PokittoDisk.h"
+#include "Synth.h"
+#ifdef POK_SIM
+#include "FileIO.h"
+#endif
+
+/** SONG FUNCTIONS **/
+
+//uint8_t chunk1[CHUNKSIZE], chunk2[CHUNKSIZE]; // 8 rows, 3 channels (columns), 2 bytes per entry
+uint8_t chunk[2][CHUNKSIZE]; // 8 rows, 3 channels (columns), 2 bytes per entry
+uint8_t cc = 0;
+
+
+#if POK_ENABLE_SOUND > 0
+#if POK_ENABLE_SD > 0
+void updatePlaybackSD(uint8_t row) {
+    // samplespertick determines how long the oscillators are active before they are recalculated (i.e. the next tick
+    uint8_t i=0;
+
+    if (notetick > samplespertick ) {
+            // TRACK 1
+            //if (track1on) i = *song.instrument_stream[0];
+            i = 0xF;
+            if (track1on) i = chunk[cc][row+1]>>4;
+            if (i!=0xF) {
+                setOSC(&osc1,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
+                chunk[cc][row],patch[i].vol,
+                patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
+                patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
+                }
+            // TRACK 2
+            //if (track2on) i = *song.instrument_stream[1];
+            i = 0xF;
+            if (track2on) i = chunk[cc][row+3]>>4;
+            if (i!=0xF) {
+                setOSC(&osc2,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
+                chunk[cc][row+2],patch[i].vol,
+                patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
+                patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
+                }
+            // TRACK 3
+            i = 0xF;
+            if (track3on) i = chunk[cc][row+5]>>4;
+            if (i!=0xF) {
+                setOSC(&osc3,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
+                chunk[cc][row]+4,patch[i].vol,
+                patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
+                patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
+                }
+            playerpos++;
+            if (playerpos == PATTERNLENGTH) {
+                    // move to next song position
+                    playerpos = 0;
+                    /*sequencepos++;
+                    if (sequencepos > song.song_end) {
+                        if (song.song_loop == -1) {
+                            emptyOscillators();
+                            playing = false;
+                            sequencepos--;
+                        } else {
+                            sequencepos = song.song_loop;
+                        }
+                    }
+                    playerpos = 0;
+                    initStreams(sequencepos);
+                    tableRefresh=true;*/
+            }
+            notetick =0;
+            }
+}
+
+void updatePlayback() {
+    // samplespertick determines how long the oscillators are active before they are recalculated (i.e. the next tick
+    uint8_t i=0;
+
+    if (notetick > samplespertick ) {
+            // TRACK 1
+            if (track1on) i = *song.instrument_stream[0];
+            else i = 0;
+            if (i) {
+                setOSC(&osc1,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
+                *song.note_stream[0],patch[i].vol,
+                patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
+                patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
+                }
+            // TRACK 2
+            if (track2on) i = *song.instrument_stream[1];
+            else i = 0;
+            if (i) {
+                setOSC(&osc2,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
+                *song.note_stream[1],patch[i].vol,
+                patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
+                patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
+                }
+            // TRACK 3
+            if (track3on) i = *song.instrument_stream[2];
+            else i = 0;
+            if (i) {
+                setOSC(&osc3,1,patch[i].wave,patch[i].loop, patch[i].echo, patch[i].adsr,
+                *song.note_stream[2],patch[i].vol,
+                patch[i].attack, patch[i].decay, patch[i].sustain,patch[i].release,
+                patch[i].maxbend, patch[i].bendrate, patch[i].arpmode, patch[i].overdrive, patch[i].kick );
+                }
+            playerpos++;
+            song.instrument_stream[0]++;
+            song.note_stream[0]++;
+            song.instrument_stream[1]++;
+            song.note_stream[1]++;
+            song.instrument_stream[2]++;
+            song.note_stream[2]++;
+            if (playerpos == PATTERNLENGTH) {
+                    // move to next song position
+                    sequencepos++;
+                    if (sequencepos > song.song_end) {
+                        if (song.song_loop == -1) {
+                            emptyOscillators();
+                            playing = false;
+                            sequencepos--;
+                        } else {
+                            sequencepos = song.song_loop;
+                        }
+                    }
+                    playerpos = 0;
+                    initStreams(sequencepos);
+                    tableRefresh=true;
+            }
+            notetick =0;
+            }
+}
+
+void emptyPatches(){
+    for (int i=0; i<16; i++) {
+    patch[i].vol = 127;
+    patch[i].on = true; patch[i].wave = 1; patch[i].echo = 0; patch[i].count = 0; patch[i].cinc =0;
+    patch[i].attack = 0; patch[i].loop = 0; patch[i].adsrphase = 0; patch[i].adsr = 0; patch[i].decay = 20;
+    patch[i].pitchbend = 0; patch[i].bendrate = 0; patch[i].maxbend = 0; patch[i].sustain = 0; patch[i].release = 0, patch[i].overdrive = 0, patch[i].kick = 0;
+    }
+}
+
+void emptyBlocks(){
+    for (int i=0; i<MAXBLOCKS; i++) {
+            for (int j = 0; j < PATTERNLENGTH; j++) {
+                    block[i].instrument[j] = 0;
+                    block[i].notenumber[j] = 255;
+            }
+    }
+}
+
+void initStreams(uint8_t seqpos){
+    uint8_t blocknum;
+    // retarget pointers for track 1
+    // byte = pgm_read_byte(&(mydata[i][j]));
+    blocknum=song.block_sequence[0][seqpos];
+    //blocknum=pgm_read_byte(Song+SONG_SEQUENCE+seqpos);
+    song.instrument_stream[0]=&block[blocknum].instrument[0];
+    song.note_stream[0]=&block[blocknum].notenumber[0];
+    // retarget pointers for track 2
+    blocknum=song.block_sequence[1][seqpos];
+    song.instrument_stream[1]=&block[blocknum].instrument[0];
+    song.note_stream[1]=&block[blocknum].notenumber[0];
+    // retarget pointers for track 3
+    blocknum=song.block_sequence[2][seqpos];
+    song.instrument_stream[2]=&block[blocknum].instrument[0];
+    song.note_stream[2]=&block[blocknum].notenumber[0];
+}
+
+void emptySong(){
+    song.num_channels = 3;
+    song.num_patches = 1;
+    song.song_bpm = 120;
+    song.num_patterns = 1;
+    song.song_end = 0;
+    song.song_loop = 0; // loop back to start
+    song.rb_version = RBTRACKER_VERSION;
+    for (uint8_t i = 0; i<10; i++) {
+        song.block_sequence[0][i]=i*3; // track 1
+        song.block_sequence[1][i]=i*3+1; // track 2
+        song.block_sequence[2][i]=i*3+2; // track 3
+    }
+    song.instrument_stream[0] = &block[0].instrument[0];
+    song.note_stream[0] = &block[0].notenumber[0];
+    song.instrument_stream[1] = &block[1].instrument[0];
+    song.note_stream[1] = &block[1].notenumber[0];
+    song.instrument_stream[2] = &block[2].instrument[0];
+    song.note_stream[2] = &block[2].notenumber[0];
+    sequencepos = 0;
+}
+
+int openSongFromSD(char* buffer) {
+    if (!isThisFileOpen(buffer)) {
+        fileClose(); // close any open files
+        fileOpen(buffer,FILE_MODE_OVERWRITE | FILE_MODE_BINARY);
+    }
+    return isThisFileOpen(buffer);
+}
+
+void writeChunkToSD(uint8_t* buffer) {
+    if (fileOK()) {
+        fileWriteBytes(buffer, CHUNKSIZE);
+    }
+}
+
+void readChunkFromSD(uint8_t* buffer) {
+    if (fileOK()) {
+        fileReadBytes(buffer, CHUNKSIZE);
+    }
+}
+#endif
+#endif // POK_ENABLE_SOUND
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/POKITTO_LIBS/Synth/Synth_wavefuncs.cpp	Tue Jan 30 10:41:47 2018 +0000
@@ -0,0 +1,110 @@
+/**************************************************************************/
+/*!
+    @file     Synth_wavefuncs.cpp
+    @author   Jonne Valola
+
+    @section LICENSE
+
+    Software License Agreement (BSD License)
+
+    Copyright (c) 2016, Jonne Valola
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+    1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+    2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+    3. Neither the name of the copyright holders nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/**************************************************************************/
+
+#include "Synth.h"
+
+uint16_t noiseval, noiseval2;
+
+void waveoff(OSC* o); void sqwave(OSC* o); void sawwave(OSC* o); void triwave(OSC* o); void noise(OSC* o); void tonenoise(OSC* o); void sample(OSC* o);
+void noADSR(OSC* o); void attackFunc(OSC* o); void decayFunc(OSC* o); void releaseFunc(OSC* o);
+void mix1(); void mix2(); void mix3(); void updateEnvelopes();
+
+waveFunction Farr []  = {waveoff, sqwave, sawwave, triwave, noise, tonenoise};
+envFunction Earr [] = {noADSR, attackFunc, decayFunc, releaseFunc};
+mixFunction Marr [] = {updateEnvelopes,mix3,mix2,mix1}; // counts down
+mixFunction HWMarr [] = {updateEnvelopes,mix3,mix2,mix1}; // counts down
+
+/** SOUND FUNCTIONS **/
+
+void waveoff(OSC* o){
+  o->output = 0;
+}
+
+void sqwave(OSC* o){
+// square. If bit 16 set, its 2nd half of cycle and then output. if not, silence.
+ if (o->count & 0x80000000) o->output = 0;
+ else
+     o->output = 0xFFFF;
+}
+
+void sawwave(OSC* o){
+ // saw is just twice the count, so it happens 2 times in a cycle.
+ o->output = (o->count >>15);  //its now 32 bits (o->count << 1)>>4; // simple, eh ?
+}
+
+void triwave(OSC* o){
+    // exploit the fact that above 0x7FFF bit 16 will be set (ie. when on second side of cycle)
+    if (o->count & 0x80000000) o->output = (~o->count) >>15;// << 1; // counts down because complement goes other way
+    else o->output = o->count >>15; // now 32 bits ! << 1; // count up on first side of cycle
+}
+
+void noise(OSC* o){
+  // Standard libc random gives 10-12 fps
+  // Xorshift16 gives 32-39 fps
+  // Xorshift8 gives
+
+  if (o->count > 0x80000000) {
+    o->output = noiseval2;
+    //noiseval = random(0,0xFFFF);
+    noiseval = xorshift16();
+    //noiseval = xorshift8()*256;
+  }
+  else  {
+    o->output = noiseval;
+    //noiseval2 = random(0,0xFFFF);
+    noiseval2 = xorshift16();
+    //noiseval2 = xorshift8()*256;
+  }
+}
+
+void tonenoise(OSC* o){
+  // square. If bit 16 set, its 2nd half of cycle and then output. if not, silence.
+ if (o->count & 0x80000000) o->output = (xorshift16()>>6); //was 0
+ else  o->output = (xorshift16()>>1) + 0x4000;//random(0,0xFFFF);
+}
+
+void sample(OSC* o) {
+
+    /*if (o->samplepos > o->samplelength ) o->samplepos = 0;
+
+    if (o->count > o->wcycle) {
+        o->count=0;
+        if (o->output) o->output = 0;
+        //else o->output = o->output=pgm_read_byte((uint32_t)(sfxBike) + o->inccount);
+    }*/
+}
+
+