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