diff --git a/PxMatrix.h b/PxMatrix.h index f0c1bc8..553be7a 100644 --- a/PxMatrix.h +++ b/PxMatrix.h @@ -84,13 +84,13 @@ enum scan_patterns {LINE, ZIGZAG, ZAGGIZ, WZAGZIG, VZAG}; enum driver_chips {SHIFT, FM6124, FM6126A}; -#define max_matrix_pixels PxMATRIX_MAX_HEIGHT * PxMATRIX_MAX_WIDTH -#define color_step 256 / PxMATRIX_COLOR_DEPTH -#define color_half_step int(color_step / 2) -#define color_third_step int(color_step / 3) -#define color_two_third_step int(color_third_step*2) +#define max_matrix_pixels (PxMATRIX_MAX_HEIGHT * PxMATRIX_MAX_WIDTH) +#define color_step (256 / PxMATRIX_COLOR_DEPTH) +#define color_half_step (int(color_step / 2)) +#define color_third_step (int(color_step / 3)) +#define color_two_third_step (int(color_third_step*2)) -#define buffer_size max_matrix_pixels * 3 / 8 +#define buffer_size (max_matrix_pixels * 3 / 8) class PxMATRIX : public Adafruit_GFX { public: @@ -99,10 +99,12 @@ class PxMATRIX : public Adafruit_GFX { inline PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C,uint8_t D); inline PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t OE, uint8_t A,uint8_t B,uint8_t C,uint8_t D,uint8_t E); + inline void begin(uint8_t row_pattern, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t SS); inline void begin(uint8_t row_pattern); inline void begin(); inline void clearDisplay(void); + inline void clearDisplay(bool selected_buffer); // Updates the display inline void display(uint16_t show_time); @@ -110,15 +112,12 @@ class PxMATRIX : public Adafruit_GFX { // Draw pixels inline void drawPixelRGB565(int16_t x, int16_t y, uint16_t color); - inline void drawPixelRGB565(int16_t x, int16_t y, uint16_t color, bool selected_buffer); inline void drawPixel(int16_t x, int16_t y, uint16_t color); - inline void drawPixel(int16_t x, int16_t y, uint16_t color, bool selected_buffer); inline void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b); - inline void drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b, bool selected_buffer); - // Does nothing for now + // Does nothing for now (always returns 0) uint8_t getPixel(int8_t x, int8_t y); // Converts RGB888 to RGB565 @@ -139,11 +138,8 @@ class PxMATRIX : public Adafruit_GFX { // Helps to reduce display update latency on larger displays inline void setFastUpdate(bool fast_update); - // Select active buffer to updare display from - inline void selectBuffer(bool selected_buffer); - - // Select active buffer to updare display from - inline void swapBuffers(); + // When using double buffering, this displays the draw buffer + inline void showBuffer(); // Control the minimum color values that result in an active pixel inline void setColorOffset(uint8_t r, uint8_t g,uint8_t b); @@ -167,10 +163,9 @@ class PxMATRIX : public Adafruit_GFX { private: // the display buffer for the LED matrix + uint8_t PxMATRIX_buffer[PxMATRIX_COLOR_DEPTH][buffer_size]; #ifdef double_buffer - uint8_t PxMATRIX_buffer[PxMATRIX_COLOR_DEPTH][2*buffer_size];// = {0x00 }; -#else - uint8_t PxMATRIX_buffer[PxMATRIX_COLOR_DEPTH][buffer_size];// = {0x00 }; + uint8_t PxMATRIX_buffer2[PxMATRIX_COLOR_DEPTH][buffer_size]; #endif // GPIO pins @@ -181,6 +176,13 @@ class PxMATRIX : public Adafruit_GFX { uint8_t _C_PIN; uint8_t _D_PIN; uint8_t _E_PIN; + + // SPI pins + uint8_t _SPI_CLK = SPI_BUS_CLK; + uint8_t _SPI_MOSI = SPI_BUS_MOSI; + uint8_t _SPI_MISO = SPI_BUS_MISO; + uint8_t _SPI_SS = SPI_BUS_SS; + uint8_t _width; uint8_t _height; uint8_t _panels_width; @@ -213,7 +215,6 @@ class PxMATRIX : public Adafruit_GFX { uint16_t _send_buffer_size; // This is for double buffering - bool _selected_buffer; bool _active_buffer; // Hols configuration @@ -286,7 +287,6 @@ inline void PxMATRIX::init(uint16_t width, uint16_t height,uint8_t LATCH, uint8_ _rows_per_buffer = _height/2; _panel_width_bytes = (_width/_panels_width)/8; - _selected_buffer=false; _active_buffer=false; _color_R_offset=0; @@ -303,7 +303,10 @@ inline void PxMATRIX::init(uint16_t width, uint16_t height,uint8_t LATCH, uint8_ _scan_pattern=LINE; _driver_chip=SHIFT; - clearDisplay(); + clearDisplay(0); +#ifdef double_buffer + clearDisplay(1); +#endif } @@ -333,9 +336,9 @@ inline void PxMATRIX::writeRegister(uint16_t reg_value, uint8_t reg_position) // b12 - 9/8/7/6/5 = 4 bit brightness // b13 - 9 =1 screen on // b13 - 6 =1 screen off - pinMode(SPI_BUS_CLK,OUTPUT); - pinMode(SPI_BUS_MOSI,OUTPUT); - digitalWrite(SPI_BUS_CLK,HIGH); // CCK LOW + pinMode(_SPI_CLK,OUTPUT); + pinMode(_SPI_MOSI,OUTPUT); + digitalWrite(_SPI_CLK,HIGH); // CCK LOW digitalWrite(_OE_PIN,LOW); digitalWrite(_LATCH_PIN,HIGH); digitalWrite(_A_PIN,HIGH); @@ -348,14 +351,14 @@ inline void PxMATRIX::writeRegister(uint16_t reg_value, uint8_t reg_position) { reg_bit=bit_counter%16; if ((reg_value>>reg_bit)&1) - digitalWrite(SPI_BUS_MOSI,HIGH); + digitalWrite(_SPI_MOSI,HIGH); else - digitalWrite(SPI_BUS_MOSI,LOW); + digitalWrite(_SPI_MOSI,LOW); delay(1); - digitalWrite(SPI_BUS_CLK,LOW); // CLK HIGH + digitalWrite(_SPI_CLK,LOW); // CLK HIGH delay(1); - digitalWrite(SPI_BUS_CLK,HIGH); // CLK LOW + digitalWrite(_SPI_CLK,HIGH); // CLK LOW delay(1); if ((bit_counter == (_send_buffer_size*8 - reg_position-1))) { @@ -457,26 +460,13 @@ inline PxMATRIX::PxMATRIX(uint16_t width, uint16_t height,uint8_t LATCH, uint8_t } inline void PxMATRIX::drawPixel(int16_t x, int16_t y, uint16_t color) { - drawPixelRGB565( x, y, color,0 ); + drawPixelRGB565(x, y, color); } -inline void PxMATRIX::drawPixel(int16_t x, int16_t y, uint16_t color, bool selected_buffer) { - drawPixelRGB565( x, y, color, selected_buffer); +inline void PxMATRIX::showBuffer() { + _active_buffer=!_active_buffer; } -inline void PxMATRIX::selectBuffer(bool selected_buffer) -{ - - _selected_buffer=selected_buffer; -} - -inline void PxMATRIX::swapBuffers() -{ - - _selected_buffer!=_selected_buffer; -} - - inline void PxMATRIX::setColorOffset(uint8_t r, uint8_t g,uint8_t b) { if ((color_half_step+r)<0) @@ -564,11 +554,7 @@ inline void PxMATRIX::fillMatrixBuffer(int16_t x, int16_t y, uint8_t r, uint8_t if (_scan_pattern!=LINE && _scan_pattern!=WZAGZIG && _scan_pattern!=VZAG) { // Precomputed row offset values -#ifdef double_buffer - base_offset=buffer_size*selected_buffer+_row_offset[y]-(x/8)*2; -#else base_offset=_row_offset[y]-(x/8)*2; -#endif uint8_t row_sector=0; uint16_t row_sector__offset=_width/4; for (uint8_t yy = 0; yy<_height; yy+=2*_row_pattern) @@ -593,9 +579,6 @@ inline void PxMATRIX::fillMatrixBuffer(int16_t x, int16_t y, uint8_t r, uint8_t uint8_t in_row_byte_offset = x_byte%_panel_width_bytes; // this could be pretty easily extended to vertical stacking as well total_offset_r = _row_offset[y] - in_row_byte_offset - _panel_width_bytes*(_row_sets_per_buffer*(_panels_width*which_buffer + which_panel) + vert_index_in_buffer); -#ifdef double_buffer - total_offset_r -= buffer_size*selected_buffer; -#endif } total_offset_g=total_offset_r-_pattern_color_bytes; @@ -605,48 +588,51 @@ inline void PxMATRIX::fillMatrixBuffer(int16_t x, int16_t y, uint8_t r, uint8_t if ((_scan_pattern==ZAGGIZ) && ((y%(_row_pattern*2))<_row_pattern)) bit_select = 7-bit_select; + uint8_t (*PxMATRIX_bufferp)[PxMATRIX_COLOR_DEPTH][buffer_size] = &PxMATRIX_buffer; + +#ifdef double_buffer + PxMATRIX_bufferp = selected_buffer ? &PxMATRIX_buffer2 : &PxMATRIX_buffer; +#endif + //Color interlacing for (int this_color=0; this_color color_tresh+_color_R_offset) - PxMATRIX_buffer[this_color][total_offset_r] |=_BV(bit_select); + (*PxMATRIX_bufferp)[this_color][total_offset_r] |=_BV(bit_select); else - PxMATRIX_buffer[this_color][total_offset_r] &= ~_BV(bit_select); + (*PxMATRIX_bufferp)[this_color][total_offset_r] &= ~_BV(bit_select); if (g > color_tresh+_color_G_offset) - PxMATRIX_buffer[(this_color+color_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_g] |=_BV(bit_select); + (*PxMATRIX_bufferp)[(this_color+color_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_g] |=_BV(bit_select); else - PxMATRIX_buffer[(this_color+color_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_g] &= ~_BV(bit_select); + (*PxMATRIX_bufferp)[(this_color+color_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_g] &= ~_BV(bit_select); if (b > color_tresh+_color_B_offset) - PxMATRIX_buffer[(this_color+color_two_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_b] |=_BV(bit_select); + (*PxMATRIX_bufferp)[(this_color+color_two_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_b] |=_BV(bit_select); else - PxMATRIX_buffer[(this_color+color_two_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_b] &= ~_BV(bit_select); + (*PxMATRIX_bufferp)[(this_color+color_two_third_step)%PxMATRIX_COLOR_DEPTH][total_offset_b] &= ~_BV(bit_select); } } -inline void PxMATRIX::drawPixelRGB565(int16_t x, int16_t y, uint16_t color, bool selected_buffer) { - uint8_t r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; - uint8_t g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; - uint8_t b = (((color & 0x1F) * 527) + 23) >> 6; - fillMatrixBuffer( x, y, r, g,b, selected_buffer); -} - inline void PxMATRIX::drawPixelRGB565(int16_t x, int16_t y, uint16_t color) { uint8_t r = ((((color >> 11) & 0x1F) * 527) + 23) >> 6; uint8_t g = ((((color >> 5) & 0x3F) * 259) + 33) >> 6; uint8_t b = (((color & 0x1F) * 527) + 23) >> 6; - fillMatrixBuffer( x, y, r, g,b, 0); -} - -inline void PxMATRIX::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b, bool selected_buffer) { - fillMatrixBuffer(x, y, r, g,b, selected_buffer); +#ifdef double_buffer + fillMatrixBuffer(x, y, r, g, b, !_active_buffer); +#else + fillMatrixBuffer(x, y, r, g, b, false); +#endif } inline void PxMATRIX::drawPixelRGB888(int16_t x, int16_t y, uint8_t r, uint8_t g,uint8_t b) { - fillMatrixBuffer(x, y, r, g,b, 0); +#ifdef double_buffer + fillMatrixBuffer(x, y, r, g, b, !_active_buffer); +#else + fillMatrixBuffer(x, y, r, g, b, false); +#endif } // the most basic function, get a single pixel @@ -660,13 +646,23 @@ inline void PxMATRIX::begin() } +void PxMATRIX::begin(uint8_t row_pattern, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t SS) +{ + _SPI_CLK = CLK; + _SPI_MOSI = MOSI; + _SPI_MISO = MISO; + _SPI_SS = SS; + begin(row_pattern); + +} + void PxMATRIX::spi_init(){ #ifdef ESP8266 SPI.begin(); #endif #ifdef ESP32 - SPI.begin(SPI_BUS_CLK, SPI_BUS_MISO, SPI_BUS_MOSI, SPI_BUS_SS); + SPI.begin(_SPI_CLK, _SPI_MISO, _SPI_MOSI, _SPI_SS); #endif SPI.setDataMode(SPI_MODE0); @@ -814,12 +810,12 @@ void PxMATRIX::latch(uint16_t show_time ) { //digitalWrite(_OE_PIN,0); // <<< remove this digitalWrite(_LATCH_PIN,LOW); - digitalWrite(SPI_BUS_CLK,LOW); + digitalWrite(_SPI_CLK,LOW); for (uint8_t latch_count=0; latch_count<3; latch_count++) { - digitalWrite(SPI_BUS_CLK,HIGH); + digitalWrite(_SPI_CLK,HIGH); delayMicroseconds(1); - digitalWrite(SPI_BUS_CLK,LOW); + digitalWrite(_SPI_CLK,LOW); delayMicroseconds(1); } digitalWrite(_LATCH_PIN,HIGH); @@ -842,6 +838,16 @@ void PxMATRIX::display(uint16_t show_time) { #ifdef ESP8266 ESP.wdtFeed(); #endif + +uint8_t (*bufferp)[PxMATRIX_COLOR_DEPTH][buffer_size] = &PxMATRIX_buffer; + +#ifdef double_buffer + if(_active_buffer) + bufferp=&PxMATRIX_buffer2; + else + bufferp=&PxMATRIX_buffer; +#endif + for (uint8_t i=0;i<_row_pattern;i++) { if(_driver_chip == SHIFT) { @@ -861,11 +867,8 @@ void PxMATRIX::display(uint16_t show_time) { digitalWrite(_LATCH_PIN,LOW); delayMicroseconds(1); -#ifdef double_buffer - SPI.writeBytes(&PxMATRIX_buffer[_display_color][buffer_size*_active_buffer+i*_send_buffer_size],_send_buffer_size); -#else - SPI.writeBytes(&PxMATRIX_buffer[_display_color][i*_send_buffer_size],_send_buffer_size); -#endif + SPI.writeBytes(&(*bufferp)[_display_color][i*_send_buffer_size],_send_buffer_size); + while ((micros()-start_time)> (7 - bb)) & 1) == 1) - // GPIO_REG_SET( 1 << SPI_BUS_MOSI); + // GPIO_REG_SET( 1 << _SPI_MOSI); // else - // GPIO_REG_CLEAR( 1 << SPI_BUS_MOSI); - // GPIO_REG_SET( 1 << SPI_BUS_CLK); - // GPIO_REG_CLEAR( 1 << SPI_BUS_CLK); + // GPIO_REG_CLEAR( 1 << _SPI_MOSI); + // GPIO_REG_SET( 1 << _SPI_CLK); + // GPIO_REG_CLEAR( 1 << _SPI_CLK); // } // } - pinMode(SPI_BUS_CLK, SPECIAL); - pinMode(SPI_BUS_MOSI, SPECIAL); + pinMode(_SPI_CLK, SPECIAL); + pinMode(_SPI_MOSI, SPECIAL); - SPI.writeBytes(&PxMATRIX_buffer[_display_color][i*_send_buffer_size],_send_buffer_size-1); + SPI.writeBytes(&(*bufferp)[_display_color][i*_send_buffer_size],_send_buffer_size-1); - pinMode(SPI_BUS_CLK, OUTPUT); - pinMode(SPI_BUS_MOSI, OUTPUT); - pinMode(SPI_BUS_MISO, OUTPUT); - pinMode(SPI_BUS_SS, OUTPUT); + pinMode(_SPI_CLK, OUTPUT); + pinMode(_SPI_MOSI, OUTPUT); + pinMode(_SPI_MISO, OUTPUT); + pinMode(_SPI_SS, OUTPUT); set_mux(i); - uint8_t v = PxMATRIX_buffer[_display_color][i*_send_buffer_size + _send_buffer_size - 1]; + uint8_t v = (*bufferp)[_display_color][i*_send_buffer_size + _send_buffer_size - 1]; for (uint8_t this_byte = 0; this_byte < 8; this_byte++) { if (((v >> (7 - this_byte)) & 1)) - GPIO_REG_SET( 1 << SPI_BUS_MOSI); + GPIO_REG_SET( 1 << _SPI_MOSI); else - GPIO_REG_CLEAR( 1 << SPI_BUS_MOSI); - GPIO_REG_SET( 1 << SPI_BUS_CLK); - GPIO_REG_CLEAR( 1 << SPI_BUS_CLK); + GPIO_REG_CLEAR( 1 << _SPI_MOSI); + GPIO_REG_SET( 1 << _SPI_CLK); + GPIO_REG_CLEAR( 1 << _SPI_CLK); if (this_byte == 4) @@ -945,9 +943,6 @@ void PxMATRIX::display(uint16_t show_time) { if (_display_color>=PxMATRIX_COLOR_DEPTH) { _display_color=0; -#ifdef double_buffer - _active_buffer=_selected_buffer; -#endif } } @@ -1037,10 +1032,24 @@ void PxMATRIX::displayTestPixel(uint16_t show_time) { latch(show_time); } -// clear everything void PxMATRIX::clearDisplay(void) { - for(int this_color=0;this_color + +#ifdef ESP32 + +#define P_LAT 22 +#define P_A 19 +#define P_B 23 +#define P_C 18 +#define P_D 5 +#define P_E 15 +#define P_OE 2 +hw_timer_t * timer = NULL; +portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; + +#endif + +#ifdef ESP8266 + +#include +Ticker display_ticker; +#define P_LAT 16 +#define P_A 5 +#define P_B 4 +#define P_C 15 +#define P_D 12 +#define P_E 0 +#define P_OE 2 + +#endif +// Pins for LED MATRIX + +//PxMATRIX display(32,16,P_LAT, P_OE,P_A,P_B,P_C); +PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D); +//PxMATRIX display(64,64,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E); + +#ifdef ESP8266 +// ISR for display refresh +void display_updater() +{ + display.display(70); +} +#endif + +#ifdef ESP32 +void IRAM_ATTR display_updater(){ + // Increment the counter and set the time of ISR + portENTER_CRITICAL_ISR(&timerMux); + display.display(70); + portEXIT_CRITICAL_ISR(&timerMux); +} +#endif + +struct Text { + const char *text; + uint16_t width, height; + int16_t x, y; + int16_t dx, dy; +} text = {"Hello", 0, 0, 0, 0, 1, 1}; + + +uint16_t textColor = display.color565(0, 0, 255); +uint16_t myBLACK = display.color565(0, 0, 0); +uint16_t lineColor = display.color565(255, 0, 0); +uint16_t backgroundColor = display.color565(0, 255, 0); + +void setup() { + // put your setup code here, to run once: +Serial.begin(9600); + display.begin(16); + display.flushDisplay(); + display.setTextWrap(false); + + #ifdef ESP8266 + display_ticker.attach(0.002, display_updater); + #endif + + #ifdef ESP32 + timer = timerBegin(0, 80, true); + timerAttachInterrupt(timer, &display_updater, true); + timerAlarmWrite(timer, 2000, true); + timerAlarmEnable(timer); + #endif + + int16_t x1 = 0, y1 = 0; + display.getTextBounds(text.text, 0, 0, &x1, &y1, &text.width, &text.height); + text.width-=2; + text.height-=2; +} + +int16_t x=0, dx=1; + +void loop() { +// display.clearDisplay(); + display.fillScreen(backgroundColor); + + if(x+dx>=display.width() || x+dx<0) + dx=-dx; + x+=dx; + display.drawLine(x,0, display.width()-x-1, display.height()-1, lineColor); + + if(text.x+text.dx+text.width>=display.width() || text.x+text.dx<0) + text.dx=-text.dx; + if(text.y+text.dy+text.height>=display.height() || text.y+text.dy<0) + text.dy=-text.dy; + text.x+=text.dx; + text.y+=text.dy; + display.setTextColor(textColor); + display.setCursor(text.x, text.y); + display.print(text.text); + + display.showBuffer(); + delay(20); +} diff --git a/examples/override_spi_pins_esp32/override_spi_pins_esp32.ino b/examples/override_spi_pins_esp32/override_spi_pins_esp32.ino new file mode 100644 index 0000000..563622c --- /dev/null +++ b/examples/override_spi_pins_esp32/override_spi_pins_esp32.ino @@ -0,0 +1,217 @@ +/* ------------------------- + + This is the pixel time example but for use with + ESP32 boards that do not have the hardcoded SPI + pins used in the library broken out + + NOTE: This only works on the ESP32! + + This example is setup for the TinyPICO development board + which does not have pin 2 or pin 13 broken out to headers + + Pin 2 is usuall "P_OE" and gets defined with the pins + and passed into the constructor, we will replace + this with pin 26 + + Pin 13 is used for the MOSI pin for SPI within the library + but we can now override the default SPI pins by passing them + into the "display.begin" method in the setup, we will replace + pin 13 with pin 27 + + All other pins should be wired as an ESP32 as described + in the README + + ----------------------------*/ + + +#include + +#ifdef ESP32 + +#define P_LAT 22 +#define P_A 19 +#define P_B 23 +#define P_C 18 +#define P_D 5 +#define P_E 15 +#define P_OE 26 // For the TinyPICO +//#define P_OE 2 +hw_timer_t * timer = NULL; +portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; + +#endif + +#define matrix_width 32 +#define matrix_height 16 + +// This defines the 'on' time of the display is us. The larger this number, +// the brighter the display. If too large the ESP will crash +uint8_t display_draw_time = 10; //10-50 is usually fine + +//PxMATRIX display(matrix_width, matrix_height, P_LAT, P_OE, P_A, P_B, P_C); +PxMATRIX display(64,32,P_LAT, P_OE,P_A,P_B,P_C,P_D); +//PxMATRIX display(64,64,P_LAT, P_OE,P_A,P_B,P_C,P_D,P_E); + +// Some standard colors +uint16_t myRED = display.color565(255, 0, 0); +uint16_t myGREEN = display.color565(0, 255, 0); +uint16_t myBLUE = display.color565(0, 0, 255); +uint16_t myWHITE = display.color565(255, 255, 255); +uint16_t myYELLOW = display.color565(255, 255, 0); +uint16_t myCYAN = display.color565(0, 255, 255); +uint16_t myMAGENTA = display.color565(255, 0, 255); +uint16_t myBLACK = display.color565(0, 0, 0); + +uint16_t myCOLORS[8] = {myRED, myGREEN, myBLUE, myWHITE, myYELLOW, myCYAN, myMAGENTA, myBLACK}; + +uint8_t static weather_icons[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 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, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00 + , 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xff, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00 + , 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x20, 0x00, 0x00, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0xff, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0xff, 0x00, 0x20, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xdf, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xdf, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xdf, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 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, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 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, 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, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0x07, 0xdf, 0x07, 0xff, 0x07, 0xff, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xe0, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + +#ifdef ESP32 +void IRAM_ATTR display_updater() { +// Increment the counter and set the time of ISR +portENTER_CRITICAL_ISR(&timerMux); +display.display(display_draw_time); +portEXIT_CRITICAL_ISR(&timerMux); +} +#endif + + +void display_update_enable(bool is_enable) +{ + +#ifdef ESP32 +if (is_enable) +{ + timer = timerBegin(0, 80, true); + timerAttachInterrupt(timer, &display_updater, true); + timerAlarmWrite(timer, 2000, true); + timerAlarmEnable(timer); +} +else +{ + timerDetachInterrupt(timer); + timerAlarmDisable(timer); +} +#endif +} + + + +void setup() { +Serial.begin(9600); +// Define your display layout here, e.g. 1/8 step +//display.begin(8); +//begin(uint8_t row_pattern, uint8_t CLK, uint8_t MOSI, uint8_t MISO, uint8_t SS) +display.begin(16, SPI_BUS_CLK, 27, SPI_BUS_MISO, SPI_BUS_SS); + +// Define your scan pattern here {LINE, ZIGZAG, ZAGGIZ, WZAGZIG, VZAG} (default is LINE) +//display.setScanPattern(LINE); + +// Define multiplex implemention here {BINARY, STRAIGHT} (default is BINARY) +//display.setMuxPattern(BINARY); + +display.setFastUpdate(true); +display.clearDisplay(); +display.setTextColor(myCYAN); +display.setCursor(2, 0); +display.print("Pixel"); +display.setTextColor(myMAGENTA); +display.setCursor(2, 8); +display.print("Time"); +display_update_enable(true); + +delay(3000); + +} +union single_double { +uint8_t two[2]; +uint16_t one; +} this_single_double; + +// This draws the weather icons +void draw_weather_icon (uint8_t icon) +{ +if (icon > 10) + icon = 10; +for (int yy = 0; yy < 10; yy++) +{ + for (int xx = 0; xx < 10; xx++) + { + uint16_t byte_pos = (xx + icon * 10) * 2 + yy * 220; + this_single_double.two[1] = weather_icons[byte_pos]; + this_single_double.two[0] = weather_icons[byte_pos + 1]; + display.drawPixel(1 + xx, yy, this_single_double.one); + } +} +} + +unsigned long last_draw = 0; +void scroll_text(uint8_t ypos, unsigned long scroll_delay, String text, uint8_t colorR, uint8_t colorG, uint8_t colorB) +{ +uint16_t text_length = text.length(); +display.setTextWrap(false); // we don't wrap text so it scrolls nicely +display.setTextSize(1); +display.setRotation(0); +display.setTextColor(display.color565(colorR, colorG, colorB)); + +// Asuming 5 pixel average character width +for (int xpos = matrix_width; xpos > -(matrix_width + text_length * 5); xpos--) +{ + display.setTextColor(display.color565(colorR, colorG, colorB)); + display.clearDisplay(); + display.setCursor(xpos, ypos); + display.println(text); + delay(scroll_delay); + yield(); + + // This might smooth the transition a bit if we go slow + // display.setTextColor(display.color565(colorR/4,colorG/4,colorB/4)); + // display.setCursor(xpos-1,ypos); + // display.println(text); + + delay(scroll_delay / 5); + yield(); + +} +} + +uint8_t icon_index = 0; +void loop() { +scroll_text(1, 50, "Welcome to PxMatrix!", 96, 96, 250); +display.clearDisplay(); + +draw_weather_icon(icon_index); +icon_index++; +if (icon_index > 10) + icon_index = 0; + +for (int xx = 0; xx < 16; xx++) +{ + display.drawLine(xx + 16, 0, xx + 16, 5, display.color565(xx * 16, 0, 0)); + display.drawLine(xx + 16, 6, xx + 16, 10, display.color565(0, xx * 16, 0)); + display.drawLine(xx + 16, 11, xx + 16, 15, display.color565(0, 0, xx * 16)); +} +for (uint8_t dimm = 255; dimm > 0; dimm--) +{ + display.setBrightness(dimm); + delay(5); +} +for (uint8_t dimm = 0; dimm < 255; dimm++) +{ + display.setBrightness(dimm); + delay(5); +} + + +} + \ No newline at end of file