当前位置:   article > 正文

oled屏幕(IIC接口+1306驱动)+raspberrypi pico 显示基于RT-Thread_raspberry pi pico ssd1306

raspberry pi pico ssd1306

屏幕参数

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

  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-01-28 Damon first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include "pico/stdlib.h"
  13. #include "include/ss_oled.hpp"
  14. // RPI Pico
  15. #define SDA_PIN 4
  16. #define SCL_PIN 5
  17. #define PICO_I2C i2c0
  18. #define I2C_SPEED 100 * 1000
  19. #define OLED_WIDTH 128
  20. #define OLED_HEIGHT 64
  21. #define LED_PIN 25
  22. int main(void)
  23. {
  24. rt_kprintf("Hello, RT-Thread!\n");
  25. rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
  26. static uint8_t ucBuffer[1024];
  27. uint8_t uc[8];
  28. int i, j, rc;
  29. char szTemp[32];
  30. picoSSOLED myOled(OLED_128x64, 0x3c, 0, 0, PICO_I2C, SDA_PIN, SCL_PIN, I2C_SPEED);
  31. rc = myOled.init() ;
  32. myOled.set_back_buffer(ucBuffer);
  33. while (1) {
  34. if (rc != OLED_NOT_FOUND)
  35. {
  36. rt_pin_write(LED_PIN, 1);
  37. rt_thread_mdelay(1000);
  38. myOled.fill(0,1);
  39. myOled.set_contrast(255);
  40. myOled.write_string(0,0,0,(char *)"**************** ", FONT_8x8, 0, 1);
  41. myOled.write_string(0,4,1,(char *)"RT-Pico SS_OLED", FONT_6x8, 0, 1);
  42. myOled.write_string(0,8,2,(char *)"running on the", FONT_8x8, 0, 1);
  43. myOled.write_string(0,8,3,(char *)"SSD1306 128x64", FONT_8x8, 0, 1);
  44. myOled.write_string(0,4,4,(char *)"monochrome OLED", FONT_8x8, 0, 1);
  45. myOled.write_string(0,0,5,(char *)"Written by Damon", FONT_8x8, 0, 1);
  46. //myOled.write_string(0,4,6,(char *), FONT_6x8, 0, 1);
  47. myOled.write_string(0,0,7,(char *)"**************** ", FONT_8x8, 0, 1);
  48. sleep_ms(10000);
  49. }
  50. myOled.fill(0,1);
  51. myOled.write_string(0,0,0,(char *)"Now with 5 font sizes", FONT_6x8, 0, 1);
  52. myOled.write_string(0,0,1,(char *)"6x8 8x8 16x16", FONT_8x8, 0, 1);
  53. myOled.write_string(0,0,2,(char *)"16x32 and a new", FONT_8x8, 0, 1);
  54. myOled.write_string(0,0,3,(char *)"Stretched", FONT_12x16, 0, 1);
  55. myOled.write_string(0,0,5,(char *)"from 6x8", FONT_12x16, 0, 1);
  56. sleep_ms(10000);
  57. int x, y;
  58. myOled.fill(0, 1);
  59. myOled.write_string(0,0,0,(char *)"Backbuffer Test", FONT_NORMAL,0,1);
  60. myOled.write_string(0,0,1,(char *)"96 lines", FONT_NORMAL,0,1);
  61. sleep_ms(10000);
  62. for (x=0; x<OLED_WIDTH-1; x+=2)
  63. {
  64. myOled.draw_line(x, 0, OLED_WIDTH-x, OLED_HEIGHT-1, 1);
  65. };
  66. for (y=0; y<OLED_HEIGHT-1; y+=2)
  67. {
  68. myOled.draw_line(OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 1);
  69. };
  70. sleep_ms(10000);
  71. myOled.write_string(0,0,1,(char *)"Without backbuffer", FONT_SMALL,0,1);
  72. sleep_ms(10000);
  73. myOled.fill(0,1);
  74. for (x=0; x<OLED_WIDTH-1; x+=2)
  75. {
  76. myOled.draw_line(x, 0, OLED_WIDTH-1-x, OLED_HEIGHT-1, 0);
  77. }
  78. for (y=0; y<OLED_HEIGHT-1; y+=2)
  79. {
  80. myOled.draw_line(OLED_WIDTH-1,y, 0,OLED_HEIGHT-1-y, 0);
  81. }
  82. myOled.dump_buffer(ucBuffer);
  83. myOled.write_string(0,0,1,(char *)"With backbuffer", FONT_SMALL,0,1);
  84. sleep_ms(10000);
  85. rt_pin_write(LED_PIN, 0);
  86. rt_thread_mdelay(1000);
  87. }
  88. return 0;
  89. }

