Table of Contents
SPI Dot-Matrix
How to use SPI on ODROID-C2
Since the C2 doesn't support Hardware SPI. This Example is using the GPIO-based bitbanging SPI Master.
In this case, the maximum clock is about 390KHz.
Update the Kernel first. This module drivers are available on 3.14.29-32 or higher.
odroid@odroid64:~$ sudo modprobe spi-bitbang odroid@odroid64:~$ sudo modprobe spi-gpio odroid@odroid64:~$ sudo modprobe spidev odroid@odroid64:~$ lsmod Module Size Used by spidev 5785 0 spi_gpio 5978 0 spi_bitbang 3637 1 spi_gpio fuse 77425 3 autofs4 24813 2 odroid@odroid64:~$
odroid@odroid64:~$ ls /dev/spidev0.0 /dev/spidev0.0 odroid@odroid64:~$
Compile & run SPI test example source code
odroid@odroid64:~$ gcc -o dot_test dot_test.c
odroid@odroid64:~$ sudo ./dot_test spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz)
Set to 500 KHz, but it is actually operating at 390KHz.
- dot_test.c
/* * SPI testing utility (using spidev driver) * * Copyright (c) 2007 MontaVista Software, Inc. * Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com> * * 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 <stdint.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/spi/spidev.h> #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; 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; }
odroid@odroid64:~$ gcc -o dot_shift_test dot_shift_test.c
odroid@odroid64:~$ sudo ./dot_shift_test max speed: 1000000 Hz (1000 KHz)
- dot_shift_test.c
//------------------------------------------------------------------------------ // // Dot-Matrix LED Test Application.(ODROIDs SPIDEV) // // if defined USE_WIRING_PI_LIB // Compile : gcc -o <create excute file name> <source file name> -lwiringPi -lwiringPiDev -lpthread // else // Compile : gcc -o <create excute file name> <source file name> // // Run : sudo ./<created excute file name> // //------------------------------------------------------------------------------ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/spi/spidev.h> #include <unistd.h> #include <string.h> #include <time.h> #include <ifaddrs.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <net/if.h> #include <arpa/inet.h> // 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 <wiringPi.h> #include <wiringPiSPI.h> #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; 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 ; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------
- dotfont.h
/* 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 } };