diff --git a/README.md b/README.md index a41e3dcf..910ce69e 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ LoLin32lite + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-L *SPI only*: - Pyom: WiPy -- WeMos: LoLin32, LoLin32 Lite, WeMos D32 +- WeMos: LoLin32, LoLin32 Lite, WeMos D32, [Wemos32 Oled](https://www.instructables.com/id/ESP32-With-Integrated-OLED-WEMOSLolin-Getting-Star/) - Generic ESP32 Depending on board hardware following features are supported: @@ -54,6 +54,7 @@ Depending on board hardware following features are supported: - Real Time Clock (Maxim DS3231 I2C) - IF482 (serial) and DCF77 (gpio) time telegram generator - Switch external power / battery +- 64x16 pixel LED Matrix display (similar to [this model](https://www.instructables.com/id/64x16-RED-LED-Marquee/)) Target platform must be selected in [platformio.ini](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/platformio.ini).
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory. If you want to use a ESP32 board which is not yet supported, use hal file generic.h and tailor pin mappings to your needs. Pull requests for new boards welcome.
@@ -153,7 +154,7 @@ Output of user sensor data can be switched by user remote control command 0x13 s Output of sensor and peripheral data is internally switched by a bitmask register. Default mask (0xFF) can be tailored by editing *cfg.payloadmask* initialization value in [*configmanager.cpp*](src/configmanager.cpp) following this scheme: | Bit | Sensordata | -|-----|---------------| +| --- | ------------- | | 0 | GPS | | 1 | Beacon alarm | | 2 | BME280/680 | diff --git a/include/button.h b/include/button.h index b6951ceb..e7799847 100644 --- a/include/button.h +++ b/include/button.h @@ -1,6 +1,9 @@ #ifndef _BUTTON_H #define _BUTTON_H +#include + +void button_init(int pin); void readButton(); #endif \ No newline at end of file diff --git a/include/globals.h b/include/globals.h index 7b427e5a..a3edad17 100644 --- a/include/globals.h +++ b/include/globals.h @@ -113,7 +113,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble, batt_voltage; // display values extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC extern timesource_t timeSource; -extern hw_timer_t *displayIRQ, *ppsIRQ, *gpsIRQ; +extern hw_timer_t *displayIRQ, *matrixDisplayIRQ, *ppsIRQ, *gpsIRQ; extern SemaphoreHandle_t I2Caccess; extern TaskHandle_t irqHandlerTask, ClockTask; extern TimerHandle_t WifiChanTimer; @@ -138,6 +138,10 @@ extern time_t volatile gps_pps_time; #include "display.h" #endif +#ifdef HAS_MATRIX_DISPLAY +#include "ledmatrixdisplay.h" +#endif + #ifdef HAS_BUTTON #include "button.h" #endif diff --git a/include/irqhandler.h b/include/irqhandler.h index 67af99ba..db5dd2f1 100644 --- a/include/irqhandler.h +++ b/include/irqhandler.h @@ -1,14 +1,15 @@ #ifndef _IRQHANDLER_H #define _IRQHANDLER_H -#define DISPLAY_IRQ 0x01 -#define BUTTON_IRQ 0x02 -#define SENDCYCLE_IRQ 0x04 -#define CYCLIC_IRQ 0x08 -#define TIMESYNC_IRQ 0x10 -#define MASK_IRQ 0x20 -#define UNMASK_IRQ 0x40 -#define GPS_IRQ 0x80 +#define DISPLAY_IRQ 0x001 +#define BUTTON_IRQ 0x002 +#define SENDCYCLE_IRQ 0x004 +#define CYCLIC_IRQ 0x008 +#define TIMESYNC_IRQ 0x010 +#define MASK_IRQ 0x020 +#define UNMASK_IRQ 0x040 +#define GPS_IRQ 0x080 +#define MATRIX_DISPLAY_IRQ 0x100 #include "globals.h" #include "cyclic.h" @@ -23,6 +24,10 @@ int unmask_user_IRQ(); void IRAM_ATTR DisplayIRQ(); #endif +#ifdef HAS_MATRIX_DISPLAY +void IRAM_ATTR MatrixDisplayIRQ(); +#endif + #ifdef HAS_BUTTON void IRAM_ATTR ButtonIRQ(); #endif diff --git a/include/ledmatrixdisplay.h b/include/ledmatrixdisplay.h new file mode 100644 index 00000000..5c44676a --- /dev/null +++ b/include/ledmatrixdisplay.h @@ -0,0 +1,17 @@ +#ifndef _MATRIX_DISPLAY_H +#define _MATRIX_DISPLAY_H + +#include "LEDMatrix.h" +#include "ledmatrixfonts.h" + +extern uint8_t MatrixDisplayIsOn = 0; + +extern LEDMatrix matrix; + +void init_matrix_display(const char *Productname, const char *Version); +void refreshTheMatrixDisplay(void); +void DrawNumber(String strNum, uint8_t iDotPos = 0); +uint8_t GetCharFromFont(char cChar); +uint8_t GetCharWidth(char cChar); + +#endif \ No newline at end of file diff --git a/include/ledmatrixfonts.h b/include/ledmatrixfonts.h new file mode 100644 index 00000000..1539465a --- /dev/null +++ b/include/ledmatrixfonts.h @@ -0,0 +1,40 @@ +// Fonts.h + +#ifndef _FONTS_h +#define _FONTS_h + +#include "Arduino.h" + +struct FONT_CHAR_INFO { + uint8_t width; // width in bits + uint8_t height; + uint16_t offset; // offset of char into char array +}; + +struct FONT_INFO { + uint8_t CharHeight; + char StartChar; + char EndChar; + uint8_t SpaceWidth; + const FONT_CHAR_INFO *Descriptors; + const uint8_t *Bitmap; +}; + +// Font data for Microsoft Sans Serif 11pt +extern const uint8_t arialNarrow_17ptBitmaps[]; + +extern const uint8_t gillSansMTCondensed_18ptBitmaps[]; +extern const FONT_INFO gillSansMTCondensed_18ptFontInfo; +extern const FONT_CHAR_INFO gillSansMTCondensed_18ptDescriptors[]; + +// Font data for Gill Sans MT Condensed 16pt +extern const uint8_t gillSansMTCondensed_16ptBitmaps[]; +extern const FONT_INFO gillSansMTCondensed_16ptFontInfo; +extern const FONT_CHAR_INFO gillSansMTCondensed_16ptDescriptors[]; + +// Font data for Digital-7 18pt +extern const uint8_t digital7_18ptBitmaps[]; +extern const FONT_INFO digital7_18ptFontInfo; +extern const FONT_CHAR_INFO digital7_18ptDescriptors[]; + +#endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index edc903b4..e42691a4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -6,7 +6,7 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -env_default = generic +;env_default = generic ;env_default = ebox ;env_default = eboxtube ;env_default = ecopower @@ -24,6 +24,7 @@ env_default = generic ;env_default = lolin32litelora ;env_default = lolin32lora ;env_default = lolin32lite +env_default = wemos32oled ;env_default = octopus32 ;env_default = ecopower, eboxtube, heltec, ttgobeam, lopy4, lopy, ttgov21old, ttgov21new, ttgofox ; @@ -31,7 +32,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.55 +release_version = 1.7.61 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 3 @@ -49,6 +50,8 @@ lib_deps_lora = https://github.com/mcci-catena/arduino-lmic.git lib_deps_display = U8g2@>=2.25.7 +lib_deps_matrix_display = + https://github.com/Seeed-Studio/Ultrathin_LED_Matrix.git lib_deps_rgbled = SmartLeds@>=1.1.5 lib_deps_gps = @@ -60,6 +63,7 @@ lib_deps_basic = ArduinoJson@^5.13.1 Timezone@^1.2.2 RTC@^2.3.0 + SimpleButton lib_deps_all = ${common.lib_deps_basic} ${common.lib_deps_lora} @@ -357,6 +361,22 @@ upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} +[env:wemos32oled] +platform = ${common.platform_espressif32} +framework = arduino +board = lolin32 +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_display} + ${common.lib_deps_matrix_display} +build_flags = + ${common.build_flags_all} +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + [env:octopus32] platform = ${common.platform_espressif32} framework = arduino diff --git a/src/TTN/plain_decoder.js b/src/TTN/plain_decoder.js index d87fcb9e..96655ee7 100644 --- a/src/TTN/plain_decoder.js +++ b/src/TTN/plain_decoder.js @@ -81,7 +81,6 @@ function Decoder(bytes, port) { decoded.time = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); decoded.timestatus = bytes[i++]; } - return decoded; } - + return decoded; } diff --git a/src/button.cpp b/src/button.cpp index 68e29d4e..ed34367f 100644 --- a/src/button.cpp +++ b/src/button.cpp @@ -3,17 +3,44 @@ #include "globals.h" #include "button.h" +using namespace simplebutton; + // Local logging tag static const char TAG[] = __FILE__; -void readButton() { - ESP_LOGI(TAG, "Button pressed"); -#ifdef HAS_DISPLAY - refreshtheDisplay(true); // switch to next display page +static Button *b = NULL; + +void button_init(int pin) { +#ifdef BUTTON_PULLDOWN + b = new Button(pin); #else - payload.reset(); - payload.addButton(0x01); - SendPayload(BUTTONPORT, prio_normal); + b = new ButtonPullup(pin); #endif + + // attach events to the button + + b->setOnDoubleClicked([]() {}); + + b->setOnClicked([]() { +#ifdef HAS_DISPLAY + refreshtheDisplay(true); // switch to next display page +#else + payload.reset(); + payload.addButton(0x01); + SendPayload(BUTTONPORT, prio_normal); +#endif + }); + + b->setOnHolding([]() { +#if (HAS_LORA) + cfg.adrmode = !cfg.adrmode; + LMIC_setAdrMode(cfg.adrmode); +#endif + }); + + // attach interrupt to the button + attachInterrupt(digitalPinToInterrupt(pin), ButtonIRQ, CHANGE); } + +void readButton() { b->update(); } #endif \ No newline at end of file diff --git a/src/hal/wemos32oled.h b/src/hal/wemos32oled.h new file mode 100644 index 00000000..d5c27832 --- /dev/null +++ b/src/hal/wemos32oled.h @@ -0,0 +1,45 @@ +// clang-format off + +#ifndef _WEMOS32OLED_H +#define _WEMOS32OLED_H + +#include + +// Hardware related definitions for TTGO T-Beam board +// (only) for older T-Beam version T22_V05 eternal wiring LORA_IO1 to GPIO33 is needed! +// +// pinouts taken from http://tinymicros.com/wiki/TTGO_T-Beam + +#define HAS_LED NOT_A_PIN // no LED + +//#define HAS_LORA 1 // comment out if device shall not send data via LoRa +//#define CFG_sx1276_radio 1 // HPD13A LoRa SoC +//#define BOARD_HAS_PSRAM // use extra 4MB external RAM +//#define HAS_BUTTON GPIO_NUM_39 // on board button (next to reset) +//#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +//#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board + +// GPS settings +//#define HAS_GPS 1 // use on board GPS +//#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M +//#define GPS_INT GPIO_NUM_34 // 30ns accurary timepulse, to be external wired on pcb: NEO 6M Pin#3 -> GPIO34 + +// enable only if device has these sensors, otherwise comment these lines +// BME680 sensor on I2C bus +//#define HAS_BME 1 // Enable BME sensors in general +//#define HAS_BME680 SDA, SCL +//#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !! + +// display (if connected) +#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +#define MY_OLED_SDA (5) +#define MY_OLED_SCL (4) +#define MY_OLED_RST U8X8_PIN_NONE +#define DISPLAY_FLIP 1 // use if display is rotated + +// user defined sensors (if connected) +//#define HAS_SENSORS 1 // comment out if device has user defined sensors + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature + +#endif diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index 97c026e0..da999da7 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -39,6 +39,12 @@ void irqHandler(void *pvParameters) { refreshtheDisplay(); #endif +// LED Matrix display needs refresh? +#ifdef HAS_MATRIX_DISPLAY + if (InterruptStatus & MATRIX_DISPLAY_IRQ) + refreshTheMatrixDisplay(); +#endif + // gps refresh buffer? #if (HAS_GPS) if (InterruptStatus & GPS_IRQ) @@ -79,6 +85,17 @@ void IRAM_ATTR DisplayIRQ() { } #endif +#ifdef HAS_MATRIX_DISPLAY +void IRAM_ATTR MatrixDisplayIRQ() { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + xTaskNotifyFromISR(irqHandlerTask, MATRIX_DISPLAY_IRQ, eSetBits, + &xHigherPriorityTaskWoken); + if (xHigherPriorityTaskWoken) + portYIELD_FROM_ISR(); +} +#endif + #ifdef HAS_BUTTON void IRAM_ATTR ButtonIRQ() { BaseType_t xHigherPriorityTaskWoken = pdFALSE; diff --git a/src/ledmatrixdisplay.cpp b/src/ledmatrixdisplay.cpp new file mode 100644 index 00000000..6a4f39d4 --- /dev/null +++ b/src/ledmatrixdisplay.cpp @@ -0,0 +1,144 @@ +#ifdef HAS_MATRIX_DISPLAY + +#include "globals.h" + +#define NUMCHARS 5 + +// local Tag for logging +static const char TAG[] = __FILE__; + +uint8_t MatrixDisplayIsOn = 0; +static unsigned long ulLastNumMacs = 0; + +LEDMatrix matrix(LED_MATRIX_LA_74138, LED_MATRIX_LB_74138, LED_MATRIX_LC_74138, + LED_MATRIX_LD_74138, LED_MATRIX_EN_74138, LED_MATRIX_DATA_R1, + LED_MATRIX_LATCHPIN, LED_MATRIX_CLOCKPIN); + +// Display Buffer 128 = 64 * 16 / 8 +uint8_t displaybuf[LED_MATRIX_WIDTH * LED_MATRIX_HEIGHT / NUMCHARS]; + +const FONT_INFO *ActiveFontInfo = &digital7_18ptFontInfo; +const uint8_t *iaActiveFont = ActiveFontInfo->Bitmap; +const FONT_CHAR_INFO *ActiveFontCharInfo = ActiveFontInfo->Descriptors; + +void init_matrix_display(const char *Productname, const char *Version) { + ESP_LOGI(TAG, "Initializing LED Matrix display"); + matrix.begin(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT); + matrix.reverse(); + matrix.clear(); + DrawNumber(String("0")); +} // init_display + +void refreshTheMatrixDisplay() { + + // if Matrixdisplay is switched off we don't refresh it to relax cpu + if (!MatrixDisplayIsOn && (MatrixDisplayIsOn == cfg.screenon)) + return; + + // set display on/off according to current device configuration + if (MatrixDisplayIsOn != cfg.screenon) { + MatrixDisplayIsOn = cfg.screenon; + } + + if (ulLastNumMacs != macs.size()) { + ulLastNumMacs = macs.size(); + matrix.clear(); + DrawNumber(String(macs.size())); + ESP_LOGI(TAG, "Setting display to counter: %lu", macs.size()); + } + + matrix.scan(); +} + +// (x, y) top-left position, x should be multiple of 8 +void DrawChar(uint16_t x, uint16_t y, char cChar) { + // Get address of char in font char descriptor from font descriptor + auto CharDescAddress = (cChar - ActiveFontInfo->StartChar); + + // Get offset of char into font bitmap + uint16_t FontBitmapOffset = ActiveFontCharInfo[CharDescAddress].offset; + // Serial.printf("Address of %c is %i, bitmap offset is %u\r\n", cChar, + // CharDescAddress, FontBitmapOffset); + + // Check font height, if it's less than matrix height we need to + // add some empty lines to font does not stick to the top + if (ActiveFontInfo->CharHeight < (LED_MATRIX_HEIGHT - y)) { + uint8_t FillerLines = (LED_MATRIX_HEIGHT - y) - ActiveFontInfo->CharHeight; + if (FillerLines % 2 == 0) { + // Use floor (round down) to get heighest possible divider + // for missing lines + y = floor(FillerLines / 2); + } + } + + int iDst = (x / 8) + (y * 8); + int Shift = x % 8; + // Serial.printf("Got hex '%x'\r\n", pSrc); + for (uint8_t i = 0; i < ActiveFontCharInfo[CharDescAddress].height; i++) { + int iDigitA = iaActiveFont[FontBitmapOffset]; + + int Left = iDigitA >> Shift; + int Right = iDigitA << (8 - Shift); + + displaybuf[iDst] |= Left; + displaybuf[iDst + 1] |= Right; + + if (ActiveFontCharInfo[CharDescAddress].width > 8) { + int iDigitB = iaActiveFont[FontBitmapOffset + 1]; + Left = iDigitB >> Shift; + Right = iDigitB << (8 - Shift); + + displaybuf[iDst + 1] |= Left; + displaybuf[iDst + 2] |= Right; + FontBitmapOffset++; + } + + FontBitmapOffset++; + iDst += 8; + } +} + +void DrawNumber(String strNum, uint8_t iDotPos) { + uint8_t iNumLength = strNum.length(); + uint8_t iDigitPos = 0; + + // Serial.printf("Showing number '%s' (length: %i)\r\n", strNum.c_str(), + // iNumLength); + for (int i = 0; i < iNumLength; i++) { + // Serial.printf("Showing char '%c' at x:%i y:%i\r\n", + // strNum.charAt(i), + // iDigitPos, 0); + DrawChar(iDigitPos, 0, strNum.charAt(i)); + if (i + 1 == iDotPos) { + // matrix.drawRect((iDigitPos * 8) - 1, 15, iDigitPos * 8, + // 16, 1); + iDigitPos = iDigitPos + GetCharWidth(strNum.charAt(i)) + + ActiveFontInfo->SpaceWidth; + DrawChar(iDigitPos, 0, '.'); + iDigitPos = iDigitPos + GetCharWidth('.') + ActiveFontInfo->SpaceWidth; + } else { + iDigitPos = iDigitPos + GetCharWidth(strNum.charAt(i)) + + ActiveFontInfo->SpaceWidth; + } + } +} + +uint8_t GetCharFromFont(char cChar) { + auto cStartChar = ActiveFontInfo->StartChar; + auto iCharLocation = cChar - cStartChar; + auto iCharBitmap = iaActiveFont[iCharLocation]; + + return iCharBitmap; +} + +uint8_t GetCharWidth(char cChar) { + // Get address of char in font char descriptor from font descriptor + auto CharDescAddress = (cChar - ActiveFontInfo->StartChar); + + // Get offset of char into font bitmap + auto CharDescriptor = ActiveFontCharInfo[CharDescAddress]; + // Serial.printf("Char %c is %i wide\r\n", cChar, CharDescriptor.width); + return CharDescriptor.width; +} + +#endif // HAS_MATRIX_DISPLAY \ No newline at end of file diff --git a/src/ledmatrixfonts.cpp b/src/ledmatrixfonts.cpp new file mode 100644 index 00000000..1dfa2158 --- /dev/null +++ b/src/ledmatrixfonts.cpp @@ -0,0 +1,903 @@ +#include "ledmatrixfonts.h" +#include "Arduino.h" +// +// Font data for Arial Narrow 17pt +// + +// Character bitmaps for Arial Narrow 17pt +const uint8_t arialNarrow_17ptBitmaps[] = { + // @0 '-' (10 pixels wide) + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00111110, 0b00000000, // ##### + 0b00111110, 0b00000000, // ##### + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + 0b00000000, 0b00000000, // + + // @32 '0' (10 pixels wide) + 0b00011110, 0b00000000, // #### + 0b00111111, 0b00000000, // ###### + 0b00110011, 0b00000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b00110011, 0b00000000, // ## ## + 0b00111111, 0b00000000, // ###### + 0b00011110, 0b00000000, // #### + + // @64 '1' (10 pixels wide) + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00001110, 0b00000000, // ### + 0b00011110, 0b00000000, // #### + 0b00110110, 0b00000000, // ## ## + 0b00100110, 0b00000000, // # ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + + // @96 '2' (10 pixels wide) + 0b00011110, 0b00000000, // #### + 0b00111111, 0b00000000, // ###### + 0b00110011, 0b10000000, // ## ### + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b00000001, 0b10000000, // ## + 0b00000001, 0b10000000, // ## + 0b00000011, 0b00000000, // ## + 0b00000111, 0b00000000, // ### + 0b00001110, 0b00000000, // ### + 0b00001100, 0b00000000, // ## + 0b00011000, 0b00000000, // ## + 0b00110000, 0b00000000, // ## + 0b00100000, 0b00000000, // # + 0b01111111, 0b10000000, // ######## + 0b01111111, 0b10000000, // ######## + + // @128 '3' (10 pixels wide) + 0b00011110, 0b00000000, // #### + 0b00111111, 0b00000000, // ###### + 0b01110011, 0b10000000, // ### ### + 0b01100001, 0b10000000, // ## ## + 0b00000001, 0b10000000, // ## + 0b00000011, 0b10000000, // ### + 0b00001111, 0b00000000, // #### + 0b00001110, 0b00000000, // ### + 0b00000011, 0b00000000, // ## + 0b00000001, 0b10000000, // ## + 0b00000001, 0b10000000, // ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b00110011, 0b10000000, // ## ### + 0b00111111, 0b00000000, // ###### + 0b00011110, 0b00000000, // #### + + // @160 '4' (10 pixels wide) + 0b00000111, 0b00000000, // ### + 0b00000111, 0b00000000, // ### + 0b00001111, 0b00000000, // #### + 0b00001111, 0b00000000, // #### + 0b00011011, 0b00000000, // ## ## + 0b00011011, 0b00000000, // ## ## + 0b00110011, 0b00000000, // ## ## + 0b01100011, 0b00000000, // ## ## + 0b01100011, 0b00000000, // ## ## + 0b11000011, 0b00000000, // ## ## + 0b11111111, 0b11000000, // ########## + 0b11111111, 0b11000000, // ########## + 0b00000011, 0b00000000, // ## + 0b00000011, 0b00000000, // ## + 0b00000011, 0b00000000, // ## + 0b00000011, 0b00000000, // ## + + // @192 '5' (10 pixels wide) + 0b00111111, 0b00000000, // ###### + 0b00111111, 0b00000000, // ###### + 0b00110000, 0b00000000, // ## + 0b00110000, 0b00000000, // ## + 0b01100000, 0b00000000, // ## + 0b01101110, 0b00000000, // ## ### + 0b01111111, 0b00000000, // ####### + 0b01110011, 0b10000000, // ### ### + 0b00000001, 0b10000000, // ## + 0b00000001, 0b10000000, // ## + 0b00000001, 0b10000000, // ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b00110011, 0b00000000, // ## ## + 0b00111111, 0b00000000, // ###### + 0b00011110, 0b00000000, // #### + + // @224 '6' (10 pixels wide) + 0b00001110, 0b00000000, // ### + 0b00011111, 0b00000000, // ##### + 0b00110011, 0b10000000, // ## ### + 0b00100001, 0b10000000, // # ## + 0b01100000, 0b00000000, // ## + 0b01101110, 0b00000000, // ## ### + 0b01111111, 0b00000000, // ####### + 0b01110011, 0b10000000, // ### ### + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b00110011, 0b00000000, // ## ## + 0b00111111, 0b00000000, // ###### + 0b00011110, 0b00000000, // #### + + // @256 '7' (10 pixels wide) + 0b01111111, 0b10000000, // ######## + 0b01111111, 0b10000000, // ######## + 0b00000001, 0b00000000, // # + 0b00000011, 0b00000000, // ## + 0b00000011, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000110, 0b00000000, // ## + 0b00000100, 0b00000000, // # + 0b00001100, 0b00000000, // ## + 0b00001100, 0b00000000, // ## + 0b00001100, 0b00000000, // ## + 0b00001100, 0b00000000, // ## + 0b00011000, 0b00000000, // ## + 0b00011000, 0b00000000, // ## + 0b00011000, 0b00000000, // ## + 0b00011000, 0b00000000, // ## + + // @288 '8' (10 pixels wide) + 0b00011110, 0b00000000, // #### + 0b00111111, 0b00000000, // ###### + 0b01110011, 0b10000000, // ### ### + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01110011, 0b10000000, // ### ### + 0b00111111, 0b00000000, // ###### + 0b00111111, 0b00000000, // ###### + 0b00110011, 0b00000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01110011, 0b10000000, // ### ### + 0b00111111, 0b00000000, // ###### + 0b00011110, 0b00000000, // #### + + // @320 '9' (10 pixels wide) + 0b00011110, 0b00000000, // #### + 0b00111111, 0b00000000, // ###### + 0b00110011, 0b00000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01100001, 0b10000000, // ## ## + 0b01110011, 0b10000000, // ### ### + 0b00111111, 0b10000000, // ####### + 0b00011101, 0b10000000, // ### ## + 0b00000001, 0b10000000, // ## + 0b01100001, 0b00000000, // ## # + 0b01110011, 0b00000000, // ### ## + 0b00111110, 0b00000000, // ##### + 0b00011100, 0b00000000, // ### +}; + +// +// Font data for Gill Sans MT Condensed 18pt +// + +// Character bitmaps for Gill Sans MT Condensed 18pt +const uint8_t gillSansMTCondensed_18ptBitmaps[] = { + // @0 '-' (8 pixels wide) + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b01111100, // ##### + 0b01111100, // ##### + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + + // @16 '0' (8 pixels wide) + 0b00111100, // #### + 0b01111110, // ###### + 0b01111110, // ###### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b01111110, // ###### + 0b01111110, // ###### + 0b00111100, // #### + + // @32 '1' (8 pixels wide) + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + + // @48 '2' (8 pixels wide) + 0b11111100, // ###### + 0b11111110, // ####### + 0b11001111, // ## #### + 0b00000111, // ### + 0b00000111, // ### + 0b00000111, // ### + 0b00000111, // ### + 0b00000110, // ## + 0b00001110, // ### + 0b00001110, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b01110000, // ### + 0b01111111, // ####### + 0b11111111, // ######## + + // @64 '3' (8 pixels wide) + 0b11111000, // ##### + 0b11111100, // ###### + 0b00011110, // #### + 0b00001110, // ### + 0b00001110, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00011100, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b11011110, // ## #### + 0b11111100, // ###### + 0b11111000, // ##### + + // @80 '4' (8 pixels wide) + 0b00001110, // ### + 0b00001110, // ### + 0b00011110, // #### + 0b00011110, // #### + 0b00111110, // ##### + 0b00111110, // ##### + 0b00111110, // ##### + 0b01101110, // ## ### + 0b01101110, // ## ### + 0b11001110, // ## ### + 0b11001110, // ## ### + 0b11111111, // ######## + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + + // @96 '5' (8 pixels wide) + 0b01111110, // ###### + 0b01111110, // ###### + 0b01110000, // ### + 0b01110000, // ### + 0b01110000, // ### + 0b01110000, // ### + 0b01111000, // #### + 0b01111100, // ##### + 0b00011110, // #### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00011100, // ### + 0b11111100, // ###### + 0b11111000, // ##### + + // @112 '6' (8 pixels wide) + 0b00001110, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b01110000, // ### + 0b01111100, // ##### + 0b11111110, // ####### + 0b11110111, // #### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11111111, // ######## + 0b01111110, // ###### + 0b00111100, // #### + + // @128 '7' (8 pixels wide) + 0b11111111, // ######## + 0b11111111, // ######## + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00110000, // ## + 0b01110000, // ### + 0b01110000, // ### + + // @144 '8' (8 pixels wide) + 0b00111100, // #### + 0b01111110, // ###### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b01111110, // ###### + 0b01111110, // ###### + 0b01111110, // ###### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11111111, // ######## + 0b01111110, // ###### + 0b00111100, // #### + + // @160 '9' (8 pixels wide) + 0b00111100, // #### + 0b01111110, // ###### + 0b11111111, // ######## + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11100111, // ### ### + 0b11101111, // ### #### + 0b01111111, // ####### + 0b00111110, // ##### + 0b00001110, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b01110000, // ### +}; + +// Character descriptors for Gill Sans MT Condensed 18pt +// { [Char width in bits], [Char height in bits], [Offset into +// gillSansMTCondensed_18ptCharBitmaps in bytes] } +const FONT_CHAR_INFO gillSansMTCondensed_18ptDescriptors[] = { + {8, 16, 0}, // - + {0, 0, 0}, // . + {0, 0, 0}, // / + {8, 16, 16}, // 0 + {8, 16, 32}, // 1 + {8, 16, 48}, // 2 + {8, 16, 64}, // 3 + {8, 16, 80}, // 4 + {8, 16, 96}, // 5 + {8, 16, 112}, // 6 + {8, 16, 128}, // 7 + {8, 16, 144}, // 8 + {8, 16, 160}, // 9 +}; + +// Font information for Gill Sans MT Condensed 18pt +const FONT_INFO gillSansMTCondensed_18ptFontInfo = { + 2, // Character height + '-', // Start character + '9', // End character + 2, // Width, in pixels, of space character + gillSansMTCondensed_18ptDescriptors, + gillSansMTCondensed_18ptBitmaps}; + +// +// Font data for Gill Sans MT Condensed 16pt +// + +// Character bitmaps for Gill Sans MT Condensed 16pt +const uint8_t gillSansMTCondensed_16ptBitmaps[] = { + // @0 '-' (7 pixels wide) + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00111110, // ##### + 0b00111110, // ##### + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + + // @14 '0' (7 pixels wide) + 0b00111000, // ### + 0b01111100, // ##### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b01111100, // ##### + 0b00111000, // ### + + // @28 '1' (7 pixels wide) + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + + // @42 '2' (7 pixels wide) + 0b11111000, // ##### + 0b11111100, // ###### + 0b00011110, // #### + 0b00001110, // ### + 0b00001110, // ### + 0b00001110, // ### + 0b00001100, // ## + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b01110000, // ### + 0b01111110, // ###### + 0b11111110, // ####### + + // @56 '3' (7 pixels wide) + 0b11110000, // #### + 0b11111000, // ##### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b11111000, // ##### + 0b11110000, // #### + + // @70 '4' (7 pixels wide) + 0b00011100, // ### + 0b00011100, // ### + 0b00111100, // #### + 0b00111100, // #### + 0b01111100, // ##### + 0b01111100, // ##### + 0b01111100, // ##### + 0b11011100, // ## ### + 0b11011100, // ## ### + 0b11111110, // ####### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + + // @84 '5' (7 pixels wide) + 0b01111110, // ###### + 0b01111110, // ###### + 0b01110000, // ### + 0b01110000, // ### + 0b01110000, // ### + 0b01110000, // ### + 0b01111100, // ##### + 0b01111100, // ##### + 0b00011110, // #### + 0b00001110, // ### + 0b00001110, // ### + 0b00011110, // #### + 0b11111100, // ###### + 0b11111000, // ##### + + // @98 '6' (7 pixels wide) + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b01110000, // ### + 0b01110000, // ### + 0b01111100, // ##### + 0b11111100, // ###### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b01111100, // ##### + 0b01111000, // #### + + // @112 '7' (7 pixels wide) + 0b11111110, // ####### + 0b11111110, // ####### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b01110000, // ### + 0b01110000, // ### + 0b01110000, // ### + + // @126 '8' (7 pixels wide) + 0b01111100, // ##### + 0b01111100, // ##### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b01111100, // ##### + 0b01111100, // ##### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b01111100, // ##### + 0b01111100, // ##### + + // @140 '9' (7 pixels wide) + 0b00111100, // #### + 0b01111100, // ##### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b11101110, // ### ### + 0b01111110, // ###### + 0b01111100, // ##### + 0b00011100, // ### + 0b00011100, // ### + 0b00111000, // ### + 0b00111000, // ### + 0b01110000, // ### +}; + +// Character descriptors for Gill Sans MT Condensed 16pt +// { [Char width in bits], [Char height in bits], [Offset into +// gillSansMTCondensed_16ptCharBitmaps in bytes] } +const FONT_CHAR_INFO gillSansMTCondensed_16ptDescriptors[] = { + {7, 14, 0}, // - + {0, 0, 0}, // . + {0, 0, 0}, // / + {7, 14, 14}, // 0 + {7, 14, 28}, // 1 + {7, 14, 42}, // 2 + {7, 14, 56}, // 3 + {7, 14, 70}, // 4 + {7, 14, 84}, // 5 + {7, 14, 98}, // 6 + {7, 14, 112}, // 7 + {7, 14, 126}, // 8 + {7, 14, 140}, // 9 +}; + +// Font information for Gill Sans MT Condensed 16pt +const FONT_INFO gillSansMTCondensed_16ptFontInfo = { + 2, // Character height + '-', // Start character + '9', // End character + 2, // Width, in pixels, of space character + gillSansMTCondensed_16ptDescriptors, // Character descriptor array + gillSansMTCondensed_16ptBitmaps, // Character bitmap array +}; + +// +// Font data for Digital-7 18pt +// + +// Character bitmaps for Digital-7 18pt +const uint8_t digital7_18ptBitmaps[] = { + // @0 '-' (7 pixels wide) + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b11111110, // ####### + 0b11111110, // ####### + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + + // @16 '.' (3 pixels wide) + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b00000000, // + 0b11100000, // ### + 0b11100000, // ### + + // @32 '0' (11 pixels wide) + 0b00111111, 0b10000000, // ####### + 0b01111111, 0b11000000, // ######### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11000000, 0b01100000, // ## ## + 0b11000000, 0b01100000, // ## ## + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b01111111, 0b11000000, // ######### + 0b00111111, 0b10000000, // ####### + + // @64 '1' (3 pixels wide) + 0b01100000, // ## + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b01100000, // ## + 0b01100000, // ## + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b11100000, // ### + 0b01100000, // ## + + // @80 '2' (11 pixels wide) + 0b11111111, 0b10000000, // ######### + 0b01111111, 0b11000000, // ######### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b01111111, 0b11100000, // ########## + 0b11111111, 0b11000000, // ########## + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b01111111, 0b11000000, // ######### + 0b00111111, 0b11100000, // ######### + + // @112 '3' (10 pixels wide) + 0b11111111, 0b00000000, // ######## + 0b11111111, 0b11000000, // ########## + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b01111111, 0b11000000, // ######### + 0b01111111, 0b11000000, // ######### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b00000001, 0b11000000, // ### + 0b11111111, 0b11000000, // ########## + 0b11111111, 0b00000000, // ######## + + // @144 '4' (11 pixels wide) + 0b11000000, 0b01100000, // ## ## + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11111111, 0b11100000, // ########### + 0b01111111, 0b11100000, // ########## + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b01100000, // ## + + // @176 '5' (11 pixels wide) + 0b00111111, 0b11000000, // ######## + 0b01111111, 0b10000000, // ######## + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11111111, 0b10000000, // ######### + 0b01111111, 0b11100000, // ########## + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b01111111, 0b11000000, // ######### + 0b11111111, 0b10000000, // ######### + + // @208 '6' (11 pixels wide) + 0b00111111, 0b11000000, // ######## + 0b01111111, 0b10000000, // ######## + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11100000, 0b00000000, // ### + 0b11111111, 0b10000000, // ######### + 0b11111111, 0b11100000, // ########### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11111111, 0b11100000, // ########### + 0b01111111, 0b10000000, // ######## + + // @240 '7' (11 pixels wide) + 0b00111111, 0b10000000, // ####### + 0b01111111, 0b11100000, // ########## + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11000000, 0b01100000, // ## ## + 0b00000000, 0b01100000, // ## + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b01100000, // ## + + // @272 '8' (11 pixels wide) + 0b00111111, 0b10000000, // ####### + 0b01111111, 0b11000000, // ######### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11111111, 0b11100000, // ########### + 0b11111111, 0b11100000, // ########### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b01111111, 0b11000000, // ######### + 0b00111111, 0b10000000, // ####### + + // @304 '9' (11 pixels wide) + 0b00111111, 0b11000000, // ######## + 0b01111111, 0b11100000, // ########## + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11100000, 0b11100000, // ### ### + 0b11111111, 0b11100000, // ########### + 0b01111111, 0b11100000, // ########## + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b00000000, 0b11100000, // ### + 0b01111111, 0b11000000, // ######### + 0b11111111, 0b10000000, // ######### +}; + +// Character descriptors for Digital-7 18pt +// { [Char width in bits], [Char height in bits], [Offset into +// digital7_18ptCharBitmaps in bytes] } +const FONT_CHAR_INFO digital7_18ptDescriptors[] = { + {7, 16, 0}, // - + {3, 16, 16}, // . + {0, 0, 0}, // / + {11, 16, 32}, // 0 + {3, 16, 64}, // 1 + {11, 16, 80}, // 2 + {10, 16, 112}, // 3 + {11, 16, 144}, // 4 + {11, 16, 176}, // 5 + {11, 16, 208}, // 6 + {11, 16, 240}, // 7 + {11, 16, 272}, // 8 + {11, 16, 304}, // 9 +}; + +// Font information for Digital-7 18pt +const FONT_INFO digital7_18ptFontInfo = { + 16, // Character height + '-', // Start character + '9', // End character + 2, // Width, in pixels, of space character + digital7_18ptDescriptors, // Character descriptor array + digital7_18ptBitmaps, // Character bitmap array +}; diff --git a/src/main.cpp b/src/main.cpp index 96198e4a..a26379fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,7 +52,7 @@ So don't do it if you do not own a digital oscilloscope. 0 displayIRQ -> display refresh -> 40ms (DISPLAYREFRESH_MS) 1 ppsIRQ -> pps clock irq -> 1sec 2 gpsIRQ -> gps store data -> 300ms -3 unused +3 MatrixDisplayIRQ -> matrix mux cycle -> 0,5ms (MATRIX_DISPLAY_SCAN_US) // Interrupt routines @@ -85,7 +85,8 @@ uint8_t volatile channel = 0; // channel rotation counter uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0, batt_voltage = 0; // globals for display -hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *gpsIRQ = NULL; +hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL, *matrixDisplayIRQ = NULL, + *gpsIRQ = NULL; TaskHandle_t irqHandlerTask = NULL, ClockTask = NULL; SemaphoreHandle_t I2Caccess; @@ -265,20 +266,6 @@ void setup() { esp_coex_prefer_t)ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib #endif -// initialize button -#ifdef HAS_BUTTON - strcat_P(features, " BTN_"); -#ifdef BUTTON_PULLUP - strcat_P(features, "PU"); - // install button interrupt (pullup mode) - pinMode(HAS_BUTTON, INPUT_PULLUP); -#else - strcat_P(features, "PD"); - // install button interrupt (pulldown mode) - pinMode(HAS_BUTTON, INPUT_PULLDOWN); -#endif // BUTTON_PULLUP -#endif // HAS_BUTTON - // initialize gps #if (HAS_GPS) strcat_P(features, " GPS"); @@ -323,6 +310,13 @@ void setup() { init_display(PRODUCTNAME, PROGVERSION); // note: blocking call #endif +// initialize matrix display +#ifdef HAS_MATRIX_DISPLAY + strcat_P(features, " LED_MATRIX"); + MatrixDisplayIsOn = cfg.screenon; + init_matrix_display(PRODUCTNAME, PROGVERSION); // note: blocking call +#endif + // show payload encoder #if PAYLOAD_ENCODER == 1 strcat_P(features, " PLAIN"); @@ -364,9 +358,6 @@ void setup() { esp_wifi_deinit(); #endif - // show compiled features - ESP_LOGI(TAG, "Features:%s", features); - // start state machine ESP_LOGI(TAG, "Starting Interrupt Handler..."); xTaskCreatePinnedToCore(irqHandler, // task function @@ -410,7 +401,28 @@ void setup() { timerAlarmEnable(displayIRQ); #endif - // gps buffer read interrupt + // LED Matrix display interrupt +#ifdef HAS_MATRIX_DISPLAY + // https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/ + // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 3, count up + matrixDisplayIRQ = timerBegin(3, 80, true); + timerAttachInterrupt(matrixDisplayIRQ, &MatrixDisplayIRQ, true); + timerAlarmWrite(matrixDisplayIRQ, MATRIX_DISPLAY_SCAN_US, true); + timerAlarmEnable(matrixDisplayIRQ); +#endif + + // initialize button +#ifdef HAS_BUTTON + strcat_P(features, " BTN_"); +#ifdef BUTTON_PULLUP + strcat_P(features, "PU"); +#else + strcat_P(features, "PD"); +#endif // BUTTON_PULLUP + button_init(HAS_BUTTON); +#endif // HAS_BUTTON + + // gps buffer read interrupt #if (HAS_GPS) gpsIRQ = timerBegin(2, 80, true); timerAttachInterrupt(gpsIRQ, &GpsIRQ, true); @@ -422,15 +434,6 @@ void setup() { sendcycler.attach(SENDCYCLE * 2, sendcycle); housekeeper.attach(HOMECYCLE, housekeeping); -// button interrupt -#ifdef HAS_BUTTON -#ifdef BUTTON_PULLUP - attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING); -#else - attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING); -#endif -#endif // HAS_BUTTON - #if (TIME_SYNC_INTERVAL) #if (!(TIME_SYNC_LORAWAN) && !(TIME_SYNC_LORASERVER) && !defined HAS_GPS && \ @@ -453,6 +456,9 @@ void setup() { #endif // TIME_SYNC_INTERVAL + // show compiled features + ESP_LOGI(TAG, "Features:%s", features); + } // setup() void loop() { diff --git a/src/paxcounter.conf b/src/paxcounter.conf index f042d2cf..f4ec3bfb 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -110,3 +110,18 @@ // LMIC settings // -> in src/lmic_config.h + +// LED Matrix display settings. Pin numbers work fine for Wemos Lolin32 board (all used pins are on 1 side of the board) +// Note: LED Matrix will only show number of found devices, no other information will be shown for now +//#define HAS_MATRIX_DISPLAY 1 // Uncomment to enable LED matrix display output +#define MATRIX_DISPLAY_SCAN_US 500 // Matrix display scan rate in microseconds (1ms is about 'acceptable') +#define LED_MATRIX_LATCHPIN 13 // Connects to LAT pin on display +#define LED_MATRIX_CLOCKPIN 32 // Connects to CLK pin on display +#define LED_MATRIX_EN_74138 12 // Connects to OE pin on display +#define LED_MATRIX_LA_74138 14 // Connects to LA pin on display +#define LED_MATRIX_LB_74138 27 // Connects to LB pin on display +#define LED_MATRIX_LC_74138 25 // Connects to LC pin on display +#define LED_MATRIX_LD_74138 26 // Connects to LD pin on display +#define LED_MATRIX_DATA_R1 33 // Connects to R1 pin on display +#define LED_MATRIX_WIDTH 64 // Width in pixels (LEDs) of your display +#define LED_MATRIX_HEIGHT 16 // Height in pixels (LEDs ) of your display \ No newline at end of file