====== SPI Dot-Matrix ======
{{http://dn.odroid.com/wiki_image/xu4_spi_dot_matrix.jpg?500|}}
To use spidev on your **ODROID-XU4** you should fix device tree source.
To use the SPI, you first need to update the kernel version to "3.10.82" or higher.
sudo apt-get update && sudo apt-get dist-upgrade
=== How to enable driver (Only Ubuntu 16.04 or higher is required) ===
Edit /etc/modprobe.d/blacklist-odroid.conf to comment out following two ines.
blacklist spidev
blacklist spi_s3c64xx
Reboot.
reboot
Check your SPI node.
ls /dev/spidev*
==== Compile & run SPI test example source code ====
gcc -o dot_test dot_test.c
odroid@odroid:~$ sudo ./dot_test
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)
==== Simple Dot-matrix LED test ====
/*
* SPI testing utility (using spidev driver)
*
* Copyright (c) 2007 MontaVista Software, Inc.
* Copyright (c) 2007 Anton Vorontsov
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/
#include
#include
#include
#include
#include
#include
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define uchar unsigned char
#define MAX_RAW 36
#define MAX_COLUMN 8
uchar disp1[MAX_RAW][MAX_COLUMN] = {
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
{0x10,0x30,0x50,0x10,0x10,0x10,0x10,0x7C},//1
{0x3E,0x02,0x02,0x3E,0x20,0x20,0x3E,0x00},//2
{0x00,0x7C,0x04,0x04,0x7C,0x04,0x04,0x7C},//3
{0x08,0x18,0x28,0x48,0xFE,0x08,0x08,0x08},//4
{0x3C,0x20,0x20,0x3C,0x04,0x04,0x3C,0x00},//5
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x00},//6
{0x3E,0x22,0x04,0x08,0x08,0x08,0x08,0x08},//7
{0x00,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
{0x3E,0x22,0x22,0x3E,0x02,0x02,0x02,0x3E},//9
{0x08,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x00},//B
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x00},//C
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x00},//D
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
{0x3C,0x08,0x08,0x08,0x08,0x08,0x48,0x30},//J
{0x00,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x00},//N
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x00,0x1E,0x20,0x20,0x3E,0x02,0x02,0x3C},//S
{0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08},//T
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
{0x00,0x49,0x49,0x49,0x49,0x2A,0x1C,0x00},//W
{0x00,0x41,0x22,0x14,0x08,0x14,0x22,0x41},//X
{0x41,0x22,0x14,0x08,0x08,0x08,0x08,0x08},//Y
{0x00,0x7F,0x02,0x04,0x08,0x10,0x20,0x7F},//Z
};
static void pabort(const char *s) {
perror(s);
abort();
}
static const char *device_spidev0_0 = "/dev/spidev0.0";
static const char *device_spidev1_0 = "/dev/spidev1.0";
static uint8_t mode;
static uint8_t bits = 8;
static uint32_t speed = 500000;
static void transfer(int fd, uchar address1, uchar dat1, uchar address2, uchar dat2) {
int ret;
uint8_t tx[] = {
address1, dat1, address2, dat2
};
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr;
memset((void *)&tr, 0x00, sizeof(tr));
tr.tx_buf = (unsigned long)tx;
tr.rx_buf = (unsigned long)rx;
tr.len = ARRAY_SIZE(tx);
tr.speed_hz = speed;
tr.bits_per_word = bits;
tr.delay_usecs = 0;
tr.cs_change = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send SPI message");
}
int main() {
uchar i , j;
int ret = 0;
int fd;
fd = open(device_spidev0_0, O_RDWR);
if (fd < 0) {
printf("can't open /dev/spidev0.0\nTry /dev/spidev1.0\n");
fd = open(device_spidev1_0, O_RDWR);
if (fd < 0)
pabort("can't open /dev/spidev1.0");
}
/* SPI mode */
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
pabort("can't set SPI mode");
ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
pabort("can't get SPI mode");
/* bits per word */
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/* max speed hz */
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed Hz");
ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed Hz");
printf("SPI mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
transfer(fd, 0x09,0x00,0x09,0x00);
transfer(fd, 0x0a,0x03,0x0a,0x03);
transfer(fd, 0x0b,0x07,0x0b,0x07);
transfer(fd, 0x0c,0x01,0x0c,0x01);
transfer(fd, 0x0f,0x00,0x0f,0x00);
while (1) {
for(j = 0; j < MAX_RAW - 1; j++) {
for(i = 1; i < MAX_COLUMN + 1; i++)
transfer(fd, i, disp1[j + 1][i - 1], i, disp1[j][i - 1]);
usleep(1000000);
}
}
close(fd);
return ret;
}
==== Example of Scrolling Text ====
**WiringPi SPI API** use case :
Uncomment this line first.
#define USE_WIRING_PI_LIB
Build the example with proper library option.
if defined USE_WIRING_PI_LIB
Compile : gcc -o
gcc -o dot_test dot_shift_test.c
odroid@odroid:~$ sudo ./dot_shift_test
max speed: 1000000 Hz (1000 KHz)
//------------------------------------------------------------------------------
//
// Dot-Matrix LED Test Application.(ODROIDs SPIDEV)
//
// if defined USE_WIRING_PI_LIB
// Compile : gcc -o -lwiringPi -lwiringPiDev -lpthread
// else
// Compile : gcc -o
//
// Run : sudo ./
//
//------------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// wiringPi Library use flag (if disable then normal spidev control)
//#define USE_WIRING_PI_LIB
// Display Item flag (if disable then Data & Time Display)
#define DISPLAY_IP_ADDR
#define START_STR "Hello! Odroid!"
#define SPI_MAX_SPEED 1000000 // 1Mhz SPI Speed
//------------------------------------------------------------------------------
//
// Application use value define
//
//------------------------------------------------------------------------------
#include "dotfont.h"
#define SHIFT_DELAY_MS 70
#define DISPLAY_DELAY_MS 1000
#define MAX_SHIFT_CHAR_COUNT 256
#define DOT_MATRIX_8X8_COUNT MAX_SHIFT_CHAR_COUNT
//
// Virtual Dotmatrix framebuffer define.
//
unsigned char DotMatrixFb[DOT_MATRIX_8X8_COUNT][8] = { 0 };
//------------------------------------------------------------------------------
//
// wiringPi use header file
//
//------------------------------------------------------------------------------
#if defined(USE_WIRING_PI_LIB)
#include
#include
#else
//#define SPIDEV_NODE_NAME "/dev/spidev0.0" // ODROID-C1/C1+
#define SPIDEV_NODE_NAME "/dev/spidev1.0" // ODROID-XU3/XU4
int SpidevFd = -1;
#endif
//------------------------------------------------------------------------------
//
// SPI Dot Matrix Initialize data
//
//------------------------------------------------------------------------------
unsigned char dotled_init[5][4] = {
{0x09,0x00,0x09,0x00},
{0x0a,0x03,0x0a,0x03},
{0x0b,0x07,0x0b,0x07},
{0x0c,0x01,0x0c,0x01},
{0x0f,0x00,0x0f,0x00},
};
//------------------------------------------------------------------------------
//
// Get ethernet ip addr
//
//------------------------------------------------------------------------------
int get_ethernet_ip (unsigned char *buf)
{
struct ifaddrs *ifa;
int str_cnt;
getifaddrs(&ifa);
while(ifa) {
if(ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *pAddr = (struct sockaddr_in *)ifa->ifa_addr;
if(0==strncmp(ifa->ifa_name, "eth", 2)) {
// str_cnt = sprintf(buf, "IP(%s):%s", ifa->ifa_name, inet_ntoa(pAddr->sin_addr));
str_cnt = sprintf(buf, "IP:%s", inet_ntoa(pAddr->sin_addr));
}
}
ifa = ifa->ifa_next;
}
freeifaddrs(ifa);
return str_cnt;
}
//------------------------------------------------------------------------------
//
// Get date & time
//
//------------------------------------------------------------------------------
int get_date_time (unsigned char *buf)
{
time_t tm_time;
struct tm *st_time;
int str_cnt;
time(&tm_time);
st_time = localtime(&tm_time);
return (strftime(buf, MAX_SHIFT_CHAR_COUNT , "%Y/%m/%d %a %H:%M:%S %p", st_time));
}
//------------------------------------------------------------------------------
//
// SPI Dot Matrix H/W Write
//
//------------------------------------------------------------------------------
#if !defined(USE_WIRING_PI_LIB)
void dotmatrix_write (unsigned char *buf, unsigned int len)
{
struct spi_ioc_transfer tr;
memset((void *)&tr, 0x00, sizeof(tr));
tr.tx_buf = (unsigned long)buf;
tr.rx_buf = (unsigned long)buf;
tr.len = len;
tr.speed_hz = SPI_MAX_SPEED;
tr.bits_per_word = 8;
tr.delay_usecs = 0;
tr.cs_change = 0;
if (ioctl(SpidevFd, SPI_IOC_MESSAGE(1), &tr) < 1)
fprintf (stderr, "%s: can't send SPI message", __func__);
}
#endif
//------------------------------------------------------------------------------
//
// SPI Dot Matrix update
//
//------------------------------------------------------------------------------
void dotmatrix_update (void)
{
unsigned char spi_data[4] = { 0, }, i;
for(i = 0; i < 8; i++) {
spi_data[0] = i +1; spi_data[1] = DotMatrixFb[1][i];
spi_data[2] = i +1; spi_data[3] = DotMatrixFb[0][i];
#if defined(USE_WIRING_PI_LIB)
wiringPiSPIDataRW(0, &spi_data[0], sizeof(spi_data));
#else
dotmatrix_write(&spi_data[0], sizeof(spi_data));
#endif
}
}
//------------------------------------------------------------------------------
//
// Dot Matrix Frambuffer Shift
//
//------------------------------------------------------------------------------
void dotmatrix_buffer_shift(int delay_ms)
{
int i, j;
for(j = 0; j < DOT_MATRIX_8X8_COUNT; j++) {
for(i = 0; i < 8; i++) {
DotMatrixFb[j][i] <<= 1;
if((j != DOT_MATRIX_8X8_COUNT -1) && (DotMatrixFb[j + 1][i] & 0x80))
DotMatrixFb[j][i] |= 0x01;
}
}
dotmatrix_update();
usleep(delay_ms * 1000);
}
//------------------------------------------------------------------------------
//
// Dot Matrix Framebuffer Update
//
//------------------------------------------------------------------------------
int dotmatrix_buffer_update (unsigned char *str, int delay_ms)
{
int i, buf_pos = 0, bits_count = 0;
while(*str != 0x00) {
for(i = 0; i < 8; i++) {
DotMatrixFb[buf_pos][i] = VINCENT_FONT[*str][i];
bits_count++;
}
buf_pos++; str++;
}
dotmatrix_update();
usleep(delay_ms * 1000);
return (bits_count); // String total bits
}
//------------------------------------------------------------------------------
//
// system init
//
//------------------------------------------------------------------------------
int system_init(void)
{
int i, spi_speed = SPI_MAX_SPEED;
#if defined(USE_WIRING_PI_LIB)
// spi channel open, speed = 1Mhz
if(wiringPiSPISetup(0, spi_speed) < 0)
{
fprintf (stderr, "%s: wiringPiSPISetup failed\n", __func__); return -1;
}
for(i = 0; i < 5; i++) {
wiringPiSPIDataRW(0, &dotled_init[i][0], 4);
}
#else
if ((SpidevFd = open(SPIDEV_NODE_NAME, O_RDWR)) < 0) {
fprintf (stderr, "%s : Hardware Init(%s) failed\n", __func__, SPIDEV_NODE_NAME);
return -1;
}
if(ioctl(SpidevFd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0) {
fprintf (stderr, "%s : can't set max speed Hz", __func__);
return -1;
}
for(i = 0; i < 5; i++) {
dotmatrix_write(&dotled_init[i][0], 4);
}
#endif
return 0;
}
//------------------------------------------------------------------------------
//
// Start Program
//
//------------------------------------------------------------------------------
int main (int argc, char *argv[])
{
int speed, shift_len;
unsigned char disp_str[MAX_SHIFT_CHAR_COUNT];
#if defined(USE_WIRING_PI_LIB)
wiringPiSetup ();
#endif
if (system_init() < 0)
{
fprintf (stderr, "%s: System Init failed\n", __func__); return -1;
}
#if defined(USE_WIRING_PI_LIB)
if (ioctl(wiringPiSPIGetFd(0), SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1) {
fprintf (stderr, "%s: Get Max Speed Error!\n", __func__); return -1;
}
#else
if (ioctl(SpidevFd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1) {
fprintf (stderr, "%s: Get Max Speed Error!\n", __func__); return -1;
}
#endif
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
while(1)
{
// display buffer clear
memset(disp_str, 0x00, sizeof(disp_str));
#if defined(START_STR)
shift_len = sprintf(&disp_str[0], "%s ", START_STR);
#else
shift_len = 0;
#endif
#if defined(DISPLAY_IP_ADDR)
get_ethernet_ip(&disp_str[shift_len]);
#else
get_date_time(&disp_str[shift_len]);
#endif
shift_len = dotmatrix_buffer_update(disp_str, DISPLAY_DELAY_MS);
while(shift_len--) dotmatrix_buffer_shift(SHIFT_DELAY_MS);
}
return 0 ;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/* vincent font from
http://forum.osdev.org/viewtopic.php?f=2&t=22033&start=0&sid=d8da9a564483052518f8d632556c617f */
const unsigned char VINCENT_FONT[128][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x3E, 0x41, 0x55, 0x41, 0x55, 0x49, 0x3E },
{ 0x00, 0x3E, 0x7F, 0x6B, 0x7F, 0x6B, 0x77, 0x3E },
{ 0x00, 0x22, 0x77, 0x7F, 0x7F, 0x3E, 0x1C, 0x08 },
{ 0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x1C, 0x08 },
{ 0x00, 0x08, 0x1C, 0x2A, 0x7F, 0x2A, 0x08, 0x1C },
{ 0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x3E, 0x08, 0x1C },
{ 0x00, 0x00, 0x1C, 0x3E, 0x3E, 0x3E, 0x1C, 0x00 },
{ 0xFF, 0xFF, 0xE3, 0xC1, 0xC1, 0xC1, 0xE3, 0xFF },
{ 0x00, 0x00, 0x1C, 0x22, 0x22, 0x22, 0x1C, 0x00 },
{ 0xFF, 0xFF, 0xE3, 0xDD, 0xDD, 0xDD, 0xE3, 0xFF },
{ 0x00, 0x0F, 0x03, 0x05, 0x39, 0x48, 0x48, 0x30 },
{ 0x00, 0x08, 0x3E, 0x08, 0x1C, 0x22, 0x22, 0x1C },
{ 0x00, 0x18, 0x14, 0x10, 0x10, 0x30, 0x70, 0x60 },
{ 0x00, 0x0F, 0x19, 0x11, 0x13, 0x37, 0x76, 0x60 },
{ 0x00, 0x08, 0x2A, 0x1C, 0x77, 0x1C, 0x2A, 0x08 },
{ 0x00, 0x60, 0x78, 0x7E, 0x7F, 0x7E, 0x78, 0x60 },
{ 0x00, 0x03, 0x0F, 0x3F, 0x7F, 0x3F, 0x0F, 0x03 },
{ 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x2A, 0x1C, 0x08 },
{ 0x00, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66 },
{ 0x00, 0x3F, 0x65, 0x65, 0x3D, 0x05, 0x05, 0x05 },
{ 0x00, 0x0C, 0x32, 0x48, 0x24, 0x12, 0x4C, 0x30 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F },
{ 0x00, 0x08, 0x1C, 0x2A, 0x08, 0x2A, 0x1C, 0x3E },
{ 0x00, 0x08, 0x1C, 0x3E, 0x7F, 0x1C, 0x1C, 0x1C },
{ 0x00, 0x1C, 0x1C, 0x1C, 0x7F, 0x3E, 0x1C, 0x08 },
{ 0x00, 0x08, 0x0C, 0x7E, 0x7F, 0x7E, 0x0C, 0x08 },
{ 0x00, 0x08, 0x18, 0x3F, 0x7F, 0x3F, 0x18, 0x08 },
{ 0x00, 0x00, 0x00, 0x70, 0x70, 0x70, 0x7F, 0x7F },
{ 0x00, 0x00, 0x14, 0x22, 0x7F, 0x22, 0x14, 0x00 },
{ 0x00, 0x08, 0x1C, 0x1C, 0x3E, 0x3E, 0x7F, 0x7F },
{ 0x00, 0x7F, 0x7F, 0x3E, 0x3E, 0x1C, 0x1C, 0x08 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18 },
{ 0x00, 0x36, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36 },
{ 0x00, 0x08, 0x1E, 0x20, 0x1C, 0x02, 0x3C, 0x08 },
{ 0x00, 0x60, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x06 },
{ 0x00, 0x3C, 0x66, 0x3C, 0x28, 0x65, 0x66, 0x3F },
{ 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00 },
{ 0x00, 0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06 },
{ 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60 },
{ 0x00, 0x00, 0x36, 0x1C, 0x7F, 0x1C, 0x36, 0x00 },
{ 0x00, 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x60 },
{ 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60 },
{ 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00 },
{ 0x00, 0x3C, 0x66, 0x6E, 0x76, 0x66, 0x66, 0x3C },
{ 0x00, 0x18, 0x18, 0x38, 0x18, 0x18, 0x18, 0x7E },
{ 0x00, 0x3C, 0x66, 0x06, 0x0C, 0x30, 0x60, 0x7E },
{ 0x00, 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C },
{ 0x00, 0x0C, 0x1C, 0x2C, 0x4C, 0x7E, 0x0C, 0x0C },
{ 0x00, 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C },
{ 0x00, 0x3C, 0x66, 0x60, 0x7C, 0x66, 0x66, 0x3C },
{ 0x00, 0x7E, 0x66, 0x0C, 0x0C, 0x18, 0x18, 0x18 },
{ 0x00, 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C },
{ 0x00, 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x66, 0x3C },
{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00 },
{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30 },
{ 0x00, 0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06 },
{ 0x00, 0x00, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x00 },
{ 0x00, 0x60, 0x30, 0x18, 0x0C, 0x18, 0x30, 0x60 },
{ 0x00, 0x3C, 0x66, 0x06, 0x1C, 0x18, 0x00, 0x18 },
{ 0x00, 0x38, 0x44, 0x5C, 0x58, 0x42, 0x3C, 0x00 },
{ 0x00, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66 },
{ 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C },
{ 0x00, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C },
{ 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C },
{ 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E },
{ 0x00, 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60 },
{ 0x00, 0x3C, 0x66, 0x60, 0x60, 0x6E, 0x66, 0x3C },
{ 0x00, 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66 },
{ 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C },
{ 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x6C, 0x6C, 0x38 },
{ 0x00, 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66 },
{ 0x00, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E },
{ 0x00, 0x63, 0x77, 0x7F, 0x6B, 0x63, 0x63, 0x63 },
{ 0x00, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x63, 0x63 },
{ 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C },
{ 0x00, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60 },
{ 0x00, 0x3C, 0x66, 0x66, 0x66, 0x6E, 0x3C, 0x06 },
{ 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x78, 0x6C, 0x66 },
{ 0x00, 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C },
{ 0x00, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18 },
{ 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3E },
{ 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18 },
{ 0x00, 0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63 },
{ 0x00, 0x63, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x63 },
{ 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18 },
{ 0x00, 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E },
{ 0x00, 0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E },
{ 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00 },
{ 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78 },
{ 0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F },
{ 0x00, 0x0C, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E },
{ 0x00, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x7C },
{ 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C },
{ 0x00, 0x06, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3E },
{ 0x00, 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C },
{ 0x00, 0x1C, 0x36, 0x30, 0x30, 0x7C, 0x30, 0x30 },
{ 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C },
{ 0x00, 0x60, 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66 },
{ 0x00, 0x00, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C },
{ 0x00, 0x0C, 0x00, 0x0C, 0x0C, 0x6C, 0x6C, 0x38 },
{ 0x00, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66 },
{ 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },
{ 0x00, 0x00, 0x00, 0x63, 0x77, 0x7F, 0x6B, 0x6B },
{ 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x66, 0x66, 0x66 },
{ 0x00, 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C },
{ 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60 },
{ 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x3C, 0x0D, 0x0F },
{ 0x00, 0x00, 0x00, 0x7C, 0x66, 0x66, 0x60, 0x60 },
{ 0x00, 0x00, 0x00, 0x3E, 0x40, 0x3C, 0x02, 0x7C },
{ 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18 },
{ 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E },
{ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18 },
{ 0x00, 0x00, 0x00, 0x63, 0x6B, 0x6B, 0x6B, 0x3E },
{ 0x00, 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66 },
{ 0x00, 0x00, 0x00, 0x66, 0x66, 0x3E, 0x06, 0x3C },
{ 0x00, 0x00, 0x00, 0x3C, 0x0C, 0x18, 0x30, 0x3C },
{ 0x00, 0x0E, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0E },
{ 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18 },
{ 0x00, 0x70, 0x18, 0x18, 0x0C, 0x18, 0x18, 0x70 },
{ 0x00, 0x00, 0x00, 0x3A, 0x6C, 0x00, 0x00, 0x00 },
{ 0x00, 0x08, 0x1C, 0x36, 0x63, 0x41, 0x41, 0x7F }
};