├── LICENSE
├── README.md
├── demo.jpg
├── examples
├── Unicode_demo
│ ├── DejaVuSansMono_Bold14pt8b.h
│ └── Unicode_demo.ino
├── co2_uno_epd
│ ├── Roboto_Black_28.h
│ └── co2_uno_epd.ino
├── epd_test
│ ├── Roboto_Black_40.h
│ └── epd_test.ino
├── epd_test_213_bwr
│ └── epd_test_213_bwr.ino
├── multi_oled_demo
│ └── multi_oled_demo.ino
├── obd_class_demo
│ └── obd_class_demo.ino
├── obd_cmd_demo
│ └── obd_cmd_demo.ino
├── oled_gfx_demo
│ └── oled_gfx_demo.ino
├── onebit_lcd_test
│ └── onebit_lcd_test.ino
├── pico_oled_13_demo
│ └── pico_oled_13_demo.ino
├── prop_font_demo
│ ├── FreeSerif12pt7b.h
│ └── prop_font_demo.ino
├── sharp_memory_lcd
│ └── sharp_memory_lcd.ino
├── simple_demo
│ └── simple_demo.ino
├── simple_demo_avr
│ └── simple_demo_avr.ino
├── tiff_on_avr
│ ├── bart_1bpp.h
│ ├── tiff_on_avr.ino
│ └── uno_bw.h
├── uc1609_test
│ ├── uc1609.h
│ └── uc1609_test.ino
└── virtual_display
│ └── virtual_display.ino
├── fontconvert
├── Makefile
├── README.txt
└── main.c
├── fonts_opt.jpg
├── library.properties
├── linux
├── Makefile
├── OLED_demo
│ ├── Makefile
│ └── main.c
├── README.txt
├── Sharp_LCD
│ ├── Makefile
│ └── main.c
├── epd_cpp_demo
│ ├── Makefile
│ └── main.cpp
├── epd_demo
│ ├── Makefile
│ ├── Roboto_Black_28.h
│ └── main.c
├── gif_1_bus_2_oleds
│ ├── Makefile
│ ├── main.c
│ └── running_256_64.h
├── obd.c
├── sharp_fast_gif
│ ├── Makefile
│ ├── main.c
│ └── pattern_400x240.h
├── sharp_lcd_gif
│ ├── Makefile
│ ├── main.c
│ └── pattern_400x240.h
├── spi_demo
│ ├── Makefile
│ └── main.c
└── virtual_disp
│ ├── Makefile
│ ├── main.c
│ └── notes.h
├── notes.txt
├── sharp_lcd.jpg
└── src
├── OneBitDisplay.cpp
├── OneBitDisplay.h
├── obd.inl
├── obd_gfx.inl
├── obd_io.inl
└── obd_stub.inl
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2020 BitBank Software, Inc. All rights reserved.
2 |
3 | Apache License
4 | Version 2.0, January 2004
5 | http://www.apache.org/licenses/
6 |
7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
8 |
9 | 1. Definitions.
10 |
11 | "License" shall mean the terms and conditions for use, reproduction,
12 | and distribution as defined by Sections 1 through 9 of this document.
13 |
14 | "Licensor" shall mean the copyright owner or entity authorized by
15 | the copyright owner that is granting the License.
16 |
17 | "Legal Entity" shall mean the union of the acting entity and all
18 | other entities that control, are controlled by, or are under common
19 | control with that entity. For the purposes of this definition,
20 | "control" means (i) the power, direct or indirect, to cause the
21 | direction or management of such entity, whether by contract or
22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
23 | outstanding shares, or (iii) beneficial ownership of such entity.
24 |
25 | "You" (or "Your") shall mean an individual or Legal Entity
26 | exercising permissions granted by this License.
27 |
28 | "Source" form shall mean the preferred form for making modifications,
29 | including but not limited to software source code, documentation
30 | source, and configuration files.
31 |
32 | "Object" form shall mean any form resulting from mechanical
33 | transformation or translation of a Source form, including but
34 | not limited to compiled object code, generated documentation,
35 | and conversions to other media types.
36 |
37 | "Work" shall mean the work of authorship, whether in Source or
38 | Object form, made available under the License, as indicated by a
39 | copyright notice that is included in or attached to the work
40 | (an example is provided in the Appendix below).
41 |
42 | "Derivative Works" shall mean any work, whether in Source or Object
43 | form, that is based on (or derived from) the Work and for which the
44 | editorial revisions, annotations, elaborations, or other modifications
45 | represent, as a whole, an original work of authorship. For the purposes
46 | of this License, Derivative Works shall not include works that remain
47 | separable from, or merely link (or bind by name) to the interfaces of,
48 | the Work and Derivative Works thereof.
49 |
50 | "Contribution" shall mean any work of authorship, including
51 | the original version of the Work and any modifications or additions
52 | to that Work or Derivative Works thereof, that is intentionally
53 | submitted to Licensor for inclusion in the Work by the copyright owner
54 | or by an individual or Legal Entity authorized to submit on behalf of
55 | the copyright owner. For the purposes of this definition, "submitted"
56 | means any form of electronic, verbal, or written communication sent
57 | to the Licensor or its representatives, including but not limited to
58 | communication on electronic mailing lists, source code control systems,
59 | and issue tracking systems that are managed by, or on behalf of, the
60 | Licensor for the purpose of discussing and improving the Work, but
61 | excluding communication that is conspicuously marked or otherwise
62 | designated in writing by the copyright owner as "Not a Contribution."
63 |
64 | "Contributor" shall mean Licensor and any individual or Legal Entity
65 | on behalf of whom a Contribution has been received by Licensor and
66 | subsequently incorporated within the Work.
67 |
68 | 2. Grant of Copyright License. Subject to the terms and conditions of
69 | this License, each Contributor hereby grants to You a perpetual,
70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
71 | copyright license to reproduce, prepare Derivative Works of,
72 | publicly display, publicly perform, sublicense, and distribute the
73 | Work and such Derivative Works in Source or Object form.
74 |
75 | 3. Grant of Patent License. Subject to the terms and conditions of
76 | this License, each Contributor hereby grants to You a perpetual,
77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
78 | (except as stated in this section) patent license to make, have made,
79 | use, offer to sell, sell, import, and otherwise transfer the Work,
80 | where such license applies only to those patent claims licensable
81 | by such Contributor that are necessarily infringed by their
82 | Contribution(s) alone or by combination of their Contribution(s)
83 | with the Work to which such Contribution(s) was submitted. If You
84 | institute patent litigation against any entity (including a
85 | cross-claim or counterclaim in a lawsuit) alleging that the Work
86 | or a Contribution incorporated within the Work constitutes direct
87 | or contributory patent infringement, then any patent licenses
88 | granted to You under this License for that Work shall terminate
89 | as of the date such litigation is filed.
90 |
91 | 4. Redistribution. You may reproduce and distribute copies of the
92 | Work or Derivative Works thereof in any medium, with or without
93 | modifications, and in Source or Object form, provided that You
94 | meet the following conditions:
95 |
96 | (a) You must give any other recipients of the Work or
97 | Derivative Works a copy of this License; and
98 |
99 | (b) You must cause any modified files to carry prominent notices
100 | stating that You changed the files; and
101 |
102 | (c) You must retain, in the Source form of any Derivative Works
103 | that You distribute, all copyright, patent, trademark, and
104 | attribution notices from the Source form of the Work,
105 | excluding those notices that do not pertain to any part of
106 | the Derivative Works; and
107 |
108 | (d) If the Work includes a "NOTICE" text file as part of its
109 | distribution, then any Derivative Works that You distribute must
110 | include a readable copy of the attribution notices contained
111 | within such NOTICE file, excluding those notices that do not
112 | pertain to any part of the Derivative Works, in at least one
113 | of the following places: within a NOTICE text file distributed
114 | as part of the Derivative Works; within the Source form or
115 | documentation, if provided along with the Derivative Works; or,
116 | within a display generated by the Derivative Works, if and
117 | wherever such third-party notices normally appear. The contents
118 | of the NOTICE file are for informational purposes only and
119 | do not modify the License. You may add Your own attribution
120 | notices within Derivative Works that You distribute, alongside
121 | or as an addendum to the NOTICE text from the Work, provided
122 | that such additional attribution notices cannot be construed
123 | as modifying the License.
124 |
125 | You may add Your own copyright statement to Your modifications and
126 | may provide additional or different license terms and conditions
127 | for use, reproduction, or distribution of Your modifications, or
128 | for any such Derivative Works as a whole, provided Your use,
129 | reproduction, and distribution of the Work otherwise complies with
130 | the conditions stated in this License.
131 |
132 | 5. Submission of Contributions. Unless You explicitly state otherwise,
133 | any Contribution intentionally submitted for inclusion in the Work
134 | by You to the Licensor shall be under the terms and conditions of
135 | this License, without any additional terms or conditions.
136 | Notwithstanding the above, nothing herein shall supersede or modify
137 | the terms of any separate license agreement you may have executed
138 | with Licensor regarding such Contributions.
139 |
140 | 6. Trademarks. This License does not grant permission to use the trade
141 | names, trademarks, service marks, or product names of the Licensor,
142 | except as required for reasonable and customary use in describing the
143 | origin of the Work and reproducing the content of the NOTICE file.
144 |
145 | 7. Disclaimer of Warranty. Unless required by applicable law or
146 | agreed to in writing, Licensor provides the Work (and each
147 | Contributor provides its Contributions) on an "AS IS" BASIS,
148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
149 | implied, including, without limitation, any warranties or conditions
150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
151 | PARTICULAR PURPOSE. You are solely responsible for determining the
152 | appropriateness of using or redistributing the Work and assume any
153 | risks associated with Your exercise of permissions under this License.
154 |
155 | 8. Limitation of Liability. In no event and under no legal theory,
156 | whether in tort (including negligence), contract, or otherwise,
157 | unless required by applicable law (such as deliberate and grossly
158 | negligent acts) or agreed to in writing, shall any Contributor be
159 | liable to You for damages, including any direct, indirect, special,
160 | incidental, or consequential damages of any character arising as a
161 | result of this License or out of the use or inability to use the
162 | Work (including but not limited to damages for loss of goodwill,
163 | work stoppage, computer failure or malfunction, or any and all
164 | other commercial damages or losses), even if such Contributor
165 | has been advised of the possibility of such damages.
166 |
167 | 9. Accepting Warranty or Additional Liability. While redistributing
168 | the Work or Derivative Works thereof, You may choose to offer,
169 | and charge a fee for, acceptance of support, warranty, indemnity,
170 | or other liability obligations and/or rights consistent with this
171 | License. However, in accepting such obligations, You may act only
172 | on Your own behalf and on Your sole responsibility, not on behalf
173 | of any other Contributor, and only if You agree to indemnify,
174 | defend, and hold each Contributor harmless for any liability
175 | incurred by, or claims asserted against, such Contributor by reason
176 | of your accepting any such warranty or additional liability.
177 |
178 | END OF TERMS AND CONDITIONS
179 |
180 | APPENDIX: How to apply the Apache License to your work.
181 |
182 | To apply the Apache License to your work, attach the following
183 | boilerplate notice, with the fields enclosed by brackets "[]"
184 | replaced with your own identifying information. (Don't include
185 | the brackets!) The text should be enclosed in the appropriate
186 | comment syntax for the file format. We also recommend that a
187 | file or class name and description of purpose be included on the
188 | same "printed page" as the copyright notice for easier
189 | identification within third-party archives.
190 |
191 | Copyright [yyyy] [name of copyright owner]
192 |
193 | Licensed under the Apache License, Version 2.0 (the "License");
194 | you may not use this file except in compliance with the License.
195 | You may obtain a copy of the License at
196 |
197 | http://www.apache.org/licenses/LICENSE-2.0
198 |
199 | Unless required by applicable law or agreed to in writing, software
200 | distributed under the License is distributed on an "AS IS" BASIS,
201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
202 | See the License for the specific language governing permissions and
203 | limitations under the License.
204 |
205 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | OneBitDisplay (1-bpp OLED/LCD library)
2 | -----------------------------------
3 | Project started 3/23/2020
4 | Copyright (c) 2020 BitBank Software, Inc.
5 | Written by Larry Bank
6 | bitbank@pobox.com
7 |
8 | 
9 |
10 | The purpose of this code is to easily control monochrome (1-bit per pixel) OLED and LCD displays. The displays can be connected to the traditional I2C or SPI bus, or you can use GPIO pins to bit bang the signals.
11 |
12 | On AVR microcontrollers, there is an optimized option to speed up access to the GPIO pins to allow speeds which match or exceed normal I2C speeds. The pins are numbered with the Port letter as the first digit followed by the bit number. For example, To use bit 0 of Port B, you would reference pin number 0xb0.
13 |
14 | Includes the unique feature that the I2C init function can optionally detect the display address (0x3C or 0x3D) and the controller type (SSD1306, SH1106 or SH1107).
15 |
16 | I try to support as many OLEDs as I can. I was able to justify buying a bunch
17 | of different sized SSD1306 displays because they're around $2 each. A generous patron
18 | donated money so that I could purchase Pimoroni's 128x128 OLED and add support for it.
19 | It uses the SH1107 controller and behaves very similarly to the SH1106.
20 |
21 |
22 | Features:
23 | ---------
24 | - C API and C++ wrapper class which mimics the Adafruit_GFX API
25 | - Supports any number of simultaneous displays of any type (mix and match)
26 | - Optionally detect the display address and type (I2C only)
27 | - Supports 72x40, 96x16, 64x32, 128x32, 128x64, 64x128 (SH1107), 128x128 (SH1107) and 132x64 (SH1106) OLED display sizes
28 | - Supports 96x68 HX1230, 84x48 Nokia 5110 and 128x64 ST7567/UC1701 mono LCDs
29 | - Supports 144x168 and 400x240 Sharp Memory LCDs
30 | - Supports the ST7302 low power LCD (250x122, 2.13")
31 | - *NEW* supports a few popular epd (e-ink) panels
32 | - Virtual displays of any size which can be drawn across multiple physical displays
33 | - Flexible copy function can convert the internal pixel format to any output format and orientation
34 | - Drive displays from I2C, SPI or any GPIO pins (virtual I2C/SPI)
35 | - Includes 5 sizes of fixed fonts (6x8, 8x8, 12x16, 16x16, 16x32)
36 | - Text drawing at any fractional scale (e.g. 1.25x), and any of 4 directions/rotations
37 | - Can use Adafruit_GFX format bitmap fonts (proportional and fixed)
38 | - Deferred rendering allows preparing a back buffer, then displaying it (usually faster)
39 | - Text scrolling features (vertical and horizontal)
40 | - Text cursor position with optional line wrap
41 | - A function to load a Windows BMP file
42 | - Pixel drawing on SH1106/7 without needing backing RAM
43 | - Optimized Bresenham line drawing
44 | - Optimized Bresenham outline and filled ellipse drawing
45 | - Optimized outline and filled rectangle drawing
46 | - Optional backing RAM (needed for some text and drawing functions)
47 | - 16x16 Tile/Sprite drawing at any angle.
48 | - Run full frame animations at high frame rates with a simple API
49 |
50 | This code depends on the BitBang_I2C library. You can download it here:
51 | https://github.com/bitbank2/BitBang_I2C
52 |
53 | See the Wiki for help getting started
54 | https://github.com/bitbank2/OneBitDisplay/wiki
55 |
56 |
57 | 
58 | A few words about fonts
59 | -----------------------
60 |
61 | The library includes 3 fixed fonts (6x8, 8x8 and 16x32). The 16x32 font is disabled when compiling for AVR targets (e.g. Arduino Uno) to save FLASH program space. The other 2 fonts offer 2x stretched versions (12x16 from 6x8 and 16x16 from 8x8). A simple smoothing algorithm is applied to the stretched 6x8 font to make it look better. In the photo above are the first 4 font sizes shown on a 128x64 yellow OLED display. Only 96 ASCII characters are defined per font to save space. To use more elaborate fonts with more extensive character support, use Adafruit_GFX format bitmap fonts with the `obdWriteStringCustom()` function.
62 |
63 | 
64 | Sharp Memory LCD Support
65 | ------------------------
66 | New - support for the Sharp 144x168 and 400x240 memory LCDs. These are a different type of LCD that have a high refresh rate and low power usage. They cost quite a bit more than normal LCDs. They require a memory back buffer to use the drawing functions due to the way data is written to them one line at a time. I've also added a specific function if you would like to skip the back buffer - `obdWriteLCDLine()`. It allows you to write a single line of pixels without needing any additional memory. Please see the Wiki for more details.
67 |
68 | Instructions for use:
69 | ---------------------
70 | Start by initializing the library. Either using hardware I2C, bit-banged I2C or SPI to talk to the display. For I2C, the
71 | address of the display will be detected automatically (either 0x3c or 0x3d) or you can specify it. The typical MCU only allows setting the I2C speed up to 400Khz, but the SSD1306 displays can handle a much faster signal. With the bit-bang code, you can usually specify a stable 800Khz clock and with Cortex-M0 targets, the hardware I2C can be told to be almost any speed, but the displays I've tested tend to stop working beyond 1.6Mhz.
72 |
73 | After initializing the display you can begin drawing text or graphics on it. The final parameter of all of the drawing functions is a render flag. When true, the graphics will be sent to the internal backing buffer (when available) and sent to the display. You optionally pass the library a backing buffer (if your MCU has enough RAM) with the obdSetBackBuffer() function. When the render flag is false, the graphics will only be drawn into the internal buffer. Once you're ready to send the pixels to the display, call obdDumpBuffer(NULL) and it will copy the internal buffer in its entirety to the display.
74 |
75 | The text drawing function now has a scroll offset parameter. This tells it how many pixels of the text to skip before drawing the text at the given destination coordinates. For example, if you pass a value of 20 for the scroll offset and are using an 8-pixel wide font (FONT_8x8), the first two and a half characters will not be drawn; the second half of the third and subsequent characters will be drawn starting at the x/y you specified. This allows you to create a scrolling text effect by repeatedly calling the oledWriteString() function with progressively larger scroll offset values to make the text scroll from right to left.
76 |
77 |
78 | If you find this code useful, please consider sending a donation or becomming a Github sponsor.
79 |
80 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=SR4F44J2UR8S4)
81 |
82 |
--------------------------------------------------------------------------------
/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitbank2/OneBitDisplay/5c5e1b9c2ebd08a63e66c39460514a9d811bb921/demo.jpg
--------------------------------------------------------------------------------
/examples/Unicode_demo/Unicode_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // Unicode character demo
3 | //
4 | // The purpose of this demo is to show how to use Unicode
5 | // characters directly in your sketches with no hassles
6 | // OneBitDisplay supports using 8-bit values to display
7 | // TrueType font glyphs that have been converted to
8 | // bitmap form. This limits the possible characters that
9 | // can be displayed since Unicode is a 16-bit code. The
10 | // workaround created by Microsoft many years ago was to
11 | // select the most used characters for Western languages
12 | // and place them in a set they called codepage 1252. This
13 | // set includes accented characters and symbols in the
14 | // range 128-255. These map to Unicode values up to 2300.
15 | // OneBitDisplay now allows you to generate bitmap fonts
16 | // with this mapping (use the fontconvert tool) and the
17 | // UTF-8 multi-byte characters typed into your text editor
18 | // get converted on the fly to the codepage 1252 range.
19 | // This works for most situations except Asian and middle-East
20 | // languages.
21 | //
22 | #include
23 | #include "DejaVuSansMono_Bold14pt8b.h"
24 | ONE_BIT_DISPLAY obd;
25 |
26 | void setup()
27 | {
28 | obd.I2Cbegin(OLED_128x64);
29 | obd.allocBuffer(); // we need a back buffer for precise vertical placement on this OLED
30 | obd.fillScreen(OBD_WHITE);
31 | obd.setFreeFont(&DejaVuSansMono_Bold14pt8b);
32 | obd.setCursor(0, 22); // the character baseline is the Y position for TrueType fonts
33 | obd.println("Está a"); // Use UTF-8 strings directly in your code
34 | obd.println("começar!"); // and the characters will map internally to codepage 1252
35 | obd.display(); // show the buffer on the physical display
36 | }
37 |
38 | void loop()
39 | {
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/examples/co2_uno_epd/co2_uno_epd.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay EPD (e-ink) demo sketch
3 | // Written by Larry Bank 10/10/2022
4 | //
5 | // This program shows how to use epd panels
6 | // with the OneBitDisplay library. The general idea
7 | // is that it doesn't support "immediate" mode with e-ink.
8 | // You'll need to allocate a buffer to hold the pixel
9 | // data, draw on it, then dump it all at once to the panel
10 | // as a full update (display) or partial (displayPartial).
11 | // If your MCU doesn't have enough RAM to hold the framebuffer
12 | // then you can use the 'zero buffer' mode as shown below.
13 | // The orientation and drawing functions are more limited,
14 | // but an MCU with constrained resources can still display
15 | // attractive content.
16 | //
17 | #include
18 | #include
19 | #include "Roboto_Black_28.h"
20 |
21 | ONE_BIT_DISPLAY lcd;
22 | SCD41 mySensor;
23 |
24 | // Define both of these to be -1 for default I2C pins
25 | #define SDA_PIN -1
26 | #define SCL_PIN -1
27 | #define BITBANG false
28 |
29 | #if defined(ARDUINO_AVR_UNO)
30 | #define EPD_FREQ 2000000
31 | #define EPD_CS 10
32 | #define EPD_DC 9
33 | #define EPD_BUSY 7
34 | #define EPD_RES 8
35 | #define EPD_MOSI -1
36 | #define EPD_SCK -1
37 | #define POWER_ENABLE -1
38 | #define EPD_TYPE EPD213_122x250
39 | #endif
40 | void setup()
41 | {
42 | lcd.setSPIPins(EPD_CS, EPD_MOSI, EPD_SCK, EPD_DC, EPD_RES, EPD_BUSY);
43 | lcd.SPIbegin(EPD_TYPE, EPD_FREQ);
44 | lcd.setRotation(90);
45 | if (mySensor.init(SDA_PIN, SCL_PIN, BITBANG, 100000) == SCD41_SUCCESS)
46 | {
47 | mySensor.start(); // start sampling mode
48 | } else { // can't find the sensor, stop
49 | lcd.fillScreen(OBD_WHITE);
50 | lcd.drawString("SCD41 not found!",0,0);
51 | lcd.drawString("Halted...", 0, 8);
52 | lcd.display();
53 | while (1) {};
54 | }
55 | } /* setup() */
56 |
57 | void loop() {
58 | char szTemp[32];
59 |
60 | mySensor.getSample();
61 | lcd.fillScreen(OBD_WHITE); // 0 for EPDs is white (for OneBitDisplay)
62 | lcd.setTextColor(OBD_BLACK);
63 | lcd.setFont(FONT_12x16);
64 | lcd.drawString("2.13 250x122 AVR test",0,0);
65 | lcd.setFreeFont(&Roboto_Black_28);
66 | // Display CO2 value
67 | sprintf(szTemp, "CO2: %dppm", mySensor.co2());
68 | lcd.drawString(szTemp, 0, 48);
69 |
70 | // Display temperature
71 | sprintf(szTemp, "Temperature: %dC", mySensor.temperature());
72 | lcd.drawString(szTemp, 0, 88);
73 |
74 | // Display humidity
75 | sprintf(szTemp, "Humidity: %d%%", mySensor.humidity());
76 | lcd.drawString(szTemp, 0, 122);
77 |
78 | // Tell EPD to do a full refresh
79 | lcd.display();
80 | delay(30000); // get a new sample every 30 seconds
81 | }
82 |
--------------------------------------------------------------------------------
/examples/epd_test/epd_test.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay EPD (e-ink) demo sketch
3 | // Written by Larry Bank 7/10/2022
4 | //
5 | // This program shows how to use epd panels
6 | // with the OneBitDisplay library. The general idea
7 | // is that it doesn't support "immediate" mode with e-ink.
8 | // You'll need to allocate a buffer to hold the pixel
9 | // data, draw on it, then dump it all at once to the panel
10 | // as a full update (display) or partial (displayPartial).
11 | // This demo draws some text using the built-in fonts and
12 | // a custom font in Adafruit_GFX format
13 | //
14 | // The target hardware for this demo is the Pimoroni Badger2040
15 | // A RPI Pico MCU with a UC8151 2.9" 128x296 1-bpp epd
16 | //
17 | #include
18 | #include "Roboto_Black_40.h"
19 |
20 | ONE_BIT_DISPLAY lcd;
21 |
22 | #define BADGER_FREQ 12000000
23 | #define BADGER_CS 17
24 | #define BADGER_BUSY -1
25 | #define BADGER_RES 21
26 | #define BADGER_DC 20
27 | #define BADGER_MOSI 19
28 | #define BADGER_SCK 18
29 | #define BADGER_BATT 29
30 |
31 | void setup() {
32 | // Initialize the library by telling it how the display is connected
33 | lcd.setSPIPins(BADGER_CS, -1, -1, BADGER_DC, BADGER_RES, BADGER_BUSY);
34 | lcd.SPIbegin(EPD29_128x296, BADGER_FREQ); // 12Mhz is fast enough
35 |
36 | // Set the orientation to draw in the direction we want
37 | lcd.setRotation(90); // the panel is actually 128 wide by 296 tall, but oriented 90 right
38 | lcd.allocBuffer(); // allocate a back buffer and keep it internal to the class
39 | lcd.fillScreen(OBD_WHITE); // 0 for EPDs is white (for OneBitDisplay)
40 | lcd.setFont(FONT_12x16); // use the internal stretched/smoothed font
41 | lcd.print("This was a full update");
42 | lcd.display(); // do a full update
43 | for (int i=24; i<120; i += 32) {
44 | lcd.fillCircle(i, i, 8, 1);
45 | lcd.displayFast(); // draw a ball and show intermediate results with a partial update
46 | }
47 | lcd.setCursor(0, 112);
48 | lcd.print("then a partial update");
49 | lcd.displayFast(); // final partial update
50 | delay(4000);
51 | lcd.fillScreen(OBD_WHITE);
52 | lcd.setFreeFont(&Roboto_Black_40);
53 | lcd.setCursor(0,40);
54 | lcd.println("Gratuitous");
55 | lcd.println("pretty font");
56 | lcd.setFont(FONT_12x16);
57 | lcd.setCursor(0,112);
58 | lcd.println("Finished");
59 | lcd.display(); // show final screen with a full update
60 | }
61 |
62 | void loop() {
63 | // nothing going on here
64 | }
65 |
--------------------------------------------------------------------------------
/examples/epd_test_213_bwr/epd_test_213_bwr.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay BWR EPD (e-ink) demo sketch
3 | // Written by Larry Bank 7/10/2022
4 | // edit by Aaron Christophel ATC1441 20/11/2022
5 | //
6 | // This program shows how to use epd panels
7 | // with the OneBitDisplay library. The general idea
8 | // is that it doesn't support "immediate" mode with e-ink.
9 | // You'll need to allocate a buffer to hold the pixel
10 | // data, draw on it, then dump it all at once to the panel
11 | // as a full update (display) or partial (displayPartial).
12 | // This demo draws some text using the built-in fonts and
13 | // a custom font in Adafruit_GFX format
14 | //
15 |
16 | #include
17 |
18 | ONE_BIT_DISPLAY lcd;
19 |
20 | #define EPD_FREQ 12000000
21 | #define EPD_CS 5
22 | #define EPD_BUSY 4
23 | #define EPD_RES 16
24 | #define EPD_DC 17
25 | #define EPD_MOSI 23
26 | #define EPD_SCK 18
27 |
28 | void setup() {
29 | // Initialize the library by telling it how the display is connected
30 | lcd.setSPIPins(EPD_CS, -1, -1, EPD_DC, EPD_RES, EPD_BUSY);
31 | lcd.SPIbegin(EPD213R_104x212_d, EPD_FREQ); // 12Mhz is fast enough
32 |
33 | // Set the orientation to draw in the direction we want
34 | lcd.setRotation(90); // the panel is actually 128 wide by 296 tall, but oriented 90 right
35 | lcd.allocBuffer(); // allocate a back buffer and keep it internal to the class
36 | lcd.fillScreen(OBD_WHITE); // 0 for EPDs is white (for OneBitDisplay)
37 | lcd.setFont(FONT_12x16); // use the internal stretched/smoothed font
38 | lcd.println("This was");
39 | lcd.setTextColor(2);
40 | lcd.print("a full update");
41 | lcd.display(); // do a full update
42 | }
43 |
44 | void loop() {
45 | // nothing going on here
46 | }
47 |
--------------------------------------------------------------------------------
/examples/multi_oled_demo/multi_oled_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay library multi-display demo
3 | //
4 | // Demonstrates how to initialize and use multiple displays
5 | //
6 | #include
7 |
8 | // Use -1 for the Wire library default pins
9 | // or specify the pin numbers to use with the Wire library or bit banging on any GPIO pins
10 | // These are reversed because I did straight-through wiring for my SSD1306
11 | // and it has the 4-pin header as GND,VCC,SCL,SDA, but the GROVE connector is
12 | // GND,VCC,SDA,SCL
13 | #define GROVE_SDA_PIN 32
14 | #define GROVE_SCL_PIN 26
15 | // These are the pin numbers for the M5Stack Atom default I2C
16 | #define SDA_PIN 21
17 | #define SCL_PIN 22
18 | // Set this to -1 to disable or the GPIO pin number connected to the reset
19 | // line of your display if it requires an external reset
20 | #define RESET_PIN -1
21 | // let ss_oled figure out the display address
22 | #define OLED_ADDR -1
23 | // don't rotate the display
24 | #define FLIP180 0
25 | // don't invert the display
26 | #define INVERT 0
27 | // Bit-Bang the I2C bus
28 | #define USE_HW_I2C 0
29 |
30 | // Change these if you're using different OLED displays
31 | #define MY_OLED1 OLED_128x64
32 | #define MY_OLED2 OLED_64x32
33 |
34 | // 2 copies of the SSOLED structure. Each structure is about 56 bytes
35 | // There is no limit to the number of simultaneous displays which can be controlled by ss_oled
36 | OBDISP obd[2];
37 |
38 | void setup() {
39 | char *msgs[] = {(char *)"SSD1306 @ 0x3C", (char *)"SSD1306 @ 0x3D",(char *)"SH1106 @ 0x3C",(char *)"SH1106 @ 0x3D"};
40 | int rc;
41 | // The I2C SDA/SCL pins set to -1 means to use the default Wire library
42 | // If pins were specified, they would be bit-banged in software
43 | // This isn't inferior to hw I2C and in fact allows you to go faster on certain CPUs
44 | // The reset pin is optional and I've only seen it needed on larger OLEDs (2.4")
45 | // that can be configured as either SPI or I2C
46 | //
47 | // obdI2CInit(OBDISP *, type, oled_addr, rotate180, invert, bWire, SDA_PIN, SCL_PIN, RESET_PIN, speed)
48 |
49 | rc = obdI2CInit(&obd[0], MY_OLED1, OLED_ADDR, FLIP180, INVERT, 1, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); // use standard I2C bus at 400Khz
50 | if (rc != OLED_NOT_FOUND)
51 | {
52 | obdFill(&obd[0], OBD_WHITE, 1);
53 | obdWriteString(&obd[0], 0,0,0,msgs[rc], FONT_8x8, OBD_BLACK, 1);
54 | obdWriteString(&obd[0], 0,8,3,(char *)"Display", FONT_16x16, OBD_BLACK, 1);
55 | obdWriteString(&obd[0], 0,56,6,(char *)"0", FONT_16x16, OBD_BLACK, 1);
56 | }
57 | rc = obdI2CInit(&obd[1], MY_OLED2, OLED_ADDR, FLIP180, INVERT, 0, GROVE_SDA_PIN, GROVE_SCL_PIN, RESET_PIN, 400000L); // use standard I2C bus at 400Khz
58 | if (rc != OLED_NOT_FOUND)
59 | {
60 | obdFill(&obd[1], OBD_WHITE, 1);
61 | obdSetTextWrap(&obd[1], 1);
62 | obdWriteString(&obd[1], 0,0,0,msgs[rc], FONT_6x8, OBD_BLACK, 1);
63 | obdWriteString(&obd[1], 0,4,2,(char *)"Display", FONT_8x8, OBD_BLACK, 1);
64 | obdWriteString(&obd[1], 0,28,3,(char *)"1", FONT_8x8, OBD_BLACK, 1);
65 | }
66 | } /* setup() */
67 |
68 | void loop() {
69 | // put your main code here, to run repeatedly:
70 |
71 | } /* loop() */
72 |
--------------------------------------------------------------------------------
/examples/obd_class_demo/obd_class_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // Simple demo sketch to show how to use the new
3 | // C++ class which wraps the OneBitDisplay C API
4 | // This class was modeled after the Adafruit GFX API
5 | // to make it easier to port code, yet still retains
6 | // the unique features of OBD
7 | //
8 | // Written by Larry Bank
9 | // project started April 24, 2022
10 | //
11 | #include
12 | ONE_BIT_DISPLAY tft; // static class instantiation
13 |
14 | void setup()
15 | {
16 | int i;
17 | // The I2Cbegin() method needs a minimum of the type of OLED/LCD being used
18 | // Optional parameters are for the I2C address (auto discovered if not specified)
19 | // and the I2C bus speed (defaults to 400Kbs)
20 | // The Arduino default I2C pins are used here (works on many setups)
21 | // If you need to specify them, use the setI2CPins() method
22 | tft.I2Cbegin(OLED_64x128);
23 | //
24 | // Here we're asking the library to allocate the backing buffer
25 | // If successful, the library will change the render flag to "RAM only" so that
26 | // all drawing occurs only to the internal buffer, and display() must be called
27 | // to see the changes. Without a backing buffer, the API will try to draw all
28 | // output directly to the display instead.
29 | //
30 | if (!tft.allocBuffer()) {
31 | tft.print("Alloc failed");
32 | }
33 | // tft.setRotation(3); // optionally rotate in 90 degree increments - only supports 0/180 without a RAM backing buffer
34 | tft.fillScreen(OBD_WHITE);
35 | tft.setScroll(true); // enable text printing to scroll the display buffer a line at a time
36 | tft.setFont(FONT_12x16); // Use the 6x8 (stretched+smoothed) font
37 | i = 0;
38 | while (1) {
39 | tft.print("Count = ");
40 | tft.println(i++, DEC); // this will keep the last line blank because it immediately scrolls up
41 | tft.display(); // copy the RAM buffer to the physical display
42 | delay(250); // slow it down a bit
43 | }
44 | }
45 |
46 | void loop() {
47 | // nothing going on here
48 | }
49 |
--------------------------------------------------------------------------------
/examples/obd_cmd_demo/obd_cmd_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay command example
3 | // shows how to create and play back a buffer of bytewise display commands
4 | // written by Larry Bank 1/23/2022
5 | //
6 | #include
7 | OBDISP obd, obdCMD;
8 | uint8_t ucBuffer[1024], ucBackBuffer[1024];
9 | // 16x16 X image
10 | uint8_t ucSprite[32] = {0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,
11 | 0x08,0x10,0x04,0x20,0x02,0x40,0x01,0x80,
12 | 0x01,0x80,0x02,0x40,0x04,0x20,0x08,0x10,
13 | 0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01};
14 | void setup() {
15 | int rc;
16 | char szTemp[32];
17 | // int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int iSDAPin, int iSCLPin, int iResetPin, int32_t iSpeed);
18 | rc = obdI2CInit(&obd, OLED_128x64, -1, 0, 0, 1, -1, -1, -1, 800000);
19 | obdSetBackBuffer(&obd, ucBackBuffer);
20 | obdFill(&obd, OBD_WHITE, 1);
21 | memset(&obdCMD, 0, sizeof(obdCMD)); // ready for commands
22 | obdSetBackBuffer(&obdCMD, ucBuffer); // give it a memory space to save the commands
23 |
24 | obdWriteString(&obd, 0,0,0, (char *)"OBD Command test", FONT_8x8, OBD_BLACK, 1);
25 | obdWriteString(&obd, 0,0,1, (char *)"Executing...", FONT_8x8, OBD_BLACK, 1);
26 | obdFill(&obdCMD, OBD_WHITE, 1);
27 | obdWriteString(&obdCMD, 0,0,0,(char *)"The OBD lib functions", FONT_6x8, OBD_BLACK, 1);
28 | obdWriteString(&obdCMD, 0,0,1,(char *)"become byte codes", FONT_6x8, OBD_BLACK, 1);
29 | obdWriteString(&obdCMD, 0,0,2,(char *)"written into memory", FONT_6x8, OBD_BLACK, 1);
30 | obdWriteString(&obdCMD, 0,0,3,(char *)"and then played back", FONT_6x8, OBD_BLACK, 1);
31 | obdEllipse(&obdCMD, 32, 48, 31, 15, OBD_BLACK, 1);
32 | obdEllipse(&obdCMD, 32, 48, 15, 12, OBD_WHITE, 1);
33 | obdDrawSprite(&obdCMD, ucSprite, 16, 16, 2, 96,40, 1);
34 | // obdEllipse(&obdCMD, 96, 48, 31, 15, 1, 1);
35 | // obdEllipse(&obdCMD, 96, 48, 15, 12, 0, 1);
36 | sprintf(szTemp, "%d bytes generated", obdGetCommandLen(&obdCMD));
37 | obdWriteString(&obd, 0,0,2, szTemp, FONT_6x8, OBD_BLACK, 1);
38 | delay(4000);
39 | obdExecCommands(ucBuffer, obdGetCommandLen(&obdCMD), &obd, 0);
40 | obdDumpBuffer(&obd, NULL);
41 | } /* setup() */
42 |
43 | void loop() {
44 | // put your main code here, to run repeatedly:
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/examples/oled_gfx_demo/oled_gfx_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay library GFX demo
3 | //
4 | #include
5 |
6 | // Use -1 for the Wire library default pins
7 | // or specify the pin numbers to use with the Wire library or bit banging on any GPIO pins
8 | // These are reversed because I did straight-through wiring for my SSD1306
9 | // and it has the 4-pin header as GND,VCC,SCL,SDA, but the GROVE connector is
10 | // GND,VCC,SDA,SCL
11 | // Even though I've wired the SDA/SCL pins backwards, the ESP32 can still use
12 | // the hardware I2C device because of the flexible pin definitions
13 | #define GROVE_SDA_PIN 32
14 | #define GROVE_SCL_PIN 26
15 | // Set this to -1 to disable or the GPIO pin number connected to the reset
16 | // line of your display if it requires an external reset
17 | #define RESET_PIN -1
18 | // let OneBitDisplay figure out the display address
19 | #define OLED_ADDR -1
20 | // don't rotate the display
21 | #define FLIP180 0
22 | // don't invert the display
23 | #define INVERT 0
24 | // Bit-Bang the I2C bus
25 | #define USE_HW_I2C 1
26 |
27 | // Change this if you're using different OLED displays
28 | #define MY_OLED OLED_128x64
29 | uint8_t ucBackBuffer[1024];
30 |
31 | // The OBDISP structure
32 | // There is no limit to the number of simultaneous displays which can be controlled by OneBitDisplay
33 | OBDISP obd;
34 |
35 | void setup() {
36 | char *msgs[] = {(char *)"SSD1306 @ 0x3C", (char *)"SSD1306 @ 0x3D",(char *)"SH1106 @ 0x3C",(char *)"SH1106 @ 0x3D"};
37 | int rc;
38 | // The I2C SDA/SCL pins set to -1 means to use the default Wire library
39 | // If pins were specified, they would be bit-banged in software
40 | // This isn't inferior to hw I2C and in fact allows you to go faster on certain CPUs
41 | // The reset pin is optional and I've only seen it needed on larger OLEDs (2.4")
42 | // that can be configured as either SPI or I2C
43 | //
44 | // obdI2CInit(OBDISP *, type, oled_addr, rotate180, invert, bWire, SDA_PIN, SCL_PIN, RESET_PIN, speed)
45 |
46 | rc = obdI2CInit(&obd, MY_OLED, OLED_ADDR, FLIP180, INVERT, USE_HW_I2C, GROVE_SDA_PIN, GROVE_SCL_PIN, RESET_PIN, 800000L); // use standard I2C bus at 400Khz
47 | if (rc != OLED_NOT_FOUND)
48 | {
49 | obdFill(&obd, OBD_WHITE, 1);
50 | obdWriteString(&obd, 0,0,0,msgs[rc], FONT_8x8, OBD_BLACK, 1);
51 | delay(2000);
52 | }
53 | else
54 | {
55 | while (1) {};
56 | }
57 | obdSetBackBuffer(&obd, ucBackBuffer);
58 | } /* setup() */
59 |
60 | #define DRAW_ELLIPSES
61 | #define DRAW_RECTS
62 |
63 | void loop() {
64 | int i, x, y, x2, y2, r1, r2;
65 | uint8_t ucColor;
66 |
67 | #ifdef DRAW_ELLIPSES
68 | obdFill(&obd, OBD_WHITE, 1);
69 | obdWriteString(&obd, 0, 0, 0, (char *)"Ellipses", FONT_8x8, OBD_BLACK, 1);
70 | delay(2000);
71 | obdFill(&obd, OBD_WHITE, 1);
72 | for (i=0; i<100; i++)
73 | {
74 | x = random(128);
75 | y = random(64);
76 | r1 = random(64);
77 | r2 = random(32);
78 | obdEllipse(&obd, x, y, r1, r2, OBD_BLACK, 0);
79 | obdDumpBuffer(&obd, NULL);
80 | }
81 | obdFill(&obd, OBD_WHITE, 1);
82 | obdWriteString(&obd, 0, 0, 0, (char *)"Filled Ellipses", FONT_8x8, OBD_BLACK, 1);
83 | delay(2000);
84 | obdFill(&obd, OBD_WHITE, 1);
85 | for (i=0; i<100; i++)
86 | {
87 | x = random(128);
88 | y = random(64);
89 | r1 = random(64);
90 | r2 = random(32);
91 | ucColor = random(2);
92 | obdEllipse(&obd, x, y, r1, r2, ucColor, 1);
93 | obdDumpBuffer(&obd, NULL);
94 | }
95 | #endif // DRAW_ELLIPSES
96 |
97 | #ifdef DRAW_RECTS
98 | obdFill(&obd, OBD_WHITE, 1);
99 | obdWriteString(&obd, 0, 0, 0, (char *)"Rectangles", FONT_8x8, OBD_BLACK, 1);
100 | delay(2000);
101 | obdFill(&obd, OBD_WHITE, 1);
102 | for (i=0; i<100; i++)
103 | {
104 | x = random(128);
105 | y = random(64);
106 | x2 = random(128);
107 | y2 = random(64);
108 | obdRectangle(&obd, x, y, x2, y2, OBD_BLACK, 0);
109 | obdDumpBuffer(&obd, NULL);
110 | }
111 | obdFill(&obd, OBD_WHITE, 1);
112 | obdWriteString(&obd, 0, 0, 0, (char *)"Filled Rects", FONT_8x8, OBD_BLACK, 1);
113 | delay(2000);
114 | obdFill(&obd, OBD_WHITE, 1);
115 | for (i=0; i<100; i++)
116 | {
117 | x = random(128);
118 | y = random(64);
119 | x2 = random(128);
120 | y2 = random(64);
121 | ucColor = random(2);
122 | obdRectangle(&obd, x, y, x2, y2, ucColor, 1);
123 | obdDumpBuffer(&obd, NULL);
124 | }
125 | #endif // DRAW_RECTS
126 |
127 | delay(4000);
128 | } /* loop() */
129 |
--------------------------------------------------------------------------------
/examples/onebit_lcd_test/onebit_lcd_test.ino:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | OBDISP obd;
4 | #define FLIP180 0
5 | #define INVERT 0
6 | #define BITBANG 1
7 | #define DC_PIN 22
8 | #define CS_PIN 3
9 | #define RESET_PIN 1
10 | #define MOSI_PIN 19
11 | #define CLK_PIN 23
12 | #define LED_PIN 18
13 | void setup() {
14 | // put your setup code here, to run once:
15 | //void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int bBitBang, int32_t iSpeed)
16 | obdSPIInit(&obd, LCD_UC1701, DC_PIN, CS_PIN, RESET_PIN, MOSI_PIN, CLK_PIN, LED_PIN, FLIP180, INVERT, BITBANG, 0);
17 | obdFill(&obd, OBD_WHITE, 1);
18 | }
19 |
20 | void loop() {
21 | // put your main code here, to run repeatedly:
22 | obdWriteString(&obd, 0, 0, 0, (char *)"Hello World!", FONT_8x8, OBD_BLACK, 1);
23 | while (1)
24 | {
25 |
26 | };
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/examples/pico_oled_13_demo/pico_oled_13_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay WaveShare Pico OLED 1.3 demo sketch
3 | // Written by Larry Bank 7/12/2022
4 | //
5 | #include
6 |
7 | ONE_BIT_DISPLAY lcd;
8 |
9 | #define PICO_FREQ 10000000
10 | #define PICO_CS 9
11 | #define PICO_LED -1
12 | #define PICO_RES 12
13 | #define PICO_DC 8
14 | #define PICO_MOSI 11
15 | #define PICO_SCK 10
16 |
17 | void setup() {
18 | // Initialize the library by telling it how the display is connected
19 | lcd.setSPIPins(PICO_CS, PICO_MOSI, PICO_SCK, PICO_DC, PICO_RES, PICO_LED);
20 | lcd.SPIbegin(OLED_64x128, PICO_FREQ);
21 |
22 | // Set the orientation to draw in the direction we want
23 | lcd.allocBuffer(); // allocate a back buffer and keep it internal to the class
24 | lcd.setRotation(90); // the panel is actually 64 wide by 128 tall, but oriented 90 right
25 | // To draw characters rotated 90/270 we need to allocate a back buffer
26 | lcd.fillScreen(OBD_WHITE); // 0 for EPDs is white (for OneBitDisplay)
27 | lcd.setFont(FONT_12x16); // use the internal stretched/smoothed font
28 | lcd.println("WaveShare");
29 | lcd.println("Pico-OLED");
30 | lcd.println("Demo");
31 | lcd.display(); // update
32 | } /* setup() */
33 |
34 | void loop() {
35 | int i;
36 | for (i=0; i<2047; i++) {
37 | int x, y;
38 | x = rand() & 127;
39 | y = rand() & 63;
40 | lcd.drawPixel(x, y, 1);
41 | if ((i & 3) == 3)
42 | lcd.display();
43 | }
44 | lcd.setFont(FONT_6x8);
45 | lcd.setScroll(true);
46 | lcd.fillScreen(OBD_WHITE);
47 | i = 0;
48 | while (1) {
49 | lcd.println(i++, DEC);
50 | lcd.display();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/examples/prop_font_demo/FreeSerif12pt7b.h:
--------------------------------------------------------------------------------
1 | const uint8_t FreeSerif12pt7bBitmaps[] PROGMEM = {
2 | 0xFF, 0xFE, 0xA8, 0x3F, 0xCF, 0x3C, 0xF3, 0x8A, 0x20, 0x0C, 0x40, 0xC4,
3 | 0x08, 0x40, 0x8C, 0x08, 0xC7, 0xFF, 0x18, 0x81, 0x88, 0x10, 0x81, 0x08,
4 | 0xFF, 0xE1, 0x18, 0x31, 0x03, 0x10, 0x31, 0x02, 0x10, 0x04, 0x07, 0xC6,
5 | 0x5B, 0x12, 0xC4, 0xB1, 0x0F, 0x41, 0xF0, 0x1E, 0x01, 0xE0, 0x58, 0x13,
6 | 0x84, 0xE1, 0x3C, 0x4F, 0x96, 0x3F, 0x01, 0x00, 0x00, 0x04, 0x03, 0x83,
7 | 0x03, 0x9F, 0x81, 0xC2, 0x20, 0x60, 0x90, 0x38, 0x24, 0x0C, 0x12, 0x03,
8 | 0x0D, 0x00, 0xC6, 0x47, 0x9E, 0x23, 0x10, 0x09, 0x84, 0x04, 0xE1, 0x03,
9 | 0x30, 0x40, 0x8C, 0x20, 0x43, 0x08, 0x10, 0xC4, 0x08, 0x1E, 0x00, 0x03,
10 | 0xC0, 0x02, 0x30, 0x03, 0x08, 0x01, 0x84, 0x00, 0xC4, 0x00, 0x7C, 0xF8,
11 | 0x1C, 0x38, 0x1E, 0x08, 0x33, 0x0C, 0x31, 0xC4, 0x10, 0x74, 0x18, 0x3A,
12 | 0x0C, 0x0E, 0x07, 0x03, 0x83, 0xC3, 0xE2, 0x7E, 0x3E, 0xFF, 0xA0, 0x04,
13 | 0x21, 0x08, 0x61, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC1, 0x04, 0x18, 0x20,
14 | 0x40, 0x81, 0x81, 0x02, 0x04, 0x18, 0x20, 0x83, 0x0C, 0x30, 0xC3, 0x0C,
15 | 0x30, 0x86, 0x10, 0x84, 0x20, 0x30, 0xB3, 0xD7, 0x54, 0x38, 0x7C, 0xD3,
16 | 0x30, 0x30, 0x10, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x41, 0xFF, 0xC1,
17 | 0x00, 0x20, 0x04, 0x00, 0x80, 0x10, 0x00, 0xDF, 0x95, 0x00, 0xFC, 0xFC,
18 | 0x06, 0x0C, 0x10, 0x60, 0xC1, 0x06, 0x0C, 0x10, 0x60, 0xC1, 0x06, 0x0C,
19 | 0x10, 0x60, 0xC0, 0x1E, 0x0C, 0xC6, 0x19, 0x86, 0xC0, 0xB0, 0x3C, 0x0F,
20 | 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E,
21 | 0x00, 0x11, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3,
22 | 0x0C, 0xFC, 0x1E, 0x18, 0xC4, 0x1A, 0x06, 0x01, 0x80, 0x60, 0x10, 0x0C,
23 | 0x02, 0x01, 0x00, 0xC0, 0x60, 0x30, 0x18, 0x1F, 0xF8, 0x1E, 0x18, 0xE8,
24 | 0x18, 0x06, 0x01, 0x00, 0x80, 0xF0, 0x7E, 0x03, 0xC0, 0x70, 0x0C, 0x03,
25 | 0x00, 0xC0, 0x6E, 0x11, 0xF8, 0x01, 0x00, 0xC0, 0x70, 0x2C, 0x0B, 0x04,
26 | 0xC2, 0x30, 0x8C, 0x43, 0x20, 0xC8, 0x33, 0xFF, 0x03, 0x00, 0xC0, 0x30,
27 | 0x0C, 0x00, 0x03, 0xF1, 0x00, 0x40, 0x18, 0x0F, 0x80, 0xF8, 0x0E, 0x01,
28 | 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x20, 0x1B, 0x8C, 0x7C, 0x00, 0x01,
29 | 0xC3, 0xC1, 0xC0, 0xC0, 0x70, 0x18, 0x0E, 0xF3, 0xCE, 0xC1, 0xF0, 0x3C,
30 | 0x0F, 0x03, 0xC0, 0xD8, 0x36, 0x08, 0xC6, 0x1E, 0x00, 0x3F, 0xD0, 0x38,
31 | 0x08, 0x06, 0x01, 0x80, 0x40, 0x10, 0x0C, 0x02, 0x00, 0x80, 0x20, 0x10,
32 | 0x04, 0x01, 0x00, 0x80, 0x20, 0x1F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0xF8,
33 | 0x67, 0x30, 0xF0, 0x1E, 0x09, 0xE6, 0x3B, 0x07, 0xC0, 0xF0, 0x3C, 0x0D,
34 | 0x86, 0x1F, 0x00, 0x1E, 0x08, 0xC6, 0x1B, 0x02, 0xC0, 0xF0, 0x3C, 0x0F,
35 | 0x03, 0xE0, 0xDC, 0x73, 0xEC, 0x06, 0x01, 0x80, 0xC0, 0x70, 0x38, 0x38,
36 | 0x18, 0x00, 0xFC, 0x00, 0x3F, 0xCC, 0xC0, 0x00, 0x00, 0x06, 0x77, 0x12,
37 | 0x40, 0x00, 0x00, 0x07, 0x01, 0xE0, 0x78, 0x1E, 0x07, 0x00, 0xC0, 0x0F,
38 | 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x00, 0x10, 0xFF, 0xF0, 0x00,
39 | 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x0E, 0x00, 0x3C, 0x00, 0xF0,
40 | 0x03, 0xC0, 0x0F, 0x00, 0x30, 0x0E, 0x07, 0x81, 0xE0, 0x78, 0x0E, 0x00,
41 | 0x00, 0x00, 0x7C, 0x86, 0x83, 0xC3, 0x03, 0x03, 0x06, 0x0C, 0x08, 0x08,
42 | 0x10, 0x10, 0x00, 0x00, 0x30, 0x30, 0x30, 0x03, 0xF0, 0x06, 0x06, 0x06,
43 | 0x00, 0x86, 0x00, 0x26, 0x0E, 0xD3, 0x0C, 0xC7, 0x0C, 0x63, 0x84, 0x31,
44 | 0xC6, 0x18, 0xE3, 0x08, 0x71, 0x8C, 0x4C, 0xC6, 0x46, 0x3D, 0xC1, 0x80,
45 | 0x00, 0x30, 0x10, 0x07, 0xF0, 0x00, 0x80, 0x00, 0x60, 0x00, 0x70, 0x00,
46 | 0x38, 0x00, 0x2E, 0x00, 0x13, 0x00, 0x19, 0xC0, 0x08, 0x60, 0x04, 0x38,
47 | 0x04, 0x0C, 0x03, 0xFF, 0x03, 0x03, 0x81, 0x00, 0xE1, 0x80, 0x70, 0xC0,
48 | 0x3D, 0xF0, 0x3F, 0xFF, 0x83, 0x0C, 0x30, 0x63, 0x06, 0x30, 0x63, 0x06,
49 | 0x30, 0xC3, 0xF0, 0x30, 0xE3, 0x06, 0x30, 0x33, 0x03, 0x30, 0x33, 0x07,
50 | 0x30, 0xEF, 0xFC, 0x07, 0xE2, 0x38, 0x3C, 0xC0, 0x3B, 0x00, 0x36, 0x00,
51 | 0x38, 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x03,
52 | 0x00, 0x06, 0x00, 0x06, 0x00, 0x47, 0x03, 0x03, 0xF8, 0xFF, 0xC0, 0x30,
53 | 0x78, 0x30, 0x1C, 0x30, 0x0E, 0x30, 0x06, 0x30, 0x03, 0x30, 0x03, 0x30,
54 | 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x06, 0x30, 0x06, 0x30,
55 | 0x0C, 0x30, 0x78, 0xFF, 0xC0, 0xFF, 0xFC, 0xC0, 0x33, 0x00, 0x4C, 0x00,
56 | 0x30, 0x00, 0xC0, 0x43, 0x03, 0x0F, 0xFC, 0x30, 0x30, 0xC0, 0x43, 0x00,
57 | 0x0C, 0x00, 0x30, 0x08, 0xC0, 0x23, 0x03, 0xBF, 0xFE, 0xFF, 0xFC, 0xC0,
58 | 0x33, 0x00, 0x4C, 0x00, 0x30, 0x00, 0xC0, 0x43, 0x03, 0x0F, 0xFC, 0x30,
59 | 0x30, 0xC0, 0x43, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x3F,
60 | 0x00, 0x07, 0xE4, 0x1C, 0x3C, 0x30, 0x0C, 0x60, 0x0C, 0x60, 0x04, 0xC0,
61 | 0x00, 0xC0, 0x00, 0xC0, 0x3F, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0x60,
62 | 0x0C, 0x60, 0x0C, 0x30, 0x0C, 0x1C, 0x1C, 0x07, 0xE0, 0xFC, 0x3F, 0x30,
63 | 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x3F,
64 | 0xFC, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30, 0x0C, 0x30,
65 | 0x0C, 0x30, 0x0C, 0xFC, 0x3F, 0xFC, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30,
66 | 0xC3, 0x0C, 0x30, 0xC3, 0x3F, 0x3F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
67 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xC8, 0xF0, 0xFC, 0xFE, 0x30,
68 | 0x38, 0x30, 0x20, 0x30, 0x40, 0x30, 0x80, 0x33, 0x00, 0x36, 0x00, 0x3E,
69 | 0x00, 0x37, 0x00, 0x33, 0x80, 0x31, 0xC0, 0x30, 0xE0, 0x30, 0x70, 0x30,
70 | 0x38, 0x30, 0x3C, 0xFC, 0x7F, 0xFC, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80,
71 | 0x03, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00,
72 | 0xC0, 0x01, 0x80, 0x03, 0x00, 0x26, 0x00, 0x8C, 0x07, 0x7F, 0xFE, 0xF8,
73 | 0x01, 0xE7, 0x00, 0x70, 0xE0, 0x0E, 0x1E, 0x03, 0xC2, 0xC0, 0x58, 0x5C,
74 | 0x1B, 0x09, 0x82, 0x61, 0x38, 0x4C, 0x27, 0x11, 0x84, 0x72, 0x30, 0x8E,
75 | 0xC6, 0x10, 0xD0, 0xC2, 0x1E, 0x18, 0x41, 0x83, 0x1C, 0x30, 0x67, 0xC4,
76 | 0x3F, 0xF0, 0x1F, 0x78, 0x0E, 0x3C, 0x04, 0x3E, 0x04, 0x2E, 0x04, 0x27,
77 | 0x04, 0x23, 0x84, 0x23, 0xC4, 0x21, 0xE4, 0x20, 0xE4, 0x20, 0x74, 0x20,
78 | 0x3C, 0x20, 0x1C, 0x20, 0x0C, 0x70, 0x0C, 0xF8, 0x04, 0x07, 0xC0, 0x30,
79 | 0x60, 0xC0, 0x63, 0x00, 0x66, 0x00, 0xD8, 0x00, 0xF0, 0x01, 0xE0, 0x03,
80 | 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x1B, 0x00, 0x66, 0x00, 0xC6, 0x03, 0x06,
81 | 0x0C, 0x03, 0xE0, 0xFF, 0x83, 0x0E, 0x30, 0x73, 0x03, 0x30, 0x33, 0x03,
82 | 0x30, 0x63, 0x0E, 0x3F, 0x83, 0x00, 0x30, 0x03, 0x00, 0x30, 0x03, 0x00,
83 | 0x30, 0x0F, 0xC0, 0x0F, 0xE0, 0x18, 0x30, 0x30, 0x18, 0x60, 0x0C, 0x60,
84 | 0x0C, 0xC0, 0x06, 0xC0, 0x06, 0xC0, 0x06, 0xC0, 0x06, 0xC0, 0x06, 0xC0,
85 | 0x06, 0x60, 0x0C, 0x60, 0x0C, 0x30, 0x18, 0x18, 0x30, 0x07, 0xC0, 0x03,
86 | 0xC0, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1F, 0xFF, 0x80, 0x61, 0xC0, 0xC1,
87 | 0xC1, 0x81, 0x83, 0x03, 0x06, 0x06, 0x0C, 0x1C, 0x18, 0x70, 0x3F, 0x80,
88 | 0x67, 0x00, 0xC7, 0x01, 0x8F, 0x03, 0x0F, 0x06, 0x0E, 0x0C, 0x0E, 0x7E,
89 | 0x0F, 0x1F, 0x46, 0x19, 0x81, 0x30, 0x27, 0x02, 0xF0, 0x0F, 0x00, 0xF8,
90 | 0x07, 0xC0, 0x38, 0x03, 0xC0, 0x34, 0x06, 0x80, 0xDC, 0x32, 0x7C, 0xFF,
91 | 0xFF, 0x86, 0x0E, 0x0C, 0x1C, 0x18, 0x10, 0x30, 0x00, 0x60, 0x00, 0xC0,
92 | 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x30, 0x00,
93 | 0x60, 0x00, 0xC0, 0x07, 0xE0, 0xFC, 0x1F, 0x30, 0x0E, 0x30, 0x04, 0x30,
94 | 0x04, 0x30, 0x04, 0x30, 0x04, 0x30, 0x04, 0x30, 0x04, 0x30, 0x04, 0x30,
95 | 0x04, 0x30, 0x04, 0x30, 0x04, 0x30, 0x04, 0x18, 0x08, 0x1C, 0x18, 0x07,
96 | 0xE0, 0xFE, 0x0F, 0x9C, 0x03, 0x0E, 0x01, 0x83, 0x00, 0x81, 0xC0, 0x40,
97 | 0x60, 0x40, 0x38, 0x20, 0x0C, 0x30, 0x07, 0x10, 0x01, 0x98, 0x00, 0xE8,
98 | 0x00, 0x34, 0x00, 0x1E, 0x00, 0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 0xFC,
99 | 0xFC, 0x3D, 0xE1, 0xC0, 0x63, 0x83, 0x01, 0x86, 0x0E, 0x04, 0x1C, 0x18,
100 | 0x10, 0x70, 0x70, 0x80, 0xC3, 0xC2, 0x03, 0x8B, 0x08, 0x06, 0x6E, 0x40,
101 | 0x1D, 0x19, 0x00, 0x74, 0x78, 0x00, 0xE1, 0xE0, 0x03, 0x83, 0x80, 0x0E,
102 | 0x0C, 0x00, 0x10, 0x10, 0x00, 0x40, 0x40, 0x7F, 0x1F, 0x9E, 0x03, 0x07,
103 | 0x03, 0x01, 0xC3, 0x00, 0x71, 0x00, 0x19, 0x00, 0x0F, 0x00, 0x03, 0x80,
104 | 0x01, 0xE0, 0x01, 0xB0, 0x01, 0x9C, 0x00, 0x87, 0x00, 0x81, 0xC0, 0x80,
105 | 0xE0, 0xC0, 0x79, 0xF8, 0x7F, 0xFE, 0x1F, 0x78, 0x0C, 0x38, 0x08, 0x1C,
106 | 0x18, 0x0E, 0x10, 0x06, 0x20, 0x07, 0x60, 0x03, 0xC0, 0x01, 0x80, 0x01,
107 | 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x07,
108 | 0xE0, 0x7F, 0xFB, 0x00, 0xC8, 0x07, 0x20, 0x38, 0x01, 0xC0, 0x07, 0x00,
109 | 0x38, 0x01, 0xC0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x38, 0x05,
110 | 0xC0, 0x3E, 0x01, 0xBF, 0xFE, 0xFE, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31,
111 | 0x8C, 0x63, 0x18, 0xC6, 0x31, 0xF0, 0xC1, 0x81, 0x03, 0x06, 0x04, 0x0C,
112 | 0x18, 0x10, 0x30, 0x60, 0x40, 0xC1, 0x81, 0x03, 0x06, 0xF8, 0xC6, 0x31,
113 | 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC7, 0xF0, 0x0C, 0x07,
114 | 0x01, 0x60, 0xD8, 0x23, 0x18, 0xC4, 0x1B, 0x06, 0x80, 0xC0, 0xFF, 0xF0,
115 | 0xC7, 0x0C, 0x30, 0x3E, 0x31, 0x8C, 0x30, 0x0C, 0x03, 0x07, 0xC6, 0x33,
116 | 0x0C, 0xC3, 0x31, 0xC7, 0xB8, 0x20, 0x38, 0x06, 0x01, 0x80, 0x60, 0x18,
117 | 0x06, 0xF1, 0xC6, 0x61, 0xD8, 0x36, 0x0D, 0x83, 0x60, 0xD8, 0x26, 0x19,
118 | 0x84, 0x3E, 0x00, 0x1E, 0x23, 0x63, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE1,
119 | 0x72, 0x3C, 0x00, 0x80, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x61, 0xD8, 0x8E,
120 | 0x61, 0xB0, 0x6C, 0x1B, 0x06, 0xC1, 0xB0, 0x6E, 0x19, 0xCE, 0x3D, 0xC0,
121 | 0x1E, 0x08, 0xE4, 0x1B, 0xFE, 0xC0, 0x30, 0x0C, 0x03, 0x81, 0x60, 0x9C,
122 | 0x41, 0xE0, 0x0F, 0x08, 0xC4, 0x06, 0x03, 0x01, 0x81, 0xF0, 0x60, 0x30,
123 | 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0xFC, 0x00, 0x1F, 0x03,
124 | 0x1F, 0x60, 0xC6, 0x0C, 0x60, 0xC3, 0x18, 0x1F, 0x02, 0x00, 0x40, 0x07,
125 | 0xFC, 0x40, 0x24, 0x02, 0xC0, 0x2C, 0x04, 0xE0, 0x83, 0xF0, 0x30, 0x1E,
126 | 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0D, 0xE1, 0xCE, 0x30, 0xC6, 0x18,
127 | 0xC3, 0x18, 0x63, 0x0C, 0x61, 0x8C, 0x31, 0x86, 0x79, 0xE0, 0x31, 0x80,
128 | 0x00, 0x09, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xDF, 0x0C, 0x30, 0x00, 0x00,
129 | 0x31, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xF2, 0xF0,
130 | 0x20, 0x1C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0xFB, 0x08, 0x62,
131 | 0x0C, 0x81, 0xE0, 0x3E, 0x06, 0xE0, 0xCE, 0x18, 0xC3, 0x0E, 0xF3, 0xE0,
132 | 0x13, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0xF8, 0xF7,
133 | 0x8F, 0x0E, 0x3C, 0xE3, 0x0C, 0x18, 0xC3, 0x06, 0x30, 0xC1, 0x8C, 0x30,
134 | 0x63, 0x0C, 0x18, 0xC3, 0x06, 0x30, 0xC1, 0x8C, 0x30, 0x67, 0x9E, 0x3C,
135 | 0xF7, 0x87, 0x18, 0xC3, 0x18, 0x63, 0x0C, 0x61, 0x8C, 0x31, 0x86, 0x30,
136 | 0xC6, 0x19, 0xE7, 0x80, 0x1E, 0x18, 0xE4, 0x1B, 0x03, 0xC0, 0xF0, 0x3C,
137 | 0x0F, 0x03, 0x60, 0x9C, 0x41, 0xE0, 0x77, 0x87, 0x18, 0xC3, 0x98, 0x33,
138 | 0x06, 0x60, 0xCC, 0x19, 0x83, 0x30, 0xC7, 0x10, 0xDC, 0x18, 0x03, 0x00,
139 | 0x60, 0x0C, 0x07, 0xE0, 0x1E, 0x8C, 0xE6, 0x1B, 0x06, 0xC1, 0xB0, 0x6C,
140 | 0x1B, 0x06, 0xE1, 0x98, 0xE3, 0xD8, 0x06, 0x01, 0x80, 0x60, 0x18, 0x1F,
141 | 0x37, 0x7B, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x7C, 0x7B,
142 | 0x0E, 0x1C, 0x1E, 0x0F, 0x07, 0xC3, 0x87, 0x8A, 0xE0, 0x21, 0x8F, 0x98,
143 | 0x61, 0x86, 0x18, 0x61, 0x86, 0x19, 0x38, 0xE3, 0x98, 0x66, 0x19, 0x86,
144 | 0x61, 0x98, 0x66, 0x19, 0x86, 0x61, 0x9C, 0xE3, 0xDC, 0xF8, 0xEE, 0x08,
145 | 0xC1, 0x18, 0x41, 0x88, 0x32, 0x03, 0x40, 0x68, 0x06, 0x00, 0xC0, 0x10,
146 | 0x00, 0xF3, 0xE7, 0x61, 0x83, 0x70, 0xC2, 0x30, 0xC2, 0x30, 0xC4, 0x19,
147 | 0x64, 0x19, 0x68, 0x0E, 0x38, 0x0E, 0x38, 0x0C, 0x30, 0x04, 0x10, 0xFB,
148 | 0xC6, 0x30, 0x64, 0x0F, 0x00, 0xC0, 0x0C, 0x03, 0xC0, 0x98, 0x21, 0x8C,
149 | 0x3B, 0xCF, 0x80, 0xF8, 0xEE, 0x08, 0xC1, 0x18, 0x41, 0x88, 0x31, 0x03,
150 | 0x40, 0x68, 0x06, 0x00, 0xC0, 0x08, 0x02, 0x00, 0x40, 0x10, 0x1E, 0x03,
151 | 0x80, 0x7F, 0x90, 0xE0, 0x30, 0x18, 0x0E, 0x03, 0x01, 0xC0, 0xE0, 0x30,
152 | 0x5C, 0x3F, 0xF8, 0x19, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0xB0, 0x63, 0x18,
153 | 0xC6, 0x31, 0x8C, 0x61, 0x80, 0xFF, 0xFF, 0x80, 0xC3, 0x18, 0xC6, 0x31,
154 | 0x8C, 0x63, 0x06, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xCC, 0x00, 0x38, 0x06,
155 | 0x62, 0x41, 0xC0};
156 |
157 | const GFXglyph FreeSerif12pt7bGlyphs[] PROGMEM = {
158 | {0, 0, 0, 6, 0, 1}, // 0x20 ' '
159 | {0, 2, 16, 8, 3, -15}, // 0x21 '!'
160 | {4, 6, 6, 10, 1, -15}, // 0x22 '"'
161 | {9, 12, 16, 12, 0, -15}, // 0x23 '#'
162 | {33, 10, 18, 12, 1, -16}, // 0x24 '$'
163 | {56, 18, 17, 20, 1, -16}, // 0x25 '%'
164 | {95, 17, 16, 19, 1, -15}, // 0x26 '&'
165 | {129, 2, 6, 5, 1, -15}, // 0x27 '''
166 | {131, 6, 20, 8, 1, -15}, // 0x28 '('
167 | {146, 6, 20, 8, 1, -15}, // 0x29 ')'
168 | {161, 8, 10, 12, 3, -14}, // 0x2A '*'
169 | {171, 11, 11, 14, 1, -10}, // 0x2B '+'
170 | {187, 3, 6, 6, 2, -2}, // 0x2C ','
171 | {190, 6, 1, 8, 1, -5}, // 0x2D '-'
172 | {191, 2, 3, 6, 2, -2}, // 0x2E '.'
173 | {192, 7, 17, 7, 0, -16}, // 0x2F '/'
174 | {207, 10, 17, 12, 1, -16}, // 0x30 '0'
175 | {229, 6, 17, 12, 3, -16}, // 0x31 '1'
176 | {242, 10, 15, 12, 1, -14}, // 0x32 '2'
177 | {261, 10, 16, 12, 1, -15}, // 0x33 '3'
178 | {281, 10, 16, 12, 1, -15}, // 0x34 '4'
179 | {301, 10, 17, 12, 1, -16}, // 0x35 '5'
180 | {323, 10, 17, 12, 1, -16}, // 0x36 '6'
181 | {345, 10, 16, 12, 0, -15}, // 0x37 '7'
182 | {365, 10, 17, 12, 1, -16}, // 0x38 '8'
183 | {387, 10, 18, 12, 1, -16}, // 0x39 '9'
184 | {410, 2, 12, 6, 2, -11}, // 0x3A ':'
185 | {413, 4, 15, 6, 2, -11}, // 0x3B ';'
186 | {421, 12, 13, 14, 1, -12}, // 0x3C '<'
187 | {441, 12, 6, 14, 1, -8}, // 0x3D '='
188 | {450, 12, 13, 14, 1, -11}, // 0x3E '>'
189 | {470, 8, 17, 11, 2, -16}, // 0x3F '?'
190 | {487, 17, 16, 21, 2, -15}, // 0x40 '@'
191 | {521, 17, 16, 17, 0, -15}, // 0x41 'A'
192 | {555, 12, 16, 15, 1, -15}, // 0x42 'B'
193 | {579, 15, 16, 16, 1, -15}, // 0x43 'C'
194 | {609, 16, 16, 17, 0, -15}, // 0x44 'D'
195 | {641, 14, 16, 15, 0, -15}, // 0x45 'E'
196 | {669, 14, 16, 14, 0, -15}, // 0x46 'F'
197 | {697, 16, 16, 17, 1, -15}, // 0x47 'G'
198 | {729, 16, 16, 17, 0, -15}, // 0x48 'H'
199 | {761, 6, 16, 8, 1, -15}, // 0x49 'I'
200 | {773, 8, 16, 9, 0, -15}, // 0x4A 'J'
201 | {789, 16, 16, 17, 1, -15}, // 0x4B 'K'
202 | {821, 15, 16, 15, 0, -15}, // 0x4C 'L'
203 | {851, 19, 16, 21, 1, -15}, // 0x4D 'M'
204 | {889, 16, 16, 17, 1, -15}, // 0x4E 'N'
205 | {921, 15, 16, 17, 1, -15}, // 0x4F 'O'
206 | {951, 12, 16, 14, 0, -15}, // 0x50 'P'
207 | {975, 16, 20, 17, 1, -15}, // 0x51 'Q'
208 | {1015, 15, 16, 16, 0, -15}, // 0x52 'R'
209 | {1045, 11, 16, 13, 0, -15}, // 0x53 'S'
210 | {1067, 15, 16, 15, 0, -15}, // 0x54 'T'
211 | {1097, 16, 16, 17, 1, -15}, // 0x55 'U'
212 | {1129, 17, 16, 17, 0, -15}, // 0x56 'V'
213 | {1163, 22, 16, 23, 0, -15}, // 0x57 'W'
214 | {1207, 17, 16, 17, 0, -15}, // 0x58 'X'
215 | {1241, 16, 16, 17, 0, -15}, // 0x59 'Y'
216 | {1273, 14, 16, 15, 1, -15}, // 0x5A 'Z'
217 | {1301, 5, 20, 8, 2, -15}, // 0x5B '['
218 | {1314, 7, 17, 7, 0, -16}, // 0x5C '\'
219 | {1329, 5, 20, 8, 1, -15}, // 0x5D ']'
220 | {1342, 10, 9, 11, 1, -15}, // 0x5E '^'
221 | {1354, 12, 1, 12, 0, 3}, // 0x5F '_'
222 | {1356, 5, 4, 6, 0, -15}, // 0x60 '`'
223 | {1359, 10, 11, 10, 1, -10}, // 0x61 'a'
224 | {1373, 10, 17, 12, 1, -16}, // 0x62 'b'
225 | {1395, 8, 11, 11, 1, -10}, // 0x63 'c'
226 | {1406, 10, 17, 12, 1, -16}, // 0x64 'd'
227 | {1428, 10, 11, 11, 1, -10}, // 0x65 'e'
228 | {1442, 9, 17, 9, 0, -16}, // 0x66 'f'
229 | {1462, 12, 16, 11, 0, -10}, // 0x67 'g'
230 | {1486, 11, 17, 12, 0, -16}, // 0x68 'h'
231 | {1510, 5, 16, 7, 0, -15}, // 0x69 'i'
232 | {1520, 6, 21, 8, 0, -15}, // 0x6A 'j'
233 | {1536, 11, 17, 12, 1, -16}, // 0x6B 'k'
234 | {1560, 5, 17, 6, 0, -16}, // 0x6C 'l'
235 | {1571, 18, 11, 19, 0, -10}, // 0x6D 'm'
236 | {1596, 11, 11, 12, 0, -10}, // 0x6E 'n'
237 | {1612, 10, 11, 12, 1, -10}, // 0x6F 'o'
238 | {1626, 11, 16, 12, 0, -10}, // 0x70 'p'
239 | {1648, 10, 16, 12, 1, -10}, // 0x71 'q'
240 | {1668, 8, 11, 8, 0, -10}, // 0x72 'r'
241 | {1679, 7, 11, 9, 1, -10}, // 0x73 's'
242 | {1689, 6, 13, 7, 1, -12}, // 0x74 't'
243 | {1699, 10, 11, 12, 1, -10}, // 0x75 'u'
244 | {1713, 11, 11, 11, 0, -10}, // 0x76 'v'
245 | {1729, 16, 11, 16, 0, -10}, // 0x77 'w'
246 | {1751, 11, 11, 12, 0, -10}, // 0x78 'x'
247 | {1767, 11, 16, 11, 0, -10}, // 0x79 'y'
248 | {1789, 10, 11, 10, 0, -10}, // 0x7A 'z'
249 | {1803, 5, 21, 12, 2, -16}, // 0x7B '{'
250 | {1817, 1, 17, 5, 2, -16}, // 0x7C '|'
251 | {1820, 5, 21, 12, 5, -15}, // 0x7D '}'
252 | {1834, 12, 3, 12, 0, -6}}; // 0x7E '~'
253 |
254 | const GFXfont FreeSerif12pt7b PROGMEM = {(uint8_t *)FreeSerif12pt7bBitmaps,
255 | (GFXglyph *)FreeSerif12pt7bGlyphs,
256 | 0x20, 0x7E, 29};
257 |
258 | // Approx. 2511 bytes
259 |
--------------------------------------------------------------------------------
/examples/prop_font_demo/prop_font_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay library simple demo
3 | //
4 | // Demonstrates how to initialize and use a few functions of the library
5 | // If your MCU has enough RAM, enable the backbuffer to see a demonstration
6 | // of the speed difference between drawing directly on the display versus
7 | // deferred rendering, followed by a "dump" of the memory to the display
8 | //
9 | #include
10 | #include "FreeSerif12pt7b.h"
11 |
12 | static uint8_t ucBackBuffer[1024];
13 |
14 | // Use -1 for the Wire library default pins
15 | // or specify the pin numbers to use with the Wire library or bit banging on any GPIO pins
16 | // These are the pin numbers for the M5Stack Atom Grove port I2C (reversed SDA/SCL for straight through wiring)
17 | #define SDA_PIN 32
18 | #define SCL_PIN 26
19 | // Set this to -1 to disable or the GPIO pin number connected to the reset
20 | // line of your display if it requires an external reset
21 | #define RESET_PIN -1
22 | // let OneBitDisplay figure out the display address
23 | #define OLED_ADDR -1
24 | // don't rotate the display
25 | #define FLIP180 0
26 | // don't invert the display
27 | #define INVERT 0
28 | // Bit-Bang the I2C bus
29 | #define USE_HW_I2C 1
30 |
31 | // Change these if you're using a different OLED display
32 | #define MY_OLED OLED_128x64
33 | #define OLED_WIDTH 128
34 | #define OLED_HEIGHT 64
35 | //#define MY_OLED OLED_64x32
36 | //#define OLED_WIDTH 64
37 | //#define OLED_HEIGHT 32
38 |
39 | OBDISP obd;
40 |
41 | void setup() {
42 | int rc;
43 | // The I2C SDA/SCL pins set to -1 means to use the default Wire library
44 | // If pins were specified, they would be bit-banged in software
45 | // This isn't inferior to hw I2C and in fact allows you to go faster on certain CPUs
46 | // The reset pin is optional and I've only seen it needed on larger OLEDs (2.4")
47 | // that can be configured as either SPI or I2C
48 | //
49 | // obdI2CInit(OBDISP *, type, oled_addr, rotate180, invert, bWire, SDA_PIN, SCL_PIN, RESET_PIN, speed)
50 |
51 | rc = obdI2CInit(&obd, MY_OLED, OLED_ADDR, FLIP180, INVERT, USE_HW_I2C, SDA_PIN, SCL_PIN, RESET_PIN, 800000L); // use standard I2C bus at 400Khz
52 | if (rc != OLED_NOT_FOUND)
53 | {
54 | char *msgs[] = {(char *)"SSD1306 @ 0x3C", (char *)"SSD1306 @ 0x3D",(char *)"SH1106 @ 0x3C",(char *)"SH1106 @ 0x3D"};
55 | obdFill(&obd, OBD_WHITE, 1);
56 | obdWriteString(&obd, 0,0,0,msgs[rc], FONT_8x8, OBD_BLACK, 1);
57 | obdSetBackBuffer(&obd, ucBackBuffer);
58 | delay(2000);
59 | }
60 | } /* setup() */
61 |
62 | void loop() {
63 | int y;
64 | char szTemp[32];
65 | unsigned long ms;
66 |
67 | obdFill(&obd, OBD_WHITE, 0);
68 | ms = micros();
69 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, 16, (char *)"Hello World",OBD_BLACK);
70 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, 16+FreeSerif12pt7b.yAdvance, (char *)"Fast Perf!", OBD_BLACK);
71 | ms = micros() - ms;
72 | obdDumpBuffer(&obd, NULL);
73 | sprintf(szTemp, "rendered in %d us", (int)ms);
74 | obdWriteString(&obd, 0,0,7,szTemp, FONT_6x8, OBD_BLACK, 1);
75 | delay(4000);
76 |
77 | for (y=-30; y<80; y++)
78 | {
79 | obdFill(&obd, OBD_BLACK, 0);
80 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, y, (char *)"Hello World", OBD_WHITE);
81 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, y+FreeSerif12pt7b.yAdvance, (char *)"Fast Perf!", OBD_WHITE);
82 | obdDumpBuffer(&obd, NULL);
83 | }
84 | for (y=79; y>=-30; y--)
85 | {
86 | obdFill(&obd, OBD_WHITE, 0);
87 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, y, (char *)"Hello World", OBD_BLACK);
88 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, y+FreeSerif12pt7b.yAdvance, (char *)"Fast Perf!", OBD_BLACK);
89 | obdDumpBuffer(&obd, NULL);
90 | }
91 | } /* loop() */
92 |
--------------------------------------------------------------------------------
/examples/sharp_memory_lcd/sharp_memory_lcd.ino:
--------------------------------------------------------------------------------
1 | // Sharp Memory LCD (144x168)
2 |
3 | #include
4 |
5 | OBDISP obd;
6 | #define FLIP180 0
7 | #define INVERT 0
8 | #define BITBANG 0
9 | #define DC_PIN -1
10 | #define CS_PIN 10
11 | #define RESET_PIN -1
12 | #define MOSI_PIN -1
13 | #define CLK_PIN -1
14 | #define LED_PIN -1
15 | uint8_t ucBackBuf[400*240/8];
16 |
17 | void setup() {
18 | obdSPIInit(&obd, SHARP_400x240, DC_PIN, CS_PIN, RESET_PIN, MOSI_PIN, CLK_PIN, LED_PIN, FLIP180, INVERT, BITBANG, 8000000L);
19 | obdSetBackBuffer(&obd, ucBackBuf);
20 | obdFill(&obd, OBD_WHITE, 0);
21 | obdWriteString(&obd,0,0,0,(char *)"Sharp Memory LCD Demo!", FONT_16x16, OBD_BLACK, 0);
22 | obdDumpBuffer(&obd, NULL);
23 | }
24 |
25 | void loop() {
26 | int i;
27 |
28 | while (1)
29 | {
30 | for (i=1; i<100; i++)
31 | {
32 | obdEllipse(&obd, 200, 140, i, i, OBD_BLACK, 0); // circle, not filled
33 | obdDumpBuffer(&obd, NULL);
34 | }
35 | for (i=99; i>=1; i--)
36 | {
37 | obdEllipse(&obd, 200, 140, i, i, OBD_WHITE, 0); // circle, not filled
38 | obdDumpBuffer(&obd, NULL);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/examples/simple_demo/simple_demo.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay library simple demo
3 | //
4 | // Demonstrates how to initialize and use a few functions of the library
5 | // If your MCU has enough RAM, enable the backbuffer to see a demonstration
6 | // of the speed difference between drawing directly on the display versus
7 | // deferred rendering, followed by a "dump" of the memory to the display
8 | //
9 | #include
10 |
11 | // if your system doesn't have enough RAM for a back buffer, comment out
12 | // this line (e.g. ATtiny85)
13 | #define USE_BACKBUFFER
14 |
15 | #ifdef USE_BACKBUFFER
16 | static uint8_t ucBackBuffer[1024];
17 | #else
18 | static uint8_t *ucBackBuffer = NULL;
19 | #endif
20 |
21 | // Use -1 for the Wire library default pins
22 | // or specify the pin numbers to use with the Wire library or bit banging on any GPIO pins
23 | // These are the pin numbers for the M5Stack Atom Grove port I2C (reversed SDA/SCL for straight through wiring)
24 | #define SDA_PIN -1
25 | #define SCL_PIN -1
26 | //#define SDA_PIN 32
27 | //#define SCL_PIN 26
28 | // Set this to -1 to disable or the GPIO pin number connected to the reset
29 | // line of your display if it requires an external reset
30 | #define RESET_PIN -1
31 | // let OneBitDisplay figure out the display address
32 | #define OLED_ADDR -1
33 | // don't rotate the display
34 | #define FLIP180 0
35 | // don't invert the display
36 | #define INVERT 0
37 | // Bit-Bang the I2C bus
38 | #define USE_HW_I2C 1
39 |
40 | // Change these if you're using a different OLED display
41 | #define MY_OLED OLED_128x64
42 | #define OLED_WIDTH 128
43 | #define OLED_HEIGHT 64
44 | //#define MY_OLED OLED_64x32
45 | //#define OLED_WIDTH 64
46 | //#define OLED_HEIGHT 32
47 |
48 | OBDISP obd;
49 |
50 | void setup() {
51 | int rc;
52 | // The I2C SDA/SCL pins set to -1 means to use the default Wire library
53 | // If pins were specified, they would be bit-banged in software
54 | // This isn't inferior to hw I2C and in fact allows you to go faster on certain CPUs
55 | // The reset pin is optional and I've only seen it needed on larger OLEDs (2.4")
56 | // that can be configured as either SPI or I2C
57 | //
58 | // obdI2CInit(OBDISP *, type, oled_addr, rotate180, invert, bWire, SDA_PIN, SCL_PIN, RESET_PIN, speed)
59 |
60 | rc = obdI2CInit(&obd, MY_OLED, OLED_ADDR, FLIP180, INVERT, USE_HW_I2C, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); // use standard I2C bus at 400Khz
61 | if (rc != OLED_NOT_FOUND)
62 | {
63 | char *msgs[] = {(char *)"SSD1306 @ 0x3C", (char *)"SSD1306 @ 0x3D",(char *)"SH1106 @ 0x3C",(char *)"SH1106 @ 0x3D"};
64 | obdFill(&obd, OBD_WHITE, 1);
65 | obdWriteString(&obd, 0,0,0,msgs[rc], FONT_8x8, OBD_BLACK, 1);
66 | obdSetBackBuffer(&obd, ucBackBuffer);
67 | delay(2000);
68 | }
69 | } /* setup() */
70 |
71 | void loop() {
72 | // put your main code here, to run repeatedly:
73 | int i, x, y;
74 | char szTemp[32];
75 | unsigned long ms;
76 |
77 | obdFill(&obd, OBD_WHITE, 1);
78 | obdWriteString(&obd, 0,28,0,(char *)"OLED Demo", FONT_8x8, OBD_BLACK, 1);
79 | obdWriteString(&obd, 0,0,8,(char *)"Written by Larry Bank", FONT_6x8, OBD_WHITE, 1);
80 | obdWriteString(&obd, 0,0,24,(char *)"**Demo**", FONT_16x32, OBD_BLACK, 1);
81 | delay(2000);
82 |
83 | // Pixel and line functions won't work without a back buffer
84 | #ifdef USE_BACKBUFFER
85 | obdFill(&obd, OBD_WHITE, 1);
86 | obdWriteString(&obd, 0,0,0,(char *)"Backbuffer Test", FONT_8x8,OBD_BLACK,1);
87 | obdWriteString(&obd, 0,0,8,(char *)"3000 Random dots", FONT_8x8,OBD_BLACK,1);
88 | delay(2000);
89 | obdFill(&obd, OBD_WHITE,1);
90 | ms = millis();
91 | for (i=0; i<3000; i++)
92 | {
93 | x = random(OLED_WIDTH);
94 | y = random(OLED_HEIGHT);
95 | obdSetPixel(&obd, x, y, 1, 1);
96 | }
97 | ms = millis() - ms;
98 | sprintf(szTemp, "%dms", (int)ms);
99 | obdWriteString(&obd, 0,0,0,szTemp, FONT_8x8, OBD_BLACK, 1);
100 | obdWriteString(&obd, 0,0,8,(char *)"Without backbuffer", FONT_6x8,OBD_BLACK,1);
101 | delay(2000);
102 | obdFill(&obd, OBD_WHITE,1);
103 | ms = millis();
104 | for (i=0; i<3000; i++)
105 | {
106 | x = random(OLED_WIDTH);
107 | y = random(OLED_HEIGHT);
108 | obdSetPixel(&obd, x, y, 1, 0);
109 | }
110 | obdDumpBuffer(&obd, NULL);
111 | ms = millis() - ms;
112 | sprintf(szTemp, "%dms", (int)ms);
113 | obdWriteString(&obd, 0,0,0,szTemp, FONT_8x8, OBD_BLACK, 1);
114 | obdWriteString(&obd, 0,0,8,(char *)"With backbuffer", FONT_6x8,OBD_BLACK,1);
115 | delay(2000);
116 | obdFill(&obd, OBD_WHITE, 1);
117 | obdWriteString(&obd, 0,0,0,(char *)"Backbuffer Test", FONT_8x8,OBD_BLACK,1);
118 | obdWriteString(&obd, 0,0,8,(char *)"96 lines", FONT_8x8,OBD_BLACK,1);
119 | delay(2000);
120 | ms = millis();
121 | for (x=0; x
6 |
7 | OBDISP obd;
8 | #define SDA_PIN -1
9 | #define SCL_PIN -1
10 | // no reset pin needed
11 | #define RESET_PIN -1
12 | // let OneBitDisplay find the address of our display
13 | #define OLED_ADDR -1
14 | #define FLIP180 0
15 | #define INVERT 0
16 | // Use the default Wire library
17 | #define USE_HW_I2C 1
18 | void setup()
19 | {
20 | int rc;
21 | rc = obdI2CInit(&obd, OLED_128x64, OLED_ADDR, FLIP180, INVERT, USE_HW_I2C, SDA_PIN, SCL_PIN, RESET_PIN, 400000L); // Standard HW I2C bus at 400Khz
22 |
23 | if (rc != OLED_NOT_FOUND)
24 | {
25 | char *msgs[] =
26 | {
27 | (char *)"SSD1306 @ 0x3C",
28 | (char *)"SSD1306 @ 0x3D",
29 | (char *)"SH1106 @ 0x3C",
30 | (char *)"SH1106 @ 0x3D"
31 | };
32 |
33 | obdFill(&obd, 0, 1);
34 | obdWriteString(&obd, 0, 0, 0, (char *)"OLED found:", FONT_8x8, 0, 1);
35 | obdWriteString(&obd, 0, 10, 2, msgs[rc], FONT_8x8, 0, 1);
36 | delay(3000);
37 | }
38 | }
39 |
40 | void loop()
41 | {
42 | int i, x, y;
43 |
44 | obdFill(&obd, 0, 1);
45 | obdWriteString(&obd, 0, 28, 0,(char *)"OLED Demo", FONT_8x8, 0, 1);
46 | obdWriteString(&obd, 0, 0, 1,(char *)"Written by Larry Bank", FONT_6x8, 1, 1);
47 | obdWriteString(&obd, 0, 0, 3,(char *)"**Demo**", FONT_16x16, 0, 1);
48 | obdWriteString(&obd, 0, 9, 6,(char *)"for AVR", FONT_16x16, 0, 1);
49 |
50 | delay(2000);
51 | obdFill(&obd, 0, 1);
52 |
53 | for (i = 0; i < 1000; i++)
54 | {
55 | x = random(128);
56 | y = random(64);
57 | obdSetPixel(&obd, x, y, 1, 1);
58 | }
59 |
60 | delay(2000);
61 | }
62 |
--------------------------------------------------------------------------------
/examples/tiff_on_avr/bart_1bpp.h:
--------------------------------------------------------------------------------
1 | //
2 | // bart_1bpp
3 | // Data size = 860 bytes
4 | //
5 | // TIFF, Compression=G4, Size: 104 x 285, 1-Bpp
6 | //
7 | // for non-Arduino builds...
8 | #ifndef PROGMEM
9 | #define PROGMEM
10 | #endif
11 | const uint8_t bart_1bpp[] PROGMEM = {
12 | 0x4d,0x4d,0x00,0x2a,0x00,0x00,0x02,0xba,0x26,0xa0,0x78,0x36,0x7f,0xff,0xc8,0x35,
13 | 0x0e,0x41,0x81,0xf2,0x0d,0xdd,0x48,0xae,0x9f,0x76,0xbe,0x41,0x07,0xb4,0xd3,0x52,
14 | 0x4f,0xda,0xfa,0x69,0x92,0x7e,0xed,0x34,0xf5,0x5e,0xd3,0x8d,0x57,0xee,0x26,0x11,
15 | 0x9a,0x13,0x09,0xda,0x92,0x1f,0x89,0x8e,0xd6,0xc6,0x9a,0xea,0xd3,0x4d,0x4f,0x7d,
16 | 0x3e,0x6d,0x27,0xea,0xa3,0x5f,0x7a,0x69,0xa7,0x67,0x97,0x22,0x8f,0xee,0xe3,0xd7,
17 | 0x1a,0xfb,0x42,0x35,0x58,0x5f,0x11,0x6a,0x79,0x57,0xaa,0x6a,0xc2,0x5f,0xf1,0xf8,
18 | 0xd7,0xf4,0xce,0x25,0xe3,0x5f,0xc2,0x5f,0x1f,0xeb,0xd7,0x5f,0xeb,0xff,0x5f,0xfe,
19 | 0xbf,0xff,0xa5,0xfa,0xff,0xff,0x5f,0xfe,0xbf,0xff,0x55,0xfa,0xff,0xff,0x5f,0xff,
20 | 0xd6,0xb4,0xbd,0x2f,0xa2,0x0d,0x23,0xaf,0x44,0xfc,0x86,0x08,0xfc,0x10,0x30,0x41,
21 | 0xfc,0x43,0x41,0xd7,0x27,0x98,0x46,0x62,0xbf,0x9e,0x08,0xd0,0x20,0xdf,0xd0,0x62,
22 | 0x10,0x6d,0x74,0x13,0x4d,0xfa,0x4d,0x3f,0xf4,0xdd,0x69,0x53,0xfe,0xb7,0xe9,0x53,
23 | 0xfe,0x44,0xce,0xff,0x4d,0x75,0xeb,0xa2,0x0b,0xdb,0xff,0xe9,0xff,0xfa,0x7f,0xdf,
24 | 0xfd,0x7b,0x5f,0xfe,0x3d,0x7e,0xe5,0x91,0x6d,0x2f,0xda,0x18,0xfe,0xc7,0x5f,0x33,
25 | 0x1b,0x5f,0x61,0x10,0xc5,0xeb,0xbb,0x69,0x7d,0x36,0x95,0xfd,0xa8,0x4f,0xb6,0xd2,
26 | 0x4f,0xdb,0x4a,0x6f,0x7d,0xb0,0x60,0x94,0x20,0xfd,0xb1,0x42,0x55,0x39,0x38,0x30,
27 | 0x12,0xf3,0x50,0x20,0x4b,0xcc,0x6c,0x82,0xf9,0xf8,0x34,0x33,0xeb,0xe2,0x0f,0xfb,
28 | 0x4b,0xa8,0x7f,0x20,0x51,0x69,0x75,0x15,0xed,0x6a,0x18,0x5e,0xd7,0x5f,0xde,0xbf,
29 | 0xfd,0x7d,0x90,0x57,0xcf,0xb0,0x9f,0xb0,0xc2,0x6f,0xb6,0x11,0x9a,0xf8,0x60,0xc8,
30 | 0x34,0x1d,0xfd,0x83,0x20,0xdc,0x31,0xf0,0xc4,0x2f,0x06,0x44,0x80,0xbf,0x06,0x49,
31 | 0x86,0x67,0x20,0xdf,0x5b,0xc8,0x69,0x67,0xb3,0x30,0xcd,0xed,0xde,0xdd,0xe0,0xeb,
32 | 0x86,0xc2,0x7e,0x83,0xdc,0x20,0xfc,0x13,0xf2,0x09,0xa9,0x3c,0xd0,0x84,0x1b,0xd1,
33 | 0x50,0x93,0x7a,0x25,0xcd,0x37,0xa3,0x81,0xb1,0x37,0xaa,0x5e,0xbb,0x7d,0x25,0xeb,
34 | 0xbe,0xa9,0x5e,0x96,0xfc,0xda,0xd7,0xa4,0xbd,0xfe,0xbe,0x95,0x6f,0xd7,0x5e,0xab,
35 | 0xff,0xfe,0x97,0xff,0x4b,0xfa,0xc9,0x3f,0xb1,0xc5,0xef,0xf5,0x33,0x07,0xfb,0x87,
36 | 0xf0,0x78,0x5a,0xf5,0xff,0xcc,0x25,0xaf,0xff,0xc7,0xfa,0xd7,0xff,0xcc,0x2f,0xff,
37 | 0xfc,0x57,0xff,0x7a,0xf3,0x09,0xf5,0xf7,0xd7,0xbf,0x5e,0xdf,0x5e,0xff,0xf7,0xa4,
38 | 0xbb,0x7d,0x6b,0xeb,0xed,0xf5,0xfe,0xbe,0xfd,0x55,0x5e,0xbe,0xff,0xf7,0xd7,0xfa,
39 | 0xfb,0xfe,0xb7,0xd2,0xff,0xfb,0xeb,0xff,0xf5,0x7f,0x5f,0xfe,0xfd,0x7f,0xde,0xbf,
40 | 0x0d,0x7b,0xd9,0x40,0x65,0x7f,0x65,0x40,0x7d,0x7b,0x15,0x1e,0xcd,0xaf,0xb9,0x0e,
41 | 0x0f,0xec,0x86,0x55,0x10,0x2d,0xbb,0x9b,0x0b,0xf9,0x88,0x3a,0xfb,0xd8,0x3d,0x2d,
42 | 0x3c,0x30,0x7d,0x77,0x86,0x35,0xef,0x0c,0x34,0xbb,0xc1,0xb5,0xe6,0xd3,0xc8,0x11,
43 | 0xc9,0x78,0x6e,0xc6,0xbd,0x87,0xd7,0xb6,0xff,0xb0,0xef,0xf0,0xc3,0x6f,0xf6,0x0e,
44 | 0xff,0x0c,0xa0,0x7f,0xc1,0x86,0x3f,0x61,0xfd,0x86,0x41,0x8b,0xf6,0x0f,0xf6,0x3f,
45 | 0x0e,0x17,0x21,0xaa,0x20,0x17,0x06,0x41,0x83,0x0b,0x98,0x08,0x21,0x78,0x64,0x0c,
46 | 0x33,0xf6,0x61,0x12,0xe0,0xa3,0xf3,0x60,0x9f,0xfa,0xff,0xff,0xff,0xff,0xf7,0xff,
47 | 0xff,0xff,0xff,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xfd,0x06,0xbf,
48 | 0xa1,0xfe,0x9f,0xf3,0x77,0xfc,0x8a,0xe4,0xa7,0xe1,0x06,0x28,0x19,0x29,0xe8,0x86,
49 | 0x43,0xd1,0xc4,0x2f,0x09,0x06,0x6b,0x46,0x19,0x47,0xd0,0x44,0x25,0x62,0xba,0x40,
50 | 0xc1,0x84,0xf4,0xa6,0xe1,0xf5,0x48,0xf2,0x23,0x13,0xd2,0xd0,0x41,0x84,0xfa,0x5a,
51 | 0x44,0x3d,0xde,0x94,0x50,0xbf,0xb5,0x7a,0x55,0xe9,0x24,0xfc,0x3a,0xf4,0x0d,0x2b,
52 | 0xe5,0x3b,0x4f,0xcc,0x21,0xfd,0x96,0x30,0x27,0xc1,0x91,0x86,0x0b,0xca,0x02,0x9a,
53 | 0x03,0x7e,0x18,0x9d,0x45,0x29,0xd3,0xc1,0x88,0x55,0x90,0x68,0xa8,0xc0,0x40,0xb9,
54 | 0x0d,0x64,0x12,0xac,0x17,0x21,0xb6,0x71,0x31,0x1b,0x10,0x58,0x30,0x58,0x32,0x90,
55 | 0x32,0xe4,0x16,0x03,0xc7,0xff,0xfe,0x00,0x20,0x02,0x00,0x0d,0x01,0x00,0x00,0x03,
56 | 0x00,0x00,0x00,0x01,0x00,0x68,0x00,0x00,0x01,0x01,0x00,0x03,0x00,0x00,0x00,0x01,
57 | 0x01,0x1d,0x00,0x00,0x01,0x02,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
58 | 0x01,0x03,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x04,0x00,0x00,0x01,0x06,0x00,0x03,
59 | 0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x0a,0x00,0x03,0x00,0x00,0x00,0x01,
60 | 0x00,0x01,0x00,0x00,0x01,0x11,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,
61 | 0x01,0x12,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x15,0x00,0x03,
62 | 0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x16,0x00,0x03,0x00,0x00,0x00,0x01,
63 | 0x01,0x1d,0x00,0x00,0x01,0x17,0x00,0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x02,0xb2,
64 | 0x01,0x1c,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x29,0x00,0x03,
65 | 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00};
66 |
--------------------------------------------------------------------------------
/examples/tiff_on_avr/tiff_on_avr.ino:
--------------------------------------------------------------------------------
1 | //
2 | // This demo sketch shows something that's normally very challenging
3 | // to accomplish on a resource-constrained 8-bit MCU (Arduino Uno)
4 | // The sketch has 2 TIFF G4 images (1-bit highly compressed)
5 | // stored in FLASH that are decoded directly into the e-paper's
6 | // frame buffer. This allows this particular demo to work with images
7 | // that normally would not fit in the available RAM (2K). One limitation
8 | // of this method is that the image can only be written in the native
9 | // memory direction of the e-paper panel. In this case, the 128x296 EPD
10 | // is oriented with the bytes in portrait orientation, MSB on the left.
11 | //
12 | // The G4 library has size limits imposed (200 pixels wide by N tall) to be
13 | // able to use only 1K of RAM to accomplish this task. The OneBitDisplay
14 | // library includes code specifically to allow working with e-paper
15 | // displays without a local buffer to hold the pixels
16 | //
17 | // If you disable the Serial print statements, there will be
18 | // plenty of FLASH space left on the UNO to hold other code/data
19 | //
20 | // Written by Larry Bank Oct 13, 2022
21 | //
22 | #include
23 | #include
24 | #include "uno_bw.h"
25 | #include "bart_1bpp.h"
26 |
27 | ONE_BIT_DISPLAY obd;
28 | TIFFG4 tiff;
29 |
30 | //
31 | // These defines are for the Waveshare Arduino UNO e-paper shield
32 | // please change them to suit your hardware
33 | //
34 | #define EPD_FREQ 2000000
35 | #define EPD_CS 10
36 | #define EPD_DC 9
37 | #define EPD_BUSY 7
38 | #define EPD_RES 8
39 | // Values of -1 here indicate that the default system pin numbers should be used
40 | #define EPD_MOSI -1
41 | #define EPD_SCK -1
42 | // This is a 2.9" 128x296 e-paper with the SSD16xx controller chip
43 | // The panel I used for this demo has "HINK-E029A27-A0"
44 | #define EPD_TYPE EPD293_128x296
45 |
46 | // This is the callback function you write to receive each line
47 | // of decoded pixels as they're being decoded
48 | void TIFFDraw(TIFFDRAW *pDraw)
49 | {
50 | // Serial.print("TIFFDraw line = ");
51 | // Serial.println(pDraw->y, DEC);
52 | if (pDraw->y == 0) { // When you receive the first line, you can set the memory window parameters for the e-paper
53 | obd.setPosition(0, 0, tiff.getWidth(), tiff.getHeight());
54 | }
55 | // invert the pixels for EPD (black = 1)
56 | for (int i=0; i<(pDraw->iWidth/8); i++) {
57 | pDraw->pPixels[i] = ~pDraw->pPixels[i];
58 | }
59 | obd.pushPixels((uint8_t *)pDraw->pPixels, (pDraw->iWidth/8)); // send this line of pixels to the EPD; the destination address will automatically increment
60 | } /* TIFFDraw() */
61 |
62 | void setup() {
63 | Serial.begin(115200);
64 | Serial.println("Starting");
65 | obd.setSPIPins(EPD_CS, EPD_MOSI, EPD_SCK, EPD_DC, EPD_RES, EPD_BUSY);
66 | obd.SPIbegin(EPD_TYPE, EPD_FREQ); // initialize OneBitDisplay for this e-paper panel
67 | } /* setup() */
68 |
69 | //
70 | // This function will decode a TIFF image that is stored in FLASH
71 | // given the starting offset and size of the data
72 | //
73 | void decodeImage(const uint8_t *pData, size_t size)
74 | {
75 | if (tiff.openTIFF((uint8_t *)pData, (int)size, TIFFDraw))
76 | {
77 | Serial.print("TIFF opened, size = ");
78 | Serial.print(tiff.getWidth(), DEC);
79 | Serial.print("x");
80 | Serial.println(tiff.getHeight(), DEC);
81 | tiff.decode();
82 | tiff.close();
83 | Serial.println("Finished decoding");
84 | } else {
85 | Serial.print("Error opening TIFF = ");
86 | Serial.println(tiff.getLastError(), DEC);
87 | }
88 | } /* decodeImage() */
89 |
90 | void loop() {
91 |
92 | obd.fillScreen(OBD_WHITE); // clear the EPD's internal RAM to white
93 | obd.setTextColor(OBD_BLACK, OBD_WHITE); // use the correct EPD memory plane (0)
94 | decodeImage(uno_bw, sizeof(uno_bw));
95 | obd.display(); // this causes the EPD to do a full refresh
96 | obd.fillScreen(OBD_WHITE); // prepare the second image by clearing the EPD memory to white again
97 | decodeImage(bart_1bpp, sizeof(bart_1bpp));
98 | obd.display(); // show the Bart image
99 | obd.fillScreen(OBD_WHITE);
100 | obd.display(); // finish by clearing the EPD to white again
101 | while (1)
102 | {};
103 | } /* loop() */
104 |
--------------------------------------------------------------------------------
/examples/tiff_on_avr/uno_bw.h:
--------------------------------------------------------------------------------
1 | //
2 | // uno_bw
3 | // Data size = 532 bytes
4 | //
5 | // TIFF, Compression=G4, Size: 128 x 166, 1-Bpp
6 | //
7 | // for non-Arduino builds...
8 | #ifndef PROGMEM
9 | #define PROGMEM
10 | #endif
11 | const uint8_t uno_bw[] PROGMEM = {
12 | 0x4d,0x4d,0x00,0x2a,0x00,0x00,0x01,0x72,0x26,0xa1,0x90,0x1b,0xff,0xf2,0x07,0x85,
13 | 0x07,0xae,0x9f,0xff,0xff,0xe4,0x36,0x69,0xe1,0x07,0xf7,0xff,0xff,0xf9,0x09,0xd9,
14 | 0x80,0xf3,0x27,0xd3,0xd3,0xd3,0xd7,0x5d,0x7f,0xff,0xf7,0xdf,0xae,0xbf,0xf6,0xb0,
15 | 0xff,0x8e,0x43,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfb,0xff,
16 | 0xd7,0xfb,0x5f,0xe3,0xff,0xff,0xfd,0x7e,0xd7,0xe3,0xff,0xff,0xff,0xff,0xff,0xff,
17 | 0xff,0xff,0xff,0xff,0xe4,0x0f,0x0d,0xd1,0xf8,0x41,0xfe,0x9f,0xe9,0xfe,0x9f,0xe8,
18 | 0x9e,0x7f,0xa0,0x40,0xdf,0xf0,0x83,0xfe,0x93,0x7f,0xff,0xf4,0xdf,0xea,0x47,0x1f,
19 | 0xfe,0xff,0x90,0xcf,0xa7,0xff,0xa7,0xff,0xff,0xff,0x82,0x23,0xf3,0x8f,0xff,0xe1,
20 | 0x3d,0x07,0xeb,0xff,0xff,0xff,0xf4,0xdf,0xfe,0x38,0xe2,0x97,0xfd,0xff,0x90,0x4b,
21 | 0xca,0xb7,0x4b,0xff,0xed,0x7f,0xfa,0x6d,0x2f,0xc7,0x16,0x1a,0xff,0xb6,0x12,0xfc,
22 | 0x82,0x5e,0x55,0xc5,0x7f,0xf8,0x6b,0xff,0xd8,0x5f,0x8e,0x2d,0x7f,0x84,0x1f,0xe4,
23 | 0x12,0xf2,0xad,0x3f,0xff,0x4f,0xff,0xd1,0xa4,0xff,0x1c,0x50,0x41,0xbf,0xfa,0x7f,
24 | 0xc8,0x25,0xe5,0x42,0x4d,0xff,0xf7,0x4f,0xff,0xe9,0x37,0xfb,0x5b,0x5f,0xf8,0xe3,
25 | 0x44,0x70,0xdf,0xe4,0x1d,0xf2,0xa1,0x7f,0xf4,0xfb,0xf7,0xff,0xfc,0x10,0x3f,0xf6,
26 | 0xba,0xff,0xf1,0xc7,0xff,0xc8,0x3b,0xe5,0x46,0x0c,0x17,0xfa,0x7d,0xfa,0xff,0xff,
27 | 0xff,0xb5,0xd3,0x63,0x5f,0x8e,0x3a,0xfe,0x41,0xdf,0x2a,0x1b,0x5f,0xd3,0xee,0xd2,
28 | 0xff,0xf6,0x18,0x4b,0xf6,0xba,0x63,0xfc,0x71,0xaf,0xc8,0x3b,0xe7,0x70,0xc2,0xfd,
29 | 0x3d,0x36,0xbf,0xfc,0x30,0xbf,0xfa,0x06,0x0b,0xf1,0xc4,0x7f,0xff,0x20,0x97,0x95,
30 | 0x7f,0xff,0xff,0xff,0x8e,0x3f,0xff,0x90,0x4b,0xca,0xbf,0xff,0xff,0xff,0xc7,0x1f,
31 | 0xff,0xc8,0x25,0xe5,0x47,0xff,0x7f,0xff,0xf8,0xe3,0xff,0xf9,0x04,0xbc,0xa8,0xff,
32 | 0xef,0xff,0xff,0x6b,0x6b,0xf1,0xc7,0xf2,0x0e,0xf9,0x51,0xfa,0x7d,0xff,0xcf,0x3f,
33 | 0xfb,0x54,0xf5,0xf8,0xf8,0xff,0x1f,0xf5,0xf8,0x90,0xda,0x02,0xf5,0xf0,0xbd,0xaf,
34 | 0x6b,0xb1,0x5b,0x5b,0x3b,0x4e,0x1a,0x76,0xb6,0xb6,0xb6,0xb1,0xff,0xe0,0x02,0x00,
35 | 0x20,0x00,0x00,0x0d,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x80,0x00,0x00,
36 | 0x01,0x01,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x01,0x02,0x00,0x03,
37 | 0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x03,0x00,0x03,0x00,0x00,0x00,0x01,
38 | 0x00,0x04,0x00,0x00,0x01,0x06,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
39 | 0x01,0x0a,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x11,0x00,0x04,
40 | 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x01,0x12,0x00,0x03,0x00,0x00,0x00,0x01,
41 | 0x00,0x01,0x00,0x00,0x01,0x15,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
42 | 0x01,0x16,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0xa6,0x00,0x00,0x01,0x17,0x00,0x04,
43 | 0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x69,0x01,0x1c,0x00,0x03,0x00,0x00,0x00,0x01,
44 | 0x00,0x01,0x00,0x00,0x01,0x29,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,
45 | 0x00,0x00,0x00,0x00};
46 |
--------------------------------------------------------------------------------
/examples/uc1609_test/uc1609.h:
--------------------------------------------------------------------------------
1 | //
2 | // uc1609
3 | //
4 | const uint8_t uc1609[] PROGMEM = { 0x42,0x4d,0x82,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x00,0x00,0x00,0x6c,0x00,
5 | 0x00,0x00,0xc0,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
6 | 0x00,0x00,0x00,0x06,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
7 | 0x00,0x00,0x02,0x00,0x00,0x00,0x42,0x47,0x52,0x73,0x00,0x00,0x00,0x00,0x00,0x00,
8 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
9 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
10 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
11 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
12 | 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
13 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
14 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
15 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
16 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
17 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
18 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
19 | 0x00,0x00,0x00,0x00,0x03,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
20 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xf0,0x00,0x00,
21 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
22 | 0x00,0x00,0x00,0x00,0x03,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
23 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,
24 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
25 | 0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff,
26 | 0x00,0x18,0x00,0x07,0xf0,0x03,0xcf,0x1e,0x1e,0x0f,0x3c,0x3e,0xf0,0x1e,0x00,0x00,
27 | 0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0x00,0x18,0x00,0x0f,0xfc,0x07,0xff,0x1e,
28 | 0x1e,0x3f,0xfc,0x7f,0xf0,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
29 | 0x00,0x18,0x00,0x0f,0xfe,0x0f,0xff,0x1e,0x1e,0x3f,0xfc,0xff,0xf0,0x1f,0x00,0x00,
30 | 0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x0c,0x1f,0x0f,0x1f,0x1e,
31 | 0x1e,0x7c,0x7c,0xf1,0xf0,0x3b,0x80,0x00,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,
32 | 0x00,0x18,0x00,0x00,0x0f,0x0f,0x1f,0x1e,0x1e,0x78,0x3c,0xf0,0xf0,0x3b,0x80,0x00,
33 | 0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x00,0x0f,0x0f,0x0f,0x1e,
34 | 0x1e,0x78,0x3c,0xf8,0xf0,0x7b,0x80,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xff,
35 | 0x00,0x18,0x00,0x00,0x1f,0x0f,0x0f,0x1e,0x1e,0x78,0x3c,0x7f,0xf0,0x71,0xc0,0x00,
36 | 0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x00,0xfe,0x0f,0x0f,0x1e,
37 | 0x1e,0x78,0x3c,0x1f,0xf0,0x71,0xc0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,
38 | 0x00,0x18,0x00,0x03,0xfe,0x0f,0x0f,0x1f,0x1e,0x78,0x3c,0x00,0xf0,0xf1,0xe0,0x00,
39 | 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x07,0xf8,0x0f,0x0f,0x1f,
40 | 0x1e,0x3c,0x3c,0x40,0xf0,0xe0,0xe0,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,
41 | 0x00,0x18,0x00,0x0f,0xc0,0x0f,0x0f,0x1f,0xfe,0x3f,0xfc,0x7f,0xf1,0xe0,0xe0,0x00,
42 | 0x00,0x00,0x03,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x0f,0x00,0x0f,0x0f,0x1f,
43 | 0xfc,0x1f,0xfc,0x7f,0xe1,0xe0,0xf0,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0xff,
44 | 0x00,0x18,0x00,0x0f,0x00,0x0f,0x0f,0x1e,0xf8,0x07,0xfc,0x3f,0xc1,0xc0,0x70,0x00,
45 | 0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x0f,0x82,0x00,0x00,0x00,
46 | 0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,
47 | 0x00,0x18,0x00,0x07,0xfe,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,
48 | 0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x07,0xfe,0x00,0x00,0x00,
49 | 0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,
50 | 0x00,0x18,0x00,0x01,0xfc,0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,
51 | 0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
52 | 0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,
53 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
54 | 0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
55 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,
56 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
57 | 0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
58 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,
59 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
60 | 0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
61 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,
62 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
63 | 0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,
64 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,
65 | 0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
66 | 0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,
67 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,
68 | 0x00,0x18,0x60,0x00,0x0c,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x03,0x80,0x00,
69 | 0x03,0x00,0x1f,0xff,0xff,0xff,0xff,0xfe,0x00,0x18,0x70,0x00,0x1c,0x03,0xff,0x8f,
70 | 0xf0,0x00,0x00,0x03,0xff,0x8f,0xe0,0x00,0x1f,0xe0,0x1f,0xff,0xff,0xff,0xff,0xfe,
71 | 0x00,0x18,0x20,0xfe,0x18,0x03,0xff,0x9f,0xf8,0x00,0x00,0x03,0xff,0x9f,0xf0,0x00,
72 | 0x3f,0xf0,0x1f,0xff,0xff,0xff,0xff,0xfe,0x00,0x18,0x03,0xff,0x00,0x01,0xe7,0x9c,
73 | 0x78,0x00,0x00,0x01,0xe7,0x0c,0x78,0x00,0x7c,0x70,0x1f,0xff,0xff,0xff,0xff,0xfc,
74 | 0x00,0x18,0x07,0xff,0xc0,0x00,0xf0,0x08,0x3c,0x00,0x00,0x00,0xf0,0x00,0x38,0x00,
75 | 0x78,0x20,0x1f,0xff,0xff,0xff,0xff,0xfc,0x00,0x18,0x0f,0xff,0xc0,0x00,0x78,0x00,
76 | 0x1c,0x00,0x00,0x00,0x78,0x00,0x38,0x00,0xf0,0x00,0x1f,0xff,0xff,0xff,0xff,0xf8,
77 | 0x00,0x18,0x1f,0xff,0xe0,0x00,0x3c,0x00,0x3c,0x00,0x1f,0x80,0x3c,0x00,0x1c,0x00,
78 | 0xe0,0x00,0x1f,0xff,0xff,0xff,0xff,0xf8,0x00,0x18,0x1f,0xff,0xe0,0x00,0x1c,0x00,
79 | 0x78,0x40,0x3f,0xc0,0x1c,0x07,0xdc,0x00,0xe0,0x00,0x1f,0xff,0xff,0xff,0xff,0xf0,
80 | 0x00,0x18,0x1f,0xff,0xf0,0x00,0x0e,0x03,0xf0,0xe0,0x7d,0xe0,0x1e,0x0f,0xfc,0x00,
81 | 0xe0,0x00,0x1f,0xff,0xff,0xff,0xff,0xe0,0x00,0x18,0x3f,0xff,0xf0,0x00,0x0f,0x03,
82 | 0xe0,0xf9,0xf0,0xf0,0x0e,0x1e,0x7c,0x00,0xe0,0x00,0x1f,0xff,0xff,0xff,0xff,0xc0,
83 | 0x00,0x1b,0xbf,0xff,0xf7,0x80,0x07,0x00,0xf0,0x7f,0xe0,0x60,0x07,0x1c,0x1c,0x00,
84 | 0xe0,0x00,0x1f,0xff,0xff,0xff,0xff,0x80,0x00,0x1b,0xbf,0xff,0xf3,0x00,0x07,0x00,
85 | 0x38,0x3f,0x80,0x00,0x07,0x1c,0x1c,0x78,0xe0,0x00,0x1f,0xff,0xff,0xff,0xff,0x00,
86 | 0x00,0x18,0x1f,0xff,0xf0,0x00,0x07,0x00,0x38,0x04,0x00,0x00,0x07,0x1c,0x38,0xfc,
87 | 0xf0,0x00,0x1f,0xff,0xff,0xff,0xfe,0x00,0x00,0x18,0x1f,0xff,0xf0,0x01,0x07,0x00,
88 | 0x38,0x00,0x00,0x01,0x07,0x1c,0x38,0x84,0x78,0x20,0x1f,0xff,0xff,0xff,0xf8,0x00,
89 | 0x00,0x18,0x1f,0xff,0xe0,0x03,0x8f,0x0c,0x78,0x00,0x00,0x03,0x8f,0x1e,0x79,0x86,
90 | 0x7e,0xe0,0x1f,0xff,0xff,0xff,0xe0,0x00,0x00,0x18,0x0f,0xff,0xe0,0x03,0xfe,0x1f,
91 | 0xf0,0x00,0x00,0x03,0xfe,0x0f,0xf0,0xcc,0x3f,0xf0,0x1f,0xff,0xff,0xff,0x00,0x00,
92 | 0x00,0x18,0x07,0xff,0xc0,0x00,0xfc,0x07,0xe0,0x00,0x00,0x00,0xfc,0x07,0xe0,0xfc,
93 | 0x0f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x03,0xff,0x80,0x00,0x00,0x00,
94 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
95 | 0x00,0x18,0x21,0xfe,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
96 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x70,0x30,0x18,0x00,0x00,0x00,
97 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
98 | 0x00,0x18,0xe0,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
99 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,
100 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
101 | 0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
102 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x30,0x00,0x00,0x00,0x00,
103 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
104 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
105 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
106 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
107 | 0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
108 | 0x00,0x00};
109 |
--------------------------------------------------------------------------------
/examples/uc1609_test/uc1609_test.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay library GFX demo
3 | //
4 | #include
5 | #include "uc1609.h" // demo bitmap
6 |
7 | #define RESET_PIN 9
8 | #define DC_PIN 8
9 | #define CS_PIN 10
10 | #define MOSI_PIN -1
11 | #define SCK_PIN -1
12 | // don't rotate the display
13 | #define FLIP180 0
14 | // don't invert the display
15 | #define INVERT 0
16 |
17 | #ifndef __AVR__
18 | #define USE_BACKBUFFER
19 | #endif
20 |
21 | #ifdef USE_BACKBUFFER
22 | uint8_t ucBackBuffer[1536];
23 | #endif
24 |
25 | // The OBDISP structure
26 | // There is no limit to the number of simultaneous displays which can be controlled by OneBitDisplay
27 | OBDISP obd;
28 |
29 | void setup() {
30 | int rc;
31 | Serial.begin(115200);
32 |
33 | //void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int iBitBang, int32_t iSpeed);
34 | obdSPIInit(&obd, LCD_UC1609, DC_PIN, CS_PIN, RESET_PIN, MOSI_PIN, SCK_PIN, -1, 0, 0, 0, 4000000);
35 | obdFill(&obd, OBD_WHITE, 1);
36 | obdWriteString(&obd, 0,0,0,(char *)"UC1701 192x64 LCD Demo", FONT_8x8, OBD_BLACK, 1);
37 | delay(4000);
38 | rc = obdLoadBMP(&obd, (uint8_t *)uc1609, 0, 0, OBD_BLACK, OBD_WHITE);
39 | if (rc != 0)
40 | Serial.println("Error displaying bitmap");
41 | delay(4000);
42 | #ifdef USE_BACKBUFFER
43 | obdSetBackBuffer(&obd, ucBackBuffer);
44 | #endif
45 | } /* setup() */
46 |
47 | #ifdef USE_BACKBUFFER
48 | #define DRAW_ELLIPSES
49 | #define DRAW_RECTS
50 | #define DRAW_TEXT
51 | #endif
52 |
53 | void loop() {
54 | int i, x, y, x2, y2, r1, r2;
55 | uint8_t ucColor;
56 | unsigned long ulTime;
57 | char szTemp[32];
58 |
59 | #ifdef DRAW_ELLIPSES
60 | obdFill(&obd, OBD_WHITE, 1);
61 | obdWriteString(&obd, 0, 0, 0, (char *)"Ellipses", FONT_8x8, OBD_BLACK, 1);
62 | delay(2000);
63 | obdFill(&obd, OBD_WHITE, 1);
64 | ulTime = micros();
65 | for (i=0; i<100; i++)
66 | {
67 | x = random(192);
68 | y = random(64);
69 | r1 = random(64);
70 | r2 = random(32);
71 | obdEllipse(&obd, x, y, r1, r2, OBD_BLACK, 0);
72 | obdDumpBuffer(&obd, NULL);
73 | }
74 | ulTime = micros() - ulTime;
75 | obdFill(&obd, OBD_WHITE, 1);
76 | obdWriteString(&obd, 0, 0, 0, (char *)"100 frames drawn", FONT_8x8, OBD_BLACK, 1);
77 | sprintf(szTemp, "in %d ms", (int)(ulTime/1000));
78 | obdWriteString(&obd, 0, 0, 1, szTemp, FONT_8x8, OBD_BLACK, 1);
79 | sprintf(szTemp, "%d FPS", 100000000 / (ulTime));
80 | obdWriteString(&obd, 0, 0, 2, szTemp, FONT_8x8, OBD_BLACK, 1);
81 | delay(4000);
82 | obdFill(&obd, OBD_WHITE, 1);
83 | obdWriteString(&obd, 0, 0, 0, (char *)"Filled Ellipses", FONT_8x8, OBD_BLACK, 1);
84 | delay(2000);
85 | obdFill(&obd, OBD_WHITE, 1);
86 | ulTime = micros();
87 | for (i=0; i<100; i++)
88 | {
89 | x = random(192);
90 | y = random(64);
91 | r1 = random(64);
92 | r2 = random(32);
93 | ucColor = random(2);
94 | obdEllipse(&obd, x, y, r1, r2, ucColor, 1);
95 | obdDumpBuffer(&obd, NULL);
96 | }
97 | ulTime = micros() - ulTime;
98 | obdFill(&obd, 0, 1);
99 | obdWriteString(&obd, 0, 0, 0, (char *)"100 frames drawn", FONT_8x8, OBD_BLACK, 1);
100 | sprintf(szTemp, "in %d ms", (int)(ulTime/1000));
101 | obdWriteString(&obd, 0, 0, 1, szTemp, FONT_8x8, OBD_BLACK, 1);
102 | sprintf(szTemp, "%d FPS", 100000000 / (ulTime));
103 | obdWriteString(&obd, 0, 0, 2, szTemp, FONT_8x8, OBD_BLACK, 1);
104 | delay(4000);
105 |
106 | #endif // DRAW_ELLIPSES
107 |
108 | #ifdef DRAW_RECTS
109 | obdFill(&obd, OBD_WHITE, 1);
110 | obdWriteString(&obd, 0, 0, 0, (char *)"Rectangles", FONT_8x8, OBD_BLACK, 1);
111 | delay(2000);
112 | obdFill(&obd, OBD_WHITE, 1);
113 | ulTime = micros();
114 | for (i=0; i<100; i++)
115 | {
116 | x = random(192);
117 | y = random(64);
118 | x2 = random(192);
119 | y2 = random(64);
120 | obdRectangle(&obd, x, y, x2, y2, OBD_BLACK, 0);
121 | obdDumpBuffer(&obd, NULL);
122 | }
123 | ulTime = micros() - ulTime;
124 | obdFill(&obd, OBD_WHITE, 1);
125 | obdWriteString(&obd, 0, 0, 0, (char *)"100 frames drawn", FONT_8x8, OBD_BLACK, 1);
126 | sprintf(szTemp, "in %d ms", (int)(ulTime/1000));
127 | obdWriteString(&obd, 0, 0, 1, szTemp, FONT_8x8, OBD_BLACK, 1);
128 | sprintf(szTemp, "%d FPS", 100000000 / (ulTime));
129 | obdWriteString(&obd, 0, 0, 2, szTemp, FONT_8x8, OBD_BLACK, 1);
130 | delay(4000);
131 | obdFill(&obd, OBD_WHITE, 1);
132 | obdWriteString(&obd, 0, 0, 0, (char *)"Filled Rects", FONT_8x8, OBD_BLACK, 1);
133 | delay(2000);
134 | obdFill(&obd, OBD_WHITE, 1);
135 | ulTime = micros();
136 | for (i=0; i<100; i++)
137 | {
138 | x = random(192);
139 | y = random(64);
140 | x2 = random(192);
141 | y2 = random(64);
142 | ucColor = random(2);
143 | obdRectangle(&obd, x, y, x2, y2, ucColor, 1);
144 | obdDumpBuffer(&obd, NULL);
145 | }
146 | ulTime = micros() - ulTime;
147 | obdFill(&obd, OBD_WHITE, 1);
148 | obdWriteString(&obd, 0, 0, 0, (char *)"100 frames drawn", FONT_8x8, OBD_BLACK, 1);
149 | sprintf(szTemp, "in %d ms", (int)(ulTime/1000));
150 | obdWriteString(&obd, 0, 0, 1, szTemp, FONT_8x8, OBD_BLACK, 1);
151 | sprintf(szTemp, "%d FPS", 100000000 / (ulTime));
152 | obdWriteString(&obd, 0, 0, 2, szTemp, FONT_8x8, OBD_BLACK, 1);
153 | delay(4000);
154 | #endif // DRAW_RECTS
155 | #ifdef DRAW_TEXT
156 | obdFill(&obd,OBD_WHITE,1);
157 | obdWriteString(&obd,0,0,0,(char *)"Small Font", FONT_8x8, OBD_BLACK, 1);
158 | delay(2000);
159 | obdFill(&obd,OBD_WHITE,1);
160 | ulTime = micros();
161 | for (i=0; i<100; i++)
162 | {
163 | char szTemp[34];
164 | szTemp[32] = 0;
165 | x = i;
166 | while (x >= 26)
167 | x -= 26;
168 | for (y=0; y<8; y++)
169 | {
170 | for (x2=0; x2<32; x2++)
171 | {
172 | szTemp[x2] = 'A' + x;
173 | x++;
174 | if (x >= 26) x -= 26;
175 | }
176 | obdWriteString(&obd, 0,0,y,szTemp, FONT_6x8, OBD_BLACK, 1);
177 | } // for y
178 | }
179 | ulTime = micros() - ulTime;
180 | obdFill(&obd, OBD_WHITE, 1);
181 | obdWriteString(&obd, 0, 0, 0, (char *)"16800 chars", FONT_8x8, OBD_BLACK, 1);
182 | sprintf(szTemp, "in %d ms", (int)(ulTime/1000));
183 | obdWriteString(&obd, 0, 0, 1, szTemp, FONT_8x8, OBD_BLACK, 1);
184 | delay(4000);
185 | obdFill(&obd,OBD_WHITE,1);
186 | obdWriteString(&obd,0,0,0,(char *)"Normal Font", FONT_8x8, OBD_BLACK, 1);
187 | delay(2000);
188 | obdFill(&obd,OBD_WHITE,1);
189 | ulTime = micros();
190 | for (i=0; i<100; i++)
191 | {
192 | char szTemp[34];
193 | szTemp[24] = 0;
194 | x = i;
195 | while (x >= 26)
196 | x -= 26;
197 | for (y=0; y<8; y++)
198 | {
199 | for (x2=0; x2<24; x2++)
200 | {
201 | szTemp[x2] = 'A' + x;
202 | x++;
203 | if (x >= 26) x -= 26;
204 | }
205 | obdWriteString(&obd, 0,0,y,szTemp, FONT_8x8, OBD_BLACK, 1);
206 | } // for y
207 | }
208 | ulTime = micros() - ulTime;
209 | obdFill(&obd, OBD_WHITE, 1);
210 | obdWriteString(&obd, 0, 0, 0, (char *)"12800 chars", FONT_8x8, OBD_BLACK, 1);
211 | sprintf(szTemp, "in %d ms", (int)(ulTime/1000));
212 | obdWriteString(&obd, 0, 0, 1, szTemp, FONT_8x8, OBD_BLACK, 1);
213 | delay(4000);
214 | #endif // DRAW_TEXT
215 | } /* loop() */
216 |
--------------------------------------------------------------------------------
/examples/virtual_display/virtual_display.ino:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay library demo
3 | //
4 | // Demonstrates how to use virtual displays
5 | // these allow you to create a display of any size in memory
6 | // and draw it across multiple physical displays
7 | //
8 | //#include
9 | #include
10 | OBDISP obLeft;
11 | OBDISP obRight;
12 | OBDISP obVirt;
13 |
14 | // define a 256x64 framebuffer
15 | static uint8_t ucBackBuffer[2048];
16 |
17 | // Toaster animation images
18 | const uint8_t toastermask0[] = {
19 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
20 | 0x00, 0x20, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00,
21 | 0x00, 0x10, 0x00, 0x00, 0x00, 0x43, 0xF8, 0x00,
22 | 0x00, 0x1F, 0x80, 0x00, 0x00, 0x7C, 0x3F, 0x80,
23 | 0x01, 0xF1, 0xF8, 0xF0, 0x07, 0xC7, 0xC7, 0x00,
24 | 0x0F, 0x1F, 0x08, 0x2B, 0x1E, 0x7C, 0x11, 0x00,
25 | 0x04, 0xF0, 0x20, 0x56, 0x61, 0xE4, 0x22, 0x00,
26 | 0x78, 0x48, 0x40, 0xA8, 0x4E, 0x10, 0x44, 0x00,
27 | 0x53, 0x90, 0x81, 0xF8, 0x5C, 0xA0, 0x90, 0x58,
28 | 0x7C, 0xA1, 0x07, 0x90, 0x74, 0xA1, 0x21, 0x38,
29 | 0x7F, 0xB5, 0x0E, 0x30, 0x77, 0xB0, 0x90, 0x78,
30 | 0x7F, 0xB4, 0x60, 0xF0, 0x77, 0xBB, 0x03, 0xE0,
31 | 0x7F, 0xBC, 0x0F, 0xC0, 0x77, 0xBF, 0xFF, 0x00,
32 | 0x7F, 0xBF, 0xFC, 0x00, 0x3F, 0xBF, 0xF0, 0x00,
33 | 0x1F, 0xBF, 0xC0, 0x00, 0x07, 0xBE, 0x00, 0x00,
34 | 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
35 | const uint8_t toastermask1[] = {
36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0xF8, 0x00,
39 | 0x00, 0x1F, 0x80, 0x00, 0x00, 0x7C, 0x3F, 0x80,
40 | 0x01, 0xF1, 0xF8, 0x00, 0x07, 0xC7, 0xC1, 0xE0,
41 | 0x0F, 0x1F, 0x06, 0x10, 0x1E, 0x7C, 0x00, 0x00,
42 | 0x04, 0xF0, 0x07, 0xF0, 0x61, 0xE4, 0x18, 0x08,
43 | 0x78, 0x48, 0x20, 0x80, 0x4E, 0x10, 0x40, 0x2B,
44 | 0x53, 0x90, 0x81, 0x00, 0x5C, 0xA0, 0x80, 0x58,
45 | 0x7C, 0xA1, 0x02, 0x00, 0x74, 0xA1, 0x28, 0xB8,
46 | 0x7F, 0xB5, 0x0F, 0xF0, 0x77, 0xB0, 0x90, 0x78,
47 | 0x7F, 0xB4, 0x60, 0xF0, 0x77, 0xBB, 0x03, 0xE0,
48 | 0x7F, 0xBC, 0x0F, 0xC0, 0x77, 0xBF, 0xFF, 0x00,
49 | 0x7F, 0xBF, 0xFC, 0x00, 0x3F, 0xBF, 0xF0, 0x00,
50 | 0x1F, 0xBF, 0xC0, 0x00, 0x07, 0xBE, 0x00, 0x00,
51 | 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
52 | const uint8_t toastermask2[] = {
53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00,
56 | 0x00, 0x1F, 0x80, 0x00, 0x00, 0x7C, 0x3F, 0x80,
57 | 0x01, 0xF1, 0xF8, 0x00, 0x07, 0xC7, 0xC1, 0xE0,
58 | 0x0F, 0x1F, 0x06, 0x10, 0x1E, 0x7C, 0x00, 0x00,
59 | 0x04, 0xF0, 0x00, 0x00, 0x61, 0xE4, 0x00, 0x08,
60 | 0x78, 0x48, 0x00, 0x10, 0x4E, 0x10, 0x00, 0x18,
61 | 0x53, 0x90, 0x60, 0x70, 0x5C, 0xA0, 0x9F, 0xC8,
62 | 0x7C, 0xA1, 0x04, 0x92, 0x74, 0xA1, 0x09, 0x24,
63 | 0x7F, 0xB5, 0x02, 0x48, 0x77, 0xB0, 0x80, 0x10,
64 | 0x7F, 0xB4, 0x41, 0x00, 0x77, 0xBB, 0x20, 0x40,
65 | 0x7F, 0xBC, 0x10, 0x00, 0x77, 0xBF, 0xF8, 0x00,
66 | 0x7F, 0xBF, 0xFC, 0x00, 0x3F, 0xBF, 0xF0, 0x00,
67 | 0x1F, 0xBF, 0xC0, 0x00, 0x07, 0xBE, 0x00, 0x00,
68 | 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
69 | const uint8_t toaster0[] = {
70 | 0x00, 0x30, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00,
71 | 0x01, 0xD8, 0x00, 0x00, 0x03, 0x74, 0xF0, 0x00,
72 | 0x07, 0xEF, 0xFE, 0x00, 0x07, 0xBC, 0x07, 0x80,
73 | 0x0F, 0xE0, 0x7F, 0xE0, 0x0F, 0x83, 0xC0, 0x70,
74 | 0x1E, 0x0E, 0x07, 0x08, 0x18, 0x38, 0x38, 0xFF,
75 | 0x30, 0xE0, 0xF7, 0xD4, 0x61, 0x83, 0xEE, 0xFF,
76 | 0x7B, 0x0F, 0xDF, 0xA8, 0x9E, 0x1B, 0xDD, 0xFE,
77 | 0x87, 0xB7, 0xBF, 0x50, 0xB1, 0xEF, 0xBB, 0xF8,
78 | 0xAC, 0x6F, 0x7E, 0x00, 0xA3, 0x5F, 0x6F, 0xA0,
79 | 0x83, 0x5E, 0xF8, 0x68, 0x8B, 0x5E, 0xDE, 0xC0,
80 | 0x80, 0x4A, 0xF1, 0xC8, 0x88, 0x4F, 0x6F, 0x80,
81 | 0x80, 0x4B, 0x9F, 0x08, 0x88, 0x44, 0xFC, 0x10,
82 | 0x80, 0x43, 0xF0, 0x20, 0x88, 0x40, 0x00, 0xC0,
83 | 0x80, 0x40, 0x03, 0x00, 0x40, 0x40, 0x0C, 0x00,
84 | 0x20, 0x40, 0x30, 0x00, 0x18, 0x41, 0xC0, 0x00,
85 | 0x06, 0x4E, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00 };
86 | const uint8_t toaster1[] = {
87 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xF0, 0x00,
89 | 0x00, 0xF7, 0xFE, 0x00, 0x01, 0xBC, 0x07, 0x80,
90 | 0x03, 0xE0, 0x7F, 0xE0, 0x07, 0x83, 0xC0, 0x70,
91 | 0x0E, 0x0E, 0x07, 0xF8, 0x18, 0x38, 0x3E, 0x18,
92 | 0x30, 0xE0, 0xF9, 0xE8, 0x61, 0x83, 0xFF, 0xF8,
93 | 0x7B, 0x0F, 0xF8, 0x08, 0x9E, 0x1B, 0xE7, 0xF0,
94 | 0x87, 0xB7, 0xDF, 0x7F, 0xB1, 0xEF, 0xBF, 0xD4,
95 | 0xAC, 0x6F, 0x7E, 0xFF, 0xA3, 0x5F, 0x7F, 0xA6,
96 | 0x83, 0x5E, 0xFD, 0xF8, 0x8B, 0x5E, 0xD7, 0x40,
97 | 0x80, 0x4A, 0xF0, 0x08, 0x88, 0x4F, 0x6F, 0x80,
98 | 0x80, 0x4B, 0x9F, 0x08, 0x88, 0x44, 0xFC, 0x10,
99 | 0x80, 0x43, 0xF0, 0x20, 0x88, 0x40, 0x00, 0xC0,
100 | 0x80, 0x40, 0x03, 0x00, 0x40, 0x40, 0x0C, 0x00,
101 | 0x20, 0x40, 0x30, 0x00, 0x18, 0x41, 0xC0, 0x00,
102 | 0x06, 0x4E, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00 };
103 | const uint8_t toaster2[] = {
104 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00,
106 | 0x00, 0x07, 0xFE, 0x00, 0x00, 0x3C, 0x07, 0x80,
107 | 0x00, 0xE0, 0x7F, 0xE0, 0x03, 0x83, 0xC0, 0x70,
108 | 0x0E, 0x0E, 0x07, 0xF8, 0x18, 0x38, 0x3E, 0x18,
109 | 0x30, 0xE0, 0xF9, 0xE8, 0x61, 0x83, 0xFF, 0xF8,
110 | 0x7B, 0x0F, 0xFF, 0xF8, 0x9E, 0x1B, 0xFF, 0xF0,
111 | 0x87, 0xB7, 0xFF, 0xE8, 0xB1, 0xEF, 0xFF, 0xE0,
112 | 0xAC, 0x6F, 0x9F, 0x88, 0xA3, 0x5F, 0x60, 0x36,
113 | 0x83, 0x5E, 0xFB, 0x6D, 0x8B, 0x5E, 0xF6, 0xDB,
114 | 0x80, 0x4A, 0xFD, 0xB6, 0x88, 0x4F, 0x7F, 0xEE,
115 | 0x80, 0x4B, 0xBE, 0xFC, 0x88, 0x44, 0xDF, 0xBC,
116 | 0x80, 0x43, 0xEF, 0xF8, 0x88, 0x40, 0x07, 0xF0,
117 | 0x80, 0x40, 0x03, 0xE0, 0x40, 0x40, 0x0C, 0xC0,
118 | 0x20, 0x40, 0x30, 0x00, 0x18, 0x41, 0xC0, 0x00,
119 | 0x06, 0x4E, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00 };
120 | uint8_t * toasters[] = {(uint8_t *)toaster0, (uint8_t *)toaster1, (uint8_t *)toaster2, (uint8_t *)toaster1};
121 | uint8_t * masks[] = {(uint8_t *)toastermask0, (uint8_t *)toastermask1, (uint8_t *)toastermask2, (uint8_t *)toastermask1};
122 |
123 | void setup() {
124 | int rc;
125 | //int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int iSDAPin, int iSCLPin, int iResetPin, int32_t iSpeed);
126 | // Create a virtual display (memory only)
127 | obdCreateVirtualDisplay(&obVirt, 256, 64, ucBackBuffer);
128 | // Initialize 2 physical OLED displays
129 | // In this case, they are defined on the W600-PICO using bit banging
130 | // Change the SDA and SCL pin definitions to match your setup
131 | rc = obdI2CInit(&obLeft, OLED_128x64, -1, 0, 0,0,WM_IO_PB_12, WM_IO_PA_00,-1,1200000L);
132 | rc = obdI2CInit(&obRight, OLED_128x64, -1, 0, 0,0,WM_IO_PB_11, WM_IO_PA_00,-1,1200000L);
133 | if (rc != OLED_NOT_FOUND)
134 | {
135 | char *msgs[] = {(char *)"SSD1306 @ 0x3C", (char *)"SSD1306 @ 0x3D",(char *)"SH1106 @ 0x3C",(char *)"SH1106 @ 0x3D"};
136 | obdFill(&obLeft, OBD_WHITE, 1);
137 | obdWriteString(&obLeft,0,0,0,msgs[rc], FONT_8x8, OBD_BLACK, 1);
138 | delay(2000);
139 | }
140 | }
141 | #define NUM_SPRITES 10
142 | void loop() {
143 | int i, x, y;
144 | char szTemp[32];
145 | unsigned long ms;
146 | int xpos[NUM_SPRITES], ypos[NUM_SPRITES], index[NUM_SPRITES], velocity[NUM_SPRITES];
147 |
148 | obdFill(&obLeft, OBD_WHITE, 1);
149 | obdWriteString(&obLeft,0,16,0,(char *)"ss_oled Demo", FONT_8x8, OBD_BLACK, 1);
150 | obdWriteString(&obLeft,0,0,1,(char *)"Written by Larry Bank", FONT_6x8, OBD_WHITE, 1);
151 | obdWriteString(&obLeft,0,0,3,(char *)"**Demo**", FONT_16x32, OBD_BLACK, 1);
152 | delay(2000);
153 |
154 | // Sprites
155 | // generate random starting positions, speed and animation frame index
156 | for (i=0; i>2, ypos[i]>>2, 0);
170 | obdDrawSprite(&obVirt,toasters[index[i] & 3], 32, 32, 4, xpos[i]>>2, ypos[i]>>2, 1);
171 | xpos[i]-= velocity[i];
172 | ypos[i]+= velocity[i];
173 | index[i]++;
174 | x = xpos[i] >> 2; y = ypos[i] >> 2;
175 | if (x < -31 || y >= 64)
176 | {
177 | xpos[i] = 4*((rand()&255) + 31);
178 | ypos[i] = 4*((rand()&63) - 31);
179 | }
180 | }
181 | // Show the left half of the virtual display on the left OLED
182 | obdDumpWindow(&obVirt, &obLeft,0,0,0,0,128,64);
183 | // and the right half on the right OLED
184 | obdDumpWindow(&obVirt, &obRight,128,0,0,0,128,64);
185 | } // while (1)
186 | } /* main() */
187 |
--------------------------------------------------------------------------------
/fontconvert/Makefile:
--------------------------------------------------------------------------------
1 | all: fontconvert
2 |
3 | CC = gcc
4 | CFLAGS = -Wall -I/usr/local/include/freetype2 -I/usr/include/freetype2 -I/usr/include -I/opt/homebrew/include/freetype2
5 | LIBS = -L/opt/homebrew/lib -lfreetype
6 |
7 | fontconvert: main.c
8 | $(CC) $(CFLAGS) main.c $(LIBS) -o fontconvert
9 | strip fontconvert
10 |
11 | clean:
12 | rm -f fontconvert
13 |
--------------------------------------------------------------------------------
/fontconvert/README.txt:
--------------------------------------------------------------------------------
1 | TrueType font convert tool
2 | --------------------------
3 | This program was written by Adafruit and I modified it to map characters
4 | 128 to 255 from Unicode to the Microsoft codepage 1252 set. This allows
5 | you to support nearly all European/Western languages with direct use
6 | of UTF-8 Unicode strings from your projects. It's not a perfect solution,
7 | but it's better than not being able to use those symbols and accented
8 | characters. See the Unicode_demo for an example of how to use them.
9 |
10 | Build the tool with GCC and Make. I've tested this on MacOS and Linux,
11 | but it should work on Windows too.
12 |
13 |
--------------------------------------------------------------------------------
/fontconvert/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | TrueType to Adafruit_GFX font converter. Derived from Peter Jakobs'
3 | Adafruit_ftGFX fork & makefont tool, and Paul Kourany's Adafruit_mfGFX.
4 |
5 | NOT AN ARDUINO SKETCH. This is a command-line tool for preprocessing
6 | fonts to be used with the Adafruit_GFX Arduino library.
7 |
8 | For UNIX-like systems. Outputs to stdout; redirect to header file, e.g.:
9 | ./fontconvert ~/Library/Fonts/FreeSans.ttf 18 > FreeSans18pt7b.h
10 |
11 | REQUIRES FREETYPE LIBRARY. www.freetype.org
12 |
13 | Currently this only extracts the printable 7-bit ASCII chars of a font.
14 | Will eventually extend with some int'l chars a la ftGFX, not there yet.
15 | Keep 7-bit fonts around as an option in that case, more compact.
16 |
17 | See notes at end for glyph nomenclature & other tidbits.
18 | */
19 | #ifndef ARDUINO
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include FT_GLYPH_H
26 | #include FT_MODULE_H
27 | #include FT_TRUETYPE_DRIVER_H
28 |
29 | typedef struct {
30 | uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
31 | uint16_t width; ///< Bitmap dimensions in pixels
32 | uint16_t height; ///< Bitmap dimensions in pixels
33 | uint16_t xAdvance; ///< Distance to advance cursor (x axis)
34 | int16_t xOffset; ///< X dist from cursor pos to UL corner
35 | int16_t yOffset; ///< Y dist from cursor pos to UL corner
36 | } GFXglyph;
37 |
38 | /// Data stored for FONT AS A WHOLE
39 | typedef struct {
40 | uint8_t *bitmap; ///< Glyph bitmaps, concatenated
41 | GFXglyph *glyph; ///< Glyph array
42 | uint8_t first; ///< ASCII extents (first char)
43 | uint8_t last; ///< ASCII extents (last char)
44 | int16_t yAdvance; ///< Newline distance (y axis)
45 | } GFXfont;
46 |
47 | #define DPI 141 // Approximate res. of Adafruit 2.8" TFT
48 |
49 | // Accumulate bits for output, with periodic hexadecimal byte write
50 | void enbit(uint8_t value) {
51 | static uint8_t row = 0, sum = 0, bit = 0x80, firstCall = 1;
52 | if (value)
53 | sum |= bit; // Set bit if needed
54 | if (!(bit >>= 1)) { // Advance to next bit, end of byte reached?
55 | if (!firstCall) { // Format output table nicely
56 | if (++row >= 12) { // Last entry on line?
57 | printf(",\n "); // Newline format output
58 | row = 0; // Reset row counter
59 | } else { // Not end of line
60 | printf(", "); // Simple comma delim
61 | }
62 | }
63 | printf("0x%02X", sum); // Write byte value
64 | sum = 0; // Clear for next byte
65 | bit = 0x80; // Reset bit counter
66 | firstCall = 0; // Formatting flag
67 | }
68 | }
69 | //
70 | // Lookup table to convert codepage 1252 to Unicode
71 | //
72 | const uint16_t uc1252Table[256] = {
73 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 0-15 not used (some can be mapped to printable characters if needed)
74 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 16-31 not used
75 | 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
76 | 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,
77 | 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
78 | 80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
79 | 96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,
80 | 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
81 | // Now starts the remapped Unicode characters
82 | 0x20ac, 32, 0x201a, 0x192, 0x201e, 0x2026, 0x2020, 0x2021, 0x2c6, 0x2030,0x160,0x2039,0x152,32,0x17d,32, // 0x80-0x8f
83 | 32, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x2dc, 0x2122, 0x161, 0x2031, 0x153, 32, 0x17e, 0x178, // 0x90-0x9f
84 | 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
85 | 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
86 | 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
87 | 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
88 | 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
89 | 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
90 | };
91 |
92 | int main(int argc, char *argv[]) {
93 | int i, j, err, size, first = ' ', last = '~', bitmapOffset = 0, x, y, byte;
94 | char *fontName, c, *ptr;
95 | FT_Library library;
96 | FT_Face face;
97 | FT_Glyph glyph;
98 | FT_Bitmap *bitmap;
99 | FT_BitmapGlyphRec *g;
100 | GFXglyph *table;
101 | uint8_t bit;
102 |
103 | // Parse command line. Valid syntaxes are:
104 | // fontconvert [filename] [size]
105 | // fontconvert [filename] [size] [last char]
106 | // fontconvert [filename] [size] [first char] [last char]
107 | // Unless overridden, default first and last chars are
108 | // ' ' (space) and '~', respectively
109 |
110 | if (argc < 3) {
111 | fprintf(stderr, "Usage: %s fontfile size [first] [last]\n", argv[0]);
112 | return 1;
113 | }
114 |
115 | size = atoi(argv[2]);
116 |
117 | if (argc == 4) {
118 | last = atoi(argv[3]);
119 | } else if (argc == 5) {
120 | first = atoi(argv[3]);
121 | last = atoi(argv[4]);
122 | }
123 |
124 | if (last < first) {
125 | i = first;
126 | first = last;
127 | last = i;
128 | }
129 |
130 | ptr = strrchr(argv[1], '/'); // Find last slash in filename
131 | if (ptr)
132 | ptr++; // First character of filename (path stripped)
133 | else
134 | ptr = argv[1]; // No path; font in local dir.
135 |
136 | // Allocate space for font name and glyph table
137 | if ((!(fontName = malloc(strlen(ptr) + 20))) ||
138 | (!(table = (GFXglyph *)malloc((last - first + 1) * sizeof(GFXglyph))))) {
139 | fprintf(stderr, "Malloc error\n");
140 | return 1;
141 | }
142 |
143 | // Derive font table names from filename. Period (filename
144 | // extension) is truncated and replaced with the font size & bits.
145 | strcpy(fontName, ptr);
146 | ptr = strrchr(fontName, '.'); // Find last period (file ext)
147 | if (!ptr)
148 | ptr = &fontName[strlen(fontName)]; // If none, append
149 | // Insert font size and 7/8 bit. fontName was alloc'd w/extra
150 | // space to allow this, we're not sprintfing into Forbidden Zone.
151 | sprintf(ptr, "%dpt%db", size, (last > 127) ? 8 : 7);
152 | // Space and punctuation chars in name replaced w/ underscores.
153 | for (i = 0; (c = fontName[i]); i++) {
154 | if (isspace(c) || ispunct(c))
155 | fontName[i] = '_';
156 | }
157 |
158 | // Init FreeType lib, load font
159 | if ((err = FT_Init_FreeType(&library))) {
160 | fprintf(stderr, "FreeType init error: %d", err);
161 | return err;
162 | }
163 |
164 | // Use TrueType engine version 35, without subpixel rendering.
165 | // This improves clarity of fonts since this library does not
166 | // support rendering multiple levels of gray in a glyph.
167 | // See https://github.com/adafruit/Adafruit-GFX-Library/issues/103
168 | FT_UInt interpreter_version = TT_INTERPRETER_VERSION_35;
169 | FT_Property_Set(library, "truetype", "interpreter-version",
170 | &interpreter_version);
171 |
172 | if ((err = FT_New_Face(library, argv[1], 0, &face))) {
173 | fprintf(stderr, "Font load error: %d", err);
174 | FT_Done_FreeType(library);
175 | return err;
176 | }
177 |
178 | // << 6 because '26dot6' fixed-point format
179 | FT_Set_Char_Size(face, size << 6, 0, DPI, 0);
180 |
181 | // Currently all symbols from 'first' to 'last' are processed.
182 | // Fonts may contain WAY more glyphs than that, but this code
183 | // will need to handle encoding stuff to deal with extracting
184 | // the right symbols, and that's not done yet.
185 | // fprintf(stderr, "%ld glyphs\n", face->num_glyphs);
186 |
187 | printf("const uint8_t %sBitmaps[] PROGMEM = {\n ", fontName);
188 |
189 | // Process glyphs and output huge bitmap data array
190 | for (i = first, j = 0; i <= last; i++, j++) {
191 | int iChar = uc1252Table[i]; // convert CP1252 to Unicode
192 | // MONO renderer provides clean image with perfect crop
193 | // (no wasted pixels) via bitmap struct.
194 | if ((err = FT_Load_Char(face, iChar, FT_LOAD_TARGET_MONO))) {
195 | fprintf(stderr, "Error %d loading char '%c'\n", err, iChar);
196 | continue;
197 | }
198 |
199 | if ((err = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO))) {
200 | fprintf(stderr, "Error %d rendering char '%c'\n", err, iChar);
201 | continue;
202 | }
203 |
204 | if ((err = FT_Get_Glyph(face->glyph, &glyph))) {
205 | fprintf(stderr, "Error %d getting glyph '%c'\n", err, iChar);
206 | continue;
207 | }
208 |
209 | bitmap = &face->glyph->bitmap;
210 | g = (FT_BitmapGlyphRec *)glyph;
211 |
212 | // Minimal font and per-glyph information is stored to
213 | // reduce flash space requirements. Glyph bitmaps are
214 | // fully bit-packed; no per-scanline pad, though end of
215 | // each character may be padded to next byte boundary
216 | // when needed. 16-bit offset means 64K max for bitmaps,
217 | // code currently doesn't check for overflow. (Doesn't
218 | // check that size & offsets are within bounds either for
219 | // that matter...please convert fonts responsibly.)
220 | table[j].bitmapOffset = bitmapOffset;
221 | table[j].width = bitmap->width;
222 | table[j].height = bitmap->rows;
223 | table[j].xAdvance = face->glyph->advance.x >> 6;
224 | table[j].xOffset = g->left;
225 | table[j].yOffset = 1 - g->top;
226 |
227 | for (y = 0; y < bitmap->rows; y++) {
228 | for (x = 0; x < bitmap->width; x++) {
229 | byte = x / 8;
230 | bit = 0x80 >> (x & 7);
231 | enbit(bitmap->buffer[y * bitmap->pitch + byte] & bit);
232 | }
233 | }
234 |
235 | // Pad end of char bitmap to next byte boundary if needed
236 | int n = (bitmap->width * bitmap->rows) & 7;
237 | if (n) { // Pixel count not an even multiple of 8?
238 | n = 8 - n; // # bits to next multiple
239 | while (n--)
240 | enbit(0);
241 | }
242 | bitmapOffset += (bitmap->width * bitmap->rows + 7) / 8;
243 |
244 | FT_Done_Glyph(glyph);
245 | }
246 |
247 | printf(" };\n\n"); // End bitmap array
248 |
249 | // Output glyph attributes table (one per character)
250 | printf("const GFXglyph %sGlyphs[] PROGMEM = {\n", fontName);
251 | for (i = first, j = 0; i <= last; i++, j++) {
252 | printf(" { %5d, %3d, %3d, %3d, %4d, %4d }", table[j].bitmapOffset,
253 | table[j].width, table[j].height, table[j].xAdvance, table[j].xOffset,
254 | table[j].yOffset);
255 | if (i < last) {
256 | printf(", // 0x%02X", i);
257 | if ((i >= ' ') && (i <= '~')) {
258 | printf(" '%c'", i);
259 | }
260 | putchar('\n');
261 | }
262 | }
263 | printf(" }; // 0x%02X", last);
264 | if ((last >= ' ') && (last <= '~'))
265 | printf(" '%c'", last);
266 | printf("\n\n");
267 |
268 | // Output font structure
269 | printf("const GFXfont %s PROGMEM = {\n", fontName);
270 | printf(" (uint8_t *)%sBitmaps,\n", fontName);
271 | printf(" (GFXglyph *)%sGlyphs,\n", fontName);
272 | if (face->size->metrics.height == 0) {
273 | // No face height info, assume fixed width and get from a glyph.
274 | printf(" 0x%02X, 0x%02X, %d };\n\n", first, last, table[0].height);
275 | } else {
276 | printf(" 0x%02X, 0x%02X, %ld };\n\n", first, last,
277 | face->size->metrics.height >> 6);
278 | }
279 | printf("// Approx. %d bytes\n", bitmapOffset + (last - first + 1) * 7 + 7);
280 | // Size estimate is based on AVR struct and pointer sizes;
281 | // actual size may vary.
282 |
283 | FT_Done_FreeType(library);
284 |
285 | return 0;
286 | }
287 |
288 | /* -------------------------------------------------------------------------
289 |
290 | Character metrics are slightly different from classic GFX & ftGFX.
291 | In classic GFX: cursor position is the upper-left pixel of each 5x7
292 | character; lower extent of most glyphs (except those w/descenders)
293 | is +6 pixels in Y direction.
294 | W/new GFX fonts: cursor position is on baseline, where baseline is
295 | 'inclusive' (containing the bottom-most row of pixels in most symbols,
296 | except those with descenders; ftGFX is one pixel lower).
297 |
298 | Cursor Y will be moved automatically when switching between classic
299 | and new fonts. If you switch fonts, any print() calls will continue
300 | along the same baseline.
301 |
302 | ...........#####.. -- yOffset
303 | ..........######..
304 | ..........######..
305 | .........#######..
306 | ........#########.
307 | * = Cursor pos. ........#########.
308 | .......##########.
309 | ......#####..####.
310 | ......#####..####.
311 | *.#.. .....#####...####.
312 | .#.#. ....##############
313 | #...# ...###############
314 | #...# ...###############
315 | ##### ..#####......#####
316 | #...# .#####.......#####
317 | ====== #...# ====== #*###.........#### ======= Baseline
318 | || xOffset
319 |
320 | glyph->xOffset and yOffset are pixel offsets, in GFX coordinate space
321 | (+Y is down), from the cursor position to the top-left pixel of the
322 | glyph bitmap. i.e. yOffset is typically negative, xOffset is typically
323 | zero but a few glyphs will have other values (even negative xOffsets
324 | sometimes, totally normal). glyph->xAdvance is the distance to move
325 | the cursor on the X axis after drawing the corresponding symbol.
326 |
327 | There's also some changes with regard to 'background' color and new GFX
328 | fonts (classic fonts unchanged). See Adafruit_GFX.cpp for explanation.
329 | */
330 |
331 | #endif /* !ARDUINO */
332 |
--------------------------------------------------------------------------------
/fonts_opt.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitbank2/OneBitDisplay/5c5e1b9c2ebd08a63e66c39460514a9d811bb921/fonts_opt.jpg
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=OneBitDisplay
2 | version=2.3.3
3 | author=Larry Bank
4 | maintainer=Larry Bank
5 | sentence=OLED, LCD and e-paper library for 1-bit per pixel displays.
6 | paragraph=Supports most monochrome OLEDs, LCDs, Sharp Memory LCDs and many e-paper displays. Designed to provide a rich set of features with a simple API. Can automatically detect the display address (3C or 3D) and the controller type (SSD1306, SH1106 or SH1107). Includes 5 sizes of fixed fonts (6x8, 8x8, 12x16, 16x16, 16x32). Can use I2C, SPI or bit bang I2C+SPI on any GPIO pins with the use of my BitBang_I2C library. Supports display sizes of: 128x128, 128x64, 128x32, 64x32, 96x16, 72x40. Includes scrolling text/gfx, deferred rendering, lines, sprites, circles, rectangles and more.
7 | category=Display
8 | url=https://github.com/bitbank2/OneBitDisplay
9 | architectures=*
10 | includes=OneBitDisplay.h
11 | depends=BitBang_I2C
12 |
--------------------------------------------------------------------------------
/linux/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O2 -I../src -DSPI_BUS_NUMBER=0
2 | LIBS = -lm -lpthread
3 |
4 | all: libOneBitDisplay.a
5 |
6 | libOneBitDisplay.a: obd.o ../src/OneBitDisplay.h
7 | ar -rc libOneBitDisplay.a obd.o ;\
8 | sudo cp libOneBitDisplay.a /usr/local/lib ;\
9 | sudo cp ../src/OneBitDisplay.h /usr/local/include
10 |
11 | obd.o: obd.c ../src/obd.inl ../src/OneBitDisplay.h
12 | $(CC) $(CFLAGS) -D_LINUX_ obd.c
13 |
14 | clean:
15 | rm *.o libOneBitDisplay.a
16 |
--------------------------------------------------------------------------------
/linux/OLED_demo/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O3 -D_LINUX_ -DSPI_BUS_NUMBER=0
2 | LFLAGS= -larmbianio -pthread
3 | all: oled_demo
4 |
5 | oled_demo: main.o
6 | $(CC) -lpthread main.o $(LFLAGS) -o oled_demo
7 |
8 | main.o: main.c ../../src/obd.inl ../../src/OneBitDisplay.cpp ../../src/OneBitDisplay.h
9 | $(CC) $(CFLAGS) main.c
10 |
11 | clean:
12 | rm -rf *.o oled_demo
13 |
--------------------------------------------------------------------------------
/linux/OLED_demo/main.c:
--------------------------------------------------------------------------------
1 | //
2 | // main.c
3 | // OneBitDisplay library test program
4 | // Demonstrates many of the features for OLED displays
5 | //
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "../../src/OneBitDisplay.cpp"
19 |
20 | volatile int iStop = 0;
21 |
22 | #define OLED_TYPE OLED_128x64
23 | #define OLED_ADDR 0x3c
24 | #define FLIP180 0
25 | #define INVERT 0
26 | #define HW_I2C 1
27 | // On Linux this is the I2C bus number (SDA_PIN) for HW I2C
28 | #define SDA_PIN 1
29 | // On Linux this is the I2C device address
30 | #define SCL_PIN 0x3c
31 | #define RESET_PIN -1
32 | // This is not controlled on Linux through the API
33 | // On the Raspberry PI, see /boot/config.txt
34 | #define SPEED 0
35 | #define MAX_THREADS 2
36 | void *OLEDThread(void *);
37 |
38 | OBDISP obd[MAX_THREADS];
39 |
40 | void my_handler(int signal)
41 | {
42 | iStop = 1;
43 | } /* my_handler() */
44 |
45 | int main(int argc, const char *argv[])
46 | {
47 | int i, ID[MAX_THREADS];
48 | pthread_t tinfo[MAX_THREADS];
49 | struct sigaction sigIntHandler;
50 | size_t ret;
51 |
52 | // Set CTRL-C signal handler
53 | sigIntHandler.sa_handler = my_handler;
54 | sigemptyset(&sigIntHandler.sa_mask);
55 | sigIntHandler.sa_flags = 0;
56 | sigaction(SIGINT, &sigIntHandler, NULL);
57 |
58 | for (i=0; i
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include "../../src/OneBitDisplay.cpp"
18 |
19 | volatile int iStop = 0;
20 |
21 | #define DISPLAY_TYPE SHARP_400x240
22 | #define FLIP180 0
23 | #define INVERT 0
24 | #define DC_PIN -1
25 | #define CS_PIN 16
26 | #define DISP_PIN 18
27 | #define EXTCOM_PIN 22
28 | #define RESET_PIN -1
29 | #define SPEED 4000000
30 | #define BITBANG 0
31 | #define LED_PIN -1
32 | OBDISP obd;
33 | static uint8_t ucBuffer[12000];
34 |
35 | void my_handler(int signal)
36 | {
37 | iStop = 1;
38 | } /* my_handler() */
39 |
40 | int main(int argc, const char *argv[])
41 | {
42 | int i;
43 | struct sigaction sigIntHandler;
44 | //size_t ret;
45 |
46 | // Set CTRL-C signal handler
47 | sigIntHandler.sa_handler = my_handler;
48 | sigemptyset(&sigIntHandler.sa_mask);
49 | sigIntHandler.sa_flags = 0;
50 | sigaction(SIGINT, &sigIntHandler, NULL);
51 |
52 | printf("Sharp Memory LCD demo\n");
53 | printf("Press Ctrl-C to quit\n");
54 |
55 | i = AIOInitBoard("Raspberry Pi");
56 | if (i == 0) // problem
57 | {
58 | printf("Error in AIOInit(); check if this board is supported\n");
59 | return 0;
60 | }
61 | AIOAddGPIO(DISP_PIN, OUTPUT); // enable display
62 | AIOWriteGPIO(DISP_PIN, HIGH);
63 | AIOAddGPIO(EXTCOM_PIN, OUTPUT);
64 |
65 | //void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int bBitBang, int32_t iSpeed)
66 | obdSPIInit(&obd, DISPLAY_TYPE, DC_PIN, CS_PIN, RESET_PIN, -1, -1, LED_PIN, FLIP180, INVERT, BITBANG, SPEED);
67 | obdSetBackBuffer(&obd, ucBuffer);
68 | //obdSetRotation(&obd, 270);
69 | // Create some simple content
70 | obdFill(&obd, 0, 0);
71 | obdWriteString(&obd,0,0,0,"OneBitDisplay", FONT_16x32, OBD_BLACK, 0);
72 | for (int i=0; i<400; i+=3) {
73 | obdDrawLine(&obd, i, 0, 399-i, 239, OBD_BLACK, 0);
74 | obdDumpBuffer(&obd, NULL);
75 | }
76 | // for (int i=0; i<240; i+=3) {
77 | // obdDrawLine(&obd, 399, i, 0, 239-i, OBD_BLACK, 0);
78 | // }
79 | obdDumpBuffer(&obd, NULL);
80 | while (!iStop) { // toggle the EXTCOM signal until the user hits CTRL-C
81 | AIOWriteGPIO(EXTCOM_PIN, LOW);
82 | usleep(500000); // toggle ext com at 1hz
83 | AIOWriteGPIO(EXTCOM_PIN, HIGH);
84 | usleep(500000);
85 | }
86 | AIOWriteGPIO(DISP_PIN, LOW); // turn off LCD
87 | AIOShutdown();
88 | return 0;
89 | } /* main() */
90 |
--------------------------------------------------------------------------------
/linux/epd_cpp_demo/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O2 -DSPI_BUS_NUMBER=0 -D_LINUX_
2 | LIBS = -lpthread -larmbianio
3 | all: epd_demo
4 |
5 | epd_demo: main.o OneBitDisplay.o
6 | g++ main.o OneBitDisplay.o $(LIBS) -o epd_demo
7 |
8 | main.o: main.cpp ../../src/obd.inl ../../src/OneBitDisplay.cpp ../../src/OneBitDisplay.h
9 | g++ $(CFLAGS) main.cpp
10 |
11 | OneBitDisplay.o: ../../src/OneBitDisplay.cpp ../../src/OneBitDisplay.h ../../src/obd.inl
12 | g++ $(CFLAGS) ../../src/OneBitDisplay.cpp
13 |
14 | clean:
15 | rm -rf *.o epd_demo
16 |
--------------------------------------------------------------------------------
/linux/epd_cpp_demo/main.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Inky Phat (old) test
3 | // 104x212 e-paper (SSD1608)
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include "../../src/OneBitDisplay.h"
10 | //#include "Roboto_Black_40.h"
11 | //#include "Roboto_Black_20.h"
12 |
13 | ONE_BIT_DISPLAY epd;
14 |
15 | #define EPD_FREQ 2000000
16 | // Waveshare 2.13 250x122 hat
17 | #define INKY_CS 24
18 | #define INKY_BUSY 18
19 | #define INKY_DC 22
20 | #define INKY_RES 11
21 |
22 | //#define INKY_CS 27
23 | //#define INKY_BUSY 11
24 | //#define INKY_DC 15
25 | //#define INKY_RES 13
26 | #define INKY_MOSI -1
27 | #define INKY_SCK -1
28 |
29 | int main(int argc, char **argv)
30 | {
31 | AIOInitBoard("Raspberry Pi");
32 | printf("Starting...\n");
33 | epd.setSPIPins(INKY_CS, -1, -1, INKY_DC, INKY_RES, INKY_BUSY);
34 | epd.SPIbegin(EPD213_104x212, EPD_FREQ);
35 | epd.setRotation(270);
36 | epd.allocBuffer();
37 | epd.fillScreen(0);
38 |
39 | epd.setFont(FONT_12x16);
40 | epd.println("Inky Phat with");
41 | epd.println("OneBitDisplay lib");
42 | epd.setTextColor(OBD_RED);
43 | epd.println(1234, DEC);
44 | epd.println(4095, HEX);
45 | epd.display();
46 | printf("Display done\n");
47 | return 0;
48 | } /* main() */
49 |
--------------------------------------------------------------------------------
/linux/epd_demo/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O2 -DSPI_BUS_NUMBER=0 -D_LINUX_
2 | LIBS = -larmbianio -lOneBitDisplay -pthread
3 | all: epd_demo
4 |
5 | epd_demo: main.o
6 | $(CC) main.o $(LIBS) -o epd_demo
7 |
8 | main.o: main.c
9 | $(CC) $(CFLAGS) main.c
10 |
11 | clean:
12 | rm -rf *.o epd_demo
13 |
--------------------------------------------------------------------------------
/linux/epd_demo/Roboto_Black_28.h:
--------------------------------------------------------------------------------
1 | // Created by http://oleddisplay.squix.ch/ Consider a donation
2 | // In case of problems make sure that you are using the font file with the correct version!
3 | const uint8_t Roboto_Black_28Bitmaps[] PROGMEM = {
4 |
5 | // Bitmap Data:
6 | 0x00, // ' '
7 | 0xFB,0xEF,0x3C,0xF3,0xCF,0x3C,0xF3,0xCF,0x3C,0xF0,0x00,0x3C,0xF3,0xEF,0x3C, // '!'
8 | 0xF7,0x7B,0xB9,0xDC,0xEE,0x77,0x3B,0x9D,0xCE, // '"'
9 | 0x03,0x18,0x03,0x9C,0x01,0xCE,0x00,0xE7,0x00,0x73,0x80,0x39,0x81,0xFF,0xFC,0xFF,0xFE,0x7F,0xFF,0x07,0x38,0x03,0x9C,0x01,0xCC,0x0F,0xFF,0xE7,0xFF,0xF3,0xFF,0xF8,0x39,0xC0,0x1C,0xE0,0x0E,0x70,0x06,0x30,0x07,0x38,0x00, // '#'
10 | 0x03,0x80,0x07,0x00,0x0E,0x00,0x7E,0x01,0xFF,0x07,0xFF,0x1F,0xFE,0x3E,0x3E,0x78,0x7C,0xF8,0x01,0xF8,0x01,0xFC,0x01,0xFE,0x01,0xFE,0x00,0xFE,0x00,0x7E,0xF8,0x7D,0xF0,0xFB,0xF1,0xF3,0xFF,0xE7,0xFF,0x87,0xFE,0x03,0xF8,0x01,0x80,0x03,0x00,0x06,0x00, // '$'
11 | 0x3E,0x00,0x07,0xF0,0x00,0xFF,0x84,0x0E,0x38,0xE0,0xE3,0x8C,0x0E,0x39,0xC0,0xFF,0xB8,0x07,0xF3,0x80,0x3E,0x70,0x00,0x06,0x00,0x00,0xE0,0x00,0x1C,0xF0,0x01,0xFF,0xC0,0x3B,0xFC,0x07,0x39,0xE0,0x73,0x8E,0x0E,0x39,0xE0,0xE3,0xFC,0x14,0x3F,0xC0,0x00,0xF0, // '%'
12 | 0x07,0xC0,0x07,0xF8,0x03,0xFF,0x00,0xFF,0xC0,0x3C,0xF0,0x0F,0x1C,0x03,0xCF,0x00,0xFF,0x80,0x1F,0xC0,0x07,0xE0,0x03,0xF8,0xF1,0xFF,0x3C,0xFB,0xEF,0x3C,0x7F,0xCF,0x0F,0xE3,0xE1,0xF8,0xFF,0xFC,0x1F,0xFF,0x83,0xFF,0xF0,0x7E,0x3E, // '&'
13 | 0xF7,0xBD,0xEE,0x73,0x9C, // '''
14 | 0x02,0x0E,0x1E,0x1C,0x38,0x78,0x78,0x70,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,0xF0,0xF0,0x70,0x70,0x78,0x38,0x3C,0x1E,0x0E,0x02, // '('
15 | 0x80,0x70,0x3C,0x0F,0x03,0x81,0xE0,0x70,0x3C,0x1E,0x0F,0x07,0x81,0xC0,0xF0,0x78,0x3C,0x1E,0x0F,0x0F,0x07,0x83,0xC1,0xE1,0xE0,0xF0,0x70,0x78,0x78,0x38,0x10,0x00, // ')'
16 | 0x07,0x00,0x1C,0x00,0x70,0x18,0xC4,0x7B,0xFB,0xFF,0xC0,0x70,0x03,0xE0,0x1D,0xC0,0xE3,0x83,0x8E,0x04,0x20, // '*'
17 | 0x0F,0x80,0x3E,0x00,0xF8,0x03,0xE0,0x0F,0x83,0xFF,0xEF,0xFF,0xBF,0xFE,0xFF,0xF8,0x3E,0x00,0xF8,0x03,0xE0,0x0F,0x80,0x3E,0x00, // '+'
18 | 0x79,0xE7,0x9E,0x79,0xE7,0x38,0x60, // ','
19 | 0xFF,0x7F,0xBF,0xDF,0xE0, // '-'
20 | 0x73,0xCF,0xBE,0x70, // '.'
21 | 0x03,0xC0,0x70,0x0E,0x03,0xC0,0x70,0x0E,0x03,0xC0,0x70,0x0E,0x03,0xC0,0x70,0x0E,0x01,0xC0,0x78,0x0E,0x01,0xC0,0x78,0x0E,0x01,0xC0,0x78,0x0E,0x01,0xC0,0x00, // '/'
22 | 0x0F,0xC0,0x3F,0xC0,0xFF,0xC3,0xFF,0xC7,0xCF,0x9F,0x0F,0xBE,0x1F,0x7C,0x3E,0xF8,0x7D,0xF0,0xFB,0xE1,0xF7,0xC3,0xEF,0x87,0xDF,0x0F,0xBE,0x1F,0x3E,0x7C,0x7F,0xF8,0x7F,0xE0,0xFF,0xC0,0x7E,0x00, // '0'
23 | 0x00,0x81,0xE3,0xFB,0xFE,0xFF,0xBF,0xEC,0x78,0x1E,0x07,0x81,0xE0,0x78,0x1E,0x07,0x81,0xE0,0x78,0x1E,0x07,0x81,0xE0,0x78,0x1E, // '1'
24 | 0x0F,0xC0,0x7F,0xE1,0xFF,0xE7,0xFF,0xCF,0x8F,0x9F,0x0F,0x3C,0x1F,0x00,0x3C,0x00,0xF8,0x03,0xE0,0x0F,0x80,0x3F,0x00,0xFC,0x03,0xF0,0x0F,0xC0,0x3F,0x00,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xE0, // '2'
25 | 0x0F,0xC0,0x7F,0xE1,0xFF,0xE7,0xFF,0xCF,0x8F,0xDE,0x0F,0x80,0x1F,0x00,0x7C,0x0F,0xF8,0x1F,0xC0,0x3F,0xC0,0x7F,0xC0,0x07,0xC0,0x0F,0xBC,0x1F,0x7C,0x3E,0xFF,0xFC,0xFF,0xF0,0xFF,0xC0,0x7E,0x00, // '3'
26 | 0x01,0xF0,0x03,0xE0,0x0F,0xC0,0x3F,0x80,0x7F,0x01,0xFE,0x03,0xBC,0x0F,0x78,0x3C,0xF0,0x79,0xE1,0xE3,0xC7,0x87,0x8F,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0x00,0xF0,0x01,0xE0,0x03,0xC0,0x07,0x80, // '4'
27 | 0x3F,0xF8,0xFF,0xF1,0xFF,0xE3,0xFF,0xC7,0x80,0x0F,0x00,0x1E,0x00,0x3D,0xF0,0x7F,0xF0,0xFF,0xF3,0xFF,0xE0,0x87,0xE0,0x07,0xC0,0x0F,0xBE,0x1F,0x7C,0x7E,0xFF,0xF8,0xFF,0xF0,0xFF,0xC0,0x7E,0x00, // '5'
28 | 0x01,0xE0,0x0F,0xC0,0x7F,0x81,0xFF,0x03,0xF0,0x0F,0x80,0x1F,0x00,0x7D,0xF0,0xFF,0xF1,0xFF,0xF3,0xFF,0xF7,0xC3,0xEF,0x83,0xDF,0x07,0xBE,0x0F,0x3E,0x3E,0x7F,0xFC,0x7F,0xF0,0x7F,0xC0,0x3E,0x00, // '6'
29 | 0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xE0,0x07,0x80,0x1F,0x00,0x3C,0x00,0x78,0x01,0xF0,0x03,0xC0,0x0F,0x80,0x1E,0x00,0x7C,0x00,0xF0,0x03,0xE0,0x07,0xC0,0x1F,0x00,0x3E,0x00,0xF8,0x01,0xF0,0x00, // '7'
30 | 0x0F,0xC0,0x7F,0xE1,0xFF,0xE3,0xFF,0xC7,0xCF,0x9F,0x0F,0x9E,0x1E,0x3E,0x7C,0x7F,0xF8,0x7F,0xE0,0xFF,0xC3,0xFF,0xCF,0x87,0xDF,0x0F,0xBE,0x1F,0x7C,0x3E,0xFF,0xFC,0xFF,0xF0,0xFF,0xC0,0x7E,0x00, // '8'
31 | 0x0F,0xC0,0x3F,0xC0,0xFF,0xC3,0xFF,0xC7,0xCF,0x9F,0x0F,0xBE,0x1F,0x7C,0x3E,0xF8,0x7D,0xF8,0xF9,0xFF,0xF3,0xFF,0xE3,0xFF,0xC3,0xEF,0x00,0x3E,0x00,0xF8,0x1F,0xF0,0x3F,0xC0,0x7E,0x00,0xF0,0x00, // '9'
32 | 0x73,0xCF,0xBE,0x70,0x00,0x00,0x00,0x00,0x1C,0xF3,0xEF,0x9C, // ':'
33 | 0x38,0xF1,0xF3,0xE3,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x1E,0x3C,0x78,0xF1,0xE3,0x8E,0x0C,0x00, // ';'
34 | 0x00,0x30,0x07,0x81,0xFC,0x3F,0xEF,0xFC,0x7F,0x03,0xC0,0x1F,0xC0,0xFF,0xC0,0xFF,0x81,0xFC,0x01,0xE0,0x03,0x00, // '<'
35 | 0xFF,0xF7,0xFF,0xBF,0xFD,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xDF,0xFE,0xFF,0xF7,0xFF,0x80, // '='
36 | 0x80,0x07,0x00,0x3F,0x01,0xFE,0x07,0xFE,0x07,0xF8,0x07,0xC1,0xFE,0x7F,0xE7,0xF8,0x3F,0x01,0xC0,0x08,0x00,0x00, // '>'
37 | 0x0F,0xC0,0xFF,0xC7,0xFF,0x9F,0xFE,0xF8,0xF8,0x01,0xE0,0x0F,0x80,0x7C,0x03,0xF0,0x1F,0x00,0x78,0x01,0xE0,0x07,0x80,0x00,0x00,0x00,0x01,0xC0,0x0F,0x80,0x3E,0x00,0xF8,0x01,0xC0, // '?'
38 | 0x00,0x7F,0x00,0x03,0xFF,0xC0,0x07,0xFF,0xF0,0x0F,0x81,0xF8,0x1E,0x00,0x78,0x3C,0x00,0x1C,0x78,0x3E,0x1C,0x70,0x7F,0x8E,0x70,0xFF,0x8E,0xF1,0xE3,0x8E,0xE1,0xC7,0x8E,0xE3,0xC7,0x0E,0xE3,0x87,0x0E,0xE3,0x87,0x0E,0xE3,0x87,0x0E,0xE3,0xCF,0x1C,0xE3,0xFF,0xFC,0xF1,0xFB,0xF8,0x70,0xF1,0xE0,0x78,0x00,0x00,0x3C,0x00,0x00,0x3F,0x01,0x00,0x1F,0xFF,0x00,0x07,0xFF,0x00,0x01,0xFC,0x00, // '@'
39 | 0x01,0xF0,0x00,0x1F,0x00,0x03,0xF8,0x00,0x3F,0x80,0x03,0xF8,0x00,0x7F,0xC0,0x07,0xBC,0x00,0x7B,0xE0,0x0F,0xBE,0x00,0xF1,0xE0,0x1F,0x1F,0x01,0xF1,0xF0,0x1F,0x0F,0x03,0xFF,0xF8,0x3F,0xFF,0x83,0xFF,0xF8,0x7F,0xFF,0xC7,0xC0,0x7C,0xFC,0x07,0xEF,0x80,0x3E, // 'A'
40 | 0xFF,0xE0,0x7F,0xFE,0x3F,0xFF,0x9F,0xFF,0xCF,0x83,0xE7,0xC0,0xF3,0xE0,0x79,0xF0,0x7C,0xFF,0xFE,0x7F,0xFC,0x3F,0xFF,0x1F,0xFF,0xCF,0x83,0xF7,0xC0,0xFB,0xE0,0x7D,0xF0,0x7E,0xFF,0xFE,0x7F,0xFF,0x3F,0xFF,0x1F,0xFE,0x00, // 'B'
41 | 0x07,0xE0,0x0F,0xFC,0x0F,0xFF,0x8F,0xFF,0xC7,0xC3,0xF7,0xC0,0xFB,0xE0,0x3D,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x7B,0xE0,0x7C,0xF8,0x7E,0x7F,0xFE,0x1F,0xFF,0x07,0xFF,0x00,0xFE,0x00, // 'C'
42 | 0xFF,0x80,0xFF,0xE0,0xFF,0xF0,0xFF,0xF8,0xF0,0xFC,0xF0,0x7C,0xF0,0x3E,0xF0,0x3E,0xF0,0x3E,0xF0,0x3E,0xF0,0x3E,0xF0,0x3E,0xF0,0x3E,0xF0,0x3E,0xF0,0x7C,0xF0,0xFC,0xFF,0xF8,0xFF,0xF0,0xFF,0xE0,0xFF,0x80, // 'D'
43 | 0xFF,0xFB,0xFF,0xEF,0xFF,0xBF,0xFE,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xFF,0xF3,0xFF,0xCF,0xFF,0x3F,0xFC,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xFF,0xFB,0xFF,0xEF,0xFF,0xBF,0xFE, // 'E'
44 | 0xFF,0xFB,0xFF,0xEF,0xFF,0xBF,0xFE,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xFF,0xF3,0xFF,0xCF,0xFF,0x3F,0xFC,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00, // 'F'
45 | 0x03,0xF0,0x03,0xFF,0x03,0xFF,0xE0,0xFF,0xFC,0x7E,0x1F,0x1F,0x03,0xEF,0x80,0xFB,0xE0,0x00,0xF8,0x00,0x3E,0x1F,0xEF,0x87,0xFB,0xE1,0xFE,0xF8,0x7F,0xBE,0x03,0xE7,0xC0,0xF9,0xF8,0x3E,0x3F,0xFF,0x8F,0xFF,0xE0,0xFF,0xE0,0x0F,0xE0, // 'G'
46 | 0xF0,0x1F,0x78,0x0F,0xBC,0x07,0xDE,0x03,0xEF,0x01,0xF7,0x80,0xFB,0xC0,0x7D,0xE0,0x3E,0xFF,0xFF,0x7F,0xFF,0xBF,0xFF,0xDF,0xFF,0xEF,0x01,0xF7,0x80,0xFB,0xC0,0x7D,0xE0,0x3E,0xF0,0x1F,0x78,0x0F,0xBC,0x07,0xDE,0x03,0xE0, // 'H'
47 | 0xFB,0xEF,0xBE,0xFB,0xEF,0xBE,0xFB,0xEF,0xBE,0xFB,0xEF,0xBE,0xFB,0xEF,0xBE, // 'I'
48 | 0x00,0x78,0x01,0xE0,0x07,0x80,0x1E,0x00,0x78,0x01,0xE0,0x07,0x80,0x1E,0x00,0x78,0x01,0xE0,0x07,0x80,0x1E,0x00,0x7B,0xC1,0xEF,0x8F,0xBE,0x3E,0xFF,0xF9,0xFF,0xC3,0xFE,0x07,0xE0, // 'J'
49 | 0xF0,0x3F,0x78,0x3F,0x3C,0x1F,0x1E,0x1F,0x8F,0x1F,0x87,0x8F,0x83,0xCF,0x81,0xEF,0xC0,0xF7,0xC0,0x7F,0xE0,0x3F,0xF8,0x1F,0xFC,0x0F,0xFF,0x07,0xCF,0x83,0xE7,0xE1,0xE1,0xF8,0xF0,0x7C,0x78,0x3F,0x3C,0x0F,0x9E,0x07,0xE0, // 'K'
50 | 0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xFF,0xFB,0xFF,0xEF,0xFF,0xBF,0xFE, // 'L'
51 | 0xFC,0x01,0xFB,0xF0,0x0F,0xEF,0xE0,0x3F,0xBF,0x80,0xFE,0xFE,0x07,0xFB,0xFC,0x1F,0xEF,0xF0,0x77,0xBF,0xC3,0xDE,0xF7,0x8F,0x7B,0xDE,0x3B,0xEF,0x79,0xEF,0xBC,0xE7,0xBE,0xF3,0xDC,0xFB,0xCF,0xF3,0xEF,0x1F,0xCF,0xBC,0x7E,0x3E,0xF1,0xF8,0xFB,0xC3,0xE3,0xEF,0x0F,0x0F,0xBC,0x3C,0x3E, // 'M'
52 | 0xF8,0x0F,0x7C,0x07,0xBF,0x03,0xDF,0xC1,0xEF,0xE0,0xF7,0xF8,0x7B,0xFC,0x3D,0xFF,0x1E,0xFF,0x8F,0x7D,0xE7,0xBE,0xF3,0xDF,0x3D,0xEF,0x9F,0xF7,0xC7,0xFB,0xE3,0xFD,0xF0,0xFE,0xF8,0x3F,0x7C,0x1F,0xBE,0x07,0xDF,0x03,0xE0, // 'N'
53 | 0x07,0xE0,0x07,0xFE,0x03,0xFF,0xE1,0xFF,0xF8,0x7E,0x3F,0x3F,0x07,0xCF,0x80,0xFB,0xE0,0x3E,0xF8,0x0F,0xBE,0x03,0xEF,0x80,0xFB,0xE0,0x3E,0xF8,0x0F,0xBE,0x03,0xEF,0xC1,0xF9,0xF8,0xFC,0x7F,0xFF,0x0F,0xFF,0x81,0xFF,0xC0,0x1F,0xC0, // 'O'
54 | 0xFF,0xE0,0x7F,0xFC,0x3F,0xFF,0x9F,0xFF,0xCF,0x83,0xF7,0xC0,0xFB,0xE0,0x7D,0xF0,0x3E,0xF8,0x3F,0x7F,0xFF,0x3F,0xFF,0x9F,0xFF,0x8F,0xFF,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x00, // 'P'
55 | 0x07,0xE0,0x07,0xFE,0x03,0xFF,0xE1,0xFF,0xF8,0x7E,0x3F,0x3F,0x07,0xCF,0x80,0xFB,0xE0,0x3E,0xF8,0x0F,0xBE,0x03,0xEF,0x80,0xFB,0xE0,0x3E,0xF8,0x0F,0xBE,0x03,0xEF,0xC1,0xF9,0xF8,0xFC,0x7F,0xFF,0x0F,0xFF,0x81,0xFF,0xC0,0x1F,0xF8,0x00,0x3F,0x80,0x03,0xC0,0x00,0x60, // 'Q'
56 | 0xFF,0xF0,0x7F,0xFE,0x3F,0xFF,0x9F,0xFF,0xCF,0x83,0xF7,0xC0,0xFB,0xE0,0x7D,0xF0,0x3E,0xF8,0x3E,0x7F,0xFF,0x3F,0xFF,0x1F,0xFF,0x0F,0xFF,0x87,0xC7,0xC3,0xE1,0xF1,0xF0,0xF8,0xF8,0x3E,0x7C,0x1F,0x3E,0x07,0xDF,0x03,0xE0, // 'R'
57 | 0x07,0xE0,0x0F,0xFC,0x0F,0xFF,0x8F,0xFF,0xC7,0xC3,0xF3,0xE0,0xF9,0xF0,0x00,0xFE,0x00,0x3F,0xE0,0x0F,0xFC,0x03,0xFF,0x00,0x3F,0xC0,0x03,0xF7,0xC0,0xFB,0xE0,0x7D,0xF8,0x7E,0x7F,0xFE,0x1F,0xFF,0x07,0xFF,0x00,0xFE,0x00, // 'S'
58 | 0xFF,0xFF,0x7F,0xFF,0xBF,0xFF,0xDF,0xFF,0xE0,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00, // 'T'
59 | 0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF0,0x1E,0xF8,0x3E,0xF8,0x3E,0xFC,0x7E,0xFF,0xFE,0x7F,0xFC,0x3F,0xF8,0x0F,0xE0, // 'U'
60 | 0xFC,0x07,0xE7,0xC0,0x7C,0x7C,0x07,0xC7,0xC0,0xFC,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x81,0xF1,0xF0,0x1F,0x1F,0x01,0xF1,0xF0,0x0F,0x1E,0x00,0xFB,0xE0,0x0F,0xBE,0x00,0x7B,0xC0,0x07,0xFC,0x00,0x7F,0xC0,0x03,0xF8,0x00,0x3F,0x80,0x03,0xF8,0x00,0x1F,0x00, // 'V'
61 | 0xF8,0x3C,0x1F,0x7C,0x1E,0x0F,0x9E,0x1F,0x87,0x8F,0x8F,0xC7,0xC7,0xC7,0xE3,0xE3,0xE3,0xF1,0xF0,0xF3,0xF8,0xF0,0x79,0xFE,0x78,0x3C,0xFF,0x7C,0x1F,0x7F,0xBE,0x0F,0xBF,0xDF,0x03,0xFC,0xFF,0x01,0xFE,0x7F,0x80,0xFF,0x3F,0xC0,0x7F,0x9F,0xE0,0x3F,0x87,0xF0,0x0F,0xC3,0xF0,0x07,0xE1,0xF8,0x03,0xF0,0xFC,0x01,0xF0,0x7E,0x00, // 'W'
62 | 0xFC,0x0F,0xCF,0x83,0xF0,0xF8,0x7C,0x1F,0x1F,0x81,0xF3,0xE0,0x3E,0xFC,0x03,0xFF,0x00,0x7F,0xC0,0x07,0xF8,0x00,0x7E,0x00,0x1F,0xC0,0x03,0xFC,0x00,0xFF,0xC0,0x1F,0xF8,0x07,0xCF,0x80,0xF9,0xF0,0x3E,0x1F,0x0F,0xC3,0xE1,0xF0,0x3E,0x7E,0x07,0xE0, // 'X'
63 | 0xF8,0x0F,0xCF,0x81,0xF1,0xF0,0x7C,0x1F,0x0F,0x83,0xE1,0xE0,0x3C,0x7C,0x07,0xCF,0x00,0x7B,0xE0,0x0F,0xF8,0x00,0xFF,0x00,0x1F,0xC0,0x01,0xF8,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00, // 'Y'
64 | 0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0x00,0x7C,0x00,0xF8,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x07,0xC0,0x0F,0x80,0x1F,0x00,0x1F,0x00,0x3E,0x00,0x7C,0x00,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE, // 'Z'
65 | 0xFE,0xFE,0xFE,0xFE,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xFE,0xFE,0xFE,0xFE, // '['
66 | 0xF8,0x03,0xE0,0x07,0x80,0x1F,0x00,0x7C,0x00,0xF8,0x03,0xE0,0x07,0x80,0x1F,0x00,0x7C,0x00,0xF0,0x03,0xE0,0x0F,0x80,0x1F,0x00,0x7C,0x00,0xF0,0x03,0xE0,0x0F,0x80,0x1F,0x00,0x7C,0x01,0xF0,0x03,0xE0, // '\'
67 | 0xFD,0xFB,0xF7,0xE3,0xC7,0x8F,0x1E,0x3C,0x78,0xF1,0xE3,0xC7,0x8F,0x1E,0x3C,0x78,0xF1,0xE3,0xC7,0x8F,0x1E,0xFD,0xFB,0xF7,0xE0, // ']'
68 | 0x0E,0x01,0xF0,0x1F,0x03,0xF8,0x3B,0x83,0xB8,0x79,0xC7,0x1C,0xF1,0xEE,0x0E, // '^'
69 | 0xFF,0xF7,0xFF,0xBF,0xFC, // '_'
70 | 0xF8,0x7C,0x3E,0x1E, // '`'
71 | 0x0F,0x80,0xFF,0x87,0xFF,0x3F,0xFC,0xF8,0xF8,0x03,0xE1,0xFF,0x9F,0xFE,0xFF,0xFB,0xE3,0xEF,0x0F,0xBF,0xFE,0xFF,0xF9,0xFF,0xE3,0xEF,0x80, // 'a'
72 | 0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x1F,0x00,0x3E,0xF8,0x7F,0xF8,0xFF,0xF9,0xFF,0xF3,0xF1,0xF7,0xC3,0xEF,0x87,0xDF,0x07,0xBE,0x1F,0x7C,0x3E,0xFC,0x7D,0xFF,0xFB,0xFF,0xE7,0xFF,0x8F,0xBE,0x00, // 'b'
73 | 0x0F,0xC0,0xFF,0x87,0xFF,0x1F,0xFE,0xF8,0xFB,0xE1,0xEF,0x80,0x3E,0x00,0xF8,0x03,0xE0,0x0F,0x8F,0x9F,0xFE,0x7F,0xF0,0xFF,0x80,0xFC,0x00, // 'c'
74 | 0x00,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x87,0xDF,0x1F,0xFE,0x7F,0xFD,0xFF,0xFB,0xE3,0xF7,0xC3,0xEF,0x07,0xDE,0x0F,0xBC,0x1F,0x7C,0x3E,0xF8,0xFC,0xFF,0xF9,0xFF,0xF1,0xFF,0xE1,0xF7,0xC0, // 'd'
75 | 0x0F,0xC0,0x7F,0xC1,0xFF,0xC3,0xFF,0xCF,0x87,0x9F,0x0F,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xF0,0x03,0xF0,0xC3,0xFF,0xC7,0xFF,0x87,0xFE,0x03,0xF0,0x00, // 'e'
76 | 0x07,0xC1,0xF8,0x7F,0x1F,0xE3,0xE0,0x7C,0x3F,0xF7,0xFE,0xFF,0xDF,0xF8,0xF8,0x1F,0x03,0xE0,0x7C,0x0F,0x81,0xF0,0x3E,0x07,0xC0,0xF8,0x1F,0x03,0xE0, // 'f'
77 | 0x1F,0x7C,0x7F,0xF9,0xFF,0xF7,0xFF,0xEF,0x87,0xDF,0x0F,0xBC,0x1F,0x78,0x3E,0xF0,0x7D,0xF0,0xFB,0xE1,0xF7,0xFF,0xE7,0xFF,0xC7,0xFF,0x87,0xDF,0x00,0x3E,0x30,0xF8,0xFF,0xF1,0xFF,0xC1,0xFF,0x00,0xF8,0x00, // 'g'
78 | 0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x1F,0x00,0x3E,0xF8,0x7F,0xF8,0xFF,0xF9,0xFF,0xF3,0xE3,0xF7,0xC3,0xEF,0x87,0xDF,0x0F,0xBE,0x1F,0x7C,0x3E,0xF8,0x7D,0xF0,0xFB,0xE1,0xF7,0xC3,0xEF,0x87,0xC0, // 'h'
79 | 0x78,0xF3,0xF3,0xC7,0x80,0x00,0x3C,0x78,0xF1,0xE3,0xC7,0x8F,0x1E,0x3C,0x78,0xF1,0xE3,0xC7,0x8F,0x00, // 'i'
80 | 0x1E,0x0F,0x0F,0xC3,0xC1,0xE0,0x00,0x00,0x3C,0x1E,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0x78,0x3C,0x1E,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0x78,0x7C,0xFE,0x7F,0x3F,0x1E,0x00, // 'j'
81 | 0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0x00,0xF8,0xFC,0xF8,0xF8,0xF9,0xF0,0xFB,0xE0,0xFF,0xE0,0xFF,0xC0,0xFF,0x80,0xFF,0xC0,0xFF,0xE0,0xFF,0xE0,0xF9,0xF0,0xF9,0xF8,0xF8,0xF8,0xF8,0x7C,0xF8,0x7E, // 'k'
82 | 0xF7,0xBD,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x00, // 'l'
83 | 0xF9,0xE1,0xE1,0xFF,0xEF,0xF3,0xFF,0xFF,0xE7,0xFF,0xFF,0xCF,0x8F,0xC7,0xDF,0x0F,0x0F,0xBE,0x1E,0x1F,0x7C,0x3C,0x3E,0xF8,0x78,0x7D,0xF0,0xF0,0xFB,0xE1,0xE1,0xF7,0xC3,0xC3,0xEF,0x87,0x87,0xDF,0x0F,0x0F,0xBE,0x1E,0x1F,0x00, // 'm'
84 | 0xFB,0xE1,0xFF,0xF3,0xFF,0xE7,0xFF,0xCF,0x87,0xDF,0x0F,0xBE,0x1F,0x7C,0x3E,0xF8,0x7D,0xF0,0xFB,0xE1,0xF7,0xC3,0xEF,0x87,0xDF,0x0F,0xBE,0x1F,0x00, // 'n'
85 | 0x0F,0xC0,0x7F,0xC1,0xFF,0xC3,0xFF,0xCF,0x8F,0xDF,0x0F,0xBC,0x1F,0x78,0x3E,0xF0,0x7D,0xF0,0xFB,0xE3,0xF3,0xFF,0xC7,0xFF,0x87,0xFE,0x03,0xF0,0x00, // 'o'
86 | 0xFB,0xE1,0xFF,0xE3,0xFF,0xE7,0xFF,0xCF,0xC7,0xDF,0x0F,0xBE,0x1F,0x7C,0x1E,0xF8,0x7D,0xF0,0xFB,0xF1,0xF7,0xFF,0xCF,0xFF,0x9F,0xFE,0x3E,0xF8,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x00, // 'p'
87 | 0x1F,0x7C,0x7F,0xF9,0xFF,0xF7,0xFF,0xEF,0x8F,0xDF,0x0F,0xBC,0x1F,0x78,0x3E,0xF0,0x7D,0xF0,0xFB,0xE3,0xF7,0xFF,0xE7,0xFF,0xC7,0xFF,0x87,0xDF,0x00,0x3E,0x00,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0, // 'q'
88 | 0xF7,0xBF,0xEF,0xF3,0xFC,0xF8,0x3C,0x0F,0x03,0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xF0,0x3C,0x0F,0x00, // 'r'
89 | 0x0F,0xC0,0xFF,0xC7,0xFF,0x9F,0xFE,0x78,0xF9,0xE0,0x07,0xFC,0x0F,0xFC,0x0F,0xF8,0x03,0xEF,0x87,0x9F,0xFE,0x7F,0xF8,0xFF,0xC0,0xFC,0x00, // 's'
90 | 0x3E,0x0F,0x83,0xE0,0xF8,0xFF,0xBF,0xEF,0xFB,0xFE,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xFE,0x3F,0x87,0xE0,0xF8, // 't'
91 | 0xF8,0x7D,0xF0,0xFB,0xE1,0xF7,0xC3,0xEF,0x87,0xDF,0x0F,0xBE,0x1F,0x7C,0x3E,0xF8,0x7D,0xF0,0xFB,0xE3,0xF3,0xFF,0xE7,0xFF,0xCF,0xFF,0x87,0xDF,0x00, // 'u'
92 | 0xF8,0x7D,0xF0,0xF9,0xE1,0xE3,0xE7,0xC7,0xCF,0x87,0x9E,0x0F,0x3C,0x1E,0xF8,0x1F,0xE0,0x3F,0xC0,0x7F,0x80,0x7E,0x00,0xFC,0x01,0xF8,0x03,0xF0,0x00, // 'v'
93 | 0xF8,0xF1,0xF7,0xC7,0x8F,0x1E,0x3C,0x78,0xF3,0xF3,0xC7,0x9F,0x9E,0x3C,0xFD,0xF0,0xF7,0xEF,0x07,0xFF,0xF8,0x3F,0x9F,0xC1,0xFC,0xFE,0x07,0xE7,0xE0,0x3F,0x3F,0x01,0xF0,0xF8,0x0F,0x87,0xC0,0x3C,0x3C,0x00, // 'w'
94 | 0xF8,0x7C,0xF8,0xF0,0xF3,0xE1,0xF7,0x81,0xFF,0x03,0xFC,0x03,0xF8,0x07,0xE0,0x0F,0xE0,0x3F,0xC0,0x7F,0xC1,0xF7,0xC7,0xCF,0x8F,0x8F,0xBE,0x1F,0x00, // 'x'
95 | 0xF8,0x3E,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x3C,0x78,0x3E,0xF8,0x3E,0xF8,0x1E,0xF0,0x1F,0xF0,0x0F,0xF0,0x0F,0xE0,0x0F,0xE0,0x07,0xE0,0x07,0xC0,0x07,0xC0,0x07,0xC0,0x0F,0x80,0x3F,0x80,0x3F,0x00,0x3F,0x00,0x3C,0x00, // 'y'
96 | 0xFF,0xF7,0xFF,0xBF,0xFD,0xFF,0xE0,0x3E,0x03,0xE0,0x3E,0x01,0xF0,0x1F,0x01,0xF0,0x1F,0x01,0xFF,0xEF,0xFF,0x7F,0xFB,0xFF,0xC0, // 'z'
97 | 0x06,0x07,0x07,0xC7,0x83,0xC1,0xE0,0xF0,0x78,0x3C,0x1E,0x0F,0x0F,0x0F,0x87,0x03,0xE0,0xF0,0x3C,0x1E,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0x78,0x1E,0x07,0x81,0x80, // '{'
98 | 0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE,0xEE, // '|'
99 | 0xC0,0x70,0x3C,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0x78,0x3C,0x1E,0x07,0x83,0xF0,0x78,0xFC,0x78,0x78,0x3C,0x1E,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0xF0,0x70,0x30,0x00 // '}'
100 | };
101 | const GFXglyph Roboto_Black_28Glyphs[] PROGMEM = {
102 | // bitmapOffset, width, height, xAdvance, xOffset, yOffset
103 | { 0, 1, 1, 8, 0, 0 }, // ' '
104 | { 1, 6, 20, 9, 2, -20 }, // '!'
105 | { 16, 9, 8, 10, 0, -21 }, // '"'
106 | { 25, 17, 20, 17, 0, -20 }, // '#'
107 | { 68, 15, 26, 17, 1, -23 }, // '$'
108 | { 117, 20, 20, 22, 1, -20 }, // '%'
109 | { 167, 18, 20, 20, 1, -20 }, // '&'
110 | { 212, 5, 8, 5, 0, -21 }, // '''
111 | { 217, 8, 28, 11, 2, -22 }, // '('
112 | { 245, 9, 28, 11, 1, -22 }, // ')'
113 | { 277, 14, 12, 14, 0, -20 }, // '*'
114 | { 298, 14, 14, 16, 1, -16 }, // '+'
115 | { 323, 6, 9, 9, 1, -3 }, // ','
116 | { 330, 9, 4, 14, 2, -10 }, // '-'
117 | { 335, 6, 5, 9, 2, -5 }, // '.'
118 | { 339, 11, 22, 11, 0, -20 }, // '/'
119 | { 370, 15, 20, 17, 1, -20 }, // '0'
120 | { 408, 10, 20, 17, 2, -20 }, // '1'
121 | { 433, 15, 20, 17, 1, -20 }, // '2'
122 | { 471, 15, 20, 17, 1, -20 }, // '3'
123 | { 509, 15, 20, 17, 1, -20 }, // '4'
124 | { 547, 15, 20, 17, 1, -20 }, // '5'
125 | { 585, 15, 20, 17, 1, -20 }, // '6'
126 | { 623, 15, 20, 17, 1, -20 }, // '7'
127 | { 661, 15, 20, 17, 1, -20 }, // '8'
128 | { 699, 15, 20, 17, 1, -20 }, // '9'
129 | { 737, 6, 16, 9, 2, -16 }, // ':'
130 | { 749, 7, 22, 9, 1, -16 }, // ';'
131 | { 769, 13, 13, 15, 1, -15 }, // '<'
132 | { 791, 13, 10, 17, 2, -13 }, // '='
133 | { 808, 13, 13, 15, 2, -15 }, // '>'
134 | { 830, 14, 20, 15, 0, -20 }, // '?'
135 | { 865, 24, 25, 26, 1, -19 }, // '@'
136 | { 940, 20, 20, 20, 0, -20 }, // 'A'
137 | { 990, 17, 20, 19, 1, -20 }, // 'B'
138 | { 1033, 17, 20, 19, 1, -20 }, // 'C'
139 | { 1076, 16, 20, 19, 2, -20 }, // 'D'
140 | { 1116, 14, 20, 17, 2, -20 }, // 'E'
141 | { 1151, 14, 20, 16, 2, -20 }, // 'F'
142 | { 1186, 18, 20, 20, 1, -20 }, // 'G'
143 | { 1231, 17, 20, 21, 2, -20 }, // 'H'
144 | { 1274, 6, 20, 9, 2, -20 }, // 'I'
145 | { 1289, 14, 20, 17, 1, -20 }, // 'J'
146 | { 1324, 17, 20, 19, 2, -20 }, // 'K'
147 | { 1367, 14, 20, 16, 2, -20 }, // 'L'
148 | { 1402, 22, 20, 26, 2, -20 }, // 'M'
149 | { 1457, 17, 20, 21, 2, -20 }, // 'N'
150 | { 1500, 18, 20, 20, 1, -20 }, // 'O'
151 | { 1545, 17, 20, 19, 1, -20 }, // 'P'
152 | { 1588, 18, 23, 20, 1, -20 }, // 'Q'
153 | { 1640, 17, 20, 19, 1, -20 }, // 'R'
154 | { 1683, 17, 20, 19, 1, -20 }, // 'S'
155 | { 1726, 17, 20, 19, 1, -20 }, // 'T'
156 | { 1769, 16, 20, 20, 2, -20 }, // 'U'
157 | { 1809, 20, 20, 20, 0, -20 }, // 'V'
158 | { 1859, 25, 20, 25, 0, -20 }, // 'W'
159 | { 1922, 19, 20, 19, 0, -20 }, // 'X'
160 | { 1970, 19, 20, 19, 0, -20 }, // 'Y'
161 | { 2018, 16, 20, 18, 1, -20 }, // 'Z'
162 | { 2058, 8, 28, 9, 1, -23 }, // '['
163 | { 2086, 14, 22, 13, 0, -20 }, // '\'
164 | { 2125, 7, 28, 9, 0, -23 }, // ']'
165 | { 2150, 12, 10, 14, 1, -20 }, // '^'
166 | { 2165, 13, 3, 13, 0, 0 }, // '_'
167 | { 2170, 8, 4, 11, 1, -21 }, // '`'
168 | { 2174, 14, 15, 16, 1, -15 }, // 'a'
169 | { 2201, 15, 21, 17, 1, -21 }, // 'b'
170 | { 2241, 14, 15, 16, 1, -15 }, // 'c'
171 | { 2268, 15, 21, 17, 1, -21 }, // 'd'
172 | { 2308, 15, 15, 16, 1, -15 }, // 'e'
173 | { 2337, 11, 21, 11, 0, -21 }, // 'f'
174 | { 2366, 15, 21, 17, 1, -15 }, // 'g'
175 | { 2406, 15, 21, 17, 1, -21 }, // 'h'
176 | { 2446, 7, 22, 9, 1, -22 }, // 'i'
177 | { 2466, 9, 28, 9, -1, -22 }, // 'j'
178 | { 2498, 16, 21, 16, 1, -21 }, // 'k'
179 | { 2540, 5, 21, 9, 2, -21 }, // 'l'
180 | { 2554, 23, 15, 25, 1, -15 }, // 'm'
181 | { 2598, 15, 15, 17, 1, -15 }, // 'n'
182 | { 2627, 15, 15, 17, 1, -15 }, // 'o'
183 | { 2656, 15, 21, 17, 1, -15 }, // 'p'
184 | { 2696, 15, 21, 17, 1, -15 }, // 'q'
185 | { 2736, 10, 15, 12, 2, -15 }, // 'r'
186 | { 2755, 14, 15, 15, 0, -15 }, // 's'
187 | { 2782, 10, 19, 11, 0, -19 }, // 't'
188 | { 2806, 15, 15, 17, 1, -15 }, // 'u'
189 | { 2835, 15, 15, 15, 0, -15 }, // 'v'
190 | { 2864, 21, 15, 21, 0, -15 }, // 'w'
191 | { 2904, 15, 15, 15, 0, -15 }, // 'x'
192 | { 2933, 16, 21, 16, 0, -15 }, // 'y'
193 | { 2975, 13, 15, 15, 1, -15 }, // 'z'
194 | { 3000, 9, 27, 10, 1, -22 }, // '{'
195 | { 3031, 4, 24, 8, 2, -20 }, // '|'
196 | { 3043, 9, 27, 10, 1, -22 } // '}'
197 | };
198 | const GFXfont Roboto_Black_28 PROGMEM = {
199 | (uint8_t *)Roboto_Black_28Bitmaps,(GFXglyph *)Roboto_Black_28Glyphs,0x20, 0x7E, 33};
200 |
201 |
--------------------------------------------------------------------------------
/linux/epd_demo/main.c:
--------------------------------------------------------------------------------
1 | //
2 | // WaveShare 2.7" e-paper HAT demo
3 | // The same hardware connection numbers should work
4 | // on other WaveShare hats
5 | //
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | //#include "../../src/OneBitDisplay.cpp"
13 | #include "Roboto_Black_28.h"
14 |
15 | OBDISP epd;
16 |
17 | #define EPD_FREQ 4000000
18 | // header pin numbers, NOT BCM
19 | #define INKY_CS 24
20 | #define INKY_BUSY 18
21 | #define INKY_DC 22
22 | #define INKY_RES 11
23 | #define FLIP180 0
24 | #define INVERT 0
25 | #define BITBANG 0
26 |
27 | int main(int argc, char **argv)
28 | {
29 | int i;
30 |
31 | printf("Starting...\n");
32 | i = AIOInitBoard("Raspberry Pi");
33 | if (i == 0) // problem
34 | {
35 | printf("Error in AIOInitBoard(); check if this board is supported\n");
36 | return 0;
37 | }
38 |
39 | obdSPIInit(&epd, EPD27_176x264, INKY_DC, INKY_CS, INKY_RES, -1, -1, INKY_BUSY, FLIP180, INVERT, BITBANG, EPD_FREQ);
40 | obdSetRotation(&epd, 90);
41 | obdAllocBuffer(&epd);
42 | obdFill(&epd, 0, 0);
43 | obdWriteString(&epd, 0,0,0,(char *)"WaveShare 2.7\" e-paper", FONT_12x16, OBD_BLACK, 0);
44 | obdWriteString(&epd, 0,0,16,(char *)"OneBitDisplay lib in C", FONT_12x16,OBD_BLACK,0);
45 | obdEllipse(&epd,epd.width/2, epd.height/2, 40,40,OBD_BLACK,1);
46 | obdWriteStringCustom(&epd, (GFXfont *)&Roboto_Black_28, 0,epd.height, (char *)"Custom fonts too", OBD_BLACK);
47 | obdDumpBuffer(&epd, NULL); // do a full update
48 | printf("Display done\n");
49 | return 0;
50 | } /* main() */
51 |
52 |
--------------------------------------------------------------------------------
/linux/gif_1_bus_2_oleds/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O3 -D__LINUX__ -D_LINUX_
2 |
3 | all: gifplay
4 |
5 | gifplay: main.o
6 | $(CC) main.o -o gifplay
7 |
8 | main.o: main.c ../../src/obd.inl ../../src/OneBitDisplay.h
9 | $(CC) $(CFLAGS) main.c
10 |
11 | clean:
12 | rm -rf *.o gifplay
13 |
--------------------------------------------------------------------------------
/linux/gif_1_bus_2_oleds/main.c:
--------------------------------------------------------------------------------
1 | //
2 | // main.c
3 | // OneBitDisplay library test program
4 | //
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include "../../../AnimatedGIF/src/AnimatedGIF.h"
17 | #include "../../../AnimatedGIF/src/gif.inl"
18 | #include "../../src/OneBitDisplay.cpp"
19 | #include "running_256_64.h"
20 |
21 | #define OLED_TYPE OLED_132x64
22 | #define OLED_ADDR 0x3c
23 | #define FLIP180 0
24 | #define INVERT 0
25 | #define HW_I2C 1
26 | // On Linux this is the I2C bus number (SDA_PIN) for HW I2C
27 | #define SDA_PIN 1
28 | // On Linux this is the I2C device address
29 | #define SCL_PIN 0x3c
30 | #define RESET_PIN -1
31 | // This is not controlled on Linux through the API
32 | // On the Raspberry PI, see /boot/config.txt
33 | #define SPEED 0
34 | #define DISPLAY_WIDTH 256
35 | #define DISPLAY_HEIGHT 64
36 | static uint8_t ucOLED_0[1024], ucOLED_1[1024];
37 | static OBDISP obd[2];
38 | //
39 | // This doesn't have to be super efficient
40 | //
41 | void DrawPixel(int x, int y, uint8_t ucColor)
42 | {
43 | uint8_t *d, ucMask;
44 |
45 | ucMask = 1 << (y & 7);
46 | if (x >= 128) // right display
47 | d = &ucOLED_1[(x-128)+((y>>3) << 7)];
48 | else
49 | d = &ucOLED_0[x + ((y>>3) << 7)];
50 | if (ucColor)
51 | *d |= ucMask;
52 | else
53 | *d &= ~ucMask;
54 | }
55 |
56 | // Draw a line of image into our 1-bpp virtual display buffers
57 | void GIFDraw(GIFDRAW *pDraw)
58 | {
59 | uint8_t *s;
60 | int x, y, iWidth;
61 | static uint8_t ucPalette[256]; // thresholded palette
62 |
63 | if (pDraw->y == 0) // first line, convert palette to 0/1
64 | {
65 | for (x = 0; x < 256; x++)
66 | {
67 | uint16_t usColor = pDraw->pPalette[x];
68 | int gray = (usColor & 0xf800) >> 8; // red
69 | gray += ((usColor & 0x7e0) >> 2); // plus green*2
70 | gray += ((usColor & 0x1f) << 3); // plus blue
71 | ucPalette[x] = (gray >> 9); // 0->511 = 0, 512->1023 = 1
72 | }
73 | }
74 | y = pDraw->iY + pDraw->y; // current line
75 | iWidth = pDraw->iWidth;
76 | if (iWidth > DISPLAY_WIDTH)
77 | iWidth = DISPLAY_WIDTH;
78 |
79 | s = pDraw->pPixels;
80 | if (pDraw->ucDisposalMethod == 2) // restore to background color
81 | {
82 | for (x=0; xucTransparent)
85 | s[x] = pDraw->ucBackground;
86 | }
87 | pDraw->ucHasTransparency = 0;
88 | }
89 | // Apply the new pixels to the main image
90 | if (pDraw->ucHasTransparency) // if transparency used
91 | {
92 | uint8_t c, ucTransparent = pDraw->ucTransparent;
93 | int x;
94 | for(x=0; x < iWidth; x++)
95 | {
96 | c = *s++;
97 | if (c != ucTransparent)
98 | DrawPixel(pDraw->iX + x, y, ucPalette[c]);
99 | }
100 | }
101 | else
102 | {
103 | s = pDraw->pPixels;
104 | // Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
105 | for (x=0; xiWidth; x++)
106 | DrawPixel(pDraw->iX + x, y, ucPalette[*s++]);
107 | }
108 | if (pDraw->y == pDraw->iHeight-1) { // last line, render it to the display(s)
109 | obdDumpBuffer(&obd[0], NULL);
110 | obdDumpBuffer(&obd[1], NULL);
111 | }
112 | } /* GIFDraw() */
113 |
114 | int main(int argc, const char * argv[])
115 | {
116 | GIFIMAGE gif;
117 | int rc;
118 | int iDelay;
119 |
120 | obdI2CInit(&obd[0], OLED_TYPE, -1, FLIP180, INVERT, HW_I2C, 1, 0x3C, RESET_PIN, SPEED);
121 | obdSetBackBuffer(&obd[0], ucOLED_0);
122 | obdFill(&obd[0], 0, 1);
123 | obdI2CInit(&obd[1], OLED_TYPE, -1, FLIP180, INVERT, HW_I2C, 1, 0x3D, RESET_PIN, SPEED);
124 | obdSetBackBuffer(&obd[1], ucOLED_1);
125 | obdFill(&obd[1], 0, 1);
126 | GIF_begin(&gif, GIF_PALETTE_RGB565_LE);
127 | while (1) {
128 | rc = GIF_openRAM(&gif, (uint8_t *)running_256_64, sizeof(running_256_64), GIFDraw);
129 | if (rc) {
130 | while (GIF_playFrame(&gif, &iDelay, NULL)) {
131 | // usleep(iDelay * 1000);
132 | }
133 | }
134 | } // while (1)
135 | return 0;
136 | } /* main() */
137 |
--------------------------------------------------------------------------------
/linux/obd.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #define OUTPUT GPIO_OUT
11 | #define INPUT GPIO_IN
12 | #define INPUT_PULLUP GPIO_IN_PULLUP
13 | #define HIGH 1
14 | #define LOW 0
15 | #include "../src/OneBitDisplay.h"
16 | #include "../src/obd.inl"
17 |
18 |
--------------------------------------------------------------------------------
/linux/sharp_fast_gif/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O3 -D__LINUX__ -D_LINUX_ -DSPI_BUS_NUMBER=0
2 | LIBS = -lpthread -larmbianio
3 | all: gifplay
4 |
5 | gifplay: main.o
6 | $(CC) main.o $(LIBS) -o gifplay
7 |
8 | main.o: main.c ../../src/obd.inl ../../src/OneBitDisplay.h
9 | $(CC) $(CFLAGS) main.c
10 |
11 | clean:
12 | rm -rf *.o gifplay
13 |
--------------------------------------------------------------------------------
/linux/sharp_fast_gif/main.c:
--------------------------------------------------------------------------------
1 | //
2 | // main.c
3 | // OneBitDisplay library test program
4 | //
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "../../../AnimatedGIF/src/AnimatedGIF.h"
19 | #include "../../../AnimatedGIF/src/gif.inl"
20 | #include "../../src/OneBitDisplay.cpp"
21 | #include "pattern_400x240.h"
22 |
23 | #define DISPLAY_TYPE SHARP_400x240
24 | #define FLIP180 0
25 | #define INVERT 0
26 | #define DC_PIN -1
27 | #define CS_PIN 16
28 | #define DISP_PIN 18
29 | #define EXTCOM_PIN 22
30 | #define RESET_PIN -1
31 | #define SPEED 8000000
32 | #define BITBANG 0
33 | #define LED_PIN -1
34 |
35 | // This is not controlled on Linux through the API
36 | // On the Raspberry PI, see /boot/config.txt
37 | #define DISPLAY_WIDTH 400
38 | #define DISPLAY_HEIGHT 240
39 | #define DISPLAY_PITCH ((DISPLAY_WIDTH>>3)+2)
40 | static uint8_t ucBuffer[(DISPLAY_PITCH * DISPLAY_HEIGHT)+2];
41 | static OBDISP obd;
42 | volatile int iStop = 0;
43 |
44 | void my_handler(int signal)
45 | {
46 | iStop = 1;
47 | } /* my_handler() */
48 |
49 | //
50 | // This doesn't have to be super efficient
51 | //
52 | void DrawPixel(int x, int y, uint8_t ucColor)
53 | {
54 | uint8_t *d, ucMask;
55 |
56 | ucMask = 0x80 >> (x & 7);
57 | d = &ucBuffer[2 + (x>>3) + (y*DISPLAY_PITCH)];
58 | if (ucColor)
59 | *d &= ~ucMask;
60 | else
61 | *d |= ucMask;
62 | }
63 |
64 | // Draw a line of image into our 1-bpp virtual display buffers
65 | void GIFDraw(GIFDRAW *pDraw)
66 | {
67 | uint8_t *s, *d = &ucBuffer[2];
68 | int x, y, iWidth;
69 | int iX = pDraw->iX;
70 | static uint8_t ucPalette[256]; // thresholded palette
71 |
72 | if (pDraw->y == 0) // first line, convert palette to 0/1
73 | {
74 | for (x = 0; x < 256; x++)
75 | {
76 | uint16_t usColor = pDraw->pPalette[x];
77 | int gray = (usColor & 0xf800) >> 8; // red
78 | gray += ((usColor & 0x7e0) >> 2); // plus green*2
79 | gray += ((usColor & 0x1f) << 3); // plus blue
80 | ucPalette[x] = (gray >> 9); // 0->511 = 0, 512->1023 = 1
81 | }
82 | }
83 | y = pDraw->iY + pDraw->y; // current line
84 | d += (y * DISPLAY_PITCH);
85 | iWidth = pDraw->iWidth;
86 | if (iWidth > DISPLAY_WIDTH)
87 | iWidth = DISPLAY_WIDTH;
88 |
89 | s = pDraw->pPixels;
90 | if (pDraw->ucDisposalMethod == 2) // restore to background color
91 | {
92 | for (x=0; xucTransparent)
95 | s[x] = pDraw->ucBackground;
96 | }
97 | pDraw->ucHasTransparency = 0;
98 | }
99 | // Apply the new pixels to the main image
100 | if (pDraw->ucHasTransparency) // if transparency used
101 | {
102 | uint8_t c, ucTransparent = pDraw->ucTransparent;
103 | int x;
104 | for(x=0; x < iWidth; x++)
105 | {
106 | c = *s++;
107 | if (c != ucTransparent) {
108 | // DrawPixel(iX + x, y, ucPalette[c]);
109 | if (ucPalette[c]) d[((iX+x)>>3)] |= (0x80 >> ((iX+x)&7));
110 | else d[((iX+x)>>3)] &= ~(0x80 >> ((iX+x)&7));
111 | }
112 | }
113 | }
114 | else
115 | {
116 | s = pDraw->pPixels;
117 | // Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
118 | for (x=0; xiWidth; x++) {
119 | if (ucPalette[*s++]) d[((iX+x)>>3)] |= (0x80 >> ((iX+x)&7));
120 | else d[((iX+x)>>3)] &= ~(0x80 >> ((iX+x)&7));
121 | //DrawPixel(pDraw->iX + x, y, ucPalette[*s++]);
122 | }
123 | }
124 | if (pDraw->y == pDraw->iHeight-1) { // last line, render it to the display
125 | // obdDumpBuffer(&obd, NULL);
126 | AIOWriteGPIO(CS_PIN, HIGH);
127 | ucBuffer[0] ^= 0x40; // toggle VCOM bit
128 | AIOWriteSPI(obd.bbi2c.file_i2c, ucBuffer, sizeof(ucBuffer));
129 | // RawWriteData(&obd, ucBuffer, sizeof(ucBuffer));
130 | AIOWriteGPIO(CS_PIN, LOW);
131 | }
132 | } /* GIFDraw() */
133 |
134 | // Less efficient than a lookup table, but it's only used at init time
135 | // This saves a couple hundred bytes of FLASH
136 | uint8_t MirrorBits(uint8_t v)
137 | {
138 | uint8_t r = v & 1;
139 | uint8_t s = 7;
140 | for (v >>= 1; v; v >>= 1) {
141 | r <<= 1;
142 | r |= (v & 1);
143 | s--;
144 | }
145 | r <<= s; // adjust for 0's
146 | return r;
147 | } /* MirrorBits() */
148 |
149 | void PrepBuffer(void)
150 | {
151 | uint8_t *d;
152 | int i;
153 |
154 | d = ucBuffer;
155 | *d++ = 0x80; // start byte
156 | for (i=0; i
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "../../../AnimatedGIF/src/AnimatedGIF.h"
19 | #include "../../../AnimatedGIF/src/gif.inl"
20 | #include "../../src/OneBitDisplay.cpp"
21 | #include "pattern_400x240.h"
22 |
23 | #define DISPLAY_TYPE SHARP_400x240
24 | #define FLIP180 0
25 | #define INVERT 0
26 | #define DC_PIN -1
27 | #define CS_PIN 16
28 | #define DISP_PIN 18
29 | #define EXTCOM_PIN 22
30 | #define RESET_PIN -1
31 | #define SPEED 8000000
32 | #define BITBANG 0
33 | #define LED_PIN -1
34 |
35 | // This is not controlled on Linux through the API
36 | // On the Raspberry PI, see /boot/config.txt
37 | #define DISPLAY_WIDTH 400
38 | #define DISPLAY_HEIGHT 240
39 | static uint8_t ucBuffer[12000];
40 | static OBDISP obd;
41 | volatile int iStop = 0;
42 |
43 | void my_handler(int signal)
44 | {
45 | iStop = 1;
46 | } /* my_handler() */
47 |
48 | //
49 | // This doesn't have to be super efficient
50 | //
51 | void DrawPixel(int x, int y, uint8_t ucColor)
52 | {
53 | uint8_t *d, ucMask;
54 |
55 | ucMask = 1 << (y & 7);
56 | d = &ucBuffer[x + ((y>>3) * DISPLAY_WIDTH)];
57 | if (ucColor)
58 | *d &= ~ucMask;
59 | else
60 | *d |= ucMask;
61 | }
62 |
63 | // Draw a line of image into our 1-bpp virtual display buffers
64 | void GIFDraw(GIFDRAW *pDraw)
65 | {
66 | uint8_t *s;
67 | int x, y, iWidth;
68 | static uint8_t ucPalette[256]; // thresholded palette
69 |
70 | if (pDraw->y == 0) // first line, convert palette to 0/1
71 | {
72 | for (x = 0; x < 256; x++)
73 | {
74 | uint16_t usColor = pDraw->pPalette[x];
75 | int gray = (usColor & 0xf800) >> 8; // red
76 | gray += ((usColor & 0x7e0) >> 2); // plus green*2
77 | gray += ((usColor & 0x1f) << 3); // plus blue
78 | ucPalette[x] = (gray >> 9); // 0->511 = 0, 512->1023 = 1
79 | }
80 | }
81 | y = pDraw->iY + pDraw->y; // current line
82 | iWidth = pDraw->iWidth;
83 | if (iWidth > DISPLAY_WIDTH)
84 | iWidth = DISPLAY_WIDTH;
85 |
86 | s = pDraw->pPixels;
87 | if (pDraw->ucDisposalMethod == 2) // restore to background color
88 | {
89 | for (x=0; xucTransparent)
92 | s[x] = pDraw->ucBackground;
93 | }
94 | pDraw->ucHasTransparency = 0;
95 | }
96 | // Apply the new pixels to the main image
97 | if (pDraw->ucHasTransparency) // if transparency used
98 | {
99 | uint8_t c, ucTransparent = pDraw->ucTransparent;
100 | int x;
101 | for(x=0; x < iWidth; x++)
102 | {
103 | c = *s++;
104 | if (c != ucTransparent)
105 | DrawPixel(pDraw->iX + x, y, ucPalette[c]);
106 | }
107 | }
108 | else
109 | {
110 | s = pDraw->pPixels;
111 | // Translate the 8-bit pixels through the RGB565 palette (already byte reversed)
112 | for (x=0; xiWidth; x++)
113 | DrawPixel(pDraw->iX + x, y, ucPalette[*s++]);
114 | }
115 | if (pDraw->y == pDraw->iHeight-1) { // last line, render it to the display
116 | obdDumpBuffer(&obd, NULL);
117 | }
118 | } /* GIFDraw() */
119 |
120 | int main(int argc, const char * argv[])
121 | {
122 | GIFIMAGE gif;
123 | int rc;
124 | int iDelay;
125 | struct sigaction sigIntHandler;
126 |
127 | // Set CTRL-C signal handler
128 | sigIntHandler.sa_handler = my_handler;
129 | sigemptyset(&sigIntHandler.sa_mask);
130 | sigIntHandler.sa_flags = 0;
131 | sigaction(SIGINT, &sigIntHandler, NULL);
132 |
133 | printf("Sharp Memory LCD GIF demo\n");
134 | printf("Press Ctrl-C to quit\n");
135 |
136 | rc = AIOInitBoard("Raspberry Pi");
137 | if (rc == 0) // problem
138 | {
139 | printf("Error in AIOInit(); check if this board is supported\n");
140 | return 0;
141 | }
142 | AIOAddGPIO(DISP_PIN, OUTPUT); // enable display
143 | AIOWriteGPIO(DISP_PIN, HIGH);
144 | AIOAddGPIO(EXTCOM_PIN, OUTPUT);
145 |
146 | obdSPIInit(&obd, DISPLAY_TYPE, DC_PIN, CS_PIN, RESET_PIN, -1, -1, LED_PIN, FLIP180, INVERT, BITBANG, SPEED);
147 | obdSetBackBuffer(&obd, ucBuffer);
148 | obdFill(&obd, 0, 0);
149 | obdDumpBuffer(&obd, NULL);
150 | GIF_begin(&gif, GIF_PALETTE_RGB565_LE);
151 | while (!iStop) {
152 | rc = GIF_openRAM(&gif, (uint8_t *)pattern_400x240, sizeof(pattern_400x240), GIFDraw);
153 | if (rc) {
154 | while (GIF_playFrame(&gif, &iDelay, NULL)) {
155 | //usleep(iDelay * 1000);
156 | }
157 | } else {
158 | printf("GIF decode error = %d\n", gif.iError);
159 | iStop = 1;
160 | }
161 | } // while (1)
162 | AIOWriteGPIO(DISP_PIN, LOW); // turn off LCD
163 | AIOShutdown();
164 |
165 | return 0;
166 | } /* main() */
167 |
--------------------------------------------------------------------------------
/linux/spi_demo/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O2 -DSPI_BUS_NUMBER=0 -D_LINUX_
2 | LIBS = -lpthread -larmbianio
3 | all: spi_demo
4 |
5 | spi_demo: main.o
6 | $(CC) main.o $(LIBS) -o spi_demo
7 |
8 | main.o: main.c ../../src/obd.inl ../../src/OneBitDisplay.cpp ../../src/OneBitDisplay.h
9 | $(CC) $(CFLAGS) main.c
10 |
11 | clean:
12 | rm -rf *.o spi_demo
13 |
--------------------------------------------------------------------------------
/linux/spi_demo/main.c:
--------------------------------------------------------------------------------
1 | //
2 | // main.c
3 | // OneBitDisplay library test program
4 | // Demonstrates many of the features for OLED displays
5 | //
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | #include "../../src/OneBitDisplay.cpp"
19 |
20 | volatile int iStop = 0;
21 |
22 | //#define OLED_TYPE OLED_132x64
23 | //#define OLED_TYPE LCD_UC1609
24 | #define OLED_TYPE LCD_UC1701
25 | #define FLIP180 0
26 | #define INVERT 0
27 | #define DC_PIN 22
28 | #define CS_PIN -1
29 | //#define CS_PIN 24
30 | #define RESET_PIN 13
31 | #define SPEED 4000000
32 | #define BITBANG 0
33 | // LED on GPIO 12
34 | #define LED_PIN 32
35 | OBDISP obd;
36 | static uint8_t ucBuffer[1024];
37 |
38 | void my_handler(int signal)
39 | {
40 | iStop = 1;
41 | } /* my_handler() */
42 |
43 | int main(int argc, const char *argv[])
44 | {
45 | int i;
46 | struct sigaction sigIntHandler;
47 | //size_t ret;
48 |
49 | // Set CTRL-C signal handler
50 | sigIntHandler.sa_handler = my_handler;
51 | sigemptyset(&sigIntHandler.sa_mask);
52 | sigIntHandler.sa_flags = 0;
53 | sigaction(SIGINT, &sigIntHandler, NULL);
54 |
55 | i = AIOInitBoard("Raspberry Pi");
56 | if (i == 0) // problem
57 | {
58 | printf("Error in AIOInit(); check if this board is supported\n");
59 | return 0;
60 | }
61 |
62 | //void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int bBitBang, int32_t iSpeed)
63 | obdSPIInit(&obd, OLED_TYPE, DC_PIN, CS_PIN, RESET_PIN, -1, -1, LED_PIN, FLIP180, INVERT, BITBANG, SPEED);
64 | obdSetBackBuffer(&obd, ucBuffer);
65 | // Create some simple content
66 | obdFill(&obd, 0, 1);
67 | obdSetContrast(&obd, 63); // white on black requires max contrast to be visible
68 | obdBacklight(&obd, 1);
69 | obdWriteString(&obd,0,0,0,"OneBitDisplay", FONT_8x8, 0, 1);
70 | while (!iStop) {
71 | obdFill(&obd, 0, 1);
72 | for (int i=0; i<128; i++) {
73 | obdDrawLine(&obd, i, 0, 127-i, 63, 1, 1);
74 | }
75 | for (int i=0; i<64; i++) {
76 | obdDrawLine(&obd, 127, i, 0, 63-i, 1, 1);
77 | }
78 | }
79 | // obdEllipse(&obd, 320, 240+64, 150,100, 0, 1);
80 | // obdRectangle(&obd, 300, 240+32, 340, 240+96, 1, 1);
81 | obdFill(&obd, 0, 1);
82 | obdBacklight(&obd, 0);
83 | AIOShutdown();
84 | return 0;
85 | } /* main() */
86 |
--------------------------------------------------------------------------------
/linux/virtual_disp/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS=-c -Wall -O3 -D_LINUX_
2 |
3 | all: obd_test
4 |
5 | obd_test: main.o
6 | $(CC) main.o -o obd_test
7 |
8 | main.o: main.c ../../src/obd.inl ../../src/OneBitDisplay.h
9 | $(CC) $(CFLAGS) main.c
10 |
11 | clean:
12 | rm -rf *.o obd_test
13 |
--------------------------------------------------------------------------------
/linux/virtual_disp/main.c:
--------------------------------------------------------------------------------
1 | //
2 | // main.c
3 | // OneBitDisplay library test program
4 | //
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include "../../src/OneBitDisplay.h"
17 | #include "../../src/obd.inl"
18 | #include "../../examples/prop_font_demo/FreeSerif12pt7b.h"
19 | #include "notes.h"
20 |
21 | void WriteBMP(const char *name, uint8_t *pData, int width, int height, int bpp)
22 | {
23 | int bsize, lsize, i, iHeaderSize, iBodySize;
24 | uint8_t pBuf[128]; // holds BMP header
25 | FILE *outfile;
26 |
27 | bsize = width >> 3;
28 | lsize = (bsize + 3) & 0xfffc; // DWORD aligned
29 | iHeaderSize = 54;
30 | iHeaderSize += (1<<(bpp+2));
31 | iBodySize = lsize * height;
32 | i = iBodySize + iHeaderSize; // datasize
33 | memset(pBuf, 0, 54);
34 | pBuf[0] = 'B';
35 | pBuf[1] = 'M';
36 | pBuf[2] = i & 0xff; // 4 bytes of file size
37 | pBuf[3] = (i >> 8) & 0xff;
38 | pBuf[4] = (i >> 16) & 0xff;
39 | pBuf[5] = (i >> 24) & 0xff;
40 | /* Offset to data bits */
41 | pBuf[10] = iHeaderSize & 0xff;
42 | pBuf[11] = (unsigned char)(iHeaderSize >> 8);
43 | pBuf[14] = 0x28;
44 | pBuf[18] = width & 0xff; // xsize low
45 | pBuf[19] = (unsigned char)(width >> 8); // xsize high
46 | i = -height; // top down bitmap
47 | pBuf[22] = i & 0xff; // ysize low
48 | pBuf[23] = (unsigned char)(i >> 8); // ysize high
49 | pBuf[24] = 0xff;
50 | pBuf[25] = 0xff;
51 | pBuf[26] = 1; // number of planes
52 | pBuf[28] = (uint8_t)bpp;
53 | pBuf[30] = 0; // uncompressed
54 | i = iBodySize;
55 | pBuf[34] = i & 0xff; // data size
56 | pBuf[35] = (i >> 8) & 0xff;
57 | pBuf[36] = (i >> 16) & 0xff;
58 | pBuf[37] = (i >> 24) & 0xff;
59 | pBuf[54] = pBuf[55] = pBuf[56] = pBuf[57] = pBuf[61] = 0; // palette
60 | pBuf[58] = pBuf[59] = pBuf[60] = 0xff;
61 | outfile = fopen((char *)name, "w+b");
62 | if (outfile)
63 | {
64 | uint8_t *s = pData;
65 | fwrite(pBuf, 1, iHeaderSize, outfile);
66 | for (i=0; i> 3;
89 | pBitonal = malloc(out_pitch * height);
90 | pOut = malloc(out_pitch * height);
91 |
92 | obdCreateVirtualDisplay(&obd, width, height, pBitonal);
93 | // Create some simple content
94 | obdFill(&obd, 0xff, 1); // colors are inverted
95 | obdWriteString(&obd,0,0,0,"OneBitDisplay test program", FONT_12x16, 1, 1);
96 | obdWriteString(&obd,0,0,2,"Written to vertify fonts and GFX", FONT_16x16, 1, 1);
97 | obdWriteString(&obd,0,0,4,"This is the 8x8 fixed font", FONT_8x8, 1, 1);
98 | obdWriteString(&obd,0,0,5,"This is the smallest (6x8) font", FONT_6x8, 1, 1);
99 | obdWriteString(&obd,0,0,6,"This is the largest built-in font", FONT_16x32, 1, 1);
100 | obdWriteStringCustom(&obd, (GFXfont *)&FreeSerif12pt7b, 0, 100, (char *)"Custom (Adafruit_GFX format) fonts are supported too",0);
101 | for (int i=0; i<640; i+=8) {
102 | obdDrawLine(&obd, i, 128, 640-i, 479, 0, 0);
103 | }
104 | obdEllipse(&obd, 320, 240+64, 150,100, 0, 1);
105 | obdRectangle(&obd, 300, 240+32, 340, 240+96, 1, 1);
106 | obdLoadBMP(&obd, (uint8_t *)notes, 15, 240, 0);
107 | obdCopy(&obd, OBD_ROTATE_90 | OBD_MSB_FIRST | OBD_HORZ_BYTES | OBD_FLIP_VERT | OBD_FLIP_HORZ, pOut);
108 | WriteBMP(argv[1], pOut, height, width, 1);
109 | free(pOut);
110 | free(pBitonal);
111 | return 0;
112 | } /* main() */
113 |
--------------------------------------------------------------------------------
/linux/virtual_disp/notes.h:
--------------------------------------------------------------------------------
1 | //
2 | // notes
3 | // Data size = 2386 bytes
4 | //
5 | // OS/2 BMP, Compression=None, Size: 100 x 140, 1-Bpp
6 | //
7 | // for non-Arduino builds...
8 | #ifndef PROGMEM
9 | #define PROGMEM
10 | #endif
11 | const uint8_t notes[] PROGMEM = {
12 | 0x42,0x4d,0x52,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x92,0x00,0x00,0x00,0x7c,0x00,
13 | 0x00,0x00,0x64,0x00,0x00,0x00,0x8c,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x03,0x00,
14 | 0x00,0x00,0xc0,0x08,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x02,0x00,
15 | 0x00,0x00,0x02,0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0xe0,0x07,0x00,0x00,0x1f,0x00,
16 | 0x00,0x00,0x00,0x00,0x00,0x00,0x42,0x47,0x52,0x73,0x00,0x00,0x00,0x00,0x00,0x00,
17 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
18 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
19 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,
20 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
21 | 0xff,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
22 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
23 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
24 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
25 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
26 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
27 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
28 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
29 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
30 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
31 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
32 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
33 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
34 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x01,0xff,0xff,0xff,0xf0,0x00,
35 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x3f,0xff,0xff,0xf0,0x00,
36 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x0f,0xff,0xff,0xf0,0x00,
37 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x80,0x00,0x03,0xff,0xff,0xf0,0x00,
38 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x01,0xff,0xff,0xf0,0x00,
39 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x00,0x00,0x00,0xff,0xff,0xf0,0x00,
40 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xfc,0x00,0x00,0x00,0x7f,0xff,0xf0,0x00,
41 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x3f,0xff,0xf0,0x00,
42 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf8,0x00,0x00,0x00,0x3f,0xff,0xf0,0x00,
43 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x1f,0xff,0xf0,0x00,
44 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x1f,0xff,0xf0,0x00,
45 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,0x00,0x00,0x0f,0xff,0xf0,0x00,
46 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x0f,0xff,0xf0,0x00,
47 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x0f,0xff,0xf0,0x00,
48 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x07,0xff,0xf0,0x00,
49 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0x00,0x00,0x00,0x07,0xff,0xf0,0x00,
50 | 0x00,0x00,0xff,0xff,0xfc,0x00,0xff,0xff,0xe0,0x00,0x00,0x00,0x07,0xff,0xf0,0x00,
51 | 0x00,0x00,0xff,0xff,0xe0,0x00,0x3f,0xff,0xf0,0x00,0x00,0x00,0x03,0xff,0xf0,0x00,
52 | 0x00,0x00,0xff,0xff,0x80,0x00,0x0f,0xff,0xf0,0x00,0x00,0x00,0x03,0xff,0xf0,0x00,
53 | 0x00,0x00,0xff,0xff,0x00,0x00,0x03,0xff,0xf0,0x00,0x00,0x00,0x03,0xff,0xf0,0x00,
54 | 0x00,0x00,0xff,0xfe,0x00,0x00,0x01,0xff,0xf8,0x00,0x00,0x00,0x03,0xff,0xf0,0x00,
55 | 0x00,0x00,0xff,0xfc,0x00,0x00,0x00,0xff,0xf8,0x00,0x00,0x00,0x01,0xff,0xf0,0x00,
56 | 0x00,0x00,0xff,0xf8,0x00,0x00,0x00,0xff,0xfc,0x00,0x00,0x00,0x01,0xff,0xf0,0x00,
57 | 0x00,0x00,0xff,0xf0,0x00,0x00,0x00,0x7f,0xfc,0x00,0x00,0x00,0x41,0xff,0xf0,0x00,
58 | 0x00,0x00,0xff,0xf0,0x00,0x00,0x00,0x3f,0xfe,0x00,0x00,0x00,0xc1,0xff,0xf0,0x00,
59 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x3f,0xff,0x00,0x00,0x01,0xc1,0xff,0xf0,0x00,
60 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x3f,0xff,0xc0,0x00,0x07,0xc1,0xff,0xf0,0x00,
61 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x1f,0xff,0xf0,0x00,0x1f,0xc1,0xff,0xf0,0x00,
62 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x1f,0xff,0xfc,0x00,0x7f,0xc1,0xff,0xf0,0x00,
63 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
64 | 0x00,0x00,0xff,0xc0,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
65 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
66 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
67 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
68 | 0x00,0x00,0xff,0xe0,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
69 | 0x00,0x00,0xff,0xf0,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
70 | 0x00,0x00,0xff,0xf0,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
71 | 0x00,0x00,0xff,0xf8,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
72 | 0x00,0x00,0xff,0xf8,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
73 | 0x00,0x00,0xff,0xfc,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
74 | 0x00,0x00,0xff,0xfe,0x00,0x00,0x02,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
75 | 0x00,0x00,0xff,0xff,0x00,0x00,0x06,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
76 | 0x00,0x00,0xff,0xff,0xc0,0x00,0x0e,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
77 | 0x00,0x00,0xff,0xff,0xf0,0x00,0x3e,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
78 | 0x00,0x00,0xff,0xff,0xfe,0x01,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
79 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
80 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
81 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
82 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
83 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
84 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
85 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
86 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
87 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
88 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
89 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe0,0xff,0xf0,0x00,
90 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe1,0xff,0xf0,0x00,
91 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe1,0xff,0xf0,0x00,
92 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xe1,0xff,0xf0,0x00,
93 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
94 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
95 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
96 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
97 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
98 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
99 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
100 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
101 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc1,0xff,0xf0,0x00,
102 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0xc3,0xff,0xf0,0x00,
103 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0x83,0xff,0xf0,0x00,
104 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0x83,0xff,0xf0,0x00,
105 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x0f,0xff,0xff,0xff,0xff,0x83,0xff,0xf0,0x00,
106 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x1f,0xff,0xff,0xff,0xff,0x83,0xff,0xf0,0x00,
107 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfe,0x1f,0xff,0xff,0xff,0xff,0x83,0xff,0xf0,0x00,
108 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0xff,0xfc,0x03,0xff,0xf0,0x00,
109 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0xff,0xe0,0x07,0xff,0xf0,0x00,
110 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0xff,0x00,0x07,0xff,0xf0,0x00,
111 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0xf8,0x00,0x07,0xff,0xf0,0x00,
112 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0xe0,0x00,0x07,0xff,0xf0,0x00,
113 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xff,0x00,0x03,0x07,0xff,0xf0,0x00,
114 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xfc,0x00,0x1f,0x07,0xff,0xf0,0x00,
115 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x1f,0xff,0xf0,0x00,0xfe,0x0f,0xff,0xf0,0x00,
116 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x3f,0xff,0xc0,0x03,0xfe,0x0f,0xff,0xf0,0x00,
117 | 0x00,0x00,0xff,0xff,0xff,0xff,0xfc,0x3f,0xff,0x00,0x1f,0xfe,0x0f,0xff,0xf0,0x00,
118 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x3f,0xfe,0x00,0x7f,0xfe,0x0f,0xff,0xf0,0x00,
119 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x3f,0xf8,0x01,0xff,0xfc,0x1f,0xff,0xf0,0x00,
120 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x3f,0xe0,0x07,0xff,0xc0,0x1f,0xff,0xf0,0x00,
121 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x3f,0xc0,0x1f,0xfe,0x00,0x1f,0xff,0xf0,0x00,
122 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x3f,0x00,0x7f,0xf0,0x00,0x3f,0xff,0xf0,0x00,
123 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x3e,0x00,0xff,0xc0,0x00,0x7f,0xff,0xf0,0x00,
124 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x78,0x03,0xfe,0x00,0x07,0xff,0xff,0xf0,0x00,
125 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf8,0x70,0x0f,0xf8,0x00,0x3f,0xff,0xff,0xf0,0x00,
126 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0x40,0x1f,0xe0,0x01,0xff,0xff,0xff,0xf0,0x00,
127 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0x00,0x7f,0x80,0x0f,0xff,0xff,0xff,0xf0,0x00,
128 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0x00,0xfe,0x00,0x3f,0xff,0xff,0xff,0xf0,0x00,
129 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0x03,0xf8,0x00,0xff,0xff,0xff,0xff,0xf0,0x00,
130 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0x07,0xf0,0x03,0xff,0xff,0xff,0xff,0xf0,0x00,
131 | 0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0x1f,0xc0,0x0f,0xff,0xff,0xff,0xff,0xf0,0x00,
132 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe0,0x3f,0x00,0x3f,0xff,0xff,0xff,0xff,0xf0,0x00,
133 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe0,0xfe,0x00,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
134 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe0,0xf8,0x03,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
135 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe0,0xe0,0x0f,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
136 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe0,0xc0,0x1f,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
137 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe1,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
138 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc0,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
139 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc0,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
140 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc0,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
141 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc0,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
142 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc0,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
143 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
144 | 0x00,0x00,0xff,0xff,0xff,0xff,0xc1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
145 | 0x00,0x00,0xff,0xff,0xff,0xff,0xe7,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
146 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
147 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
148 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
149 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
150 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
151 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
152 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
153 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
154 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
155 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
156 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
157 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
158 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
159 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
160 | 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0x00,
161 | 0x00,0x00};
162 |
--------------------------------------------------------------------------------
/notes.txt:
--------------------------------------------------------------------------------
1 | Technical Notes:
2 | ----------------
3 |
4 | I2C
5 | ---
6 | Since adding the obdCachededWrite feature to reduce the number of I2C transactions
7 | when drawing fixed fonts, I discovered the limitations of the Wire library. On AVR
8 | targets the wire library allows a maximum write length of 32 bytes in a single call.
9 | Any data beyond the 32 bytes is not sent. The ESP32 has a similar behavior, but the
10 | limit is 128 bytes. OneBitDisplay tests for this condition in the write wrapper function
11 | and breaks up a data write into 32-byte pieces if it's being sent to hardware I2C.
12 | The bit-bang I2C doesn't have this limitation, so the write length is unlimited.
13 |
14 | BLE
15 | ---
16 | Getting BLE to work on both ESP32 and the Arduino hardware like the Nano 33 BLE was
17 | challenging not only because of the different API, but a fundamental difference in
18 | behavior. Sending fast data is hindered when the write() requests a response. On ESP32
19 | the writeValue() method allows you to choose if you want a response or not, but on
20 | the ArduinoBLE library (for the Nano 33 BLE), it will choose to wait for a response
21 | when the characteristic offers both properties. I added a new overloaded function to
22 | the ArduinoBLE library to allow you to choose. I created a pull request on Github and
23 | hope that Arduino will eventually merge the code:
24 |
25 | https://github.com/arduino-libraries/ArduinoBLE/pull/72
26 |
27 | UART
28 | ----
29 | Sending the SSD1306 commands over a UART presented new challenges. With I2C and
30 | BLE there are well defined "packets" because a transmission begins and ends.
31 | This is necessary for this type of data stream because a single byte tells the
32 | display controller to interpret the following bytes as commands or graphics.
33 | If there is no boundary between one packet and the next, the controller will
34 | misinterpret the start byte as a command or graphics from the previous packet.
35 | This is the exact problem with transmission over a UART because the way the
36 | data is read on the receiving end doesn't necessarily correspond with the way
37 | it's transmitted. To solve this problem, I added additional code on the
38 | sending side to add a length byte in front of each packet and on the receiving
39 | end I added code to re-sync the data if the length+D/C bytes don't line up
40 | properly.
41 |
--------------------------------------------------------------------------------
/sharp_lcd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitbank2/OneBitDisplay/5c5e1b9c2ebd08a63e66c39460514a9d811bb921/sharp_lcd.jpg
--------------------------------------------------------------------------------
/src/obd_io.inl:
--------------------------------------------------------------------------------
1 | //
2 | // OneBitDisplay (OLED/LCD/E-Paper library)
3 | // Copyright (c) 2020 BitBank Software, Inc.
4 | // Written by Larry Bank (bitbank@pobox.com)
5 | // Project started 3/23/2020
6 | //
7 | // Licensed under the Apache License, Version 2.0 (the "License");
8 | // you may not use this file except in compliance with the License.
9 | // You may obtain a copy of the License at
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 | //
17 | // I/O functions for the OneBitDisplay library
18 | //
19 | // This define (WIMPY_MCU) precludes the use of hardware interfaces
20 | // such as I2C & SPI
21 | //
22 | #if defined (__AVR_ATtiny85__) || defined (ARDUINO_ARCH_MCS51)
23 | #define WIMPY_MCU
24 | #endif
25 |
26 | #define MAX_CACHE 192
27 | static uint8_t u8Cache[MAX_CACHE]; // for faster character drawing
28 | static volatile uint8_t u8End = 0;
29 | static uint8_t u8Temp[40]; // for stretched character drawing
30 |
31 | #ifdef _LINUX_
32 | #define PROGMEM
33 | #define false 0
34 | #define true 1
35 | #define LOW 0
36 | #define HIGH 1
37 | #ifndef I2C_SLAVE
38 | #define I2C_SLAVE 0
39 | #define INPUT GPIO_IN
40 | #define OUTPUT GPIO_OUT
41 | #define INPUT_PULLUP GPIO_IN_PULLUP
42 | #define HIGH 1
43 | #define LOW 0
44 | #endif
45 | #if defined(_LINUX_) || defined(ARDUINO_ARCH_MCS51)
46 | #define memcpy_P memcpy
47 | #endif
48 |
49 | void obdSetDCMode(OBDISP *pOBD, int iMode);
50 | static uint8_t pgm_read_byte(const uint8_t *ptr);
51 | static void digitalWrite(int iPin, int iState) {
52 | #ifndef MEMORY_ONLY
53 | AIOWriteGPIO(iPin, iState);
54 | #endif
55 | }
56 | static void pinMode(int iPin, int iMode)
57 | {
58 | #ifndef MEMORY_ONLY
59 | AIOAddGPIO(iPin, iMode);
60 | #endif
61 | } /* pinMode() */
62 | static void delayMicroseconds(int iTime)
63 | {
64 | usleep(iTime);
65 | } /* delayMicroseconds() */
66 | static int digitalRead(int iPin)
67 | {
68 | return AIOReadGPIO(iPin);
69 | } /* digitalRead() */
70 | #endif // _LINUX_
71 |
72 | #if !defined( _LINUX_ ) && !defined( WIMPY_MCU )
73 | #include
74 |
75 | #ifdef ARDUINO_ARCH_RP2040
76 | MbedSPI *mySPI;
77 | #else
78 | SPIClass *mySPI = &SPI;
79 | #endif
80 | #endif // !_LINUX_
81 |
82 | // Initialize SPI
83 | void initSPI(OBDISP *pOBD, int iSpeed, int iMOSI, int iCLK, int iCS)
84 | {
85 | #ifdef WIMPY_MCU
86 | (void)iSpeed; (void)iMOSI; (void)iCLK; (void)iCS;
87 | #endif
88 |
89 | if (pOBD->bBitBang)
90 | return;
91 | #ifdef _LINUX_
92 | pOBD->bbi2c.file_i2c = AIOOpenSPI(SPI_BUS_NUMBER, iSpeed);
93 | #elif defined ( ARDUINO_ARCH_RP2040 )
94 | if (iMOSI == -1 || iMOSI == 0xff) {
95 | iMOSI = MOSI; iCLK = SCK; // use the default pins
96 | }
97 | mySPI = new MbedSPI(-1,iMOSI,iCLK);
98 | mySPI->begin();
99 | #elif defined( ARDUINO_ARCH_ESP32 ) || defined( RISCV )
100 | if (iMOSI != -1 && iMOSI != 0xff) {
101 | mySPI->begin(iCLK, -1, iMOSI, iCS);
102 | } else {
103 | mySPI->begin();
104 | }
105 | #elif !defined (WIMPY_MCU) // simple (default pin) SPI
106 | (void)iMOSI; (void)iCLK; (void)iCS;
107 | mySPI->begin();
108 | mySPI->beginTransaction(SPISettings(iSpeed, MSBFIRST, SPI_MODE0));
109 | #ifndef ARDUINO_ARCH_NRF52
110 | mySPI->endTransaction(); // N.B. - if you call beginTransaction() again without a matching endTransaction(), it will hang on ESP32
111 | // BUT!!! if you do call endTransaction on NRF52, it won't send any data at all
112 | #endif
113 | #endif // _LINUX_
114 | } /* initSPI() */
115 |
116 | //
117 | // Bit Bang the data on GPIO pins
118 | //
119 | void SPI_BitBang(OBDISP *pOBD, uint8_t *pData, int iLen, uint8_t iMOSIPin, uint8_t iSCKPin)
120 | {
121 | int i;
122 | uint8_t c;
123 |
124 | // We can access the GPIO ports much quicker on AVR by directly manipulating
125 | // the port registers
126 | #ifdef __AVR__
127 | volatile uint8_t *outSCK, *outMOSI; // port registers for fast I/O
128 | uint8_t port, bitSCK, bitMOSI; // bit mask for the chosen pins
129 |
130 | port = digitalPinToPort(iMOSIPin);
131 | outMOSI = portOutputRegister(port);
132 | bitMOSI = digitalPinToBitMask(iMOSIPin);
133 | port = digitalPinToPort(iSCKPin);
134 | outSCK = portOutputRegister(port);
135 | bitSCK = digitalPinToBitMask(iSCKPin);
136 |
137 | #endif
138 |
139 | while (iLen)
140 | {
141 | c = *pData++;
142 | iLen--;
143 | if (pOBD->iDCPin == 0xff && pOBD->chip_type != OBD_CHIP_SHARP) // 3-wire SPI, write D/C bit first
144 | {
145 | #ifdef __AVR__
146 | if (pOBD->mode == MODE_DATA)
147 | *outMOSI |= bitMOSI;
148 | else
149 | *outMOSI &= ~bitMOSI;
150 | *outSCK |= bitSCK; // toggle clock
151 | *outSCK &= ~bitSCK; // no delay needed on SPI devices since AVR is slow
152 | #else
153 | digitalWrite(iMOSIPin, (pOBD->mode == MODE_DATA));
154 | digitalWrite(iSCKPin, HIGH);
155 | delayMicroseconds(1);
156 | digitalWrite(iSCKPin, LOW);
157 | #endif
158 | }
159 | #ifdef FUTURE
160 | if (c == 0 || c == 0xff) // quicker for all bits equal
161 | {
162 | #ifdef __AVR__
163 | if (c & 1)
164 | *outMOSI |= bitMOSI;
165 | else
166 | *outMOSI &= ~bitMOSI;
167 | for (i=0; i<8; i++)
168 | {
169 | *outSCK |= bitSCK;
170 | *outSCK &= ~bitSCK;
171 | }
172 | #else
173 | digitalWrite(iMOSIPin, (c & 1));
174 | for (i=0; i<8; i++)
175 | {
176 | digitalWrite(iSCKPin, HIGH);
177 | delayMicroseconds(1);
178 | digitalWrite(iSCKPin, LOW);
179 | }
180 | #endif
181 | }
182 | else
183 | #endif // FUTURE
184 | {
185 | for (i=0; i<8; i++)
186 | {
187 | #ifdef __AVR__
188 | if (c & 0x80) // MSB first
189 | *outMOSI |= bitMOSI;
190 | else
191 | *outMOSI &= ~bitMOSI;
192 | *outSCK |= bitSCK;
193 | c <<= 1;
194 | *outSCK &= ~bitSCK;
195 | #else
196 | digitalWrite(iMOSIPin, (c & 0x80) != 0); // MSB first
197 | delayMicroseconds(1);
198 | digitalWrite(iSCKPin, HIGH);
199 | c <<= 1;
200 | delayMicroseconds(1);
201 | digitalWrite(iSCKPin, LOW);
202 | delayMicroseconds(1);
203 | #endif
204 | }
205 | }
206 | }
207 | } /* SPI_BitBang() */
208 |
209 | // wrapper/adapter functions to make the code work on Linux
210 | #if defined( _LINUX_ ) || defined(ARDUINO_ARCH_MCS51)
211 | static uint8_t pgm_read_byte(const uint8_t *ptr)
212 | {
213 | return *ptr;
214 | }
215 | static int16_t pgm_read_word(const uint8_t *ptr)
216 | {
217 | return ptr[0] + (ptr[1]<<8);
218 | }
219 | #if !defined( MEMORY_ONLY ) && !defined( WIMPY_MCU )
220 | int I2CReadRegister(BBI2C *pI2C, uint8_t addr, uint8_t reg, uint8_t *pBuf, int iLen)
221 | {
222 | int rc;
223 | rc = write(pI2C->file_i2c, ®, 1);
224 | rc = read(pI2C->file_i2c, pBuf, iLen);
225 | return (rc > 0);
226 | }
227 | int I2CRead(BBI2C *pI2C, uint8_t addr, uint8_t *pBuf, int iLen)
228 | {
229 | int rc;
230 | rc = read(pI2C->file_i2c, pBuf, iLen);
231 | return (rc > 0);
232 | }
233 | void I2CInit(BBI2C *pI2C, uint32_t iSpeed)
234 | {
235 | char filename[32];
236 |
237 | sprintf(filename, "/dev/i2c-%d", pI2C->iSDA); // I2C bus number passed in SDA pin
238 | if ((pI2C->file_i2c = open(filename, O_RDWR)) < 0)
239 | return;// 1;
240 | if (ioctl(pI2C->file_i2c, I2C_SLAVE, pI2C->iSCL) < 0) // set slave address
241 | {
242 | close(pI2C->file_i2c);
243 | pI2C->file_i2c = 0;
244 | return; // 1;
245 | }
246 | return; // 0;
247 | }
248 | #endif // MEMORY_ONLY
249 |
250 | // Write raw (unfiltered) bytes directly to I2C or SPI
251 | static void RawWrite(OBDISP *pOBD, unsigned char *pData, int iLen)
252 | {
253 | #if !defined( MEMORY_ONLY ) && !defined(WIMPY_MCU)
254 | if (pOBD->com_mode == COM_I2C) {// I2C device
255 | write(pOBD->bbi2c.file_i2c, pData, iLen);
256 | } else { // must be SPI
257 | obdSetDCMode(pOBD, (pData[0] == 0) ? MODE_COMMAND : MODE_DATA);
258 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP)
259 | digitalWrite(pOBD->iCSPin, LOW);
260 | AIOWriteSPI(pOBD->bbi2c.file_i2c, &pData[1], iLen-1);
261 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP)
262 | digitalWrite(pOBD->iCSPin, HIGH);
263 | //obdSetDCMode(pOBD, MODE_DATA);
264 | }
265 | #else
266 | (void)pOBD; (void)pData; (void)iLen;
267 | #endif // MEMORY_ONLY
268 | } /* RawWrite() */
269 | void RawWriteData(OBDISP *pOBD, unsigned char *pData, int iLen)
270 | {
271 | #if !defined( MEMORY_ONLY ) && !defined(WIMPY_MCU)
272 | if (pOBD->com_mode == COM_I2C) {// I2C device
273 | write(pOBD->bbi2c.file_i2c, pData, iLen);
274 | } else { // must be SPI
275 | obdSetDCMode(pOBD, MODE_DATA);
276 | if (pOBD->iFlags & OBD_CS_EVERY_BYTE) {
277 | for (int i=0; iiCSPin, LOW);
279 | AIOWriteSPI(pOBD->bbi2c.file_i2c, &pData[i], 1);
280 | digitalWrite(pOBD->iCSPin, HIGH);
281 | }
282 | } else {
283 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP)
284 | digitalWrite(pOBD->iCSPin, LOW);
285 | AIOWriteSPI(pOBD->bbi2c.file_i2c, pData, iLen);
286 | if (pOBD->iCSPin != 0xff &&pOBD->chip_type != OBD_CHIP_SHARP)
287 | digitalWrite(pOBD->iCSPin, HIGH);
288 | }
289 | //obdSetDCMode(pOBD, MODE_DATA);
290 | }
291 | #else
292 | (void)pOBD; (void)pData; (void)iLen;
293 | #endif // MEMORY_ONLY
294 | } /* RawWriteData() */
295 | #else // Arduino
296 | static void RawWrite(OBDISP *pOBD, unsigned char *pData, int iLen)
297 | {
298 | #if !defined( WIMPY_MCU )
299 | if (pOBD->com_mode == COM_SPI) // we're writing to SPI, treat it differently
300 | {
301 | if (pOBD->iDCPin != 0xff)
302 | {
303 | digitalWrite(pOBD->iDCPin, (pData[0] == 0) ? LOW : HIGH); // data versus command
304 | }
305 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP)
306 | {
307 | digitalWrite(pOBD->iCSPin, LOW);
308 | }
309 | #ifdef HAL_ESP32_HAL_H_
310 | {
311 | uint8_t ucTemp[1024];
312 | if (pOBD->bBitBang)
313 | SPI_BitBang(pOBD, &pData[1], iLen-1, pOBD->iMOSIPin, pOBD->iCLKPin);
314 | else
315 | mySPI->transferBytes(&pData[1], ucTemp, iLen-1);
316 | }
317 | #else
318 | for (int i=1; ibBitBang)
320 | SPI_BitBang(pOBD, &pData[i], 1, pOBD->iMOSIPin, pOBD->iCLKPin);
321 | else
322 | mySPI->transfer(pData[i]);
323 | }
324 | #endif
325 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP) {
326 | digitalWrite(pOBD->iCSPin, HIGH);
327 | }
328 | if (pOBD->iDCPin != 0xff && pData[0] == 0) { // was command mode, set back to data mode
329 | digitalWrite(pOBD->iDCPin, HIGH);
330 | }
331 | }
332 | else // must be I2C
333 | #endif // !WIMPY_MCU
334 | {
335 | if (pOBD->bbi2c.bWire && iLen > 32) // Hardware I2C has write length limits
336 | {
337 | iLen--; // don't count the 0x40 byte the first time through
338 | while (iLen >= 31) // max 31 data byes + data introducer
339 | {
340 | I2CWrite(&pOBD->bbi2c, pOBD->oled_addr, pData, 32);
341 | iLen -= 31;
342 | pData += 31;
343 | pData[0] = 0x40;
344 | }
345 | if (iLen) iLen++; // If remaining data, add the last 0x40 byte
346 | }
347 | if (iLen) // if any data remaining
348 | {
349 | I2CWrite(&pOBD->bbi2c, pOBD->oled_addr, pData, iLen);
350 | }
351 | } // I2C
352 | } /* RawWrite() */
353 | void RawWriteData(OBDISP *pOBD, unsigned char *pData, int iLen)
354 | {
355 | #if !defined( WIMPY_MCU )
356 | if (pOBD->com_mode == COM_SPI) // we're writing to SPI, treat it differently
357 | {
358 | if (pOBD->iDCPin != 0xff)
359 | digitalWrite(pOBD->iDCPin, HIGH); // data mode
360 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP)
361 | digitalWrite(pOBD->iCSPin, LOW);
362 | //#ifdef HAL_ESP32_HAL_H_
363 | // {
364 | // uint8_t ucTemp[1024];
365 | // mySPI->transferBytes(pData, ucTemp, iLen);
366 | // }
367 | //#else
368 | if (pOBD->iFlags & OBD_CS_EVERY_BYTE) {
369 | for (int i=0; iiCSPin, LOW);
371 | mySPI->transfer(pData[i]);
372 | digitalWrite(pOBD->iCSPin, HIGH);
373 | }
374 | } else { // no need for CS on every byte
375 | for (int i=0; itransfer(pData[i]);
377 | }
378 | }
379 | //#endif
380 | if (pOBD->iCSPin != 0xff && pOBD->chip_type != OBD_CHIP_SHARP)
381 | digitalWrite(pOBD->iCSPin, HIGH);
382 | }
383 | else // must be I2C
384 | #endif // !WIMPY_MCU
385 | {
386 | u8Temp[0] = 0x40; // data prefix byte
387 | while (iLen >= 31) { // max 31 data byes + data introducer
388 | memcpy(&u8Temp[1], pData, 31);
389 | I2CWrite(&pOBD->bbi2c, pOBD->oled_addr, u8Temp, 32);
390 | iLen -= 31;
391 | pData += 31;
392 | } // while >= 31 bytes to send
393 | if (iLen) // if any data remaining
394 | {
395 | memcpy(&u8Temp[1], pData, iLen);
396 | I2CWrite(&pOBD->bbi2c, pOBD->oled_addr, u8Temp, iLen+1);
397 | }
398 | } // I2C
399 | } /* RawWriteData() */
400 | #endif // _LINUX_
401 |
402 | #ifdef _LINUX_
403 | void _delay(int iDelay)
404 | {
405 | usleep(iDelay * 1000);
406 | } /* _delay() */
407 | #else // Arduino
408 | void _delay(int iDelay)
409 | {
410 | #ifdef NOT_HAL_ESP32_HAL_H_
411 | // light sleep to save power
412 | esp_sleep_enable_timer_wakeup(iDelay * 1000);
413 | // esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
414 | esp_light_sleep_start();
415 | #else // any other platform
416 | delay(iDelay); // use the Arduino delay function
417 | #endif // ESP32
418 | }
419 | #endif // _LINUX_
420 |
--------------------------------------------------------------------------------
/src/obd_stub.inl:
--------------------------------------------------------------------------------
1 | //
2 | // Stub functions to allow the obd_gfx functions to be used
3 | // in a stand-alone mode without the display interface code
4 | //
5 | // obd_stub.inl
6 | #include
7 | #define MAX_CACHE 192
8 | static uint8_t u8Cache[MAX_CACHE];
9 | static volatile uint8_t u8End = 0;
10 | static uint8_t u8Temp[40]; // for stretched character drawing
11 |
12 | const uint8_t ucMirror[256] PROGMEM =
13 | {0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
14 | 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
15 | 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
16 | 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
17 | 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
18 | 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
19 | 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
20 | 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
21 | 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
22 | 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
23 | 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
24 | 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
25 | 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
26 | 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
27 | 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
28 | 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255};
29 |
30 | uint8_t pgm_read_byte(const uint8_t *p)
31 | {
32 | return p[0];
33 | } /* pgm_read_byte() */
34 |
35 | // Write raw (unfiltered) bytes directly to I2C or SPI
36 | static void RawWrite(OBDISP *pOBD, unsigned char *pData, int iLen)
37 | {
38 | (void)pOBD; (void)pData; (void)iLen;
39 | } /* RawWrite() */
40 |
41 | void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender)
42 | {
43 | int iPitch = pOBD->width;
44 |
45 | y >>= 3; // DEBUG - since we address the display by lines of 8 pixels
46 | pOBD->iScreenOffset = (y*iPitch)+x;
47 |
48 | } /* obdSetPosition() */
49 |
50 | void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender)
51 | {
52 | int iPitch, iBufferSize;
53 | int iRedOffset = 0;
54 |
55 | iPitch = pOBD->width;
56 | iBufferSize = iPitch * ((pOBD->height+7) / 8);
57 | if (pOBD->iFG == OBD_RED) {
58 | iRedOffset = pOBD->width * ((pOBD->height+7)/8);
59 | }
60 | // Keep a copy in local buffer
61 | if (pOBD->ucScreen && (iLen + pOBD->iScreenOffset) <= iBufferSize)
62 | {
63 | memcpy(&pOBD->ucScreen[iRedOffset + pOBD->iScreenOffset], ucBuf, iLen);
64 | pOBD->iScreenOffset += iLen;
65 | // wrap around ?
66 | if (pOBD->iScreenOffset >= iBufferSize)
67 | pOBD->iScreenOffset -= iBufferSize;
68 | }
69 | } /* obdWriteDataBlock() */
70 |
71 |
--------------------------------------------------------------------------------