summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.ccls232
-rw-r--r--.clangd251
-rw-r--r--.gitignore1
-rw-r--r--.oldds32rtc.cpp375
-rw-r--r--.oldds32rtc.h93
-rw-r--r--include/README39
-rw-r--r--lib/README46
-rw-r--r--platformio.ini30
-rw-r--r--src/DSEG7_Classic_Bold_25.h199
-rw-r--r--src/DSEG7_Classic_Regular_15.h199
-rw-r--r--src/DSEG7_Classic_Regular_39.h199
-rw-r--r--src/Seven_Segment10pt7b.h204
-rw-r--r--src/castRay.cpp20
-rw-r--r--src/castRay.h22
-rw-r--r--src/castRay.ino10
-rw-r--r--src/icons.h176
-rw-r--r--src/pixelfunc.cpp82
-rw-r--r--src/pixelfunc.h51
-rw-r--r--src/raycastlib.cpp1563
-rw-r--r--src/raycastlib.h504
-rw-r--r--src/settings.h28
-rw-r--r--test/README11
22 files changed, 4335 insertions, 0 deletions
diff --git a/.ccls b/.ccls
new file mode 100644
index 0000000..565b603
--- /dev/null
+++ b/.ccls
@@ -0,0 +1,232 @@
+clang
+
+%c -mlongcalls -Wno-frame-address -std=gnu99 -Wno-old-style-declaration -ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -Os -freorder-blocks -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -MMD
+%cpp -mlongcalls -Wno-frame-address -std=gnu++11 -fexceptions -fno-rtti -ffunction-sections -fdata-sections -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -ggdb -Os -freorder-blocks -Wwrite-strings -fstack-protector -fstrict-volatile-bitfields -Wno-error=unused-but-set-variable -fno-jump-tables -fno-tree-switch-conversion -MMD
+
+-I/home/salad/docs/projects/watchyfaces/caster/include
+-I/home/salad/docs/projects/watchyfaces/caster/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/config
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/newlib/platform_include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/esp_additions/freertos
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/port/xtensa/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freertos/include/esp_additions
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include/soc
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/include/soc/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hw_support/port/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/heap/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/log/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/include/apps
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/include/apps/sntp
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/lwip/src/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/port/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/lwip/port/esp32/include/arch
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/soc/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/soc/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/soc/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/hal/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/hal/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/hal/platform_port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rom/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rom/include/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rom/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_common/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_system/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_system/port/soc
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_system/port/public_compat
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/xtensa/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/xtensa/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/driver/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/driver/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_pm/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_ringbuf/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/efuse/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/efuse/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/vfs/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_wifi/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_event/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_netif/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_eth/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/tcpip_adapter/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_phy/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_phy/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_ipc/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/app_trace/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_timer/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mbedtls/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mbedtls/mbedtls/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mbedtls/esp_crt_bundle/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/app_update/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/spi_flash/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bootloader_support/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nvs_flash/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/pthread/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_gdbstub/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_gdbstub/xtensa
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_gdbstub/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/espcoredump/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/espcoredump/include/port/xtensa
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wpa_supplicant/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wpa_supplicant/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wpa_supplicant/esp_supplicant/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/ieee802154/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/console
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/asio/asio/asio/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/asio/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/osi/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/include/esp32/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/api/include/api
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/btc/profile/esp/blufi/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/common/btc/profile/esp/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/bt/host/bluedroid/api/include/api
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/cbor/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/unity/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/unity/unity/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/cmock/CMock/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/coap/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/coap/libcoap/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/nghttp/nghttp2/lib/includes
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-tls
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-tls/esp-tls-crypto
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_adc_cal/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_hid/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/tcp_transport/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_http_client/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_http_server/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_https_ota/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_lcd/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_lcd/interface
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protobuf-c/protobuf-c
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protocomm/include/common
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protocomm/include/security
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/protocomm/include/transports
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mdns/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_local_ctrl/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/sdmmc/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_serial_slave_link/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_websocket_client/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/expat/expat/expat/lib
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/expat/port/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wear_levelling/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fatfs/diskio
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fatfs/vfs
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fatfs/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/freemodbus/common/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/idf_test/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/idf_test/include/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/jsmn/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json/cJSON
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/libsodium/libsodium/src/libsodium/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/libsodium/port_include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/mqtt/esp-mqtt/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/openssl/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/perfmon/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/spiffs/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/ulp/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/wifi_provisioning/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/button/button/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json_parser
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json_parser/jsmn/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/json_generator
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_schedule/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_rainmaker/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/qrcode/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/ws2812_led
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_littlefs/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp_littlefs/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/dotprod/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/support/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/hann/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman_harris/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/blackman_nuttall/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/nuttall/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/windows/flat_top/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/iir/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/fir/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/add/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/sub/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/mul/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/addc/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/mulc/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/math/sqrt/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/matrix/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/fft/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/dct/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/conv/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/common/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/kalman/ekf/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-dsp/modules/kalman/ekf_imu13states/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/tool
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/typedef
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/image
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/math
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/nn
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/layer
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/detect
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp-face/include/model_zoo
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp32-camera/driver/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/esp32-camera/conversions/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/tools/sdk/esp32/include/fb_gfx/include
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/cores/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/variants/esp32
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/ArduinoOTA/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/AsyncUDP/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/BLE/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/BluetoothSerial/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/DNSServer/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/EEPROM/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/ESP32/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/ESPmDNS/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/Ethernet/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/FFat/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/FS/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/HTTPClient/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdate/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/HTTPUpdateServer/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/LittleFS/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/NetBIOS/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/Preferences/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/RainMaker/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/SD/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/SD_MMC/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/SPI/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/SPIFFS/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/SimpleBLE/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/Ticker/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/USB/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/Update/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/WebServer/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/WiFi/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/WiFiClientSecure/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/WiFiProv/src
+-I/home/salad/.platformio/packages/framework-arduinoespressif32/libraries/Wire/src
+-I/home/salad/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0
+-I/home/salad/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include/c++/8.4.0/xtensa-esp32-elf
+-I/home/salad/.platformio/packages/toolchain-xtensa-esp32/lib/gcc/xtensa-esp32-elf/8.4.0/include-fixed
+-I/home/salad/.platformio/packages/toolchain-xtensa-esp32/lib/gcc/xtensa-esp32-elf/8.4.0/include
+-I/home/salad/.platformio/packages/toolchain-xtensa-esp32/xtensa-esp32-elf/include
+
+-DPLATFORMIO=50205
+-DARDUINO_ESP32_DEV
+-DHAVE_CONFIG_H
+-DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h"
+-DUNITY_INCLUDE_CONFIG_H
+-DWITH_POSIX
+-D_GNU_SOURCE
+-DIDF_VER="v4.4-beta1-189-ga79dc75f0a"
+-DESP_PLATFORM
+-D_POSIX_READER_WRITER_LOCKS
+-DARDUINO_ARCH_ESP32
+-DESP32
+-DF_CPU=240000000L
+-DARDUINO=10812
+-DARDUINO_VARIANT="esp32"
+-DARDUINO_BOARD="Espressif ESP32 Dev Module"
+-DARDUINO_PARTITION_default
diff --git a/.clangd b/.clangd
new file mode 100644
index 0000000..72fe464
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,251 @@
+CompileFlags: # Tweak the parse settings
+ Add:
+ - "-I=./.oldds32rtc.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SD_Example/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SD_Example/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SD_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/GxEPD2_display_selection.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/BitmapDisplay.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/TextDisplay.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_GFX_Example/GxEPD2_display_selection_added.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Spiffs_Example/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Spiffs_Example/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Spiffs_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SerialFlash_Example/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SerialFlash_Example/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SerialFlash_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_PagedDisplayUsingCallback/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_U8G2_Fonts_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_HelloWorld/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_HelloWorld/GxEPD2_display_selection.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_HelloWorld/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_HelloWorld/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_HelloWorld/GxEPD2_display_selection_added.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_NotPagedExample/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_NotPagedExample/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_NotPagedExample/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_WiFi_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_MinimumExample/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_MinimumExample/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_MinimumExample/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_RotaryUsingBusyCallback/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_RotaryUsingBusyCallback/BasicEncoder.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SD_AVR_Example/GxEPD2_SD_AVR_boards_added.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_SD_AVR_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Example/GxEPD2_selection_check.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Example/GxEPD2_display_selection.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Example/GxEPD2_display_selection_new_style.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Example/GxEPD2_wiring_examples.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/examples/GxEPD2_Example/GxEPD2_display_selection_added.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/GxEPD2_7C.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/GxEPD2_BW.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/it8951/GxEPD2_it78_1872x1404.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/it8951/GxEPD2_it60.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/it8951/GxEPD2_it60_1448x1072.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/GxEPD2.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/GxEPD2_3C.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_154_D67.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_270.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_154_M10.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_1248.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_420.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213_B72.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_420_M01.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_154.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213_B74.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_583_T8.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290_M06.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_370_TC1.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213_M21.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_102.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290_T94_V2.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_750.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290_T5.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213_T5D.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290_T5D.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_154_M09.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290_T94.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_583.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213_flex.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213_B73.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_260_M01.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_371.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_750_T7.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_154_T8.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_260.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_213.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_290_I6FD.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd/GxEPD2_1160_T91.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/GxEPD2_GFX.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps640x384.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps400x300.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c200x200.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps176x264.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps80x128.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c176x264.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c800x480.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c400x300.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps80x128.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps800x480.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps200x200.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps152x296.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps3c200x200.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps7c192x143.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c128x250.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps152x152.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps3c128x296.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c104x212.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps648x480.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps3c400x300.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps128x296.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c128x296.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps176x264.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps104x212.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps104x212.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps3c880x528.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps1304x984.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps3c104x212.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps240x416.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/WS_Bitmaps800x600.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/bitmaps/Bitmaps128x250.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/GxEPD2_EPD.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_270c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_154c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_583c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_154_Z90c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_290c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_290_C90c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_420c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_213c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_213_Z98c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_750c_Z90.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_213_Z19c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_750c_Z08.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_750c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_565c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_290_Z13c.h"
+ - "-I=./.pio/libdeps/esp32dev/GxEPD2/src/epd3c/GxEPD2_420c_Z21.h"
+ - "-I=./.pio/libdeps/esp32dev/WiFiManager@0.16.0/extras/template.h"
+ - "-I=./.pio/libdeps/esp32dev/WiFiManager@0.16.0/WiFiManager.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/icons.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/DSEG7_Classic_Regular_15.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/DSEG7_Classic_Regular_39.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/Watchy_7_SEG.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/DSEG7_Classic_Bold_25.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/7_SEG/Seven_Segment10pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Basic/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Tetris/tetris.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Tetris/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Tetris/Watchy_Tetris.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/MacPaint/Watchy_MacPaint.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/MacPaint/macpaint.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/MacPaint/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/DOS/Watchy_DOS.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/DOS/Px437_IBM_BIOS5pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/DOS/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Pokemon/pokemon.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Pokemon/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/Pokemon/Watchy_Pokemon.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/StarryHorizon/stars.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/StarryHorizon/MadeSunflower39pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/examples/WatchFaces/StarryHorizon/settings.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/config.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/bma.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/WatchyRTC.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/BLE.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/DSEG7_Classic_Bold_53.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/Watchy.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/bma4_defs.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/bma423.h"
+ - "-I=./.pio/libdeps/esp32dev/Watchy/src/bma4.h"
+ - "-I=./.pio/libdeps/esp32dev/Arduino_JSON/src/JSON.h"
+ - "-I=./.pio/libdeps/esp32dev/Arduino_JSON/src/Arduino_JSON.h"
+ - "-I=./.pio/libdeps/esp32dev/Arduino_JSON/src/JSONVar.h"
+ - "-I=./.pio/libdeps/esp32dev/Arduino_JSON/src/cjson/cJSON.h"
+ - "-I=./.pio/libdeps/esp32dev/Time/TimeLib.h"
+ - "-I=./.pio/libdeps/esp32dev/WiFiManager/extras/template.h"
+ - "-I=./.pio/libdeps/esp32dev/WiFiManager/strings_en.h"
+ - "-I=./.pio/libdeps/esp32dev/WiFiManager/WiFiManager.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit BusIO/Adafruit_I2CRegister.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit BusIO/Adafruit_I2CDevice.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit BusIO/Adafruit_SPIDevice.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit BusIO/Adafruit_BusIO_Register.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/examples/GFXcanvas/GFXcanvasSerialDemo.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Adafruit_GrayOLED.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Adafruit_GFX.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBoldOblique12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBold18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBoldItalic9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBold24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoOblique24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/Org_01.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansOblique18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBoldItalic18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSans9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoOblique12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBold12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBoldItalic12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBold18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerif12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBold18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBold24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifItalic9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifItalic12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBold9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansOblique12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMono9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBoldOblique24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoOblique9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBoldOblique12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBoldOblique18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/Picopixel.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSans12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBoldOblique24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMono24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBold24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBoldOblique9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/TomThumb.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifItalic18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansOblique24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerif9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSans18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMono18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerif24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansOblique9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBoldOblique9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/Tiny3x3a2pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSans24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerif18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBoldItalic24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoBold12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMono12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBold12pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBold9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSansBoldOblique18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeMonoOblique18pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifBold9pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Fonts/FreeSerifItalic24pt7b.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/gfxfont.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Adafruit_SPITFT.h"
+ - "-I=./.pio/libdeps/esp32dev/Adafruit GFX Library/Adafruit_SPITFT_Macros.h"
+ - "-I=./.pio/libdeps/esp32dev/DS3232RTC/src/DS3232RTC.h"
+ - "-I=./.pio/libdeps/esp32dev/NTPClient/NTPClient.h"
+ - "-I=./.pio/libdeps/esp32dev/Rtc_Pcf8563/Rtc_Pcf8563.h"
+ - "-I=./src/icons.h"
+ - "-I=./src/DSEG7_Classic_Regular_15.h"
+ - "-I=./src/DSEG7_Classic_Regular_39.h"
+ - "-I=./src/Watchy_7_SEG.h"
+ - "-I=./src/settings.h"
+ - "-I=./src/DSEG7_Classic_Bold_25.h"
+ - "-I=./src/Seven_Segment10pt7b.h"
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..03f4a3c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.pio
diff --git a/.oldds32rtc.cpp b/.oldds32rtc.cpp
new file mode 100644
index 0000000..0d519a9
--- /dev/null
+++ b/.oldds32rtc.cpp
@@ -0,0 +1,375 @@
+// Arduino DS3232RTC Library
+// https://github.com/JChristensen/DS3232RTC
+// Copyright (C) 2018 by Jack Christensen and licensed under
+// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
+//
+// Arduino library for the Maxim Integrated DS3232 and DS3231
+// Real-Time Clocks.
+// Requires PJRC's improved version of the Arduino Time Library,
+// https://playground.arduino.cc/Code/Time
+// https://github.com/PaulStoffregen/Time
+//
+// For AVR architecture, a DS3232RTC object named RTC is instantiated
+// by the library and I2C initialization occurs in the constructor;
+// this is for backwards compatibility.
+// For other architectures, the user needs to instantiate a DS3232RTC
+// object and optionally initialize the I2C bus by calling
+// DS3232RTC::begin(). The constructor has an optional bool parameter
+// to indicate whether I2C initialization should occur in the
+// constructor; this parameter defaults to true if not given.
+
+// define release-independent I2C functions
+#if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
+#include <TinyWireM.h>
+#define i2cBegin TinyWireM.begin
+#define i2cBeginTransmission TinyWireM.beginTransmission
+#define i2cEndTransmission TinyWireM.endTransmission
+#define i2cRequestFrom TinyWireM.requestFrom
+#define i2cRead TinyWireM.receive
+#define i2cWrite TinyWireM.send
+#elif ARDUINO >= 100
+#include <Wire.h>
+#define i2cBegin Wire.begin
+#define i2cBeginTransmission Wire.beginTransmission
+#define i2cEndTransmission Wire.endTransmission
+#define i2cRequestFrom Wire.requestFrom
+#define i2cRead Wire.read
+#define i2cWrite Wire.write
+#else
+#include <Wire.h>
+#define i2cBegin Wire.begin
+#define i2cBeginTransmission Wire.beginTransmission
+#define i2cEndTransmission Wire.endTransmission
+#define i2cRequestFrom Wire.requestFrom
+#define i2cRead Wire.receive
+#define i2cWrite Wire.send
+#endif
+
+#include <TimeLib.h> //https://github.com/PaulStoffregen/Time
+#include <DS3232RTC.h>
+
+// DS3232 I2C Address
+#define RTC_ADDR 0x68
+
+// DS3232 Register Addresses
+#define RTC_SECONDS 0x00
+#define RTC_MINUTES 0x01
+#define RTC_HOURS 0x02
+#define RTC_DAY 0x03
+#define RTC_DATE 0x04
+#define RTC_MONTH 0x05
+#define RTC_YEAR 0x06
+#define ALM1_SECONDS 0x07
+#define ALM1_MINUTES 0x08
+#define ALM1_HOURS 0x09
+#define ALM1_DAYDATE 0x0A
+#define ALM2_MINUTES 0x0B
+#define ALM2_HOURS 0x0C
+#define ALM2_DAYDATE 0x0D
+#define RTC_CONTROL 0x0E
+#define RTC_STATUS 0x0F
+#define RTC_AGING 0x10
+#define RTC_TEMP_MSB 0x11
+#define RTC_TEMP_LSB 0x12
+#define SRAM_START_ADDR 0x14 // first SRAM address
+#define SRAM_SIZE 236 // number of bytes of SRAM
+
+// Alarm mask bits
+#define A1M1 7
+#define A1M2 7
+#define A1M3 7
+#define A1M4 7
+#define A2M2 7
+#define A2M3 7
+#define A2M4 7
+
+// Control register bits
+#define EOSC 7
+#define BBSQW 6
+#define CONV 5
+#define RS2 4
+#define RS1 3
+#define INTCN 2
+#define A2IE 1
+#define A1IE 0
+
+// Status register bits
+#define OSF 7
+#define BB32KHZ 6
+#define CRATE1 5
+#define CRATE0 4
+#define EN32KHZ 3
+#define BSY 2
+#define A2F 1
+#define A1F 0
+
+// Other
+#define DS1307_CH 7 // for DS1307 compatibility, Clock Halt bit in Seconds register
+#define HR1224 6 // Hours register 12 or 24 hour mode (24 hour mode==0)
+#define CENTURY 7 // Century bit in Month register
+#define DYDT 6 // Day/Date flag bit in alarm Day/Date registers
+
+byte DS3232RTC::errCode; // for debug
+
+// Constructor. Initializes the I2C bus by default, but better
+// practice is to pass false in the constructor and call
+// the begin() function in the setup code.
+DS3232RTC::DS3232RTC(bool initI2C)
+{
+ if (initI2C) i2cBegin();
+}
+
+// Initialize the I2C bus.
+void DS3232RTC::begin()
+{
+ i2cBegin();
+}
+
+// Read the current time from the RTC and return it as a time_t
+// value. Returns a zero value if an I2C error occurred (e.g. RTC
+// not present).
+time_t DS3232RTC::get()
+{
+ tmElements_t tm;
+
+ if ( read(tm) ) return 0;
+ return( makeTime(tm) );
+}
+
+// Set the RTC to the given time_t value and clear the
+// oscillator stop flag (OSF) in the Control/Status register.
+// Returns the I2C status (zero if successful).
+byte DS3232RTC::set(time_t t)
+{
+ tmElements_t tm;
+
+ breakTime(t, tm);
+ return ( write(tm) );
+}
+
+// Read the current time from the RTC and return it in a tmElements_t
+// structure. Returns the I2C status (zero if successful).
+byte DS3232RTC::read(tmElements_t &tm)
+{
+ i2cBeginTransmission(RTC_ADDR);
+ i2cWrite((uint8_t)RTC_SECONDS);
+ if ( byte e = i2cEndTransmission() ) { errCode = e; return e; }
+ // request 7 bytes (secs, min, hr, dow, date, mth, yr)
+ i2cRequestFrom(RTC_ADDR, tmNbrFields);
+ tm.Second = bcd2dec(i2cRead() & ~_BV(DS1307_CH));
+ tm.Minute = bcd2dec(i2cRead());
+ tm.Hour = bcd2dec(i2cRead() & ~_BV(HR1224)); // assumes 24hr clock
+ tm.Wday = i2cRead();
+ tm.Day = bcd2dec(i2cRead());
+ tm.Month = bcd2dec(i2cRead() & ~_BV(CENTURY)); // don't use the Century bit
+ tm.Year = y2kYearToTm(bcd2dec(i2cRead()));
+ return 0;
+}
+
+// Set the RTC time from a tmElements_t structure and clear the
+// oscillator stop flag (OSF) in the Control/Status register.
+// Returns the I2C status (zero if successful).
+byte DS3232RTC::write(tmElements_t &tm)
+{
+ i2cBeginTransmission(RTC_ADDR);
+ i2cWrite((uint8_t)RTC_SECONDS);
+ i2cWrite(dec2bcd(tm.Second));
+ i2cWrite(dec2bcd(tm.Minute));
+ i2cWrite(dec2bcd(tm.Hour)); // sets 24 hour format (Bit 6 == 0)
+ i2cWrite(tm.Wday);
+ i2cWrite(dec2bcd(tm.Day));
+ i2cWrite(dec2bcd(tm.Month));
+ i2cWrite(dec2bcd(tmYearToY2k(tm.Year)));
+ byte ret = i2cEndTransmission();
+ uint8_t s = readRTC(RTC_STATUS); // read the status register
+ writeRTC( RTC_STATUS, s & ~_BV(OSF) ); // clear the Oscillator Stop Flag
+ return ret;
+}
+
+// Write multiple bytes to RTC RAM.
+// Valid address range is 0x00 - 0xFF, no checking.
+// Number of bytes (nBytes) must be between 1 and 31 (Wire library
+// limitation).
+// Returns the I2C status (zero if successful).
+byte DS3232RTC::writeRTC(byte addr, byte *values, byte nBytes)
+{
+ i2cBeginTransmission(RTC_ADDR);
+ i2cWrite(addr);
+ for (byte i=0; i<nBytes; i++) i2cWrite(values[i]);
+ return i2cEndTransmission();
+}
+
+// Write a single byte to RTC RAM.
+// Valid address range is 0x00 - 0xFF, no checking.
+// Returns the I2C status (zero if successful).
+byte DS3232RTC::writeRTC(byte addr, byte value)
+{
+ return ( writeRTC(addr, &value, 1) );
+}
+
+// Read multiple bytes from RTC RAM.
+// Valid address range is 0x00 - 0xFF, no checking.
+// Number of bytes (nBytes) must be between 1 and 32 (Wire library
+// limitation).
+// Returns the I2C status (zero if successful).
+byte DS3232RTC::readRTC(byte addr, byte *values, byte nBytes)
+{
+ i2cBeginTransmission(RTC_ADDR);
+ i2cWrite(addr);
+ if ( byte e = i2cEndTransmission() ) return e;
+ i2cRequestFrom( (uint8_t)RTC_ADDR, nBytes );
+ for (byte i=0; i<nBytes; i++) values[i] = i2cRead();
+ return 0;
+}
+
+// Read a single byte from RTC RAM.
+// Valid address range is 0x00 - 0xFF, no checking.
+byte DS3232RTC::readRTC(byte addr)
+{
+ byte b;
+
+ readRTC(addr, &b, 1);
+ return b;
+}
+
+// Set an alarm time. Sets the alarm registers only. To cause the
+// INT pin to be asserted on alarm match, use alarmInterrupt().
+// This method can set either Alarm 1 or Alarm 2, depending on the
+// value of alarmType (use a value from the ALARM_TYPES_t enumeration).
+// When setting Alarm 2, the seconds value must be supplied but is
+// ignored, recommend using zero. (Alarm 2 has no seconds register.)
+void DS3232RTC::setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate)
+{
+ uint8_t addr;
+
+ seconds = dec2bcd(seconds);
+ minutes = dec2bcd(minutes);
+ hours = dec2bcd(hours);
+ daydate = dec2bcd(daydate);
+ if (alarmType & 0x01) seconds |= _BV(A1M1);
+ if (alarmType & 0x02) minutes |= _BV(A1M2);
+ if (alarmType & 0x04) hours |= _BV(A1M3);
+ if (alarmType & 0x10) daydate |= _BV(DYDT);
+ if (alarmType & 0x08) daydate |= _BV(A1M4);
+
+ if ( !(alarmType & 0x80) ) // alarm 1
+ {
+ addr = ALM1_SECONDS;
+ writeRTC(addr++, seconds);
+ }
+ else
+ {
+ addr = ALM2_MINUTES;
+ }
+ writeRTC(addr++, minutes);
+ writeRTC(addr++, hours);
+ writeRTC(addr++, daydate);
+}
+
+// Set an alarm time. Sets the alarm registers only. To cause the
+// INT pin to be asserted on alarm match, use alarmInterrupt().
+// This method can set either Alarm 1 or Alarm 2, depending on the
+// value of alarmType (use a value from the ALARM_TYPES_t enumeration).
+// However, when using this method to set Alarm 1, the seconds value
+// is set to zero. (Alarm 2 has no seconds register.)
+void DS3232RTC::setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate)
+{
+ setAlarm(alarmType, 0, minutes, hours, daydate);
+}
+
+// Enable or disable an alarm "interrupt" which asserts the INT pin
+// on the RTC.
+void DS3232RTC::alarmInterrupt(byte alarmNumber, bool interruptEnabled)
+{
+ uint8_t controlReg, mask;
+
+ controlReg = readRTC(RTC_CONTROL);
+ mask = _BV(A1IE) << (alarmNumber - 1);
+ if (interruptEnabled)
+ controlReg |= mask;
+ else
+ controlReg &= ~mask;
+ writeRTC(RTC_CONTROL, controlReg);
+}
+
+// Returns true or false depending on whether the given alarm has been
+// triggered, and resets the alarm flag bit.
+bool DS3232RTC::alarm(byte alarmNumber)
+{
+ uint8_t statusReg, mask;
+
+ statusReg = readRTC(RTC_STATUS);
+ mask = _BV(A1F) << (alarmNumber - 1);
+ if (statusReg & mask)
+ {
+ statusReg &= ~mask;
+ writeRTC(RTC_STATUS, statusReg);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Enable or disable the square wave output.
+// Use a value from the SQWAVE_FREQS_t enumeration for the parameter.
+void DS3232RTC::squareWave(SQWAVE_FREQS_t freq)
+{
+ uint8_t controlReg;
+
+ controlReg = readRTC(RTC_CONTROL);
+ if (freq >= SQWAVE_NONE)
+ {
+ controlReg |= _BV(INTCN);
+ }
+ else
+ {
+ controlReg = (controlReg & 0xE3) | (freq << RS1);
+ }
+ writeRTC(RTC_CONTROL, controlReg);
+}
+
+// Returns the value of the oscillator stop flag (OSF) bit in the
+// control/status register which indicates that the oscillator is or *
+// was stopped, and that the timekeeping data may be invalid.
+// Optionally clears the OSF bit depending on the argument passed.
+bool DS3232RTC::oscStopped(bool clearOSF)
+{
+ uint8_t s = readRTC(RTC_STATUS); // read the status register
+ bool ret = s & _BV(OSF); // isolate the osc stop flag to return to caller
+ if (ret && clearOSF) // clear OSF if it's set and the caller wants to clear it
+ {
+ writeRTC( RTC_STATUS, s & ~_BV(OSF) );
+ }
+ return ret;
+}
+
+// Returns the temperature in Celsius times four.
+int16_t DS3232RTC::temperature()
+{
+ union int16_byte {
+ int16_t i;
+ byte b[2];
+ } rtcTemp;
+
+ rtcTemp.b[0] = readRTC(RTC_TEMP_LSB);
+ rtcTemp.b[1] = readRTC(RTC_TEMP_MSB);
+ return rtcTemp.i / 64;
+}
+
+// Decimal-to-BCD conversion
+uint8_t DS3232RTC::dec2bcd(uint8_t n)
+{
+ return n + 6 * (n / 10);
+}
+
+// BCD-to-Decimal conversion
+uint8_t __attribute__ ((noinline)) DS3232RTC::bcd2dec(uint8_t n)
+{
+ return n - 6 * (n >> 4);
+}
+
+#ifdef ARDUINO_ARCH_AVR
+DS3232RTC RTC; // instantiate an RTC object
+#endif
diff --git a/.oldds32rtc.h b/.oldds32rtc.h
new file mode 100644
index 0000000..0f627ca
--- /dev/null
+++ b/.oldds32rtc.h
@@ -0,0 +1,93 @@
+// Arduino DS3232RTC Library
+// https://github.com/JChristensen/DS3232RTC
+// Copyright (C) 2018 by Jack Christensen and licensed under
+// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
+//
+// Arduino library for the Maxim Integrated DS3232 and DS3231
+// Real-Time Clocks.
+// Requires PJRC's improved version of the Arduino Time Library,
+// https://playground.arduino.cc/Code/Time
+// https://github.com/PaulStoffregen/Time
+//
+// For AVR architecture, a DS3232RTC object named RTC is instantiated
+// by the library and I2C initialization occurs in the constructor;
+// this is for backwards compatibility.
+// For other architectures, the user needs to instantiate a DS3232RTC
+// object and optionally initialize the I2C bus by calling
+// DS3232RTC::begin(). The constructor has an optional bool parameter
+// to indicate whether I2C initialization should occur in the
+// constructor; this parameter defaults to true if not given.
+
+#ifndef DS3232RTC_H_INCLUDED
+#define DS3232RTC_H_INCLUDED
+
+#include <Arduino.h>
+#include <TimeLib.h> // https://github.com/PaulStoffregen/Time
+
+// Alarm masks
+enum ALARM_TYPES_t {
+ ALM1_EVERY_SECOND = 0x0F,
+ ALM1_MATCH_SECONDS = 0x0E,
+ ALM1_MATCH_MINUTES = 0x0C, // match minutes *and* seconds
+ ALM1_MATCH_HOURS = 0x08, // match hours *and* minutes, seconds
+ ALM1_MATCH_DATE = 0x00, // match date *and* hours, minutes, seconds
+ ALM1_MATCH_DAY = 0x10, // match day *and* hours, minutes, seconds
+ ALM2_EVERY_MINUTE = 0x8E,
+ ALM2_MATCH_MINUTES = 0x8C, // match minutes
+ ALM2_MATCH_HOURS = 0x88, // match hours *and* minutes
+ ALM2_MATCH_DATE = 0x80, // match date *and* hours, minutes
+ ALM2_MATCH_DAY = 0x90, // match day *and* hours, minutes
+};
+
+// Square-wave output frequency (TS2, RS1 bits)
+enum SQWAVE_FREQS_t {
+ SQWAVE_1_HZ,
+ SQWAVE_1024_HZ,
+ SQWAVE_4096_HZ,
+ SQWAVE_8192_HZ,
+ SQWAVE_NONE
+};
+
+#define ALARM_1 1 // constants for alarm functions
+#define ALARM_2 2
+
+class DS3232RTC
+{
+ public:
+ DS3232RTC(bool initI2C = true);
+ void begin();
+ static time_t get(); // static needed to work with setSyncProvider() in the Time library
+ byte set(time_t t);
+ static byte read(tmElements_t &tm);
+ byte write(tmElements_t &tm);
+ byte writeRTC(byte addr, byte *values, byte nBytes);
+ byte writeRTC(byte addr, byte value);
+ byte readRTC(byte addr, byte *values, byte nBytes);
+ byte readRTC(byte addr);
+ void setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate);
+ void setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate);
+ void alarmInterrupt(byte alarmNumber, bool alarmEnabled);
+ bool alarm(byte alarmNumber);
+ void squareWave(SQWAVE_FREQS_t freq);
+ bool oscStopped(bool clearOSF = false);
+ int16_t temperature();
+ static byte errCode;
+
+ private:
+ uint8_t dec2bcd(uint8_t n);
+ static uint8_t bcd2dec(uint8_t n);
+};
+
+#ifdef ARDUINO_ARCH_AVR
+extern DS3232RTC RTC;
+#endif
+
+#ifndef _BV
+#define _BV(bit) (1 << (bit))
+#endif
+
+#ifndef BUFFER_LENGTH // a horrible and limiting kludge for samd (arduino zero)
+#define BUFFER_LENGTH 32
+#endif
+
+#endif
diff --git a/include/README b/include/README
new file mode 100644
index 0000000..194dcd4
--- /dev/null
+++ b/include/README
@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000..6debab1
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in a an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+| |
+| |--Bar
+| | |--docs
+| | |--examples
+| | |--src
+| | |- Bar.c
+| | |- Bar.h
+| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+| |
+| |--Foo
+| | |- Foo.c
+| | |- Foo.h
+| |
+| |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+ |- main.c
+
+and a contents of `src/main.c`:
+```
+#include <Foo.h>
+#include <Bar.h>
+
+int main (void)
+{
+ ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html
diff --git a/platformio.ini b/platformio.ini
new file mode 100644
index 0000000..6de3f31
--- /dev/null
+++ b/platformio.ini
@@ -0,0 +1,30 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+[env:esp32dev]
+platform = espressif32
+board = pico32
+; board = esp32dev
+framework = arduino
+lib_deps =
+ sqfmi/Watchy @ 1.4.1 ; Pinned version to ensure we don't pull broken code
+ https://github.com/tzapu/WiFiManager.git#v2.0.11-beta ; Pinned for the same reason
+lib_ldf_mode = deep+
+board_build.partitions = min_spiffs.csv
+
+; upload_speed = 3000000
+upload_port = /dev/ttyUSB0
+monitor_port = /dev/ttyUSB0
+; monitor_speed = 115200
+monitor_speed = 921600
+monitor_filters = esp32_exception_decoder
+
+board_build.f_cpu = 240000000L
+board_build.f_flash = 80000000L
+build_flags = -DCORE_DEBUG_LEVEL=0
diff --git a/src/DSEG7_Classic_Bold_25.h b/src/DSEG7_Classic_Bold_25.h
new file mode 100644
index 0000000..de77563
--- /dev/null
+++ b/src/DSEG7_Classic_Bold_25.h
@@ -0,0 +1,199 @@
+// Created by http://oleddisplay.squix.ch/ Consider a donation
+// In case of problems make sure that you are using the font file with the correct version!
+const uint8_t DSEG7_Classic_Bold_25Bitmaps[] PROGMEM = {
+
+ // Bitmap Data:
+ 0x00, // ' '
+ 0x00, // '!'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '"'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '#'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '$'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '%'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '&'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '''
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '('
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // ')'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '*'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '+'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // ','
+ 0x7F,0xE7,0xFF,0x9F,0xF8, // '-'
+ 0x67,0x98, // '.'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '/'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDC,0x00,0x60,0x00,0x07,0x00,0x1B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xFF,0xEC,0xFF,0xFA,0x3F,0xFE,0x00, // '0'
+ 0x26,0xEE,0xEE,0xEE,0xEE,0x60,0x6E,0xEE,0xEE,0xEE,0xE6,0x20, // '1'
+ 0x3F,0xFE,0x1F,0xFE,0x87,0xFE,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC3,0xFF,0x63,0xFF,0xC7,0xFF,0xC3,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x00, // '2'
+ 0xFF,0xF9,0xFF,0xE9,0xFF,0xB0,0x00,0xE0,0x01,0xC0,0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x73,0xFF,0x6F,0xFF,0x0F,0xFD,0x80,0x07,0x00,0x0E,0x00,0x1C,0x00,0x38,0x00,0x70,0x00,0xE0,0x01,0xC0,0x03,0x9F,0xFB,0x7F,0xFA,0xFF,0xF8, // '3'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x81,0xFF,0xB0,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x18,0x00,0x04, // '4'
+ 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1F,0xFF,0x03,0xFF,0xC0,0xFF,0xD8,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x7F,0xEC,0x7F,0xFA,0x3F,0xFE,0x00, // '5'
+ 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1F,0xFF,0x03,0xFF,0xC7,0xFF,0xDB,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xFF,0xEC,0xFF,0xFA,0x3F,0xFE,0x00, // '6'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDC,0x00,0x60,0x00,0x00,0x00,0x18,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x0C,0x00,0x02, // '7'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC7,0xFF,0xDB,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xFF,0xEC,0xFF,0xFA,0x3F,0xFE,0x00, // '8'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC0,0xFF,0xD8,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x7F,0xEC,0x7F,0xFA,0x3F,0xFE,0x00, // '9'
+ 0x4E,0xE0,0x00,0x00,0x00,0x4E,0xE4, // ':'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // ';'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '<'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '='
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '>'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '?'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '@'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC7,0xFF,0xDB,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0x80,0x0C,0x80,0x02, // 'A'
+ 0x40,0x00,0x70,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3F,0xFE,0x07,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'B'
+ 0x1F,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'C'
+ 0x00,0x01,0x00,0x01,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x87,0xFE,0xC7,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'D'
+ 0x3F,0xFE,0x7F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'E'
+ 0x3F,0xFE,0x7F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xE0,0x00,0x40,0x00, // 'F'
+ 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1C,0x00,0x00,0x00,0x07,0x00,0x1B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xFF,0xEC,0xFF,0xFA,0x3F,0xFE,0x00, // 'G'
+ 0x40,0x00,0x70,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3F,0xFE,0x07,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x00,0x19,0x00,0x04, // 'H'
+ 0x6E,0xEE,0xEE,0xEE,0xE6,0x20, // 'I'
+ 0x00,0x01,0x00,0x01,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x00,0xC0,0x00,0x0E,0x00,0x37,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'J'
+ 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1F,0xFF,0x03,0xFF,0xC7,0xFF,0xDB,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0x80,0x0C,0x80,0x02, // 'K'
+ 0x40,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'L'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDC,0x00,0x60,0x00,0x07,0x00,0x1B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0x80,0x0C,0x80,0x02, // 'M'
+ 0x1F,0xF8,0x1F,0xFE,0x3F,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDC,0x00,0x64,0x00,0x10, // 'N'
+ 0x1F,0xF8,0x1F,0xFE,0x3F,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x67,0xFF,0xD1,0xFF,0xF0, // 'O'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC7,0xFF,0xC3,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0x80,0x00,0x80,0x00, // 'P'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC0,0xFF,0xD8,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x0C,0x00,0x02, // 'Q'
+ 0x1F,0xF8,0x7F,0xFB,0xFF,0xE7,0x80,0x0F,0x00,0x1E,0x00,0x3C,0x00,0x78,0x00,0xF0,0x01,0xE0,0x03,0xC0,0x07,0x00,0x04,0x00,0x00, // 'R'
+ 0x40,0x00,0x70,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3F,0xFE,0x07,0xFF,0x81,0xFF,0xB0,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0xFF,0xD8,0xFF,0xF4,0x7F,0xFC, // 'S'
+ 0x40,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'T'
+ 0xE0,0x03,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x7F,0xFD,0x9F,0xFF,0x47,0xFF,0xC0, // 'U'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xB8,0x00,0xC0,0x00,0x0E,0x00,0x37,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'V'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'W'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x00,0x19,0x00,0x04, // 'X'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x81,0xFF,0xB0,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0xFF,0xD8,0xFF,0xF4,0x7F,0xFC, // 'Y'
+ 0x3F,0xFE,0x1F,0xFE,0x87,0xFE,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0x60,0x00,0x07,0x00,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x00, // 'Z'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '['
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '\'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // ']'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '^'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '_'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '`'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC7,0xFF,0xDB,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0x80,0x0C,0x80,0x02, // 'a'
+ 0x40,0x00,0x70,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3F,0xFE,0x07,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'b'
+ 0x1F,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'c'
+ 0x00,0x01,0x00,0x01,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x87,0xFE,0xC7,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'd'
+ 0x3F,0xFE,0x7F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'e'
+ 0x3F,0xFE,0x7F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xE0,0x00,0x40,0x00, // 'f'
+ 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1C,0x00,0x00,0x00,0x07,0x00,0x1B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xFF,0xEC,0xFF,0xFA,0x3F,0xFE,0x00, // 'g'
+ 0x40,0x00,0x70,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3F,0xFE,0x07,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x00,0x19,0x00,0x04, // 'h'
+ 0x6E,0xEE,0xEE,0xEE,0xE6,0x20, // 'i'
+ 0x00,0x01,0x00,0x01,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x00,0xC0,0x00,0x0E,0x00,0x37,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'j'
+ 0x3F,0xFE,0x3F,0xFE,0x3F,0xFE,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1F,0xFF,0x03,0xFF,0xC7,0xFF,0xDB,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0x80,0x0C,0x80,0x02, // 'k'
+ 0x40,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 'l'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDC,0x00,0x60,0x00,0x07,0x00,0x1B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0x80,0x0C,0x80,0x02, // 'm'
+ 0x1F,0xF8,0x1F,0xFE,0x3F,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDC,0x00,0x64,0x00,0x10, // 'n'
+ 0x1F,0xF8,0x1F,0xFE,0x3F,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x67,0xFF,0xD1,0xFF,0xF0, // 'o'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC7,0xFF,0xC3,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0x80,0x00,0x80,0x00, // 'p'
+ 0x3F,0xFE,0x3F,0xFE,0xBF,0xFE,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDF,0xFF,0x63,0xFF,0xC0,0xFF,0xD8,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x0C,0x00,0x02, // 'q'
+ 0x1F,0xF8,0x7F,0xFB,0xFF,0xE7,0x80,0x0F,0x00,0x1E,0x00,0x3C,0x00,0x78,0x00,0xF0,0x01,0xE0,0x03,0xC0,0x07,0x00,0x04,0x00,0x00, // 'r'
+ 0x40,0x00,0x70,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3F,0xFE,0x07,0xFF,0x81,0xFF,0xB0,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0xFF,0xD8,0xFF,0xF4,0x7F,0xFC, // 's'
+ 0x40,0x00,0xE0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x3F,0xFC,0xFF,0xF8,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xF0,0x00,0xFF,0xF8,0x7F,0xFC,0x3F,0xFE, // 't'
+ 0xE0,0x03,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x7F,0xFD,0x9F,0xFF,0x47,0xFF,0xC0, // 'u'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xB8,0x00,0xC0,0x00,0x0E,0x00,0x37,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'v'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0xFF,0xD9,0xFF,0xF4,0x7F,0xFC, // 'w'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x8F,0xFF,0xB7,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x00,0x19,0x00,0x04, // 'x'
+ 0x40,0x01,0x70,0x01,0xBC,0x01,0xDE,0x00,0xEF,0x00,0x77,0x80,0x3B,0xC0,0x1D,0xE0,0x0E,0xF0,0x07,0x78,0x03,0xBF,0xFE,0xC7,0xFF,0x81,0xFF,0xB0,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0xFF,0xD8,0xFF,0xF4,0x7F,0xFC, // 'y'
+ 0x3F,0xFE,0x1F,0xFE,0x87,0xFE,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0x60,0x00,0x07,0x00,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0x78,0x00,0x3C,0x00,0x1E,0x00,0x0F,0x00,0x07,0x80,0x03,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x00, // 'z'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '{'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE, // '|'
+ 0xFE,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xFE // '}'
+};
+const GFXglyph DSEG7_Classic_Bold_25Glyphs[] PROGMEM = {
+// bitmapOffset, width, height, xAdvance, xOffset, yOffset
+ { 0, 1, 1, 6, 0, 0 }, // ' '
+ { 1, 1, 1, 21, 0, 0 }, // '!'
+ { 2, 8, 17, 10, 1, -17 }, // '"'
+ { 19, 8, 17, 10, 1, -17 }, // '#'
+ { 36, 8, 17, 10, 1, -17 }, // '$'
+ { 53, 8, 17, 10, 1, -17 }, // '%'
+ { 70, 8, 17, 10, 1, -17 }, // '&'
+ { 87, 8, 17, 10, 1, -17 }, // '''
+ { 104, 8, 17, 10, 1, -17 }, // '('
+ { 121, 8, 17, 10, 1, -17 }, // ')'
+ { 138, 8, 17, 10, 1, -17 }, // '*'
+ { 155, 8, 17, 10, 1, -17 }, // '+'
+ { 172, 8, 17, 10, 1, -17 }, // ','
+ { 189, 13, 3, 21, 4, -14 }, // '-'
+ { 194, 5, 3, 1, -2, -3 }, // '.'
+ { 196, 8, 17, 10, 1, -17 }, // '/'
+ { 213, 17, 25, 21, 2, -25 }, // '0'
+ { 267, 4, 23, 21, 15, -24 }, // '1'
+ { 279, 17, 25, 21, 2, -25 }, // '2'
+ { 333, 15, 25, 21, 4, -25 }, // '3'
+ { 380, 17, 23, 21, 2, -24 }, // '4'
+ { 429, 17, 25, 21, 2, -25 }, // '5'
+ { 483, 17, 25, 21, 2, -25 }, // '6'
+ { 537, 17, 24, 21, 2, -25 }, // '7'
+ { 588, 17, 25, 21, 2, -25 }, // '8'
+ { 642, 17, 25, 21, 2, -25 }, // '9'
+ { 696, 4, 14, 6, 1, -19 }, // ':'
+ { 703, 8, 17, 10, 1, -17 }, // ';'
+ { 720, 8, 17, 10, 1, -17 }, // '<'
+ { 737, 8, 17, 10, 1, -17 }, // '='
+ { 754, 8, 17, 10, 1, -17 }, // '>'
+ { 771, 8, 17, 10, 1, -17 }, // '?'
+ { 788, 8, 17, 10, 1, -17 }, // '@'
+ { 805, 17, 24, 21, 2, -25 }, // 'A'
+ { 856, 17, 24, 21, 2, -24 }, // 'B'
+ { 907, 16, 14, 21, 2, -14 }, // 'C'
+ { 935, 17, 24, 21, 2, -24 }, // 'D'
+ { 986, 16, 25, 21, 2, -25 }, // 'E'
+ { 1036, 16, 24, 21, 2, -25 }, // 'F'
+ { 1084, 17, 25, 21, 2, -25 }, // 'G'
+ { 1138, 17, 23, 21, 2, -24 }, // 'H'
+ { 1187, 4, 11, 21, 15, -12 }, // 'I'
+ { 1193, 17, 24, 21, 2, -24 }, // 'J'
+ { 1244, 17, 24, 21, 2, -25 }, // 'K'
+ { 1295, 16, 24, 21, 2, -24 }, // 'L'
+ { 1343, 17, 24, 21, 2, -25 }, // 'M'
+ { 1394, 17, 13, 21, 2, -14 }, // 'N'
+ { 1422, 17, 14, 21, 2, -14 }, // 'O'
+ { 1452, 17, 24, 21, 2, -25 }, // 'P'
+ { 1503, 17, 24, 21, 2, -25 }, // 'Q'
+ { 1554, 15, 13, 21, 2, -14 }, // 'R'
+ { 1579, 17, 24, 21, 2, -24 }, // 'S'
+ { 1630, 16, 24, 21, 2, -24 }, // 'T'
+ { 1678, 17, 12, 21, 2, -12 }, // 'U'
+ { 1704, 17, 24, 21, 2, -24 }, // 'V'
+ { 1755, 17, 24, 21, 2, -24 }, // 'W'
+ { 1806, 17, 23, 21, 2, -24 }, // 'X'
+ { 1855, 17, 24, 21, 2, -24 }, // 'Y'
+ { 1906, 17, 25, 21, 2, -25 }, // 'Z'
+ { 1960, 8, 17, 10, 1, -17 }, // '['
+ { 1977, 8, 17, 10, 1, -17 }, // '\'
+ { 1994, 8, 17, 10, 1, -17 }, // ']'
+ { 2011, 8, 17, 10, 1, -17 }, // '^'
+ { 2028, 8, 17, 10, 1, -17 }, // '_'
+ { 2045, 8, 17, 10, 1, -17 }, // '`'
+ { 2062, 17, 24, 21, 2, -25 }, // 'a'
+ { 2113, 17, 24, 21, 2, -24 }, // 'b'
+ { 2164, 16, 14, 21, 2, -14 }, // 'c'
+ { 2192, 17, 24, 21, 2, -24 }, // 'd'
+ { 2243, 16, 25, 21, 2, -25 }, // 'e'
+ { 2293, 16, 24, 21, 2, -25 }, // 'f'
+ { 2341, 17, 25, 21, 2, -25 }, // 'g'
+ { 2395, 17, 23, 21, 2, -24 }, // 'h'
+ { 2444, 4, 11, 21, 15, -12 }, // 'i'
+ { 2450, 17, 24, 21, 2, -24 }, // 'j'
+ { 2501, 17, 24, 21, 2, -25 }, // 'k'
+ { 2552, 16, 24, 21, 2, -24 }, // 'l'
+ { 2600, 17, 24, 21, 2, -25 }, // 'm'
+ { 2651, 17, 13, 21, 2, -14 }, // 'n'
+ { 2679, 17, 14, 21, 2, -14 }, // 'o'
+ { 2709, 17, 24, 21, 2, -25 }, // 'p'
+ { 2760, 17, 24, 21, 2, -25 }, // 'q'
+ { 2811, 15, 13, 21, 2, -14 }, // 'r'
+ { 2836, 17, 24, 21, 2, -24 }, // 's'
+ { 2887, 16, 24, 21, 2, -24 }, // 't'
+ { 2935, 17, 12, 21, 2, -12 }, // 'u'
+ { 2961, 17, 24, 21, 2, -24 }, // 'v'
+ { 3012, 17, 24, 21, 2, -24 }, // 'w'
+ { 3063, 17, 23, 21, 2, -24 }, // 'x'
+ { 3112, 17, 24, 21, 2, -24 }, // 'y'
+ { 3163, 17, 25, 21, 2, -25 }, // 'z'
+ { 3217, 8, 17, 10, 1, -17 }, // '{'
+ { 3234, 8, 17, 10, 1, -17 }, // '|'
+ { 3251, 8, 17, 10, 1, -17 } // '}'
+};
+const GFXfont DSEG7_Classic_Bold_25 PROGMEM = {
+(uint8_t *)DSEG7_Classic_Bold_25Bitmaps,(GFXglyph *)DSEG7_Classic_Bold_25Glyphs,0x20, 0x7E, 28};
diff --git a/src/DSEG7_Classic_Regular_15.h b/src/DSEG7_Classic_Regular_15.h
new file mode 100644
index 0000000..83b250d
--- /dev/null
+++ b/src/DSEG7_Classic_Regular_15.h
@@ -0,0 +1,199 @@
+// Created by http://oleddisplay.squix.ch/ Consider a donation
+// In case of problems make sure that you are using the font file with the correct version!
+const uint8_t DSEG7_Classic_Regular_15Bitmaps[] PROGMEM = {
+
+ // Bitmap Data:
+ 0x00, // ' '
+ 0x00, // '!'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '"'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '#'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '$'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '%'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '&'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '''
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '('
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // ')'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '*'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '+'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // ','
+ 0xFF,0x00, // '-'
+ 0xD8, // '.'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '/'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30,0x00,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // '0'
+ 0xDB,0x6D,0x86,0xDB,0x6C, // '1'
+ 0x7F,0x80,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x33,0xFC,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE0, // '2'
+ 0xFF,0x00,0x60,0x18,0x06,0x01,0x80,0x60,0x1B,0xFC,0x01,0x80,0x60,0x18,0x06,0x01,0x80,0x6F,0xF0, // '3'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C, // '4'
+ 0x7F,0x98,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x03,0xFC,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x9F,0xE0, // '5'
+ 0x7F,0x98,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x03,0xFC,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // '6'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30,0x00,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80, // '7'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // '8'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x9F,0xE0, // '9'
+ 0xA0,0x0A, // ':'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // ';'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '<'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '='
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '>'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '?'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '@'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80, // 'A'
+ 0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'B'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x01,0xFE, // 'C'
+ 0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x9F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'D'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x01,0xFE,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x07,0xF8, // 'E'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x01,0xFE,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x00, // 'F'
+ 0x7F,0x98,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x00,0x00,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // 'G'
+ 0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C, // 'H'
+ 0xDB,0x6D,0x80, // 'I'
+ 0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x06,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'J'
+ 0x7F,0x98,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x03,0xFC,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80, // 'K'
+ 0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x00,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x1F,0xE0, // 'L'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30,0x00,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80, // 'M'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30, // 'N'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC, // 'O'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x00, // 'P'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80, // 'Q'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x00, // 'R'
+ 0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE0,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0xFF,0x00, // 'S'
+ 0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x07,0xFB,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x1F,0xE0, // 'T'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // 'U'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80,0x06,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'V'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'W'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C, // 'X'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0xFF,0x00, // 'Y'
+ 0x7F,0x80,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE0, // 'Z'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '['
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '\'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // ']'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '^'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '_'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '`'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80, // 'a'
+ 0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'b'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x01,0xFE, // 'c'
+ 0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x9F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'd'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x01,0xFE,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x07,0xF8, // 'e'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x01,0xFE,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x00, // 'f'
+ 0x7F,0x98,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x00,0x00,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // 'g'
+ 0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C, // 'h'
+ 0xDB,0x6D,0x80, // 'i'
+ 0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x06,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'j'
+ 0x7F,0x98,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x03,0xFC,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80, // 'k'
+ 0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x00,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x1F,0xE0, // 'l'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30,0x00,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80, // 'm'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30, // 'n'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC, // 'o'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x00, // 'p'
+ 0x7F,0x98,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x33,0xFC,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80, // 'q'
+ 0x7F,0xB0,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x00, // 'r'
+ 0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE0,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0xFF,0x00, // 's'
+ 0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x07,0xFB,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x1F,0xE0, // 't'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0, // 'u'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80,0x06,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'v'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C,0xFF,0x00, // 'w'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE6,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0C, // 'x'
+ 0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x9F,0xE0,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0xFF,0x00, // 'y'
+ 0x7F,0x80,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x1F,0xE0, // 'z'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '{'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC, // '|'
+ 0xF4,0xA5,0x29,0x4A,0x52,0x94,0xBC // '}'
+};
+const GFXglyph DSEG7_Classic_Regular_15Glyphs[] PROGMEM = {
+// bitmapOffset, width, height, xAdvance, xOffset, yOffset
+ { 0, 1, 1, 4, 0, 0 }, // ' '
+ { 1, 1, 1, 13, 0, 0 }, // '!'
+ { 2, 5, 11, 6, 1, -11 }, // '"'
+ { 9, 5, 11, 6, 1, -11 }, // '#'
+ { 16, 5, 11, 6, 1, -11 }, // '$'
+ { 23, 5, 11, 6, 1, -11 }, // '%'
+ { 30, 5, 11, 6, 1, -11 }, // '&'
+ { 37, 5, 11, 6, 1, -11 }, // '''
+ { 44, 5, 11, 6, 1, -11 }, // '('
+ { 51, 5, 11, 6, 1, -11 }, // ')'
+ { 58, 5, 11, 6, 1, -11 }, // '*'
+ { 65, 5, 11, 6, 1, -11 }, // '+'
+ { 72, 5, 11, 6, 1, -11 }, // ','
+ { 79, 9, 1, 13, 2, -8 }, // '-'
+ { 81, 3, 2, 1, -1, -2 }, // '.'
+ { 82, 5, 11, 6, 1, -11 }, // '/'
+ { 89, 11, 15, 13, 1, -15 }, // '0'
+ { 110, 3, 13, 13, 9, -14 }, // '1'
+ { 115, 11, 15, 13, 1, -15 }, // '2'
+ { 136, 10, 15, 13, 2, -15 }, // '3'
+ { 155, 11, 13, 13, 1, -14 }, // '4'
+ { 173, 11, 15, 13, 1, -15 }, // '5'
+ { 194, 11, 15, 13, 1, -15 }, // '6'
+ { 215, 11, 14, 13, 1, -15 }, // '7'
+ { 235, 11, 15, 13, 1, -15 }, // '8'
+ { 256, 11, 15, 13, 1, -15 }, // '9'
+ { 277, 2, 8, 4, 1, -11 }, // ':'
+ { 279, 5, 11, 6, 1, -11 }, // ';'
+ { 286, 5, 11, 6, 1, -11 }, // '<'
+ { 293, 5, 11, 6, 1, -11 }, // '='
+ { 300, 5, 11, 6, 1, -11 }, // '>'
+ { 307, 5, 11, 6, 1, -11 }, // '?'
+ { 314, 5, 11, 6, 1, -11 }, // '@'
+ { 321, 11, 14, 13, 1, -15 }, // 'A'
+ { 341, 11, 14, 13, 1, -14 }, // 'B'
+ { 361, 10, 8, 13, 1, -8 }, // 'C'
+ { 371, 11, 14, 13, 1, -14 }, // 'D'
+ { 391, 10, 15, 13, 1, -15 }, // 'E'
+ { 410, 10, 14, 13, 1, -15 }, // 'F'
+ { 428, 11, 15, 13, 1, -15 }, // 'G'
+ { 449, 11, 13, 13, 1, -14 }, // 'H'
+ { 467, 3, 6, 13, 9, -7 }, // 'I'
+ { 470, 11, 14, 13, 1, -14 }, // 'J'
+ { 490, 11, 14, 13, 1, -15 }, // 'K'
+ { 510, 10, 14, 13, 1, -14 }, // 'L'
+ { 528, 11, 14, 13, 1, -15 }, // 'M'
+ { 548, 11, 7, 13, 1, -8 }, // 'N'
+ { 558, 11, 8, 13, 1, -8 }, // 'O'
+ { 569, 11, 14, 13, 1, -15 }, // 'P'
+ { 589, 11, 14, 13, 1, -15 }, // 'Q'
+ { 609, 10, 7, 13, 1, -8 }, // 'R'
+ { 618, 11, 14, 13, 1, -14 }, // 'S'
+ { 638, 10, 14, 13, 1, -14 }, // 'T'
+ { 656, 11, 7, 13, 1, -7 }, // 'U'
+ { 666, 11, 14, 13, 1, -14 }, // 'V'
+ { 686, 11, 14, 13, 1, -14 }, // 'W'
+ { 706, 11, 13, 13, 1, -14 }, // 'X'
+ { 724, 11, 14, 13, 1, -14 }, // 'Y'
+ { 744, 11, 15, 13, 1, -15 }, // 'Z'
+ { 765, 5, 11, 6, 1, -11 }, // '['
+ { 772, 5, 11, 6, 1, -11 }, // '\'
+ { 779, 5, 11, 6, 1, -11 }, // ']'
+ { 786, 5, 11, 6, 1, -11 }, // '^'
+ { 793, 5, 11, 6, 1, -11 }, // '_'
+ { 800, 5, 11, 6, 1, -11 }, // '`'
+ { 807, 11, 14, 13, 1, -15 }, // 'a'
+ { 827, 11, 14, 13, 1, -14 }, // 'b'
+ { 847, 10, 8, 13, 1, -8 }, // 'c'
+ { 857, 11, 14, 13, 1, -14 }, // 'd'
+ { 877, 10, 15, 13, 1, -15 }, // 'e'
+ { 896, 10, 14, 13, 1, -15 }, // 'f'
+ { 914, 11, 15, 13, 1, -15 }, // 'g'
+ { 935, 11, 13, 13, 1, -14 }, // 'h'
+ { 953, 3, 6, 13, 9, -7 }, // 'i'
+ { 956, 11, 14, 13, 1, -14 }, // 'j'
+ { 976, 11, 14, 13, 1, -15 }, // 'k'
+ { 996, 10, 14, 13, 1, -14 }, // 'l'
+ { 1014, 11, 14, 13, 1, -15 }, // 'm'
+ { 1034, 11, 7, 13, 1, -8 }, // 'n'
+ { 1044, 11, 8, 13, 1, -8 }, // 'o'
+ { 1055, 11, 14, 13, 1, -15 }, // 'p'
+ { 1075, 11, 14, 13, 1, -15 }, // 'q'
+ { 1095, 10, 7, 13, 1, -8 }, // 'r'
+ { 1104, 11, 14, 13, 1, -14 }, // 's'
+ { 1124, 10, 14, 13, 1, -14 }, // 't'
+ { 1142, 11, 7, 13, 1, -7 }, // 'u'
+ { 1152, 11, 14, 13, 1, -14 }, // 'v'
+ { 1172, 11, 14, 13, 1, -14 }, // 'w'
+ { 1192, 11, 13, 13, 1, -14 }, // 'x'
+ { 1210, 11, 14, 13, 1, -14 }, // 'y'
+ { 1230, 11, 15, 13, 1, -15 }, // 'z'
+ { 1251, 5, 11, 6, 1, -11 }, // '{'
+ { 1258, 5, 11, 6, 1, -11 }, // '|'
+ { 1265, 5, 11, 6, 1, -11 } // '}'
+};
+const GFXfont DSEG7_Classic_Regular_15 PROGMEM = {
+(uint8_t *)DSEG7_Classic_Regular_15Bitmaps,(GFXglyph *)DSEG7_Classic_Regular_15Glyphs,0x20, 0x7E, 17};
diff --git a/src/DSEG7_Classic_Regular_39.h b/src/DSEG7_Classic_Regular_39.h
new file mode 100644
index 0000000..2dbfc8d
--- /dev/null
+++ b/src/DSEG7_Classic_Regular_39.h
@@ -0,0 +1,199 @@
+// Created by http://oleddisplay.squix.ch/ Consider a donation
+// In case of problems make sure that you are using the font file with the correct version!
+const uint8_t DSEG7_Classic_Regular_39Bitmaps[] PROGMEM = {
+
+ // Bitmap Data:
+ 0x00, // ' '
+ 0x00, // '!'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '"'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '#'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '$'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '%'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '&'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '''
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '('
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // ')'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '*'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '+'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // ','
+ 0x7F,0xFF,0xE7,0xFF,0xFF,0x9F,0xFF,0xF8, // '-'
+ 0x67,0xBD,0xE6,0x00, // '.'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '/'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0,0x00,0x00,0x08,0x00,0x00,0x36,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDD,0xFF,0xFE,0xED,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // '0'
+ 0x33,0xBD,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x7B,0xCE,0x30,0x0C,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x7B,0xDE,0xF3,0x8C, // '1'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC1,0xFF,0xFE,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x03,0x87,0xFF,0xFE,0xC7,0xFF,0xFF,0x89,0xFF,0xFF,0x86,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1D,0xFF,0xFE,0x0D,0xFF,0xFF,0x81,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // '2'
+ 0xFF,0xFF,0xF1,0xFF,0xFF,0xE1,0xFF,0xFF,0xB1,0xFF,0xFE,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x39,0xFF,0xFF,0xB7,0xFF,0xFF,0x87,0xFF,0xFE,0xC0,0x00,0x03,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF1,0xFF,0xFE,0xE7,0xFF,0xFE,0xDF,0xFF,0xFE,0x3F,0xFF,0xFC,0x00, // '3'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0, // '4'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0x1D,0xFF,0xFE,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x37,0xFF,0xFE,0x07,0xFF,0xFF,0x81,0xFF,0xFF,0xB0,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC1,0xFF,0xFE,0xE1,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // '5'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0x1D,0xFF,0xFE,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x37,0xFF,0xFE,0x07,0xFF,0xFF,0x89,0xFF,0xFF,0xB6,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDD,0xFF,0xFE,0xED,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // '6'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x00,0xE0,0x00,0x00,0x30, // '7'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x89,0xFF,0xFF,0xB6,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDD,0xFF,0xFE,0xED,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // '8'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x81,0xFF,0xFF,0xB0,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC1,0xFF,0xFE,0xE1,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // '9'
+ 0x79,0xE7,0x9E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x79,0xE7,0x9E, // ':'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // ';'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '<'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '='
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '>'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '?'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '@'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x89,0xFF,0xFF,0xB6,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x00,0xEC,0x00,0x00,0x30, // 'A'
+ 0xC0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xDF,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'B'
+ 0x1F,0xFF,0xF8,0x7F,0xFF,0xFA,0x7F,0xFF,0xE6,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xDF,0xFF,0xE3,0x7F,0xFF,0xE1,0xFF,0xFF,0xE3,0xFF,0xFF,0xC0, // 'C'
+ 0x00,0x00,0x03,0x00,0x00,0x03,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x0E,0x1F,0xFF,0xFB,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'D'
+ 0x3F,0xFF,0xFC,0x7F,0xFF,0xFB,0x7F,0xFF,0xE7,0x7F,0xFF,0x8E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x7F,0xFF,0xE1,0xFF,0xFF,0xE9,0xFF,0xFF,0x98,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x7F,0xFF,0x8D,0xFF,0xFF,0x87,0xFF,0xFF,0x8F,0xFF,0xFF,0x00, // 'E'
+ 0x3F,0xFF,0xFC,0x7F,0xFF,0xFB,0x7F,0xFF,0xE7,0x7F,0xFF,0x8E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x7F,0xFF,0xE1,0xFF,0xFF,0xE9,0xFF,0xFF,0x98,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0C,0x00,0x00,0x00, // 'F'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0x1D,0xFF,0xFE,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x36,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDD,0xFF,0xFE,0xED,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // 'G'
+ 0xC0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xDF,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0, // 'H'
+ 0x33,0xBD,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x7B,0xCE,0x30, // 'I'
+ 0x00,0x00,0x03,0x00,0x00,0x03,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x0E,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x00,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'J'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0x1D,0xFF,0xFE,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x37,0xFF,0xFE,0x07,0xFF,0xFF,0x89,0xFF,0xFF,0xB6,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x00,0xEC,0x00,0x00,0x30, // 'K'
+ 0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x06,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xDF,0xFF,0xE3,0x7F,0xFF,0xE1,0xFF,0xFF,0xE3,0xFF,0xFF,0xC0, // 'L'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0,0x00,0x00,0x08,0x00,0x00,0x36,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x00,0xEC,0x00,0x00,0x30, // 'M'
+ 0x1F,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0, // 'N'
+ 0x1F,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'O'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x89,0xFF,0xFF,0x86,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0C,0x00,0x00,0x00, // 'P'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x81,0xFF,0xFF,0xB0,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x00,0xE0,0x00,0x00,0x30, // 'Q'
+ 0x1F,0xFF,0xF8,0x7F,0xFF,0xFA,0x7F,0xFF,0xE6,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x00,0x00,0x00, // 'R'
+ 0xC0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xDF,0xFF,0xF8,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x07,0xFF,0xFB,0x87,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'S'
+ 0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xDF,0xFF,0xF8,0x7F,0xFF,0xFA,0x7F,0xFF,0xE6,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xDF,0xFF,0xE3,0x7F,0xFF,0xE1,0xFF,0xFF,0xE3,0xFF,0xFF,0xC0, // 'T'
+ 0x80,0x00,0x03,0x60,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xDF,0xFF,0xEE,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x0F,0xFF,0xFF,0x00, // 'U'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xC0,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x00,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'V'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'W'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0, // 'X'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x07,0xFF,0xFB,0x87,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'Y'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC1,0xFF,0xFE,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0,0x00,0x00,0x08,0x00,0x00,0x06,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1D,0xFF,0xFE,0x0D,0xFF,0xFF,0x81,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // 'Z'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '['
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '\'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // ']'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '^'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '_'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '`'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x89,0xFF,0xFF,0xB6,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x00,0xEC,0x00,0x00,0x30, // 'a'
+ 0xC0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xDF,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'b'
+ 0x1F,0xFF,0xF8,0x7F,0xFF,0xFA,0x7F,0xFF,0xE6,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xDF,0xFF,0xE3,0x7F,0xFF,0xE1,0xFF,0xFF,0xE3,0xFF,0xFF,0xC0, // 'c'
+ 0x00,0x00,0x03,0x00,0x00,0x03,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x0E,0x1F,0xFF,0xFB,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'd'
+ 0x3F,0xFF,0xFC,0x7F,0xFF,0xFB,0x7F,0xFF,0xE7,0x7F,0xFF,0x8E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x7F,0xFF,0xE1,0xFF,0xFF,0xE9,0xFF,0xFF,0x98,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x7F,0xFF,0x8D,0xFF,0xFF,0x87,0xFF,0xFF,0x8F,0xFF,0xFF,0x00, // 'e'
+ 0x3F,0xFF,0xFC,0x7F,0xFF,0xFB,0x7F,0xFF,0xE7,0x7F,0xFF,0x8E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x7F,0xFF,0xE1,0xFF,0xFF,0xE9,0xFF,0xFF,0x98,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0C,0x00,0x00,0x00, // 'f'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0x1D,0xFF,0xFE,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x36,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDD,0xFF,0xFE,0xED,0xFF,0xFF,0xB1,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // 'g'
+ 0xC0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xDF,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0, // 'h'
+ 0x33,0xBD,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x7B,0xCE,0x30, // 'i'
+ 0x00,0x00,0x03,0x00,0x00,0x03,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x0E,0x00,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x00,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'j'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0x1D,0xFF,0xFE,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x37,0xFF,0xFE,0x07,0xFF,0xFF,0x89,0xFF,0xFF,0xB6,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x00,0xEC,0x00,0x00,0x30, // 'k'
+ 0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x06,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xDF,0xFF,0xE3,0x7F,0xFF,0xE1,0xFF,0xFF,0xE3,0xFF,0xFF,0xC0, // 'l'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0,0x00,0x00,0x08,0x00,0x00,0x36,0x00,0x00,0x3B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x00,0xEC,0x00,0x00,0x30, // 'm'
+ 0x1F,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0, // 'n'
+ 0x1F,0xFF,0xF8,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'o'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x89,0xFF,0xFF,0x86,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0C,0x00,0x00,0x00, // 'p'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x37,0xFF,0xFE,0xDD,0xFF,0xFE,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x81,0xFF,0xFF,0xB0,0x00,0x00,0x38,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x00,0xE0,0x00,0x00,0x30, // 'q'
+ 0x1F,0xFF,0xF8,0x7F,0xFF,0xFA,0x7F,0xFF,0xE6,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x00,0x00,0x00, // 'r'
+ 0xC0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xDF,0xFF,0xF8,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x07,0xFF,0xFB,0x87,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 's'
+ 0xC0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xDF,0xFF,0xF8,0x7F,0xFF,0xFA,0x7F,0xFF,0xE6,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x07,0x00,0x00,0x0E,0x00,0x00,0x1C,0x00,0x00,0x38,0x00,0x00,0x70,0x00,0x00,0xE0,0x00,0x01,0xDF,0xFF,0xE3,0x7F,0xFF,0xE1,0xFF,0xFF,0xE3,0xFF,0xFF,0xC0, // 't'
+ 0x80,0x00,0x03,0x60,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xDF,0xFF,0xEE,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x0F,0xFF,0xFF,0x00, // 'u'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xC0,0x00,0x03,0x00,0x00,0x00,0x20,0x00,0x00,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'v'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x77,0xFF,0xFB,0xB7,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'w'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x27,0xFF,0xFE,0xD8,0x00,0x00,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x03,0xB0,0x00,0x00,0xC0, // 'x'
+ 0xC0,0x00,0x03,0x70,0x00,0x03,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x1E,0xE0,0x00,0x0F,0x70,0x00,0x07,0xB8,0x00,0x03,0xDC,0x00,0x01,0xEE,0x00,0x00,0xF7,0x00,0x00,0x7B,0x80,0x00,0x3D,0xC0,0x00,0x0E,0xDF,0xFF,0xFB,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC0,0x00,0x00,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x07,0xFF,0xFB,0x87,0xFF,0xFE,0xC7,0xFF,0xFF,0x83,0xFF,0xFF,0xC0, // 'y'
+ 0x3F,0xFF,0xFC,0x1F,0xFF,0xFE,0x07,0xFF,0xFE,0xC1,0xFF,0xFE,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x07,0x80,0x00,0x03,0xC0,0x00,0x01,0xE0,0x00,0x00,0xF0,0x00,0x00,0x78,0x00,0x00,0x3C,0x00,0x00,0x1E,0x00,0x00,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0,0x00,0x00,0x08,0x00,0x00,0x06,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00,0x0E,0x00,0x00,0x07,0x00,0x00,0x03,0x80,0x00,0x01,0xC0,0x00,0x00,0xE0,0x00,0x00,0x70,0x00,0x00,0x38,0x00,0x00,0x1D,0xFF,0xFE,0x0D,0xFF,0xFF,0x81,0xFF,0xFF,0xE0,0xFF,0xFF,0xF0, // 'z'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '{'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '|'
+ 0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8 // '}'
+};
+const GFXglyph DSEG7_Classic_Regular_39Glyphs[] PROGMEM = {
+// bitmapOffset, width, height, xAdvance, xOffset, yOffset
+ { 0, 1, 1, 9, 0, 0 }, // ' '
+ { 1, 1, 1, 33, 0, 0 }, // '!'
+ { 2, 11, 26, 15, 1, -26 }, // '"'
+ { 38, 11, 26, 15, 1, -26 }, // '#'
+ { 74, 11, 26, 15, 1, -26 }, // '$'
+ { 110, 11, 26, 15, 1, -26 }, // '%'
+ { 146, 11, 26, 15, 1, -26 }, // '&'
+ { 182, 11, 26, 15, 1, -26 }, // '''
+ { 218, 11, 26, 15, 1, -26 }, // '('
+ { 254, 11, 26, 15, 1, -26 }, // ')'
+ { 290, 11, 26, 15, 1, -26 }, // '*'
+ { 326, 11, 26, 15, 1, -26 }, // '+'
+ { 362, 11, 26, 15, 1, -26 }, // ','
+ { 398, 21, 3, 33, 6, -21 }, // '-'
+ { 406, 5, 5, 1, -2, -5 }, // '.'
+ { 410, 11, 26, 15, 1, -26 }, // '/'
+ { 446, 25, 39, 33, 4, -39 }, // '0'
+ { 568, 5, 35, 33, 24, -37 }, // '1'
+ { 590, 25, 39, 33, 4, -39 }, // '2'
+ { 712, 23, 39, 33, 6, -39 }, // '3'
+ { 825, 25, 35, 33, 4, -37 }, // '4'
+ { 935, 25, 39, 33, 4, -39 }, // '5'
+ { 1057, 25, 39, 33, 4, -39 }, // '6'
+ { 1179, 25, 37, 33, 4, -39 }, // '7'
+ { 1295, 25, 39, 33, 4, -39 }, // '8'
+ { 1417, 25, 39, 33, 4, -39 }, // '9'
+ { 1539, 6, 20, 9, 1, -29 }, // ':'
+ { 1554, 11, 26, 15, 1, -26 }, // ';'
+ { 1590, 11, 26, 15, 1, -26 }, // '<'
+ { 1626, 11, 26, 15, 1, -26 }, // '='
+ { 1662, 11, 26, 15, 1, -26 }, // '>'
+ { 1698, 11, 26, 15, 1, -26 }, // '?'
+ { 1734, 11, 26, 15, 1, -26 }, // '@'
+ { 1770, 25, 37, 33, 4, -39 }, // 'A'
+ { 1886, 25, 37, 33, 4, -37 }, // 'B'
+ { 2002, 23, 21, 33, 4, -21 }, // 'C'
+ { 2063, 25, 37, 33, 4, -37 }, // 'D'
+ { 2179, 23, 39, 33, 4, -39 }, // 'E'
+ { 2292, 23, 37, 33, 4, -39 }, // 'F'
+ { 2399, 25, 39, 33, 4, -39 }, // 'G'
+ { 2521, 25, 35, 33, 4, -37 }, // 'H'
+ { 2631, 5, 17, 33, 24, -19 }, // 'I'
+ { 2642, 25, 37, 33, 4, -37 }, // 'J'
+ { 2758, 25, 37, 33, 4, -39 }, // 'K'
+ { 2874, 23, 37, 33, 4, -37 }, // 'L'
+ { 2981, 25, 37, 33, 4, -39 }, // 'M'
+ { 3097, 25, 19, 33, 4, -21 }, // 'N'
+ { 3157, 25, 21, 33, 4, -21 }, // 'O'
+ { 3223, 25, 37, 33, 4, -39 }, // 'P'
+ { 3339, 25, 37, 33, 4, -39 }, // 'Q'
+ { 3455, 23, 19, 33, 4, -21 }, // 'R'
+ { 3510, 25, 37, 33, 4, -37 }, // 'S'
+ { 3626, 23, 37, 33, 4, -37 }, // 'T'
+ { 3733, 25, 19, 33, 4, -19 }, // 'U'
+ { 3793, 25, 37, 33, 4, -37 }, // 'V'
+ { 3909, 25, 37, 33, 4, -37 }, // 'W'
+ { 4025, 25, 35, 33, 4, -37 }, // 'X'
+ { 4135, 25, 37, 33, 4, -37 }, // 'Y'
+ { 4251, 25, 39, 33, 4, -39 }, // 'Z'
+ { 4373, 11, 26, 15, 1, -26 }, // '['
+ { 4409, 11, 26, 15, 1, -26 }, // '\'
+ { 4445, 11, 26, 15, 1, -26 }, // ']'
+ { 4481, 11, 26, 15, 1, -26 }, // '^'
+ { 4517, 11, 26, 15, 1, -26 }, // '_'
+ { 4553, 11, 26, 15, 1, -26 }, // '`'
+ { 4589, 25, 37, 33, 4, -39 }, // 'a'
+ { 4705, 25, 37, 33, 4, -37 }, // 'b'
+ { 4821, 23, 21, 33, 4, -21 }, // 'c'
+ { 4882, 25, 37, 33, 4, -37 }, // 'd'
+ { 4998, 23, 39, 33, 4, -39 }, // 'e'
+ { 5111, 23, 37, 33, 4, -39 }, // 'f'
+ { 5218, 25, 39, 33, 4, -39 }, // 'g'
+ { 5340, 25, 35, 33, 4, -37 }, // 'h'
+ { 5450, 5, 17, 33, 24, -19 }, // 'i'
+ { 5461, 25, 37, 33, 4, -37 }, // 'j'
+ { 5577, 25, 37, 33, 4, -39 }, // 'k'
+ { 5693, 23, 37, 33, 4, -37 }, // 'l'
+ { 5800, 25, 37, 33, 4, -39 }, // 'm'
+ { 5916, 25, 19, 33, 4, -21 }, // 'n'
+ { 5976, 25, 21, 33, 4, -21 }, // 'o'
+ { 6042, 25, 37, 33, 4, -39 }, // 'p'
+ { 6158, 25, 37, 33, 4, -39 }, // 'q'
+ { 6274, 23, 19, 33, 4, -21 }, // 'r'
+ { 6329, 25, 37, 33, 4, -37 }, // 's'
+ { 6445, 23, 37, 33, 4, -37 }, // 't'
+ { 6552, 25, 19, 33, 4, -19 }, // 'u'
+ { 6612, 25, 37, 33, 4, -37 }, // 'v'
+ { 6728, 25, 37, 33, 4, -37 }, // 'w'
+ { 6844, 25, 35, 33, 4, -37 }, // 'x'
+ { 6954, 25, 37, 33, 4, -37 }, // 'y'
+ { 7070, 25, 39, 33, 4, -39 }, // 'z'
+ { 7192, 11, 26, 15, 1, -26 }, // '{'
+ { 7228, 11, 26, 15, 1, -26 }, // '|'
+ { 7264, 11, 26, 15, 1, -26 } // '}'
+};
+const GFXfont DSEG7_Classic_Regular_39 PROGMEM = {
+(uint8_t *)DSEG7_Classic_Regular_39Bitmaps,(GFXglyph *)DSEG7_Classic_Regular_39Glyphs,0x20, 0x7E, 43};
diff --git a/src/Seven_Segment10pt7b.h b/src/Seven_Segment10pt7b.h
new file mode 100644
index 0000000..851ddd5
--- /dev/null
+++ b/src/Seven_Segment10pt7b.h
@@ -0,0 +1,204 @@
+const uint8_t Seven_Segment10pt7bBitmaps[] PROGMEM = {
+ 0x00, 0xFF, 0xFC, 0xA0, 0x09, 0x05, 0x86, 0x9F, 0xF1, 0x47, 0xFC, 0xB0,
+ 0xD0, 0x48, 0x00, 0x10, 0x10, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7E, 0x10, 0x10, 0x00, 0x40, 0x04,
+ 0x70, 0x88, 0x88, 0x89, 0x08, 0xB0, 0x72, 0x00, 0x66, 0x04, 0x90, 0xC9,
+ 0x08, 0x91, 0x06, 0x30, 0x02, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7E, 0x1F, 0x0F, 0x87, 0xE1, 0xF8, 0x02, 0x01, 0x00,
+ 0x81, 0x20, 0x80, 0x20, 0x10, 0x08, 0x12, 0x08, 0x02, 0x01, 0x00, 0x81,
+ 0x20, 0x80, 0x20, 0x10, 0x08, 0x12, 0x08, 0x02, 0x01, 0x00, 0x81, 0x20,
+ 0x80, 0x20, 0x10, 0x08, 0x12, 0x07, 0xE2, 0x01, 0x00, 0x7E, 0x20, 0xFE,
+ 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0x7C, 0x21,
+ 0x08, 0x42, 0x10, 0x84, 0x21, 0x08, 0x3C, 0xF0, 0x42, 0x10, 0x84, 0x21,
+ 0x08, 0x42, 0x10, 0xF8, 0x21, 0x3E, 0xEF, 0xD4, 0x80, 0x04, 0x00, 0x80,
+ 0x10, 0x02, 0x00, 0x41, 0xF7, 0xC1, 0x00, 0x20, 0x04, 0x00, 0x80, 0x10,
+ 0x00, 0x60, 0xF8, 0x80, 0x01, 0x00, 0x80, 0xC0, 0x40, 0x60, 0x20, 0x30,
+ 0x00, 0x10, 0x18, 0x08, 0x0C, 0x04, 0x04, 0x00, 0x7E, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0xFF, 0xFC,
+ 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x7E, 0xF8, 0x10, 0x41, 0x04, 0x1F, 0x81, 0x04, 0x10, 0x41, 0x07,
+ 0xE0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x7E, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0xF8, 0x10, 0x41, 0x04, 0x10,
+ 0x41, 0x04, 0x10, 0x41, 0x04, 0x10, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x7E, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7E, 0xCC, 0xFE,
+ 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0x25, 0x25,
+ 0x24, 0x89, 0x22, 0x40, 0xFF, 0x80, 0x00, 0x00, 0x0F, 0xF8, 0x91, 0x24,
+ 0x49, 0x29, 0x29, 0x00, 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7E,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E, 0x81, 0x81, 0x81, 0x8F, 0x91,
+ 0x91, 0x10, 0x91, 0x91, 0x8E, 0x80, 0x80, 0x7E, 0x7E, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E,
+ 0x7E, 0x08, 0x20, 0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x81, 0xF0, 0x7E,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x7E, 0x7E, 0x08, 0x20, 0x82, 0x07, 0xE0, 0x82, 0x08, 0x20, 0x81, 0xF0,
+ 0x7E, 0x08, 0x20, 0x82, 0x07, 0xE0, 0x82, 0x08, 0x20, 0x82, 0x00, 0x7E,
+ 0x80, 0x80, 0x80, 0x80, 0x80, 0x3E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0xFF, 0xFC, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x86, 0x8C, 0x98, 0xB0,
+ 0xA0, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x08, 0x20,
+ 0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x81, 0xF0, 0x7B, 0xD0, 0x86, 0x10,
+ 0xC2, 0x18, 0x43, 0x08, 0x61, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0,
+ 0x18, 0x03, 0x00, 0x40, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x7E, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x83, 0x7F,
+ 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x80, 0xB0, 0x98, 0x8C, 0x86,
+ 0x82, 0x81, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x7E, 0xF7, 0x84, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20,
+ 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x66, 0x24, 0x24,
+ 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x21, 0x84,
+ 0x30, 0x86, 0x10, 0xC2, 0x18, 0x42, 0xF7, 0x80, 0x81, 0xC3, 0x42, 0x66,
+ 0x24, 0x24, 0x00, 0x00, 0x24, 0x24, 0x66, 0x42, 0xC3, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7E,
+ 0xFE, 0x02, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x10, 0x30, 0x20, 0x60, 0x40,
+ 0x40, 0x7F, 0x7C, 0x21, 0x08, 0x42, 0x10, 0x84, 0x21, 0x08, 0x3C, 0x80,
+ 0x60, 0x10, 0x04, 0x03, 0x00, 0x80, 0x40, 0x00, 0x0C, 0x03, 0x00, 0x80,
+ 0x60, 0x10, 0x0C, 0xF0, 0x42, 0x10, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8,
+ 0x06, 0xC0, 0xE1, 0xEC, 0x00, 0xC0, 0xFF, 0xC0, 0xFE, 0x18, 0x61, 0x86,
+ 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0x7E, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x7E,
+ 0x08, 0x20, 0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x81, 0xF0, 0x7E, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E,
+ 0x7E, 0x08, 0x20, 0x82, 0x07, 0xE0, 0x82, 0x08, 0x20, 0x81, 0xF0, 0x7E,
+ 0x08, 0x20, 0x82, 0x07, 0xE0, 0x82, 0x08, 0x20, 0x82, 0x00, 0x7E, 0x80,
+ 0x80, 0x80, 0x80, 0x80, 0x3E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0xFF, 0xFC, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x86, 0x8C, 0x98, 0xB0, 0xA0,
+ 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0x08, 0x20, 0x82,
+ 0x08, 0x20, 0x82, 0x08, 0x20, 0x81, 0xF0, 0x7B, 0xD0, 0x86, 0x10, 0xC2,
+ 0x18, 0x43, 0x08, 0x61, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18,
+ 0x03, 0x00, 0x40, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x7E, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x83, 0x7F, 0x7E,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x80, 0xB0, 0x98, 0x8C, 0x86, 0x82,
+ 0x81, 0x7E, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7E, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x7E, 0xF7, 0x84, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10,
+ 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x81, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x7E, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x42, 0x66, 0x24, 0x24, 0x80,
+ 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x21, 0x84, 0x30,
+ 0x86, 0x10, 0xC2, 0x18, 0x42, 0xF7, 0x80, 0x81, 0xC3, 0x42, 0x66, 0x24,
+ 0x24, 0x00, 0x00, 0x24, 0x24, 0x66, 0x42, 0xC3, 0x81, 0x81, 0x81, 0x81,
+ 0x81, 0x81, 0x81, 0x7E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7E, 0xFE,
+ 0x02, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x10, 0x30, 0x20, 0x60, 0x40, 0x40,
+ 0x7F, 0x1E, 0x40, 0x81, 0x02, 0x04, 0x08, 0x60, 0x20, 0x40, 0x81, 0x02,
+ 0x03, 0xC0, 0xFF, 0xFF, 0xF0, 0x10, 0x20, 0x40, 0x81, 0x02, 0x03, 0x08,
+ 0x10, 0x20, 0x40, 0x9E, 0x00, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86,
+ 0x18, 0x61, 0x87, 0xF0 };
+
+const GFXglyph Seven_Segment10pt7bGlyphs[] PROGMEM = {
+ { 0, 1, 1, 6, 0, 0 }, // 0x20 ' '
+ { 1, 1, 14, 4, 1, -13 }, // 0x21 '!'
+ { 3, 3, 1, 6, 1, -12 }, // 0x22 '"'
+ { 4, 9, 9, 11, 1, -8 }, // 0x23 '#'
+ { 15, 8, 18, 10, 1, -15 }, // 0x24 '$'
+ { 33, 12, 14, 14, 1, -13 }, // 0x25 '%'
+ { 54, 44, 14, 47, 1, -13 }, // 0x26 '&'
+ { 131, 6, 14, 7, 1, -13 }, // 0x27 '''
+ { 142, 5, 14, 8, 1, -13 }, // 0x28 '('
+ { 151, 5, 14, 8, 1, -13 }, // 0x29 ')'
+ { 160, 5, 7, 8, 2, -16 }, // 0x2A '*'
+ { 165, 11, 11, 13, 1, -11 }, // 0x2B '+'
+ { 181, 2, 2, 5, 1, -1 }, // 0x2C ','
+ { 182, 5, 1, 8, 1, -6 }, // 0x2D '-'
+ { 183, 1, 1, 4, 1, 0 }, // 0x2E '.'
+ { 184, 9, 14, 11, 1, -13 }, // 0x2F '/'
+ { 200, 8, 14, 10, 1, -13 }, // 0x30 '0'
+ { 214, 1, 14, 4, 1, -13 }, // 0x31 '1'
+ { 216, 8, 14, 10, 1, -13 }, // 0x32 '2'
+ { 230, 6, 14, 9, 2, -13 }, // 0x33 '3'
+ { 241, 8, 14, 10, 1, -13 }, // 0x34 '4'
+ { 255, 8, 14, 10, 1, -13 }, // 0x35 '5'
+ { 269, 8, 14, 10, 1, -13 }, // 0x36 '6'
+ { 283, 6, 14, 9, 2, -13 }, // 0x37 '7'
+ { 294, 8, 14, 10, 1, -13 }, // 0x38 '8'
+ { 308, 8, 14, 10, 1, -13 }, // 0x39 '9'
+ { 322, 1, 6, 4, 1, -5 }, // 0x3A ':'
+ { 323, 6, 14, 7, 1, -13 }, // 0x3B ';'
+ { 334, 3, 14, 6, 1, -13 }, // 0x3C '<'
+ { 340, 9, 5, 11, 1, -7 }, // 0x3D '='
+ { 346, 3, 14, 6, 1, -13 }, // 0x3E '>'
+ { 352, 8, 14, 10, 1, -13 }, // 0x3F '?'
+ { 366, 8, 14, 10, 1, -13 }, // 0x40 '@'
+ { 380, 8, 14, 10, 1, -13 }, // 0x41 'A'
+ { 394, 8, 14, 10, 1, -13 }, // 0x42 'B'
+ { 408, 6, 14, 9, 1, -13 }, // 0x43 'C'
+ { 419, 8, 14, 10, 1, -13 }, // 0x44 'D'
+ { 433, 6, 14, 9, 1, -13 }, // 0x45 'E'
+ { 444, 6, 14, 9, 1, -13 }, // 0x46 'F'
+ { 455, 8, 14, 10, 1, -13 }, // 0x47 'G'
+ { 469, 8, 14, 10, 1, -13 }, // 0x48 'H'
+ { 483, 1, 14, 4, 1, -13 }, // 0x49 'I'
+ { 485, 8, 14, 10, 1, -13 }, // 0x4A 'J'
+ { 499, 8, 14, 10, 1, -13 }, // 0x4B 'K'
+ { 513, 6, 14, 9, 1, -13 }, // 0x4C 'L'
+ { 524, 11, 14, 14, 1, -13 }, // 0x4D 'M'
+ { 544, 8, 14, 10, 1, -13 }, // 0x4E 'N'
+ { 558, 8, 14, 10, 1, -13 }, // 0x4F 'O'
+ { 572, 8, 14, 10, 1, -13 }, // 0x50 'P'
+ { 586, 8, 14, 10, 1, -13 }, // 0x51 'Q'
+ { 600, 8, 14, 10, 1, -13 }, // 0x52 'R'
+ { 614, 8, 14, 10, 1, -13 }, // 0x53 'S'
+ { 628, 9, 14, 12, 1, -13 }, // 0x54 'T'
+ { 644, 8, 14, 10, 1, -13 }, // 0x55 'U'
+ { 658, 8, 14, 10, 1, -13 }, // 0x56 'V'
+ { 672, 11, 14, 14, 1, -13 }, // 0x57 'W'
+ { 692, 8, 14, 10, 1, -13 }, // 0x58 'X'
+ { 706, 8, 14, 10, 1, -13 }, // 0x59 'Y'
+ { 720, 8, 14, 10, 1, -13 }, // 0x5A 'Z'
+ { 734, 5, 14, 8, 1, -13 }, // 0x5B '['
+ { 743, 9, 14, 11, 1, -13 }, // 0x5C '\'
+ { 759, 5, 14, 8, 1, -13 }, // 0x5D ']'
+ { 768, 14, 3, 16, 1, -8 }, // 0x5E '^'
+ { 774, 10, 1, 12, 1, 0 }, // 0x5F '_'
+ { 776, 6, 14, 7, 1, -13 }, // 0x60 '`'
+ { 787, 8, 14, 10, 1, -13 }, // 0x61 'a'
+ { 801, 8, 14, 10, 1, -13 }, // 0x62 'b'
+ { 815, 6, 14, 9, 1, -13 }, // 0x63 'c'
+ { 826, 8, 14, 10, 1, -13 }, // 0x64 'd'
+ { 840, 6, 14, 9, 1, -13 }, // 0x65 'e'
+ { 851, 6, 14, 9, 1, -13 }, // 0x66 'f'
+ { 862, 8, 14, 10, 1, -13 }, // 0x67 'g'
+ { 876, 8, 14, 10, 1, -13 }, // 0x68 'h'
+ { 890, 1, 14, 4, 1, -13 }, // 0x69 'i'
+ { 892, 8, 14, 10, 1, -13 }, // 0x6A 'j'
+ { 906, 8, 14, 10, 1, -13 }, // 0x6B 'k'
+ { 920, 6, 14, 9, 1, -13 }, // 0x6C 'l'
+ { 931, 11, 14, 14, 1, -13 }, // 0x6D 'm'
+ { 951, 8, 14, 10, 1, -13 }, // 0x6E 'n'
+ { 965, 8, 14, 10, 1, -13 }, // 0x6F 'o'
+ { 979, 8, 14, 10, 1, -13 }, // 0x70 'p'
+ { 993, 8, 14, 10, 1, -13 }, // 0x71 'q'
+ { 1007, 8, 14, 10, 1, -13 }, // 0x72 'r'
+ { 1021, 8, 14, 10, 1, -13 }, // 0x73 's'
+ { 1035, 9, 14, 12, 1, -13 }, // 0x74 't'
+ { 1051, 8, 14, 10, 1, -13 }, // 0x75 'u'
+ { 1065, 8, 14, 10, 1, -13 }, // 0x76 'v'
+ { 1079, 11, 14, 14, 1, -13 }, // 0x77 'w'
+ { 1099, 8, 14, 10, 1, -13 }, // 0x78 'x'
+ { 1113, 8, 14, 10, 1, -13 }, // 0x79 'y'
+ { 1127, 8, 14, 10, 1, -13 }, // 0x7A 'z'
+ { 1141, 7, 14, 10, 1, -13 }, // 0x7B '{'
+ { 1154, 1, 16, 4, 1, -15 }, // 0x7C '|'
+ { 1156, 7, 14, 10, 1, -13 }, // 0x7D '}'
+ { 1169, 6, 14, 7, 1, -13 } }; // 0x7E '~'
+
+const GFXfont Seven_Segment10pt7b PROGMEM = {
+ (uint8_t *)Seven_Segment10pt7bBitmaps,
+ (GFXglyph *)Seven_Segment10pt7bGlyphs,
+ 0x20, 0x7E, 20 };
+
+// Approx. 1852 bytes
diff --git a/src/castRay.cpp b/src/castRay.cpp
new file mode 100644
index 0000000..d8e7e20
--- /dev/null
+++ b/src/castRay.cpp
@@ -0,0 +1,20 @@
+#include "castRay.h"
+
+#define DARKMODE false
+void CastRay::drawLoop()
+{
+ display.fillScreen(GxEPD_WHITE);
+}
+
+void CastRay::drawWatchFace()
+{
+ display.fillScreen(GxEPD_WHITE);
+ display.setTextColor(GxEPD_BLACK);
+
+ display.setFont(&DSEG7_Classic_Bold_53);
+ display.setCursor(5, 53+5);
+ display.print("0x0x0x0x0");
+ displayPtr = &display;
+ usleep(1);
+ this->drawLoop();
+}
diff --git a/src/castRay.h b/src/castRay.h
new file mode 100644
index 0000000..10dc756
--- /dev/null
+++ b/src/castRay.h
@@ -0,0 +1,22 @@
+#ifndef CASTRAY_H
+#define CASTRAY_H
+
+#include <Watchy.h>
+#include "Seven_Segment10pt7b.h"
+#include "DSEG7_Classic_Regular_15.h"
+#include "DSEG7_Classic_Bold_25.h"
+#include "DSEG7_Classic_Regular_39.h"
+#include "icons.h"
+
+#include "pixelfunc.h"
+
+static GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> * displayPtr = nullptr;
+
+class CastRay : public Watchy{
+ using Watchy::Watchy;
+ public:
+ void drawWatchFace();
+ void drawLoop();
+};
+
+#endif
diff --git a/src/castRay.ino b/src/castRay.ino
new file mode 100644
index 0000000..6372336
--- /dev/null
+++ b/src/castRay.ino
@@ -0,0 +1,10 @@
+#include "castRay.h"
+#include "settings.h"
+
+CastRay watchy(settings);
+
+void setup(){
+ watchy.init();
+}
+
+void loop(){}
diff --git a/src/icons.h b/src/icons.h
new file mode 100644
index 0000000..66354b6
--- /dev/null
+++ b/src/icons.h
@@ -0,0 +1,176 @@
+// 'battery', 37x21px
+const unsigned char battery [] PROGMEM = {
+ 0x3f, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xe0,
+ 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0xe0, 0x00,
+ 0x00, 0x00, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x38, 0xe0, 0x00, 0x00,
+ 0x00, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x38, 0xe0, 0x00, 0x00, 0x00,
+ 0x38, 0xe0, 0x00, 0x00, 0x00, 0x38, 0xe0, 0x00, 0x00, 0x00, 0xf8, 0xe0, 0x00, 0x00, 0x00, 0xf8,
+ 0xe0, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f,
+ 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xff, 0x80
+};
+// 'bluetooth', 13x21px
+const unsigned char bluetooth [] PROGMEM = {
+ 0x1f, 0xc0, 0x3f, 0xe0, 0x7f, 0xf0, 0xfd, 0xf8, 0xfc, 0xf8, 0xfc, 0x78, 0xdd, 0x38, 0xcd, 0x98,
+ 0xe5, 0x38, 0xf0, 0x78, 0xf8, 0xf8, 0xf8, 0xf8, 0xf0, 0x78, 0xe5, 0x38, 0xcd, 0x98, 0xfd, 0x38,
+ 0xfc, 0x78, 0xfc, 0xf8, 0x7d, 0xf0, 0x3f, 0xe0, 0x1f, 0xc0
+};
+// 'celsius', 26x20px
+const unsigned char celsius [] PROGMEM = {
+ 0x3f, 0x80, 0x1f, 0xc0, 0x7f, 0xc0, 0x3f, 0xc0, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00,
+ 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00,
+ 0xc0, 0x60, 0x60, 0x00, 0xff, 0xc0, 0x40, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x3f, 0xc0
+};
+// 'fahrenheit', 26x20px
+const unsigned char fahrenheit [] PROGMEM = {
+ 0x3f, 0x80, 0x1f, 0xc0, 0x7f, 0xc0, 0x3f, 0xc0, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00,
+ 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x60, 0x00,
+ 0xc0, 0x60, 0x60, 0x00, 0xff, 0xc0, 0x7f, 0xc0, 0x7f, 0x80, 0x3f, 0xc0, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+// 'cloudsun', 48x32px
+const unsigned char cloudsun [] PROGMEM = {
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x84, 0x40, 0x00, 0x00, 0x00, 0x10, 0x44, 0x42, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+ 0x00, 0x00, 0x00, 0x31, 0x80, 0x61, 0x00, 0x07, 0xe0, 0x19, 0x00, 0x32, 0x00, 0x38, 0x38, 0x02,
+ 0x00, 0x10, 0x00, 0x60, 0x04, 0x02, 0x00, 0x10, 0x00, 0x80, 0x03, 0xf2, 0x00, 0x10, 0x01, 0x00,
+ 0x01, 0x9e, 0x00, 0x10, 0x03, 0x00, 0x00, 0x03, 0x00, 0x10, 0x02, 0x00, 0x00, 0x01, 0x80, 0x10,
+ 0x02, 0x00, 0x00, 0x00, 0x80, 0x32, 0x04, 0x00, 0x00, 0x00, 0x40, 0x61, 0x04, 0x00, 0x00, 0x00,
+ 0x70, 0xc0, 0x0c, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x08, 0x60, 0x00,
+ 0x00, 0x00, 0x01, 0x04, 0x40, 0x00, 0x00, 0x00, 0x01, 0xc2, 0x40, 0x00, 0x00, 0x00, 0x00, 0xc0,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xfc, 0x00
+};
+// 'cloudy', 48x32px
+const unsigned char cloudy [] PROGMEM = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x00, 0x01, 0x80, 0x00, 0x3f,
+ 0xc0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x03, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0
+};
+// 'rain', 48x32px
+const unsigned char rain [] PROGMEM = {
+ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x07, 0x80, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x80,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x21, 0x08, 0x42, 0x10, 0x00, 0x00, 0x42, 0x10, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x84, 0x21, 0x00, 0x00, 0x04, 0x21,
+ 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x84, 0x21, 0x08, 0x00, 0x00
+};
+// 'snow', 48x32px
+const unsigned char snow [] PROGMEM = {
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x81, 0x02, 0x40, 0x00, 0x00, 0x02, 0x81, 0x02, 0x80, 0x00,
+ 0x00, 0x01, 0x81, 0x03, 0x00, 0x00, 0x00, 0x07, 0x81, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x41, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00, 0x00, 0x80,
+ 0x09, 0x20, 0x04, 0x00, 0x00, 0x40, 0x05, 0x40, 0x08, 0x00, 0x00, 0x20, 0x03, 0x80, 0x10, 0x00,
+ 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x03, 0x80, 0x10, 0x00, 0x00, 0x40, 0x05, 0x40,
+ 0x08, 0x00, 0x00, 0x80, 0x09, 0x20, 0x04, 0x00, 0x00, 0x00, 0x11, 0x10, 0x00, 0x00, 0x00, 0x00,
+ 0x21, 0x08, 0x00, 0x00, 0x00, 0x00, 0x41, 0x04, 0x00, 0x00, 0x00, 0x03, 0x81, 0x03, 0x80, 0x00,
+ 0x00, 0x01, 0x81, 0x03, 0x00, 0x00, 0x00, 0x02, 0x81, 0x02, 0x80, 0x00, 0x00, 0x04, 0x01, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x40, 0x00, 0x00, 0x00, 0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+// 'sunny', 48x32px
+const unsigned char sunny [] PROGMEM = {
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x18,
+ 0x20, 0x10, 0x60, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00,
+ 0x00, 0x02, 0x0f, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0c,
+ 0x00, 0x00, 0x00, 0x30, 0x80, 0x04, 0x30, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
+ 0x03, 0xf2, 0x00, 0x01, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x30,
+ 0x80, 0x04, 0x30, 0x00, 0x00, 0x00, 0xc0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00,
+ 0x00, 0x02, 0x0f, 0xc1, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00,
+ 0xc0, 0x00, 0x00, 0x18, 0x20, 0x10, 0x60, 0x00, 0x00, 0x00, 0x21, 0x08, 0x00, 0x00, 0x00, 0x00,
+ 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
+};
+// 'atmosphere', 48x32px
+const unsigned char atmosphere[] PROGMEM = {
+ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x07, 0x80, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x04, 0x07, 0xff, 0xf8, 0xf0, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x80,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0x9f, 0x1f, 0xff, 0xfc, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+// 'drizzle', 48x32px
+const unsigned char drizzle[] PROGMEM = {
+ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x07, 0x80, 0x00, 0xc0, 0x00, 0x00,
+ 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x80,
+ 0x00, 0x00, 0x00, 0x60, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x08, 0x00, 0x00
+};
+// 'thunderstorm', 48x32px
+const unsigned char thunderstorm[] PROGMEM = {
+ 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x03, 0x81, 0x80, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x30,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0x20, 0x00, 0x00, 0x18, 0x00, 0x00, 0x20, 0x00, 0x00, 0x08, 0x00,
+ 0x00, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, 0x00, 0x00, 0x07, 0x80, 0x00, 0xc0, 0x0f, 0x80,
+ 0x00, 0xc0, 0x03, 0x00, 0x0f, 0x80, 0x00, 0x20, 0x02, 0x00, 0x1f, 0x00, 0x00, 0x10, 0x04, 0x00,
+ 0x1e, 0x00, 0x00, 0x18, 0x04, 0x00, 0x3e, 0x00, 0x00, 0x08, 0x08, 0x00, 0x3c, 0x00, 0x00, 0x08,
+ 0x08, 0x00, 0x7c, 0x00, 0x00, 0x08, 0x04, 0x00, 0x78, 0x00, 0x00, 0x08, 0x04, 0x00, 0xf8, 0x00,
+ 0x00, 0x08, 0x04, 0x00, 0xff, 0x00, 0x00, 0x10, 0x02, 0x00, 0x1f, 0x00, 0x00, 0x30, 0x01, 0x80,
+ 0x1e, 0x00, 0x00, 0x60, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+// 'steps', 19x23px
+const unsigned char steps [] PROGMEM = {
+ 0x00, 0x03, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x0f, 0xe0, 0x78, 0x0f, 0xe0, 0xfc,
+ 0x0f, 0xe0, 0xfc, 0x0f, 0xe0, 0xfc, 0x0f, 0xe0, 0xfe, 0x0f, 0xe0, 0xfe, 0x07, 0xc0, 0xfe, 0x07,
+ 0xc0, 0xfe, 0x07, 0x80, 0xfe, 0x00, 0x00, 0x7c, 0x0e, 0x00, 0x7c, 0x0f, 0x80, 0x7c, 0x1f, 0x80,
+ 0x20, 0x1f, 0x00, 0x06, 0x0f, 0x00, 0x3e, 0x0e, 0x00, 0x3e, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x1e,
+ 0x00, 0x00, 0x1e, 0x00, 0x00
+};
+// 'wifi', 26x18px
+const unsigned char wifi [] PROGMEM = {
+ 0x00, 0x7f, 0x80, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xfc, 0x00, 0x1f, 0xc0, 0xfe, 0x00,
+ 0x7e, 0x00, 0x1f, 0x80, 0xf8, 0x3f, 0x07, 0xc0, 0x71, 0xff, 0xe3, 0x80, 0x23, 0xff, 0xf1, 0x00,
+ 0x07, 0xc0, 0xf8, 0x00, 0x0f, 0x00, 0x3c, 0x00, 0x06, 0x3f, 0x18, 0x00, 0x02, 0x7f, 0x90, 0x00,
+ 0x00, 0xff, 0xc0, 0x00, 0x00, 0xe1, 0xc0, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x0c, 0x00, 0x00,
+ 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00
+};
+// 'wifioff', 26x18px
+const unsigned char wifioff [] PROGMEM = {
+ 0x00, 0x7f, 0x87, 0xc0, 0x03, 0xff, 0xff, 0x80, 0x0f, 0xff, 0xff, 0x00, 0x1f, 0xc0, 0xfe, 0x00,
+ 0x7e, 0x00, 0x7f, 0x80, 0xf8, 0x3f, 0xf7, 0xc0, 0x71, 0xff, 0xe3, 0x80, 0x23, 0xff, 0xf1, 0x00,
+ 0x07, 0xcf, 0xf8, 0x00, 0x0f, 0x3e, 0x3c, 0x00, 0x06, 0x7f, 0x18, 0x00, 0x02, 0xff, 0x90, 0x00,
+ 0x01, 0xff, 0xc0, 0x00, 0x07, 0xe1, 0xc0, 0x00, 0x0f, 0xc0, 0x80, 0x00, 0x1f, 0x0c, 0x00, 0x00,
+ 0x3c, 0x1e, 0x00, 0x00, 0xf8, 0x0c, 0x00, 0x00
+};
diff --git a/src/pixelfunc.cpp b/src/pixelfunc.cpp
new file mode 100644
index 0000000..08bbee6
--- /dev/null
+++ b/src/pixelfunc.cpp
@@ -0,0 +1,82 @@
+#include "pixelfunc.h"
+
+RCL_Camera camera;
+static int dx = 1;
+static int dy = 0;
+static int dr = 1;
+static int frame = 0;
+
+void pixelFunc(RCL_PixelInfo *p)
+{
+ int c = GxEPD_WHITE;
+ if (p->isWall)
+ {
+ c = GxEPD_BLACK;
+ }
+ if (displayPtr != nullptr)
+ {
+ displayPtr->drawPixel(p->position.x, p->position.y, c);
+ }
+}
+
+RCL_Unit heightAt(int16_t x, int16_t y)
+{
+ int32_t index = y * LEVEL_W + x;
+
+ if (index < 0 || (index >= LEVEL_W * LEVEL_H))
+ return RCL_UNITS_PER_SQUARE * 2;
+
+ return level[y * LEVEL_W + x] * RCL_UNITS_PER_SQUARE * 2;
+}
+
+void draw()
+{
+ RCL_RayConstraints c;
+
+ RCL_initRayConstraints(&c);
+
+ c.maxHits = 1;
+ c.maxSteps = 100;
+
+ RCL_renderSimple(camera,heightAt,0,0,c);
+}
+
+void draw_doom()
+{
+ RCL_initCamera(&camera);
+ camera.position.x = 2 * RCL_UNITS_PER_SQUARE;
+ camera.position.y = 2 * RCL_UNITS_PER_SQUARE;
+ camera.direction = 0;
+ camera.resolution.x = SCREEN_W;
+ camera.resolution.y = SCREEN_H;
+
+ for (int i = 0; i < 10000; ++i)
+ {
+ draw();
+
+ int squareX = RCL_divRoundDown(camera.position.x,RCL_UNITS_PER_SQUARE);
+ int squareY = RCL_divRoundDown(camera.position.y,RCL_UNITS_PER_SQUARE);
+
+ if (rand() % 100 == 0)
+ {
+ dx = 1 - rand() % 3;
+ dy = 1 - rand() % 3;
+ dr = 1 - rand() % 3;
+ }
+
+ while (heightAt(squareX + dx,squareY + dy) > 0)
+ {
+ dx = 1 - rand() % 3;
+ dy = 1 - rand() % 3;
+ dr = 1 - rand() % 3;
+ }
+
+ camera.position.x += dx * 200;
+ camera.position.y += dy * 200;
+ camera.direction += dr * 10;
+
+ camera.height = RCL_UNITS_PER_SQUARE + RCL_sin(frame * 16) / 2;
+
+ frame++;
+ }
+}
diff --git a/src/pixelfunc.h b/src/pixelfunc.h
new file mode 100644
index 0000000..4316679
--- /dev/null
+++ b/src/pixelfunc.h
@@ -0,0 +1,51 @@
+#ifndef PIXEL_FUNC_H
+#define PIXEL_FUNC_H
+
+/* raycastlib */
+
+#define RCL_COMPUTE_FLOOR_DEPTH 0 // turn off what we don't need
+#define RCL_COMPUTE_CEILING_DEPTH 0
+#define RCL_PIXEL_FUNCTION pixelFunc // set our pixel function
+#include "raycastlib.h"
+#include "castRay.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <Watchy.h>
+
+#define SCREEN_W 100
+#define SCREEN_H 100
+
+#define PIXELS_TOTAL ((SCREEN_W + 1) * (SCREEN_H + 1))
+#define LEVEL_W 20
+#define LEVEL_H 15
+
+const int8_t level[LEVEL_W * LEVEL_H] = // here 1 means wall, 0 floor
+{
+/* 11 13 15 17 19
+ 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 */
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, // 0
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0, // 1
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, // 2
+ 1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0, // 3
+ 0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0, // 4
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0, // 5
+ 1,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0, // 6
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0, // 7
+ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1, // 8
+ 0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, // 9
+ 0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1, // 10
+ 0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,1,0,0,1, // 11
+ 0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0, // 12
+ 0,0,0,0,0,1,0,0,0,1,1,1,0,0,1,0,0,0,0,0, // 13
+ 0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0 // 14
+};
+
+void run_doom();
+void draw();
+RCL_Unit heightAt(int16_t x, int16_t y);
+void pixelFunc(RCL_PixelInfo *p);
+
+/* end raycastlib */
+
+#endif
diff --git a/src/raycastlib.cpp b/src/raycastlib.cpp
new file mode 100644
index 0000000..07f1b87
--- /dev/null
+++ b/src/raycastlib.cpp
@@ -0,0 +1,1563 @@
+#include "raycastlib.h"
+
+//=============================================================================
+// privates
+
+#define _RCL_UNUSED(what) (void)(what);
+
+#ifndef RCL_PIXEL_FUNCTION
+#define RCL_PIXEL_FUNCTION pixelFunc
+#endif
+void pixelFunc(RCL_PixelInfo *p);
+
+// global helper variables, for precomputing stuff etc.
+RCL_Camera _RCL_camera;
+RCL_Unit _RCL_horizontalDepthStep = 0;
+RCL_Unit _RCL_startFloorHeight = 0;
+RCL_Unit _RCL_startCeil_Height = 0;
+RCL_Unit _RCL_camResYLimit = 0;
+RCL_Unit _RCL_middleRow = 0;
+RCL_ArrayFunction _RCL_floorFunction = 0;
+RCL_ArrayFunction _RCL_ceilFunction = 0;
+RCL_Unit _RCL_fHorizontalDepthStart = 0;
+RCL_Unit _RCL_cHorizontalDepthStart = 0;
+int16_t _RCL_cameraHeightScreen = 0;
+RCL_ArrayFunction _RCL_rollFunction = 0; // says door rolling
+RCL_Unit *_RCL_floorPixelDistances = 0;
+RCL_Unit _RCL_fovCorrectionFactors[2] = {0,0}; //correction for hor/vert fov
+
+RCL_Unit RCL_clamp(RCL_Unit value, RCL_Unit valueMin, RCL_Unit valueMax)
+{
+ if (value >= valueMin)
+ {
+ if (value <= valueMax)
+ return value;
+ else
+ return valueMax;
+ }
+ else
+ return valueMin;
+}
+
+static inline RCL_Unit RCL_abs(RCL_Unit value)
+{
+ return value * (((value >= 0) << 1) - 1);
+}
+
+/// Like mod, but behaves differently for negative values.
+static inline RCL_Unit RCL_wrap(RCL_Unit value, RCL_Unit mod)
+{
+ RCL_Unit cmp = value < 0;
+ return cmp * mod + (value % mod) - cmp;
+}
+
+/// Performs division, rounding down, NOT towards zero.
+RCL_Unit RCL_divRoundDown(RCL_Unit value, RCL_Unit divisor)
+{
+ return value / divisor - ((value >= 0) ? 0 : 1);
+}
+
+// Bhaskara's cosine approximation formula
+#define trigHelper(x) (((RCL_Unit) RCL_UNITS_PER_SQUARE) *\
+ (RCL_UNITS_PER_SQUARE / 2 * RCL_UNITS_PER_SQUARE / 2 - 4 * (x) * (x)) /\
+ (RCL_UNITS_PER_SQUARE / 2 * RCL_UNITS_PER_SQUARE / 2 + (x) * (x)))
+
+#if RCL_USE_COS_LUT == 1
+
+ #ifdef RCL_RAYCAST_TINY
+ const RCL_Unit cosLUT[64] =
+ {
+ 16,14,11,6,0,-6,-11,-14,-15,-14,-11,-6,0,6,11,14
+ };
+ #else
+ const RCL_Unit cosLUT[64] =
+ {
+ 1024,1019,1004,979,946,903,851,791,724,649,568,482,391,297,199,100,0,-100,
+ -199,-297,-391,-482,-568,-649,-724,-791,-851,-903,-946,-979,-1004,-1019,
+ -1023,-1019,-1004,-979,-946,-903,-851,-791,-724,-649,-568,-482,-391,-297,
+ -199,-100,0,100,199,297,391,482,568,649,724,791,851,903,946,979,1004,1019
+ };
+ #endif
+
+#elif RCL_USE_COS_LUT == 2
+const RCL_Unit cosLUT[128] =
+{
+ 1024,1022,1019,1012,1004,993,979,964,946,925,903,878,851,822,791,758,724,
+ 687,649,609,568,526,482,437,391,344,297,248,199,150,100,50,0,-50,-100,-150,
+ -199,-248,-297,-344,-391,-437,-482,-526,-568,-609,-649,-687,-724,-758,-791,
+ -822,-851,-878,-903,-925,-946,-964,-979,-993,-1004,-1012,-1019,-1022,-1023,
+ -1022,-1019,-1012,-1004,-993,-979,-964,-946,-925,-903,-878,-851,-822,-791,
+ -758,-724,-687,-649,-609,-568,-526,-482,-437,-391,-344,-297,-248,-199,-150,
+ -100,-50,0,50,100,150,199,248,297,344,391,437,482,526,568,609,649,687,724,
+ 758,791,822,851,878,903,925,946,964,979,993,1004,1012,1019,1022
+};
+#endif
+
+RCL_Unit RCL_cos(RCL_Unit input)
+{
+ input = RCL_wrap(input,RCL_UNITS_PER_SQUARE);
+
+#if RCL_USE_COS_LUT == 1
+
+ #ifdef RCL_RAYCAST_TINY
+ return cosLUT[input];
+ #else
+ return cosLUT[input / 16];
+ #endif
+
+#elif RCL_USE_COS_LUT == 2
+ return cosLUT[input / 8];
+#else
+ if (input < RCL_UNITS_PER_SQUARE / 4)
+ return trigHelper(input);
+ else if (input < RCL_UNITS_PER_SQUARE / 2)
+ return -1 * trigHelper(RCL_UNITS_PER_SQUARE / 2 - input);
+ else if (input < 3 * RCL_UNITS_PER_SQUARE / 4)
+ return -1 * trigHelper(input - RCL_UNITS_PER_SQUARE / 2);
+ else
+ return trigHelper(RCL_UNITS_PER_SQUARE - input);
+#endif
+}
+
+#undef trigHelper
+
+RCL_Unit RCL_sin(RCL_Unit input)
+{
+ return RCL_cos(input - RCL_UNITS_PER_SQUARE / 4);
+}
+
+RCL_Unit RCL_tan(RCL_Unit input)
+{
+ return (RCL_sin(input) * RCL_UNITS_PER_SQUARE) / RCL_nonZero(RCL_cos(input)
+);
+
+ return (RCL_sin(input) * RCL_UNITS_PER_SQUARE) / RCL_nonZero(RCL_cos(input));
+}
+
+RCL_Unit RCL_ctg(RCL_Unit input)
+{
+ return (RCL_cos(input) * RCL_UNITS_PER_SQUARE) / RCL_sin(input);
+}
+
+RCL_Vector2D RCL_angleToDirection(RCL_Unit angle)
+{
+ RCL_Vector2D result;
+
+ result.x = RCL_cos(angle);
+ result.y = -1 * RCL_sin(angle);
+
+ return result;
+}
+
+uint16_t RCL_sqrt(RCL_Unit value)
+{
+#ifdef RCL_RAYCAST_TINY
+ uint16_t result = 0;
+ uint16_t a = value;
+ uint16_t b = 1u << 14;
+#else
+ uint32_t result = 0;
+ uint32_t a = value;
+ uint32_t b = 1u << 30;
+#endif
+
+ while (b > a)
+ b >>= 2;
+
+ while (b != 0)
+ {
+ if (a >= result + b)
+ {
+ a -= result + b;
+ result = result + 2 * b;
+ }
+
+ b >>= 2;
+ result >>= 1;
+ }
+
+ return result;
+}
+
+RCL_Unit RCL_dist(RCL_Vector2D p1, RCL_Vector2D p2)
+{
+ RCL_Unit dx = p2.x - p1.x;
+ RCL_Unit dy = p2.y - p1.y;
+
+#if RCL_USE_DIST_APPROX == 2
+ // octagonal approximation
+
+ dx = RCL_abs(dx);
+ dy = RCL_abs(dy);
+
+ return dy > dx ? dx / 2 + dy : dy / 2 + dx;
+#elif RCL_USE_DIST_APPROX == 1
+ // more accurate approximation
+
+ RCL_Unit a, b, result;
+
+ dx = ((dx < 0) * 2 - 1) * dx;
+ dy = ((dy < 0) * 2 - 1) * dy;
+
+ if (dx < dy)
+ {
+ a = dy;
+ b = dx;
+ }
+ else
+ {
+ a = dx;
+ b = dy;
+ }
+
+ result = a + (44 * b) / 102;
+
+ if (a < (b << 4))
+ result -= (5 * a) / 128;
+
+ return result;
+#else
+ dx = dx * dx;
+ dy = dy * dy;
+
+ return RCL_sqrt((RCL_Unit) (dx + dy));
+#endif
+}
+
+RCL_Unit RCL_len(RCL_Vector2D v)
+{
+ RCL_Vector2D zero;
+ zero.x = 0;
+ zero.y = 0;
+
+ return RCL_dist(zero,v);
+}
+
+static inline int8_t RCL_pointIsLeftOfRay(RCL_Vector2D point, RCL_Ray ray)
+{
+ RCL_Unit dX = point.x - ray.start.x;
+ RCL_Unit dY = point.y - ray.start.y;
+ return (ray.direction.x * dY - ray.direction.y * dX) > 0;
+ // ^ Z component of cross-product
+}
+
+void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
+ RCL_ArrayFunction typeFunc, RCL_HitResult *hitResults,
+ uint16_t *hitResultsLen, RCL_RayConstraints constraints)
+{
+ RCL_Vector2D currentPos = ray.start;
+ RCL_Vector2D currentSquare;
+
+ currentSquare.x = RCL_divRoundDown(ray.start.x,RCL_UNITS_PER_SQUARE);
+ currentSquare.y = RCL_divRoundDown(ray.start.y,RCL_UNITS_PER_SQUARE);
+
+ *hitResultsLen = 0;
+
+ RCL_Unit squareType = arrayFunc(currentSquare.x,currentSquare.y);
+
+ // DDA variables
+ RCL_Vector2D nextSideDist; // dist. from start to the next side in given axis
+ RCL_Vector2D delta;
+ RCL_Vector2D step; // -1 or 1 for each axis
+ int8_t stepHorizontal = 0; // whether the last step was hor. or vert.
+
+ nextSideDist.x = 0;
+ nextSideDist.y = 0;
+
+ RCL_Unit dirVecLengthNorm = RCL_len(ray.direction) * RCL_UNITS_PER_SQUARE;
+
+ delta.x = RCL_abs(dirVecLengthNorm / RCL_nonZero(ray.direction.x));
+ delta.y = RCL_abs(dirVecLengthNorm / RCL_nonZero(ray.direction.y));
+
+ // init DDA
+
+ if (ray.direction.x < 0)
+ {
+ step.x = -1;
+ nextSideDist.x = (RCL_wrap(ray.start.x,RCL_UNITS_PER_SQUARE) * delta.x) /
+ RCL_UNITS_PER_SQUARE;
+ }
+ else
+ {
+ step.x = 1;
+ nextSideDist.x =
+ ((RCL_wrap(RCL_UNITS_PER_SQUARE - ray.start.x,RCL_UNITS_PER_SQUARE)) *
+ delta.x) / RCL_UNITS_PER_SQUARE;
+ }
+
+ if (ray.direction.y < 0)
+ {
+ step.y = -1;
+ nextSideDist.y = (RCL_wrap(ray.start.y,RCL_UNITS_PER_SQUARE) * delta.y) /
+ RCL_UNITS_PER_SQUARE;
+ }
+ else
+ {
+ step.y = 1;
+ nextSideDist.y =
+ ((RCL_wrap(RCL_UNITS_PER_SQUARE - ray.start.y,RCL_UNITS_PER_SQUARE)) *
+ delta.y) / RCL_UNITS_PER_SQUARE;
+ }
+
+ // DDA loop
+
+ #define RECIP_SCALE 65536
+
+ RCL_Unit rayDirXRecip = RECIP_SCALE / RCL_nonZero(ray.direction.x);
+ RCL_Unit rayDirYRecip = RECIP_SCALE / RCL_nonZero(ray.direction.y);
+ // ^ we precompute reciprocals to avoid divisions in the loop
+
+ for (uint16_t i = 0; i < constraints.maxSteps; ++i)
+ {
+ RCL_Unit currentType = arrayFunc(currentSquare.x,currentSquare.y);
+
+ if (RCL_unlikely(currentType != squareType))
+ {
+ // collision
+
+ RCL_HitResult h;
+
+ h.arrayValue = currentType;
+ h.doorRoll = 0;
+ h.position = currentPos;
+ h.square = currentSquare;
+
+ if (stepHorizontal)
+ {
+ h.position.x = currentSquare.x * RCL_UNITS_PER_SQUARE;
+ h.direction = 3;
+
+ if (step.x == -1)
+ {
+ h.direction = 1;
+ h.position.x += RCL_UNITS_PER_SQUARE;
+ }
+
+ RCL_Unit diff = h.position.x - ray.start.x;
+
+ h.position.y = // avoid division by multiplying with reciprocal
+ ray.start.y + (ray.direction.y * diff * rayDirXRecip) / RECIP_SCALE;
+
+#if RCL_RECTILINEAR
+ /* Here we compute the fish eye corrected distance (perpendicular to
+ the projection plane) as the Euclidean distance (of hit from camera
+ position) divided by the length of the ray direction vector. This can
+ be computed without actually computing Euclidean distances as a
+ hypothenuse A (distance) divided by hypothenuse B (length) is equal to
+ leg A (distance along principal axis) divided by leg B (length along
+ the same principal axis). */
+
+#define CORRECT(dir1,dir2)\
+ RCL_Unit tmp = diff / 4; /* 4 to prevent overflow */ \
+ h.distance = ((tmp / 8) != 0) ? /* prevent a bug with small dists */ \
+ ((tmp * RCL_UNITS_PER_SQUARE * rayDir ## dir1 ## Recip) / (RECIP_SCALE / 4)):\
+ RCL_abs(h.position.dir2 - ray.start.dir2);
+
+ CORRECT(X,y)
+
+#endif // RCL_RECTILINEAR
+ }
+ else
+ {
+ h.position.y = currentSquare.y * RCL_UNITS_PER_SQUARE;
+ h.direction = 2;
+
+ if (step.y == -1)
+ {
+ h.direction = 0;
+ h.position.y += RCL_UNITS_PER_SQUARE;
+ }
+
+ RCL_Unit diff = h.position.y - ray.start.y;
+
+ h.position.x =
+ ray.start.x + (ray.direction.x * diff * rayDirYRecip) / RECIP_SCALE;
+
+#if RCL_RECTILINEAR
+
+ CORRECT(Y,x) // same as above but for different axis
+
+#undef CORRECT
+
+#endif // RCL_RECTILINEAR
+ }
+
+#if !RCL_RECTILINEAR
+ h.distance = RCL_dist(h.position,ray.start);
+#endif
+ if (typeFunc != 0)
+ h.type = typeFunc(currentSquare.x,currentSquare.y);
+
+#if RCL_COMPUTE_WALL_TEXCOORDS == 1
+ switch (h.direction)
+ {
+ case 0: h.textureCoord =
+ RCL_wrap(-1 * h.position.x,RCL_UNITS_PER_SQUARE); break;
+
+ case 1: h.textureCoord =
+ RCL_wrap(h.position.y,RCL_UNITS_PER_SQUARE); break;
+
+ case 2: h.textureCoord =
+ RCL_wrap(h.position.x,RCL_UNITS_PER_SQUARE); break;
+
+ case 3: h.textureCoord =
+ RCL_wrap(-1 * h.position.y,RCL_UNITS_PER_SQUARE); break;
+
+ default: h.textureCoord = 0; break;
+ }
+
+ if (_RCL_rollFunction != 0)
+ {
+ h.doorRoll = _RCL_rollFunction(currentSquare.x,currentSquare.y);
+
+ if (h.direction == 0 || h.direction == 1)
+ h.doorRoll *= -1;
+ }
+
+#else
+ h.textureCoord = 0;
+#endif
+
+ hitResults[*hitResultsLen] = h;
+
+ *hitResultsLen += 1;
+
+ squareType = currentType;
+
+ if (*hitResultsLen >= constraints.maxHits)
+ break;
+ }
+
+ // DDA step
+
+ if (nextSideDist.x < nextSideDist.y)
+ {
+ nextSideDist.x += delta.x;
+ currentSquare.x += step.x;
+ stepHorizontal = 1;
+ }
+ else
+ {
+ nextSideDist.y += delta.y;
+ currentSquare.y += step.y;
+ stepHorizontal = 0;
+ }
+ }
+}
+
+RCL_HitResult RCL_castRay(RCL_Ray ray, RCL_ArrayFunction arrayFunc)
+{
+ RCL_HitResult result;
+ uint16_t len;
+ RCL_RayConstraints c;
+
+ c.maxSteps = 1000;
+ c.maxHits = 1;
+
+ RCL_castRayMultiHit(ray,arrayFunc,0,&result,&len,c);
+
+ if (len == 0)
+ result.distance = -1;
+
+ return result;
+}
+
+void RCL_castRaysMultiHit(RCL_Camera cam, RCL_ArrayFunction arrayFunc,
+ RCL_ArrayFunction typeFunction, RCL_ColumnFunction columnFunc,
+ RCL_RayConstraints constraints)
+{
+ RCL_Vector2D dir1 =
+ RCL_angleToDirection(cam.direction - RCL_HORIZONTAL_FOV_HALF);
+
+ RCL_Vector2D dir2 =
+ RCL_angleToDirection(cam.direction + RCL_HORIZONTAL_FOV_HALF);
+
+ /* We scale the side distances so that the middle one is
+ RCL_UNITS_PER_SQUARE, which has to be this way. */
+
+ RCL_Unit cos = RCL_nonZero(RCL_cos(RCL_HORIZONTAL_FOV_HALF));
+
+ dir1.x = (dir1.x * RCL_UNITS_PER_SQUARE) / cos;
+ dir1.y = (dir1.y * RCL_UNITS_PER_SQUARE) / cos;
+
+ dir2.x = (dir2.x * RCL_UNITS_PER_SQUARE) / cos;
+ dir2.y = (dir2.y * RCL_UNITS_PER_SQUARE) / cos;
+
+ RCL_Unit dX = dir2.x - dir1.x;
+ RCL_Unit dY = dir2.y - dir1.y;
+
+ RCL_HitResult hits[constraints.maxHits];
+ uint16_t hitCount;
+
+ RCL_Ray r;
+ r.start = cam.position;
+
+ RCL_Unit currentDX = 0;
+ RCL_Unit currentDY = 0;
+
+ for (int16_t i = 0; i < cam.resolution.x; ++i)
+ {
+ /* Here by linearly interpolating the direction vector its length changes,
+ which in result achieves correcting the fish eye effect (computing
+ perpendicular distance). */
+
+ r.direction.x = dir1.x + currentDX / cam.resolution.x;
+ r.direction.y = dir1.y + currentDY / cam.resolution.x;
+
+ RCL_castRayMultiHit(r,arrayFunc,typeFunction,hits,&hitCount,constraints);
+
+ columnFunc(hits,hitCount,i,r);
+
+ currentDX += dX;
+ currentDY += dY;
+ }
+}
+
+/**
+ Helper function that determines intersection with both ceiling and floor.
+*/
+RCL_Unit _RCL_floorCeilFunction(int16_t x, int16_t y)
+{
+ RCL_Unit f = _RCL_floorFunction(x,y);
+
+ if (_RCL_ceilFunction == 0)
+ return f;
+
+ RCL_Unit c = _RCL_ceilFunction(x,y);
+
+#ifndef RCL_RAYCAST_TINY
+ return ((f & 0x0000ffff) << 16) | (c & 0x0000ffff);
+#else
+ return ((f & 0x00ff) << 8) | (c & 0x00ff);
+#endif
+}
+
+RCL_Unit _floorHeightNotZeroFunction(int16_t x, int16_t y)
+{
+ return _RCL_floorFunction(x,y) == 0 ? 0 :
+ RCL_nonZero((x & 0x00FF) | ((y & 0x00FF) << 8));
+ // ^ this makes collisions between all squares - needed for rolling doors
+}
+
+RCL_Unit RCL_adjustDistance(RCL_Unit distance, RCL_Camera *camera,
+ RCL_Ray *ray)
+{
+ /* FIXME/TODO: The adjusted (=orthogonal, camera-space) distance could
+ possibly be computed more efficiently by not computing Euclidean
+ distance at all, but rather compute the distance of the collision
+ point from the projection plane (line). */
+
+ RCL_Unit result =
+ (distance *
+ RCL_vectorsAngleCos(RCL_angleToDirection(camera->direction),
+ ray->direction)) / RCL_UNITS_PER_SQUARE;
+
+ return RCL_nonZero(result);
+ // ^ prevent division by zero
+}
+
+/// Helper for drawing floor or ceiling. Returns the last drawn pixel position.
+static inline int16_t _RCL_drawHorizontalColumn(
+ RCL_Unit yCurrent,
+ RCL_Unit yTo,
+ RCL_Unit limit1, // TODO: int16_t?
+ RCL_Unit limit2,
+ RCL_Unit verticalOffset,
+ int16_t increment,
+ int8_t computeDepth,
+ int8_t computeCoords,
+ int16_t depthIncrementMultiplier,
+ RCL_Ray *ray,
+ RCL_PixelInfo *pixelInfo
+)
+{
+ _RCL_UNUSED(ray);
+
+ RCL_Unit depthIncrement;
+ RCL_Unit dx;
+ RCL_Unit dy;
+
+ pixelInfo->isWall = 0;
+
+ int16_t limit = RCL_clamp(yTo,limit1,limit2);
+
+ RCL_Unit depth = 0; /* TODO: this is for clamping depth to 0 so that we don't
+ have negative depths, but we should do it more
+ elegantly and efficiently */
+
+ _RCL_UNUSED(depth);
+
+ /* for performance reasons have different version of the critical loop
+ to be able to branch early */
+ #define loop(doDepth,doCoords)\
+ {\
+ if (doDepth) /*constant condition - compiler should optimize it out*/\
+ {\
+ depth = pixelInfo->depth + RCL_abs(verticalOffset) *\
+ RCL_VERTICAL_DEPTH_MULTIPLY;\
+ depthIncrement = depthIncrementMultiplier *\
+ _RCL_horizontalDepthStep;\
+ }\
+ if (doCoords) /*constant condition - compiler should optimize it out*/\
+ {\
+ dx = pixelInfo->hit.position.x - _RCL_camera.position.x;\
+ dy = pixelInfo->hit.position.y - _RCL_camera.position.y;\
+ }\
+ for (int16_t i = yCurrent + increment;\
+ increment == -1 ? i >= limit : i <= limit; /* TODO: is efficient? */\
+ i += increment)\
+ {\
+ pixelInfo->position.y = i;\
+ if (doDepth) /*constant condition - compiler should optimize it out*/\
+ {\
+ depth += depthIncrement;\
+ pixelInfo->depth = RCL_zeroClamp(depth); \
+ /* ^ int comparison is fast, it is not braching! (= test instr.) */\
+ }\
+ if (doCoords) /*constant condition - compiler should optimize it out*/\
+ {\
+ RCL_Unit d = _RCL_floorPixelDistances[i];\
+ RCL_Unit d2 = RCL_nonZero(pixelInfo->hit.distance);\
+ pixelInfo->texCoords.x =\
+ _RCL_camera.position.x + ((d * dx) / d2);\
+ pixelInfo->texCoords.y =\
+ _RCL_camera.position.y + ((d * dy) / d2);\
+ }\
+ RCL_PIXEL_FUNCTION(pixelInfo);\
+ }\
+ }
+
+ if (computeDepth) // branch early
+ {
+ if (!computeCoords)
+ loop(1,0)
+ else
+ loop(1,1)
+ }
+ else
+ {
+ if (!computeCoords)
+ loop(0,0)
+ else
+ loop(1,1)
+ }
+
+ #undef loop
+
+ return limit;
+}
+
+/// Helper for drawing walls. Returns the last drawn pixel position.
+static inline int16_t _RCL_drawWall(
+ RCL_Unit yCurrent,
+ RCL_Unit yFrom,
+ RCL_Unit yTo,
+ RCL_Unit limit1, // TODO: int16_t?
+ RCL_Unit limit2,
+ RCL_Unit height,
+ int16_t increment,
+ RCL_PixelInfo *pixelInfo
+ )
+{
+ _RCL_UNUSED(height)
+
+ height = RCL_abs(height);
+
+ pixelInfo->isWall = 1;
+
+ RCL_Unit limit = RCL_clamp(yTo,limit1,limit2);
+
+ RCL_Unit wallLength = RCL_nonZero(RCL_abs(yTo - yFrom - 1));
+
+ RCL_Unit wallPosition = RCL_abs(yFrom - yCurrent) - increment;
+
+ RCL_Unit heightScaled = height * RCL_TEXTURE_INTERPOLATION_SCALE;
+ _RCL_UNUSED(heightScaled);
+
+ RCL_Unit coordStepScaled = RCL_COMPUTE_WALL_TEXCOORDS ?
+#if RCL_TEXTURE_VERTICAL_STRETCH == 1
+ ((RCL_UNITS_PER_SQUARE * RCL_TEXTURE_INTERPOLATION_SCALE) / wallLength)
+#else
+ (heightScaled / wallLength)
+#endif
+ : 0;
+
+ pixelInfo->texCoords.y = RCL_COMPUTE_WALL_TEXCOORDS ?
+ (wallPosition * coordStepScaled) : 0;
+
+ if (increment < 0)
+ {
+ coordStepScaled *= -1;
+ pixelInfo->texCoords.y =
+#if RCL_TEXTURE_VERTICAL_STRETCH == 1
+ (RCL_UNITS_PER_SQUARE * RCL_TEXTURE_INTERPOLATION_SCALE)
+ - pixelInfo->texCoords.y;
+#else
+ heightScaled - pixelInfo->texCoords.y;
+#endif
+ }
+ else
+ {
+ // with floor wall, don't start under 0
+ pixelInfo->texCoords.y = RCL_zeroClamp(pixelInfo->texCoords.y);
+ }
+
+ RCL_Unit textureCoordScaled = pixelInfo->texCoords.y;
+
+ for (RCL_Unit i = yCurrent + increment;
+ increment == -1 ? i >= limit : i <= limit; // TODO: is efficient?
+ i += increment)
+ {
+ pixelInfo->position.y = i;
+
+#if RCL_COMPUTE_WALL_TEXCOORDS == 1
+ pixelInfo->texCoords.y =
+ textureCoordScaled / RCL_TEXTURE_INTERPOLATION_SCALE;
+
+ textureCoordScaled += coordStepScaled;
+#endif
+
+ RCL_PIXEL_FUNCTION(pixelInfo);
+ }
+
+ return limit;
+}
+
+/// Fills a RCL_HitResult struct with info for a hit at infinity.
+static inline void _RCL_makeInfiniteHit(RCL_HitResult *hit, RCL_Ray *ray)
+{
+ hit->distance = RCL_UNITS_PER_SQUARE * RCL_UNITS_PER_SQUARE;
+ /* ^ horizon is at infinity, but we can't use too big infinity
+ (RCL_INFINITY) because it would overflow in the following mult. */
+ hit->position.x = (ray->direction.x * hit->distance) / RCL_UNITS_PER_SQUARE;
+ hit->position.y = (ray->direction.y * hit->distance) / RCL_UNITS_PER_SQUARE;
+
+ hit->direction = 0;
+ hit->textureCoord = 0;
+ hit->arrayValue = 0;
+ hit->doorRoll = 0;
+ hit->type = 0;
+}
+
+void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t x,
+ RCL_Ray ray)
+{
+ // last written Y position, can never go backwards
+ RCL_Unit fPosY = _RCL_camera.resolution.y;
+ RCL_Unit cPosY = -1;
+
+ // world coordinates (relative to camera height though)
+ RCL_Unit fZ1World = _RCL_startFloorHeight;
+ RCL_Unit cZ1World = _RCL_startCeil_Height;
+
+ RCL_PixelInfo p;
+ p.position.x = x;
+ p.height = 0;
+ p.wallHeight = 0;
+ p.texCoords.x = 0;
+ p.texCoords.y = 0;
+
+ // we'll be simulatenously drawing the floor and the ceiling now
+ for (RCL_Unit j = 0; j <= hitCount; ++j)
+ { // ^ = add extra iteration for horizon plane
+ int8_t drawingHorizon = j == hitCount;
+
+ RCL_HitResult hit;
+ RCL_Unit distance = 1;
+
+ RCL_Unit fWallHeight = 0, cWallHeight = 0;
+ RCL_Unit fZ2World = 0, cZ2World = 0;
+ RCL_Unit fZ1Screen = 0, cZ1Screen = 0;
+ RCL_Unit fZ2Screen = 0, cZ2Screen = 0;
+
+ if (!drawingHorizon)
+ {
+ hit = hits[j];
+ distance = RCL_nonZero(hit.distance);
+ p.hit = hit;
+
+ fWallHeight = _RCL_floorFunction(hit.square.x,hit.square.y);
+ fZ2World = fWallHeight - _RCL_camera.height;
+ fZ1Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
+ (fZ1World * _RCL_camera.resolution.y) /
+ RCL_UNITS_PER_SQUARE,distance);
+ fZ2Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
+ (fZ2World * _RCL_camera.resolution.y) /
+ RCL_UNITS_PER_SQUARE,distance);
+
+ if (_RCL_ceilFunction != 0)
+ {
+ cWallHeight = _RCL_ceilFunction(hit.square.x,hit.square.y);
+ cZ2World = cWallHeight - _RCL_camera.height;
+ cZ1Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
+ (cZ1World * _RCL_camera.resolution.y) /
+ RCL_UNITS_PER_SQUARE,distance);
+ cZ2Screen = _RCL_middleRow - RCL_perspectiveScaleVertical(
+ (cZ2World * _RCL_camera.resolution.y) /
+ RCL_UNITS_PER_SQUARE,distance);
+ }
+ }
+ else
+ {
+ fZ1Screen = _RCL_middleRow;
+ cZ1Screen = _RCL_middleRow + 1;
+ _RCL_makeInfiniteHit(&p.hit,&ray);
+ }
+
+ RCL_Unit limit;
+
+ p.isWall = 0;
+ p.isHorizon = drawingHorizon;
+
+ // draw floor until wall
+ p.isFloor = 1;
+ p.height = fZ1World + _RCL_camera.height;
+ p.wallHeight = 0;
+
+#if RCL_COMPUTE_FLOOR_DEPTH == 1
+ p.depth = (_RCL_fHorizontalDepthStart - fPosY) * _RCL_horizontalDepthStep;
+#else
+ p.depth = 0;
+#endif
+
+ limit = _RCL_drawHorizontalColumn(fPosY,fZ1Screen,cPosY + 1,
+ _RCL_camera.resolution.y,fZ1World,-1,RCL_COMPUTE_FLOOR_DEPTH,
+ // ^ purposfully allow outside screen bounds
+ RCL_COMPUTE_FLOOR_TEXCOORDS && p.height == RCL_FLOOR_TEXCOORDS_HEIGHT,
+ 1,&ray,&p);
+
+ if (fPosY > limit)
+ fPosY = limit;
+
+ if (_RCL_ceilFunction != 0 || drawingHorizon)
+ {
+ // draw ceiling until wall
+ p.isFloor = 0;
+ p.height = cZ1World + _RCL_camera.height;
+
+#if RCL_COMPUTE_CEILING_DEPTH == 1
+ p.depth = (cPosY - _RCL_cHorizontalDepthStart) *
+ _RCL_horizontalDepthStep;
+#endif
+
+ limit = _RCL_drawHorizontalColumn(cPosY,cZ1Screen,
+ -1,fPosY - 1,cZ1World,1,RCL_COMPUTE_CEILING_DEPTH,0,1,&ray,&p);
+ // ^ purposfully allow outside screen bounds here
+
+ if (cPosY < limit)
+ cPosY = limit;
+ }
+
+ if (!drawingHorizon) // don't draw walls for horizon plane
+ {
+ p.isWall = 1;
+ p.depth = distance;
+ p.isFloor = 1;
+ p.texCoords.x = hit.textureCoord;
+ p.height = fZ1World + _RCL_camera.height;
+ p.wallHeight = fWallHeight;
+
+ // draw floor wall
+
+ if (fPosY > 0) // still pixels left?
+ {
+ p.isFloor = 1;
+
+ limit = _RCL_drawWall(fPosY,fZ1Screen,fZ2Screen,cPosY + 1,
+ _RCL_camera.resolution.y,
+ // ^ purposfully allow outside screen bounds here
+#if RCL_TEXTURE_VERTICAL_STRETCH == 1
+ RCL_UNITS_PER_SQUARE
+#else
+ fZ2World - fZ1World
+#endif
+ ,-1,&p);
+
+
+ if (fPosY > limit)
+ fPosY = limit;
+
+ fZ1World = fZ2World; // for the next iteration
+ } // ^ purposfully allow outside screen bounds here
+
+ // draw ceiling wall
+
+ if (_RCL_ceilFunction != 0 && cPosY < _RCL_camResYLimit) // pixels left?
+ {
+ p.isFloor = 0;
+ p.height = cZ1World + _RCL_camera.height;
+ p.wallHeight = cWallHeight;
+
+ limit = _RCL_drawWall(cPosY,cZ1Screen,cZ2Screen,
+ -1,fPosY - 1,
+ // ^ puposfully allow outside screen bounds here
+#if RCL_TEXTURE_VERTICAL_STRETCH == 1
+ RCL_UNITS_PER_SQUARE
+#else
+ cZ1World - cZ2World
+#endif
+ ,1,&p);
+
+ if (cPosY < limit)
+ cPosY = limit;
+
+ cZ1World = cZ2World; // for the next iteration
+ } // ^ puposfully allow outside screen bounds here
+ }
+ }
+}
+
+void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount,
+ uint16_t x, RCL_Ray ray)
+{
+ RCL_Unit y = 0;
+ RCL_Unit wallHeightScreen = 0;
+ RCL_Unit wallStart = _RCL_middleRow;
+
+ RCL_Unit dist = 1;
+
+ RCL_PixelInfo p;
+ p.position.x = x;
+ p.wallHeight = RCL_UNITS_PER_SQUARE;
+
+ if (hitCount > 0)
+ {
+ RCL_HitResult hit = hits[0];
+
+ uint8_t goOn = 1;
+
+ if (_RCL_rollFunction != 0 && RCL_COMPUTE_WALL_TEXCOORDS == 1)
+ {
+ if (hit.arrayValue == 0)
+ {
+ // standing inside door square, looking out => move to the next hit
+
+ if (hitCount > 1)
+ hit = hits[1];
+ else
+ goOn = 0;
+ }
+ else
+ {
+ // normal hit, check the door roll
+
+ RCL_Unit texCoordMod = hit.textureCoord % RCL_UNITS_PER_SQUARE;
+
+ int8_t unrolled = hit.doorRoll >= 0 ?
+ (hit.doorRoll > texCoordMod) :
+ (texCoordMod > RCL_UNITS_PER_SQUARE + hit.doorRoll);
+
+ if (unrolled)
+ {
+ goOn = 0;
+
+ if (hitCount > 1) /* should probably always be true (hit on square
+ exit) */
+ {
+ if (hit.direction % 2 != hits[1].direction % 2)
+ {
+ // hit on the inner side
+ hit = hits[1];
+ goOn = 1;
+ }
+ else if (hitCount > 2)
+ {
+ // hit on the opposite side
+ hit = hits[2];
+ goOn = 1;
+ }
+ }
+ }
+ }
+ }
+
+ p.hit = hit;
+
+ if (goOn)
+ {
+ dist = hit.distance;
+
+ RCL_Unit wallHeightWorld = _RCL_floorFunction(hit.square.x,hit.square.y);
+
+ if (wallHeightWorld < 0)
+ {
+ /* We can't just do wallHeightWorld = max(0,wallHeightWorld) because
+ we would be processing an actual hit with height 0, which shouldn't
+ ever happen, so we assign some arbitrary height. */
+
+ wallHeightWorld = RCL_UNITS_PER_SQUARE;
+ }
+
+ RCL_Unit worldPointTop = wallHeightWorld - _RCL_camera.height;
+ RCL_Unit worldPointBottom = -1 * _RCL_camera.height;
+
+ wallStart = _RCL_middleRow -
+ (RCL_perspectiveScaleVertical(worldPointTop,dist)
+ * _RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE;
+
+ int16_t wallEnd = _RCL_middleRow -
+ (RCL_perspectiveScaleVertical(worldPointBottom,dist)
+ * _RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE;
+
+ wallHeightScreen = wallEnd - wallStart;
+
+ if (wallHeightScreen <= 0) // can happen because of rounding errors
+ wallHeightScreen = 1;
+ }
+ }
+ else
+ {
+ _RCL_makeInfiniteHit(&p.hit,&ray);
+ }
+
+ // draw ceiling
+
+ p.isWall = 0;
+ p.isFloor = 0;
+ p.isHorizon = 1;
+ p.depth = 1;
+ p.height = RCL_UNITS_PER_SQUARE;
+
+ y = _RCL_drawHorizontalColumn(-1,wallStart,-1,_RCL_middleRow,_RCL_camera.height,1,
+ RCL_COMPUTE_CEILING_DEPTH,0,1,&ray,&p);
+
+ // draw wall
+
+ p.isWall = 1;
+ p.isFloor = 1;
+ p.depth = dist;
+ p.height = 0;
+
+#if RCL_ROLL_TEXTURE_COORDS == 1 && RCL_COMPUTE_WALL_TEXCOORDS == 1
+ p.hit.textureCoord -= p.hit.doorRoll;
+#endif
+
+ p.texCoords.x = p.hit.textureCoord;
+ p.texCoords.y = 0;
+
+ RCL_Unit limit = _RCL_drawWall(y,wallStart,wallStart + wallHeightScreen - 1,
+ -1,_RCL_camResYLimit,p.hit.arrayValue,1,&p);
+
+ y = RCL_max(y,limit); // take max, in case no wall was drawn
+ y = RCL_max(y,wallStart);
+
+ // draw floor
+
+ p.isWall = 0;
+
+#if RCL_COMPUTE_FLOOR_DEPTH == 1
+ p.depth = (_RCL_camera.resolution.y - y) * _RCL_horizontalDepthStep + 1;
+#endif
+
+ _RCL_drawHorizontalColumn(y,_RCL_camResYLimit,-1,_RCL_camResYLimit,
+ _RCL_camera.height,1,RCL_COMPUTE_FLOOR_DEPTH,RCL_COMPUTE_FLOOR_TEXCOORDS,
+ -1,&ray,&p);
+}
+
+/**
+ Precomputes a distance from camera to the floor at each screen row into an
+ array (must be preallocated with sufficient (camera.resolution.y) length).
+*/
+static inline void _RCL_precomputeFloorDistances(RCL_Camera camera,
+ RCL_Unit *dest, uint16_t startIndex)
+{
+ RCL_Unit camHeightScreenSize =
+ (camera.height * camera.resolution.y) / RCL_UNITS_PER_SQUARE;
+
+ for (uint16_t i = startIndex; i < camera.resolution.y; ++i)
+ dest[i] = RCL_perspectiveScaleVerticalInverse(camHeightScreenSize,
+ RCL_abs(i - _RCL_middleRow));
+}
+
+void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
+ RCL_ArrayFunction ceilingHeightFunc, RCL_ArrayFunction typeFunction,
+ RCL_RayConstraints constraints)
+{
+ _RCL_floorFunction = floorHeightFunc;
+ _RCL_ceilFunction = ceilingHeightFunc;
+ _RCL_camera = cam;
+ _RCL_camResYLimit = cam.resolution.y - 1;
+
+ uint16_t halfResY = cam.resolution.y / 2;
+
+ _RCL_middleRow = halfResY + cam.shear;
+
+ _RCL_fHorizontalDepthStart = _RCL_middleRow + halfResY;
+ _RCL_cHorizontalDepthStart = _RCL_middleRow - halfResY;
+
+ _RCL_startFloorHeight = floorHeightFunc(
+ RCL_divRoundDown(cam.position.x,RCL_UNITS_PER_SQUARE),
+ RCL_divRoundDown(cam.position.y,RCL_UNITS_PER_SQUARE)) -1 * cam.height;
+
+ _RCL_startCeil_Height =
+ ceilingHeightFunc != 0 ?
+ ceilingHeightFunc(
+ RCL_divRoundDown(cam.position.x,RCL_UNITS_PER_SQUARE),
+ RCL_divRoundDown(cam.position.y,RCL_UNITS_PER_SQUARE)) -1 * cam.height
+ : RCL_INFINITY;
+
+ _RCL_horizontalDepthStep = RCL_HORIZON_DEPTH / cam.resolution.y;
+
+#if RCL_COMPUTE_FLOOR_TEXCOORDS == 1
+ RCL_Unit floorPixelDistances[cam.resolution.y];
+ _RCL_precomputeFloorDistances(cam,floorPixelDistances,0);
+ _RCL_floorPixelDistances = floorPixelDistances; // pass to column function
+#endif
+
+ RCL_castRaysMultiHit(cam,_RCL_floorCeilFunction,typeFunction,
+ _RCL_columnFunctionComplex,constraints);
+}
+
+void RCL_renderSimple(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
+ RCL_ArrayFunction typeFunc, RCL_ArrayFunction rollFunc,
+ RCL_RayConstraints constraints)
+{
+ _RCL_floorFunction = floorHeightFunc;
+ _RCL_camera = cam;
+ _RCL_camResYLimit = cam.resolution.y - 1;
+ _RCL_middleRow = cam.resolution.y / 2;
+ _RCL_rollFunction = rollFunc;
+
+ _RCL_cameraHeightScreen =
+ (_RCL_camera.resolution.y * (_RCL_camera.height - RCL_UNITS_PER_SQUARE)) /
+ RCL_UNITS_PER_SQUARE;
+
+ _RCL_horizontalDepthStep = RCL_HORIZON_DEPTH / cam.resolution.y;
+
+ constraints.maxHits =
+ _RCL_rollFunction == 0 ?
+ 1 : // no door => 1 hit is enough
+ 3; // for correctly rendering rolling doors we'll need 3 hits (NOT 2)
+
+#if RCL_COMPUTE_FLOOR_TEXCOORDS == 1
+ RCL_Unit floorPixelDistances[cam.resolution.y];
+ _RCL_precomputeFloorDistances(cam,floorPixelDistances,_RCL_middleRow);
+ _RCL_floorPixelDistances = floorPixelDistances; // pass to column function
+#endif
+
+ RCL_castRaysMultiHit(cam,_floorHeightNotZeroFunction,typeFunc,
+ _RCL_columnFunctionSimple, constraints);
+
+#if RCL_COMPUTE_FLOOR_TEXCOORDS == 1
+ _RCL_floorPixelDistances = 0;
+#endif
+}
+
+RCL_Vector2D RCL_normalize(RCL_Vector2D v)
+{
+ RCL_Vector2D result;
+ RCL_Unit l = RCL_len(v);
+ l = RCL_nonZero(l);
+
+ result.x = (v.x * RCL_UNITS_PER_SQUARE) / l;
+ result.y = (v.y * RCL_UNITS_PER_SQUARE) / l;
+
+ return result;
+}
+
+RCL_Unit RCL_vectorsAngleCos(RCL_Vector2D v1, RCL_Vector2D v2)
+{
+ v1 = RCL_normalize(v1);
+ v2 = RCL_normalize(v2);
+
+ return (v1.x * v2.x + v1.y * v2.y) / RCL_UNITS_PER_SQUARE;
+}
+
+
+RCL_PixelInfo RCL_mapToScreen(RCL_Vector2D worldPosition, RCL_Unit height,
+ RCL_Camera camera)
+{
+ RCL_PixelInfo result;
+
+ RCL_Vector2D toPoint;
+
+ toPoint.x = worldPosition.x - camera.position.x;
+ toPoint.y = worldPosition.y - camera.position.y;
+
+ RCL_Unit middleColumn = camera.resolution.x / 2;
+
+ // rotate the point to camera space (y left/right, x forw/backw)
+
+ RCL_Unit cos = RCL_cos(camera.direction);
+ RCL_Unit sin = RCL_sin(camera.direction);
+
+ RCL_Unit tmp = toPoint.x;
+
+ toPoint.x = (toPoint.x * cos - toPoint.y * sin) / RCL_UNITS_PER_SQUARE;
+ toPoint.y = (tmp * sin + toPoint.y * cos) / RCL_UNITS_PER_SQUARE;
+
+ result.depth = toPoint.x;
+
+ result.position.x = middleColumn -
+ (RCL_perspectiveScaleHorizontal(toPoint.y,result.depth) * middleColumn) /
+ RCL_UNITS_PER_SQUARE;
+
+ result.position.y =
+ (RCL_perspectiveScaleVertical(height - camera.height,result.depth)
+ * camera.resolution.y) / RCL_UNITS_PER_SQUARE;
+
+ result.position.y = camera.resolution.y / 2 - result.position.y + camera.shear;
+
+ return result;
+}
+
+RCL_Unit RCL_degreesToUnitsAngle(int16_t degrees)
+{
+ return (degrees * RCL_UNITS_PER_SQUARE) / 360;
+}
+
+/**
+ Ugly temporary hack to solve mapping to screen. This function computes
+ (approximately, usin a table) a divisor needed for FOV correction.
+*/
+RCL_Unit _RCL_fovCorrectionFactor(RCL_Unit fov)
+{
+ uint16_t table[9] =
+ {1,208,408,692,1024,1540,2304,5376,30000};
+
+ fov = RCL_min(RCL_UNITS_PER_SQUARE / 2 - 1,fov);
+
+ uint8_t index = fov / 64;
+ uint32_t t = ((fov - index * 64) * RCL_UNITS_PER_SQUARE) / 64;
+ uint32_t v1 = table[index];
+ uint32_t v2 = table[index + 1];
+
+ return v1 + ((v2 - v1) * t) / RCL_UNITS_PER_SQUARE;
+}
+
+RCL_Unit RCL_perspectiveScaleVertical(RCL_Unit originalSize, RCL_Unit distance)
+{
+ if (_RCL_fovCorrectionFactors[1] == 0)
+ _RCL_fovCorrectionFactors[1] = _RCL_fovCorrectionFactor(RCL_VERTICAL_FOV);
+
+ return distance != 0 ? ((originalSize * RCL_UNITS_PER_SQUARE) /
+ RCL_nonZero((_RCL_fovCorrectionFactors[1] * distance) / RCL_UNITS_PER_SQUARE)
+ ) : 0;
+}
+
+RCL_Unit RCL_perspectiveScaleVerticalInverse(RCL_Unit originalSize,
+ RCL_Unit scaledSize)
+{
+ if (_RCL_fovCorrectionFactors[1] == 0)
+ _RCL_fovCorrectionFactors[1] = _RCL_fovCorrectionFactor(RCL_VERTICAL_FOV);
+
+ return scaledSize != 0 ?
+
+ ((originalSize * RCL_UNITS_PER_SQUARE) /
+ RCL_nonZero((_RCL_fovCorrectionFactors[1] * scaledSize)
+ / RCL_UNITS_PER_SQUARE)) : RCL_INFINITY;
+}
+
+RCL_Unit
+ RCL_perspectiveScaleHorizontal(RCL_Unit originalSize, RCL_Unit distance)
+{
+ if (_RCL_fovCorrectionFactors[0] == 0)
+ _RCL_fovCorrectionFactors[0] = _RCL_fovCorrectionFactor(RCL_HORIZONTAL_FOV);
+
+ return distance != 0 ?
+ ((originalSize * RCL_UNITS_PER_SQUARE) /
+ RCL_nonZero((_RCL_fovCorrectionFactors[0] * distance) / RCL_UNITS_PER_SQUARE)
+ ) : 0;
+}
+
+RCL_Unit RCL_perspectiveScaleHorizontalInverse(RCL_Unit originalSize,
+ RCL_Unit scaledSize)
+{
+ // TODO: probably doesn't work
+
+ return scaledSize != 0 ?
+ (originalSize * RCL_UNITS_PER_SQUARE + RCL_UNITS_PER_SQUARE / 2) /
+ ((RCL_HORIZONTAL_FOV_TAN * 2 * scaledSize) / RCL_UNITS_PER_SQUARE)
+ : RCL_INFINITY;
+}
+
+RCL_Unit RCL_castRay3D(
+ RCL_Vector2D pos1, RCL_Unit height1, RCL_Vector2D pos2, RCL_Unit height2,
+ RCL_ArrayFunction floorHeightFunc, RCL_ArrayFunction ceilingHeightFunc,
+ RCL_RayConstraints constraints)
+{
+ RCL_HitResult hits[constraints.maxHits];
+ uint16_t numHits;
+
+ RCL_Ray ray;
+
+ ray.start = pos1;
+
+ RCL_Unit distance;
+
+ ray.direction.x = pos2.x - pos1.x;
+ ray.direction.y = pos2.y - pos1.y;
+
+ distance = RCL_len(ray.direction);
+
+ ray.direction = RCL_normalize(ray.direction);
+
+ RCL_Unit heightDiff = height2 - height1;
+
+ RCL_castRayMultiHit(ray,floorHeightFunc,0,hits,&numHits,constraints);
+
+ RCL_Unit result = RCL_UNITS_PER_SQUARE;
+
+ int16_t squareX = RCL_divRoundDown(pos1.x,RCL_UNITS_PER_SQUARE);
+ int16_t squareY = RCL_divRoundDown(pos1.y,RCL_UNITS_PER_SQUARE);
+
+ RCL_Unit startHeight = floorHeightFunc(squareX,squareY);
+
+ #define checkHits(comp,res) \
+ { \
+ RCL_Unit currentHeight = startHeight; \
+ for (uint16_t i = 0; i < numHits; ++i) \
+ { \
+ if (hits[i].distance > distance) \
+ break;\
+ RCL_Unit h = hits[i].arrayValue; \
+ if ((currentHeight comp h ? currentHeight : h) \
+ comp (height1 + (hits[i].distance * heightDiff) / distance)) \
+ { \
+ res = (hits[i].distance * RCL_UNITS_PER_SQUARE) / distance; \
+ break; \
+ } \
+ currentHeight = h; \
+ } \
+ }
+
+ checkHits(>,result)
+
+ if (ceilingHeightFunc != 0)
+ {
+ RCL_Unit result2 = RCL_UNITS_PER_SQUARE;
+
+ startHeight = ceilingHeightFunc(squareX,squareY);
+
+ RCL_castRayMultiHit(ray,ceilingHeightFunc,0,hits,&numHits,constraints);
+
+ checkHits(<,result2)
+
+ if (result2 < result)
+ result = result2;
+ }
+
+ #undef checkHits
+
+ return result;
+}
+
+void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
+ RCL_Unit heightOffset, RCL_ArrayFunction floorHeightFunc,
+ RCL_ArrayFunction ceilingHeightFunc, int8_t computeHeight, int8_t force)
+{
+ int8_t movesInPlane = planeOffset.x != 0 || planeOffset.y != 0;
+
+ if (movesInPlane || force)
+ {
+ int16_t xSquareNew, ySquareNew;
+
+ RCL_Vector2D corner; // BBox corner in the movement direction
+ RCL_Vector2D cornerNew;
+
+ int16_t xDir = planeOffset.x > 0 ? 1 : -1;
+ int16_t yDir = planeOffset.y > 0 ? 1 : -1;
+
+ corner.x = camera->position.x + xDir * RCL_CAMERA_COLL_RADIUS;
+ corner.y = camera->position.y + yDir * RCL_CAMERA_COLL_RADIUS;
+
+ int16_t xSquare = RCL_divRoundDown(corner.x,RCL_UNITS_PER_SQUARE);
+ int16_t ySquare = RCL_divRoundDown(corner.y,RCL_UNITS_PER_SQUARE);
+
+ cornerNew.x = corner.x + planeOffset.x;
+ cornerNew.y = corner.y + planeOffset.y;
+
+ xSquareNew = RCL_divRoundDown(cornerNew.x,RCL_UNITS_PER_SQUARE);
+ ySquareNew = RCL_divRoundDown(cornerNew.y,RCL_UNITS_PER_SQUARE);
+
+ RCL_Unit bottomLimit = -1 * RCL_INFINITY;
+ RCL_Unit topLimit = RCL_INFINITY;
+
+ RCL_Unit currCeilHeight = RCL_INFINITY;
+
+ if (computeHeight)
+ {
+ bottomLimit = camera->height - RCL_CAMERA_COLL_HEIGHT_BELOW +
+ RCL_CAMERA_COLL_STEP_HEIGHT;
+
+ topLimit = camera->height + RCL_CAMERA_COLL_HEIGHT_ABOVE;
+
+ if (ceilingHeightFunc != 0)
+ currCeilHeight = ceilingHeightFunc(xSquare,ySquare);
+ }
+
+ // checks a single square for collision against the camera
+ #define collCheck(dir,s1,s2)\
+ if (computeHeight)\
+ {\
+ RCL_Unit height = floorHeightFunc(s1,s2);\
+ if (height > bottomLimit || \
+ currCeilHeight - height < \
+ RCL_CAMERA_COLL_HEIGHT_BELOW + RCL_CAMERA_COLL_HEIGHT_ABOVE)\
+ dir##Collides = 1;\
+ else if (ceilingHeightFunc != 0)\
+ {\
+ RCL_Unit height2 = ceilingHeightFunc(s1,s2);\
+ if ((height2 < topLimit) || ((height2 - height) < \
+ (RCL_CAMERA_COLL_HEIGHT_ABOVE + RCL_CAMERA_COLL_HEIGHT_BELOW)))\
+ dir##Collides = 1;\
+ }\
+ }\
+ else\
+ dir##Collides = floorHeightFunc(s1,s2) > RCL_CAMERA_COLL_STEP_HEIGHT;
+
+ // check collision against non-diagonal square
+ #define collCheckOrtho(dir,dir2,s1,s2,x)\
+ if (dir##SquareNew != dir##Square)\
+ {\
+ collCheck(dir,s1,s2)\
+ }\
+ if (!dir##Collides)\
+ { /* now also check for coll on the neighbouring square */ \
+ int16_t dir2##Square2 = RCL_divRoundDown(corner.dir2 - dir2##Dir *\
+ RCL_CAMERA_COLL_RADIUS * 2,RCL_UNITS_PER_SQUARE);\
+ if (dir2##Square2 != dir2##Square)\
+ {\
+ if (x)\
+ collCheck(dir,dir##SquareNew,dir2##Square2)\
+ else\
+ collCheck(dir,dir2##Square2,dir##SquareNew)\
+ }\
+ }
+
+ int8_t xCollides = 0;
+ collCheckOrtho(x,y,xSquareNew,ySquare,1)
+
+ int8_t yCollides = 0;
+ collCheckOrtho(y,x,xSquare,ySquareNew,0)
+
+ if (xCollides || yCollides)
+ {
+ if (movesInPlane)
+ {
+ #define collHandle(dir)\
+ if (dir##Collides)\
+ cornerNew.dir = (dir##Square) * RCL_UNITS_PER_SQUARE +\
+ RCL_UNITS_PER_SQUARE / 2 + dir##Dir * (RCL_UNITS_PER_SQUARE / 2) -\
+ dir##Dir;\
+
+ collHandle(x)
+ collHandle(y)
+
+ #undef collHandle
+ }
+ else
+ {
+ /* Player collides without moving in the plane; this can happen e.g. on
+ elevators due to vertical only movement. This code can get executed
+ when force == 1. */
+
+ RCL_Vector2D squarePos;
+ RCL_Vector2D newPos;
+
+ squarePos.x = xSquare * RCL_UNITS_PER_SQUARE;
+ squarePos.y = ySquare * RCL_UNITS_PER_SQUARE;
+
+ newPos.x =
+ RCL_max(squarePos.x + RCL_CAMERA_COLL_RADIUS + 1,
+ RCL_min(squarePos.x + RCL_UNITS_PER_SQUARE - RCL_CAMERA_COLL_RADIUS - 1,
+ camera->position.x));
+
+ newPos.y =
+ RCL_max(squarePos.y + RCL_CAMERA_COLL_RADIUS + 1,
+ RCL_min(squarePos.y + RCL_UNITS_PER_SQUARE - RCL_CAMERA_COLL_RADIUS - 1,
+ camera->position.y));
+
+ cornerNew.x = corner.x + (newPos.x - camera->position.x);
+ cornerNew.y = corner.y + (newPos.y - camera->position.y);
+ }
+ }
+ else
+ {
+ /* If no non-diagonal collision is detected, a diagonal/corner collision
+ can still happen, check it here. */
+
+ if (xSquare != xSquareNew && ySquare != ySquareNew)
+ {
+ int8_t xyCollides = 0;
+ collCheck(xy,xSquareNew,ySquareNew)
+
+ if (xyCollides)
+ {
+ // normally should slide, but let's KISS and simply stop any movement
+ cornerNew = corner;
+ }
+ }
+ }
+
+ #undef collCheck
+
+ camera->position.x = cornerNew.x - xDir * RCL_CAMERA_COLL_RADIUS;
+ camera->position.y = cornerNew.y - yDir * RCL_CAMERA_COLL_RADIUS;
+ }
+
+ if (computeHeight && (movesInPlane || (heightOffset != 0) || force))
+ {
+ camera->height += heightOffset;
+
+ int16_t xSquare1 = RCL_divRoundDown(camera->position.x -
+ RCL_CAMERA_COLL_RADIUS,RCL_UNITS_PER_SQUARE);
+
+ int16_t xSquare2 = RCL_divRoundDown(camera->position.x +
+ RCL_CAMERA_COLL_RADIUS,RCL_UNITS_PER_SQUARE);
+
+ int16_t ySquare1 = RCL_divRoundDown(camera->position.y -
+ RCL_CAMERA_COLL_RADIUS,RCL_UNITS_PER_SQUARE);
+
+ int16_t ySquare2 = RCL_divRoundDown(camera->position.y +
+ RCL_CAMERA_COLL_RADIUS,RCL_UNITS_PER_SQUARE);
+
+ RCL_Unit bottomLimit = floorHeightFunc(xSquare1,ySquare1);
+ RCL_Unit topLimit = ceilingHeightFunc != 0 ?
+ ceilingHeightFunc(xSquare1,ySquare1) : RCL_INFINITY;
+
+ RCL_Unit height;
+
+ #define checkSquares(s1,s2)\
+ {\
+ height = floorHeightFunc(xSquare##s1,ySquare##s2);\
+ bottomLimit = RCL_max(bottomLimit,height);\
+ height = ceilingHeightFunc != 0 ?\
+ ceilingHeightFunc(xSquare##s1,ySquare##s2) : RCL_INFINITY;\
+ topLimit = RCL_min(topLimit,height);\
+ }
+
+ if (xSquare2 != xSquare1)
+ checkSquares(2,1)
+
+ if (ySquare2 != ySquare1)
+ checkSquares(1,2)
+
+ if (xSquare2 != xSquare1 && ySquare2 != ySquare1)
+ checkSquares(2,2)
+
+ camera->height = RCL_clamp(camera->height,
+ bottomLimit + RCL_CAMERA_COLL_HEIGHT_BELOW,
+ topLimit - RCL_CAMERA_COLL_HEIGHT_ABOVE);
+
+ #undef checkSquares
+ }
+}
+
+void RCL_initCamera(RCL_Camera *camera)
+{
+ camera->position.x = 0;
+ camera->position.y = 0;
+ camera->direction = 0;
+ camera->resolution.x = 20;
+ camera->resolution.y = 15;
+ camera->shear = 0;
+ camera->height = RCL_UNITS_PER_SQUARE;
+}
+
+void RCL_initRayConstraints(RCL_RayConstraints *constraints)
+{
+ constraints->maxHits = 1;
+ constraints->maxSteps = 20;
+}
+
diff --git a/src/raycastlib.h b/src/raycastlib.h
new file mode 100644
index 0000000..c882bfd
--- /dev/null
+++ b/src/raycastlib.h
@@ -0,0 +1,504 @@
+#ifndef RAYCASTLIB_H
+#define RAYCASTLIB_H
+
+/**
+ raycastlib (RCL) - Small C header-only raycasting library for embedded and
+ low performance computers, such as Arduino. Only uses integer math and stdint
+ standard library.
+
+ Check the defines below to fine-tune accuracy vs performance! Don't forget
+ to compile with optimizations.
+
+ Before including the library define RCL_PIXEL_FUNCTION to the name of the
+ function (with RCL_PixelFunction signature) that will render your pixels!
+
+ - All public (and most private) library identifiers start with RCL_.
+ - Game field's bottom left corner is at [0,0].
+ - X axis goes right in the ground plane.
+ - Y axis goes up in the ground plane.
+ - Height means the Z (vertical) coordinate.
+ - Each game square is RCL_UNITS_PER_SQUARE * RCL_UNITS_PER_SQUARE points.
+ - Angles are in RCL_Units, 0 means pointing right (x+) and positively rotates
+ clockwise. A full angle has RCL_UNITS_PER_SQUARE RCL_Units.
+ - Most things are normalized with RCL_UNITS_PER_SQUARE (sin, cos, vector
+ unit length, texture coordinates etc.).
+ - Screen coordinates are normal: [0,0] = top left, x goes right, y goes down.
+
+ author: Miloslav "drummyfish" Ciz
+ license: CC0 1.0
+ version: 0.908d
+
+ Version numbering: major.minor[d], id 'd' is appended, this is a
+ in-development version based on the previous stable major.minor version. Two
+ 'd' versions with the same version number, .e.g. 1.0d, may be different.
+*/
+
+#include <stdint.h>
+
+#ifndef RCL_RAYCAST_TINY /** Turns on super efficient version of this library.
+ Only use if neccesarry, looks ugly. Also not done
+ yet. */
+ #define RCL_UNITS_PER_SQUARE 1024 /**< Number of RCL_Units in a side of a
+ spatial square. */
+ typedef int32_t RCL_Unit; /**< Smallest spatial unit, there is
+ RCL_UNITS_PER_SQUARE units in a square's
+ length. This effectively serves the purpose of
+ a fixed-point arithmetic. */
+ #define RCL_INFINITY 2000000000
+#else
+ #define RCL_UNITS_PER_SQUARE 32
+ typedef int16_t RCL_Unit;
+ #define RCL_INFINITY 30000
+ #define RCL_USE_DIST_APPROX 2
+#endif
+
+#ifndef RCL_COMPUTE_WALL_TEXCOORDS
+#define RCL_COMPUTE_WALL_TEXCOORDS 1
+#endif
+
+#ifndef RCL_COMPUTE_FLOOR_TEXCOORDS
+#define RCL_COMPUTE_FLOOR_TEXCOORDS 0
+#endif
+
+#ifndef RCL_FLOOR_TEXCOORDS_HEIGHT
+#define RCL_FLOOR_TEXCOORDS_HEIGHT 0 /** If RCL_COMPUTE_FLOOR_TEXCOORDS == 1,
+ this says for what height level the
+ texture coords will be computed for
+ (for simplicity/performance only one
+ level is allowed). */
+#endif
+
+#ifndef RCL_USE_COS_LUT
+#define RCL_USE_COS_LUT 0 /**< type of look up table for cos function:
+ 0: none (compute)
+ 1: 64 items
+ 2: 128 items */
+#endif
+
+#ifndef RCL_USE_DIST_APPROX
+#define RCL_USE_DIST_APPROX 0 /**< What distance approximation to use:
+ 0: none (compute full Euclidean distance)
+ 1: accurate approximation
+ 2: octagonal approximation (LQ) */
+#endif
+
+#ifndef RCL_RECTILINEAR
+#define RCL_RECTILINEAR 1 /**< Whether to use rectilinear perspective (normally
+ used), or curvilinear perspective (fish eye). */
+#endif
+
+#ifndef RCL_TEXTURE_VERTICAL_STRETCH
+#define RCL_TEXTURE_VERTICAL_STRETCH 1 /**< Whether textures should be
+ stretched to wall height (possibly
+ slightly slower if on). */
+#endif
+
+#ifndef RCL_COMPUTE_FLOOR_DEPTH
+#define RCL_COMPUTE_FLOOR_DEPTH 1 /**< Whether depth should be computed for
+ floor pixels - turns this off if not
+ needed. */
+#endif
+
+#ifndef RCL_COMPUTE_CEILING_DEPTH
+#define RCL_COMPUTE_CEILING_DEPTH 1 /**< As RCL_COMPUTE_FLOOR_DEPTH but for
+ ceiling. */
+#endif
+
+#ifndef RCL_ROLL_TEXTURE_COORDS
+#define RCL_ROLL_TEXTURE_COORDS 1 /**< Says whether rolling doors should also
+ roll the texture coordinates along (mostly
+ desired for doors). */
+#endif
+
+#ifndef RCL_VERTICAL_FOV
+#define RCL_VERTICAL_FOV (RCL_UNITS_PER_SQUARE / 3)
+#endif
+
+#define RCL_VERTICAL_FOV_TAN (RCL_VERTICAL_FOV * 4) ///< tan approximation
+
+#ifndef RCL_HORIZONTAL_FOV
+#define RCL_HORIZONTAL_FOV (RCL_UNITS_PER_SQUARE / 4)
+#endif
+
+#define RCL_HORIZONTAL_FOV_TAN (RCL_HORIZONTAL_FOV * 4)
+
+#define RCL_HORIZONTAL_FOV_HALF (RCL_HORIZONTAL_FOV / 2)
+
+#ifndef RCL_CAMERA_COLL_RADIUS
+#define RCL_CAMERA_COLL_RADIUS RCL_UNITS_PER_SQUARE / 4
+#endif
+
+#ifndef RCL_CAMERA_COLL_HEIGHT_BELOW
+#define RCL_CAMERA_COLL_HEIGHT_BELOW RCL_UNITS_PER_SQUARE
+#endif
+
+#ifndef RCL_CAMERA_COLL_HEIGHT_ABOVE
+#define RCL_CAMERA_COLL_HEIGHT_ABOVE (RCL_UNITS_PER_SQUARE / 3)
+#endif
+
+#ifndef RCL_CAMERA_COLL_STEP_HEIGHT
+#define RCL_CAMERA_COLL_STEP_HEIGHT (RCL_UNITS_PER_SQUARE / 2)
+#endif
+
+#ifndef RCL_TEXTURE_INTERPOLATION_SCALE
+ #define RCL_TEXTURE_INTERPOLATION_SCALE 1024 /**< This says scaling of fixed
+ poit vertical texture coord
+ computation. This should be power
+ of two! Higher number can look more
+ accurate but may cause overflow. */
+#endif
+
+#define RCL_HORIZON_DEPTH (11 * RCL_UNITS_PER_SQUARE) /**< What depth the
+ horizon has (the floor
+ depth is only
+ approximated with the
+ help of this
+ constant). */
+#ifndef RCL_VERTICAL_DEPTH_MULTIPLY
+#define RCL_VERTICAL_DEPTH_MULTIPLY 2 /**< Defines a multiplier of height
+ difference when approximating floor/ceil
+ depth. */
+#endif
+
+#define RCL_min(a,b) ((a) < (b) ? (a) : (b))
+#define RCL_max(a,b) ((a) > (b) ? (a) : (b))
+#define RCL_nonZero(v) ((v) + ((v) == 0)) ///< To prevent zero divisions.
+#define RCL_zeroClamp(x) ((x) * ((x) >= 0))
+#define RCL_likely(cond) __builtin_expect(!!(cond),1)
+#define RCL_unlikely(cond) __builtin_expect(!!(cond),0)
+
+#define RCL_logV2D(v)\
+ printf("[%d,%d]\n",v.x,v.y);
+
+#define RCL_logRay(r){\
+ printf("ray:\n");\
+ printf(" start: ");\
+ RCL_logV2D(r.start);\
+ printf(" dir: ");\
+ RCL_logV2D(r.direction);}
+
+#define RCL_logHitResult(h){\
+ printf("hit:\n");\
+ printf(" square: ");\
+ RCL_logV2D(h.square);\
+ printf(" pos: ");\
+ RCL_logV2D(h.position);\
+ printf(" dist: %d\n", h.distance);\
+ printf(" dir: %d\n", h.direction);\
+ printf(" texcoord: %d\n", h.textureCoord);}
+
+#define RCL_logPixelInfo(p){\
+ printf("pixel:\n");\
+ printf(" position: ");\
+ RCL_logV2D(p.position);\
+ printf(" texCoord: ");\
+ RCL_logV2D(p.texCoords);\
+ printf(" depth: %d\n", p.depth);\
+ printf(" height: %d\n", p.height);\
+ printf(" wall: %d\n", p.isWall);\
+ printf(" hit: ");\
+ RCL_logHitResult(p.hit);\
+ }
+
+#define RCL_logCamera(c){\
+ printf("camera:\n");\
+ printf(" position: ");\
+ RCL_logV2D(c.position);\
+ printf(" height: %d\n",c.height);\
+ printf(" direction: %d\n",c.direction);\
+ printf(" shear: %d\n",c.shear);\
+ printf(" resolution: %d x %d\n",c.resolution.x,c.resolution.y);\
+ }
+
+/// Position in 2D space.
+typedef struct
+{
+ RCL_Unit x;
+ RCL_Unit y;
+} RCL_Vector2D;
+
+typedef struct
+{
+ RCL_Vector2D start;
+ RCL_Vector2D direction;
+} RCL_Ray;
+
+typedef struct
+{
+ RCL_Unit distance; /**< Distance to the hit position, or -1 if no
+ collision happened. If RCL_RECTILINEAR != 0, then
+ the distance is perpendicular to the projection
+ plane (fish eye correction), otherwise it is
+ the straight distance to the ray start
+ position. */
+ uint8_t direction; /**< Direction of hit. The convention for angle
+ units is explained above. */
+ RCL_Unit textureCoord; /**< Normalized (0 to RCL_UNITS_PER_SQUARE - 1)
+ texture coordinate (horizontal). */
+ RCL_Vector2D square; ///< Collided square coordinates.
+ RCL_Vector2D position; ///< Exact collision position in RCL_Units.
+ RCL_Unit arrayValue; /** Value returned by array function (most often
+ this will be the floor height). */
+ RCL_Unit type; /**< Integer identifying type of square (number
+ returned by type function, e.g. texture
+ index).*/
+ RCL_Unit doorRoll; ///< Holds value of door roll.
+} RCL_HitResult;
+
+typedef struct
+{
+ RCL_Vector2D position;
+ RCL_Unit direction; // TODO: rename to "angle" to keep consistency
+ RCL_Vector2D resolution;
+ int16_t shear; /**< Shear offset in pixels (0 => no shear), can simulate
+ looking up/down. */
+ RCL_Unit height;
+} RCL_Camera;
+
+/**
+ Holds an information about a single rendered pixel (for a pixel function
+ that works as a fragment shader).
+*/
+typedef struct
+{
+ RCL_Vector2D position; ///< On-screen position.
+ int8_t isWall; ///< Whether the pixel is a wall or a floor/ceiling.
+ int8_t isFloor; ///< Whether the pixel is floor or ceiling.
+ int8_t isHorizon; ///< If the pixel belongs to horizon segment.
+ RCL_Unit depth; ///< Corrected depth.
+ RCL_Unit wallHeight;///< Only for wall pixels, says its height.
+ RCL_Unit height; ///< World height (mostly for floor).
+ RCL_HitResult hit; ///< Corresponding ray hit.
+ RCL_Vector2D texCoords; /**< Normalized (0 to RCL_UNITS_PER_SQUARE - 1)
+ texture coordinates. */
+} RCL_PixelInfo;
+
+void RCL_PIXEL_FUNCTION (RCL_PixelInfo *pixel);
+
+typedef struct
+{
+ uint16_t maxHits;
+ uint16_t maxSteps;
+} RCL_RayConstraints;
+
+/**
+ Function used to retrieve some information about cells of the rendered scene.
+ It should return a characteristic of given square as an integer (e.g. square
+ height, texture index, ...) - between squares that return different numbers
+ there is considered to be a collision.
+
+ This function should be as fast as possible as it will typically be called
+ very often.
+*/
+typedef RCL_Unit (*RCL_ArrayFunction)(int16_t x, int16_t y);
+/*
+ TODO: maybe array functions should be replaced by defines of funtion names
+ like with pixelFunc? Could be more efficient than function pointers.
+*/
+
+
+RCL_Unit RCL_divRoundDown(RCL_Unit value, RCL_Unit divisor);
+
+/**
+ Function that renders a single pixel at the display. It is handed an info
+ about the pixel it should draw.
+
+ This function should be as fast as possible as it will typically be called
+ very often.
+*/
+typedef void (*RCL_PixelFunction)(RCL_PixelInfo *info);
+
+typedef void
+ (*RCL_ColumnFunction)(RCL_HitResult *hits, uint16_t hitCount, uint16_t x,
+ RCL_Ray ray);
+
+/**
+ Simple-interface function to cast a single ray.
+
+ @return The first collision result.
+*/
+RCL_HitResult RCL_castRay(RCL_Ray ray, RCL_ArrayFunction arrayFunc);
+
+/**
+ Casts a 3D ray in 3D environment with floor and optional ceiling
+ (ceilingHeightFunc can be 0). This can be useful for hitscan shooting,
+ visibility checking etc.
+
+ @return normalized ditance (0 to RCL_UNITS_PER_SQUARE) along the ray at which
+ the environment was hit, RCL_UNITS_PER_SQUARE means nothing was hit
+*/
+RCL_Unit RCL_castRay3D(
+ RCL_Vector2D pos1, RCL_Unit height1, RCL_Vector2D pos2, RCL_Unit height2,
+ RCL_ArrayFunction floorHeightFunc, RCL_ArrayFunction ceilingHeightFunc,
+ RCL_RayConstraints constraints);
+
+/**
+ Maps a single point in the world to the screen (2D position + depth).
+*/
+RCL_PixelInfo RCL_mapToScreen(RCL_Vector2D worldPosition, RCL_Unit height,
+ RCL_Camera camera);
+
+/**
+ Casts a single ray and returns a list of collisions.
+
+ @param ray ray to be cast, if RCL_RECTILINEAR != 0 then the computed hit
+ distance is divided by the ray direction vector length (to correct
+ the fish eye effect)
+ @param arrayFunc function that will be used to determine collisions (hits)
+ with the ray (squares for which this function returns different values
+ are considered to have a collision between them), this will typically
+ be a function returning floor height
+ @param typeFunc optional (can be 0) function - if provided, it will be used
+ to mark the hit result with the number returned by this function
+ (it can be e.g. a texture index)
+ @param hitResults array in which the hit results will be stored (has to be
+ preallocated with at space for at least as many hit results as
+ maxHits specified with the constraints parameter)
+ @param hitResultsLen in this variable the number of hit results will be
+ returned
+ @param constraints specifies constraints for the ray cast
+*/
+void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc,
+ RCL_ArrayFunction typeFunc, RCL_HitResult *hitResults,
+ uint16_t *hitResultsLen, RCL_RayConstraints constraints);
+
+RCL_Vector2D RCL_angleToDirection(RCL_Unit angle);
+
+/**
+Cos function.
+
+@param input to cos in RCL_Units (RCL_UNITS_PER_SQUARE = 2 * pi = 360 degrees)
+@return RCL_normalized output in RCL_Units (from -RCL_UNITS_PER_SQUARE to
+ RCL_UNITS_PER_SQUARE)
+*/
+RCL_Unit RCL_cos(RCL_Unit input);
+
+RCL_Unit RCL_sin(RCL_Unit input);
+
+RCL_Unit RCL_tan(RCL_Unit input);
+
+RCL_Unit RCL_ctg(RCL_Unit input);
+
+/// Normalizes given vector to have RCL_UNITS_PER_SQUARE length.
+RCL_Vector2D RCL_normalize(RCL_Vector2D v);
+
+/// Computes a cos of an angle between two vectors.
+RCL_Unit RCL_vectorsAngleCos(RCL_Vector2D v1, RCL_Vector2D v2);
+
+uint16_t RCL_sqrt(RCL_Unit value);
+RCL_Unit RCL_dist(RCL_Vector2D p1, RCL_Vector2D p2);
+RCL_Unit RCL_len(RCL_Vector2D v);
+
+/**
+ Converts an angle in whole degrees to an angle in RCL_Units that this library
+ uses.
+*/
+RCL_Unit RCL_degreesToUnitsAngle(int16_t degrees);
+
+///< Computes the change in size of an object due to perspective (vertical FOV).
+RCL_Unit RCL_perspectiveScaleVertical(RCL_Unit originalSize, RCL_Unit distance);
+
+RCL_Unit RCL_perspectiveScaleVerticalInverse(RCL_Unit originalSize,
+ RCL_Unit scaledSize);
+
+RCL_Unit
+ RCL_perspectiveScaleHorizontal(RCL_Unit originalSize, RCL_Unit distance);
+
+RCL_Unit RCL_perspectiveScaleHorizontalInverse(RCL_Unit originalSize,
+ RCL_Unit scaledSize);
+
+/**
+ Casts rays for given camera view and for each hit calls a user provided
+ function.
+*/
+void RCL_castRaysMultiHit(RCL_Camera cam, RCL_ArrayFunction arrayFunc,
+ RCL_ArrayFunction typeFunction, RCL_ColumnFunction columnFunc,
+ RCL_RayConstraints constraints);
+
+/**
+ Using provided functions, renders a complete complex (multilevel) camera
+ view.
+
+ This function should render each screen pixel exactly once.
+
+ function rendering summary:
+ - performance: slower
+ - accuracy: higher
+ - wall textures: yes
+ - different wall heights: yes
+ - floor/ceiling textures: no
+ - floor geometry: yes, multilevel
+ - ceiling geometry: yes (optional), multilevel
+ - rolling door: no
+ - camera shearing: yes
+ - rendering order: left-to-right, not specifically ordered vertically
+
+ @param cam camera whose view to render
+ @param floorHeightFunc function that returns floor height (in RCL_Units)
+ @param ceilingHeightFunc same as floorHeightFunc but for ceiling, can also be
+ 0 (no ceiling will be rendered)
+ @param typeFunction function that says a type of square (e.g. its texture
+ index), can be 0 (no type in hit result)
+ @param pixelFunc callback function to draw a single pixel on screen
+ @param constraints constraints for each cast ray
+*/
+void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
+ RCL_ArrayFunction ceilingHeightFunc, RCL_ArrayFunction typeFunction,
+ RCL_RayConstraints constraints);
+
+/**
+ Renders given camera view, with help of provided functions. This function is
+ simpler and faster than RCL_renderComplex(...) and is meant to be rendering
+ flat levels.
+
+ function rendering summary:
+ - performance: faster
+ - accuracy: lower
+ - wall textures: yes
+ - different wall heights: yes
+ - floor/ceiling textures: yes (only floor, you can mirror it for ceiling)
+ - floor geometry: no (just flat floor, with depth information)
+ - ceiling geometry: no (just flat ceiling, with depth information)
+ - rolling door: yes
+ - camera shearing: no
+ - rendering order: left-to-right, top-to-bottom
+
+ Additionally this function supports rendering rolling doors.
+
+ This function should render each screen pixel exactly once.
+
+ @param rollFunc function that for given square says its door roll in
+ RCL_Units (0 = no roll, RCL_UNITS_PER_SQUARE = full roll right,
+ -RCL_UNITS_PER_SQUARE = full roll left), can be zero (no rolling door,
+ rendering should also be faster as fewer intersections will be tested)
+*/
+void RCL_renderSimple(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc,
+ RCL_ArrayFunction typeFunc, RCL_ArrayFunction rollFunc,
+ RCL_RayConstraints constraints);
+
+/**
+ Function that moves given camera and makes it collide with walls and
+ potentially also floor and ceilings. It's meant to help implement player
+ movement.
+
+ @param camera camera to move
+ @param planeOffset offset to move the camera in
+ @param heightOffset height offset to move the camera in
+ @param floorHeightFunc function used to retrieve the floor height
+ @param ceilingHeightFunc function for retrieving ceiling height, can be 0
+ (camera won't collide with ceiling)
+ @param computeHeight whether to compute height - if false (0), floor and
+ ceiling functions won't be used and the camera will
+ only collide horizontally with walls (good for simpler
+ game, also faster)
+ @param force if true, forces to recompute collision even if position doesn't
+ change
+*/
+void RCL_moveCameraWithCollision(RCL_Camera *camera, RCL_Vector2D planeOffset,
+ RCL_Unit heightOffset, RCL_ArrayFunction floorHeightFunc,
+ RCL_ArrayFunction ceilingHeightFunc, int8_t computeHeight, int8_t force);
+
+void RCL_initCamera(RCL_Camera *camera);
+void RCL_initRayConstraints(RCL_RayConstraints *constraints);
+
+#endif
diff --git a/src/settings.h b/src/settings.h
new file mode 100644
index 0000000..365c5e2
--- /dev/null
+++ b/src/settings.h
@@ -0,0 +1,28 @@
+#ifndef SETTINGS_H
+#define SETTINGS_H
+
+//Weather Settings
+#define CITY_ID "5128581" //New York City https://openweathermap.org/current#cityid
+#define OPENWEATHERMAP_APIKEY "f058fe1cad2afe8e2ddc5d063a64cecb" //use your own API key :)
+#define OPENWEATHERMAP_URL "http://api.openweathermap.org/data/2.5/weather?id=" //open weather api
+#define TEMP_UNIT "metric" //metric = Celsius , imperial = Fahrenheit
+#define TEMP_LANG "en"
+#define WEATHER_UPDATE_INTERVAL 30 //must be greater than 5, measured in minutes
+//NTP Settings
+#define NTP_SERVER "pool.ntp.org"
+#define GMT_OFFSET_SEC 3600 * -5 //New York is UTC -5
+#define DST_OFFSET_SEC 3600
+
+watchySettings settings{
+ CITY_ID,
+ OPENWEATHERMAP_APIKEY,
+ OPENWEATHERMAP_URL,
+ TEMP_UNIT,
+ TEMP_LANG,
+ WEATHER_UPDATE_INTERVAL,
+ NTP_SERVER,
+ GMT_OFFSET_SEC,
+ DST_OFFSET_SEC
+};
+
+#endif
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..b94d089
--- /dev/null
+++ b/test/README
@@ -0,0 +1,11 @@
+
+This directory is intended for PlatformIO Unit Testing and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PlatformIO Unit Testing:
+- https://docs.platformio.org/page/plus/unit-testing.html