ss_oled.cpp

  1. //
  2. // ss_oled (Small, Simple OLED library)
  3. // Copyright (c) 2017-2019 BitBank Software, Inc.
  4. // Written by Larry Bank (bitbank@pobox.com)
  5. // Project started 1/15/2017
  6. //
  7. // This program is free software: you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation, either version 3 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. //
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include "pico/stdlib.h"
  24. #include "include/ss_oled.h"
  25. const uint8_t ucFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x5f, 0x06, 0x00, 0x00,
  26. 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x14, 0x7f, 0x7f, 0x14, 0x7f, 0x7f, 0x14, 0x24, 0x2e, 0x2a, 0x6b, 0x6b,
  27. 0x3a, 0x12, 0x46, 0x66, 0x30, 0x18, 0x0c, 0x66, 0x62, 0x30, 0x7a, 0x4f, 0x5d, 0x37, 0x7a, 0x48, 0x00, 0x04,
  28. 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, 0x00, 0x41, 0x63, 0x3e, 0x1c, 0x00,
  29. 0x00, 0x08, 0x2a, 0x3e, 0x1c, 0x3e, 0x2a, 0x08, 0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x80,
  30. 0xe0, 0x60, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
  31. 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x3e, 0x7f, 0x59, 0x4d, 0x47, 0x7f, 0x3e, 0x40, 0x42, 0x7f, 0x7f,
  32. 0x40, 0x40, 0x00, 0x62, 0x73, 0x59, 0x49, 0x6f, 0x66, 0x00, 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x18,
  33. 0x1c, 0x16, 0x53, 0x7f, 0x7f, 0x50, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, 0x3c, 0x7e, 0x4b, 0x49, 0x79,
  34. 0x30, 0x00, 0x03, 0x03, 0x71, 0x79, 0x0f, 0x07, 0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x06, 0x4f,
  35. 0x49, 0x69, 0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe6, 0x66, 0x00,
  36. 0x00, 0x08, 0x1c, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x63,
  37. 0x36, 0x1c, 0x08, 0x00, 0x00, 0x02, 0x03, 0x59, 0x5d, 0x07, 0x02, 0x3e, 0x7f, 0x41, 0x5d, 0x5d, 0x5f, 0x0e,
  38. 0x7c, 0x7e, 0x13, 0x13, 0x7e, 0x7c, 0x00, 0x41, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x1c, 0x3e, 0x63, 0x41,
  39. 0x41, 0x63, 0x22, 0x41, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f, 0x49, 0x5d, 0x41, 0x63, 0x41,
  40. 0x7f, 0x7f, 0x49, 0x1d, 0x01, 0x03, 0x1c, 0x3e, 0x63, 0x41, 0x51, 0x33, 0x72, 0x7f, 0x7f, 0x08, 0x08, 0x7f,
  41. 0x7f, 0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, 0x30, 0x70, 0x40, 0x41, 0x7f, 0x3f, 0x01, 0x41, 0x7f,
  42. 0x7f, 0x08, 0x1c, 0x77, 0x63, 0x41, 0x7f, 0x7f, 0x41, 0x40, 0x60, 0x70, 0x7f, 0x7f, 0x0e, 0x1c, 0x0e, 0x7f,
  43. 0x7f, 0x7f, 0x7f, 0x06, 0x0c, 0x18, 0x7f, 0x7f, 0x1c, 0x3e, 0x63, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f,
  44. 0x49, 0x09, 0x0f, 0x06, 0x1e, 0x3f, 0x21, 0x31, 0x61, 0x7f, 0x5e, 0x41, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66,
  45. 0x26, 0x6f, 0x4d, 0x49, 0x59, 0x73, 0x32, 0x03, 0x41, 0x7f, 0x7f, 0x41, 0x03, 0x00, 0x7f, 0x7f, 0x40, 0x40,
  46. 0x7f, 0x7f, 0x00, 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, 0x3f, 0x7f, 0x60, 0x30, 0x60, 0x7f, 0x3f, 0x63,
  47. 0x77, 0x1c, 0x08, 0x1c, 0x77, 0x63, 0x07, 0x4f, 0x78, 0x78, 0x4f, 0x07, 0x00, 0x47, 0x63, 0x71, 0x59, 0x4d,
  48. 0x67, 0x73, 0x00, 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x41,
  49. 0x41, 0x7f, 0x7f, 0x00, 0x00, 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  50. 0x80, 0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x20, 0x74, 0x54, 0x54, 0x3c, 0x78, 0x40, 0x41, 0x7f, 0x3f,
  51. 0x48, 0x48, 0x78, 0x30, 0x38, 0x7c, 0x44, 0x44, 0x6c, 0x28, 0x00, 0x30, 0x78, 0x48, 0x49, 0x3f, 0x7f, 0x40,
  52. 0x38, 0x7c, 0x54, 0x54, 0x5c, 0x18, 0x00, 0x48, 0x7e, 0x7f, 0x49, 0x03, 0x06, 0x00, 0x98, 0xbc, 0xa4, 0xa4,
  53. 0xf8, 0x7c, 0x04, 0x41, 0x7f, 0x7f, 0x08, 0x04, 0x7c, 0x78, 0x00, 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00, 0x60,
  54. 0xe0, 0x80, 0x84, 0xfd, 0x7d, 0x00, 0x41, 0x7f, 0x7f, 0x10, 0x38, 0x6c, 0x44, 0x00, 0x41, 0x7f, 0x7f, 0x40,
  55. 0x00, 0x00, 0x7c, 0x7c, 0x18, 0x78, 0x1c, 0x7c, 0x78, 0x7c, 0x78, 0x04, 0x04, 0x7c, 0x78, 0x00, 0x38, 0x7c,
  56. 0x44, 0x44, 0x7c, 0x38, 0x00, 0x84, 0xfc, 0xf8, 0xa4, 0x24, 0x3c, 0x18, 0x18, 0x3c, 0x24, 0xa4, 0xf8, 0xfc,
  57. 0x84, 0x44, 0x7c, 0x78, 0x4c, 0x04, 0x0c, 0x18, 0x48, 0x5c, 0x54, 0x74, 0x64, 0x24, 0x00, 0x04, 0x04, 0x3e,
  58. 0x7f, 0x44, 0x24, 0x00, 0x3c, 0x7c, 0x40, 0x40, 0x3c, 0x7c, 0x40, 0x1c, 0x3c, 0x60, 0x60, 0x3c, 0x1c, 0x00,
  59. 0x3c, 0x7c, 0x60, 0x30, 0x60, 0x7c, 0x3c, 0x44, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0x44, 0x9c, 0xbc, 0xa0, 0xa0,
  60. 0xfc, 0x7c, 0x00, 0x4c, 0x64, 0x74, 0x5c, 0x4c, 0x64, 0x00, 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, 0x00,
  61. 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02,
  62. 0x03, 0x01, 0x70, 0x78, 0x4c, 0x46, 0x4c, 0x78, 0x70 };
  63. const uint8_t ucBigFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  65. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
  67. 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
  68. 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
  69. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f,
  71. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xfc,
  74. 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0xfc, 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0xff,
  75. 0xff, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  76. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0,
  77. 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0f,
  78. 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
  79. 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f, 0x3f, 0x3f, 0x03, 0x03, 0x00, 0x00, 0x00,
  80. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
  81. 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0,
  82. 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  83. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  84. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0xff,
  85. 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xff,
  86. 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  87. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  88. 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f, 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  89. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  90. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  91. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
  92. 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  93. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  94. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  95. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x00,
  96. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  97. 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  98. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  99. 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xff, 0xff, 0x3f,
  100. 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xcc, 0xcc, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  101. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  102. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  103. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x00,
  104. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  105. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  106. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  107. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f,
  108. 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  109. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  110. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
  111. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  112. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  113. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  114. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  115. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  116. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  117. 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03,
  118. 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  119. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  120. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff,
  121. 0xff, 0xff, 0xff, 0x30, 0x30, 0x0f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
  122. 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  123. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3c, 0x3c, 0xff,
  124. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  125. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
  126. 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  127. 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0x3c, 0x3c, 0x00,
  128. 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  129. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  130. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  131. 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
  132. 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
  133. 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  134. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x00,
  135. 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x00,
  136. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
  137. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  138. 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
  139. 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
  140. 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  141. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x00,
  142. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
  143. 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  144. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  145. 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  146. 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  147. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  148. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03,
  149. 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
  150. 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  151. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  152. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
  153. 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0c,
  154. 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  155. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
  156. 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  157. 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00,
  158. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  159. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
  160. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  161. 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  162. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  163. 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3f, 0x3f, 0xf3,
  164. 0xf3, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  165. 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  166. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  167. 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00,
  168. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  169. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
  170. 0x0c, 0x3c, 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  171. 0x00, 0xc0, 0xc0, 0xf3, 0xf3, 0x3f, 0x3f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  172. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  173. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
  174. 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
  175. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  176. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
  177. 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff,
  178. 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  179. 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  180. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x3c,
  181. 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff,
  182. 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
  183. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  184. 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
  185. 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  186. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  187. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03,
  188. 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  189. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  190. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  191. 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00,
  192. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
  193. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  194. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff,
  195. 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
  196. 0x03, 0x0f, 0x0f, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
  197. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  198. 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f,
  199. 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  200. 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  201. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
  202. 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  203. 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  204. 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  205. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  206. 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff,
  207. 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  208. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  209. 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  210. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
  211. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  212. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  213. 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  214. 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  215. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  216. 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0x00, 0x00, 0x00,
  217. 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  218. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  219. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03,
  220. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  221. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  222. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  223. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf0, 0xf0, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00,
  224. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f,
  225. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  226. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc,
  227. 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03,
  228. 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  229. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  230. 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0,
  231. 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  232. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  233. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  234. 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  235. 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
  236. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
  238. 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff,
  239. 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc3, 0x00,
  240. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  241. 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff,
  242. 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
  243. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  244. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x03, 0x03, 0x03,
  245. 0x03, 0x3f, 0x3f, 0x3c, 0x3c, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xfc,
  246. 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  247. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  248. 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
  249. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  250. 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  251. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  252. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  253. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  254. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  255. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  256. 0x00, 0x3f, 0x3f, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x00,
  257. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  258. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  259. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xfc,
  260. 0xfc, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f,
  261. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  262. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f,
  263. 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x00,
  264. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00,
  265. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  266. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  267. 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  268. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  269. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
  270. 0xff, 0x3f, 0x3f, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0xc0,
  271. 0xc0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  272. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  273. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  274. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  275. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  277. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3f, 0x3f, 0xfc, 0xfc, 0xf0,
  278. 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
  279. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  280. 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  281. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  282. 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  283. 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  284. 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  285. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  286. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  287. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  288. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  289. 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  290. 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  291. 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  292. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  293. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  294. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  295. 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  296. 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
  297. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  298. 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  299. 0xff, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0c,
  300. 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  301. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
  302. 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
  303. 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  304. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  305. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
  306. 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  307. 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  308. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
  309. 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  310. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  311. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  312. 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x03,
  313. 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  314. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  315. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
  316. 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  317. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xcf, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff,
  318. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
  319. 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  320. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
  321. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  322. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  323. 0xc0, 0xcf, 0xcf, 0xcf, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  324. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
  325. 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  326. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xcf, 0xcf, 0xcf,
  327. 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  328. 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  329. 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  330. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  331. 0xff, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  332. 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  333. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00,
  334. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  335. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
  336. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  337. 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  338. 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  339. 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  340. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  341. 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  342. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
  343. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  344. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
  345. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
  346. 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  347. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0,
  348. 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  349. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  350. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  351. 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  352. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03,
  353. 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  354. 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  355. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
  356. 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
  357. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  358. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  359. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x30, 0x30, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x00,
  360. 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00,
  361. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  362. 0xc0, 0xfc, 0xfc, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  363. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
  364. 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  365. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  366. 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  367. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
  368. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  369. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
  370. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  371. 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  372. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
  373. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xff,
  374. 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03,
  375. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  376. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  377. 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  378. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  379. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  380. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  381. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xff,
  382. 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
  383. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  384. 0x00, 0x03, 0x03, 0xc3, 0xc3, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f,
  385. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  386. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  387. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff,
  388. 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
  389. 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  390. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  391. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
  392. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  393. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  394. 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  395. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  396. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  397. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f,
  398. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  399. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  400. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  401. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
  402. 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
  403. 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  404. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  405. // 5x7 font (in 6x8 cell)
  406. const uint8_t ucSmallFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x06, 0x00, 0x07, 0x03, 0x00, 0x07,
  407. 0x03, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x2b, 0x6a, 0x12, 0x00, 0x63, 0x13, 0x08, 0x64, 0x63, 0x36, 0x49,
  408. 0x56, 0x20, 0x50, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x41, 0x3e, 0x00, 0x00,
  409. 0x08, 0x3e, 0x1c, 0x3e, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0xe0, 0x60, 0x00, 0x00, 0x08, 0x08, 0x08,
  410. 0x08, 0x08, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00,
  411. 0x42, 0x7f, 0x40, 0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x22, 0x49, 0x49, 0x49, 0x36, 0x18, 0x14, 0x12, 0x7f,
  412. 0x10, 0x2f, 0x49, 0x49, 0x49, 0x31, 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x01, 0x71, 0x09, 0x05, 0x03, 0x36, 0x49,
  413. 0x49, 0x49, 0x36, 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x00, 0x00,
  414. 0x08, 0x14, 0x22, 0x41, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59,
  415. 0x09, 0x06, 0x3e, 0x41, 0x5d, 0x55, 0x1e, 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e,
  416. 0x41, 0x41, 0x41, 0x22, 0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x7f, 0x09, 0x09, 0x09,
  417. 0x01, 0x3e, 0x41, 0x49, 0x49, 0x7a, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x41, 0x7f, 0x41, 0x00, 0x30, 0x40,
  418. 0x40, 0x40, 0x3f, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x7f, 0x02, 0x04, 0x02, 0x7f,
  419. 0x7f, 0x02, 0x04, 0x08, 0x7f, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x09, 0x09, 0x09, 0x06, 0x3e, 0x41, 0x51,
  420. 0x21, 0x5e, 0x7f, 0x09, 0x09, 0x19, 0x66, 0x26, 0x49, 0x49, 0x49, 0x32, 0x01, 0x01, 0x7f, 0x01, 0x01, 0x3f,
  421. 0x40, 0x40, 0x40, 0x3f, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x3f, 0x40, 0x3c, 0x40, 0x3f, 0x63, 0x14, 0x08, 0x14,
  422. 0x63, 0x07, 0x08, 0x70, 0x08, 0x07, 0x71, 0x49, 0x45, 0x43, 0x00, 0x00, 0x7f, 0x41, 0x41, 0x00, 0x02, 0x04,
  423. 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7f, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x80, 0x80, 0x80, 0x80, 0x80,
  424. 0x00, 0x03, 0x07, 0x00, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x7f, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44,
  425. 0x44, 0x28, 0x38, 0x44, 0x44, 0x44, 0x7f, 0x38, 0x54, 0x54, 0x54, 0x08, 0x08, 0x7e, 0x09, 0x09, 0x00, 0x18,
  426. 0xa4, 0xa4, 0xa4, 0x7c, 0x7f, 0x04, 0x04, 0x78, 0x00, 0x00, 0x00, 0x7d, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7d,
  427. 0x00, 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x00, 0x7c, 0x04, 0x18, 0x04, 0x78, 0x7c, 0x04,
  428. 0x04, 0x78, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0xfc, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0xfc,
  429. 0x44, 0x78, 0x44, 0x04, 0x08, 0x08, 0x54, 0x54, 0x54, 0x20, 0x04, 0x3e, 0x44, 0x24, 0x00, 0x3c, 0x40, 0x20,
  430. 0x7c, 0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x3c, 0x60, 0x30, 0x60, 0x3c, 0x6c, 0x10, 0x10, 0x6c, 0x00, 0x9c,
  431. 0xa0, 0x60, 0x3c, 0x00, 0x64, 0x54, 0x54, 0x4c, 0x00, 0x08, 0x3e, 0x41, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00,
  432. 0x00, 0x00, 0x41, 0x41, 0x3e, 0x08, 0x02, 0x01, 0x02, 0x01, 0x00, 0x3c, 0x26, 0x23, 0x26, 0x3c };
  433. // Initialization sequences
  434. const unsigned char oled128_initbuf[] = { 0x00, 0xae, 0xdc, 0x00, 0x81, 0x40, 0xa1, 0xc8, 0xa8, 0x7f, 0xd5, 0x50, 0xd9,
  435. 0x22, 0xdb, 0x35, 0xb0, 0xda, 0x12, 0xa4, 0xa6, 0xaf };
  436. const unsigned char oled64_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
  437. 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
  438. const unsigned char oled32_initbuf[] = { 0x00, 0xae, 0xd5, 0x80, 0xa8, 0x1f, 0xd3, 0x00, 0x40, 0x8d, 0x14, 0xa1, 0xc8,
  439. 0xda, 0x02, 0x81, 0x7f, 0xd9, 0xf1, 0xdb, 0x40, 0xa4, 0xa6, 0xaf };
  440. const unsigned char oled72_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
  441. 0xad, 0x30, 0xd9, 0xf1, 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
  442. // some globals
  443. static void __oledWriteCommand(SSOLED *pOLED, unsigned char c);
  444. void __InvertBytes(uint8_t *pData, uint8_t bLen);
  445. // wrapper/adapter functions to make the code work on Linux
  446. static uint8_t pgm_read_byte(uint8_t *ptr)
  447. {
  448. return *ptr;
  449. }
  450. static int16_t pgm_read_word(uint8_t *ptr)
  451. {
  452. return ptr[0] + (ptr[1] << 8);
  453. }
  454. static void _I2CWrite(SSOLED *pOLED, unsigned char *pData, int iLen)
  455. {
  456. I2CWrite(&pOLED->bbi2c, pOLED->oled_addr, pData, iLen);
  457. } /* _I2CWrite() */
  458. //
  459. // Initializes the OLED controller into "page mode"
  460. //
  461. int __oledInit(SSOLED *pOLED, int bInvert, int32_t iSpeed)
  462. {
  463. unsigned char uc[4];
  464. int rc = OLED_NOT_FOUND;
  465. int iAddr = pOLED->oled_addr;
  466. int bFlip = (int) pOLED->oled_flip;
  467. int iType = pOLED->oled_type;
  468. pOLED->ucScreen = NULL; // reset backbuffer; user must provide one later
  469. pOLED->oled_wrap = 0; // default - disable text wrap
  470. I2CInit(&pOLED->bbi2c, iSpeed); // on Linux, SDA = bus number, SCL = device address
  471. // find the device address if requested
  472. if (iAddr == -1 || iAddr == 0 || iAddr == 0xff) // find it
  473. {
  474. I2CTest(&pOLED->bbi2c, 0x3c);
  475. if (I2CTest(&pOLED->bbi2c, 0x3c))
  476. pOLED->oled_addr = 0x3c;
  477. else if (I2CTest(&pOLED->bbi2c, 0x3d))
  478. pOLED->oled_addr = 0x3d;
  479. else
  480. return rc; // no display found!
  481. }
  482. else
  483. {
  484. pOLED->oled_addr = iAddr;
  485. I2CTest(&pOLED->bbi2c, iAddr);
  486. if (!I2CTest(&pOLED->bbi2c, iAddr))
  487. return rc; // no display found
  488. }
  489. // Detect the display controller (SSD1306, SH1107 or SH1106)
  490. uint8_t u = 0;
  491. I2CReadRegister(&pOLED->bbi2c, pOLED->oled_addr, 0x00, &u, 1); // read the status register
  492. u &= 0x0f; // mask off power on/off bit
  493. if (u == 0x7 || u == 0xf) // SH1107
  494. {
  495. pOLED->oled_type = OLED_128x128;
  496. rc = OLED_SH1107_3C;
  497. bFlip = !bFlip; // SH1107 seems to have this reversed from the usual direction
  498. }
  499. else if (u == 0x8) // SH1106
  500. {
  501. rc = OLED_SH1106_3C;
  502. pOLED->oled_type = OLED_132x64; // needs to be treated a little differently
  503. }
  504. else if (u == 3 || u == 6) // 6=128x64 display, 3=smaller
  505. {
  506. rc = OLED_SSD1306_3C;
  507. }
  508. if (pOLED->oled_addr == 0x3d)
  509. rc++; // return the '3D' version of the type
  510. if (iType == OLED_128x32 || iType == OLED_96x16)
  511. _I2CWrite(pOLED, (unsigned char *) oled32_initbuf, sizeof(oled32_initbuf));
  512. else if (iType == OLED_128x128)
  513. _I2CWrite(pOLED, (unsigned char *) oled128_initbuf, sizeof(oled128_initbuf));
  514. else if (iType == OLED_72x40)
  515. _I2CWrite(pOLED, (unsigned char *) oled72_initbuf, sizeof(oled72_initbuf));
  516. else
  517. // 132x64, 128x64 and 64x32
  518. _I2CWrite(pOLED, (unsigned char *) oled64_initbuf, sizeof(oled64_initbuf));
  519. if (bInvert)
  520. {
  521. uc[0] = 0; // command
  522. uc[1] = 0xa7; // invert command
  523. _I2CWrite(pOLED, uc, 2);
  524. }
  525. if (bFlip) // rotate display 180
  526. {
  527. uc[0] = 0; // command
  528. uc[1] = 0xa0;
  529. _I2CWrite(pOLED, uc, 2);
  530. uc[1] = 0xc0;
  531. _I2CWrite(pOLED, uc, 2);
  532. }
  533. pOLED->oled_x = 128; // assume 128x64
  534. pOLED->oled_y = 64;
  535. if (iType == OLED_96x16)
  536. {
  537. pOLED->oled_x = 96;
  538. pOLED->oled_y = 16;
  539. }
  540. else if (iType == OLED_128x32)
  541. pOLED->oled_y = 32;
  542. else if (iType == OLED_128x128)
  543. pOLED->oled_y = 128;
  544. else if (iType == OLED_64x32)
  545. {
  546. pOLED->oled_x = 64;
  547. pOLED->oled_y = 32;
  548. }
  549. else if (iType == OLED_72x40)
  550. {
  551. pOLED->oled_x = 72;
  552. pOLED->oled_y = 40;
  553. }
  554. return rc;
  555. } /* oledInit() */
  556. //
  557. // Sends a command to turn on or off the OLED display
  558. //
  559. void __oledPower(SSOLED *pOLED, uint8_t bOn)
  560. {
  561. if (bOn)
  562. __oledWriteCommand(pOLED, 0xaf); // turn on OLED
  563. else
  564. __oledWriteCommand(pOLED, 0xae); // turn off OLED
  565. } /* oledPower() */
  566. // Send a single byte command to the OLED controller
  567. static void __oledWriteCommand(SSOLED *pOLED, unsigned char c)
  568. {
  569. unsigned char buf[2];
  570. buf[0] = 0x00; // command introducer
  571. buf[1] = c;
  572. _I2CWrite(pOLED, buf, 2);
  573. } /* oledWriteCommand() */
  574. static void __oledWriteCommand2(SSOLED *pOLED, unsigned char c, unsigned char d)
  575. {
  576. unsigned char buf[3];
  577. buf[0] = 0x00;
  578. buf[1] = c;
  579. buf[2] = d;
  580. _I2CWrite(pOLED, buf, 3);
  581. } /* oledWriteCommand2() */
  582. //
  583. // Sets the brightness (0=off, 255=brightest)
  584. //
  585. void __oledSetContrast(SSOLED *pOLED, unsigned char ucContrast)
  586. {
  587. __oledWriteCommand2(pOLED, 0x81, ucContrast);
  588. } /* oledSetContrast() */
  589. //
  590. // Scroll the internal buffer by 1 scanline (up/down)
  591. // width is in pixels, lines is group of 8 rows
  592. //
  593. int __oledScrollBuffer(SSOLED *pOLED, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp)
  594. {
  595. uint8_t b, *s;
  596. int col, row;
  597. if (iStartCol < 0 || iStartCol > 127 || iEndCol < 0 || iEndCol > 127 || iStartCol > iEndCol) // invalid
  598. return -1;
  599. if (iStartRow < 0 || iStartRow > 7 || iEndRow < 0 || iEndRow > 7 || iStartRow > iEndRow)
  600. return -1;
  601. if (bUp)
  602. {
  603. for (row = iStartRow; row <= iEndRow; row++)
  604. {
  605. s = &pOLED->ucScreen[(row * 128) + iStartCol];
  606. for (col = iStartCol; col <= iEndCol; col++)
  607. {
  608. b = *s;
  609. b >>= 1; // scroll pixels 'up'
  610. if (row < iEndRow)
  611. b |= (s[128] << 7); // capture pixel of row below, except for last row
  612. *s++ = b;
  613. } // for col
  614. } // for row
  615. } // up
  616. else // down
  617. {
  618. for (row = iEndRow; row >= iStartRow; row--)
  619. {
  620. s = &pOLED->ucScreen[(row * 128) + iStartCol];
  621. for (col = iStartCol; col <= iEndCol; col++)
  622. {
  623. b = *s;
  624. b <<= 1; // scroll down
  625. if (row > iStartRow)
  626. b |= (s[-128] >> 7); // capture pixel of row above
  627. *s++ = b;
  628. } // for col
  629. } // for row
  630. }
  631. return 0;
  632. } /* oledScrollBuffer() */
  633. //
  634. // Send commands to position the "cursor" (aka memory write address)
  635. // to the given row and column
  636. //
  637. static void __oledSetPosition(SSOLED *pOLED, int x, int y, int bRender)
  638. {
  639. unsigned char buf[4];
  640. pOLED->iScreenOffset = (y * 128) + x;
  641. if (!bRender)
  642. return; // don't send the commands to the OLED if we're not rendering the graphics now
  643. if (pOLED->oled_type == OLED_64x32) // visible display starts at column 32, row 4
  644. {
  645. x += 32; // display is centered in VRAM, so this is always true
  646. if (pOLED->oled_flip == 0) // non-flipped display starts from line 4
  647. y += 4;
  648. }
  649. else if (pOLED->oled_type == OLED_132x64) // SH1106 has 128 pixels centered in 132
  650. {
  651. x += 2;
  652. }
  653. else if (pOLED->oled_type == OLED_96x16) // visible display starts at line 2
  654. { // mapping is a bit strange on the 96x16 OLED
  655. if (pOLED->oled_flip)
  656. x += 32;
  657. else
  658. y += 2;
  659. }
  660. else if (pOLED->oled_type == OLED_72x40) // starts at x=28,y=3
  661. {
  662. x += 28;
  663. if (!pOLED->oled_flip)
  664. {
  665. y += 3;
  666. }
  667. }
  668. buf[0] = 0x00; // command introducer
  669. buf[1] = 0xb0 | y; // set page to Y
  670. buf[2] = x & 0xf; // lower column address
  671. buf[3] = 0x10 | (x >> 4); // upper column addr
  672. _I2CWrite(pOLED, buf, 4);
  673. } /* oledSetPosition() */
  674. //
  675. // Write a block of pixel data to the OLED
  676. // Length can be anything from 1 to 1024 (whole display)
  677. //
  678. static void __oledWriteDataBlock(SSOLED *pOLED, unsigned char *ucBuf, int iLen, int bRender)
  679. {
  680. unsigned char ucTemp[129];
  681. ucTemp[0] = 0x40; // data command
  682. // Copying the data has the benefit in SPI mode of not letting
  683. // the original data get overwritten by the SPI.transfer() function
  684. if (bRender)
  685. {
  686. memcpy(&ucTemp[1], ucBuf, iLen);
  687. _I2CWrite(pOLED, ucTemp, iLen + 1);
  688. }
  689. // Keep a copy in local buffer
  690. if (pOLED->ucScreen)
  691. {
  692. memcpy(&pOLED->ucScreen[pOLED->iScreenOffset], ucBuf, iLen);
  693. pOLED->iScreenOffset += iLen;
  694. pOLED->iScreenOffset &= 1023; // we use a fixed stride of 128 no matter what the display size
  695. }
  696. }
  697. //
  698. // Byte operands for compressing the data
  699. // The first 2 bits are the type, followed by the counts
  700. #define OP_MASK 0xc0
  701. #define OP_SKIPCOPY 0x00
  702. #define OP_COPYSKIP 0x40
  703. #define OP_REPEATSKIP 0x80
  704. #define OP_REPEAT 0xc0
  705. //
  706. // Write a block of flash memory to the display
  707. //
  708. void __oledWriteFlashBlock(SSOLED *pOLED, uint8_t *s, int iLen)
  709. {
  710. int j;
  711. int iWidthMask = pOLED->oled_x - 1;
  712. int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
  713. int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 wide
  714. uint8_t ucTemp[128];
  715. while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
  716. {
  717. j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
  718. memcpy(ucTemp, s, j);
  719. __oledWriteDataBlock(pOLED, ucTemp, j, 1);
  720. s += j;
  721. iLen -= j;
  722. pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
  723. __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
  724. } // while it needs some help
  725. memcpy(ucTemp, s, iLen);
  726. __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
  727. pOLED->iScreenOffset = (pOLED->iScreenOffset + iLen) & iSizeMask;
  728. } /* oledWriteFlashBlock() */
  729. //
  730. // Write a repeating byte to the display
  731. //
  732. void __oledRepeatByte(SSOLED *pOLED, uint8_t b, int iLen)
  733. {
  734. int j;
  735. int iWidthMask = pOLED->oled_x - 1;
  736. int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 pixels wide
  737. int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
  738. uint8_t ucTemp[128];
  739. memset(ucTemp, b, (iLen > 128) ? 128 : iLen);
  740. while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
  741. {
  742. j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
  743. __oledWriteDataBlock(pOLED, ucTemp, j, 1);
  744. iLen -= j;
  745. pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
  746. __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
  747. } // while it needs some help
  748. __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
  749. pOLED->iScreenOffset += iLen;
  750. } /* oledRepeatByte() */
  751. //
  752. // Play a frame of animation data
  753. // The animation data is assumed to be encoded for a full frame of the display
  754. // Given the pointer to the start of the compressed data,
  755. // it returns the pointer to the start of the next frame
  756. // Frame rate control is up to the calling program to manage
  757. // When it finishes the last frame, it will start again from the beginning
  758. //
  759. uint8_t * __oledPlayAnimFrame(SSOLED *pOLED, uint8_t *pAnimation, uint8_t *pCurrent, int iLen)
  760. {
  761. uint8_t *s;
  762. int i, j;
  763. unsigned char b, bCode;
  764. int iBufferSize = (pOLED->oled_x * pOLED->oled_y) / 8; // size in bytes of the display devce
  765. int iWidthMask, iWidthShift;
  766. iWidthMask = pOLED->oled_x - 1;
  767. iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // 128 or 64 pixels wide
  768. if (pCurrent == NULL || pCurrent > pAnimation + iLen)
  769. return NULL; // invalid starting point
  770. s = (uint8_t *) pCurrent; // start of animation data
  771. i = 0;
  772. __oledSetPosition(pOLED, 0, 0, 1);
  773. while (i < iBufferSize) // run one frame
  774. {
  775. bCode = pgm_read_byte(s++);
  776. switch (bCode & OP_MASK)
  777. // different compression types
  778. {
  779. case OP_SKIPCOPY: // skip/copy
  780. if (bCode == OP_SKIPCOPY) // big skip
  781. {
  782. b = pgm_read_byte(s++);
  783. i += b + 1;
  784. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  785. }
  786. else // skip/copy
  787. {
  788. if (bCode & 0x38)
  789. {
  790. i += ((bCode & 0x38) >> 3); // skip amount
  791. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  792. }
  793. if (bCode & 7)
  794. {
  795. __oledWriteFlashBlock(pOLED, s, bCode & 7);
  796. s += (bCode & 7);
  797. i += bCode & 7;
  798. }
  799. }
  800. break;
  801. case OP_COPYSKIP: // copy/skip
  802. if (bCode == OP_COPYSKIP) // big copy
  803. {
  804. b = pgm_read_byte(s++);
  805. j = b + 1;
  806. __oledWriteFlashBlock(pOLED, s, j);
  807. s += j;
  808. i += j;
  809. }
  810. else
  811. {
  812. j = ((bCode & 0x38) >> 3);
  813. if (j)
  814. {
  815. __oledWriteFlashBlock(pOLED, s, j);
  816. s += j;
  817. i += j;
  818. }
  819. if (bCode & 7)
  820. {
  821. i += (bCode & 7); // skip
  822. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  823. }
  824. }
  825. break;
  826. case OP_REPEATSKIP: // repeat/skip
  827. j = (bCode & 0x38) >> 3; // repeat count
  828. b = pgm_read_byte(s++);
  829. __oledRepeatByte(pOLED, b, j);
  830. i += j;
  831. if (bCode & 7)
  832. {
  833. i += (bCode & 7); // skip amount
  834. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  835. }
  836. break;
  837. case OP_REPEAT:
  838. j = (bCode & 0x3f) + 1;
  839. b = pgm_read_byte(s++);
  840. __oledRepeatByte(pOLED, b, j);
  841. i += j;
  842. break;
  843. } // switch on code type
  844. } // while rendering a frame
  845. if (s >= pAnimation + iLen) // we've hit the end, restart from the beginning
  846. s = pAnimation;
  847. return s; // return pointer to start of next frame
  848. } /* oledPlayAnimFrame() */
  849. //
  850. // Draw a sprite of any size in any position
  851. // If it goes beyond the left/right or top/bottom edges
  852. // it's trimmed to show the valid parts
  853. // This function requires a back buffer to be defined
  854. // The priority color (0 or 1) determines which color is painted
  855. // when a 1 is encountered in the source image.
  856. //
  857. void __oledDrawSprite(SSOLED *pOLED, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
  858. {
  859. int tx, ty, dx, dy, iStartX;
  860. uint8_t *s, *d, uc, pix, ucSrcMask, ucDstMask;
  861. if (x + cx < 0 || y + cy < 0 || x >= pOLED->oled_x || y >= pOLED->oled_y || pOLED->ucScreen == NULL)
  862. return; // no backbuffer or out of bounds
  863. dy = y; // destination y
  864. if (y < 0) // skip the invisible parts
  865. {
  866. cy += y;
  867. y = -y;
  868. pSprite += (y * iPitch);
  869. dy = 0;
  870. }
  871. if (y + cy > pOLED->oled_y)
  872. cy = pOLED->oled_y - y;
  873. iStartX = 0;
  874. dx = x;
  875. if (x < 0)
  876. {
  877. cx += x;
  878. x = -x;
  879. iStartX = x;
  880. dx = 0;
  881. }
  882. if (x + cx > pOLED->oled_x)
  883. cx = pOLED->oled_x - x;
  884. for (ty = 0; ty < cy; ty++)
  885. {
  886. s = &pSprite[iStartX >> 3];
  887. d = &pOLED->ucScreen[(dy >> 3) * pOLED->oled_x + dx];
  888. ucSrcMask = 0x80 >> (iStartX & 7);
  889. pix = *s++;
  890. ucDstMask = 1 << (dy & 7);
  891. if (iPriority) // priority color is 1
  892. {
  893. for (tx = 0; tx < cx; tx++)
  894. {
  895. uc = d[0];
  896. if (pix & ucSrcMask) // set pixel in source, set it in dest
  897. d[0] = (uc | ucDstMask);
  898. d++; // next pixel column
  899. ucSrcMask >>= 1;
  900. if (ucSrcMask == 0) // read next byte
  901. {
  902. ucSrcMask = 0x80;
  903. pix = *s++;
  904. }
  905. } // for tx
  906. } // priorty color 1
  907. else
  908. {
  909. for (tx = 0; tx < cx; tx++)
  910. {
  911. uc = d[0];
  912. if (pix & ucSrcMask) // clr pixel in source, clr it in dest
  913. d[0] = (uc & ~ucDstMask);
  914. d++; // next pixel column
  915. ucSrcMask >>= 1;
  916. if (ucSrcMask == 0) // read next byte
  917. {
  918. ucSrcMask = 0x80;
  919. pix = *s++;
  920. }
  921. } // for tx
  922. } // priority color 0
  923. dy++;
  924. pSprite += iPitch;
  925. } // for ty
  926. } /* oledDrawSprite() */
  927. //
  928. // Draw a 16x16 tile in any of 4 rotated positions
  929. // Assumes input image is laid out like "normal" graphics with
  930. // the MSB on the left and 2 bytes per line
  931. // On AVR, the source image is assumed to be in FLASH memory
  932. // The function can draw the tile on byte boundaries, so the x value
  933. // can be from 0 to 112 and y can be from 0 to 6
  934. //
  935. void __oledDrawTile(SSOLED *pOLED, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender)
  936. {
  937. uint8_t ucTemp[32]; // prepare LCD data here
  938. uint8_t i, j, k, iOffset, ucMask, uc, ucPixels;
  939. uint8_t bFlipX = 0, bFlipY = 0;
  940. if (x < 0 || y < 0 || y > 6 || x > 112)
  941. return; // out of bounds
  942. if (pTile == NULL)
  943. return; // bad pointer; really? :(
  944. if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPX)
  945. bFlipX = 1;
  946. if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPY)
  947. bFlipY = 1;
  948. memset(ucTemp, 0, sizeof(ucTemp)); // we only set white pixels, so start from black
  949. if (iRotation == ANGLE_0 || iRotation == ANGLE_180 || iRotation == ANGLE_FLIPX || iRotation == ANGLE_FLIPY)
  950. {
  951. for (j = 0; j < 16; j++) // y
  952. {
  953. for (i = 0; i < 16; i += 8) // x
  954. {
  955. ucPixels = pgm_read_byte((uint8_t*) pTile++);
  956. ucMask = 0x80; // MSB is the first source pixel
  957. for (k = 0; k < 8; k++)
  958. {
  959. if (ucPixels & ucMask) // translate the pixel
  960. {
  961. if (bFlipY)
  962. uc = 0x80 >> (j & 7);
  963. else
  964. uc = 1 << (j & 7);
  965. iOffset = i + k;
  966. if (bFlipX)
  967. iOffset = 15 - iOffset;
  968. iOffset += (j & 8) << 1; // top/bottom half of output
  969. if (bFlipY)
  970. iOffset ^= 16;
  971. ucTemp[iOffset] |= uc;
  972. }
  973. ucMask >>= 1;
  974. } // for k
  975. } // for i
  976. } // for j
  977. }
  978. else // rotated 90/270
  979. {
  980. for (j = 0; j < 16; j++) // y
  981. {
  982. for (i = 0; i < 16; i += 8) // x
  983. {
  984. ucPixels = pgm_read_byte((uint8_t*) pTile++);
  985. ucMask = 0x80; // MSB is the first source pixel
  986. for (k = 0; k < 8; k++)
  987. {
  988. if (ucPixels & ucMask) // translate the pixel
  989. {
  990. if (bFlipY)
  991. uc = 0x80 >> k;
  992. else
  993. uc = 1 << k;
  994. iOffset = 15 - j;
  995. if (bFlipX)
  996. iOffset = 15 - iOffset;
  997. iOffset += i << 1; // top/bottom half of output
  998. if (bFlipY)
  999. iOffset ^= 16;
  1000. ucTemp[iOffset] |= uc;
  1001. }
  1002. ucMask >>= 1;
  1003. } // for k
  1004. } // for i
  1005. } // for j
  1006. }
  1007. if (bInvert)
  1008. __InvertBytes(ucTemp, 32);
  1009. // Send the data to the display
  1010. __oledSetPosition(pOLED, x, y, bRender);
  1011. __oledWriteDataBlock(pOLED, ucTemp, 16, bRender); // top half
  1012. __oledSetPosition(pOLED, x, y + 1, bRender);
  1013. __oledWriteDataBlock(pOLED, &ucTemp[16], 16, bRender); // bottom half
  1014. } /* oledDrawTile() */
  1015. // Set (or clear) an individual pixel
  1016. // The local copy of the frame buffer is used to avoid
  1017. // reading data from the display controller
  1018. int __oledSetPixel(SSOLED *pOLED, int x, int y, unsigned char ucColor, int bRender)
  1019. {
  1020. int i;
  1021. unsigned char uc, ucOld;
  1022. i = ((y >> 3) * 128) + x;
  1023. if (i < 0 || i > 1023) // off the screen
  1024. return -1;
  1025. __oledSetPosition(pOLED, x, y >> 3, bRender);
  1026. if (pOLED->ucScreen)
  1027. uc = ucOld = pOLED->ucScreen[i];
  1028. else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // SH1106/SH1107 can read data
  1029. {
  1030. uint8_t ucTemp[3];
  1031. ucTemp[0] = 0x80; // one command
  1032. ucTemp[1] = 0xE0; // read_modify_write
  1033. ucTemp[2] = 0xC0; // one data
  1034. _I2CWrite(pOLED, ucTemp, 3);
  1035. // read a dummy byte followed by the data byte we want
  1036. I2CRead(&pOLED->bbi2c, pOLED->oled_addr, ucTemp, 2);
  1037. uc = ucOld = ucTemp[1]; // first byte is garbage
  1038. }
  1039. else
  1040. uc = ucOld = 0;
  1041. uc &= ~(0x1 << (y & 7));
  1042. if (ucColor)
  1043. {
  1044. uc |= (0x1 << (y & 7));
  1045. }
  1046. if (uc != ucOld) // pixel changed
  1047. {
  1048. // oledSetPosition(x, y>>3);
  1049. if (pOLED->ucScreen)
  1050. {
  1051. __oledWriteDataBlock(pOLED, &uc, 1, bRender);
  1052. pOLED->ucScreen[i] = uc;
  1053. }
  1054. else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // end the read_modify_write operation
  1055. {
  1056. uint8_t ucTemp[4];
  1057. ucTemp[0] = 0xc0; // one data
  1058. ucTemp[1] = uc; // actual data
  1059. ucTemp[2] = 0x80; // one command
  1060. ucTemp[3] = 0xEE; // end read_modify_write operation
  1061. _I2CWrite(pOLED, ucTemp, 4);
  1062. }
  1063. }
  1064. return 0;
  1065. } /* oledSetPixel() */
  1066. //
  1067. // Invert font data
  1068. //
  1069. void __InvertBytes(uint8_t *pData, uint8_t bLen)
  1070. {
  1071. uint8_t i;
  1072. for (i = 0; i < bLen; i++)
  1073. {
  1074. *pData = ~(*pData);
  1075. pData++;
  1076. }
  1077. } /* InvertBytes() */
  1078. //
  1079. // Load a 128x64 1-bpp Windows bitmap
  1080. // Pass the pointer to the beginning of the BMP file
  1081. // First pass version assumes a full screen bitmap
  1082. //
  1083. int __oledLoadBMP(SSOLED *pOLED, uint8_t *pBMP, int bInvert, int bRender)
  1084. {
  1085. int16_t i16;
  1086. int iOffBits, q, y, j; // offset to bitmap data
  1087. int iPitch;
  1088. uint8_t x, z, b, *s;
  1089. uint8_t dst_mask;
  1090. uint8_t ucTemp[16]; // process 16 bytes at a time
  1091. uint8_t bFlipped = false;
  1092. i16 = pgm_read_word(pBMP);
  1093. if (i16 != 0x4d42) // must start with 'BM'
  1094. return -1; // not a BMP file
  1095. i16 = pgm_read_word(pBMP + 18);
  1096. if (i16 != 128) // must be 128 pixels wide
  1097. return -1;
  1098. i16 = pgm_read_word(pBMP + 22);
  1099. if (i16 != 64 && i16 != -64) // must be 64 pixels tall
  1100. return -1;
  1101. if (i16 == 64) // BMP is flipped vertically (typical)
  1102. bFlipped = true;
  1103. i16 = pgm_read_word(pBMP + 28);
  1104. if (i16 != 1) // must be 1 bit per pixel
  1105. return -1;
  1106. iOffBits = pgm_read_word(pBMP + 10);
  1107. iPitch = 16;
  1108. if (bFlipped)
  1109. {
  1110. iPitch = -16;
  1111. iOffBits += (63 * 16); // start from bottom
  1112. }
  1113. // rotate the data and send it to the display
  1114. for (y = 0; y < 8; y++) // 8 lines of 8 pixels
  1115. {
  1116. __oledSetPosition(pOLED, 0, y, bRender);
  1117. for (j = 0; j < 8; j++) // do 8 sections of 16 columns
  1118. {
  1119. s = &pBMP[iOffBits + (j * 2) + (y * iPitch * 8)]; // source line
  1120. memset(ucTemp, 0, 16); // start with all black
  1121. for (x = 0; x < 16; x += 8) // do each block of 16x8 pixels
  1122. {
  1123. dst_mask = 1;
  1124. for (q = 0; q < 8; q++) // gather 8 rows
  1125. {
  1126. b = pgm_read_byte(s + (q * iPitch));
  1127. for (z = 0; z < 8; z++) // gather up the 8 bits of this column
  1128. {
  1129. if (b & 0x80)
  1130. ucTemp[x + z] |= dst_mask;
  1131. b <<= 1;
  1132. } // for z
  1133. dst_mask <<= 1;
  1134. } // for q
  1135. s++; // next source byte
  1136. } // for x
  1137. if (bInvert)
  1138. __InvertBytes(ucTemp, 16);
  1139. __oledWriteDataBlock(pOLED, ucTemp, 16, bRender);
  1140. } // for j
  1141. } // for y
  1142. return 0;
  1143. } /* oledLoadBMP() */
  1144. //
  1145. // Set the current cursor position
  1146. // The column represents the pixel column (0-127)
  1147. // The row represents the text row (0-7)
  1148. //
  1149. void __oledSetCursor(SSOLED *pOLED, int x, int y)
  1150. {
  1151. pOLED->iCursorX = x;
  1152. pOLED->iCursorY = y;
  1153. } /* oledSetCursor() */
  1154. //
  1155. // Turn text wrap on or off for the oldWriteString() function
  1156. //
  1157. void __oledSetTextWrap(SSOLED *pOLED, int bWrap)
  1158. {
  1159. pOLED->oled_wrap = bWrap;
  1160. } /* oledSetTextWrap() */
  1161. //
  1162. // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
  1163. // At the given col+row
  1164. //
  1165. int __oledWriteString(SSOLED *pOLED, int iScroll, int x, int y, char *szMsg, int iSize, int bInvert, int bRender)
  1166. {
  1167. int i, iFontOff, iLen, iFontSkip;
  1168. unsigned char c, *s, ucTemp[40];
  1169. if (x == -1 || y == -1) // use the cursor position
  1170. {
  1171. x = pOLED->iCursorX;
  1172. y = pOLED->iCursorY;
  1173. }
  1174. else
  1175. {
  1176. pOLED->iCursorX = x;
  1177. pOLED->iCursorY = y; // set the new cursor position
  1178. }
  1179. if (pOLED->iCursorX >= pOLED->oled_x || pOLED->iCursorY >= pOLED->oled_y / 8)
  1180. return -1; // can't draw off the display
  1181. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1182. if (iSize == FONT_8x8) // 8x8 font
  1183. {
  1184. i = 0;
  1185. iFontSkip = iScroll & 7; // number of columns to initially skip
  1186. while (pOLED->iCursorX < pOLED->oled_x && szMsg[i] != 0 && pOLED->iCursorY < pOLED->oled_y / 8)
  1187. {
  1188. if (iScroll < 8) // only display visible characters
  1189. {
  1190. c = (unsigned char) szMsg[i];
  1191. iFontOff = (int) (c - 32) * 7;
  1192. // we can't directly use the pointer to FLASH memory, so copy to a local buffer
  1193. ucTemp[0] = 0;
  1194. memcpy(&ucTemp[1], &ucFont[iFontOff], 7);
  1195. if (bInvert)
  1196. __InvertBytes(ucTemp, 8);
  1197. // oledCachedWrite(ucTemp, 8);
  1198. iLen = 8 - iFontSkip;
  1199. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1200. iLen = pOLED->oled_x - pOLED->iCursorX;
  1201. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1202. pOLED->iCursorX += iLen;
  1203. if (pOLED->iCursorX >= pOLED->oled_x - 7 && pOLED->oled_wrap) // word wrap enabled?
  1204. {
  1205. pOLED->iCursorX = 0; // start at the beginning of the next line
  1206. pOLED->iCursorY++;
  1207. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1208. }
  1209. iFontSkip = 0;
  1210. }
  1211. iScroll -= 8;
  1212. i++;
  1213. } // while
  1214. // oledCachedFlush(); // write any remaining data
  1215. return 0;
  1216. } // 8x8
  1217. #ifndef __AVR__
  1218. else if (iSize == FONT_16x32) // 16x32 font
  1219. {
  1220. i = 0;
  1221. iFontSkip = iScroll & 15; // number of columns to initially skip
  1222. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 3 && szMsg[i] != 0)
  1223. {
  1224. if (iScroll < 16) // if characters are visible
  1225. {
  1226. s = (unsigned char *) &ucBigFont[(unsigned char) (szMsg[i] - 32) * 64];
  1227. iLen = 16 - iFontSkip;
  1228. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1229. iLen = pOLED->oled_x - pOLED->iCursorX;
  1230. // we can't directly use the pointer to FLASH memory, so copy to a local buffer
  1231. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1232. memcpy(ucTemp, s, 16);
  1233. if (bInvert)
  1234. __InvertBytes(ucTemp, 16);
  1235. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1236. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
  1237. memcpy(ucTemp, s + 16, 16);
  1238. if (bInvert)
  1239. __InvertBytes(ucTemp, 16);
  1240. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1241. if (pOLED->iCursorY <= 5)
  1242. {
  1243. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 2, bRender);
  1244. memcpy(ucTemp, s + 32, 16);
  1245. if (bInvert)
  1246. __InvertBytes(ucTemp, 16);
  1247. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1248. }
  1249. if (pOLED->iCursorY <= 4)
  1250. {
  1251. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 3, bRender);
  1252. memcpy(ucTemp, s + 48, 16);
  1253. if (bInvert)
  1254. __InvertBytes(ucTemp, 16);
  1255. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1256. }
  1257. pOLED->iCursorX += iLen;
  1258. if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
  1259. {
  1260. pOLED->iCursorX = 0; // start at the beginning of the next line
  1261. pOLED->iCursorY += 4;
  1262. }
  1263. iFontSkip = 0;
  1264. } // if character visible from scrolling
  1265. iScroll -= 16;
  1266. i++;
  1267. } // while
  1268. return 0;
  1269. } // 16x32
  1270. #endif // !__AVR__
  1271. else if (iSize == FONT_12x16) // 6x8 stretched to 12x16
  1272. {
  1273. i = 0;
  1274. iFontSkip = iScroll % 12; // number of columns to initially skip
  1275. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
  1276. {
  1277. // stretch the 'normal' font instead of using the big font
  1278. if (iScroll < 12) // if characters are visible
  1279. {
  1280. int tx, ty;
  1281. c = szMsg[i] - 32;
  1282. unsigned char uc1, uc2, ucMask, *pDest;
  1283. s = (unsigned char *) &ucSmallFont[(int) c * 5];
  1284. ucTemp[0] = 0; // first column is blank
  1285. memcpy(&ucTemp[1], s, 6);
  1286. if (bInvert)
  1287. __InvertBytes(ucTemp, 6);
  1288. // Stretch the font to double width + double height
  1289. memset(&ucTemp[6], 0, 24); // write 24 new bytes
  1290. for (tx = 0; tx < 6; tx++)
  1291. {
  1292. ucMask = 3;
  1293. pDest = &ucTemp[6 + tx * 2];
  1294. uc1 = uc2 = 0;
  1295. c = ucTemp[tx];
  1296. for (ty = 0; ty < 4; ty++)
  1297. {
  1298. if (c & (1 << ty)) // a bit is set
  1299. uc1 |= ucMask;
  1300. if (c & (1 << (ty + 4)))
  1301. uc2 |= ucMask;
  1302. ucMask <<= 2;
  1303. }
  1304. pDest[0] = uc1;
  1305. pDest[1] = uc1; // double width
  1306. pDest[12] = uc2;
  1307. pDest[13] = uc2;
  1308. }
  1309. // smooth the diagonal lines
  1310. for (tx = 0; tx < 5; tx++)
  1311. {
  1312. uint8_t c0, c1, ucMask2;
  1313. c0 = ucTemp[tx];
  1314. c1 = ucTemp[tx + 1];
  1315. pDest = &ucTemp[6 + tx * 2];
  1316. ucMask = 1;
  1317. ucMask2 = 2;
  1318. for (ty = 0; ty < 7; ty++)
  1319. {
  1320. if (((c0 & ucMask) && !(c1 & ucMask) && !(c0 & ucMask2) && (c1 & ucMask2))
  1321. || (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2)))
  1322. {
  1323. if (ty < 3) // top half
  1324. {
  1325. pDest[1] |= (1 << ((ty * 2) + 1));
  1326. pDest[2] |= (1 << ((ty * 2) + 1));
  1327. pDest[1] |= (1 << ((ty + 1) * 2));
  1328. pDest[2] |= (1 << ((ty + 1) * 2));
  1329. }
  1330. else if (ty == 3) // on the border
  1331. {
  1332. pDest[1] |= 0x80;
  1333. pDest[2] |= 0x80;
  1334. pDest[13] |= 1;
  1335. pDest[14] |= 1;
  1336. }
  1337. else // bottom half
  1338. {
  1339. pDest[13] |= (1 << (2 * (ty - 4) + 1));
  1340. pDest[14] |= (1 << (2 * (ty - 4) + 1));
  1341. pDest[13] |= (1 << ((ty - 3) * 2));
  1342. pDest[14] |= (1 << ((ty - 3) * 2));
  1343. }
  1344. }
  1345. else if (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2))
  1346. {
  1347. if (ty < 4) // top half
  1348. {
  1349. pDest[1] |= (1 << ((ty * 2) + 1));
  1350. pDest[2] |= (1 << ((ty + 1) * 2));
  1351. }
  1352. else
  1353. {
  1354. pDest[13] |= (1 << (2 * (ty - 4) + 1));
  1355. pDest[14] |= (1 << ((ty - 3) * 2));
  1356. }
  1357. }
  1358. ucMask <<= 1;
  1359. ucMask2 <<= 1;
  1360. }
  1361. }
  1362. iLen = 12 - iFontSkip;
  1363. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1364. iLen = pOLED->oled_x - pOLED->iCursorX;
  1365. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1366. __oledWriteDataBlock(pOLED, &ucTemp[6 + iFontSkip], iLen, bRender);
  1367. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
  1368. __oledWriteDataBlock(pOLED, &ucTemp[18 + iFontSkip], iLen, bRender);
  1369. pOLED->iCursorX += iLen;
  1370. if (pOLED->iCursorX >= pOLED->oled_x - 11 && pOLED->oled_wrap) // word wrap enabled?
  1371. {
  1372. pOLED->iCursorX = 0; // start at the beginning of the next line
  1373. pOLED->iCursorY += 2;
  1374. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1375. }
  1376. iFontSkip = 0;
  1377. } // if characters are visible
  1378. iScroll -= 12;
  1379. i++;
  1380. } // while
  1381. return 0;
  1382. } // 12x16
  1383. else if (iSize == FONT_16x16) // 8x8 stretched to 16x16
  1384. {
  1385. i = 0;
  1386. iFontSkip = iScroll & 15; // number of columns to initially skip
  1387. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
  1388. {
  1389. // stretch the 'normal' font instead of using the big font
  1390. if (iScroll < 16) // if characters are visible
  1391. {
  1392. int tx, ty;
  1393. c = szMsg[i] - 32;
  1394. unsigned char uc1, uc2, ucMask, *pDest;
  1395. s = (unsigned char *) &ucFont[(int) c * 7];
  1396. ucTemp[0] = 0;
  1397. memcpy(&ucTemp[1], s, 7);
  1398. if (bInvert)
  1399. __InvertBytes(ucTemp, 8);
  1400. // Stretch the font to double width + double height
  1401. memset(&ucTemp[8], 0, 32); // write 32 new bytes
  1402. for (tx = 0; tx < 8; tx++)
  1403. {
  1404. ucMask = 3;
  1405. pDest = &ucTemp[8 + tx * 2];
  1406. uc1 = uc2 = 0;
  1407. c = ucTemp[tx];
  1408. for (ty = 0; ty < 4; ty++)
  1409. {
  1410. if (c & (1 << ty)) // a bit is set
  1411. uc1 |= ucMask;
  1412. if (c & (1 << (ty + 4)))
  1413. uc2 |= ucMask;
  1414. ucMask <<= 2;
  1415. }
  1416. pDest[0] = uc1;
  1417. pDest[1] = uc1; // double width
  1418. pDest[16] = uc2;
  1419. pDest[17] = uc2;
  1420. }
  1421. iLen = 16 - iFontSkip;
  1422. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1423. iLen = pOLED->oled_x - pOLED->iCursorX;
  1424. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1425. __oledWriteDataBlock(pOLED, &ucTemp[8 + iFontSkip], iLen, bRender);
  1426. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
  1427. __oledWriteDataBlock(pOLED, &ucTemp[24 + iFontSkip], iLen, bRender);
  1428. pOLED->iCursorX += iLen;
  1429. if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
  1430. {
  1431. pOLED->iCursorX = 0; // start at the beginning of the next line
  1432. pOLED->iCursorY += 2;
  1433. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1434. }
  1435. iFontSkip = 0;
  1436. } // if characters are visible
  1437. iScroll -= 16;
  1438. i++;
  1439. } // while
  1440. return 0;
  1441. } // 16x16
  1442. else if (iSize == FONT_6x8) // 6x8 font
  1443. {
  1444. i = 0;
  1445. iFontSkip = iScroll % 6;
  1446. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) && szMsg[i] != 0)
  1447. {
  1448. if (iScroll < 6) // if characters are visible
  1449. {
  1450. c = szMsg[i] - 32;
  1451. // we can't directly use the pointer to FLASH memory, so copy to a local buffer
  1452. ucTemp[0] = 0;
  1453. memcpy(&ucTemp[1], &ucSmallFont[(int) c * 5], 5);
  1454. if (bInvert)
  1455. __InvertBytes(ucTemp, 6);
  1456. iLen = 6 - iFontSkip;
  1457. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1458. iLen = pOLED->oled_x - pOLED->iCursorX;
  1459. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1460. // oledCachedWrite(ucTemp, 6);
  1461. pOLED->iCursorX += iLen;
  1462. iFontSkip = 0;
  1463. if (pOLED->iCursorX >= pOLED->oled_x - 5 && pOLED->oled_wrap) // word wrap enabled?
  1464. {
  1465. pOLED->iCursorX = 0; // start at the beginning of the next line
  1466. pOLED->iCursorY++;
  1467. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1468. }
  1469. } // if characters are visible
  1470. iScroll -= 6;
  1471. i++;
  1472. }
  1473. // oledCachedFlush(); // write any remaining data
  1474. return 0;
  1475. } // 6x8
  1476. return -1; // invalid size
  1477. } /* oledWriteString() */
  1478. //
  1479. // Render a sprite/rectangle of pixels from a provided buffer to the display.
  1480. // The row values refer to byte rows, not pixel rows due to the memory
  1481. // layout of OLEDs.
  1482. // returns 0 for success, -1 for invalid parameter
  1483. //
  1484. int __oledDrawGFX(SSOLED *pOLED, uint8_t *pBuffer, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth,
  1485. int iHeight, int iSrcPitch)
  1486. {
  1487. int y;
  1488. if (iSrcCol < 0 || iSrcCol > 127 || iSrcRow < 0 || iSrcRow > 7 || iDestCol < 0 || iDestCol >= pOLED->oled_x
  1489. || iDestRow < 0 || iDestRow >= (pOLED->oled_y >> 3) || iSrcPitch <= 0)
  1490. return -1; // invalid
  1491. for (y = iSrcRow; y < iSrcRow + iHeight; y++)
  1492. {
  1493. uint8_t *s = &pBuffer[(y * iSrcPitch) + iSrcCol];
  1494. __oledSetPosition(pOLED, iDestCol, iDestRow, 1);
  1495. __oledWriteDataBlock(pOLED, s, iWidth, 1);
  1496. pBuffer += iSrcPitch;
  1497. iDestRow++;
  1498. } // for y
  1499. return 0;
  1500. } /* oledDrawGFX() */
  1501. //
  1502. // Dump a screen's worth of data directly to the display
  1503. // Try to speed it up by comparing the new bytes with the existing buffer
  1504. //
  1505. void __oledDumpBuffer(SSOLED *pOLED, uint8_t *pBuffer)
  1506. {
  1507. int x, y;
  1508. int iLines, iCols;
  1509. uint8_t bNeedPos;
  1510. uint8_t *pSrc = pOLED->ucScreen;
  1511. if (pBuffer == NULL) // dump the internal buffer if none is given
  1512. pBuffer = pOLED->ucScreen;
  1513. if (pBuffer == NULL)
  1514. return; // no backbuffer and no provided buffer
  1515. iLines = pOLED->oled_y >> 3;
  1516. iCols = pOLED->oled_x >> 4;
  1517. for (y = 0; y < iLines; y++)
  1518. {
  1519. bNeedPos = 1; // start of a new line means we need to set the position too
  1520. 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
  1521. {
  1522. if (pOLED->ucScreen == NULL || pBuffer == pSrc || memcmp(pSrc, pBuffer, 16) != 0) // doesn't match, need to send it
  1523. {
  1524. if (bNeedPos) // need to reposition output cursor?
  1525. {
  1526. bNeedPos = 0;
  1527. __oledSetPosition(pOLED, x * 16, y, 1);
  1528. }
  1529. __oledWriteDataBlock(pOLED, pBuffer, 16, 1);
  1530. }
  1531. else
  1532. {
  1533. bNeedPos = 1; // we're skipping a block, so next time will need to set the new position
  1534. }
  1535. pSrc += 16;
  1536. pBuffer += 16;
  1537. } // for x
  1538. pSrc += (128 - pOLED->oled_x); // for narrow displays, skip to the next line
  1539. pBuffer += (128 - pOLED->oled_x);
  1540. } // for y
  1541. } /* oledDumpBuffer() */
  1542. //
  1543. // Fill the frame buffer with a byte pattern
  1544. // e.g. all off (0x00) or all on (0xff)
  1545. //
  1546. void __oledFill(SSOLED *pOLED, unsigned char ucData, int bRender)
  1547. {
  1548. uint8_t x, y;
  1549. uint8_t iLines, iCols;
  1550. unsigned char temp[16];
  1551. iLines = pOLED->oled_y >> 3;
  1552. iCols = pOLED->oled_x >> 4;
  1553. memset(temp, ucData, 16);
  1554. pOLED->iCursorX = pOLED->iCursorY = 0;
  1555. for (y = 0; y < iLines; y++)
  1556. {
  1557. __oledSetPosition(pOLED, 0, y, bRender); // set to (0,Y)
  1558. 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
  1559. {
  1560. __oledWriteDataBlock(pOLED, temp, 16, bRender);
  1561. } // for x
  1562. // 72 isn't evenly divisible by 16, so fix it
  1563. if (pOLED->oled_type == OLED_72x40)
  1564. __oledWriteDataBlock(pOLED, temp, 8, bRender);
  1565. } // for y
  1566. if (pOLED->ucScreen)
  1567. memset(pOLED->ucScreen, ucData, (pOLED->oled_x * pOLED->oled_y) / 8);
  1568. } /* oledFill() */
  1569. //
  1570. // Provide or revoke a back buffer for your OLED graphics
  1571. // This allows you to manage the RAM used by ss_oled on tiny
  1572. // embedded platforms like the ATmega series
  1573. // Pass NULL to revoke the buffer. Make sure you provide a buffer
  1574. // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
  1575. //
  1576. void __oledSetBackBuffer(SSOLED *pOLED, uint8_t *pBuffer)
  1577. {
  1578. pOLED->ucScreen = pBuffer;
  1579. } /* oledSetBackBuffer() */
  1580. void __oledDrawLine(SSOLED *pOLED, int x1, int y1, int x2, int y2, int bRender)
  1581. {
  1582. int temp;
  1583. int dx = x2 - x1;
  1584. int dy = y2 - y1;
  1585. int error;
  1586. uint8_t *p, *pStart, mask, bOld, bNew;
  1587. int xinc, yinc;
  1588. int y, x;
  1589. if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pOLED->oled_x || x2 >= pOLED->oled_x || y1 >= pOLED->oled_y
  1590. || y2 >= pOLED->oled_y)
  1591. return;
  1592. if (abs(dx) > abs(dy))
  1593. {
  1594. // X major case
  1595. if (x2 < x1)
  1596. {
  1597. dx = -dx;
  1598. temp = x1;
  1599. x1 = x2;
  1600. x2 = temp;
  1601. temp = y1;
  1602. y1 = y2;
  1603. y2 = temp;
  1604. }
  1605. y = y1;
  1606. dy = (y2 - y1);
  1607. error = dx >> 1;
  1608. yinc = 1;
  1609. if (dy < 0)
  1610. {
  1611. dy = -dy;
  1612. yinc = -1;
  1613. }
  1614. p = pStart = &pOLED->ucScreen[x1 + ((y >> 3) << 7)]; // point to current spot in back buffer
  1615. mask = 1 << (y & 7); // current bit offset
  1616. for (x = x1; x1 <= x2; x1++)
  1617. {
  1618. *p++ |= mask; // set pixel and increment x pointer
  1619. error -= dy;
  1620. if (error < 0)
  1621. {
  1622. error += dx;
  1623. if (yinc > 0)
  1624. mask <<= 1;
  1625. else
  1626. mask >>= 1;
  1627. if (mask == 0) // we've moved outside the current row, write the data we changed
  1628. {
  1629. __oledSetPosition(pOLED, x, y >> 3, bRender);
  1630. __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender); // write the row we changed
  1631. x = x1 + 1; // we've already written the byte at x1
  1632. y1 = y + yinc;
  1633. p += (yinc > 0) ? 128 : -128;
  1634. pStart = p;
  1635. mask = 1 << (y1 & 7);
  1636. }
  1637. y += yinc;
  1638. }
  1639. } // for x1
  1640. if (p != pStart) // some data needs to be written
  1641. {
  1642. __oledSetPosition(pOLED, x, y >> 3, bRender);
  1643. __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender);
  1644. }
  1645. }
  1646. else
  1647. {
  1648. // Y major case
  1649. if (y1 > y2)
  1650. {
  1651. dy = -dy;
  1652. temp = x1;
  1653. x1 = x2;
  1654. x2 = temp;
  1655. temp = y1;
  1656. y1 = y2;
  1657. y2 = temp;
  1658. }
  1659. p = &pOLED->ucScreen[x1 + ((y1 >> 3) * 128)]; // point to current spot in back buffer
  1660. bOld = bNew = p[0]; // current data at that address
  1661. mask = 1 << (y1 & 7); // current bit offset
  1662. dx = (x2 - x1);
  1663. error = dy >> 1;
  1664. xinc = 1;
  1665. if (dx < 0)
  1666. {
  1667. dx = -dx;
  1668. xinc = -1;
  1669. }
  1670. for (x = x1; y1 <= y2; y1++)
  1671. {
  1672. bNew |= mask; // set the pixel
  1673. error -= dx;
  1674. mask <<= 1; // y1++
  1675. if (mask == 0) // we're done with this byte, write it if necessary
  1676. {
  1677. if (bOld != bNew)
  1678. {
  1679. p[0] = bNew; // save to RAM
  1680. __oledSetPosition(pOLED, x, y1 >> 3, bRender);
  1681. __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
  1682. }
  1683. p += 128; // next line
  1684. bOld = bNew = p[0];
  1685. mask = 1; // start at LSB again
  1686. }
  1687. if (error < 0)
  1688. {
  1689. error += dy;
  1690. if (bOld != bNew) // write the last byte we modified if it changed
  1691. {
  1692. p[0] = bNew; // save to RAM
  1693. __oledSetPosition(pOLED, x, y1 >> 3, bRender);
  1694. __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
  1695. }
  1696. p += xinc;
  1697. x += xinc;
  1698. bOld = bNew = p[0];
  1699. }
  1700. } // for y
  1701. if (bOld != bNew) // write the last byte we modified if it changed
  1702. {
  1703. p[0] = bNew; // save to RAM
  1704. __oledSetPosition(pOLED, x, y2 >> 3, bRender);
  1705. __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
  1706. }
  1707. } // y major case
  1708. } /* oledDrawLine() */
  1709. //
  1710. // For drawing ellipses, a circle is drawn and the x and y pixels are scaled by a 16-bit integer fraction
  1711. // This function draws a single pixel and scales its position based on the x/y fraction of the ellipse
  1712. //
  1713. static void __DrawScaledPixel(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
  1714. uint8_t ucColor)
  1715. {
  1716. uint8_t *d, ucMask;
  1717. if (iXFrac != 0x10000)
  1718. x = ((x * iXFrac) >> 16);
  1719. if (iYFrac != 0x10000)
  1720. y = ((y * iYFrac) >> 16);
  1721. x += iCX;
  1722. y += iCY;
  1723. if (x < 0 || x >= pOLED->oled_x || y < 0 || y >= pOLED->oled_y)
  1724. return; // off the screen
  1725. d = &pOLED->ucScreen[((y >> 3) * 128) + x];
  1726. ucMask = 1 << (y & 7);
  1727. if (ucColor)
  1728. *d |= ucMask;
  1729. else
  1730. *d &= ~ucMask;
  1731. } /* DrawScaledPixel() */
  1732. //
  1733. // For drawing filled ellipses
  1734. //
  1735. static void __DrawScaledLine(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
  1736. uint8_t ucColor)
  1737. {
  1738. int iLen, x2;
  1739. uint8_t *d, ucMask;
  1740. if (iXFrac != 0x10000)
  1741. x = ((x * iXFrac) >> 16);
  1742. if (iYFrac != 0x10000)
  1743. y = ((y * iYFrac) >> 16);
  1744. iLen = x * 2;
  1745. x = iCX - x;
  1746. y += iCY;
  1747. x2 = x + iLen;
  1748. if (y < 0 || y >= pOLED->oled_y)
  1749. return; // completely off the screen
  1750. if (x < 0)
  1751. x = 0;
  1752. if (x2 >= pOLED->oled_x)
  1753. x2 = pOLED->oled_x - 1;
  1754. iLen = x2 - x + 1; // new length
  1755. d = &pOLED->ucScreen[((y >> 3) * 128) + x];
  1756. ucMask = 1 << (y & 7);
  1757. if (ucColor) // white
  1758. {
  1759. for (; iLen > 0; iLen--)
  1760. *d++ |= ucMask;
  1761. }
  1762. else // black
  1763. {
  1764. for (; iLen > 0; iLen--)
  1765. *d++ &= ~ucMask;
  1766. }
  1767. } /* DrawScaledLine() */
  1768. //
  1769. // Draw the 8 pixels around the Bresenham circle
  1770. // (scaled to make an ellipse)
  1771. //
  1772. static void BresenhamCircle(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
  1773. uint8_t ucColor, uint8_t bFill)
  1774. {
  1775. if (bFill) // draw a filled ellipse
  1776. {
  1777. // for a filled ellipse, draw 4 lines instead of 8 pixels
  1778. __DrawScaledLine(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
  1779. __DrawScaledLine(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
  1780. __DrawScaledLine(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
  1781. __DrawScaledLine(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
  1782. }
  1783. else // draw 8 pixels around the edges
  1784. {
  1785. __DrawScaledPixel(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
  1786. __DrawScaledPixel(pOLED, iCX, iCY, -x, y, iXFrac, iYFrac, ucColor);
  1787. __DrawScaledPixel(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
  1788. __DrawScaledPixel(pOLED, iCX, iCY, -x, -y, iXFrac, iYFrac, ucColor);
  1789. __DrawScaledPixel(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
  1790. __DrawScaledPixel(pOLED, iCX, iCY, -y, x, iXFrac, iYFrac, ucColor);
  1791. __DrawScaledPixel(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
  1792. __DrawScaledPixel(pOLED, iCX, iCY, -y, -x, iXFrac, iYFrac, ucColor);
  1793. }
  1794. } /* BresenhamCircle() */
  1795. //
  1796. // Draw an outline or filled ellipse
  1797. //
  1798. void __oledEllipse(SSOLED *pOLED, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor,
  1799. uint8_t bFilled)
  1800. {
  1801. int32_t iXFrac, iYFrac;
  1802. int iRadius, iDelta, x, y;
  1803. if (pOLED == NULL || pOLED->ucScreen == NULL)
  1804. return; // must have back buffer defined
  1805. if (iRadiusX <= 0 || iRadiusY <= 0)
  1806. return; // invalid radii
  1807. if (iRadiusX > iRadiusY) // use X as the primary radius
  1808. {
  1809. iRadius = iRadiusX;
  1810. iXFrac = 65536;
  1811. iYFrac = (iRadiusY * 65536) / iRadiusX;
  1812. }
  1813. else
  1814. {
  1815. iRadius = iRadiusY;
  1816. iXFrac = (iRadiusX * 65536) / iRadiusY;
  1817. iYFrac = 65536;
  1818. }
  1819. iDelta = 3 - (2 * iRadius);
  1820. x = 0;
  1821. y = iRadius;
  1822. while (x <= y)
  1823. {
  1824. BresenhamCircle(pOLED, iCenterX, iCenterY, x, y, iXFrac, iYFrac, ucColor, bFilled);
  1825. x++;
  1826. if (iDelta < 0)
  1827. {
  1828. iDelta += (4 * x) + 6;
  1829. }
  1830. else
  1831. {
  1832. iDelta += 4 * (x - y) + 10;
  1833. y--;
  1834. }
  1835. }
  1836. } /* oledEllipse() */
  1837. //
  1838. // Draw an outline or filled rectangle
  1839. //
  1840. void __oledRectangle(SSOLED *pOLED, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled)
  1841. {
  1842. uint8_t *d, ucMask, ucMask2;
  1843. int tmp, iOff;
  1844. if (pOLED == NULL || pOLED->ucScreen == NULL)
  1845. return; // only works with a back buffer
  1846. if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x1 >= pOLED->oled_x || y1 >= pOLED->oled_y || x2 >= pOLED->oled_x
  1847. || y2 >= pOLED->oled_y)
  1848. return; // invalid coordinates
  1849. // Make sure that X1/Y1 is above and to the left of X2/Y2
  1850. // swap coordinates as needed to make this true
  1851. if (x2 < x1)
  1852. {
  1853. tmp = x1;
  1854. x1 = x2;
  1855. x2 = tmp;
  1856. }
  1857. if (y2 < y1)
  1858. {
  1859. tmp = y1;
  1860. y1 = y2;
  1861. y2 = tmp;
  1862. }
  1863. if (bFilled)
  1864. {
  1865. int x, y, iMiddle;
  1866. iMiddle = (y2 >> 3) - (y1 >> 3);
  1867. ucMask = 0xff << (y1 & 7);
  1868. if (iMiddle == 0) // top and bottom lines are in the same row
  1869. ucMask &= (0xff >> (7 - (y2 & 7)));
  1870. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
  1871. // Draw top
  1872. for (x = x1; x <= x2; x++)
  1873. {
  1874. if (ucColor)
  1875. *d |= ucMask;
  1876. else
  1877. *d &= ~ucMask;
  1878. d++;
  1879. }
  1880. if (iMiddle > 1) // need to draw middle part
  1881. {
  1882. ucMask = (ucColor) ? 0xff : 0x00;
  1883. for (y = 1; y < iMiddle; y++)
  1884. {
  1885. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1 + (y * 128)];
  1886. for (x = x1; x <= x2; x++)
  1887. *d++ = ucMask;
  1888. }
  1889. }
  1890. if (iMiddle >= 1) // need to draw bottom part
  1891. {
  1892. ucMask = 0xff >> (7 - (y2 & 7));
  1893. d = &pOLED->ucScreen[(y2 >> 3) * 128 + x1];
  1894. for (x = x1; x <= x2; x++)
  1895. {
  1896. if (ucColor)
  1897. *d++ |= ucMask;
  1898. else
  1899. *d++ &= ~ucMask;
  1900. }
  1901. }
  1902. }
  1903. else // outline
  1904. {
  1905. // see if top and bottom lines are within the same byte rows
  1906. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
  1907. if ((y1 >> 3) == (y2 >> 3))
  1908. {
  1909. ucMask2 = 0xff << (y1 & 7); // L/R end masks
  1910. ucMask = 1 << (y1 & 7);
  1911. ucMask |= 1 << (y2 & 7);
  1912. ucMask2 &= (0xff >> (7 - (y2 & 7)));
  1913. if (ucColor)
  1914. {
  1915. *d++ |= ucMask2; // start
  1916. x1++;
  1917. for (; x1 < x2; x1++)
  1918. *d++ |= ucMask;
  1919. if (x1 <= x2)
  1920. *d++ |= ucMask2; // right edge
  1921. }
  1922. else
  1923. {
  1924. *d++ &= ~ucMask2;
  1925. x1++;
  1926. for (; x1 < x2; x1++)
  1927. *d++ &= ~ucMask;
  1928. if (x1 <= x2)
  1929. *d++ &= ~ucMask2; // right edge
  1930. }
  1931. }
  1932. else
  1933. {
  1934. int y;
  1935. // L/R sides
  1936. iOff = (x2 - x1);
  1937. ucMask = 1 << (y1 & 7);
  1938. for (y = y1; y <= y2; y++)
  1939. {
  1940. if (ucColor)
  1941. {
  1942. *d |= ucMask;
  1943. d[iOff] |= ucMask;
  1944. }
  1945. else
  1946. {
  1947. *d &= ~ucMask;
  1948. d[iOff] &= ~ucMask;
  1949. }
  1950. ucMask <<= 1;
  1951. if (ucMask == 0)
  1952. {
  1953. ucMask = 1;
  1954. d += 128;
  1955. }
  1956. }
  1957. // T/B sides
  1958. ucMask = 1 << (y1 & 7);
  1959. ucMask2 = 1 << (y2 & 7);
  1960. x1++;
  1961. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
  1962. iOff = (y2 >> 3) - (y1 >> 3);
  1963. iOff *= 128;
  1964. for (; x1 < x2; x1++)
  1965. {
  1966. if (ucColor)
  1967. {
  1968. *d |= ucMask;
  1969. d[iOff] |= ucMask2;
  1970. }
  1971. else
  1972. {
  1973. *d &= ~ucMask;
  1974. d[iOff] &= ~ucMask2;
  1975. }
  1976. d++;
  1977. }
  1978. }
  1979. } // outline
  1980. } /* oledRectangle() */

bit_bangiic.cpp

  1. //
  2. // ss_oled (Small, Simple OLED library)
  3. // Copyright (c) 2017-2019 BitBank Software, Inc.
  4. // Written by Larry Bank (bitbank@pobox.com)
  5. // Project started 1/15/2017
  6. //
  7. // This program is free software: you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation, either version 3 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. //
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include "pico/stdlib.h"
  24. #include "include/ss_oled.h"
  25. const uint8_t ucFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x5f, 0x06, 0x00, 0x00,
  26. 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x14, 0x7f, 0x7f, 0x14, 0x7f, 0x7f, 0x14, 0x24, 0x2e, 0x2a, 0x6b, 0x6b,
  27. 0x3a, 0x12, 0x46, 0x66, 0x30, 0x18, 0x0c, 0x66, 0x62, 0x30, 0x7a, 0x4f, 0x5d, 0x37, 0x7a, 0x48, 0x00, 0x04,
  28. 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x3e, 0x63, 0x41, 0x00, 0x00, 0x00, 0x41, 0x63, 0x3e, 0x1c, 0x00,
  29. 0x00, 0x08, 0x2a, 0x3e, 0x1c, 0x3e, 0x2a, 0x08, 0x00, 0x08, 0x08, 0x3e, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x80,
  30. 0xe0, 0x60, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00,
  31. 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x3e, 0x7f, 0x59, 0x4d, 0x47, 0x7f, 0x3e, 0x40, 0x42, 0x7f, 0x7f,
  32. 0x40, 0x40, 0x00, 0x62, 0x73, 0x59, 0x49, 0x6f, 0x66, 0x00, 0x22, 0x63, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x18,
  33. 0x1c, 0x16, 0x53, 0x7f, 0x7f, 0x50, 0x27, 0x67, 0x45, 0x45, 0x7d, 0x39, 0x00, 0x3c, 0x7e, 0x4b, 0x49, 0x79,
  34. 0x30, 0x00, 0x03, 0x03, 0x71, 0x79, 0x0f, 0x07, 0x00, 0x36, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x00, 0x06, 0x4f,
  35. 0x49, 0x69, 0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe6, 0x66, 0x00,
  36. 0x00, 0x08, 0x1c, 0x36, 0x63, 0x41, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x41, 0x63,
  37. 0x36, 0x1c, 0x08, 0x00, 0x00, 0x02, 0x03, 0x59, 0x5d, 0x07, 0x02, 0x3e, 0x7f, 0x41, 0x5d, 0x5d, 0x5f, 0x0e,
  38. 0x7c, 0x7e, 0x13, 0x13, 0x7e, 0x7c, 0x00, 0x41, 0x7f, 0x7f, 0x49, 0x49, 0x7f, 0x36, 0x1c, 0x3e, 0x63, 0x41,
  39. 0x41, 0x63, 0x22, 0x41, 0x7f, 0x7f, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f, 0x49, 0x5d, 0x41, 0x63, 0x41,
  40. 0x7f, 0x7f, 0x49, 0x1d, 0x01, 0x03, 0x1c, 0x3e, 0x63, 0x41, 0x51, 0x33, 0x72, 0x7f, 0x7f, 0x08, 0x08, 0x7f,
  41. 0x7f, 0x00, 0x00, 0x41, 0x7f, 0x7f, 0x41, 0x00, 0x00, 0x30, 0x70, 0x40, 0x41, 0x7f, 0x3f, 0x01, 0x41, 0x7f,
  42. 0x7f, 0x08, 0x1c, 0x77, 0x63, 0x41, 0x7f, 0x7f, 0x41, 0x40, 0x60, 0x70, 0x7f, 0x7f, 0x0e, 0x1c, 0x0e, 0x7f,
  43. 0x7f, 0x7f, 0x7f, 0x06, 0x0c, 0x18, 0x7f, 0x7f, 0x1c, 0x3e, 0x63, 0x41, 0x63, 0x3e, 0x1c, 0x41, 0x7f, 0x7f,
  44. 0x49, 0x09, 0x0f, 0x06, 0x1e, 0x3f, 0x21, 0x31, 0x61, 0x7f, 0x5e, 0x41, 0x7f, 0x7f, 0x09, 0x19, 0x7f, 0x66,
  45. 0x26, 0x6f, 0x4d, 0x49, 0x59, 0x73, 0x32, 0x03, 0x41, 0x7f, 0x7f, 0x41, 0x03, 0x00, 0x7f, 0x7f, 0x40, 0x40,
  46. 0x7f, 0x7f, 0x00, 0x1f, 0x3f, 0x60, 0x60, 0x3f, 0x1f, 0x00, 0x3f, 0x7f, 0x60, 0x30, 0x60, 0x7f, 0x3f, 0x63,
  47. 0x77, 0x1c, 0x08, 0x1c, 0x77, 0x63, 0x07, 0x4f, 0x78, 0x78, 0x4f, 0x07, 0x00, 0x47, 0x63, 0x71, 0x59, 0x4d,
  48. 0x67, 0x73, 0x00, 0x7f, 0x7f, 0x41, 0x41, 0x00, 0x00, 0x01, 0x03, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x41,
  49. 0x41, 0x7f, 0x7f, 0x00, 0x00, 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x08, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
  50. 0x80, 0x00, 0x00, 0x03, 0x07, 0x04, 0x00, 0x00, 0x20, 0x74, 0x54, 0x54, 0x3c, 0x78, 0x40, 0x41, 0x7f, 0x3f,
  51. 0x48, 0x48, 0x78, 0x30, 0x38, 0x7c, 0x44, 0x44, 0x6c, 0x28, 0x00, 0x30, 0x78, 0x48, 0x49, 0x3f, 0x7f, 0x40,
  52. 0x38, 0x7c, 0x54, 0x54, 0x5c, 0x18, 0x00, 0x48, 0x7e, 0x7f, 0x49, 0x03, 0x06, 0x00, 0x98, 0xbc, 0xa4, 0xa4,
  53. 0xf8, 0x7c, 0x04, 0x41, 0x7f, 0x7f, 0x08, 0x04, 0x7c, 0x78, 0x00, 0x44, 0x7d, 0x7d, 0x40, 0x00, 0x00, 0x60,
  54. 0xe0, 0x80, 0x84, 0xfd, 0x7d, 0x00, 0x41, 0x7f, 0x7f, 0x10, 0x38, 0x6c, 0x44, 0x00, 0x41, 0x7f, 0x7f, 0x40,
  55. 0x00, 0x00, 0x7c, 0x7c, 0x18, 0x78, 0x1c, 0x7c, 0x78, 0x7c, 0x78, 0x04, 0x04, 0x7c, 0x78, 0x00, 0x38, 0x7c,
  56. 0x44, 0x44, 0x7c, 0x38, 0x00, 0x84, 0xfc, 0xf8, 0xa4, 0x24, 0x3c, 0x18, 0x18, 0x3c, 0x24, 0xa4, 0xf8, 0xfc,
  57. 0x84, 0x44, 0x7c, 0x78, 0x4c, 0x04, 0x0c, 0x18, 0x48, 0x5c, 0x54, 0x74, 0x64, 0x24, 0x00, 0x04, 0x04, 0x3e,
  58. 0x7f, 0x44, 0x24, 0x00, 0x3c, 0x7c, 0x40, 0x40, 0x3c, 0x7c, 0x40, 0x1c, 0x3c, 0x60, 0x60, 0x3c, 0x1c, 0x00,
  59. 0x3c, 0x7c, 0x60, 0x30, 0x60, 0x7c, 0x3c, 0x44, 0x6c, 0x38, 0x10, 0x38, 0x6c, 0x44, 0x9c, 0xbc, 0xa0, 0xa0,
  60. 0xfc, 0x7c, 0x00, 0x4c, 0x64, 0x74, 0x5c, 0x4c, 0x64, 0x00, 0x08, 0x08, 0x3e, 0x77, 0x41, 0x41, 0x00, 0x00,
  61. 0x00, 0x00, 0x77, 0x77, 0x00, 0x00, 0x41, 0x41, 0x77, 0x3e, 0x08, 0x08, 0x00, 0x02, 0x03, 0x01, 0x03, 0x02,
  62. 0x03, 0x01, 0x70, 0x78, 0x4c, 0x46, 0x4c, 0x78, 0x70 };
  63. const uint8_t ucBigFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  64. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  65. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
  67. 0xfc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
  68. 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
  69. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  70. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f,
  71. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  72. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  73. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xfc,
  74. 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0xfc, 0xfc, 0xfc, 0xfc, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0xff,
  75. 0xff, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  76. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0,
  77. 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0f,
  78. 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
  79. 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x3f, 0x3f, 0x3f, 0x3f, 0x03, 0x03, 0x00, 0x00, 0x00,
  80. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
  81. 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0,
  82. 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  83. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  84. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0xff,
  85. 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xff,
  86. 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  87. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  88. 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f, 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  89. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  90. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  91. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
  92. 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  93. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  94. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  95. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x00,
  96. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  97. 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  98. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  99. 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0xcc, 0xcc, 0xff, 0xff, 0x3f,
  100. 0x3f, 0x3f, 0x3f, 0xff, 0xff, 0xcc, 0xcc, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  101. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  102. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  103. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x00,
  104. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  105. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  106. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  107. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3f,
  108. 0x3f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  109. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  110. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
  111. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  112. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  113. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  114. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  115. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  116. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  117. 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03,
  118. 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  119. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  120. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff,
  121. 0xff, 0xff, 0xff, 0x30, 0x30, 0x0f, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
  122. 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  123. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x3c, 0x3c, 0xff,
  124. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  125. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
  126. 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  127. 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff, 0xff, 0x3c, 0x3c, 0x00,
  128. 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  129. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  130. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  131. 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
  132. 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
  133. 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  134. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0xff, 0xff, 0xff, 0xff, 0x00,
  135. 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x00,
  136. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
  137. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  138. 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
  139. 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
  140. 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  141. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x00,
  142. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc,
  143. 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  144. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  145. 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  146. 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  147. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  148. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03,
  149. 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
  150. 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  151. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  152. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
  153. 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0c,
  154. 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  155. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
  156. 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  157. 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00,
  158. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  159. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
  160. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  161. 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  162. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  163. 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x3f, 0x3f, 0xf3,
  164. 0xf3, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  165. 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  166. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  167. 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00,
  168. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  169. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
  170. 0x0c, 0x3c, 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  171. 0x00, 0xc0, 0xc0, 0xf3, 0xf3, 0x3f, 0x3f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  172. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  173. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
  174. 0xff, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
  175. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  176. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
  177. 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff,
  178. 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  179. 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  180. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x3c,
  181. 0x3c, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xff,
  182. 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
  183. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  184. 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00,
  185. 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  186. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  187. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03,
  188. 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  189. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  190. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  191. 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0, 0xf0, 0x00,
  192. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
  193. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  194. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff,
  195. 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
  196. 0x03, 0x0f, 0x0f, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c,
  197. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  198. 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0xc3, 0xc3, 0x0f, 0x0f, 0x3f,
  199. 0x3f, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  200. 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  201. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc,
  202. 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  203. 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  204. 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  205. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  206. 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff,
  207. 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  208. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  209. 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  210. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
  211. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  212. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  213. 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  214. 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  215. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  216. 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0x00, 0x00, 0x00,
  217. 0x00, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  218. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  219. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x03,
  220. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  221. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  222. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  223. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xf0, 0xf0, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00,
  224. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f,
  225. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  226. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfc,
  227. 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03,
  228. 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  229. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  230. 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0xfc, 0xfc, 0xf0,
  231. 0xf0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  232. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  233. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  234. 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  235. 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c,
  236. 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  237. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xff,
  238. 0xff, 0xfc, 0xfc, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff,
  239. 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc3, 0x00,
  240. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  241. 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xff,
  242. 0xff, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
  243. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  244. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x03, 0x03, 0x03,
  245. 0x03, 0x3f, 0x3f, 0x3c, 0x3c, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0xfc,
  246. 0xfc, 0xf0, 0xf0, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  247. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  248. 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x0f, 0x3f, 0x3f, 0x00, 0x00, 0x00,
  249. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  250. 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  251. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  252. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  253. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  254. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  255. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  256. 0x00, 0x3f, 0x3f, 0xff, 0xff, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xff, 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x00,
  257. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  258. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  259. 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xfc,
  260. 0xfc, 0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x0f,
  261. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  262. 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f,
  263. 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xff, 0xff, 0x0f, 0x0f, 0xff, 0xff, 0xf0, 0xf0, 0x00, 0x00, 0x00,
  264. 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00,
  265. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  266. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  267. 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  268. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  269. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0xc3, 0xc3, 0xff,
  270. 0xff, 0x3f, 0x3f, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0xc0,
  271. 0xc0, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  272. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  273. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  274. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
  275. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  276. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  277. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3f, 0x3f, 0xfc, 0xfc, 0xf0,
  278. 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
  279. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  280. 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  281. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  282. 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  283. 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  284. 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  285. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  286. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  287. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  288. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  289. 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  290. 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  291. 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  292. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  293. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  294. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  295. 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  296. 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
  297. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  298. 0xff, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  299. 0xff, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0c,
  300. 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  301. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
  302. 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03,
  303. 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00,
  304. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  305. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
  306. 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c,
  307. 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  308. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
  309. 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  310. 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03,
  311. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  312. 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x03,
  313. 0x03, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  314. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  315. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
  316. 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  317. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xcf, 0xcf, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff,
  318. 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
  319. 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  320. 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0c,
  321. 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  322. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  323. 0xc0, 0xcf, 0xcf, 0xcf, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  324. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f,
  325. 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  326. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xcf, 0xcf, 0xcf,
  327. 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  328. 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  329. 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff,
  330. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  331. 0xff, 0x3c, 0x3c, 0xff, 0xff, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  332. 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  333. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00,
  334. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  335. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00,
  336. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
  337. 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
  338. 0xff, 0x03, 0x03, 0xff, 0xff, 0x03, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00,
  339. 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  340. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  341. 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff,
  342. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f,
  343. 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  344. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
  345. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f,
  346. 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  347. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0,
  348. 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  349. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  350. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
  351. 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  352. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x03,
  353. 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  354. 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  355. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x03,
  356. 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
  357. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  358. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  359. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x3c, 0x3c, 0x30, 0x30, 0xf0, 0xf0, 0xc3, 0xc3, 0x03, 0x03, 0x00,
  360. 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00,
  361. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  362. 0xc0, 0xfc, 0xfc, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
  363. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
  364. 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  365. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0,
  366. 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
  367. 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00,
  368. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  369. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff,
  370. 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  371. 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  372. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
  373. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0, 0xf0, 0x00, 0x00, 0xff,
  374. 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x03,
  375. 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  376. 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  377. 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f,
  378. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  379. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
  380. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
  381. 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xff,
  382. 0xff, 0x3f, 0x3f, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
  383. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
  384. 0x00, 0x03, 0x03, 0xc3, 0xc3, 0xf0, 0xf0, 0x3c, 0x3c, 0x0f, 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f,
  385. 0x0f, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
  386. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  387. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff,
  388. 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x0f,
  389. 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  390. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
  391. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00,
  392. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  393. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
  394. 0x03, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  395. 0x00, 0xfc, 0xfc, 0xff, 0xff, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f,
  396. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  397. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x0f, 0x03, 0x03, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f,
  398. 0x0f, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  399. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  400. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  401. 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xf0, 0xf0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xff,
  402. 0xff, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0xff, 0xff, 0xfc, 0xfc, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03,
  403. 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  404. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  405. // 5x7 font (in 6x8 cell)
  406. const uint8_t ucSmallFont[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x5f, 0x06, 0x00, 0x07, 0x03, 0x00, 0x07,
  407. 0x03, 0x24, 0x7e, 0x24, 0x7e, 0x24, 0x24, 0x2b, 0x6a, 0x12, 0x00, 0x63, 0x13, 0x08, 0x64, 0x63, 0x36, 0x49,
  408. 0x56, 0x20, 0x50, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x3e, 0x41, 0x00, 0x00, 0x00, 0x41, 0x3e, 0x00, 0x00,
  409. 0x08, 0x3e, 0x1c, 0x3e, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0xe0, 0x60, 0x00, 0x00, 0x08, 0x08, 0x08,
  410. 0x08, 0x08, 0x00, 0x60, 0x60, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00,
  411. 0x42, 0x7f, 0x40, 0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x22, 0x49, 0x49, 0x49, 0x36, 0x18, 0x14, 0x12, 0x7f,
  412. 0x10, 0x2f, 0x49, 0x49, 0x49, 0x31, 0x3c, 0x4a, 0x49, 0x49, 0x30, 0x01, 0x71, 0x09, 0x05, 0x03, 0x36, 0x49,
  413. 0x49, 0x49, 0x36, 0x06, 0x49, 0x49, 0x29, 0x1e, 0x00, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0xec, 0x6c, 0x00, 0x00,
  414. 0x08, 0x14, 0x22, 0x41, 0x00, 0x24, 0x24, 0x24, 0x24, 0x24, 0x00, 0x41, 0x22, 0x14, 0x08, 0x02, 0x01, 0x59,
  415. 0x09, 0x06, 0x3e, 0x41, 0x5d, 0x55, 0x1e, 0x7e, 0x11, 0x11, 0x11, 0x7e, 0x7f, 0x49, 0x49, 0x49, 0x36, 0x3e,
  416. 0x41, 0x41, 0x41, 0x22, 0x7f, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x49, 0x49, 0x49, 0x41, 0x7f, 0x09, 0x09, 0x09,
  417. 0x01, 0x3e, 0x41, 0x49, 0x49, 0x7a, 0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, 0x41, 0x7f, 0x41, 0x00, 0x30, 0x40,
  418. 0x40, 0x40, 0x3f, 0x7f, 0x08, 0x14, 0x22, 0x41, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x7f, 0x02, 0x04, 0x02, 0x7f,
  419. 0x7f, 0x02, 0x04, 0x08, 0x7f, 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x7f, 0x09, 0x09, 0x09, 0x06, 0x3e, 0x41, 0x51,
  420. 0x21, 0x5e, 0x7f, 0x09, 0x09, 0x19, 0x66, 0x26, 0x49, 0x49, 0x49, 0x32, 0x01, 0x01, 0x7f, 0x01, 0x01, 0x3f,
  421. 0x40, 0x40, 0x40, 0x3f, 0x1f, 0x20, 0x40, 0x20, 0x1f, 0x3f, 0x40, 0x3c, 0x40, 0x3f, 0x63, 0x14, 0x08, 0x14,
  422. 0x63, 0x07, 0x08, 0x70, 0x08, 0x07, 0x71, 0x49, 0x45, 0x43, 0x00, 0x00, 0x7f, 0x41, 0x41, 0x00, 0x02, 0x04,
  423. 0x08, 0x10, 0x20, 0x00, 0x41, 0x41, 0x7f, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x80, 0x80, 0x80, 0x80, 0x80,
  424. 0x00, 0x03, 0x07, 0x00, 0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x7f, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44,
  425. 0x44, 0x28, 0x38, 0x44, 0x44, 0x44, 0x7f, 0x38, 0x54, 0x54, 0x54, 0x08, 0x08, 0x7e, 0x09, 0x09, 0x00, 0x18,
  426. 0xa4, 0xa4, 0xa4, 0x7c, 0x7f, 0x04, 0x04, 0x78, 0x00, 0x00, 0x00, 0x7d, 0x40, 0x00, 0x40, 0x80, 0x84, 0x7d,
  427. 0x00, 0x7f, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x00, 0x7c, 0x04, 0x18, 0x04, 0x78, 0x7c, 0x04,
  428. 0x04, 0x78, 0x00, 0x38, 0x44, 0x44, 0x44, 0x38, 0xfc, 0x44, 0x44, 0x44, 0x38, 0x38, 0x44, 0x44, 0x44, 0xfc,
  429. 0x44, 0x78, 0x44, 0x04, 0x08, 0x08, 0x54, 0x54, 0x54, 0x20, 0x04, 0x3e, 0x44, 0x24, 0x00, 0x3c, 0x40, 0x20,
  430. 0x7c, 0x00, 0x1c, 0x20, 0x40, 0x20, 0x1c, 0x3c, 0x60, 0x30, 0x60, 0x3c, 0x6c, 0x10, 0x10, 0x6c, 0x00, 0x9c,
  431. 0xa0, 0x60, 0x3c, 0x00, 0x64, 0x54, 0x54, 0x4c, 0x00, 0x08, 0x3e, 0x41, 0x41, 0x00, 0x00, 0x00, 0x77, 0x00,
  432. 0x00, 0x00, 0x41, 0x41, 0x3e, 0x08, 0x02, 0x01, 0x02, 0x01, 0x00, 0x3c, 0x26, 0x23, 0x26, 0x3c };
  433. // Initialization sequences
  434. const unsigned char oled128_initbuf[] = { 0x00, 0xae, 0xdc, 0x00, 0x81, 0x40, 0xa1, 0xc8, 0xa8, 0x7f, 0xd5, 0x50, 0xd9,
  435. 0x22, 0xdb, 0x35, 0xb0, 0xda, 0x12, 0xa4, 0xa6, 0xaf };
  436. const unsigned char oled64_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
  437. 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
  438. const unsigned char oled32_initbuf[] = { 0x00, 0xae, 0xd5, 0x80, 0xa8, 0x1f, 0xd3, 0x00, 0x40, 0x8d, 0x14, 0xa1, 0xc8,
  439. 0xda, 0x02, 0x81, 0x7f, 0xd9, 0xf1, 0xdb, 0x40, 0xa4, 0xa6, 0xaf };
  440. const unsigned char oled72_initbuf[] = { 0x00, 0xae, 0xa8, 0x3f, 0xd3, 0x00, 0x40, 0xa1, 0xc8, 0xda, 0x12, 0x81, 0xff,
  441. 0xad, 0x30, 0xd9, 0xf1, 0xa4, 0xa6, 0xd5, 0x80, 0x8d, 0x14, 0xaf, 0x20, 0x02 };
  442. // some globals
  443. static void __oledWriteCommand(SSOLED *pOLED, unsigned char c);
  444. void __InvertBytes(uint8_t *pData, uint8_t bLen);
  445. // wrapper/adapter functions to make the code work on Linux
  446. static uint8_t pgm_read_byte(uint8_t *ptr)
  447. {
  448. return *ptr;
  449. }
  450. static int16_t pgm_read_word(uint8_t *ptr)
  451. {
  452. return ptr[0] + (ptr[1] << 8);
  453. }
  454. static void _I2CWrite(SSOLED *pOLED, unsigned char *pData, int iLen)
  455. {
  456. I2CWrite(&pOLED->bbi2c, pOLED->oled_addr, pData, iLen);
  457. } /* _I2CWrite() */
  458. //
  459. // Initializes the OLED controller into "page mode"
  460. //
  461. int __oledInit(SSOLED *pOLED, int bInvert, int32_t iSpeed)
  462. {
  463. unsigned char uc[4];
  464. int rc = OLED_NOT_FOUND;
  465. int iAddr = pOLED->oled_addr;
  466. int bFlip = (int) pOLED->oled_flip;
  467. int iType = pOLED->oled_type;
  468. pOLED->ucScreen = NULL; // reset backbuffer; user must provide one later
  469. pOLED->oled_wrap = 0; // default - disable text wrap
  470. I2CInit(&pOLED->bbi2c, iSpeed); // on Linux, SDA = bus number, SCL = device address
  471. // find the device address if requested
  472. if (iAddr == -1 || iAddr == 0 || iAddr == 0xff) // find it
  473. {
  474. I2CTest(&pOLED->bbi2c, 0x3c);
  475. if (I2CTest(&pOLED->bbi2c, 0x3c))
  476. pOLED->oled_addr = 0x3c;
  477. else if (I2CTest(&pOLED->bbi2c, 0x3d))
  478. pOLED->oled_addr = 0x3d;
  479. else
  480. return rc; // no display found!
  481. }
  482. else
  483. {
  484. pOLED->oled_addr = iAddr;
  485. I2CTest(&pOLED->bbi2c, iAddr);
  486. if (!I2CTest(&pOLED->bbi2c, iAddr))
  487. return rc; // no display found
  488. }
  489. // Detect the display controller (SSD1306, SH1107 or SH1106)
  490. uint8_t u = 0;
  491. I2CReadRegister(&pOLED->bbi2c, pOLED->oled_addr, 0x00, &u, 1); // read the status register
  492. u &= 0x0f; // mask off power on/off bit
  493. if (u == 0x7 || u == 0xf) // SH1107
  494. {
  495. pOLED->oled_type = OLED_128x128;
  496. rc = OLED_SH1107_3C;
  497. bFlip = !bFlip; // SH1107 seems to have this reversed from the usual direction
  498. }
  499. else if (u == 0x8) // SH1106
  500. {
  501. rc = OLED_SH1106_3C;
  502. pOLED->oled_type = OLED_132x64; // needs to be treated a little differently
  503. }
  504. else if (u == 3 || u == 6) // 6=128x64 display, 3=smaller
  505. {
  506. rc = OLED_SSD1306_3C;
  507. }
  508. if (pOLED->oled_addr == 0x3d)
  509. rc++; // return the '3D' version of the type
  510. if (iType == OLED_128x32 || iType == OLED_96x16)
  511. _I2CWrite(pOLED, (unsigned char *) oled32_initbuf, sizeof(oled32_initbuf));
  512. else if (iType == OLED_128x128)
  513. _I2CWrite(pOLED, (unsigned char *) oled128_initbuf, sizeof(oled128_initbuf));
  514. else if (iType == OLED_72x40)
  515. _I2CWrite(pOLED, (unsigned char *) oled72_initbuf, sizeof(oled72_initbuf));
  516. else
  517. // 132x64, 128x64 and 64x32
  518. _I2CWrite(pOLED, (unsigned char *) oled64_initbuf, sizeof(oled64_initbuf));
  519. if (bInvert)
  520. {
  521. uc[0] = 0; // command
  522. uc[1] = 0xa7; // invert command
  523. _I2CWrite(pOLED, uc, 2);
  524. }
  525. if (bFlip) // rotate display 180
  526. {
  527. uc[0] = 0; // command
  528. uc[1] = 0xa0;
  529. _I2CWrite(pOLED, uc, 2);
  530. uc[1] = 0xc0;
  531. _I2CWrite(pOLED, uc, 2);
  532. }
  533. pOLED->oled_x = 128; // assume 128x64
  534. pOLED->oled_y = 64;
  535. if (iType == OLED_96x16)
  536. {
  537. pOLED->oled_x = 96;
  538. pOLED->oled_y = 16;
  539. }
  540. else if (iType == OLED_128x32)
  541. pOLED->oled_y = 32;
  542. else if (iType == OLED_128x128)
  543. pOLED->oled_y = 128;
  544. else if (iType == OLED_64x32)
  545. {
  546. pOLED->oled_x = 64;
  547. pOLED->oled_y = 32;
  548. }
  549. else if (iType == OLED_72x40)
  550. {
  551. pOLED->oled_x = 72;
  552. pOLED->oled_y = 40;
  553. }
  554. return rc;
  555. } /* oledInit() */
  556. //
  557. // Sends a command to turn on or off the OLED display
  558. //
  559. void __oledPower(SSOLED *pOLED, uint8_t bOn)
  560. {
  561. if (bOn)
  562. __oledWriteCommand(pOLED, 0xaf); // turn on OLED
  563. else
  564. __oledWriteCommand(pOLED, 0xae); // turn off OLED
  565. } /* oledPower() */
  566. // Send a single byte command to the OLED controller
  567. static void __oledWriteCommand(SSOLED *pOLED, unsigned char c)
  568. {
  569. unsigned char buf[2];
  570. buf[0] = 0x00; // command introducer
  571. buf[1] = c;
  572. _I2CWrite(pOLED, buf, 2);
  573. } /* oledWriteCommand() */
  574. static void __oledWriteCommand2(SSOLED *pOLED, unsigned char c, unsigned char d)
  575. {
  576. unsigned char buf[3];
  577. buf[0] = 0x00;
  578. buf[1] = c;
  579. buf[2] = d;
  580. _I2CWrite(pOLED, buf, 3);
  581. } /* oledWriteCommand2() */
  582. //
  583. // Sets the brightness (0=off, 255=brightest)
  584. //
  585. void __oledSetContrast(SSOLED *pOLED, unsigned char ucContrast)
  586. {
  587. __oledWriteCommand2(pOLED, 0x81, ucContrast);
  588. } /* oledSetContrast() */
  589. //
  590. // Scroll the internal buffer by 1 scanline (up/down)
  591. // width is in pixels, lines is group of 8 rows
  592. //
  593. int __oledScrollBuffer(SSOLED *pOLED, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp)
  594. {
  595. uint8_t b, *s;
  596. int col, row;
  597. if (iStartCol < 0 || iStartCol > 127 || iEndCol < 0 || iEndCol > 127 || iStartCol > iEndCol) // invalid
  598. return -1;
  599. if (iStartRow < 0 || iStartRow > 7 || iEndRow < 0 || iEndRow > 7 || iStartRow > iEndRow)
  600. return -1;
  601. if (bUp)
  602. {
  603. for (row = iStartRow; row <= iEndRow; row++)
  604. {
  605. s = &pOLED->ucScreen[(row * 128) + iStartCol];
  606. for (col = iStartCol; col <= iEndCol; col++)
  607. {
  608. b = *s;
  609. b >>= 1; // scroll pixels 'up'
  610. if (row < iEndRow)
  611. b |= (s[128] << 7); // capture pixel of row below, except for last row
  612. *s++ = b;
  613. } // for col
  614. } // for row
  615. } // up
  616. else // down
  617. {
  618. for (row = iEndRow; row >= iStartRow; row--)
  619. {
  620. s = &pOLED->ucScreen[(row * 128) + iStartCol];
  621. for (col = iStartCol; col <= iEndCol; col++)
  622. {
  623. b = *s;
  624. b <<= 1; // scroll down
  625. if (row > iStartRow)
  626. b |= (s[-128] >> 7); // capture pixel of row above
  627. *s++ = b;
  628. } // for col
  629. } // for row
  630. }
  631. return 0;
  632. } /* oledScrollBuffer() */
  633. //
  634. // Send commands to position the "cursor" (aka memory write address)
  635. // to the given row and column
  636. //
  637. static void __oledSetPosition(SSOLED *pOLED, int x, int y, int bRender)
  638. {
  639. unsigned char buf[4];
  640. pOLED->iScreenOffset = (y * 128) + x;
  641. if (!bRender)
  642. return; // don't send the commands to the OLED if we're not rendering the graphics now
  643. if (pOLED->oled_type == OLED_64x32) // visible display starts at column 32, row 4
  644. {
  645. x += 32; // display is centered in VRAM, so this is always true
  646. if (pOLED->oled_flip == 0) // non-flipped display starts from line 4
  647. y += 4;
  648. }
  649. else if (pOLED->oled_type == OLED_132x64) // SH1106 has 128 pixels centered in 132
  650. {
  651. x += 2;
  652. }
  653. else if (pOLED->oled_type == OLED_96x16) // visible display starts at line 2
  654. { // mapping is a bit strange on the 96x16 OLED
  655. if (pOLED->oled_flip)
  656. x += 32;
  657. else
  658. y += 2;
  659. }
  660. else if (pOLED->oled_type == OLED_72x40) // starts at x=28,y=3
  661. {
  662. x += 28;
  663. if (!pOLED->oled_flip)
  664. {
  665. y += 3;
  666. }
  667. }
  668. buf[0] = 0x00; // command introducer
  669. buf[1] = 0xb0 | y; // set page to Y
  670. buf[2] = x & 0xf; // lower column address
  671. buf[3] = 0x10 | (x >> 4); // upper column addr
  672. _I2CWrite(pOLED, buf, 4);
  673. } /* oledSetPosition() */
  674. //
  675. // Write a block of pixel data to the OLED
  676. // Length can be anything from 1 to 1024 (whole display)
  677. //
  678. static void __oledWriteDataBlock(SSOLED *pOLED, unsigned char *ucBuf, int iLen, int bRender)
  679. {
  680. unsigned char ucTemp[129];
  681. ucTemp[0] = 0x40; // data command
  682. // Copying the data has the benefit in SPI mode of not letting
  683. // the original data get overwritten by the SPI.transfer() function
  684. if (bRender)
  685. {
  686. memcpy(&ucTemp[1], ucBuf, iLen);
  687. _I2CWrite(pOLED, ucTemp, iLen + 1);
  688. }
  689. // Keep a copy in local buffer
  690. if (pOLED->ucScreen)
  691. {
  692. memcpy(&pOLED->ucScreen[pOLED->iScreenOffset], ucBuf, iLen);
  693. pOLED->iScreenOffset += iLen;
  694. pOLED->iScreenOffset &= 1023; // we use a fixed stride of 128 no matter what the display size
  695. }
  696. }
  697. //
  698. // Byte operands for compressing the data
  699. // The first 2 bits are the type, followed by the counts
  700. #define OP_MASK 0xc0
  701. #define OP_SKIPCOPY 0x00
  702. #define OP_COPYSKIP 0x40
  703. #define OP_REPEATSKIP 0x80
  704. #define OP_REPEAT 0xc0
  705. //
  706. // Write a block of flash memory to the display
  707. //
  708. void __oledWriteFlashBlock(SSOLED *pOLED, uint8_t *s, int iLen)
  709. {
  710. int j;
  711. int iWidthMask = pOLED->oled_x - 1;
  712. int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
  713. int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 wide
  714. uint8_t ucTemp[128];
  715. while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
  716. {
  717. j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
  718. memcpy(ucTemp, s, j);
  719. __oledWriteDataBlock(pOLED, ucTemp, j, 1);
  720. s += j;
  721. iLen -= j;
  722. pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
  723. __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
  724. } // while it needs some help
  725. memcpy(ucTemp, s, iLen);
  726. __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
  727. pOLED->iScreenOffset = (pOLED->iScreenOffset + iLen) & iSizeMask;
  728. } /* oledWriteFlashBlock() */
  729. //
  730. // Write a repeating byte to the display
  731. //
  732. void __oledRepeatByte(SSOLED *pOLED, uint8_t b, int iLen)
  733. {
  734. int j;
  735. int iWidthMask = pOLED->oled_x - 1;
  736. int iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // assume 128 or 64 pixels wide
  737. int iSizeMask = ((pOLED->oled_x * pOLED->oled_y) / 8) - 1;
  738. uint8_t ucTemp[128];
  739. memset(ucTemp, b, (iLen > 128) ? 128 : iLen);
  740. while (((pOLED->iScreenOffset & iWidthMask) + iLen) >= pOLED->oled_x) // if it will hit the page end
  741. {
  742. j = pOLED->oled_x - (pOLED->iScreenOffset & iWidthMask); // amount we can write in one shot
  743. __oledWriteDataBlock(pOLED, ucTemp, j, 1);
  744. iLen -= j;
  745. pOLED->iScreenOffset = (pOLED->iScreenOffset + j) & iSizeMask;
  746. __oledSetPosition(pOLED, pOLED->iScreenOffset & iWidthMask, (pOLED->iScreenOffset >> iWidthShift), 1);
  747. } // while it needs some help
  748. __oledWriteDataBlock(pOLED, ucTemp, iLen, 1);
  749. pOLED->iScreenOffset += iLen;
  750. } /* oledRepeatByte() */
  751. //
  752. // Play a frame of animation data
  753. // The animation data is assumed to be encoded for a full frame of the display
  754. // Given the pointer to the start of the compressed data,
  755. // it returns the pointer to the start of the next frame
  756. // Frame rate control is up to the calling program to manage
  757. // When it finishes the last frame, it will start again from the beginning
  758. //
  759. uint8_t * __oledPlayAnimFrame(SSOLED *pOLED, uint8_t *pAnimation, uint8_t *pCurrent, int iLen)
  760. {
  761. uint8_t *s;
  762. int i, j;
  763. unsigned char b, bCode;
  764. int iBufferSize = (pOLED->oled_x * pOLED->oled_y) / 8; // size in bytes of the display devce
  765. int iWidthMask, iWidthShift;
  766. iWidthMask = pOLED->oled_x - 1;
  767. iWidthShift = (pOLED->oled_x == 128) ? 7 : 6; // 128 or 64 pixels wide
  768. if (pCurrent == NULL || pCurrent > pAnimation + iLen)
  769. return NULL; // invalid starting point
  770. s = (uint8_t *) pCurrent; // start of animation data
  771. i = 0;
  772. __oledSetPosition(pOLED, 0, 0, 1);
  773. while (i < iBufferSize) // run one frame
  774. {
  775. bCode = pgm_read_byte(s++);
  776. switch (bCode & OP_MASK)
  777. // different compression types
  778. {
  779. case OP_SKIPCOPY: // skip/copy
  780. if (bCode == OP_SKIPCOPY) // big skip
  781. {
  782. b = pgm_read_byte(s++);
  783. i += b + 1;
  784. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  785. }
  786. else // skip/copy
  787. {
  788. if (bCode & 0x38)
  789. {
  790. i += ((bCode & 0x38) >> 3); // skip amount
  791. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  792. }
  793. if (bCode & 7)
  794. {
  795. __oledWriteFlashBlock(pOLED, s, bCode & 7);
  796. s += (bCode & 7);
  797. i += bCode & 7;
  798. }
  799. }
  800. break;
  801. case OP_COPYSKIP: // copy/skip
  802. if (bCode == OP_COPYSKIP) // big copy
  803. {
  804. b = pgm_read_byte(s++);
  805. j = b + 1;
  806. __oledWriteFlashBlock(pOLED, s, j);
  807. s += j;
  808. i += j;
  809. }
  810. else
  811. {
  812. j = ((bCode & 0x38) >> 3);
  813. if (j)
  814. {
  815. __oledWriteFlashBlock(pOLED, s, j);
  816. s += j;
  817. i += j;
  818. }
  819. if (bCode & 7)
  820. {
  821. i += (bCode & 7); // skip
  822. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  823. }
  824. }
  825. break;
  826. case OP_REPEATSKIP: // repeat/skip
  827. j = (bCode & 0x38) >> 3; // repeat count
  828. b = pgm_read_byte(s++);
  829. __oledRepeatByte(pOLED, b, j);
  830. i += j;
  831. if (bCode & 7)
  832. {
  833. i += (bCode & 7); // skip amount
  834. __oledSetPosition(pOLED, i & iWidthMask, (i >> iWidthShift), 1);
  835. }
  836. break;
  837. case OP_REPEAT:
  838. j = (bCode & 0x3f) + 1;
  839. b = pgm_read_byte(s++);
  840. __oledRepeatByte(pOLED, b, j);
  841. i += j;
  842. break;
  843. } // switch on code type
  844. } // while rendering a frame
  845. if (s >= pAnimation + iLen) // we've hit the end, restart from the beginning
  846. s = pAnimation;
  847. return s; // return pointer to start of next frame
  848. } /* oledPlayAnimFrame() */
  849. //
  850. // Draw a sprite of any size in any position
  851. // If it goes beyond the left/right or top/bottom edges
  852. // it's trimmed to show the valid parts
  853. // This function requires a back buffer to be defined
  854. // The priority color (0 or 1) determines which color is painted
  855. // when a 1 is encountered in the source image.
  856. //
  857. void __oledDrawSprite(SSOLED *pOLED, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
  858. {
  859. int tx, ty, dx, dy, iStartX;
  860. uint8_t *s, *d, uc, pix, ucSrcMask, ucDstMask;
  861. if (x + cx < 0 || y + cy < 0 || x >= pOLED->oled_x || y >= pOLED->oled_y || pOLED->ucScreen == NULL)
  862. return; // no backbuffer or out of bounds
  863. dy = y; // destination y
  864. if (y < 0) // skip the invisible parts
  865. {
  866. cy += y;
  867. y = -y;
  868. pSprite += (y * iPitch);
  869. dy = 0;
  870. }
  871. if (y + cy > pOLED->oled_y)
  872. cy = pOLED->oled_y - y;
  873. iStartX = 0;
  874. dx = x;
  875. if (x < 0)
  876. {
  877. cx += x;
  878. x = -x;
  879. iStartX = x;
  880. dx = 0;
  881. }
  882. if (x + cx > pOLED->oled_x)
  883. cx = pOLED->oled_x - x;
  884. for (ty = 0; ty < cy; ty++)
  885. {
  886. s = &pSprite[iStartX >> 3];
  887. d = &pOLED->ucScreen[(dy >> 3) * pOLED->oled_x + dx];
  888. ucSrcMask = 0x80 >> (iStartX & 7);
  889. pix = *s++;
  890. ucDstMask = 1 << (dy & 7);
  891. if (iPriority) // priority color is 1
  892. {
  893. for (tx = 0; tx < cx; tx++)
  894. {
  895. uc = d[0];
  896. if (pix & ucSrcMask) // set pixel in source, set it in dest
  897. d[0] = (uc | ucDstMask);
  898. d++; // next pixel column
  899. ucSrcMask >>= 1;
  900. if (ucSrcMask == 0) // read next byte
  901. {
  902. ucSrcMask = 0x80;
  903. pix = *s++;
  904. }
  905. } // for tx
  906. } // priorty color 1
  907. else
  908. {
  909. for (tx = 0; tx < cx; tx++)
  910. {
  911. uc = d[0];
  912. if (pix & ucSrcMask) // clr pixel in source, clr it in dest
  913. d[0] = (uc & ~ucDstMask);
  914. d++; // next pixel column
  915. ucSrcMask >>= 1;
  916. if (ucSrcMask == 0) // read next byte
  917. {
  918. ucSrcMask = 0x80;
  919. pix = *s++;
  920. }
  921. } // for tx
  922. } // priority color 0
  923. dy++;
  924. pSprite += iPitch;
  925. } // for ty
  926. } /* oledDrawSprite() */
  927. //
  928. // Draw a 16x16 tile in any of 4 rotated positions
  929. // Assumes input image is laid out like "normal" graphics with
  930. // the MSB on the left and 2 bytes per line
  931. // On AVR, the source image is assumed to be in FLASH memory
  932. // The function can draw the tile on byte boundaries, so the x value
  933. // can be from 0 to 112 and y can be from 0 to 6
  934. //
  935. void __oledDrawTile(SSOLED *pOLED, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender)
  936. {
  937. uint8_t ucTemp[32]; // prepare LCD data here
  938. uint8_t i, j, k, iOffset, ucMask, uc, ucPixels;
  939. uint8_t bFlipX = 0, bFlipY = 0;
  940. if (x < 0 || y < 0 || y > 6 || x > 112)
  941. return; // out of bounds
  942. if (pTile == NULL)
  943. return; // bad pointer; really? :(
  944. if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPX)
  945. bFlipX = 1;
  946. if (iRotation == ANGLE_180 || iRotation == ANGLE_270 || iRotation == ANGLE_FLIPY)
  947. bFlipY = 1;
  948. memset(ucTemp, 0, sizeof(ucTemp)); // we only set white pixels, so start from black
  949. if (iRotation == ANGLE_0 || iRotation == ANGLE_180 || iRotation == ANGLE_FLIPX || iRotation == ANGLE_FLIPY)
  950. {
  951. for (j = 0; j < 16; j++) // y
  952. {
  953. for (i = 0; i < 16; i += 8) // x
  954. {
  955. ucPixels = pgm_read_byte((uint8_t*) pTile++);
  956. ucMask = 0x80; // MSB is the first source pixel
  957. for (k = 0; k < 8; k++)
  958. {
  959. if (ucPixels & ucMask) // translate the pixel
  960. {
  961. if (bFlipY)
  962. uc = 0x80 >> (j & 7);
  963. else
  964. uc = 1 << (j & 7);
  965. iOffset = i + k;
  966. if (bFlipX)
  967. iOffset = 15 - iOffset;
  968. iOffset += (j & 8) << 1; // top/bottom half of output
  969. if (bFlipY)
  970. iOffset ^= 16;
  971. ucTemp[iOffset] |= uc;
  972. }
  973. ucMask >>= 1;
  974. } // for k
  975. } // for i
  976. } // for j
  977. }
  978. else // rotated 90/270
  979. {
  980. for (j = 0; j < 16; j++) // y
  981. {
  982. for (i = 0; i < 16; i += 8) // x
  983. {
  984. ucPixels = pgm_read_byte((uint8_t*) pTile++);
  985. ucMask = 0x80; // MSB is the first source pixel
  986. for (k = 0; k < 8; k++)
  987. {
  988. if (ucPixels & ucMask) // translate the pixel
  989. {
  990. if (bFlipY)
  991. uc = 0x80 >> k;
  992. else
  993. uc = 1 << k;
  994. iOffset = 15 - j;
  995. if (bFlipX)
  996. iOffset = 15 - iOffset;
  997. iOffset += i << 1; // top/bottom half of output
  998. if (bFlipY)
  999. iOffset ^= 16;
  1000. ucTemp[iOffset] |= uc;
  1001. }
  1002. ucMask >>= 1;
  1003. } // for k
  1004. } // for i
  1005. } // for j
  1006. }
  1007. if (bInvert)
  1008. __InvertBytes(ucTemp, 32);
  1009. // Send the data to the display
  1010. __oledSetPosition(pOLED, x, y, bRender);
  1011. __oledWriteDataBlock(pOLED, ucTemp, 16, bRender); // top half
  1012. __oledSetPosition(pOLED, x, y + 1, bRender);
  1013. __oledWriteDataBlock(pOLED, &ucTemp[16], 16, bRender); // bottom half
  1014. } /* oledDrawTile() */
  1015. // Set (or clear) an individual pixel
  1016. // The local copy of the frame buffer is used to avoid
  1017. // reading data from the display controller
  1018. int __oledSetPixel(SSOLED *pOLED, int x, int y, unsigned char ucColor, int bRender)
  1019. {
  1020. int i;
  1021. unsigned char uc, ucOld;
  1022. i = ((y >> 3) * 128) + x;
  1023. if (i < 0 || i > 1023) // off the screen
  1024. return -1;
  1025. __oledSetPosition(pOLED, x, y >> 3, bRender);
  1026. if (pOLED->ucScreen)
  1027. uc = ucOld = pOLED->ucScreen[i];
  1028. else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // SH1106/SH1107 can read data
  1029. {
  1030. uint8_t ucTemp[3];
  1031. ucTemp[0] = 0x80; // one command
  1032. ucTemp[1] = 0xE0; // read_modify_write
  1033. ucTemp[2] = 0xC0; // one data
  1034. _I2CWrite(pOLED, ucTemp, 3);
  1035. // read a dummy byte followed by the data byte we want
  1036. I2CRead(&pOLED->bbi2c, pOLED->oled_addr, ucTemp, 2);
  1037. uc = ucOld = ucTemp[1]; // first byte is garbage
  1038. }
  1039. else
  1040. uc = ucOld = 0;
  1041. uc &= ~(0x1 << (y & 7));
  1042. if (ucColor)
  1043. {
  1044. uc |= (0x1 << (y & 7));
  1045. }
  1046. if (uc != ucOld) // pixel changed
  1047. {
  1048. // oledSetPosition(x, y>>3);
  1049. if (pOLED->ucScreen)
  1050. {
  1051. __oledWriteDataBlock(pOLED, &uc, 1, bRender);
  1052. pOLED->ucScreen[i] = uc;
  1053. }
  1054. else if (pOLED->oled_type == OLED_132x64 || pOLED->oled_type == OLED_128x128) // end the read_modify_write operation
  1055. {
  1056. uint8_t ucTemp[4];
  1057. ucTemp[0] = 0xc0; // one data
  1058. ucTemp[1] = uc; // actual data
  1059. ucTemp[2] = 0x80; // one command
  1060. ucTemp[3] = 0xEE; // end read_modify_write operation
  1061. _I2CWrite(pOLED, ucTemp, 4);
  1062. }
  1063. }
  1064. return 0;
  1065. } /* oledSetPixel() */
  1066. //
  1067. // Invert font data
  1068. //
  1069. void __InvertBytes(uint8_t *pData, uint8_t bLen)
  1070. {
  1071. uint8_t i;
  1072. for (i = 0; i < bLen; i++)
  1073. {
  1074. *pData = ~(*pData);
  1075. pData++;
  1076. }
  1077. } /* InvertBytes() */
  1078. //
  1079. // Load a 128x64 1-bpp Windows bitmap
  1080. // Pass the pointer to the beginning of the BMP file
  1081. // First pass version assumes a full screen bitmap
  1082. //
  1083. int __oledLoadBMP(SSOLED *pOLED, uint8_t *pBMP, int bInvert, int bRender)
  1084. {
  1085. int16_t i16;
  1086. int iOffBits, q, y, j; // offset to bitmap data
  1087. int iPitch;
  1088. uint8_t x, z, b, *s;
  1089. uint8_t dst_mask;
  1090. uint8_t ucTemp[16]; // process 16 bytes at a time
  1091. uint8_t bFlipped = false;
  1092. i16 = pgm_read_word(pBMP);
  1093. if (i16 != 0x4d42) // must start with 'BM'
  1094. return -1; // not a BMP file
  1095. i16 = pgm_read_word(pBMP + 18);
  1096. if (i16 != 128) // must be 128 pixels wide
  1097. return -1;
  1098. i16 = pgm_read_word(pBMP + 22);
  1099. if (i16 != 64 && i16 != -64) // must be 64 pixels tall
  1100. return -1;
  1101. if (i16 == 64) // BMP is flipped vertically (typical)
  1102. bFlipped = true;
  1103. i16 = pgm_read_word(pBMP + 28);
  1104. if (i16 != 1) // must be 1 bit per pixel
  1105. return -1;
  1106. iOffBits = pgm_read_word(pBMP + 10);
  1107. iPitch = 16;
  1108. if (bFlipped)
  1109. {
  1110. iPitch = -16;
  1111. iOffBits += (63 * 16); // start from bottom
  1112. }
  1113. // rotate the data and send it to the display
  1114. for (y = 0; y < 8; y++) // 8 lines of 8 pixels
  1115. {
  1116. __oledSetPosition(pOLED, 0, y, bRender);
  1117. for (j = 0; j < 8; j++) // do 8 sections of 16 columns
  1118. {
  1119. s = &pBMP[iOffBits + (j * 2) + (y * iPitch * 8)]; // source line
  1120. memset(ucTemp, 0, 16); // start with all black
  1121. for (x = 0; x < 16; x += 8) // do each block of 16x8 pixels
  1122. {
  1123. dst_mask = 1;
  1124. for (q = 0; q < 8; q++) // gather 8 rows
  1125. {
  1126. b = pgm_read_byte(s + (q * iPitch));
  1127. for (z = 0; z < 8; z++) // gather up the 8 bits of this column
  1128. {
  1129. if (b & 0x80)
  1130. ucTemp[x + z] |= dst_mask;
  1131. b <<= 1;
  1132. } // for z
  1133. dst_mask <<= 1;
  1134. } // for q
  1135. s++; // next source byte
  1136. } // for x
  1137. if (bInvert)
  1138. __InvertBytes(ucTemp, 16);
  1139. __oledWriteDataBlock(pOLED, ucTemp, 16, bRender);
  1140. } // for j
  1141. } // for y
  1142. return 0;
  1143. } /* oledLoadBMP() */
  1144. //
  1145. // Set the current cursor position
  1146. // The column represents the pixel column (0-127)
  1147. // The row represents the text row (0-7)
  1148. //
  1149. void __oledSetCursor(SSOLED *pOLED, int x, int y)
  1150. {
  1151. pOLED->iCursorX = x;
  1152. pOLED->iCursorY = y;
  1153. } /* oledSetCursor() */
  1154. //
  1155. // Turn text wrap on or off for the oldWriteString() function
  1156. //
  1157. void __oledSetTextWrap(SSOLED *pOLED, int bWrap)
  1158. {
  1159. pOLED->oled_wrap = bWrap;
  1160. } /* oledSetTextWrap() */
  1161. //
  1162. // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
  1163. // At the given col+row
  1164. //
  1165. int __oledWriteString(SSOLED *pOLED, int iScroll, int x, int y, char *szMsg, int iSize, int bInvert, int bRender)
  1166. {
  1167. int i, iFontOff, iLen, iFontSkip;
  1168. unsigned char c, *s, ucTemp[40];
  1169. if (x == -1 || y == -1) // use the cursor position
  1170. {
  1171. x = pOLED->iCursorX;
  1172. y = pOLED->iCursorY;
  1173. }
  1174. else
  1175. {
  1176. pOLED->iCursorX = x;
  1177. pOLED->iCursorY = y; // set the new cursor position
  1178. }
  1179. if (pOLED->iCursorX >= pOLED->oled_x || pOLED->iCursorY >= pOLED->oled_y / 8)
  1180. return -1; // can't draw off the display
  1181. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1182. if (iSize == FONT_8x8) // 8x8 font
  1183. {
  1184. i = 0;
  1185. iFontSkip = iScroll & 7; // number of columns to initially skip
  1186. while (pOLED->iCursorX < pOLED->oled_x && szMsg[i] != 0 && pOLED->iCursorY < pOLED->oled_y / 8)
  1187. {
  1188. if (iScroll < 8) // only display visible characters
  1189. {
  1190. c = (unsigned char) szMsg[i];
  1191. iFontOff = (int) (c - 32) * 7;
  1192. // we can't directly use the pointer to FLASH memory, so copy to a local buffer
  1193. ucTemp[0] = 0;
  1194. memcpy(&ucTemp[1], &ucFont[iFontOff], 7);
  1195. if (bInvert)
  1196. __InvertBytes(ucTemp, 8);
  1197. // oledCachedWrite(ucTemp, 8);
  1198. iLen = 8 - iFontSkip;
  1199. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1200. iLen = pOLED->oled_x - pOLED->iCursorX;
  1201. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1202. pOLED->iCursorX += iLen;
  1203. if (pOLED->iCursorX >= pOLED->oled_x - 7 && pOLED->oled_wrap) // word wrap enabled?
  1204. {
  1205. pOLED->iCursorX = 0; // start at the beginning of the next line
  1206. pOLED->iCursorY++;
  1207. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1208. }
  1209. iFontSkip = 0;
  1210. }
  1211. iScroll -= 8;
  1212. i++;
  1213. } // while
  1214. // oledCachedFlush(); // write any remaining data
  1215. return 0;
  1216. } // 8x8
  1217. #ifndef __AVR__
  1218. else if (iSize == FONT_16x32) // 16x32 font
  1219. {
  1220. i = 0;
  1221. iFontSkip = iScroll & 15; // number of columns to initially skip
  1222. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 3 && szMsg[i] != 0)
  1223. {
  1224. if (iScroll < 16) // if characters are visible
  1225. {
  1226. s = (unsigned char *) &ucBigFont[(unsigned char) (szMsg[i] - 32) * 64];
  1227. iLen = 16 - iFontSkip;
  1228. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1229. iLen = pOLED->oled_x - pOLED->iCursorX;
  1230. // we can't directly use the pointer to FLASH memory, so copy to a local buffer
  1231. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1232. memcpy(ucTemp, s, 16);
  1233. if (bInvert)
  1234. __InvertBytes(ucTemp, 16);
  1235. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1236. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
  1237. memcpy(ucTemp, s + 16, 16);
  1238. if (bInvert)
  1239. __InvertBytes(ucTemp, 16);
  1240. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1241. if (pOLED->iCursorY <= 5)
  1242. {
  1243. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 2, bRender);
  1244. memcpy(ucTemp, s + 32, 16);
  1245. if (bInvert)
  1246. __InvertBytes(ucTemp, 16);
  1247. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1248. }
  1249. if (pOLED->iCursorY <= 4)
  1250. {
  1251. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 3, bRender);
  1252. memcpy(ucTemp, s + 48, 16);
  1253. if (bInvert)
  1254. __InvertBytes(ucTemp, 16);
  1255. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1256. }
  1257. pOLED->iCursorX += iLen;
  1258. if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
  1259. {
  1260. pOLED->iCursorX = 0; // start at the beginning of the next line
  1261. pOLED->iCursorY += 4;
  1262. }
  1263. iFontSkip = 0;
  1264. } // if character visible from scrolling
  1265. iScroll -= 16;
  1266. i++;
  1267. } // while
  1268. return 0;
  1269. } // 16x32
  1270. #endif // !__AVR__
  1271. else if (iSize == FONT_12x16) // 6x8 stretched to 12x16
  1272. {
  1273. i = 0;
  1274. iFontSkip = iScroll % 12; // number of columns to initially skip
  1275. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
  1276. {
  1277. // stretch the 'normal' font instead of using the big font
  1278. if (iScroll < 12) // if characters are visible
  1279. {
  1280. int tx, ty;
  1281. c = szMsg[i] - 32;
  1282. unsigned char uc1, uc2, ucMask, *pDest;
  1283. s = (unsigned char *) &ucSmallFont[(int) c * 5];
  1284. ucTemp[0] = 0; // first column is blank
  1285. memcpy(&ucTemp[1], s, 6);
  1286. if (bInvert)
  1287. __InvertBytes(ucTemp, 6);
  1288. // Stretch the font to double width + double height
  1289. memset(&ucTemp[6], 0, 24); // write 24 new bytes
  1290. for (tx = 0; tx < 6; tx++)
  1291. {
  1292. ucMask = 3;
  1293. pDest = &ucTemp[6 + tx * 2];
  1294. uc1 = uc2 = 0;
  1295. c = ucTemp[tx];
  1296. for (ty = 0; ty < 4; ty++)
  1297. {
  1298. if (c & (1 << ty)) // a bit is set
  1299. uc1 |= ucMask;
  1300. if (c & (1 << (ty + 4)))
  1301. uc2 |= ucMask;
  1302. ucMask <<= 2;
  1303. }
  1304. pDest[0] = uc1;
  1305. pDest[1] = uc1; // double width
  1306. pDest[12] = uc2;
  1307. pDest[13] = uc2;
  1308. }
  1309. // smooth the diagonal lines
  1310. for (tx = 0; tx < 5; tx++)
  1311. {
  1312. uint8_t c0, c1, ucMask2;
  1313. c0 = ucTemp[tx];
  1314. c1 = ucTemp[tx + 1];
  1315. pDest = &ucTemp[6 + tx * 2];
  1316. ucMask = 1;
  1317. ucMask2 = 2;
  1318. for (ty = 0; ty < 7; ty++)
  1319. {
  1320. if (((c0 & ucMask) && !(c1 & ucMask) && !(c0 & ucMask2) && (c1 & ucMask2))
  1321. || (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2)))
  1322. {
  1323. if (ty < 3) // top half
  1324. {
  1325. pDest[1] |= (1 << ((ty * 2) + 1));
  1326. pDest[2] |= (1 << ((ty * 2) + 1));
  1327. pDest[1] |= (1 << ((ty + 1) * 2));
  1328. pDest[2] |= (1 << ((ty + 1) * 2));
  1329. }
  1330. else if (ty == 3) // on the border
  1331. {
  1332. pDest[1] |= 0x80;
  1333. pDest[2] |= 0x80;
  1334. pDest[13] |= 1;
  1335. pDest[14] |= 1;
  1336. }
  1337. else // bottom half
  1338. {
  1339. pDest[13] |= (1 << (2 * (ty - 4) + 1));
  1340. pDest[14] |= (1 << (2 * (ty - 4) + 1));
  1341. pDest[13] |= (1 << ((ty - 3) * 2));
  1342. pDest[14] |= (1 << ((ty - 3) * 2));
  1343. }
  1344. }
  1345. else if (!(c0 & ucMask) && (c1 & ucMask) && (c0 & ucMask2) && !(c1 & ucMask2))
  1346. {
  1347. if (ty < 4) // top half
  1348. {
  1349. pDest[1] |= (1 << ((ty * 2) + 1));
  1350. pDest[2] |= (1 << ((ty + 1) * 2));
  1351. }
  1352. else
  1353. {
  1354. pDest[13] |= (1 << (2 * (ty - 4) + 1));
  1355. pDest[14] |= (1 << ((ty - 3) * 2));
  1356. }
  1357. }
  1358. ucMask <<= 1;
  1359. ucMask2 <<= 1;
  1360. }
  1361. }
  1362. iLen = 12 - iFontSkip;
  1363. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1364. iLen = pOLED->oled_x - pOLED->iCursorX;
  1365. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1366. __oledWriteDataBlock(pOLED, &ucTemp[6 + iFontSkip], iLen, bRender);
  1367. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
  1368. __oledWriteDataBlock(pOLED, &ucTemp[18 + iFontSkip], iLen, bRender);
  1369. pOLED->iCursorX += iLen;
  1370. if (pOLED->iCursorX >= pOLED->oled_x - 11 && pOLED->oled_wrap) // word wrap enabled?
  1371. {
  1372. pOLED->iCursorX = 0; // start at the beginning of the next line
  1373. pOLED->iCursorY += 2;
  1374. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1375. }
  1376. iFontSkip = 0;
  1377. } // if characters are visible
  1378. iScroll -= 12;
  1379. i++;
  1380. } // while
  1381. return 0;
  1382. } // 12x16
  1383. else if (iSize == FONT_16x16) // 8x8 stretched to 16x16
  1384. {
  1385. i = 0;
  1386. iFontSkip = iScroll & 15; // number of columns to initially skip
  1387. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) - 1 && szMsg[i] != 0)
  1388. {
  1389. // stretch the 'normal' font instead of using the big font
  1390. if (iScroll < 16) // if characters are visible
  1391. {
  1392. int tx, ty;
  1393. c = szMsg[i] - 32;
  1394. unsigned char uc1, uc2, ucMask, *pDest;
  1395. s = (unsigned char *) &ucFont[(int) c * 7];
  1396. ucTemp[0] = 0;
  1397. memcpy(&ucTemp[1], s, 7);
  1398. if (bInvert)
  1399. __InvertBytes(ucTemp, 8);
  1400. // Stretch the font to double width + double height
  1401. memset(&ucTemp[8], 0, 32); // write 32 new bytes
  1402. for (tx = 0; tx < 8; tx++)
  1403. {
  1404. ucMask = 3;
  1405. pDest = &ucTemp[8 + tx * 2];
  1406. uc1 = uc2 = 0;
  1407. c = ucTemp[tx];
  1408. for (ty = 0; ty < 4; ty++)
  1409. {
  1410. if (c & (1 << ty)) // a bit is set
  1411. uc1 |= ucMask;
  1412. if (c & (1 << (ty + 4)))
  1413. uc2 |= ucMask;
  1414. ucMask <<= 2;
  1415. }
  1416. pDest[0] = uc1;
  1417. pDest[1] = uc1; // double width
  1418. pDest[16] = uc2;
  1419. pDest[17] = uc2;
  1420. }
  1421. iLen = 16 - iFontSkip;
  1422. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1423. iLen = pOLED->oled_x - pOLED->iCursorX;
  1424. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1425. __oledWriteDataBlock(pOLED, &ucTemp[8 + iFontSkip], iLen, bRender);
  1426. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY + 1, bRender);
  1427. __oledWriteDataBlock(pOLED, &ucTemp[24 + iFontSkip], iLen, bRender);
  1428. pOLED->iCursorX += iLen;
  1429. if (pOLED->iCursorX >= pOLED->oled_x - 15 && pOLED->oled_wrap) // word wrap enabled?
  1430. {
  1431. pOLED->iCursorX = 0; // start at the beginning of the next line
  1432. pOLED->iCursorY += 2;
  1433. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1434. }
  1435. iFontSkip = 0;
  1436. } // if characters are visible
  1437. iScroll -= 16;
  1438. i++;
  1439. } // while
  1440. return 0;
  1441. } // 16x16
  1442. else if (iSize == FONT_6x8) // 6x8 font
  1443. {
  1444. i = 0;
  1445. iFontSkip = iScroll % 6;
  1446. while (pOLED->iCursorX < pOLED->oled_x && pOLED->iCursorY < (pOLED->oled_y / 8) && szMsg[i] != 0)
  1447. {
  1448. if (iScroll < 6) // if characters are visible
  1449. {
  1450. c = szMsg[i] - 32;
  1451. // we can't directly use the pointer to FLASH memory, so copy to a local buffer
  1452. ucTemp[0] = 0;
  1453. memcpy(&ucTemp[1], &ucSmallFont[(int) c * 5], 5);
  1454. if (bInvert)
  1455. __InvertBytes(ucTemp, 6);
  1456. iLen = 6 - iFontSkip;
  1457. if (pOLED->iCursorX + iLen > pOLED->oled_x) // clip right edge
  1458. iLen = pOLED->oled_x - pOLED->iCursorX;
  1459. __oledWriteDataBlock(pOLED, &ucTemp[iFontSkip], iLen, bRender); // write character pattern
  1460. // oledCachedWrite(ucTemp, 6);
  1461. pOLED->iCursorX += iLen;
  1462. iFontSkip = 0;
  1463. if (pOLED->iCursorX >= pOLED->oled_x - 5 && pOLED->oled_wrap) // word wrap enabled?
  1464. {
  1465. pOLED->iCursorX = 0; // start at the beginning of the next line
  1466. pOLED->iCursorY++;
  1467. __oledSetPosition(pOLED, pOLED->iCursorX, pOLED->iCursorY, bRender);
  1468. }
  1469. } // if characters are visible
  1470. iScroll -= 6;
  1471. i++;
  1472. }
  1473. // oledCachedFlush(); // write any remaining data
  1474. return 0;
  1475. } // 6x8
  1476. return -1; // invalid size
  1477. } /* oledWriteString() */
  1478. //
  1479. // Render a sprite/rectangle of pixels from a provided buffer to the display.
  1480. // The row values refer to byte rows, not pixel rows due to the memory
  1481. // layout of OLEDs.
  1482. // returns 0 for success, -1 for invalid parameter
  1483. //
  1484. int __oledDrawGFX(SSOLED *pOLED, uint8_t *pBuffer, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth,
  1485. int iHeight, int iSrcPitch)
  1486. {
  1487. int y;
  1488. if (iSrcCol < 0 || iSrcCol > 127 || iSrcRow < 0 || iSrcRow > 7 || iDestCol < 0 || iDestCol >= pOLED->oled_x
  1489. || iDestRow < 0 || iDestRow >= (pOLED->oled_y >> 3) || iSrcPitch <= 0)
  1490. return -1; // invalid
  1491. for (y = iSrcRow; y < iSrcRow + iHeight; y++)
  1492. {
  1493. uint8_t *s = &pBuffer[(y * iSrcPitch) + iSrcCol];
  1494. __oledSetPosition(pOLED, iDestCol, iDestRow, 1);
  1495. __oledWriteDataBlock(pOLED, s, iWidth, 1);
  1496. pBuffer += iSrcPitch;
  1497. iDestRow++;
  1498. } // for y
  1499. return 0;
  1500. } /* oledDrawGFX() */
  1501. //
  1502. // Dump a screen's worth of data directly to the display
  1503. // Try to speed it up by comparing the new bytes with the existing buffer
  1504. //
  1505. void __oledDumpBuffer(SSOLED *pOLED, uint8_t *pBuffer)
  1506. {
  1507. int x, y;
  1508. int iLines, iCols;
  1509. uint8_t bNeedPos;
  1510. uint8_t *pSrc = pOLED->ucScreen;
  1511. if (pBuffer == NULL) // dump the internal buffer if none is given
  1512. pBuffer = pOLED->ucScreen;
  1513. if (pBuffer == NULL)
  1514. return; // no backbuffer and no provided buffer
  1515. iLines = pOLED->oled_y >> 3;
  1516. iCols = pOLED->oled_x >> 4;
  1517. for (y = 0; y < iLines; y++)
  1518. {
  1519. bNeedPos = 1; // start of a new line means we need to set the position too
  1520. 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
  1521. {
  1522. if (pOLED->ucScreen == NULL || pBuffer == pSrc || memcmp(pSrc, pBuffer, 16) != 0) // doesn't match, need to send it
  1523. {
  1524. if (bNeedPos) // need to reposition output cursor?
  1525. {
  1526. bNeedPos = 0;
  1527. __oledSetPosition(pOLED, x * 16, y, 1);
  1528. }
  1529. __oledWriteDataBlock(pOLED, pBuffer, 16, 1);
  1530. }
  1531. else
  1532. {
  1533. bNeedPos = 1; // we're skipping a block, so next time will need to set the new position
  1534. }
  1535. pSrc += 16;
  1536. pBuffer += 16;
  1537. } // for x
  1538. pSrc += (128 - pOLED->oled_x); // for narrow displays, skip to the next line
  1539. pBuffer += (128 - pOLED->oled_x);
  1540. } // for y
  1541. } /* oledDumpBuffer() */
  1542. //
  1543. // Fill the frame buffer with a byte pattern
  1544. // e.g. all off (0x00) or all on (0xff)
  1545. //
  1546. void __oledFill(SSOLED *pOLED, unsigned char ucData, int bRender)
  1547. {
  1548. uint8_t x, y;
  1549. uint8_t iLines, iCols;
  1550. unsigned char temp[16];
  1551. iLines = pOLED->oled_y >> 3;
  1552. iCols = pOLED->oled_x >> 4;
  1553. memset(temp, ucData, 16);
  1554. pOLED->iCursorX = pOLED->iCursorY = 0;
  1555. for (y = 0; y < iLines; y++)
  1556. {
  1557. __oledSetPosition(pOLED, 0, y, bRender); // set to (0,Y)
  1558. 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
  1559. {
  1560. __oledWriteDataBlock(pOLED, temp, 16, bRender);
  1561. } // for x
  1562. // 72 isn't evenly divisible by 16, so fix it
  1563. if (pOLED->oled_type == OLED_72x40)
  1564. __oledWriteDataBlock(pOLED, temp, 8, bRender);
  1565. } // for y
  1566. if (pOLED->ucScreen)
  1567. memset(pOLED->ucScreen, ucData, (pOLED->oled_x * pOLED->oled_y) / 8);
  1568. } /* oledFill() */
  1569. //
  1570. // Provide or revoke a back buffer for your OLED graphics
  1571. // This allows you to manage the RAM used by ss_oled on tiny
  1572. // embedded platforms like the ATmega series
  1573. // Pass NULL to revoke the buffer. Make sure you provide a buffer
  1574. // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
  1575. //
  1576. void __oledSetBackBuffer(SSOLED *pOLED, uint8_t *pBuffer)
  1577. {
  1578. pOLED->ucScreen = pBuffer;
  1579. } /* oledSetBackBuffer() */
  1580. void __oledDrawLine(SSOLED *pOLED, int x1, int y1, int x2, int y2, int bRender)
  1581. {
  1582. int temp;
  1583. int dx = x2 - x1;
  1584. int dy = y2 - y1;
  1585. int error;
  1586. uint8_t *p, *pStart, mask, bOld, bNew;
  1587. int xinc, yinc;
  1588. int y, x;
  1589. if (x1 < 0 || x2 < 0 || y1 < 0 || y2 < 0 || x1 >= pOLED->oled_x || x2 >= pOLED->oled_x || y1 >= pOLED->oled_y
  1590. || y2 >= pOLED->oled_y)
  1591. return;
  1592. if (abs(dx) > abs(dy))
  1593. {
  1594. // X major case
  1595. if (x2 < x1)
  1596. {
  1597. dx = -dx;
  1598. temp = x1;
  1599. x1 = x2;
  1600. x2 = temp;
  1601. temp = y1;
  1602. y1 = y2;
  1603. y2 = temp;
  1604. }
  1605. y = y1;
  1606. dy = (y2 - y1);
  1607. error = dx >> 1;
  1608. yinc = 1;
  1609. if (dy < 0)
  1610. {
  1611. dy = -dy;
  1612. yinc = -1;
  1613. }
  1614. p = pStart = &pOLED->ucScreen[x1 + ((y >> 3) << 7)]; // point to current spot in back buffer
  1615. mask = 1 << (y & 7); // current bit offset
  1616. for (x = x1; x1 <= x2; x1++)
  1617. {
  1618. *p++ |= mask; // set pixel and increment x pointer
  1619. error -= dy;
  1620. if (error < 0)
  1621. {
  1622. error += dx;
  1623. if (yinc > 0)
  1624. mask <<= 1;
  1625. else
  1626. mask >>= 1;
  1627. if (mask == 0) // we've moved outside the current row, write the data we changed
  1628. {
  1629. __oledSetPosition(pOLED, x, y >> 3, bRender);
  1630. __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender); // write the row we changed
  1631. x = x1 + 1; // we've already written the byte at x1
  1632. y1 = y + yinc;
  1633. p += (yinc > 0) ? 128 : -128;
  1634. pStart = p;
  1635. mask = 1 << (y1 & 7);
  1636. }
  1637. y += yinc;
  1638. }
  1639. } // for x1
  1640. if (p != pStart) // some data needs to be written
  1641. {
  1642. __oledSetPosition(pOLED, x, y >> 3, bRender);
  1643. __oledWriteDataBlock(pOLED, pStart, (int) (p - pStart), bRender);
  1644. }
  1645. }
  1646. else
  1647. {
  1648. // Y major case
  1649. if (y1 > y2)
  1650. {
  1651. dy = -dy;
  1652. temp = x1;
  1653. x1 = x2;
  1654. x2 = temp;
  1655. temp = y1;
  1656. y1 = y2;
  1657. y2 = temp;
  1658. }
  1659. p = &pOLED->ucScreen[x1 + ((y1 >> 3) * 128)]; // point to current spot in back buffer
  1660. bOld = bNew = p[0]; // current data at that address
  1661. mask = 1 << (y1 & 7); // current bit offset
  1662. dx = (x2 - x1);
  1663. error = dy >> 1;
  1664. xinc = 1;
  1665. if (dx < 0)
  1666. {
  1667. dx = -dx;
  1668. xinc = -1;
  1669. }
  1670. for (x = x1; y1 <= y2; y1++)
  1671. {
  1672. bNew |= mask; // set the pixel
  1673. error -= dx;
  1674. mask <<= 1; // y1++
  1675. if (mask == 0) // we're done with this byte, write it if necessary
  1676. {
  1677. if (bOld != bNew)
  1678. {
  1679. p[0] = bNew; // save to RAM
  1680. __oledSetPosition(pOLED, x, y1 >> 3, bRender);
  1681. __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
  1682. }
  1683. p += 128; // next line
  1684. bOld = bNew = p[0];
  1685. mask = 1; // start at LSB again
  1686. }
  1687. if (error < 0)
  1688. {
  1689. error += dy;
  1690. if (bOld != bNew) // write the last byte we modified if it changed
  1691. {
  1692. p[0] = bNew; // save to RAM
  1693. __oledSetPosition(pOLED, x, y1 >> 3, bRender);
  1694. __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
  1695. }
  1696. p += xinc;
  1697. x += xinc;
  1698. bOld = bNew = p[0];
  1699. }
  1700. } // for y
  1701. if (bOld != bNew) // write the last byte we modified if it changed
  1702. {
  1703. p[0] = bNew; // save to RAM
  1704. __oledSetPosition(pOLED, x, y2 >> 3, bRender);
  1705. __oledWriteDataBlock(pOLED, &bNew, 1, bRender);
  1706. }
  1707. } // y major case
  1708. } /* oledDrawLine() */
  1709. //
  1710. // For drawing ellipses, a circle is drawn and the x and y pixels are scaled by a 16-bit integer fraction
  1711. // This function draws a single pixel and scales its position based on the x/y fraction of the ellipse
  1712. //
  1713. static void __DrawScaledPixel(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
  1714. uint8_t ucColor)
  1715. {
  1716. uint8_t *d, ucMask;
  1717. if (iXFrac != 0x10000)
  1718. x = ((x * iXFrac) >> 16);
  1719. if (iYFrac != 0x10000)
  1720. y = ((y * iYFrac) >> 16);
  1721. x += iCX;
  1722. y += iCY;
  1723. if (x < 0 || x >= pOLED->oled_x || y < 0 || y >= pOLED->oled_y)
  1724. return; // off the screen
  1725. d = &pOLED->ucScreen[((y >> 3) * 128) + x];
  1726. ucMask = 1 << (y & 7);
  1727. if (ucColor)
  1728. *d |= ucMask;
  1729. else
  1730. *d &= ~ucMask;
  1731. } /* DrawScaledPixel() */
  1732. //
  1733. // For drawing filled ellipses
  1734. //
  1735. static void __DrawScaledLine(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
  1736. uint8_t ucColor)
  1737. {
  1738. int iLen, x2;
  1739. uint8_t *d, ucMask;
  1740. if (iXFrac != 0x10000)
  1741. x = ((x * iXFrac) >> 16);
  1742. if (iYFrac != 0x10000)
  1743. y = ((y * iYFrac) >> 16);
  1744. iLen = x * 2;
  1745. x = iCX - x;
  1746. y += iCY;
  1747. x2 = x + iLen;
  1748. if (y < 0 || y >= pOLED->oled_y)
  1749. return; // completely off the screen
  1750. if (x < 0)
  1751. x = 0;
  1752. if (x2 >= pOLED->oled_x)
  1753. x2 = pOLED->oled_x - 1;
  1754. iLen = x2 - x + 1; // new length
  1755. d = &pOLED->ucScreen[((y >> 3) * 128) + x];
  1756. ucMask = 1 << (y & 7);
  1757. if (ucColor) // white
  1758. {
  1759. for (; iLen > 0; iLen--)
  1760. *d++ |= ucMask;
  1761. }
  1762. else // black
  1763. {
  1764. for (; iLen > 0; iLen--)
  1765. *d++ &= ~ucMask;
  1766. }
  1767. } /* DrawScaledLine() */
  1768. //
  1769. // Draw the 8 pixels around the Bresenham circle
  1770. // (scaled to make an ellipse)
  1771. //
  1772. static void BresenhamCircle(SSOLED *pOLED, int iCX, int iCY, int x, int y, int32_t iXFrac, int32_t iYFrac,
  1773. uint8_t ucColor, uint8_t bFill)
  1774. {
  1775. if (bFill) // draw a filled ellipse
  1776. {
  1777. // for a filled ellipse, draw 4 lines instead of 8 pixels
  1778. __DrawScaledLine(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
  1779. __DrawScaledLine(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
  1780. __DrawScaledLine(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
  1781. __DrawScaledLine(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
  1782. }
  1783. else // draw 8 pixels around the edges
  1784. {
  1785. __DrawScaledPixel(pOLED, iCX, iCY, x, y, iXFrac, iYFrac, ucColor);
  1786. __DrawScaledPixel(pOLED, iCX, iCY, -x, y, iXFrac, iYFrac, ucColor);
  1787. __DrawScaledPixel(pOLED, iCX, iCY, x, -y, iXFrac, iYFrac, ucColor);
  1788. __DrawScaledPixel(pOLED, iCX, iCY, -x, -y, iXFrac, iYFrac, ucColor);
  1789. __DrawScaledPixel(pOLED, iCX, iCY, y, x, iXFrac, iYFrac, ucColor);
  1790. __DrawScaledPixel(pOLED, iCX, iCY, -y, x, iXFrac, iYFrac, ucColor);
  1791. __DrawScaledPixel(pOLED, iCX, iCY, y, -x, iXFrac, iYFrac, ucColor);
  1792. __DrawScaledPixel(pOLED, iCX, iCY, -y, -x, iXFrac, iYFrac, ucColor);
  1793. }
  1794. } /* BresenhamCircle() */
  1795. //
  1796. // Draw an outline or filled ellipse
  1797. //
  1798. void __oledEllipse(SSOLED *pOLED, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor,
  1799. uint8_t bFilled)
  1800. {
  1801. int32_t iXFrac, iYFrac;
  1802. int iRadius, iDelta, x, y;
  1803. if (pOLED == NULL || pOLED->ucScreen == NULL)
  1804. return; // must have back buffer defined
  1805. if (iRadiusX <= 0 || iRadiusY <= 0)
  1806. return; // invalid radii
  1807. if (iRadiusX > iRadiusY) // use X as the primary radius
  1808. {
  1809. iRadius = iRadiusX;
  1810. iXFrac = 65536;
  1811. iYFrac = (iRadiusY * 65536) / iRadiusX;
  1812. }
  1813. else
  1814. {
  1815. iRadius = iRadiusY;
  1816. iXFrac = (iRadiusX * 65536) / iRadiusY;
  1817. iYFrac = 65536;
  1818. }
  1819. iDelta = 3 - (2 * iRadius);
  1820. x = 0;
  1821. y = iRadius;
  1822. while (x <= y)
  1823. {
  1824. BresenhamCircle(pOLED, iCenterX, iCenterY, x, y, iXFrac, iYFrac, ucColor, bFilled);
  1825. x++;
  1826. if (iDelta < 0)
  1827. {
  1828. iDelta += (4 * x) + 6;
  1829. }
  1830. else
  1831. {
  1832. iDelta += 4 * (x - y) + 10;
  1833. y--;
  1834. }
  1835. }
  1836. } /* oledEllipse() */
  1837. //
  1838. // Draw an outline or filled rectangle
  1839. //
  1840. void __oledRectangle(SSOLED *pOLED, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled)
  1841. {
  1842. uint8_t *d, ucMask, ucMask2;
  1843. int tmp, iOff;
  1844. if (pOLED == NULL || pOLED->ucScreen == NULL)
  1845. return; // only works with a back buffer
  1846. if (x1 < 0 || y1 < 0 || x2 < 0 || y2 < 0 || x1 >= pOLED->oled_x || y1 >= pOLED->oled_y || x2 >= pOLED->oled_x
  1847. || y2 >= pOLED->oled_y)
  1848. return; // invalid coordinates
  1849. // Make sure that X1/Y1 is above and to the left of X2/Y2
  1850. // swap coordinates as needed to make this true
  1851. if (x2 < x1)
  1852. {
  1853. tmp = x1;
  1854. x1 = x2;
  1855. x2 = tmp;
  1856. }
  1857. if (y2 < y1)
  1858. {
  1859. tmp = y1;
  1860. y1 = y2;
  1861. y2 = tmp;
  1862. }
  1863. if (bFilled)
  1864. {
  1865. int x, y, iMiddle;
  1866. iMiddle = (y2 >> 3) - (y1 >> 3);
  1867. ucMask = 0xff << (y1 & 7);
  1868. if (iMiddle == 0) // top and bottom lines are in the same row
  1869. ucMask &= (0xff >> (7 - (y2 & 7)));
  1870. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
  1871. // Draw top
  1872. for (x = x1; x <= x2; x++)
  1873. {
  1874. if (ucColor)
  1875. *d |= ucMask;
  1876. else
  1877. *d &= ~ucMask;
  1878. d++;
  1879. }
  1880. if (iMiddle > 1) // need to draw middle part
  1881. {
  1882. ucMask = (ucColor) ? 0xff : 0x00;
  1883. for (y = 1; y < iMiddle; y++)
  1884. {
  1885. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1 + (y * 128)];
  1886. for (x = x1; x <= x2; x++)
  1887. *d++ = ucMask;
  1888. }
  1889. }
  1890. if (iMiddle >= 1) // need to draw bottom part
  1891. {
  1892. ucMask = 0xff >> (7 - (y2 & 7));
  1893. d = &pOLED->ucScreen[(y2 >> 3) * 128 + x1];
  1894. for (x = x1; x <= x2; x++)
  1895. {
  1896. if (ucColor)
  1897. *d++ |= ucMask;
  1898. else
  1899. *d++ &= ~ucMask;
  1900. }
  1901. }
  1902. }
  1903. else // outline
  1904. {
  1905. // see if top and bottom lines are within the same byte rows
  1906. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
  1907. if ((y1 >> 3) == (y2 >> 3))
  1908. {
  1909. ucMask2 = 0xff << (y1 & 7); // L/R end masks
  1910. ucMask = 1 << (y1 & 7);
  1911. ucMask |= 1 << (y2 & 7);
  1912. ucMask2 &= (0xff >> (7 - (y2 & 7)));
  1913. if (ucColor)
  1914. {
  1915. *d++ |= ucMask2; // start
  1916. x1++;
  1917. for (; x1 < x2; x1++)
  1918. *d++ |= ucMask;
  1919. if (x1 <= x2)
  1920. *d++ |= ucMask2; // right edge
  1921. }
  1922. else
  1923. {
  1924. *d++ &= ~ucMask2;
  1925. x1++;
  1926. for (; x1 < x2; x1++)
  1927. *d++ &= ~ucMask;
  1928. if (x1 <= x2)
  1929. *d++ &= ~ucMask2; // right edge
  1930. }
  1931. }
  1932. else
  1933. {
  1934. int y;
  1935. // L/R sides
  1936. iOff = (x2 - x1);
  1937. ucMask = 1 << (y1 & 7);
  1938. for (y = y1; y <= y2; y++)
  1939. {
  1940. if (ucColor)
  1941. {
  1942. *d |= ucMask;
  1943. d[iOff] |= ucMask;
  1944. }
  1945. else
  1946. {
  1947. *d &= ~ucMask;
  1948. d[iOff] &= ~ucMask;
  1949. }
  1950. ucMask <<= 1;
  1951. if (ucMask == 0)
  1952. {
  1953. ucMask = 1;
  1954. d += 128;
  1955. }
  1956. }
  1957. // T/B sides
  1958. ucMask = 1 << (y1 & 7);
  1959. ucMask2 = 1 << (y2 & 7);
  1960. x1++;
  1961. d = &pOLED->ucScreen[(y1 >> 3) * 128 + x1];
  1962. iOff = (y2 >> 3) - (y1 >> 3);
  1963. iOff *= 128;
  1964. for (; x1 < x2; x1++)
  1965. {
  1966. if (ucColor)
  1967. {
  1968. *d |= ucMask;
  1969. d[iOff] |= ucMask2;
  1970. }
  1971. else
  1972. {
  1973. *d &= ~ucMask;
  1974. d[iOff] &= ~ucMask2;
  1975. }
  1976. d++;
  1977. }
  1978. }
  1979. } // outline
  1980. } /* oledRectangle() */

include 文件夹包含的文件

bitbang_iic.h

  1. //
  2. // Bit Bang I2C library
  3. // Copyright (c) 2018 BitBank Software, Inc.
  4. // Written by Larry Bank (bitbank@pobox.com)
  5. // Project started 10/12/2018
  6. //
  7. // This program is free software: you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License as published by
  9. // the Free Software Foundation, either version 3 of the License, or
  10. // (at your option) any later version.
  11. //
  12. // This program is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License
  18. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. //
  20. #ifndef __BITBANG_I2C__
  21. #define __BITBANG_I2C__
  22. #include "pico/stdlib.h"
  23. #include "hardware/i2c.h"
  24. // supported devices
  25. enum {
  26. DEVICE_UNKNOWN = 0,
  27. DEVICE_SSD1306,
  28. DEVICE_SH1106,
  29. DEVICE_VL53L0X,
  30. DEVICE_BMP180,
  31. DEVICE_BMP280,
  32. DEVICE_BME280,
  33. DEVICE_MPU6000,
  34. DEVICE_MPU9250,
  35. DEVICE_MCP9808,
  36. DEVICE_LSM6DS3,
  37. DEVICE_ADXL345,
  38. DEVICE_ADS1115,
  39. DEVICE_MAX44009,
  40. DEVICE_MAG3110,
  41. DEVICE_CCS811,
  42. DEVICE_HTS221,
  43. DEVICE_LPS25H,
  44. DEVICE_LSM9DS1,
  45. DEVICE_LM8330,
  46. DEVICE_DS3231,
  47. DEVICE_LIS3DH,
  48. DEVICE_LIS3DSH,
  49. DEVICE_INA219,
  50. DEVICE_SHT3X,
  51. DEVICE_HDC1080,
  52. DEVICE_MPU6886,
  53. DEVICE_BME680,
  54. DEVICE_AXP202,
  55. DEVICE_AXP192,
  56. DEVICE_24AAXXXE64,
  57. DEVICE_DS1307
  58. };
  59. #ifndef LOW
  60. #define LOW 0
  61. #define HIGH 1
  62. #endif
  63. typedef struct mybbi2c
  64. {
  65. uint8_t iSDA, iSCL; // pin numbers (0xff = disabled)
  66. i2c_inst_t * picoI2C; // used pico I2C
  67. } BBI2C;
  68. #ifdef __cplusplus
  69. extern "C" {
  70. #endif
  71. //
  72. // Read N bytes
  73. //
  74. int I2CRead(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
  75. //
  76. // Read N bytes starting at a specific I2C internal register
  77. //
  78. int I2CReadRegister(BBI2C *pI2C, uint8_t iAddr, uint8_t u8Register, uint8_t *pData, int iLen);
  79. //
  80. // Write I2C data
  81. // quits if a NACK is received and returns 0
  82. // otherwise returns the number of bytes written
  83. //
  84. int I2CWrite(BBI2C *pI2C, uint8_t iAddr, uint8_t *pData, int iLen);
  85. //
  86. // Scans for I2C devices on the bus
  87. // returns a bitmap of devices which are present (128 bits = 16 bytes, LSB first)
  88. //
  89. // Test if an address responds
  90. // returns 0 if no response, 1 if it responds
  91. //
  92. uint8_t I2CTest(BBI2C *pI2C, uint8_t addr);
  93. // A set bit indicates that a device responded at that address
  94. //
  95. void I2CScan(BBI2C *pI2C, uint8_t *pMap);
  96. //
  97. // Initialize the I2C BitBang library
  98. // Pass the pin numbers used for SDA and SCL
  99. // as well as the clock rate in Hz
  100. //
  101. void I2CInit(BBI2C *pI2C, uint32_t iClock);
  102. //
  103. // Figure out what device is at that address
  104. // returns the enumerated value
  105. //
  106. int I2CDiscoverDevice(BBI2C *pI2C, uint8_t i);
  107. #ifdef __cplusplus
  108. }
  109. #endif
  110. #endif //__BITBANG_I2C__

ss_oled.h

  1. #ifndef __SS_OLED_H__
  2. #define __SS_OLED_H__
  3. #include <include/bitbang_iic.h>
  4. typedef struct ssoleds
  5. {
  6. uint8_t oled_addr; // requested address or 0xff for automatic detection
  7. uint8_t oled_wrap, oled_flip, oled_type;
  8. uint8_t *ucScreen;
  9. uint8_t iCursorX, iCursorY;
  10. uint8_t oled_x, oled_y;
  11. int iScreenOffset;
  12. BBI2C bbi2c;
  13. } SSOLED;
  14. // Make the Linux library interface C instead of C++
  15. #if defined(__cplusplus)
  16. extern "C" {
  17. #endif
  18. // 4 possible font sizes: 8x8, 16x32, 6x8, 16x16 (stretched from 8x8)
  19. enum {
  20. FONT_6x8 = 0,
  21. FONT_8x8,
  22. FONT_12x16,
  23. FONT_16x16,
  24. FONT_16x32
  25. };
  26. #define FONT_NORMAL FONT_8x8
  27. #define FONT_SMALL FONT_6x8
  28. #define FONT_LARGE FONT_16x32
  29. #define FONT_STRETCHED FONT_16x16
  30. // OLED type for init function
  31. enum {
  32. OLED_128x128 = 1,
  33. OLED_128x32,
  34. OLED_128x64,
  35. OLED_132x64,
  36. OLED_64x32,
  37. OLED_96x16,
  38. OLED_72x40
  39. };
  40. // Rotation and flip angles to draw tiles
  41. enum {
  42. ANGLE_0=0,
  43. ANGLE_90,
  44. ANGLE_180,
  45. ANGLE_270,
  46. ANGLE_FLIPX,
  47. ANGLE_FLIPY
  48. };
  49. // Return value from oledInit()
  50. enum {
  51. OLED_NOT_FOUND = -1, // no display found
  52. OLED_SSD1306_3C, // SSD1306 found at 0x3C
  53. OLED_SSD1306_3D, // SSD1306 found at 0x3D
  54. OLED_SH1106_3C, // SH1106 found at 0x3C
  55. OLED_SH1106_3D, // SH1106 found at 0x3D
  56. OLED_SH1107_3C, // SH1107
  57. OLED_SH1107_3D
  58. };
  59. //
  60. // Initializes the OLED controller into "page mode" on I2C
  61. // If SDAPin and SCLPin are not -1, then bit bang I2C on those pins
  62. // Otherwise use the Wire library.
  63. // If you don't need to use a separate reset pin, set it to -1
  64. //
  65. int __oledInit(SSOLED *pOLED, int bInvert, int32_t iSpeed);
  66. //
  67. // Provide or revoke a back buffer for your OLED graphics
  68. // This allows you to manage the RAM used by ss_oled on tiny
  69. // embedded platforms like the ATmega series
  70. // Pass NULL to revoke the buffer. Make sure you provide a buffer
  71. // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
  72. //
  73. void __oledSetBackBuffer(SSOLED *pOLED, uint8_t *pBuffer);
  74. //
  75. // Sets the brightness (0=off, 255=brightest)
  76. //
  77. void __oledSetContrast(SSOLED *pOLED, unsigned char ucContrast);
  78. //
  79. // Load a 128x64 1-bpp Windows bitmap
  80. // Pass the pointer to the beginning of the BMP file
  81. // First pass version assumes a full screen bitmap
  82. //
  83. int __oledLoadBMP(SSOLED *pOLED, uint8_t *pBMP, int bInvert, int bRender);
  84. //
  85. // Power up/down the display
  86. // useful for low power situations
  87. //
  88. void __oledPower(SSOLED *pOLED, uint8_t bOn);
  89. //
  90. // Set the current cursor position
  91. // The column represents the pixel column (0-127)
  92. // The row represents the text row (0-7)
  93. //
  94. void __oledSetCursor(SSOLED *pOLED, int x, int y);
  95. //
  96. // Turn text wrap on or off for the oldWriteString() function
  97. //
  98. void __oledSetTextWrap(SSOLED *pOLED, int bWrap);
  99. //
  100. // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
  101. // At the given col+row with the given scroll offset. The scroll offset allows you to
  102. // horizontally scroll text which does not fit on the width of the display. The offset
  103. // represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
  104. // of the text.
  105. // The system remembers where the last text was written (the cursor position)
  106. // To continue writing from the last position, set the x,y values to -1
  107. // The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
  108. // otherwise text which would go off the right edge will not be drawn and the cursor will
  109. // be left "off screen" until set to a new position explicitly
  110. //
  111. // Returns 0 for success, -1 for invalid parameter
  112. //
  113. int __oledWriteString(SSOLED *pOLED, int iScrollX, int x, int y, char *szMsg, int iSize, int bInvert, int bRender);
  114. //
  115. // Fill the frame buffer with a byte pattern
  116. // e.g. all off (0x00) or all on (0xff)
  117. //
  118. void __oledFill(SSOLED *pOLED, unsigned char ucData, int bRender);
  119. //
  120. // Set (or clear) an individual pixel
  121. // The local copy of the frame buffer is used to avoid
  122. // reading data from the display controller
  123. // (which isn't possible in most configurations)
  124. // This function needs the USE_BACKBUFFER macro to be defined
  125. // otherwise, new pixels will erase old pixels within the same byte
  126. //
  127. int __oledSetPixel(SSOLED *pOLED, int x, int y, unsigned char ucColor, int bRender);
  128. //
  129. // Dump an entire custom buffer to the display
  130. // useful for custom animation effects
  131. //
  132. void __oledDumpBuffer(SSOLED *pOLED, uint8_t *pBuffer);
  133. //
  134. // Render a window of pixels from a provided buffer or the library's internal buffer
  135. // to the display. The row values refer to byte rows, not pixel rows due to the memory
  136. // layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
  137. // returns 0 for success, -1 for invalid parameter
  138. //
  139. int __oledDrawGFX(SSOLED *pOLED, uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
  140. //
  141. // Draw a line between 2 points
  142. //
  143. void __oledDrawLine(SSOLED *pOLED, int x1, int y1, int x2, int y2, int bRender);
  144. //
  145. // Play a frame of animation data
  146. // The animation data is assumed to be encoded for a full frame of the display
  147. // Given the pointer to the start of the compressed data,
  148. // it returns the pointer to the start of the next frame
  149. // Frame rate control is up to the calling program to manage
  150. // When it finishes the last frame, it will start again from the beginning
  151. //
  152. uint8_t * __oledPlayAnimFrame(SSOLED *pOLED, uint8_t *pAnimation, uint8_t *pCurrent, int iLen);
  153. //
  154. // Scroll the internal buffer by 1 scanline (up/down)
  155. // width is in pixels, lines is group of 8 rows
  156. // Returns 0 for success, -1 for invalid parameter
  157. //
  158. int __oledScrollBuffer(SSOLED *pOLED, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp);
  159. //
  160. // Draw a sprite of any size in any position
  161. // If it goes beyond the left/right or top/bottom edges
  162. // it's trimmed to show the valid parts
  163. // This function requires a back buffer to be defined
  164. // The priority color (0 or 1) determines which color is painted
  165. // when a 1 is encountered in the source image.
  166. // e.g. when 0, the input bitmap acts like a mask to clear
  167. // the destination where bits are set.
  168. //
  169. void __oledDrawSprite(SSOLED *pOLED, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
  170. //
  171. // Draw a 16x16 tile in any of 4 rotated positions
  172. // Assumes input image is laid out like "normal" graphics with
  173. // the MSB on the left and 2 bytes per line
  174. // On AVR, the source image is assumed to be in FLASH memory
  175. // The function can draw the tile on byte boundaries, so the x value
  176. // can be from 0 to 112 and y can be from 0 to 6
  177. //
  178. void __oledDrawTile(SSOLED *pOLED, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
  179. //
  180. // Draw an outline or filled ellipse
  181. //
  182. void __oledEllipse(SSOLED *pOLED, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled);
  183. //
  184. // Draw an outline or filled rectangle
  185. //
  186. void __oledRectangle(SSOLED *pOLED, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled);
  187. #if defined(__cplusplus)
  188. }
  189. #endif
  190. #endif // __SS_OLED_H__

ss_oled.hpp

  1. #pragma once
  2. #include <include/bitbang_iic.h>
  3. #include "pico/stdlib.h"
  4. #include "hardware/i2c.h"
  5. #include "ss_oled.h"
  6. class picoSSOLED
  7. {
  8. private:
  9. SSOLED oled;
  10. bool invert;
  11. int32_t speed;
  12. public:
  13. //constructor
  14. picoSSOLED(int iType, int iAddr, bool bFlip, bool bInvert, i2c_inst_t * pI2C, int sda, int scl, int32_t iSpeed)
  15. {
  16. oled.oled_type = iType;
  17. oled.oled_addr = iAddr;
  18. oled.oled_flip = (int) bFlip;
  19. invert = bInvert;
  20. oled.bbi2c.picoI2C = pI2C;
  21. oled.bbi2c.iSDA = sda;
  22. oled.bbi2c.iSCL = scl;
  23. speed = iSpeed;
  24. }
  25. ;
  26. int init()
  27. {
  28. return __oledInit(&oled, (int) invert, (int32_t) speed);
  29. }
  30. ;
  31. //
  32. // Provide or revoke a back buffer for your OLED graphics
  33. // This allows you to manage the RAM used by ss_oled on tiny
  34. // embedded platforms like the ATmega series
  35. // Pass NULL to revoke the buffer. Make sure you provide a buffer
  36. // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
  37. //
  38. void set_back_buffer(uint8_t * pBuffer)
  39. {
  40. __oledSetBackBuffer(&oled, pBuffer);
  41. }
  42. ;
  43. //
  44. // Sets the brightness (0=off, 255=brightest)
  45. //
  46. void set_contrast(uint ucContrast)
  47. {
  48. __oledSetContrast(&oled, (unsigned char) ucContrast);
  49. }
  50. ;
  51. //
  52. // Load a 128x64 1-bpp Windows bitmap
  53. // Pass the pointer to the beginning of the BMP file
  54. // First pass version assumes a full screen bitmap
  55. //
  56. int load_bmp(uint8_t *pBMP, bool bInvert, bool bRender)
  57. {
  58. return __oledLoadBMP(&oled, pBMP, (int) bInvert, (int) bRender);
  59. }
  60. ;
  61. //
  62. // Power up/down the display
  63. // useful for low power situations
  64. //
  65. void power(bool bON)
  66. {
  67. __oledPower(&oled, (uint8_t) bON);
  68. }
  69. ;
  70. //
  71. // Set the current cursor position
  72. // The column represents the pixel column (0-127)
  73. // The row represents the text row (0-7)
  74. //
  75. void set_cursor(int x, int y)
  76. {
  77. __oledSetCursor(&oled, x, y);
  78. }
  79. ;
  80. //
  81. // Turn text wrap on or off for the oldWriteString() function
  82. //
  83. void set_textWrap(bool bWrap)
  84. {
  85. __oledSetTextWrap(&oled, (int) bWrap);
  86. }
  87. ;
  88. //
  89. // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
  90. // At the given col+row with the given scroll offset. The scroll offset allows you to
  91. // horizontally scroll text which does not fit on the width of the display. The offset
  92. // represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
  93. // of the text.
  94. // The system remembers where the last text was written (the cursor position)
  95. // To continue writing from the last position, set the x,y values to -1
  96. // The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
  97. // otherwise text which would go off the right edge will not be drawn and the cursor will
  98. // be left "off screen" until set to a new position explicitly
  99. //
  100. // Returns 0 for success, -1 for invalid parameter
  101. //
  102. int write_string(int iScrollX, int x, int y, char *szMsg, int iSize, bool bInvert, bool bRender)
  103. {
  104. return __oledWriteString(&oled, iScrollX, x, y, szMsg, iSize, (int) bInvert, (int) bRender);
  105. }
  106. ;
  107. //
  108. // Fill the frame buffer with a byte pattern
  109. // e.g. all off (0x00) or all on (0xff)
  110. //
  111. void fill(unsigned char ucData, bool bRender)
  112. {
  113. __oledFill(&oled, ucData, (int) bRender);
  114. }
  115. //
  116. // Set (or clear) an individual pixel
  117. // The local copy of the frame buffer is used to avoid
  118. // reading data from the display controller
  119. // (which isn't possible in most configurations)
  120. // This function needs the USE_BACKBUFFER macro to be defined
  121. // otherwise, new pixels will erase old pixels within the same byte
  122. //
  123. int set_pixel(int x, int y, unsigned char ucColor, bool bRender)
  124. {
  125. return __oledSetPixel(&oled, x, y, ucColor, (int) bRender);
  126. }
  127. ;
  128. //
  129. // Dump an entire custom buffer to the display
  130. // useful for custom animation effects
  131. //
  132. void dump_buffer(uint8_t *pBuffer)
  133. {
  134. __oledDumpBuffer(&oled, pBuffer);
  135. }
  136. ;
  137. //
  138. // Render a window of pixels from a provided buffer or the library's internal buffer
  139. // to the display. The row values refer to byte rows, not pixel rows due to the memory
  140. // layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
  141. // returns 0 for success, -1 for invalid parameter
  142. //
  143. int draw_GFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight,
  144. int iSrcPitch)
  145. {
  146. return __oledDrawGFX(&oled, pSrc, iSrcCol, iSrcRow, iDestCol, iDestRow, iWidth, iHeight, iSrcPitch);
  147. }
  148. ;
  149. //
  150. // Draw a line between 2 points
  151. //
  152. void draw_line(int x1, int y1, int x2, int y2, bool bRender)
  153. {
  154. __oledDrawLine(&oled, x1, y1, x2, y2, (int) bRender);
  155. }
  156. ;
  157. //
  158. // Play a frame of animation data
  159. // The animation data is assumed to be encoded for a full frame of the display
  160. // Given the pointer to the start of the compressed data,
  161. // it returns the pointer to the start of the next frame
  162. // Frame rate control is up to the calling program to manage
  163. // When it finishes the last frame, it will start again from the beginning
  164. //
  165. uint8_t * play_anim_frame(uint8_t *pAnimation, uint8_t *pCurrent, int iLen)
  166. {
  167. return __oledPlayAnimFrame(&oled, pAnimation, pCurrent, iLen);
  168. }
  169. ;
  170. //
  171. // Scroll the internal buffer by 1 scanline (up/down)
  172. // width is in pixels, lines is group of 8 rows
  173. // Returns 0 for success, -1 for invalid parameter
  174. //
  175. int scroll_buffer(int iStartCol, int iEndCol, int iStartRow, int iEndRow, bool bUp)
  176. {
  177. return __oledScrollBuffer(&oled, iStartCol, iEndCol, iStartRow, iEndRow, (int) bUp);
  178. }
  179. ;
  180. //
  181. // Draw a sprite of any size in any position
  182. // If it goes beyond the left/right or top/bottom edges
  183. // it's trimmed to show the valid parts
  184. // This function requires a back buffer to be defined
  185. // The priority color (0 or 1) determines which color is painted
  186. // when a 1 is encountered in the source image.
  187. // e.g. when 0, the input bitmap acts like a mask to clear
  188. // the destination where bits are set.
  189. //
  190. void draw_sprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority)
  191. {
  192. __oledDrawSprite(&oled, pSprite, cx, cy, iPitch, x, y, iPriority);
  193. }
  194. ;
  195. //
  196. // Draw a 16x16 tile in any of 4 rotated positions
  197. // Assumes input image is laid out like "normal" graphics with
  198. // the MSB on the left and 2 bytes per line
  199. // On AVR, the source image is assumed to be in FLASH memory
  200. // The function can draw the tile on byte boundaries, so the x value
  201. // can be from 0 to 112 and y can be from 0 to 6
  202. //
  203. void draw_tile(const uint8_t *pTile, int x, int y, int iRotation, bool bInvert, bool bRender)
  204. {
  205. __oledDrawTile(&oled, (const uint8_t *) pTile, x, y, iRotation, (int) bInvert, (int) bRender);
  206. }
  207. ;
  208. //
  209. // Draw an outline or filled ellipse
  210. //
  211. void draw_ellipse(int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, bool bFilled)
  212. {
  213. __oledEllipse(&oled, iCenterX, iCenterY, iRadiusX, iRadiusY, ucColor, (uint8_t) bFilled);
  214. }
  215. ;
  216. //
  217. // Draw an outline or filled rectangle
  218. //
  219. void draw_rectangle(int x1, int y1, int x2, int y2, uint8_t ucColor, bool bFilled)
  220. {
  221. __oledRectangle(&oled, x1, y1, x2, y2, ucColor, (uint8_t) bFilled);
  222. }
  223. ;
  224. };

stripp.hpp

  1. //class, constructor & methods definitions
  2. class picoSSOLED {
  3. private:
  4. [...]
  5. public:
  6. //constructor
  7. picoSSOLED(int iType, int iAddr, bool bFlip, bool bInvert, i2c_inst_t * pUART, int sda, int scl, int32_t iSpeed) {
  8. //methods
  9. int init ();
  10. //
  11. // Provide or revoke a back buffer for your OLED graphics
  12. // This allows you to manage the RAM used by ss_oled on tiny
  13. // embedded platforms like the ATmega series
  14. // Pass NULL to revoke the buffer. Make sure you provide a buffer
  15. // large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
  16. //
  17. void set_back_buffer(uint8_t * pBuffer);
  18. //
  19. // Sets the brightness (0=off, 255=brightest)
  20. //
  21. void set_contrast(uint ucContrast);
  22. //
  23. // Load a 128x64 1-bpp Windows bitmap
  24. // Pass the pointer to the beginning of the BMP file
  25. // First pass version assumes a full screen bitmap
  26. //
  27. int load_bmp(uint8_t *pBMP, bool bInvert, bool bRender);
  28. //
  29. // Power up/down the display
  30. // useful for low power situations
  31. //
  32. void power(bool bON);
  33. //
  34. // Set the current cursor position
  35. // The column represents the pixel column (0-127)
  36. // The row represents the text row (0-7)
  37. //
  38. void set_cursor(int x, int y);
  39. //
  40. // Turn text wrap on or off for the oldWriteString() function
  41. //
  42. void set_textWrap(bool bWrap);
  43. //
  44. // Draw a string of normal (8x8), small (6x8) or large (16x32) characters
  45. // At the given col+row with the given scroll offset. The scroll offset allows you to
  46. // horizontally scroll text which does not fit on the width of the display. The offset
  47. // represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
  48. // of the text.
  49. // The system remembers where the last text was written (the cursor position)
  50. // To continue writing from the last position, set the x,y values to -1
  51. // The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
  52. // otherwise text which would go off the right edge will not be drawn and the cursor will
  53. // be left "off screen" until set to a new position explicitly
  54. //
  55. // Returns 0 for success, -1 for invalid parameter
  56. //
  57. int write_string(int iScrollX, int x, int y, char *szMsg, int iSize, bool bInvert, bool bRender);
  58. //
  59. // Fill the frame buffer with a byte pattern
  60. // e.g. all off (0x00) or all on (0xff)
  61. //
  62. void fill(unsigned char ucData, bool bRender);
  63. //
  64. // Set (or clear) an individual pixel
  65. // The local copy of the frame buffer is used to avoid
  66. // reading data from the display controller
  67. // (which isn't possible in most configurations)
  68. // This function needs the USE_BACKBUFFER macro to be defined
  69. // otherwise, new pixels will erase old pixels within the same byte
  70. //
  71. int set_pixel(int x, int y, unsigned char ucColor, bool bRender);
  72. //
  73. // Dump an entire custom buffer to the display
  74. // useful for custom animation effects
  75. //
  76. void dump_buffer(uint8_t *pBuffer);
  77. //
  78. // Render a window of pixels from a provided buffer or the library's internal buffer
  79. // to the display. The row values refer to byte rows, not pixel rows due to the memory
  80. // layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
  81. // returns 0 for success, -1 for invalid parameter
  82. //
  83. int draw_GFX(uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
  84. //
  85. // Draw a line between 2 points
  86. //
  87. void draw_line(int x1, int y1, int x2, int y2, bool bRender);
  88. //
  89. // Play a frame of animation data
  90. // The animation data is assumed to be encoded for a full frame of the display
  91. // Given the pointer to the start of the compressed data,
  92. // it returns the pointer to the start of the next frame
  93. // Frame rate control is up to the calling program to manage
  94. // When it finishes the last frame, it will start again from the beginning
  95. //
  96. uint8_t * play_anim_frame(uint8_t *pAnimation, uint8_t *pCurrent, int iLen);
  97. //
  98. // Scroll the internal buffer by 1 scanline (up/down)
  99. // width is in pixels, lines is group of 8 rows
  100. // Returns 0 for success, -1 for invalid parameter
  101. //
  102. int scroll_buffer(int iStartCol, int iEndCol, int iStartRow, int iEndRow, bool bUp);
  103. //
  104. // Draw a sprite of any size in any position
  105. // If it goes beyond the left/right or top/bottom edges
  106. // it's trimmed to show the valid parts
  107. // This function requires a back buffer to be defined
  108. // The priority color (0 or 1) determines which color is painted
  109. // when a 1 is encountered in the source image.
  110. // e.g. when 0, the input bitmap acts like a mask to clear
  111. // the destination where bits are set.
  112. //
  113. void draw_sprite(uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
  114. //
  115. // Draw a 16x16 tile in any of 4 rotated positions
  116. // Assumes input image is laid out like "normal" graphics with
  117. // the MSB on the left and 2 bytes per line
  118. // On AVR, the source image is assumed to be in FLASH memory
  119. // The function can draw the tile on byte boundaries, so the x value
  120. // can be from 0 to 112 and y can be from 0 to 6
  121. //
  122. void draw_tile(const uint8_t *pTile, int x, int y, int iRotation, bool bInvert, bool bRender);
  123. //
  124. // Draw an outline or filled ellipse
  125. //
  126. void draw_ellipse(int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, bool bFilled);
  127. //
  128. // Draw an outline or filled rectangle
  129. //
  130. void draw_rectangle(int x1, int y1, int x2, int y2, uint8_t ucColor, bool bFilled);
  131. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/468134
推荐阅读
相关标签
  

闽ICP备14008679号