diff --git a/Firmware/oled/.cproject b/Firmware/oled/.cproject
new file mode 100644
index 0000000..d502f80
--- /dev/null
+++ b/Firmware/oled/.cproject
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Firmware/oled/.gitignore b/Firmware/oled/.gitignore
new file mode 100644
index 0000000..10d12cc
--- /dev/null
+++ b/Firmware/oled/.gitignore
@@ -0,0 +1,3 @@
+/oled
+*.o
+/.settings
diff --git a/Firmware/oled/.project b/Firmware/oled/.project
new file mode 100644
index 0000000..30df2b8
--- /dev/null
+++ b/Firmware/oled/.project
@@ -0,0 +1,27 @@
+
+
+ edison-oled
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/Firmware/oled/Makefile b/Firmware/oled/Makefile
new file mode 100644
index 0000000..841022b
--- /dev/null
+++ b/Firmware/oled/Makefile
@@ -0,0 +1,27 @@
+CPP=g++
+CPPFLAGS=-c -Wall -m32 -g
+LDFLAGS=-m32
+SOURCES=\
+ src/spi/spi_port_edison.cpp \
+ src/spi/spi_device_edison.cpp \
+ src/oled/Edison_OLED.cpp \
+ src/gpio/gpio_edison.cpp \
+# src/edison-oled.cpp \
+
+
+OBJECTS=$(SOURCES:.cpp=.o)
+EXECUTABLE=oled oled-input
+
+all: $(SOURCES) $(EXECUTABLE)
+
+oled: $(OBJECTS) src/edison-oled.o
+ $(CPP) $(LDFLAGS) $(OBJECTS) src/edison-oled.o -o $@
+
+oled-input: $(OBJECTS) src/input-oled.o
+ $(CPP) $(LDFLAGS) $(OBJECTS) src/input-oled.o -o $@
+
+.cpp.o:
+ $(CPP) $(CPPFLAGS) $< -o $@
+
+clean:
+ rm -rf $(EXECUTABLE) `find src -type f -name '*.o'`
diff --git a/Firmware/oled/oled.sh b/Firmware/oled/oled.sh
new file mode 100644
index 0000000..4b01280
--- /dev/null
+++ b/Firmware/oled/oled.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+function oled-menu () {
+ local SELECTION
+ local SCREEN_BUF
+ local OPTIONS
+ local CHOICE
+ local FROM
+ local MAXCHOICE
+ local index
+ local icount
+ local button
+
+ SELECTION="$1"
+ SCREEN_BUF="$2"
+ shift 2
+
+ if [[ $# -eq 0 ]]; then
+ return
+ fi
+
+ MAXCHOICE=0
+ OPTIONS=()
+ while [[ $# -gt 0 ]]; do
+ OPTIONS+=("$1")
+ shift
+ [[ $MAXCHOICE -lt 6 ]] && MAXCHOICE=$(( $MAXCHOICE + 1 ))
+ done
+
+ FROM=0
+ CHOICE=0
+ while true; do
+ icount=0
+ oled clear save "${SCREEN_BUF}"
+ for o in ${OPTIONS[@]:$FROM}; do
+ oled load "${SCREEN_BUF}" setCursor 6 $(( $icount * 8 )) print "$o" save "${SCREEN_BUF}"
+ icount=$(($icount + 1))
+ [[ $icount -eq 6 ]] && break
+ done
+ oled load "${SCREEN_BUF}" \
+ line 0 $(( $CHOICE * 8 + 1 )) 5 $(( $CHOICE * 8 + 3 )) \
+ line 0 $(( $CHOICE * 8 + 1 )) 0 $(( $CHOICE * 8 + 5 )) \
+ line 0 $(( $CHOICE * 8 + 5 )) 5 $(( $CHOICE * 8 + 3 )) \
+ display
+ for button in $(oled wait buttons); do
+ case $button in
+ U)
+ CHOICE=$(($CHOICE - 1))
+ [[ $CHOICE -eq -1 ]] && [[ $FROM -gt 0 ]] && FROM=$(( $FROM - 1 ))
+ [[ $CHOICE -eq -1 ]] && CHOICE=$(( $CHOICE + 1 ))
+ ;;
+ D)
+ CHOICE=$(($CHOICE + 1))
+ [[ $CHOICE -eq $MAXCHOICE ]] && [[ $FROM -lt $(( ${#OPTIONS[@]} - 6)) ]] && FROM=$(( FROM + 1 ))
+ [[ $CHOICE -eq $MAXCHOICE ]] && CHOICE=$(( $CHOICE - 1 ))
+ ;;
+ B)
+ rm "${SCREEN_BUF}"
+ oled clear display
+ return
+ ;;
+ A)
+ $SELECTION $(( $CHOICE + $FROM ))
+ ;;
+ esac
+ done
+ done
+}
diff --git a/Firmware/oled/src/edison-oled.cpp b/Firmware/oled/src/edison-oled.cpp
new file mode 100644
index 0000000..da63c10
--- /dev/null
+++ b/Firmware/oled/src/edison-oled.cpp
@@ -0,0 +1,151 @@
+//============================================================================
+// Name : edison-oled.cpp
+// Author : Robin Kirkman
+// Version :
+// Copyright : GPL
+// Description : Hello World in C, Ansi-style
+//============================================================================
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "oled/Edison_OLED.h"
+#include "gpio/gpio.h"
+
+// Define an edOLED object:
+edOLED oled;
+
+// Pin definitions:
+// All buttons have pull-up resistors on-board, so just declare
+// them as regular INPUT's
+gpio BUTTON_UP(47, INPUT);
+gpio BUTTON_DOWN(44, INPUT);
+gpio BUTTON_LEFT(165, INPUT);
+gpio BUTTON_RIGHT(45, INPUT);
+gpio BUTTON_SELECT(48, INPUT);
+gpio BUTTON_A(49, INPUT);
+gpio BUTTON_B(46, INPUT);
+
+void eval(char ***cmd);
+
+int main(int argc, char **argv) {
+ char **cmd = (char**) malloc(sizeof(char*) * argc);
+ memcpy(cmd, argv+1, sizeof(char*) * (argc - 1));
+ cmd[argc-1] = 0;
+
+ while(*cmd)
+ eval(&cmd);
+}
+
+#define NEXT(c) (*((*c)++))
+#define INEXT(c) (atoi(NEXT(c)))
+
+int buttons_value(void);
+
+void eval(char ***cmd) {
+ char *c = NEXT(cmd);
+ if(!strcmp("begin", c))
+ oled.begin();
+ else if(!strcmp("print", c))
+ oled.print(NEXT(cmd));
+ else if(!strcmp("clear", c))
+ oled.clear(PAGE);
+ else if(!strcmp("invert", c))
+ oled.invert(INEXT(cmd));
+ else if(!strcmp("display", c))
+ oled.display();
+ else if(!strcmp("setCursor", c)) {
+ int x = INEXT(cmd);
+ int y = INEXT(cmd);
+ oled.setCursor(x, y);
+ } else if(!strcmp("pixel", c)) {
+ int x = INEXT(cmd);
+ int y = INEXT(cmd);
+ oled.pixel(x, y);
+ } else if(!strcmp("line", c)) {
+ int x0 = INEXT(cmd);
+ int y0 = INEXT(cmd);
+ int x1 = INEXT(cmd);
+ int y1 = INEXT(cmd);
+ oled.line(x0, y0, x1, y1);
+ } else if(!strcmp("rect", c)) {
+ int x = INEXT(cmd);
+ int y = INEXT(cmd);
+ int width = INEXT(cmd);
+ int height = INEXT(cmd);
+ oled.rect(x, y, width, height);
+ } else if(!strcmp("rectFill", c)) {
+ int x = INEXT(cmd);
+ int y = INEXT(cmd);
+ int width = INEXT(cmd);
+ int height = INEXT(cmd);
+ oled.rectFill(x, y, width, height);
+ } else if(!strcmp("circle", c)) {
+ int x = INEXT(cmd);
+ int y = INEXT(cmd);
+ int radius = INEXT(cmd);
+ oled.circle(x, y, radius);
+ } else if(!strcmp("circleFill", c)) {
+ int x = INEXT(cmd);
+ int y = INEXT(cmd);
+ int radius = INEXT(cmd);
+ oled.circleFill(x, y, radius);
+ } else if(!strcmp("setColor", c))
+ oled.setColor(INEXT(cmd));
+ else if(!strcmp("setDrawMode", c))
+ oled.setDrawMode(INEXT(cmd));
+ else if(!strcmp("buttons", c)) {
+ if(!BUTTON_UP.pinRead())
+ printf("U ");
+ if(!BUTTON_DOWN.pinRead())
+ printf("D ");
+ if(!BUTTON_LEFT.pinRead())
+ printf("L ");
+ if(!BUTTON_RIGHT.pinRead())
+ printf("R ");
+ if(!BUTTON_SELECT.pinRead())
+ printf("S ");
+ if(!BUTTON_A.pinRead())
+ printf("A ");
+ if(!BUTTON_B.pinRead())
+ printf("B ");
+ printf("\n");
+ } else if(!strcmp("wait", c)) {
+ for(int bv = buttons_value(); bv == buttons_value();)
+ usleep(100000);
+ } else if(!strcmp("displayoff", c)) {
+ oled.command(DISPLAYOFF);
+ } else if(!strcmp("displayon", c)) {
+ oled.command(DISPLAYON);
+ } else if(!strcmp("save", c)) {
+ int fd = creat(NEXT(cmd), S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR);
+ if(fd != -1) {
+ write(fd, oled.screenmemory, 384);
+ close(fd);
+ }
+ } else if(!strcmp("load", c)) {
+ int fd = open(NEXT(cmd), O_RDONLY);
+ if(fd != -1) {
+ read(fd, oled.screenmemory, 384);
+ close(fd);
+ }
+ }
+}
+
+int buttons_value(void) {
+ int v = 0;
+ v |= BUTTON_UP.pinRead() << 0;
+ v |= BUTTON_DOWN.pinRead() << 1;
+ v |= BUTTON_LEFT.pinRead() << 2;
+ v |= BUTTON_RIGHT.pinRead() << 3;
+ v |= BUTTON_SELECT.pinRead() << 4;
+ v |= BUTTON_A.pinRead() << 5;
+ v |= BUTTON_B.pinRead() << 6;
+ return v;
+
+}
diff --git a/Firmware/oled/src/gpio/gpio.h b/Firmware/oled/src/gpio/gpio.h
new file mode 100644
index 0000000..f6822da
--- /dev/null
+++ b/Firmware/oled/src/gpio/gpio.h
@@ -0,0 +1,53 @@
+#ifndef __gpio_h__
+#define __gpio_h__
+
+/* Values that can be taken by a pin. LOW and HIGH are obvious, and NONE is
+ provided as a useful alternative that may never be used. */
+enum PIN_VALUE
+{
+ LOW,
+ HIGH,
+ NONE,
+};
+
+/* Pin modes. InPUT and OUTPUT should be nearly universal; the others may or
+ may not be needed depending on platform. On platforms where a particular
+ value isn't allowed, an exception will be thrown. */
+enum PIN_MODE
+{
+ INPUT,
+ OUTPUT,
+ INPUT_PU,
+ INPUT_PD,
+ SPI,
+ I2C,
+ PWM,
+ ADC,
+ UART,
+};
+
+/* This is the top-level class for a gpio pin. It should be suitable for all
+ platforms, since it provides the minimum needed for a GPIO pin. All
+ functions will throw exceptions defined in the sparklibs.h file. */
+class gpio
+{
+ public:
+ gpio(int pinID, PIN_MODE initMode, PIN_VALUE initVal=LOW);
+ ~gpio();
+ void pinMode(PIN_MODE newMode);
+ void pinWrite(PIN_VALUE newLevel);
+ PIN_VALUE pinRead();
+
+ private:
+ /* The gpioHelper is provided to provide a place to hide the
+ down-and-dirty implementation details that vary from one architecture
+ to the next; that way, this class doesn't need to provide functions
+ for, say, file IO which wouldn't get used in an environment without a
+ filesystem. */
+ class gpioHelper *helper;
+ int _pinNumber;
+ gpio();
+};
+
+#endif
+
diff --git a/Firmware/oled/src/gpio/gpio_edison.cpp b/Firmware/oled/src/gpio/gpio_edison.cpp
new file mode 100644
index 0000000..7369d62
--- /dev/null
+++ b/Firmware/oled/src/gpio/gpio_edison.cpp
@@ -0,0 +1,232 @@
+#include
+#include
+#include
+#include
+
+#include "gpio.h"
+#include "gpio_edison.h"
+#include "../sparklibs.h"
+
+// Class constructor. initVal can be omitted; defaults to LOW.
+gpio::gpio(int pinID, PIN_MODE initMode, PIN_VALUE initVal)
+{
+ /* We'll want to remember the pin number associated with this object, so we
+ can provide the user with useful information when we throw exceptions. */
+ this->_pinNumber = pinID;
+
+ char tBuffer[75];
+
+ /* GPIO functions are handled through accessing a resource in the filesystem.
+ It's possible that these resources may not exist; in that case, we'll
+ throw an exception, because creating a GPIO object with no resource to
+ back it up makes no sense. */
+
+ /* A few words here on the role of gpioHelper: since this library is
+ meant to be platform agnostic, we want to divorce the filesystem-related
+ elements of the GPIO from the main GPIO object. After all, not all of the
+ target architectures this will work for will have a filesystem! */
+ helper = new gpioHelper();
+
+ /* Create the path for the direction setting file and open it. This file
+ handles GPIO direction only. */
+ sprintf(tBuffer, GPIO_DIRECTION, pinID);
+ helper->_dirFileID = open(tBuffer, O_RDWR);
+
+ /* The mode file (aka pinmux) handles some weird internal logic on the Edison
+ which routes the various IO peripherals (SPI, PWM) to the physical pin on
+ the Edison connector. */
+ sprintf(tBuffer, GPIO_MODE, pinID);
+ helper->_modeFileID = open(tBuffer, O_RDWR);
+
+ // Same process for the "value" file, same caveat..
+ sprintf(tBuffer, GPIO_VALUE, pinID);
+ helper->_valueFileID = open(tBuffer, O_RDWR);
+
+ // And for pullmode.
+ sprintf(tBuffer, GPIO_PULLMODE, pinID);
+ helper->_pullmodeFileID = open(tBuffer, O_RDWR);
+
+ /* It's not hard to imagine a case where the user would pass a bogus pin ID,
+ so let's just make sure we handle that gracefully by throwing an
+ exception. */
+ if ((helper->_modeFileID == -1) ||
+ (helper->_dirFileID == -1) ||
+ (helper->_pullmodeFileID == -1) ||
+ (helper->_valueFileID == -1))
+ {
+ throw (GPIO_NO_PIN << 16) + pinID;
+ return;
+ }
+
+ // Write the initial value to the pin.
+ this->pinWrite(initVal);
+
+ // Write the initial mode to the pin.
+ this->pinMode(initMode);
+
+ // If we make it here without throwing any exceptions, we have a pin object!
+}
+
+// Destructor. Nothing special here.
+gpio::~gpio()
+{
+ close(helper->_modeFileID);
+ close(helper->_valueFileID);
+ close(helper->_dirFileID);
+ close(helper->_pullmodeFileID);
+ delete helper;
+}
+
+// Mode setting function. Throws exception GPIO_BAD_MODE if you pass it an
+// invalid mode value.
+void gpio::pinMode(PIN_MODE newMode)
+{
+ char tBuffer[10];
+ switch (newMode)
+ {
+ // For an input or output, we write to the direction file ("in" or "out"),
+ // and to the pinmux file ("mode0"). We can assume that this is valid for
+ // all possible pins.
+ case INPUT:
+ sprintf(tBuffer, "in");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode0");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "nopull");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ case OUTPUT:
+ sprintf(tBuffer, "out");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode0");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "nopull");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ case SPI:
+ // We need to make sure we're on a valid SPI pin; that's pins 109, 111,
+ // 114 and 115. Any other pin throws an exception. To activate SPI mode,
+ // we need to set pinmux to mode1.
+ switch (this->_pinNumber)
+ {
+ case 109: // SPI clock.
+ case 111: // SPI CS
+ case 115: // SPI MOSI
+ sprintf(tBuffer, "out");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode1");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "nopull");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ case 114: // SPI MISO
+ sprintf(tBuffer, "in");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode1");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "nopull");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ default:
+ throw (GPIO_BAD_MODE << 16) + this->_pinNumber;
+ return;
+ }
+ break;
+ case PWM:
+ // We need to make sure we're on a valid PWM pin; that's pins 12, 13, 182
+ // and 183, as PWM0-3 respectively. We're going to assume that the user
+ // took care of exporting the PWM pin elsewhere in their code (really,
+ // that just means that they created a PWMPin object); otherwise, they
+ // can set the pin to PWM mode but not really use it.
+ switch(this->_pinNumber)
+ {
+ case 12:
+ case 13:
+ case 182:
+ case 183:
+ sprintf(tBuffer, "out");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode1");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "nopull");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ default:
+ throw (GPIO_BAD_MODE << 16) + this->_pinNumber;
+ return;
+ }
+ break;
+ case INPUT_PU:
+ sprintf(tBuffer, "in");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode0");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "pullup");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ case INPUT_PD:
+ sprintf(tBuffer, "in");
+ helper->writeFile(helper->_dirFileID, tBuffer);
+ sprintf(tBuffer, "mode0");
+ helper->writeFile(helper->_modeFileID, tBuffer);
+ sprintf(tBuffer, "pulldown");
+ helper->writeFile(helper->_pullmodeFileID, tBuffer);
+ break;
+ case I2C:
+ case UART:
+ case ADC:
+ default:
+ throw (GPIO_BAD_MODE<<16) + this->_pinNumber;
+ return;
+ }
+}
+
+// Pin value write function. Throws exception GPIO_BAD_VALUE if you pass it a
+// bad level value.
+void gpio::pinWrite(PIN_VALUE newLevel)
+{
+ char tBuffer[5];
+ // Writing to /sys/class/gpio#/value, we'd write '1' or '0'. To the debug
+ // file, we write 'low' or 'high'.
+ if (newLevel == LOW)
+ {
+ sprintf(tBuffer, "low");
+ }
+ else if (newLevel == HIGH)
+ {
+ sprintf(tBuffer, "high");
+ }
+ else
+ {
+ throw (GPIO_BAD_VALUE<<16) + _pinNumber;
+ return;
+ }
+
+ helper->writeFile(helper->_valueFileID, tBuffer);
+}
+
+PIN_VALUE gpio::pinRead()
+{
+ lseek(helper->_valueFileID, 0, SEEK_SET);
+ char buffer[4];
+ read(helper->_valueFileID, &buffer, 4);
+ if (buffer[0] == 'h')
+ {
+ return HIGH;
+ }
+ else
+ {
+ //printf("IT'S LOW\n\r");
+ return LOW;
+ }
+}
+
+// writeFile() is made a function so we don't need to explicitly do the lseek()
+// to get to the top of the file before every write. It feels derpy to me that
+// a file like this needs you to seek to the top, but there it is.
+void gpioHelper::writeFile(int fileID, const char *buffer)
+{
+ lseek(fileID, 0, SEEK_SET); // Make sure we're at the top of the file!
+ write(fileID, buffer, strlen(buffer));
+}
+
diff --git a/Firmware/oled/src/gpio/gpio_edison.h b/Firmware/oled/src/gpio/gpio_edison.h
new file mode 100644
index 0000000..015988e
--- /dev/null
+++ b/Firmware/oled/src/gpio/gpio_edison.h
@@ -0,0 +1,54 @@
+#ifndef __gpio_edison_h__
+#define __gpio_edison_h__
+
+// gpioHelper is defined independently in a platform-specific file, and
+// abstracts the nitty-gritty details of how a GPIO pin is actually accessed
+// for a given platform. Sometimes it'll be via file descriptors, other
+// times, it'll be via register access.
+
+// In the Edison, GPIO pins can be multiplexed to different functions. While
+// *can* access them via the /sys/class/gpio route, it's more useful (although
+// more verbose) to go through /sys/kernel/debug/gpio_debug.
+
+// One of the main reasons for using the debug route is that the Edison has some
+// internal muxing going on that you need to adjust to enable alternate
+// functions on the GPIO pins (things like PWM and SPI, for instance).
+
+// This directory contains *all* valid native GPIO pins. Pins provided via the
+// I/O expanders are not in this folder, however; to access them, you'll need
+// to go through the /sys/class/gpio/ interface.
+#define GPIO_ROOT "/sys/kernel/debug/gpio_debug/"
+
+// Each GPIO has a directory associated with it. Each directory has a number of
+// super useful files inside. These strings link to those files.
+
+// This file is read/write for current value of the pin. Write a string of "low"
+// or "high" to it, or read it to get "low" or "high" back.
+#define GPIO_VALUE GPIO_ROOT "gpio%u/current_value"
+
+// Current pin direction. This is *only* for input/output mode: more advanced
+// modes, like I2C et al, are set via the next file, current_pinmux.
+#define GPIO_DIRECTION GPIO_ROOT "gpio%u/current_direction"
+
+// Current pin mux mode. There are, generally, 8 modes, denoted by strings
+// "mode0", etc. "mode0" indicates GPIO mode; others are something else and
+// we'll cover that in appropriate places.
+#define GPIO_MODE GPIO_ROOT "gpio%u/current_pinmux"
+
+// If we want to have a pullup or pulldown on the pin, we need to write
+// "pullup" or "pulldown" to this file.
+#define GPIO_PULLMODE GPIO_ROOT "gpio%u/current_pullmode"
+
+class gpioHelper
+{
+ friend class gpio;
+ private:
+ int _valueFileID;
+ int _modeFileID;
+ int _dirFileID;
+ int _pullmodeFileID;
+ void writeFile(int fileID, const char *value);
+};
+
+#endif
+
diff --git a/Firmware/oled/src/input-oled.cpp b/Firmware/oled/src/input-oled.cpp
new file mode 100644
index 0000000..ae80896
--- /dev/null
+++ b/Firmware/oled/src/input-oled.cpp
@@ -0,0 +1,189 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "oled/Edison_OLED.h"
+#include "gpio/gpio.h"
+
+// Define an edOLED object:
+edOLED oled;
+
+// Pin definitions:
+// All buttons have pull-up resistors on-board, so just declare
+// them as regular INPUT's
+gpio BUTTON_UP(47, INPUT);
+gpio BUTTON_DOWN(44, INPUT);
+gpio BUTTON_LEFT(165, INPUT);
+gpio BUTTON_RIGHT(45, INPUT);
+gpio BUTTON_SELECT(48, INPUT);
+gpio BUTTON_A(49, INPUT);
+gpio BUTTON_B(46, INPUT);
+
+#define UP_MASK 1
+#define DOWN_MASK 2
+#define LEFT_MASK 4
+#define RIGHT_MASK 8
+#define SELECT_MASK 16
+#define A_MASK 32
+#define B_MASK 64
+
+#define FIELD_SIZE 95
+
+char field[FIELD_SIZE];
+
+void init_field() {
+ int i = 0;
+ for (char c = 'a'; c <= 'z'; c++)
+ field[i++] = c;
+ for (char c = '0'; c <= '9'; c++)
+ field[i++] = c;
+ for (char c = 'A'; c <= 'Z'; c++)
+ field[i++] = c;
+ for (char c = 32; c <=47; c++)
+ field[i++] = c;
+ for (char c = 58; c <= 64; c++)
+ field[i++] = c;
+ for (char c = 91; c <= 96; c++)
+ field[i++] = c;
+ for (char c = 123; c <= 126; c++)
+ field[i++] = c;
+}
+
+
+void draw_field(int n, int row, const char *text) {
+ int ul = 9 * row, lr = 9 * (row + 4) + 9 - 1;
+ int x, y;
+
+ oled.setColor(BLACK);
+ oled.rectFill(0, 8, 64, 40);
+
+ oled.setColor(WHITE);
+
+ char buf[] = {0,0};
+ for (int i = ul; i <= lr && i < FIELD_SIZE; i++) {
+ if (i == n)
+ continue;
+ x = 7 * (i % 9);
+ y = 8 + 8 * ((i / 9) - row);
+ if (i == n) {
+ oled.rectFill(x, y, 7, 9);
+ oled.setColor(BLACK);
+ }
+ oled.setCursor(x+1, y);
+ buf[0] = field[i];
+ oled.print(buf);
+ if (i == n)
+ oled.setColor(WHITE);
+ }
+ x = 7 * (n % 9);
+ y = 8 + 8 * ((n / 9) - row);
+ oled.rectFill(x, y, 7, 9);
+ oled.setColor(BLACK);
+ oled.setCursor(x+1, y);
+ buf[0] = field[n];
+ oled.print(buf);
+
+ oled.rectFill(0, 0, 64, 8);
+ if (strlen(text) > 10)
+ text += strlen(text) - 10;
+ oled.setColor(WHITE);
+ oled.setCursor(2, 0);
+ oled.print(text + (strlen(text) > 10 ? strlen(text) - 10 : 0));
+
+ oled.display();
+
+
+}
+
+int pressed() {
+ int mask = 0;
+ if (BUTTON_UP.pinRead() == LOW)
+ mask |= UP_MASK;
+ if (BUTTON_DOWN.pinRead() == LOW)
+ mask |= DOWN_MASK;
+ if (BUTTON_LEFT.pinRead() == LOW)
+ mask |= LEFT_MASK;
+ if (BUTTON_RIGHT.pinRead() == LOW)
+ mask |= RIGHT_MASK;
+ if (BUTTON_SELECT.pinRead() == LOW)
+ mask |= SELECT_MASK;
+ if (BUTTON_A.pinRead() == LOW)
+ mask |= A_MASK;
+ if (BUTTON_B.pinRead() == LOW)
+ mask |= B_MASK;
+ return mask;
+}
+
+int main(int argc, char **argv) {
+ init_field();
+
+ oled.begin();
+
+ int n = 0;
+ int row = 0;
+
+ draw_field(n, row, "");
+
+ int sleeps = 0;
+ int q = 0;
+
+ char text[256];
+ memset(text, 0, 256);
+ int pos = 0;
+
+ for (int p = pressed(); p != SELECT_MASK; p = pressed()) {
+ while (q == p && sleeps < 500) {
+ usleep(1000);
+ p = pressed();
+ sleeps++;
+ }
+ if (q != p)
+ sleeps = 0;
+ switch(p) {
+ case UP_MASK:
+ if (n >= 9)
+ n -= 9;
+ break;
+ case DOWN_MASK:
+ if (n < FIELD_SIZE - 9)
+ n += 9;
+ break;
+ case LEFT_MASK:
+ if (n >= 1)
+ n -= 1;
+ break;
+ case RIGHT_MASK:
+ if (n < FIELD_SIZE - 1)
+ n += 1;
+ break;
+ case A_MASK:
+ if (pos < 255)
+ text[pos++] = field[n];
+ break;
+ case B_MASK:
+ if (pos > 0)
+ text[--pos] = 0;
+ break;
+ default:
+ q = p;
+ usleep(100);
+ continue;
+ }
+ if (row > n / 9)
+ row -= 1;
+ if (row + 4 < n/9)
+ row += 1;
+ draw_field(n, row, text);
+ q = p;
+ }
+
+ oled.setColor(BLACK);
+ oled.rectFill(0, 0, 64, 48);
+ oled.display();
+
+ printf("%s", text);
+}
diff --git a/Firmware/oled/src/oled/Edison_OLED.cpp b/Firmware/oled/src/oled/Edison_OLED.cpp
new file mode 100644
index 0000000..bff4bd0
--- /dev/null
+++ b/Firmware/oled/src/oled/Edison_OLED.cpp
@@ -0,0 +1,908 @@
+/******************************************************************************
+ Edison_OLED.cpp
+ Main source code for the Edison OLED Block C++ Library
+
+ Jim Lindblom @ SparkFun Electronics
+ January 8, 2014
+ https://github.com/sparkfun/Edison_OLED_Block/tree/master/Firmware/
+
+ This file defines the hardware interface for the Edison OLED Block
+
+ This code was heavily based around the MicroView library, written by GeekAmmo
+ (https://github.com/geekammo/MicroView-Arduino-Library), and released under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+******************************************************************************/
+#include "Edison_OLED.h"
+#include "../spi/spi.h"
+#include "../gpio/gpio.h"
+#include "edison_fonts.h" // External file to store font bit-map arrays
+#include
+#include // for memset
+#include // for sprintf
+#include // for usleep
+
+// Change the total fonts included
+#define TOTALFONTS 4
+#define recvLEN 100
+char serInStr[recvLEN];
+unsigned char serCmd[recvLEN];
+
+// Add the font name as declared in the header file
+const unsigned char *edOLED::fontsPointer[]={
+ font5x7
+ ,font8x16
+ ,sevensegment
+ ,fontlargenumber
+};
+
+
+
+// Pin definitions:
+gpio CS_PIN(111, OUTPUT, HIGH);
+gpio RST_PIN(15, OUTPUT, HIGH);
+gpio DC_PIN(14, OUTPUT, HIGH);
+gpio SCLK_PIN(109, SPI, HIGH);
+gpio MOSI_PIN(115, SPI, HIGH);
+
+// SPI set up:
+spiPort *spi5 = new spiPort();
+//spiDevice oledSPI(spi5);
+spiDevice oledSPI(spi5, SPI_MODE_0, 10000000, false, &CS_PIN);
+#define pgm_read_byte(x) (*(x))
+
+edOLED::edOLED()
+{
+ // default 5x7 font
+ setFontType(0);
+ setColor(WHITE);
+ setDrawMode(NORM);
+ setCursor(0,0);
+
+ spiSetup();
+
+
+}
+
+/** \brief Initialization of edOLED Library.
+
+ Setup IO pins for SPI port then send initialization commands to the
+ SSD1306 controller inside the OLED.
+*/
+void edOLED::begin()
+{
+ RST_PIN.pinWrite(HIGH); //(digitalWrite(rstPin, HIGH);
+ usleep(5000); // VDD (3.3V) goes high at start, lets just chill for 5 ms
+ RST_PIN.pinWrite(LOW); // bring reset low
+ usleep(10000); // wait 10ms
+ RST_PIN.pinWrite(HIGH); //digitalWrite(rstPin, HIGH);
+
+ // Init sequence for 64x48 OLED module
+ command(DISPLAYOFF); // 0xAE
+
+ command(SETDISPLAYCLOCKDIV); // 0xD5
+ command(0x80); // the suggested ratio 0x80
+
+ command(SETMULTIPLEX); // 0xA8
+ command(0x2F);
+
+ command(SETDISPLAYOFFSET); // 0xD3
+ command(0x0); // no offset
+
+ command(SETSTARTLINE | 0x0); // line #0
+
+ command(CHARGEPUMP); // enable charge pump
+ command(0x14);
+
+ command(NORMALDISPLAY); // 0xA6
+ command(DISPLAYALLONRESUME); // 0xA4
+
+ command(SEGREMAP | 0x1);
+ command(COMSCANDEC);
+
+ command(SETCOMPINS); // 0xDA
+ command(0x12);
+
+ command(SETCONTRAST); // 0x81
+ command(0x8F);
+
+ command(SETPRECHARGE); // 0xd9
+ command(0xF1);
+
+ command(SETVCOMDESELECT); // 0xDB
+ command(0x40);
+
+ command(DISPLAYON); //--turn on oled panel
+}
+
+/** \brief SPI command.
+
+ Setup DC and SS pins, then send command via SPI to SSD1306 controller.
+*/
+void edOLED::command(unsigned char c)
+{
+ DC_PIN.pinWrite(LOW); // DC pin LOW
+ spiTransfer(c);
+}
+
+/** \brief SPI data.
+
+ Setup DC and SS pins, then send data via SPI to SSD1306 controller.
+*/
+void edOLED::data(unsigned char c)
+{
+ DC_PIN.pinWrite(HIGH); // DC HIGH
+ spiTransfer(c);
+}
+
+/** \brief Set SSD1306 page address.
+
+ Send page address command and address to the SSD1306 OLED controller.
+*/
+void edOLED::setPageAddress(unsigned char add)
+{
+ add=0xb0|add;
+ command(add);
+ return;
+}
+
+/** \brief Set SSD1306 column address.
+
+ Send column address command and address to the SSD1306 OLED controller.
+*/
+void edOLED::setColumnAddress(unsigned char add)
+{
+ command((0x10|(add>>4))+0x02);
+ command((0x0f&add));
+ return;
+}
+
+/** \brief Clear screen buffer or SSD1306's memory.
+
+ To clear GDRAM inside the LCD controller, pass in the variable mode =
+ ALL and to clear screen page buffer pass in the variable mode = PAGE.
+*/
+void edOLED::clear(unsigned char mode)
+{
+ // unsigned char page=6, col=0x40;
+ if (mode==ALL)
+ {
+ for (int i=0;i<8; i++)
+ {
+ setPageAddress(i);
+ setColumnAddress(0);
+ for (int j=0; j<0x80; j++)
+ {
+ data(0);
+ }
+ }
+ }
+ else
+ {
+ memset(screenmemory,0,384); // (64 x 48) / 8 = 384
+ }
+}
+
+/** \brief Clear or replace screen buffer or SSD1306's memory with a character.
+
+ To clear GDRAM inside the LCD controller, pass in the variable mode = ALL
+ with c character and to clear screen page buffer, pass in the variable
+ mode = PAGE with c character.
+*/
+void edOLED::clear(unsigned char mode, unsigned char c)
+{
+ //unsigned char page=6, col=0x40;
+ if (mode==ALL)
+ {
+ for (int i=0;i<8; i++)
+ {
+ setPageAddress(i);
+ setColumnAddress(0);
+ for (int j=0; j<0x80; j++)
+ {
+ data(c);
+ }
+ }
+ }
+ else
+ {
+ memset(screenmemory,c,384); // (64 x 48) / 8 = 384
+ display();
+ }
+}
+
+/** \brief Invert display.
+
+ The WHITE color of the display will turn to BLACK and the BLACK will turn
+ to WHITE.
+*/
+void edOLED::invert(unsigned char inv)
+{
+ if (inv)
+ command(INVERTDISPLAY);
+ else
+ command(NORMALDISPLAY);
+}
+
+/** \brief Set contrast.
+
+ OLED contract value from 0 to 255. Note: Contrast level is not very obvious.
+*/
+void edOLED::contrast(unsigned char contrast)
+{
+ command(SETCONTRAST); // 0x81
+ command(contrast);
+}
+
+/** \brief Transfer display memory.
+
+ Bulk move the screen buffer to the SSD1306 controller's memory so that images/graphics drawn on the screen buffer will be displayed on the OLED.
+*/
+void edOLED::display(void)
+{
+ unsigned char i, j;
+
+ for (i=0; i<6; i++)
+ {
+ setPageAddress(i);
+ setColumnAddress(0);
+ for (j=0;j<0x40;j++)
+ {
+ data(screenmemory[i*0x40+j]);
+ }
+ }
+}
+
+/** \brief write a character to the display
+
+*/
+unsigned char edOLED::write(unsigned char c)
+{
+ if (c == '\n')
+ {
+ cursorY += fontHeight;
+ cursorX = 0;
+ }
+ else if (c == '\r')
+ {
+ // skip
+ }
+ else
+ {
+ drawChar(cursorX, cursorY, c, foreColor, drawMode);
+ cursorX += fontWidth+1;
+ if ((cursorX > (LCDWIDTH - fontWidth)))
+ {
+ cursorY += fontHeight;
+ cursorX = 0;
+ }
+ }
+
+ return 1;
+}
+
+
+void edOLED::print(const char * c)
+{
+ int len = strlen(c);
+
+ for (int i=0; i=LCDWIDTH) || (y<0) || (y>=LCDHEIGHT))
+ return;
+
+ if (mode==XOR)
+ {
+ if (color==WHITE)
+ screenmemory[x+ (y/8)*LCDWIDTH] ^= (1<<(y%8));
+ }
+ else
+ {
+ if (color==WHITE)
+ screenmemory[x+ (y/8)*LCDWIDTH] |= (1<<(y%8));
+ else
+ screenmemory[x+ (y/8)*LCDWIDTH] &= ~(1<<(y%8));
+ }
+}
+
+/** \brief Draw line.
+
+ Draw line using current fore color and current draw mode from x0,y0 to x1,y1 of the screen buffer.
+*/
+void edOLED::line(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1)
+{
+ line(x0,y0,x1,y1,foreColor,drawMode);
+}
+
+/** \brief Draw line with color and mode.
+
+ Draw line using color and mode from x0,y0 to x1,y1 of the screen buffer.
+*/
+void edOLED::line(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char color, unsigned char mode)
+{
+ unsigned char steep = abs(y1 - y0) > abs(x1 - x0);
+ if (steep)
+ {
+ swapOLED(x0, y0);
+ swapOLED(x1, y1);
+ }
+
+ if (x0 > x1)
+ {
+ swapOLED(x0, x1);
+ swapOLED(y0, y1);
+ }
+
+ unsigned char dx, dy;
+ dx = x1 - x0;
+ dy = abs(y1 - y0);
+
+ int8_t err = dx / 2;
+ int8_t ystep;
+
+ if (y0 < y1)
+ {
+ ystep = 1;
+ }
+ else
+ {
+ ystep = -1;
+ }
+
+ for (; x0= 0)
+ {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ pixel(x0 + x, y0 + y, color, mode);
+ pixel(x0 - x, y0 + y, color, mode);
+ pixel(x0 + x, y0 - y, color, mode);
+ pixel(x0 - x, y0 - y, color, mode);
+
+ pixel(x0 + y, y0 + x, color, mode);
+ pixel(x0 - y, y0 + x, color, mode);
+ pixel(x0 + y, y0 - x, color, mode);
+ pixel(x0 - y, y0 - x, color, mode);
+
+ }
+}
+
+/** \brief Draw filled circle.
+
+ Draw filled circle with radius using current fore color and current draw mode at x,y of the screen buffer.
+*/
+void edOLED::circleFill(unsigned char x0, unsigned char y0, unsigned char radius)
+{
+ circleFill(x0,y0,radius,foreColor,drawMode);
+}
+
+/** \brief Draw filled circle with color and mode.
+
+ Draw filled circle with radius using color and mode at x,y of the screen buffer.
+*/
+void edOLED::circleFill(unsigned char x0, unsigned char y0, unsigned char radius, unsigned char color, unsigned char mode)
+{
+ int8_t f = 1 - radius;
+ int8_t ddF_x = 1;
+ int8_t ddF_y = -2 * radius;
+ int8_t x = 0;
+ int8_t y = radius;
+
+ // Temporary disable fill circle for XOR mode.
+ if (mode==XOR) return;
+
+ for (unsigned char i=y0-radius; i<=y0+radius; i++)
+ {
+ pixel(x0, i, color, mode);
+ }
+
+ while (x= 0)
+ {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ for (unsigned char i=y0-y; i<=y0+y; i++)
+ {
+ pixel(x0+x, i, color, mode);
+ pixel(x0-x, i, color, mode);
+ }
+ for (unsigned char i=y0-x; i<=y0+x; i++)
+ {
+ pixel(x0+y, i, color, mode);
+ pixel(x0-y, i, color, mode);
+ }
+ }
+}
+
+/** \brief Get LCD height.
+
+ The height of the LCD return as unsigned char.
+*/
+unsigned char edOLED::getLCDHeight(void)
+{
+ return LCDHEIGHT;
+}
+
+/** \brief Get LCD width.
+
+ The width of the LCD return as unsigned char.
+*/
+unsigned char edOLED::getLCDWidth(void)
+{
+ return LCDWIDTH;
+}
+
+/** \brief Get font width.
+
+ The cucrrent font's width return as unsigned char.
+*/
+unsigned char edOLED::getFontWidth(void)
+{
+ return fontWidth;
+}
+
+/** \brief Get font height.
+
+ The current font's height return as unsigned char.
+*/
+unsigned char edOLED::getFontHeight(void)
+{
+ return fontHeight;
+}
+
+/** \brief Get font starting character.
+
+ Return the starting ASCII character of the currnet font, not all fonts start with ASCII character 0. Custom fonts can start from any ASCII character.
+*/
+unsigned char edOLED::getFontStartChar(void)
+{
+ return fontStartChar;
+}
+
+/** \brief Get font total characters.
+
+ Return the total characters of the current font.
+*/
+unsigned char edOLED::getFontTotalChar(void)
+{
+ return fontTotalChar;
+}
+
+/** \brief Get total fonts.
+
+ Return the total number of fonts loaded into the edOLED's flash memory.
+*/
+unsigned char edOLED::getTotalFonts(void)
+{
+ return TOTALFONTS;
+}
+
+/** \brief Get font type.
+
+ Return the font type number of the current font.
+*/
+unsigned char edOLED::getFontType(void)
+{
+ return fontType;
+}
+
+/** \brief Set font type.
+
+ Set the current font type number, ie changing to different fonts base on the type provided.
+*/
+unsigned char edOLED::setFontType(unsigned char type)
+{
+ if ((type>=TOTALFONTS) || (type<0))
+ return false;
+
+ fontType=type;
+ fontWidth=pgm_read_byte(fontsPointer[fontType]+0);
+ fontHeight=pgm_read_byte(fontsPointer[fontType]+1);
+ fontStartChar=pgm_read_byte(fontsPointer[fontType]+2);
+ fontTotalChar=pgm_read_byte(fontsPointer[fontType]+3);
+ fontMapWidth=(pgm_read_byte(fontsPointer[fontType]+4)*100)+pgm_read_byte(fontsPointer[fontType]+5); // two unsigned chars values into integer 16
+ return true;
+}
+
+/** \brief Set color.
+
+ Set the current draw's color. Only WHITE and BLACK available.
+*/
+void edOLED::setColor(unsigned char color)
+{
+ foreColor=color;
+}
+
+/** \brief Set draw mode.
+
+ Set current draw mode with NORM or XOR.
+*/
+void edOLED::setDrawMode(unsigned char mode)
+{
+ drawMode=mode;
+}
+
+/** \brief Draw character.
+
+ Draw character c using current color and current draw mode at x,y.
+*/
+void edOLED::drawChar(unsigned char x, unsigned char y, unsigned char c)
+{
+ drawChar(x,y,c,foreColor,drawMode);
+}
+
+/** \brief Draw character with color and mode.
+
+ Draw character c using color and draw mode at x,y.
+*/
+void edOLED::drawChar(unsigned char x, unsigned char y, unsigned char c, unsigned char color, unsigned char mode)
+{
+ unsigned char rowsToDraw,row, tempC;
+ unsigned char i,j,temp;
+ unsigned int charPerBitmapRow,charColPositionOnBitmap,charRowPositionOnBitmap,charBitmapStartPosition;
+
+ if ((c(fontStartChar+fontTotalChar-1))) // no bitmap for the required c
+ return;
+
+ tempC=c-fontStartChar;
+
+ // each row (in datasheet is call page) is 8 bits high, 16 bit high character will have 2 rows to be drawn
+ rowsToDraw=fontHeight/8; // 8 is LCD's page size, see SSD1306 datasheet
+ if (rowsToDraw<=1) rowsToDraw=1;
+
+ // the following draw function can draw anywhere on the screen, but SLOW pixel by pixel draw
+ if (rowsToDraw==1)
+ {
+ for (i=0;i>=1;
+ }
+ }
+ return;
+ }
+
+ // font height over 8 bit
+ // take character "0" ASCII 48 as example
+ charPerBitmapRow=fontMapWidth/fontWidth; // 256/8 =32 char per row
+ charColPositionOnBitmap=tempC % charPerBitmapRow; // =16
+ charRowPositionOnBitmap=int(tempC/charPerBitmapRow); // =1
+ charBitmapStartPosition=(charRowPositionOnBitmap * fontMapWidth * (fontHeight/8)) + (charColPositionOnBitmap * fontWidth) ;
+
+ // each row on LCD is 8 bit height (see datasheet for explanation)
+ for(row=0;row>=1;
+ }
+ }
+ }
+
+}
+
+/** \brief Stop scrolling.
+
+ Stop the scrolling of graphics on the OLED.
+*/
+void edOLED::scrollStop(void)
+{
+ command(DEACTIVATESCROLL);
+}
+
+/** \brief Right scrolling.
+
+ Set row start to row stop on the OLED to scroll right. Refer to http://learn.edOLED.io/intro/general-overview-of-edOLED.html for explanation of the rows.
+*/
+void edOLED::scrollRight(unsigned char start, unsigned char stop)
+{
+ if (stop=0; i--)
+ {
+ if (data & (1<.
+******************************************************************************/
+
+#ifndef EDISON_OLED_H
+#define EDISON_OLED_H
+
+#define swapOLED(a, b) { unsigned char t = a; a = b; b = t; }
+
+#define BLACK 0
+#define WHITE 1
+
+#define LCDWIDTH 64
+#define LCDHEIGHT 48
+#define FONTHEADERSIZE 6
+
+#define NORM 0
+#define XOR 1
+
+#define PAGE 0
+#define ALL 1
+
+#define SETCONTRAST 0x81
+#define DISPLAYALLONRESUME 0xA4
+#define DISPLAYALLON 0xA5
+#define NORMALDISPLAY 0xA6
+#define INVERTDISPLAY 0xA7
+#define DISPLAYOFF 0xAE
+#define DISPLAYON 0xAF
+#define SETDISPLAYOFFSET 0xD3
+#define SETCOMPINS 0xDA
+#define SETVCOMDESELECT 0xDB
+#define SETDISPLAYCLOCKDIV 0xD5
+#define SETPRECHARGE 0xD9
+#define SETMULTIPLEX 0xA8
+#define SETLOWCOLUMN 0x00
+#define SETHIGHCOLUMN 0x10
+#define SETSTARTLINE 0x40
+#define MEMORYMODE 0x20
+#define COMSCANINC 0xC0
+#define COMSCANDEC 0xC8
+#define SEGREMAP 0xA0
+#define CHARGEPUMP 0x8D
+#define EXTERNALVCC 0x01
+#define SWITCHCAPVCC 0x02
+
+// Scroll
+#define ACTIVATESCROLL 0x2F
+#define DEACTIVATESCROLL 0x2E
+#define SETVERTICALSCROLLAREA 0xA3
+#define RIGHTHORIZONTALSCROLL 0x26
+#define LEFT_HORIZONTALSCROLL 0x27
+#define VERTICALRIGHTHORIZONTALSCROLL 0x29
+#define VERTICALLEFTHORIZONTALSCROLL 0x2A
+
+typedef enum CMD {
+ CMD_CLEAR, //0
+ CMD_INVERT, //1
+ CMD_CONTRAST, //2
+ CMD_DISPLAY, //3
+ CMD_SETCURSOR, //4
+ CMD_PIXEL, //5
+ CMD_LINE, //6
+ CMD_LINEH, //7
+ CMD_LINEV, //8
+ CMD_RECT, //9
+ CMD_RECTFILL, //10
+ CMD_CIRCLE, //11
+ CMD_CIRCLEFILL, //12
+ CMD_DRAWCHAR, //13
+ CMD_DRAWBITMAP, //14
+ CMD_GETLCDWIDTH, //15
+ CMD_GETLCDHEIGHT, //16
+ CMD_SETCOLOR, //17
+ CMD_SETDRAWMODE //18
+} commCommand_t;
+
+class edOLED {
+public:
+ edOLED();
+
+ void begin(void);
+
+ unsigned char write(unsigned char);
+ void print(const char * c);
+ void print(int d);
+ void print(float f);
+
+ // RAW LCD functions
+ void command(unsigned char c);
+ void data(unsigned char c);
+ void setColumnAddress(unsigned char add);
+ void setPageAddress(unsigned char add);
+
+ // LCD Draw functions
+ void clear(unsigned char mode);
+ void clear(unsigned char mode, unsigned char c);
+ void invert(unsigned char inv);
+ void contrast(unsigned char contrast);
+ void display(void);
+ void setCursor(unsigned char x, unsigned char y);
+ void pixel(unsigned char x, unsigned char y);
+ void pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char mode);
+ void line(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1);
+ void line(unsigned char x0, unsigned char y0, unsigned char x1, unsigned char y1, unsigned char color, unsigned char mode);
+ void lineH(unsigned char x, unsigned char y, unsigned char width);
+ void lineH(unsigned char x, unsigned char y, unsigned char width, unsigned char color, unsigned char mode);
+ void lineV(unsigned char x, unsigned char y, unsigned char height);
+ void lineV(unsigned char x, unsigned char y, unsigned char height, unsigned char color, unsigned char mode);
+ void rect(unsigned char x, unsigned char y, unsigned char width, unsigned char height);
+ void rect(unsigned char x, unsigned char y, unsigned char width, unsigned char height, unsigned char color , unsigned char mode);
+ void rectFill(unsigned char x, unsigned char y, unsigned char width, unsigned char height);
+ void rectFill(unsigned char x, unsigned char y, unsigned char width, unsigned char height, unsigned char color , unsigned char mode);
+ void circle(unsigned char x, unsigned char y, unsigned char radius);
+ void circle(unsigned char x, unsigned char y, unsigned char radius, unsigned char color, unsigned char mode);
+ void circleFill(unsigned char x0, unsigned char y0, unsigned char radius);
+ void circleFill(unsigned char x0, unsigned char y0, unsigned char radius, unsigned char color, unsigned char mode);
+ void drawChar(unsigned char x, unsigned char y, unsigned char c);
+ void drawChar(unsigned char x, unsigned char y, unsigned char c, unsigned char color, unsigned char mode);
+ void drawBitmap(void);
+ unsigned char getLCDWidth(void);
+ unsigned char getLCDHeight(void);
+ void setColor(unsigned char color);
+ void setDrawMode(unsigned char mode);
+
+ // Font functions
+ unsigned char getFontWidth(void);
+ unsigned char getFontHeight(void);
+ unsigned char getTotalFonts(void);
+ unsigned char getFontType(void);
+ unsigned char setFontType(unsigned char type);
+ unsigned char getFontStartChar(void);
+ unsigned char getFontTotalChar(void);
+
+ // LCD Rotate Scroll functions
+ void scrollRight(unsigned char start, unsigned char stop);
+ void scrollLeft(unsigned char start, unsigned char stop);
+ void scrollVertRight(unsigned char start, unsigned char stop);
+ void scrollVertLeft(unsigned char start, unsigned char stop);
+ void scrollStop(void);
+ void flipVertical(unsigned char flip);
+ void flipHorizontal(unsigned char flip);
+
+ //void doCmd(unsigned char index);
+ /** \brief edOLED screen buffer.
+ Page buffer 64 x 48 divided by 8 = 384 unsigned chars
+ Page buffer is required because in SPI mode, the host cannot read the SSD1306's
+ GDRAM of the controller. This page buffer serves as a scratch RAM for graphical
+ functions. All drawing function will first be drawn on this page buffer, only
+ upon calling display() function will transfer the page buffer to the actual LCD
+ controller's memory.
+ */
+ unsigned char screenmemory [384];
+
+private:
+ unsigned char foreColor,drawMode,fontWidth, fontHeight, fontType, fontStartChar, fontTotalChar, cursorX, cursorY;
+ unsigned int fontMapWidth;
+ static const unsigned char *fontsPointer[];
+
+ // Communication
+ void spiTransfer(unsigned char data);
+ void spiSetup();
+};
+#endif
diff --git a/Firmware/oled/src/oled/edison_fonts.h b/Firmware/oled/src/oled/edison_fonts.h
new file mode 100644
index 0000000..885aed5
--- /dev/null
+++ b/Firmware/oled/src/oled/edison_fonts.h
@@ -0,0 +1,461 @@
+/******************************************************************************
+ * fonts.h
+ *
+ * Definition for all four default fonts.
+ *
+ * This file was imported from the MicroView library, written by GeekAmmo
+ * (https://github.com/geekammo/MicroView-Arduino-Library), and released under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+******************************************************************************/
+
+#ifndef OLED_FONTS_H
+#define OLED_FONTS_H
+
+// Standard ASCII 5x7 font
+static const unsigned char font5x7[] = {
+ // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
+ 5,8,0,255,12,75,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
+ 0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
+ 0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
+ 0x18, 0x3C, 0x7E, 0x3C, 0x18,
+ 0x1C, 0x57, 0x7D, 0x57, 0x1C,
+ 0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
+ 0x00, 0x18, 0x3C, 0x18, 0x00,
+ 0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
+ 0x00, 0x18, 0x24, 0x18, 0x00,
+ 0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
+ 0x30, 0x48, 0x3A, 0x06, 0x0E,
+ 0x26, 0x29, 0x79, 0x29, 0x26,
+ 0x40, 0x7F, 0x05, 0x05, 0x07,
+ 0x40, 0x7F, 0x05, 0x25, 0x3F,
+ 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
+ 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
+ 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
+ 0x14, 0x22, 0x7F, 0x22, 0x14,
+ 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
+ 0x06, 0x09, 0x7F, 0x01, 0x7F,
+ 0x00, 0x66, 0x89, 0x95, 0x6A,
+ 0x60, 0x60, 0x60, 0x60, 0x60,
+ 0x94, 0xA2, 0xFF, 0xA2, 0x94,
+ 0x08, 0x04, 0x7E, 0x04, 0x08,
+ 0x10, 0x20, 0x7E, 0x20, 0x10,
+ 0x08, 0x08, 0x2A, 0x1C, 0x08,
+ 0x08, 0x1C, 0x2A, 0x08, 0x08,
+ 0x1E, 0x10, 0x10, 0x10, 0x10,
+ 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
+ 0x30, 0x38, 0x3E, 0x38, 0x30,
+ 0x06, 0x0E, 0x3E, 0x0E, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x5F, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x07, 0x00,
+ 0x14, 0x7F, 0x14, 0x7F, 0x14,
+ 0x24, 0x2A, 0x7F, 0x2A, 0x12,
+ 0x23, 0x13, 0x08, 0x64, 0x62,
+ 0x36, 0x49, 0x56, 0x20, 0x50,
+ 0x00, 0x08, 0x07, 0x03, 0x00,
+ 0x00, 0x1C, 0x22, 0x41, 0x00,
+ 0x00, 0x41, 0x22, 0x1C, 0x00,
+ 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
+ 0x08, 0x08, 0x3E, 0x08, 0x08,
+ 0x00, 0x80, 0x70, 0x30, 0x00,
+ 0x08, 0x08, 0x08, 0x08, 0x08,
+ 0x00, 0x00, 0x60, 0x60, 0x00,
+ 0x20, 0x10, 0x08, 0x04, 0x02,
+ 0x3E, 0x51, 0x49, 0x45, 0x3E,
+ 0x00, 0x42, 0x7F, 0x40, 0x00,
+ 0x72, 0x49, 0x49, 0x49, 0x46,
+ 0x21, 0x41, 0x49, 0x4D, 0x33,
+ 0x18, 0x14, 0x12, 0x7F, 0x10,
+ 0x27, 0x45, 0x45, 0x45, 0x39,
+ 0x3C, 0x4A, 0x49, 0x49, 0x31,
+ 0x41, 0x21, 0x11, 0x09, 0x07,
+ 0x36, 0x49, 0x49, 0x49, 0x36,
+ 0x46, 0x49, 0x49, 0x29, 0x1E,
+ 0x00, 0x00, 0x14, 0x00, 0x00,
+ 0x00, 0x40, 0x34, 0x00, 0x00,
+ 0x00, 0x08, 0x14, 0x22, 0x41,
+ 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x00, 0x41, 0x22, 0x14, 0x08,
+ 0x02, 0x01, 0x59, 0x09, 0x06,
+ 0x3E, 0x41, 0x5D, 0x59, 0x4E,
+ 0x7C, 0x12, 0x11, 0x12, 0x7C,
+ 0x7F, 0x49, 0x49, 0x49, 0x36,
+ 0x3E, 0x41, 0x41, 0x41, 0x22,
+ 0x7F, 0x41, 0x41, 0x41, 0x3E,
+ 0x7F, 0x49, 0x49, 0x49, 0x41,
+ 0x7F, 0x09, 0x09, 0x09, 0x01,
+ 0x3E, 0x41, 0x41, 0x51, 0x73,
+ 0x7F, 0x08, 0x08, 0x08, 0x7F,
+ 0x00, 0x41, 0x7F, 0x41, 0x00,
+ 0x20, 0x40, 0x41, 0x3F, 0x01,
+ 0x7F, 0x08, 0x14, 0x22, 0x41,
+ 0x7F, 0x40, 0x40, 0x40, 0x40,
+ 0x7F, 0x02, 0x1C, 0x02, 0x7F,
+ 0x7F, 0x04, 0x08, 0x10, 0x7F,
+ 0x3E, 0x41, 0x41, 0x41, 0x3E,
+ 0x7F, 0x09, 0x09, 0x09, 0x06,
+ 0x3E, 0x41, 0x51, 0x21, 0x5E,
+ 0x7F, 0x09, 0x19, 0x29, 0x46,
+ 0x26, 0x49, 0x49, 0x49, 0x32,
+ 0x03, 0x01, 0x7F, 0x01, 0x03,
+ 0x3F, 0x40, 0x40, 0x40, 0x3F,
+ 0x1F, 0x20, 0x40, 0x20, 0x1F,
+ 0x3F, 0x40, 0x38, 0x40, 0x3F,
+ 0x63, 0x14, 0x08, 0x14, 0x63,
+ 0x03, 0x04, 0x78, 0x04, 0x03,
+ 0x61, 0x59, 0x49, 0x4D, 0x43,
+ 0x00, 0x7F, 0x41, 0x41, 0x41,
+ 0x02, 0x04, 0x08, 0x10, 0x20,
+ 0x00, 0x41, 0x41, 0x41, 0x7F,
+ 0x04, 0x02, 0x01, 0x02, 0x04,
+ 0x40, 0x40, 0x40, 0x40, 0x40,
+ 0x00, 0x03, 0x07, 0x08, 0x00,
+ 0x20, 0x54, 0x54, 0x78, 0x40,
+ 0x7F, 0x28, 0x44, 0x44, 0x38,
+ 0x38, 0x44, 0x44, 0x44, 0x28,
+ 0x38, 0x44, 0x44, 0x28, 0x7F,
+ 0x38, 0x54, 0x54, 0x54, 0x18,
+ 0x00, 0x08, 0x7E, 0x09, 0x02,
+ 0x18, 0xA4, 0xA4, 0x9C, 0x78,
+ 0x7F, 0x08, 0x04, 0x04, 0x78,
+ 0x00, 0x44, 0x7D, 0x40, 0x00,
+ 0x20, 0x40, 0x40, 0x3D, 0x00,
+ 0x7F, 0x10, 0x28, 0x44, 0x00,
+ 0x00, 0x41, 0x7F, 0x40, 0x00,
+ 0x7C, 0x04, 0x78, 0x04, 0x78,
+ 0x7C, 0x08, 0x04, 0x04, 0x78,
+ 0x38, 0x44, 0x44, 0x44, 0x38,
+ 0xFC, 0x18, 0x24, 0x24, 0x18,
+ 0x18, 0x24, 0x24, 0x18, 0xFC,
+ 0x7C, 0x08, 0x04, 0x04, 0x08,
+ 0x48, 0x54, 0x54, 0x54, 0x24,
+ 0x04, 0x04, 0x3F, 0x44, 0x24,
+ 0x3C, 0x40, 0x40, 0x20, 0x7C,
+ 0x1C, 0x20, 0x40, 0x20, 0x1C,
+ 0x3C, 0x40, 0x30, 0x40, 0x3C,
+ 0x44, 0x28, 0x10, 0x28, 0x44,
+ 0x4C, 0x90, 0x90, 0x90, 0x7C,
+ 0x44, 0x64, 0x54, 0x4C, 0x44,
+ 0x00, 0x08, 0x36, 0x41, 0x00,
+ 0x00, 0x00, 0x77, 0x00, 0x00,
+ 0x00, 0x41, 0x36, 0x08, 0x00,
+ 0x02, 0x01, 0x02, 0x04, 0x02,
+ 0x3C, 0x26, 0x23, 0x26, 0x3C,
+ 0x1E, 0xA1, 0xA1, 0x61, 0x12,
+ 0x3A, 0x40, 0x40, 0x20, 0x7A,
+ 0x38, 0x54, 0x54, 0x55, 0x59,
+ 0x21, 0x55, 0x55, 0x79, 0x41,
+ 0x21, 0x54, 0x54, 0x78, 0x41,
+ 0x21, 0x55, 0x54, 0x78, 0x40,
+ 0x20, 0x54, 0x55, 0x79, 0x40,
+ 0x0C, 0x1E, 0x52, 0x72, 0x12,
+ 0x39, 0x55, 0x55, 0x55, 0x59,
+ 0x39, 0x54, 0x54, 0x54, 0x59,
+ 0x39, 0x55, 0x54, 0x54, 0x58,
+ 0x00, 0x00, 0x45, 0x7C, 0x41,
+ 0x00, 0x02, 0x45, 0x7D, 0x42,
+ 0x00, 0x01, 0x45, 0x7C, 0x40,
+ 0xF0, 0x29, 0x24, 0x29, 0xF0,
+ 0xF0, 0x28, 0x25, 0x28, 0xF0,
+ 0x7C, 0x54, 0x55, 0x45, 0x00,
+ 0x20, 0x54, 0x54, 0x7C, 0x54,
+ 0x7C, 0x0A, 0x09, 0x7F, 0x49,
+ 0x32, 0x49, 0x49, 0x49, 0x32,
+ 0x32, 0x48, 0x48, 0x48, 0x32,
+ 0x32, 0x4A, 0x48, 0x48, 0x30,
+ 0x3A, 0x41, 0x41, 0x21, 0x7A,
+ 0x3A, 0x42, 0x40, 0x20, 0x78,
+ 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
+ 0x39, 0x44, 0x44, 0x44, 0x39,
+ 0x3D, 0x40, 0x40, 0x40, 0x3D,
+ 0x3C, 0x24, 0xFF, 0x24, 0x24,
+ 0x48, 0x7E, 0x49, 0x43, 0x66,
+ 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
+ 0xFF, 0x09, 0x29, 0xF6, 0x20,
+ 0xC0, 0x88, 0x7E, 0x09, 0x03,
+ 0x20, 0x54, 0x54, 0x79, 0x41,
+ 0x00, 0x00, 0x44, 0x7D, 0x41,
+ 0x30, 0x48, 0x48, 0x4A, 0x32,
+ 0x38, 0x40, 0x40, 0x22, 0x7A,
+ 0x00, 0x7A, 0x0A, 0x0A, 0x72,
+ 0x7D, 0x0D, 0x19, 0x31, 0x7D,
+ 0x26, 0x29, 0x29, 0x2F, 0x28,
+ 0x26, 0x29, 0x29, 0x29, 0x26,
+ 0x30, 0x48, 0x4D, 0x40, 0x20,
+ 0x38, 0x08, 0x08, 0x08, 0x08,
+ 0x08, 0x08, 0x08, 0x08, 0x38,
+ 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
+ 0x2F, 0x10, 0x28, 0x34, 0xFA,
+ 0x00, 0x00, 0x7B, 0x00, 0x00,
+ 0x08, 0x14, 0x2A, 0x14, 0x22,
+ 0x22, 0x14, 0x2A, 0x14, 0x08,
+ 0xAA, 0x00, 0x55, 0x00, 0xAA,
+ 0xAA, 0x55, 0xAA, 0x55, 0xAA,
+ 0x00, 0x00, 0x00, 0xFF, 0x00,
+ 0x10, 0x10, 0x10, 0xFF, 0x00,
+ 0x14, 0x14, 0x14, 0xFF, 0x00,
+ 0x10, 0x10, 0xFF, 0x00, 0xFF,
+ 0x10, 0x10, 0xF0, 0x10, 0xF0,
+ 0x14, 0x14, 0x14, 0xFC, 0x00,
+ 0x14, 0x14, 0xF7, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF,
+ 0x14, 0x14, 0xF4, 0x04, 0xFC,
+ 0x14, 0x14, 0x17, 0x10, 0x1F,
+ 0x10, 0x10, 0x1F, 0x10, 0x1F,
+ 0x14, 0x14, 0x14, 0x1F, 0x00,
+ 0x10, 0x10, 0x10, 0xF0, 0x00,
+ 0x00, 0x00, 0x00, 0x1F, 0x10,
+ 0x10, 0x10, 0x10, 0x1F, 0x10,
+ 0x10, 0x10, 0x10, 0xF0, 0x10,
+ 0x00, 0x00, 0x00, 0xFF, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0xFF, 0x10,
+ 0x00, 0x00, 0x00, 0xFF, 0x14,
+ 0x00, 0x00, 0xFF, 0x00, 0xFF,
+ 0x00, 0x00, 0x1F, 0x10, 0x17,
+ 0x00, 0x00, 0xFC, 0x04, 0xF4,
+ 0x14, 0x14, 0x17, 0x10, 0x17,
+ 0x14, 0x14, 0xF4, 0x04, 0xF4,
+ 0x00, 0x00, 0xFF, 0x00, 0xF7,
+ 0x14, 0x14, 0x14, 0x14, 0x14,
+ 0x14, 0x14, 0xF7, 0x00, 0xF7,
+ 0x14, 0x14, 0x14, 0x17, 0x14,
+ 0x10, 0x10, 0x1F, 0x10, 0x1F,
+ 0x14, 0x14, 0x14, 0xF4, 0x14,
+ 0x10, 0x10, 0xF0, 0x10, 0xF0,
+ 0x00, 0x00, 0x1F, 0x10, 0x1F,
+ 0x00, 0x00, 0x00, 0x1F, 0x14,
+ 0x00, 0x00, 0x00, 0xFC, 0x14,
+ 0x00, 0x00, 0xF0, 0x10, 0xF0,
+ 0x10, 0x10, 0xFF, 0x10, 0xFF,
+ 0x14, 0x14, 0x14, 0xFF, 0x14,
+ 0x10, 0x10, 0x10, 0x1F, 0x00,
+ 0x00, 0x00, 0x00, 0xF0, 0x10,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0x38, 0x44, 0x44, 0x38, 0x44,
+ 0x7C, 0x2A, 0x2A, 0x3E, 0x14,
+ 0x7E, 0x02, 0x02, 0x06, 0x06,
+ 0x02, 0x7E, 0x02, 0x7E, 0x02,
+ 0x63, 0x55, 0x49, 0x41, 0x63,
+ 0x38, 0x44, 0x44, 0x3C, 0x04,
+ 0x40, 0x7E, 0x20, 0x1E, 0x20,
+ 0x06, 0x02, 0x7E, 0x02, 0x02,
+ 0x99, 0xA5, 0xE7, 0xA5, 0x99,
+ 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
+ 0x4C, 0x72, 0x01, 0x72, 0x4C,
+ 0x30, 0x4A, 0x4D, 0x4D, 0x30,
+ 0x30, 0x48, 0x78, 0x48, 0x30,
+ 0xBC, 0x62, 0x5A, 0x46, 0x3D,
+ 0x3E, 0x49, 0x49, 0x49, 0x00,
+ 0x7E, 0x01, 0x01, 0x01, 0x7E,
+ 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
+ 0x44, 0x44, 0x5F, 0x44, 0x44,
+ 0x40, 0x51, 0x4A, 0x44, 0x40,
+ 0x40, 0x44, 0x4A, 0x51, 0x40,
+ 0x00, 0x00, 0xFF, 0x01, 0x03,
+ 0xE0, 0x80, 0xFF, 0x00, 0x00,
+ 0x08, 0x08, 0x6B, 0x6B, 0x08,
+ 0x36, 0x12, 0x36, 0x24, 0x36,
+ 0x06, 0x0F, 0x09, 0x0F, 0x06,
+ 0x00, 0x00, 0x18, 0x18, 0x00,
+ 0x00, 0x00, 0x10, 0x10, 0x00,
+ 0x30, 0x40, 0xFF, 0x01, 0x01,
+ 0x00, 0x1F, 0x01, 0x01, 0x1E,
+ 0x00, 0x19, 0x1D, 0x17, 0x12,
+ 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
+ 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char font8x16[] = {
+ // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
+ 8,16,32,96,2,56,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xBE, 0x90, 0xD0, 0xBE, 0x90, 0x00,
+ 0x00, 0x1C, 0x62, 0xFF, 0xC2, 0x80, 0x00, 0x00, 0x0C, 0x12, 0x92, 0x4C, 0xB0, 0x88, 0x06, 0x00,
+ 0x80, 0x7C, 0x62, 0xB2, 0x1C, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0x18, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00,
+ 0x00, 0x24, 0x18, 0x7E, 0x18, 0x24, 0x00, 0x00, 0x80, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00,
+ 0xF8, 0x04, 0xC2, 0x32, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x04, 0x04, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x02, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00,
+ 0xC0, 0xA0, 0x98, 0x84, 0xFE, 0x80, 0x80, 0x00, 0x00, 0x1E, 0x12, 0x12, 0x22, 0xC2, 0x00, 0x00,
+ 0xF8, 0x44, 0x22, 0x22, 0x22, 0xC0, 0x00, 0x00, 0x00, 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00,
+ 0x00, 0x8C, 0x52, 0x22, 0x52, 0x8C, 0x00, 0x00, 0x3C, 0x42, 0x42, 0x42, 0x26, 0xF8, 0x00, 0x00,
+ 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
+ 0x10, 0x20, 0x20, 0x40, 0x40, 0x80, 0x80, 0x00, 0x00, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x04, 0x0F, 0x04, 0x03, 0x00, 0x00, 0x04, 0x02, 0x01, 0x03, 0x04, 0x04, 0x03, 0x00,
+ 0x03, 0x04, 0x04, 0x04, 0x05, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x06, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x08, 0x06, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x03, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x01, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x04, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+ 0x04, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xF8, 0x04, 0x72, 0x8A, 0xFA, 0x84, 0x78, 0x00, 0x00, 0xC0, 0x38, 0x06, 0x38, 0xC0, 0x00, 0x00,
+ 0x00, 0xFE, 0x22, 0x22, 0x22, 0xDC, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00,
+ 0xFE, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00,
+ 0x00, 0xFE, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x22, 0xE2, 0x00, 0x00,
+ 0xFE, 0x20, 0x20, 0x20, 0x20, 0xFE, 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0xFE, 0x40, 0xB0, 0x08, 0x04, 0x02, 0x00, 0x00,
+ 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0C, 0x70, 0x80, 0x70, 0x0C, 0xFE, 0x00,
+ 0xFE, 0x0C, 0x30, 0xC0, 0x00, 0xFE, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00,
+ 0xFE, 0x42, 0x42, 0x42, 0x22, 0x1C, 0x00, 0x00, 0xF8, 0x04, 0x02, 0x02, 0x04, 0xF8, 0x00, 0x00,
+ 0x00, 0xFE, 0x42, 0x42, 0xA2, 0x1C, 0x00, 0x00, 0x00, 0x1C, 0x22, 0x42, 0x42, 0x80, 0x00, 0x00,
+ 0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00,
+ 0x06, 0x38, 0xC0, 0x00, 0xC0, 0x38, 0x06, 0x00, 0x3E, 0xC0, 0xF0, 0x0E, 0xF0, 0xC0, 0x3E, 0x00,
+ 0x00, 0x06, 0x98, 0x60, 0x98, 0x06, 0x00, 0x00, 0x00, 0x06, 0x18, 0xE0, 0x18, 0x06, 0x00, 0x00,
+ 0x02, 0x02, 0xC2, 0x32, 0x0A, 0x06, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x02, 0x00,
+ 0x00, 0x06, 0x18, 0x60, 0x80, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00,
+ 0x40, 0x30, 0x0C, 0x0C, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x02, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x07, 0x04, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x04, 0x07, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x03, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x04, 0x02, 0x01, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x0C, 0x12, 0x11, 0x10, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x06, 0x01, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x00, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00,
+ 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0xE0, 0x10, 0x10, 0x10, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x90, 0x90, 0x90, 0xE0, 0x00, 0x00,
+ 0x00, 0x20, 0xFC, 0x22, 0x22, 0x22, 0x02, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00,
+ 0x00, 0xFE, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x10, 0xF2, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x80, 0x40, 0x20, 0x10, 0x00, 0x00,
+ 0x00, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0x10, 0xF0, 0x20, 0x10, 0xF0, 0x00,
+ 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xE0, 0x00, 0x00,
+ 0x00, 0xF0, 0x20, 0x10, 0x10, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x10, 0x10, 0x10, 0xF0, 0x00, 0x00,
+ 0x00, 0xF0, 0x20, 0x10, 0x10, 0x70, 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x20, 0x00, 0x00,
+ 0x00, 0x20, 0x20, 0xFC, 0x20, 0x20, 0x20, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00,
+ 0x00, 0x70, 0x80, 0x00, 0x80, 0x70, 0x00, 0x00, 0xF0, 0x00, 0xC0, 0x30, 0xC0, 0x00, 0xF0, 0x00,
+ 0x00, 0x30, 0xC0, 0xC0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x30, 0xC0, 0x00, 0x80, 0x70, 0x00, 0x00,
+ 0x00, 0x10, 0x10, 0x90, 0x50, 0x30, 0x00, 0x00, 0x00, 0x80, 0x80, 0x7E, 0x02, 0x02, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x7E, 0x80, 0x80, 0x00, 0x00,
+ 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00,
+ 0x00, 0x07, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x24, 0x24, 0x22, 0x1F, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x00,
+ 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x02, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x3F, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x3F, 0x00, 0x00,
+ 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x04, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x04, 0x04, 0x04, 0x00, 0x00, 0x03, 0x04, 0x04, 0x02, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x04, 0x03, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x00, 0x01, 0x06, 0x01, 0x00,
+ 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00, 0x20, 0x20, 0x31, 0x0E, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x05, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x10, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x1F, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static const unsigned char sevensegment [] = {
+ // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
+ 10,16,46,12,1,20,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0xFC, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0xFC, 0x78, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0x00, 0x00, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02,
+ 0xFC, 0x78, 0x00, 0x00, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0xFC, 0x78, 0x7E, 0xFF, 0x00, 0x80,
+ 0x80, 0x80, 0x80, 0x00, 0xFF, 0x7E, 0x78, 0xFC, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0x00, 0x00,
+ 0x78, 0xFC, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0x00, 0x00, 0x00, 0x02, 0x03, 0x03, 0x03, 0x03,
+ 0x03, 0x02, 0xFC, 0x78, 0x78, 0xFC, 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0xFC, 0x78, 0x78, 0xFC,
+ 0x02, 0x83, 0x83, 0x83, 0x83, 0x02, 0xFC, 0x78, 0x00, 0x00, 0x00, 0x60, 0xF0, 0xF0, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0x40, 0xC0,
+ 0xC0, 0xC0, 0xC0, 0x40, 0x3F, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E,
+ 0x1C, 0x3E, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x00, 0x00, 0x00, 0x00, 0x41, 0xC1, 0xC1, 0xC1,
+ 0xC1, 0x41, 0x3E, 0x1C, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0x7E, 0x00, 0x00,
+ 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C, 0x1C, 0x3E, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41,
+ 0x3E, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0x1C, 0x3E, 0x41, 0xC1,
+ 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C, 0x00, 0x00, 0x41, 0xC1, 0xC1, 0xC1, 0xC1, 0x41, 0x3E, 0x1C
+};
+
+static const unsigned char fontlargenumber[] = {
+ // first row defines - FONTWIDTH, FONTHEIGHT, ASCII START CHAR, TOTAL CHARACTERS, FONT MAP WIDTH HIGH, FONT MAP WIDTH LOW (2,56 meaning 256)
+ 12,48,48,11,1,32,
+ 0x00, 0xC0, 0xF8, 0x7C, 0x3E, 0x3E, 0xFC, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0,
+ 0x78, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x7C, 0x3C, 0x3E, 0x3E, 0xFE, 0xFC,
+ 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x3E, 0x3E, 0x3E, 0xFE, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x3E,
+ 0x3E, 0x3E, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFC, 0x3E, 0x3E, 0x3E,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0xFE, 0xFE, 0x00, 0x00,
+ 0x00, 0x00, 0xC0, 0xF8, 0xFE, 0x3E, 0x7E, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFC,
+ 0x7E, 0x3E, 0xFE, 0xF8, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xC0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0xF9, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x03, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x3F,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFC,
+ 0x7F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00,
+ 0x00, 0xFE, 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3F, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00,
+ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8,
+ 0xFC, 0xFF, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0x3F, 0x03, 0x00, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3E, 0x7E, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x80, 0xF0, 0x7C, 0x7C, 0xF8, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xF8, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x9F, 0xFF, 0xF8, 0xFE, 0x1F,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0xFC,
+ 0x7F, 0x03, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xE7, 0xE0,
+ 0xE0, 0xE0, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFC, 0x3F,
+ 0x03, 0x03, 0x1F, 0xFF, 0xFC, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3E, 0x3E, 0x0F, 0x01,
+ 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFE, 0x0F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x7F, 0x00, 0x00, 0x00,
+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFF, 0xFF, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xC0, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x80,
+ 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0xFC, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F, 0x3F, 0x7C, 0x7C, 0x3F, 0x1F, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7F, 0x7F, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7C,
+ 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x7E, 0x7C, 0x7C, 0x7E, 0x1F, 0x07,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0x3E, 0x7C, 0x7C, 0x3E, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1F,
+ 0x7F, 0x7C, 0x7C, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1F, 0x3F, 0x7E, 0x7C, 0x7E, 0x3F, 0x1F, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x3E, 0x7C, 0x7C, 0x7E, 0x3F, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#endif
\ No newline at end of file
diff --git a/Firmware/oled/src/oled/gpl-3.0.txt b/Firmware/oled/src/oled/gpl-3.0.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/Firmware/oled/src/oled/gpl-3.0.txt
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/Firmware/oled/src/sparklibs.h b/Firmware/oled/src/sparklibs.h
new file mode 100644
index 0000000..100400f
--- /dev/null
+++ b/Firmware/oled/src/sparklibs.h
@@ -0,0 +1,16 @@
+#ifndef __sparklibs_h_
+#define __sparklibs_h_
+
+enum exceptions {
+GPIO_NO_PIN = 0x10, // No GPIO file exists for that GPIO ID.
+GPIO_BAD_MODE, // Selected GPIO cannot take that mode.
+GPIO_BAD_VALUE, // Selected GPIO cannot take that value.
+I2C_NO_DEV = 0x30, // No I2C device with that ID can be accessed.
+SPI_NO_DEV = 0x50, // No SPI device at that location.
+PWM_NO_DEV = 0x70, // No PWM function at that location.
+PWM_BAD_PERIOD, // Period value is outside the acceptable limit.
+PWM_BAD_DUTY, // Duty cycle value is outside the acceptable limit.
+
+};
+
+#endif
diff --git a/Firmware/oled/src/spi/spi.h b/Firmware/oled/src/spi/spi.h
new file mode 100644
index 0000000..e67a269
--- /dev/null
+++ b/Firmware/oled/src/spi/spi.h
@@ -0,0 +1,62 @@
+#ifndef __spi_h__
+#define __spi_h__
+
+#include
+#include
+
+struct spi_ioc_transfer;
+class spiDevice;
+class gpio;
+
+class spiPort
+{
+ public:
+ spiPort(int spiDriver=5);
+ ~spiPort();
+ bool doIOwn(spiDevice *curiousDevice);
+ void takeOwnership(spiDevice *bossyDevice);
+ void transferData(spi_ioc_transfer *xfer);
+
+ private:
+ void configurePort();
+ void configurePins(int spiDriver);
+
+ int _spiFile;
+ spiDevice *_portOwner;
+ gpio *_MOSI;
+ gpio *_MISO;
+ gpio *_SCK;
+ gpio *_CS;
+};
+
+class spiDevice
+{
+ public:
+ spiDevice(){};
+ spiDevice(spiPort *port, \
+ unsigned char spiMode = SPI_MODE_0, \
+ long speed = 1000000, \
+ bool lsbFirst = false, \
+ gpio *csPin = NULL);
+ void transferData(unsigned char *outData, \
+ unsigned char *inData = NULL, \
+ unsigned int len = 1, \
+ bool deselect = true);
+ bool customCS();
+ void CSLow();
+ void CSHigh();
+ bool doLSBFirst();
+ int getSPIMode();
+ gpio* getCSPin();
+ protected:
+ gpio *_csPin;
+ bool _customCS;
+ spiPort *_port;
+ unsigned char _spiMode;
+ long _speed;
+ bool _lsbFirst;
+
+};
+
+#endif
+
diff --git a/Firmware/oled/src/spi/spi_device_edison.cpp b/Firmware/oled/src/spi/spi_device_edison.cpp
new file mode 100644
index 0000000..919e630
--- /dev/null
+++ b/Firmware/oled/src/spi/spi_device_edison.cpp
@@ -0,0 +1,89 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../gpio/gpio.h"
+#include "spi.h"
+
+spiDevice::spiDevice(spiPort *port, \
+ unsigned char spiMode, \
+ long speed, \
+ bool lsbFirst, \
+ gpio *csPin)
+{
+ _port = port;
+ _port->takeOwnership(this);
+ _spiMode = spiMode;
+ _speed = speed;
+ _lsbFirst = lsbFirst;
+ _csPin = csPin;
+ if (csPin == NULL)
+ {
+ _customCS = false;
+ }
+ else
+ {
+ _customCS = true;
+ }
+}
+
+void spiDevice::transferData(unsigned char *dataOut, \
+ unsigned char *dataIn, \
+ unsigned int len,
+ bool deselect)
+{
+ spi_ioc_transfer xfer;
+ xfer.tx_buf =(unsigned long)dataOut;
+ xfer.rx_buf =(unsigned long)dataIn;
+ xfer.len = len;
+ xfer.speed_hz = _speed;
+ xfer.bits_per_word = 8;
+ if (deselect)
+ {
+ xfer.cs_change = 1;
+ }
+ else
+ {
+ xfer.cs_change = 0;
+ }
+ if (_port->doIOwn(this))
+ {
+ _port->takeOwnership(this);
+ }
+ _port->transferData(&xfer);
+}
+
+gpio* spiDevice::getCSPin()
+{
+ return this->_csPin;
+}
+
+bool spiDevice::customCS()
+{
+ return this->_customCS;
+}
+void spiDevice::CSLow()
+{
+ if (_csPin != NULL)
+ _csPin->pinWrite(LOW);
+}
+
+void spiDevice::CSHigh()
+{
+ if (_csPin != NULL)
+ _csPin->pinWrite(HIGH);
+}
+
+bool spiDevice::doLSBFirst()
+{
+ return _lsbFirst;
+}
+
+int spiDevice::getSPIMode()
+{
+ return _spiMode;
+}
+
diff --git a/Firmware/oled/src/spi/spi_port_edison.cpp b/Firmware/oled/src/spi/spi_port_edison.cpp
new file mode 100644
index 0000000..328de31
--- /dev/null
+++ b/Firmware/oled/src/spi/spi_port_edison.cpp
@@ -0,0 +1,74 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../sparklibs.h"
+#include "../gpio/gpio.h"
+#include "spi.h"
+
+
+spiPort::~spiPort()
+{
+ close(_spiFile);
+}
+
+spiPort::spiPort(int spiDriver)
+
+{
+ const char *path = "/dev/spidev5.1";
+ _spiFile = open(path, O_RDWR);
+ if (_spiFile < 0) throw SPI_NO_DEV;
+ _portOwner = NULL;
+
+}
+
+// configurePort() only handles the parts which must be handled apart from
+// the message struct.
+void spiPort::configurePort()
+{
+ if (_portOwner == NULL)
+ {
+ return;
+ }
+
+ // We'll make a little temp variable to transmit the various mode info to
+ // the SPI driver.
+ int temp = 0;
+
+ // The boolean lsbfirst is a rare case where the bit order should be
+ // reversed during transmission; it corresponds to the SPI_LSB_FIRST
+ // constant in the spidev.h file.
+ if (_portOwner->doLSBFirst())
+ {
+ temp = SPI_LSB_FIRST;
+ ioctl(_spiFile, SPI_IOC_WR_LSB_FIRST, &temp);
+ }
+ else
+ {
+ temp = 0;
+ ioctl(_spiFile, SPI_IOC_WR_LSB_FIRST, &temp);
+ }
+
+ temp = _portOwner->getSPIMode();
+ ioctl(_spiFile, SPI_IOC_WR_MODE, &temp);
+}
+
+void spiPort::transferData(spi_ioc_transfer *xfer)
+{
+ ioctl(_spiFile, SPI_IOC_MESSAGE(1), xfer);
+}
+
+bool spiPort::doIOwn(spiDevice *curiousDevice)
+{
+ return (curiousDevice == _portOwner);
+}
+
+void spiPort::takeOwnership(spiDevice *bossyDevice)
+{
+ _portOwner = bossyDevice;
+ configurePort();
+}
+
diff --git a/Firmware/oled/system-menu.sh b/Firmware/oled/system-menu.sh
new file mode 100644
index 0000000..a6c8815
--- /dev/null
+++ b/Firmware/oled/system-menu.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+cd /usr/local/sbin
+
+. ./oled.sh
+
+oled begin
+
+MENU_ITEMS=()
+MENU_FUNCTIONS=()
+
+for F in /usr/local/sbin/system-menu.d/*.sh; do
+ . "$F"
+done
+
+function menuf () {
+ ${MENU_FUNCTIONS[$1]}
+}
+
+while true; do
+ oled-menu "menuf" /tmp/system.menu.tmp "${MENU_ITEMS[@]}"
+ while [[ -n $(oled buttons) ]]; do
+ oled wait
+ done
+ while [[ -z $(oled buttons) ]]; do
+ oled wait
+ done
+done
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 8e7f1c4..d83ac1b 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,11 @@
+*Fork of SparkFun Edison OLED Block repo, adding a command-line tool to interact with the OLED Block*
+
+See [Firmware/oled](Firmware/oled/) for the command-line tool.
+
+Contains very minor modifications to the original SparkFun OLED drivers, such as making the screen buffer a public field of the `edOLED` class rather than a private static.
+
+-----
+
SparkFun Edison OLED Block
===========================