Browse Source

Added fonts and functionalities

master
Englebert 3 years ago
parent
commit
28a3cf9b63
  1. 4
      BertFPVDiversity.h
  2. 130
      BertFPVDiversity.ino
  3. 476
      ESP_8_BIT_GFX.cpp
  4. 244
      ESP_8_BIT_GFX.h
  5. 850
      ESP_8_BIT_composite.cpp
  6. 123
      ESP_8_BIT_composite.h
  7. 36
      README.md
  8. 318
      channels.cpp
  9. 28
      channels.h
  10. 15
      intro.cpp
  11. 294
      kimberle13pt7b.h
  12. 484
      kimberle18pt7b.h
  13. 153
      kimberle6pt7b.h
  14. 188
      kimberle8pt7b.h
  15. 87
      main.cpp
  16. 23
      main.h
  17. 43
      menu.cpp
  18. 9
      rx5808.cpp
  19. 3
      rx5808.h
  20. 2
      video.cpp
  21. 9
      video.h

4
BertFPVDiversity.h

@ -11,8 +11,12 @@
#include <Arduino.h>
#define MAX_RSSI 1366
extern uint8_t display_screen;
extern uint32_t current_millis;
extern uint32_t rssi1, rssi2;
extern uint8_t vtx_channel;
void IRAM_ATTR onTimer();
void display_output();

130
BertFPVDiversity.ino

