From 894973a9e7665004ff6e30a072b0fb7c51ce8f9d Mon Sep 17 00:00:00 2001 From: Pavel Brychta Date: Wed, 21 Oct 2020 09:24:36 +0200 Subject: [PATCH] Prvni odevzdani --- README.md | 406 +++++- .../SSD1306ClockDemo/SSD1306ClockDemo.ino | 214 +++ examples/SSD1306ClockDemo/images.h | 21 + .../SSD1306DrawingDemo/SSD1306DrawingDemo.ino | 233 +++ examples/SSD1306OTADemo/SSD1306OTADemo.ino | 123 ++ .../SSD1306SimpleDemo/SSD1306SimpleDemo.ino | 197 +++ examples/SSD1306SimpleDemo/images.h | 28 + .../SSD1306TwoScreenDemo.ino | 75 + examples/SSD1306TwoScreenDemo/images.h | 28 + examples/SSD1306UiDemo/SSD1306UiDemo.ino | 194 +++ examples/SSD1306UiDemo/images.h | 50 + library.json | 34 + library.properties | 9 + license | 24 + resources/DemoFrame1.jpg | Bin 0 -> 16026 bytes resources/DemoFrame2.jpg | Bin 0 -> 19502 bytes resources/DemoFrame3.jpg | Bin 0 -> 21777 bytes resources/DemoFrame4.jpg | Bin 0 -> 25325 bytes resources/FontTool.png | Bin 0 -> 14052 bytes resources/SPI_version.jpg | Bin 0 -> 26912 bytes resources/glyphEditor.html | 664 +++++++++ resources/glyphEditor.png | Bin 0 -> 68751 bytes resources/xbmPreview.png | Bin 0 -> 41692 bytes src/OLEDDisplay.cpp | 1082 ++++++++++++++ src/OLEDDisplay.h | 392 +++++ src/OLEDDisplayFonts.cpp | 1272 +++++++++++++++++ src/OLEDDisplayFonts.h | 14 + src/OLEDDisplayUi.cpp | 501 +++++++ src/OLEDDisplayUi.h | 317 ++++ src/SH1106.h | 39 + src/SH1106Brzo.h | 141 ++ src/SH1106Spi.h | 135 ++ src/SH1106Wire.h | 205 +++ src/SSD1306.h | 39 + src/SSD1306Brzo.h | 162 +++ src/SSD1306I2C.h | 152 ++ src/SSD1306Spi.h | 163 +++ src/SSD1306Wire.h | 217 +++ 38 files changed, 7129 insertions(+), 2 deletions(-) create mode 100644 examples/SSD1306ClockDemo/SSD1306ClockDemo.ino create mode 100644 examples/SSD1306ClockDemo/images.h create mode 100644 examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino create mode 100644 examples/SSD1306OTADemo/SSD1306OTADemo.ino create mode 100644 examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino create mode 100644 examples/SSD1306SimpleDemo/images.h create mode 100644 examples/SSD1306TwoScreenDemo/SSD1306TwoScreenDemo.ino create mode 100644 examples/SSD1306TwoScreenDemo/images.h create mode 100644 examples/SSD1306UiDemo/SSD1306UiDemo.ino create mode 100644 examples/SSD1306UiDemo/images.h create mode 100644 library.json create mode 100644 library.properties create mode 100644 license create mode 100644 resources/DemoFrame1.jpg create mode 100644 resources/DemoFrame2.jpg create mode 100644 resources/DemoFrame3.jpg create mode 100644 resources/DemoFrame4.jpg create mode 100644 resources/FontTool.png create mode 100644 resources/SPI_version.jpg create mode 100644 resources/glyphEditor.html create mode 100644 resources/glyphEditor.png create mode 100644 resources/xbmPreview.png create mode 100644 src/OLEDDisplay.cpp create mode 100644 src/OLEDDisplay.h create mode 100644 src/OLEDDisplayFonts.cpp create mode 100644 src/OLEDDisplayFonts.h create mode 100644 src/OLEDDisplayUi.cpp create mode 100644 src/OLEDDisplayUi.h create mode 100644 src/SH1106.h create mode 100644 src/SH1106Brzo.h create mode 100644 src/SH1106Spi.h create mode 100644 src/SH1106Wire.h create mode 100644 src/SSD1306.h create mode 100644 src/SSD1306Brzo.h create mode 100644 src/SSD1306I2C.h create mode 100644 src/SSD1306Spi.h create mode 100644 src/SSD1306Wire.h diff --git a/README.md b/README.md index 17afcb1..52ea5c8 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,405 @@ -# OLED_SSD +# Knihovna OLED_SSD (ESP8266/ESP32/SAMD21) -Arduino knihovna pro obsluhu malých OLED displejů \ No newline at end of file +Jedná se o modifikovanou knihovnu pro obsluhu malých OLED displejů, připojených přes I2C, nebo SPI rozhraní. Modifikace spočívají zejména v doplnění programového kódu, umožňujícího dithering (šrafování). + + +Následuje mírně upravený obsah originálního README.md od původních autorů + +# ThingPulse OLED SSD1306 (ESP8266/ESP32) + +This is a driver for SSD1306 128x64 and 128x32 OLED displays running on the Arduino/ESP8266 & ESP32 and mbed-os platforms. +Can be used with either the I2C or SPI version of the display. + +You can either download this library as a zip file and unpack it to your Arduino/libraries folder or find it in the Arduino library manager under "ESP8266 and ESP32 Oled Driver for SSD1306 display". For mbed-os a copy of the files are available as an mbed-os library. + +## Credits + +This library has initially been written by Daniel Eichhorn ([@squix78](https://github.com/squix78)). Many thanks go to Fabrice Weinberg ([@FWeinb](https://github.com/FWeinb)) for optimizing and refactoring many aspects of the library. Also many thanks to the many committers who helped to add new features and who fixed many bugs. Mbed-OS support and other improvements were contributed by Helmut Tschemernjak ([@helmut64](https://github.com/helmut64)). + +The init sequence for the SSD1306 was inspired by Adafruit's library for the same display. + +## Usage + +Check out the examples folder for a few comprehensive demonstrations how to use the library. Also check out the [ESP8266 Weather Station](https://github.com/ThingPulse/esp8266-weather-station) library which uses the OLED library to display beautiful weather information. + +## Features + +* Draw pixels at given coordinates +* Draw lines from given coordinates to given coordinates +* Draw or fill a rectangle with given dimensions +* Draw Text at given coordinates: + * Define Alignment: Left, Right and Center + * Set the Fontface you want to use (see section Fonts below) + * Limit the width of the text by an amount of pixels. Before this widths will be reached, the renderer will wrap the text to a new line if possible +* Display content in automatically side scrolling carousel + * Define transition cycles + * Define how long one frame will be displayed + * Draw the different frames in callback methods + * One indicator per frame will be automatically displayed. The active frame will be displayed from inactive once + +## Fonts + +Fonts are defined in a proprietary but open format. You can create new font files by choosing from a given list +of open sourced Fonts from this web app: http://oleddisplay.squix.ch +Choose the font family, style and size, check the preview image and if you like what you see click the "Create" button. This will create the font array in a text area form where you can copy and paste it into a new or existing header file. + + +![FontTool](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/FontTool.png) + +## Hardware Abstraction + +The library supports different protocols to access the OLED display. Currently there is support for I2C using the built in Wire.h library, I2C by using the much faster [BRZO I2C library](https://github.com/pasko-zh/brzo_i2c) written in assembler and it also supports displays which come with the SPI interface. + +### I2C with Wire.h + +```C++ +#include +#include "SSD1306Wire.h" + +// for 128x64 displays: +SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL +// for 128x32 displays: +// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, GEOMETRY_128_32 (or 128_64) +// for using 2nd Hardware I2C (if available) +// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_TWO); //default value is I2C_ONE if not mentioned +// By default SD1306Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value +// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz +// SSD1306Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency +``` + +for a SH1106: +```C++ +#include +#include "SH1106Wire.h" + +SH1106Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL +// By default SH1106Wire set I2C frequency to 700000, you can use set either another frequency or skip setting the frequency by providing -1 value +// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, 400000); //set I2C frequency to 400kHz +// SH1106Wire(0x3c, SDA, SCL, GEOMETRY_128_64, I2C_ONE, -1); //skip setting the I2C bus frequency +``` + +### I2C with brzo_i2c + +```C++ +#include +#include "SSD1306Brzo.h" + +SSD1306Brzo display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL +``` +or for the SH1106: +```C++ +#include +#include "SH1106Brzo.h" + +SH1106Brzo display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL +``` + +### SPI + +```C++ +#include +#include "SSD1306Spi.h" + +SSD1306Spi display(D0, D2, D8); // RES, DC, CS +``` +or for the SH1106: +```C++ +#include +#include "SH1106Spi.h" + +SH1106Spi display(D0, D2); // RES, DC +``` + +## API + +### Display Control + +```C++ +// Initialize the display +void init(); + +// Free the memory used by the display +void end(); + +// Cycle through the initialization +void resetDisplay(void); + +// Connect again to the display through I2C +void reconnect(void); + +// Turn the display on +void displayOn(void); + +// Turn the display offs +void displayOff(void); + +// Clear the local pixel buffer +void clear(void); + +// Write the buffer to the display memory +void display(void); + +// Inverted display mode +void invertDisplay(void); + +// Normal display mode +void normalDisplay(void); + +// Set display contrast +// really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0 +// normal brightness & contrast: contrast = 100 +void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64); + +// Convenience method to access +void setBrightness(uint8_t); + +// Turn the display upside down +void flipScreenVertically(); + +// Draw the screen mirrored +void mirrorScreen(); +``` + +## Pixel drawing + +```C++ + +/* Drawing functions */ +// Sets the color of all pixel operations +// color : BLACK, WHITE, INVERSE +void setColor(OLEDDISPLAY_COLOR color); + +// Draw a pixel at given position +void setPixel(int16_t x, int16_t y); + +// Draw a line from position 0 to position 1 +void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); + +// Draw the border of a rectangle at the given location +void drawRect(int16_t x, int16_t y, int16_t width, int16_t height); + +// Fill the rectangle +void fillRect(int16_t x, int16_t y, int16_t width, int16_t height); + +// Draw the border of a circle +void drawCircle(int16_t x, int16_t y, int16_t radius); + +// Fill circle +void fillCircle(int16_t x, int16_t y, int16_t radius); + +// Draw a line horizontally +void drawHorizontalLine(int16_t x, int16_t y, int16_t length); + +// Draw a lin vertically +void drawVerticalLine(int16_t x, int16_t y, int16_t length); + +// Draws a rounded progress bar with the outer dimensions given by width and height. Progress is +// a unsigned byte value between 0 and 100 +void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress); + +// Draw a bitmap in the internal image format +void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image); + +// Draw a XBM +void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const char* xbm); +``` + +## Text operations + +``` C++ +void drawString(int16_t x, int16_t y, String text); + +// Draws a String with a maximum width at the given location. +// If the given String is wider than the specified width +// The text will be wrapped to the next line at a space or dash +void drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, String text); + +// Returns the width of the const char* with the current +// font settings +uint16_t getStringWidth(const char* text, uint16_t length); + +// Convencience method for the const char version +uint16_t getStringWidth(String text); + +// Specifies relative to which anchor point +// the text is rendered. Available constants: +// TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH +void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); + +// Sets the current font. Available default fonts +// ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24 +// Or create one with the font tool at http://oleddisplay.squix.ch +void setFont(const uint8_t* fontData); +``` + +## Ui Library (OLEDDisplayUi) + +The Ui Library is used to provide a basic set of Ui elements called, `Frames` and `Overlays`. A `Frame` is used to provide +information the default behaviour is to display a `Frame` for a defined time and than move to the next. The library also provides an `Indicator` that will be updated accordingly. An `Overlay` on the other hand is a pieces of information (e.g. a clock) that is displayed always at the same position. + + +```C++ +/** + * Initialise the display + */ +void init(); + +/** + * Configure the internal used target FPS + */ +void setTargetFPS(uint8_t fps); + +/** + * Enable automatic transition to next frame after the some time can be configured with + * `setTimePerFrame` and `setTimePerTransition`. + */ +void enableAutoTransition(); + +/** + * Disable automatic transition to next frame. + */ +void disableAutoTransition(); + +/** + * Set the direction if the automatic transitioning + */ +void setAutoTransitionForwards(); +void setAutoTransitionBackwards(); + +/** + * Set the approx. time a frame is displayed + */ +void setTimePerFrame(uint16_t time); + +/** + * Set the approx. time a transition will take + */ +void setTimePerTransition(uint16_t time); + +/** + * Draw the indicator. + * This is the default state for all frames if + * the indicator was hidden on the previous frame + * it will be slided in. + */ +void enableIndicator(); + +/** + * Don't draw the indicator. + * This will slide out the indicator + * when transitioning to the next frame. + */ +void disableIndicator(); + +/** + * Enable drawing of all indicators. + */ +void enableAllIndicators(); + +/** + * Disable drawing of all indicators. + */ +void disableAllIndicators(); + +/** + * Set the position of the indicator bar. + */ +void setIndicatorPosition(IndicatorPosition pos); + +/** + * Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING + */ +void setIndicatorDirection(IndicatorDirection dir); + +/** + * Set the symbol to indicate an active frame in the indicator bar. + */ +void setActiveSymbol(const char* symbol); + +/** + * Set the symbol to indicate an inactive frame in the indicator bar. + */ +void setInactiveSymbol(const char* symbol); + +/** + * Configure what animation is used to transition from one frame to another + */ +void setFrameAnimation(AnimationDirection dir); + +/** + * Add frame drawing functions + */ +void setFrames(FrameCallback* frameFunctions, uint8_t frameCount); + +/** + * Add overlays drawing functions that are draw independent of the Frames + */ +void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount); + +/** + * Set the function that will draw each step + * in the loading animation + */ +void setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction); + +/** + * Run the loading process + */ +void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount); + +// Manuell Controll +void nextFrame(); +void previousFrame(); + +/** + * Switch without transition to frame `frame`. + */ +void switchToFrame(uint8_t frame); + +/** + * Transition to frame `frame`, when the `frame` number is bigger than the current + * frame the forward animation will be used, otherwise the backwards animation is used. + */ +void transitionToFrame(uint8_t frame); + +// State Info +OLEDDisplayUiState* getUiState(); + +// This needs to be called in the main loop +// the returned value is the remaining time (in ms) +// you have to draw after drawing to keep the frame budget. +int8_t update(); +``` + +## Example: SSD1306Demo + +### Frame 1 +![DemoFrame1](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame1.jpg) + +This frame shows three things: + * How to draw an xbm image + * How to draw a static text which is not moved by the frame transition + * The active/inactive frame indicators + +### Frame 2 +![DemoFrame2](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame2.jpg) + +Currently there are one fontface with three sizes included in the library: Arial 10, 16 and 24. Once the converter is published you will be able to convert any ttf font into the used format. + +### Frame 3 + +![DemoFrame3](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame3.jpg) + +This frame demonstrates the text alignment. The coordinates in the frame show relative to which position the texts have been rendered. + +### Frame 4 + +![DemoFrame4](https://github.com/squix78/esp8266-oled-ssd1306/raw/master/resources/DemoFrame4.jpg) + +This shows how to use define a maximum width after which the driver automatically wraps a word to the next line. This comes in very handy if you have longer texts to display. + +### SPI version + +![SPIVersion](https://github.com/neptune2/esp8266-oled-ssd1306/raw/master/resources/SPI_version.jpg) + +This shows the code working on the SPI version of the display. See demo code for ESP8266 pins used. diff --git a/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino b/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino new file mode 100644 index 0000000..63102cf --- /dev/null +++ b/examples/SSD1306ClockDemo/SSD1306ClockDemo.ino @@ -0,0 +1,214 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#include + +// Include the correct display library +// For a connection via I2C using Wire include +#include // Only needed for Arduino 1.6.5 and earlier +#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"` +// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"` +// For a connection via I2C using brzo_i2c (must be installed) include +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Brzo.h" +// #include "SH1106Brzo.h" +// For a connection via SPI include +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Spi.h" +// #include "SH1106SPi.h" + +// Include the UI lib +#include "OLEDDisplayUi.h" + +// Include custom images +#include "images.h" + +// Use the corresponding display class: + +// Initialize the OLED display using SPI +// D5 -> CLK +// D7 -> MOSI (DOUT) +// D0 -> RES +// D2 -> DC +// D8 -> CS +// SSD1306Spi display(D0, D2, D8); +// or +// SH1106Spi display(D0, D2); + +// Initialize the OLED display using brzo_i2c +// D3 -> SDA +// D5 -> SCL +// SSD1306Brzo display(0x3c, D3, D5); +// or +// SH1106Brzo display(0x3c, D3, D5); + +// Initialize the OLED display using Wire library +SSD1306Wire display(0x3c, D3, D5); +// SH1106 display(0x3c, D3, D5); + +OLEDDisplayUi ui ( &display ); + +int screenW = 128; +int screenH = 64; +int clockCenterX = screenW/2; +int clockCenterY = ((screenH-16)/2)+16; // top yellow part is 16 px height +int clockRadius = 23; + +// utility function for digital clock display: prints leading 0 +String twoDigits(int digits){ + if(digits < 10) { + String i = '0'+String(digits); + return i; + } + else { + return String(digits); + } +} + +void clockOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { + +} + +void analogClockFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { +// ui.disableIndicator(); + + // Draw the clock face +// display->drawCircle(clockCenterX + x, clockCenterY + y, clockRadius); + display->drawCircle(clockCenterX + x, clockCenterY + y, 2); + // + //hour ticks + for( int z=0; z < 360;z= z + 30 ){ + //Begin at 0° and stop at 360° + float angle = z ; + angle = ( angle / 57.29577951 ) ; //Convert degrees to radians + int x2 = ( clockCenterX + ( sin(angle) * clockRadius ) ); + int y2 = ( clockCenterY - ( cos(angle) * clockRadius ) ); + int x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 8 ) ) ) ); + int y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 8 ) ) ) ); + display->drawLine( x2 + x , y2 + y , x3 + x , y3 + y); + } + + // display second hand + float angle = second() * 6 ; + angle = ( angle / 57.29577951 ) ; //Convert degrees to radians + int x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 5 ) ) ) ); + int y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 5 ) ) ) ); + display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y); + // + // display minute hand + angle = minute() * 6 ; + angle = ( angle / 57.29577951 ) ; //Convert degrees to radians + x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 4 ) ) ) ); + y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 4 ) ) ) ); + display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y); + // + // display hour hand + angle = hour() * 30 + int( ( minute() / 12 ) * 6 ) ; + angle = ( angle / 57.29577951 ) ; //Convert degrees to radians + x3 = ( clockCenterX + ( sin(angle) * ( clockRadius - ( clockRadius / 2 ) ) ) ); + y3 = ( clockCenterY - ( cos(angle) * ( clockRadius - ( clockRadius / 2 ) ) ) ); + display->drawLine( clockCenterX + x , clockCenterY + y , x3 + x , y3 + y); +} + +void digitalClockFrame(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + String timenow = String(hour())+":"+twoDigits(minute())+":"+twoDigits(second()); + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_24); + display->drawString(clockCenterX + x , clockCenterY + y, timenow ); +} + +// This array keeps function pointers to all frames +// frames are the single views that slide in +FrameCallback frames[] = { analogClockFrame, digitalClockFrame }; + +// how many frames are there? +int frameCount = 2; + +// Overlays are statically drawn on top of a frame eg. a clock +OverlayCallback overlays[] = { clockOverlay }; +int overlaysCount = 1; + +void setup() { + Serial.begin(9600); + Serial.println(); + + // The ESP is capable of rendering 60fps in 80Mhz mode + // but that won't give you much time for anything else + // run it in 160Mhz mode or just set it to 30 fps + ui.setTargetFPS(60); + + // Customize the active and inactive symbol + ui.setActiveSymbol(activeSymbol); + ui.setInactiveSymbol(inactiveSymbol); + + // You can change this to + // TOP, LEFT, BOTTOM, RIGHT + ui.setIndicatorPosition(TOP); + + // Defines where the first frame is located in the bar. + ui.setIndicatorDirection(LEFT_RIGHT); + + // You can change the transition that is used + // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN + ui.setFrameAnimation(SLIDE_LEFT); + + // Add frames + ui.setFrames(frames, frameCount); + + // Add overlays + ui.setOverlays(overlays, overlaysCount); + + // Initialising the UI will init the display too. + ui.init(); + + display.flipScreenVertically(); + + unsigned long secsSinceStart = millis(); + // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: + const unsigned long seventyYears = 2208988800UL; + // subtract seventy years: + unsigned long epoch = secsSinceStart - seventyYears * SECS_PER_HOUR; + setTime(epoch); + +} + + +void loop() { + int remainingTimeBudget = ui.update(); + + if (remainingTimeBudget > 0) { + // You can do some work here + // Don't do stuff if you are below your + // time budget. + delay(remainingTimeBudget); + + } + + +} diff --git a/examples/SSD1306ClockDemo/images.h b/examples/SSD1306ClockDemo/images.h new file mode 100644 index 0000000..1889188 --- /dev/null +++ b/examples/SSD1306ClockDemo/images.h @@ -0,0 +1,21 @@ +const unsigned char activeSymbol[] PROGMEM = { + B00000000, + B00000000, + B00011000, + B00100100, + B01000010, + B01000010, + B00100100, + B00011000 +}; + +const unsigned char inactiveSymbol[] PROGMEM = { + B00000000, + B00000000, + B00000000, + B00000000, + B00011000, + B00011000, + B00000000, + B00000000 +}; diff --git a/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino b/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino new file mode 100644 index 0000000..43bd974 --- /dev/null +++ b/examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino @@ -0,0 +1,233 @@ + /** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + + // Include the correct display library + // For a connection via I2C using Wire include + #include // Only needed for Arduino 1.6.5 and earlier +#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"` + // or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"` + // For a connection via I2C using brzo_i2c (must be installed) include + // #include // Only needed for Arduino 1.6.5 and earlier + // #include "SSD1306Brzo.h" + // #include "SH1106Brzo.h" + // For a connection via SPI include + // #include // Only needed for Arduino 1.6.5 and earlier + // #include "SSD1306Spi.h" + // #include "SH1106SPi.h" + + // Use the corresponding display class: + + // Initialize the OLED display using SPI + // D5 -> CLK + // D7 -> MOSI (DOUT) + // D0 -> RES + // D2 -> DC + // D8 -> CS + // SSD1306Spi display(D0, D2, D8); + // or + // SH1106Spi display(D0, D2); + + // Initialize the OLED display using brzo_i2c + // D3 -> SDA + // D5 -> SCL + // SSD1306Brzo display(0x3c, D3, D5); + // or + // SH1106Brzo display(0x3c, D3, D5); + + // Initialize the OLED display using Wire library + SSD1306Wire display(0x3c, D3, D5); + // SH1106 display(0x3c, D3, D5); + +// Adapted from Adafruit_SSD1306 +void drawLines() { + for (int16_t i=0; i=0; i-=4) { + display.drawLine(0, display.getHeight()-1, display.getWidth()-1, i); + display.display(); + delay(10); + } + delay(250); + + display.clear(); + for (int16_t i=display.getWidth()-1; i>=0; i-=4) { + display.drawLine(display.getWidth()-1, display.getHeight()-1, i, 0); + display.display(); + delay(10); + } + for (int16_t i=display.getHeight()-1; i>=0; i-=4) { + display.drawLine(display.getWidth()-1, display.getHeight()-1, 0, i); + display.display(); + delay(10); + } + delay(250); + display.clear(); + for (int16_t i=0; i + + // OTA Includes + #include + #include + + const char *ssid = "[Your SSID]"; + const char *password = "[Your Password]"; + + +// Include the correct display library +// For a connection via I2C using Wire include +#include // Only needed for Arduino 1.6.5 and earlier +#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"` +// or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"` +// For a connection via I2C using brzo_i2c (must be installed) include +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Brzo.h" +// #include "SH1106Brzo.h" +// For a connection via SPI include +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Spi.h" +// #include "SH1106SPi.h" + +// Use the corresponding display class: + +// Initialize the OLED display using SPI +// D5 -> CLK +// D7 -> MOSI (DOUT) +// D0 -> RES +// D2 -> DC +// D8 -> CS +// SSD1306Spi display(D0, D2, D8); +// or +// SH1106Spi display(D0, D2); + +// Initialize the OLED display using brzo_i2c +// D3 -> SDA +// D5 -> SCL +// SSD1306Brzo display(0x3c, D3, D5); +// or +// SH1106Brzo display(0x3c, D3, D5); + +// Initialize the OLED display using Wire library +SSD1306Wire display(0x3c, D3, D5); +// SH1106 display(0x3c, D3, D5); + + +void setup() { + WiFi.begin ( ssid, password ); + + // Wait for connection + while ( WiFi.status() != WL_CONNECTED ) { + delay ( 10 ); + } + + display.init(); + display.flipScreenVertically(); + display.setContrast(255); + + ArduinoOTA.begin(); + ArduinoOTA.onStart([]() { + display.clear(); + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH); + display.drawString(display.getWidth()/2, display.getHeight()/2 - 10, "OTA Update"); + display.display(); + }); + + ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { + display.drawProgressBar(4, 32, 120, 8, progress / (total / 100) ); + display.display(); + }); + + ArduinoOTA.onEnd([]() { + display.clear(); + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH); + display.drawString(display.getWidth()/2, display.getHeight()/2, "Restart"); + display.display(); + }); + + // Align text vertical/horizontal center + display.setTextAlignment(TEXT_ALIGN_CENTER_BOTH); + display.setFont(ArialMT_Plain_10); + display.drawString(display.getWidth()/2, display.getHeight()/2, "Ready for OTA:\n" + WiFi.localIP().toString()); + display.display(); +} + +void loop() { + ArduinoOTA.handle(); +} diff --git a/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino b/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino new file mode 100644 index 0000000..8d715e4 --- /dev/null +++ b/examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino @@ -0,0 +1,197 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +// Include the correct display library + +// For a connection via I2C using the Arduino Wire include: +#include // Only needed for Arduino 1.6.5 and earlier +#include "SSD1306Wire.h" // legacy: #include "SSD1306.h" +// OR #include "SH1106Wire.h" // legacy: #include "SH1106.h" + +// For a connection via I2C using brzo_i2c (must be installed) include: +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Brzo.h" +// OR #include "SH1106Brzo.h" + +// For a connection via SPI include: +// #include // Only needed for Arduino 1.6.5 and earlier +// #include "SSD1306Spi.h" +// OR #include "SH1106SPi.h" + + +// Optionally include custom images +#include "images.h" + + +// Initialize the OLED display using Arduino Wire: +SSD1306Wire display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h +// SSD1306Wire display(0x3c, D3, D5); // ADDRESS, SDA, SCL - If not, they can be specified manually. +// SSD1306Wire display(0x3c, SDA, SCL, GEOMETRY_128_32); // ADDRESS, SDA, SCL, OLEDDISPLAY_GEOMETRY - Extra param required for 128x32 displays. +// SH1106 display(0x3c, SDA, SCL); // ADDRESS, SDA, SCL + +// Initialize the OLED display using brzo_i2c: +// SSD1306Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL +// or +// SH1106Brzo display(0x3c, D3, D5); // ADDRESS, SDA, SCL + +// Initialize the OLED display using SPI: +// D5 -> CLK +// D7 -> MOSI (DOUT) +// D0 -> RES +// D2 -> DC +// D8 -> CS +// SSD1306Spi display(D0, D2, D8); // RES, DC, CS +// or +// SH1106Spi display(D0, D2); // RES, DC + + +#define DEMO_DURATION 3000 +typedef void (*Demo)(void); + +int demoMode = 0; +int counter = 1; + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); + + + // Initialising the UI will init the display too. + display.init(); + + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_10); + +} + +void drawFontFaceDemo() { + // Font Demo1 + // create more fonts at http://oleddisplay.squix.ch/ + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.setFont(ArialMT_Plain_10); + display.drawString(0, 0, "Hello world"); + display.setFont(ArialMT_Plain_16); + display.drawString(0, 10, "Hello world"); + display.setFont(ArialMT_Plain_24); + display.drawString(0, 26, "Hello world"); +} + +void drawTextFlowDemo() { + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawStringMaxWidth(0, 0, 128, + "Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore." ); +} + +void drawTextAlignmentDemo() { + // Text alignment demo + display.setFont(ArialMT_Plain_10); + + // The coordinates define the left starting point of the text + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawString(0, 10, "Left aligned (0,10)"); + + // The coordinates define the center of the text + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.drawString(64, 22, "Center aligned (64,22)"); + + // The coordinates define the right end of the text + display.setTextAlignment(TEXT_ALIGN_RIGHT); + display.drawString(128, 33, "Right aligned (128,33)"); +} + +void drawRectDemo() { + // Draw a pixel at given position + for (int i = 0; i < 10; i++) { + display.setPixel(i, i); + display.setPixel(10 - i, i); + } + display.drawRect(12, 12, 20, 20); + + // Fill the rectangle + display.fillRect(14, 14, 17, 17); + + // Draw a line horizontally + display.drawHorizontalLine(0, 40, 20); + + // Draw a line horizontally + display.drawVerticalLine(40, 0, 20); +} + +void drawCircleDemo() { + for (int i=1; i < 8; i++) { + display.setColor(WHITE); + display.drawCircle(32, 32, i*3); + if (i % 2 == 0) { + display.setColor(BLACK); + } + display.fillCircle(96, 32, 32 - i* 3); + } +} + +void drawProgressBarDemo() { + int progress = (counter / 5) % 100; + // draw the progress bar + display.drawProgressBar(0, 32, 120, 10, progress); + + // draw the percentage as String + display.setTextAlignment(TEXT_ALIGN_CENTER); + display.drawString(64, 15, String(progress) + "%"); +} + +void drawImageDemo() { + // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html + // on how to create xbm files + display.drawXbm(34, 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits); +} + +Demo demos[] = {drawFontFaceDemo, drawTextFlowDemo, drawTextAlignmentDemo, drawRectDemo, drawCircleDemo, drawProgressBarDemo, drawImageDemo}; +int demoLength = (sizeof(demos) / sizeof(Demo)); +long timeSinceLastModeSwitch = 0; + +void loop() { + // clear the display + display.clear(); + // draw the current demo method + demos[demoMode](); + + display.setTextAlignment(TEXT_ALIGN_RIGHT); + display.drawString(10, 128, String(millis())); + // write the buffer to the display + display.display(); + + if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) { + demoMode = (demoMode + 1) % demoLength; + timeSinceLastModeSwitch = millis(); + } + counter++; + delay(10); +} diff --git a/examples/SSD1306SimpleDemo/images.h b/examples/SSD1306SimpleDemo/images.h new file mode 100644 index 0000000..5041799 --- /dev/null +++ b/examples/SSD1306SimpleDemo/images.h @@ -0,0 +1,28 @@ +#define WiFi_Logo_width 60 +#define WiFi_Logo_height 36 +const uint8_t WiFi_Logo_bits[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, + 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, + 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, + 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, + 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, + 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, + 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, + 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, + 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, + 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; diff --git a/examples/SSD1306TwoScreenDemo/SSD1306TwoScreenDemo.ino b/examples/SSD1306TwoScreenDemo/SSD1306TwoScreenDemo.ino new file mode 100644 index 0000000..b9595d8 --- /dev/null +++ b/examples/SSD1306TwoScreenDemo/SSD1306TwoScreenDemo.ino @@ -0,0 +1,75 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +// Include the correct display library +// For a connection via I2C using Wire include +#include // Only needed for Arduino 1.6.5 and earlier +#include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"` +#include "images.h" + +// Initialize the OLED display using Wire library +SSD1306Wire display(0x3c, D3, D5); +SSD1306Wire display2(0x3c, D1, D2); + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); + + + // Initialising the UI will init the display too. + display.init(); + display2.init(); + + // This will make sure that multiple instances of a display driver + // running on different ports will work together transparently + display.setI2cAutoInit(true); + display2.setI2cAutoInit(true); + + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_LEFT); + + display2.flipScreenVertically(); + display2.setFont(ArialMT_Plain_10); + display2.setTextAlignment(TEXT_ALIGN_LEFT); + +} + +void loop() { + display.clear(); + display.drawString(0, 0, "Hello world: " + String(millis())); + display.display(); + + display2.clear(); + display2.drawString(0, 0, "Hello world: " + String(millis())); + display2.display(); + + delay(10); +} diff --git a/examples/SSD1306TwoScreenDemo/images.h b/examples/SSD1306TwoScreenDemo/images.h new file mode 100644 index 0000000..5041799 --- /dev/null +++ b/examples/SSD1306TwoScreenDemo/images.h @@ -0,0 +1,28 @@ +#define WiFi_Logo_width 60 +#define WiFi_Logo_height 36 +const uint8_t WiFi_Logo_bits[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, + 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, + 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, + 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, + 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, + 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, + 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, + 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, + 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, + 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; diff --git a/examples/SSD1306UiDemo/SSD1306UiDemo.ino b/examples/SSD1306UiDemo/SSD1306UiDemo.ino new file mode 100644 index 0000000..72c836b --- /dev/null +++ b/examples/SSD1306UiDemo/SSD1306UiDemo.ino @@ -0,0 +1,194 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + + // Include the correct display library + // For a connection via I2C using Wire include + #include // Only needed for Arduino 1.6.5 and earlier + #include "SSD1306Wire.h" // legacy include: `#include "SSD1306.h"` + // or #include "SH1106Wire.h", legacy include: `#include "SH1106.h"` + // For a connection via I2C using brzo_i2c (must be installed) include + // #include // Only needed for Arduino 1.6.5 and earlier + // #include "SSD1306Brzo.h" + // #include "SH1106Brzo.h" + // For a connection via SPI include + // #include // Only needed for Arduino 1.6.5 and earlier + // #include "SSD1306Spi.h" + // #include "SH1106SPi.h" + +// Include the UI lib +#include "OLEDDisplayUi.h" + +// Include custom images + +#include "images.h" + +// Use the corresponding display class: + +// Initialize the OLED display using SPI +// D5 -> CLK +// D7 -> MOSI (DOUT) +// D0 -> RES +// D2 -> DC +// D8 -> CS +// SSD1306Spi display(D0, D2, D8); +// or +// SH1106Spi display(D0, D2); + +// Initialize the OLED display using brzo_i2c +// D3 -> SDA +// D5 -> SCL +// SSD1306Brzo display(0x3c, D3, D5); +// or +// SH1106Brzo display(0x3c, D3, D5); + +// Initialize the OLED display using Wire library +SSD1306Wire display(0x3c, D3, D5); +// SH1106Wire display(0x3c, D3, D5); + +OLEDDisplayUi ui ( &display ); + +void msOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) { + display->setTextAlignment(TEXT_ALIGN_RIGHT); + display->setFont(ArialMT_Plain_10); + display->drawString(128, 0, String(millis())); +} + +void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + // draw an xbm image. + // Please note that everything that should be transitioned + // needs to be drawn relative to x and y + + display->drawXbm(x + 34, y + 14, WiFi_Logo_width, WiFi_Logo_height, WiFi_Logo_bits); +} + +void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + // Demonstrates the 3 included default sizes. The fonts come from SSD1306Fonts.h file + // Besides the default fonts there will be a program to convert TrueType fonts into this format + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_10); + display->drawString(0 + x, 10 + y, "Arial 10"); + + display->setFont(ArialMT_Plain_16); + display->drawString(0 + x, 20 + y, "Arial 16"); + + display->setFont(ArialMT_Plain_24); + display->drawString(0 + x, 34 + y, "Arial 24"); +} + +void drawFrame3(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + // Text alignment demo + display->setFont(ArialMT_Plain_10); + + // The coordinates define the left starting point of the text + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->drawString(0 + x, 11 + y, "Left aligned (0,10)"); + + // The coordinates define the center of the text + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->drawString(64 + x, 22 + y, "Center aligned (64,22)"); + + // The coordinates define the right end of the text + display->setTextAlignment(TEXT_ALIGN_RIGHT); + display->drawString(128 + x, 33 + y, "Right aligned (128,33)"); +} + +void drawFrame4(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + // Demo for drawStringMaxWidth: + // with the third parameter you can define the width after which words will be wrapped. + // Currently only spaces and "-" are allowed for wrapping + display->setTextAlignment(TEXT_ALIGN_LEFT); + display->setFont(ArialMT_Plain_10); + display->drawStringMaxWidth(0 + x, 10 + y, 128, "Lorem ipsum\n dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore."); +} + +void drawFrame5(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) { + +} + +// This array keeps function pointers to all frames +// frames are the single views that slide in +FrameCallback frames[] = { drawFrame1, drawFrame2, drawFrame3, drawFrame4, drawFrame5 }; + +// how many frames are there? +int frameCount = 5; + +// Overlays are statically drawn on top of a frame eg. a clock +OverlayCallback overlays[] = { msOverlay }; +int overlaysCount = 1; + +void setup() { + Serial.begin(115200); + Serial.println(); + Serial.println(); + + // The ESP is capable of rendering 60fps in 80Mhz mode + // but that won't give you much time for anything else + // run it in 160Mhz mode or just set it to 30 fps + ui.setTargetFPS(60); + + // Customize the active and inactive symbol + ui.setActiveSymbol(activeSymbol); + ui.setInactiveSymbol(inactiveSymbol); + + // You can change this to + // TOP, LEFT, BOTTOM, RIGHT + ui.setIndicatorPosition(BOTTOM); + + // Defines where the first frame is located in the bar. + ui.setIndicatorDirection(LEFT_RIGHT); + + // You can change the transition that is used + // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_UP, SLIDE_DOWN + ui.setFrameAnimation(SLIDE_LEFT); + + // Add frames + ui.setFrames(frames, frameCount); + + // Add overlays + ui.setOverlays(overlays, overlaysCount); + + // Initialising the UI will init the display too. + ui.init(); + + display.flipScreenVertically(); + +} + + +void loop() { + int remainingTimeBudget = ui.update(); + + if (remainingTimeBudget > 0) { + // You can do some work here + // Don't do stuff if you are below your + // time budget. + delay(remainingTimeBudget); + } +} diff --git a/examples/SSD1306UiDemo/images.h b/examples/SSD1306UiDemo/images.h new file mode 100644 index 0000000..2489d1e --- /dev/null +++ b/examples/SSD1306UiDemo/images.h @@ -0,0 +1,50 @@ +#define WiFi_Logo_width 60 +#define WiFi_Logo_height 36 +const uint8_t WiFi_Logo_bits[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0x07, 0xC0, 0x83, 0x01, 0x80, 0xFF, 0xFF, 0xFF, + 0x01, 0x00, 0x07, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0C, 0x00, + 0xC0, 0xFF, 0xFF, 0x7C, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x31, 0x46, 0x7C, + 0xFC, 0x77, 0x08, 0x00, 0xE0, 0x23, 0xC6, 0x3C, 0xFC, 0x67, 0x18, 0x00, + 0xE0, 0x23, 0xE4, 0x3F, 0x1C, 0x00, 0x18, 0x00, 0xE0, 0x23, 0x60, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x03, 0x60, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x07, 0x60, 0x3C, 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, + 0xFC, 0x73, 0x18, 0x00, 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, + 0xE0, 0x87, 0x70, 0x3C, 0x1C, 0x70, 0x18, 0x00, 0xE0, 0x8F, 0x71, 0x3C, + 0x1C, 0x70, 0x18, 0x00, 0xC0, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x08, 0x00, + 0xC0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x1F, + 0x00, 0x00, 0x06, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x07, 0x00, + 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xF8, 0xFF, 0xFF, + 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + +const uint8_t activeSymbol[] PROGMEM = { + B00000000, + B00000000, + B00011000, + B00100100, + B01000010, + B01000010, + B00100100, + B00011000 +}; + +const uint8_t inactiveSymbol[] PROGMEM = { + B00000000, + B00000000, + B00000000, + B00000000, + B00011000, + B00011000, + B00000000, + B00000000 +}; diff --git a/library.json b/library.json new file mode 100644 index 0000000..f5a9cff --- /dev/null +++ b/library.json @@ -0,0 +1,34 @@ +{ + "name": "ESP8266, ESP32 and SAMD21 OLED driver for SSD1306 displays", + "version": "1.0.0", + "keywords": "ssd1306, oled, display, i2c, spi", + "description": "I2C/SPI display driver for SSD1306 OLED displays connected to ESP8266, ESP32, SAMD21", + "repository": + { + "type": "git", + "url": "https://git.xpablo.cz/xPablo.cz/OLED_SSD" + }, + "authors": + [ + { + "name": "Daniel Eichhorn, ThingPulse", + "email": "squix78@gmail.com", + "url": "https://thingpulse.com" + }, + { + "name": "Fabrice Weinberg", + "email": "fabrice@weinberg.me" + }, + { + "name": "Pavel Brychta", + "email": "pablo@xpablo.cz", + "url": "https://xpablo.cz" + } + ], + "frameworks": "arduino", + "platforms": [ + "espressif8266", + "espressif32", + "atmelsam" + ] +} diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..15d9f75 --- /dev/null +++ b/library.properties @@ -0,0 +1,9 @@ +name=ESP8266, ESP32 and SAMD21 OLED driver for SSD1306 displays +version=1.0.0 +author=ThingPulse, Fabrice Weinberg, Pavel Brychta +maintainer=xPablo.cz +sentence=I2C/SPI display driver for SSD1306 OLED displays connected to ESP8266, ESP32, SAMD21 +paragraph=The following geometries are currently supported: 128x64, 128x32, 64x48. The init sequence was inspired by Adafruit's library for the same display. +category=Display +url=https://git.xpablo.cz/xPablo.cz/OLED_SSD +architectures=esp8266,esp32,samd21 diff --git a/license b/license new file mode 100644 index 0000000..706c10f --- /dev/null +++ b/license @@ -0,0 +1,24 @@ +The MIT License (MIT) + +Copyright (c) 2016 by Daniel Eichhorn +Copyright (c) 2016 by Fabrice Weinberg + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +See more at http://blog.squix.ch diff --git a/resources/DemoFrame1.jpg b/resources/DemoFrame1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..536b570db09931ec634b38777033432276bafed8 GIT binary patch literal 16026 zcmaL8Wmp`|)-K#=7=lZJ2X_hX?t>2lgu#Lb8QcjF5gww1`=$F$fI`{N!43e_)j0ti;D5{g4}e(7 z+uF$=Km#xziuC~CeiMWEm6w;B1RtM^C$FWAtCcOUwJV&@&(e*LpZ7T*ASLVPW@+tY z>qT#6YwzG9&G@skhmqdFMw-z`SnIi#o1*P22ekkXTm1lSsC9sowYUwVtPH)BpM)RW z4Q}gYN$&@DcJY+(lVHnqT?~aq)lZ5D?&b(BSd(ck#0H<8kq1`cDl?ww~4=4sKo!t}gWd z)M#nt>g^@X_<;0(g#dTc()w@3|6^;x;s3<-FKtgRi0%J|@jq&NLjB!r`5?BQuHGKj zwh!t||1o}OyZ^VNe-t0kNGQ2ld&6yAywsJX86Qe`Z5(VQgvAwvROAJoiwP+5^YbeU ziwOuSiYxLfD5(f5Dv63J{Kr<^#na2u#oG2iwhsTbFa9wNdeKh13751tc8)2QP}s!U{t2{~!|){Rg4EilTy&pqRjOC4Ln} z5hWGIf7{yp57GVGR^8{Ug{Q5H2nVg!g|78af6B z7A6)58ykd=i-U_#Nbn$pg#S|d_X+QR<^FHG|K{#{0b(3r92mhsBL>ik(J+Y7?gxPO z2Y}cZXlM_of6Id-Osq!$HVz0E4M4;CKQBGR^3O%=M??<^Ow0#7*pDzlSP#Yz>SiTf@Y@IWRBg!eWcUVYXBp^8%*RBKfDyi!-QC(Wn__Umr zj*f=J8rq0oG>|s1gx^x53%P^CU?cvNrQqS;e3c{ZnUmji8r!QkG2! zkS)gmU#BsuS$;I|(OuY~5%Y(m?#$&?9Q`20m76)%MBNjCqfbRQTjZX)q{ zXY_ouoU2VfH}9L1TP8b?<~SZ#d3@fY^==vqc+bm1Ko-x;${b-wbH3bsT`)~`V*sf* z;S_|h2@A~)e8K`vH*#;QTdjnYklmTQ|G-i14EFj_*+gcKcdKF1`&?It{XVK<4cge#e#xhE*s8MLI^U}9*``~-*7o9aXY$66J1eO)|ReQcAVcm@3^u*-i&8bzFJd@wA4^9D{;b_lN3%QBEUR} z9Zm_$ZMGn>O-LWsNs<#+=`%MIFL7>L8FzH%m{fkbKa)XPKHVVNJvC4SZMsBsIlWhL zNzLJ0CrkU}8DhOyuQ5(Y-jPmJxDt_Hw_Xjijn|V`BxqWzZBB!FP*vmO3oU$3HUbMx zYsBnvI;0eDvI9`_CwJ&pJ!gAbUiRKtv+75bIhHl$5;?XT6H4{Uo;`{+`Dr>%e>RdtJjf1v){QVS%fvpEyLy{ z4o(!|VMx^_Ad(kF$LpnVH~yMfOeAh85i9q*TQ1p{%x}yANN?jkkS5D_EW6m&qe$%O zv?vrVanZ6jtA3qrz`2v>z=WfWI_iFEbo!I(jJ54k60TL8I>@nJ-tT~*NR4(@UAB-u z9iI7hmN_2sT3;z3xpclnk#6-)LwQqzUPm7aDkgu-0|-27CS)>!%P8f>f} zH(5_TEkxs;&!ORdPaV)XJ1aJcC6D+3$A4<}LW)cdAb#ZaaW+g=WBU&0WGflbjxg}{ zRt}t+gMMr^^;Wh)Ds5?A4|!k@p$(R8!cw@4)xz^vvb1N`MXO8viaJaVY1M44bNkW? zBdOU2lJQO$N%SC4n}y>xY5ZU1=Y|LHS$%ycIlG9Hej{vT3H?g0b_p}V=#<_UpU#HV zu7*1a@hy?jnD_$~AsT{>M|jvv7Daf8xUv81}p;`L@Po>YQ3-XYqqvO=hyh5YeBvOAOGA%i# z!U{Lnm~#%tT^wH>YFXu!DP8L{^Rb(?p^Kc3vyAch=Dn8pZ(nL};|jaI*OPAC*cduu z2klW{c|-|QScCxajP;b^kB&oaZ0VgccfTCIdWkZd6`=(as-KRlCO#cW!ba4#xLRCu z1}=^cUfUDJO$~^!3XddgeQft>vt~}0($ZoUI&zNVs*Ti6Uwmc#DF%%KH-2^9y)eG9 z(g4U|6d+c-qn7uwPtTX2-s?bjr09w|9V`**u%AO~JF^huROij^awMW{sw^^^Tv_1l!i6&9ZbkWAgr=c-jPw~xe+R;qbZ2I z^kfNJ^7xk8ip-uLhRzq%-p}uWjMCLbPWy&ELEQtq1VY>}K}XY=Zf76nY9C?o8ApG zy?P^vY(i%?_eKt7br0%DVYAu{!fpxmP7!bG8h)36yOvzTPL*E*;}-c*wHN6vRxFyeijFI{0^fqY7J4*y304ar z2L9br$te6*afC?82+uqoQP@Pvnjo&U(o(DUDfQc1Jqztc)}$uJ+|VM9lF|soTNOJ6 z2^W-QAKilfXlI9czsZ8fmWtlTdAzTa;pCS5GJ@$L6iE_j9KVEH9hEzGzt4@o_b0ch z)z$d0-5Y(1@Lc4c)EafO%eJSD;UQ_M9`(p~teC4L=dt!a;>uEKc@i1Q!O%+51k~bv zi+B|47<4ph{m~caD41$71qn7Zyu0ugM$dc$nj1dqC!oXaP(zBpzq&1pncW#_Um+;66wC=qyDnI_xkV-_ixrlNB6b`J0y|J&{TcU z2~ix#AHz9w{#|qDP%kiOIrE7lb#PoqdO9DEE>f$IEh?L*a>3Hk@K~jxCeDLIFDn^g zp8dIAS=g+du&`aFosV4-&VFr@IMY-`nUXzFSSljyBs4GKN$c~CArOBnW*QdBOZH5t zOe{u04p&!D^IIrwp=hTMJXTiEthML0S4fK)xV2jQz{D0T8$&T~ie&&-R>l`iF7}6| zYo=-fI{gtO{3AE+?H(WFXi<8ptSKgQ?T%Fx#usb$SX_dV z^P^(jTDDsi3%jo*Qi*bzZAr-{NXJ_MUfML8h9la3pGrN4%589Q>vOlg5}?EdZIA&B zdejn>IR8{KNdqa6w$x*3Znz09_;C~K)gE8R|D%?_>&wyj)US3{l&u!m1=MRA+EI4k zuurAPg9zu)ow%%yXw-8DrCga+`QL*1@S>EV7`R43&Ih z&tUi#shO+a_%oc_UBAu(@@$v<8Z%Rz$HU+|c^8ry-dmqjpIv-ShLud)d{A(o|B8GX z1!%A{#1($VnAOh9On6RO)u-fj`~z90JClZB`5QCgILx^S$!g{e&H3(Xw4Y((;&pcQ zJl}AOqc7PlSuQDKxPjT&@b@Ub&+g}!-_#`PKJUuT9-b-siQrQgJDJ9lJQAZ*ZoNt5 z^7!r}tL2lbOkC&E`FHlCSiNP7bH!c$Mg1Ue&K~Ex8q;U`QS4?yiR5os?M&GyJ=+I) zypi5a7M06u7R{AjC?`=2VaYGf&HAmr)Xr6mnJIg=SD6L@8Fa!$>Kax75L_z*51wiv zMt5hr*rT9US7@2S5rd};ojj=ERUE8d3s>>M;rdk7pGuUy^L;ctjC zx>=#N6_ot5^m-nv=IdmYzlzK&lCSVfU5-^Sa;70iP7LubUd;X&X*sNzCn~F5>wW9# zWX>Z31IIW8b#$S2gW~Yd#G~3Ig^M-C>JVTh=1qigv%CC(5yFHUKeXw`#Tt)Y&AwAX zewq8hUM25E>=!6MO&ax*l5-@@^Q#eVs8zR#=hLsLq;JSKbn`{gO64qt?+j>SWn!Fj=H@7z!Z1Npl#x5!%>&q^zCOIULHybf^pnQM#^F z8TI(sf~?oF@CX_+j>X=UAfplm2u$zDQUJe!X@d$t;h^ zQZhBX=_P{M=Fxtf^J`@%qe`yzkKg)3D~u@hIfL@ien!{@VHz5i9zsfuk-DX?3JCPN zX(%0gHDrM8Fi*qcePj=!$e>yGOR6VQ0YOBBnAlHNp*VR@U15KM$46d(tLEdm&8;HX zd-Aq$?)k@665G9}LV4>(OP2b$@y4r0B6RS%?q-iUG7~N@7Kk7N42qXP5q$c{aqVhQ zY`fcgZ#;$*1pk(Zc;l{b%%ciesL}b?pyPn~vHyU81mncVJYMwckc2 z0XGlK2{R^wK2a~0t=6gNK}WdHU@JWDuvXu3=FppZ@A{W(e!;LNe}ER z-syr|!arlU4b`JgwU6tw>vYhUbY&Q-YfW z5cO9Z1MIBR<&u56D>N&&!dok9d!4Q2h$8;jF$li^QPxL`0pGTPi<@$RH1j1CT|t*p zn!(Fb0G(NGmaj~VY~whDn7sqHbumpi-d9V68i{#u4-_=95*V}FK0c6L{mTeH5$;0u zRHIg=-b;wsEuuVvTJcvVUGNM>NhO32Wyp1ixoxu*#YHFUNB!`xz(<6OGq2+?Ti7@F z$U~p!>vIH##u)0W&&`b@Z03oz#mJGWjf7Pd+*-@$K;^Bf}Hylke_h}S)M zBN0unAvM5`o#!PEI9w4rv%d*fQ`_V&ct!sbX~!zb=oNuIzr@T4!+F+C&X7++=Fvyn zB*)7Ck9C z?jCqe__Tv_dm+Ab(d}()D!CBn*gH{jCYhzW2|Y9v4qCC_om&&Is#MTxkIH7pIKHHS zqJ>InYBXcuu|@7j S^sZpGua}NnqEmi2RAvCM;J;-omjz_X)DBFl;Mg-J3)G|w! zQ6vF8pf(2iq?2p;fv5<>$YTj#1!EsUP>#~btyPQboyuR^{^pkQ1bs)makdjmv514Eo%_OG11<<>3`bu2>`{5A<) z*eEjg0YmEdK=ue|-MQU{yThn{fqLhkLA7leVnKfN=)ItsP@wo*Mt1iHKXmE3e9X># zV4YSJY=?CBm~^*H zSQ=Ae2F0O-<}UBZx8vmkZ#5SLy1{cOz+7yJu+v_au)+o90^_0LgOr7i(MjC)QQ}HG zxKBJE$$XDW5@Y}d(LtCr&zTyCbTh`>08Cr_mrp+`%B@xljUk)6Myb|qJ0fY+Ip}CX zK%A1c?!Fs2X;ub7qwZ3OLIQ(wT@u5om1ZFqw4fl}Y$dfQd7)2uka|41r0Dwo~b>J2HqCk^9Kn?aI@+Vk-+LL6O^2?FsT{!Xj@B#1`= z?_k%k=FD=sn*j0Li=(64iSY~&_24^uqcu*4eFx;ioica^rP=bfgaa%9phYvE#P>gL z3W!J4o{3kj??2{WU5_l!A^%esP~Elv*Sc$AQS)f9`OKuPq3keii!71E0a8p>AeT&L z(9d3w@%t(K6Zm=czE^yb#lhjGj=%O0Yp_#ALK#8B_C3&=(4*Mg@@-drMuppJ!ew$d zxXp#|X?9hMKg>~on?cs!-&v4KToMH1dd%#Q2j?MK<~^^VXOTWXI;R%f7hrsbEAI`) zLI;J-Tr1$tAIGC72}Hi)s?&xkXRj|5R#J(bIla52dSTWlYM338kYORKscVm-3k;zx z^*U*Xh`*YZp-l?+_yXrA#|xA!lF%y;OgQ-=E zD*B<)94oubSg<5D%H6*~A~-(d#$+3V{^|2gy1122r%o2d%;`x(`kiYgRB-5DgZZnq z9>unR&Nhn`yM2{sMJOSB27~iMSg2|yA9~m%1%i->6`X{rU>|H09m%Ibx6-k7kupOk z=}@_tM-ag(>NGKBUNRb>>!b{x{?v4CF}>uwD1V1@URlst{1Z1|ta{tO6s#OKUc}8p z#)~2F>y@)wds^zVNd8!lHPkPu*dHOSVN8yE2P6oa#RJE%ioR9v$_-(;RQYdC=cO4(Oa)NT9SX8N3`H$ylmD zC-Ld6e`WLXo=QH+E^I$B-`lrvANv-p8XE37+v)E5y^^)(00j%2=D&Nf)I}W-Uz@-7 zB))CQhxfwuxMtCw{V>O_BO9YEbB0Qx9Vw6;I_CKZ6i{n3e0EX>!buyczGi1Uc2gZ=j0-4Iqgbu zYqihY0qLOOtCN=S7Oe!W*Zc@%5}x$BS*@(u_o-<}4i`EfSrj0Dv26)Xag@*(42=Y94RX^1d% zdmT7S9wRd|D+J~_%J63rix1|@)7fOcN7A8U&CDFlr$5%H>p`L_>{-}znFrs|qb1-t z0@prcbZD^yje>VXJ3uZYThszA6Yq69&RlrHeu^;R7wT)L2}s+yG;mH`$76Ck_e|T_ zH~H+<>$A$WvmKVciYG=dmge$pa8abk2?iG>(WqMUgn5d6b2_`CKN)*>V_a;k^N|LW zlWf{T1|gqss4ooWbLPLmi<(<&mQB2YV+q*f$(+k9ePN;ahQmr+w*n0ZeP^IJo7Ig~ zZ+9cgCy;iL)$gk59)LH^&Z|Q*J-2&Ne|p+?E)Splv>r}wIyNzGj(AY0`n1y%h2}RBfdLo1_cs(m%dYlS|W=hGRdFC;RsK1nlK2ht< zprD0s&^0cy6=;G{(cHIZyXic>PdmUbnl#2zP^>A{eoZ<0qB-sJX8RwdrRQCb*5+>6 zv<_N>M!h<@JVez>Klf|RiOrb!@qN%pz=ql-J(t{S(XksEJU$t!PmnxV)o;hW(<)x$ z0JA`|A+T%HMhA-`lHFA-S*n3>PlWD{vywte3Xi#m}a&*^KhN- z#)xEU?$JH)>|MR;IK{AIDN^P&A>WUnbnI{NG#A6m*;H5%t&Ge}S;vnM1?tpW;gnLS zWRKTRlalof9r+gIQ&^;Id1#-d z8&%`_{=97eq)Kd_IyBGJ?^A)4ezmf>flb|~4D2&#IJ%q_pN7(C6LBCH zxuLqrJgA7lTlug~hq2D*-HJ9SlSad3hHe0NJ zsm0vX3=Ov9cG$~_rm%0z*+wkLl&Gbz1cC@5T`?ap@K{RKhDEMUq)RnbF_nWtAZ-*H zdJjCm{N!%Pd}#t<7L6fUa}of`#wSWhC(2Ksr~OTSU0bQp2#pR8K*&GSapnYi)huy= zWVehw8?{9Al!0ybRGjNa>XbqJ9)yr5>JY90v?=#5TMo>+oxSHhXX{JQjceYpBtpj7oH@$er=Z87SLdseR4VOB&vonY7EzEA~Gm@f!Mj@4JJH5V6snoapOacKVW+{vwHf4js?YX9rz>pgH}um9VICQ#zt z_KpQE`G)FEWmAXccc0nzTCEjd#_A_GWqHdN21294;kTV}B_$$XjR*LkF$8+e8=dgg zpCj3fyO^u5_hotLn``nW`hMi}EwI@*{K%dw*-3#dm@d=~hfdLoT`1Q}>>fNWNQ3vx zIEiYm)?09K9lD&Crg9;5#&bc=$V?yRB*xcD+wA)SlEM>scxBwt>l-f768n3wQ#+lt zo8K>HQY(F|A4j*+%J9CIze28{f({q&0VNKOisdS0ffkgjhhb`1`D)HT40pE;I~ak zk-cbj#E#Ng>=cS8CwId_bV?O|VZY`S4!KsQGwW6zKlG`_4ehYGc3p&+ZqWy zy8Xq#skI5Y4rO4Wm(s9iB{=2*YiQC31A+WC^}ay1}NJqYd3NPuEb_1xuD0W?I14}thA zF}B!#uESE?vZC_=1RkFvDIq)C0j`S@k7XmxYmrg&1NVRqh;uO=m(R7WI{Y_tJ<>@4 zpBdRLob07>02`}a`huc-fsYJuml6&#O%zSSqx2hf1z(YbpZv30yB8?{DSJ(c-6l@m=>uxlG%d zB$U35$Y~XyZbSEvPk(|olf)b+rnw#KD;poIcFSGHz7o4D3~rf!8ZPlm%;g@q{?XZV z)au>$ye8VP`d2`$Zx3?VJ1@0mCJ5Ihui{EY*Mq=>!eX}Md^qqPI7bSrTi1GRT#8%V z1NdScL-)YYv%8p%+ux2})9_VdEw2k6^_F9>v&5uu5D&TFE-nj$C9e?!OdS&gVO;;a z^#PuGCexhpAYI)<^P+c~o&Lf=_=eTUJukm@_`yOyJy@|?g_s%Fab#*9Q z)10kZG2CS^;cbK7#)fk!q33TQ5E+)+qs&2xkQCD+DTRT#W|H) z(C)35X?LuZ>8La#Q~?TOMyeX|E0UDM5p&+&HW{9=WxG&i0u{lLfjvK)&>xZPEiB4H zyQD))YrPKqY^9=ZFXM?W;Bn4GESCe_Srj|8Vl-RxUD#c!KctF@cz#%5U8~jZYz@RIbPvQ!6X**zax{zi+dhRZl1)1Wu>CH9YgD)7uFc;H zo<9xC^r7xrNnFVY0y9h99#v~$Lo(hmAN0BR+y5nWIoybJXQ{T9F(V0B+)$WI82RNc z)h=>pa9gBw{R_tX?16rFb^$h4$%VByUAF#0M;z-K!Is*5U~p4`R6SA!f-V+*o!|xM zQ?3p8`%U*A;5a&mYqhk)Q-iVz=nr-FkWD|%RT7G_;Ha+Ag&Bju9;W1Rt_5!fp=v(; z6g3h(m|U)k-m>Li!pAy3@OkAM%j%H1>(`XwfoD?L6{=6x$4(I!PRnE~*FEl=KcP31 zogFzHwbVV{=5!tFH9ylU99N;cQi-9-x=HkiSfE$cHl$sVWYu}egn_)!VwkQr!-TM@ zqJ1^6jK}1)35Nu#XgWm{M6qWbHF50GJ~(&y!%BsQ9On@&C##+Nu=$9GZ~-npw5n}L zs`!N(*mFC~AcaMZG=WlysqZ9=jC&K{qj-rf=Jw{X;wym?F_Z%rI9mO&16Kcg)i*zK zpQCCO79@UAvq3US?Y6FUxBIf)by;7nSiP+4K10t_rD46b)&m#%||Eg(g=u zw^Iq$=Qp#zBnQDyZjamY=cRchJ@%kbiQ30-M!)i5op*0)KCNaW;KT1vcarxu6sbie z#Ll5EI&Uqe3pL)mDtX1Z?j9XTB$Pi{&*5+8IBqqmrf#0QilG`ZYbq$k%l&5bb^L+N zWXX28p9OW}lW80AVZL3q^%4@LB}Vs-JrkUPJOqi;TUrgtzx}T(U1_wM(AO zZ|F#?e~TrQOe3q4U^ayF{uyEjDA>W(kNWlr8e1zqoH{&M2&(l3ky$|l+csf(L zm0P(EYh5egM84X(*!;5)+r+yb5u{`+;aF3(Cc<9$F#iw@4ETQJ-St?R6!};&BD~Nxr_x#EuD^6CLo$QdxnA5c6kgDoc#j#rgB4yrTycAC7V2%9eKQsNucg70-Fi%5UUCwzmCW$XuR;VQN`g z7gt|5mSc@IZqf&)Fi2o^hoF`)vy|N?WH^?))YNKK;2WKdKs}|qVq-`ZlaAQP%Ot@k zMxJ@Nsog`gI31nuk5kF3l2w>ZeRQIjG#$qv|WF~i=@$7+WXuJoEvOn$?W;^zx1!B)b*7V<%o{s@%gsL-t>8!V-;CxLHwpWH zM|*r|)0RV)_M5z9T~Mxl(ocbsu3(R!%cN?wepIyx}oq3vr zmn73_i=Fq^k#|$-U=G3b0K%;#^j3t6pyJ7R6?Hq-fMq8A_oFX4b6NOoEGExs2x_9jnvt z$W1P5_sK<;V5s&5rrhu_jxfF)*8OIpx9DPt1R0)wPr4o_-bx=bO&)Y+esUOULRBH> z6UKc#;WsI|4$Rf%ER=T|IvW(_E?zk#a3dJiBZx%xem{~fwM)t9DDGE?lMUp{@{db+ z{Z9G!7cH{dzsp-bn{a3+>TV-(%Z=w6ax|Eeus&*zQ~Dk6z}x*-OS4i^jWQ4f0stUCrg>)iMpFe!2RGLA4JQQA z^PuLbN4e=qfwtqq{WhjQLUOEI$=9pKe0O_x(e&tL9 zaDKpOQ?*_d;2FDp9f!w78utO|uC{;N?fO&e>EHBoUso@C>-iVHgKyU#>0e2k*fyIw zP712)s_(T|JyMLpoyo=_iAnc(RU>X1Tey+T5%k!c_kDjBm*sLtX{-ED^nAOKXAQy> zc`Od;yJ%XketWj{#X(r}eO6p_wa{)aEeEo@LSM&W zrn|cKZ^lpRet3eWAr*>lHork=@b}6W-Bbh9_DV<&sKR|Pp_Ahgy_x_qufcCFp-wUI z-jN6-Mp{U%1a&l3-8RPg{?MW0SAeJzRGLIblQSTv(cz{aa`#O8sk`&>K}E2GyO2X> z8tLv#nG^(cvK>#H_s)j^QY{J(bUHuYg)F*VSUa{6yS3mTJT z2P3Tw1F2WK6%%)Q!|GY1pm8D{oY4AxO0id8Gx{k?eKr9!ZdHOMc0i|__zjb63(@01 z$IsFh2D`fbYWnbEWD}>{Xt7^3^Q4NW^eOprc}1fR!E8HE{TA5UmY4AmOzT~??h?-6 zXv+!aht(%XM=pCOptUD1OBi;L6+g^q*|a0vb~7U>=?frfVk+Id@NwR{6lMRF*tUv< zSufAa5k#8AgiW8s=B3kUTrle==ljJcHZjzVo#dqMo5tvjdoKT5Z1UbJ07?NAYv zj-kXM{2t)Jg+)=gVGd^H{9@ek8Ph7+QY6^0!yn^U??G#*Y0gg7kBP*RKs+h+u9Vj$ znJ@LouFEzETKT(3&YH5LU2oaxGjA{vub&w^B{n444q5m-;;kl#Z9bCubkz^v4N1?N zibjP|fex7g#g(k_i5;!(e=fQFTY7SaTf?rysq>z@T$jPyR8!$+i|i{iJAE-F z-b30Z^i2WM4-<;Cn?BJ_^n3E#!~umzKvk~T0PoieVn)xKLhMlzAj5qVj|TJa2YETR zPBEvKPpGgpKLArBa5=FFP~fIjZ&QnBLHNg#Ux0?ot6fSGWU*StrMyqvlPdMW@6NO@ zEi2%kw3m&uns_)=wG#aSQ*eO*rG3IY>D&ZCjL%%imWk5o zTs7n-OpDy;v)pJAI8??xZ2WCZr48nR|fcl!9oM2=qh8*|2&gC`04(SnrlYsV6lo{cZ~BT|8S+tZHX`^zMMMIM zIZg=nAd&KByXY6GmlsOK_E74jI)Ql5ct%|=zS-pC{TqPSMi~{y%8s3}!<@>f;%|vi z8m13#C6FMXu`KF4OCNmbyI0tFH6frIdZ46C)?Kw}jH;Id{@TRo^GiTT{5Gav3Qq_C zneG-(M-VN%(c@`@vW8m);z^@9Iai39mm|RsE2`0LE5rT5z;jt=W$(}J2~-WL6*`8C z<__5%{x(p~I5dtDPIj;Y0$?$ClYG+E*a;lzZDBZE1KzeoSp})v0fvP0Tbf6d*P(fhI8G^;;rQjGPM~X3facy_s7LnbB4Stq3>{D z#4k01d7$k}vFgsEPY2mvAwPH|TSA%MF8mplig6i^)f{HFW}l56aFYAo8;}ec|1nG< z-)}#$dqYng^~^>0ChE~85n9TCHW^xWgUk}p_b^HUk2iof2eL}&8Bzs6Um)hgVCVAu z4cV17{>w*=vGkOJ5n{a<;bP4qGoTa3098CqfXF)Gfi_>s>HZSEk+lnT!g8r5I|4cC zM;K?kOcH+P7MlM=x6lb2oCj0Ss-S|{B2w~ZNfj_mcxc--ceNru6oB*x7oq96Z-FF? zx(Q{czlILhivDdETZ_8ud--s(aM)3~r-nKkt)n_KYfzFk^>?N*@1*I&{3>&8_IlX`L!VQcP!5bnDeM<(6QR@oWUwqPighPSWyNM;&n@S`1 zGYn|EBLeExPvR%ofJcgsY#an5a?C9)WethrhVsSFlNrMb0&MjhZ_ZgUF| zTj5yqbtN8T)qMd9g`VP&qI()2^QWg?P%lAH#I)Z!YCEk?jvjMVmz0;6f-5X4ki1e` zX@%Zc%wJ=lYi{jv#%|6{kFHVbeIKb5HR^a*ed|e3_=9ubtjsQFf!f%nov~~NsRNTs z-0?eX(ZZVE)&7Yo_?p)V*KKvZ; z0tQD_qcN)?O%r8j7~1L$M#3|97mgr?g@^dacbf{I(_(aji$k*+=VKY3x)+8jFnSNfl4A(_PV~(I zxo%LjJPJ7hH?)*tx(C7yw*YMH8O3|r1p^W1$w;~%GHv$6pQNg(Vw$Ahu!S;%1`tHL z5PiHn`CJI>Wqw#SEiF3)S}L`oevL6AC-8HMiU)sc&ADY!y#gL_KnKmU48Zc2_K zNEuu_(t7k>Pq*uQ=<7liV)v8Q8_;yv$%tY~EjCl!Bf_59Oha(aesds>ubM-@HvqYRUmVv79TyZWhr+zN0K*LH{`Gwscx38i? z$6=y7^`d??2Z#(#j}GJ}+rJqXYm6?I-ql>HzVQ;02pB-MtbrY{V>)9ljG$~=8X#!m zk`Z7KeH7)YK4#u0CS7-#DfoWQK3;4akHJ|7N4Ju>`X`5m0cW(nD{~y@*h@{tSuz{s zTcuEhb_TV){g2@=CaYp;6I_=Juy0>ujQ)_>sd1M&yK=@hw~{!X01YrsXd{x3DTen3 z?G4^P+hIr}0s20E)moAzoX=7YSYR6YP5dYv$4m%tZRhzj`g5PkhURR^aNZoHja53r=WFZgS{!LCAxRLj;tZdcFKIGbAubXZv*M~o zu-zci9Z#eMimOcH3@r1W1ruu#R z3z~)Mcq4swt&U6wiDb4vq_UcZ6^fUly|I!e?vEhDqg?HW*D$=Q@=Ym#bc`kf{zR*^ zX1bkQ!K11uXjKqv~Ni;1TsQdnqM zOst7Jn?VJ&L?+8%zT}s%Q5vi$7HAeJK2YfUD8;I)%l0FiM4?nwQu7d(!^APMm)#0a zfsADQ5)VzmaD8@K48c-JVq@5tmS|_GTBv+3>(kMwtogX6R)b@PEp|_v2Gg{a1!q1< z-Nj4QbooP3Q9)^ua=nvFT$2!aG$%++bH1NuJ2%rs>v+q1p;m=oZ|Ph)YtGv_t8}@l zIheVjVAz2S#amGcdH30YN{A49)lJLWnXWAZ4TD|K#vwks+=4*YDvFG_`|fh^Fz5W9K@dJ%3T z?1JnVY^#iWcrD!u5Bmkuld`iM+foo(rYl|bx8*5D3Z7hMd-9W&=~+|ZQo~^+sT|3P z1z{sY4A11T8V`>ccfK~~Q--}!qY+b7btn4VL>DTi^|XTzuqm6U4n z5AJ1=6A|}7nZMWc33GFf)IE?He08!d>xz>aICh-3{S*1r;H=yK9{7FU3_9y}FZ#o9 zbNwe~8XlrEq4$h;$FHaC;lm5xZB6Z8S*R?`^EXD>^`8;avni{lzogmsz}WAPXMd#_ zf*B=35+;)C{Ry9U$wml!Onm#rV|+TldBYIQRHQ?g!De>0?zVWX@jIB0|Chyu%!o@j zqr>JemP4t8QPh{~$G^E|i}s{`?pYUEp!(UZs{Q{&({kJd+X@Wz2>s+r<>C6P%BNWz zOy^5jqbDf1)O(oHeh&yzem@ew2fW1H$aMF=ab=Xr{_;K;Pv9g`c&9hAP%UHbr)_TK zA3{e&Z>8nIYQI|&cHy5;^Wu(Z6XY0@I!UvE0IUAK2gK7tez-@ig~X6l_`M!|8mwB@ zf9<4m63md^W5`d}Elclp@;h_Q0+F}+``O^xUbG{)3p)FFTs8H2g6(oZur^_&(`|s?1i?eC5tG|*wD&`h@f2!^Q`wkw?>p!u}5C0?CnB?)@s(=9*Fr}+;!upq?x3 vza8WuwfHl5ScD<{<80$Yf7prM1LT`$zwQCc)9Fq_(wNFfLG@GF`{n-+$Y8wi literal 0 HcmV?d00001 diff --git a/resources/DemoFrame2.jpg b/resources/DemoFrame2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8dccbcd0210b5c1dd7bad824982c1ecbf5c1edc2 GIT binary patch literal 19502 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 C1xwrj literal 0 HcmV?d00001 diff --git a/resources/DemoFrame4.jpg b/resources/DemoFrame4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..99cbe1bc41ce7fe01700f5cd00bf04da68f9602a GIT binary patch literal 25325 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 EUrx=8H~;_u literal 0 HcmV?d00001 diff --git a/resources/SPI_version.jpg b/resources/SPI_version.jpg new file mode 100644 index 0000000000000000000000000000000000000000..115c9f3bccef1177204c88ef8b8cb8f22daa9e7c GIT binary patch literal 26912 zcmeFXXH*nj^Do*1NDw6FETBl193&Y?A|N0+j3i;mISGt{pk&EP6af(hM#&k;nUO4U zfFTG7%z(fM1KjpW@Bf~4KHT?yxNF^Yp54>a)wOGfs@~yO)qVc$d=a3&tFEOEKp+r6 z6Fh+PC8lh(K-ePy(9r<|0RSKcC;=|u0!Tr?n|25lKmgLjAl(n4{(~k1>8}u4fbb6) zFb5+3kIW22;t!f0lvyO8`%4C_={XD_`m4^LFRuJeGhQo{_@gZ_kLg~a7~cKy+O~Li{D+-<><|WZTbZ!#lPZBAqzuE#dNhbS?2BA*!#eZZ*lj;B9gP4hSCOPDHTZHN$ zy_}r%M;{2qL7kJ6|3km|yU*g+ufKu(RVRp`-Vpqa!zjMIA^e*rd-;~>FBwqxfo6qg`AKZ4){Xe*k+&kE%2`e{H3oL_zsiAcFag@tnZ>ZZPL>ncqn6 zZ@LMLi2Y4Bg3^D}5HJ>X5iASF#t210?q7Te9T-*nTL$dWKlJaI7+~w^3iI*3eqE1- z0MG^Q0k;5szyL4@OaTzZg559%x`1!M6mSF#0y^NK0XzWnT>)<(1n>cz!7_$GFMtAY z01~9k0TVzOFai<*UqA`C21o(Y057Q2Hn0KA0v3Qh@DPvzB!C>CAC$TWo@Kx|kOt;n zfE)uIkTF0WETsZ;0z+UKE`SpV1P*~*@WcS8z!N|jatERc2mmX<87RXIN(ce3foSmV z2s|hu;eZIh1h4>a05re{I08jrJ{Ry9xCEhv5JM6m7LZ6V_ZnFHEZDC~@Lv$%0D=KB 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 Vmt>cr&zI7iF#5{vw(shH|JlZ6us8q! literal 0 HcmV?d00001 diff --git a/resources/glyphEditor.html b/resources/glyphEditor.html new file mode 100644 index 0000000..31fbd90 --- /dev/null +++ b/resources/glyphEditor.html @@ -0,0 +1,664 @@ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
Font array name: +
First char code:
Width:
Height:
+ + + + +
+
+
+
+
+

