From bfb9cb6732ea3d909f8750d75b0bb5bdd722d48b Mon Sep 17 00:00:00 2001 From: rspaargaren Date: Sun, 28 Jun 2020 22:33:06 +0200 Subject: [PATCH] Max7219 in Dot Matrix configuration (#1053) * push final files * Update max7219digit.cpp reenter small bug fix on uint8 declaration * small debug * set max offset to 100 * remove unwanted file * Update font file to make travis happy * travis update * further progress in keeping Yarvis happy * travis font * travis will never be satisfied but one step ahead * YARVIS TAKE 10000000 * never ending yarvis * Almost there with Yarvis * removed double declaration YARVIS * added namespace to font file (TRAVIS) * almost there last changes for YARVIS * further travis updates * removed files for travis * fix display.py length of line travis remark * further update on display.py * file delete travis requirement * final entry for travis? * Some further debug on max offset * Travis updates * scroll_left_new * 90degreesrotate * added option to config rotate90 * four orientations for the chips * new setup for scroll * replaced small bug missing {} * debug changed int8 to int16 on scroll function * removed small merge failure * travis updates round 1 * travis updates round 2 * travis details round 3 * added options to set scroll parameters in yaml conf * removed ttf and png to satisfy travis * travis update * travis updates * travis * further updates after input from @glmnet * remove deleted comments * Added ENUM TYPE to config file * change in test file * removed test files * updates for pull request * Typing error removed * travis update * PR updates travis * Update test3.yaml * Update test3.yaml * update device schema as per #988 * Delete partitions.csv * repair on image display and invert routine * further update and a bit of cleanup * added writing 0 in draw pixel * small deletion error * travis updates * Update max7219digit.cpp adding intensity value to dynamically set value * Update max7219digit.h adding option for intensity * remove some files from tests --- esphome/components/max7219digit/__init__.py | 0 esphome/components/max7219digit/display.py | 63 ++++ .../components/max7219digit/max7219digit.cpp | 293 ++++++++++++++++++ .../components/max7219digit/max7219digit.h | 107 +++++++ esphome/components/max7219digit/max7219font.h | 268 ++++++++++++++++ tests/test3.yaml | 12 + 6 files changed, 743 insertions(+) create mode 100644 esphome/components/max7219digit/__init__.py create mode 100644 esphome/components/max7219digit/display.py create mode 100644 esphome/components/max7219digit/max7219digit.cpp create mode 100644 esphome/components/max7219digit/max7219digit.h create mode 100644 esphome/components/max7219digit/max7219font.h diff --git a/esphome/components/max7219digit/__init__.py b/esphome/components/max7219digit/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphome/components/max7219digit/display.py b/esphome/components/max7219digit/display.py new file mode 100644 index 0000000000..5bba71148c --- /dev/null +++ b/esphome/components/max7219digit/display.py @@ -0,0 +1,63 @@ +import esphome.codegen as cg +import esphome.config_validation as cv +from esphome.components import display, spi +from esphome.const import CONF_ID, CONF_INTENSITY, CONF_LAMBDA, CONF_NUM_CHIPS + +DEPENDENCIES = ['spi'] + +CONF_ROTATE_CHIP = 'rotate_chip' +CONF_SCROLL_SPEED = 'scroll_speed' +CONF_SCROLL_DWELL = 'scroll_dwell' +CONF_SCROLL_DELAY = 'scroll_delay' +CONF_SCROLL_ENABLE = 'scroll_enable' +CONF_SCROLL_MODE = 'scroll_mode' + +SCROLL_MODES = { + 'CONTINUOUS': 0, + 'STOP': 1, +} + +CHIP_MODES = { + '0': 0, + '90': 1, + '180': 2, + '270': 3, +} + +max7219_ns = cg.esphome_ns.namespace('max7219digit') +MAX7219Component = max7219_ns.class_('MAX7219Component', cg.PollingComponent, spi.SPIDevice, + display.DisplayBuffer) +MAX7219ComponentRef = MAX7219Component.operator('ref') + +CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ + cv.GenerateID(): cv.declare_id(MAX7219Component), + cv.Optional(CONF_NUM_CHIPS, default=4): cv.int_range(min=1, max=255), + cv.Optional(CONF_INTENSITY, default=15): cv.int_range(min=0, max=15), + cv.Optional(CONF_ROTATE_CHIP, default='0'): cv.enum(CHIP_MODES, upper=True), + cv.Optional(CONF_SCROLL_MODE, default='CONTINUOUS'): cv.enum(SCROLL_MODES, upper=True), + cv.Optional(CONF_SCROLL_ENABLE, default=True): cv.boolean, + cv.Optional(CONF_SCROLL_SPEED, default='250ms'): cv.positive_time_period_milliseconds, + cv.Optional(CONF_SCROLL_DELAY, default='1000ms'): cv.positive_time_period_milliseconds, + cv.Optional(CONF_SCROLL_DWELL, default='1000ms'): cv.positive_time_period_milliseconds, +}).extend(cv.polling_component_schema('500ms')).extend(spi.spi_device_schema(CS_PIN_required=True)) + + +def to_code(config): + var = cg.new_Pvariable(config[CONF_ID]) + yield cg.register_component(var, config) + yield spi.register_spi_device(var, config) + yield display.register_display(var, config) + + cg.add(var.set_num_chips(config[CONF_NUM_CHIPS])) + cg.add(var.set_intensity(config[CONF_INTENSITY])) + cg.add(var.set_chip_orientation(config[CONF_ROTATE_CHIP])) + cg.add(var.set_scroll_speed(config[CONF_SCROLL_SPEED])) + cg.add(var.set_scroll_dwell(config[CONF_SCROLL_DWELL])) + cg.add(var.set_scroll_delay(config[CONF_SCROLL_DELAY])) + cg.add(var.set_scroll(config[CONF_SCROLL_ENABLE])) + cg.add(var.set_scroll_mode(config[CONF_SCROLL_MODE])) + + if CONF_LAMBDA in config: + lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(MAX7219ComponentRef, 'it')], + return_type=cg.void) + cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/max7219digit/max7219digit.cpp b/esphome/components/max7219digit/max7219digit.cpp new file mode 100644 index 0000000000..b19f05143f --- /dev/null +++ b/esphome/components/max7219digit/max7219digit.cpp @@ -0,0 +1,293 @@ +#include "max7219digit.h" +#include "esphome/core/log.h" +#include "esphome/core/helpers.h" +#include "max7219font.h" + +namespace esphome { +namespace max7219digit { + +static const char *TAG = "max7219DIGIT"; + +static const uint8_t MAX7219_REGISTER_NOOP = 0x00; +static const uint8_t MAX7219_REGISTER_DECODE_MODE = 0x09; +static const uint8_t MAX7219_REGISTER_INTENSITY = 0x0A; +static const uint8_t MAX7219_REGISTER_SCAN_LIMIT = 0x0B; +static const uint8_t MAX7219_REGISTER_SHUTDOWN = 0x0C; +static const uint8_t MAX7219_REGISTER_DISPLAY_TEST = 0x0F; +constexpr uint8_t MAX7219_NO_SHUTDOWN = 0x00; +constexpr uint8_t MAX7219_SHUTDOWN = 0x01; +constexpr uint8_t MAX7219_NO_DISPLAY_TEST = 0x00; +constexpr uint8_t MAX7219_DISPLAY_TEST = 0x01; + +float MAX7219Component::get_setup_priority() const { return setup_priority::PROCESSOR; } + +void MAX7219Component::setup() { + ESP_LOGCONFIG(TAG, "Setting up MAX7219_DIGITS..."); + this->spi_setup(); + this->stepsleft_ = 0; + this->max_displaybuffer_.reserve(500); // Create base space to write buffer + // Initialize buffer with 0 for display so all non written pixels are blank + this->max_displaybuffer_.resize(this->num_chips_ * 8, 0); + // let's assume the user has all 8 digits connected, only important in daisy chained setups anyway + this->send_to_all_(MAX7219_REGISTER_SCAN_LIMIT, 7); + // let's use our own ASCII -> led pattern encoding + this->send_to_all_(MAX7219_REGISTER_DECODE_MODE, 0); + // No display test with all the pixels on + this->send_to_all_(MAX7219_REGISTER_DISPLAY_TEST, MAX7219_NO_DISPLAY_TEST); + // SET Intsity of display + this->send_to_all_(MAX7219_REGISTER_INTENSITY, this->intensity_); + // this->send_to_all_(MAX7219_REGISTER_INTENSITY, 1); + this->display(); + // power up + this->send_to_all_(MAX7219_REGISTER_SHUTDOWN, 1); +} + +void MAX7219Component::dump_config() { + ESP_LOGCONFIG(TAG, "MAX7219DIGIT:"); + ESP_LOGCONFIG(TAG, " Number of Chips: %u", this->num_chips_); + ESP_LOGCONFIG(TAG, " Intensity: %u", this->intensity_); + ESP_LOGCONFIG(TAG, " Scroll Mode: %u", this->scroll_mode_); + ESP_LOGCONFIG(TAG, " Scroll Speed: %u", this->scroll_speed_); + ESP_LOGCONFIG(TAG, " Scroll Dwell: %u", this->scroll_dwell_); + ESP_LOGCONFIG(TAG, " Scroll Delay: %u", this->scroll_delay_); + LOG_PIN(" CS Pin: ", this->cs_); + LOG_UPDATE_INTERVAL(this); +} + +void MAX7219Component::loop() { + unsigned long now = millis(); + + // check if the buffer has shrunk past the current position since last update + if ((this->max_displaybuffer_.size() >= this->old_buffer_size_ + 3) || + (this->max_displaybuffer_.size() <= this->old_buffer_size_ - 3)) { + this->stepsleft_ = 0; + this->display(); + this->old_buffer_size_ = this->max_displaybuffer_.size(); + } + + // Reset the counter back to 0 when full string has been displayed. + if (this->stepsleft_ > this->max_displaybuffer_.size()) + this->stepsleft_ = 0; + + // Return if there is no need to scroll or scroll is off + if (!this->scroll_ || (this->max_displaybuffer_.size() <= this->num_chips_ * 8)) { + this->display(); + return; + } + + if ((this->stepsleft_ == 0) && (now - this->last_scroll_ < this->scroll_delay_)) { + this->display(); + return; + } + + // Dwell time at end of string in case of stop at end + if (this->scroll_mode_ == 1) { + if (this->stepsleft_ >= this->max_displaybuffer_.size() - this->num_chips_ * 8 + 1) { + if (now - this->last_scroll_ >= this->scroll_dwell_) { + this->stepsleft_ = 0; + this->last_scroll_ = now; + this->display(); + } + return; + } + } + + // Actual call to scroll left action + if (now - this->last_scroll_ >= this->scroll_speed_) { + this->last_scroll_ = now; + this->scroll_left(); + this->display(); + } +} + +void MAX7219Component::display() { + byte pixels[8]; + // Run this loop for every MAX CHIP (GRID OF 64 leds) + // Run this routine for the rows of every chip 8x row 0 top to 7 bottom + // Fill the pixel parameter with diplay data + // Send the data to the chip + for (uint8_t i = 0; i < this->num_chips_; i++) { + for (uint8_t j = 0; j < 8; j++) { + pixels[j] = this->max_displaybuffer_[i * 8 + j]; + } + this->send64pixels(i, pixels); + } +} + +int MAX7219Component::get_height_internal() { + return 8; // TO BE DONE -> STACK TWO DISPLAYS ON TOP OF EACH OTHE + // TO BE DONE -> CREATE Virtual size of screen and scroll +} + +int MAX7219Component::get_width_internal() { return this->num_chips_ * 8; } + +size_t MAX7219Component::get_buffer_length_() { return this->num_chips_ * 8; } + +void HOT MAX7219Component::draw_absolute_pixel_internal(int x, int y, int color) { + if (x + 1 > this->max_displaybuffer_.size()) { // Extend the display buffer in case required + this->max_displaybuffer_.resize(x + 1, this->bckgrnd_); + } + + if (y >= this->get_height_internal() || y < 0) // If pixel is outside display then dont draw + return; + + uint16_t pos = x; // X is starting at 0 top left + uint8_t subpos = y; // Y is starting at 0 top left + + if (color == 1) { + this->max_displaybuffer_[pos] |= (1 << subpos); + } else { + this->max_displaybuffer_[pos] &= ~(1 << subpos); + } +} + +void MAX7219Component::send_byte_(uint8_t a_register, uint8_t data) { + this->write_byte(a_register); // Write register value to MAX + this->write_byte(data); // Followed by actual data +} +void MAX7219Component::send_to_all_(uint8_t a_register, uint8_t data) { + this->enable(); // Enable SPI + for (uint8_t i = 0; i < this->num_chips_; i++) // Run the loop for every MAX chip in the stack + this->send_byte_(a_register, data); // Send the data to the chips + this->disable(); // Disable SPI +} +void MAX7219Component::update() { + this->update_ = true; + this->max_displaybuffer_.clear(); + this->max_displaybuffer_.resize(this->num_chips_ * 8, this->bckgrnd_); + if (this->writer_local_.has_value()) // insert Labda function if available + (*this->writer_local_)(*this); +} + +void MAX7219Component::invert_on_off(bool on_off) { this->invert_ = on_off; }; +void MAX7219Component::invert_on_off() { this->invert_ = !this->invert_; }; + +void MAX7219Component::turn_on_off(bool on_off) { + if (on_off) { + this->send_to_all_(MAX7219_REGISTER_SHUTDOWN, 1); + } else { + this->send_to_all_(MAX7219_REGISTER_SHUTDOWN, 0); + } +} + +void MAX7219Component::scroll(bool on_off, uint8_t mode, uint16_t speed, uint16_t delay, uint16_t dwell) { + this->set_scroll(on_off); + this->set_scroll_mode(mode); + this->set_scroll_speed(speed); + this->set_scroll_dwell(dwell); + this->set_scroll_delay(delay); +} + +void MAX7219Component::scroll(bool on_off, uint8_t mode) { + this->set_scroll(on_off); + this->set_scroll_mode(mode); +} + +void MAX7219Component::intensity(uint8_t intensity) { + this->intensity_ = intensity; + this->send_to_all_(MAX7219_REGISTER_INTENSITY, this->intensity_); +} + +void MAX7219Component::scroll(bool on_off) { this->set_scroll(on_off); } + +void MAX7219Component::scroll_left() { + if (this->update_) { + this->max_displaybuffer_.push_back(this->bckgrnd_); + for (uint16_t i = 0; i < this->stepsleft_; i++) { + this->max_displaybuffer_.push_back(this->max_displaybuffer_.front()); + this->max_displaybuffer_.erase(this->max_displaybuffer_.begin()); + this->update_ = false; + } + } else { + this->max_displaybuffer_.push_back(this->max_displaybuffer_.front()); + this->max_displaybuffer_.erase(this->max_displaybuffer_.begin()); + } + this->stepsleft_++; +} + +void MAX7219Component::send_char(byte chip, byte data) { + // get this character from PROGMEM + for (byte i = 0; i < 8; i++) + this->max_displaybuffer_[chip * 8 + i] = pgm_read_byte(&MAX7219_DOT_MATRIX_FONT[data][i]); +} // end of send_char + +// send one character (data) to position (chip) + +void MAX7219Component::send64pixels(byte chip, const byte pixels[8]) { + for (byte col = 0; col < 8; col++) { // RUN THIS LOOP 8 times until column is 7 + this->enable(); // start sending by enabling SPI + for (byte i = 0; i < chip; i++) // send extra NOPs to push the pixels out to extra displays + this->send_byte_(MAX7219_REGISTER_NOOP, + MAX7219_REGISTER_NOOP); // run this loop unit the matching chip is reached + byte b = 0; // rotate pixels 90 degrees -- set byte to 0 + if (this->orientation_ == 0) { + for (byte i = 0; i < 8; i++) // run this loop 8 times for all the pixels[8] received + b |= bitRead(pixels[i], col) << (7 - i); // change the column bits into row bits + } else if (this->orientation_ == 1) { + b = pixels[col]; + } else if (this->orientation_ == 2) { + for (byte i = 0; i < 8; i++) + b |= bitRead(pixels[i], 7 - col) << (7 - i); + } else { + b = pixels[7 - col]; + } + // send this byte to dispay at selected chip + if (this->invert_) { + this->send_byte_(col + 1, ~b); + } else { + this->send_byte_(col + 1, b); + } + for (int i = 0; i < this->num_chips_ - chip - 1; i++) // end with enough NOPs so later chips don't update + this->send_byte_(MAX7219_REGISTER_NOOP, MAX7219_REGISTER_NOOP); + this->disable(); // all done disable SPI + } // end of for each column +} // end of send64pixels + +uint8_t MAX7219Component::printdigit(const char *str) { return this->printdigit(0, str); } + +uint8_t MAX7219Component::printdigit(uint8_t start_pos, const char *s) { + byte chip; + for (chip = start_pos; chip < this->num_chips_ && *s; chip++) + send_char(chip, *s++); + // space out rest + while (chip < (this->num_chips_)) + send_char(chip++, ' '); + return 0; +} // end of sendString + +uint8_t MAX7219Component::printdigitf(uint8_t pos, const char *format, ...) { + va_list arg; + va_start(arg, format); + char buffer[64]; + int ret = vsnprintf(buffer, sizeof(buffer), format, arg); + va_end(arg); + if (ret > 0) + return this->printdigit(pos, buffer); + return 0; +} +uint8_t MAX7219Component::printdigitf(const char *format, ...) { + va_list arg; + va_start(arg, format); + char buffer[64]; + int ret = vsnprintf(buffer, sizeof(buffer), format, arg); + va_end(arg); + if (ret > 0) + return this->printdigit(buffer); + return 0; +} + +#ifdef USE_TIME +uint8_t MAX7219Component::strftimedigit(uint8_t pos, const char *format, time::ESPTime time) { + char buffer[64]; + size_t ret = time.strftime(buffer, sizeof(buffer), format); + if (ret > 0) + return this->printdigit(pos, buffer); + return 0; +} +uint8_t MAX7219Component::strftimedigit(const char *format, time::ESPTime time) { + return this->strftimedigit(0, format, time); +} +#endif + +} // namespace max7219digit +} // namespace esphome diff --git a/esphome/components/max7219digit/max7219digit.h b/esphome/components/max7219digit/max7219digit.h new file mode 100644 index 0000000000..b032f33b58 --- /dev/null +++ b/esphome/components/max7219digit/max7219digit.h @@ -0,0 +1,107 @@ +#pragma once + +#include "esphome/core/component.h" +#include "esphome/core/defines.h" +#include "esphome/components/display/display_buffer.h" +#include "esphome/components/spi/spi.h" + +#ifdef USE_TIME +#include "esphome/components/time/real_time_clock.h" +#endif + +namespace esphome { +namespace max7219digit { + +class MAX7219Component; + +using max7219_writer_t = std::function; + +class MAX7219Component : public PollingComponent, + public display::DisplayBuffer, + public spi::SPIDevice { + public: + void set_writer(max7219_writer_t &&writer) { this->writer_local_ = writer; }; + + void setup() override; + + void loop() override; + + void dump_config() override; + + void update() override; + + float get_setup_priority() const override; + + void display(); + + void invert_on_off(bool on_off); + void invert_on_off(); + + void turn_on_off(bool on_off); + + void draw_absolute_pixel_internal(int x, int y, int color) override; + int get_height_internal() override; + int get_width_internal() override; + + void set_intensity(uint8_t intensity) { this->intensity_ = intensity; }; + void set_num_chips(uint8_t num_chips) { this->num_chips_ = num_chips; }; + void set_chip_orientation(uint8_t rotate) { this->orientation_ = rotate; }; + void set_scroll_speed(uint16_t speed) { this->scroll_speed_ = speed; }; + void set_scroll_dwell(uint16_t dwell) { this->scroll_dwell_ = dwell; }; + void set_scroll_delay(uint16_t delay) { this->scroll_delay_ = delay; }; + void set_scroll(bool on_off) { this->scroll_ = on_off; }; + void set_scroll_mode(uint8_t mode) { this->scroll_mode_ = mode; }; + + void send_char(byte chip, byte data); + void send64pixels(byte chip, const byte pixels[8]); + + void scroll_left(); + void scroll(bool on_off, uint8_t mode, uint16_t speed, uint16_t delay, uint16_t dwell); + void scroll(bool on_off, uint8_t mode); + void scroll(bool on_off); + void intensity(uint8_t intensity); + + /// Evaluate the printf-format and print the result at the given position. + uint8_t printdigitf(uint8_t pos, const char *format, ...) __attribute__((format(printf, 3, 4))); + /// Evaluate the printf-format and print the result at position 0. + uint8_t printdigitf(const char *format, ...) __attribute__((format(printf, 2, 3))); + + /// Print `str` at the given position. + uint8_t printdigit(uint8_t pos, const char *str); + /// Print `str` at position 0. + uint8_t printdigit(const char *str); + +#ifdef USE_TIME + /// Evaluate the strftime-format and print the result at the given position. + uint8_t strftimedigit(uint8_t pos, const char *format, time::ESPTime time) __attribute__((format(strftime, 3, 0))); + + /// Evaluate the strftime-format and print the result at position 0. + uint8_t strftimedigit(const char *format, time::ESPTime time) __attribute__((format(strftime, 2, 0))); +#endif + + protected: + void send_byte_(uint8_t a_register, uint8_t data); + void send_to_all_(uint8_t a_register, uint8_t data); + + uint8_t intensity_; /// Intensity of the display from 0 to 15 (most) + uint8_t num_chips_; + bool scroll_; + bool update_{false}; + uint16_t scroll_speed_; + uint16_t scroll_delay_; + uint16_t scroll_dwell_; + uint16_t old_buffer_size_ = 0; + uint8_t scroll_mode_; + bool invert_ = false; + uint8_t orientation_; + uint8_t bckgrnd_ = 0x0; + std::vector max_displaybuffer_; + unsigned long last_scroll_ = 0; + uint16_t stepsleft_; + size_t get_buffer_length_(); + optional writer_local_{}; +}; + +} // namespace max7219digit +} // namespace esphome diff --git a/esphome/components/max7219digit/max7219font.h b/esphome/components/max7219digit/max7219font.h new file mode 100644 index 0000000000..3d42d1cc2d --- /dev/null +++ b/esphome/components/max7219digit/max7219font.h @@ -0,0 +1,268 @@ +#pragma once + +namespace esphome { +namespace max7219digit { + +// bit patterns for the CP437 font + +const byte MAX7219_DOT_MATRIX_FONT[256][8] PROGMEM = { + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0x00 + {0x7E, 0x81, 0x95, 0xB1, 0xB1, 0x95, 0x81, 0x7E}, // 0x01 + {0x7E, 0xFF, 0xEB, 0xCF, 0xCF, 0xEB, 0xFF, 0x7E}, // 0x02 + {0x0E, 0x1F, 0x3F, 0x7E, 0x3F, 0x1F, 0x0E, 0x00}, // 0x03 + {0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08, 0x00}, // 0x04 + {0x18, 0xBA, 0xFF, 0xFF, 0xFF, 0xBA, 0x18, 0x00}, // 0x05 + {0x10, 0xB8, 0xFC, 0xFF, 0xFC, 0xB8, 0x10, 0x00}, // 0x06 + {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00}, // 0x07 + {0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF}, // 0x08 + {0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00}, // 0x09 + {0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF}, // 0x0A + {0x70, 0xF8, 0x88, 0x88, 0xFD, 0x7F, 0x07, 0x0F}, // 0x0B + {0x00, 0x4E, 0x5F, 0xF1, 0xF1, 0x5F, 0x4E, 0x00}, // 0x0C + {0xC0, 0xE0, 0xFF, 0x7F, 0x05, 0x05, 0x07, 0x07}, // 0x0D + {0xC0, 0xFF, 0x7F, 0x05, 0x05, 0x65, 0x7F, 0x3F}, // 0x0E + {0x99, 0x5A, 0x3C, 0xE7, 0xE7, 0x3C, 0x5A, 0x99}, // 0x0F + {0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08, 0x08, 0x00}, // 0x10 + {0x08, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x00}, // 0x11 + {0x00, 0x24, 0x66, 0xFF, 0xFF, 0x66, 0x24, 0x00}, // 0x12 + {0x00, 0x5F, 0x5F, 0x00, 0x00, 0x5F, 0x5F, 0x00}, // 0x13 + {0x06, 0x0F, 0x09, 0x7F, 0x7F, 0x01, 0x7F, 0x7F}, // 0x14 + {0x40, 0xDA, 0xBF, 0xA5, 0xFD, 0x59, 0x03, 0x02}, // 0x15 + {0x00, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x00}, // 0x16 + {0x80, 0x94, 0xB6, 0xFF, 0xFF, 0xB6, 0x94, 0x80}, // 0x17 + {0x00, 0x04, 0x06, 0x7F, 0x7F, 0x06, 0x04, 0x00}, // 0x18 + {0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00}, // 0x19 + {0x08, 0x08, 0x08, 0x2A, 0x3E, 0x1C, 0x08, 0x00}, // 0x1A + {0x08, 0x1C, 0x3E, 0x2A, 0x08, 0x08, 0x08, 0x00}, // 0x1B + {0x3C, 0x3C, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // 0x1C + {0x08, 0x1C, 0x3E, 0x08, 0x08, 0x3E, 0x1C, 0x08}, // 0x1D + {0x30, 0x38, 0x3C, 0x3E, 0x3E, 0x3C, 0x38, 0x30}, // 0x1E + {0x06, 0x0E, 0x1E, 0x3E, 0x3E, 0x1E, 0x0E, 0x06}, // 0x1F + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // ' ' + {0x00, 0x06, 0x5F, 0x5F, 0x06, 0x00, 0x00, 0x00}, // '!' + {0x00, 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x00}, // '"' + {0x14, 0x7F, 0x7F, 0x14, 0x7F, 0x7F, 0x14, 0x00}, // '#' + {0x24, 0x2E, 0x6B, 0x6B, 0x3A, 0x12, 0x00, 0x00}, // '$' + {0x46, 0x66, 0x30, 0x18, 0x0C, 0x66, 0x62, 0x00}, // '%' + {0x30, 0x7A, 0x4F, 0x5D, 0x37, 0x7A, 0x48, 0x00}, // '&' + {0x04, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00}, // ''' + {0x00, 0x1C, 0x3E, 0x63, 0x41, 0x00, 0x00, 0x00}, // '(' + {0x00, 0x41, 0x63, 0x3E, 0x1C, 0x00, 0x00, 0x00}, // ')' + {0x08, 0x2A, 0x3E, 0x1C, 0x1C, 0x3E, 0x2A, 0x08}, // '*' + {0x08, 0x08, 0x3E, 0x3E, 0x08, 0x08, 0x00, 0x00}, // '+' + {0x00, 0x80, 0xE0, 0x60, 0x00, 0x00, 0x00, 0x00}, // ',' + {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, // '-' + {0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00}, // '.' + {0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00}, // '/' + {0x3E, 0x7F, 0x71, 0x59, 0x4D, 0x7F, 0x3E, 0x00}, // '0' + {0x40, 0x42, 0x7F, 0x7F, 0x40, 0x40, 0x00, 0x00}, // '1' + {0x62, 0x73, 0x59, 0x49, 0x6F, 0x66, 0x00, 0x00}, // '2' + {0x22, 0x63, 0x49, 0x49, 0x7F, 0x36, 0x00, 0x00}, // '3' + {0x18, 0x1C, 0x16, 0x53, 0x7F, 0x7F, 0x50, 0x00}, // '4' + {0x27, 0x67, 0x45, 0x45, 0x7D, 0x39, 0x00, 0x00}, // '5' + {0x3C, 0x7E, 0x4B, 0x49, 0x79, 0x30, 0x00, 0x00}, // '6' + {0x03, 0x03, 0x71, 0x79, 0x0F, 0x07, 0x00, 0x00}, // '7' + {0x36, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00, 0x00}, // '8' + {0x06, 0x4F, 0x49, 0x69, 0x3F, 0x1E, 0x00, 0x00}, // '9' + {0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00}, // ':' + {0x00, 0x80, 0xE6, 0x66, 0x00, 0x00, 0x00, 0x00}, // ';' + {0x08, 0x1C, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00}, // '<' + {0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00}, // '=' + {0x00, 0x41, 0x63, 0x36, 0x1C, 0x08, 0x00, 0x00}, // '>' + {0x02, 0x03, 0x51, 0x59, 0x0F, 0x06, 0x00, 0x00}, // '?' + {0x3E, 0x7F, 0x41, 0x5D, 0x5D, 0x1F, 0x1E, 0x00}, // '@' + {0x7C, 0x7E, 0x13, 0x13, 0x7E, 0x7C, 0x00, 0x00}, // 'A' + {0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}, // 'B' + {0x1C, 0x3E, 0x63, 0x41, 0x41, 0x63, 0x22, 0x00}, // 'C' + {0x41, 0x7F, 0x7F, 0x41, 0x63, 0x3E, 0x1C, 0x00}, // 'D' + {0x41, 0x7F, 0x7F, 0x49, 0x5D, 0x41, 0x63, 0x00}, // 'E' + {0x41, 0x7F, 0x7F, 0x49, 0x1D, 0x01, 0x03, 0x00}, // 'F' + {0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00}, // 'G' + {0x7F, 0x7F, 0x08, 0x08, 0x7F, 0x7F, 0x00, 0x00}, // 'H' + {0x00, 0x41, 0x7F, 0x7F, 0x41, 0x00, 0x00, 0x00}, // 'I' + {0x30, 0x70, 0x40, 0x41, 0x7F, 0x3F, 0x01, 0x00}, // 'J' + {0x41, 0x7F, 0x7F, 0x08, 0x1C, 0x77, 0x63, 0x00}, // 'K' + {0x41, 0x7F, 0x7F, 0x41, 0x40, 0x60, 0x70, 0x00}, // 'L' + {0x7F, 0x7F, 0x0E, 0x1C, 0x0E, 0x7F, 0x7F, 0x00}, // 'M' + {0x7F, 0x7F, 0x06, 0x0C, 0x18, 0x7F, 0x7F, 0x00}, // 'N' + {0x1C, 0x3E, 0x63, 0x41, 0x63, 0x3E, 0x1C, 0x00}, // 'O' + {0x41, 0x7F, 0x7F, 0x49, 0x09, 0x0F, 0x06, 0x00}, // 'P' + {0x1E, 0x3F, 0x21, 0x71, 0x7F, 0x5E, 0x00, 0x00}, // 'Q' + {0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00}, // 'R' + {0x26, 0x6F, 0x4D, 0x59, 0x73, 0x32, 0x00, 0x00}, // 'S' + {0x03, 0x41, 0x7F, 0x7F, 0x41, 0x03, 0x00, 0x00}, // 'T' + {0x7F, 0x7F, 0x40, 0x40, 0x7F, 0x7F, 0x00, 0x00}, // 'U' + {0x1F, 0x3F, 0x60, 0x60, 0x3F, 0x1F, 0x00, 0x00}, // 'V' + {0x7F, 0x7F, 0x30, 0x18, 0x30, 0x7F, 0x7F, 0x00}, // 'W' + {0x43, 0x67, 0x3C, 0x18, 0x3C, 0x67, 0x43, 0x00}, // 'X' + {0x07, 0x4F, 0x78, 0x78, 0x4F, 0x07, 0x00, 0x00}, // 'Y' + {0x47, 0x63, 0x71, 0x59, 0x4D, 0x67, 0x73, 0x00}, // 'Z' + {0x00, 0x7F, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00}, // '[' + {0x01, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00}, // backslash + {0x00, 0x41, 0x41, 0x7F, 0x7F, 0x00, 0x00, 0x00}, // ']' + {0x08, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x08, 0x00}, // '^' + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, // '_' + {0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x00}, // '`' + {0x20, 0x74, 0x54, 0x54, 0x3C, 0x78, 0x40, 0x00}, // 'a' + {0x41, 0x7F, 0x3F, 0x48, 0x48, 0x78, 0x30, 0x00}, // 'b' + {0x38, 0x7C, 0x44, 0x44, 0x6C, 0x28, 0x00, 0x00}, // 'c' + {0x30, 0x78, 0x48, 0x49, 0x3F, 0x7F, 0x40, 0x00}, // 'd' + {0x38, 0x7C, 0x54, 0x54, 0x5C, 0x18, 0x00, 0x00}, // 'e' + {0x48, 0x7E, 0x7F, 0x49, 0x03, 0x02, 0x00, 0x00}, // 'f' + {0x98, 0xBC, 0xA4, 0xA4, 0xF8, 0x7C, 0x04, 0x00}, // 'g' + {0x41, 0x7F, 0x7F, 0x08, 0x04, 0x7C, 0x78, 0x00}, // 'h' + {0x00, 0x44, 0x7D, 0x7D, 0x40, 0x00, 0x00, 0x00}, // 'i' + {0x60, 0xE0, 0x80, 0x80, 0xFD, 0x7D, 0x00, 0x00}, // 'j' + {0x41, 0x7F, 0x7F, 0x10, 0x38, 0x6C, 0x44, 0x00}, // 'k' + {0x00, 0x41, 0x7F, 0x7F, 0x40, 0x00, 0x00, 0x00}, // 'l' + {0x7C, 0x7C, 0x18, 0x38, 0x1C, 0x7C, 0x78, 0x00}, // 'm' + {0x7C, 0x7C, 0x04, 0x04, 0x7C, 0x78, 0x00, 0x00}, // 'n' + {0x38, 0x7C, 0x44, 0x44, 0x7C, 0x38, 0x00, 0x00}, // 'o' + {0x84, 0xFC, 0xF8, 0xA4, 0x24, 0x3C, 0x18, 0x00}, // 'p' + {0x18, 0x3C, 0x24, 0xA4, 0xF8, 0xFC, 0x84, 0x00}, // 'q' + {0x44, 0x7C, 0x78, 0x4C, 0x04, 0x1C, 0x18, 0x00}, // 'r' + {0x48, 0x5C, 0x54, 0x54, 0x74, 0x24, 0x00, 0x00}, // 's' + {0x00, 0x04, 0x3E, 0x7F, 0x44, 0x24, 0x00, 0x00}, // 't' + {0x3C, 0x7C, 0x40, 0x40, 0x3C, 0x7C, 0x40, 0x00}, // 'u' + {0x1C, 0x3C, 0x60, 0x60, 0x3C, 0x1C, 0x00, 0x00}, // 'v' + {0x3C, 0x7C, 0x70, 0x38, 0x70, 0x7C, 0x3C, 0x00}, // 'w' + {0x44, 0x6C, 0x38, 0x10, 0x38, 0x6C, 0x44, 0x00}, // 'x' + {0x9C, 0xBC, 0xA0, 0xA0, 0xFC, 0x7C, 0x00, 0x00}, // 'y' + {0x4C, 0x64, 0x74, 0x5C, 0x4C, 0x64, 0x00, 0x00}, // 'z' + {0x08, 0x08, 0x3E, 0x77, 0x41, 0x41, 0x00, 0x00}, // '{' + {0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x00}, // '|' + {0x41, 0x41, 0x77, 0x3E, 0x08, 0x08, 0x00, 0x00}, // '}' + {0x02, 0x03, 0x01, 0x03, 0x02, 0x03, 0x01, 0x00}, // '~' + {0x70, 0x78, 0x4C, 0x46, 0x4C, 0x78, 0x70, 0x00}, // 0x7F + {0x0E, 0x9F, 0x91, 0xB1, 0xFB, 0x4A, 0x00, 0x00}, // 0x80 + {0x3A, 0x7A, 0x40, 0x40, 0x7A, 0x7A, 0x40, 0x00}, // 0x81 + {0x38, 0x7C, 0x54, 0x55, 0x5D, 0x19, 0x00, 0x00}, // 0x82 + {0x02, 0x23, 0x75, 0x55, 0x55, 0x7D, 0x7B, 0x42}, // 0x83 + {0x21, 0x75, 0x54, 0x54, 0x7D, 0x79, 0x40, 0x00}, // 0x84 + {0x21, 0x75, 0x55, 0x54, 0x7C, 0x78, 0x40, 0x00}, // 0x85 + {0x20, 0x74, 0x57, 0x57, 0x7C, 0x78, 0x40, 0x00}, // 0x86 + {0x18, 0x3C, 0xA4, 0xA4, 0xE4, 0x40, 0x00, 0x00}, // 0x87 + {0x02, 0x3B, 0x7D, 0x55, 0x55, 0x5D, 0x1B, 0x02}, // 0x88 + {0x39, 0x7D, 0x54, 0x54, 0x5D, 0x19, 0x00, 0x00}, // 0x89 + {0x39, 0x7D, 0x55, 0x54, 0x5C, 0x18, 0x00, 0x00}, // 0x8A + {0x01, 0x45, 0x7C, 0x7C, 0x41, 0x01, 0x00, 0x00}, // 0x8B + {0x02, 0x03, 0x45, 0x7D, 0x7D, 0x43, 0x02, 0x00}, // 0x8C + {0x01, 0x45, 0x7D, 0x7C, 0x40, 0x00, 0x00, 0x00}, // 0x8D + {0x79, 0x7D, 0x16, 0x12, 0x16, 0x7D, 0x79, 0x00}, // 0x8E + {0x70, 0x78, 0x2B, 0x2B, 0x78, 0x70, 0x00, 0x00}, // 0x8F + {0x44, 0x7C, 0x7C, 0x55, 0x55, 0x45, 0x00, 0x00}, // 0x90 + {0x20, 0x74, 0x54, 0x54, 0x7C, 0x7C, 0x54, 0x54}, // 0x91 + {0x7C, 0x7E, 0x0B, 0x09, 0x7F, 0x7F, 0x49, 0x00}, // 0x92 + {0x32, 0x7B, 0x49, 0x49, 0x7B, 0x32, 0x00, 0x00}, // 0x93 + {0x32, 0x7A, 0x48, 0x48, 0x7A, 0x32, 0x00, 0x00}, // 0x94 + {0x32, 0x7A, 0x4A, 0x48, 0x78, 0x30, 0x00, 0x00}, // 0x95 + {0x3A, 0x7B, 0x41, 0x41, 0x7B, 0x7A, 0x40, 0x00}, // 0x96 + {0x3A, 0x7A, 0x42, 0x40, 0x78, 0x78, 0x40, 0x00}, // 0x97 + {0x9A, 0xBA, 0xA0, 0xA0, 0xFA, 0x7A, 0x00, 0x00}, // 0x98 + {0x01, 0x19, 0x3C, 0x66, 0x66, 0x3C, 0x19, 0x01}, // 0x99 + {0x3D, 0x7D, 0x40, 0x40, 0x7D, 0x3D, 0x00, 0x00}, // 0x9A + {0x18, 0x3C, 0x24, 0xE7, 0xE7, 0x24, 0x24, 0x00}, // 0x9B + {0x68, 0x7E, 0x7F, 0x49, 0x43, 0x66, 0x20, 0x00}, // 0x9C + {0x2B, 0x2F, 0xFC, 0xFC, 0x2F, 0x2B, 0x00, 0x00}, // 0x9D + {0xFF, 0xFF, 0x09, 0x09, 0x2F, 0xF6, 0xF8, 0xA0}, // 0x9E + {0x40, 0xC0, 0x88, 0xFE, 0x7F, 0x09, 0x03, 0x02}, // 0x9F + {0x20, 0x74, 0x54, 0x55, 0x7D, 0x79, 0x40, 0x00}, // 0xA0 + {0x00, 0x44, 0x7D, 0x7D, 0x41, 0x00, 0x00, 0x00}, // 0xA1 + {0x30, 0x78, 0x48, 0x4A, 0x7A, 0x32, 0x00, 0x00}, // 0xA2 + {0x38, 0x78, 0x40, 0x42, 0x7A, 0x7A, 0x40, 0x00}, // 0xA3 + {0x7A, 0x7A, 0x0A, 0x0A, 0x7A, 0x70, 0x00, 0x00}, // 0xA4 + {0x7D, 0x7D, 0x19, 0x31, 0x7D, 0x7D, 0x00, 0x00}, // 0xA5 + {0x00, 0x26, 0x2F, 0x29, 0x2F, 0x2F, 0x28, 0x00}, // 0xA6 + {0x00, 0x26, 0x2F, 0x29, 0x2F, 0x26, 0x00, 0x00}, // 0xA7 + {0x30, 0x78, 0x4D, 0x45, 0x60, 0x20, 0x00, 0x00}, // 0xA8 + {0x38, 0x38, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, // 0xA9 + {0x08, 0x08, 0x08, 0x08, 0x38, 0x38, 0x00, 0x00}, // 0xAA + {0x4F, 0x6F, 0x30, 0x18, 0xCC, 0xEE, 0xBB, 0x91}, // 0xAB + {0x4F, 0x6F, 0x30, 0x18, 0x6C, 0x76, 0xFB, 0xF9}, // 0xAC + {0x00, 0x00, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x00}, // 0xAD + {0x08, 0x1C, 0x36, 0x22, 0x08, 0x1C, 0x36, 0x22}, // 0xAE + {0x22, 0x36, 0x1C, 0x08, 0x22, 0x36, 0x1C, 0x08}, // 0xAF + {0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00}, // 0xB0 + {0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55}, // 0xB1 + {0xDD, 0xFF, 0xAA, 0x77, 0xDD, 0xAA, 0xFF, 0x77}, // 0xB2 + {0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // 0xB3 + {0x10, 0x10, 0x10, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // 0xB4 + {0x14, 0x14, 0x14, 0xFF, 0xFF, 0x00, 0x00, 0x00}, // 0xB5 + {0x10, 0x10, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00}, // 0xB6 + {0x10, 0x10, 0xF0, 0xF0, 0x10, 0xF0, 0xF0, 0x00}, // 0xB7 + {0x14, 0x14, 0x14, 0xFC, 0xFC, 0x00, 0x00, 0x00}, // 0xB8 + {0x14, 0x14, 0xF7, 0xF7, 0x00, 0xFF, 0xFF, 0x00}, // 0xB9 + {0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00}, // 0xBA + {0x14, 0x14, 0xF4, 0xF4, 0x04, 0xFC, 0xFC, 0x00}, // 0xBB + {0x14, 0x14, 0x17, 0x17, 0x10, 0x1F, 0x1F, 0x00}, // 0xBC + {0x10, 0x10, 0x1F, 0x1F, 0x10, 0x1F, 0x1F, 0x00}, // 0xBD + {0x14, 0x14, 0x14, 0x1F, 0x1F, 0x00, 0x00, 0x00}, // 0xBE + {0x10, 0x10, 0x10, 0xF0, 0xF0, 0x00, 0x00, 0x00}, // 0xBF + {0x00, 0x00, 0x00, 0x1F, 0x1F, 0x10, 0x10, 0x10}, // 0xC0 + {0x10, 0x10, 0x10, 0x1F, 0x1F, 0x10, 0x10, 0x10}, // 0xC1 + {0x10, 0x10, 0x10, 0xF0, 0xF0, 0x10, 0x10, 0x10}, // 0xC2 + {0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x10, 0x10}, // 0xC3 + {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, // 0xC4 + {0x10, 0x10, 0x10, 0xFF, 0xFF, 0x10, 0x10, 0x10}, // 0xC5 + {0x00, 0x00, 0x00, 0xFF, 0xFF, 0x14, 0x14, 0x14}, // 0xC6 + {0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x10}, // 0xC7 + {0x00, 0x00, 0x1F, 0x1F, 0x10, 0x17, 0x17, 0x14}, // 0xC8 + {0x00, 0x00, 0xFC, 0xFC, 0x04, 0xF4, 0xF4, 0x14}, // 0xC9 + {0x14, 0x14, 0x17, 0x17, 0x10, 0x17, 0x17, 0x14}, // 0xCA + {0x14, 0x14, 0xF4, 0xF4, 0x04, 0xF4, 0xF4, 0x14}, // 0xCB + {0x00, 0x00, 0xFF, 0xFF, 0x00, 0xF7, 0xF7, 0x14}, // 0xCC + {0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}, // 0xCD + {0x14, 0x14, 0xF7, 0xF7, 0x00, 0xF7, 0xF7, 0x14}, // 0xCE + {0x14, 0x14, 0x14, 0x17, 0x17, 0x14, 0x14, 0x14}, // 0xCF + {0x10, 0x10, 0x1F, 0x1F, 0x10, 0x1F, 0x1F, 0x10}, // 0xD0 + {0x14, 0x14, 0x14, 0xF4, 0xF4, 0x14, 0x14, 0x14}, // 0xD1 + {0x10, 0x10, 0xF0, 0xF0, 0x10, 0xF0, 0xF0, 0x10}, // 0xD2 + {0x00, 0x00, 0x1F, 0x1F, 0x10, 0x1F, 0x1F, 0x10}, // 0xD3 + {0x00, 0x00, 0x00, 0x1F, 0x1F, 0x14, 0x14, 0x14}, // 0xD4 + {0x00, 0x00, 0x00, 0xFC, 0xFC, 0x14, 0x14, 0x14}, // 0xD5 + {0x00, 0x00, 0xF0, 0xF0, 0x10, 0xF0, 0xF0, 0x10}, // 0xD6 + {0x10, 0x10, 0xFF, 0xFF, 0x10, 0xFF, 0xFF, 0x10}, // 0xD7 + {0x14, 0x14, 0x14, 0xFF, 0xFF, 0x14, 0x14, 0x14}, // 0xD8 + {0x10, 0x10, 0x10, 0x1F, 0x1F, 0x00, 0x00, 0x00}, // 0xD9 + {0x00, 0x00, 0x00, 0xF0, 0xF0, 0x10, 0x10, 0x10}, // 0xDA + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // 0xDB + {0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0}, // 0xDC + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, // 0xDD + {0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, // 0xDE + {0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F}, // 0xDF + {0x38, 0x7C, 0x44, 0x6C, 0x38, 0x6C, 0x44, 0x00}, // 0xE0 + {0xFC, 0xFE, 0x2A, 0x2A, 0x3E, 0x14, 0x00, 0x00}, // 0xE1 + {0x7E, 0x7E, 0x02, 0x02, 0x06, 0x06, 0x00, 0x00}, // 0xE2 + {0x02, 0x7E, 0x7E, 0x02, 0x7E, 0x7E, 0x02, 0x00}, // 0xE3 + {0x63, 0x77, 0x5D, 0x49, 0x63, 0x63, 0x00, 0x00}, // 0xE4 + {0x38, 0x7C, 0x44, 0x7C, 0x3C, 0x04, 0x04, 0x00}, // 0xE5 + {0x80, 0xFE, 0x7E, 0x20, 0x20, 0x3E, 0x1E, 0x00}, // 0xE6 + {0x04, 0x06, 0x02, 0x7E, 0x7C, 0x06, 0x02, 0x00}, // 0xE7 + {0x99, 0xBD, 0xE7, 0xE7, 0xBD, 0x99, 0x00, 0x00}, // 0xE8 + {0x1C, 0x3E, 0x6B, 0x49, 0x6B, 0x3E, 0x1C, 0x00}, // 0xE9 + {0x4C, 0x7E, 0x73, 0x01, 0x73, 0x7E, 0x4C, 0x00}, // 0xEA + {0x30, 0x78, 0x4A, 0x4F, 0x7D, 0x39, 0x00, 0x00}, // 0xEB + {0x18, 0x3C, 0x24, 0x3C, 0x3C, 0x24, 0x3C, 0x18}, // 0xEC + {0x98, 0xFC, 0x64, 0x3C, 0x3E, 0x27, 0x3D, 0x18}, // 0xED + {0x1C, 0x3E, 0x6B, 0x49, 0x49, 0x00, 0x00, 0x00}, // 0xEE + {0x7E, 0x7F, 0x01, 0x01, 0x7F, 0x7E, 0x00, 0x00}, // 0xEF + {0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, 0x00}, // 0xF0 + {0x44, 0x44, 0x5F, 0x5F, 0x44, 0x44, 0x00, 0x00}, // 0xF1 + {0x40, 0x51, 0x5B, 0x4E, 0x44, 0x40, 0x00, 0x00}, // 0xF2 + {0x40, 0x44, 0x4E, 0x5B, 0x51, 0x40, 0x00, 0x00}, // 0xF3 + {0x00, 0x00, 0x00, 0xFE, 0xFF, 0x01, 0x07, 0x06}, // 0xF4 + {0x60, 0xE0, 0x80, 0xFF, 0x7F, 0x00, 0x00, 0x00}, // 0xF5 + {0x08, 0x08, 0x6B, 0x6B, 0x08, 0x08, 0x00, 0x00}, // 0xF6 + {0x24, 0x36, 0x12, 0x36, 0x24, 0x36, 0x12, 0x00}, // 0xF7 + {0x00, 0x06, 0x0F, 0x09, 0x0F, 0x06, 0x00, 0x00}, // 0xF8 + {0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00}, // 0xF9 + {0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00}, // 0xFA + {0x10, 0x30, 0x70, 0xC0, 0xFF, 0xFF, 0x01, 0x01}, // 0xFB + {0x00, 0x1F, 0x1F, 0x01, 0x1F, 0x1E, 0x00, 0x00}, // 0xFC + {0x00, 0x19, 0x1D, 0x17, 0x12, 0x00, 0x00, 0x00}, // 0xFD + {0x00, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00}, // 0xFE + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // 0xFF +}; // end of MAX7219_Dot_Matrix_font + +} // namespace max7219digit +} // namespace esphome diff --git a/tests/test3.yaml b/tests/test3.yaml index dded01fb67..edbf472657 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -803,6 +803,7 @@ tm1651: id: tm1651_battery clk_pin: D6 dio_pin: D5 + rf_bridge: on_code_received: - lambda: |- @@ -817,3 +818,14 @@ rf_bridge: high: 0x1234 code: 0x123456 - rf_bridge.learn + +display: + - platform: max7219digit + cs_pin: GPIO15 + num_chips: 4 + rotate_chip: 0 + intensity: 10 + scroll_mode: 'STOP' + id: my_matrix + lambda: |- + it.printdigit("hello");