@ -9,6 +9,7 @@
// 8-bits color code
// RRRGGGBB
#include "Arduino.h"
#include <EEPROM.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
@ -18,8 +19,9 @@
#include "video.h"
#include "intro.h"
#include "menu.h"
#include "search.h"
#include "main.h"
#include "rx5808.h"
#include "channels.h"
uint8_t display_screen = 0;
@ -31,6 +33,7 @@ uint8_t display_screen = 0;
#define INDICATOR_V2 15
#define BUZZER 23
#define VIDEO_SELECTOR 12
#define RSSI1 39
#define RSSI2 36
@ -38,6 +41,12 @@ uint8_t display_screen = 0;
uint32_t last_buzzer_seconds = 0;
bool last_buzzer_seconds_cron = false;
uint32_t last_rssi_read = 0;
uint32_t rssi1, rssi2;
uint8_t vtx_channel = 0;
uint32_t last_display = 0;
// Starting up WebServer
WebServer server(80);
@ -486,7 +495,7 @@ uint32_t current_millis = 0;
hw_timer_t * timer = NULL; /* create a hardware timer */
uint8_t c = 0;
uint8_t color = 0;
bool display_output_state = true;
bool display_output_state = false;
void display_output() {
// Wait for the next frame to minimize chance of visible tearing
@ -506,6 +515,11 @@ void display_output() {
case 1:
Menu::begin();
break;
// Functions screens
case 2:
Main::begin();
break;
}
/*******
@ -574,9 +588,9 @@ void touchBeep(uint8_t beep_type = 0) {
// Instead of delay we use cronjob method
if(beep_type == 0) {
last_buzzer_seconds = millis() + 200;
last_buzzer_seconds = millis() + 50;
} else if(beep_type == 1) {
last_buzzer_seconds = millis() + 500;
last_buzzer_seconds = millis() + 90;
} else if(beep_type == 2) {
last_buzzer_seconds = millis() + 100;
}
@ -632,6 +646,9 @@ void setup() {
/* Standard serial baud rate */
Serial.begin(115200);
/* Preparing EEPROM SIZE */
EEPROM.begin(32);
/* Setting up IO pins */
io_setup();
@ -646,6 +663,16 @@ void setup() {
/* Setup Finish Routine */
setup_done();
/* Cool down a bit... */
delay(500);
osd(1);
osd(0);
osd(1);
display_output_state = true;
/* Trying to set freq.... */
RX5808::setChannelByFreq(5865);
}
void osd(uint8_t state) {
@ -661,12 +688,10 @@ void osd(uint8_t state) {
gpio_set_pull_mode(GPIO_NUM_25, GPIO_FLOATING);
RX5808::setPowerDownRegister(0b00010000110000010011);
touchBeep(1);
} else {
RX5808::setPowerDownRegister(0b01010000110000010011);
dac_output_enable(DAC_CHANNEL_1);
dac_i2s_enable();
touchBeep(0);
}
}
@ -706,6 +731,19 @@ bool touchpad(uint8_t touch_id) {
}
void loop() {
// Get readings from both RX5808 module
if(millis() > last_rssi_read) {
for(uint8_t i = 0; i < 4; i++) {
rssi1 += analogRead(RSSI1);
rssi2 += analogRead(RSSI2);
}
rssi1 = rssi1 >> 2; // Faster way to divide 4
rssi2 = rssi2 >> 2; // Faster way to divide 4
rssi1 = (rssi1 > MAX_RSSI) ? MAX_RSSI : rssi1;
rssi2 = (rssi2 > MAX_RSSI) ? MAX_RSSI : rssi2;
last_rssi_read = millis() + 10;
}
// Handling web services every 100mS
if(millis() > last_webserver_seconds) {
server.handleClient();
@ -719,8 +757,10 @@ void loop() {
}
// Handling cronjobs - END
if(display_output_state)
display_output();
if(millis() > last_display) {
if(display_output_state) display_output();
last_display = millis() + 1;
}
// Checking TouchPad - MODE
if(millis() > last_mode_touched) {
@ -732,8 +772,9 @@ void loop() {
osd(1);
}
touchBeep(1);
// Next touch scan
last_mode_touched = millis() + 500;
last_mode_touched = millis() + 200;
} else {
// Next touch scan
last_mode_touched = millis() + 100;
@ -743,12 +784,19 @@ void loop() {
// Checking TouchPad - NEXT
if(millis() > last_next_touched) {
if(touchpad(TOUCH_DOWN)) {
Menu::menu_position++;
Menu::menu_position = (Menu::menu_position >= Menu::MAX_MENU_ITEMS) ? 0 : Menu::menu_position;
if(display_screen == 1) {
Menu::menu_position++;
Menu::menu_position = (Menu::menu_position >= Menu::MAX_MENU_ITEMS) ? 0 : Menu::menu_position;
} else if(display_screen == 2) {
vtx_channel++;
vtx_channel = (vtx_channel > CHANNELS_SIZE - 1) ? CHANNELS_SIZE - 1: vtx_channel;
RX5808::setChannelByFreq(Channels::getFrequency(vtx_channel));
}
touchBeep(2);
// Next touch scan
last_next_touched = millis() + 500;
last_next_touched = millis() + 200;
} else {
// Next touch scan
last_next_touched = millis() + 100;
@ -758,15 +806,21 @@ void loop() {
// Checking TouchPad - PREV
if(millis() > last_prev_touched) {
if(touchpad(TOUCH_UP)) {
Menu::menu_position--;
Menu::menu_position = (Menu::menu_position < 0) ? Menu::MAX_MENU_ITEMS - 1 : Menu::menu_position;
if(display_screen == 1) {
Menu::menu_position--;
Menu::menu_position = (Menu::menu_position < 0) ? Menu::MAX_MENU_ITEMS - 1 : Menu::menu_position;
} else if(display_screen == 2) {
vtx_channel--;
vtx_channel = (vtx_channel > CHANNELS_SIZE) ? 0: vtx_channel;
RX5808::setChannelByFreq(Channels::getFrequency(vtx_channel));
}
touchBeep(2);
// Next touch scan
last_next_touched = millis() + 500;
last_prev_touched = millis() + 200;
} else {
// Next touch scan
last_next_touched = millis() + 100;
last_prev_touched = millis() + 100;
}
}
@ -774,13 +828,20 @@ void loop() {
if(millis() > last_enter_touched) {
if(touchpad(TOUCH_ENTER)) {
touchBeep(2);
if(display_screen == 1) {
// Different menu different functions
switch(Menu::menu_position) {
case 0:
display_screen = 2;
break;
// Different menu different functions
switch(Menu::menu_position) {
case 3:
delay(800);
ESP.restart();
break;
case 2:
delay(800);
ESP.restart();
break;
}
} else if(display_screen == 2) {
display_screen = 1;
}
// Next touch scan
@ -790,30 +851,8 @@ void loop() {
last_enter_touched = millis() + 100;
}
}
/****************
// Checking TouchPad - Up
touched_val = touchRead(TOUCH_UP);
if(touched_val < THRESHOLD_MODE) {
if(millis() > last_mode_touched) {
Menu::menu_position--;
last_mode_touched = millis() + 500;
Menu::menu_position = (Menu::menu_position < 0) ? Menu::MAX_MENU_ITEMS - 1 : Menu::menu_position;
//Menu::menu_position = (Menu::menu_position >= Menu::MAX_MENU_ITEMS) ? 0 : Menu::menu_position;
}
}
// Checking TouchPad - DOWN
touched_val = touchRead(TOUCH_DOWN);
if(touched_val < THRESHOLD_MODE) {
if(millis() > last_mode_touched) {
Menu::menu_position++;
last_mode_touched = millis() + 500;
//Menu::menu_position = (Menu::menu_position < 0) ? Menu::MAX_MENU_ITEMS - 1 : Menu::menu_position;
Menu::menu_position = (Menu::menu_position >= Menu::MAX_MENU_ITEMS) ? 0 : Menu::menu_position;
}
}
**********/
/***********
// Temporary
if(Serial.available() > 0) {
String serial_cmd_string = Serial.readStringUntil('\n');
@ -897,4 +936,5 @@ void loop() {
Menu::menu_position = (Menu::menu_position < 0) ? Menu::MAX_MENU_ITEMS - 1 : Menu::menu_position;
Menu::menu_position = (Menu::menu_position >= Menu::MAX_MENU_ITEMS) ? 0 : Menu::menu_position;
}
********/
}

476
ESP_8_BIT_GFX.cpp

@ -0,0 +1,476 @@
/*
Adafruit_GFX for ESP_8_BIT color composite video.
NOT AN OFFICIAL ADAFRUIT GRAPHICS LIBRARY.
Allows ESP32 Arduino sketches to draw to a composite video device using
Adafruit's graphics API.
NOTE RE:COLOR
Adafruit GFX is designed for 16-bit (RGB565) color, but ESP_8_BIT video
only handles 8-bit (RGB332) color. There are two ways to handle this,
specified by passsing "8" or "16" into the constructor:
8 = Truncate the 16-bit color values and use the lower 8 bits directly as
RGB332 color. This is faster, but caller needs to know to use 8-bit
color values. A good choice when writing new code using this library.
16 = Automatically extract the most significant 3 red, 3 green, and 2 blue
bits from a 16-bit RGB565 color value to generate a RGB332 color.
Performing this conversion slows down the code, but the caller does not
need to know about the limitations. A good choice when reusing existing
Adafruit GFX code that works in 16-bit color space.
An utility function RGB565toRGB332 is available to perform this conversion.
NOTE RE:ASPECT RATIO
Adafruit GFX assumes pixels are square, but this is not true of ESP_8_BIT
which has nonsquare pixels. (4:3 aspect ratio in a 256x240 frame buffer.)
Circles will look squashed as wide ovals, etc. This version of the API does
not offer any way to compensate, the caller has to deal with it.
Copyright (c) Roger Cheng
MIT License
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 "ESP_8_BIT_GFX.h"
static const char *TAG = "ESP_8_BIT_GFX";
static const int16_t MAX_Y = 239;
static const int16_t MAX_X = 255;
/*
* @brief Expose Adafruit GFX API for ESP_8_BIT composite video generator
*/
ESP_8_BIT_GFX::ESP_8_BIT_GFX(bool ntsc, uint8_t colorDepth)
: Adafruit_GFX(MAX_X+1, MAX_Y+1)
{
_pVideo = new ESP_8_BIT_composite(ntsc);
if (NULL==_pVideo)
{
ESP_LOGE(TAG, "Video signal generator allocation failed");
ESP_ERROR_CHECK(ESP_FAIL);
}
if (8 == colorDepth || 16 == colorDepth)
{
_colorDepth = colorDepth;
}
else
{
ESP_LOGE(TAG, "Unsupported color depth");
ESP_ERROR_CHECK(ESP_FAIL);
}
// Default behavior is not to copy buffer upon swap
copyAfterSwap = false;
// Initialize performance tracking state
_perfStart = 0;
_perfEnd = 0;
_waitTally = 0;
}
/*
* @brief Call once to set up the API with self-allocated frame buffer.
*/
void ESP_8_BIT_GFX::begin()
{
_pVideo->begin();
}
/*
* @brief Calculate performance metrics, output as INFO log.
* @return Number range from 0 to 10000. Higher values indicate more time
* has been spent waiting for buffer swap, implying the rest of the code
* ran faster and completed more quickly.
*/
uint32_t ESP_8_BIT_GFX::perfData()
{
uint32_t fraction = getWaitFraction();
if (_perfEnd < _perfStart)
{
ESP_LOGE(TAG, "Performance end time is earlier than start time.");
}
else
{
uint32_t duration = _perfEnd - _perfStart;
if (duration < _waitTally)
{
ESP_LOGE(TAG, "Overall time duration is less than tally of wait times.");
}
else
{
uint32_t frames = _pVideo->getRenderedFrameCount() - _frameStart;
uint32_t swaps = _pVideo->getBufferSwapCount() - _swapStart;
uint32_t wholePercent = fraction/100;
uint32_t decimalPercent = fraction%100;
ESP_LOGI(TAG, "Waited %d.%d%%, missed %d of %d frames",
wholePercent, decimalPercent, frames-swaps, frames);
}
}
_perfStart = 0;
_perfEnd = 0;
_waitTally = 0;
return fraction;
}
/*
* @brief Wait for swap of front and back buffer. Gathers performance
* metrics while waiting.
*/
void ESP_8_BIT_GFX::waitForFrame()
{
// Track the old lines array in case we need to copy after swap
uint8_t** oldLineArray = _pVideo->getFrameBufferLines();
// Values to track time spent waiting for swap
uint32_t waitStart = xthal_get_ccount();
uint32_t waitEnd;
if (waitStart < _perfEnd)
{
// CCount overflowed since last call, conclude this session.
perfData();
}
if (0 == _waitTally)
{
// No wait tally signifies start of new session.
_perfStart = waitStart;
_frameStart = _pVideo->getRenderedFrameCount();
_swapStart = _pVideo->getBufferSwapCount();
}
// Wait for swap of front and back buffer
_pVideo->waitForFrame();
if (copyAfterSwap)
{
uint8_t** newLineArray = _pVideo->getFrameBufferLines();
// This must be kept in sync with how frame buffer memory
// is allocated in ESP_8_BIT_composite::frameBufferAlloc()
for (uint8_t chunk = 0; chunk < 15; chunk++)
{
memcpy(newLineArray[chunk*16], oldLineArray[chunk*16], 256*16);
}
}
// Core clock count after we've finished waiting
waitEnd = xthal_get_ccount();
if (waitEnd < waitStart)
{
// CCount overflowed while we were waiting, perform calculation
// ignoring the time spent waiting.
_perfEnd = waitStart;
perfData();
}
else
{
// Increase tally of time we spent waiting for buffer swap
_waitTally += waitEnd-waitStart;
_perfEnd = waitEnd;
}
}
/*
* @brief Fraction of time in waitForFrame() in percent of percent.
* @return Number range from 0 to 10000. Higher values indicate more time
* has been spent waiting for buffer swap, implying the rest of the code
* ran faster and completed more quickly.
*/
uint32_t ESP_8_BIT_GFX::getWaitFraction()
{
if (_perfEnd > _perfStart + 10000)
{
return _waitTally/((_perfEnd-_perfStart)/10000);
}
else
{
return 10000;
}
}
/*
* @brief Ends the current performance tracking session and start a new
* one. Useful for isolating sections of code for measurement.
* @note Sessions are still terminated whenever CPU clock counter
* overflows (every ~18 seconds @ 240MHz) so some data may still be lost.
* @return Number range from 0 to 10000. Higher values indicate more time
* has been spent waiting for buffer swap, implying the rest of the code
* ran faster and completed more quickly.
*/
uint32_t ESP_8_BIT_GFX::newPerformanceTrackingSession()
{
return perfData();
}
/*
* @brief Utility to convert from 16-bit RGB565 color to 8-bit RGB332 color
*/
uint8_t ESP_8_BIT_GFX::convertRGB565toRGB332(uint16_t color)
{
// Extract most significant 3 red, 3 green and 2 blue bits.
return (uint8_t)(
(color & 0xE000) >> 8 |
(color & 0x0700) >> 6 |
(color & 0x0018) >> 3
);
}
/*
* @brief Retrieve color to use depending on _colorDepth
*/
uint8_t ESP_8_BIT_GFX::getColor8(uint16_t color)
{
switch(_colorDepth)
{
case 8:
// Use lower 8 bits directly
return (uint8_t)color;
break;
case 16:
// Downsample from 16 to 8-bit color.
return convertRGB565toRGB332(color);
break;
}
}
/*
* @brief Clamp X coordinate value within valid range
*/
int16_t ESP_8_BIT_GFX::clampX(int16_t inputX)
{
if (inputX < 0) {
ESP_LOGV(TAG, "Clamping X to 0");
return 0;
}
if (inputX > MAX_X) {
ESP_LOGV(TAG, "Clamping X to 255");
return MAX_X;
}
return inputX;
}
/*
* @brief Clamp Y coordinate value within valid range
*/
int16_t ESP_8_BIT_GFX::clampY(int16_t inputY)
{
if (inputY < 0) {
ESP_LOGV(TAG, "Clamping Y to 0");
return 0;
}
if (inputY > MAX_Y) {
ESP_LOGV(TAG, "Clamping Y to 239");
return MAX_Y;
}
return inputY;
}
/*
* @brief Required Adafruit_GFX override to put a pixel on screen
*/
void ESP_8_BIT_GFX::drawPixel(int16_t x, int16_t y, uint16_t color)
{
if (x < 0 || x > MAX_X ||
y < 0 || y > MAX_Y )
{
// This pixel is off screen, nothing to draw.
return;
}
startWrite();
_pVideo->getFrameBufferLines()[y][x] = getColor8(color);
endWrite();
}
/**************************************************************************/
/*!
@brief Draw a perfectly vertical line, optimized for ESP_8_BIT
@param x Top-most x coordinate
@param y Top-most y coordinate
@param h Height in pixels
@param color Color to fill with.
*/
/**************************************************************************/
void ESP_8_BIT_GFX::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color)
{
if (h < 1)
{
// Don't draw anything for zero or negative height
return;
}
if (x < 0 || x > MAX_X)
{
// This vertical line is off screen left or right, nothing to draw.
return;
}
if (y+h < 0 || y > MAX_Y )
{
// This vertical line is off screen top or bottom, nothing to draw.
return;
}
int16_t clampedY = clampY(y);
int16_t clampedYH = clampY(y+h-1)+1;
uint8_t color8 = getColor8(color);
uint8_t** lines = _pVideo->getFrameBufferLines();
startWrite();
for(int16_t vertical = clampedY; vertical < clampedYH; vertical++)
{
lines[vertical][x] = color8;
}
endWrite();
}
/**************************************************************************/
/*!
@brief Draw a perfectly horizontal line, optimized for ESP_8_BIT
@param x Left-most x coordinate
@param y Left-most y coordinate
@param w Width in pixels
@param color Color to fill with
*/
/**************************************************************************/
void ESP_8_BIT_GFX::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color)
{
if (w < 1)
{
// Don't draw anything for zero or negative width
return;
}
if (y < 0 || y > MAX_Y)
{
// This horizontal line is off screen top or bottom, nothing to draw.
return;
}
if (x+w < 0 || x > MAX_X)
{
// This horizontal line is off screen left or right, nothing to draw.
return;
}
int16_t clampedX = clampX(x);
int16_t clampedXW = clampX(x+w-1);
int16_t fillWidth = clampedXW-clampedX+1;
uint8_t color8 = getColor8(color);
uint8_t** lines = _pVideo->getFrameBufferLines();
startWrite();
memset(&(lines[y][clampedX]), color8, fillWidth);
endWrite();
}
/**************************************************************************/
/*!
@brief Fill a rectangle completely with one color, optimized for ESP_8_BIT
@param x Top left corner x coordinate
@param y Top left corner y coordinate
@param w Width in pixels
@param h Height in pixels
@param color Color to fill with
*/
/**************************************************************************/
void ESP_8_BIT_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color)
{
if (h < 1)
{
// Don't draw anything for zero or negative height
return;
}
if (w < 1)
{
// Don't draw anything for zero or negative width
return;
}
if (x+w < 0 || x > MAX_X)
{
// This rectangle is off screen left or right, nothing to draw.
return;
}
if (y+h < 0 || y > MAX_Y )
{
// This rectangle is off screen top or bottom, nothing to draw.
return;
}
int16_t clampedX = clampX(x);
int16_t clampedXW = clampX(x+w-1);
int16_t fillWidth = clampedXW-clampedX+1;
int16_t clampedY = clampY(y);
int16_t clampedYH = clampY(y+h-1)+1;
uint8_t color8 = getColor8(color);
uint8_t** lines = _pVideo->getFrameBufferLines();
startWrite();
for(int16_t vertical = clampedY; vertical < clampedYH; vertical++)
{
memset(&(lines[vertical][clampedX]), color8, fillWidth);
}
endWrite();
}
/**************************************************************************/
/*!
@brief Fill the screen completely with one color, optimized for ESP_8_BIT.
@param color Color to fill with
*/
/**************************************************************************/
void ESP_8_BIT_GFX::fillScreen(uint16_t color)
{
uint8_t color8 = getColor8(color);
uint8_t** lines = _pVideo->getFrameBufferLines();
startWrite();
// We can't do a single memset() because it is valid for _lines to point
// into non-contingous pieces of memory. (Necessary when memory is
// fragmented and we can't get a big enough chunk of contiguous bytes.)
for(uint8_t y = 0; y <= MAX_Y; y++)
{
memset(lines[y], color8, 256);
}
endWrite();
}

244
ESP_8_BIT_GFX.h

@ -0,0 +1,244 @@
/*
Adafruit_GFX for ESP_8_BIT color composite video.
NOT AN OFFICIAL ADAFRUIT GRAPHICS LIBRARY.
Allows ESP32 Arduino sketches to draw to a composite video device using
Adafruit's graphics API.
NOTE RE:COLOR
Adafruit GFX is designed for 16-bit (RGB565) color, but ESP_8_BIT video
only handles 8-bit (RGB332) color. There are two ways to handle this,
depending on passsing "8" or "16" into the constructor:
8 = Truncate the 16-bit color values and use the lower 8 bits directly as
RGB332 color. This is faster, but caller needs to know to use 8-bit
color values. A good choice when writing new code using this library.
16 = Automatically extract the most significant 3 red, 3 green, and 2 blue
bits from a 16-bit RGB565 color value to generate a RGB332 color.
Performing this conversion slows down the code, but the caller does not
need to know about the limitations. A good choice when reusing existing
Adafruit GFX code that works in 16-bit color space.
An utility function RGB565toRGB332 is available to perform this conversion.
NOTE RE:ASPECT RATIO
Adafruit GFX assumes pixels are square, but this is not true of ESP_8_BIT
which has nonsquare pixels. (4:3 aspect ratio in a 256x240 frame buffer.)
Circles will look squashed as wide ovals, etc. This version of the API does
not offer any way to compensate, the caller has to deal with it.
Copyright (c) Roger Cheng
MIT License
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.
*/
#ifndef ESP_8_BIT_GFX_H
#define ESP_8_BIT_GFX_H
#include "Arduino.h"
#include "Adafruit_GFX.h"
#include "ESP_8_BIT_composite.h"
/*
* @brief Expose Adafruit GFX API for ESP_8_BIT composite video generator
*/
class ESP_8_BIT_GFX : public Adafruit_GFX {
public:
/*
* @brief Constructor
* @param ntsc true for NTSC, false for PAL
* @param colorDepth 8 to treat color as 8-bit directly, 16 to perform
* downconversion from 16-bit RGB565 color to 8-bit RGB332.
*/
ESP_8_BIT_GFX(bool ntsc, uint8_t colorDepth);
/*
* @brief Call once to set up the API with self-allocated frame buffer.
*/
void begin();
/*
* @brief Wait for swap of front and back buffer. Gathers performance
* metrics while waiting.
*/
void waitForFrame();
/*
* @brief Fraction of time in waitForFrame() in percent of percent.
* @return Number range from 0 to 10000. Higher values indicate more time
* has been spent waiting for buffer swap, implying the rest of the code
* ran faster and completed more quickly.
*/
uint32_t getWaitFraction();
/*
* @brief Ends the current performance tracking session and start a new
* one. Useful for isolating sections of code for measurement.
* @note Sessions are still terminated whenever CPU clock counter
* overflows (every ~18 seconds @ 240MHz) so some data may still be lost.
* @return Number range from 0 to 10000. Higher values indicate more time
* has been spent waiting for buffer swap, implying the rest of the code
* ran faster and completed more quickly.
*/
uint32_t newPerformanceTrackingSession();
/*
* @brief Utility to convert from 16-bit RGB565 color to 8-bit RGB332 color
*/
uint8_t convertRGB565toRGB332(uint16_t color);
/*
* @brief Required Adafruit_GFX override to put a pixel on screen
*/
void drawPixel(int16_t x, int16_t y, uint16_t color) override;
/*
* @brief Optional Adafruit_GFX overrides for performance
*/
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
void fillScreen(uint16_t color) override;
/*
* @brief Set this to true if the frame buffer should be copied upon every
* swap of the front/back buffer. Defaults to false.
* @note Some graphics libraries act on delta from previous frame, so the
* front and buffers need to be in sync to avoid visual artifacts.
*/
bool copyAfterSwap;
private:
/*
* @brief Given input X-coordinate, return value clamped within valid range.
*/
int16_t clampX(int16_t inputX);
/*
* @brief Given input Y-coordinate, return value clamped within valid range.
*/
int16_t clampY(int16_t inputY);
/*
* @brief Whether to treat color as 8 or 16 bit color values
*/
uint8_t _colorDepth;
/*
* @brief Internal reference to ESP_8_BIT video generator wrapper class
*/
ESP_8_BIT_composite* _pVideo;
/*
* @brief Retrieve color to use depending on _colorDepth
*/
uint8_t getColor8(uint16_t color);
/////////////////////////////////////////////////////////////////////////
//
// Performance metric data
//
// The Tensilica core in an ESP32 keeps a count of clock cycles read via
// xthal_get_ccount(). This is only a 32-bit unsigned value. So when the
// core is running at 240MHz we have just under 18 seconds before this
// value overflows.
//
// Rather than trying to make error-prone and expensive calculations to
// account for clock count overflows, this performance tracking is
// divided up into sessions. Every ~18 seconds the clock count overflow,
// we start a new session. Performance data of gaps between sessions
// are lost.
//
// Each sessions retrieves from the underlying rendering class two pieces
// of data: the number of frames rendered to screen and the number of
// buffer swaps performed. These are uint32_t. When they overflow, the
// frame count related statistics will be nonsensical for that session.
// The values should make sense again for the following session.
//
// Performance data is only gathered during waitForFrame(), which assumes
// the application is calling waitForFrame() at high rate so we can
// sample performance data. Applications that do not call waitForFrame()
// frequently may experience large session gaps of lost data. If
// waitForFrame() is not called for more than 18 seconds, the data will
// be nonsensical. Fortunately applications that do not make frequent
// frame updates are probably not concerned with performance data anyway.
//
// Clock cycle count is a value kept by a core. They are not synchronized
// across multiple ESP32 cores. Trying to calculate from cycle counts
// from different cores will result in nonsensical data. This is usually
// not a problem as the typical usage has Arduino runtime pinned to a
// single core.
//
// These metrics track the number of clocks we spend waiting, but that
// includes both idle clock cycles and clock cycles consumed by other
// code. Including our underlying rendering class! The percentage is
// valid for relative comparisons. "Algorithm A leaves lower percentage
// waiting than B, so B is faster" is a valid conclusion. However
// inferring from absolute numbers are not valid. For example "We wait
// 50% of the time so we have enough power for twice the work" would be
// wrong. Some of that 50% wait time is used by other code and not free
// for use.
//
// The tradeoff for the limitations above is that we have a very
// lightweight performance tracker that imposes minimal overhead. But
// take care interpreting its numbers!
/*
* @brief Number of clock counts spent waiting for frame buffer swap.
*/
uint32_t _waitTally;
/*
* @brief Clock count value at the start of a session.
*/
uint32_t _perfStart;
/*
* @brief Clock count value at the end of a session.
*/
uint32_t _perfEnd;
/*
* @brief Number of frames rendered at the start of a session
*/
uint32_t _frameStart;
/*
* @brief Number of buffer swaps performed at the start of a session
*/
uint32_t _swapStart;
/*
* @brief Calculate performance metrics, output as INFO log.
* @return Number range from 0 to 10000. Higher values indicate more time
* has been spent waiting for buffer swap, implying the rest of the code
* ran faster and completed more quickly.
*/
uint32_t perfData();
};
#endif // #ifndef ESP_8_BIT_GFX_H

850
ESP_8_BIT_composite.cpp

@ -0,0 +1,850 @@
/* Copyright (c) 2020, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
/*
** Extracted from Peter Barrett's ESP_8_BIT project and adapted to Arduino
** library by Roger Cheng
*/
#include "ESP_8_BIT_composite.h"
static const char *TAG = "ESP_8_BIT";
static ESP_8_BIT_composite* _instance_ = NULL;
static int _pal_ = 0;
//====================================================================================================
//====================================================================================================
//
// low level HW setup of DAC/DMA/APLL/PWM
//
lldesc_t _dma_desc[4] = {0};
intr_handle_t _isr_handle;
extern "C"
void IRAM_ATTR video_isr(volatile void* buf);
// simple isr
void IRAM_ATTR i2s_intr_handler_video(void *arg)
{
if (I2S0.int_st.out_eof)
video_isr(((lldesc_t*)I2S0.out_eof_des_addr)->buf); // get the next line of video
I2S0.int_clr.val = I2S0.int_st.val; // reset the interrupt
}
static esp_err_t start_dma(int line_width,int samples_per_cc, int ch = 1)
{
periph_module_enable(PERIPH_I2S0_MODULE);
// setup interrupt
if (esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
i2s_intr_handler_video, 0, &_isr_handle) != ESP_OK)
return -1;
// reset conf
I2S0.conf.val = 1;
I2S0.conf.val = 0;
I2S0.conf.tx_right_first = 1;
I2S0.conf.tx_mono = (ch == 2 ? 0 : 1);
I2S0.conf2.lcd_en = 1;
I2S0.fifo_conf.tx_fifo_mod_force_en = 1;
I2S0.sample_rate_conf.tx_bits_mod = 16;
I2S0.conf_chan.tx_chan_mod = (ch == 2) ? 0 : 1;
// Create TX DMA buffers
for (int i = 0; i < 2; i++) {
int n = line_width*2*ch;
if (n >= 4092) {
printf("DMA chunk too big:%s\n",n);
return -1;
}
_dma_desc[i].buf = (uint8_t*)heap_caps_calloc(1, n, MALLOC_CAP_DMA);
if (!_dma_desc[i].buf)
return -1;
_dma_desc[i].owner = 1;
_dma_desc[i].eof = 1;
_dma_desc[i].length = n;
_dma_desc[i].size = n;
_dma_desc[i].empty = (uint32_t)(i == 1 ? _dma_desc : _dma_desc+1);
}
I2S0.out_link.addr = (uint32_t)_dma_desc;
// Setup up the apll: See ref 3.2.7 Audio PLL
// f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000;
// f_out = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536); // 250 < f_out < 500
// apll_freq = f_out/((o_div + 2) * 2)
// operating range of the f_out is 250 MHz ~ 500 MHz
// operating range of the apll_freq is 16 ~ 128 MHz.
// select sdm0,sdm1,sdm2 to produce nice multiples of colorburst frequencies
// see calc_freq() for math: (4+a)*10/((2 + b)*2) mhz
// up to 20mhz seems to work ok:
// rtc_clk_apll_enable(1,0x00,0x00,0x4,0); // 20mhz for fancy DDS
if (!_pal_) {
switch (samples_per_cc) {
case 3: rtc_clk_apll_enable(1,0x46,0x97,0x4,2); break; // 10.7386363636 3x NTSC (10.7386398315mhz)
case 4: rtc_clk_apll_enable(1,0x46,0x97,0x4,1); break; // 14.3181818182 4x NTSC (14.3181864421mhz)
}
} else {
rtc_clk_apll_enable(1,0x04,0xA4,0x6,1); // 17.734476mhz ~4x PAL
}
I2S0.clkm_conf.clkm_div_num = 1; // I2S clock divider’s integral value.
I2S0.clkm_conf.clkm_div_b = 0; // Fractional clock divider’s numerator value.
I2S0.clkm_conf.clkm_div_a = 1; // Fractional clock divider’s denominator value
I2S0.sample_rate_conf.tx_bck_div_num = 1;
I2S0.clkm_conf.clka_en = 1; // Set this bit to enable clk_apll.
I2S0.fifo_conf.tx_fifo_mod = (ch == 2) ? 0 : 1; // 32-bit dual or 16-bit single channel data
dac_output_enable(DAC_CHANNEL_1); // DAC, video on GPIO25
dac_i2s_enable(); // start DAC!
I2S0.conf.tx_start = 1; // start DMA!
I2S0.int_clr.val = 0xFFFFFFFF;
I2S0.int_ena.out_eof = 1;
I2S0.out_link.start = 1;
return esp_intr_enable(_isr_handle); // start interruprs!
}
void video_init_hw(int line_width, int samples_per_cc)
{
// setup apll 4x NTSC or PAL colorburst rate
start_dma(line_width,samples_per_cc,1);
// Now ideally we would like to use the decoupled left DAC channel to produce audio
// But when using the APLL there appears to be some clock domain conflict that causes
// nasty digitial spikes and dropouts.
}
//====================================================================================================
//====================================================================================================
// ntsc phase representation of a rrrgggbb pixel
// must be in RAM so VBL works
const static DRAM_ATTR uint32_t ntsc_RGB332[256] = {
0x18181818,0x18171A1C,0x1A151D22,0x1B141F26,0x1D1C1A1B,0x1E1B1C20,0x20191F26,0x2119222A,
0x23201C1F,0x241F1E24,0x251E222A,0x261D242E,0x29241F23,0x2A232128,0x2B22242E,0x2C212632,
0x2E282127,0x2F27232C,0x31262732,0x32252936,0x342C232B,0x352B2630,0x372A2936,0x38292B3A,
0x3A30262F,0x3B2F2833,0x3C2E2B3A,0x3D2D2E3E,0x40352834,0x41342B38,0x43332E3E,0x44323042,
0x181B1B18,0x191A1D1C,0x1B192022,0x1C182327,0x1E1F1D1C,0x1F1E2020,0x201D2326,0x211C252B,
0x24232020,0x25222224,0x2621252A,0x2720272F,0x29272224,0x2A262428,0x2C25282E,0x2D242A33,
0x2F2B2428,0x302A272C,0x32292A32,0x33282C37,0x352F272C,0x362E2930,0x372D2C36,0x382C2F3B,
0x3B332930,0x3C332B34,0x3D312F3A,0x3E30313F,0x41382C35,0x42372E39,0x4336313F,0x44353443,
0x191E1E19,0x1A1D211D,0x1B1C2423,0x1C1B2628,0x1F22211D,0x20212321,0x21202627,0x221F292C,
0x24262321,0x25252525,0x2724292B,0x28232B30,0x2A2A2625,0x2B292829,0x2D282B2F,0x2E272D34,
0x302E2829,0x312E2A2D,0x322C2D33,0x332B3038,0x36332A2D,0x37322C31,0x38303037,0x392F323C,
0x3B372D31,0x3C362F35,0x3E35323B,0x3F343440,0x423B2F36,0x423A313A,0x44393540,0x45383744,
0x1A21221A,0x1B20241E,0x1C1F2724,0x1D1E2A29,0x1F25241E,0x20242622,0x22232A28,0x23222C2D,
0x25292722,0x26292926,0x27272C2C,0x28262E30,0x2B2E2926,0x2C2D2B2A,0x2D2B2E30,0x2E2A3134,
0x31322B2A,0x32312E2E,0x332F3134,0x342F3338,0x36362E2E,0x37353032,0x39343338,0x3A33363C,
0x3C3A3032,0x3D393236,0x3E38363C,0x3F373840,0x423E3337,0x433E353B,0x453C3841,0x463B3A45,
0x1A24251B,0x1B24271F,0x1D222B25,0x1E212D29,0x2029281F,0x21282A23,0x22262D29,0x23252F2D,
0x262D2A23,0x272C2C27,0x282A2F2D,0x292A3231,0x2C312C27,0x2C302F2B,0x2E2F3231,0x2F2E3435,
0x31352F2B,0x3234312F,0x34333435,0x35323739,0x3739312F,0x38383333,0x39373739,0x3A36393D,
0x3D3D3433,0x3E3C3637,0x3F3B393D,0x403A3B41,0x43423637,0x4441383B,0x453F3C42,0x463F3E46,
0x1B28291C,0x1C272B20,0x1D252E26,0x1E25302A,0x212C2B20,0x222B2D24,0x232A312A,0x2429332E,
0x26302D24,0x272F3028,0x292E332E,0x2A2D3532,0x2C343028,0x2D33322C,0x2F323532,0x30313836,
0x3238322C,0x33373430,0x34363836,0x35353A3A,0x383C3530,0x393B3734,0x3A3A3A3A,0x3B393C3E,
0x3D403734,0x3E403938,0x403E3C3E,0x413D3F42,0x44453A38,0x45443C3C,0x46433F42,0x47424147,
0x1C2B2C1D,0x1D2A2E21,0x1E293227,0x1F28342B,0x212F2E21,0x222E3125,0x242D342B,0x252C362F,
0x27333125,0x28323329,0x2A31362F,0x2B303933,0x2D373329,0x2E36352D,0x2F353933,0x30343B37,
0x333B362D,0x343B3831,0x35393B37,0x36383D3B,0x38403831,0x393F3A35,0x3B3D3E3B,0x3C3C403F,
0x3E443A35,0x3F433D39,0x4141403F,0x42414243,0x44483D39,0x45473F3D,0x47464243,0x48454548,
0x1C2E301E,0x1D2E3222,0x1F2C3528,0x202B382C,0x22333222,0x23323426,0x2530382C,0x262F3A30,
0x28373526,0x2936372A,0x2A343A30,0x2B343C34,0x2E3B372A,0x2F3A392E,0x30393C34,0x31383F38,
0x333F392E,0x343E3C32,0x363D3F38,0x373C413C,0x39433C32,0x3A423E36,0x3C41413C,0x3D404440,
0x3F473E36,0x4046403A,0x41454440,0x42444644,0x454C413A,0x464B433E,0x47494644,0x49494949,
};
// PAL yuyv palette, must be in RAM
const static DRAM_ATTR uint32_t pal_yuyv[] = {
0x18181818,0x1A16191E,0x1E121A26,0x21101A2C,0x1E1D1A1B,0x211B1A20,0x25171B29,0x27151C2E,
0x25231B1E,0x27201C23,0x2B1D1D2B,0x2E1A1E31,0x2B281D20,0x2E261E26,0x31221F2E,0x34202034,
0x322D1F23,0x342B2029,0x38282131,0x3A252137,0x38332126,0x3A30212B,0x3E2D2234,0x412A2339,
0x3E382229,0x4136232E,0x44322436,0x4730253C,0x453E242C,0x483C2531,0x4B382639,0x4E36273F,
0x171B1D19,0x1A181E1F,0x1D151F27,0x20121F2D,0x1E201F1C,0x201E1F22,0x241A202A,0x26182130,
0x2425201F,0x27232124,0x2A20222D,0x2D1D2332,0x2A2B2222,0x2D282327,0x3125242F,0x33222435,
0x31302424,0x332E242A,0x372A2632,0x3A282638,0x37362627,0x3A33262D,0x3D302735,0x402D283B,
0x3E3B272A,0x4039282F,0x44352938,0x46332A3D,0x4441292D,0x473E2A32,0x4B3B2B3B,0x4D382C40,
0x171D221B,0x191B2220,0x1D182329,0x1F15242E,0x1D23231E,0x1F202423,0x231D252B,0x261A2631,
0x23282520,0x26262626,0x2A22272E,0x2C202834,0x2A2E2723,0x2C2B2829,0x30282931,0x33252937,
0x30332926,0x3331292B,0x362D2A34,0x392B2B39,0x36382A29,0x39362B2E,0x3D322C36,0x3F302D3C,
0x3D3E2C2B,0x3F3B2D31,0x43382E39,0x46352F3F,0x44432E2E,0x46412F34,0x4A3E303C,0x4D3B3042,
0x1620271C,0x181E2722,0x1C1A282A,0x1F182930,0x1C26281F,0x1F232924,0x22202A2D,0x251D2B32,
0x232B2A22,0x25292B27,0x29252C30,0x2B232C35,0x29302C24,0x2C2E2C2A,0x2F2A2D32,0x32282E38,
0x2F362D27,0x32332E2D,0x36302F35,0x382D303B,0x363B2F2A,0x38393030,0x3C353138,0x3F33323E,
0x3C40312D,0x3F3E3232,0x423A333B,0x45383340,0x43463330,0x46443435,0x4940353E,0x4C3E3543,
0x15232B1E,0x18212C23,0x1B1D2D2B,0x1E1B2E31,0x1C282D20,0x1E262E26,0x22222F2E,0x24202F34,
0x222E2F23,0x242B3029,0x28283131,0x2B253137,0x28333126,0x2B31312B,0x2F2D3234,0x312B3339,
0x2F383229,0x3136332E,0x35323436,0x3730353C,0x353E342B,0x383B3531,0x3B383639,0x3E35363F,
0x3B43362E,0x3E413634,0x423D373C,0x443B3842,0x42493831,0x45473837,0x4943393F,0x4B413A45,
0x1526301F,0x17233125,0x1B20322D,0x1D1D3333,0x1B2B3222,0x1D293327,0x21253430,0x24233435,
0x21303425,0x242E342A,0x272A3532,0x2A283638,0x28363527,0x2A33362D,0x2E303735,0x302D383B,
0x2E3B372A,0x30393830,0x34353938,0x37333A3E,0x3440392D,0x373E3A32,0x3B3B3B3B,0x3D383B40,
0x3B463B30,0x3D433B35,0x41403C3D,0x443D3D43,0x424C3D33,0x44493D38,0x48463E40,0x4A433F46,
0x14283520,0x16263626,0x1A23372E,0x1D203734,0x1A2E3723,0x1D2B3729,0x20283831,0x23253937,
0x21333826,0x2331392B,0x272D3A34,0x292B3B39,0x27383A29,0x29363B2E,0x2D333C36,0x30303D3C,
0x2D3E3C2B,0x303B3D31,0x34383E39,0x36363E3F,0x34433E2E,0x36413E34,0x3A3D3F3C,0x3C3B4042,
0x3A493F31,0x3D464036,0x4043413F,0x43404244,0x414E4134,0x434C4239,0x47484342,0x4A464447,
0x132B3A22,0x16293B27,0x19253C30,0x1C233D35,0x19313C25,0x1C2E3D2A,0x202B3E32,0x22283E38,
0x20363E27,0x22343E2D,0x26303F35,0x292E403B,0x263B3F2A,0x29394030,0x2C364138,0x2F33423E,
0x2D41412D,0x2F3E4232,0x333B433B,0x35384440,0x33464330,0x35444435,0x3940453E,0x3C3E4543,
0x394C4533,0x3C494538,0x40464640,0x42434746,0x40514735,0x434F473B,0x464B4843,0x49494949,
//odd
0x18181818,0x19161A1E,0x1A121E26,0x1A10212C,0x1A1D1E1B,0x1A1B2120,0x1B172529,0x1C15272E,
0x1B23251E,0x1C202723,0x1D1D2B2B,0x1E1A2E31,0x1D282B20,0x1E262E26,0x1F22312E,0x20203434,
0x1F2D3223,0x202B3429,0x21283831,0x21253A37,0x21333826,0x21303A2B,0x222D3E34,0x232A4139,
0x22383E29,0x2336412E,0x24324436,0x2530473C,0x243E452C,0x253C4831,0x26384B39,0x27364E3F,
0x1D1B1719,0x1E181A1F,0x1F151D27,0x1F12202D,0x1F201E1C,0x1F1E2022,0x201A242A,0x21182630,
0x2025241F,0x21232724,0x22202A2D,0x231D2D32,0x222B2A22,0x23282D27,0x2425312F,0x24223335,
0x24303124,0x242E332A,0x262A3732,0x26283A38,0x26363727,0x26333A2D,0x27303D35,0x282D403B,
0x273B3E2A,0x2839402F,0x29354438,0x2A33463D,0x2941442D,0x2A3E4732,0x2B3B4B3B,0x2C384D40,
0x221D171B,0x221B1920,0x23181D29,0x24151F2E,0x23231D1E,0x24201F23,0x251D232B,0x261A2631,
0x25282320,0x26262626,0x27222A2E,0x28202C34,0x272E2A23,0x282B2C29,0x29283031,0x29253337,
0x29333026,0x2931332B,0x2A2D3634,0x2B2B3939,0x2A383629,0x2B36392E,0x2C323D36,0x2D303F3C,
0x2C3E3D2B,0x2D3B3F31,0x2E384339,0x2F35463F,0x2E43442E,0x2F414634,0x303E4A3C,0x303B4D42,
0x2720161C,0x271E1822,0x281A1C2A,0x29181F30,0x28261C1F,0x29231F24,0x2A20222D,0x2B1D2532,
0x2A2B2322,0x2B292527,0x2C252930,0x2C232B35,0x2C302924,0x2C2E2C2A,0x2D2A2F32,0x2E283238,
0x2D362F27,0x2E33322D,0x2F303635,0x302D383B,0x2F3B362A,0x30393830,0x31353C38,0x32333F3E,
0x31403C2D,0x323E3F32,0x333A423B,0x33384540,0x33464330,0x34444635,0x3540493E,0x353E4C43,
0x2B23151E,0x2C211823,0x2D1D1B2B,0x2E1B1E31,0x2D281C20,0x2E261E26,0x2F22222E,0x2F202434,
0x2F2E2223,0x302B2429,0x31282831,0x31252B37,0x31332826,0x31312B2B,0x322D2F34,0x332B3139,
0x32382F29,0x3336312E,0x34323536,0x3530373C,0x343E352B,0x353B3831,0x36383B39,0x36353E3F,
0x36433B2E,0x36413E34,0x373D423C,0x383B4442,0x38494231,0x38474537,0x3943493F,0x3A414B45,
0x3026151F,0x31231725,0x32201B2D,0x331D1D33,0x322B1B22,0x33291D27,0x34252130,0x34232435,
0x34302125,0x342E242A,0x352A2732,0x36282A38,0x35362827,0x36332A2D,0x37302E35,0x382D303B,
0x373B2E2A,0x38393030,0x39353438,0x3A33373E,0x3940342D,0x3A3E3732,0x3B3B3B3B,0x3B383D40,
0x3B463B30,0x3B433D35,0x3C40413D,0x3D3D4443,0x3D4C4233,0x3D494438,0x3E464840,0x3F434A46,
0x35281420,0x36261626,0x37231A2E,0x37201D34,0x372E1A23,0x372B1D29,0x38282031,0x39252337,
0x38332126,0x3931232B,0x3A2D2734,0x3B2B2939,0x3A382729,0x3B36292E,0x3C332D36,0x3D30303C,
0x3C3E2D2B,0x3D3B3031,0x3E383439,0x3E36363F,0x3E43342E,0x3E413634,0x3F3D3A3C,0x403B3C42,
0x3F493A31,0x40463D36,0x4143403F,0x42404344,0x414E4134,0x424C4339,0x43484742,0x44464A47,
0x3A2B1322,0x3B291627,0x3C251930,0x3D231C35,0x3C311925,0x3D2E1C2A,0x3E2B2032,0x3E282238,
0x3E362027,0x3E34222D,0x3F302635,0x402E293B,0x3F3B262A,0x40392930,0x41362C38,0x42332F3E,
0x41412D2D,0x423E2F32,0x433B333B,0x44383540,0x43463330,0x44443535,0x4540393E,0x453E3C43,
0x454C3933,0x45493C38,0x46464040,0x47434246,0x47514035,0x474F433B,0x484B4643,0x49494949,
};
//====================================================================================================
//====================================================================================================
uint32_t cpu_ticks()
{
return xthal_get_ccount();
}
uint32_t us() {
return cpu_ticks()/240;
}
// Color clock frequency is 315/88 (3.57954545455)
// DAC_MHZ is 315/11 or 8x color clock
// 455/2 color clocks per line, round up to maintain phase
// HSYNCH period is 44/315*455 or 63.55555..us
// Field period is 262*44/315*455 or 16651.5555us
#define IRE(_x) ((uint32_t)(((_x)+40)*255/3.3/147.5) << 8) // 3.3V DAC
#define SYNC_LEVEL IRE(-40)
#define BLANKING_LEVEL IRE(0)
#define BLACK_LEVEL IRE(7.5)
#define GRAY_LEVEL IRE(50)
#define WHITE_LEVEL IRE(100)
#define P0 (color >> 16)
#define P1 (color >> 8)
#define P2 (color)
#define P3 (color << 8)
// Double-buffering: _bufferA and _bufferB will be swapped back and forth.
static uint8_t** _bufferA;
static uint8_t** _bufferB;
// _lines may point to either _bufferA or _bufferB, depending on which is being displayed
// _backBuffer points to whichever one _lines is not pointing to
static uint8_t** _lines; // Front buffer currently on display
static uint8_t** _backBuffer; // Back buffer waiting to be swapped to front
// TRUE when _backBuffer is ready to go.
static bool _swapReady;
// Notification handle once front and back buffers have been swapped.
static TaskHandle_t _swapCompleteNotify;
// Number of swaps completed
static uint32_t _swap_counter = 0;
volatile int _line_counter = 0;
volatile uint32_t _frame_counter = 0;
int _active_lines;
int _line_count;
int _line_width;
int _samples_per_cc;
const uint32_t* _palette;
float _sample_rate;
int _hsync;
int _hsync_long;
int _hsync_short;
int _burst_start;
int _burst_width;
int _active_start;
int16_t* _burst0 = 0; // pal bursts
int16_t* _burst1 = 0;
static int usec(float us)
{
uint32_t r = (uint32_t)(us*_sample_rate);
return ((r + _samples_per_cc)/(_samples_per_cc << 1))*(_samples_per_cc << 1); // multiple of color clock, word align
}
#define NTSC_COLOR_CLOCKS_PER_SCANLINE 228 // really 227.5 for NTSC but want to avoid half phase fiddling for now
#define NTSC_FREQUENCY (315000000.0/88)
#define NTSC_LINES 262
#define PAL_COLOR_CLOCKS_PER_SCANLINE 284 // really 283.75 ?
#define PAL_FREQUENCY 4433618.75
#define PAL_LINES 312
void pal_init();
void video_init(int samples_per_cc, int ntsc)
{
_samples_per_cc = samples_per_cc;
if (ntsc) {
_sample_rate = 315.0/88 * samples_per_cc; // DAC rate
_line_width = NTSC_COLOR_CLOCKS_PER_SCANLINE*samples_per_cc;
_line_count = NTSC_LINES;
_hsync_long = usec(63.555-4.7);
_active_start = usec(samples_per_cc == 4 ? 10 : 10.5);
_hsync = usec(4.7);
_palette = ntsc_RGB332;
_pal_ = 0;
} else {
pal_init();
_palette = pal_yuyv;
_pal_ = 1;
}
_active_lines = 240;
video_init_hw(_line_width,_samples_per_cc); // init the hardware
}
//===================================================================================================
//===================================================================================================
// PAL
void pal_init()
{
int cc_width = 4;
_sample_rate = PAL_FREQUENCY*cc_width/1000000.0; // DAC rate in mhz
_line_width = PAL_COLOR_CLOCKS_PER_SCANLINE*cc_width;
_line_count = PAL_LINES;
_hsync_short = usec(2);
_hsync_long = usec(30);
_hsync = usec(4.7);
_burst_start = usec(5.6);
_burst_width = (int)(10*cc_width + 4) & 0xFFFE;
_active_start = usec(10.4);
// make colorburst tables for even and odd lines
_burst0 = new int16_t[_burst_width];
_burst1 = new int16_t[_burst_width];
float phase = 2*M_PI/2;
for (int i = 0; i < _burst_width; i++)
{
_burst0[i] = BLANKING_LEVEL + sin(phase + 3*M_PI/4) * BLANKING_LEVEL/1.5;
_burst1[i] = BLANKING_LEVEL + sin(phase - 3*M_PI/4) * BLANKING_LEVEL/1.5;
phase += 2*M_PI/cc_width;
}
}
void IRAM_ATTR blit_pal(uint8_t* src, uint16_t* dst)
{
uint32_t c,color;
bool even = _line_counter & 1;
const uint32_t* p = even ? _palette : _palette + 256;
int left = 0;
int right = 256;
uint8_t mask = 0xFF;
uint8_t c0,c1,c2,c3,c4;
uint8_t y1,y2,y3;
// 192 of 288 color clocks wide: roughly correct aspect ratio
dst += 88;
// 4 pixels over 3 color clocks, 12 samples
// do the blitting
for (int i = left; i < right; i += 4) {
c = *((uint32_t*)(src+i));
color = p[c & mask];
dst[0^1] = P0;
dst[1^1] = P1;
dst[2^1] = P2;
color = p[(c >> 8) & mask];
dst[3^1] = P3;
dst[4^1] = P0;
dst[5^1] = P1;
color = p[(c >> 16) & mask];
dst[6^1] = P2;
dst[7^1] = P3;
dst[8^1] = P0;
color = p[(c >> 24) & mask];
dst[9^1] = P1;
dst[10^1] = P2;
dst[11^1] = P3;
dst += 12;
}
}
void IRAM_ATTR burst_pal(uint16_t* line)
{
line += _burst_start;
int16_t* b = (_line_counter & 1) ? _burst0 : _burst1;
for (int i = 0; i < _burst_width; i += 2) {
line[i^1] = b[i];
line[(i+1)^1] = b[i+1];
}
}
//===================================================================================================
//===================================================================================================
// ntsc tables
// AA AA // 2 pixels, 1 color clock - atari
// AA AB BB // 3 pixels, 2 color clocks - nes
// AAA ABB BBC CCC // 4 pixels, 3 color clocks - sms
// cc == 3 gives 684 samples per line, 3 samples per cc, 3 pixels for 2 cc
// cc == 4 gives 912 samples per line, 4 samples per cc, 2 pixels per cc
#ifdef PERF
#define BEGIN_TIMING() uint32_t t = cpu_ticks()
#define END_TIMING() t = cpu_ticks() - t; _blit_ticks_min = min(_blit_ticks_min,t); _blit_ticks_max = max(_blit_ticks_max,t);
#define ISR_BEGIN() uint32_t t = cpu_ticks()
#define ISR_END() t = cpu_ticks() - t;_isr_us += (t+120)/240;
uint32_t _blit_ticks_min = 0;
uint32_t _blit_ticks_max = 0;
uint32_t _isr_us = 0;
#else
#define BEGIN_TIMING()
#define END_TIMING()
#define ISR_BEGIN()
#define ISR_END()
#endif
// draw a line of game in NTSC
void IRAM_ATTR blit(uint8_t* src, uint16_t* dst)
{
uint32_t* d = (uint32_t*)dst;
const uint32_t* p = _palette;
uint32_t color,c;
uint32_t mask = 0xFF;
int i;
BEGIN_TIMING();
if (_pal_) {
blit_pal(src,dst);
END_TIMING();
return;
}
// AAA ABB BBC CCC
// 4 pixels, 3 color clocks, 4 samples per cc
// each pixel gets 3 samples, 192 color clocks wide
for (i = 0; i < 256; i += 4) {
c = *((uint32_t*)(src+i));
color = p[c & mask];
dst[0^1] = P0;
dst[1^1] = P1;
dst[2^1] = P2;
color = p[(c >> 8) & mask];
dst[3^1] = P3;
dst[4^1] = P0;
dst[5^1] = P1;
color = p[(c >> 16) & mask];
dst[6^1] = P2;
dst[7^1] = P3;
dst[8^1] = P0;
color = p[(c >> 24) & mask];
dst[9^1] = P1;
dst[10^1] = P2;
dst[11^1] = P3;
dst += 12;
}
END_TIMING();
}
void IRAM_ATTR burst(uint16_t* line)
{
if (_pal_) {
burst_pal(line);
return;
}
int i,phase;
switch (_samples_per_cc) {
case 4:
// 4 samples per color clock
for (i = _hsync; i < _hsync + (4*10); i += 4) {
line[i+1] = BLANKING_LEVEL;
line[i+0] = BLANKING_LEVEL + BLANKING_LEVEL/2;
line[i+3] = BLANKING_LEVEL;
line[i+2] = BLANKING_LEVEL - BLANKING_LEVEL/2;
}
break;
case 3:
// 3 samples per color clock
phase = 0.866025*BLANKING_LEVEL/2;
for (i = _hsync; i < _hsync + (3*10); i += 6) {
line[i+1] = BLANKING_LEVEL;
line[i+0] = BLANKING_LEVEL + phase;
line[i+3] = BLANKING_LEVEL - phase;
line[i+2] = BLANKING_LEVEL;
line[i+5] = BLANKING_LEVEL + phase;
line[i+4] = BLANKING_LEVEL - phase;
}
break;
}
}
void IRAM_ATTR sync(uint16_t* line, int syncwidth)
{
for (int i = 0; i < syncwidth; i++)
line[i] = SYNC_LEVEL;
}
void IRAM_ATTR blanking(uint16_t* line, bool vbl)
{
int syncwidth = vbl ? _hsync_long : _hsync;
sync(line,syncwidth);
for (int i = syncwidth; i < _line_width; i++)
line[i] = BLANKING_LEVEL;
if (!vbl)
burst(line); // no burst during vbl
}
// Fancy pal non-interlace
// http://martin.hinner.info/vga/pal.html
void IRAM_ATTR pal_sync2(uint16_t* line, int width, int swidth)
{
swidth = swidth ? _hsync_long : _hsync_short;
int i;
for (i = 0; i < swidth; i++)
line[i] = SYNC_LEVEL;
for (; i < width; i++)
line[i] = BLANKING_LEVEL;
}
uint8_t DRAM_ATTR _sync_type[8] = {0,0,0,3,3,2,0,0};
void IRAM_ATTR pal_sync(uint16_t* line, int i)
{
uint8_t t = _sync_type[i-304];
pal_sync2(line,_line_width/2, t & 2);
pal_sync2(line+_line_width/2,_line_width/2, t & 1);
}
// Wait for front and back buffers to swap before starting drawing
void video_sync()
{
if (!_lines)
return;
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
}
// Workhorse ISR handles audio and video updates
extern "C"
void IRAM_ATTR video_isr(volatile void* vbuf)
{
if (!_lines)
return;
ISR_BEGIN();
int i = _line_counter++;
uint16_t* buf = (uint16_t*)vbuf;
if (_pal_) {
// pal
if (i < 32) {
blanking(buf,false); // pre render/black 0-32
} else if (i < _active_lines + 32) { // active video 32-272
sync(buf,_hsync);
burst(buf);
blit(_lines[i-32],buf + _active_start);
} else if (i < 304) { // post render/black 272-304
blanking(buf,false);
} else {
pal_sync(buf,i); // 8 lines of sync 304-312
}
} else {
// ntsc
if (i < _active_lines) { // active video
sync(buf,_hsync);
burst(buf);
blit(_lines[i],buf + _active_start);
} else if (i < (_active_lines + 5)) { // post render/black
blanking(buf,false);
} else if (i < (_active_lines + 8)) { // vsync
blanking(buf,true);
} else { // pre render/black
blanking(buf,false);
}
}
if (_line_counter == _line_count) {
_line_counter = 0; // frame is done
_frame_counter++;
// Is the back buffer ready to go?
if (_swapReady) {
// Swap front and back buffers
if (_lines == _bufferA) {
_lines = _bufferB;
_backBuffer = _bufferA;
} else {
_lines = _bufferA;
_backBuffer = _bufferB;
}
_swapReady = false;
_swap_counter++;
// Signal video_sync() swap has completed
vTaskNotifyGiveFromISR(
_swapCompleteNotify,
NULL);
}
}
ISR_END();
}
//===================================================================================================
//===================================================================================================
// Wrapper class
/*
* @brief Constructor for ESP_8_BIT composite video wrapper class
* @param ntsc True (or nonzero) for NTSC mode, False (or zero) for PAL mode
*/
ESP_8_BIT_composite::ESP_8_BIT_composite(int ntsc)
{
_pal_ = !ntsc;
if (NULL == _instance_)
{
_instance_ = this;
}
_started = false;
_bufferA = NULL;
_bufferB = NULL;
}
/*
* @brief Destructor for ESP_8_BIT composite video wrapper class.
*/
ESP_8_BIT_composite::~ESP_8_BIT_composite()
{
if(_bufferA)
{
frameBufferFree(_bufferA);
_bufferA= NULL;
}
if(_bufferB)
{
frameBufferFree(_bufferB);
_bufferB= NULL;
}
if (_started)
{
// Free resources by mirroring everything allocated in start_dma()
esp_intr_disable(_isr_handle);
dac_i2s_disable();
dac_output_disable(DAC_CHANNEL_1);
if (!_pal_) {
rtc_clk_apll_enable(false,0x46,0x97,0x4,1);
} else {
rtc_clk_apll_enable(false,0x04,0xA4,0x6,1);
}
for (int i = 0; i < 2; i++) {
heap_caps_free((void*)(_dma_desc[i].buf));
_dma_desc[i].buf = NULL;
}
// Missing: There doesn't seem to be a esp_intr_free() to go with esp_intr_alloc()?
periph_module_disable(PERIPH_I2S0_MODULE);
_started = false;
}
_lines = NULL;
_backBuffer = NULL;
_instance_ = NULL;
}
/*
* @brief Check to ensure this instance is the first and only allowed instance
*/
void ESP_8_BIT_composite::instance_check()
{
if (_instance_ != this)
{
ESP_LOGE(TAG, "Only one instance of ESP_8_BIT_composite class is allowed.");
ESP_ERROR_CHECK(ESP_FAIL);
}
}
/*
* @brief Video subsystem setup: allocate frame buffer and start engine
*/
void ESP_8_BIT_composite::begin()
{
instance_check();
if (_started)
{
ESP_LOGE(TAG, "begin() is only allowed to be called once.");
ESP_ERROR_CHECK(ESP_FAIL);
}
_started = true;
_bufferA = frameBufferAlloc();
_bufferB = frameBufferAlloc();
_lines = _bufferA;
_backBuffer = _bufferB;
// Initialize double-buffering infrastructure
_swapReady = false;
_swapCompleteNotify = xTaskGetCurrentTaskHandle();
// Start video signal generator
video_init(4, !_pal_);
}
/////////////////////////////////////////////////////////////////////////////
//
// Frame buffer memory allocation notes
//
// Architecture can tolerate each _line[i] being a separate chunk of memory
// but allocating in tiny 256 byte chunks is inefficient. (16 bytes of
// overhead per allocation.) On the opposite end, allocating the entire
// buffer at once (256*240 = 60kB) demands a large contiguous chunk of
// memory which might not exist if memory space is fragmented.
//
// Compromise: Allocate frame buffer in 4kB chunks. This means each
// frame buffer is made of 15 4kB chunks instead of a single 60kB chunk.
//
// 14 extra allocations * 16 byte overhead = 224 extra bytes, worth it.
const uint16_t linesPerFrame = 240;
const uint16_t bytesPerLine = 256;
const uint16_t linesPerChunk = 16;
const uint16_t chunkSize = bytesPerLine*linesPerChunk;
const uint16_t chunksPerFrame = 15;
/*
* @brief Allocate memory for frame buffer
*/
uint8_t** ESP_8_BIT_composite::frameBufferAlloc()
{
uint8_t** lineArray = NULL;
uint8_t* lineChunk = NULL;
uint8_t* lineStep = NULL;
lineArray = new uint8_t*[linesPerFrame];
if ( NULL == lineArray )
{
ESP_LOGE(TAG, "Frame lines array allocation fail");
ESP_ERROR_CHECK(ESP_FAIL);
}
for (uint8_t chunk = 0; chunk < chunksPerFrame; chunk++)
{
lineChunk = new uint8_t[chunkSize];
if ( NULL == lineChunk )
{
ESP_LOGE(TAG, "Frame buffer chunk allocation fail");
ESP_ERROR_CHECK(ESP_FAIL);
}
lineStep = lineChunk;
for (uint8_t lineIndex = 0; lineIndex < linesPerChunk; lineIndex++)
{
lineArray[(chunk*linesPerChunk)+lineIndex] = lineStep;
lineStep += bytesPerLine;
}
}
return lineArray;
}
/*
* @brief Free memory allocated by frameBufferAlloc();
*/
void ESP_8_BIT_composite::frameBufferFree(uint8_t** lineArray)
{
for (uint8_t chunk = 0; chunk < chunksPerFrame; chunk++)
{
free(lineArray[chunk*linesPerChunk]);
}
free(lineArray);
}
/*
* @brief Wait for current frame to finish rendering
*/
void ESP_8_BIT_composite::waitForFrame()
{
instance_check();
_swapReady = true;
video_sync();
}
/*
* @brief Retrieve pointer to frame buffer lines array
*/
uint8_t** ESP_8_BIT_composite::getFrameBufferLines()
{
instance_check();
return _backBuffer;
}
/*
* @brief Number of frames sent to screen
*/
uint32_t ESP_8_BIT_composite::getRenderedFrameCount()
{
return _frame_counter;
}
/*
* @brief Number of buffer swaps performed
*/
uint32_t ESP_8_BIT_composite::getBufferSwapCount()
{
return _swap_counter;
}

123
ESP_8_BIT_composite.h

@ -0,0 +1,123 @@
/*
ESP_8_BIT color composite video generator wrapper class.
Wrapper class adapting code extracted from Peter Barrett's ESP_8_BIT project
into a standalone Arduino library.
Copyright (c) Roger Cheng
MIT License
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.
*/
#ifndef ESP_8_BIT_COMPOSITE_H
#define ESP_8_BIT_COMPOSITE_H
#include "Arduino.h"
#ifndef ARDUINO_ARCH_ESP32
#error This library requires ESP32 as it uses ESP32-specific hardware peripheral
#endif
#include "esp_types.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_heap_caps.h"
#include "esp_intr_alloc.h"
#include "driver/periph_ctrl.h"
#include "driver/dac.h"
#include "driver/gpio.h"
#include "driver/i2s.h"
#include "rom/gpio.h"
#include "rom/lldesc.h"
#include "soc/gpio_reg.h"
#include "soc/i2s_struct.h"
#include "soc/i2s_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/rtc.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc.h"
class ESP_8_BIT_composite
{
public:
/*
* @brief Constructor for ESP_8_BIT composite video wrapper class
* @param ntsc True (or nonzero) for NTSC mode, False (or zero) for PAL mode
*/
ESP_8_BIT_composite(int ntsc);
/*
* @brief Destructor for ESP_8_BIT composite video wrapper class. This
* is only useful for freeing self-allocated memory, because I don't know how
* to properly tear down rossumur's ESP_8_BIT magic I wrapped.
*/
~ESP_8_BIT_composite();
/*
* @brief Video subsystem setup: allocate frame buffer and start engine
*/
void begin();
/*
* @brief Wait for current frame to finish rendering
*/
void waitForFrame();
/*
* @brief Retrieve pointer to frame buffer lines array
*/
uint8_t** getFrameBufferLines();
/*
* @brief Number of frames sent to screen
*/
uint32_t getRenderedFrameCount();
/*
* @brief Number of buffer swaps performed
*/
uint32_t getBufferSwapCount();
private:
/*
* @brief Check to ensure this instance is the first and only allowed instance
*/
void instance_check();
/*
* @brief Flag to ensure begin() is called once and only once
*/
bool _started;
/*
* @brief Allocate memory for frame buffer
*/
uint8_t** frameBufferAlloc();
/*
* @brief Free memory allocated by frameBufferAlloc();
*/
void frameBufferFree(uint8_t** frameBuffer);
};
#endif // ESP_8_BIT_COMPOSITE_H

36
README.md

@ -0,0 +1,36 @@
### COLOR SCHEME
Black 0b00000000 0x00
Blue 0b00000011 0x03
Green 0b00011100 0x1C
Cyan 0b00011111 0x1F
Red 0b11100000 0xE0
Magenta 0b11100011 0xE3
Yellow 0b11111100 0xFC
White 0b11111111 0xFF
### MENU ITEMS
1. STATUS
2. SCAN
3. REBOOT
### STATUS
5800
A1
[--------------]
[--------- ]
### SCAN
5800
[--- ]
[---- ]
A B E F R D U O
L H
1 2 3 4 5 6 7 8
### REBOOT
REBOOT
> YES
NO

318
channels.cpp

@ -0,0 +1,318 @@
/*
* Filename: channels.cpp
* Date: Mon 20 Sep 22:14:58 +08 2021
* Author: Englebert
* Description:
* - Handling channels settings
*/
#include "channels.h"
// Fixed Standard channels values in MHz - Reference: https://oscarliang.com/fpv-channels/
static const uint16_t channelsFreqTable[] PROGMEM = {
5865, 5845, 5825, 5805, 5785, 5765, 5745, 5725, // A
5733, 5752, 5771, 5790, 5809, 5828, 5847, 5866, // B
5705, 5685, 5665, 5645, 5885, 5905, 5925, 5945, // E
5740, 5760, 5780, 5800, 5820, 5840, 5860, 5880, // F
5658, 5695, 5732, 5769, 5806, 5843, 5880, 5917, // R
5362, 5399, 5436, 5473, 5510, 5547, 5584, 5621, // D
5325, 5348, 5366, 5384, 5402, 5420, 5438, 5456, // U
5474, 5492, 5510, 5528, 5546, 5564, 5582, 5600, // O
5333, 5373, 5413, 5453, 5493, 5533, 5573, 5613, // L
5653, 5693, 5733, 5773, 5813, 5853, 5893, 5933 // H
};
static const uint8_t channelFreqOrderedIndex[] PROGMEM = {
48, // 5325
64, // 5333
49, // 5348
40, // 5362
50, // 5366
65, // 5373
51, // 5384
41, // 5399
52, // 5402
66, // 5413
53, // 5420
42, // 5436
54, // 5438
67, // 5453
55, // 5456
43, // 5473
56, // 5474
57, // 5492
68, // 5493
44, // 5510
58, // 5510
44, // 5510
58, // 5510
59, // 5528
69, // 5533
60, // 5546
45, // 5547
61, // 5564
70, // 5573
62, // 5582
46, // 5584
63, // 5600
71, // 5613
47, // 5621
19, // 5645
72, // 5653
32, // 5658
18, // 5665
17, // 5685
73, // 5693
33, // 5695
16, // 5705
7, // 5725
34, // 5732
8, // 5733
74, // 5733
8, // 5733
74, // 5733
24, // 5740
6, // 5745
9, // 5752
25, // 5760
5, // 5765
35, // 5769
10, // 5771
75, // 5773
26, // 5780
4, // 5785
11, // 5790
27, // 5800
3, // 5805
36, // 5806
12, // 5809
76, // 5813
28, // 5820
2, // 5825
13, // 5828
29, // 5840
37, // 5843
1, // 5845
14, // 5847
77, // 5853
30, // 5860
0, // 5865
15, // 5866
31, // 5880
38, // 5880
31, // 5880
38, // 5880
20, // 5885
78, // 5893
21, // 5905
39, // 5917
22, // 5925
79, // 5933
23, // 5945
};
static const uint8_t channelIndexToOrderedIndex[] PROGMEM = {
73,
69,
65,
60,
57,
52,
49,
42,
44,
46,
44,
46,
50,
54,
58,
62,
66,
70,
74,
41,
38,
37,
34,
79,
48,
51,
56,
59,
64,
67,
72,
75,
77,
75,
77,
36,
40,
43,
53,
61,
68,
76,
78,
76,
78,
3,
7,
11,
15,
19,
21,
19,
21,
26,
30,
33,
0,
2,
4,
6,
8,
10,
12,
14,
16,
17,
20,
22,
20,
22,
23,
25,
27,
29,
31,
1,
5,
9,
13,
18,
24,
28,
32,
35,
39,
45,
47
};
namespace Channels {
const uint16_t getSynthRegisterB(uint8_t index) {
return getSynthRegisterBFreq(getFrequency(index));
}
const uint16_t getSynthRegisterBFreq(uint16_t f) {
return ((((f - 479) / 2) / 32) << 7) | (((f - 479) / 2) % 32);
}
const uint16_t getFrequency(uint8_t index) {
return pgm_read_word_near(channelsFreqTable + index);
}
// Returns channel name as a string.
char bandNames[] = {
65, // A
66, // B
68, // D
69, // E
70, // F
82, // R
76, // L
85, // U
79, // O
72 // H
};
char nameBuffer[2];
char *getName(uint8_t index) {
uint8_t band = index / 8;
uint8_t channel = 48 + (index % 8) + 1; // https://www.arduino.cc/en/Reference/ASCIIchart
nameBuffer[0] = bandNames[band];
nameBuffer[1] = channel;
return nameBuffer;
}
uint8_t getChannelNumber(uint8_t index) {
return (index % 8) + 1;
}
const uint8_t getOrderedIndexFromIndex(uint8_t index) {
return pgm_read_byte_near(channelIndexToOrderedIndex + index);
}
const uint8_t getOrderedIndex(uint8_t index) {
return pgm_read_byte_near(channelFreqOrderedIndex + index);
}
/*************
const uint16_t getCenterFreq(uint16_t freq) {
// // Centering notification
// Ui::clearRect(30, 60, 100, 13);
// Ui::drawRoundRect(30, 60, 100, 13, 2, WHITE);
// Ui::setTextSize(1);
// Ui::setTextColor(WHITE);
// Ui::setCursor(33, 62);
// Ui::display.print(PSTR2("Centering..."));
// Ui::needDisplay();
// Ui::update();
uint16_t upperFreq = freq;
uint16_t lowerFreq = freq;
uint16_t rssi = 1000;
while (rssi > EepromSettings.rssiSeekTreshold) {
upperFreq = upperFreq + 1;
Receiver::setChannelByFreq(upperFreq);
while (!Receiver::isRssiStable()) {
delay(1);
}
Receiver::updateRssi();
rssi = (Receiver::rssiA + Receiver::rssiB)/2;
if (EepromSettings.quadversity) {
rssi = ((Receiver::rssiA + Receiver::rssiB)/2 + (Receiver::rssiC + Receiver::rssiD)/2) / 2;
}
}
rssi = 1000;
while (rssi > EepromSettings.rssiSeekTreshold) {
lowerFreq = lowerFreq - 1;
Receiver::setChannelByFreq(lowerFreq);
while (!Receiver::isRssiStable()) {
delay(1);
}
Receiver::updateRssi();
rssi = (Receiver::rssiA + Receiver::rssiB)/2;
if (EepromSettings.quadversity) {
rssi = ((Receiver::rssiA + Receiver::rssiB)/2 + (Receiver::rssiC + Receiver::rssiD)/2) / 2;
}
}
// Ui::clearRect(26, 27, 76, 12);
return (lowerFreq + upperFreq) / 2;
}
*****/
const uint8_t getClosestChannel(uint16_t freq) {
uint8_t closestChannel = 0;
for (int j=0; j<CHANNELS_SIZE; j++) {
if (
max( Channels::getFrequency(j), freq ) - min( Channels::getFrequency(j), freq ) <=
max( Channels::getFrequency(closestChannel), freq ) - min( Channels::getFrequency(closestChannel), freq )
) {
closestChannel = j;
}
}
return closestChannel;
}
}

28
channels.h

@ -0,0 +1,28 @@
/*
* Filename: channels.h
* Date: Mon 20 Sep 22:14:58 +08 2021
* Author: Englebert
* Description:
* - Handling channels settings
*/
#ifndef CHANNELS_H
#define CHANNELS_H
#include "BertFPVDiversity.h"
#define CHANNELS_SIZE 80
namespace Channels {
const uint16_t getSynthRegisterB(uint8_t index);
const uint16_t getSynthRegisterBFreq(uint16_t freq);
const uint16_t getFrequency(uint8_t index);
extern char *getName(uint8_t index);
const uint8_t getOrderedIndex(uint8_t index);
const uint8_t getOrderedIndexFromIndex(uint8_t index);
/// const uint16_t getCenterFreq(uint16_t freq);
const uint8_t getClosestChannel(uint16_t freq);
uint8_t getChannelNumber(uint8_t index);
}
#endif

15
intro.cpp

@ -14,11 +14,13 @@ namespace Intro {
void display() {
// First time
if(intro_delays_time == 0) {
intro_delays_time = current_millis + 1000;
intro_delays_time = current_millis + 1200;
}
if(current_millis > intro_delays_time) {
display_screen = 1;
// display_screen = 1;
// Temporary...
display_screen = 2;
return;
}
@ -26,9 +28,9 @@ namespace Intro {
Video::video.waitForFrame();
// Clear screen
Video::video.fillScreen(0x00);
Video::video.fillScreen(0x10);
/***
Video::video.setTextColor(0xFD);
Video::video.setTextSize(1);
Video::video.setFont(&FreeSansBold18pt7b);
@ -42,6 +44,11 @@ namespace Intro {
Video::video.setCursor(80,135);
Video::video.setTextColor(0x0F);
Video::video.print("Version 1.0");
***/
Video::video.setTextColor(0xFF);
Video::video.setFont(&kimberle18pt7b);
Video::video.setCursor(70,120);
Video::video.print("READY");
// Just for 1 seconds ;)
// delay(1000);

294
kimberle13pt7b.h

@ -0,0 +1,294 @@
const uint8_t kimberle13pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xFD, 0xCE, 0x73, 0x9C, 0xE0, 0x03, 0xDE, 0xF7,
0xBC, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x10, 0x1E, 0x78,
0x1E, 0x78, 0x1E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x1E, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x78,
0x1E, 0x78, 0x1E, 0x78, 0x0E, 0x00, 0xE0, 0x0E, 0x07, 0xFE, 0xFF, 0xEF,
0xFE, 0xFF, 0xEF, 0xE0, 0xFE, 0x0F, 0xFE, 0xFF, 0xF7, 0xFF, 0x0F, 0xF0,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFC, 0x0E, 0x00, 0xE0, 0x38, 0x72,
0x23, 0x20, 0xB1, 0x07, 0x88, 0x31, 0x23, 0x04, 0xF8, 0x23, 0x41, 0x31,
0x13, 0x87, 0x00, 0x7F, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xF0, 0x78, 0xF0, 0x78, 0xF0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF0, 0x78, 0xF0, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x36, 0x40, 0x3C, 0xE7, 0x9E,
0x79, 0xEF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xC7, 0x9E,
0x79, 0xE3, 0x8F, 0xF1, 0xC7, 0x9E, 0x79, 0xE3, 0xCF, 0x3C, 0xF3, 0xCF,
0x3C, 0xF3, 0xCF, 0x3C, 0xF7, 0x9E, 0x79, 0xE7, 0x3C, 0x0E, 0x03, 0x86,
0xE9, 0xFF, 0xFF, 0xCF, 0xE3, 0xF9, 0xFF, 0x7F, 0x93, 0xA0, 0xE0, 0x3C,
0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0xFF, 0xFF, 0x76, 0x40, 0xFF,
0xFC, 0xFF, 0xFF, 0xF0, 0x00, 0x60, 0x18, 0x03, 0x00, 0xC0, 0x18, 0x06,
0x00, 0xC0, 0x38, 0x06, 0x01, 0xC0, 0x30, 0x0E, 0x01, 0x80, 0x70, 0x0C,
0x03, 0x80, 0x60, 0x1C, 0x03, 0x00, 0x00, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDF, 0xFC, 0xFB, 0xEF, 0xFF, 0xFC, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C,
0xF3, 0xCF, 0x3C, 0xF3, 0xC0, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x80, 0x3C, 0x01, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xE0,
0x0F, 0x00, 0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0xFF, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C,
0x00, 0xF0, 0x7B, 0xC1, 0xEF, 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC7, 0x8F,
0x1E, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0x03,
0xC0, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
0x03, 0xC0, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xF0, 0x07,
0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xC0, 0x1F, 0xFE, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xDF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF8, 0x03, 0xE0, 0x0F, 0x00, 0x7C, 0x01, 0xE0, 0x0F, 0x80, 0x3C,
0x01, 0xF0, 0x0F, 0x80, 0x3E, 0x01, 0xF0, 0x07, 0xC0, 0x3E, 0x00, 0xF8,
0x07, 0xC0, 0x00, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
0x3F, 0xC1, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x07,
0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFC, 0x7F, 0xF7,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xF0, 0x07, 0x80, 0x3F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x0F, 0xFF, 0xF7, 0x64, 0x04, 0x07, 0x07, 0xC3, 0xF3, 0xE3,
0xE3, 0xE0, 0xF8, 0x3E, 0x0F, 0x87, 0xE1, 0xC0, 0x40, 0xFF, 0xFC, 0x00,
0x00, 0x1F, 0xFF, 0x80, 0x20, 0x38, 0x3E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E,
0x7E, 0x7E, 0x7E, 0x3E, 0x0E, 0x02, 0x00, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0x3C, 0x01, 0xE1, 0xFF, 0x1F, 0xF8, 0xFF, 0xC7,
0xFC, 0x3E, 0x01, 0xE0, 0x00, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0,
0x07, 0x80, 0x7F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x3C, 0xFC, 0x79,
0xFC, 0xF3, 0xF9, 0xE0, 0x33, 0xC0, 0x67, 0x9F, 0xCF, 0x31, 0x9E, 0x63,
0x3C, 0xFE, 0x79, 0xF8, 0xF0, 0x01, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFD,
0xFF, 0xF0, 0x7F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x0F, 0xF0,
0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xC0,
0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0x3F, 0xC1, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F,
0x00, 0xF0, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xF0,
0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE,
0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x3C, 0x07, 0xFC, 0xFF, 0x9F, 0xF3, 0xFE, 0x78, 0x0F,
0x01, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3C, 0x07, 0xFC, 0xFF, 0x9F, 0xF3,
0xFE, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0,
0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xC0,
0x1E, 0x7F, 0xF3, 0xFF, 0x9F, 0xFC, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFE, 0xF0, 0x7F, 0x83, 0xFC,
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F,
0x83, 0xFC, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0xF0, 0xFD, 0xE3, 0xE3, 0xC7, 0xC7, 0x9F, 0x0F, 0x7C, 0x1F, 0xF0,
0x3F, 0xC0, 0x7F, 0x00, 0xFE, 0x01, 0xFE, 0x03, 0xFE, 0x07, 0xBE, 0x0F,
0x3C, 0x1E, 0x7C, 0x3C, 0x7C, 0x78, 0xF8, 0xF0, 0xF9, 0xE0, 0xFB, 0xC1,
0xF8, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80,
0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0xF0, 0x07, 0xF8, 0x03, 0xFE, 0x03, 0xFF, 0x01,
0xFF, 0x80, 0xFF, 0xE0, 0xFF, 0xF0, 0x7F, 0xF8, 0x3F, 0xFE, 0x3F, 0xFF,
0x1F, 0xFF, 0x8F, 0xFF, 0xEF, 0xFF, 0xF7, 0xFF, 0xBB, 0xBF, 0xDF, 0xDF,
0xEF, 0xEF, 0xF3, 0xE7, 0xF9, 0xF3, 0xFC, 0xF9, 0xE0, 0xE0, 0x3F, 0xC0,
0xFF, 0x03, 0xFE, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF, 0xE3, 0xFF, 0xCF, 0xFF,
0x3F, 0xFE, 0xFF, 0x7F, 0xFC, 0xFF, 0xF1, 0xFF, 0xC7, 0xFF, 0x0F, 0xFC,
0x1F, 0xF0, 0x3F, 0xC0, 0xFF, 0x01, 0xC0, 0x3F, 0xE3, 0xFF, 0xBF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF,
0xCF, 0xFC, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0x3F,
0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xE0, 0x0F, 0x00, 0x78,
0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x00, 0x7F, 0xF3, 0xFF,
0xEF, 0xFF, 0xBF, 0xFE, 0xFF, 0xFB, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0,
0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0xFF, 0xBF,
0xFE, 0xFF, 0xFB, 0xFF, 0xC7, 0xFF, 0x80, 0x1F, 0x00, 0x38, 0x00, 0x40,
0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF8, 0x3F, 0xC1, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1,
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1E, 0x3F, 0xFB, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xC0, 0x1E, 0x00, 0xFF, 0xF7, 0xFF, 0xDF,
0xFE, 0x00, 0xF0, 0x07, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xBF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0x0F,
0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F,
0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xDF, 0xFC, 0xF8, 0x1E, 0xF0, 0x7D, 0xE0, 0xFB, 0xE1, 0xE3, 0xC3, 0xC7,
0x8F, 0x8F, 0x1E, 0x1E, 0x3C, 0x1E, 0x78, 0x3C, 0xF0, 0x7B, 0xC0, 0x77,
0x80, 0xFF, 0x01, 0xFC, 0x03, 0xF8, 0x03, 0xF0, 0x07, 0xC0, 0x0F, 0x80,
0x0F, 0x00, 0xF8, 0x3C, 0x1F, 0xF8, 0x3C, 0x1E, 0x78, 0x3C, 0x3E, 0x7C,
0x7C, 0x3E, 0x7C, 0x7E, 0x3C, 0x3C, 0x7E, 0x3C, 0x3C, 0x7E, 0x7C, 0x3E,
0x7E, 0x7C, 0x1E, 0xFE, 0x78, 0x1E, 0xFF, 0x78, 0x1E, 0xFF, 0xF8, 0x0F,
0xEF, 0xF0, 0x0F, 0xE7, 0xF0, 0x0F, 0xE7, 0xF0, 0x07, 0xE7, 0xE0, 0x07,
0xE7, 0xE0, 0x07, 0xE7, 0xE0, 0x07, 0xC3, 0xC0, 0x03, 0xC3, 0xC0, 0xF8,
0x1F, 0x78, 0x1E, 0x7C, 0x3C, 0x3C, 0x3C, 0x3E, 0x78, 0x1E, 0x78, 0x0F,
0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xC0, 0x07, 0xE0, 0x0F, 0xF0, 0x0F,
0xF0, 0x1E, 0x78, 0x3E, 0x78, 0x3C, 0x3C, 0x7C, 0x3C, 0x78, 0x1E, 0xF8,
0x1F, 0xF0, 0x3F, 0xE1, 0xF7, 0x87, 0x9E, 0x1E, 0x3C, 0xF0, 0xF3, 0xC1,
0xCE, 0x07, 0xF8, 0x0F, 0xC0, 0x3F, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80,
0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xF8, 0x07, 0xC0, 0x3E, 0x00,
0xF0, 0x07, 0xC0, 0x3E, 0x00, 0xF0, 0x07, 0xC0, 0x3E, 0x00, 0xF0, 0x07,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF,
0xFF, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C,
0xF3, 0xCF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x1E, 0x01, 0xE0, 0x3C, 0x07,
0x80, 0x78, 0x0F, 0x00, 0xE0, 0x1E, 0x03, 0xC0, 0x3C, 0x07, 0x80, 0x70,
0x0F, 0x01, 0xE0, 0x1E, 0x03, 0xC0, 0x78, 0x07, 0x80, 0xFF, 0xFF, 0xFF,
0xFC, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF,
0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0xC7, 0x9E, 0x30, 0x7F, 0xF3, 0xFF, 0xDF, 0xFE, 0xFF, 0xF7, 0xFF,
0x80, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFC, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFD, 0xFF, 0xC0, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F,
0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0xFC, 0x1F, 0xE0,
0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3C, 0x07, 0x80, 0xF0,
0x1E, 0x03, 0xC0, 0x7F, 0xFF, 0xFF, 0xFF, 0xDF, 0xF8, 0x00, 0x78, 0x03,
0xC0, 0x1E, 0x00, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xDF, 0xFE, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x80, 0x3C, 0x01, 0xFF, 0xEF,
0xFF, 0x7F, 0xF9, 0xFF, 0xC0, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0xFE,
0xFE, 0xFE, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE,
0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF,
0xE0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xC0, 0xF0, 0x07, 0x80,
0x3C, 0x01, 0xE0, 0x0F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0,
0x7F, 0x83, 0xFC, 0x1E, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x3C, 0xF3, 0xC0, 0x3C, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0x3C,
0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0xFF, 0xFF, 0xFE, 0xF0, 0x0F, 0x00, 0xF0,
0x0F, 0x00, 0xF3, 0xFF, 0x3E, 0xF7, 0xCF, 0x78, 0xFF, 0x0F, 0xE0, 0xFE,
0x0F, 0xC0, 0xFE, 0x0F, 0xF0, 0xFF, 0x0F, 0x78, 0xF7, 0xCF, 0x3E, 0xF3,
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F,
0xFF, 0x8F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1,
0xE3, 0xFC, 0x3C, 0x7F, 0x87, 0x8F, 0xF0, 0xF1, 0xFE, 0x1E, 0x3F, 0xC3,
0xC7, 0xF8, 0x78, 0xFF, 0x0F, 0x1F, 0xE1, 0xE3, 0xFC, 0x3C, 0x78, 0x3F,
0xE3, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F,
0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xE0,
0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE,
0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF,
0xC0, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1,
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xDE, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x00, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83,
0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xE0, 0x0F, 0x00, 0x78,
0x03, 0xC0, 0x1E, 0x7F, 0x7F, 0xFF, 0xFF, 0xF8, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xDF, 0xFF, 0x7F, 0xF8, 0x03, 0xC0, 0x1F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF3, 0xCF, 0x3C, 0xFF, 0xFF,
0xFF, 0xF3, 0xCF, 0x3C, 0xF3, 0xCF, 0xBF, 0xFF, 0xF7, 0xC0, 0xF0, 0x7F,
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0,
0x7F, 0x83, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xBF, 0xF8, 0xFF, 0x80, 0xF8,
0x1F, 0x78, 0x3E, 0x7C, 0x3E, 0x3C, 0x3C, 0x3C, 0x7C, 0x3E, 0x78, 0x1E,
0x78, 0x1E, 0xF8, 0x1F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x07, 0xE0, 0x07,
0xE0, 0x07, 0xC0, 0x03, 0xC0, 0xF8, 0x3C, 0x1F, 0xF8, 0x3C, 0x3E, 0x78,
0x7C, 0x3E, 0x7C, 0x7C, 0x3C, 0x3C, 0x7E, 0x7C, 0x3C, 0x7E, 0x7C, 0x3E,
0xFE, 0x78, 0x1E, 0xFF, 0xF8, 0x1E, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x0F,
0xEF, 0xF0, 0x0F, 0xE7, 0xE0, 0x07, 0xE7, 0xE0, 0x07, 0xC7, 0xC0, 0x03,
0xC3, 0xC0, 0xF8, 0x3F, 0x7C, 0x3E, 0x7C, 0x7C, 0x3E, 0xF8, 0x1F, 0xF8,
0x1F, 0xF0, 0x0F, 0xE0, 0x07, 0xC0, 0x0F, 0xE0, 0x0F, 0xF0, 0x1F, 0xF0,
0x3E, 0xF8, 0x3E, 0x7C, 0x7C, 0x7C, 0xF8, 0x3F, 0xF8, 0x3F, 0xF0, 0x7D,
0xE0, 0xF3, 0xE3, 0xE3, 0xC7, 0x87, 0x8F, 0x0F, 0xBE, 0x0F, 0x78, 0x1E,
0xF0, 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0x7C, 0x00, 0xF8, 0x01, 0xF0,
0x03, 0xC0, 0x0F, 0x80, 0x1E, 0x00, 0x3C, 0x00, 0xF8, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x7C, 0x00, 0xF8, 0x01, 0xF0,
0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF8, 0x00, 0x00 };
const GFXglyph kimberle13pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 8, 0, 0 }, // 0x20 ' '
{ 1, 5, 19, 6, 1, -18 }, // 0x21 '!'
{ 13, 10, 7, 10, 0, -18 }, // 0x22 '"'
{ 22, 16, 15, 16, 0, -14 }, // 0x23 '#'
{ 52, 12, 20, 14, 1, -19 }, // 0x24 '$'
{ 82, 13, 10, 15, 1, -13 }, // 0x25 '%'
{ 99, 16, 19, 18, 1, -18 }, // 0x26 '&'
{ 137, 4, 7, 6, 1, -14 }, // 0x27 '''
{ 141, 6, 24, 7, 1, -19 }, // 0x28 '('
{ 159, 6, 24, 7, 0, -19 }, // 0x29 ')'
{ 177, 10, 11, 9, -1, -12 }, // 0x2A '*'
{ 191, 8, 8, 10, 1, -12 }, // 0x2B '+'
{ 199, 4, 7, 6, 1, -4 }, // 0x2C ','
{ 203, 7, 2, 9, 1, -9 }, // 0x2D '-'
{ 205, 4, 5, 6, 1, -4 }, // 0x2E '.'
{ 208, 11, 19, 13, 1, -18 }, // 0x2F '/'
{ 235, 13, 19, 15, 1, -18 }, // 0x30 '0'
{ 266, 6, 19, 8, 1, -18 }, // 0x31 '1'
{ 281, 13, 19, 15, 1, -18 }, // 0x32 '2'
{ 312, 12, 19, 14, 1, -18 }, // 0x33 '3'
{ 341, 14, 19, 16, 1, -18 }, // 0x34 '4'
{ 375, 13, 19, 15, 1, -18 }, // 0x35 '5'
{ 406, 13, 19, 15, 1, -18 }, // 0x36 '6'
{ 437, 14, 19, 16, 1, -18 }, // 0x37 '7'
{ 471, 13, 19, 15, 1, -18 }, // 0x38 '8'
{ 502, 13, 19, 15, 1, -18 }, // 0x39 '9'
{ 533, 4, 12, 6, 1, -11 }, // 0x3A ':'
{ 539, 4, 14, 6, 1, -11 }, // 0x3B ';'
{ 546, 9, 13, 10, 1, -15 }, // 0x3C '<'
{ 561, 7, 7, 9, 1, -12 }, // 0x3D '='
{ 568, 9, 13, 10, 1, -15 }, // 0x3E '>'
{ 583, 13, 19, 14, 1, -18 }, // 0x3F '?'
{ 614, 15, 19, 17, 1, -18 }, // 0x40 '@'
{ 650, 14, 19, 16, 1, -18 }, // 0x41 'A'
{ 684, 13, 19, 15, 1, -18 }, // 0x42 'B'
{ 715, 12, 19, 14, 1, -18 }, // 0x43 'C'
{ 744, 13, 19, 15, 1, -18 }, // 0x44 'D'
{ 775, 11, 19, 13, 1, -18 }, // 0x45 'E'
{ 802, 11, 19, 13, 1, -18 }, // 0x46 'F'
{ 829, 13, 19, 15, 1, -18 }, // 0x47 'G'
{ 860, 13, 19, 15, 1, -18 }, // 0x48 'H'
{ 891, 4, 19, 6, 1, -18 }, // 0x49 'I'
{ 901, 10, 19, 11, 0, -18 }, // 0x4A 'J'
{ 925, 15, 19, 16, 1, -18 }, // 0x4B 'K'
{ 961, 11, 19, 13, 1, -18 }, // 0x4C 'L'
{ 988, 17, 19, 19, 1, -18 }, // 0x4D 'M'
{ 1029, 14, 19, 16, 1, -18 }, // 0x4E 'N'
{ 1063, 13, 19, 15, 1, -18 }, // 0x4F 'O'
{ 1094, 13, 19, 15, 1, -18 }, // 0x50 'P'
{ 1125, 14, 22, 16, 1, -18 }, // 0x51 'Q'
{ 1164, 13, 19, 15, 1, -18 }, // 0x52 'R'
{ 1195, 13, 19, 15, 1, -18 }, // 0x53 'S'
{ 1226, 12, 19, 13, 1, -18 }, // 0x54 'T'
{ 1255, 13, 19, 15, 1, -18 }, // 0x55 'U'
{ 1286, 15, 19, 16, 0, -18 }, // 0x56 'V'
{ 1322, 24, 19, 24, 0, -18 }, // 0x57 'W'
{ 1379, 16, 19, 18, 1, -18 }, // 0x58 'X'
{ 1417, 14, 19, 15, 0, -18 }, // 0x59 'Y'
{ 1451, 14, 19, 16, 1, -18 }, // 0x5A 'Z'
{ 1485, 6, 27, 7, 1, -22 }, // 0x5B '['
{ 1506, 11, 19, 13, 1, -18 }, // 0x5C '\'
{ 1533, 6, 27, 7, 1, -22 }, // 0x5D ']'
{ 1554, 1, 1, 13, 0, 0 }, // 0x5E '^'
{ 1555, 14, 3, 16, 1, 1 }, // 0x5F '_'
{ 1561, 5, 4, 15, 5, -22 }, // 0x60 '`'
{ 1564, 13, 15, 15, 1, -14 }, // 0x61 'a'
{ 1589, 13, 19, 15, 1, -18 }, // 0x62 'b'
{ 1620, 11, 15, 12, 1, -14 }, // 0x63 'c'
{ 1641, 13, 19, 15, 1, -18 }, // 0x64 'd'
{ 1672, 13, 15, 15, 1, -14 }, // 0x65 'e'
{ 1697, 8, 19, 10, 1, -18 }, // 0x66 'f'
{ 1716, 13, 20, 15, 1, -14 }, // 0x67 'g'
{ 1749, 13, 19, 15, 1, -18 }, // 0x68 'h'
{ 1780, 4, 19, 6, 1, -18 }, // 0x69 'i'
{ 1790, 6, 24, 8, 1, -18 }, // 0x6A 'j'
{ 1808, 12, 19, 14, 1, -18 }, // 0x6B 'k'
{ 1837, 4, 19, 6, 1, -18 }, // 0x6C 'l'
{ 1847, 19, 15, 21, 1, -14 }, // 0x6D 'm'
{ 1883, 13, 15, 15, 1, -14 }, // 0x6E 'n'
{ 1908, 13, 15, 15, 1, -14 }, // 0x6F 'o'
{ 1933, 13, 19, 15, 1, -14 }, // 0x70 'p'
{ 1964, 13, 19, 15, 1, -14 }, // 0x71 'q'
{ 1995, 8, 15, 10, 1, -14 }, // 0x72 'r'
{ 2010, 13, 15, 15, 1, -14 }, // 0x73 's'
{ 2035, 6, 19, 7, 1, -18 }, // 0x74 't'
{ 2050, 13, 15, 15, 1, -14 }, // 0x75 'u'
{ 2075, 16, 15, 16, 0, -14 }, // 0x76 'v'
{ 2105, 24, 15, 24, 0, -14 }, // 0x77 'w'
{ 2150, 16, 15, 17, 1, -14 }, // 0x78 'x'
{ 2180, 15, 20, 15, 0, -14 }, // 0x79 'y'
{ 2218, 16, 15, 16, 0, -14 }, // 0x7A 'z'
{ 2248, 1, 1, 13, 0, 0 }, // 0x7B '{'
{ 2249, 3, 23, 4, 1, -18 }, // 0x7C '|'
{ 2258, 1, 1, 13, 0, 0 }, // 0x7D '}'
{ 2259, 1, 1, 13, 0, 0 } }; // 0x7E '~'
const GFXfont kimberle13pt7b PROGMEM = {
(uint8_t *)kimberle13pt7bBitmaps,
(GFXglyph *)kimberle13pt7bGlyphs,
0x20, 0x7E, 33 };
// Approx. 2932 bytes

484
kimberle18pt7b.h

@ -0,0 +1,484 @@
const uint8_t kimberle18pt7bBitmaps[] PROGMEM = {
0x00, 0x7E, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0x3E, 0x7C, 0xF9, 0xF1, 0xE3,
0xC7, 0x8F, 0x1E, 0x00, 0x00, 0x00, 0x0F, 0xDF, 0xBF, 0x7E, 0xFD, 0xFB,
0xF0, 0xFD, 0xFF, 0xEF, 0x9E, 0x3C, 0xF1, 0xE7, 0x8F, 0x3C, 0x79, 0xE3,
0xCF, 0x1E, 0x78, 0xF3, 0x80, 0x00, 0x0F, 0x8F, 0x80, 0x7C, 0x7C, 0x03,
0xE3, 0xE0, 0x1F, 0x1F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x7C, 0x7C, 0x03, 0xE3, 0xE0, 0x1F,
0x1F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x7C, 0x7C, 0x03, 0xE3, 0xE0, 0x1F, 0x1F, 0x00, 0xF8,
0xF8, 0x00, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x03, 0xFF,
0xF3, 0xFF, 0xFB, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0xFF, 0xBE,
0xF8, 0x1F, 0x7C, 0x0F, 0xFF, 0xE7, 0xFF, 0xF9, 0xFF, 0xFE, 0xFF, 0xFF,
0x3F, 0xFF, 0x80, 0xF7, 0xC0, 0x7B, 0xEF, 0xFF, 0xF7, 0xFF, 0xFB, 0xFF,
0xFD, 0xFF, 0xFE, 0xFF, 0xFE, 0x7F, 0xF8, 0x00, 0xF0, 0x00, 0x78, 0x00,
0x3C, 0x00, 0x3E, 0x03, 0xCC, 0x30, 0xF3, 0x02, 0x3C, 0x40, 0x2F, 0x08,
0x07, 0xC1, 0x00, 0xFF, 0x30, 0x3E, 0x33, 0x0F, 0x82, 0x3F, 0xE0, 0x20,
0xFC, 0x04, 0x3D, 0x80, 0x8F, 0x18, 0x33, 0xC1, 0x8C, 0xF0, 0x1F, 0x00,
0x3F, 0xE0, 0x00, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x07, 0xFF, 0x00, 0x0F,
0xFE, 0x00, 0x1F, 0xFC, 0x00, 0x3F, 0xF8, 0x00, 0x7E, 0x03, 0xF0, 0xFC,
0x07, 0xE1, 0xF8, 0x0F, 0xC3, 0xF0, 0x1F, 0x87, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF8, 0x0F, 0xC3, 0xF0, 0x1F, 0x87, 0xE0, 0x3F, 0x0F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xF8, 0x7B, 0xFF, 0xFF, 0xFF, 0xF3, 0xC6,
0x18, 0xC0, 0x3F, 0x3E, 0x3E, 0x3E, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0xFC,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x3E, 0x3E, 0x3E, 0x3F, 0xFC, 0x7C,
0x7C, 0x7C, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3F, 0x1F, 0x1F, 0x1F, 0x1F,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3E, 0x3E, 0x3E,
0x3E, 0x3E, 0x7C, 0x7C, 0x7C, 0xFC, 0x07, 0x80, 0x1E, 0x04, 0x79, 0x0D,
0xEE, 0x7F, 0xFB, 0xFF, 0xF7, 0xFF, 0x87, 0xFC, 0x3F, 0xF1, 0xFF, 0xFF,
0xFF, 0x9F, 0xFE, 0x37, 0x90, 0x1E, 0x00, 0x78, 0x00, 0x1F, 0x81, 0xF8,
0x1F, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1, 0xF8,
0x1F, 0x81, 0xF8, 0x1F, 0x80, 0x7B, 0xFF, 0xFF, 0xFF, 0xF7, 0x8E, 0x31,
0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00,
0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00,
0x38, 0x00, 0x70, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xE0, 0x01, 0xE0, 0x01,
0xC0, 0x03, 0xC0, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00, 0x0F, 0x00, 0x0E,
0x00, 0x0E, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70,
0x00, 0x70, 0x00, 0xF0, 0x00, 0x3F, 0xFF, 0x8F, 0xFF, 0xFB, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F,
0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F,
0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF,
0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xF8, 0xFF, 0xFE, 0x00, 0xF8, 0xFE,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
0x3F, 0xFF, 0xFF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00,
0xFC, 0x00, 0x1F, 0x9F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x9F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00,
0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFE, 0x7F, 0xFF, 0xBF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, 0x00,
0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xE3,
0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xBF, 0xFF, 0x80, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00,
0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x7E, 0xFC, 0x0F,
0x9F, 0x83, 0xF3, 0xF0, 0x7E, 0x7E, 0x1F, 0x8F, 0xC3, 0xF1, 0xF8, 0x7C,
0x3F, 0x1F, 0x87, 0xE3, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xE0, 0x00,
0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7F,
0xFF, 0xCF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF,
0xFE, 0x00, 0x3F, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0xFC, 0x00, 0x1F,
0x80, 0x03, 0xF0, 0x00, 0x7F, 0xFF, 0xCF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE,
0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xEF, 0xFF, 0xF8, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x00, 0xFC, 0x00, 0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x80, 0x03,
0xF0, 0x00, 0x7F, 0x00, 0x07, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xC0, 0x01,
0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xF0, 0x00,
0x7E, 0x00, 0x0F, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0xC0, 0x03, 0xF8, 0x00,
0x3F, 0x80, 0x00, 0x3F, 0xFF, 0x8F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFC, 0x07,
0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF7, 0xFF, 0xFC, 0x3F, 0xFE,
0x1F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xF0, 0x1F,
0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xEF, 0xFF, 0xF8, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0x8F, 0xFF,
0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x3F, 0xFF,
0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFE,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xBF, 0xFF,
0xFF, 0xFF, 0x78, 0xE3, 0x18, 0x00, 0x80, 0x1C, 0x03, 0xE0, 0x7F, 0x0F,
0xF1, 0xFE, 0x3F, 0xC7, 0xF8, 0x7F, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
0xE0, 0xFF, 0x07, 0xF0, 0x3E, 0x01, 0xC0, 0x08, 0xFF, 0xFF, 0xFF, 0xFC,
0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x10, 0x01, 0x80,
0x3C, 0x07, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0xFF,
0x1F, 0xE3, 0xFC, 0x7F, 0x8F, 0xF0, 0x7E, 0x03, 0xC0, 0x18, 0x01, 0x00,
0xFF, 0xFF, 0x3F, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00,
0xFC, 0x0F, 0xFF, 0x0F, 0xFF, 0xC3, 0xFF, 0xF0, 0xFF, 0xF8, 0x3F, 0xFC,
0x0F, 0xC0, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x03,
0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC,
0x00, 0x3F, 0xFF, 0xE1, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xB8, 0x00, 0x07,
0xE0, 0x00, 0x1F, 0x80, 0x00, 0x7E, 0x3F, 0xE1, 0xF8, 0xFF, 0xC7, 0xE3,
0xFF, 0x1F, 0x8F, 0xFC, 0x7E, 0x00, 0x71, 0xF8, 0x01, 0xC7, 0xE1, 0xFF,
0x1F, 0x8F, 0xFC, 0x7E, 0x38, 0x71, 0xF8, 0xE1, 0xC7, 0xE3, 0xFF, 0x1F,
0x8F, 0xFC, 0x7E, 0x1F, 0xE1, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x1F, 0x80,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF8, 0xFF, 0xFF,
0xC0, 0x3F, 0xFF, 0xC7, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF,
0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xC0, 0x3F, 0xFC, 0x03,
0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0,
0x3F, 0xFC, 0x03, 0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xF0, 0xFF, 0xFF, 0x9F,
0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x7F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFE, 0x3F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF,
0xFE, 0x00, 0x1F, 0xFF, 0x9F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x3F,
0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00,
0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xFF, 0xFB, 0xFF,
0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0xFF, 0x9F, 0xFF, 0xC7, 0xFF, 0xE0,
0xFF, 0xFF, 0x1F, 0xFF, 0xFB, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF,
0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF,
0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFB, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xFC, 0x00, 0xFC,
0x00, 0xFC, 0x00, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF,
0xF8, 0xFF, 0xF8, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFF, 0xF8, 0xFF,
0xF8, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8, 0xFF, 0xF8, 0xFC, 0x00, 0xFC,
0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC,
0x00, 0xFC, 0x00, 0xFC, 0x00, 0x1F, 0xFF, 0xE7, 0xFF, 0xFD, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00,
0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x3F, 0xFF, 0xC7, 0xFF,
0xF8, 0xFF, 0xDF, 0x1F, 0xFB, 0xE3, 0xFF, 0x7C, 0x7F, 0xEF, 0x80, 0xFD,
0xF0, 0x1F, 0xBE, 0x03, 0xF7, 0xFF, 0xFE, 0xFF, 0xFF, 0xDF, 0xFF, 0xFB,
0xFF, 0xFF, 0x7F, 0xFF, 0xE7, 0xFF, 0xFC, 0x7F, 0xFF, 0x80, 0xFC, 0x07,
0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F,
0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F,
0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF,
0xF0, 0x1F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03,
0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xCF, 0xFE, 0x00,
0xFC, 0x0F, 0xE7, 0xE0, 0xFE, 0x3F, 0x0F, 0xE1, 0xF8, 0x7E, 0x0F, 0xC7,
0xF0, 0x7E, 0x7F, 0x03, 0xF3, 0xF0, 0x1F, 0xBF, 0x00, 0xFF, 0xF0, 0x07,
0xFF, 0x00, 0x3F, 0xF8, 0x01, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0x7F, 0xF8,
0x03, 0xFF, 0xC0, 0x1F, 0xBF, 0x00, 0xFD, 0xFC, 0x07, 0xE7, 0xE0, 0x3F,
0x1F, 0x81, 0xF8, 0xFE, 0x0F, 0xC3, 0xF8, 0x7E, 0x1F, 0xC3, 0xF0, 0x7F,
0x1F, 0x81, 0xFC, 0xFC, 0x0F, 0xE7, 0xE0, 0x3F, 0xBF, 0x01, 0xFE, 0xFC,
0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC,
0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC,
0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC, 0x00, 0xFC,
0x00, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
0x00, 0x3F, 0xFC, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE,
0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
0x81, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF,
0xC3, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xE7, 0xFF, 0xFD,
0xF7, 0xBF, 0xFD, 0xFF, 0xBF, 0xFD, 0xFF, 0xBF, 0xFC, 0xFF, 0x3F, 0xFC,
0xFF, 0x3F, 0xFC, 0xFF, 0x3F, 0xFC, 0x7F, 0x3F, 0xFC, 0x7E, 0x3F, 0xFC,
0x7E, 0x3F, 0xF0, 0x03, 0xFF, 0x80, 0x3F, 0xF8, 0x03, 0xFF, 0xC0, 0x3F,
0xFE, 0x03, 0xFF, 0xE0, 0x3F, 0xFF, 0x03, 0xFF, 0xF8, 0x3F, 0xFF, 0xC3,
0xFF, 0xFC, 0x3F, 0xFF, 0xE3, 0xFF, 0xFF, 0x3F, 0xFF, 0xF3, 0xFF, 0xFF,
0xBF, 0xFD, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0x7F, 0xFF, 0xC7, 0xFF, 0xFC,
0x3F, 0xFF, 0xC1, 0xFF, 0xFC, 0x0F, 0xFF, 0xC0, 0xFF, 0xFC, 0x07, 0xFF,
0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0, 0x1F, 0xFC, 0x00, 0xF0, 0x0F, 0xFF,
0x07, 0xFF, 0xF1, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F,
0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xDF, 0x01, 0xFB, 0xE0, 0x3F,
0x7C, 0x07, 0xEF, 0x80, 0xFD, 0xF0, 0x1F, 0xBE, 0x03, 0xF7, 0xFF, 0xFE,
0xFF, 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF, 0x7F, 0xFF, 0xE7, 0xFF, 0xF8,
0x7F, 0xFE, 0x00, 0xFF, 0xFF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFC, 0x07,
0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0x9F, 0x80, 0x03, 0xF0, 0x00,
0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00,
0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x83, 0xFF,
0xFE, 0x3F, 0xFF, 0xF9, 0xFF, 0xFF, 0xCF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF3,
0xFF, 0xFF, 0x9F, 0x80, 0xFC, 0xFC, 0x07, 0xE7, 0xE0, 0x3F, 0x3F, 0x01,
0xF9, 0xF8, 0x0F, 0xCF, 0xC0, 0x7E, 0x7E, 0x03, 0xF3, 0xF0, 0x1F, 0x9F,
0x80, 0xFC, 0xFC, 0x07, 0xE7, 0xE0, 0x3F, 0x3F, 0x01, 0xF9, 0xF8, 0x0F,
0xCF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF3, 0xFF, 0xFF, 0x9F, 0xFF, 0xFC, 0xFF,
0xFF, 0xC3, 0xFF, 0xFF, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xF0, 0x00, 0x3F,
0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0x9F, 0xFF, 0xFB, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x7F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFD, 0xFF, 0xFE, 0x3F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01,
0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0x80, 0x0F,
0xFF, 0xE7, 0xFF, 0xFD, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFC, 0x00, 0x0F, 0x80, 0x01, 0xF0,
0x00, 0x3F, 0xFF, 0xC7, 0xFF, 0xFC, 0xFF, 0xFF, 0xCF, 0xFF, 0xF8, 0xFF,
0xFF, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF,
0xFB, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0xFC, 0x07,
0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F,
0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F,
0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F,
0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xF8,
0xFF, 0xFE, 0x00, 0xFE, 0x01, 0xFB, 0xF0, 0x0F, 0xDF, 0x80, 0xFE, 0xFC,
0x07, 0xE3, 0xF0, 0x3F, 0x1F, 0x81, 0xF8, 0xFC, 0x0F, 0xC7, 0xE0, 0xFC,
0x1F, 0x87, 0xE0, 0xFC, 0x3F, 0x07, 0xE1, 0xF0, 0x1F, 0x1F, 0x80, 0xFC,
0xFC, 0x07, 0xE7, 0xE0, 0x1F, 0x3E, 0x00, 0xFB, 0xF0, 0x07, 0xDF, 0x80,
0x3F, 0xF8, 0x00, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x3F, 0xE0, 0x00, 0xFF,
0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFC, 0x00, 0x07, 0xE0, 0x00,
0x3F, 0x00, 0xFE, 0x03, 0xE0, 0x1F, 0xFF, 0x01, 0xF0, 0x1F, 0xDF, 0x80,
0xFC, 0x0F, 0xEF, 0xE0, 0x7E, 0x07, 0xE7, 0xF0, 0x7F, 0x03, 0xF1, 0xF8,
0x3F, 0x83, 0xF8, 0xFC, 0x1F, 0xC1, 0xF8, 0x7F, 0x0F, 0xF0, 0xFC, 0x1F,
0x87, 0xF8, 0x7E, 0x0F, 0xC7, 0xFC, 0x7F, 0x07, 0xE3, 0xFE, 0x3F, 0x01,
0xF9, 0xFF, 0x1F, 0x80, 0xFC, 0xFF, 0xCF, 0xC0, 0x7E, 0x7F, 0xEF, 0xC0,
0x3F, 0x7D, 0xF7, 0xE0, 0x0F, 0xFE, 0xFB, 0xF0, 0x07, 0xFF, 0x7D, 0xF0,
0x03, 0xFF, 0x9F, 0xF8, 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x7F, 0xC7, 0xFC,
0x00, 0x3F, 0xE3, 0xFE, 0x00, 0x0F, 0xF1, 0xFF, 0x00, 0x07, 0xF8, 0x7F,
0x80, 0x03, 0xFC, 0x3F, 0x80, 0x00, 0xFE, 0x1F, 0xC0, 0x00, 0x7E, 0x0F,
0xE0, 0x00, 0x3F, 0x07, 0xE0, 0x00, 0xFE, 0x00, 0xFE, 0xFC, 0x01, 0xF8,
0xFC, 0x07, 0xE1, 0xF8, 0x0F, 0xC1, 0xF8, 0x3F, 0x03, 0xF0, 0x7C, 0x03,
0xF1, 0xF8, 0x07, 0xE3, 0xE0, 0x07, 0xEF, 0xC0, 0x07, 0xDF, 0x00, 0x0F,
0xFE, 0x00, 0x0F, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x1F, 0xC0, 0x00, 0x7F,
0x80, 0x00, 0xFF, 0x80, 0x03, 0xFF, 0x80, 0x07, 0xDF, 0x00, 0x1F, 0xBF,
0x00, 0x7E, 0x3E, 0x00, 0xFC, 0x7E, 0x03, 0xF0, 0x7C, 0x07, 0xE0, 0xFC,
0x1F, 0x80, 0xFC, 0x7F, 0x01, 0xF8, 0xFC, 0x01, 0xFB, 0xF8, 0x03, 0xF8,
0xFE, 0x01, 0xFD, 0xF8, 0x07, 0xE3, 0xF0, 0x3F, 0x0F, 0xC0, 0xFC, 0x1F,
0x03, 0xE0, 0x7E, 0x1F, 0x80, 0xF8, 0x7E, 0x03, 0xF3, 0xF0, 0x0F, 0xCF,
0xC0, 0x1F, 0x3E, 0x00, 0x7F, 0xF8, 0x00, 0xFF, 0xC0, 0x03, 0xFF, 0x00,
0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03,
0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0,
0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00,
0x0F, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xC0, 0x01, 0xF8, 0x00,
0x3F, 0x80, 0x07, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00,
0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00,
0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0xFF, 0xF7, 0xFF, 0xFF, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFC, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x3E, 0x00, 0x3F, 0x00,
0x3F, 0x00, 0x1F, 0x00, 0x1F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0xC0,
0x07, 0xC0, 0x07, 0xE0, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xF0, 0x01, 0xF0,
0x01, 0xF0, 0x01, 0xF8, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0x7C, 0x00, 0x7C,
0x00, 0x7E, 0x00, 0x3E, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF8, 0x7E, 0x1F, 0x06, 0x7F,
0xFF, 0x8F, 0xFF, 0xF9, 0xFF, 0xFF, 0xBF, 0xFF, 0xF7, 0xFF, 0xFE, 0xFF,
0xFF, 0xDF, 0xFF, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE3, 0xFF, 0xFD, 0xFF,
0xFF, 0xBF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0x81, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xBF, 0xFF, 0xE1, 0xFF,
0xF8, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0,
0x01, 0xF8, 0x00, 0x3F, 0xFF, 0xE7, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x01,
0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03,
0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFB, 0xFF, 0xFE, 0x00, 0x3F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x7E, 0x00, 0xFC, 0x01, 0xF8,
0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xF3, 0xFF, 0xE0, 0x00, 0x07,
0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F,
0xCF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F,
0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFC,
0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0x0F, 0xFF, 0xFB, 0xFF, 0xFF, 0x7F, 0xFF,
0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFC, 0x0F,
0xDF, 0xFF, 0xFB, 0xFF, 0xFF, 0x7F, 0xFF, 0xCF, 0xFF, 0xF1, 0xF8, 0x00,
0x3F, 0x00, 0x07, 0xFF, 0xFE, 0xFF, 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF,
0x3F, 0xFF, 0xE3, 0xFF, 0xFC, 0x1F, 0xF3, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFC, 0x0F, 0xFC, 0xFF, 0xCF, 0xFC, 0xFF,
0xCF, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC,
0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x00, 0x3F, 0xFF,
0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F,
0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xF3, 0xFF, 0xFE,
0x00, 0x0F, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xF0, 0xFC, 0x00, 0x1F, 0x80, 0x03,
0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0xFF, 0xE7,
0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF,
0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF,
0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0x80,
0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0x8F, 0xC7, 0xE3,
0xF0, 0x00, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC,
0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F,
0x8F, 0xC7, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x7E, 0x00, 0xFC,
0x00, 0x7E, 0x00, 0x3F, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03,
0xF1, 0xFF, 0xF8, 0xFE, 0xFC, 0xFE, 0x7E, 0x7E, 0x3F, 0x7F, 0x1F, 0xBF,
0x0F, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0x80, 0x7F,
0xE0, 0x3F, 0xF8, 0x1F, 0xFC, 0x0F, 0xFF, 0x07, 0xEF, 0xC3, 0xF7, 0xF1,
0xF9, 0xF8, 0xFC, 0xFE, 0x7E, 0x3F, 0xBF, 0x1F, 0xE0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0x87, 0xFF, 0xFF,
0xFE, 0x7F, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xF8, 0x3F, 0xFC, 0x1F,
0x83, 0xFF, 0xC1, 0xF8, 0x3F, 0xFC, 0x1F, 0x83, 0xFF, 0xC1, 0xF8, 0x3F,
0xFC, 0x1F, 0x83, 0xFF, 0xC1, 0xF8, 0x3F, 0xFC, 0x1F, 0x83, 0xFF, 0xC1,
0xF8, 0x3F, 0xFC, 0x1F, 0x83, 0xFF, 0xC1, 0xF8, 0x3F, 0xFC, 0x1F, 0x83,
0xFF, 0xC1, 0xF8, 0x3F, 0xFC, 0x1F, 0x83, 0xF0, 0x1F, 0xFF, 0x0F, 0xFF,
0xF9, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03,
0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07,
0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7E, 0x3F, 0xFF,
0x8F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F,
0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xE3, 0xFF, 0xF8,
0xFF, 0xFF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF,
0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF,
0xFF, 0xF9, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F,
0x80, 0x03, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F,
0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F,
0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xBF, 0xFF, 0xF3, 0xFF, 0xFE, 0x00, 0x0F, 0xC0, 0x01, 0xF8,
0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x1F, 0xF7,
0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xC0, 0xFC, 0x0F,
0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x0F,
0xC0, 0xFC, 0x0F, 0xC0, 0xFC, 0x00, 0x3F, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x00, 0xFF, 0xFF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0x3F, 0xFF, 0xF3, 0xFF,
0xFE, 0x00, 0x0F, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xF8, 0xFC, 0xFC, 0xFC, 0xFC,
0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0xFC,
0x07, 0xFF, 0x80, 0xFF, 0xF0, 0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8,
0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xF0,
0x1F, 0xFE, 0x03, 0xFF, 0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xE1, 0xFF,
0xF0, 0xFE, 0x01, 0xFD, 0xF8, 0x07, 0xE7, 0xE0, 0x1F, 0x8F, 0xC0, 0xFC,
0x3F, 0x03, 0xF0, 0xFC, 0x1F, 0xC1, 0xF8, 0x7E, 0x07, 0xE1, 0xF8, 0x0F,
0x8F, 0xE0, 0x3F, 0x3F, 0x00, 0xFC, 0xFC, 0x01, 0xF7, 0xE0, 0x07, 0xFF,
0x80, 0x1F, 0xFE, 0x00, 0x3F, 0xF0, 0x00, 0xFF, 0xC0, 0x01, 0xFE, 0x00,
0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0xFC,
0x03, 0xE0, 0x3F, 0xFF, 0x01, 0xF0, 0x1F, 0xDF, 0x81, 0xFC, 0x0F, 0xCF,
0xE0, 0xFE, 0x0F, 0xE7, 0xF0, 0x7F, 0x07, 0xF1, 0xF8, 0x7F, 0x83, 0xF0,
0xFE, 0x3F, 0xE3, 0xF8, 0x3F, 0x1F, 0xF1, 0xF8, 0x1F, 0x8F, 0xF8, 0xFC,
0x0F, 0xEF, 0xFE, 0xFE, 0x03, 0xF7, 0xFF, 0x7E, 0x01, 0xFB, 0xFF, 0xFF,
0x00, 0x7F, 0xF7, 0xFF, 0x00, 0x3F, 0xFB, 0xFF, 0x80, 0x1F, 0xFD, 0xFF,
0x80, 0x07, 0xFC, 0x7F, 0xC0, 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x1F,
0xE0, 0x00, 0x7F, 0x07, 0xF0, 0x00, 0x1F, 0x83, 0xF0, 0x00, 0x0F, 0xC1,
0xF8, 0x00, 0xFF, 0x01, 0xFD, 0xFC, 0x0F, 0xE3, 0xF8, 0x3F, 0x8F, 0xE1,
0xFC, 0x1F, 0xCF, 0xE0, 0x3F, 0xBF, 0x80, 0xFF, 0xFC, 0x01, 0xFF, 0xE0,
0x03, 0xFF, 0x00, 0x07, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x03,
0xFF, 0x00, 0x0F, 0xFE, 0x00, 0x7F, 0xF8, 0x03, 0xFF, 0xF0, 0x1F, 0xCF,
0xE0, 0x7F, 0x1F, 0xC3, 0xF8, 0x7F, 0x1F, 0xC0, 0xFE, 0xFF, 0x03, 0xFC,
0xFC, 0x01, 0xFF, 0xF0, 0x1F, 0xDF, 0x80, 0xFC, 0xFC, 0x07, 0xE3, 0xF0,
0x7F, 0x1F, 0x83, 0xF0, 0xFC, 0x1F, 0x83, 0xF1, 0xF8, 0x1F, 0x8F, 0xC0,
0x7C, 0x7E, 0x03, 0xF7, 0xE0, 0x1F, 0xBF, 0x00, 0x7D, 0xF0, 0x03, 0xFF,
0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x0F, 0xF0, 0x00,
0x7F, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0x0F, 0xE0,
0x00, 0x7E, 0x00, 0x07, 0xF0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x1F,
0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xF0, 0x00,
0x7F, 0x00, 0x07, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xF0, 0x00, 0x7F, 0x00,
0x07, 0xF0, 0x00, 0x7F, 0x80, 0x07, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF0, 0x00, 0x00 };
const GFXglyph kimberle18pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 11, 0, 0 }, // 0x20 ' '
{ 1, 7, 27, 9, 1, -26 }, // 0x21 '!'
{ 25, 13, 10, 13, 0, -26 }, // 0x22 '"'
{ 42, 21, 21, 22, 1, -20 }, // 0x23 '#'
{ 98, 17, 28, 19, 1, -27 }, // 0x24 '$'
{ 158, 19, 14, 21, 1, -18 }, // 0x25 '%'
{ 192, 23, 27, 25, 1, -26 }, // 0x26 '&'
{ 270, 6, 10, 8, 1, -20 }, // 0x27 '''
{ 278, 8, 32, 10, 1, -26 }, // 0x28 '('
{ 310, 8, 32, 10, 1, -26 }, // 0x29 ')'
{ 342, 14, 15, 12, -1, -17 }, // 0x2A '*'
{ 369, 12, 13, 14, 1, -18 }, // 0x2B '+'
{ 389, 6, 10, 8, 1, -6 }, // 0x2C ','
{ 397, 10, 3, 12, 1, -14 }, // 0x2D '-'
{ 401, 6, 7, 8, 1, -6 }, // 0x2E '.'
{ 407, 16, 27, 18, 1, -26 }, // 0x2F '/'
{ 461, 19, 27, 21, 1, -26 }, // 0x30 '0'
{ 526, 8, 27, 11, 1, -26 }, // 0x31 '1'
{ 553, 19, 27, 21, 1, -26 }, // 0x32 '2'
{ 618, 17, 27, 20, 1, -26 }, // 0x33 '3'
{ 676, 19, 27, 22, 1, -26 }, // 0x34 '4'
{ 741, 19, 27, 21, 1, -26 }, // 0x35 '5'
{ 806, 19, 27, 21, 1, -26 }, // 0x36 '6'
{ 871, 20, 27, 22, 1, -26 }, // 0x37 '7'
{ 939, 19, 27, 22, 1, -26 }, // 0x38 '8'
{ 1004, 19, 27, 21, 1, -26 }, // 0x39 '9'
{ 1069, 6, 17, 8, 1, -16 }, // 0x3A ':'
{ 1082, 6, 20, 8, 1, -16 }, // 0x3B ';'
{ 1097, 12, 18, 14, 1, -21 }, // 0x3C '<'
{ 1124, 10, 10, 12, 1, -17 }, // 0x3D '='
{ 1137, 12, 18, 14, 1, -21 }, // 0x3E '>'
{ 1164, 18, 27, 20, 1, -26 }, // 0x3F '?'
{ 1225, 22, 26, 24, 1, -25 }, // 0x40 '@'
{ 1297, 20, 27, 22, 1, -26 }, // 0x41 'A'
{ 1365, 19, 27, 21, 1, -26 }, // 0x42 'B'
{ 1430, 17, 27, 19, 1, -26 }, // 0x43 'C'
{ 1488, 19, 27, 21, 1, -26 }, // 0x44 'D'
{ 1553, 16, 27, 18, 1, -26 }, // 0x45 'E'
{ 1607, 16, 27, 18, 1, -26 }, // 0x46 'F'
{ 1661, 19, 27, 21, 1, -26 }, // 0x47 'G'
{ 1726, 19, 27, 21, 1, -26 }, // 0x48 'H'
{ 1791, 6, 27, 8, 1, -26 }, // 0x49 'I'
{ 1812, 14, 27, 16, 1, -26 }, // 0x4A 'J'
{ 1860, 21, 27, 23, 1, -26 }, // 0x4B 'K'
{ 1931, 16, 27, 18, 1, -26 }, // 0x4C 'L'
{ 1985, 24, 27, 27, 1, -26 }, // 0x4D 'M'
{ 2066, 20, 27, 22, 1, -26 }, // 0x4E 'N'
{ 2134, 19, 27, 21, 1, -26 }, // 0x4F 'O'
{ 2199, 19, 27, 21, 1, -26 }, // 0x50 'P'
{ 2264, 21, 31, 23, 1, -26 }, // 0x51 'Q'
{ 2346, 19, 27, 21, 1, -26 }, // 0x52 'R'
{ 2411, 19, 27, 21, 1, -26 }, // 0x53 'S'
{ 2476, 16, 27, 18, 1, -26 }, // 0x54 'T'
{ 2530, 19, 27, 21, 1, -26 }, // 0x55 'U'
{ 2595, 21, 27, 22, 0, -26 }, // 0x56 'V'
{ 2666, 33, 27, 33, 0, -26 }, // 0x57 'W'
{ 2778, 23, 27, 25, 1, -26 }, // 0x58 'X'
{ 2856, 22, 27, 21, -1, -26 }, // 0x59 'Y'
{ 2931, 20, 27, 22, 1, -26 }, // 0x5A 'Z'
{ 2999, 8, 37, 10, 1, -31 }, // 0x5B '['
{ 3036, 16, 27, 18, 1, -26 }, // 0x5C '\'
{ 3090, 8, 37, 10, 1, -31 }, // 0x5D ']'
{ 3127, 1, 1, 18, 0, 0 }, // 0x5E '^'
{ 3128, 20, 4, 22, 1, 1 }, // 0x5F '_'
{ 3138, 8, 5, 21, 7, -31 }, // 0x60 '`'
{ 3143, 19, 21, 21, 1, -20 }, // 0x61 'a'
{ 3193, 19, 27, 21, 1, -26 }, // 0x62 'b'
{ 3258, 15, 21, 17, 1, -20 }, // 0x63 'c'
{ 3298, 19, 27, 21, 1, -26 }, // 0x64 'd'
{ 3363, 19, 21, 21, 1, -20 }, // 0x65 'e'
{ 3413, 12, 27, 14, 1, -26 }, // 0x66 'f'
{ 3454, 19, 29, 21, 1, -20 }, // 0x67 'g'
{ 3523, 19, 27, 21, 1, -26 }, // 0x68 'h'
{ 3588, 6, 26, 8, 1, -25 }, // 0x69 'i'
{ 3608, 9, 34, 11, 1, -25 }, // 0x6A 'j'
{ 3647, 17, 27, 20, 1, -26 }, // 0x6B 'k'
{ 3705, 6, 27, 8, 1, -26 }, // 0x6C 'l'
{ 3726, 28, 21, 30, 1, -20 }, // 0x6D 'm'
{ 3800, 19, 21, 21, 1, -20 }, // 0x6E 'n'
{ 3850, 19, 21, 21, 1, -20 }, // 0x6F 'o'
{ 3900, 19, 27, 21, 1, -20 }, // 0x70 'p'
{ 3965, 19, 27, 21, 1, -20 }, // 0x71 'q'
{ 4030, 12, 21, 14, 1, -20 }, // 0x72 'r'
{ 4062, 19, 21, 21, 1, -20 }, // 0x73 's'
{ 4112, 8, 27, 10, 1, -26 }, // 0x74 't'
{ 4139, 19, 21, 21, 1, -20 }, // 0x75 'u'
{ 4189, 22, 21, 22, 0, -20 }, // 0x76 'v'
{ 4247, 33, 21, 33, 0, -20 }, // 0x77 'w'
{ 4334, 22, 21, 24, 1, -20 }, // 0x78 'x'
{ 4392, 21, 28, 21, 0, -20 }, // 0x79 'y'
{ 4466, 21, 21, 22, 1, -20 }, // 0x7A 'z'
{ 4522, 1, 1, 18, 0, 0 }, // 0x7B '{'
{ 4523, 4, 31, 6, 1, -25 }, // 0x7C '|'
{ 4539, 1, 1, 18, 0, 0 }, // 0x7D '}'
{ 4540, 1, 1, 18, 0, 0 } }; // 0x7E '~'
const GFXfont kimberle18pt7b PROGMEM = {
(uint8_t *)kimberle18pt7bBitmaps,
(GFXglyph *)kimberle18pt7bGlyphs,
0x20, 0x7E, 46 };
// Approx. 5213 bytes

153
kimberle6pt7b.h

@ -0,0 +1,153 @@
const uint8_t kimberle6pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xE3, 0xC0, 0xDC, 0x62, 0x6D, 0xFF, 0xFB, 0x6F, 0xFF, 0xDB,
0x00, 0x11, 0xFF, 0xFC, 0xF1, 0xF1, 0xDF, 0x7C, 0x40, 0x67, 0x3A, 0x4B,
0x9C, 0xC0, 0xF0, 0xF0, 0xC6, 0xFF, 0xFF, 0xC6, 0xC6, 0xFF, 0xFF, 0xF4,
0x6F, 0x6D, 0xB6, 0xCD, 0x80, 0xC9, 0xB6, 0xDB, 0x7B, 0x00, 0x6F, 0x7F,
0x60, 0x6F, 0xF6, 0xF8, 0xF0, 0xF0, 0x0C, 0x21, 0x84, 0x10, 0x82, 0x10,
0xC0, 0xFF, 0xFF, 0x1E, 0x3C, 0x78, 0xF1, 0xFF, 0xFE, 0xFD, 0xB6, 0xDB,
0x60, 0xFF, 0xFC, 0x1F, 0xFF, 0xF8, 0x30, 0x7F, 0xFE, 0xFF, 0xF0, 0xFF,
0xF8, 0x30, 0xFF, 0xFC, 0x0C, 0x19, 0xF3, 0x66, 0xDF, 0xFF, 0x86, 0x0C,
0xFF, 0xFF, 0x07, 0xFF, 0xE0, 0xC1, 0xFF, 0xFE, 0xFF, 0xFF, 0x07, 0xFF,
0xF8, 0xF1, 0xFF, 0xFE, 0xFF, 0xFC, 0x38, 0x61, 0xC3, 0x0E, 0x18, 0x60,
0xFF, 0xFF, 0x1F, 0xF7, 0xD8, 0xF1, 0xFF, 0xFE, 0xFF, 0xFF, 0x1F, 0xFF,
0xE0, 0xC1, 0xFF, 0xFE, 0xF0, 0xF0, 0xF3, 0xE0, 0x11, 0xDD, 0xC7, 0x1C,
0x40, 0xF0, 0x0F, 0x47, 0x1C, 0x77, 0x71, 0x00, 0xFF, 0xF0, 0xCF, 0x7D,
0x80, 0x18, 0x60, 0x7E, 0x81, 0x9D, 0x85, 0xBD, 0xA5, 0x99, 0x81, 0x7E,
0xFF, 0xFF, 0x1F, 0xFF, 0xF8, 0xF1, 0xE3, 0xC6, 0xFD, 0xFF, 0x1F, 0xFF,
0x98, 0xF1, 0xFF, 0xFC, 0x7F, 0xFC, 0x30, 0xC1, 0x04, 0x1F, 0x7C, 0xFD,
0xFF, 0x1E, 0x3C, 0x78, 0xF1, 0xFF, 0xFC, 0xFF, 0xF1, 0xEF, 0x63, 0x1F,
0xF8, 0xFF, 0xF1, 0xEF, 0x63, 0x18, 0xC0, 0x7F, 0xFF, 0x06, 0x7C, 0xE8,
0xD1, 0xBF, 0x7E, 0xC7, 0x8F, 0x1F, 0xFF, 0xF8, 0xF1, 0xE3, 0xC6, 0xFF,
0xFF, 0xC0, 0x18, 0xC6, 0x31, 0x8C, 0x7F, 0xF8, 0xDD, 0xB3, 0xC7, 0x0F,
0x1A, 0x36, 0x66, 0xCE, 0xC6, 0x31, 0x8C, 0x63, 0x1F, 0xF8, 0xC1, 0xF1,
0xF8, 0xFC, 0x7F, 0x7F, 0xBF, 0x57, 0xBB, 0xDD, 0x80, 0xC7, 0x8F, 0x9F,
0xBF, 0xFB, 0xF3, 0xE3, 0xC6, 0x7D, 0xFF, 0x1E, 0x3C, 0x68, 0xD1, 0xBF,
0x7C, 0xFF, 0xFF, 0x1F, 0xFF, 0xF8, 0x30, 0x60, 0xC0, 0xFE, 0xFE, 0xC6,
0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xFE, 0x03, 0xFF, 0xFF, 0x1F, 0xFF, 0x98,
0xF1, 0xE3, 0xC6, 0x7F, 0xFF, 0xFA, 0x07, 0xC0, 0xC1, 0xFF, 0xFC, 0xFF,
0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1,
0xFF, 0xFE, 0xC6, 0xCD, 0x9B, 0x66, 0xC7, 0x8E, 0x1C, 0x18, 0xC6, 0x7C,
0xCD, 0xB9, 0xB7, 0x66, 0xEC, 0x77, 0x8E, 0xE1, 0xDC, 0x19, 0x80, 0xE3,
0x66, 0x36, 0x3C, 0x18, 0x3C, 0x36, 0x66, 0xE3, 0xE7, 0x66, 0x24, 0x3C,
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFC, 0x30, 0xE1, 0x86, 0x1C, 0x3F,
0xFE, 0xFF, 0x6D, 0xB6, 0xDB, 0x7E, 0xC1, 0x86, 0x0C, 0x30, 0xC1, 0x86,
0x0C, 0xFD, 0xB6, 0xDB, 0x6D, 0xFE, 0x00, 0xFE, 0xCC, 0xFF, 0xF0, 0xFF,
0xCF, 0xFF, 0xC0, 0xC1, 0x83, 0xFF, 0xFC, 0x78, 0xF1, 0xFF, 0xFE, 0xFF,
0xF1, 0x8C, 0x7F, 0xE0, 0x06, 0x0F, 0xFF, 0xFC, 0x78, 0xF1, 0xFF, 0xFE,
0xFF, 0xFC, 0xFF, 0xC3, 0xFF, 0xC0, 0x7F, 0xCE, 0xCC, 0xCC, 0xC0, 0xFF,
0xFF, 0x1E, 0x3C, 0x7F, 0xFF, 0x83, 0xFF, 0xF8, 0xC1, 0x83, 0xFF, 0xFC,
0x78, 0xF1, 0xE3, 0xC6, 0xFF, 0xFF, 0xC0, 0x6D, 0xB6, 0xDB, 0x6F, 0xF0,
0xC3, 0x0D, 0xF6, 0xF3, 0x8F, 0x36, 0xDC, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF,
0xFC, 0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCC, 0xFF, 0xFF, 0x1E, 0x3C, 0x78,
0xF1, 0x80, 0xFF, 0xFF, 0x1E, 0x3C, 0x7F, 0xFF, 0x80, 0xFF, 0xFF, 0x1E,
0x3C, 0x7F, 0xFF, 0xE0, 0xC0, 0xFF, 0xFF, 0x1E, 0x3C, 0x7F, 0xFF, 0x83,
0x06, 0xFF, 0xCC, 0xCC, 0xC0, 0x7F, 0xFF, 0xFB, 0xE0, 0x7F, 0xFF, 0x00,
0xDB, 0xFD, 0xB7, 0xE0, 0xC7, 0x8F, 0x1E, 0x3C, 0x7F, 0xFF, 0x80, 0xC6,
0xCD, 0xB3, 0xE3, 0xC7, 0x06, 0x00, 0xC6, 0x7D, 0xCD, 0xBB, 0x37, 0x63,
0xBC, 0x77, 0x06, 0xE0, 0xE7, 0x7E, 0x3C, 0x18, 0x3C, 0x76, 0xE7, 0xC7,
0xCD, 0xB3, 0x63, 0xC7, 0x0E, 0x1C, 0x30, 0xE0, 0xFF, 0xFC, 0x71, 0xC7,
0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xE0, 0x00, 0x00 };
const GFXglyph kimberle6pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
{ 1, 2, 9, 4, 1, -8 }, // 0x21 '!'
{ 4, 5, 3, 5, 0, -8 }, // 0x22 '"'
{ 6, 7, 7, 8, 0, -6 }, // 0x23 '#'
{ 13, 6, 10, 7, 0, -9 }, // 0x24 '$'
{ 21, 7, 5, 8, 0, -6 }, // 0x25 '%'
{ 26, 8, 9, 9, 0, -8 }, // 0x26 '&'
{ 35, 2, 3, 3, 0, -6 }, // 0x27 '''
{ 36, 3, 11, 4, 0, -8 }, // 0x28 '('
{ 41, 3, 11, 4, 0, -8 }, // 0x29 ')'
{ 46, 4, 5, 4, 0, -5 }, // 0x2A '*'
{ 49, 4, 4, 5, 0, -5 }, // 0x2B '+'
{ 51, 2, 3, 3, 0, -1 }, // 0x2C ','
{ 52, 4, 1, 5, 0, -4 }, // 0x2D '-'
{ 53, 2, 2, 3, 0, -1 }, // 0x2E '.'
{ 54, 6, 9, 7, 0, -8 }, // 0x2F '/'
{ 61, 7, 9, 8, 0, -8 }, // 0x30 '0'
{ 69, 3, 9, 4, 0, -8 }, // 0x31 '1'
{ 73, 7, 9, 8, 0, -8 }, // 0x32 '2'
{ 81, 6, 9, 7, 0, -8 }, // 0x33 '3'
{ 88, 7, 9, 8, 0, -8 }, // 0x34 '4'
{ 96, 7, 9, 8, 0, -8 }, // 0x35 '5'
{ 104, 7, 9, 8, 0, -8 }, // 0x36 '6'
{ 112, 7, 9, 8, 0, -8 }, // 0x37 '7'
{ 120, 7, 9, 8, 0, -8 }, // 0x38 '8'
{ 128, 7, 9, 8, 0, -8 }, // 0x39 '9'
{ 136, 2, 6, 3, 0, -5 }, // 0x3A ':'
{ 138, 2, 6, 3, 0, -4 }, // 0x3B ';'
{ 140, 5, 7, 5, 0, -7 }, // 0x3C '<'
{ 145, 4, 4, 5, 0, -6 }, // 0x3D '='
{ 147, 5, 7, 5, 0, -7 }, // 0x3E '>'
{ 152, 6, 9, 7, 1, -8 }, // 0x3F '?'
{ 159, 8, 9, 9, 0, -8 }, // 0x40 '@'
{ 168, 7, 9, 8, 0, -8 }, // 0x41 'A'
{ 176, 7, 9, 8, 0, -8 }, // 0x42 'B'
{ 184, 6, 9, 7, 0, -8 }, // 0x43 'C'
{ 191, 7, 9, 8, 0, -8 }, // 0x44 'D'
{ 199, 5, 9, 7, 0, -8 }, // 0x45 'E'
{ 205, 5, 9, 7, 0, -8 }, // 0x46 'F'
{ 211, 7, 9, 8, 0, -8 }, // 0x47 'G'
{ 219, 7, 9, 8, 0, -8 }, // 0x48 'H'
{ 227, 2, 9, 3, 0, -8 }, // 0x49 'I'
{ 230, 5, 9, 6, 0, -8 }, // 0x4A 'J'
{ 236, 7, 9, 8, 0, -8 }, // 0x4B 'K'
{ 244, 5, 9, 7, 0, -8 }, // 0x4C 'L'
{ 250, 9, 9, 10, 0, -8 }, // 0x4D 'M'
{ 261, 7, 9, 8, 0, -8 }, // 0x4E 'N'
{ 269, 7, 9, 8, 0, -8 }, // 0x4F 'O'
{ 277, 7, 9, 8, 0, -8 }, // 0x50 'P'
{ 285, 8, 10, 8, 0, -8 }, // 0x51 'Q'
{ 295, 7, 9, 8, 0, -8 }, // 0x52 'R'
{ 303, 7, 9, 8, 0, -8 }, // 0x53 'S'
{ 311, 6, 9, 7, 0, -8 }, // 0x54 'T'
{ 318, 7, 9, 8, 0, -8 }, // 0x55 'U'
{ 326, 7, 9, 8, 0, -8 }, // 0x56 'V'
{ 334, 11, 9, 12, 0, -8 }, // 0x57 'W'
{ 347, 8, 9, 9, 0, -8 }, // 0x58 'X'
{ 356, 8, 9, 8, -1, -8 }, // 0x59 'Y'
{ 365, 7, 9, 8, 0, -8 }, // 0x5A 'Z'
{ 373, 3, 13, 4, 0, -10 }, // 0x5B '['
{ 378, 6, 9, 7, 0, -8 }, // 0x5C '\'
{ 385, 3, 13, 4, 0, -10 }, // 0x5D ']'
{ 390, 1, 1, 6, 0, 0 }, // 0x5E '^'
{ 391, 7, 1, 8, 0, 1 }, // 0x5F '_'
{ 392, 3, 2, 7, 2, -10 }, // 0x60 '`'
{ 393, 6, 7, 8, 1, -6 }, // 0x61 'a'
{ 399, 7, 9, 8, 0, -8 }, // 0x62 'b'
{ 407, 5, 7, 6, 0, -6 }, // 0x63 'c'
{ 412, 7, 9, 8, 0, -8 }, // 0x64 'd'
{ 420, 6, 7, 8, 0, -6 }, // 0x65 'e'
{ 426, 4, 9, 5, 0, -8 }, // 0x66 'f'
{ 431, 7, 10, 7, 0, -6 }, // 0x67 'g'
{ 440, 7, 9, 8, 0, -8 }, // 0x68 'h'
{ 448, 2, 9, 3, 0, -8 }, // 0x69 'i'
{ 451, 3, 12, 4, 0, -8 }, // 0x6A 'j'
{ 456, 6, 9, 7, 0, -8 }, // 0x6B 'k'
{ 463, 2, 9, 3, 0, -8 }, // 0x6C 'l'
{ 466, 10, 7, 11, 0, -6 }, // 0x6D 'm'
{ 475, 7, 7, 8, 0, -6 }, // 0x6E 'n'
{ 482, 7, 7, 7, 0, -6 }, // 0x6F 'o'
{ 489, 7, 9, 8, 0, -6 }, // 0x70 'p'
{ 497, 7, 9, 8, 0, -6 }, // 0x71 'q'
{ 505, 4, 7, 5, 0, -6 }, // 0x72 'r'
{ 509, 7, 7, 8, 0, -6 }, // 0x73 's'
{ 516, 3, 9, 4, 0, -8 }, // 0x74 't'
{ 520, 7, 7, 8, 0, -6 }, // 0x75 'u'
{ 527, 7, 7, 8, 0, -6 }, // 0x76 'v'
{ 534, 11, 7, 12, 0, -6 }, // 0x77 'w'
{ 544, 8, 7, 8, 0, -6 }, // 0x78 'x'
{ 551, 7, 10, 8, 0, -6 }, // 0x79 'y'
{ 560, 7, 7, 8, 0, -6 }, // 0x7A 'z'
{ 567, 1, 1, 6, 0, 0 }, // 0x7B '{'
{ 568, 1, 11, 2, 0, -8 }, // 0x7C '|'
{ 570, 1, 1, 6, 0, 0 }, // 0x7D '}'
{ 571, 1, 1, 6, 0, 0 } }; // 0x7E '~'
const GFXfont kimberle6pt7b PROGMEM = {
(uint8_t *)kimberle6pt7bBitmaps,
(GFXglyph *)kimberle6pt7bGlyphs,
0x20, 0x7E, 15 };
// Approx. 1244 bytes

188
kimberle8pt7b.h

@ -0,0 +1,188 @@
const uint8_t kimberle8pt7bBitmaps[] PROGMEM = {
0x00, 0xEE, 0x66, 0x66, 0x60, 0x07, 0x77, 0xCF, 0x3C, 0xF3, 0x30, 0x0C,
0xCF, 0xFF, 0xFF, 0x33, 0x0C, 0xCF, 0xFF, 0xFF, 0x33, 0x0C, 0xC0, 0x18,
0x1F, 0x7F, 0x7F, 0xF8, 0xF8, 0x7F, 0x7F, 0x1F, 0x7F, 0x7F, 0x7C, 0x18,
0x71, 0xC5, 0x23, 0xD1, 0x17, 0x89, 0x47, 0x9C, 0x78, 0x1F, 0x03, 0xE0,
0x71, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0xE3, 0x9F, 0xFF, 0xFF, 0xBF,
0xF0, 0xFD, 0xA0, 0x6F, 0xED, 0xB6, 0xDB, 0x6E, 0xD8, 0xDB, 0xB6, 0xDB,
0x6D, 0xBF, 0xB0, 0x33, 0xEF, 0xDE, 0xFE, 0xE3, 0x00, 0x38, 0x73, 0xFF,
0xFF, 0xE7, 0x00, 0xFF, 0xA0, 0xFF, 0xC0, 0xFF, 0x80, 0x03, 0x02, 0x06,
0x04, 0x0C, 0x08, 0x18, 0x10, 0x30, 0x20, 0x60, 0xC0, 0x7F, 0x7F, 0xFF,
0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xFF, 0xFF, 0xEF, 0xE0, 0xEF,
0xF7, 0x77, 0x77, 0x77, 0x77, 0xFF, 0x7F, 0xFF, 0xE0, 0x77, 0xFF, 0xFF,
0xFD, 0xC0, 0xE0, 0x7F, 0xFF, 0xFF, 0xF0, 0xFE, 0xFF, 0xFF, 0x07, 0xFF,
0xFF, 0xFF, 0x07, 0x07, 0xFF, 0xFF, 0xFE, 0x07, 0x03, 0x81, 0xC7, 0xE7,
0x73, 0x3B, 0x9D, 0xFF, 0xFF, 0xFF, 0xC1, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF,
0xFC, 0x0F, 0xF7, 0xFF, 0xFE, 0x07, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F,
0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0xC7, 0xE3, 0xFF, 0xFF, 0xEF,
0xE0, 0xFF, 0xFF, 0xFF, 0xF8, 0x0E, 0x07, 0x01, 0xC0, 0xE0, 0x38, 0x1C,
0x07, 0x03, 0x81, 0xE0, 0x7F, 0x7F, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF,
0xC7, 0xE3, 0xFF, 0xFF, 0xEF, 0xE0, 0x7F, 0x7F, 0xFF, 0xFC, 0x7F, 0xFF,
0xFF, 0xFE, 0x07, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0x81, 0xFF, 0xFF,
0x81, 0xFF, 0x40, 0x08, 0x73, 0x9E, 0xF8, 0xE1, 0xC2, 0xFF, 0xC1, 0xFF,
0x80, 0x21, 0xCF, 0x8F, 0x3D, 0xEF, 0x08, 0xFF, 0x7F, 0xFF, 0xE0, 0x70,
0x38, 0xFC, 0xFC, 0x70, 0x00, 0x1C, 0x0E, 0x07, 0x00, 0x7F, 0xD0, 0x1D,
0xE7, 0x7D, 0xC3, 0x70, 0xDD, 0xF7, 0x6D, 0xC4, 0x70, 0x14, 0x05, 0xFF,
0x7F, 0xBF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xE1, 0xF8,
0x7E, 0x1F, 0x87, 0xFF, 0x7F, 0xF8, 0xFC, 0x7F, 0xFF, 0xFB, 0xFD, 0xC7,
0xE3, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0x60,
0x60, 0x60, 0x7F, 0x7F, 0x3F, 0xFF, 0x7F, 0xFF, 0xFC, 0x7E, 0x3F, 0x1F,
0x8F, 0xC7, 0xE3, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFC,
0xFC, 0xFC, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFC,
0xFC, 0xFC, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x7F, 0xFF, 0xFF, 0xFC, 0x0E,
0xFF, 0x7D, 0xBE, 0xC7, 0x63, 0xBF, 0xDF, 0xE7, 0xF0, 0xE3, 0xF1, 0xF8,
0xFC, 0x7F, 0xFF, 0xFF, 0xFF, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x70, 0xFF,
0xFF, 0xFF, 0xFF, 0xF0, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0F,
0xFF, 0xFF, 0xE0, 0xE3, 0xB9, 0xCE, 0xE3, 0xF0, 0xF8, 0x3E, 0x0F, 0xC3,
0xB8, 0xE7, 0x39, 0xCE, 0x3B, 0x8F, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38,
0x70, 0xE1, 0xFF, 0xFF, 0xF0, 0xE0, 0x7E, 0x07, 0xF0, 0xFF, 0x0F, 0xF0,
0xFF, 0x9F, 0xF9, 0xFF, 0x9F, 0xFF, 0xFE, 0xF7, 0xEF, 0x7E, 0xF7, 0xC1,
0xF8, 0x7F, 0x1F, 0xC7, 0xF9, 0xFF, 0x7E, 0xFF, 0x9F, 0xE7, 0xF8, 0xFE,
0x1F, 0x83, 0x3F, 0x3F, 0xFF, 0xFC, 0x7E, 0x3F, 0x1D, 0x8E, 0xC7, 0x63,
0xBF, 0xDF, 0xE7, 0xE0, 0xFF, 0x7F, 0xF8, 0xFC, 0x7F, 0xFF, 0xFF, 0xFD,
0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x00, 0x7F, 0x3F, 0xEF, 0xFB, 0x8E, 0xE3,
0xB8, 0xEE, 0x3B, 0x8E, 0xE3, 0xBF, 0xEF, 0xF9, 0xFE, 0x01, 0xC0, 0x20,
0xFF, 0x7F, 0xF8, 0xFC, 0x7F, 0xFF, 0xFB, 0xFD, 0xC7, 0xE3, 0xF1, 0xF8,
0xFC, 0x70, 0x3F, 0xBF, 0xFF, 0xFC, 0x06, 0x03, 0xFD, 0xFE, 0x07, 0x03,
0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xF9, 0xC3, 0x87, 0x0E, 0x1C, 0x38,
0x70, 0xE1, 0xC0, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7,
0xE3, 0xFF, 0xFF, 0xEF, 0xE0, 0xE1, 0xD8, 0x67, 0x39, 0xCE, 0x73, 0x0C,
0xC3, 0xF0, 0xFC, 0x1E, 0x07, 0x81, 0xE0, 0x30, 0xE3, 0x8F, 0xC7, 0x1D,
0xCE, 0x33, 0x9C, 0xE7, 0x3D, 0xC6, 0xFB, 0x8F, 0xF6, 0x1F, 0x7C, 0x1E,
0xF8, 0x3D, 0xE0, 0x79, 0xC0, 0x73, 0x80, 0xF0, 0xEE, 0x38, 0xE6, 0x0D,
0xC1, 0xB0, 0x1C, 0x03, 0xC0, 0xD8, 0x1B, 0x87, 0x31, 0xC7, 0x78, 0x70,
0xE3, 0xF1, 0xD8, 0xCE, 0xE3, 0x61, 0xF0, 0x70, 0x38, 0x1C, 0x0E, 0x07,
0x03, 0x80, 0xFF, 0xFF, 0xFF, 0xF8, 0x1C, 0x07, 0x03, 0x81, 0xC0, 0xE0,
0x38, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xED, 0xB6, 0xDB, 0x6D, 0xBF, 0xE0,
0xE0, 0x70, 0x70, 0x30, 0x38, 0x18, 0x18, 0x1C, 0x0C, 0x0E, 0x06, 0x07,
0xFF, 0xB6, 0xDB, 0x6D, 0xB6, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0xC3,
0x7F, 0x3F, 0xDF, 0xE0, 0x77, 0xFF, 0x1F, 0xFF, 0xFF, 0x7F, 0x00, 0xE0,
0x70, 0x38, 0x1F, 0xEF, 0xFF, 0x1F, 0x8F, 0xC7, 0xE3, 0xFF, 0xFF, 0xFF,
0xE0, 0x7F, 0xFF, 0xFF, 0x0E, 0x1C, 0x3F, 0xFF, 0x7E, 0x03, 0x81, 0xC0,
0xEF, 0xFF, 0xFF, 0x1F, 0x8F, 0xC7, 0xE3, 0xFF, 0xFF, 0xEF, 0xF0, 0x7F,
0x7F, 0xFF, 0xFC, 0x7F, 0xF7, 0x03, 0xFD, 0xFE, 0x7F, 0x00, 0x7F, 0xFF,
0xF8, 0xFB, 0xEE, 0x38, 0xE3, 0x8E, 0x38, 0x7F, 0xFF, 0xF8, 0xFC, 0x7E,
0x3F, 0x1F, 0xFF, 0xFF, 0x7F, 0x81, 0xFF, 0xFF, 0xFF, 0xF0, 0xE0, 0x70,
0x38, 0x1F, 0xEF, 0xFF, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x70,
0xFC, 0x7F, 0xFF, 0xFF, 0xF0, 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x7F,
0xFE, 0xE0, 0xE0, 0xE0, 0xEF, 0xEC, 0xFC, 0xF8, 0xF0, 0xF8, 0xFC, 0xEC,
0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xF7, 0xFF, 0xF9, 0xCF, 0xCE,
0x7E, 0x73, 0xF3, 0x9F, 0x9C, 0xFC, 0xE7, 0xE7, 0x38, 0x7F, 0x7F, 0xF8,
0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0x80, 0x7F, 0x7F, 0xF8, 0xFC,
0x7E, 0x3F, 0x1F, 0xFF, 0xFF, 0x7F, 0x00, 0xFF, 0x7F, 0xF8, 0xFC, 0x7E,
0x3F, 0x1F, 0xFF, 0xFF, 0xFF, 0x70, 0x38, 0x1C, 0x00, 0x7F, 0xFF, 0xF8,
0xFC, 0x7E, 0x3F, 0x1F, 0xFF, 0xFF, 0x7F, 0x81, 0xC0, 0xE0, 0x70, 0x7F,
0xFF, 0xF8, 0xE3, 0x8E, 0x38, 0xE0, 0x7F, 0xBF, 0xFF, 0xEC, 0x07, 0xF8,
0x1D, 0xFE, 0xFF, 0x7F, 0x00, 0xEE, 0xEF, 0xFF, 0xEE, 0xEF, 0xF7, 0xE3,
0xF1, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0xFF, 0xFF, 0x7F, 0x00, 0xE1, 0xDC,
0xE7, 0x38, 0xCE, 0x3F, 0x0F, 0xC1, 0xE0, 0x78, 0x0C, 0x00, 0xE3, 0x8F,
0xC7, 0x1D, 0xCE, 0x73, 0xBE, 0xE3, 0xFF, 0x87, 0xDF, 0x07, 0xBC, 0x0F,
0x78, 0x0C, 0x70, 0xF1, 0xE7, 0x70, 0x7E, 0x0F, 0x80, 0xE0, 0x3E, 0x0E,
0xE1, 0xDE, 0xF1, 0xE0, 0xE1, 0xD8, 0xE7, 0x39, 0xDC, 0x3F, 0x0F, 0x81,
0xE0, 0x78, 0x1C, 0x07, 0x01, 0x80, 0xE0, 0xFF, 0xFF, 0xFF, 0xFE, 0x03,
0x80, 0xE0, 0x38, 0x0F, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xFF,
0xF0, 0x00, 0x00 };
const GFXglyph kimberle8pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
{ 1, 4, 12, 5, 0, -11 }, // 0x21 '!'
{ 7, 6, 4, 7, 0, -11 }, // 0x22 '"'
{ 10, 10, 10, 11, 0, -9 }, // 0x23 '#'
{ 23, 8, 13, 9, 0, -12 }, // 0x24 '$'
{ 36, 9, 7, 10, 0, -8 }, // 0x25 '%'
{ 44, 11, 12, 12, 0, -11 }, // 0x26 '&'
{ 61, 3, 4, 4, 0, -8 }, // 0x27 '''
{ 63, 3, 15, 5, 1, -12 }, // 0x28 '('
{ 69, 3, 15, 5, 1, -12 }, // 0x29 ')'
{ 75, 6, 7, 5, 0, -7 }, // 0x2A '*'
{ 81, 7, 6, 7, 0, -8 }, // 0x2B '+'
{ 87, 3, 4, 4, 0, -2 }, // 0x2C ','
{ 89, 5, 2, 6, 0, -6 }, // 0x2D '-'
{ 91, 3, 3, 4, 0, -2 }, // 0x2E '.'
{ 93, 8, 12, 9, 0, -11 }, // 0x2F '/'
{ 105, 9, 12, 10, 0, -11 }, // 0x30 '0'
{ 119, 4, 12, 5, 0, -11 }, // 0x31 '1'
{ 125, 9, 12, 10, 0, -11 }, // 0x32 '2'
{ 139, 8, 12, 9, 1, -11 }, // 0x33 '3'
{ 151, 9, 12, 10, 1, -11 }, // 0x34 '4'
{ 165, 9, 12, 10, 0, -11 }, // 0x35 '5'
{ 179, 9, 12, 10, 0, -11 }, // 0x36 '6'
{ 193, 10, 12, 11, 0, -11 }, // 0x37 '7'
{ 208, 9, 12, 10, 0, -11 }, // 0x38 '8'
{ 222, 9, 12, 10, 0, -11 }, // 0x39 '9'
{ 236, 3, 8, 4, 0, -7 }, // 0x3A ':'
{ 239, 3, 9, 4, 0, -7 }, // 0x3B ';'
{ 243, 6, 8, 7, 0, -9 }, // 0x3C '<'
{ 249, 5, 5, 6, 0, -8 }, // 0x3D '='
{ 253, 6, 8, 7, 0, -9 }, // 0x3E '>'
{ 259, 9, 12, 10, 0, -11 }, // 0x3F '?'
{ 273, 10, 12, 11, 0, -11 }, // 0x40 '@'
{ 288, 10, 12, 10, 0, -11 }, // 0x41 'A'
{ 303, 9, 12, 10, 0, -11 }, // 0x42 'B'
{ 317, 8, 12, 9, 0, -11 }, // 0x43 'C'
{ 329, 9, 12, 10, 0, -11 }, // 0x44 'D'
{ 343, 8, 12, 9, 0, -11 }, // 0x45 'E'
{ 355, 8, 12, 9, 0, -11 }, // 0x46 'F'
{ 367, 9, 12, 10, 0, -11 }, // 0x47 'G'
{ 381, 9, 12, 10, 0, -11 }, // 0x48 'H'
{ 395, 3, 12, 4, 0, -11 }, // 0x49 'I'
{ 400, 7, 12, 8, 0, -11 }, // 0x4A 'J'
{ 411, 10, 12, 11, 0, -11 }, // 0x4B 'K'
{ 426, 7, 12, 9, 0, -11 }, // 0x4C 'L'
{ 437, 12, 12, 13, 0, -11 }, // 0x4D 'M'
{ 455, 10, 12, 11, 0, -11 }, // 0x4E 'N'
{ 470, 9, 12, 10, 0, -11 }, // 0x4F 'O'
{ 484, 9, 12, 10, 0, -11 }, // 0x50 'P'
{ 498, 10, 14, 11, 0, -11 }, // 0x51 'Q'
{ 516, 9, 12, 10, 0, -11 }, // 0x52 'R'
{ 530, 9, 12, 10, 0, -11 }, // 0x53 'S'
{ 544, 7, 12, 9, 1, -11 }, // 0x54 'T'
{ 555, 9, 12, 10, 0, -11 }, // 0x55 'U'
{ 569, 10, 12, 10, 0, -11 }, // 0x56 'V'
{ 584, 15, 12, 16, 0, -11 }, // 0x57 'W'
{ 607, 11, 12, 12, 0, -11 }, // 0x58 'X'
{ 624, 9, 12, 10, 0, -11 }, // 0x59 'Y'
{ 638, 10, 12, 11, 0, -11 }, // 0x5A 'Z'
{ 653, 3, 17, 5, 1, -14 }, // 0x5B '['
{ 660, 8, 12, 9, 0, -11 }, // 0x5C '\'
{ 672, 3, 17, 5, 1, -14 }, // 0x5D ']'
{ 679, 1, 1, 8, 0, 0 }, // 0x5E '^'
{ 680, 10, 2, 11, 0, 1 }, // 0x5F '_'
{ 683, 4, 2, 10, 3, -13 }, // 0x60 '`'
{ 684, 9, 9, 10, 0, -8 }, // 0x61 'a'
{ 695, 9, 12, 10, 0, -11 }, // 0x62 'b'
{ 709, 7, 9, 8, 0, -8 }, // 0x63 'c'
{ 717, 9, 12, 10, 0, -11 }, // 0x64 'd'
{ 731, 9, 9, 10, 0, -8 }, // 0x65 'e'
{ 742, 6, 12, 7, 0, -11 }, // 0x66 'f'
{ 751, 9, 13, 9, 0, -8 }, // 0x67 'g'
{ 766, 9, 12, 10, 0, -11 }, // 0x68 'h'
{ 780, 3, 12, 4, 0, -11 }, // 0x69 'i'
{ 785, 4, 16, 6, 1, -11 }, // 0x6A 'j'
{ 793, 8, 12, 10, 0, -11 }, // 0x6B 'k'
{ 805, 3, 12, 4, 0, -11 }, // 0x6C 'l'
{ 810, 13, 9, 14, 0, -8 }, // 0x6D 'm'
{ 825, 9, 9, 10, 0, -8 }, // 0x6E 'n'
{ 836, 9, 9, 9, 0, -8 }, // 0x6F 'o'
{ 847, 9, 12, 10, 0, -8 }, // 0x70 'p'
{ 861, 9, 12, 10, 0, -8 }, // 0x71 'q'
{ 875, 6, 9, 7, 0, -8 }, // 0x72 'r'
{ 882, 9, 9, 10, 0, -8 }, // 0x73 's'
{ 893, 4, 12, 5, 0, -11 }, // 0x74 't'
{ 899, 9, 9, 10, 0, -8 }, // 0x75 'u'
{ 910, 10, 9, 11, 0, -8 }, // 0x76 'v'
{ 922, 15, 9, 16, 0, -8 }, // 0x77 'w'
{ 939, 11, 9, 11, 0, -8 }, // 0x78 'x'
{ 952, 10, 12, 10, 0, -8 }, // 0x79 'y'
{ 967, 11, 9, 11, 0, -8 }, // 0x7A 'z'
{ 980, 1, 1, 8, 0, 0 }, // 0x7B '{'
{ 981, 2, 14, 3, 0, -11 }, // 0x7C '|'
{ 985, 1, 1, 8, 0, 0 }, // 0x7D '}'
{ 986, 1, 1, 8, 0, 0 } }; // 0x7E '~'
const GFXfont kimberle8pt7b PROGMEM = {
(uint8_t *)kimberle8pt7bBitmaps,
(GFXglyph *)kimberle8pt7bGlyphs,
0x20, 0x7E, 20 };
// Approx. 1659 bytes

87
main.cpp

@ -0,0 +1,87 @@
#include "main.h"
namespace Main {
void begin() {
// Wait for the next frame to minimize chance of visible tearing
Video::video.waitForFrame();
// Clear screen
Video::video.fillScreen(0x00);
Video::video.setFont(&kimberle8pt7b);
Video::video.setCursor(0,13);
Video::video.setTextColor(0xFF);
String frequency = String(Channels::getFrequency(vtx_channel)) + "MHz";
Video::video.print(frequency);
Video::video.setCursor(0,28);
String current_channel = Channels::getName(vtx_channel);
Video::video.print(current_channel);
Video::video.setFont(&kimberle8pt7b);
Video::video.setTextColor(0xFF);
// Display signal bars
uint8_t rssi1_bar = map(rssi1, 0, MAX_RSSI, 0, 255);
uint8_t rssi2_bar = map(rssi2, 0, MAX_RSSI, 0, 255);
signalbar(rssi1_bar, rssi2_bar);
// Display cubes...
/*
* +---+---+---+---+---+---+---+---+
* | | | | | | | | |
* +---+---+---+---+---+---+---+---+
*/
channelbox();
}
void channelbox() {
uint8_t color_scheme = 0xFF;
uint8_t x1, margin;
String bandname = Channels::getName(vtx_channel);
String bandnameFront = bandname.substring(0, 1);
uint8_t channel_number = Channels::getChannelNumber(vtx_channel);
margin = 3;
for(uint8_t box = 0; box < 8; box++) {
x1 = box * 25 + (7 * box);
color_scheme = (channel_number == (box + 1)) ? 0x1C : 0x29;
// Top Line
Video::video.drawFastHLine(margin + 0 + x1, 65, 25, color_scheme);
// Left Line
Video::video.drawFastVLine(margin + 0 + x1, 65, 25, color_scheme);
// Right Line
Video::video.drawFastVLine(margin + 25 + x1, 65, 25, color_scheme);
// Bottom Line
Video::video.drawFastHLine(margin + 0 + x1, 90, 25, color_scheme);
Video::video.setCursor(margin + 3 + x1, 83);
Video::video.setTextColor(color_scheme);
Video::video.print(bandnameFront + String(box + 1));
}
}
void signalbar(uint8_t rssi1, uint8_t rssi2) {
// uint8_t color_scheme = 0xFC;
uint8_t color_scheme = 0x1F;
Video::video.drawFastHLine(0, 35, 255, color_scheme);
Video::video.drawFastHLine(0, 45, 255, color_scheme);
Video::video.drawFastVLine(0, 35, 10, color_scheme);
Video::video.drawFastVLine(255, 35, 10, color_scheme);
Video::video.fillRect(0, 36, rssi1, 9 , color_scheme);
Video::video.drawFastHLine(0, 47, 255, color_scheme);
Video::video.drawFastHLine(0, 57, 255, color_scheme);
Video::video.drawFastVLine(0, 47, 10, color_scheme);
Video::video.drawFastVLine(255, 47, 10, color_scheme);
Video::video.fillRect(0, 48, rssi2, 10, color_scheme);
}
}

23
main.h

@ -0,0 +1,23 @@
/*
* Filename: main.h
* Date: Mon 20 Sep 22:14:58 +08 2021
* Author: Englebert
* Description:
* - Main minimalist screen
*/
#ifndef MAIN_H
#define MAIN_H
#include <Arduino.h>
#include "BertFPVDiversity.h"
#include "video.h"
#include "channels.h"
namespace Main {
void begin();
void signalbar(uint8_t rssi1, uint8_t rssi2);
void channelbox();
}
#endif

43
menu.cpp

@ -6,7 +6,7 @@
namespace Menu {
int8_t menu_position = 0;
uint8_t MAX_MENU_ITEMS = 4;
uint8_t MAX_MENU_ITEMS = 3;
void begin() {
// Wait for the next frame to minimize chance of visible tearing
@ -15,40 +15,33 @@ namespace Menu {
// Clear screen
Video::video.fillScreen(0x00);
uint8_t title_color = 0xBB;
uint8_t title_color = 0xFF;
Video::video.setTextColor(title_color);
Video::video.setFont(&kimberle8pt7b);
Video::video.setTextSize(1);
Video::video.setCursor(20,30);
Video::video.print("STATUS");
Video::video.setCursor(20,45);
Video::video.print("SCAN");
Video::video.setCursor(20,60);
Video::video.print("REBOOT");
switch(menu_position) {
case 0:
Video::drawBitmap(60, 50, icon_search, 100, 100, 0xFF);
Video::video.setFont(&FreeSansBold18pt7b);
Video::video.setCursor(55,180);
Video::video.setTextColor(title_color);
Video::video.print("Search");
// Video::drawBitmap(60, 50, icon_search, 100, 100, 0xFF);
Video::video.setCursor(10,30);
break;
case 1:
Video::drawBitmap(60, 50, icon_wifi, 100, 100, 0xFF);
Video::video.setFont(&FreeSansBold18pt7b);
Video::video.setCursor(65,180);
Video::video.setTextColor(title_color);
Video::video.print("WiFi");
Video::video.setCursor(10,45);
//Video::drawBitmap(60, 50, icon_wifi, 100, 100, 0xFF);
break;
case 2:
Video::drawBitmap(60, 50, icon_settings, 100, 100, 0xFF);
Video::video.setFont(&FreeSansBold18pt7b);
Video::video.setCursor(40,180);
Video::video.setTextColor(title_color);
Video::video.print("Settings");
break;
case 3:
Video::drawBitmap(60, 50, icon_reboot, 100, 100, 0xFF);
Video::video.setFont(&FreeSansBold18pt7b);
Video::video.setCursor(40,180);
Video::video.setTextColor(title_color);
Video::video.print("Reboot");
//Video::drawBitmap(60, 50, icon_settings, 100, 100, 0xFF);
Video::video.setCursor(10,60);
break;
}
Video::video.print(">");
}
}

9
rx5808.cpp

@ -1,6 +1,7 @@
#include "rx5808.h"
#include <SPI.h>
#include "SoftSPI.h"
#include "channels.h"
#define SPI_ADDRESS_SYNTH_B 0x01
#define SPI_ADDRESS_POWER 0x0A
@ -57,6 +58,14 @@ namespace RX5808 {
sendRegister(SPI_ADDRESS_STATE, 0b00000000000000000000);
// sendCommand(0b00000000000000000000);
}
void setChannel(uint8_t channel) {
setSynthRegisterB(Channels::getSynthRegisterB(channel));
}
void setChannelByFreq(uint16_t freq) {
setSynthRegisterB(Channels::getSynthRegisterBFreq(freq));
}
}

3
rx5808.h

@ -20,6 +20,9 @@ namespace RX5808 {
void rxStandby(uint8_t receiver_id);
void rxPowerOn(uint8_t receiver_id);
void rxReset(uint8_t receiver_id);
void setChannel(uint8_t channel);
void setChannelByFreq(uint16_t freq);
}
#endif

2
video.cpp

@ -2,7 +2,7 @@
namespace Video {
// Create an instance of the graphics library
ESP_8_BIT_GFX video(true /* = NTSC */, 8 /* = RGB332 color */);
ESP_8_BIT_GFX video(false /* = NTSC */, 8 /* = RGB332 color */);
void begin() {
video.begin();

9
video.h

@ -10,10 +10,11 @@
#define VIDEO_H
#include "BertFPVDiversity.h"
#include <ESP_8_BIT_GFX.h>
#include <Fonts/FreeSansBold18pt7b.h>
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSans9pt7b.h>
#include "ESP_8_BIT_GFX.h"
#include "kimberle6pt7b.h"
#include "kimberle8pt7b.h"
#include "kimberle13pt7b.h"
#include "kimberle18pt7b.h"
namespace Video {
extern ESP_8_BIT_GFX video;

Loading…
Cancel
Save