+ +
+
+ +
+
+
+
+ + + diff --git a/resources/glyphEditor.png b/resources/glyphEditor.png new file mode 100644 index 0000000000000000000000000000000000000000..800efc56f4bd50ba347eab57f3205ec8d0c0dd31 GIT binary patch literal 68751 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 M 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℞9m-8fv#DxWbiNUN1>5} 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 V=l%V&;(J^#ke61GDt>7i_#ZiQOU?iQ literal 0 HcmV?d00001 diff --git a/resources/xbmPreview.png b/resources/xbmPreview.png new file mode 100644 index 0000000000000000000000000000000000000000..70ea3a53a843f220f18d2ef7cc0698516a990ba6 GIT binary patch literal 41692 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 literal 0 HcmV?d00001 diff --git a/src/OLEDDisplay.cpp b/src/OLEDDisplay.cpp new file mode 100644 index 0000000..409c97a --- /dev/null +++ b/src/OLEDDisplay.cpp @@ -0,0 +1,1082 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + + /* + * TODO Helmut + * - test/finish dislplay.printf() on mbed-os + * - Finish _putc with drawLogBuffer when running display + */ + +#include "OLEDDisplay.h" + +OLEDDisplay::OLEDDisplay() { + + displayWidth = 128; + displayHeight = 64; + displayBufferSize = displayWidth * displayHeight / 8; + color = WHITE; + geometry = GEOMETRY_128_64; + textAlignment = TEXT_ALIGN_LEFT; + fontData = ArialMT_Plain_10; + fontTableLookupFunction = DefaultFontTableLookup; + buffer = NULL; +#ifdef OLEDDISPLAY_DOUBLE_BUFFER + buffer_back = NULL; +#endif +} + +OLEDDisplay::~OLEDDisplay() { + end(); +} + +bool OLEDDisplay::allocateBuffer() { + + logBufferSize = 0; + logBufferFilled = 0; + logBufferLine = 0; + logBufferMaxLines = 0; + logBuffer = NULL; + + if (!this->connect()) { + DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n"); + return false; + } + + if(this->buffer==NULL) { + this->buffer = (uint8_t*) malloc((sizeof(uint8_t) * displayBufferSize) + getBufferOffset()); + this->buffer += getBufferOffset(); + + if(!this->buffer) { + DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n"); + return false; + } + } + + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + if(this->buffer_back==NULL) { + this->buffer_back = (uint8_t*) malloc((sizeof(uint8_t) * displayBufferSize) + getBufferOffset()); + this->buffer_back += getBufferOffset(); + + if(!this->buffer_back) { + DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n"); + free(this->buffer - getBufferOffset()); + return false; + } + } + #endif + + return true; +} + +bool OLEDDisplay::init() { + + if(!allocateBuffer()) { + return false; + } + + sendInitCommands(); + resetDisplay(); + + return true; +} + +void OLEDDisplay::end() { + if (this->buffer) { free(this->buffer - getBufferOffset()); this->buffer = NULL; } + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + if (this->buffer_back) { free(this->buffer_back - getBufferOffset()); this->buffer_back = NULL; } + #endif + if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; } +} + +void OLEDDisplay::resetDisplay(void) { + clear(); + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + memset(buffer_back, 1, displayBufferSize); + #endif + display(); +} + +void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) { + this->color = color; +} + +OLEDDISPLAY_COLOR OLEDDisplay::getColor() { + return this->color; +} + +void OLEDDisplay::setPixel(int16_t x, int16_t y) { + if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) { + switch (color) { + case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break; + case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break; + case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break; + } + } +} + +void OLEDDisplay::setPixelColor(int16_t x, int16_t y, OLEDDISPLAY_COLOR color) { + if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) { + switch (color) { + case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break; + case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break; + case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break; + } + } +} + +void OLEDDisplay::clearPixel(int16_t x, int16_t y) { + if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) { + switch (color) { + case BLACK: buffer[x + (y >> 3) * this->width()] |= (1 << (y & 7)); break; + case WHITE: buffer[x + (y >> 3) * this->width()] &= ~(1 << (y & 7)); break; + case INVERSE: buffer[x + (y >> 3) * this->width()] ^= (1 << (y & 7)); break; + } + } +} + + +// Bresenham's algorithm - thx wikipedia and Adafruit_GFX +void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { + int16_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + _swap_int16_t(x0, y0); + _swap_int16_t(x1, y1); + } + + if (x0 > x1) { + _swap_int16_t(x0, x1); + _swap_int16_t(y0, y1); + } + + int16_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int16_t err = dx / 2; + int16_t ystep; + + if (y0 < y1) { + ystep = 1; + } else { + ystep = -1; + } + + for (; x0<=x1; x0++) { + if (steep) { + setPixel(y0, x0); + } else { + setPixel(x0, y0); + } + err -= dy; + if (err < 0) { + y0 += ystep; + err += dx; + } + } +} + +void OLEDDisplay::drawRect(int16_t x, int16_t y, int16_t width, int16_t height) { + drawHorizontalLine(x, y, width); + drawVerticalLine(x, y, height); + drawVerticalLine(x + width - 1, y, height); + drawHorizontalLine(x, y + height - 1, width); +} + +void OLEDDisplay::fillRect(int16_t xMove, int16_t yMove, int16_t width, int16_t height) { + for (int16_t x = xMove; x < xMove + width; x++) { + drawVerticalLine(x, yMove, height); + } +} + +void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) { + int16_t x = 0, y = radius; + int16_t dp = 1 - radius; + do { + if (dp < 0) + dp = dp + (x++) * 2 + 3; + else + dp = dp + (x++) * 2 - (y--) * 2 + 5; + + setPixel(x0 + x, y0 + y); //For the 8 octants + setPixel(x0 - x, y0 + y); + setPixel(x0 + x, y0 - y); + setPixel(x0 - x, y0 - y); + setPixel(x0 + y, y0 + x); + setPixel(x0 - y, y0 + x); + setPixel(x0 + y, y0 - x); + setPixel(x0 - y, y0 - x); + + } while (x < y); + + setPixel(x0 + radius, y0); + setPixel(x0, y0 + radius); + setPixel(x0 - radius, y0); + setPixel(x0, y0 - radius); +} + +void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads) { + int16_t x = 0, y = radius; + int16_t dp = 1 - radius; + while (x < y) { + if (dp < 0) + dp = dp + (x++) * 2 + 3; + else + dp = dp + (x++) * 2 - (y--) * 2 + 5; + if (quads & 0x1) { + setPixel(x0 + x, y0 - y); + setPixel(x0 + y, y0 - x); + } + if (quads & 0x2) { + setPixel(x0 - y, y0 - x); + setPixel(x0 - x, y0 - y); + } + if (quads & 0x4) { + setPixel(x0 - y, y0 + x); + setPixel(x0 - x, y0 + y); + } + if (quads & 0x8) { + setPixel(x0 + x, y0 + y); + setPixel(x0 + y, y0 + x); + } + } + if (quads & 0x1 && quads & 0x8) { + setPixel(x0 + radius, y0); + } + if (quads & 0x4 && quads & 0x8) { + setPixel(x0, y0 + radius); + } + if (quads & 0x2 && quads & 0x4) { + setPixel(x0 - radius, y0); + } + if (quads & 0x1 && quads & 0x2) { + setPixel(x0, y0 - radius); + } +} + + +void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) { + int16_t x = 0, y = radius; + int16_t dp = 1 - radius; + do { + if (dp < 0) + dp = dp + (x++) * 2 + 3; + else + dp = dp + (x++) * 2 - (y--) * 2 + 5; + + drawHorizontalLine(x0 - x, y0 - y, 2*x); + drawHorizontalLine(x0 - x, y0 + y, 2*x); + drawHorizontalLine(x0 - y, y0 - x, 2*y); + drawHorizontalLine(x0 - y, y0 + x, 2*y); + + + } while (x < y); + drawHorizontalLine(x0 - radius, y0, 2 * radius); + +} + +void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) { + if (y < 0 || y >= this->height()) { return; } + + if (x < 0) { + length += x; + x = 0; + } + + if ( (x + length) > this->width()) { + length = (this->width() - x); + } + + if (length <= 0) { return; } + + uint8_t * bufferPtr = buffer; + bufferPtr += (y >> 3) * this->width(); + bufferPtr += x; + + uint8_t drawBit = 1 << (y & 7); + + switch (color) { + case WHITE: while (length--) { + *bufferPtr++ |= drawBit; + }; break; + case BLACK: drawBit = ~drawBit; while (length--) { + *bufferPtr++ &= drawBit; + }; break; + case INVERSE: while (length--) { + *bufferPtr++ ^= drawBit; + }; break; + } +} + +void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) { + if (x < 0 || x >= this->width()) return; + + if (y < 0) { + length += y; + y = 0; + } + + if ( (y + length) > this->height()) { + length = (this->height() - y); + } + + if (length <= 0) return; + + + uint8_t yOffset = y & 7; + uint8_t drawBit; + uint8_t *bufferPtr = buffer; + + bufferPtr += (y >> 3) * this->width(); + bufferPtr += x; + + if (yOffset) { + yOffset = 8 - yOffset; + drawBit = ~(0xFF >> (yOffset)); + + if (length < yOffset) { + drawBit &= (0xFF >> (yOffset - length)); + } + + switch (color) { + case WHITE: *bufferPtr |= drawBit; break; + case BLACK: *bufferPtr &= ~drawBit; break; + case INVERSE: *bufferPtr ^= drawBit; break; + } + + if (length < yOffset) return; + + length -= yOffset; + bufferPtr += this->width(); + } + + if (length >= 8) { + switch (color) { + case WHITE: + case BLACK: + drawBit = (color == WHITE) ? 0xFF : 0x00; + do { + *bufferPtr = drawBit; + bufferPtr += this->width(); + length -= 8; + } while (length >= 8); + break; + case INVERSE: + do { + *bufferPtr = ~(*bufferPtr); + bufferPtr += this->width(); + length -= 8; + } while (length >= 8); + break; + } + } + + if (length > 0) { + drawBit = (1 << (length & 7)) - 1; + switch (color) { + case WHITE: *bufferPtr |= drawBit; break; + case BLACK: *bufferPtr &= ~drawBit; break; + case INVERSE: *bufferPtr ^= drawBit; break; + } + } +} + +void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress) { + uint16_t radius = height / 2; + uint16_t xRadius = x + radius; + uint16_t yRadius = y + radius; + uint16_t doubleRadius = 2 * radius; + uint16_t innerRadius = radius - 2; + + setColor(WHITE); + drawCircleQuads(xRadius, yRadius, radius, 0b00000110); + drawHorizontalLine(xRadius, y, width - doubleRadius + 1); + drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1); + drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001); + + uint16_t maxProgressWidth = (width - doubleRadius + 1) * progress / 100; + + fillCircle(xRadius, yRadius, innerRadius); + fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3); + fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius); +} + +void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *image) { + drawInternal(xMove, yMove, width, height, image, 0, 0); +} + +void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) { + int16_t widthInXbm = (width + 7) / 8; + uint8_t data = 0; + + for(int16_t y = 0; y < height; y++) { + for(int16_t x = 0; x < width; x++ ) { + if (x & 7) { + data >>= 1; // Move a bit + } else { // Read new data every 8 bit + data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm); + } + // if there is a bit draw it + if (data & 0x01) { + setPixel(xMove + x, yMove + y); + } + } + } +} + +void OLEDDisplay::drawIco16x16(int16_t xMove, int16_t yMove, const char *ico, bool inverse) { + uint16_t data; + + for(int16_t y = 0; y < 16; y++) { + data = pgm_read_byte(ico + (y << 1)) + (pgm_read_byte(ico + (y << 1) + 1) << 8); + for(int16_t x = 0; x < 16; x++ ) { + if ((data & 0x01) ^ inverse) { + setPixelColor(xMove + x, yMove + y, WHITE); + } else { + setPixelColor(xMove + x, yMove + y, BLACK); + } + data >>= 1; // Move a bit + } + } +} + +void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth) { + uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS); + uint8_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); + uint16_t sizeOfJumpTable = pgm_read_byte(fontData + CHAR_NUM_POS) * JUMPTABLE_BYTES; + + uint16_t cursorX = 0; + uint16_t cursorY = 0; + + switch (textAlignment) { + case TEXT_ALIGN_CENTER_BOTH: + yMove -= textHeight >> 1; + // Fallthrough + case TEXT_ALIGN_CENTER: + xMove -= textWidth >> 1; // divide by 2 + break; + case TEXT_ALIGN_RIGHT: + xMove -= textWidth; + break; + case TEXT_ALIGN_LEFT: + break; + } + + // Don't draw anything if it is not on the screen. + if (xMove + textWidth < 0 || xMove > this->width() ) {return;} + if (yMove + textHeight < 0 || yMove > this->width() ) {return;} + + for (uint16_t j = 0; j < textLength; j++) { + int16_t xPos = xMove + cursorX; + int16_t yPos = yMove + cursorY; + + uint8_t code = text[j]; + if (code >= firstChar) { + uint8_t charCode = code - firstChar; + + // 4 Bytes per char code + uint8_t msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress + uint8_t lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB); // LSB / + uint8_t charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE); // Size + uint8_t currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Width + + // Test if the char is drawable + if (!(msbJumpToChar == 255 && lsbJumpToChar == 255)) { + // Get the position of the char data + uint16_t charDataPosition = JUMPTABLE_START + sizeOfJumpTable + ((msbJumpToChar << 8) + lsbJumpToChar); + drawInternal(xPos, yPos, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize); + } + + cursorX += currentCharWidth; + } + } +} + + +void OLEDDisplay::drawString(int16_t xMove, int16_t yMove, const String &strUser) { + uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); + + // char* text must be freed! + char* text = utf8ascii(strUser); + + uint16_t yOffset = 0; + // If the string should be centered vertically too + // we need to now how heigh the string is. + if (textAlignment == TEXT_ALIGN_CENTER_BOTH) { + uint16_t lb = 0; + // Find number of linebreaks in text + for (uint16_t i=0;text[i] != 0; i++) { + lb += (text[i] == 10); + } + // Calculate center + yOffset = (lb * lineHeight) / 2; + } + + uint16_t line = 0; + char* textPart = strtok(text,"\n"); + while (textPart != NULL) { + uint16_t length = strlen(textPart); + drawStringInternal(xMove, yMove - yOffset + (line++) * lineHeight, textPart, length, getStringWidth(textPart, length)); + textPart = strtok(NULL, "\n"); + } + free(text); +} + +void OLEDDisplay::drawStringMaxWidth(int16_t xMove, int16_t yMove, uint16_t maxLineWidth, const String &strUser) { + uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); + uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); + + char* text = utf8ascii(strUser); + + uint16_t length = strlen(text); + uint16_t lastDrawnPos = 0; + uint16_t lineNumber = 0; + uint16_t strWidth = 0; + + uint16_t preferredBreakpoint = 0; + uint16_t widthAtBreakpoint = 0; + + for (uint16_t i = 0; i < length; i++) { + strWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[i] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); + + // Always try to break on a space or dash + if (text[i] == ' ' || text[i]== '-') { + preferredBreakpoint = i; + widthAtBreakpoint = strWidth; + } + + if (strWidth >= maxLineWidth) { + if (preferredBreakpoint == 0) { + preferredBreakpoint = i; + widthAtBreakpoint = strWidth; + } + drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], preferredBreakpoint - lastDrawnPos, widthAtBreakpoint); + lastDrawnPos = preferredBreakpoint + 1; + // It is possible that we did not draw all letters to i so we need + // to account for the width of the chars from `i - preferredBreakpoint` + // by calculating the width we did not draw yet. + strWidth = strWidth - widthAtBreakpoint; + preferredBreakpoint = 0; + } + } + + // Draw last part if needed + if (lastDrawnPos < length) { + drawStringInternal(xMove, yMove + lineNumber * lineHeight , &text[lastDrawnPos], length - lastDrawnPos, getStringWidth(&text[lastDrawnPos], length - lastDrawnPos)); + } + + free(text); +} + +uint16_t OLEDDisplay::getStringWidth(const char* text, uint16_t length) { + uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); + + uint16_t stringWidth = 0; + uint16_t maxWidth = 0; + + while (length--) { + stringWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[length] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); + if (text[length] == 10) { + maxWidth = max(maxWidth, stringWidth); + stringWidth = 0; + } + } + + return max(maxWidth, stringWidth); +} + +uint16_t OLEDDisplay::getStringWidth(const String &strUser) { + char* text = utf8ascii(strUser); + uint16_t length = strlen(text); + uint16_t width = getStringWidth(text, length); + free(text); + return width; +} + +void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) { + this->textAlignment = textAlignment; +} + +void OLEDDisplay::setFont(const uint8_t *fontData) { + this->fontData = fontData; +} + +void OLEDDisplay::displayOn(void) { + sendCommand(DISPLAYON); +} + +void OLEDDisplay::displayOff(void) { + sendCommand(DISPLAYOFF); +} + +void OLEDDisplay::invertDisplay(void) { + sendCommand(INVERTDISPLAY); +} + +void OLEDDisplay::normalDisplay(void) { + sendCommand(NORMALDISPLAY); +} + +void OLEDDisplay::setContrast(uint8_t contrast, uint8_t precharge, uint8_t comdetect) { + sendCommand(SETPRECHARGE); //0xD9 + sendCommand(precharge); //0xF1 default, to lower the contrast, put 1-1F + sendCommand(SETCONTRAST); + sendCommand(contrast); // 0-255 + sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast) + sendCommand(comdetect); //0x40 default, to lower the contrast, put 0 + sendCommand(DISPLAYALLON_RESUME); + sendCommand(NORMALDISPLAY); + sendCommand(DISPLAYON); +} + +void OLEDDisplay::setBrightness(uint8_t brightness) { + uint8_t contrast = brightness; + if (brightness < 128) { + // Magic values to get a smooth/ step-free transition + contrast = brightness * 1.171; + } else { + contrast = brightness * 1.171 - 43; + } + + uint8_t precharge = 241; + if (brightness == 0) { + precharge = 0; + } + uint8_t comdetect = brightness / 8; + + setContrast(contrast, precharge, comdetect); +} + +void OLEDDisplay::resetOrientation() { + sendCommand(SEGREMAP); + sendCommand(COMSCANINC); //Reset screen rotation or mirroring +} + +void OLEDDisplay::flipScreenVertically() { + sendCommand(SEGREMAP | 0x01); + sendCommand(COMSCANDEC); //Rotate screen 180 Deg +} + +void OLEDDisplay::mirrorScreen() { + sendCommand(SEGREMAP); + sendCommand(COMSCANDEC); //Mirror screen +} + +void OLEDDisplay::clear(void) { + memset(buffer, 0, displayBufferSize); +} + +void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) { + uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); + // Always align left + setTextAlignment(TEXT_ALIGN_LEFT); + + // State values + uint16_t length = 0; + uint16_t line = 0; + uint16_t lastPos = 0; + + for (uint16_t i=0;ilogBufferFilled;i++){ + // Everytime we have a \n print + if (this->logBuffer[i] == 10) { + length++; + // Draw string on line `line` from lastPos to length + // Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT + drawStringInternal(xMove, yMove + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0); + // Remember last pos + lastPos = i; + // Reset length + length = 0; + } else { + // Count chars until next linebreak + length++; + } + } + // Draw the remaining string + if (length > 0) { + drawStringInternal(xMove, yMove + line * lineHeight, &this->logBuffer[lastPos], length, 0); + } +} + +uint16_t OLEDDisplay::getWidth(void) { + return displayWidth; +} + +uint16_t OLEDDisplay::getHeight(void) { + return displayHeight; +} + +bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){ + if (logBuffer != NULL) free(logBuffer); + uint16_t size = lines * chars; + if (size > 0) { + this->logBufferLine = 0; // Lines printed + this->logBufferFilled = 0; // Nothing stored yet + this->logBufferMaxLines = lines; // Lines max printable + this->logBufferSize = size; // Total number of characters the buffer can hold + this->logBuffer = (char *) malloc(size * sizeof(uint8_t)); + if(!this->logBuffer) { + DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n"); + return false; + } + } + return true; +} + +size_t OLEDDisplay::write(uint8_t c) { + if (this->logBufferSize > 0) { + // Don't waste space on \r\n line endings, dropping \r + if (c == 13) return 1; + + // convert UTF-8 character to font table index + c = (this->fontTableLookupFunction)(c); + // drop unknown character + if (c == 0) return 1; + + bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines; + bool bufferNotFull = this->logBufferFilled < this->logBufferSize; + + // Can we write to the buffer? + if (bufferNotFull && maxLineNotReached) { + this->logBuffer[logBufferFilled] = c; + this->logBufferFilled++; + // Keep track of lines written + if (c == 10) this->logBufferLine++; + } else { + // Max line number is reached + if (!maxLineNotReached) this->logBufferLine--; + + // Find the end of the first line + uint16_t firstLineEnd = 0; + for (uint16_t i=0;ilogBufferFilled;i++) { + if (this->logBuffer[i] == 10){ + // Include last char too + firstLineEnd = i + 1; + break; + } + } + // If there was a line ending + if (firstLineEnd > 0) { + // Calculate the new logBufferFilled value + this->logBufferFilled = logBufferFilled - firstLineEnd; + // Now we move the lines infront of the buffer + memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled); + } else { + // Let's reuse the buffer if it was full + if (!bufferNotFull) { + this->logBufferFilled = 0; + }// else { + // Nothing to do here + //} + } + write(c); + } + } + // We are always writing all uint8_t to the buffer + return 1; +} + +size_t OLEDDisplay::write(const char* str) { + if (str == NULL) return 0; + size_t length = strlen(str); + for (size_t i = 0; i < length; i++) { + write(str[i]); + } + return length; +} + +#ifdef __MBED__ +int OLEDDisplay::_putc(int c) { + + if (!fontData) + return 1; + if (!logBufferSize) { + uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS); + uint16_t lines = this->displayHeight / textHeight; + uint16_t chars = 2 * (this->displayWidth / textHeight); + + if (this->displayHeight % textHeight) + lines++; + if (this->displayWidth % textHeight) + chars++; + setLogBuffer(lines, chars); + } + + return this->write((uint8_t)c); +} +#endif + +// Private functions +void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width, uint16_t height) { + this->geometry = g; + switch (g) { + case GEOMETRY_128_64: + this->displayWidth = 128; + this->displayHeight = 64; + break; + case GEOMETRY_128_32: + this->displayWidth = 128; + this->displayHeight = 32; + break; + case GEOMETRY_RAWMODE: + this->displayWidth = width > 0 ? width : 128; + this->displayHeight = height > 0 ? height : 64; + break; + } + this->displayBufferSize = displayWidth * displayHeight /8; +} + +void OLEDDisplay::sendInitCommands(void) { + if (geometry == GEOMETRY_RAWMODE) + return; + sendCommand(DISPLAYOFF); + sendCommand(SETDISPLAYCLOCKDIV); + sendCommand(0xF0); // Increase speed of the display max ~96Hz + sendCommand(SETMULTIPLEX); + sendCommand(this->height() - 1); + sendCommand(SETDISPLAYOFFSET); + sendCommand(0x00); + sendCommand(SETSTARTLINE); + sendCommand(CHARGEPUMP); + sendCommand(0x14); + sendCommand(MEMORYMODE); + sendCommand(0x00); + sendCommand(SEGREMAP); + sendCommand(COMSCANINC); + sendCommand(SETCOMPINS); + + if (geometry == GEOMETRY_128_64) { + sendCommand(0x12); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x02); + } + + sendCommand(SETCONTRAST); + + if (geometry == GEOMETRY_128_64) { + sendCommand(0xCF); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x8F); + } + + sendCommand(SETPRECHARGE); + sendCommand(0xF1); + sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast) + sendCommand(0x40); //0x40 default, to lower the contrast, put 0 + sendCommand(DISPLAYALLON_RESUME); + sendCommand(NORMALDISPLAY); + sendCommand(0x2e); // stop scroll + sendCommand(DISPLAYON); +} + +void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) { + if (width < 0 || height < 0) return; + if (yMove + height < 0 || yMove > this->height()) return; + if (xMove + width < 0 || xMove > this->width()) return; + + uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0) + int8_t yOffset = yMove & 7; + + bytesInData = bytesInData == 0 ? width * rasterHeight : bytesInData; + + int16_t initYMove = yMove; + int8_t initYOffset = yOffset; + + + for (uint16_t i = 0; i < bytesInData; i++) { + + // Reset if next horizontal drawing phase is started. + if ( i % rasterHeight == 0) { + yMove = initYMove; + yOffset = initYOffset; + } + + uint8_t currentByte = pgm_read_byte(data + offset + i); + + int16_t xPos = xMove + (i / rasterHeight); + int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width(); + +// int16_t yScreenPos = yMove + yOffset; + int16_t dataPos = xPos + yPos; + + if (dataPos >= 0 && dataPos < displayBufferSize && + xPos >= 0 && xPos < this->width() ) { + + if (yOffset >= 0) { + switch (this->color) { + case WHITE: buffer[dataPos] |= currentByte << yOffset; break; + case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break; + case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break; + } + + if (dataPos < (displayBufferSize - this->width())) { + switch (this->color) { + case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break; + case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break; + case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break; + } + } + } else { + // Make new offset position + yOffset = -yOffset; + + switch (this->color) { + case WHITE: buffer[dataPos] |= currentByte >> yOffset; break; + case BLACK: buffer[dataPos] &= ~(currentByte >> yOffset); break; + case INVERSE: buffer[dataPos] ^= currentByte >> yOffset; break; + } + + // Prepare for next iteration by moving one block up + yMove -= 8; + + // and setting the new yOffset + yOffset = 8 - yOffset; + } +#ifndef __MBED__ + yield(); +#endif + } + } +} + +// You need to free the char! +char* OLEDDisplay::utf8ascii(const String &str) { + uint16_t k = 0; + uint16_t length = str.length() + 1; + + // Copy the string into a char array + char* s = (char*) malloc(length * sizeof(char)); + if(!s) { + DEBUG_OLEDDISPLAY("[OLEDDISPLAY][utf8ascii] Can't allocate another char array. Drop support for UTF-8.\n"); + return (char*) str.c_str(); + } + str.toCharArray(s, length); + + length--; + + for (uint16_t i=0; i < length; i++) { + char c = (this->fontTableLookupFunction)(s[i]); + if (c!=0) { + s[k++]=c; + } + } + + s[k]=0; + + // This will leak 's' be sure to free it in the calling function. + return s; +} + +void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) { + this->fontTableLookupFunction = function; +} + + +char DefaultFontTableLookup(const uint8_t ch) { + // UTF-8 to font table index converter + // Code form http://playground.arduino.cc/Main/Utf8ascii + static uint8_t LASTCHAR; + + if (ch < 128) { // Standard ASCII-set 0..0x7F handling + LASTCHAR = 0; + return ch; + } + + uint8_t last = LASTCHAR; // get last char + LASTCHAR = ch; + + switch (last) { // conversion depnding on first UTF8-character + case 0xC2: return (uint8_t) ch; + case 0xC3: return (uint8_t) (ch | 0xC0); + case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol + } + + return (uint8_t) 0; // otherwise: return zero, if character has to be ignored +} + +void OLEDDisplay::ditherArea(int16_t x, int16_t y, int16_t w, int16_t h) { + bool vms = true; + + while (h) + { // row + int16_t w1 = w; + int16_t x1 = x; + bool vm = vms; + while (w1) + { // line + if (x1 >= 0 && x1 < this->width() && y >= 0 && y < this->height()) { // visible dot + uint8_t mask = 1 << (y & 7); + unsigned offset = x1 + (y / 8) * this->width(); + if ((0 != (buffer[offset] & mask)) && vm) { + buffer[offset] &= ~mask; // erase pixel (dither) + } + } + w1--; + x1++; + vm = !vm; + } + h--; + y++; + vms = !vms; + } +} + +uint16_t OLEDDisplay::getTextHeight(void) { + uint16_t retval = pgm_read_byte(fontData + HEIGHT_POS); + + return retval; +} + +void OLEDDisplay::fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r) { + int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis + if(r > max_radius) + r = max_radius; + // smarter version + fillRect(x+r, y, w-2*r, h); + // draw four corners + fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1); + fillCircleHelper(x+r , y+r, r, 2, h-2*r-1); +} + +void OLEDDisplay::drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r) { + int16_t max_radius = ((w < h) ? w : h) / 2; // 1/2 minor axis + if(r > max_radius) + r = max_radius; + // smarter version + drawHorizontalLine(x+r , y , w-2*r); // Top + drawHorizontalLine(x+r , y+h-1, w-2*r); // Bottom + drawVerticalLine(x , y+r , h-2*r); // Left + drawVerticalLine(x+w-1, y+r , h-2*r); // Right + // draw four corners + drawCircleQuads(x+r , y+r , r, 2); + drawCircleQuads(x+w-r-1, y+r , r, 1); + drawCircleQuads(x+w-r-1, y+h-r-1, r, 8); + drawCircleQuads(x+r , y+h-r-1, r, 4); +} diff --git a/src/OLEDDisplay.h b/src/OLEDDisplay.h new file mode 100644 index 0000000..c2555d2 --- /dev/null +++ b/src/OLEDDisplay.h @@ -0,0 +1,392 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef OLEDDISPLAY_h +#define OLEDDISPLAY_h + +#ifdef ARDUINO +#include +#elif __MBED__ +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) + +#include +#define delay(x) wait_ms(x) +#define yield() void() + +/* + * This is a little Arduino String emulation to keep the OLEDDisplay + * library code in common between Arduino and mbed-os + */ +class String { +public: + String(const char *s) { _str = s; }; + int length() { return strlen(_str); }; + const char *c_str() { return _str; }; + void toCharArray(char *buf, unsigned int bufsize, unsigned int index = 0) const { + memcpy(buf, _str + index, std::min(bufsize, strlen(_str))); + }; +private: + const char *_str; +}; + +#else +#error "Unkown operating system" +#endif + +#include "OLEDDisplayFonts.h" + +//#define DEBUG_OLEDDISPLAY(...) Serial.printf( __VA_ARGS__ ) +//#define DEBUG_OLEDDISPLAY(...) dprintf("%s", __VA_ARGS__ ) + +#ifndef DEBUG_OLEDDISPLAY +#define DEBUG_OLEDDISPLAY(...) +#endif + +// Use DOUBLE BUFFERING by default +#ifndef OLEDDISPLAY_REDUCE_MEMORY +#define OLEDDISPLAY_DOUBLE_BUFFER +#endif + +// Header Values +#define JUMPTABLE_BYTES 4 + +#define JUMPTABLE_LSB 1 +#define JUMPTABLE_SIZE 2 +#define JUMPTABLE_WIDTH 3 +#define JUMPTABLE_START 4 + +#define WIDTH_POS 0 +#define HEIGHT_POS 1 +#define FIRST_CHAR_POS 2 +#define CHAR_NUM_POS 3 + + +// Display commands +#define CHARGEPUMP 0x8D +#define COLUMNADDR 0x21 +#define COMSCANDEC 0xC8 +#define COMSCANINC 0xC0 +#define DISPLAYALLON 0xA5 +#define DISPLAYALLON_RESUME 0xA4 +#define DISPLAYOFF 0xAE +#define DISPLAYON 0xAF +#define EXTERNALVCC 0x1 +#define INVERTDISPLAY 0xA7 +#define MEMORYMODE 0x20 +#define NORMALDISPLAY 0xA6 +#define PAGEADDR 0x22 +#define SEGREMAP 0xA0 +#define SETCOMPINS 0xDA +#define SETCONTRAST 0x81 +#define SETDISPLAYCLOCKDIV 0xD5 +#define SETDISPLAYOFFSET 0xD3 +#define SETHIGHCOLUMN 0x10 +#define SETLOWCOLUMN 0x00 +#define SETMULTIPLEX 0xA8 +#define SETPRECHARGE 0xD9 +#define SETSEGMENTREMAP 0xA1 +#define SETSTARTLINE 0x40 +#define SETVCOMDETECT 0xDB +#define SWITCHCAPVCC 0x2 + +#ifndef _swap_int16_t +#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } +#endif + +enum OLEDDISPLAY_COLOR { + BLACK = 0, + WHITE = 1, + INVERSE = 2 +}; + +enum OLEDDISPLAY_TEXT_ALIGNMENT { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_RIGHT = 1, + TEXT_ALIGN_CENTER = 2, + TEXT_ALIGN_CENTER_BOTH = 3 +}; + + +enum OLEDDISPLAY_GEOMETRY { + GEOMETRY_128_64 = 0, + GEOMETRY_128_32, + GEOMETRY_RAWMODE, +}; + +enum HW_I2C { + I2C_ONE, + I2C_TWO +}; + +typedef char (*FontTableLookupFunction)(const uint8_t ch); +char DefaultFontTableLookup(const uint8_t ch); + + +#ifdef ARDUINO +class OLEDDisplay : public Print { +#elif __MBED__ +class OLEDDisplay : public Stream { +#else +#error "Unkown operating system" +#endif + + public: + OLEDDisplay(); + virtual ~OLEDDisplay(); + + uint16_t width(void) const { return displayWidth; }; + uint16_t height(void) const { return displayHeight; }; + uint16_t getBufferSize(void) const { return displayBufferSize; }; + + // Use this to resume after a deep sleep without resetting the display (what init() would do). + // Returns true if connection to the display was established and the buffer allocated, false otherwise. + bool allocateBuffer(); + + // Allocates the buffer and initializes the driver & display. Resets the display! + // Returns false if buffer allocation failed, true otherwise. + bool init(); + + // Free the memory used by the display + void end(); + + // Cycle through the initialization + void resetDisplay(void); + + /* Drawing functions */ + // Sets the color of all pixel operations + void setColor(OLEDDISPLAY_COLOR color); + + // Returns the current color. + OLEDDISPLAY_COLOR getColor(); + + // Draw a pixel at given position + void setPixel(int16_t x, int16_t y); + + // Draw a pixel at given position and color + void setPixelColor(int16_t x, int16_t y, OLEDDISPLAY_COLOR color); + + // Clear a pixel at given position FIXME: INVERSE is untested with this function + void clearPixel(int16_t x, int16_t y); + + // Draw a line from position 0 to position 1 + void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); + + // Draw the border of a rectangle at the given location + void drawRect(int16_t x, int16_t y, int16_t width, int16_t height); + + // Draw a rounded rectangle border at the given location + void drawRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r); + + // Fill the rectangle + void fillRect(int16_t x, int16_t y, int16_t width, int16_t height); + + // Fll rounded rectangle + void fillRoundRect(int16_t x, int16_t y, int16_t w, int16_t h, int16_t r); + + // Draw the border of a circle + void drawCircle(int16_t x, int16_t y, int16_t radius); + + // Draw all Quadrants specified in the quads bit mask + void drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads); + + // Fill circle + void fillCircle(int16_t x, int16_t y, int16_t radius); + + // Draw a line horizontally + void drawHorizontalLine(int16_t x, int16_t y, int16_t length); + + // Draw a line vertically + void drawVerticalLine(int16_t x, int16_t y, int16_t length); + + // Draws a rounded progress bar with the outer dimensions given by width and height. Progress is + // a unsigned byte value between 0 and 100 + void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress); + + // Draw a bitmap in the internal image format + void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image); + + // Draw a XBM + void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm); + + // Draw icon 16x16 xbm format + void drawIco16x16(int16_t x, int16_t y, const char *ico, bool inverse = false); + + /* Text functions */ + + // Draws a string at the given location + void drawString(int16_t x, int16_t y, const String& text); + + // Draws a String with a maximum width at the given location. + // If the given String is wider than the specified width + // The text will be wrapped to the next line at a space or dash + void drawStringMaxWidth(int16_t x, int16_t y, uint16_t maxLineWidth, const String& text); + + // Returns the width of the const char* with the current + // font settings + uint16_t getStringWidth(const char* text, uint16_t length); + + // Convencience method for the const char version + uint16_t getStringWidth(const String& text); + + uint16_t getTextHeight(void); + + // Specifies relative to which anchor point + // the text is rendered. Available constants: + // TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH + void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); + + // Sets the current font. Available default fonts + // ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24 + void setFont(const uint8_t *fontData); + + // Set the function that will convert utf-8 to font table index + void setFontTableLookupFunction(FontTableLookupFunction function); + + // Dither an screen area at the given location + void ditherArea(int16_t x, int16_t y, int16_t w, int16_t h); + + /* Display functions */ + + // Turn the display on + void displayOn(void); + + // Turn the display offs + void displayOff(void); + + // Inverted display mode + void invertDisplay(void); + + // Normal display mode + void normalDisplay(void); + + // Set display contrast + // really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0 + // normal brightness & contrast: contrast = 100 + void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64); + + // Convenience method to access + void setBrightness(uint8_t); + + // Reset display rotation or mirroring + void resetOrientation(); + + // Turn the display upside down + void flipScreenVertically(); + + // Mirror the display (to be used in a mirror or as a projector) + void mirrorScreen(); + + // Write the buffer to the display memory + virtual void display(void) = 0; + + // Clear the local pixel buffer + void clear(void); + + // Log buffer implementation + + // This will define the lines and characters you can + // print to the screen. When you exeed the buffer size (lines * chars) + // the output may be truncated due to the size constraint. + bool setLogBuffer(uint16_t lines, uint16_t chars); + + // Draw the log buffer at position (x, y) + void drawLogBuffer(uint16_t x, uint16_t y); + + // Get screen geometry + uint16_t getWidth(void); + uint16_t getHeight(void); + + // Implement needed function to be compatible with Print class + size_t write(uint8_t c); + size_t write(const char* s); + + // Implement needed function to be compatible with Stream class +#ifdef __MBED__ + int _putc(int c); + int _getc() { return -1; }; +#endif + + + uint8_t *buffer; + + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t *buffer_back; + #endif + + protected: + + OLEDDISPLAY_GEOMETRY geometry; + + uint16_t displayWidth; + uint16_t displayHeight; + uint16_t displayBufferSize; + + // Set the correct height, width and buffer for the geometry + void setGeometry(OLEDDISPLAY_GEOMETRY g, uint16_t width = 0, uint16_t height = 0); + + OLEDDISPLAY_TEXT_ALIGNMENT textAlignment; + OLEDDISPLAY_COLOR color; + + const uint8_t *fontData; + + // State values for logBuffer + uint16_t logBufferSize; + uint16_t logBufferFilled; + uint16_t logBufferLine; + uint16_t logBufferMaxLines; + char *logBuffer; + + + // the header size of the buffer used, e.g. for the SPI command header + virtual int getBufferOffset(void) = 0; + + // Send a command to the display (low level function) + virtual void sendCommand(uint8_t com) {(void)com;}; + + // Connect to the display + virtual bool connect() { return false; }; + + // Send all the init commands + void sendInitCommands(); + + // converts utf8 characters to extended ascii + char* utf8ascii(const String& s); + + void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline)); + + void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth); + + void fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t corners, int16_t delta); + + FontTableLookupFunction fontTableLookupFunction; +}; + +#endif diff --git a/src/OLEDDisplayFonts.cpp b/src/OLEDDisplayFonts.cpp new file mode 100644 index 0000000..9e3f3fb --- /dev/null +++ b/src/OLEDDisplayFonts.cpp @@ -0,0 +1,1272 @@ +#include "OLEDDisplayFonts.h" + +const uint8_t ArialMT_Plain_10[] PROGMEM = { + 0x0A, // Width: 10 + 0x0D, // Height: 13 + 0x20, // First Char: 32 + 0xE0, // Numbers of Chars: 224 + + // Jump Table: + 0xFF, 0xFF, 0x00, 0x03, // 32:65535 + 0x00, 0x00, 0x04, 0x03, // 33:0 + 0x00, 0x04, 0x05, 0x04, // 34:4 + 0x00, 0x09, 0x09, 0x06, // 35:9 + 0x00, 0x12, 0x0A, 0x06, // 36:18 + 0x00, 0x1C, 0x10, 0x09, // 37:28 + 0x00, 0x2C, 0x0E, 0x07, // 38:44 + 0x00, 0x3A, 0x01, 0x02, // 39:58 + 0x00, 0x3B, 0x06, 0x03, // 40:59 + 0x00, 0x41, 0x06, 0x03, // 41:65 + 0x00, 0x47, 0x05, 0x04, // 42:71 + 0x00, 0x4C, 0x09, 0x06, // 43:76 + 0x00, 0x55, 0x04, 0x03, // 44:85 + 0x00, 0x59, 0x03, 0x03, // 45:89 + 0x00, 0x5C, 0x04, 0x03, // 46:92 + 0x00, 0x60, 0x05, 0x03, // 47:96 + 0x00, 0x65, 0x0A, 0x06, // 48:101 + 0x00, 0x6F, 0x08, 0x06, // 49:111 + 0x00, 0x77, 0x0A, 0x06, // 50:119 + 0x00, 0x81, 0x0A, 0x06, // 51:129 + 0x00, 0x8B, 0x0B, 0x06, // 52:139 + 0x00, 0x96, 0x0A, 0x06, // 53:150 + 0x00, 0xA0, 0x0A, 0x06, // 54:160 + 0x00, 0xAA, 0x09, 0x06, // 55:170 + 0x00, 0xB3, 0x0A, 0x06, // 56:179 + 0x00, 0xBD, 0x0A, 0x06, // 57:189 + 0x00, 0xC7, 0x04, 0x03, // 58:199 + 0x00, 0xCB, 0x04, 0x03, // 59:203 + 0x00, 0xCF, 0x0A, 0x06, // 60:207 + 0x00, 0xD9, 0x09, 0x06, // 61:217 + 0x00, 0xE2, 0x09, 0x06, // 62:226 + 0x00, 0xEB, 0x0B, 0x06, // 63:235 + 0x00, 0xF6, 0x14, 0x0A, // 64:246 + 0x01, 0x0A, 0x0E, 0x07, // 65:266 + 0x01, 0x18, 0x0C, 0x07, // 66:280 + 0x01, 0x24, 0x0C, 0x07, // 67:292 + 0x01, 0x30, 0x0B, 0x07, // 68:304 + 0x01, 0x3B, 0x0C, 0x07, // 69:315 + 0x01, 0x47, 0x09, 0x06, // 70:327 + 0x01, 0x50, 0x0D, 0x08, // 71:336 + 0x01, 0x5D, 0x0C, 0x07, // 72:349 + 0x01, 0x69, 0x04, 0x03, // 73:361 + 0x01, 0x6D, 0x08, 0x05, // 74:365 + 0x01, 0x75, 0x0E, 0x07, // 75:373 + 0x01, 0x83, 0x0C, 0x06, // 76:387 + 0x01, 0x8F, 0x10, 0x08, // 77:399 + 0x01, 0x9F, 0x0C, 0x07, // 78:415 + 0x01, 0xAB, 0x0E, 0x08, // 79:427 + 0x01, 0xB9, 0x0B, 0x07, // 80:441 + 0x01, 0xC4, 0x0E, 0x08, // 81:452 + 0x01, 0xD2, 0x0C, 0x07, // 82:466 + 0x01, 0xDE, 0x0C, 0x07, // 83:478 + 0x01, 0xEA, 0x0B, 0x06, // 84:490 + 0x01, 0xF5, 0x0C, 0x07, // 85:501 + 0x02, 0x01, 0x0D, 0x07, // 86:513 + 0x02, 0x0E, 0x11, 0x09, // 87:526 + 0x02, 0x1F, 0x0E, 0x07, // 88:543 + 0x02, 0x2D, 0x0D, 0x07, // 89:557 + 0x02, 0x3A, 0x0C, 0x06, // 90:570 + 0x02, 0x46, 0x06, 0x03, // 91:582 + 0x02, 0x4C, 0x06, 0x03, // 92:588 + 0x02, 0x52, 0x04, 0x03, // 93:594 + 0x02, 0x56, 0x09, 0x05, // 94:598 + 0x02, 0x5F, 0x0C, 0x06, // 95:607 + 0x02, 0x6B, 0x03, 0x03, // 96:619 + 0x02, 0x6E, 0x0A, 0x06, // 97:622 + 0x02, 0x78, 0x0A, 0x06, // 98:632 + 0x02, 0x82, 0x0A, 0x05, // 99:642 + 0x02, 0x8C, 0x0A, 0x06, // 100:652 + 0x02, 0x96, 0x0A, 0x06, // 101:662 + 0x02, 0xA0, 0x05, 0x03, // 102:672 + 0x02, 0xA5, 0x0A, 0x06, // 103:677 + 0x02, 0xAF, 0x0A, 0x06, // 104:687 + 0x02, 0xB9, 0x04, 0x02, // 105:697 + 0x02, 0xBD, 0x04, 0x02, // 106:701 + 0x02, 0xC1, 0x08, 0x05, // 107:705 + 0x02, 0xC9, 0x04, 0x02, // 108:713 + 0x02, 0xCD, 0x10, 0x08, // 109:717 + 0x02, 0xDD, 0x0A, 0x06, // 110:733 + 0x02, 0xE7, 0x0A, 0x06, // 111:743 + 0x02, 0xF1, 0x0A, 0x06, // 112:753 + 0x02, 0xFB, 0x0A, 0x06, // 113:763 + 0x03, 0x05, 0x05, 0x03, // 114:773 + 0x03, 0x0A, 0x08, 0x05, // 115:778 + 0x03, 0x12, 0x06, 0x03, // 116:786 + 0x03, 0x18, 0x0A, 0x06, // 117:792 + 0x03, 0x22, 0x09, 0x05, // 118:802 + 0x03, 0x2B, 0x0E, 0x07, // 119:811 + 0x03, 0x39, 0x0A, 0x05, // 120:825 + 0x03, 0x43, 0x09, 0x05, // 121:835 + 0x03, 0x4C, 0x0A, 0x05, // 122:844 + 0x03, 0x56, 0x06, 0x03, // 123:854 + 0x03, 0x5C, 0x04, 0x03, // 124:860 + 0x03, 0x60, 0x05, 0x03, // 125:864 + 0x03, 0x65, 0x09, 0x06, // 126:869 + 0xFF, 0xFF, 0x00, 0x00, // 127:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 128:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 129:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 130:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 131:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 132:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 133:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 134:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 135:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 136:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 137:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 138:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 139:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 140:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 141:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 142:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 143:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 144:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 145:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 146:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 147:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 148:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 149:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 150:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 151:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 152:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 153:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 154:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 155:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 156:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 157:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 158:65535 + 0xFF, 0xFF, 0x00, 0x0A, // 159:65535 + 0xFF, 0xFF, 0x00, 0x03, // 160:65535 + 0x03, 0x6E, 0x04, 0x03, // 161:878 + 0x03, 0x72, 0x0A, 0x06, // 162:882 + 0x03, 0x7C, 0x0C, 0x06, // 163:892 + 0x03, 0x88, 0x0A, 0x06, // 164:904 + 0x03, 0x92, 0x0A, 0x06, // 165:914 + 0x03, 0x9C, 0x04, 0x03, // 166:924 + 0x03, 0xA0, 0x0A, 0x06, // 167:928 + 0x03, 0xAA, 0x05, 0x03, // 168:938 + 0x03, 0xAF, 0x0D, 0x07, // 169:943 + 0x03, 0xBC, 0x07, 0x04, // 170:956 + 0x03, 0xC3, 0x0A, 0x06, // 171:963 + 0x03, 0xCD, 0x09, 0x06, // 172:973 + 0x03, 0xD6, 0x03, 0x03, // 173:982 + 0x03, 0xD9, 0x0D, 0x07, // 174:985 + 0x03, 0xE6, 0x0B, 0x06, // 175:998 + 0x03, 0xF1, 0x07, 0x04, // 176:1009 + 0x03, 0xF8, 0x0A, 0x05, // 177:1016 + 0x04, 0x02, 0x05, 0x03, // 178:1026 + 0x04, 0x07, 0x05, 0x03, // 179:1031 + 0x04, 0x0C, 0x05, 0x03, // 180:1036 + 0x04, 0x11, 0x0A, 0x06, // 181:1041 + 0x04, 0x1B, 0x09, 0x05, // 182:1051 + 0x04, 0x24, 0x03, 0x03, // 183:1060 + 0x04, 0x27, 0x06, 0x03, // 184:1063 + 0x04, 0x2D, 0x05, 0x03, // 185:1069 + 0x04, 0x32, 0x07, 0x04, // 186:1074 + 0x04, 0x39, 0x0A, 0x06, // 187:1081 + 0x04, 0x43, 0x10, 0x08, // 188:1091 + 0x04, 0x53, 0x10, 0x08, // 189:1107 + 0x04, 0x63, 0x10, 0x08, // 190:1123 + 0x04, 0x73, 0x0A, 0x06, // 191:1139 + 0x04, 0x7D, 0x0E, 0x07, // 192:1149 + 0x04, 0x8B, 0x0E, 0x07, // 193:1163 + 0x04, 0x99, 0x0E, 0x07, // 194:1177 + 0x04, 0xA7, 0x0E, 0x07, // 195:1191 + 0x04, 0xB5, 0x0E, 0x07, // 196:1205 + 0x04, 0xC3, 0x0E, 0x07, // 197:1219 + 0x04, 0xD1, 0x12, 0x0A, // 198:1233 + 0x04, 0xE3, 0x0C, 0x07, // 199:1251 + 0x04, 0xEF, 0x0C, 0x07, // 200:1263 + 0x04, 0xFB, 0x0C, 0x07, // 201:1275 + 0x05, 0x07, 0x0C, 0x07, // 202:1287 + 0x05, 0x13, 0x0C, 0x07, // 203:1299 + 0x05, 0x1F, 0x05, 0x03, // 204:1311 + 0x05, 0x24, 0x04, 0x03, // 205:1316 + 0x05, 0x28, 0x04, 0x03, // 206:1320 + 0x05, 0x2C, 0x05, 0x03, // 207:1324 + 0x05, 0x31, 0x0B, 0x07, // 208:1329 + 0x05, 0x3C, 0x0C, 0x07, // 209:1340 + 0x05, 0x48, 0x0E, 0x08, // 210:1352 + 0x05, 0x56, 0x0E, 0x08, // 211:1366 + 0x05, 0x64, 0x0E, 0x08, // 212:1380 + 0x05, 0x72, 0x0E, 0x08, // 213:1394 + 0x05, 0x80, 0x0E, 0x08, // 214:1408 + 0x05, 0x8E, 0x0A, 0x06, // 215:1422 + 0x05, 0x98, 0x0D, 0x08, // 216:1432 + 0x05, 0xA5, 0x0C, 0x07, // 217:1445 + 0x05, 0xB1, 0x0C, 0x07, // 218:1457 + 0x05, 0xBD, 0x0C, 0x07, // 219:1469 + 0x05, 0xC9, 0x0C, 0x07, // 220:1481 + 0x05, 0xD5, 0x0D, 0x07, // 221:1493 + 0x05, 0xE2, 0x0B, 0x07, // 222:1506 + 0x05, 0xED, 0x0C, 0x06, // 223:1517 + 0x05, 0xF9, 0x0A, 0x06, // 224:1529 + 0x06, 0x03, 0x0A, 0x06, // 225:1539 + 0x06, 0x0D, 0x0A, 0x06, // 226:1549 + 0x06, 0x17, 0x0A, 0x06, // 227:1559 + 0x06, 0x21, 0x0A, 0x06, // 228:1569 + 0x06, 0x2B, 0x0A, 0x06, // 229:1579 + 0x06, 0x35, 0x10, 0x09, // 230:1589 + 0x06, 0x45, 0x0A, 0x05, // 231:1605 + 0x06, 0x4F, 0x0A, 0x06, // 232:1615 + 0x06, 0x59, 0x0A, 0x06, // 233:1625 + 0x06, 0x63, 0x0A, 0x06, // 234:1635 + 0x06, 0x6D, 0x0A, 0x06, // 235:1645 + 0x06, 0x77, 0x05, 0x03, // 236:1655 + 0x06, 0x7C, 0x04, 0x03, // 237:1660 + 0x06, 0x80, 0x05, 0x03, // 238:1664 + 0x06, 0x85, 0x05, 0x03, // 239:1669 + 0x06, 0x8A, 0x0A, 0x06, // 240:1674 + 0x06, 0x94, 0x0A, 0x06, // 241:1684 + 0x06, 0x9E, 0x0A, 0x06, // 242:1694 + 0x06, 0xA8, 0x0A, 0x06, // 243:1704 + 0x06, 0xB2, 0x0A, 0x06, // 244:1714 + 0x06, 0xBC, 0x0A, 0x06, // 245:1724 + 0x06, 0xC6, 0x0A, 0x06, // 246:1734 + 0x06, 0xD0, 0x09, 0x05, // 247:1744 + 0x06, 0xD9, 0x0A, 0x06, // 248:1753 + 0x06, 0xE3, 0x0A, 0x06, // 249:1763 + 0x06, 0xED, 0x0A, 0x06, // 250:1773 + 0x06, 0xF7, 0x0A, 0x06, // 251:1783 + 0x07, 0x01, 0x0A, 0x06, // 252:1793 + 0x07, 0x0B, 0x09, 0x05, // 253:1803 + 0x07, 0x14, 0x0A, 0x06, // 254:1812 + 0x07, 0x1E, 0x09, 0x05, // 255:1822 + + // Font Data: + 0x00,0x00,0xF8,0x02, // 33 + 0x38,0x00,0x00,0x00,0x38, // 34 + 0xA0,0x03,0xE0,0x00,0xB8,0x03,0xE0,0x00,0xB8, // 35 + 0x30,0x01,0x28,0x02,0xF8,0x07,0x48,0x02,0x90,0x01, // 36 + 0x00,0x00,0x30,0x00,0x48,0x00,0x30,0x03,0xC0,0x00,0xB0,0x01,0x48,0x02,0x80,0x01, // 37 + 0x80,0x01,0x50,0x02,0x68,0x02,0xA8,0x02,0x18,0x01,0x80,0x03,0x80,0x02, // 38 + 0x38, // 39 + 0xE0,0x03,0x10,0x04,0x08,0x08, // 40 + 0x08,0x08,0x10,0x04,0xE0,0x03, // 41 + 0x28,0x00,0x18,0x00,0x28, // 42 + 0x40,0x00,0x40,0x00,0xF0,0x01,0x40,0x00,0x40, // 43 + 0x00,0x00,0x00,0x06, // 44 + 0x80,0x00,0x80, // 45 + 0x00,0x00,0x00,0x02, // 46 + 0x00,0x03,0xE0,0x00,0x18, // 47 + 0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x02,0xF0,0x01, // 48 + 0x00,0x00,0x20,0x00,0x10,0x00,0xF8,0x03, // 49 + 0x10,0x02,0x08,0x03,0x88,0x02,0x48,0x02,0x30,0x02, // 50 + 0x10,0x01,0x08,0x02,0x48,0x02,0x48,0x02,0xB0,0x01, // 51 + 0xC0,0x00,0xA0,0x00,0x90,0x00,0x88,0x00,0xF8,0x03,0x80, // 52 + 0x60,0x01,0x38,0x02,0x28,0x02,0x28,0x02,0xC8,0x01, // 53 + 0xF0,0x01,0x28,0x02,0x28,0x02,0x28,0x02,0xD0,0x01, // 54 + 0x08,0x00,0x08,0x03,0xC8,0x00,0x38,0x00,0x08, // 55 + 0xB0,0x01,0x48,0x02,0x48,0x02,0x48,0x02,0xB0,0x01, // 56 + 0x70,0x01,0x88,0x02,0x88,0x02,0x88,0x02,0xF0,0x01, // 57 + 0x00,0x00,0x20,0x02, // 58 + 0x00,0x00,0x20,0x06, // 59 + 0x00,0x00,0x40,0x00,0xA0,0x00,0xA0,0x00,0x10,0x01, // 60 + 0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0, // 61 + 0x00,0x00,0x10,0x01,0xA0,0x00,0xA0,0x00,0x40, // 62 + 0x10,0x00,0x08,0x00,0x08,0x00,0xC8,0x02,0x48,0x00,0x30, // 63 + 0x00,0x00,0xC0,0x03,0x30,0x04,0xD0,0x09,0x28,0x0A,0x28,0x0A,0xC8,0x0B,0x68,0x0A,0x10,0x05,0xE0,0x04, // 64 + 0x00,0x02,0xC0,0x01,0xB0,0x00,0x88,0x00,0xB0,0x00,0xC0,0x01,0x00,0x02, // 65 + 0x00,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x48,0x02,0xF0,0x01, // 66 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x02,0x10,0x01, // 67 + 0x00,0x00,0xF8,0x03,0x08,0x02,0x08,0x02,0x10,0x01,0xE0, // 68 + 0x00,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x48,0x02,0x48,0x02, // 69 + 0x00,0x00,0xF8,0x03,0x48,0x00,0x48,0x00,0x08, // 70 + 0x00,0x00,0xE0,0x00,0x10,0x01,0x08,0x02,0x48,0x02,0x50,0x01,0xC0, // 71 + 0x00,0x00,0xF8,0x03,0x40,0x00,0x40,0x00,0x40,0x00,0xF8,0x03, // 72 + 0x00,0x00,0xF8,0x03, // 73 + 0x00,0x03,0x00,0x02,0x00,0x02,0xF8,0x01, // 74 + 0x00,0x00,0xF8,0x03,0x80,0x00,0x60,0x00,0x90,0x00,0x08,0x01,0x00,0x02, // 75 + 0x00,0x00,0xF8,0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, // 76 + 0x00,0x00,0xF8,0x03,0x30,0x00,0xC0,0x01,0x00,0x02,0xC0,0x01,0x30,0x00,0xF8,0x03, // 77 + 0x00,0x00,0xF8,0x03,0x30,0x00,0x40,0x00,0x80,0x01,0xF8,0x03, // 78 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x02,0x08,0x02,0xF0,0x01, // 79 + 0x00,0x00,0xF8,0x03,0x48,0x00,0x48,0x00,0x48,0x00,0x30, // 80 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x03,0x08,0x03,0xF0,0x02, // 81 + 0x00,0x00,0xF8,0x03,0x48,0x00,0x48,0x00,0xC8,0x00,0x30,0x03, // 82 + 0x00,0x00,0x30,0x01,0x48,0x02,0x48,0x02,0x48,0x02,0x90,0x01, // 83 + 0x00,0x00,0x08,0x00,0x08,0x00,0xF8,0x03,0x08,0x00,0x08, // 84 + 0x00,0x00,0xF8,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0xF8,0x01, // 85 + 0x08,0x00,0x70,0x00,0x80,0x01,0x00,0x02,0x80,0x01,0x70,0x00,0x08, // 86 + 0x18,0x00,0xE0,0x01,0x00,0x02,0xF0,0x01,0x08,0x00,0xF0,0x01,0x00,0x02,0xE0,0x01,0x18, // 87 + 0x00,0x02,0x08,0x01,0x90,0x00,0x60,0x00,0x90,0x00,0x08,0x01,0x00,0x02, // 88 + 0x08,0x00,0x10,0x00,0x20,0x00,0xC0,0x03,0x20,0x00,0x10,0x00,0x08, // 89 + 0x08,0x03,0x88,0x02,0xC8,0x02,0x68,0x02,0x38,0x02,0x18,0x02, // 90 + 0x00,0x00,0xF8,0x0F,0x08,0x08, // 91 + 0x18,0x00,0xE0,0x00,0x00,0x03, // 92 + 0x08,0x08,0xF8,0x0F, // 93 + 0x40,0x00,0x30,0x00,0x08,0x00,0x30,0x00,0x40, // 94 + 0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08, // 95 + 0x08,0x00,0x10, // 96 + 0x00,0x00,0x00,0x03,0xA0,0x02,0xA0,0x02,0xE0,0x03, // 97 + 0x00,0x00,0xF8,0x03,0x20,0x02,0x20,0x02,0xC0,0x01, // 98 + 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0x40,0x01, // 99 + 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0xF8,0x03, // 100 + 0x00,0x00,0xC0,0x01,0xA0,0x02,0xA0,0x02,0xC0,0x02, // 101 + 0x20,0x00,0xF0,0x03,0x28, // 102 + 0x00,0x00,0xC0,0x05,0x20,0x0A,0x20,0x0A,0xE0,0x07, // 103 + 0x00,0x00,0xF8,0x03,0x20,0x00,0x20,0x00,0xC0,0x03, // 104 + 0x00,0x00,0xE8,0x03, // 105 + 0x00,0x08,0xE8,0x07, // 106 + 0xF8,0x03,0x80,0x00,0xC0,0x01,0x20,0x02, // 107 + 0x00,0x00,0xF8,0x03, // 108 + 0x00,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0xC0,0x03, // 109 + 0x00,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0xC0,0x03, // 110 + 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0xC0,0x01, // 111 + 0x00,0x00,0xE0,0x0F,0x20,0x02,0x20,0x02,0xC0,0x01, // 112 + 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0xE0,0x0F, // 113 + 0x00,0x00,0xE0,0x03,0x20, // 114 + 0x40,0x02,0xA0,0x02,0xA0,0x02,0x20,0x01, // 115 + 0x20,0x00,0xF8,0x03,0x20,0x02, // 116 + 0x00,0x00,0xE0,0x01,0x00,0x02,0x00,0x02,0xE0,0x03, // 117 + 0x20,0x00,0xC0,0x01,0x00,0x02,0xC0,0x01,0x20, // 118 + 0xE0,0x01,0x00,0x02,0xC0,0x01,0x20,0x00,0xC0,0x01,0x00,0x02,0xE0,0x01, // 119 + 0x20,0x02,0x40,0x01,0x80,0x00,0x40,0x01,0x20,0x02, // 120 + 0x20,0x00,0xC0,0x09,0x00,0x06,0xC0,0x01,0x20, // 121 + 0x20,0x02,0x20,0x03,0xA0,0x02,0x60,0x02,0x20,0x02, // 122 + 0x80,0x00,0x78,0x0F,0x08,0x08, // 123 + 0x00,0x00,0xF8,0x0F, // 124 + 0x08,0x08,0x78,0x0F,0x80, // 125 + 0xC0,0x00,0x40,0x00,0xC0,0x00,0x80,0x00,0xC0, // 126 + 0x00,0x00,0xA0,0x0F, // 161 + 0x00,0x00,0xC0,0x01,0xA0,0x0F,0x78,0x02,0x40,0x01, // 162 + 0x40,0x02,0x70,0x03,0xC8,0x02,0x48,0x02,0x08,0x02,0x10,0x02, // 163 + 0x00,0x00,0xE0,0x01,0x20,0x01,0x20,0x01,0xE0,0x01, // 164 + 0x48,0x01,0x70,0x01,0xC0,0x03,0x70,0x01,0x48,0x01, // 165 + 0x00,0x00,0x38,0x0F, // 166 + 0xD0,0x04,0x28,0x09,0x48,0x09,0x48,0x0A,0x90,0x05, // 167 + 0x08,0x00,0x00,0x00,0x08, // 168 + 0xE0,0x00,0x10,0x01,0x48,0x02,0xA8,0x02,0xA8,0x02,0x10,0x01,0xE0, // 169 + 0x68,0x00,0x68,0x00,0x68,0x00,0x78, // 170 + 0x00,0x00,0x80,0x01,0x40,0x02,0x80,0x01,0x40,0x02, // 171 + 0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xE0, // 172 + 0x80,0x00,0x80, // 173 + 0xE0,0x00,0x10,0x01,0xE8,0x02,0x68,0x02,0xC8,0x02,0x10,0x01,0xE0, // 174 + 0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, // 175 + 0x00,0x00,0x38,0x00,0x28,0x00,0x38, // 176 + 0x40,0x02,0x40,0x02,0xF0,0x03,0x40,0x02,0x40,0x02, // 177 + 0x48,0x00,0x68,0x00,0x58, // 178 + 0x48,0x00,0x58,0x00,0x68, // 179 + 0x00,0x00,0x10,0x00,0x08, // 180 + 0x00,0x00,0xE0,0x0F,0x00,0x02,0x00,0x02,0xE0,0x03, // 181 + 0x70,0x00,0xF8,0x0F,0x08,0x00,0xF8,0x0F,0x08, // 182 + 0x00,0x00,0x40, // 183 + 0x00,0x00,0x00,0x14,0x00,0x18, // 184 + 0x00,0x00,0x10,0x00,0x78, // 185 + 0x30,0x00,0x48,0x00,0x48,0x00,0x30, // 186 + 0x00,0x00,0x40,0x02,0x80,0x01,0x40,0x02,0x80,0x01, // 187 + 0x00,0x00,0x10,0x02,0x78,0x01,0xC0,0x00,0x20,0x01,0x90,0x01,0xC8,0x03,0x00,0x01, // 188 + 0x00,0x00,0x10,0x02,0x78,0x01,0x80,0x00,0x60,0x00,0x50,0x02,0x48,0x03,0xC0,0x02, // 189 + 0x48,0x00,0x58,0x00,0x68,0x03,0x80,0x00,0x60,0x01,0x90,0x01,0xC8,0x03,0x00,0x01, // 190 + 0x00,0x00,0x00,0x06,0x00,0x09,0xA0,0x09,0x00,0x04, // 191 + 0x00,0x02,0xC0,0x01,0xB0,0x00,0x89,0x00,0xB2,0x00,0xC0,0x01,0x00,0x02, // 192 + 0x00,0x02,0xC0,0x01,0xB0,0x00,0x8A,0x00,0xB1,0x00,0xC0,0x01,0x00,0x02, // 193 + 0x00,0x02,0xC0,0x01,0xB2,0x00,0x89,0x00,0xB2,0x00,0xC0,0x01,0x00,0x02, // 194 + 0x00,0x02,0xC2,0x01,0xB1,0x00,0x8A,0x00,0xB1,0x00,0xC0,0x01,0x00,0x02, // 195 + 0x00,0x02,0xC0,0x01,0xB2,0x00,0x88,0x00,0xB2,0x00,0xC0,0x01,0x00,0x02, // 196 + 0x00,0x02,0xC0,0x01,0xBE,0x00,0x8A,0x00,0xBE,0x00,0xC0,0x01,0x00,0x02, // 197 + 0x00,0x03,0xC0,0x00,0xE0,0x00,0x98,0x00,0x88,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x48,0x02, // 198 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x16,0x08,0x1A,0x10,0x01, // 199 + 0x00,0x00,0xF8,0x03,0x49,0x02,0x4A,0x02,0x48,0x02,0x48,0x02, // 200 + 0x00,0x00,0xF8,0x03,0x48,0x02,0x4A,0x02,0x49,0x02,0x48,0x02, // 201 + 0x00,0x00,0xFA,0x03,0x49,0x02,0x4A,0x02,0x48,0x02,0x48,0x02, // 202 + 0x00,0x00,0xF8,0x03,0x4A,0x02,0x48,0x02,0x4A,0x02,0x48,0x02, // 203 + 0x00,0x00,0xF9,0x03,0x02, // 204 + 0x02,0x00,0xF9,0x03, // 205 + 0x01,0x00,0xFA,0x03, // 206 + 0x02,0x00,0xF8,0x03,0x02, // 207 + 0x40,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x10,0x01,0xE0, // 208 + 0x00,0x00,0xFA,0x03,0x31,0x00,0x42,0x00,0x81,0x01,0xF8,0x03, // 209 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x09,0x02,0x0A,0x02,0x08,0x02,0xF0,0x01, // 210 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x0A,0x02,0x09,0x02,0x08,0x02,0xF0,0x01, // 211 + 0x00,0x00,0xF0,0x01,0x08,0x02,0x0A,0x02,0x09,0x02,0x0A,0x02,0xF0,0x01, // 212 + 0x00,0x00,0xF0,0x01,0x0A,0x02,0x09,0x02,0x0A,0x02,0x09,0x02,0xF0,0x01, // 213 + 0x00,0x00,0xF0,0x01,0x0A,0x02,0x08,0x02,0x0A,0x02,0x08,0x02,0xF0,0x01, // 214 + 0x10,0x01,0xA0,0x00,0xE0,0x00,0xA0,0x00,0x10,0x01, // 215 + 0x00,0x00,0xF0,0x02,0x08,0x03,0xC8,0x02,0x28,0x02,0x18,0x03,0xE8, // 216 + 0x00,0x00,0xF8,0x01,0x01,0x02,0x02,0x02,0x00,0x02,0xF8,0x01, // 217 + 0x00,0x00,0xF8,0x01,0x02,0x02,0x01,0x02,0x00,0x02,0xF8,0x01, // 218 + 0x00,0x00,0xF8,0x01,0x02,0x02,0x01,0x02,0x02,0x02,0xF8,0x01, // 219 + 0x00,0x00,0xF8,0x01,0x02,0x02,0x00,0x02,0x02,0x02,0xF8,0x01, // 220 + 0x08,0x00,0x10,0x00,0x20,0x00,0xC2,0x03,0x21,0x00,0x10,0x00,0x08, // 221 + 0x00,0x00,0xF8,0x03,0x10,0x01,0x10,0x01,0x10,0x01,0xE0, // 222 + 0x00,0x00,0xF0,0x03,0x08,0x01,0x48,0x02,0xB0,0x02,0x80,0x01, // 223 + 0x00,0x00,0x00,0x03,0xA4,0x02,0xA8,0x02,0xE0,0x03, // 224 + 0x00,0x00,0x00,0x03,0xA8,0x02,0xA4,0x02,0xE0,0x03, // 225 + 0x00,0x00,0x00,0x03,0xA8,0x02,0xA4,0x02,0xE8,0x03, // 226 + 0x00,0x00,0x08,0x03,0xA4,0x02,0xA8,0x02,0xE4,0x03, // 227 + 0x00,0x00,0x00,0x03,0xA8,0x02,0xA0,0x02,0xE8,0x03, // 228 + 0x00,0x00,0x00,0x03,0xAE,0x02,0xAA,0x02,0xEE,0x03, // 229 + 0x00,0x00,0x40,0x03,0xA0,0x02,0xA0,0x02,0xC0,0x01,0xA0,0x02,0xA0,0x02,0xC0,0x02, // 230 + 0x00,0x00,0xC0,0x01,0x20,0x16,0x20,0x1A,0x40,0x01, // 231 + 0x00,0x00,0xC0,0x01,0xA4,0x02,0xA8,0x02,0xC0,0x02, // 232 + 0x00,0x00,0xC0,0x01,0xA8,0x02,0xA4,0x02,0xC0,0x02, // 233 + 0x00,0x00,0xC0,0x01,0xA8,0x02,0xA4,0x02,0xC8,0x02, // 234 + 0x00,0x00,0xC0,0x01,0xA8,0x02,0xA0,0x02,0xC8,0x02, // 235 + 0x00,0x00,0xE4,0x03,0x08, // 236 + 0x08,0x00,0xE4,0x03, // 237 + 0x08,0x00,0xE4,0x03,0x08, // 238 + 0x08,0x00,0xE0,0x03,0x08, // 239 + 0x00,0x00,0xC0,0x01,0x28,0x02,0x38,0x02,0xE0,0x01, // 240 + 0x00,0x00,0xE8,0x03,0x24,0x00,0x28,0x00,0xC4,0x03, // 241 + 0x00,0x00,0xC0,0x01,0x24,0x02,0x28,0x02,0xC0,0x01, // 242 + 0x00,0x00,0xC0,0x01,0x28,0x02,0x24,0x02,0xC0,0x01, // 243 + 0x00,0x00,0xC0,0x01,0x28,0x02,0x24,0x02,0xC8,0x01, // 244 + 0x00,0x00,0xC8,0x01,0x24,0x02,0x28,0x02,0xC4,0x01, // 245 + 0x00,0x00,0xC0,0x01,0x28,0x02,0x20,0x02,0xC8,0x01, // 246 + 0x40,0x00,0x40,0x00,0x50,0x01,0x40,0x00,0x40, // 247 + 0x00,0x00,0xC0,0x02,0xA0,0x03,0x60,0x02,0xA0,0x01, // 248 + 0x00,0x00,0xE0,0x01,0x04,0x02,0x08,0x02,0xE0,0x03, // 249 + 0x00,0x00,0xE0,0x01,0x08,0x02,0x04,0x02,0xE0,0x03, // 250 + 0x00,0x00,0xE8,0x01,0x04,0x02,0x08,0x02,0xE0,0x03, // 251 + 0x00,0x00,0xE0,0x01,0x08,0x02,0x00,0x02,0xE8,0x03, // 252 + 0x20,0x00,0xC0,0x09,0x08,0x06,0xC4,0x01,0x20, // 253 + 0x00,0x00,0xF8,0x0F,0x20,0x02,0x20,0x02,0xC0,0x01, // 254 + 0x20,0x00,0xC8,0x09,0x00,0x06,0xC8,0x01,0x20 // 255 +}; + +const uint8_t ArialMT_Plain_16[] PROGMEM = { + 0x10, // Width: 16 + 0x13, // Height: 19 + 0x20, // First Char: 32 + 0xE0, // Numbers of Chars: 224 + + // Jump Table: + 0xFF, 0xFF, 0x00, 0x04, // 32:65535 + 0x00, 0x00, 0x08, 0x04, // 33:0 + 0x00, 0x08, 0x0D, 0x06, // 34:8 + 0x00, 0x15, 0x1A, 0x09, // 35:21 + 0x00, 0x2F, 0x17, 0x09, // 36:47 + 0x00, 0x46, 0x26, 0x0E, // 37:70 + 0x00, 0x6C, 0x1D, 0x0B, // 38:108 + 0x00, 0x89, 0x04, 0x03, // 39:137 + 0x00, 0x8D, 0x0C, 0x05, // 40:141 + 0x00, 0x99, 0x0B, 0x05, // 41:153 + 0x00, 0xA4, 0x0D, 0x06, // 42:164 + 0x00, 0xB1, 0x17, 0x09, // 43:177 + 0x00, 0xC8, 0x09, 0x04, // 44:200 + 0x00, 0xD1, 0x0B, 0x05, // 45:209 + 0x00, 0xDC, 0x08, 0x04, // 46:220 + 0x00, 0xE4, 0x0A, 0x04, // 47:228 + 0x00, 0xEE, 0x17, 0x09, // 48:238 + 0x01, 0x05, 0x11, 0x09, // 49:261 + 0x01, 0x16, 0x17, 0x09, // 50:278 + 0x01, 0x2D, 0x17, 0x09, // 51:301 + 0x01, 0x44, 0x17, 0x09, // 52:324 + 0x01, 0x5B, 0x17, 0x09, // 53:347 + 0x01, 0x72, 0x17, 0x09, // 54:370 + 0x01, 0x89, 0x16, 0x09, // 55:393 + 0x01, 0x9F, 0x17, 0x09, // 56:415 + 0x01, 0xB6, 0x17, 0x09, // 57:438 + 0x01, 0xCD, 0x05, 0x04, // 58:461 + 0x01, 0xD2, 0x06, 0x04, // 59:466 + 0x01, 0xD8, 0x17, 0x09, // 60:472 + 0x01, 0xEF, 0x17, 0x09, // 61:495 + 0x02, 0x06, 0x17, 0x09, // 62:518 + 0x02, 0x1D, 0x16, 0x09, // 63:541 + 0x02, 0x33, 0x2F, 0x10, // 64:563 + 0x02, 0x62, 0x1D, 0x0B, // 65:610 + 0x02, 0x7F, 0x1D, 0x0B, // 66:639 + 0x02, 0x9C, 0x20, 0x0C, // 67:668 + 0x02, 0xBC, 0x20, 0x0C, // 68:700 + 0x02, 0xDC, 0x1D, 0x0B, // 69:732 + 0x02, 0xF9, 0x19, 0x0A, // 70:761 + 0x03, 0x12, 0x20, 0x0C, // 71:786 + 0x03, 0x32, 0x1D, 0x0C, // 72:818 + 0x03, 0x4F, 0x05, 0x04, // 73:847 + 0x03, 0x54, 0x14, 0x08, // 74:852 + 0x03, 0x68, 0x1D, 0x0B, // 75:872 + 0x03, 0x85, 0x17, 0x09, // 76:901 + 0x03, 0x9C, 0x23, 0x0D, // 77:924 + 0x03, 0xBF, 0x1D, 0x0C, // 78:959 + 0x03, 0xDC, 0x20, 0x0C, // 79:988 + 0x03, 0xFC, 0x1C, 0x0B, // 80:1020 + 0x04, 0x18, 0x20, 0x0C, // 81:1048 + 0x04, 0x38, 0x1D, 0x0C, // 82:1080 + 0x04, 0x55, 0x1D, 0x0B, // 83:1109 + 0x04, 0x72, 0x19, 0x0A, // 84:1138 + 0x04, 0x8B, 0x1D, 0x0C, // 85:1163 + 0x04, 0xA8, 0x1C, 0x0B, // 86:1192 + 0x04, 0xC4, 0x2B, 0x0F, // 87:1220 + 0x04, 0xEF, 0x20, 0x0B, // 88:1263 + 0x05, 0x0F, 0x19, 0x0B, // 89:1295 + 0x05, 0x28, 0x1A, 0x0A, // 90:1320 + 0x05, 0x42, 0x0C, 0x04, // 91:1346 + 0x05, 0x4E, 0x0B, 0x04, // 92:1358 + 0x05, 0x59, 0x09, 0x04, // 93:1369 + 0x05, 0x62, 0x14, 0x08, // 94:1378 + 0x05, 0x76, 0x1B, 0x09, // 95:1398 + 0x05, 0x91, 0x07, 0x05, // 96:1425 + 0x05, 0x98, 0x17, 0x09, // 97:1432 + 0x05, 0xAF, 0x17, 0x09, // 98:1455 + 0x05, 0xC6, 0x14, 0x08, // 99:1478 + 0x05, 0xDA, 0x17, 0x09, // 100:1498 + 0x05, 0xF1, 0x17, 0x09, // 101:1521 + 0x06, 0x08, 0x0A, 0x04, // 102:1544 + 0x06, 0x12, 0x17, 0x09, // 103:1554 + 0x06, 0x29, 0x14, 0x09, // 104:1577 + 0x06, 0x3D, 0x05, 0x04, // 105:1597 + 0x06, 0x42, 0x06, 0x04, // 106:1602 + 0x06, 0x48, 0x17, 0x08, // 107:1608 + 0x06, 0x5F, 0x05, 0x04, // 108:1631 + 0x06, 0x64, 0x23, 0x0D, // 109:1636 + 0x06, 0x87, 0x14, 0x09, // 110:1671 + 0x06, 0x9B, 0x17, 0x09, // 111:1691 + 0x06, 0xB2, 0x17, 0x09, // 112:1714 + 0x06, 0xC9, 0x18, 0x09, // 113:1737 + 0x06, 0xE1, 0x0D, 0x05, // 114:1761 + 0x06, 0xEE, 0x14, 0x08, // 115:1774 + 0x07, 0x02, 0x0B, 0x04, // 116:1794 + 0x07, 0x0D, 0x14, 0x09, // 117:1805 + 0x07, 0x21, 0x13, 0x08, // 118:1825 + 0x07, 0x34, 0x1F, 0x0C, // 119:1844 + 0x07, 0x53, 0x14, 0x08, // 120:1875 + 0x07, 0x67, 0x13, 0x08, // 121:1895 + 0x07, 0x7A, 0x14, 0x08, // 122:1914 + 0x07, 0x8E, 0x0F, 0x05, // 123:1934 + 0x07, 0x9D, 0x06, 0x04, // 124:1949 + 0x07, 0xA3, 0x0E, 0x05, // 125:1955 + 0x07, 0xB1, 0x17, 0x09, // 126:1969 + 0xFF, 0xFF, 0x00, 0x00, // 127:65535 + 0xFF, 0xFF, 0x00, 0x10, // 128:65535 + 0xFF, 0xFF, 0x00, 0x10, // 129:65535 + 0xFF, 0xFF, 0x00, 0x10, // 130:65535 + 0xFF, 0xFF, 0x00, 0x10, // 131:65535 + 0xFF, 0xFF, 0x00, 0x10, // 132:65535 + 0xFF, 0xFF, 0x00, 0x10, // 133:65535 + 0xFF, 0xFF, 0x00, 0x10, // 134:65535 + 0xFF, 0xFF, 0x00, 0x10, // 135:65535 + 0xFF, 0xFF, 0x00, 0x10, // 136:65535 + 0xFF, 0xFF, 0x00, 0x10, // 137:65535 + 0xFF, 0xFF, 0x00, 0x10, // 138:65535 + 0xFF, 0xFF, 0x00, 0x10, // 139:65535 + 0xFF, 0xFF, 0x00, 0x10, // 140:65535 + 0xFF, 0xFF, 0x00, 0x10, // 141:65535 + 0xFF, 0xFF, 0x00, 0x10, // 142:65535 + 0xFF, 0xFF, 0x00, 0x10, // 143:65535 + 0xFF, 0xFF, 0x00, 0x10, // 144:65535 + 0xFF, 0xFF, 0x00, 0x10, // 145:65535 + 0xFF, 0xFF, 0x00, 0x10, // 146:65535 + 0xFF, 0xFF, 0x00, 0x10, // 147:65535 + 0xFF, 0xFF, 0x00, 0x10, // 148:65535 + 0xFF, 0xFF, 0x00, 0x10, // 149:65535 + 0xFF, 0xFF, 0x00, 0x10, // 150:65535 + 0xFF, 0xFF, 0x00, 0x10, // 151:65535 + 0xFF, 0xFF, 0x00, 0x10, // 152:65535 + 0xFF, 0xFF, 0x00, 0x10, // 153:65535 + 0xFF, 0xFF, 0x00, 0x10, // 154:65535 + 0xFF, 0xFF, 0x00, 0x10, // 155:65535 + 0xFF, 0xFF, 0x00, 0x10, // 156:65535 + 0xFF, 0xFF, 0x00, 0x10, // 157:65535 + 0xFF, 0xFF, 0x00, 0x10, // 158:65535 + 0xFF, 0xFF, 0x00, 0x10, // 159:65535 + 0xFF, 0xFF, 0x00, 0x04, // 160:65535 + 0x07, 0xC8, 0x09, 0x05, // 161:1992 + 0x07, 0xD1, 0x17, 0x09, // 162:2001 + 0x07, 0xE8, 0x17, 0x09, // 163:2024 + 0x07, 0xFF, 0x14, 0x09, // 164:2047 + 0x08, 0x13, 0x1A, 0x09, // 165:2067 + 0x08, 0x2D, 0x06, 0x04, // 166:2093 + 0x08, 0x33, 0x17, 0x09, // 167:2099 + 0x08, 0x4A, 0x07, 0x05, // 168:2122 + 0x08, 0x51, 0x23, 0x0C, // 169:2129 + 0x08, 0x74, 0x0E, 0x06, // 170:2164 + 0x08, 0x82, 0x14, 0x09, // 171:2178 + 0x08, 0x96, 0x17, 0x09, // 172:2198 + 0x08, 0xAD, 0x0B, 0x05, // 173:2221 + 0x08, 0xB8, 0x23, 0x0C, // 174:2232 + 0x08, 0xDB, 0x19, 0x09, // 175:2267 + 0x08, 0xF4, 0x0D, 0x06, // 176:2292 + 0x09, 0x01, 0x17, 0x09, // 177:2305 + 0x09, 0x18, 0x0E, 0x05, // 178:2328 + 0x09, 0x26, 0x0D, 0x05, // 179:2342 + 0x09, 0x33, 0x0A, 0x05, // 180:2355 + 0x09, 0x3D, 0x17, 0x09, // 181:2365 + 0x09, 0x54, 0x19, 0x09, // 182:2388 + 0x09, 0x6D, 0x08, 0x05, // 183:2413 + 0x09, 0x75, 0x0C, 0x05, // 184:2421 + 0x09, 0x81, 0x0B, 0x05, // 185:2433 + 0x09, 0x8C, 0x0D, 0x06, // 186:2444 + 0x09, 0x99, 0x17, 0x09, // 187:2457 + 0x09, 0xB0, 0x26, 0x0D, // 188:2480 + 0x09, 0xD6, 0x26, 0x0D, // 189:2518 + 0x09, 0xFC, 0x26, 0x0D, // 190:2556 + 0x0A, 0x22, 0x1A, 0x0A, // 191:2594 + 0x0A, 0x3C, 0x1D, 0x0B, // 192:2620 + 0x0A, 0x59, 0x1D, 0x0B, // 193:2649 + 0x0A, 0x76, 0x1D, 0x0B, // 194:2678 + 0x0A, 0x93, 0x1D, 0x0B, // 195:2707 + 0x0A, 0xB0, 0x1D, 0x0B, // 196:2736 + 0x0A, 0xCD, 0x1D, 0x0B, // 197:2765 + 0x0A, 0xEA, 0x2C, 0x10, // 198:2794 + 0x0B, 0x16, 0x20, 0x0C, // 199:2838 + 0x0B, 0x36, 0x1D, 0x0B, // 200:2870 + 0x0B, 0x53, 0x1D, 0x0B, // 201:2899 + 0x0B, 0x70, 0x1D, 0x0B, // 202:2928 + 0x0B, 0x8D, 0x1D, 0x0B, // 203:2957 + 0x0B, 0xAA, 0x05, 0x04, // 204:2986 + 0x0B, 0xAF, 0x07, 0x04, // 205:2991 + 0x0B, 0xB6, 0x0A, 0x04, // 206:2998 + 0x0B, 0xC0, 0x07, 0x04, // 207:3008 + 0x0B, 0xC7, 0x20, 0x0C, // 208:3015 + 0x0B, 0xE7, 0x1D, 0x0C, // 209:3047 + 0x0C, 0x04, 0x20, 0x0C, // 210:3076 + 0x0C, 0x24, 0x20, 0x0C, // 211:3108 + 0x0C, 0x44, 0x20, 0x0C, // 212:3140 + 0x0C, 0x64, 0x20, 0x0C, // 213:3172 + 0x0C, 0x84, 0x20, 0x0C, // 214:3204 + 0x0C, 0xA4, 0x17, 0x09, // 215:3236 + 0x0C, 0xBB, 0x20, 0x0C, // 216:3259 + 0x0C, 0xDB, 0x1D, 0x0C, // 217:3291 + 0x0C, 0xF8, 0x1D, 0x0C, // 218:3320 + 0x0D, 0x15, 0x1D, 0x0C, // 219:3349 + 0x0D, 0x32, 0x1D, 0x0C, // 220:3378 + 0x0D, 0x4F, 0x19, 0x0B, // 221:3407 + 0x0D, 0x68, 0x1D, 0x0B, // 222:3432 + 0x0D, 0x85, 0x17, 0x0A, // 223:3461 + 0x0D, 0x9C, 0x17, 0x09, // 224:3484 + 0x0D, 0xB3, 0x17, 0x09, // 225:3507 + 0x0D, 0xCA, 0x17, 0x09, // 226:3530 + 0x0D, 0xE1, 0x17, 0x09, // 227:3553 + 0x0D, 0xF8, 0x17, 0x09, // 228:3576 + 0x0E, 0x0F, 0x17, 0x09, // 229:3599 + 0x0E, 0x26, 0x29, 0x0E, // 230:3622 + 0x0E, 0x4F, 0x14, 0x08, // 231:3663 + 0x0E, 0x63, 0x17, 0x09, // 232:3683 + 0x0E, 0x7A, 0x17, 0x09, // 233:3706 + 0x0E, 0x91, 0x17, 0x09, // 234:3729 + 0x0E, 0xA8, 0x17, 0x09, // 235:3752 + 0x0E, 0xBF, 0x05, 0x04, // 236:3775 + 0x0E, 0xC4, 0x07, 0x04, // 237:3780 + 0x0E, 0xCB, 0x0A, 0x04, // 238:3787 + 0x0E, 0xD5, 0x07, 0x04, // 239:3797 + 0x0E, 0xDC, 0x17, 0x09, // 240:3804 + 0x0E, 0xF3, 0x14, 0x09, // 241:3827 + 0x0F, 0x07, 0x17, 0x09, // 242:3847 + 0x0F, 0x1E, 0x17, 0x09, // 243:3870 + 0x0F, 0x35, 0x17, 0x09, // 244:3893 + 0x0F, 0x4C, 0x17, 0x09, // 245:3916 + 0x0F, 0x63, 0x17, 0x09, // 246:3939 + 0x0F, 0x7A, 0x17, 0x09, // 247:3962 + 0x0F, 0x91, 0x17, 0x0A, // 248:3985 + 0x0F, 0xA8, 0x14, 0x09, // 249:4008 + 0x0F, 0xBC, 0x14, 0x09, // 250:4028 + 0x0F, 0xD0, 0x14, 0x09, // 251:4048 + 0x0F, 0xE4, 0x14, 0x09, // 252:4068 + 0x0F, 0xF8, 0x13, 0x08, // 253:4088 + 0x10, 0x0B, 0x17, 0x09, // 254:4107 + 0x10, 0x22, 0x13, 0x08, // 255:4130 + + // Font Data: + 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x5F, // 33 + 0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, // 34 + 0x80,0x08,0x00,0x80,0x78,0x00,0xC0,0x0F,0x00,0xB8,0x08,0x00,0x80,0x08,0x00,0x80,0x78,0x00,0xC0,0x0F,0x00,0xB8,0x08,0x00,0x80,0x08, // 35 + 0x00,0x00,0x00,0xE0,0x10,0x00,0x10,0x21,0x00,0x08,0x41,0x00,0xFC,0xFF,0x00,0x08,0x42,0x00,0x10,0x22,0x00,0x20,0x1C, // 36 + 0x00,0x00,0x00,0xF0,0x00,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x61,0x00,0xF0,0x18,0x00,0x00,0x06,0x00,0xC0,0x01,0x00,0x30,0x3C,0x00,0x08,0x42,0x00,0x00,0x42,0x00,0x00,0x42,0x00,0x00,0x3C, // 37 + 0x00,0x00,0x00,0x00,0x1C,0x00,0x70,0x22,0x00,0x88,0x41,0x00,0x08,0x43,0x00,0x88,0x44,0x00,0x70,0x28,0x00,0x00,0x10,0x00,0x00,0x28,0x00,0x00,0x44, // 38 + 0x00,0x00,0x00,0x78, // 39 + 0x00,0x00,0x00,0x80,0x3F,0x00,0x70,0xC0,0x01,0x08,0x00,0x02, // 40 + 0x00,0x00,0x00,0x08,0x00,0x02,0x70,0xC0,0x01,0x80,0x3F, // 41 + 0x10,0x00,0x00,0xD0,0x00,0x00,0x38,0x00,0x00,0xD0,0x00,0x00,0x10, // 42 + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0xC0,0x1F,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02, // 43 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01, // 44 + 0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08, // 45 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40, // 46 + 0x00,0x60,0x00,0x00,0x1E,0x00,0xE0,0x01,0x00,0x18, // 47 + 0x00,0x00,0x00,0xE0,0x1F,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0xE0,0x1F, // 48 + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0xF8,0x7F, // 49 + 0x00,0x00,0x00,0x20,0x40,0x00,0x10,0x60,0x00,0x08,0x50,0x00,0x08,0x48,0x00,0x08,0x44,0x00,0x10,0x43,0x00,0xE0,0x40, // 50 + 0x00,0x00,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x88,0x41,0x00,0xF0,0x22,0x00,0x00,0x1C, // 51 + 0x00,0x0C,0x00,0x00,0x0A,0x00,0x00,0x09,0x00,0xC0,0x08,0x00,0x20,0x08,0x00,0x10,0x08,0x00,0xF8,0x7F,0x00,0x00,0x08, // 52 + 0x00,0x00,0x00,0xC0,0x11,0x00,0xB8,0x20,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x08,0x21,0x00,0x08,0x1E, // 53 + 0x00,0x00,0x00,0xE0,0x1F,0x00,0x10,0x21,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x10,0x21,0x00,0x20,0x1E, // 54 + 0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x78,0x00,0x08,0x07,0x00,0xC8,0x00,0x00,0x28,0x00,0x00,0x18, // 55 + 0x00,0x00,0x00,0x60,0x1C,0x00,0x90,0x22,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x90,0x22,0x00,0x60,0x1C, // 56 + 0x00,0x00,0x00,0xE0,0x11,0x00,0x10,0x22,0x00,0x08,0x44,0x00,0x08,0x44,0x00,0x08,0x44,0x00,0x10,0x22,0x00,0xE0,0x1F, // 57 + 0x00,0x00,0x00,0x40,0x40, // 58 + 0x00,0x00,0x00,0x40,0xC0,0x01, // 59 + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x05,0x00,0x00,0x05,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x40,0x10, // 60 + 0x00,0x00,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08, // 61 + 0x00,0x00,0x00,0x40,0x10,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x00,0x05,0x00,0x00,0x05,0x00,0x00,0x02, // 62 + 0x00,0x00,0x00,0x60,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x08,0x5C,0x00,0x08,0x02,0x00,0x10,0x01,0x00,0xE0, // 63 + 0x00,0x00,0x00,0x00,0x3F,0x00,0xC0,0x40,0x00,0x20,0x80,0x00,0x10,0x1E,0x01,0x10,0x21,0x01,0x88,0x40,0x02,0x48,0x40,0x02,0x48,0x40,0x02,0x48,0x20,0x02,0x88,0x7C,0x02,0xC8,0x43,0x02,0x10,0x40,0x02,0x10,0x20,0x01,0x60,0x10,0x01,0x80,0x8F, // 64 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x70,0x04,0x00,0x08,0x04,0x00,0x70,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 65 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x90,0x22,0x00,0x60,0x1C, // 66 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10, // 67 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 68 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 69 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08, // 70 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x10,0x22,0x00,0x20,0x12,0x00,0x00,0x0E, // 71 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0xF8,0x7F, // 72 + 0x00,0x00,0x00,0xF8,0x7F, // 73 + 0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0xF8,0x3F, // 74 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x04,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0x80,0x03,0x00,0x40,0x04,0x00,0x20,0x18,0x00,0x10,0x20,0x00,0x08,0x40, // 75 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40, // 76 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x30,0x00,0x00,0xC0,0x00,0x00,0x00,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x03,0x00,0xC0,0x00,0x00,0x30,0x00,0x00,0xF8,0x7F, // 77 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x10,0x00,0x00,0x60,0x00,0x00,0x80,0x00,0x00,0x00,0x03,0x00,0x00,0x04,0x00,0x00,0x18,0x00,0x00,0x20,0x00,0xF8,0x7F, // 78 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 79 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x10,0x01,0x00,0xE0, // 80 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x50,0x00,0x08,0x50,0x00,0x10,0x20,0x00,0x20,0x70,0x00,0xC0,0x4F, // 81 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x06,0x00,0x08,0x1A,0x00,0x10,0x21,0x00,0xE0,0x40, // 82 + 0x00,0x00,0x00,0x60,0x10,0x00,0x90,0x20,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x10,0x22,0x00,0x20,0x1C, // 83 + 0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0xF8,0x7F,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08, // 84 + 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 85 + 0x00,0x00,0x00,0x18,0x00,0x00,0xE0,0x00,0x00,0x00,0x07,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x07,0x00,0xE0,0x00,0x00,0x18, // 86 + 0x18,0x00,0x00,0xE0,0x01,0x00,0x00,0x1E,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x03,0x00,0x70,0x00,0x00,0x08,0x00,0x00,0x70,0x00,0x00,0x80,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1E,0x00,0xE0,0x01,0x00,0x18, // 87 + 0x00,0x40,0x00,0x08,0x20,0x00,0x10,0x10,0x00,0x60,0x0C,0x00,0x80,0x02,0x00,0x00,0x01,0x00,0x80,0x02,0x00,0x60,0x0C,0x00,0x10,0x10,0x00,0x08,0x20,0x00,0x00,0x40, // 88 + 0x08,0x00,0x00,0x30,0x00,0x00,0x40,0x00,0x00,0x80,0x01,0x00,0x00,0x7E,0x00,0x80,0x01,0x00,0x40,0x00,0x00,0x30,0x00,0x00,0x08, // 89 + 0x00,0x40,0x00,0x08,0x60,0x00,0x08,0x58,0x00,0x08,0x44,0x00,0x08,0x43,0x00,0x88,0x40,0x00,0x68,0x40,0x00,0x18,0x40,0x00,0x08,0x40, // 90 + 0x00,0x00,0x00,0xF8,0xFF,0x03,0x08,0x00,0x02,0x08,0x00,0x02, // 91 + 0x18,0x00,0x00,0xE0,0x01,0x00,0x00,0x1E,0x00,0x00,0x60, // 92 + 0x08,0x00,0x02,0x08,0x00,0x02,0xF8,0xFF,0x03, // 93 + 0x00,0x01,0x00,0xC0,0x00,0x00,0x30,0x00,0x00,0x08,0x00,0x00,0x30,0x00,0x00,0xC0,0x00,0x00,0x00,0x01, // 94 + 0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02, // 95 + 0x00,0x00,0x00,0x08,0x00,0x00,0x10, // 96 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 97 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 98 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20, // 99 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0xF8,0x7F, // 100 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 101 + 0x40,0x00,0x00,0xF0,0x7F,0x00,0x48,0x00,0x00,0x48, // 102 + 0x00,0x00,0x00,0x00,0x1F,0x01,0x80,0x20,0x02,0x40,0x40,0x02,0x40,0x40,0x02,0x40,0x40,0x02,0x80,0x20,0x01,0xC0,0xFF, // 103 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F, // 104 + 0x00,0x00,0x00,0xC8,0x7F, // 105 + 0x00,0x00,0x02,0xC8,0xFF,0x01, // 106 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x06,0x00,0x00,0x19,0x00,0x80,0x20,0x00,0x40,0x40, // 107 + 0x00,0x00,0x00,0xF8,0x7F, // 108 + 0x00,0x00,0x00,0xC0,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F, // 109 + 0x00,0x00,0x00,0xC0,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F, // 110 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 111 + 0x00,0x00,0x00,0xC0,0xFF,0x03,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 112 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0xC0,0xFF,0x03, // 113 + 0x00,0x00,0x00,0xC0,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40, // 114 + 0x00,0x00,0x00,0x80,0x23,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x80,0x38, // 115 + 0x40,0x00,0x00,0xF0,0x7F,0x00,0x40,0x40,0x00,0x40,0x40, // 116 + 0x00,0x00,0x00,0xC0,0x3F,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 117 + 0xC0,0x00,0x00,0x00,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x03,0x00,0xC0, // 118 + 0xC0,0x00,0x00,0x00,0x1F,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x03,0x00,0xC0,0x00,0x00,0x00,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1F,0x00,0xC0, // 119 + 0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1B,0x00,0x00,0x04,0x00,0x00,0x1B,0x00,0x80,0x20,0x00,0x40,0x40, // 120 + 0xC0,0x01,0x00,0x00,0x06,0x02,0x00,0x38,0x02,0x00,0xE0,0x01,0x00,0x38,0x00,0x00,0x07,0x00,0xC0, // 121 + 0x40,0x40,0x00,0x40,0x60,0x00,0x40,0x58,0x00,0x40,0x44,0x00,0x40,0x43,0x00,0xC0,0x40,0x00,0x40,0x40, // 122 + 0x00,0x04,0x00,0x00,0x04,0x00,0xF0,0xFB,0x01,0x08,0x00,0x02,0x08,0x00,0x02, // 123 + 0x00,0x00,0x00,0xF8,0xFF,0x03, // 124 + 0x08,0x00,0x02,0x08,0x00,0x02,0xF0,0xFB,0x01,0x00,0x04,0x00,0x00,0x04, // 125 + 0x00,0x02,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x01, // 126 + 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xFF,0x03, // 161 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x03,0x40,0xF0,0x00,0x40,0x4E,0x00,0xC0,0x41,0x00,0xB8,0x20,0x00,0x00,0x11, // 162 + 0x00,0x41,0x00,0xE0,0x31,0x00,0x10,0x2F,0x00,0x08,0x21,0x00,0x08,0x21,0x00,0x08,0x40,0x00,0x10,0x40,0x00,0x20,0x20, // 163 + 0x00,0x00,0x00,0x40,0x0B,0x00,0x80,0x04,0x00,0x40,0x08,0x00,0x40,0x08,0x00,0x80,0x04,0x00,0x40,0x0B, // 164 + 0x08,0x0A,0x00,0x10,0x0A,0x00,0x60,0x0A,0x00,0x80,0x0B,0x00,0x00,0x7E,0x00,0x80,0x0B,0x00,0x60,0x0A,0x00,0x10,0x0A,0x00,0x08,0x0A, // 165 + 0x00,0x00,0x00,0xF8,0xF1,0x03, // 166 + 0x00,0x86,0x00,0x70,0x09,0x01,0xC8,0x10,0x02,0x88,0x10,0x02,0x08,0x21,0x02,0x08,0x61,0x02,0x30,0xD2,0x01,0x00,0x0C, // 167 + 0x08,0x00,0x00,0x00,0x00,0x00,0x08, // 168 + 0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0xC8,0x47,0x00,0x28,0x48,0x00,0x28,0x48,0x00,0x28,0x48,0x00,0x28,0x48,0x00,0x48,0x44,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 169 + 0xD0,0x00,0x00,0x48,0x01,0x00,0x28,0x01,0x00,0x28,0x01,0x00,0xF0,0x01, // 170 + 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x1B,0x00,0x80,0x20,0x00,0x00,0x04,0x00,0x00,0x1B,0x00,0x80,0x20, // 171 + 0x00,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x0F, // 172 + 0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08, // 173 + 0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0xE8,0x4F,0x00,0x28,0x41,0x00,0x28,0x41,0x00,0x28,0x43,0x00,0x28,0x45,0x00,0xC8,0x48,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 174 + 0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04, // 175 + 0x00,0x00,0x00,0x30,0x00,0x00,0x48,0x00,0x00,0x48,0x00,0x00,0x30, // 176 + 0x00,0x00,0x00,0x00,0x41,0x00,0x00,0x41,0x00,0x00,0x41,0x00,0xE0,0x4F,0x00,0x00,0x41,0x00,0x00,0x41,0x00,0x00,0x41, // 177 + 0x10,0x01,0x00,0x88,0x01,0x00,0x48,0x01,0x00,0x48,0x01,0x00,0x30,0x01, // 178 + 0x90,0x00,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x28,0x01,0x00,0xD8, // 179 + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x08, // 180 + 0x00,0x00,0x00,0xC0,0xFF,0x03,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 181 + 0xF0,0x00,0x00,0xF8,0x00,0x00,0xF8,0x01,0x00,0xF8,0x01,0x00,0xF8,0xFF,0x03,0x08,0x00,0x00,0x08,0x00,0x00,0xF8,0xFF,0x03,0x08, // 182 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // 183 + 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x02,0x00,0x00,0x03, // 184 + 0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0xF8,0x01, // 185 + 0xF0,0x00,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0xF0, // 186 + 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x1B,0x00,0x00,0x04,0x00,0x80,0x20,0x00,0x00,0x1B,0x00,0x00,0x04, // 187 + 0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x40,0x00,0xF8,0x21,0x00,0x00,0x10,0x00,0x00,0x0C,0x00,0x00,0x02,0x00,0x80,0x01,0x00,0x40,0x30,0x00,0x30,0x28,0x00,0x08,0x24,0x00,0x00,0x7E,0x00,0x00,0x20, // 188 + 0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x40,0x00,0xF8,0x31,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x03,0x00,0x80,0x00,0x00,0x60,0x44,0x00,0x10,0x62,0x00,0x08,0x52,0x00,0x00,0x52,0x00,0x00,0x4C, // 189 + 0x90,0x00,0x00,0x08,0x01,0x00,0x08,0x41,0x00,0x28,0x21,0x00,0xD8,0x18,0x00,0x00,0x04,0x00,0x00,0x03,0x00,0x80,0x00,0x00,0x40,0x30,0x00,0x30,0x28,0x00,0x08,0x24,0x00,0x00,0x7E,0x00,0x00,0x20, // 190 + 0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x10,0x01,0x00,0x08,0x02,0x40,0x07,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0xC0, // 191 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x71,0x04,0x00,0x0A,0x04,0x00,0x70,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 192 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x70,0x04,0x00,0x0A,0x04,0x00,0x71,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 193 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x72,0x04,0x00,0x09,0x04,0x00,0x71,0x04,0x00,0x82,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 194 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x72,0x04,0x00,0x09,0x04,0x00,0x72,0x04,0x00,0x81,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 195 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x72,0x04,0x00,0x08,0x04,0x00,0x72,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 196 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x7E,0x04,0x00,0x0A,0x04,0x00,0x7E,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 197 + 0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x06,0x00,0x80,0x05,0x00,0x60,0x04,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41, // 198 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x02,0x08,0xC0,0x02,0x08,0x40,0x03,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10, // 199 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x09,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 200 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x09,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 201 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x09,0x41,0x00,0x09,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 202 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 203 + 0x01,0x00,0x00,0xFA,0x7F, // 204 + 0x00,0x00,0x00,0xFA,0x7F,0x00,0x01, // 205 + 0x02,0x00,0x00,0xF9,0x7F,0x00,0x01,0x00,0x00,0x02, // 206 + 0x02,0x00,0x00,0xF8,0x7F,0x00,0x02, // 207 + 0x00,0x02,0x00,0xF8,0x7F,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 208 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x10,0x00,0x00,0x60,0x00,0x00,0x82,0x00,0x00,0x01,0x03,0x00,0x02,0x04,0x00,0x01,0x18,0x00,0x00,0x20,0x00,0xF8,0x7F, // 209 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x09,0x40,0x00,0x0A,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 210 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 211 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x09,0x40,0x00,0x0A,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 212 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 213 + 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x0A,0x40,0x00,0x08,0x40,0x00,0x0A,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 214 + 0x00,0x00,0x00,0x40,0x10,0x00,0x80,0x08,0x00,0x00,0x05,0x00,0x00,0x07,0x00,0x00,0x05,0x00,0x80,0x08,0x00,0x40,0x10, // 215 + 0x00,0x00,0x00,0xC0,0x4F,0x00,0x20,0x30,0x00,0x10,0x30,0x00,0x08,0x4C,0x00,0x08,0x42,0x00,0x08,0x41,0x00,0xC8,0x40,0x00,0x30,0x20,0x00,0x30,0x10,0x00,0xC8,0x0F, // 216 + 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x01,0x40,0x00,0x02,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 217 + 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x01,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 218 + 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x01,0x40,0x00,0x01,0x40,0x00,0x02,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 219 + 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 220 + 0x08,0x00,0x00,0x30,0x00,0x00,0x40,0x00,0x00,0x80,0x01,0x00,0x02,0x7E,0x00,0x81,0x01,0x00,0x40,0x00,0x00,0x30,0x00,0x00,0x08, // 221 + 0x00,0x00,0x00,0xF8,0x7F,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x40,0x08,0x00,0x80,0x07, // 222 + 0x00,0x00,0x00,0xE0,0x7F,0x00,0x10,0x00,0x00,0x08,0x20,0x00,0x88,0x43,0x00,0x70,0x42,0x00,0x00,0x44,0x00,0x00,0x38, // 223 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x48,0x44,0x00,0x50,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 224 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x50,0x44,0x00,0x48,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 225 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x48,0x42,0x00,0x50,0x22,0x00,0x80,0x7F, // 226 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x50,0x42,0x00,0x48,0x22,0x00,0x80,0x7F, // 227 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x50,0x44,0x00,0x40,0x44,0x00,0x50,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 228 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x5C,0x44,0x00,0x54,0x44,0x00,0x5C,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 229 + 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x42,0x00,0x40,0x22,0x00,0x80,0x3F,0x00,0x80,0x24,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 230 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x02,0x40,0xC0,0x02,0x40,0x40,0x03,0x80,0x20, // 231 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x48,0x44,0x00,0x50,0x44,0x00,0x40,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 232 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x40,0x44,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 233 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x48,0x44,0x00,0x90,0x24,0x00,0x00,0x17, // 234 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x50,0x44,0x00,0x40,0x44,0x00,0x50,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 235 + 0x08,0x00,0x00,0xD0,0x7F, // 236 + 0x00,0x00,0x00,0xD0,0x7F,0x00,0x08, // 237 + 0x10,0x00,0x00,0xC8,0x7F,0x00,0x08,0x00,0x00,0x10, // 238 + 0x10,0x00,0x00,0xC0,0x7F,0x00,0x10, // 239 + 0x00,0x00,0x00,0x00,0x1F,0x00,0xA0,0x20,0x00,0x68,0x40,0x00,0x58,0x40,0x00,0x70,0x40,0x00,0xE8,0x20,0x00,0x00,0x1F, // 240 + 0x00,0x00,0x00,0xC0,0x7F,0x00,0x90,0x00,0x00,0x48,0x00,0x00,0x50,0x00,0x00,0x48,0x00,0x00,0x80,0x7F, // 241 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x48,0x40,0x00,0x50,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 242 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x50,0x40,0x00,0x48,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 243 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x50,0x40,0x00,0x48,0x40,0x00,0x48,0x40,0x00,0x90,0x20,0x00,0x00,0x1F, // 244 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x50,0x40,0x00,0x48,0x40,0x00,0x50,0x40,0x00,0x88,0x20,0x00,0x00,0x1F, // 245 + 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x50,0x40,0x00,0x40,0x40,0x00,0x50,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 246 + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x80,0x0A,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02, // 247 + 0x00,0x00,0x00,0x00,0x5F,0x00,0x80,0x30,0x00,0x40,0x48,0x00,0x40,0x44,0x00,0x40,0x42,0x00,0x80,0x21,0x00,0x40,0x1F, // 248 + 0x00,0x00,0x00,0xC0,0x3F,0x00,0x00,0x40,0x00,0x08,0x40,0x00,0x10,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 249 + 0x00,0x00,0x00,0xC0,0x3F,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x10,0x40,0x00,0x08,0x20,0x00,0xC0,0x7F, // 250 + 0x00,0x00,0x00,0xC0,0x3F,0x00,0x10,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0xC0,0x7F, // 251 + 0x00,0x00,0x00,0xD0,0x3F,0x00,0x00,0x40,0x00,0x10,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 252 + 0xC0,0x01,0x00,0x00,0x06,0x02,0x00,0x38,0x02,0x10,0xE0,0x01,0x08,0x38,0x00,0x00,0x07,0x00,0xC0, // 253 + 0x00,0x00,0x00,0xF8,0xFF,0x03,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 254 + 0xC0,0x01,0x00,0x00,0x06,0x02,0x10,0x38,0x02,0x00,0xE0,0x01,0x10,0x38,0x00,0x00,0x07,0x00,0xC0 // 255 +}; +const uint8_t ArialMT_Plain_24[] PROGMEM = { + 0x18, // Width: 24 + 0x1C, // Height: 28 + 0x20, // First Char: 32 + 0xE0, // Numbers of Chars: 224 + + // Jump Table: + 0xFF, 0xFF, 0x00, 0x07, // 32:65535 + 0x00, 0x00, 0x13, 0x07, // 33:0 + 0x00, 0x13, 0x1A, 0x09, // 34:19 + 0x00, 0x2D, 0x33, 0x0D, // 35:45 + 0x00, 0x60, 0x2F, 0x0D, // 36:96 + 0x00, 0x8F, 0x4F, 0x15, // 37:143 + 0x00, 0xDE, 0x3B, 0x10, // 38:222 + 0x01, 0x19, 0x0A, 0x05, // 39:281 + 0x01, 0x23, 0x1C, 0x08, // 40:291 + 0x01, 0x3F, 0x1B, 0x08, // 41:319 + 0x01, 0x5A, 0x21, 0x09, // 42:346 + 0x01, 0x7B, 0x32, 0x0E, // 43:379 + 0x01, 0xAD, 0x10, 0x07, // 44:429 + 0x01, 0xBD, 0x1B, 0x08, // 45:445 + 0x01, 0xD8, 0x0F, 0x07, // 46:472 + 0x01, 0xE7, 0x19, 0x07, // 47:487 + 0x02, 0x00, 0x2F, 0x0D, // 48:512 + 0x02, 0x2F, 0x23, 0x0D, // 49:559 + 0x02, 0x52, 0x2F, 0x0D, // 50:594 + 0x02, 0x81, 0x2F, 0x0D, // 51:641 + 0x02, 0xB0, 0x2F, 0x0D, // 52:688 + 0x02, 0xDF, 0x2F, 0x0D, // 53:735 + 0x03, 0x0E, 0x2F, 0x0D, // 54:782 + 0x03, 0x3D, 0x2D, 0x0D, // 55:829 + 0x03, 0x6A, 0x2F, 0x0D, // 56:874 + 0x03, 0x99, 0x2F, 0x0D, // 57:921 + 0x03, 0xC8, 0x0F, 0x07, // 58:968 + 0x03, 0xD7, 0x10, 0x07, // 59:983 + 0x03, 0xE7, 0x2F, 0x0E, // 60:999 + 0x04, 0x16, 0x2F, 0x0E, // 61:1046 + 0x04, 0x45, 0x2E, 0x0E, // 62:1093 + 0x04, 0x73, 0x2E, 0x0D, // 63:1139 + 0x04, 0xA1, 0x5B, 0x18, // 64:1185 + 0x04, 0xFC, 0x3B, 0x10, // 65:1276 + 0x05, 0x37, 0x3B, 0x10, // 66:1335 + 0x05, 0x72, 0x3F, 0x11, // 67:1394 + 0x05, 0xB1, 0x3F, 0x11, // 68:1457 + 0x05, 0xF0, 0x3B, 0x10, // 69:1520 + 0x06, 0x2B, 0x35, 0x0F, // 70:1579 + 0x06, 0x60, 0x43, 0x13, // 71:1632 + 0x06, 0xA3, 0x3B, 0x11, // 72:1699 + 0x06, 0xDE, 0x0F, 0x07, // 73:1758 + 0x06, 0xED, 0x27, 0x0C, // 74:1773 + 0x07, 0x14, 0x3F, 0x10, // 75:1812 + 0x07, 0x53, 0x2F, 0x0D, // 76:1875 + 0x07, 0x82, 0x43, 0x14, // 77:1922 + 0x07, 0xC5, 0x3B, 0x11, // 78:1989 + 0x08, 0x00, 0x47, 0x13, // 79:2048 + 0x08, 0x47, 0x3A, 0x10, // 80:2119 + 0x08, 0x81, 0x47, 0x13, // 81:2177 + 0x08, 0xC8, 0x3F, 0x11, // 82:2248 + 0x09, 0x07, 0x3B, 0x10, // 83:2311 + 0x09, 0x42, 0x35, 0x0F, // 84:2370 + 0x09, 0x77, 0x3B, 0x11, // 85:2423 + 0x09, 0xB2, 0x39, 0x10, // 86:2482 + 0x09, 0xEB, 0x59, 0x17, // 87:2539 + 0x0A, 0x44, 0x3B, 0x10, // 88:2628 + 0x0A, 0x7F, 0x3D, 0x10, // 89:2687 + 0x0A, 0xBC, 0x37, 0x0F, // 90:2748 + 0x0A, 0xF3, 0x14, 0x07, // 91:2803 + 0x0B, 0x07, 0x1B, 0x07, // 92:2823 + 0x0B, 0x22, 0x18, 0x07, // 93:2850 + 0x0B, 0x3A, 0x2A, 0x0B, // 94:2874 + 0x0B, 0x64, 0x34, 0x0D, // 95:2916 + 0x0B, 0x98, 0x11, 0x08, // 96:2968 + 0x0B, 0xA9, 0x2F, 0x0D, // 97:2985 + 0x0B, 0xD8, 0x33, 0x0D, // 98:3032 + 0x0C, 0x0B, 0x2B, 0x0C, // 99:3083 + 0x0C, 0x36, 0x2F, 0x0D, // 100:3126 + 0x0C, 0x65, 0x2F, 0x0D, // 101:3173 + 0x0C, 0x94, 0x1A, 0x07, // 102:3220 + 0x0C, 0xAE, 0x2F, 0x0D, // 103:3246 + 0x0C, 0xDD, 0x2F, 0x0D, // 104:3293 + 0x0D, 0x0C, 0x0F, 0x05, // 105:3340 + 0x0D, 0x1B, 0x10, 0x05, // 106:3355 + 0x0D, 0x2B, 0x2F, 0x0C, // 107:3371 + 0x0D, 0x5A, 0x0F, 0x05, // 108:3418 + 0x0D, 0x69, 0x47, 0x14, // 109:3433 + 0x0D, 0xB0, 0x2F, 0x0D, // 110:3504 + 0x0D, 0xDF, 0x2F, 0x0D, // 111:3551 + 0x0E, 0x0E, 0x33, 0x0D, // 112:3598 + 0x0E, 0x41, 0x30, 0x0D, // 113:3649 + 0x0E, 0x71, 0x1E, 0x08, // 114:3697 + 0x0E, 0x8F, 0x2B, 0x0C, // 115:3727 + 0x0E, 0xBA, 0x1B, 0x07, // 116:3770 + 0x0E, 0xD5, 0x2F, 0x0D, // 117:3797 + 0x0F, 0x04, 0x2A, 0x0C, // 118:3844 + 0x0F, 0x2E, 0x42, 0x11, // 119:3886 + 0x0F, 0x70, 0x2B, 0x0C, // 120:3952 + 0x0F, 0x9B, 0x2A, 0x0C, // 121:3995 + 0x0F, 0xC5, 0x2B, 0x0C, // 122:4037 + 0x0F, 0xF0, 0x1C, 0x08, // 123:4080 + 0x10, 0x0C, 0x10, 0x06, // 124:4108 + 0x10, 0x1C, 0x1B, 0x08, // 125:4124 + 0x10, 0x37, 0x32, 0x0E, // 126:4151 + 0xFF, 0xFF, 0x00, 0x00, // 127:65535 + 0xFF, 0xFF, 0x00, 0x18, // 128:65535 + 0xFF, 0xFF, 0x00, 0x18, // 129:65535 + 0xFF, 0xFF, 0x00, 0x18, // 130:65535 + 0xFF, 0xFF, 0x00, 0x18, // 131:65535 + 0xFF, 0xFF, 0x00, 0x18, // 132:65535 + 0xFF, 0xFF, 0x00, 0x18, // 133:65535 + 0xFF, 0xFF, 0x00, 0x18, // 134:65535 + 0xFF, 0xFF, 0x00, 0x18, // 135:65535 + 0xFF, 0xFF, 0x00, 0x18, // 136:65535 + 0xFF, 0xFF, 0x00, 0x18, // 137:65535 + 0xFF, 0xFF, 0x00, 0x18, // 138:65535 + 0xFF, 0xFF, 0x00, 0x18, // 139:65535 + 0xFF, 0xFF, 0x00, 0x18, // 140:65535 + 0xFF, 0xFF, 0x00, 0x18, // 141:65535 + 0xFF, 0xFF, 0x00, 0x18, // 142:65535 + 0xFF, 0xFF, 0x00, 0x18, // 143:65535 + 0xFF, 0xFF, 0x00, 0x18, // 144:65535 + 0xFF, 0xFF, 0x00, 0x18, // 145:65535 + 0xFF, 0xFF, 0x00, 0x18, // 146:65535 + 0xFF, 0xFF, 0x00, 0x18, // 147:65535 + 0xFF, 0xFF, 0x00, 0x18, // 148:65535 + 0xFF, 0xFF, 0x00, 0x18, // 149:65535 + 0xFF, 0xFF, 0x00, 0x18, // 150:65535 + 0xFF, 0xFF, 0x00, 0x18, // 151:65535 + 0xFF, 0xFF, 0x00, 0x18, // 152:65535 + 0xFF, 0xFF, 0x00, 0x18, // 153:65535 + 0xFF, 0xFF, 0x00, 0x18, // 154:65535 + 0xFF, 0xFF, 0x00, 0x18, // 155:65535 + 0xFF, 0xFF, 0x00, 0x18, // 156:65535 + 0xFF, 0xFF, 0x00, 0x18, // 157:65535 + 0xFF, 0xFF, 0x00, 0x18, // 158:65535 + 0xFF, 0xFF, 0x00, 0x18, // 159:65535 + 0xFF, 0xFF, 0x00, 0x07, // 160:65535 + 0x10, 0x69, 0x14, 0x08, // 161:4201 + 0x10, 0x7D, 0x2B, 0x0D, // 162:4221 + 0x10, 0xA8, 0x2F, 0x0D, // 163:4264 + 0x10, 0xD7, 0x33, 0x0D, // 164:4311 + 0x11, 0x0A, 0x31, 0x0D, // 165:4362 + 0x11, 0x3B, 0x10, 0x06, // 166:4411 + 0x11, 0x4B, 0x2F, 0x0D, // 167:4427 + 0x11, 0x7A, 0x19, 0x08, // 168:4474 + 0x11, 0x93, 0x46, 0x12, // 169:4499 + 0x11, 0xD9, 0x1A, 0x09, // 170:4569 + 0x11, 0xF3, 0x27, 0x0D, // 171:4595 + 0x12, 0x1A, 0x2F, 0x0E, // 172:4634 + 0x12, 0x49, 0x1B, 0x08, // 173:4681 + 0x12, 0x64, 0x46, 0x12, // 174:4708 + 0x12, 0xAA, 0x31, 0x0D, // 175:4778 + 0x12, 0xDB, 0x1E, 0x0A, // 176:4827 + 0x12, 0xF9, 0x33, 0x0D, // 177:4857 + 0x13, 0x2C, 0x1A, 0x08, // 178:4908 + 0x13, 0x46, 0x1A, 0x08, // 179:4934 + 0x13, 0x60, 0x19, 0x08, // 180:4960 + 0x13, 0x79, 0x2F, 0x0E, // 181:4985 + 0x13, 0xA8, 0x31, 0x0D, // 182:5032 + 0x13, 0xD9, 0x12, 0x08, // 183:5081 + 0x13, 0xEB, 0x18, 0x08, // 184:5099 + 0x14, 0x03, 0x16, 0x08, // 185:5123 + 0x14, 0x19, 0x1E, 0x09, // 186:5145 + 0x14, 0x37, 0x2E, 0x0D, // 187:5175 + 0x14, 0x65, 0x4F, 0x14, // 188:5221 + 0x14, 0xB4, 0x4B, 0x14, // 189:5300 + 0x14, 0xFF, 0x4B, 0x14, // 190:5375 + 0x15, 0x4A, 0x33, 0x0F, // 191:5450 + 0x15, 0x7D, 0x3B, 0x10, // 192:5501 + 0x15, 0xB8, 0x3B, 0x10, // 193:5560 + 0x15, 0xF3, 0x3B, 0x10, // 194:5619 + 0x16, 0x2E, 0x3B, 0x10, // 195:5678 + 0x16, 0x69, 0x3B, 0x10, // 196:5737 + 0x16, 0xA4, 0x3B, 0x10, // 197:5796 + 0x16, 0xDF, 0x5B, 0x18, // 198:5855 + 0x17, 0x3A, 0x3F, 0x11, // 199:5946 + 0x17, 0x79, 0x3B, 0x10, // 200:6009 + 0x17, 0xB4, 0x3B, 0x10, // 201:6068 + 0x17, 0xEF, 0x3B, 0x10, // 202:6127 + 0x18, 0x2A, 0x3B, 0x10, // 203:6186 + 0x18, 0x65, 0x11, 0x07, // 204:6245 + 0x18, 0x76, 0x11, 0x07, // 205:6262 + 0x18, 0x87, 0x15, 0x07, // 206:6279 + 0x18, 0x9C, 0x15, 0x07, // 207:6300 + 0x18, 0xB1, 0x3F, 0x11, // 208:6321 + 0x18, 0xF0, 0x3B, 0x11, // 209:6384 + 0x19, 0x2B, 0x47, 0x13, // 210:6443 + 0x19, 0x72, 0x47, 0x13, // 211:6514 + 0x19, 0xB9, 0x47, 0x13, // 212:6585 + 0x1A, 0x00, 0x47, 0x13, // 213:6656 + 0x1A, 0x47, 0x47, 0x13, // 214:6727 + 0x1A, 0x8E, 0x2B, 0x0E, // 215:6798 + 0x1A, 0xB9, 0x47, 0x13, // 216:6841 + 0x1B, 0x00, 0x3B, 0x11, // 217:6912 + 0x1B, 0x3B, 0x3B, 0x11, // 218:6971 + 0x1B, 0x76, 0x3B, 0x11, // 219:7030 + 0x1B, 0xB1, 0x3B, 0x11, // 220:7089 + 0x1B, 0xEC, 0x3D, 0x10, // 221:7148 + 0x1C, 0x29, 0x3A, 0x10, // 222:7209 + 0x1C, 0x63, 0x37, 0x0F, // 223:7267 + 0x1C, 0x9A, 0x2F, 0x0D, // 224:7322 + 0x1C, 0xC9, 0x2F, 0x0D, // 225:7369 + 0x1C, 0xF8, 0x2F, 0x0D, // 226:7416 + 0x1D, 0x27, 0x2F, 0x0D, // 227:7463 + 0x1D, 0x56, 0x2F, 0x0D, // 228:7510 + 0x1D, 0x85, 0x2F, 0x0D, // 229:7557 + 0x1D, 0xB4, 0x53, 0x15, // 230:7604 + 0x1E, 0x07, 0x2B, 0x0C, // 231:7687 + 0x1E, 0x32, 0x2F, 0x0D, // 232:7730 + 0x1E, 0x61, 0x2F, 0x0D, // 233:7777 + 0x1E, 0x90, 0x2F, 0x0D, // 234:7824 + 0x1E, 0xBF, 0x2F, 0x0D, // 235:7871 + 0x1E, 0xEE, 0x11, 0x07, // 236:7918 + 0x1E, 0xFF, 0x11, 0x07, // 237:7935 + 0x1F, 0x10, 0x15, 0x07, // 238:7952 + 0x1F, 0x25, 0x15, 0x07, // 239:7973 + 0x1F, 0x3A, 0x2F, 0x0D, // 240:7994 + 0x1F, 0x69, 0x2F, 0x0D, // 241:8041 + 0x1F, 0x98, 0x2F, 0x0D, // 242:8088 + 0x1F, 0xC7, 0x2F, 0x0D, // 243:8135 + 0x1F, 0xF6, 0x2F, 0x0D, // 244:8182 + 0x20, 0x25, 0x2F, 0x0D, // 245:8229 + 0x20, 0x54, 0x2F, 0x0D, // 246:8276 + 0x20, 0x83, 0x32, 0x0D, // 247:8323 + 0x20, 0xB5, 0x33, 0x0F, // 248:8373 + 0x20, 0xE8, 0x2F, 0x0D, // 249:8424 + 0x21, 0x17, 0x2F, 0x0D, // 250:8471 + 0x21, 0x46, 0x2F, 0x0D, // 251:8518 + 0x21, 0x75, 0x2F, 0x0D, // 252:8565 + 0x21, 0xA4, 0x2A, 0x0C, // 253:8612 + 0x21, 0xCE, 0x2F, 0x0D, // 254:8654 + 0x21, 0xFD, 0x2A, 0x0C, // 255:8701 + + // Font Data: + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x33,0x00,0xE0,0xFF,0x33, // 33 + 0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xE0,0x07, // 34 + 0x00,0x0C,0x03,0x00,0x00,0x0C,0x33,0x00,0x00,0x0C,0x3F,0x00,0x00,0xFC,0x0F,0x00,0x80,0xFF,0x03,0x00,0xE0,0x0F,0x03,0x00,0x60,0x0C,0x33,0x00,0x00,0x0C,0x3F,0x00,0x00,0xFC,0x0F,0x00,0x80,0xFF,0x03,0x00,0xE0,0x0F,0x03,0x00,0x60,0x0C,0x03,0x00,0x00,0x0C,0x03, // 35 + 0x00,0x00,0x00,0x00,0x80,0x07,0x06,0x00,0xC0,0x0F,0x1E,0x00,0xC0,0x18,0x1C,0x00,0x60,0x18,0x38,0x00,0x60,0x30,0x30,0x00,0xF0,0xFF,0xFF,0x00,0x60,0x30,0x30,0x00,0x60,0x60,0x38,0x00,0xC0,0x60,0x18,0x00,0xC0,0xC1,0x1F,0x00,0x00,0x81,0x07, // 36 + 0x00,0x00,0x00,0x00,0x80,0x0F,0x00,0x00,0xC0,0x1F,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x00,0x60,0x30,0x38,0x00,0xC0,0x1F,0x1E,0x00,0x80,0x8F,0x0F,0x00,0x00,0xC0,0x03,0x00,0x00,0xF0,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x8F,0x0F,0x00,0xC0,0xC3,0x1F,0x00,0xE0,0x60,0x30,0x00,0x20,0x20,0x20,0x00,0x00,0x20,0x20,0x00,0x00,0x60,0x30,0x00,0x00,0xC0,0x1F,0x00,0x00,0x80,0x0F, // 37 + 0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xC0,0x0F,0x00,0x80,0xE3,0x1C,0x00,0xC0,0x77,0x38,0x00,0xE0,0x3C,0x30,0x00,0x60,0x38,0x30,0x00,0x60,0x78,0x30,0x00,0xE0,0xEC,0x38,0x00,0xC0,0x8F,0x1B,0x00,0x80,0x03,0x1F,0x00,0x00,0x00,0x0F,0x00,0x00,0xC0,0x1F,0x00,0x00,0xC0,0x38,0x00,0x00,0x00,0x10, // 38 + 0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xE0,0x07, // 39 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x0F,0x00,0x00,0xFE,0x7F,0x00,0x80,0x0F,0xF0,0x01,0xC0,0x01,0x80,0x03,0x60,0x00,0x00,0x06,0x20,0x00,0x00,0x04, // 40 + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x04,0x60,0x00,0x00,0x06,0xC0,0x01,0x80,0x03,0x80,0x0F,0xF0,0x01,0x00,0xFE,0x7F,0x00,0x00,0xF0,0x0F, // 41 + 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x0F,0x00,0x00,0xE0,0x03,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x80,0x04,0x00,0x00,0x80, // 42 + 0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xFF,0x0F,0x00,0x00,0xFF,0x0F,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 43 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x03,0x00,0x00,0xF0,0x01, // 44 + 0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01, // 45 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30, // 46 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0xE0,0x0F,0x00,0x00,0xFC,0x01,0x00,0x80,0x3F,0x00,0x00,0xE0,0x03,0x00,0x00,0x60, // 47 + 0x00,0x00,0x00,0x00,0x00,0xFE,0x03,0x00,0x80,0xFF,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xE0,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x01,0x1C,0x00,0x80,0xFF,0x0F,0x00,0x00,0xFE,0x03, // 48 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x00,0x80,0x01,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 49 + 0x00,0x00,0x00,0x00,0x00,0x03,0x30,0x00,0xC0,0x03,0x38,0x00,0xC0,0x00,0x3C,0x00,0x60,0x00,0x36,0x00,0x60,0x00,0x33,0x00,0x60,0x80,0x31,0x00,0x60,0xC0,0x30,0x00,0x60,0x60,0x30,0x00,0xC0,0x30,0x30,0x00,0xC0,0x1F,0x30,0x00,0x00,0x0F,0x30, // 50 + 0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x00,0xC0,0x01,0x0E,0x00,0xC0,0x00,0x1C,0x00,0x60,0x00,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0xC0,0x38,0x30,0x00,0xC0,0x6F,0x18,0x00,0x80,0xC7,0x0F,0x00,0x00,0x80,0x07, // 51 + 0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x03,0x00,0x00,0xF0,0x03,0x00,0x00,0x3C,0x03,0x00,0x00,0x0E,0x03,0x00,0x80,0x07,0x03,0x00,0xC0,0x01,0x03,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03, // 52 + 0x00,0x00,0x00,0x00,0x00,0x30,0x06,0x00,0x80,0x3F,0x0E,0x00,0xE0,0x1F,0x18,0x00,0x60,0x08,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x18,0x1C,0x00,0x60,0xF0,0x0F,0x00,0x00,0xE0,0x03, // 53 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x03,0x00,0x80,0xFF,0x0F,0x00,0xC0,0x63,0x1C,0x00,0xC0,0x30,0x38,0x00,0x60,0x18,0x30,0x00,0x60,0x18,0x30,0x00,0x60,0x18,0x30,0x00,0x60,0x18,0x30,0x00,0xE0,0x30,0x18,0x00,0xC0,0xF1,0x0F,0x00,0x80,0xC1,0x07, // 54 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x3C,0x00,0x60,0x80,0x3F,0x00,0x60,0xE0,0x03,0x00,0x60,0x78,0x00,0x00,0x60,0x0E,0x00,0x00,0x60,0x03,0x00,0x00,0xE0,0x01,0x00,0x00,0x60, // 55 + 0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x80,0xC7,0x1F,0x00,0xC0,0x6F,0x18,0x00,0xE0,0x38,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0xE0,0x38,0x30,0x00,0xC0,0x6F,0x18,0x00,0x80,0xC7,0x1F,0x00,0x00,0x80,0x07, // 56 + 0x00,0x00,0x00,0x00,0x00,0x1F,0x0C,0x00,0x80,0x7F,0x1C,0x00,0xC0,0x61,0x38,0x00,0x60,0xC0,0x30,0x00,0x60,0xC0,0x30,0x00,0x60,0xC0,0x30,0x00,0x60,0xC0,0x30,0x00,0x60,0x60,0x18,0x00,0xC0,0x31,0x1E,0x00,0x80,0xFF,0x0F,0x00,0x00,0xFE,0x01, // 57 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30, // 58 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x30,0x03,0x00,0x06,0xF0,0x01, // 59 + 0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0xD8,0x00,0x00,0x00,0xD8,0x00,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x04,0x01,0x00,0x00,0x06,0x03,0x00,0x00,0x06,0x03,0x00,0x00,0x03,0x06, // 60 + 0x00,0x00,0x00,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01, // 61 + 0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x00,0x00,0x06,0x03,0x00,0x00,0x06,0x03,0x00,0x00,0x04,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0xD8,0x00,0x00,0x00,0xD8,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x20, // 62 + 0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,0x60,0x80,0x33,0x00,0x60,0xC0,0x33,0x00,0x60,0xE0,0x00,0x00,0x60,0x30,0x00,0x00,0xC0,0x38,0x00,0x00,0xC0,0x1F,0x00,0x00,0x00,0x07, // 63 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x1E,0xF0,0x00,0x00,0x07,0xC0,0x01,0x80,0xC3,0x87,0x01,0xC0,0xF1,0x9F,0x03,0xC0,0x38,0x18,0x03,0xC0,0x0C,0x30,0x03,0x60,0x0E,0x30,0x06,0x60,0x06,0x30,0x06,0x60,0x06,0x18,0x06,0x60,0x06,0x0C,0x06,0x60,0x0C,0x1E,0x06,0x60,0xF8,0x3F,0x06,0xE0,0xFE,0x31,0x06,0xC0,0x0E,0x30,0x06,0xC0,0x01,0x18,0x03,0x80,0x03,0x1C,0x03,0x00,0x07,0x8F,0x01,0x00,0xFE,0x87,0x01,0x00,0xF8,0xC1,0x00,0x00,0x00,0x40, // 64 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x80,0x8F,0x01,0x00,0xE0,0x83,0x01,0x00,0x60,0x80,0x01,0x00,0xE0,0x83,0x01,0x00,0x80,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 65 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0xC0,0x78,0x30,0x00,0xC0,0xFF,0x18,0x00,0x80,0xC7,0x1F,0x00,0x00,0x80,0x07, // 66 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0F,0x00,0x00,0x02,0x03, // 67 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0E,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 68 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 69 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60, // 70 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x18,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x60,0x30,0x00,0x60,0x60,0x30,0x00,0xE0,0x60,0x38,0x00,0xC0,0x60,0x18,0x00,0xC0,0x61,0x18,0x00,0x80,0xE3,0x0F,0x00,0x00,0xE2,0x0F, // 71 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 72 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 73 + 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0xE0,0xFF,0x1F,0x00,0xE0,0xFF,0x0F, // 74 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xE7,0x01,0x00,0x80,0x83,0x07,0x00,0xC0,0x01,0x0F,0x00,0xE0,0x00,0x1E,0x00,0x60,0x00,0x38,0x00,0x20,0x00,0x30,0x00,0x00,0x00,0x20, // 75 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30, // 76 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0x01,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3F,0x00,0x00,0xE0,0x07,0x00,0x00,0xFE,0x00,0x00,0xC0,0x0F,0x00,0x00,0xE0,0x01,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 77 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0xC0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0xE0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 78 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 79 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0xC0,0x30,0x00,0x00,0xC0,0x3F,0x00,0x00,0x00,0x0F, // 80 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x0C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x18,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x36,0x00,0x60,0x00,0x36,0x00,0xE0,0x00,0x3C,0x00,0xC0,0x00,0x1C,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x3F,0x00,0x00,0xFF,0x77,0x00,0x00,0xFC,0x61, // 81 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x70,0x00,0x00,0x60,0xF0,0x00,0x00,0x60,0xF0,0x03,0x00,0x60,0xB0,0x07,0x00,0xE0,0x18,0x1F,0x00,0xC0,0x1F,0x3C,0x00,0x80,0x0F,0x30,0x00,0x00,0x00,0x20, // 82 + 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x07,0x0F,0x00,0xC0,0x1F,0x1C,0x00,0xC0,0x18,0x18,0x00,0x60,0x38,0x38,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x70,0x30,0x00,0xC0,0x60,0x18,0x00,0xC0,0xE1,0x18,0x00,0x80,0xC3,0x0F,0x00,0x00,0x83,0x07, // 83 + 0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 84 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 85 + 0x20,0x00,0x00,0x00,0xE0,0x01,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0xF8,0x01,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x3E,0x00,0x00,0xC0,0x0F,0x00,0x00,0xF8,0x01,0x00,0x00,0x3E,0x00,0x00,0xC0,0x0F,0x00,0x00,0xE0,0x01,0x00,0x00,0x20, // 86 + 0x60,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0x80,0xFF,0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x80,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3F,0x00,0x00,0xE0,0x0F,0x00,0x00,0xFC,0x01,0x00,0x80,0x1F,0x00,0x00,0xE0,0x03,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xE0,0x0F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x80,0x3F,0x00,0x00,0xF8,0x0F,0x00,0x80,0xFF,0x00,0x00,0xE0,0x07,0x00,0x00,0x60, // 87 + 0x00,0x00,0x20,0x00,0x20,0x00,0x30,0x00,0x60,0x00,0x3C,0x00,0xE0,0x01,0x1E,0x00,0xC0,0x83,0x07,0x00,0x00,0xCF,0x03,0x00,0x00,0xFE,0x01,0x00,0x00,0x38,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0xCF,0x03,0x00,0xC0,0x03,0x07,0x00,0xE0,0x01,0x1E,0x00,0x60,0x00,0x3C,0x00,0x20,0x00,0x30,0x00,0x00,0x00,0x20, // 88 + 0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xC0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0xF0,0x3F,0x00,0x00,0xF0,0x3F,0x00,0x00,0x3C,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x07,0x00,0x00,0xC0,0x03,0x00,0x00,0xE0,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x20, // 89 + 0x00,0x00,0x30,0x00,0x60,0x00,0x38,0x00,0x60,0x00,0x3C,0x00,0x60,0x00,0x37,0x00,0x60,0x80,0x33,0x00,0x60,0xC0,0x31,0x00,0x60,0xE0,0x30,0x00,0x60,0x38,0x30,0x00,0x60,0x1C,0x30,0x00,0x60,0x0E,0x30,0x00,0x60,0x07,0x30,0x00,0xE0,0x01,0x30,0x00,0xE0,0x00,0x30,0x00,0x60,0x00,0x30, // 90 + 0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06, // 91 + 0x60,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x3F,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xE0,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 92 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07, // 93 + 0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1F,0x00,0x00,0xC0,0x07,0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xC0,0x07,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x20, // 94 + 0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06, // 95 + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x80, // 96 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x00,0x86,0x31,0x00,0x00,0x86,0x31,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x18,0x00,0x00,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 97 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xE0,0x03, // 98 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0x18,0x0C, // 99 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0C,0x18,0x00,0x00,0x18,0x0C,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 100 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x00,0xCE,0x38,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xCE,0x38,0x00,0x00,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 101 + 0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0xC0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x06,0x00,0x00,0x60,0x06,0x00,0x00,0x60,0x06, // 102 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x83,0x01,0x00,0xF8,0x8F,0x03,0x00,0x1C,0x1C,0x07,0x00,0x0E,0x38,0x06,0x00,0x06,0x30,0x06,0x00,0x06,0x30,0x06,0x00,0x06,0x30,0x06,0x00,0x0C,0x18,0x07,0x00,0x18,0x8C,0x03,0x00,0xFE,0xFF,0x01,0x00,0xFE,0xFF, // 103 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 104 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xFE,0x3F,0x00,0x60,0xFE,0x3F, // 105 + 0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x60,0xFE,0xFF,0x07,0x60,0xFE,0xFF,0x03, // 106 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xF0,0x01,0x00,0x00,0x98,0x07,0x00,0x00,0x0C,0x0E,0x00,0x00,0x06,0x3C,0x00,0x00,0x02,0x30,0x00,0x00,0x00,0x20, // 107 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 108 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 109 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 110 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 111 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x07,0x00,0xFE,0xFF,0x07,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xE0,0x03, // 112 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0C,0x18,0x00,0x00,0x18,0x0C,0x00,0x00,0xFE,0xFF,0x07,0x00,0xFE,0xFF,0x07, // 113 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06, // 114 + 0x00,0x00,0x00,0x00,0x00,0x38,0x0C,0x00,0x00,0x7C,0x1C,0x00,0x00,0xEE,0x38,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x31,0x00,0x00,0xC6,0x31,0x00,0x00,0x8E,0x39,0x00,0x00,0x9C,0x1F,0x00,0x00,0x18,0x0F, // 115 + 0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0xC0,0xFF,0x1F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30, // 116 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 117 + 0x00,0x06,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xC0,0x07,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1F,0x00,0x00,0xC0,0x07,0x00,0x00,0xF8,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x06, // 118 + 0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x80,0x1F,0x00,0x00,0xE0,0x03,0x00,0x00,0x7C,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x80,0x1F,0x00,0x00,0xF0,0x03,0x00,0x00,0x7E,0x00,0x00,0x00,0x0E, // 119 + 0x00,0x02,0x20,0x00,0x00,0x06,0x30,0x00,0x00,0x1E,0x3C,0x00,0x00,0x38,0x0E,0x00,0x00,0xF0,0x07,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x07,0x00,0x00,0x38,0x0E,0x00,0x00,0x1C,0x3C,0x00,0x00,0x0E,0x30,0x00,0x00,0x02,0x20, // 120 + 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0x00,0xF0,0x01,0x06,0x00,0x80,0x0F,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xFC,0x00,0x00,0xC0,0x1F,0x00,0x00,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06, // 121 + 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x06,0x3C,0x00,0x00,0x06,0x3E,0x00,0x00,0x06,0x37,0x00,0x00,0xC6,0x33,0x00,0x00,0xE6,0x30,0x00,0x00,0x76,0x30,0x00,0x00,0x3E,0x30,0x00,0x00,0x1E,0x30,0x00,0x00,0x06,0x30, // 122 + 0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x03,0x00,0xC0,0x7F,0xFE,0x03,0xE0,0x3F,0xFC,0x07,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06, // 123 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x0F,0xE0,0xFF,0xFF,0x0F, // 124 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06,0xE0,0x3F,0xFC,0x07,0xC0,0x7F,0xFF,0x03,0x00,0xC0,0x03,0x00,0x00,0x80,0x01, // 125 + 0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x60, // 126 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0xFF,0x07,0x00,0xE6,0xFF,0x07, // 161 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x9C,0x07,0x00,0x0E,0x78,0x00,0x00,0x06,0x3F,0x00,0x00,0xF6,0x30,0x00,0x00,0x0E,0x30,0x00,0xE0,0x0D,0x1C,0x00,0x00,0x1C,0x0E,0x00,0x00,0x10,0x06, // 162 + 0x00,0x60,0x10,0x00,0x00,0x60,0x38,0x00,0x00,0x7F,0x1C,0x00,0xC0,0xFF,0x1F,0x00,0xE0,0xE0,0x19,0x00,0x60,0x60,0x18,0x00,0x60,0x60,0x18,0x00,0x60,0x60,0x30,0x00,0xE0,0x00,0x30,0x00,0xC0,0x01,0x30,0x00,0x80,0x01,0x38,0x00,0x00,0x00,0x10, // 163 + 0x00,0x00,0x00,0x00,0x00,0x02,0x04,0x00,0x00,0xF7,0x0E,0x00,0x00,0xFE,0x07,0x00,0x00,0x0C,0x03,0x00,0x00,0x06,0x06,0x00,0x00,0x06,0x06,0x00,0x00,0x06,0x06,0x00,0x00,0x06,0x06,0x00,0x00,0x0C,0x03,0x00,0x00,0xFE,0x07,0x00,0x00,0xF7,0x0E,0x00,0x00,0x02,0x04, // 164 + 0xE0,0x60,0x06,0x00,0xC0,0x61,0x06,0x00,0x80,0x67,0x06,0x00,0x00,0x7E,0x06,0x00,0x00,0x7C,0x06,0x00,0x00,0xF0,0x3F,0x00,0x00,0xF0,0x3F,0x00,0x00,0x7C,0x06,0x00,0x00,0x7E,0x06,0x00,0x80,0x67,0x06,0x00,0xC0,0x61,0x06,0x00,0xE0,0x60,0x06,0x00,0x20, // 165 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0xF8,0x0F,0xE0,0x7F,0xF8,0x0F, // 166 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x80,0xF3,0xC1,0x00,0xC0,0x1F,0xC3,0x03,0xE0,0x0C,0x07,0x03,0x60,0x1C,0x06,0x06,0x60,0x18,0x0C,0x06,0x60,0x30,0x1C,0x06,0xE0,0x70,0x38,0x07,0xC0,0xE1,0xF4,0x03,0x80,0xC1,0xE7,0x01,0x00,0x80,0x03, // 167 + 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 168 + 0x00,0xF8,0x00,0x00,0x00,0xFE,0x03,0x00,0x00,0x07,0x07,0x00,0x80,0x01,0x0C,0x00,0xC0,0x79,0x1C,0x00,0xC0,0xFE,0x19,0x00,0x60,0x86,0x31,0x00,0x60,0x03,0x33,0x00,0x60,0x03,0x33,0x00,0x60,0x03,0x33,0x00,0x60,0x03,0x33,0x00,0x60,0x87,0x33,0x00,0xC0,0x86,0x19,0x00,0xC0,0x85,0x1C,0x00,0x80,0x01,0x0C,0x00,0x00,0x07,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xF8, // 169 + 0x00,0x00,0x00,0x00,0xC0,0x1C,0x00,0x00,0xE0,0x3E,0x00,0x00,0x60,0x32,0x00,0x00,0x60,0x32,0x00,0x00,0xE0,0x3F,0x00,0x00,0xC0,0x3F, // 170 + 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x78,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x84,0x10,0x00,0x00,0xE0,0x03,0x00,0x00,0x78,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x04,0x10, // 171 + 0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFC,0x01, // 172 + 0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01, // 173 + 0x00,0xF8,0x00,0x00,0x00,0xFE,0x03,0x00,0x00,0x07,0x07,0x00,0x80,0x01,0x0C,0x00,0xC0,0x01,0x1C,0x00,0xC0,0xFE,0x1B,0x00,0x60,0xFE,0x33,0x00,0x60,0x66,0x30,0x00,0x60,0x66,0x30,0x00,0x60,0xE6,0x30,0x00,0x60,0xFE,0x31,0x00,0x60,0x3C,0x33,0x00,0xC0,0x00,0x1A,0x00,0xC0,0x01,0x1C,0x00,0x80,0x01,0x0C,0x00,0x00,0x07,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xF8, // 174 + 0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C, // 175 + 0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x40,0x04,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x40,0x04,0x00,0x00,0x80,0x03, // 176 + 0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0xFF,0x3F,0x00,0x00,0xFF,0x3F,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30, // 177 + 0x40,0x20,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x38,0x00,0x00,0x20,0x2C,0x00,0x00,0x20,0x26,0x00,0x00,0xE0,0x23,0x00,0x00,0xC0,0x21, // 178 + 0x40,0x10,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x22,0x00,0x00,0x20,0x22,0x00,0x00,0xE0,0x3D,0x00,0x00,0xC0,0x1D, // 179 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20, // 180 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x07,0x00,0xFE,0xFF,0x07,0x00,0x00,0x1C,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x1C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 181 + 0x00,0x0F,0x00,0x00,0xC0,0x3F,0x00,0x00,0xC0,0x3F,0x00,0x00,0xE0,0x7F,0x00,0x00,0xE0,0x7F,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x60,0x00,0x00,0x00,0x60, // 182 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 183 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0xC0,0x02,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x01, // 184 + 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0,0x3F,0x00,0x00,0xE0,0x3F, // 185 + 0x00,0x00,0x00,0x00,0x80,0x0F,0x00,0x00,0xC0,0x1F,0x00,0x00,0xE0,0x38,0x00,0x00,0x60,0x30,0x00,0x00,0xE0,0x38,0x00,0x00,0xC0,0x1F,0x00,0x00,0x80,0x0F, // 186 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x00,0x00,0x1C,0x1C,0x00,0x00,0x78,0x0F,0x00,0x00,0xE0,0x03,0x00,0x00,0x84,0x10,0x00,0x00,0x1C,0x1C,0x00,0x00,0x78,0x0F,0x00,0x00,0xE0,0x03,0x00,0x00,0x80, // 187 + 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x20,0x00,0xE0,0x3F,0x38,0x00,0xE0,0x3F,0x1C,0x00,0x00,0x00,0x0E,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x07,0x0C,0x00,0xC0,0x01,0x0E,0x00,0xE0,0x80,0x0B,0x00,0x60,0xC0,0x08,0x00,0x00,0xE0,0x3F,0x00,0x00,0xE0,0x3F,0x00,0x00,0x00,0x08, // 188 + 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x20,0x00,0xE0,0x3F,0x30,0x00,0xE0,0x3F,0x1C,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x07,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x4E,0x20,0x00,0x00,0x67,0x30,0x00,0xC0,0x21,0x38,0x00,0xE0,0x20,0x2C,0x00,0x60,0x20,0x26,0x00,0x00,0xE0,0x27,0x00,0x00,0xC0,0x21, // 189 + 0x40,0x10,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x22,0x20,0x00,0x20,0x22,0x30,0x00,0xE0,0x3D,0x38,0x00,0xC0,0x1D,0x0E,0x00,0x00,0x00,0x07,0x00,0x00,0x80,0x03,0x00,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x0E,0x0C,0x00,0x00,0x07,0x0E,0x00,0x80,0x83,0x0B,0x00,0xE0,0xC0,0x08,0x00,0x60,0xE0,0x3F,0x00,0x20,0xE0,0x3F,0x00,0x00,0x00,0x08, // 190 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xF8,0x03,0x00,0x00,0x1E,0x03,0x00,0x00,0x07,0x07,0x00,0xE6,0x03,0x06,0x00,0xE6,0x01,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x01,0x00,0x00,0xC0, // 191 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x82,0x8F,0x01,0x00,0xE6,0x83,0x01,0x00,0x6E,0x80,0x01,0x00,0xE8,0x83,0x01,0x00,0x80,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 192 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x80,0x8F,0x01,0x00,0xE8,0x83,0x01,0x00,0x6E,0x80,0x01,0x00,0xE6,0x83,0x01,0x00,0x82,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 193 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x88,0x8F,0x01,0x00,0xEC,0x83,0x01,0x00,0x66,0x80,0x01,0x00,0xE6,0x83,0x01,0x00,0x8C,0x8F,0x01,0x00,0x08,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 194 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x0C,0xFE,0x01,0x00,0x8E,0x8F,0x01,0x00,0xE6,0x83,0x01,0x00,0x66,0x80,0x01,0x00,0xEC,0x83,0x01,0x00,0x8C,0x8F,0x01,0x00,0x0E,0xFE,0x01,0x00,0x06,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 195 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x8C,0x8F,0x01,0x00,0xEC,0x83,0x01,0x00,0x60,0x80,0x01,0x00,0xE0,0x83,0x01,0x00,0x8C,0x8F,0x01,0x00,0x0C,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 196 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x9C,0x8F,0x01,0x00,0xE2,0x83,0x01,0x00,0x62,0x80,0x01,0x00,0xE2,0x83,0x01,0x00,0x9C,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 197 + 0x00,0x00,0x30,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x0F,0x00,0x00,0xC0,0x03,0x00,0x00,0xF0,0x01,0x00,0x00,0xBC,0x01,0x00,0x00,0x8F,0x01,0x00,0xC0,0x83,0x01,0x00,0xE0,0x80,0x01,0x00,0x60,0x80,0x01,0x00,0x60,0x80,0x01,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 198 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0x60,0x00,0x30,0x02,0x60,0x00,0x30,0x02,0x60,0x00,0xF0,0x02,0x60,0x00,0xB0,0x03,0x60,0x00,0x30,0x01,0x60,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0F,0x00,0x00,0x02,0x03, // 199 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x62,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x6E,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 200 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x6E,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x62,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 201 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 202 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 203 + 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xE6,0xFF,0x3F,0x00,0xEE,0xFF,0x3F,0x00,0x08, // 204 + 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0xEE,0xFF,0x3F,0x00,0xE6,0xFF,0x3F,0x00,0x02, // 205 + 0x08,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0xE6,0xFF,0x3F,0x00,0xE6,0xFF,0x3F,0x00,0x0C,0x00,0x00,0x00,0x08, // 206 + 0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x0C,0x00,0x00,0x00,0x0C, // 207 + 0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0E,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 208 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0xC0,0x01,0x00,0x00,0x8C,0x03,0x00,0x00,0x0E,0x0E,0x00,0x00,0x06,0x3C,0x00,0x00,0x06,0x70,0x00,0x00,0x0C,0xE0,0x01,0x00,0x0C,0x80,0x03,0x00,0x0E,0x00,0x0F,0x00,0x06,0x00,0x1C,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 209 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x62,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x6E,0x00,0x30,0x00,0x68,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 210 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0x68,0x00,0x30,0x00,0x6E,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x62,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 211 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x68,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0xE8,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 212 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xCC,0x00,0x18,0x00,0xEE,0x00,0x38,0x00,0x66,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x6E,0x00,0x30,0x00,0xE6,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 213 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x6C,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0xEC,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 214 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x03,0x00,0x00,0x8E,0x03,0x00,0x00,0xDC,0x01,0x00,0x00,0xF8,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xDC,0x01,0x00,0x00,0x8E,0x03,0x00,0x00,0x06,0x03, // 215 + 0x00,0x00,0x00,0x00,0x00,0xFC,0x21,0x00,0x00,0xFF,0x77,0x00,0x80,0x07,0x3F,0x00,0xC0,0x01,0x1E,0x00,0xC0,0x00,0x1F,0x00,0xE0,0x80,0x3B,0x00,0x60,0xC0,0x31,0x00,0x60,0xE0,0x30,0x00,0x60,0x70,0x30,0x00,0x60,0x38,0x30,0x00,0x60,0x1C,0x30,0x00,0xE0,0x0E,0x38,0x00,0xC0,0x07,0x18,0x00,0xC0,0x03,0x1C,0x00,0xE0,0x07,0x0F,0x00,0x70,0xFF,0x07,0x00,0x20,0xFC,0x01, // 216 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x02,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x0E,0x00,0x30,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 217 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x08,0x00,0x30,0x00,0x0E,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 218 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x08,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x08,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 219 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x0C,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x0C,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 220 + 0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xC0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x3C,0x00,0x00,0x08,0xF0,0x3F,0x00,0x0E,0xF0,0x3F,0x00,0x06,0x3C,0x00,0x00,0x02,0x1E,0x00,0x00,0x00,0x07,0x00,0x00,0xC0,0x03,0x00,0x00,0xE0,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x20, // 221 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x07,0x00,0x00,0x86,0x03,0x00,0x00,0xFE,0x01,0x00,0x00,0xF8, // 222 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0x00,0xC0,0xFF,0x3F,0x00,0xC0,0x00,0x00,0x00,0x60,0x00,0x08,0x00,0x60,0x00,0x1C,0x00,0x60,0x00,0x38,0x00,0xE0,0x78,0x30,0x00,0xC0,0x7F,0x30,0x00,0x80,0xC7,0x30,0x00,0x00,0x80,0x39,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0x0F, // 223 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x20,0x86,0x31,0x00,0x60,0x86,0x31,0x00,0xE0,0xC6,0x30,0x00,0x80,0xC6,0x18,0x00,0x00,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 224 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x00,0x86,0x31,0x00,0x80,0x86,0x31,0x00,0xE0,0xC6,0x30,0x00,0x60,0xC6,0x18,0x00,0x20,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 225 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x80,0x8C,0x39,0x00,0xC0,0x86,0x31,0x00,0x60,0x86,0x31,0x00,0x60,0xC6,0x30,0x00,0xC0,0xC6,0x18,0x00,0x80,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 226 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0xC0,0x1C,0x1F,0x00,0xE0,0x8C,0x39,0x00,0x60,0x86,0x31,0x00,0x60,0x86,0x31,0x00,0xC0,0xC6,0x30,0x00,0xC0,0xC6,0x18,0x00,0xE0,0xCE,0x0C,0x00,0x60,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 227 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0xC0,0x8C,0x39,0x00,0xC0,0x86,0x31,0x00,0x00,0x86,0x31,0x00,0x00,0xC6,0x30,0x00,0xC0,0xC6,0x18,0x00,0xC0,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 228 + 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x70,0x86,0x31,0x00,0x88,0x86,0x31,0x00,0x88,0xC6,0x30,0x00,0x88,0xC6,0x18,0x00,0x70,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 229 + 0x00,0x00,0x00,0x00,0x00,0x10,0x0F,0x00,0x00,0x9C,0x1F,0x00,0x00,0xCC,0x39,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0x66,0x18,0x00,0x00,0x6E,0x1C,0x00,0x00,0xFC,0x0F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xCC,0x1C,0x00,0x00,0xCE,0x38,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xCC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xE0,0x04, // 230 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x02,0x00,0x06,0x30,0x02,0x00,0x06,0xF0,0x02,0x00,0x06,0xB0,0x03,0x00,0x0E,0x38,0x01,0x00,0x1C,0x1C,0x00,0x00,0x18,0x0C, // 231 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x20,0xCE,0x38,0x00,0x60,0xC6,0x30,0x00,0xE0,0xC6,0x30,0x00,0x80,0xC6,0x30,0x00,0x00,0xCE,0x38,0x00,0x00,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 232 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x00,0xCE,0x38,0x00,0x80,0xC6,0x30,0x00,0xE0,0xC6,0x30,0x00,0x60,0xC6,0x30,0x00,0x20,0xCE,0x38,0x00,0x00,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 233 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x80,0xCE,0x38,0x00,0xC0,0xC6,0x30,0x00,0x60,0xC6,0x30,0x00,0x60,0xC6,0x30,0x00,0xC0,0xCE,0x38,0x00,0x80,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 234 + 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0xC0,0xCE,0x38,0x00,0xC0,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0xC0,0xCE,0x38,0x00,0xC0,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 235 + 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0xFE,0x3F,0x00,0xE0,0xFE,0x3F,0x00,0x80, // 236 + 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0xFE,0x3F,0x00,0x60,0xFE,0x3F,0x00,0x20, // 237 + 0x80,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x60,0xFE,0x3F,0x00,0x60,0xFE,0x3F,0x00,0xC0,0x00,0x00,0x00,0x80, // 238 + 0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0xC0,0x00,0x00,0x00,0xC0, // 239 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1D,0x1C,0x00,0xA0,0x0F,0x38,0x00,0xA0,0x06,0x30,0x00,0xE0,0x06,0x30,0x00,0xC0,0x06,0x30,0x00,0xC0,0x0F,0x38,0x00,0x20,0x1F,0x1C,0x00,0x00,0xFC,0x0F,0x00,0x00,0xE0,0x07, // 240 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0xC0,0xFE,0x3F,0x00,0xE0,0x18,0x00,0x00,0x60,0x0C,0x00,0x00,0x60,0x06,0x00,0x00,0xC0,0x06,0x00,0x00,0xC0,0x06,0x00,0x00,0xE0,0x0E,0x00,0x00,0x60,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 241 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x20,0x0E,0x38,0x00,0x60,0x06,0x30,0x00,0xE0,0x06,0x30,0x00,0x80,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 242 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x80,0x06,0x30,0x00,0xE0,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0x20,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 243 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x80,0x0E,0x38,0x00,0xC0,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0xC0,0x0E,0x38,0x00,0x80,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 244 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0xC0,0x1C,0x1C,0x00,0xE0,0x0E,0x38,0x00,0x60,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0xC0,0x06,0x30,0x00,0xC0,0x0E,0x38,0x00,0xE0,0x1C,0x1C,0x00,0x60,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 245 + 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0xC0,0x0E,0x38,0x00,0xC0,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0xC0,0x0E,0x38,0x00,0xC0,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 246 + 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0xB6,0x01,0x00,0x00,0xB6,0x01,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30, // 247 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x67,0x00,0x00,0xF8,0x7F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x3F,0x00,0x00,0x86,0x33,0x00,0x00,0xE6,0x31,0x00,0x00,0x76,0x30,0x00,0x00,0x3E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xFF,0x0F,0x00,0x00,0xF3,0x07, // 248 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x20,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x30,0x00,0x80,0x00,0x30,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 249 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x80,0x00,0x30,0x00,0xE0,0x00,0x30,0x00,0x60,0x00,0x18,0x00,0x20,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 250 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x80,0x00,0x38,0x00,0xC0,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0x80,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 251 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0xC0,0x00,0x38,0x00,0xC0,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0xC0,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 252 + 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0x00,0xF0,0x01,0x06,0x00,0x80,0x0F,0x07,0x80,0x00,0xFE,0x03,0xE0,0x00,0xFC,0x00,0x60,0xC0,0x1F,0x00,0x20,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06, // 253 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x00,0x1C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x03, // 254 + 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0xC0,0xF0,0x01,0x06,0xC0,0x80,0x0F,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xFC,0x00,0xC0,0xC0,0x1F,0x00,0xC0,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06 // 255 +}; diff --git a/src/OLEDDisplayFonts.h b/src/OLEDDisplayFonts.h new file mode 100644 index 0000000..2113d77 --- /dev/null +++ b/src/OLEDDisplayFonts.h @@ -0,0 +1,14 @@ +#ifndef OLEDDISPLAYFONTS_h +#define OLEDDISPLAYFONTS_h +#include + +#ifdef __MBED__ +# define PROGMEM +#endif + +extern const uint8_t ArialMT_Plain_10[] PROGMEM; + +extern const uint8_t ArialMT_Plain_16[] PROGMEM; + +extern const uint8_t ArialMT_Plain_24[] PROGMEM; +#endif diff --git a/src/OLEDDisplayUi.cpp b/src/OLEDDisplayUi.cpp new file mode 100644 index 0000000..b4dcf4f --- /dev/null +++ b/src/OLEDDisplayUi.cpp @@ -0,0 +1,501 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#include "OLEDDisplayUi.h" + +void LoadingDrawDefault(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) { + display->setTextAlignment(TEXT_ALIGN_CENTER); + display->setFont(ArialMT_Plain_10); + display->drawString(64, 18, stage->process); + display->drawProgressBar(4, 32, 120, 8, progress); +}; + + +OLEDDisplayUi::OLEDDisplayUi(OLEDDisplay *display) { + this->display = display; + + indicatorPosition = BOTTOM; + indicatorDirection = LEFT_RIGHT; + activeSymbol = ANIMATION_activeSymbol; + inactiveSymbol = ANIMATION_inactiveSymbol; + frameAnimationDirection = SLIDE_RIGHT; + lastTransitionDirection = 1; + frameCount = 0; + nextFrameNumber = -1; + overlayCount = 0; + indicatorDrawState = 1; + loadingDrawFunction = LoadingDrawDefault; + updateInterval = 33; + state.lastUpdate = 0; + state.ticksSinceLastStateSwitch = 0; + state.frameState = FIXED; + state.currentFrame = 0; + state.frameTransitionDirection = 1; + state.isIndicatorDrawen = true; + state.manuelControll = false; + state.userData = NULL; + shouldDrawIndicators = true; + autoTransition = true; + setTimePerFrame(5000); + setTimePerTransition(500); +} + +OLEDDisplayUi::OLEDDisplayUi() { + this->display = nullptr; + + indicatorPosition = BOTTOM; + indicatorDirection = LEFT_RIGHT; + activeSymbol = ANIMATION_activeSymbol; + inactiveSymbol = ANIMATION_inactiveSymbol; + frameAnimationDirection = SLIDE_RIGHT; + lastTransitionDirection = 1; + frameCount = 0; + nextFrameNumber = -1; + overlayCount = 0; + indicatorDrawState = 1; + loadingDrawFunction = LoadingDrawDefault; + updateInterval = 33; + state.lastUpdate = 0; + state.ticksSinceLastStateSwitch = 0; + state.frameState = FIXED; + state.currentFrame = 0; + state.frameTransitionDirection = 1; + state.isIndicatorDrawen = true; + state.manuelControll = false; + state.userData = NULL; + shouldDrawIndicators = true; + autoTransition = true; + setTimePerFrame(5000); + setTimePerTransition(500); +} + +void OLEDDisplayUi::init() { +// this->display->init(); +} + +void OLEDDisplayUi::init(OLEDDisplay *display) { + this->display = display; +} + +void OLEDDisplayUi::setTargetFPS(uint8_t fps){ + this->updateInterval = ((float) 1.0 / (float) fps) * 1000; + + this->ticksPerFrame = timePerFrame / updateInterval; + this->ticksPerTransition = timePerTransition / updateInterval; +} + +// -/------ Automatic controll ------\- + +void OLEDDisplayUi::enableAutoTransition(){ + this->autoTransition = true; +} +void OLEDDisplayUi::disableAutoTransition(){ + this->autoTransition = false; +} +void OLEDDisplayUi::setAutoTransitionForwards(){ + this->state.frameTransitionDirection = 1; + this->lastTransitionDirection = 1; +} +void OLEDDisplayUi::setAutoTransitionBackwards(){ + this->state.frameTransitionDirection = -1; + this->lastTransitionDirection = -1; +} +void OLEDDisplayUi::setTimePerFrame(uint16_t time){ + this->timePerFrame = time; + this->ticksPerFrame = timePerFrame / updateInterval; +} +void OLEDDisplayUi::setTimePerTransition(uint16_t time){ + this->timePerTransition = time; + this->ticksPerTransition = timePerTransition / updateInterval; +} + +// -/------ Customize indicator position and style -------\- +void OLEDDisplayUi::enableIndicator(){ + this->state.isIndicatorDrawen = true; +} + +void OLEDDisplayUi::disableIndicator(){ + this->state.isIndicatorDrawen = false; +} + +void OLEDDisplayUi::enableAllIndicators(){ + this->shouldDrawIndicators = true; +} + +void OLEDDisplayUi::disableAllIndicators(){ + this->shouldDrawIndicators = false; +} + +void OLEDDisplayUi::setIndicatorPosition(IndicatorPosition pos) { + this->indicatorPosition = pos; +} +void OLEDDisplayUi::setIndicatorDirection(IndicatorDirection dir) { + this->indicatorDirection = dir; +} +void OLEDDisplayUi::setActiveSymbol(const uint8_t* symbol) { + this->activeSymbol = symbol; +} +void OLEDDisplayUi::setInactiveSymbol(const uint8_t* symbol) { + this->inactiveSymbol = symbol; +} + + +// -/----- Frame settings -----\- +void OLEDDisplayUi::setFrameAnimation(AnimationDirection dir) { + this->frameAnimationDirection = dir; +} +void OLEDDisplayUi::setFrames(FrameCallback* frameFunctions, uint8_t frameCount) { + this->frameFunctions = frameFunctions; + this->frameCount = frameCount; + this->resetState(); +} + +// -/----- Overlays ------\- +void OLEDDisplayUi::setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount){ + this->overlayFunctions = overlayFunctions; + this->overlayCount = overlayCount; +} + +// -/----- Loading Process -----\- + +void OLEDDisplayUi::setLoadingDrawFunction(LoadingDrawFunction loadingDrawFunction) { + this->loadingDrawFunction = loadingDrawFunction; +} + +void OLEDDisplayUi::runLoadingProcess(LoadingStage* stages, uint8_t stagesCount) { + uint8_t progress = 0; + uint8_t increment = 100 / stagesCount; + + for (uint8_t i = 0; i < stagesCount; i++) { + display->clear(); + this->loadingDrawFunction(this->display, &stages[i], progress); + display->display(); + + stages[i].callback(); + + progress += increment; + yield(); + } + + display->clear(); + this->loadingDrawFunction(this->display, &stages[stagesCount-1], progress); + display->display(); + + delay(150); +} + +// -/----- Manuel control -----\- +void OLEDDisplayUi::nextFrame() { + if (this->state.frameState != IN_TRANSITION) { + this->state.manuelControll = true; + this->state.frameState = IN_TRANSITION; + this->state.ticksSinceLastStateSwitch = 0; + this->lastTransitionDirection = this->state.frameTransitionDirection; + this->state.frameTransitionDirection = 1; + } +} +void OLEDDisplayUi::previousFrame() { + if (this->state.frameState != IN_TRANSITION) { + this->state.manuelControll = true; + this->state.frameState = IN_TRANSITION; + this->state.ticksSinceLastStateSwitch = 0; + this->lastTransitionDirection = this->state.frameTransitionDirection; + this->state.frameTransitionDirection = -1; + } +} + +void OLEDDisplayUi::switchToFrame(uint8_t frame) { + if (frame >= this->frameCount) return; + this->state.ticksSinceLastStateSwitch = 0; + if (frame == this->state.currentFrame) return; + this->state.frameState = FIXED; + this->state.currentFrame = frame; + this->state.isIndicatorDrawen = true; +} + +void OLEDDisplayUi::transitionToFrame(uint8_t frame) { + if (frame >= this->frameCount) return; + this->state.ticksSinceLastStateSwitch = 0; + if (frame == this->state.currentFrame) return; + this->nextFrameNumber = frame; + this->lastTransitionDirection = this->state.frameTransitionDirection; + this->state.manuelControll = true; + this->state.frameState = IN_TRANSITION; + this->state.frameTransitionDirection = frame < this->state.currentFrame ? -1 : 1; +} + + +// -/----- State information -----\- +OLEDDisplayUiState* OLEDDisplayUi::getUiState(){ + return &this->state; +} + +int16_t OLEDDisplayUi::update(){ +#ifdef ARDUINO + unsigned long frameStart = millis(); +#elif __MBED__ + Timer t; + t.start(); + unsigned long frameStart = t.read_ms(); +#else +#error "Unkown operating system" +#endif + int32_t timeBudget = this->updateInterval - (frameStart - this->state.lastUpdate); + if ( timeBudget <= 0) { + // Implement frame skipping to ensure time budget is keept + if (this->autoTransition && this->state.lastUpdate != 0) this->state.ticksSinceLastStateSwitch += ceil((double)-timeBudget / (double)this->updateInterval); + + this->state.lastUpdate = frameStart; + this->tick(); + } +#ifdef ARDUINO + return this->updateInterval - (millis() - frameStart); +#elif __MBED__ + return this->updateInterval - (t.read_ms() - frameStart); +#else +#error "Unkown operating system" +#endif +} + + +void OLEDDisplayUi::tick() { + this->state.ticksSinceLastStateSwitch++; + + switch (this->state.frameState) { + case IN_TRANSITION: + if (this->state.ticksSinceLastStateSwitch >= this->ticksPerTransition){ + this->state.frameState = FIXED; + this->state.currentFrame = getNextFrameNumber(); + this->state.ticksSinceLastStateSwitch = 0; + this->nextFrameNumber = -1; + } + break; + case FIXED: + // Revert manuelControll + if (this->state.manuelControll) { + this->state.frameTransitionDirection = this->lastTransitionDirection; + this->state.manuelControll = false; + } + if (this->state.ticksSinceLastStateSwitch >= this->ticksPerFrame){ + if (this->autoTransition){ + this->state.frameState = IN_TRANSITION; + } + this->state.ticksSinceLastStateSwitch = 0; + } + break; + } + + this->display->clear(); + this->drawFrame(); + if (shouldDrawIndicators) { + this->drawIndicator(); + } + this->drawOverlays(); + this->display->display(); +} + +void OLEDDisplayUi::resetState() { + this->state.lastUpdate = 0; + this->state.ticksSinceLastStateSwitch = 0; + this->state.frameState = FIXED; + this->state.currentFrame = 0; + this->state.isIndicatorDrawen = true; +} + +void OLEDDisplayUi::drawFrame(){ + switch (this->state.frameState){ + case IN_TRANSITION: { + float progress = (float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition; + int16_t x = 0, y = 0, x1 = 0, y1 = 0; + switch(this->frameAnimationDirection){ + case SLIDE_LEFT: + x = -this->display->width() * progress; + y = 0; + x1 = x + this->display->width(); + y1 = 0; + break; + case SLIDE_RIGHT: + x = this->display->width() * progress; + y = 0; + x1 = x - this->display->width(); + y1 = 0; + break; + case SLIDE_UP: + x = 0; + y = -this->display->height() * progress; + x1 = 0; + y1 = y + this->display->height(); + break; + case SLIDE_DOWN: + default: + x = 0; + y = this->display->height() * progress; + x1 = 0; + y1 = y - this->display->height(); + break; + } + + // Invert animation if direction is reversed. + int8_t dir = this->state.frameTransitionDirection >= 0 ? 1 : -1; + x *= dir; y *= dir; x1 *= dir; y1 *= dir; + + bool drawenCurrentFrame; + + + // Prope each frameFunction for the indicator Drawen state + this->enableIndicator(); + (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y); + drawenCurrentFrame = this->state.isIndicatorDrawen; + + this->enableIndicator(); + (this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1); + + // Build up the indicatorDrawState + if (drawenCurrentFrame && !this->state.isIndicatorDrawen) { + // Drawen now but not next + this->indicatorDrawState = 2; + } else if (!drawenCurrentFrame && this->state.isIndicatorDrawen) { + // Not drawen now but next + this->indicatorDrawState = 1; + } else if (!drawenCurrentFrame && !this->state.isIndicatorDrawen) { + // Not drawen in both frames + this->indicatorDrawState = 3; + } + + // If the indicator isn't draw in the current frame + // reflect it in state.isIndicatorDrawen + if (!drawenCurrentFrame) this->state.isIndicatorDrawen = false; + + break; + } + case FIXED: + // Always assume that the indicator is drawn! + // And set indicatorDrawState to "not known yet" + this->indicatorDrawState = 0; + this->enableIndicator(); + (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, 0, 0); + break; + } +} + +void OLEDDisplayUi::drawIndicator() { + + // Only draw if the indicator is invisible + // for both frames or + // the indiactor is shown and we are IN_TRANSITION + if (this->indicatorDrawState == 3 || (!this->state.isIndicatorDrawen && this->state.frameState != IN_TRANSITION)) { + return; + } + + uint8_t posOfHighlightFrame = 0; + float indicatorFadeProgress = 0; + + // if the indicator needs to be slided in we want to + // highlight the next frame in the transition + uint8_t frameToHighlight = this->indicatorDrawState == 1 ? this->getNextFrameNumber() : this->state.currentFrame; + + // Calculate the frame that needs to be highlighted + // based on the Direction the indiactor is drawn + switch (this->indicatorDirection){ + case LEFT_RIGHT: + posOfHighlightFrame = frameToHighlight; + break; + case RIGHT_LEFT: + default: + posOfHighlightFrame = this->frameCount - frameToHighlight; + break; + } + + switch (this->indicatorDrawState) { + case 1: // Indicator was not drawn in this frame but will be in next + // Slide IN + indicatorFadeProgress = 1 - ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition); + break; + case 2: // Indicator was drawn in this frame but not in next + // Slide OUT + indicatorFadeProgress = ((float) this->state.ticksSinceLastStateSwitch / (float) this->ticksPerTransition); + break; + } + + //Space between indicators - reduce for small screen sizes + uint16_t indicatorSpacing = 12; + if (this->display->getHeight() < 64 && (this->indicatorPosition == RIGHT || this->indicatorPosition == LEFT)) { + indicatorSpacing = 6; + } + + uint16_t frameStartPos = (indicatorSpacing * frameCount / 2); + const uint8_t *image; + + uint16_t x = 0,y = 0; + + + for (uint8_t i = 0; i < this->frameCount; i++) { + + switch (this->indicatorPosition){ + case TOP: + y = 0 - (8 * indicatorFadeProgress); + x = (this->display->width() / 2) - frameStartPos + 12 * i; + break; + case BOTTOM: + y = (this->display->height() - 8) + (8 * indicatorFadeProgress); + x = (this->display->width() / 2) - frameStartPos + 12 * i; + break; + case RIGHT: + x = (this->display->width() - 8) + (8 * indicatorFadeProgress); + y = (this->display->height() / 2) - frameStartPos + 2 + 12 * i; + break; + case LEFT: + default: + x = 0 - (8 * indicatorFadeProgress); + y = (this->display->height() / 2) - frameStartPos + 2 + indicatorSpacing * i; + break; + } + + if (posOfHighlightFrame == i) { + image = this->activeSymbol; + } else { + image = this->inactiveSymbol; + } + + this->display->drawFastImage(x, y, 8, 8, image); + } +} + +void OLEDDisplayUi::drawOverlays() { + for (uint8_t i=0;ioverlayCount;i++){ + (this->overlayFunctions[i])(this->display, &this->state); + } +} + +uint8_t OLEDDisplayUi::getNextFrameNumber(){ + if (this->nextFrameNumber != -1) return this->nextFrameNumber; + return (this->state.currentFrame + this->frameCount + this->state.frameTransitionDirection) % this->frameCount; +} diff --git a/src/OLEDDisplayUi.h b/src/OLEDDisplayUi.h new file mode 100644 index 0000000..6dbb2c3 --- /dev/null +++ b/src/OLEDDisplayUi.h @@ -0,0 +1,317 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * Copyright (c) 2019 by Helmut Tschemernjak - www.radioshuttle.de + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef OLEDDISPLAYUI_h +#define OLEDDISPLAYUI_h + +#ifdef ARDUINO +#include +#elif __MBED__ +#include +#else +#error "Unkown operating system" +#endif + +#include "OLEDDisplay.h" + +//#define DEBUG_OLEDDISPLAYUI(...) Serial.printf( __VA_ARGS__ ) + +#ifndef DEBUG_OLEDDISPLAYUI +#define DEBUG_OLEDDISPLAYUI(...) +#endif + +enum AnimationDirection { + SLIDE_UP, + SLIDE_DOWN, + SLIDE_LEFT, + SLIDE_RIGHT +}; + +enum IndicatorPosition { + TOP, + RIGHT, + BOTTOM, + LEFT +}; + +enum IndicatorDirection { + LEFT_RIGHT, + RIGHT_LEFT +}; + +enum FrameState { + IN_TRANSITION, + FIXED +}; + + +const uint8_t ANIMATION_activeSymbol[] PROGMEM = { + 0x00, 0x18, 0x3c, 0x7e, 0x7e, 0x3c, 0x18, 0x00 +}; + +const uint8_t ANIMATION_inactiveSymbol[] PROGMEM = { + 0x00, 0x0, 0x0, 0x18, 0x18, 0x0, 0x0, 0x00 +}; + + +// Structure of the UiState +struct OLEDDisplayUiState { + uint64_t lastUpdate; + uint16_t ticksSinceLastStateSwitch; + + FrameState frameState; + uint8_t currentFrame; + + bool isIndicatorDrawen; + + // Normal = 1, Inverse = -1; + int8_t frameTransitionDirection; + + bool manuelControll; + + // Custom data that can be used by the user + void* userData; +}; + +struct LoadingStage { + const char* process; + void (*callback)(); +}; + +typedef void (*FrameCallback)(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); +typedef void (*OverlayCallback)(OLEDDisplay *display, OLEDDisplayUiState* state); +typedef void (*LoadingDrawFunction)(OLEDDisplay *display, LoadingStage* stage, uint8_t progress); + +class OLEDDisplayUi { + private: + OLEDDisplay *display; + + // Symbols for the Indicator + IndicatorPosition indicatorPosition; + IndicatorDirection indicatorDirection; + + const uint8_t* activeSymbol; + const uint8_t* inactiveSymbol; + + bool shouldDrawIndicators; + + // Values for the Frames + AnimationDirection frameAnimationDirection; + + int8_t lastTransitionDirection; + + uint16_t ticksPerFrame; // ~ 5000ms at 30 FPS + uint16_t ticksPerTransition; // ~ 500ms at 30 FPS + + bool autoTransition; + + FrameCallback* frameFunctions; + uint8_t frameCount; + + // Internally used to transition to a specific frame + int8_t nextFrameNumber; + + // Values for Overlays + OverlayCallback* overlayFunctions; + uint8_t overlayCount; + + // Will the Indicator be drawen + // 3 Not drawn in both frames + // 2 Drawn this frame but not next + // 1 Not drown this frame but next + // 0 Not known yet + uint8_t indicatorDrawState; + + // Loading screen + LoadingDrawFunction loadingDrawFunction; + + // UI State + OLEDDisplayUiState state; + + // Bookeeping for update + uint16_t updateInterval = 33; + + uint16_t timePerFrame; + uint16_t timePerTransition; + + uint8_t getNextFrameNumber(); + void drawIndicator(); + void drawFrame(); + void drawOverlays(); + void tick(); + void resetState(); + + public: + + OLEDDisplayUi(OLEDDisplay *display); + OLEDDisplayUi(); + + /** + * Initialise the display + */ + void init(); + void init(OLEDDisplay *display); + + /** + * Configure the internal used target FPS + */ + void setTargetFPS(uint8_t fps); + + // Automatic Controll + /** + * Enable automatic transition to next frame after the some time can be configured with `setTimePerFrame` and `setTimePerTransition`. + */ + void enableAutoTransition(); + + /** + * Disable automatic transition to next frame. + */ + void disableAutoTransition(); + + /** + * Set the direction if the automatic transitioning + */ + void setAutoTransitionForwards(); + void setAutoTransitionBackwards(); + + /** + * Set the approx. time a frame is displayed + */ + void setTimePerFrame(uint16_t time); + + /** + * Set the approx. time a transition will take + */ + void setTimePerTransition(uint16_t time); + + // Customize indicator position and style + + /** + * Draw the indicator. + * This is the defaut state for all frames if + * the indicator was hidden on the previous frame + * it will be slided in. + */ + void enableIndicator(); + + /** + * Don't draw the indicator. + * This will slide out the indicator + * when transitioning to the next frame. + */ + void disableIndicator(); + + /** + * Enable drawing of indicators + */ + void enableAllIndicators(); + + /** + * Disable draw of indicators. + */ + void disableAllIndicators(); + + /** + * Set the position of the indicator bar. + */ + void setIndicatorPosition(IndicatorPosition pos); + + /** + * Set the direction of the indicator bar. Defining the order of frames ASCENDING / DESCENDING + */ + void setIndicatorDirection(IndicatorDirection dir); + + /** + * Set the symbol to indicate an active frame in the indicator bar. + */ + void setActiveSymbol(const uint8_t* symbol); + + /** + * Set the symbol to indicate an inactive frame in the indicator bar. + */ + void setInactiveSymbol(const uint8_t* symbol); + + + // Frame settings + + /** + * Configure what animation is used to transition from one frame to another + */ + void setFrameAnimation(AnimationDirection dir); + + /** + * Add frame drawing functions + */ + void setFrames(FrameCallback* frameFunctions, uint8_t frameCount); + + // Overlay + + /** + * Add overlays drawing functions that are draw independent of the Frames + */ + void setOverlays(OverlayCallback* overlayFunctions, uint8_t overlayCount); + + + // Loading animation + /** + * Set the function that will draw each step + * in the loading animation + */ + void setLoadingDrawFunction(LoadingDrawFunction loadingFunction); + + + /** + * Run the loading process + */ + void runLoadingProcess(LoadingStage* stages, uint8_t stagesCount); + + + // Manual Control + void nextFrame(); + void previousFrame(); + + /** + * Switch without transition to frame `frame`. + */ + void switchToFrame(uint8_t frame); + + /** + * Transition to frame `frame`, when the `frame` number is bigger than the current + * frame the forward animation will be used, otherwise the backwards animation is used. + */ + void transitionToFrame(uint8_t frame); + + // State Info + OLEDDisplayUiState* getUiState(); + + int16_t update(); +}; +#endif diff --git a/src/SH1106.h b/src/SH1106.h new file mode 100644 index 0000000..47188d1 --- /dev/null +++ b/src/SH1106.h @@ -0,0 +1,39 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SH1106_h +#define SH1106_h +#include "SH1106Wire.h" + +// For make SH1106 an alias for SH1106Wire +typedef SH1106Wire SH1106; + + +#endif diff --git a/src/SH1106Brzo.h b/src/SH1106Brzo.h new file mode 100644 index 0000000..be9c0c7 --- /dev/null +++ b/src/SH1106Brzo.h @@ -0,0 +1,141 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SH1106Brzo_h +#define SH1106Brzo_h + +#include "OLEDDisplay.h" +#include + +#if F_CPU == 160000000L + #define BRZO_I2C_SPEED 1000 +#else + #define BRZO_I2C_SPEED 800 +#endif + +class SH1106Brzo : public OLEDDisplay { + private: + uint8_t _address; + uint8_t _sda; + uint8_t _scl; + + public: + SH1106Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + setGeometry(g); + + this->_address = _address; + this->_sda = _sda; + this->_scl = _scl; + } + + bool connect(){ + brzo_i2c_setup(_sda, _scl, 0); + return true; + } + + void display(void) { + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (displayHeight / 8); y++) { + for (x = 0; x < displayWidth; x++) { + uint16_t pos = x + y * displayWidth; + if (buffer[pos] != buffer_back[pos]) { + minBoundY = _min(minBoundY, y); + maxBoundY = _max(maxBoundY, y); + minBoundX = _min(minBoundX, x); + maxBoundX = _max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + if (minBoundY == UINT8_MAX) return; + + byte k = 0; + uint8_t sendBuffer[17]; + sendBuffer[0] = 0x40; + + // Calculate the colum offset + uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F; + uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 ); + + brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED); + + for (y = minBoundY; y <= maxBoundY; y++) { + sendCommand(0xB0 + y); + sendCommand(minBoundXp2H); + sendCommand(minBoundXp2L); + for (x = minBoundX; x <= maxBoundX; x++) { + k++; + sendBuffer[k] = buffer[x + y * displayWidth]; + if (k == 16) { + brzo_i2c_write(sendBuffer, 17, true); + k = 0; + } + } + if (k != 0) { + brzo_i2c_write(sendBuffer, k + 1, true); + k = 0; + } + yield(); + } + if (k != 0) { + brzo_i2c_write(sendBuffer, k + 1, true); + } + brzo_i2c_end_transaction(); + #else + #endif + } + + private: + int getBufferOffset(void) { + return 0; + } + inline void sendCommand(uint8_t com) __attribute__((always_inline)){ + uint8_t command[2] = {0x80 /* command mode */, com}; + brzo_i2c_start_transaction(_address, BRZO_I2C_SPEED); + brzo_i2c_write(command, 2, true); + brzo_i2c_end_transaction(); + } +}; + +#endif diff --git a/src/SH1106Spi.h b/src/SH1106Spi.h new file mode 100644 index 0000000..23693bc --- /dev/null +++ b/src/SH1106Spi.h @@ -0,0 +1,135 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SH1106Spi_h +#define SH1106Spi_h + +#include "OLEDDisplay.h" +#include + +class SH1106Spi : public OLEDDisplay { + private: + uint8_t _rst; + uint8_t _dc; + + public: + SH1106Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + setGeometry(g); + + this->_rst = _rst; + this->_dc = _dc; + } + + bool connect(){ + pinMode(_dc, OUTPUT); + pinMode(_rst, OUTPUT); + + SPI.begin (); + SPI.setClockDivider (SPI_CLOCK_DIV2); + + // Pulse Reset low for 10ms + digitalWrite(_rst, HIGH); + delay(1); + digitalWrite(_rst, LOW); + delay(10); + digitalWrite(_rst, HIGH); + return true; + } + + void display(void) { + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (displayHeight / 8); y++) { + for (x = 0; x < displayWidth; x++) { + uint16_t pos = x + y * displayWidth; + if (buffer[pos] != buffer_back[pos]) { + minBoundY = _min(minBoundY, y); + maxBoundY = _max(maxBoundY, y); + minBoundX = _min(minBoundX, x); + maxBoundX = _max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + if (minBoundY == UINT8_MAX) return; + + // Calculate the colum offset + uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F; + uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 ); + + for (y = minBoundY; y <= maxBoundY; y++) { + sendCommand(0xB0 + y); + sendCommand(minBoundXp2H); + sendCommand(minBoundXp2L); + digitalWrite(_dc, HIGH); // data mode + for (x = minBoundX; x <= maxBoundX; x++) { + SPI.transfer(buffer[x + y * displayWidth]); + } + yield(); + } + #else + for (uint8_t y=0; y + +#define SH1106_SET_PUMP_VOLTAGE 0X30 +#define SH1106_SET_PUMP_MODE 0XAD +#define SH1106_PUMP_ON 0X8B +#define SH1106_PUMP_OFF 0X8A +//-------------------------------------- + +class SH1106Wire : public OLEDDisplay { + private: + uint8_t _address; + uint8_t _sda; + uint8_t _scl; + bool _doI2cAutoInit = false; + TwoWire* _wire = NULL; + int _frequency; + + public: + /** + * Create and initialize the Display using Wire library + * + * Beware for retro-compatibility default values are provided for all parameters see below. + * Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to + * ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple + * device on the same bus. + * + * @param _address I2C Display address + * @param _sda I2C SDA pin number, default to -1 to skip Wire begin call + * @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call) + * @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options + * @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE + * @param _frequency for Frequency by default Let's use ~700khz if ESP8266 is in 160Mhz mode, this will be limited to ~400khz if the ESP8266 in 80Mhz mode + */ + SH1106Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) { + setGeometry(g); + + this->_address = _address; + this->_sda = _sda; + this->_scl = _scl; +#if !defined(ARDUINO_ARCH_ESP32) + this->_wire = &Wire; +#else + this->_wire = (_i2cBus==I2C_ONE) ? &Wire : &Wire1; +#endif + this->_frequency = _frequency; + } + + bool connect() { +#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266) + _wire->begin(); +#else + // On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us. + if(this->_sda != -1) + _wire->begin(this->_sda, this->_scl); +#endif + // Let's use ~700khz if ESP8266 is in 160Mhz mode + // this will be limited to ~400khz if the ESP8266 in 80Mhz mode. + if(this->_frequency != -1) + _wire->setClock(this->_frequency); + return true; + } + + void display(void) { + initI2cIfNeccesary(); + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (displayHeight / 8); y++) { + for (x = 0; x < displayWidth; x++) { + uint16_t pos = x + y * displayWidth; + if (buffer[pos] != buffer_back[pos]) { + minBoundY = min(minBoundY, y); + maxBoundY = max(maxBoundY, y); + minBoundX = min(minBoundX, x); + maxBoundX = max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + if (minBoundY == UINT8_MAX) return; + + // Calculate the colum offset + uint8_t minBoundXp2H = (minBoundX + 2) & 0x0F; + uint8_t minBoundXp2L = 0x10 | ((minBoundX + 2) >> 4 ); + + byte k = 0; + for (y = minBoundY; y <= maxBoundY; y++) { + sendCommand(0xB0 + y); + sendCommand(minBoundXp2H); + sendCommand(minBoundXp2L); + for (x = minBoundX; x <= maxBoundX; x++) { + if (k == 0) { + _wire->beginTransmission(_address); + _wire->write(0x40); + } + _wire->write(buffer[x + y * displayWidth]); + k++; + if (k == 16) { + _wire->endTransmission(); + k = 0; + } + } + if (k != 0) { + _wire->endTransmission(); + k = 0; + } + yield(); + } + + if (k != 0) { + _wire->endTransmission(); + } + #else + uint8_t * p = &buffer[0]; + for (uint8_t y=0; y<8; y++) { + sendCommand(0xB0+y); + sendCommand(0x02); + sendCommand(0x10); + for( uint8_t x=0; x<8; x++) { + _wire->beginTransmission(_address); + _wire->write(0x40); + for (uint8_t k = 0; k < 16; k++) { + _wire->write(*p++); + } + _wire->endTransmission(); + } + } + #endif + } + + void setI2cAutoInit(bool doI2cAutoInit) { + _doI2cAutoInit = doI2cAutoInit; + } + + private: + int getBufferOffset(void) { + return 0; + } + inline void sendCommand(uint8_t command) __attribute__((always_inline)){ + _wire->beginTransmission(_address); + _wire->write(0x80); + _wire->write(command); + _wire->endTransmission(); + } + + void initI2cIfNeccesary() { + if (_doI2cAutoInit) { +#ifdef ARDUINO_ARCH_AVR + _wire->begin(); +#else + _wire->begin(this->_sda, this->_scl); +#endif + } + } + +}; + +#endif diff --git a/src/SSD1306.h b/src/SSD1306.h new file mode 100644 index 0000000..f6bd554 --- /dev/null +++ b/src/SSD1306.h @@ -0,0 +1,39 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SSD1306_h +#define SSD1306_h +#include "SSD1306Wire.h" + +// For legacy support make SSD1306 an alias for SSD1306 +typedef SSD1306Wire SSD1306; + + +#endif diff --git a/src/SSD1306Brzo.h b/src/SSD1306Brzo.h new file mode 100644 index 0000000..987dd5b --- /dev/null +++ b/src/SSD1306Brzo.h @@ -0,0 +1,162 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SSD1306Brzo_h +#define SSD1306Brzo_h + +#include "OLEDDisplay.h" +#include + +#if F_CPU == 160000000L + #define BRZO_I2C_SPEED 1000 +#else + #define BRZO_I2C_SPEED 800 +#endif + +class SSD1306Brzo : public OLEDDisplay { + private: + uint8_t _address; + uint8_t _sda; + uint8_t _scl; + + public: + SSD1306Brzo(uint8_t _address, uint8_t _sda, uint8_t _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + setGeometry(g); + + this->_address = _address; + this->_sda = _sda; + this->_scl = _scl; + } + + bool connect(){ + brzo_i2c_setup(_sda, _scl, 0); + return true; + } + + void display(void) { + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (displayHeight / 8); y++) { + for (x = 0; x < displayWidth; x++) { + uint16_t pos = x + y * displayWidth; + if (buffer[pos] != buffer_back[pos]) { + minBoundY = _min(minBoundY, y); + maxBoundY = _max(maxBoundY, y); + minBoundX = _min(minBoundX, x); + maxBoundX = _max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + if (minBoundY == UINT8_MAX) return; + + sendCommand(COLUMNADDR); + sendCommand(minBoundX); + sendCommand(maxBoundX); + + sendCommand(PAGEADDR); + sendCommand(minBoundY); + sendCommand(maxBoundY); + + byte k = 0; + uint8_t sendBuffer[17]; + sendBuffer[0] = 0x40; + brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED); + for (y = minBoundY; y <= maxBoundY; y++) { + for (x = minBoundX; x <= maxBoundX; x++) { + k++; + sendBuffer[k] = buffer[x + y * displayWidth]; + if (k == 16) { + brzo_i2c_write(sendBuffer, 17, true); + k = 0; + } + } + yield(); + } + brzo_i2c_write(sendBuffer, k + 1, true); + brzo_i2c_end_transaction(); + #else + // No double buffering + sendCommand(COLUMNADDR); + sendCommand(0x0); + sendCommand(0x7F); + + sendCommand(PAGEADDR); + sendCommand(0x0); + + if (geometry == GEOMETRY_128_64) { + sendCommand(0x7); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x3); + } + + uint8_t sendBuffer[17]; + sendBuffer[0] = 0x40; + brzo_i2c_start_transaction(this->_address, BRZO_I2C_SPEED); + for (uint16_t i=0; i + +#ifndef UINT8_MAX + #define UINT8_MAX 0xff +#endif + +class SSD1306I2C : public OLEDDisplay { +public: + SSD1306I2C(uint8_t _address, PinName _sda, PinName _scl, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + setGeometry(g); + + this->_address = _address << 1; // convert from 7 to 8 bit for mbed. + this->_sda = _sda; + this->_scl = _scl; + _i2c = new I2C(_sda, _scl); + } + + bool connect() { + // mbed supports 100k and 400k some device maybe 1000k +#ifdef TARGET_STM32L4 + _i2c->frequency(1000000); +#else + _i2c->frequency(400000); +#endif + return true; + } + + void display(void) { + const int x_offset = (128 - this->width()) / 2; +#ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (this->height() / 8); y++) { + for (x = 0; x < this->width(); x++) { + uint16_t pos = x + y * this->width(); + if (buffer[pos] != buffer_back[pos]) { + minBoundY = std::min(minBoundY, y); + maxBoundY = std::max(maxBoundY, y); + minBoundX = std::min(minBoundX, x); + maxBoundX = std::max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + + if (minBoundY == UINT8_MAX) return; + + sendCommand(COLUMNADDR); + sendCommand(x_offset + minBoundX); // column start address (0 = reset) + sendCommand(x_offset + maxBoundX); // column end address (127 = reset) + + sendCommand(PAGEADDR); + sendCommand(minBoundY); // page start address + sendCommand(maxBoundY); // page end address + + for (y = minBoundY; y <= maxBoundY; y++) { + uint8_t *start = &buffer[(minBoundX + y * this->width())-1]; + uint8_t save = *start; + + *start = 0x40; // control + _i2c->write(_address, (char *)start, (maxBoundX-minBoundX) + 1 + 1); + *start = save; + } +#else + + sendCommand(COLUMNADDR); + sendCommand(x_offset); // column start address (0 = reset) + sendCommand(x_offset + (this->width() - 1));// column end address (127 = reset) + + sendCommand(PAGEADDR); + sendCommand(0x0); // page start address (0 = reset) + + if (geometry == GEOMETRY_128_64) { + sendCommand(0x7); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x3); + } + + buffer[-1] = 0x40; // control + _i2c->write(_address, (char *)&buffer[-1], displayBufferSize + 1); +#endif + } + +private: + int getBufferOffset(void) { + return 0; + } + + inline void sendCommand(uint8_t command) __attribute__((always_inline)) { + char _data[2]; + _data[0] = 0x80; // control + _data[1] = command; + _i2c->write(_address, _data, sizeof(_data)); + } + + uint8_t _address; + PinName _sda; + PinName _scl; + I2C *_i2c; +}; + +#endif + +#endif diff --git a/src/SSD1306Spi.h b/src/SSD1306Spi.h new file mode 100644 index 0000000..e1b6458 --- /dev/null +++ b/src/SSD1306Spi.h @@ -0,0 +1,163 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn + * Copyright (c) 2018 by Fabrice Weinberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * ThingPulse invests considerable time and money to develop these open source libraries. + * Please support us by buying our products (and not the clones) from + * https://thingpulse.com + * + */ + +#ifndef SSD1306Spi_h +#define SSD1306Spi_h + +#include "OLEDDisplay.h" +#include + +#if F_CPU == 160000000L + #define BRZO_I2C_SPEED 1000 +#else + #define BRZO_I2C_SPEED 800 +#endif + +class SSD1306Spi : public OLEDDisplay { + private: + uint8_t _rst; + uint8_t _dc; + uint8_t _cs; + + public: + SSD1306Spi(uint8_t _rst, uint8_t _dc, uint8_t _cs, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { + setGeometry(g); + + this->_rst = _rst; + this->_dc = _dc; + this->_cs = _cs; + } + + bool connect(){ + pinMode(_dc, OUTPUT); + pinMode(_cs, OUTPUT); + pinMode(_rst, OUTPUT); + + SPI.begin (); + SPI.setClockDivider (SPI_CLOCK_DIV2); + + // Pulse Reset low for 10ms + digitalWrite(_rst, HIGH); + delay(1); + digitalWrite(_rst, LOW); + delay(10); + digitalWrite(_rst, HIGH); + return true; + } + + void display(void) { + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (displayHeight / 8); y++) { + for (x = 0; x < displayWidth; x++) { + uint16_t pos = x + y * displayWidth; + if (buffer[pos] != buffer_back[pos]) { + minBoundY = _min(minBoundY, y); + maxBoundY = _max(maxBoundY, y); + minBoundX = _min(minBoundX, x); + maxBoundX = _max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + if (minBoundY == UINT8_MAX) return; + + sendCommand(COLUMNADDR); + sendCommand(minBoundX); + sendCommand(maxBoundX); + + sendCommand(PAGEADDR); + sendCommand(minBoundY); + sendCommand(maxBoundY); + + digitalWrite(_cs, HIGH); + digitalWrite(_dc, HIGH); // data mode + digitalWrite(_cs, LOW); + for (y = minBoundY; y <= maxBoundY; y++) { + for (x = minBoundX; x <= maxBoundX; x++) { + SPI.transfer(buffer[x + y * displayWidth]); + } + yield(); + } + digitalWrite(_cs, HIGH); + #else + // No double buffering + sendCommand(COLUMNADDR); + sendCommand(0x0); + sendCommand(0x7F); + + sendCommand(PAGEADDR); + sendCommand(0x0); + + if (geometry == GEOMETRY_128_64) { + sendCommand(0x7); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x3); + } + + digitalWrite(_cs, HIGH); + digitalWrite(_dc, HIGH); // data mode + digitalWrite(_cs, LOW); + for (uint16_t i=0; i +#include + +#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_STM32) +#define _min min +#define _max max +#endif +//-------------------------------------- + +class SSD1306Wire : public OLEDDisplay { + private: + uint8_t _address; + int _sda; + int _scl; + bool _doI2cAutoInit = false; + TwoWire* _wire = NULL; + int _frequency; + + public: + + /** + * Create and initialize the Display using Wire library + * + * Beware for retro-compatibility default values are provided for all parameters see below. + * Please note that if you don't wan't SD1306Wire to initialize and change frequency speed ot need to + * ensure -1 value are specified for all 3 parameters. This can be usefull to control TwoWire with multiple + * device on the same bus. + * + * @param _address I2C Display address + * @param _sda I2C SDA pin number, default to -1 to skip Wire begin call + * @param _scl I2C SCL pin number, default to -1 (only SDA = -1 is considered to skip Wire begin call) + * @param g display geometry dafault to generic GEOMETRY_128_64, see OLEDDISPLAY_GEOMETRY definition for other options + * @param _i2cBus on ESP32 with 2 I2C HW buses, I2C_ONE for 1st Bus, I2C_TWO fot 2nd bus, default I2C_ONE + * @param _frequency for Frequency by default Let's use ~700khz if ESP8266 is in 160Mhz mode, this will be limited to ~400khz if the ESP8266 in 80Mhz mode + */ + SSD1306Wire(uint8_t _address, int _sda = -1, int _scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C _i2cBus = I2C_ONE, int _frequency = 700000) { + setGeometry(g); + + this->_address = _address; + this->_sda = _sda; + this->_scl = _scl; +#if !defined(ARDUINO_ARCH_ESP32) + this->_wire = &Wire; +#else + this->_wire = (_i2cBus==I2C_ONE) ? &Wire : &Wire1; +#endif + this->_frequency = _frequency; + } + + bool connect() { +#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266) + _wire->begin(); +#else + // On ESP32 arduino, -1 means 'don't change pins', someone else has called begin for us. + if(this->_sda != -1) + _wire->begin(this->_sda, this->_scl); +#endif + // Let's use ~700khz if ESP8266 is in 160Mhz mode + // this will be limited to ~400khz if the ESP8266 in 80Mhz mode. + if(this->_frequency != -1) + _wire->setClock(this->_frequency); + return true; + } + + void display(void) { + initI2cIfNeccesary(); + const int x_offset = (128 - this->width()) / 2; + #ifdef OLEDDISPLAY_DOUBLE_BUFFER + uint8_t minBoundY = UINT8_MAX; + uint8_t maxBoundY = 0; + + uint8_t minBoundX = UINT8_MAX; + uint8_t maxBoundX = 0; + uint8_t x, y; + + // Calculate the Y bounding box of changes + // and copy buffer[pos] to buffer_back[pos]; + for (y = 0; y < (this->height() / 8); y++) { + for (x = 0; x < this->width(); x++) { + uint16_t pos = x + y * this->width(); + if (buffer[pos] != buffer_back[pos]) { + minBoundY = std::min(minBoundY, y); + maxBoundY = std::max(maxBoundY, y); + minBoundX = std::min(minBoundX, x); + maxBoundX = std::max(maxBoundX, x); + } + buffer_back[pos] = buffer[pos]; + } + yield(); + } + + // If the minBoundY wasn't updated + // we can savely assume that buffer_back[pos] == buffer[pos] + // holdes true for all values of pos + + if (minBoundY == UINT8_MAX) return; + + sendCommand(COLUMNADDR); + sendCommand(x_offset + minBoundX); + sendCommand(x_offset + maxBoundX); + + sendCommand(PAGEADDR); + sendCommand(minBoundY); + sendCommand(maxBoundY); + + byte k = 0; + for (y = minBoundY; y <= maxBoundY; y++) { + for (x = minBoundX; x <= maxBoundX; x++) { + if (k == 0) { + _wire->beginTransmission(_address); + _wire->write(0x40); + } + + _wire->write(buffer[x + y * this->width()]); + k++; + if (k == 16) { + _wire->endTransmission(); + k = 0; + } + } + yield(); + } + + if (k != 0) { + _wire->endTransmission(); + } + #else + + sendCommand(COLUMNADDR); + sendCommand(x_offset); + sendCommand(x_offset + (this->width() - 1)); + + sendCommand(PAGEADDR); + sendCommand(0x0); + + if (geometry == GEOMETRY_128_64) { + sendCommand(0x7); + } else if (geometry == GEOMETRY_128_32) { + sendCommand(0x3); + } + + for (uint16_t i=0; i < displayBufferSize; i++) { + _wire->beginTransmission(this->_address); + _wire->write(0x40); + for (uint8_t x = 0; x < 16; x++) { + _wire->write(buffer[i]); + i++; + } + i--; + _wire->endTransmission(); + } + #endif + } + + void setI2cAutoInit(bool doI2cAutoInit) { + _doI2cAutoInit = doI2cAutoInit; + } + + private: + int getBufferOffset(void) { + return 0; + } + inline void sendCommand(uint8_t command) __attribute__((always_inline)){ + initI2cIfNeccesary(); + _wire->beginTransmission(_address); + _wire->write(0x80); + _wire->write(command); + _wire->endTransmission(); + } + + void initI2cIfNeccesary() { + if (_doI2cAutoInit) { +#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH8266) + _wire->begin(); +#else + _wire->begin(this->_sda, this->_scl); +#endif + } + } + +}; + +#endif