Repository: squix78/esp8266-oled-ssd1306 Branch: master Commit: 5fd04d4bc6c4 Files: 48 Total size: 377.1 KB Directory structure: gitextract_do6gekij/ ├── .editorconfig ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── support-request.md │ ├── stale.yml │ └── workflows/ │ └── main.yml ├── .gitignore ├── CMakeLists.txt ├── CONTRIBUTING.md ├── README.md ├── README_GEOMETRY_64_48.md ├── UPGRADE-3.0.md ├── UPGRADE-4.0.md ├── component.mk ├── examples/ │ ├── SSD1306ClockDemo/ │ │ ├── SSD1306ClockDemo.ino │ │ └── images.h │ ├── SSD1306DrawingDemo/ │ │ └── SSD1306DrawingDemo.ino │ ├── SSD1306FontTryout/ │ │ ├── Dialog_plain_6.h │ │ ├── Dialog_plain_7.h │ │ ├── Dialog_plain_8.h │ │ └── SSD1306FontTryout.ino │ ├── SSD1306OTADemo/ │ │ └── SSD1306OTADemo.ino │ ├── SSD1306ScrollVerticalDemo/ │ │ └── SSD1306ScrollVerticalDemo.ino │ ├── SSD1306SimpleDemo/ │ │ ├── SSD1306SimpleDemo.ino │ │ └── images.h │ ├── SSD1306TwoScreenDemo/ │ │ ├── SSD1306TwoScreenDemo.ino │ │ └── images.h │ └── SSD1306UiDemo/ │ ├── SSD1306UiDemo.ino │ └── images.h ├── keywords.txt ├── library.json ├── library.properties ├── license ├── platformio.ini ├── resources/ │ └── glyphEditor.html └── src/ ├── OLEDDisplay.cpp ├── OLEDDisplay.h ├── OLEDDisplayFonts.h ├── OLEDDisplayUi.cpp ├── OLEDDisplayUi.h ├── SH1106.h ├── SH1106Brzo.h ├── SH1106Spi.h ├── SH1106Wire.h ├── SSD1306.h ├── SSD1306Brzo.h ├── SSD1306I2C.h ├── SSD1306Spi.h └── SSD1306Wire.h ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ # This file is for unifying the coding style for different editors and IDEs # editorconfig.org root = true [*] end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 2 max_line_length = 120 curly_bracket_next_line = false ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Do this '....' 3. Do that '....' 4. See error **Sample code** Provide a [MCVE](https://stackoverflow.com/help/minimal-reproducible-example) below. ```c # your code goes here ``` **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Versions (please complete the following information):** - Library: [e.g. 4.2] - Platform [e.g. ESP266 Arduino Core 2.5.x] **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/support-request.md ================================================ --- name: Support request about: Describe this issue template's purpose here. title: '' labels: '' assignees: '' --- We offer support to our customers at https://support.thingpulse.com/. Send us an email if you don't have an account yet. ================================================ FILE: .github/stale.yml ================================================ # Number of days of inactivity before an issue becomes stale daysUntilStale: 180 # Number of days of inactivity before a stale issue is closed daysUntilClose: 14 # Issues with these labels will never be considered stale exemptLabels: - pinned - security # Label to use when marking an issue as stale staleLabel: stale # Comment to post when marking an issue as stale. Set to `false` to disable markComment: > This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. # Comment to post when closing a stale issue. Set to `false` to disable closeComment: false ================================================ FILE: .github/workflows/main.yml ================================================ # documentation at https://docs.platformio.org/en/latest/integration/ci/github-actions.html name: PlatformIO CI on: [push, pull_request] jobs: build: runs-on: ubuntu-latest strategy: matrix: example: [examples/SSD1306UiDemo, examples/SSD1306SimpleDemo, examples/SSD1306DrawingDemo, examples/SSD1306OTADemo, examples/SSD1306ClockDemo, examples/SSD1306TwoScreenDemo] steps: - uses: actions/checkout@v4 - name: Cache pip uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} restore-keys: ${{ runner.os }}-pip- - name: Cache PlatformIO uses: actions/cache@v3 with: path: ~/.platformio key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }} - name: Set up Python uses: actions/setup-python@v5 - name: Install PlatformIO run: | python -m pip install --upgrade pip pip install --upgrade platformio intelhex - name: Install library dependencies run: pio pkg install -g -l "paulstoffregen/Time@^1.6" - name: Run PlatformIO run: pio ci --lib="." --board=nodemcuv2 --board=d1_mini --board=esp-wrover-kit --board=esp32doit-devkit-v1 env: PLATFORMIO_CI_SRC: ${{ matrix.example }} ================================================ FILE: .gitignore ================================================ .vscode .pio ================================================ FILE: CMakeLists.txt ================================================ set(COMPONENT_ADD_INCLUDEDIRS src) set(COMPONENT_PRIV_REQUIRES arduino-esp32) set(COMPONENT_SRCDIRS src) register_component() ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to ThingPulse OLED SSD1306 :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: The following is a set of guidelines for contributing to the ThingPulse OLED SSD1306 library on GitHub. These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request. It is appreciated if you raise an issue _before_ you start changing the code, discussing the proposed change; emphasizing that you are proposing to develop the patch yourself, and outlining the strategy for implementation. This type of discussion is what we should be doing on the issues list and it is better to do this before or in parallel to developing the patch rather than having "you should have done it this way" type of feedback on the PR itself. ### Table Of Contents * [General remarks](#general-remarks) * [Writing Documentation](#writing-documentation) * [Working with Git and GitHub](#working-with-git-and-github) * [General flow](#general-flow) * [Keeping your fork in sync](#keeping-your-fork-in-sync) * [Commit messages](#commit-messages) ## General remarks We are a friendly and welcoming community and look forward to your contributions. Once your contribution is integrated into this repository we feel responsible for it. Therefore, be prepared for constructive feedback. Before we merge anything we need to ensure that it fits in and is consistent with the rest of code. If you made something really cool but won't spend the time to integrate it into this upstream project please still share it in your fork on GitHub. If you mention it in an issue we'll take a look at it anyway. ## Writing Documentation ThingPulse maintains documentation for its products at [https://github.com/thingpulse/docs/](https://github.com/thingpulse/docs/). If you contribute features for this project that require altering the respective product guide then we ask you to prepare a pull request with the necessary documentation changes as well. ## Working with Git and GitHub Avoid intermediate merge commits. [Rebase](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) your feature branch onto `master` to pull updates and verify your local changes against them before placing the pull request. ### General flow 1. [Fork](https://help.github.com/articles/fork-a-repo) this repository on GitHub. 1. [Create a branch](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/#creating-a-branch) in your fork on GitHub **based on the `master` branch**. 1. Clone the fork on your machine with `git clone https://github.com//.git` 1. `cd ` then run `git remote add upstream https://github.com/ThingPulse/esp8266-oled-ssd1306` 1. `git checkout ` 1. Make changes to the code base and commit them using e.g. `git commit -a -m 'Look ma, I did it'` 1. When you're done bring your fork up-to-date with the upstream repo ([see below](#keeping-your-fork-in-sync)). Then rebase your branch on `master` running `git rebase master`. 1. `git push` 1. [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) (PR) on GitHub. This is just one way of doing things. If you're proficient in Git matters you're free to choose your own. If you want to read more then the [GitHub chapter in the Git book](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project#The-GitHub-Flow) is a way to start. [GitHub's own documentation](https://help.github.com/categories/collaborating/) contains a wealth of information as well. ### Keeping your fork in sync You need to sync your fork with the upstream repository from time to time, latest before you rebase (see flow above). 1. `git fetch upstream` 1. `git checkout master` 1. `git merge upstream/master` ### Commit messages From: [http://git-scm.com/book/ch5-2.html](http://git-scm.com/book/ch5-2.html)
Short (50 chars or less) summary of changes

More detailed explanatory text, if necessary.  Wrap it to about 72
characters or so.  In some contexts, the first line is treated as the
subject of an email and the rest of the text as the body.  The blank
line separating the summary from the body is critical (unless you omit
the body entirely); tools like rebase can get confused if you run the
two together.

Further paragraphs come after blank lines.

- Bullet points are okay, too
- Typically a hyphen or asterisk is used for the bullet, preceded by a
   single space, with blank lines in between, but conventions vary here
