赞
踩
屏幕参数
1.I2C接口(GND,VCC,SCL ,SDA(双向数据线))
2.分辨率128*64
3.超逛可视角度 160
4.超低功耗正常显示0.04w
5.宽供电范围3.3-5V
6、工业级温度:-30---70C
7、体积28.65mm---27.8mm
8.亮度、对比度可以通过程序指令控制
9.使用寿命不少于16000小时
10、OLED内部驱动SSD1306
连接方式如下图
代码
main.cpp
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-01-28 Damon first version
- */
-
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "pico/stdlib.h"
- #include "include/ss_oled.hpp"
-
- // RPI Pico
- #define SDA_PIN 4
- #define SCL_PIN 5
- #define PICO_I2C i2c0
- #define I2C_SPEED 100 * 1000
-
-
- #define OLED_WIDTH 128
- #define OLED_HEIGHT 64
- #define LED_PIN 25
-
- int main(void)
- {
- rt_kprintf("Hello, RT-Thread!\n");
- rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
-
-
- static uint8_t ucBuffer[1024];
- uint8_t uc[8];
- int i, j, rc;
- char szTemp[32];
- picoSSOLED myOled(OLED_128x64, 0x3c, 0, 0, PICO_I2C, SDA_PIN, SCL_PIN, I2C_SPEED);
-
- rc = myOled.init() ;
- myOled.set_back_buffer(ucBuffer);
-
- while (1) {
-
- if (rc != OLED_NOT_FOUND)
- {
- rt_pin_write(LED_PIN, 1);
- rt_thread_mdelay(1000);
-
- myOled.fill(0,1);
- myOled.set_contrast(255);
- myOled.write_string(0,0,0,(char *)"**************** ", FONT_8x8, 0, 1);
- myOled.write_string(0,4,1,(char *)"RT-Pico SS_OLED", FONT_6x8, 0, 1);
- myOled.write_string(0,8,2,(char *)"running on the", FONT_8x8, 0, 1);
- myOled.write_string(0,8,3,(char *)"SSD1306 128x64", FONT_8x8, 0, 1);
- myOled.write_string(0,4,4,(char *)"monochrome OLED", FONT_8x8, 0, 1);
- myOled.write_string(0,0,5,(char *)"Written by Damon", FONT_8x8, 0, 1);
- //myOled.write_string(0,4,6,(char *), FONT_6x8, 0, 1);
- myOled.write_string(0,0,7,(char *)"**************** ", FONT_8x8, 0, 1);
- sleep_ms(10000);
- }
-
-
- myOled.fill(0,1);
- myOled.write_string(0,0,0,(char *)"Now with 5 font sizes", FONT_6x8, 0, 1);
- myOled.write_string(0,0,1,(char *)"6x8 8x8 16x16", FONT_8x8, 0, 1);
- myOled.write_string(0,0,2,(char *)"16x32 and a new", FONT_8x8, 0, 1);
- myOled.write_string(0,0,3,(char *)"Stretched", FONT_12x16, 0, 1);
- myOled.write_string(0,0,5,(char *)"from 6x8", FONT_12x16, 0, 1);
- sleep_ms(10000);
-
- int x, y;
- myOled.fill(0, 1);
- myOled.write_string(0,0,0,(char *)"Backbuffer Test", FONT_NORMAL,0,1);
- myOled.write_string(0,0,1,(char *)"96 lines", FONT_NORMAL,0,1);
- sleep_ms(10000);
- for (x=0; x<OLED_WIDTH-1; x+=2)
- {
- myOled.draw_line(x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
- };
- for (y=0; y<OLED_HEIGHT-1; y+=2)
- {
- myOled.draw_line(OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
- };
- sleep_ms(10000);
- myOled.write_string(0,0,1,(char *)"Without backbuffer", FONT_SMALL,0,1);
- sleep_ms(10000);
- myOled.fill(0,1);
-
- for (x=0; x<OLED_WIDTH-1; x+=2)
- {
- myOled.draw_line(x, 0, OLED_WIDTH-1-x, OLED_HEIGHT-1, 0);
- }
- for (y=0; y<OLED_HEIGHT-1; y+=2)
- {
- myOled.draw_line(OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 0);
- }
- myOled.dump_buffer(ucBuffer);
- myOled.write_string(0,0,1,(char *)"With backbuffer", FONT_SMALL,0,1);
- sleep_ms(10000);
-
- rt_pin_write(LED_PIN, 0);
- rt_thread_mdelay(1000);
- }
-
-
-
- return 0;
- }
-

ss_oled.cpp
- //
- // ss_oled (Small, Simple OLED library)
- // Copyright (c) 2017-2019 BitBank Software, Inc.
- // Written by Larry Bank (bitbank@pobox.com)
- // Project started 1/15/2017
- //
- // 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 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "pico/stdlib.h"
-
- #include "include/ss_oled.h"
-
- const uint8_t ucFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x5f, 0x06, 0x00, 0x00,
- 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x14, 0x7f, 0x7f, 0x14, 0x7f, 0x7f, 0x14, 0x24, 0x2e, 0x2a, 0x6b, 0x6b,
- 0x3a, 0x12, 0x46, 0x66, 0x30, 0x18, 0x0c, 0x66, 0x62, 0x30, 0x7a, 0x4f, 0x5d, 0x37, 0x7a, 0x48, 0x00, 0x04,
- 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, 0x00, 0x41, 0x63, 0x3e, 0x1c, 0x00,
- 0x00, 0x08, 0x2a, 0x3e, 0x1c, 0x3e, 0x2a, 0x08, 0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x80,
- 0xe0, 0x60, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
- 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x3e, 0x7f, 0x59, 0x4d, 0x47, 0x7f, 0x3e, 0x40, 0x42, 0x7f, 0x7f,
- 0x40, 0x40, 0x00, 0x62, 0x73, 0x59, 0x49, 0x6f, 0x66, 0x00, 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x18,
- 0x1c, 0x16, 0x53, 0x7f, 0x7f, 0x50, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, 0x3c, 0x7e, 0x4b, 0x49, 0x79,
- 0x30, 0x00, 0x03, 0x03, 0x71, 0x79, 0x0f, 0x07, 0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x06, 0x4f,
- 0x49, 0x69, 0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe6, 0x66, 0x00,
- 0x00, 0x08, 0x1c, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x63,
- 0x36, 0x1c, 0x08, 0x00, 0x00, 0x02, 0x03, 0x59, 0x5d, 0x07, 0x02, 0x3e, 0x7f, 0x41, 0x5d, 0x5d, 0x5f, 0x0e,
- 0x7c, 0x7e, 0x13, 0x13, 0x7e, 0x7c, 0x00, 0x41, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x1c, 0x3e, 0x63, 0x41,
- 0x41, 0x63, 0x22, 0x41, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f, 0x49, 0x5d, 0x41, 0x63, 0x41,
- 0x7f, 0x7f, 0x49, 0x1d, 0x01, 0x03, 0x1c, 0x3e, 0x63, 0x41, 0x51, 0x33, 0x72, 0x7f, 0x7f, 0x08, 0x08, 0x7f,
- 0x7f, 0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, 0x30, 0x70, 0x40, 0x41, 0x7f, 0x3f, 0x01, 0x41, 0x7f,
- 0x7f, 0x08, 0x1c, 0x77, 0x63, 0x41, 0x7f, 0x7f, 0x41, 0x40, 0x60, 0x70, 0x7f, 0x7f, 0x0e, 0x1c, 0x0e, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x06, 0x0c, 0x18, 0x7f, 0x7f, 0x1c, 0x3e, 0x63, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f,
- 0x49, 0x09, 0x0f, 0x06, 0x1e, 0x3f, 0x21, 0x31, 0x61, 0x7f, 0x5e, 0x41, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66,
- 0x26, 0x6f, 0x4d, 0x49, 0x59, 0x73, 0x32, 0x03, 0x41, 0x7f, 0x7f, 0x41, 0x03, 0x00, 0x7f, 0x7f, 0x40, 0x40,
- 0x7f, 0x7f, 0x00, 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, 0x3f, 0x7f, 0x60, 0x30, 0x60, 0x7f, 0x3f, 0x63,
- 0x77, 0x1c, 0x08, 0x1c, 0x77, 0x63, 0x07, 0x4f, 0x78, 0x78, 0x4f, 0x07, 0x00, 0x47, 0x63, 0x71, 0x59, 0x4d,
- 0x67, 0x73, 0x00, 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x41,
- 0x41, 0x7f, 0x7f, 0x00, 0x00, 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x20, 0x74, 0x54, 0x54, 0x3c, 0x78, 0x40, 0x41, 0x7f, 0x3f,
- 0x48, 0x48, 0x78, 0x30, 0x38, 0x7c, 0x44, 0x44, 0x6c, 0x28, 0x00, 0x30, 0x78, 0x48, 0x49, 0x3f, 0x7f, 0x40,
- 0x38, 0x7c, 0x54, 0x54, 0x5c, 0x18, 0x00, 0x48, 0x7e, 0x7f, 0x49, 0x03, 0x06, 0x00, 0x98, 0xbc, 0xa4, 0xa4,
- 0xf8, 0x7c, 0x04, 0x41, 0x7f, 0x7f, 0x08, 0x04, 0x7c, 0x78, 0x00, 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00, 0x60,
- 0xe0, 0x80, 0x84, 0xfd, 0x7d, 0x00, 0x41, 0x7f, 0x7f, 0x10, 0x38, 0x6c, 0x44, 0x00, 0x41, 0x7f, 0x7f, 0x40,
- 0x00, 0x00, 0x7c, 0x7c, 0x18, 0x78, 0x1c, 0x7c, 0x78, 0x7c, 0x78, 0x04, 0x04, 0x7c, 0x78, 0x00, 0x38, 0x7c,
- 0x44, 0x44, 0x7c, 0x38, 0x00, 0x84, 0xfc, 0xf8, 0xa4, 0x24, 0x3c, 0x18, 0x18, 0x3c, 0x24, 0xa4, 0xf8, 0xfc,
- 0x84, 0x44, 0x7c, 0x78, 0x4c, 0x04, 0x0c, 0x18, 0x48, 0x5c, 0x54, 0x74, 0x64, 0x24, 0x00, 0x04, 0x04, 0x3e,
- 0x7f, 0x44, 0x24, 0x00, 0x3c, 0x7c, 0x40, 0x40, 0x3c, 0x7c, 0x40, 0x1c, 0x3c, 0x60, 0x60, 0x3c, 0x1c, 0x00,
- 0x3c, 0x7c, 0x60, 0x30, 0x60, 0x7c, 0x3c, 0x44, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0x44, 0x9c, 0xbc, 0xa0, 0xa0,
- 0xfc, 0x7c, 0x00, 0x4c, 0x64, 0x74, 0x5c, 0x4c, 0x64, 0x00, 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, 0x00,
- 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02,
- 0x03, 0x01, 0x70, 0x78, 0x4c, 0x46, 0x4c, 0x78, 0x70 };
- const uint8_t ucBigFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
- 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xfc,
- 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0xfc, 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0xff,
- 0xff, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0,
- 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0f,
- 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f, 0x3f, 0x3f, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0xff,
- 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xff,
- 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f, 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
- 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xff, 0xff, 0x3f,
- 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xcc, 0xcc, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f,
- 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x30, 0x30, 0x0f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3c, 0x3c, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0x3c, 0x3c, 0x00,
- 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
- 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
- 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3f, 0x3f, 0xf3,
- 0xf3, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x0c, 0x3c, 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xf3, 0xf3, 0x3f, 0x3f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
- 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x3c,
- 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03,
- 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
- 0x03, 0x0f, 0x0f, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f,
- 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
- 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf0, 0xf0, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc,
- 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0,
- 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
- 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc3, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x03, 0x03, 0x03,
- 0x03, 0x3f, 0x3f, 0x3c, 0x3c, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xfc,
- 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x3f, 0x3f, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xfc,
- 0xfc, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
- 0xff, 0x3f, 0x3f, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0xc0,
- 0xc0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3f, 0x3f, 0xfc, 0xfc, 0xf0,
- 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
- 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
- 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xcf, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xcf, 0xcf, 0xcf, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xcf, 0xcf, 0xcf,
- 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
- 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x30, 0x30, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x00,
- 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xfc, 0xfc, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xff,
- 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0x03, 0x03, 0xc3, 0xc3, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff,
- 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
- 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- // 5x7 font (in 6x8 cell)
- const uint8_t ucSmallFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x06, 0x00, 0x07, 0x03, 0x00, 0x07,
- 0x03, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x2b, 0x6a, 0x12, 0x00, 0x63, 0x13, 0x08, 0x64, 0x63, 0x36, 0x49,
- 0x56, 0x20, 0x50, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x41, 0x3e, 0x00, 0x00,
- 0x08, 0x3e, 0x1c, 0x3e, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0xe0, 0x60, 0x00, 0x00, 0x08, 0x08, 0x08,
- 0x08, 0x08, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00,
- 0x42, 0x7f, 0x40, 0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x22, 0x49, 0x49, 0x49, 0x36, 0x18, 0x14, 0x12, 0x7f,
- 0x10, 0x2f, 0x49, 0x49, 0x49, 0x31, 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x01, 0x71, 0x09, 0x05, 0x03, 0x36, 0x49,
- 0x49, 0x49, 0x36, 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x00, 0x00,
- 0x08, 0x14, 0x22, 0x41, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59,
- 0x09, 0x06, 0x3e, 0x41, 0x5d, 0x55, 0x1e, 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e,
- 0x41, 0x41, 0x41, 0x22, 0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x7f, 0x09, 0x09, 0x09,
- 0x01, 0x3e, 0x41, 0x49, 0x49, 0x7a, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x41, 0x7f, 0x41, 0x00, 0x30, 0x40,
- 0x40, 0x40, 0x3f, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x7f, 0x02, 0x04, 0x02, 0x7f,
- 0x7f, 0x02, 0x04, 0x08, 0x7f, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x09, 0x09, 0x09, 0x06, 0x3e, 0x41, 0x51,
- 0x21, 0x5e, 0x7f, 0x09, 0x09, 0x19, 0x66, 0x26, 0x49, 0x49, 0x49, 0x32, 0x01, 0x01, 0x7f, 0x01, 0x01, 0x3f,
- 0x40, 0x40, 0x40, 0x3f, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x3f, 0x40, 0x3c, 0x40, 0x3f, 0x63, 0x14, 0x08, 0x14,
- 0x63, 0x07, 0x08, 0x70, 0x08, 0x07, 0x71, 0x49, 0x45, 0x43, 0x00, 0x00, 0x7f, 0x41, 0x41, 0x00, 0x02, 0x04,
- 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7f, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x00, 0x03, 0x07, 0x00, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x7f, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44,
- 0x44, 0x28, 0x38, 0x44, 0x44, 0x44, 0x7f, 0x38, 0x54, 0x54, 0x54, 0x08, 0x08, 0x7e, 0x09, 0x09, 0x00, 0x18,
- 0xa4, 0xa4, 0xa4, 0x7c, 0x7f, 0x04, 0x04, 0x78, 0x00, 0x00, 0x00, 0x7d, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7d,
- 0x00, 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x00, 0x7c, 0x04, 0x18, 0x04, 0x78, 0x7c, 0x04,
- 0x04, 0x78, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0xfc, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0xfc,
- 0x44, 0x78, 0x44, 0x04, 0x08, 0x08, 0x54, 0x54, 0x54, 0x20, 0x04, 0x3e, 0x44, 0x24, 0x00, 0x3c, 0x40, 0x20,
- 0x7c, 0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x3c, 0x60, 0x30, 0x60, 0x3c, 0x6c, 0x10, 0x10, 0x6c, 0x00, 0x9c,
- 0xa0, 0x60, 0x3c, 0x00, 0x64, 0x54, 0x54, 0x4c, 0x00, 0x08, 0x3e, 0x41, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00,
- 0x00, 0x00, 0x41, 0x41, 0x3e, 0x08, 0x02, 0x01, 0x02, 0x01, 0x00, 0x3c, 0x26, 0x23, 0x26, 0x3c };
-
- // Initialization sequences
- const unsigned char oled128_initbuf[] = { 0x00, 0xae, 0xdc, 0x00, 0x81, 0x40, 0xa1, 0xc8, 0xa8, 0x7f, 0xd5, 0x50, 0xd9,
- 0x22, 0xdb, 0x35, 0xb0, 0xda, 0x12, 0xa4, 0xa6, 0xaf };
-
- const unsigned char oled64_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
- 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
-
- const unsigned char oled32_initbuf[] = { 0x00, 0xae, 0xd5, 0x80, 0xa8, 0x1f, 0xd3, 0x00, 0x40, 0x8d, 0x14, 0xa1, 0xc8,
- 0xda, 0x02, 0x81, 0x7f, 0xd9, 0xf1, 0xdb, 0x40, 0xa4, 0xa6, 0xaf };
-
- const unsigned char oled72_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
- 0xad, 0x30, 0xd9, 0xf1, 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
-
- // some globals
-
- static void __oledWriteCommand(SSOLED *pOLED, unsigned char c);
- void __InvertBytes(uint8_t *pData, uint8_t bLen);
-
- // wrapper/adapter functions to make the code work on Linux
- static uint8_t pgm_read_byte(uint8_t *ptr)
- {
- return *ptr;
- }
- static int16_t pgm_read_word(uint8_t *ptr)
- {
- return ptr[0] + (ptr[1] << 8);
- }
-
- static void _I2CWrite(SSOLED *pOLED, unsigned char *pData, int iLen)
- {
- I2CWrite(&pOLED->bbi2c, pOLED->oled_addr, pData, iLen);
- } /* _I2CWrite() */
-
- //
- // Initializes the OLED controller into "page mode"
- //
- int __oledInit(SSOLED *pOLED, int bInvert, int32_t iSpeed)
- {
- unsigned char uc[4];
- int rc = OLED_NOT_FOUND;
- int iAddr = pOLED->oled_addr;
- int bFlip = (int) pOLED->oled_flip;
- int iType = pOLED->oled_type;
-
- pOLED->ucScreen = NULL; // reset backbuffer; user must provide one later
- pOLED->oled_wrap = 0; // default - disable text wrap
-
- I2CInit(&pOLED->bbi2c, iSpeed); // on Linux, SDA = bus number, SCL = device address
-
- // find the device address if requested
- if (iAddr == -1 || iAddr == 0 || iAddr == 0xff) // find it
- {
- I2CTest(&pOLED->bbi2c, 0x3c);
- if (I2CTest(&pOLED->bbi2c, 0x3c))
- pOLED->oled_addr = 0x3c;
- else if (I2CTest(&pOLED->bbi2c, 0x3d))
- pOLED->oled_addr = 0x3d;
- else
- return rc; // no display found!
- }
- else
- {
- pOLED->oled_addr = iAddr;
- I2CTest(&pOLED->bbi2c, iAddr);
- if (!I2CTest(&pOLED->bbi2c, iAddr))
- return rc; // no display found
- }
- // Detect the display controller (SSD1306, SH1107 or SH1106)
- uint8_t u = 0;
- I2CReadRegister(&pOLED->bbi2c, pOLED->oled_addr, 0x00, &u, 1); // read the status register
- u &= 0x0f; // mask off power on/off bit
- if (u == 0x7 || u == 0xf) // SH1107
- {
- pOLED->oled_type = OLED_128x128;
- rc = OLED_SH1107_3C;
- bFlip = !bFlip; // SH1107 seems to have this reversed from the usual direction
- }
- else if (u == 0x8) // SH1106
- {
- rc = OLED_SH1106_3C;
- pOLED->oled_type = OLED_132x64; // needs to be treated a little differently
- }
- else if (u == 3 || u == 6) // 6=128x64 display, 3=smaller
- {
- rc = OLED_SSD1306_3C;
- }
- if (pOLED->oled_addr == 0x3d)
- rc++; // return the '3D' version of the type
-
- if (iType == OLED_128x32 || iType == OLED_96x16)
- _I2CWrite(pOLED, (unsigned char *) oled32_initbuf, sizeof(oled32_initbuf));
- else if (iType == OLED_128x128)
- _I2CWrite(pOLED, (unsigned char *) oled128_initbuf, sizeof(oled128_initbuf));
- else if (iType == OLED_72x40)
- _I2CWrite(pOLED, (unsigned char *) oled72_initbuf, sizeof(oled72_initbuf));
- else
- // 132x64, 128x64 and 64x32
- _I2CWrite(pOLED, (unsigned char *) oled64_initbuf, sizeof(oled64_initbuf));
- if (bInvert)
- {
- uc[0] = 0; // command
- uc[1] = 0xa7; // invert command
- _I2CWrite(pOLED, uc, 2);
- }
- if (bFlip) // rotate display 180
- {
- uc[0] = 0; // command
- uc[1] = 0xa0;
- _I2CWrite(pOLED, uc, 2);
- uc[1] = 0xc0;
- _I2CWrite(pOLED, uc, 2);
- }
- pOLED->oled_x = 128; // assume 128x64
- pOLED->oled_y = 64;
- if (iType == OLED_96x16)
- {
- pOLED->oled_x = 96;
- pOLED->oled_y = 16;
- }
- else if (iType == OLED_128x32)
- pOLED->oled_y = 32;
- else if (iType == OLED_128x128)
- pOLED->oled_y = 128;
- else if (iType == OLED_64x32)
- {
- pOLED->oled_x = 64;
- pOLED->oled_y = 32;
- }
- else if (iType == OLED_72x40)
- {
- pOLED->oled_x = 72;
- pOLED->oled_y = 40;
- }
- return rc;
- } /* oledInit() */
- //
- // Sends a command to turn on or off the OLED display
- //
- void __oledPower(SSOLED *pOLED, uint8_t bOn)
- {
- if (bOn)
- __oledWriteCommand(pOLED, 0xaf); // turn on OLED
- else
- __oledWriteCommand(pOLED, 0xae); // turn off OLED
- } /* oledPower() */
-
- // Send a single byte command to the OLED controller
- static void __oledWriteCommand(SSOLED *pOLED, unsigned char c)
- {
- unsigned char buf[2];
-
- buf[0] = 0x00; // command introducer
- buf[1] = c;
- _I2CWrite(pOLED, buf, 2);
- } /* oledWriteCommand() */
-
- static void __oledWriteCommand2(SSOLED *pOLED, unsigned char c, unsigned char d)
- {
- unsigned char buf[3];
-
- buf[0] = 0x00;
- buf[1] = c;
- buf[2] = d;
- _I2CWrite(pOLED, buf, 3);
- } /* oledWriteCommand2() */
-
- //
- // Sets the brightness (0=off, 255=brightest)
- //
- void __oledSetContrast(SSOLED *pOLED, unsigned char ucContrast)
- {
- __oledWriteCommand2(pOLED, 0x81, ucContrast);
- } /* oledSetContrast() */
- //
- // Scroll the internal buffer by 1 scanline (up/down)
- // width is in pixels, lines is group of 8 rows
- //
- int __oledScrollBuffer(SSOLED *pOLED, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp)
- {
- uint8_t b, *s;
- int col, row;
-
- if (iStartCol < 0 || iStartCol > 127 || iEndCol < 0 || iEndCol > 127 || iStartCol > iEndCol) // invalid
- return -1;
- if (iStartRow < 0 || iStartRow > 7 || iEndRow < 0 || iEndRow > 7 || iStartRow > iEndRow)
- return -1;
-
- if (bUp)
- {
- for (row = iStartRow; row <= iEndRow; row++)
- {
- s = &pOLED->ucScreen[(row * 128) + iStartCol];
- for (col = iStartCol; col <= iEndCol; col++)
- {
- b = *s;
- b >>= 1; // scroll pixels 'up'
- if (row < iEndRow)
- b |= (s[128] << 7); // capture pixel of row below, except for last row
- *s++ = b;
- } // for col
- } // for row
- } // up
- else // down
- {
- for (row = iEndRow; row >= iStartRow; row--)
- {
- s = &pOLED->ucScreen[(row * 128) + iStartCol];
- for (col = iStartCol; col <= iEndCol; col++)
- {
- b = *s;
- b <<= 1; // scroll down
- if (row > iStartRow)
- b |= (s[-128] >> 7); // capture pixel of row above
- *s++ = b;
- } // for col
- } // for row
- }
- return 0;
- } /* oledScrollBuffer() */
- //
- // Send commands to position the "cursor" (aka memory write address)
- // to the given row and column
- //
- static void __oledSetPosition(SSOLED *pOLED, int x, int y, int bRender)
- {
- unsigned char buf[4];
-
- pOLED->iScreenOffset = (y * 128) + x;
- if (!bRender)
- return; // don't send the commands to the OLED if we're not rendering the graphics now
- if (pOLED->oled_type == OLED_64x32) // visible display starts at column 32, row 4
- {
- x += 32; // display is centered in VRAM, so this is always true
- if (pOLED->oled_flip == 0) // non-flipped display starts from line 4
- y += 4;
- }
- else if (pOLED->oled_type == OLED_132x64) // SH1106 has 128 pixels centered in 132
- {
- x += 2;
- }
- else if (pOLED->oled_type == OLED_96x16) // visible display starts at line 2
- { // mapping is a bit strange on the 96x16 OLED
- if (pOLED->oled_flip)
- x += 32;
- else
- y += 2;
- }
- else if (pOLED->oled_type == OLED_72x40) // starts at x=28,y=3
- {
- x += 28;
- if (!pOLED->oled_flip)
- {
- y += 3;
- }
- }
- buf[0] = 0x00; // command introducer
- buf[1] = 0xb0 | y; // set page to Y
- buf[2] = x & 0xf; // lower column address
- buf[3] = 0x10 | (x >> 4); // upper column addr
- _I2CWrite(pOLED, buf, 4);
- } /* oledSetPosition() */
-
- //
- // Write a block of pixel data to the OLED
- // Length can be anything from 1 to 1024 (whole display)
- //
- static void __oledWriteDataBlock(SSOLED *pOLED, unsigned char *ucBuf, int iLen, int bRender)
- {
- unsigned char ucTemp[129];
-
- ucTemp[0] = 0x40; // data command
- // Copying the data has the benefit in SPI mode of not letting
- // the original data get overwritten by the SPI.transfer() function
- if (bRender)
- {
- memcpy(&ucTemp[1], ucBuf, iLen);
- _I2CWrite(pOLED, ucTemp, iLen + 1);
- }
- // Keep a copy in local buffer
- if (pOLED->ucScreen)
- {
- memcpy(&pOLED->ucScreen[pOLED->iScreenOffset], ucBuf, iLen);
- pOLED->iScreenOffset += iLen;
- pOLED->iScreenOffset &= 1023; // we use a fixed stride of 128 no matter what the display size
- }
- }
- //
- // Byte operands for compressing the data
- // The first 2 bits are the type, followed by the counts
- #define OP_MASK 0xc0
- #define OP_SKIPCOPY 0x00
- #define OP_COPYSKIP 0x40
- #define OP_REPEATSKIP 0x80
- #define OP_REPEAT 0xc0
- //
- // Write a block of flash memory to the display
- //
- void __oledWriteFlashBlock(SSOLED *pOLED, uint8_t *s, int iLen)
- {
- int j;
- int iWidthMask = pOLED->oled_x - 1;
- int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
- int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 wide
- uint8_t ucTemp[128];
-
- while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
- {
- j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
- memcpy(ucTemp, s, j);
- __oledWriteDataBlock(pOLED, ucTemp, j, 1);
- s += j;
- iLen -= j;
- pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
- __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
- } // while it needs some help
- memcpy(ucTemp, s, iLen);
- __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
- pOLED->iScreenOffset = (pOLED->iScreenOffset + iLen) & iSizeMask;
- } /* oledWriteFlashBlock() */
-
- //
- // Write a repeating byte to the display
- //
- void __oledRepeatByte(SSOLED *pOLED, uint8_t b, int iLen)
- {
- int j;
- int iWidthMask = pOLED->oled_x - 1;
- int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 pixels wide
- int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
- uint8_t ucTemp[128];
-
- memset(ucTemp, b, (iLen > 128) ? 128 : iLen);
- while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
- {
- j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
- __oledWriteDataBlock(pOLED, ucTemp, j, 1);
- iLen -= j;
- pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
- __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
- } // while it needs some help
- __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
- pOLED->iScreenOffset += iLen;
- } /* oledRepeatByte() */
-
- //
- // Play a frame of animation data
- // The animation data is assumed to be encoded for a full frame of the display
- // Given the pointer to the start of the compressed data,
- // it returns the pointer to the start of the next frame
- // Frame rate control is up to the calling program to manage
- // When it finishes the last frame, it will start again from the beginning
- //
- uint8_t * __oledPlayAnimFrame(SSOLED *pOLED, uint8_t *pAnimation, uint8_t *pCurrent, int iLen)
- {
- uint8_t *s;
- int i, j;
- unsigned char b, bCode;
- int iBufferSize = (pOLED->oled_x * pOLED->oled_y) / 8; // size in bytes of the display devce
- int iWidthMask, iWidthShift;
-
- iWidthMask = pOLED->oled_x - 1;
- iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // 128 or 64 pixels wide
- if (pCurrent == NULL || pCurrent > pAnimation + iLen)
- return NULL; // invalid starting point
-
- s = (uint8_t *) pCurrent; // start of animation data
- i = 0;
- __oledSetPosition(pOLED, 0, 0, 1);
- while (i < iBufferSize) // run one frame
- {
- bCode = pgm_read_byte(s++);
- switch (bCode & OP_MASK)
- // different compression types
- {
- case OP_SKIPCOPY: // skip/copy
- if (bCode == OP_SKIPCOPY) // big skip
- {
- b = pgm_read_byte(s++);
- i += b + 1;
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- else // skip/copy
- {
- if (bCode & 0x38)
- {
- i += ((bCode & 0x38) >> 3); // skip amount
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- if (bCode & 7)
- {
- __oledWriteFlashBlock(pOLED, s, bCode & 7);
- s += (bCode & 7);
- i += bCode & 7;
- }
- }
- break;
- case OP_COPYSKIP: // copy/skip
- if (bCode == OP_COPYSKIP) // big copy
- {
- b = pgm_read_byte(s++);
- j = b + 1;
- __oledWriteFlashBlock(pOLED, s, j);
- s += j;
- i += j;
- }
- else
- {
- j = ((bCode & 0x38) >> 3);
- if (j)
- {
- __oledWriteFlashBlock(pOLED, s, j);
- s += j;
- i += j;
- }
- if (bCode & 7)
- {
- i += (bCode & 7); // skip
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- }
- break;
- case OP_REPEATSKIP: // repeat/skip
- j = (bCode & 0x38) >> 3; // repeat count
- b = pgm_read_byte(s++);
- __oledRepeatByte(pOLED, b, j);
- i += j;
- if (bCode & 7)
- {
- i += (bCode & 7); // skip amount
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- break;
-
- case OP_REPEAT:
- j = (bCode & 0x3f) + 1;
- b = pgm_read_byte(s++);
- __oledRepeatByte(pOLED, b, j);
- i += j;
- break;
- } // switch on code type
- } // while rendering a frame
- if (s >= pAnimation + iLen) // we've hit the end, restart from the beginning
- s = pAnimation;
- return s; // return pointer to start of next frame
- } /* oledPlayAnimFrame() */
- //
- // Draw a sprite of any size in any position
- // If it goes beyond the left/right or top/bottom edges
- // it's trimmed to show the valid parts
- // This function requires a back buffer to be defined
- // The priority color (0 or 1) determines which color is painted
- // when a 1 is encountered in the source image.
- //
- void __oledDrawSprite(SSOLED *pOLED, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
- {
- int tx, ty, dx, dy, iStartX;
- uint8_t *s, *d, uc, pix, ucSrcMask, ucDstMask;
-
- if (x + cx < 0 || y + cy < 0 || x >= pOLED->oled_x || y >= pOLED->oled_y || pOLED->ucScreen == NULL)
- return; // no backbuffer or out of bounds
- dy = y; // destination y
- if (y < 0) // skip the invisible parts
- {
- cy += y;
- y = -y;
- pSprite += (y * iPitch);
- dy = 0;
- }
- if (y + cy > pOLED->oled_y)
- cy = pOLED->oled_y - y;
- iStartX = 0;
- dx = x;
- if (x < 0)
- {
- cx += x;
- x = -x;
- iStartX = x;
- dx = 0;
- }
- if (x + cx > pOLED->oled_x)
- cx = pOLED->oled_x - x;
- for (ty = 0; ty < cy; ty++)
- {
- s = &pSprite[iStartX >> 3];
- d = &pOLED->ucScreen[(dy >> 3) * pOLED->oled_x + dx];
- ucSrcMask = 0x80 >> (iStartX & 7);
- pix = *s++;
- ucDstMask = 1 << (dy & 7);
- if (iPriority) // priority color is 1
- {
- for (tx = 0; tx < cx; tx++)
- {
- uc = d[0];
- if (pix & ucSrcMask) // set pixel in source, set it in dest
- d[0] = (uc | ucDstMask);
- d++; // next pixel column
- ucSrcMask >>= 1;
- if (ucSrcMask == 0) // read next byte
- {
- ucSrcMask = 0x80;
- pix = *s++;
- }
- } // for tx
- } // priorty color 1
- else
- {
- for (tx = 0; tx < cx; tx++)
- {
- uc = d[0];
- if (pix & ucSrcMask) // clr pixel in source, clr it in dest
- d[0] = (uc & ~ucDstMask);
- d++; // next pixel column
- ucSrcMask >>= 1;
- if (ucSrcMask == 0) // read next byte
- {
- ucSrcMask = 0x80;
- pix = *s++;
- }
- } // for tx
- } // priority color 0
- dy++;
- pSprite += iPitch;
- } // for ty
- } /* oledDrawSprite() */
- //
- // Draw a 16x16 tile in any of 4 rotated positions
- // Assumes input image is laid out like "normal" graphics with
- // the MSB on the left and 2 bytes per line
- // On AVR, the source image is assumed to be in FLASH memory
- // The function can draw the tile on byte boundaries, so the x value
- // can be from 0 to 112 and y can be from 0 to 6
- //
- void __oledDrawTile(SSOLED *pOLED, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender)
- {
- uint8_t ucTemp[32]; // prepare LCD data here
- uint8_t i, j, k, iOffset, ucMask, uc, ucPixels;
- uint8_t bFlipX = 0, bFlipY = 0;
-
- if (x < 0 || y < 0 || y > 6 || x > 112)
- return; // out of bounds
- if (pTile == NULL)
- return; // bad pointer; really? :(
- if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPX)
- bFlipX = 1;
- if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPY)
- bFlipY = 1;
-
- memset(ucTemp, 0, sizeof(ucTemp)); // we only set white pixels, so start from black
- if (iRotation == ANGLE_0 || iRotation == ANGLE_180 || iRotation == ANGLE_FLIPX || iRotation == ANGLE_FLIPY)
- {
- for (j = 0; j < 16; j++) // y
- {
- for (i = 0; i < 16; i += 8) // x
- {
- ucPixels = pgm_read_byte((uint8_t*) pTile++);
- ucMask = 0x80; // MSB is the first source pixel
- for (k = 0; k < 8; k++)
- {
- if (ucPixels & ucMask) // translate the pixel
- {
- if (bFlipY)
- uc = 0x80 >> (j & 7);
- else
- uc = 1 << (j & 7);
- iOffset = i + k;
- if (bFlipX)
- iOffset = 15 - iOffset;
- iOffset += (j & 8) << 1; // top/bottom half of output
- if (bFlipY)
- iOffset ^= 16;
- ucTemp[iOffset] |= uc;
- }
- ucMask >>= 1;
- } // for k
- } // for i
- } // for j
- }
- else // rotated 90/270
- {
- for (j = 0; j < 16; j++) // y
- {
- for (i = 0; i < 16; i += 8) // x
- {
- ucPixels = pgm_read_byte((uint8_t*) pTile++);
- ucMask = 0x80; // MSB is the first source pixel
- for (k = 0; k < 8; k++)
- {
- if (ucPixels & ucMask) // translate the pixel
- {
- if (bFlipY)
- uc = 0x80 >> k;
- else
- uc = 1 << k;
- iOffset = 15 - j;
- if (bFlipX)
- iOffset = 15 - iOffset;
- iOffset += i << 1; // top/bottom half of output
- if (bFlipY)
- iOffset ^= 16;
- ucTemp[iOffset] |= uc;
- }
- ucMask >>= 1;
- } // for k
- } // for i
- } // for j
- }
- if (bInvert)
- __InvertBytes(ucTemp, 32);
- // Send the data to the display
- __oledSetPosition(pOLED, x, y, bRender);
- __oledWriteDataBlock(pOLED, ucTemp, 16, bRender); // top half
- __oledSetPosition(pOLED, x, y + 1, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[16], 16, bRender); // bottom half
- } /* oledDrawTile() */
-
- // Set (or clear) an individual pixel
- // The local copy of the frame buffer is used to avoid
- // reading data from the display controller
- int __oledSetPixel(SSOLED *pOLED, int x, int y, unsigned char ucColor, int bRender)
- {
- int i;
- unsigned char uc, ucOld;
-
- i = ((y >> 3) * 128) + x;
- if (i < 0 || i > 1023) // off the screen
- return -1;
- __oledSetPosition(pOLED, x, y >> 3, bRender);
-
- if (pOLED->ucScreen)
- uc = ucOld = pOLED->ucScreen[i];
- else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // SH1106/SH1107 can read data
- {
- uint8_t ucTemp[3];
- ucTemp[0] = 0x80; // one command
- ucTemp[1] = 0xE0; // read_modify_write
- ucTemp[2] = 0xC0; // one data
- _I2CWrite(pOLED, ucTemp, 3);
-
- // read a dummy byte followed by the data byte we want
- I2CRead(&pOLED->bbi2c, pOLED->oled_addr, ucTemp, 2);
- uc = ucOld = ucTemp[1]; // first byte is garbage
- }
- else
- uc = ucOld = 0;
-
- uc &= ~(0x1 << (y & 7));
- if (ucColor)
- {
- uc |= (0x1 << (y & 7));
- }
- if (uc != ucOld) // pixel changed
- {
- // oledSetPosition(x, y>>3);
- if (pOLED->ucScreen)
- {
- __oledWriteDataBlock(pOLED, &uc, 1, bRender);
- pOLED->ucScreen[i] = uc;
- }
- else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // end the read_modify_write operation
- {
- uint8_t ucTemp[4];
- ucTemp[0] = 0xc0; // one data
- ucTemp[1] = uc; // actual data
- ucTemp[2] = 0x80; // one command
- ucTemp[3] = 0xEE; // end read_modify_write operation
- _I2CWrite(pOLED, ucTemp, 4);
- }
- }
- return 0;
- } /* oledSetPixel() */
-
- //
- // Invert font data
- //
- void __InvertBytes(uint8_t *pData, uint8_t bLen)
- {
- uint8_t i;
- for (i = 0; i < bLen; i++)
- {
- *pData = ~(*pData);
- pData++;
- }
- } /* InvertBytes() */
-
- //
- // Load a 128x64 1-bpp Windows bitmap
- // Pass the pointer to the beginning of the BMP file
- // First pass version assumes a full screen bitmap
- //
- int __oledLoadBMP(SSOLED *pOLED, uint8_t *pBMP, int bInvert, int bRender)
- {
- int16_t i16;
- int iOffBits, q, y, j; // offset to bitmap data
- int iPitch;
- uint8_t x, z, b, *s;
- uint8_t dst_mask;
- uint8_t ucTemp[16]; // process 16 bytes at a time
- uint8_t bFlipped = false;
-
- i16 = pgm_read_word(pBMP);
- if (i16 != 0x4d42) // must start with 'BM'
- return -1; // not a BMP file
- i16 = pgm_read_word(pBMP + 18);
- if (i16 != 128) // must be 128 pixels wide
- return -1;
- i16 = pgm_read_word(pBMP + 22);
- if (i16 != 64 && i16 != -64) // must be 64 pixels tall
- return -1;
- if (i16 == 64) // BMP is flipped vertically (typical)
- bFlipped = true;
- i16 = pgm_read_word(pBMP + 28);
- if (i16 != 1) // must be 1 bit per pixel
- return -1;
- iOffBits = pgm_read_word(pBMP + 10);
- iPitch = 16;
- if (bFlipped)
- {
- iPitch = -16;
- iOffBits += (63 * 16); // start from bottom
- }
-
- // rotate the data and send it to the display
- for (y = 0; y < 8; y++) // 8 lines of 8 pixels
- {
- __oledSetPosition(pOLED, 0, y, bRender);
- for (j = 0; j < 8; j++) // do 8 sections of 16 columns
- {
- s = &pBMP[iOffBits + (j * 2) + (y * iPitch * 8)]; // source line
- memset(ucTemp, 0, 16); // start with all black
- for (x = 0; x < 16; x += 8) // do each block of 16x8 pixels
- {
- dst_mask = 1;
- for (q = 0; q < 8; q++) // gather 8 rows
- {
- b = pgm_read_byte(s + (q * iPitch));
- for (z = 0; z < 8; z++) // gather up the 8 bits of this column
- {
- if (b & 0x80)
- ucTemp[x + z] |= dst_mask;
- b <<= 1;
- } // for z
- dst_mask <<= 1;
- } // for q
- s++; // next source byte
- } // for x
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, ucTemp, 16, bRender);
- } // for j
- } // for y
- return 0;
- } /* oledLoadBMP() */
- //
- // Set the current cursor position
- // The column represents the pixel column (0-127)
- // The row represents the text row (0-7)
- //
- void __oledSetCursor(SSOLED *pOLED, int x, int y)
- {
- pOLED->iCursorX = x;
- pOLED->iCursorY = y;
- } /* oledSetCursor() */
- //
- // Turn text wrap on or off for the oldWriteString() function
- //
- void __oledSetTextWrap(SSOLED *pOLED, int bWrap)
- {
- pOLED->oled_wrap = bWrap;
- } /* oledSetTextWrap() */
- //
- // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
- // At the given col+row
- //
- int __oledWriteString(SSOLED *pOLED, int iScroll, int x, int y, char *szMsg, int iSize, int bInvert, int bRender)
- {
- int i, iFontOff, iLen, iFontSkip;
- unsigned char c, *s, ucTemp[40];
-
- if (x == -1 || y == -1) // use the cursor position
- {
- x = pOLED->iCursorX;
- y = pOLED->iCursorY;
- }
- else
- {
- pOLED->iCursorX = x;
- pOLED->iCursorY = y; // set the new cursor position
- }
- if (pOLED->iCursorX >= pOLED->oled_x || pOLED->iCursorY >= pOLED->oled_y / 8)
- return -1; // can't draw off the display
-
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- if (iSize == FONT_8x8) // 8x8 font
- {
- i = 0;
- iFontSkip = iScroll & 7; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && szMsg[i] != 0 && pOLED->iCursorY < pOLED->oled_y / 8)
- {
- if (iScroll < 8) // only display visible characters
- {
- c = (unsigned char) szMsg[i];
- iFontOff = (int) (c - 32) * 7;
- // we can't directly use the pointer to FLASH memory, so copy to a local buffer
- ucTemp[0] = 0;
- memcpy(&ucTemp[1], &ucFont[iFontOff], 7);
- if (bInvert)
- __InvertBytes(ucTemp, 8);
- // oledCachedWrite(ucTemp, 8);
- iLen = 8 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 7 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY++;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- iFontSkip = 0;
- }
- iScroll -= 8;
- i++;
- } // while
- // oledCachedFlush(); // write any remaining data
- return 0;
- } // 8x8
- #ifndef __AVR__
- else if (iSize == FONT_16x32) // 16x32 font
- {
- i = 0;
- iFontSkip = iScroll & 15; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 3 && szMsg[i] != 0)
- {
- if (iScroll < 16) // if characters are visible
- {
- s = (unsigned char *) &ucBigFont[(unsigned char) (szMsg[i] - 32) * 64];
- iLen = 16 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- // we can't directly use the pointer to FLASH memory, so copy to a local buffer
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- memcpy(ucTemp, s, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
- memcpy(ucTemp, s + 16, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- if (pOLED->iCursorY <= 5)
- {
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 2, bRender);
- memcpy(ucTemp, s + 32, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- }
- if (pOLED->iCursorY <= 4)
- {
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 3, bRender);
- memcpy(ucTemp, s + 48, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- }
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY += 4;
- }
- iFontSkip = 0;
- } // if character visible from scrolling
- iScroll -= 16;
- i++;
- } // while
- return 0;
- } // 16x32
- #endif // !__AVR__
- else if (iSize == FONT_12x16) // 6x8 stretched to 12x16
- {
- i = 0;
- iFontSkip = iScroll % 12; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
- {
- // stretch the 'normal' font instead of using the big font
- if (iScroll < 12) // if characters are visible
- {
- int tx, ty;
- c = szMsg[i] - 32;
- unsigned char uc1, uc2, ucMask, *pDest;
- s = (unsigned char *) &ucSmallFont[(int) c * 5];
- ucTemp[0] = 0; // first column is blank
- memcpy(&ucTemp[1], s, 6);
- if (bInvert)
- __InvertBytes(ucTemp, 6);
- // Stretch the font to double width + double height
- memset(&ucTemp[6], 0, 24); // write 24 new bytes
- for (tx = 0; tx < 6; tx++)
- {
- ucMask = 3;
- pDest = &ucTemp[6 + tx * 2];
- uc1 = uc2 = 0;
- c = ucTemp[tx];
- for (ty = 0; ty < 4; ty++)
- {
- if (c & (1 << ty)) // a bit is set
- uc1 |= ucMask;
- if (c & (1 << (ty + 4)))
- uc2 |= ucMask;
- ucMask <<= 2;
- }
- pDest[0] = uc1;
- pDest[1] = uc1; // double width
- pDest[12] = uc2;
- pDest[13] = uc2;
- }
- // smooth the diagonal lines
- for (tx = 0; tx < 5; tx++)
- {
- uint8_t c0, c1, ucMask2;
- c0 = ucTemp[tx];
- c1 = ucTemp[tx + 1];
- pDest = &ucTemp[6 + tx * 2];
- ucMask = 1;
- ucMask2 = 2;
- for (ty = 0; ty < 7; ty++)
- {
- if (((c0 & ucMask) && !(c1 & ucMask) && !(c0 & ucMask2) && (c1 & ucMask2))
- || (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2)))
- {
- if (ty < 3) // top half
- {
- pDest[1] |= (1 << ((ty * 2) + 1));
- pDest[2] |= (1 << ((ty * 2) + 1));
- pDest[1] |= (1 << ((ty + 1) * 2));
- pDest[2] |= (1 << ((ty + 1) * 2));
- }
- else if (ty == 3) // on the border
- {
- pDest[1] |= 0x80;
- pDest[2] |= 0x80;
- pDest[13] |= 1;
- pDest[14] |= 1;
- }
- else // bottom half
- {
- pDest[13] |= (1 << (2 * (ty - 4) + 1));
- pDest[14] |= (1 << (2 * (ty - 4) + 1));
- pDest[13] |= (1 << ((ty - 3) * 2));
- pDest[14] |= (1 << ((ty - 3) * 2));
- }
- }
- else if (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2))
- {
- if (ty < 4) // top half
- {
- pDest[1] |= (1 << ((ty * 2) + 1));
- pDest[2] |= (1 << ((ty + 1) * 2));
- }
- else
- {
- pDest[13] |= (1 << (2 * (ty - 4) + 1));
- pDest[14] |= (1 << ((ty - 3) * 2));
- }
- }
- ucMask <<= 1;
- ucMask2 <<= 1;
- }
- }
- iLen = 12 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[6 + iFontSkip], iLen, bRender);
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[18 + iFontSkip], iLen, bRender);
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 11 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY += 2;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- iFontSkip = 0;
- } // if characters are visible
- iScroll -= 12;
- i++;
- } // while
- return 0;
- } // 12x16
- else if (iSize == FONT_16x16) // 8x8 stretched to 16x16
- {
- i = 0;
- iFontSkip = iScroll & 15; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
- {
- // stretch the 'normal' font instead of using the big font
- if (iScroll < 16) // if characters are visible
- {
- int tx, ty;
- c = szMsg[i] - 32;
- unsigned char uc1, uc2, ucMask, *pDest;
- s = (unsigned char *) &ucFont[(int) c * 7];
- ucTemp[0] = 0;
- memcpy(&ucTemp[1], s, 7);
- if (bInvert)
- __InvertBytes(ucTemp, 8);
- // Stretch the font to double width + double height
- memset(&ucTemp[8], 0, 32); // write 32 new bytes
- for (tx = 0; tx < 8; tx++)
- {
- ucMask = 3;
- pDest = &ucTemp[8 + tx * 2];
- uc1 = uc2 = 0;
- c = ucTemp[tx];
- for (ty = 0; ty < 4; ty++)
- {
- if (c & (1 << ty)) // a bit is set
- uc1 |= ucMask;
- if (c & (1 << (ty + 4)))
- uc2 |= ucMask;
- ucMask <<= 2;
- }
- pDest[0] = uc1;
- pDest[1] = uc1; // double width
- pDest[16] = uc2;
- pDest[17] = uc2;
- }
- iLen = 16 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[8 + iFontSkip], iLen, bRender);
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[24 + iFontSkip], iLen, bRender);
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY += 2;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- iFontSkip = 0;
- } // if characters are visible
- iScroll -= 16;
- i++;
- } // while
- return 0;
- } // 16x16
- else if (iSize == FONT_6x8) // 6x8 font
- {
- i = 0;
- iFontSkip = iScroll % 6;
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) && szMsg[i] != 0)
- {
- if (iScroll < 6) // if characters are visible
- {
- c = szMsg[i] - 32;
- // we can't directly use the pointer to FLASH memory, so copy to a local buffer
- ucTemp[0] = 0;
- memcpy(&ucTemp[1], &ucSmallFont[(int) c * 5], 5);
- if (bInvert)
- __InvertBytes(ucTemp, 6);
- iLen = 6 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- // oledCachedWrite(ucTemp, 6);
- pOLED->iCursorX += iLen;
- iFontSkip = 0;
- if (pOLED->iCursorX >= pOLED->oled_x - 5 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY++;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- } // if characters are visible
- iScroll -= 6;
- i++;
- }
- // oledCachedFlush(); // write any remaining data
- return 0;
- } // 6x8
- return -1; // invalid size
- } /* oledWriteString() */
-
- //
- // Render a sprite/rectangle of pixels from a provided buffer to the display.
- // The row values refer to byte rows, not pixel rows due to the memory
- // layout of OLEDs.
- // returns 0 for success, -1 for invalid parameter
- //
- int __oledDrawGFX(SSOLED *pOLED, uint8_t *pBuffer, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth,
- int iHeight, int iSrcPitch)
- {
- int y;
-
- if (iSrcCol < 0 || iSrcCol > 127 || iSrcRow < 0 || iSrcRow > 7 || iDestCol < 0 || iDestCol >= pOLED->oled_x
- || iDestRow < 0 || iDestRow >= (pOLED->oled_y >> 3) || iSrcPitch <= 0)
- return -1; // invalid
-
- for (y = iSrcRow; y < iSrcRow + iHeight; y++)
- {
- uint8_t *s = &pBuffer[(y * iSrcPitch) + iSrcCol];
- __oledSetPosition(pOLED, iDestCol, iDestRow, 1);
- __oledWriteDataBlock(pOLED, s, iWidth, 1);
- pBuffer += iSrcPitch;
- iDestRow++;
- } // for y
- return 0;
- } /* oledDrawGFX() */
- //
- // Dump a screen's worth of data directly to the display
- // Try to speed it up by comparing the new bytes with the existing buffer
- //
- void __oledDumpBuffer(SSOLED *pOLED, uint8_t *pBuffer)
- {
- int x, y;
- int iLines, iCols;
- uint8_t bNeedPos;
- uint8_t *pSrc = pOLED->ucScreen;
-
- if (pBuffer == NULL) // dump the internal buffer if none is given
- pBuffer = pOLED->ucScreen;
- if (pBuffer == NULL)
- return; // no backbuffer and no provided buffer
-
- iLines = pOLED->oled_y >> 3;
- iCols = pOLED->oled_x >> 4;
- for (y = 0; y < iLines; y++)
- {
- bNeedPos = 1; // start of a new line means we need to set the position too
- for (x = 0; x < iCols; x++) // wiring library has a 32-byte buffer, so send 16 bytes so that the data prefix (0x40) can fit
- {
- if (pOLED->ucScreen == NULL || pBuffer == pSrc || memcmp(pSrc, pBuffer, 16) != 0) // doesn't match, need to send it
- {
- if (bNeedPos) // need to reposition output cursor?
- {
- bNeedPos = 0;
- __oledSetPosition(pOLED, x * 16, y, 1);
- }
- __oledWriteDataBlock(pOLED, pBuffer, 16, 1);
- }
- else
- {
- bNeedPos = 1; // we're skipping a block, so next time will need to set the new position
- }
- pSrc += 16;
- pBuffer += 16;
- } // for x
- pSrc += (128 - pOLED->oled_x); // for narrow displays, skip to the next line
- pBuffer += (128 - pOLED->oled_x);
- } // for y
- } /* oledDumpBuffer() */
- //
- // Fill the frame buffer with a byte pattern
- // e.g. all off (0x00) or all on (0xff)
- //
- void __oledFill(SSOLED *pOLED, unsigned char ucData, int bRender)
- {
- uint8_t x, y;
- uint8_t iLines, iCols;
- unsigned char temp[16];
-
- iLines = pOLED->oled_y >> 3;
- iCols = pOLED->oled_x >> 4;
- memset(temp, ucData, 16);
- pOLED->iCursorX = pOLED->iCursorY = 0;
-
- for (y = 0; y < iLines; y++)
- {
- __oledSetPosition(pOLED, 0, y, bRender); // set to (0,Y)
- for (x = 0; x < iCols; x++) // wiring library has a 32-byte buffer, so send 16 bytes so that the data prefix (0x40) can fit
- {
- __oledWriteDataBlock(pOLED, temp, 16, bRender);
- } // for x
- // 72 isn't evenly divisible by 16, so fix it
- if (pOLED->oled_type == OLED_72x40)
- __oledWriteDataBlock(pOLED, temp, 8, bRender);
- } // for y
- if (pOLED->ucScreen)
- memset(pOLED->ucScreen, ucData, (pOLED->oled_x * pOLED->oled_y) / 8);
- } /* oledFill() */
-
- //
- // Provide or revoke a back buffer for your OLED graphics
- // This allows you to manage the RAM used by ss_oled on tiny
- // embedded platforms like the ATmega series
- // Pass NULL to revoke the buffer. Make sure you provide a buffer
- // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
- //
- void __oledSetBackBuffer(SSOLED *pOLED, uint8_t *pBuffer)
- {
- pOLED->ucScreen = pBuffer;
- } /* oledSetBackBuffer() */
-
- void __oledDrawLine(SSOLED *pOLED, int x1, int y1, int x2, int y2, int bRender)
- {
- int temp;
- int dx = x2 - x1;
- int dy = y2 - y1;
- int error;
- uint8_t *p, *pStart, mask, bOld, bNew;
- int xinc, yinc;
- int y, x;
-
- if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pOLED->oled_x || x2 >= pOLED->oled_x || y1 >= pOLED->oled_y
- || y2 >= pOLED->oled_y)
- return;
-
- if (abs(dx) > abs(dy))
- {
- // X major case
- if (x2 < x1)
- {
- dx = -dx;
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- }
-
- y = y1;
- dy = (y2 - y1);
- error = dx >> 1;
- yinc = 1;
- if (dy < 0)
- {
- dy = -dy;
- yinc = -1;
- }
- p = pStart = &pOLED->ucScreen[x1 + ((y >> 3) << 7)]; // point to current spot in back buffer
- mask = 1 << (y & 7); // current bit offset
- for (x = x1; x1 <= x2; x1++)
- {
- *p++ |= mask; // set pixel and increment x pointer
- error -= dy;
- if (error < 0)
- {
- error += dx;
- if (yinc > 0)
- mask <<= 1;
- else
- mask >>= 1;
- if (mask == 0) // we've moved outside the current row, write the data we changed
- {
- __oledSetPosition(pOLED, x, y >> 3, bRender);
- __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender); // write the row we changed
- x = x1 + 1; // we've already written the byte at x1
- y1 = y + yinc;
- p += (yinc > 0) ? 128 : -128;
- pStart = p;
- mask = 1 << (y1 & 7);
- }
- y += yinc;
- }
- } // for x1
- if (p != pStart) // some data needs to be written
- {
- __oledSetPosition(pOLED, x, y >> 3, bRender);
- __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender);
- }
- }
- else
- {
- // Y major case
- if (y1 > y2)
- {
- dy = -dy;
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- }
-
- p = &pOLED->ucScreen[x1 + ((y1 >> 3) * 128)]; // point to current spot in back buffer
- bOld = bNew = p[0]; // current data at that address
- mask = 1 << (y1 & 7); // current bit offset
- dx = (x2 - x1);
- error = dy >> 1;
- xinc = 1;
- if (dx < 0)
- {
- dx = -dx;
- xinc = -1;
- }
- for (x = x1; y1 <= y2; y1++)
- {
- bNew |= mask; // set the pixel
- error -= dx;
- mask <<= 1; // y1++
- if (mask == 0) // we're done with this byte, write it if necessary
- {
- if (bOld != bNew)
- {
- p[0] = bNew; // save to RAM
- __oledSetPosition(pOLED, x, y1 >> 3, bRender);
- __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
- }
- p += 128; // next line
- bOld = bNew = p[0];
- mask = 1; // start at LSB again
- }
- if (error < 0)
- {
- error += dy;
- if (bOld != bNew) // write the last byte we modified if it changed
- {
- p[0] = bNew; // save to RAM
- __oledSetPosition(pOLED, x, y1 >> 3, bRender);
- __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
- }
- p += xinc;
- x += xinc;
- bOld = bNew = p[0];
- }
- } // for y
- if (bOld != bNew) // write the last byte we modified if it changed
- {
- p[0] = bNew; // save to RAM
- __oledSetPosition(pOLED, x, y2 >> 3, bRender);
- __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
- }
- } // y major case
- } /* oledDrawLine() */
-
- //
- // For drawing ellipses, a circle is drawn and the x and y pixels are scaled by a 16-bit integer fraction
- // This function draws a single pixel and scales its position based on the x/y fraction of the ellipse
- //
- static void __DrawScaledPixel(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
- uint8_t ucColor)
- {
- uint8_t *d, ucMask;
-
- if (iXFrac != 0x10000)
- x = ((x * iXFrac) >> 16);
- if (iYFrac != 0x10000)
- y = ((y * iYFrac) >> 16);
- x += iCX;
- y += iCY;
- if (x < 0 || x >= pOLED->oled_x || y < 0 || y >= pOLED->oled_y)
- return; // off the screen
- d = &pOLED->ucScreen[((y >> 3) * 128) + x];
- ucMask = 1 << (y & 7);
- if (ucColor)
- *d |= ucMask;
- else
- *d &= ~ucMask;
- } /* DrawScaledPixel() */
- //
- // For drawing filled ellipses
- //
- static void __DrawScaledLine(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
- uint8_t ucColor)
- {
- int iLen, x2;
- uint8_t *d, ucMask;
- if (iXFrac != 0x10000)
- x = ((x * iXFrac) >> 16);
- if (iYFrac != 0x10000)
- y = ((y * iYFrac) >> 16);
- iLen = x * 2;
- x = iCX - x;
- y += iCY;
- x2 = x + iLen;
- if (y < 0 || y >= pOLED->oled_y)
- return; // completely off the screen
- if (x < 0)
- x = 0;
- if (x2 >= pOLED->oled_x)
- x2 = pOLED->oled_x - 1;
- iLen = x2 - x + 1; // new length
- d = &pOLED->ucScreen[((y >> 3) * 128) + x];
- ucMask = 1 << (y & 7);
- if (ucColor) // white
- {
- for (; iLen > 0; iLen--)
- *d++ |= ucMask;
- }
- else // black
- {
- for (; iLen > 0; iLen--)
- *d++ &= ~ucMask;
- }
- } /* DrawScaledLine() */
- //
- // Draw the 8 pixels around the Bresenham circle
- // (scaled to make an ellipse)
- //
- static void BresenhamCircle(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
- uint8_t ucColor, uint8_t bFill)
- {
- if (bFill) // draw a filled ellipse
- {
- // for a filled ellipse, draw 4 lines instead of 8 pixels
- __DrawScaledLine(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
- __DrawScaledLine(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
- __DrawScaledLine(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
- __DrawScaledLine(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
- }
- else // draw 8 pixels around the edges
- {
- __DrawScaledPixel(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -x, y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -x, -y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -y, x, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -y, -x, iXFrac, iYFrac, ucColor);
- }
- } /* BresenhamCircle() */
-
- //
- // Draw an outline or filled ellipse
- //
- void __oledEllipse(SSOLED *pOLED, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor,
- uint8_t bFilled)
- {
- int32_t iXFrac, iYFrac;
- int iRadius, iDelta, x, y;
-
- if (pOLED == NULL || pOLED->ucScreen == NULL)
- return; // must have back buffer defined
- if (iRadiusX <= 0 || iRadiusY <= 0)
- return; // invalid radii
-
- if (iRadiusX > iRadiusY) // use X as the primary radius
- {
- iRadius = iRadiusX;
- iXFrac = 65536;
- iYFrac = (iRadiusY * 65536) / iRadiusX;
- }
- else
- {
- iRadius = iRadiusY;
- iXFrac = (iRadiusX * 65536) / iRadiusY;
- iYFrac = 65536;
- }
- iDelta = 3 - (2 * iRadius);
- x = 0;
- y = iRadius;
- while (x <= y)
- {
- BresenhamCircle(pOLED, iCenterX, iCenterY, x, y, iXFrac, iYFrac, ucColor, bFilled);
- x++;
- if (iDelta < 0)
- {
- iDelta += (4 * x) + 6;
- }
- else
- {
- iDelta += 4 * (x - y) + 10;
- y--;
- }
- }
- } /* oledEllipse() */
- //
- // Draw an outline or filled rectangle
- //
- void __oledRectangle(SSOLED *pOLED, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled)
- {
- uint8_t *d, ucMask, ucMask2;
- int tmp, iOff;
- if (pOLED == NULL || pOLED->ucScreen == NULL)
- return; // only works with a back buffer
- if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x1 >= pOLED->oled_x || y1 >= pOLED->oled_y || x2 >= pOLED->oled_x
- || y2 >= pOLED->oled_y)
- return; // invalid coordinates
- // Make sure that X1/Y1 is above and to the left of X2/Y2
- // swap coordinates as needed to make this true
- if (x2 < x1)
- {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- if (y2 < y1)
- {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- if (bFilled)
- {
- int x, y, iMiddle;
- iMiddle = (y2 >> 3) - (y1 >> 3);
- ucMask = 0xff << (y1 & 7);
- if (iMiddle == 0) // top and bottom lines are in the same row
- ucMask &= (0xff >> (7 - (y2 & 7)));
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
- // Draw top
- for (x = x1; x <= x2; x++)
- {
- if (ucColor)
- *d |= ucMask;
- else
- *d &= ~ucMask;
- d++;
- }
- if (iMiddle > 1) // need to draw middle part
- {
- ucMask = (ucColor) ? 0xff : 0x00;
- for (y = 1; y < iMiddle; y++)
- {
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1 + (y * 128)];
- for (x = x1; x <= x2; x++)
- *d++ = ucMask;
- }
- }
- if (iMiddle >= 1) // need to draw bottom part
- {
- ucMask = 0xff >> (7 - (y2 & 7));
- d = &pOLED->ucScreen[(y2 >> 3) * 128 + x1];
- for (x = x1; x <= x2; x++)
- {
- if (ucColor)
- *d++ |= ucMask;
- else
- *d++ &= ~ucMask;
- }
- }
- }
- else // outline
- {
- // see if top and bottom lines are within the same byte rows
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
- if ((y1 >> 3) == (y2 >> 3))
- {
- ucMask2 = 0xff << (y1 & 7); // L/R end masks
- ucMask = 1 << (y1 & 7);
- ucMask |= 1 << (y2 & 7);
- ucMask2 &= (0xff >> (7 - (y2 & 7)));
- if (ucColor)
- {
- *d++ |= ucMask2; // start
- x1++;
- for (; x1 < x2; x1++)
- *d++ |= ucMask;
- if (x1 <= x2)
- *d++ |= ucMask2; // right edge
- }
- else
- {
- *d++ &= ~ucMask2;
- x1++;
- for (; x1 < x2; x1++)
- *d++ &= ~ucMask;
- if (x1 <= x2)
- *d++ &= ~ucMask2; // right edge
- }
- }
- else
- {
- int y;
- // L/R sides
- iOff = (x2 - x1);
- ucMask = 1 << (y1 & 7);
- for (y = y1; y <= y2; y++)
- {
- if (ucColor)
- {
- *d |= ucMask;
- d[iOff] |= ucMask;
- }
- else
- {
- *d &= ~ucMask;
- d[iOff] &= ~ucMask;
- }
- ucMask <<= 1;
- if (ucMask == 0)
- {
- ucMask = 1;
- d += 128;
- }
- }
- // T/B sides
- ucMask = 1 << (y1 & 7);
- ucMask2 = 1 << (y2 & 7);
- x1++;
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
- iOff = (y2 >> 3) - (y1 >> 3);
- iOff *= 128;
- for (; x1 < x2; x1++)
- {
- if (ucColor)
- {
- *d |= ucMask;
- d[iOff] |= ucMask2;
- }
- else
- {
- *d &= ~ucMask;
- d[iOff] &= ~ucMask2;
- }
- d++;
- }
- }
- } // outline
- } /* oledRectangle() */

bit_bangiic.cpp
- //
- // ss_oled (Small, Simple OLED library)
- // Copyright (c) 2017-2019 BitBank Software, Inc.
- // Written by Larry Bank (bitbank@pobox.com)
- // Project started 1/15/2017
- //
- // 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 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "pico/stdlib.h"
-
- #include "include/ss_oled.h"
-
- const uint8_t ucFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x5f, 0x06, 0x00, 0x00,
- 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x14, 0x7f, 0x7f, 0x14, 0x7f, 0x7f, 0x14, 0x24, 0x2e, 0x2a, 0x6b, 0x6b,
- 0x3a, 0x12, 0x46, 0x66, 0x30, 0x18, 0x0c, 0x66, 0x62, 0x30, 0x7a, 0x4f, 0x5d, 0x37, 0x7a, 0x48, 0x00, 0x04,
- 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, 0x00, 0x41, 0x63, 0x3e, 0x1c, 0x00,
- 0x00, 0x08, 0x2a, 0x3e, 0x1c, 0x3e, 0x2a, 0x08, 0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x80,
- 0xe0, 0x60, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
- 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x3e, 0x7f, 0x59, 0x4d, 0x47, 0x7f, 0x3e, 0x40, 0x42, 0x7f, 0x7f,
- 0x40, 0x40, 0x00, 0x62, 0x73, 0x59, 0x49, 0x6f, 0x66, 0x00, 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x18,
- 0x1c, 0x16, 0x53, 0x7f, 0x7f, 0x50, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, 0x3c, 0x7e, 0x4b, 0x49, 0x79,
- 0x30, 0x00, 0x03, 0x03, 0x71, 0x79, 0x0f, 0x07, 0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x06, 0x4f,
- 0x49, 0x69, 0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe6, 0x66, 0x00,
- 0x00, 0x08, 0x1c, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x63,
- 0x36, 0x1c, 0x08, 0x00, 0x00, 0x02, 0x03, 0x59, 0x5d, 0x07, 0x02, 0x3e, 0x7f, 0x41, 0x5d, 0x5d, 0x5f, 0x0e,
- 0x7c, 0x7e, 0x13, 0x13, 0x7e, 0x7c, 0x00, 0x41, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x1c, 0x3e, 0x63, 0x41,
- 0x41, 0x63, 0x22, 0x41, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f, 0x49, 0x5d, 0x41, 0x63, 0x41,
- 0x7f, 0x7f, 0x49, 0x1d, 0x01, 0x03, 0x1c, 0x3e, 0x63, 0x41, 0x51, 0x33, 0x72, 0x7f, 0x7f, 0x08, 0x08, 0x7f,
- 0x7f, 0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, 0x30, 0x70, 0x40, 0x41, 0x7f, 0x3f, 0x01, 0x41, 0x7f,
- 0x7f, 0x08, 0x1c, 0x77, 0x63, 0x41, 0x7f, 0x7f, 0x41, 0x40, 0x60, 0x70, 0x7f, 0x7f, 0x0e, 0x1c, 0x0e, 0x7f,
- 0x7f, 0x7f, 0x7f, 0x06, 0x0c, 0x18, 0x7f, 0x7f, 0x1c, 0x3e, 0x63, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f,
- 0x49, 0x09, 0x0f, 0x06, 0x1e, 0x3f, 0x21, 0x31, 0x61, 0x7f, 0x5e, 0x41, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66,
- 0x26, 0x6f, 0x4d, 0x49, 0x59, 0x73, 0x32, 0x03, 0x41, 0x7f, 0x7f, 0x41, 0x03, 0x00, 0x7f, 0x7f, 0x40, 0x40,
- 0x7f, 0x7f, 0x00, 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, 0x3f, 0x7f, 0x60, 0x30, 0x60, 0x7f, 0x3f, 0x63,
- 0x77, 0x1c, 0x08, 0x1c, 0x77, 0x63, 0x07, 0x4f, 0x78, 0x78, 0x4f, 0x07, 0x00, 0x47, 0x63, 0x71, 0x59, 0x4d,
- 0x67, 0x73, 0x00, 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x41,
- 0x41, 0x7f, 0x7f, 0x00, 0x00, 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x80, 0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x20, 0x74, 0x54, 0x54, 0x3c, 0x78, 0x40, 0x41, 0x7f, 0x3f,
- 0x48, 0x48, 0x78, 0x30, 0x38, 0x7c, 0x44, 0x44, 0x6c, 0x28, 0x00, 0x30, 0x78, 0x48, 0x49, 0x3f, 0x7f, 0x40,
- 0x38, 0x7c, 0x54, 0x54, 0x5c, 0x18, 0x00, 0x48, 0x7e, 0x7f, 0x49, 0x03, 0x06, 0x00, 0x98, 0xbc, 0xa4, 0xa4,
- 0xf8, 0x7c, 0x04, 0x41, 0x7f, 0x7f, 0x08, 0x04, 0x7c, 0x78, 0x00, 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00, 0x60,
- 0xe0, 0x80, 0x84, 0xfd, 0x7d, 0x00, 0x41, 0x7f, 0x7f, 0x10, 0x38, 0x6c, 0x44, 0x00, 0x41, 0x7f, 0x7f, 0x40,
- 0x00, 0x00, 0x7c, 0x7c, 0x18, 0x78, 0x1c, 0x7c, 0x78, 0x7c, 0x78, 0x04, 0x04, 0x7c, 0x78, 0x00, 0x38, 0x7c,
- 0x44, 0x44, 0x7c, 0x38, 0x00, 0x84, 0xfc, 0xf8, 0xa4, 0x24, 0x3c, 0x18, 0x18, 0x3c, 0x24, 0xa4, 0xf8, 0xfc,
- 0x84, 0x44, 0x7c, 0x78, 0x4c, 0x04, 0x0c, 0x18, 0x48, 0x5c, 0x54, 0x74, 0x64, 0x24, 0x00, 0x04, 0x04, 0x3e,
- 0x7f, 0x44, 0x24, 0x00, 0x3c, 0x7c, 0x40, 0x40, 0x3c, 0x7c, 0x40, 0x1c, 0x3c, 0x60, 0x60, 0x3c, 0x1c, 0x00,
- 0x3c, 0x7c, 0x60, 0x30, 0x60, 0x7c, 0x3c, 0x44, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0x44, 0x9c, 0xbc, 0xa0, 0xa0,
- 0xfc, 0x7c, 0x00, 0x4c, 0x64, 0x74, 0x5c, 0x4c, 0x64, 0x00, 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, 0x00,
- 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02,
- 0x03, 0x01, 0x70, 0x78, 0x4c, 0x46, 0x4c, 0x78, 0x70 };
- const uint8_t ucBigFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
- 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
- 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xfc,
- 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0xfc, 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0xff,
- 0xff, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0,
- 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0f,
- 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
- 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f, 0x3f, 0x3f, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0xff,
- 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xff,
- 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f, 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
- 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xff, 0xff, 0x3f,
- 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xcc, 0xcc, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f,
- 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x30, 0x30, 0x0f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3c, 0x3c, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0x3c, 0x3c, 0x00,
- 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
- 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
- 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3f, 0x3f, 0xf3,
- 0xf3, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x0c, 0x3c, 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xf3, 0xf3, 0x3f, 0x3f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
- 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
- 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x3c,
- 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03,
- 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
- 0x03, 0x0f, 0x0f, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f,
- 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
- 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf0, 0xf0, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc,
- 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0,
- 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
- 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc3, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x03, 0x03, 0x03,
- 0x03, 0x3f, 0x3f, 0x3c, 0x3c, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xfc,
- 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x3f, 0x3f, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xfc,
- 0xfc, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x00,
- 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
- 0xff, 0x3f, 0x3f, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0xc0,
- 0xc0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3f, 0x3f, 0xfc, 0xfc, 0xf0,
- 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
- 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
- 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xcf, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff,
- 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
- 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xcf, 0xcf, 0xcf, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xcf, 0xcf, 0xcf,
- 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
- 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
- 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
- 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0,
- 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
- 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x30, 0x30, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x00,
- 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0xfc, 0xfc, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
- 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xff,
- 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xff,
- 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
- 0x00, 0x03, 0x03, 0xc3, 0xc3, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f,
- 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff,
- 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
- 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
- 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f,
- 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
- 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
- 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
- // 5x7 font (in 6x8 cell)
- const uint8_t ucSmallFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x06, 0x00, 0x07, 0x03, 0x00, 0x07,
- 0x03, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x2b, 0x6a, 0x12, 0x00, 0x63, 0x13, 0x08, 0x64, 0x63, 0x36, 0x49,
- 0x56, 0x20, 0x50, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x41, 0x3e, 0x00, 0x00,
- 0x08, 0x3e, 0x1c, 0x3e, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0xe0, 0x60, 0x00, 0x00, 0x08, 0x08, 0x08,
- 0x08, 0x08, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00,
- 0x42, 0x7f, 0x40, 0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x22, 0x49, 0x49, 0x49, 0x36, 0x18, 0x14, 0x12, 0x7f,
- 0x10, 0x2f, 0x49, 0x49, 0x49, 0x31, 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x01, 0x71, 0x09, 0x05, 0x03, 0x36, 0x49,
- 0x49, 0x49, 0x36, 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x00, 0x00,
- 0x08, 0x14, 0x22, 0x41, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59,
- 0x09, 0x06, 0x3e, 0x41, 0x5d, 0x55, 0x1e, 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e,
- 0x41, 0x41, 0x41, 0x22, 0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x7f, 0x09, 0x09, 0x09,
- 0x01, 0x3e, 0x41, 0x49, 0x49, 0x7a, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x41, 0x7f, 0x41, 0x00, 0x30, 0x40,
- 0x40, 0x40, 0x3f, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x7f, 0x02, 0x04, 0x02, 0x7f,
- 0x7f, 0x02, 0x04, 0x08, 0x7f, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x09, 0x09, 0x09, 0x06, 0x3e, 0x41, 0x51,
- 0x21, 0x5e, 0x7f, 0x09, 0x09, 0x19, 0x66, 0x26, 0x49, 0x49, 0x49, 0x32, 0x01, 0x01, 0x7f, 0x01, 0x01, 0x3f,
- 0x40, 0x40, 0x40, 0x3f, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x3f, 0x40, 0x3c, 0x40, 0x3f, 0x63, 0x14, 0x08, 0x14,
- 0x63, 0x07, 0x08, 0x70, 0x08, 0x07, 0x71, 0x49, 0x45, 0x43, 0x00, 0x00, 0x7f, 0x41, 0x41, 0x00, 0x02, 0x04,
- 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7f, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x80, 0x80, 0x80, 0x80, 0x80,
- 0x00, 0x03, 0x07, 0x00, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x7f, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44,
- 0x44, 0x28, 0x38, 0x44, 0x44, 0x44, 0x7f, 0x38, 0x54, 0x54, 0x54, 0x08, 0x08, 0x7e, 0x09, 0x09, 0x00, 0x18,
- 0xa4, 0xa4, 0xa4, 0x7c, 0x7f, 0x04, 0x04, 0x78, 0x00, 0x00, 0x00, 0x7d, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7d,
- 0x00, 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x00, 0x7c, 0x04, 0x18, 0x04, 0x78, 0x7c, 0x04,
- 0x04, 0x78, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0xfc, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0xfc,
- 0x44, 0x78, 0x44, 0x04, 0x08, 0x08, 0x54, 0x54, 0x54, 0x20, 0x04, 0x3e, 0x44, 0x24, 0x00, 0x3c, 0x40, 0x20,
- 0x7c, 0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x3c, 0x60, 0x30, 0x60, 0x3c, 0x6c, 0x10, 0x10, 0x6c, 0x00, 0x9c,
- 0xa0, 0x60, 0x3c, 0x00, 0x64, 0x54, 0x54, 0x4c, 0x00, 0x08, 0x3e, 0x41, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00,
- 0x00, 0x00, 0x41, 0x41, 0x3e, 0x08, 0x02, 0x01, 0x02, 0x01, 0x00, 0x3c, 0x26, 0x23, 0x26, 0x3c };
-
- // Initialization sequences
- const unsigned char oled128_initbuf[] = { 0x00, 0xae, 0xdc, 0x00, 0x81, 0x40, 0xa1, 0xc8, 0xa8, 0x7f, 0xd5, 0x50, 0xd9,
- 0x22, 0xdb, 0x35, 0xb0, 0xda, 0x12, 0xa4, 0xa6, 0xaf };
-
- const unsigned char oled64_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
- 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
-
- const unsigned char oled32_initbuf[] = { 0x00, 0xae, 0xd5, 0x80, 0xa8, 0x1f, 0xd3, 0x00, 0x40, 0x8d, 0x14, 0xa1, 0xc8,
- 0xda, 0x02, 0x81, 0x7f, 0xd9, 0xf1, 0xdb, 0x40, 0xa4, 0xa6, 0xaf };
-
- const unsigned char oled72_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
- 0xad, 0x30, 0xd9, 0xf1, 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
-
- // some globals
-
- static void __oledWriteCommand(SSOLED *pOLED, unsigned char c);
- void __InvertBytes(uint8_t *pData, uint8_t bLen);
-
- // wrapper/adapter functions to make the code work on Linux
- static uint8_t pgm_read_byte(uint8_t *ptr)
- {
- return *ptr;
- }
- static int16_t pgm_read_word(uint8_t *ptr)
- {
- return ptr[0] + (ptr[1] << 8);
- }
-
- static void _I2CWrite(SSOLED *pOLED, unsigned char *pData, int iLen)
- {
- I2CWrite(&pOLED->bbi2c, pOLED->oled_addr, pData, iLen);
- } /* _I2CWrite() */
-
- //
- // Initializes the OLED controller into "page mode"
- //
- int __oledInit(SSOLED *pOLED, int bInvert, int32_t iSpeed)
- {
- unsigned char uc[4];
- int rc = OLED_NOT_FOUND;
- int iAddr = pOLED->oled_addr;
- int bFlip = (int) pOLED->oled_flip;
- int iType = pOLED->oled_type;
-
- pOLED->ucScreen = NULL; // reset backbuffer; user must provide one later
- pOLED->oled_wrap = 0; // default - disable text wrap
-
- I2CInit(&pOLED->bbi2c, iSpeed); // on Linux, SDA = bus number, SCL = device address
-
- // find the device address if requested
- if (iAddr == -1 || iAddr == 0 || iAddr == 0xff) // find it
- {
- I2CTest(&pOLED->bbi2c, 0x3c);
- if (I2CTest(&pOLED->bbi2c, 0x3c))
- pOLED->oled_addr = 0x3c;
- else if (I2CTest(&pOLED->bbi2c, 0x3d))
- pOLED->oled_addr = 0x3d;
- else
- return rc; // no display found!
- }
- else
- {
- pOLED->oled_addr = iAddr;
- I2CTest(&pOLED->bbi2c, iAddr);
- if (!I2CTest(&pOLED->bbi2c, iAddr))
- return rc; // no display found
- }
- // Detect the display controller (SSD1306, SH1107 or SH1106)
- uint8_t u = 0;
- I2CReadRegister(&pOLED->bbi2c, pOLED->oled_addr, 0x00, &u, 1); // read the status register
- u &= 0x0f; // mask off power on/off bit
- if (u == 0x7 || u == 0xf) // SH1107
- {
- pOLED->oled_type = OLED_128x128;
- rc = OLED_SH1107_3C;
- bFlip = !bFlip; // SH1107 seems to have this reversed from the usual direction
- }
- else if (u == 0x8) // SH1106
- {
- rc = OLED_SH1106_3C;
- pOLED->oled_type = OLED_132x64; // needs to be treated a little differently
- }
- else if (u == 3 || u == 6) // 6=128x64 display, 3=smaller
- {
- rc = OLED_SSD1306_3C;
- }
- if (pOLED->oled_addr == 0x3d)
- rc++; // return the '3D' version of the type
-
- if (iType == OLED_128x32 || iType == OLED_96x16)
- _I2CWrite(pOLED, (unsigned char *) oled32_initbuf, sizeof(oled32_initbuf));
- else if (iType == OLED_128x128)
- _I2CWrite(pOLED, (unsigned char *) oled128_initbuf, sizeof(oled128_initbuf));
- else if (iType == OLED_72x40)
- _I2CWrite(pOLED, (unsigned char *) oled72_initbuf, sizeof(oled72_initbuf));
- else
- // 132x64, 128x64 and 64x32
- _I2CWrite(pOLED, (unsigned char *) oled64_initbuf, sizeof(oled64_initbuf));
- if (bInvert)
- {
- uc[0] = 0; // command
- uc[1] = 0xa7; // invert command
- _I2CWrite(pOLED, uc, 2);
- }
- if (bFlip) // rotate display 180
- {
- uc[0] = 0; // command
- uc[1] = 0xa0;
- _I2CWrite(pOLED, uc, 2);
- uc[1] = 0xc0;
- _I2CWrite(pOLED, uc, 2);
- }
- pOLED->oled_x = 128; // assume 128x64
- pOLED->oled_y = 64;
- if (iType == OLED_96x16)
- {
- pOLED->oled_x = 96;
- pOLED->oled_y = 16;
- }
- else if (iType == OLED_128x32)
- pOLED->oled_y = 32;
- else if (iType == OLED_128x128)
- pOLED->oled_y = 128;
- else if (iType == OLED_64x32)
- {
- pOLED->oled_x = 64;
- pOLED->oled_y = 32;
- }
- else if (iType == OLED_72x40)
- {
- pOLED->oled_x = 72;
- pOLED->oled_y = 40;
- }
- return rc;
- } /* oledInit() */
- //
- // Sends a command to turn on or off the OLED display
- //
- void __oledPower(SSOLED *pOLED, uint8_t bOn)
- {
- if (bOn)
- __oledWriteCommand(pOLED, 0xaf); // turn on OLED
- else
- __oledWriteCommand(pOLED, 0xae); // turn off OLED
- } /* oledPower() */
-
- // Send a single byte command to the OLED controller
- static void __oledWriteCommand(SSOLED *pOLED, unsigned char c)
- {
- unsigned char buf[2];
-
- buf[0] = 0x00; // command introducer
- buf[1] = c;
- _I2CWrite(pOLED, buf, 2);
- } /* oledWriteCommand() */
-
- static void __oledWriteCommand2(SSOLED *pOLED, unsigned char c, unsigned char d)
- {
- unsigned char buf[3];
-
- buf[0] = 0x00;
- buf[1] = c;
- buf[2] = d;
- _I2CWrite(pOLED, buf, 3);
- } /* oledWriteCommand2() */
-
- //
- // Sets the brightness (0=off, 255=brightest)
- //
- void __oledSetContrast(SSOLED *pOLED, unsigned char ucContrast)
- {
- __oledWriteCommand2(pOLED, 0x81, ucContrast);
- } /* oledSetContrast() */
- //
- // Scroll the internal buffer by 1 scanline (up/down)
- // width is in pixels, lines is group of 8 rows
- //
- int __oledScrollBuffer(SSOLED *pOLED, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp)
- {
- uint8_t b, *s;
- int col, row;
-
- if (iStartCol < 0 || iStartCol > 127 || iEndCol < 0 || iEndCol > 127 || iStartCol > iEndCol) // invalid
- return -1;
- if (iStartRow < 0 || iStartRow > 7 || iEndRow < 0 || iEndRow > 7 || iStartRow > iEndRow)
- return -1;
-
- if (bUp)
- {
- for (row = iStartRow; row <= iEndRow; row++)
- {
- s = &pOLED->ucScreen[(row * 128) + iStartCol];
- for (col = iStartCol; col <= iEndCol; col++)
- {
- b = *s;
- b >>= 1; // scroll pixels 'up'
- if (row < iEndRow)
- b |= (s[128] << 7); // capture pixel of row below, except for last row
- *s++ = b;
- } // for col
- } // for row
- } // up
- else // down
- {
- for (row = iEndRow; row >= iStartRow; row--)
- {
- s = &pOLED->ucScreen[(row * 128) + iStartCol];
- for (col = iStartCol; col <= iEndCol; col++)
- {
- b = *s;
- b <<= 1; // scroll down
- if (row > iStartRow)
- b |= (s[-128] >> 7); // capture pixel of row above
- *s++ = b;
- } // for col
- } // for row
- }
- return 0;
- } /* oledScrollBuffer() */
- //
- // Send commands to position the "cursor" (aka memory write address)
- // to the given row and column
- //
- static void __oledSetPosition(SSOLED *pOLED, int x, int y, int bRender)
- {
- unsigned char buf[4];
-
- pOLED->iScreenOffset = (y * 128) + x;
- if (!bRender)
- return; // don't send the commands to the OLED if we're not rendering the graphics now
- if (pOLED->oled_type == OLED_64x32) // visible display starts at column 32, row 4
- {
- x += 32; // display is centered in VRAM, so this is always true
- if (pOLED->oled_flip == 0) // non-flipped display starts from line 4
- y += 4;
- }
- else if (pOLED->oled_type == OLED_132x64) // SH1106 has 128 pixels centered in 132
- {
- x += 2;
- }
- else if (pOLED->oled_type == OLED_96x16) // visible display starts at line 2
- { // mapping is a bit strange on the 96x16 OLED
- if (pOLED->oled_flip)
- x += 32;
- else
- y += 2;
- }
- else if (pOLED->oled_type == OLED_72x40) // starts at x=28,y=3
- {
- x += 28;
- if (!pOLED->oled_flip)
- {
- y += 3;
- }
- }
- buf[0] = 0x00; // command introducer
- buf[1] = 0xb0 | y; // set page to Y
- buf[2] = x & 0xf; // lower column address
- buf[3] = 0x10 | (x >> 4); // upper column addr
- _I2CWrite(pOLED, buf, 4);
- } /* oledSetPosition() */
-
- //
- // Write a block of pixel data to the OLED
- // Length can be anything from 1 to 1024 (whole display)
- //
- static void __oledWriteDataBlock(SSOLED *pOLED, unsigned char *ucBuf, int iLen, int bRender)
- {
- unsigned char ucTemp[129];
-
- ucTemp[0] = 0x40; // data command
- // Copying the data has the benefit in SPI mode of not letting
- // the original data get overwritten by the SPI.transfer() function
- if (bRender)
- {
- memcpy(&ucTemp[1], ucBuf, iLen);
- _I2CWrite(pOLED, ucTemp, iLen + 1);
- }
- // Keep a copy in local buffer
- if (pOLED->ucScreen)
- {
- memcpy(&pOLED->ucScreen[pOLED->iScreenOffset], ucBuf, iLen);
- pOLED->iScreenOffset += iLen;
- pOLED->iScreenOffset &= 1023; // we use a fixed stride of 128 no matter what the display size
- }
- }
- //
- // Byte operands for compressing the data
- // The first 2 bits are the type, followed by the counts
- #define OP_MASK 0xc0
- #define OP_SKIPCOPY 0x00
- #define OP_COPYSKIP 0x40
- #define OP_REPEATSKIP 0x80
- #define OP_REPEAT 0xc0
- //
- // Write a block of flash memory to the display
- //
- void __oledWriteFlashBlock(SSOLED *pOLED, uint8_t *s, int iLen)
- {
- int j;
- int iWidthMask = pOLED->oled_x - 1;
- int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
- int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 wide
- uint8_t ucTemp[128];
-
- while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
- {
- j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
- memcpy(ucTemp, s, j);
- __oledWriteDataBlock(pOLED, ucTemp, j, 1);
- s += j;
- iLen -= j;
- pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
- __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
- } // while it needs some help
- memcpy(ucTemp, s, iLen);
- __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
- pOLED->iScreenOffset = (pOLED->iScreenOffset + iLen) & iSizeMask;
- } /* oledWriteFlashBlock() */
-
- //
- // Write a repeating byte to the display
- //
- void __oledRepeatByte(SSOLED *pOLED, uint8_t b, int iLen)
- {
- int j;
- int iWidthMask = pOLED->oled_x - 1;
- int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 pixels wide
- int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
- uint8_t ucTemp[128];
-
- memset(ucTemp, b, (iLen > 128) ? 128 : iLen);
- while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
- {
- j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
- __oledWriteDataBlock(pOLED, ucTemp, j, 1);
- iLen -= j;
- pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
- __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
- } // while it needs some help
- __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
- pOLED->iScreenOffset += iLen;
- } /* oledRepeatByte() */
-
- //
- // Play a frame of animation data
- // The animation data is assumed to be encoded for a full frame of the display
- // Given the pointer to the start of the compressed data,
- // it returns the pointer to the start of the next frame
- // Frame rate control is up to the calling program to manage
- // When it finishes the last frame, it will start again from the beginning
- //
- uint8_t * __oledPlayAnimFrame(SSOLED *pOLED, uint8_t *pAnimation, uint8_t *pCurrent, int iLen)
- {
- uint8_t *s;
- int i, j;
- unsigned char b, bCode;
- int iBufferSize = (pOLED->oled_x * pOLED->oled_y) / 8; // size in bytes of the display devce
- int iWidthMask, iWidthShift;
-
- iWidthMask = pOLED->oled_x - 1;
- iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // 128 or 64 pixels wide
- if (pCurrent == NULL || pCurrent > pAnimation + iLen)
- return NULL; // invalid starting point
-
- s = (uint8_t *) pCurrent; // start of animation data
- i = 0;
- __oledSetPosition(pOLED, 0, 0, 1);
- while (i < iBufferSize) // run one frame
- {
- bCode = pgm_read_byte(s++);
- switch (bCode & OP_MASK)
- // different compression types
- {
- case OP_SKIPCOPY: // skip/copy
- if (bCode == OP_SKIPCOPY) // big skip
- {
- b = pgm_read_byte(s++);
- i += b + 1;
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- else // skip/copy
- {
- if (bCode & 0x38)
- {
- i += ((bCode & 0x38) >> 3); // skip amount
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- if (bCode & 7)
- {
- __oledWriteFlashBlock(pOLED, s, bCode & 7);
- s += (bCode & 7);
- i += bCode & 7;
- }
- }
- break;
- case OP_COPYSKIP: // copy/skip
- if (bCode == OP_COPYSKIP) // big copy
- {
- b = pgm_read_byte(s++);
- j = b + 1;
- __oledWriteFlashBlock(pOLED, s, j);
- s += j;
- i += j;
- }
- else
- {
- j = ((bCode & 0x38) >> 3);
- if (j)
- {
- __oledWriteFlashBlock(pOLED, s, j);
- s += j;
- i += j;
- }
- if (bCode & 7)
- {
- i += (bCode & 7); // skip
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- }
- break;
- case OP_REPEATSKIP: // repeat/skip
- j = (bCode & 0x38) >> 3; // repeat count
- b = pgm_read_byte(s++);
- __oledRepeatByte(pOLED, b, j);
- i += j;
- if (bCode & 7)
- {
- i += (bCode & 7); // skip amount
- __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
- }
- break;
-
- case OP_REPEAT:
- j = (bCode & 0x3f) + 1;
- b = pgm_read_byte(s++);
- __oledRepeatByte(pOLED, b, j);
- i += j;
- break;
- } // switch on code type
- } // while rendering a frame
- if (s >= pAnimation + iLen) // we've hit the end, restart from the beginning
- s = pAnimation;
- return s; // return pointer to start of next frame
- } /* oledPlayAnimFrame() */
- //
- // Draw a sprite of any size in any position
- // If it goes beyond the left/right or top/bottom edges
- // it's trimmed to show the valid parts
- // This function requires a back buffer to be defined
- // The priority color (0 or 1) determines which color is painted
- // when a 1 is encountered in the source image.
- //
- void __oledDrawSprite(SSOLED *pOLED, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
- {
- int tx, ty, dx, dy, iStartX;
- uint8_t *s, *d, uc, pix, ucSrcMask, ucDstMask;
-
- if (x + cx < 0 || y + cy < 0 || x >= pOLED->oled_x || y >= pOLED->oled_y || pOLED->ucScreen == NULL)
- return; // no backbuffer or out of bounds
- dy = y; // destination y
- if (y < 0) // skip the invisible parts
- {
- cy += y;
- y = -y;
- pSprite += (y * iPitch);
- dy = 0;
- }
- if (y + cy > pOLED->oled_y)
- cy = pOLED->oled_y - y;
- iStartX = 0;
- dx = x;
- if (x < 0)
- {
- cx += x;
- x = -x;
- iStartX = x;
- dx = 0;
- }
- if (x + cx > pOLED->oled_x)
- cx = pOLED->oled_x - x;
- for (ty = 0; ty < cy; ty++)
- {
- s = &pSprite[iStartX >> 3];
- d = &pOLED->ucScreen[(dy >> 3) * pOLED->oled_x + dx];
- ucSrcMask = 0x80 >> (iStartX & 7);
- pix = *s++;
- ucDstMask = 1 << (dy & 7);
- if (iPriority) // priority color is 1
- {
- for (tx = 0; tx < cx; tx++)
- {
- uc = d[0];
- if (pix & ucSrcMask) // set pixel in source, set it in dest
- d[0] = (uc | ucDstMask);
- d++; // next pixel column
- ucSrcMask >>= 1;
- if (ucSrcMask == 0) // read next byte
- {
- ucSrcMask = 0x80;
- pix = *s++;
- }
- } // for tx
- } // priorty color 1
- else
- {
- for (tx = 0; tx < cx; tx++)
- {
- uc = d[0];
- if (pix & ucSrcMask) // clr pixel in source, clr it in dest
- d[0] = (uc & ~ucDstMask);
- d++; // next pixel column
- ucSrcMask >>= 1;
- if (ucSrcMask == 0) // read next byte
- {
- ucSrcMask = 0x80;
- pix = *s++;
- }
- } // for tx
- } // priority color 0
- dy++;
- pSprite += iPitch;
- } // for ty
- } /* oledDrawSprite() */
- //
- // Draw a 16x16 tile in any of 4 rotated positions
- // Assumes input image is laid out like "normal" graphics with
- // the MSB on the left and 2 bytes per line
- // On AVR, the source image is assumed to be in FLASH memory
- // The function can draw the tile on byte boundaries, so the x value
- // can be from 0 to 112 and y can be from 0 to 6
- //
- void __oledDrawTile(SSOLED *pOLED, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender)
- {
- uint8_t ucTemp[32]; // prepare LCD data here
- uint8_t i, j, k, iOffset, ucMask, uc, ucPixels;
- uint8_t bFlipX = 0, bFlipY = 0;
-
- if (x < 0 || y < 0 || y > 6 || x > 112)
- return; // out of bounds
- if (pTile == NULL)
- return; // bad pointer; really? :(
- if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPX)
- bFlipX = 1;
- if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPY)
- bFlipY = 1;
-
- memset(ucTemp, 0, sizeof(ucTemp)); // we only set white pixels, so start from black
- if (iRotation == ANGLE_0 || iRotation == ANGLE_180 || iRotation == ANGLE_FLIPX || iRotation == ANGLE_FLIPY)
- {
- for (j = 0; j < 16; j++) // y
- {
- for (i = 0; i < 16; i += 8) // x
- {
- ucPixels = pgm_read_byte((uint8_t*) pTile++);
- ucMask = 0x80; // MSB is the first source pixel
- for (k = 0; k < 8; k++)
- {
- if (ucPixels & ucMask) // translate the pixel
- {
- if (bFlipY)
- uc = 0x80 >> (j & 7);
- else
- uc = 1 << (j & 7);
- iOffset = i + k;
- if (bFlipX)
- iOffset = 15 - iOffset;
- iOffset += (j & 8) << 1; // top/bottom half of output
- if (bFlipY)
- iOffset ^= 16;
- ucTemp[iOffset] |= uc;
- }
- ucMask >>= 1;
- } // for k
- } // for i
- } // for j
- }
- else // rotated 90/270
- {
- for (j = 0; j < 16; j++) // y
- {
- for (i = 0; i < 16; i += 8) // x
- {
- ucPixels = pgm_read_byte((uint8_t*) pTile++);
- ucMask = 0x80; // MSB is the first source pixel
- for (k = 0; k < 8; k++)
- {
- if (ucPixels & ucMask) // translate the pixel
- {
- if (bFlipY)
- uc = 0x80 >> k;
- else
- uc = 1 << k;
- iOffset = 15 - j;
- if (bFlipX)
- iOffset = 15 - iOffset;
- iOffset += i << 1; // top/bottom half of output
- if (bFlipY)
- iOffset ^= 16;
- ucTemp[iOffset] |= uc;
- }
- ucMask >>= 1;
- } // for k
- } // for i
- } // for j
- }
- if (bInvert)
- __InvertBytes(ucTemp, 32);
- // Send the data to the display
- __oledSetPosition(pOLED, x, y, bRender);
- __oledWriteDataBlock(pOLED, ucTemp, 16, bRender); // top half
- __oledSetPosition(pOLED, x, y + 1, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[16], 16, bRender); // bottom half
- } /* oledDrawTile() */
-
- // Set (or clear) an individual pixel
- // The local copy of the frame buffer is used to avoid
- // reading data from the display controller
- int __oledSetPixel(SSOLED *pOLED, int x, int y, unsigned char ucColor, int bRender)
- {
- int i;
- unsigned char uc, ucOld;
-
- i = ((y >> 3) * 128) + x;
- if (i < 0 || i > 1023) // off the screen
- return -1;
- __oledSetPosition(pOLED, x, y >> 3, bRender);
-
- if (pOLED->ucScreen)
- uc = ucOld = pOLED->ucScreen[i];
- else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // SH1106/SH1107 can read data
- {
- uint8_t ucTemp[3];
- ucTemp[0] = 0x80; // one command
- ucTemp[1] = 0xE0; // read_modify_write
- ucTemp[2] = 0xC0; // one data
- _I2CWrite(pOLED, ucTemp, 3);
-
- // read a dummy byte followed by the data byte we want
- I2CRead(&pOLED->bbi2c, pOLED->oled_addr, ucTemp, 2);
- uc = ucOld = ucTemp[1]; // first byte is garbage
- }
- else
- uc = ucOld = 0;
-
- uc &= ~(0x1 << (y & 7));
- if (ucColor)
- {
- uc |= (0x1 << (y & 7));
- }
- if (uc != ucOld) // pixel changed
- {
- // oledSetPosition(x, y>>3);
- if (pOLED->ucScreen)
- {
- __oledWriteDataBlock(pOLED, &uc, 1, bRender);
- pOLED->ucScreen[i] = uc;
- }
- else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // end the read_modify_write operation
- {
- uint8_t ucTemp[4];
- ucTemp[0] = 0xc0; // one data
- ucTemp[1] = uc; // actual data
- ucTemp[2] = 0x80; // one command
- ucTemp[3] = 0xEE; // end read_modify_write operation
- _I2CWrite(pOLED, ucTemp, 4);
- }
- }
- return 0;
- } /* oledSetPixel() */
-
- //
- // Invert font data
- //
- void __InvertBytes(uint8_t *pData, uint8_t bLen)
- {
- uint8_t i;
- for (i = 0; i < bLen; i++)
- {
- *pData = ~(*pData);
- pData++;
- }
- } /* InvertBytes() */
-
- //
- // Load a 128x64 1-bpp Windows bitmap
- // Pass the pointer to the beginning of the BMP file
- // First pass version assumes a full screen bitmap
- //
- int __oledLoadBMP(SSOLED *pOLED, uint8_t *pBMP, int bInvert, int bRender)
- {
- int16_t i16;
- int iOffBits, q, y, j; // offset to bitmap data
- int iPitch;
- uint8_t x, z, b, *s;
- uint8_t dst_mask;
- uint8_t ucTemp[16]; // process 16 bytes at a time
- uint8_t bFlipped = false;
-
- i16 = pgm_read_word(pBMP);
- if (i16 != 0x4d42) // must start with 'BM'
- return -1; // not a BMP file
- i16 = pgm_read_word(pBMP + 18);
- if (i16 != 128) // must be 128 pixels wide
- return -1;
- i16 = pgm_read_word(pBMP + 22);
- if (i16 != 64 && i16 != -64) // must be 64 pixels tall
- return -1;
- if (i16 == 64) // BMP is flipped vertically (typical)
- bFlipped = true;
- i16 = pgm_read_word(pBMP + 28);
- if (i16 != 1) // must be 1 bit per pixel
- return -1;
- iOffBits = pgm_read_word(pBMP + 10);
- iPitch = 16;
- if (bFlipped)
- {
- iPitch = -16;
- iOffBits += (63 * 16); // start from bottom
- }
-
- // rotate the data and send it to the display
- for (y = 0; y < 8; y++) // 8 lines of 8 pixels
- {
- __oledSetPosition(pOLED, 0, y, bRender);
- for (j = 0; j < 8; j++) // do 8 sections of 16 columns
- {
- s = &pBMP[iOffBits + (j * 2) + (y * iPitch * 8)]; // source line
- memset(ucTemp, 0, 16); // start with all black
- for (x = 0; x < 16; x += 8) // do each block of 16x8 pixels
- {
- dst_mask = 1;
- for (q = 0; q < 8; q++) // gather 8 rows
- {
- b = pgm_read_byte(s + (q * iPitch));
- for (z = 0; z < 8; z++) // gather up the 8 bits of this column
- {
- if (b & 0x80)
- ucTemp[x + z] |= dst_mask;
- b <<= 1;
- } // for z
- dst_mask <<= 1;
- } // for q
- s++; // next source byte
- } // for x
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, ucTemp, 16, bRender);
- } // for j
- } // for y
- return 0;
- } /* oledLoadBMP() */
- //
- // Set the current cursor position
- // The column represents the pixel column (0-127)
- // The row represents the text row (0-7)
- //
- void __oledSetCursor(SSOLED *pOLED, int x, int y)
- {
- pOLED->iCursorX = x;
- pOLED->iCursorY = y;
- } /* oledSetCursor() */
- //
- // Turn text wrap on or off for the oldWriteString() function
- //
- void __oledSetTextWrap(SSOLED *pOLED, int bWrap)
- {
- pOLED->oled_wrap = bWrap;
- } /* oledSetTextWrap() */
- //
- // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
- // At the given col+row
- //
- int __oledWriteString(SSOLED *pOLED, int iScroll, int x, int y, char *szMsg, int iSize, int bInvert, int bRender)
- {
- int i, iFontOff, iLen, iFontSkip;
- unsigned char c, *s, ucTemp[40];
-
- if (x == -1 || y == -1) // use the cursor position
- {
- x = pOLED->iCursorX;
- y = pOLED->iCursorY;
- }
- else
- {
- pOLED->iCursorX = x;
- pOLED->iCursorY = y; // set the new cursor position
- }
- if (pOLED->iCursorX >= pOLED->oled_x || pOLED->iCursorY >= pOLED->oled_y / 8)
- return -1; // can't draw off the display
-
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- if (iSize == FONT_8x8) // 8x8 font
- {
- i = 0;
- iFontSkip = iScroll & 7; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && szMsg[i] != 0 && pOLED->iCursorY < pOLED->oled_y / 8)
- {
- if (iScroll < 8) // only display visible characters
- {
- c = (unsigned char) szMsg[i];
- iFontOff = (int) (c - 32) * 7;
- // we can't directly use the pointer to FLASH memory, so copy to a local buffer
- ucTemp[0] = 0;
- memcpy(&ucTemp[1], &ucFont[iFontOff], 7);
- if (bInvert)
- __InvertBytes(ucTemp, 8);
- // oledCachedWrite(ucTemp, 8);
- iLen = 8 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 7 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY++;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- iFontSkip = 0;
- }
- iScroll -= 8;
- i++;
- } // while
- // oledCachedFlush(); // write any remaining data
- return 0;
- } // 8x8
- #ifndef __AVR__
- else if (iSize == FONT_16x32) // 16x32 font
- {
- i = 0;
- iFontSkip = iScroll & 15; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 3 && szMsg[i] != 0)
- {
- if (iScroll < 16) // if characters are visible
- {
- s = (unsigned char *) &ucBigFont[(unsigned char) (szMsg[i] - 32) * 64];
- iLen = 16 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- // we can't directly use the pointer to FLASH memory, so copy to a local buffer
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- memcpy(ucTemp, s, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
- memcpy(ucTemp, s + 16, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- if (pOLED->iCursorY <= 5)
- {
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 2, bRender);
- memcpy(ucTemp, s + 32, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- }
- if (pOLED->iCursorY <= 4)
- {
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 3, bRender);
- memcpy(ucTemp, s + 48, 16);
- if (bInvert)
- __InvertBytes(ucTemp, 16);
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- }
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY += 4;
- }
- iFontSkip = 0;
- } // if character visible from scrolling
- iScroll -= 16;
- i++;
- } // while
- return 0;
- } // 16x32
- #endif // !__AVR__
- else if (iSize == FONT_12x16) // 6x8 stretched to 12x16
- {
- i = 0;
- iFontSkip = iScroll % 12; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
- {
- // stretch the 'normal' font instead of using the big font
- if (iScroll < 12) // if characters are visible
- {
- int tx, ty;
- c = szMsg[i] - 32;
- unsigned char uc1, uc2, ucMask, *pDest;
- s = (unsigned char *) &ucSmallFont[(int) c * 5];
- ucTemp[0] = 0; // first column is blank
- memcpy(&ucTemp[1], s, 6);
- if (bInvert)
- __InvertBytes(ucTemp, 6);
- // Stretch the font to double width + double height
- memset(&ucTemp[6], 0, 24); // write 24 new bytes
- for (tx = 0; tx < 6; tx++)
- {
- ucMask = 3;
- pDest = &ucTemp[6 + tx * 2];
- uc1 = uc2 = 0;
- c = ucTemp[tx];
- for (ty = 0; ty < 4; ty++)
- {
- if (c & (1 << ty)) // a bit is set
- uc1 |= ucMask;
- if (c & (1 << (ty + 4)))
- uc2 |= ucMask;
- ucMask <<= 2;
- }
- pDest[0] = uc1;
- pDest[1] = uc1; // double width
- pDest[12] = uc2;
- pDest[13] = uc2;
- }
- // smooth the diagonal lines
- for (tx = 0; tx < 5; tx++)
- {
- uint8_t c0, c1, ucMask2;
- c0 = ucTemp[tx];
- c1 = ucTemp[tx + 1];
- pDest = &ucTemp[6 + tx * 2];
- ucMask = 1;
- ucMask2 = 2;
- for (ty = 0; ty < 7; ty++)
- {
- if (((c0 & ucMask) && !(c1 & ucMask) && !(c0 & ucMask2) && (c1 & ucMask2))
- || (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2)))
- {
- if (ty < 3) // top half
- {
- pDest[1] |= (1 << ((ty * 2) + 1));
- pDest[2] |= (1 << ((ty * 2) + 1));
- pDest[1] |= (1 << ((ty + 1) * 2));
- pDest[2] |= (1 << ((ty + 1) * 2));
- }
- else if (ty == 3) // on the border
- {
- pDest[1] |= 0x80;
- pDest[2] |= 0x80;
- pDest[13] |= 1;
- pDest[14] |= 1;
- }
- else // bottom half
- {
- pDest[13] |= (1 << (2 * (ty - 4) + 1));
- pDest[14] |= (1 << (2 * (ty - 4) + 1));
- pDest[13] |= (1 << ((ty - 3) * 2));
- pDest[14] |= (1 << ((ty - 3) * 2));
- }
- }
- else if (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2))
- {
- if (ty < 4) // top half
- {
- pDest[1] |= (1 << ((ty * 2) + 1));
- pDest[2] |= (1 << ((ty + 1) * 2));
- }
- else
- {
- pDest[13] |= (1 << (2 * (ty - 4) + 1));
- pDest[14] |= (1 << ((ty - 3) * 2));
- }
- }
- ucMask <<= 1;
- ucMask2 <<= 1;
- }
- }
- iLen = 12 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[6 + iFontSkip], iLen, bRender);
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[18 + iFontSkip], iLen, bRender);
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 11 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY += 2;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- iFontSkip = 0;
- } // if characters are visible
- iScroll -= 12;
- i++;
- } // while
- return 0;
- } // 12x16
- else if (iSize == FONT_16x16) // 8x8 stretched to 16x16
- {
- i = 0;
- iFontSkip = iScroll & 15; // number of columns to initially skip
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
- {
- // stretch the 'normal' font instead of using the big font
- if (iScroll < 16) // if characters are visible
- {
- int tx, ty;
- c = szMsg[i] - 32;
- unsigned char uc1, uc2, ucMask, *pDest;
- s = (unsigned char *) &ucFont[(int) c * 7];
- ucTemp[0] = 0;
- memcpy(&ucTemp[1], s, 7);
- if (bInvert)
- __InvertBytes(ucTemp, 8);
- // Stretch the font to double width + double height
- memset(&ucTemp[8], 0, 32); // write 32 new bytes
- for (tx = 0; tx < 8; tx++)
- {
- ucMask = 3;
- pDest = &ucTemp[8 + tx * 2];
- uc1 = uc2 = 0;
- c = ucTemp[tx];
- for (ty = 0; ty < 4; ty++)
- {
- if (c & (1 << ty)) // a bit is set
- uc1 |= ucMask;
- if (c & (1 << (ty + 4)))
- uc2 |= ucMask;
- ucMask <<= 2;
- }
- pDest[0] = uc1;
- pDest[1] = uc1; // double width
- pDest[16] = uc2;
- pDest[17] = uc2;
- }
- iLen = 16 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[8 + iFontSkip], iLen, bRender);
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
- __oledWriteDataBlock(pOLED, &ucTemp[24 + iFontSkip], iLen, bRender);
- pOLED->iCursorX += iLen;
- if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY += 2;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- iFontSkip = 0;
- } // if characters are visible
- iScroll -= 16;
- i++;
- } // while
- return 0;
- } // 16x16
- else if (iSize == FONT_6x8) // 6x8 font
- {
- i = 0;
- iFontSkip = iScroll % 6;
- while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) && szMsg[i] != 0)
- {
- if (iScroll < 6) // if characters are visible
- {
- c = szMsg[i] - 32;
- // we can't directly use the pointer to FLASH memory, so copy to a local buffer
- ucTemp[0] = 0;
- memcpy(&ucTemp[1], &ucSmallFont[(int) c * 5], 5);
- if (bInvert)
- __InvertBytes(ucTemp, 6);
- iLen = 6 - iFontSkip;
- if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
- iLen = pOLED->oled_x - pOLED->iCursorX;
- __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
- // oledCachedWrite(ucTemp, 6);
- pOLED->iCursorX += iLen;
- iFontSkip = 0;
- if (pOLED->iCursorX >= pOLED->oled_x - 5 && pOLED->oled_wrap) // word wrap enabled?
- {
- pOLED->iCursorX = 0; // start at the beginning of the next line
- pOLED->iCursorY++;
- __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
- }
- } // if characters are visible
- iScroll -= 6;
- i++;
- }
- // oledCachedFlush(); // write any remaining data
- return 0;
- } // 6x8
- return -1; // invalid size
- } /* oledWriteString() */
-
- //
- // Render a sprite/rectangle of pixels from a provided buffer to the display.
- // The row values refer to byte rows, not pixel rows due to the memory
- // layout of OLEDs.
- // returns 0 for success, -1 for invalid parameter
- //
- int __oledDrawGFX(SSOLED *pOLED, uint8_t *pBuffer, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth,
- int iHeight, int iSrcPitch)
- {
- int y;
-
- if (iSrcCol < 0 || iSrcCol > 127 || iSrcRow < 0 || iSrcRow > 7 || iDestCol < 0 || iDestCol >= pOLED->oled_x
- || iDestRow < 0 || iDestRow >= (pOLED->oled_y >> 3) || iSrcPitch <= 0)
- return -1; // invalid
-
- for (y = iSrcRow; y < iSrcRow + iHeight; y++)
- {
- uint8_t *s = &pBuffer[(y * iSrcPitch) + iSrcCol];
- __oledSetPosition(pOLED, iDestCol, iDestRow, 1);
- __oledWriteDataBlock(pOLED, s, iWidth, 1);
- pBuffer += iSrcPitch;
- iDestRow++;
- } // for y
- return 0;
- } /* oledDrawGFX() */
- //
- // Dump a screen's worth of data directly to the display
- // Try to speed it up by comparing the new bytes with the existing buffer
- //
- void __oledDumpBuffer(SSOLED *pOLED, uint8_t *pBuffer)
- {
- int x, y;
- int iLines, iCols;
- uint8_t bNeedPos;
- uint8_t *pSrc = pOLED->ucScreen;
-
- if (pBuffer == NULL) // dump the internal buffer if none is given
- pBuffer = pOLED->ucScreen;
- if (pBuffer == NULL)
- return; // no backbuffer and no provided buffer
-
- iLines = pOLED->oled_y >> 3;
- iCols = pOLED->oled_x >> 4;
- for (y = 0; y < iLines; y++)
- {
- bNeedPos = 1; // start of a new line means we need to set the position too
- for (x = 0; x < iCols; x++) // wiring library has a 32-byte buffer, so send 16 bytes so that the data prefix (0x40) can fit
- {
- if (pOLED->ucScreen == NULL || pBuffer == pSrc || memcmp(pSrc, pBuffer, 16) != 0) // doesn't match, need to send it
- {
- if (bNeedPos) // need to reposition output cursor?
- {
- bNeedPos = 0;
- __oledSetPosition(pOLED, x * 16, y, 1);
- }
- __oledWriteDataBlock(pOLED, pBuffer, 16, 1);
- }
- else
- {
- bNeedPos = 1; // we're skipping a block, so next time will need to set the new position
- }
- pSrc += 16;
- pBuffer += 16;
- } // for x
- pSrc += (128 - pOLED->oled_x); // for narrow displays, skip to the next line
- pBuffer += (128 - pOLED->oled_x);
- } // for y
- } /* oledDumpBuffer() */
- //
- // Fill the frame buffer with a byte pattern
- // e.g. all off (0x00) or all on (0xff)
- //
- void __oledFill(SSOLED *pOLED, unsigned char ucData, int bRender)
- {
- uint8_t x, y;
- uint8_t iLines, iCols;
- unsigned char temp[16];
-
- iLines = pOLED->oled_y >> 3;
- iCols = pOLED->oled_x >> 4;
- memset(temp, ucData, 16);
- pOLED->iCursorX = pOLED->iCursorY = 0;
-
- for (y = 0; y < iLines; y++)
- {
- __oledSetPosition(pOLED, 0, y, bRender); // set to (0,Y)
- for (x = 0; x < iCols; x++) // wiring library has a 32-byte buffer, so send 16 bytes so that the data prefix (0x40) can fit
- {
- __oledWriteDataBlock(pOLED, temp, 16, bRender);
- } // for x
- // 72 isn't evenly divisible by 16, so fix it
- if (pOLED->oled_type == OLED_72x40)
- __oledWriteDataBlock(pOLED, temp, 8, bRender);
- } // for y
- if (pOLED->ucScreen)
- memset(pOLED->ucScreen, ucData, (pOLED->oled_x * pOLED->oled_y) / 8);
- } /* oledFill() */
-
- //
- // Provide or revoke a back buffer for your OLED graphics
- // This allows you to manage the RAM used by ss_oled on tiny
- // embedded platforms like the ATmega series
- // Pass NULL to revoke the buffer. Make sure you provide a buffer
- // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
- //
- void __oledSetBackBuffer(SSOLED *pOLED, uint8_t *pBuffer)
- {
- pOLED->ucScreen = pBuffer;
- } /* oledSetBackBuffer() */
-
- void __oledDrawLine(SSOLED *pOLED, int x1, int y1, int x2, int y2, int bRender)
- {
- int temp;
- int dx = x2 - x1;
- int dy = y2 - y1;
- int error;
- uint8_t *p, *pStart, mask, bOld, bNew;
- int xinc, yinc;
- int y, x;
-
- if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pOLED->oled_x || x2 >= pOLED->oled_x || y1 >= pOLED->oled_y
- || y2 >= pOLED->oled_y)
- return;
-
- if (abs(dx) > abs(dy))
- {
- // X major case
- if (x2 < x1)
- {
- dx = -dx;
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- }
-
- y = y1;
- dy = (y2 - y1);
- error = dx >> 1;
- yinc = 1;
- if (dy < 0)
- {
- dy = -dy;
- yinc = -1;
- }
- p = pStart = &pOLED->ucScreen[x1 + ((y >> 3) << 7)]; // point to current spot in back buffer
- mask = 1 << (y & 7); // current bit offset
- for (x = x1; x1 <= x2; x1++)
- {
- *p++ |= mask; // set pixel and increment x pointer
- error -= dy;
- if (error < 0)
- {
- error += dx;
- if (yinc > 0)
- mask <<= 1;
- else
- mask >>= 1;
- if (mask == 0) // we've moved outside the current row, write the data we changed
- {
- __oledSetPosition(pOLED, x, y >> 3, bRender);
- __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender); // write the row we changed
- x = x1 + 1; // we've already written the byte at x1
- y1 = y + yinc;
- p += (yinc > 0) ? 128 : -128;
- pStart = p;
- mask = 1 << (y1 & 7);
- }
- y += yinc;
- }
- } // for x1
- if (p != pStart) // some data needs to be written
- {
- __oledSetPosition(pOLED, x, y >> 3, bRender);
- __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender);
- }
- }
- else
- {
- // Y major case
- if (y1 > y2)
- {
- dy = -dy;
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- }
-
- p = &pOLED->ucScreen[x1 + ((y1 >> 3) * 128)]; // point to current spot in back buffer
- bOld = bNew = p[0]; // current data at that address
- mask = 1 << (y1 & 7); // current bit offset
- dx = (x2 - x1);
- error = dy >> 1;
- xinc = 1;
- if (dx < 0)
- {
- dx = -dx;
- xinc = -1;
- }
- for (x = x1; y1 <= y2; y1++)
- {
- bNew |= mask; // set the pixel
- error -= dx;
- mask <<= 1; // y1++
- if (mask == 0) // we're done with this byte, write it if necessary
- {
- if (bOld != bNew)
- {
- p[0] = bNew; // save to RAM
- __oledSetPosition(pOLED, x, y1 >> 3, bRender);
- __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
- }
- p += 128; // next line
- bOld = bNew = p[0];
- mask = 1; // start at LSB again
- }
- if (error < 0)
- {
- error += dy;
- if (bOld != bNew) // write the last byte we modified if it changed
- {
- p[0] = bNew; // save to RAM
- __oledSetPosition(pOLED, x, y1 >> 3, bRender);
- __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
- }
- p += xinc;
- x += xinc;
- bOld = bNew = p[0];
- }
- } // for y
- if (bOld != bNew) // write the last byte we modified if it changed
- {
- p[0] = bNew; // save to RAM
- __oledSetPosition(pOLED, x, y2 >> 3, bRender);
- __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
- }
- } // y major case
- } /* oledDrawLine() */
-
- //
- // For drawing ellipses, a circle is drawn and the x and y pixels are scaled by a 16-bit integer fraction
- // This function draws a single pixel and scales its position based on the x/y fraction of the ellipse
- //
- static void __DrawScaledPixel(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
- uint8_t ucColor)
- {
- uint8_t *d, ucMask;
-
- if (iXFrac != 0x10000)
- x = ((x * iXFrac) >> 16);
- if (iYFrac != 0x10000)
- y = ((y * iYFrac) >> 16);
- x += iCX;
- y += iCY;
- if (x < 0 || x >= pOLED->oled_x || y < 0 || y >= pOLED->oled_y)
- return; // off the screen
- d = &pOLED->ucScreen[((y >> 3) * 128) + x];
- ucMask = 1 << (y & 7);
- if (ucColor)
- *d |= ucMask;
- else
- *d &= ~ucMask;
- } /* DrawScaledPixel() */
- //
- // For drawing filled ellipses
- //
- static void __DrawScaledLine(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
- uint8_t ucColor)
- {
- int iLen, x2;
- uint8_t *d, ucMask;
- if (iXFrac != 0x10000)
- x = ((x * iXFrac) >> 16);
- if (iYFrac != 0x10000)
- y = ((y * iYFrac) >> 16);
- iLen = x * 2;
- x = iCX - x;
- y += iCY;
- x2 = x + iLen;
- if (y < 0 || y >= pOLED->oled_y)
- return; // completely off the screen
- if (x < 0)
- x = 0;
- if (x2 >= pOLED->oled_x)
- x2 = pOLED->oled_x - 1;
- iLen = x2 - x + 1; // new length
- d = &pOLED->ucScreen[((y >> 3) * 128) + x];
- ucMask = 1 << (y & 7);
- if (ucColor) // white
- {
- for (; iLen > 0; iLen--)
- *d++ |= ucMask;
- }
- else // black
- {
- for (; iLen > 0; iLen--)
- *d++ &= ~ucMask;
- }
- } /* DrawScaledLine() */
- //
- // Draw the 8 pixels around the Bresenham circle
- // (scaled to make an ellipse)
- //
- static void BresenhamCircle(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
- uint8_t ucColor, uint8_t bFill)
- {
- if (bFill) // draw a filled ellipse
- {
- // for a filled ellipse, draw 4 lines instead of 8 pixels
- __DrawScaledLine(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
- __DrawScaledLine(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
- __DrawScaledLine(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
- __DrawScaledLine(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
- }
- else // draw 8 pixels around the edges
- {
- __DrawScaledPixel(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -x, y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -x, -y, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -y, x, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
- __DrawScaledPixel(pOLED, iCX, iCY, -y, -x, iXFrac, iYFrac, ucColor);
- }
- } /* BresenhamCircle() */
-
- //
- // Draw an outline or filled ellipse
- //
- void __oledEllipse(SSOLED *pOLED, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor,
- uint8_t bFilled)
- {
- int32_t iXFrac, iYFrac;
- int iRadius, iDelta, x, y;
-
- if (pOLED == NULL || pOLED->ucScreen == NULL)
- return; // must have back buffer defined
- if (iRadiusX <= 0 || iRadiusY <= 0)
- return; // invalid radii
-
- if (iRadiusX > iRadiusY) // use X as the primary radius
- {
- iRadius = iRadiusX;
- iXFrac = 65536;
- iYFrac = (iRadiusY * 65536) / iRadiusX;
- }
- else
- {
- iRadius = iRadiusY;
- iXFrac = (iRadiusX * 65536) / iRadiusY;
- iYFrac = 65536;
- }
- iDelta = 3 - (2 * iRadius);
- x = 0;
- y = iRadius;
- while (x <= y)
- {
- BresenhamCircle(pOLED, iCenterX, iCenterY, x, y, iXFrac, iYFrac, ucColor, bFilled);
- x++;
- if (iDelta < 0)
- {
- iDelta += (4 * x) + 6;
- }
- else
- {
- iDelta += 4 * (x - y) + 10;
- y--;
- }
- }
- } /* oledEllipse() */
- //
- // Draw an outline or filled rectangle
- //
- void __oledRectangle(SSOLED *pOLED, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled)
- {
- uint8_t *d, ucMask, ucMask2;
- int tmp, iOff;
- if (pOLED == NULL || pOLED->ucScreen == NULL)
- return; // only works with a back buffer
- if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x1 >= pOLED->oled_x || y1 >= pOLED->oled_y || x2 >= pOLED->oled_x
- || y2 >= pOLED->oled_y)
- return; // invalid coordinates
- // Make sure that X1/Y1 is above and to the left of X2/Y2
- // swap coordinates as needed to make this true
- if (x2 < x1)
- {
- tmp = x1;
- x1 = x2;
- x2 = tmp;
- }
- if (y2 < y1)
- {
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- if (bFilled)
- {
- int x, y, iMiddle;
- iMiddle = (y2 >> 3) - (y1 >> 3);
- ucMask = 0xff << (y1 & 7);
- if (iMiddle == 0) // top and bottom lines are in the same row
- ucMask &= (0xff >> (7 - (y2 & 7)));
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
- // Draw top
- for (x = x1; x <= x2; x++)
- {
- if (ucColor)
- *d |= ucMask;
- else
- *d &= ~ucMask;
- d++;
- }
- if (iMiddle > 1) // need to draw middle part
- {
- ucMask = (ucColor) ? 0xff : 0x00;
- for (y = 1; y < iMiddle; y++)
- {
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1 + (y * 128)];
- for (x = x1; x <= x2; x++)
- *d++ = ucMask;
- }
- }
- if (iMiddle >= 1) // need to draw bottom part
- {
- ucMask = 0xff >> (7 - (y2 & 7));
- d = &pOLED->ucScreen[(y2 >> 3) * 128 + x1];
- for (x = x1; x <= x2; x++)
- {
- if (ucColor)
- *d++ |= ucMask;
- else
- *d++ &= ~ucMask;
- }
- }
- }
- else // outline
- {
- // see if top and bottom lines are within the same byte rows
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
- if ((y1 >> 3) == (y2 >> 3))
- {
- ucMask2 = 0xff << (y1 & 7); // L/R end masks
- ucMask = 1 << (y1 & 7);
- ucMask |= 1 << (y2 & 7);
- ucMask2 &= (0xff >> (7 - (y2 & 7)));
- if (ucColor)
- {
- *d++ |= ucMask2; // start
- x1++;
- for (; x1 < x2; x1++)
- *d++ |= ucMask;
- if (x1 <= x2)
- *d++ |= ucMask2; // right edge
- }
- else
- {
- *d++ &= ~ucMask2;
- x1++;
- for (; x1 < x2; x1++)
- *d++ &= ~ucMask;
- if (x1 <= x2)
- *d++ &= ~ucMask2; // right edge
- }
- }
- else
- {
- int y;
- // L/R sides
- iOff = (x2 - x1);
- ucMask = 1 << (y1 & 7);
- for (y = y1; y <= y2; y++)
- {
- if (ucColor)
- {
- *d |= ucMask;
- d[iOff] |= ucMask;
- }
- else
- {
- *d &= ~ucMask;
- d[iOff] &= ~ucMask;
- }
- ucMask <<= 1;
- if (ucMask == 0)
- {
- ucMask = 1;
- d += 128;
- }
- }
- // T/B sides
- ucMask = 1 << (y1 & 7);
- ucMask2 = 1 << (y2 & 7);
- x1++;
- d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
- iOff = (y2 >> 3) - (y1 >> 3);
- iOff *= 128;
- for (; x1 < x2; x1++)
- {
- if (ucColor)
- {
- *d |= ucMask;
- d[iOff] |= ucMask2;
- }
- else
- {
- *d &= ~ucMask;
- d[iOff] &= ~ucMask2;
- }
- d++;
- }
- }
- } // outline
- } /* oledRectangle() */

include 文件夹包含的文件
bitbang_iic.h
- //
- // Bit Bang I2C library
- // Copyright (c) 2018 BitBank Software, Inc.
- // Written by Larry Bank (bitbank@pobox.com)
- // Project started 10/12/2018
- //
- // 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 3 of the License, or
- // (at your option) any later version.
- //
- // This program is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with this program. If not, see <http://www.gnu.org/licenses/>.
- //
- #ifndef __BITBANG_I2C__
- #define __BITBANG_I2C__
-
- #include "pico/stdlib.h"
- #include "hardware/i2c.h"
-
- // supported devices
- enum {
- DEVICE_UNKNOWN = 0,
- DEVICE_SSD1306,
- DEVICE_SH1106,
- DEVICE_VL53L0X,
- DEVICE_BMP180,
- DEVICE_BMP280,
- DEVICE_BME280,
- DEVICE_MPU6000,
- DEVICE_MPU9250,
- DEVICE_MCP9808,
- DEVICE_LSM6DS3,
- DEVICE_ADXL345,
- DEVICE_ADS1115,
- DEVICE_MAX44009,
- DEVICE_MAG3110,
- DEVICE_CCS811,
- DEVICE_HTS221,
- DEVICE_LPS25H,
- DEVICE_LSM9DS1,
- DEVICE_LM8330,
- DEVICE_DS3231,
- DEVICE_LIS3DH,
- DEVICE_LIS3DSH,
- DEVICE_INA219,
- DEVICE_SHT3X,
- DEVICE_HDC1080,
- DEVICE_MPU6886,
- DEVICE_BME680,
- DEVICE_AXP202,
- DEVICE_AXP192,
- DEVICE_24AAXXXE64,
- DEVICE_DS1307
- };
-
- #ifndef LOW
- #define LOW 0
- #define HIGH 1
- #endif
-
- typedef struct mybbi2c
- {
- uint8_t iSDA, iSCL; // pin numbers (0xff = disabled)
- i2c_inst_t * picoI2C; // used pico I2C
- } BBI2C;
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- //
- // Read N bytes
- //
- int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
- //
- // Read N bytes starting at a specific I2C internal register
- //
- int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
- //
- // Write I2C data
- // quits if a NACK is received and returns 0
- // otherwise returns the number of bytes written
- //
- int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
- //
- // Scans for I2C devices on the bus
- // returns a bitmap of devices which are present (128 bits = 16 bytes, LSB first)
- //
- // Test if an address responds
- // returns 0 if no response, 1 if it responds
- //
- uint8_t I2CTest(BBI2C *pI2C, uint8_t addr);
-
- // A set bit indicates that a device responded at that address
- //
- void I2CScan(BBI2C *pI2C, uint8_t *pMap);
- //
- // Initialize the I2C BitBang library
- // Pass the pin numbers used for SDA and SCL
- // as well as the clock rate in Hz
- //
- void I2CInit(BBI2C *pI2C, uint32_t iClock);
- //
- // Figure out what device is at that address
- // returns the enumerated value
- //
- int I2CDiscoverDevice(BBI2C *pI2C, uint8_t i);
-
- #ifdef __cplusplus
- }
- #endif
-
- #endif //__BITBANG_I2C__
-

ss_oled.h
- #ifndef __SS_OLED_H__
- #define __SS_OLED_H__
-
- #include <include/bitbang_iic.h>
-
- typedef struct ssoleds
- {
- uint8_t oled_addr; // requested address or 0xff for automatic detection
- uint8_t oled_wrap, oled_flip, oled_type;
- uint8_t *ucScreen;
- uint8_t iCursorX, iCursorY;
- uint8_t oled_x, oled_y;
- int iScreenOffset;
- BBI2C bbi2c;
- } SSOLED;
- // Make the Linux library interface C instead of C++
- #if defined(__cplusplus)
- extern "C" {
- #endif
-
- // 4 possible font sizes: 8x8, 16x32, 6x8, 16x16 (stretched from 8x8)
- enum {
- FONT_6x8 = 0,
- FONT_8x8,
- FONT_12x16,
- FONT_16x16,
- FONT_16x32
- };
- #define FONT_NORMAL FONT_8x8
- #define FONT_SMALL FONT_6x8
- #define FONT_LARGE FONT_16x32
- #define FONT_STRETCHED FONT_16x16
-
- // OLED type for init function
- enum {
- OLED_128x128 = 1,
- OLED_128x32,
- OLED_128x64,
- OLED_132x64,
- OLED_64x32,
- OLED_96x16,
- OLED_72x40
- };
-
- // Rotation and flip angles to draw tiles
- enum {
- ANGLE_0=0,
- ANGLE_90,
- ANGLE_180,
- ANGLE_270,
- ANGLE_FLIPX,
- ANGLE_FLIPY
- };
-
- // Return value from oledInit()
- enum {
- OLED_NOT_FOUND = -1, // no display found
- OLED_SSD1306_3C, // SSD1306 found at 0x3C
- OLED_SSD1306_3D, // SSD1306 found at 0x3D
- OLED_SH1106_3C, // SH1106 found at 0x3C
- OLED_SH1106_3D, // SH1106 found at 0x3D
- OLED_SH1107_3C, // SH1107
- OLED_SH1107_3D
- };
- //
- // Initializes the OLED controller into "page mode" on I2C
- // If SDAPin and SCLPin are not -1, then bit bang I2C on those pins
- // Otherwise use the Wire library.
- // If you don't need to use a separate reset pin, set it to -1
- //
- int __oledInit(SSOLED *pOLED, int bInvert, int32_t iSpeed);
-
- //
- // Provide or revoke a back buffer for your OLED graphics
- // This allows you to manage the RAM used by ss_oled on tiny
- // embedded platforms like the ATmega series
- // Pass NULL to revoke the buffer. Make sure you provide a buffer
- // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
- //
- void __oledSetBackBuffer(SSOLED *pOLED, uint8_t *pBuffer);
-
- //
- // Sets the brightness (0=off, 255=brightest)
- //
- void __oledSetContrast(SSOLED *pOLED, unsigned char ucContrast);
-
- //
- // Load a 128x64 1-bpp Windows bitmap
- // Pass the pointer to the beginning of the BMP file
- // First pass version assumes a full screen bitmap
- //
- int __oledLoadBMP(SSOLED *pOLED, uint8_t *pBMP, int bInvert, int bRender);
-
- //
- // Power up/down the display
- // useful for low power situations
- //
- void __oledPower(SSOLED *pOLED, uint8_t bOn);
-
- //
- // Set the current cursor position
- // The column represents the pixel column (0-127)
- // The row represents the text row (0-7)
- //
- void __oledSetCursor(SSOLED *pOLED, int x, int y);
-
- //
- // Turn text wrap on or off for the oldWriteString() function
- //
- void __oledSetTextWrap(SSOLED *pOLED, int bWrap);
-
- //
- // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
- // At the given col+row with the given scroll offset. The scroll offset allows you to
- // horizontally scroll text which does not fit on the width of the display. The offset
- // represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
- // of the text.
- // The system remembers where the last text was written (the cursor position)
- // To continue writing from the last position, set the x,y values to -1
- // The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
- // otherwise text which would go off the right edge will not be drawn and the cursor will
- // be left "off screen" until set to a new position explicitly
- //
- // Returns 0 for success, -1 for invalid parameter
- //
- int __oledWriteString(SSOLED *pOLED, int iScrollX, int x, int y, char *szMsg, int iSize, int bInvert, int bRender);
-
- //
- // Fill the frame buffer with a byte pattern
- // e.g. all off (0x00) or all on (0xff)
- //
- void __oledFill(SSOLED *pOLED, unsigned char ucData, int bRender);
-
- //
- // Set (or clear) an individual pixel
- // The local copy of the frame buffer is used to avoid
- // reading data from the display controller
- // (which isn't possible in most configurations)
- // This function needs the USE_BACKBUFFER macro to be defined
- // otherwise, new pixels will erase old pixels within the same byte
- //
- int __oledSetPixel(SSOLED *pOLED, int x, int y, unsigned char ucColor, int bRender);
-
- //
- // Dump an entire custom buffer to the display
- // useful for custom animation effects
- //
- void __oledDumpBuffer(SSOLED *pOLED, uint8_t *pBuffer);
-
- //
- // Render a window of pixels from a provided buffer or the library's internal buffer
- // to the display. The row values refer to byte rows, not pixel rows due to the memory
- // layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
- // returns 0 for success, -1 for invalid parameter
- //
- int __oledDrawGFX(SSOLED *pOLED, uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
-
- //
- // Draw a line between 2 points
- //
- void __oledDrawLine(SSOLED *pOLED, int x1, int y1, int x2, int y2, int bRender);
-
- //
- // Play a frame of animation data
- // The animation data is assumed to be encoded for a full frame of the display
- // Given the pointer to the start of the compressed data,
- // it returns the pointer to the start of the next frame
- // Frame rate control is up to the calling program to manage
- // When it finishes the last frame, it will start again from the beginning
- //
- uint8_t * __oledPlayAnimFrame(SSOLED *pOLED, uint8_t *pAnimation, uint8_t *pCurrent, int iLen);
-
- //
- // Scroll the internal buffer by 1 scanline (up/down)
- // width is in pixels, lines is group of 8 rows
- // Returns 0 for success, -1 for invalid parameter
- //
- int __oledScrollBuffer(SSOLED *pOLED, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp);
-
- //
- // Draw a sprite of any size in any position
- // If it goes beyond the left/right or top/bottom edges
- // it's trimmed to show the valid parts
- // This function requires a back buffer to be defined
- // The priority color (0 or 1) determines which color is painted
- // when a 1 is encountered in the source image.
- // e.g. when 0, the input bitmap acts like a mask to clear
- // the destination where bits are set.
- //
- void __oledDrawSprite(SSOLED *pOLED, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
-
- //
- // Draw a 16x16 tile in any of 4 rotated positions
- // Assumes input image is laid out like "normal" graphics with
- // the MSB on the left and 2 bytes per line
- // On AVR, the source image is assumed to be in FLASH memory
- // The function can draw the tile on byte boundaries, so the x value
- // can be from 0 to 112 and y can be from 0 to 6
- //
- void __oledDrawTile(SSOLED *pOLED, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
-
- //
- // Draw an outline or filled ellipse
- //
- void __oledEllipse(SSOLED *pOLED, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled);
-
- //
- // Draw an outline or filled rectangle
- //
- void __oledRectangle(SSOLED *pOLED, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled);
-
- #if defined(__cplusplus)
- }
- #endif
-
- #endif // __SS_OLED_H__
-

ss_oled.hpp
- #pragma once
-
- #include <include/bitbang_iic.h>
- #include "pico/stdlib.h"
- #include "hardware/i2c.h"
-
- #include "ss_oled.h"
- class picoSSOLED
- {
-
- private:
- SSOLED oled;
- bool invert;
- int32_t speed;
- public:
- //constructor
- picoSSOLED(int iType, int iAddr, bool bFlip, bool bInvert, i2c_inst_t * pI2C, int sda, int scl, int32_t iSpeed)
- {
- oled.oled_type = iType;
- oled.oled_addr = iAddr;
- oled.oled_flip = (int) bFlip;
- invert = bInvert;
- oled.bbi2c.picoI2C = pI2C;
- oled.bbi2c.iSDA = sda;
- oled.bbi2c.iSCL = scl;
- speed = iSpeed;
- }
- ;
-
- int init()
- {
- return __oledInit(&oled, (int) invert, (int32_t) speed);
- }
- ;
-
- //
- // Provide or revoke a back buffer for your OLED graphics
- // This allows you to manage the RAM used by ss_oled on tiny
- // embedded platforms like the ATmega series
- // Pass NULL to revoke the buffer. Make sure you provide a buffer
- // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
- //
- void set_back_buffer(uint8_t * pBuffer)
- {
- __oledSetBackBuffer(&oled, pBuffer);
- }
- ;
-
- //
- // Sets the brightness (0=off, 255=brightest)
- //
- void set_contrast(uint ucContrast)
- {
- __oledSetContrast(&oled, (unsigned char) ucContrast);
- }
- ;
-
- //
- // Load a 128x64 1-bpp Windows bitmap
- // Pass the pointer to the beginning of the BMP file
- // First pass version assumes a full screen bitmap
- //
- int load_bmp(uint8_t *pBMP, bool bInvert, bool bRender)
- {
- return __oledLoadBMP(&oled, pBMP, (int) bInvert, (int) bRender);
- }
- ;
-
- //
- // Power up/down the display
- // useful for low power situations
- //
- void power(bool bON)
- {
- __oledPower(&oled, (uint8_t) bON);
- }
- ;
-
- //
- // Set the current cursor position
- // The column represents the pixel column (0-127)
- // The row represents the text row (0-7)
- //
- void set_cursor(int x, int y)
- {
- __oledSetCursor(&oled, x, y);
- }
- ;
-
- //
- // Turn text wrap on or off for the oldWriteString() function
- //
- void set_textWrap(bool bWrap)
- {
- __oledSetTextWrap(&oled, (int) bWrap);
- }
- ;
-
- //
- // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
- // At the given col+row with the given scroll offset. The scroll offset allows you to
- // horizontally scroll text which does not fit on the width of the display. The offset
- // represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
- // of the text.
- // The system remembers where the last text was written (the cursor position)
- // To continue writing from the last position, set the x,y values to -1
- // The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
- // otherwise text which would go off the right edge will not be drawn and the cursor will
- // be left "off screen" until set to a new position explicitly
- //
- // Returns 0 for success, -1 for invalid parameter
- //
- int write_string(int iScrollX, int x, int y, char *szMsg, int iSize, bool bInvert, bool bRender)
- {
- return __oledWriteString(&oled, iScrollX, x, y, szMsg, iSize, (int) bInvert, (int) bRender);
- }
- ;
-
- //
- // Fill the frame buffer with a byte pattern
- // e.g. all off (0x00) or all on (0xff)
- //
- void fill(unsigned char ucData, bool bRender)
- {
- __oledFill(&oled, ucData, (int) bRender);
- }
-
- //
- // Set (or clear) an individual pixel
- // The local copy of the frame buffer is used to avoid
- // reading data from the display controller
- // (which isn't possible in most configurations)
- // This function needs the USE_BACKBUFFER macro to be defined
- // otherwise, new pixels will erase old pixels within the same byte
- //
- int set_pixel(int x, int y, unsigned char ucColor, bool bRender)
- {
- return __oledSetPixel(&oled, x, y, ucColor, (int) bRender);
- }
- ;
-
- //
- // Dump an entire custom buffer to the display
- // useful for custom animation effects
- //
- void dump_buffer(uint8_t *pBuffer)
- {
- __oledDumpBuffer(&oled, pBuffer);
- }
- ;
-
- //
- // Render a window of pixels from a provided buffer or the library's internal buffer
- // to the display. The row values refer to byte rows, not pixel rows due to the memory
- // layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
- // returns 0 for success, -1 for invalid parameter
- //
- int draw_GFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight,
- int iSrcPitch)
- {
- return __oledDrawGFX(&oled, pSrc, iSrcCol, iSrcRow, iDestCol, iDestRow, iWidth, iHeight, iSrcPitch);
- }
- ;
-
- //
- // Draw a line between 2 points
- //
- void draw_line(int x1, int y1, int x2, int y2, bool bRender)
- {
- __oledDrawLine(&oled, x1, y1, x2, y2, (int) bRender);
- }
- ;
-
- //
- // Play a frame of animation data
- // The animation data is assumed to be encoded for a full frame of the display
- // Given the pointer to the start of the compressed data,
- // it returns the pointer to the start of the next frame
- // Frame rate control is up to the calling program to manage
- // When it finishes the last frame, it will start again from the beginning
- //
- uint8_t * play_anim_frame(uint8_t *pAnimation, uint8_t *pCurrent, int iLen)
- {
- return __oledPlayAnimFrame(&oled, pAnimation, pCurrent, iLen);
- }
- ;
-
- //
- // Scroll the internal buffer by 1 scanline (up/down)
- // width is in pixels, lines is group of 8 rows
- // Returns 0 for success, -1 for invalid parameter
- //
- int scroll_buffer(int iStartCol, int iEndCol, int iStartRow, int iEndRow, bool bUp)
- {
- return __oledScrollBuffer(&oled, iStartCol, iEndCol, iStartRow, iEndRow, (int) bUp);
- }
- ;
-
- //
- // Draw a sprite of any size in any position
- // If it goes beyond the left/right or top/bottom edges
- // it's trimmed to show the valid parts
- // This function requires a back buffer to be defined
- // The priority color (0 or 1) determines which color is painted
- // when a 1 is encountered in the source image.
- // e.g. when 0, the input bitmap acts like a mask to clear
- // the destination where bits are set.
- //
- void draw_sprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
- {
- __oledDrawSprite(&oled, pSprite, cx, cy, iPitch, x, y, iPriority);
- }
- ;
-
- //
- // Draw a 16x16 tile in any of 4 rotated positions
- // Assumes input image is laid out like "normal" graphics with
- // the MSB on the left and 2 bytes per line
- // On AVR, the source image is assumed to be in FLASH memory
- // The function can draw the tile on byte boundaries, so the x value
- // can be from 0 to 112 and y can be from 0 to 6
- //
- void draw_tile(const uint8_t *pTile, int x, int y, int iRotation, bool bInvert, bool bRender)
- {
- __oledDrawTile(&oled, (const uint8_t *) pTile, x, y, iRotation, (int) bInvert, (int) bRender);
- }
- ;
-
- //
- // Draw an outline or filled ellipse
- //
- void draw_ellipse(int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, bool bFilled)
- {
- __oledEllipse(&oled, iCenterX, iCenterY, iRadiusX, iRadiusY, ucColor, (uint8_t) bFilled);
- }
- ;
-
- //
- // Draw an outline or filled rectangle
- //
- void draw_rectangle(int x1, int y1, int x2, int y2, uint8_t ucColor, bool bFilled)
- {
- __oledRectangle(&oled, x1, y1, x2, y2, ucColor, (uint8_t) bFilled);
-
- }
- ;
-
- };
-

stripp.hpp
- //class, constructor & methods definitions
-
- class picoSSOLED {
-
- private:
-
- [...]
-
- public:
- //constructor
-
- picoSSOLED(int iType, int iAddr, bool bFlip, bool bInvert, i2c_inst_t * pUART, int sda, int scl, int32_t iSpeed) {
-
- //methods
- int init ();
-
-
- //
- // Provide or revoke a back buffer for your OLED graphics
- // This allows you to manage the RAM used by ss_oled on tiny
- // embedded platforms like the ATmega series
- // Pass NULL to revoke the buffer. Make sure you provide a buffer
- // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
- //
- void set_back_buffer(uint8_t * pBuffer);
-
- //
- // Sets the brightness (0=off, 255=brightest)
- //
- void set_contrast(uint ucContrast);
-
- //
- // Load a 128x64 1-bpp Windows bitmap
- // Pass the pointer to the beginning of the BMP file
- // First pass version assumes a full screen bitmap
- //
- int load_bmp(uint8_t *pBMP, bool bInvert, bool bRender);
-
- //
- // Power up/down the display
- // useful for low power situations
- //
- void power(bool bON);
-
- //
- // Set the current cursor position
- // The column represents the pixel column (0-127)
- // The row represents the text row (0-7)
- //
- void set_cursor(int x, int y);
-
- //
- // Turn text wrap on or off for the oldWriteString() function
- //
- void set_textWrap(bool bWrap);
-
- //
- // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
- // At the given col+row with the given scroll offset. The scroll offset allows you to
- // horizontally scroll text which does not fit on the width of the display. The offset
- // represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
- // of the text.
- // The system remembers where the last text was written (the cursor position)
- // To continue writing from the last position, set the x,y values to -1
- // The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
- // otherwise text which would go off the right edge will not be drawn and the cursor will
- // be left "off screen" until set to a new position explicitly
- //
- // Returns 0 for success, -1 for invalid parameter
- //
- int write_string(int iScrollX, int x, int y, char *szMsg, int iSize, bool bInvert, bool bRender);
-
- //
- // Fill the frame buffer with a byte pattern
- // e.g. all off (0x00) or all on (0xff)
- //
- void fill(unsigned char ucData, bool bRender);
-
- //
- // Set (or clear) an individual pixel
- // The local copy of the frame buffer is used to avoid
- // reading data from the display controller
- // (which isn't possible in most configurations)
- // This function needs the USE_BACKBUFFER macro to be defined
- // otherwise, new pixels will erase old pixels within the same byte
- //
- int set_pixel(int x, int y, unsigned char ucColor, bool bRender);
-
- //
- // Dump an entire custom buffer to the display
- // useful for custom animation effects
- //
- void dump_buffer(uint8_t *pBuffer);
-
- //
- // Render a window of pixels from a provided buffer or the library's internal buffer
- // to the display. The row values refer to byte rows, not pixel rows due to the memory
- // layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
- // returns 0 for success, -1 for invalid parameter
- //
- int draw_GFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
-
- //
- // Draw a line between 2 points
- //
- void draw_line(int x1, int y1, int x2, int y2, bool bRender);
-
- //
- // Play a frame of animation data
- // The animation data is assumed to be encoded for a full frame of the display
- // Given the pointer to the start of the compressed data,
- // it returns the pointer to the start of the next frame
- // Frame rate control is up to the calling program to manage
- // When it finishes the last frame, it will start again from the beginning
- //
- uint8_t * play_anim_frame(uint8_t *pAnimation, uint8_t *pCurrent, int iLen);
-
- //
- // Scroll the internal buffer by 1 scanline (up/down)
- // width is in pixels, lines is group of 8 rows
- // Returns 0 for success, -1 for invalid parameter
- //
- int scroll_buffer(int iStartCol, int iEndCol, int iStartRow, int iEndRow, bool bUp);
-
- //
- // Draw a sprite of any size in any position
- // If it goes beyond the left/right or top/bottom edges
- // it's trimmed to show the valid parts
- // This function requires a back buffer to be defined
- // The priority color (0 or 1) determines which color is painted
- // when a 1 is encountered in the source image.
- // e.g. when 0, the input bitmap acts like a mask to clear
- // the destination where bits are set.
- //
- void draw_sprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
-
- //
- // Draw a 16x16 tile in any of 4 rotated positions
- // Assumes input image is laid out like "normal" graphics with
- // the MSB on the left and 2 bytes per line
- // On AVR, the source image is assumed to be in FLASH memory
- // The function can draw the tile on byte boundaries, so the x value
- // can be from 0 to 112 and y can be from 0 to 6
- //
- void draw_tile(const uint8_t *pTile, int x, int y, int iRotation, bool bInvert, bool bRender);
-
- //
- // Draw an outline or filled ellipse
- //
- void draw_ellipse(int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, bool bFilled);
-
- //
- // Draw an outline or filled rectangle
- //
- void draw_rectangle(int x1, int y1, int x2, int y2, uint8_t ucColor, bool bFilled);
-
- };
-
-

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。