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..e00d4d12 100644 --- a/include/irqhandler.h +++ b/include/irqhandler.h @@ -3,6 +3,7 @@ #define DISPLAY_IRQ 0x01 #define BUTTON_IRQ 0x02 +#define MATRIX_DISPLAY_IRQ 0x03 #define SENDCYCLE_IRQ 0x04 #define CYCLIC_IRQ 0x08 #define TIMESYNC_IRQ 0x10 @@ -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..227f300d --- /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; + +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 0cd36d90..511be877 100644 --- a/platformio.ini +++ b/platformio.ini @@ -49,6 +49,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 = @@ -66,6 +68,7 @@ lib_deps_all = ${common.lib_deps_display} ${common.lib_deps_rgbled} ${common.lib_deps_gps} + ${common.lib_deps_matrix_display} build_flags_basic = -include "src/hal/${PIOENV}.h" -include "src/paxcounter.conf" 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..5c211b40 --- /dev/null +++ b/src/ledmatrixdisplay.cpp @@ -0,0 +1,135 @@ +#ifdef HAS_MATRIX_DISPLAY + +#include "globals.h" + +#define NUMCHARS 5 + +// local Tag for logging +static const char TAG[] = __FILE__; + +uint8_t MatrixDisplayIsOn = 0; +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 (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..50ecac69 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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; @@ -323,6 +324,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"); @@ -410,7 +418,17 @@ 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 + + // gps buffer read interrupt #if (HAS_GPS) gpsIRQ = timerBegin(2, 80, true); timerAttachInterrupt(gpsIRQ, &GpsIRQ, true); 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