From 82d4ee110fa4cb7194c47a09c2348bd308225c56 Mon Sep 17 00:00:00 2001 From: "Hansi, dl9rdz" Date: Sun, 13 Oct 2019 18:14:33 +0200 Subject: [PATCH] some more display configurations options (select fonts, better but still incomplete support for ILI9225). autodetect of new t-beam 1.0 with oled --- RX_FSK/RX_FSK.ino | 51 +++- RX_FSK/data/index.html | 2 + RX_FSK/data/screens.txt | 38 +++ RX_FSK/version.h | 2 +- libraries/SondeLib/Display.cpp | 373 +++++++++++++++++---------- libraries/SondeLib/Display.h | 27 +- libraries/SondeLib/Sonde.cpp | 53 ++-- libraries/SondeLib/Sonde.h | 10 +- libraries/SondeLib/TFT22_ILI9225.cpp | 3 +- libraries/fonts/FreeMono12pt7b.h | 227 ++++++++++++++++ libraries/fonts/FreeMono9pt7b.h | 176 +++++++++++++ libraries/fonts/Picopixel.h | 123 +++++++++ 12 files changed, 915 insertions(+), 170 deletions(-) create mode 100644 libraries/fonts/FreeMono12pt7b.h create mode 100644 libraries/fonts/FreeMono9pt7b.h create mode 100644 libraries/fonts/Picopixel.h diff --git a/RX_FSK/RX_FSK.ino b/RX_FSK/RX_FSK.ino index 7570b4a..6e65f9d 100644 --- a/RX_FSK/RX_FSK.ino +++ b/RX_FSK/RX_FSK.ino @@ -48,6 +48,8 @@ WiFiClient client; WiFiServer tncserver(14580); WiFiClient tncclient; +boolean forceReloadScreenConfig = false; + enum KeyPress { KP_NONE = 0, KP_SHORT, KP_DOUBLE, KP_MID, KP_LONG }; // "doublepress" is now also used to eliminate key glitch on TTGO T-Beam startup (SENSOR_VN/GPIO39) @@ -93,6 +95,19 @@ String processor(const String& var) { if (var == "VERSION_ID") { return String(version_id); } + if (var == "AUTODETECT_INFO") { + char tmpstr[128]; + const char *fpstr; + int i=0; + while(fingerprintValue[i] != sonde.fingerprint && fingerprintValue[i]!=-1) i++; + if(fingerprintValue[i]==-1) { + fpstr = "Unknown board"; + } else { + fpstr = fingerprintText[i]; + } + snprintf(tmpstr, 128, "Fingerprint %d (%s)", sonde.fingerprint, fpstr); + return String(tmpstr); + } return String(); } @@ -644,7 +659,7 @@ const char *handleEditPost(AsyncWebServerRequest *request) { file.close(); if (strcmp(filename.c_str(), "screens.txt") == 0) { // screens update => reload - disp.initFromFile(); + forceReloadScreenConfig = true; } return ""; } @@ -886,7 +901,7 @@ void gpsTask(void *parameter) { bool b = nmea.getAltitude(alt); bool valid = nmea.isValid(); uint8_t hdop = nmea.getHDOP(); - Serial.printf("\nDecode: valid: %d N %ld E %ld alt %ld (%d) dop:%d", valid ? 1 : 0, lat, lon, alt, b, hdop); + //Serial.printf("\nDecode: valid: %d N %ld E %ld alt %ld (%d) dop:%d", valid ? 1 : 0, lat, lon, alt, b, hdop); } } delay(50); @@ -1053,7 +1068,6 @@ int getKeyPressEvent() { } #define SSD1306_ADDRESS 0x3c -#define AXP192_SLAVE_ADDRESS 0x34 bool ssd1306_found = false; bool axp192_found = false; @@ -1108,8 +1122,27 @@ void setup() Serial.printf("%d:%d ", i, v); } Serial.println(""); + #if 0 delay(2000); - + // temporary test + volatile uint32_t *ioport = portOutputRegister(digitalPinToPort(4)); + uint32_t portmask = digitalPinToBitMask(4); + int t = millis(); + for(int i=0; i<10000000; i++) { + digitalWrite(4, LOW); + digitalWrite(4, HIGH); + } + int res = millis() - t; + Serial.printf("Duration w/ digitalWriteo: %d\n", res); + + t = millis(); + for(int i=0; i<10000000; i++) { + *ioport |= portmask; + *ioport &= ~portmask; + } + res = millis() - t; + Serial.printf("Duration w/ fast io: %d\n", res); +#endif for (int i = 0; i < 39; i++) { Serial.printf("%d:%d ", i, initlevels[i]); } @@ -1342,7 +1375,8 @@ static const char *action2text(uint8_t action) { void loopDecoder() { // sonde knows the current type and frequency, and delegates to the right decoder uint16_t res = sonde.waitRXcomplete(); - int action, event = 0; + int action; + Serial.printf("waitRX result is %x\n", (int)res); action = (int)(res >> 8); // TODO: update displayed sonde? @@ -1406,6 +1440,10 @@ void loopDecoder() { } } Serial.println("updateDisplay started"); + if(forceReloadScreenConfig) { + disp.initFromFile(); + forceReloadScreenConfig = false; + } sonde.updateDisplay(); Serial.println("updateDisplay done"); } @@ -1676,8 +1714,9 @@ void loopWifiBackground() { } } else if (wifi_state == WIFI_CONNECTED) { if (!WiFi.isConnected()) { - sonde.clearIP(); + sonde.setIP("",false); sonde.updateDisplayIP(); + wifi_state = WIFI_DISABLED; // restart scan enableNetwork(false); WiFi.disconnect(true); diff --git a/RX_FSK/data/index.html b/RX_FSK/data/index.html index c5e98c2..b7a74e0 100644 --- a/RX_FSK/data/index.html +++ b/RX_FSK/data/index.html @@ -59,6 +59,8 @@ Copyright © 2019 by Hansi Reiser, DL9RDZ
(version %VERSION_ID%)
with mods by Meinhard Guenther, DL2MF
+
+ Autodetect info: %AUTODETECT_INFO%

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
diff --git a/RX_FSK/data/screens.txt b/RX_FSK/data/screens.txt index ffbca23..69a6264 100644 --- a/RX_FSK/data/screens.txt +++ b/RX_FSK/data/screens.txt @@ -36,6 +36,44 @@ # Mx telemetry value x (t temp p preassure h hyg) # Gx value relativ to GPS reference point (x: D dist, I direction) GV. GPS valid symbol; GL, GO, GA: ref lat long alt # R RSSI +# +# fonts=x,y can be used to select font (x=small, y=large) for all items below +# for SSD1306, x and y can be used to select one of those fonts: +# (y should be a 1x2 font (1,5,6,7), x a small font) +# u8x8_font_chroma48medium8_r, // 0 ** default small +# u8x8_font_7x14_1x2_f, // 1 ** default large +# u8x8_font_amstrad_cpc_extended_f, // 2 +# u8x8_font_5x7_f, // 3 +# u8x8_font_5x8_f, // 4 +# u8x8_font_8x13_1x2_f, // 5 +# u8x8_font_8x13B_1x2_f, // 6 +# u8x8_font_7x14B_1x2_f, // 7 +# u8x8_font_artossans8_r, // 8 +# u8x8_font_artosserif8_r, // 9 +# u8x8_font_torussansbold8_r, // 10 +# u8x8_font_victoriabold8_r, // 11 +# u8x8_font_victoriamedium8_r, // 12 +# u8x8_font_pressstart2p_f, // 13 +# u8x8_font_pcsenior_f, // 14 +# u8x8_font_pxplusibmcgathin_f, // 15 +# u8x8_font_pxplusibmcga_f, // 16 +# u8x8_font_pxplustandynewtv_f, // 17 +# +# for ILI9225, these fonts are available: +# Terminal6x8 // 0 +# Terminal11x16 // 1 +# Terminal12x16 // 2 +# FreeMono9pt7b, // 3 +# FreeMono12pt7b, // 4 +# FreeSans9pt7b, // 5 +# FreeSans12pt7b, // 6 +# Picopixel, // 7 +# +# color=rrggbb,rrggbb can be used to select color (foreground, background) +# see https://github.com/Nkawu/TFT_22_ILI9225/wiki#color-reference for example (use without "#"-sign) +# +# for TFT display, coordinates are multiplied by xscale,yscale and later used in pixels +# with scale=1,1 you can directly use pixel coordinates. ########### # # Default configuration for "Scanner" display: diff --git a/RX_FSK/version.h b/RX_FSK/version.h index efd7aca..a67c10e 100644 --- a/RX_FSK/version.h +++ b/RX_FSK/version.h @@ -1,2 +1,2 @@ const char *version_name = "rdzTTGOsonde"; -const char *version_id = "devel20191008"; +const char *version_id = "devel20191013"; diff --git a/libraries/SondeLib/Display.cpp b/libraries/SondeLib/Display.cpp index 84215c0..10393f9 100644 --- a/libraries/SondeLib/Display.cpp +++ b/libraries/SondeLib/Display.cpp @@ -9,8 +9,11 @@ extern const char *version_name; extern const char *version_id; +#include <../fonts/FreeMono9pt7b.h> +#include <../fonts/FreeMono12pt7b.h> #include <../fonts/FreeSans9pt7b.h> #include <../fonts/FreeSans12pt7b.h> +#include <../fonts/Picopixel.h> extern Sonde sonde; @@ -74,12 +77,12 @@ static uint8_t deg_tile[8]={0x00, 0x06,0x09, 0x09, 0x06, 0x00, 0x00, 0x00}; * based on key presses or on expired timeouts */ DispEntry searchLayout[] = { - {0, 0, FONT_LARGE, disp.drawText, "Scan:"}, - {0, 8, FONT_LARGE, disp.drawType, NULL}, - {3, 0, FONT_LARGE, disp.drawFreq, " MHz"}, - {5, 0, FONT_LARGE, disp.drawSite, NULL}, - {7, 5, 0, disp.drawIP, NULL}, - {-1, -1, -1, NULL, NULL}, + {0, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawText, "Scan:"}, + {0, 8, FONT_LARGE, -1, 0xFFFF, 0, disp.drawType, NULL}, + {3, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawFreq, " MHz"}, + {5, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawSite, NULL}, + {7, 5, 0, -1, 0xFFFF, 0, disp.drawIP, NULL}, + {-1, -1, -1, 0, 0, 0, NULL, NULL}, }; int16_t searchTimeouts[] = { -1, 0, 0 }; uint8_t searchActions[] = { @@ -88,19 +91,19 @@ uint8_t searchActions[] = { ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_DISPLAY_DEFAULT, ACT_NEXTSONDE}; DispEntry legacyLayout[] = { - {0, 5, FONT_SMALL, disp.drawFreq, " MHz"}, - {1, 8, FONT_SMALL, disp.drawAFC, NULL}, - {0, 0, FONT_SMALL, disp.drawType, NULL}, - {1, 0, FONT_SMALL, disp.drawID, NULL}, - {2, 0, FONT_LARGE, disp.drawLat, NULL}, - {4, 0, FONT_LARGE, disp.drawLon, NULL}, - {2, 10, FONT_SMALL, disp.drawAlt, NULL}, - {3, 10, FONT_SMALL, disp.drawHS, NULL}, - {4, 9, FONT_SMALL, disp.drawVS, NULL}, - {6, 0, FONT_LARGE, disp.drawRSSI, NULL}, - {6, 7, 0, disp.drawQS, NULL}, - {7, 5, 0, disp.drawIP, NULL}, - {-1, -1, -1, NULL, NULL}, + {0, 5, FONT_SMALL, -1, 0xFFFF, 0, disp.drawFreq, " MHz"}, + {1, 8, FONT_SMALL, -1, 0xFFFF, 0, disp.drawAFC, NULL}, + {0, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawType, NULL}, + {1, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawID, NULL}, + {2, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawLat, NULL}, + {4, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawLon, NULL}, + {2, 10, FONT_SMALL, -1, 0xFFFF, 0, disp.drawAlt, NULL}, + {3, 10, FONT_SMALL, -1, 0xFFFF, 0, disp.drawHS, NULL}, + {4, 9, FONT_SMALL, -1, 0xFFFF, 0, disp.drawVS, NULL}, + {6, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawRSSI, NULL}, + {6, 7, 0, -1, 0xFFFF, 0, disp.drawQS, NULL}, + {7, 5, 0, -1, 0xFFFF, 0, disp.drawIP, NULL}, + {-1, -1, -1, 0, 0, 0, NULL, NULL}, }; int16_t legacyTimeouts[] = { -1, -1, 20000 }; uint8_t legacyActions[] = { @@ -109,14 +112,14 @@ uint8_t legacyActions[] = { ACT_DISPLAY(2), ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_DISPLAY(0)}; DispEntry fieldLayout[] = { - {2, 0, FONT_LARGE, disp.drawLat, NULL}, - {4, 0, FONT_LARGE, disp.drawLon, NULL}, - {3, 10, FONT_SMALL, disp.drawHS, NULL}, - {4, 9, FONT_SMALL, disp.drawVS, NULL}, - {0, 0, FONT_LARGE, disp.drawID, NULL}, - {6, 0, FONT_LARGE, disp.drawAlt, NULL}, - {6, 7, 0, disp.drawQS, NULL}, - {-1, -1, -1, NULL, NULL}, + {2, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawLat, NULL}, + {4, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawLon, NULL}, + {3, 10, FONT_SMALL, -1, 0xFFFF, 0, disp.drawHS, NULL}, + {4, 9, FONT_SMALL, -1, 0xFFFF, 0, disp.drawVS, NULL}, + {0, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawID, NULL}, + {6, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawAlt, NULL}, + {6, 7, 0, -1, 0xFFFF, 0, disp.drawQS, NULL}, + {-1, -1, -1, 0, 0, 0, NULL, NULL}, }; int16_t fieldTimeouts[] = { -1, -1, -1 }; uint8_t fieldActions[] = { @@ -125,16 +128,16 @@ uint8_t fieldActions[] = { ACT_DISPLAY(4), ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE}; DispEntry field2Layout[] = { - {2, 0, FONT_LARGE, disp.drawLat, NULL}, - {4, 0, FONT_LARGE, disp.drawLon, NULL}, - {1, 12, FONT_SMALL, disp.drawType, NULL}, - {0, 9, FONT_SMALL, disp.drawFreq, ""}, - {3, 10, FONT_SMALL, disp.drawHS, NULL}, - {4, 9, FONT_SMALL, disp.drawVS, NULL}, - {0, 0, FONT_LARGE, disp.drawID, NULL}, - {6, 0, FONT_LARGE, disp.drawAlt, NULL}, - {6, 7, 0, disp.drawQS, NULL}, - {-1, -1, -1, NULL, NULL}, + {2, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawLat, NULL}, + {4, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawLon, NULL}, + {1, 12, FONT_SMALL, -1, 0xFFFF, 0, disp.drawType, NULL}, + {0, 9, FONT_SMALL, -1, 0xFFFF, 0, disp.drawFreq, ""}, + {3, 10, FONT_SMALL, -1, 0xFFFF, 0, disp.drawHS, NULL}, + {4, 9, FONT_SMALL, -1, 0xFFFF, 0, disp.drawVS, NULL}, + {0, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawID, NULL}, + {6, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawAlt, NULL}, + {6, 7, 0, -1, 0xFFFF, 0, disp.drawQS, NULL}, + {-1, -1, -1, 0, 0, 0, NULL, NULL}, }; uint8_t field2Actions[] = { ACT_NONE, @@ -142,16 +145,16 @@ uint8_t field2Actions[] = { ACT_DISPLAY(1), ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE, ACT_NONE}; DispEntry gpsLayout[] = { - {0, 0, FONT_LARGE, disp.drawID, NULL}, - {2, 0, FONT_SMALL, disp.drawLat, NULL}, - {3, 0, FONT_SMALL, disp.drawLon, NULL}, - {4, 0, FONT_SMALL, disp.drawAlt, NULL}, - {6, 0, FONT_SMALL, disp.drawGPS, "V"}, + {0, 0, FONT_LARGE, -1, 0xFFFF, 0, disp.drawID, NULL}, + {2, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawLat, NULL}, + {3, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawLon, NULL}, + {4, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawAlt, NULL}, + {6, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawGPS, "V"}, //{6, 1, FONT_SMALL, disp.drawGPS, "A"}, //{6, 8, FONT_SMALL, disp.drawGPS, "O"}, - {7, 0, FONT_SMALL, disp.drawGPS, "D"}, - {7, 8, FONT_SMALL, disp.drawGPS, "I"}, - {-1, -1, -1, NULL, NULL}, + {7, 0, FONT_SMALL, -1, 0xFFFF, 0, disp.drawGPS, "D"}, + {7, 8, FONT_SMALL, -1, 0xFFFF, 0, disp.drawGPS, "I"}, + {-1, -1, -1, 0, 0, 0, NULL, NULL}, }; uint8_t gpsActions[] = { ACT_NONE, @@ -170,6 +173,32 @@ DispInfo *layouts = staticLayouts; /////////////// Wrapper code for various display +// ALLFONTS requires 30k extra flash memory... for now there is still enough space :) +#define ALLFONTS 1 +static const uint8_t *fl[] = { + u8x8_font_chroma48medium8_r, // 0 ** default small + u8x8_font_7x14_1x2_f, // 1 ** default large +#ifdef ALLFONTS + u8x8_font_amstrad_cpc_extended_f, // 2 + u8x8_font_5x7_f, // 3 + u8x8_font_5x8_f, // 4 + u8x8_font_8x13_1x2_f, // 5 + u8x8_font_8x13B_1x2_f, // 6 + u8x8_font_7x14B_1x2_f, // 7 + u8x8_font_artossans8_r, // 8 + u8x8_font_artosserif8_r, // 9 + u8x8_font_torussansbold8_r, // 10 + u8x8_font_victoriabold8_r, // 11 + u8x8_font_victoriamedium8_r, // 12 + u8x8_font_pressstart2p_f, // 13 + u8x8_font_pcsenior_f, // 14 + u8x8_font_pxplusibmcgathin_f, // 15 + u8x8_font_pxplusibmcga_f, // 16 + u8x8_font_pxplustandynewtv_f, // 17 +#endif +}; + + void U8x8Display::begin() { Serial.printf("Init SSD1306 display %d %d\n", sonde.config.oled_scl, sonde.config.oled_sda); //u8x8 = new U8X8_SSD1306_128X64_NONAME_SW_I2C(/* clock=*/ sonde.config.oled_scl, /* data=*/ sonde.config.oled_sda, /* reset=*/ sonde.config.oled_rst); // Unbuffered, basic graphics, software I2C @@ -180,18 +209,23 @@ void U8x8Display::begin() { } u8x8->begin(); + fontlist = fl; + nfonts = sizeof(fl)/sizeof(uint8_t *); + Serial.printf("Size of font list is %d\n", nfonts); } void U8x8Display::clear() { u8x8->clear(); } + // For u8x8 oled display: 0=small font, 1=large font 7x14 -void U8x8Display::setFont(int large) { - u8x8->setFont((large)?u8x8_font_7x14_1x2_r:u8x8_font_chroma48medium8_r); +void U8x8Display::setFont(uint8_t fontindex) { + if(fontindex>=nfonts) fontindex=0; // prevent overflow + u8x8->setFont( fontlist[fontindex] ); } -void U8x8Display::drawString(uint8_t x, uint8_t y, const char *s) { +void U8x8Display::drawString(uint8_t x, uint8_t y, const char *s, int16_t width, uint16_t fg, uint16_t bg) { u8x8->drawString(x, y, s); } @@ -208,7 +242,57 @@ void U8x8Display::welcome() { drawString(0, 6, "by Hansi, DL9RDZ"); } +static String previp; +void U8x8Display::drawIP(uint8_t x, uint8_t y, int16_t width, uint16_t fg, uint16_t bg) { + if(!previp.equals(sonde.ipaddr)) { + // ip address has changed + // create tiles + memset(myIP_tiles, 0, 11*8); + int len = sonde.ipaddr.length(); + const char *ip = sonde.ipaddr.c_str(); + int pix = (len-3)*6+6; + int tp = 80-pix+8; + if(sonde.isAP) memcpy(myIP_tiles+(tp<16?0:8), ap_tile, 8); + for(int i=0; idrawTile(x, y, 11, myIP_tiles); +} + +const GFXfont *gfl[] = { + &FreeMono9pt7b, // 3 + &FreeMono12pt7b, // 4 + &FreeSans9pt7b, // 5 + &FreeSans12pt7b, // 6 + &Picopixel, // 7 +}; +struct gfxoffset_t { + uint8_t yofs, yclear; +}; +// obtained as max offset from font (last column) and maximum height (3rd column) in glyphs +// first value: offset: max offset from font glyphs (last column * (-1)) (check /, \, `, $)` +// yclear:max height: max of (height in 3rd column) + (yofs + 6th column) (check j) +const struct gfxoffset_t gfxoffsets[]={ + { 11, 15 }, // 13+11-9 "j" + { 15, 20 }, // 19+15-14 + { 13, 18 }, // 17+13-12 "j" + { 17, 23 }, // 23+17-17 + { 4, 6}, // 6+4-4 +}; +static int ngfx = sizeof(gfl)/sizeof(GFXfont *); + + #define TFT_LED 0 // 0 if wired to +5V directly #define TFT_BRIGHTNESS 100 // Initial brightness of TFT backlight (optional) @@ -224,31 +308,33 @@ void ILI9225Display::clear() { } // for now, 0=small=FreeSans9pt7b, 1=large=FreeSans18pt7b -void ILI9225Display::setFont(int large) { - tft->setGFXFont(large ? &FreeSans12pt7b : &FreeSans9pt7b); - //tft->setFont(large?Terminal12x16: Terminal6x8); - fsize = large; - yofs = 0; +void ILI9225Display::setFont(uint8_t fontindex) { + findex = fontindex; + switch(fontindex) { + case 0: tft->setFont(Terminal6x8); break; + case 1: tft->setFont(Terminal11x16); break; + case 2: tft->setFont(Terminal12x16); break; + default: tft->setGFXFont(gfl[fontindex-3]); + } } -/* Notes on Fonts: - * FreeSans9pt: höhe: baseline -13..+5; breite: max 18, i.d.r. <=15 -*/ -// normal size: avg. 14x22 // large wvg. 17x29 -#define XSKIP 14 -#define YSKIP 22 -void ILI9225Display::drawString(uint8_t x, uint8_t y, const char *s) { +void ILI9225Display::drawString(uint8_t x, uint8_t y, const char *s, int16_t width, uint16_t fg, uint16_t bg) { int16_t w,h; -#if 1 - tft->getGFXTextExtent(s, x*XSKIP, y*YSKIP, &w, &h); - int len = strlen(s); - if(fsize) { - tft->fillRectangle(x*XSKIP, y*YSKIP+3, x*XSKIP + len*17, y*YSKIP +29, COLOR_BLACK); - } else { - tft->fillRectangle(x*XSKIP, y*YSKIP+3, x*XSKIP + len*14, y*YSKIP +22, COLOR_BLACK); + if(findex<3) { // standard font + //////////////tft->drawText(x...); + Serial.printf("Simple Text %s at %d,%d\n", s, x, y); + tft->drawText(x, y, s, fg); + return; } - tft->drawGFXText(x*XSKIP, (1+y)*YSKIP, s, COLOR_WHITE); -#endif + // GFX font + if(width==-1) { + tft->getGFXTextExtent(s, x, y + gfxoffsets[findex-3].yofs, &w, &h); + width = w; + } + if(findex-3>=ngfx) findex=3; + tft->fillRectangle(x, y, x + width, y + gfxoffsets[findex-3].yclear, bg); + Serial.printf("GFX Text %s at %d,%d+%d in color %x, width=%d\n", s, x, y, gfxoffsets[findex-3].yofs, fg, width); + tft->drawGFXText(x, y + gfxoffsets[findex-3].yofs, s, fg); } void ILI9225Display::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) { @@ -271,21 +357,29 @@ void ILI9225Display::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_p void ILI9225Display::welcome() { tft->clear(); - setFont(FONT_LARGE); - drawString(0, 0, version_name); - setFont(FONT_SMALL); - drawString(0, 1, "RS41,RS92,DFM6/9"); - drawString(0, 3, version_id); - drawString(0, 5, "by Hansi, DL9RDZ"); + setFont(6); + drawString(0, 0*22, version_name, -1, 0xff77); + setFont(5); + drawString(0, 1*22, "RS41,RS92,DFM6/9"); + drawString(0, 3*22, version_id); + drawString(0, 5*22, "by Hansi, DL9RDZ"); } + +void ILI9225Display::drawIP(uint8_t x, uint8_t y, int16_t width, uint16_t fg, uint16_t bg) { + setFont(0); + char buf[20]; + snprintf(buf, 20, "%c %s", sonde.isAP?'A':' ', sonde.ipaddr.c_str()); + drawString(x, y, buf); +} + #include #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) void MY_ILI9225::drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) { int i,j; startWrite(); - for(int i=0; i='A'&&type<='Z') { type += 32; // lc - de->fmt = FONT_LARGE; + de->fmt = fontlar; } else { - de->fmt = FONT_SMALL; + de->fmt = fontsma; } + de->fg = colfg; + de->bg = colbg; switch(type) { case 'l': de->func = disp.drawLat; break; @@ -478,6 +574,9 @@ void Display::initFromFile() { } memset(layouts, 0, MAXSCREENS * sizeof(DispInfo)); + // default color + colfg = 0xffff; // white; only used for ILI9225 + colbg = 0; // black; only used for ILI9225 int idx = -1; int what = -1; int entrysize; @@ -536,13 +635,28 @@ void Display::initFromFile() { layouts[idx].actions[9] = ACTION(c1); layouts[idx].actions[10] = ACTION(c2); layouts[idx].actions[11] = ACTION(c3); + } else if(strncmp(s, "fonts=",6)==0) { // change font + sscanf(s+6, "%d,%d", &fontsma, &fontlar); + } else if(strncmp(s, "scale=",6)==0) { // change line->pixel scaling for ILI9225 display + sscanf(s+6, "%d,%d", &yscale, &xscale); + } else if(strncmp(s, "color=",6)==0) { // + int res; + uint32_t fg,bg; + res=sscanf(s+6, "%" SCNx32 ",%" SCNx32, &fg, &bg); + colfg = (fg>>19) << 11 | ((fg>>10)&0x3F) << 5 | ((fg>>3)&0x1F); + if(res==2) { + colbg = (bg>>19) << 11 | ((bg>>10)&0x3F) << 5 | ((bg>>3)&0x1F); + } } else if(strchr(s, '=')) { // one line with some data... int x,y; char text[30]; sscanf(s, "%d,%d=%30[^\r\n]", &y, &x, text); + if(sonde.config.disptype==1) { x*=xscale; y*=yscale; } layouts[idx].de[what].x = x; layouts[idx].de[what].y = y; parseDispElement(text, layouts[idx].de+what); + Serial.printf("entry at %d,%d font %d, color=%x,%x\n", x, y, layouts[idx].de[what].fmt, + layouts[idx].de[what].fg, layouts[idx].de[what].bg); what++; layouts[idx].de[what].func = NULL; } else { @@ -554,92 +668,102 @@ void Display::initFromFile() { break; } } + setLayout(0); } void Display::setLayout(int layoutIdx) { layout = &layouts[layoutIdx]; } +void Display::drawString(DispEntry *de, const char *str) { + rdis->drawString(de->x, de->y, str, -1 /*de->width*/, de->fg, de->bg); +} + void Display::drawLat(DispEntry *de) { rdis->setFont(de->fmt); if(!sonde.si()->validPos) { - rdis->drawString(de->x,de->y," "); + drawString(de," "); return; } snprintf(buf, 16, "%2.5f", sonde.si()->lat); - rdis->drawString(de->x,de->y,buf); + drawString(de,buf); } void Display::drawLon(DispEntry *de) { rdis->setFont(de->fmt); if(!sonde.si()->validPos) { - rdis->drawString(de->x,de->y," "); + drawString(de," "); return; } snprintf(buf, 16, "%2.5f", sonde.si()->lon); - rdis->drawString(de->x,de->y,buf); + drawString(de,buf); } void Display::drawAlt(DispEntry *de) { rdis->setFont(de->fmt); if(!sonde.si()->validPos) { - rdis->drawString(de->x,de->y," "); + drawString(de," "); return; } snprintf(buf, 16, sonde.si()->alt>=1000?" %5.0fm":" %3.1fm", sonde.si()->alt); - rdis->drawString(de->x,de->y,buf+strlen(buf)-6); + drawString(de,buf+strlen(buf)-6); } void Display::drawHS(DispEntry *de) { rdis->setFont(de->fmt); if(!sonde.si()->validPos) { - rdis->drawString(de->x,de->y," "); + drawString(de," "); return; } snprintf(buf, 16, sonde.si()->hs>99?" %3.0f":" %2.1f", sonde.si()->hs); - rdis->drawString(de->x,de->y,buf+strlen(buf)-4); + drawString(de,buf+strlen(buf)-4); rdis->drawTile(de->x+4,de->y,2,kmh_tiles); } void Display::drawVS(DispEntry *de) { rdis->setFont(de->fmt); if(!sonde.si()->validPos) { - rdis->drawString(de->x,de->y," "); + drawString(de," "); return; } snprintf(buf, 16, " %+2.1f", sonde.si()->vs); - rdis->drawString(de->x, de->y, buf+strlen(buf)-5); + drawString(de, buf+strlen(buf)-5); rdis->drawTile(de->x+5,de->y,2,ms_tiles); } void Display::drawID(DispEntry *de) { rdis->setFont(de->fmt); if(!sonde.si()->validID) { - rdis->drawString(de->x, de->y, "nnnnnnnn "); + drawString(de, "nnnnnnnn "); return; } // TODO: handle DFM6 IDs if(!de->extra || de->extra[0]=='s') { // real serial number, as printed on sonde - rdis->drawString(de->x, de->y, sonde.si()->id); + drawString(de, sonde.si()->id); } else if (de->extra[0]=='a') { // autorx sonde number ("DF9" and last 6 digits of real serial number strcpy(buf, sonde.si()->id); memcpy(buf, "DF9", 3); - rdis->drawString(de->x, de->y, buf); + drawString(de, buf); } else { // dxlAPRS sonde number (DF6 (why??) and 5 last digits of serial number as hex number uint32_t id = atoi(sonde.si()->id); id = id&0xfffff; snprintf(buf, 16, "DF6%05X", id); - rdis->drawString(de->x, de->y, buf); + drawString(de, buf); } } void Display::drawRSSI(DispEntry *de) { rdis->setFont(de->fmt); - snprintf(buf, 16, "-%d ", sonde.si()->rssi/2); - int len=strlen(buf)-3; - Serial.printf("drawRSSI: %d %d %d (%d)[%d]\n", de->y, de->x, sonde.si()->rssi/2, sonde.currentSonde, len); - buf[5]=0; - rdis->drawString(de->x,de->y,buf); - rdis->drawTile(de->x+len, de->y, 1, (sonde.si()->rssi&1)?halfdb_tile1:empty_tile1); - rdis->drawTile(de->x+len, de->y+1, 1, (sonde.si()->rssi&1)?halfdb_tile2:empty_tile2); + if(sonde.config.disptype!=1) { + snprintf(buf, 16, "-%d ", sonde.si()->rssi/2); + int len=strlen(buf)-3; + Serial.printf("drawRSSI: %d %d %d (%d)[%d]\n", de->y, de->x, sonde.si()->rssi/2, sonde.currentSonde, len); + buf[5]=0; + drawString(de,buf); + rdis->drawTile(de->x+len, de->y, 1, (sonde.si()->rssi&1)?halfdb_tile1:empty_tile1); + rdis->drawTile(de->x+len, de->y+1, 1, (sonde.si()->rssi&1)?halfdb_tile2:empty_tile2); + } else { // special for 2" display + snprintf(buf, 16, "-%d.%c ", sonde.si()->rssi/2, (sonde.si()->rssi&1)?'5':'0'); + drawString(de,buf); + } } void Display::drawQS(DispEntry *de) { uint8_t *stat = sonde.si()->rxStat; @@ -652,27 +776,26 @@ void Display::drawQS(DispEntry *de) { } void Display::drawType(DispEntry *de) { rdis->setFont(de->fmt); - rdis->drawString(de->x, de->y, sondeTypeStr[sonde.si()->type]); + drawString(de, sondeTypeStr[sonde.si()->type]); } void Display::drawFreq(DispEntry *de) { rdis->setFont(de->fmt); snprintf(buf, 16, "%3.3f%s", sonde.si()->freq, de->extra?de->extra:""); - rdis->drawString(de->x, de->y, buf); + drawString(de, buf); } void Display::drawAFC(DispEntry *de) { if(!sonde.config.showafc) return; rdis->setFont(de->fmt); if(sonde.si()->afc==0) { strcpy(buf, " "); } else { snprintf(buf, 15, " %+3.2fk", sonde.si()->afc*0.001); } - rdis->drawString(de->x, de->y, buf+strlen(buf)-8); + drawString(de, buf+strlen(buf)-8); } void Display::drawIP(DispEntry *de) { - rdis->drawTile(de->x, de->y, 11, myIP_tiles); - + rdis->drawIP(de->x, de->y, -1 /*de->width*/, de->fg, de->bg); } void Display::drawSite(DispEntry *de) { rdis->setFont(de->fmt); - rdis->drawString(de->x, de->y, sonde.si()->launchsite); + drawString(de, sonde.si()->launchsite); } void Display::drawTelemetry(DispEntry *de) { } @@ -700,7 +823,7 @@ void Display::drawGPS(DispEntry *de) { float lon = nmea.getLongitude()*0.000001; Serial.print("lon: "); Serial.println(lon); snprintf(buf, 16, "%2.5f", lon); - rdis->drawString(de->x,de->y,buf); + drawString(de,buf); } break; case 'A': @@ -709,7 +832,7 @@ void Display::drawGPS(DispEntry *de) { float lat = nmea.getLatitude()*0.000001; Serial.print("lat: "); Serial.println(lat); snprintf(buf, 16, "%2.5f", lat); - rdis->drawString(de->x,de->y,buf); + drawString(de,buf); } break; case 'H': @@ -718,7 +841,7 @@ void Display::drawGPS(DispEntry *de) { long alt = -1; nmea.getAltitude(alt); snprintf(buf, 16, "%5fm", alt*0.00001); - rdis->drawString(de->x,de->y,buf); + drawString(de,buf); } break; case 'D': @@ -748,13 +871,13 @@ void Display::drawGPS(DispEntry *de) { buf[6]=0; } } - rdis->drawString(de->x, de->y, buf); + drawString(de, buf); } break; case 'I': // dIrection if( (!nmea.isValid()) || ((sonde.si()->validPos&0x03)!=0x03 ) ) { - rdis->drawString(de->x, de->y, "---"); + drawString(de, "---"); break; } { @@ -769,7 +892,7 @@ void Display::drawGPS(DispEntry *de) { Serial.printf("direction is %.2f\n", dir); snprintf(buf, 16, "%3d", (int)dir); buf[3]=0; - rdis->drawString(de->x, de->y, buf); + drawString(de, buf); if(de->extra[1]==(char)176) rdis->drawTile(de->x+3, de->y, 1, deg_tile); } @@ -779,35 +902,12 @@ void Display::drawGPS(DispEntry *de) { break; } } + void Display::drawText(DispEntry *de) { rdis->setFont(de->fmt); - rdis->drawString(de->x, de->y, de->extra); + drawString(de, de->extra); } - -void Display::clearIP() { - memset(myIP_tiles, 0, 11*8); -} - -void Display::setIP(const char *ip, bool AP) { - memset(myIP_tiles, 0, 11*8); - int len = strlen(ip); - int pix = (len-3)*6+6; - int tp = 80-pix+8; - if(AP) memcpy(myIP_tiles+(tp<16?0:8), ap_tile, 8); - for(int i=0; ide; di->func != NULL; di++) { if(di->func != disp.drawLat && di->func != disp.drawLon) continue; @@ -845,6 +945,7 @@ void Display::updateDisplayRXConfig() { di->func(di); } } + void Display::updateDisplayIP() { for(DispEntry *di=layout->de; di->func != NULL; di++) { if(di->func != disp.drawIP) continue; diff --git a/libraries/SondeLib/Display.h b/libraries/SondeLib/Display.h index d5dbc13..2dc9093 100644 --- a/libraries/SondeLib/Display.h +++ b/libraries/SondeLib/Display.h @@ -13,7 +13,8 @@ struct DispEntry { int8_t y; int8_t x; - int16_t fmt; + int16_t fmt, width; + uint16_t fg,bg; void (*func)(DispEntry *de); const char *extra; }; @@ -29,25 +30,29 @@ class RawDisplay { public: virtual void begin() = 0; virtual void clear() = 0; - virtual void setFont(int nr) = 0; - virtual void drawString(uint8_t x, uint8_t y, const char *s) = 0; + virtual void setFont(uint8_t fontindex) = 0; + virtual void drawString(uint8_t x, uint8_t y, const char *s, int16_t width=-1, uint16_t fg=0xffff, uint16_t bg=0 ) = 0; virtual void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr) = 0; virtual void welcome() = 0; + virtual void drawIP(uint8_t x, uint8_t y, int16_t width=-1, uint16_t fg=0xffff, uint16_t bg=0 ) = 0; }; class U8x8Display : public RawDisplay { private: U8X8 *u8x8 = NULL; // initialize later after reading config file int _type; + const uint8_t **fontlist; + int nfonts; public: U8x8Display(int type = 0) { _type = type; } void begin(); void clear(); - void setFont(int nr); - void drawString(uint8_t x, uint8_t y, const char *s); + void setFont(uint8_t fontindex); + void drawString(uint8_t x, uint8_t y, const char *s, int16_t width=-1, uint16_t fg=0xffff, uint16_t bg=0); void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr); void welcome(); + void drawIP(uint8_t x, uint8_t y, int16_t width=-1, uint16_t fg=0xffff, uint16_t bg=0); }; class MY_ILI9225 : public TFT22_ILI9225 { @@ -61,16 +66,17 @@ class ILI9225Display : public RawDisplay { private: MY_ILI9225 *tft = NULL; // initialize later after reading config file uint8_t yofs=0; - uint8_t fsize=0; + uint8_t findex=0; public: void begin(); void clear(); - void setFont(int nr); - void drawString(uint8_t x, uint8_t y, const char *s); + void setFont(uint8_t fontindex); + void drawString(uint8_t x, uint8_t y, const char *s, int16_t width=-1, uint16_t fg=0xffff, uint16_t bg=0); void drawTile(uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr); void welcome(); + void drawIP(uint8_t x, uint8_t y, int16_t width=-1, uint16_t fg=0xffff, uint16_t bg=0); }; class Display { @@ -78,7 +84,9 @@ private: void freeLayouts(); int allocDispInfo(int entries, DispInfo *d); void parseDispElement(char *text, DispEntry *de); - + int xscale=13, yscale=22; + int fontsma=0, fontlar=1; + uint16_t colfg, colbg; public: void initFromFile(); @@ -105,6 +113,7 @@ public: static void drawTelemetry(DispEntry *de); static void drawGPS(DispEntry *de); static void drawText(DispEntry *de); + static void drawString(DispEntry *de, const char *str); void clearIP(); void setIP(const char *ip, bool AP); void updateDisplayPos(); diff --git a/libraries/SondeLib/Sonde.cpp b/libraries/SondeLib/Sonde.cpp index 4265136..e3eaf87 100644 --- a/libraries/SondeLib/Sonde.cpp +++ b/libraries/SondeLib/Sonde.cpp @@ -17,6 +17,16 @@ const char *evstring[]={"NONE", "KEY1S", "KEY1D", "KEY1M", "KEY1L", "KEY2S", "KE const char *RXstr[]={"RX_OK", "RX_TIMEOUT", "RX_ERROR", "RX_UNKNOWN"}; +int fingerprintValue[]={ 31, 64, 55, 51, 23, 48, -1 }; +const char *fingerprintText[]={ + "TTGO LORA32 v2.1_1.6 (0.9\" OLED@21,22)", + "TTGO LORA v1.0 or Heltecc (0.9\" OLED@4,15)", + "TTGO T-Beam (old version), 0.9\" OLED@21,22", + "TTGO T-Beam (old version), SPI TFT@4,21,22", + "TTGO T-Beam (new version 1.0), 0.9\" OLED@21,22", + "TTGO T-Beam (new version 1.0), SPI TFT@4,13,14", +}; + int getKeyPressEvent(); /* in RX_FSK.ino */ /* Task model: @@ -39,9 +49,14 @@ Sonde::Sonde() { for (int i = 0; i < 39; i++) { initlevels[i] = gpio_get_level((gpio_num_t)i); } - for (int i = 0; i < 39*3; i++) { - initlevels[i%39] += gpio_get_level((gpio_num_t)(i%39)); - } + fingerprint = initlevels[4]; + fingerprint = (fingerprint<<1) | initlevels[12]; + fingerprint = (fingerprint<<1) | initlevels[16]; + fingerprint = (fingerprint<<1) | initlevels[17]; + fingerprint = (fingerprint<<1) | initlevels[21]; + fingerprint = (fingerprint<<1) | initlevels[22]; + fingerprint = (fingerprint<<1) | initlevels[23]; + sondeList = (SondeInfo *)malloc((MAXSONDE+1)*sizeof(SondeInfo)); memset(sondeList, 0, (MAXSONDE+1)*sizeof(SondeInfo)); config.touch_thresh = 70; @@ -57,28 +72,39 @@ Sonde::Sonde() { config.oled_scl = 15; config.button_pin = 0; config.button2_pin = T4 + 128; // T4 == GPIO13 + Serial.println("Autoconfig: looks like v1 board"); } else { config.oled_sda = 21; config.oled_scl = 22; if(initlevels[17]==0) { // T-Beam if(initlevels[12]==0) { // T-Beam v1.0 + Serial.println("Autoconfig: looks like T-Beam 1.0 board"); config.button_pin = 38; config.button2_pin = -1; //T4 + 128; // T4 = GPIO13 config.gps_rxd = 34; // for now, lets assume TFT display / SPI // CS=0, RST=14, RS=2, SDA=4, CLK=13 - config.disptype = 1; - config.oled_sda = 4; - config.oled_scl = 13; - config.oled_rst = 14; - config.tft_rs = 2; - config.tft_cs = 0; + if(initlevels[21]==0) { + Serial.println("... with large TFT display\n"); + config.disptype = 1; + config.oled_sda = 4; + config.oled_scl = 13; + config.oled_rst = 14; + config.tft_rs = 2; + config.tft_cs = 0; + } else { + // OLED display, pins 21,22 ok... + config.disptype = 0; + Serial.println("... with small OLED display\n"); + } } else { + Serial.println("Autoconfig: looks like T-Beam v0.7 board"); config.button_pin = 39; config.button2_pin = T4 + 128; // T4 == GPIO13 config.gps_rxd = 12; // Check if we possibly have a large display if(initlevels[21]==0) { + Serial.println("Autoconfig: looks like T-Beam v0.7 board with large TFT display"); config.disptype = 1; config.oled_sda = 4; config.oled_scl = 21; @@ -237,12 +263,9 @@ void Sonde::setConfig(const char *cfg) { } } -void Sonde::clearIP() { - disp.clearIP(); -} - -void Sonde::setIP(const char *ip, bool AP) { - disp.setIP(ip, AP); +void Sonde::setIP(String ip, bool AP) { + ipaddr = ip; + isAP = AP; } void Sonde::clearSonde() { diff --git a/libraries/SondeLib/Sonde.h b/libraries/SondeLib/Sonde.h index a0ad31a..ecc98c2 100644 --- a/libraries/SondeLib/Sonde.h +++ b/libraries/SondeLib/Sonde.h @@ -150,13 +150,19 @@ typedef struct st_sondeinfo { #define MAXSONDE 99 +extern int fingerprintValue[]; +extern const char *fingerprintText[]; + class Sonde { private: public: RDZConfig config; + int fingerprint = 0; int currentSonde = 0; int nSonde; + String ipaddr; + bool isAP; // moved to heap, saving space in .bss //SondeInfo sondeList[MAXSONDE+1]; SondeInfo *sondeList; @@ -194,8 +200,8 @@ public: void updateDisplay(); void updateDisplayScanner(); void clearDisplay(); - void setIP(const char *ip, bool isAP); - void clearIP(); + + void setIP(String ip, bool isAP); }; extern Sonde sonde; diff --git a/libraries/SondeLib/TFT22_ILI9225.cpp b/libraries/SondeLib/TFT22_ILI9225.cpp index 0fb7105..443a1ca 100644 --- a/libraries/SondeLib/TFT22_ILI9225.cpp +++ b/libraries/SondeLib/TFT22_ILI9225.cpp @@ -1373,7 +1373,8 @@ void TFT22_ILI9225::getGFXTextExtent(STRING str, int16_t x, int16_t y, int16_t * if(gh > *h) { *h = gh; } - *w += xa; + *w += xa + 1; } + if(*w>0) (*w)--; } diff --git a/libraries/fonts/FreeMono12pt7b.h b/libraries/fonts/FreeMono12pt7b.h new file mode 100644 index 0000000..94ecb88 --- /dev/null +++ b/libraries/fonts/FreeMono12pt7b.h @@ -0,0 +1,227 @@ +const uint8_t FreeMono12pt7bBitmaps[] PROGMEM = { + 0x49, 0x24, 0x92, 0x48, 0x01, 0xF8, 0xE7, 0xE7, 0x67, 0x42, 0x42, 0x42, + 0x42, 0x09, 0x02, 0x41, 0x10, 0x44, 0x11, 0x1F, 0xF1, 0x10, 0x4C, 0x12, + 0x3F, 0xE1, 0x20, 0x48, 0x12, 0x04, 0x81, 0x20, 0x48, 0x04, 0x07, 0xA2, + 0x19, 0x02, 0x40, 0x10, 0x03, 0x00, 0x3C, 0x00, 0x80, 0x10, 0x06, 0x01, + 0xE0, 0xA7, 0xC0, 0x40, 0x10, 0x04, 0x00, 0x3C, 0x19, 0x84, 0x21, 0x08, + 0x66, 0x0F, 0x00, 0x0C, 0x1C, 0x78, 0x01, 0xE0, 0xCC, 0x21, 0x08, 0x43, + 0x30, 0x78, 0x3E, 0x30, 0x10, 0x08, 0x02, 0x03, 0x03, 0x47, 0x14, 0x8A, + 0x43, 0x11, 0x8F, 0x60, 0xFD, 0xA4, 0x90, 0x05, 0x25, 0x24, 0x92, 0x48, + 0x92, 0x24, 0x11, 0x24, 0x89, 0x24, 0x92, 0x92, 0x90, 0x00, 0x04, 0x02, + 0x11, 0x07, 0xF0, 0xC0, 0x50, 0x48, 0x42, 0x00, 0x08, 0x04, 0x02, 0x01, + 0x00, 0x87, 0xFC, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x3B, 0x9C, 0xCE, + 0x62, 0x00, 0xFF, 0xE0, 0xFF, 0x80, 0x00, 0x80, 0xC0, 0x40, 0x20, 0x20, + 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x00, 0x80, + 0x80, 0x40, 0x00, 0x1C, 0x31, 0x90, 0x58, 0x38, 0x0C, 0x06, 0x03, 0x01, + 0x80, 0xC0, 0x60, 0x30, 0x34, 0x13, 0x18, 0x70, 0x30, 0xE1, 0x44, 0x81, + 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x1F, 0xC0, 0x1E, 0x10, 0x90, + 0x68, 0x10, 0x08, 0x0C, 0x04, 0x04, 0x04, 0x06, 0x06, 0x06, 0x06, 0x0E, + 0x07, 0xFE, 0x3E, 0x10, 0x40, 0x08, 0x02, 0x00, 0x80, 0x40, 0xE0, 0x04, + 0x00, 0x80, 0x10, 0x04, 0x01, 0x00, 0xD8, 0x63, 0xE0, 0x06, 0x0A, 0x0A, + 0x12, 0x22, 0x22, 0x42, 0x42, 0x82, 0x82, 0xFF, 0x02, 0x02, 0x02, 0x0F, + 0x7F, 0x20, 0x10, 0x08, 0x04, 0x02, 0xF1, 0x8C, 0x03, 0x00, 0x80, 0x40, + 0x20, 0x18, 0x16, 0x18, 0xF0, 0x0F, 0x8C, 0x08, 0x08, 0x04, 0x04, 0x02, + 0x79, 0x46, 0xC1, 0xE0, 0x60, 0x28, 0x14, 0x19, 0x08, 0x78, 0xFF, 0x81, + 0x81, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, + 0x08, 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x05, 0x8C, 0x38, 0x63, 0x40, + 0x60, 0x30, 0x18, 0x1B, 0x18, 0xF8, 0x3C, 0x31, 0x30, 0x50, 0x28, 0x0C, + 0x0F, 0x06, 0x85, 0x3C, 0x80, 0x40, 0x40, 0x20, 0x20, 0x63, 0xE0, 0xFF, + 0x80, 0x07, 0xFC, 0x39, 0xCE, 0x00, 0x00, 0x06, 0x33, 0x98, 0xC4, 0x00, + 0x00, 0xC0, 0x60, 0x18, 0x0C, 0x06, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, + 0x00, 0x30, 0x01, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x06, + 0x00, 0x30, 0x01, 0x80, 0x18, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C, 0x02, + 0x00, 0x00, 0x3E, 0x60, 0xA0, 0x20, 0x10, 0x08, 0x08, 0x18, 0x10, 0x08, + 0x00, 0x00, 0x00, 0x01, 0xC0, 0xE0, 0x1C, 0x31, 0x10, 0x50, 0x28, 0x14, + 0x3A, 0x25, 0x22, 0x91, 0x4C, 0xA3, 0xF0, 0x08, 0x02, 0x01, 0x80, 0x7C, + 0x3F, 0x00, 0x0C, 0x00, 0x48, 0x01, 0x20, 0x04, 0x40, 0x21, 0x00, 0x84, + 0x04, 0x08, 0x1F, 0xE0, 0x40, 0x82, 0x01, 0x08, 0x04, 0x20, 0x13, 0xE1, + 0xF0, 0xFF, 0x08, 0x11, 0x01, 0x20, 0x24, 0x04, 0x81, 0x1F, 0xC2, 0x06, + 0x40, 0x68, 0x05, 0x00, 0xA0, 0x14, 0x05, 0xFF, 0x00, 0x1E, 0x48, 0x74, + 0x05, 0x01, 0x80, 0x20, 0x08, 0x02, 0x00, 0x80, 0x20, 0x04, 0x01, 0x01, + 0x30, 0x87, 0xC0, 0xFE, 0x10, 0x44, 0x09, 0x02, 0x40, 0x50, 0x14, 0x05, + 0x01, 0x40, 0x50, 0x14, 0x0D, 0x02, 0x41, 0x3F, 0x80, 0xFF, 0xC8, 0x09, + 0x01, 0x20, 0x04, 0x00, 0x88, 0x1F, 0x02, 0x20, 0x40, 0x08, 0x01, 0x00, + 0xA0, 0x14, 0x03, 0xFF, 0xC0, 0xFF, 0xE8, 0x05, 0x00, 0xA0, 0x04, 0x00, + 0x88, 0x1F, 0x02, 0x20, 0x40, 0x08, 0x01, 0x00, 0x20, 0x04, 0x01, 0xF0, + 0x00, 0x1F, 0x46, 0x19, 0x01, 0x60, 0x28, 0x01, 0x00, 0x20, 0x04, 0x00, + 0x83, 0xF0, 0x0B, 0x01, 0x20, 0x23, 0x0C, 0x3E, 0x00, 0xE1, 0xD0, 0x24, + 0x09, 0x02, 0x40, 0x90, 0x27, 0xF9, 0x02, 0x40, 0x90, 0x24, 0x09, 0x02, + 0x40, 0xB8, 0x70, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x20, + 0x40, 0x81, 0x1F, 0xC0, 0x0F, 0xE0, 0x10, 0x02, 0x00, 0x40, 0x08, 0x01, + 0x00, 0x20, 0x04, 0x80, 0x90, 0x12, 0x02, 0x40, 0xC6, 0x30, 0x7C, 0x00, + 0xF1, 0xE4, 0x0C, 0x41, 0x04, 0x20, 0x44, 0x04, 0x80, 0x5C, 0x06, 0x60, + 0x43, 0x04, 0x10, 0x40, 0x84, 0x08, 0x40, 0xCF, 0x07, 0xF8, 0x04, 0x00, + 0x80, 0x10, 0x02, 0x00, 0x40, 0x08, 0x01, 0x00, 0x20, 0x04, 0x04, 0x80, + 0x90, 0x12, 0x03, 0xFF, 0xC0, 0xE0, 0x3B, 0x01, 0x94, 0x14, 0xA0, 0xA4, + 0x89, 0x24, 0x49, 0x14, 0x48, 0xA2, 0x45, 0x12, 0x10, 0x90, 0x04, 0x80, + 0x24, 0x01, 0x78, 0x3C, 0xE0, 0xF6, 0x02, 0x50, 0x25, 0x02, 0x48, 0x24, + 0xC2, 0x44, 0x24, 0x22, 0x43, 0x24, 0x12, 0x40, 0xA4, 0x0A, 0x40, 0x6F, + 0x06, 0x0F, 0x03, 0x0C, 0x60, 0x64, 0x02, 0x80, 0x18, 0x01, 0x80, 0x18, + 0x01, 0x80, 0x18, 0x01, 0x40, 0x26, 0x06, 0x30, 0xC0, 0xF0, 0xFF, 0x10, + 0x64, 0x05, 0x01, 0x40, 0x50, 0x34, 0x19, 0xFC, 0x40, 0x10, 0x04, 0x01, + 0x00, 0x40, 0x3E, 0x00, 0x0F, 0x03, 0x0C, 0x60, 0x64, 0x02, 0x80, 0x18, + 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x40, 0x26, 0x06, 0x30, 0xC1, + 0xF0, 0x0C, 0x01, 0xF1, 0x30, 0xE0, 0xFF, 0x04, 0x18, 0x40, 0xC4, 0x04, + 0x40, 0x44, 0x0C, 0x41, 0x87, 0xE0, 0x43, 0x04, 0x10, 0x40, 0x84, 0x04, + 0x40, 0x4F, 0x03, 0x1F, 0x48, 0x34, 0x05, 0x01, 0x40, 0x08, 0x01, 0xC0, + 0x0E, 0x00, 0x40, 0x18, 0x06, 0x01, 0xE1, 0xA7, 0xC0, 0xFF, 0xF0, 0x86, + 0x10, 0x82, 0x00, 0x40, 0x08, 0x01, 0x00, 0x20, 0x04, 0x00, 0x80, 0x10, + 0x02, 0x00, 0x40, 0x7F, 0x00, 0xF0, 0xF4, 0x02, 0x40, 0x24, 0x02, 0x40, + 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x24, 0x02, 0x40, 0x22, 0x04, 0x30, + 0xC0, 0xF0, 0xF8, 0x7C, 0x80, 0x22, 0x01, 0x04, 0x04, 0x10, 0x20, 0x40, + 0x80, 0x82, 0x02, 0x10, 0x08, 0x40, 0x11, 0x00, 0x48, 0x01, 0xA0, 0x03, + 0x00, 0x0C, 0x00, 0xF8, 0x7C, 0x80, 0x22, 0x00, 0x88, 0xC2, 0x23, 0x10, + 0x8E, 0x42, 0x29, 0x09, 0x24, 0x24, 0x90, 0x91, 0x41, 0x85, 0x06, 0x14, + 0x18, 0x70, 0x60, 0x80, 0xF0, 0xF2, 0x06, 0x30, 0x41, 0x08, 0x09, 0x80, + 0x50, 0x06, 0x00, 0x60, 0x0D, 0x00, 0x88, 0x10, 0xC2, 0x04, 0x60, 0x2F, + 0x0F, 0xF0, 0xF2, 0x02, 0x10, 0x41, 0x04, 0x08, 0x80, 0x50, 0x05, 0x00, + 0x20, 0x02, 0x00, 0x20, 0x02, 0x00, 0x20, 0x02, 0x01, 0xFC, 0xFF, 0x40, + 0xA0, 0x90, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x10, 0x50, 0x30, 0x18, + 0x0F, 0xFC, 0xF2, 0x49, 0x24, 0x92, 0x49, 0x24, 0x9C, 0x80, 0x60, 0x10, + 0x08, 0x02, 0x01, 0x00, 0x40, 0x20, 0x08, 0x04, 0x01, 0x00, 0x80, 0x20, + 0x10, 0x04, 0x02, 0x00, 0x80, 0x40, 0xE4, 0x92, 0x49, 0x24, 0x92, 0x49, + 0x3C, 0x08, 0x0C, 0x09, 0x0C, 0x4C, 0x14, 0x04, 0xFF, 0xFC, 0x84, 0x21, + 0x3E, 0x00, 0x60, 0x08, 0x02, 0x3F, 0x98, 0x28, 0x0A, 0x02, 0xC3, 0x9F, + 0x30, 0xE0, 0x01, 0x00, 0x08, 0x00, 0x40, 0x02, 0x00, 0x13, 0xE0, 0xA0, + 0x86, 0x02, 0x20, 0x09, 0x00, 0x48, 0x02, 0x40, 0x13, 0x01, 0x14, 0x1B, + 0x9F, 0x00, 0x1F, 0x4C, 0x19, 0x01, 0x40, 0x28, 0x01, 0x00, 0x20, 0x02, + 0x00, 0x60, 0x43, 0xF0, 0x00, 0xC0, 0x08, 0x01, 0x00, 0x20, 0x04, 0x3C, + 0x98, 0x52, 0x06, 0x80, 0x50, 0x0A, 0x01, 0x40, 0x24, 0x0C, 0xC2, 0x87, + 0x98, 0x3F, 0x18, 0x68, 0x06, 0x01, 0xFF, 0xE0, 0x08, 0x03, 0x00, 0x60, + 0xC7, 0xC0, 0x0F, 0x98, 0x08, 0x04, 0x02, 0x07, 0xF8, 0x80, 0x40, 0x20, + 0x10, 0x08, 0x04, 0x02, 0x01, 0x03, 0xF8, 0x1E, 0x6C, 0x39, 0x03, 0x40, + 0x28, 0x05, 0x00, 0xA0, 0x12, 0x06, 0x61, 0x43, 0xC8, 0x01, 0x00, 0x20, + 0x08, 0x3E, 0x00, 0xC0, 0x10, 0x04, 0x01, 0x00, 0x40, 0x13, 0x87, 0x11, + 0x82, 0x40, 0x90, 0x24, 0x09, 0x02, 0x40, 0x90, 0x2E, 0x1C, 0x08, 0x04, + 0x02, 0x00, 0x00, 0x03, 0xC0, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, + 0x80, 0x43, 0xFE, 0x04, 0x08, 0x10, 0x00, 0x1F, 0xC0, 0x81, 0x02, 0x04, + 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x0B, 0xE0, 0xE0, 0x02, 0x00, 0x20, + 0x02, 0x00, 0x20, 0x02, 0x3C, 0x21, 0x02, 0x60, 0x2C, 0x03, 0x80, 0x24, + 0x02, 0x20, 0x21, 0x02, 0x08, 0xE1, 0xF0, 0x78, 0x04, 0x02, 0x01, 0x00, + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x43, 0xFE, + 0xDC, 0xE3, 0x19, 0x90, 0x84, 0x84, 0x24, 0x21, 0x21, 0x09, 0x08, 0x48, + 0x42, 0x42, 0x17, 0x18, 0xC0, 0x67, 0x83, 0x84, 0x20, 0x22, 0x02, 0x20, + 0x22, 0x02, 0x20, 0x22, 0x02, 0x20, 0x2F, 0x07, 0x1F, 0x04, 0x11, 0x01, + 0x40, 0x18, 0x03, 0x00, 0x60, 0x0A, 0x02, 0x20, 0x83, 0xE0, 0xCF, 0x85, + 0x06, 0x60, 0x24, 0x01, 0x40, 0x14, 0x01, 0x40, 0x16, 0x02, 0x50, 0x44, + 0xF8, 0x40, 0x04, 0x00, 0x40, 0x0F, 0x00, 0x1E, 0x6C, 0x3B, 0x03, 0x40, + 0x28, 0x05, 0x00, 0xA0, 0x12, 0x06, 0x61, 0x43, 0xC8, 0x01, 0x00, 0x20, + 0x04, 0x03, 0xC0, 0xE3, 0x8B, 0x13, 0x80, 0x80, 0x20, 0x08, 0x02, 0x00, + 0x80, 0x20, 0x3F, 0x80, 0x1F, 0x58, 0x34, 0x05, 0x80, 0x1E, 0x00, 0x60, + 0x06, 0x01, 0xC0, 0xAF, 0xC0, 0x20, 0x04, 0x00, 0x80, 0x10, 0x0F, 0xF0, + 0x40, 0x08, 0x01, 0x00, 0x20, 0x04, 0x00, 0x80, 0x10, 0x03, 0x04, 0x3F, + 0x00, 0xC1, 0xC8, 0x09, 0x01, 0x20, 0x24, 0x04, 0x80, 0x90, 0x12, 0x02, + 0x61, 0xC7, 0xCC, 0xF8, 0xF9, 0x01, 0x08, 0x10, 0x60, 0x81, 0x08, 0x08, + 0x40, 0x22, 0x01, 0x20, 0x05, 0x00, 0x30, 0x00, 0xF0, 0x7A, 0x01, 0x10, + 0x08, 0x8C, 0x42, 0x62, 0x12, 0x90, 0xA5, 0x05, 0x18, 0x28, 0xC0, 0x86, + 0x00, 0x78, 0xF3, 0x04, 0x18, 0x80, 0xD0, 0x06, 0x00, 0x70, 0x09, 0x81, + 0x0C, 0x20, 0x6F, 0x8F, 0xF0, 0xF2, 0x02, 0x20, 0x41, 0x04, 0x10, 0x80, + 0x88, 0x09, 0x00, 0x50, 0x06, 0x00, 0x20, 0x04, 0x00, 0x40, 0x08, 0x0F, + 0xE0, 0xFF, 0x41, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x40, 0xBF, + 0xC0, 0x19, 0x08, 0x42, 0x10, 0x84, 0x64, 0x18, 0x42, 0x10, 0x84, 0x20, + 0xC0, 0xFF, 0xFF, 0xC0, 0xC1, 0x08, 0x42, 0x10, 0x84, 0x10, 0x4C, 0x42, + 0x10, 0x84, 0x26, 0x00, 0x38, 0x13, 0x38, 0x38 }; + +const GFXglyph FreeMono12pt7bGlyphs[] PROGMEM = { + { 0, 0, 0, 14, 0, 1 }, // 0x20 ' ' + { 0, 3, 15, 14, 6, -14 }, // 0x21 '!' + { 6, 8, 7, 14, 3, -14 }, // 0x22 '"' + { 13, 10, 16, 14, 2, -14 }, // 0x23 '#' + { 33, 10, 17, 14, 2, -14 }, // 0x24 '$' + { 55, 10, 15, 14, 2, -14 }, // 0x25 '%' + { 74, 9, 12, 14, 3, -11 }, // 0x26 '&' + { 88, 3, 7, 14, 5, -14 }, // 0x27 ''' + { 91, 3, 18, 14, 7, -14 }, // 0x28 '(' + { 98, 3, 18, 14, 4, -14 }, // 0x29 ')' + { 105, 9, 9, 14, 3, -14 }, // 0x2A '*' + { 116, 9, 11, 14, 3, -11 }, // 0x2B '+' + { 129, 5, 7, 14, 3, -3 }, // 0x2C ',' + { 134, 11, 1, 14, 2, -6 }, // 0x2D '-' + { 136, 3, 3, 14, 5, -2 }, // 0x2E '.' + { 138, 9, 18, 14, 3, -15 }, // 0x2F '/' + { 159, 9, 15, 14, 3, -14 }, // 0x30 '0' + { 176, 7, 14, 14, 4, -13 }, // 0x31 '1' + { 189, 9, 15, 14, 2, -14 }, // 0x32 '2' + { 206, 10, 15, 14, 2, -14 }, // 0x33 '3' + { 225, 8, 15, 14, 3, -14 }, // 0x34 '4' + { 240, 9, 15, 14, 3, -14 }, // 0x35 '5' + { 257, 9, 15, 14, 3, -14 }, // 0x36 '6' + { 274, 8, 15, 14, 3, -14 }, // 0x37 '7' + { 289, 9, 15, 14, 3, -14 }, // 0x38 '8' + { 306, 9, 15, 14, 3, -14 }, // 0x39 '9' + { 323, 3, 10, 14, 5, -9 }, // 0x3A ':' + { 327, 5, 13, 14, 3, -9 }, // 0x3B ';' + { 336, 11, 11, 14, 2, -11 }, // 0x3C '<' + { 352, 12, 4, 14, 1, -8 }, // 0x3D '=' + { 358, 11, 11, 14, 2, -11 }, // 0x3E '>' + { 374, 9, 14, 14, 3, -13 }, // 0x3F '?' + { 390, 9, 16, 14, 3, -14 }, // 0x40 '@' + { 408, 14, 14, 14, 0, -13 }, // 0x41 'A' + { 433, 11, 14, 14, 2, -13 }, // 0x42 'B' + { 453, 10, 14, 14, 2, -13 }, // 0x43 'C' + { 471, 10, 14, 14, 2, -13 }, // 0x44 'D' + { 489, 11, 14, 14, 2, -13 }, // 0x45 'E' + { 509, 11, 14, 14, 2, -13 }, // 0x46 'F' + { 529, 11, 14, 14, 2, -13 }, // 0x47 'G' + { 549, 10, 14, 14, 2, -13 }, // 0x48 'H' + { 567, 7, 14, 14, 4, -13 }, // 0x49 'I' + { 580, 11, 14, 14, 2, -13 }, // 0x4A 'J' + { 600, 12, 14, 14, 2, -13 }, // 0x4B 'K' + { 621, 11, 14, 14, 2, -13 }, // 0x4C 'L' + { 641, 13, 14, 14, 1, -13 }, // 0x4D 'M' + { 664, 12, 14, 14, 1, -13 }, // 0x4E 'N' + { 685, 12, 14, 14, 1, -13 }, // 0x4F 'O' + { 706, 10, 14, 14, 2, -13 }, // 0x50 'P' + { 724, 12, 17, 14, 1, -13 }, // 0x51 'Q' + { 750, 12, 14, 14, 2, -13 }, // 0x52 'R' + { 771, 10, 14, 14, 2, -13 }, // 0x53 'S' + { 789, 11, 14, 14, 2, -13 }, // 0x54 'T' + { 809, 12, 14, 14, 1, -13 }, // 0x55 'U' + { 830, 14, 14, 14, 0, -13 }, // 0x56 'V' + { 855, 14, 14, 14, 0, -13 }, // 0x57 'W' + { 880, 12, 14, 14, 1, -13 }, // 0x58 'X' + { 901, 12, 14, 14, 1, -13 }, // 0x59 'Y' + { 922, 9, 14, 14, 3, -13 }, // 0x5A 'Z' + { 938, 3, 18, 14, 7, -14 }, // 0x5B '[' + { 945, 9, 18, 14, 3, -15 }, // 0x5C '\' + { 966, 3, 18, 14, 5, -14 }, // 0x5D ']' + { 973, 9, 6, 14, 3, -14 }, // 0x5E '^' + { 980, 14, 1, 14, 0, 3 }, // 0x5F '_' + { 982, 4, 4, 14, 4, -15 }, // 0x60 '`' + { 984, 10, 10, 14, 2, -9 }, // 0x61 'a' + { 997, 13, 15, 14, 0, -14 }, // 0x62 'b' + { 1022, 11, 10, 14, 2, -9 }, // 0x63 'c' + { 1036, 11, 15, 14, 2, -14 }, // 0x64 'd' + { 1057, 10, 10, 14, 2, -9 }, // 0x65 'e' + { 1070, 9, 15, 14, 4, -14 }, // 0x66 'f' + { 1087, 11, 14, 14, 2, -9 }, // 0x67 'g' + { 1107, 10, 15, 14, 2, -14 }, // 0x68 'h' + { 1126, 9, 15, 14, 3, -14 }, // 0x69 'i' + { 1143, 7, 19, 14, 3, -14 }, // 0x6A 'j' + { 1160, 12, 15, 14, 1, -14 }, // 0x6B 'k' + { 1183, 9, 15, 14, 3, -14 }, // 0x6C 'l' + { 1200, 13, 10, 14, 1, -9 }, // 0x6D 'm' + { 1217, 12, 10, 14, 1, -9 }, // 0x6E 'n' + { 1232, 11, 10, 14, 2, -9 }, // 0x6F 'o' + { 1246, 12, 14, 14, 1, -9 }, // 0x70 'p' + { 1267, 11, 14, 14, 2, -9 }, // 0x71 'q' + { 1287, 10, 10, 14, 3, -9 }, // 0x72 'r' + { 1300, 10, 10, 14, 2, -9 }, // 0x73 's' + { 1313, 11, 14, 14, 1, -13 }, // 0x74 't' + { 1333, 11, 10, 14, 2, -9 }, // 0x75 'u' + { 1347, 13, 10, 14, 1, -9 }, // 0x76 'v' + { 1364, 13, 10, 14, 1, -9 }, // 0x77 'w' + { 1381, 12, 10, 14, 1, -9 }, // 0x78 'x' + { 1396, 12, 14, 14, 1, -9 }, // 0x79 'y' + { 1417, 9, 10, 14, 3, -9 }, // 0x7A 'z' + { 1429, 5, 18, 14, 5, -14 }, // 0x7B '{' + { 1441, 1, 18, 14, 7, -14 }, // 0x7C '|' + { 1444, 5, 18, 14, 5, -14 }, // 0x7D '}' + { 1456, 10, 3, 14, 2, -7 } }; // 0x7E '~' + +const GFXfont FreeMono12pt7b PROGMEM = { + (uint8_t *)FreeMono12pt7bBitmaps, + (GFXglyph *)FreeMono12pt7bGlyphs, + 0x20, 0x7E, 24 }; + +// Approx. 2132 bytes diff --git a/libraries/fonts/FreeMono9pt7b.h b/libraries/fonts/FreeMono9pt7b.h new file mode 100644 index 0000000..c82d786 --- /dev/null +++ b/libraries/fonts/FreeMono9pt7b.h @@ -0,0 +1,176 @@ +const uint8_t FreeMono9pt7bBitmaps[] PROGMEM = { + 0xAA, 0xA8, 0x0C, 0xED, 0x24, 0x92, 0x48, 0x24, 0x48, 0x91, 0x2F, 0xE4, + 0x89, 0x7F, 0x28, 0x51, 0x22, 0x40, 0x08, 0x3E, 0x62, 0x40, 0x30, 0x0E, + 0x01, 0x81, 0xC3, 0xBE, 0x08, 0x08, 0x71, 0x12, 0x23, 0x80, 0x23, 0xB8, + 0x0E, 0x22, 0x44, 0x70, 0x38, 0x81, 0x02, 0x06, 0x1A, 0x65, 0x46, 0xC8, + 0xEC, 0xE9, 0x24, 0x5A, 0xAA, 0xA9, 0x40, 0xA9, 0x55, 0x5A, 0x80, 0x10, + 0x22, 0x4B, 0xE3, 0x05, 0x11, 0x00, 0x10, 0x20, 0x47, 0xF1, 0x02, 0x04, + 0x00, 0x6B, 0x48, 0xFF, 0x00, 0xF0, 0x02, 0x08, 0x10, 0x60, 0x81, 0x04, + 0x08, 0x20, 0x41, 0x02, 0x08, 0x00, 0x38, 0x8A, 0x0C, 0x18, 0x30, 0x60, + 0xC1, 0x82, 0x88, 0xE0, 0x27, 0x28, 0x42, 0x10, 0x84, 0x21, 0x3E, 0x38, + 0x8A, 0x08, 0x10, 0x20, 0x82, 0x08, 0x61, 0x03, 0xF8, 0x7C, 0x06, 0x02, + 0x02, 0x1C, 0x06, 0x01, 0x01, 0x01, 0x42, 0x3C, 0x18, 0xA2, 0x92, 0x8A, + 0x28, 0xBF, 0x08, 0x21, 0xC0, 0x7C, 0x81, 0x03, 0xE4, 0x40, 0x40, 0x81, + 0x03, 0x88, 0xE0, 0x1E, 0x41, 0x04, 0x0B, 0x98, 0xB0, 0xC1, 0xC2, 0x88, + 0xE0, 0xFE, 0x04, 0x08, 0x20, 0x40, 0x82, 0x04, 0x08, 0x20, 0x40, 0x38, + 0x8A, 0x0C, 0x14, 0x47, 0x11, 0x41, 0x83, 0x8C, 0xE0, 0x38, 0x8A, 0x1C, + 0x18, 0x68, 0xCE, 0x81, 0x04, 0x13, 0xC0, 0xF0, 0x0F, 0x6C, 0x00, 0xD2, + 0xD2, 0x00, 0x03, 0x04, 0x18, 0x60, 0x60, 0x18, 0x04, 0x03, 0xFF, 0x80, + 0x00, 0x1F, 0xF0, 0x40, 0x18, 0x03, 0x00, 0x60, 0x20, 0x60, 0xC0, 0x80, + 0x3D, 0x84, 0x08, 0x30, 0xC2, 0x00, 0x00, 0x00, 0x30, 0x3C, 0x46, 0x82, + 0x8E, 0xB2, 0xA2, 0xA2, 0x9F, 0x80, 0x80, 0x40, 0x3C, 0x3C, 0x01, 0x40, + 0x28, 0x09, 0x01, 0x10, 0x42, 0x0F, 0xC1, 0x04, 0x40, 0x9E, 0x3C, 0xFE, + 0x21, 0x90, 0x48, 0x67, 0xE2, 0x09, 0x02, 0x81, 0x41, 0xFF, 0x80, 0x3E, + 0xB0, 0xF0, 0x30, 0x08, 0x04, 0x02, 0x00, 0x80, 0x60, 0x8F, 0x80, 0xFE, + 0x21, 0x90, 0x68, 0x14, 0x0A, 0x05, 0x02, 0x83, 0x43, 0x7F, 0x00, 0xFF, + 0x20, 0x90, 0x08, 0x87, 0xC2, 0x21, 0x00, 0x81, 0x40, 0xFF, 0xC0, 0xFF, + 0xA0, 0x50, 0x08, 0x87, 0xC2, 0x21, 0x00, 0x80, 0x40, 0x78, 0x00, 0x1E, + 0x98, 0x6C, 0x0A, 0x00, 0x80, 0x20, 0xF8, 0x0B, 0x02, 0x60, 0x87, 0xC0, + 0xE3, 0xA0, 0x90, 0x48, 0x27, 0xF2, 0x09, 0x04, 0x82, 0x41, 0x71, 0xC0, + 0xF9, 0x08, 0x42, 0x10, 0x84, 0x27, 0xC0, 0x1F, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x82, 0x82, 0xC6, 0x78, 0xE3, 0xA1, 0x11, 0x09, 0x05, 0x83, 0x21, + 0x08, 0x84, 0x41, 0x70, 0xC0, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, + 0x41, 0x41, 0xFF, 0xE0, 0xEC, 0x19, 0x45, 0x28, 0xA4, 0xA4, 0x94, 0x91, + 0x12, 0x02, 0x40, 0x5C, 0x1C, 0xC3, 0xB0, 0x94, 0x4A, 0x24, 0x92, 0x49, + 0x14, 0x8A, 0x43, 0x70, 0x80, 0x1E, 0x31, 0x90, 0x50, 0x18, 0x0C, 0x06, + 0x02, 0x82, 0x63, 0x0F, 0x00, 0xFE, 0x43, 0x41, 0x41, 0x42, 0x7C, 0x40, + 0x40, 0x40, 0xF0, 0x1C, 0x31, 0x90, 0x50, 0x18, 0x0C, 0x06, 0x02, 0x82, + 0x63, 0x1F, 0x04, 0x07, 0x92, 0x30, 0xFE, 0x21, 0x90, 0x48, 0x24, 0x23, + 0xE1, 0x10, 0x84, 0x41, 0x70, 0xC0, 0x3A, 0xCD, 0x0A, 0x03, 0x01, 0x80, + 0xC1, 0xC7, 0x78, 0xFF, 0xC4, 0x62, 0x21, 0x00, 0x80, 0x40, 0x20, 0x10, + 0x08, 0x1F, 0x00, 0xE3, 0xA0, 0x90, 0x48, 0x24, 0x12, 0x09, 0x04, 0x82, + 0x22, 0x0E, 0x00, 0xF1, 0xE8, 0x10, 0x82, 0x10, 0x42, 0x10, 0x22, 0x04, + 0x80, 0x50, 0x0C, 0x00, 0x80, 0xF1, 0xE8, 0x09, 0x11, 0x25, 0x44, 0xA8, + 0x55, 0x0C, 0xA1, 0x8C, 0x31, 0x84, 0x30, 0xE3, 0xA0, 0x88, 0x82, 0x80, + 0x80, 0xC0, 0x90, 0x44, 0x41, 0x71, 0xC0, 0xE3, 0xA0, 0x88, 0x82, 0x81, + 0x40, 0x40, 0x20, 0x10, 0x08, 0x1F, 0x00, 0xFD, 0x0A, 0x20, 0x81, 0x04, + 0x10, 0x21, 0x83, 0xFC, 0xEA, 0xAA, 0xAA, 0xC0, 0x80, 0x81, 0x03, 0x02, + 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0xD5, 0x55, 0x55, 0xC0, + 0x10, 0x51, 0x22, 0x28, 0x20, 0xFF, 0xE0, 0x88, 0x80, 0x7E, 0x00, 0x80, + 0x47, 0xEC, 0x14, 0x0A, 0x0C, 0xFB, 0xC0, 0x20, 0x10, 0x0B, 0xC6, 0x12, + 0x05, 0x02, 0x81, 0x40, 0xB0, 0xB7, 0x80, 0x3A, 0x8E, 0x0C, 0x08, 0x10, + 0x10, 0x9E, 0x03, 0x00, 0x80, 0x47, 0xA4, 0x34, 0x0A, 0x05, 0x02, 0x81, + 0x21, 0x8F, 0x60, 0x3C, 0x43, 0x81, 0xFF, 0x80, 0x80, 0x61, 0x3E, 0x3D, + 0x04, 0x3E, 0x41, 0x04, 0x10, 0x41, 0x0F, 0x80, 0x3D, 0xA1, 0xA0, 0x50, + 0x28, 0x14, 0x09, 0x0C, 0x7A, 0x01, 0x01, 0x87, 0x80, 0xC0, 0x20, 0x10, + 0x0B, 0xC6, 0x32, 0x09, 0x04, 0x82, 0x41, 0x20, 0xB8, 0xE0, 0x10, 0x01, + 0xC0, 0x81, 0x02, 0x04, 0x08, 0x11, 0xFC, 0x10, 0x3E, 0x10, 0x84, 0x21, + 0x08, 0x42, 0x3F, 0x00, 0xC0, 0x40, 0x40, 0x4F, 0x44, 0x58, 0x70, 0x48, + 0x44, 0x42, 0xC7, 0x70, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x23, + 0xF8, 0xB7, 0x64, 0x62, 0x31, 0x18, 0x8C, 0x46, 0x23, 0x91, 0x5E, 0x31, + 0x90, 0x48, 0x24, 0x12, 0x09, 0x05, 0xC7, 0x3E, 0x31, 0xA0, 0x30, 0x18, + 0x0C, 0x05, 0x8C, 0x7C, 0xDE, 0x30, 0x90, 0x28, 0x14, 0x0A, 0x05, 0x84, + 0xBC, 0x40, 0x20, 0x38, 0x00, 0x3D, 0xA1, 0xA0, 0x50, 0x28, 0x14, 0x09, + 0x0C, 0x7A, 0x01, 0x00, 0x80, 0xE0, 0xCE, 0xA1, 0x82, 0x04, 0x08, 0x10, + 0x7C, 0x3A, 0x8D, 0x0B, 0x80, 0xF0, 0x70, 0xDE, 0x40, 0x40, 0xFC, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x41, 0x3E, 0xC3, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x43, 0x3D, 0xE3, 0xA0, 0x90, 0x84, 0x42, 0x20, 0xA0, 0x50, 0x10, 0xE3, + 0xC0, 0x92, 0x4B, 0x25, 0x92, 0xA9, 0x98, 0x44, 0xE3, 0x31, 0x05, 0x01, + 0x01, 0x41, 0x11, 0x05, 0xC7, 0xE3, 0xA0, 0x90, 0x84, 0x42, 0x40, 0xA0, + 0x60, 0x10, 0x10, 0x08, 0x3E, 0x00, 0xFD, 0x08, 0x20, 0x82, 0x08, 0x10, + 0xBF, 0x29, 0x24, 0xA2, 0x49, 0x26, 0xFF, 0xF8, 0x89, 0x24, 0x8A, 0x49, + 0x2C, 0x61, 0x24, 0x30 }; + +const GFXglyph FreeMono9pt7bGlyphs[] PROGMEM = { + { 0, 0, 0, 11, 0, 1 }, // 0x20 ' ' + { 0, 2, 11, 11, 4, -10 }, // 0x21 '!' + { 3, 6, 5, 11, 2, -10 }, // 0x22 '"' + { 7, 7, 12, 11, 2, -10 }, // 0x23 '#' + { 18, 8, 12, 11, 1, -10 }, // 0x24 '$' + { 30, 7, 11, 11, 2, -10 }, // 0x25 '%' + { 40, 7, 10, 11, 2, -9 }, // 0x26 '&' + { 49, 3, 5, 11, 4, -10 }, // 0x27 ''' + { 51, 2, 13, 11, 5, -10 }, // 0x28 '(' + { 55, 2, 13, 11, 4, -10 }, // 0x29 ')' + { 59, 7, 7, 11, 2, -10 }, // 0x2A '*' + { 66, 7, 7, 11, 2, -8 }, // 0x2B '+' + { 73, 3, 5, 11, 2, -1 }, // 0x2C ',' + { 75, 9, 1, 11, 1, -5 }, // 0x2D '-' + { 77, 2, 2, 11, 4, -1 }, // 0x2E '.' + { 78, 7, 13, 11, 2, -11 }, // 0x2F '/' + { 90, 7, 11, 11, 2, -10 }, // 0x30 '0' + { 100, 5, 11, 11, 3, -10 }, // 0x31 '1' + { 107, 7, 11, 11, 2, -10 }, // 0x32 '2' + { 117, 8, 11, 11, 1, -10 }, // 0x33 '3' + { 128, 6, 11, 11, 3, -10 }, // 0x34 '4' + { 137, 7, 11, 11, 2, -10 }, // 0x35 '5' + { 147, 7, 11, 11, 2, -10 }, // 0x36 '6' + { 157, 7, 11, 11, 2, -10 }, // 0x37 '7' + { 167, 7, 11, 11, 2, -10 }, // 0x38 '8' + { 177, 7, 11, 11, 2, -10 }, // 0x39 '9' + { 187, 2, 8, 11, 4, -7 }, // 0x3A ':' + { 189, 3, 11, 11, 3, -7 }, // 0x3B ';' + { 194, 8, 8, 11, 1, -8 }, // 0x3C '<' + { 202, 9, 4, 11, 1, -6 }, // 0x3D '=' + { 207, 9, 8, 11, 1, -8 }, // 0x3E '>' + { 216, 7, 10, 11, 2, -9 }, // 0x3F '?' + { 225, 8, 12, 11, 2, -10 }, // 0x40 '@' + { 237, 11, 10, 11, 0, -9 }, // 0x41 'A' + { 251, 9, 10, 11, 1, -9 }, // 0x42 'B' + { 263, 9, 10, 11, 1, -9 }, // 0x43 'C' + { 275, 9, 10, 11, 1, -9 }, // 0x44 'D' + { 287, 9, 10, 11, 1, -9 }, // 0x45 'E' + { 299, 9, 10, 11, 1, -9 }, // 0x46 'F' + { 311, 10, 10, 11, 1, -9 }, // 0x47 'G' + { 324, 9, 10, 11, 1, -9 }, // 0x48 'H' + { 336, 5, 10, 11, 3, -9 }, // 0x49 'I' + { 343, 8, 10, 11, 2, -9 }, // 0x4A 'J' + { 353, 9, 10, 11, 1, -9 }, // 0x4B 'K' + { 365, 8, 10, 11, 2, -9 }, // 0x4C 'L' + { 375, 11, 10, 11, 0, -9 }, // 0x4D 'M' + { 389, 9, 10, 11, 1, -9 }, // 0x4E 'N' + { 401, 9, 10, 11, 1, -9 }, // 0x4F 'O' + { 413, 8, 10, 11, 1, -9 }, // 0x50 'P' + { 423, 9, 13, 11, 1, -9 }, // 0x51 'Q' + { 438, 9, 10, 11, 1, -9 }, // 0x52 'R' + { 450, 7, 10, 11, 2, -9 }, // 0x53 'S' + { 459, 9, 10, 11, 1, -9 }, // 0x54 'T' + { 471, 9, 10, 11, 1, -9 }, // 0x55 'U' + { 483, 11, 10, 11, 0, -9 }, // 0x56 'V' + { 497, 11, 10, 11, 0, -9 }, // 0x57 'W' + { 511, 9, 10, 11, 1, -9 }, // 0x58 'X' + { 523, 9, 10, 11, 1, -9 }, // 0x59 'Y' + { 535, 7, 10, 11, 2, -9 }, // 0x5A 'Z' + { 544, 2, 13, 11, 5, -10 }, // 0x5B '[' + { 548, 7, 13, 11, 2, -11 }, // 0x5C '\' + { 560, 2, 13, 11, 4, -10 }, // 0x5D ']' + { 564, 7, 5, 11, 2, -10 }, // 0x5E '^' + { 569, 11, 1, 11, 0, 2 }, // 0x5F '_' + { 571, 3, 3, 11, 3, -11 }, // 0x60 '`' + { 573, 9, 8, 11, 1, -7 }, // 0x61 'a' + { 582, 9, 11, 11, 1, -10 }, // 0x62 'b' + { 595, 7, 8, 11, 2, -7 }, // 0x63 'c' + { 602, 9, 11, 11, 1, -10 }, // 0x64 'd' + { 615, 8, 8, 11, 1, -7 }, // 0x65 'e' + { 623, 6, 11, 11, 3, -10 }, // 0x66 'f' + { 632, 9, 11, 11, 1, -7 }, // 0x67 'g' + { 645, 9, 11, 11, 1, -10 }, // 0x68 'h' + { 658, 7, 10, 11, 2, -9 }, // 0x69 'i' + { 667, 5, 13, 11, 3, -9 }, // 0x6A 'j' + { 676, 8, 11, 11, 2, -10 }, // 0x6B 'k' + { 687, 7, 11, 11, 2, -10 }, // 0x6C 'l' + { 697, 9, 8, 11, 1, -7 }, // 0x6D 'm' + { 706, 9, 8, 11, 1, -7 }, // 0x6E 'n' + { 715, 9, 8, 11, 1, -7 }, // 0x6F 'o' + { 724, 9, 11, 11, 1, -7 }, // 0x70 'p' + { 737, 9, 11, 11, 1, -7 }, // 0x71 'q' + { 750, 7, 8, 11, 3, -7 }, // 0x72 'r' + { 757, 7, 8, 11, 2, -7 }, // 0x73 's' + { 764, 8, 10, 11, 2, -9 }, // 0x74 't' + { 774, 8, 8, 11, 1, -7 }, // 0x75 'u' + { 782, 9, 8, 11, 1, -7 }, // 0x76 'v' + { 791, 9, 8, 11, 1, -7 }, // 0x77 'w' + { 800, 9, 8, 11, 1, -7 }, // 0x78 'x' + { 809, 9, 11, 11, 1, -7 }, // 0x79 'y' + { 822, 7, 8, 11, 2, -7 }, // 0x7A 'z' + { 829, 3, 13, 11, 4, -10 }, // 0x7B '{' + { 834, 1, 13, 11, 5, -10 }, // 0x7C '|' + { 836, 3, 13, 11, 4, -10 }, // 0x7D '}' + { 841, 7, 3, 11, 2, -6 } }; // 0x7E '~' + +const GFXfont FreeMono9pt7b PROGMEM = { + (uint8_t *)FreeMono9pt7bBitmaps, + (GFXglyph *)FreeMono9pt7bGlyphs, + 0x20, 0x7E, 18 }; + +// Approx. 1516 bytes diff --git a/libraries/fonts/Picopixel.h b/libraries/fonts/Picopixel.h new file mode 100644 index 0000000..0ed6543 --- /dev/null +++ b/libraries/fonts/Picopixel.h @@ -0,0 +1,123 @@ +// Picopixel by Sebastian Weber. A tiny font +// with all characters within a 6 pixel height. + +const uint8_t PicopixelBitmaps[] PROGMEM = { + 0xE8, 0xB4, 0x57, 0xD5, 0xF5, 0x00, 0x4E, 0x3E, 0x80, 0xA5, 0x4A, 0x4A, + 0x5A, 0x50, 0xC0, 0x6A, 0x40, 0x95, 0x80, 0xAA, 0x80, 0x5D, 0x00, 0x60, + 0xE0, 0x80, 0x25, 0x48, 0x56, 0xD4, 0x75, 0x40, 0xC5, 0x4E, 0xC5, 0x1C, + 0x97, 0x92, 0xF3, 0x1C, 0x53, 0x54, 0xE5, 0x48, 0x55, 0x54, 0x55, 0x94, + 0xA0, 0x46, 0x64, 0xE3, 0x80, 0x98, 0xC5, 0x04, 0x56, 0xC6, 0x57, 0xDA, + 0xD7, 0x5C, 0x72, 0x46, 0xD6, 0xDC, 0xF3, 0xCE, 0xF3, 0x48, 0x72, 0xD4, + 0xB7, 0xDA, 0xF8, 0x24, 0xD4, 0xBB, 0x5A, 0x92, 0x4E, 0x8E, 0xEB, 0x58, + 0x80, 0x9D, 0xB9, 0x90, 0x56, 0xD4, 0xD7, 0x48, 0x56, 0xD4, 0x40, 0xD7, + 0x5A, 0x71, 0x1C, 0xE9, 0x24, 0xB6, 0xD4, 0xB6, 0xA4, 0x8C, 0x6B, 0x55, + 0x00, 0xB5, 0x5A, 0xB5, 0x24, 0xE5, 0x4E, 0xEA, 0xC0, 0x91, 0x12, 0xD5, + 0xC0, 0x54, 0xF0, 0x90, 0xC7, 0xF0, 0x93, 0x5E, 0x71, 0x80, 0x25, 0xDE, + 0x5E, 0x30, 0x6E, 0x80, 0x77, 0x9C, 0x93, 0x5A, 0xB8, 0x45, 0x60, 0x92, + 0xEA, 0xAA, 0x40, 0xD5, 0x6A, 0xD6, 0x80, 0x55, 0x00, 0xD7, 0x40, 0x75, + 0x90, 0xE8, 0x71, 0xE0, 0xBA, 0x40, 0xB5, 0x80, 0xB5, 0x00, 0x8D, 0x54, + 0xAA, 0x80, 0xAC, 0xE0, 0xE5, 0x70, 0x6A, 0x26, 0xFC, 0xC8, 0xAC, 0x5A }; + +const GFXglyph PicopixelGlyphs[] PROGMEM = { + { 0, 0, 0, 2, 0, 1 }, // 0x20 ' ' + { 0, 1, 5, 2, 0, -4 }, // 0x21 '!' + { 1, 3, 2, 4, 0, -4 }, // 0x22 '"' + { 2, 5, 5, 6, 0, -4 }, // 0x23 '#' + { 6, 3, 6, 4, 0, -4 }, // 0x24 '$' + { 9, 3, 5, 4, 0, -4 }, // 0x25 '%' + { 11, 4, 5, 5, 0, -4 }, // 0x26 '&' + { 14, 1, 2, 2, 0, -4 }, // 0x27 ''' + { 15, 2, 5, 3, 0, -4 }, // 0x28 '(' + { 17, 2, 5, 3, 0, -4 }, // 0x29 ')' + { 19, 3, 3, 4, 0, -3 }, // 0x2A '*' + { 21, 3, 3, 4, 0, -3 }, // 0x2B '+' + { 23, 2, 2, 3, 0, 0 }, // 0x2C ',' + { 24, 3, 1, 4, 0, -2 }, // 0x2D '-' + { 25, 1, 1, 2, 0, 0 }, // 0x2E '.' + { 26, 3, 5, 4, 0, -4 }, // 0x2F '/' + { 28, 3, 5, 4, 0, -4 }, // 0x30 '0' + { 30, 2, 5, 3, 0, -4 }, // 0x31 '1' + { 32, 3, 5, 4, 0, -4 }, // 0x32 '2' + { 34, 3, 5, 4, 0, -4 }, // 0x33 '3' + { 36, 3, 5, 4, 0, -4 }, // 0x34 '4' + { 38, 3, 5, 4, 0, -4 }, // 0x35 '5' + { 40, 3, 5, 4, 0, -4 }, // 0x36 '6' + { 42, 3, 5, 4, 0, -4 }, // 0x37 '7' + { 44, 3, 5, 4, 0, -4 }, // 0x38 '8' + { 46, 3, 5, 4, 0, -4 }, // 0x39 '9' + { 48, 1, 3, 2, 0, -3 }, // 0x3A ':' + { 49, 2, 4, 3, 0, -3 }, // 0x3B ';' + { 50, 2, 3, 3, 0, -3 }, // 0x3C '<' + { 51, 3, 3, 4, 0, -3 }, // 0x3D '=' + { 53, 2, 3, 3, 0, -3 }, // 0x3E '>' + { 54, 3, 5, 4, 0, -4 }, // 0x3F '?' + { 56, 3, 5, 4, 0, -4 }, // 0x40 '@' + { 58, 3, 5, 4, 0, -4 }, // 0x41 'A' + { 60, 3, 5, 4, 0, -4 }, // 0x42 'B' + { 62, 3, 5, 4, 0, -4 }, // 0x43 'C' + { 64, 3, 5, 4, 0, -4 }, // 0x44 'D' + { 66, 3, 5, 4, 0, -4 }, // 0x45 'E' + { 68, 3, 5, 4, 0, -4 }, // 0x46 'F' + { 70, 3, 5, 4, 0, -4 }, // 0x47 'G' + { 72, 3, 5, 4, 0, -4 }, // 0x48 'H' + { 74, 1, 5, 2, 0, -4 }, // 0x49 'I' + { 75, 3, 5, 4, 0, -4 }, // 0x4A 'J' + { 77, 3, 5, 4, 0, -4 }, // 0x4B 'K' + { 79, 3, 5, 4, 0, -4 }, // 0x4C 'L' + { 81, 5, 5, 6, 0, -4 }, // 0x4D 'M' + { 85, 4, 5, 5, 0, -4 }, // 0x4E 'N' + { 88, 3, 5, 4, 0, -4 }, // 0x4F 'O' + { 90, 3, 5, 4, 0, -4 }, // 0x50 'P' + { 92, 3, 6, 4, 0, -4 }, // 0x51 'Q' + { 95, 3, 5, 4, 0, -4 }, // 0x52 'R' + { 97, 3, 5, 4, 0, -4 }, // 0x53 'S' + { 99, 3, 5, 4, 0, -4 }, // 0x54 'T' + { 101, 3, 5, 4, 0, -4 }, // 0x55 'U' + { 103, 3, 5, 4, 0, -4 }, // 0x56 'V' + { 105, 5, 5, 6, 0, -4 }, // 0x57 'W' + { 109, 3, 5, 4, 0, -4 }, // 0x58 'X' + { 111, 3, 5, 4, 0, -4 }, // 0x59 'Y' + { 113, 3, 5, 4, 0, -4 }, // 0x5A 'Z' + { 115, 2, 5, 3, 0, -4 }, // 0x5B '[' + { 117, 3, 5, 4, 0, -4 }, // 0x5C '\' + { 119, 2, 5, 3, 0, -4 }, // 0x5D ']' + { 121, 3, 2, 4, 0, -4 }, // 0x5E '^' + { 122, 4, 1, 4, 0, 1 }, // 0x5F '_' + { 123, 2, 2, 3, 0, -4 }, // 0x60 '`' + { 124, 3, 4, 4, 0, -3 }, // 0x61 'a' + { 126, 3, 5, 4, 0, -4 }, // 0x62 'b' + { 128, 3, 3, 4, 0, -2 }, // 0x63 'c' + { 130, 3, 5, 4, 0, -4 }, // 0x64 'd' + { 132, 3, 4, 4, 0, -3 }, // 0x65 'e' + { 134, 2, 5, 3, 0, -4 }, // 0x66 'f' + { 136, 3, 5, 4, 0, -3 }, // 0x67 'g' + { 138, 3, 5, 4, 0, -4 }, // 0x68 'h' + { 140, 1, 5, 2, 0, -4 }, // 0x69 'i' + { 141, 2, 6, 3, 0, -4 }, // 0x6A 'j' + { 143, 3, 5, 4, 0, -4 }, // 0x6B 'k' + { 145, 2, 5, 3, 0, -4 }, // 0x6C 'l' + { 147, 5, 3, 6, 0, -2 }, // 0x6D 'm' + { 149, 3, 3, 4, 0, -2 }, // 0x6E 'n' + { 151, 3, 3, 4, 0, -2 }, // 0x6F 'o' + { 153, 3, 4, 4, 0, -2 }, // 0x70 'p' + { 155, 3, 4, 4, 0, -2 }, // 0x71 'q' + { 157, 2, 3, 3, 0, -2 }, // 0x72 'r' + { 158, 3, 4, 4, 0, -3 }, // 0x73 's' + { 160, 2, 5, 3, 0, -4 }, // 0x74 't' + { 162, 3, 3, 4, 0, -2 }, // 0x75 'u' + { 164, 3, 3, 4, 0, -2 }, // 0x76 'v' + { 166, 5, 3, 6, 0, -2 }, // 0x77 'w' + { 168, 3, 3, 4, 0, -2 }, // 0x78 'x' + { 170, 3, 4, 4, 0, -2 }, // 0x79 'y' + { 172, 3, 4, 4, 0, -3 }, // 0x7A 'z' + { 174, 3, 5, 4, 0, -4 }, // 0x7B '{' + { 176, 1, 6, 2, 0, -4 }, // 0x7C '|' + { 177, 3, 5, 4, 0, -4 }, // 0x7D '}' + { 179, 4, 2, 5, 0, -3 } }; // 0x7E '~' + +const GFXfont Picopixel PROGMEM = { + (uint8_t *)PicopixelBitmaps, + (GFXglyph *)PicopixelGlyphs, + 0x20, 0x7E, 7 }; + +// Approx. 852 bytes