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
This commit is contained in:
rspaargaren 2020-06-28 22:33:06 +02:00 committed by GitHub
parent 3c9712d683
commit bfb9cb6732
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 743 additions and 0 deletions

View file

@ -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_))

View file

@ -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

View file

@ -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<void(MAX7219Component &)>;
class MAX7219Component : public PollingComponent,
public display::DisplayBuffer,
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_1MHZ> {
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<uint8_t> max_displaybuffer_;
unsigned long last_scroll_ = 0;
uint16_t stepsleft_;
size_t get_buffer_length_();
optional<max7219_writer_t> writer_local_{};
};
} // namespace max7219digit
} // namespace esphome

View file

@ -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

View file

@ -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");