diff --git a/Images.md b/Images.md
index 36c634f..5213c3a 100644
--- a/Images.md
+++ b/Images.md
@@ -57,4 +57,6 @@
\
\
\
-
+\
+\
+
diff --git a/README.md b/README.md
index ff2d72d..6a363cf 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,8 @@ https://aliexpress.com/item/32965676064.html
- or **LCD1602** 16x2 I2C https://aliexpress.com/item/32305776560.html
- or **LCD1602** 16x2 without I2C https://aliexpress.com/item/32305776560.html
- or **SSD1327** 1.5' 128x128 I2C https://aliexpress.com/item/1005001414175498.html
-- or **ILI9341** 3.2'320x240 SPI https://aliexpress.com/item/33048191074.html
+- or **ILI9341** 3.2' 320x240 SPI https://aliexpress.com/item/33048191074.html
+- or **ILI9341** 2.8' 320x240 SPI https://aliexpress.com/item/1005004502250619.html
- or **SSD1305 (SSD1309)** 2.4' 128x64 SPI/I2C https://aliexpress.com/item/32950307344.html
- or **SH1107** 0.96' 128x64 I2C https://aliexpress.com/item/4000551696674.html
- or **GC9106** 0.96' 160x80 SPI (looks like ST7735S, but it's not him) https://aliexpress.com/item/32947890530.html
@@ -53,6 +54,7 @@ https://aliexpress.com/item/32965676064.html
- or **LCD2004** 20x4 without I2C https://aliexpress.com/item/32783128355.html
- or **ILI9225** 2.0' 220x176 SPI https://aliexpress.com/item/32952021835.html
- or **Nextion displays** - [more info](https://github.com/e2002/yoradio/tree/main/nextion)
+- or **ST7796** 3.5' 480x320 SPI https://aliexpress.com/item/1005004632953455.html?sku_id=12000029911293172
##### Controls
- Three tact buttons https://www.aliexpress.com/item/32907144687.html
@@ -299,6 +301,16 @@ Work is in progress...
---
## Version history
+#### v0.8.03b
+- added support for ST7796 display
+- added support for capacitive touch GT911
+- HSPI bus support added - DSP_HSPI, VS_HSPI, TS_HSPI options More details in examples/myoptions.h
+- changed the method of connecting the touchscreen in myoptions.h Now instead of specifying TS_CS, you must specify TS_MODEL (by default TS_MODEL_UNDEFINED) More details in examples/myoptions.h
+- new parameters TS_SDA, TS_SCL, TS_INT, TS_RST for GT911 touchscreen
+- new parameters LIGHT_SENSOR and AUTOBACKLIGHT - to automatically adjust the brightness of the display. More details in examples/myoptions.h
+- new parameter LED_INVERT (true/false) - to invert the behavior of the built-in LED
+- fixed bug with extra sign } in humidity value
+
#### v0.8.02b
- fixed artifacts when displaying the volume level
- changes in mytheme.h . Added colors COLOR_PL_CURRENT, COLOR_PL_CURRENT_BG, COLOR_PL_CURRENT_FILL. Details in [exsamples/mytheme.h](exsamples/mytheme.h)
diff --git a/exsamples/myoptions.h b/exsamples/myoptions.h
index 7b14a93..36eee34 100644
--- a/exsamples/myoptions.h
+++ b/exsamples/myoptions.h
@@ -10,6 +10,7 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
********************************************************/
#define LED_BUILTIN 2 /* Onboard LED Pin */
+//#define LED_INVERT false /* Invert Onboard LED? */
#define L10N_LANGUAGE EN /* Language (EN, RU). More info in yoRadio/locale/displayL10n_(en|ru).h
/* DSP_MODEL. See description/available values in https://github.com/e2002/yoradio/wiki/Available-display-models */
@@ -25,11 +26,14 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
*/
/******************************************/
-/* SPI PINS. SCL(SCK, CLK) must be connected to pin 18
- SDA(MOSI, DIN, SDI) must be connected to pin 23 */
+/* VSPI PINS. SCL(SCK, CLK) must be connected to pin 18
+ SDA(MOSI, DIN, SDI) must be connected to pin 23 */
//#define TFT_CS 5 /* SPI CS pin */
//#define TFT_RST 15 /* SPI RST pin. set to -1 and connect to Esp EN pin */
//#define TFT_DC 4 /* SPI DC/RS pin */
+/* HSPI PINS. SCL(SCK, CLK) must be connected to pin 14
+ SDA(MOSI, DIN, SDI) must be connected to pin 13 */
+//#define DSP_HSPI false /* Use HSPI for display */
/******************************************/
/* NEXTION */
@@ -47,13 +51,17 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
//#define I2S_LRC 25 /* WSEL Left Right Clock */
/******************************************/
-/* VS1053 PINS. VS1053 SCK must be connected to pin 18
- VS1053 MISO must be connected to pin 19
- VS1053 MOSI must be connected to pin 23 */
+/* VS1053 VSPI PINS. VS1053 SCK must be connected to pin 18
+ VS1053 MISO must be connected to pin 19
+ VS1053 MOSI must be connected to pin 23 */
//#define VS1053_CS 255 /* XCS pin. Should be set to 255 if the board is not used */
//#define VS1053_DCS 25 /* XDCS pin. */
//#define VS1053_DREQ 26 /* DREQ pin. */
//#define VS1053_RST -1 /* XRESET pin. Set to -1 if connected to Esp EN pin */
+/* VS1053 HSPI PINS. VS1053 SCK must be connected to pin 14
+ VS1053 MISO must be connected to pin 12
+ VS1053 MOSI must be connected to pin 13 */
+//#define VS_HSPI false /* Use HSPI for VS */
/******************************************/
/* ENCODER */
@@ -94,11 +102,25 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
/******************************************/
/* TOUCHSCREEN */
-/* SPI PINS. CLK must be connected to pin 18
- DIN must be connected to pin 23
- DO must be connected to pin 19
- IRQ - not connected */
-//#define TS_CS 255 /* Touch screen CS pin
+//#define TS_MODEL TS_MODEL_UNDEFINED /* See description/available values in yoRadio/src/core/options.h */
+
+/* Resistive SPI touch screen */
+/* TS VSPI PINS. CLK must be connected to pin 18
+ DIN must be connected to pin 23
+ DO must be connected to pin 19
+ IRQ - not connected */
+//#define TS_CS 255 /* Touch screen CS pin */
+/* TS HSPI PINS. CLK must be connected to pin 14
+ DIN must be connected to pin 13
+ DO must be connected to pin 12
+ IRQ - not connected */
+//#define TS_HSPI false /* Use HSPI for Touch screen */
+
+/* Capacitive I2C touch screen */
+//#define TS_SDA 33
+//#define TS_SCL 32
+//#define TS_INT 21
+//#define TS_RST 25
/******************************************/
/* Other settings. */
@@ -118,12 +140,9 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
//#define ROTATE_90 false /* Optional 90 degree rotation for square displays */
//#define WAKE_PIN 255 /* Wake Pin (for manual wakeup from sleep mode. can match with BTN_XXXX, ENC_BTNB, ENC2_BTNB. must be one of: 0,2,4,12,13,14,15,25,26,27,32,33,34,35,36,39) */
/* For sample #define ENC_BTNB 36 - next line - #define WAKE_PIN ENC_BTNB */
-/* VU settings. See the default settings for your display in file yoRadio/display_vu.h */
-/************************************************************************************************************************************************************************************/
-/* vu left | vu top | band width | band height | band space | num of bands | fade speed | horisontal | Max Bands Color | Min Bands Color */
-/************************************************************************************************************************************************************************************/
-//#define VU_PARAMS2 { VU_X = 4, VU_Y = 60, VU_BW = 10, VU_BH = 34, VU_BS = 2, VU_NB = 8, VU_FS = 2, VU_HOR = 0, VU_COLOR_MAX = TFT_LOGO, VU_COLOR_MIN = SILVER }
-/************************************************************************************************************************************************************************************/
+//#define LIGHT_SENSOR 255 /* Light sensor */
+//#define AUTOBACKLIGHT(x) *function* /* Autobacklight function. See options.h for exsample */
+/******************************************/
/* IR control */
//#define IR_PIN 255
diff --git a/images/img29.jpg b/images/img29.jpg
new file mode 100644
index 0000000..be19392
Binary files /dev/null and b/images/img29.jpg differ
diff --git a/yoRadio/src/Adafruit_ST7796S/Adafruit_ST7796S_kbv.cpp b/yoRadio/src/Adafruit_ST7796S/Adafruit_ST7796S_kbv.cpp
new file mode 100644
index 0000000..536884a
--- /dev/null
+++ b/yoRadio/src/Adafruit_ST7796S/Adafruit_ST7796S_kbv.cpp
@@ -0,0 +1,341 @@
+#include "../core/options.h"
+#if DSP_MODEL==DSP_ST7796
+/*!
+ * These displays use SPI to communicate, 4 or 5 pins are required
+ * to interface (RST is optional).
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ * @section dependencies Dependencies
+ *
+ * This library depends on
+ * Adafruit_GFX being present on your system. Please make sure you have
+ * installed the latest version before using this library.
+ *
+ * @section author Author
+ *
+ * Written by Limor "ladyada" Fried for Adafruit Industries.
+ *
+ * @section license License
+ *
+ * BSD license, all text here must be included in any redistribution.
+ *
+ */
+
+#include "Adafruit_ST7796S_kbv.h"
+#ifndef ARDUINO_STM32_FEATHER
+#include "pins_arduino.h"
+#ifndef RASPI
+#include "wiring_private.h"
+#endif
+#endif
+#include
+
+#if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
+#define SPI_DEFAULT_FREQ 16000000
+// Teensy 3.0, 3.1/3.2, 3.5, 3.6
+#elif defined(__MK20DX128__) || defined(__MK20DX256__) || \
+ defined(__MK64FX512__) || defined(__MK66FX1M0__)
+#define SPI_DEFAULT_FREQ 40000000
+#elif defined(__AVR__) || defined(TEENSYDUINO)
+#define SPI_DEFAULT_FREQ 8000000
+#elif defined(ESP8266) || defined(ESP32)
+#define SPI_DEFAULT_FREQ 40000000
+#elif defined(RASPI)
+#define SPI_DEFAULT_FREQ 80000000
+#elif defined(ARDUINO_ARCH_STM32F1)
+#define SPI_DEFAULT_FREQ 36000000
+#else
+#define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
+#endif
+
+#define MADCTL_MY 0x80 ///< Bottom to top
+#define MADCTL_MX 0x40 ///< Right to left
+#define MADCTL_MV 0x20 ///< Reverse Mode
+#define MADCTL_ML 0x10 ///< LCD refresh Bottom to top
+#define MADCTL_RGB 0x00 ///< Red-Green-Blue pixel order
+#define MADCTL_BGR 0x08 ///< Blue-Green-Red pixel order
+#define MADCTL_MH 0x04 ///< LCD refresh right to left
+
+/**************************************************************************/
+/*!
+ @brief Instantiate Adafruit ST7796S driver with software SPI
+ @param cs Chip select pin #
+ @param dc Data/Command pin #
+ @param mosi SPI MOSI pin #
+ @param sclk SPI Clock pin #
+ @param rst Reset pin # (optional, pass -1 if unused)
+ @param miso SPI MISO pin # (optional, pass -1 if unused)
+*/
+/**************************************************************************/
+Adafruit_ST7796S_kbv::Adafruit_ST7796S_kbv(int8_t cs, int8_t dc, int8_t mosi,
+ int8_t sclk, int8_t rst, int8_t miso)
+ : Adafruit_SPITFT(ST7796S_TFTWIDTH, ST7796S_TFTHEIGHT, cs, dc, mosi, sclk,
+ rst, miso) {}
+
+/**************************************************************************/
+/*!
+ @brief Instantiate Adafruit ST7796S driver with hardware SPI using the
+ default SPI peripheral.
+ @param cs Chip select pin # (OK to pass -1 if CS tied to GND).
+ @param dc Data/Command pin # (required).
+ @param rst Reset pin # (optional, pass -1 if unused).
+*/
+/**************************************************************************/
+Adafruit_ST7796S_kbv::Adafruit_ST7796S_kbv(int8_t cs, int8_t dc, int8_t rst)
+ : Adafruit_SPITFT(ST7796S_TFTWIDTH, ST7796S_TFTHEIGHT, cs, dc, rst) {}
+
+#if !defined(ESP8266)
+/**************************************************************************/
+/*!
+ @brief Instantiate Adafruit ST7796S driver with hardware SPI using
+ a specific SPI peripheral (not necessarily default).
+ @param spiClass Pointer to SPI peripheral (e.g. &SPI or &SPI1).
+ @param dc Data/Command pin # (required).
+ @param cs Chip select pin # (optional, pass -1 if unused and
+ CS is tied to GND).
+ @param rst Reset pin # (optional, pass -1 if unused).
+*/
+/**************************************************************************/
+Adafruit_ST7796S_kbv::Adafruit_ST7796S_kbv(SPIClass *spiClass, int8_t dc, int8_t cs,
+ int8_t rst)
+ : Adafruit_SPITFT(ST7796S_TFTWIDTH, ST7796S_TFTHEIGHT, spiClass, cs, dc,
+ rst) {}
+#endif // end !ESP8266
+
+/**************************************************************************/
+/*!
+ @brief Instantiate Adafruit ST7796S driver using parallel interface.
+ @param busWidth If tft16 (enumeration in Adafruit_SPITFT.h), is a
+ 16-bit interface, else 8-bit.
+ @param d0 Data pin 0 (MUST be a byte- or word-aligned LSB of a
+ PORT register -- pins 1-n are extrapolated from this).
+ @param wr Write strobe pin # (required).
+ @param dc Data/Command pin # (required).
+ @param cs Chip select pin # (optional, pass -1 if unused and CS
+ is tied to GND).
+ @param rst Reset pin # (optional, pass -1 if unused).
+ @param rd Read strobe pin # (optional, pass -1 if unused).
+*/
+/**************************************************************************/
+Adafruit_ST7796S_kbv::Adafruit_ST7796S_kbv(tftBusWidth busWidth, int8_t d0, int8_t wr,
+ int8_t dc, int8_t cs, int8_t rst, int8_t rd)
+ : Adafruit_SPITFT(ST7796S_TFTWIDTH, ST7796S_TFTHEIGHT, busWidth, d0, wr, dc,
+ cs, rst, rd) {}
+
+// clang-format off
+static const uint8_t PROGMEM initcmd[] = {
+ // (COMMAND_BYTE), n, data_bytes....
+ 0x01, 0x80, // Soft reset, then delay 150 ms
+ 0xF0, 1, 0xC3, // ?? Unlock Manufacturer
+ 0xF0, 1, 0x96,
+#if 0
+#elif 0 //LCDWIKI
+ 0x36, 1, 0x68,
+ 0x3A, 1, 0x05,
+ 0 0xB0, 1, 0x80,
+ 0xB6, 2, 0x00, 0x02,
+ 0xB5, 4, 0x02, 0x03, 0x00, 0x04,
+ 0xB1, 2, 0x80, 0x10,
+ 0xB4, 1, 0x00,
+ 0xB7, 1, 0xC6,
+ 0xC5, 1, 0x24,
+ 0xE4, 1, 0x31,
+ 0xE8, 8, 0x40, 0x8A, 0x00, 0x00, 0x29, 0x19, 0xA5, 0x33,
+ 0xC2, 1, 0xA7,
+ 0xE0, 14, 0xF0, 0x09, 0x13, 0x12, 0x12, 0x2B, 0x3C, 0x44, 0x4B, 0x1B, 0x18, 0x17, 0x1D, 0x21,
+ 0xE1, 14, 0xF0, 0x09, 0x13, 0x0C, 0x0D, 0x27, 0x3B, 0x44, 0x4D, 0x0B, 0x17 ,0x17, 0x1D, 0x21,
+ 0x36, 1, 0x48,
+
+#elif 0 //TFT_eSPI
+ 0x36, 1, 0x48,
+ 0x3A, 1, 0x05, //Interlace Pixel Format [XX]
+ 0xB4, 1, 0x01, //Inversion Control [01]
+ 0xB6, 3, 0x80, 0x02, 0x3B, // Display Function Control [80 02 3B]
+ 0xE8, 8, 0x40, 0x8A, 0x00, 0x00, 0x29, 0x19, 0xA5, 0x33, //Adjustment Control 3 [40 8A 00 00 25 0A 38 33]
+ 0xC1, 1, 0x06, //Power Control 2 [13]
+ 0xC2, 1, 0xA7, //Power Control 3 [A?]
+ 0xC5, 1, 0x18, //VCOM=0.9 [1C]
+ //0x11, 0x80, //delay 150 ms
+ (0xE0), 14, 0xF0, 0x09, 0x0B, 0x06, 0x04, 0x15, 0x2F, 0x54, 0x42, 0x3C, 0x17, 0x14, 0x18, 0x1B, //PVGAMCTRL: Positive Voltage Gamma control
+ (0xE1), 14, 0xE0, 0x09, 0x0B, 0x06, 0x04, 0x03, 0x2B, 0x43, 0x42, 0x3B, 0x16, 0x14, 0x17, 0x1B, //NVGAMCTRL: Negative Voltage Gamma control
+#else
+// 0xC0, 2, 0x10, 0x10, //Power Control 1 [80 25]
+// 0xC1, 1, 0x41, //Power Control 2 [13]
+ 0xC5, 1, 0x1C, //VCOM Control 1 [1C]
+ 0x36, 1, 0x48, //Memory Access [00]
+ 0x3A, 1, 0x55, //565
+ 0xB0, 1, 0x80, //Interface [00]
+ //0xB1, 2, 0xB0, 0x11, //Frame Rate Control [A0 10]
+ 0xB4, 1, 0x01, //Inversion Control [01]
+ 0xB6, 3, 0x80, 0x02, 0x3B, // Display Function Control [80 02 3B] .kbv SS=1, NL=480
+ 0xB7, 1, 0xC6, //Entry Mode [06]
+// 0x3A, 1, 0x66, //Interlace Pixel Format [XX]
+// 0xF7, 4, 0xA9, 0x51, 0x2C, 0x82, //Adjustment Control 3 [A9 51 2C 82]
+#endif
+ 0xF0, 1, 0x69, //?? lock manufacturer commands
+ 0xF0, 1, 0x3C, //
+ 0x11, 0x80, // Exit Sleep, then delay 150 ms
+ 0x29, 0x80, // Main screen turn on, delay 150 ms
+ 0x00 // End of list
+};
+// clang-format on
+
+/**************************************************************************/
+/*!
+ @brief Initialize ST7796S chip
+ Connects to the ST7796S over SPI and sends initialization procedure commands
+ @param freq Desired SPI clock frequency
+*/
+/**************************************************************************/
+void Adafruit_ST7796S_kbv::begin(uint32_t freq) {
+
+ if (!freq)
+ freq = SPI_DEFAULT_FREQ;
+ initSPI(freq);
+
+ if (_rst < 0) { // If no hardware reset pin...
+ sendCommand(ST7796S_SWRESET); // Engage software reset
+ delay(150);
+ }
+
+ uint8_t cmd, x, numArgs;
+ const uint8_t *addr = initcmd;
+ while ((cmd = pgm_read_byte(addr++)) > 0) {
+ x = pgm_read_byte(addr++);
+ numArgs = x & 0x7F;
+ sendCommand(cmd, addr, numArgs);
+ addr += numArgs;
+ if (x & 0x80)
+ delay(150);
+ }
+
+ _width = ST7796S_TFTWIDTH;
+ _height = ST7796S_TFTHEIGHT;
+}
+
+/**************************************************************************/
+/*!
+ @brief Set origin of (0,0) and orientation of TFT display
+ @param m The index for rotation, from 0-3 inclusive
+*/
+/**************************************************************************/
+void Adafruit_ST7796S_kbv::setRotation(uint8_t m) {
+ rotation = m % 4; // can't be higher than 3
+ switch (rotation) {
+ case 0:
+ m = (MADCTL_MX | MADCTL_BGR);
+ _width = ST7796S_TFTWIDTH;
+ _height = ST7796S_TFTHEIGHT;
+ break;
+ case 1:
+ m = (MADCTL_MV | MADCTL_BGR);
+ _width = ST7796S_TFTHEIGHT;
+ _height = ST7796S_TFTWIDTH;
+ break;
+ case 2:
+ m = (MADCTL_MY | MADCTL_ML | MADCTL_BGR);
+ _width = ST7796S_TFTWIDTH;
+ _height = ST7796S_TFTHEIGHT;
+ break;
+ case 3:
+ m = (MADCTL_MX | MADCTL_MY | MADCTL_MV | MADCTL_ML | MADCTL_BGR);
+ _width = ST7796S_TFTHEIGHT;
+ _height = ST7796S_TFTWIDTH;
+ break;
+ }
+
+ sendCommand(ST7796S_MADCTL, &m, 1);
+ setScrollMargins(0, 0); //.kbv
+ scrollTo(0);
+}
+
+/**************************************************************************/
+/*!
+ @brief Enable/Disable display color inversion
+ @param invert True to invert, False to have normal color
+*/
+/**************************************************************************/
+void Adafruit_ST7796S_kbv::invertDisplay(bool invert) {
+ sendCommand(invert ? ST7796S_INVON : ST7796S_INVOFF);
+}
+
+/**************************************************************************/
+/*!
+ @brief Scroll display memory
+ @param y How many pixels to scroll display by
+*/
+/**************************************************************************/
+void Adafruit_ST7796S_kbv::scrollTo(uint16_t y) {
+ uint8_t data[2];
+ data[0] = y >> 8;
+ data[1] = y & 0xff;
+ sendCommand(ST7796S_VSCRSADD, (uint8_t *)data, 2);
+}
+
+/**************************************************************************/
+/*!
+ @brief Set the height of the Top and Bottom Scroll Margins
+ @param top The height of the Top scroll margin
+ @param bottom The height of the Bottom scroll margin
+ */
+/**************************************************************************/
+void Adafruit_ST7796S_kbv::setScrollMargins(uint16_t top, uint16_t bottom) {
+ // TFA+VSA+BFA must equal 480
+ if (top + bottom <= ST7796S_TFTHEIGHT) {
+ uint16_t middle = ST7796S_TFTHEIGHT - top - bottom;
+ uint8_t data[6];
+ data[0] = top >> 8;
+ data[1] = top & 0xff;
+ data[2] = middle >> 8;
+ data[3] = middle & 0xff;
+ data[4] = bottom >> 8;
+ data[5] = bottom & 0xff;
+ sendCommand(ST7796S_VSCRDEF, (uint8_t *)data, 6);
+ }
+}
+
+/**************************************************************************/
+/*!
+ @brief Set the "address window" - the rectangle we will write to RAM with
+ the next chunk of SPI data writes. The ST7796S will automatically wrap
+ the data as each row is filled
+ @param x1 TFT memory 'x' origin
+ @param y1 TFT memory 'y' origin
+ @param w Width of rectangle
+ @param h Height of rectangle
+*/
+/**************************************************************************/
+void Adafruit_ST7796S_kbv::setAddrWindow(uint16_t x1, uint16_t y1, uint16_t w,
+ uint16_t h) {
+ uint16_t x2 = (x1 + w - 1), y2 = (y1 + h - 1);
+ writeCommand(ST7796S_CASET); // Column address set
+ SPI_WRITE16(x1);
+ SPI_WRITE16(x2);
+ writeCommand(ST7796S_PASET); // Row address set
+ SPI_WRITE16(y1);
+ SPI_WRITE16(y2);
+ writeCommand(ST7796S_RAMWR); // Write to RAM
+}
+
+/**************************************************************************/
+/*!
+ @brief Read 8 bits of data from ST7796S configuration memory. NOT from RAM!
+ This is highly undocumented/supported, it's really a hack but kinda
+ works?
+ @param commandByte The command register to read data from
+ @param index The byte index into the command to read from
+ @return Unsigned 8-bit data read from ST7796S register
+ */
+/**************************************************************************/
+uint8_t Adafruit_ST7796S_kbv::readcommand8(uint8_t commandByte, uint8_t index) {
+ uint8_t data = 0x10 + index, ret;
+ sendCommand(0xFB, &data, 1); // Set Index Register
+ ret = Adafruit_SPITFT::readcommand8(commandByte);
+ data = 0x00;
+ sendCommand(0xFB, &data, 1); // Set Index Register
+ return ret;
+}
+#endif
diff --git a/yoRadio/src/Adafruit_ST7796S/Adafruit_ST7796S_kbv.h b/yoRadio/src/Adafruit_ST7796S/Adafruit_ST7796S_kbv.h
new file mode 100644
index 0000000..baf210b
--- /dev/null
+++ b/yoRadio/src/Adafruit_ST7796S/Adafruit_ST7796S_kbv.h
@@ -0,0 +1,129 @@
+/*
+ * Adafruit_ST7796S_kbv class inherits from Adafruit_GFX, Adafruit_SPITFT class and the Arduino Print class.
+ * Adafruit_ST7796S_kbv written by David Prentice
+ *
+ * Any use of Adafruit_ST7796S_kbv class and examples is dependent on Adafruit and Arduino licenses
+ * The license texts are in the accompanying license.txt file
+ */
+
+/*!
+ * @file Adafruit_ST7796S_kbv.h
+ *
+ * These displays use SPI to communicate, 4 or 5 pins are required
+ * to interface (RST is optional IF YOU ADD A PULLUP RESISTOR).
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ *
+ * This library depends on
+ * Adafruit_GFX being present on your system. Please make sure you have
+ * installed the latest version before using this library.
+ *
+ * Adafruit_GFX, Adafruit_SPITFT written by Limor "ladyada" Fried for Adafruit Industries.
+ *
+ * BSD license, all text here must be included in any redistribution.
+ *
+ */
+
+
+#ifndef _ADAFRUIT_ST7796S_KBV_H_
+#define _ADAFRUIT_ST7796S_KBV_H_
+
+#include "Adafruit_GFX.h"
+#include "Arduino.h"
+#include "Print.h"
+#include
+#include
+#include
+
+#define ST7796S_TFTWIDTH 320 ///< ST7796S max TFT width
+#define ST7796S_TFTHEIGHT 480 ///< ST7796S max TFT height
+
+#define ST7796S_NOP 0x00 ///< No-op register
+#define ST7796S_SWRESET 0x01 ///< Software reset register
+#define ST7796S_RDDID 0x04 ///< Read display identification information
+#define ST7796S_RDDST 0x09 ///< Read Display Status
+
+#define ST7796S_SLPIN 0x10 ///< Enter Sleep Mode
+#define ST7796S_SLPOUT 0x11 ///< Sleep Out
+#define ST7796S_PTLON 0x12 ///< Partial Mode ON
+#define ST7796S_NORON 0x13 ///< Normal Display Mode ON
+
+#define ST7796S_RDMODE 0x0A ///< Read Display Power Mode
+#define ST7796S_RDMADCTL 0x0B ///< Read Display MADCTL
+#define ST7796S_RDPIXFMT 0x0C ///< Read Display Pixel Format
+#define ST7796S_RDIMGFMT 0x0D ///< Read Display Image Format
+#define ST7796S_RDSELFDIAG 0x0F ///< Read Display Self-Diagnostic Result
+
+#define ST7796S_INVOFF 0x20 ///< Display Inversion OFF
+#define ST7796S_INVON 0x21 ///< Display Inversion ON
+#define ST7796S_GAMMASET 0x26 ///< Gamma Set
+#define ST7796S_DISPOFF 0x28 ///< Display OFF
+#define ST7796S_DISPON 0x29 ///< Display ON
+
+#define ST7796S_CASET 0x2A ///< Column Address Set
+#define ST7796S_PASET 0x2B ///< Page Address Set
+#define ST7796S_RAMWR 0x2C ///< Memory Write
+#define ST7796S_RAMRD 0x2E ///< Memory Read
+
+#define ST7796S_PTLAR 0x30 ///< Partial Area
+#define ST7796S_VSCRDEF 0x33 ///< Vertical Scrolling Definition
+#define ST7796S_MADCTL 0x36 ///< Memory Access Control
+#define ST7796S_VSCRSADD 0x37 ///< Vertical Scrolling Start Address
+#define ST7796S_PIXFMT 0x3A ///< COLMOD: Pixel Format Set
+
+
+// Color definitions
+#define ST7796S_BLACK 0x0000 ///< 0, 0, 0
+#define ST7796S_NAVY 0x000F ///< 0, 0, 123
+#define ST7796S_DARKGREEN 0x03E0 ///< 0, 125, 0
+#define ST7796S_DARKCYAN 0x03EF ///< 0, 125, 123
+#define ST7796S_MAROON 0x7800 ///< 123, 0, 0
+#define ST7796S_PURPLE 0x780F ///< 123, 0, 123
+#define ST7796S_OLIVE 0x7BE0 ///< 123, 125, 0
+#define ST7796S_LIGHTGREY 0xC618 ///< 198, 195, 198
+#define ST7796S_DARKGREY 0x7BEF ///< 123, 125, 123
+#define ST7796S_BLUE 0x001F ///< 0, 0, 255
+#define ST7796S_GREEN 0x07E0 ///< 0, 255, 0
+#define ST7796S_CYAN 0x07FF ///< 0, 255, 255
+#define ST7796S_RED 0xF800 ///< 255, 0, 0
+#define ST7796S_MAGENTA 0xF81F ///< 255, 0, 255
+#define ST7796S_YELLOW 0xFFE0 ///< 255, 255, 0
+#define ST7796S_WHITE 0xFFFF ///< 255, 255, 255
+#define ST7796S_ORANGE 0xFD20 ///< 255, 165, 0
+#define ST7796S_GREENYELLOW 0xAFE5 ///< 173, 255, 41
+#define ST7796S_PINK 0xFC18 ///< 255, 130, 198
+
+/**************************************************************************/
+/*!
+@brief Class to manage hardware interface with ST7796S chipset
+*/
+/**************************************************************************/
+
+class Adafruit_ST7796S_kbv : public Adafruit_SPITFT {
+public:
+ Adafruit_ST7796S_kbv(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK,
+ int8_t _RST = -1, int8_t _MISO = -1);
+ Adafruit_ST7796S_kbv(int8_t _CS, int8_t _DC, int8_t _RST = -1);
+#if !defined(ESP8266)
+ Adafruit_ST7796S_kbv(SPIClass *spiClass, int8_t dc, int8_t cs = -1,
+ int8_t rst = -1);
+#endif // end !ESP8266
+ Adafruit_ST7796S_kbv(tftBusWidth busWidth, int8_t d0, int8_t wr, int8_t dc,
+ int8_t cs = -1, int8_t rst = -1, int8_t rd = -1);
+
+ void begin(uint32_t freq = 0);
+ void setRotation(uint8_t r);
+ void invertDisplay(bool i);
+ void scrollTo(uint16_t y);
+ void setScrollMargins(uint16_t top, uint16_t bottom);
+
+ // Transaction API not used by GFX
+ void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
+
+ uint8_t readcommand8(uint8_t reg, uint8_t index = 0);
+};
+
+#endif // _ADAFRUIT_ST7796SH_
diff --git a/yoRadio/src/GT911_Touchscreen/TAMC_GT911.cpp b/yoRadio/src/GT911_Touchscreen/TAMC_GT911.cpp
new file mode 100644
index 0000000..38892a4
--- /dev/null
+++ b/yoRadio/src/GT911_Touchscreen/TAMC_GT911.cpp
@@ -0,0 +1,168 @@
+#if TS_MODEL==TS_MODEL_GT911
+#include "Arduino.h"
+#include "TAMC_GT911.h"
+#include
+
+TAMC_GT911::TAMC_GT911(uint8_t _sda, uint8_t _scl, uint8_t _int, uint8_t _rst, uint16_t _width, uint16_t _height) :
+ pinSda(_sda), pinScl(_scl), pinInt(_int), pinRst(_rst), width(_width), height(_height) {
+
+}
+
+void TAMC_GT911::begin(uint8_t _addr) {
+ addr = _addr;
+ Wire.begin(pinSda, pinScl);
+ reset();
+}
+void TAMC_GT911::reset() {
+ pinMode(pinInt, OUTPUT);
+ pinMode(pinRst, OUTPUT);
+ digitalWrite(pinInt, 0);
+ digitalWrite(pinRst, 0);
+ delay(10);
+ digitalWrite(pinInt, addr==GT911_ADDR2);
+ delay(1);
+ digitalWrite(pinRst, 1);
+ delay(5);
+ digitalWrite(pinInt, 0);
+ delay(50);
+ pinMode(pinInt, INPUT);
+ // attachInterrupt(pinInt, TAMC_GT911::onInterrupt, RISING);
+ delay(50);
+ readBlockData(configBuf, GT911_CONFIG_START, GT911_CONFIG_SIZE);
+ setResolution(width, height);
+}
+void TAMC_GT911::calculateChecksum() {
+ uint8_t checksum = 0;
+ for (uint8_t i=0; i> 7 & 1;
+ isLargeDetect = pointInfo >> 6 & 1;
+ touches = pointInfo & 0xF;
+ // Serial.print("bufferStatus: ");Serial.println(bufferStatus);
+ // Serial.print("largeDetect: ");Serial.println(isLargeDetect);
+ // Serial.print("proximityValid: ");Serial.println(proximityValid);
+ // Serial.print("haveKey: ");Serial.println(haveKey);
+ // Serial.print("touches: ");Serial.println(touches);
+ isTouched = touches > 0;
+ if (bufferStatus == 1 && isTouched) {
+ for (uint8_t i=0; i
+
+#define GT911_ADDR1 (uint8_t)0x5D
+#define GT911_ADDR2 (uint8_t)0x14
+
+#define ROTATION_LEFT (uint8_t)0
+#define ROTATION_INVERTED (uint8_t)1
+#define ROTATION_RIGHT (uint8_t)2
+#define ROTATION_NORMAL (uint8_t)3
+
+
+// Real-time command (Write only)
+#define GT911_COMMAND (uint16_t)0x8040
+#define GT911_ESD_CHECK (uint16_t)0x8041
+#define GT911_COMMAND_CHECK (uint16_t)0x8046
+
+// Configuration information (R/W)
+#define GT911_CONFIG_START (uint16_t)0x8047
+#define GT911_CONFIG_VERSION (uint16_t)0x8047
+#define GT911_X_OUTPUT_MAX_LOW (uint16_t)0x8048
+#define GT911_X_OUTPUT_MAX_HIGH (uint16_t)0x8049
+#define GT911_Y_OUTPUT_MAX_LOW (uint16_t)0x804A
+#define GT911_Y_OUTPUT_MAX_HIGH (uint16_t)0x804B
+#define GT911_TOUCH_NUMBER (uint16_t)0x804C
+#define GT911_MODULE_SWITCH_1 (uint16_t)0x804D
+#define GT911_MODULE_SWITCH_2 (uint16_t)0x804E
+#define GT911_SHAKE_COUNT (uint16_t)0x804F
+#define GT911_FILTER (uint16_t)0x8050
+#define GT911_LARGE_TOUCH (uint16_t)0x8051
+#define GT911_NOISE_REDUCTION (uint16_t)0x8052
+#define GT911_SCREEN_TOUCH_LEVEL (uint16_t)0x8053
+#define GT911_SCREEN_RELEASE_LEVEL (uint16_t)0x8054
+#define GT911_LOW_POWER_CONTROL (uint16_t)0x8055
+#define GT911_REFRESH_RATE (uint16_t)0x8056
+#define GT911_X_THRESHOLD (uint16_t)0x8057
+#define GT911_Y_THRESHOLD (uint16_t)0x8058
+#define GT911_X_SPEED_LIMIT (uint16_t)0x8059 //Reserve
+#define GT911_Y_SPEED_LIMIT (uint16_t)0x805A //Reserve
+#define GT911_SPACE_TOP_BOTTOM (uint16_t)0x805B
+#define GT911_SPACE_LEFT_RIGHT (uint16_t)0x805C
+#define GT911_MINI_FILTER (uint16_t)0x805D
+#define GT911_STRETCH_R0 (uint16_t)0x805E
+#define GT911_STRETCH_R1 (uint16_t)0x805F
+#define GT911_STRETCH_R2 (uint16_t)0x8060
+#define GT911_STRETCH_RM (uint16_t)0x8061
+#define GT911_DRV_GROUPA_NUM (uint16_t)0x8062
+#define GT911_DRV_GROUPB_NUM (uint16_t)0x8063
+#define GT911_SENSOR_NUM (uint16_t)0x8064
+#define GT911_FREQ_A_FACTOR (uint16_t)0x8065
+#define GT911_FREQ_B_FACTOR (uint16_t)0x8066
+#define GT911_PANEL_BIT_FREQ_L (uint16_t)0x8067
+#define GT911_PANEL_BIT_FREQ_H (uint16_t)0x8068
+#define GT911_PANEL_SENSOR_TIME_L (uint16_t)0x8069 //Reserve
+#define GT911_PANEL_SENSOR_TIME_H (uint16_t)0x806A
+#define GT911_PANEL_TX_GAIN (uint16_t)0x806B
+#define GT911_PANEL_RX_GAIN (uint16_t)0x806C
+#define GT911_PANEL_DUMP_SHIFT (uint16_t)0x806D
+#define GT911_DRV_FRAME_CONTROL (uint16_t)0x806E
+#define GT911_CHARGING_LEVEL_UP (uint16_t)0x806F
+#define GT911_MODULE_SWITCH3 (uint16_t)0x8070
+#define GT911_GESTURE_DIS (uint16_t)0X8071
+#define GT911_GESTURE_LONG_PRESS_TIME (uint16_t)0x8072
+#define GT911_X_Y_SLOPE_ADJUST (uint16_t)0X8073
+#define GT911_GESTURE_CONTROL (uint16_t)0X8074
+#define GT911_GESTURE_SWITCH1 (uint16_t)0X8075
+#define GT911_GESTURE_SWITCH2 (uint16_t)0X8076
+#define GT911_GESTURE_REFRESH_RATE (uint16_t)0x8077
+#define GT911_GESTURE_TOUCH_LEVEL (uint16_t)0x8078
+#define GT911_NEWGREENWAKEUPLEVEL (uint16_t)0x8079
+#define GT911_FREQ_HOPPING_START (uint16_t)0x807A
+#define GT911_FREQ_HOPPING_END (uint16_t)0X807B
+#define GT911_NOISE_DETECT_TIMES (uint16_t)0x807C
+#define GT911_HOPPING_FLAG (uint16_t)0X807D
+#define GT911_HOPPING_THRESHOLD (uint16_t)0X807E
+#define GT911_NOISE_THRESHOLD (uint16_t)0X807F //Reserve
+#define GT911_NOISE_MIN_THRESHOLD (uint16_t)0X8080
+#define GT911_HOPPING_SENSOR_GROUP (uint16_t)0X8082
+#define GT911_HOPPING_SEG1_NORMALIZE (uint16_t)0X8083
+#define GT911_HOPPING_SEG1_FACTOR (uint16_t)0X8084
+#define GT911_MAIN_CLOCK_AJDUST (uint16_t)0X8085
+#define GT911_HOPPING_SEG2_NORMALIZE (uint16_t)0X8086
+#define GT911_HOPPING_SEG2_FACTOR (uint16_t)0X8087
+#define GT911_HOPPING_SEG3_NORMALIZE (uint16_t)0X8089
+#define GT911_HOPPING_SEG3_FACTOR (uint16_t)0X808A
+#define GT911_HOPPING_SEG4_NORMALIZE (uint16_t)0X808C
+#define GT911_HOPPING_SEG4_FACTOR (uint16_t)0X808D
+#define GT911_HOPPING_SEG5_NORMALIZE (uint16_t)0X808F
+#define GT911_HOPPING_SEG5_FACTOR (uint16_t)0X8090
+#define GT911_HOPPING_SEG6_NORMALIZE (uint16_t)0X8092
+#define GT911_KEY_1 (uint16_t)0X8093
+#define GT911_KEY_2 (uint16_t)0X8094
+#define GT911_KEY_3 (uint16_t)0X8095
+#define GT911_KEY_4 (uint16_t)0X8096
+#define GT911_KEY_AREA (uint16_t)0X8097
+#define GT911_KEY_TOUCH_LEVEL (uint16_t)0X8098
+#define GT911_KEY_LEAVE_LEVEL (uint16_t)0X8099
+#define GT911_KEY_SENS_1_2 (uint16_t)0X809A
+#define GT911_KEY_SENS_3_4 (uint16_t)0X809B
+#define GT911_KEY_RESTRAIN (uint16_t)0X809C
+#define GT911_KEY_RESTRAIN_TIME (uint16_t)0X809D
+#define GT911_GESTURE_LARGE_TOUCH (uint16_t)0X809E
+#define GT911_HOTKNOT_NOISE_MAP (uint16_t)0X80A1
+#define GT911_LINK_THRESHOLD (uint16_t)0X80A2
+#define GT911_PXY_THRESHOLD (uint16_t)0X80A3
+#define GT911_GHOT_DUMP_SHIFT (uint16_t)0X80A4
+#define GT911_GHOT_RX_GAIN (uint16_t)0X80A5
+#define GT911_FREQ_GAIN0 (uint16_t)0X80A6
+#define GT911_FREQ_GAIN1 (uint16_t)0X80A7
+#define GT911_FREQ_GAIN2 (uint16_t)0X80A8
+#define GT911_FREQ_GAIN3 (uint16_t)0X80A9
+#define GT911_COMBINE_DIS (uint16_t)0X80B3
+#define GT911_SPLIT_SET (uint16_t)0X80B4
+#define GT911_SENSOR_CH0 (uint16_t)0X80B7
+#define GT911_DRIVER_CH0 (uint16_t)0X80D5
+#define GT911_CONFIG_CHKSUM (uint16_t)0X80FF
+#define GT911_CONFIG_FRESH (uint16_t)0X8100
+#define GT911_CONFIG_SIZE (uint16_t)0xFF-0x46
+// Coordinate information
+#define GT911_PRODUCT_ID (uint16_t)0X8140
+#define GT911_FIRMWARE_VERSION (uint16_t)0X8140
+#define GT911_RESOLUTION (uint16_t)0X8140
+#define GT911_VENDOR_ID (uint16_t)0X8140
+#define GT911_IMFORMATION (uint16_t)0X8140
+#define GT911_POINT_INFO (uint16_t)0X814E
+#define GT911_POINT_1 (uint16_t)0X814F
+#define GT911_POINT_2 (uint16_t)0X8157
+#define GT911_POINT_3 (uint16_t)0X815F
+#define GT911_POINT_4 (uint16_t)0X8167
+#define GT911_POINT_5 (uint16_t)0X816F
+#define GT911_POINTS_REG {GT911_POINT_1, GT911_POINT_2, GT911_POINT_3, GT911_POINT_4, GT911_POINT_5}
+
+class TP_Point {
+ public:
+ TP_Point(void);
+ TP_Point(uint8_t id, uint16_t x, uint16_t y, uint16_t size);
+
+ bool operator==(TP_Point);
+ bool operator!=(TP_Point);
+
+ uint8_t id;
+ uint16_t x;
+ uint16_t y;
+ uint8_t size;
+};
+
+class TAMC_GT911 {
+ public:
+ TAMC_GT911(uint8_t _sda, uint8_t _scl, uint8_t _int, uint8_t _rst, uint16_t _width, uint16_t _height);
+ void begin(uint8_t _addr=GT911_ADDR1);
+ void reset();
+ void setRotation(uint8_t rot);
+ void setResolution(uint16_t _width, uint16_t _height);
+ // void setOnRead(void (*isr)());
+ uint8_t getGesture(void);
+ void read(void);
+ uint8_t isLargeDetect;
+ uint8_t touches = 0;
+ bool isTouched = false;
+ // uint8_t gesture = NO_GESTURE;
+ TP_Point points[5];
+
+ private:
+ void calculateChecksum();
+ void reflashConfig();
+ // static void ARDUINO_ISR_ATTR onInterrupt();
+ TP_Point readPoint(uint8_t *data);
+ // void (*onRead)();
+ void writeByteData(uint16_t reg, uint8_t val);
+ uint8_t readByteData(uint16_t reg);
+ void writeBlockData(uint16_t reg, uint8_t *val, uint8_t size);
+ void readBlockData(uint8_t *buf, uint16_t reg, uint8_t size);
+ uint8_t rotation = ROTATION_NORMAL;
+ uint8_t addr;
+ uint8_t pinSda;
+ uint8_t pinScl;
+ uint8_t pinInt;
+ uint8_t pinRst;
+ uint16_t width;
+ uint16_t height;
+ uint8_t configBuf[GT911_CONFIG_SIZE];
+ // uint8_t *configBuf;
+};
+
+#endif // TAMC_GT911_H
diff --git a/yoRadio/src/core/config.cpp b/yoRadio/src/core/config.cpp
index 30ecee8..714c0ef 100644
--- a/yoRadio/src/core/config.cpp
+++ b/yoRadio/src/core/config.cpp
@@ -6,6 +6,10 @@
Config config;
+#if DSP_HSPI || TS_HSPI || VS_HSPI
+SPIClass SPI2(HSPI);
+#endif
+
void u8fix(char *src){
char last = src[strlen(src)-1];
if ((uint8_t)last >= 0xC2) src[strlen(src)-1]='\0';
diff --git a/yoRadio/src/core/config.h b/yoRadio/src/core/config.h
index 10f1a48..671b1f3 100644
--- a/yoRadio/src/core/config.h
+++ b/yoRadio/src/core/config.h
@@ -2,6 +2,7 @@
#define config_h
#include "Arduino.h"
#include
+#include
#include "options.h"
#define EEPROM_SIZE 768
@@ -184,5 +185,9 @@ class Config {
};
extern Config config;
+#if DSP_HSPI || TS_HSPI || VS_HSPI
+extern SPIClass SPI2;
+#endif
+
#endif
diff --git a/yoRadio/src/core/controls.cpp b/yoRadio/src/core/controls.cpp
index ce590a7..77ff705 100644
--- a/yoRadio/src/core/controls.cpp
+++ b/yoRadio/src/core/controls.cpp
@@ -42,9 +42,9 @@ yoEncoder encoder2 = yoEncoder(ENC2_BTNL, ENC2_BTNR, ENCODER2_STEPS, ENC2_INTERN
#endif
#endif
-#if TS_CS!=255
-#include
-XPT2046_Touchscreen ts(TS_CS);
+#if TS_MODEL!=TS_MODEL_UNDEFINED
+ #include "touchscreen.h"
+ TouchScreen touchscreen;
#endif
#if IR_PIN!=255
@@ -113,9 +113,8 @@ void initControls() {
button[i].setPressTicks(BTN_PRESS_TICKS);
}
#endif
-#if TS_CS!=255
- ts.begin();
- ts.setRotation(config.store.fliptouch?3:1);
+#if TS_MODEL!=TS_MODEL_UNDEFINED
+ touchscreen.init();
#endif
#if IR_PIN!=255
pinMode(IR_PIN, INPUT);
@@ -145,18 +144,15 @@ void loopControls() {
if (lpId >= 0) {
if (DSP_MODEL == DSP_DUMMY && (lpId == 4 || lpId == 5)) continue;
onBtnDuringLongPress(lpId);
- yield();
}
- yield();
}
#endif
#if IR_PIN!=255
irLoop();
#endif
-#if TS_CS!=255
- touchLoop();
+#if TS_MODEL!=TS_MODEL_UNDEFINED
+ touchscreen.loop();
#endif
- yield();
}
#if ENC_BTNL!=255
@@ -326,122 +322,6 @@ void irLoop() {
}
#endif // if IR_PIN!=255
-#if TS_CS!=255
-#ifndef TS_X_MIN
- #define TS_X_MIN 400
-#endif
-#ifndef TS_X_MAX
- #define TS_X_MAX 3800
-#endif
-#ifndef TS_Y_MIN
- #define TS_Y_MIN 260
-#endif
-#ifndef TS_Y_MAX
- #define TS_Y_MAX 3800
-#endif
-#ifndef TS_STEPS
- #define TS_STEPS 40
-#endif
-
-boolean wastouched = true;
-unsigned long touchdelay;
-uint16_t touchVol, touchStation;
-uint16_t oldTouchP[2];
-tsDirection_e direct;
-unsigned long touchLongPress;
-
-tsDirection_e tsDirection(uint16_t x, uint16_t y) {
- int16_t dX = x - oldTouchP[0];
- int16_t dY = y - oldTouchP[1];
- if (abs(dX) > 20 || abs(dY) > 20) {
- if (abs(dX) > abs(dY)) {
- if (dX > 0) {
- return TSD_RIGHT;
- } else {
- return TSD_LEFT;
- }
- } else {
- if (dY > 0) {
- return TSD_DOWN;
- } else {
- return TSD_UP;
- }
- }
- } else {
- return TDS_REQUEST;
- }
-}
-
-void touchLoop() {
- if (!checklpdelay(100, touchdelay)) return;
- boolean istouched = ts.touched();
- if (istouched) {
- TS_Point p = ts.getPoint();
- uint16_t touchX = map(p.x, TS_X_MIN, TS_X_MAX, 0, dsp.width());
- uint16_t touchY = map(p.y, TS_Y_MIN, TS_Y_MAX, 0, dsp.height());
- if (!wastouched) { /* START TOUCH */
- oldTouchP[0] = touchX;
- oldTouchP[1] = touchY;
- touchVol = touchX;
- touchStation = touchY;
- direct = TDS_REQUEST;
- touchLongPress=millis();
- } else { /* SWIPE TOUCH */
- direct = tsDirection(touchX, touchY);
- switch (direct) {
- case TSD_LEFT:
- case TSD_RIGHT: {
- touchLongPress=millis();
- if(display.mode()==PLAYER || display.mode()==VOL){
- int16_t xDelta = map(abs(touchVol - touchX), 0, dsp.width(), 0, TS_STEPS);
- display.putRequest(NEWMODE, VOL);
- if (xDelta>1) {
- controlsEvent((touchVol - touchX)<0);
- touchVol = touchX;
- }
- }
- break;
- }
- case TSD_UP:
- case TSD_DOWN: {
- touchLongPress=millis();
- if(display.mode()==PLAYER || display.mode()==STATIONS){
- int16_t yDelta = map(abs(touchStation - touchY), 0, dsp.height(), 0, TS_STEPS);
- display.putRequest(NEWMODE, STATIONS);
- if (yDelta>1) {
- controlsEvent((touchStation - touchY)<0);
- touchStation = touchY;
- }
- }
- break;
- }
- default:
- break;
- }
- }
- if (config.store.dbgtouch) {
- Serial.print(", x = ");
- Serial.print(p.x);
- Serial.print(", y = ");
- Serial.println(p.y);
- }
- } else {
- if (wastouched) {/* END TOUCH */
- if (direct == TDS_REQUEST) {
- uint32_t pressTicks = millis()-touchLongPress;
- if( pressTicks < BTN_PRESS_TICKS*2){
- if(pressTicks > 50) onBtnClick(EVT_BTNCENTER);
- }else{
- display.putRequest(NEWMODE, display.mode() == PLAYER ? STATIONS : PLAYER);
- }
- }
- direct = TSD_STAY;
- }
- }
- wastouched = istouched;
-}
-#endif // if TS_CS!=255
-
void onBtnLongPressStart(int id) {
switch ((controlEvt_e)id) {
case EVT_BTNLEFT:
@@ -629,7 +509,7 @@ void setEncAcceleration(uint16_t acc){
#endif
}
void flipTS(){
-#if TS_CS!=255
- ts.setRotation(config.store.fliptouch?3:1);
+#if TS_MODEL!=TS_MODEL_UNDEFINED
+ touchscreen.flip();
#endif
}
diff --git a/yoRadio/src/core/controls.h b/yoRadio/src/core/controls.h
index 84a76d1..c44bb92 100644
--- a/yoRadio/src/core/controls.h
+++ b/yoRadio/src/core/controls.h
@@ -4,7 +4,7 @@
enum controlEvt_e { EVT_BTNLEFT, EVT_BTNCENTER, EVT_BTNRIGHT, EVT_ENCBTNB, EVT_BTNUP, EVT_BTNDOWN, EVT_ENC2BTNB };
-enum tsDirection_e { TSD_STAY, TSD_LEFT, TSD_RIGHT, TSD_UP, TSD_DOWN, TDS_REQUEST };
+//enum tsDirection_e { TSD_STAY, TSD_LEFT, TSD_RIGHT, TSD_UP, TSD_DOWN, TDS_REQUEST };
#if IR_PIN!=255
enum : uint8_t { IR_UP=0, IR_PREV=1, IR_PLAY=2, IR_NEXT=3, IR_DOWN=4, IR_1=5, IR_2=6, IR_3=7, IR_4=8, IR_5=9, IR_6=10, IR_7=11, IR_8=12, IR_9=13, IR_AST=14, IR_0=15, IR_HASH=16 };
@@ -17,7 +17,7 @@ void loopControls();
void encoderLoop();
void encoder2Loop();
void irLoop();
-void touchLoop();
+//void touchLoop();
void irNum(byte num);
void irBlink();
void controlsEvent(bool toRight, int8_t volDelta = 0);
@@ -27,7 +27,7 @@ void onBtnDoubleClick(int id);
void onBtnDuringLongPress(int id);
void onBtnLongPressStart(int id);
void onBtnLongPressStop(int id);
-tsDirection_e tsDirection(uint16_t x, uint16_t y);
+//tsDirection_e tsDirection(uint16_t x, uint16_t y);
void setIRTolerance(uint8_t tl);
void setEncAcceleration(uint16_t acc);
diff --git a/yoRadio/src/core/display.cpp b/yoRadio/src/core/display.cpp
index db5e3fa..d381b9c 100644
--- a/yoRadio/src/core/display.cpp
+++ b/yoRadio/src/core/display.cpp
@@ -49,6 +49,9 @@ void loopDspTask(void * pvParameters){
void Display::init() {
#ifdef USE_NEXTION
nextion.begin();
+#endif
+#if LIGHT_SENSOR!=255
+ analogSetAttenuation(ADC_0db);
#endif
_bootStep = 0;
dsp.initDisplay();
@@ -442,6 +445,10 @@ void Display::_title() {
}
void Display::_time(bool redraw) {
+#if LIGHT_SENSOR!=255
+ config.store.brightness = AUTOBACKLIGHT(analogRead(LIGHT_SENSOR));
+ config.setBrightness();
+#endif
_clock.draw();
/*#ifdef USE_NEXTION
nextion.printClock(network.timeinfo);
diff --git a/yoRadio/src/core/display.h b/yoRadio/src/core/display.h
index f98aa53..18c9f0a 100644
--- a/yoRadio/src/core/display.h
+++ b/yoRadio/src/core/display.h
@@ -110,4 +110,5 @@ class Display {
extern Display display;
+
#endif
diff --git a/yoRadio/src/core/netserver.cpp b/yoRadio/src/core/netserver.cpp
index 4e0f099..a9257d5 100644
--- a/yoRadio/src/core/netserver.cpp
+++ b/yoRadio/src/core/netserver.cpp
@@ -557,7 +557,7 @@ void NetServer::requestOnChange(requestType_e request, uint8_t clientId) {
#endif
if (BRIGHTNESS_PIN != 255 || nxtn || dbgact) act += F("\"group_brightness\",");
if (DSP_CAN_FLIPPED || dbgact) act += F("\"group_tft\",");
- if (TS_CS != 255 || dbgact) act += F("\"group_touch\",");
+ if (TS_MODEL != TS_MODEL_UNDEFINED || dbgact) act += F("\"group_touch\",");
if (DSP_MODEL == DSP_NOKIA5110) act += F("\"group_nokia\",");
act += F("\"group_timezone\",");
if (SHOW_WEATHER || dbgact) act += F("\"group_weather\",");
diff --git a/yoRadio/src/core/network.cpp b/yoRadio/src/core/network.cpp
index ea13e1e..6122c60 100644
--- a/yoRadio/src/core/network.cpp
+++ b/yoRadio/src/core/network.cpp
@@ -209,6 +209,7 @@ bool getWeather(char *wstr) {
}
char *tmpe;
char *tmps;
+ char *tmpc;
const char* cursor = line.c_str();
char desc[120], temp[20], hum[20], press[20], icon[5];
@@ -251,8 +252,9 @@ bool getWeather(char *wstr) {
if (tmps == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;}
tmps += 10;
tmpe = strstr(tmps, ",\"");
+ tmpc = strstr(tmps, "}");
if (tmpe == NULL) { Serial.println("## OPENWEATHERMAP ###: humidity not found !"); return false;}
- strlcpy(hum, tmps, tmpe - tmps + 1);
+ strlcpy(hum, tmps, tmpe - tmps + (tmpc>tmpe?1:0));
#ifdef USE_NEXTION
nextion.putcmdf("press_txt.txt=\"%dmm\"", pressi);
diff --git a/yoRadio/src/core/options.h b/yoRadio/src/core/options.h
index cb4b9f9..2d18829 100644
--- a/yoRadio/src/core/options.h
+++ b/yoRadio/src/core/options.h
@@ -1,7 +1,7 @@
#ifndef options_h
#define options_h
-#define VERSION "0.8.02b"
+#define VERSION "0.8.03b"
/*******************************************************
DO NOT EDIT THIS FILE.
@@ -41,6 +41,7 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#define DSP_SSD1305I2C 16 // 128x64 2.4' SSD1305 and SSD1309 I2C https://aliexpress.com/item/32950307344.html
#define DSP_ILI9225 17 // 220x176 2.0' https://aliexpress.com/item/32952021835.html
#define DSP_ST7789_240 18 // 240x240 1.3' https://aliexpress.com/item/32996979276.html
+#define DSP_ST7796 19
/* !!! DSP_ST7789_240 requires further development when used in conjunction with the VS1053 module !!! See the link https://www.instructables.com/Adding-CS-Pin-to-13-LCD/ */
#define DSP_CUSTOM 101 // your display
@@ -48,6 +49,12 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef DSP_MODEL
#define DSP_MODEL DSP_DUMMY
#endif
+#ifndef DSP_HSPI
+ #define DSP_HSPI false // use HSPI for displays (miso=12, mosi=13, clk=14) instead of VSPI (by default)
+#endif
+#ifndef LED_INVERT
+ #define LED_INVERT false // invert onboard LED?
+#endif
/* TFT DISPLAY */
#ifndef TFT_CS
@@ -92,6 +99,9 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef VS1053_RST
#define VS1053_RST -1 // set to -1 if connected to Esp EN pin
#endif
+#ifndef VS_HSPI
+ #define VS_HSPI false // use HSPI for VS1053 (miso=12, mosi=13, clk=14) instead of VSPI (by default)
+#endif
/* I2S DAC */
#ifndef I2S_DOUT
@@ -167,8 +177,32 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#endif
/* TOUCH SCREEN */
+#define TS_MODEL_UNDEFINED 0
+#define TS_MODEL_XPT2046 1
+#define TS_MODEL_GT911 2
+
+#ifndef TS_MODEL
+ #define TS_MODEL TS_MODEL_UNDEFINED
+#endif
+
#ifndef TS_CS
- #define TS_CS 255
+ #define TS_CS 13
+#endif
+#ifndef TS_SDA
+ #define TS_SDA 33
+#endif
+#ifndef TS_SCL
+ #define TS_SCL 32
+#endif
+#ifndef TS_INT
+ #define TS_INT 21
+#endif
+#ifndef TS_RST
+ #define TS_RST 25
+#endif
+
+#ifndef TS_HSPI
+ #define TS_HSPI false // use HSPI for touchscreen (miso=12, mosi=13, clk=14) instead of VSPI (by default)
#endif
/* LCD DISPLAY */
@@ -218,6 +252,18 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#ifndef WAKE_PIN
#define WAKE_PIN 255 // Wake Pin (for manual wakeup from sleep mode. can match with BTN_XXXX, ENC_BTNB, ENC2_BTNB. must be one of: 0,2,4,12,13,14,15,25,26,27,32,33,34,35,36,39)
#endif
+#ifndef LIGHT_SENSOR
+ #define LIGHT_SENSOR 255 // Light sensor
+#endif
+#ifndef AUTOBACKLIGHT
+ #ifndef AUTOBACKLIGHT_MAX
+ #define AUTOBACKLIGHT_MAX 2500
+ #endif
+ #ifndef AUTOBACKLIGHT_MIN
+ #define AUTOBACKLIGHT_MIN 12
+ #endif
+ #define AUTOBACKLIGHT(x) ({uint16_t _lh=(x>AUTOBACKLIGHT_MAX?AUTOBACKLIGHT_MAX:x); map(_lh, AUTOBACKLIGHT_MAX, 0, AUTOBACKLIGHT_MIN, 100);}) // autobacklight function
+#endif
/*
*** ST7735 display submodel ***
INITR_BLACKTAB // 1.8' https://aliexpress.ru/item/1005002822797745.html
diff --git a/yoRadio/src/core/player.cpp b/yoRadio/src/core/player.cpp
index c812178..728a34f 100644
--- a/yoRadio/src/core/player.cpp
+++ b/yoRadio/src/core/player.cpp
@@ -11,9 +11,11 @@
Player player;
#if VS1053_CS!=255 && !I2S_INTERNAL
- Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ) {
-
- }
+ #if VS_HSPI
+ Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ, HSPI, 13, 12, 14) {}
+ #else
+ Player::Player(): Audio(VS1053_CS, VS1053_DCS, VS1053_DREQ) {}
+ #endif
void ResetChip(){
pinMode(VS1053_RST, OUTPUT);
digitalWrite(VS1053_RST, LOW);
@@ -116,7 +118,7 @@ void Player::zeroRequest() {
}
void Player::setOutputPins(bool isPlaying) {
- digitalWrite(LED_BUILTIN, isPlaying);
+ digitalWrite(LED_BUILTIN, LED_INVERT?!isPlaying:isPlaying);
if(MUTE_PIN!=255) digitalWrite(MUTE_PIN, isPlaying?!MUTE_VAL:MUTE_VAL);
}
diff --git a/yoRadio/src/core/touchscreen.cpp b/yoRadio/src/core/touchscreen.cpp
new file mode 100644
index 0000000..b401d99
--- /dev/null
+++ b/yoRadio/src/core/touchscreen.cpp
@@ -0,0 +1,196 @@
+#include "options.h"
+#if TS_MODEL!=TS_MODEL_UNDEFINED
+
+#include "touchscreen.h"
+#include "config.h"
+#include "controls.h"
+#include "display.h"
+#include "player.h"
+
+#ifndef TS_X_MIN
+ #define TS_X_MIN 400
+#endif
+#ifndef TS_X_MAX
+ #define TS_X_MAX 3800
+#endif
+#ifndef TS_Y_MIN
+ #define TS_Y_MIN 260
+#endif
+#ifndef TS_Y_MAX
+ #define TS_Y_MAX 3800
+#endif
+#ifndef TS_STEPS
+ #define TS_STEPS 40
+#endif
+
+#if TS_MODEL==TS_MODEL_XPT2046
+ #ifdef TS_SPIPINS
+ SPIClass TSSPI(HSPI);
+ #endif
+ #include
+ XPT2046_Touchscreen ts(TS_CS);
+ typedef TS_Point TSPoint;
+#elif TS_MODEL==TS_MODEL_GT911
+ #include "../GT911_Touchscreen/TAMC_GT911.h"
+ TAMC_GT911 ts = TAMC_GT911(TS_SDA, TS_SCL, TS_INT, TS_RST, 0, 0);
+ typedef TP_Point TSPoint;
+#endif
+
+void TouchScreen::init(){
+
+#if TS_MODEL==TS_MODEL_XPT2046
+ #ifdef TS_SPIPINS
+ TSSPI.begin(TS_SPIPINS);
+ ts.begin(TSSPI);
+ #else
+ #if TS_HSPI
+ ts.begin(SPI2);
+ #else
+ ts.begin();
+ #endif
+ #endif
+ ts.setRotation(config.store.fliptouch?3:1);
+#endif
+#if TS_MODEL==TS_MODEL_GT911
+ ts.begin();
+ ts.setRotation(config.store.fliptouch?0:2);
+#endif
+ _width = dsp.width();
+ _height = dsp.height();
+#if TS_MODEL==TS_MODEL_GT911
+ ts.setResolution(_width, _height);
+#endif
+}
+
+tsDirection_e TouchScreen::_tsDirection(uint16_t x, uint16_t y) {
+ int16_t dX = x - _oldTouchX;
+ int16_t dY = y - _oldTouchY;
+ if (abs(dX) > 20 || abs(dY) > 20) {
+ if (abs(dX) > abs(dY)) {
+ if (dX > 0) {
+ return TSD_RIGHT;
+ } else {
+ return TSD_LEFT;
+ }
+ } else {
+ if (dY > 0) {
+ return TSD_DOWN;
+ } else {
+ return TSD_UP;
+ }
+ }
+ } else {
+ return TDS_REQUEST;
+ }
+}
+
+void TouchScreen::flip(){
+#if TS_MODEL==TS_MODEL_XPT2046
+ ts.setRotation(config.store.fliptouch?3:1);
+#endif
+#if TS_MODEL==TS_MODEL_GT911
+ ts.setRotation(config.store.fliptouch?0:2);
+#endif
+}
+
+void TouchScreen::loop(){
+ uint16_t touchX, touchY;
+ static bool wastouched = true;
+ static uint32_t touchLongPress;
+ static tsDirection_e direct;
+ static uint16_t touchVol, touchStation;
+ if (!_checklpdelay(20, _touchdelay)) return;
+#if TS_MODEL==TS_MODEL_GT911
+ ts.read();
+#endif
+ bool istouched = _istouched();
+ if(istouched){
+ #if TS_MODEL==TS_MODEL_XPT2046
+ TSPoint p = ts.getPoint();
+ touchX = map(p.x, TS_X_MIN, TS_X_MAX, 0, _width);
+ touchY = map(p.y, TS_Y_MIN, TS_Y_MAX, 0, _height);
+ #elif TS_MODEL==TS_MODEL_GT911
+ TSPoint p = ts.points[0];
+ touchX = p.x;
+ touchY = p.y;
+ #endif
+ if (!wastouched) { /* START TOUCH */
+ _oldTouchX = touchX;
+ _oldTouchY = touchY;
+ touchVol = touchX;
+ touchStation = touchY;
+ direct = TDS_REQUEST;
+ touchLongPress=millis();
+ } else { /* SWIPE TOUCH */
+ direct = _tsDirection(touchX, touchY);
+ switch (direct) {
+ case TSD_LEFT:
+ case TSD_RIGHT: {
+ touchLongPress=millis();
+ if(display.mode()==PLAYER || display.mode()==VOL){
+ int16_t xDelta = map(abs(touchVol - touchX), 0, _width, 0, TS_STEPS);
+ display.putRequest(NEWMODE, VOL);
+ if (xDelta>1) {
+ controlsEvent((touchVol - touchX)<0);
+ touchVol = touchX;
+ }
+ }
+ break;
+ }
+ case TSD_UP:
+ case TSD_DOWN: {
+ touchLongPress=millis();
+ if(display.mode()==PLAYER || display.mode()==STATIONS){
+ int16_t yDelta = map(abs(touchStation - touchY), 0, _height, 0, TS_STEPS);
+ display.putRequest(NEWMODE, STATIONS);
+ if (yDelta>1) {
+ controlsEvent((touchStation - touchY)<0);
+ touchStation = touchY;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ if (config.store.dbgtouch) {
+ Serial.print(", x = ");
+ Serial.print(p.x);
+ Serial.print(", y = ");
+ Serial.println(p.y);
+ }
+ }else{
+ if (wastouched) {/* END TOUCH */
+ if (direct == TDS_REQUEST) {
+ uint32_t pressTicks = millis()-touchLongPress;
+ if( pressTicks < BTN_PRESS_TICKS*2){
+ if(pressTicks > 50) onBtnClick(EVT_BTNCENTER);
+ }else{
+ display.putRequest(NEWMODE, display.mode() == PLAYER ? STATIONS : PLAYER);
+ }
+ }
+ direct = TSD_STAY;
+ }
+ }
+ wastouched = istouched;
+}
+
+bool TouchScreen::_checklpdelay(int m, uint32_t &tstamp) {
+ if (millis() - tstamp > m) {
+ tstamp = millis();
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool TouchScreen::_istouched(){
+#if TS_MODEL==TS_MODEL_XPT2046
+ return ts.touched();
+#elif TS_MODEL==TS_MODEL_GT911
+ return ts.isTouched;
+#endif
+}
+
+#endif // TS_MODEL!=TS_MODEL_UNDEFINED
diff --git a/yoRadio/src/core/touchscreen.h b/yoRadio/src/core/touchscreen.h
new file mode 100644
index 0000000..23233cd
--- /dev/null
+++ b/yoRadio/src/core/touchscreen.h
@@ -0,0 +1,23 @@
+#ifndef touchscreen_h
+#define touchscreen_h
+#include "Arduino.h"
+
+enum tsDirection_e { TSD_STAY, TSD_LEFT, TSD_RIGHT, TSD_UP, TSD_DOWN, TDS_REQUEST };
+
+class TouchScreen {
+ public:
+ TouchScreen() {}
+ void init();
+ void loop();
+ void flip();
+ private:
+ uint16_t _oldTouchX, _oldTouchY, _width, _height;
+ uint32_t _touchdelay;
+ bool _checklpdelay(int m, uint32_t &tstamp);
+ tsDirection_e _tsDirection(uint16_t x, uint16_t y);
+ bool _istouched();
+};
+
+extern TouchScreen touchscreen;
+
+#endif
diff --git a/yoRadio/src/displays/conf/displayST7789conf.h b/yoRadio/src/displays/conf/displayST7789conf.h
index 657b133..fa7bcd3 100644
--- a/yoRadio/src/displays/conf/displayST7789conf.h
+++ b/yoRadio/src/displays/conf/displayST7789conf.h
@@ -21,7 +21,7 @@
const ScrollConfig metaConf PROGMEM = {{ TFT_FRAMEWDT, TFT_FRAMEWDT, 3, WA_LEFT }, 140, true, MAX_WIDTH, 5000, 5, 30 };
const ScrollConfig title1Conf PROGMEM = {{ TFT_FRAMEWDT, 50, 2, WA_LEFT }, 140, true, MAX_WIDTH, 5000, 4, 30 };
const ScrollConfig title2Conf PROGMEM = {{ TFT_FRAMEWDT, 70, 2, WA_LEFT }, 140, true, MAX_WIDTH, 5000, 4, 30 };
-const ScrollConfig playlistConf PROGMEM = {{ TFT_FRAMEWDT, 112, 2, WA_LEFT }, 140, true, MAX_WIDTH, 0, 2, 30 };
+const ScrollConfig playlistConf PROGMEM = {{ TFT_FRAMEWDT, 112, 2, WA_LEFT }, 140, true, MAX_WIDTH, 1000, 2, 30 };
const ScrollConfig apTitleConf PROGMEM = {{ TFT_FRAMEWDT, TFT_FRAMEWDT, 3, WA_CENTER }, 140, false, MAX_WIDTH, 0, 4, 20 };
const ScrollConfig apSettConf PROGMEM = {{ TFT_FRAMEWDT, 240-TFT_FRAMEWDT-16, 2, WA_LEFT }, 140, false, MAX_WIDTH, 0, 4, 30 };
const ScrollConfig weatherConf PROGMEM = {{ 8, 87, 2, WA_LEFT }, 140, true, MAX_WIDTH, 0, 4, 30 };
diff --git a/yoRadio/src/displays/conf/displayST7796conf.h b/yoRadio/src/displays/conf/displayST7796conf.h
new file mode 100644
index 0000000..ccdd8dd
--- /dev/null
+++ b/yoRadio/src/displays/conf/displayST7796conf.h
@@ -0,0 +1,68 @@
+/*************************************************************************************
+ ST7796 480X320 displays configuration file.
+ Copy this file to yoRadio/src/displays/conf/displayST7789conf_custom.h
+ and modify it
+ More info on https://github.com/e2002/yoradio/wiki/Widgets#widgets-description
+*************************************************************************************/
+
+#ifndef displayST7789conf_h
+#define displayST7789conf_h
+
+#define DSP_WIDTH 480
+#define DSP_HEIGHT 320
+#define TFT_FRAMEWDT 10
+#define MAX_WIDTH DSP_WIDTH-TFT_FRAMEWDT*2
+#define PLMITEMS 11
+#define PLMITEMLENGHT 40
+#define PLMITEMHEIGHT 32
+
+#define bootLogoTop 110
+
+/* SROLLS */ /* {{ left, top, fontsize, align }, buffsize, uppercase, width, scrolldelay, scrolldelta, scrolltime } */
+const ScrollConfig metaConf PROGMEM = {{ TFT_FRAMEWDT, TFT_FRAMEWDT, 4, WA_LEFT }, 140, true, MAX_WIDTH, 5000, 7, 40 };
+const ScrollConfig title1Conf PROGMEM = {{ TFT_FRAMEWDT, 62, 2, WA_LEFT }, 140, true, MAX_WIDTH-6*2*7-6, 5000, 7, 40 };
+const ScrollConfig title2Conf PROGMEM = {{ TFT_FRAMEWDT, 86, 2, WA_LEFT }, 140, true, MAX_WIDTH, 5000, 7, 40 };
+const ScrollConfig playlistConf PROGMEM = {{ TFT_FRAMEWDT, 146, 3, WA_LEFT }, 140, true, MAX_WIDTH, 1000, 7, 40 };
+const ScrollConfig apTitleConf PROGMEM = {{ TFT_FRAMEWDT, TFT_FRAMEWDT, 4, WA_CENTER }, 140, false, MAX_WIDTH, 0, 7, 40 };
+const ScrollConfig apSettConf PROGMEM = {{ TFT_FRAMEWDT, 320-TFT_FRAMEWDT-16, 2, WA_LEFT }, 140, false, MAX_WIDTH, 0, 7, 40 };
+const ScrollConfig weatherConf PROGMEM = {{ TFT_FRAMEWDT, 116, 2, WA_LEFT }, 140, true, MAX_WIDTH, 0, 7, 40 };
+
+/* BACKGROUNDS */ /* {{ left, top, fontsize, align }, width, height, outlined } */
+const FillConfig metaBGConf PROGMEM = {{ 0, 0, 0, WA_LEFT }, DSP_WIDTH, 50, false };
+const FillConfig volbarConf PROGMEM = {{ TFT_FRAMEWDT, DSP_HEIGHT-TFT_FRAMEWDT-8, 0, WA_LEFT }, MAX_WIDTH, 8, true };
+const FillConfig playlBGConf PROGMEM = {{ 0, 138, 0, WA_LEFT }, DSP_WIDTH, 36, false };
+const FillConfig heapbarConf PROGMEM = {{ 0, DSP_HEIGHT-2, 0, WA_LEFT }, DSP_WIDTH, 2, false };
+
+/* WIDGETS */ /* { left, top, fontsize, align } */
+const WidgetConfig bootstrConf PROGMEM = { 0, 243, 1, WA_CENTER };
+const WidgetConfig bitrateConf PROGMEM = { 6, 62, 2, WA_RIGHT };
+const WidgetConfig voltxtConf PROGMEM = { 0, DSP_HEIGHT-38, 2, WA_CENTER };
+const WidgetConfig iptxtConf PROGMEM = { TFT_FRAMEWDT, DSP_HEIGHT-38, 2, WA_LEFT };
+const WidgetConfig rssiConf PROGMEM = { TFT_FRAMEWDT, DSP_HEIGHT-38, 2, WA_RIGHT };
+const WidgetConfig numConf PROGMEM = { 0, 200, 70, WA_CENTER };
+const WidgetConfig apNameConf PROGMEM = { TFT_FRAMEWDT, 88, 3, WA_CENTER };
+const WidgetConfig apName2Conf PROGMEM = { TFT_FRAMEWDT, 120, 3, WA_CENTER };
+const WidgetConfig apPassConf PROGMEM = { TFT_FRAMEWDT, 173, 3, WA_CENTER };
+const WidgetConfig apPass2Conf PROGMEM = { TFT_FRAMEWDT, 205, 3, WA_CENTER };
+const WidgetConfig clockConf PROGMEM = { 16, 224, 70, WA_RIGHT }; /* 52 is a fixed font size. do not change */
+const WidgetConfig vuConf PROGMEM = { TFT_FRAMEWDT, 136, 1, WA_LEFT };
+
+const WidgetConfig bootWdtConf PROGMEM = { 0, 216, 1, WA_CENTER };
+const ProgressConfig bootPrgConf PROGMEM = { 90, 14, 4 };
+
+/* BANDS */ /* { onebandwidth, onebandheight, bandsHspace, bandsVspace, numofbands, fadespeed } */
+const VUBandsConfig bandsConf PROGMEM = { 32, 130, 4, 2, 10, 6 };
+
+/* STRINGS */
+const char numtxtFmt[] PROGMEM = "%d";
+const char rssiFmt[] PROGMEM = "WiFi %d";
+const char iptxtFmt[] PROGMEM = "%s";
+const char voltxtFmt[] PROGMEM = "%d";
+const char bitrateFmt[] PROGMEM = "%d kBs";
+
+/* MOVES */ /* { left, top, width } */
+const MoveConfig clockMove PROGMEM = { 0, 176, -1 };
+const MoveConfig weatherMove PROGMEM = { 8, 120, MAX_WIDTH };
+const MoveConfig weatherMoveVU PROGMEM = { 89, 120, 381 };
+
+#endif
diff --git a/yoRadio/src/displays/displayGC9106.cpp b/yoRadio/src/displays/displayGC9106.cpp
index 368fe53..e8d26d4 100644
--- a/yoRadio/src/displays/displayGC9106.cpp
+++ b/yoRadio/src/displays/displayGC9106.cpp
@@ -14,7 +14,11 @@
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
-DspCore::DspCore(): Adafruit_GC9106Ex(TFT_CS, TFT_DC, TFT_RST) { }
+#if DSP_HSPI
+DspCore::DspCore(): Adafruit_GC9106Ex(&SPI2, TFT_DC, TFT_CS, TFT_RST) {}
+#else
+DspCore::DspCore(): Adafruit_GC9106Ex(TFT_CS, TFT_DC, TFT_RST) {}
+#endif
#include "tools/utf8RusGFX.h"
diff --git a/yoRadio/src/displays/displayILI9225.cpp b/yoRadio/src/displays/displayILI9225.cpp
index 0b0c6f1..1662291 100644
--- a/yoRadio/src/displays/displayILI9225.cpp
+++ b/yoRadio/src/displays/displayILI9225.cpp
@@ -13,11 +13,8 @@ extern unsigned char yofont10x14[];
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
-//SPIClass hspi(VSPI);
-DspCore::DspCore(): TFT_22_ILI9225(TFT_RST, TFT_DC, TFT_CS, 0) {
-
-}
+DspCore::DspCore(): TFT_22_ILI9225(TFT_RST, TFT_DC, TFT_CS, 0) {}
#include "tools/utf8RusGFX.h"
@@ -97,7 +94,11 @@ void DspCore::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
void DspCore::initDisplay() {
TAKE_MUTEX();
+#if DSP_HSPI
+ begin(SPI2);
+#else
begin();
+#endif
invert();
flip();
setTextSize(1);
diff --git a/yoRadio/src/displays/displayILI9341.cpp b/yoRadio/src/displays/displayILI9341.cpp
index c75af0f..71ded06 100644
--- a/yoRadio/src/displays/displayILI9341.cpp
+++ b/yoRadio/src/displays/displayILI9341.cpp
@@ -10,9 +10,11 @@
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
-DspCore::DspCore(): Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST) {
-
-}
+#if DSP_HSPI
+DspCore::DspCore(): Adafruit_ILI9341(&SPI2, TFT_DC, TFT_CS, TFT_RST) {}
+#else
+DspCore::DspCore(): Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST) {}
+#endif
#include "tools/utf8RusGFX.h"
diff --git a/yoRadio/src/displays/displayN5110.cpp b/yoRadio/src/displays/displayN5110.cpp
index 935dd3b..01aeead 100644
--- a/yoRadio/src/displays/displayN5110.cpp
+++ b/yoRadio/src/displays/displayN5110.cpp
@@ -23,9 +23,11 @@ const unsigned char logo [] PROGMEM=
0xe0, 0x01, 0xff, 0xc0
};
-DspCore::DspCore(): Adafruit_PCD8544(TFT_DC, TFT_CS, TFT_RST) {
-
-}
+#if DSP_HSPI
+DspCore::DspCore(): Adafruit_PCD8544(TFT_DC, TFT_CS, TFT_RST, &SPI2) {}
+#else
+DspCore::DspCore(): Adafruit_PCD8544(TFT_DC, TFT_CS, TFT_RST) {}
+#endif
#include "tools/utf8RusGFX.h"
diff --git a/yoRadio/src/displays/displaySSD1305.cpp b/yoRadio/src/displays/displaySSD1305.cpp
index f5a80fd..90981f8 100644
--- a/yoRadio/src/displays/displaySSD1305.cpp
+++ b/yoRadio/src/displays/displaySSD1305.cpp
@@ -30,9 +30,11 @@ const unsigned char logo [] PROGMEM=
};
#if DSP_MODEL==DSP_SSD1305
-DspCore::DspCore(): Adafruit_SSD1305(128, 64, &SPI, TFT_DC, TFT_RST, TFT_CS, DEF_SPI_FREQ) {
-
-}
+ #if DSP_HSPI
+ DspCore::DspCore(): Adafruit_SSD1305(128, 64, &SPI2, TFT_DC, TFT_RST, TFT_CS, DEF_SPI_FREQ) {}
+ #else
+ DspCore::DspCore(): Adafruit_SSD1305(128, 64, &SPI, TFT_DC, TFT_RST, TFT_CS, DEF_SPI_FREQ) {}
+ #endif
#else
#include
TwoWire I2CSSD1305 = TwoWire(0);
diff --git a/yoRadio/src/displays/displayST7735.cpp b/yoRadio/src/displays/displayST7735.cpp
index 0179604..ca2ed6d 100644
--- a/yoRadio/src/displays/displayST7735.cpp
+++ b/yoRadio/src/displays/displayST7735.cpp
@@ -14,9 +14,11 @@
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
-DspCore::DspCore(): Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST) {
-
-}
+#if DSP_HSPI
+DspCore::DspCore(): Adafruit_ST7735(&SPI2, TFT_CS, TFT_DC, TFT_RST) {}
+#else
+DspCore::DspCore(): Adafruit_ST7735(&SPI, TFT_CS, TFT_DC, TFT_RST) {}
+#endif
#include "tools/utf8RusGFX.h"
diff --git a/yoRadio/src/displays/displayST7789.cpp b/yoRadio/src/displays/displayST7789.cpp
index 8da1a0b..baf8d97 100644
--- a/yoRadio/src/displays/displayST7789.cpp
+++ b/yoRadio/src/displays/displayST7789.cpp
@@ -15,7 +15,11 @@
#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
+#if DSP_HSPI
+DspCore::DspCore(): Adafruit_ST7789(&SPI2, TFT_CS, TFT_DC, TFT_RST) {}
+#else
DspCore::DspCore(): Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST) {}
+#endif
#include "tools/utf8RusGFX.h"
diff --git a/yoRadio/src/displays/displayST7796.cpp b/yoRadio/src/displays/displayST7796.cpp
new file mode 100644
index 0000000..7aff7ad
--- /dev/null
+++ b/yoRadio/src/displays/displayST7796.cpp
@@ -0,0 +1,216 @@
+#include "../core/options.h"
+#if DSP_MODEL==DSP_ST7796
+
+#include "displayST7796.h"
+//#include
+#include "fonts/bootlogo.h"
+#include "../core/player.h"
+#include "../core/config.h"
+#include "../core/network.h"
+
+#ifndef DEF_SPI_FREQ
+ #define DEF_SPI_FREQ 40000000UL /* set it to 0 for system default */
+#endif
+
+#define TAKE_MUTEX() if(player.mutex_pl) xSemaphoreTake(player.mutex_pl, portMAX_DELAY)
+#define GIVE_MUTEX() if(player.mutex_pl) xSemaphoreGive(player.mutex_pl)
+
+#if DSP_HSPI
+DspCore::DspCore(): Adafruit_ST7796S_kbv(&SPI2, TFT_DC, TFT_CS, TFT_RST) {}
+#else
+DspCore::DspCore(): Adafruit_ST7796S_kbv(TFT_CS, TFT_DC, TFT_RST) {}
+#endif
+
+#include "tools/utf8RusGFX.h"
+
+void DspCore::initDisplay() {
+ begin();
+ if(DEF_SPI_FREQ > 0) setSPISpeed(DEF_SPI_FREQ);
+ invert();
+ cp437(true);
+ flip();
+ setTextWrap(false);
+ setTextSize(1);
+ fillScreen(0x0000);
+}
+
+void DspCore::drawLogo(uint16_t top) { drawRGBBitmap((width() - 99) / 2, top, bootlogo2, 99, 64); }
+
+void DspCore::drawPlaylist(uint16_t currentItem, char* currentItemText) {
+ for (byte i = 0; i < PLMITEMS; i++) {
+ plMenu[i][0] = '\0';
+ }
+ config.fillPlMenu(plMenu, currentItem - 5, PLMITEMS);
+ setTextSize(3);
+ int yStart = (height() / 2 - PLMITEMHEIGHT / 2) - PLMITEMHEIGHT * (PLMITEMS - 1) / 2 + 3;
+
+ for (byte i = 0; i < PLMITEMS; i++) {
+ if (i == 5) {
+ strlcpy(currentItemText, plMenu[i], PLMITEMLENGHT - 1);
+ } else {
+ setTextColor(config.theme.playlist[abs(i - 5)-1], config.theme.background);
+ setCursor(TFT_FRAMEWDT, yStart + i * PLMITEMHEIGHT);
+ fillRect(0, yStart + i * PLMITEMHEIGHT - 1, width(), PLMITEMHEIGHT - 6, config.theme.background);
+ print(utf8Rus(plMenu[i], true));
+ }
+ }
+}
+
+void DspCore::clearDsp(bool black) { fillScreen(black?0:config.theme.background); }
+
+GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c) {
+ return gfxFont->glyph + c;
+}
+
+uint8_t DspCore::_charWidth(unsigned char c){
+ GFXglyph *glyph = pgm_read_glyph_ptr(&DS_DIGI56pt7b, c - 0x20);
+ return pgm_read_byte(&glyph->xAdvance);
+}
+
+uint16_t DspCore::textWidth(const char *txt){
+ uint16_t w = 0, l=strlen(txt);
+ for(uint16_t c=0;c0)
+ dsp.fillRect(_olddateleft, clockTop+10, _olddatewidth, CHARHEIGHT, config.theme.background);
+ setTextColor(config.theme.date, config.theme.background);
+ setCursor(_dateleft, clockTop+15);
+ setTextSize(2);
+ print(_dateBuf); /* print date */
+ strlcpy(_oldDateBuf, _dateBuf, sizeof(_dateBuf));
+ _olddatewidth = _datewidth;
+ _olddateleft = _dateleft;
+ setTextSize(4);
+ setTextColor(config.theme.dow, config.theme.background);
+ setCursor(width() - 8 - clockRightSpace - CHARWIDTH*4*2, clockTop-CHARHEIGHT*4+4);
+ print(utf8Rus(dow[network.timeinfo.tm_wday], false)); /* print dow */
+}
+
+void DspCore::_clockTime(){
+ if(_oldtimeleft>0) dsp.fillRect(_oldtimeleft, clockTop-clockTimeHeight+1, _oldtimewidth, clockTimeHeight, config.theme.background);
+ _timeleft = width()-clockRightSpace-CHARWIDTH*4*2-24-_timewidth;
+ setTextSize(1);
+ setFont(&DS_DIGI56pt7b);
+ setTextColor(config.theme.clock, config.theme.background);
+ setCursor(_timeleft, clockTop);
+ print(_timeBuf);
+ setFont();
+ strlcpy(_oldTimeBuf, _timeBuf, sizeof(_timeBuf));
+ _oldtimewidth = _timewidth;
+ _oldtimeleft = _timeleft;
+ drawFastVLine(width()-clockRightSpace-CHARWIDTH*4*2-18, clockTop-clockTimeHeight, clockTimeHeight+4, config.theme.div); /*divider vert*/
+ drawFastHLine(width()-clockRightSpace-CHARWIDTH*4*2-18, clockTop-clockTimeHeight+37, 59, config.theme.div); /*divider hor*/
+ sprintf(_buffordate, "%2d %s %d", network.timeinfo.tm_mday,mnths[network.timeinfo.tm_mon], network.timeinfo.tm_year+1900);
+ strlcpy(_dateBuf, utf8Rus(_buffordate, true), sizeof(_dateBuf));
+ _datewidth = strlen(_dateBuf) * CHARWIDTH*2;
+ _dateleft = width() - 10 - clockRightSpace - _datewidth;
+}
+
+void DspCore::printClock(uint16_t top, uint16_t rightspace, uint16_t timeheight, bool redraw){
+ clockTop = top;
+ clockRightSpace = rightspace;
+ clockTimeHeight = timeheight;
+ strftime(_timeBuf, sizeof(_timeBuf), "%H:%M", &network.timeinfo);
+ if(strcmp(_oldTimeBuf, _timeBuf)!=0 || redraw){
+ _getTimeBounds();
+ _clockTime();
+ if(strcmp(_oldDateBuf, _dateBuf)!=0 || redraw) _clockDate();
+ }
+ _clockSeconds();
+}
+
+void DspCore::clearClock(){
+ dsp.fillRect(_timeleft, clockTop-clockTimeHeight, _timewidth+CHARWIDTH*3*2+24, clockTimeHeight+12+CHARHEIGHT, config.theme.background);
+}
+
+void DspCore::startWrite(void) {
+ TAKE_MUTEX();
+ Adafruit_ST7796S_kbv::startWrite();
+}
+
+void DspCore::endWrite(void) {
+ Adafruit_ST7796S_kbv::endWrite();
+ GIVE_MUTEX();
+}
+
+void DspCore::loop(bool force) {
+
+}
+
+void DspCore::charSize(uint8_t textsize, uint8_t& width, uint16_t& height){
+ width = textsize * CHARWIDTH;
+ height = textsize * CHARHEIGHT;
+}
+
+void DspCore::setTextSize(uint8_t s){
+ Adafruit_GFX::setTextSize(s);
+}
+
+void DspCore::flip(){
+ setRotation(config.store.flipscreen?3:1);
+}
+
+void DspCore::invert(){
+ invertDisplay(config.store.invertdisplay);
+}
+
+void DspCore::sleep(void) {
+ sendCommand(ST7796S_SLPIN); delay(150); sendCommand(ST7796S_DISPOFF); delay(150);
+}
+
+void DspCore::wake(void) {
+ sendCommand(ST7796S_DISPON); delay(150); sendCommand(ST7796S_SLPOUT); delay(150);
+}
+
+void DspCore::writePixel(int16_t x, int16_t y, uint16_t color) {
+ if(_clipping){
+ if ((x < _cliparea.left) || (x > _cliparea.left+_cliparea.width) || (y < _cliparea.top) || (y > _cliparea.top + _cliparea.height)) return;
+ }
+ Adafruit_ST7796S_kbv::writePixel(x, y, color);
+}
+
+void DspCore::writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) {
+ if(_clipping){
+ if ((x < _cliparea.left) || (x >= _cliparea.left+_cliparea.width) || (y < _cliparea.top) || (y > _cliparea.top + _cliparea.height)) return;
+ }
+ Adafruit_ST7796S_kbv::writeFillRect(x, y, w, h, color);
+}
+
+void DspCore::setClipping(clipArea ca){
+ _cliparea = ca;
+ _clipping = true;
+}
+
+void DspCore::clearClipping(){
+ _clipping = false;
+}
+
+void DspCore::setNumFont(){
+ setFont(&DS_DIGI56pt7b);
+ setTextSize(1);
+}
+#endif
diff --git a/yoRadio/src/displays/displayST7796.h b/yoRadio/src/displays/displayST7796.h
new file mode 100644
index 0000000..586f85b
--- /dev/null
+++ b/yoRadio/src/displays/displayST7796.h
@@ -0,0 +1,35 @@
+#ifndef displayST7789_h
+#define displayST7789_h
+#include "../core/options.h"
+
+#include "Arduino.h"
+#include
+//#include
+#include "../Adafruit_ST7796S/Adafruit_ST7796S_kbv.h"
+#include "fonts/DS_DIGI56pt7b.h" // https://tchapi.github.io/Adafruit-GFX-Font-Customiser/
+#include "tools/l10n.h"
+
+#define CHARWIDTH 6
+#define CHARHEIGHT 8
+
+typedef GFXcanvas16 Canvas;
+#include "widgets/widgets.h"
+#include "widgets/pages.h"
+
+#if __has_include("conf/displayST7796conf_custom.h")
+ #include "conf/displayST7796conf_custom.h"
+#else
+ #include "conf/displayST7796conf.h"
+#endif
+
+#define BOOT_PRG_COLOR 0xE68B
+#define BOOT_TXT_COLOR 0xFFFF
+#define PINK 0xF97F
+
+class DspCore: public Adafruit_ST7796S_kbv {
+#include "tools/commongfx.h"
+};
+
+extern DspCore dsp;
+
+#endif
diff --git a/yoRadio/src/displays/dspcore.h b/yoRadio/src/displays/dspcore.h
index 18b7fa6..769ae03 100644
--- a/yoRadio/src/displays/dspcore.h
+++ b/yoRadio/src/displays/dspcore.h
@@ -34,6 +34,8 @@
#include "displayCustom.h"
#elif DSP_MODEL==DSP_ILI9225
#include "displayILI9225.h"
+#elif DSP_MODEL==DSP_ST7796
+ #include "displayST7796.h"
#endif
//extern DspCore dsp;
diff --git a/yoRadio/src/displays/fonts/DS_DIGI56pt7b.h b/yoRadio/src/displays/fonts/DS_DIGI56pt7b.h
new file mode 100644
index 0000000..cd19b37
--- /dev/null
+++ b/yoRadio/src/displays/fonts/DS_DIGI56pt7b.h
@@ -0,0 +1,320 @@
+const uint8_t DS_DIGI56pt7bBitmaps[] PROGMEM = {
+ 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xC7, 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0xE3, 0xFF, 0xFF,
+ 0xFF, 0xF1, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0x8F, 0xFF, 0xFF, 0xFC,
+ 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
+ 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F,
+ 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0,
+ 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01,
+ 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00,
+ 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x7D, 0xC0, 0x00, 0x00, 0x00, 0x0E,
+ 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x01, 0x1C, 0x00, 0x00, 0x00, 0x00, 0xEF, 0x80, 0x00, 0x00, 0x00,
+ 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
+ 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F,
+ 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0,
+ 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01,
+ 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
+ 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0x1F,
+ 0xF1, 0xFF, 0xFF, 0xFF, 0xE3, 0xF8, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x7F,
+ 0xFF, 0xFF, 0xFF, 0x8E, 0x3F, 0xFF, 0xFF, 0xFF, 0xF1, 0x1F, 0xFF, 0xFF,
+ 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x04, 0x18, 0x71,
+ 0xE7, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xCF, 0x8E,
+ 0x08, 0x00, 0x00, 0x00, 0x83, 0x8F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xEF, 0xCF, 0x8F, 0x0E, 0x0C, 0x08, 0x00, 0x3F, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xC4,
+ 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0x03, 0xFF, 0xFF, 0xFF, 0xF1, 0xC0, 0x7F,
+ 0xFF, 0xFF, 0xF8, 0xF0, 0x0F, 0xFF, 0xFF, 0xFC, 0x7C, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07,
+ 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00,
+ 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00,
+ 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07,
+ 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00,
+ 0x00, 0x00, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0x1F, 0x03, 0xFF, 0xFF, 0xFF,
+ 0xE3, 0x81, 0xFF, 0xFF, 0xFF, 0xFC, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
+ 0x1F, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x08, 0x7F,
+ 0xFF, 0xFF, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00,
+ 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00,
+ 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00,
+ 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03,
+ 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80,
+ 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00,
+ 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00,
+ 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00,
+ 0x00, 0x00, 0x03, 0xE3, 0xFF, 0xFF, 0xFF, 0x00, 0xF1, 0xFF, 0xFF, 0xFF,
+ 0xE0, 0x38, 0xFF, 0xFF, 0xFF, 0xFC, 0x0C, 0x7F, 0xFF, 0xFF, 0xFF, 0x82,
+ 0x3F, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF,
+ 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xE1,
+ 0x07, 0xFF, 0xFF, 0xFF, 0xC3, 0x03, 0xFF, 0xFF, 0xFF, 0x87, 0x01, 0xFF,
+ 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00,
+ 0x3F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x03, 0xFF, 0xFF, 0xFF, 0x1F, 0x07, 0xFF, 0xFF, 0xFF,
+ 0x8E, 0x0F, 0xFF, 0xFF, 0xFF, 0xC4, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F,
+ 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF,
+ 0xFF, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x1F,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x01, 0xFF, 0xFF, 0xFF, 0x1F,
+ 0x03, 0xFF, 0xFF, 0xFF, 0x8F, 0x07, 0xFF, 0xFF, 0xFF, 0xC7, 0x0F, 0xFF,
+ 0xFF, 0xFF, 0xE3, 0x1F, 0xFF, 0xFF, 0xFF, 0xF1, 0x3F, 0xFF, 0xFF, 0xFF,
+ 0xF8, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00,
+ 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x3F,
+ 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0,
+ 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01,
+ 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
+ 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F,
+ 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0,
+ 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x9F, 0xFF, 0xFF, 0xFE,
+ 0x7D, 0xCF, 0xFF, 0xFF, 0xFF, 0xCE, 0x27, 0xFF, 0xFF, 0xFF, 0xF9, 0x03,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF,
+ 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x3F,
+ 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00,
+ 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0,
+ 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00,
+ 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00,
+ 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00,
+ 0x7C, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0,
+ 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0,
+ 0xE3, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x7F, 0xFF, 0xFF, 0xF8, 0x0F, 0x8F,
+ 0xFF, 0xFF, 0xFC, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00,
+ 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F,
+ 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00,
+ 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00,
+ 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00,
+ 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0,
+ 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00,
+ 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F,
+ 0x80, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x03, 0xE7, 0xFF,
+ 0xFF, 0xFF, 0x80, 0x73, 0xFF, 0xFF, 0xFF, 0xF0, 0x09, 0xFF, 0xFF, 0xFF,
+ 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0,
+ 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xF8, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0,
+ 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00,
+ 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00,
+ 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0,
+ 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0xFF,
+ 0xFF, 0xFF, 0x1F, 0x01, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0xFF, 0xFF, 0xFF,
+ 0xFC, 0x70, 0x7F, 0xFF, 0xFF, 0xFF, 0x8C, 0x3F, 0xFF, 0xFF, 0xFF, 0xF1,
+ 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xC3, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0xE3, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0x3C, 0x7F, 0xFF, 0xFF, 0xF8, 0x0F, 0x8F, 0xFF, 0xFF, 0xFC, 0x03,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80,
+ 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00,
+ 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00,
+ 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00,
+ 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03,
+ 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80,
+ 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00,
+ 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00,
+ 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x03, 0xE7, 0xFF, 0xFF, 0xFF, 0x80, 0x73,
+ 0xFF, 0xFF, 0xFF, 0xF0, 0x09, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFF,
+ 0xF0, 0x08, 0x7F, 0xFF, 0xFF, 0xF8, 0x47, 0x00, 0x00, 0x00, 0x00, 0x3B,
+ 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80,
+ 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00,
+ 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07,
+ 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE,
+ 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00,
+ 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00,
+ 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF,
+ 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80,
+ 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00,
+ 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07,
+ 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0x1F, 0xF1,
+ 0xFF, 0xFF, 0xFF, 0xE3, 0xF8, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0x7F, 0xFF,
+ 0xFF, 0xFF, 0x8E, 0x3F, 0xFF, 0xFF, 0xFF, 0xF1, 0x1F, 0xFF, 0xFF, 0xFF,
+ 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC,
+ 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0xF1, 0x07, 0xFF,
+ 0xFF, 0xFF, 0xE3, 0x03, 0xFF, 0xFF, 0xFF, 0xC7, 0x01, 0xFF, 0xFF, 0xFF,
+ 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x3F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00,
+ 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00,
+ 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00,
+ 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x1F, 0xFF, 0xFF, 0xFF,
+ 0xE3, 0xE3, 0xFF, 0xFF, 0xFF, 0xF1, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF,
+ 0x8F, 0xFF, 0xFF, 0xFC, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x00,
+ 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00,
+ 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F,
+ 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8,
+ 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00,
+ 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00,
+ 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF,
+ 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00,
+ 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00,
+ 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F,
+ 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE7,
+ 0xFF, 0xFF, 0xFF, 0x9F, 0x73, 0xFF, 0xFF, 0xFF, 0xF3, 0x89, 0xFF, 0xFF,
+ 0xFF, 0xFE, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF,
+ 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x08, 0x7F, 0xFF, 0xFF, 0xF8, 0x47,
+ 0x00, 0x00, 0x00, 0x00, 0x3B, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00,
+ 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00,
+ 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F,
+ 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8,
+ 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00,
+ 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00,
+ 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF,
+ 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00,
+ 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00,
+ 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F,
+ 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE3,
+ 0xFF, 0xFF, 0xFF, 0x1F, 0xF1, 0xFF, 0xFF, 0xFF, 0xE3, 0xF8, 0xFF, 0xFF,
+ 0xFF, 0xFC, 0x7C, 0x7F, 0xFF, 0xFF, 0xFF, 0x8E, 0x3F, 0xFF, 0xFF, 0xFF,
+ 0xF1, 0x1F, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
+ 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xC7, 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0xE3, 0xFF, 0xFF,
+ 0xFF, 0xF1, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0x8F, 0xFF, 0xFF, 0xFC,
+ 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
+ 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F,
+ 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0,
+ 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00,
+ 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01,
+ 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF,
+ 0x80, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x00,
+ 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
+ 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0x9F,
+ 0x73, 0xFF, 0xFF, 0xFF, 0xF3, 0x89, 0xFF, 0xFF, 0xFF, 0xFE, 0x40, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF,
+ 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xF8, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0,
+ 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00,
+ 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F,
+ 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00,
+ 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
+ 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01,
+ 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0,
+ 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
+ 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00,
+ 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0x1F,
+ 0x01, 0xFF, 0xFF, 0xFF, 0xE3, 0xC0, 0xFF, 0xFF, 0xFF, 0xFC, 0x70, 0x7F,
+ 0xFF, 0xFF, 0xFF, 0x8C, 0x3F, 0xFF, 0xFF, 0xFF, 0xF1, 0x1F, 0xFF, 0xFF,
+ 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+};
+
+const GFXglyph DS_DIGI56pt7bGlyphs[] PROGMEM = {
+ { 0, 0, 0, 24, 0, 1 }, // 0x20 ' '
+ { 0, 0, 0, 0, 0, 0 }, // 0x21 '!'
+ { 0, 0, 0, 0, 0, 0 }, // 0x22 '"'
+ { 0, 0, 0, 0, 0, 0 }, // 0x23 '#'
+ { 0, 0, 0, 0, 0, 0 }, // 0x24 '$'
+ { 0, 0, 0, 0, 0, 0 }, // 0x25 '%'
+ { 0, 0, 0, 0, 0, 0 }, // 0x26 '&'
+ { 0, 0, 0, 0, 0, 0 }, // 0x27 '''
+ { 0, 0, 0, 0, 0, 0 }, // 0x28 '('
+ { 0, 0, 0, 0, 0, 0 }, // 0x29 ')'
+ { 0, 0, 0, 0, 0, 0 }, // 0x2A '*'
+ { 0, 0, 0, 0, 0, 0 }, // 0x2B '+'
+ { 0, 0, 0, 0, 0, 0 }, // 0x2C ','
+ { 0, 0, 0, 0, 0, 0 }, // 0x2D '-'
+ { 0, 0, 0, 0, 0, 0 }, // 0x2E '.'
+ { 0, 0, 0, 0, 0, 0 }, // 0x2F '/'
+ { 0, 42, 70, 54, 6, -69 }, // 0x30 '0'
+ { 368, 7, 68, 29, 10, -68 }, // 0x31 '1'
+ { 428, 42, 70, 54, 6, -69 }, // 0x32 '2'
+ { 796, 40, 70, 54, 7, -69 }, // 0x33 '3'
+ { 1146, 42, 68, 54, 6, -68 }, // 0x34 '4'
+ { 1503, 42, 70, 54, 6, -69 }, // 0x35 '5'
+ { 1871, 42, 70, 54, 6, -69 }, // 0x36 '6'
+ { 2239, 40, 69, 54, 7, -69 }, // 0x37 '7'
+ { 2584, 42, 70, 54, 6, -69 }, // 0x38 '8'
+ { 2952, 42, 70, 54, 6, -69 }, // 0x39 '9'
+ { 3320, 7, 59, 24, 8, -58 } // 0x3A ':'
+};
+
+const GFXfont DS_DIGI56pt7b PROGMEM = {
+ (uint8_t *)DS_DIGI56pt7bBitmaps,
+ (GFXglyph *)DS_DIGI56pt7bGlyphs, 0x20, 0x3A, 110 };
+
+// Approx. 6564 bytes