Final Project¶
Final Project Slide Final Project Video
For my final project, my original idea was to make a compact, battery powered, easily customizable display that could be reproduced simply. My original intention was also to make this something that could hide behind picture frames easily and be installed in photographs or paintings. I still did make a display with the original features I described, but it ended up being, for the most part, a standalone device, not for hiding behind picture frames. though this could still be done with what i made, i did not experiment with this use as much.
The Board¶
Attempt 1¶
When first approaching a design for the board, I searched online for other battery powered, ESP and E-Ink projects. Even though I was not completely aware of the differences between the two when I started, I knew I wanted to use the ESP32 over the ESP8266, because I knew it had more features that I would discover while working with it, and wanted to become familiar with the latest ESP model; even though there is less documentation on it at the moment, it will only grow in popularity.
The first project that really caugh my attention was this one: youtube and github because, even though it operated off an ESP8266, was the general package I would want: long lasting battery, connected to wifi, and a board with SPI connections as well as USB connectivity:
In my Output Devices week, I went over making the SPI connections to the esp8266, and specifically how the original configuration I was using kept failing because one of the SPI connections overlapped with one of the UART TX/RX lines, so the board could not be programmed when the e-ink display was connected. I ended up being able to plug the problem connection into a different SPI bus. With this in mind, however, after looking at the esp32 SPI connections and trying to design a board that both kept these open, and had onboard UART to USB connections as well, I decided I might be starting with too many variables, especially as I was adapting the board to ESP32, and should instead work starting from an ESP32 design that I knew worked. I decided this was definitely the better path to take when i talked about wanting to use the ESP32 in regional review, and Luc said none of his previous ESP32 board designs ended up working.
So I instead started from Neil’s Hello ESP32 Wroom design
I decided I would simply break out the SPI connections that I needed and add additional connections for battery power supply. The only thing that concerned me about doing this was the risk of powering the board from two power sources at once. To try to protect each power source, I added diodes to both the new battery connections and USB power line. My first design and schematic:
The switch sat in two small holes on the board to prevent it from moving. In networking and communications week, I go over that the best method I found for drawing holes is by adding them as a new layer and drawing circles in Kicad PCB design. To mill these, I left the traces drillbit in the small CNC, but chose the mill outline preset in mods, so that it would go through the depth of the board. I then changed the drillbit size to .4, and kept speed on 1, instead of the normal setting of 4 for outline. This ended up working perfectly the first time, so this is the technique I continued to use.
I soldered the parts onto the board (took this picture a bit late, when the board was already roughed up):
After making the board, however, I still did not have a clear idea of what Neil’s button and switch were about, or how I could program the board. I watched the videos he uploaded with the board to try to get a sense of how the button and switch were used, but could not exactly tell what was going on. SO I ended up on this page from espressif’s documentation:
Neil’s switch is connected to GPIO 0 in the design, so I figured this is where it should switch between the bootloader and normal execution.
The button, connected to the GND and EN lines, looked to be for resetting the board. This is because the EN, or enable pin, enables the 3.3v regulator and is default pulled up, so connecting it to ground will disable the 3.3v.
Description from randomnerdtutorials : “Enable (EN) is the 3.3V regulator’s enable pin. It’s pulled up, so connect to ground to disable the 3.3V regulator. This means that you can use this pin connected to a pushbutton to restart your ESP32, for example.”
So I understood what neil was doing in the videos was switching between modes for the chip and then resetting the chip.
I then had to prepare the Arduino IDE for programming the board. I downloaded the ESP32 driver by adding
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
I prepared a blan sketch to try to upload to the board, connected the board to an FTDI cable and plugged it into the computer and…no luck.
I got the following error:
I tried to move the switch into both positions just in case, but no luck.
If I unplugged the board and tried to upload the sketch, I got the same error, so it seemed the board was not establishing a connection. I googled the error too, and found it was common to get this with ESP32 boards when it seemed that everything should be working. Many troubleshooitng guides, such as this one, suggesting adding a capacitor between x and x, but it appeared that Neil’s design already did this. So, I decided it might be a hardware error.
I resoldered all the legs, and Henk told me to pay special attention to make sure I touched the tip of the iron to each of the pads on the board, to ensure that sodler would flow onto them and not just touch them.
I did this and…no change. I decided to give up and make a new board, this time keeping it even closer to Neil’s original design.
Attempt 2¶
For this new design, I removed the additional area for battery connections (which I realized was poorly designed the first time around anyway…as it only connected to the power line an not both the power and ground lines on the main board)
I still broke out the pads needed for SPI connection, but did not add anything on top of these. So I would keep it identical to Neil’s board to start.
Here is my second design:
And here it is after soldering:
I connected it to the computer, tried to upload an empty sketch and it almost worked! At least the computer was now successfully finding the board. The problem was, it would still read timed out waiting for packet header, even after showing it had uploaded 100% of the sketch.
I tried to do very basic tasks with the board using ESPtool, first with erase flash. And strangely, it would still time out when I did this, either getting stuck on the below readout indefinitely or also delivering ‘Timed out waiting for packet header’
I thought maybe something was wrong with the bootloader, so I looked up how to flash a new bootloader to the device using ESPtool, and followed this guide. This resulted in the same problem, a timeout.
I opened the Arduino serial monitor to see if this gave any other info, and noticed there was a strange readout appearing here, a flash read error:
I did some research on what this issue could be, and found that it likely described a hardware issue— it meant that for some reason the board could not communicate with its flash memory. Apparently, new ESP32s occasionally have this problem, and this error can mean that you simply need to replace the board.
The diagnostic for this was typically to run erase flash, as it should at the very least be able to do this. Already having done this, I figured that not even being able to erase flash was a pretty good sign that it simply did not have a good hardware connection to the flash memory. So I decided to replace the board. I asked Henk to remove the board for me so I could reuse the PCB, but it unfortunately still took off a lot of feet, so I had to resolder.
Attempt 3¶
I again milled the identical above design, soldered, connected, and tried to upload a blank sketch and it worked! I was happy and felt that the ease with which this one connected likely did mean that the last one had a hardware issue.
I then soldered connectors onto the SPI pins I had extended from the board and tried to upload the sketch to run an e-ink display that I had worked on in the Output Devices week. I only had to change the initial list of connections at the beginning to work for the esp32 instead of the esp8266. These were the connections they recommended in the sketch for the ESP32, and they were the ones I had extended out in the design.
GxIO_Class io(SPI, /*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); // arbitrary selection of (16), 4
It uploaded, but nothing happened to the display. The pad for the display’s DC connection looked like it had gotten damaged a bit during soldering and was peeling off of the board a tiny bit on top. I figured that the connection was probably still working, as thepad was still solidly connected underneath the board. For some reason, I also assumed that this line was not actually affecting the connection, as I thought that DIN and DC were the same as MOSI and MISO, and that the display would not need a MISO line. I tested for connection on all the pins using a multimeter, and it seemed ok… but it was hard to tell because the board only had feet and not pins, so I could not tell if the connections were really running into the board or just up to it. So i decided to try setting up a circuit with an LED on a breadboard and seeing if each pin could control it with a blink sketch.
It turns out the only one that couldn’t was the DC connection, or pin 17. I looked for another SPI DC pin on the pinmap and decided to use GPIO15. I soldered a new pin onto that footprint of the board with a blob of solder, changed DC to 15 in the sketch, and tried uploading again. It worked!
Accelerometer¶
I had been thinking that it would be nice to be able to control the display with rotations or taps, so that I would not have to have any buttons on it and could potentially control it even while it was in a picture frame, or simply rotate it if it were sitting on a desk.
After seeing how easy it was to solder a new pin directly to the board, I decided to try and use the I2C accelerometer that I used during the Input devices week, as I thought I would only need to add 2 extra pins. I again made connections to the SDA and SCL lines, pins 20 and 22, using blobs of sodler directly on the ESP32. I connected power connections I had added for the E-ink display to a breadboard, so that i could power both the display and accelerometer with them. I first used used the same ADXL arduino library and example sketch that I had used previously just to test the accelerometer, and it worked, showing results in the Serial monitor. I then copied the most basic bits of code I thought i would need to make this work, and added them to the sketch to run the e-ink display, so that turning the accelerometer would change the image displayed. it would check the accelerometer position every 10 seconds. Here is the code I used:
Accelerometer and E-Ink sketch
#include <GxFont_GFX.h>
#include <GxEPD.h>
#include <GxGDEP015OC1/GxGDEP015OC1.h>
//#include <GxGDEH029A1/GxGDEH029A1.h> // 2.9" b/w
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#include <Fonts/FreeMonoBold9pt7b.h>
GxIO_Class io(SPI, /*CS=5*/ SS, /*DC=*/ 15, /*RST=*/ 16); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); // arbitrary selection of (16), 4
#include <SparkFun_ADXL345.h> // SparkFun ADXL345 Library
/*********** COMMUNICATION SELECTION ***********/
/* Comment Out The One You Are Not Using */
//ADXL345 adxl = ADXL345(10); // USE FOR SPI COMMUNICATION, ADXL345(CS_PIN);
ADXL345 adxl = ADXL345(); // USE FOR I2C COMMUNICATION
const unsigned char IMAGE_BLACK[] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x20, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe8, 0x40, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x20, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x10, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x05, 0x20, 0x84, 0x80, 0x17, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x50, 0x85, 0x10, 0x08, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x00, 0x54, 0x44, 0x42, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x90, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x94, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x21, 0x40, 0x00, 0x00, 0x08, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x10, 0x20, 0x00, 0x21, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x40, 0x00, 0x01, 0x24, 0x08, 0x01, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x81, 0x55, 0x14, 0x01, 0x20, 0x84, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x08, 0x40, 0x40, 0x95, 0x55, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x04, 0x59, 0x12, 0x55, 0xda, 0xa0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x02, 0x4c, 0xcf, 0x5c, 0xda, 0xa0, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0x48, 0x92, 0x55, 0x77, 0x6e, 0x91, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x01, 0x2d, 0xdf, 0xad, 0xdb, 0xec, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x54, 0xb6, 0xa9, 0xf7, 0x6d, 0x29, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x94, 0x12, 0xd6, 0xff, 0x7d, 0xef, 0xa9, 0x40, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x78, 0xba, 0xed, 0xdb, 0xb2, 0xd4, 0x80, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xad, 0x3b, 0xdd, 0x77, 0xef, 0xfd, 0xaf, 0x20, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0xdb, 0x6f, 0xfe, 0xfb, 0x5e, 0xf1, 0x90, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x22, 0xfb, 0xf9, 0xf7, 0xff, 0xeb, 0x5d, 0x48, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x5d, 0xb7, 0xbf, 0x6d, 0xbf, 0x65, 0xa0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0a, 0xff, 0xff, 0xdf, 0xfe, 0xf5, 0xbe, 0x48, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xc2, 0xfb, 0xfd, 0xfb, 0xb7, 0xbb, 0xab, 0xe4, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x2f, 0x7f, 0xff, 0xdf, 0xff, 0xdd, 0xe8, 0x50, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x8b, 0xde, 0xdf, 0xfe, 0xfa, 0xfe, 0xbf, 0xc8, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x2f, 0xff, 0xfe, 0xff, 0xef, 0x5b, 0xeb, 0x32, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x1a, 0xff, 0xef, 0x76, 0xff, 0xed, 0x39, 0xc8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xaf, 0xbf, 0xff, 0xbf, 0xfb, 0xbf, 0xdc, 0x64, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x5e, 0xf7, 0xff, 0xfe, 0xde, 0xf5, 0x57, 0xb0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x37, 0xfb, 0xff, 0xff, 0xef, 0xff, 0xfd, 0x4a, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x9f, 0xfe, 0xed, 0xd7, 0xf7, 0xaa, 0x96, 0xa9, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x6e, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xf7, 0xa8, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x3f, 0xff, 0x7f, 0x7f, 0xff, 0xf5, 0x29, 0x54, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x5b, 0xb7, 0xf7, 0xfb, 0x7b, 0x6e, 0xdf, 0xd2, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x6f, 0xff, 0x7d, 0x5f, 0xdf, 0xbb, 0xe9, 0x49, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7d, 0xf7, 0xef, 0xf5, 0xf5, 0xda, 0xb9, 0xd4, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x77, 0xdb, 0x7f, 0x5f, 0x7f, 0x6d, 0x4a, 0x49, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x5f, 0x64, 0x01, 0xfb, 0xd5, 0xb0, 0x01, 0x14, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0x25, 0x28, 0x0d, 0xfd, 0x88, 0x00, 0x02, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xed, 0x29, 0x84, 0x7e, 0xf6, 0x42, 0x41, 0x02, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xfe, 0xb6, 0x62, 0x87, 0xb9, 0x00, 0x2c, 0x80, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x69, 0x6f, 0xbd, 0x3b, 0xed, 0x15, 0x92, 0x52, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbc, 0xf7, 0xea, 0xce, 0xf4, 0xda, 0xed, 0x02, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf7, 0x7a, 0xfd, 0x77, 0x5c, 0x46, 0xb4, 0xc1, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfb, 0x6f, 0xa2, 0xbd, 0xea, 0xa9, 0xcb, 0x30, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x5d, 0xbb, 0xe9, 0x57, 0xf0, 0x13, 0x24, 0x05, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xdc, 0x04, 0x5f, 0xdf, 0xcc, 0x80, 0x90, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x5b, 0xd4, 0x45, 0x6d, 0xe1, 0x42, 0x4a, 0x44, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xfe, 0x52, 0x14, 0xbb, 0x58, 0xb4, 0x20, 0x12, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xfb, 0x67, 0x4f, 0xed, 0xf5, 0x4f, 0x14, 0xac, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xda, 0xbf, 0x5b, 0xb2, 0xef, 0xf5, 0x35, 0x58, 0x25, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xff, 0xf9, 0xb5, 0x7f, 0xb9, 0xb7, 0x4a, 0x95, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x57, 0x5e, 0xdb, 0xf5, 0xec, 0x54, 0xa4, 0x29, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xfd, 0xeb, 0x56, 0xdf, 0x73, 0x95, 0xb5, 0x56, 0x54, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xff, 0x6e, 0xef, 0xb8, 0xb6, 0xc5, 0x53, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xde, 0xf7, 0xf7, 0xf7, 0xde, 0x9a, 0xb6, 0xd8, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f, 0xff, 0xdf, 0xbf, 0xf2, 0xea, 0xf9, 0x6b, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xfb, 0xb7, 0x7e, 0xfb, 0x6d, 0x2f, 0x87, 0x54, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0x7f, 0xff, 0xef, 0xdf, 0xea, 0xaa, 0xf9, 0xda, 0x45, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xbd, 0xfb, 0xfe, 0xff, 0x6a, 0xab, 0x6e, 0xea, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xef, 0xef, 0x7f, 0xdd, 0xea, 0xad, 0xbb, 0x55, 0x0d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x7f, 0xbf, 0xea, 0xff, 0xb5, 0x36, 0xee, 0xd4, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xfd, 0xfb, 0xff, 0xdf, 0xfa, 0x9b, 0xb3, 0x6b, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xaf, 0xff, 0x7e, 0xef, 0x5a, 0xdd, 0x7d, 0x68, 0x93, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x5d, 0xf7, 0xfd, 0xed, 0x27, 0xab, 0xa6, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xdf, 0xff, 0xfb, 0xb7, 0xb2, 0x9a, 0xfd, 0x59, 0x0b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xef, 0xff, 0xfe, 0xff, 0xfa, 0xaf, 0x4f, 0x64, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0x77, 0xbe, 0xfb, 0xbf, 0xba, 0xa5, 0xe3, 0xb4, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfd, 0xf7, 0xdf, 0xf7, 0xed, 0x5e, 0xfc, 0x92, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbf, 0xfb, 0xea, 0xff, 0x78, 0x2b, 0xd7, 0xe8, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0xdf, 0xfd, 0xff, 0xb7, 0xb6, 0x8d, 0x75, 0x14, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x6d, 0x7e, 0xde, 0xd2, 0xd0, 0xa7, 0xf5, 0xd4, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x7b, 0xca, 0x40, 0x1a, 0xbd, 0x22, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xb7, 0xdb, 0xef, 0xef, 0x24, 0xab, 0x6a, 0xd8, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xff, 0xfe, 0xb1, 0x10, 0x25, 0x9f, 0x44, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbd, 0xda, 0xeb, 0xdd, 0x4a, 0x10, 0xc9, 0x52, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x57, 0xff, 0xbe, 0xa4, 0x24, 0xad, 0x36, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x6d, 0xea, 0xfb, 0x93, 0x42, 0x4d, 0x48, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9b, 0xfe, 0xaf, 0x7e, 0xfd, 0xac, 0xa5, 0x44, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0xff, 0xa7, 0xdf, 0xac, 0xa4, 0x2a, 0x21, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd6, 0xaf, 0xdb, 0x6a, 0xd2, 0x92, 0xaa, 0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfa, 0xa2, 0x95, 0x6d, 0x00, 0x54, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x7f, 0xaa, 0xeb, 0x20, 0xab, 0xd6, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x5a, 0xdf, 0xba, 0xad, 0xa4, 0x52, 0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xef, 0xdf, 0xef, 0xfa, 0x97, 0xa9, 0x13, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0xb7, 0x5a, 0xfb, 0xdd, 0x6d, 0x54, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xdb, 0x7f, 0x7e, 0xee, 0xa5, 0x48, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x5b, 0xb7, 0xed, 0x75, 0x2b, 0xa4, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xee, 0xde, 0xbb, 0x4a, 0xac, 0x91, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x53, 0x7b, 0xe4, 0x90, 0x13, 0x24, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xde, 0xb4, 0x4a, 0xd8, 0x90, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xd7, 0xfe, 0x42, 0xd6, 0x8a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc5, 0x5f, 0x6a, 0xbe, 0x5a, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xbd, 0xbf, 0x69, 0xd4, 0x81, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0xcf, 0xff, 0xbf, 0x72, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0x77, 0xaf, 0xd1, 0x92, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x9a, 0xfa, 0xfd, 0x69, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7e, 0x6f, 0xef, 0x56, 0x94, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x15, 0x75, 0xaa, 0x50, 0x10, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x7f, 0x8b, 0x5e, 0xf5, 0x0a, 0x08, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe2, 0xf7, 0xc5, 0xab, 0x14, 0xa0, 0x44, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc4, 0xfe, 0xf2, 0x5a, 0xe8, 0x41, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x22, 0xff, 0xd9, 0x42, 0x06, 0x10, 0x08, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x11, 0x6d, 0xec, 0x31, 0x50, 0x01, 0x44, 0x40, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x45, 0xff, 0x7a, 0x08, 0x22, 0x08, 0x21, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x09, 0x11, 0xdf, 0xef, 0xc0, 0x01, 0x24, 0x94, 0x80, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x20, 0x89, 0xf7, 0xbb, 0x75, 0x01, 0x04, 0x10, 0x08, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd1, 0x14, 0x20, 0xfd, 0xfd, 0x95, 0x68, 0x82, 0x95, 0x40, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x04, 0x40, 0x05, 0xff, 0xd7, 0xe9, 0x80, 0x24, 0x88, 0x00, 0x04, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x52, 0x01, 0x40, 0xee, 0xff, 0x76, 0x55, 0x52, 0x65, 0x82, 0x40, 0x88, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe2, 0x00, 0xa8, 0x08, 0x7f, 0x7b, 0xbb, 0x54, 0x01, 0x20, 0x40, 0x20, 0x00, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x42, 0x04, 0x44, 0x7f, 0xbb, 0xdb, 0xc5, 0x54, 0x12, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x02, 0x28, 0x50, 0x02, 0xef, 0xee, 0xa9, 0x30, 0x5a, 0xa9, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0x49, 0x01, 0x01, 0x50, 0x3b, 0xff, 0xfe, 0xd6, 0xa1, 0x44, 0x10, 0x02, 0x24, 0x22, 0x1f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x04, 0x90, 0xa5, 0x00, 0x3f, 0x6d, 0xd7, 0x12, 0x5d, 0x33, 0x08, 0x01, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x48, 0x80, 0x08, 0x10, 0x29, 0x1d, 0xf7, 0x7b, 0xda, 0x49, 0x08, 0x00, 0x00, 0x00, 0x21, 0x03, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xd1, 0x02, 0x22, 0x91, 0x08, 0x04, 0x0f, 0xff, 0xdd, 0x53, 0x65, 0x54, 0x00, 0x80, 0x25, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x84, 0x08, 0x10, 0x04, 0x20, 0x90, 0x03, 0xbd, 0x76, 0xac, 0x9a, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x52, 0x84, 0x88, 0x40, 0x8a, 0x0a, 0x49, 0xff, 0xda, 0xa7, 0x49, 0x50, 0x00, 0x10, 0x00, 0x08, 0x20, 0x0f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x00, 0x40, 0x04, 0x04, 0x21, 0x01, 0x00, 0xdb, 0x6e, 0xe9, 0x6a, 0x40, 0x81, 0x08, 0x00, 0x85, 0x00, 0x03, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf5, 0x11, 0x01, 0x20, 0x92, 0x08, 0x44, 0x10, 0x7f, 0xd3, 0x16, 0xa9, 0x04, 0x04, 0x02, 0x08, 0x00, 0x08, 0x01, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x44, 0x08, 0x02, 0x01, 0x40, 0x80, 0x82, 0x1e, 0xfa, 0xd5, 0x45, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x88, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc4, 0x00, 0x80, 0x8a, 0xa8, 0x24, 0x10, 0x90, 0x07, 0x5d, 0x77, 0xd0, 0x00, 0x00, 0x80, 0x40, 0x80, 0x40, 0x00, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0x22, 0x24, 0x50, 0x40, 0x02, 0x21, 0x04, 0x0a, 0x01, 0xd7, 0x3a, 0x80, 0x80, 0x00, 0x00, 0x04, 0x40, 0x08, 0x80, 0x1f, 0xff, 0xff,
0xff, 0xff, 0xff, 0x00, 0x80, 0x0a, 0x12, 0x90, 0x88, 0xa0, 0x40, 0x84, 0x08, 0x8a, 0x22, 0x12, 0x00, 0x00, 0x00, 0x04, 0x20, 0x12, 0x07, 0xff, 0xff,
0xff, 0xff, 0xff, 0x4a, 0x02, 0x01, 0x40, 0x04, 0x04, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x24, 0x20, 0x20, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x20, 0x50, 0xa8, 0x22, 0x42, 0x40, 0x85, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x04, 0x00, 0x04, 0x02, 0x01, 0x11, 0xff, 0xff,
0xff, 0xff, 0xfc, 0x00, 0x00, 0x02, 0x10, 0x20, 0x2a, 0x00, 0x43, 0x21, 0x10, 0x00, 0x11, 0x02, 0x00, 0x10, 0x20, 0x00, 0x20, 0x90, 0x00, 0xff, 0xff,
0xff, 0xff, 0xf9, 0x25, 0x0a, 0x08, 0x82, 0x09, 0x00, 0x50, 0x10, 0x08, 0x01, 0x12, 0x80, 0x10, 0x00, 0x80, 0x09, 0x41, 0x00, 0x00, 0x80, 0x7f, 0xff,
0xff, 0xff, 0xf0, 0x80, 0x20, 0x40, 0x11, 0x20, 0x80, 0x02, 0x80, 0x40, 0x84, 0x00, 0x00, 0x40, 0x20, 0x00, 0x80, 0x00, 0x04, 0x00, 0x04, 0x3f, 0xff,
0xff, 0xff, 0xec, 0x28, 0x82, 0x10, 0x89, 0x10, 0x50, 0x10, 0x10, 0x04, 0x00, 0x80, 0x10, 0x09, 0x08, 0x00, 0x00, 0x20, 0x00, 0x80, 0x20, 0x1f, 0xff,
0xff, 0xff, 0xc5, 0x04, 0x51, 0x08, 0x00, 0x08, 0x0a, 0x00, 0x88, 0x80, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x40, 0x20, 0x00, 0x0f, 0xff,
0xff, 0xff, 0x90, 0x40, 0x80, 0x04, 0x40, 0x82, 0x40, 0x84, 0x04, 0x22, 0x04, 0x22, 0x94, 0x00, 0x01, 0x20, 0x09, 0x01, 0x00, 0x08, 0x04, 0x0f, 0xff,
0xff, 0xff, 0xc5, 0x12, 0x02, 0x42, 0x12, 0x11, 0x04, 0x10, 0x02, 0x00, 0x00, 0x88, 0x00, 0x40, 0x84, 0x00, 0x40, 0x40, 0x09, 0x01, 0x00, 0x87, 0xff,
0xff, 0xff, 0xa0, 0x08, 0x90, 0x21, 0x08, 0x08, 0x20, 0x85, 0x21, 0x29, 0x20, 0x00, 0x02, 0x10, 0x40, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x03, 0xff,
0xff, 0xff, 0xaa, 0x84, 0x04, 0x00, 0x42, 0x40, 0x88, 0x10, 0x80, 0x80, 0x80, 0x09, 0x00, 0x00, 0x02, 0x10, 0x00, 0x04, 0x01, 0x08, 0x80, 0x01, 0xff,
0xff, 0xff, 0x01, 0x00, 0x41, 0x48, 0x01, 0x02, 0x04, 0x80, 0x08, 0x00, 0x12, 0x40, 0x08, 0x84, 0x00, 0x01, 0x00, 0x00, 0x40, 0x40, 0x02, 0x01, 0xff,
0xff, 0xff, 0x54, 0xaa, 0x08, 0x01, 0x08, 0x08, 0x20, 0x42, 0x00, 0x42, 0x01, 0x04, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x20, 0xff,
0xff, 0xfe, 0x90, 0x01, 0x44, 0x24, 0xa2, 0x44, 0x00, 0x21, 0x48, 0x10, 0x40, 0x82, 0x04, 0x02, 0x00, 0x40, 0x04, 0x20, 0x28, 0x01, 0x00, 0x08, 0xff,
0xff, 0xfe, 0x4a, 0xa0, 0x22, 0x10, 0x00, 0x01, 0x50, 0x00, 0x04, 0x00, 0x20, 0x20, 0x00, 0x81, 0x12, 0x10, 0x01, 0x09, 0x00, 0x20, 0x02, 0x00, 0xff,
0xff, 0xfe, 0x90, 0x08, 0x00, 0x80, 0x12, 0x48, 0x0a, 0x24, 0x10, 0xa4, 0x00, 0x01, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x48, 0x00, 0x7f,
0xff, 0xfe, 0x05, 0x42, 0x48, 0x42, 0x41, 0x02, 0x00, 0x10, 0x42, 0x01, 0x08, 0x80, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84, 0x00, 0x04, 0x7f,
0xff, 0xff, 0xa8, 0x20, 0x04, 0x08, 0x00, 0x20, 0x82, 0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x81, 0x20, 0x80, 0xa0, 0x40, 0x20, 0x40, 0x00, 0x80, 0x7f,
0xff, 0xfe, 0x44, 0x94, 0x40, 0x82, 0x21, 0x10, 0x50, 0x08, 0x42, 0x01, 0x04, 0x49, 0x20, 0x00, 0x08, 0x20, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x3f,
0xff, 0xfd, 0x12, 0x01, 0x08, 0x20, 0x88, 0x00, 0x00, 0x41, 0x10, 0x90, 0x40, 0x00, 0x08, 0x48, 0x00, 0x00, 0x14, 0x00, 0x00, 0x10, 0x84, 0x00, 0x7f,
0xff, 0xfe, 0x48, 0x50, 0x02, 0x84, 0x04, 0x45, 0x21, 0x04, 0x00, 0x08, 0x01, 0x20, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x08, 0x00, 0x00, 0x14, 0x3f,
0xff, 0xff, 0x4a, 0x0a, 0x50, 0x20, 0x80, 0x20, 0x08, 0x20, 0x4a, 0x01, 0x20, 0x0a, 0x04, 0x22, 0x40, 0x10, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x3f,
0xff, 0xfc, 0x21, 0x01, 0x00, 0x12, 0x14, 0x12, 0x42, 0x04, 0x21, 0x08, 0x09, 0x00, 0x40, 0x00, 0x00, 0x84, 0x00, 0x40, 0x88, 0x01, 0x44, 0x04, 0x3f,
0xff, 0xfe, 0x8a, 0x48, 0x12, 0x80, 0x41, 0x08, 0x00, 0x20, 0x80, 0x00, 0x80, 0x00, 0x01, 0x00, 0x08, 0x00, 0x88, 0x00, 0x01, 0x10, 0x10, 0x00, 0x3f,
0xff, 0xfe, 0x51, 0x10, 0x80, 0x24, 0x00, 0x81, 0x08, 0x84, 0x00, 0x48, 0x10, 0x89, 0x10, 0x14, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
0xff, 0xfe, 0x48, 0x84, 0x08, 0x01, 0x28, 0x40, 0x48, 0x00, 0x24, 0x04, 0x08, 0x00, 0x08, 0x00, 0x00, 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x20, 0x3f,
0xff, 0xfe, 0x22, 0x12, 0xa4, 0x90, 0x00, 0x08, 0x04, 0x4a, 0x02, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x81, 0x08, 0x40, 0x92, 0x48, 0x00, 0x00, 0x3f,
0xff, 0xfe, 0x90, 0x80, 0x00, 0x05, 0x04, 0x42, 0x81, 0x00, 0x10, 0xa2, 0x84, 0x21, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x3f,
0xff, 0xfe, 0x4a, 0x28, 0x89, 0x20, 0xa1, 0x10, 0x10, 0x20, 0x80, 0x00, 0x40, 0x04, 0x12, 0x04, 0x02, 0x48, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x3f,
0xff, 0xff, 0x02, 0x84, 0x44, 0x20, 0x10, 0x00, 0x88, 0x10, 0x04, 0x10, 0x20, 0x01, 0x00, 0x21, 0x10, 0x04, 0x00, 0x12, 0x00, 0x00, 0x01, 0x20, 0x3f,
0xff, 0xff, 0x60, 0xa2, 0x10, 0x14, 0x49, 0x48, 0x04, 0x08, 0xa2, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x00, 0x02, 0x08, 0x40, 0x02, 0x3f,
0xff, 0xfe, 0x94, 0x08, 0x42, 0x81, 0x00, 0x12, 0x40, 0x82, 0x00, 0x90, 0x00, 0x40, 0x82, 0x10, 0x00, 0x40, 0x00, 0x00, 0x40, 0x21, 0x00, 0x08, 0x3f,
0xff, 0xff, 0x01, 0x50, 0x00, 0x04, 0x0a, 0x00, 0x02, 0x20, 0x10, 0x00, 0x40, 0x00, 0x08, 0x04, 0x40, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x3f,
0xff, 0xff, 0x55, 0x05, 0x24, 0xa0, 0x40, 0xa1, 0x20, 0x09, 0x0a, 0x42, 0x12, 0x10, 0x00, 0x00, 0x14, 0x11, 0x08, 0x40, 0x00, 0x00, 0x20, 0x00, 0x3f,
0xff, 0xff, 0x00, 0xa0, 0x92, 0x0a, 0x04, 0x10, 0x92, 0x40, 0x80, 0x20, 0x41, 0x09, 0x04, 0x84, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7f,
0xff, 0xfe, 0xaa, 0x14, 0x40, 0x40, 0x50, 0x88, 0x00, 0x04, 0x02, 0x08, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x3f,
0xff, 0xff, 0x20, 0x51, 0x02, 0x05, 0x00, 0x42, 0x04, 0x20, 0x08, 0x02, 0x08, 0x40, 0x10, 0x02, 0x00, 0x00, 0x40, 0x24, 0x02, 0x10, 0x00, 0x40, 0x7f,
0xff, 0xfe, 0xa9, 0x14, 0xa0, 0x40, 0x14, 0x00, 0xa1, 0x02, 0x41, 0x01, 0x04, 0x28, 0x01, 0x01, 0x50, 0x40, 0x04, 0x02, 0x01, 0x08, 0x00, 0x24, 0x3f,
0xff, 0xfe, 0x24, 0x90, 0x12, 0x25, 0x40, 0x94, 0x04, 0x20, 0x08, 0x80, 0x40, 0x00, 0x08, 0x80, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3f,
0xff, 0xfe, 0xa1, 0x44, 0x88, 0x00, 0x04, 0x00, 0x20, 0x09, 0x00, 0x21, 0x02, 0x04, 0x80, 0x00, 0x00, 0x21, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3f,
0xff, 0xff, 0x54, 0x12, 0x41, 0x52, 0x10, 0x92, 0x01, 0x40, 0x24, 0x08, 0x00, 0x00, 0x20, 0x08, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x3f,
0xff, 0xfe, 0x92, 0x88, 0x28, 0x08, 0x8a, 0x01, 0x20, 0x24, 0x01, 0x00, 0x21, 0x20, 0x00, 0x84, 0x40, 0x00, 0x20, 0x44, 0x00, 0x00, 0x24, 0x10, 0x1f,
0xff, 0xfe, 0xa8, 0x4a, 0x82, 0x20, 0x01, 0x40, 0x10, 0x01, 0x04, 0x09, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
0xff, 0xfc, 0x42, 0x90, 0x28, 0x82, 0x44, 0x12, 0x82, 0x00, 0x20, 0x40, 0x00, 0x04, 0x10, 0x00, 0x00, 0x20, 0x08, 0x01, 0x00, 0x00, 0x00, 0x80, 0x1f,
0xff, 0xff, 0x28, 0x05, 0x02, 0x09, 0x10, 0x08, 0x20, 0x55, 0x00, 0x04, 0x04, 0x81, 0x01, 0x00, 0x80, 0x82, 0x40, 0x80, 0x22, 0x20, 0x00, 0x00, 0x1f,
0xff, 0xfc, 0x85, 0x51, 0x51, 0x40, 0x02, 0x80, 0x0a, 0x00, 0x95, 0x41, 0x00, 0x00, 0x48, 0x40, 0x48, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x0f,
0xff, 0xfe, 0x54, 0x08, 0x10, 0x11, 0x28, 0x4a, 0x40, 0x40, 0x00, 0x00, 0x40, 0x80, 0x00, 0x20, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10, 0x20, 0x0f,
0xff, 0xf9, 0xa1, 0x45, 0x4a, 0x84, 0x01, 0x00, 0x02, 0x00, 0x00, 0x11, 0x04, 0x12, 0x00, 0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x1f,
0xff, 0xfc, 0x14, 0x10, 0x10, 0x20, 0xa0, 0x21, 0x10, 0x14, 0x92, 0x00, 0x10, 0x00, 0x24, 0x00, 0x22, 0x01, 0x01, 0x10, 0x20, 0x00, 0x00, 0x08, 0x8f,
0xff, 0xfb, 0x52, 0x8a, 0x85, 0x0a, 0x09, 0x08, 0x81, 0x00, 0x00, 0x90, 0x01, 0x01, 0x02, 0x40, 0x00, 0x00, 0x80, 0x08, 0x10, 0x00, 0x02, 0x04, 0x07,
0xff, 0xf9, 0x08, 0x40, 0x00, 0x80, 0x44, 0x40, 0x44, 0x84, 0x00, 0x08, 0x88, 0x20, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07,
0xff, 0xf2, 0x41, 0x00, 0x02, 0x49, 0x00, 0x09, 0x10, 0x08, 0xa8, 0x42, 0x00, 0x84, 0x00, 0x20, 0x44, 0x40, 0x08, 0x02, 0x00, 0x00, 0x40, 0x00, 0x07,
0xff, 0xf8, 0x94, 0x29, 0x21, 0x20, 0x2a, 0xa0, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
0xff, 0xf6, 0x42, 0x08, 0x00, 0x15, 0x00, 0x08, 0x22, 0x04, 0x02, 0x00, 0x22, 0x20, 0x80, 0x04, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
0xff, 0xf2, 0xa9, 0x00, 0x01, 0x40, 0x80, 0x42, 0x00, 0x00, 0x80, 0x42, 0x10, 0x04, 0x02, 0x20, 0x00, 0x00, 0x00, 0x40, 0x80, 0x20, 0x04, 0x80, 0x07,
0xff, 0xe5, 0x00, 0x41, 0x00, 0x0a, 0x15, 0x00, 0x91, 0x24, 0x01, 0x08, 0x01, 0x00, 0x48, 0x01, 0x14, 0x00, 0x00, 0x00, 0x08, 0x80, 0x10, 0x10, 0x11,
0xff, 0xea, 0x55, 0x04, 0x40, 0x60, 0x40, 0x44, 0x04, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x04, 0x03,
0xff, 0xe1, 0x40, 0x40, 0x00, 0x22, 0x08, 0x21, 0x20, 0x10, 0x48, 0x40, 0x20, 0x04, 0x00, 0x10, 0x00, 0x22, 0x40, 0x10, 0x00, 0x09, 0x00, 0x00, 0x01,
0xff, 0xd4, 0x50, 0x00, 0x00, 0x11, 0x24, 0x10, 0x15, 0x08, 0x20, 0x04, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x00,
0xff, 0xc2, 0x84, 0xa0, 0x00, 0x48, 0x80, 0x81, 0x00, 0x02, 0x02, 0x40, 0x11, 0x22, 0x12, 0x48, 0x21, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01,
0xff, 0xd4, 0x52, 0x00, 0x40, 0x02, 0x22, 0x48, 0x00, 0x21, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x03, 0x00, 0x02, 0x00, 0x00,
0xff, 0xc2, 0x40, 0x24, 0x10, 0x28, 0x10, 0x02, 0x4a, 0x00, 0x10, 0x09, 0x00, 0x00, 0x00, 0x01, 0x10, 0x50, 0x10, 0x02, 0x01, 0x00, 0x00, 0x80, 0x00,
0xff, 0x91, 0x29, 0x00, 0x00, 0x02, 0x8a, 0x48, 0x00, 0x21, 0x00, 0x80, 0x42, 0x49, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x45, 0x00, 0x00, 0x22, 0x40,
0xff, 0x80, 0x12, 0x00, 0x00, 0x88, 0x00, 0x02, 0x42, 0x84, 0x08, 0x09, 0x08, 0x00, 0x41, 0x48, 0x08, 0x00, 0x00, 0x00, 0x05, 0x80, 0x00, 0x00, 0x00,
0xff, 0xaa, 0x40, 0x22, 0x00, 0x22, 0x50, 0xa0, 0x08, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00, 0x80, 0x02, 0x80, 0x40, 0x00, 0x00,
0xff, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x12, 0x40, 0x20, 0x00, 0x40, 0x00, 0x24, 0x10, 0x00, 0x01, 0x01, 0x00, 0x20, 0x0a, 0xc0, 0x00, 0x00, 0x00,
};
const unsigned char APPLE[] PROGMEM = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x65, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc5, 0xda, 0x95, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x36, 0x6d, 0xd7, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb3, 0x93, 0x54, 0xab, 0xab, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x98, 0xed, 0x57, 0x74, 0xda, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xe7, 0x5a, 0xba, 0x8b, 0x25, 0xaf, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x2a, 0xa7, 0x4d, 0x6a, 0xfa, 0xb7, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed, 0xb2, 0xf9, 0xb5, 0x5a, 0x4d, 0x52, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0x5f, 0x0e, 0xd5, 0x65, 0xa5, 0xad, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0xe8, 0xf3, 0x6b, 0x97, 0x3b, 0x52, 0xaf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2a, 0x17, 0x3c, 0x99, 0x72, 0xcc, 0xbd, 0x57, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xad, 0xd5, 0x96, 0xc9, 0x52, 0xa5, 0x45, 0x53, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x57, 0x55, 0x6b, 0x36, 0xba, 0xd6, 0xbd, 0x69, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa9, 0x2a, 0xb4, 0xeb, 0x4d, 0x29, 0x52, 0xaf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0xad, 0xb5, 0x57, 0x2d, 0xa7, 0xad, 0x9b, 0x50, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd8, 0xad, 0x55, 0xa1, 0xaa, 0xb1, 0x6d, 0x55, 0x5b, 0x5f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xaf, 0x55, 0x4a, 0xbe, 0x74, 0xae, 0xa5, 0xda, 0xad, 0x3f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0xaa, 0xb7, 0x41, 0x96, 0xad, 0x5b, 0x25, 0x52, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2e, 0xab, 0x59, 0x7a, 0xd5, 0x53, 0x6a, 0xd5, 0xaa, 0x9f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x6a, 0xad, 0x2d, 0x55, 0x79, 0x2a, 0xb4, 0xb4, 0xcf, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x54, 0xaa, 0x55, 0xb5, 0x56, 0x8d, 0x5d, 0x57, 0x57, 0x65, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x56, 0xcd, 0x6a, 0xab, 0x55, 0x72, 0x62, 0x49, 0x4a, 0x9b, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x7a, 0xb7, 0xb6, 0xd5, 0x5a, 0x9b, 0x3b, 0x55, 0x72, 0xca, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x4a, 0x94, 0xab, 0x6d, 0xdb, 0xdb, 0xcb, 0x56, 0x5a, 0x6b, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb7, 0x6b, 0xbd, 0xb7, 0x2a, 0xad, 0x75, 0xdb, 0xab, 0xa9, 0x1f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xcc, 0xae, 0xe2, 0x48, 0xe6, 0xf5, 0x5a, 0xac, 0x4d, 0x56, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x76, 0xb5, 0x39, 0x57, 0x2a, 0x95, 0x4a, 0xa7, 0x65, 0x5b, 0x3f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x57, 0xd5, 0x96, 0xd1, 0xea, 0x5a, 0xae, 0xb1, 0xb5, 0x69, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xaa, 0xa5, 0x5a, 0x56, 0x35, 0xa6, 0xd1, 0x4e, 0xd5, 0x95, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb5, 0x5a, 0xaf, 0xaa, 0xcd, 0x59, 0x77, 0xb1, 0x17, 0x6f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x9b, 0x54, 0xa0, 0xd5, 0x27, 0x4d, 0x29, 0x5e, 0xe9, 0xaf, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0x49, 0x56, 0xba, 0x5a, 0xd1, 0xe5, 0xbd, 0xaa, 0x56, 0xef, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xed, 0xaa, 0xca, 0xc5, 0xbe, 0xb4, 0x8a, 0x95, 0xb9, 0x7f, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xb5, 0x56, 0xbb, 0x3e, 0x6f, 0xfb, 0x72, 0xeb, 0x67, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x52, 0x8e, 0xd7, 0xff, 0xfd, 0x9e, 0xad, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xff, 0xff, 0x5a, 0xff, 0x7f, 0xff, 0xfe, 0xff, 0xea, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x06, 0xa4, 0x15, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xab, 0x78, 0x45, 0x15, 0x55, 0x15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x5b, 0xd8, 0x8d, 0x12, 0xa5, 0x54, 0xc6, 0xbf, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0xd6, 0xb7, 0x20, 0x4a, 0x5a, 0xab, 0x2a, 0xed, 0x7a, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0x5a, 0xc8, 0xae, 0x05, 0xa2, 0xad, 0xab, 0xb2, 0x87, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xab, 0xea, 0x6e, 0x43, 0x24, 0xbb, 0xea, 0xbd, 0xa8, 0x20, 0xca, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xf4, 0x25, 0x51, 0xb4, 0x93, 0xcd, 0x3f, 0x7e, 0xd1, 0x12, 0x2e, 0xaf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xab, 0x4f, 0xdd, 0xaa, 0x4a, 0x82, 0x3b, 0xfd, 0xeb, 0x4a, 0x40, 0x01, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb5, 0x7a, 0xf6, 0xed, 0x2a, 0x81, 0xdf, 0xee, 0xb5, 0x09, 0x2a, 0x91, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x9f, 0xaf, 0x5f, 0xff, 0xeb, 0xff, 0xf9, 0x25, 0x10, 0xa0, 0x00, 0x88, 0x34, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x75, 0xf7, 0xfe, 0xad, 0xbe, 0xda, 0x44, 0x08, 0x44, 0x09, 0x54, 0x42, 0x8a, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xdf, 0x5a, 0xfb, 0x76, 0xfb, 0x25, 0x12, 0xa1, 0x4a, 0xa4, 0x02, 0x99, 0x25, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xed, 0xff, 0xd5, 0x52, 0x88, 0x81, 0x48, 0x8c, 0x22, 0x02, 0x50, 0x48, 0x91, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x95, 0x77, 0x76, 0xd9, 0x54, 0xca, 0xa9, 0x26, 0x45, 0x11, 0x49, 0x04, 0x04, 0x48, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0xdb, 0xdf, 0x6e, 0xaa, 0x25, 0x54, 0x90, 0xa0, 0x84, 0x24, 0x51, 0x53, 0x15, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x2b, 0x6d, 0xfd, 0xd2, 0xd5, 0xdb, 0x48, 0x4b, 0x55, 0x31, 0x40, 0x82, 0x28, 0xa4, 0x9b, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xad, 0xb5, 0x6f, 0x7e, 0xdd, 0x6d, 0x6f, 0x11, 0x08, 0x94, 0x3a, 0x58, 0x84, 0x92, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0xa6, 0xdb, 0x55, 0xdb, 0xee, 0xb7, 0xa4, 0xcc, 0xe4, 0x05, 0x01, 0x04, 0x54, 0xaa, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf6, 0x9b, 0x69, 0x7f, 0xee, 0xb7, 0xed, 0xfb, 0x33, 0x13, 0x52, 0x94, 0xa2, 0x82, 0x29, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf1, 0x34, 0x97, 0xbe, 0xbb, 0xba, 0xb6, 0x94, 0xd4, 0xe8, 0x88, 0x12, 0x4d, 0x29, 0x42, 0x96, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc8, 0xd3, 0x59, 0xd7, 0xdd, 0xdf, 0x76, 0xea, 0x56, 0x2c, 0x25, 0x44, 0xa0, 0x84, 0x5a, 0xd1, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xca, 0x5a, 0x8e, 0xfd, 0xee, 0xef, 0xbb, 0x3f, 0x53, 0x56, 0x91, 0x24, 0x56, 0xb2, 0x24, 0x55, 0xbf, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x95, 0xad, 0x75, 0xd6, 0xb7, 0xb5, 0x5d, 0xd1, 0x5d, 0x21, 0x24, 0x52, 0x88, 0x44, 0x93, 0x12, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xa2, 0x52, 0xaf, 0x7b, 0xfe, 0xdb, 0xf7, 0x6e, 0xa4, 0xd4, 0x91, 0x08, 0x25, 0x09, 0x48, 0xec, 0x9f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x19, 0x1a, 0x6f, 0x5d, 0x5b, 0x6d, 0x5a, 0xb1, 0x55, 0x14, 0x09, 0x45, 0x52, 0xa4, 0x24, 0x22, 0x4f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x8d, 0xab, 0xb7, 0xef, 0xbd, 0xbb, 0xda, 0x9d, 0x4d, 0x8b, 0x44, 0x50, 0x08, 0x92, 0x95, 0x59, 0x2f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x22, 0x95, 0x7d, 0x74, 0xd6, 0xed, 0x6d, 0xca, 0xb2, 0x64, 0x21, 0x06, 0xc5, 0x48, 0x04, 0xa6, 0x8f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x94, 0xaa, 0xf7, 0xef, 0x7b, 0xb6, 0xb6, 0xb5, 0x54, 0x92, 0x94, 0x10, 0x12, 0x25, 0x52, 0x0a, 0xa7, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x8a, 0xb3, 0x5d, 0x35, 0xae, 0xdf, 0xbb, 0x6d, 0x52, 0x52, 0x41, 0x49, 0x51, 0x24, 0x89, 0x72, 0xa7, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf8, 0xa5, 0x55, 0xed, 0xde, 0xf6, 0xd5, 0xad, 0xb5, 0x59, 0x11, 0x10, 0x04, 0x14, 0x12, 0x45, 0x0a, 0x53, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfa, 0x52, 0x57, 0x77, 0x73, 0x5b, 0x6e, 0xb4, 0xaa, 0x54, 0x4a, 0x4a, 0xa1, 0x41, 0x49, 0x22, 0x2b, 0x27, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0x04, 0x89, 0xdd, 0xed, 0xed, 0xb9, 0x57, 0x55, 0xa2, 0x91, 0x20, 0x14, 0x12, 0x20, 0x98, 0xc5, 0x49, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0x6b, 0x6f, 0x6d, 0x3d, 0x56, 0xcf, 0xa9, 0x6a, 0xaa, 0xc8, 0x8a, 0x84, 0x88, 0x8a, 0x4a, 0x29, 0xab, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe0, 0x28, 0x83, 0x6d, 0xad, 0xea, 0xf5, 0x55, 0x29, 0x20, 0x52, 0x40, 0x42, 0x4a, 0x61, 0x21, 0x8d, 0x89, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xea, 0x85, 0x7d, 0xb6, 0xd7, 0x5f, 0x5b, 0xaa, 0xd5, 0x95, 0x09, 0x2a, 0x11, 0x21, 0x08, 0x14, 0x62, 0xe5, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x75, 0x16, 0xfb, 0xba, 0xea, 0xf4, 0x55, 0x2a, 0xa4, 0x60, 0x90, 0x88, 0x14, 0x23, 0x42, 0x95, 0x12, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe5, 0x15, 0x5b, 0x2a, 0xab, 0x36, 0x9f, 0x56, 0xaa, 0x51, 0x2c, 0x4a, 0x85, 0x08, 0xa8, 0x50, 0x45, 0xd9, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe8, 0x45, 0x4d, 0xff, 0xdb, 0xb6, 0xcb, 0x53, 0x29, 0x2c, 0x02, 0x20, 0x44, 0x84, 0x04, 0x48, 0x54, 0xca, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc2, 0xa9, 0x37, 0x2a, 0x6d, 0x55, 0x6a, 0xac, 0xaa, 0x81, 0x54, 0x88, 0x90, 0x52, 0x49, 0x25, 0x03, 0x71, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe5, 0x12, 0x5a, 0xf5, 0xd5, 0x6e, 0xd5, 0x55, 0x4a, 0x2a, 0x22, 0x22, 0x01, 0x09, 0x04, 0x88, 0xa8, 0xac, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xa0, 0x4a, 0xcb, 0x56, 0x5d, 0xb3, 0x35, 0x92, 0xa1, 0xa1, 0x11, 0x12, 0x54, 0x40, 0xa2, 0x44, 0x15, 0xb5, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xd5, 0x22, 0x6a, 0xb7, 0x4d, 0x5b, 0x94, 0xda, 0xb4, 0x14, 0x84, 0x81, 0x01, 0x28, 0x10, 0x12, 0x44, 0xaa, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x99, 0x3b, 0x59, 0xa5, 0xac, 0xeb, 0x25, 0x49, 0x49, 0x50, 0x10, 0x24, 0x05, 0x42, 0x81, 0x22, 0xd4, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xd6, 0x54, 0xca, 0xed, 0x76, 0xab, 0x2a, 0x54, 0xa4, 0x24, 0x45, 0x4a, 0x09, 0x50, 0x28, 0x54, 0x08, 0x3a, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x81, 0x26, 0x6d, 0x27, 0x53, 0x6a, 0xb5, 0x92, 0x12, 0x82, 0x20, 0x01, 0x80, 0x0a, 0x25, 0x09, 0xa5, 0xd5, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xa4, 0x32, 0xa6, 0xf2, 0xf9, 0x2d, 0x14, 0xaa, 0xd0, 0x52, 0x92, 0x80, 0x55, 0x42, 0x10, 0x84, 0x14, 0x5a, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x91, 0x41, 0x3b, 0x4d, 0x0f, 0xaa, 0xd2, 0x95, 0x0a, 0x88, 0x08, 0x59, 0x00, 0x11, 0x45, 0x21, 0x21, 0x29, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x4a, 0x2a, 0xa5, 0x5a, 0xe8, 0xd5, 0x2a, 0x60, 0xa4, 0x22, 0xa9, 0x04, 0x42, 0x84, 0x10, 0x94, 0x8a, 0xbd, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x89, 0x28, 0xbb, 0x4b, 0x56, 0x6a, 0xa9, 0x2a, 0x13, 0x21, 0x04, 0x80, 0x10, 0x20, 0x8a, 0x00, 0x50, 0x85, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x89, 0x0c, 0x8b, 0xb5, 0x55, 0x32, 0xaa, 0x23, 0x48, 0x90, 0xc2, 0x55, 0x09, 0x14, 0x41, 0x4a, 0x0c, 0xf4, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x44, 0x52, 0x68, 0xd8, 0xab, 0x9a, 0x29, 0x98, 0x82, 0x08, 0x10, 0x00, 0xa4, 0x82, 0x12, 0x20, 0xa2, 0x1a, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xa9, 0x08, 0x97, 0x26, 0xaa, 0x65, 0x54, 0x22, 0x68, 0x53, 0x4a, 0x88, 0x00, 0x50, 0x88, 0x8a, 0x09, 0x75, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x04, 0xa6, 0xb5, 0xba, 0xad, 0x55, 0x15, 0x8a, 0x25, 0x00, 0x00, 0x4a, 0x28, 0x04, 0x44, 0x41, 0xa9, 0x2e, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x42, 0x10, 0x85, 0x4a, 0xa6, 0xa9, 0x92, 0x42, 0x10, 0x29, 0x54, 0x22, 0x84, 0x51, 0x22, 0x28, 0x24, 0xb2, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x11, 0x46, 0x69, 0xaa, 0x92, 0xaa, 0x49, 0x35, 0x45, 0x44, 0x02, 0x00, 0x01, 0x04, 0x08, 0x84, 0x92, 0xac, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x94, 0x10, 0x82, 0x54, 0xad, 0x55, 0x94, 0x48, 0x28, 0x00, 0x89, 0x4a, 0x14, 0x20, 0xa1, 0x20, 0x09, 0x36, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x05, 0x4a, 0x58, 0x52, 0x85, 0x52, 0x65, 0x03, 0x02, 0xa4, 0x40, 0x20, 0x81, 0x04, 0x14, 0x8d, 0x41, 0x95, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x20, 0x41, 0x06, 0x14, 0x61, 0x13, 0x15, 0x50, 0x90, 0x82, 0x08, 0x88, 0xa8, 0x52, 0x42, 0x40, 0x28, 0xd5, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x0b, 0x24, 0xa1, 0x49, 0x14, 0xa8, 0xa0, 0x48, 0x04, 0x10, 0xa2, 0x02, 0x00, 0x80, 0x10, 0xaa, 0x85, 0x74, 0xbf, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xa0, 0x12, 0x8c, 0x91, 0x49, 0x05, 0x2b, 0x05, 0x28, 0x4a, 0x08, 0x28, 0xa2, 0x09, 0x45, 0x01, 0x15, 0x0d, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0x0a, 0x88, 0x44, 0x4c, 0x09, 0x50, 0xa9, 0x60, 0x82, 0x00, 0x82, 0x08, 0x12, 0x24, 0x10, 0xa8, 0x44, 0xf4, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x40, 0xa5, 0x45, 0x22, 0xa9, 0x1a, 0x10, 0x24, 0x52, 0x4a, 0x41, 0x04, 0x01, 0x02, 0x88, 0x05, 0x12, 0x15, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x12, 0x00, 0x22, 0x45, 0x04, 0xa1, 0x4d, 0x12, 0x08, 0x80, 0x28, 0x40, 0x90, 0x48, 0x45, 0x20, 0x85, 0xea, 0x3f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x44, 0x55, 0x49, 0x10, 0x51, 0x15, 0x20, 0x80, 0xa2, 0x08, 0x82, 0x92, 0x25, 0x01, 0x14, 0x8a, 0x22, 0x54, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x05, 0x44, 0x28, 0x95, 0x08, 0x80, 0x2a, 0x68, 0x09, 0x44, 0x50, 0x49, 0x00, 0x50, 0x42, 0x20, 0x91, 0x2a, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x22, 0x84, 0x84, 0xa8, 0x55, 0x01, 0x0a, 0x20, 0x10, 0x00, 0x00, 0x50, 0x08, 0x29, 0x14, 0x4a, 0xb1, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x54, 0x50, 0x24, 0x50, 0x05, 0x40, 0xaa, 0x21, 0x04, 0x44, 0x15, 0x15, 0x0a, 0x82, 0x80, 0x82, 0x22, 0xca, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x81, 0x05, 0x11, 0x25, 0x52, 0x2a, 0x88, 0x84, 0x12, 0x01, 0x50, 0x40, 0x20, 0x28, 0x2a, 0x28, 0x89, 0x39, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x84, 0x91, 0x44, 0x11, 0x21, 0x08, 0x24, 0xa2, 0x81, 0x20, 0x0a, 0x24, 0x14, 0x05, 0x01, 0x22, 0x4a, 0x84, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x92, 0x11, 0x22, 0x88, 0x91, 0x45, 0x80, 0x10, 0x04, 0x94, 0x80, 0x12, 0x04, 0xa0, 0x50, 0x91, 0x4a, 0xd5, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x40, 0x84, 0x28, 0x52, 0x28, 0x28, 0x2a, 0xa5, 0x50, 0x00, 0x04, 0x40, 0x92, 0x05, 0x04, 0x08, 0x11, 0x50, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x8a, 0x50, 0x92, 0x88, 0x82, 0x92, 0x90, 0x10, 0x02, 0x8a, 0x90, 0x84, 0x41, 0x20, 0x22, 0xa2, 0xa5, 0x25, 0x7f, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x24, 0x12, 0x4a, 0x2a, 0x00, 0x44, 0x88, 0xa0, 0x40, 0x0a, 0x22, 0x20, 0x11, 0x10, 0x08, 0x94, 0xd1, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xaa, 0x12, 0x80, 0x09, 0x11, 0x5a, 0x2a, 0x04, 0x04, 0x09, 0x81, 0x20, 0x15, 0x08, 0x0a, 0xa4, 0x4a, 0x54, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0x80, 0x80, 0x55, 0x40, 0xc2, 0x20, 0x80, 0x22, 0x51, 0x20, 0x24, 0x11, 0x40, 0x82, 0x80, 0x03, 0x23, 0x43, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe5, 0x25, 0x02, 0x1a, 0x28, 0x86, 0x28, 0x89, 0x00, 0x84, 0x00, 0x84, 0x02, 0x28, 0x55, 0x28, 0x8c, 0xa9, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xc0, 0x11, 0x50, 0x88, 0x0a, 0x52, 0x8a, 0x20, 0x48, 0x22, 0x90, 0x50, 0x91, 0x04, 0x00, 0x04, 0xa3, 0x25, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe5, 0x00, 0x14, 0x85, 0x41, 0x09, 0x45, 0x15, 0x21, 0x08, 0x44, 0x04, 0x48, 0x82, 0x45, 0x52, 0x29, 0x13, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xd0, 0xaa, 0x82, 0x52, 0x28, 0xa4, 0x20, 0x80, 0x08, 0x11, 0x02, 0x01, 0x00, 0x28, 0x10, 0x88, 0xa5, 0x47, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe8, 0x40, 0x48, 0x08, 0x82, 0x11, 0x4a, 0x54, 0x42, 0x44, 0x11, 0x54, 0x4a, 0x81, 0x42, 0x45, 0x14, 0x95, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xe2, 0x11, 0x25, 0x44, 0x48, 0x95, 0x08, 0x01, 0x08, 0x02, 0x80, 0x00, 0x40, 0x48, 0x08, 0x20, 0xc2, 0x47, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf1, 0x08, 0x00, 0x42, 0x22, 0x00, 0xa6, 0xa8, 0x42, 0x40, 0x50, 0x92, 0x12, 0x24, 0x85, 0x1c, 0x59, 0x27, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf0, 0x42, 0xaa, 0x29, 0x08, 0xaa, 0x40, 0x05, 0x08, 0x84, 0x09, 0x08, 0x08, 0x00, 0x48, 0x42, 0xa6, 0x97, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0x28, 0x10, 0x80, 0x42, 0x42, 0x09, 0x50, 0x42, 0x12, 0x84, 0x20, 0xa0, 0xa2, 0x22, 0x2a, 0x90, 0x47, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf4, 0x05, 0x0a, 0x54, 0x28, 0x11, 0xa4, 0x08, 0x20, 0x40, 0x41, 0x04, 0x12, 0x11, 0x00, 0x08, 0x4d, 0x2f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xf9, 0x40, 0x81, 0x04, 0x82, 0x94, 0x11, 0x05, 0x05, 0x02, 0x20, 0x21, 0x08, 0x40, 0xab, 0x46, 0x41, 0x2f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x12, 0x28, 0x52, 0x24, 0x00, 0x84, 0x88, 0x20, 0x28, 0x09, 0x04, 0x41, 0x12, 0x04, 0xa9, 0x34, 0x9f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfc, 0x48, 0x81, 0x08, 0x10, 0xa4, 0x42, 0x20, 0x89, 0x00, 0x84, 0x12, 0x28, 0x08, 0x20, 0x52, 0x92, 0x2f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x04, 0x24, 0x45, 0x04, 0x42, 0x50, 0x84, 0x40, 0x94, 0x42, 0x80, 0x05, 0x02, 0x8a, 0x4a, 0x94, 0x9f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xfe, 0x42, 0x90, 0x20, 0x52, 0x28, 0x04, 0x44, 0x28, 0x82, 0x00, 0x22, 0x10, 0x90, 0x4a, 0x22, 0x42, 0x5f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x10, 0x05, 0x05, 0x00, 0x22, 0xa0, 0x21, 0x00, 0x20, 0x4a, 0x08, 0x80, 0x42, 0x21, 0x58, 0x95, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x05, 0x20, 0x50, 0xa4, 0x88, 0x0a, 0x84, 0x92, 0x14, 0x20, 0x44, 0x45, 0x08, 0x8a, 0x83, 0x22, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x50, 0x95, 0x04, 0x10, 0x21, 0x40, 0x20, 0x09, 0x02, 0x02, 0x02, 0x40, 0x44, 0x20, 0xa8, 0x99, 0x3f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x84, 0x10, 0xa2, 0x0a, 0x90, 0x29, 0x12, 0x40, 0x80, 0xa0, 0x80, 0x24, 0x12, 0x5c, 0x8a, 0x44, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x81, 0x44, 0x08, 0xa0, 0x05, 0x04, 0x80, 0x04, 0x2a, 0x08, 0x24, 0x10, 0x81, 0x02, 0x61, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xd4, 0x01, 0x51, 0x12, 0x08, 0x50, 0x14, 0xa0, 0x80, 0x02, 0x11, 0x42, 0x54, 0x55, 0x15, 0x68, 0x7f, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xc1, 0x54, 0x0c, 0x08, 0xa2, 0x15, 0x40, 0x14, 0x29, 0x20, 0x88, 0x10, 0x00, 0x11, 0x11, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xe0, 0x42, 0x83, 0x44, 0x09, 0x04, 0x28, 0x41, 0x00, 0x90, 0x22, 0x8a, 0xa5, 0x4a, 0x88, 0x61, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf5, 0x00, 0x48, 0x11, 0x20, 0x91, 0x02, 0x04, 0x14, 0x04, 0x80, 0x20, 0x08, 0xa4, 0x55, 0x17, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf0, 0x4a, 0x24, 0x48, 0x8a, 0x44, 0x49, 0x12, 0x40, 0xa2, 0x15, 0x01, 0x45, 0x12, 0xa5, 0x53, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xf8, 0x21, 0x01, 0x04, 0x40, 0x05, 0x00, 0x81, 0x24, 0x00, 0x80, 0x54, 0x40, 0x91, 0x12, 0x4b, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfc, 0x08, 0xa8, 0x92, 0x54, 0xa0, 0xa8, 0x10, 0x01, 0x24, 0x45, 0x00, 0x0a, 0x49, 0x4a, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xa4, 0x02, 0x41, 0x02, 0x04, 0x01, 0x42, 0x54, 0x00, 0x10, 0x55, 0x51, 0x14, 0xa1, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfd, 0x10, 0x28, 0x04, 0x29, 0x50, 0xa4, 0x08, 0x02, 0x29, 0x4a, 0x00, 0x04, 0xa2, 0x8c, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x86, 0x85, 0x52, 0xa0, 0x0a, 0x01, 0x42, 0x40, 0x80, 0x01, 0x55, 0x44, 0x92, 0x66, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0x90, 0x20, 0x08, 0x15, 0x49, 0x50, 0x21, 0x24, 0x09, 0x48, 0x11, 0x20, 0x49, 0x21, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x42, 0x95, 0x52, 0x88, 0x80, 0x09, 0x08, 0x00, 0x40, 0x02, 0x84, 0x55, 0x24, 0x94, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x00, 0x00, 0x22, 0x55, 0x44, 0x90, 0x95, 0x14, 0x49, 0x29, 0x04, 0x92, 0x4a, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0x95, 0x52, 0x4a, 0x92, 0x00, 0x00, 0x04, 0x00, 0x82, 0x20, 0x49, 0x42, 0x49, 0x28, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x09, 0x20, 0x51, 0x56, 0x92, 0x81, 0x42, 0x00, 0x95, 0x20, 0xa9, 0x29, 0x26, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x44, 0x15, 0x04, 0x00, 0x44, 0x28, 0x10, 0x50, 0x02, 0x0a, 0x12, 0x44, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x21, 0x40, 0xa8, 0xaa, 0x91, 0x02, 0x01, 0x05, 0x28, 0xa0, 0xa0, 0x95, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x08, 0x14, 0x82, 0x80, 0x00, 0x50, 0xa8, 0x00, 0x84, 0x28, 0x14, 0x45, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0xa4, 0x84, 0x50, 0x52, 0x94, 0x04, 0x01, 0x42, 0x22, 0x8d, 0x15, 0x51, 0x43, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x02, 0x51, 0x15, 0x21, 0x01, 0x11, 0x28, 0x08, 0x09, 0x20, 0xc0, 0x8c, 0x4b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa8, 0x04, 0x48, 0x44, 0x54, 0x44, 0x81, 0x20, 0xa4, 0x42, 0x15, 0x21, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0x21, 0x45, 0x32, 0x02, 0x00, 0x44, 0x10, 0x21, 0x11, 0x44, 0xaa, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0x94, 0x24, 0x0a, 0xc1, 0x48, 0x21, 0x0a, 0x14, 0x88, 0x22, 0x28, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x41, 0x02, 0x41, 0x50, 0x28, 0x22, 0x10, 0x00, 0x80, 0x52, 0x99, 0x55, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x94, 0x28, 0x94, 0x22, 0x82, 0x08, 0x82, 0x10, 0x15, 0x05, 0x42, 0x42, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x82, 0x43, 0x18, 0xa9, 0x00, 0x21, 0x45, 0x44, 0xa0, 0x29, 0x30, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x59, 0x28, 0x84, 0x84, 0x94, 0x90, 0x10, 0x52, 0x2a, 0x85, 0x48, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe4, 0xa4, 0x82, 0x52, 0x50, 0x40, 0x00, 0x41, 0x04, 0x82, 0x50, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x02, 0x59, 0x09, 0x49, 0x05, 0x45, 0x04, 0x51, 0x29, 0x0a, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xd2, 0x44, 0xa4, 0x44, 0x20, 0x20, 0x02, 0x08, 0x84, 0xa4, 0xa3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x49, 0x24, 0x92, 0x52, 0x92, 0x12, 0xa1, 0x44, 0x62, 0x12, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xb4, 0x92, 0x49, 0x24, 0x41, 0x44, 0x08, 0x09, 0x19, 0x41, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x44, 0x84, 0x89, 0x0c, 0x00, 0x95, 0x52, 0x44, 0x0a, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x54, 0x52, 0x64, 0xa5, 0x54, 0x44, 0x41, 0x02, 0xa9, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x98, 0x05, 0x0a, 0x09, 0x00, 0x02, 0x12, 0x20, 0xa2, 0x04, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe5, 0xd0, 0xa1, 0x52, 0x55, 0x50, 0x41, 0x14, 0x48, 0xaa, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x0a, 0x94, 0x81, 0x01, 0x05, 0x14, 0x41, 0x02, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x62, 0x12, 0x68, 0xd4, 0xa4, 0x82, 0x35, 0x21, 0x49, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x29, 0x48, 0x24, 0x02, 0x00, 0x49, 0x00, 0x90, 0x4f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x84, 0x82, 0x92, 0xa8, 0x92, 0x20, 0x48, 0x05, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xa8, 0x10, 0x08, 0x00, 0x48, 0x84, 0x24, 0x52, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x43, 0x52, 0x04, 0xa4, 0x04, 0x12, 0x02, 0x01, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x08, 0x00, 0x02, 0xa2, 0x81, 0x00, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0x40, 0x00, 0x00, 0x00, 0x08, 0x51, 0x5f, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xa8, 0xaa, 0x80, 0x04, 0x40, 0x00, 0x52, 0xbf, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0xfa, 0x00, 0x0a, 0x2b, 0x5b, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xd1, 0x4a, 0xbd, 0xad, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
void setup() {
// put your setup code here, to run once:
// setup the display
Serial.begin(115200);
display.init(115200);
// colours are good.
// display.fillScreen(GxEPD_WHITE);
// display.update();
// display.setTextColor(GxEPD_BLACK);
// load a font - in the library
// display.setFont(&FreeMonoBold9pt7b);
// let the strings begin
// display.setCursor(0, 0);
// display.println();
// display.println();
// display.println("@ WAAG Amsterdamm" );
// display.update();
// delay(30000);
// display.fillScreen(GxEPD_BLACK);
// display.drawBitmap(0, 0, IMAGE_BLACK, 200, 200, GxEPD_WHITE);
// display.update();
// delay(30000);
//Accelerometer
Serial.println("SparkFun ADXL345 Accelerometer Hook Up Guide Example");
Serial.println();
adxl.powerOn(); // Power on the ADXL345
adxl.setRangeSetting(16); // Give the range settings
// Accepted values are 2g, 4g, 8g or 16g
// Higher Values = Wider Measurement Range
// Lower Values = Greater Sensitivity
adxl.setSpiBit(0); // Configure the device to be in 4 wire SPI mode when set to '0' or 3 wire SPI mode when set to 1
// Default: Set to 1
// SPI pins on the ATMega328: 11, 12 and 13 as reference in SPI Library
adxl.setActivityXYZ(1, 1, 1); // Set to activate movement detection in the axes "adxl.setActivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
adxl.setActivityThreshold(75); // 62.5mg per increment // Set activity // Inactivity thresholds (0-255)
adxl.setInactivityXYZ(1, 0, 0); // Set to detect inactivity in all the axes "adxl.setInactivityXYZ(X, Y, Z);" (1 == ON, 0 == OFF)
adxl.setInactivityThreshold(75); // 62.5mg per increment // Set inactivity // Inactivity thresholds (0-255)
adxl.setTimeInactivity(10); // How many seconds of no activity is inactive?
}
void loop() {
int x,y,z;
adxl.readAccel(&x, &y, &z); // Read the accelerometer values and store them in variables declared above x,y,z
//
//Serial.println(x);
//Serial.println(y);
//Serial.println(z);
if (x <= 32 && x > 16){
Serial.println("GROUP A");
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, IMAGE_BLACK, 200, 200, GxEPD_WHITE);
display.update();
}
else if(x <= 16 && x > 0){
Serial.println("GROUP B");
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
// load a font - in the library
display.setFont(&FreeMonoBold9pt7b);
// let the strings begin
display.setCursor(0, 0);
display.println();
display.println();
display.println("BBBBBBBBBBBBBBB");
display.println("BBBBBBBBBBBBBBB");
display.println("BBBBBBBBBBBBBBB");
display.println("BBBBBBBBBBBBBBB");
display.update();
}
else if(x <= 0 && x > -16){
Serial.println("GROUP C");
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, APPLE, 200, 200, GxEPD_WHITE);
display.update();
}
else if(x <= -16 && x >= 32){
Serial.println("GROUP D");
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
// load a font - in the library
display.setFont(&FreeMonoBold9pt7b);
// let the strings begin
display.setCursor(0, 0);
display.println();
display.println();
display.println("DDDDDDDDDDDDDDD");
display.println("DDDDDDDDDDDDDDD");
display.println("DDDDDDDDDDDDDDD");
display.println("DDDDDDDDDDDDDDD");
display.println("DDDDDDDDDDDDDDD");
display.println("DDDDDDDDDDDDDDD");
display.update();
}
else {
Serial.println("NO GROUP");
Serial.println("GROUP D");
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
// load a font - in the library
display.setFont(&FreeMonoBold9pt7b);
// let the strings begin
display.setCursor(0, 0);
display.println();
display.println();
display.println("NO GROUP");
display.println("NO GROUP");
display.println("NO GROUP");
display.println("NO GROUP");
display.println("NO GROUP");
display.update();
}
delay(10000);
And here is my setup:
It worked! Turning the accelerometer would produce a change in image. I was happy as I had the core of the electronics down, or so at least I thought. Henk said we had some SMD accelerometers I could incorporate into my PCB design, so I decided to try and use one of these. I decided I would first try and imitate a breakout board for one of these and connect that to my existing ESP32 board, so that it would be easier to debug the accelerometer connections.
The first one I decided to use was the ADXL335. I looked at breakout boards for it, and decided to try and remake this one from sparkfun:
Here are my schematic and PCB from KiCad:
I tried bringing it into MODS, but the preview of the toolpath showed that it would not outline the individual feet, as it was too small:
I tried reducing the tool size to something smaller than .4, even though that was the smallest drillbit we had, and it still would not access the feet, even if I set the size to .3. I asked Henk about this, and he said it would not work… so I had to use a different accelerometer.
Of the ones that we had, the only one with feet that appeared big enough was a 2-axis MXD6235 From breakout boards with these online and the datasheet, it seemed I only needed to add a capacitor to each line.
I decided to use this design and try to remake the breakout board, so I printed a very tiny board for the accelerometer:
I could not find a library for this board, but tried to simply get values from the pins to understand how it worked. I tried both AnalogRead(), and a sketch which took the amount of DigitalRead() highs and lows from 100 different readings and printed out the ratio, to try and understand what kind of signals I was getting. While the signals did vary, they did not seem consistent with any pattern that made me think it was actually working. Henk suggested we look at the signals on a logic analyzer. The result- Nothing! A flat readout. The accelerometer was used when I found it, so i figured it might be dead.
We then tested the sparkfun accelerometer I had used previously, to see what ana ccelrometer output might look like, even though this was I2C, so a different type of Serial communication. This produced a clear readout, of the clock on the second line and data on the first shown here:
Henk ordered th ADXL343 in the fabacademy inventory, as we were out of them, and suggested I design for those. I again decided to use Neil’s board design, the hello.adxl343 and to just incorporate the footprint and connections from that board into my design. Here is Neil’s board:
And here is my board with the accelerometer incorporated. I did not connect to the standard I2C lines, but to pins x and x, as I had read it would be easy to redirect the I2C connection in the code:
The accelerometer only had feet underneath it, so I had to place a bit of solder on the pads then apply it with the heatgun. Here is my board with the acceleromter soldered:
I tried connecting this and using the ADXL library in Arduino, but the readout was very strange.
So I decided to use an example I2C find address sketch first to see if I could see the accelerometer. Again, the readout was very odd. It seemed to crash the program when it found the accelerometer, not print no devices found. So it was finding it, but getting some kind of erroneous readout it could not process.
I thought this might be because I was using different pins. I had made connections for the standard I2C pins on the board just in case, so I used jumpers to connect the accelerometer to the standard pins instead. This produced the same result. I tested with the accelerometer breakout board I had been using before, and this worked just fine.
I tried replacing the accelerometer, and it produced the same result. Though I wanted to get the accelerometer working and was very close to doing so, it was at this point too close to my presentation date, so i decided to abandon the accelerometer and use the touch pins that are already in the ESP32 instead. This has the added bonus of much lower power consumption anyway, so I was not too mad about it. Hopefully I figure out the accelerometer one day in the future.
I went back to the second, original working version of my board design as the final design. I also added pads to many more pins, including several of the touch pins and the main I2C SDA and SCL lines. I knew I would at least use touch pins, but this gave me more flexibility. Additionally, I added two pins that directly entered the power line after the voltage regulator, so that I could attach the battery not have the regulator consume extra power.
When I printed the new one, I also cut the SPI cable that connected to the E-ink display, so that I could solder it directly to the board. I drilled through holes in the SPI pads and ran the wires into the board from the back of it .
After some testing with this board, I milled the same design again with a new outline so that it would sit in my final case better. I additionally skipped the holes, and soldered wires directly on the pads.
Final Schematic:
Final PCB:
Board:
Power Management¶
I first bought CR2032 coin cell battery to use as the power source. I placed it in a CR2032 battery holder that we had in the lab. When I plugged it into the board, however, it would only reset the display as it powered up, but was apparently not sufficient to power the program and load/change images on the display. I attached the board to a power supply, and found the minimum voltage needed to operate it was 2.6v. I tested the battery, which is listed as 3v, to a multimeter, and whilem running it would drop to 2.4v. I told Henk about this problem, and he showed me this 3.7v 600mah rechargeable battery that I could pick up at a store in Amsterdam. I picked some up the next morning, plugged them in, and they were able to power display and the display through the program. :)
The Casing¶
Body¶
I wanted to 3d print a slim, compact case for the board that I could then put inside something more decorative or inside a frame.
The most difficult part of the design was figuring out how to center the display, which sat unevenly on its body, which had a cable on one side and a larger margin on the other. I made a pocket for the cable which, along with the shorter side of the display, added up to the wider side of the display. I made this area fit snugly around the display. This was the first layer of my design. I printed this, on the Ultimaker, slicing the files in Cura, before designing the rest of the casing, to get an idea for how it fit.
And here without the display, and with broken pegs:
I then made a second layer that would act as a pocket for the board and the battery. It had a slot for the cables to enter, but otherwise had a solid plane separating this area from the display.
All of this would then be enclosed with a flat back lid with pegs. I additionally put two circles in this lid, so that I could create touch pin access. I made the positive pegs 4mm and the negative areas they would enter 4.2mm.
Unfortunately, they didn’t really fit together when the print was done- I should have made the pegs even smaller! I was able to break some/jam them in however, figuring I could reprint. After putting the case together, however, It dawned on me that I could make it much more simply. I decided I would make a single case that had the same pocket for the screen, then within that same part of the casing, a “shelf” area that simply extended wider than the display, and which could hold the battery and board, as they were both wider than the display. I would print pegs on the back of this. This would be a single 3d printed component instead of 3. I would then laser cut the back piece, which would be flat with holes in it to sit on the pegs. This would make it much easier to adjust for size to fit well on the pegs, and additionally to experiment with designs to hold the touch pin buttons.
The second design:
The new design worked well.
Facade¶
I then wanted to make a wooden frame to cover the front of the screen. My first thought was to make something ornate, but as it would be very small and done on the CNC mill, I decided the simpler the better. I made a cutaway where the display would show through the frame. This is the design I made in Fusion:
I exported it as an stl and brought it to the CNC machine.
This was the first preview:
In order to get the machine to cut it out, but not shave off all of the material around it, Rutger suggested I add a 2d path of a rectangle around it, and keep the cutting at model boundary:
I nailed a piece of scrap wood to the machine
And entered the following settings:
Roughing
Setting | Value |
---|---|
Drillbit | 3mm 2 flute |
Stepover | 48% |
Pass Depth | 1.5mm |
Spindle Speed | 18000 |
Feed rate | 120 |
Finishing
Setting | Value |
---|---|
Drillbit | 3mm 2 flute |
Stepover | 15% |
Pass Depth | 1.5mm |
Spindle Speed | 18000 |
Feed rate | 120 |
The frame came out a bit more raggedy that I was hoping, as the wood wasn’t great quality, but I was able to get a very basic demo going. Here is the finished frame sitting in front of the display in the 3d printed case:
After seeing this, I did not like how the 3d printed case looked with the wood frame, and decided to find a way to make the entire design appear wooden. At first, I thought I would laser cut a box to go around the 3d printed display. I thought that this would be ugly however, and look like the lasercut boxes that Neil hates. So I decided a better solution, which would also keep to my original dimensions, would be to print the body as slices of wood.
After searching how to slice bodies for lasercutter fusion, I found out there was a separate app called slicer for fusion360. I watched this tutorial and saw that it was simple to use.
I exported my file as an stl from fusion, then brought it in to Slicer.
This is the menu to set material size. Since our lasercutter and material were large compared to the project I was doing, the main setting that mattered here was the material thickness.
I had to make adjustments for the slices to look right.
Then , after clicking on get plans I am brought to this screen, where I can export the slices as a dxf.
I then brought the dxf into illustrator to clean up any extra text that was on it. After doing this, it imported into the lasercut software easily, which is always a surprise.
Here are what some of the individual slices look like:
And here they are stacked:
Finally, I wanted to mill the frame out of nicer wood. I repeated the process for milling the first one described above, only I removed the part that previously covered the 3d printed casing, as it would now reveal wood so no need to put more wood over it. I still extrude the entire bottom by a fraction of a millimeter, to give it room to maneuver in the CNC.
Here is the new frame, much cleaner:
And here is the frame and stack of slices all glued together, with a bit of wood stain added:
Finally, I made the back of the case in the lasercut software for what I thought was a test run, and forgot to take a picture in the software. But I used one of the templates from the slicer file with a bit of editing, described here:
I then used small screws to attach this plate to the rest of the body, but also placed screws at the center, which I connected touch pins by soldering wires to the touch pin pads, then securing the other end to the screws with a nut:
This is my final interior electronics setup:
The battery ended up being very tempermental, and the cords to it could not be bent at all. Because of this, I ended up having to glue a few extra laser cut slices to the stack to give everything more room, and also had to use the flat wires to connect to the battery, pictured in the above setup, instead of connecting it directly to the board.
Programming¶
As the first order of importance, I wanted my board to be able to work with OTA programming and deep sleep mode. First, I did some research into deep sleep.
Deep Sleep¶
I found this tutorial very useful for getting a handle on the ESP32 deep sleep feature, especially using it alongside touch pins.
#define TOUCH_THRESHOLD 40
void callback(){
}
void setup(){
Serial.begin(9600);
Serial.println("ESP32 has started");
// Setup interrupt on Touch Pad 0 (GPIO4)
touchAttachInterrupt(T3, callback, TOUCH_THRESHOLD);
//Configure Touchpad as wakeup source
esp_sleep_enable_touchpad_wakeup();
Serial.println("Going to deepsleep");
delay(1000);
esp_deep_sleep_start();
}
void loop(){
//This will never be reached
}
The function touchAttachInterrupt tells the ESP32 to listen to a certain touchPin, and takes 3 parameters - the first is the touchpin that will be used. In this example, I am using ‘T3’ or touch pin 3, which corresponds to GPIO15. The second parameter asks for the name of a function that will be called if the pin is touched. The third parameter establishes how sensitive the touch pin is.
This example sketch worked on the first attempt. Here is a picture of the Serial monitor readout:
Seeing how easy this was, I decided to incorporate the e-ink image display sketch that I used in Output Devices week with the touch pins to create a slideshow of images. One pin would scroll through images, while another pin would put the board to sleep if touched.
I set up TouchAttachinterrupts for two different pins on the board. I created corresponding booleans for each pin, touch1detected and touch2detected. When a pin is touched, it would set the corresponding callback function to true:
int threshold = 40;
bool touch1detected = false;
bool touch2detected = false;
void gotTouch1(){
touch1detected = true;
}
void gotTouch2(){
touch2detected = true;
}
int place=0;
void setup() {
// put your setup code here, to run once:
// setup the display
Serial.begin(115200);
display.init(115200);
delay(1000);
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
display.update();
delay(1000);
touchAttachInterrupt(T3, gotTouch1, threshold);
touchAttachInterrupt(T2, gotTouch2, threshold);
esp_sleep_enable_touchpad_wakeup();
}
I defined a ‘place’ variable to act as a counter, which would determine which image in the slideshow the screen should display. If the touch1detected boolean becomes true, it will advance the place variable by one, then enter a switch/case statement in which he case variable determines what the board should do. Within each case, I have a command to display a different image, then reset touch1detected to false:
void loop() {
if(touch1detected){
place=place+1;
switch (place) {
case 1:
Serial.println("WHALE");
display.setRotation(3);
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, OLDE, 296, 128, GxEPD_WHITE);
display.update();
delay (2000);
touch1detected = false;
break;
case 2:
Serial.println("WHALE");
display.setRotation(3);
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, WHALE, 296, 128, GxEPD_WHITE);
display.update();
delay (2000);
touch1detected = false;
break;
case 3:
Serial.println("DESERT");
display.setRotation(3);
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, CAPTAIN, 296, 128, GxEPD_WHITE);
display.update();
delay (2000);
touch1detected = false;
break;
case 4:
Serial.println("DESERT");
display.setRotation(3);
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, DESERT, 296, 128, GxEPD_WHITE);
display.update();
delay (2000);
touch1detected = false;
break;
case 5:
Serial.println("DESERT");
display.setRotation(3);
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, FAMILY, 296, 128, GxEPD_WHITE);
display.update();
delay (2000);
touch1detected = false;
break;
case 6:
place=0;
touch1detected = false;
break;
}
}
Finally, I added an ‘else if’ which listens to see if touch2detected becomes true. If so, this enters the board into deep sleep mode:
else if (touch2detected){
Serial.println("Going to deepsleep");
esp_deep_sleep_start();
}
Placing this line:
esp_sleep_enable_touchpad_wakeup();
in the setup allows for any of the touch pins to wake the board up. When this happens, it will reset entirely. The user can then scroll to the image or program that they want to leave the board on, and again put it into deep sleep.
This program was also relatively easy to get running successfully. Here is the serial readout to show how it was working:
OTA programming¶
Next, I wanted to place all of this inside of some code that would allow the board to be programmed remotely. This was another feature of the ESP32 that I wanted to take advantage of, as low power consumption + OTA programming, would make it unnecessary to open the display casing very often, and iit would only be necessary to do so to change the battery. In the networking week, I liked controlling the ESP32 off of a webserver run from the board. I wanted to do something like this to allow the board to be reprogrammed.
I found this tutorial for OTA programming using the board’s IP address. I copied this bit of the code to prepare the board for wifi and added it to the beginning of my code:
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
const char* host = "esp32";
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
WebServer server(80);
const char* serverIndex =
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";
I then took the part of the code which establishes a connection to the server, which was placed in the setup in the tutorial, and added it to a new position in my case statement. I additionally added a message to display to the e-ink that it was starting to connect, and would add a delay before it actually did so. As connecting to wifi consumes more power, I wanted to give the user the option to scroll past this before it started:
case 6:
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
// load a font - in the library
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(0, 0);
display.println();
display.println("Preparing to connect to update server..." );
display.update();
delay(8000)
display.println("Connecting." );
display.update();
// Connect to WiFi network
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/*use mdns for host name resolution*/
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
server.begin();
}
server.handleClient();
delay(10000);
touch1detected = false;
break;
}
At first, I added a delay of 10 seconds after the server.handleClient()
command, but this did not give adequate time even to connect to the server. So i changed this to 30 and uploaded again. Now, I could connect to the server! everything was working. However, I realized this still would not be enough time to upload a sketch. Instead of a delay, I put the server.handleClient in a while (true) loop. I thought that I would still be able to break out of this by using the touch pin I assigned to scrolling through the case statement.
I ran the code again, but realized that once I entered the handleClient loop, I could not break out of it! So to make the touch pin work to break from the wifi connection and restart the slideshow, I changed the code like this:
touch1detected = false;
while (true) {
server.handleClient();
if (touch1detected){
break;
}
}
touch1detected = false;
break;
To program over the air, grab the IP address of the board from the Serial monitor, as displayed in the picture from the readout above.
Visit this in a browser from the same network that the ESP is connected to, and you will see this page:
After entering the username and password that you set, you will be brought to this page:
Where you can upload the compiled bin.
In order to upload sketches over the webserver, they must be exported as compiled binaries. This can be done in Arduino, by clicking Sketch > Export as compiled binary. The .bin file will then appear in the sketch’s folder in the Arduino library. I tested this by OTA uploading a different sketch with the same format, only one of the images in the slideshow changed out, and it works well. Just always remember to include the OTA code in the program, or it will lose this ability.
What I Learned¶
The meain thing that I learned from the final project is the importance of spiral development. It is important to have a fully assembled prototype working at each stage of production. I assumed that because I had the board, the display, and the battery connected and functioning, as well as the case designed, that I had a working prototype. When i finally returned to this stage after giving up on the accelerometer, however, I learned that it would still take me a week from here to design something that actually worked! This is because the cables were more sensitive than i imagined, and a case that was too tight deactivated the device.
That being said, power management, in general, is something that I would like to have better knowledge of. I found a battery that fit my power requirements, but still do not know much about them. Furthermore, I wish i had more time to experiment with different ways to integrate the battery into the board design that are more elegant than connecting to the ftdi connection. Even better, I would have liked to add microusb rechargeable battery, so that the case does not have to be opened in order to recharge the battery. I would have liked to dedicate more time to thisrather than the accelerometer.
Additionally, I feel like cable management is another topic unto itself that I did not get to study in isolation. I want to know the best way to minimize cables, secure them to the board in a clean fashion, and have them not be so sensitive that being in a very slim design affects them.
Finally, I would have liked to spend more time onm programming. I was able to get some basic features in, as well as over the air programming and deep sleep, but a more intuitive user interface, or interface on the computer through which one could upload images/change the slideshow, would have been great.
I think if I had attempted to fully assemble at the stage I was at before working on the accelerometer, I could have organized my final weeks better and spent more time on power management, cables, and programming.
I also learned the lesson I learned every week, and in all of fabacademy, which is that everything in digital fabrication takes so much longer than it seems like it will.
While it still feels a bit like I produced a more limited version of what I wanted to make, I appreciate the fact that I would have had absolutely no ability to even begin to think of how to do this before fabacademy. I am now confident that I could figure out how to build simple electronics, like an alarm clock, “smart” displays, automatic lamps, etc. —things that were always a black box to me before. Fabacademy moves so quickly through so many topics that, although we do not have a deep knowledge of any single subject by the end, when it is over I felt like I now had the ability to learn anything — no subject seems as impenetrable anymore.
Files¶
You can download my final sketch with images formatted for e-ink, and all other project files here:
Slide and Video¶
Previous Tracking Documentation¶
From Output Devices Week¶
Connecting display to NodeMCU¶
This was unnecessarily difficult and took up way too much time. A large part of this was due to the fact that the 1.54 inch e-paper display that Henk ordered was not working simply because I needed to disconnect and reconnect the ribbon cable attached to the driver—it must have been connected incorrectly. So a lot of troubleshooting on the programming/electronics side for nothing!
When I finally did try connecting the 2.9inch display and realizing the 1.54 inch display itself had been the problem, I then ran into further issues, as the board was very inconsistent in responding to programming and I thought I might be having issues with the NodeMCU. It turns out this was a good issue to have before designing the board, as I learned that the problem was that I could not have the display connected to any of the board’s UART pins while programming it.
First, I looked for Waveshare E-ink and ESP8266 setup examples online, which all referenced the GxEPD libraries. The arduino libraries designed for the Waveshare displays are the GxEPD and GxEPD2 libraries, which can be found here on github or in the Arduino library manager.
The example sketches from these libraries work by having a long list of the different waveshare e-ink displays as instances of the display class, all commented out at the beginning. You can uncomment the display you are working with for the code to work. Additionally, they offer a list of suggestions for connecting to different development boards at the beginning. For the ESP8266, they suggest:
// mapping suggestion from Waveshare SPI e-Paper to generic ESP8266
// BUSY -> GPIO4, RST -> GPIO2, DC -> GPIO0, CS -> GPIO15, CLK -> GPIO14, DIN -> GPIO13, GND -> GND, 3.3V -> 3.3V
I followed this suggestion for connection, uncommented the 1.54” display I was working with, and attempted to compile and upload to the NodeMCU. I kept running into the error that the board did not exist or was not connected. This was frustrating, as I would see a light blink on the board when I tried to upload, so I knew some communication was happening. I tried to upload Blink, and this didn’t work either. I then looked up the issue in a forum, and some people suggested that I go into the Board Manager and install an earlier version of the NodeMCU driver instead of the latest one. This also didn’t work.
I found out about the esptool.py command line interface, attempted to use this to delete flash on the board, as I thought maybe working outside of Arduino would offer some help. I downloaded the software using
pip3 install esptool
and attempted to use delete flash with
esptool.py erase_flash
which automatically scans for esp boards on each port and erases the flash memory when it finds one. The port for the ESP, named /cu.SLAB_USBtoUART would give the following output when the software checked on it:
/dev/cu.SLAB_USBtoUART failed to connect: [Errno 16] could not open port /dev/cu.SLAB_USBtoUART: [Errno 16] Resource busy: '/dev/cu.SLAB_USBtoUART'
I finally thought to disconnect the display, something I had been resisting as it required 8 pin connections so was a bit of a hassle to disconnect and reconnect. When I did this, I ran erase-flash again and it worked!
I went back to Arduino, compiled the example sketch, and uploaded it, and this also worked!
I plugged the display in and…nothing. I tried resetting the ESP, disconnecting and reconnecting again to double check my connections, still nothing. I moved it to a breadboard so the connections could stay in place if I picked up the board. I still was having no luck, so i switched to the 2.9 inch display and an image instantly appeared!
Good news. I changed the example to work for the 2.9 inch display, and again had trouble with the board with the same upload error. I disconnected the display, and it was able to upload. I was very excited to have the display finally working, but I needed to figure out why I couldn’t have the board connected and upload at the same time, as this would be a big obstacle in my final project if this was something I could not fix.
I looked up the issue, and saw a discussion of it happening with Arduinos when the Tx/Rx pins are used in a sketch, and it recommended to avoid using them. I tried plugging in the pins on the ESP one at a time until the sketch failed, to try to get a sense of which one prevented upload. I figured out it was D8, which was connected to the clock pin on the display. When I looked at the ESP8266 data, this made perfect sense. This was one of the UART communication pins. Of course, as i was connected through a UART converter, I should avoid these lines.
I connected to the clock pin on the other side of the board, which was not listed as a UART pin, and it solved the problem. I was able to upload and be connected to the display at once. Huge relief, and many hours gone, but at least I could be grateful I did not design a board with those same connections as listed in the example.
After this realization, I started to do some general web searches for connecting the e-ink displays to the ESP32, as this was the microcontroller I wanted to design a board for with the waveshare display. I found that waveshare already makes an ESP32 driver for the e-ink displays, which is essentially what I would be making. However, in the pictures it showed the ribbon cable connected to the driver, and I got to thinking that I had not checked if this was ok on the 1.54” display. I disconnected and reconnected the cable, and this display could now run with the upload sketch too! I felt stupid that it was such a simple fix, but I was glad to now have both displays working.
Customize the Display¶
On the GitHub page for the display libraries, he describes how the GxEPD libraries are a subclass of the Adafruit GFX libraries, so I look into the Adafruit documentation for information on ways I can print to the screen.
I tried using the GxEPD example code, but found customizing this difficult, as each part of the example display was called as its own method, and the code contains different commands for different boards and screen sizes. I instead looked around for a post going over how to start from nothing and simply print text or a single image to the screen. I found this website.
void setup() {
// setup the display
display.init();
// colours are good.
display.fillScreen(GxEPD_WHITE);
display.setTextColor(GxEPD_BLACK);
// load a font - in the library
display.setFont(&FreeMonoBold9pt7b);
// let the strings begin
display.setCursor(0, 0);
display.println();
display.println("Hello. My name is Inigo Montoya. You killed my father. Prepare to die." );
display.println();
display.println("This is another line!" );
display.update();
}
This is the example code for printing text to a waveshare e-ink display from the website. It did not have any calls to include or define at the top, so I tried adding only #include
#include <GxFont_GFX.h>
#include <GxEPD.h>
#include <GxGDEP015OC1/GxGDEP015OC1.h>
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#include <Fonts/FreeMonoBold9pt7b.h>
GxIO_Class io(SPI, /*CS=D8*/ SS, /*DC=D3*/ 0, /*RST=D4*/ 2); // arbitrary selection of D3(=0), D4(=2), selected for default of GxEPD_Class
GxEPD_Class display(io, /*RST=D4*/ 2, /*BUSY=D2*/ 4); // default selection of D4(=2), D2(=4)
I still do not completely understand what all of these are doing, but including them made the code work!
Now, I wanted to test getting images running on the display. The same tutorial from above also included basic code for this, which was to include a byte array:
const unsigned char gImage_IMG_0001[] = {
0xff, 0xff, 0xfb, 0xff, 0xff, 0xfe, 0x00, 0x08, 0x80, 0x08, 0x4a, 0x4c, 0x65, 0x2a, 0xf,
...
};
Then add these lines in the program:
display.fillScreen(GxEPD_BLACK);
display.drawBitmap(0, 0, gImage_IMG_0001, 200, 200, GxEPD_WHITE);
display.update();
I tried to just copy and paste one of the bitmap arrays from the example code, but this did not work and produced this:
I then made my own image with photoshop, using only black and white pixels, and made it exactly the resolution of the screen, 200x200. I used several online image to c array converters, and all of them produced the same hazy display. Finally, running the file through this converter produced a code that worked.
I had made this image using the threshold effect in photoshop, but knew I could get a more photo-like result, so i changed it by first choosing Image > Grayscale, then Image > Bitmap. Once you click on bitmap, it will give a menu for different ways of creating the bitmap (halftone, threshole, etc). I then ran the new bitmap I made through the same converter as above, and produced this:
I then combined the image and text code, and also had them alternate.
OTA Programming¶
This ended up being the easiest part. I looked at several tutorials online for ota programming. If you have python installed, there should be an ‘Arduino OTA’ example code from the arduino File > Examples menu.
#ifndef STASSID
#define STASSID "......"
#define STAPSK "......"
#endif
Substitute your wireless network and passcode for these two strings and upload the code to the ESP. Then, open the serial monitor. Hit reset on the ESP. The IP Address of the ESP should appear in the serial monitor if the program ran successfully. Now, when you go to Tools > Port, the IP Address should appear as an option. To put your own program on the ESP and maintain OTA programming capabilities, you simply need to add your sketch into the OTA example sketch. I copied the definitions and setup from the e-ink customization sketch, and added them into the OTA sketch, changing the text printout so I would be able to know if it successfully sent a new program. I unplugged the ESP and plugged it into a powerbank. I uploaded the new code using the OTA port and it worked!
The only problem I ran into here was inserting my own code into the OTA sketch in the wrong place. There are several loops in the setup, and I accidentally put part of my code inside of one, which prevented it from printing. This had me stuck for at least an hour and was a silly mistake.
Final Prices
Component | Price |
---|---|
ESP32 | $3.80 |
Waveshare E-Ink display | $28.95 |
Li-Po 3.7v 600ma rechargeable battery | $7 |
Switch | $.33 |
3.3v Regulator | $1.16 |
SMD Capacitor .1uf | .12 |
SMD Capacitor 1uf | .07 |
SMD Capacitor 10uf | .18 |
10k Resistor | .01 |
3D printed casing | ? |
Total: 41.62 each! (give or take a bit for 3d printing, milling, and laser cutting)
Week 1¶
I entered the FabAcademy without a clear idea of what I want to do for a final project. After browsing through final projects from previous years, Andrew Sleigh’s final video caught my attention.
I was intrigued by the use of media cards and photo-interrup switches.
My first thought is to build a frame around a monitor. Photo-Interrupt switches, or a similar mechanism, would be embedded in the base of the frame. Different laser-cut shapes could be placed in the frame, and these shapes would create a ‘foreground.’ Each different shape, when placed in the frame, would then trigger a different ‘background’ to be displayed on the monitor. A simple sketch is below:
The text below the shapes describes that they would have some sort of key, through which they connect to the frame, that also creates a signal to change the display.
The other text says “monitor display changes according to which shape is connected to the frame”
I want to use more complicated images and shapes, but used obvious environments for the sketch to make the idea clear. As I spend a lot of time manipulating images in photoshop, I am interested in the idea of building an image with a combination of the digital display and physical elements.
At this point, I have no clue how to build something like this, but hope to figure it out over the coming months.
Week 2 Update¶
I remembered that a few months ago I saw some sculptures by the artist Alex Da Corte and wanted to know how they were made. They were images sourced from cartoons that he made into 3D wall works. I am not aware of what process he used, but it looked like the kind of thing 3d fabrication could help with.
While I don’t have a clear idea of what my final project will do, I want to make a visual object that builds on the frame idea. Instead of building a frame, however, I hope to build something like one of these and make a part of the object vary, either with a moving part or integrated display that responds to some input. I think the initial challenge for my project will be deciding on the image I want to make, and then how I plan to enhance it. For this week, I sketched a castle, then turned it into a sculpture in fusion 360and animated the door. I left an area for electronics in the back that could connect to different areas of the object.
Applications and Implications¶
What will it do?¶
I want to create a system of screens that can be embedded within a printed photograph in order to animate parts of the image. I want to be able to control these screens both as a group and independently, all from within the same app. I will use screens of varying type and size. E-ink screens are my first priority, and I will therefore begin with 2 small e-ink screens, one 1.54 in and the other 2.9 in. Once I have these working within the system, I will additionally integrate an LCD screen, and possibly more from there. I hope to make the system flexible, so that screens may be added and removed. I will then make at least two different applications for these, like the following examples:
Here, E-ink displays appear behind signs in the image, and an lcd screen appears as part of the dashboard. In this application, the screens could be controlled independently.
Here, the e-ink displays appear as speech text in the comics. Here it would be ideal if the text could all be controlled to change at once, or appear in a synchronized fashion, where it is all being controlled at once.
My hope is that this system will then be easy to use in other applications- the display can be framed and used as wall art, attached to a bulletin board to display messages, used as a clock, or incorporated into a larger drawing. I want to make casing, programming, and controllers that can be reproduced easily, so more displays of the same kind can be integrated into the display system when needed.
Who’s done what beforehand?¶
Here is a link to creating a controller for a single e-paper display
In a later week, the same student controlled that display remotely.
Here is a link to sending text to a display remotely
What will you design?¶
-housing for each individual display, that will contain the display, its controller, and a power source. I want the front of the housing to be flush with the screen, so that the displays can be on the same plane as the printed photograph, or other image, that they are embedded within. These should additionally be as thin as possible, so that they can rest behind a picture frame without making it noticeably protrude from the wall
-controllers for each display that can connect to the raspberry pi for programming, but which can also run and be powered independently once programmed
What materials and components will be used?¶
Raspberry Pi as MQTT Broker
E-Ink displays
LCD display
Iphone or computer for app control
Processors for each display, potentially ESP32/8266, ATSamD
Where will come from?¶
Bits and parts is what we use to order at Waag and will have the necessary components.
Wavesharehas additional, larger e-ink displays if I want to expand to larger screens beyond the ones available from bits and parts.
How much will they cost?¶
Each display unit, excluding the central computer, is estimated to be in the $40 range
Raspberry pi is 40 euros and will be the most expensive part
If I order 4.3 inch displays from waveshare, these will be $30 each
Henk ordered the smaller e-ink displays that I will start with, which are also around $30 each.
Further components TBD
What parts and systems will be made?¶
3D printed housing for each display
PCB board for each display
One larger picture frame, to demonstrate embedding within a photo
One smaller picture frame, to demonstrate use as clock/comic display
What processes will be used?¶
3D printing for the housing
CNC milling for the larger wood frames
PCB milling/electronics design
What questions need to be answered?¶
-How will I design the PCB boards for each display and how will they communicate with the larger system (wifi enabled, or wired connection to raspberry pi)
-How will I mount the photos and disguise the separation between the image and displays as much as possible?
-Can the display units be powered independently
How will it be evaluated?¶
Can the displays be shown to work as a single system (for example, as a clock display, or to display a narrative that changes in order, like with comics)?
Can they be changed individually?
Can the E-Ink displays be powered once the pi is removed?
Is there an easy way to control the displays variably (like through an app)?
Interface¶
I want to make it easy to interface with multiple displays at once, and want to do this through Node-Red. I will, however, have to create some python programs as nodes. I think I will primarily need two programs
- A program which takes an image or text as input and outputs a .ino file that displays that image or text on a specified e-ink display
- A program which converts images into byte arrays for arduino files, and makes these the correct dimensions for a specified e-ink display
Arduino CLI¶
I wanted to create a python program that could write/compile/upload arduino sketches for the boards I would make, so that what appeared on the OLED and e-ink screens I used could vary a lot- text, animations, slideshows, individual images, charts, etc.
After doing some research, it seemed that doing this through the Arduino command line interface might be easy, as this way I could easily integrate with the libraries for devices that are already in the Arduino IDE. Additionally, you can compile in a single line, which will be very useful for the interface I want to make:
arduino-cli compile -b arduino:avr:uno /home/user/Arduino/MySketch
arduino-cli upload -b arduino:avr:uno -p /dev/cu.usbmodem...
arduino-cli compile --upload
-
Navigate to the sketch folder youy want to use in terminal, use the command $ arduino-cli boards list. This will produce the following readout:
-
From here, copy the /dev/cu. address of the port to which the board you want to program is attached
-
Enter
arduino-cli board attach serial:///dev/cu.....
- After the CLI is attached to the correct board and within the sketch folder, simply run
arduino-cli compile --upload
I am in the process of writing a python program that automates this process with Python’s subprocess module and will update this page. The idea is that I will have processes that make this easy to do in an interface on the raspberry Pi, so that I can quickly change what is displayed on any connected display.
Board Design¶
The board I am working on for the final project will be something like the schematic below, with noted adjustments. I want the board to essentially be an ESP32 driver for E-Ink displays, but I also want it to have battery power and an SPI connection, rather than a direct connection for the ribbon cable.
New¶
https://randomnerdtutorials.com/esp32-esp8266-input-data-html-form/