Don't forget to [reference affected issues](https://help.github.com/articles/closing-issues-via-commit-messages/) in the commit message to have them closed automatically on GitHub. [Amend](https://help.github.com/articles/changing-a-commit-message/) your commit messages if necessary to make sure what the world sees on GitHub is as expressive and meaningful as possible. ================================================ FILE: README.md ================================================ # ThingPulse OLED SSD1306 (ESP8266/ESP32/Mbed-OS) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/thingpulse/library/ESP8266%20and%20ESP32%20OLED%20driver%20for%20SSD1306%20displays.svg)](https://registry.platformio.org/libraries/thingpulse/ESP8266%20and%20ESP32%20OLED%20driver%20for%20SSD1306%20displays) [![Build Status](https://github.com/ThingPulse/esp8266-oled-ssd1306/actions/workflows/main.yml/badge.svg)](https://github.com/ThingPulse/esp8266-oled-ssd1306/actions) This is a driver for SSD1306 and SH1106 128x64, 128x32, 64x48 and 64x32 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. This library drives the OLED display included in the [ThingPulse IoT starter kit](https://thingpulse.com/product/esp8266-iot-electronics-starter-kit-weatherstation-planespotter-worldclock/) aka classic kit aka weather station kit. [![ThingPulse ESP8266 WeatherStation Classic Kit](https://github.com/ThingPulse/esp8266-weather-station/blob/master/resources/ThingPulse-ESP8266-Weather-Station.jpeg?raw=true)](https://thingpulse.com/product/esp8266-iot-electronics-starter-kit-weatherstation-planespotter-worldclock/) 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. It is also available as a [PlatformIO library](https://platformio.org/lib/show/2978/ESP8266%20and%20ESP32%20OLED%20driver%20for%20SSD1306%20displays/examples). Just execute the following command: ``` platformio lib install 2978 ``` ## Service level promise
This is a ThingPulse prime project. See our open-source commitment declaration for what this means.
## Credits This library has initially been written by [Daniel Eichhorn](https://github.com/squix78). Many thanks go to [Fabrice Weinberg](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](https://github.com/helmut64). The init sequence for the SSD1306 was inspired by Adafruit's library for the same display. ## mbed-os This library has been adopted to support the ARM mbed-os environment. A copy of this library is available in mbed-os under the name OLED_SSD1306 by Helmut Tschemernjak. An alternate installation option is to copy the following files into your mbed-os project: OLEDDisplay.cpp OLEDDisplay.h OLEDDisplayFonts.h OLEDDisplayUi.cpp OLEDDisplayUi.h SSD1306I2C.h ## 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. ## Upgrade The API changed a lot with the 3.0 release. If you were using this library with older versions please have a look at the [Upgrade Guide](UPGRADE-3.0.md). Going from 3.x version to 4.0 a lot of internals changed and compatibility for more displays was added. Please read the [Upgrade Guide](UPGRADE-4.0.md). ## 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, CS); // RES, DC, CS ``` In case the CS pin is not used (hard wired to ground), pass CS as -1. ## 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 setContrast with only brightness parameter 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 an empty triangle i.e. only the outline void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); // Draw a solid triangle i.e. filled void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); // 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 uint8_t *xbm); ``` ## Text operations ``` C++ // Draws a string at the given location, returns how many chars have been written uint16_t 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 // returns 0 if everything fits on the screen or the numbers of characters in the // first line if not uint16_t 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, bool utf8 = false); // Convencience method for the const char version uint16_t getStringWidth(const 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); ``` ## Arduino `Print` functionality Because this class has been "derived" from Arduino's `Print` class, you can use the functions it provides. In plain language, this means that you can use `print`, `println` and `printf` to the display. Internally, a buffer holds the text that was printed to the display previously (that would still fit on the display) and every time you print something, this buffer is put on the screen, using the functions from the previous section. What that means is that printing using `print` and "manually" putting things on the display are somewhat mutually exclusive: as soon as you print, everything that was on the display already is gone and only what you put there before with `print`, `println` or `printf` remains. Still, using `print` is a very simple way to put something on the display quickly. One extra function is provided: `cls()` ```cpp // cls() will clear the display immediately and empty the logBuffer, meaning // the next print statement will print at the top of the display again. // cls() should not be confused with clear(), which only clears the internal // graphics buffer, which can then be shown on the display with display(). void cls(); > _Note that printing to the display, contrary to what you might expect, does not wrap your lines, so everything on a line that doesn't fit on the screen is cut off._ ```  
## Ui Library (OLEDDisplayUi) The Ui Library is used to provide a basic set of user interface elements called `Frames` and `Overlays`. A `Frame` is used to provide information to the user. The default behaviour is to display a `Frame` for a defined time and than move to the next `Frame`. The library also provides an `Indicator` element that will be updated accordingly. An `Overlay` on the other hand is a piece of information (e.g. a clock) that is always displayed 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 uint8_t* symbol); /** * Set the symbol to indicate an inactive frame in the indicator bar. */ void setInactiveSymbol(const uint8_t* 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); // 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(); // 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(); ``` ## Creating and using XBM bitmaps If you want to display your own images with this library, the best way to do this is using a bitmap. There are two options to convert an image to a compatible bitmap: 1. **Using Gimp.** In this case exporting the bitmap in an 1-bit XBM format is sufficient. 2. **Using a converter website.** You could also use online converter services like e.g. [https://javl.github.io/image2cpp/](https://javl.github.io/image2cpp/). The uploaded image should have the same dimension as the screen (e.g. 128x64). The following output settings should be set: - Draw Mode: Horizontal - 1 bit per pixel - Swap bits in byte: swap checkbox should be checked. The resulting bitmap can be put into a header file: ```C++ const unsigned char epd_example [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ... ... }; ``` Subsequently, it can be used like this: ```C++ display.clear(); display.drawXbm(0, 0, 128, 64, epd_example); // assuming your bitmap is 128x64 display.display(); ``` ## 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 XMB image * How to draw 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. ## Selection of projects using this library * [QRCode ESP8266](https://github.com/anunpanya/ESP8266_QRcode) (by @anunpanya) * [Scan I2C](https://github.com/hallard/Scan-I2C-WiFi) (by @hallard) * [ThingPulse Weather Station](https://github.com/ThingPulse/esp8266-weather-station) * [Meshtastic](https://www.meshtastic.org/) - an open source GPS communicator mesh radio * [OpenMQTTGateway](https://docs.openmqttgateway.com) - OpenMQTTGateway aims to unify various technologies and protocols into a single firmware. This reduces the need for multiple physical bridges and streamlines diverse technologies under the widely-used MQTT protocol. * [OpenAstroTracker](https://openastrotech.com) - Open source hardware and software for Astrophotography. The firmware for the mounts supports displays and uses this library to drive them. * Yours? ================================================ FILE: README_GEOMETRY_64_48.md ================================================ # GEOMETRY_64_48 The 64x48 geometry setting are working with the `Wire.h` and `brzo_i2c` libraries. I've tested it successfully with a WEMOS D1 mini Lite and a WEMOS OLED shield Initialization code: - Wire ``` #include #include SSD1306Wire display(0x3c, D2, D1, GEOMETRY_64_48 ); // WEMOS OLED shield ``` - BRZO i2c ``` #include SSD1306Brzo display(0x3c, D2, D1, GEOMETRY_64_48 ); // WEMOS OLED Shield ``` ================================================ FILE: UPGRADE-3.0.md ================================================ # Upgrade from 2.0 to 3.0 While developing version 3.0 we made some breaking changes to the public API of this library. This document will help you update your code to work with version 3.0 ## Font Definitions To get better performance and a smaller font definition format, we change the memory layout of the font definition format. If you are using custom fonts not included in this library we updated the font generator [here](http://oleddisplay.squix.ch/#/home). Please update your fonts to be working with 3.0 by selecting the respective version in the dropdown. ## Architectural Changes To become a more versatile library for the SSD1306 chipset we abstracted the hardware connection into subclasses of the base display class now called `OLEDDisplay`. This library is currently shipping with three implementations: * `SSD1306Wire` implementing the I2C protocol using the Wire Library. * `SSD1306Brzo` implementing the I2C protocol using the faster [`brzo_i2c`](https://github.com/pasko-zh/brzo_i2c) library. * `SSD1306Spi` implementing the SPI protocol. To keep backwards compatiblity with the old API `SSD1306` is an alias of `SSD1306Wire`. If you are not using the UI components you don't have to change anything to keep your code working. ## Name Changes [Naming things is hard](http://martinfowler.com/bliki/TwoHardThings.html), to better reflect our intention with this library we changed the name of the base class to `OLEDDisplay` and the UI library accordingly to `OLEDDisplayUi`. As a consequence the type definitions of all frame and overlay related functions changed. This means that you have to update all your frame drawing callbacks from: ```c bool frame1(SSD1306 *display, SSD1306UiState* state, int x, int y); ``` too ```c void frame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y); ``` And your overlay drawing functions from: ```c bool overlay1(SSD1306 *display, SSD1306UiState* state); ``` too ```c void overlay1(OLEDDisplay *display, OLEDDisplayUiState* state); ``` ## New Features ### Loading Animation While using this library ourself we noticed a pattern emerging. We want to drawing a loading progress while connecting to WiFi and updating weather data etc. The simplest thing was to add the function `drawProgressBar(x, y, width, height, progress)` ,where `progress` is between `0` and `100`, right to the `OLEDDisplay` class. But we didn't stop there. We added a new feature to the `OLEDDisplayUi` called `LoadingStages`. You can define your loading process like this: ```c++ LoadingStage loadingStages[] = { { .process = "Connect to WiFi", .callback = []() { // Connect to WiFi } }, { .process = "Get time from NTP", .callback = []() { // Get current time via NTP } } // more steps }; int LOADING_STAGES_COUNT = sizeof(loadingStages) / sizeof(LoadingStage); ``` After defining your array of `LoadingStages` you can then run the loading process by using `ui.runLoadingProcess(loadingStages, LOADING_STAGES_COUNT)`. This will give you a nice little loading animation you can see in the beginning of [this](https://vimeo.com/168362918) video. To further customize this you are free to define your own `LoadingDrawFunction` like this: ```c void myLoadingDraw(OLEDDisplay *display, LoadingStage* stage, uint8_t progress) { display->setTextAlignment(TEXT_ALIGN_CENTER); display->setFont(ArialMT_Plain_10); // stage->process contains the text of the current progress e.q. "Connect to WiFi" display->drawString(64, 18, stage->process); // you could just print the current process without the progress bar display->drawString(64, 28, progress); } ``` After defining a function like that, you can pass it to the Ui library by use `ui.setLoadingDrawFunction(myLoadingDraw)`. ### Text Logging It is always useful to display some text on the display without worrying to much where it goes and managing it. In 3.0 we made the `OLEDDisplay` class implement [`Print`](https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.h) so you can use it like you would use `Serial`. We calls this feature `LogBuffer` and the only thing you have to do is to define how many lines you want to display and how many characters there are on average on each. This is done by calling `setLogBuffer(lines, chars);`. If there is not enough memory the function will return false. After that you can draw the `LogBuffer` anywhere you want by calling `drawLogBuffer(x, y)`. (Note: You have to call `display()` to update the screen) We made a [video](https://www.youtube.com/watch?v=8Fiss77A3TE) showing this feature in action. ================================================ FILE: UPGRADE-4.0.md ================================================ # Upgrade from 3.x to 4.0 There are changes that breaks compatibility with older versions. 1. You'll have to change data type for all your binary resources such as images and fonts from ```c const char MySymbol[] PROGMEM = { ``` to ```c const uint8_t MySymbol[] PROGMEM = { ``` 1. Arguments of `setContrast` from `char` to `uint8_t` ```c++ void OLEDDisplay::setContrast(char contrast, char precharge, char comdetect); ``` to ```c++ void OLEDDisplay::setContrast(uint8_t contrast, uint8_t precharge, uint8_t comdetect); ``` ================================================ FILE: component.mk ================================================ COMPONENT_ADD_INCLUDEDIRS := src COMPONENT_SRCDIRS := src CXXFLAGS += -Wno-ignored-qualifiers ================================================ FILE: examples/SSD1306ClockDemo/SSD1306ClockDemo.ino ================================================ /** 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 */ // Install https://github.com/PaulStoffregen/Time #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, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h // SH1106Wire display(0x3c, SDA, SCL); 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(115200); 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); } } ================================================ FILE: examples/SSD1306ClockDemo/images.h ================================================ 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 }; ================================================ FILE: examples/SSD1306DrawingDemo/SSD1306DrawingDemo.ino ================================================ /** 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, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h // SH1106Wire display(0x3c, SDA, SCL); // Adapted from Adafruit_SSD1306 void drawLines() { for (int16_t i = 0; i < display.getWidth(); i += 4) { display.drawLine(0, 0, i, display.getHeight() - 1); display.display(); delay(10); } for (int16_t i = 0; i < display.getHeight(); i += 4) { display.drawLine(0, 0, display.getWidth() - 1, i); display.display(); delay(10); } delay(250); display.clear(); for (int16_t i = 0; i < display.getWidth(); i += 4) { display.drawLine(0, display.getHeight() - 1, i, 0); display.display(); delay(10); } for (int16_t i = display.getHeight() - 1; 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 < display.getHeight(); i += 4) { display.drawLine(display.getWidth() - 1, 0, 0, i); display.display(); delay(10); } for (int16_t i = 0; i < display.getWidth(); i += 4) { display.drawLine(display.getWidth() - 1, 0, i, display.getHeight() - 1); display.display(); delay(10); } delay(250); } // Adapted from Adafruit_SSD1306 void drawRect(void) { for (int16_t i = 0; i < display.getHeight() / 2; i += 2) { display.drawRect(i, i, display.getWidth() - 2 * i, display.getHeight() - 2 * i); display.display(); delay(10); } } // Adapted from Adafruit_SSD1306 void fillRect(void) { uint8_t color = 1; for (int16_t i = 0; i < display.getHeight() / 2; i += 3) { display.setColor((color % 2 == 0) ? BLACK : WHITE); // alternate colors display.fillRect(i, i, display.getWidth() - i * 2, display.getHeight() - i * 2); display.display(); delay(10); color++; } // Reset back to WHITE display.setColor(WHITE); } // Adapted from Adafruit_SSD1306 void drawCircle(void) { for (int16_t i = 0; i < display.getHeight(); i += 2) { display.drawCircle(display.getWidth() / 2, display.getHeight() / 2, i); display.display(); delay(10); } delay(1000); display.clear(); // This will draw the part of the circel in quadrant 1 // Quadrants are numberd like this: // 0010 | 0001 // ------|----- // 0100 | 1000 // display.drawCircleQuads(display.getWidth() / 2, display.getHeight() / 2, display.getHeight() / 4, 0b00000001); display.display(); delay(200); display.drawCircleQuads(display.getWidth() / 2, display.getHeight() / 2, display.getHeight() / 4, 0b00000011); display.display(); delay(200); display.drawCircleQuads(display.getWidth() / 2, display.getHeight() / 2, display.getHeight() / 4, 0b00000111); display.display(); delay(200); display.drawCircleQuads(display.getWidth() / 2, display.getHeight() / 2, display.getHeight() / 4, 0b00001111); display.display(); } void printBuffer(void) { // Some test data const char* test[] = { "Hello", "World" , "----", "Show off", "how", "the log buffer", "is", "working.", "Even", "scrolling is", "working" }; display.clear(); for (uint8_t i = 0; i < 11; i++) { // Print to the screen display.println(test[i]); delay(500); } } void setup() { display.init(); // display.flipScreenVertically(); display.setContrast(255); drawLines(); delay(1000); display.clear(); drawRect(); delay(1000); display.clear(); fillRect(); delay(1000); display.clear(); drawCircle(); delay(1000); display.clear(); printBuffer(); delay(1000); display.clear(); } void loop() { } ================================================ FILE: examples/SSD1306FontTryout/Dialog_plain_6.h ================================================ // Created by http://oleddisplay.squix.ch/ Consider a donation // In case of problems make sure that you are using the font file with the correct version! const char Dialog_plain_6[] PROGMEM = { 0x06, // Width: 6 0x08, // Height: 8 0x20, // First Char: 32 0xE0, // Numbers of Chars: 224 // Jump Table: 0xFF, 0xFF, 0x00, 0x02, // 32:65535 0x00, 0x00, 0x02, 0x02, // 33:0 0x00, 0x02, 0x02, 0x03, // 34:2 0x00, 0x04, 0x05, 0x05, // 35:4 0x00, 0x09, 0x04, 0x04, // 36:9 0x00, 0x0D, 0x06, 0x06, // 37:13 0x00, 0x13, 0x05, 0x05, // 38:19 0x00, 0x18, 0x02, 0x02, // 39:24 0x00, 0x1A, 0x02, 0x02, // 40:26 0x00, 0x1C, 0x02, 0x02, // 41:28 0x00, 0x1E, 0x03, 0x03, // 42:30 0x00, 0x21, 0x05, 0x05, // 43:33 0x00, 0x26, 0x02, 0x02, // 44:38 0x00, 0x28, 0x02, 0x02, // 45:40 0x00, 0x2A, 0x02, 0x02, // 46:42 0x00, 0x2C, 0x02, 0x02, // 47:44 0x00, 0x2E, 0x04, 0x04, // 48:46 0x00, 0x32, 0x04, 0x04, // 49:50 0x00, 0x36, 0x04, 0x04, // 50:54 0x00, 0x3A, 0x04, 0x04, // 51:58 0x00, 0x3E, 0x04, 0x04, // 52:62 0x00, 0x42, 0x04, 0x04, // 53:66 0x00, 0x46, 0x04, 0x04, // 54:70 0x00, 0x4A, 0x04, 0x04, // 55:74 0x00, 0x4E, 0x04, 0x04, // 56:78 0x00, 0x52, 0x04, 0x04, // 57:82 0x00, 0x56, 0x02, 0x02, // 58:86 0x00, 0x58, 0x02, 0x02, // 59:88 0x00, 0x5A, 0x05, 0x05, // 60:90 0x00, 0x5F, 0x05, 0x05, // 61:95 0x00, 0x64, 0x05, 0x05, // 62:100 0x00, 0x69, 0x03, 0x03, // 63:105 0x00, 0x6C, 0x06, 0x06, // 64:108 0x00, 0x72, 0x04, 0x04, // 65:114 0x00, 0x76, 0x04, 0x04, // 66:118 0x00, 0x7A, 0x04, 0x04, // 67:122 0x00, 0x7E, 0x05, 0x05, // 68:126 0x00, 0x83, 0x04, 0x04, // 69:131 0x00, 0x87, 0x03, 0x03, // 70:135 0x00, 0x8A, 0x05, 0x05, // 71:138 0x00, 0x8F, 0x04, 0x05, // 72:143 0x00, 0x93, 0x02, 0x02, // 73:147 0x00, 0x95, 0x02, 0x02, // 74:149 0x00, 0x97, 0x04, 0x04, // 75:151 0x00, 0x9B, 0x03, 0x03, // 76:155 0x00, 0x9E, 0x05, 0x05, // 77:158 0x00, 0xA3, 0x04, 0x04, // 78:163 0x00, 0xA7, 0x05, 0x05, // 79:167 0x00, 0xAC, 0x04, 0x04, // 80:172 0x00, 0xB0, 0x05, 0x05, // 81:176 0x00, 0xB5, 0x04, 0x04, // 82:181 0x00, 0xB9, 0x04, 0x04, // 83:185 0x00, 0xBD, 0x04, 0x04, // 84:189 0x00, 0xC1, 0x04, 0x04, // 85:193 0x00, 0xC5, 0x04, 0x04, // 86:197 0x00, 0xC9, 0x06, 0x06, // 87:201 0x00, 0xCF, 0x04, 0x04, // 88:207 0x00, 0xD3, 0x04, 0x04, // 89:211 0x00, 0xD7, 0x04, 0x04, // 90:215 0x00, 0xDB, 0x02, 0x02, // 91:219 0x00, 0xDD, 0x02, 0x02, // 92:221 0x00, 0xDF, 0x02, 0x02, // 93:223 0x00, 0xE1, 0x05, 0x05, // 94:225 0x00, 0xE6, 0x03, 0x03, // 95:230 0x00, 0xE9, 0x02, 0x03, // 96:233 0x00, 0xEB, 0x04, 0x04, // 97:235 0x00, 0xEF, 0x04, 0x04, // 98:239 0x00, 0xF3, 0x03, 0x03, // 99:243 0x00, 0xF6, 0x04, 0x04, // 100:246 0x00, 0xFA, 0x04, 0x04, // 101:250 0x00, 0xFE, 0x02, 0x02, // 102:254 0x01, 0x00, 0x04, 0x04, // 103:256 0x01, 0x04, 0x04, 0x04, // 104:260 0x01, 0x08, 0x02, 0x02, // 105:264 0x01, 0x0A, 0x02, 0x02, // 106:266 0x01, 0x0C, 0x03, 0x03, // 107:268 0x01, 0x0F, 0x02, 0x02, // 108:271 0x01, 0x11, 0x06, 0x06, // 109:273 0x01, 0x17, 0x04, 0x04, // 110:279 0x01, 0x1B, 0x04, 0x04, // 111:283 0x01, 0x1F, 0x04, 0x04, // 112:287 0x01, 0x23, 0x04, 0x04, // 113:291 0x01, 0x27, 0x02, 0x02, // 114:295 0x01, 0x29, 0x03, 0x03, // 115:297 0x01, 0x2C, 0x02, 0x02, // 116:300 0x01, 0x2E, 0x04, 0x04, // 117:302 0x01, 0x32, 0x03, 0x04, // 118:306 0x01, 0x35, 0x04, 0x05, // 119:309 0x01, 0x39, 0x03, 0x04, // 120:313 0x01, 0x3C, 0x03, 0x04, // 121:316 0x01, 0x3F, 0x03, 0x03, // 122:319 0x01, 0x42, 0x04, 0x04, // 123:322 0x01, 0x46, 0x02, 0x02, // 124:326 0x01, 0x48, 0x04, 0x04, // 125:328 0x01, 0x4C, 0x05, 0x05, // 126:332 0x01, 0x51, 0x03, 0x04, // 127:337 0x01, 0x54, 0x03, 0x04, // 128:340 0x01, 0x57, 0x03, 0x04, // 129:343 0x01, 0x5A, 0x03, 0x04, // 130:346 0x01, 0x5D, 0x03, 0x04, // 131:349 0x01, 0x60, 0x03, 0x04, // 132:352 0x01, 0x63, 0x03, 0x04, // 133:355 0x01, 0x66, 0x03, 0x04, // 134:358 0x01, 0x69, 0x03, 0x04, // 135:361 0x01, 0x6C, 0x03, 0x04, // 136:364 0x01, 0x6F, 0x03, 0x04, // 137:367 0x01, 0x72, 0x03, 0x04, // 138:370 0x01, 0x75, 0x03, 0x04, // 139:373 0x01, 0x78, 0x03, 0x04, // 140:376 0x01, 0x7B, 0x03, 0x04, // 141:379 0x01, 0x7E, 0x03, 0x04, // 142:382 0x01, 0x81, 0x03, 0x04, // 143:385 0x01, 0x84, 0x03, 0x04, // 144:388 0x01, 0x87, 0x03, 0x04, // 145:391 0x01, 0x8A, 0x03, 0x04, // 146:394 0x01, 0x8D, 0x03, 0x04, // 147:397 0x01, 0x90, 0x03, 0x04, // 148:400 0x01, 0x93, 0x03, 0x04, // 149:403 0x01, 0x96, 0x03, 0x04, // 150:406 0x01, 0x99, 0x03, 0x04, // 151:409 0x01, 0x9C, 0x03, 0x04, // 152:412 0x01, 0x9F, 0x03, 0x04, // 153:415 0x01, 0xA2, 0x03, 0x04, // 154:418 0x01, 0xA5, 0x03, 0x04, // 155:421 0x01, 0xA8, 0x03, 0x04, // 156:424 0x01, 0xAB, 0x03, 0x04, // 157:427 0x01, 0xAE, 0x03, 0x04, // 158:430 0x01, 0xB1, 0x03, 0x04, // 159:433 0xFF, 0xFF, 0x00, 0x02, // 160:65535 0x01, 0xB4, 0x02, 0x02, // 161:436 0x01, 0xB6, 0x04, 0x04, // 162:438 0x01, 0xBA, 0x04, 0x04, // 163:442 0x01, 0xBE, 0x04, 0x04, // 164:446 0x01, 0xC2, 0x04, 0x04, // 165:450 0x01, 0xC6, 0x02, 0x02, // 166:454 0x01, 0xC8, 0x03, 0x03, // 167:456 0x01, 0xCB, 0x02, 0x03, // 168:459 0x01, 0xCD, 0x05, 0x06, // 169:461 0x01, 0xD2, 0x03, 0x03, // 170:466 0x01, 0xD5, 0x03, 0x04, // 171:469 0x01, 0xD8, 0x05, 0x05, // 172:472 0x01, 0xDD, 0x02, 0x02, // 173:477 0x01, 0xDF, 0x05, 0x06, // 174:479 0x01, 0xE4, 0x03, 0x03, // 175:484 0x01, 0xE7, 0x03, 0x03, // 176:487 0x01, 0xEA, 0x05, 0x05, // 177:490 0x01, 0xEF, 0x02, 0x02, // 178:495 0x01, 0xF1, 0x02, 0x02, // 179:497 0x01, 0xF3, 0x02, 0x03, // 180:499 0x01, 0xF5, 0x04, 0x04, // 181:501 0x01, 0xF9, 0x03, 0x04, // 182:505 0x01, 0xFC, 0x02, 0x02, // 183:508 0x01, 0xFE, 0x02, 0x03, // 184:510 0x02, 0x00, 0x02, 0x02, // 185:512 0x02, 0x02, 0x03, 0x03, // 186:514 0x02, 0x05, 0x03, 0x04, // 187:517 0x02, 0x08, 0x06, 0x06, // 188:520 0x02, 0x0E, 0x06, 0x06, // 189:526 0x02, 0x14, 0x06, 0x06, // 190:532 0x02, 0x1A, 0x03, 0x03, // 191:538 0x02, 0x1D, 0x04, 0x04, // 192:541 0x02, 0x21, 0x04, 0x04, // 193:545 0x02, 0x25, 0x04, 0x04, // 194:549 0x02, 0x29, 0x04, 0x04, // 195:553 0x02, 0x2D, 0x04, 0x04, // 196:557 0x02, 0x31, 0x04, 0x04, // 197:561 0x02, 0x35, 0x06, 0x06, // 198:565 0x02, 0x3B, 0x04, 0x04, // 199:571 0x02, 0x3F, 0x04, 0x04, // 200:575 0x02, 0x43, 0x04, 0x04, // 201:579 0x02, 0x47, 0x04, 0x04, // 202:583 0x02, 0x4B, 0x04, 0x04, // 203:587 0x02, 0x4F, 0x02, 0x02, // 204:591 0x02, 0x51, 0x02, 0x02, // 205:593 0x02, 0x53, 0x02, 0x02, // 206:595 0x02, 0x55, 0x02, 0x02, // 207:597 0x02, 0x57, 0x05, 0x05, // 208:599 0x02, 0x5C, 0x04, 0x04, // 209:604 0x02, 0x60, 0x05, 0x05, // 210:608 0x02, 0x65, 0x05, 0x05, // 211:613 0x02, 0x6A, 0x05, 0x05, // 212:618 0x02, 0x6F, 0x05, 0x05, // 213:623 0x02, 0x74, 0x05, 0x05, // 214:628 0x02, 0x79, 0x04, 0x05, // 215:633 0x02, 0x7D, 0x05, 0x05, // 216:637 0x02, 0x82, 0x04, 0x04, // 217:642 0x02, 0x86, 0x04, 0x04, // 218:646 0x02, 0x8A, 0x04, 0x04, // 219:650 0x02, 0x8E, 0x04, 0x04, // 220:654 0x02, 0x92, 0x04, 0x04, // 221:658 0x02, 0x96, 0x04, 0x04, // 222:662 0x02, 0x9A, 0x04, 0x04, // 223:666 0x02, 0x9E, 0x04, 0x04, // 224:670 0x02, 0xA2, 0x04, 0x04, // 225:674 0x02, 0xA6, 0x04, 0x04, // 226:678 0x02, 0xAA, 0x04, 0x04, // 227:682 0x02, 0xAE, 0x04, 0x04, // 228:686 0x02, 0xB2, 0x04, 0x04, // 229:690 0x02, 0xB6, 0x06, 0x06, // 230:694 0x02, 0xBC, 0x03, 0x03, // 231:700 0x02, 0xBF, 0x04, 0x04, // 232:703 0x02, 0xC3, 0x04, 0x04, // 233:707 0x02, 0xC7, 0x04, 0x04, // 234:711 0x02, 0xCB, 0x04, 0x04, // 235:715 0x02, 0xCF, 0x02, 0x02, // 236:719 0x02, 0xD1, 0x02, 0x02, // 237:721 0x02, 0xD3, 0x02, 0x02, // 238:723 0x02, 0xD5, 0x02, 0x02, // 239:725 0x02, 0xD7, 0x04, 0x04, // 240:727 0x02, 0xDB, 0x04, 0x04, // 241:731 0x02, 0xDF, 0x04, 0x04, // 242:735 0x02, 0xE3, 0x04, 0x04, // 243:739 0x02, 0xE7, 0x04, 0x04, // 244:743 0x02, 0xEB, 0x04, 0x04, // 245:747 0x02, 0xEF, 0x04, 0x04, // 246:751 0x02, 0xF3, 0x05, 0x05, // 247:755 0x02, 0xF8, 0x04, 0x04, // 248:760 0x02, 0xFC, 0x04, 0x04, // 249:764 0x03, 0x00, 0x04, 0x04, // 250:768 0x03, 0x04, 0x04, 0x04, // 251:772 0x03, 0x08, 0x04, 0x04, // 252:776 0x03, 0x0C, 0x03, 0x04, // 253:780 0x03, 0x0F, 0x04, 0x04, // 254:783 0x03, 0x13, 0x03, 0x04, // 255:787 // Font Data: 0x00,0x2C, // 33 0x00,0x0C, // 34 0x00,0x18,0x1C,0x38,0x18, // 35 0x00,0x2C,0x7E,0x3C, // 36 0x00,0x0C,0x2C,0x18,0x34,0x30, // 37 0x00,0x30,0x3C,0x34,0x30, // 38 0x00,0x0C, // 39 0x00,0x1C, // 40 0x00,0x1C, // 41 0x0C,0x0C,0x0C, // 42 0x00,0x08,0x08,0x3E,0x08, // 43 0x00,0x20, // 44 0x00,0x10, // 45 0x00,0x20, // 46 0x70,0x1C, // 47 0x00,0x3C,0x24,0x3C, // 48 0x00,0x24,0x3C,0x20, // 49 0x00,0x24,0x34,0x3C, // 50 0x00,0x24,0x2C,0x34, // 51 0x00,0x10,0x18,0x3C, // 52 0x00,0x2C,0x2C,0x3C, // 53 0x00,0x38,0x34,0x34, // 54 0x00,0x04,0x34,0x0C, // 55 0x00,0x34,0x2C,0x34, // 56 0x00,0x2C,0x2C,0x1C, // 57 0x00,0x28, // 58 0x00,0x28, // 59 0x00,0x08,0x08,0x1C,0x14, // 60 0x00,0x14,0x14,0x14,0x14, // 61 0x00,0x14,0x1C,0x08,0x08, // 62 0x00,0x04,0x24, // 63 0x00,0x38,0x54,0x74,0x14,0x08, // 64 0x20,0x1C,0x1C,0x20, // 65 0x00,0x3C,0x2C,0x34, // 66 0x00,0x18,0x24,0x24, // 67 0x00,0x3C,0x24,0x24,0x18, // 68 0x00,0x3C,0x2C,0x2C, // 69 0x00,0x3C,0x0C, // 70 0x00,0x18,0x24,0x2C,0x3C, // 71 0x00,0x3C,0x08,0x3C, // 72 0x00,0x3C, // 73 0x40,0x7C, // 74 0x00,0x3C,0x3C,0x24, // 75 0x00,0x3C,0x20, // 76 0x00,0x3C,0x1C,0x0C,0x3C, // 77 0x00,0x3C,0x1C,0x3C, // 78 0x00,0x18,0x24,0x24,0x18, // 79 0x00,0x3C,0x14,0x1C, // 80 0x00,0x18,0x24,0x64,0x18, // 81 0x00,0x3C,0x34,0x2C, // 82 0x00,0x2C,0x2C,0x3C, // 83 0x04,0x04,0x3C,0x04, // 84 0x00,0x3C,0x20,0x3C, // 85 0x04,0x38,0x38,0x04, // 86 0x0C,0x30,0x0C,0x0C,0x30,0x0C, // 87 0x24,0x3C,0x3C,0x24, // 88 0x04,0x0C,0x38,0x0C, // 89 0x00,0x24,0x3C,0x2C, // 90 0x00,0x3E, // 91 0x1C,0x70, // 92 0x00,0x22, // 93 0x00,0x08,0x04,0x04,0x08, // 94 0x40,0x40,0x40, // 95 0x00,0x02, // 96 0x00,0x30,0x38,0x38, // 97 0x00,0x3E,0x28,0x38, // 98 0x00,0x38,0x28, // 99 0x00,0x38,0x28,0x3E, // 100 0x00,0x38,0x38,0x38, // 101 0x08,0x3E, // 102 0x00,0x78,0x68,0x78, // 103 0x00,0x3E,0x08,0x38, // 104 0x00,0x3A, // 105 0x40,0x7A, // 106 0x00,0x3E,0x38, // 107 0x00,0x3E, // 108 0x00,0x38,0x08,0x38,0x08,0x38, // 109 0x00,0x38,0x08,0x38, // 110 0x00,0x38,0x28,0x38, // 111 0x00,0x78,0x28,0x38, // 112 0x00,0x38,0x28,0x78, // 113 0x00,0x38, // 114 0x00,0x28,0x38, // 115 0x00,0x3C, // 116 0x00,0x38,0x20,0x38, // 117 0x08,0x30,0x08, // 118 0x38,0x18,0x38,0x18, // 119 0x28,0x38,0x28, // 120 0x68,0x30,0x08, // 121 0x00,0x28,0x38, // 122 0x00,0x08,0x76,0x42, // 123 0x00,0x7E, // 124 0x00,0x42,0x76,0x08, // 125 0x00,0x08,0x08,0x08,0x08, // 126 0x7C,0x44,0x7C, // 127 0x7C,0x44,0x7C, // 128 0x7C,0x44,0x7C, // 129 0x7C,0x44,0x7C, // 130 0x7C,0x44,0x7C, // 131 0x7C,0x44,0x7C, // 132 0x7C,0x44,0x7C, // 133 0x7C,0x44,0x7C, // 134 0x7C,0x44,0x7C, // 135 0x7C,0x44,0x7C, // 136 0x7C,0x44,0x7C, // 137 0x7C,0x44,0x7C, // 138 0x7C,0x44,0x7C, // 139 0x7C,0x44,0x7C, // 140 0x7C,0x44,0x7C, // 141 0x7C,0x44,0x7C, // 142 0x7C,0x44,0x7C, // 143 0x7C,0x44,0x7C, // 144 0x7C,0x44,0x7C, // 145 0x7C,0x44,0x7C, // 146 0x7C,0x44,0x7C, // 147 0x7C,0x44,0x7C, // 148 0x7C,0x44,0x7C, // 149 0x7C,0x44,0x7C, // 150 0x7C,0x44,0x7C, // 151 0x7C,0x44,0x7C, // 152 0x7C,0x44,0x7C, // 153 0x7C,0x44,0x7C, // 154 0x7C,0x44,0x7C, // 155 0x7C,0x44,0x7C, // 156 0x7C,0x44,0x7C, // 157 0x7C,0x44,0x7C, // 158 0x7C,0x44,0x7C, // 159 0x00,0x68, // 161 0x00,0x38,0x7C,0x28, // 162 0x28,0x3C,0x2C,0x24, // 163 0x00,0x38,0x28,0x38, // 164 0x00,0x2C,0x38,0x2C, // 165 0x00,0x6C, // 166 0x00,0x5C,0x74, // 167 0x00,0x02, // 168 0x00,0x18,0x24,0x3C,0x18, // 169 0x00,0x2C,0x2C, // 170 0x00,0x10,0x10, // 171 0x00,0x08,0x08,0x08,0x18, // 172 0x00,0x10, // 173 0x00,0x18,0x34,0x34,0x18, // 174 0x00,0x04,0x04, // 175 0x00,0x0C,0x0C, // 176 0x28,0x28,0x3C,0x28,0x28, // 177 0x00,0x0C, // 178 0x00,0x0C, // 179 0x00,0x02, // 180 0x00,0x78,0x20,0x38, // 181 0x7C,0x04,0x7C, // 182 0x00,0x10, // 183 0x00,0x40, // 184 0x00,0x0C, // 185 0x00,0x2C,0x2C, // 186 0x00,0x10,0x10, // 187 0x00,0x2C,0x1C,0x0C,0x20,0x30, // 188 0x00,0x2C,0x1C,0x0C,0x30,0x30, // 189 0x00,0x2C,0x18,0x04,0x20,0x30, // 190 0x00,0x48,0x40, // 191 0x20,0x1C,0x1D,0x21, // 192 0x20,0x1C,0x1D,0x20, // 193 0x20,0x1D,0x1D,0x20, // 194 0x20,0x1D,0x1D,0x20, // 195 0x20,0x1D,0x1D,0x20, // 196 0x20,0x1E,0x1A,0x20, // 197 0x20,0x18,0x14,0x3C,0x2C,0x2C, // 198 0x00,0x18,0x64,0x24, // 199 0x00,0x3D,0x2D,0x2C, // 200 0x00,0x3D,0x2C,0x2C, // 201 0x00,0x3D,0x2D,0x2C, // 202 0x00,0x3D,0x2C,0x2D, // 203 0x01,0x3D, // 204 0x01,0x3C, // 205 0x01,0x3D, // 206 0x01,0x3C, // 207 0x10,0x3C,0x34,0x24,0x18, // 208 0x00,0x3C,0x1D,0x3C, // 209 0x00,0x18,0x25,0x25,0x18, // 210 0x00,0x18,0x25,0x24,0x18, // 211 0x00,0x18,0x25,0x25,0x18, // 212 0x00,0x18,0x25,0x25,0x18, // 213 0x00,0x19,0x24,0x24,0x19, // 214 0x00,0x14,0x1C,0x14, // 215 0x00,0x3C,0x34,0x2C,0x3C, // 216 0x00,0x3C,0x21,0x3D, // 217 0x00,0x3C,0x21,0x3C, // 218 0x00,0x3C,0x20,0x3C, // 219 0x00,0x3D,0x20,0x3D, // 220 0x04,0x0D,0x38,0x0C, // 221 0x00,0x3C,0x28,0x38, // 222 0x00,0x3E,0x0A,0x36, // 223 0x00,0x32,0x38,0x38, // 224 0x00,0x32,0x38,0x38, // 225 0x00,0x30,0x38,0x38, // 226 0x00,0x30,0x3A,0x38, // 227 0x00,0x32,0x38,0x3A, // 228 0x00,0x30,0x3B,0x3B, // 229 0x00,0x30,0x38,0x10,0x38,0x38, // 230 0x00,0x78,0x28, // 231 0x00,0x3A,0x38,0x38, // 232 0x00,0x3A,0x38,0x38, // 233 0x00,0x3A,0x3A,0x38, // 234 0x00,0x3A,0x38,0x3A, // 235 0x02,0x38, // 236 0x02,0x38, // 237 0x02,0x3A, // 238 0x02,0x38, // 239 0x00,0x38,0x2E,0x3C, // 240 0x02,0x3A,0x08,0x38, // 241 0x00,0x3A,0x28,0x38, // 242 0x00,0x3A,0x28,0x38, // 243 0x00,0x38,0x28,0x38, // 244 0x00,0x38,0x2A,0x38, // 245 0x00,0x3A,0x28,0x3A, // 246 0x00,0x08,0x08,0x1C,0x08, // 247 0x00,0x38,0x38,0x38, // 248 0x00,0x3A,0x20,0x38, // 249 0x00,0x3A,0x20,0x38, // 250 0x00,0x38,0x20,0x38, // 251 0x00,0x3A,0x20,0x3A, // 252 0x68,0x32,0x08, // 253 0x00,0x7E,0x28,0x38, // 254 0x68,0x32,0x0A // 255 }; ================================================ FILE: examples/SSD1306FontTryout/Dialog_plain_7.h ================================================ // Created by http://oleddisplay.squix.ch/ Consider a donation // In case of problems make sure that you are using the font file with the correct version! const char Dialog_plain_7[] PROGMEM = { 0x07, // Width: 7 0x09, // Height: 9 0x20, // First Char: 32 0xE0, // Numbers of Chars: 224 // Jump Table: 0xFF, 0xFF, 0x00, 0x02, // 32:65535 0x00, 0x00, 0x03, 0x03, // 33:0 0x00, 0x03, 0x03, 0x03, // 34:3 0x00, 0x06, 0x0B, 0x06, // 35:6 0x00, 0x11, 0x07, 0x04, // 36:17 0x00, 0x18, 0x0D, 0x07, // 37:24 0x00, 0x25, 0x09, 0x05, // 38:37 0x00, 0x2E, 0x03, 0x02, // 39:46 0x00, 0x31, 0x05, 0x03, // 40:49 0x00, 0x36, 0x05, 0x03, // 41:54 0x00, 0x3B, 0x07, 0x04, // 42:59 0x00, 0x42, 0x0B, 0x06, // 43:66 0x00, 0x4D, 0x03, 0x02, // 44:77 0x00, 0x50, 0x05, 0x03, // 45:80 0x00, 0x55, 0x03, 0x02, // 46:85 0x00, 0x58, 0x03, 0x02, // 47:88 0x00, 0x5B, 0x07, 0x04, // 48:91 0x00, 0x62, 0x07, 0x04, // 49:98 0x00, 0x69, 0x07, 0x04, // 50:105 0x00, 0x70, 0x07, 0x04, // 51:112 0x00, 0x77, 0x07, 0x04, // 52:119 0x00, 0x7E, 0x07, 0x04, // 53:126 0x00, 0x85, 0x07, 0x04, // 54:133 0x00, 0x8C, 0x07, 0x04, // 55:140 0x00, 0x93, 0x07, 0x04, // 56:147 0x00, 0x9A, 0x07, 0x04, // 57:154 0x00, 0xA1, 0x03, 0x02, // 58:161 0x00, 0xA4, 0x03, 0x02, // 59:164 0x00, 0xA7, 0x09, 0x06, // 60:167 0x00, 0xB0, 0x09, 0x06, // 61:176 0x00, 0xB9, 0x09, 0x06, // 62:185 0x00, 0xC2, 0x07, 0x04, // 63:194 0x00, 0xC9, 0x0D, 0x07, // 64:201 0x00, 0xD6, 0x09, 0x05, // 65:214 0x00, 0xDF, 0x09, 0x05, // 66:223 0x00, 0xE8, 0x09, 0x05, // 67:232 0x00, 0xF1, 0x09, 0x05, // 68:241 0x00, 0xFA, 0x07, 0x04, // 69:250 0x01, 0x01, 0x07, 0x04, // 70:257 0x01, 0x08, 0x09, 0x05, // 71:264 0x01, 0x11, 0x09, 0x05, // 72:273 0x01, 0x1A, 0x03, 0x02, // 73:282 0x01, 0x1D, 0x03, 0x02, // 74:285 0x01, 0x20, 0x09, 0x05, // 75:288 0x01, 0x29, 0x07, 0x04, // 76:297 0x01, 0x30, 0x0B, 0x06, // 77:304 0x01, 0x3B, 0x09, 0x05, // 78:315 0x01, 0x44, 0x09, 0x06, // 79:324 0x01, 0x4D, 0x07, 0x04, // 80:333 0x01, 0x54, 0x09, 0x06, // 81:340 0x01, 0x5D, 0x09, 0x05, // 82:349 0x01, 0x66, 0x07, 0x04, // 83:358 0x01, 0x6D, 0x07, 0x04, // 84:365 0x01, 0x74, 0x09, 0x05, // 85:372 0x01, 0x7D, 0x09, 0x05, // 86:381 0x01, 0x86, 0x0B, 0x07, // 87:390 0x01, 0x91, 0x07, 0x04, // 88:401 0x01, 0x98, 0x07, 0x04, // 89:408 0x01, 0x9F, 0x09, 0x05, // 90:415 0x01, 0xA8, 0x05, 0x03, // 91:424 0x01, 0xAD, 0x03, 0x02, // 92:429 0x01, 0xB0, 0x05, 0x03, // 93:432 0x01, 0xB5, 0x09, 0x06, // 94:437 0x01, 0xBE, 0x08, 0x04, // 95:446 0x01, 0xC6, 0x01, 0x04, // 96:454 0x01, 0xC7, 0x07, 0x04, // 97:455 0x01, 0xCE, 0x07, 0x04, // 98:462 0x01, 0xD5, 0x07, 0x04, // 99:469 0x01, 0xDC, 0x07, 0x04, // 100:476 0x01, 0xE3, 0x07, 0x04, // 101:483 0x01, 0xEA, 0x03, 0x02, // 102:490 0x01, 0xED, 0x07, 0x04, // 103:493 0x01, 0xF4, 0x07, 0x04, // 104:500 0x01, 0xFB, 0x03, 0x02, // 105:507 0x01, 0xFE, 0x03, 0x02, // 106:510 0x02, 0x01, 0x07, 0x04, // 107:513 0x02, 0x08, 0x03, 0x02, // 108:520 0x02, 0x0B, 0x0B, 0x07, // 109:523 0x02, 0x16, 0x07, 0x04, // 110:534 0x02, 0x1D, 0x07, 0x04, // 111:541 0x02, 0x24, 0x07, 0x04, // 112:548 0x02, 0x2B, 0x07, 0x04, // 113:555 0x02, 0x32, 0x05, 0x03, // 114:562 0x02, 0x37, 0x07, 0x04, // 115:567 0x02, 0x3E, 0x05, 0x03, // 116:574 0x02, 0x43, 0x07, 0x04, // 117:579 0x02, 0x4A, 0x07, 0x04, // 118:586 0x02, 0x51, 0x09, 0x06, // 119:593 0x02, 0x5A, 0x07, 0x04, // 120:602 0x02, 0x61, 0x07, 0x04, // 121:609 0x02, 0x68, 0x07, 0x04, // 122:616 0x02, 0x6F, 0x07, 0x04, // 123:623 0x02, 0x76, 0x04, 0x02, // 124:630 0x02, 0x7A, 0x07, 0x04, // 125:634 0x02, 0x81, 0x09, 0x06, // 126:641 0x02, 0x8A, 0x07, 0x04, // 127:650 0x02, 0x91, 0x07, 0x04, // 128:657 0x02, 0x98, 0x07, 0x04, // 129:664 0x02, 0x9F, 0x07, 0x04, // 130:671 0x02, 0xA6, 0x07, 0x04, // 131:678 0x02, 0xAD, 0x07, 0x04, // 132:685 0x02, 0xB4, 0x07, 0x04, // 133:692 0x02, 0xBB, 0x07, 0x04, // 134:699 0x02, 0xC2, 0x07, 0x04, // 135:706 0x02, 0xC9, 0x07, 0x04, // 136:713 0x02, 0xD0, 0x07, 0x04, // 137:720 0x02, 0xD7, 0x07, 0x04, // 138:727 0x02, 0xDE, 0x07, 0x04, // 139:734 0x02, 0xE5, 0x07, 0x04, // 140:741 0x02, 0xEC, 0x07, 0x04, // 141:748 0x02, 0xF3, 0x07, 0x04, // 142:755 0x02, 0xFA, 0x07, 0x04, // 143:762 0x03, 0x01, 0x07, 0x04, // 144:769 0x03, 0x08, 0x07, 0x04, // 145:776 0x03, 0x0F, 0x07, 0x04, // 146:783 0x03, 0x16, 0x07, 0x04, // 147:790 0x03, 0x1D, 0x07, 0x04, // 148:797 0x03, 0x24, 0x07, 0x04, // 149:804 0x03, 0x2B, 0x07, 0x04, // 150:811 0x03, 0x32, 0x07, 0x04, // 151:818 0x03, 0x39, 0x07, 0x04, // 152:825 0x03, 0x40, 0x07, 0x04, // 153:832 0x03, 0x47, 0x07, 0x04, // 154:839 0x03, 0x4E, 0x07, 0x04, // 155:846 0x03, 0x55, 0x07, 0x04, // 156:853 0x03, 0x5C, 0x07, 0x04, // 157:860 0x03, 0x63, 0x07, 0x04, // 158:867 0x03, 0x6A, 0x07, 0x04, // 159:874 0xFF, 0xFF, 0x00, 0x02, // 160:65535 0x03, 0x71, 0x03, 0x03, // 161:881 0x03, 0x74, 0x07, 0x04, // 162:884 0x03, 0x7B, 0x07, 0x04, // 163:891 0x03, 0x82, 0x07, 0x04, // 164:898 0x03, 0x89, 0x07, 0x04, // 165:905 0x03, 0x90, 0x04, 0x02, // 166:912 0x03, 0x94, 0x07, 0x04, // 167:916 0x03, 0x9B, 0x07, 0x04, // 168:923 0x03, 0xA2, 0x0B, 0x07, // 169:930 0x03, 0xAD, 0x05, 0x03, // 170:941 0x03, 0xB2, 0x07, 0x04, // 171:946 0x03, 0xB9, 0x09, 0x06, // 172:953 0x03, 0xC2, 0x05, 0x03, // 173:962 0x03, 0xC7, 0x0B, 0x07, // 174:967 0x03, 0xD2, 0x05, 0x04, // 175:978 0x03, 0xD7, 0x05, 0x04, // 176:983 0x03, 0xDC, 0x0B, 0x06, // 177:988 0x03, 0xE7, 0x05, 0x03, // 178:999 0x03, 0xEC, 0x05, 0x03, // 179:1004 0x03, 0xF1, 0x03, 0x04, // 180:1009 0x03, 0xF4, 0x07, 0x04, // 181:1012 0x03, 0xFB, 0x07, 0x04, // 182:1019 0x04, 0x02, 0x03, 0x02, // 183:1026 0x04, 0x05, 0x03, 0x04, // 184:1029 0x04, 0x08, 0x05, 0x03, // 185:1032 0x04, 0x0D, 0x05, 0x03, // 186:1037 0x04, 0x12, 0x07, 0x04, // 187:1042 0x04, 0x19, 0x0D, 0x07, // 188:1049 0x04, 0x26, 0x0D, 0x07, // 189:1062 0x04, 0x33, 0x0D, 0x07, // 190:1075 0x04, 0x40, 0x07, 0x04, // 191:1088 0x04, 0x47, 0x09, 0x05, // 192:1095 0x04, 0x50, 0x09, 0x05, // 193:1104 0x04, 0x59, 0x09, 0x05, // 194:1113 0x04, 0x62, 0x09, 0x05, // 195:1122 0x04, 0x6B, 0x09, 0x05, // 196:1131 0x04, 0x74, 0x09, 0x05, // 197:1140 0x04, 0x7D, 0x0B, 0x07, // 198:1149 0x04, 0x88, 0x09, 0x05, // 199:1160 0x04, 0x91, 0x07, 0x04, // 200:1169 0x04, 0x98, 0x07, 0x04, // 201:1176 0x04, 0x9F, 0x07, 0x04, // 202:1183 0x04, 0xA6, 0x07, 0x04, // 203:1190 0x04, 0xAD, 0x03, 0x02, // 204:1197 0x04, 0xB0, 0x03, 0x02, // 205:1200 0x04, 0xB3, 0x03, 0x02, // 206:1203 0x04, 0xB6, 0x03, 0x02, // 207:1206 0x04, 0xB9, 0x09, 0x05, // 208:1209 0x04, 0xC2, 0x09, 0x05, // 209:1218 0x04, 0xCB, 0x09, 0x06, // 210:1227 0x04, 0xD4, 0x09, 0x06, // 211:1236 0x04, 0xDD, 0x09, 0x06, // 212:1245 0x04, 0xE6, 0x09, 0x06, // 213:1254 0x04, 0xEF, 0x09, 0x06, // 214:1263 0x04, 0xF8, 0x09, 0x06, // 215:1272 0x05, 0x01, 0x09, 0x06, // 216:1281 0x05, 0x0A, 0x09, 0x05, // 217:1290 0x05, 0x13, 0x09, 0x05, // 218:1299 0x05, 0x1C, 0x09, 0x05, // 219:1308 0x05, 0x25, 0x09, 0x05, // 220:1317 0x05, 0x2E, 0x07, 0x04, // 221:1326 0x05, 0x35, 0x07, 0x04, // 222:1333 0x05, 0x3C, 0x07, 0x04, // 223:1340 0x05, 0x43, 0x07, 0x04, // 224:1347 0x05, 0x4A, 0x07, 0x04, // 225:1354 0x05, 0x51, 0x07, 0x04, // 226:1361 0x05, 0x58, 0x07, 0x04, // 227:1368 0x05, 0x5F, 0x07, 0x04, // 228:1375 0x05, 0x66, 0x07, 0x04, // 229:1382 0x05, 0x6D, 0x0B, 0x07, // 230:1389 0x05, 0x78, 0x07, 0x04, // 231:1400 0x05, 0x7F, 0x07, 0x04, // 232:1407 0x05, 0x86, 0x07, 0x04, // 233:1414 0x05, 0x8D, 0x07, 0x04, // 234:1421 0x05, 0x94, 0x07, 0x04, // 235:1428 0x05, 0x9B, 0x03, 0x02, // 236:1435 0x05, 0x9E, 0x03, 0x02, // 237:1438 0x05, 0xA1, 0x03, 0x02, // 238:1441 0x05, 0xA4, 0x03, 0x02, // 239:1444 0x05, 0xA7, 0x07, 0x04, // 240:1447 0x05, 0xAE, 0x07, 0x04, // 241:1454 0x05, 0xB5, 0x07, 0x04, // 242:1461 0x05, 0xBC, 0x07, 0x04, // 243:1468 0x05, 0xC3, 0x07, 0x04, // 244:1475 0x05, 0xCA, 0x07, 0x04, // 245:1482 0x05, 0xD1, 0x07, 0x04, // 246:1489 0x05, 0xD8, 0x0B, 0x06, // 247:1496 0x05, 0xE3, 0x07, 0x04, // 248:1507 0x05, 0xEA, 0x07, 0x04, // 249:1514 0x05, 0xF1, 0x07, 0x04, // 250:1521 0x05, 0xF8, 0x07, 0x04, // 251:1528 0x05, 0xFF, 0x07, 0x04, // 252:1535 0x06, 0x06, 0x07, 0x04, // 253:1542 0x06, 0x0D, 0x07, 0x04, // 254:1549 0x06, 0x14, 0x07, 0x04, // 255:1556 // Font Data: 0x00,0x00,0x5C, // 33 0x00,0x00,0x0C, // 34 0x00,0x00,0x28,0x00,0x7C,0x00,0x68,0x00,0x3C,0x00,0x28, // 35 0x00,0x00,0x5C,0x00,0xFE,0x00,0x74, // 36 0x00,0x00,0x1C,0x00,0x5C,0x00,0x30,0x00,0x18,0x00,0x74,0x00,0x70, // 37 0x00,0x00,0x30,0x00,0x5C,0x00,0x74,0x00,0x64, // 38 0x00,0x00,0x0C, // 39 0x00,0x00,0x3C,0x00,0x42, // 40 0x00,0x00,0x42,0x00,0x3C, // 41 0x00,0x00,0x28,0x00,0x3C,0x00,0x28, // 42 0x00,0x00,0x10,0x00,0x10,0x00,0x7C,0x00,0x10,0x00,0x10, // 43 0x00,0x00,0xC0, // 44 0x00,0x00,0x10,0x00,0x10, // 45 0x00,0x00,0x40, // 46 0xE0,0x00,0x1C, // 47 0x00,0x00,0x7C,0x00,0x44,0x00,0x7C, // 48 0x00,0x00,0x44,0x00,0x7C,0x00,0x40, // 49 0x00,0x00,0x44,0x00,0x64,0x00,0x5C, // 50 0x00,0x00,0x44,0x00,0x54,0x00,0x6C, // 51 0x00,0x00,0x20,0x00,0x38,0x00,0x7C, // 52 0x00,0x00,0x5C,0x00,0x54,0x00,0x74, // 53 0x00,0x00,0x78,0x00,0x54,0x00,0x74, // 54 0x00,0x00,0x04,0x00,0x64,0x00,0x1C, // 55 0x00,0x00,0x6C,0x00,0x54,0x00,0x6C, // 56 0x00,0x00,0x5C,0x00,0x54,0x00,0x3C, // 57 0x00,0x00,0x48, // 58 0x00,0x00,0xC8, // 59 0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x48, // 60 0x00,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28, // 61 0x00,0x00,0x48,0x00,0x30,0x00,0x30,0x00,0x30, // 62 0x00,0x00,0x04,0x00,0x54,0x00,0x0C, // 63 0x00,0x00,0x78,0x00,0xCC,0x00,0xB4,0x00,0xB4,0x00,0x24,0x00,0x18, // 64 0x40,0x00,0x38,0x00,0x2C,0x00,0x38,0x00,0x40, // 65 0x00,0x00,0x7C,0x00,0x54,0x00,0x54,0x00,0x6C, // 66 0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x44, // 67 0x00,0x00,0x7C,0x00,0x44,0x00,0x44,0x00,0x38, // 68 0x00,0x00,0x7C,0x00,0x54,0x00,0x54, // 69 0x00,0x00,0x7C,0x00,0x14,0x00,0x14, // 70 0x00,0x00,0x38,0x00,0x44,0x00,0x54,0x00,0x74, // 71 0x00,0x00,0x7C,0x00,0x10,0x00,0x10,0x00,0x7C, // 72 0x00,0x00,0x7C, // 73 0x80,0x00,0xFC, // 74 0x00,0x00,0x7C,0x00,0x38,0x00,0x64,0x00,0x40, // 75 0x00,0x00,0x7C,0x00,0x40,0x00,0x40, // 76 0x00,0x00,0x7C,0x00,0x0C,0x00,0x30,0x00,0x0C,0x00,0x7C, // 77 0x00,0x00,0x7C,0x00,0x1C,0x00,0x30,0x00,0x7C, // 78 0x00,0x00,0x38,0x00,0x44,0x00,0x44,0x00,0x38, // 79 0x00,0x00,0x7C,0x00,0x14,0x00,0x1C, // 80 0x00,0x00,0x38,0x00,0x44,0x00,0xC4,0x00,0x38, // 81 0x00,0x00,0x7C,0x00,0x14,0x00,0x6C,0x00,0x40, // 82 0x00,0x00,0x4C,0x00,0x54,0x00,0x54, // 83 0x04,0x00,0x04,0x00,0x7C,0x00,0x04, // 84 0x00,0x00,0x3C,0x00,0x40,0x00,0x40,0x00,0x3C, // 85 0x04,0x00,0x38,0x00,0x60,0x00,0x38,0x00,0x04, // 86 0x0C,0x00,0x70,0x00,0x1C,0x00,0x1C,0x00,0x70,0x00,0x0C, // 87 0x44,0x00,0x38,0x00,0x38,0x00,0x44, // 88 0x04,0x00,0x0C,0x00,0x70,0x00,0x0C, // 89 0x00,0x00,0x44,0x00,0x74,0x00,0x5C,0x00,0x44, // 90 0x00,0x00,0xFC,0x00,0x84, // 91 0x1C,0x00,0xE0, // 92 0x00,0x00,0x84,0x00,0xFC, // 93 0x00,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x08, // 94 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, // 95 0x02, // 96 0x00,0x00,0x60,0x00,0x68,0x00,0x78, // 97 0x00,0x00,0x7E,0x00,0x48,0x00,0x78, // 98 0x00,0x00,0x30,0x00,0x48,0x00,0x48, // 99 0x00,0x00,0x78,0x00,0x48,0x00,0x7E, // 100 0x00,0x00,0x78,0x00,0x58,0x00,0x58, // 101 0x08,0x00,0x7E, // 102 0x00,0x00,0xF8,0x00,0xC8,0x00,0xF8, // 103 0x00,0x00,0x7E,0x00,0x08,0x00,0x78, // 104 0x00,0x00,0x7C, // 105 0x80,0x00,0xFC, // 106 0x00,0x00,0x7E,0x00,0x78,0x00,0x48, // 107 0x00,0x00,0x7E, // 108 0x00,0x00,0x78,0x00,0x08,0x00,0x78,0x00,0x08,0x00,0x78, // 109 0x00,0x00,0x78,0x00,0x08,0x00,0x78, // 110 0x00,0x00,0x78,0x00,0x48,0x00,0x78, // 111 0x00,0x00,0xF8,0x00,0x48,0x00,0x78, // 112 0x00,0x00,0x78,0x00,0x48,0x00,0xF8, // 113 0x00,0x00,0x78,0x00,0x08, // 114 0x00,0x00,0x58,0x00,0x58,0x00,0x68, // 115 0x00,0x00,0x7C,0x00,0x48, // 116 0x00,0x00,0x78,0x00,0x40,0x00,0x78, // 117 0x08,0x00,0x70,0x00,0x70,0x00,0x08, // 118 0x18,0x00,0x70,0x00,0x08,0x00,0x70,0x00,0x18, // 119 0x48,0x00,0x78,0x00,0x78,0x00,0x48, // 120 0x88,0x00,0xF0,0x00,0x30,0x00,0x08, // 121 0x00,0x00,0x48,0x00,0x78,0x00,0x58, // 122 0x00,0x00,0x10,0x00,0xEC,0x00,0x84, // 123 0x00,0x00,0xFC,0x01, // 124 0x00,0x00,0x84,0x00,0xEC,0x00,0x10, // 125 0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10, // 126 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 127 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 128 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 129 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 130 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 131 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 132 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 133 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 134 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 135 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 136 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 137 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 138 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 139 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 140 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 141 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 142 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 143 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 144 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 145 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 146 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 147 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 148 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 149 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 150 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 151 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 152 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 153 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 154 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 155 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 156 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 157 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 158 0xFC,0x00,0x84,0x00,0x84,0x00,0xFC, // 159 0x00,0x00,0xE8, // 161 0x00,0x00,0x78,0x00,0xFC,0x00,0x48, // 162 0x50,0x00,0x7C,0x00,0x54,0x00,0x44, // 163 0x00,0x00,0x38,0x00,0x28,0x00,0x38, // 164 0x00,0x00,0x2C,0x00,0x70,0x00,0x2C, // 165 0x00,0x00,0xDC,0x01, // 166 0x00,0x00,0xBC,0x00,0xB4,0x00,0xF4, // 167 0x00,0x00,0x04,0x00,0x00,0x00,0x04, // 168 0x00,0x00,0x38,0x00,0x44,0x00,0x54,0x00,0x44,0x00,0x38, // 169 0x00,0x00,0x58,0x00,0x5C, // 170 0x00,0x00,0x10,0x00,0x38,0x00,0x10, // 171 0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x30, // 172 0x00,0x00,0x10,0x00,0x10, // 173 0x00,0x00,0x38,0x00,0x44,0x00,0x74,0x00,0x44,0x00,0x38, // 174 0x00,0x00,0x04,0x00,0x04, // 175 0x00,0x00,0x0C,0x00,0x0C, // 176 0x00,0x00,0x50,0x00,0x50,0x00,0x78,0x00,0x50,0x00,0x50, // 177 0x00,0x00,0x14,0x00,0x1C, // 178 0x00,0x00,0x1C,0x00,0x14, // 179 0x00,0x00,0x02, // 180 0x00,0x00,0xF8,0x00,0x40,0x00,0x78, // 181 0x00,0x00,0xFC,0x00,0x04,0x00,0xFC, // 182 0x00,0x00,0x10, // 183 0x00,0x00,0x80, // 184 0x00,0x00,0x14,0x00,0x1C, // 185 0x00,0x00,0x5C,0x00,0x54, // 186 0x00,0x00,0x38,0x00,0x10,0x00,0x38, // 187 0x00,0x00,0x14,0x00,0x5C,0x00,0x30,0x00,0x18,0x00,0x64,0x00,0x70, // 188 0x00,0x00,0x14,0x00,0x5C,0x00,0x30,0x00,0x18,0x00,0x54,0x00,0x70, // 189 0x00,0x00,0x1C,0x00,0x54,0x00,0x30,0x00,0x18,0x00,0x64,0x00,0x70, // 190 0x00,0x00,0xC0,0x00,0xA8,0x00,0x80, // 191 0x40,0x00,0x3A,0x00,0x2E,0x00,0x38,0x00,0x40, // 192 0x40,0x00,0x38,0x00,0x2E,0x00,0x3A,0x00,0x40, // 193 0x40,0x00,0x38,0x00,0x2C,0x00,0x38,0x00,0x40, // 194 0x40,0x00,0x38,0x00,0x2E,0x00,0x38,0x00,0x40, // 195 0x40,0x00,0x3A,0x00,0x2C,0x00,0x3A,0x00,0x40, // 196 0x40,0x00,0x3A,0x00,0x2E,0x00,0x3A,0x00,0x40, // 197 0x40,0x00,0x38,0x00,0x2C,0x00,0x7C,0x00,0x54,0x00,0x54, // 198 0x00,0x00,0x38,0x00,0xC4,0x00,0x44,0x00,0x44, // 199 0x00,0x00,0x7E,0x00,0x56,0x00,0x54, // 200 0x00,0x00,0x7C,0x00,0x56,0x00,0x56, // 201 0x00,0x00,0x7E,0x00,0x56,0x00,0x54, // 202 0x00,0x00,0x7E,0x00,0x54,0x00,0x56, // 203 0x02,0x00,0x7E, // 204 0x00,0x00,0x7E, // 205 0x02,0x00,0x7E, // 206 0x02,0x00,0x7C, // 207 0x10,0x00,0x7C,0x00,0x54,0x00,0x44,0x00,0x38, // 208 0x00,0x00,0x7C,0x00,0x1E,0x00,0x32,0x00,0x7C, // 209 0x00,0x00,0x38,0x00,0x46,0x00,0x46,0x00,0x38, // 210 0x00,0x00,0x38,0x00,0x44,0x00,0x46,0x00,0x3A, // 211 0x00,0x00,0x38,0x00,0x46,0x00,0x46,0x00,0x38, // 212 0x00,0x00,0x38,0x00,0x46,0x00,0x46,0x00,0x38, // 213 0x00,0x00,0x3A,0x00,0x44,0x00,0x44,0x00,0x3A, // 214 0x00,0x00,0x48,0x00,0x30,0x00,0x30,0x00,0x48, // 215 0x00,0x00,0x78,0x00,0x54,0x00,0x54,0x00,0x3C, // 216 0x00,0x00,0x3E,0x00,0x42,0x00,0x40,0x00,0x3C, // 217 0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x3C, // 218 0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x3C, // 219 0x00,0x00,0x3E,0x00,0x40,0x00,0x40,0x00,0x3E, // 220 0x04,0x00,0x0C,0x00,0x72,0x00,0x0E, // 221 0x00,0x00,0x7C,0x00,0x28,0x00,0x38, // 222 0x00,0x00,0x7E,0x00,0x1A,0x00,0x66, // 223 0x02,0x00,0x60,0x00,0x68,0x00,0x78, // 224 0x00,0x00,0x62,0x00,0x68,0x00,0x78, // 225 0x00,0x00,0x60,0x00,0x68,0x00,0x78, // 226 0x00,0x00,0x6C,0x00,0x6C,0x00,0x7C, // 227 0x00,0x00,0x64,0x00,0x68,0x00,0x7C, // 228 0x00,0x00,0x60,0x00,0x6E,0x00,0x7E, // 229 0x00,0x00,0x60,0x00,0x68,0x00,0x30,0x00,0x58,0x00,0x58, // 230 0x00,0x00,0xB0,0x00,0x48,0x00,0x48, // 231 0x02,0x00,0x78,0x00,0x58,0x00,0x58, // 232 0x00,0x00,0x7A,0x00,0x58,0x00,0x58, // 233 0x00,0x00,0x7A,0x00,0x5A,0x00,0x58, // 234 0x00,0x00,0x7C,0x00,0x58,0x00,0x5C, // 235 0x00,0x00,0x78, // 236 0x02,0x00,0x78, // 237 0x02,0x00,0x7A, // 238 0x04,0x00,0x78, // 239 0x00,0x00,0x78,0x00,0x4C,0x00,0x78, // 240 0x00,0x00,0x7C,0x00,0x0C,0x00,0x7C, // 241 0x02,0x00,0x78,0x00,0x48,0x00,0x78, // 242 0x00,0x00,0x7A,0x00,0x48,0x00,0x78, // 243 0x00,0x00,0x78,0x00,0x48,0x00,0x78, // 244 0x00,0x00,0x7C,0x00,0x4C,0x00,0x7C, // 245 0x00,0x00,0x7C,0x00,0x48,0x00,0x7C, // 246 0x00,0x00,0x10,0x00,0x10,0x00,0x54,0x00,0x10,0x00,0x10, // 247 0x00,0x00,0x78,0x00,0x68,0x00,0x78, // 248 0x02,0x00,0x78,0x00,0x40,0x00,0x78, // 249 0x00,0x00,0x7A,0x00,0x40,0x00,0x78, // 250 0x00,0x00,0x78,0x00,0x40,0x00,0x78, // 251 0x00,0x00,0x7C,0x00,0x40,0x00,0x7C, // 252 0x88,0x00,0xF2,0x00,0x30,0x00,0x08, // 253 0x00,0x00,0xFE,0x00,0x48,0x00,0x78, // 254 0x88,0x00,0xF4,0x00,0x34,0x00,0x08 // 255 }; ================================================ FILE: examples/SSD1306FontTryout/Dialog_plain_8.h ================================================ // Created by http://oleddisplay.squix.ch/ Consider a donation // In case of problems make sure that you are using the font file with the correct version! const char Dialog_plain_8[] PROGMEM = { 0x08, // Width: 8 0x0A, // Height: 10 0x20, // First Char: 32 0xE0, // Numbers of Chars: 224 // Jump Table: 0xFF, 0xFF, 0x00, 0x03, // 32:65535 0x00, 0x00, 0x03, 0x03, // 33:0 0x00, 0x03, 0x07, 0x04, // 34:3 0x00, 0x0A, 0x0B, 0x07, // 35:10 0x00, 0x15, 0x09, 0x05, // 36:21 0x00, 0x1E, 0x0F, 0x08, // 37:30 0x00, 0x2D, 0x0B, 0x06, // 38:45 0x00, 0x38, 0x03, 0x02, // 39:56 0x00, 0x3B, 0x05, 0x03, // 40:59 0x00, 0x40, 0x05, 0x03, // 41:64 0x00, 0x45, 0x07, 0x04, // 42:69 0x00, 0x4C, 0x0B, 0x07, // 43:76 0x00, 0x57, 0x04, 0x03, // 44:87 0x00, 0x5B, 0x05, 0x03, // 45:91 0x00, 0x60, 0x03, 0x03, // 46:96 0x00, 0x63, 0x05, 0x03, // 47:99 0x00, 0x68, 0x09, 0x05, // 48:104 0x00, 0x71, 0x07, 0x05, // 49:113 0x00, 0x78, 0x09, 0x05, // 50:120 0x00, 0x81, 0x09, 0x05, // 51:129 0x00, 0x8A, 0x09, 0x05, // 52:138 0x00, 0x93, 0x09, 0x05, // 53:147 0x00, 0x9C, 0x09, 0x05, // 54:156 0x00, 0xA5, 0x09, 0x05, // 55:165 0x00, 0xAE, 0x09, 0x05, // 56:174 0x00, 0xB7, 0x09, 0x05, // 57:183 0x00, 0xC0, 0x03, 0x03, // 58:192 0x00, 0xC3, 0x04, 0x03, // 59:195 0x00, 0xC7, 0x0B, 0x07, // 60:199 0x00, 0xD2, 0x0B, 0x07, // 61:210 0x00, 0xDD, 0x0B, 0x07, // 62:221 0x00, 0xE8, 0x07, 0x04, // 63:232 0x00, 0xEF, 0x0F, 0x08, // 64:239 0x00, 0xFE, 0x09, 0x05, // 65:254 0x01, 0x07, 0x09, 0x05, // 66:263 0x01, 0x10, 0x0B, 0x06, // 67:272 0x01, 0x1B, 0x0B, 0x06, // 68:283 0x01, 0x26, 0x09, 0x05, // 69:294 0x01, 0x2F, 0x07, 0x05, // 70:303 0x01, 0x36, 0x0B, 0x06, // 71:310 0x01, 0x41, 0x09, 0x06, // 72:321 0x01, 0x4A, 0x03, 0x02, // 73:330 0x01, 0x4D, 0x04, 0x02, // 74:333 0x01, 0x51, 0x09, 0x05, // 75:337 0x01, 0x5A, 0x07, 0x04, // 76:346 0x01, 0x61, 0x0B, 0x07, // 77:353 0x01, 0x6C, 0x09, 0x06, // 78:364 0x01, 0x75, 0x0B, 0x06, // 79:373 0x01, 0x80, 0x09, 0x05, // 80:384 0x01, 0x89, 0x0B, 0x06, // 81:393 0x01, 0x94, 0x0B, 0x06, // 82:404 0x01, 0x9F, 0x09, 0x05, // 83:415 0x01, 0xA8, 0x09, 0x05, // 84:424 0x01, 0xB1, 0x09, 0x06, // 85:433 0x01, 0xBA, 0x09, 0x05, // 86:442 0x01, 0xC3, 0x0D, 0x08, // 87:451 0x01, 0xD0, 0x09, 0x05, // 88:464 0x01, 0xD9, 0x09, 0x05, // 89:473 0x01, 0xE2, 0x09, 0x05, // 90:482 0x01, 0xEB, 0x06, 0x03, // 91:491 0x01, 0xF1, 0x06, 0x03, // 92:497 0x01, 0xF7, 0x06, 0x03, // 93:503 0x01, 0xFD, 0x09, 0x07, // 94:509 0x02, 0x06, 0x08, 0x04, // 95:518 0x02, 0x0E, 0x03, 0x04, // 96:526 0x02, 0x11, 0x09, 0x05, // 97:529 0x02, 0x1A, 0x09, 0x05, // 98:538 0x02, 0x23, 0x07, 0x04, // 99:547 0x02, 0x2A, 0x09, 0x05, // 100:554 0x02, 0x33, 0x09, 0x05, // 101:563 0x02, 0x3C, 0x05, 0x03, // 102:572 0x02, 0x41, 0x0A, 0x05, // 103:577 0x02, 0x4B, 0x09, 0x05, // 104:587 0x02, 0x54, 0x03, 0x02, // 105:596 0x02, 0x57, 0x04, 0x02, // 106:599 0x02, 0x5B, 0x07, 0x05, // 107:603 0x02, 0x62, 0x03, 0x02, // 108:610 0x02, 0x65, 0x0F, 0x08, // 109:613 0x02, 0x74, 0x09, 0x05, // 110:628 0x02, 0x7D, 0x09, 0x05, // 111:637 0x02, 0x86, 0x09, 0x05, // 112:646 0x02, 0x8F, 0x0A, 0x05, // 113:655 0x02, 0x99, 0x05, 0x03, // 114:665 0x02, 0x9E, 0x07, 0x04, // 115:670 0x02, 0xA5, 0x05, 0x03, // 116:677 0x02, 0xAA, 0x09, 0x05, // 117:682 0x02, 0xB3, 0x07, 0x05, // 118:691 0x02, 0xBA, 0x0B, 0x07, // 119:698 0x02, 0xC5, 0x07, 0x05, // 120:709 0x02, 0xCC, 0x09, 0x05, // 121:716 0x02, 0xD5, 0x07, 0x04, // 122:725 0x02, 0xDC, 0x08, 0x05, // 123:732 0x02, 0xE4, 0x04, 0x03, // 124:740 0x02, 0xE8, 0x07, 0x05, // 125:744 0x02, 0xEF, 0x0B, 0x07, // 126:751 0x02, 0xFA, 0x08, 0x05, // 127:762 0x03, 0x02, 0x08, 0x05, // 128:770 0x03, 0x0A, 0x08, 0x05, // 129:778 0x03, 0x12, 0x08, 0x05, // 130:786 0x03, 0x1A, 0x08, 0x05, // 131:794 0x03, 0x22, 0x08, 0x05, // 132:802 0x03, 0x2A, 0x08, 0x05, // 133:810 0x03, 0x32, 0x08, 0x05, // 134:818 0x03, 0x3A, 0x08, 0x05, // 135:826 0x03, 0x42, 0x08, 0x05, // 136:834 0x03, 0x4A, 0x08, 0x05, // 137:842 0x03, 0x52, 0x08, 0x05, // 138:850 0x03, 0x5A, 0x08, 0x05, // 139:858 0x03, 0x62, 0x08, 0x05, // 140:866 0x03, 0x6A, 0x08, 0x05, // 141:874 0x03, 0x72, 0x08, 0x05, // 142:882 0x03, 0x7A, 0x08, 0x05, // 143:890 0x03, 0x82, 0x08, 0x05, // 144:898 0x03, 0x8A, 0x08, 0x05, // 145:906 0x03, 0x92, 0x08, 0x05, // 146:914 0x03, 0x9A, 0x08, 0x05, // 147:922 0x03, 0xA2, 0x08, 0x05, // 148:930 0x03, 0xAA, 0x08, 0x05, // 149:938 0x03, 0xB2, 0x08, 0x05, // 150:946 0x03, 0xBA, 0x08, 0x05, // 151:954 0x03, 0xC2, 0x08, 0x05, // 152:962 0x03, 0xCA, 0x08, 0x05, // 153:970 0x03, 0xD2, 0x08, 0x05, // 154:978 0x03, 0xDA, 0x08, 0x05, // 155:986 0x03, 0xE2, 0x08, 0x05, // 156:994 0x03, 0xEA, 0x08, 0x05, // 157:1002 0x03, 0xF2, 0x08, 0x05, // 158:1010 0x03, 0xFA, 0x08, 0x05, // 159:1018 0xFF, 0xFF, 0x00, 0x03, // 160:65535 0x04, 0x02, 0x04, 0x03, // 161:1026 0x04, 0x06, 0x07, 0x05, // 162:1030 0x04, 0x0D, 0x07, 0x05, // 163:1037 0x04, 0x14, 0x09, 0x05, // 164:1044 0x04, 0x1D, 0x09, 0x05, // 165:1053 0x04, 0x26, 0x04, 0x03, // 166:1062 0x04, 0x2A, 0x08, 0x04, // 167:1066 0x04, 0x32, 0x07, 0x04, // 168:1074 0x04, 0x39, 0x0D, 0x08, // 169:1081 0x04, 0x46, 0x07, 0x04, // 170:1094 0x04, 0x4D, 0x09, 0x05, // 171:1101 0x04, 0x56, 0x0B, 0x07, // 172:1110 0x04, 0x61, 0x05, 0x03, // 173:1121 0x04, 0x66, 0x0D, 0x08, // 174:1126 0x04, 0x73, 0x05, 0x04, // 175:1139 0x04, 0x78, 0x05, 0x04, // 176:1144 0x04, 0x7D, 0x0B, 0x07, // 177:1149 0x04, 0x88, 0x05, 0x03, // 178:1160 0x04, 0x8D, 0x05, 0x03, // 179:1165 0x04, 0x92, 0x03, 0x04, // 180:1170 0x04, 0x95, 0x09, 0x05, // 181:1173 0x04, 0x9E, 0x0A, 0x05, // 182:1182 0x04, 0xA8, 0x03, 0x03, // 183:1192 0x04, 0xAB, 0x06, 0x04, // 184:1195 0x04, 0xB1, 0x05, 0x03, // 185:1201 0x04, 0xB6, 0x07, 0x04, // 186:1206 0x04, 0xBD, 0x09, 0x05, // 187:1213 0x04, 0xC6, 0x0F, 0x08, // 188:1222 0x04, 0xD5, 0x0F, 0x08, // 189:1237 0x04, 0xE4, 0x0F, 0x08, // 190:1252 0x04, 0xF3, 0x08, 0x04, // 191:1267 0x04, 0xFB, 0x09, 0x05, // 192:1275 0x05, 0x04, 0x09, 0x05, // 193:1284 0x05, 0x0D, 0x09, 0x05, // 194:1293 0x05, 0x16, 0x09, 0x05, // 195:1302 0x05, 0x1F, 0x09, 0x05, // 196:1311 0x05, 0x28, 0x09, 0x05, // 197:1320 0x05, 0x31, 0x0D, 0x08, // 198:1329 0x05, 0x3E, 0x0B, 0x06, // 199:1342 0x05, 0x49, 0x09, 0x05, // 200:1353 0x05, 0x52, 0x09, 0x05, // 201:1362 0x05, 0x5B, 0x09, 0x05, // 202:1371 0x05, 0x64, 0x09, 0x05, // 203:1380 0x05, 0x6D, 0x03, 0x02, // 204:1389 0x05, 0x70, 0x03, 0x02, // 205:1392 0x05, 0x73, 0x03, 0x02, // 206:1395 0x05, 0x76, 0x03, 0x02, // 207:1398 0x05, 0x79, 0x0B, 0x06, // 208:1401 0x05, 0x84, 0x09, 0x06, // 209:1412 0x05, 0x8D, 0x0B, 0x06, // 210:1421 0x05, 0x98, 0x0B, 0x06, // 211:1432 0x05, 0xA3, 0x0B, 0x06, // 212:1443 0x05, 0xAE, 0x0B, 0x06, // 213:1454 0x05, 0xB9, 0x0B, 0x06, // 214:1465 0x05, 0xC4, 0x0B, 0x07, // 215:1476 0x05, 0xCF, 0x0B, 0x06, // 216:1487 0x05, 0xDA, 0x09, 0x06, // 217:1498 0x05, 0xE3, 0x09, 0x06, // 218:1507 0x05, 0xEC, 0x09, 0x06, // 219:1516 0x05, 0xF5, 0x09, 0x06, // 220:1525 0x05, 0xFE, 0x09, 0x05, // 221:1534 0x06, 0x07, 0x09, 0x05, // 222:1543 0x06, 0x10, 0x09, 0x05, // 223:1552 0x06, 0x19, 0x09, 0x05, // 224:1561 0x06, 0x22, 0x09, 0x05, // 225:1570 0x06, 0x2B, 0x09, 0x05, // 226:1579 0x06, 0x34, 0x09, 0x05, // 227:1588 0x06, 0x3D, 0x09, 0x05, // 228:1597 0x06, 0x46, 0x09, 0x05, // 229:1606 0x06, 0x4F, 0x0F, 0x08, // 230:1615 0x06, 0x5E, 0x08, 0x04, // 231:1630 0x06, 0x66, 0x09, 0x05, // 232:1638 0x06, 0x6F, 0x09, 0x05, // 233:1647 0x06, 0x78, 0x09, 0x05, // 234:1656 0x06, 0x81, 0x09, 0x05, // 235:1665 0x06, 0x8A, 0x03, 0x02, // 236:1674 0x06, 0x8D, 0x03, 0x02, // 237:1677 0x06, 0x90, 0x03, 0x02, // 238:1680 0x06, 0x93, 0x03, 0x02, // 239:1683 0x06, 0x96, 0x09, 0x05, // 240:1686 0x06, 0x9F, 0x09, 0x05, // 241:1695 0x06, 0xA8, 0x09, 0x05, // 242:1704 0x06, 0xB1, 0x09, 0x05, // 243:1713 0x06, 0xBA, 0x09, 0x05, // 244:1722 0x06, 0xC3, 0x09, 0x05, // 245:1731 0x06, 0xCC, 0x09, 0x05, // 246:1740 0x06, 0xD5, 0x0B, 0x07, // 247:1749 0x06, 0xE0, 0x09, 0x05, // 248:1760 0x06, 0xE9, 0x09, 0x05, // 249:1769 0x06, 0xF2, 0x09, 0x05, // 250:1778 0x06, 0xFB, 0x09, 0x05, // 251:1787 0x07, 0x04, 0x09, 0x05, // 252:1796 0x07, 0x0D, 0x09, 0x05, // 253:1805 0x07, 0x16, 0x09, 0x05, // 254:1814 0x07, 0x1F, 0x09, 0x05, // 255:1823 // Font Data: 0x00,0x00,0xBC, // 33 0x00,0x00,0x0C,0x00,0x00,0x00,0x0C, // 34 0x00,0x00,0xA8,0x00,0x7C,0x00,0xEA,0x00,0x3E,0x00,0x28, // 35 0x00,0x00,0x98,0x00,0xA8,0x00,0xFC,0x01,0xA8, // 36 0x00,0x00,0x1C,0x00,0x14,0x00,0xDC,0x00,0x30,0x00,0xEC,0x00,0xA0,0x00,0xE0, // 37 0x00,0x00,0x60,0x00,0xBC,0x00,0xF4,0x00,0xC4,0x00,0xA0, // 38 0x00,0x00,0x0C, // 39 0x00,0x00,0x7C,0x00,0x82, // 40 0x00,0x00,0x82,0x00,0x7C, // 41 0x24,0x00,0x18,0x00,0x3C,0x00,0x18, // 42 0x00,0x00,0x20,0x00,0x20,0x00,0xF8,0x00,0x20,0x00,0x20, // 43 0x00,0x00,0x80,0x01, // 44 0x00,0x00,0x20,0x00,0x20, // 45 0x00,0x00,0x80, // 46 0x80,0x01,0x70,0x00,0x0C, // 47 0x00,0x00,0x78,0x00,0x84,0x00,0x84,0x00,0x78, // 48 0x00,0x00,0x84,0x00,0xFC,0x00,0x80, // 49 0x00,0x00,0x84,0x00,0xC4,0x00,0xA4,0x00,0x98, // 50 0x00,0x00,0x84,0x00,0xA4,0x00,0xA4,0x00,0xD8, // 51 0x00,0x00,0x60,0x00,0x58,0x00,0xFC,0x00,0x40, // 52 0x00,0x00,0x9C,0x00,0x94,0x00,0x94,0x00,0x64, // 53 0x00,0x00,0x78,0x00,0xAC,0x00,0xA4,0x00,0xE4, // 54 0x00,0x00,0x04,0x00,0x84,0x00,0x74,0x00,0x0C, // 55 0x00,0x00,0xD8,0x00,0xA4,0x00,0xA4,0x00,0xD8, // 56 0x00,0x00,0x9C,0x00,0x94,0x00,0xD4,0x00,0x78, // 57 0x00,0x00,0x90, // 58 0x00,0x00,0x90,0x01, // 59 0x00,0x00,0x20,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x48, // 60 0x00,0x00,0x50,0x00,0x50,0x00,0x50,0x00,0x50,0x00,0x50, // 61 0x00,0x00,0x48,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x20, // 62 0x00,0x00,0x04,0x00,0xB4,0x00,0x0C, // 63 0x00,0x00,0x70,0x00,0x88,0x00,0x74,0x01,0x54,0x01,0x74,0x01,0x4C,0x00,0x38, // 64 0x80,0x00,0x70,0x00,0x4C,0x00,0x70,0x00,0x80, // 65 0x00,0x00,0xFC,0x00,0xA4,0x00,0xA4,0x00,0xDC, // 66 0x00,0x00,0x78,0x00,0xCC,0x00,0x84,0x00,0x84,0x00,0x88, // 67 0x00,0x00,0xFC,0x00,0x84,0x00,0x84,0x00,0x84,0x00,0x78, // 68 0x00,0x00,0xFC,0x00,0xA4,0x00,0xA4,0x00,0xA4, // 69 0x00,0x00,0xFC,0x00,0x24,0x00,0x24, // 70 0x00,0x00,0x78,0x00,0x8C,0x00,0x84,0x00,0x94,0x00,0x78, // 71 0x00,0x00,0xFC,0x00,0x20,0x00,0x20,0x00,0xFC, // 72 0x00,0x00,0xFC, // 73 0x00,0x02,0xFC,0x03, // 74 0x00,0x00,0xFC,0x00,0x30,0x00,0x68,0x00,0xC4, // 75 0x00,0x00,0xFC,0x00,0x80,0x00,0x80, // 76 0x00,0x00,0xFC,0x00,0x1C,0x00,0x70,0x00,0x1C,0x00,0xFC, // 77 0x00,0x00,0xFC,0x00,0x18,0x00,0x60,0x00,0xFC, // 78 0x00,0x00,0x78,0x00,0x84,0x00,0x84,0x00,0x84,0x00,0x78, // 79 0x00,0x00,0xFC,0x00,0x14,0x00,0x14,0x00,0x1C, // 80 0x00,0x00,0x78,0x00,0x84,0x00,0x84,0x00,0x84,0x01,0x78, // 81 0x00,0x00,0xFC,0x00,0x14,0x00,0x34,0x00,0x6C,0x00,0x80, // 82 0x00,0x00,0x98,0x00,0x94,0x00,0xB4,0x00,0xE4, // 83 0x04,0x00,0x04,0x00,0xFC,0x00,0x04,0x00,0x04, // 84 0x00,0x00,0x7C,0x00,0x80,0x00,0x80,0x00,0x7C, // 85 0x04,0x00,0x38,0x00,0xC0,0x00,0x38,0x00,0x04, // 86 0x0C,0x00,0xF0,0x00,0x78,0x00,0x04,0x00,0x78,0x00,0xF0,0x00,0x0C, // 87 0x84,0x00,0x4C,0x00,0x30,0x00,0x4C,0x00,0x84, // 88 0x04,0x00,0x0C,0x00,0xF0,0x00,0x0C,0x00,0x04, // 89 0x00,0x00,0x84,0x00,0xE4,0x00,0xB4,0x00,0x8C, // 90 0x00,0x00,0xFC,0x01,0x04,0x01, // 91 0x0C,0x00,0x70,0x00,0x80,0x01, // 92 0x00,0x00,0x04,0x01,0xFC,0x01, // 93 0x00,0x00,0x08,0x00,0x08,0x00,0x04,0x00,0x08, // 94 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, // 95 0x00,0x00,0x04, // 96 0x00,0x00,0xE0,0x00,0xB0,0x00,0xB0,0x00,0xF0, // 97 0x00,0x00,0xFE,0x00,0x90,0x00,0x90,0x00,0x60, // 98 0x00,0x00,0x60,0x00,0x90,0x00,0x90, // 99 0x00,0x00,0x60,0x00,0x90,0x00,0x90,0x00,0xFE, // 100 0x00,0x00,0x60,0x00,0xB0,0x00,0xB0,0x00,0xB0, // 101 0x10,0x00,0xFE,0x00,0x12, // 102 0x00,0x00,0x60,0x00,0x90,0x02,0x90,0x02,0xF0,0x01, // 103 0x00,0x00,0xFE,0x00,0x10,0x00,0x10,0x00,0xF0, // 104 0x00,0x00,0xF4, // 105 0x00,0x02,0xF4,0x03, // 106 0x00,0x00,0xFE,0x00,0x60,0x00,0x90, // 107 0x00,0x00,0xFE, // 108 0x00,0x00,0xF0,0x00,0x10,0x00,0x10,0x00,0xF0,0x00,0x10,0x00,0x10,0x00,0xF0, // 109 0x00,0x00,0xF0,0x00,0x10,0x00,0x10,0x00,0xF0, // 110 0x00,0x00,0x60,0x00,0x90,0x00,0x90,0x00,0x60, // 111 0x00,0x00,0xF0,0x03,0x90,0x00,0x90,0x00,0x60, // 112 0x00,0x00,0x60,0x00,0x90,0x00,0x90,0x00,0xF0,0x03, // 113 0x00,0x00,0xF0,0x00,0x10, // 114 0x00,0x00,0xB0,0x00,0xB0,0x00,0xD0, // 115 0x10,0x00,0xF8,0x00,0x90, // 116 0x00,0x00,0xF0,0x00,0x80,0x00,0x80,0x00,0xF0, // 117 0x10,0x00,0xE0,0x00,0xE0,0x00,0x10, // 118 0x30,0x00,0xC0,0x00,0x30,0x00,0x30,0x00,0xC0,0x00,0x30, // 119 0x90,0x00,0xF0,0x00,0xF0,0x00,0x90, // 120 0x00,0x00,0x10,0x02,0xE0,0x03,0x60,0x00,0x10, // 121 0x00,0x00,0x90,0x00,0xD0,0x00,0xF0, // 122 0x00,0x00,0x20,0x00,0xDC,0x01,0x04,0x01, // 123 0x00,0x00,0xFC,0x03, // 124 0x00,0x00,0x04,0x01,0xDC,0x01,0x20, // 125 0x00,0x00,0x20,0x00,0x20,0x00,0x60,0x00,0x40,0x00,0x40, // 126 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 127 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 128 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 129 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 130 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 131 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 132 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 133 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 134 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 135 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 136 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 137 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 138 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 139 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 140 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 141 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 142 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 143 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 144 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 145 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 146 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 147 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 148 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 149 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 150 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 151 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 152 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 153 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 154 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 155 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 156 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 157 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 158 0xFC,0x01,0x04,0x01,0x04,0x01,0xFC,0x01, // 159 0x00,0x00,0xD0,0x03, // 161 0x00,0x00,0xF0,0x00,0xF8,0x01,0x90, // 162 0xA0,0x00,0xFC,0x00,0xA4,0x00,0xA4, // 163 0x88,0x00,0x70,0x00,0x50,0x00,0x70,0x00,0x88, // 164 0x54,0x00,0x58,0x00,0xE0,0x00,0x58,0x00,0x54, // 165 0x00,0x00,0xDC,0x01, // 166 0x00,0x00,0x3C,0x01,0x54,0x01,0xE4,0x01, // 167 0x00,0x00,0x04,0x00,0x00,0x00,0x04, // 168 0x00,0x00,0x78,0x00,0xCC,0x00,0xB4,0x00,0xB4,0x00,0xCC,0x00,0x78, // 169 0x00,0x00,0x58,0x00,0x5C,0x00,0x5C, // 170 0x00,0x00,0x60,0x00,0xF0,0x00,0x60,0x00,0xF0, // 171 0x00,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x60, // 172 0x00,0x00,0x20,0x00,0x20, // 173 0x00,0x00,0x78,0x00,0xCC,0x00,0xB4,0x00,0xB4,0x00,0xCC,0x00,0x78, // 174 0x00,0x00,0x04,0x00,0x04, // 175 0x00,0x00,0x0C,0x00,0x0C, // 176 0x00,0x00,0x90,0x00,0x90,0x00,0xFC,0x00,0x90,0x00,0x90, // 177 0x00,0x00,0x14,0x00,0x1C, // 178 0x00,0x00,0x1C,0x00,0x14, // 179 0x00,0x00,0x04, // 180 0x00,0x00,0xF0,0x03,0x80,0x00,0x80,0x00,0xF0, // 181 0x00,0x00,0x3C,0x00,0xFC,0x01,0x04,0x00,0xFC,0x01, // 182 0x00,0x00,0x20, // 183 0x00,0x00,0x00,0x02,0x00,0x03, // 184 0x00,0x00,0x14,0x00,0x1C, // 185 0x00,0x00,0x5C,0x00,0x54,0x00,0x5C, // 186 0x00,0x00,0xF0,0x00,0x60,0x00,0xF0,0x00,0x60, // 187 0x00,0x00,0x14,0x00,0x9C,0x00,0x70,0x00,0x18,0x00,0x04,0x00,0xC0,0x00,0xE0, // 188 0x00,0x00,0x14,0x00,0x9C,0x00,0x70,0x00,0x18,0x00,0x04,0x00,0xA0,0x00,0xE0, // 189 0x00,0x00,0x1C,0x00,0x94,0x00,0x60,0x00,0x18,0x00,0x04,0x00,0xC0,0x00,0xE0, // 190 0x00,0x00,0x00,0x03,0xD0,0x02,0x00,0x02, // 191 0x80,0x00,0x70,0x00,0x4E,0x00,0x72,0x00,0x80, // 192 0x80,0x00,0x70,0x00,0x4E,0x00,0x72,0x00,0x80, // 193 0x80,0x00,0x70,0x00,0x4C,0x00,0x70,0x00,0x80, // 194 0x80,0x00,0x72,0x00,0x4E,0x00,0x72,0x00,0x80, // 195 0x80,0x00,0x72,0x00,0x4C,0x00,0x72,0x00,0x80, // 196 0x80,0x00,0x60,0x00,0x5F,0x00,0x60,0x00,0x80, // 197 0x80,0x00,0x70,0x00,0x4C,0x00,0xFC,0x00,0xA4,0x00,0xA4,0x00,0xA4, // 198 0x00,0x00,0x78,0x00,0xCC,0x02,0x84,0x03,0x84,0x00,0x88, // 199 0x00,0x00,0xFC,0x00,0xA6,0x00,0xA6,0x00,0xA4, // 200 0x00,0x00,0xFC,0x00,0xA6,0x00,0xA6,0x00,0xA4, // 201 0x00,0x00,0xFC,0x00,0xA6,0x00,0xA6,0x00,0xA4, // 202 0x00,0x00,0xFC,0x00,0xA6,0x00,0xA4,0x00,0xA6, // 203 0x02,0x00,0xFE, // 204 0x02,0x00,0xFE, // 205 0x02,0x00,0xFE, // 206 0x02,0x00,0xFC, // 207 0x20,0x00,0xFC,0x00,0xA4,0x00,0x84,0x00,0xCC,0x00,0x78, // 208 0x00,0x00,0xFC,0x00,0x1A,0x00,0x62,0x00,0xFC, // 209 0x00,0x00,0x78,0x00,0x86,0x00,0x86,0x00,0x84,0x00,0x78, // 210 0x00,0x00,0x78,0x00,0x86,0x00,0x86,0x00,0x84,0x00,0x78, // 211 0x00,0x00,0x78,0x00,0x84,0x00,0x84,0x00,0x84,0x00,0x78, // 212 0x00,0x00,0x78,0x00,0x86,0x00,0x86,0x00,0x86,0x00,0x78, // 213 0x00,0x00,0x78,0x00,0x86,0x00,0x84,0x00,0x86,0x00,0x78, // 214 0x00,0x00,0x88,0x00,0x50,0x00,0x20,0x00,0x50,0x00,0x88, // 215 0x00,0x00,0xB8,0x00,0xE4,0x00,0x94,0x00,0x8C,0x00,0x74, // 216 0x00,0x00,0x7C,0x00,0x82,0x00,0x82,0x00,0x7C, // 217 0x00,0x00,0x7C,0x00,0x82,0x00,0x82,0x00,0x7C, // 218 0x00,0x00,0x7C,0x00,0x82,0x00,0x82,0x00,0x7C, // 219 0x00,0x00,0x7E,0x00,0x80,0x00,0x80,0x00,0x7E, // 220 0x04,0x00,0x0E,0x00,0xF2,0x00,0x0C,0x00,0x04, // 221 0x00,0x00,0xFC,0x00,0x28,0x00,0x28,0x00,0x38, // 222 0x00,0x00,0xFC,0x00,0x02,0x00,0x9A,0x00,0xE4, // 223 0x00,0x00,0xE4,0x00,0xB0,0x00,0xB0,0x00,0xF0, // 224 0x00,0x00,0xE4,0x00,0xB0,0x00,0xB0,0x00,0xF0, // 225 0x00,0x00,0xE0,0x00,0xB4,0x00,0xB4,0x00,0xF0, // 226 0x00,0x00,0xE0,0x00,0xBC,0x00,0xBC,0x00,0xF0, // 227 0x00,0x00,0xE0,0x00,0xB4,0x00,0xB4,0x00,0xF0, // 228 0x00,0x00,0xE0,0x00,0xB6,0x00,0xB6,0x00,0xF0, // 229 0x00,0x00,0xE0,0x00,0xB0,0x00,0xB0,0x00,0x60,0x00,0xB0,0x00,0xB0,0x00,0xB0, // 230 0x00,0x00,0x60,0x00,0x90,0x02,0x90,0x03, // 231 0x00,0x00,0x60,0x00,0xB4,0x00,0xB0,0x00,0xB0, // 232 0x00,0x00,0x60,0x00,0xB4,0x00,0xB0,0x00,0xB0, // 233 0x00,0x00,0x60,0x00,0xB4,0x00,0xB4,0x00,0xB0, // 234 0x00,0x00,0x60,0x00,0xB4,0x00,0xB0,0x00,0xB4, // 235 0x04,0x00,0xF0, // 236 0x04,0x00,0xF0, // 237 0x04,0x00,0xF4, // 238 0x04,0x00,0xF0, // 239 0x00,0x00,0x60,0x00,0x94,0x00,0x9C,0x00,0x70, // 240 0x00,0x00,0xFC,0x00,0x1C,0x00,0x1C,0x00,0xF0, // 241 0x00,0x00,0x64,0x00,0x90,0x00,0x90,0x00,0x60, // 242 0x00,0x00,0x64,0x00,0x90,0x00,0x90,0x00,0x60, // 243 0x00,0x00,0x60,0x00,0x94,0x00,0x94,0x00,0x60, // 244 0x00,0x00,0x60,0x00,0x9C,0x00,0x9C,0x00,0x60, // 245 0x00,0x00,0x64,0x00,0x90,0x00,0x90,0x00,0x64, // 246 0x00,0x00,0x20,0x00,0x20,0x00,0xA8,0x00,0x20,0x00,0x20, // 247 0x00,0x00,0xF0,0x00,0xD0,0x00,0xB0,0x00,0xF0, // 248 0x00,0x00,0xF4,0x00,0x80,0x00,0x80,0x00,0xF0, // 249 0x00,0x00,0xF4,0x00,0x80,0x00,0x80,0x00,0xF0, // 250 0x00,0x00,0xF0,0x00,0x84,0x00,0x84,0x00,0xF0, // 251 0x00,0x00,0xF0,0x00,0x84,0x00,0x84,0x00,0xF0, // 252 0x00,0x00,0x14,0x02,0xE0,0x03,0x60,0x00,0x10, // 253 0x00,0x00,0xFE,0x03,0x90,0x00,0x90,0x00,0x60, // 254 0x00,0x00,0x14,0x02,0xE0,0x03,0x64,0x00,0x10 // 255 }; ================================================ FILE: examples/SSD1306FontTryout/SSD1306FontTryout.ino ================================================ /** The MIT License (MIT) 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 */ /** Using this sketch, you can try out the fonts. Simply generate new font files at https://oleddisplay.squix.ch/ , download them and add to your sketch with "Sketch / Add file" in the Arduino IDE. Then include them and add their names to loop(). You'll see the name of the font on the serial monitor as the sketch cycles through them. */ // 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, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h // SH1106Wire display(0x3c, SDA, SCL); // Include all the font files you add to the Sketch #include "Dialog_plain_8.h" #include "Dialog_plain_7.h" #include "Dialog_plain_6.h" // This will call the function doPrint() with the name; // once without and once with quotes. #define DO_PRINT(a) doPrint(a, #a); void setup() { display.init(); // display.flipScreenVertically(); display.setContrast(255); } void loop() { // These three fonts come with the display driver DO_PRINT(ArialMT_Plain_10); DO_PRINT(ArialMT_Plain_16); DO_PRINT(ArialMT_Plain_24); // These three I had generated and added as files DO_PRINT(Dialog_plain_6); DO_PRINT(Dialog_plain_7); DO_PRINT(Dialog_plain_8); } void doPrint(const uint8_t* font, String fontname) { Serial.println(fontname); display.cls(); display.setFont(font); display.println("Lorem ipsum dolor sit amet, consectetur"); display.println("adipiscing elit, sed do eiusmod tempor"); display.println("incididunt ut labore et dolore magna aliqua."); display.println("Ut enim ad minim veniam, quis nostrud exercitation"); display.println("ullamco laboris nisi ut aliquip ex ea commodo"); display.println("consequat. Duis aute irure dolor in reprehenderit"); display.println("in voluptate velit esse cillum dolore eu fugiat"); display.println("nulla pariatur. Excepteur sint occaecat cupidatat"); display.println("non proident, sunt in culpa qui officia deserunt."); delay(5000); } // The library comes with fonts as a const uint8_t array, the site at // https://oleddisplay.squix.ch/ generates them as const char array. This code // converts one in the other to make sure both work here. void doPrint(const char* font, String fontname) { doPrint(static_cast(reinterpret_cast(font)), fontname); } ================================================ FILE: examples/SSD1306OTADemo/SSD1306OTADemo.ino ================================================ /** 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 */ #if defined(ESP8266) #include #include #elif defined(ESP32) #include #include #include #endif #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, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h // SH1106Wire display(0x3c, SDA, SCL); 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(); } ================================================ FILE: examples/SSD1306ScrollVerticalDemo/SSD1306ScrollVerticalDemo.ino ================================================ /** The MIT License (MIT) Copyright (c) 2022 by Stefan Seyfried 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. */ // 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, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h // SH1106Wire display(0x3c, SDA, SCL); // UTF-8 sprinkled within, because it tests special conditions in the char-counting code const String loremipsum = "Lorem ipsum dolor sit ämet, " "consetetur sadipscing elitr, sed diam nonümy eirmöd " "tempor invidunt ut labore et dolore mägnä aliquyam erat, " "sed diam voluptua. At vero eos et accusam et justo duo " "dolores et ea rebum. Stet clita kasd gubergren, no sea " "takimata sanctus est Lorem ipsum dolor sit amet. " "äöü-ÄÖÜ/߀é/çØ."; void setup() { display.init(); display.setContrast(255); display.setTextAlignment(TEXT_ALIGN_LEFT); display.setFont(ArialMT_Plain_16); display.display(); } void loop() { static uint16_t start_at = 0; display.clear(); uint16_t firstline = display.drawStringMaxWidth(0, 0, 128, loremipsum.substring(start_at)); display.display(); if (firstline != 0) { start_at += firstline; } else { start_at = 0; delay(1000); // additional pause before going back to start } delay(1000); } ================================================ FILE: examples/SSD1306SimpleDemo/SSD1306SimpleDemo.ino ================================================ /** 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 e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/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. // SH1106Wire 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.setFont(ArialMT_Plain_10); display.setTextAlignment(TEXT_ALIGN_RIGHT); display.drawString(128, 54, String(millis())); // write the buffer to the display display.display(); if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) { demoMode = (demoMode + 1) % demoLength; timeSinceLastModeSwitch = millis(); } counter++; delay(10); } ================================================ FILE: examples/SSD1306SimpleDemo/images.h ================================================ #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, }; ================================================ FILE: examples/SSD1306TwoScreenDemo/SSD1306TwoScreenDemo.ino ================================================ /** 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 // // GOTCHA! // // Pay attention if you work with ESP32 as some have two I2C buses. // You need to set the 'i2cBus' constructor parameter accordingly. // See https://github.com/ThingPulse/esp8266-oled-ssd1306/issues/387#issuecomment-2874437238 for a discussion. SSD1306Wire display(0x3c, 0, 14); SSD1306Wire display2(0x3c, 5, 4); 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); } ================================================ FILE: examples/SSD1306TwoScreenDemo/images.h ================================================ #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, }; ================================================ FILE: examples/SSD1306UiDemo/SSD1306UiDemo.ino ================================================ /** 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, SDA, SCL); // ADDRESS, SDA, SCL - SDA and SCL usually populate automatically based on your board's pins_arduino.h e.g. https://github.com/esp8266/Arduino/blob/master/variants/nodemcu/pins_arduino.h // SH1106Wire display(0x3c, SDA, SCL); 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); } } ================================================ FILE: examples/SSD1306UiDemo/images.h ================================================ #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 }; ================================================ FILE: keywords.txt ================================================ ####################################### # Syntax Coloring Map List ####################################### ####################################### # Constants (LITERAL1) ####################################### INVERSE LITERAL1 TEXT_ALIGN_LEFT LITERAL1 TEXT_ALIGN_RIGHT LITERAL1 TEXT_ALIGN_CENTER LITERAL1 TEXT_ALIGN_CENTER_BOTH LITERAL1 GEOMETRY_128_64 LITERAL1 GEOMETRY_128_32 LITERAL1 GEOMETRY_RAWMODE LITERAL1 ArialMT_Plain_10 LITERAL1 ArialMT_Plain_16 LITERAL1 ArialMT_Plain_24 LITERAL1 SLIDE_UP LITERAL1 SLIDE_DOWN LITERAL1 SLIDE_LEFT LITERAL1 SLIDE_RIGHT LITERAL1 TOP LITERAL1 RIGHT LITERAL1 BOTTOM LITERAL1 LEFT LITERAL1 LEFT_RIGHT LITERAL1 RIGHT_LEFT LITERAL1 IN_TRANSITION LITERAL1 FIXED LITERAL1 ####################################### # Datatypes (KEYWORD1) ####################################### OLEDDisplay KEYWORD1 OLEDDisplayUi KEYWORD1 SH1106Wire KEYWORD1 SH1106Brzo KEYWORD1 SH1106Spi KEYWORD1 SSD1306Wire KEYWORD1 SSD1306Brzo KEYWORD1 SSD1306I2C KEYWORD1 SSD1306Spi KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### allocateBuffer KEYWORD2 init KEYWORD2 resetDisplay KEYWORD2 setColor KEYWORD2 getColor KEYWORD2 setPixel KEYWORD2 setPixelColor KEYWORD2 clearPixel KEYWORD2 drawLine KEYWORD2 drawRect KEYWORD2 fillRect KEYWORD2 drawCircle KEYWORD2 drawCircleQuads KEYWORD2 fillCircle KEYWORD2 fillRing KEYWORD2 drawHorizontalLine KEYWORD2 drawVerticalLine KEYWORD2 drawProgressBar KEYWORD2 drawFastImage KEYWORD2 drawXbm KEYWORD2 drawIco16x16 KEYWORD2 drawString KEYWORD2 drawStringMaxWidth KEYWORD2 getStringWidth KEYWORD2 setTextAlignment KEYWORD2 setFont KEYWORD2 setFontTableLookupFunction KEYWORD2 displayOn KEYWORD2 displayOff KEYWORD2 invertDisplay KEYWORD2 normalDisplay KEYWORD2 setContrast KEYWORD2 setBrightness KEYWORD2 resetOrientation KEYWORD2 flipScreenVertically KEYWORD2 mirrorScreen KEYWORD2 display KEYWORD2 setLogBuffer KEYWORD2 drawLogBuffer KEYWORD2 getWidth KEYWORD2 getHeight KEYWORD2 ================================================ FILE: library.json ================================================ { "name": "ESP8266 and ESP32 OLED driver for SSD1306 displays", "version": "4.6.2", "keywords": "ssd1306, oled, display, i2c", "description": "I2C display driver for SSD1306 OLED displays connected to ESP8266, ESP32, Mbed-OS", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/ThingPulse/esp8266-oled-ssd1306" }, "authors": [ { "name": "Daniel Eichhorn, ThingPulse", "email": "squix78@gmail.com", "url": "https://thingpulse.com" }, { "name": "Fabrice Weinberg", "email": "fabrice@weinberg.me" } ], "frameworks": "arduino", "platforms": [ "espressif8266", "espressif32", "nordicnrf52" ] } ================================================ FILE: library.properties ================================================ name=ESP8266 and ESP32 OLED driver for SSD1306 displays version=4.6.2 author=ThingPulse, Fabrice Weinberg maintainer=ThingPulse sentence=I2C display driver for SSD1306 OLED displays connected to ESP8266, ESP32, Mbed-OS 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://github.com/ThingPulse/esp8266-oled-ssd1306 architectures=esp8266,esp32 license=MIT ================================================ FILE: license ================================================ 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 ================================================ FILE: platformio.ini ================================================ ; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; http://docs.platformio.org/page/projectconf.html [env:d1_mini] platform = espressif8266 board = d1_mini framework = arduino upload_speed = 921600 board_build.f_cpu = 160000000L upload_port = /dev/cu.SLAB_USBtoUART monitor_port = /dev/cu.SLAB_USBtoUART lib_deps = ================================================ FILE: resources/glyphEditor.html ================================================
Font array name:
First char code:
Width:
Height:
NewWidth:
NewHeight:

Shift all


================================================ FILE: src/OLEDDisplay.cpp ================================================ /** * 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 */ #include "OLEDDisplay.h" OLEDDisplay::OLEDDisplay() { displayWidth = 128; displayHeight = 64; displayBufferSize = displayWidth * displayHeight / 8; inhibitDrawLogBuffer = false; 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 (!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) + BufferOffset); this->buffer += BufferOffset; 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) + BufferOffset); this->buffer_back += BufferOffset; if(!this->buffer_back) { DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n"); free(this->buffer - BufferOffset); return false; } } #endif return true; } bool OLEDDisplay::init() { BufferOffset = getBufferOffset(); if(!allocateBuffer()) { return false; } sendInitCommands(); resetDisplay(); return true; } void OLEDDisplay::end() { if (this->buffer) { free(this->buffer - BufferOffset); this->buffer = NULL; } #ifdef OLEDDISPLAY_DOUBLE_BUFFER if (this->buffer_back) { free(this->buffer_back - BufferOffset); 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::drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) { drawLine(x0, y0, x1, y1); drawLine(x1, y1, x2, y2); drawLine(x2, y2, x0, y0); } void OLEDDisplay::fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) { int16_t a, b, y, last; if (y0 > y1) { _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); } if (y1 > y2) { _swap_int16_t(y2, y1); _swap_int16_t(x2, x1); } if (y0 > y1) { _swap_int16_t(y0, y1); _swap_int16_t(x0, x1); } if (y0 == y2) { a = b = x0; if (x1 < a) { a = x1; } else if (x1 > b) { b = x1; } if (x2 < a) { a = x2; } else if (x2 > b) { b = x2; } drawHorizontalLine(a, y0, b - a + 1); return; } int16_t dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1, dy12 = y2 - y1; int32_t sa = 0, sb = 0; if (y1 == y2) { last = y1; // Include y1 scanline } else { last = y1 - 1; // Skip it } for (y = y0; y <= last; y++) { a = x0 + sa / dy01; b = x0 + sb / dy02; sa += dx01; sb += dx02; if (a > b) { _swap_int16_t(a, b); } drawHorizontalLine(a, y, b - a + 1); } sa = dx12 * (y - y1); sb = dx02 * (y - y0); for (; y <= y2; y++) { a = x1 + sa / dy12; b = x0 + sb / dy02; sa += dx12; sb += dx02; if (a > b) { _swap_int16_t(a, b); } drawHorizontalLine(a, y, b - a + 1); } } 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 uint8_t *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 } } } uint16_t OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, const char* text, uint16_t textLength, uint16_t textWidth, bool utf8) { 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; uint16_t charCount = 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 0;} if (yMove + textHeight < 0 || yMove >= this->height()) {return 0;} for (uint16_t j = 0; j < textLength; j++) { int16_t xPos = xMove + cursorX; int16_t yPos = yMove + cursorY; if (xPos > this->width()) break; // no need to continue charCount++; uint8_t code; if (utf8) { code = (this->fontTableLookupFunction)(text[j]); if (code == 0) continue; } else 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; } } return charCount; } uint16_t 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 = strdup(strUser.c_str()); if (!text) { DEBUG_OLEDDISPLAY("[OLEDDISPLAY][drawString] Can't allocate char array.\n"); return 0; } 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 charDrawn = 0; uint16_t line = 0; char* textPart = strtok(text,"\n"); while (textPart != NULL) { uint16_t length = strlen(textPart); charDrawn += drawStringInternal(xMove, yMove - yOffset + (line++) * lineHeight, textPart, length, getStringWidth(textPart, length, true), true); textPart = strtok(NULL, "\n"); } free(text); return charDrawn; } void OLEDDisplay::drawStringf( int16_t x, int16_t y, char* buffer, String format, ... ) { va_list myargs; va_start(myargs, format); vsprintf(buffer, format.c_str(), myargs); va_end(myargs); drawString( x, y, buffer ); } uint16_t 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); const char* text = strUser.c_str(); 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; uint16_t firstLineChars = 0; uint16_t drawStringResult = 1; // later tested for 0 == error, so initialize to 1 for (uint16_t i = 0; i < length; i++) { char c = (this->fontTableLookupFunction)(text[i]); if (c == 0) continue; strWidth += pgm_read_byte(fontData + JUMPTABLE_START + (c - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Always try to break on a space, dash or slash if (text[i] == ' ' || text[i]== '-' || text[i] == '/') { preferredBreakpoint = i + 1; widthAtBreakpoint = strWidth; } if (strWidth >= maxLineWidth) { if (preferredBreakpoint == 0) { preferredBreakpoint = i; widthAtBreakpoint = strWidth; } drawStringResult = drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], preferredBreakpoint - lastDrawnPos, widthAtBreakpoint, true); if (firstLineChars == 0) firstLineChars = preferredBreakpoint; lastDrawnPos = preferredBreakpoint; // 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; if (drawStringResult == 0) // we are past the display already? break; } } // Draw last part if needed if (drawStringResult != 0 && lastDrawnPos < length) { drawStringResult = drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], length - lastDrawnPos, getStringWidth(&text[lastDrawnPos], length - lastDrawnPos, true), true); } if (drawStringResult == 0 || (yMove + lineNumber * lineHeight) >= this->height()) // text did not fit on screen return firstLineChars; return 0; // everything was drawn } uint16_t OLEDDisplay::getStringWidth(const char* text, uint16_t length, bool utf8) { uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); uint16_t stringWidth = 0; uint16_t maxWidth = 0; for (uint16_t i = 0; i < length; i++) { char c = text[i]; if (utf8) { c = (this->fontTableLookupFunction)(c); if (c == 0) continue; } stringWidth += pgm_read_byte(fontData + JUMPTABLE_START + (c - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); if (c == 10) { maxWidth = max(maxWidth, stringWidth); stringWidth = 0; } } return max(maxWidth, stringWidth); } uint16_t OLEDDisplay::getStringWidth(const String &strUser) { uint16_t width = getStringWidth(strUser.c_str(), strUser.length()); return width; } void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) { this->textAlignment = textAlignment; } void OLEDDisplay::setFont(const uint8_t *fontData) { this->fontData = fontData; // New font, so must recalculate. Whatever was there is gone at next print. setLogBuffer(); } void OLEDDisplay::setFont(const char *fontData) { setFont(static_cast(reinterpret_cast(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(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) { #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) Serial.println("[deprecated] Print functionality now handles buffer management automatically. This is a no-op."); #endif } void OLEDDisplay::drawLogBuffer() { 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; // If the lineHeight and the display height are not cleanly divisible, we need // to start off the screen when the buffer has logBufferMaxLines so that the // first line, and not the last line, drops off. uint16_t shiftUp = (this->logBufferLine == this->logBufferMaxLines) ? (lineHeight - (displayHeight % lineHeight)) % lineHeight : 0; for (uint16_t i=0;ilogBufferFilled;i++){ length++; // Everytime we have a \n print if (this->logBuffer[i] == 10) { // Draw string on line `line` from lastPos to length // Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT drawStringInternal(0, 0 - shiftUp + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0, false); // Remember last pos lastPos = i; // Reset length length = 0; } } // Draw the remaining string if (length > 0) { drawStringInternal(0, 0 - shiftUp + line * lineHeight, &this->logBuffer[lastPos], length, 0, false); } } uint16_t OLEDDisplay::getWidth(void) { return displayWidth; } uint16_t OLEDDisplay::getHeight(void) { return displayHeight; } void OLEDDisplay::cls() { clear(); this->logBufferFilled = 0; this->logBufferLine = 0; display(); } bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars) { #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) Serial.println("[deprecated] Print functionality now handles buffer management automatically. This is a no-op."); #endif return true; } bool OLEDDisplay::setLogBuffer(){ // don't know how big we need it without a font set. if (!fontData) return false; // we're always starting over if (logBuffer != NULL) free(logBuffer); // figure out how big it needs to be uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS); if (!textHeight) return false; // Prevent division by zero crashes uint16_t lines = this->displayHeight / textHeight + (this->displayHeight % textHeight ? 1 : 0); uint16_t chars = 5 * (this->displayWidth / textHeight); uint16_t size = lines * (chars + 1); // +1 is for \n // Something weird must have happened if (size == 0) return false; // All good, initialize logBuffer this->logBufferLine = 0; // Lines printed this->logBufferFilled = 0; // Nothing stored yet this->logBufferMaxLines = lines; // Lines max printable this->logBufferLineLen = chars; // Chars per line 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 (!fontData) return 1; // Create a logBuffer if there isn't one if (!logBufferSize) { // Give up if we can't create a logBuffer somehow if (!setLogBuffer()) return 1; } // 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 maxLineReached = this->logBufferLine >= this->logBufferMaxLines; bool bufferFull = this->logBufferFilled >= this->logBufferSize; // Can we write to the buffer? If not, make space. if (bufferFull || maxLineReached) { // See if we can chop off the first line uint16_t firstLineEnd = 0; for (uint16_t i = 0; i < this->logBufferFilled; i++) { if (this->logBuffer[i] == 10){ // Include last char too firstLineEnd = i + 1; // Calculate the new logBufferFilled value this->logBufferFilled = logBufferFilled - firstLineEnd; // Now move other lines to front of the buffer memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled); // And voila, buffer one line shorter this->logBufferLine--; break; } } // In we can't take off first line, we just empty the buffer if (!firstLineEnd) { this->logBufferFilled = 0; this->logBufferLine = 0; } } // So now we know for sure we have space in the buffer // Find the length of the last line uint16_t lastLineLen= 0; for (uint16_t i = 0; i < this->logBufferFilled; i++) { lastLineLen++; if (this->logBuffer[i] == 10) lastLineLen = 0; } // if last line is max length, ignore anything but linebreaks if (lastLineLen >= this->logBufferLineLen) { if (c != 10) return 1; } // Write to buffer this->logBuffer[this->logBufferFilled++] = c; // Keep track of lines written if (c == 10) this->logBufferLine++; // Draw to screen unless we're writing a whole string at a time if (!this->inhibitDrawLogBuffer) { clear(); drawLogBuffer(); display(); } // We always claim we printed it all return 1; } size_t OLEDDisplay::write(const char* str) { if (str == NULL) return 0; size_t length = strlen(str); // If we write a string, only do the drawLogBuffer at the end, not every time we write a char this->inhibitDrawLogBuffer = true; for (size_t i = 0; i < length; i++) { write(str[i]); } this->inhibitDrawLogBuffer = false; clear(); drawLogBuffer(); display(); return length; } #ifdef __MBED__ int OLEDDisplay::_putc(int c) { 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_64_48: this->displayWidth = 64; this->displayHeight = 48; break; case GEOMETRY_64_32: this->displayWidth = 64; 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); if(geometry == GEOMETRY_64_32) sendCommand(0x00); else sendCommand(SETSTARTLINE); sendCommand(CHARGEPUMP); sendCommand(0x14); sendCommand(MEMORYMODE); sendCommand(0x00); sendCommand(SEGREMAP); sendCommand(COMSCANINC); sendCommand(SETCOMPINS); if (geometry == GEOMETRY_128_64 || geometry == GEOMETRY_64_48 || geometry == GEOMETRY_64_32) { sendCommand(0x12); } else if (geometry == GEOMETRY_128_32) { sendCommand(0x02); } sendCommand(SETCONTRAST); if (geometry == GEOMETRY_128_64 || geometry == GEOMETRY_64_48 || geometry == GEOMETRY_64_32) { 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 } ================================================ FILE: src/OLEDDisplay.h ================================================ /** * 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 = 1, GEOMETRY_64_48 = 2, GEOMETRY_64_32 = 3, GEOMETRY_RAWMODE = 4 }; 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; }; // 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); // 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); // 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 an empty triangle i.e. only the outline void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); // Draw a solid triangle i.e. filled void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); // 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 uint8_t *ico, bool inverse = false); /* Text functions */ // Draws a string at the given location, returns how many chars have been written uint16_t drawString(int16_t x, int16_t y, const String &text); // Draws a formatted string (like printf) at the given location void drawStringf(int16_t x, int16_t y, char* buffer, String format, ... ); // 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 // returns 0 if everything fits on the screen or the numbers of characters in the // first line if not uint16_t 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, bool utf8 = false); // Convencience method for the const char version uint16_t getStringWidth(const 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 void setFont(const uint8_t *fontData); // Set the current font when supplied as a char* instead of a uint8_t* void setFont(const char *fontData); // Set the function that will convert utf-8 to font table index void setFontTableLookupFunction(FontTableLookupFunction function); /* 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 setContrast with only brightness parameter 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); // Print class device // Because this display class is "derived" from Arduino's Print class, // various function that work on it also work here. These functions include // print, println and printf. // cls() will clear the display immediately and empty the logBuffer, meaning // the next print statement will print at the top of the display again. // cls() should not be confused with clear(), which only clears the internal // graphics buffer, which can then be shown on the display with display(). void cls(); // Replaced by setLogBuffer() , which is protected bool setLogBuffer(uint16_t lines, uint16_t chars); // Draw the log buffer at position (x, y) // // (Automatically called with you use print, println or printf) 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; uint16_t logBufferLineLen; char *logBuffer; bool inhibitDrawLogBuffer; // the header size of the buffer used, e.g. for the SPI command header int BufferOffset; 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)); uint16_t drawStringInternal(int16_t xMove, int16_t yMove, const char* text, uint16_t textLength, uint16_t textWidth, bool utf8); // (re)creates the logBuffer that printing uses to remember what was on the // screen already bool setLogBuffer(); // Draws the contents of the logBuffer to the screen void drawLogBuffer(); FontTableLookupFunction fontTableLookupFunction; }; #endif ================================================ FILE: src/OLEDDisplayFonts.h ================================================ #ifndef OLEDDISPLAYFONTS_h #define OLEDDISPLAYFONTS_h #ifdef __MBED__ #define PROGMEM #endif 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 }; #endif ================================================ FILE: src/OLEDDisplayUi.cpp ================================================ /** * 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.isIndicatorDrawn = true; state.manualControl = false; state.userData = NULL; shouldDrawIndicators = true; autoTransition = true; setTimePerFrame(5000); setTimePerTransition(500); } void OLEDDisplayUi::init() { this->display->init(); } 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.isIndicatorDrawn = true; } void OLEDDisplayUi::disableIndicator(){ this->state.isIndicatorDrawn = 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); } // -/----- Manual control -----\- void OLEDDisplayUi::nextFrame() { if (this->state.frameState != IN_TRANSITION) { this->state.manualControl = 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.manualControl = 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.isIndicatorDrawn = 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.manualControl = 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 kept 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 manualControl if (this->state.manualControl) { this->state.frameTransitionDirection = this->lastTransitionDirection; this->state.manualControl = 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.isIndicatorDrawn = true; } void OLEDDisplayUi::drawFrame(){ switch (this->state.frameState){ case IN_TRANSITION: { float progress = 0.f; if (this->ticksPerTransition > 0u) { 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 drawnCurrentFrame; // Probe each frameFunction for the indicator drawn state this->enableIndicator(); (this->frameFunctions[this->state.currentFrame])(this->display, &this->state, x, y); drawnCurrentFrame = this->state.isIndicatorDrawn; this->enableIndicator(); (this->frameFunctions[this->getNextFrameNumber()])(this->display, &this->state, x1, y1); // Build up the indicatorDrawState if (drawnCurrentFrame && !this->state.isIndicatorDrawn) { // Drawn now but not next this->indicatorDrawState = 2; } else if (!drawnCurrentFrame && this->state.isIndicatorDrawn) { // Not drawn now but next this->indicatorDrawState = 1; } else if (!drawnCurrentFrame && !this->state.isIndicatorDrawn) { // Not drawn in both frames this->indicatorDrawState = 3; } // If the indicator isn't draw in the current frame // reflect it in state.isIndicatorDrawn if (!drawnCurrentFrame) this->state.isIndicatorDrawn = 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.isIndicatorDrawn && 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; } ================================================ FILE: src/OLEDDisplayUi.h ================================================ /** * 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 isIndicatorDrawn; // Normal = 1, Inverse = -1; int8_t frameTransitionDirection; bool manualControl; // 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 drawn // 3 Not drawn in both frames // 2 Drawn this frame but not next // 1 Not drawn 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); /** * Initialise the display */ void init(); /** * Configure the internal used target FPS */ void setTargetFPS(uint8_t fps); // Automatic Control /** * 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 approximate time a frame is displayed */ void setTimePerFrame(uint16_t time); /** * Set the approximate 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 ================================================ FILE: src/SH1106.h ================================================ /** * 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 ================================================ FILE: src/SH1106Brzo.h ================================================ /** * 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; uint8_t 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 ================================================ FILE: src/SH1106Spi.h ================================================ /** * 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; uint8_t _cs; public: /* pass _cs as -1 to indicate "do not use CS pin", for cases where it is hard wired low */ SH1106Spi(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); if (_cs != (uint8_t) -1) { 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; // 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); set_CS(HIGH); digitalWrite(_dc, HIGH); // data mode set_CS(LOW); for (x = minBoundX; x <= maxBoundX; x++) { SPI.transfer(buffer[x + y * displayWidth]); } set_CS(HIGH); yield(); } #else for (uint8_t y=0; y #if defined(ARDUINO_ARCH_ESP32) #define I2C_OLED_TRANSFER_BYTE 64 /** ESP32 can Transfer Max 128 bytes */ #else #define I2C_OLED_TRANSFER_BYTE 16 #endif #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; int _sda; int _scl; bool _doI2cAutoInit = false; TwoWire* _wire = NULL; long _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, int sda = -1, int scl = -1, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64, HW_I2C i2cBus = I2C_ONE, long frequency = 700000) { setGeometry(g); this->_address = address; this->_sda = sda; this->_scl = scl; #if !defined(ARDUINO_ARCH_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) this->_wire = &Wire; #else this->_wire = (i2cBus==I2C_ONE) ? &Wire : &Wire1; #endif this->_frequency = frequency; } bool connect() { #if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP8266) _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 ); uint8_t 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 == I2C_OLED_TRANSFER_BYTE) { _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<(128/I2C_OLED_TRANSFER_BYTE); x++) { _wire->beginTransmission(_address); _wire->write(0x40); for (uint8_t k = 0; k < I2C_OLED_TRANSFER_BYTE; 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) { #if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP8266) _wire->begin(); #else _wire->begin(this->_sda, this->_scl); #endif } } }; #endif ================================================ FILE: src/SSD1306.h ================================================ /** * 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 ================================================ FILE: src/SSD1306Brzo.h ================================================ /** * 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) { 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 = _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(x_offset + minBoundX); sendCommand(x_offset + maxBoundX); sendCommand(PAGEADDR); sendCommand(minBoundY); sendCommand(maxBoundY); uint8_t k = 0; int buflen = ( this->width() / 8 ) + 1; uint8_t sendBuffer[buflen]; 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 * this->width()]; if (k == (buflen-1)) { brzo_i2c_write(sendBuffer, buflen, true); k = 0; } } yield(); } brzo_i2c_write(sendBuffer, k + 1, true); brzo_i2c_end_transaction(); #else // No double buffering sendCommand(COLUMNADDR); sendCommand(x_offset); sendCommand(x_offset + (this->width() - 1)); sendCommand(PAGEADDR); sendCommand(0x0); sendCommand((this->height() / 8) - 1); int buflen = ( this->width() / 8 ) + 1; uint8_t sendBuffer[buflen]; 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 ================================================ FILE: src/SSD1306Spi.h ================================================ /** * 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: /* pass _cs as -1 to indicate "do not use CS pin", for cases where it is hard wired low */ 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); if (_cs != (uint8_t) -1) { 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); set_CS(HIGH); digitalWrite(_dc, HIGH); // data mode set_CS(LOW); for (y = minBoundY; y <= maxBoundY; y++) { for (x = minBoundX; x <= maxBoundX; x++) { SPI.transfer(buffer[x + y * displayWidth]); } yield(); } set_CS(HIGH); #else // No double buffering sendCommand(COLUMNADDR); sendCommand(0x0); sendCommand(0x7F); sendCommand(PAGEADDR); sendCommand(0x0); if (geometry == GEOMETRY_128_64 || geometry == GEOMETRY_64_48 || geometry == GEOMETRY_64_32 ) { sendCommand(0x7); } else if (geometry == GEOMETRY_128_32) { sendCommand(0x3); } set_CS(HIGH); digitalWrite(_dc, HIGH); // data mode set_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 #if defined(ARDUINO_ARCH_ESP32) #define I2C_MAX_TRANSFER_BYTE 128 /** ESP32 can Transfer 128 bytes */ #else #define I2C_MAX_TRANSFER_BYTE 17 #endif //-------------------------------------- class SSD1306Wire : public OLEDDisplay { private: uint8_t _address; int _sda; int _scl; bool _doI2cAutoInit = false; TwoWire* _wire = NULL; long _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, long frequency = 700000) { setGeometry(g); this->_address = address; this->_sda = sda; this->_scl = scl; #if !defined(ARDUINO_ARCH_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) this->_wire = &Wire; #else this->_wire = (i2cBus == I2C_ONE) ? &Wire : &Wire1; #endif this->_frequency = frequency; } bool connect() { #if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ARCH_ESP8266) _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); uint8_t 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 == (I2C_MAX_TRANSFER_BYTE - 1)) { _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); for (uint16_t i=0; i < displayBufferSize; i++) { _wire->beginTransmission(this->_address); _wire->write(0x40); for (uint8_t x = 0; x < (I2C_MAX_TRANSFER_BYTE - 1); 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_ARCH_ESP8266) _wire->begin(); #else _wire->begin(this->_sda, this->_scl); #endif } } }; #endif