From cdc4f9178e5a0bf3364ffed28a4346845f57de56 Mon Sep 17 00:00:00 2001 From: Jeija Date: Fri, 11 Mar 2016 10:52:59 +0100 Subject: [PATCH] Initial Upload - Hardware, software, production files, BOM, ... --- .gitignore | 4 + README.md | 39 + board/v1/.gitignore | 1 + board/v1/README.md | 42 + board/v1/fp-lib-table | 3 + board/v1/gerber/handgelenk.gbl | 4533 ++++++++++++++ board/v1/gerber/handgelenk.gbo | 1014 ++++ board/v1/gerber/handgelenk.gbs | 132 + board/v1/gerber/handgelenk.gml | 53 + board/v1/gerber/handgelenk.gtl | 5213 +++++++++++++++++ board/v1/gerber/handgelenk.gto | 2862 +++++++++ board/v1/gerber/handgelenk.gts | 270 + board/v1/gerber/handgelenk.txt | 89 + board/v1/gerber/handgelenk.zip | Bin 0 -> 48659 bytes board/v1/handgelenk-cache.lib | 514 ++ board/v1/handgelenk.kicad_pcb | 4251 ++++++++++++++ board/v1/handgelenk.net | 1040 ++++ board/v1/handgelenk.pro | 118 + board/v1/handgelenk.sch | 1221 ++++ board/v1/handgelenk.xml | 1264 ++++ board/v1/lib/er-oled-ssd1306.dcm | 3 + board/v1/lib/er-oled-ssd1306.lib | 46 + board/v1/lib/esp8266ex.dcm | 3 + board/v1/lib/esp8266ex.lib | 49 + board/v1/lib/ft232rq.bck | 3 + board/v1/lib/ft232rq.dcm | 3 + board/v1/lib/ft232rq.lib | 52 + board/v1/lib/lt1129cst.dcm | 9 + board/v1/lib/lt1129cst.lib | 23 + board/v1/lib/mcp73831.dcm | 3 + board/v1/lib/mcp73831.lib | 24 + board/v1/lib/mpu9250.dcm | 3 + board/v1/lib/mpu9250.lib | 32 + board/v1/lib/rv3029c2.dcm | 3 + board/v1/lib/rv3029c2.lib | 24 + board/v1/lib/tlv70233.dcm | 3 + board/v1/lib/tlv70233.lib | 20 + board/v1/lib/w25q32bv.bck | 3 + board/v1/lib/w25q32bv.dcm | 3 + board/v1/lib/w25q32bv.lib | 24 + board/v1/mod/an9520.kicad_mod | 12 + board/v1/mod/crystal_2.5x2.kicad_mod | 16 + board/v1/mod/er-oled-ssd1306.kicad_mod | 57 + board/v1/mod/rv3029.kicad_mod | 24 + board/v1/mod/ts015a.kicad_mod | 19 + board/v1/mod/wifilogo.kicad_mod | 109 + board/v1/mod/wson8_5x6.kicad_mod | 25 + board/v1/mpu9250.sch | 239 + board/v1/power.sch | 640 ++ board/v1/rv3029c2.sch | 200 + firmwares/README.md | 2 + firmwares/compass/.gitignore | 2 + firmwares/compass/Makefile | 64 + firmwares/compass/ldscript.ld | 214 + firmwares/compass/src/buttons.c | 27 + firmwares/compass/src/buttons.h | 14 + firmwares/compass/src/font.h | 199 + firmwares/compass/src/httpclient.c | 483 ++ firmwares/compass/src/httpclient.h | 50 + firmwares/compass/src/i2c_master.c | 316 + firmwares/compass/src/i2c_master.h | 39 + firmwares/compass/src/i2cdevice.c | 118 + firmwares/compass/src/i2cdevice.h | 16 + firmwares/compass/src/main.c | 114 + firmwares/compass/src/mpu9250.c | 146 + firmwares/compass/src/mpu9250.h | 39 + firmwares/compass/src/mpu9250_reg.h | 388 ++ firmwares/compass/src/rv3029.c | 117 + firmwares/compass/src/rv3029.h | 30 + firmwares/compass/src/ssd1306.c | 310 + firmwares/compass/src/ssd1306.h | 90 + firmwares/compass/src/user_config.h | 5 + firmwares/compass/src/util.c | 26 + firmwares/compass/src/util.h | 16 + firmwares/compass/src/vector.c | 19 + firmwares/compass/src/vector.h | 29 + firmwares/minetest/.gitignore | 2 + firmwares/minetest/Makefile | 76 + firmwares/minetest/html/index.html | 11 + firmwares/minetest/ldscript.ld | 214 + firmwares/minetest/libesphttpd/.gitignore | 12 + firmwares/minetest/libesphttpd/.gitmodules | 3 + firmwares/minetest/libesphttpd/Makefile | 191 + firmwares/minetest/libesphttpd/README.md | 320 + firmwares/minetest/libesphttpd/core/auth.c | 61 + firmwares/minetest/libesphttpd/core/base64.c | 109 + firmwares/minetest/libesphttpd/core/base64.h | 6 + .../libesphttpd/core/httpd-freertos.c | 243 + .../minetest/libesphttpd/core/httpd-nonos.c | 76 + .../libesphttpd/core/httpd-platform.h | 9 + firmwares/minetest/libesphttpd/core/httpd.c | 775 +++ .../minetest/libesphttpd/core/httpdespfs.c | 189 + firmwares/minetest/libesphttpd/core/sha1.c | 168 + firmwares/minetest/libesphttpd/espfs/espfs.c | 269 + .../minetest/libesphttpd/espfs/espfsformat.h | 33 + .../libesphttpd/espfs/espfstest/Makefile | 13 + .../libesphttpd/espfs/espfstest/main.c | 67 + .../espfs/heatshrink_config_custom.h | 25 + .../libesphttpd/espfs/heatshrink_decoder.c | 17 + .../libesphttpd/espfs/mkespfsimage/Makefile | 24 + .../espfs/mkespfsimage/heatshrink_encoder.c | 4 + .../libesphttpd/espfs/mkespfsimage/main.c | 362 ++ firmwares/minetest/libesphttpd/include/auth.h | 22 + .../minetest/libesphttpd/include/captdns.h | 5 + .../minetest/libesphttpd/include/cgiflash.h | 22 + .../libesphttpd/include/cgiwebsocket.h | 37 + .../minetest/libesphttpd/include/cgiwifi.h | 13 + .../minetest/libesphttpd/include/esp8266.h | 27 + .../minetest/libesphttpd/include/espfs.h | 23 + .../libesphttpd/include/espmissingincludes.h | 76 + .../minetest/libesphttpd/include/httpd.h | 83 + .../minetest/libesphttpd/include/httpdespfs.h | 9 + .../minetest/libesphttpd/include/platform.h | 33 + firmwares/minetest/libesphttpd/include/sha1.h | 39 + .../libesphttpd/include/user_config.h | 1 + .../libesphttpd/include/webpages-espfs.h | 3 + .../libesphttpd/lib/heatshrink/.gitignore | 6 + .../libesphttpd/lib/heatshrink/.travis.yml | 9 + .../libesphttpd/lib/heatshrink/LICENSE | 14 + .../libesphttpd/lib/heatshrink/Makefile | 49 + .../libesphttpd/lib/heatshrink/README.md | 49 + .../libesphttpd/lib/heatshrink/dec_sm.dot | 52 + .../libesphttpd/lib/heatshrink/enc_sm.dot | 51 + .../libesphttpd/lib/heatshrink/greatest.h | 591 ++ .../libesphttpd/lib/heatshrink/heatshrink.c | 446 ++ .../lib/heatshrink/heatshrink_common.h | 20 + .../lib/heatshrink/heatshrink_config.h | 24 + .../lib/heatshrink/heatshrink_decoder.c | 382 ++ .../lib/heatshrink/heatshrink_decoder.h | 101 + .../lib/heatshrink/heatshrink_encoder.c | 650 ++ .../lib/heatshrink/heatshrink_encoder.h | 109 + .../lib/heatshrink/test_heatshrink_dynamic.c | 999 ++++ .../test_heatshrink_dynamic_theft.c | 521 ++ .../lib/heatshrink/test_heatshrink_static.c | 167 + .../minetest/libesphttpd/mkupgimg/.gitignore | 1 + .../minetest/libesphttpd/mkupgimg/Makefile | 5 + .../minetest/libesphttpd/mkupgimg/mkupgimg.c | 92 + firmwares/minetest/libesphttpd/util/captdns.c | 331 ++ .../minetest/libesphttpd/util/cgiflash.c | 323 + .../minetest/libesphttpd/util/cgiwebsocket.c | 354 ++ firmwares/minetest/libesphttpd/util/cgiwifi.c | 314 + .../minetest/libesphttpd/webpages.espfs.ld | 12 + firmwares/minetest/src/buttons.c | 27 + firmwares/minetest/src/buttons.h | 14 + firmwares/minetest/src/font.h | 199 + firmwares/minetest/src/httpclient.c | 483 ++ firmwares/minetest/src/httpclient.h | 50 + firmwares/minetest/src/i2c_master.c | 316 + firmwares/minetest/src/i2c_master.h | 39 + firmwares/minetest/src/i2cdevice.c | 118 + firmwares/minetest/src/i2cdevice.h | 16 + firmwares/minetest/src/main.c | 158 + firmwares/minetest/src/mpu9250.c | 182 + firmwares/minetest/src/mpu9250.h | 61 + firmwares/minetest/src/mpu9250_reg.h | 388 ++ firmwares/minetest/src/rv3029.c | 117 + firmwares/minetest/src/rv3029.h | 30 + firmwares/minetest/src/ssd1306.c | 310 + firmwares/minetest/src/ssd1306.h | 90 + firmwares/minetest/src/user_config.h | 5 + firmwares/minetest/src/util.c | 26 + firmwares/minetest/src/util.h | 16 + firmwares/minetest/src/vector.c | 19 + firmwares/minetest/src/vector.h | 29 + firmwares/wifitime/.gitignore | 2 + firmwares/wifitime/Makefile | 63 + firmwares/wifitime/src/font.h | 199 + firmwares/wifitime/src/httpclient.c | 483 ++ firmwares/wifitime/src/httpclient.h | 50 + firmwares/wifitime/src/i2c_master.c | 316 + firmwares/wifitime/src/i2c_master.h | 39 + firmwares/wifitime/src/main.c | 170 + firmwares/wifitime/src/rv3029.c | 120 + firmwares/wifitime/src/rv3029.h | 22 + firmwares/wifitime/src/ssd1306.c | 285 + firmwares/wifitime/src/ssd1306.h | 80 + firmwares/wifitime/src/user_config.h | 5 + firmwares/wifitime/src/util.c | 25 + firmwares/wifitime/src/util.h | 7 + model/model.scad | 162 + 180 files changed, 41275 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 board/v1/.gitignore create mode 100644 board/v1/README.md create mode 100644 board/v1/fp-lib-table create mode 100644 board/v1/gerber/handgelenk.gbl create mode 100644 board/v1/gerber/handgelenk.gbo create mode 100644 board/v1/gerber/handgelenk.gbs create mode 100644 board/v1/gerber/handgelenk.gml create mode 100644 board/v1/gerber/handgelenk.gtl create mode 100644 board/v1/gerber/handgelenk.gto create mode 100644 board/v1/gerber/handgelenk.gts create mode 100644 board/v1/gerber/handgelenk.txt create mode 100644 board/v1/gerber/handgelenk.zip create mode 100644 board/v1/handgelenk-cache.lib create mode 100644 board/v1/handgelenk.kicad_pcb create mode 100644 board/v1/handgelenk.net create mode 100644 board/v1/handgelenk.pro create mode 100644 board/v1/handgelenk.sch create mode 100644 board/v1/handgelenk.xml create mode 100644 board/v1/lib/er-oled-ssd1306.dcm create mode 100644 board/v1/lib/er-oled-ssd1306.lib create mode 100644 board/v1/lib/esp8266ex.dcm create mode 100644 board/v1/lib/esp8266ex.lib create mode 100644 board/v1/lib/ft232rq.bck create mode 100644 board/v1/lib/ft232rq.dcm create mode 100644 board/v1/lib/ft232rq.lib create mode 100644 board/v1/lib/lt1129cst.dcm create mode 100644 board/v1/lib/lt1129cst.lib create mode 100644 board/v1/lib/mcp73831.dcm create mode 100644 board/v1/lib/mcp73831.lib create mode 100644 board/v1/lib/mpu9250.dcm create mode 100644 board/v1/lib/mpu9250.lib create mode 100644 board/v1/lib/rv3029c2.dcm create mode 100644 board/v1/lib/rv3029c2.lib create mode 100644 board/v1/lib/tlv70233.dcm create mode 100644 board/v1/lib/tlv70233.lib create mode 100644 board/v1/lib/w25q32bv.bck create mode 100644 board/v1/lib/w25q32bv.dcm create mode 100644 board/v1/lib/w25q32bv.lib create mode 100644 board/v1/mod/an9520.kicad_mod create mode 100644 board/v1/mod/crystal_2.5x2.kicad_mod create mode 100644 board/v1/mod/er-oled-ssd1306.kicad_mod create mode 100644 board/v1/mod/rv3029.kicad_mod create mode 100644 board/v1/mod/ts015a.kicad_mod create mode 100644 board/v1/mod/wifilogo.kicad_mod create mode 100644 board/v1/mod/wson8_5x6.kicad_mod create mode 100644 board/v1/mpu9250.sch create mode 100644 board/v1/power.sch create mode 100644 board/v1/rv3029c2.sch create mode 100644 firmwares/README.md create mode 100644 firmwares/compass/.gitignore create mode 100644 firmwares/compass/Makefile create mode 100644 firmwares/compass/ldscript.ld create mode 100644 firmwares/compass/src/buttons.c create mode 100644 firmwares/compass/src/buttons.h create mode 100644 firmwares/compass/src/font.h create mode 100644 firmwares/compass/src/httpclient.c create mode 100644 firmwares/compass/src/httpclient.h create mode 100644 firmwares/compass/src/i2c_master.c create mode 100644 firmwares/compass/src/i2c_master.h create mode 100644 firmwares/compass/src/i2cdevice.c create mode 100644 firmwares/compass/src/i2cdevice.h create mode 100644 firmwares/compass/src/main.c create mode 100644 firmwares/compass/src/mpu9250.c create mode 100644 firmwares/compass/src/mpu9250.h create mode 100644 firmwares/compass/src/mpu9250_reg.h create mode 100644 firmwares/compass/src/rv3029.c create mode 100644 firmwares/compass/src/rv3029.h create mode 100644 firmwares/compass/src/ssd1306.c create mode 100644 firmwares/compass/src/ssd1306.h create mode 100644 firmwares/compass/src/user_config.h create mode 100644 firmwares/compass/src/util.c create mode 100644 firmwares/compass/src/util.h create mode 100644 firmwares/compass/src/vector.c create mode 100644 firmwares/compass/src/vector.h create mode 100644 firmwares/minetest/.gitignore create mode 100644 firmwares/minetest/Makefile create mode 100644 firmwares/minetest/html/index.html create mode 100644 firmwares/minetest/ldscript.ld create mode 100644 firmwares/minetest/libesphttpd/.gitignore create mode 100644 firmwares/minetest/libesphttpd/.gitmodules create mode 100644 firmwares/minetest/libesphttpd/Makefile create mode 100644 firmwares/minetest/libesphttpd/README.md create mode 100644 firmwares/minetest/libesphttpd/core/auth.c create mode 100644 firmwares/minetest/libesphttpd/core/base64.c create mode 100644 firmwares/minetest/libesphttpd/core/base64.h create mode 100644 firmwares/minetest/libesphttpd/core/httpd-freertos.c create mode 100644 firmwares/minetest/libesphttpd/core/httpd-nonos.c create mode 100644 firmwares/minetest/libesphttpd/core/httpd-platform.h create mode 100644 firmwares/minetest/libesphttpd/core/httpd.c create mode 100644 firmwares/minetest/libesphttpd/core/httpdespfs.c create mode 100644 firmwares/minetest/libesphttpd/core/sha1.c create mode 100644 firmwares/minetest/libesphttpd/espfs/espfs.c create mode 100644 firmwares/minetest/libesphttpd/espfs/espfsformat.h create mode 100644 firmwares/minetest/libesphttpd/espfs/espfstest/Makefile create mode 100644 firmwares/minetest/libesphttpd/espfs/espfstest/main.c create mode 100644 firmwares/minetest/libesphttpd/espfs/heatshrink_config_custom.h create mode 100644 firmwares/minetest/libesphttpd/espfs/heatshrink_decoder.c create mode 100644 firmwares/minetest/libesphttpd/espfs/mkespfsimage/Makefile create mode 100644 firmwares/minetest/libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c create mode 100644 firmwares/minetest/libesphttpd/espfs/mkespfsimage/main.c create mode 100644 firmwares/minetest/libesphttpd/include/auth.h create mode 100644 firmwares/minetest/libesphttpd/include/captdns.h create mode 100644 firmwares/minetest/libesphttpd/include/cgiflash.h create mode 100644 firmwares/minetest/libesphttpd/include/cgiwebsocket.h create mode 100644 firmwares/minetest/libesphttpd/include/cgiwifi.h create mode 100644 firmwares/minetest/libesphttpd/include/esp8266.h create mode 100644 firmwares/minetest/libesphttpd/include/espfs.h create mode 100644 firmwares/minetest/libesphttpd/include/espmissingincludes.h create mode 100644 firmwares/minetest/libesphttpd/include/httpd.h create mode 100644 firmwares/minetest/libesphttpd/include/httpdespfs.h create mode 100644 firmwares/minetest/libesphttpd/include/platform.h create mode 100644 firmwares/minetest/libesphttpd/include/sha1.h create mode 100644 firmwares/minetest/libesphttpd/include/user_config.h create mode 100644 firmwares/minetest/libesphttpd/include/webpages-espfs.h create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/.gitignore create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/.travis.yml create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/LICENSE create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/Makefile create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/README.md create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/dec_sm.dot create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/enc_sm.dot create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/greatest.h create mode 100755 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink.c create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_common.h create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_config.h create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.c create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.h create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.c create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.h create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic.c create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic_theft.c create mode 100644 firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_static.c create mode 100644 firmwares/minetest/libesphttpd/mkupgimg/.gitignore create mode 100644 firmwares/minetest/libesphttpd/mkupgimg/Makefile create mode 100644 firmwares/minetest/libesphttpd/mkupgimg/mkupgimg.c create mode 100644 firmwares/minetest/libesphttpd/util/captdns.c create mode 100644 firmwares/minetest/libesphttpd/util/cgiflash.c create mode 100644 firmwares/minetest/libesphttpd/util/cgiwebsocket.c create mode 100644 firmwares/minetest/libesphttpd/util/cgiwifi.c create mode 100644 firmwares/minetest/libesphttpd/webpages.espfs.ld create mode 100644 firmwares/minetest/src/buttons.c create mode 100644 firmwares/minetest/src/buttons.h create mode 100644 firmwares/minetest/src/font.h create mode 100644 firmwares/minetest/src/httpclient.c create mode 100644 firmwares/minetest/src/httpclient.h create mode 100644 firmwares/minetest/src/i2c_master.c create mode 100644 firmwares/minetest/src/i2c_master.h create mode 100644 firmwares/minetest/src/i2cdevice.c create mode 100644 firmwares/minetest/src/i2cdevice.h create mode 100644 firmwares/minetest/src/main.c create mode 100644 firmwares/minetest/src/mpu9250.c create mode 100644 firmwares/minetest/src/mpu9250.h create mode 100644 firmwares/minetest/src/mpu9250_reg.h create mode 100644 firmwares/minetest/src/rv3029.c create mode 100644 firmwares/minetest/src/rv3029.h create mode 100644 firmwares/minetest/src/ssd1306.c create mode 100644 firmwares/minetest/src/ssd1306.h create mode 100644 firmwares/minetest/src/user_config.h create mode 100644 firmwares/minetest/src/util.c create mode 100644 firmwares/minetest/src/util.h create mode 100644 firmwares/minetest/src/vector.c create mode 100644 firmwares/minetest/src/vector.h create mode 100644 firmwares/wifitime/.gitignore create mode 100644 firmwares/wifitime/Makefile create mode 100644 firmwares/wifitime/src/font.h create mode 100644 firmwares/wifitime/src/httpclient.c create mode 100644 firmwares/wifitime/src/httpclient.h create mode 100644 firmwares/wifitime/src/i2c_master.c create mode 100644 firmwares/wifitime/src/i2c_master.h create mode 100644 firmwares/wifitime/src/main.c create mode 100644 firmwares/wifitime/src/rv3029.c create mode 100644 firmwares/wifitime/src/rv3029.h create mode 100644 firmwares/wifitime/src/ssd1306.c create mode 100644 firmwares/wifitime/src/ssd1306.h create mode 100644 firmwares/wifitime/src/user_config.h create mode 100644 firmwares/wifitime/src/util.c create mode 100644 firmwares/wifitime/src/util.h create mode 100644 model/model.scad diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fc4a74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +*.bak +firmwares/*/build +firmwares/*/obj diff --git a/README.md b/README.md new file mode 100644 index 0000000..f949bd0 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# ESP8266 Smartwatch +## Pictures / Videos +![Features overview](http://i.imgur.com/IAOPWqe.jpg) +![Side view](http://i.imgur.com/wB7QXaz.jpg) +![On a wrist](http://i.imgur.com/c6pgJzJ.jpg) + +#### YouTube Videos +* [Building the watch](https://www.youtube.com/watch?v=ve8lzYSVnGo) +* [Minetest controller](https://www.youtube.com/watch?v=W3ALEUs_7kA) +* [Compass test](https://www.youtube.com/watch?v=Mj3a6peVI30) + +# Hardware +## Specifications +* ESP8266 with 32Mbit of flash memory +* MPU-9250 gyroscope, accelerometer with integrated AK8963 magnetometer +* RV-3029-C2 Real Time Clock +* FT232RQ for USB communication +* SSD1306 OLED Display, 128x64 +* 3 Hardware Buttons +* MCP73831 LiPo charger +* 250mAh LiPo battery +* Dimensions: 35 * 39 * 11mm +* WiFi with chip antenna +* Vibration Motor + +See `board/v1/README.md` for a detailed parts list. + +# Software +The firmwares in `firmwares` use the [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk). You may need to customize the `main.c` files to reflect your WiFi configuration. This is mainly a hardware project and not a software project, so the firmwares are primarily meant to be demos for the hardware features of the watch. Firmwares can be uploaded using [esptool](https://github.com/themadinventor/esptool) and debugging is possible with a serial port terminal like [espterm](https://github.com/Jeija/espterm). + +# Attribution +* `libesphttpd` (used in the minetest firmware) was [written by Spritetm](https://github.com/Spritetm/libesphttpd) and contributors and is licensed under "THE BEER-WARE LICENSE". +* `httpclient.c` / `httpclient.h` (included in all firmwares) was [written by Caerbannog](https://github.com/Caerbannog/esphttpclient) and contributors and is licensed under "THE BEER-WARE LICENSE". +* `i2c_master.h` / `i2c_master.c` was written by Espressif Systems + +# License +The hardware design (schematic, PCB design, footprints, ...) is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/) (CC-BY-NC-SA). + +The firmware source code is licensed under the [MIT License](https://opensource.org/licenses/MIT). diff --git a/board/v1/.gitignore b/board/v1/.gitignore new file mode 100644 index 0000000..751553b --- /dev/null +++ b/board/v1/.gitignore @@ -0,0 +1 @@ +*.bak diff --git a/board/v1/README.md b/board/v1/README.md new file mode 100644 index 0000000..109a6b8 --- /dev/null +++ b/board/v1/README.md @@ -0,0 +1,42 @@ +# ESP8266 Smartwatch Hardware V1 +## Parts list +* 1x PCB +* 1x ESP8266EX WiFi SoC +* 1x FT232RQ USB to UART +* 1x MCP73831 LiPo charger +* 1x TLV70233 SOT-23 LDO (or compatible) +* 1x W25Q32BV 32Mbit flash +* 1x InvenSense MPU-9250 9-axis sensor +* 1x RV-3029-C2 RTC +* 1x 26MHz crystal 2.5x2mm +* 1x Rainsun AN9520 Chip Antenna +* 3x TS-015A / WS-TUS 434331045822 Buttons +* 1x muRata BLM21PG 600 EMI Suppression Filter +* 1x USB Micro B connector, SMD +* 1x EastRising SSD1306 OLED +* 1x 250mAh LiPo +* 1x Low power vibration motor +* 1x BC849 SOT-23 NPN transistor +* 6x 100nF 0603 Capacitor +* 3x 10nF 0603 Capacitor +* 2x 4.7µF 0603 Capacitor +* 1x 100µF 1206 Capacitor +* 1x 10µF 1206 Capacitor +* 1x 5.6pF 0402 Capacitor +* 2x 10pF 0402 Capacitor +* 5x 1µF 0603 Capacitor +* 1x 2.2µF 0603 Capacitor +* 3x 1N4148 SOD-323 Diode +* 2x 1K 0603 Resistor +* 1x 12K 0603 Resistor +* 1x 3.3K 0603 Resistor +* 1x 300 0603 Resistor +* 1x 200 0603 Resistor +* 1x 330K 0603 Resistor +* 1x 100K 0603 Resistor +* 4x 10K 0603 Resistor +* 1x 50 0603 Resistor +* 1x 390K 0603 Resistor + +## Production files +See the `gerber` directory for original PCB production files. My PCBs were manufactured by Seeedstudio's PCB service. diff --git a/board/v1/fp-lib-table b/board/v1/fp-lib-table new file mode 100644 index 0000000..4370b2b --- /dev/null +++ b/board/v1/fp-lib-table @@ -0,0 +1,3 @@ +(fp_lib_table + (lib (name "Project Libraries")(type KiCad)(uri "$(KIPRJMOD)/mod")(options "")(descr "")) +) diff --git a/board/v1/gerber/handgelenk.gbl b/board/v1/gerber/handgelenk.gbl new file mode 100644 index 0000000..558abca --- /dev/null +++ b/board/v1/gerber/handgelenk.gbl @@ -0,0 +1,4533 @@ +G04 #@! TF.FileFunction,Copper,L2,Bot,Signal* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11R,0.400000X3.000000*% +%ADD12R,2.032000X2.032000*% +%ADD13O,2.032000X2.032000*% +%ADD14R,0.450000X0.590000*% +%ADD15R,0.900000X0.500000*% +%ADD16R,1.350000X0.400000*% +%ADD17O,0.950000X1.250000*% +%ADD18O,1.550000X1.000000*% +%ADD19R,0.750000X0.800000*% +%ADD20R,0.590000X0.450000*% +%ADD21R,0.800100X0.800100*% +%ADD22R,1.000000X1.200000*% +%ADD23C,0.600000*% +%ADD24C,2.500000*% +%ADD25C,0.600000*% +%ADD26C,0.450000*% +%ADD27C,0.350000*% +%ADD28C,0.300000*% +%ADD29C,0.200000*% +%ADD30C,0.254000*% +G04 APERTURE END LIST* +D10* +D11* +X47650000Y-27250000D03* +X46950000Y-27250000D03* +X46250000Y-27250000D03* +X45550000Y-27250000D03* +X44850000Y-27250000D03* +X43450000Y-27250000D03* +X42750000Y-27250000D03* +X42050000Y-27250000D03* +X41350000Y-27250000D03* +X40650000Y-27250000D03* +X39950000Y-27250000D03* +X39250000Y-27250000D03* +X38550000Y-27250000D03* +X37850000Y-27250000D03* +X37150000Y-27250000D03* +X36450000Y-27250000D03* +X35750000Y-27250000D03* +X35050000Y-27250000D03* +X34350000Y-27250000D03* +X33650000Y-27250000D03* +X32950000Y-27250000D03* +X32250000Y-27250000D03* +X31550000Y-27250000D03* +X30850000Y-27250000D03* +X30150000Y-27250000D03* +X29450000Y-27250000D03* +X28750000Y-27250000D03* +X28050000Y-27250000D03* +X27350000Y-27250000D03* +X44150000Y-27250000D03* +D12* +X43726696Y-41500000D03* +D13* +X46266696Y-41500000D03* +D14* +X42000000Y-33805000D03* +X42000000Y-31695000D03* +D15* +X40000000Y-32000000D03* +X40000000Y-33500000D03* +D16* +X24312540Y-46550900D03* +X24312540Y-45900900D03* +X24312540Y-45250900D03* +X24312540Y-44600900D03* +X24312540Y-43950900D03* +D17* +X24312540Y-47750900D03* +X24312540Y-42750900D03* +D18* +X21612540Y-48750900D03* +X21612540Y-41750900D03* +D12* +X35500000Y-47750000D03* +D13* +X35500000Y-45210000D03* +D19* +X50500000Y-24250000D03* +X50500000Y-25750000D03* +X50500000Y-45750000D03* +X50500000Y-44250000D03* +X45750000Y-32000000D03* +X45750000Y-33500000D03* +X44000000Y-32000000D03* +X44000000Y-33500000D03* +X30250000Y-32000000D03* +X30250000Y-33500000D03* +X26750000Y-32000000D03* +X26750000Y-33500000D03* +X49250000Y-33500000D03* +X49250000Y-32000000D03* +X47500000Y-33500000D03* +X47500000Y-32000000D03* +X28500000Y-32000000D03* +X28500000Y-33500000D03* +D20* +X52195000Y-30000000D03* +X54305000Y-30000000D03* +X52195000Y-40000000D03* +X54305000Y-40000000D03* +D21* +X45276696Y-36999240D03* +X47176696Y-36999240D03* +X46226696Y-38998220D03* +D15* +X43226696Y-37250000D03* +X43226696Y-38750000D03* +X34500000Y-33500000D03* +X34500000Y-32000000D03* +X36250000Y-33500000D03* +X36250000Y-32000000D03* +X50500000Y-41250000D03* +X50500000Y-42750000D03* +X32000000Y-32000000D03* +X32000000Y-33500000D03* +D22* +X54100000Y-27800000D03* +X54100000Y-22200000D03* +X52400000Y-27800000D03* +X52400000Y-22200000D03* +X54100000Y-47800000D03* +X54100000Y-42200000D03* +X52400000Y-47800000D03* +X52400000Y-42200000D03* +X54100000Y-37800000D03* +X54100000Y-32200000D03* +X52400000Y-37800000D03* +X52400000Y-32200000D03* +D23* +X29900000Y-35000000D03* +X26250000Y-24520075D03* +X44700000Y-22300000D03* +X37300000Y-23200000D03* +X45773137Y-24850633D03* +X44300000Y-30700000D03* +X32200000Y-29600000D03* +X26000000Y-30520010D03* +X28998135Y-23257462D03* +X26250000Y-26500000D03* +X50500000Y-20900000D03* +D24* +X48052703Y-46736498D03* +D23* +X48600000Y-43400000D03* +X31190415Y-33500000D03* +X31200000Y-34300000D03* +X30362500Y-42112500D03* +X30362500Y-40387500D03* +X31000000Y-23257453D03* +X26800000Y-22000000D03* +X34662300Y-21520576D03* +X47085702Y-23498198D03* +X47900000Y-23500000D03* +X28600000Y-42200000D03* +X28600000Y-40400000D03* +X38550886Y-33350886D03* +X49400000Y-44200000D03* +X30850000Y-25571545D03* +X28050000Y-25534450D03* +X25500000Y-46500000D03* +X41000000Y-49000000D03* +X48500000Y-25300000D03* +X26900000Y-24000000D03* +X36400000Y-35000000D03* +X26179990Y-35500000D03* +X23229990Y-24857438D03* +X46300000Y-38100000D03* +X26000000Y-42250000D03* +X26000000Y-41250000D03* +X29300000Y-34300000D03* +X34200000Y-40300000D03* +X26026518Y-28879990D03* +X23750000Y-24250000D03* +X39500000Y-43800000D03* +X33700000Y-37180031D03* +X43800000Y-35100000D03* +X38113097Y-33922501D03* +X45300000Y-35000000D03* +X33442665Y-32700000D03* +X35167799Y-36867799D03* +X34000000Y-34500000D03* +X33679990Y-40809118D03* +X30800000Y-37900000D03* +X38873521Y-36140020D03* +X37092994Y-38207006D03* +X37086558Y-34289702D03* +X35900000Y-22300000D03* +X35890882Y-35520010D03* +D25* +X26250000Y-24520075D02* +X26250000Y-24415602D01* +X26250000Y-24415602D02* +X26179999Y-24345601D01* +X26179999Y-24345601D02* +X26179999Y-23654399D01* +X26179999Y-23654399D02* +X26576936Y-23257462D01* +X26576936Y-23257462D02* +X28573871Y-23257462D01* +X28573871Y-23257462D02* +X28998135Y-23257462D01* +X26250000Y-26500000D02* +X26250000Y-24520075D01* +X26250000Y-26500000D02* +X26250000Y-28148870D01* +D26* +X26336119Y-28234989D02* +X26250000Y-28148870D01* +X26401130Y-28300000D02* +X26336119Y-28234989D01* +X26336119Y-28234989D02* +X26334989Y-28234989D01* +X26700000Y-29272110D02* +X26700000Y-28598870D01* +X26700000Y-28598870D02* +X26401130Y-28300000D01* +D25* +X26000000Y-30520010D02* +X26000000Y-29972110D01* +X26000000Y-29972110D02* +X26700000Y-29272110D01* +X33288063Y-33500000D02* +X33288063Y-33667939D01* +X33288063Y-33667939D02* +X31936001Y-35020001D01* +X31936001Y-35020001D02* +X29920001Y-35020001D01* +X29920001Y-35020001D02* +X29900000Y-35000000D01* +D26* +X34500000Y-33500000D02* +X33288063Y-33500000D01* +X33288063Y-33500000D02* +X32797664Y-33009601D01* +X32797664Y-33009601D02* +X32797664Y-30197664D01* +X32797664Y-30197664D02* +X32499999Y-29899999D01* +X32499999Y-29899999D02* +X32200000Y-29600000D01* +D25* +X34720003Y-34500000D02* +X34720003Y-33720003D01* +X43726696Y-41500000D02* +X41712033Y-41500000D01* +X41712033Y-41500000D02* +X36452044Y-36240011D01* +X36452044Y-36240011D02* +X35545281Y-36240011D01* +X35545281Y-36240011D02* +X34720003Y-35414733D01* +X34720003Y-35414733D02* +X34720003Y-34924264D01* +X34720003Y-34924264D02* +X34720003Y-34500000D01* +D27* +X44700000Y-22300000D02* +X38200000Y-22300000D01* +X38200000Y-22300000D02* +X37300000Y-23200000D01* +X44699367Y-24850633D02* +X45773137Y-24850633D01* +X44150000Y-27250000D02* +X44150000Y-25400000D01* +X44150000Y-25400000D02* +X44699367Y-24850633D01* +X44144425Y-29303425D02* +X44331650Y-29490650D01* +X44331650Y-29490650D02* +X45750000Y-30909000D01* +X44300000Y-30700000D02* +X44300000Y-29522300D01* +X44300000Y-29522300D02* +X44331650Y-29490650D01* +X34500000Y-33500000D02* +X34300000Y-33500000D01* +X36250000Y-33500000D02* +X34500000Y-33500000D01* +X29005597Y-23250000D02* +X28998135Y-23257462D01* +X43886001Y-29045001D02* +X44144425Y-29303425D01* +X44144425Y-29303425D02* +X44150000Y-29297850D01* +X44150000Y-29297850D02* +X44150000Y-27250000D01* +X45750000Y-30909000D02* +X45750000Y-32000000D01* +X41704999Y-29045001D02* +X42313999Y-29045001D01* +X42050000Y-27250000D02* +X42050000Y-28781002D01* +X44150000Y-28781002D02* +X44150000Y-27250000D01* +X42050000Y-28781002D02* +X42313999Y-29045001D01* +X42313999Y-29045001D02* +X43886001Y-29045001D01* +X43886001Y-29045001D02* +X44150000Y-28781002D01* +X40650000Y-27250000D02* +X40650000Y-28781002D01* +X40650000Y-28781002D02* +X40913999Y-29045001D01* +X40913999Y-29045001D02* +X41704999Y-29045001D01* +X41704999Y-29045001D02* +X42050000Y-28700000D01* +X42050000Y-28700000D02* +X42050000Y-27250000D01* +X32950000Y-27250000D02* +X32250000Y-27250000D01* +X33650000Y-27250000D02* +X32950000Y-27250000D01* +X47176696Y-36999240D02* +X47176696Y-36249190D01* +D25* +X24312540Y-42750900D02* +X24312540Y-43950900D01* +D28* +X31190415Y-33500000D02* +X32000000Y-33500000D01* +D25* +X30250000Y-33500000D02* +X31190415Y-33500000D01* +X30250000Y-33500000D02* +X30400000Y-33500000D01* +X30400000Y-33500000D02* +X31200000Y-34300000D01* +X28500000Y-33500000D02* +X28500000Y-34500000D01* +X28500000Y-34500000D02* +X28400000Y-34600000D01* +D28* +X26750000Y-33500000D02* +X28500000Y-33500000D01* +D25* +X30250000Y-33500000D02* +X28500000Y-33500000D01* +D28* +X27350000Y-27250000D02* +X27350000Y-29976125D01* +X27350000Y-29976125D02* +X26075000Y-31251125D01* +X26075000Y-31251125D02* +X26075000Y-32800000D01* +X26075000Y-32800000D02* +X26750000Y-33475000D01* +X26750000Y-33475000D02* +X26750000Y-33500000D01* +D27* +X21612540Y-41750900D02* +X21612540Y-40900900D01* +X21612540Y-40900900D02* +X23963440Y-38550000D01* +X23963440Y-38550000D02* +X26750000Y-38550000D01* +X30362500Y-42112500D02* +X28687500Y-42112500D01* +X28687500Y-42112500D02* +X28600000Y-42200000D01* +X30362500Y-40387500D02* +X30362500Y-42112500D01* +D28* +X28600000Y-40400000D02* +X30350000Y-40400000D01* +X30350000Y-40400000D02* +X30362500Y-40387500D01* +X26800000Y-22000000D02* +X29742547Y-22000000D01* +X29742547Y-22000000D02* +X31000000Y-23257453D01* +D27* +X34700000Y-23202334D02* +X34700000Y-21558276D01* +X34700000Y-21558276D02* +X34662300Y-21520576D01* +X47900000Y-23500000D02* +X47383734Y-23500000D01* +X47383734Y-23500000D02* +X47087504Y-23500000D01* +X47650000Y-23750000D02* +X47633734Y-23750000D01* +X47633734Y-23750000D02* +X47383734Y-23500000D01* +X47087504Y-23500000D02* +X47085702Y-23498198D01* +X47650000Y-24400000D02* +X47650000Y-23750000D01* +X47650000Y-23750000D02* +X47900000Y-23500000D01* +D28* +X47650000Y-27250000D02* +X49025000Y-27250000D01* +X49025000Y-27250000D02* +X50500000Y-25775000D01* +X50500000Y-25775000D02* +X50500000Y-25750000D01* +X50500000Y-38085306D02* +X50500000Y-31400000D01* +X50500000Y-31400000D02* +X47650000Y-28550000D01* +X47650000Y-28550000D02* +X47650000Y-27250000D01* +D27* +X47200000Y-34500000D02* +X47000000Y-34300000D01* +X47000000Y-34300000D02* +X45800000Y-34300000D01* +X47200000Y-36225886D02* +X47200000Y-34500000D01* +X47176696Y-36249190D02* +X47200000Y-36225886D01* +X45750000Y-33500000D02* +X45750000Y-34250000D01* +X45750000Y-34250000D02* +X45800000Y-34300000D01* +D28* +X28600000Y-41279785D02* +X28600000Y-40400000D01* +X28600000Y-42200000D02* +X28600000Y-41279785D01* +X30200000Y-43816000D02* +X30200000Y-43800000D01* +X30200000Y-43800000D02* +X28600000Y-42200000D01* +X26750000Y-33500000D02* +X26750000Y-38550000D01* +X26750000Y-38550000D02* +X28600000Y-40400000D01* +D27* +X30200000Y-43816000D02* +X30595530Y-44211530D01* +X34134000Y-47750000D02* +X30595530Y-44211530D01* +X38700000Y-33500000D02* +X38550886Y-33350886D01* +X40000000Y-33500000D02* +X38700000Y-33500000D01* +X35500000Y-47750000D02* +X34134000Y-47750000D01* +X48300000Y-38700000D02* +X49114694Y-38700000D01* +X49114694Y-38700000D02* +X49500000Y-39085306D01* +X47176696Y-36999240D02* +X47176696Y-37576696D01* +X47176696Y-37576696D02* +X48300000Y-38700000D01* +X44000000Y-33500000D02* +X45750000Y-33500000D01* +X42000000Y-33805000D02* +X43695000Y-33805000D01* +X43695000Y-33805000D02* +X44000000Y-33500000D01* +X40000000Y-33500000D02* +X41695000Y-33500000D01* +X41695000Y-33500000D02* +X42000000Y-33805000D01* +X34700000Y-23202334D02* +X33650000Y-24252334D01* +X33647666Y-24250000D02* +X36409241Y-24250000D01* +X49400000Y-44200000D02* +X50450000Y-44200000D01* +X50450000Y-44200000D02* +X50500000Y-44250000D01* +X47650000Y-27250000D02* +X47650000Y-24400000D01* +X30850000Y-25571545D02* +X30850000Y-24267181D01* +D28* +X30850000Y-27250000D02* +X30850000Y-25571545D01* +X21612540Y-41750900D02* +X21887540Y-41750900D01* +X21612540Y-48750900D02* +X21612540Y-47950900D01* +X21612540Y-47950900D02* +X21612540Y-41750900D01* +X30200000Y-33550000D02* +X30250000Y-33500000D01* +D27* +X28050000Y-25534450D02* +X28050000Y-24297051D01* +X28050000Y-27250000D02* +X28050000Y-25534450D01* +X39278698Y-24250000D02* +X39936339Y-24250000D01* +X50500000Y-42750000D02* +X50500000Y-44250000D01* +X50500000Y-38085306D02* +X49500000Y-39085306D01* +X49500000Y-39085306D02* +X49500000Y-41950000D01* +X50300000Y-42750000D02* +X50500000Y-42750000D01* +X49500000Y-41950000D02* +X50300000Y-42750000D01* +X41385764Y-24250000D02* +X42716996Y-24250000D01* +X42716996Y-24250000D02* +X47500000Y-24250000D01* +X42750000Y-27250000D02* +X42750000Y-24283004D01* +X42750000Y-24283004D02* +X42716996Y-24250000D01* +X39936339Y-24250000D02* +X41385764Y-24250000D01* +X41350000Y-27250000D02* +X41350000Y-24285764D01* +X41350000Y-24285764D02* +X41385764Y-24250000D01* +X39950000Y-27250000D02* +X39950000Y-25400000D01* +X39950000Y-25400000D02* +X39936339Y-25386339D01* +X39936339Y-25386339D02* +X39936339Y-24250000D01* +X37893663Y-24250000D02* +X39278698Y-24250000D01* +X39250000Y-27250000D02* +X39250000Y-24278698D01* +X39250000Y-24278698D02* +X39278698Y-24250000D01* +X37175014Y-24250000D02* +X37893663Y-24250000D01* +X37850000Y-27250000D02* +X37850000Y-24293663D01* +X37850000Y-24293663D02* +X37893663Y-24250000D01* +X36409241Y-24250000D02* +X37175014Y-24250000D01* +X37150000Y-24275014D02* +X37175014Y-24250000D01* +X37150000Y-27250000D02* +X37150000Y-24275014D01* +X36450000Y-27250000D02* +X36450000Y-24290759D01* +X36450000Y-24290759D02* +X36409241Y-24250000D01* +X32969938Y-24250000D02* +X33647666Y-24250000D01* +X33650000Y-27250000D02* +X33650000Y-24252334D01* +X33650000Y-24252334D02* +X33647666Y-24250000D01* +X32277475Y-24250000D02* +X32969938Y-24250000D01* +X32950000Y-27250000D02* +X32950000Y-24269938D01* +X32950000Y-24269938D02* +X32969938Y-24250000D01* +X31549529Y-24250000D02* +X32277475Y-24250000D01* +X32250000Y-24277475D02* +X32277475Y-24250000D01* +X32250000Y-27250000D02* +X32250000Y-24277475D01* +X30867181Y-24250000D02* +X31549529Y-24250000D01* +X31550000Y-27250000D02* +X31550000Y-24250471D01* +X31550000Y-24250471D02* +X31549529Y-24250000D01* +X28097051Y-24250000D02* +X30867181Y-24250000D01* +X30850000Y-24267181D02* +X30867181Y-24250000D01* +X27500000Y-24250000D02* +X28097051Y-24250000D01* +X28050000Y-24297051D02* +X28097051Y-24250000D01* +X47650000Y-24400000D02* +X47500000Y-24250000D01* +X27500000Y-24250000D02* +X27350000Y-24400000D01* +X27350000Y-24400000D02* +X27350000Y-27250000D01* +X28050000Y-27250000D02* +X27350000Y-27250000D01* +X30850000Y-27250000D02* +X31550000Y-27250000D01* +X31550000Y-27250000D02* +X32250000Y-27250000D01* +X37150000Y-27250000D02* +X36450000Y-27250000D01* +X37850000Y-27250000D02* +X37150000Y-27250000D01* +X39950000Y-27250000D02* +X39250000Y-27250000D01* +D25* +X25500000Y-46500000D02* +X25449100Y-46550900D01* +X25449100Y-46550900D02* +X24312540Y-46550900D01* +D29* +X37210000Y-45210000D02* +X35500000Y-45210000D01* +X41000000Y-49000000D02* +X37210000Y-45210000D01* +X26900000Y-24000000D02* +X27122537Y-23777463D01* +X27122537Y-23777463D02* +X31635811Y-23777463D01* +X31635811Y-23777463D02* +X34412699Y-21000575D01* +X34412699Y-21000575D02* +X34911901Y-21000575D01* +X34911901Y-21000575D02* +X35300000Y-21388674D01* +X35300000Y-21388674D02* +X35300000Y-22680596D01* +X35300000Y-22680596D02* +X36339405Y-23720001D01* +X36339405Y-23720001D02* +X46094297Y-23720001D01* +X46836101Y-22978197D02* +X48147799Y-22978197D01* +X46094297Y-23720001D02* +X46836101Y-22978197D01* +X48147799Y-22978197D02* +X48500000Y-23330398D01* +X48500000Y-23330398D02* +X48500000Y-24833568D01* +X48500000Y-24833568D02* +X48500000Y-25300000D01* +X36400000Y-35000000D02* +X36699999Y-35299999D01* +X36699999Y-35299999D02* +X37263898Y-35299999D01* +X37263898Y-35299999D02* +X40063899Y-38100000D01* +X40063899Y-38100000D02* +X45875736Y-38100000D01* +X45875736Y-38100000D02* +X46300000Y-38100000D01* +X26179990Y-35500000D02* +X23229990Y-32550000D01* +X23229990Y-32550000D02* +X23229990Y-24857438D01* +X24312540Y-45900900D02* +X25349100Y-45900900D01* +X26000000Y-45250000D02* +X26000000Y-42250000D01* +X25349100Y-45900900D02* +X26000000Y-45250000D01* +X23000000Y-45000000D02* +X23250900Y-45250900D01* +X23250900Y-45250900D02* +X24312540Y-45250900D01* +X23000000Y-42750000D02* +X23000000Y-45000000D01* +X24000000Y-41750000D02* +X23000000Y-42750000D01* +X25500000Y-41750000D02* +X24000000Y-41750000D01* +X26000000Y-41250000D02* +X25500000Y-41750000D01* +X29300000Y-34300000D02* +X29300000Y-35400000D01* +X29300000Y-35400000D02* +X34200000Y-40300000D01* +X23750000Y-26250000D02* +X23750000Y-26014248D01* +X23750000Y-26014248D02* +X23750000Y-24250000D01* +X26026518Y-28879990D02* +X25602254Y-28879990D01* +X25602254Y-28879990D02* +X23750000Y-27027736D01* +X23750000Y-27027736D02* +X23750000Y-26014248D01* +X33700000Y-37180031D02* +X39500000Y-42980031D01* +X39500000Y-42980031D02* +X39500000Y-43800000D01* +X39135486Y-34944890D02* +X38113097Y-33922501D01* +X43800000Y-35100000D02* +X39290596Y-35100000D01* +X39290596Y-35100000D02* +X39135486Y-34944890D01* +X36250000Y-31550000D02* +X35750000Y-31050000D01* +X38113097Y-33922501D02* +X38113097Y-33663097D01* +X38113097Y-33663097D02* +X36450000Y-32000000D01* +X36450000Y-32000000D02* +X36250000Y-32000000D01* +X35750000Y-31050000D02* +X35750000Y-28950000D01* +X35750000Y-28950000D02* +X35750000Y-27250000D01* +X36250000Y-32000000D02* +X36250000Y-31550000D01* +X44400000Y-35620010D02* +X44679990Y-35620010D01* +X44679990Y-35620010D02* +X45300000Y-35000000D01* +X34850000Y-32800000D02* +X36720196Y-32800000D01* +X36720196Y-32800000D02* +X37593096Y-33672900D01* +X37593096Y-34172102D02* +X39041004Y-35620010D01* +X37593096Y-33672900D02* +X37593096Y-34172102D01* +X39041004Y-35620010D02* +X44400000Y-35620010D01* +X34500000Y-32000000D02* +X34500000Y-32450000D01* +X34500000Y-32450000D02* +X34850000Y-32800000D01* +X33442665Y-32700000D02* +X33800000Y-32700000D01* +X33800000Y-32700000D02* +X34500000Y-32000000D01* +X34350000Y-27250000D02* +X34350000Y-29677148D01* +X35050000Y-27250000D02* +X34350000Y-27250000D01* +X35050000Y-27250000D02* +X35050000Y-28950000D01* +X35050000Y-28950000D02* +X34350000Y-29650000D01* +X34350000Y-29650000D02* +X34350000Y-29677148D01* +X34350000Y-29677148D02* +X34350000Y-31850000D01* +X34350000Y-31850000D02* +X34500000Y-32000000D01* +X35200000Y-36800000D02* +X34000000Y-35600000D01* +X34000000Y-35600000D02* +X34000000Y-34500000D01* +X30800000Y-37900000D02* +X33679990Y-40779990D01* +X33679990Y-40779990D02* +X33679990Y-40809118D01* +D27* +X50500000Y-45750000D02* +X54078549Y-45750000D01* +D29* +X44600000Y-44200000D02* +X43085988Y-44200000D01* +X43085988Y-44200000D02* +X37092994Y-38207006D01* +X49584989Y-45154591D02* +X49584989Y-46165330D01* +X49584989Y-46165330D02* +X49584990Y-46458554D01* +X51500000Y-48600000D02* +X51500000Y-48373564D01* +X51500000Y-48373564D02* +X49584989Y-46458553D01* +X49584989Y-46458553D02* +X49584989Y-46165330D01* +X51700000Y-48800000D02* +X51500000Y-48600000D01* +X53200000Y-48800000D02* +X51700000Y-48800000D01* +X54100000Y-47900000D02* +X53200000Y-48800000D01* +X48630398Y-44200000D02* +X49584989Y-45154591D01* +X44600000Y-44200000D02* +X48630398Y-44200000D01* +X38873521Y-36140020D02* +X37086558Y-34353057D01* +X37086558Y-34353057D02* +X37086558Y-34289702D01* +X54100000Y-47900000D02* +X54100000Y-47800000D01* +D27* +X54100000Y-42200000D02* +X54100000Y-45728549D01* +X54100000Y-45728549D02* +X54100000Y-47800000D01* +X54078549Y-45750000D02* +X54100000Y-45728549D01* +X54100000Y-42200000D02* +X54100000Y-40205000D01* +X54100000Y-40205000D02* +X54305000Y-40000000D01* +D29* +X43289412Y-21894990D02* +X43090013Y-21894990D01* +X43305010Y-21894990D02* +X43090013Y-21894990D01* +X43090013Y-21894990D02* +X36305010Y-21894990D01* +X49300000Y-20800000D02* +X44400000Y-20800000D01* +X44400000Y-20800000D02* +X43305010Y-21894990D01* +X49920001Y-21420001D02* +X49300000Y-20800000D01* +X53200000Y-21200000D02* +X50969602Y-21200000D01* +X50969602Y-21200000D02* +X50749601Y-21420001D01* +X50749601Y-21420001D02* +X49920001Y-21420001D01* +X54100000Y-22100000D02* +X53200000Y-21200000D01* +X36305010Y-21894990D02* +X36295010Y-21904990D01* +X36295010Y-21904990D02* +X35900000Y-22300000D01* +X54100000Y-22200000D02* +X54100000Y-22100000D01* +X54000000Y-22100000D02* +X54100000Y-22200000D01* +D27* +X54100000Y-26850000D02* +X54100000Y-24222780D01* +X54100000Y-24222780D02* +X54100000Y-22200000D01* +X50500000Y-24250000D02* +X54072780Y-24250000D01* +X54072780Y-24250000D02* +X54100000Y-24222780D01* +X54100000Y-27800000D02* +X54100000Y-26850000D01* +X54305000Y-30000000D02* +X54305000Y-28005000D01* +X54305000Y-28005000D02* +X54100000Y-27800000D01* +D29* +X44000000Y-32000000D02* +X44000000Y-31400000D01* +X44000000Y-31400000D02* +X42700000Y-30100000D01* +X42700000Y-30100000D02* +X40475000Y-30100000D01* +X42000000Y-31695000D02* +X42000000Y-31625000D01* +X42000000Y-31625000D02* +X40475000Y-30100000D01* +X40475000Y-30100000D02* +X38550000Y-30100000D01* +X40000000Y-32000000D02* +X40000000Y-31550000D01* +X40000000Y-31550000D02* +X38550000Y-30100000D01* +X38550000Y-30100000D02* +X38550000Y-28950000D01* +X38550000Y-28950000D02* +X38550000Y-27250000D01* +X30250000Y-32000000D02* +X30250000Y-31400000D01* +X30250000Y-31400000D02* +X29450000Y-30600000D01* +X29450000Y-30600000D02* +X29450000Y-28950000D01* +X29450000Y-28950000D02* +X29450000Y-27250000D01* +X28500000Y-32000000D02* +X28500000Y-29650000D01* +X28500000Y-29650000D02* +X28750000Y-29400000D01* +X26750000Y-32000000D02* +X26750000Y-31400000D01* +X26750000Y-31400000D02* +X28750000Y-29400000D01* +X28750000Y-28950000D02* +X28750000Y-27250000D01* +X28750000Y-29400000D02* +X28750000Y-28950000D01* +X48500000Y-33325000D02* +X48500000Y-31143440D01* +X48500000Y-31143440D02* +X46250000Y-28893440D01* +X46250000Y-28893440D02* +X46250000Y-27250000D01* +X49250000Y-33500000D02* +X48675000Y-33500000D01* +X48675000Y-33500000D02* +X48500000Y-33325000D01* +X49250000Y-32000000D02* +X49250000Y-30946002D01* +X49250000Y-30946002D02* +X46950000Y-28646002D01* +X46950000Y-28646002D02* +X46950000Y-27250000D01* +X46750000Y-30850000D02* +X46750000Y-32725000D01* +X46750000Y-32725000D02* +X47500000Y-33475000D01* +X47500000Y-33475000D02* +X47500000Y-33500000D01* +X44850000Y-27250000D02* +X44850000Y-28950000D01* +X44850000Y-28950000D02* +X46750000Y-30850000D01* +X45550000Y-29150000D02* +X47500000Y-31100000D01* +X47500000Y-31100000D02* +X47500000Y-32000000D01* +X45550000Y-27250000D02* +X45550000Y-29150000D01* +X45550000Y-28646002D02* +X45550000Y-27250000D01* +D27* +X47500000Y-32000000D02* +X47500000Y-31975000D01* +X54100000Y-37800000D02* +X54100000Y-36850000D01* +X54100000Y-36850000D02* +X54100000Y-32200000D01* +X54100000Y-37800000D02* +X54100000Y-38095000D01* +X54100000Y-38095000D02* +X52195000Y-40000000D01* +X54100000Y-32200000D02* +X54100000Y-31905000D01* +X54100000Y-31905000D02* +X52195000Y-30000000D01* +X52195000Y-30000000D02* +X52265000Y-30000000D01* +D29* +X32000000Y-32000000D02* +X32000000Y-31550000D01* +X32000000Y-31550000D02* +X30150000Y-29700000D01* +X30150000Y-29700000D02* +X30150000Y-28950000D01* +X30150000Y-28950000D02* +X30150000Y-27250000D01* +D27* +X46226696Y-38998220D02* +X46226696Y-41460000D01* +X46226696Y-41460000D02* +X46266696Y-41500000D01* +X45276696Y-36999240D02* +X43477456Y-36999240D01* +X43477456Y-36999240D02* +X43226696Y-37250000D01* +D29* +X36625727Y-35667099D02* +X37096549Y-36137921D01* +X37096549Y-36137921D02* +X39708628Y-38750000D01* +X35890882Y-35520010D02* +X36467448Y-35520010D01* +X36467448Y-35520010D02* +X37085359Y-36137921D01* +X37085359Y-36137921D02* +X37096549Y-36137921D01* +X43226696Y-38750000D02* +X41707312Y-38750000D01* +X41707312Y-38750000D02* +X40526309Y-38750000D01* +X39708628Y-38750000D02* +X41707312Y-38750000D01* +X40526309Y-38750000D02* +X40350000Y-38750000D01* +X39950000Y-38750000D02* +X40526309Y-38750000D01* +X50921002Y-45000000D02* +X52400000Y-43521002D01* +X50078998Y-45000000D02* +X50921002Y-45000000D01* +X49904999Y-45173999D02* +X50078998Y-45000000D01* +X49904999Y-46326001D02* +X49904999Y-45173999D01* +X51378998Y-47800000D02* +X49904999Y-46326001D01* +X52400000Y-47800000D02* +X51378998Y-47800000D01* +X52400000Y-43521002D02* +X52400000Y-43000000D01* +X52400000Y-43000000D02* +X52400000Y-42200000D01* +D27* +X52400000Y-37800000D02* +X52400000Y-32200000D01* +X50500000Y-41250000D02* +X50500000Y-38750000D01* +X50500000Y-38750000D02* +X51450000Y-37800000D01* +X51450000Y-37800000D02* +X52400000Y-37800000D01* +X51550000Y-41250000D02* +X50500000Y-41250000D01* +X52400000Y-42100000D02* +X51550000Y-41250000D01* +D29* +X50078998Y-25000000D02* +X50921002Y-25000000D01* +X50921002Y-25000000D02* +X52400000Y-26478998D01* +X52400000Y-26478998D02* +X52400000Y-27000000D01* +X52400000Y-27000000D02* +X52400000Y-27800000D01* +X52400000Y-22200000D02* +X51378998Y-22200000D01* +X51378998Y-22200000D02* +X49904999Y-23673999D01* +X49904999Y-23673999D02* +X49904999Y-24826001D01* +X49904999Y-24826001D02* +X50078998Y-25000000D01* +D27* +X52400000Y-27800000D02* +X52400000Y-27900000D01* +X52400000Y-27900000D02* +X51250000Y-29050000D01* +X51250000Y-30950000D02* +X52400000Y-32100000D01* +X51250000Y-29050000D02* +X51250000Y-30950000D01* +X52400000Y-32100000D02* +X52400000Y-32200000D01* +X52400000Y-37800000D02* +X52400000Y-37900000D01* +X52400000Y-42100000D02* +X52400000Y-42200000D01* +D30* +G36* +X25279106Y-29203138D02* +X25427368Y-29302203D01* +X25542535Y-29325111D01* +X25630122Y-29412850D01* +X25535431Y-29507541D01* +X25393011Y-29720687D01* +X25343000Y-29972110D01* +X25343000Y-30520010D01* +X25342887Y-30650122D01* +X25442698Y-30891684D01* +X25627354Y-31076662D01* +X25748575Y-31126997D01* +X25748577Y-31126999D01* +X25748580Y-31127000D01* +X25868741Y-31176895D01* +X25999997Y-31177009D01* +X26000000Y-31177010D01* +X26000003Y-31177010D01* +X26130112Y-31177123D01* +X26251421Y-31126999D01* +X26251423Y-31126999D01* +X26251425Y-31126998D01* +X26371674Y-31077312D01* +X26556652Y-30892656D01* +X26606987Y-30771435D01* +X26606989Y-30771433D01* +X26606990Y-30771430D01* +X26656885Y-30651269D01* +X26657113Y-30389898D01* +X26657000Y-30389625D01* +X26657000Y-30244248D01* +X27164569Y-29736680D01* +X27306989Y-29523533D01* +X27356999Y-29272110D01* +X27327927Y-29125953D01* +X27490302Y-29288327D01* +X27527474Y-29303724D01* +X27608750Y-29385000D01* +X27676309Y-29385000D01* +X27700000Y-29375187D01* +X27723691Y-29385000D01* +X27791250Y-29385000D01* +X27872526Y-29303724D01* +X27909698Y-29288327D01* +X28088327Y-29109699D01* +X28150000Y-28960807D01* +X28150000Y-29226250D01* +X28213727Y-29289977D01* +X26426852Y-31076852D01* +X26327787Y-31225113D01* +X26323700Y-31245659D01* +X26242704Y-31260899D01* +X26121198Y-31339086D01* +X26039684Y-31458386D01* +X26011006Y-31600000D01* +X26011006Y-32400000D01* +X26035899Y-32532296D01* +X26046490Y-32548754D01* +X26015301Y-32561673D01* +X25836673Y-32740302D01* +X25740000Y-32973691D01* +X25740000Y-33214250D01* +X25898750Y-33373000D01* +X26623000Y-33373000D01* +X26623000Y-33353000D01* +X26877000Y-33353000D01* +X26877000Y-33373000D01* +X27601250Y-33373000D01* +X27625000Y-33349250D01* +X27648750Y-33373000D01* +X28373000Y-33373000D01* +X28373000Y-33353000D01* +X28627000Y-33353000D01* +X28627000Y-33373000D01* +X29351250Y-33373000D01* +X29375000Y-33349250D01* +X29398750Y-33373000D01* +X30123000Y-33373000D01* +X30123000Y-33353000D01* +X30377000Y-33353000D01* +X30377000Y-33373000D01* +X31071750Y-33373000D01* +X31073750Y-33375000D01* +X31873000Y-33375000D01* +X31873000Y-32773750D01* +X31714250Y-32615000D01* +X31423690Y-32615000D01* +X31190301Y-32711673D01* +X31162500Y-32739475D01* +X30984699Y-32561673D01* +X30955012Y-32549376D01* +X30960316Y-32541614D01* +X30988994Y-32400000D01* +X30988994Y-31600000D01* +X30964101Y-31467704D01* +X30885914Y-31346198D01* +X30766614Y-31264684D01* +X30676452Y-31246425D01* +X30672213Y-31225114D01* +X30573148Y-31076852D01* +X29907000Y-30410704D01* +X29907000Y-30103296D01* +X31294815Y-31491111D01* +X31214684Y-31608386D01* +X31186006Y-31750000D01* +X31186006Y-32250000D01* +X31210899Y-32382296D01* +X31289086Y-32503802D01* +X31408386Y-32585316D01* +X31550000Y-32613994D01* +X32215664Y-32613994D01* +X32215664Y-32685086D01* +X32127000Y-32773750D01* +X32127000Y-33375000D01* +X32147000Y-33375000D01* +X32147000Y-33625000D01* +X32127000Y-33625000D01* +X32127000Y-33647000D01* +X31873000Y-33647000D01* +X31873000Y-33625000D01* +X31073750Y-33625000D01* +X31071750Y-33627000D01* +X30377000Y-33627000D01* +X30377000Y-33647000D01* +X30123000Y-33647000D01* +X30123000Y-33627000D01* +X29398750Y-33627000D01* +X29382677Y-33643073D01* +X29367309Y-33643059D01* +X29351250Y-33627000D01* +X28627000Y-33627000D01* +X28627000Y-34376250D01* +X28642920Y-34392170D01* +X28642887Y-34430112D01* +X28742698Y-34671674D01* +X28843000Y-34772151D01* +X28843000Y-35400000D01* +X28877787Y-35574887D01* +X28976852Y-35723148D01* +X30547260Y-37293556D01* +X30428326Y-37342698D01* +X30243348Y-37527354D01* +X30143115Y-37768741D01* +X30142887Y-38030112D01* +X30242698Y-38271674D01* +X30427354Y-38456652D01* +X30668741Y-38556885D01* +X30810713Y-38557009D01* +X33023025Y-40769321D01* +X33022877Y-40939230D01* +X33122688Y-41180792D01* +X33307344Y-41365770D01* +X33548731Y-41466003D01* +X33810102Y-41466231D01* +X34051664Y-41366420D01* +X34236642Y-41181764D01* +X34329926Y-40957113D01* +X34330112Y-40957113D01* +X34571674Y-40857302D01* +X34756652Y-40672646D01* +X34856885Y-40431259D01* +X34857113Y-40169888D01* +X34757302Y-39928326D01* +X34572646Y-39743348D01* +X34331259Y-39643115D01* +X34189286Y-39642991D01* +X31856439Y-37310143D01* +X33042887Y-37310143D01* +X33142698Y-37551705D01* +X33327354Y-37736683D01* +X33568741Y-37836916D01* +X33710713Y-37837040D01* +X39043000Y-43169327D01* +X39043000Y-43327875D01* +X38943348Y-43427354D01* +X38843115Y-43668741D01* +X38842887Y-43930112D01* +X38942698Y-44171674D01* +X39127354Y-44356652D01* +X39368741Y-44456885D01* +X39630112Y-44457113D01* +X39871674Y-44357302D01* +X40056652Y-44172646D01* +X40156885Y-43931259D01* +X40157113Y-43669888D01* +X40057302Y-43428326D01* +X39957000Y-43327849D01* +X39957000Y-42980036D01* +X39957001Y-42980031D01* +X39922213Y-42805145D01* +X39823148Y-42656883D01* +X34356990Y-37190725D01* +X34357113Y-37049919D01* +X34257302Y-36808357D01* +X34072646Y-36623379D01* +X33831259Y-36523146D01* +X33569888Y-36522918D01* +X33328326Y-36622729D01* +X33143348Y-36807385D01* +X33043115Y-37048772D01* +X33042887Y-37310143D01* +X31856439Y-37310143D01* +X30223297Y-35677001D01* +X31936001Y-35677001D01* +X32187424Y-35626990D01* +X32400570Y-35484570D01* +X33342964Y-34542176D01* +X33342887Y-34630112D01* +X33442698Y-34871674D01* +X33543000Y-34972151D01* +X33543000Y-35600000D01* +X33577787Y-35774887D01* +X33676852Y-35923148D01* +X34510896Y-36757192D01* +X34510686Y-36997911D01* +X34610497Y-37239473D01* +X34795153Y-37424451D01* +X35036540Y-37524684D01* +X35297911Y-37524912D01* +X35539473Y-37425101D01* +X35724451Y-37240445D01* +X35824684Y-36999058D01* +X35824773Y-36897011D01* +X36179906Y-36897011D01* +X36870825Y-37587930D01* +X36721320Y-37649704D01* +X36536342Y-37834360D01* +X36436109Y-38075747D01* +X36435881Y-38337118D01* +X36535692Y-38578680D01* +X36720348Y-38763658D01* +X36961735Y-38863891D01* +X37103707Y-38864015D01* +X42762840Y-44523148D01* +X42911102Y-44622213D01* +X43085988Y-44657000D01* +X48441102Y-44657000D01* +X49127989Y-45343886D01* +X49127989Y-46458553D01* +X49162776Y-46633440D01* +X49261841Y-46781701D01* +X51043000Y-48562859D01* +X51043000Y-48600000D01* +X51077787Y-48774887D01* +X51176852Y-48923148D01* +X51376852Y-49123148D01* +X51525114Y-49222213D01* +X51700000Y-49257000D01* +X53200000Y-49257000D01* +X53374887Y-49222213D01* +X53523148Y-49123148D01* +X53882302Y-48763994D01* +X54568000Y-48763994D01* +X54568000Y-50198018D01* +X52733009Y-53868000D01* +X22266991Y-53868000D01* +X20482991Y-50300000D01* +X22568000Y-50300000D01* +X22571028Y-50315224D01* +X22569087Y-50330624D01* +X22587376Y-50397408D01* +X22600884Y-50465319D01* +X22609507Y-50478224D01* +X22613607Y-50493196D01* +X23513607Y-52293196D01* +X23556062Y-52347899D01* +X23594530Y-52405470D01* +X23607436Y-52414094D01* +X23616953Y-52426356D01* +X23677107Y-52460646D01* +X23734681Y-52499116D01* +X23749906Y-52502144D01* +X23763390Y-52509831D01* +X23832085Y-52518491D01* +X23900000Y-52532000D01* +X51100000Y-52532000D01* +X51167915Y-52518491D01* +X51236610Y-52509831D01* +X51250094Y-52502144D01* +X51265319Y-52499116D01* +X51322893Y-52460646D01* +X51383047Y-52426356D01* +X51392564Y-52414094D01* +X51405470Y-52405470D01* +X51443938Y-52347899D01* +X51486393Y-52293196D01* +X52386392Y-50493196D01* +X52390491Y-50478227D01* +X52399116Y-50465319D01* +X52412625Y-50397403D01* +X52430913Y-50330624D01* +X52428972Y-50315224D01* +X52432000Y-50300000D01* +X52418491Y-50232085D01* +X52409831Y-50163390D01* +X52402144Y-50149906D01* +X52399116Y-50134681D01* +X52360646Y-50077107D01* +X52326356Y-50016953D01* +X52314094Y-50007436D01* +X52305470Y-49994530D01* +X52247894Y-49956059D01* +X52193196Y-49913608D01* +X52178227Y-49909509D01* +X52165319Y-49900884D01* +X52097403Y-49887375D01* +X52030624Y-49869087D01* +X52015224Y-49871028D01* +X52000000Y-49868000D01* +X23000000Y-49868000D01* +X22984776Y-49871028D01* +X22969376Y-49869087D01* +X22902592Y-49887376D01* +X22834681Y-49900884D01* +X22821776Y-49909507D01* +X22806804Y-49913607D01* +X22752101Y-49956062D01* +X22694530Y-49994530D01* +X22685906Y-50007436D01* +X22673644Y-50016953D01* +X22639354Y-50077107D01* +X22600884Y-50134681D01* +X22597856Y-50149906D01* +X22590169Y-50163390D01* +X22581509Y-50232085D01* +X22568000Y-50300000D01* +X20482991Y-50300000D01* +X20432000Y-50198018D01* +X20432000Y-49436837D01* +X20445172Y-49463663D01* +X20785862Y-49750902D01* +X21210540Y-49885900D01* +X21485540Y-49885900D01* +X21485540Y-48877900D01* +X21739540Y-48877900D01* +X21739540Y-49885900D01* +X22014540Y-49885900D01* +X22439218Y-49750902D01* +X22779908Y-49463663D01* +X22981659Y-49052774D01* +X22855494Y-48877900D01* +X21739540Y-48877900D01* +X21485540Y-48877900D01* +X21465540Y-48877900D01* +X21465540Y-48623900D01* +X21485540Y-48623900D01* +X21485540Y-47615900D01* +X21739540Y-47615900D01* +X21739540Y-48623900D01* +X22855494Y-48623900D01* +X22981659Y-48449026D01* +X22786731Y-48052031D01* +X23211311Y-48052031D01* +X23352972Y-48461949D01* +X23640719Y-48786452D01* +X24014602Y-48970168D01* +X24185540Y-48843634D01* +X24185540Y-47877900D01* +X24439540Y-47877900D01* +X24439540Y-48843634D01* +X24610478Y-48970168D01* +X24984361Y-48786452D01* +X25272108Y-48461949D01* +X25413769Y-48052031D01* +X25399869Y-48035750D01* +X33849000Y-48035750D01* +X33849000Y-48892310D01* +X33945673Y-49125699D01* +X34124302Y-49304327D01* +X34357691Y-49401000D01* +X35214250Y-49401000D01* +X35373000Y-49242250D01* +X35373000Y-47877000D01* +X35627000Y-47877000D01* +X35627000Y-49242250D01* +X35785750Y-49401000D01* +X36642309Y-49401000D01* +X36875698Y-49304327D01* +X37054327Y-49125699D01* +X37151000Y-48892310D01* +X37151000Y-48035750D01* +X36992250Y-47877000D01* +X35627000Y-47877000D01* +X35373000Y-47877000D01* +X34007750Y-47877000D01* +X33849000Y-48035750D01* +X25399869Y-48035750D01* +X25265103Y-47877900D01* +X24439540Y-47877900D01* +X24185540Y-47877900D01* +X23359977Y-47877900D01* +X23211311Y-48052031D01* +X22786731Y-48052031D01* +X22779908Y-48038137D01* +X22439218Y-47750898D01* +X22014540Y-47615900D01* +X21739540Y-47615900D01* +X21485540Y-47615900D01* +X21210540Y-47615900D01* +X20785862Y-47750898D01* +X20445172Y-48038137D01* +X20432000Y-48064963D01* +X20432000Y-42436837D01* +X20445172Y-42463663D01* +X20785862Y-42750902D01* +X21210540Y-42885900D01* +X21485540Y-42885900D01* +X21485540Y-41877900D01* +X21739540Y-41877900D01* +X21739540Y-42885900D01* +X22014540Y-42885900D01* +X22439218Y-42750902D01* +X22563696Y-42645953D01* +X22543000Y-42750000D01* +X22543000Y-45000000D01* +X22577787Y-45174887D01* +X22676852Y-45323148D01* +X22927752Y-45574048D01* +X23076013Y-45673113D01* +X23250900Y-45707900D01* +X23273546Y-45707900D01* +X23273546Y-46100900D01* +X23297930Y-46230490D01* +X23273546Y-46350900D01* +X23273546Y-46750900D01* +X23298439Y-46883196D01* +X23376626Y-47004702D01* +X23381305Y-47007899D01* +X23352972Y-47039851D01* +X23211311Y-47449769D01* +X23359977Y-47623900D01* +X24185540Y-47623900D01* +X24185540Y-47603900D01* +X24439540Y-47603900D01* +X24439540Y-47623900D01* +X25265103Y-47623900D01* +X25413769Y-47449769D01* +X25330183Y-47207900D01* +X25449100Y-47207900D01* +X25700523Y-47157889D01* +X25817661Y-47079620D01* +X25871674Y-47057302D01* +X25913400Y-47015649D01* +X25913669Y-47015469D01* +X25964570Y-46964568D01* +X26056652Y-46872646D01* +X26106987Y-46751425D01* +X26106989Y-46751423D01* +X26106990Y-46751420D01* +X26156885Y-46631259D01* +X26156905Y-46607690D01* +X33849000Y-46607690D01* +X33849000Y-47464250D01* +X34007750Y-47623000D01* +X35373000Y-47623000D01* +X35373000Y-47603000D01* +X35627000Y-47603000D01* +X35627000Y-47623000D01* +X36992250Y-47623000D01* +X37151000Y-47464250D01* +X37151000Y-46607690D01* +X37054327Y-46374301D01* +X36875698Y-46195673D01* +X36642309Y-46099000D01* +X36552453Y-46099000D01* +X36795386Y-45735424D01* +X36808996Y-45667000D01* +X37020704Y-45667000D01* +X40343010Y-48989306D01* +X40342887Y-49130112D01* +X40442698Y-49371674D01* +X40627354Y-49556652D01* +X40868741Y-49656885D01* +X41130112Y-49657113D01* +X41371674Y-49557302D01* +X41556652Y-49372646D01* +X41656885Y-49131259D01* +X41657113Y-48869888D01* +X41557302Y-48628326D01* +X41372646Y-48443348D01* +X41131259Y-48343115D01* +X40989287Y-48342991D01* +X37533148Y-44886852D01* +X37384887Y-44787787D01* +X37210000Y-44753000D01* +X36808996Y-44753000D01* +X36795386Y-44684576D01* +X36497757Y-44239142D01* +X36052323Y-43941513D01* +X35526899Y-43837000D01* +X35473101Y-43837000D01* +X34947677Y-43941513D01* +X34502243Y-44239142D01* +X34204614Y-44684576D01* +X34100101Y-45210000D01* +X34204614Y-45735424D01* +X34447547Y-46099000D01* +X34357691Y-46099000D01* +X34124302Y-46195673D01* +X33945673Y-46374301D01* +X33849000Y-46607690D01* +X26156905Y-46607690D01* +X26157113Y-46369888D01* +X26057302Y-46128326D01* +X25912762Y-45983534D01* +X26323148Y-45573148D01* +X26422213Y-45424886D01* +X26457001Y-45250000D01* +X26457000Y-45249995D01* +X26457000Y-42722125D01* +X26556652Y-42622646D01* +X26656885Y-42381259D01* +X26657113Y-42119888D01* +X26557302Y-41878326D01* +X26429138Y-41749938D01* +X26556652Y-41622646D01* +X26656885Y-41381259D01* +X26657113Y-41119888D01* +X26557302Y-40878326D01* +X26372646Y-40693348D01* +X26131259Y-40593115D01* +X25869888Y-40592887D01* +X25628326Y-40692698D01* +X25443348Y-40877354D01* +X25343115Y-41118741D01* +X25342991Y-41260713D01* +X25310704Y-41293000D01* +X24000005Y-41293000D01* +X24000000Y-41292999D01* +X23825114Y-41327787D01* +X23676852Y-41426852D01* +X23676850Y-41426855D01* +X22914835Y-42188870D01* +X22981659Y-42052774D01* +X22855494Y-41877900D01* +X21739540Y-41877900D01* +X21485540Y-41877900D01* +X21465540Y-41877900D01* +X21465540Y-41623900D01* +X21485540Y-41623900D01* +X21485540Y-40615900D01* +X21739540Y-40615900D01* +X21739540Y-41623900D01* +X22855494Y-41623900D01* +X22981659Y-41449026D01* +X22779908Y-41038137D01* +X22439218Y-40750898D01* +X22014540Y-40615900D01* +X21739540Y-40615900D01* +X21485540Y-40615900D01* +X21210540Y-40615900D01* +X20785862Y-40750898D01* +X20445172Y-41038137D01* +X20432000Y-41064963D01* +X20432000Y-37618250D01* +X21292722Y-37618250D01* +X21536857Y-38209103D01* +X21988519Y-38661554D01* +X22578946Y-38906720D01* +X23218250Y-38907278D01* +X23809103Y-38663143D01* +X24261554Y-38211481D01* +X24506720Y-37621054D01* +X24507278Y-36981750D01* +X24263143Y-36390897D01* +X23811481Y-35938446D01* +X23221054Y-35693280D01* +X22581750Y-35692722D01* +X21990897Y-35936857D01* +X21538446Y-36388519D01* +X21293280Y-36978946D01* +X21292722Y-37618250D01* +X20432000Y-37618250D01* +X20432000Y-32727000D01* +X22809189Y-32727000D01* +X22906842Y-32873148D01* +X25523000Y-35489306D01* +X25522877Y-35630112D01* +X25622688Y-35871674D01* +X25807344Y-36056652D01* +X26048731Y-36156885D01* +X26310102Y-36157113D01* +X26551664Y-36057302D01* +X26736642Y-35872646D01* +X26836875Y-35631259D01* +X26837103Y-35369888D01* +X26737292Y-35128326D01* +X26552636Y-34943348D01* +X26311249Y-34843115D01* +X26169277Y-34842991D01* +X25112036Y-33785750D01* +X25740000Y-33785750D01* +X25740000Y-34026309D01* +X25836673Y-34259698D01* +X26015301Y-34438327D01* +X26248690Y-34535000D01* +X26464250Y-34535000D01* +X26623000Y-34376250D01* +X26623000Y-33627000D01* +X26877000Y-33627000D01* +X26877000Y-34376250D01* +X27035750Y-34535000D01* +X27251310Y-34535000D01* +X27484699Y-34438327D01* +X27625000Y-34298025D01* +X27765301Y-34438327D01* +X27998690Y-34535000D01* +X28214250Y-34535000D01* +X28373000Y-34376250D01* +X28373000Y-33627000D01* +X27648750Y-33627000D01* +X27625000Y-33650750D01* +X27601250Y-33627000D01* +X26877000Y-33627000D01* +X26623000Y-33627000D01* +X25898750Y-33627000D01* +X25740000Y-33785750D01* +X25112036Y-33785750D01* +X24000355Y-32674069D01* +X24018315Y-32646159D01* +X24027000Y-32600000D01* +X24027000Y-27951032D01* +X25279106Y-29203138D01* +X25279106Y-29203138D01* +G37* +X25279106Y-29203138D02* +X25427368Y-29302203D01* +X25542535Y-29325111D01* +X25630122Y-29412850D01* +X25535431Y-29507541D01* +X25393011Y-29720687D01* +X25343000Y-29972110D01* +X25343000Y-30520010D01* +X25342887Y-30650122D01* +X25442698Y-30891684D01* +X25627354Y-31076662D01* +X25748575Y-31126997D01* +X25748577Y-31126999D01* +X25748580Y-31127000D01* +X25868741Y-31176895D01* +X25999997Y-31177009D01* +X26000000Y-31177010D01* +X26000003Y-31177010D01* +X26130112Y-31177123D01* +X26251421Y-31126999D01* +X26251423Y-31126999D01* +X26251425Y-31126998D01* +X26371674Y-31077312D01* +X26556652Y-30892656D01* +X26606987Y-30771435D01* +X26606989Y-30771433D01* +X26606990Y-30771430D01* +X26656885Y-30651269D01* +X26657113Y-30389898D01* +X26657000Y-30389625D01* +X26657000Y-30244248D01* +X27164569Y-29736680D01* +X27306989Y-29523533D01* +X27356999Y-29272110D01* +X27327927Y-29125953D01* +X27490302Y-29288327D01* +X27527474Y-29303724D01* +X27608750Y-29385000D01* +X27676309Y-29385000D01* +X27700000Y-29375187D01* +X27723691Y-29385000D01* +X27791250Y-29385000D01* +X27872526Y-29303724D01* +X27909698Y-29288327D01* +X28088327Y-29109699D01* +X28150000Y-28960807D01* +X28150000Y-29226250D01* +X28213727Y-29289977D01* +X26426852Y-31076852D01* +X26327787Y-31225113D01* +X26323700Y-31245659D01* +X26242704Y-31260899D01* +X26121198Y-31339086D01* +X26039684Y-31458386D01* +X26011006Y-31600000D01* +X26011006Y-32400000D01* +X26035899Y-32532296D01* +X26046490Y-32548754D01* +X26015301Y-32561673D01* +X25836673Y-32740302D01* +X25740000Y-32973691D01* +X25740000Y-33214250D01* +X25898750Y-33373000D01* +X26623000Y-33373000D01* +X26623000Y-33353000D01* +X26877000Y-33353000D01* +X26877000Y-33373000D01* +X27601250Y-33373000D01* +X27625000Y-33349250D01* +X27648750Y-33373000D01* +X28373000Y-33373000D01* +X28373000Y-33353000D01* +X28627000Y-33353000D01* +X28627000Y-33373000D01* +X29351250Y-33373000D01* +X29375000Y-33349250D01* +X29398750Y-33373000D01* +X30123000Y-33373000D01* +X30123000Y-33353000D01* +X30377000Y-33353000D01* +X30377000Y-33373000D01* +X31071750Y-33373000D01* +X31073750Y-33375000D01* +X31873000Y-33375000D01* +X31873000Y-32773750D01* +X31714250Y-32615000D01* +X31423690Y-32615000D01* +X31190301Y-32711673D01* +X31162500Y-32739475D01* +X30984699Y-32561673D01* +X30955012Y-32549376D01* +X30960316Y-32541614D01* +X30988994Y-32400000D01* +X30988994Y-31600000D01* +X30964101Y-31467704D01* +X30885914Y-31346198D01* +X30766614Y-31264684D01* +X30676452Y-31246425D01* +X30672213Y-31225114D01* +X30573148Y-31076852D01* +X29907000Y-30410704D01* +X29907000Y-30103296D01* +X31294815Y-31491111D01* +X31214684Y-31608386D01* +X31186006Y-31750000D01* +X31186006Y-32250000D01* +X31210899Y-32382296D01* +X31289086Y-32503802D01* +X31408386Y-32585316D01* +X31550000Y-32613994D01* +X32215664Y-32613994D01* +X32215664Y-32685086D01* +X32127000Y-32773750D01* +X32127000Y-33375000D01* +X32147000Y-33375000D01* +X32147000Y-33625000D01* +X32127000Y-33625000D01* +X32127000Y-33647000D01* +X31873000Y-33647000D01* +X31873000Y-33625000D01* +X31073750Y-33625000D01* +X31071750Y-33627000D01* +X30377000Y-33627000D01* +X30377000Y-33647000D01* +X30123000Y-33647000D01* +X30123000Y-33627000D01* +X29398750Y-33627000D01* +X29382677Y-33643073D01* +X29367309Y-33643059D01* +X29351250Y-33627000D01* +X28627000Y-33627000D01* +X28627000Y-34376250D01* +X28642920Y-34392170D01* +X28642887Y-34430112D01* +X28742698Y-34671674D01* +X28843000Y-34772151D01* +X28843000Y-35400000D01* +X28877787Y-35574887D01* +X28976852Y-35723148D01* +X30547260Y-37293556D01* +X30428326Y-37342698D01* +X30243348Y-37527354D01* +X30143115Y-37768741D01* +X30142887Y-38030112D01* +X30242698Y-38271674D01* +X30427354Y-38456652D01* +X30668741Y-38556885D01* +X30810713Y-38557009D01* +X33023025Y-40769321D01* +X33022877Y-40939230D01* +X33122688Y-41180792D01* +X33307344Y-41365770D01* +X33548731Y-41466003D01* +X33810102Y-41466231D01* +X34051664Y-41366420D01* +X34236642Y-41181764D01* +X34329926Y-40957113D01* +X34330112Y-40957113D01* +X34571674Y-40857302D01* +X34756652Y-40672646D01* +X34856885Y-40431259D01* +X34857113Y-40169888D01* +X34757302Y-39928326D01* +X34572646Y-39743348D01* +X34331259Y-39643115D01* +X34189286Y-39642991D01* +X31856439Y-37310143D01* +X33042887Y-37310143D01* +X33142698Y-37551705D01* +X33327354Y-37736683D01* +X33568741Y-37836916D01* +X33710713Y-37837040D01* +X39043000Y-43169327D01* +X39043000Y-43327875D01* +X38943348Y-43427354D01* +X38843115Y-43668741D01* +X38842887Y-43930112D01* +X38942698Y-44171674D01* +X39127354Y-44356652D01* +X39368741Y-44456885D01* +X39630112Y-44457113D01* +X39871674Y-44357302D01* +X40056652Y-44172646D01* +X40156885Y-43931259D01* +X40157113Y-43669888D01* +X40057302Y-43428326D01* +X39957000Y-43327849D01* +X39957000Y-42980036D01* +X39957001Y-42980031D01* +X39922213Y-42805145D01* +X39823148Y-42656883D01* +X34356990Y-37190725D01* +X34357113Y-37049919D01* +X34257302Y-36808357D01* +X34072646Y-36623379D01* +X33831259Y-36523146D01* +X33569888Y-36522918D01* +X33328326Y-36622729D01* +X33143348Y-36807385D01* +X33043115Y-37048772D01* +X33042887Y-37310143D01* +X31856439Y-37310143D01* +X30223297Y-35677001D01* +X31936001Y-35677001D01* +X32187424Y-35626990D01* +X32400570Y-35484570D01* +X33342964Y-34542176D01* +X33342887Y-34630112D01* +X33442698Y-34871674D01* +X33543000Y-34972151D01* +X33543000Y-35600000D01* +X33577787Y-35774887D01* +X33676852Y-35923148D01* +X34510896Y-36757192D01* +X34510686Y-36997911D01* +X34610497Y-37239473D01* +X34795153Y-37424451D01* +X35036540Y-37524684D01* +X35297911Y-37524912D01* +X35539473Y-37425101D01* +X35724451Y-37240445D01* +X35824684Y-36999058D01* +X35824773Y-36897011D01* +X36179906Y-36897011D01* +X36870825Y-37587930D01* +X36721320Y-37649704D01* +X36536342Y-37834360D01* +X36436109Y-38075747D01* +X36435881Y-38337118D01* +X36535692Y-38578680D01* +X36720348Y-38763658D01* +X36961735Y-38863891D01* +X37103707Y-38864015D01* +X42762840Y-44523148D01* +X42911102Y-44622213D01* +X43085988Y-44657000D01* +X48441102Y-44657000D01* +X49127989Y-45343886D01* +X49127989Y-46458553D01* +X49162776Y-46633440D01* +X49261841Y-46781701D01* +X51043000Y-48562859D01* +X51043000Y-48600000D01* +X51077787Y-48774887D01* +X51176852Y-48923148D01* +X51376852Y-49123148D01* +X51525114Y-49222213D01* +X51700000Y-49257000D01* +X53200000Y-49257000D01* +X53374887Y-49222213D01* +X53523148Y-49123148D01* +X53882302Y-48763994D01* +X54568000Y-48763994D01* +X54568000Y-50198018D01* +X52733009Y-53868000D01* +X22266991Y-53868000D01* +X20482991Y-50300000D01* +X22568000Y-50300000D01* +X22571028Y-50315224D01* +X22569087Y-50330624D01* +X22587376Y-50397408D01* +X22600884Y-50465319D01* +X22609507Y-50478224D01* +X22613607Y-50493196D01* +X23513607Y-52293196D01* +X23556062Y-52347899D01* +X23594530Y-52405470D01* +X23607436Y-52414094D01* +X23616953Y-52426356D01* +X23677107Y-52460646D01* +X23734681Y-52499116D01* +X23749906Y-52502144D01* +X23763390Y-52509831D01* +X23832085Y-52518491D01* +X23900000Y-52532000D01* +X51100000Y-52532000D01* +X51167915Y-52518491D01* +X51236610Y-52509831D01* +X51250094Y-52502144D01* +X51265319Y-52499116D01* +X51322893Y-52460646D01* +X51383047Y-52426356D01* +X51392564Y-52414094D01* +X51405470Y-52405470D01* +X51443938Y-52347899D01* +X51486393Y-52293196D01* +X52386392Y-50493196D01* +X52390491Y-50478227D01* +X52399116Y-50465319D01* +X52412625Y-50397403D01* +X52430913Y-50330624D01* +X52428972Y-50315224D01* +X52432000Y-50300000D01* +X52418491Y-50232085D01* +X52409831Y-50163390D01* +X52402144Y-50149906D01* +X52399116Y-50134681D01* +X52360646Y-50077107D01* +X52326356Y-50016953D01* +X52314094Y-50007436D01* +X52305470Y-49994530D01* +X52247894Y-49956059D01* +X52193196Y-49913608D01* +X52178227Y-49909509D01* +X52165319Y-49900884D01* +X52097403Y-49887375D01* +X52030624Y-49869087D01* +X52015224Y-49871028D01* +X52000000Y-49868000D01* +X23000000Y-49868000D01* +X22984776Y-49871028D01* +X22969376Y-49869087D01* +X22902592Y-49887376D01* +X22834681Y-49900884D01* +X22821776Y-49909507D01* +X22806804Y-49913607D01* +X22752101Y-49956062D01* +X22694530Y-49994530D01* +X22685906Y-50007436D01* +X22673644Y-50016953D01* +X22639354Y-50077107D01* +X22600884Y-50134681D01* +X22597856Y-50149906D01* +X22590169Y-50163390D01* +X22581509Y-50232085D01* +X22568000Y-50300000D01* +X20482991Y-50300000D01* +X20432000Y-50198018D01* +X20432000Y-49436837D01* +X20445172Y-49463663D01* +X20785862Y-49750902D01* +X21210540Y-49885900D01* +X21485540Y-49885900D01* +X21485540Y-48877900D01* +X21739540Y-48877900D01* +X21739540Y-49885900D01* +X22014540Y-49885900D01* +X22439218Y-49750902D01* +X22779908Y-49463663D01* +X22981659Y-49052774D01* +X22855494Y-48877900D01* +X21739540Y-48877900D01* +X21485540Y-48877900D01* +X21465540Y-48877900D01* +X21465540Y-48623900D01* +X21485540Y-48623900D01* +X21485540Y-47615900D01* +X21739540Y-47615900D01* +X21739540Y-48623900D01* +X22855494Y-48623900D01* +X22981659Y-48449026D01* +X22786731Y-48052031D01* +X23211311Y-48052031D01* +X23352972Y-48461949D01* +X23640719Y-48786452D01* +X24014602Y-48970168D01* +X24185540Y-48843634D01* +X24185540Y-47877900D01* +X24439540Y-47877900D01* +X24439540Y-48843634D01* +X24610478Y-48970168D01* +X24984361Y-48786452D01* +X25272108Y-48461949D01* +X25413769Y-48052031D01* +X25399869Y-48035750D01* +X33849000Y-48035750D01* +X33849000Y-48892310D01* +X33945673Y-49125699D01* +X34124302Y-49304327D01* +X34357691Y-49401000D01* +X35214250Y-49401000D01* +X35373000Y-49242250D01* +X35373000Y-47877000D01* +X35627000Y-47877000D01* +X35627000Y-49242250D01* +X35785750Y-49401000D01* +X36642309Y-49401000D01* +X36875698Y-49304327D01* +X37054327Y-49125699D01* +X37151000Y-48892310D01* +X37151000Y-48035750D01* +X36992250Y-47877000D01* +X35627000Y-47877000D01* +X35373000Y-47877000D01* +X34007750Y-47877000D01* +X33849000Y-48035750D01* +X25399869Y-48035750D01* +X25265103Y-47877900D01* +X24439540Y-47877900D01* +X24185540Y-47877900D01* +X23359977Y-47877900D01* +X23211311Y-48052031D01* +X22786731Y-48052031D01* +X22779908Y-48038137D01* +X22439218Y-47750898D01* +X22014540Y-47615900D01* +X21739540Y-47615900D01* +X21485540Y-47615900D01* +X21210540Y-47615900D01* +X20785862Y-47750898D01* +X20445172Y-48038137D01* +X20432000Y-48064963D01* +X20432000Y-42436837D01* +X20445172Y-42463663D01* +X20785862Y-42750902D01* +X21210540Y-42885900D01* +X21485540Y-42885900D01* +X21485540Y-41877900D01* +X21739540Y-41877900D01* +X21739540Y-42885900D01* +X22014540Y-42885900D01* +X22439218Y-42750902D01* +X22563696Y-42645953D01* +X22543000Y-42750000D01* +X22543000Y-45000000D01* +X22577787Y-45174887D01* +X22676852Y-45323148D01* +X22927752Y-45574048D01* +X23076013Y-45673113D01* +X23250900Y-45707900D01* +X23273546Y-45707900D01* +X23273546Y-46100900D01* +X23297930Y-46230490D01* +X23273546Y-46350900D01* +X23273546Y-46750900D01* +X23298439Y-46883196D01* +X23376626Y-47004702D01* +X23381305Y-47007899D01* +X23352972Y-47039851D01* +X23211311Y-47449769D01* +X23359977Y-47623900D01* +X24185540Y-47623900D01* +X24185540Y-47603900D01* +X24439540Y-47603900D01* +X24439540Y-47623900D01* +X25265103Y-47623900D01* +X25413769Y-47449769D01* +X25330183Y-47207900D01* +X25449100Y-47207900D01* +X25700523Y-47157889D01* +X25817661Y-47079620D01* +X25871674Y-47057302D01* +X25913400Y-47015649D01* +X25913669Y-47015469D01* +X25964570Y-46964568D01* +X26056652Y-46872646D01* +X26106987Y-46751425D01* +X26106989Y-46751423D01* +X26106990Y-46751420D01* +X26156885Y-46631259D01* +X26156905Y-46607690D01* +X33849000Y-46607690D01* +X33849000Y-47464250D01* +X34007750Y-47623000D01* +X35373000Y-47623000D01* +X35373000Y-47603000D01* +X35627000Y-47603000D01* +X35627000Y-47623000D01* +X36992250Y-47623000D01* +X37151000Y-47464250D01* +X37151000Y-46607690D01* +X37054327Y-46374301D01* +X36875698Y-46195673D01* +X36642309Y-46099000D01* +X36552453Y-46099000D01* +X36795386Y-45735424D01* +X36808996Y-45667000D01* +X37020704Y-45667000D01* +X40343010Y-48989306D01* +X40342887Y-49130112D01* +X40442698Y-49371674D01* +X40627354Y-49556652D01* +X40868741Y-49656885D01* +X41130112Y-49657113D01* +X41371674Y-49557302D01* +X41556652Y-49372646D01* +X41656885Y-49131259D01* +X41657113Y-48869888D01* +X41557302Y-48628326D01* +X41372646Y-48443348D01* +X41131259Y-48343115D01* +X40989287Y-48342991D01* +X37533148Y-44886852D01* +X37384887Y-44787787D01* +X37210000Y-44753000D01* +X36808996Y-44753000D01* +X36795386Y-44684576D01* +X36497757Y-44239142D01* +X36052323Y-43941513D01* +X35526899Y-43837000D01* +X35473101Y-43837000D01* +X34947677Y-43941513D01* +X34502243Y-44239142D01* +X34204614Y-44684576D01* +X34100101Y-45210000D01* +X34204614Y-45735424D01* +X34447547Y-46099000D01* +X34357691Y-46099000D01* +X34124302Y-46195673D01* +X33945673Y-46374301D01* +X33849000Y-46607690D01* +X26156905Y-46607690D01* +X26157113Y-46369888D01* +X26057302Y-46128326D01* +X25912762Y-45983534D01* +X26323148Y-45573148D01* +X26422213Y-45424886D01* +X26457001Y-45250000D01* +X26457000Y-45249995D01* +X26457000Y-42722125D01* +X26556652Y-42622646D01* +X26656885Y-42381259D01* +X26657113Y-42119888D01* +X26557302Y-41878326D01* +X26429138Y-41749938D01* +X26556652Y-41622646D01* +X26656885Y-41381259D01* +X26657113Y-41119888D01* +X26557302Y-40878326D01* +X26372646Y-40693348D01* +X26131259Y-40593115D01* +X25869888Y-40592887D01* +X25628326Y-40692698D01* +X25443348Y-40877354D01* +X25343115Y-41118741D01* +X25342991Y-41260713D01* +X25310704Y-41293000D01* +X24000005Y-41293000D01* +X24000000Y-41292999D01* +X23825114Y-41327787D01* +X23676852Y-41426852D01* +X23676850Y-41426855D01* +X22914835Y-42188870D01* +X22981659Y-42052774D01* +X22855494Y-41877900D01* +X21739540Y-41877900D01* +X21485540Y-41877900D01* +X21465540Y-41877900D01* +X21465540Y-41623900D01* +X21485540Y-41623900D01* +X21485540Y-40615900D01* +X21739540Y-40615900D01* +X21739540Y-41623900D01* +X22855494Y-41623900D01* +X22981659Y-41449026D01* +X22779908Y-41038137D01* +X22439218Y-40750898D01* +X22014540Y-40615900D01* +X21739540Y-40615900D01* +X21485540Y-40615900D01* +X21210540Y-40615900D01* +X20785862Y-40750898D01* +X20445172Y-41038137D01* +X20432000Y-41064963D01* +X20432000Y-37618250D01* +X21292722Y-37618250D01* +X21536857Y-38209103D01* +X21988519Y-38661554D01* +X22578946Y-38906720D01* +X23218250Y-38907278D01* +X23809103Y-38663143D01* +X24261554Y-38211481D01* +X24506720Y-37621054D01* +X24507278Y-36981750D01* +X24263143Y-36390897D01* +X23811481Y-35938446D01* +X23221054Y-35693280D01* +X22581750Y-35692722D01* +X21990897Y-35936857D01* +X21538446Y-36388519D01* +X21293280Y-36978946D01* +X21292722Y-37618250D01* +X20432000Y-37618250D01* +X20432000Y-32727000D01* +X22809189Y-32727000D01* +X22906842Y-32873148D01* +X25523000Y-35489306D01* +X25522877Y-35630112D01* +X25622688Y-35871674D01* +X25807344Y-36056652D01* +X26048731Y-36156885D01* +X26310102Y-36157113D01* +X26551664Y-36057302D01* +X26736642Y-35872646D01* +X26836875Y-35631259D01* +X26837103Y-35369888D01* +X26737292Y-35128326D01* +X26552636Y-34943348D01* +X26311249Y-34843115D01* +X26169277Y-34842991D01* +X25112036Y-33785750D01* +X25740000Y-33785750D01* +X25740000Y-34026309D01* +X25836673Y-34259698D01* +X26015301Y-34438327D01* +X26248690Y-34535000D01* +X26464250Y-34535000D01* +X26623000Y-34376250D01* +X26623000Y-33627000D01* +X26877000Y-33627000D01* +X26877000Y-34376250D01* +X27035750Y-34535000D01* +X27251310Y-34535000D01* +X27484699Y-34438327D01* +X27625000Y-34298025D01* +X27765301Y-34438327D01* +X27998690Y-34535000D01* +X28214250Y-34535000D01* +X28373000Y-34376250D01* +X28373000Y-33627000D01* +X27648750Y-33627000D01* +X27625000Y-33650750D01* +X27601250Y-33627000D01* +X26877000Y-33627000D01* +X26623000Y-33627000D01* +X25898750Y-33627000D01* +X25740000Y-33785750D01* +X25112036Y-33785750D01* +X24000355Y-32674069D01* +X24018315Y-32646159D01* +X24027000Y-32600000D01* +X24027000Y-27951032D01* +X25279106Y-29203138D01* +G36* +X25442698Y-42621674D02* +X25543000Y-42722151D01* +X25543000Y-43432564D01* +X25525867Y-43391201D01* +X25355450Y-43220785D01* +X25413769Y-43052031D01* +X25265103Y-42877900D01* +X24439540Y-42877900D01* +X24439540Y-43850900D01* +X24449356Y-43850900D01* +X24459540Y-43858439D01* +X24459540Y-44036906D01* +X24165540Y-44036906D01* +X24165540Y-43858439D01* +X24175724Y-43850900D01* +X24185540Y-43850900D01* +X24185540Y-42877900D01* +X24165540Y-42877900D01* +X24165540Y-42623900D01* +X24185540Y-42623900D01* +X24185540Y-42603900D01* +X24439540Y-42603900D01* +X24439540Y-42623900D01* +X25265103Y-42623900D01* +X25385399Y-42482999D01* +X25442698Y-42621674D01* +X25442698Y-42621674D01* +G37* +X25442698Y-42621674D02* +X25543000Y-42722151D01* +X25543000Y-43432564D01* +X25525867Y-43391201D01* +X25355450Y-43220785D01* +X25413769Y-43052031D01* +X25265103Y-42877900D01* +X24439540Y-42877900D01* +X24439540Y-43850900D01* +X24449356Y-43850900D01* +X24459540Y-43858439D01* +X24459540Y-44036906D01* +X24165540Y-44036906D01* +X24165540Y-43858439D01* +X24175724Y-43850900D01* +X24185540Y-43850900D01* +X24185540Y-42877900D01* +X24165540Y-42877900D01* +X24165540Y-42623900D01* +X24185540Y-42623900D01* +X24185540Y-42603900D01* +X24439540Y-42603900D01* +X24439540Y-42623900D01* +X25265103Y-42623900D01* +X25385399Y-42482999D01* +X25442698Y-42621674D01* +G36* +X49596853Y-21743149D02* +X49745115Y-21842214D01* +X49920001Y-21877001D01* +X50749601Y-21877001D01* +X50924488Y-21842214D01* +X51072749Y-21743149D01* +X51158898Y-21657000D01* +X51536006Y-21657000D01* +X51536006Y-21743000D01* +X51378998Y-21743000D01* +X51204112Y-21777787D01* +X51055850Y-21876852D01* +X49581851Y-23350851D01* +X49482786Y-23499112D01* +X49462206Y-23602576D01* +X49447999Y-23673999D01* +X49447999Y-24826001D01* +X49482786Y-25000888D01* +X49544210Y-25092816D01* +X49490000Y-25223691D01* +X49490000Y-25464250D01* +X49648750Y-25623000D01* +X50373000Y-25623000D01* +X50373000Y-25603000D01* +X50627000Y-25603000D01* +X50627000Y-25623000D01* +X50647000Y-25623000D01* +X50647000Y-25877000D01* +X50627000Y-25877000D01* +X50627000Y-26626250D01* +X50785750Y-26785000D01* +X51001310Y-26785000D01* +X51234699Y-26688327D01* +X51413327Y-26509698D01* +X51510000Y-26276309D01* +X51510000Y-26235294D01* +X51943000Y-26668294D01* +X51943000Y-26836006D01* +X51900000Y-26836006D01* +X51767704Y-26860899D01* +X51646198Y-26939086D01* +X51564684Y-27058386D01* +X51536006Y-27200000D01* +X51536006Y-28011632D01* +X50873819Y-28673819D01* +X50758496Y-28846412D01* +X50718000Y-29050000D01* +X50718000Y-30950000D01* +X50758496Y-31153588D01* +X50813566Y-31236006D01* +X50873819Y-31326181D01* +X51536006Y-31988368D01* +X51536006Y-32800000D01* +X51560899Y-32932296D01* +X51639086Y-33053802D01* +X51758386Y-33135316D01* +X51868000Y-33157514D01* +X51868000Y-36842027D01* +X51767704Y-36860899D01* +X51646198Y-36939086D01* +X51564684Y-37058386D01* +X51536006Y-37200000D01* +X51536006Y-37268000D01* +X51450000Y-37268000D01* +X51246412Y-37308496D01* +X51176937Y-37354918D01* +X51073819Y-37423819D01* +X50123819Y-38373819D01* +X50008496Y-38546412D01* +X49968000Y-38750000D01* +X49968000Y-40651435D01* +X49917704Y-40660899D01* +X49796198Y-40739086D01* +X49714684Y-40858386D01* +X49686006Y-41000000D01* +X49686006Y-41500000D01* +X49710899Y-41632296D01* +X49789086Y-41753802D01* +X49908386Y-41835316D01* +X50050000Y-41863994D01* +X50950000Y-41863994D01* +X51082296Y-41839101D01* +X51171033Y-41782000D01* +X51329638Y-41782000D01* +X51536006Y-41988368D01* +X51536006Y-42255409D01* +X51488327Y-42140302D01* +X51309699Y-41961673D01* +X51076310Y-41865000D01* +X50785750Y-41865000D01* +X50627000Y-42023750D01* +X50627000Y-42625000D01* +X50647000Y-42625000D01* +X50647000Y-42875000D01* +X50627000Y-42875000D01* +X50627000Y-44123000D01* +X50647000Y-44123000D01* +X50647000Y-44377000D01* +X50627000Y-44377000D01* +X50627000Y-44397000D01* +X50373000Y-44397000D01* +X50373000Y-44377000D01* +X49648750Y-44377000D01* +X49551222Y-44474528D01* +X48953546Y-43876852D01* +X48805285Y-43777787D01* +X48630398Y-43743000D01* +X43275284Y-43743000D01* +X42566034Y-43033750D01* +X49415000Y-43033750D01* +X49415000Y-43126309D01* +X49511673Y-43359698D01* +X49614475Y-43462500D01* +X49586673Y-43490302D01* +X49490000Y-43723691D01* +X49490000Y-43964250D01* +X49648750Y-44123000D01* +X50373000Y-44123000D01* +X50373000Y-42875000D01* +X49573750Y-42875000D01* +X49415000Y-43033750D01* +X42566034Y-43033750D01* +X41683635Y-42151351D01* +X41712033Y-42157000D01* +X42346702Y-42157000D01* +X42346702Y-42516000D01* +X42371595Y-42648296D01* +X42449782Y-42769802D01* +X42569082Y-42851316D01* +X42710696Y-42879994D01* +X44742696Y-42879994D01* +X44874992Y-42855101D01* +X44996498Y-42776914D01* +X45078012Y-42657614D01* +X45106690Y-42516000D01* +X45106690Y-42214677D01* +X45295838Y-42497757D01* +X45741272Y-42795386D01* +X46266696Y-42899899D01* +X46792120Y-42795386D01* +X47237554Y-42497757D01* +X47320452Y-42373691D01* +X49415000Y-42373691D01* +X49415000Y-42466250D01* +X49573750Y-42625000D01* +X50373000Y-42625000D01* +X50373000Y-42023750D01* +X50214250Y-41865000D01* +X49923690Y-41865000D01* +X49690301Y-41961673D01* +X49511673Y-42140302D01* +X49415000Y-42373691D01* +X47320452Y-42373691D01* +X47535183Y-42052323D01* +X47639696Y-41526899D01* +X47639696Y-41473101D01* +X47535183Y-40947677D01* +X47237554Y-40502243D01* +X46792120Y-40204614D01* +X46758696Y-40197966D01* +X46758696Y-39737436D01* +X46759042Y-39737371D01* +X46880548Y-39659184D01* +X46962062Y-39539884D01* +X46990740Y-39398270D01* +X46990740Y-38598170D01* +X46965847Y-38465874D01* +X46901188Y-38365391D01* +X46956885Y-38231259D01* +X46957113Y-37969888D01* +X46956597Y-37968639D01* +X47049696Y-37875540D01* +X47049696Y-37126240D01* +X47303696Y-37126240D01* +X47303696Y-37875540D01* +X47462446Y-38034290D01* +X47703055Y-38034290D01* +X47936444Y-37937617D01* +X48115073Y-37758989D01* +X48211746Y-37525600D01* +X48211746Y-37284990D01* +X48052996Y-37126240D01* +X47303696Y-37126240D01* +X47049696Y-37126240D01* +X46300396Y-37126240D01* +X46141646Y-37284990D01* +X46141646Y-37454556D01* +X46019312Y-37505104D01* +X46040740Y-37399290D01* +X46040740Y-36599190D01* +X46016974Y-36472880D01* +X46141646Y-36472880D01* +X46141646Y-36713490D01* +X46300396Y-36872240D01* +X47049696Y-36872240D01* +X47049696Y-36122940D01* +X47303696Y-36122940D01* +X47303696Y-36872240D01* +X48052996Y-36872240D01* +X48211746Y-36713490D01* +X48211746Y-36472880D01* +X48115073Y-36239491D01* +X47936444Y-36060863D01* +X47703055Y-35964190D01* +X47462446Y-35964190D01* +X47303696Y-36122940D01* +X47049696Y-36122940D01* +X46890946Y-35964190D01* +X46650337Y-35964190D01* +X46416948Y-36060863D01* +X46238319Y-36239491D01* +X46141646Y-36472880D01* +X46016974Y-36472880D01* +X46015847Y-36466894D01* +X45937660Y-36345388D01* +X45818360Y-36263874D01* +X45676746Y-36235196D01* +X44876646Y-36235196D01* +X44744350Y-36260089D01* +X44622844Y-36338276D01* +X44541330Y-36457576D01* +X44539373Y-36467240D01* +X43477456Y-36467240D01* +X43273868Y-36507736D01* +X43101769Y-36622729D01* +X43101275Y-36623059D01* +X43088328Y-36636006D01* +X42776696Y-36636006D01* +X42644400Y-36660899D01* +X42522894Y-36739086D01* +X42441380Y-36858386D01* +X42412702Y-37000000D01* +X42412702Y-37500000D01* +X42437595Y-37632296D01* +X42444483Y-37643000D01* +X40253195Y-37643000D01* +X39276383Y-36666188D01* +X39430173Y-36512666D01* +X39530406Y-36271279D01* +X39530575Y-36077010D01* +X44679990Y-36077010D01* +X44854877Y-36042223D01* +X45003138Y-35943158D01* +X45289305Y-35656990D01* +X45430112Y-35657113D01* +X45671674Y-35557302D01* +X45856652Y-35372646D01* +X45956885Y-35131259D01* +X45957113Y-34869888D01* +X45857302Y-34628326D01* +X45764138Y-34535000D01* +X45877002Y-34535000D01* +X45877002Y-34376252D01* +X46035750Y-34535000D01* +X46251310Y-34535000D01* +X46484699Y-34438327D01* +X46663327Y-34259698D01* +X46760000Y-34026309D01* +X46760000Y-33785750D01* +X46601250Y-33627000D01* +X45877000Y-33627000D01* +X45877000Y-33647000D01* +X45623000Y-33647000D01* +X45623000Y-33627000D01* +X44898750Y-33627000D01* +X44875000Y-33650750D01* +X44851250Y-33627000D01* +X44127000Y-33627000D01* +X44127000Y-33647000D01* +X43873000Y-33647000D01* +X43873000Y-33627000D01* +X43148750Y-33627000D01* +X42990000Y-33785750D01* +X42990000Y-34026309D01* +X43086673Y-34259698D01* +X43265301Y-34438327D01* +X43472855Y-34524299D01* +X43428326Y-34542698D01* +X43327849Y-34643000D01* +X42573417Y-34643000D01* +X42584699Y-34638327D01* +X42763327Y-34459698D01* +X42860000Y-34226309D01* +X42860000Y-34090750D01* +X42701250Y-33932000D01* +X42112500Y-33932000D01* +X42112500Y-33952000D01* +X41887500Y-33952000D01* +X41887500Y-33932000D01* +X41298750Y-33932000D01* +X41140000Y-34090750D01* +X41140000Y-34226309D01* +X41236673Y-34459698D01* +X41415301Y-34638327D01* +X41426583Y-34643000D01* +X39479892Y-34643000D01* +X38770087Y-33933195D01* +X38770210Y-33792389D01* +X38766641Y-33783750D01* +X38915000Y-33783750D01* +X38915000Y-33876309D01* +X39011673Y-34109698D01* +X39190301Y-34288327D01* +X39423690Y-34385000D01* +X39714250Y-34385000D01* +X39873000Y-34226250D01* +X39873000Y-33625000D01* +X40127000Y-33625000D01* +X40127000Y-34226250D01* +X40285750Y-34385000D01* +X40576310Y-34385000D01* +X40809699Y-34288327D01* +X40988327Y-34109698D01* +X41085000Y-33876309D01* +X41085000Y-33783750D01* +X40926250Y-33625000D01* +X40127000Y-33625000D01* +X39873000Y-33625000D01* +X39073750Y-33625000D01* +X38915000Y-33783750D01* +X38766641Y-33783750D01* +X38670399Y-33550827D01* +X38503554Y-33383691D01* +X41140000Y-33383691D01* +X41140000Y-33519250D01* +X41298750Y-33678000D01* +X41887500Y-33678000D01* +X41887500Y-33033750D01* +X42112500Y-33033750D01* +X42112500Y-33678000D01* +X42701250Y-33678000D01* +X42860000Y-33519250D01* +X42860000Y-33383691D01* +X42763327Y-33150302D01* +X42584699Y-32971673D01* +X42351310Y-32875000D01* +X42271250Y-32875000D01* +X42112500Y-33033750D01* +X41887500Y-33033750D01* +X41728750Y-32875000D01* +X41648690Y-32875000D01* +X41415301Y-32971673D01* +X41236673Y-33150302D01* +X41140000Y-33383691D01* +X38503554Y-33383691D01* +X38485743Y-33365849D01* +X38441189Y-33347349D01* +X38436245Y-33339949D01* +X38219987Y-33123691D01* +X38915000Y-33123691D01* +X38915000Y-33216250D01* +X39073750Y-33375000D01* +X39873000Y-33375000D01* +X39873000Y-32773750D01* +X40127000Y-32773750D01* +X40127000Y-33375000D01* +X40926250Y-33375000D01* +X41085000Y-33216250D01* +X41085000Y-33123691D01* +X40988327Y-32890302D01* +X40809699Y-32711673D01* +X40576310Y-32615000D01* +X40285750Y-32615000D01* +X40127000Y-32773750D01* +X39873000Y-32773750D01* +X39714250Y-32615000D01* +X39423690Y-32615000D01* +X39190301Y-32711673D01* +X39011673Y-32890302D01* +X38915000Y-33123691D01* +X38219987Y-33123691D01* +X37063994Y-31967698D01* +X37063994Y-31750000D01* +X37039101Y-31617704D01* +X36960914Y-31496198D01* +X36841614Y-31414684D01* +X36700000Y-31386006D01* +X36674380Y-31386006D01* +X36672213Y-31375114D01* +X36573148Y-31226852D01* +X36207000Y-30860704D01* +X36207000Y-29369250D01* +X36350000Y-29226250D01* +X36350000Y-28960807D01* +X36411673Y-29109699D01* +X36590302Y-29288327D01* +X36627474Y-29303724D01* +X36708750Y-29385000D01* +X36776309Y-29385000D01* +X36800000Y-29375187D01* +X36823691Y-29385000D01* +X36891250Y-29385000D01* +X36972526Y-29303724D01* +X37009698Y-29288327D01* +X37150000Y-29148026D01* +X37290302Y-29288327D01* +X37327474Y-29303724D01* +X37408750Y-29385000D01* +X37476309Y-29385000D01* +X37500000Y-29375187D01* +X37523691Y-29385000D01* +X37591250Y-29385000D01* +X37672526Y-29303724D01* +X37709698Y-29288327D01* +X37888327Y-29109699D01* +X37950000Y-28960807D01* +X37950000Y-29226250D01* +X38093000Y-29369250D01* +X38093000Y-30100000D01* +X38127787Y-30274887D01* +X38226852Y-30423148D01* +X39294815Y-31491111D01* +X39214684Y-31608386D01* +X39186006Y-31750000D01* +X39186006Y-32250000D01* +X39210899Y-32382296D01* +X39289086Y-32503802D01* +X39408386Y-32585316D01* +X39550000Y-32613994D01* +X40450000Y-32613994D01* +X40582296Y-32589101D01* +X40703802Y-32510914D01* +X40785316Y-32391614D01* +X40813994Y-32250000D01* +X40813994Y-31750000D01* +X40789101Y-31617704D01* +X40710914Y-31496198D01* +X40591614Y-31414684D01* +X40450000Y-31386006D01* +X40424380Y-31386006D01* +X40422213Y-31375114D01* +X40323148Y-31226852D01* +X39653296Y-30557000D01* +X40285704Y-30557000D01* +X41411006Y-31682302D01* +X41411006Y-31990000D01* +X41435899Y-32122296D01* +X41514086Y-32243802D01* +X41633386Y-32325316D01* +X41775000Y-32353994D01* +X42225000Y-32353994D01* +X42357296Y-32329101D01* +X42478802Y-32250914D01* +X42560316Y-32131614D01* +X42588994Y-31990000D01* +X42588994Y-31400000D01* +X42564101Y-31267704D01* +X42485914Y-31146198D01* +X42366614Y-31064684D01* +X42225000Y-31036006D01* +X42057302Y-31036006D01* +X41578296Y-30557000D01* +X42510704Y-30557000D01* +X43339371Y-31385667D01* +X43289684Y-31458386D01* +X43261006Y-31600000D01* +X43261006Y-32400000D01* +X43285899Y-32532296D01* +X43296490Y-32548754D01* +X43265301Y-32561673D01* +X43086673Y-32740302D01* +X42990000Y-32973691D01* +X42990000Y-33214250D01* +X43148750Y-33373000D01* +X43873000Y-33373000D01* +X43873000Y-33353000D01* +X44127000Y-33353000D01* +X44127000Y-33373000D01* +X44851250Y-33373000D01* +X44875000Y-33349250D01* +X44898750Y-33373000D01* +X45623000Y-33373000D01* +X45623000Y-33353000D01* +X45877000Y-33353000D01* +X45877000Y-33373000D01* +X46601250Y-33373000D01* +X46676477Y-33297773D01* +X46761006Y-33382302D01* +X46761006Y-33900000D01* +X46785899Y-34032296D01* +X46864086Y-34153802D01* +X46983386Y-34235316D01* +X47125000Y-34263994D01* +X47875000Y-34263994D01* +X48007296Y-34239101D01* +X48128802Y-34160914D01* +X48210316Y-34041614D01* +X48238994Y-33900000D01* +X48238994Y-33710290D01* +X48351852Y-33823148D01* +X48500114Y-33922213D01* +X48515772Y-33925328D01* +X48535899Y-34032296D01* +X48614086Y-34153802D01* +X48733386Y-34235316D01* +X48875000Y-34263994D01* +X49625000Y-34263994D01* +X49757296Y-34239101D01* +X49878802Y-34160914D01* +X49960316Y-34041614D01* +X49988994Y-33900000D01* +X49988994Y-33100000D01* +X49964101Y-32967704D01* +X49885914Y-32846198D01* +X49766614Y-32764684D01* +X49696641Y-32750514D01* +X49757296Y-32739101D01* +X49878802Y-32660914D01* +X49960316Y-32541614D01* +X49988994Y-32400000D01* +X49988994Y-31600000D01* +X49964101Y-31467704D01* +X49885914Y-31346198D01* +X49766614Y-31264684D01* +X49707000Y-31252612D01* +X49707000Y-30946002D01* +X49696389Y-30892656D01* +X49672213Y-30771115D01* +X49573148Y-30622854D01* +X48224160Y-29273866D01* +X48388327Y-29109699D01* +X48485000Y-28876310D01* +X48485000Y-27535750D01* +X48326250Y-27377000D01* +X47750000Y-27377000D01* +X47750000Y-27397000D01* +X47550000Y-27397000D01* +X47550000Y-27377000D01* +X47513994Y-27377000D01* +X47513994Y-27123000D01* +X47550000Y-27123000D01* +X47550000Y-25273750D01* +X47391250Y-25115000D01* +X47323691Y-25115000D01* +X47090302Y-25211673D01* +X46915968Y-25386006D01* +X46750000Y-25386006D01* +X46617704Y-25410899D01* +X46601415Y-25421381D01* +X46591614Y-25414684D01* +X46450000Y-25386006D01* +X46166778Y-25386006D01* +X46329789Y-25223279D01* +X46430022Y-24981892D01* +X46430250Y-24720521D01* +X46330439Y-24478959D01* +X46145783Y-24293981D01* +X45904396Y-24193748D01* +X45643025Y-24193520D01* +X45401463Y-24293331D01* +X45376117Y-24318633D01* +X44699367Y-24318633D01* +X44495779Y-24359129D01* +X44323186Y-24474452D01* +X43773819Y-25023819D01* +X43658496Y-25196412D01* +X43620784Y-25386006D01* +X43484032Y-25386006D01* +X43309698Y-25211673D01* +X43076309Y-25115000D01* +X43008750Y-25115000D01* +X42850000Y-25273750D01* +X42850000Y-27123000D01* +X42886006Y-27123000D01* +X42886006Y-27377000D01* +X42850000Y-27377000D01* +X42850000Y-27397000D01* +X42650000Y-27397000D01* +X42650000Y-27377000D01* +X42613994Y-27377000D01* +X42613994Y-27123000D01* +X42650000Y-27123000D01* +X42650000Y-25273750D01* +X42491250Y-25115000D01* +X42423691Y-25115000D01* +X42190302Y-25211673D01* +X42050000Y-25351974D01* +X41909698Y-25211673D01* +X41676309Y-25115000D01* +X41608750Y-25115000D01* +X41450000Y-25273750D01* +X41450000Y-27123000D01* +X41486006Y-27123000D01* +X41486006Y-27377000D01* +X41450000Y-27377000D01* +X41450000Y-27397000D01* +X41250000Y-27397000D01* +X41250000Y-27377000D01* +X41213994Y-27377000D01* +X41213994Y-27123000D01* +X41250000Y-27123000D01* +X41250000Y-25273750D01* +X41091250Y-25115000D01* +X41023691Y-25115000D01* +X40790302Y-25211673D01* +X40650000Y-25351974D01* +X40509698Y-25211673D01* +X40276309Y-25115000D01* +X40208750Y-25115000D01* +X40050000Y-25273750D01* +X40050000Y-25539193D01* +X39988327Y-25390301D01* +X39809698Y-25211673D01* +X39772526Y-25196276D01* +X39691250Y-25115000D01* +X39623691Y-25115000D01* +X39600000Y-25124813D01* +X39576309Y-25115000D01* +X39508750Y-25115000D01* +X39427474Y-25196276D01* +X39390302Y-25211673D01* +X39211673Y-25390301D01* +X39150000Y-25539193D01* +X39150000Y-25273750D01* +X38991250Y-25115000D01* +X38923691Y-25115000D01* +X38690302Y-25211673D01* +X38550000Y-25351974D01* +X38409698Y-25211673D01* +X38176309Y-25115000D01* +X38108750Y-25115000D01* +X37950000Y-25273750D01* +X37950000Y-25539193D01* +X37888327Y-25390301D01* +X37709698Y-25211673D01* +X37672526Y-25196276D01* +X37591250Y-25115000D01* +X37523691Y-25115000D01* +X37500000Y-25124813D01* +X37476309Y-25115000D01* +X37408750Y-25115000D01* +X37327474Y-25196276D01* +X37290302Y-25211673D01* +X37150000Y-25351974D01* +X37009698Y-25211673D01* +X36972526Y-25196276D01* +X36891250Y-25115000D01* +X36823691Y-25115000D01* +X36800000Y-25124813D01* +X36776309Y-25115000D01* +X36708750Y-25115000D01* +X36627474Y-25196276D01* +X36590302Y-25211673D01* +X36411673Y-25390301D01* +X36350000Y-25539193D01* +X36350000Y-25273750D01* +X36191250Y-25115000D01* +X36123691Y-25115000D01* +X35890302Y-25211673D01* +X35715968Y-25386006D01* +X35550000Y-25386006D01* +X35417704Y-25410899D01* +X35401415Y-25421381D01* +X35391614Y-25414684D01* +X35250000Y-25386006D01* +X34850000Y-25386006D01* +X34717704Y-25410899D01* +X34701415Y-25421381D01* +X34691614Y-25414684D01* +X34550000Y-25386006D01* +X34384032Y-25386006D01* +X34209698Y-25211673D01* +X33976309Y-25115000D01* +X33908750Y-25115000D01* +X33750000Y-25273750D01* +X33750000Y-25539193D01* +X33688327Y-25390301D01* +X33509698Y-25211673D01* +X33472526Y-25196276D01* +X33391250Y-25115000D01* +X33323691Y-25115000D01* +X33300000Y-25124813D01* +X33276309Y-25115000D01* +X33208750Y-25115000D01* +X33127474Y-25196276D01* +X33090302Y-25211673D01* +X32950000Y-25351974D01* +X32809698Y-25211673D01* +X32772526Y-25196276D01* +X32691250Y-25115000D01* +X32623691Y-25115000D01* +X32600000Y-25124813D01* +X32576309Y-25115000D01* +X32508750Y-25115000D01* +X32427474Y-25196276D01* +X32390302Y-25211673D01* +X32250000Y-25351974D01* +X32109698Y-25211673D01* +X32072526Y-25196276D01* +X31991250Y-25115000D01* +X31923691Y-25115000D01* +X31900000Y-25124813D01* +X31876309Y-25115000D01* +X31808750Y-25115000D01* +X31727474Y-25196276D01* +X31690302Y-25211673D01* +X31550000Y-25351974D01* +X31409698Y-25211673D01* +X31372526Y-25196276D01* +X31291250Y-25115000D01* +X31223691Y-25115000D01* +X31200000Y-25124813D01* +X31176309Y-25115000D01* +X31108750Y-25115000D01* +X31027474Y-25196276D01* +X30990302Y-25211673D01* +X30811673Y-25390301D01* +X30750000Y-25539193D01* +X30750000Y-25273750D01* +X30591250Y-25115000D01* +X30523691Y-25115000D01* +X30290302Y-25211673D01* +X30115968Y-25386006D01* +X29950000Y-25386006D01* +X29817704Y-25410899D01* +X29801415Y-25421381D01* +X29791614Y-25414684D01* +X29650000Y-25386006D01* +X29250000Y-25386006D01* +X29117704Y-25410899D01* +X29101415Y-25421381D01* +X29091614Y-25414684D01* +X28950000Y-25386006D01* +X28784032Y-25386006D01* +X28609698Y-25211673D01* +X28376309Y-25115000D01* +X28308750Y-25115000D01* +X28150000Y-25273750D01* +X28150000Y-25539193D01* +X28088327Y-25390301D01* +X27909698Y-25211673D01* +X27872526Y-25196276D01* +X27791250Y-25115000D01* +X27723691Y-25115000D01* +X27700000Y-25124813D01* +X27676309Y-25115000D01* +X27608750Y-25115000D01* +X27527474Y-25196276D01* +X27490302Y-25211673D01* +X27311673Y-25390301D01* +X27250000Y-25539193D01* +X27250000Y-25273750D01* +X27091250Y-25115000D01* +X27023691Y-25115000D01* +X26907000Y-25163335D01* +X26907000Y-24657006D01* +X27030112Y-24657113D01* +X27271674Y-24557302D01* +X27456652Y-24372646D01* +X27514031Y-24234463D01* +X31635811Y-24234463D01* +X31810698Y-24199676D01* +X31958959Y-24100611D01* +X34601995Y-21457575D01* +X34722605Y-21457575D01* +X34843000Y-21577970D01* +X34843000Y-22680596D01* +X34877787Y-22855483D01* +X34976852Y-23003744D01* +X36016257Y-24043149D01* +X36164519Y-24142214D01* +X36339405Y-24177002D01* +X36339410Y-24177001D01* +X46094297Y-24177001D01* +X46269184Y-24142214D01* +X46417445Y-24043149D01* +X47025397Y-23435197D01* +X47958503Y-23435197D01* +X48043000Y-23519693D01* +X48043000Y-24827875D01* +X47943348Y-24927354D01* +X47843115Y-25168741D01* +X47843105Y-25180645D01* +X47750000Y-25273750D01* +X47750000Y-27123000D01* +X48326250Y-27123000D01* +X48485000Y-26964250D01* +X48485000Y-26035750D01* +X49490000Y-26035750D01* +X49490000Y-26276309D01* +X49586673Y-26509698D01* +X49765301Y-26688327D01* +X49998690Y-26785000D01* +X50214250Y-26785000D01* +X50373000Y-26626250D01* +X50373000Y-25877000D01* +X49648750Y-25877000D01* +X49490000Y-26035750D01* +X48485000Y-26035750D01* +X48485000Y-25956986D01* +X48630112Y-25957113D01* +X48871674Y-25857302D01* +X49056652Y-25672646D01* +X49156885Y-25431259D01* +X49157113Y-25169888D01* +X49057302Y-24928326D01* +X48957000Y-24827849D01* +X48957000Y-23330398D01* +X48922213Y-23155512D01* +X48823148Y-23007250D01* +X48823145Y-23007248D01* +X48470947Y-22655049D01* +X48322686Y-22555984D01* +X48147799Y-22521197D01* +X46836101Y-22521197D01* +X46661214Y-22555984D01* +X46512953Y-22655049D01* +X45905001Y-23263001D01* +X37989361Y-23263001D01* +X38420362Y-22832000D01* +X44302745Y-22832000D01* +X44327354Y-22856652D01* +X44568741Y-22956885D01* +X44830112Y-22957113D01* +X45071674Y-22857302D01* +X45256652Y-22672646D01* +X45356885Y-22431259D01* +X45357113Y-22169888D01* +X45257302Y-21928326D01* +X45072646Y-21743348D01* +X44831259Y-21643115D01* +X44569888Y-21642887D01* +X44328326Y-21742698D01* +X44302980Y-21768000D01* +X44078296Y-21768000D01* +X44589296Y-21257000D01* +X49110704Y-21257000D01* +X49596853Y-21743149D01* +X49596853Y-21743149D01* +G37* +X49596853Y-21743149D02* +X49745115Y-21842214D01* +X49920001Y-21877001D01* +X50749601Y-21877001D01* +X50924488Y-21842214D01* +X51072749Y-21743149D01* +X51158898Y-21657000D01* +X51536006Y-21657000D01* +X51536006Y-21743000D01* +X51378998Y-21743000D01* +X51204112Y-21777787D01* +X51055850Y-21876852D01* +X49581851Y-23350851D01* +X49482786Y-23499112D01* +X49462206Y-23602576D01* +X49447999Y-23673999D01* +X49447999Y-24826001D01* +X49482786Y-25000888D01* +X49544210Y-25092816D01* +X49490000Y-25223691D01* +X49490000Y-25464250D01* +X49648750Y-25623000D01* +X50373000Y-25623000D01* +X50373000Y-25603000D01* +X50627000Y-25603000D01* +X50627000Y-25623000D01* +X50647000Y-25623000D01* +X50647000Y-25877000D01* +X50627000Y-25877000D01* +X50627000Y-26626250D01* +X50785750Y-26785000D01* +X51001310Y-26785000D01* +X51234699Y-26688327D01* +X51413327Y-26509698D01* +X51510000Y-26276309D01* +X51510000Y-26235294D01* +X51943000Y-26668294D01* +X51943000Y-26836006D01* +X51900000Y-26836006D01* +X51767704Y-26860899D01* +X51646198Y-26939086D01* +X51564684Y-27058386D01* +X51536006Y-27200000D01* +X51536006Y-28011632D01* +X50873819Y-28673819D01* +X50758496Y-28846412D01* +X50718000Y-29050000D01* +X50718000Y-30950000D01* +X50758496Y-31153588D01* +X50813566Y-31236006D01* +X50873819Y-31326181D01* +X51536006Y-31988368D01* +X51536006Y-32800000D01* +X51560899Y-32932296D01* +X51639086Y-33053802D01* +X51758386Y-33135316D01* +X51868000Y-33157514D01* +X51868000Y-36842027D01* +X51767704Y-36860899D01* +X51646198Y-36939086D01* +X51564684Y-37058386D01* +X51536006Y-37200000D01* +X51536006Y-37268000D01* +X51450000Y-37268000D01* +X51246412Y-37308496D01* +X51176937Y-37354918D01* +X51073819Y-37423819D01* +X50123819Y-38373819D01* +X50008496Y-38546412D01* +X49968000Y-38750000D01* +X49968000Y-40651435D01* +X49917704Y-40660899D01* +X49796198Y-40739086D01* +X49714684Y-40858386D01* +X49686006Y-41000000D01* +X49686006Y-41500000D01* +X49710899Y-41632296D01* +X49789086Y-41753802D01* +X49908386Y-41835316D01* +X50050000Y-41863994D01* +X50950000Y-41863994D01* +X51082296Y-41839101D01* +X51171033Y-41782000D01* +X51329638Y-41782000D01* +X51536006Y-41988368D01* +X51536006Y-42255409D01* +X51488327Y-42140302D01* +X51309699Y-41961673D01* +X51076310Y-41865000D01* +X50785750Y-41865000D01* +X50627000Y-42023750D01* +X50627000Y-42625000D01* +X50647000Y-42625000D01* +X50647000Y-42875000D01* +X50627000Y-42875000D01* +X50627000Y-44123000D01* +X50647000Y-44123000D01* +X50647000Y-44377000D01* +X50627000Y-44377000D01* +X50627000Y-44397000D01* +X50373000Y-44397000D01* +X50373000Y-44377000D01* +X49648750Y-44377000D01* +X49551222Y-44474528D01* +X48953546Y-43876852D01* +X48805285Y-43777787D01* +X48630398Y-43743000D01* +X43275284Y-43743000D01* +X42566034Y-43033750D01* +X49415000Y-43033750D01* +X49415000Y-43126309D01* +X49511673Y-43359698D01* +X49614475Y-43462500D01* +X49586673Y-43490302D01* +X49490000Y-43723691D01* +X49490000Y-43964250D01* +X49648750Y-44123000D01* +X50373000Y-44123000D01* +X50373000Y-42875000D01* +X49573750Y-42875000D01* +X49415000Y-43033750D01* +X42566034Y-43033750D01* +X41683635Y-42151351D01* +X41712033Y-42157000D01* +X42346702Y-42157000D01* +X42346702Y-42516000D01* +X42371595Y-42648296D01* +X42449782Y-42769802D01* +X42569082Y-42851316D01* +X42710696Y-42879994D01* +X44742696Y-42879994D01* +X44874992Y-42855101D01* +X44996498Y-42776914D01* +X45078012Y-42657614D01* +X45106690Y-42516000D01* +X45106690Y-42214677D01* +X45295838Y-42497757D01* +X45741272Y-42795386D01* +X46266696Y-42899899D01* +X46792120Y-42795386D01* +X47237554Y-42497757D01* +X47320452Y-42373691D01* +X49415000Y-42373691D01* +X49415000Y-42466250D01* +X49573750Y-42625000D01* +X50373000Y-42625000D01* +X50373000Y-42023750D01* +X50214250Y-41865000D01* +X49923690Y-41865000D01* +X49690301Y-41961673D01* +X49511673Y-42140302D01* +X49415000Y-42373691D01* +X47320452Y-42373691D01* +X47535183Y-42052323D01* +X47639696Y-41526899D01* +X47639696Y-41473101D01* +X47535183Y-40947677D01* +X47237554Y-40502243D01* +X46792120Y-40204614D01* +X46758696Y-40197966D01* +X46758696Y-39737436D01* +X46759042Y-39737371D01* +X46880548Y-39659184D01* +X46962062Y-39539884D01* +X46990740Y-39398270D01* +X46990740Y-38598170D01* +X46965847Y-38465874D01* +X46901188Y-38365391D01* +X46956885Y-38231259D01* +X46957113Y-37969888D01* +X46956597Y-37968639D01* +X47049696Y-37875540D01* +X47049696Y-37126240D01* +X47303696Y-37126240D01* +X47303696Y-37875540D01* +X47462446Y-38034290D01* +X47703055Y-38034290D01* +X47936444Y-37937617D01* +X48115073Y-37758989D01* +X48211746Y-37525600D01* +X48211746Y-37284990D01* +X48052996Y-37126240D01* +X47303696Y-37126240D01* +X47049696Y-37126240D01* +X46300396Y-37126240D01* +X46141646Y-37284990D01* +X46141646Y-37454556D01* +X46019312Y-37505104D01* +X46040740Y-37399290D01* +X46040740Y-36599190D01* +X46016974Y-36472880D01* +X46141646Y-36472880D01* +X46141646Y-36713490D01* +X46300396Y-36872240D01* +X47049696Y-36872240D01* +X47049696Y-36122940D01* +X47303696Y-36122940D01* +X47303696Y-36872240D01* +X48052996Y-36872240D01* +X48211746Y-36713490D01* +X48211746Y-36472880D01* +X48115073Y-36239491D01* +X47936444Y-36060863D01* +X47703055Y-35964190D01* +X47462446Y-35964190D01* +X47303696Y-36122940D01* +X47049696Y-36122940D01* +X46890946Y-35964190D01* +X46650337Y-35964190D01* +X46416948Y-36060863D01* +X46238319Y-36239491D01* +X46141646Y-36472880D01* +X46016974Y-36472880D01* +X46015847Y-36466894D01* +X45937660Y-36345388D01* +X45818360Y-36263874D01* +X45676746Y-36235196D01* +X44876646Y-36235196D01* +X44744350Y-36260089D01* +X44622844Y-36338276D01* +X44541330Y-36457576D01* +X44539373Y-36467240D01* +X43477456Y-36467240D01* +X43273868Y-36507736D01* +X43101769Y-36622729D01* +X43101275Y-36623059D01* +X43088328Y-36636006D01* +X42776696Y-36636006D01* +X42644400Y-36660899D01* +X42522894Y-36739086D01* +X42441380Y-36858386D01* +X42412702Y-37000000D01* +X42412702Y-37500000D01* +X42437595Y-37632296D01* +X42444483Y-37643000D01* +X40253195Y-37643000D01* +X39276383Y-36666188D01* +X39430173Y-36512666D01* +X39530406Y-36271279D01* +X39530575Y-36077010D01* +X44679990Y-36077010D01* +X44854877Y-36042223D01* +X45003138Y-35943158D01* +X45289305Y-35656990D01* +X45430112Y-35657113D01* +X45671674Y-35557302D01* +X45856652Y-35372646D01* +X45956885Y-35131259D01* +X45957113Y-34869888D01* +X45857302Y-34628326D01* +X45764138Y-34535000D01* +X45877002Y-34535000D01* +X45877002Y-34376252D01* +X46035750Y-34535000D01* +X46251310Y-34535000D01* +X46484699Y-34438327D01* +X46663327Y-34259698D01* +X46760000Y-34026309D01* +X46760000Y-33785750D01* +X46601250Y-33627000D01* +X45877000Y-33627000D01* +X45877000Y-33647000D01* +X45623000Y-33647000D01* +X45623000Y-33627000D01* +X44898750Y-33627000D01* +X44875000Y-33650750D01* +X44851250Y-33627000D01* +X44127000Y-33627000D01* +X44127000Y-33647000D01* +X43873000Y-33647000D01* +X43873000Y-33627000D01* +X43148750Y-33627000D01* +X42990000Y-33785750D01* +X42990000Y-34026309D01* +X43086673Y-34259698D01* +X43265301Y-34438327D01* +X43472855Y-34524299D01* +X43428326Y-34542698D01* +X43327849Y-34643000D01* +X42573417Y-34643000D01* +X42584699Y-34638327D01* +X42763327Y-34459698D01* +X42860000Y-34226309D01* +X42860000Y-34090750D01* +X42701250Y-33932000D01* +X42112500Y-33932000D01* +X42112500Y-33952000D01* +X41887500Y-33952000D01* +X41887500Y-33932000D01* +X41298750Y-33932000D01* +X41140000Y-34090750D01* +X41140000Y-34226309D01* +X41236673Y-34459698D01* +X41415301Y-34638327D01* +X41426583Y-34643000D01* +X39479892Y-34643000D01* +X38770087Y-33933195D01* +X38770210Y-33792389D01* +X38766641Y-33783750D01* +X38915000Y-33783750D01* +X38915000Y-33876309D01* +X39011673Y-34109698D01* +X39190301Y-34288327D01* +X39423690Y-34385000D01* +X39714250Y-34385000D01* +X39873000Y-34226250D01* +X39873000Y-33625000D01* +X40127000Y-33625000D01* +X40127000Y-34226250D01* +X40285750Y-34385000D01* +X40576310Y-34385000D01* +X40809699Y-34288327D01* +X40988327Y-34109698D01* +X41085000Y-33876309D01* +X41085000Y-33783750D01* +X40926250Y-33625000D01* +X40127000Y-33625000D01* +X39873000Y-33625000D01* +X39073750Y-33625000D01* +X38915000Y-33783750D01* +X38766641Y-33783750D01* +X38670399Y-33550827D01* +X38503554Y-33383691D01* +X41140000Y-33383691D01* +X41140000Y-33519250D01* +X41298750Y-33678000D01* +X41887500Y-33678000D01* +X41887500Y-33033750D01* +X42112500Y-33033750D01* +X42112500Y-33678000D01* +X42701250Y-33678000D01* +X42860000Y-33519250D01* +X42860000Y-33383691D01* +X42763327Y-33150302D01* +X42584699Y-32971673D01* +X42351310Y-32875000D01* +X42271250Y-32875000D01* +X42112500Y-33033750D01* +X41887500Y-33033750D01* +X41728750Y-32875000D01* +X41648690Y-32875000D01* +X41415301Y-32971673D01* +X41236673Y-33150302D01* +X41140000Y-33383691D01* +X38503554Y-33383691D01* +X38485743Y-33365849D01* +X38441189Y-33347349D01* +X38436245Y-33339949D01* +X38219987Y-33123691D01* +X38915000Y-33123691D01* +X38915000Y-33216250D01* +X39073750Y-33375000D01* +X39873000Y-33375000D01* +X39873000Y-32773750D01* +X40127000Y-32773750D01* +X40127000Y-33375000D01* +X40926250Y-33375000D01* +X41085000Y-33216250D01* +X41085000Y-33123691D01* +X40988327Y-32890302D01* +X40809699Y-32711673D01* +X40576310Y-32615000D01* +X40285750Y-32615000D01* +X40127000Y-32773750D01* +X39873000Y-32773750D01* +X39714250Y-32615000D01* +X39423690Y-32615000D01* +X39190301Y-32711673D01* +X39011673Y-32890302D01* +X38915000Y-33123691D01* +X38219987Y-33123691D01* +X37063994Y-31967698D01* +X37063994Y-31750000D01* +X37039101Y-31617704D01* +X36960914Y-31496198D01* +X36841614Y-31414684D01* +X36700000Y-31386006D01* +X36674380Y-31386006D01* +X36672213Y-31375114D01* +X36573148Y-31226852D01* +X36207000Y-30860704D01* +X36207000Y-29369250D01* +X36350000Y-29226250D01* +X36350000Y-28960807D01* +X36411673Y-29109699D01* +X36590302Y-29288327D01* +X36627474Y-29303724D01* +X36708750Y-29385000D01* +X36776309Y-29385000D01* +X36800000Y-29375187D01* +X36823691Y-29385000D01* +X36891250Y-29385000D01* +X36972526Y-29303724D01* +X37009698Y-29288327D01* +X37150000Y-29148026D01* +X37290302Y-29288327D01* +X37327474Y-29303724D01* +X37408750Y-29385000D01* +X37476309Y-29385000D01* +X37500000Y-29375187D01* +X37523691Y-29385000D01* +X37591250Y-29385000D01* +X37672526Y-29303724D01* +X37709698Y-29288327D01* +X37888327Y-29109699D01* +X37950000Y-28960807D01* +X37950000Y-29226250D01* +X38093000Y-29369250D01* +X38093000Y-30100000D01* +X38127787Y-30274887D01* +X38226852Y-30423148D01* +X39294815Y-31491111D01* +X39214684Y-31608386D01* +X39186006Y-31750000D01* +X39186006Y-32250000D01* +X39210899Y-32382296D01* +X39289086Y-32503802D01* +X39408386Y-32585316D01* +X39550000Y-32613994D01* +X40450000Y-32613994D01* +X40582296Y-32589101D01* +X40703802Y-32510914D01* +X40785316Y-32391614D01* +X40813994Y-32250000D01* +X40813994Y-31750000D01* +X40789101Y-31617704D01* +X40710914Y-31496198D01* +X40591614Y-31414684D01* +X40450000Y-31386006D01* +X40424380Y-31386006D01* +X40422213Y-31375114D01* +X40323148Y-31226852D01* +X39653296Y-30557000D01* +X40285704Y-30557000D01* +X41411006Y-31682302D01* +X41411006Y-31990000D01* +X41435899Y-32122296D01* +X41514086Y-32243802D01* +X41633386Y-32325316D01* +X41775000Y-32353994D01* +X42225000Y-32353994D01* +X42357296Y-32329101D01* +X42478802Y-32250914D01* +X42560316Y-32131614D01* +X42588994Y-31990000D01* +X42588994Y-31400000D01* +X42564101Y-31267704D01* +X42485914Y-31146198D01* +X42366614Y-31064684D01* +X42225000Y-31036006D01* +X42057302Y-31036006D01* +X41578296Y-30557000D01* +X42510704Y-30557000D01* +X43339371Y-31385667D01* +X43289684Y-31458386D01* +X43261006Y-31600000D01* +X43261006Y-32400000D01* +X43285899Y-32532296D01* +X43296490Y-32548754D01* +X43265301Y-32561673D01* +X43086673Y-32740302D01* +X42990000Y-32973691D01* +X42990000Y-33214250D01* +X43148750Y-33373000D01* +X43873000Y-33373000D01* +X43873000Y-33353000D01* +X44127000Y-33353000D01* +X44127000Y-33373000D01* +X44851250Y-33373000D01* +X44875000Y-33349250D01* +X44898750Y-33373000D01* +X45623000Y-33373000D01* +X45623000Y-33353000D01* +X45877000Y-33353000D01* +X45877000Y-33373000D01* +X46601250Y-33373000D01* +X46676477Y-33297773D01* +X46761006Y-33382302D01* +X46761006Y-33900000D01* +X46785899Y-34032296D01* +X46864086Y-34153802D01* +X46983386Y-34235316D01* +X47125000Y-34263994D01* +X47875000Y-34263994D01* +X48007296Y-34239101D01* +X48128802Y-34160914D01* +X48210316Y-34041614D01* +X48238994Y-33900000D01* +X48238994Y-33710290D01* +X48351852Y-33823148D01* +X48500114Y-33922213D01* +X48515772Y-33925328D01* +X48535899Y-34032296D01* +X48614086Y-34153802D01* +X48733386Y-34235316D01* +X48875000Y-34263994D01* +X49625000Y-34263994D01* +X49757296Y-34239101D01* +X49878802Y-34160914D01* +X49960316Y-34041614D01* +X49988994Y-33900000D01* +X49988994Y-33100000D01* +X49964101Y-32967704D01* +X49885914Y-32846198D01* +X49766614Y-32764684D01* +X49696641Y-32750514D01* +X49757296Y-32739101D01* +X49878802Y-32660914D01* +X49960316Y-32541614D01* +X49988994Y-32400000D01* +X49988994Y-31600000D01* +X49964101Y-31467704D01* +X49885914Y-31346198D01* +X49766614Y-31264684D01* +X49707000Y-31252612D01* +X49707000Y-30946002D01* +X49696389Y-30892656D01* +X49672213Y-30771115D01* +X49573148Y-30622854D01* +X48224160Y-29273866D01* +X48388327Y-29109699D01* +X48485000Y-28876310D01* +X48485000Y-27535750D01* +X48326250Y-27377000D01* +X47750000Y-27377000D01* +X47750000Y-27397000D01* +X47550000Y-27397000D01* +X47550000Y-27377000D01* +X47513994Y-27377000D01* +X47513994Y-27123000D01* +X47550000Y-27123000D01* +X47550000Y-25273750D01* +X47391250Y-25115000D01* +X47323691Y-25115000D01* +X47090302Y-25211673D01* +X46915968Y-25386006D01* +X46750000Y-25386006D01* +X46617704Y-25410899D01* +X46601415Y-25421381D01* +X46591614Y-25414684D01* +X46450000Y-25386006D01* +X46166778Y-25386006D01* +X46329789Y-25223279D01* +X46430022Y-24981892D01* +X46430250Y-24720521D01* +X46330439Y-24478959D01* +X46145783Y-24293981D01* +X45904396Y-24193748D01* +X45643025Y-24193520D01* +X45401463Y-24293331D01* +X45376117Y-24318633D01* +X44699367Y-24318633D01* +X44495779Y-24359129D01* +X44323186Y-24474452D01* +X43773819Y-25023819D01* +X43658496Y-25196412D01* +X43620784Y-25386006D01* +X43484032Y-25386006D01* +X43309698Y-25211673D01* +X43076309Y-25115000D01* +X43008750Y-25115000D01* +X42850000Y-25273750D01* +X42850000Y-27123000D01* +X42886006Y-27123000D01* +X42886006Y-27377000D01* +X42850000Y-27377000D01* +X42850000Y-27397000D01* +X42650000Y-27397000D01* +X42650000Y-27377000D01* +X42613994Y-27377000D01* +X42613994Y-27123000D01* +X42650000Y-27123000D01* +X42650000Y-25273750D01* +X42491250Y-25115000D01* +X42423691Y-25115000D01* +X42190302Y-25211673D01* +X42050000Y-25351974D01* +X41909698Y-25211673D01* +X41676309Y-25115000D01* +X41608750Y-25115000D01* +X41450000Y-25273750D01* +X41450000Y-27123000D01* +X41486006Y-27123000D01* +X41486006Y-27377000D01* +X41450000Y-27377000D01* +X41450000Y-27397000D01* +X41250000Y-27397000D01* +X41250000Y-27377000D01* +X41213994Y-27377000D01* +X41213994Y-27123000D01* +X41250000Y-27123000D01* +X41250000Y-25273750D01* +X41091250Y-25115000D01* +X41023691Y-25115000D01* +X40790302Y-25211673D01* +X40650000Y-25351974D01* +X40509698Y-25211673D01* +X40276309Y-25115000D01* +X40208750Y-25115000D01* +X40050000Y-25273750D01* +X40050000Y-25539193D01* +X39988327Y-25390301D01* +X39809698Y-25211673D01* +X39772526Y-25196276D01* +X39691250Y-25115000D01* +X39623691Y-25115000D01* +X39600000Y-25124813D01* +X39576309Y-25115000D01* +X39508750Y-25115000D01* +X39427474Y-25196276D01* +X39390302Y-25211673D01* +X39211673Y-25390301D01* +X39150000Y-25539193D01* +X39150000Y-25273750D01* +X38991250Y-25115000D01* +X38923691Y-25115000D01* +X38690302Y-25211673D01* +X38550000Y-25351974D01* +X38409698Y-25211673D01* +X38176309Y-25115000D01* +X38108750Y-25115000D01* +X37950000Y-25273750D01* +X37950000Y-25539193D01* +X37888327Y-25390301D01* +X37709698Y-25211673D01* +X37672526Y-25196276D01* +X37591250Y-25115000D01* +X37523691Y-25115000D01* +X37500000Y-25124813D01* +X37476309Y-25115000D01* +X37408750Y-25115000D01* +X37327474Y-25196276D01* +X37290302Y-25211673D01* +X37150000Y-25351974D01* +X37009698Y-25211673D01* +X36972526Y-25196276D01* +X36891250Y-25115000D01* +X36823691Y-25115000D01* +X36800000Y-25124813D01* +X36776309Y-25115000D01* +X36708750Y-25115000D01* +X36627474Y-25196276D01* +X36590302Y-25211673D01* +X36411673Y-25390301D01* +X36350000Y-25539193D01* +X36350000Y-25273750D01* +X36191250Y-25115000D01* +X36123691Y-25115000D01* +X35890302Y-25211673D01* +X35715968Y-25386006D01* +X35550000Y-25386006D01* +X35417704Y-25410899D01* +X35401415Y-25421381D01* +X35391614Y-25414684D01* +X35250000Y-25386006D01* +X34850000Y-25386006D01* +X34717704Y-25410899D01* +X34701415Y-25421381D01* +X34691614Y-25414684D01* +X34550000Y-25386006D01* +X34384032Y-25386006D01* +X34209698Y-25211673D01* +X33976309Y-25115000D01* +X33908750Y-25115000D01* +X33750000Y-25273750D01* +X33750000Y-25539193D01* +X33688327Y-25390301D01* +X33509698Y-25211673D01* +X33472526Y-25196276D01* +X33391250Y-25115000D01* +X33323691Y-25115000D01* +X33300000Y-25124813D01* +X33276309Y-25115000D01* +X33208750Y-25115000D01* +X33127474Y-25196276D01* +X33090302Y-25211673D01* +X32950000Y-25351974D01* +X32809698Y-25211673D01* +X32772526Y-25196276D01* +X32691250Y-25115000D01* +X32623691Y-25115000D01* +X32600000Y-25124813D01* +X32576309Y-25115000D01* +X32508750Y-25115000D01* +X32427474Y-25196276D01* +X32390302Y-25211673D01* +X32250000Y-25351974D01* +X32109698Y-25211673D01* +X32072526Y-25196276D01* +X31991250Y-25115000D01* +X31923691Y-25115000D01* +X31900000Y-25124813D01* +X31876309Y-25115000D01* +X31808750Y-25115000D01* +X31727474Y-25196276D01* +X31690302Y-25211673D01* +X31550000Y-25351974D01* +X31409698Y-25211673D01* +X31372526Y-25196276D01* +X31291250Y-25115000D01* +X31223691Y-25115000D01* +X31200000Y-25124813D01* +X31176309Y-25115000D01* +X31108750Y-25115000D01* +X31027474Y-25196276D01* +X30990302Y-25211673D01* +X30811673Y-25390301D01* +X30750000Y-25539193D01* +X30750000Y-25273750D01* +X30591250Y-25115000D01* +X30523691Y-25115000D01* +X30290302Y-25211673D01* +X30115968Y-25386006D01* +X29950000Y-25386006D01* +X29817704Y-25410899D01* +X29801415Y-25421381D01* +X29791614Y-25414684D01* +X29650000Y-25386006D01* +X29250000Y-25386006D01* +X29117704Y-25410899D01* +X29101415Y-25421381D01* +X29091614Y-25414684D01* +X28950000Y-25386006D01* +X28784032Y-25386006D01* +X28609698Y-25211673D01* +X28376309Y-25115000D01* +X28308750Y-25115000D01* +X28150000Y-25273750D01* +X28150000Y-25539193D01* +X28088327Y-25390301D01* +X27909698Y-25211673D01* +X27872526Y-25196276D01* +X27791250Y-25115000D01* +X27723691Y-25115000D01* +X27700000Y-25124813D01* +X27676309Y-25115000D01* +X27608750Y-25115000D01* +X27527474Y-25196276D01* +X27490302Y-25211673D01* +X27311673Y-25390301D01* +X27250000Y-25539193D01* +X27250000Y-25273750D01* +X27091250Y-25115000D01* +X27023691Y-25115000D01* +X26907000Y-25163335D01* +X26907000Y-24657006D01* +X27030112Y-24657113D01* +X27271674Y-24557302D01* +X27456652Y-24372646D01* +X27514031Y-24234463D01* +X31635811Y-24234463D01* +X31810698Y-24199676D01* +X31958959Y-24100611D01* +X34601995Y-21457575D01* +X34722605Y-21457575D01* +X34843000Y-21577970D01* +X34843000Y-22680596D01* +X34877787Y-22855483D01* +X34976852Y-23003744D01* +X36016257Y-24043149D01* +X36164519Y-24142214D01* +X36339405Y-24177002D01* +X36339410Y-24177001D01* +X46094297Y-24177001D01* +X46269184Y-24142214D01* +X46417445Y-24043149D01* +X47025397Y-23435197D01* +X47958503Y-23435197D01* +X48043000Y-23519693D01* +X48043000Y-24827875D01* +X47943348Y-24927354D01* +X47843115Y-25168741D01* +X47843105Y-25180645D01* +X47750000Y-25273750D01* +X47750000Y-27123000D01* +X48326250Y-27123000D01* +X48485000Y-26964250D01* +X48485000Y-26035750D01* +X49490000Y-26035750D01* +X49490000Y-26276309D01* +X49586673Y-26509698D01* +X49765301Y-26688327D01* +X49998690Y-26785000D01* +X50214250Y-26785000D01* +X50373000Y-26626250D01* +X50373000Y-25877000D01* +X49648750Y-25877000D01* +X49490000Y-26035750D01* +X48485000Y-26035750D01* +X48485000Y-25956986D01* +X48630112Y-25957113D01* +X48871674Y-25857302D01* +X49056652Y-25672646D01* +X49156885Y-25431259D01* +X49157113Y-25169888D01* +X49057302Y-24928326D01* +X48957000Y-24827849D01* +X48957000Y-23330398D01* +X48922213Y-23155512D01* +X48823148Y-23007250D01* +X48823145Y-23007248D01* +X48470947Y-22655049D01* +X48322686Y-22555984D01* +X48147799Y-22521197D01* +X46836101Y-22521197D01* +X46661214Y-22555984D01* +X46512953Y-22655049D01* +X45905001Y-23263001D01* +X37989361Y-23263001D01* +X38420362Y-22832000D01* +X44302745Y-22832000D01* +X44327354Y-22856652D01* +X44568741Y-22956885D01* +X44830112Y-22957113D01* +X45071674Y-22857302D01* +X45256652Y-22672646D01* +X45356885Y-22431259D01* +X45357113Y-22169888D01* +X45257302Y-21928326D01* +X45072646Y-21743348D01* +X44831259Y-21643115D01* +X44569888Y-21642887D01* +X44328326Y-21742698D01* +X44302980Y-21768000D01* +X44078296Y-21768000D01* +X44589296Y-21257000D01* +X49110704Y-21257000D01* +X49596853Y-21743149D01* +G36* +X31190301Y-34288327D02* +X31370580Y-34363001D01* +X31060025Y-34363001D01* +X31162500Y-34260525D01* +X31190301Y-34288327D01* +X31190301Y-34288327D01* +G37* +X31190301Y-34288327D02* +X31370580Y-34363001D01* +X31060025Y-34363001D01* +X31162500Y-34260525D01* +X31190301Y-34288327D01* +G36* +X30940554Y-20439630D02* +X30970767Y-20469906D01* +X30994530Y-20505470D01* +X31029722Y-20528985D01* +X31059618Y-20558943D01* +X31099116Y-20575352D01* +X31134681Y-20599116D01* +X31176192Y-20607373D01* +X31215278Y-20623611D01* +X31258050Y-20623656D01* +X31300000Y-20632000D01* +X34157538Y-20632000D01* +X34089551Y-20677427D01* +X31446515Y-23320463D01* +X29655080Y-23320463D01* +X29655248Y-23127350D01* +X29555437Y-22885788D01* +X29370781Y-22700810D01* +X29249560Y-22650475D01* +X29249558Y-22650473D01* +X29249555Y-22650472D01* +X29129394Y-22600577D01* +X28998138Y-22600463D01* +X28998135Y-22600462D01* +X28997562Y-22600462D01* +X28868023Y-22600349D01* +X28867750Y-22600462D01* +X26576936Y-22600462D01* +X26325513Y-22650473D01* +X26112367Y-22792893D01* +X25715430Y-23189830D01* +X25573010Y-23402976D01* +X25522999Y-23654399D01* +X25522999Y-24345601D01* +X25573010Y-24597024D01* +X25592907Y-24626802D01* +X25592887Y-24650187D01* +X25593000Y-24650460D01* +X25593000Y-26500000D01* +X25592887Y-26630112D01* +X25593000Y-26630385D01* +X25593000Y-28148870D01* +X25611764Y-28243204D01* +X24207000Y-26838440D01* +X24207000Y-24722125D01* +X24306652Y-24622646D01* +X24406885Y-24381259D01* +X24407113Y-24119888D01* +X24307302Y-23878326D01* +X24122646Y-23693348D01* +X24027000Y-23653632D01* +X24027000Y-20332000D01* +X30868801Y-20332000D01* +X30940554Y-20439630D01* +X30940554Y-20439630D01* +G37* +X30940554Y-20439630D02* +X30970767Y-20469906D01* +X30994530Y-20505470D01* +X31029722Y-20528985D01* +X31059618Y-20558943D01* +X31099116Y-20575352D01* +X31134681Y-20599116D01* +X31176192Y-20607373D01* +X31215278Y-20623611D01* +X31258050Y-20623656D01* +X31300000Y-20632000D01* +X34157538Y-20632000D01* +X34089551Y-20677427D01* +X31446515Y-23320463D01* +X29655080Y-23320463D01* +X29655248Y-23127350D01* +X29555437Y-22885788D01* +X29370781Y-22700810D01* +X29249560Y-22650475D01* +X29249558Y-22650473D01* +X29249555Y-22650472D01* +X29129394Y-22600577D01* +X28998138Y-22600463D01* +X28998135Y-22600462D01* +X28997562Y-22600462D01* +X28868023Y-22600349D01* +X28867750Y-22600462D01* +X26576936Y-22600462D01* +X26325513Y-22650473D01* +X26112367Y-22792893D01* +X25715430Y-23189830D01* +X25573010Y-23402976D01* +X25522999Y-23654399D01* +X25522999Y-24345601D01* +X25573010Y-24597024D01* +X25592907Y-24626802D01* +X25592887Y-24650187D01* +X25593000Y-24650460D01* +X25593000Y-26500000D01* +X25592887Y-26630112D01* +X25593000Y-26630385D01* +X25593000Y-28148870D01* +X25611764Y-28243204D01* +X24207000Y-26838440D01* +X24207000Y-24722125D01* +X24306652Y-24622646D01* +X24406885Y-24381259D01* +X24407113Y-24119888D01* +X24307302Y-23878326D01* +X24122646Y-23693348D01* +X24027000Y-23653632D01* +X24027000Y-20332000D01* +X30868801Y-20332000D01* +X30940554Y-20439630D01* +G36* +X28150000Y-27123000D02* +X28186006Y-27123000D01* +X28186006Y-27377000D01* +X28150000Y-27377000D01* +X28150000Y-27500750D01* +X28026250Y-27377000D01* +X27373750Y-27377000D01* +X27250000Y-27500750D01* +X27250000Y-27377000D01* +X27203000Y-27377000D01* +X27203000Y-27123000D01* +X27250000Y-27123000D01* +X27250000Y-26999250D01* +X27373750Y-27123000D01* +X28026250Y-27123000D01* +X28150000Y-26999250D01* +X28150000Y-27123000D01* +X28150000Y-27123000D01* +G37* +X28150000Y-27123000D02* +X28186006Y-27123000D01* +X28186006Y-27377000D01* +X28150000Y-27377000D01* +X28150000Y-27500750D01* +X28026250Y-27377000D01* +X27373750Y-27377000D01* +X27250000Y-27500750D01* +X27250000Y-27377000D01* +X27203000Y-27377000D01* +X27203000Y-27123000D01* +X27250000Y-27123000D01* +X27250000Y-26999250D01* +X27373750Y-27123000D01* +X28026250Y-27123000D01* +X28150000Y-26999250D01* +X28150000Y-27123000D01* +G36* +X37950000Y-27123000D02* +X37986006Y-27123000D01* +X37986006Y-27377000D01* +X37950000Y-27377000D01* +X37950000Y-27500750D01* +X37826250Y-27377000D01* +X37173750Y-27377000D01* +X37150000Y-27400750D01* +X37126250Y-27377000D01* +X36473750Y-27377000D01* +X36350000Y-27500750D01* +X36350000Y-27377000D01* +X36313994Y-27377000D01* +X36313994Y-27123000D01* +X36350000Y-27123000D01* +X36350000Y-26999250D01* +X36473750Y-27123000D01* +X37126250Y-27123000D01* +X37150000Y-27099250D01* +X37173750Y-27123000D01* +X37826250Y-27123000D01* +X37950000Y-26999250D01* +X37950000Y-27123000D01* +X37950000Y-27123000D01* +G37* +X37950000Y-27123000D02* +X37986006Y-27123000D01* +X37986006Y-27377000D01* +X37950000Y-27377000D01* +X37950000Y-27500750D01* +X37826250Y-27377000D01* +X37173750Y-27377000D01* +X37150000Y-27400750D01* +X37126250Y-27377000D01* +X36473750Y-27377000D01* +X36350000Y-27500750D01* +X36350000Y-27377000D01* +X36313994Y-27377000D01* +X36313994Y-27123000D01* +X36350000Y-27123000D01* +X36350000Y-26999250D01* +X36473750Y-27123000D01* +X37126250Y-27123000D01* +X37150000Y-27099250D01* +X37173750Y-27123000D01* +X37826250Y-27123000D01* +X37950000Y-26999250D01* +X37950000Y-27123000D01* +G36* +X33750000Y-27123000D02* +X33786006Y-27123000D01* +X33786006Y-27377000D01* +X33750000Y-27377000D01* +X33750000Y-27397000D01* +X33646250Y-27397000D01* +X33626250Y-27377000D01* +X32973750Y-27377000D01* +X32953750Y-27397000D01* +X32946250Y-27397000D01* +X32926250Y-27377000D01* +X32273750Y-27377000D01* +X32253750Y-27397000D01* +X32246250Y-27397000D01* +X32226250Y-27377000D01* +X31573750Y-27377000D01* +X31553750Y-27397000D01* +X31546250Y-27397000D01* +X31526250Y-27377000D01* +X30873750Y-27377000D01* +X30853750Y-27397000D01* +X30750000Y-27397000D01* +X30750000Y-27377000D01* +X30713994Y-27377000D01* +X30713994Y-27123000D01* +X30750000Y-27123000D01* +X30750000Y-26999250D01* +X30873750Y-27123000D01* +X31526250Y-27123000D01* +X31550000Y-27099250D01* +X31573750Y-27123000D01* +X32226250Y-27123000D01* +X32250000Y-27099250D01* +X32273750Y-27123000D01* +X32926250Y-27123000D01* +X32950000Y-27099250D01* +X32973750Y-27123000D01* +X33626250Y-27123000D01* +X33750000Y-26999250D01* +X33750000Y-27123000D01* +X33750000Y-27123000D01* +G37* +X33750000Y-27123000D02* +X33786006Y-27123000D01* +X33786006Y-27377000D01* +X33750000Y-27377000D01* +X33750000Y-27397000D01* +X33646250Y-27397000D01* +X33626250Y-27377000D01* +X32973750Y-27377000D01* +X32953750Y-27397000D01* +X32946250Y-27397000D01* +X32926250Y-27377000D01* +X32273750Y-27377000D01* +X32253750Y-27397000D01* +X32246250Y-27397000D01* +X32226250Y-27377000D01* +X31573750Y-27377000D01* +X31553750Y-27397000D01* +X31546250Y-27397000D01* +X31526250Y-27377000D01* +X30873750Y-27377000D01* +X30853750Y-27397000D01* +X30750000Y-27397000D01* +X30750000Y-27377000D01* +X30713994Y-27377000D01* +X30713994Y-27123000D01* +X30750000Y-27123000D01* +X30750000Y-26999250D01* +X30873750Y-27123000D01* +X31526250Y-27123000D01* +X31550000Y-27099250D01* +X31573750Y-27123000D01* +X32226250Y-27123000D01* +X32250000Y-27099250D01* +X32273750Y-27123000D01* +X32926250Y-27123000D01* +X32950000Y-27099250D01* +X32973750Y-27123000D01* +X33626250Y-27123000D01* +X33750000Y-26999250D01* +X33750000Y-27123000D01* +G36* +X40050000Y-27123000D02* +X40086006Y-27123000D01* +X40086006Y-27377000D01* +X40050000Y-27377000D01* +X40050000Y-27397000D01* +X39946250Y-27397000D01* +X39926250Y-27377000D01* +X39273750Y-27377000D01* +X39253750Y-27397000D01* +X39150000Y-27397000D01* +X39150000Y-27377000D01* +X39113994Y-27377000D01* +X39113994Y-27123000D01* +X39150000Y-27123000D01* +X39150000Y-26999250D01* +X39273750Y-27123000D01* +X39926250Y-27123000D01* +X40050000Y-26999250D01* +X40050000Y-27123000D01* +X40050000Y-27123000D01* +G37* +X40050000Y-27123000D02* +X40086006Y-27123000D01* +X40086006Y-27377000D01* +X40050000Y-27377000D01* +X40050000Y-27397000D01* +X39946250Y-27397000D01* +X39926250Y-27377000D01* +X39273750Y-27377000D01* +X39253750Y-27397000D01* +X39150000Y-27397000D01* +X39150000Y-27377000D01* +X39113994Y-27377000D01* +X39113994Y-27123000D01* +X39150000Y-27123000D01* +X39150000Y-26999250D01* +X39273750Y-27123000D01* +X39926250Y-27123000D01* +X40050000Y-26999250D01* +X40050000Y-27123000D01* +G36* +X54568000Y-20001982D02* +X54568000Y-21236006D01* +X53882302Y-21236006D01* +X53523148Y-20876852D01* +X53374887Y-20777787D01* +X53200000Y-20743000D01* +X50969602Y-20743000D01* +X50794716Y-20777787D01* +X50794714Y-20777788D01* +X50794715Y-20777788D01* +X50646454Y-20876852D01* +X50560305Y-20963001D01* +X50109297Y-20963001D01* +X49623148Y-20476852D01* +X49474887Y-20377787D01* +X49300000Y-20343000D01* +X44400000Y-20343000D01* +X44225114Y-20377787D01* +X44076852Y-20476852D01* +X43115714Y-21437990D01* +X36305010Y-21437990D01* +X36130123Y-21472777D01* +X35981862Y-21571842D01* +X35971862Y-21581842D01* +X35971860Y-21581845D01* +X35910695Y-21643010D01* +X35769888Y-21642887D01* +X35757000Y-21648212D01* +X35757000Y-21388674D01* +X35747136Y-21339086D01* +X35722213Y-21213787D01* +X35623148Y-21065526D01* +X35235049Y-20677427D01* +X35167063Y-20632000D01* +X43700000Y-20632000D01* +X43741950Y-20623656D01* +X43784722Y-20623611D01* +X43823808Y-20607373D01* +X43865319Y-20599116D01* +X43900884Y-20575352D01* +X43940382Y-20558943D01* +X43970278Y-20528985D01* +X44005470Y-20505470D01* +X44029233Y-20469906D01* +X44059446Y-20439630D01* +X44131200Y-20332000D01* +X52000000Y-20332000D01* +X52015224Y-20328972D01* +X52030624Y-20330913D01* +X52097403Y-20312625D01* +X52165319Y-20299116D01* +X52178227Y-20290491D01* +X52193196Y-20286392D01* +X52247894Y-20243941D01* +X52305470Y-20205470D01* +X52314094Y-20192564D01* +X52326356Y-20183047D01* +X52360646Y-20122893D01* +X52399116Y-20065319D01* +X52402144Y-20050094D01* +X52409831Y-20036610D01* +X52418491Y-19967915D01* +X52432000Y-19900000D01* +X52428972Y-19884776D01* +X52430913Y-19869376D01* +X52412625Y-19802597D01* +X52399116Y-19734681D01* +X52390491Y-19721773D01* +X52386392Y-19706804D01* +X51486393Y-17906804D01* +X51443938Y-17852101D01* +X51405470Y-17794530D01* +X51392564Y-17785906D01* +X51383047Y-17773644D01* +X51322893Y-17739354D01* +X51265319Y-17700884D01* +X51250094Y-17697856D01* +X51236610Y-17690169D01* +X51167915Y-17681509D01* +X51100000Y-17668000D01* +X23900000Y-17668000D01* +X23832085Y-17681509D01* +X23763390Y-17690169D01* +X23749906Y-17697856D01* +X23734681Y-17700884D01* +X23677107Y-17739354D01* +X23616953Y-17773644D01* +X23607436Y-17785906D01* +X23594530Y-17794530D01* +X23556062Y-17852101D01* +X23513607Y-17906804D01* +X22613607Y-19706804D01* +X22609507Y-19721776D01* +X22600884Y-19734681D01* +X22593262Y-19773000D01* +X20546491Y-19773000D01* +X22266991Y-16332000D01* +X52733009Y-16332000D01* +X54568000Y-20001982D01* +X54568000Y-20001982D01* +G37* +X54568000Y-20001982D02* +X54568000Y-21236006D01* +X53882302Y-21236006D01* +X53523148Y-20876852D01* +X53374887Y-20777787D01* +X53200000Y-20743000D01* +X50969602Y-20743000D01* +X50794716Y-20777787D01* +X50794714Y-20777788D01* +X50794715Y-20777788D01* +X50646454Y-20876852D01* +X50560305Y-20963001D01* +X50109297Y-20963001D01* +X49623148Y-20476852D01* +X49474887Y-20377787D01* +X49300000Y-20343000D01* +X44400000Y-20343000D01* +X44225114Y-20377787D01* +X44076852Y-20476852D01* +X43115714Y-21437990D01* +X36305010Y-21437990D01* +X36130123Y-21472777D01* +X35981862Y-21571842D01* +X35971862Y-21581842D01* +X35971860Y-21581845D01* +X35910695Y-21643010D01* +X35769888Y-21642887D01* +X35757000Y-21648212D01* +X35757000Y-21388674D01* +X35747136Y-21339086D01* +X35722213Y-21213787D01* +X35623148Y-21065526D01* +X35235049Y-20677427D01* +X35167063Y-20632000D01* +X43700000Y-20632000D01* +X43741950Y-20623656D01* +X43784722Y-20623611D01* +X43823808Y-20607373D01* +X43865319Y-20599116D01* +X43900884Y-20575352D01* +X43940382Y-20558943D01* +X43970278Y-20528985D01* +X44005470Y-20505470D01* +X44029233Y-20469906D01* +X44059446Y-20439630D01* +X44131200Y-20332000D01* +X52000000Y-20332000D01* +X52015224Y-20328972D01* +X52030624Y-20330913D01* +X52097403Y-20312625D01* +X52165319Y-20299116D01* +X52178227Y-20290491D01* +X52193196Y-20286392D01* +X52247894Y-20243941D01* +X52305470Y-20205470D01* +X52314094Y-20192564D01* +X52326356Y-20183047D01* +X52360646Y-20122893D01* +X52399116Y-20065319D01* +X52402144Y-20050094D01* +X52409831Y-20036610D01* +X52418491Y-19967915D01* +X52432000Y-19900000D01* +X52428972Y-19884776D01* +X52430913Y-19869376D01* +X52412625Y-19802597D01* +X52399116Y-19734681D01* +X52390491Y-19721773D01* +X52386392Y-19706804D01* +X51486393Y-17906804D01* +X51443938Y-17852101D01* +X51405470Y-17794530D01* +X51392564Y-17785906D01* +X51383047Y-17773644D01* +X51322893Y-17739354D01* +X51265319Y-17700884D01* +X51250094Y-17697856D01* +X51236610Y-17690169D01* +X51167915Y-17681509D01* +X51100000Y-17668000D01* +X23900000Y-17668000D01* +X23832085Y-17681509D01* +X23763390Y-17690169D01* +X23749906Y-17697856D01* +X23734681Y-17700884D01* +X23677107Y-17739354D01* +X23616953Y-17773644D01* +X23607436Y-17785906D01* +X23594530Y-17794530D01* +X23556062Y-17852101D01* +X23513607Y-17906804D01* +X22613607Y-19706804D01* +X22609507Y-19721776D01* +X22600884Y-19734681D01* +X22593262Y-19773000D01* +X20546491Y-19773000D01* +X22266991Y-16332000D01* +X52733009Y-16332000D01* +X54568000Y-20001982D01* +M02* diff --git a/board/v1/gerber/handgelenk.gbo b/board/v1/gerber/handgelenk.gbo new file mode 100644 index 0000000..30a2236 --- /dev/null +++ b/board/v1/gerber/handgelenk.gbo @@ -0,0 +1,1014 @@ +G04 #@! TF.FileFunction,Legend,Bot* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11C,0.150000*% +G04 APERTURE END LIST* +D10* +D11* +X31500000Y-20850000D02* +X31500000Y-19850000D01* +X43500000Y-19850000D02* +X43500000Y-20850000D01* +X43500000Y-19850000D02* +X42600000Y-19850000D01* +X42600000Y-19850000D02* +X31500000Y-19850000D01* +X26500000Y-23750000D02* +X31500000Y-20850000D01* +X43500000Y-20850000D02* +X48500000Y-23750000D01* +X26500000Y-27750000D02* +X26500000Y-23750000D01* +X48500000Y-27750000D02* +X48500000Y-23750000D01* +X42000000Y-32500000D02* +X42000000Y-32250000D01* +X42000000Y-33000000D02* +X42000000Y-33250000D01* +X42000000Y-33000000D02* +X42350000Y-32500000D01* +X42350000Y-32500000D02* +X41650000Y-32500000D01* +X41650000Y-32500000D02* +X42000000Y-33000000D01* +X42350000Y-33000000D02* +X41650000Y-33000000D01* +X41200000Y-34050000D02* +X41200000Y-31650000D01* +X42800000Y-34050000D02* +X42800000Y-31650000D01* +X40675000Y-33250000D02* +X40675000Y-32250000D01* +X39325000Y-32250000D02* +X39325000Y-33250000D01* +X18932540Y-49600900D02* +X18932540Y-40900900D01* +X25337540Y-49600900D02* +X25337540Y-40900900D01* +X25337540Y-40900900D02* +X18932540Y-40900900D01* +X20162540Y-40900900D02* +X20162540Y-49600900D01* +X18932540Y-49600900D02* +X25337540Y-49600900D01* +X49900000Y-24650000D02* +X49900000Y-25350000D01* +X51100000Y-25350000D02* +X51100000Y-24650000D01* +X51100000Y-45350000D02* +X51100000Y-44650000D01* +X49900000Y-44650000D02* +X49900000Y-45350000D01* +X45150000Y-32400000D02* +X45150000Y-33100000D01* +X46350000Y-33100000D02* +X46350000Y-32400000D01* +X43400000Y-32400000D02* +X43400000Y-33100000D01* +X44600000Y-33100000D02* +X44600000Y-32400000D01* +X29650000Y-32400000D02* +X29650000Y-33100000D01* +X30850000Y-33100000D02* +X30850000Y-32400000D01* +X26150000Y-32400000D02* +X26150000Y-33100000D01* +X27350000Y-33100000D02* +X27350000Y-32400000D01* +X49850000Y-33100000D02* +X49850000Y-32400000D01* +X48650000Y-32400000D02* +X48650000Y-33100000D01* +X48100000Y-33100000D02* +X48100000Y-32400000D01* +X46900000Y-32400000D02* +X46900000Y-33100000D01* +X27900000Y-32400000D02* +X27900000Y-33100000D01* +X29100000Y-33100000D02* +X29100000Y-32400000D01* +X53500000Y-30000000D02* +X53750000Y-30000000D01* +X53000000Y-30000000D02* +X52750000Y-30000000D01* +X53000000Y-30000000D02* +X53500000Y-30350000D01* +X53500000Y-30350000D02* +X53500000Y-29650000D01* +X53500000Y-29650000D02* +X53000000Y-30000000D01* +X53000000Y-30350000D02* +X53000000Y-29650000D01* +X51950000Y-29200000D02* +X54350000Y-29200000D01* +X51950000Y-30800000D02* +X54350000Y-30800000D01* +X53500000Y-40000000D02* +X53750000Y-40000000D01* +X53000000Y-40000000D02* +X52750000Y-40000000D01* +X53000000Y-40000000D02* +X53500000Y-40350000D01* +X53500000Y-40350000D02* +X53500000Y-39650000D01* +X53500000Y-39650000D02* +X53000000Y-40000000D01* +X53000000Y-40350000D02* +X53000000Y-39650000D01* +X51950000Y-39200000D02* +X54350000Y-39200000D01* +X51950000Y-40800000D02* +X54350000Y-40800000D01* +X47525856Y-38650240D02* +X47477596Y-38650240D01* +X44726876Y-37949200D02* +X44726876Y-38650240D01* +X44726876Y-38650240D02* +X44975796Y-38650240D01* +X47525856Y-38650240D02* +X47726516Y-38650240D01* +X47726516Y-38650240D02* +X47726516Y-37949200D01* +X43901696Y-38500000D02* +X43901696Y-37500000D01* +X42551696Y-37500000D02* +X42551696Y-38500000D01* +X33825000Y-32250000D02* +X33825000Y-33250000D01* +X35175000Y-33250000D02* +X35175000Y-32250000D01* +X35575000Y-32250000D02* +X35575000Y-33250000D01* +X36925000Y-33250000D02* +X36925000Y-32250000D01* +X51175000Y-42500000D02* +X51175000Y-41500000D01* +X49825000Y-41500000D02* +X49825000Y-42500000D01* +X32675000Y-33250000D02* +X32675000Y-32250000D01* +X31325000Y-32250000D02* +X31325000Y-33250000D01* +X55050000Y-26300000D02* +X56150000Y-26300000D01* +X55050000Y-23700000D02* +X56150000Y-23700000D01* +X56150000Y-26300000D02* +X56150000Y-23700000D01* +X55050000Y-27300000D02* +X55050000Y-22700000D01* +X51450000Y-22700000D02* +X55050000Y-22700000D01* +X51450000Y-27300000D02* +X55050000Y-27300000D01* +X51450000Y-27300000D02* +X51450000Y-22700000D01* +X55050000Y-46300000D02* +X56150000Y-46300000D01* +X55050000Y-43700000D02* +X56150000Y-43700000D01* +X56150000Y-46300000D02* +X56150000Y-43700000D01* +X55050000Y-47300000D02* +X55050000Y-42700000D01* +X51450000Y-42700000D02* +X55050000Y-42700000D01* +X51450000Y-47300000D02* +X55050000Y-47300000D01* +X51450000Y-47300000D02* +X51450000Y-42700000D01* +X55050000Y-36300000D02* +X56150000Y-36300000D01* +X55050000Y-33700000D02* +X56150000Y-33700000D01* +X56150000Y-36300000D02* +X56150000Y-33700000D01* +X55050000Y-37300000D02* +X55050000Y-32700000D01* +X51450000Y-32700000D02* +X55050000Y-32700000D01* +X51450000Y-37300000D02* +X55050000Y-37300000D01* +X51450000Y-37300000D02* +X51450000Y-32700000D01* +X38714286Y-30102381D02* +X38714286Y-29102381D01* +X38476191Y-29102381D01* +X38333333Y-29150000D01* +X38238095Y-29245238D01* +X38190476Y-29340476D01* +X38142857Y-29530952D01* +X38142857Y-29673810D01* +X38190476Y-29864286D01* +X38238095Y-29959524D01* +X38333333Y-30054762D01* +X38476191Y-30102381D01* +X38714286Y-30102381D01* +X37761905Y-30054762D02* +X37619048Y-30102381D01* +X37380952Y-30102381D01* +X37285714Y-30054762D01* +X37238095Y-30007143D01* +X37190476Y-29911905D01* +X37190476Y-29816667D01* +X37238095Y-29721429D01* +X37285714Y-29673810D01* +X37380952Y-29626190D01* +X37571429Y-29578571D01* +X37666667Y-29530952D01* +X37714286Y-29483333D01* +X37761905Y-29388095D01* +X37761905Y-29292857D01* +X37714286Y-29197619D01* +X37666667Y-29150000D01* +X37571429Y-29102381D01* +X37333333Y-29102381D01* +X37190476Y-29150000D01* +X36238095Y-30102381D02* +X36809524Y-30102381D01* +X36523810Y-30102381D02* +X36523810Y-29102381D01* +X36619048Y-29245238D01* +X36714286Y-29340476D01* +X36809524Y-29388095D01* +X42452381Y-34761905D02* +X41452381Y-34761905D01* +X41452381Y-35000000D01* +X41500000Y-35142858D01* +X41595238Y-35238096D01* +X41690476Y-35285715D01* +X41880952Y-35333334D01* +X42023810Y-35333334D01* +X42214286Y-35285715D01* +X42309524Y-35238096D01* +X42404762Y-35142858D01* +X42452381Y-35000000D01* +X42452381Y-34761905D01* +X41452381Y-35666667D02* +X41452381Y-36285715D01* +X41833333Y-35952381D01* +X41833333Y-36095239D01* +X41880952Y-36190477D01* +X41928571Y-36238096D01* +X42023810Y-36285715D01* +X42261905Y-36285715D01* +X42357143Y-36238096D01* +X42404762Y-36190477D01* +X42452381Y-36095239D01* +X42452381Y-35809524D01* +X42404762Y-35714286D01* +X42357143Y-35666667D01* +X40452381Y-35157143D02* +X39976190Y-34823809D01* +X40452381Y-34585714D02* +X39452381Y-34585714D01* +X39452381Y-34966667D01* +X39500000Y-35061905D01* +X39547619Y-35109524D01* +X39642857Y-35157143D01* +X39785714Y-35157143D01* +X39880952Y-35109524D01* +X39928571Y-35061905D01* +X39976190Y-34966667D01* +X39976190Y-34585714D01* +X40452381Y-36109524D02* +X40452381Y-35538095D01* +X40452381Y-35823809D02* +X39452381Y-35823809D01* +X39595238Y-35728571D01* +X39690476Y-35633333D01* +X39738095Y-35538095D01* +X39452381Y-36442857D02* +X39452381Y-37061905D01* +X39833333Y-36728571D01* +X39833333Y-36871429D01* +X39880952Y-36966667D01* +X39928571Y-37014286D01* +X40023810Y-37061905D01* +X40261905Y-37061905D01* +X40357143Y-37014286D01* +X40404762Y-36966667D01* +X40452381Y-36871429D01* +X40452381Y-36585714D01* +X40404762Y-36490476D01* +X40357143Y-36442857D01* +X26652381Y-44511905D02* +X25652381Y-44511905D01* +X25652381Y-44892858D01* +X25700000Y-44988096D01* +X25747619Y-45035715D01* +X25842857Y-45083334D01* +X25985714Y-45083334D01* +X26080952Y-45035715D01* +X26128571Y-44988096D01* +X26176190Y-44892858D01* +X26176190Y-44511905D01* +X26652381Y-46035715D02* +X26652381Y-45464286D01* +X26652381Y-45750000D02* +X25652381Y-45750000D01* +X25795238Y-45654762D01* +X25890476Y-45559524D01* +X25938095Y-45464286D01* +X50857143Y-21457143D02* +X50904762Y-21409524D01* +X50952381Y-21266667D01* +X50952381Y-21171429D01* +X50904762Y-21028571D01* +X50809524Y-20933333D01* +X50714286Y-20885714D01* +X50523810Y-20838095D01* +X50380952Y-20838095D01* +X50190476Y-20885714D01* +X50095238Y-20933333D01* +X50000000Y-21028571D01* +X49952381Y-21171429D01* +X49952381Y-21266667D01* +X50000000Y-21409524D01* +X50047619Y-21457143D01* +X50952381Y-22409524D02* +X50952381Y-21838095D01* +X50952381Y-22123809D02* +X49952381Y-22123809D01* +X50095238Y-22028571D01* +X50190476Y-21933333D01* +X50238095Y-21838095D01* +X49952381Y-23266667D02* +X49952381Y-23076190D01* +X50000000Y-22980952D01* +X50047619Y-22933333D01* +X50190476Y-22838095D01* +X50380952Y-22790476D01* +X50761905Y-22790476D01* +X50857143Y-22838095D01* +X50904762Y-22885714D01* +X50952381Y-22980952D01* +X50952381Y-23171429D01* +X50904762Y-23266667D01* +X50857143Y-23314286D01* +X50761905Y-23361905D01* +X50523810Y-23361905D01* +X50428571Y-23314286D01* +X50380952Y-23266667D01* +X50333333Y-23171429D01* +X50333333Y-22980952D01* +X50380952Y-22885714D01* +X50428571Y-22838095D01* +X50523810Y-22790476D01* +X49142857Y-44857143D02* +X49190476Y-44904762D01* +X49333333Y-44952381D01* +X49428571Y-44952381D01* +X49571429Y-44904762D01* +X49666667Y-44809524D01* +X49714286Y-44714286D01* +X49761905Y-44523810D01* +X49761905Y-44380952D01* +X49714286Y-44190476D01* +X49666667Y-44095238D01* +X49571429Y-44000000D01* +X49428571Y-43952381D01* +X49333333Y-43952381D01* +X49190476Y-44000000D01* +X49142857Y-44047619D01* +X48190476Y-44952381D02* +X48761905Y-44952381D01* +X48476191Y-44952381D02* +X48476191Y-43952381D01* +X48571429Y-44095238D01* +X48666667Y-44190476D01* +X48761905Y-44238095D01* +X47857143Y-43952381D02* +X47190476Y-43952381D01* +X47619048Y-44952381D01* +X46342857Y-35257143D02* +X46390476Y-35304762D01* +X46533333Y-35352381D01* +X46628571Y-35352381D01* +X46771429Y-35304762D01* +X46866667Y-35209524D01* +X46914286Y-35114286D01* +X46961905Y-34923810D01* +X46961905Y-34780952D01* +X46914286Y-34590476D01* +X46866667Y-34495238D01* +X46771429Y-34400000D01* +X46628571Y-34352381D01* +X46533333Y-34352381D01* +X46390476Y-34400000D01* +X46342857Y-34447619D01* +X45390476Y-35352381D02* +X45961905Y-35352381D01* +X45676191Y-35352381D02* +X45676191Y-34352381D01* +X45771429Y-34495238D01* +X45866667Y-34590476D01* +X45961905Y-34638095D01* +X44819048Y-34780952D02* +X44914286Y-34733333D01* +X44961905Y-34685714D01* +X45009524Y-34590476D01* +X45009524Y-34542857D01* +X44961905Y-34447619D01* +X44914286Y-34400000D01* +X44819048Y-34352381D01* +X44628571Y-34352381D01* +X44533333Y-34400000D01* +X44485714Y-34447619D01* +X44438095Y-34542857D01* +X44438095Y-34590476D01* +X44485714Y-34685714D01* +X44533333Y-34733333D01* +X44628571Y-34780952D01* +X44819048Y-34780952D01* +X44914286Y-34828571D01* +X44961905Y-34876190D01* +X45009524Y-34971429D01* +X45009524Y-35161905D01* +X44961905Y-35257143D01* +X44914286Y-35304762D01* +X44819048Y-35352381D01* +X44628571Y-35352381D01* +X44533333Y-35304762D01* +X44485714Y-35257143D01* +X44438095Y-35161905D01* +X44438095Y-34971429D01* +X44485714Y-34876190D01* +X44533333Y-34828571D01* +X44628571Y-34780952D01* +X44642857Y-30957143D02* +X44690476Y-31004762D01* +X44833333Y-31052381D01* +X44928571Y-31052381D01* +X45071429Y-31004762D01* +X45166667Y-30909524D01* +X45214286Y-30814286D01* +X45261905Y-30623810D01* +X45261905Y-30480952D01* +X45214286Y-30290476D01* +X45166667Y-30195238D01* +X45071429Y-30100000D01* +X44928571Y-30052381D01* +X44833333Y-30052381D01* +X44690476Y-30100000D01* +X44642857Y-30147619D01* +X43690476Y-31052381D02* +X44261905Y-31052381D01* +X43976191Y-31052381D02* +X43976191Y-30052381D01* +X44071429Y-30195238D01* +X44166667Y-30290476D01* +X44261905Y-30338095D01* +X43214286Y-31052381D02* +X43023810Y-31052381D01* +X42928571Y-31004762D01* +X42880952Y-30957143D01* +X42785714Y-30814286D01* +X42738095Y-30623810D01* +X42738095Y-30242857D01* +X42785714Y-30147619D01* +X42833333Y-30100000D01* +X42928571Y-30052381D01* +X43119048Y-30052381D01* +X43214286Y-30100000D01* +X43261905Y-30147619D01* +X43309524Y-30242857D01* +X43309524Y-30480952D01* +X43261905Y-30576190D01* +X43214286Y-30623810D01* +X43119048Y-30671429D01* +X42928571Y-30671429D01* +X42833333Y-30623810D01* +X42785714Y-30576190D01* +X42738095Y-30480952D01* +X30557143Y-35157143D02* +X30604762Y-35109524D01* +X30652381Y-34966667D01* +X30652381Y-34871429D01* +X30604762Y-34728571D01* +X30509524Y-34633333D01* +X30414286Y-34585714D01* +X30223810Y-34538095D01* +X30080952Y-34538095D01* +X29890476Y-34585714D01* +X29795238Y-34633333D01* +X29700000Y-34728571D01* +X29652381Y-34871429D01* +X29652381Y-34966667D01* +X29700000Y-35109524D01* +X29747619Y-35157143D01* +X29747619Y-35538095D02* +X29700000Y-35585714D01* +X29652381Y-35680952D01* +X29652381Y-35919048D01* +X29700000Y-36014286D01* +X29747619Y-36061905D01* +X29842857Y-36109524D01* +X29938095Y-36109524D01* +X30080952Y-36061905D01* +X30652381Y-35490476D01* +X30652381Y-36109524D01* +X29652381Y-36728571D02* +X29652381Y-36823810D01* +X29700000Y-36919048D01* +X29747619Y-36966667D01* +X29842857Y-37014286D01* +X30033333Y-37061905D01* +X30271429Y-37061905D01* +X30461905Y-37014286D01* +X30557143Y-36966667D01* +X30604762Y-36919048D01* +X30652381Y-36823810D01* +X30652381Y-36728571D01* +X30604762Y-36633333D01* +X30557143Y-36585714D01* +X30461905Y-36538095D01* +X30271429Y-36490476D01* +X30033333Y-36490476D01* +X29842857Y-36538095D01* +X29747619Y-36585714D01* +X29700000Y-36633333D01* +X29652381Y-36728571D01* +X27157143Y-35157143D02* +X27204762Y-35109524D01* +X27252381Y-34966667D01* +X27252381Y-34871429D01* +X27204762Y-34728571D01* +X27109524Y-34633333D01* +X27014286Y-34585714D01* +X26823810Y-34538095D01* +X26680952Y-34538095D01* +X26490476Y-34585714D01* +X26395238Y-34633333D01* +X26300000Y-34728571D01* +X26252381Y-34871429D01* +X26252381Y-34966667D01* +X26300000Y-35109524D01* +X26347619Y-35157143D01* +X26347619Y-35538095D02* +X26300000Y-35585714D01* +X26252381Y-35680952D01* +X26252381Y-35919048D01* +X26300000Y-36014286D01* +X26347619Y-36061905D01* +X26442857Y-36109524D01* +X26538095Y-36109524D01* +X26680952Y-36061905D01* +X27252381Y-35490476D01* +X27252381Y-36109524D01* +X27252381Y-37061905D02* +X27252381Y-36490476D01* +X27252381Y-36776190D02* +X26252381Y-36776190D01* +X26395238Y-36680952D01* +X26490476Y-36585714D01* +X26538095Y-36490476D01* +X49842857Y-35257143D02* +X49890476Y-35304762D01* +X50033333Y-35352381D01* +X50128571Y-35352381D01* +X50271429Y-35304762D01* +X50366667Y-35209524D01* +X50414286Y-35114286D01* +X50461905Y-34923810D01* +X50461905Y-34780952D01* +X50414286Y-34590476D01* +X50366667Y-34495238D01* +X50271429Y-34400000D01* +X50128571Y-34352381D01* +X50033333Y-34352381D01* +X49890476Y-34400000D01* +X49842857Y-34447619D01* +X49461905Y-34447619D02* +X49414286Y-34400000D01* +X49319048Y-34352381D01* +X49080952Y-34352381D01* +X48985714Y-34400000D01* +X48938095Y-34447619D01* +X48890476Y-34542857D01* +X48890476Y-34638095D01* +X48938095Y-34780952D01* +X49509524Y-35352381D01* +X48890476Y-35352381D01* +X48509524Y-34447619D02* +X48461905Y-34400000D01* +X48366667Y-34352381D01* +X48128571Y-34352381D01* +X48033333Y-34400000D01* +X47985714Y-34447619D01* +X47938095Y-34542857D01* +X47938095Y-34638095D01* +X47985714Y-34780952D01* +X48557143Y-35352381D01* +X47938095Y-35352381D01* +X48142857Y-31057143D02* +X48190476Y-31104762D01* +X48333333Y-31152381D01* +X48428571Y-31152381D01* +X48571429Y-31104762D01* +X48666667Y-31009524D01* +X48714286Y-30914286D01* +X48761905Y-30723810D01* +X48761905Y-30580952D01* +X48714286Y-30390476D01* +X48666667Y-30295238D01* +X48571429Y-30200000D01* +X48428571Y-30152381D01* +X48333333Y-30152381D01* +X48190476Y-30200000D01* +X48142857Y-30247619D01* +X47761905Y-30247619D02* +X47714286Y-30200000D01* +X47619048Y-30152381D01* +X47380952Y-30152381D01* +X47285714Y-30200000D01* +X47238095Y-30247619D01* +X47190476Y-30342857D01* +X47190476Y-30438095D01* +X47238095Y-30580952D01* +X47809524Y-31152381D01* +X47190476Y-31152381D01* +X46857143Y-30152381D02* +X46238095Y-30152381D01* +X46571429Y-30533333D01* +X46428571Y-30533333D01* +X46333333Y-30580952D01* +X46285714Y-30628571D01* +X46238095Y-30723810D01* +X46238095Y-30961905D01* +X46285714Y-31057143D01* +X46333333Y-31104762D01* +X46428571Y-31152381D01* +X46714286Y-31152381D01* +X46809524Y-31104762D01* +X46857143Y-31057143D01* +X28857143Y-35157143D02* +X28904762Y-35109524D01* +X28952381Y-34966667D01* +X28952381Y-34871429D01* +X28904762Y-34728571D01* +X28809524Y-34633333D01* +X28714286Y-34585714D01* +X28523810Y-34538095D01* +X28380952Y-34538095D01* +X28190476Y-34585714D01* +X28095238Y-34633333D01* +X28000000Y-34728571D01* +X27952381Y-34871429D01* +X27952381Y-34966667D01* +X28000000Y-35109524D01* +X28047619Y-35157143D01* +X28047619Y-35538095D02* +X28000000Y-35585714D01* +X27952381Y-35680952D01* +X27952381Y-35919048D01* +X28000000Y-36014286D01* +X28047619Y-36061905D01* +X28142857Y-36109524D01* +X28238095Y-36109524D01* +X28380952Y-36061905D01* +X28952381Y-35490476D01* +X28952381Y-36109524D01* +X28285714Y-36966667D02* +X28952381Y-36966667D01* +X27904762Y-36728571D02* +X28619048Y-36490476D01* +X28619048Y-37109524D01* +X51438095Y-30452381D02* +X51438095Y-29452381D01* +X51200000Y-29452381D01* +X51057142Y-29500000D01* +X50961904Y-29595238D01* +X50914285Y-29690476D01* +X50866666Y-29880952D01* +X50866666Y-30023810D01* +X50914285Y-30214286D01* +X50961904Y-30309524D01* +X51057142Y-30404762D01* +X51200000Y-30452381D01* +X51438095Y-30452381D01* +X49914285Y-30452381D02* +X50485714Y-30452381D01* +X50200000Y-30452381D02* +X50200000Y-29452381D01* +X50295238Y-29595238D01* +X50390476Y-29690476D01* +X50485714Y-29738095D01* +X51438095Y-40452381D02* +X51438095Y-39452381D01* +X51200000Y-39452381D01* +X51057142Y-39500000D01* +X50961904Y-39595238D01* +X50914285Y-39690476D01* +X50866666Y-39880952D01* +X50866666Y-40023810D01* +X50914285Y-40214286D01* +X50961904Y-40309524D01* +X51057142Y-40404762D01* +X51200000Y-40452381D01* +X51438095Y-40452381D01* +X50485714Y-39547619D02* +X50438095Y-39500000D01* +X50342857Y-39452381D01* +X50104761Y-39452381D01* +X50009523Y-39500000D01* +X49961904Y-39547619D01* +X49914285Y-39642857D01* +X49914285Y-39738095D01* +X49961904Y-39880952D01* +X50533333Y-40452381D01* +X49914285Y-40452381D01* +X48995238Y-38547619D02* +X49090476Y-38500000D01* +X49185714Y-38404762D01* +X49328571Y-38261905D01* +X49423810Y-38214286D01* +X49519048Y-38214286D01* +X49471429Y-38452381D02* +X49566667Y-38404762D01* +X49661905Y-38309524D01* +X49709524Y-38119048D01* +X49709524Y-37785714D01* +X49661905Y-37595238D01* +X49566667Y-37500000D01* +X49471429Y-37452381D01* +X49280952Y-37452381D01* +X49185714Y-37500000D01* +X49090476Y-37595238D01* +X49042857Y-37785714D01* +X49042857Y-38119048D01* +X49090476Y-38309524D01* +X49185714Y-38404762D01* +X49280952Y-38452381D01* +X49471429Y-38452381D01* +X48090476Y-38452381D02* +X48661905Y-38452381D01* +X48376191Y-38452381D02* +X48376191Y-37452381D01* +X48471429Y-37595238D01* +X48566667Y-37690476D01* +X48661905Y-37738095D01* +X42252381Y-37833334D02* +X41776190Y-37500000D01* +X42252381Y-37261905D02* +X41252381Y-37261905D01* +X41252381Y-37642858D01* +X41300000Y-37738096D01* +X41347619Y-37785715D01* +X41442857Y-37833334D01* +X41585714Y-37833334D01* +X41680952Y-37785715D01* +X41728571Y-37738096D01* +X41776190Y-37642858D01* +X41776190Y-37261905D01* +X41252381Y-38166667D02* +X41252381Y-38785715D01* +X41633333Y-38452381D01* +X41633333Y-38595239D01* +X41680952Y-38690477D01* +X41728571Y-38738096D01* +X41823810Y-38785715D01* +X42061905Y-38785715D01* +X42157143Y-38738096D01* +X42204762Y-38690477D01* +X42252381Y-38595239D01* +X42252381Y-38309524D01* +X42204762Y-38214286D01* +X42157143Y-38166667D01* +X34952381Y-35157143D02* +X34476190Y-34823809D01* +X34952381Y-34585714D02* +X33952381Y-34585714D01* +X33952381Y-34966667D01* +X34000000Y-35061905D01* +X34047619Y-35109524D01* +X34142857Y-35157143D01* +X34285714Y-35157143D01* +X34380952Y-35109524D01* +X34428571Y-35061905D01* +X34476190Y-34966667D01* +X34476190Y-34585714D01* +X34952381Y-36109524D02* +X34952381Y-35538095D01* +X34952381Y-35823809D02* +X33952381Y-35823809D01* +X34095238Y-35728571D01* +X34190476Y-35633333D01* +X34238095Y-35538095D01* +X33952381Y-36728571D02* +X33952381Y-36823810D01* +X34000000Y-36919048D01* +X34047619Y-36966667D01* +X34142857Y-37014286D01* +X34333333Y-37061905D01* +X34571429Y-37061905D01* +X34761905Y-37014286D01* +X34857143Y-36966667D01* +X34904762Y-36919048D01* +X34952381Y-36823810D01* +X34952381Y-36728571D01* +X34904762Y-36633333D01* +X34857143Y-36585714D01* +X34761905Y-36538095D01* +X34571429Y-36490476D01* +X34333333Y-36490476D01* +X34142857Y-36538095D01* +X34047619Y-36585714D01* +X34000000Y-36633333D01* +X33952381Y-36728571D01* +X36752381Y-35157143D02* +X36276190Y-34823809D01* +X36752381Y-34585714D02* +X35752381Y-34585714D01* +X35752381Y-34966667D01* +X35800000Y-35061905D01* +X35847619Y-35109524D01* +X35942857Y-35157143D01* +X36085714Y-35157143D01* +X36180952Y-35109524D01* +X36228571Y-35061905D01* +X36276190Y-34966667D01* +X36276190Y-34585714D01* +X36752381Y-36109524D02* +X36752381Y-35538095D01* +X36752381Y-35823809D02* +X35752381Y-35823809D01* +X35895238Y-35728571D01* +X35990476Y-35633333D01* +X36038095Y-35538095D01* +X36752381Y-37061905D02* +X36752381Y-36490476D01* +X36752381Y-36776190D02* +X35752381Y-36776190D01* +X35895238Y-36680952D01* +X35990476Y-36585714D01* +X36038095Y-36490476D01* +X49452381Y-41357143D02* +X48976190Y-41023809D01* +X49452381Y-40785714D02* +X48452381Y-40785714D01* +X48452381Y-41166667D01* +X48500000Y-41261905D01* +X48547619Y-41309524D01* +X48642857Y-41357143D01* +X48785714Y-41357143D01* +X48880952Y-41309524D01* +X48928571Y-41261905D01* +X48976190Y-41166667D01* +X48976190Y-40785714D01* +X49452381Y-42309524D02* +X49452381Y-41738095D01* +X49452381Y-42023809D02* +X48452381Y-42023809D01* +X48595238Y-41928571D01* +X48690476Y-41833333D01* +X48738095Y-41738095D01* +X48547619Y-42690476D02* +X48500000Y-42738095D01* +X48452381Y-42833333D01* +X48452381Y-43071429D01* +X48500000Y-43166667D01* +X48547619Y-43214286D01* +X48642857Y-43261905D01* +X48738095Y-43261905D01* +X48880952Y-43214286D01* +X49452381Y-42642857D01* +X49452381Y-43261905D01* +X32452381Y-35157143D02* +X31976190Y-34823809D01* +X32452381Y-34585714D02* +X31452381Y-34585714D01* +X31452381Y-34966667D01* +X31500000Y-35061905D01* +X31547619Y-35109524D01* +X31642857Y-35157143D01* +X31785714Y-35157143D01* +X31880952Y-35109524D01* +X31928571Y-35061905D01* +X31976190Y-34966667D01* +X31976190Y-34585714D01* +X32452381Y-36109524D02* +X32452381Y-35538095D01* +X32452381Y-35823809D02* +X31452381Y-35823809D01* +X31595238Y-35728571D01* +X31690476Y-35633333D01* +X31738095Y-35538095D01* +X31785714Y-36966667D02* +X32452381Y-36966667D01* +X31404762Y-36728571D02* +X32119048Y-36490476D01* +X32119048Y-37109524D01* +X53654762Y-23666667D02* +X53702381Y-23809524D01* +X53702381Y-24047620D01* +X53654762Y-24142858D01* +X53607143Y-24190477D01* +X53511905Y-24238096D01* +X53416667Y-24238096D01* +X53321429Y-24190477D01* +X53273810Y-24142858D01* +X53226190Y-24047620D01* +X53178571Y-23857143D01* +X53130952Y-23761905D01* +X53083333Y-23714286D01* +X52988095Y-23666667D01* +X52892857Y-23666667D01* +X52797619Y-23714286D01* +X52750000Y-23761905D01* +X52702381Y-23857143D01* +X52702381Y-24095239D01* +X52750000Y-24238096D01* +X52702381Y-24571429D02* +X53702381Y-24809524D01* +X52988095Y-25000001D01* +X53702381Y-25190477D01* +X52702381Y-25428572D01* +X53702381Y-26333334D02* +X53702381Y-25761905D01* +X53702381Y-26047619D02* +X52702381Y-26047619D01* +X52845238Y-25952381D01* +X52940476Y-25857143D01* +X52988095Y-25761905D01* +X53654762Y-43666667D02* +X53702381Y-43809524D01* +X53702381Y-44047620D01* +X53654762Y-44142858D01* +X53607143Y-44190477D01* +X53511905Y-44238096D01* +X53416667Y-44238096D01* +X53321429Y-44190477D01* +X53273810Y-44142858D01* +X53226190Y-44047620D01* +X53178571Y-43857143D01* +X53130952Y-43761905D01* +X53083333Y-43714286D01* +X52988095Y-43666667D01* +X52892857Y-43666667D01* +X52797619Y-43714286D01* +X52750000Y-43761905D01* +X52702381Y-43857143D01* +X52702381Y-44095239D01* +X52750000Y-44238096D01* +X52702381Y-44571429D02* +X53702381Y-44809524D01* +X52988095Y-45000001D01* +X53702381Y-45190477D01* +X52702381Y-45428572D01* +X52797619Y-45761905D02* +X52750000Y-45809524D01* +X52702381Y-45904762D01* +X52702381Y-46142858D01* +X52750000Y-46238096D01* +X52797619Y-46285715D01* +X52892857Y-46333334D01* +X52988095Y-46333334D01* +X53130952Y-46285715D01* +X53702381Y-45714286D01* +X53702381Y-46333334D01* +X53654762Y-33666667D02* +X53702381Y-33809524D01* +X53702381Y-34047620D01* +X53654762Y-34142858D01* +X53607143Y-34190477D01* +X53511905Y-34238096D01* +X53416667Y-34238096D01* +X53321429Y-34190477D01* +X53273810Y-34142858D01* +X53226190Y-34047620D01* +X53178571Y-33857143D01* +X53130952Y-33761905D01* +X53083333Y-33714286D01* +X52988095Y-33666667D01* +X52892857Y-33666667D01* +X52797619Y-33714286D01* +X52750000Y-33761905D01* +X52702381Y-33857143D01* +X52702381Y-34095239D01* +X52750000Y-34238096D01* +X52702381Y-34571429D02* +X53702381Y-34809524D01* +X52988095Y-35000001D01* +X53702381Y-35190477D01* +X52702381Y-35428572D01* +X52702381Y-35714286D02* +X52702381Y-36333334D01* +X53083333Y-36000000D01* +X53083333Y-36142858D01* +X53130952Y-36238096D01* +X53178571Y-36285715D01* +X53273810Y-36333334D01* +X53511905Y-36333334D01* +X53607143Y-36285715D01* +X53654762Y-36238096D01* +X53702381Y-36142858D01* +X53702381Y-35857143D01* +X53654762Y-35761905D01* +X53607143Y-35714286D01* +M02* diff --git a/board/v1/gerber/handgelenk.gbs b/board/v1/gerber/handgelenk.gbs new file mode 100644 index 0000000..1eb5528 --- /dev/null +++ b/board/v1/gerber/handgelenk.gbs @@ -0,0 +1,132 @@ +G04 #@! TF.FileFunction,Soldermask,Bot* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11R,0.800000X3.400000*% +%ADD12R,2.432000X2.432000*% +%ADD13O,2.432000X2.432000*% +%ADD14R,0.850000X0.990000*% +%ADD15R,1.300000X0.900000*% +%ADD16R,1.750000X0.800000*% +%ADD17O,1.350000X1.650000*% +%ADD18O,1.950000X1.400000*% +%ADD19R,1.150000X1.200000*% +%ADD20R,0.990000X0.850000*% +%ADD21R,1.200100X1.200100*% +%ADD22R,1.400000X1.600000*% +G04 APERTURE END LIST* +D10* +D11* +X47650000Y-27250000D03* +X46950000Y-27250000D03* +X46250000Y-27250000D03* +X45550000Y-27250000D03* +X44850000Y-27250000D03* +X43450000Y-27250000D03* +X42750000Y-27250000D03* +X42050000Y-27250000D03* +X41350000Y-27250000D03* +X40650000Y-27250000D03* +X39950000Y-27250000D03* +X39250000Y-27250000D03* +X38550000Y-27250000D03* +X37850000Y-27250000D03* +X37150000Y-27250000D03* +X36450000Y-27250000D03* +X35750000Y-27250000D03* +X35050000Y-27250000D03* +X34350000Y-27250000D03* +X33650000Y-27250000D03* +X32950000Y-27250000D03* +X32250000Y-27250000D03* +X31550000Y-27250000D03* +X30850000Y-27250000D03* +X30150000Y-27250000D03* +X29450000Y-27250000D03* +X28750000Y-27250000D03* +X28050000Y-27250000D03* +X27350000Y-27250000D03* +X44150000Y-27250000D03* +D12* +X43726696Y-41500000D03* +D13* +X46266696Y-41500000D03* +D14* +X42000000Y-33805000D03* +X42000000Y-31695000D03* +D15* +X40000000Y-32000000D03* +X40000000Y-33500000D03* +D16* +X24312540Y-46550900D03* +X24312540Y-45900900D03* +X24312540Y-45250900D03* +X24312540Y-44600900D03* +X24312540Y-43950900D03* +D17* +X24312540Y-47750900D03* +X24312540Y-42750900D03* +D18* +X21612540Y-48750900D03* +X21612540Y-41750900D03* +D12* +X35500000Y-47750000D03* +D13* +X35500000Y-45210000D03* +D19* +X50500000Y-24250000D03* +X50500000Y-25750000D03* +X50500000Y-45750000D03* +X50500000Y-44250000D03* +X45750000Y-32000000D03* +X45750000Y-33500000D03* +X44000000Y-32000000D03* +X44000000Y-33500000D03* +X30250000Y-32000000D03* +X30250000Y-33500000D03* +X26750000Y-32000000D03* +X26750000Y-33500000D03* +X49250000Y-33500000D03* +X49250000Y-32000000D03* +X47500000Y-33500000D03* +X47500000Y-32000000D03* +X28500000Y-32000000D03* +X28500000Y-33500000D03* +D20* +X52195000Y-30000000D03* +X54305000Y-30000000D03* +X52195000Y-40000000D03* +X54305000Y-40000000D03* +D21* +X45276696Y-36999240D03* +X47176696Y-36999240D03* +X46226696Y-38998220D03* +D15* +X43226696Y-37250000D03* +X43226696Y-38750000D03* +X34500000Y-33500000D03* +X34500000Y-32000000D03* +X36250000Y-33500000D03* +X36250000Y-32000000D03* +X50500000Y-41250000D03* +X50500000Y-42750000D03* +X32000000Y-32000000D03* +X32000000Y-33500000D03* +D22* +X54100000Y-27800000D03* +X54100000Y-22200000D03* +X52400000Y-27800000D03* +X52400000Y-22200000D03* +X54100000Y-47800000D03* +X54100000Y-42200000D03* +X52400000Y-47800000D03* +X52400000Y-42200000D03* +X54100000Y-37800000D03* +X54100000Y-32200000D03* +X52400000Y-37800000D03* +X52400000Y-32200000D03* +M02* diff --git a/board/v1/gerber/handgelenk.gml b/board/v1/gerber/handgelenk.gml new file mode 100644 index 0000000..2be2256 --- /dev/null +++ b/board/v1/gerber/handgelenk.gml @@ -0,0 +1,53 @@ +G04 #@! TF.FileFunction,Profile,NP* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11C,0.150000*% +G04 APERTURE END LIST* +D10* +D11* +X43900000Y-19900000D02* +X52000000Y-19900000D01* +X43700000Y-20200000D02* +X43900000Y-19900000D01* +X31300000Y-20200000D02* +X43700000Y-20200000D01* +X31300000Y-20200000D02* +X31100000Y-19900000D01* +X31100000Y-19900000D02* +X23000000Y-19900000D01* +X52000000Y-50300000D02* +X23000000Y-50300000D01* +X51100000Y-52100000D02* +X23900000Y-52100000D01* +X23900000Y-52100000D02* +X23000000Y-50300000D01* +X52000000Y-50300000D02* +X51100000Y-52100000D01* +X55000000Y-50300000D02* +X53000000Y-54300000D01* +X22000000Y-54300000D02* +X20000000Y-50300000D01* +X53000000Y-54300000D02* +X22000000Y-54300000D01* +X23900000Y-18100000D02* +X51100000Y-18100000D01* +X51100000Y-18100000D02* +X52000000Y-19900000D01* +X23000000Y-19900000D02* +X23900000Y-18100000D01* +X22000000Y-15900000D02* +X53000000Y-15900000D01* +X53000000Y-15900000D02* +X55000000Y-19900000D01* +X20000000Y-19900000D02* +X22000000Y-15900000D01* +X55000000Y-19900000D02* +X55000000Y-50300000D01* +X20000000Y-19900000D02* +X20000000Y-50300000D01* +M02* diff --git a/board/v1/gerber/handgelenk.gtl b/board/v1/gerber/handgelenk.gtl new file mode 100644 index 0000000..6d5e5dc --- /dev/null +++ b/board/v1/gerber/handgelenk.gtl @@ -0,0 +1,5213 @@ +G04 #@! TF.FileFunction,Copper,L1,Top,Signal* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11R,0.750000X0.800000*% +%ADD12R,0.700000X0.250000*% +%ADD13R,0.250000X0.700000*% +%ADD14R,1.725000X1.725000*% +%ADD15R,2.032000X2.032000*% +%ADD16O,2.032000X2.032000*% +%ADD17R,0.600000X0.900000*% +%ADD18R,0.800000X0.750000*% +%ADD19R,0.500000X1.300000*% +%ADD20R,2.000000X1.400000*% +%ADD21R,1.600000X1.000000*% +%ADD22R,0.600000X0.500000*% +%ADD23R,0.500000X0.600000*% +%ADD24R,1.000000X1.250000*% +%ADD25O,0.950000X1.250000*% +%ADD26O,1.550000X1.000000*% +%ADD27R,0.900000X0.500000*% +%ADD28R,0.500000X0.900000*% +%ADD29R,1.060000X0.650000*% +%ADD30R,0.550000X0.200000*% +%ADD31R,0.200000X0.550000*% +%ADD32R,0.875000X0.800000*% +%ADD33R,1.100000X0.900000*% +%ADD34C,0.600000*% +%ADD35C,2.500000*% +%ADD36C,0.600000*% +%ADD37C,0.300000*% +%ADD38C,0.350000*% +%ADD39C,0.250000*% +%ADD40C,0.200000*% +%ADD41C,0.450000*% +%ADD42C,0.254000*% +G04 APERTURE END LIST* +D10* +D11* +X24250000Y-45750000D03* +X24250000Y-44250000D03* +D12* +X27100000Y-25250000D03* +X27100000Y-25750000D03* +X27100000Y-26250000D03* +X27100000Y-26750000D03* +X27100000Y-27250000D03* +X27100000Y-27750000D03* +X27100000Y-28250000D03* +X27100000Y-28750000D03* +D13* +X27750000Y-29400000D03* +X28250000Y-29400000D03* +X28750000Y-29400000D03* +X29250000Y-29400000D03* +X29750000Y-29400000D03* +X30250000Y-29400000D03* +X30750000Y-29400000D03* +X31250000Y-29400000D03* +D12* +X31900000Y-28750000D03* +X31900000Y-28250000D03* +X31900000Y-27750000D03* +X31900000Y-27250000D03* +X31900000Y-26750000D03* +X31900000Y-26250000D03* +X31900000Y-25750000D03* +X31900000Y-25250000D03* +D13* +X31250000Y-24600000D03* +X30750000Y-24600000D03* +X30250000Y-24600000D03* +X29750000Y-24600000D03* +X29250000Y-24600000D03* +X28750000Y-24600000D03* +X28250000Y-24600000D03* +X27750000Y-24600000D03* +D14* +X30362500Y-27862500D03* +X30362500Y-26137500D03* +X28637500Y-27862500D03* +X28637500Y-26137500D03* +D15* +X43726696Y-41500000D03* +D16* +X46266696Y-41500000D03* +D17* +X49300000Y-34050000D03* +X48300000Y-34050000D03* +X47300000Y-34050000D03* +X46300000Y-34050000D03* +X45300000Y-34050000D03* +X45300000Y-37150000D03* +X46300000Y-37150000D03* +X47300000Y-37150000D03* +X48300000Y-37150000D03* +X49300000Y-37150000D03* +D18* +X23800000Y-39900000D03* +X22300000Y-39900000D03* +D19* +X37295000Y-30321000D03* +X38565000Y-30321000D03* +X39835000Y-30321000D03* +X41105000Y-30321000D03* +X41105000Y-24479000D03* +X39835000Y-24479000D03* +X38565000Y-24479000D03* +X37295000Y-24479000D03* +D20* +X21500000Y-30750000D03* +X21500000Y-21250000D03* +D18* +X28500000Y-31000000D03* +X30000000Y-31000000D03* +D11* +X26750000Y-47250000D03* +X26750000Y-48750000D03* +X38000000Y-47250000D03* +X38000000Y-48750000D03* +D21* +X45750000Y-45750000D03* +X45750000Y-48750000D03* +D11* +X43750000Y-47250000D03* +X43750000Y-48750000D03* +D22* +X24550000Y-26000000D03* +X23450000Y-26000000D03* +D23* +X28250000Y-22300000D03* +X28250000Y-21200000D03* +D22* +X32700000Y-21000000D03* +X33800000Y-21000000D03* +D18* +X25250000Y-21500000D03* +X23750000Y-21500000D03* +D11* +X50520702Y-23848198D03* +X50520702Y-22348198D03* +X52270702Y-23848198D03* +X52270702Y-22348198D03* +D18* +X48020702Y-26348198D03* +X46520702Y-26348198D03* +D11* +X51300000Y-34850000D03* +X51300000Y-36350000D03* +D24* +X26750000Y-45500000D03* +X28750000Y-45500000D03* +D25* +X24312540Y-47750900D03* +X24312540Y-42750900D03* +D26* +X21612540Y-48750900D03* +X21612540Y-41750900D03* +D15* +X35500000Y-47750000D03* +D16* +X35500000Y-45210000D03* +D27* +X24500000Y-27500000D03* +X24500000Y-29000000D03* +X26750000Y-22750000D03* +X26750000Y-21250000D03* +X28750000Y-47500000D03* +X28750000Y-49000000D03* +D28* +X25250000Y-23250000D03* +X23750000Y-23250000D03* +D27* +X34000000Y-25250000D03* +X34000000Y-26750000D03* +D28* +X38000000Y-45000000D03* +X39500000Y-45000000D03* +X41000000Y-45000000D03* +X42500000Y-45000000D03* +D27* +X53050000Y-34850000D03* +X53050000Y-36350000D03* +D13* +X31250000Y-38850000D03* +X30750000Y-38850000D03* +X30250000Y-38850000D03* +X29750000Y-38850000D03* +X29250000Y-38850000D03* +X28750000Y-38850000D03* +X28250000Y-38850000D03* +X27750000Y-38850000D03* +D12* +X27100000Y-39500000D03* +X27100000Y-40000000D03* +X27100000Y-40500000D03* +X27100000Y-41000000D03* +X27100000Y-41500000D03* +X27100000Y-42000000D03* +X27100000Y-42500000D03* +X27100000Y-43000000D03* +D13* +X27750000Y-43650000D03* +X28250000Y-43650000D03* +X28750000Y-43650000D03* +X29250000Y-43650000D03* +X29750000Y-43650000D03* +X30250000Y-43650000D03* +X30750000Y-43650000D03* +X31250000Y-43650000D03* +D12* +X31900000Y-43000000D03* +X31900000Y-42500000D03* +X31900000Y-42000000D03* +X31900000Y-41500000D03* +X31900000Y-41000000D03* +X31900000Y-40500000D03* +X31900000Y-40000000D03* +X31900000Y-39500000D03* +D14* +X28637500Y-42112500D03* +X30362500Y-42112500D03* +X28637500Y-40387500D03* +X30362500Y-40387500D03* +D29* +X32600000Y-48950000D03* +X32600000Y-48000000D03* +X32600000Y-47050000D03* +X30400000Y-47050000D03* +X30400000Y-48950000D03* +D30* +X46020702Y-22098198D03* +X46020702Y-22498198D03* +X46020702Y-22898198D03* +X46020702Y-23298198D03* +X46020702Y-23698198D03* +X46020702Y-24098198D03* +D31* +X46520702Y-24598198D03* +X46920702Y-24598198D03* +X47320702Y-24598198D03* +X47720702Y-24598198D03* +X48120702Y-24598198D03* +X48520702Y-24598198D03* +D30* +X49020702Y-24098198D03* +X49020702Y-23698198D03* +X49020702Y-23298198D03* +X49020702Y-22898198D03* +X49020702Y-22498198D03* +X49020702Y-22098198D03* +D31* +X48520702Y-21598198D03* +X48120702Y-21598198D03* +X47720702Y-21598198D03* +X47320702Y-21598198D03* +X46920702Y-21598198D03* +X46520702Y-21598198D03* +D32* +X47955702Y-23498198D03* +X47955702Y-22698198D03* +X47085702Y-23498198D03* +X47085702Y-22698198D03* +D29* +X39900000Y-47050000D03* +X39900000Y-48000000D03* +X39900000Y-48950000D03* +X42100000Y-48950000D03* +X42100000Y-47050000D03* +D33* +X29650000Y-22400000D03* +X29650000Y-21100000D03* +X31350000Y-22400000D03* +X31350000Y-21100000D03* +D34* +X29900000Y-35000000D03* +X26250000Y-24520075D03* +X44700000Y-22300000D03* +X37300000Y-23200000D03* +X45773137Y-24850633D03* +X44300000Y-30700000D03* +X32200000Y-29600000D03* +X26000000Y-30520010D03* +X28998135Y-23257462D03* +X26250000Y-26500000D03* +X50500000Y-20900000D03* +D35* +X48052703Y-46736498D03* +D34* +X48600000Y-43400000D03* +X31190415Y-33500000D03* +X31200000Y-34300000D03* +X30362500Y-42112500D03* +X30362500Y-40387500D03* +X31000000Y-23257453D03* +X26800000Y-22000000D03* +X34662300Y-21520576D03* +X47085702Y-23498198D03* +X47900000Y-23500000D03* +X28600000Y-42200000D03* +X28600000Y-40400000D03* +X38550886Y-33350886D03* +X49400000Y-44200000D03* +X30850000Y-25571545D03* +X28050000Y-25534450D03* +X25500000Y-46500000D03* +X41000000Y-49000000D03* +X48500000Y-25300000D03* +X26900000Y-24000000D03* +X36400000Y-35000000D03* +X26179990Y-35500000D03* +X23229990Y-24857438D03* +X46300000Y-38100000D03* +X26000000Y-42250000D03* +X26000000Y-41250000D03* +X29300000Y-34300000D03* +X34200000Y-40300000D03* +X26026518Y-28879990D03* +X23750000Y-24250000D03* +X39500000Y-43800000D03* +X33700000Y-37180031D03* +X43800000Y-35100000D03* +X38113097Y-33922501D03* +X45300000Y-35000000D03* +X33442665Y-32700000D03* +X35167799Y-36867799D03* +X34000000Y-34500000D03* +X33679990Y-40809118D03* +X30800000Y-37900000D03* +X38873521Y-36140020D03* +X37092994Y-38207006D03* +X37086558Y-34289702D03* +X35900000Y-22300000D03* +X35890882Y-35520010D03* +D36* +X48200000Y-48400000D02* +X48700000Y-48400000D01* +X48700000Y-48400000D02* +X48800000Y-48300000D01* +D37* +X23450000Y-26000000D02* +X23400000Y-26000000D01* +X23400000Y-26000000D02* +X21500000Y-27900000D01* +X21500000Y-27900000D02* +X21500000Y-29750000D01* +X21500000Y-29750000D02* +X21500000Y-30750000D01* +D38* +X32200000Y-29600000D02* +X32624264Y-29600000D01* +X32624264Y-29600000D02* +X32900000Y-29324264D01* +X32900000Y-29324264D02* +X32900000Y-28993982D01* +X32900000Y-28993982D02* +X32656018Y-28750000D01* +X32656018Y-28750000D02* +X31900000Y-28750000D01* +X46043617Y-35915011D02* +X46870010Y-35088618D01* +X46870010Y-35088618D02* +X47100000Y-35088618D01* +D36* +X48936381Y-35088618D02* +X47100000Y-35088618D01* +D38* +X48936381Y-35088618D02* +X48936381Y-35213619D01* +D36* +X49300000Y-34050000D02* +X49300000Y-34724999D01* +X49300000Y-34724999D02* +X48936381Y-35088618D01* +X51300000Y-34850000D02* +X50100000Y-34850000D01* +X50100000Y-34850000D02* +X49300000Y-34050000D01* +D38* +X51300000Y-34850000D02* +X50575000Y-34850000D01* +X43726696Y-37424302D02* +X44414425Y-36736573D01* +X44414425Y-36736573D02* +X45076009Y-36074989D01* +X46043617Y-35915011D02* +X45235987Y-35915011D01* +X45235987Y-35915011D02* +X44414425Y-36736573D01* +D36* +X28500000Y-31000000D02* +X28500000Y-35000000D01* +X28500000Y-35000000D02* +X28934398Y-35000000D01* +X29455735Y-35020001D02* +X29475736Y-35000000D01* +X28934398Y-35000000D02* +X28954399Y-35020001D01* +X28954399Y-35020001D02* +X29455735Y-35020001D01* +X29475736Y-35000000D02* +X29900000Y-35000000D01* +X42100000Y-47050000D02* +X43550000Y-47050000D01* +X43550000Y-47050000D02* +X43750000Y-47250000D01* +X45750000Y-45750000D02* +X45250000Y-45750000D01* +X45250000Y-45750000D02* +X43750000Y-47250000D01* +X43726696Y-41500000D02* +X43726696Y-43726696D01* +X43726696Y-43726696D02* +X45750000Y-45750000D01* +X28500000Y-31000000D02* +X26479990Y-31000000D01* +X26479990Y-31000000D02* +X26000000Y-30520010D01* +D38* +X26250000Y-25250000D02* +X26250000Y-24520075D01* +X27100000Y-25250000D02* +X26250000Y-25250000D01* +X43726696Y-41500000D02* +X43726696Y-37424302D01* +D39* +X46020702Y-22098198D02* +X45001802Y-22098198D01* +X45001802Y-22098198D02* +X44800000Y-22300000D01* +X44800000Y-22300000D02* +X44700000Y-22300000D01* +D38* +X44700000Y-23777496D02* +X44700000Y-22300000D01* +X44700000Y-23777496D02* +X45773137Y-24850633D01* +X37295000Y-23205000D02* +X37300000Y-23200000D01* +X37295000Y-24479000D02* +X37295000Y-23205000D01* +X46750000Y-30700000D02* +X50520702Y-26929298D01* +X50520702Y-26929298D02* +X50520702Y-23848198D01* +D39* +X46270702Y-25348198D02* +X45773137Y-24850633D01* +X45773137Y-24850633D02* +X45270702Y-24348198D01* +D38* +X49300000Y-34050000D02* +X49300000Y-33250000D01* +X46750000Y-30700000D02* +X44300000Y-30700000D01* +X49300000Y-33250000D02* +X46750000Y-30700000D01* +D39* +X28750000Y-24600000D02* +X28750000Y-23505597D01* +X28750000Y-23505597D02* +X28998135Y-23257462D01* +X29250000Y-24600000D02* +X29250000Y-23509327D01* +X29250000Y-23509327D02* +X28998135Y-23257462D01* +X46920702Y-24598198D02* +X46920702Y-25014200D01* +X46920702Y-25014200D02* +X46586704Y-25348198D01* +X46586704Y-25348198D02* +X46270702Y-25348198D01* +X52270702Y-23848198D02* +X50520702Y-23848198D01* +X50520702Y-23848198D02* +X50270702Y-24098198D01* +X50270702Y-24098198D02* +X49020702Y-24098198D01* +D38* +X53050000Y-34850000D02* +X51300000Y-34850000D01* +D40* +X24500000Y-27500000D02* +X25250000Y-27500000D01* +X25250000Y-27500000D02* +X26250000Y-26500000D01* +D37* +X27100000Y-25250000D02* +X26750000Y-25250000D01* +X28750000Y-29400000D02* +X28750000Y-29861002D01* +X28750000Y-29400000D02* +X28750000Y-30750000D01* +X28750000Y-30750000D02* +X28500000Y-31000000D01* +X27100000Y-26750000D02* +X26500000Y-26750000D01* +X26500000Y-26750000D02* +X26250000Y-26500000D01* +X27100000Y-26250000D02* +X26500000Y-26250000D01* +X26500000Y-26250000D02* +X26250000Y-26500000D01* +D36* +X28800000Y-49900000D02* +X34966000Y-49900000D01* +X34966000Y-49900000D02* +X35500000Y-49366000D01* +X28750000Y-49000000D02* +X28750000Y-49850000D01* +X28750000Y-49850000D02* +X28800000Y-49900000D01* +D41* +X39297612Y-33350886D02* +X41105000Y-31543498D01* +X41105000Y-31543498D02* +X41105000Y-30321000D01* +X38550886Y-33350886D02* +X39297612Y-33350886D01* +D38* +X47300000Y-39000000D02* +X47500000Y-39200000D01* +X47500000Y-39200000D02* +X49200000Y-39200000D01* +X49200000Y-39200000D02* +X49300000Y-39100000D01* +X49300000Y-39100000D02* +X49300000Y-37150000D01* +D40* +X50520702Y-22348198D02* +X50520702Y-20920702D01* +X50520702Y-20920702D02* +X50500000Y-20900000D01* +D36* +X49400000Y-45400000D02* +X48052703Y-46736498D01* +X45750000Y-48750000D02* +X46039201Y-48750000D01* +X46039201Y-48750000D02* +X48052703Y-46736498D01* +D38* +X42300000Y-46200000D02* +X42500000Y-46000000D01* +X42500000Y-46000000D02* +X42500000Y-45000000D01* +X41500000Y-46200000D02* +X42300000Y-46200000D01* +X40999325Y-46700675D02* +X41500000Y-46200000D01* +X40999325Y-48000000D02* +X40999325Y-46700675D01* +X42500000Y-45200000D02* +X42500000Y-45000000D01* +D36* +X43000000Y-48000000D02* +X43278739Y-48278739D01* +X43278739Y-48278739D02* +X43750000Y-48750000D01* +X41000000Y-47999325D02* +X42999325Y-47999325D01* +X42999325Y-47999325D02* +X43278739Y-48278739D01* +X39900000Y-48000000D02* +X40999325Y-48000000D01* +X40999325Y-48000000D02* +X41000000Y-47999325D01* +X49400000Y-44200000D02* +X48600000Y-43400000D01* +X49400000Y-44200000D02* +X49400000Y-45400000D01* +X43750000Y-48750000D02* +X45750000Y-48750000D01* +X38000000Y-48750000D02* +X38750000Y-48000000D01* +X38750000Y-48000000D02* +X39900000Y-48000000D01* +X35500000Y-49366000D02* +X36116000Y-48750000D01* +X36116000Y-48750000D02* +X38000000Y-48750000D01* +X35170999Y-49695001D02* +X35500000Y-49366000D01* +X35500000Y-49366000D02* +X35500000Y-47750000D01* +X26750000Y-48750000D02* +X28500000Y-48750000D01* +X28500000Y-48750000D02* +X28750000Y-49000000D01* +X26750000Y-48750000D02* +X25311640Y-48750000D01* +X25311640Y-48750000D02* +X24312540Y-47750900D01* +X24250000Y-44250000D02* +X24250000Y-42813440D01* +X22612540Y-42750900D02* +X22295354Y-42433714D01* +X22295354Y-42433714D02* +X21612540Y-41750900D01* +X23000000Y-44500000D02* +X23000000Y-43138360D01* +X23000000Y-43138360D02* +X22295354Y-42433714D01* +X24312540Y-42750900D02* +X22612540Y-42750900D01* +X24250000Y-42813440D02* +X24312540Y-42750900D01* +X23000000Y-44500000D02* +X23250000Y-44250000D01* +X23250000Y-44250000D02* +X24250000Y-44250000D01* +X23000000Y-47513360D02* +X23000000Y-44500000D01* +X24312540Y-47750900D02* +X23237540Y-47750900D01* +X23237540Y-47750900D02* +X23000000Y-47513360D01* +X21612540Y-48750900D02* +X23312540Y-48750900D01* +X23312540Y-48750900D02* +X24312540Y-47750900D01* +D37* +X31200000Y-34300000D02* +X31200000Y-32175000D01* +X31200000Y-32175000D02* +X30025000Y-31000000D01* +X30025000Y-31000000D02* +X30000000Y-31000000D01* +X31000000Y-23257453D02* +X31000000Y-22750000D01* +X31000000Y-22750000D02* +X31350000Y-22400000D01* +X26750000Y-21250000D02* +X26750000Y-21950000D01* +X26750000Y-21950000D02* +X26800000Y-22000000D01* +D38* +X34662300Y-21520576D02* +X34320576Y-21520576D01* +X34320576Y-21520576D02* +X33800000Y-21000000D01* +X28637500Y-26137500D02* +X30362500Y-26137500D01* +X30362500Y-26137500D02* +X30362500Y-27862500D01* +X30850000Y-25571545D02* +X30850000Y-25650000D01* +X30850000Y-25650000D02* +X30362500Y-26137500D01* +X28637500Y-27862500D02* +X28637500Y-26137500D01* +X28637500Y-27862500D02* +X30362500Y-27862500D01* +X28050000Y-25534450D02* +X28050000Y-25550000D01* +X28050000Y-25550000D02* +X28637500Y-26137500D01* +X31900000Y-42500000D02* +X30750000Y-42500000D01* +X30750000Y-42500000D02* +X30362500Y-42112500D01* +D39* +X33800000Y-21000000D02* +X33750000Y-21000000D01* +X29750000Y-21100000D02* +X29650000Y-21100000D01* +D38* +X47300000Y-37150000D02* +X47300000Y-39000000D01* +X47300000Y-39000000D02* +X47100000Y-39200000D01* +X47100000Y-39200000D02* +X45500000Y-39200000D01* +X45500000Y-39200000D02* +X45300000Y-39000000D01* +X45300000Y-39000000D02* +X45300000Y-37950000D01* +X45300000Y-37950000D02* +X45300000Y-37150000D01* +X31250000Y-43650000D02* +X31250000Y-43000000D01* +X31250000Y-43000000D02* +X30362500Y-42112500D01* +X29250000Y-43650000D02* +X29250000Y-42725000D01* +X29250000Y-42725000D02* +X28637500Y-42112500D01* +D40* +X21612540Y-41750900D02* +X21612540Y-40562460D01* +X21612540Y-40562460D02* +X22275000Y-39900000D01* +X22275000Y-39900000D02* +X22300000Y-39900000D01* +D38* +X43750000Y-48725000D02* +X43750000Y-48750000D01* +X28637500Y-42112500D02* +X30362500Y-42112500D01* +X28637500Y-40387500D02* +X30362500Y-40387500D01* +X26800000Y-21200000D02* +X26750000Y-21250000D01* +D37* +X31350000Y-22400000D02* +X32400000Y-22400000D01* +X32400000Y-22400000D02* +X33200000Y-21600000D01* +X33200000Y-21600000D02* +X33200000Y-21550000D01* +X33200000Y-21550000D02* +X33750000Y-21000000D01* +D39* +X29650000Y-21100000D02* +X29950000Y-21100000D01* +X31250000Y-22400000D02* +X31350000Y-22400000D01* +X28250000Y-21200000D02* +X29550000Y-21200000D01* +X29550000Y-21200000D02* +X29650000Y-21100000D01* +X28250000Y-21200000D02* +X26800000Y-21200000D01* +X46520702Y-26348198D02* +X47320702Y-25548198D01* +X47320702Y-25548198D02* +X47320702Y-24598198D01* +X47320702Y-24598198D02* +X47320702Y-23733198D01* +X47320702Y-23733198D02* +X47085702Y-23498198D01* +X47955702Y-23498198D02* +X48120702Y-23663198D01* +X48120702Y-23663198D02* +X48120702Y-24598198D01* +X47085702Y-22698198D02* +X47085702Y-23498198D01* +X47955702Y-23498198D02* +X47955702Y-22698198D01* +X47085702Y-23498198D02* +X47955702Y-23498198D01* +X47955702Y-22698198D02* +X47085702Y-22698198D01* +X48120702Y-21598198D02* +X48120702Y-22533198D01* +X48120702Y-22533198D02* +X47955702Y-22698198D01* +X49020702Y-22098198D02* +X48836704Y-22098198D01* +X48836704Y-22098198D02* +X48781705Y-22153197D01* +X48781705Y-22153197D02* +X48500703Y-22153197D01* +X48500703Y-22153197D02* +X47955702Y-22698198D01* +X49020702Y-22098198D02* +X50270702Y-22098198D01* +X50270702Y-22098198D02* +X50520702Y-22348198D01* +X52270702Y-22348198D02* +X50520702Y-22348198D01* +D38* +X47300000Y-37150000D02* +X47300000Y-37431002D01* +X49300000Y-37431002D02* +X49300000Y-37150000D01* +X45300000Y-37150000D02* +X45300000Y-37431002D01* +X49300000Y-37150000D02* +X50500000Y-37150000D01* +X50500000Y-37150000D02* +X51300000Y-36350000D01* +D37* +X29750000Y-29400000D02* +X29750000Y-28475000D01* +X29750000Y-28475000D02* +X30362500Y-27862500D01* +X30000000Y-31000000D02* +X29750000Y-30750000D01* +X29750000Y-30750000D02* +X29750000Y-29400000D01* +D40* +X29550000Y-21450000D02* +X29650000Y-21350000D01* +X27750000Y-43650000D02* +X27750000Y-43000000D01* +X27750000Y-43000000D02* +X28637500Y-42112500D01* +X27750000Y-43650000D02* +X25211640Y-43650000D01* +X25211640Y-43650000D02* +X24312540Y-42750900D01* +X29750000Y-38850000D02* +X29750000Y-39775000D01* +X29750000Y-39775000D02* +X30362500Y-40387500D01* +X24312540Y-47750900D02* +X24312540Y-48062540D01* +X32600000Y-48000000D02* +X35250000Y-48000000D01* +X35250000Y-48000000D02* +X35500000Y-47750000D01* +X35500000Y-47750000D02* +X36000000Y-47750000D01* +X38000000Y-48750000D02* +X38250000Y-48750000D01* +X31250000Y-38850000D02* +X31250000Y-38219602D01* +X31250000Y-38219602D02* +X31320001Y-38149601D01* +X31049601Y-37379999D02* +X30420001Y-37379999D01* +X31320001Y-38149601D02* +X31320001Y-37650399D01* +X31320001Y-37650399D02* +X31049601Y-37379999D01* +X30420001Y-37379999D02* +X30179999Y-37620001D01* +X30179999Y-37620001D02* +X26720001Y-37620001D01* +X26720001Y-37620001D02* +X26700000Y-37600000D01* +X26700000Y-37600000D02* +X24400000Y-39900000D01* +X24400000Y-39900000D02* +X23800000Y-39900000D01* +X27100000Y-43000000D02* +X25980398Y-43000000D01* +X25980398Y-43000000D02* +X23800000Y-40819602D01* +X23800000Y-40819602D02* +X23800000Y-40475000D01* +X23800000Y-40475000D02* +X23800000Y-39900000D01* +D36* +X25500000Y-46500000D02* +X25750000Y-46500000D01* +X25750000Y-46500000D02* +X26750000Y-45500000D01* +X24250000Y-45750000D02* +X24750000Y-45750000D01* +X24750000Y-45750000D02* +X25500000Y-46500000D01* +D40* +X26500000Y-45500000D02* +X26750000Y-45500000D01* +D36* +X28750000Y-45500000D02* +X28850000Y-45500000D01* +X28850000Y-45500000D02* +X30400000Y-47050000D01* +X26750000Y-47250000D02* +X27000000Y-47250000D01* +X27000000Y-47250000D02* +X28750000Y-45500000D01* +D40* +X28750000Y-43650000D02* +X28750000Y-45500000D01* +X30400000Y-47050000D02* +X30300000Y-47050000D01* +D36* +X39900000Y-47050000D02* +X38200000Y-47050000D01* +X38200000Y-47050000D02* +X38000000Y-47250000D01* +X35500000Y-45210000D02* +X35960000Y-45210000D01* +X35960000Y-45210000D02* +X38000000Y-47250000D01* +X35500000Y-45210000D02* +X37790000Y-45210000D01* +X37790000Y-45210000D02* +X38000000Y-45000000D01* +X32600000Y-47050000D02* +X34440000Y-45210000D01* +X34440000Y-45210000D02* +X35500000Y-45210000D01* +D38* +X36010000Y-45210000D02* +X35500000Y-45210000D01* +X38000000Y-47250000D02* +X38000000Y-47225000D01* +D40* +X39900000Y-48950000D02* +X40950000Y-48950000D01* +X40950000Y-48950000D02* +X41000000Y-49000000D01* +X39900000Y-48950000D02* +X39900000Y-49100000D01* +X38000000Y-47250000D02* +X38000000Y-47000000D01* +X36210000Y-45210000D02* +X35500000Y-45210000D01* +X38000000Y-47250000D02* +X37750000Y-47250000D01* +X38000000Y-47250000D02* +X38250000Y-47250000D01* +D37* +X24550000Y-26000000D02* +X24800000Y-25750000D01* +X24800000Y-25750000D02* +X27100000Y-25750000D01* +D39* +X29750000Y-24600000D02* +X29750000Y-22500000D01* +X29750000Y-22500000D02* +X29650000Y-22400000D01* +X28250000Y-22300000D02* +X29550000Y-22300000D01* +X29550000Y-22300000D02* +X29650000Y-22400000D01* +D40* +X29550000Y-22550000D02* +X29650000Y-22650000D01* +X29750000Y-22750000D02* +X29650000Y-22650000D01* +X30500000Y-23100000D02* +X30500000Y-21710505D01* +X30500000Y-21710505D02* +X30500000Y-21600000D01* +X31350000Y-21100000D02* +X30600000Y-21100000D01* +X30600000Y-21100000D02* +X30500000Y-21200000D01* +X30500000Y-21200000D02* +X30500000Y-21710505D01* +X30250000Y-23350000D02* +X30500000Y-23100000D01* +X30250000Y-24600000D02* +X30250000Y-23350000D01* +X32700000Y-21000000D02* +X31450000Y-21000000D01* +X31450000Y-21000000D02* +X31350000Y-21100000D01* +D39* +X31208998Y-21100000D02* +X31350000Y-21100000D01* +D40* +X48500000Y-25300000D02* +X48500000Y-24618900D01* +X48500000Y-24618900D02* +X48520702Y-24598198D01* +X27111890Y-23570010D02* +X26070010Y-23570010D01* +X27570010Y-23570010D02* +X27111890Y-23570010D01* +X27111890Y-23570010D02* +X27111890Y-23788110D01* +X27111890Y-23788110D02* +X26900000Y-24000000D01* +X25250000Y-23250000D02* +X25250000Y-21500000D01* +X27750000Y-24600000D02* +X27750000Y-23750000D01* +X27750000Y-23750000D02* +X27570010Y-23570010D01* +X26070010Y-23570010D02* +X25750000Y-23250000D01* +X25750000Y-23250000D02* +X25250000Y-23250000D01* +X23229990Y-24857438D02* +X23229990Y-24433174D01* +X23229990Y-24433174D02* +X23000000Y-24203184D01* +X23000000Y-24203184D02* +X23000000Y-22225000D01* +X23750000Y-21500000D02* +X23725000Y-21500000D01* +X23725000Y-21500000D02* +X23000000Y-22225000D01* +X46908628Y-35608628D02* +X51150090Y-35608628D01* +X51150090Y-35608628D02* +X51658628Y-35608628D01* +X52108628Y-35608628D02* +X51150090Y-35608628D01* +X53050000Y-36350000D02* +X52850000Y-36350000D01* +X52850000Y-36350000D02* +X52108628Y-35608628D01* +X46300000Y-37150000D02* +X46300000Y-36217256D01* +X46300000Y-36217256D02* +X46908628Y-35608628D01* +X34980110Y-35358716D02* +X35338826Y-35000000D01* +X35338826Y-35000000D02* +X36400000Y-35000000D01* +X34516828Y-35590011D02* +X34748815Y-35590011D01* +X34748815Y-35590011D02* +X34980110Y-35358716D01* +X34516828Y-35590011D02* +X26270001Y-35590011D01* +X26270001Y-35590011D02* +X26179990Y-35500000D01* +X46300000Y-37150000D02* +X46300000Y-38100000D01* +X46300000Y-37000000D02* +X46300000Y-37150000D01* +D39* +X48020702Y-26348198D02* +X47720702Y-26048198D01* +X47720702Y-26048198D02* +X47720702Y-24598198D01* +D40* +X26250000Y-42500000D02* +X27100000Y-42500000D01* +X26000000Y-42250000D02* +X26250000Y-42500000D01* +X27100000Y-42000000D02* +X26500000Y-42000000D01* +X26250000Y-41500000D02* +X26000000Y-41250000D01* +X26250000Y-41750000D02* +X26250000Y-41500000D01* +X26500000Y-42000000D02* +X26250000Y-41750000D01* +X28000000Y-23250000D02* +X26800000Y-23250000D01* +X28250000Y-24600000D02* +X28250000Y-23500000D01* +X28250000Y-23500000D02* +X28000000Y-23250000D01* +X26800000Y-23250000D02* +X26750000Y-23200000D01* +X26750000Y-23200000D02* +X26750000Y-22750000D01* +X26950000Y-22750000D02* +X26750000Y-22750000D01* +X29250000Y-34125736D02* +X29250000Y-34250000D01* +X29250000Y-34250000D02* +X29300000Y-34300000D01* +X34200000Y-43300000D02* +X34200000Y-42971085D01* +X34200000Y-42971085D02* +X34200000Y-40300000D01* +X32600000Y-48950000D02* +X31700000Y-48950000D01* +X31500000Y-46200000D02* +X34200000Y-43500000D01* +X31700000Y-48950000D02* +X31500000Y-48750000D01* +X31500000Y-48750000D02* +X31500000Y-46200000D01* +X34200000Y-43500000D02* +X34200000Y-42971085D01* +X29250000Y-29400000D02* +X29250000Y-33174388D01* +X29250000Y-33174388D02* +X29250000Y-33450000D01* +X29250000Y-34125736D02* +X29250000Y-33174388D01* +X30400000Y-48950000D02* +X30200000Y-48950000D01* +X30200000Y-48950000D02* +X28750000Y-47500000D01* +X26250000Y-28750000D02* +X26156508Y-28750000D01* +X26156508Y-28750000D02* +X26026518Y-28879990D01* +X27100000Y-28750000D02* +X26250000Y-28750000D01* +X23750000Y-24250000D02* +X23750000Y-23250000D01* +D39* +X37038399Y-22654999D02* +X38084279Y-22654999D01* +X38084279Y-22654999D02* +X38410999Y-22654999D01* +X39835000Y-24479000D02* +X39835000Y-23579000D01* +X39835000Y-23579000D02* +X38910999Y-22654999D01* +X38910999Y-22654999D02* +X38084279Y-22654999D01* +X34000000Y-25250000D02* +X34700000Y-25250000D01* +X34700000Y-25250000D02* +X36754999Y-23195001D01* +X36754999Y-23195001D02* +X36754999Y-22938399D01* +X36754999Y-22938399D02* +X37038399Y-22654999D01* +X39835000Y-24079000D02* +X39835000Y-24479000D01* +D40* +X31900000Y-26750000D02* +X34000000Y-26750000D01* +X39500000Y-43800000D02* +X39500000Y-45000000D01* +X31980031Y-36980031D02* +X33500000Y-36980031D01* +X33500000Y-36980031D02* +X33700000Y-37180031D01* +X27100000Y-27750000D02* +X25947438Y-27750000D01* +X25947438Y-27750000D02* +X25397438Y-28300000D01* +X25397438Y-28300000D02* +X24000000Y-28300000D01* +X23600000Y-29500000D02* +X24500000Y-30400000D01* +X24500000Y-30400000D02* +X24500000Y-35947298D01* +X24000000Y-28300000D02* +X23600000Y-28700000D01* +X23600000Y-28700000D02* +X23600000Y-29500000D01* +X24500000Y-35947298D02* +X25532732Y-36980030D01* +X25532732Y-36980030D02* +X31980031Y-36980031D01* +X39500000Y-44500000D02* +X39500000Y-45000000D01* +D37* +X39500000Y-45000000D02* +X41000000Y-45000000D01* +D40* +X36353593Y-35816009D02* +X36973739Y-35195863D01* +X44900000Y-20500000D02* +X46452563Y-20500001D01* +X46920702Y-21123198D02* +X46920702Y-21598198D01* +X46452563Y-20500001D02* +X46920702Y-20968140D01* +X46920702Y-20968140D02* +X46920702Y-21123198D01* +X42579999Y-33879999D02* +X43800000Y-35100000D01* +X44900000Y-20500000D02* +X44620001Y-20779999D01* +X42579999Y-21050399D02* +X42579999Y-33879999D01* +X44620001Y-20779999D02* +X42850399Y-20779999D01* +X42850399Y-20779999D02* +X42579999Y-21050399D01* +X46300000Y-35100000D02* +X45879999Y-35520001D01* +X45879999Y-35520001D02* +X44220001Y-35520001D01* +X44220001Y-35520001D02* +X43800000Y-35100000D01* +X25159990Y-31451782D02* +X25159990Y-35478902D01* +X25797837Y-36340011D02* +X25159990Y-35702164D01* +X25159990Y-35702164D02* +X25159990Y-35478902D01* +X25797837Y-36340011D02* +X35829591Y-36340011D01* +X36973739Y-35195863D02* +X37600000Y-34569602D01* +X35829591Y-36340011D02* +X36973739Y-35195863D01* +X36029591Y-36140011D02* +X36353593Y-35816009D01* +X35929592Y-36240010D02* +X36353593Y-35816009D01* +X37630398Y-34569602D02* +X38113097Y-34086903D01* +X37600000Y-34569602D02* +X37630398Y-34569602D01* +X38113097Y-34086903D02* +X38113097Y-33922501D01* +X27750000Y-29400000D02* +X25897846Y-29400000D01* +X25897846Y-29400000D02* +X25159989Y-30137857D01* +X25159989Y-30137857D02* +X25159990Y-31451782D01* +X46300000Y-35100000D02* +X46300000Y-34050000D01* +X46300000Y-33900000D02* +X46300000Y-34050000D01* +X45032552Y-20820010D02* +X45990398Y-20820010D01* +X46320010Y-20820010D02* +X45990398Y-20820010D01* +X45990398Y-20820010D02* +X46200000Y-20820010D01* +X46520702Y-21020702D02* +X46320010Y-20820010D01* +X46520702Y-21598198D02* +X46520702Y-21020702D01* +X44752554Y-21100008D02* +X45032552Y-20820010D01* +X43100000Y-21200000D02* +X43199991Y-21100009D01* +X43199991Y-21100009D02* +X44752554Y-21100008D01* +X43100000Y-21300000D02* +X43100000Y-21200000D01* +X45300000Y-35000000D02* +X45300000Y-34050000D01* +X30250000Y-29400000D02* +X30250000Y-29950000D01* +X30250000Y-29950000D02* +X33000000Y-32700000D01* +X33000000Y-32700000D02* +X33442665Y-32700000D01* +X45300000Y-34050000D02* +X45300000Y-33400000D01* +X45300000Y-33400000D02* +X43100000Y-31200000D01* +X43100000Y-31200000D02* +X43100000Y-21300000D01* +X30750000Y-29950000D02* +X32979999Y-32179999D01* +X32979999Y-32179999D02* +X33692266Y-32179999D01* +X33692266Y-32179999D02* +X34000000Y-32487733D01* +X31900000Y-40000000D02* +X32552562Y-40000000D01* +X32552562Y-40000000D02* +X35167799Y-37384763D01* +X35167799Y-37384763D02* +X35167799Y-36867799D01* +X35200000Y-37071002D02* +X35200000Y-36800000D01* +X33830832Y-32318565D02* +X33962666Y-32450399D01* +X34000000Y-34500000D02* +X34000000Y-32487733D01* +X34000000Y-32487733D02* +X33830832Y-32318565D01* +X30750000Y-29400000D02* +X30750000Y-29950000D01* +X30750000Y-29950000D02* +X30797438Y-29997438D01* +D39* +X36900000Y-32400000D02* +X38517228Y-32400000D01* +X38517228Y-32400000D02* +X39084580Y-32400000D01* +X39583804Y-32400000D02* +X38517228Y-32400000D01* +X40500000Y-31483804D02* +X39583804Y-32400000D01* +X40500000Y-31019934D02* +X40500000Y-31483804D01* +X40500000Y-29300000D02* +X40500000Y-27597647D01* +X38565000Y-24479000D02* +X38565000Y-25379000D01* +X38565000Y-25379000D02* +X40500000Y-27314000D01* +X40500000Y-27314000D02* +X40500000Y-27597647D01* +D40* +X40500000Y-29500000D02* +X40500000Y-29300000D01* +X40500000Y-31019934D02* +X40500000Y-29500000D01* +X39084580Y-32400000D02* +X39119934Y-32400000D01* +D39* +X31900000Y-28250000D02* +X32750000Y-28250000D01* +X32750000Y-28250000D02* +X36900000Y-32400000D01* +X38565000Y-24879000D02* +X38565000Y-24479000D01* +X39835000Y-30321000D02* +X39835000Y-31197018D01* +X39835000Y-31197018D02* +X39532018Y-31500000D01* +X39532018Y-31500000D02* +X36800000Y-31500000D01* +X36800000Y-31500000D02* +X33050000Y-27750000D01* +X33050000Y-27750000D02* +X32500000Y-27750000D01* +X32500000Y-27750000D02* +X31900000Y-27750000D01* +X32673272Y-27750000D02* +X32500000Y-27750000D01* +X39835000Y-30721000D02* +X39835000Y-30321000D01* +X39835000Y-29921000D02* +X39835000Y-30321000D01* +X37295000Y-30321000D02* +X37295000Y-29421000D01* +X37295000Y-29421000D02* +X35244272Y-29421000D01* +X35244272Y-29421000D02* +X33073272Y-27250000D01* +X33073272Y-27250000D02* +X31900000Y-27250000D01* +X37295000Y-29921000D02* +X37295000Y-30321000D01* +X31900000Y-26250000D02* +X32500000Y-26250000D01* +X32500000Y-26250000D02* +X32650000Y-26100000D01* +X32650000Y-26100000D02* +X35244000Y-26100000D01* +X35244000Y-26100000D02* +X38565000Y-29421000D01* +X38565000Y-29421000D02* +X38565000Y-30321000D01* +X38565000Y-29921000D02* +X38565000Y-30321000D01* +X36885136Y-22284989D02* +X39074166Y-22284989D01* +X39074166Y-22284989D02* +X39310989Y-22284989D01* +X41105000Y-24479000D02* +X41105000Y-23579000D01* +X41105000Y-23579000D02* +X39810989Y-22284989D01* +X39810989Y-22284989D02* +X39074166Y-22284989D01* +X31900000Y-25750000D02* +X32500000Y-25750000D01* +X33500000Y-24600000D02* +X34874394Y-23225606D01* +X32500000Y-25750000D02* +X33200000Y-25050000D01* +X33200000Y-25050000D02* +X33200000Y-24700000D01* +X35944519Y-23225606D02* +X36885136Y-22284989D01* +X33200000Y-24700000D02* +X33300000Y-24600000D01* +X34874394Y-23225606D02* +X35944519Y-23225606D01* +X33300000Y-24600000D02* +X33500000Y-24600000D01* +X41105000Y-24079000D02* +X41105000Y-24479000D01* +X31900000Y-25750000D02* +X32358998Y-25750000D01* +D40* +X35613232Y-21817166D02* +X35650399Y-21779999D01* +X41762458Y-23262458D02* +X40279999Y-21779999D01* +X35650399Y-21779999D02* +X35568180Y-21862218D01* +X40279999Y-21779999D02* +X35650399Y-21779999D01* +X35568180Y-21862218D02* +X35613232Y-21817166D01* +X41762458Y-23840456D02* +X41762458Y-23262458D01* +X32777836Y-40500000D02* +X31900000Y-40500000D01* +X41762458Y-23840456D02* +X41762458Y-31515378D01* +X41762458Y-31515378D02* +X32777836Y-40500000D01* +X35490419Y-21939979D02* +X35568180Y-21862218D01* +X31250000Y-24600000D02* +X32322438Y-24600000D01* +X32322438Y-24600000D02* +X34561843Y-22360595D01* +X35379999Y-22050399D02* +X35568180Y-21862218D01* +X34561843Y-22360595D02* +X35339405Y-22360595D01* +X35339405Y-22360595D02* +X35379999Y-22320001D01* +X35379999Y-22320001D02* +X35379999Y-22050399D01* +X34618399Y-22040585D02* +X35059415Y-22040585D01* +X35059415Y-22040585D02* +X35059989Y-22040011D01* +X35059989Y-22040011D02* +X35059989Y-21917847D01* +X35059989Y-21917847D02* +X35517846Y-21459990D01* +X35517846Y-21459990D02* +X40412552Y-21459990D01* +X40412552Y-21459990D02* +X42082468Y-23129906D01* +X42082468Y-23129906D02* +X42082468Y-31647930D01* +X42082468Y-31647930D02* +X41465362Y-32265036D01* +X33679999Y-40050399D02* +X41465362Y-32265036D01* +X41465362Y-32265036D02* +X41730398Y-32000000D01* +X41895011Y-31835387D02* +X41465362Y-32265036D01* +X33679990Y-40809118D02* +X33679999Y-40809109D01* +X33679999Y-40809109D02* +X33679999Y-40050399D01* +X32669876Y-23800000D02* +X34429291Y-22040585D01* +X34618399Y-22040585D02* +X34429290Y-22040586D01* +X31000000Y-23800000D02* +X32669876Y-23800000D01* +X34429291Y-22040585D02* +X34618399Y-22040585D01* +X30750000Y-24050000D02* +X31000000Y-23800000D01* +X30750000Y-24050000D02* +X30750000Y-24600000D01* +X30750000Y-38850000D02* +X30750000Y-37950000D01* +X30750000Y-37950000D02* +X30800000Y-37900000D01* +X26134070Y-36660021D02* +X32983728Y-36660021D01* +X31900000Y-39500000D02* +X32600000Y-39500000D01* +X32600000Y-39500000D02* +X34647798Y-37452202D01* +X34647798Y-37452202D02* +X34647798Y-37358227D01* +X34647798Y-37358227D02* +X33949592Y-36660021D01* +X33949592Y-36660021D02* +X32983728Y-36660021D01* +X26134070Y-36660021D02* +X25665284Y-36660020D01* +X24839981Y-35834717D02* +X25665285Y-36660021D01* +X25665285Y-36660021D02* +X26134070Y-36660021D01* +X25480349Y-28669651D02* +X24839980Y-29310020D01* +X24839980Y-29310020D02* +X24839981Y-35834717D01* +X25150000Y-29000000D02* +X25480349Y-28669651D01* +X25480349Y-28669651D02* +X25920001Y-28229999D01* +X31900000Y-39500000D02* +X32125000Y-39500000D01* +X24500000Y-29000000D02* +X25150000Y-29000000D01* +X25920001Y-28229999D02* +X26529999Y-28229999D01* +X26529999Y-28229999D02* +X26550000Y-28250000D01* +X26550000Y-28250000D02* +X27100000Y-28250000D01* +X31250000Y-29997438D02* +X33112551Y-31859989D01* +X33112551Y-31859989D02* +X33824818Y-31859989D01* +X33824818Y-31859989D02* +X36254531Y-34289702D01* +X31250000Y-29400000D02* +X31250000Y-29997438D01* +X37092994Y-38207006D02* +X38873521Y-36426479D01* +X38873521Y-36426479D02* +X38873521Y-36140020D01* +X37086558Y-34289702D02* +X36254531Y-34289702D01* +X31250000Y-29625000D02* +X31250000Y-29400000D01* +X35075719Y-22680605D02* +X35519395Y-22680605D01* +X32512084Y-25250000D02* +X32512084Y-24899999D01* +X32512084Y-24899999D02* +X34731478Y-22680605D01* +X34731478Y-22680605D02* +X35075719Y-22680605D01* +X31900000Y-25250000D02* +X32512084Y-25250000D01* +X35519395Y-22680605D02* +X35900000Y-22300000D01* +X31900000Y-25250000D02* +X32125000Y-25250000D01* +X25479999Y-32050508D02* +X25479999Y-35569611D01* +X25479999Y-35569611D02* +X25930389Y-36020001D01* +X35390891Y-36020001D02* +X35890882Y-35520010D01* +X25930389Y-36020001D02* +X35390891Y-36020001D01* +X35767099Y-35643793D02* +X35890882Y-35520010D01* +X25479999Y-31056397D02* +X25479999Y-32050508D01* +X25479999Y-32050508D02* +X25479999Y-32579999D01* +X28250000Y-29400000D02* +X28250000Y-30050000D01* +X25479999Y-30270409D02* +X25479999Y-31056397D01* +X28250000Y-30050000D02* +X28100000Y-30200000D01* +X28100000Y-30200000D02* +X26449592Y-30200000D01* +X26449592Y-30200000D02* +X26249601Y-30000009D01* +X26249601Y-30000009D02* +X25750399Y-30000009D01* +X25750399Y-30000009D02* +X25479999Y-30270409D01* +X25479999Y-31056397D02* +X25479999Y-31319229D01* +D42* +G36* +X54568000Y-20001982D02* +X54568000Y-50198018D01* +X52733009Y-53868000D01* +X22266991Y-53868000D01* +X20432000Y-50198018D01* +X20432000Y-49436837D01* +X20445172Y-49463663D01* +X20785862Y-49750902D01* +X21210540Y-49885900D01* +X21485540Y-49885900D01* +X21485540Y-48877900D01* +X21739540Y-48877900D01* +X21739540Y-49885900D01* +X22014540Y-49885900D01* +X22439218Y-49750902D01* +X22779908Y-49463663D01* +X22981659Y-49052774D01* +X22969377Y-49035750D01* +X25740000Y-49035750D01* +X25740000Y-49276309D01* +X25836673Y-49509698D01* +X26015301Y-49688327D01* +X26248690Y-49785000D01* +X26464250Y-49785000D01* +X26623000Y-49626250D01* +X26623000Y-48877000D01* +X25898750Y-48877000D01* +X25740000Y-49035750D01* +X22969377Y-49035750D01* +X22855494Y-48877900D01* +X21739540Y-48877900D01* +X21485540Y-48877900D01* +X21465540Y-48877900D01* +X21465540Y-48623900D01* +X21485540Y-48623900D01* +X21485540Y-47615900D01* +X21739540Y-47615900D01* +X21739540Y-48623900D01* +X22855494Y-48623900D01* +X22981659Y-48449026D01* +X22786731Y-48052031D01* +X23211311Y-48052031D01* +X23352972Y-48461949D01* +X23640719Y-48786452D01* +X24014602Y-48970168D01* +X24185540Y-48843634D01* +X24185540Y-47877900D01* +X24439540Y-47877900D01* +X24439540Y-48843634D01* +X24610478Y-48970168D01* +X24984361Y-48786452D01* +X25272108Y-48461949D01* +X25413769Y-48052031D01* +X25265103Y-47877900D01* +X24439540Y-47877900D01* +X24185540Y-47877900D01* +X23359977Y-47877900D01* +X23211311Y-48052031D01* +X22786731Y-48052031D01* +X22779908Y-48038137D01* +X22439218Y-47750898D01* +X22014540Y-47615900D01* +X21739540Y-47615900D01* +X21485540Y-47615900D01* +X21210540Y-47615900D01* +X20785862Y-47750898D01* +X20445172Y-48038137D01* +X20432000Y-48064963D01* +X20432000Y-43052031D01* +X23211311Y-43052031D01* +X23352972Y-43461949D01* +X23358637Y-43468338D01* +X23336673Y-43490302D01* +X23240000Y-43723691D01* +X23240000Y-43964250D01* +X23398750Y-44123000D01* +X24123000Y-44123000D01* +X24123000Y-43889928D01* +X24185540Y-43843634D01* +X24185540Y-42877900D01* +X23359977Y-42877900D01* +X23211311Y-43052031D01* +X20432000Y-43052031D01* +X20432000Y-42436837D01* +X20445172Y-42463663D01* +X20785862Y-42750902D01* +X21210540Y-42885900D01* +X21485540Y-42885900D01* +X21485540Y-41877900D01* +X21739540Y-41877900D01* +X21739540Y-42885900D01* +X22014540Y-42885900D01* +X22439218Y-42750902D01* +X22779908Y-42463663D01* +X22981659Y-42052774D01* +X22855494Y-41877900D01* +X21739540Y-41877900D01* +X21485540Y-41877900D01* +X21465540Y-41877900D01* +X21465540Y-41623900D01* +X21485540Y-41623900D01* +X21485540Y-41603900D01* +X21739540Y-41603900D01* +X21739540Y-41623900D01* +X22855494Y-41623900D01* +X22981659Y-41449026D01* +X22779908Y-41038137D01* +X22627927Y-40910000D01* +X22826309Y-40910000D01* +X23059698Y-40813327D01* +X23238327Y-40634699D01* +X23250624Y-40605012D01* +X23258386Y-40610316D01* +X23343000Y-40627451D01* +X23343000Y-40819602D01* +X23377787Y-40994489D01* +X23476852Y-41142750D01* +X23914783Y-41580681D01* +X23640719Y-41715348D01* +X23352972Y-42039851D01* +X23211311Y-42449769D01* +X23359977Y-42623900D01* +X24185540Y-42623900D01* +X24185540Y-42603900D01* +X24439540Y-42603900D01* +X24439540Y-42623900D01* +X24459540Y-42623900D01* +X24459540Y-42877900D01* +X24439540Y-42877900D01* +X24439540Y-43311210D01* +X24377000Y-43373750D01* +X24377000Y-44123000D01* +X25101250Y-44123000D01* +X25260000Y-43964250D01* +X25260000Y-43723691D01* +X25189957Y-43554593D01* +X25272108Y-43461949D01* +X25406672Y-43072569D01* +X25657248Y-43323145D01* +X25657250Y-43323148D01* +X25805512Y-43422213D01* +X25980398Y-43457000D01* +X26603533Y-43457000D01* +X26608386Y-43460316D01* +X26750000Y-43488994D01* +X27114744Y-43488994D01* +X27148750Y-43523000D01* +X27438654Y-43523000D01* +X27648690Y-43610000D01* +X27761006Y-43610000D01* +X27761006Y-44000000D01* +X27785899Y-44132296D01* +X27812500Y-44173635D01* +X27812500Y-44476250D01* +X27971250Y-44635000D01* +X27981908Y-44635000D01* +X27914684Y-44733386D01* +X27886006Y-44875000D01* +X27886006Y-45434856D01* +X27613994Y-45706868D01* +X27613994Y-44875000D01* +X27589101Y-44742704D01* +X27519795Y-44635000D01* +X27528750Y-44635000D01* +X27687500Y-44476250D01* +X27687500Y-43777000D01* +X27148750Y-43777000D01* +X26990000Y-43935750D01* +X26990000Y-44126309D01* +X27086673Y-44359698D01* +X27237980Y-44511006D01* +X26250000Y-44511006D01* +X26117704Y-44535899D01* +X25996198Y-44614086D01* +X25914684Y-44733386D01* +X25886006Y-44875000D01* +X25886006Y-45434856D01* +X25625000Y-45695862D01* +X25214569Y-45285431D01* +X25018563Y-45154463D01* +X25163327Y-45009698D01* +X25260000Y-44776309D01* +X25260000Y-44535750D01* +X25101250Y-44377000D01* +X24377000Y-44377000D01* +X24377000Y-44397000D01* +X24123000Y-44397000D01* +X24123000Y-44377000D01* +X23398750Y-44377000D01* +X23240000Y-44535750D01* +X23240000Y-44776309D01* +X23336673Y-45009698D01* +X23515301Y-45188327D01* +X23544988Y-45200624D01* +X23539684Y-45208386D01* +X23511006Y-45350000D01* +X23511006Y-46150000D01* +X23535899Y-46282296D01* +X23614086Y-46403802D01* +X23733386Y-46485316D01* +X23875000Y-46513994D01* +X24185538Y-46513994D01* +X24185538Y-46658165D01* +X24014602Y-46531632D01* +X23640719Y-46715348D01* +X23352972Y-47039851D01* +X23211311Y-47449769D01* +X23359977Y-47623900D01* +X24185540Y-47623900D01* +X24185540Y-47603900D01* +X24439540Y-47603900D01* +X24439540Y-47623900D01* +X25265103Y-47623900D01* +X25413769Y-47449769D01* +X25303139Y-47129645D01* +X25368741Y-47156885D01* +X25499997Y-47156999D01* +X25500000Y-47157000D01* +X25500573Y-47157000D01* +X25630112Y-47157113D01* +X25630385Y-47157000D01* +X25750000Y-47157000D01* +X26001423Y-47106989D01* +X26011006Y-47100586D01* +X26011006Y-47650000D01* +X26035899Y-47782296D01* +X26046490Y-47798754D01* +X26015301Y-47811673D01* +X25836673Y-47990302D01* +X25740000Y-48223691D01* +X25740000Y-48464250D01* +X25898750Y-48623000D01* +X26623000Y-48623000D01* +X26623000Y-48603000D01* +X26877000Y-48603000D01* +X26877000Y-48623000D01* +X26897000Y-48623000D01* +X26897000Y-48877000D01* +X26877000Y-48877000D01* +X26877000Y-49626250D01* +X27035750Y-49785000D01* +X27251310Y-49785000D01* +X27484699Y-49688327D01* +X27663327Y-49509698D01* +X27691789Y-49440984D01* +X27761673Y-49609698D01* +X27940301Y-49788327D01* +X28132648Y-49868000D01* +X23000000Y-49868000D01* +X22984776Y-49871028D01* +X22969376Y-49869087D01* +X22902592Y-49887376D01* +X22834681Y-49900884D01* +X22821776Y-49909507D01* +X22806804Y-49913607D01* +X22752101Y-49956062D01* +X22694530Y-49994530D01* +X22685906Y-50007436D01* +X22673644Y-50016953D01* +X22639354Y-50077107D01* +X22600884Y-50134681D01* +X22597856Y-50149906D01* +X22590169Y-50163390D01* +X22581509Y-50232085D01* +X22568000Y-50300000D01* +X22571028Y-50315224D01* +X22569087Y-50330624D01* +X22587376Y-50397408D01* +X22600884Y-50465319D01* +X22609507Y-50478224D01* +X22613607Y-50493196D01* +X23513607Y-52293196D01* +X23556062Y-52347899D01* +X23594530Y-52405470D01* +X23607436Y-52414094D01* +X23616953Y-52426356D01* +X23677107Y-52460646D01* +X23734681Y-52499116D01* +X23749906Y-52502144D01* +X23763390Y-52509831D01* +X23832085Y-52518491D01* +X23900000Y-52532000D01* +X51100000Y-52532000D01* +X51167915Y-52518491D01* +X51236610Y-52509831D01* +X51250094Y-52502144D01* +X51265319Y-52499116D01* +X51322893Y-52460646D01* +X51383047Y-52426356D01* +X51392564Y-52414094D01* +X51405470Y-52405470D01* +X51443938Y-52347899D01* +X51486393Y-52293196D01* +X52386392Y-50493196D01* +X52390491Y-50478227D01* +X52399116Y-50465319D01* +X52412625Y-50397403D01* +X52430913Y-50330624D01* +X52428972Y-50315224D01* +X52432000Y-50300000D01* +X52418491Y-50232085D01* +X52409831Y-50163390D01* +X52402144Y-50149906D01* +X52399116Y-50134681D01* +X52360646Y-50077107D01* +X52326356Y-50016953D01* +X52314094Y-50007436D01* +X52305470Y-49994530D01* +X52247894Y-49956059D01* +X52193196Y-49913608D01* +X52178227Y-49909509D01* +X52165319Y-49900884D01* +X52097403Y-49887375D01* +X52030624Y-49869087D01* +X52015224Y-49871028D01* +X52000000Y-49868000D01* +X46717352Y-49868000D01* +X46909699Y-49788327D01* +X47088327Y-49609698D01* +X47185000Y-49376309D01* +X47185000Y-49035750D01* +X47026250Y-48877000D01* +X45877000Y-48877000D01* +X45877000Y-48897000D01* +X45623000Y-48897000D01* +X45623000Y-48877000D01* +X43877000Y-48877000D01* +X43877000Y-49626250D01* +X44035750Y-49785000D01* +X44251310Y-49785000D01* +X44484699Y-49688327D01* +X44487500Y-49685526D01* +X44590301Y-49788327D01* +X44782648Y-49868000D01* +X29367352Y-49868000D01* +X29559699Y-49788327D01* +X29736139Y-49611886D01* +X29870000Y-49638994D01* +X30930000Y-49638994D01* +X31062296Y-49614101D01* +X31183802Y-49535914D01* +X31265316Y-49416614D01* +X31293994Y-49275000D01* +X31293994Y-49190290D01* +X31376852Y-49273148D01* +X31525114Y-49372213D01* +X31700000Y-49407000D01* +X31730843Y-49407000D01* +X31730899Y-49407296D01* +X31809086Y-49528802D01* +X31928386Y-49610316D01* +X32070000Y-49638994D01* +X33130000Y-49638994D01* +X33262296Y-49614101D01* +X33383802Y-49535914D01* +X33465316Y-49416614D01* +X33493994Y-49275000D01* +X33493994Y-48859031D01* +X33668327Y-48684699D01* +X33765000Y-48451310D01* +X33765000Y-48285750D01* +X33606250Y-48127000D01* +X32727000Y-48127000D01* +X32727000Y-48147000D01* +X32473000Y-48147000D01* +X32473000Y-48127000D01* +X32453000Y-48127000D01* +X32453000Y-48035750D01* +X33849000Y-48035750D01* +X33849000Y-48892310D01* +X33945673Y-49125699D01* +X34124302Y-49304327D01* +X34357691Y-49401000D01* +X35214250Y-49401000D01* +X35373000Y-49242250D01* +X35373000Y-47877000D01* +X34007750Y-47877000D01* +X33849000Y-48035750D01* +X32453000Y-48035750D01* +X32453000Y-47873000D01* +X32473000Y-47873000D01* +X32473000Y-47853000D01* +X32727000Y-47853000D01* +X32727000Y-47873000D01* +X33606250Y-47873000D01* +X33765000Y-47714250D01* +X33765000Y-47548690D01* +X33668327Y-47315301D01* +X33493994Y-47140969D01* +X33493994Y-47085144D01* +X33849000Y-46730138D01* +X33849000Y-47464250D01* +X34007750Y-47623000D01* +X35373000Y-47623000D01* +X35373000Y-47603000D01* +X35627000Y-47603000D01* +X35627000Y-47623000D01* +X36992250Y-47623000D01* +X37151000Y-47464250D01* +X37151000Y-47330138D01* +X37261006Y-47440144D01* +X37261006Y-47650000D01* +X37285899Y-47782296D01* +X37296490Y-47798754D01* +X37265301Y-47811673D01* +X37096112Y-47980862D01* +X36992250Y-47877000D01* +X35627000Y-47877000D01* +X35627000Y-49242250D01* +X35785750Y-49401000D01* +X36642309Y-49401000D01* +X36875698Y-49304327D01* +X36990000Y-49190026D01* +X36990000Y-49276309D01* +X37086673Y-49509698D01* +X37265301Y-49688327D01* +X37498690Y-49785000D01* +X37714250Y-49785000D01* +X37873000Y-49626250D01* +X37873000Y-48877000D01* +X37853000Y-48877000D01* +X37853000Y-48623000D01* +X37873000Y-48623000D01* +X37873000Y-48603000D01* +X38127000Y-48603000D01* +X38127000Y-48623000D01* +X38147000Y-48623000D01* +X38147000Y-48877000D01* +X38127000Y-48877000D01* +X38127000Y-49626250D01* +X38285750Y-49785000D01* +X38501310Y-49785000D01* +X38734699Y-49688327D01* +X38913327Y-49509698D01* +X39007423Y-49282531D01* +X39030899Y-49407296D01* +X39109086Y-49528802D01* +X39228386Y-49610316D01* +X39370000Y-49638994D01* +X40430000Y-49638994D01* +X40562296Y-49614101D01* +X40642075Y-49562765D01* +X40868741Y-49656885D01* +X41130112Y-49657113D01* +X41358664Y-49562677D01* +X41428386Y-49610316D01* +X41570000Y-49638994D01* +X42630000Y-49638994D01* +X42762296Y-49614101D01* +X42871077Y-49544102D01* +X43015301Y-49688327D01* +X43248690Y-49785000D01* +X43464250Y-49785000D01* +X43623000Y-49626250D01* +X43623000Y-48877000D01* +X43603000Y-48877000D01* +X43603000Y-48623000D01* +X43623000Y-48623000D01* +X43623000Y-48603000D01* +X43877000Y-48603000D01* +X43877000Y-48623000D01* +X45623000Y-48623000D01* +X45623000Y-47773750D01* +X45877000Y-47773750D01* +X45877000Y-48623000D01* +X47026250Y-48623000D01* +X47185000Y-48464250D01* +X47185000Y-48400000D01* +X47543000Y-48400000D01* +X47593011Y-48651423D01* +X47735431Y-48864569D01* +X47948577Y-49006989D01* +X48200000Y-49057000D01* +X48700000Y-49057000D01* +X48951423Y-49006989D01* +X49164569Y-48864569D01* +X49264569Y-48764569D01* +X49406989Y-48551423D01* +X49457000Y-48300000D01* +X49406989Y-48048577D01* +X49264569Y-47835431D01* +X49051423Y-47693011D01* +X48800000Y-47643000D01* +X48548577Y-47693011D01* +X48473763Y-47743000D01* +X48200000Y-47743000D01* +X47948577Y-47793011D01* +X47735431Y-47935431D01* +X47593011Y-48148577D01* +X47543000Y-48400000D01* +X47185000Y-48400000D01* +X47185000Y-48123691D01* +X47088327Y-47890302D01* +X46909699Y-47711673D01* +X46676310Y-47615000D01* +X46035750Y-47615000D01* +X45877000Y-47773750D01* +X45623000Y-47773750D01* +X45464250Y-47615000D01* +X44823690Y-47615000D01* +X44590301Y-47711673D01* +X44487500Y-47814474D01* +X44484699Y-47811673D01* +X44455012Y-47799376D01* +X44460316Y-47791614D01* +X44488994Y-47650000D01* +X44488994Y-47440144D01* +X45315144Y-46613994D01* +X46550000Y-46613994D01* +X46682296Y-46589101D01* +X46803802Y-46510914D01* +X46885316Y-46391614D01* +X46913994Y-46250000D01* +X46913994Y-45250000D01* +X46889101Y-45117704D01* +X46810914Y-44996198D01* +X46691614Y-44914684D01* +X46550000Y-44886006D01* +X45815144Y-44886006D01* +X44383696Y-43454558D01* +X44383696Y-42879994D01* +X44742696Y-42879994D01* +X44874992Y-42855101D01* +X44996498Y-42776914D01* +X45078012Y-42657614D01* +X45106690Y-42516000D01* +X45106690Y-42214677D01* +X45295838Y-42497757D01* +X45741272Y-42795386D01* +X46266696Y-42899899D01* +X46792120Y-42795386D01* +X47237554Y-42497757D01* +X47535183Y-42052323D01* +X47639696Y-41526899D01* +X47639696Y-41473101D01* +X47535183Y-40947677D01* +X47237554Y-40502243D01* +X46792120Y-40204614D01* +X46266696Y-40100101D01* +X45741272Y-40204614D01* +X45295838Y-40502243D01* +X45106690Y-40785323D01* +X45106690Y-40484000D01* +X45081797Y-40351704D01* +X45003610Y-40230198D01* +X44884310Y-40148684D01* +X44742696Y-40120006D01* +X44258696Y-40120006D01* +X44258696Y-37644664D01* +X44365000Y-37538360D01* +X44365000Y-37726310D01* +X44461673Y-37959699D01* +X44640302Y-38138327D01* +X44873691Y-38235000D01* +X45014250Y-38235000D01* +X45173000Y-38076250D01* +X45173000Y-37277000D01* +X45153000Y-37277000D01* +X45153000Y-37023000D01* +X45173000Y-37023000D01* +X45173000Y-37003000D01* +X45427000Y-37003000D01* +X45427000Y-37023000D01* +X45447000Y-37023000D01* +X45447000Y-37277000D01* +X45427000Y-37277000D01* +X45427000Y-38076250D01* +X45585750Y-38235000D01* +X45644907Y-38235000D01* +X45742698Y-38471674D01* +X45927354Y-38656652D01* +X46168741Y-38756885D01* +X46430112Y-38757113D01* +X46671674Y-38657302D01* +X46856652Y-38472646D01* +X46955332Y-38235000D01* +X47014250Y-38235000D01* +X47173000Y-38076250D01* +X47173000Y-37277000D01* +X47153000Y-37277000D01* +X47153000Y-37023000D01* +X47173000Y-37023000D01* +X47173000Y-37003000D01* +X47427000Y-37003000D01* +X47427000Y-37023000D01* +X47447000Y-37023000D01* +X47447000Y-37277000D01* +X47427000Y-37277000D01* +X47427000Y-38076250D01* +X47585750Y-38235000D01* +X47726309Y-38235000D01* +X47959698Y-38138327D01* +X48134032Y-37963994D01* +X48465968Y-37963994D01* +X48640302Y-38138327D01* +X48873691Y-38235000D01* +X49014250Y-38235000D01* +X49173000Y-38076250D01* +X49173000Y-37277000D01* +X49427000Y-37277000D01* +X49427000Y-38076250D01* +X49585750Y-38235000D01* +X49726309Y-38235000D01* +X49959698Y-38138327D01* +X50138327Y-37959699D01* +X50235000Y-37726310D01* +X50235000Y-37435750D01* +X50076250Y-37277000D01* +X49427000Y-37277000D01* +X49173000Y-37277000D01* +X49153000Y-37277000D01* +X49153000Y-37023000D01* +X49173000Y-37023000D01* +X49173000Y-37003000D01* +X49427000Y-37003000D01* +X49427000Y-37023000D01* +X50076250Y-37023000D01* +X50235000Y-36864250D01* +X50235000Y-36635750D01* +X50290000Y-36635750D01* +X50290000Y-36876309D01* +X50386673Y-37109698D01* +X50565301Y-37288327D01* +X50798690Y-37385000D01* +X51014250Y-37385000D01* +X51173000Y-37226250D01* +X51173000Y-36477000D01* +X50448750Y-36477000D01* +X50290000Y-36635750D01* +X50235000Y-36635750D01* +X50235000Y-36573690D01* +X50138327Y-36340301D01* +X49959698Y-36161673D01* +X49727825Y-36065628D01* +X50291378Y-36065628D01* +X50448750Y-36223000D01* +X51173000Y-36223000D01* +X51173000Y-36203000D01* +X51427000Y-36203000D01* +X51427000Y-36223000D01* +X51447000Y-36223000D01* +X51447000Y-36477000D01* +X51427000Y-36477000D01* +X51427000Y-37226250D01* +X51585750Y-37385000D01* +X51801310Y-37385000D01* +X52034699Y-37288327D01* +X52213327Y-37109698D01* +X52310000Y-36876309D01* +X52310000Y-36808601D01* +X52339086Y-36853802D01* +X52458386Y-36935316D01* +X52600000Y-36963994D01* +X53500000Y-36963994D01* +X53632296Y-36939101D01* +X53753802Y-36860914D01* +X53835316Y-36741614D01* +X53863994Y-36600000D01* +X53863994Y-36100000D01* +X53839101Y-35967704D01* +X53760914Y-35846198D01* +X53641614Y-35764684D01* +X53500000Y-35736006D01* +X52882302Y-35736006D01* +X52610290Y-35463994D01* +X53500000Y-35463994D01* +X53632296Y-35439101D01* +X53753802Y-35360914D01* +X53835316Y-35241614D01* +X53863994Y-35100000D01* +X53863994Y-34600000D01* +X53839101Y-34467704D01* +X53760914Y-34346198D01* +X53641614Y-34264684D01* +X53500000Y-34236006D01* +X52600000Y-34236006D01* +X52467704Y-34260899D01* +X52378967Y-34318000D01* +X52014157Y-34318000D01* +X52014101Y-34317704D01* +X51935914Y-34196198D01* +X51816614Y-34114684D01* +X51675000Y-34086006D01* +X50925000Y-34086006D01* +X50792704Y-34110899D01* +X50671198Y-34189086D01* +X50668524Y-34193000D01* +X50372138Y-34193000D01* +X49963994Y-33784856D01* +X49963994Y-33600000D01* +X49939101Y-33467704D01* +X49860914Y-33346198D01* +X49832000Y-33326442D01* +X49832000Y-33250005D01* +X49832001Y-33250000D01* +X49791505Y-33046413D01* +X49676181Y-32873819D01* +X47502362Y-30700000D01* +X50896883Y-27305479D01* +X50926660Y-27260914D01* +X51012206Y-27132886D01* +X51052702Y-26929298D01* +X51052702Y-24571402D01* +X51149504Y-24509112D01* +X51231018Y-24389812D01* +X51243090Y-24330198D01* +X51547137Y-24330198D01* +X51556601Y-24380494D01* +X51634788Y-24502000D01* +X51754088Y-24583514D01* +X51895702Y-24612192D01* +X52645702Y-24612192D01* +X52777998Y-24587299D01* +X52899504Y-24509112D01* +X52981018Y-24389812D01* +X53009696Y-24248198D01* +X53009696Y-23448198D01* +X52984803Y-23315902D01* +X52974212Y-23299444D01* +X53005401Y-23286525D01* +X53184029Y-23107896D01* +X53280702Y-22874507D01* +X53280702Y-22633948D01* +X53121952Y-22475198D01* +X52397702Y-22475198D01* +X52397702Y-22495198D01* +X52143702Y-22495198D01* +X52143702Y-22475198D01* +X51419452Y-22475198D01* +X51395702Y-22498948D01* +X51371952Y-22475198D01* +X50647702Y-22475198D01* +X50647702Y-22495198D01* +X50393702Y-22495198D01* +X50393702Y-22475198D01* +X50373702Y-22475198D01* +X50373702Y-22221198D01* +X50393702Y-22221198D01* +X50393702Y-21471948D01* +X50647702Y-21471948D01* +X50647702Y-22221198D01* +X51371952Y-22221198D01* +X51395702Y-22197448D01* +X51419452Y-22221198D01* +X52143702Y-22221198D01* +X52143702Y-21471948D01* +X52397702Y-21471948D01* +X52397702Y-22221198D01* +X53121952Y-22221198D01* +X53280702Y-22062448D01* +X53280702Y-21821889D01* +X53184029Y-21588500D01* +X53005401Y-21409871D01* +X52772012Y-21313198D01* +X52556452Y-21313198D01* +X52397702Y-21471948D01* +X52143702Y-21471948D01* +X51984952Y-21313198D01* +X51769392Y-21313198D01* +X51536003Y-21409871D01* +X51395702Y-21550173D01* +X51255401Y-21409871D01* +X51022012Y-21313198D01* +X50806452Y-21313198D01* +X50647702Y-21471948D01* +X50393702Y-21471948D01* +X50234952Y-21313198D01* +X50019392Y-21313198D01* +X49786003Y-21409871D01* +X49695702Y-21500173D01* +X49655400Y-21459871D01* +X49422011Y-21363198D01* +X49306452Y-21363198D01* +X49147702Y-21521948D01* +X49147702Y-22034204D01* +X48971171Y-22034204D01* +X48958356Y-22003266D01* +X48984696Y-21873198D01* +X48984696Y-21323198D01* +X48959803Y-21190902D01* +X48881616Y-21069396D01* +X48771817Y-20994374D01* +X48759029Y-20963500D01* +X48580401Y-20784871D01* +X48347012Y-20688198D01* +X48329452Y-20688198D01* +X48170702Y-20846948D01* +X48170702Y-21059837D01* +X48166900Y-21062284D01* +X48120622Y-21130014D01* +X48081616Y-21069396D01* +X48070702Y-21061939D01* +X48070702Y-20846948D01* +X47911952Y-20688198D01* +X47894392Y-20688198D01* +X47661003Y-20784871D01* +X47482375Y-20963500D01* +X47479244Y-20971059D01* +X47420702Y-20959204D01* +X47375925Y-20959204D01* +X47342915Y-20793254D01* +X47314014Y-20750000D01* +X47243850Y-20644992D01* +X47243847Y-20644990D01* +X46930858Y-20332000D01* +X52000000Y-20332000D01* +X52015224Y-20328972D01* +X52030624Y-20330913D01* +X52097403Y-20312625D01* +X52165319Y-20299116D01* +X52178227Y-20290491D01* +X52193196Y-20286392D01* +X52247894Y-20243941D01* +X52305470Y-20205470D01* +X52314094Y-20192564D01* +X52326356Y-20183047D01* +X52360646Y-20122893D01* +X52399116Y-20065319D01* +X52402144Y-20050094D01* +X52409831Y-20036610D01* +X52418491Y-19967915D01* +X52432000Y-19900000D01* +X52428972Y-19884776D01* +X52430913Y-19869376D01* +X52412625Y-19802597D01* +X52399116Y-19734681D01* +X52390491Y-19721773D01* +X52386392Y-19706804D01* +X51486393Y-17906804D01* +X51443938Y-17852101D01* +X51405470Y-17794530D01* +X51392564Y-17785906D01* +X51383047Y-17773644D01* +X51322893Y-17739354D01* +X51265319Y-17700884D01* +X51250094Y-17697856D01* +X51236610Y-17690169D01* +X51167915Y-17681509D01* +X51100000Y-17668000D01* +X23900000Y-17668000D01* +X23832085Y-17681509D01* +X23763390Y-17690169D01* +X23749906Y-17697856D01* +X23734681Y-17700884D01* +X23677107Y-17739354D01* +X23616953Y-17773644D01* +X23607436Y-17785906D01* +X23594530Y-17794530D01* +X23556062Y-17852101D01* +X23513607Y-17906804D01* +X22613607Y-19706804D01* +X22609507Y-19721776D01* +X22600884Y-19734681D01* +X22593262Y-19773000D01* +X20546491Y-19773000D01* +X22266991Y-16332000D01* +X52733009Y-16332000D01* +X54568000Y-20001982D01* +X54568000Y-20001982D01* +G37* +X54568000Y-20001982D02* +X54568000Y-50198018D01* +X52733009Y-53868000D01* +X22266991Y-53868000D01* +X20432000Y-50198018D01* +X20432000Y-49436837D01* +X20445172Y-49463663D01* +X20785862Y-49750902D01* +X21210540Y-49885900D01* +X21485540Y-49885900D01* +X21485540Y-48877900D01* +X21739540Y-48877900D01* +X21739540Y-49885900D01* +X22014540Y-49885900D01* +X22439218Y-49750902D01* +X22779908Y-49463663D01* +X22981659Y-49052774D01* +X22969377Y-49035750D01* +X25740000Y-49035750D01* +X25740000Y-49276309D01* +X25836673Y-49509698D01* +X26015301Y-49688327D01* +X26248690Y-49785000D01* +X26464250Y-49785000D01* +X26623000Y-49626250D01* +X26623000Y-48877000D01* +X25898750Y-48877000D01* +X25740000Y-49035750D01* +X22969377Y-49035750D01* +X22855494Y-48877900D01* +X21739540Y-48877900D01* +X21485540Y-48877900D01* +X21465540Y-48877900D01* +X21465540Y-48623900D01* +X21485540Y-48623900D01* +X21485540Y-47615900D01* +X21739540Y-47615900D01* +X21739540Y-48623900D01* +X22855494Y-48623900D01* +X22981659Y-48449026D01* +X22786731Y-48052031D01* +X23211311Y-48052031D01* +X23352972Y-48461949D01* +X23640719Y-48786452D01* +X24014602Y-48970168D01* +X24185540Y-48843634D01* +X24185540Y-47877900D01* +X24439540Y-47877900D01* +X24439540Y-48843634D01* +X24610478Y-48970168D01* +X24984361Y-48786452D01* +X25272108Y-48461949D01* +X25413769Y-48052031D01* +X25265103Y-47877900D01* +X24439540Y-47877900D01* +X24185540Y-47877900D01* +X23359977Y-47877900D01* +X23211311Y-48052031D01* +X22786731Y-48052031D01* +X22779908Y-48038137D01* +X22439218Y-47750898D01* +X22014540Y-47615900D01* +X21739540Y-47615900D01* +X21485540Y-47615900D01* +X21210540Y-47615900D01* +X20785862Y-47750898D01* +X20445172Y-48038137D01* +X20432000Y-48064963D01* +X20432000Y-43052031D01* +X23211311Y-43052031D01* +X23352972Y-43461949D01* +X23358637Y-43468338D01* +X23336673Y-43490302D01* +X23240000Y-43723691D01* +X23240000Y-43964250D01* +X23398750Y-44123000D01* +X24123000Y-44123000D01* +X24123000Y-43889928D01* +X24185540Y-43843634D01* +X24185540Y-42877900D01* +X23359977Y-42877900D01* +X23211311Y-43052031D01* +X20432000Y-43052031D01* +X20432000Y-42436837D01* +X20445172Y-42463663D01* +X20785862Y-42750902D01* +X21210540Y-42885900D01* +X21485540Y-42885900D01* +X21485540Y-41877900D01* +X21739540Y-41877900D01* +X21739540Y-42885900D01* +X22014540Y-42885900D01* +X22439218Y-42750902D01* +X22779908Y-42463663D01* +X22981659Y-42052774D01* +X22855494Y-41877900D01* +X21739540Y-41877900D01* +X21485540Y-41877900D01* +X21465540Y-41877900D01* +X21465540Y-41623900D01* +X21485540Y-41623900D01* +X21485540Y-41603900D01* +X21739540Y-41603900D01* +X21739540Y-41623900D01* +X22855494Y-41623900D01* +X22981659Y-41449026D01* +X22779908Y-41038137D01* +X22627927Y-40910000D01* +X22826309Y-40910000D01* +X23059698Y-40813327D01* +X23238327Y-40634699D01* +X23250624Y-40605012D01* +X23258386Y-40610316D01* +X23343000Y-40627451D01* +X23343000Y-40819602D01* +X23377787Y-40994489D01* +X23476852Y-41142750D01* +X23914783Y-41580681D01* +X23640719Y-41715348D01* +X23352972Y-42039851D01* +X23211311Y-42449769D01* +X23359977Y-42623900D01* +X24185540Y-42623900D01* +X24185540Y-42603900D01* +X24439540Y-42603900D01* +X24439540Y-42623900D01* +X24459540Y-42623900D01* +X24459540Y-42877900D01* +X24439540Y-42877900D01* +X24439540Y-43311210D01* +X24377000Y-43373750D01* +X24377000Y-44123000D01* +X25101250Y-44123000D01* +X25260000Y-43964250D01* +X25260000Y-43723691D01* +X25189957Y-43554593D01* +X25272108Y-43461949D01* +X25406672Y-43072569D01* +X25657248Y-43323145D01* +X25657250Y-43323148D01* +X25805512Y-43422213D01* +X25980398Y-43457000D01* +X26603533Y-43457000D01* +X26608386Y-43460316D01* +X26750000Y-43488994D01* +X27114744Y-43488994D01* +X27148750Y-43523000D01* +X27438654Y-43523000D01* +X27648690Y-43610000D01* +X27761006Y-43610000D01* +X27761006Y-44000000D01* +X27785899Y-44132296D01* +X27812500Y-44173635D01* +X27812500Y-44476250D01* +X27971250Y-44635000D01* +X27981908Y-44635000D01* +X27914684Y-44733386D01* +X27886006Y-44875000D01* +X27886006Y-45434856D01* +X27613994Y-45706868D01* +X27613994Y-44875000D01* +X27589101Y-44742704D01* +X27519795Y-44635000D01* +X27528750Y-44635000D01* +X27687500Y-44476250D01* +X27687500Y-43777000D01* +X27148750Y-43777000D01* +X26990000Y-43935750D01* +X26990000Y-44126309D01* +X27086673Y-44359698D01* +X27237980Y-44511006D01* +X26250000Y-44511006D01* +X26117704Y-44535899D01* +X25996198Y-44614086D01* +X25914684Y-44733386D01* +X25886006Y-44875000D01* +X25886006Y-45434856D01* +X25625000Y-45695862D01* +X25214569Y-45285431D01* +X25018563Y-45154463D01* +X25163327Y-45009698D01* +X25260000Y-44776309D01* +X25260000Y-44535750D01* +X25101250Y-44377000D01* +X24377000Y-44377000D01* +X24377000Y-44397000D01* +X24123000Y-44397000D01* +X24123000Y-44377000D01* +X23398750Y-44377000D01* +X23240000Y-44535750D01* +X23240000Y-44776309D01* +X23336673Y-45009698D01* +X23515301Y-45188327D01* +X23544988Y-45200624D01* +X23539684Y-45208386D01* +X23511006Y-45350000D01* +X23511006Y-46150000D01* +X23535899Y-46282296D01* +X23614086Y-46403802D01* +X23733386Y-46485316D01* +X23875000Y-46513994D01* +X24185538Y-46513994D01* +X24185538Y-46658165D01* +X24014602Y-46531632D01* +X23640719Y-46715348D01* +X23352972Y-47039851D01* +X23211311Y-47449769D01* +X23359977Y-47623900D01* +X24185540Y-47623900D01* +X24185540Y-47603900D01* +X24439540Y-47603900D01* +X24439540Y-47623900D01* +X25265103Y-47623900D01* +X25413769Y-47449769D01* +X25303139Y-47129645D01* +X25368741Y-47156885D01* +X25499997Y-47156999D01* +X25500000Y-47157000D01* +X25500573Y-47157000D01* +X25630112Y-47157113D01* +X25630385Y-47157000D01* +X25750000Y-47157000D01* +X26001423Y-47106989D01* +X26011006Y-47100586D01* +X26011006Y-47650000D01* +X26035899Y-47782296D01* +X26046490Y-47798754D01* +X26015301Y-47811673D01* +X25836673Y-47990302D01* +X25740000Y-48223691D01* +X25740000Y-48464250D01* +X25898750Y-48623000D01* +X26623000Y-48623000D01* +X26623000Y-48603000D01* +X26877000Y-48603000D01* +X26877000Y-48623000D01* +X26897000Y-48623000D01* +X26897000Y-48877000D01* +X26877000Y-48877000D01* +X26877000Y-49626250D01* +X27035750Y-49785000D01* +X27251310Y-49785000D01* +X27484699Y-49688327D01* +X27663327Y-49509698D01* +X27691789Y-49440984D01* +X27761673Y-49609698D01* +X27940301Y-49788327D01* +X28132648Y-49868000D01* +X23000000Y-49868000D01* +X22984776Y-49871028D01* +X22969376Y-49869087D01* +X22902592Y-49887376D01* +X22834681Y-49900884D01* +X22821776Y-49909507D01* +X22806804Y-49913607D01* +X22752101Y-49956062D01* +X22694530Y-49994530D01* +X22685906Y-50007436D01* +X22673644Y-50016953D01* +X22639354Y-50077107D01* +X22600884Y-50134681D01* +X22597856Y-50149906D01* +X22590169Y-50163390D01* +X22581509Y-50232085D01* +X22568000Y-50300000D01* +X22571028Y-50315224D01* +X22569087Y-50330624D01* +X22587376Y-50397408D01* +X22600884Y-50465319D01* +X22609507Y-50478224D01* +X22613607Y-50493196D01* +X23513607Y-52293196D01* +X23556062Y-52347899D01* +X23594530Y-52405470D01* +X23607436Y-52414094D01* +X23616953Y-52426356D01* +X23677107Y-52460646D01* +X23734681Y-52499116D01* +X23749906Y-52502144D01* +X23763390Y-52509831D01* +X23832085Y-52518491D01* +X23900000Y-52532000D01* +X51100000Y-52532000D01* +X51167915Y-52518491D01* +X51236610Y-52509831D01* +X51250094Y-52502144D01* +X51265319Y-52499116D01* +X51322893Y-52460646D01* +X51383047Y-52426356D01* +X51392564Y-52414094D01* +X51405470Y-52405470D01* +X51443938Y-52347899D01* +X51486393Y-52293196D01* +X52386392Y-50493196D01* +X52390491Y-50478227D01* +X52399116Y-50465319D01* +X52412625Y-50397403D01* +X52430913Y-50330624D01* +X52428972Y-50315224D01* +X52432000Y-50300000D01* +X52418491Y-50232085D01* +X52409831Y-50163390D01* +X52402144Y-50149906D01* +X52399116Y-50134681D01* +X52360646Y-50077107D01* +X52326356Y-50016953D01* +X52314094Y-50007436D01* +X52305470Y-49994530D01* +X52247894Y-49956059D01* +X52193196Y-49913608D01* +X52178227Y-49909509D01* +X52165319Y-49900884D01* +X52097403Y-49887375D01* +X52030624Y-49869087D01* +X52015224Y-49871028D01* +X52000000Y-49868000D01* +X46717352Y-49868000D01* +X46909699Y-49788327D01* +X47088327Y-49609698D01* +X47185000Y-49376309D01* +X47185000Y-49035750D01* +X47026250Y-48877000D01* +X45877000Y-48877000D01* +X45877000Y-48897000D01* +X45623000Y-48897000D01* +X45623000Y-48877000D01* +X43877000Y-48877000D01* +X43877000Y-49626250D01* +X44035750Y-49785000D01* +X44251310Y-49785000D01* +X44484699Y-49688327D01* +X44487500Y-49685526D01* +X44590301Y-49788327D01* +X44782648Y-49868000D01* +X29367352Y-49868000D01* +X29559699Y-49788327D01* +X29736139Y-49611886D01* +X29870000Y-49638994D01* +X30930000Y-49638994D01* +X31062296Y-49614101D01* +X31183802Y-49535914D01* +X31265316Y-49416614D01* +X31293994Y-49275000D01* +X31293994Y-49190290D01* +X31376852Y-49273148D01* +X31525114Y-49372213D01* +X31700000Y-49407000D01* +X31730843Y-49407000D01* +X31730899Y-49407296D01* +X31809086Y-49528802D01* +X31928386Y-49610316D01* +X32070000Y-49638994D01* +X33130000Y-49638994D01* +X33262296Y-49614101D01* +X33383802Y-49535914D01* +X33465316Y-49416614D01* +X33493994Y-49275000D01* +X33493994Y-48859031D01* +X33668327Y-48684699D01* +X33765000Y-48451310D01* +X33765000Y-48285750D01* +X33606250Y-48127000D01* +X32727000Y-48127000D01* +X32727000Y-48147000D01* +X32473000Y-48147000D01* +X32473000Y-48127000D01* +X32453000Y-48127000D01* +X32453000Y-48035750D01* +X33849000Y-48035750D01* +X33849000Y-48892310D01* +X33945673Y-49125699D01* +X34124302Y-49304327D01* +X34357691Y-49401000D01* +X35214250Y-49401000D01* +X35373000Y-49242250D01* +X35373000Y-47877000D01* +X34007750Y-47877000D01* +X33849000Y-48035750D01* +X32453000Y-48035750D01* +X32453000Y-47873000D01* +X32473000Y-47873000D01* +X32473000Y-47853000D01* +X32727000Y-47853000D01* +X32727000Y-47873000D01* +X33606250Y-47873000D01* +X33765000Y-47714250D01* +X33765000Y-47548690D01* +X33668327Y-47315301D01* +X33493994Y-47140969D01* +X33493994Y-47085144D01* +X33849000Y-46730138D01* +X33849000Y-47464250D01* +X34007750Y-47623000D01* +X35373000Y-47623000D01* +X35373000Y-47603000D01* +X35627000Y-47603000D01* +X35627000Y-47623000D01* +X36992250Y-47623000D01* +X37151000Y-47464250D01* +X37151000Y-47330138D01* +X37261006Y-47440144D01* +X37261006Y-47650000D01* +X37285899Y-47782296D01* +X37296490Y-47798754D01* +X37265301Y-47811673D01* +X37096112Y-47980862D01* +X36992250Y-47877000D01* +X35627000Y-47877000D01* +X35627000Y-49242250D01* +X35785750Y-49401000D01* +X36642309Y-49401000D01* +X36875698Y-49304327D01* +X36990000Y-49190026D01* +X36990000Y-49276309D01* +X37086673Y-49509698D01* +X37265301Y-49688327D01* +X37498690Y-49785000D01* +X37714250Y-49785000D01* +X37873000Y-49626250D01* +X37873000Y-48877000D01* +X37853000Y-48877000D01* +X37853000Y-48623000D01* +X37873000Y-48623000D01* +X37873000Y-48603000D01* +X38127000Y-48603000D01* +X38127000Y-48623000D01* +X38147000Y-48623000D01* +X38147000Y-48877000D01* +X38127000Y-48877000D01* +X38127000Y-49626250D01* +X38285750Y-49785000D01* +X38501310Y-49785000D01* +X38734699Y-49688327D01* +X38913327Y-49509698D01* +X39007423Y-49282531D01* +X39030899Y-49407296D01* +X39109086Y-49528802D01* +X39228386Y-49610316D01* +X39370000Y-49638994D01* +X40430000Y-49638994D01* +X40562296Y-49614101D01* +X40642075Y-49562765D01* +X40868741Y-49656885D01* +X41130112Y-49657113D01* +X41358664Y-49562677D01* +X41428386Y-49610316D01* +X41570000Y-49638994D01* +X42630000Y-49638994D01* +X42762296Y-49614101D01* +X42871077Y-49544102D01* +X43015301Y-49688327D01* +X43248690Y-49785000D01* +X43464250Y-49785000D01* +X43623000Y-49626250D01* +X43623000Y-48877000D01* +X43603000Y-48877000D01* +X43603000Y-48623000D01* +X43623000Y-48623000D01* +X43623000Y-48603000D01* +X43877000Y-48603000D01* +X43877000Y-48623000D01* +X45623000Y-48623000D01* +X45623000Y-47773750D01* +X45877000Y-47773750D01* +X45877000Y-48623000D01* +X47026250Y-48623000D01* +X47185000Y-48464250D01* +X47185000Y-48400000D01* +X47543000Y-48400000D01* +X47593011Y-48651423D01* +X47735431Y-48864569D01* +X47948577Y-49006989D01* +X48200000Y-49057000D01* +X48700000Y-49057000D01* +X48951423Y-49006989D01* +X49164569Y-48864569D01* +X49264569Y-48764569D01* +X49406989Y-48551423D01* +X49457000Y-48300000D01* +X49406989Y-48048577D01* +X49264569Y-47835431D01* +X49051423Y-47693011D01* +X48800000Y-47643000D01* +X48548577Y-47693011D01* +X48473763Y-47743000D01* +X48200000Y-47743000D01* +X47948577Y-47793011D01* +X47735431Y-47935431D01* +X47593011Y-48148577D01* +X47543000Y-48400000D01* +X47185000Y-48400000D01* +X47185000Y-48123691D01* +X47088327Y-47890302D01* +X46909699Y-47711673D01* +X46676310Y-47615000D01* +X46035750Y-47615000D01* +X45877000Y-47773750D01* +X45623000Y-47773750D01* +X45464250Y-47615000D01* +X44823690Y-47615000D01* +X44590301Y-47711673D01* +X44487500Y-47814474D01* +X44484699Y-47811673D01* +X44455012Y-47799376D01* +X44460316Y-47791614D01* +X44488994Y-47650000D01* +X44488994Y-47440144D01* +X45315144Y-46613994D01* +X46550000Y-46613994D01* +X46682296Y-46589101D01* +X46803802Y-46510914D01* +X46885316Y-46391614D01* +X46913994Y-46250000D01* +X46913994Y-45250000D01* +X46889101Y-45117704D01* +X46810914Y-44996198D01* +X46691614Y-44914684D01* +X46550000Y-44886006D01* +X45815144Y-44886006D01* +X44383696Y-43454558D01* +X44383696Y-42879994D01* +X44742696Y-42879994D01* +X44874992Y-42855101D01* +X44996498Y-42776914D01* +X45078012Y-42657614D01* +X45106690Y-42516000D01* +X45106690Y-42214677D01* +X45295838Y-42497757D01* +X45741272Y-42795386D01* +X46266696Y-42899899D01* +X46792120Y-42795386D01* +X47237554Y-42497757D01* +X47535183Y-42052323D01* +X47639696Y-41526899D01* +X47639696Y-41473101D01* +X47535183Y-40947677D01* +X47237554Y-40502243D01* +X46792120Y-40204614D01* +X46266696Y-40100101D01* +X45741272Y-40204614D01* +X45295838Y-40502243D01* +X45106690Y-40785323D01* +X45106690Y-40484000D01* +X45081797Y-40351704D01* +X45003610Y-40230198D01* +X44884310Y-40148684D01* +X44742696Y-40120006D01* +X44258696Y-40120006D01* +X44258696Y-37644664D01* +X44365000Y-37538360D01* +X44365000Y-37726310D01* +X44461673Y-37959699D01* +X44640302Y-38138327D01* +X44873691Y-38235000D01* +X45014250Y-38235000D01* +X45173000Y-38076250D01* +X45173000Y-37277000D01* +X45153000Y-37277000D01* +X45153000Y-37023000D01* +X45173000Y-37023000D01* +X45173000Y-37003000D01* +X45427000Y-37003000D01* +X45427000Y-37023000D01* +X45447000Y-37023000D01* +X45447000Y-37277000D01* +X45427000Y-37277000D01* +X45427000Y-38076250D01* +X45585750Y-38235000D01* +X45644907Y-38235000D01* +X45742698Y-38471674D01* +X45927354Y-38656652D01* +X46168741Y-38756885D01* +X46430112Y-38757113D01* +X46671674Y-38657302D01* +X46856652Y-38472646D01* +X46955332Y-38235000D01* +X47014250Y-38235000D01* +X47173000Y-38076250D01* +X47173000Y-37277000D01* +X47153000Y-37277000D01* +X47153000Y-37023000D01* +X47173000Y-37023000D01* +X47173000Y-37003000D01* +X47427000Y-37003000D01* +X47427000Y-37023000D01* +X47447000Y-37023000D01* +X47447000Y-37277000D01* +X47427000Y-37277000D01* +X47427000Y-38076250D01* +X47585750Y-38235000D01* +X47726309Y-38235000D01* +X47959698Y-38138327D01* +X48134032Y-37963994D01* +X48465968Y-37963994D01* +X48640302Y-38138327D01* +X48873691Y-38235000D01* +X49014250Y-38235000D01* +X49173000Y-38076250D01* +X49173000Y-37277000D01* +X49427000Y-37277000D01* +X49427000Y-38076250D01* +X49585750Y-38235000D01* +X49726309Y-38235000D01* +X49959698Y-38138327D01* +X50138327Y-37959699D01* +X50235000Y-37726310D01* +X50235000Y-37435750D01* +X50076250Y-37277000D01* +X49427000Y-37277000D01* +X49173000Y-37277000D01* +X49153000Y-37277000D01* +X49153000Y-37023000D01* +X49173000Y-37023000D01* +X49173000Y-37003000D01* +X49427000Y-37003000D01* +X49427000Y-37023000D01* +X50076250Y-37023000D01* +X50235000Y-36864250D01* +X50235000Y-36635750D01* +X50290000Y-36635750D01* +X50290000Y-36876309D01* +X50386673Y-37109698D01* +X50565301Y-37288327D01* +X50798690Y-37385000D01* +X51014250Y-37385000D01* +X51173000Y-37226250D01* +X51173000Y-36477000D01* +X50448750Y-36477000D01* +X50290000Y-36635750D01* +X50235000Y-36635750D01* +X50235000Y-36573690D01* +X50138327Y-36340301D01* +X49959698Y-36161673D01* +X49727825Y-36065628D01* +X50291378Y-36065628D01* +X50448750Y-36223000D01* +X51173000Y-36223000D01* +X51173000Y-36203000D01* +X51427000Y-36203000D01* +X51427000Y-36223000D01* +X51447000Y-36223000D01* +X51447000Y-36477000D01* +X51427000Y-36477000D01* +X51427000Y-37226250D01* +X51585750Y-37385000D01* +X51801310Y-37385000D01* +X52034699Y-37288327D01* +X52213327Y-37109698D01* +X52310000Y-36876309D01* +X52310000Y-36808601D01* +X52339086Y-36853802D01* +X52458386Y-36935316D01* +X52600000Y-36963994D01* +X53500000Y-36963994D01* +X53632296Y-36939101D01* +X53753802Y-36860914D01* +X53835316Y-36741614D01* +X53863994Y-36600000D01* +X53863994Y-36100000D01* +X53839101Y-35967704D01* +X53760914Y-35846198D01* +X53641614Y-35764684D01* +X53500000Y-35736006D01* +X52882302Y-35736006D01* +X52610290Y-35463994D01* +X53500000Y-35463994D01* +X53632296Y-35439101D01* +X53753802Y-35360914D01* +X53835316Y-35241614D01* +X53863994Y-35100000D01* +X53863994Y-34600000D01* +X53839101Y-34467704D01* +X53760914Y-34346198D01* +X53641614Y-34264684D01* +X53500000Y-34236006D01* +X52600000Y-34236006D01* +X52467704Y-34260899D01* +X52378967Y-34318000D01* +X52014157Y-34318000D01* +X52014101Y-34317704D01* +X51935914Y-34196198D01* +X51816614Y-34114684D01* +X51675000Y-34086006D01* +X50925000Y-34086006D01* +X50792704Y-34110899D01* +X50671198Y-34189086D01* +X50668524Y-34193000D01* +X50372138Y-34193000D01* +X49963994Y-33784856D01* +X49963994Y-33600000D01* +X49939101Y-33467704D01* +X49860914Y-33346198D01* +X49832000Y-33326442D01* +X49832000Y-33250005D01* +X49832001Y-33250000D01* +X49791505Y-33046413D01* +X49676181Y-32873819D01* +X47502362Y-30700000D01* +X50896883Y-27305479D01* +X50926660Y-27260914D01* +X51012206Y-27132886D01* +X51052702Y-26929298D01* +X51052702Y-24571402D01* +X51149504Y-24509112D01* +X51231018Y-24389812D01* +X51243090Y-24330198D01* +X51547137Y-24330198D01* +X51556601Y-24380494D01* +X51634788Y-24502000D01* +X51754088Y-24583514D01* +X51895702Y-24612192D01* +X52645702Y-24612192D01* +X52777998Y-24587299D01* +X52899504Y-24509112D01* +X52981018Y-24389812D01* +X53009696Y-24248198D01* +X53009696Y-23448198D01* +X52984803Y-23315902D01* +X52974212Y-23299444D01* +X53005401Y-23286525D01* +X53184029Y-23107896D01* +X53280702Y-22874507D01* +X53280702Y-22633948D01* +X53121952Y-22475198D01* +X52397702Y-22475198D01* +X52397702Y-22495198D01* +X52143702Y-22495198D01* +X52143702Y-22475198D01* +X51419452Y-22475198D01* +X51395702Y-22498948D01* +X51371952Y-22475198D01* +X50647702Y-22475198D01* +X50647702Y-22495198D01* +X50393702Y-22495198D01* +X50393702Y-22475198D01* +X50373702Y-22475198D01* +X50373702Y-22221198D01* +X50393702Y-22221198D01* +X50393702Y-21471948D01* +X50647702Y-21471948D01* +X50647702Y-22221198D01* +X51371952Y-22221198D01* +X51395702Y-22197448D01* +X51419452Y-22221198D01* +X52143702Y-22221198D01* +X52143702Y-21471948D01* +X52397702Y-21471948D01* +X52397702Y-22221198D01* +X53121952Y-22221198D01* +X53280702Y-22062448D01* +X53280702Y-21821889D01* +X53184029Y-21588500D01* +X53005401Y-21409871D01* +X52772012Y-21313198D01* +X52556452Y-21313198D01* +X52397702Y-21471948D01* +X52143702Y-21471948D01* +X51984952Y-21313198D01* +X51769392Y-21313198D01* +X51536003Y-21409871D01* +X51395702Y-21550173D01* +X51255401Y-21409871D01* +X51022012Y-21313198D01* +X50806452Y-21313198D01* +X50647702Y-21471948D01* +X50393702Y-21471948D01* +X50234952Y-21313198D01* +X50019392Y-21313198D01* +X49786003Y-21409871D01* +X49695702Y-21500173D01* +X49655400Y-21459871D01* +X49422011Y-21363198D01* +X49306452Y-21363198D01* +X49147702Y-21521948D01* +X49147702Y-22034204D01* +X48971171Y-22034204D01* +X48958356Y-22003266D01* +X48984696Y-21873198D01* +X48984696Y-21323198D01* +X48959803Y-21190902D01* +X48881616Y-21069396D01* +X48771817Y-20994374D01* +X48759029Y-20963500D01* +X48580401Y-20784871D01* +X48347012Y-20688198D01* +X48329452Y-20688198D01* +X48170702Y-20846948D01* +X48170702Y-21059837D01* +X48166900Y-21062284D01* +X48120622Y-21130014D01* +X48081616Y-21069396D01* +X48070702Y-21061939D01* +X48070702Y-20846948D01* +X47911952Y-20688198D01* +X47894392Y-20688198D01* +X47661003Y-20784871D01* +X47482375Y-20963500D01* +X47479244Y-20971059D01* +X47420702Y-20959204D01* +X47375925Y-20959204D01* +X47342915Y-20793254D01* +X47314014Y-20750000D01* +X47243850Y-20644992D01* +X47243847Y-20644990D01* +X46930858Y-20332000D01* +X52000000Y-20332000D01* +X52015224Y-20328972D01* +X52030624Y-20330913D01* +X52097403Y-20312625D01* +X52165319Y-20299116D01* +X52178227Y-20290491D01* +X52193196Y-20286392D01* +X52247894Y-20243941D01* +X52305470Y-20205470D01* +X52314094Y-20192564D01* +X52326356Y-20183047D01* +X52360646Y-20122893D01* +X52399116Y-20065319D01* +X52402144Y-20050094D01* +X52409831Y-20036610D01* +X52418491Y-19967915D01* +X52432000Y-19900000D01* +X52428972Y-19884776D01* +X52430913Y-19869376D01* +X52412625Y-19802597D01* +X52399116Y-19734681D01* +X52390491Y-19721773D01* +X52386392Y-19706804D01* +X51486393Y-17906804D01* +X51443938Y-17852101D01* +X51405470Y-17794530D01* +X51392564Y-17785906D01* +X51383047Y-17773644D01* +X51322893Y-17739354D01* +X51265319Y-17700884D01* +X51250094Y-17697856D01* +X51236610Y-17690169D01* +X51167915Y-17681509D01* +X51100000Y-17668000D01* +X23900000Y-17668000D01* +X23832085Y-17681509D01* +X23763390Y-17690169D01* +X23749906Y-17697856D01* +X23734681Y-17700884D01* +X23677107Y-17739354D01* +X23616953Y-17773644D01* +X23607436Y-17785906D01* +X23594530Y-17794530D01* +X23556062Y-17852101D01* +X23513607Y-17906804D01* +X22613607Y-19706804D01* +X22609507Y-19721776D01* +X22600884Y-19734681D01* +X22593262Y-19773000D01* +X20546491Y-19773000D01* +X22266991Y-16332000D01* +X52733009Y-16332000D01* +X54568000Y-20001982D01* +G36* +X28877000Y-48875000D02* +X28897000Y-48875000D01* +X28897000Y-49125000D01* +X28877000Y-49125000D01* +X28877000Y-49147000D01* +X28623000Y-49147000D01* +X28623000Y-49125000D01* +X28603000Y-49125000D01* +X28603000Y-48875000D01* +X28623000Y-48875000D01* +X28623000Y-48853000D01* +X28877000Y-48853000D01* +X28877000Y-48875000D01* +X28877000Y-48875000D01* +G37* +X28877000Y-48875000D02* +X28897000Y-48875000D01* +X28897000Y-49125000D01* +X28877000Y-49125000D01* +X28877000Y-49147000D01* +X28623000Y-49147000D01* +X28623000Y-49125000D01* +X28603000Y-49125000D01* +X28603000Y-48875000D01* +X28623000Y-48875000D01* +X28623000Y-48853000D01* +X28877000Y-48853000D01* +X28877000Y-48875000D01* +G36* +X42122999Y-33879999D02* +X42157786Y-34054886D01* +X42256851Y-34203147D01* +X43143010Y-35089306D01* +X43142887Y-35230112D01* +X43242698Y-35471674D01* +X43427354Y-35656652D01* +X43668741Y-35756885D01* +X43810713Y-35757009D01* +X43896853Y-35843149D01* +X44045114Y-35942214D01* +X44220001Y-35977001D01* +X44421635Y-35977001D01* +X43350515Y-37048121D01* +X43235192Y-37220714D01* +X43194696Y-37424302D01* +X43194696Y-40120006D01* +X42710696Y-40120006D01* +X42578400Y-40144899D01* +X42456894Y-40223086D01* +X42375380Y-40342386D01* +X42346702Y-40484000D01* +X42346702Y-42516000D01* +X42371595Y-42648296D01* +X42449782Y-42769802D01* +X42569082Y-42851316D01* +X42710696Y-42879994D01* +X43069696Y-42879994D01* +X43069696Y-43726696D01* +X43119707Y-43978119D01* +X43207428Y-44109403D01* +X43109698Y-44011673D01* +X42876309Y-43915000D01* +X42783750Y-43915000D01* +X42625000Y-44073750D01* +X42625000Y-44873000D01* +X43226250Y-44873000D01* +X43385000Y-44714250D01* +X43385000Y-44423690D01* +X43307535Y-44236673D01* +X44570862Y-45500000D01* +X43656648Y-46414214D01* +X43550000Y-46393000D01* +X42776467Y-46393000D01* +X42771614Y-46389684D01* +X42630000Y-46361006D01* +X41570000Y-46361006D01* +X41437704Y-46385899D01* +X41316198Y-46464086D01* +X41234684Y-46583386D01* +X41206006Y-46725000D01* +X41206006Y-47375000D01* +X41230899Y-47507296D01* +X41309086Y-47628802D01* +X41428386Y-47710316D01* +X41570000Y-47738994D01* +X42630000Y-47738994D01* +X42762296Y-47714101D01* +X42773331Y-47707000D01* +X43021731Y-47707000D01* +X43035899Y-47782296D01* +X43046490Y-47798754D01* +X43015301Y-47811673D01* +X42836673Y-47990302D01* +X42740000Y-48223691D01* +X42740000Y-48283282D01* +X42630000Y-48261006D01* +X41570000Y-48261006D01* +X41437704Y-48285899D01* +X41316198Y-48364086D01* +X41286486Y-48407571D01* +X41131259Y-48343115D01* +X41065000Y-48343057D01* +X41065000Y-48285750D01* +X40906250Y-48127000D01* +X40027000Y-48127000D01* +X40027000Y-48147000D01* +X39773000Y-48147000D01* +X39773000Y-48127000D01* +X39753000Y-48127000D01* +X39753000Y-47873000D01* +X39773000Y-47873000D01* +X39773000Y-47853000D01* +X40027000Y-47853000D01* +X40027000Y-47873000D01* +X40906250Y-47873000D01* +X41065000Y-47714250D01* +X41065000Y-47548690D01* +X40968327Y-47315301D01* +X40793994Y-47140969D01* +X40793994Y-46725000D01* +X40769101Y-46592704D01* +X40690914Y-46471198D01* +X40571614Y-46389684D01* +X40430000Y-46361006D01* +X39370000Y-46361006D01* +X39237704Y-46385899D01* +X39226669Y-46393000D01* +X38200000Y-46393000D01* +X38093352Y-46414214D01* +X37546138Y-45867000D01* +X37790000Y-45867000D01* +X38041423Y-45816989D01* +X38045905Y-45813994D01* +X38250000Y-45813994D01* +X38382296Y-45789101D01* +X38503802Y-45710914D01* +X38585316Y-45591614D01* +X38613994Y-45450000D01* +X38613994Y-45216206D01* +X38657000Y-45000000D01* +X38613994Y-44783794D01* +X38613994Y-44550000D01* +X38589101Y-44417704D01* +X38510914Y-44296198D01* +X38391614Y-44214684D01* +X38250000Y-44186006D01* +X37750000Y-44186006D01* +X37617704Y-44210899D01* +X37496198Y-44289086D01* +X37414684Y-44408386D01* +X37386006Y-44550000D01* +X37386006Y-44553000D01* +X36707470Y-44553000D01* +X36497757Y-44239142D01* +X36052323Y-43941513D01* +X35995007Y-43930112D01* +X38842887Y-43930112D01* +X38942698Y-44171674D01* +X39034988Y-44264125D01* +X38996198Y-44289086D01* +X38914684Y-44408386D01* +X38886006Y-44550000D01* +X38886006Y-45450000D01* +X38910899Y-45582296D01* +X38989086Y-45703802D01* +X39108386Y-45785316D01* +X39250000Y-45813994D01* +X39750000Y-45813994D01* +X39882296Y-45789101D01* +X40003802Y-45710914D01* +X40085316Y-45591614D01* +X40102451Y-45507000D01* +X40396731Y-45507000D01* +X40410899Y-45582296D01* +X40489086Y-45703802D01* +X40608386Y-45785316D01* +X40750000Y-45813994D01* +X41250000Y-45813994D01* +X41382296Y-45789101D01* +X41503802Y-45710914D01* +X41585316Y-45591614D01* +X41613994Y-45450000D01* +X41613994Y-45285750D01* +X41615000Y-45285750D01* +X41615000Y-45576310D01* +X41711673Y-45809699D01* +X41890302Y-45988327D01* +X42123691Y-46085000D01* +X42216250Y-46085000D01* +X42375000Y-45926250D01* +X42375000Y-45127000D01* +X42625000Y-45127000D01* +X42625000Y-45926250D01* +X42783750Y-46085000D01* +X42876309Y-46085000D01* +X43109698Y-45988327D01* +X43288327Y-45809699D01* +X43385000Y-45576310D01* +X43385000Y-45285750D01* +X43226250Y-45127000D01* +X42625000Y-45127000D01* +X42375000Y-45127000D01* +X41773750Y-45127000D01* +X41615000Y-45285750D01* +X41613994Y-45285750D01* +X41613994Y-44550000D01* +X41590228Y-44423690D01* +X41615000Y-44423690D01* +X41615000Y-44714250D01* +X41773750Y-44873000D01* +X42375000Y-44873000D01* +X42375000Y-44073750D01* +X42216250Y-43915000D01* +X42123691Y-43915000D01* +X41890302Y-44011673D01* +X41711673Y-44190301D01* +X41615000Y-44423690D01* +X41590228Y-44423690D01* +X41589101Y-44417704D01* +X41510914Y-44296198D01* +X41391614Y-44214684D01* +X41250000Y-44186006D01* +X40750000Y-44186006D01* +X40617704Y-44210899D01* +X40496198Y-44289086D01* +X40414684Y-44408386D01* +X40397549Y-44493000D01* +X40103269Y-44493000D01* +X40089101Y-44417704D01* +X40010914Y-44296198D01* +X39964591Y-44264547D01* +X40056652Y-44172646D01* +X40156885Y-43931259D01* +X40157113Y-43669888D01* +X40057302Y-43428326D01* +X39872646Y-43243348D01* +X39631259Y-43143115D01* +X39369888Y-43142887D01* +X39128326Y-43242698D01* +X38943348Y-43427354D01* +X38843115Y-43668741D01* +X38842887Y-43930112D01* +X35995007Y-43930112D01* +X35526899Y-43837000D01* +X35473101Y-43837000D01* +X34947677Y-43941513D01* +X34502243Y-44239142D01* +X34269926Y-44586830D01* +X34188577Y-44603011D01* +X33975431Y-44745431D01* +X32359856Y-46361006D01* +X32070000Y-46361006D01* +X31965657Y-46380639D01* +X34523148Y-43823148D01* +X34622213Y-43674886D01* +X34657001Y-43500000D01* +X34657000Y-43499995D01* +X34657000Y-40772125D01* +X34756652Y-40672646D01* +X34856885Y-40431259D01* +X34857113Y-40169888D01* +X34757302Y-39928326D01* +X34602970Y-39773724D01* +X36532087Y-37844607D01* +X36436109Y-38075747D01* +X36435881Y-38337118D01* +X36535692Y-38578680D01* +X36720348Y-38763658D01* +X36961735Y-38863891D01* +X37223106Y-38864119D01* +X37464668Y-38764308D01* +X37649646Y-38579652D01* +X37749879Y-38338265D01* +X37750003Y-38196293D01* +X39196666Y-36749629D01* +X39196669Y-36749627D01* +X39226440Y-36705071D01* +X39245195Y-36697322D01* +X39430173Y-36512666D01* +X39530406Y-36271279D01* +X39530634Y-36009908D01* +X39430823Y-35768346D01* +X39246167Y-35583368D01* +X39004780Y-35483135D01* +X38893656Y-35483038D01* +X42122999Y-32253695D01* +X42122999Y-33879999D01* +X42122999Y-33879999D01* +G37* +X42122999Y-33879999D02* +X42157786Y-34054886D01* +X42256851Y-34203147D01* +X43143010Y-35089306D01* +X43142887Y-35230112D01* +X43242698Y-35471674D01* +X43427354Y-35656652D01* +X43668741Y-35756885D01* +X43810713Y-35757009D01* +X43896853Y-35843149D01* +X44045114Y-35942214D01* +X44220001Y-35977001D01* +X44421635Y-35977001D01* +X43350515Y-37048121D01* +X43235192Y-37220714D01* +X43194696Y-37424302D01* +X43194696Y-40120006D01* +X42710696Y-40120006D01* +X42578400Y-40144899D01* +X42456894Y-40223086D01* +X42375380Y-40342386D01* +X42346702Y-40484000D01* +X42346702Y-42516000D01* +X42371595Y-42648296D01* +X42449782Y-42769802D01* +X42569082Y-42851316D01* +X42710696Y-42879994D01* +X43069696Y-42879994D01* +X43069696Y-43726696D01* +X43119707Y-43978119D01* +X43207428Y-44109403D01* +X43109698Y-44011673D01* +X42876309Y-43915000D01* +X42783750Y-43915000D01* +X42625000Y-44073750D01* +X42625000Y-44873000D01* +X43226250Y-44873000D01* +X43385000Y-44714250D01* +X43385000Y-44423690D01* +X43307535Y-44236673D01* +X44570862Y-45500000D01* +X43656648Y-46414214D01* +X43550000Y-46393000D01* +X42776467Y-46393000D01* +X42771614Y-46389684D01* +X42630000Y-46361006D01* +X41570000Y-46361006D01* +X41437704Y-46385899D01* +X41316198Y-46464086D01* +X41234684Y-46583386D01* +X41206006Y-46725000D01* +X41206006Y-47375000D01* +X41230899Y-47507296D01* +X41309086Y-47628802D01* +X41428386Y-47710316D01* +X41570000Y-47738994D01* +X42630000Y-47738994D01* +X42762296Y-47714101D01* +X42773331Y-47707000D01* +X43021731Y-47707000D01* +X43035899Y-47782296D01* +X43046490Y-47798754D01* +X43015301Y-47811673D01* +X42836673Y-47990302D01* +X42740000Y-48223691D01* +X42740000Y-48283282D01* +X42630000Y-48261006D01* +X41570000Y-48261006D01* +X41437704Y-48285899D01* +X41316198Y-48364086D01* +X41286486Y-48407571D01* +X41131259Y-48343115D01* +X41065000Y-48343057D01* +X41065000Y-48285750D01* +X40906250Y-48127000D01* +X40027000Y-48127000D01* +X40027000Y-48147000D01* +X39773000Y-48147000D01* +X39773000Y-48127000D01* +X39753000Y-48127000D01* +X39753000Y-47873000D01* +X39773000Y-47873000D01* +X39773000Y-47853000D01* +X40027000Y-47853000D01* +X40027000Y-47873000D01* +X40906250Y-47873000D01* +X41065000Y-47714250D01* +X41065000Y-47548690D01* +X40968327Y-47315301D01* +X40793994Y-47140969D01* +X40793994Y-46725000D01* +X40769101Y-46592704D01* +X40690914Y-46471198D01* +X40571614Y-46389684D01* +X40430000Y-46361006D01* +X39370000Y-46361006D01* +X39237704Y-46385899D01* +X39226669Y-46393000D01* +X38200000Y-46393000D01* +X38093352Y-46414214D01* +X37546138Y-45867000D01* +X37790000Y-45867000D01* +X38041423Y-45816989D01* +X38045905Y-45813994D01* +X38250000Y-45813994D01* +X38382296Y-45789101D01* +X38503802Y-45710914D01* +X38585316Y-45591614D01* +X38613994Y-45450000D01* +X38613994Y-45216206D01* +X38657000Y-45000000D01* +X38613994Y-44783794D01* +X38613994Y-44550000D01* +X38589101Y-44417704D01* +X38510914Y-44296198D01* +X38391614Y-44214684D01* +X38250000Y-44186006D01* +X37750000Y-44186006D01* +X37617704Y-44210899D01* +X37496198Y-44289086D01* +X37414684Y-44408386D01* +X37386006Y-44550000D01* +X37386006Y-44553000D01* +X36707470Y-44553000D01* +X36497757Y-44239142D01* +X36052323Y-43941513D01* +X35995007Y-43930112D01* +X38842887Y-43930112D01* +X38942698Y-44171674D01* +X39034988Y-44264125D01* +X38996198Y-44289086D01* +X38914684Y-44408386D01* +X38886006Y-44550000D01* +X38886006Y-45450000D01* +X38910899Y-45582296D01* +X38989086Y-45703802D01* +X39108386Y-45785316D01* +X39250000Y-45813994D01* +X39750000Y-45813994D01* +X39882296Y-45789101D01* +X40003802Y-45710914D01* +X40085316Y-45591614D01* +X40102451Y-45507000D01* +X40396731Y-45507000D01* +X40410899Y-45582296D01* +X40489086Y-45703802D01* +X40608386Y-45785316D01* +X40750000Y-45813994D01* +X41250000Y-45813994D01* +X41382296Y-45789101D01* +X41503802Y-45710914D01* +X41585316Y-45591614D01* +X41613994Y-45450000D01* +X41613994Y-45285750D01* +X41615000Y-45285750D01* +X41615000Y-45576310D01* +X41711673Y-45809699D01* +X41890302Y-45988327D01* +X42123691Y-46085000D01* +X42216250Y-46085000D01* +X42375000Y-45926250D01* +X42375000Y-45127000D01* +X42625000Y-45127000D01* +X42625000Y-45926250D01* +X42783750Y-46085000D01* +X42876309Y-46085000D01* +X43109698Y-45988327D01* +X43288327Y-45809699D01* +X43385000Y-45576310D01* +X43385000Y-45285750D01* +X43226250Y-45127000D01* +X42625000Y-45127000D01* +X42375000Y-45127000D01* +X41773750Y-45127000D01* +X41615000Y-45285750D01* +X41613994Y-45285750D01* +X41613994Y-44550000D01* +X41590228Y-44423690D01* +X41615000Y-44423690D01* +X41615000Y-44714250D01* +X41773750Y-44873000D01* +X42375000Y-44873000D01* +X42375000Y-44073750D01* +X42216250Y-43915000D01* +X42123691Y-43915000D01* +X41890302Y-44011673D01* +X41711673Y-44190301D01* +X41615000Y-44423690D01* +X41590228Y-44423690D01* +X41589101Y-44417704D01* +X41510914Y-44296198D01* +X41391614Y-44214684D01* +X41250000Y-44186006D01* +X40750000Y-44186006D01* +X40617704Y-44210899D01* +X40496198Y-44289086D01* +X40414684Y-44408386D01* +X40397549Y-44493000D01* +X40103269Y-44493000D01* +X40089101Y-44417704D01* +X40010914Y-44296198D01* +X39964591Y-44264547D01* +X40056652Y-44172646D01* +X40156885Y-43931259D01* +X40157113Y-43669888D01* +X40057302Y-43428326D01* +X39872646Y-43243348D01* +X39631259Y-43143115D01* +X39369888Y-43142887D01* +X39128326Y-43242698D01* +X38943348Y-43427354D01* +X38843115Y-43668741D01* +X38842887Y-43930112D01* +X35995007Y-43930112D01* +X35526899Y-43837000D01* +X35473101Y-43837000D01* +X34947677Y-43941513D01* +X34502243Y-44239142D01* +X34269926Y-44586830D01* +X34188577Y-44603011D01* +X33975431Y-44745431D01* +X32359856Y-46361006D01* +X32070000Y-46361006D01* +X31965657Y-46380639D01* +X34523148Y-43823148D01* +X34622213Y-43674886D01* +X34657001Y-43500000D01* +X34657000Y-43499995D01* +X34657000Y-40772125D01* +X34756652Y-40672646D01* +X34856885Y-40431259D01* +X34857113Y-40169888D01* +X34757302Y-39928326D01* +X34602970Y-39773724D01* +X36532087Y-37844607D01* +X36436109Y-38075747D01* +X36435881Y-38337118D01* +X36535692Y-38578680D01* +X36720348Y-38763658D01* +X36961735Y-38863891D01* +X37223106Y-38864119D01* +X37464668Y-38764308D01* +X37649646Y-38579652D01* +X37749879Y-38338265D01* +X37750003Y-38196293D01* +X39196666Y-36749629D01* +X39196669Y-36749627D01* +X39226440Y-36705071D01* +X39245195Y-36697322D01* +X39430173Y-36512666D01* +X39530406Y-36271279D01* +X39530634Y-36009908D01* +X39430823Y-35768346D01* +X39246167Y-35583368D01* +X39004780Y-35483135D01* +X38893656Y-35483038D01* +X42122999Y-32253695D01* +X42122999Y-33879999D01* +G36* +X33022877Y-40939230D02* +X33122688Y-41180792D01* +X33307344Y-41365770D01* +X33548731Y-41466003D01* +X33743000Y-41466172D01* +X33743000Y-43310704D01* +X31176852Y-45876852D01* +X31077787Y-46025113D01* +X31077787Y-46025114D01* +X31043000Y-46200000D01* +X31043000Y-46383889D01* +X30930000Y-46361006D01* +X30640144Y-46361006D01* +X29613994Y-45334856D01* +X29613994Y-44875000D01* +X29589101Y-44742704D01* +X29515905Y-44628954D01* +X29734699Y-44538327D01* +X29913327Y-44359698D01* +X29914637Y-44356536D01* +X30004590Y-44339610D01* +X30125000Y-44363994D01* +X30375000Y-44363994D01* +X30504590Y-44339610D01* +X30585106Y-44355915D01* +X30586673Y-44359698D01* +X30765301Y-44538327D01* +X30998690Y-44635000D01* +X31028750Y-44635000D01* +X31187500Y-44476250D01* +X31187500Y-44175006D01* +X31210316Y-44141614D01* +X31238994Y-44000000D01* +X31238994Y-43777000D01* +X31312500Y-43777000D01* +X31312500Y-44476250D01* +X31471250Y-44635000D01* +X31501310Y-44635000D01* +X31734699Y-44538327D01* +X31913327Y-44359698D01* +X32010000Y-44126309D01* +X32010000Y-43935750D01* +X31851250Y-43777000D01* +X31312500Y-43777000D01* +X31238994Y-43777000D01* +X31238994Y-43610000D01* +X31351310Y-43610000D01* +X31561346Y-43523000D01* +X31851250Y-43523000D01* +X31885256Y-43488994D01* +X32250000Y-43488994D01* +X32382296Y-43464101D01* +X32503802Y-43385914D01* +X32585316Y-43266614D01* +X32605915Y-43164894D01* +X32609698Y-43163327D01* +X32788327Y-42984699D01* +X32885000Y-42751310D01* +X32885000Y-42721250D01* +X32726250Y-42562500D01* +X32425006Y-42562500D01* +X32391614Y-42539684D01* +X32250000Y-42511006D01* +X31860000Y-42511006D01* +X31860000Y-42488994D01* +X32250000Y-42488994D01* +X32382296Y-42464101D01* +X32423635Y-42437500D01* +X32726250Y-42437500D01* +X32885000Y-42278750D01* +X32885000Y-42248690D01* +X32788327Y-42015301D01* +X32609698Y-41836673D01* +X32606536Y-41835363D01* +X32589610Y-41745410D01* +X32613994Y-41625000D01* +X32613994Y-41375000D01* +X32589610Y-41245410D01* +X32613994Y-41125000D01* +X32613994Y-40957000D01* +X32777836Y-40957000D01* +X32952723Y-40922213D01* +X33022933Y-40875300D01* +X33022877Y-40939230D01* +X33022877Y-40939230D01* +G37* +X33022877Y-40939230D02* +X33122688Y-41180792D01* +X33307344Y-41365770D01* +X33548731Y-41466003D01* +X33743000Y-41466172D01* +X33743000Y-43310704D01* +X31176852Y-45876852D01* +X31077787Y-46025113D01* +X31077787Y-46025114D01* +X31043000Y-46200000D01* +X31043000Y-46383889D01* +X30930000Y-46361006D01* +X30640144Y-46361006D01* +X29613994Y-45334856D01* +X29613994Y-44875000D01* +X29589101Y-44742704D01* +X29515905Y-44628954D01* +X29734699Y-44538327D01* +X29913327Y-44359698D01* +X29914637Y-44356536D01* +X30004590Y-44339610D01* +X30125000Y-44363994D01* +X30375000Y-44363994D01* +X30504590Y-44339610D01* +X30585106Y-44355915D01* +X30586673Y-44359698D01* +X30765301Y-44538327D01* +X30998690Y-44635000D01* +X31028750Y-44635000D01* +X31187500Y-44476250D01* +X31187500Y-44175006D01* +X31210316Y-44141614D01* +X31238994Y-44000000D01* +X31238994Y-43777000D01* +X31312500Y-43777000D01* +X31312500Y-44476250D01* +X31471250Y-44635000D01* +X31501310Y-44635000D01* +X31734699Y-44538327D01* +X31913327Y-44359698D01* +X32010000Y-44126309D01* +X32010000Y-43935750D01* +X31851250Y-43777000D01* +X31312500Y-43777000D01* +X31238994Y-43777000D01* +X31238994Y-43610000D01* +X31351310Y-43610000D01* +X31561346Y-43523000D01* +X31851250Y-43523000D01* +X31885256Y-43488994D01* +X32250000Y-43488994D01* +X32382296Y-43464101D01* +X32503802Y-43385914D01* +X32585316Y-43266614D01* +X32605915Y-43164894D01* +X32609698Y-43163327D01* +X32788327Y-42984699D01* +X32885000Y-42751310D01* +X32885000Y-42721250D01* +X32726250Y-42562500D01* +X32425006Y-42562500D01* +X32391614Y-42539684D01* +X32250000Y-42511006D01* +X31860000Y-42511006D01* +X31860000Y-42488994D01* +X32250000Y-42488994D01* +X32382296Y-42464101D01* +X32423635Y-42437500D01* +X32726250Y-42437500D01* +X32885000Y-42278750D01* +X32885000Y-42248690D01* +X32788327Y-42015301D01* +X32609698Y-41836673D01* +X32606536Y-41835363D01* +X32589610Y-41745410D01* +X32613994Y-41625000D01* +X32613994Y-41375000D01* +X32589610Y-41245410D01* +X32613994Y-41125000D01* +X32613994Y-40957000D01* +X32777836Y-40957000D01* +X32952723Y-40922213D01* +X33022933Y-40875300D01* +X33022877Y-40939230D01* +G36* +X29261006Y-43797000D02* +X29238994Y-43797000D01* +X29238994Y-43610000D01* +X29261006Y-43610000D01* +X29261006Y-43797000D01* +X29261006Y-43797000D01* +G37* +X29261006Y-43797000D02* +X29238994Y-43797000D01* +X29238994Y-43610000D01* +X29261006Y-43610000D01* +X29261006Y-43797000D01* +G36* +X28764500Y-40260500D02* +X30235500Y-40260500D01* +X30235500Y-40240500D01* +X30489500Y-40240500D01* +X30489500Y-40260500D01* +X30509500Y-40260500D01* +X30509500Y-40514500D01* +X30489500Y-40514500D01* +X30489500Y-41985500D01* +X30509500Y-41985500D01* +X30509500Y-42239500D01* +X30489500Y-42239500D01* +X30489500Y-42259500D01* +X30235500Y-42259500D01* +X30235500Y-42239500D01* +X28764500Y-42239500D01* +X28764500Y-42259500D01* +X28510500Y-42259500D01* +X28510500Y-42239500D01* +X28490500Y-42239500D01* +X28490500Y-41985500D01* +X28510500Y-41985500D01* +X28510500Y-40514500D01* +X28764500Y-40514500D01* +X28764500Y-41985500D01* +X30235500Y-41985500D01* +X30235500Y-40514500D01* +X28764500Y-40514500D01* +X28510500Y-40514500D01* +X28490500Y-40514500D01* +X28490500Y-40260500D01* +X28510500Y-40260500D01* +X28510500Y-40240500D01* +X28764500Y-40240500D01* +X28764500Y-40260500D01* +X28764500Y-40260500D01* +G37* +X28764500Y-40260500D02* +X30235500Y-40260500D01* +X30235500Y-40240500D01* +X30489500Y-40240500D01* +X30489500Y-40260500D01* +X30509500Y-40260500D01* +X30509500Y-40514500D01* +X30489500Y-40514500D01* +X30489500Y-41985500D01* +X30509500Y-41985500D01* +X30509500Y-42239500D01* +X30489500Y-42239500D01* +X30489500Y-42259500D01* +X30235500Y-42259500D01* +X30235500Y-42239500D01* +X28764500Y-42239500D01* +X28764500Y-42259500D01* +X28510500Y-42259500D01* +X28510500Y-42239500D01* +X28490500Y-42239500D01* +X28490500Y-41985500D01* +X28510500Y-41985500D01* +X28510500Y-40514500D01* +X28764500Y-40514500D01* +X28764500Y-41985500D01* +X30235500Y-41985500D01* +X30235500Y-40514500D01* +X28764500Y-40514500D01* +X28510500Y-40514500D01* +X28490500Y-40514500D01* +X28490500Y-40260500D01* +X28510500Y-40260500D01* +X28510500Y-40240500D01* +X28764500Y-40240500D01* +X28764500Y-40260500D01* +G36* +X24043000Y-30589296D02* +X24043000Y-35947298D01* +X24077787Y-36122185D01* +X24176852Y-36270446D01* +X25209584Y-37303178D01* +X25357846Y-37402243D01* +X25532732Y-37437031D01* +X25532737Y-37437030D01* +X26216674Y-37437030D01* +X24414333Y-39239371D01* +X24341614Y-39189684D01* +X24200000Y-39161006D01* +X23400000Y-39161006D01* +X23267704Y-39185899D01* +X23251246Y-39196490D01* +X23238327Y-39165301D01* +X23059698Y-38986673D01* +X22867282Y-38906972D01* +X23218250Y-38907278D01* +X23809103Y-38663143D01* +X24261554Y-38211481D01* +X24506720Y-37621054D01* +X24507278Y-36981750D01* +X24263143Y-36390897D01* +X23811481Y-35938446D01* +X23221054Y-35693280D01* +X22581750Y-35692722D01* +X21990897Y-35936857D01* +X21538446Y-36388519D01* +X21293280Y-36978946D01* +X21292722Y-37618250D01* +X21536857Y-38209103D01* +X21988519Y-38661554D01* +X22571939Y-38903811D01* +X22427000Y-39048750D01* +X22427000Y-39773000D01* +X22447000Y-39773000D01* +X22447000Y-40027000D01* +X22427000Y-40027000D01* +X22427000Y-40047000D01* +X22173000Y-40047000D01* +X22173000Y-40027000D01* +X21423750Y-40027000D01* +X21265000Y-40185750D01* +X21265000Y-40401310D01* +X21353886Y-40615900D01* +X21210540Y-40615900D01* +X20785862Y-40750898D01* +X20445172Y-41038137D01* +X20432000Y-41064963D01* +X20432000Y-39398690D01* +X21265000Y-39398690D01* +X21265000Y-39614250D01* +X21423750Y-39773000D01* +X22173000Y-39773000D01* +X22173000Y-39048750D01* +X22014250Y-38890000D01* +X21773691Y-38890000D01* +X21540302Y-38986673D01* +X21361673Y-39165301D01* +X21265000Y-39398690D01* +X20432000Y-39398690D01* +X20432000Y-32727000D01* +X23900000Y-32727000D01* +X23949410Y-32716994D01* +X23991035Y-32688553D01* +X24018315Y-32646159D01* +X24027000Y-32600000D01* +X24027000Y-30573296D01* +X24043000Y-30589296D01* +X24043000Y-30589296D01* +G37* +X24043000Y-30589296D02* +X24043000Y-35947298D01* +X24077787Y-36122185D01* +X24176852Y-36270446D01* +X25209584Y-37303178D01* +X25357846Y-37402243D01* +X25532732Y-37437031D01* +X25532737Y-37437030D01* +X26216674Y-37437030D01* +X24414333Y-39239371D01* +X24341614Y-39189684D01* +X24200000Y-39161006D01* +X23400000Y-39161006D01* +X23267704Y-39185899D01* +X23251246Y-39196490D01* +X23238327Y-39165301D01* +X23059698Y-38986673D01* +X22867282Y-38906972D01* +X23218250Y-38907278D01* +X23809103Y-38663143D01* +X24261554Y-38211481D01* +X24506720Y-37621054D01* +X24507278Y-36981750D01* +X24263143Y-36390897D01* +X23811481Y-35938446D01* +X23221054Y-35693280D01* +X22581750Y-35692722D01* +X21990897Y-35936857D01* +X21538446Y-36388519D01* +X21293280Y-36978946D01* +X21292722Y-37618250D01* +X21536857Y-38209103D01* +X21988519Y-38661554D01* +X22571939Y-38903811D01* +X22427000Y-39048750D01* +X22427000Y-39773000D01* +X22447000Y-39773000D01* +X22447000Y-40027000D01* +X22427000Y-40027000D01* +X22427000Y-40047000D01* +X22173000Y-40047000D01* +X22173000Y-40027000D01* +X21423750Y-40027000D01* +X21265000Y-40185750D01* +X21265000Y-40401310D01* +X21353886Y-40615900D01* +X21210540Y-40615900D01* +X20785862Y-40750898D01* +X20445172Y-41038137D01* +X20432000Y-41064963D01* +X20432000Y-39398690D01* +X21265000Y-39398690D01* +X21265000Y-39614250D01* +X21423750Y-39773000D01* +X22173000Y-39773000D01* +X22173000Y-39048750D01* +X22014250Y-38890000D01* +X21773691Y-38890000D01* +X21540302Y-38986673D01* +X21361673Y-39165301D01* +X21265000Y-39398690D01* +X20432000Y-39398690D01* +X20432000Y-32727000D01* +X23900000Y-32727000D01* +X23949410Y-32716994D01* +X23991035Y-32688553D01* +X24018315Y-32646159D01* +X24027000Y-32600000D01* +X24027000Y-30573296D01* +X24043000Y-30589296D01* +G36* +X29761006Y-38890000D02* +X29738994Y-38890000D01* +X29738994Y-38703000D01* +X29761006Y-38703000D01* +X29761006Y-38890000D01* +X29761006Y-38890000D01* +G37* +X29761006Y-38890000D02* +X29738994Y-38890000D01* +X29738994Y-38703000D01* +X29761006Y-38703000D01* +X29761006Y-38890000D01* +G36* +X30127000Y-30873000D02* +X30147000Y-30873000D01* +X30147000Y-31127000D01* +X30127000Y-31127000D01* +X30127000Y-31851250D01* +X30285750Y-32010000D01* +X30526309Y-32010000D01* +X30759698Y-31913327D01* +X30938327Y-31734699D01* +X31035000Y-31501310D01* +X31035000Y-31381296D01* +X32676852Y-33023148D01* +X32825113Y-33122213D01* +X32963242Y-33149688D01* +X33070019Y-33256652D01* +X33311406Y-33356885D01* +X33543000Y-33357087D01* +X33543000Y-34027875D01* +X33443348Y-34127354D01* +X33343115Y-34368741D01* +X33342887Y-34630112D01* +X33442698Y-34871674D01* +X33627354Y-35056652D01* +X33811246Y-35133011D01* +X30556158Y-35133011D01* +X30556885Y-35131259D01* +X30557113Y-34869888D01* +X30457302Y-34628326D01* +X30272646Y-34443348D01* +X30151425Y-34393013D01* +X30151423Y-34393011D01* +X30151420Y-34393010D01* +X30031259Y-34343115D01* +X29956962Y-34343050D01* +X29957113Y-34169888D01* +X29857302Y-33928326D01* +X29707000Y-33777762D01* +X29707000Y-32010000D01* +X29714250Y-32010000D01* +X29873000Y-31851250D01* +X29873000Y-31127000D01* +X29853000Y-31127000D01* +X29853000Y-30873000D01* +X29873000Y-30873000D01* +X29873000Y-30853000D01* +X30127000Y-30853000D01* +X30127000Y-30873000D01* +X30127000Y-30873000D01* +G37* +X30127000Y-30873000D02* +X30147000Y-30873000D01* +X30147000Y-31127000D01* +X30127000Y-31127000D01* +X30127000Y-31851250D01* +X30285750Y-32010000D01* +X30526309Y-32010000D01* +X30759698Y-31913327D01* +X30938327Y-31734699D01* +X31035000Y-31501310D01* +X31035000Y-31381296D01* +X32676852Y-33023148D01* +X32825113Y-33122213D01* +X32963242Y-33149688D01* +X33070019Y-33256652D01* +X33311406Y-33356885D01* +X33543000Y-33357087D01* +X33543000Y-34027875D01* +X33443348Y-34127354D01* +X33343115Y-34368741D01* +X33342887Y-34630112D01* +X33442698Y-34871674D01* +X33627354Y-35056652D01* +X33811246Y-35133011D01* +X30556158Y-35133011D01* +X30556885Y-35131259D01* +X30557113Y-34869888D01* +X30457302Y-34628326D01* +X30272646Y-34443348D01* +X30151425Y-34393013D01* +X30151423Y-34393011D01* +X30151420Y-34393010D01* +X30031259Y-34343115D01* +X29956962Y-34343050D01* +X29957113Y-34169888D01* +X29857302Y-33928326D01* +X29707000Y-33777762D01* +X29707000Y-32010000D01* +X29714250Y-32010000D01* +X29873000Y-31851250D01* +X29873000Y-31127000D01* +X29853000Y-31127000D01* +X29853000Y-30873000D01* +X29873000Y-30873000D01* +X29873000Y-30853000D01* +X30127000Y-30853000D01* +X30127000Y-30873000D01* +G36* +X36559174Y-32740825D02* +X36585621Y-32758496D01* +X36715547Y-32845310D01* +X36900000Y-32882000D01* +X39583804Y-32882000D01* +X39738445Y-32851240D01* +X39768258Y-32845310D01* +X39822421Y-32809119D01* +X38770150Y-33861390D01* +X38770210Y-33792389D01* +X38670399Y-33550827D01* +X38485743Y-33365849D01* +X38244356Y-33265616D01* +X37982985Y-33265388D01* +X37741423Y-33365199D01* +X37556445Y-33549855D01* +X37474156Y-33748028D01* +X37459204Y-33733050D01* +X37217817Y-33632817D01* +X36956446Y-33632589D01* +X36714884Y-33732400D01* +X36614407Y-33832702D01* +X36443827Y-33832702D01* +X34147966Y-31536841D01* +X33999705Y-31437776D01* +X33824818Y-31402989D01* +X33301847Y-31402989D01* +X32155819Y-30256961D01* +X32330112Y-30257113D01* +X32571674Y-30157302D01* +X32597020Y-30132000D01* +X32624264Y-30132000D01* +X32827852Y-30091504D01* +X33000445Y-29976181D01* +X33276181Y-29700445D01* +X33373359Y-29555009D01* +X36559174Y-32740825D01* +X36559174Y-32740825D01* +G37* +X36559174Y-32740825D02* +X36585621Y-32758496D01* +X36715547Y-32845310D01* +X36900000Y-32882000D01* +X39583804Y-32882000D01* +X39738445Y-32851240D01* +X39768258Y-32845310D01* +X39822421Y-32809119D01* +X38770150Y-33861390D01* +X38770210Y-33792389D01* +X38670399Y-33550827D01* +X38485743Y-33365849D01* +X38244356Y-33265616D01* +X37982985Y-33265388D01* +X37741423Y-33365199D01* +X37556445Y-33549855D01* +X37474156Y-33748028D01* +X37459204Y-33733050D01* +X37217817Y-33632817D01* +X36956446Y-33632589D01* +X36714884Y-33732400D01* +X36614407Y-33832702D01* +X36443827Y-33832702D01* +X34147966Y-31536841D01* +X33999705Y-31437776D01* +X33824818Y-31402989D01* +X33301847Y-31402989D01* +X32155819Y-30256961D01* +X32330112Y-30257113D01* +X32571674Y-30157302D01* +X32597020Y-30132000D01* +X32624264Y-30132000D01* +X32827852Y-30091504D01* +X33000445Y-29976181D01* +X33276181Y-29700445D01* +X33373359Y-29555009D01* +X36559174Y-32740825D01* +G36* +X46063702Y-21288661D02* +X46056708Y-21323198D01* +X46056708Y-21623360D01* +X46020702Y-21616198D01* +X45001802Y-21616198D01* +X44847951Y-21646801D01* +X44842667Y-21647852D01* +X44831259Y-21643115D01* +X44569888Y-21642887D01* +X44328326Y-21742698D01* +X44143348Y-21927354D01* +X44043115Y-22168741D01* +X44042887Y-22430112D01* +X44142698Y-22671674D01* +X44168000Y-22697020D01* +X44168000Y-23777496D01* +X44208496Y-23981084D01* +X44299981Y-24118001D01* +X44323819Y-24153677D01* +X45116054Y-24945912D01* +X45116024Y-24980745D01* +X45215835Y-25222307D01* +X45400491Y-25407285D01* +X45641878Y-25507518D01* +X45688316Y-25507559D01* +X45582375Y-25613499D01* +X45485702Y-25846888D01* +X45485702Y-26062448D01* +X45644452Y-26221198D01* +X46393702Y-26221198D01* +X46393702Y-26201198D01* +X46647702Y-26201198D01* +X46647702Y-26221198D01* +X46667702Y-26221198D01* +X46667702Y-26475198D01* +X46647702Y-26475198D01* +X46647702Y-27199448D01* +X46806452Y-27358198D01* +X47047011Y-27358198D01* +X47280400Y-27261525D01* +X47459029Y-27082897D01* +X47471326Y-27053210D01* +X47479088Y-27058514D01* +X47620702Y-27087192D01* +X48420702Y-27087192D01* +X48552998Y-27062299D01* +X48674504Y-26984112D01* +X48756018Y-26864812D01* +X48784696Y-26723198D01* +X48784696Y-25973198D01* +X48770736Y-25899008D01* +X48871674Y-25857302D01* +X49056652Y-25672646D01* +X49156885Y-25431259D01* +X49157113Y-25169888D01* +X49057302Y-24928326D01* +X48984696Y-24855593D01* +X48984696Y-24573036D01* +X49020702Y-24580198D01* +X49988702Y-24580198D01* +X49988702Y-26708936D01* +X46529638Y-30168000D01* +X44697255Y-30168000D01* +X44672646Y-30143348D01* +X44431259Y-30043115D01* +X44169888Y-30042887D01* +X43928326Y-30142698D01* +X43743348Y-30327354D01* +X43643115Y-30568741D01* +X43642887Y-30830112D01* +X43742698Y-31071674D01* +X43927354Y-31256652D01* +X44168741Y-31356885D01* +X44430112Y-31357113D01* +X44671674Y-31257302D01* +X44697020Y-31232000D01* +X46529638Y-31232000D01* +X48533644Y-33236006D01* +X48000000Y-33236006D01* +X47867704Y-33260899D01* +X47799916Y-33304520D01* +X47741614Y-33264684D01* +X47600000Y-33236006D01* +X47000000Y-33236006D01* +X46867704Y-33260899D01* +X46799916Y-33304520D01* +X46741614Y-33264684D01* +X46600000Y-33236006D01* +X46000000Y-33236006D01* +X45867704Y-33260899D01* +X45799916Y-33304520D01* +X45741614Y-33264684D01* +X45729600Y-33262251D01* +X45722213Y-33225114D01* +X45623148Y-33076852D01* +X43557000Y-31010704D01* +X43557000Y-26633948D01* +X45485702Y-26633948D01* +X45485702Y-26849508D01* +X45582375Y-27082897D01* +X45761004Y-27261525D01* +X45994393Y-27358198D01* +X46234952Y-27358198D01* +X46393702Y-27199448D01* +X46393702Y-26475198D01* +X45644452Y-26475198D01* +X45485702Y-26633948D01* +X43557000Y-26633948D01* +X43557000Y-21557009D01* +X44752554Y-21557008D01* +X44927441Y-21522221D01* +X45075702Y-21423156D01* +X45221848Y-21277010D01* +X46063702Y-21277010D01* +X46063702Y-21288661D01* +X46063702Y-21288661D01* +G37* +X46063702Y-21288661D02* +X46056708Y-21323198D01* +X46056708Y-21623360D01* +X46020702Y-21616198D01* +X45001802Y-21616198D01* +X44847951Y-21646801D01* +X44842667Y-21647852D01* +X44831259Y-21643115D01* +X44569888Y-21642887D01* +X44328326Y-21742698D01* +X44143348Y-21927354D01* +X44043115Y-22168741D01* +X44042887Y-22430112D01* +X44142698Y-22671674D01* +X44168000Y-22697020D01* +X44168000Y-23777496D01* +X44208496Y-23981084D01* +X44299981Y-24118001D01* +X44323819Y-24153677D01* +X45116054Y-24945912D01* +X45116024Y-24980745D01* +X45215835Y-25222307D01* +X45400491Y-25407285D01* +X45641878Y-25507518D01* +X45688316Y-25507559D01* +X45582375Y-25613499D01* +X45485702Y-25846888D01* +X45485702Y-26062448D01* +X45644452Y-26221198D01* +X46393702Y-26221198D01* +X46393702Y-26201198D01* +X46647702Y-26201198D01* +X46647702Y-26221198D01* +X46667702Y-26221198D01* +X46667702Y-26475198D01* +X46647702Y-26475198D01* +X46647702Y-27199448D01* +X46806452Y-27358198D01* +X47047011Y-27358198D01* +X47280400Y-27261525D01* +X47459029Y-27082897D01* +X47471326Y-27053210D01* +X47479088Y-27058514D01* +X47620702Y-27087192D01* +X48420702Y-27087192D01* +X48552998Y-27062299D01* +X48674504Y-26984112D01* +X48756018Y-26864812D01* +X48784696Y-26723198D01* +X48784696Y-25973198D01* +X48770736Y-25899008D01* +X48871674Y-25857302D01* +X49056652Y-25672646D01* +X49156885Y-25431259D01* +X49157113Y-25169888D01* +X49057302Y-24928326D01* +X48984696Y-24855593D01* +X48984696Y-24573036D01* +X49020702Y-24580198D01* +X49988702Y-24580198D01* +X49988702Y-26708936D01* +X46529638Y-30168000D01* +X44697255Y-30168000D01* +X44672646Y-30143348D01* +X44431259Y-30043115D01* +X44169888Y-30042887D01* +X43928326Y-30142698D01* +X43743348Y-30327354D01* +X43643115Y-30568741D01* +X43642887Y-30830112D01* +X43742698Y-31071674D01* +X43927354Y-31256652D01* +X44168741Y-31356885D01* +X44430112Y-31357113D01* +X44671674Y-31257302D01* +X44697020Y-31232000D01* +X46529638Y-31232000D01* +X48533644Y-33236006D01* +X48000000Y-33236006D01* +X47867704Y-33260899D01* +X47799916Y-33304520D01* +X47741614Y-33264684D01* +X47600000Y-33236006D01* +X47000000Y-33236006D01* +X46867704Y-33260899D01* +X46799916Y-33304520D01* +X46741614Y-33264684D01* +X46600000Y-33236006D01* +X46000000Y-33236006D01* +X45867704Y-33260899D01* +X45799916Y-33304520D01* +X45741614Y-33264684D01* +X45729600Y-33262251D01* +X45722213Y-33225114D01* +X45623148Y-33076852D01* +X43557000Y-31010704D01* +X43557000Y-26633948D01* +X45485702Y-26633948D01* +X45485702Y-26849508D01* +X45582375Y-27082897D01* +X45761004Y-27261525D01* +X45994393Y-27358198D01* +X46234952Y-27358198D01* +X46393702Y-27199448D01* +X46393702Y-26475198D01* +X45644452Y-26475198D01* +X45485702Y-26633948D01* +X43557000Y-26633948D01* +X43557000Y-21557009D01* +X44752554Y-21557008D01* +X44927441Y-21522221D01* +X45075702Y-21423156D01* +X45221848Y-21277010D01* +X46063702Y-21277010D01* +X46063702Y-21288661D01* +G36* +X39254576Y-23680227D02* +X39249684Y-23687386D01* +X39221006Y-23829000D01* +X39221006Y-25129000D01* +X39245899Y-25261296D01* +X39324086Y-25382802D01* +X39443386Y-25464316D01* +X39585000Y-25492994D01* +X40085000Y-25492994D01* +X40217296Y-25468101D01* +X40338802Y-25389914D01* +X40420316Y-25270614D01* +X40448994Y-25129000D01* +X40448994Y-23829000D01* +X40424101Y-23696704D01* +X40345914Y-23575198D01* +X40311577Y-23551737D01* +X40303141Y-23509327D01* +X40290593Y-23446244D01* +X40524576Y-23680227D01* +X40519684Y-23687386D01* +X40491006Y-23829000D01* +X40491006Y-25129000D01* +X40515899Y-25261296D01* +X40594086Y-25382802D01* +X40713386Y-25464316D01* +X40855000Y-25492994D01* +X41305458Y-25492994D01* +X41305458Y-29119292D01* +X41230000Y-29194750D01* +X41230000Y-30194000D01* +X41252000Y-30194000D01* +X41252000Y-30448000D01* +X41230000Y-30448000D01* +X41230000Y-30468000D01* +X40980000Y-30468000D01* +X40980000Y-30448000D01* +X40958000Y-30448000D01* +X40958000Y-30194000D01* +X40980000Y-30194000D01* +X40980000Y-29310055D01* +X40982000Y-29300000D01* +X40982000Y-27314000D01* +X40947710Y-27141614D01* +X40945310Y-27129546D01* +X40840825Y-26973174D01* +X39145424Y-25277774D01* +X39150316Y-25270614D01* +X39178994Y-25129000D01* +X39178994Y-23829000D01* +X39154101Y-23696704D01* +X39075914Y-23575198D01* +X38956614Y-23493684D01* +X38815000Y-23465006D01* +X38315000Y-23465006D01* +X38182704Y-23489899D01* +X38061198Y-23568086D01* +X37979684Y-23687386D01* +X37951006Y-23829000D01* +X37951006Y-25129000D01* +X37975899Y-25261296D01* +X38054086Y-25382802D01* +X38088423Y-25406263D01* +X38109963Y-25514551D01* +X38119690Y-25563454D01* +X38224175Y-25719825D01* +X40018000Y-27513651D01* +X40018000Y-29300000D01* +X40019394Y-29307006D01* +X39585000Y-29307006D01* +X39452704Y-29331899D01* +X39331198Y-29410086D01* +X39249684Y-29529386D01* +X39221006Y-29671000D01* +X39221006Y-30971000D01* +X39229850Y-31018000D01* +X39169476Y-31018000D01* +X39178994Y-30971000D01* +X39178994Y-29671000D01* +X39154101Y-29538704D01* +X39075914Y-29417198D01* +X39041577Y-29393737D01* +X39010310Y-29236547D01* +X39010310Y-29236546D01* +X38905825Y-29080174D01* +X35584825Y-25759175D01* +X35428454Y-25654690D01* +X35397851Y-25648603D01* +X35244000Y-25618000D01* +X35000155Y-25618000D01* +X35040825Y-25590825D01* +X36681006Y-23950645D01* +X36681006Y-25129000D01* +X36705899Y-25261296D01* +X36784086Y-25382802D01* +X36903386Y-25464316D01* +X37045000Y-25492994D01* +X37545000Y-25492994D01* +X37677296Y-25468101D01* +X37798802Y-25389914D01* +X37880316Y-25270614D01* +X37908994Y-25129000D01* +X37908994Y-23829000D01* +X37884101Y-23696704D01* +X37827000Y-23607967D01* +X37827000Y-23602246D01* +X37856652Y-23572646D01* +X37956885Y-23331259D01* +X37957054Y-23136999D01* +X38711349Y-23136999D01* +X39254576Y-23680227D01* +X39254576Y-23680227D01* +G37* +X39254576Y-23680227D02* +X39249684Y-23687386D01* +X39221006Y-23829000D01* +X39221006Y-25129000D01* +X39245899Y-25261296D01* +X39324086Y-25382802D01* +X39443386Y-25464316D01* +X39585000Y-25492994D01* +X40085000Y-25492994D01* +X40217296Y-25468101D01* +X40338802Y-25389914D01* +X40420316Y-25270614D01* +X40448994Y-25129000D01* +X40448994Y-23829000D01* +X40424101Y-23696704D01* +X40345914Y-23575198D01* +X40311577Y-23551737D01* +X40303141Y-23509327D01* +X40290593Y-23446244D01* +X40524576Y-23680227D01* +X40519684Y-23687386D01* +X40491006Y-23829000D01* +X40491006Y-25129000D01* +X40515899Y-25261296D01* +X40594086Y-25382802D01* +X40713386Y-25464316D01* +X40855000Y-25492994D01* +X41305458Y-25492994D01* +X41305458Y-29119292D01* +X41230000Y-29194750D01* +X41230000Y-30194000D01* +X41252000Y-30194000D01* +X41252000Y-30448000D01* +X41230000Y-30448000D01* +X41230000Y-30468000D01* +X40980000Y-30468000D01* +X40980000Y-30448000D01* +X40958000Y-30448000D01* +X40958000Y-30194000D01* +X40980000Y-30194000D01* +X40980000Y-29310055D01* +X40982000Y-29300000D01* +X40982000Y-27314000D01* +X40947710Y-27141614D01* +X40945310Y-27129546D01* +X40840825Y-26973174D01* +X39145424Y-25277774D01* +X39150316Y-25270614D01* +X39178994Y-25129000D01* +X39178994Y-23829000D01* +X39154101Y-23696704D01* +X39075914Y-23575198D01* +X38956614Y-23493684D01* +X38815000Y-23465006D01* +X38315000Y-23465006D01* +X38182704Y-23489899D01* +X38061198Y-23568086D01* +X37979684Y-23687386D01* +X37951006Y-23829000D01* +X37951006Y-25129000D01* +X37975899Y-25261296D01* +X38054086Y-25382802D01* +X38088423Y-25406263D01* +X38109963Y-25514551D01* +X38119690Y-25563454D01* +X38224175Y-25719825D01* +X40018000Y-27513651D01* +X40018000Y-29300000D01* +X40019394Y-29307006D01* +X39585000Y-29307006D01* +X39452704Y-29331899D01* +X39331198Y-29410086D01* +X39249684Y-29529386D01* +X39221006Y-29671000D01* +X39221006Y-30971000D01* +X39229850Y-31018000D01* +X39169476Y-31018000D01* +X39178994Y-30971000D01* +X39178994Y-29671000D01* +X39154101Y-29538704D01* +X39075914Y-29417198D01* +X39041577Y-29393737D01* +X39010310Y-29236547D01* +X39010310Y-29236546D01* +X38905825Y-29080174D01* +X35584825Y-25759175D01* +X35428454Y-25654690D01* +X35397851Y-25648603D01* +X35244000Y-25618000D01* +X35000155Y-25618000D01* +X35040825Y-25590825D01* +X36681006Y-23950645D01* +X36681006Y-25129000D01* +X36705899Y-25261296D01* +X36784086Y-25382802D01* +X36903386Y-25464316D01* +X37045000Y-25492994D01* +X37545000Y-25492994D01* +X37677296Y-25468101D01* +X37798802Y-25389914D01* +X37880316Y-25270614D01* +X37908994Y-25129000D01* +X37908994Y-23829000D01* +X37884101Y-23696704D01* +X37827000Y-23607967D01* +X37827000Y-23602246D01* +X37856652Y-23572646D01* +X37956885Y-23331259D01* +X37957054Y-23136999D01* +X38711349Y-23136999D01* +X39254576Y-23680227D01* +G36* +X29761006Y-29547000D02* +X29738994Y-29547000D01* +X29738994Y-29360000D01* +X29761006Y-29360000D01* +X29761006Y-29547000D01* +X29761006Y-29547000D01* +G37* +X29761006Y-29547000D02* +X29738994Y-29547000D01* +X29738994Y-29360000D01* +X29761006Y-29360000D01* +X29761006Y-29547000D01* +G36* +X28764500Y-26010500D02* +X30235500Y-26010500D01* +X30235500Y-25990500D01* +X30489500Y-25990500D01* +X30489500Y-26010500D01* +X30509500Y-26010500D01* +X30509500Y-26264500D01* +X30489500Y-26264500D01* +X30489500Y-27735500D01* +X30509500Y-27735500D01* +X30509500Y-27989500D01* +X30489500Y-27989500D01* +X30489500Y-28009500D01* +X30235500Y-28009500D01* +X30235500Y-27989500D01* +X28764500Y-27989500D01* +X28764500Y-28009500D01* +X28510500Y-28009500D01* +X28510500Y-27989500D01* +X28490500Y-27989500D01* +X28490500Y-27735500D01* +X28510500Y-27735500D01* +X28510500Y-26264500D01* +X28764500Y-26264500D01* +X28764500Y-27735500D01* +X30235500Y-27735500D01* +X30235500Y-26264500D01* +X28764500Y-26264500D01* +X28510500Y-26264500D01* +X28490500Y-26264500D01* +X28490500Y-26010500D01* +X28510500Y-26010500D01* +X28510500Y-25990500D01* +X28764500Y-25990500D01* +X28764500Y-26010500D01* +X28764500Y-26010500D01* +G37* +X28764500Y-26010500D02* +X30235500Y-26010500D01* +X30235500Y-25990500D01* +X30489500Y-25990500D01* +X30489500Y-26010500D01* +X30509500Y-26010500D01* +X30509500Y-26264500D01* +X30489500Y-26264500D01* +X30489500Y-27735500D01* +X30509500Y-27735500D01* +X30509500Y-27989500D01* +X30489500Y-27989500D01* +X30489500Y-28009500D01* +X30235500Y-28009500D01* +X30235500Y-27989500D01* +X28764500Y-27989500D01* +X28764500Y-28009500D01* +X28510500Y-28009500D01* +X28510500Y-27989500D01* +X28490500Y-27989500D01* +X28490500Y-27735500D01* +X28510500Y-27735500D01* +X28510500Y-26264500D01* +X28764500Y-26264500D01* +X28764500Y-27735500D01* +X30235500Y-27735500D01* +X30235500Y-26264500D01* +X28764500Y-26264500D01* +X28510500Y-26264500D01* +X28490500Y-26264500D01* +X28490500Y-26010500D01* +X28510500Y-26010500D01* +X28510500Y-25990500D01* +X28764500Y-25990500D01* +X28764500Y-26010500D01* +G36* +X42256851Y-20727251D02* +X42157786Y-20875512D01* +X42125510Y-21037777D01* +X42122999Y-21050399D01* +X42122999Y-22524141D01* +X40735700Y-21136842D01* +X40587439Y-21037777D01* +X40412552Y-21002990D01* +X35517851Y-21002990D01* +X35517846Y-21002989D01* +X35342960Y-21037777D01* +X35194698Y-21136842D01* +X34747955Y-21583585D01* +X34649144Y-21583585D01* +X34735000Y-21376310D01* +X34735000Y-21283750D01* +X34576250Y-21125000D01* +X33927000Y-21125000D01* +X33927000Y-21726250D01* +X34012165Y-21811415D01* +X32480580Y-23343000D01* +X32305025Y-23343000D01* +X32438327Y-23209699D01* +X32535000Y-22976310D01* +X32535000Y-22685750D01* +X32376250Y-22527000D01* +X31477000Y-22527000D01* +X31477000Y-22547000D01* +X31223000Y-22547000D01* +X31223000Y-22527000D01* +X31203000Y-22527000D01* +X31203000Y-22273000D01* +X31223000Y-22273000D01* +X31223000Y-22253000D01* +X31477000Y-22253000D01* +X31477000Y-22273000D01* +X32376250Y-22273000D01* +X32535000Y-22114250D01* +X32535000Y-21823690D01* +X32448141Y-21613994D01* +X32965968Y-21613994D01* +X33140302Y-21788327D01* +X33373691Y-21885000D01* +X33514250Y-21885000D01* +X33673000Y-21726250D01* +X33673000Y-21125000D01* +X33653000Y-21125000D01* +X33653000Y-20875000D01* +X33673000Y-20875000D01* +X33673000Y-20853000D01* +X33927000Y-20853000D01* +X33927000Y-20875000D01* +X34576250Y-20875000D01* +X34735000Y-20716250D01* +X34735000Y-20632000D01* +X42352102Y-20632000D01* +X42256851Y-20727251D01* +X42256851Y-20727251D01* +G37* +X42256851Y-20727251D02* +X42157786Y-20875512D01* +X42125510Y-21037777D01* +X42122999Y-21050399D01* +X42122999Y-22524141D01* +X40735700Y-21136842D01* +X40587439Y-21037777D01* +X40412552Y-21002990D01* +X35517851Y-21002990D01* +X35517846Y-21002989D01* +X35342960Y-21037777D01* +X35194698Y-21136842D01* +X34747955Y-21583585D01* +X34649144Y-21583585D01* +X34735000Y-21376310D01* +X34735000Y-21283750D01* +X34576250Y-21125000D01* +X33927000Y-21125000D01* +X33927000Y-21726250D01* +X34012165Y-21811415D01* +X32480580Y-23343000D01* +X32305025Y-23343000D01* +X32438327Y-23209699D01* +X32535000Y-22976310D01* +X32535000Y-22685750D01* +X32376250Y-22527000D01* +X31477000Y-22527000D01* +X31477000Y-22547000D01* +X31223000Y-22547000D01* +X31223000Y-22527000D01* +X31203000Y-22527000D01* +X31203000Y-22273000D01* +X31223000Y-22273000D01* +X31223000Y-22253000D01* +X31477000Y-22253000D01* +X31477000Y-22273000D01* +X32376250Y-22273000D01* +X32535000Y-22114250D01* +X32535000Y-21823690D01* +X32448141Y-21613994D01* +X32965968Y-21613994D01* +X33140302Y-21788327D01* +X33373691Y-21885000D01* +X33514250Y-21885000D01* +X33673000Y-21726250D01* +X33673000Y-21125000D01* +X33653000Y-21125000D01* +X33653000Y-20875000D01* +X33673000Y-20875000D01* +X33673000Y-20853000D01* +X33927000Y-20853000D01* +X33927000Y-20875000D01* +X34576250Y-20875000D01* +X34735000Y-20716250D01* +X34735000Y-20632000D01* +X42352102Y-20632000D01* +X42256851Y-20727251D01* +G36* +X27640301Y-20361673D02* +X27545983Y-20455992D01* +X27326310Y-20365000D01* +X27035750Y-20365000D01* +X26877000Y-20523750D01* +X26877000Y-21125000D01* +X27676250Y-21125000D01* +X27728250Y-21073000D01* +X28125000Y-21073000D01* +X28125000Y-21053000D01* +X28375000Y-21053000D01* +X28375000Y-21073000D01* +X28976250Y-21073000D01* +X29076250Y-20973000D01* +X29523000Y-20973000D01* +X29523000Y-20953000D01* +X29777000Y-20953000D01* +X29777000Y-20973000D01* +X29797000Y-20973000D01* +X29797000Y-21227000D01* +X29777000Y-21227000D01* +X29777000Y-21247000D01* +X29523000Y-21247000D01* +X29523000Y-21227000D01* +X28623750Y-21227000D01* +X28523750Y-21327000D01* +X28375000Y-21327000D01* +X28375000Y-21347000D01* +X28125000Y-21347000D01* +X28125000Y-21327000D01* +X27523750Y-21327000D01* +X27475750Y-21375000D01* +X26877000Y-21375000D01* +X26877000Y-21976250D01* +X27035750Y-22135000D01* +X27326310Y-22135000D01* +X27559699Y-22038327D01* +X27600000Y-21998026D01* +X27636006Y-22034032D01* +X27636006Y-22600000D01* +X27660899Y-22732296D01* +X27699961Y-22793000D01* +X27563994Y-22793000D01* +X27563994Y-22500000D01* +X27539101Y-22367704D01* +X27460914Y-22246198D01* +X27341614Y-22164684D01* +X27200000Y-22136006D01* +X26300000Y-22136006D01* +X26167704Y-22160899D01* +X26046198Y-22239086D01* +X25964684Y-22358386D01* +X25936006Y-22500000D01* +X25936006Y-22835216D01* +X25924887Y-22827787D01* +X25863994Y-22815675D01* +X25863994Y-22800000D01* +X25839101Y-22667704D01* +X25760914Y-22546198D01* +X25707000Y-22509360D01* +X25707000Y-22228269D01* +X25782296Y-22214101D01* +X25903802Y-22135914D01* +X25963823Y-22048070D01* +X26173690Y-22135000D01* +X26464250Y-22135000D01* +X26623000Y-21976250D01* +X26623000Y-21375000D01* +X26603000Y-21375000D01* +X26603000Y-21125000D01* +X26623000Y-21125000D01* +X26623000Y-20523750D01* +X26464250Y-20365000D01* +X26173690Y-20365000D01* +X25940301Y-20461673D01* +X25761673Y-20640302D01* +X25706903Y-20772529D01* +X25650000Y-20761006D01* +X24850000Y-20761006D01* +X24717704Y-20785899D01* +X24596198Y-20864086D01* +X24514684Y-20983386D01* +X24500514Y-21053359D01* +X24489101Y-20992704D01* +X24410914Y-20871198D01* +X24291614Y-20789684D01* +X24150000Y-20761006D01* +X24027000Y-20761006D01* +X24027000Y-20332000D01* +X27711938Y-20332000D01* +X27640301Y-20361673D01* +X27640301Y-20361673D01* +G37* +X27640301Y-20361673D02* +X27545983Y-20455992D01* +X27326310Y-20365000D01* +X27035750Y-20365000D01* +X26877000Y-20523750D01* +X26877000Y-21125000D01* +X27676250Y-21125000D01* +X27728250Y-21073000D01* +X28125000Y-21073000D01* +X28125000Y-21053000D01* +X28375000Y-21053000D01* +X28375000Y-21073000D01* +X28976250Y-21073000D01* +X29076250Y-20973000D01* +X29523000Y-20973000D01* +X29523000Y-20953000D01* +X29777000Y-20953000D01* +X29777000Y-20973000D01* +X29797000Y-20973000D01* +X29797000Y-21227000D01* +X29777000Y-21227000D01* +X29777000Y-21247000D01* +X29523000Y-21247000D01* +X29523000Y-21227000D01* +X28623750Y-21227000D01* +X28523750Y-21327000D01* +X28375000Y-21327000D01* +X28375000Y-21347000D01* +X28125000Y-21347000D01* +X28125000Y-21327000D01* +X27523750Y-21327000D01* +X27475750Y-21375000D01* +X26877000Y-21375000D01* +X26877000Y-21976250D01* +X27035750Y-22135000D01* +X27326310Y-22135000D01* +X27559699Y-22038327D01* +X27600000Y-21998026D01* +X27636006Y-22034032D01* +X27636006Y-22600000D01* +X27660899Y-22732296D01* +X27699961Y-22793000D01* +X27563994Y-22793000D01* +X27563994Y-22500000D01* +X27539101Y-22367704D01* +X27460914Y-22246198D01* +X27341614Y-22164684D01* +X27200000Y-22136006D01* +X26300000Y-22136006D01* +X26167704Y-22160899D01* +X26046198Y-22239086D01* +X25964684Y-22358386D01* +X25936006Y-22500000D01* +X25936006Y-22835216D01* +X25924887Y-22827787D01* +X25863994Y-22815675D01* +X25863994Y-22800000D01* +X25839101Y-22667704D01* +X25760914Y-22546198D01* +X25707000Y-22509360D01* +X25707000Y-22228269D01* +X25782296Y-22214101D01* +X25903802Y-22135914D01* +X25963823Y-22048070D01* +X26173690Y-22135000D01* +X26464250Y-22135000D01* +X26623000Y-21976250D01* +X26623000Y-21375000D01* +X26603000Y-21375000D01* +X26603000Y-21125000D01* +X26623000Y-21125000D01* +X26623000Y-20523750D01* +X26464250Y-20365000D01* +X26173690Y-20365000D01* +X25940301Y-20461673D01* +X25761673Y-20640302D01* +X25706903Y-20772529D01* +X25650000Y-20761006D01* +X24850000Y-20761006D01* +X24717704Y-20785899D01* +X24596198Y-20864086D01* +X24514684Y-20983386D01* +X24500514Y-21053359D01* +X24489101Y-20992704D01* +X24410914Y-20871198D01* +X24291614Y-20789684D01* +X24150000Y-20761006D01* +X24027000Y-20761006D01* +X24027000Y-20332000D01* +X27711938Y-20332000D01* +X27640301Y-20361673D01* +M02* diff --git a/board/v1/gerber/handgelenk.gto b/board/v1/gerber/handgelenk.gto new file mode 100644 index 0000000..723d05c --- /dev/null +++ b/board/v1/gerber/handgelenk.gto @@ -0,0 +1,2862 @@ +G04 #@! TF.FileFunction,Legend,Top* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11C,0.300000*% +%ADD12C,0.150000*% +%ADD13C,0.200000*% +%ADD14C,0.010000*% +G04 APERTURE END LIST* +D10* +D11* +X31157144Y-34492857D02* +X31657144Y-34492857D01* +X31871430Y-35278571D02* +X31157144Y-35278571D01* +X31157144Y-33778571D01* +X31871430Y-33778571D01* +X32442858Y-35207143D02* +X32657144Y-35278571D01* +X33014287Y-35278571D01* +X33157144Y-35207143D01* +X33228573Y-35135714D01* +X33300001Y-34992857D01* +X33300001Y-34850000D01* +X33228573Y-34707143D01* +X33157144Y-34635714D01* +X33014287Y-34564286D01* +X32728573Y-34492857D01* +X32585715Y-34421429D01* +X32514287Y-34350000D01* +X32442858Y-34207143D01* +X32442858Y-34064286D01* +X32514287Y-33921429D01* +X32585715Y-33850000D01* +X32728573Y-33778571D01* +X33085715Y-33778571D01* +X33300001Y-33850000D01* +X33942858Y-35278571D02* +X33942858Y-33778571D01* +X34514286Y-33778571D01* +X34657144Y-33850000D01* +X34728572Y-33921429D01* +X34800001Y-34064286D01* +X34800001Y-34278571D01* +X34728572Y-34421429D01* +X34657144Y-34492857D01* +X34514286Y-34564286D01* +X33942858Y-34564286D01* +X35657144Y-34421429D02* +X35514286Y-34350000D01* +X35442858Y-34278571D01* +X35371429Y-34135714D01* +X35371429Y-34064286D01* +X35442858Y-33921429D01* +X35514286Y-33850000D01* +X35657144Y-33778571D01* +X35942858Y-33778571D01* +X36085715Y-33850000D01* +X36157144Y-33921429D01* +X36228572Y-34064286D01* +X36228572Y-34135714D01* +X36157144Y-34278571D01* +X36085715Y-34350000D01* +X35942858Y-34421429D01* +X35657144Y-34421429D01* +X35514286Y-34492857D01* +X35442858Y-34564286D01* +X35371429Y-34707143D01* +X35371429Y-34992857D01* +X35442858Y-35135714D01* +X35514286Y-35207143D01* +X35657144Y-35278571D01* +X35942858Y-35278571D01* +X36085715Y-35207143D01* +X36157144Y-35135714D01* +X36228572Y-34992857D01* +X36228572Y-34707143D01* +X36157144Y-34564286D01* +X36085715Y-34492857D01* +X35942858Y-34421429D01* +X36800000Y-33921429D02* +X36871429Y-33850000D01* +X37014286Y-33778571D01* +X37371429Y-33778571D01* +X37514286Y-33850000D01* +X37585715Y-33921429D01* +X37657143Y-34064286D01* +X37657143Y-34207143D01* +X37585715Y-34421429D01* +X36728572Y-35278571D01* +X37657143Y-35278571D01* +X38942857Y-33778571D02* +X38657143Y-33778571D01* +X38514286Y-33850000D01* +X38442857Y-33921429D01* +X38300000Y-34135714D01* +X38228571Y-34421429D01* +X38228571Y-34992857D01* +X38300000Y-35135714D01* +X38371428Y-35207143D01* +X38514286Y-35278571D01* +X38800000Y-35278571D01* +X38942857Y-35207143D01* +X39014286Y-35135714D01* +X39085714Y-34992857D01* +X39085714Y-34635714D01* +X39014286Y-34492857D01* +X38942857Y-34421429D01* +X38800000Y-34350000D01* +X38514286Y-34350000D01* +X38371428Y-34421429D01* +X38300000Y-34492857D01* +X38228571Y-34635714D01* +X40371428Y-33778571D02* +X40085714Y-33778571D01* +X39942857Y-33850000D01* +X39871428Y-33921429D01* +X39728571Y-34135714D01* +X39657142Y-34421429D01* +X39657142Y-34992857D01* +X39728571Y-35135714D01* +X39799999Y-35207143D01* +X39942857Y-35278571D01* +X40228571Y-35278571D01* +X40371428Y-35207143D01* +X40442857Y-35135714D01* +X40514285Y-34992857D01* +X40514285Y-34635714D01* +X40442857Y-34492857D01* +X40371428Y-34421429D01* +X40228571Y-34350000D01* +X39942857Y-34350000D01* +X39799999Y-34421429D01* +X39728571Y-34492857D01* +X39657142Y-34635714D01* +D12* +X23650000Y-45350000D02* +X23650000Y-44650000D01* +X24850000Y-44650000D02* +X24850000Y-45350000D01* +X32125000Y-24375000D02* +X32125000Y-24900000D01* +X26875000Y-29625000D02* +X26875000Y-29100000D01* +X32125000Y-29625000D02* +X32125000Y-29100000D01* +X26875000Y-24375000D02* +X27400000Y-24375000D01* +X26875000Y-29625000D02* +X27400000Y-29625000D01* +X32125000Y-29625000D02* +X31600000Y-29625000D01* +X32125000Y-24375000D02* +X31600000Y-24375000D01* +X44996696Y-40230000D02* +X47536696Y-40230000D01* +X42176696Y-39950000D02* +X43726696Y-39950000D01* +X44996696Y-40230000D02* +X44996696Y-42770000D01* +X43726696Y-43050000D02* +X42176696Y-43050000D01* +X42176696Y-43050000D02* +X42176696Y-39950000D01* +X44996696Y-42770000D02* +X47536696Y-42770000D01* +X47536696Y-42770000D02* +X47536696Y-40230000D01* +X44300000Y-34100000D02* +X44800000Y-34100000D01* +X44300000Y-37100000D02* +X44300000Y-34100000D01* +X44800000Y-37100000D02* +X44300000Y-37100000D01* +X50300000Y-34100000D02* +X49800000Y-34100000D01* +X50300000Y-37100000D02* +X50300000Y-34100000D01* +X49800000Y-37100000D02* +X50300000Y-37100000D01* +X23400000Y-40500000D02* +X22700000Y-40500000D01* +X22700000Y-39300000D02* +X23400000Y-39300000D01* +D13* +X37200000Y-29400000D02* +G75* +G03X37200000Y-29400000I-100000J0D01* +G01* +D12* +X36950000Y-29900000D02* +X36700000Y-29900000D01* +X36700000Y-29900000D02* +X36700000Y-25650000D01* +X36700000Y-25650000D02* +X36700000Y-24900000D01* +X36700000Y-24900000D02* +X36950000Y-24900000D01* +X41450000Y-29900000D02* +X41700000Y-29900000D01* +X41700000Y-29900000D02* +X41700000Y-26400000D01* +X41700000Y-26400000D02* +X41700000Y-24900000D01* +X41700000Y-24900000D02* +X41450000Y-24900000D01* +X22500000Y-22500000D02* +X22500000Y-29500000D01* +X20500000Y-29500000D02* +X20500000Y-22500000D01* +X28900000Y-30400000D02* +X29600000Y-30400000D01* +X29600000Y-31600000D02* +X28900000Y-31600000D01* +X27350000Y-47650000D02* +X27350000Y-48350000D01* +X26150000Y-48350000D02* +X26150000Y-47650000D01* +X38600000Y-47650000D02* +X38600000Y-48350000D01* +X37400000Y-48350000D02* +X37400000Y-47650000D01* +X46775000Y-48250000D02* +X46775000Y-46250000D01* +X44725000Y-46250000D02* +X44725000Y-48250000D01* +X44350000Y-47650000D02* +X44350000Y-48350000D01* +X43150000Y-48350000D02* +X43150000Y-47650000D01* +X23750000Y-26475000D02* +X24250000Y-26475000D01* +X24250000Y-25525000D02* +X23750000Y-25525000D01* +X27775000Y-21500000D02* +X27775000Y-22000000D01* +X28725000Y-22000000D02* +X28725000Y-21500000D01* +X33500000Y-20525000D02* +X33000000Y-20525000D01* +X33000000Y-21475000D02* +X33500000Y-21475000D01* +X24850000Y-22100000D02* +X24150000Y-22100000D01* +X24150000Y-20900000D02* +X24850000Y-20900000D01* +X49920702Y-23448198D02* +X49920702Y-22748198D01* +X51120702Y-22748198D02* +X51120702Y-23448198D01* +X51670702Y-23448198D02* +X51670702Y-22748198D01* +X52870702Y-22748198D02* +X52870702Y-23448198D01* +X47620702Y-26948198D02* +X46920702Y-26948198D01* +X46920702Y-25748198D02* +X47620702Y-25748198D01* +X51900000Y-35250000D02* +X51900000Y-35950000D01* +X50700000Y-35950000D02* +X50700000Y-35250000D01* +X28250000Y-44650000D02* +X27250000Y-44650000D01* +X27250000Y-46350000D02* +X28250000Y-46350000D01* +X34230000Y-46480000D02* +X34230000Y-43940000D01* +X33950000Y-49300000D02* +X33950000Y-47750000D01* +X34230000Y-46480000D02* +X36770000Y-46480000D01* +X37050000Y-47750000D02* +X37050000Y-49300000D01* +X37050000Y-49300000D02* +X33950000Y-49300000D01* +X36770000Y-46480000D02* +X36770000Y-43940000D01* +X36770000Y-43940000D02* +X34230000Y-43940000D01* +X23825000Y-28750000D02* +X23825000Y-27750000D01* +X25175000Y-27750000D02* +X25175000Y-28750000D01* +X27425000Y-21500000D02* +X27425000Y-22500000D01* +X26075000Y-22500000D02* +X26075000Y-21500000D01* +X28075000Y-48750000D02* +X28075000Y-47750000D01* +X29425000Y-47750000D02* +X29425000Y-48750000D01* +X24000000Y-22575000D02* +X25000000Y-22575000D01* +X25000000Y-23925000D02* +X24000000Y-23925000D01* +X33325000Y-26500000D02* +X33325000Y-25500000D01* +X34675000Y-25500000D02* +X34675000Y-26500000D01* +X39250000Y-45675000D02* +X38250000Y-45675000D01* +X38250000Y-44325000D02* +X39250000Y-44325000D01* +X42250000Y-45675000D02* +X41250000Y-45675000D01* +X41250000Y-44325000D02* +X42250000Y-44325000D01* +X52375000Y-36100000D02* +X52375000Y-35100000D01* +X53725000Y-35100000D02* +X53725000Y-36100000D01* +X32125000Y-43875000D02* +X31600000Y-43875000D01* +X26875000Y-38625000D02* +X27400000Y-38625000D01* +X26875000Y-43875000D02* +X27400000Y-43875000D01* +X32125000Y-38625000D02* +X32125000Y-39150000D01* +X26875000Y-38625000D02* +X26875000Y-39150000D01* +X26875000Y-43875000D02* +X26875000Y-43350000D01* +X32125000Y-43875000D02* +X32125000Y-43350000D01* +X31900000Y-49700000D02* +G75* +G03X31900000Y-49700000I-100000J0D01* +G01* +X31250000Y-49450000D02* +X31750000Y-49450000D01* +X31250000Y-46550000D02* +X31250000Y-49450000D01* +X31750000Y-46550000D02* +X31250000Y-46550000D01* +X31750000Y-49450000D02* +X31750000Y-46550000D01* +X45920702Y-24698198D02* +X45920702Y-24298198D01* +X45920702Y-24698198D02* +X46320702Y-24698198D01* +X49120702Y-24698198D02* +X49120702Y-24298198D01* +X49120702Y-24698198D02* +X48720702Y-24698198D01* +X49120702Y-21498198D02* +X49120702Y-21898198D01* +X49120702Y-21498198D02* +X48720702Y-21498198D01* +X45920702Y-21498198D02* +X46320702Y-21498198D01* +X40800000Y-46300000D02* +G75* +G03X40800000Y-46300000I-100000J0D01* +G01* +X41250000Y-46550000D02* +X40750000Y-46550000D01* +X41250000Y-49450000D02* +X41250000Y-46550000D01* +X40750000Y-49450000D02* +X41250000Y-49450000D01* +X40750000Y-46550000D02* +X40750000Y-49450000D01* +X31750000Y-21850000D02* +X31750000Y-21650000D01* +X30300000Y-22750000D02* +X30700000Y-22750000D01* +X29250000Y-21850000D02* +X29250000Y-21650000D01* +X30300000Y-20750000D02* +X30700000Y-20750000D01* +D14* +G36* +X51314007Y-28961083D02* +X51320704Y-28863677D01* +X51333721Y-28768600D01* +X51353213Y-28674982D01* +X51379333Y-28581953D01* +X51412237Y-28488644D01* +X51418051Y-28473857D01* +X51453375Y-28392874D01* +X51494530Y-28312031D01* +X51540827Y-28232317D01* +X51591578Y-28154716D01* +X51646094Y-28080215D01* +X51703687Y-28009800D01* +X51763667Y-27944457D01* +X51825346Y-27885173D01* +X51835231Y-27876400D01* +X51871086Y-27844939D01* +X51871086Y-27662759D01* +X51871118Y-27617597D01* +X51871258Y-27578945D01* +X51871567Y-27546059D01* +X51872108Y-27518192D01* +X51872942Y-27494599D01* +X51874133Y-27474533D01* +X51875742Y-27457248D01* +X51877832Y-27442000D01* +X51880465Y-27428041D01* +X51883704Y-27414626D01* +X51887610Y-27401009D01* +X51892246Y-27386444D01* +X51894811Y-27378712D01* +X51910254Y-27338793D01* +X51930440Y-27296322D01* +X51954308Y-27253102D01* +X51980795Y-27210935D01* +X52008839Y-27171625D01* +X52036821Y-27137598D01* +X52074829Y-27098870D01* +X52118146Y-27061424D01* +X52165523Y-27026026D01* +X52215710Y-26993439D01* +X52267460Y-26964427D01* +X52319523Y-26939755D01* +X52370650Y-26920185D01* +X52411545Y-26908350D01* +X52423292Y-26905588D01* +X52434699Y-26903141D01* +X52446254Y-26900991D01* +X52458445Y-26899123D01* +X52471759Y-26897520D01* +X52486682Y-26896164D01* +X52503702Y-26895041D01* +X52523307Y-26894132D01* +X52545984Y-26893421D01* +X52572220Y-26892892D01* +X52602502Y-26892528D01* +X52637317Y-26892312D01* +X52677153Y-26892229D01* +X52722498Y-26892260D01* +X52773838Y-26892390D01* +X52831660Y-26892602D01* +X52868943Y-26892759D01* +X52927210Y-26893023D01* +X52978672Y-26893286D01* +X53023784Y-26893557D01* +X53062996Y-26893846D01* +X53096764Y-26894161D01* +X53125539Y-26894512D01* +X53149773Y-26894907D01* +X53169922Y-26895356D01* +X53186436Y-26895867D01* +X53199769Y-26896451D01* +X53210374Y-26897115D01* +X53218703Y-26897869D01* +X53225211Y-26898723D01* +X53230348Y-26899684D01* +X53231890Y-26900044D01* +X53265394Y-26909489D01* +X53297449Y-26921208D01* +X53328853Y-26935698D01* +X53360404Y-26953455D01* +X53392899Y-26974977D01* +X53427136Y-27000761D01* +X53463912Y-27031303D01* +X53504026Y-27067101D01* +X53512444Y-27074866D01* +X53561739Y-27124440D01* +X53604205Y-27175650D01* +X53640195Y-27229107D01* +X53670067Y-27285423D01* +X53694173Y-27345207D01* +X53712868Y-27409069D01* +X53716963Y-27426762D01* +X53718994Y-27436109D01* +X53720722Y-27444606D01* +X53722179Y-27452921D01* +X53723395Y-27461720D01* +X53724400Y-27471673D01* +X53725226Y-27483447D01* +X53725904Y-27497709D01* +X53726465Y-27515128D01* +X53726938Y-27536371D01* +X53727356Y-27562106D01* +X53727749Y-27593000D01* +X53728148Y-27629722D01* +X53728584Y-27672939D01* +X53728650Y-27679576D01* +X53730728Y-27888595D01* +X53753762Y-27907076D01* +X53824560Y-27968188D01* +X53892371Y-28035298D01* +X53956474Y-28107512D01* +X54016150Y-28183936D01* +X54070679Y-28263673D01* +X54119340Y-28345830D01* +X54142835Y-28390705D01* +X54181088Y-28472768D01* +X54213087Y-28553668D01* +X54239309Y-28634949D01* +X54260235Y-28718154D01* +X54276342Y-28804826D01* +X54280744Y-28834900D01* +X54283224Y-28857395D01* +X54285384Y-28885524D01* +X54287188Y-28917807D01* +X54288603Y-28952766D01* +X54289594Y-28988922D01* +X54290127Y-29024797D01* +X54290169Y-29058910D01* +X54289684Y-29089784D01* +X54288640Y-29115940D01* +X54287560Y-29130629D01* +X54274484Y-29231476D01* +X54254557Y-29329938D01* +X54227809Y-29425942D01* +X54194268Y-29519413D01* +X54153965Y-29610277D01* +X54106927Y-29698459D01* +X54053185Y-29783886D01* +X54005146Y-29850504D01* +X53962055Y-29903885D01* +X53915009Y-29956706D01* +X53865606Y-30007315D01* +X53815447Y-30054063D01* +X53773364Y-30089569D01* +X53732543Y-30122239D01* +X53732528Y-30314955D01* +X53732492Y-30361324D01* +X53732357Y-30401164D01* +X53732072Y-30435202D01* +X53731587Y-30464166D01* +X53730851Y-30488783D01* +X53729813Y-30509782D01* +X53728423Y-30527890D01* +X53726628Y-30543834D01* +X53724380Y-30558343D01* +X53721626Y-30572143D01* +X53718317Y-30585963D01* +X53714401Y-30600530D01* +X53712007Y-30608999D01* +X53689681Y-30674042D01* +X53660568Y-30736684D01* +X53624632Y-30796988D01* +X53591028Y-30842553D01* +X53591028Y-29178339D01* +X53590960Y-28431491D01* +X53590936Y-28356840D01* +X53590879Y-28283254D01* +X53590792Y-28211133D01* +X53590675Y-28140880D01* +X53590530Y-28072897D01* +X53590360Y-28007584D01* +X53590165Y-27945343D01* +X53589947Y-27886577D01* +X53589708Y-27831686D01* +X53589450Y-27781072D01* +X53589174Y-27735137D01* +X53588882Y-27694283D01* +X53588576Y-27658911D01* +X53588257Y-27629422D01* +X53587927Y-27606219D01* +X53587588Y-27589703D01* +X53587443Y-27584857D01* +X53585929Y-27543996D01* +X53584292Y-27509421D01* +X53582298Y-27480162D01* +X53579711Y-27455249D01* +X53576294Y-27433711D01* +X53571814Y-27414580D01* +X53566033Y-27396884D01* +X53558718Y-27379654D01* +X53549631Y-27361919D01* +X53538538Y-27342709D01* +X53525203Y-27321055D01* +X53522257Y-27316361D01* +X53483286Y-27260247D01* +X53440558Y-27209685D01* +X53394379Y-27164931D01* +X53345059Y-27126239D01* +X53292905Y-27093865D01* +X53238226Y-27068062D01* +X53208760Y-27057281D01* +X53198837Y-27054165D01* +X53188741Y-27051418D01* +X53177972Y-27049018D01* +X53166028Y-27046940D01* +X53152407Y-27045162D01* +X53136609Y-27043662D01* +X53118133Y-27042416D01* +X53096477Y-27041402D01* +X53071140Y-27040596D01* +X53041620Y-27039976D01* +X53007417Y-27039519D01* +X52968028Y-27039202D01* +X52922954Y-27039002D01* +X52871693Y-27038896D01* +X52813742Y-27038861D01* +X52805443Y-27038860D01* +X52742856Y-27038908D01* +X52687296Y-27039054D01* +X52638532Y-27039302D01* +X52596334Y-27039654D01* +X52560471Y-27040113D01* +X52530714Y-27040683D01* +X52506832Y-27041367D01* +X52488595Y-27042167D01* +X52475772Y-27043087D01* +X52474169Y-27043249D01* +X52425842Y-27051863D01* +X52376979Y-27067140D01* +X52328327Y-27088602D01* +X52280635Y-27115771D01* +X52234651Y-27148167D01* +X52191122Y-27185311D01* +X52150796Y-27226726D01* +X52114423Y-27271931D01* +X52112318Y-27274843D01* +X52098972Y-27295130D01* +X52084993Y-27319313D01* +X52071263Y-27345585D01* +X52058663Y-27372140D01* +X52048074Y-27397172D01* +X52040377Y-27418875D01* +X52038106Y-27427014D01* +X52035938Y-27436044D01* +X52033979Y-27444936D01* +X52032218Y-27454092D01* +X52030643Y-27463915D01* +X52029242Y-27474806D01* +X52028001Y-27487168D01* +X52026910Y-27501404D01* +X52025956Y-27517914D01* +X52025125Y-27537102D01* +X52024407Y-27559369D01* +X52023790Y-27585118D01* +X52023259Y-27614750D01* +X52022805Y-27648668D01* +X52022413Y-27687274D01* +X52022073Y-27730970D01* +X52021771Y-27780159D01* +X52021496Y-27835241D01* +X52021236Y-27896620D01* +X52020977Y-27964698D01* +X52020875Y-27993072D01* +X52019209Y-28457529D01* +X52032282Y-28497939D01* +X52051581Y-28549096D01* +X52075531Y-28596936D01* +X52104839Y-28642616D01* +X52140216Y-28687292D01* +X52164916Y-28714377D01* +X52201953Y-28750922D01* +X52240229Y-28784558D01* +X52278957Y-28814758D01* +X52317351Y-28840999D01* +X52354624Y-28862753D01* +X52389991Y-28879497D01* +X52422665Y-28890704D01* +X52432270Y-28893003D01* +X52443660Y-28895050D01* +X52457838Y-28896915D01* +X52475199Y-28898616D01* +X52496142Y-28900166D01* +X52521063Y-28901580D01* +X52550359Y-28902875D01* +X52584427Y-28904064D01* +X52623664Y-28905163D01* +X52668467Y-28906187D01* +X52719232Y-28907151D01* +X52776358Y-28908070D01* +X52840240Y-28908960D01* +X52858057Y-28909189D01* +X52913362Y-28909906D01* +X52961967Y-28910597D01* +X53004426Y-28911302D01* +X53041296Y-28912065D01* +X53073132Y-28912926D01* +X53100491Y-28913926D01* +X53123927Y-28915109D01* +X53143997Y-28916515D01* +X53161257Y-28918186D01* +X53176262Y-28920164D01* +X53189568Y-28922491D01* +X53201732Y-28925208D01* +X53213308Y-28928356D01* +X53224852Y-28931978D01* +X53236921Y-28936116D01* +X53242240Y-28938002D01* +X53291538Y-28957363D01* +X53338052Y-28979469D01* +X53382855Y-29005017D01* +X53427024Y-29034699D01* +X53471631Y-29069210D01* +X53517753Y-29109244D01* +X53541136Y-29130996D01* +X53591028Y-29178339D01* +X53591028Y-30842553D01* +X53581836Y-30855018D01* +X53540095Y-30902542D01* +X53486415Y-30954413D01* +X53429855Y-30999627D01* +X53370396Y-31038192D01* +X53308022Y-31070119D01* +X53242714Y-31095419D01* +X53180218Y-31112806D01* +X53174160Y-31114153D01* +X53168158Y-31115336D01* +X53161714Y-31116368D01* +X53154331Y-31117262D01* +X53145511Y-31118032D01* +X53134758Y-31118688D01* +X53121575Y-31119245D01* +X53105464Y-31119715D01* +X53085927Y-31120111D01* +X53062469Y-31120446D01* +X53034592Y-31120731D01* +X53001798Y-31120981D01* +X52963590Y-31121207D01* +X52919471Y-31121422D01* +X52868945Y-31121640D01* +X52829028Y-31121802D01* +X52772370Y-31122025D01* +X52722446Y-31122197D01* +X52678734Y-31122298D01* +X52640712Y-31122311D01* +X52607857Y-31122217D01* +X52579647Y-31121997D01* +X52555559Y-31121632D01* +X52535071Y-31121103D01* +X52517660Y-31120393D01* +X52502804Y-31119481D01* +X52489980Y-31118350D01* +X52478667Y-31116980D01* +X52468341Y-31115354D01* +X52458479Y-31113451D01* +X52448561Y-31111254D01* +X52438062Y-31108744D01* +X52433514Y-31107631D01* +X52374676Y-31089738D01* +X52331667Y-31071766D01* +X52331667Y-30744449D01* +X52343950Y-30742278D01* +X52345400Y-30741964D01* +X52363344Y-30737998D01* +X52387171Y-30732665D01* +X52416294Y-30726100D01* +X52450127Y-30718437D01* +X52488082Y-30709812D01* +X52529572Y-30700360D01* +X52574010Y-30690216D01* +X52620808Y-30679514D01* +X52669379Y-30668390D01* +X52719137Y-30656978D01* +X52769494Y-30645415D01* +X52819863Y-30633834D01* +X52869657Y-30622371D01* +X52918288Y-30611161D01* +X52965169Y-30600339D01* +X53009714Y-30590039D01* +X53051335Y-30580397D01* +X53089445Y-30571548D01* +X53123457Y-30563627D01* +X53152783Y-30556768D01* +X53176837Y-30551108D01* +X53195031Y-30546780D01* +X53206778Y-30543920D01* +X53207351Y-30543776D01* +X53220590Y-30540221D01* +X53228515Y-30536572D01* +X53232841Y-30530936D01* +X53235284Y-30521423D01* +X53236814Y-30511300D01* +X53237256Y-30504209D01* +X53237474Y-30491511D01* +X53237492Y-30474329D01* +X53237336Y-30453786D01* +X53237028Y-30431006D01* +X53236592Y-30407111D01* +X53236053Y-30383225D01* +X53235435Y-30360470D01* +X53234761Y-30339970D01* +X53234056Y-30322848D01* +X53233344Y-30310226D01* +X53232648Y-30303228D01* +X53232344Y-30302211D01* +X53228367Y-30301041D01* +X53218052Y-30298681D01* +X53202187Y-30295294D01* +X53181563Y-30291043D01* +X53156972Y-30286089D01* +X53129203Y-30280596D01* +X53099047Y-30274727D01* +X53093914Y-30273737D01* +X53044010Y-30264092D01* +X52995723Y-30254702D01* +X52949570Y-30245668D01* +X52906064Y-30237095D01* +X52865722Y-30229086D01* +X52829057Y-30221744D01* +X52796585Y-30215173D01* +X52768821Y-30209476D01* +X52746279Y-30204758D01* +X52729475Y-30201120D01* +X52718923Y-30198667D01* +X52715530Y-30197709D01* +X52711190Y-30195627D01* +X52712131Y-30193873D01* +X52719152Y-30191596D01* +X52721986Y-30190837D01* +X52727976Y-30189508D01* +X52740465Y-30186940D01* +X52758822Y-30183259D01* +X52782417Y-30178586D01* +X52810620Y-30173046D01* +X52842801Y-30166763D01* +X52878330Y-30159859D01* +X52916576Y-30152459D01* +X52956910Y-30144686D01* +X52975986Y-30141020D01* +X53016890Y-30133131D01* +X53055855Y-30125546D01* +X53092270Y-30118391D01* +X53125523Y-30111787D01* +X53155002Y-30105858D01* +X53180094Y-30100729D01* +X53200188Y-30096522D01* +X53214672Y-30093361D01* +X53222933Y-30091370D01* +X53224513Y-30090863D01* +X53232753Y-30083418D01* +X53235877Y-30075837D01* +X53236724Y-30068086D01* +X53237404Y-30054382D01* +X53237917Y-30035975D01* +X53238264Y-30014115D01* +X53238447Y-29990053D01* +X53238467Y-29965040D01* +X53238325Y-29940324D01* +X53238023Y-29917156D01* +X53237561Y-29896787D01* +X53236942Y-29880467D01* +X53236166Y-29869446D01* +X53235659Y-29866034D01* +X53233213Y-29856768D01* +X53231153Y-29851053D01* +X53230779Y-29850485D01* +X53226883Y-29849246D01* +X53216446Y-29846521D01* +X53199980Y-29842426D01* +X53177995Y-29837080D01* +X53151005Y-29830602D01* +X53119520Y-29823110D01* +X53084053Y-29814722D01* +X53045114Y-29805557D01* +X53003215Y-29795732D01* +X52958868Y-29785367D01* +X52912585Y-29774579D01* +X52864877Y-29763487D01* +X52816256Y-29752209D01* +X52767232Y-29740864D01* +X52718319Y-29729569D01* +X52670028Y-29718444D01* +X52622869Y-29707606D01* +X52577355Y-29697173D01* +X52571400Y-29695813D01* +X52571400Y-29511629D01* +X53239057Y-29511629D01* +X53239057Y-29286657D01* +X52571400Y-29286657D01* +X52571400Y-29511629D01* +X52571400Y-29695813D01* +X52533998Y-29687265D01* +X52493308Y-29677999D01* +X52455798Y-29669494D01* +X52421979Y-29661868D01* +X52392363Y-29655239D01* +X52386245Y-29653885D01* +X52386245Y-29530764D01* +X52409364Y-29526858D01* +X52421396Y-29522233D01* +X52442198Y-29508641D01* +X52461165Y-29489695D01* +X52476873Y-29467287D01* +X52487896Y-29443308D01* +X52491680Y-29428894D01* +X52493524Y-29408350D01* +X52492817Y-29384207D01* +X52489813Y-29359559D01* +X52484768Y-29337499D01* +X52483977Y-29334988D01* +X52472394Y-29308874D01* +X52456472Y-29286826D01* +X52437108Y-29269791D01* +X52415199Y-29258716D01* +X52410276Y-29257213D01* +X52392365Y-29254692D01* +X52371811Y-29255310D01* +X52351893Y-29258759D01* +X52337087Y-29264098D01* +X52321708Y-29274584D01* +X52306242Y-29289535D01* +X52292903Y-29306535D01* +X52284657Y-29321328D01* +X52277135Y-29344367D01* +X52272491Y-29370397D01* +X52270775Y-29397388D01* +X52272042Y-29423306D01* +X52276340Y-29446120D01* +X52281155Y-29459099D01* +X52291165Y-29475559D01* +X52304837Y-29492455D01* +X52320227Y-29507734D01* +X52335393Y-29519344D01* +X52341376Y-29522704D01* +X52362686Y-29529385D01* +X52386245Y-29530764D01* +X52386245Y-29653885D01* +X52367462Y-29649726D01* +X52347786Y-29645447D01* +X52333847Y-29642520D01* +X52326158Y-29641064D01* +X52324759Y-29640944D01* +X52324272Y-29644897D01* +X52323758Y-29655259D01* +X52323239Y-29671181D01* +X52322735Y-29691815D01* +X52322268Y-29716313D01* +X52321859Y-29743827D01* +X52321595Y-29766836D01* +X52320347Y-29890814D01* +X52466738Y-29912138D01* +X52512368Y-29918806D01* +X52556944Y-29925360D01* +X52599849Y-29931707D01* +X52640467Y-29937755D01* +X52678182Y-29943409D01* +X52712377Y-29948577D01* +X52742436Y-29953166D01* +X52767744Y-29957083D01* +X52787684Y-29960235D01* +X52801641Y-29962527D01* +X52808773Y-29963821D01* +X52815403Y-29965921D01* +X52815235Y-29968225D01* +X52814216Y-29968865D01* +X52809045Y-29970472D01* +X52796935Y-29973467D01* +X52778061Y-29977811D01* +X52752601Y-29983467D01* +X52720731Y-29990397D01* +X52682626Y-29998562D01* +X52638464Y-30007925D01* +X52588420Y-30018447D01* +X52532671Y-30030092D01* +X52471393Y-30042820D01* +X52459374Y-30045309D01* +X52428594Y-30051701D01* +X52400111Y-30057653D01* +X52374691Y-30063004D01* +X52353101Y-30067590D01* +X52336106Y-30071247D01* +X52324473Y-30073814D01* +X52318968Y-30075127D01* +X52318629Y-30075248D01* +X52318350Y-30078986D01* +X52318036Y-30089105D01* +X52317702Y-30104727D01* +X52317364Y-30124976D01* +X52317038Y-30148975D01* +X52316739Y-30175847D01* +X52316602Y-30190305D01* +X52315586Y-30304352D01* +X52379086Y-30317546D01* +X52396453Y-30321153D01* +X52419799Y-30325999D01* +X52447995Y-30331850D01* +X52479915Y-30338473D01* +X52514431Y-30345632D01* +X52550414Y-30353095D01* +X52586737Y-30360627D01* +X52604057Y-30364218D01* +X52651540Y-30374079D01* +X52692331Y-30382591D01* +X52726850Y-30389845D01* +X52755519Y-30395933D01* +X52778756Y-30400949D01* +X52796983Y-30404983D01* +X52810620Y-30408130D01* +X52820087Y-30410481D01* +X52825805Y-30412128D01* +X52828194Y-30413164D01* +X52828275Y-30413477D01* +X52824393Y-30414406D01* +X52814014Y-30416308D01* +X52797817Y-30419075D01* +X52776482Y-30422603D01* +X52750687Y-30426784D01* +X52721114Y-30431512D01* +X52688440Y-30436681D01* +X52653345Y-30442185D01* +X52616510Y-30447916D01* +X52578612Y-30453769D01* +X52540331Y-30459637D01* +X52502348Y-30465413D01* +X52465340Y-30470993D01* +X52429989Y-30476268D01* +X52396972Y-30481133D01* +X52385726Y-30482772D01* +X52317982Y-30492617D01* +X52315524Y-30525544D01* +X52314630Y-30542082D01* +X52314058Y-30562503D01* +X52313785Y-30585719D01* +X52313788Y-30610644D01* +X52314045Y-30636189D01* +X52314534Y-30661267D01* +X52315232Y-30684791D01* +X52316117Y-30705674D01* +X52317166Y-30722826D01* +X52318356Y-30735162D01* +X52319666Y-30741593D01* +X52320000Y-30742142D01* +X52324293Y-30744400D01* +X52331667Y-30744449D01* +X52331667Y-31071766D01* +X52316205Y-31065304D01* +X52258760Y-31034934D01* +X52202998Y-30999229D01* +X52149577Y-30958792D01* +X52099156Y-30914226D01* +X52052391Y-30866132D01* +X52009941Y-30815113D01* +X51972463Y-30761771D01* +X51940617Y-30706710D01* +X51915059Y-30650531D01* +X51905472Y-30624110D01* +X51900260Y-30608390D01* +X51895837Y-30594542D01* +X51892133Y-30581821D01* +X51889079Y-30569477D01* +X51886605Y-30556764D01* +X51884643Y-30542933D01* +X51883122Y-30527238D01* +X51881974Y-30508930D01* +X51881130Y-30487263D01* +X51880519Y-30461487D01* +X51880073Y-30430857D01* +X51879722Y-30394623D01* +X51879397Y-30352039D01* +X51879325Y-30342104D01* +X51877936Y-30151137D01* +X51842761Y-30123912D01* +X51788235Y-30078534D01* +X51733759Y-30027099D01* +X51680314Y-29970746D01* +X51628877Y-29910616D01* +X51580428Y-29847849D01* +X51535946Y-29783585D01* +X51499416Y-29724200D01* +X51452182Y-29635860D01* +X51412058Y-29546693D01* +X51378921Y-29456262D01* +X51352648Y-29364133D01* +X51333118Y-29269868D01* +X51320209Y-29173032D01* +X51313796Y-29073189D01* +X51313475Y-29061686D01* +X51314007Y-28961083D01* +X51314007Y-28961083D01* +G37* +X51314007Y-28961083D02* +X51320704Y-28863677D01* +X51333721Y-28768600D01* +X51353213Y-28674982D01* +X51379333Y-28581953D01* +X51412237Y-28488644D01* +X51418051Y-28473857D01* +X51453375Y-28392874D01* +X51494530Y-28312031D01* +X51540827Y-28232317D01* +X51591578Y-28154716D01* +X51646094Y-28080215D01* +X51703687Y-28009800D01* +X51763667Y-27944457D01* +X51825346Y-27885173D01* +X51835231Y-27876400D01* +X51871086Y-27844939D01* +X51871086Y-27662759D01* +X51871118Y-27617597D01* +X51871258Y-27578945D01* +X51871567Y-27546059D01* +X51872108Y-27518192D01* +X51872942Y-27494599D01* +X51874133Y-27474533D01* +X51875742Y-27457248D01* +X51877832Y-27442000D01* +X51880465Y-27428041D01* +X51883704Y-27414626D01* +X51887610Y-27401009D01* +X51892246Y-27386444D01* +X51894811Y-27378712D01* +X51910254Y-27338793D01* +X51930440Y-27296322D01* +X51954308Y-27253102D01* +X51980795Y-27210935D01* +X52008839Y-27171625D01* +X52036821Y-27137598D01* +X52074829Y-27098870D01* +X52118146Y-27061424D01* +X52165523Y-27026026D01* +X52215710Y-26993439D01* +X52267460Y-26964427D01* +X52319523Y-26939755D01* +X52370650Y-26920185D01* +X52411545Y-26908350D01* +X52423292Y-26905588D01* +X52434699Y-26903141D01* +X52446254Y-26900991D01* +X52458445Y-26899123D01* +X52471759Y-26897520D01* +X52486682Y-26896164D01* +X52503702Y-26895041D01* +X52523307Y-26894132D01* +X52545984Y-26893421D01* +X52572220Y-26892892D01* +X52602502Y-26892528D01* +X52637317Y-26892312D01* +X52677153Y-26892229D01* +X52722498Y-26892260D01* +X52773838Y-26892390D01* +X52831660Y-26892602D01* +X52868943Y-26892759D01* +X52927210Y-26893023D01* +X52978672Y-26893286D01* +X53023784Y-26893557D01* +X53062996Y-26893846D01* +X53096764Y-26894161D01* +X53125539Y-26894512D01* +X53149773Y-26894907D01* +X53169922Y-26895356D01* +X53186436Y-26895867D01* +X53199769Y-26896451D01* +X53210374Y-26897115D01* +X53218703Y-26897869D01* +X53225211Y-26898723D01* +X53230348Y-26899684D01* +X53231890Y-26900044D01* +X53265394Y-26909489D01* +X53297449Y-26921208D01* +X53328853Y-26935698D01* +X53360404Y-26953455D01* +X53392899Y-26974977D01* +X53427136Y-27000761D01* +X53463912Y-27031303D01* +X53504026Y-27067101D01* +X53512444Y-27074866D01* +X53561739Y-27124440D01* +X53604205Y-27175650D01* +X53640195Y-27229107D01* +X53670067Y-27285423D01* +X53694173Y-27345207D01* +X53712868Y-27409069D01* +X53716963Y-27426762D01* +X53718994Y-27436109D01* +X53720722Y-27444606D01* +X53722179Y-27452921D01* +X53723395Y-27461720D01* +X53724400Y-27471673D01* +X53725226Y-27483447D01* +X53725904Y-27497709D01* +X53726465Y-27515128D01* +X53726938Y-27536371D01* +X53727356Y-27562106D01* +X53727749Y-27593000D01* +X53728148Y-27629722D01* +X53728584Y-27672939D01* +X53728650Y-27679576D01* +X53730728Y-27888595D01* +X53753762Y-27907076D01* +X53824560Y-27968188D01* +X53892371Y-28035298D01* +X53956474Y-28107512D01* +X54016150Y-28183936D01* +X54070679Y-28263673D01* +X54119340Y-28345830D01* +X54142835Y-28390705D01* +X54181088Y-28472768D01* +X54213087Y-28553668D01* +X54239309Y-28634949D01* +X54260235Y-28718154D01* +X54276342Y-28804826D01* +X54280744Y-28834900D01* +X54283224Y-28857395D01* +X54285384Y-28885524D01* +X54287188Y-28917807D01* +X54288603Y-28952766D01* +X54289594Y-28988922D01* +X54290127Y-29024797D01* +X54290169Y-29058910D01* +X54289684Y-29089784D01* +X54288640Y-29115940D01* +X54287560Y-29130629D01* +X54274484Y-29231476D01* +X54254557Y-29329938D01* +X54227809Y-29425942D01* +X54194268Y-29519413D01* +X54153965Y-29610277D01* +X54106927Y-29698459D01* +X54053185Y-29783886D01* +X54005146Y-29850504D01* +X53962055Y-29903885D01* +X53915009Y-29956706D01* +X53865606Y-30007315D01* +X53815447Y-30054063D01* +X53773364Y-30089569D01* +X53732543Y-30122239D01* +X53732528Y-30314955D01* +X53732492Y-30361324D01* +X53732357Y-30401164D01* +X53732072Y-30435202D01* +X53731587Y-30464166D01* +X53730851Y-30488783D01* +X53729813Y-30509782D01* +X53728423Y-30527890D01* +X53726628Y-30543834D01* +X53724380Y-30558343D01* +X53721626Y-30572143D01* +X53718317Y-30585963D01* +X53714401Y-30600530D01* +X53712007Y-30608999D01* +X53689681Y-30674042D01* +X53660568Y-30736684D01* +X53624632Y-30796988D01* +X53591028Y-30842553D01* +X53591028Y-29178339D01* +X53590960Y-28431491D01* +X53590936Y-28356840D01* +X53590879Y-28283254D01* +X53590792Y-28211133D01* +X53590675Y-28140880D01* +X53590530Y-28072897D01* +X53590360Y-28007584D01* +X53590165Y-27945343D01* +X53589947Y-27886577D01* +X53589708Y-27831686D01* +X53589450Y-27781072D01* +X53589174Y-27735137D01* +X53588882Y-27694283D01* +X53588576Y-27658911D01* +X53588257Y-27629422D01* +X53587927Y-27606219D01* +X53587588Y-27589703D01* +X53587443Y-27584857D01* +X53585929Y-27543996D01* +X53584292Y-27509421D01* +X53582298Y-27480162D01* +X53579711Y-27455249D01* +X53576294Y-27433711D01* +X53571814Y-27414580D01* +X53566033Y-27396884D01* +X53558718Y-27379654D01* +X53549631Y-27361919D01* +X53538538Y-27342709D01* +X53525203Y-27321055D01* +X53522257Y-27316361D01* +X53483286Y-27260247D01* +X53440558Y-27209685D01* +X53394379Y-27164931D01* +X53345059Y-27126239D01* +X53292905Y-27093865D01* +X53238226Y-27068062D01* +X53208760Y-27057281D01* +X53198837Y-27054165D01* +X53188741Y-27051418D01* +X53177972Y-27049018D01* +X53166028Y-27046940D01* +X53152407Y-27045162D01* +X53136609Y-27043662D01* +X53118133Y-27042416D01* +X53096477Y-27041402D01* +X53071140Y-27040596D01* +X53041620Y-27039976D01* +X53007417Y-27039519D01* +X52968028Y-27039202D01* +X52922954Y-27039002D01* +X52871693Y-27038896D01* +X52813742Y-27038861D01* +X52805443Y-27038860D01* +X52742856Y-27038908D01* +X52687296Y-27039054D01* +X52638532Y-27039302D01* +X52596334Y-27039654D01* +X52560471Y-27040113D01* +X52530714Y-27040683D01* +X52506832Y-27041367D01* +X52488595Y-27042167D01* +X52475772Y-27043087D01* +X52474169Y-27043249D01* +X52425842Y-27051863D01* +X52376979Y-27067140D01* +X52328327Y-27088602D01* +X52280635Y-27115771D01* +X52234651Y-27148167D01* +X52191122Y-27185311D01* +X52150796Y-27226726D01* +X52114423Y-27271931D01* +X52112318Y-27274843D01* +X52098972Y-27295130D01* +X52084993Y-27319313D01* +X52071263Y-27345585D01* +X52058663Y-27372140D01* +X52048074Y-27397172D01* +X52040377Y-27418875D01* +X52038106Y-27427014D01* +X52035938Y-27436044D01* +X52033979Y-27444936D01* +X52032218Y-27454092D01* +X52030643Y-27463915D01* +X52029242Y-27474806D01* +X52028001Y-27487168D01* +X52026910Y-27501404D01* +X52025956Y-27517914D01* +X52025125Y-27537102D01* +X52024407Y-27559369D01* +X52023790Y-27585118D01* +X52023259Y-27614750D01* +X52022805Y-27648668D01* +X52022413Y-27687274D01* +X52022073Y-27730970D01* +X52021771Y-27780159D01* +X52021496Y-27835241D01* +X52021236Y-27896620D01* +X52020977Y-27964698D01* +X52020875Y-27993072D01* +X52019209Y-28457529D01* +X52032282Y-28497939D01* +X52051581Y-28549096D01* +X52075531Y-28596936D01* +X52104839Y-28642616D01* +X52140216Y-28687292D01* +X52164916Y-28714377D01* +X52201953Y-28750922D01* +X52240229Y-28784558D01* +X52278957Y-28814758D01* +X52317351Y-28840999D01* +X52354624Y-28862753D01* +X52389991Y-28879497D01* +X52422665Y-28890704D01* +X52432270Y-28893003D01* +X52443660Y-28895050D01* +X52457838Y-28896915D01* +X52475199Y-28898616D01* +X52496142Y-28900166D01* +X52521063Y-28901580D01* +X52550359Y-28902875D01* +X52584427Y-28904064D01* +X52623664Y-28905163D01* +X52668467Y-28906187D01* +X52719232Y-28907151D01* +X52776358Y-28908070D01* +X52840240Y-28908960D01* +X52858057Y-28909189D01* +X52913362Y-28909906D01* +X52961967Y-28910597D01* +X53004426Y-28911302D01* +X53041296Y-28912065D01* +X53073132Y-28912926D01* +X53100491Y-28913926D01* +X53123927Y-28915109D01* +X53143997Y-28916515D01* +X53161257Y-28918186D01* +X53176262Y-28920164D01* +X53189568Y-28922491D01* +X53201732Y-28925208D01* +X53213308Y-28928356D01* +X53224852Y-28931978D01* +X53236921Y-28936116D01* +X53242240Y-28938002D01* +X53291538Y-28957363D01* +X53338052Y-28979469D01* +X53382855Y-29005017D01* +X53427024Y-29034699D01* +X53471631Y-29069210D01* +X53517753Y-29109244D01* +X53541136Y-29130996D01* +X53591028Y-29178339D01* +X53591028Y-30842553D01* +X53581836Y-30855018D01* +X53540095Y-30902542D01* +X53486415Y-30954413D01* +X53429855Y-30999627D01* +X53370396Y-31038192D01* +X53308022Y-31070119D01* +X53242714Y-31095419D01* +X53180218Y-31112806D01* +X53174160Y-31114153D01* +X53168158Y-31115336D01* +X53161714Y-31116368D01* +X53154331Y-31117262D01* +X53145511Y-31118032D01* +X53134758Y-31118688D01* +X53121575Y-31119245D01* +X53105464Y-31119715D01* +X53085927Y-31120111D01* +X53062469Y-31120446D01* +X53034592Y-31120731D01* +X53001798Y-31120981D01* +X52963590Y-31121207D01* +X52919471Y-31121422D01* +X52868945Y-31121640D01* +X52829028Y-31121802D01* +X52772370Y-31122025D01* +X52722446Y-31122197D01* +X52678734Y-31122298D01* +X52640712Y-31122311D01* +X52607857Y-31122217D01* +X52579647Y-31121997D01* +X52555559Y-31121632D01* +X52535071Y-31121103D01* +X52517660Y-31120393D01* +X52502804Y-31119481D01* +X52489980Y-31118350D01* +X52478667Y-31116980D01* +X52468341Y-31115354D01* +X52458479Y-31113451D01* +X52448561Y-31111254D01* +X52438062Y-31108744D01* +X52433514Y-31107631D01* +X52374676Y-31089738D01* +X52331667Y-31071766D01* +X52331667Y-30744449D01* +X52343950Y-30742278D01* +X52345400Y-30741964D01* +X52363344Y-30737998D01* +X52387171Y-30732665D01* +X52416294Y-30726100D01* +X52450127Y-30718437D01* +X52488082Y-30709812D01* +X52529572Y-30700360D01* +X52574010Y-30690216D01* +X52620808Y-30679514D01* +X52669379Y-30668390D01* +X52719137Y-30656978D01* +X52769494Y-30645415D01* +X52819863Y-30633834D01* +X52869657Y-30622371D01* +X52918288Y-30611161D01* +X52965169Y-30600339D01* +X53009714Y-30590039D01* +X53051335Y-30580397D01* +X53089445Y-30571548D01* +X53123457Y-30563627D01* +X53152783Y-30556768D01* +X53176837Y-30551108D01* +X53195031Y-30546780D01* +X53206778Y-30543920D01* +X53207351Y-30543776D01* +X53220590Y-30540221D01* +X53228515Y-30536572D01* +X53232841Y-30530936D01* +X53235284Y-30521423D01* +X53236814Y-30511300D01* +X53237256Y-30504209D01* +X53237474Y-30491511D01* +X53237492Y-30474329D01* +X53237336Y-30453786D01* +X53237028Y-30431006D01* +X53236592Y-30407111D01* +X53236053Y-30383225D01* +X53235435Y-30360470D01* +X53234761Y-30339970D01* +X53234056Y-30322848D01* +X53233344Y-30310226D01* +X53232648Y-30303228D01* +X53232344Y-30302211D01* +X53228367Y-30301041D01* +X53218052Y-30298681D01* +X53202187Y-30295294D01* +X53181563Y-30291043D01* +X53156972Y-30286089D01* +X53129203Y-30280596D01* +X53099047Y-30274727D01* +X53093914Y-30273737D01* +X53044010Y-30264092D01* +X52995723Y-30254702D01* +X52949570Y-30245668D01* +X52906064Y-30237095D01* +X52865722Y-30229086D01* +X52829057Y-30221744D01* +X52796585Y-30215173D01* +X52768821Y-30209476D01* +X52746279Y-30204758D01* +X52729475Y-30201120D01* +X52718923Y-30198667D01* +X52715530Y-30197709D01* +X52711190Y-30195627D01* +X52712131Y-30193873D01* +X52719152Y-30191596D01* +X52721986Y-30190837D01* +X52727976Y-30189508D01* +X52740465Y-30186940D01* +X52758822Y-30183259D01* +X52782417Y-30178586D01* +X52810620Y-30173046D01* +X52842801Y-30166763D01* +X52878330Y-30159859D01* +X52916576Y-30152459D01* +X52956910Y-30144686D01* +X52975986Y-30141020D01* +X53016890Y-30133131D01* +X53055855Y-30125546D01* +X53092270Y-30118391D01* +X53125523Y-30111787D01* +X53155002Y-30105858D01* +X53180094Y-30100729D01* +X53200188Y-30096522D01* +X53214672Y-30093361D01* +X53222933Y-30091370D01* +X53224513Y-30090863D01* +X53232753Y-30083418D01* +X53235877Y-30075837D01* +X53236724Y-30068086D01* +X53237404Y-30054382D01* +X53237917Y-30035975D01* +X53238264Y-30014115D01* +X53238447Y-29990053D01* +X53238467Y-29965040D01* +X53238325Y-29940324D01* +X53238023Y-29917156D01* +X53237561Y-29896787D01* +X53236942Y-29880467D01* +X53236166Y-29869446D01* +X53235659Y-29866034D01* +X53233213Y-29856768D01* +X53231153Y-29851053D01* +X53230779Y-29850485D01* +X53226883Y-29849246D01* +X53216446Y-29846521D01* +X53199980Y-29842426D01* +X53177995Y-29837080D01* +X53151005Y-29830602D01* +X53119520Y-29823110D01* +X53084053Y-29814722D01* +X53045114Y-29805557D01* +X53003215Y-29795732D01* +X52958868Y-29785367D01* +X52912585Y-29774579D01* +X52864877Y-29763487D01* +X52816256Y-29752209D01* +X52767232Y-29740864D01* +X52718319Y-29729569D01* +X52670028Y-29718444D01* +X52622869Y-29707606D01* +X52577355Y-29697173D01* +X52571400Y-29695813D01* +X52571400Y-29511629D01* +X53239057Y-29511629D01* +X53239057Y-29286657D01* +X52571400Y-29286657D01* +X52571400Y-29511629D01* +X52571400Y-29695813D01* +X52533998Y-29687265D01* +X52493308Y-29677999D01* +X52455798Y-29669494D01* +X52421979Y-29661868D01* +X52392363Y-29655239D01* +X52386245Y-29653885D01* +X52386245Y-29530764D01* +X52409364Y-29526858D01* +X52421396Y-29522233D01* +X52442198Y-29508641D01* +X52461165Y-29489695D01* +X52476873Y-29467287D01* +X52487896Y-29443308D01* +X52491680Y-29428894D01* +X52493524Y-29408350D01* +X52492817Y-29384207D01* +X52489813Y-29359559D01* +X52484768Y-29337499D01* +X52483977Y-29334988D01* +X52472394Y-29308874D01* +X52456472Y-29286826D01* +X52437108Y-29269791D01* +X52415199Y-29258716D01* +X52410276Y-29257213D01* +X52392365Y-29254692D01* +X52371811Y-29255310D01* +X52351893Y-29258759D01* +X52337087Y-29264098D01* +X52321708Y-29274584D01* +X52306242Y-29289535D01* +X52292903Y-29306535D01* +X52284657Y-29321328D01* +X52277135Y-29344367D01* +X52272491Y-29370397D01* +X52270775Y-29397388D01* +X52272042Y-29423306D01* +X52276340Y-29446120D01* +X52281155Y-29459099D01* +X52291165Y-29475559D01* +X52304837Y-29492455D01* +X52320227Y-29507734D01* +X52335393Y-29519344D01* +X52341376Y-29522704D01* +X52362686Y-29529385D01* +X52386245Y-29530764D01* +X52386245Y-29653885D01* +X52367462Y-29649726D01* +X52347786Y-29645447D01* +X52333847Y-29642520D01* +X52326158Y-29641064D01* +X52324759Y-29640944D01* +X52324272Y-29644897D01* +X52323758Y-29655259D01* +X52323239Y-29671181D01* +X52322735Y-29691815D01* +X52322268Y-29716313D01* +X52321859Y-29743827D01* +X52321595Y-29766836D01* +X52320347Y-29890814D01* +X52466738Y-29912138D01* +X52512368Y-29918806D01* +X52556944Y-29925360D01* +X52599849Y-29931707D01* +X52640467Y-29937755D01* +X52678182Y-29943409D01* +X52712377Y-29948577D01* +X52742436Y-29953166D01* +X52767744Y-29957083D01* +X52787684Y-29960235D01* +X52801641Y-29962527D01* +X52808773Y-29963821D01* +X52815403Y-29965921D01* +X52815235Y-29968225D01* +X52814216Y-29968865D01* +X52809045Y-29970472D01* +X52796935Y-29973467D01* +X52778061Y-29977811D01* +X52752601Y-29983467D01* +X52720731Y-29990397D01* +X52682626Y-29998562D01* +X52638464Y-30007925D01* +X52588420Y-30018447D01* +X52532671Y-30030092D01* +X52471393Y-30042820D01* +X52459374Y-30045309D01* +X52428594Y-30051701D01* +X52400111Y-30057653D01* +X52374691Y-30063004D01* +X52353101Y-30067590D01* +X52336106Y-30071247D01* +X52324473Y-30073814D01* +X52318968Y-30075127D01* +X52318629Y-30075248D01* +X52318350Y-30078986D01* +X52318036Y-30089105D01* +X52317702Y-30104727D01* +X52317364Y-30124976D01* +X52317038Y-30148975D01* +X52316739Y-30175847D01* +X52316602Y-30190305D01* +X52315586Y-30304352D01* +X52379086Y-30317546D01* +X52396453Y-30321153D01* +X52419799Y-30325999D01* +X52447995Y-30331850D01* +X52479915Y-30338473D01* +X52514431Y-30345632D01* +X52550414Y-30353095D01* +X52586737Y-30360627D01* +X52604057Y-30364218D01* +X52651540Y-30374079D01* +X52692331Y-30382591D01* +X52726850Y-30389845D01* +X52755519Y-30395933D01* +X52778756Y-30400949D01* +X52796983Y-30404983D01* +X52810620Y-30408130D01* +X52820087Y-30410481D01* +X52825805Y-30412128D01* +X52828194Y-30413164D01* +X52828275Y-30413477D01* +X52824393Y-30414406D01* +X52814014Y-30416308D01* +X52797817Y-30419075D01* +X52776482Y-30422603D01* +X52750687Y-30426784D01* +X52721114Y-30431512D01* +X52688440Y-30436681D01* +X52653345Y-30442185D01* +X52616510Y-30447916D01* +X52578612Y-30453769D01* +X52540331Y-30459637D01* +X52502348Y-30465413D01* +X52465340Y-30470993D01* +X52429989Y-30476268D01* +X52396972Y-30481133D01* +X52385726Y-30482772D01* +X52317982Y-30492617D01* +X52315524Y-30525544D01* +X52314630Y-30542082D01* +X52314058Y-30562503D01* +X52313785Y-30585719D01* +X52313788Y-30610644D01* +X52314045Y-30636189D01* +X52314534Y-30661267D01* +X52315232Y-30684791D01* +X52316117Y-30705674D01* +X52317166Y-30722826D01* +X52318356Y-30735162D01* +X52319666Y-30741593D01* +X52320000Y-30742142D01* +X52324293Y-30744400D01* +X52331667Y-30744449D01* +X52331667Y-31071766D01* +X52316205Y-31065304D01* +X52258760Y-31034934D01* +X52202998Y-30999229D01* +X52149577Y-30958792D01* +X52099156Y-30914226D01* +X52052391Y-30866132D01* +X52009941Y-30815113D01* +X51972463Y-30761771D01* +X51940617Y-30706710D01* +X51915059Y-30650531D01* +X51905472Y-30624110D01* +X51900260Y-30608390D01* +X51895837Y-30594542D01* +X51892133Y-30581821D01* +X51889079Y-30569477D01* +X51886605Y-30556764D01* +X51884643Y-30542933D01* +X51883122Y-30527238D01* +X51881974Y-30508930D01* +X51881130Y-30487263D01* +X51880519Y-30461487D01* +X51880073Y-30430857D01* +X51879722Y-30394623D01* +X51879397Y-30352039D01* +X51879325Y-30342104D01* +X51877936Y-30151137D01* +X51842761Y-30123912D01* +X51788235Y-30078534D01* +X51733759Y-30027099D01* +X51680314Y-29970746D01* +X51628877Y-29910616D01* +X51580428Y-29847849D01* +X51535946Y-29783585D01* +X51499416Y-29724200D01* +X51452182Y-29635860D01* +X51412058Y-29546693D01* +X51378921Y-29456262D01* +X51352648Y-29364133D01* +X51333118Y-29269868D01* +X51320209Y-29173032D01* +X51313796Y-29073189D01* +X51313475Y-29061686D01* +X51314007Y-28961083D01* +G36* +X53242686Y-27399800D02* +X53242686Y-27632029D01* +X52567771Y-27632029D01* +X52567771Y-27399800D01* +X53242686Y-27399800D01* +X53242686Y-27399800D01* +G37* +X53242686Y-27399800D02* +X53242686Y-27632029D01* +X52567771Y-27632029D01* +X52567771Y-27399800D01* +X53242686Y-27399800D01* +G36* +X52531486Y-27773543D02* +X52531486Y-28328714D01* +X52745571Y-28328714D01* +X52745571Y-27838857D01* +X52963286Y-27838857D01* +X52963286Y-28328714D01* +X53235428Y-28328714D01* +X53235428Y-28585583D01* +X52815421Y-28587836D01* +X52759881Y-28588150D01* +X52705751Y-28588487D01* +X52653547Y-28588841D01* +X52603783Y-28589210D01* +X52556974Y-28589586D01* +X52513635Y-28589967D01* +X52474280Y-28590346D01* +X52439424Y-28590719D01* +X52409581Y-28591081D01* +X52385267Y-28591428D01* +X52366997Y-28591755D01* +X52355284Y-28592056D01* +X52352778Y-28592157D01* +X52310143Y-28594225D01* +X52310143Y-27773543D01* +X52531486Y-27773543D01* +X52531486Y-27773543D01* +G37* +X52531486Y-27773543D02* +X52531486Y-28328714D01* +X52745571Y-28328714D01* +X52745571Y-27838857D01* +X52963286Y-27838857D01* +X52963286Y-28328714D01* +X53235428Y-28328714D01* +X53235428Y-28585583D01* +X52815421Y-28587836D01* +X52759881Y-28588150D01* +X52705751Y-28588487D01* +X52653547Y-28588841D01* +X52603783Y-28589210D01* +X52556974Y-28589586D01* +X52513635Y-28589967D01* +X52474280Y-28590346D01* +X52439424Y-28590719D01* +X52409581Y-28591081D01* +X52385267Y-28591428D01* +X52366997Y-28591755D01* +X52355284Y-28592056D01* +X52352778Y-28592157D01* +X52310143Y-28594225D01* +X52310143Y-27773543D01* +X52531486Y-27773543D01* +G36* +X52264655Y-27490460D02* +X52265569Y-27483544D01* +X52272827Y-27454109D01* +X52284729Y-27426922D01* +X52300463Y-27403238D01* +X52319217Y-27384309D01* +X52337357Y-27372685D01* +X52349314Y-27368566D01* +X52364690Y-27365429D01* +X52375457Y-27364271D01* +X52402711Y-27365968D01* +X52427533Y-27374016D01* +X52449464Y-27387786D01* +X52468044Y-27406646D01* +X52482816Y-27429965D01* +X52493320Y-27457110D01* +X52499098Y-27487452D01* +X52499691Y-27520359D01* +X52498450Y-27533491D01* +X52491677Y-27562201D01* +X52479274Y-27589394D01* +X52462219Y-27613591D01* +X52441493Y-27633311D01* +X52425695Y-27643464D01* +X52406123Y-27650211D01* +X52383593Y-27652314D01* +X52360714Y-27649783D01* +X52340986Y-27643077D01* +X52316919Y-27627384D01* +X52296701Y-27606336D01* +X52280849Y-27581027D01* +X52269880Y-27552550D01* +X52264310Y-27521997D01* +X52264655Y-27490460D01* +X52264655Y-27490460D01* +G37* +X52264655Y-27490460D02* +X52265569Y-27483544D01* +X52272827Y-27454109D01* +X52284729Y-27426922D01* +X52300463Y-27403238D01* +X52319217Y-27384309D01* +X52337357Y-27372685D01* +X52349314Y-27368566D01* +X52364690Y-27365429D01* +X52375457Y-27364271D01* +X52402711Y-27365968D01* +X52427533Y-27374016D01* +X52449464Y-27387786D01* +X52468044Y-27406646D01* +X52482816Y-27429965D01* +X52493320Y-27457110D01* +X52499098Y-27487452D01* +X52499691Y-27520359D01* +X52498450Y-27533491D01* +X52491677Y-27562201D01* +X52479274Y-27589394D01* +X52462219Y-27613591D01* +X52441493Y-27633311D01* +X52425695Y-27643464D01* +X52406123Y-27650211D01* +X52383593Y-27652314D01* +X52360714Y-27649783D01* +X52340986Y-27643077D01* +X52316919Y-27627384D01* +X52296701Y-27606336D01* +X52280849Y-27581027D01* +X52269880Y-27552550D01* +X52264310Y-27521997D01* +X52264655Y-27490460D01* +D12* +X23257143Y-45166666D02* +X23304762Y-45214285D01* +X23352381Y-45357142D01* +X23352381Y-45452380D01* +X23304762Y-45595238D01* +X23209524Y-45690476D01* +X23114286Y-45738095D01* +X22923810Y-45785714D01* +X22780952Y-45785714D01* +X22590476Y-45738095D01* +X22495238Y-45690476D01* +X22400000Y-45595238D01* +X22352381Y-45452380D01* +X22352381Y-45357142D01* +X22400000Y-45214285D01* +X22447619Y-45166666D01* +X22352381Y-44833333D02* +X22352381Y-44214285D01* +X22733333Y-44547619D01* +X22733333Y-44404761D01* +X22780952Y-44309523D01* +X22828571Y-44261904D01* +X22923810Y-44214285D01* +X23161905Y-44214285D01* +X23257143Y-44261904D01* +X23304762Y-44309523D01* +X23352381Y-44404761D01* +X23352381Y-44690476D01* +X23304762Y-44785714D01* +X23257143Y-44833333D01* +X31938095Y-29952381D02* +X31938095Y-30761905D01* +X31985714Y-30857143D01* +X32033333Y-30904762D01* +X32128571Y-30952381D01* +X32319048Y-30952381D01* +X32414286Y-30904762D01* +X32461905Y-30857143D01* +X32509524Y-30761905D01* +X32509524Y-29952381D01* +X33509524Y-30952381D02* +X32938095Y-30952381D01* +X33223809Y-30952381D02* +X33223809Y-29952381D01* +X33128571Y-30095238D01* +X33033333Y-30190476D01* +X32938095Y-30238095D01* +X42961905Y-39652381D02* +X42961905Y-38652381D01* +X43342858Y-38652381D01* +X43438096Y-38700000D01* +X43485715Y-38747619D01* +X43533334Y-38842857D01* +X43533334Y-38985714D01* +X43485715Y-39080952D01* +X43438096Y-39128571D01* +X43342858Y-39176190D01* +X42961905Y-39176190D01* +X43866667Y-38652381D02* +X44485715Y-38652381D01* +X44152381Y-39033333D01* +X44295239Y-39033333D01* +X44390477Y-39080952D01* +X44438096Y-39128571D01* +X44485715Y-39223810D01* +X44485715Y-39461905D01* +X44438096Y-39557143D01* +X44390477Y-39604762D01* +X44295239Y-39652381D01* +X44009524Y-39652381D01* +X43914286Y-39604762D01* +X43866667Y-39557143D01* +X46538095Y-35052381D02* +X46538095Y-35861905D01* +X46585714Y-35957143D01* +X46633333Y-36004762D01* +X46728571Y-36052381D01* +X46919048Y-36052381D01* +X47014286Y-36004762D01* +X47061905Y-35957143D01* +X47109524Y-35861905D01* +X47109524Y-35052381D01* +X47490476Y-35052381D02* +X48157143Y-35052381D01* +X47728571Y-36052381D01* +X23733334Y-41657143D02* +X23685715Y-41704762D01* +X23542858Y-41752381D01* +X23447620Y-41752381D01* +X23304762Y-41704762D01* +X23209524Y-41609524D01* +X23161905Y-41514286D01* +X23114286Y-41323810D01* +X23114286Y-41180952D01* +X23161905Y-40990476D01* +X23209524Y-40895238D01* +X23304762Y-40800000D01* +X23447620Y-40752381D01* +X23542858Y-40752381D01* +X23685715Y-40800000D01* +X23733334Y-40847619D01* +X24114286Y-40847619D02* +X24161905Y-40800000D01* +X24257143Y-40752381D01* +X24495239Y-40752381D01* +X24590477Y-40800000D01* +X24638096Y-40847619D01* +X24685715Y-40942857D01* +X24685715Y-41038095D01* +X24638096Y-41180952D01* +X24066667Y-41752381D01* +X24685715Y-41752381D01* +X38438095Y-27352381D02* +X38438095Y-28161905D01* +X38485714Y-28257143D01* +X38533333Y-28304762D01* +X38628571Y-28352381D01* +X38819048Y-28352381D01* +X38914286Y-28304762D01* +X38961905Y-28257143D01* +X39009524Y-28161905D01* +X39009524Y-27352381D01* +X39961905Y-27352381D02* +X39485714Y-27352381D01* +X39438095Y-27828571D01* +X39485714Y-27780952D01* +X39580952Y-27733333D01* +X39819048Y-27733333D01* +X39914286Y-27780952D01* +X39961905Y-27828571D01* +X40009524Y-27923810D01* +X40009524Y-28161905D01* +X39961905Y-28257143D01* +X39914286Y-28304762D01* +X39819048Y-28352381D01* +X39580952Y-28352381D01* +X39485714Y-28304762D01* +X39438095Y-28257143D01* +X21766667Y-27419048D02* +X21766667Y-26942857D01* +X22052381Y-27514286D02* +X21052381Y-27180953D01* +X22052381Y-26847619D01* +X22052381Y-26514286D02* +X21052381Y-26514286D01* +X22052381Y-25942857D01* +X21052381Y-25942857D01* +X21052381Y-25609524D02* +X21052381Y-25038095D01* +X22052381Y-25323810D02* +X21052381Y-25323810D01* +X22052381Y-24180952D02* +X22052381Y-24752381D01* +X22052381Y-24466667D02* +X21052381Y-24466667D01* +X21195238Y-24561905D01* +X21290476Y-24657143D01* +X21338095Y-24752381D01* +X26633334Y-31357143D02* +X26585715Y-31404762D01* +X26442858Y-31452381D01* +X26347620Y-31452381D01* +X26204762Y-31404762D01* +X26109524Y-31309524D01* +X26061905Y-31214286D01* +X26014286Y-31023810D01* +X26014286Y-30880952D01* +X26061905Y-30690476D01* +X26109524Y-30595238D01* +X26204762Y-30500000D01* +X26347620Y-30452381D01* +X26442858Y-30452381D01* +X26585715Y-30500000D01* +X26633334Y-30547619D01* +X27585715Y-31452381D02* +X27014286Y-31452381D01* +X27300000Y-31452381D02* +X27300000Y-30452381D01* +X27204762Y-30595238D01* +X27109524Y-30690476D01* +X27014286Y-30738095D01* +X23333334Y-49957143D02* +X23285715Y-50004762D01* +X23142858Y-50052381D01* +X23047620Y-50052381D01* +X22904762Y-50004762D01* +X22809524Y-49909524D01* +X22761905Y-49814286D01* +X22714286Y-49623810D01* +X22714286Y-49480952D01* +X22761905Y-49290476D01* +X22809524Y-49195238D01* +X22904762Y-49100000D01* +X23047620Y-49052381D01* +X23142858Y-49052381D01* +X23285715Y-49100000D01* +X23333334Y-49147619D01* +X24190477Y-49385714D02* +X24190477Y-50052381D01* +X23952381Y-49004762D02* +X23714286Y-49719048D01* +X24333334Y-49719048D01* +X40257143Y-48166666D02* +X40304762Y-48214285D01* +X40352381Y-48357142D01* +X40352381Y-48452380D01* +X40304762Y-48595238D01* +X40209524Y-48690476D01* +X40114286Y-48738095D01* +X39923810Y-48785714D01* +X39780952Y-48785714D01* +X39590476Y-48738095D01* +X39495238Y-48690476D01* +X39400000Y-48595238D01* +X39352381Y-48452380D01* +X39352381Y-48357142D01* +X39400000Y-48214285D01* +X39447619Y-48166666D01* +X39352381Y-47261904D02* +X39352381Y-47738095D01* +X39828571Y-47785714D01* +X39780952Y-47738095D01* +X39733333Y-47642857D01* +X39733333Y-47404761D01* +X39780952Y-47309523D01* +X39828571Y-47261904D01* +X39923810Y-47214285D01* +X40161905Y-47214285D01* +X40257143Y-47261904D01* +X40304762Y-47309523D01* +X40352381Y-47404761D01* +X40352381Y-47642857D01* +X40304762Y-47738095D01* +X40257143Y-47785714D01* +X51857143Y-44866666D02* +X51904762Y-44914285D01* +X51952381Y-45057142D01* +X51952381Y-45152380D01* +X51904762Y-45295238D01* +X51809524Y-45390476D01* +X51714286Y-45438095D01* +X51523810Y-45485714D01* +X51380952Y-45485714D01* +X51190476Y-45438095D01* +X51095238Y-45390476D01* +X51000000Y-45295238D01* +X50952381Y-45152380D01* +X50952381Y-45057142D01* +X51000000Y-44914285D01* +X51047619Y-44866666D01* +X50952381Y-44009523D02* +X50952381Y-44200000D01* +X51000000Y-44295238D01* +X51047619Y-44342857D01* +X51190476Y-44438095D01* +X51380952Y-44485714D01* +X51761905Y-44485714D01* +X51857143Y-44438095D01* +X51904762Y-44390476D01* +X51952381Y-44295238D01* +X51952381Y-44104761D01* +X51904762Y-44009523D01* +X51857143Y-43961904D01* +X51761905Y-43914285D01* +X51523810Y-43914285D01* +X51428571Y-43961904D01* +X51380952Y-44009523D01* +X51333333Y-44104761D01* +X51333333Y-44295238D01* +X51380952Y-44390476D01* +X51428571Y-44438095D01* +X51523810Y-44485714D01* +X50457143Y-44866666D02* +X50504762Y-44914285D01* +X50552381Y-45057142D01* +X50552381Y-45152380D01* +X50504762Y-45295238D01* +X50409524Y-45390476D01* +X50314286Y-45438095D01* +X50123810Y-45485714D01* +X49980952Y-45485714D01* +X49790476Y-45438095D01* +X49695238Y-45390476D01* +X49600000Y-45295238D01* +X49552381Y-45152380D01* +X49552381Y-45057142D01* +X49600000Y-44914285D01* +X49647619Y-44866666D01* +X49552381Y-44533333D02* +X49552381Y-43866666D01* +X50552381Y-44295238D01* +X26257143Y-25666666D02* +X26304762Y-25714285D01* +X26352381Y-25857142D01* +X26352381Y-25952380D01* +X26304762Y-26095238D01* +X26209524Y-26190476D01* +X26114286Y-26238095D01* +X25923810Y-26285714D01* +X25780952Y-26285714D01* +X25590476Y-26238095D01* +X25495238Y-26190476D01* +X25400000Y-26095238D01* +X25352381Y-25952380D01* +X25352381Y-25857142D01* +X25400000Y-25714285D01* +X25447619Y-25666666D01* +X25780952Y-25095238D02* +X25733333Y-25190476D01* +X25685714Y-25238095D01* +X25590476Y-25285714D01* +X25542857Y-25285714D01* +X25447619Y-25238095D01* +X25400000Y-25190476D01* +X25352381Y-25095238D01* +X25352381Y-24904761D01* +X25400000Y-24809523D01* +X25447619Y-24761904D01* +X25542857Y-24714285D01* +X25590476Y-24714285D01* +X25685714Y-24761904D01* +X25733333Y-24809523D01* +X25780952Y-24904761D01* +X25780952Y-25095238D01* +X25828571Y-25190476D01* +X25876190Y-25238095D01* +X25971429Y-25285714D01* +X26161905Y-25285714D01* +X26257143Y-25238095D01* +X26304762Y-25190476D01* +X26352381Y-25095238D01* +X26352381Y-24904761D01* +X26304762Y-24809523D01* +X26257143Y-24761904D01* +X26161905Y-24714285D01* +X25971429Y-24714285D01* +X25876190Y-24761904D01* +X25828571Y-24809523D01* +X25780952Y-24904761D01* +X39157143Y-22166666D02* +X39204762Y-22214285D01* +X39252381Y-22357142D01* +X39252381Y-22452380D01* +X39204762Y-22595238D01* +X39109524Y-22690476D01* +X39014286Y-22738095D01* +X38823810Y-22785714D01* +X38680952Y-22785714D01* +X38490476Y-22738095D01* +X38395238Y-22690476D01* +X38300000Y-22595238D01* +X38252381Y-22452380D01* +X38252381Y-22357142D01* +X38300000Y-22214285D01* +X38347619Y-22166666D01* +X39252381Y-21690476D02* +X39252381Y-21500000D01* +X39204762Y-21404761D01* +X39157143Y-21357142D01* +X39014286Y-21261904D01* +X38823810Y-21214285D01* +X38442857Y-21214285D01* +X38347619Y-21261904D01* +X38300000Y-21309523D01* +X38252381Y-21404761D01* +X38252381Y-21595238D01* +X38300000Y-21690476D01* +X38347619Y-21738095D01* +X38442857Y-21785714D01* +X38680952Y-21785714D01* +X38776190Y-21738095D01* +X38823810Y-21690476D01* +X38871429Y-21595238D01* +X38871429Y-21404761D01* +X38823810Y-21309523D01* +X38776190Y-21261904D01* +X38680952Y-21214285D01* +X41857143Y-22642857D02* +X41904762Y-22690476D01* +X41952381Y-22833333D01* +X41952381Y-22928571D01* +X41904762Y-23071429D01* +X41809524Y-23166667D01* +X41714286Y-23214286D01* +X41523810Y-23261905D01* +X41380952Y-23261905D01* +X41190476Y-23214286D01* +X41095238Y-23166667D01* +X41000000Y-23071429D01* +X40952381Y-22928571D01* +X40952381Y-22833333D01* +X41000000Y-22690476D01* +X41047619Y-22642857D01* +X41952381Y-21690476D02* +X41952381Y-22261905D01* +X41952381Y-21976191D02* +X40952381Y-21976191D01* +X41095238Y-22071429D01* +X41190476Y-22166667D01* +X41238095Y-22261905D01* +X40952381Y-21071429D02* +X40952381Y-20976190D01* +X41000000Y-20880952D01* +X41047619Y-20833333D01* +X41142857Y-20785714D01* +X41333333Y-20738095D01* +X41571429Y-20738095D01* +X41761905Y-20785714D01* +X41857143Y-20833333D01* +X41904762Y-20880952D01* +X41952381Y-20976190D01* +X41952381Y-21071429D01* +X41904762Y-21166667D01* +X41857143Y-21214286D01* +X41761905Y-21261905D01* +X41571429Y-21309524D01* +X41333333Y-21309524D01* +X41142857Y-21261905D01* +X41047619Y-21214286D01* +X41000000Y-21166667D01* +X40952381Y-21071429D01* +X36357143Y-22642857D02* +X36404762Y-22690476D01* +X36452381Y-22833333D01* +X36452381Y-22928571D01* +X36404762Y-23071429D01* +X36309524Y-23166667D01* +X36214286Y-23214286D01* +X36023810Y-23261905D01* +X35880952Y-23261905D01* +X35690476Y-23214286D01* +X35595238Y-23166667D01* +X35500000Y-23071429D01* +X35452381Y-22928571D01* +X35452381Y-22833333D01* +X35500000Y-22690476D01* +X35547619Y-22642857D01* +X36452381Y-21690476D02* +X36452381Y-22261905D01* +X36452381Y-21976191D02* +X35452381Y-21976191D01* +X35595238Y-22071429D01* +X35690476Y-22166667D01* +X35738095Y-22261905D01* +X36452381Y-20738095D02* +X36452381Y-21309524D01* +X36452381Y-21023810D02* +X35452381Y-21023810D01* +X35595238Y-21119048D01* +X35690476Y-21214286D01* +X35738095Y-21309524D01* +X49857143Y-21257143D02* +X49809524Y-21304762D01* +X49666667Y-21352381D01* +X49571429Y-21352381D01* +X49428571Y-21304762D01* +X49333333Y-21209524D01* +X49285714Y-21114286D01* +X49238095Y-20923810D01* +X49238095Y-20780952D01* +X49285714Y-20590476D01* +X49333333Y-20495238D01* +X49428571Y-20400000D01* +X49571429Y-20352381D01* +X49666667Y-20352381D01* +X49809524Y-20400000D01* +X49857143Y-20447619D01* +X50809524Y-21352381D02* +X50238095Y-21352381D01* +X50523809Y-21352381D02* +X50523809Y-20352381D01* +X50428571Y-20495238D01* +X50333333Y-20590476D01* +X50238095Y-20638095D01* +X51190476Y-20447619D02* +X51238095Y-20400000D01* +X51333333Y-20352381D01* +X51571429Y-20352381D01* +X51666667Y-20400000D01* +X51714286Y-20447619D01* +X51761905Y-20542857D01* +X51761905Y-20638095D01* +X51714286Y-20780952D01* +X51142857Y-21352381D01* +X51761905Y-21352381D01* +X54157143Y-23742857D02* +X54204762Y-23790476D01* +X54252381Y-23933333D01* +X54252381Y-24028571D01* +X54204762Y-24171429D01* +X54109524Y-24266667D01* +X54014286Y-24314286D01* +X53823810Y-24361905D01* +X53680952Y-24361905D01* +X53490476Y-24314286D01* +X53395238Y-24266667D01* +X53300000Y-24171429D01* +X53252381Y-24028571D01* +X53252381Y-23933333D01* +X53300000Y-23790476D01* +X53347619Y-23742857D01* +X54252381Y-22790476D02* +X54252381Y-23361905D01* +X54252381Y-23076191D02* +X53252381Y-23076191D01* +X53395238Y-23171429D01* +X53490476Y-23266667D01* +X53538095Y-23361905D01* +X53252381Y-22457143D02* +X53252381Y-21838095D01* +X53633333Y-22171429D01* +X53633333Y-22028571D01* +X53680952Y-21933333D01* +X53728571Y-21885714D01* +X53823810Y-21838095D01* +X54061905Y-21838095D01* +X54157143Y-21885714D01* +X54204762Y-21933333D01* +X54252381Y-22028571D01* +X54252381Y-22314286D01* +X54204762Y-22409524D01* +X54157143Y-22457143D01* +X46627845Y-28605341D02* +X46580226Y-28652960D01* +X46437369Y-28700579D01* +X46342131Y-28700579D01* +X46199273Y-28652960D01* +X46104035Y-28557722D01* +X46056416Y-28462484D01* +X46008797Y-28272008D01* +X46008797Y-28129150D01* +X46056416Y-27938674D01* +X46104035Y-27843436D01* +X46199273Y-27748198D01* +X46342131Y-27700579D01* +X46437369Y-27700579D01* +X46580226Y-27748198D01* +X46627845Y-27795817D01* +X47580226Y-28700579D02* +X47008797Y-28700579D01* +X47294511Y-28700579D02* +X47294511Y-27700579D01* +X47199273Y-27843436D01* +X47104035Y-27938674D01* +X47008797Y-27986293D01* +X48437369Y-28033912D02* +X48437369Y-28700579D01* +X48199273Y-27652960D02* +X47961178Y-28367246D01* +X48580226Y-28367246D01* +X52357143Y-39442857D02* +X52404762Y-39490476D01* +X52452381Y-39633333D01* +X52452381Y-39728571D01* +X52404762Y-39871429D01* +X52309524Y-39966667D01* +X52214286Y-40014286D01* +X52023810Y-40061905D01* +X51880952Y-40061905D01* +X51690476Y-40014286D01* +X51595238Y-39966667D01* +X51500000Y-39871429D01* +X51452381Y-39728571D01* +X51452381Y-39633333D01* +X51500000Y-39490476D01* +X51547619Y-39442857D01* +X52452381Y-38490476D02* +X52452381Y-39061905D01* +X52452381Y-38776191D02* +X51452381Y-38776191D01* +X51595238Y-38871429D01* +X51690476Y-38966667D01* +X51738095Y-39061905D01* +X51452381Y-37585714D02* +X51452381Y-38061905D01* +X51928571Y-38109524D01* +X51880952Y-38061905D01* +X51833333Y-37966667D01* +X51833333Y-37728571D01* +X51880952Y-37633333D01* +X51928571Y-37585714D01* +X52023810Y-37538095D01* +X52261905Y-37538095D01* +X52357143Y-37585714D01* +X52404762Y-37633333D01* +X52452381Y-37728571D01* +X52452381Y-37966667D01* +X52404762Y-38061905D01* +X52357143Y-38109524D01* +X30066667Y-44928571D02* +X29733333Y-44928571D01* +X29733333Y-45452381D02* +X29733333Y-44452381D01* +X30209524Y-44452381D01* +X30923810Y-44928571D02* +X31066667Y-44976190D01* +X31114286Y-45023810D01* +X31161905Y-45119048D01* +X31161905Y-45261905D01* +X31114286Y-45357143D01* +X31066667Y-45404762D01* +X30971429Y-45452381D01* +X30590476Y-45452381D01* +X30590476Y-44452381D01* +X30923810Y-44452381D01* +X31019048Y-44500000D01* +X31066667Y-44547619D01* +X31114286Y-44642857D01* +X31114286Y-44738095D01* +X31066667Y-44833333D01* +X31019048Y-44880952D01* +X30923810Y-44928571D01* +X30590476Y-44928571D01* +X32114286Y-45452381D02* +X31542857Y-45452381D01* +X31828571Y-45452381D02* +X31828571Y-44452381D01* +X31733333Y-44595238D01* +X31638095Y-44690476D01* +X31542857Y-44738095D01* +X34761905Y-43452381D02* +X34761905Y-42452381D01* +X35142858Y-42452381D01* +X35238096Y-42500000D01* +X35285715Y-42547619D01* +X35333334Y-42642857D01* +X35333334Y-42785714D01* +X35285715Y-42880952D01* +X35238096Y-42928571D01* +X35142858Y-42976190D01* +X34761905Y-42976190D01* +X35714286Y-42547619D02* +X35761905Y-42500000D01* +X35857143Y-42452381D01* +X36095239Y-42452381D01* +X36190477Y-42500000D01* +X36238096Y-42547619D01* +X36285715Y-42642857D01* +X36285715Y-42738095D01* +X36238096Y-42880952D01* +X35666667Y-43452381D01* +X36285715Y-43452381D01* +X24852381Y-30766666D02* +X24376190Y-31100000D01* +X24852381Y-31338095D02* +X23852381Y-31338095D01* +X23852381Y-30957142D01* +X23900000Y-30861904D01* +X23947619Y-30814285D01* +X24042857Y-30766666D01* +X24185714Y-30766666D01* +X24280952Y-30814285D01* +X24328571Y-30861904D01* +X24376190Y-30957142D01* +X24376190Y-31338095D01* +X24852381Y-29814285D02* +X24852381Y-30385714D01* +X24852381Y-30100000D02* +X23852381Y-30100000D01* +X23995238Y-30195238D01* +X24090476Y-30290476D01* +X24138095Y-30385714D01* +X37852381Y-22166666D02* +X37376190Y-22500000D01* +X37852381Y-22738095D02* +X36852381Y-22738095D01* +X36852381Y-22357142D01* +X36900000Y-22261904D01* +X36947619Y-22214285D01* +X37042857Y-22166666D01* +X37185714Y-22166666D01* +X37280952Y-22214285D01* +X37328571Y-22261904D01* +X37376190Y-22357142D01* +X37376190Y-22738095D01* +X36947619Y-21785714D02* +X36900000Y-21738095D01* +X36852381Y-21642857D01* +X36852381Y-21404761D01* +X36900000Y-21309523D01* +X36947619Y-21261904D01* +X37042857Y-21214285D01* +X37138095Y-21214285D01* +X37280952Y-21261904D01* +X37852381Y-21833333D01* +X37852381Y-21214285D01* +X25133334Y-50052381D02* +X24800000Y-49576190D01* +X24561905Y-50052381D02* +X24561905Y-49052381D01* +X24942858Y-49052381D01* +X25038096Y-49100000D01* +X25085715Y-49147619D01* +X25133334Y-49242857D01* +X25133334Y-49385714D01* +X25085715Y-49480952D01* +X25038096Y-49528571D01* +X24942858Y-49576190D01* +X24561905Y-49576190D01* +X25990477Y-49385714D02* +X25990477Y-50052381D01* +X25752381Y-49004762D02* +X25514286Y-49719048D01* +X26133334Y-49719048D01* +X23933334Y-25152381D02* +X23600000Y-24676190D01* +X23361905Y-25152381D02* +X23361905Y-24152381D01* +X23742858Y-24152381D01* +X23838096Y-24200000D01* +X23885715Y-24247619D01* +X23933334Y-24342857D01* +X23933334Y-24485714D01* +X23885715Y-24580952D01* +X23838096Y-24628571D01* +X23742858Y-24676190D01* +X23361905Y-24676190D01* +X24838096Y-24152381D02* +X24361905Y-24152381D01* +X24314286Y-24628571D01* +X24361905Y-24580952D01* +X24457143Y-24533333D01* +X24695239Y-24533333D01* +X24790477Y-24580952D01* +X24838096Y-24628571D01* +X24885715Y-24723810D01* +X24885715Y-24961905D01* +X24838096Y-25057143D01* +X24790477Y-25104762D01* +X24695239Y-25152381D01* +X24457143Y-25152381D01* +X24361905Y-25104762D01* +X24314286Y-25057143D01* +X33833334Y-28452381D02* +X33500000Y-27976190D01* +X33261905Y-28452381D02* +X33261905Y-27452381D01* +X33642858Y-27452381D01* +X33738096Y-27500000D01* +X33785715Y-27547619D01* +X33833334Y-27642857D01* +X33833334Y-27785714D01* +X33785715Y-27880952D01* +X33738096Y-27928571D01* +X33642858Y-27976190D01* +X33261905Y-27976190D01* +X34690477Y-27452381D02* +X34500000Y-27452381D01* +X34404762Y-27500000D01* +X34357143Y-27547619D01* +X34261905Y-27690476D01* +X34214286Y-27880952D01* +X34214286Y-28261905D01* +X34261905Y-28357143D01* +X34309524Y-28404762D01* +X34404762Y-28452381D01* +X34595239Y-28452381D01* +X34690477Y-28404762D01* +X34738096Y-28357143D01* +X34785715Y-28261905D01* +X34785715Y-28023810D01* +X34738096Y-27928571D01* +X34690477Y-27880952D01* +X34595239Y-27833333D01* +X34404762Y-27833333D01* +X34309524Y-27880952D01* +X34261905Y-27928571D01* +X34214286Y-28023810D01* +X38633334Y-43852381D02* +X38300000Y-43376190D01* +X38061905Y-43852381D02* +X38061905Y-42852381D01* +X38442858Y-42852381D01* +X38538096Y-42900000D01* +X38585715Y-42947619D01* +X38633334Y-43042857D01* +X38633334Y-43185714D01* +X38585715Y-43280952D01* +X38538096Y-43328571D01* +X38442858Y-43376190D01* +X38061905Y-43376190D01* +X38966667Y-42852381D02* +X39633334Y-42852381D01* +X39204762Y-43852381D01* +X40733334Y-43852381D02* +X40400000Y-43376190D01* +X40161905Y-43852381D02* +X40161905Y-42852381D01* +X40542858Y-42852381D01* +X40638096Y-42900000D01* +X40685715Y-42947619D01* +X40733334Y-43042857D01* +X40733334Y-43185714D01* +X40685715Y-43280952D01* +X40638096Y-43328571D01* +X40542858Y-43376190D01* +X40161905Y-43376190D01* +X41304762Y-43280952D02* +X41209524Y-43233333D01* +X41161905Y-43185714D01* +X41114286Y-43090476D01* +X41114286Y-43042857D01* +X41161905Y-42947619D01* +X41209524Y-42900000D01* +X41304762Y-42852381D01* +X41495239Y-42852381D01* +X41590477Y-42900000D01* +X41638096Y-42947619D01* +X41685715Y-43042857D01* +X41685715Y-43090476D01* +X41638096Y-43185714D01* +X41590477Y-43233333D01* +X41495239Y-43280952D01* +X41304762Y-43280952D01* +X41209524Y-43328571D01* +X41161905Y-43376190D01* +X41114286Y-43471429D01* +X41114286Y-43661905D01* +X41161905Y-43757143D01* +X41209524Y-43804762D01* +X41304762Y-43852381D01* +X41495239Y-43852381D01* +X41590477Y-43804762D01* +X41638096Y-43757143D01* +X41685715Y-43661905D01* +X41685715Y-43471429D01* +X41638096Y-43376190D01* +X41590477Y-43328571D01* +X41495239Y-43280952D01* +X54052381Y-38466666D02* +X53576190Y-38800000D01* +X54052381Y-39038095D02* +X53052381Y-39038095D01* +X53052381Y-38657142D01* +X53100000Y-38561904D01* +X53147619Y-38514285D01* +X53242857Y-38466666D01* +X53385714Y-38466666D01* +X53480952Y-38514285D01* +X53528571Y-38561904D01* +X53576190Y-38657142D01* +X53576190Y-39038095D01* +X54052381Y-37990476D02* +X54052381Y-37800000D01* +X54004762Y-37704761D01* +X53957143Y-37657142D01* +X53814286Y-37561904D01* +X53623810Y-37514285D01* +X53242857Y-37514285D01* +X53147619Y-37561904D01* +X53100000Y-37609523D01* +X53052381Y-37704761D01* +X53052381Y-37895238D01* +X53100000Y-37990476D01* +X53147619Y-38038095D01* +X53242857Y-38085714D01* +X53480952Y-38085714D01* +X53576190Y-38038095D01* +X53623810Y-37990476D01* +X53671429Y-37895238D01* +X53671429Y-37704761D01* +X53623810Y-37609523D01* +X53576190Y-37561904D01* +X53480952Y-37514285D01* +X32652381Y-39861905D02* +X33461905Y-39861905D01* +X33557143Y-39814286D01* +X33604762Y-39766667D01* +X33652381Y-39671429D01* +X33652381Y-39480952D01* +X33604762Y-39385714D01* +X33557143Y-39338095D01* +X33461905Y-39290476D01* +X32652381Y-39290476D01* +X32747619Y-38861905D02* +X32700000Y-38814286D01* +X32652381Y-38719048D01* +X32652381Y-38480952D01* +X32700000Y-38385714D01* +X32747619Y-38338095D01* +X32842857Y-38290476D01* +X32938095Y-38290476D01* +X33080952Y-38338095D01* +X33652381Y-38909524D01* +X33652381Y-38290476D01* +X32452381Y-46161905D02* +X33261905Y-46161905D01* +X33357143Y-46114286D01* +X33404762Y-46066667D01* +X33452381Y-45971429D01* +X33452381Y-45780952D01* +X33404762Y-45685714D01* +X33357143Y-45638095D01* +X33261905Y-45590476D01* +X32452381Y-45590476D01* +X32452381Y-45209524D02* +X32452381Y-44590476D01* +X32833333Y-44923810D01* +X32833333Y-44780952D01* +X32880952Y-44685714D01* +X32928571Y-44638095D01* +X33023810Y-44590476D01* +X33261905Y-44590476D01* +X33357143Y-44638095D01* +X33404762Y-44685714D01* +X33452381Y-44780952D01* +X33452381Y-45066667D01* +X33404762Y-45161905D01* +X33357143Y-45209524D01* +X44252381Y-24561905D02* +X45061905Y-24561905D01* +X45157143Y-24514286D01* +X45204762Y-24466667D01* +X45252381Y-24371429D01* +X45252381Y-24180952D01* +X45204762Y-24085714D01* +X45157143Y-24038095D01* +X45061905Y-23990476D01* +X44252381Y-23990476D01* +X44252381Y-23085714D02* +X44252381Y-23276191D01* +X44300000Y-23371429D01* +X44347619Y-23419048D01* +X44490476Y-23514286D01* +X44680952Y-23561905D01* +X45061905Y-23561905D01* +X45157143Y-23514286D01* +X45204762Y-23466667D01* +X45252381Y-23371429D01* +X45252381Y-23180952D01* +X45204762Y-23085714D01* +X45157143Y-23038095D01* +X45061905Y-22990476D01* +X44823810Y-22990476D01* +X44728571Y-23038095D01* +X44680952Y-23085714D01* +X44633333Y-23180952D01* +X44633333Y-23371429D01* +X44680952Y-23466667D01* +X44728571Y-23514286D01* +X44823810Y-23561905D01* +X48052381Y-45461905D02* +X48861905Y-45461905D01* +X48957143Y-45414286D01* +X49004762Y-45366667D01* +X49052381Y-45271429D01* +X49052381Y-45080952D01* +X49004762Y-44985714D01* +X48957143Y-44938095D01* +X48861905Y-44890476D01* +X48052381Y-44890476D01* +X48385714Y-43985714D02* +X49052381Y-43985714D01* +X48004762Y-44223810D02* +X48719048Y-44461905D01* +X48719048Y-43842857D01* +X39552381Y-22809524D02* +X40552381Y-22142857D01* +X39552381Y-22142857D02* +X40552381Y-22809524D01* +X40552381Y-21238095D02* +X40552381Y-21809524D01* +X40552381Y-21523810D02* +X39552381Y-21523810D01* +X39695238Y-21619048D01* +X39790476Y-21714286D01* +X39838095Y-21809524D01* +M02* diff --git a/board/v1/gerber/handgelenk.gts b/board/v1/gerber/handgelenk.gts new file mode 100644 index 0000000..efed9f7 --- /dev/null +++ b/board/v1/gerber/handgelenk.gts @@ -0,0 +1,270 @@ +G04 #@! TF.FileFunction,Soldermask,Top* +%FSLAX46Y46*% +G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* +G04 Created by KiCad (PCBNEW (2015-08-11 BZR 6084)-product) date Mi 23 Sep 2015 17:42:07 CEST* +%MOMM*% +G01* +G04 APERTURE LIST* +%ADD10C,0.100000*% +%ADD11R,1.150000X1.200000*% +%ADD12R,1.100000X0.650000*% +%ADD13R,0.650000X1.100000*% +%ADD14R,2.125000X2.125000*% +%ADD15R,2.432000X2.432000*% +%ADD16O,2.432000X2.432000*% +%ADD17R,1.000000X1.300000*% +%ADD18R,1.200000X1.150000*% +%ADD19R,0.900000X1.700000*% +%ADD20R,2.400000X1.800000*% +%ADD21R,2.000000X1.400000*% +%ADD22R,1.000000X0.900000*% +%ADD23R,0.900000X1.000000*% +%ADD24R,1.400000X1.650000*% +%ADD25O,1.350000X1.650000*% +%ADD26O,1.950000X1.400000*% +%ADD27R,1.300000X0.900000*% +%ADD28R,0.900000X1.300000*% +%ADD29R,1.460000X1.050000*% +%ADD30R,0.950000X0.600000*% +%ADD31R,0.600000X0.950000*% +%ADD32R,1.275000X1.200000*% +%ADD33R,1.500000X1.300000*% +G04 APERTURE END LIST* +D10* +D11* +X24250000Y-45750000D03* +X24250000Y-44250000D03* +D12* +X27100000Y-25250000D03* +X27100000Y-25750000D03* +X27100000Y-26250000D03* +X27100000Y-26750000D03* +X27100000Y-27250000D03* +X27100000Y-27750000D03* +X27100000Y-28250000D03* +X27100000Y-28750000D03* +D13* +X27750000Y-29400000D03* +X28250000Y-29400000D03* +X28750000Y-29400000D03* +X29250000Y-29400000D03* +X29750000Y-29400000D03* +X30250000Y-29400000D03* +X30750000Y-29400000D03* +X31250000Y-29400000D03* +D12* +X31900000Y-28750000D03* +X31900000Y-28250000D03* +X31900000Y-27750000D03* +X31900000Y-27250000D03* +X31900000Y-26750000D03* +X31900000Y-26250000D03* +X31900000Y-25750000D03* +X31900000Y-25250000D03* +D13* +X31250000Y-24600000D03* +X30750000Y-24600000D03* +X30250000Y-24600000D03* +X29750000Y-24600000D03* +X29250000Y-24600000D03* +X28750000Y-24600000D03* +X28250000Y-24600000D03* +X27750000Y-24600000D03* +D14* +X30362500Y-27862500D03* +X30362500Y-26137500D03* +X28637500Y-27862500D03* +X28637500Y-26137500D03* +D15* +X43726696Y-41500000D03* +D16* +X46266696Y-41500000D03* +D17* +X49300000Y-34050000D03* +X48300000Y-34050000D03* +X47300000Y-34050000D03* +X46300000Y-34050000D03* +X45300000Y-34050000D03* +X45300000Y-37150000D03* +X46300000Y-37150000D03* +X47300000Y-37150000D03* +X48300000Y-37150000D03* +X49300000Y-37150000D03* +D18* +X23800000Y-39900000D03* +X22300000Y-39900000D03* +D19* +X37295000Y-30321000D03* +X38565000Y-30321000D03* +X39835000Y-30321000D03* +X41105000Y-30321000D03* +X41105000Y-24479000D03* +X39835000Y-24479000D03* +X38565000Y-24479000D03* +X37295000Y-24479000D03* +D20* +X21500000Y-30750000D03* +X21500000Y-21250000D03* +D18* +X28500000Y-31000000D03* +X30000000Y-31000000D03* +D11* +X26750000Y-47250000D03* +X26750000Y-48750000D03* +X38000000Y-47250000D03* +X38000000Y-48750000D03* +D21* +X45750000Y-45750000D03* +X45750000Y-48750000D03* +D11* +X43750000Y-47250000D03* +X43750000Y-48750000D03* +D22* +X24550000Y-26000000D03* +X23450000Y-26000000D03* +D23* +X28250000Y-22300000D03* +X28250000Y-21200000D03* +D22* +X32700000Y-21000000D03* +X33800000Y-21000000D03* +D18* +X25250000Y-21500000D03* +X23750000Y-21500000D03* +D11* +X50520702Y-23848198D03* +X50520702Y-22348198D03* +X52270702Y-23848198D03* +X52270702Y-22348198D03* +D18* +X48020702Y-26348198D03* +X46520702Y-26348198D03* +D11* +X51300000Y-34850000D03* +X51300000Y-36350000D03* +D24* +X26750000Y-45500000D03* +X28750000Y-45500000D03* +D25* +X24312540Y-47750900D03* +X24312540Y-42750900D03* +D26* +X21612540Y-48750900D03* +X21612540Y-41750900D03* +D15* +X35500000Y-47750000D03* +D16* +X35500000Y-45210000D03* +D27* +X24500000Y-27500000D03* +X24500000Y-29000000D03* +X26750000Y-22750000D03* +X26750000Y-21250000D03* +X28750000Y-47500000D03* +X28750000Y-49000000D03* +D28* +X25250000Y-23250000D03* +X23750000Y-23250000D03* +D27* +X34000000Y-25250000D03* +X34000000Y-26750000D03* +D28* +X38000000Y-45000000D03* +X39500000Y-45000000D03* +X41000000Y-45000000D03* +X42500000Y-45000000D03* +D27* +X53050000Y-34850000D03* +X53050000Y-36350000D03* +D13* +X31250000Y-38850000D03* +X30750000Y-38850000D03* +X30250000Y-38850000D03* +X29750000Y-38850000D03* +X29250000Y-38850000D03* +X28750000Y-38850000D03* +X28250000Y-38850000D03* +X27750000Y-38850000D03* +D12* +X27100000Y-39500000D03* +X27100000Y-40000000D03* +X27100000Y-40500000D03* +X27100000Y-41000000D03* +X27100000Y-41500000D03* +X27100000Y-42000000D03* +X27100000Y-42500000D03* +X27100000Y-43000000D03* +D13* +X27750000Y-43650000D03* +X28250000Y-43650000D03* +X28750000Y-43650000D03* +X29250000Y-43650000D03* +X29750000Y-43650000D03* +X30250000Y-43650000D03* +X30750000Y-43650000D03* +X31250000Y-43650000D03* +D12* +X31900000Y-43000000D03* +X31900000Y-42500000D03* +X31900000Y-42000000D03* +X31900000Y-41500000D03* +X31900000Y-41000000D03* +X31900000Y-40500000D03* +X31900000Y-40000000D03* +X31900000Y-39500000D03* +D14* +X28637500Y-42112500D03* +X30362500Y-42112500D03* +X28637500Y-40387500D03* +X30362500Y-40387500D03* +D29* +X32600000Y-48950000D03* +X32600000Y-48000000D03* +X32600000Y-47050000D03* +X30400000Y-47050000D03* +X30400000Y-48950000D03* +D30* +X46020702Y-22098198D03* +X46020702Y-22498198D03* +X46020702Y-22898198D03* +X46020702Y-23298198D03* +X46020702Y-23698198D03* +X46020702Y-24098198D03* +D31* +X46520702Y-24598198D03* +X46920702Y-24598198D03* +X47320702Y-24598198D03* +X47720702Y-24598198D03* +X48120702Y-24598198D03* +X48520702Y-24598198D03* +D30* +X49020702Y-24098198D03* +X49020702Y-23698198D03* +X49020702Y-23298198D03* +X49020702Y-22898198D03* +X49020702Y-22498198D03* +X49020702Y-22098198D03* +D31* +X48520702Y-21598198D03* +X48120702Y-21598198D03* +X47720702Y-21598198D03* +X47320702Y-21598198D03* +X46920702Y-21598198D03* +X46520702Y-21598198D03* +D32* +X47955702Y-23498198D03* +X47955702Y-22698198D03* +X47085702Y-23498198D03* +X47085702Y-22698198D03* +D29* +X39900000Y-47050000D03* +X39900000Y-48000000D03* +X39900000Y-48950000D03* +X42100000Y-48950000D03* +X42100000Y-47050000D03* +D33* +X29650000Y-22400000D03* +X29650000Y-21100000D03* +X31350000Y-22400000D03* +X31350000Y-21100000D03* +M02* diff --git a/board/v1/gerber/handgelenk.txt b/board/v1/gerber/handgelenk.txt new file mode 100644 index 0000000..4a81a2f --- /dev/null +++ b/board/v1/gerber/handgelenk.txt @@ -0,0 +1,89 @@ +M48 +INCH,TZ +T1C0.012 +T2C0.020 +T3C0.022 +T4C0.040 +T5C0.083 +T6C0.098 +% +G90 +G05 +T1 +X9146Y-9786 +X9350Y-9547 +X10039Y-18307 +X10236Y-12016 +X10236Y-16240 +X10236Y-16634 +X10247Y-11370 +X10307Y-13976 +X10335Y-9654 +X10335Y-10433 +X10551Y-8661 +X10591Y-9449 +X11043Y-10053 +X11260Y-15906 +X11260Y-16614 +X11417Y-9156 +X11535Y-13504 +X11772Y-13780 +X11954Y-15901 +X11954Y-16580 +X12126Y-14921 +X12146Y-10068 +X12205Y-9156 +X12280Y-13189 +X12283Y-13504 +X12677Y-11654 +X13166Y-12874 +X13260Y-16067 +X13268Y-14638 +X13386Y-13583 +X13465Y-15866 +X13647Y-8473 +X13846Y-14515 +X14130Y-13984 +X14134Y-8780 +X14331Y-13780 +X14601Y-13500 +X14604Y-15042 +X14685Y-9134 +X15005Y-13355 +X15178Y-13130 +X15305Y-14228 +X15551Y-17244 +X16142Y-19291 +X17244Y-13819 +X17441Y-12087 +X17598Y-8780 +X17835Y-13780 +X18021Y-9784 +X18228Y-15000 +X18538Y-9251 +X18858Y-9252 +X19094Y-9961 +X19134Y-17087 +X19449Y-17402 +X19882Y-8228 +T4 +X13976Y-17799 +X13976Y-18799 +X17215Y-16339 +X18215Y-16339 +T5 +X18918Y-18400 +T6 +X9016Y-14685 +T2 +X8381Y-16437G85X8637Y-16437 +G05 +X8381Y-19193G85X8637Y-19193 +G05 +T3 +X9572Y-16772G85X9572Y-16890 +G05 +X9572Y-18741G85X9572Y-18859 +G05 +T0 +M30 diff --git a/board/v1/gerber/handgelenk.zip b/board/v1/gerber/handgelenk.zip new file mode 100644 index 0000000000000000000000000000000000000000..e36a08aadf2c014fdaa31a9fa24455ed1a495f46 GIT binary patch literal 48659 zcmd42d03Ls6EJF8sV!PsnT1+vnrW`3pa^A_nx>Vdxzb`$x#GTJWo7QUqKT4inrpd& zqGT?(LgtpagNTYsfPjkV=kNF3d!PF~-#_2|?>-OAIWuR@%z5W|&%E!MdFQ&d*v>;@ zA|etZ=1E2togxRKo}L#G$@;iML`p){Ko!O!2gNuVRy7`F>a<2NFjT;f6}o6mgnAxZNlNgk%;wwg-}}p zK3qr{>7CDm!rUj(?)XrCBWvU1up`;$R3T>5I4WE?H^S*Rftjw)B@id`CQe?65?R_o zng6JS$=`D>jNip0ooR}zW;u_!u>IPp@w^2(E7lLql3$A}(^ZC<_+s4kO1IeKmz2DO= zG9K$S>%Q%};Asfnq_DMBv=6RF*UhsV2lSt=P4BpU45R(rL?_GdZ@{1_s+O)5VS9f1 z8@(e!>S6bY)^s)f8XsT#lA13!5>O@?YbrMpVEfnlKimVRu~~j&{`w;v2U)2IcTlJ1 z7|Z%os%z%e@9dVCa^pi25B)}tbXitOh2NQ7etf7LkN_f>E8u2d?Nmfe;|Feqx4cZf z<+Jy5(Tk*?nI+Bn{q8ysE8zBY)Scm<&iv*gMWv^W2fDSq+_C=XvDg{Ab}7=`YZdv@u{@~z6xAC2m3<=t&FwgqSjoxDe||rbe#7q6Dx!(|AcI{-F77Mj z6cuK%y&Ys%NNVR^-H;&0-a0A@Tan?W!eo*UepqK7?`i9?#Gk^_U(F>ORb8pZ;}>7S z_hxV$P?ErNlWW0PYk(TPeDaHCnh)qK^7NK2tyrLU|(u_>3T<8EkZR; z=VTLu4~`>SMcPsV5|y~9b28&zM;6x2)_-eU6}e3}zusuD`kvmEZcrwB?cvN{>bX}x z!BiX5OKw*(9sx8Hl>DOjG3k5{i=i784jP9xr1XS#D&5Q9iLPrkv9t7%AyyG2yC0(8u!p>Z)wKSPus_V#akICfCJl!vIBsQl_U!Bel2 z$ox=;UP#re zau{NT%{51;{%Bjh=}VK<{w3HsS=-LQq|U%=Rs^9%)TJk7KYzh)%D?K_)fYaUEw+>& zyIbzUOmmn+T5GduNaLN+xu~<}i(k&M@{G>&t7sXkfTSUh=})iHN8D)He({go$Tnpc zr>SfUI6mX4SGjcLTpw0sDqCCPu1E0CSS5oO?9i4r&edye?0N~-Y`7$cl8`M)xI*9-E;SAV@8UsW*M5OzAXJpOni8+gX&#~|CnD2 z%v|!5QTbbuyUb57r5lS+pWnCsBPRNAM%VaOmU!b)$+Z(Z6}jPy1Me17h?kN?i7)Ld zG3^Hl*$5|If5u{!9?0xNW=YSgWTAIsx!l3u`SjGJH5bCDdb)d-Pa>r zY*PRAvoqt3n^M>^y~zj$^s{N2Pb0>K>xoyX&YPVcbKdb|S=KyiJzj|BMjwT# zlz3MgO=rwVs!`1})$hQ<4;bv-j7ud0)hs5e*$&4=-wLF`TuiH#P!*kqup(-*;yP1J zL3Z3e=$#de-_`bAvWn}`$-X}|lXjIH4<2m znLGF*pf+*LsO7deT=nv>xFUDp%h#9vPAQhRhb!gh7I<3akB$| zv)7rxQ^Kj7vze57ePC;lXNz0K*}jMkvrkmrcWL2zBih$x#M3A3p3o>sQeZx&_nzh8 z(|+9>FH&6fpZ_*Y_BB+azi#91<*&Nr+l|dbPQWac$)k*%3?s8^nI>{(xAKz?csNCu z5MYx}$MjA?L+<)3y+{LQk14!wrN5aBZFe%7dVRWWrUOBAV^-jLpG-r2ib{BPx{cAE2dAub@gaN1oZUiy)p>NgdN0V@ z=7v*yI!Y6wuku)((s|YXCrjQp7NTQq;}KspKK_lbd298^HG8Q;4;Pv0ai#uy2Ry6e zqx-L{RrH!9AOzt`jxhD_cb>sVzdUoK%6}%?&w2UCt|&l7=HBzW4-AXvuUoaJnl)tc zu0S>Aj@i{i{+&bmGcwSzA7?urAkWloc50-LVRehx(1QpO07-<$8v(_MVeVc(q8GGgdWSL5QCnScCjLXnsA z(n=WFuDFk?Qp@FIYnCdh{t9%@nl9H)WsHj3o#T|^lrgTdW!qv_h|z+9^_0Euo83pb zB*(@|Or5{y=c~ia&|mgX-aEJ|t^SgGB>SsRn?S9kUDDZQ)3NYD36E%=#*`XXhZp*u zu6d^bQbU}Mi?ISYSKQS%_%{Z+thn+!y9NvKzgix8-#;^bx6aU3kS#Lm5z!R0*T^#g zGTkD5fgX%sk9)3D7=2q4b$Q#dlxN-dznqz+S!{#+m9>plQ)bCQt`%CZzxlaVR2P#2 zI}hKnq5RTL7Kqco)jBr2GLa67>TN}_tGxmC6^u5JT6nQ_#QBAEV7BYQFRD^%jT88JQFck_3GJ_S~@e@;a9D#xbX{ao3w$$$${>`qv9J{s`#v!p(HezH0XZ zwFc_Z&|k!upi2(&@Xq_n-m7-y4piP5UZUOZr?if3E0-9#`~Rc?txE#_vHq?lZd%V{ zzCipYpS-fZEUC_yUulM~*!7NWB{x8pd(y%+c)5(rt;CX5g)tKGFz?lapHBilPY5jo zpx!Kd$zNTm)YlD7#d`ZDP8qIf%9XynU=V%bz=b1QR)DLNyE3t9$d(!MuerqT#jTh2 zzkRbe;zai^GxPrE7F`oOa>ivk_tBMJ*(imUhbVHO>^UOWC0}5-S`6QaO*84v8hE`! zr2bTI%cfD5r3T}|OM?~I_{SrP9velX_t`pIeAX>vAJ(yGV0kb_#};LA?H}7xQn+;R z5LD3DHqY+p+5r6HKGwHg0_8U+pwI~~8t`zNaz6W$hW;-;8Y&*v|(*6%H{Mb0+5<(ZwL zpXja-chX#lo*~qUOH?c9*ea1D2#)&ppH2*h>`qOStV)v=S)2dk-g#g%VuP0t8Vxf> zmP<-doUD|)S>1)Es0|KUs-P!ip8y;2`CyaUj^DqZ}seV#91=PV7TpVKPPDGpt!vj!T z6};6$^Pgd%VIRdB(W0a-0uT#Ski?9Ucku_9oC_O_X6+_o(_NyP=Kt^m}A4lO0!>LA|SvT#JV-O+r|x$tQs+ zTdVcPe;}-K;=^$@EE~mS;a1OYtu8QEmzktXC@|BvFehwbi}vQHvMiyInxqyz)2b8Q z#^fY)0(_0qYNC36X6ToA2y4M=~aCA^*|U#yFWo z(?li}w$f6&|8N5k^(%WPeG9B_tv;1jw%On**okOv`D{U!TbXN536mmC(oH6*a2ai# zmV&y`eZSkD5Ww`U8EH#zVnRR7%?_I^$WfA2+hXToFl*bE7-0qVHt&p(X&)xlM^bha z>Tdu%wy#q2o}d+WW}Z#a49C6yvr%YQ*saO&(V;Aa9tr6~QQPLJ3a-o?U6mmA=9Mmh zKE2-f+9^%>O7+1(Vw(v>;pgdmot2;6-B!jEt*)y1$r#9z8f_owC1 z=Fo*mhkONJ8$-ti6LN)Vhk6Qmo|Pu9!!-VAt+)Y*HHG-a5fbUdLCsDGkr3sURE}{Y zI^OWY*d}ZWvDnBuII+Zi)L;{2`7%A4o^!FwvF#U}W~zXS4til@{Gcs*EuP=GHE#lG zqQ*haFz2xwC6#gB4nI*9p>b6*+P0qPip;BuC|mmS%4(}h@9upD{dRCmp}S-#8^->1 zO4^<6>i9R>C8vbYP|57ZOp{TstGH#NGjVqZWks(f<1oqSvt9CUp3xolpM2=8ez}#} z{>+^A;?N#h@|i^1o^pK_df%Vrokt+rc=wibkP7c`R z##pZx#m&sEJ5{S6woF}HdB$^(Bewk9H9D@$4IP5|hKP6Y%e06G-ASY0Une1xTZvXT zBqo;t^aMsI0B*sVTm`BqIG(p(VA<%`PW~r0@SniMlFN^`H9mG#NbLsc z>nlo$K#hJcsiwI20Im&GGLm{llLKn1+~P9BT+deJ)k_gO)A0Z+dv$l2qeWDe>}Rpmrjw#B%}{-0rF6VmA!$Nj%-pd|)v zHv2A}Tm+_7tOF*wHmA2{uWY{z1hHz|wIN}=@Udj-X3Yds+s=Yg!UP92{Z;f>Uivu& z_949`p67@C?%;=Umw!f)l;p0y;Hj<@T7=?sPy9weqw5kt@48tBHfbU1w_K4vgOKIr zY1)F!G_lGNj+6b^S_(r{c2NgIYN%$-9<;HuCbmDdZj?t|MgU$NtQiwry}Pkuba&mw zwvceKf6{-xl=k6~F>A=F`}SG06pPz{x)QM&vizIp)xM2Y9zPKu{B-PW?*o&~hm2ZJ z?hgIUDwa?6Hw?mrX8N`J>xoTKpFg_*Rd2`aJ^fC|&OQJr+`N1){#|Yn4th7LfK4P z`uZVL#V7~Ox~F<}3Jc8oQN3m>VuO%&A}5W!=(2r%p6#d_U|8VUUrvTxAS^OTE#N-rdav+ zPNNQRsXb;-4(ptG=|ioW9H}BXJt8E)^QuTlRMlh>(*^4UCvZlXUEaKg$mNg^5~-$} z<;hmkb&ts_=3pO*G*eQm28n2TIJ5he`Io#sUT3bCs~+)38#BnV^H_%=nBwJZ@Pt#h z)dlku3;0s-qZjQh<2dl|dw+fBa_)|{oV08(o$mA-lgxQPrm8T5t^9sH?Ay0%_-`jY zn9Oo*2bbxnwr=u>4&b>0ethS3x|-3)B9>fV z4xepq{@$Nq(9v{oVxX{G)%*-HOnHs@+B3_TH_A_Fp&aA6ScWU|{9&3C#c%A# zt1^XMH{1Je;_?y)+s6;$$A5T?Ica?}mF;UkC0pwH{JO_jw(Q@NF|1JCi;qoS&xG>4 zstrsRlze^ivFy__xzkiEb={k46|Oa`d&) z0A`q%G~sEjN|?O#wQqcItx0Z2#Kb7biFQMs zu>lSmET1pn6}7Os1m&Z=3$G#v*Ct>*WOd$?r4T#Rq1wAja+eE(9~eNE3+^qIzr6sp zFuVSoU3BmzRc4*6IKAmd#|uc8p0VeDS{*IPo5`2_zJ6K$@jKf48Es-oj>c9^9v>Me z%stK`1%wz44CW_Pfcq<0=cP`jT?ig)L4OBiJcC0|nYT+bH4mSWYsmonh$cHN-}|r< zu;WlnvYmJ}FjC&5&8FdFD+60PzWVy zV-^zz9)Ko$sNuv) z*sdukb)08I{SRQw@e?S=@slV5?CZ?GVi)+~hK8e}U{h21uDFYAmHfjF`OrTNC@(AT zqayDGot9hVJ(XJupU>v+8hmj}zf*N(j;3f~*naoN8|P(A{z-JVN;$u6@lkb`$ur>f zh!Zi2%c-E*i{hkTAm4h+dKws+w7MJ`9gMB_gRCX?(=qczyy4%kJixppqT$dx(cBH6M%#PS9`{EN zYPFymKDnyljcAvh^(v4F$@|V8?h+#3eEsY`Ok8nA#ztTIU*bRIC zJ$3C>k?*{_6fu4_#pr5X!mlQuuiGwySMTyP3BUAxc>K3E!{>#?K#M|Zo#TLtt%BTW zN>Mkiox@XE@GnLDX&N3^E@$|Jn!EWNvQePFsds(pRKIaB2m~8~@6u2E*+t=gb(nU~vOH7jCQ_CH2nnx>MuV+F%2r$B%tkN9G4QP#MIDX#W=C?m zV=9K9-(=itIn~x1)p~H3^7M_018)ivgZGHu+Sr_#w^-B5zubB|GI1+PI0;#nTVJi8 zfF)89XjFTc7gj|P@zm8@oa@GX=$fjQHtOGd_u&XF3`%$8a)*OQ7`10q4-UCA@YMd~ z*h@H%FH-92W>1;aH;LsOGbM}G=bxy;rzcw(JRaiZbWP*w(Ag!z4hBlKVFl4K_<*+^| zfrR=MQRj;kxXz8-8$+3H-(sVK5W$WV`eo|oL8WD-dt=begkXrT+{x<63Fyxjp$cRS zN)ZZG8t%Q#=c!W4JL{TMYc(?jJJJWWyJT7IWV&IV4T+!|=f1J_zyHl^rx zCF|U}fs*~O(`Pu|d8xGgX+;rXO#jzmW82GaB+1kXuEPMVyz}J!(XSu0>pb?%Efp8h z2JOeC57$s`*?Diz;X2rP7sl6vOA7PXqZcdG)zxFWfw8R}^O8r*x~axWUvCniPQ$T< z_E;Sz|8`eWhjJEQaE8X>AWv+K<*eW}N}6ayg|^@;7v8hqN!FHpaB7xAHen;5647(0SHUG9o%C+&tob8xjPpWV$psiAza?Vj`! z;?LSKvi9|_zei1!%q^?vU#&OaNQkHVs!Mjqe=Hqlh|B&yZbV@<`3NEj!#{;1aDcc2 z;p?zfDy#i7dslmK-kOS;{Du1QrCKF0r&j63zb{HikYFyBhilBM)6WY;Ir=Gt=}iha zxGj?k_$t5=);@ivx0rzL*`+nAcT`&Ll4;{p%~&ooMBVQ4UE|2v^v$xZ&P`(O%XPJa zCaWS}nT7xVb)nbH#tET+jZhweXmHU6TQ_C>VO>d;?pG_5C)ql5^B3CW;t#j;pSA;} zpRa~mf)$VTEnQ;3>DRIKswLyteA*>o?A~vu{sfaBhz$Bf-@I z3bkNdju4S;ly?affHQ|_O(vDVD|+Z5x=k@Gf+v*=waf%h^tJALFX5717U zV>b)gsvPBttF4GmQ z6p@ZlYU}-+!-X>4b$j*Gb%w8+PnJtSxi?R>PXaYRd)ZBo+a|cA9BW<@sawtjJG;-% zjFzQYpw!jPQI4_+wG+gl6! zMvzG@Z@P|sH+?(U^;IzKMfO)~`9bFCkR@u5+Olwswf(kLzh~-PxD*}ub*cAD<;}4w znh#LYE{N{I!w<2q4!qrJQd+wQWw#(_Vuc-zO0h1kuEoQJ_DhYleJ4j)eP>6yZ_7L| zS=wHA39fHF5=$-i#tj0Wq}(3$uRv4^QS51ig1X4z+A*MgExl2twYUr|yQA)-imnd- zJtNZM31H~~xT6Je(!5v{=eD4Q1?<`m99(jK)b@2{ZE31~wI8`_bqNe^L|v48J;^ zaa;_Zu@}S2anE(CS>QukiH|FKD+?d?|K3_1T&qVFj81`ZbCB;5L4v zijuqYv$vd8${A+Xj=)-j>3`Qf7TL*npV0E7++`32F48EQGme*kEaj-lcaNV%pd9~+ zl(N706slyOLXV!$yWSIJ@_D!8hVxsWkc;ei=2!aKWQSKB)Ih&3LPjQ$ZM#^kPce~w z;}98K+p4Fi=+Ioc>f8M2R>bwi!K9PDlDZY%2m1 z_wE=?;><;Z-6gWMNfHK90G*wQLeXvV1L)81KPJl&t>QLzRg-!BBd>JwPpnWEv8JN8 z?&F@^58OB>TEgySbvZdWwkjV!#o??*`Ti{P@5`l6!0!9P4c(e}ijSQ6F#hBnZ+ zhkc^v4mj(Um0;gm#2-;`^7lc#>c0jBo5;}S$R-#>IKf8U9JA!bTslT=ePb^}#Omux zQ1ztFU(=;yO@(0%`GRKUlfIN}4P8OtMeDdeTNSBx!034%^Qd&o`PS}U<%rE|!3K9o z9{}G?byxlLrI_s5+55E8>|l54>~UPeH#6K0b04D*2b@TN88`P`IVJd_?F`5WZfpaf zuC@HZFb~~wANRs!G8^g6Q9_tdHQ3|iEr zv-S(XZOFM*iltN#^4YqP8&oLwNgKNCGJ07RyAhrz{VDM)!9*R0_}7PQd9(EMnR~hA zqgprlon9bN8og~W2!s_gV}_7zvK7xvyK9@bMvdP|2o1tZd~6Sn_xMHok|jCnXp$-w z(wh80Q1#(&MN}4Xv$TlkiJ_U2&$!c_w(|iLWAfAOO)vZl$K{?N;uc3~<2&X$BS4{b z{j>hOX`(-G1&5Bp${VcVN(tlM_}#xCsF1eyN_LGfn&}^;g5=3t@bp*wFx`{1@KKU+ z;#4O*0*EGn+!ScFc^M!q!&xy0&dWz3Y?9-W4~TvUl~2x$afSv8`U*e8|DpRUSV3TSxy zrzdPhY|qf<0@72xe`->YV-Hq&5~^@z+QLNMUdL9V+cZvPwAbbv_)iU0^=Zx4NDFz1 zva=Pl^wU{sWCBCW*!1!Zi*C0Eu2i}un}t)SBYEocf$rfXnC0f2L9)oJ^-{+R<41kL zC(d%l%9otBxDikZvqYpPMyU06uwG~M{5pJnb%WZnDKu2`UR|SwWMAz8Bv89R+jZ=ms*zl42Za*pXDD-)loO5CHBf}wkNB=dQeR#%Ufj!TN-<`7 z$McbR)+0ERK|1)MEP!M0SYmJ}NNHl>_tTijq3=V6VS|mNhVrG@RDN(TJdYXaGmM{9 zDJ+kOWUfu!-Kd4x26WHi$E0%un!I!N3m+F|?e=wfWYv<`cIlUU^8J$u0!7r1dm^=1 zoL?eZ0*BS4)N+Q)b2`kPApUyiw7ef$qh)wm?MVpm4Iza2rjXTWTXrTw%3q@Rp*jfU zJyx137C$^%!8zJ4en@HiZ}+JanM@V?Q;;HkI(Za&dWT0sf9Y`85JR64l*6qjg}cEU z%d6b$65I)MNf7OVP}15Ih;Da*o$8xsa96_>FpS-fq6r^>M}$=W+UOqZTo%4sp8UOc zwKEQ~@%s^2$Ge@g-OvrGqW;s)b`guJqT0*cYKlZ$WteH%P|o9MaMuE+yuA-P_Hnq5 z@@K&X(Ob}zS?)d=pYE54AFQL;JczQkM{bA}Z&vURSyE3&Q*~b)E#lY!qmd~s7nHBM zxZaq+qTYHFv)86=x*jJ);Oel7tWzIys*Gu#^fxAP#N#2qRhBOfN9D$2#;A0qI&c|k6hv0gX{65 zA^WaURbh%z`>wJUw{e%_F*gDCkHsiwjI_V^LMC6F=R+64<8tFT|Av%zVRco^24g1m za(o@)?9%2^7k6eFNgF3MK^Moajdf$@m+{yNtbwD#9A0!sZbjq)AgB4~gz`W?|5N+PHj%l1Viw5u>cf+h7pIcn)UR$ziK^@oc1O!p(_I$;j}ii)lSfd$_>srC zr^c|FC5%~{E6y97h!FQDf=RGlxg%t>kG~O2w;Wp#~!ptcD!?{=SGIoe$PJg7qlmu63a&!i7Mt$X2t= zl?}Dz7+6c_29dZ5f7!7GO$jbddKXsTVh#mB?0eSiZj@j-e_`oD6LR`!COOz^X;RaI z;#0^;Q1X}FQq50>VYsvBRZ2ulm^5XzN-z@M$55ppd`=K<{4b))AV}k8$w@p-V zxZ?kwc{f?*C&1z#DEV#x;36F;+Kbrvjw+#BzBSVohhqi>G@>#YvmvZGhQ_k()soG( zqZGr{!q7GN)VHA+)#sy4QsD`x3DW0f;d(e$Kv?Av%H?!6oBJ>T5F-iAecj8DTw1&C z`e;j>v?+-eQb84y0YeNudW- z&ys|AXY?b1jNCFOpp8zC?0K4)` zTo=UVO63BF_69mhmm6<=_01qRF~G0GUGT%BlnI76qTx^BUSf9ui|v|?IWFfmeVcAl zmmk{}){#!hRL^^mLY*~TKBPMo#zqfQ`}mg;O6*Uew9X%brqe##Zq=#6b5gGDGyNW7 zS?~eayNP%wocHV7Tjg&3@AGiB)A8u`nUUI-XO=n^Gi{xHS1aa5W=WWP1SkofYvOq5 z?grxiL8_a&lbE=ogx%OKgQX(Qv9C^mAIYrbXE}q>R|W=y5bF9zLramzik9bp0iB+G zIos5(2TcOT$ib-DaXbE8cK3O9#hLGWA~7xDV;rRldD6@Y4cb+WH4(`J+~Y(|N@!$E zfSm4k5Rr(Ba(w}&Z3>pS#cu<9pRfk5Pqm9>MI#5&j-!C>^YImkdQ~gZnS|~3)8pwE z>anrn*}e5=O?P`Oz9Hx;IT$#>F482A6%gNlst`tq6?# zi9^4iS8+y&UjmXQl-_g7O9c03-#wMD#omrO?asZ&y2HIl)*DLuwh-ey7~AI9fcyy?N{yGei0Z@M5Ki_;wqKvLrcL0cKN6OCoKDKzvBM|%fQXsqZxxr{HnYr zb0;C9WKT^{=3uP-OC8cf?)OVsh}E-V@h$+QnDkYKs|w6^Qm;lr>US8k#gH?u_it;~ zd+S?3?9S~k7Aw6t)LToQX5jM?zPOgHxum+y99R)N)_AVmk#-ww2j)bYX3iU4T1k>GrH~m zE0&-=!FyFUp-PV~e(xXr>sj~O1NOmv&jO8)%?JFEy80JFA%wYQY&9jU>nXn#b?&c8 z9zVM6!b1Ew{@pL7mEh*`+K$%|a|s^;KlsP*^Bz8z=$~}RhiqQ$@8}Q?*v`@5ovRz} zIYf%VnZTD<6=|)n|CI08lj2FdhedWlwOo$ea!j5-@HL*cT&aKNe!O$tHBmixCHNuH zT3Z>E3P=-NUi_2K(-=@ugo{h#$99M|m|7J#)4rT2S91H92gTL)Q!P6+Xd(*}N(uUJ zsXY4nXiZ*L!?A19drxdmYvIP+?o}HFS=Y|n6nA`ty|(m1;?yrg%9GFRJ5Ne&{)aUd z%i4RrzDCxRw(~YH0Q;?IM>6ok{Dt578B?g^P9jnN-i#jBjRcAPkd}*?{^BQ01P1$R zT@iGH0z==MhZ6P7jd19fk~6V;pNHV^2cAz;%q`b}EgVGq8=FPMj)Y&`ptt8xCd#nn z?1SGa8==Q3|L!gT@7&O-^T_g%o)NiT?q$>R99j;ONDu))m=R3(kcEIMuu=E_1ze3T zmsrJ9<@N^(B1Jw&L7r7o@C~Ba+7{l$7KZPlNuf8IH=?*Y*g!DYY;bv$Mq(`TN?;~L zc{p@4f*DeoUJX6}gdcyOoP!>P`~QXe8#jCsl&vWx&>Ft!}{5sfghp_Ds zZBb?##h0_skadO9Dvb-?X6-&VZV&Ko#ku{ZrZWO%Wit_Z?|1JTgfOt{h?k#MFmAu= z2{#dnsAZkuAP8w3mL+W^8-`H6oN>_Ny}LJFTcy}B;t;Qg+bn(Pz!w!U8I%c5AU(Wq z-^cDjy_bI*OsjOJd z)7feN*~hN*1V}38P;c`py+!3-MWnZ@E^&H0)@Zu|q);yc4lw?ejA!T#-y5My9yrPH zD|34mGjz|jK`gAar6C{so}wfr_^S~YrXW@88UJVf^E$P|l7r$ncZV~I%x~JJ+Ai(m zwaClhOx>P!rzWl-7Fh+yFu~Hw1O?Uartt%OiG6TbcPSv6ml#2sm1dKQ?>0F zt9(hOcuZ)+^Ufvn)Uk=!PuESuT%TS4+_kn%p+*+M%4a%}}>;-Lt}LOzQC((7~`v?C>_N z>#VU(>l&qbryk`%gC0G6oR%h8TVB;zS-sB1;#5LYTKubTEhAi{w7ophO2b|4UDgf9 zj+TLIsfQQnc-ax^JVxPWbA-E71ou&I3-NqTVpra9=!+#{;d@YrECld<2!(W)!1B=hJljLj@}B@N3SQJE&r#!}0J zlw8lsj~f?OpObw;wgws8N(*vI^7^}Ty??{LZ?U<#D8ceStF2AagyP!x*=S5;MA=|+ z(MRCPi0RF$#_oh+$69H|OvpWdp}?E>Il7)c;#VAF1QYc)L<^(W(7H;i1pf3nVC=rl zF-WMp#&J+K<~$6?jgVUJ>VrpjidjG-yVsb=e+$PqqmgfN10-?l8NV>o`vUX`0X-I& z(3v+%QO>rV=(_h6fGCXr*j!TPrL6+PUVjHEq5YG|x93ss@D<~A_-5nC^bz_a)->tCqsIT|}S4D-Ijxhh3 zJNKRG)#~WaYkAhB?`M>nJZw)H<(J%AUh8VMfNZ>b(7v%2rC(?{B_W_|xS47s!2{$16@}BXF=s9{`FEt8o87|*+h6#2tLdK_ zynAG&MUq?sAY1Pc+>)Xv^`%T&Yq*X>Q)zRtUQtsoK^({|oVy=RO+QUYPFedwk3uI1 z_M(UVR^aQmY_koR4>o(kcCFt)?pNYGCkudbd}%-TmOjk9J?I_@pR!g@p#4f=d#+|n zM-Dkktrd94Xg}#S4U>AM1_KSpNyGdTcH4ZK-EgUB#$mejd5bC$-8|Y zJn#YUhN-C7fex{=?Qf1Ar4QXv>7LDR7MuosH%0O83U=h@E`OYL>lPgJUxCwC*x+9VIiwW)pf~rsegF{R9Cfc!mB)qIHs)tu94fsS582G zo76R)SG;=s720!je?XBTku)gS&mWs35Hdz5PN+ZGn#EZrRi0Kt&J2CvX10u-8(075 z`U&YCsvTIqbnQ#RXq2XXOuy^N8IQ2)t>Je~UU=vensmj|i}nbWC;tW_Jn@rOh<{B0 zqlvw!?}bd$6LdqV0N@Jer|a@(-NnvO?QVKR_Oj~SS#PxG#zgj>lT%;M0?w@b`f`;N zGpsm@&9@dj$Mr;c&YXOd_6x)l3$T!`SLg9^Z3C>+j_-Uim3ct)O8r(Fpg2DNScYe` zx5qc3<*`SJOOhYqcB&#eu#v&iAUTpXa{kL}`e9#I=_(=MPo#TV9hSToN6$j|yQdlD+pFXFsfgD- z%D!Q;OwVgX`3H))I)N(GeIq=>wGBGS_t0>KLBLxNieEZy+&oM{G4F9)#-CMuiMogm z3WaS8n*|4@HRy!iIZR+iCP!9`uJV{LSv>ghrc%>}uo(Opr3k^O$Vk6i51AM#pO0E3 z774Do-m4ECm!2)APrC(NMtYRj0ewwhnGUYgxmaTjEX#nbhYS0{a)Rs90ZlN@v}4T!)>1 zO?`*rdYQtD*kycC;TAkvV4)eWIiku3t4qy(gDXn#^-2~TFCEYSsG-D3t%fK zX5%AL-eSK=#cUbY@Jg68*#!~yi|^5Ue9eOM8u*}Cc1GdIbK_X?T~SH@QOj!w^0YQh ze5;0tE^^!E0im{?Os^9?5H=U`S8Sta)s?`RjX?;*mnp1`uVe*IYhRJW#+UKUPHS!Z zH?qE+d&#%e!TXph|G7sZZ{`dSJ1?l(!Qy14dye~lmF4W)TJf7Vn(uX#Fr9q2?_b!Q z5g&+CdOJ+tE=(kBe(@#w(vbY4{%-g+2k7~SZSMvr=uV8HhIf~R?F1>KD7ke;x1aYRuTK84yF z`A+x}VpVMs1dLZ$@A+L{tAOjGb>gjYMgiCC!Rd}d;b9_Ih3UG0-WXCX$RG4L5{8;M zOf6fks~Kj7eDYhh1F!}-DLw{WsfS({Ol6+XJ+K`8{h)@E-Lj0J#>K3bg9f(uK0+S# z5lnyHTAfahDi8YZUXg%*?3RO)iO&1jK!g_6QRwTaCBI~fqX3HdS)+{&e5=4K6IR+C zqPI2uuFqy%js5q(+gsUlMPee<;VUIfK>w=doN9GOx&}L`j&Tzb6|Bo zOk#|4082mV*L#WL$T>h60IM>(BB}!=nDuQ^uABovRxE0>)z>6;f?b`)2w-LElzDd7e~1Cqk4PEoOt9TqvC=>m(Kgqh+c!#GjTG{*wxxQMrHWK5 zp0#=LPJu!G0tmPExc)JEKxXv{CSJPXZbOcwK zed+au5W|h+Np4io?B&~b$CRY;`Gv;u0mbdzTh17s7BQi&DOm{uL)JjvCeUesR2b6B zMzhg+(e@Ue)51i^adzD;;8AahJN8v}FaU>ijdk@|W% z$e~8VPG1&uA#>G9*i#A=C-+x$F>gmv!Rvh0pe8ulKTc_QuV za{PZ6FxB3~5Hc;!o^&b>7=?ep-$aLdZtu+j$v?ZTU|zlS5V*>=4y9Z--bMrrYSJDp z&B@KZ+VN=HIgmbS+zFOBnObr&mT8ZY9XM`Js%}mdjO}=7n5Dn@>ZATC39!!C!F@hl zNcxx?gv`o9T9>SQqCes4_ga^D^z`bw$o&zef*L!-#wchBo-MQ$&(;}!cb{f!m#6;L zV}qgXP7nhgG6vgsn8Aun${ng1H|!X+gS;E?Y+u4QM7zt`zNo*I8x;Cok7uje43llx zjM^gpCuxk=+qc;o(&U5rG5DdMdB$xzQgO{)zQ!S?Y`=6gNl=Id4E9+a!G0a1_Ssx{ zCLg_rYLhnJ^d9W6nvh!<4?xscdXvvVE3v0PJR1BjpBhYb`{jFVOWJnT2VAbN#E#z$ zsG`RKe#E0I2sO)z(T=8Kwr?JX6q>0YMbKtn&o{>c)&^Qr8H4kdY$X3$F?bHZkKM&& zel%sMXb*<}psWy=%TMiz?U=o-$B+*bHkc1ffE+}2Qnkwbz~PslLJ=UR_GO|9HW#{9 zg*pKqE<%Qhr7mNGfcCo+&$%;uh(WLJW?KQgNfwk@%6v2CXwxq8PZVVPAJkqB> zCMFRp%IuXbfkz=1_sMmQ@Ol)WJ#Qg8EP}i8aBxwLPjkr=eKguAO@v||>ycm2DU3ZSvHTD(0QDRnFtgj0YI(=oK9B50{gn&%n;i|1L7$yI#=m(ogH^JLP!8Bo=}A}hohof|)AUZ6 zUT}`gPa8Dg%Ce-?ph8_Yi) zp|Oh`f#Oau`KNxXr-1+0T^Zx;|0?Bw+Vx)-nA7ZGCl+nWA%x9?xr17vHvS&aI%0>G zf;a}Bg?QKx74F=wjF46@J4=rjRkF;*LxvL{&(iL(pCJ%6S43`M?-)Ys|2 zXXHWxV3mSYX?10)Yxe5ka6*U7^U#@PkZd0bDtx2^N`p4 zS*qv7!l}(Un7bhNv)Uz==CZjQA=j9zM!H-1G|DUAdyH<_w?pKC7Nx3L@i>eIR37RqG<`;JCIJ4dT9@tG-UH!ejd!fDm`uEtsIM~D!o~1`K?caYnnV%_X-@0uNFz45lU13Lw z$QS5$^H4H4KA#%hFIZV37(Oe8mV{n%8#zY=NJqWdJ5$FW-?X&L#(OJk#Xm}FHQO&?kDaN02ObJbXwPm879(Wg6tXwUoIVRh{ls6}h4An$c0)n^wB zb`O2_D%L;4rRZO&Z1SSS2EL(M`x9cJr+uTz*xCg~Y>)bx-K{zuz(dOW(-2ZX)aRNlH+mKpta^7AQ+xH_ zD&GBHcw>;4?)OY1(;J^OjNUxcYom1x%QR;4Y+prveu#C3a=UfwrB`t+NIrm0;(sVV zIzbd(O5;E8z<(flYv%1{>)z>to9maWn0TUrsgW}{L7un4wjf~tO1))+-V$KeJC}NQ z_%zM5MH zDBqk7M)j533o62Q*7We?uOcg~0M%T-VDzI9ij%PFoO_L-zy85(SxH0rH;E++4edL8 z%QGB*AW^k?OzV+c*p{;(p!oGCvWSzOxKaOu&wUfD=brglfIv3xZby6HV>N5OtFkwE<3<`S3edd{ipv~8}j8cA| z(0xpoJepA`HB6HEc(=RUTeSh5YSseY*{Kr0@KhJK~>0@xx z)5&@_J7*;<)h8DtgUv2tPurR2+Pb7kH@MCJpTH}B z&%~TZ$$$qOF`LI99o>Q=1mb$a5x!HS!%aG4vh4pF0NroDCk6xh5g#te!U!`t@&`N zX9NTaCe9%jAcuV>H%?(Y%$ses#kBRKjR|7&+!B7jc~{h))YcMlw7$|K(j1A{^a`rS zcyDYX;I<^-Aq6qFSs#Rf&u`9CsXc?VjYIN2Xq6x`Zws=OXtqC{g7}iR2-S083&7)D zq8?~tKI(gQyO$#%@192c%N#srx~gtf$QgufVFgpb5F4^57C&VRUlQ zx-jr)gDN?RXggdh7cLgwIa;34Gif`;_7%=S;Xza>YHNR&Ovu+?C-wU3!%`P-wiUpa zwJzWD&uRJ9Ve+PKy6T(EHQP||H}(tRwL%e>azKrpXBB?bbtOBX7JRI&$SCVux0fv} ztmix>yQiMd7=+#m{K7WuH060?(*L&3yeF3@%g^AdsYekXr6Ft{8gM z4=^5f$#f4}wmr?{wYpzh$no5o)7UgEX_<%c!R!e(MLvLsd8`nzk2pVW_lmZlxE7(U zw!A}*>oYv9<@>1Nu+{2#_ey3IConM;s)`YXtzKl2I=aw_a=XU%hd02$(eAu&xvI1?YWdu$+T!xdN8uSa zo^@WtX8S~n%UwO@uwy|)*WXz1uuZIL60lZ(qd%FrS$q4TjBAAa2Q58Bd0t7&vz+as zn+UvqY0awC&S&psadhu~N)HRAA{q>cd#B@TYD@X7FPW&Ey+t~kRJp;70sAqB5^?#)%T>XIKKAH z-K|MophhSQf=T#hXV0|ex+29c!p_S_qEO?X&~+b{P~k>yc60BK%(yzm=&u=Mt7P`#D+M=VRcO9Y%o8^ zV2MWQfa-hT!QTaCgM9LBq~^i6Vgs$g#VC*`b(STuL*1*|Un zHQ4IoXxZs>oTYd)H{>kVua%WWD)e&bFIRTSO8{e)zvbMzWqIb_FZs4Bvs!G6os{0*1yauzERR>+mdl6;p}{JB|Yui>@X6%FN1$e;b# zjUSC7iT4b+RKWktqJUf9MGA{+L%c;=J}?1=Ua|Hc44lrhDY*h=4gUB(_*dqT_A@^@ zym-NS4P6&Mxb(qweO5@Uhh5{FSoOIk-kAoi&bETjFRW-!p`LYzKYvzSAhX>A-Hr=h z{%*hY_tV69*_ZwB)}q9Z2i5Qc-|fNnnvwpkuKpR*?yQyG9?y`_Se&X*ujubbNBu+9b|a?8(g7DIgEUKaN1iLkWex%yxp@W)=`qfSne=k z^G9{aQC@TFL9Oq^&_>zyid(Z+|NSD&6;s@@xWIcc;)&rCHU=ISF}0^^3k1uZe^Tx4 zP>E+>+%@;gosMsJTYXgZryxF>c(&;4c(`GCi8dL@EwA^RRz6ODc=@q<(B(ejvHOEf zDW}+J>y6y)N!I|uJF6`=K0@II2t6;I_IhpO=RW_y=uDsP!iwQo;7(&3ugH-Av#J>} z=KJ#5w`e6Uuo_N{PAp4`_#tye6C2-B_qxJyRUGtZ$*LxAo=+OP9-+nVG3snJfn9oR z`;-rY_uw0P5c%1tRyMS=Il|K*F2cY4^;Fr(rf%l-4*++onJjKqA*6tuenmwB3v(YV z*Utf0z-PmX)Ighp^Ah;r&Wf_!KO`i$Tlys=AG5Y?+1v{I`M@N2qB-N%@N-$o+UfZr zJ;259?_{ud^5((I16Nb2e*!w=+N^#(m)pJF$VW#1{3rYr{|c+R76(s=v=3IN6h=oa zmrK~E@cvAzReSEWfwy60RyA^wBCi7Izg%+C_lfV!Lc}@9KT+Q`;*p8*x7sTWTuFxp zk%>mm2Zz4Wy@3z>4t5em7u*GZ(pWQZwX~APiiZ7E2xBkIG&4hK zq$+Ao{dQ})qZBXlUQAF+66z@$5vtL6aCn|`yG&B~&aQzZU_>To2#gHlua8RQ`{Lst zv75erC;jLYm=JpwFDYgHS~BAPF~GpsYn`*Pv7!E#gc!j2v|{-igP1b(wIz+)n3is? zrn^zV+By_n=!a<3S0gbRsOTq~f=7_e_RFTp;0T8A(N5r(Dxt!S1&me;KN8YXnw1iX z<-aq1Qn)|=e3nlJH^QKO>DOS}U!E~}kK21{vM?WhcS{5@L-sCKMw1OboG4I04P5Bs zWZs2Iqq-3q>{}LDz@n2A;h2L9A4;Ej0^9yeTLDO*=WWBDT&{5LA^hZCEaap(m$F~# z)Dq5?Rvkan7i4s}L>iP1!AC4FEd_VPwK-IJi_+;&Y>;I?$X|KR6urywHZM+V=})-a z8?erYBz#SNrw01)Y{&Q;vDz|f^@c@f_UYg7s@vZIWqfVhzA4%&V*6h$q)v3&bmS`T zM(w|R0N$VTB~!c2q3r{Imt;N<%h=V<9tWh;I)kt5T2RpwG424Eoglbd$=mhKu#u zf)O$3zq1+@8ri&$Kj!(QNZHteR^slA$GppVQ4838M-J`{Q%V8fC}rjVA(H71y+hUX zsqPBi4b#$_685>Z)Och+UE*3hW0OgD*GTVWu>WX&-Z3^G#K5lG=*+E3zISj0ij_Ge zxO^GRo9c9_UzNEr%wp#)hfB+w6ISH%uOI*=MbO^gi)LR!Z}A~=<;&MJd!xc70m}~U zX*n-p+Zs3B{)A{OvomoV2vRg6z)qk1fQxWnVfK*0*llN7A4xzulzHiX{2id09FWBG z#z*MrKuvP@>5ek1C{;3dE8pT*@`do#IechPfz&n=a15#dlRJ2d$jQ?P>=qE&Hd6I= z+p*+ME&Q!+(WwyfOJ(nqv)0?*9woEWEslB0@4%URb+l-wy?W_Fx}U|4H0u;3g=_eW zWU^u$5d4X|DJd`Lu!G;;WGAzuKXn=Av25x+*|3tI3|pO}7XZ3+r{lBwy8oU}hJ-(N zJ?X31avQwY{*T@lV51;6Q_0A>cL!I8X`pfRZPQea^99yoyl47Ol<$4e(KDJzBp)>A zSzk%{leNMb3BE?}Vx=5O>BOfH0xR>B$aUvJN%S0C?cot$-qDNGCPwlmF&$8NV6M53 zr#y=Mb@7T+9O-}?O|-9HDQ+iv#E3O=B=wY_JolCzZ+g6n^I50)RlEJ=I|-s-ct0&` ztMvL8rBpw)Ii=lq4jiOJ3&)UIpYEJXUhZyRtFWR-0hSvqWSf|*cphy)K;fLm$d2V} z9#rT9zD}*RMm;_xscD8rI&xQ4#lK(1r+o0)y2ie*9G@8Ba}8#!lag+%5;D-@nn`}g z0)MX3SkFi_v}a2!YR@+o=Q1wA-ZY`P_O*W**A<#f<#s*zm%>j?w>lh`5w^^;If_D! z*9$vsmnw-lBHO)bJuwIWmi;V8MlIOPDpSBe8-7@zr0O5cZEMQ6hMU1#*8Bv0lN4ky zC*#D`T)H+Pn6bBhoA1ntZTGu&yt_GA4Vv95!{oSPYfc*LwD+2vw%y=1EX=C^P~gm$ z+g1%6Y-X4ibGeL|YJ*p(zQ0blHexPfMe(DP*QhuU(INC2peS!@C-iw*d&1KzA3d-Z zMRyiY9w&9i_@vx9qs?aNw9OBlurCzCMsvX zOcCu!+IVV`i8J^Hp;zs4QKI~5dRz_2qZ@h-3Y?O}WY6>y|7BqU?z6Y@%El-~0vBVaXgRTS%8n8F6SE=(zhnZy*~34q)=cau zs*B(8A|sJCCbIP{N8%Kz)3TGsG1J?WyKJR$x$y`3kK@up2?5WOd{P>4;CEj`qM@Rx z%9Mvm%h+W|JhIXXTiTv$(8Ms!q-VK1ja_*Ui3YHtV*pLS2}%Li`=_CYdnCTsbm z<6{@Ff#XEx6j*ThTWwfz+&*l4<#5k+(}o4P*j0zgj|<;4F{{0$+2TVNy3MuHKA#=N z?5dxX%q5^#m`<5;>X__Z_>MWEcrA&n&xsY)i?lzv-er$_Q9}e|?oG}0%s2k0Hti3c zepojEPNJg#rYDLgvbvEyaRE z*cztgiS0{sn=w_^|1EcwzJg4AfB_x9$Rcyp7T(8XnUP$S35PV$Tycm4raSMB zTG&xASDh}y^&3@CltvmWb7@Hm7&>pHz&jBTvc`%e1<27#1c@Nzw)T!miY|1jI_}Gh z)oMxE!rDoZ`p;^2^K3f9ZL9!}dPP$TFE-8#hWg&nd-CAxFR=&1@V*L@zxDjG9(a1>vLA&>#u|P&E5ZwOtL zJA@afOkPgOX(%PLZEJK>Dt!%3xIP1HH|Xb0%j4>HAyDsprg*rA6O`C`?7vmYv;^x$ z+W`O5FY0F35HoOko5&YTgHJ$@HJE|Ho)BE=L>V#Xxt(%RA=+E^ihA%F+#=p^j1r^ zQb>i#=+VSpG3K|xX=ltDJp5)QNL(uGFe~sO@`&$id zZm*%fbXE4Tyk<*fcX7ib6#7+v!&QYnn+$;8Q$^;cL-*Muk4QhKhfg7tsgrv)Efrwqs$Tf+i*CnL3UXS=|k>jdDB)19guL-sb{*)lu z%#yYlj!h7MbG^SFovHHMdYJa>{YIqT?f%L4{TXe8he){mFZm=Lu1eZO!waj4pj&vXUmESwH+V~{=2rC~yYAN$vRSQ3)v8tJEAhmZdo5q_=bFJZTkl?G$H zcz}C-{(i$wdWW%ZkOpn&8QxDt7=kySEeG0WxRUaX;Uuf5UJEML!$jXK{o$$i38ZcF z@Y-GT3v>rmv3~=f*rd6 z`l?^D6hYDRYn|ZJ&Ca%`L=};i=I~SSDH9FhAe=c7(Y(~xOq=Bq0K&~ZBP*3dy}iez z#7a+A90u+D+3C%+=+i~y(8WH(C+9;gja^RUfOi_)D z#+~jj=qJ;l$RiFLA&>bwhO;D!4%nRDao*Wvo zX`?Lzf?U>#iLs@li&k-R>zF9yx}5^K7&L-O~T+ zlvQl_+EW=vtu*Z_%)X{hqAJDuy|-Ie~MfF zV=K_{8V!{x!u7W^-aKpP#c4F3c{Pg{sk6!JtsUwkeqLHxaTuG4L5>Jv)xz`WU~TEA zk~j}QJJNO?^(pvI2%Q4;7hagG0LIfVpdgSpIi&H? zRdzh|Xqg`FCZW0}BZUWkwyxCgFr9y4>;ZI;s_Q0LDNTdz$Z4VqzjqewPwDeI9+8{= zL5c5;DN5lhE-U2qT`=eylzO9e)`Sqe5FVs~?%Fgip}JAOM}{`Shf%bQqljtpngysG zW4Mk&La?ZJaN6P42(19J%t(#c?iB>$1;kC7);PEry|(-K!75S3uWW>SjoM%;2Yg7& zTYk;&Q!}E@n1%URs-7vl?c%^7EydSUg4vXF3`({?HJ1Q4HpC1Ev{_2lXqajofG=15 z_7&09dzGLd$LSM`4oTDa&&1v9gf0un1@R4)-9RmcgkJ*gZn#5RMg6ZzYg&C)iw>Qmtq{NmF zX)g*Q?Ag!Cko%&#`rnL&ME8e8^3cS@`uMe<)SUV- z1_!%3+a(!g)M>b*ie{%QOXw64L^~Bn% zHyhj-71J}~0{Eo+8)e(8Rp%7Cwq9b^(COdYK$g#Kt%M;DjOzy=tyN9Nd_S^7d)~?W zwZS}!?Tpt2#_Tv5*AE{J65=;RaX(TUiJ;3$vdTOxGZDga5P|;$TEHsU@Nyw88fs&l z-`N0=A3Xp+5fUVEvXwMK941Hy8zNz>2cuiz|_PB7(=47dPz*iL}FcQ*$TMQ;HuZbZdozvM*MJ=#ocFNjBHi07Sg03IxM2Moa49Zxfz=1 z%^=;4dnwS^y0(S?>M&9v=4DSI*ijm7jkx-iY+kLGgou72PeziBUVi<#!26Vr2dP~O zoK#j?966bxH<&IOy}=yfu)rl4WP@9+>d3+VFC8WHkIOOJX<@ixpVX!KB zrjp^t9ENn)0Ah#AmQD*2o{rKA$5&`RdaQ;)dED_@`em!48Vab7^WA~Wq7vjvY^6x7 zX${2w8ScMLY|x8osT)l=(xrsifVNz*+@q$|y*rhKJ6AuoZP5S0Zoss$^zZ~_JrZ*k zclWBMwVdoekPK1#>l+Er z3sPPTg8R}vs^CQC)UKoamT`7w5n>#vk^y8PX0dD)ZPvXzAI8XD=?6 z-vQO-kSn);!mhLPmorhi0&tEI>g2;=$450-r^C;fGDK4y@k0D41 zi1t`^2u0%c@<6sBNlVQ^u*&p3D~pZHQo;*$RH0X{sesRDW8wW5#&J)01VWTt?k8bo zuNTD~3vRms7KApumN$V*me*5_gPw-(`l&5oP<`VkQ7m73cMViLlN;qs^Ze`!X8*M5 zsuo=v#tCpdB)4=zma&6)%3?l!lyxAQ9~|27;!i_FSfsiFWAC&HM*XMG06tfZ9kO6A ztC|;d6Hx{VJ_w#KZJoGHI>J2+4?6X42oXJmj&$KrU64Pj)B&9*i4@DmGm65qAwQ7) z+$L027=vs#)I3Ge3xwe2!Vsg2$ZFRP8;m(PfX(Ot?MBvjM4bC_G0KTlSX}zxmfjB< z2Cgn9=WM0bZve_}%^;iKiv6`>UK5!nmBIsiPh1oi z!$z~^;>Jwsoqyvvd23q~n{8y)Jmt_{yvQIb+M3#19o8eTv}kquWhowF=Qj%?76~QX z_Fb0>mXIHsjPyYS^nm@GY%tt`;pJl+TfVm8c6!e!N=ZyVaa)w5R;sGqX4uzw)TGE( zaGk}uq7UhPUNe{ZNqE=bkKEbA#CmKpB~QArz{V>U)))@iac>w~+XU0!SvW?(eH@*& zp_%b>+OMG2G9k&=KzJj+-nV|WT*PHWcMX?UjZ#Uu)<@GgZ_S(hcLmj0i^OaK$ z-aqH~Gw1Pz+g$t`b@gq_u9qZPEPY+exLMtKX9Bq!$ zZ=VvmD%XIE@q%x=9-9HmnVW}v0(MfmQ2ph`K{0PnL(__U27r8WYOtQl0MS=nYdmLa z#9?nJ|5#o&LHw$0G~3iFD*+2I@5i>57sy0%t1!;f>c>-w$% zvEMCj)4Ghr0EX>9hgw0(N&Z7VH;U?WBo6#*Gm@d7Q{WpaOE&H7Ig?S%^3Zxi&eh%3 z5}~{#F-=XXTU=b4eM_P6N#DzWrZ5l*VI9Ks5Ju0Qk4g<`k~u_njrnOpV^rkVQu@x= z&9U03*aT7B?1>|7h~&OD;2-J{KZ#gKKUix6-lQH$d#{Z|AiAO=^Ts!Nzt9A%gySya zYEK{a2?KVw4Nsmrf)34XcSveWS4WMLw|1fvbeXrZl_W-NEOsi_8}wqI zN^cRemzU$Z4BfkvzZM-3znifNd7Y~a!Rab$LFJQbnCeSL!nFg?FSVq-jsdH}4jO4~2X|ZVg+7F0Ih42&57t!17P-4s3 z!uET{e}0f)yc#zDK(f+lR4SgN$?6knPxHz1;~>-a0$u;oAP0MSMh)$tg-SC6`g$WX zREzz6GJ8qh*M@e?Lf)BARO%^7Gv7Cd&s7h;474Bex=(-z=iAP@W!rx(%ad=!sMjnV zG-31rd72#o@DkVkw2wh!Gab)SE$5%j;)R;lNJgAsII~-vR1HlLq;1-TZ|TFj8GXe< z1mlpOqdt>wk=$Y;SL~<5et85hJZ#RG1d;EO?yu~&ed=nJYL4B16AoA&1Fk@((=Uzq zhSx5vtgm&L^EY-2kPYhb=)>Yvydrym<^&9WHNbMEqB08tLVxH6f1r5I9mFWB`8c=BFeVy zW)>*EM{1;e-mij2{~xPv3@0=J*2$_|z-rKBV#3t6Vy{8qZ)mdQ13x00i_ ztmd;Xn>nr$eO{mI!Lf1amvGBmzb$n}&kf0AXe}#oX&2{5Wm4@dERSQz_^A83`TK)@ zuvl!>-qJn}cdJ{O&+n^8bFYtCO|!cD8aVxHO z8)9{#6p-7zH4Q?-{l|eOSPu9&?@?~>)SKwJ9ITdo$*R| zi>f{2P0C7PRZ zfrx;)Ee5S?vU;dq)LkuhypbEiIGQj!Q#2;dS!Mg~?03L5Q{&Ay!(|D9hnYa*we(`{ ztM76vPfFQ;FHw7D}Vrc9QTs{-EKi`$a%R;E0~qnaRg-X3XV?4CVlO`YpimP_i*V;DT7@^j<;X* zlkTXJ6d_XQj0TL`Qn9~}=@Dih6QOe4C?ZBTIY5%if7sbq-hFR^FtOga`ySLbj}}32 z&YtYF>PKz|AGfjmK5hd5+vRX95+86r?MXgg$WbWIO>A{5?%s^`$*inasBeUqToPG_ z>KEn<6N%lY)Z3N=H!HmoOTq>nvzUus)#=ewJS|W|+Y!~2bbl64ihg)uWQyvSp19kQ z8a{Bk5T3Qv0R+`g2z7yo8GmJqk34qI`u!It`j*JictPv8}_|m!TBY!jd#-at%mt`a-^dv_NAjqAR-w@J_#EDx4s`Ary?VoQeo zFoTM;XVmItHXR>)TPHQ0I^}&uJ~l-a77via_sWx>b&mYU6;}FK=A^MZ%{(j$QYx~ zp+W}@Y$=2u&|q7K~`Uq|7qzvTwnc*ocL zdi=C8KJUZ?9V@M#XDhIHv8NwyKsta=VAZ8_!oi zP=6cz8_fD}JXud7XBzpg@c4uZO8xb%F1g|N#~_K<%-n(U4*%bx{LT9>&lh}`laY|B zkWcOnpBHq zBZO)TAC&qa$Geg`{> zC^IJ?BSzS-jWU7C|IHmQ44(d1blPwTH)-uXG*I5tVAIBFCdeW80>BtpZV-CDdFKFs zHDFJ_q3`D`qkyXj?44z#%87qtv+l;Rf*v+UrvFQI(7@1LmrY%miE7w{4b@@O!g!yo zJkc!Ei5BsbsBhcT!LPScL*C%m4C(I`bUQxMJ9$}IDyjt5dQqd+WwUPIBep$#J=b|t zf+}-;s?q7uLW82KGtHG1(p0Q6D5y;kbh;juc3xz{a z_P)eyr4jlmnk`XeV+89je#g(shAAfdbXUSS&=VhVDb%qjriQ+{1#Vvuob@Tau`9cf zJ_M24-9IAX5IPr_IZ@%RJ}?pOY!h?c^t1UBRZF!&z$G)4*}g(eQO@87fkOYJl>D+w zQo5|37V;&jOAlFYj>rVqATRmH1eT3rVH^Z%bN#j*f;fw`;<{f~zaO8mgFxM6gw;03}kdw^|L#LQvn9Abj=L1zVMZi>so zg7N%|74={Fs&d4xjg}^nJ!9iGpcgpcQAgKb#aE$XRc!Sv&w#cJQQJNWqcFQtTtHEe zR_=|8@Ts7^`OJl8tJa*c|2t}Ts$Oe9M|t7CnX4D)=iEQH9jER?9heHC*L_fbWTmNI zvi!gGKPNxk)NCTuBGkkV=Lk7*Vg!FR`@wO0^I91JoyrY-;JAHMExwUPnRs0yzNOGY z^{5+DO&K+S z{u&#IhlTaYYm?o>Wt8FOWVfA!;kwa-g?&{TRwJpQz~S>mN-5U zVykLzd+27jIkz8C@pe;eS62JKqR3M*|K}RTUslaxO7Ev6^%QH2vY_rd8yomNEmx0=&yq>A@zT0#7;!$8BTGkYg@9%I9-z>b!tG^jx$y`v<;4b5 zwc&l=LSN7>SS2UcSv{d@+DGwj&4^}{;;w&^Yminxx?>>l8TVi8O@T7f;(NU|Lxvvz z$7gQ1oR10AX5YpB;aROd)oaVGOeH08`L3ie)ChjKk7G(dTl>*xXzl%?n|Qm|HlpX2 zl8}ExRkL+i3e!W?ClBkCUdGEAf4^F*f420SgZc!QmEA~-tw#bN>F!`j$yu$Cxq@0j z*6bg`%lVn?2^YX>XYbp}_4{}I4lDy*-apb+SFc|2d3LUMC+@J8T*)y1=+L-7$n1nW zeP@!h=l4-S5|6`D5y9tfoTZ&bu%GzrC<2p9Qob$Rf+3L^%3;z2{>jh+8#wl1|3-Lr zJ<}q4wDK8KrbYe~`We&Z{hN1Yetu}cTE)Cphv8&6pC78Vn#CDjjtcxSihbVovgsT{ z#)P~jY|eIgnpJx^)1oqL06th**%0Ly;(W#^`AZD0zQ=N>ApzhOAU-jl%p#ik!b&zsR~YDx=+8Iv5H^*sK!jyJ z8CxD36PSE$OmPWecwOVtz3Ii4s)WoKR&iG<&BXct^f$AmsZe)bFwP`bi?E3h*L?SI z`vIB6bqwHFVjyA^8*Xngbu*x0yy-vkMM7*}ZMI*z|6OJ}FH;S+_5mIEe9fm)W?DA$ zg`Gvs+|63>#*%K*SW}BK-Wnt)-0!If{yfR>Lud`&qd6c{G%Kn&qp9>aRwJ#GVcd>2Sue1o75Blt# zO1;wfKSig5V*AHzN{=42ezdYpkW8mS! z#UhB-VjPw23~%@>|Drke%>59v6-o;76So>Jo10}44Pf*KD06?aWkDAt0@hc!vcb6% zivYOs`?p=U2eqcH?wH1UT&^Uv(T8w^kxh;M3xdY5v2 zj?NzoDEq|0;^$w>>$z#1_bFg^1nIS}OGfiY^{jpI$J3c6B~O3uaj*>Ee382yO1G_F z=u=3Z^{yly-`vL>)~X;&h>Gp~9q<)Cy|O86n&&mT5tRW~%rK4?M2a%sNKPCGl~S7u=6|q%HEzP2@-k<+|x7%;KZqM8G*md2X*W>woUXSZ~Ub`NT$2}h*OqGno%H`cF38BOV z#lT%Zkm$s3(Imnzvt&W8i-AvVk1PXw4PvXbR5_3MMVN=w;-wC-2oBbgVvNzpn-iBF zbn_>%y{$Tw+A1i1aIjtR_DePAM`4Dl*K}%o62ppBduXc5+86(~LWoseX8O+G%3oz) zD+wk6$UEosp-fCE4<9M4x-3A3tH_V8d;X}V=XgyHtNSzKjds)0ulJ?bRF{G#W=++o z={4dPbOhg))N}ZV1xzmL`AzGR;P*9& zv&A1hNNDv-Pb^g=tXN`G&vt_YVvF+dBMrkX_P0Y~Nuc4u$6` zchMroEg7;eZPYeFD3NW zJYkH@HcJ%PePac})wG2nr_Vv~=G1%(y@x_?=$! zdtTNNG`C{chbZ#N#CKOw;y!G&S;E9uhZ*yiHae#p#?lfwcI1(ylpvp)faGvbH~v1` zD-I;(@^l^P6NW?Y^s`NGbU%Py-m>$^yvQYqOip%Og8>}w7C8>5QRmPjfj@Og7UBz>LvUr%)p+z3o`CC&QN+y)S4zyYmlA03JM4WYbHAz$I}V699VNl z`=VLn1M@cYfQ55g`(W0N-HQRPh4@d&MhZ^`pBO}vDPkql-eN&W*T~0Qx-i{mzh$ky z?Z9%!SuLB|3X-8+c)*TI6OD_EZ&gucab}PC|4^NHtK8wl2O1z;`#a1s z_#OLqi#HWW(vRL1eS;JLG~dbT+;WgHROeU<8CURqXCok=uN<_c;Cs7R7H09tjg-d zFD^6Q^MGq(@TH_biL0v56DL%ETJSV$S10#W*t=b*++5GfmXfzsv;c*^w|IY1up`6& zXf1o}#NLR?_c6wJB=s>V3`!e;zf6>Pak=-IrhkFW3Xdy)^8|9;HJIvTeQ*Y8#Fky_ z_8JJ8Gw`bG&Uy)+c}448K-}#Gpk9Bv+27e(K>n!zI5#UtRXW8lQcNdB15 zZE)g}2t)ii5Q+Pse{BUjDEdV(gu|`aTISoN)sh=>b$d15qO5L%O=G4};RN!>x(-Uy zU#J_6FOZ}{pwt|;J=Dc5DPMp6cF@7Lb}9lp!k;sC2i5pcI8y-~Zo;up`3{a9+8$cy zRmL1bmGf#ZE2`jF=&CtT7&%}wK$5pE$lvCd3H2IE`>EL>p{m65IqMq!z04mi3(XlE*4!FmA^ zgsCb<(WY4bJ@QKD0APL&8>73hF+}yxGj?~YKgV1$dQGV97uYOte#4vBVm}F&h_wp= z^9K23aOeFVt6XFE;X=;wVP;@8C7!~q@}b;c{>w{rcbjvUR6Wb2vB*X^)b3ehlu{eD zwi(gVD>Rgnw}+<3EZ58nfGnad4_w0>f=|Mih?~oB1=I*6_}RIbX^x9FjY*_x7qdQ# zsxH{bRr625QI}>*i~0Qye506reNokDQPs7P)FzGdkeDmW6pPLA2c+?1XVOKN&QI#c zv^DNiF<{fNT;DMRn=CR8eR?K-W7=?r65f)1D~A$(xmHlOZgzCd2$uj5yz=;zEjR;J zo?na81dJdqx{*^uC;m<^3h^}SdCY?GuixCT;Re`hOMG}U!M$$IP*BHIBbo0d3z};v z#Nb-gB)yIuJ}JAIiF>n>fa9i6kkr(*6|ziw=Z@tTnKeIRfHjDt)xbL5$ldpHCB}R` z#WhGk*BxC85D^RXP81Y$w4==3uL<)@QK4l^}~pOCkq>6xt3T2&beRkp+U6EK`_UdSQnWjgB3_f zlEPw$?W9F+kUrFPG_-m5>twas**W#kQ~lrRye=V=1ls4B?^|6=8P3Mix3WA zj!%Pw@UL$w3cCR0A}{d$21elP#4cJy{mOL6LNgTf(gFKo)h1p2W~XmfLii(&H~ zZ$2_}@}q9goW2|UQEd%Bm1|>jdzBJC01aOWSSS>p!L6jyC!og5S$mIELqpEizQ22DO2o1B0u zAy-3<{}j?TeYy90d>4c|31IwoXB5rjpqNnYz+;JemVqowtc7vkd!Fi>tZy>L@VPHG zn6zunKcF>Z4%@*v^06&~pnQNzkiM@vx8*g1oLLJ=h3GQBERu6hm>Wr--kd(Q|28)^ zwyQ!TpTx)=_lzLKnzb?ZU&xIhY;z7V@(}YjIA1+vcZonze)zpz?I5P2RNB2NP0Twu z+7Tg&CiS_D&r!Q07rC{xxf}eN#BRFH>Q^a)n0MC;gb%E7jW{RK?Io98}+3HHy*j zh3?N=|IplnkbQZ=;j*XHVvm2cM~%^zOMb3s^yN8kGeu5xo0#t7ouQ?vy!wd@e&NzN?Ge`fcbV>kWCP=(HN#kd~&Z|>*CF^$&#-4m! z^`tTAP`eBHL?z_S?PT*u)h`Rz6Ji?&6(Iptn)NHE_uTdI32+~w3D&O35WRja>Q16a{2i8J}S4Dtu# ziya-*PV}rQ8CW@ezZ&7l)F1Y*ik*k=dIm{0`CJ~ejRw@JNR%FD`;E`-)%p(9{-UTh z7UW|#aKq>!;%cBEFhNV>*efvRTg7)coQAr-`i{HkH9 zN&0%TsFM=E+tSoVgN_|I8N91>PULis*fDBjuz#y|@VTdQKeaTjZl}$QO)@es5>0nt zbfLC0M70-9jIFzp=aQQl9zH!vskg{4eC-n0Glg?D_S@5NMmAoRq_#IN?AxvF98V%~;% z&+)T!#Lhr)^?5UwqQCk$1ZB0$C>R5dJ-O-g?7(1R|Myzm@3(wx&cUh_>iL_>kuP^M z>RZc)>w&r&bZnjS@oNmHvxm#~?C@Ia&GnIre%0R8s=XO_@#SK>{a;C@M=t!Wx_ZUY z-}wuNb4!NbzR;0+r#z@Ms>;yX^_zUDz1Qdm#3(uDlvOo-2HdrcXu7x3rL}Xw&aO@E zy=U0gKHk`NX&dlxiHq6+wDF-^O4BM#!qybEC%en42iT!O-oXj>F^8L;R=ZUf6K!+ZDD@VPsJ_1x0{=ptyG=c zT7=wcITds}Qp+J=it-|_9soZqmTp^-^*W?#wv(ZdL6&BRitYkLKFr$d6P8 zt={ATwfVI^_SJl$#&vLB-li+d!++dqvJ5mBUg|Rt!IzQ(QdjwUD7he|Bi=m zyaZwB)`?X=xF+>VV}n&q`mI+3rjLyd-&exhqVAB8l@husH+`vJwB*QTL789tuc&xy zwB_q=@hlteKG1G&LM`N2bO()|B-jdO?}KyKf}@IVi!0$2+1)?VG?v2x4H=y>x61=gbaz(qyUsqUs)D=jYy9pa zmQbN@*w(2%P#p2w--82&sGfxzjg8^w%hFXO<;sXgRz4d0oDfalYILfzi-|_Ny>srd z*%BcRu{0@WfOA} z(k|Q^E#DxKzuOv4KCZUX2|gGk>@L2X)Gqtpvs%nHIVQI`DE@XG@Fo${<@DV}S-+y- zuvJxprf+$+^*!y$vMW+uw;~T`(FxmODPjFKQsX}I1R=Dk_2?%9-@mWvyM~Ab1O?p# z5Z~zDkl*v5uEL2t%E~PFk1-#Wu%C#le!X6a2r8C&e3){lC0@McTfF(*VXERc1%qj_ za6n@d=H_&weM!QssQLQFqPiZRxgJ?9+?&a7E%kh{PR;a4mxcWel^WN4>a0u9&aC#w&q%E<4zbDf z&#zgsuVC#N__SntWf_C}n+k(>$cC%f&|8VNzig`Dk1bRLLKHPy)5WRdkSJTYYaNSIl zv%d#ve@{{gS5(ggQ1OMV&nJ|mp4JHz6M_`R%a#82EM3iWrQZ2Yufw{*;{wvH8E~&v zSQaE$t|g?FH$80jW67@#zA)Mv=Fvy^@+JOgHXYB)n5itkUCV#GXejE5pvz5$Tg$kG zx87Vc2^hBfOTyT)2FQkzxrJHl3UUNJgz2vd!;>h*DUwUA zMb8z=34vcJst##h@=oFA-ZJ$$QsX)^YN+YTlz)GUbYp|ywX0b_wVbSHvNlEF9+mH) z&*;W`rxU~O;PnY?!wFa3b|)13(dk0V+l`f%L+}-+Y?L0>tl3hm1*GHp9q$BZkIYn|11WU**Mqd`Yv=+m zeB$sKpAYZ3kuCK1pIK8ky~x54gzLT}K7|UdEI13zv3ZLq{ka zfwPzI(O9K&M%c+F_?OG*n0#-n)j7rByk+=@OwtcE1Kh!`BbHTs!V^a89y>NEs_a!f zRHlsOmq52&m6KAY@l>?yg#kq!qYK8uX=i3UjZ|3O9JfxO`05*32k}C; zq+4m@N}7@pkv?!s}o|rEtuN(U8L)rZ=CG;<{Lu zPoi_KQ3=m)(U(uSrQD`2&3s#hJ$;(Getd0(y%(){-3t@lR9UTFTwu_AvQJlzJ&|?? z4q+ex4*IRE$2xTEO($LD2f(`o>d_YZn^$ldU3y4?Wnn=sI_BLZ>rmf$^!d8^)035_ z7@<%4=ud?;O2W$UM6B`rjZV0RW_*kZwX+T3V*U^!V@pz*reeBC*@C&Nrt`f-ALPs> z&*k>s(DVyqgg+06q7WZech0+=)#%qs!J3TrEO%h3R&gALUX=U`l9O7NN4x1L2)UpQ zD1Pq}@6ChlyXLf@BVvnPfFFkd5$SInp_ze0oix70Id;g7s`;5@`u!Fcn?C}>Z10+n zaG=FPsFs;A+UrEI++$MFL6$@cDJ!Dtu7YlF<@{?TkxeLDZM92ZA0YiO^})J8t;P-a zI7;0xa;;;ZDx+)nv7A1AB5B^D7Hw25$gT)BZ5gNNCxY>5$Itkv*1*%hmBXmFoZ`=~ zFP)x-7fsQ(?C!G=Q-Hp#!P%@VZS>rgiUN{7ohqUy3^U1ac#dMl^WrRH5&!%eyC>YG z#??oKRG{gmlT7b@S82UDTbkaM;=EoNs_&+Ahwj>0i7iute&8_HdVJ5svJNBx3}Aa8 z(02O05PWcGf8|!*hRLU4QdTt;BeIg*ckm$klD`iovikmz+6}6?0!Zn&A}i@EI%mSv z_oU8JrREdU{W|o(`^6QX?i0@*39j*Yp|HSqjF(sru}mu}J-pU2{dj@5u5B_8S>Ypo zEj@1~ygo=$ajjHRhq+|JYkr3hz1#GE2%MjQSCrG|-?RLl0c;YBD36|zoDZ|E>nb|j z_|AQ&rDT&_thv}@uzlGzq78zE9_nl8a37MDWwk^qKw}hulTh&>6pbL^Gxg~}^ z&w5xGn~?)gS*KL}UB*I(f6P@@w?x#$tkc6Zzg&F-?VnRS()0nwDHr`Q$tC988D3wM z^asAKkh*H1N*c?rQhJgTVSjvfGJ7yyO)N~|1{X+5Q~o~xezfwK3QHn(GvsCTeaNpo z`b?yY+zt7Z64zohj(2WuEEID8yz7ak&>!DOr5GaiTAoxTlOIJ+%}q=cZEzOMK1p#!`N)+zzWcM>20(7csr#_t%j@D8QD(R7mP! z2d}C4(yLErBs4pyorg{FA4Vvh(otaE+hrH(DSw6cj`7me^$?@>u;I_9U~);|8ay@#o@ZFe1Pr{klJe`TEx z3U~3$4X@H~mT^J|cqP5@uU#ngc&+swP8ymkLPpn;AS=~crSVHukJX$=b ztLV8-V+Xcv;_PfL-;^)}d`dWN+8k%|>+wyhY20CC!_z;7LFNv>^4u2jHdlTb*3tDW zKyDS$2i^}J8y;$8B3HM|>jEB>AQa_tFaBCtY+YoVoj+NnMl@EPX_iXK(-pt9}v#@Mpe(MTO1T+jkPU?@-^GVV{uMx~s>=LdW#eJ?mfGUv1Yo zIvIM~awxs|UiN6zyGKSWiA?jvyuep)j#XunccU?pQLKZ#S5FnhPyBK;KCYFV-j#8F z-#+E4N^(lpF53admUaK2JJ#UNM=(s35&afpTt>swFAyxO-)ZT0Cen5&hBDgixENIs zgIjBtZqjI%ux^xWGV6S3`c%hj&=dFY zDbIdjkH>-)cC9ju_Zq^7j@P8e*xaygm}O*auF7YZ7!d{{N6ll)X8f+Nyph{E(B8{b zsNZ368Fu_i_y&p8C+Efn=K1OmKO%H48+0yjyAzFDCDm62a?IFadgMjQR}a8nwR zvF(t?nR~P8)ST1)Gp~xp)98L?t}ZC;zY59cAVZ##w4kn(4GB=nSm#rnOtSjzYRMS6 zP93(RTc?dTOx7210+VduaehZJ&_EGeR;wx$2g9}QXzOJ58x?=cV8lE|Wprv-fA4Wv ztcPOLAkTkXJyN`W5;MSi6il^R`-_;rM$HpwS0`0WY_|@$6i^-WV6xP3U)+@uZYCiF z*>7xk5e}1*Iv>;Gy!e}zerK^X03AAStl%10Esg5hKpL%Q+WgpjC8s$OU^*V^hu0n9 zYL0BY?9>F`pf%cR%Y2f;U04E>zc)-cK zOs6e3NS1-trL2U6`5bfaetBQ|S$q4Ze@)pxA6GQBFD~yuJVFKpnz6}`=U$!@uI&-F zM<3A8`U~0_GYKikeJRZu8e^{CE!=f&LU-YA3ay*YuPR zaQRG*0vHnyy(M#obTB~+QO!9)b&;2L4)Vor_CT5Y;Uj@BEx&#mKEqPb1k1&9zBHXX zg>N%wrdHq+5t5q-H_l3(;Z7-GwImZooz=69fa`R{LoBl*s=7RrC2sGdgGg%m1^6ZDFN(q zT}u~{a5abBH>=ujhx1fOzOyNXw-mTzKY5|B*TPUsxe-rT=lBJjuK|nYu96X>6d*7hETbH_L^XGZS8I&;X z1(Z{IFlIZ`kRs~GgUkr#VcIZ!gn#4&=;`JNKN80;SP0wtrX_&xei@ra{@rq=)a006 z|AvAzGa}CGwo6hBS>HFin+-(c%!}AW`00?Qu&JXjo;c%({KxVRaa27iZSce3eyBiZ zF6^%$L|9J};@)8HmmE~t8(qA8%g#z+Q{mjl>8JdfQ-ZAU7nm=*W`CjycSRW^B_n<^ z0sv8;mb?c~V}5>l8x*iki%s z!AvCuf{U10n~R2$~7pabSk6+Ks;t+%V6-VsO=y1vqe+M+yddz(UmlaoHn~G{5 zV4I!f;8Rge_Ov@-qCvr?cwM%>F9Sy$$G=1bj}+M4hVFQIFoK6Wclyg}bvX6XW|Io- zr@C;93RAuxexzivavxZW@(7-gCe;I@9a+bL(#YPc=QiY&ZUzcEy1C-(^~jIYQETUW zE8fJiQ`<|M{=CW@rES`WmO>inN=5i?Lu z)eX1!(RQl4Kg-;oCYP?+5?;*6Z6~PQ_ipsHB|YAL(|&{xNg~5iuf2PT}063 z$KA3gZHSX8$$`2Q^W-9qzYOk9J>lo*vM~gtSkWBis@5(jF1>{{K_^cRv5dd9qYNdO zwZk@{RAe}N?e!2<5nk!4HSfNem?rGWlsaU9Dg{oL_E_kEZjz9ET_I^M$%e>0vY5MJ zj-zDFyhUPz$;^n}F3!bbfyOej>xpm|0tC)k!M$UyaWZt6PG4DjJ?_J7MvgjSNi)(u zAcdLV27VnfsPnW?hKz7=hXtpUf@6M%is&XOiqwtSPs~QpyCF^vx_1zvlnL(WHbQ-s zL@ibt#bcQ^f>ES<>P<_LD9%D7jG+*bib`^|PS_dFEE5tBcirQ6Om3iJ)E6+x-%Iu# zZYUso=6+et;~M_PRj=YV<)699#vr$m$o9w!Er^{#n3tDKeHx_NOGTYJxeY#40Tl0o zu0LYgB0M0V&G7AE!+VUVp=u>M9F3ls$jl=STszYE`NpS{+ZJMaW4_jM@4CHZNpRu- zqb-H27Y~sQO1`33jOb4yLa`z{SiNU#Dk!TYI#7WDm{3R+zEj+P>8R%=5SX&)HNVcvky& zQ_P3It!hrnT^?Ff0{#fj1Wi2Qo9a;AB~of-vHB!nk~3D(nc4;X%lwp6l*0d^#NvOL zIQ(J>V216sH8s@J#Ikx2BL$U`RNpJ0!{|y=j;`xk#U4Pq?-y_5r}YQo29GP00iCf! zh4^N|RFwbvr16k1XZuIwxpf!gEm(L0brq=dH-!C_UaHgQoDTX8h#gegxVoTG$C2_w zLu-f;rN}2>18ZtiOx%9)euZ4Nv@AjdaZ8g-NtRT4s;^Nx5pM&zhI0KGSWaP){&(;T{IYTX1F=gR}lvn zg&~N#wRs2FW@sj{0pY7Ad>pOJ3pad|#&JcAG_RKmsd!v zc(FixjUOI@_hY89t^~4oepwBnk!orDTaA3|lZN8gOuJ*NyzpL*%jkw#-&YRrPV@NW zQ>Rj3b+3ibzl@xP(8-`o4(2UoZajj3!XqMd0-1MxhcD!T0eH{^r@Se9ldNkE#G^@3 zS|OkW|ZF1oC)OgM^E%3Ym>N1%p*oNL6CtjjVg_|j|m;yVYz74%F&Um?gJl{8~ zX2FP3cv=w8GnHZEkq>u*K!|Da&ql=y3uou2I+!&MTbQ(*DEdS$yMZ&r1VVqo{~TCc zsMJ(MaxMjzj*KI&uD%uCDP9_R$Bp5*LQpNTK5G=BxF1%t6JA0$^$FVW<$Q+A$GGNuA^s0B;`XBPHEcTg{`?@{>F zMC0*PneB)XbAmNFj&wt4YJ->Sdx-3@5Wf3U#5VT;}UT ztM*Ii+0C~mK{JEAmgYW^IC*0qcq-eoI3} z@aH(8x-5J#>c?hz3|gat*TH$tJ?vJrQqd0ILgxJ$`!KmSX1lpZ*iDlEYPI{$gr$`E*I3rln)T!`jopX8D{VS2~j+SoB+n0mtwf#KCpE zhTs`#*W$DkPRP0&zgCwDFs2TlJSycIQwu!;GQ?H*z6hsIj0G%y)a|yaD`59JJce0M zUSkJM?!oACkN7qo01U)QAq;MF^hV(2<@`AId+3r9Rf=p`C=*ZT9w*`IYcH(IwrN?f zIERjSTj}H{!au|7JH^LG(-=i?JObwrxyuXqsY3PT*Okrw1Ks*E!mf)W@GhZsvitylp|iK?Lc%`r{t{J@K77{EJ-O#7b3dcmepBx-< zwb+<8b1po1%YNa?*!)%r9l@2x1DGLUUX`7{bxosfL`xhlzgy%^GqjV5@DV9a1L}gZ zWai;xV9+}`+Vz}{EPgSle?#ef{A2(IwRn+wb$U`|M_K_Knj`r;7m@2Vzciz6KaXoJQJ7RIZp*BA9yV$(?ZdzJY0 zO##6#$V~w$bYQT9l18utHYK!cSB?(nz6+3c0MuI{K;8$^_7qUVl`;{Wxj88Z42G%b zw(+b0*LX%~IdZjU?P5*{O_s!}*QgT(PkBF3tBe(HR!v)O_8=r~Ez0CdT;lM816set)awtdFdgC#Q zmrBo>iCC(t6>;{iy|HG}kj>&0{&;{bxHO);HeanK2?`lWhDc2XT0Ja$wmnx*J1F+nL&_F!Eor(M(IaioHb4HEi@&{Id9<$$TUkSVsx{(@<$j<^6^( z@A(*vi_LM^^?u%wp*LSSy4?q=Hx3Fiw4O=r84*|7M4nasc<8sd>~HPm1j9FIOA`Ms z9P{yz(mD7t*8lE3z|9?^JWck6R}a<%01?qb0e#b(s$Q?TS{3F{in3v5r9J;Ja^eQ}WjU^ss`+&&+AD>cO4 z->j-JIVIBU$Y@w>e$t1uv(%4csl@udlnL!emD8X`*PREm6Nz>nXBzYoG4fdQ9<)5R z)m+bQ>*Z-_n=3|NtImjIuS5|>Paf@|F(q^LhQqOjZbaa55x`3im}t<7+@&X}em4Ka zTdsrcExg&`-t%3*eghe2-JY{=?T)%@GDo|5b9h(ayCd*hpOi6%-jVN!rDy&;s%-Vc zjLp;yiB;LWOxs%_KmVS%ou$5e@CuV~G*-3gnxE_LDC;?OIf=Qv(yJO(rK(NpVnPGU zlW)~{D(NfP=^a)fu|wCk7fW`!(ae7xSS)6g6kGgk$2lM;dhZ$wtV5-=Q>r2u!T{Zq;B-+*ft>>_n0V}s8*dNZySaRwl4nb~o#6`(|NARRc1xD&`a>9{pr9#K zPTzc8=ks8^TRF{Q*yg+S0T-Giw9FDIXIR+!w&}E~MSHcbO&1#}77};exkJl6@W)~C z6Rkhb70&&VW&ZxCVTg>?mB)uI?sG0)+%D0-UolHJ>F+*vf2m(AtVxkZ2Apt}UA&+I zViqMDwmL{_tVILE%EBU`0A%cb4TS9YG2e^n6Od@oK#H%zf$?Ls%SdwdVc2_zmPAVv zq)O!u*n6t7HCwuoNeuoOCO4ATemjPzV>r>I83SB>D9{-Q550qWdBDYE`QXQ|O~@xg z|0-XdHP`q*l+G8muc)&=jl9`wXg7Qa1|JFF&Q3Q5tlSzuv#Ni~boubG0W59!^{Ogb z?S<(b_KT_1M%2o1qdU7@Ul7ac)$7D`>vtVVme6Y|1V| zUHp4a@Q%t;3VPw}DZ5P@*M?Q8e_zDzzcsKNdZI5|B4R&0|KIF~fgyo6x=s9tPK&}P zTzOaIpo`%>I_U?kvwx-W0moJ|F-a!K?G_gfv%60Fq_*k{O5waO*r2UqOBy+xz%I1+ezx75-9lcA50sg#DzV{aL=d zeX-X|X-2*JtgKSETT4`7f$lWKS~XZ=?4AGY;wc9T_9Xk( zTdgwXqJF!pDtiD3iwn={le4!z9Lz3_e*<@(F1dF8XsN`_hhMO}?;4r@a92*WpQGgM zOZUvlncojJE8IRkdHsuWuu}HNw-1snwL8_c&}Ee>`bxX(FOIol!YjKU9;V^&s;k;Ler!Tg)&ppz;N{PL1f~|QbrR2yQt~* z7|A@7T8qx0+fDy#bhm5;Z#%e6OiV)Tl4yKe#rC6~oD&mE&icRMF=GGcqa69=*}qmi z@B4T_A9_FZ@zQ}l@ct)OQJQETx?fC8*6sh^;QozG7S;G4Sl@qQ|4A+TZ!GZgKd=G+ z#Qu|!^WRuAtN+A4{V$#W$qxB%?9$c$#0LHs_Mf3d|Hg{N{sa48?fvIu;NRHLAOFDq kM|=M_8~isGO!yD1$RclE+p+Us+a*NbQIXv$68|OrKj$)sE&u=k literal 0 HcmV?d00001 diff --git a/board/v1/handgelenk-cache.lib b/board/v1/handgelenk-cache.lib new file mode 100644 index 0000000..b9a695f --- /dev/null +++ b/board/v1/handgelenk-cache.lib @@ -0,0 +1,514 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# +3V3 +# +DEF +3V3 #PWR 0 0 Y Y 1 F P +F0 "#PWR" 0 -150 50 H I C CNN +F1 "+3V3" 0 140 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +ALIAS +3.3V +DRAW +P 2 0 1 0 -30 50 0 100 N +P 2 0 1 0 0 0 0 100 N +P 2 0 1 0 0 100 30 50 N +X +3V3 1 0 0 0 U 50 50 1 1 W N +ENDDRAW +ENDDEF +# +# +5V +# +DEF +5V #PWR 0 0 Y Y 1 F P +F0 "#PWR" 0 -150 50 H I C CNN +F1 "+5V" 0 140 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +P 2 0 1 0 -30 50 0 100 N +P 2 0 1 0 0 0 0 100 N +P 2 0 1 0 0 100 30 50 N +X +5V 1 0 0 0 U 50 50 1 1 W N +ENDDRAW +ENDDEF +# +# +BATT +# +DEF +BATT #PWR 0 0 Y Y 1 F P +F0 "#PWR" 0 -150 50 H I C CNN +F1 "+BATT" 0 140 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +P 2 0 1 0 -30 50 0 100 N +P 2 0 1 0 0 0 0 100 N +P 2 0 1 0 0 100 30 50 N +X +BATT 1 0 0 0 U 50 50 1 1 W N +ENDDRAW +ENDDEF +# +# BC850 +# +DEF BC850 Q 0 0 Y Y 1 F N +F0 "Q" 200 75 50 H V L CNN +F1 "BC850" 200 0 50 H V L CNN +F2 "SOT-23" 200 -75 50 H V L CIN +F3 "" 0 0 50 H V L CNN +ALIAS BC849 +$FPLIST + SOT-23* +$ENDFPLIST +DRAW +C 50 0 111 0 1 10 N +P 2 0 1 0 0 0 25 0 N +P 2 0 1 0 100 100 25 25 N +P 3 0 1 0 25 -25 100 -100 100 -100 N +P 3 0 1 20 25 75 25 -75 25 -75 N +P 5 0 1 0 50 -70 70 -50 90 -90 50 -70 50 -70 F +X B 1 -200 0 200 R 50 50 1 1 I +X E 2 100 -200 100 U 50 50 1 1 P +X C 3 100 200 100 D 50 50 1 1 P +ENDDRAW +ENDDEF +# +# CONN_01X02 +# +DEF CONN_01X02 P 0 40 Y N 1 F N +F0 "P" 0 150 50 H V C CNN +F1 "CONN_01X02" 100 0 50 V V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +$FPLIST + Pin_Header_Straight_1X02 + Pin_Header_Angled_1X02 + Socket_Strip_Straight_1X02 + Socket_Strip_Angled_1X02 +$ENDFPLIST +DRAW +S -50 -45 10 -55 0 1 0 N +S -50 55 10 45 0 1 0 N +S -50 100 50 -100 0 1 0 N +X P1 1 -200 50 150 R 50 50 1 1 P +X P2 2 -200 -50 150 R 50 50 1 1 P +ENDDRAW +ENDDEF +# +# CRYSTAL_SMD +# +DEF CRYSTAL_SMD X 0 40 Y N 1 F N +F0 "X" 0 90 50 H V C CNN +F1 "CRYSTAL_SMD" 30 -110 50 H V L CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +P 2 0 1 0 -70 -70 70 -70 N +P 2 0 1 16 -70 50 -70 -50 N +P 2 0 1 16 70 50 70 -50 N +P 5 0 1 12 -40 40 40 40 40 -40 -40 -40 -40 40 f +X 1 1 -200 0 130 R 25 20 1 1 P +X 2 2 200 0 130 L 25 20 1 1 P +X case 3 0 -100 30 U 25 20 1 1 P +ENDDRAW +ENDDEF +# +# C_Small +# +DEF C_Small C 0 10 N N 1 F N +F0 "C" 10 70 50 H V L CNN +F1 "C_Small" 10 -80 50 H V L CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +$FPLIST + C? + C_????_* + C_???? + SMD*_c + Capacitor* +$ENDFPLIST +DRAW +P 2 0 1 13 -60 -20 60 -20 N +P 2 0 1 12 -60 20 60 20 N +X ~ 1 0 100 75 D 40 40 1 1 P +X ~ 2 0 -100 80 U 40 40 1 1 P +ENDDRAW +ENDDEF +# +# D +# +DEF D D 0 40 N N 1 F N +F0 "D" 0 100 50 H V C CNN +F1 "D" 0 -100 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +$FPLIST + Diode_* + D-Pak_TO252AA + *SingleDiode + *_Diode_* + *SingleDiode* +$ENDFPLIST +DRAW +P 2 0 1 6 -50 50 -50 -50 N +P 3 0 1 0 50 50 -50 0 50 -50 F +X K 1 -150 0 100 R 50 50 1 1 P +X A 2 150 0 100 L 50 50 1 1 P +ENDDRAW +ENDDEF +# +# ER-OLED-SSD1306 +# +DEF ER-OLED-SSD1306 DS 0 40 Y Y 1 F N +F0 "DS" 200 -1650 60 H V C CNN +F1 "ER-OLED-SSD1306" 100 1600 60 H V C CNN +F2 "" -100 800 60 H V C CNN +F3 "" -100 800 60 H V C CNN +DRAW +S -100 1500 300 -1600 0 1 0 f +X GND 1 -300 1400 200 R 50 50 1 1 W +X C2P 2 -300 1300 200 R 50 50 1 1 P +X C2N 3 -300 1200 200 R 50 50 1 1 P +X C1P 4 -300 1100 200 R 50 50 1 1 P +X C1N 5 -300 1000 200 R 50 50 1 1 P +X VBAT 6 -300 900 200 R 50 50 1 1 W +X ~ 7 -300 800 200 R 50 50 1 1 N +X VSS 8 -300 700 200 R 50 50 1 1 W +X VDD 9 -300 600 200 R 50 50 1 1 W +X BS0 10 -300 500 200 R 50 50 1 1 I +X D2 20 -300 -500 200 R 50 50 1 1 I +X GND 30 -300 -1500 200 R 50 50 1 1 W +X BS1 11 -300 400 200 R 50 50 1 1 I +X D3 21 -300 -600 200 R 50 50 1 1 I +X BS2 12 -300 300 200 R 50 50 1 1 I +X D4 22 -300 -700 200 R 50 50 1 1 I +X ~CS 13 -300 200 200 R 50 50 1 1 I +X D5 23 -300 -800 200 R 50 50 1 1 I +X ~RES 14 -300 100 200 R 50 50 1 1 I +X D6 24 -300 -900 200 R 50 50 1 1 I +X D/~C 15 -300 0 200 R 50 50 1 1 I +X D7 25 -300 -1000 200 R 50 50 1 1 I +X R/~W 16 -300 -100 200 R 50 50 1 1 I +X IREF 26 -300 -1100 200 R 50 50 1 1 I +X E/~RD 17 -300 -200 200 R 50 50 1 1 I +X VCOMH 27 -300 -1200 200 R 50 50 1 1 O +X D0 18 -300 -300 200 R 50 50 1 1 B +X VCC 28 -300 -1300 200 R 50 50 1 1 W +X D1 19 -300 -400 200 R 50 50 1 1 I +X VLSS 29 -300 -1400 200 R 50 50 1 1 W +ENDDRAW +ENDDEF +# +# ESP8266EX +# +DEF ESP8266EX U 0 40 Y Y 1 F N +F0 "U" -500 950 60 H V C CNN +F1 "ESP8266EX" 400 -1000 60 H V C CNN +F2 "" -800 300 60 H V C CNN +F3 "" -800 300 60 H V C CNN +DRAW +S -550 900 550 -900 1 1 0 f +X VDDA 1 -400 1200 300 D 50 50 1 1 W +X LNA 2 -850 50 300 R 50 50 1 1 B +X VDD3P3 3 -150 1200 300 D 50 50 1 1 W +X VDD3P3 4 -50 1200 300 D 50 50 1 1 W +X VDD_RTC 5 -850 550 300 R 50 50 1 1 w +X TOUT 6 850 550 300 L 50 50 1 1 I +X CHIP_EN 7 -850 400 300 R 50 50 1 1 I +X XPD_DCDC 8 -850 -350 300 R 50 50 1 1 B +X MTMS/GPIO14 9 850 -150 300 L 50 50 1 1 B +X MTDI/GPIO12 10 850 50 300 L 50 50 1 1 B +X SD_CMD 20 850 -600 300 L 50 50 1 1 B +X VDDA 30 -300 1200 300 D 50 50 1 1 W +X VDDPST 11 100 1200 300 D 50 50 1 1 W +X SD_CLK 21 850 -500 300 L 50 50 1 1 B +X RES12K 31 -50 -1200 300 U 50 50 1 1 I +X MTCK/GPIO13 12 850 -50 300 L 50 50 1 1 B +X SD_DATA_0 22 850 -400 300 L 50 50 1 1 B +X EXT_RSTB 32 -850 -450 300 R 50 50 1 1 I +X MTDO/GPIO15 13 -850 300 300 R 50 50 1 1 B +X SD_DATA_1 23 850 -300 300 L 50 50 1 1 B +X GND 33 50 -1200 300 U 50 50 1 1 W +X GPIO2 14 850 400 300 L 50 50 1 1 B +X GPIO5 24 850 200 300 L 50 50 1 1 I +X GPIO0 15 -850 200 300 R 50 50 1 1 B +X U0RXD 25 -850 -600 300 R 50 50 1 1 B +X GPIO4/VD 16 850 300 300 L 50 50 1 1 B +X U0TXD 26 -850 -700 300 R 50 50 1 1 B +X VDDPST 17 200 1200 300 D 50 50 1 1 W +X XTAL_OUT 27 -850 -200 300 R 50 50 1 1 B +X SD_DATA_2 18 850 -800 300 L 50 50 1 1 B +X XTAL_IN 28 -850 -100 300 R 50 50 1 1 B +X SD_DATA_3 19 850 -700 300 L 50 50 1 1 B +X VDDD 29 350 1200 300 D 50 50 1 1 W +ENDDRAW +ENDDEF +# +# FILTER +# +DEF FILTER FB 0 40 Y N 1 F N +F0 "FB" 0 150 50 H V C CNN +F1 "FILTER" 0 -100 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +A -150 0 50 1 1799 0 1 0 N -100 0 -200 0 +A -50 0 50 1 1799 0 1 0 N 0 0 -100 0 +A 0 0 0 0 0 0 1 0 N 0 0 0 0 +A 50 0 50 1 1799 0 1 0 N 100 0 0 0 +A 150 0 50 1 1799 0 1 0 N 200 0 100 0 +S -225 75 225 -50 0 1 0 N +X 1 1 -350 0 150 R 40 40 1 1 P +X 2 2 350 0 150 L 40 40 1 1 P +ENDDRAW +ENDDEF +# +# FT232RQ +# +DEF FT232RQ U 0 40 Y Y 1 F N +F0 "U" -600 900 60 H V C CNN +F1 "FT232RQ" 550 -950 60 H V C CNN +F2 "" 550 -100 120 H V C CNN +F3 "" 550 -100 120 H V C CNN +$FPLIST + QFN-32-1EP_5x5mm_Pitch0.5mm +$ENDFPLIST +DRAW +S -650 -850 650 850 0 1 0 f +X VCCIO 1 -850 750 200 R 50 50 1 1 W +X RXD 2 850 600 200 L 50 50 1 1 I +X ~RI 3 850 -200 200 L 50 50 1 1 I +X GND 4 -50 -1050 200 U 50 50 1 1 W +X NC 5 -850 200 200 R 50 50 1 1 N +X ~DSR 6 850 50 200 L 50 50 1 1 I +X ~DCD 7 850 -100 200 L 50 50 1 1 I +X ~CTS 8 850 300 200 L 50 50 1 1 I +X CBUS4 9 850 -750 200 L 50 50 1 1 B +X CBUS2 10 850 -550 200 L 50 50 1 1 B +X GND 20 150 -1050 200 U 50 50 1 1 W +X TXD 30 850 750 200 L 50 50 1 1 O +X CBUS3 11 850 -650 200 L 50 50 1 1 B +X CBUS1 21 850 -450 200 L 50 50 1 1 B +X ~DTR 31 850 150 200 L 50 50 1 1 O +X NC 12 -850 100 200 R 50 50 1 1 N +X CBUS0 22 850 -350 200 L 50 50 1 1 B +X ~RTS 32 850 400 200 L 50 50 1 1 O +X NC 13 -850 0 200 R 50 50 1 1 N +X NC 23 -850 -450 200 R 50 50 1 1 N +X PAD 33 -250 -1050 200 U 50 50 1 1 W +X USBDP 14 -850 350 200 R 50 50 1 1 B +X AGND 24 -150 -1050 200 U 50 50 1 1 W +X USBDM 15 -850 450 200 R 50 50 1 1 B +X NC 25 -850 -100 200 R 50 50 1 1 N +X 3V3OUT 16 -850 -750 200 R 50 50 1 1 w +X TEST 26 250 -1050 200 U 50 50 1 1 W +X GND 17 50 -1050 200 U 50 50 1 1 W +X OSCI 27 -850 -550 200 R 50 50 1 1 I +X ~RESET 18 -850 -350 200 R 50 50 1 1 I +X OSCO 28 -850 -650 200 R 50 50 1 1 O +X VCC 19 -850 650 200 R 50 50 1 1 W +X NC 29 -850 -200 200 R 50 50 1 1 N +ENDDRAW +ENDDEF +# +# GND +# +DEF GND #PWR 0 0 Y Y 1 F P +F0 "#PWR" 0 -250 50 H I C CNN +F1 "GND" 0 -150 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N +X GND 1 0 0 0 D 50 50 1 1 W N +ENDDRAW +ENDDEF +# +# INDUCTOR +# +DEF INDUCTOR L 0 0 N Y 1 F N +F0 "L" 0 100 50 H V C CNN +F1 "INDUCTOR" 0 -50 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +A -150 0 50 1 1799 0 1 0 N -100 0 -200 0 +A -50 0 50 1 1799 0 1 0 N 0 0 -100 0 +A 50 0 50 1 1799 0 1 0 N 100 0 0 0 +A 150 0 50 1 1799 0 1 0 N 200 0 100 0 +X 1 1 -250 0 50 R 30 30 1 1 I +X 2 2 250 0 50 L 30 30 1 1 I +ENDDRAW +ENDDEF +# +# MCP73831 +# +DEF MCP73831 U 0 40 Y Y 1 F N +F0 "U" -250 200 50 H V C CNN +F1 "MCP73831" 100 -200 50 H V C CNN +F2 "" 0 0 60 H V C CNN +F3 "" 0 0 60 H V C CNN +$FPLIST + SOT23-5 +$ENDFPLIST +DRAW +S -300 150 300 -150 0 1 0 f +X STAT 1 -400 -100 100 R 40 40 1 1 T +X VSS 2 400 -100 100 L 40 40 1 1 W +X VBAT 3 400 100 100 L 40 40 1 1 w +X VDD 4 -400 100 100 R 40 40 1 1 W +X PROG 5 400 0 100 L 40 40 1 1 I +ENDDRAW +ENDDEF +# +# MPU-9250 +# +DEF MPU-9250 U 0 40 Y Y 1 F N +F0 "U" -400 500 60 H V C CNN +F1 "MPU-9250" 750 -400 60 H V C CNN +F2 "" -300 250 60 H V C CNN +F3 "" -300 250 60 H V C CNN +DRAW +S -450 450 450 -450 0 1 0 f +X RE_VDDIO 1 -150 650 200 D 50 50 1 1 P +X AUX_CL 7 650 250 200 L 50 50 1 1 O +X VDDIO 8 -50 650 200 D 50 50 1 1 W +X AD0 9 -650 -200 200 R 50 50 1 1 I +X REGOUT 10 -200 -650 200 U 50 50 1 1 I +X RE_GND 20 50 -650 200 U 50 50 1 1 P +X FSYNC 11 -50 -650 200 U 50 50 1 1 I +X AUX_DA 21 650 150 200 L 50 50 1 1 B +X INT 12 650 -50 200 L 50 50 1 1 O +X nCS 22 -650 -50 200 R 50 50 1 1 I +X VDD 13 100 650 200 D 50 50 1 1 W +X SCL 23 -650 250 200 R 50 50 1 1 I +X SDA 24 -650 150 200 R 50 50 1 1 B +X PAD 25 250 -650 200 U 50 50 1 1 W +X GND 18 150 -650 200 U 50 50 1 1 W +X RE_NC 19 650 -200 200 L 50 50 1 1 P +ENDDRAW +ENDDEF +# +# PWR_FLAG +# +DEF PWR_FLAG #FLG 0 0 N N 1 F P +F0 "#FLG" 0 95 50 H I C CNN +F1 "PWR_FLAG" 0 180 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +X pwr 1 0 0 0 U 20 20 0 0 w +P 6 0 1 0 0 0 0 50 -75 100 0 150 75 100 0 50 N +ENDDRAW +ENDDEF +# +# R +# +DEF R R 0 0 N Y 1 F N +F0 "R" 80 0 50 V V C CNN +F1 "R" 0 0 50 V V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +S -40 150 40 -150 0 1 0 N +X ~ 1 0 250 100 D 50 50 1 1 P +X ~ 2 0 -250 100 U 50 50 1 1 P +ENDDRAW +ENDDEF +# +# RV-3029-C2 +# +DEF RV-3029-C2 U 0 40 Y Y 1 F N +F0 "U" -350 350 60 H V C CNN +F1 "RV-3029-C2" 350 -350 60 H V C CNN +F2 "" -100 -50 60 H V C CNN +F3 "" -100 -50 60 H V C CNN +DRAW +S -400 250 400 -250 0 1 0 f +X Vdd 1 100 450 200 D 50 50 1 1 W +X CLKOUT 2 600 -150 200 L 50 50 1 1 O +X SCL 4 -600 150 200 R 50 50 1 1 I +X SDA 5 -600 50 200 R 50 50 1 1 B +X Vss 6 0 -450 200 U 50 50 1 1 W +X ~INT 7 600 150 200 L 50 50 1 1 O +X Vback 8 -100 450 200 D 50 50 1 1 W +X CLKOE 10 -600 -150 200 R 50 50 1 1 I +ENDDRAW +ENDDEF +# +# SW_PUSH +# +DEF SW_PUSH SW 0 40 N N 1 F N +F0 "SW" 150 110 50 H V C CNN +F1 "SW_PUSH" 0 -80 50 H V C CNN +F2 "" 0 0 50 H V C CNN +F3 "" 0 0 50 H V C CNN +DRAW +S -170 50 170 60 0 1 0 N +P 4 0 1 0 -40 60 -30 90 30 90 40 60 N +X 1 1 -300 0 200 R 50 50 0 1 P I +X 2 2 300 0 200 L 50 50 0 1 P I +ENDDRAW +ENDDEF +# +# TLV70233-SOT-23 +# +DEF TLV70233-SOT-23 U 0 40 Y Y 1 F N +F0 "U" -200 200 60 H V C CNN +F1 "TLV70233-SOT-23" 450 -200 60 H V C CNN +F2 "" 0 -150 60 H V C CNN +F3 "" 0 -150 60 H V C CNN +DRAW +S -250 -150 250 150 0 1 0 f +X IN 1 -450 50 200 R 50 50 1 1 W +X GND 2 0 -350 200 U 50 50 1 1 W +X EN 3 -450 -50 200 R 50 50 1 1 I +X OUT 5 450 50 200 L 50 50 1 1 w +ENDDRAW +ENDDEF +# +# USB_OTG +# +DEF USB_OTG P 0 40 Y Y 1 F N +F0 "P" 325 -125 50 H V C CNN +F1 "USB_OTG" 0 200 50 H V C CNN +F2 "" -50 -100 50 V V C CNN +F3 "" -50 -100 50 V V C CNN +$FPLIST + USB* +$ENDFPLIST +DRAW +S -250 -150 250 150 0 1 0 N +S -205 -150 -195 -120 0 1 0 N +S -105 -150 -95 -120 0 1 0 N +S -5 -150 5 -120 0 1 0 N +S 95 -150 105 -120 0 1 0 N +S 195 -150 205 -120 0 1 0 N +X VCC 1 -200 -300 150 U 50 50 1 1 w +X D- 2 -100 -300 150 U 50 50 1 1 P +X D+ 3 0 -300 150 U 50 50 1 1 P +X ID 4 100 -300 150 U 50 50 1 1 W +X GND 5 200 -300 150 U 50 50 1 1 W +X shield 6 400 100 150 L 50 50 1 1 P +ENDDRAW +ENDDEF +# +# W25Q32BV +# +DEF W25Q32BV U 0 40 Y Y 1 F N +F0 "U" -250 350 60 H V C CNN +F1 "W25Q32BV" 300 -350 60 H V C CNN +F2 "" 0 -200 60 H V C CNN +F3 "" 0 -200 60 H V C CNN +DRAW +S -300 300 300 -300 0 1 0 f +X ~CS 1 -500 50 200 R 50 50 1 1 I +X DO 2 500 -50 200 L 50 50 1 1 B +X ~WP 3 500 -200 200 L 50 50 1 1 B +X GND 4 0 -500 200 U 50 50 1 1 W +X DI 5 500 50 200 L 50 50 1 1 B +X CLK 6 -500 -50 200 R 50 50 1 1 I +X ~HOLD 7 500 200 200 L 50 50 1 1 B +X VCC 8 0 500 200 D 50 50 1 1 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/handgelenk.kicad_pcb b/board/v1/handgelenk.kicad_pcb new file mode 100644 index 0000000..2b72030 --- /dev/null +++ b/board/v1/handgelenk.kicad_pcb @@ -0,0 +1,4251 @@ +(kicad_pcb (version 4) (host pcbnew "(2015-08-11 BZR 6084)-product") + + (general + (links 189) + (no_connects 0) + (area 14.494536 12.5 57.945 57.500001) + (thickness 1.6) + (drawings 21) + (tracks 1014) + (zones 0) + (modules 61) + (nets 49) + ) + + (page A4) + (layers + (0 F.Cu signal) + (31 B.Cu signal) + (32 B.Adhes user) + (33 F.Adhes user) + (34 B.Paste user) + (35 F.Paste user) + (36 B.SilkS user) + (37 F.SilkS user) + (38 B.Mask user) + (39 F.Mask user) + (40 Dwgs.User user) + (41 Cmts.User user hide) + (42 Eco1.User user) + (43 Eco2.User user) + (44 Edge.Cuts user) + (45 Margin user) + (46 B.CrtYd user hide) + (47 F.CrtYd user) + (48 B.Fab user hide) + (49 F.Fab user hide) + ) + + (setup + (last_trace_width 0.2) + (user_trace_width 0.25) + (user_trace_width 0.3) + (user_trace_width 0.35) + (user_trace_width 0.45) + (user_trace_width 0.6) + (trace_clearance 0.12) + (zone_clearance 0.23) + (zone_45_only no) + (trace_min 0.16) + (segment_width 0.2) + (edge_width 0.15) + (via_size 0.6) + (via_drill 0.3) + (via_min_size 0.6) + (via_min_drill 0.3) + (user_via 2 1.6) + (user_via 2.5 2.1) + (user_via 3 2.6) + (uvia_size 0.3) + (uvia_drill 0.1) + (uvias_allowed no) + (uvia_min_size 0.3) + (uvia_min_drill 0.1) + (pcb_text_width 0.3) + (pcb_text_size 1.5 1.5) + (mod_edge_width 0.15) + (mod_text_size 1 1) + (mod_text_width 0.15) + (pad_size 1.725 1.725) + (pad_drill 0) + (pad_to_mask_clearance 0.2) + (aux_axis_origin 0 0) + (visible_elements FFFFFE7F) + (pcbplotparams + (layerselection 0x010f0_80000001) + (usegerberextensions true) + (excludeedgelayer true) + (linewidth 0.100000) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15) + (hpglpenoverlay 2) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (padsonsilk false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 0) + (scaleselection 1) + (outputdirectory "")) + ) + + (net 0 "") + (net 1 "Net-(ANT1-Pad1)") + (net 2 +3V3) + (net 3 GND) + (net 4 "Net-(C2-Pad1)") + (net 5 "Net-(C3-Pad1)") + (net 6 +5V) + (net 7 +BATT) + (net 8 "Net-(C8-Pad1)") + (net 9 "Net-(C9-Pad1)") + (net 10 "Net-(C10-Pad1)") + (net 11 /MPU-9250/INT) + (net 12 /RV-3029-C2/INT) + (net 13 "Net-(C14-Pad1)") + (net 14 "/Power Management/USB_DM") + (net 15 "/Power Management/USB_DP") + (net 16 "Net-(R2-Pad1)") + (net 17 "/Power Management/~CHARGE") + (net 18 "Net-(R4-Pad1)") + (net 19 /DS_WAKE) + (net 20 "Net-(R6-Pad1)") + (net 21 /SD_CLK) + (net 22 "/Power Management/BATT_SENSE") + (net 23 /MPU-9250/SCL) + (net 24 /MPU-9250/SDA) + (net 25 "/Power Management/DTR") + (net 26 /SD_D2) + (net 27 /SD_D3) + (net 28 /SD_CMD) + (net 29 /SD_D0) + (net 30 /SD_D1) + (net 31 "/Power Management/TXD") + (net 32 "/Power Management/RXD") + (net 33 "/Power Management/RTS") + (net 34 /BTN1) + (net 35 /BTN2) + (net 36 "Net-(C19-Pad1)") + (net 37 "Net-(C20-Pad1)") + (net 38 "Net-(C21-Pad1)") + (net 39 "Net-(C22-Pad1)") + (net 40 "Net-(C22-Pad2)") + (net 41 "Net-(C23-Pad1)") + (net 42 "Net-(C23-Pad2)") + (net 43 "Net-(D1-Pad1)") + (net 44 "Net-(DS1-Pad26)") + (net 45 "Net-(P3-Pad2)") + (net 46 "Net-(Q1-Pad1)") + (net 47 /VIBR) + (net 48 "Net-(R12-Pad1)") + + (net_class Default "This is the default net class." + (clearance 0.12) + (trace_width 0.2) + (via_dia 0.6) + (via_drill 0.3) + (uvia_dia 0.3) + (uvia_drill 0.1) + (add_net +3V3) + (add_net +5V) + (add_net +BATT) + (add_net /BTN1) + (add_net /BTN2) + (add_net /DS_WAKE) + (add_net /MPU-9250/INT) + (add_net /MPU-9250/SCL) + (add_net /MPU-9250/SDA) + (add_net "/Power Management/BATT_SENSE") + (add_net "/Power Management/DTR") + (add_net "/Power Management/RTS") + (add_net "/Power Management/RXD") + (add_net "/Power Management/TXD") + (add_net "/Power Management/USB_DM") + (add_net "/Power Management/USB_DP") + (add_net "/Power Management/~CHARGE") + (add_net /RV-3029-C2/INT) + (add_net /SD_CLK) + (add_net /SD_CMD) + (add_net /SD_D0) + (add_net /SD_D1) + (add_net /SD_D2) + (add_net /SD_D3) + (add_net /VIBR) + (add_net GND) + (add_net "Net-(ANT1-Pad1)") + (add_net "Net-(C10-Pad1)") + (add_net "Net-(C14-Pad1)") + (add_net "Net-(C19-Pad1)") + (add_net "Net-(C2-Pad1)") + (add_net "Net-(C20-Pad1)") + (add_net "Net-(C21-Pad1)") + (add_net "Net-(C22-Pad1)") + (add_net "Net-(C22-Pad2)") + (add_net "Net-(C23-Pad1)") + (add_net "Net-(C23-Pad2)") + (add_net "Net-(C3-Pad1)") + (add_net "Net-(C8-Pad1)") + (add_net "Net-(C9-Pad1)") + (add_net "Net-(D1-Pad1)") + (add_net "Net-(DS1-Pad26)") + (add_net "Net-(P3-Pad2)") + (add_net "Net-(Q1-Pad1)") + (add_net "Net-(R12-Pad1)") + (add_net "Net-(R2-Pad1)") + (add_net "Net-(R4-Pad1)") + (add_net "Net-(R6-Pad1)") + ) + + (module "Project Libraries:er-oled-ssd1306" (layer B.Cu) (tedit 55FED366) (tstamp 55FC6E7F) + (at 37.5 27.25 180) + (path /55FB110E) + (fp_text reference DS1 (at 0 -2.4 180) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value ER-OLED-SSD1306 (at 0 2.5 180) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text user "1.1-1.2mm max. PCB thickness" (at 0 7.9 180) (layer Dwgs.User) + (effects (font (size 0.45 0.45) (thickness 0.11))) + ) + (fp_line (start 6 6.4) (end 6 7.4) (layer B.SilkS) (width 0.15)) + (fp_line (start -6 7.4) (end -6 6.4) (layer B.SilkS) (width 0.15)) + (fp_line (start -6 7.4) (end -5.1 7.4) (layer B.SilkS) (width 0.15)) + (fp_line (start -5.1 7.4) (end 6 7.4) (layer B.SilkS) (width 0.15)) + (fp_line (start 11 3.5) (end 6 6.4) (layer B.SilkS) (width 0.15)) + (fp_line (start -6 6.4) (end -11 3.5) (layer B.SilkS) (width 0.15)) + (fp_line (start 11 -0.5) (end 11 3.5) (layer B.SilkS) (width 0.15)) + (fp_line (start -11 -0.5) (end -11 3.5) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -10.15 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 2 smd rect (at -9.45 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 40 "Net-(C22-Pad2)")) + (pad 3 smd rect (at -8.75 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 39 "Net-(C22-Pad1)")) + (pad 4 smd rect (at -8.05 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 42 "Net-(C23-Pad2)")) + (pad 5 smd rect (at -7.35 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 41 "Net-(C23-Pad1)")) + (pad 7 smd rect (at -5.95 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask)) + (pad 8 smd rect (at -5.25 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 9 smd rect (at -4.55 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 2 +3V3)) + (pad 10 smd rect (at -3.85 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 11 smd rect (at -3.15 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 2 +3V3)) + (pad 12 smd rect (at -2.45 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 13 smd rect (at -1.75 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 14 smd rect (at -1.05 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 36 "Net-(C19-Pad1)")) + (pad 15 smd rect (at -0.35 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 16 smd rect (at 0.35 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 17 smd rect (at 1.05 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 18 smd rect (at 1.75 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 23 /MPU-9250/SCL)) + (pad 19 smd rect (at 2.45 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 24 /MPU-9250/SDA)) + (pad 20 smd rect (at 3.15 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 24 /MPU-9250/SDA)) + (pad 21 smd rect (at 3.85 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 22 smd rect (at 4.55 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 23 smd rect (at 5.25 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 24 smd rect (at 5.95 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 25 smd rect (at 6.65 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 26 smd rect (at 7.35 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 44 "Net-(DS1-Pad26)")) + (pad 27 smd rect (at 8.05 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 37 "Net-(C20-Pad1)")) + (pad 28 smd rect (at 8.75 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 38 "Net-(C21-Pad1)")) + (pad 29 smd rect (at 9.45 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 30 smd rect (at 10.15 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 6 smd rect (at -6.65 0 180) (size 0.4 3) (layers B.Cu B.Paste B.Mask) + (net 2 +3V3)) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA48) + (at 24.25 45 90) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55CFAED1/55D09B38) + (attr smd) + (fp_text reference C3 (at 0 -1.35 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10n (at 0 1.9 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 5 "Net-(C3-Pad1)")) + (pad 2 smd rect (at 0.75 0 90) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm (layer F.Cu) (tedit 54130A77) (tstamp 55F9CB07) + (at 29.5 27) + (descr "UH Package; 32-Lead Plastic QFN (5mm x 5mm); (see Linear Technology QFN_32_05-08-1693.pdf)") + (tags "QFN 0.5") + (path /55F70BBB) + (attr smd) + (fp_text reference U1 (at 3.2 3.5) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value ESP8266EX (at 0 3.75) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -3 -3) (end -3 3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 3 -3) (end 3 3) (layer F.CrtYd) (width 0.05)) + (fp_line (start -3 -3) (end 3 -3) (layer F.CrtYd) (width 0.05)) + (fp_line (start -3 3) (end 3 3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.625 -2.625) (end 2.625 -2.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.625 2.625) (end -2.625 2.1) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.625 2.625) (end 2.625 2.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.625 -2.625) (end -2.1 -2.625) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.625 2.625) (end -2.1 2.625) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.625 2.625) (end 2.1 2.625) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.625 -2.625) (end 2.1 -2.625) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.4 -1.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at -2.4 -1.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 8 "Net-(C8-Pad1)")) + (pad 3 smd rect (at -2.4 -0.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 4 smd rect (at -2.4 -0.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 5 smd rect (at -2.4 0.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 6 smd rect (at -2.4 0.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 22 "/Power Management/BATT_SENSE")) + (pad 7 smd rect (at -2.4 1.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 33 "/Power Management/RTS")) + (pad 8 smd rect (at -2.4 1.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 19 /DS_WAKE)) + (pad 9 smd rect (at -1.75 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 23 /MPU-9250/SCL)) + (pad 10 smd rect (at -1.25 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 47 /VIBR)) + (pad 11 smd rect (at -0.75 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 12 smd rect (at -0.25 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 17 "/Power Management/~CHARGE")) + (pad 13 smd rect (at 0.25 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 14 smd rect (at 0.75 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 24 /MPU-9250/SDA)) + (pad 15 smd rect (at 1.25 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 25 "/Power Management/DTR")) + (pad 16 smd rect (at 1.75 2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 34 /BTN1)) + (pad 17 smd rect (at 2.4 1.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 18 smd rect (at 2.4 1.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 26 /SD_D2)) + (pad 19 smd rect (at 2.4 0.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 27 /SD_D3)) + (pad 20 smd rect (at 2.4 0.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 28 /SD_CMD)) + (pad 21 smd rect (at 2.4 -0.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 21 /SD_CLK)) + (pad 22 smd rect (at 2.4 -0.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 29 /SD_D0)) + (pad 23 smd rect (at 2.4 -1.25) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 30 /SD_D1)) + (pad 24 smd rect (at 2.4 -1.75) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 35 /BTN2)) + (pad 25 smd rect (at 1.75 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 31 "/Power Management/TXD")) + (pad 26 smd rect (at 1.25 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 32 "/Power Management/RXD")) + (pad 27 smd rect (at 0.75 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 10 "Net-(C10-Pad1)")) + (pad 28 smd rect (at 0.25 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 9 "Net-(C9-Pad1)")) + (pad 29 smd rect (at -0.25 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 30 smd rect (at -0.75 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 31 smd rect (at -1.25 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 16 "Net-(R2-Pad1)")) + (pad 32 smd rect (at -1.75 -2.4 90) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 11 /MPU-9250/INT)) + (pad 33 smd rect (at 0.8625 0.8625) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 33 smd rect (at 0.8625 -0.8625) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 33 smd rect (at -0.8625 0.8625) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 33 smd rect (at -0.8625 -0.8625) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (model Housings_DFN_QFN.3dshapes/QFN-32-1EP_5x5mm_Pitch0.5mm.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Pin_Headers:Pin_Header_Straight_1x02 (layer F.Cu) (tedit 54EA090C) (tstamp 55FC6E85) + (at 43.726696 41.5 90) + (descr "Through hole pin header") + (tags "pin header") + (path /55FD1063) + (fp_text reference P3 (at 2.3 -0.026696 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value VIBR_MOTOR (at 0 -3.1 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 1.27 1.27) (end 1.27 3.81) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.55 -1.55) (end 1.55 0) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.75 -1.75) (end -1.75 4.3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.75 -1.75) (end 1.75 4.3) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.75 -1.75) (end 1.75 -1.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.75 4.3) (end 1.75 4.3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.27 1.27) (end -1.27 1.27) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.55 0) (end -1.55 -1.55) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.55 -1.55) (end 1.55 -1.55) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.27 1.27) (end -1.27 3.81) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.27 3.81) (end 1.27 3.81) (layer F.SilkS) (width 0.15)) + (pad 1 thru_hole rect (at 0 0 90) (size 2.032 2.032) (drill 1.016) (layers *.Cu *.Mask F.SilkS) + (net 2 +3V3)) + (pad 2 thru_hole oval (at 0 2.54 90) (size 2.032 2.032) (drill 1.016) (layers *.Cu *.Mask F.SilkS) + (net 45 "Net-(P3-Pad2)")) + ) + + (module "Project Libraries:rv3029" (layer F.Cu) (tedit 55F9C351) (tstamp 55F9CB7A) + (at 47.3 35.6 180) + (path /55F97917/55F9C7CF) + (fp_text reference U7 (at 0 0 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value RV-3029-C2 (at -4 0 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 3 1.5) (end 2.5 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 3 -1.5) (end 3 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.5 -1.5) (end 3 -1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -3 1.5) (end -2.5 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -3 -1.5) (end -3 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 -1.5) (end -3 -1.5) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2 1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at -1 1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at 0 1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 4 smd rect (at 1 1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 23 /MPU-9250/SCL)) + (pad 5 smd rect (at 2 1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 24 /MPU-9250/SDA)) + (pad 6 smd rect (at 2 -1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 7 smd rect (at 1 -1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 12 /RV-3029-C2/INT)) + (pad 8 smd rect (at 0 -1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 9 smd rect (at -1 -1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 10 smd rect (at -2 -1.55 180) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA42) + (at 23.05 39.9 180) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55CFAED1/55D08232) + (attr smd) + (fp_text reference C2 (at -0.85 -1.4 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100n (at 0 1.9 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 180) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 4 "Net-(C2-Pad1)")) + (pad 2 smd rect (at 0.75 0 180) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module "Project Libraries:wson8_5x6" (layer F.Cu) (tedit 55FD25D6) (tstamp 55FD295B) + (at 39.2 27.4 90) + (path /55F989A1) + (fp_text reference U5 (at -0.5 0 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value W25Q32BV (at 0 -3.25 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_circle (center -2 -2.1) (end -2 -2) (layer F.SilkS) (width 0.2)) + (fp_line (start -2.5 -2.25) (end -2.5 -2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 -2.5) (end 1.75 -2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.75 -2.5) (end 2.5 -2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.5 -2.5) (end 2.5 -2.25) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 2.25) (end -2.5 2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 2.5) (end 1 2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 1 2.5) (end 2.5 2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.5 2.5) (end 2.5 2.25) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.921 -1.905 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 28 /SD_CMD)) + (pad 2 smd rect (at -2.921 -0.635 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 29 /SD_D0)) + (pad 3 smd rect (at -2.921 0.635 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 27 /SD_D3)) + (pad 4 smd rect (at -2.921 1.905 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 5 smd rect (at 2.921 1.905 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 30 /SD_D1)) + (pad 6 smd rect (at 2.921 0.635 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 20 "Net-(R6-Pad1)")) + (pad 7 smd rect (at 2.921 -0.635 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 26 /SD_D2)) + (pad 8 smd rect (at 2.921 -1.905 90) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + ) + + (module Diodes_SMD:SOD-323 (layer B.Cu) (tedit 5530FC5E) (tstamp 55FC6E5D) + (at 42 32.75 90) + (descr SOD-323) + (tags SOD-323) + (path /55FC41A1) + (attr smd) + (fp_text reference D3 (at -2.75 0 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1N4148 (at 0.1 -1.9 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start 0.25 0) (end 0.5 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0) (end -0.5 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0) (end 0.25 0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.25 0.35) (end 0.25 -0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.25 -0.35) (end -0.25 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0.35) (end -0.25 -0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.5 0.95) (end 1.5 0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.5 0.95) (end 1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.5 -0.95) (end 1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.5 0.95) (end -1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.1 -0.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.3 0.8) (end 1.1 0.8) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.055 0 90) (size 0.59 0.45) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 2 smd rect (at 1.055 0 90) (size 0.59 0.45) (layers B.Cu B.Paste B.Mask) + (net 36 "Net-(C19-Pad1)")) + ) + + (module Resistors_SMD:R_0603 (layer B.Cu) (tedit 5415CC62) (tstamp 55FC6EAA) + (at 40 32.75 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55FC214E) + (attr smd) + (fp_text reference R13 (at 3.05 0 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 10K (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end -1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.3 0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.675) (end -0.5 -0.675) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.5 0.675) (end 0.5 0.675) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 36 "Net-(C19-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module "Project Libraries:an9520" (layer F.Cu) (tedit 55F9B480) (tstamp 55F9CA36) + (at 21.5 26 90) + (path /55F8139E) + (fp_text reference ANT1 (at 0.2 0.1 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value AN9520 (at 0 0 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 3.5 1) (end -3.5 1) (layer F.SilkS) (width 0.15)) + (fp_line (start -3.5 -1) (end 3.5 -1) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -4.75 0 90) (size 1.4 2) (layers F.Cu F.Paste F.Mask) + (net 1 "Net-(ANT1-Pad1)")) + (pad 2 smd rect (at 4.75 0 90) (size 1.4 2) (layers F.Cu F.Paste F.Mask)) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA3C) + (at 29.25 31) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55F6EFF8) + (attr smd) + (fp_text reference C1 (at -2.45 0) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100n (at 0 1.9) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA4E) + (at 26.75 48 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55CFAED1/55D05F2E) + (attr smd) + (fp_text reference C4 (at 1.6 3.25 360) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 4u7 (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 6 +5V)) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA54) + (at 38 48 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55CFAED1/55D07963) + (attr smd) + (fp_text reference C5 (at 0 -1.9 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 4u7 (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 7 +BATT)) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_1206 (layer F.Cu) (tedit 5415D7BD) (tstamp 55F9CA5A) + (at 45.75 47.25 270) + (descr "Capacitor SMD 1206, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 1206") + (path /55CFAED1/55D088C0) + (attr smd) + (fp_text reference C6 (at -2.55 -5.75 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100u (at 0 2.3 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -2.3 -1.15) (end 2.3 -1.15) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.3 1.15) (end 2.3 1.15) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.3 -1.15) (end -2.3 1.15) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.3 -1.15) (end 2.3 1.15) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1 -1.025) (end -1 -1.025) (layer F.SilkS) (width 0.15)) + (fp_line (start -1 1.025) (end 1 1.025) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.5 0 270) (size 1 1.6) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 1.5 0 270) (size 1 1.6) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_1206.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA60) + (at 43.75 48 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55CFAED1/55D084FD) + (attr smd) + (fp_text reference C7 (at -3.3 -6.35 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10u (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0402 (layer F.Cu) (tedit 5415D599) (tstamp 55F9CA66) + (at 24 26 180) + (descr "Capacitor SMD 0402, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0402") + (path /55F80CB5) + (attr smd) + (fp_text reference C8 (at -1.9 0.5 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 5.6p (at 0 1.7 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.15 -0.6) (end 1.15 -0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.15 0.6) (end 1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.15 -0.6) (end -1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.15 -0.6) (end 1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.25 -0.475) (end -0.25 -0.475) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 0.475) (end 0.25 0.475) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.55 0 180) (size 0.6 0.5) (layers F.Cu F.Paste F.Mask) + (net 8 "Net-(C8-Pad1)")) + (pad 2 smd rect (at 0.55 0 180) (size 0.6 0.5) (layers F.Cu F.Paste F.Mask) + (net 1 "Net-(ANT1-Pad1)")) + (model Capacitors_SMD.3dshapes/C_0402.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0402 (layer F.Cu) (tedit 5415D599) (tstamp 55F9CA6C) + (at 28.25 21.75 90) + (descr "Capacitor SMD 0402, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0402") + (path /55F73D4E) + (attr smd) + (fp_text reference C9 (at -0.25 10.55 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10p (at 0 1.7 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.15 -0.6) (end 1.15 -0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.15 0.6) (end 1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.15 -0.6) (end -1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.15 -0.6) (end 1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.25 -0.475) (end -0.25 -0.475) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 0.475) (end 0.25 0.475) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.55 0 90) (size 0.6 0.5) (layers F.Cu F.Paste F.Mask) + (net 9 "Net-(C9-Pad1)")) + (pad 2 smd rect (at 0.55 0 90) (size 0.6 0.5) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0402.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0402 (layer F.Cu) (tedit 5415D599) (tstamp 55F9CA72) + (at 33.25 21) + (descr "Capacitor SMD 0402, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0402") + (path /55F73EE1) + (attr smd) + (fp_text reference C10 (at 8.25 1 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10p (at 0 1.7) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.15 -0.6) (end 1.15 -0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.15 0.6) (end 1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.15 -0.6) (end -1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.15 -0.6) (end 1.15 0.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.25 -0.475) (end -0.25 -0.475) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 0.475) (end 0.25 0.475) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.55 0) (size 0.6 0.5) (layers F.Cu F.Paste F.Mask) + (net 10 "Net-(C10-Pad1)")) + (pad 2 smd rect (at 0.55 0) (size 0.6 0.5) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0402.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA78) + (at 24.5 21.5 180) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55F956F5) + (attr smd) + (fp_text reference C11 (at -11.5 -0.5 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100n (at 0 1.9 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 180) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 11 /MPU-9250/INT)) + (pad 2 smd rect (at 0.75 0 180) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 12 /RV-3029-C2/INT)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA7E) + (at 50.520702 23.098198 90) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55F844A4/55F83B4A) + (attr smd) + (fp_text reference C12 (at 2.198198 -0.020702 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100n (at 0 1.9 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 90) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA84) + (at 52.270702 23.098198 90) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55F844A4/55F83D26) + (attr smd) + (fp_text reference C13 (at -0.001802 1.529298 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10n (at 0 1.9 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 90) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA8A) + (at 47.270702 26.348198 180) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55F844A4/55F84959) + (attr smd) + (fp_text reference C14 (at 0 -1.9 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100n (at 0 1.9 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 180) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 13 "Net-(C14-Pad1)")) + (pad 2 smd rect (at 0.75 0 180) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer F.Cu) (tedit 5415D631) (tstamp 55F9CA90) + (at 51.3 35.6 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55F97917/55F98261) + (attr smd) + (fp_text reference C15 (at 3.2 -0.7 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10n (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end -1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.45 -0.75) (end 1.45 0.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.35 -0.6) (end 0.35 -0.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.35 0.6) (end -0.35 0.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0805 (layer F.Cu) (tedit 5415D6EA) (tstamp 55F9CA96) + (at 27.75 45.5) + (descr "Capacitor SMD 0805, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0805") + (path /55CFAED1/55D0855B) + (attr smd) + (fp_text reference FB1 (at 3.15 -0.5) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value "BLM21PG 600" (at 0 2.1) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.8 -1) (end 1.8 -1) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.8 1) (end 1.8 1) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.8 -1) (end -1.8 1) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.8 -1) (end 1.8 1) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.85) (end -0.5 -0.85) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 0.85) (end 0.5 0.85) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -1 0) (size 1 1.25) (layers F.Cu F.Paste F.Mask) + (net 5 "Net-(C3-Pad1)")) + (pad 2 smd rect (at 1 0) (size 1 1.25) (layers F.Cu F.Paste F.Mask) + (net 6 +5V)) + (model Capacitors_SMD.3dshapes/C_0805.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Connect:USB_Micro-B (layer B.Cu) (tedit 5543E447) (tstamp 55F9CAA3) + (at 22.75 45.25 90) + (descr "Micro USB Type B Receptacle") + (tags "USB USB_B USB_micro USB_OTG") + (path /55CFAED1/55D06165) + (attr smd) + (fp_text reference P1 (at 0 3.45 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value USB_OTG (at 0 -4.8 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -4.6 2.8) (end 4.6 2.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 4.6 2.8) (end 4.6 -4.05) (layer B.CrtYd) (width 0.05)) + (fp_line (start 4.6 -4.05) (end -4.6 -4.05) (layer B.CrtYd) (width 0.05)) + (fp_line (start -4.6 -4.05) (end -4.6 2.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -4.3509 -3.81746) (end 4.3491 -3.81746) (layer B.SilkS) (width 0.15)) + (fp_line (start -4.3509 2.58754) (end 4.3491 2.58754) (layer B.SilkS) (width 0.15)) + (fp_line (start 4.3491 2.58754) (end 4.3491 -3.81746) (layer B.SilkS) (width 0.15)) + (fp_line (start 4.3491 -2.58746) (end -4.3509 -2.58746) (layer B.SilkS) (width 0.15)) + (fp_line (start -4.3509 -3.81746) (end -4.3509 2.58754) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.3009 1.56254) (size 1.35 0.4) (layers B.Cu B.Paste B.Mask) + (net 5 "Net-(C3-Pad1)")) + (pad 2 smd rect (at -0.6509 1.56254) (size 1.35 0.4) (layers B.Cu B.Paste B.Mask) + (net 14 "/Power Management/USB_DM")) + (pad 3 smd rect (at -0.0009 1.56254) (size 1.35 0.4) (layers B.Cu B.Paste B.Mask) + (net 15 "/Power Management/USB_DP")) + (pad 4 smd rect (at 0.6491 1.56254) (size 1.35 0.4) (layers B.Cu B.Paste B.Mask)) + (pad 5 smd rect (at 1.2991 1.56254) (size 1.35 0.4) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 6 thru_hole oval (at -2.5009 1.56254) (size 0.95 1.25) (drill oval 0.55 0.85) (layers *.Cu *.Mask B.SilkS) + (net 3 GND)) + (pad 6 thru_hole oval (at 2.4991 1.56254) (size 0.95 1.25) (drill oval 0.55 0.85) (layers *.Cu *.Mask B.SilkS) + (net 3 GND)) + (pad 6 thru_hole oval (at -3.5009 -1.13746) (size 1.55 1) (drill oval 1.15 0.5) (layers *.Cu *.Mask B.SilkS) + (net 3 GND)) + (pad 6 thru_hole oval (at 3.4991 -1.13746) (size 1.55 1) (drill oval 1.15 0.5) (layers *.Cu *.Mask B.SilkS) + (net 3 GND)) + ) + + (module Pin_Headers:Pin_Header_Straight_1x02 (layer F.Cu) (tedit 54EA090C) (tstamp 55F9CAA9) + (at 35.5 47.75 180) + (descr "Through hole pin header") + (tags "pin header") + (path /55CFAED1/55D0747F) + (fp_text reference P2 (at 0 4.75 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value LIPO (at 0 -3.1 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 1.27 1.27) (end 1.27 3.81) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.55 -1.55) (end 1.55 0) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.75 -1.75) (end -1.75 4.3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.75 -1.75) (end 1.75 4.3) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.75 -1.75) (end 1.75 -1.75) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.75 4.3) (end 1.75 4.3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.27 1.27) (end -1.27 1.27) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.55 0) (end -1.55 -1.55) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.55 -1.55) (end 1.55 -1.55) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.27 1.27) (end -1.27 3.81) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.27 3.81) (end 1.27 3.81) (layer F.SilkS) (width 0.15)) + (pad 1 thru_hole rect (at 0 0 180) (size 2.032 2.032) (drill 1.016) (layers *.Cu *.Mask F.SilkS) + (net 3 GND)) + (pad 2 thru_hole oval (at 0 2.54 180) (size 2.032 2.032) (drill 1.016) (layers *.Cu *.Mask F.SilkS) + (net 7 +BATT)) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CAAF) + (at 24.5 28.25 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55F6F69B) + (attr smd) + (fp_text reference R1 (at 2.35 0.1 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 1K (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 33 "/Power Management/RTS")) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CAB5) + (at 26.75 22 90) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55F6E5F4) + (attr smd) + (fp_text reference R2 (at 0 10.65 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 12K (at 0 1.9 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 16 "Net-(R2-Pad1)")) + (pad 2 smd rect (at 0.75 0 90) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CAC1) + (at 28.75 48.25 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55CFAED1/55D05DFE) + (attr smd) + (fp_text reference R4 (at 1.35 3.45 360) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 3K3 (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 18 "Net-(R4-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CAC7) + (at 24.5 23.25 180) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55F9485D) + (attr smd) + (fp_text reference R5 (at 0.4 -1.45 360) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 300 (at 0 1.9 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 180) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 11 /MPU-9250/INT)) + (pad 2 smd rect (at 0.75 0 180) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 19 /DS_WAKE)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CACD) + (at 34 26 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55F9BA0E) + (attr smd) + (fp_text reference R6 (at 2 0 360) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 200 (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 20 "Net-(R6-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 21 /SD_CLK)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CAD3) + (at 38.75 45) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55CFAED1/55F9A99C) + (attr smd) + (fp_text reference R7 (at 0.05 -1.6) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 330K (at 0 1.9) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 7 +BATT)) + (pad 2 smd rect (at 0.75 0) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 22 "/Power Management/BATT_SENSE")) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CAD9) + (at 41.75 45) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55CFAED1/55F9A9FE) + (attr smd) + (fp_text reference R8 (at -0.85 -1.6) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 100K (at 0 1.9) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 22 "/Power Management/BATT_SENSE")) + (pad 2 smd rect (at 0.75 0) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer F.Cu) (tedit 5415CC62) (tstamp 55F9CADF) + (at 53.05 35.6 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55F97917/55F993EB) + (attr smd) + (fp_text reference R9 (at 2.7 -0.55 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.9 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end -1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.3 -0.8) (end 1.3 0.8) (layer F.CrtYd) (width 0.05)) + (fp_line (start 0.5 0.675) (end -0.5 0.675) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.5 -0.675) (end 0.5 -0.675) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers F.Cu F.Paste F.Mask) + (net 12 /RV-3029-C2/INT)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm (layer F.Cu) (tedit 55FBEB8F) (tstamp 55F9CB2F) + (at 29.5 41.25 270) + (descr "UH Package; 32-Lead Plastic QFN (5mm x 5mm); (see Linear Technology QFN_32_05-08-1693.pdf)") + (tags "QFN 0.5") + (path /55CFAED1/55FD3EAE) + (attr smd) + (fp_text reference U2 (at -2.15 -3.7 450) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value FT232RQ (at 0 3.75 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -3 -3) (end -3 3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 3 -3) (end 3 3) (layer F.CrtYd) (width 0.05)) + (fp_line (start -3 -3) (end 3 -3) (layer F.CrtYd) (width 0.05)) + (fp_line (start -3 3) (end 3 3) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.625 -2.625) (end 2.625 -2.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.625 2.625) (end -2.625 2.1) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.625 2.625) (end 2.625 2.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.625 -2.625) (end -2.1 -2.625) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.625 2.625) (end -2.1 2.625) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.625 2.625) (end 2.1 2.625) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.625 -2.625) (end 2.1 -2.625) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.4 -1.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 4 "Net-(C2-Pad1)")) + (pad 2 smd rect (at -2.4 -1.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 32 "/Power Management/RXD")) + (pad 3 smd rect (at -2.4 -0.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 4 smd rect (at -2.4 -0.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 5 smd rect (at -2.4 0.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 6 smd rect (at -2.4 0.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 7 smd rect (at -2.4 1.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 8 smd rect (at -2.4 1.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 9 smd rect (at -1.75 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 10 smd rect (at -1.25 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 11 smd rect (at -0.75 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 12 smd rect (at -0.25 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 13 smd rect (at 0.25 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 14 smd rect (at 0.75 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 15 "/Power Management/USB_DP")) + (pad 15 smd rect (at 1.25 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 14 "/Power Management/USB_DM")) + (pad 16 smd rect (at 1.75 2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 4 "Net-(C2-Pad1)")) + (pad 17 smd rect (at 2.4 1.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 18 smd rect (at 2.4 1.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 19 smd rect (at 2.4 0.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 6 +5V)) + (pad 20 smd rect (at 2.4 0.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 21 smd rect (at 2.4 -0.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 22 smd rect (at 2.4 -0.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 23 smd rect (at 2.4 -1.25 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 24 smd rect (at 2.4 -1.75 270) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 25 smd rect (at 1.75 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 26 smd rect (at 1.25 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 27 smd rect (at 0.75 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 28 smd rect (at 0.25 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 29 smd rect (at -0.25 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask)) + (pad 30 smd rect (at -0.75 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 31 "/Power Management/TXD")) + (pad 31 smd rect (at -1.25 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 25 "/Power Management/DTR")) + (pad 32 smd rect (at -1.75 -2.4) (size 0.7 0.25) (layers F.Cu F.Paste F.Mask) + (net 33 "/Power Management/RTS")) + (pad 33 smd rect (at 0.8625 0.8625 270) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 33 smd rect (at 0.8625 -0.8625 270) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 33 smd rect (at -0.8625 0.8625 270) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 33 smd rect (at -0.8625 -0.8625 270) (size 1.725 1.725) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (model Housings_DFN_QFN.3dshapes/QFN-32-1EP_5x5mm_Pitch0.5mm.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module TO_SOT_Packages_SMD:SOT-23-5 (layer F.Cu) (tedit 55360473) (tstamp 55F9CB38) + (at 31.5 48 180) + (descr "5-pin SOT23 package") + (tags SOT-23-5) + (path /55CFAED1/55CFAFFF) + (attr smd) + (fp_text reference U3 (at -1.5 2.6 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value MCP73831 (at -0.05 2.35 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.8 -1.6) (end 1.8 -1.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.8 -1.6) (end 1.8 1.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.8 1.6) (end -1.8 1.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.8 1.6) (end -1.8 -1.6) (layer F.CrtYd) (width 0.05)) + (fp_circle (center -0.3 -1.7) (end -0.2 -1.7) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.25 -1.45) (end -0.25 -1.45) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.25 1.45) (end 0.25 -1.45) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 1.45) (end 0.25 1.45) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 -1.45) (end -0.25 1.45) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.1 -0.95 180) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 17 "/Power Management/~CHARGE")) + (pad 2 smd rect (at -1.1 0 180) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 3 smd rect (at -1.1 0.95 180) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 7 +BATT)) + (pad 4 smd rect (at 1.1 0.95 180) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 6 +5V)) + (pad 5 smd rect (at 1.1 -0.95 180) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 18 "Net-(R4-Pad1)")) + (model TO_SOT_Packages_SMD.3dshapes/SOT-23-5.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Housings_DFN_QFN:QFN-24-1EP_3x3mm_Pitch0.4mm (layer F.Cu) (tedit 551439DF) (tstamp 55F9CB6C) + (at 47.520702 23.098198) + (descr "24-Lead Plastic QFN (3mm x 3mm); Pitch 0.4mm") + (tags "QFN 0.4") + (path /55F844A4/55F84634) + (attr smd) + (fp_text reference U6 (at -2.720702 0.701802 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value MPU-9250 (at 0 3.25) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 2.025 -2.025) (end 2.025 2.025) (layer F.CrtYd) (width 0.05)) + (fp_line (start 2.025 2.025) (end -2.025 2.025) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.025 2.025) (end -2.025 -2.025) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.025 -2.025) (end 2.025 -2.025) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.6 1.6) (end -1.6 1.2) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.6 1.6) (end -1.2 1.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.6 1.6) (end 1.6 1.2) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.6 1.6) (end 1.2 1.6) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.6 -1.6) (end 1.6 -1.2) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.6 -1.6) (end 1.2 -1.6) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.6 -1.6) (end -1.2 -1.6) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.5 -1) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at -1.5 -0.6) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at -1.5 -0.2) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 4 smd rect (at -1.5 0.2) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 5 smd rect (at -1.5 0.6) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 6 smd rect (at -1.5 1) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 7 smd rect (at -1 1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 8 smd rect (at -0.6 1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 9 smd rect (at -0.2 1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 10 smd rect (at 0.2 1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 13 "Net-(C14-Pad1)")) + (pad 11 smd rect (at 0.6 1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 12 smd rect (at 1 1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 11 /MPU-9250/INT)) + (pad 13 smd rect (at 1.5 1) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (pad 14 smd rect (at 1.5 0.6) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 15 smd rect (at 1.5 0.2) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 16 smd rect (at 1.5 -0.2) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 17 smd rect (at 1.5 -0.6) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 18 smd rect (at 1.5 -1) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 19 smd rect (at 1 -1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 20 smd rect (at 0.6 -1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 21 smd rect (at 0.2 -1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 22 smd rect (at -0.2 -1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask)) + (pad 23 smd rect (at -0.6 -1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 23 /MPU-9250/SCL)) + (pad 24 smd rect (at -1 -1.5 90) (size 0.55 0.2) (layers F.Cu F.Paste F.Mask) + (net 24 /MPU-9250/SDA)) + (pad 25 smd rect (at 0.435 0.4) (size 0.875 0.8) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 25 smd rect (at 0.435 -0.4) (size 0.875 0.8) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 25 smd rect (at -0.435 0.4) (size 0.875 0.8) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + (pad 25 smd rect (at -0.435 -0.4) (size 0.875 0.8) (layers F.Cu F.Paste F.Mask) + (net 3 GND) (solder_paste_margin_ratio -0.2)) + ) + + (module TO_SOT_Packages_SMD:SOT-23-5 (layer F.Cu) (tedit 55FAB21E) (tstamp 55FDB752) + (at 41 48) + (descr "5-pin SOT23 package") + (tags SOT-23-5) + (path /55CFAED1/55FAB6D1) + (attr smd) + (fp_text reference U4 (at 7.6 -3.3 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value TLV70233-SOT-23 (at -0.05 2.35) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.8 -1.6) (end 1.8 -1.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.8 -1.6) (end 1.8 1.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.8 1.6) (end -1.8 1.6) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.8 1.6) (end -1.8 -1.6) (layer F.CrtYd) (width 0.05)) + (fp_circle (center -0.3 -1.7) (end -0.2 -1.7) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.25 -1.45) (end -0.25 -1.45) (layer F.SilkS) (width 0.15)) + (fp_line (start 0.25 1.45) (end 0.25 -1.45) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 1.45) (end 0.25 1.45) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.25 -1.45) (end -0.25 1.45) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.1 -0.95) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 7 +BATT)) + (pad 2 smd rect (at -1.1 0) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 3 smd rect (at -1.1 0.95) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 7 +BATT)) + (pad 4 smd rect (at 1.1 0.95) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask)) + (pad 5 smd rect (at 1.1 -0.95) (size 1.06 0.65) (layers F.Cu F.Paste F.Mask) + (net 2 +3V3)) + (model TO_SOT_Packages_SMD.3dshapes/SOT-23-5.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E1B) + (at 50.5 25 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FCCDBC) + (attr smd) + (fp_text reference C16 (at -2.9 0 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1u (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 35 /BTN2)) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E21) + (at 50.5 45 90) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FCCBEB) + (attr smd) + (fp_text reference C17 (at 0.5 -2 180) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1u (at 0 -1.9 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 34 /BTN1)) + (pad 2 smd rect (at 0.75 0 90) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E27) + (at 45.75 32.75 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FBFB19) + (attr smd) + (fp_text reference C18 (at 2.15 0.05 360) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1u (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E2D) + (at 44 32.75 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FBAEDC) + (attr smd) + (fp_text reference C19 (at -2.15 0 360) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 2u2 (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 36 "Net-(C19-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E33) + (at 30.25 32.75 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FB96CA) + (attr smd) + (fp_text reference C20 (at 3.05 0.05 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 4u7 (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 37 "Net-(C20-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E39) + (at 26.75 32.75 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FB8922) + (attr smd) + (fp_text reference C21 (at 3.05 -0.05 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 2u2 (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 38 "Net-(C21-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E3F) + (at 49.25 32.75 90) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FBD1F4) + (attr smd) + (fp_text reference C22 (at -2.15 -0.05 180) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1u (at 0 -1.9 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 39 "Net-(C22-Pad1)")) + (pad 2 smd rect (at 0.75 0 90) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 40 "Net-(C22-Pad2)")) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E45) + (at 47.5 32.75 90) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FBD8B2) + (attr smd) + (fp_text reference C23 (at 2.05 0 180) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1u (at 0 -1.9 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 41 "Net-(C23-Pad1)")) + (pad 2 smd rect (at 0.75 0 90) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 42 "Net-(C23-Pad2)")) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitors_SMD:C_0603 (layer B.Cu) (tedit 5415D631) (tstamp 55FC6E4B) + (at 28.5 32.75 270) + (descr "Capacitor SMD 0603, reflow soldering, AVX (see smccp.pdf)") + (tags "capacitor 0603") + (path /55FB9F0B) + (attr smd) + (fp_text reference C24 (at 3.05 0 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 100n (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.45 0.75) (end 1.45 0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 -0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.45 0.75) (end -1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.45 0.75) (end 1.45 -0.75) (layer B.CrtYd) (width 0.05)) + (fp_line (start -0.35 0.6) (end 0.35 0.6) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.35 -0.6) (end -0.35 -0.6) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 38 "Net-(C21-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.8 0.75) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Capacitors_SMD.3dshapes/C_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Diodes_SMD:SOD-323 (layer B.Cu) (tedit 5530FC5E) (tstamp 55FC6E51) + (at 53.25 30) + (descr SOD-323) + (tags SOD-323) + (path /55FC9042) + (attr smd) + (fp_text reference D1 (at -2.55 0) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1N4148 (at 0.1 -1.9) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start 0.25 0) (end 0.5 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0) (end -0.5 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0) (end 0.25 0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.25 0.35) (end 0.25 -0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.25 -0.35) (end -0.25 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0.35) (end -0.25 -0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.5 0.95) (end 1.5 0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.5 0.95) (end 1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.5 -0.95) (end 1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.5 0.95) (end -1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.1 -0.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.3 0.8) (end 1.1 0.8) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.055 0) (size 0.59 0.45) (layers B.Cu B.Paste B.Mask) + (net 43 "Net-(D1-Pad1)")) + (pad 2 smd rect (at 1.055 0) (size 0.59 0.45) (layers B.Cu B.Paste B.Mask) + (net 35 /BTN2)) + ) + + (module Diodes_SMD:SOD-323 (layer B.Cu) (tedit 5530FC5E) (tstamp 55FC6E57) + (at 53.25 40) + (descr SOD-323) + (tags SOD-323) + (path /55FC91A0) + (attr smd) + (fp_text reference D2 (at -2.55 0) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1N4148 (at 0.1 -1.9) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start 0.25 0) (end 0.5 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0) (end -0.5 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0) (end 0.25 0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.25 0.35) (end 0.25 -0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start 0.25 -0.35) (end -0.25 0) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.25 0.35) (end -0.25 -0.35) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.5 0.95) (end 1.5 0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.5 0.95) (end 1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.5 -0.95) (end 1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.5 0.95) (end -1.5 -0.95) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.1 -0.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.3 0.8) (end 1.1 0.8) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -1.055 0) (size 0.59 0.45) (layers B.Cu B.Paste B.Mask) + (net 43 "Net-(D1-Pad1)")) + (pad 2 smd rect (at 1.055 0) (size 0.59 0.45) (layers B.Cu B.Paste B.Mask) + (net 34 /BTN1)) + ) + + (module TO_SOT_Packages_SMD:SOT-23 (layer B.Cu) (tedit 553634F8) (tstamp 55FC6E8C) + (at 46.226696 38) + (descr "SOT-23, Standard") + (tags SOT-23) + (path /55FC47BF) + (attr smd) + (fp_text reference Q1 (at 2.673304 0) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value BC849 (at 0 -2.3) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.65 1.6) (end 1.65 1.6) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.65 1.6) (end 1.65 -1.6) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.65 -1.6) (end -1.65 -1.6) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.65 -1.6) (end -1.65 1.6) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.29916 0.65024) (end 1.2509 0.65024) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.49982 -0.0508) (end -1.49982 0.65024) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.49982 0.65024) (end -1.2509 0.65024) (layer B.SilkS) (width 0.15)) + (fp_line (start 1.29916 0.65024) (end 1.49982 0.65024) (layer B.SilkS) (width 0.15)) + (fp_line (start 1.49982 0.65024) (end 1.49982 -0.0508) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.95 -1.00076) (size 0.8001 0.8001) (layers B.Cu B.Paste B.Mask) + (net 46 "Net-(Q1-Pad1)")) + (pad 2 smd rect (at 0.95 -1.00076) (size 0.8001 0.8001) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (pad 3 smd rect (at 0 0.99822) (size 0.8001 0.8001) (layers B.Cu B.Paste B.Mask) + (net 45 "Net-(P3-Pad2)")) + (model TO_SOT_Packages_SMD.3dshapes/SOT-23.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer B.Cu) (tedit 5415CC62) (tstamp 55FC6E92) + (at 43.226696 38 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55FCF00A) + (attr smd) + (fp_text reference R3 (at 0 1.426696 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 1K (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end -1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.3 0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.675) (end -0.5 -0.675) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.5 0.675) (end 0.5 0.675) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 46 "Net-(Q1-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 47 /VIBR)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer B.Cu) (tedit 5415CC62) (tstamp 55FC6E98) + (at 34.5 32.75 90) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55FCA3EE) + (attr smd) + (fp_text reference R10 (at -3.05 0 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 10K (at 0 -1.9 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end -1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.3 0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.675) (end -0.5 -0.675) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.5 0.675) (end 0.5 0.675) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 90) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 24 /MPU-9250/SDA)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer B.Cu) (tedit 5415CC62) (tstamp 55FC6E9E) + (at 36.25 32.75 90) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55FCA4BD) + (attr smd) + (fp_text reference R11 (at -3.05 0.05 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 10K (at 0 -1.9 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end -1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.3 0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.675) (end -0.5 -0.675) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.5 0.675) (end 0.5 0.675) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 90) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 2 +3V3)) + (pad 2 smd rect (at 0.75 0 90) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 23 /MPU-9250/SCL)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer B.Cu) (tedit 5415CC62) (tstamp 55FC6EA4) + (at 50.5 42 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55FC9C6F) + (attr smd) + (fp_text reference R12 (at 0 1.5 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 50 (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end -1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.3 0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.675) (end -0.5 -0.675) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.5 0.675) (end 0.5 0.675) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistors_SMD:R_0603 (layer B.Cu) (tedit 5415CC62) (tstamp 55FC6EB0) + (at 32 32.75 270) + (descr "Resistor SMD 0603, reflow soldering, Vishay (see dcrcw.pdf)") + (tags "resistor 0603") + (path /55FB6136) + (attr smd) + (fp_text reference R14 (at 3.05 0 270) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value 390K (at 0 -1.9 270) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 0.8) (end 1.3 0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 -0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start -1.3 0.8) (end -1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 1.3 0.8) (end 1.3 -0.8) (layer B.CrtYd) (width 0.05)) + (fp_line (start 0.5 -0.675) (end -0.5 -0.675) (layer B.SilkS) (width 0.15)) + (fp_line (start -0.5 0.675) (end 0.5 0.675) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 44 "Net-(DS1-Pad26)")) + (pad 2 smd rect (at 0.75 0 270) (size 0.5 0.9) (layers B.Cu B.Paste B.Mask) + (net 3 GND)) + (model Resistors_SMD.3dshapes/R_0603.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module "Project Libraries:ts015a" (layer B.Cu) (tedit 55FC44C4) (tstamp 55FC6EB8) + (at 53.25 25 90) + (path /55FC62E9) + (fp_text reference SW1 (at 0 0 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value BUTTON_UP (at 0 3.8 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 1.8) (end -1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start 1.3 1.8) (end 1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.3 2.9) (end 1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 1.8) (end 2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start 2.3 -1.8) (end 2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end -2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end 2.3 -1.8) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.8 0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 35 /BTN2)) + (pad 1 smd rect (at 2.8 0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 35 /BTN2)) + (pad 2 smd rect (at -2.8 -0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + (pad 2 smd rect (at 2.8 -0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + ) + + (module "Project Libraries:ts015a" (layer B.Cu) (tedit 55FC44C4) (tstamp 55FC6EC0) + (at 53.25 45 90) + (path /55FC65FF) + (fp_text reference SW2 (at 0 0 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value BUTTON_DOWN (at 0 3.8 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 1.8) (end -1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start 1.3 1.8) (end 1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.3 2.9) (end 1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 1.8) (end 2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start 2.3 -1.8) (end 2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end -2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end 2.3 -1.8) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.8 0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 34 /BTN1)) + (pad 1 smd rect (at 2.8 0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 34 /BTN1)) + (pad 2 smd rect (at -2.8 -0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + (pad 2 smd rect (at 2.8 -0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + ) + + (module "Project Libraries:ts015a" (layer B.Cu) (tedit 55FC44C4) (tstamp 55FC6EC8) + (at 53.25 35 90) + (path /55FC6544) + (fp_text reference SW3 (at 0 0 90) (layer B.SilkS) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_text value BUTTON_CENTER (at 0 3.8 90) (layer B.Fab) + (effects (font (size 1 1) (thickness 0.15)) (justify mirror)) + ) + (fp_line (start -1.3 1.8) (end -1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start 1.3 1.8) (end 1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start -1.3 2.9) (end 1.3 2.9) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 1.8) (end 2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start 2.3 -1.8) (end 2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end -2.3 1.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end 2.3 -1.8) (layer B.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.8 0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 43 "Net-(D1-Pad1)")) + (pad 1 smd rect (at 2.8 0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 43 "Net-(D1-Pad1)")) + (pad 2 smd rect (at -2.8 -0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + (pad 2 smd rect (at 2.8 -0.85 90) (size 1.2 1) (layers B.Cu B.Paste B.Mask) + (net 48 "Net-(R12-Pad1)")) + ) + + (module "Project Libraries:crystal_2.5x2" (layer F.Cu) (tedit 55FD1E89) (tstamp 55FD20D2) + (at 30.5 21.75) + (path /55F71659) + (fp_text reference X1 (at 9.6 0.25 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 26MHz (at 0 -2) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 1.25 0.1) (end 1.25 -0.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.2 1) (end 0.2 1) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.25 0.1) (end -1.25 -0.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.2 -1) (end 0.2 -1) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.85 0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask) + (net 9 "Net-(C9-Pad1)")) + (pad 3 smd rect (at -0.85 -0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 3 smd rect (at 0.85 0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask) + (net 3 GND)) + (pad 2 smd rect (at 0.85 -0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask) + (net 10 "Net-(C10-Pad1)")) + ) + + (module Mounting_Holes:MountingHole_2-5mm (layer F.Cu) (tedit 55FEC1BA) (tstamp 5600E6CB) + (at 22.9 37.3) + (descr "Mounting hole, Befestigungsbohrung, 2,5mm, No Annular, Kein Restring,") + (tags "Mounting hole, Befestigungsbohrung, 2,5mm, No Annular, Kein Restring,") + (fp_text reference REF** (at 0 -3.50012) (layer F.SilkS) hide + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value MountingHole_2-5mm (at 0.09906 3.59918) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_circle (center 0 0) (end 2.5 0) (layer Cmts.User) (width 0.381)) + (pad 1 thru_hole circle (at 0 0) (size 2.5 2.5) (drill 2.5) (layers)) + ) + + (module "Project Libraries:wifilogo" (layer F.Cu) (tedit 0) (tstamp 56011916) + (at 52.8 29 90) + (fp_text reference G*** (at 0 0 90) (layer F.SilkS) hide + (effects (font (thickness 0.3))) + ) + (fp_text value LOGO (at 0.75 0 90) (layer F.SilkS) hide + (effects (font (thickness 0.3))) + ) + (fp_poly (pts (xy 0.038917 -1.485993) (xy 0.136323 -1.479296) (xy 0.2314 -1.466279) (xy 0.325018 -1.446787) + (xy 0.418047 -1.420667) (xy 0.511356 -1.387763) (xy 0.526143 -1.381949) (xy 0.607126 -1.346625) + (xy 0.687969 -1.30547) (xy 0.767683 -1.259173) (xy 0.845284 -1.208422) (xy 0.919785 -1.153906) + (xy 0.9902 -1.096313) (xy 1.055543 -1.036333) (xy 1.114827 -0.974654) (xy 1.1236 -0.964769) + (xy 1.155061 -0.928914) (xy 1.337241 -0.928914) (xy 1.382403 -0.928882) (xy 1.421055 -0.928742) + (xy 1.453941 -0.928433) (xy 1.481808 -0.927892) (xy 1.505401 -0.927058) (xy 1.525467 -0.925867) + (xy 1.542752 -0.924258) (xy 1.558 -0.922168) (xy 1.571959 -0.919535) (xy 1.585374 -0.916296) + (xy 1.598991 -0.91239) (xy 1.613556 -0.907754) (xy 1.621288 -0.905189) (xy 1.661207 -0.889746) + (xy 1.703678 -0.86956) (xy 1.746898 -0.845692) (xy 1.789065 -0.819205) (xy 1.828375 -0.791161) + (xy 1.862402 -0.763179) (xy 1.90113 -0.725171) (xy 1.938576 -0.681854) (xy 1.973974 -0.634477) + (xy 2.006561 -0.58429) (xy 2.035573 -0.53254) (xy 2.060245 -0.480477) (xy 2.079815 -0.42935) + (xy 2.09165 -0.388455) (xy 2.094412 -0.376708) (xy 2.096859 -0.365301) (xy 2.099009 -0.353746) + (xy 2.100877 -0.341555) (xy 2.10248 -0.328241) (xy 2.103836 -0.313318) (xy 2.104959 -0.296298) + (xy 2.105868 -0.276693) (xy 2.106579 -0.254016) (xy 2.107108 -0.22778) (xy 2.107472 -0.197498) + (xy 2.107688 -0.162683) (xy 2.107771 -0.122847) (xy 2.10774 -0.077502) (xy 2.10761 -0.026162) + (xy 2.107398 0.03166) (xy 2.107241 0.068943) (xy 2.106977 0.12721) (xy 2.106714 0.178672) + (xy 2.106443 0.223784) (xy 2.106154 0.262996) (xy 2.105839 0.296764) (xy 2.105488 0.325539) + (xy 2.105093 0.349773) (xy 2.104644 0.369922) (xy 2.104133 0.386436) (xy 2.103549 0.399769) + (xy 2.102885 0.410374) (xy 2.102131 0.418703) (xy 2.101277 0.425211) (xy 2.100316 0.430348) + (xy 2.099956 0.43189) (xy 2.090511 0.465394) (xy 2.078792 0.497449) (xy 2.064302 0.528853) + (xy 2.046545 0.560404) (xy 2.025023 0.592899) (xy 1.999239 0.627136) (xy 1.968697 0.663912) + (xy 1.932899 0.704026) (xy 1.925134 0.712444) (xy 1.87556 0.761739) (xy 1.82435 0.804205) + (xy 1.770893 0.840195) (xy 1.714577 0.870067) (xy 1.654793 0.894173) (xy 1.590931 0.912868) + (xy 1.573238 0.916963) (xy 1.563891 0.918994) (xy 1.555394 0.920722) (xy 1.547079 0.922179) + (xy 1.53828 0.923395) (xy 1.528327 0.9244) (xy 1.516553 0.925226) (xy 1.502291 0.925904) + (xy 1.484872 0.926465) (xy 1.463629 0.926938) (xy 1.437894 0.927356) (xy 1.407 0.927749) + (xy 1.370278 0.928148) (xy 1.327061 0.928584) (xy 1.320424 0.92865) (xy 1.111405 0.930728) + (xy 1.092924 0.953762) (xy 1.031812 1.02456) (xy 0.964702 1.092371) (xy 0.892488 1.156474) + (xy 0.816064 1.21615) (xy 0.736327 1.270679) (xy 0.65417 1.31934) (xy 0.609295 1.342835) + (xy 0.527232 1.381088) (xy 0.446332 1.413087) (xy 0.365051 1.439309) (xy 0.281846 1.460235) + (xy 0.195174 1.476342) (xy 0.1651 1.480744) (xy 0.142605 1.483224) (xy 0.114476 1.485384) + (xy 0.082193 1.487188) (xy 0.047234 1.488603) (xy 0.011078 1.489594) (xy -0.024797 1.490127) + (xy -0.05891 1.490169) (xy -0.089784 1.489684) (xy -0.11594 1.48864) (xy -0.130629 1.48756) + (xy -0.231476 1.474484) (xy -0.329938 1.454557) (xy -0.425942 1.427809) (xy -0.519413 1.394268) + (xy -0.610277 1.353965) (xy -0.698459 1.306927) (xy -0.783886 1.253185) (xy -0.850504 1.205146) + (xy -0.903885 1.162055) (xy -0.956706 1.115009) (xy -1.007315 1.065606) (xy -1.054063 1.015447) + (xy -1.089569 0.973364) (xy -1.122239 0.932543) (xy -1.314955 0.932528) (xy -1.361324 0.932492) + (xy -1.401164 0.932357) (xy -1.435202 0.932072) (xy -1.464166 0.931587) (xy -1.488783 0.930851) + (xy -1.509782 0.929813) (xy -1.52789 0.928423) (xy -1.543834 0.926628) (xy -1.558343 0.92438) + (xy -1.572143 0.921626) (xy -1.585963 0.918317) (xy -1.60053 0.914401) (xy -1.608999 0.912007) + (xy -1.674042 0.889681) (xy -1.736684 0.860568) (xy -1.796988 0.824632) (xy -1.842553 0.791028) + (xy -0.178339 0.791028) (xy 0.568509 0.79096) (xy 0.64316 0.790936) (xy 0.716746 0.790879) + (xy 0.788867 0.790792) (xy 0.85912 0.790675) (xy 0.927103 0.79053) (xy 0.992416 0.79036) + (xy 1.054657 0.790165) (xy 1.113423 0.789947) (xy 1.168314 0.789708) (xy 1.218928 0.78945) + (xy 1.264863 0.789174) (xy 1.305717 0.788882) (xy 1.341089 0.788576) (xy 1.370578 0.788257) + (xy 1.393781 0.787927) (xy 1.410297 0.787588) (xy 1.415143 0.787443) (xy 1.456004 0.785929) + (xy 1.490579 0.784292) (xy 1.519838 0.782298) (xy 1.544751 0.779711) (xy 1.566289 0.776294) + (xy 1.58542 0.771814) (xy 1.603116 0.766033) (xy 1.620346 0.758718) (xy 1.638081 0.749631) + (xy 1.657291 0.738538) (xy 1.678945 0.725203) (xy 1.683639 0.722257) (xy 1.739753 0.683286) + (xy 1.790315 0.640558) (xy 1.835069 0.594379) (xy 1.873761 0.545059) (xy 1.906135 0.492905) + (xy 1.931938 0.438226) (xy 1.942719 0.40876) (xy 1.945835 0.398837) (xy 1.948582 0.388741) + (xy 1.950982 0.377972) (xy 1.95306 0.366028) (xy 1.954838 0.352407) (xy 1.956338 0.336609) + (xy 1.957584 0.318133) (xy 1.958598 0.296477) (xy 1.959404 0.27114) (xy 1.960024 0.24162) + (xy 1.960481 0.207417) (xy 1.960798 0.168028) (xy 1.960998 0.122954) (xy 1.961104 0.071693) + (xy 1.961139 0.013742) (xy 1.96114 0.005443) (xy 1.961092 -0.057144) (xy 1.960946 -0.112704) + (xy 1.960698 -0.161468) (xy 1.960346 -0.203666) (xy 1.959887 -0.239529) (xy 1.959317 -0.269286) + (xy 1.958633 -0.293168) (xy 1.957833 -0.311405) (xy 1.956913 -0.324228) (xy 1.956751 -0.325831) + (xy 1.948137 -0.374158) (xy 1.93286 -0.423021) (xy 1.911398 -0.471673) (xy 1.884229 -0.519365) + (xy 1.851833 -0.565349) (xy 1.814689 -0.608878) (xy 1.773274 -0.649204) (xy 1.728069 -0.685577) + (xy 1.725157 -0.687682) (xy 1.70487 -0.701028) (xy 1.680687 -0.715007) (xy 1.654415 -0.728737) + (xy 1.62786 -0.741337) (xy 1.602828 -0.751926) (xy 1.581125 -0.759623) (xy 1.572986 -0.761894) + (xy 1.563956 -0.764062) (xy 1.555064 -0.766021) (xy 1.545908 -0.767782) (xy 1.536085 -0.769357) + (xy 1.525194 -0.770758) (xy 1.512832 -0.771999) (xy 1.498596 -0.77309) (xy 1.482086 -0.774044) + (xy 1.462898 -0.774875) (xy 1.440631 -0.775593) (xy 1.414882 -0.77621) (xy 1.38525 -0.776741) + (xy 1.351332 -0.777195) (xy 1.312726 -0.777587) (xy 1.26903 -0.777927) (xy 1.219841 -0.778229) + (xy 1.164759 -0.778504) (xy 1.10338 -0.778764) (xy 1.035302 -0.779023) (xy 1.006928 -0.779125) + (xy 0.542471 -0.780791) (xy 0.502061 -0.767718) (xy 0.450904 -0.748419) (xy 0.403064 -0.724469) + (xy 0.357384 -0.695161) (xy 0.312708 -0.659784) (xy 0.285623 -0.635084) (xy 0.249078 -0.598047) + (xy 0.215442 -0.559771) (xy 0.185242 -0.521043) (xy 0.159001 -0.482649) (xy 0.137247 -0.445376) + (xy 0.120503 -0.410009) (xy 0.109296 -0.377335) (xy 0.106997 -0.36773) (xy 0.10495 -0.35634) + (xy 0.103085 -0.342162) (xy 0.101384 -0.324801) (xy 0.099834 -0.303858) (xy 0.09842 -0.278937) + (xy 0.097125 -0.249641) (xy 0.095936 -0.215573) (xy 0.094837 -0.176336) (xy 0.093813 -0.131533) + (xy 0.092849 -0.080768) (xy 0.09193 -0.023642) (xy 0.09104 0.04024) (xy 0.090811 0.058057) + (xy 0.090094 0.113362) (xy 0.089403 0.161967) (xy 0.088698 0.204426) (xy 0.087935 0.241296) + (xy 0.087074 0.273132) (xy 0.086074 0.300491) (xy 0.084891 0.323927) (xy 0.083485 0.343997) + (xy 0.081814 0.361257) (xy 0.079836 0.376262) (xy 0.077509 0.389568) (xy 0.074792 0.401732) + (xy 0.071644 0.413308) (xy 0.068022 0.424852) (xy 0.063884 0.436921) (xy 0.061998 0.44224) + (xy 0.042637 0.491538) (xy 0.020531 0.538052) (xy -0.005017 0.582855) (xy -0.034699 0.627024) + (xy -0.06921 0.671631) (xy -0.109244 0.717753) (xy -0.130996 0.741136) (xy -0.178339 0.791028) + (xy -1.842553 0.791028) (xy -1.855018 0.781836) (xy -1.902542 0.740095) (xy -1.954413 0.686415) + (xy -1.999627 0.629855) (xy -2.038192 0.570396) (xy -2.070119 0.508022) (xy -2.095419 0.442714) + (xy -2.112806 0.380218) (xy -2.114153 0.37416) (xy -2.115336 0.368158) (xy -2.116368 0.361714) + (xy -2.117262 0.354331) (xy -2.118032 0.345511) (xy -2.118688 0.334758) (xy -2.119245 0.321575) + (xy -2.119715 0.305464) (xy -2.120111 0.285927) (xy -2.120446 0.262469) (xy -2.120731 0.234592) + (xy -2.120981 0.201798) (xy -2.121207 0.16359) (xy -2.121422 0.119471) (xy -2.12164 0.068945) + (xy -2.121802 0.029028) (xy -2.122025 -0.02763) (xy -2.122197 -0.077554) (xy -2.122298 -0.121266) + (xy -2.122311 -0.159288) (xy -2.122217 -0.192143) (xy -2.121997 -0.220353) (xy -2.121632 -0.244441) + (xy -2.121103 -0.264929) (xy -2.120393 -0.28234) (xy -2.119481 -0.297196) (xy -2.11835 -0.31002) + (xy -2.11698 -0.321333) (xy -2.115354 -0.331659) (xy -2.113451 -0.341521) (xy -2.111254 -0.351439) + (xy -2.108744 -0.361938) (xy -2.107631 -0.366486) (xy -2.089738 -0.425324) (xy -2.071766 -0.468333) + (xy -1.744449 -0.468333) (xy -1.742278 -0.45605) (xy -1.741964 -0.4546) (xy -1.737998 -0.436656) + (xy -1.732665 -0.412829) (xy -1.7261 -0.383706) (xy -1.718437 -0.349873) (xy -1.709812 -0.311918) + (xy -1.70036 -0.270428) (xy -1.690216 -0.22599) (xy -1.679514 -0.179192) (xy -1.66839 -0.130621) + (xy -1.656978 -0.080863) (xy -1.645415 -0.030506) (xy -1.633834 0.019863) (xy -1.622371 0.069657) + (xy -1.611161 0.118288) (xy -1.600339 0.165169) (xy -1.590039 0.209714) (xy -1.580397 0.251335) + (xy -1.571548 0.289445) (xy -1.563627 0.323457) (xy -1.556768 0.352783) (xy -1.551108 0.376837) + (xy -1.54678 0.395031) (xy -1.54392 0.406778) (xy -1.543776 0.407351) (xy -1.540221 0.42059) + (xy -1.536572 0.428515) (xy -1.530936 0.432841) (xy -1.521423 0.435284) (xy -1.5113 0.436814) + (xy -1.504209 0.437256) (xy -1.491511 0.437474) (xy -1.474329 0.437492) (xy -1.453786 0.437336) + (xy -1.431006 0.437028) (xy -1.407111 0.436592) (xy -1.383225 0.436053) (xy -1.36047 0.435435) + (xy -1.33997 0.434761) (xy -1.322848 0.434056) (xy -1.310226 0.433344) (xy -1.303228 0.432648) + (xy -1.302211 0.432344) (xy -1.301041 0.428367) (xy -1.298681 0.418052) (xy -1.295294 0.402187) + (xy -1.291043 0.381563) (xy -1.286089 0.356972) (xy -1.280596 0.329203) (xy -1.274727 0.299047) + (xy -1.273737 0.293914) (xy -1.264092 0.24401) (xy -1.254702 0.195723) (xy -1.245668 0.14957) + (xy -1.237095 0.106064) (xy -1.229086 0.065722) (xy -1.221744 0.029057) (xy -1.215173 -0.003415) + (xy -1.209476 -0.031179) (xy -1.204758 -0.053721) (xy -1.20112 -0.070525) (xy -1.198667 -0.081077) + (xy -1.197709 -0.08447) (xy -1.195627 -0.08881) (xy -1.193873 -0.087869) (xy -1.191596 -0.080848) + (xy -1.190837 -0.078014) (xy -1.189508 -0.072024) (xy -1.18694 -0.059535) (xy -1.183259 -0.041178) + (xy -1.178586 -0.017583) (xy -1.173046 0.01062) (xy -1.166763 0.042801) (xy -1.159859 0.07833) + (xy -1.152459 0.116576) (xy -1.144686 0.15691) (xy -1.14102 0.175986) (xy -1.133131 0.21689) + (xy -1.125546 0.255855) (xy -1.118391 0.29227) (xy -1.111787 0.325523) (xy -1.105858 0.355002) + (xy -1.100729 0.380094) (xy -1.096522 0.400188) (xy -1.093361 0.414672) (xy -1.09137 0.422933) + (xy -1.090863 0.424513) (xy -1.083418 0.432753) (xy -1.075837 0.435877) (xy -1.068086 0.436724) + (xy -1.054382 0.437404) (xy -1.035975 0.437917) (xy -1.014115 0.438264) (xy -0.990053 0.438447) + (xy -0.96504 0.438467) (xy -0.940324 0.438325) (xy -0.917156 0.438023) (xy -0.896787 0.437561) + (xy -0.880467 0.436942) (xy -0.869446 0.436166) (xy -0.866034 0.435659) (xy -0.856768 0.433213) + (xy -0.851053 0.431153) (xy -0.850485 0.430779) (xy -0.849246 0.426883) (xy -0.846521 0.416446) + (xy -0.842426 0.39998) (xy -0.83708 0.377995) (xy -0.830602 0.351005) (xy -0.82311 0.31952) + (xy -0.814722 0.284053) (xy -0.805557 0.245114) (xy -0.795732 0.203215) (xy -0.785367 0.158868) + (xy -0.774579 0.112585) (xy -0.763487 0.064877) (xy -0.752209 0.016256) (xy -0.740864 -0.032768) + (xy -0.729569 -0.081681) (xy -0.718444 -0.129972) (xy -0.707606 -0.177131) (xy -0.697173 -0.222645) + (xy -0.695813 -0.2286) (xy -0.511629 -0.2286) (xy -0.511629 0.439057) (xy -0.286657 0.439057) + (xy -0.286657 -0.2286) (xy -0.511629 -0.2286) (xy -0.695813 -0.2286) (xy -0.687265 -0.266002) + (xy -0.677999 -0.306692) (xy -0.669494 -0.344202) (xy -0.661868 -0.378021) (xy -0.655239 -0.407637) + (xy -0.653885 -0.413755) (xy -0.530764 -0.413755) (xy -0.526858 -0.390636) (xy -0.522233 -0.378604) + (xy -0.508641 -0.357802) (xy -0.489695 -0.338835) (xy -0.467287 -0.323127) (xy -0.443308 -0.312104) + (xy -0.428894 -0.30832) (xy -0.40835 -0.306476) (xy -0.384207 -0.307183) (xy -0.359559 -0.310187) + (xy -0.337499 -0.315232) (xy -0.334988 -0.316023) (xy -0.308874 -0.327606) (xy -0.286826 -0.343528) + (xy -0.269791 -0.362892) (xy -0.258716 -0.384801) (xy -0.257213 -0.389724) (xy -0.254692 -0.407635) + (xy -0.25531 -0.428189) (xy -0.258759 -0.448107) (xy -0.264098 -0.462913) (xy -0.274584 -0.478292) + (xy -0.289535 -0.493758) (xy -0.306535 -0.507097) (xy -0.321328 -0.515343) (xy -0.344367 -0.522865) + (xy -0.370397 -0.527509) (xy -0.397388 -0.529225) (xy -0.423306 -0.527958) (xy -0.44612 -0.52366) + (xy -0.459099 -0.518845) (xy -0.475559 -0.508835) (xy -0.492455 -0.495163) (xy -0.507734 -0.479773) + (xy -0.519344 -0.464607) (xy -0.522704 -0.458624) (xy -0.529385 -0.437314) (xy -0.530764 -0.413755) + (xy -0.653885 -0.413755) (xy -0.649726 -0.432538) (xy -0.645447 -0.452214) (xy -0.64252 -0.466153) + (xy -0.641064 -0.473842) (xy -0.640944 -0.475241) (xy -0.644897 -0.475728) (xy -0.655259 -0.476242) + (xy -0.671181 -0.476761) (xy -0.691815 -0.477265) (xy -0.716313 -0.477732) (xy -0.743827 -0.478141) + (xy -0.766836 -0.478405) (xy -0.890814 -0.479653) (xy -0.912138 -0.333262) (xy -0.918806 -0.287632) + (xy -0.92536 -0.243056) (xy -0.931707 -0.200151) (xy -0.937755 -0.159533) (xy -0.943409 -0.121818) + (xy -0.948577 -0.087623) (xy -0.953166 -0.057564) (xy -0.957083 -0.032256) (xy -0.960235 -0.012316) + (xy -0.962527 0.001641) (xy -0.963821 0.008773) (xy -0.965921 0.015403) (xy -0.968225 0.015235) + (xy -0.968865 0.014216) (xy -0.970472 0.009045) (xy -0.973467 -0.003065) (xy -0.977811 -0.021939) + (xy -0.983467 -0.047399) (xy -0.990397 -0.079269) (xy -0.998562 -0.117374) (xy -1.007925 -0.161536) + (xy -1.018447 -0.21158) (xy -1.030092 -0.267329) (xy -1.04282 -0.328607) (xy -1.045309 -0.340626) + (xy -1.051701 -0.371406) (xy -1.057653 -0.399889) (xy -1.063004 -0.425309) (xy -1.06759 -0.446899) + (xy -1.071247 -0.463894) (xy -1.073814 -0.475527) (xy -1.075127 -0.481032) (xy -1.075248 -0.481371) + (xy -1.078986 -0.48165) (xy -1.089105 -0.481964) (xy -1.104727 -0.482298) (xy -1.124976 -0.482636) + (xy -1.148975 -0.482962) (xy -1.175847 -0.483261) (xy -1.190305 -0.483398) (xy -1.304352 -0.484414) + (xy -1.317546 -0.420914) (xy -1.321153 -0.403547) (xy -1.325999 -0.380201) (xy -1.33185 -0.352005) + (xy -1.338473 -0.320085) (xy -1.345632 -0.285569) (xy -1.353095 -0.249586) (xy -1.360627 -0.213263) + (xy -1.364218 -0.195943) (xy -1.374079 -0.14846) (xy -1.382591 -0.107669) (xy -1.389845 -0.07315) + (xy -1.395933 -0.044481) (xy -1.400949 -0.021244) (xy -1.404983 -0.003017) (xy -1.40813 0.01062) + (xy -1.410481 0.020087) (xy -1.412128 0.025805) (xy -1.413164 0.028194) (xy -1.413477 0.028275) + (xy -1.414406 0.024393) (xy -1.416308 0.014014) (xy -1.419075 -0.002183) (xy -1.422603 -0.023518) + (xy -1.426784 -0.049313) (xy -1.431512 -0.078886) (xy -1.436681 -0.11156) (xy -1.442185 -0.146655) + (xy -1.447916 -0.18349) (xy -1.453769 -0.221388) (xy -1.459637 -0.259669) (xy -1.465413 -0.297652) + (xy -1.470993 -0.33466) (xy -1.476268 -0.370011) (xy -1.481133 -0.403028) (xy -1.482772 -0.414274) + (xy -1.492617 -0.482018) (xy -1.525544 -0.484476) (xy -1.542082 -0.48537) (xy -1.562503 -0.485942) + (xy -1.585719 -0.486215) (xy -1.610644 -0.486212) (xy -1.636189 -0.485955) (xy -1.661267 -0.485466) + (xy -1.684791 -0.484768) (xy -1.705674 -0.483883) (xy -1.722826 -0.482834) (xy -1.735162 -0.481644) + (xy -1.741593 -0.480334) (xy -1.742142 -0.48) (xy -1.7444 -0.475707) (xy -1.744449 -0.468333) + (xy -2.071766 -0.468333) (xy -2.065304 -0.483795) (xy -2.034934 -0.54124) (xy -1.999229 -0.597002) + (xy -1.958792 -0.650423) (xy -1.914226 -0.700844) (xy -1.866132 -0.747609) (xy -1.815113 -0.790059) + (xy -1.761771 -0.827537) (xy -1.70671 -0.859383) (xy -1.650531 -0.884941) (xy -1.62411 -0.894528) + (xy -1.60839 -0.89974) (xy -1.594542 -0.904163) (xy -1.581821 -0.907867) (xy -1.569477 -0.910921) + (xy -1.556764 -0.913395) (xy -1.542933 -0.915357) (xy -1.527238 -0.916878) (xy -1.50893 -0.918026) + (xy -1.487263 -0.91887) (xy -1.461487 -0.919481) (xy -1.430857 -0.919927) (xy -1.394623 -0.920278) + (xy -1.352039 -0.920603) (xy -1.342104 -0.920675) (xy -1.151137 -0.922064) (xy -1.123912 -0.957239) + (xy -1.078534 -1.011765) (xy -1.027099 -1.066241) (xy -0.970746 -1.119686) (xy -0.910616 -1.171123) + (xy -0.847849 -1.219572) (xy -0.783585 -1.264054) (xy -0.7242 -1.300584) (xy -0.63586 -1.347818) + (xy -0.546693 -1.387942) (xy -0.456262 -1.421079) (xy -0.364133 -1.447352) (xy -0.269868 -1.466882) + (xy -0.173032 -1.479791) (xy -0.073189 -1.486204) (xy -0.061686 -1.486525) (xy 0.038917 -1.485993)) (layer F.SilkS) (width 0.01)) + (fp_poly (pts (xy 1.6002 0.442686) (xy 1.367971 0.442686) (xy 1.367971 -0.232229) (xy 1.6002 -0.232229) + (xy 1.6002 0.442686)) (layer F.SilkS) (width 0.01)) + (fp_poly (pts (xy 1.226457 -0.268514) (xy 0.671286 -0.268514) (xy 0.671286 -0.054429) (xy 1.161143 -0.054429) + (xy 1.161143 0.163286) (xy 0.671286 0.163286) (xy 0.671286 0.435428) (xy 0.414417 0.435428) + (xy 0.412164 0.015421) (xy 0.41185 -0.040119) (xy 0.411513 -0.094249) (xy 0.411159 -0.146453) + (xy 0.41079 -0.196217) (xy 0.410414 -0.243026) (xy 0.410033 -0.286365) (xy 0.409654 -0.32572) + (xy 0.409281 -0.360576) (xy 0.408919 -0.390419) (xy 0.408572 -0.414733) (xy 0.408245 -0.433003) + (xy 0.407944 -0.444716) (xy 0.407843 -0.447222) (xy 0.405775 -0.489857) (xy 1.226457 -0.489857) + (xy 1.226457 -0.268514)) (layer F.SilkS) (width 0.01)) + (fp_poly (pts (xy 1.50954 -0.535345) (xy 1.516456 -0.534431) (xy 1.545891 -0.527173) (xy 1.573078 -0.515271) + (xy 1.596762 -0.499537) (xy 1.615691 -0.480783) (xy 1.627315 -0.462643) (xy 1.631434 -0.450686) + (xy 1.634571 -0.43531) (xy 1.635729 -0.424543) (xy 1.634032 -0.397289) (xy 1.625984 -0.372467) + (xy 1.612214 -0.350536) (xy 1.593354 -0.331956) (xy 1.570035 -0.317184) (xy 1.54289 -0.30668) + (xy 1.512548 -0.300902) (xy 1.479641 -0.300309) (xy 1.466509 -0.30155) (xy 1.437799 -0.308323) + (xy 1.410606 -0.320726) (xy 1.386409 -0.337781) (xy 1.366689 -0.358507) (xy 1.356536 -0.374305) + (xy 1.349789 -0.393877) (xy 1.347686 -0.416407) (xy 1.350217 -0.439286) (xy 1.356923 -0.459014) + (xy 1.372616 -0.483081) (xy 1.393664 -0.503299) (xy 1.418973 -0.519151) (xy 1.44745 -0.53012) + (xy 1.478003 -0.53569) (xy 1.50954 -0.535345)) (layer F.SilkS) (width 0.01)) + ) + + (gr_text ESP8266 (at 35.8 34.6) (layer F.SilkS) + (effects (font (size 1.5 1.5) (thickness 0.3))) + ) + (gr_line (start 43.9 19.9) (end 52 19.9) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 43.7 20.2) (end 43.9 19.9) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 31.3 20.2) (end 43.7 20.2) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 31.3 20.2) (end 31.1 19.9) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 31.1 19.9) (end 23 19.9) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 52 50.3) (end 23 50.3) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC361)) + (gr_line (start 51.1 52.1) (end 23.9 52.1) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC360)) + (gr_line (start 23.9 52.1) (end 23 50.3) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC35F)) + (gr_line (start 52 50.3) (end 51.1 52.1) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC35E)) + (gr_line (start 55 50.3) (end 53 54.3) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC35D)) + (gr_line (start 22 54.3) (end 20 50.3) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC35C)) + (gr_line (start 53 54.3) (end 22 54.3) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC35B)) + (gr_line (start 23.9 18.1) (end 51.1 18.1) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 51.1 18.1) (end 52 19.9) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC333)) + (gr_line (start 23 19.9) (end 23.9 18.1) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC2D0)) + (gr_line (start 22 15.9) (end 53 15.9) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 53 15.9) (end 55 19.9) (layer Edge.Cuts) (width 0.15) (tstamp 55FDC2A1)) + (gr_line (start 20 19.9) (end 22 15.9) (layer Edge.Cuts) (width 0.15)) + (gr_line (start 55 19.9) (end 55 50.3) (layer Edge.Cuts) (width 0.15) (tstamp 55FD2C18)) + (gr_line (start 20 19.9) (end 20 50.3) (layer Edge.Cuts) (width 0.15)) + + (segment (start 48.2 48.4) (end 48.7 48.4) (width 0.6) (layer F.Cu) (net 0)) + (segment (start 48.7 48.4) (end 48.8 48.3) (width 0.6) (layer F.Cu) (net 0)) + (segment (start 23.45 26) (end 23.4 26) (width 0.3) (layer F.Cu) (net 1)) + (segment (start 23.4 26) (end 21.5 27.9) (width 0.3) (layer F.Cu) (net 1)) + (segment (start 21.5 27.9) (end 21.5 29.75) (width 0.3) (layer F.Cu) (net 1)) + (segment (start 21.5 29.75) (end 21.5 30.75) (width 0.3) (layer F.Cu) (net 1)) + (segment (start 32.2 29.6) (end 32.624264 29.6) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 32.624264 29.6) (end 32.9 29.324264) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 32.9 29.324264) (end 32.9 28.993982) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 32.9 28.993982) (end 32.656018 28.75) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 32.656018 28.75) (end 31.9 28.75) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.043617 35.915011) (end 46.87001 35.088618) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.87001 35.088618) (end 47.1 35.088618) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 48.936381 35.088618) (end 47.1 35.088618) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 48.936381 35.088618) (end 48.936381 35.213619) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 49.3 34.05) (end 49.3 34.724999) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 49.3 34.724999) (end 48.936381 35.088618) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 51.3 34.85) (end 50.1 34.85) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 50.1 34.85) (end 49.3 34.05) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 51.3 34.85) (end 50.575 34.85) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 43.726696 37.424302) (end 44.414425 36.736573) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 44.414425 36.736573) (end 45.076009 36.074989) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.043617 35.915011) (end 45.235987 35.915011) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 45.235987 35.915011) (end 44.414425 36.736573) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 28.5 31) (end 28.5 35) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 28.5 35) (end 28.934398 35) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 29.455735 35.020001) (end 29.475736 35) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 28.934398 35) (end 28.954399 35.020001) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 28.954399 35.020001) (end 29.455735 35.020001) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 29.475736 35) (end 29.9 35) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 42.1 47.05) (end 43.55 47.05) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 43.55 47.05) (end 43.75 47.25) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 45.75 45.75) (end 45.25 45.75) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 45.25 45.75) (end 43.75 47.25) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 43.726696 41.5) (end 43.726696 43.726696) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 43.726696 43.726696) (end 45.75 45.75) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 26.25 24.520075) (end 26.25 24.415602) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.25 24.415602) (end 26.179999 24.345601) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.179999 24.345601) (end 26.179999 23.654399) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.179999 23.654399) (end 26.576936 23.257462) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.576936 23.257462) (end 28.573871 23.257462) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 28.573871 23.257462) (end 28.998135 23.257462) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.25 26.5) (end 26.25 24.520075) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.25 26.5) (end 26.25 28.14887) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.336119 28.234989) (end 26.25 28.14887) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 26.40113 28.3) (end 26.336119 28.234989) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 26.336119 28.234989) (end 26.334989 28.234989) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 26.7 29.27211) (end 26.7 28.59887) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 26.7 28.59887) (end 26.40113 28.3) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 26 30.52001) (end 26 29.97211) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26 29.97211) (end 26.7 29.27211) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 28.5 31) (end 26.47999 31) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 26.47999 31) (end 26 30.52001) (width 0.6) (layer F.Cu) (net 2)) + (segment (start 33.288063 33.5) (end 33.288063 33.667939) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 33.288063 33.667939) (end 31.936001 35.020001) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 31.936001 35.020001) (end 29.920001 35.020001) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 29.920001 35.020001) (end 29.9 35) (width 0.6) (layer B.Cu) (net 2)) + (via (at 29.9 35) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 34.5 33.5) (end 33.288063 33.5) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 33.288063 33.5) (end 32.797664 33.009601) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 32.797664 33.009601) (end 32.797664 30.197664) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 32.797664 30.197664) (end 32.499999 29.899999) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 32.499999 29.899999) (end 32.2 29.6) (width 0.45) (layer B.Cu) (net 2)) + (segment (start 34.720003 34.5) (end 34.720003 33.720003) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 43.726696 41.5) (end 41.712033 41.5) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 41.712033 41.5) (end 36.452044 36.240011) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 36.452044 36.240011) (end 35.545281 36.240011) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 35.545281 36.240011) (end 34.720003 35.414733) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 34.720003 35.414733) (end 34.720003 34.924264) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 34.720003 34.924264) (end 34.720003 34.5) (width 0.6) (layer B.Cu) (net 2)) + (segment (start 26.25 25.25) (end 26.25 24.520075) (width 0.35) (layer F.Cu) (net 2)) + (via (at 26.25 24.520075) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 27.1 25.25) (end 26.25 25.25) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 43.726696 41.5) (end 43.726696 37.424302) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.020702 22.098198) (end 45.001802 22.098198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 45.001802 22.098198) (end 44.8 22.3) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 44.8 22.3) (end 44.7 22.3) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 44.7 22.3) (end 38.2 22.3) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 38.2 22.3) (end 37.3 23.2) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.7 23.777496) (end 44.7 22.3) (width 0.35) (layer F.Cu) (net 2)) + (via (at 44.7 22.3) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 44.7 23.777496) (end 45.773137 24.850633) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 37.295 23.205) (end 37.3 23.2) (width 0.35) (layer F.Cu) (net 2)) + (via (at 37.3 23.2) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 37.295 24.479) (end 37.295 23.205) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.75 30.7) (end 50.520702 26.929298) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 50.520702 26.929298) (end 50.520702 23.848198) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.270702 25.348198) (end 45.773137 24.850633) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 45.773137 24.850633) (end 45.270702 24.348198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 44.699367 24.850633) (end 45.773137 24.850633) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.15 27.25) (end 44.15 25.4) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.15 25.4) (end 44.699367 24.850633) (width 0.35) (layer B.Cu) (net 2)) + (via (at 45.773137 24.850633) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 44.144425 29.303425) (end 44.33165 29.49065) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.33165 29.49065) (end 45.75 30.909) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.3 30.7) (end 44.3 29.5223) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.3 29.5223) (end 44.33165 29.49065) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 49.3 34.05) (end 49.3 33.25) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 46.75 30.7) (end 44.3 30.7) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 49.3 33.25) (end 46.75 30.7) (width 0.35) (layer F.Cu) (net 2)) + (via (at 44.3 30.7) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 34.5 33.5) (end 34.3 33.5) (width 0.35) (layer B.Cu) (net 2)) + (via (at 32.2 29.6) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 36.25 33.5) (end 34.5 33.5) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 29.005597 23.25) (end 28.998135 23.257462) (width 0.35) (layer B.Cu) (net 2)) + (via (at 26 30.52001) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 28.75 24.6) (end 28.75 23.505597) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 28.75 23.505597) (end 28.998135 23.257462) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 29.25 24.6) (end 29.25 23.509327) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 29.25 23.509327) (end 28.998135 23.257462) (width 0.25) (layer F.Cu) (net 2)) + (via (at 28.998135 23.257462) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 46.920702 24.598198) (end 46.920702 25.0142) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 46.920702 25.0142) (end 46.586704 25.348198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 46.586704 25.348198) (end 46.270702 25.348198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 52.270702 23.848198) (end 50.520702 23.848198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 50.520702 23.848198) (end 50.270702 24.098198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 50.270702 24.098198) (end 49.020702 24.098198) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 53.05 34.85) (end 51.3 34.85) (width 0.35) (layer F.Cu) (net 2)) + (segment (start 24.5 27.5) (end 25.25 27.5) (width 0.2) (layer F.Cu) (net 2)) + (segment (start 25.25 27.5) (end 26.25 26.5) (width 0.2) (layer F.Cu) (net 2)) + (segment (start 43.886001 29.045001) (end 44.144425 29.303425) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.144425 29.303425) (end 44.15 29.29785) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.15 29.29785) (end 44.15 27.25) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 45.75 30.909) (end 45.75 32) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 41.704999 29.045001) (end 42.313999 29.045001) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 42.05 27.25) (end 42.05 28.781002) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 44.15 28.781002) (end 44.15 27.25) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 42.05 28.781002) (end 42.313999 29.045001) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 42.313999 29.045001) (end 43.886001 29.045001) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 43.886001 29.045001) (end 44.15 28.781002) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 40.65 27.25) (end 40.65 28.781002) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 40.65 28.781002) (end 40.913999 29.045001) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 40.913999 29.045001) (end 41.704999 29.045001) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 41.704999 29.045001) (end 42.05 28.7) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 42.05 28.7) (end 42.05 27.25) (width 0.35) (layer B.Cu) (net 2)) + (segment (start 27.1 25.25) (end 26.75 25.25) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 28.75 29.4) (end 28.75 29.861002) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 28.75 29.4) (end 28.75 30.75) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 28.75 30.75) (end 28.5 31) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 27.1 26.75) (end 26.5 26.75) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 26.5 26.75) (end 26.25 26.5) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 27.1 26.25) (end 26.5 26.25) (width 0.3) (layer F.Cu) (net 2)) + (via (at 26.25 26.5) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 2)) + (segment (start 26.5 26.25) (end 26.25 26.5) (width 0.3) (layer F.Cu) (net 2)) + (segment (start 32.95 27.25) (end 32.25 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 33.65 27.25) (end 32.95 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.8 49.9) (end 34.966 49.9) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 34.966 49.9) (end 35.5 49.366) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 28.75 49) (end 28.75 49.85) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 28.75 49.85) (end 28.8 49.9) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 39.297612 33.350886) (end 41.105 31.543498) (width 0.45) (layer F.Cu) (net 3)) + (segment (start 41.105 31.543498) (end 41.105 30.321) (width 0.45) (layer F.Cu) (net 3)) + (segment (start 38.550886 33.350886) (end 39.297612 33.350886) (width 0.45) (layer F.Cu) (net 3)) + (segment (start 47.3 39) (end 47.5 39.2) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 47.5 39.2) (end 49.2 39.2) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 49.2 39.2) (end 49.3 39.1) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 49.3 39.1) (end 49.3 37.15) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 50.520702 22.348198) (end 50.520702 20.920702) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 50.520702 20.920702) (end 50.5 20.9) (width 0.2) (layer F.Cu) (net 3)) + (via (at 50.5 20.9) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 49.4 45.4) (end 48.052703 46.736498) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 45.75 48.75) (end 46.039201 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 46.039201 48.75) (end 48.052703 46.736498) (width 0.6) (layer F.Cu) (net 3)) + (via (at 48.052703 46.736498) (size 2.5) (drill 2.1) (layers F.Cu B.Cu) (net 3)) + (segment (start 47.176696 36.99924) (end 47.176696 36.24919) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 42.3 46.2) (end 42.5 46) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 42.5 46) (end 42.5 45) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 41.5 46.2) (end 42.3 46.2) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 40.999325 46.700675) (end 41.5 46.2) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 40.999325 48) (end 40.999325 46.700675) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 42.5 45.2) (end 42.5 45) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 43 48) (end 43.278739 48.278739) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 43.278739 48.278739) (end 43.75 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 41 47.999325) (end 42.999325 47.999325) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 42.999325 47.999325) (end 43.278739 48.278739) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 39.9 48) (end 40.999325 48) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 40.999325 48) (end 41 47.999325) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 49.4 44.2) (end 48.6 43.4) (width 0.6) (layer F.Cu) (net 3)) + (via (at 48.6 43.4) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 49.4 44.2) (end 49.4 45.4) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 43.75 48.75) (end 45.75 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 38 48.75) (end 38.75 48) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 38.75 48) (end 39.9 48) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 35.5 49.366) (end 36.116 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 36.116 48.75) (end 38 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 35.170999 49.695001) (end 35.5 49.366) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 35.5 49.366) (end 35.5 47.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 26.75 48.75) (end 28.5 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 28.5 48.75) (end 28.75 49) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 26.75 48.75) (end 25.31164 48.75) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 25.31164 48.75) (end 24.31254 47.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 24.31254 42.7509) (end 24.31254 43.9509) (width 0.6) (layer B.Cu) (net 3)) + (segment (start 24.25 44.25) (end 24.25 42.81344) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 22.61254 42.7509) (end 22.295354 42.433714) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 22.295354 42.433714) (end 21.61254 41.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23 44.5) (end 23 43.13836) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23 43.13836) (end 22.295354 42.433714) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 24.31254 42.7509) (end 22.61254 42.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 24.25 42.81344) (end 24.31254 42.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23 44.5) (end 23.25 44.25) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23.25 44.25) (end 24.25 44.25) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23 47.51336) (end 23 44.5) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 24.31254 47.7509) (end 23.23754 47.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23.23754 47.7509) (end 23 47.51336) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 21.61254 48.7509) (end 23.31254 48.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 23.31254 48.7509) (end 24.31254 47.7509) (width 0.6) (layer F.Cu) (net 3)) + (segment (start 31.190415 33.5) (end 32 33.5) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 30.25 33.5) (end 31.190415 33.5) (width 0.6) (layer B.Cu) (net 3)) + (via (at 31.190415 33.5) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 30.25 33.5) (end 30.4 33.5) (width 0.6) (layer B.Cu) (net 3)) + (segment (start 30.4 33.5) (end 31.2 34.3) (width 0.6) (layer B.Cu) (net 3)) + (segment (start 28.5 33.5) (end 28.5 34.5) (width 0.6) (layer B.Cu) (net 3)) + (segment (start 28.5 34.5) (end 28.4 34.6) (width 0.6) (layer B.Cu) (net 3)) + (segment (start 26.75 33.5) (end 28.5 33.5) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 30.25 33.5) (end 28.5 33.5) (width 0.6) (layer B.Cu) (net 3)) + (segment (start 27.35 27.25) (end 27.35 29.976125) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 27.35 29.976125) (end 26.075 31.251125) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 26.075 31.251125) (end 26.075 32.8) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 26.075 32.8) (end 26.75 33.475) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 26.75 33.475) (end 26.75 33.5) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 31.2 34.3) (end 31.2 32.175) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 31.2 32.175) (end 30.025 31) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 30.025 31) (end 30 31) (width 0.3) (layer F.Cu) (net 3)) + (via (at 31.2 34.3) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 21.61254 41.7509) (end 21.61254 40.9009) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 21.61254 40.9009) (end 23.96344 38.55) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 23.96344 38.55) (end 26.75 38.55) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.3625 42.1125) (end 28.6875 42.1125) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.6875 42.1125) (end 28.6 42.2) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.3625 40.3875) (end 30.3625 42.1125) (width 0.35) (layer B.Cu) (net 3)) + (via (at 30.3625 42.1125) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 28.6 40.4) (end 30.35 40.4) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 30.35 40.4) (end 30.3625 40.3875) (width 0.3) (layer B.Cu) (net 3)) + (via (at 30.3625 40.3875) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 31 23.257453) (end 31 22.75) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 31 22.75) (end 31.35 22.4) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 26.8 22) (end 29.742547 22) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 29.742547 22) (end 31 23.257453) (width 0.3) (layer B.Cu) (net 3)) + (via (at 31 23.257453) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 26.75 21.25) (end 26.75 21.95) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 26.75 21.95) (end 26.8 22) (width 0.3) (layer F.Cu) (net 3)) + (via (at 26.8 22) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 34.6623 21.520576) (end 34.320576 21.520576) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 34.320576 21.520576) (end 33.8 21) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 34.7 23.202334) (end 34.7 21.558276) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 34.7 21.558276) (end 34.6623 21.520576) (width 0.35) (layer B.Cu) (net 3)) + (via (at 34.6623 21.520576) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 28.6375 26.1375) (end 30.3625 26.1375) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 30.3625 26.1375) (end 30.3625 27.8625) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 30.85 25.571545) (end 30.85 25.65) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 30.85 25.65) (end 30.3625 26.1375) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 28.6375 27.8625) (end 28.6375 26.1375) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 28.6375 27.8625) (end 30.3625 27.8625) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 28.05 25.53445) (end 28.05 25.55) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 28.05 25.55) (end 28.6375 26.1375) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 47.9 23.5) (end 47.383734 23.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.383734 23.5) (end 47.087504 23.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.65 23.75) (end 47.633734 23.75) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.633734 23.75) (end 47.383734 23.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.087504 23.5) (end 47.085702 23.498198) (width 0.35) (layer B.Cu) (net 3)) + (via (at 47.085702 23.498198) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 47.65 24.4) (end 47.65 23.75) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.65 23.75) (end 47.9 23.5) (width 0.35) (layer B.Cu) (net 3)) + (via (at 47.9 23.5) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 31.9 42.5) (end 30.75 42.5) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 30.75 42.5) (end 30.3625 42.1125) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 47.65 27.25) (end 49.025 27.25) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 49.025 27.25) (end 50.5 25.775) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 50.5 25.775) (end 50.5 25.75) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 50.5 38.085306) (end 50.5 31.4) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 50.5 31.4) (end 47.65 28.55) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 47.65 28.55) (end 47.65 27.25) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 33.8 21) (end 33.75 21) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 29.75 21.1) (end 29.65 21.1) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.3 37.15) (end 47.3 39) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 47.3 39) (end 47.1 39.2) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 47.1 39.2) (end 45.5 39.2) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 45.5 39.2) (end 45.3 39) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 45.3 39) (end 45.3 37.95) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 45.3 37.95) (end 45.3 37.15) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 47.2 34.5) (end 47 34.3) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47 34.3) (end 45.8 34.3) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.2 36.225886) (end 47.2 34.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.176696 36.24919) (end 47.2 36.225886) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 45.75 33.5) (end 45.75 34.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 45.75 34.25) (end 45.8 34.3) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.6 41.279785) (end 28.6 40.4) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 28.6 42.2) (end 28.6 41.279785) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 30.2 43.816) (end 30.2 43.8) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 30.2 43.8) (end 28.6 42.2) (width 0.3) (layer B.Cu) (net 3)) + (via (at 28.6 42.2) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 26.75 33.5) (end 26.75 38.55) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 26.75 38.55) (end 28.6 40.4) (width 0.3) (layer B.Cu) (net 3)) + (via (at 28.6 40.4) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 30.2 43.816) (end 30.59553 44.21153) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 31.25 43.65) (end 31.25 43) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 31.25 43) (end 30.3625 42.1125) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 29.25 43.65) (end 29.25 42.725) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 29.25 42.725) (end 28.6375 42.1125) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 34.134 47.75) (end 30.59553 44.21153) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 21.61254 41.7509) (end 21.61254 40.56246) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 21.61254 40.56246) (end 22.275 39.9) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 22.275 39.9) (end 22.3 39.9) (width 0.2) (layer F.Cu) (net 3)) + (via (at 38.550886 33.350886) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 38.7 33.5) (end 38.550886 33.350886) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 40 33.5) (end 38.7 33.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 43.75 48.725) (end 43.75 48.75) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 35.5 47.75) (end 34.134 47.75) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 48.3 38.7) (end 49.114694 38.7) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 49.114694 38.7) (end 49.5 39.085306) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.176696 36.99924) (end 47.176696 37.576696) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.176696 37.576696) (end 48.3 38.7) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 44 33.5) (end 45.75 33.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 42 33.805) (end 43.695 33.805) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 43.695 33.805) (end 44 33.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 40 33.5) (end 41.695 33.5) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 41.695 33.5) (end 42 33.805) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.6375 42.1125) (end 30.3625 42.1125) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 28.6375 40.3875) (end 30.3625 40.3875) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 26.8 21.2) (end 26.75 21.25) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 34.7 23.202334) (end 33.65 24.252334) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 33.647666 24.25) (end 36.409241 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 49.4 44.2) (end 50.45 44.2) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 50.45 44.2) (end 50.5 44.25) (width 0.35) (layer B.Cu) (net 3)) + (via (at 49.4 44.2) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 47.65 27.25) (end 47.65 24.4) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.85 25.571545) (end 30.85 24.267181) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.85 27.25) (end 30.85 25.571545) (width 0.3) (layer B.Cu) (net 3)) + (via (at 30.85 25.571545) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 21.61254 41.7509) (end 21.88754 41.7509) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 31.35 22.4) (end 32.4 22.4) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 32.4 22.4) (end 33.2 21.6) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 33.2 21.6) (end 33.2 21.55) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 33.2 21.55) (end 33.75 21) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 21.61254 48.7509) (end 21.61254 47.9509) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 21.61254 47.9509) (end 21.61254 41.7509) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 30.2 33.55) (end 30.25 33.5) (width 0.3) (layer B.Cu) (net 3)) + (segment (start 28.05 25.53445) (end 28.05 24.297051) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.05 27.25) (end 28.05 25.53445) (width 0.35) (layer B.Cu) (net 3)) + (via (at 28.05 25.53445) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 3)) + (segment (start 39.278698 24.25) (end 39.936339 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 29.65 21.1) (end 29.95 21.1) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 31.25 22.4) (end 31.35 22.4) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 28.25 21.2) (end 29.55 21.2) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 29.55 21.2) (end 29.65 21.1) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 28.25 21.2) (end 26.8 21.2) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 46.520702 26.348198) (end 47.320702 25.548198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.320702 25.548198) (end 47.320702 24.598198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.320702 24.598198) (end 47.320702 23.733198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.320702 23.733198) (end 47.085702 23.498198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.955702 23.498198) (end 48.120702 23.663198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 48.120702 23.663198) (end 48.120702 24.598198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.085702 22.698198) (end 47.085702 23.498198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.955702 23.498198) (end 47.955702 22.698198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.085702 23.498198) (end 47.955702 23.498198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.955702 22.698198) (end 47.085702 22.698198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 48.120702 21.598198) (end 48.120702 22.533198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 48.120702 22.533198) (end 47.955702 22.698198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 49.020702 22.098198) (end 48.836704 22.098198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 48.836704 22.098198) (end 48.781705 22.153197) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 48.781705 22.153197) (end 48.500703 22.153197) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 48.500703 22.153197) (end 47.955702 22.698198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 49.020702 22.098198) (end 50.270702 22.098198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 50.270702 22.098198) (end 50.520702 22.348198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 52.270702 22.348198) (end 50.520702 22.348198) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 47.3 37.15) (end 47.3 37.431002) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 49.3 37.431002) (end 49.3 37.15) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 45.3 37.15) (end 45.3 37.431002) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 49.3 37.15) (end 50.5 37.15) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 50.5 37.15) (end 51.3 36.35) (width 0.35) (layer F.Cu) (net 3)) + (segment (start 50.5 42.75) (end 50.5 44.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 50.5 38.085306) (end 49.5 39.085306) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 49.5 39.085306) (end 49.5 41.95) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 50.3 42.75) (end 50.5 42.75) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 49.5 41.95) (end 50.3 42.75) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 41.385764 24.25) (end 42.716996 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 42.716996 24.25) (end 47.5 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 42.75 27.25) (end 42.75 24.283004) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 42.75 24.283004) (end 42.716996 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.936339 24.25) (end 41.385764 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 41.35 27.25) (end 41.35 24.285764) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 41.35 24.285764) (end 41.385764 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.95 27.25) (end 39.95 25.4) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.95 25.4) (end 39.936339 25.386339) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.936339 25.386339) (end 39.936339 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.893663 24.25) (end 39.278698 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.25 27.25) (end 39.25 24.278698) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.25 24.278698) (end 39.278698 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.175014 24.25) (end 37.893663 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.85 27.25) (end 37.85 24.293663) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.85 24.293663) (end 37.893663 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 36.409241 24.25) (end 37.175014 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.15 24.275014) (end 37.175014 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.15 27.25) (end 37.15 24.275014) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 36.45 27.25) (end 36.45 24.290759) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 36.45 24.290759) (end 36.409241 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 32.969938 24.25) (end 33.647666 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 33.65 27.25) (end 33.65 24.252334) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 33.65 24.252334) (end 33.647666 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 32.277475 24.25) (end 32.969938 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 32.95 27.25) (end 32.95 24.269938) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 32.95 24.269938) (end 32.969938 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 31.549529 24.25) (end 32.277475 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 32.25 24.277475) (end 32.277475 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 32.25 27.25) (end 32.25 24.277475) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.867181 24.25) (end 31.549529 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 31.55 27.25) (end 31.55 24.250471) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 31.55 24.250471) (end 31.549529 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.097051 24.25) (end 30.867181 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.85 24.267181) (end 30.867181 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 27.5 24.25) (end 28.097051 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.05 24.297051) (end 28.097051 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 47.65 24.4) (end 47.5 24.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 27.5 24.25) (end 27.35 24.4) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 27.35 24.4) (end 27.35 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 28.05 27.25) (end 27.35 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 30.85 27.25) (end 31.55 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 31.55 27.25) (end 32.25 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.15 27.25) (end 36.45 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 37.85 27.25) (end 37.15 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 39.95 27.25) (end 39.25 27.25) (width 0.35) (layer B.Cu) (net 3)) + (segment (start 29.75 29.4) (end 29.75 28.475) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 29.75 28.475) (end 30.3625 27.8625) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 30 31) (end 29.75 30.75) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 29.75 30.75) (end 29.75 29.4) (width 0.3) (layer F.Cu) (net 3)) + (segment (start 29.55 21.45) (end 29.65 21.35) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 27.75 43.65) (end 27.75 43) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 27.75 43) (end 28.6375 42.1125) (width 0.2) (layer F.Cu) (net 3) (tstamp 55FDC1AA)) + (segment (start 27.75 43.65) (end 25.21164 43.65) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 25.21164 43.65) (end 24.31254 42.7509) (width 0.2) (layer F.Cu) (net 3) (tstamp 55FDC1A3)) + (segment (start 29.75 38.85) (end 29.75 39.775) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 29.75 39.775) (end 30.3625 40.3875) (width 0.2) (layer F.Cu) (net 3) (tstamp 55FDC19F)) + (segment (start 24.31254 47.7509) (end 24.31254 48.06254) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 32.6 48) (end 35.25 48) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 35.25 48) (end 35.5 47.75) (width 0.2) (layer F.Cu) (net 3) (tstamp 55FDBD32)) + (segment (start 35.5 47.75) (end 36 47.75) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 38 48.75) (end 38.25 48.75) (width 0.2) (layer F.Cu) (net 3)) + (segment (start 31.25 38.85) (end 31.25 38.219602) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 31.25 38.219602) (end 31.320001 38.149601) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 31.049601 37.379999) (end 30.420001 37.379999) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 31.320001 38.149601) (end 31.320001 37.650399) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 31.320001 37.650399) (end 31.049601 37.379999) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 30.420001 37.379999) (end 30.179999 37.620001) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 30.179999 37.620001) (end 26.720001 37.620001) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 26.720001 37.620001) (end 26.7 37.6) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 26.7 37.6) (end 24.4 39.9) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 24.4 39.9) (end 23.8 39.9) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 27.1 43) (end 25.980398 43) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 25.980398 43) (end 23.8 40.819602) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 23.8 40.819602) (end 23.8 40.475) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 23.8 40.475) (end 23.8 39.9) (width 0.2) (layer F.Cu) (net 4)) + (segment (start 25.5 46.5) (end 25.4491 46.5509) (width 0.6) (layer B.Cu) (net 5)) + (segment (start 25.4491 46.5509) (end 24.31254 46.5509) (width 0.6) (layer B.Cu) (net 5)) + (segment (start 25.5 46.5) (end 25.75 46.5) (width 0.6) (layer F.Cu) (net 5)) + (segment (start 25.75 46.5) (end 26.75 45.5) (width 0.6) (layer F.Cu) (net 5)) + (segment (start 24.25 45.75) (end 24.75 45.75) (width 0.6) (layer F.Cu) (net 5)) + (segment (start 24.75 45.75) (end 25.5 46.5) (width 0.6) (layer F.Cu) (net 5)) + (via (at 25.5 46.5) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 5)) + (segment (start 26.5 45.5) (end 26.75 45.5) (width 0.2) (layer F.Cu) (net 5) (tstamp 55FDBF13)) + (segment (start 28.75 45.5) (end 28.85 45.5) (width 0.6) (layer F.Cu) (net 6)) + (segment (start 28.85 45.5) (end 30.4 47.05) (width 0.6) (layer F.Cu) (net 6)) + (segment (start 26.75 47.25) (end 27 47.25) (width 0.6) (layer F.Cu) (net 6)) + (segment (start 27 47.25) (end 28.75 45.5) (width 0.6) (layer F.Cu) (net 6)) + (segment (start 28.75 43.65) (end 28.75 45.5) (width 0.2) (layer F.Cu) (net 6)) + (segment (start 30.4 47.05) (end 30.3 47.05) (width 0.2) (layer F.Cu) (net 6)) + (segment (start 39.9 47.05) (end 38.2 47.05) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 38.2 47.05) (end 38 47.25) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 35.5 45.21) (end 35.96 45.21) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 35.96 45.21) (end 38 47.25) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 35.5 45.21) (end 37.79 45.21) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 37.79 45.21) (end 38 45) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 32.6 47.05) (end 34.44 45.21) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 34.44 45.21) (end 35.5 45.21) (width 0.6) (layer F.Cu) (net 7)) + (segment (start 36.01 45.21) (end 35.5 45.21) (width 0.35) (layer F.Cu) (net 7)) + (segment (start 38 47.25) (end 38 47.225) (width 0.35) (layer F.Cu) (net 7)) + (segment (start 39.9 48.95) (end 40.95 48.95) (width 0.2) (layer F.Cu) (net 7)) + (segment (start 37.21 45.21) (end 35.5 45.21) (width 0.2) (layer B.Cu) (net 7) (tstamp 55FDBCB9)) + (segment (start 41 49) (end 37.21 45.21) (width 0.2) (layer B.Cu) (net 7) (tstamp 55FDBCB8)) + (via (at 41 49) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 7)) + (segment (start 40.95 48.95) (end 41 49) (width 0.2) (layer F.Cu) (net 7) (tstamp 55FDBCB6)) + (segment (start 39.9 48.95) (end 39.9 49.1) (width 0.2) (layer F.Cu) (net 7)) + (segment (start 38 47.25) (end 38 47) (width 0.2) (layer F.Cu) (net 7)) + (segment (start 36.21 45.21) (end 35.5 45.21) (width 0.2) (layer F.Cu) (net 7) (tstamp 55FDBAB0)) + (segment (start 38 47.25) (end 37.75 47.25) (width 0.2) (layer F.Cu) (net 7)) + (segment (start 38 47.25) (end 38.25 47.25) (width 0.2) (layer F.Cu) (net 7)) + (segment (start 24.55 26) (end 24.8 25.75) (width 0.3) (layer F.Cu) (net 8)) + (segment (start 24.8 25.75) (end 27.1 25.75) (width 0.3) (layer F.Cu) (net 8)) + (segment (start 29.75 24.6) (end 29.75 22.5) (width 0.25) (layer F.Cu) (net 9)) + (segment (start 29.75 22.5) (end 29.65 22.4) (width 0.25) (layer F.Cu) (net 9)) + (segment (start 28.25 22.3) (end 29.55 22.3) (width 0.25) (layer F.Cu) (net 9)) + (segment (start 29.55 22.3) (end 29.65 22.4) (width 0.25) (layer F.Cu) (net 9)) + (segment (start 29.55 22.55) (end 29.65 22.65) (width 0.2) (layer F.Cu) (net 9)) + (segment (start 29.75 22.75) (end 29.65 22.65) (width 0.2) (layer F.Cu) (net 9)) + (segment (start 30.5 23.1) (end 30.5 21.710505) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 30.5 21.710505) (end 30.5 21.6) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 31.35 21.1) (end 30.6 21.1) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 30.6 21.1) (end 30.5 21.2) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 30.5 21.2) (end 30.5 21.710505) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 30.25 23.35) (end 30.5 23.1) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 30.25 24.6) (end 30.25 23.35) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 32.7 21) (end 31.45 21) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 31.45 21) (end 31.35 21.1) (width 0.2) (layer F.Cu) (net 10)) + (segment (start 31.208998 21.1) (end 31.35 21.1) (width 0.25) (layer F.Cu) (net 10)) + (segment (start 26.9 24) (end 27.122537 23.777463) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 27.122537 23.777463) (end 31.635811 23.777463) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 31.635811 23.777463) (end 34.412699 21.000575) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 34.412699 21.000575) (end 34.911901 21.000575) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 34.911901 21.000575) (end 35.3 21.388674) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 35.3 21.388674) (end 35.3 22.680596) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 35.3 22.680596) (end 36.339405 23.720001) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 36.339405 23.720001) (end 46.094297 23.720001) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 46.836101 22.978197) (end 48.147799 22.978197) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 46.094297 23.720001) (end 46.836101 22.978197) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 48.147799 22.978197) (end 48.5 23.330398) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 48.5 23.330398) (end 48.5 24.833568) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 48.5 24.833568) (end 48.5 25.3) (width 0.2) (layer B.Cu) (net 11)) + (segment (start 48.5 25.3) (end 48.5 24.6189) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 48.5 24.6189) (end 48.520702 24.598198) (width 0.2) (layer F.Cu) (net 11)) + (via (at 48.5 25.3) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 11)) + (segment (start 27.11189 23.57001) (end 26.07001 23.57001) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 27.57001 23.57001) (end 27.11189 23.57001) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 27.11189 23.57001) (end 27.11189 23.78811) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 27.11189 23.78811) (end 26.9 24) (width 0.2) (layer F.Cu) (net 11)) + (via (at 26.9 24) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 11)) + (segment (start 25.25 23.25) (end 25.25 21.5) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 27.75 24.6) (end 27.75 23.75) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 27.75 23.75) (end 27.57001 23.57001) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 26.07001 23.57001) (end 25.75 23.25) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 25.75 23.25) (end 25.25 23.25) (width 0.2) (layer F.Cu) (net 11)) + (segment (start 23.22999 24.857438) (end 23.22999 24.433174) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 23.22999 24.433174) (end 23 24.203184) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 23 24.203184) (end 23 22.225) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 23.75 21.5) (end 23.725 21.5) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 23.725 21.5) (end 23 22.225) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 46.908628 35.608628) (end 51.15009 35.608628) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 51.15009 35.608628) (end 51.658628 35.608628) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 52.108628 35.608628) (end 51.15009 35.608628) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 53.05 36.35) (end 52.85 36.35) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 52.85 36.35) (end 52.108628 35.608628) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 46.3 37.15) (end 46.3 36.217256) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 46.3 36.217256) (end 46.908628 35.608628) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 36.4 35) (end 36.699999 35.299999) (width 0.2) (layer B.Cu) (net 12)) + (segment (start 36.699999 35.299999) (end 37.263898 35.299999) (width 0.2) (layer B.Cu) (net 12)) + (segment (start 37.263898 35.299999) (end 40.063899 38.1) (width 0.2) (layer B.Cu) (net 12)) + (segment (start 40.063899 38.1) (end 45.875736 38.1) (width 0.2) (layer B.Cu) (net 12)) + (segment (start 45.875736 38.1) (end 46.3 38.1) (width 0.2) (layer B.Cu) (net 12)) + (segment (start 34.98011 35.358716) (end 35.338826 35) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 35.338826 35) (end 36.4 35) (width 0.2) (layer F.Cu) (net 12)) + (via (at 36.4 35) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 12)) + (segment (start 34.516828 35.590011) (end 34.748815 35.590011) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 34.748815 35.590011) (end 34.98011 35.358716) (width 0.2) (layer F.Cu) (net 12)) + (via (at 26.17999 35.5) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 12)) + (segment (start 34.516828 35.590011) (end 26.270001 35.590011) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 26.270001 35.590011) (end 26.17999 35.5) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 26.17999 35.5) (end 23.22999 32.55) (width 0.2) (layer B.Cu) (net 12)) + (segment (start 23.22999 32.55) (end 23.22999 24.857438) (width 0.2) (layer B.Cu) (net 12)) + (via (at 23.22999 24.857438) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 12)) + (segment (start 46.3 37.15) (end 46.3 38.1) (width 0.2) (layer F.Cu) (net 12)) + (via (at 46.3 38.1) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 12)) + (segment (start 46.3 37) (end 46.3 37.15) (width 0.2) (layer F.Cu) (net 12)) + (segment (start 48.020702 26.348198) (end 47.720702 26.048198) (width 0.25) (layer F.Cu) (net 13)) + (segment (start 47.720702 26.048198) (end 47.720702 24.598198) (width 0.25) (layer F.Cu) (net 13)) + (segment (start 24.31254 45.9009) (end 25.3491 45.9009) (width 0.2) (layer B.Cu) (net 14)) + (segment (start 26.25 42.5) (end 27.1 42.5) (width 0.2) (layer F.Cu) (net 14) (tstamp 55FDC224)) + (segment (start 26 42.25) (end 26.25 42.5) (width 0.2) (layer F.Cu) (net 14) (tstamp 55FDC223)) + (via (at 26 42.25) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 14)) + (segment (start 26 45.25) (end 26 42.25) (width 0.2) (layer B.Cu) (net 14) (tstamp 55FDC221)) + (segment (start 25.3491 45.9009) (end 26 45.25) (width 0.2) (layer B.Cu) (net 14) (tstamp 55FDC220)) + (segment (start 23 45) (end 23.2509 45.2509) (width 0.2) (layer B.Cu) (net 15) (tstamp 55FDC21C)) + (segment (start 27.1 42) (end 26.5 42) (width 0.2) (layer F.Cu) (net 15)) + (segment (start 23.2509 45.2509) (end 24.31254 45.2509) (width 0.2) (layer B.Cu) (net 15) (tstamp 55FDC21D)) + (segment (start 23 42.75) (end 23 45) (width 0.2) (layer B.Cu) (net 15) (tstamp 55FDC21A)) + (segment (start 24 41.75) (end 23 42.75) (width 0.2) (layer B.Cu) (net 15) (tstamp 55FDC218)) + (segment (start 25.5 41.75) (end 24 41.75) (width 0.2) (layer B.Cu) (net 15) (tstamp 55FDC217)) + (segment (start 26 41.25) (end 25.5 41.75) (width 0.2) (layer B.Cu) (net 15) (tstamp 55FDC216)) + (via (at 26 41.25) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 15)) + (segment (start 26.25 41.5) (end 26 41.25) (width 0.2) (layer F.Cu) (net 15) (tstamp 55FDC214)) + (segment (start 26.25 41.75) (end 26.25 41.5) (width 0.2) (layer F.Cu) (net 15) (tstamp 55FDC213)) + (segment (start 26.5 42) (end 26.25 41.75) (width 0.2) (layer F.Cu) (net 15) (tstamp 55FDC212)) + (segment (start 28 23.25) (end 26.8 23.25) (width 0.2) (layer F.Cu) (net 16)) + (segment (start 28.25 24.6) (end 28.25 23.5) (width 0.2) (layer F.Cu) (net 16)) + (segment (start 28.25 23.5) (end 28 23.25) (width 0.2) (layer F.Cu) (net 16)) + (segment (start 26.8 23.25) (end 26.75 23.2) (width 0.2) (layer F.Cu) (net 16)) + (segment (start 26.75 23.2) (end 26.75 22.75) (width 0.2) (layer F.Cu) (net 16)) + (segment (start 26.95 22.75) (end 26.75 22.75) (width 0.2) (layer F.Cu) (net 16)) + (segment (start 29.3 34.3) (end 29.3 35.4) (width 0.2) (layer B.Cu) (net 17)) + (segment (start 29.3 35.4) (end 34.2 40.3) (width 0.2) (layer B.Cu) (net 17)) + (segment (start 29.25 34.125736) (end 29.25 34.25) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 29.25 34.25) (end 29.3 34.3) (width 0.2) (layer F.Cu) (net 17)) + (via (at 29.3 34.3) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 17)) + (segment (start 34.2 43.3) (end 34.2 42.971085) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 34.2 42.971085) (end 34.2 40.3) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 32.6 48.95) (end 31.7 48.95) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 31.5 46.2) (end 34.2 43.5) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 31.7 48.95) (end 31.5 48.75) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 31.5 48.75) (end 31.5 46.2) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 34.2 43.5) (end 34.2 42.971085) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 29.25 29.4) (end 29.25 33.174388) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 29.25 33.174388) (end 29.25 33.45) (width 0.2) (layer F.Cu) (net 17)) + (segment (start 29.25 34.125736) (end 29.25 33.174388) (width 0.2) (layer F.Cu) (net 17)) + (via (at 34.2 40.3) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 17)) + (segment (start 30.4 48.95) (end 30.2 48.95) (width 0.2) (layer F.Cu) (net 18)) + (segment (start 30.2 48.95) (end 28.75 47.5) (width 0.2) (layer F.Cu) (net 18) (tstamp 55FDBD59)) + (segment (start 23.75 26.25) (end 23.75 26.014248) (width 0.2) (layer B.Cu) (net 19)) + (segment (start 23.75 26.014248) (end 23.75 24.25) (width 0.2) (layer B.Cu) (net 19)) + (segment (start 26.026518 28.87999) (end 25.602254 28.87999) (width 0.2) (layer B.Cu) (net 19)) + (segment (start 25.602254 28.87999) (end 23.75 27.027736) (width 0.2) (layer B.Cu) (net 19)) + (segment (start 23.75 27.027736) (end 23.75 26.014248) (width 0.2) (layer B.Cu) (net 19)) + (segment (start 26.25 28.75) (end 26.156508 28.75) (width 0.2) (layer F.Cu) (net 19)) + (segment (start 26.156508 28.75) (end 26.026518 28.87999) (width 0.2) (layer F.Cu) (net 19)) + (via (at 26.026518 28.87999) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 19)) + (segment (start 27.1 28.75) (end 26.25 28.75) (width 0.2) (layer F.Cu) (net 19)) + (segment (start 23.75 24.25) (end 23.75 23.25) (width 0.2) (layer F.Cu) (net 19) (tstamp 55FD2BB6)) + (via (at 23.75 24.25) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 19)) + (segment (start 37.038399 22.654999) (end 38.084279 22.654999) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 38.084279 22.654999) (end 38.410999 22.654999) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 39.835 24.479) (end 39.835 23.579) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 39.835 23.579) (end 38.910999 22.654999) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 38.910999 22.654999) (end 38.084279 22.654999) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 34 25.25) (end 34.7 25.25) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 34.7 25.25) (end 36.754999 23.195001) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 36.754999 23.195001) (end 36.754999 22.938399) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 36.754999 22.938399) (end 37.038399 22.654999) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 39.835 24.079) (end 39.835 24.479) (width 0.25) (layer F.Cu) (net 20)) + (segment (start 31.9 26.75) (end 34 26.75) (width 0.2) (layer F.Cu) (net 21)) + (segment (start 39.5 43.8) (end 39.5 45) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 33.7 37.180031) (end 39.5 42.980031) (width 0.2) (layer B.Cu) (net 22)) + (segment (start 39.5 42.980031) (end 39.5 43.8) (width 0.2) (layer B.Cu) (net 22)) + (via (at 39.5 43.8) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 22)) + (segment (start 31.980031 36.980031) (end 33.5 36.980031) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 33.5 36.980031) (end 33.7 37.180031) (width 0.2) (layer F.Cu) (net 22)) + (via (at 33.7 37.180031) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 22)) + (segment (start 27.1 27.75) (end 25.947438 27.75) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 25.947438 27.75) (end 25.397438 28.3) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 25.397438 28.3) (end 24 28.3) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 23.6 29.5) (end 24.5 30.4) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 24.5 30.4) (end 24.5 35.947298) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 24 28.3) (end 23.6 28.7) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 23.6 28.7) (end 23.6 29.5) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 24.5 35.947298) (end 25.532732 36.98003) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 25.532732 36.98003) (end 31.980031 36.980031) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 39.5 44.5) (end 39.5 45) (width 0.2) (layer F.Cu) (net 22)) + (segment (start 39.5 45) (end 41 45) (width 0.3) (layer F.Cu) (net 22)) + (segment (start 36.353593 35.816009) (end 36.973739 35.195863) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 44.9 20.5) (end 46.452563 20.500001) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 46.920702 21.123198) (end 46.920702 21.598198) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 46.452563 20.500001) (end 46.920702 20.96814) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 46.920702 20.96814) (end 46.920702 21.123198) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 42.579999 33.879999) (end 43.8 35.1) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 44.9 20.5) (end 44.620001 20.779999) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 42.579999 21.050399) (end 42.579999 33.879999) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 44.620001 20.779999) (end 42.850399 20.779999) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 42.850399 20.779999) (end 42.579999 21.050399) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 39.135486 34.94489) (end 38.113097 33.922501) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 43.8 35.1) (end 39.290596 35.1) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 39.290596 35.1) (end 39.135486 34.94489) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 46.3 35.1) (end 45.879999 35.520001) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 45.879999 35.520001) (end 44.220001 35.520001) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 44.220001 35.520001) (end 43.8 35.1) (width 0.2) (layer F.Cu) (net 23)) + (via (at 43.8 35.1) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 23)) + (segment (start 25.15999 31.451782) (end 25.15999 35.478902) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 25.797837 36.340011) (end 25.15999 35.702164) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 25.15999 35.702164) (end 25.15999 35.478902) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 25.797837 36.340011) (end 35.829591 36.340011) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 36.973739 35.195863) (end 37.6 34.569602) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 35.829591 36.340011) (end 36.973739 35.195863) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 36.25 31.55) (end 35.75 31.05) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 38.113097 33.922501) (end 38.113097 33.663097) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 38.113097 33.663097) (end 36.45 32) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 36.45 32) (end 36.25 32) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 36.029591 36.140011) (end 36.353593 35.816009) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 35.929592 36.24001) (end 36.353593 35.816009) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 37.630398 34.569602) (end 38.113097 34.086903) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 37.6 34.569602) (end 37.630398 34.569602) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 38.113097 34.086903) (end 38.113097 33.922501) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 27.75 29.4) (end 25.897846 29.4) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 25.897846 29.4) (end 25.159989 30.137857) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 25.159989 30.137857) (end 25.15999 31.451782) (width 0.2) (layer F.Cu) (net 23)) + (via (at 38.113097 33.922501) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 23)) + (segment (start 46.3 35.1) (end 46.3 34.05) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 46.3 33.9) (end 46.3 34.05) (width 0.2) (layer F.Cu) (net 23)) + (segment (start 35.75 31.05) (end 35.75 28.95) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 35.75 28.95) (end 35.75 27.25) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 36.25 32) (end 36.25 31.55) (width 0.2) (layer B.Cu) (net 23)) + (segment (start 45.032552 20.82001) (end 45.990398 20.82001) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 46.32001 20.82001) (end 45.990398 20.82001) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 45.990398 20.82001) (end 46.2 20.82001) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 46.520702 21.020702) (end 46.32001 20.82001) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 46.520702 21.598198) (end 46.520702 21.020702) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 44.752554 21.100008) (end 45.032552 20.82001) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 43.1 21.2) (end 43.199991 21.100009) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 43.199991 21.100009) (end 44.752554 21.100008) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 43.1 21.3) (end 43.1 21.2) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 45.3 35) (end 45.3 34.05) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 44.4 35.62001) (end 44.67999 35.62001) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 44.67999 35.62001) (end 45.3 35) (width 0.2) (layer B.Cu) (net 24)) + (via (at 45.3 35) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 24)) + (segment (start 34.85 32.8) (end 36.720196 32.8) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 36.720196 32.8) (end 37.593096 33.6729) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 37.593096 34.172102) (end 39.041004 35.62001) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 37.593096 33.6729) (end 37.593096 34.172102) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 39.041004 35.62001) (end 44.4 35.62001) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 34.5 32) (end 34.5 32.45) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 34.5 32.45) (end 34.85 32.8) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 33.442665 32.7) (end 33.8 32.7) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 33.8 32.7) (end 34.5 32) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 30.25 29.4) (end 30.25 29.95) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 30.25 29.95) (end 33 32.7) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 33 32.7) (end 33.442665 32.7) (width 0.2) (layer F.Cu) (net 24)) + (via (at 33.442665 32.7) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 24)) + (segment (start 45.3 34.05) (end 45.3 33.4) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 45.3 33.4) (end 43.1 31.2) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 43.1 31.2) (end 43.1 21.3) (width 0.2) (layer F.Cu) (net 24)) + (segment (start 34.35 27.25) (end 34.35 29.677148) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 35.05 27.25) (end 34.35 27.25) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 35.05 27.25) (end 35.05 28.95) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 35.05 28.95) (end 34.35 29.65) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 34.35 29.65) (end 34.35 29.677148) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 34.35 29.677148) (end 34.35 31.85) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 34.35 31.85) (end 34.5 32) (width 0.2) (layer B.Cu) (net 24)) + (segment (start 30.75 29.95) (end 32.979999 32.179999) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 32.979999 32.179999) (end 33.692266 32.179999) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 33.692266 32.179999) (end 34 32.487733) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 31.9 40) (end 32.552562 40) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 32.552562 40) (end 35.167799 37.384763) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 35.167799 37.384763) (end 35.167799 36.867799) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 35.2 36.8) (end 34 35.6) (width 0.2) (layer B.Cu) (net 25)) + (segment (start 34 35.6) (end 34 34.5) (width 0.2) (layer B.Cu) (net 25)) + (segment (start 35.2 37.071002) (end 35.2 36.8) (width 0.2) (layer F.Cu) (net 25)) + (via (at 35.167799 36.867799) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 25)) + (segment (start 33.830832 32.318565) (end 33.962666 32.450399) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 34 34.5) (end 34 32.487733) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 34 32.487733) (end 33.830832 32.318565) (width 0.2) (layer F.Cu) (net 25)) + (via (at 34 34.5) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 25)) + (segment (start 30.75 29.4) (end 30.75 29.95) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 30.75 29.95) (end 30.797438 29.997438) (width 0.2) (layer F.Cu) (net 25)) + (segment (start 36.9 32.4) (end 38.517228 32.4) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 38.517228 32.4) (end 39.08458 32.4) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 39.583804 32.4) (end 38.517228 32.4) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 40.5 31.483804) (end 39.583804 32.4) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 40.5 31.019934) (end 40.5 31.483804) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 40.5 29.3) (end 40.5 27.597647) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 38.565 24.479) (end 38.565 25.379) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 38.565 25.379) (end 40.5 27.314) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 40.5 27.314) (end 40.5 27.597647) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 40.5 29.5) (end 40.5 29.3) (width 0.2) (layer F.Cu) (net 26)) + (segment (start 40.5 31.019934) (end 40.5 29.5) (width 0.2) (layer F.Cu) (net 26)) + (segment (start 39.08458 32.4) (end 39.119934 32.4) (width 0.2) (layer F.Cu) (net 26)) + (segment (start 31.9 28.25) (end 32.75 28.25) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 32.75 28.25) (end 36.9 32.4) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 38.565 24.879) (end 38.565 24.479) (width 0.25) (layer F.Cu) (net 26)) + (segment (start 39.835 30.321) (end 39.835 31.197018) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 39.835 31.197018) (end 39.532018 31.5) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 39.532018 31.5) (end 36.8 31.5) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 36.8 31.5) (end 33.05 27.75) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 33.05 27.75) (end 32.5 27.75) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 32.5 27.75) (end 31.9 27.75) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 32.673272 27.75) (end 32.5 27.75) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 39.835 30.721) (end 39.835 30.321) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 39.835 29.921) (end 39.835 30.321) (width 0.25) (layer F.Cu) (net 27)) + (segment (start 37.295 30.321) (end 37.295 29.421) (width 0.25) (layer F.Cu) (net 28)) + (segment (start 37.295 29.421) (end 35.244272 29.421) (width 0.25) (layer F.Cu) (net 28)) + (segment (start 35.244272 29.421) (end 33.073272 27.25) (width 0.25) (layer F.Cu) (net 28)) + (segment (start 33.073272 27.25) (end 31.9 27.25) (width 0.25) (layer F.Cu) (net 28)) + (segment (start 37.295 29.921) (end 37.295 30.321) (width 0.25) (layer F.Cu) (net 28)) + (segment (start 31.9 26.25) (end 32.5 26.25) (width 0.25) (layer F.Cu) (net 29)) + (segment (start 32.5 26.25) (end 32.65 26.1) (width 0.25) (layer F.Cu) (net 29)) + (segment (start 32.65 26.1) (end 35.244 26.1) (width 0.25) (layer F.Cu) (net 29)) + (segment (start 35.244 26.1) (end 38.565 29.421) (width 0.25) (layer F.Cu) (net 29)) + (segment (start 38.565 29.421) (end 38.565 30.321) (width 0.25) (layer F.Cu) (net 29)) + (segment (start 38.565 29.921) (end 38.565 30.321) (width 0.25) (layer F.Cu) (net 29)) + (segment (start 36.885136 22.284989) (end 39.074166 22.284989) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 39.074166 22.284989) (end 39.310989 22.284989) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 41.105 24.479) (end 41.105 23.579) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 41.105 23.579) (end 39.810989 22.284989) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 39.810989 22.284989) (end 39.074166 22.284989) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 31.9 25.75) (end 32.5 25.75) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 33.5 24.6) (end 34.874394 23.225606) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 32.5 25.75) (end 33.2 25.05) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 33.2 25.05) (end 33.2 24.7) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 35.944519 23.225606) (end 36.885136 22.284989) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 33.2 24.7) (end 33.3 24.6) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 34.874394 23.225606) (end 35.944519 23.225606) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 33.3 24.6) (end 33.5 24.6) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 41.105 24.079) (end 41.105 24.479) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 31.9 25.75) (end 32.358998 25.75) (width 0.25) (layer F.Cu) (net 30)) + (segment (start 35.613232 21.817166) (end 35.650399 21.779999) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 41.762458 23.262458) (end 40.279999 21.779999) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 35.650399 21.779999) (end 35.56818 21.862218) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 40.279999 21.779999) (end 35.650399 21.779999) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 35.56818 21.862218) (end 35.613232 21.817166) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 41.762458 23.840456) (end 41.762458 23.262458) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 32.777836 40.5) (end 31.9 40.5) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 41.762458 23.840456) (end 41.762458 31.515378) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 41.762458 31.515378) (end 32.777836 40.5) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 35.490419 21.939979) (end 35.56818 21.862218) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 31.25 24.6) (end 32.322438 24.6) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 32.322438 24.6) (end 34.561843 22.360595) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 35.379999 22.050399) (end 35.56818 21.862218) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 34.561843 22.360595) (end 35.339405 22.360595) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 35.339405 22.360595) (end 35.379999 22.320001) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 35.379999 22.320001) (end 35.379999 22.050399) (width 0.2) (layer F.Cu) (net 31)) + (segment (start 34.618399 22.040585) (end 35.059415 22.040585) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 35.059415 22.040585) (end 35.059989 22.040011) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 35.059989 22.040011) (end 35.059989 21.917847) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 35.059989 21.917847) (end 35.517846 21.45999) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 35.517846 21.45999) (end 40.412552 21.45999) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 40.412552 21.45999) (end 42.082468 23.129906) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 42.082468 23.129906) (end 42.082468 31.64793) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 42.082468 31.64793) (end 41.465362 32.265036) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 30.8 37.9) (end 33.67999 40.77999) (width 0.2) (layer B.Cu) (net 32)) + (segment (start 33.67999 40.77999) (end 33.67999 40.809118) (width 0.2) (layer B.Cu) (net 32)) + (segment (start 33.679999 40.050399) (end 41.465362 32.265036) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 41.465362 32.265036) (end 41.730398 32) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 41.895011 31.835387) (end 41.465362 32.265036) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 33.67999 40.809118) (end 33.679999 40.809109) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 33.679999 40.809109) (end 33.679999 40.050399) (width 0.2) (layer F.Cu) (net 32)) + (via (at 33.67999 40.809118) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 32)) + (segment (start 32.669876 23.8) (end 34.429291 22.040585) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 34.618399 22.040585) (end 34.42929 22.040586) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 31 23.8) (end 32.669876 23.8) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 34.429291 22.040585) (end 34.618399 22.040585) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 30.75 24.05) (end 31 23.8) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 30.75 24.05) (end 30.75 24.6) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 30.75 38.85) (end 30.75 37.95) (width 0.2) (layer F.Cu) (net 32)) + (segment (start 30.75 37.95) (end 30.8 37.9) (width 0.2) (layer F.Cu) (net 32)) + (via (at 30.8 37.9) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 32)) + (segment (start 26.13407 36.660021) (end 32.983728 36.660021) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 31.9 39.5) (end 32.6 39.5) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 32.6 39.5) (end 34.647798 37.452202) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 34.647798 37.452202) (end 34.647798 37.358227) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 34.647798 37.358227) (end 33.949592 36.660021) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 33.949592 36.660021) (end 32.983728 36.660021) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 26.13407 36.660021) (end 25.665284 36.66002) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 24.839981 35.834717) (end 25.665285 36.660021) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 25.665285 36.660021) (end 26.13407 36.660021) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 25.480349 28.669651) (end 24.83998 29.31002) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 24.83998 29.31002) (end 24.839981 35.834717) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 25.15 29) (end 25.480349 28.669651) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 25.480349 28.669651) (end 25.920001 28.229999) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 31.9 39.5) (end 32.125 39.5) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 24.5 29) (end 25.15 29) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 25.920001 28.229999) (end 26.529999 28.229999) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 26.529999 28.229999) (end 26.55 28.25) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 26.55 28.25) (end 27.1 28.25) (width 0.2) (layer F.Cu) (net 33)) + (segment (start 31.25 29.997438) (end 33.112551 31.859989) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 33.112551 31.859989) (end 33.824818 31.859989) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 33.824818 31.859989) (end 36.254531 34.289702) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 31.25 29.4) (end 31.25 29.997438) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 50.5 45.75) (end 54.078549 45.75) (width 0.35) (layer B.Cu) (net 34)) + (segment (start 37.092994 38.207006) (end 38.873521 36.426479) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 38.873521 36.426479) (end 38.873521 36.14002) (width 0.2) (layer F.Cu) (net 34)) + (via (at 38.873521 36.14002) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 34)) + (segment (start 44.6 44.2) (end 43.085988 44.2) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 43.085988 44.2) (end 37.092994 38.207006) (width 0.2) (layer B.Cu) (net 34)) + (via (at 37.092994 38.207006) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 34)) + (segment (start 49.584989 45.154591) (end 49.584989 46.16533) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 49.584989 46.16533) (end 49.58499 46.458554) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 51.5 48.6) (end 51.5 48.373564) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 51.5 48.373564) (end 49.584989 46.458553) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 49.584989 46.458553) (end 49.584989 46.16533) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 51.7 48.8) (end 51.5 48.6) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 53.2 48.8) (end 51.7 48.8) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 54.1 47.9) (end 53.2 48.8) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 48.630398 44.2) (end 49.584989 45.154591) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 44.6 44.2) (end 48.630398 44.2) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 37.086558 34.289702) (end 36.254531 34.289702) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 31.25 29.625) (end 31.25 29.4) (width 0.2) (layer F.Cu) (net 34)) + (segment (start 38.873521 36.14002) (end 37.086558 34.353057) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 37.086558 34.353057) (end 37.086558 34.289702) (width 0.2) (layer B.Cu) (net 34)) + (via (at 37.086558 34.289702) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 34)) + (segment (start 54.1 47.9) (end 54.1 47.8) (width 0.2) (layer B.Cu) (net 34)) + (segment (start 54.1 42.2) (end 54.1 45.728549) (width 0.35) (layer B.Cu) (net 34)) + (segment (start 54.1 45.728549) (end 54.1 47.8) (width 0.35) (layer B.Cu) (net 34)) + (segment (start 54.078549 45.75) (end 54.1 45.728549) (width 0.35) (layer B.Cu) (net 34)) + (segment (start 54.1 42.2) (end 54.1 40.205) (width 0.35) (layer B.Cu) (net 34)) + (segment (start 54.1 40.205) (end 54.305 40) (width 0.35) (layer B.Cu) (net 34)) + (segment (start 43.289412 21.89499) (end 43.090013 21.89499) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 43.30501 21.89499) (end 43.090013 21.89499) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 43.090013 21.89499) (end 36.30501 21.89499) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 49.3 20.8) (end 44.4 20.8) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 44.4 20.8) (end 43.30501 21.89499) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 49.920001 21.420001) (end 49.3 20.8) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 53.2 21.2) (end 50.969602 21.2) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 50.969602 21.2) (end 50.749601 21.420001) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 50.749601 21.420001) (end 49.920001 21.420001) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 54.1 22.1) (end 53.2 21.2) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 36.30501 21.89499) (end 36.29501 21.90499) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 36.29501 21.90499) (end 35.9 22.3) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 35.075719 22.680605) (end 35.519395 22.680605) (width 0.2) (layer F.Cu) (net 35)) + (segment (start 32.512084 25.25) (end 32.512084 24.899999) (width 0.2) (layer F.Cu) (net 35)) + (segment (start 32.512084 24.899999) (end 34.731478 22.680605) (width 0.2) (layer F.Cu) (net 35)) + (segment (start 34.731478 22.680605) (end 35.075719 22.680605) (width 0.2) (layer F.Cu) (net 35)) + (segment (start 31.9 25.25) (end 32.512084 25.25) (width 0.2) (layer F.Cu) (net 35)) + (segment (start 54.1 22.2) (end 54.1 22.1) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 35.519395 22.680605) (end 35.9 22.3) (width 0.2) (layer F.Cu) (net 35)) + (via (at 35.9 22.3) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 35)) + (segment (start 31.9 25.25) (end 32.125 25.25) (width 0.2) (layer F.Cu) (net 35)) + (segment (start 54 22.1) (end 54.1 22.2) (width 0.2) (layer B.Cu) (net 35)) + (segment (start 54.1 26.85) (end 54.1 24.22278) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 54.1 24.22278) (end 54.1 22.2) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 50.5 24.25) (end 54.07278 24.25) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 54.07278 24.25) (end 54.1 24.22278) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 54.1 27.8) (end 54.1 26.85) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 54.305 30) (end 54.305 28.005) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 54.305 28.005) (end 54.1 27.8) (width 0.35) (layer B.Cu) (net 35)) + (segment (start 44 32) (end 44 31.4) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 44 31.4) (end 42.7 30.1) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 42.7 30.1) (end 40.475 30.1) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 42 31.695) (end 42 31.625) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 42 31.625) (end 40.475 30.1) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 40.475 30.1) (end 38.55 30.1) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 40 32) (end 40 31.55) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 40 31.55) (end 38.55 30.1) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 38.55 30.1) (end 38.55 28.95) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 38.55 28.95) (end 38.55 27.25) (width 0.2) (layer B.Cu) (net 36)) + (segment (start 30.25 32) (end 30.25 31.4) (width 0.2) (layer B.Cu) (net 37)) + (segment (start 30.25 31.4) (end 29.45 30.6) (width 0.2) (layer B.Cu) (net 37)) + (segment (start 29.45 30.6) (end 29.45 28.95) (width 0.2) (layer B.Cu) (net 37)) + (segment (start 29.45 28.95) (end 29.45 27.25) (width 0.2) (layer B.Cu) (net 37)) + (segment (start 28.5 32) (end 28.5 29.65) (width 0.2) (layer B.Cu) (net 38)) + (segment (start 28.5 29.65) (end 28.75 29.4) (width 0.2) (layer B.Cu) (net 38)) + (segment (start 26.75 32) (end 26.75 31.4) (width 0.2) (layer B.Cu) (net 38)) + (segment (start 26.75 31.4) (end 28.75 29.4) (width 0.2) (layer B.Cu) (net 38)) + (segment (start 28.75 28.95) (end 28.75 27.25) (width 0.2) (layer B.Cu) (net 38)) + (segment (start 28.75 29.4) (end 28.75 28.95) (width 0.2) (layer B.Cu) (net 38)) + (segment (start 48.5 33.325) (end 48.5 31.14344) (width 0.2) (layer B.Cu) (net 39)) + (segment (start 48.5 31.14344) (end 46.25 28.89344) (width 0.2) (layer B.Cu) (net 39)) + (segment (start 46.25 28.89344) (end 46.25 27.25) (width 0.2) (layer B.Cu) (net 39)) + (segment (start 49.25 33.5) (end 48.675 33.5) (width 0.2) (layer B.Cu) (net 39)) + (segment (start 48.675 33.5) (end 48.5 33.325) (width 0.2) (layer B.Cu) (net 39)) + (segment (start 49.25 32) (end 49.25 30.946002) (width 0.2) (layer B.Cu) (net 40)) + (segment (start 49.25 30.946002) (end 46.95 28.646002) (width 0.2) (layer B.Cu) (net 40)) + (segment (start 46.95 28.646002) (end 46.95 27.25) (width 0.2) (layer B.Cu) (net 40)) + (segment (start 46.75 30.85) (end 46.75 32.725) (width 0.2) (layer B.Cu) (net 41)) + (segment (start 46.75 32.725) (end 47.5 33.475) (width 0.2) (layer B.Cu) (net 41)) + (segment (start 47.5 33.475) (end 47.5 33.5) (width 0.2) (layer B.Cu) (net 41)) + (segment (start 44.85 27.25) (end 44.85 28.95) (width 0.2) (layer B.Cu) (net 41)) + (segment (start 44.85 28.95) (end 46.75 30.85) (width 0.2) (layer B.Cu) (net 41)) + (segment (start 45.55 29.15) (end 47.5 31.1) (width 0.2) (layer B.Cu) (net 42)) + (segment (start 47.5 31.1) (end 47.5 32) (width 0.2) (layer B.Cu) (net 42)) + (segment (start 45.55 27.25) (end 45.55 29.15) (width 0.2) (layer B.Cu) (net 42)) + (segment (start 45.55 28.646002) (end 45.55 27.25) (width 0.2) (layer B.Cu) (net 42)) + (segment (start 47.5 32) (end 47.5 31.975) (width 0.35) (layer B.Cu) (net 42)) + (segment (start 54.1 37.8) (end 54.1 36.85) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 54.1 36.85) (end 54.1 32.2) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 54.1 37.8) (end 54.1 38.095) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 54.1 38.095) (end 52.195 40) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 54.1 32.2) (end 54.1 31.905) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 54.1 31.905) (end 52.195 30) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 52.195 30) (end 52.265 30) (width 0.35) (layer B.Cu) (net 43)) + (segment (start 32 32) (end 32 31.55) (width 0.2) (layer B.Cu) (net 44)) + (segment (start 32 31.55) (end 30.15 29.7) (width 0.2) (layer B.Cu) (net 44)) + (segment (start 30.15 29.7) (end 30.15 28.95) (width 0.2) (layer B.Cu) (net 44)) + (segment (start 30.15 28.95) (end 30.15 27.25) (width 0.2) (layer B.Cu) (net 44)) + (segment (start 46.226696 38.99822) (end 46.226696 41.46) (width 0.35) (layer B.Cu) (net 45)) + (segment (start 46.226696 41.46) (end 46.266696 41.5) (width 0.35) (layer B.Cu) (net 45)) + (segment (start 45.276696 36.99924) (end 43.477456 36.99924) (width 0.35) (layer B.Cu) (net 46)) + (segment (start 43.477456 36.99924) (end 43.226696 37.25) (width 0.35) (layer B.Cu) (net 46)) + (segment (start 25.479999 32.050508) (end 25.479999 35.569611) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 25.479999 35.569611) (end 25.930389 36.020001) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 35.390891 36.020001) (end 35.890882 35.52001) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 25.930389 36.020001) (end 35.390891 36.020001) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 36.625727 35.667099) (end 37.096549 36.137921) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 37.096549 36.137921) (end 39.708628 38.75) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 35.890882 35.52001) (end 36.467448 35.52001) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 36.467448 35.52001) (end 37.085359 36.137921) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 37.085359 36.137921) (end 37.096549 36.137921) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 35.767099 35.643793) (end 35.890882 35.52001) (width 0.2) (layer F.Cu) (net 47)) + (via (at 35.890882 35.52001) (size 0.6) (drill 0.3) (layers F.Cu B.Cu) (net 47)) + (segment (start 43.226696 38.75) (end 41.707312 38.75) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 41.707312 38.75) (end 40.526309 38.75) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 39.708628 38.75) (end 41.707312 38.75) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 25.479999 31.056397) (end 25.479999 32.050508) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 25.479999 32.050508) (end 25.479999 32.579999) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 28.25 29.4) (end 28.25 30.05) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 25.479999 30.270409) (end 25.479999 31.056397) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 28.25 30.05) (end 28.1 30.2) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 28.1 30.2) (end 26.449592 30.2) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 26.449592 30.2) (end 26.249601 30.000009) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 26.249601 30.000009) (end 25.750399 30.000009) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 25.750399 30.000009) (end 25.479999 30.270409) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 25.479999 31.056397) (end 25.479999 31.319229) (width 0.2) (layer F.Cu) (net 47)) + (segment (start 40.526309 38.75) (end 40.35 38.75) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 39.95 38.75) (end 40.526309 38.75) (width 0.2) (layer B.Cu) (net 47)) + (segment (start 50.921002 45) (end 52.4 43.521002) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 50.078998 45) (end 50.921002 45) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 49.904999 45.173999) (end 50.078998 45) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 49.904999 46.326001) (end 49.904999 45.173999) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 51.378998 47.8) (end 49.904999 46.326001) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 47.8) (end 51.378998 47.8) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 43.521002) (end 52.4 43) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 43) (end 52.4 42.2) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 37.8) (end 52.4 32.2) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 50.5 41.25) (end 50.5 38.75) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 50.5 38.75) (end 51.45 37.8) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 51.45 37.8) (end 52.4 37.8) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 51.55 41.25) (end 50.5 41.25) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 52.4 42.1) (end 51.55 41.25) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 50.078998 25) (end 50.921002 25) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 50.921002 25) (end 52.4 26.478998) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 26.478998) (end 52.4 27) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 27) (end 52.4 27.8) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 22.2) (end 51.378998 22.2) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 51.378998 22.2) (end 49.904999 23.673999) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 49.904999 23.673999) (end 49.904999 24.826001) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 49.904999 24.826001) (end 50.078998 25) (width 0.2) (layer B.Cu) (net 48)) + (segment (start 52.4 27.8) (end 52.4 27.9) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 52.4 27.9) (end 51.25 29.05) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 51.25 30.95) (end 52.4 32.1) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 51.25 29.05) (end 51.25 30.95) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 52.4 32.1) (end 52.4 32.2) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 52.4 37.8) (end 52.4 37.9) (width 0.35) (layer B.Cu) (net 48)) + (segment (start 52.4 42.1) (end 52.4 42.2) (width 0.35) (layer B.Cu) (net 48)) + + (zone (net 3) (net_name GND) (layer B.Cu) (tstamp 0) (hatch edge 0.508) + (connect_pads (clearance 0.23)) + (min_thickness 0.254) + (fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508)) + (polygon + (pts + (xy 17.5 57.5) (xy 57.5 57.5) (xy 57.5 12.5) (xy 17.5 12.5) (xy 17.5 16.2) + (xy 17.5 19.9) (xy 23.9 19.9) (xy 23.9 32.6) (xy 17.5 32.6) + ) + ) + (filled_polygon + (pts + (xy 25.279106 29.203138) (xy 25.427368 29.302203) (xy 25.542535 29.325111) (xy 25.630122 29.41285) (xy 25.535431 29.507541) + (xy 25.393011 29.720687) (xy 25.343 29.97211) (xy 25.343 30.52001) (xy 25.342887 30.650122) (xy 25.442698 30.891684) + (xy 25.627354 31.076662) (xy 25.748575 31.126997) (xy 25.748577 31.126999) (xy 25.74858 31.127) (xy 25.868741 31.176895) + (xy 25.999997 31.177009) (xy 26 31.17701) (xy 26.000003 31.17701) (xy 26.130112 31.177123) (xy 26.251421 31.126999) + (xy 26.251423 31.126999) (xy 26.251425 31.126998) (xy 26.371674 31.077312) (xy 26.556652 30.892656) (xy 26.606987 30.771435) + (xy 26.606989 30.771433) (xy 26.60699 30.77143) (xy 26.656885 30.651269) (xy 26.657113 30.389898) (xy 26.657 30.389625) + (xy 26.657 30.244248) (xy 27.164569 29.73668) (xy 27.306989 29.523533) (xy 27.356999 29.27211) (xy 27.327927 29.125953) + (xy 27.490302 29.288327) (xy 27.527474 29.303724) (xy 27.60875 29.385) (xy 27.676309 29.385) (xy 27.7 29.375187) + (xy 27.723691 29.385) (xy 27.79125 29.385) (xy 27.872526 29.303724) (xy 27.909698 29.288327) (xy 28.088327 29.109699) + (xy 28.15 28.960807) (xy 28.15 29.22625) (xy 28.213727 29.289977) (xy 26.426852 31.076852) (xy 26.327787 31.225113) + (xy 26.3237 31.245659) (xy 26.242704 31.260899) (xy 26.121198 31.339086) (xy 26.039684 31.458386) (xy 26.011006 31.6) + (xy 26.011006 32.4) (xy 26.035899 32.532296) (xy 26.04649 32.548754) (xy 26.015301 32.561673) (xy 25.836673 32.740302) + (xy 25.74 32.973691) (xy 25.74 33.21425) (xy 25.89875 33.373) (xy 26.623 33.373) (xy 26.623 33.353) + (xy 26.877 33.353) (xy 26.877 33.373) (xy 27.60125 33.373) (xy 27.625 33.34925) (xy 27.64875 33.373) + (xy 28.373 33.373) (xy 28.373 33.353) (xy 28.627 33.353) (xy 28.627 33.373) (xy 29.35125 33.373) + (xy 29.375 33.34925) (xy 29.39875 33.373) (xy 30.123 33.373) (xy 30.123 33.353) (xy 30.377 33.353) + (xy 30.377 33.373) (xy 31.07175 33.373) (xy 31.07375 33.375) (xy 31.873 33.375) (xy 31.873 32.77375) + (xy 31.71425 32.615) (xy 31.42369 32.615) (xy 31.190301 32.711673) (xy 31.1625 32.739475) (xy 30.984699 32.561673) + (xy 30.955012 32.549376) (xy 30.960316 32.541614) (xy 30.988994 32.4) (xy 30.988994 31.6) (xy 30.964101 31.467704) + (xy 30.885914 31.346198) (xy 30.766614 31.264684) (xy 30.676452 31.246425) (xy 30.672213 31.225114) (xy 30.573148 31.076852) + (xy 29.907 30.410704) (xy 29.907 30.103296) (xy 31.294815 31.491111) (xy 31.214684 31.608386) (xy 31.186006 31.75) + (xy 31.186006 32.25) (xy 31.210899 32.382296) (xy 31.289086 32.503802) (xy 31.408386 32.585316) (xy 31.55 32.613994) + (xy 32.215664 32.613994) (xy 32.215664 32.685086) (xy 32.127 32.77375) (xy 32.127 33.375) (xy 32.147 33.375) + (xy 32.147 33.625) (xy 32.127 33.625) (xy 32.127 33.647) (xy 31.873 33.647) (xy 31.873 33.625) + (xy 31.07375 33.625) (xy 31.07175 33.627) (xy 30.377 33.627) (xy 30.377 33.647) (xy 30.123 33.647) + (xy 30.123 33.627) (xy 29.39875 33.627) (xy 29.382677 33.643073) (xy 29.367309 33.643059) (xy 29.35125 33.627) + (xy 28.627 33.627) (xy 28.627 34.37625) (xy 28.64292 34.39217) (xy 28.642887 34.430112) (xy 28.742698 34.671674) + (xy 28.843 34.772151) (xy 28.843 35.4) (xy 28.877787 35.574887) (xy 28.976852 35.723148) (xy 30.54726 37.293556) + (xy 30.428326 37.342698) (xy 30.243348 37.527354) (xy 30.143115 37.768741) (xy 30.142887 38.030112) (xy 30.242698 38.271674) + (xy 30.427354 38.456652) (xy 30.668741 38.556885) (xy 30.810713 38.557009) (xy 33.023025 40.769321) (xy 33.022877 40.93923) + (xy 33.122688 41.180792) (xy 33.307344 41.36577) (xy 33.548731 41.466003) (xy 33.810102 41.466231) (xy 34.051664 41.36642) + (xy 34.236642 41.181764) (xy 34.329926 40.957113) (xy 34.330112 40.957113) (xy 34.571674 40.857302) (xy 34.756652 40.672646) + (xy 34.856885 40.431259) (xy 34.857113 40.169888) (xy 34.757302 39.928326) (xy 34.572646 39.743348) (xy 34.331259 39.643115) + (xy 34.189286 39.642991) (xy 31.856439 37.310143) (xy 33.042887 37.310143) (xy 33.142698 37.551705) (xy 33.327354 37.736683) + (xy 33.568741 37.836916) (xy 33.710713 37.83704) (xy 39.043 43.169327) (xy 39.043 43.327875) (xy 38.943348 43.427354) + (xy 38.843115 43.668741) (xy 38.842887 43.930112) (xy 38.942698 44.171674) (xy 39.127354 44.356652) (xy 39.368741 44.456885) + (xy 39.630112 44.457113) (xy 39.871674 44.357302) (xy 40.056652 44.172646) (xy 40.156885 43.931259) (xy 40.157113 43.669888) + (xy 40.057302 43.428326) (xy 39.957 43.327849) (xy 39.957 42.980036) (xy 39.957001 42.980031) (xy 39.922213 42.805145) + (xy 39.823148 42.656883) (xy 34.35699 37.190725) (xy 34.357113 37.049919) (xy 34.257302 36.808357) (xy 34.072646 36.623379) + (xy 33.831259 36.523146) (xy 33.569888 36.522918) (xy 33.328326 36.622729) (xy 33.143348 36.807385) (xy 33.043115 37.048772) + (xy 33.042887 37.310143) (xy 31.856439 37.310143) (xy 30.223297 35.677001) (xy 31.936001 35.677001) (xy 32.187424 35.62699) + (xy 32.40057 35.48457) (xy 33.342964 34.542176) (xy 33.342887 34.630112) (xy 33.442698 34.871674) (xy 33.543 34.972151) + (xy 33.543 35.6) (xy 33.577787 35.774887) (xy 33.676852 35.923148) (xy 34.510896 36.757192) (xy 34.510686 36.997911) + (xy 34.610497 37.239473) (xy 34.795153 37.424451) (xy 35.03654 37.524684) (xy 35.297911 37.524912) (xy 35.539473 37.425101) + (xy 35.724451 37.240445) (xy 35.824684 36.999058) (xy 35.824773 36.897011) (xy 36.179906 36.897011) (xy 36.870825 37.58793) + (xy 36.72132 37.649704) (xy 36.536342 37.83436) (xy 36.436109 38.075747) (xy 36.435881 38.337118) (xy 36.535692 38.57868) + (xy 36.720348 38.763658) (xy 36.961735 38.863891) (xy 37.103707 38.864015) (xy 42.76284 44.523148) (xy 42.911102 44.622213) + (xy 43.085988 44.657) (xy 48.441102 44.657) (xy 49.127989 45.343886) (xy 49.127989 46.458553) (xy 49.162776 46.63344) + (xy 49.261841 46.781701) (xy 51.043 48.562859) (xy 51.043 48.6) (xy 51.077787 48.774887) (xy 51.176852 48.923148) + (xy 51.376852 49.123148) (xy 51.525114 49.222213) (xy 51.7 49.257) (xy 53.2 49.257) (xy 53.374887 49.222213) + (xy 53.523148 49.123148) (xy 53.882302 48.763994) (xy 54.568 48.763994) (xy 54.568 50.198018) (xy 52.733009 53.868) + (xy 22.266991 53.868) (xy 20.482991 50.3) (xy 22.568 50.3) (xy 22.571028 50.315224) (xy 22.569087 50.330624) + (xy 22.587376 50.397408) (xy 22.600884 50.465319) (xy 22.609507 50.478224) (xy 22.613607 50.493196) (xy 23.513607 52.293196) + (xy 23.556062 52.347899) (xy 23.59453 52.40547) (xy 23.607436 52.414094) (xy 23.616953 52.426356) (xy 23.677107 52.460646) + (xy 23.734681 52.499116) (xy 23.749906 52.502144) (xy 23.76339 52.509831) (xy 23.832085 52.518491) (xy 23.9 52.532) + (xy 51.1 52.532) (xy 51.167915 52.518491) (xy 51.23661 52.509831) (xy 51.250094 52.502144) (xy 51.265319 52.499116) + (xy 51.322893 52.460646) (xy 51.383047 52.426356) (xy 51.392564 52.414094) (xy 51.40547 52.40547) (xy 51.443938 52.347899) + (xy 51.486393 52.293196) (xy 52.386392 50.493196) (xy 52.390491 50.478227) (xy 52.399116 50.465319) (xy 52.412625 50.397403) + (xy 52.430913 50.330624) (xy 52.428972 50.315224) (xy 52.432 50.3) (xy 52.418491 50.232085) (xy 52.409831 50.16339) + (xy 52.402144 50.149906) (xy 52.399116 50.134681) (xy 52.360646 50.077107) (xy 52.326356 50.016953) (xy 52.314094 50.007436) + (xy 52.30547 49.99453) (xy 52.247894 49.956059) (xy 52.193196 49.913608) (xy 52.178227 49.909509) (xy 52.165319 49.900884) + (xy 52.097403 49.887375) (xy 52.030624 49.869087) (xy 52.015224 49.871028) (xy 52 49.868) (xy 23 49.868) + (xy 22.984776 49.871028) (xy 22.969376 49.869087) (xy 22.902592 49.887376) (xy 22.834681 49.900884) (xy 22.821776 49.909507) + (xy 22.806804 49.913607) (xy 22.752101 49.956062) (xy 22.69453 49.99453) (xy 22.685906 50.007436) (xy 22.673644 50.016953) + (xy 22.639354 50.077107) (xy 22.600884 50.134681) (xy 22.597856 50.149906) (xy 22.590169 50.16339) (xy 22.581509 50.232085) + (xy 22.568 50.3) (xy 20.482991 50.3) (xy 20.432 50.198018) (xy 20.432 49.436837) (xy 20.445172 49.463663) + (xy 20.785862 49.750902) (xy 21.21054 49.8859) (xy 21.48554 49.8859) (xy 21.48554 48.8779) (xy 21.73954 48.8779) + (xy 21.73954 49.8859) (xy 22.01454 49.8859) (xy 22.439218 49.750902) (xy 22.779908 49.463663) (xy 22.981659 49.052774) + (xy 22.855494 48.8779) (xy 21.73954 48.8779) (xy 21.48554 48.8779) (xy 21.46554 48.8779) (xy 21.46554 48.6239) + (xy 21.48554 48.6239) (xy 21.48554 47.6159) (xy 21.73954 47.6159) (xy 21.73954 48.6239) (xy 22.855494 48.6239) + (xy 22.981659 48.449026) (xy 22.786731 48.052031) (xy 23.211311 48.052031) (xy 23.352972 48.461949) (xy 23.640719 48.786452) + (xy 24.014602 48.970168) (xy 24.18554 48.843634) (xy 24.18554 47.8779) (xy 24.43954 47.8779) (xy 24.43954 48.843634) + (xy 24.610478 48.970168) (xy 24.984361 48.786452) (xy 25.272108 48.461949) (xy 25.413769 48.052031) (xy 25.399869 48.03575) + (xy 33.849 48.03575) (xy 33.849 48.89231) (xy 33.945673 49.125699) (xy 34.124302 49.304327) (xy 34.357691 49.401) + (xy 35.21425 49.401) (xy 35.373 49.24225) (xy 35.373 47.877) (xy 35.627 47.877) (xy 35.627 49.24225) + (xy 35.78575 49.401) (xy 36.642309 49.401) (xy 36.875698 49.304327) (xy 37.054327 49.125699) (xy 37.151 48.89231) + (xy 37.151 48.03575) (xy 36.99225 47.877) (xy 35.627 47.877) (xy 35.373 47.877) (xy 34.00775 47.877) + (xy 33.849 48.03575) (xy 25.399869 48.03575) (xy 25.265103 47.8779) (xy 24.43954 47.8779) (xy 24.18554 47.8779) + (xy 23.359977 47.8779) (xy 23.211311 48.052031) (xy 22.786731 48.052031) (xy 22.779908 48.038137) (xy 22.439218 47.750898) + (xy 22.01454 47.6159) (xy 21.73954 47.6159) (xy 21.48554 47.6159) (xy 21.21054 47.6159) (xy 20.785862 47.750898) + (xy 20.445172 48.038137) (xy 20.432 48.064963) (xy 20.432 42.436837) (xy 20.445172 42.463663) (xy 20.785862 42.750902) + (xy 21.21054 42.8859) (xy 21.48554 42.8859) (xy 21.48554 41.8779) (xy 21.73954 41.8779) (xy 21.73954 42.8859) + (xy 22.01454 42.8859) (xy 22.439218 42.750902) (xy 22.563696 42.645953) (xy 22.543 42.75) (xy 22.543 45) + (xy 22.577787 45.174887) (xy 22.676852 45.323148) (xy 22.927752 45.574048) (xy 23.076013 45.673113) (xy 23.2509 45.7079) + (xy 23.273546 45.7079) (xy 23.273546 46.1009) (xy 23.29793 46.23049) (xy 23.273546 46.3509) (xy 23.273546 46.7509) + (xy 23.298439 46.883196) (xy 23.376626 47.004702) (xy 23.381305 47.007899) (xy 23.352972 47.039851) (xy 23.211311 47.449769) + (xy 23.359977 47.6239) (xy 24.18554 47.6239) (xy 24.18554 47.6039) (xy 24.43954 47.6039) (xy 24.43954 47.6239) + (xy 25.265103 47.6239) (xy 25.413769 47.449769) (xy 25.330183 47.2079) (xy 25.4491 47.2079) (xy 25.700523 47.157889) + (xy 25.817661 47.07962) (xy 25.871674 47.057302) (xy 25.9134 47.015649) (xy 25.913669 47.015469) (xy 25.96457 46.964568) + (xy 26.056652 46.872646) (xy 26.106987 46.751425) (xy 26.106989 46.751423) (xy 26.10699 46.75142) (xy 26.156885 46.631259) + (xy 26.156905 46.60769) (xy 33.849 46.60769) (xy 33.849 47.46425) (xy 34.00775 47.623) (xy 35.373 47.623) + (xy 35.373 47.603) (xy 35.627 47.603) (xy 35.627 47.623) (xy 36.99225 47.623) (xy 37.151 47.46425) + (xy 37.151 46.60769) (xy 37.054327 46.374301) (xy 36.875698 46.195673) (xy 36.642309 46.099) (xy 36.552453 46.099) + (xy 36.795386 45.735424) (xy 36.808996 45.667) (xy 37.020704 45.667) (xy 40.34301 48.989306) (xy 40.342887 49.130112) + (xy 40.442698 49.371674) (xy 40.627354 49.556652) (xy 40.868741 49.656885) (xy 41.130112 49.657113) (xy 41.371674 49.557302) + (xy 41.556652 49.372646) (xy 41.656885 49.131259) (xy 41.657113 48.869888) (xy 41.557302 48.628326) (xy 41.372646 48.443348) + (xy 41.131259 48.343115) (xy 40.989287 48.342991) (xy 37.533148 44.886852) (xy 37.384887 44.787787) (xy 37.21 44.753) + (xy 36.808996 44.753) (xy 36.795386 44.684576) (xy 36.497757 44.239142) (xy 36.052323 43.941513) (xy 35.526899 43.837) + (xy 35.473101 43.837) (xy 34.947677 43.941513) (xy 34.502243 44.239142) (xy 34.204614 44.684576) (xy 34.100101 45.21) + (xy 34.204614 45.735424) (xy 34.447547 46.099) (xy 34.357691 46.099) (xy 34.124302 46.195673) (xy 33.945673 46.374301) + (xy 33.849 46.60769) (xy 26.156905 46.60769) (xy 26.157113 46.369888) (xy 26.057302 46.128326) (xy 25.912762 45.983534) + (xy 26.323148 45.573148) (xy 26.422213 45.424886) (xy 26.457001 45.25) (xy 26.457 45.249995) (xy 26.457 42.722125) + (xy 26.556652 42.622646) (xy 26.656885 42.381259) (xy 26.657113 42.119888) (xy 26.557302 41.878326) (xy 26.429138 41.749938) + (xy 26.556652 41.622646) (xy 26.656885 41.381259) (xy 26.657113 41.119888) (xy 26.557302 40.878326) (xy 26.372646 40.693348) + (xy 26.131259 40.593115) (xy 25.869888 40.592887) (xy 25.628326 40.692698) (xy 25.443348 40.877354) (xy 25.343115 41.118741) + (xy 25.342991 41.260713) (xy 25.310704 41.293) (xy 24.000005 41.293) (xy 24 41.292999) (xy 23.825114 41.327787) + (xy 23.676852 41.426852) (xy 23.67685 41.426855) (xy 22.914835 42.18887) (xy 22.981659 42.052774) (xy 22.855494 41.8779) + (xy 21.73954 41.8779) (xy 21.48554 41.8779) (xy 21.46554 41.8779) (xy 21.46554 41.6239) (xy 21.48554 41.6239) + (xy 21.48554 40.6159) (xy 21.73954 40.6159) (xy 21.73954 41.6239) (xy 22.855494 41.6239) (xy 22.981659 41.449026) + (xy 22.779908 41.038137) (xy 22.439218 40.750898) (xy 22.01454 40.6159) (xy 21.73954 40.6159) (xy 21.48554 40.6159) + (xy 21.21054 40.6159) (xy 20.785862 40.750898) (xy 20.445172 41.038137) (xy 20.432 41.064963) (xy 20.432 37.61825) + (xy 21.292722 37.61825) (xy 21.536857 38.209103) (xy 21.988519 38.661554) (xy 22.578946 38.90672) (xy 23.21825 38.907278) + (xy 23.809103 38.663143) (xy 24.261554 38.211481) (xy 24.50672 37.621054) (xy 24.507278 36.98175) (xy 24.263143 36.390897) + (xy 23.811481 35.938446) (xy 23.221054 35.69328) (xy 22.58175 35.692722) (xy 21.990897 35.936857) (xy 21.538446 36.388519) + (xy 21.29328 36.978946) (xy 21.292722 37.61825) (xy 20.432 37.61825) (xy 20.432 32.727) (xy 22.809189 32.727) + (xy 22.906842 32.873148) (xy 25.523 35.489306) (xy 25.522877 35.630112) (xy 25.622688 35.871674) (xy 25.807344 36.056652) + (xy 26.048731 36.156885) (xy 26.310102 36.157113) (xy 26.551664 36.057302) (xy 26.736642 35.872646) (xy 26.836875 35.631259) + (xy 26.837103 35.369888) (xy 26.737292 35.128326) (xy 26.552636 34.943348) (xy 26.311249 34.843115) (xy 26.169277 34.842991) + (xy 25.112036 33.78575) (xy 25.74 33.78575) (xy 25.74 34.026309) (xy 25.836673 34.259698) (xy 26.015301 34.438327) + (xy 26.24869 34.535) (xy 26.46425 34.535) (xy 26.623 34.37625) (xy 26.623 33.627) (xy 26.877 33.627) + (xy 26.877 34.37625) (xy 27.03575 34.535) (xy 27.25131 34.535) (xy 27.484699 34.438327) (xy 27.625 34.298025) + (xy 27.765301 34.438327) (xy 27.99869 34.535) (xy 28.21425 34.535) (xy 28.373 34.37625) (xy 28.373 33.627) + (xy 27.64875 33.627) (xy 27.625 33.65075) (xy 27.60125 33.627) (xy 26.877 33.627) (xy 26.623 33.627) + (xy 25.89875 33.627) (xy 25.74 33.78575) (xy 25.112036 33.78575) (xy 24.000355 32.674069) (xy 24.018315 32.646159) + (xy 24.027 32.6) (xy 24.027 27.951032) + ) + ) + (filled_polygon + (pts + (xy 25.442698 42.621674) (xy 25.543 42.722151) (xy 25.543 43.432564) (xy 25.525867 43.391201) (xy 25.35545 43.220785) + (xy 25.413769 43.052031) (xy 25.265103 42.8779) (xy 24.43954 42.8779) (xy 24.43954 43.8509) (xy 24.449356 43.8509) + (xy 24.45954 43.858439) (xy 24.45954 44.036906) (xy 24.16554 44.036906) (xy 24.16554 43.858439) (xy 24.175724 43.8509) + (xy 24.18554 43.8509) (xy 24.18554 42.8779) (xy 24.16554 42.8779) (xy 24.16554 42.6239) (xy 24.18554 42.6239) + (xy 24.18554 42.6039) (xy 24.43954 42.6039) (xy 24.43954 42.6239) (xy 25.265103 42.6239) (xy 25.385399 42.482999) + ) + ) + (filled_polygon + (pts + (xy 49.596853 21.743149) (xy 49.745115 21.842214) (xy 49.920001 21.877001) (xy 50.749601 21.877001) (xy 50.924488 21.842214) + (xy 51.072749 21.743149) (xy 51.158898 21.657) (xy 51.536006 21.657) (xy 51.536006 21.743) (xy 51.378998 21.743) + (xy 51.204112 21.777787) (xy 51.05585 21.876852) (xy 49.581851 23.350851) (xy 49.482786 23.499112) (xy 49.462206 23.602576) + (xy 49.447999 23.673999) (xy 49.447999 24.826001) (xy 49.482786 25.000888) (xy 49.54421 25.092816) (xy 49.49 25.223691) + (xy 49.49 25.46425) (xy 49.64875 25.623) (xy 50.373 25.623) (xy 50.373 25.603) (xy 50.627 25.603) + (xy 50.627 25.623) (xy 50.647 25.623) (xy 50.647 25.877) (xy 50.627 25.877) (xy 50.627 26.62625) + (xy 50.78575 26.785) (xy 51.00131 26.785) (xy 51.234699 26.688327) (xy 51.413327 26.509698) (xy 51.51 26.276309) + (xy 51.51 26.235294) (xy 51.943 26.668294) (xy 51.943 26.836006) (xy 51.9 26.836006) (xy 51.767704 26.860899) + (xy 51.646198 26.939086) (xy 51.564684 27.058386) (xy 51.536006 27.2) (xy 51.536006 28.011632) (xy 50.873819 28.673819) + (xy 50.758496 28.846412) (xy 50.718 29.05) (xy 50.718 30.95) (xy 50.758496 31.153588) (xy 50.813566 31.236006) + (xy 50.873819 31.326181) (xy 51.536006 31.988368) (xy 51.536006 32.8) (xy 51.560899 32.932296) (xy 51.639086 33.053802) + (xy 51.758386 33.135316) (xy 51.868 33.157514) (xy 51.868 36.842027) (xy 51.767704 36.860899) (xy 51.646198 36.939086) + (xy 51.564684 37.058386) (xy 51.536006 37.2) (xy 51.536006 37.268) (xy 51.45 37.268) (xy 51.246412 37.308496) + (xy 51.176937 37.354918) (xy 51.073819 37.423819) (xy 50.123819 38.373819) (xy 50.008496 38.546412) (xy 49.968 38.75) + (xy 49.968 40.651435) (xy 49.917704 40.660899) (xy 49.796198 40.739086) (xy 49.714684 40.858386) (xy 49.686006 41) + (xy 49.686006 41.5) (xy 49.710899 41.632296) (xy 49.789086 41.753802) (xy 49.908386 41.835316) (xy 50.05 41.863994) + (xy 50.95 41.863994) (xy 51.082296 41.839101) (xy 51.171033 41.782) (xy 51.329638 41.782) (xy 51.536006 41.988368) + (xy 51.536006 42.255409) (xy 51.488327 42.140302) (xy 51.309699 41.961673) (xy 51.07631 41.865) (xy 50.78575 41.865) + (xy 50.627 42.02375) (xy 50.627 42.625) (xy 50.647 42.625) (xy 50.647 42.875) (xy 50.627 42.875) + (xy 50.627 44.123) (xy 50.647 44.123) (xy 50.647 44.377) (xy 50.627 44.377) (xy 50.627 44.397) + (xy 50.373 44.397) (xy 50.373 44.377) (xy 49.64875 44.377) (xy 49.551222 44.474528) (xy 48.953546 43.876852) + (xy 48.805285 43.777787) (xy 48.630398 43.743) (xy 43.275284 43.743) (xy 42.566034 43.03375) (xy 49.415 43.03375) + (xy 49.415 43.126309) (xy 49.511673 43.359698) (xy 49.614475 43.4625) (xy 49.586673 43.490302) (xy 49.49 43.723691) + (xy 49.49 43.96425) (xy 49.64875 44.123) (xy 50.373 44.123) (xy 50.373 42.875) (xy 49.57375 42.875) + (xy 49.415 43.03375) (xy 42.566034 43.03375) (xy 41.683635 42.151351) (xy 41.712033 42.157) (xy 42.346702 42.157) + (xy 42.346702 42.516) (xy 42.371595 42.648296) (xy 42.449782 42.769802) (xy 42.569082 42.851316) (xy 42.710696 42.879994) + (xy 44.742696 42.879994) (xy 44.874992 42.855101) (xy 44.996498 42.776914) (xy 45.078012 42.657614) (xy 45.10669 42.516) + (xy 45.10669 42.214677) (xy 45.295838 42.497757) (xy 45.741272 42.795386) (xy 46.266696 42.899899) (xy 46.79212 42.795386) + (xy 47.237554 42.497757) (xy 47.320452 42.373691) (xy 49.415 42.373691) (xy 49.415 42.46625) (xy 49.57375 42.625) + (xy 50.373 42.625) (xy 50.373 42.02375) (xy 50.21425 41.865) (xy 49.92369 41.865) (xy 49.690301 41.961673) + (xy 49.511673 42.140302) (xy 49.415 42.373691) (xy 47.320452 42.373691) (xy 47.535183 42.052323) (xy 47.639696 41.526899) + (xy 47.639696 41.473101) (xy 47.535183 40.947677) (xy 47.237554 40.502243) (xy 46.79212 40.204614) (xy 46.758696 40.197966) + (xy 46.758696 39.737436) (xy 46.759042 39.737371) (xy 46.880548 39.659184) (xy 46.962062 39.539884) (xy 46.99074 39.39827) + (xy 46.99074 38.59817) (xy 46.965847 38.465874) (xy 46.901188 38.365391) (xy 46.956885 38.231259) (xy 46.957113 37.969888) + (xy 46.956597 37.968639) (xy 47.049696 37.87554) (xy 47.049696 37.12624) (xy 47.303696 37.12624) (xy 47.303696 37.87554) + (xy 47.462446 38.03429) (xy 47.703055 38.03429) (xy 47.936444 37.937617) (xy 48.115073 37.758989) (xy 48.211746 37.5256) + (xy 48.211746 37.28499) (xy 48.052996 37.12624) (xy 47.303696 37.12624) (xy 47.049696 37.12624) (xy 46.300396 37.12624) + (xy 46.141646 37.28499) (xy 46.141646 37.454556) (xy 46.019312 37.505104) (xy 46.04074 37.39929) (xy 46.04074 36.59919) + (xy 46.016974 36.47288) (xy 46.141646 36.47288) (xy 46.141646 36.71349) (xy 46.300396 36.87224) (xy 47.049696 36.87224) + (xy 47.049696 36.12294) (xy 47.303696 36.12294) (xy 47.303696 36.87224) (xy 48.052996 36.87224) (xy 48.211746 36.71349) + (xy 48.211746 36.47288) (xy 48.115073 36.239491) (xy 47.936444 36.060863) (xy 47.703055 35.96419) (xy 47.462446 35.96419) + (xy 47.303696 36.12294) (xy 47.049696 36.12294) (xy 46.890946 35.96419) (xy 46.650337 35.96419) (xy 46.416948 36.060863) + (xy 46.238319 36.239491) (xy 46.141646 36.47288) (xy 46.016974 36.47288) (xy 46.015847 36.466894) (xy 45.93766 36.345388) + (xy 45.81836 36.263874) (xy 45.676746 36.235196) (xy 44.876646 36.235196) (xy 44.74435 36.260089) (xy 44.622844 36.338276) + (xy 44.54133 36.457576) (xy 44.539373 36.46724) (xy 43.477456 36.46724) (xy 43.273868 36.507736) (xy 43.101769 36.622729) + (xy 43.101275 36.623059) (xy 43.088328 36.636006) (xy 42.776696 36.636006) (xy 42.6444 36.660899) (xy 42.522894 36.739086) + (xy 42.44138 36.858386) (xy 42.412702 37) (xy 42.412702 37.5) (xy 42.437595 37.632296) (xy 42.444483 37.643) + (xy 40.253195 37.643) (xy 39.276383 36.666188) (xy 39.430173 36.512666) (xy 39.530406 36.271279) (xy 39.530575 36.07701) + (xy 44.67999 36.07701) (xy 44.854877 36.042223) (xy 45.003138 35.943158) (xy 45.289305 35.65699) (xy 45.430112 35.657113) + (xy 45.671674 35.557302) (xy 45.856652 35.372646) (xy 45.956885 35.131259) (xy 45.957113 34.869888) (xy 45.857302 34.628326) + (xy 45.764138 34.535) (xy 45.877002 34.535) (xy 45.877002 34.376252) (xy 46.03575 34.535) (xy 46.25131 34.535) + (xy 46.484699 34.438327) (xy 46.663327 34.259698) (xy 46.76 34.026309) (xy 46.76 33.78575) (xy 46.60125 33.627) + (xy 45.877 33.627) (xy 45.877 33.647) (xy 45.623 33.647) (xy 45.623 33.627) (xy 44.89875 33.627) + (xy 44.875 33.65075) (xy 44.85125 33.627) (xy 44.127 33.627) (xy 44.127 33.647) (xy 43.873 33.647) + (xy 43.873 33.627) (xy 43.14875 33.627) (xy 42.99 33.78575) (xy 42.99 34.026309) (xy 43.086673 34.259698) + (xy 43.265301 34.438327) (xy 43.472855 34.524299) (xy 43.428326 34.542698) (xy 43.327849 34.643) (xy 42.573417 34.643) + (xy 42.584699 34.638327) (xy 42.763327 34.459698) (xy 42.86 34.226309) (xy 42.86 34.09075) (xy 42.70125 33.932) + (xy 42.1125 33.932) (xy 42.1125 33.952) (xy 41.8875 33.952) (xy 41.8875 33.932) (xy 41.29875 33.932) + (xy 41.14 34.09075) (xy 41.14 34.226309) (xy 41.236673 34.459698) (xy 41.415301 34.638327) (xy 41.426583 34.643) + (xy 39.479892 34.643) (xy 38.770087 33.933195) (xy 38.77021 33.792389) (xy 38.766641 33.78375) (xy 38.915 33.78375) + (xy 38.915 33.876309) (xy 39.011673 34.109698) (xy 39.190301 34.288327) (xy 39.42369 34.385) (xy 39.71425 34.385) + (xy 39.873 34.22625) (xy 39.873 33.625) (xy 40.127 33.625) (xy 40.127 34.22625) (xy 40.28575 34.385) + (xy 40.57631 34.385) (xy 40.809699 34.288327) (xy 40.988327 34.109698) (xy 41.085 33.876309) (xy 41.085 33.78375) + (xy 40.92625 33.625) (xy 40.127 33.625) (xy 39.873 33.625) (xy 39.07375 33.625) (xy 38.915 33.78375) + (xy 38.766641 33.78375) (xy 38.670399 33.550827) (xy 38.503554 33.383691) (xy 41.14 33.383691) (xy 41.14 33.51925) + (xy 41.29875 33.678) (xy 41.8875 33.678) (xy 41.8875 33.03375) (xy 42.1125 33.03375) (xy 42.1125 33.678) + (xy 42.70125 33.678) (xy 42.86 33.51925) (xy 42.86 33.383691) (xy 42.763327 33.150302) (xy 42.584699 32.971673) + (xy 42.35131 32.875) (xy 42.27125 32.875) (xy 42.1125 33.03375) (xy 41.8875 33.03375) (xy 41.72875 32.875) + (xy 41.64869 32.875) (xy 41.415301 32.971673) (xy 41.236673 33.150302) (xy 41.14 33.383691) (xy 38.503554 33.383691) + (xy 38.485743 33.365849) (xy 38.441189 33.347349) (xy 38.436245 33.339949) (xy 38.219987 33.123691) (xy 38.915 33.123691) + (xy 38.915 33.21625) (xy 39.07375 33.375) (xy 39.873 33.375) (xy 39.873 32.77375) (xy 40.127 32.77375) + (xy 40.127 33.375) (xy 40.92625 33.375) (xy 41.085 33.21625) (xy 41.085 33.123691) (xy 40.988327 32.890302) + (xy 40.809699 32.711673) (xy 40.57631 32.615) (xy 40.28575 32.615) (xy 40.127 32.77375) (xy 39.873 32.77375) + (xy 39.71425 32.615) (xy 39.42369 32.615) (xy 39.190301 32.711673) (xy 39.011673 32.890302) (xy 38.915 33.123691) + (xy 38.219987 33.123691) (xy 37.063994 31.967698) (xy 37.063994 31.75) (xy 37.039101 31.617704) (xy 36.960914 31.496198) + (xy 36.841614 31.414684) (xy 36.7 31.386006) (xy 36.67438 31.386006) (xy 36.672213 31.375114) (xy 36.573148 31.226852) + (xy 36.207 30.860704) (xy 36.207 29.36925) (xy 36.35 29.22625) (xy 36.35 28.960807) (xy 36.411673 29.109699) + (xy 36.590302 29.288327) (xy 36.627474 29.303724) (xy 36.70875 29.385) (xy 36.776309 29.385) (xy 36.8 29.375187) + (xy 36.823691 29.385) (xy 36.89125 29.385) (xy 36.972526 29.303724) (xy 37.009698 29.288327) (xy 37.15 29.148026) + (xy 37.290302 29.288327) (xy 37.327474 29.303724) (xy 37.40875 29.385) (xy 37.476309 29.385) (xy 37.5 29.375187) + (xy 37.523691 29.385) (xy 37.59125 29.385) (xy 37.672526 29.303724) (xy 37.709698 29.288327) (xy 37.888327 29.109699) + (xy 37.95 28.960807) (xy 37.95 29.22625) (xy 38.093 29.36925) (xy 38.093 30.1) (xy 38.127787 30.274887) + (xy 38.226852 30.423148) (xy 39.294815 31.491111) (xy 39.214684 31.608386) (xy 39.186006 31.75) (xy 39.186006 32.25) + (xy 39.210899 32.382296) (xy 39.289086 32.503802) (xy 39.408386 32.585316) (xy 39.55 32.613994) (xy 40.45 32.613994) + (xy 40.582296 32.589101) (xy 40.703802 32.510914) (xy 40.785316 32.391614) (xy 40.813994 32.25) (xy 40.813994 31.75) + (xy 40.789101 31.617704) (xy 40.710914 31.496198) (xy 40.591614 31.414684) (xy 40.45 31.386006) (xy 40.42438 31.386006) + (xy 40.422213 31.375114) (xy 40.323148 31.226852) (xy 39.653296 30.557) (xy 40.285704 30.557) (xy 41.411006 31.682302) + (xy 41.411006 31.99) (xy 41.435899 32.122296) (xy 41.514086 32.243802) (xy 41.633386 32.325316) (xy 41.775 32.353994) + (xy 42.225 32.353994) (xy 42.357296 32.329101) (xy 42.478802 32.250914) (xy 42.560316 32.131614) (xy 42.588994 31.99) + (xy 42.588994 31.4) (xy 42.564101 31.267704) (xy 42.485914 31.146198) (xy 42.366614 31.064684) (xy 42.225 31.036006) + (xy 42.057302 31.036006) (xy 41.578296 30.557) (xy 42.510704 30.557) (xy 43.339371 31.385667) (xy 43.289684 31.458386) + (xy 43.261006 31.6) (xy 43.261006 32.4) (xy 43.285899 32.532296) (xy 43.29649 32.548754) (xy 43.265301 32.561673) + (xy 43.086673 32.740302) (xy 42.99 32.973691) (xy 42.99 33.21425) (xy 43.14875 33.373) (xy 43.873 33.373) + (xy 43.873 33.353) (xy 44.127 33.353) (xy 44.127 33.373) (xy 44.85125 33.373) (xy 44.875 33.34925) + (xy 44.89875 33.373) (xy 45.623 33.373) (xy 45.623 33.353) (xy 45.877 33.353) (xy 45.877 33.373) + (xy 46.60125 33.373) (xy 46.676477 33.297773) (xy 46.761006 33.382302) (xy 46.761006 33.9) (xy 46.785899 34.032296) + (xy 46.864086 34.153802) (xy 46.983386 34.235316) (xy 47.125 34.263994) (xy 47.875 34.263994) (xy 48.007296 34.239101) + (xy 48.128802 34.160914) (xy 48.210316 34.041614) (xy 48.238994 33.9) (xy 48.238994 33.71029) (xy 48.351852 33.823148) + (xy 48.500114 33.922213) (xy 48.515772 33.925328) (xy 48.535899 34.032296) (xy 48.614086 34.153802) (xy 48.733386 34.235316) + (xy 48.875 34.263994) (xy 49.625 34.263994) (xy 49.757296 34.239101) (xy 49.878802 34.160914) (xy 49.960316 34.041614) + (xy 49.988994 33.9) (xy 49.988994 33.1) (xy 49.964101 32.967704) (xy 49.885914 32.846198) (xy 49.766614 32.764684) + (xy 49.696641 32.750514) (xy 49.757296 32.739101) (xy 49.878802 32.660914) (xy 49.960316 32.541614) (xy 49.988994 32.4) + (xy 49.988994 31.6) (xy 49.964101 31.467704) (xy 49.885914 31.346198) (xy 49.766614 31.264684) (xy 49.707 31.252612) + (xy 49.707 30.946002) (xy 49.696389 30.892656) (xy 49.672213 30.771115) (xy 49.573148 30.622854) (xy 48.22416 29.273866) + (xy 48.388327 29.109699) (xy 48.485 28.87631) (xy 48.485 27.53575) (xy 48.32625 27.377) (xy 47.75 27.377) + (xy 47.75 27.397) (xy 47.55 27.397) (xy 47.55 27.377) (xy 47.513994 27.377) (xy 47.513994 27.123) + (xy 47.55 27.123) (xy 47.55 25.27375) (xy 47.39125 25.115) (xy 47.323691 25.115) (xy 47.090302 25.211673) + (xy 46.915968 25.386006) (xy 46.75 25.386006) (xy 46.617704 25.410899) (xy 46.601415 25.421381) (xy 46.591614 25.414684) + (xy 46.45 25.386006) (xy 46.166778 25.386006) (xy 46.329789 25.223279) (xy 46.430022 24.981892) (xy 46.43025 24.720521) + (xy 46.330439 24.478959) (xy 46.145783 24.293981) (xy 45.904396 24.193748) (xy 45.643025 24.19352) (xy 45.401463 24.293331) + (xy 45.376117 24.318633) (xy 44.699367 24.318633) (xy 44.495779 24.359129) (xy 44.323186 24.474452) (xy 43.773819 25.023819) + (xy 43.658496 25.196412) (xy 43.620784 25.386006) (xy 43.484032 25.386006) (xy 43.309698 25.211673) (xy 43.076309 25.115) + (xy 43.00875 25.115) (xy 42.85 25.27375) (xy 42.85 27.123) (xy 42.886006 27.123) (xy 42.886006 27.377) + (xy 42.85 27.377) (xy 42.85 27.397) (xy 42.65 27.397) (xy 42.65 27.377) (xy 42.613994 27.377) + (xy 42.613994 27.123) (xy 42.65 27.123) (xy 42.65 25.27375) (xy 42.49125 25.115) (xy 42.423691 25.115) + (xy 42.190302 25.211673) (xy 42.05 25.351974) (xy 41.909698 25.211673) (xy 41.676309 25.115) (xy 41.60875 25.115) + (xy 41.45 25.27375) (xy 41.45 27.123) (xy 41.486006 27.123) (xy 41.486006 27.377) (xy 41.45 27.377) + (xy 41.45 27.397) (xy 41.25 27.397) (xy 41.25 27.377) (xy 41.213994 27.377) (xy 41.213994 27.123) + (xy 41.25 27.123) (xy 41.25 25.27375) (xy 41.09125 25.115) (xy 41.023691 25.115) (xy 40.790302 25.211673) + (xy 40.65 25.351974) (xy 40.509698 25.211673) (xy 40.276309 25.115) (xy 40.20875 25.115) (xy 40.05 25.27375) + (xy 40.05 25.539193) (xy 39.988327 25.390301) (xy 39.809698 25.211673) (xy 39.772526 25.196276) (xy 39.69125 25.115) + (xy 39.623691 25.115) (xy 39.6 25.124813) (xy 39.576309 25.115) (xy 39.50875 25.115) (xy 39.427474 25.196276) + (xy 39.390302 25.211673) (xy 39.211673 25.390301) (xy 39.15 25.539193) (xy 39.15 25.27375) (xy 38.99125 25.115) + (xy 38.923691 25.115) (xy 38.690302 25.211673) (xy 38.55 25.351974) (xy 38.409698 25.211673) (xy 38.176309 25.115) + (xy 38.10875 25.115) (xy 37.95 25.27375) (xy 37.95 25.539193) (xy 37.888327 25.390301) (xy 37.709698 25.211673) + (xy 37.672526 25.196276) (xy 37.59125 25.115) (xy 37.523691 25.115) (xy 37.5 25.124813) (xy 37.476309 25.115) + (xy 37.40875 25.115) (xy 37.327474 25.196276) (xy 37.290302 25.211673) (xy 37.15 25.351974) (xy 37.009698 25.211673) + (xy 36.972526 25.196276) (xy 36.89125 25.115) (xy 36.823691 25.115) (xy 36.8 25.124813) (xy 36.776309 25.115) + (xy 36.70875 25.115) (xy 36.627474 25.196276) (xy 36.590302 25.211673) (xy 36.411673 25.390301) (xy 36.35 25.539193) + (xy 36.35 25.27375) (xy 36.19125 25.115) (xy 36.123691 25.115) (xy 35.890302 25.211673) (xy 35.715968 25.386006) + (xy 35.55 25.386006) (xy 35.417704 25.410899) (xy 35.401415 25.421381) (xy 35.391614 25.414684) (xy 35.25 25.386006) + (xy 34.85 25.386006) (xy 34.717704 25.410899) (xy 34.701415 25.421381) (xy 34.691614 25.414684) (xy 34.55 25.386006) + (xy 34.384032 25.386006) (xy 34.209698 25.211673) (xy 33.976309 25.115) (xy 33.90875 25.115) (xy 33.75 25.27375) + (xy 33.75 25.539193) (xy 33.688327 25.390301) (xy 33.509698 25.211673) (xy 33.472526 25.196276) (xy 33.39125 25.115) + (xy 33.323691 25.115) (xy 33.3 25.124813) (xy 33.276309 25.115) (xy 33.20875 25.115) (xy 33.127474 25.196276) + (xy 33.090302 25.211673) (xy 32.95 25.351974) (xy 32.809698 25.211673) (xy 32.772526 25.196276) (xy 32.69125 25.115) + (xy 32.623691 25.115) (xy 32.6 25.124813) (xy 32.576309 25.115) (xy 32.50875 25.115) (xy 32.427474 25.196276) + (xy 32.390302 25.211673) (xy 32.25 25.351974) (xy 32.109698 25.211673) (xy 32.072526 25.196276) (xy 31.99125 25.115) + (xy 31.923691 25.115) (xy 31.9 25.124813) (xy 31.876309 25.115) (xy 31.80875 25.115) (xy 31.727474 25.196276) + (xy 31.690302 25.211673) (xy 31.55 25.351974) (xy 31.409698 25.211673) (xy 31.372526 25.196276) (xy 31.29125 25.115) + (xy 31.223691 25.115) (xy 31.2 25.124813) (xy 31.176309 25.115) (xy 31.10875 25.115) (xy 31.027474 25.196276) + (xy 30.990302 25.211673) (xy 30.811673 25.390301) (xy 30.75 25.539193) (xy 30.75 25.27375) (xy 30.59125 25.115) + (xy 30.523691 25.115) (xy 30.290302 25.211673) (xy 30.115968 25.386006) (xy 29.95 25.386006) (xy 29.817704 25.410899) + (xy 29.801415 25.421381) (xy 29.791614 25.414684) (xy 29.65 25.386006) (xy 29.25 25.386006) (xy 29.117704 25.410899) + (xy 29.101415 25.421381) (xy 29.091614 25.414684) (xy 28.95 25.386006) (xy 28.784032 25.386006) (xy 28.609698 25.211673) + (xy 28.376309 25.115) (xy 28.30875 25.115) (xy 28.15 25.27375) (xy 28.15 25.539193) (xy 28.088327 25.390301) + (xy 27.909698 25.211673) (xy 27.872526 25.196276) (xy 27.79125 25.115) (xy 27.723691 25.115) (xy 27.7 25.124813) + (xy 27.676309 25.115) (xy 27.60875 25.115) (xy 27.527474 25.196276) (xy 27.490302 25.211673) (xy 27.311673 25.390301) + (xy 27.25 25.539193) (xy 27.25 25.27375) (xy 27.09125 25.115) (xy 27.023691 25.115) (xy 26.907 25.163335) + (xy 26.907 24.657006) (xy 27.030112 24.657113) (xy 27.271674 24.557302) (xy 27.456652 24.372646) (xy 27.514031 24.234463) + (xy 31.635811 24.234463) (xy 31.810698 24.199676) (xy 31.958959 24.100611) (xy 34.601995 21.457575) (xy 34.722605 21.457575) + (xy 34.843 21.57797) (xy 34.843 22.680596) (xy 34.877787 22.855483) (xy 34.976852 23.003744) (xy 36.016257 24.043149) + (xy 36.164519 24.142214) (xy 36.339405 24.177002) (xy 36.33941 24.177001) (xy 46.094297 24.177001) (xy 46.269184 24.142214) + (xy 46.417445 24.043149) (xy 47.025397 23.435197) (xy 47.958503 23.435197) (xy 48.043 23.519693) (xy 48.043 24.827875) + (xy 47.943348 24.927354) (xy 47.843115 25.168741) (xy 47.843105 25.180645) (xy 47.75 25.27375) (xy 47.75 27.123) + (xy 48.32625 27.123) (xy 48.485 26.96425) (xy 48.485 26.03575) (xy 49.49 26.03575) (xy 49.49 26.276309) + (xy 49.586673 26.509698) (xy 49.765301 26.688327) (xy 49.99869 26.785) (xy 50.21425 26.785) (xy 50.373 26.62625) + (xy 50.373 25.877) (xy 49.64875 25.877) (xy 49.49 26.03575) (xy 48.485 26.03575) (xy 48.485 25.956986) + (xy 48.630112 25.957113) (xy 48.871674 25.857302) (xy 49.056652 25.672646) (xy 49.156885 25.431259) (xy 49.157113 25.169888) + (xy 49.057302 24.928326) (xy 48.957 24.827849) (xy 48.957 23.330398) (xy 48.922213 23.155512) (xy 48.823148 23.00725) + (xy 48.823145 23.007248) (xy 48.470947 22.655049) (xy 48.322686 22.555984) (xy 48.147799 22.521197) (xy 46.836101 22.521197) + (xy 46.661214 22.555984) (xy 46.512953 22.655049) (xy 45.905001 23.263001) (xy 37.989361 23.263001) (xy 38.420362 22.832) + (xy 44.302745 22.832) (xy 44.327354 22.856652) (xy 44.568741 22.956885) (xy 44.830112 22.957113) (xy 45.071674 22.857302) + (xy 45.256652 22.672646) (xy 45.356885 22.431259) (xy 45.357113 22.169888) (xy 45.257302 21.928326) (xy 45.072646 21.743348) + (xy 44.831259 21.643115) (xy 44.569888 21.642887) (xy 44.328326 21.742698) (xy 44.30298 21.768) (xy 44.078296 21.768) + (xy 44.589296 21.257) (xy 49.110704 21.257) + ) + ) + (filled_polygon + (pts + (xy 31.190301 34.288327) (xy 31.37058 34.363001) (xy 31.060025 34.363001) (xy 31.1625 34.260525) + ) + ) + (filled_polygon + (pts + (xy 30.940554 20.43963) (xy 30.970767 20.469906) (xy 30.99453 20.50547) (xy 31.029722 20.528985) (xy 31.059618 20.558943) + (xy 31.099116 20.575352) (xy 31.134681 20.599116) (xy 31.176192 20.607373) (xy 31.215278 20.623611) (xy 31.25805 20.623656) + (xy 31.3 20.632) (xy 34.157538 20.632) (xy 34.089551 20.677427) (xy 31.446515 23.320463) (xy 29.65508 23.320463) + (xy 29.655248 23.12735) (xy 29.555437 22.885788) (xy 29.370781 22.70081) (xy 29.24956 22.650475) (xy 29.249558 22.650473) + (xy 29.249555 22.650472) (xy 29.129394 22.600577) (xy 28.998138 22.600463) (xy 28.998135 22.600462) (xy 28.997562 22.600462) + (xy 28.868023 22.600349) (xy 28.86775 22.600462) (xy 26.576936 22.600462) (xy 26.325513 22.650473) (xy 26.112367 22.792893) + (xy 25.71543 23.18983) (xy 25.57301 23.402976) (xy 25.522999 23.654399) (xy 25.522999 24.345601) (xy 25.57301 24.597024) + (xy 25.592907 24.626802) (xy 25.592887 24.650187) (xy 25.593 24.65046) (xy 25.593 26.5) (xy 25.592887 26.630112) + (xy 25.593 26.630385) (xy 25.593 28.14887) (xy 25.611764 28.243204) (xy 24.207 26.83844) (xy 24.207 24.722125) + (xy 24.306652 24.622646) (xy 24.406885 24.381259) (xy 24.407113 24.119888) (xy 24.307302 23.878326) (xy 24.122646 23.693348) + (xy 24.027 23.653632) (xy 24.027 20.332) (xy 30.868801 20.332) + ) + ) + (filled_polygon + (pts + (xy 28.15 27.123) (xy 28.186006 27.123) (xy 28.186006 27.377) (xy 28.15 27.377) (xy 28.15 27.50075) + (xy 28.02625 27.377) (xy 27.37375 27.377) (xy 27.25 27.50075) (xy 27.25 27.377) (xy 27.203 27.377) + (xy 27.203 27.123) (xy 27.25 27.123) (xy 27.25 26.99925) (xy 27.37375 27.123) (xy 28.02625 27.123) + (xy 28.15 26.99925) + ) + ) + (filled_polygon + (pts + (xy 37.95 27.123) (xy 37.986006 27.123) (xy 37.986006 27.377) (xy 37.95 27.377) (xy 37.95 27.50075) + (xy 37.82625 27.377) (xy 37.17375 27.377) (xy 37.15 27.40075) (xy 37.12625 27.377) (xy 36.47375 27.377) + (xy 36.35 27.50075) (xy 36.35 27.377) (xy 36.313994 27.377) (xy 36.313994 27.123) (xy 36.35 27.123) + (xy 36.35 26.99925) (xy 36.47375 27.123) (xy 37.12625 27.123) (xy 37.15 27.09925) (xy 37.17375 27.123) + (xy 37.82625 27.123) (xy 37.95 26.99925) + ) + ) + (filled_polygon + (pts + (xy 33.75 27.123) (xy 33.786006 27.123) (xy 33.786006 27.377) (xy 33.75 27.377) (xy 33.75 27.397) + (xy 33.64625 27.397) (xy 33.62625 27.377) (xy 32.97375 27.377) (xy 32.95375 27.397) (xy 32.94625 27.397) + (xy 32.92625 27.377) (xy 32.27375 27.377) (xy 32.25375 27.397) (xy 32.24625 27.397) (xy 32.22625 27.377) + (xy 31.57375 27.377) (xy 31.55375 27.397) (xy 31.54625 27.397) (xy 31.52625 27.377) (xy 30.87375 27.377) + (xy 30.85375 27.397) (xy 30.75 27.397) (xy 30.75 27.377) (xy 30.713994 27.377) (xy 30.713994 27.123) + (xy 30.75 27.123) (xy 30.75 26.99925) (xy 30.87375 27.123) (xy 31.52625 27.123) (xy 31.55 27.09925) + (xy 31.57375 27.123) (xy 32.22625 27.123) (xy 32.25 27.09925) (xy 32.27375 27.123) (xy 32.92625 27.123) + (xy 32.95 27.09925) (xy 32.97375 27.123) (xy 33.62625 27.123) (xy 33.75 26.99925) + ) + ) + (filled_polygon + (pts + (xy 40.05 27.123) (xy 40.086006 27.123) (xy 40.086006 27.377) (xy 40.05 27.377) (xy 40.05 27.397) + (xy 39.94625 27.397) (xy 39.92625 27.377) (xy 39.27375 27.377) (xy 39.25375 27.397) (xy 39.15 27.397) + (xy 39.15 27.377) (xy 39.113994 27.377) (xy 39.113994 27.123) (xy 39.15 27.123) (xy 39.15 26.99925) + (xy 39.27375 27.123) (xy 39.92625 27.123) (xy 40.05 26.99925) + ) + ) + (filled_polygon + (pts + (xy 54.568 20.001982) (xy 54.568 21.236006) (xy 53.882302 21.236006) (xy 53.523148 20.876852) (xy 53.374887 20.777787) + (xy 53.2 20.743) (xy 50.969602 20.743) (xy 50.794716 20.777787) (xy 50.794714 20.777788) (xy 50.794715 20.777788) + (xy 50.646454 20.876852) (xy 50.560305 20.963001) (xy 50.109297 20.963001) (xy 49.623148 20.476852) (xy 49.474887 20.377787) + (xy 49.3 20.343) (xy 44.4 20.343) (xy 44.225114 20.377787) (xy 44.076852 20.476852) (xy 43.115714 21.43799) + (xy 36.30501 21.43799) (xy 36.130123 21.472777) (xy 35.981862 21.571842) (xy 35.971862 21.581842) (xy 35.97186 21.581845) + (xy 35.910695 21.64301) (xy 35.769888 21.642887) (xy 35.757 21.648212) (xy 35.757 21.388674) (xy 35.747136 21.339086) + (xy 35.722213 21.213787) (xy 35.623148 21.065526) (xy 35.235049 20.677427) (xy 35.167063 20.632) (xy 43.7 20.632) + (xy 43.74195 20.623656) (xy 43.784722 20.623611) (xy 43.823808 20.607373) (xy 43.865319 20.599116) (xy 43.900884 20.575352) + (xy 43.940382 20.558943) (xy 43.970278 20.528985) (xy 44.00547 20.50547) (xy 44.029233 20.469906) (xy 44.059446 20.43963) + (xy 44.1312 20.332) (xy 52 20.332) (xy 52.015224 20.328972) (xy 52.030624 20.330913) (xy 52.097403 20.312625) + (xy 52.165319 20.299116) (xy 52.178227 20.290491) (xy 52.193196 20.286392) (xy 52.247894 20.243941) (xy 52.30547 20.20547) + (xy 52.314094 20.192564) (xy 52.326356 20.183047) (xy 52.360646 20.122893) (xy 52.399116 20.065319) (xy 52.402144 20.050094) + (xy 52.409831 20.03661) (xy 52.418491 19.967915) (xy 52.432 19.9) (xy 52.428972 19.884776) (xy 52.430913 19.869376) + (xy 52.412625 19.802597) (xy 52.399116 19.734681) (xy 52.390491 19.721773) (xy 52.386392 19.706804) (xy 51.486393 17.906804) + (xy 51.443938 17.852101) (xy 51.40547 17.79453) (xy 51.392564 17.785906) (xy 51.383047 17.773644) (xy 51.322893 17.739354) + (xy 51.265319 17.700884) (xy 51.250094 17.697856) (xy 51.23661 17.690169) (xy 51.167915 17.681509) (xy 51.1 17.668) + (xy 23.9 17.668) (xy 23.832085 17.681509) (xy 23.76339 17.690169) (xy 23.749906 17.697856) (xy 23.734681 17.700884) + (xy 23.677107 17.739354) (xy 23.616953 17.773644) (xy 23.607436 17.785906) (xy 23.59453 17.79453) (xy 23.556062 17.852101) + (xy 23.513607 17.906804) (xy 22.613607 19.706804) (xy 22.609507 19.721776) (xy 22.600884 19.734681) (xy 22.593262 19.773) + (xy 20.546491 19.773) (xy 22.266991 16.332) (xy 52.733009 16.332) + ) + ) + ) + (zone (net 3) (net_name GND) (layer F.Cu) (tstamp 0) (hatch edge 0.508) + (connect_pads (clearance 0.23)) + (min_thickness 0.254) + (fill yes (arc_segments 16) (thermal_gap 0.508) (thermal_bridge_width 0.508)) + (polygon + (pts + (xy 17.5 12.5) (xy 17.5 19.9) (xy 23.9 19.9) (xy 23.9 32.6) (xy 17.5 32.6) + (xy 17.5 57.5) (xy 57.5 57.5) (xy 57.5 12.5) + ) + ) + (filled_polygon + (pts + (xy 54.568 20.001982) (xy 54.568 50.198018) (xy 52.733009 53.868) (xy 22.266991 53.868) (xy 20.432 50.198018) + (xy 20.432 49.436837) (xy 20.445172 49.463663) (xy 20.785862 49.750902) (xy 21.21054 49.8859) (xy 21.48554 49.8859) + (xy 21.48554 48.8779) (xy 21.73954 48.8779) (xy 21.73954 49.8859) (xy 22.01454 49.8859) (xy 22.439218 49.750902) + (xy 22.779908 49.463663) (xy 22.981659 49.052774) (xy 22.969377 49.03575) (xy 25.74 49.03575) (xy 25.74 49.276309) + (xy 25.836673 49.509698) (xy 26.015301 49.688327) (xy 26.24869 49.785) (xy 26.46425 49.785) (xy 26.623 49.62625) + (xy 26.623 48.877) (xy 25.89875 48.877) (xy 25.74 49.03575) (xy 22.969377 49.03575) (xy 22.855494 48.8779) + (xy 21.73954 48.8779) (xy 21.48554 48.8779) (xy 21.46554 48.8779) (xy 21.46554 48.6239) (xy 21.48554 48.6239) + (xy 21.48554 47.6159) (xy 21.73954 47.6159) (xy 21.73954 48.6239) (xy 22.855494 48.6239) (xy 22.981659 48.449026) + (xy 22.786731 48.052031) (xy 23.211311 48.052031) (xy 23.352972 48.461949) (xy 23.640719 48.786452) (xy 24.014602 48.970168) + (xy 24.18554 48.843634) (xy 24.18554 47.8779) (xy 24.43954 47.8779) (xy 24.43954 48.843634) (xy 24.610478 48.970168) + (xy 24.984361 48.786452) (xy 25.272108 48.461949) (xy 25.413769 48.052031) (xy 25.265103 47.8779) (xy 24.43954 47.8779) + (xy 24.18554 47.8779) (xy 23.359977 47.8779) (xy 23.211311 48.052031) (xy 22.786731 48.052031) (xy 22.779908 48.038137) + (xy 22.439218 47.750898) (xy 22.01454 47.6159) (xy 21.73954 47.6159) (xy 21.48554 47.6159) (xy 21.21054 47.6159) + (xy 20.785862 47.750898) (xy 20.445172 48.038137) (xy 20.432 48.064963) (xy 20.432 43.052031) (xy 23.211311 43.052031) + (xy 23.352972 43.461949) (xy 23.358637 43.468338) (xy 23.336673 43.490302) (xy 23.24 43.723691) (xy 23.24 43.96425) + (xy 23.39875 44.123) (xy 24.123 44.123) (xy 24.123 43.889928) (xy 24.18554 43.843634) (xy 24.18554 42.8779) + (xy 23.359977 42.8779) (xy 23.211311 43.052031) (xy 20.432 43.052031) (xy 20.432 42.436837) (xy 20.445172 42.463663) + (xy 20.785862 42.750902) (xy 21.21054 42.8859) (xy 21.48554 42.8859) (xy 21.48554 41.8779) (xy 21.73954 41.8779) + (xy 21.73954 42.8859) (xy 22.01454 42.8859) (xy 22.439218 42.750902) (xy 22.779908 42.463663) (xy 22.981659 42.052774) + (xy 22.855494 41.8779) (xy 21.73954 41.8779) (xy 21.48554 41.8779) (xy 21.46554 41.8779) (xy 21.46554 41.6239) + (xy 21.48554 41.6239) (xy 21.48554 41.6039) (xy 21.73954 41.6039) (xy 21.73954 41.6239) (xy 22.855494 41.6239) + (xy 22.981659 41.449026) (xy 22.779908 41.038137) (xy 22.627927 40.91) (xy 22.826309 40.91) (xy 23.059698 40.813327) + (xy 23.238327 40.634699) (xy 23.250624 40.605012) (xy 23.258386 40.610316) (xy 23.343 40.627451) (xy 23.343 40.819602) + (xy 23.377787 40.994489) (xy 23.476852 41.14275) (xy 23.914783 41.580681) (xy 23.640719 41.715348) (xy 23.352972 42.039851) + (xy 23.211311 42.449769) (xy 23.359977 42.6239) (xy 24.18554 42.6239) (xy 24.18554 42.6039) (xy 24.43954 42.6039) + (xy 24.43954 42.6239) (xy 24.45954 42.6239) (xy 24.45954 42.8779) (xy 24.43954 42.8779) (xy 24.43954 43.31121) + (xy 24.377 43.37375) (xy 24.377 44.123) (xy 25.10125 44.123) (xy 25.26 43.96425) (xy 25.26 43.723691) + (xy 25.189957 43.554593) (xy 25.272108 43.461949) (xy 25.406672 43.072569) (xy 25.657248 43.323145) (xy 25.65725 43.323148) + (xy 25.805512 43.422213) (xy 25.980398 43.457) (xy 26.603533 43.457) (xy 26.608386 43.460316) (xy 26.75 43.488994) + (xy 27.114744 43.488994) (xy 27.14875 43.523) (xy 27.438654 43.523) (xy 27.64869 43.61) (xy 27.761006 43.61) + (xy 27.761006 44) (xy 27.785899 44.132296) (xy 27.8125 44.173635) (xy 27.8125 44.47625) (xy 27.97125 44.635) + (xy 27.981908 44.635) (xy 27.914684 44.733386) (xy 27.886006 44.875) (xy 27.886006 45.434856) (xy 27.613994 45.706868) + (xy 27.613994 44.875) (xy 27.589101 44.742704) (xy 27.519795 44.635) (xy 27.52875 44.635) (xy 27.6875 44.47625) + (xy 27.6875 43.777) (xy 27.14875 43.777) (xy 26.99 43.93575) (xy 26.99 44.126309) (xy 27.086673 44.359698) + (xy 27.23798 44.511006) (xy 26.25 44.511006) (xy 26.117704 44.535899) (xy 25.996198 44.614086) (xy 25.914684 44.733386) + (xy 25.886006 44.875) (xy 25.886006 45.434856) (xy 25.625 45.695862) (xy 25.214569 45.285431) (xy 25.018563 45.154463) + (xy 25.163327 45.009698) (xy 25.26 44.776309) (xy 25.26 44.53575) (xy 25.10125 44.377) (xy 24.377 44.377) + (xy 24.377 44.397) (xy 24.123 44.397) (xy 24.123 44.377) (xy 23.39875 44.377) (xy 23.24 44.53575) + (xy 23.24 44.776309) (xy 23.336673 45.009698) (xy 23.515301 45.188327) (xy 23.544988 45.200624) (xy 23.539684 45.208386) + (xy 23.511006 45.35) (xy 23.511006 46.15) (xy 23.535899 46.282296) (xy 23.614086 46.403802) (xy 23.733386 46.485316) + (xy 23.875 46.513994) (xy 24.185538 46.513994) (xy 24.185538 46.658165) (xy 24.014602 46.531632) (xy 23.640719 46.715348) + (xy 23.352972 47.039851) (xy 23.211311 47.449769) (xy 23.359977 47.6239) (xy 24.18554 47.6239) (xy 24.18554 47.6039) + (xy 24.43954 47.6039) (xy 24.43954 47.6239) (xy 25.265103 47.6239) (xy 25.413769 47.449769) (xy 25.303139 47.129645) + (xy 25.368741 47.156885) (xy 25.499997 47.156999) (xy 25.5 47.157) (xy 25.500573 47.157) (xy 25.630112 47.157113) + (xy 25.630385 47.157) (xy 25.75 47.157) (xy 26.001423 47.106989) (xy 26.011006 47.100586) (xy 26.011006 47.65) + (xy 26.035899 47.782296) (xy 26.04649 47.798754) (xy 26.015301 47.811673) (xy 25.836673 47.990302) (xy 25.74 48.223691) + (xy 25.74 48.46425) (xy 25.89875 48.623) (xy 26.623 48.623) (xy 26.623 48.603) (xy 26.877 48.603) + (xy 26.877 48.623) (xy 26.897 48.623) (xy 26.897 48.877) (xy 26.877 48.877) (xy 26.877 49.62625) + (xy 27.03575 49.785) (xy 27.25131 49.785) (xy 27.484699 49.688327) (xy 27.663327 49.509698) (xy 27.691789 49.440984) + (xy 27.761673 49.609698) (xy 27.940301 49.788327) (xy 28.132648 49.868) (xy 23 49.868) (xy 22.984776 49.871028) + (xy 22.969376 49.869087) (xy 22.902592 49.887376) (xy 22.834681 49.900884) (xy 22.821776 49.909507) (xy 22.806804 49.913607) + (xy 22.752101 49.956062) (xy 22.69453 49.99453) (xy 22.685906 50.007436) (xy 22.673644 50.016953) (xy 22.639354 50.077107) + (xy 22.600884 50.134681) (xy 22.597856 50.149906) (xy 22.590169 50.16339) (xy 22.581509 50.232085) (xy 22.568 50.3) + (xy 22.571028 50.315224) (xy 22.569087 50.330624) (xy 22.587376 50.397408) (xy 22.600884 50.465319) (xy 22.609507 50.478224) + (xy 22.613607 50.493196) (xy 23.513607 52.293196) (xy 23.556062 52.347899) (xy 23.59453 52.40547) (xy 23.607436 52.414094) + (xy 23.616953 52.426356) (xy 23.677107 52.460646) (xy 23.734681 52.499116) (xy 23.749906 52.502144) (xy 23.76339 52.509831) + (xy 23.832085 52.518491) (xy 23.9 52.532) (xy 51.1 52.532) (xy 51.167915 52.518491) (xy 51.23661 52.509831) + (xy 51.250094 52.502144) (xy 51.265319 52.499116) (xy 51.322893 52.460646) (xy 51.383047 52.426356) (xy 51.392564 52.414094) + (xy 51.40547 52.40547) (xy 51.443938 52.347899) (xy 51.486393 52.293196) (xy 52.386392 50.493196) (xy 52.390491 50.478227) + (xy 52.399116 50.465319) (xy 52.412625 50.397403) (xy 52.430913 50.330624) (xy 52.428972 50.315224) (xy 52.432 50.3) + (xy 52.418491 50.232085) (xy 52.409831 50.16339) (xy 52.402144 50.149906) (xy 52.399116 50.134681) (xy 52.360646 50.077107) + (xy 52.326356 50.016953) (xy 52.314094 50.007436) (xy 52.30547 49.99453) (xy 52.247894 49.956059) (xy 52.193196 49.913608) + (xy 52.178227 49.909509) (xy 52.165319 49.900884) (xy 52.097403 49.887375) (xy 52.030624 49.869087) (xy 52.015224 49.871028) + (xy 52 49.868) (xy 46.717352 49.868) (xy 46.909699 49.788327) (xy 47.088327 49.609698) (xy 47.185 49.376309) + (xy 47.185 49.03575) (xy 47.02625 48.877) (xy 45.877 48.877) (xy 45.877 48.897) (xy 45.623 48.897) + (xy 45.623 48.877) (xy 43.877 48.877) (xy 43.877 49.62625) (xy 44.03575 49.785) (xy 44.25131 49.785) + (xy 44.484699 49.688327) (xy 44.4875 49.685526) (xy 44.590301 49.788327) (xy 44.782648 49.868) (xy 29.367352 49.868) + (xy 29.559699 49.788327) (xy 29.736139 49.611886) (xy 29.87 49.638994) (xy 30.93 49.638994) (xy 31.062296 49.614101) + (xy 31.183802 49.535914) (xy 31.265316 49.416614) (xy 31.293994 49.275) (xy 31.293994 49.19029) (xy 31.376852 49.273148) + (xy 31.525114 49.372213) (xy 31.7 49.407) (xy 31.730843 49.407) (xy 31.730899 49.407296) (xy 31.809086 49.528802) + (xy 31.928386 49.610316) (xy 32.07 49.638994) (xy 33.13 49.638994) (xy 33.262296 49.614101) (xy 33.383802 49.535914) + (xy 33.465316 49.416614) (xy 33.493994 49.275) (xy 33.493994 48.859031) (xy 33.668327 48.684699) (xy 33.765 48.45131) + (xy 33.765 48.28575) (xy 33.60625 48.127) (xy 32.727 48.127) (xy 32.727 48.147) (xy 32.473 48.147) + (xy 32.473 48.127) (xy 32.453 48.127) (xy 32.453 48.03575) (xy 33.849 48.03575) (xy 33.849 48.89231) + (xy 33.945673 49.125699) (xy 34.124302 49.304327) (xy 34.357691 49.401) (xy 35.21425 49.401) (xy 35.373 49.24225) + (xy 35.373 47.877) (xy 34.00775 47.877) (xy 33.849 48.03575) (xy 32.453 48.03575) (xy 32.453 47.873) + (xy 32.473 47.873) (xy 32.473 47.853) (xy 32.727 47.853) (xy 32.727 47.873) (xy 33.60625 47.873) + (xy 33.765 47.71425) (xy 33.765 47.54869) (xy 33.668327 47.315301) (xy 33.493994 47.140969) (xy 33.493994 47.085144) + (xy 33.849 46.730138) (xy 33.849 47.46425) (xy 34.00775 47.623) (xy 35.373 47.623) (xy 35.373 47.603) + (xy 35.627 47.603) (xy 35.627 47.623) (xy 36.99225 47.623) (xy 37.151 47.46425) (xy 37.151 47.330138) + (xy 37.261006 47.440144) (xy 37.261006 47.65) (xy 37.285899 47.782296) (xy 37.29649 47.798754) (xy 37.265301 47.811673) + (xy 37.096112 47.980862) (xy 36.99225 47.877) (xy 35.627 47.877) (xy 35.627 49.24225) (xy 35.78575 49.401) + (xy 36.642309 49.401) (xy 36.875698 49.304327) (xy 36.99 49.190026) (xy 36.99 49.276309) (xy 37.086673 49.509698) + (xy 37.265301 49.688327) (xy 37.49869 49.785) (xy 37.71425 49.785) (xy 37.873 49.62625) (xy 37.873 48.877) + (xy 37.853 48.877) (xy 37.853 48.623) (xy 37.873 48.623) (xy 37.873 48.603) (xy 38.127 48.603) + (xy 38.127 48.623) (xy 38.147 48.623) (xy 38.147 48.877) (xy 38.127 48.877) (xy 38.127 49.62625) + (xy 38.28575 49.785) (xy 38.50131 49.785) (xy 38.734699 49.688327) (xy 38.913327 49.509698) (xy 39.007423 49.282531) + (xy 39.030899 49.407296) (xy 39.109086 49.528802) (xy 39.228386 49.610316) (xy 39.37 49.638994) (xy 40.43 49.638994) + (xy 40.562296 49.614101) (xy 40.642075 49.562765) (xy 40.868741 49.656885) (xy 41.130112 49.657113) (xy 41.358664 49.562677) + (xy 41.428386 49.610316) (xy 41.57 49.638994) (xy 42.63 49.638994) (xy 42.762296 49.614101) (xy 42.871077 49.544102) + (xy 43.015301 49.688327) (xy 43.24869 49.785) (xy 43.46425 49.785) (xy 43.623 49.62625) (xy 43.623 48.877) + (xy 43.603 48.877) (xy 43.603 48.623) (xy 43.623 48.623) (xy 43.623 48.603) (xy 43.877 48.603) + (xy 43.877 48.623) (xy 45.623 48.623) (xy 45.623 47.77375) (xy 45.877 47.77375) (xy 45.877 48.623) + (xy 47.02625 48.623) (xy 47.185 48.46425) (xy 47.185 48.4) (xy 47.543 48.4) (xy 47.593011 48.651423) + (xy 47.735431 48.864569) (xy 47.948577 49.006989) (xy 48.2 49.057) (xy 48.7 49.057) (xy 48.951423 49.006989) + (xy 49.164569 48.864569) (xy 49.264569 48.764569) (xy 49.406989 48.551423) (xy 49.457 48.3) (xy 49.406989 48.048577) + (xy 49.264569 47.835431) (xy 49.051423 47.693011) (xy 48.8 47.643) (xy 48.548577 47.693011) (xy 48.473763 47.743) + (xy 48.2 47.743) (xy 47.948577 47.793011) (xy 47.735431 47.935431) (xy 47.593011 48.148577) (xy 47.543 48.4) + (xy 47.185 48.4) (xy 47.185 48.123691) (xy 47.088327 47.890302) (xy 46.909699 47.711673) (xy 46.67631 47.615) + (xy 46.03575 47.615) (xy 45.877 47.77375) (xy 45.623 47.77375) (xy 45.46425 47.615) (xy 44.82369 47.615) + (xy 44.590301 47.711673) (xy 44.4875 47.814474) (xy 44.484699 47.811673) (xy 44.455012 47.799376) (xy 44.460316 47.791614) + (xy 44.488994 47.65) (xy 44.488994 47.440144) (xy 45.315144 46.613994) (xy 46.55 46.613994) (xy 46.682296 46.589101) + (xy 46.803802 46.510914) (xy 46.885316 46.391614) (xy 46.913994 46.25) (xy 46.913994 45.25) (xy 46.889101 45.117704) + (xy 46.810914 44.996198) (xy 46.691614 44.914684) (xy 46.55 44.886006) (xy 45.815144 44.886006) (xy 44.383696 43.454558) + (xy 44.383696 42.879994) (xy 44.742696 42.879994) (xy 44.874992 42.855101) (xy 44.996498 42.776914) (xy 45.078012 42.657614) + (xy 45.10669 42.516) (xy 45.10669 42.214677) (xy 45.295838 42.497757) (xy 45.741272 42.795386) (xy 46.266696 42.899899) + (xy 46.79212 42.795386) (xy 47.237554 42.497757) (xy 47.535183 42.052323) (xy 47.639696 41.526899) (xy 47.639696 41.473101) + (xy 47.535183 40.947677) (xy 47.237554 40.502243) (xy 46.79212 40.204614) (xy 46.266696 40.100101) (xy 45.741272 40.204614) + (xy 45.295838 40.502243) (xy 45.10669 40.785323) (xy 45.10669 40.484) (xy 45.081797 40.351704) (xy 45.00361 40.230198) + (xy 44.88431 40.148684) (xy 44.742696 40.120006) (xy 44.258696 40.120006) (xy 44.258696 37.644664) (xy 44.365 37.53836) + (xy 44.365 37.72631) (xy 44.461673 37.959699) (xy 44.640302 38.138327) (xy 44.873691 38.235) (xy 45.01425 38.235) + (xy 45.173 38.07625) (xy 45.173 37.277) (xy 45.153 37.277) (xy 45.153 37.023) (xy 45.173 37.023) + (xy 45.173 37.003) (xy 45.427 37.003) (xy 45.427 37.023) (xy 45.447 37.023) (xy 45.447 37.277) + (xy 45.427 37.277) (xy 45.427 38.07625) (xy 45.58575 38.235) (xy 45.644907 38.235) (xy 45.742698 38.471674) + (xy 45.927354 38.656652) (xy 46.168741 38.756885) (xy 46.430112 38.757113) (xy 46.671674 38.657302) (xy 46.856652 38.472646) + (xy 46.955332 38.235) (xy 47.01425 38.235) (xy 47.173 38.07625) (xy 47.173 37.277) (xy 47.153 37.277) + (xy 47.153 37.023) (xy 47.173 37.023) (xy 47.173 37.003) (xy 47.427 37.003) (xy 47.427 37.023) + (xy 47.447 37.023) (xy 47.447 37.277) (xy 47.427 37.277) (xy 47.427 38.07625) (xy 47.58575 38.235) + (xy 47.726309 38.235) (xy 47.959698 38.138327) (xy 48.134032 37.963994) (xy 48.465968 37.963994) (xy 48.640302 38.138327) + (xy 48.873691 38.235) (xy 49.01425 38.235) (xy 49.173 38.07625) (xy 49.173 37.277) (xy 49.427 37.277) + (xy 49.427 38.07625) (xy 49.58575 38.235) (xy 49.726309 38.235) (xy 49.959698 38.138327) (xy 50.138327 37.959699) + (xy 50.235 37.72631) (xy 50.235 37.43575) (xy 50.07625 37.277) (xy 49.427 37.277) (xy 49.173 37.277) + (xy 49.153 37.277) (xy 49.153 37.023) (xy 49.173 37.023) (xy 49.173 37.003) (xy 49.427 37.003) + (xy 49.427 37.023) (xy 50.07625 37.023) (xy 50.235 36.86425) (xy 50.235 36.63575) (xy 50.29 36.63575) + (xy 50.29 36.876309) (xy 50.386673 37.109698) (xy 50.565301 37.288327) (xy 50.79869 37.385) (xy 51.01425 37.385) + (xy 51.173 37.22625) (xy 51.173 36.477) (xy 50.44875 36.477) (xy 50.29 36.63575) (xy 50.235 36.63575) + (xy 50.235 36.57369) (xy 50.138327 36.340301) (xy 49.959698 36.161673) (xy 49.727825 36.065628) (xy 50.291378 36.065628) + (xy 50.44875 36.223) (xy 51.173 36.223) (xy 51.173 36.203) (xy 51.427 36.203) (xy 51.427 36.223) + (xy 51.447 36.223) (xy 51.447 36.477) (xy 51.427 36.477) (xy 51.427 37.22625) (xy 51.58575 37.385) + (xy 51.80131 37.385) (xy 52.034699 37.288327) (xy 52.213327 37.109698) (xy 52.31 36.876309) (xy 52.31 36.808601) + (xy 52.339086 36.853802) (xy 52.458386 36.935316) (xy 52.6 36.963994) (xy 53.5 36.963994) (xy 53.632296 36.939101) + (xy 53.753802 36.860914) (xy 53.835316 36.741614) (xy 53.863994 36.6) (xy 53.863994 36.1) (xy 53.839101 35.967704) + (xy 53.760914 35.846198) (xy 53.641614 35.764684) (xy 53.5 35.736006) (xy 52.882302 35.736006) (xy 52.61029 35.463994) + (xy 53.5 35.463994) (xy 53.632296 35.439101) (xy 53.753802 35.360914) (xy 53.835316 35.241614) (xy 53.863994 35.1) + (xy 53.863994 34.6) (xy 53.839101 34.467704) (xy 53.760914 34.346198) (xy 53.641614 34.264684) (xy 53.5 34.236006) + (xy 52.6 34.236006) (xy 52.467704 34.260899) (xy 52.378967 34.318) (xy 52.014157 34.318) (xy 52.014101 34.317704) + (xy 51.935914 34.196198) (xy 51.816614 34.114684) (xy 51.675 34.086006) (xy 50.925 34.086006) (xy 50.792704 34.110899) + (xy 50.671198 34.189086) (xy 50.668524 34.193) (xy 50.372138 34.193) (xy 49.963994 33.784856) (xy 49.963994 33.6) + (xy 49.939101 33.467704) (xy 49.860914 33.346198) (xy 49.832 33.326442) (xy 49.832 33.250005) (xy 49.832001 33.25) + (xy 49.791505 33.046413) (xy 49.676181 32.873819) (xy 47.502362 30.7) (xy 50.896883 27.305479) (xy 50.92666 27.260914) + (xy 51.012206 27.132886) (xy 51.052702 26.929298) (xy 51.052702 24.571402) (xy 51.149504 24.509112) (xy 51.231018 24.389812) + (xy 51.24309 24.330198) (xy 51.547137 24.330198) (xy 51.556601 24.380494) (xy 51.634788 24.502) (xy 51.754088 24.583514) + (xy 51.895702 24.612192) (xy 52.645702 24.612192) (xy 52.777998 24.587299) (xy 52.899504 24.509112) (xy 52.981018 24.389812) + (xy 53.009696 24.248198) (xy 53.009696 23.448198) (xy 52.984803 23.315902) (xy 52.974212 23.299444) (xy 53.005401 23.286525) + (xy 53.184029 23.107896) (xy 53.280702 22.874507) (xy 53.280702 22.633948) (xy 53.121952 22.475198) (xy 52.397702 22.475198) + (xy 52.397702 22.495198) (xy 52.143702 22.495198) (xy 52.143702 22.475198) (xy 51.419452 22.475198) (xy 51.395702 22.498948) + (xy 51.371952 22.475198) (xy 50.647702 22.475198) (xy 50.647702 22.495198) (xy 50.393702 22.495198) (xy 50.393702 22.475198) + (xy 50.373702 22.475198) (xy 50.373702 22.221198) (xy 50.393702 22.221198) (xy 50.393702 21.471948) (xy 50.647702 21.471948) + (xy 50.647702 22.221198) (xy 51.371952 22.221198) (xy 51.395702 22.197448) (xy 51.419452 22.221198) (xy 52.143702 22.221198) + (xy 52.143702 21.471948) (xy 52.397702 21.471948) (xy 52.397702 22.221198) (xy 53.121952 22.221198) (xy 53.280702 22.062448) + (xy 53.280702 21.821889) (xy 53.184029 21.5885) (xy 53.005401 21.409871) (xy 52.772012 21.313198) (xy 52.556452 21.313198) + (xy 52.397702 21.471948) (xy 52.143702 21.471948) (xy 51.984952 21.313198) (xy 51.769392 21.313198) (xy 51.536003 21.409871) + (xy 51.395702 21.550173) (xy 51.255401 21.409871) (xy 51.022012 21.313198) (xy 50.806452 21.313198) (xy 50.647702 21.471948) + (xy 50.393702 21.471948) (xy 50.234952 21.313198) (xy 50.019392 21.313198) (xy 49.786003 21.409871) (xy 49.695702 21.500173) + (xy 49.6554 21.459871) (xy 49.422011 21.363198) (xy 49.306452 21.363198) (xy 49.147702 21.521948) (xy 49.147702 22.034204) + (xy 48.971171 22.034204) (xy 48.958356 22.003266) (xy 48.984696 21.873198) (xy 48.984696 21.323198) (xy 48.959803 21.190902) + (xy 48.881616 21.069396) (xy 48.771817 20.994374) (xy 48.759029 20.9635) (xy 48.580401 20.784871) (xy 48.347012 20.688198) + (xy 48.329452 20.688198) (xy 48.170702 20.846948) (xy 48.170702 21.059837) (xy 48.1669 21.062284) (xy 48.120622 21.130014) + (xy 48.081616 21.069396) (xy 48.070702 21.061939) (xy 48.070702 20.846948) (xy 47.911952 20.688198) (xy 47.894392 20.688198) + (xy 47.661003 20.784871) (xy 47.482375 20.9635) (xy 47.479244 20.971059) (xy 47.420702 20.959204) (xy 47.375925 20.959204) + (xy 47.342915 20.793254) (xy 47.314014 20.75) (xy 47.24385 20.644992) (xy 47.243847 20.64499) (xy 46.930858 20.332) + (xy 52 20.332) (xy 52.015224 20.328972) (xy 52.030624 20.330913) (xy 52.097403 20.312625) (xy 52.165319 20.299116) + (xy 52.178227 20.290491) (xy 52.193196 20.286392) (xy 52.247894 20.243941) (xy 52.30547 20.20547) (xy 52.314094 20.192564) + (xy 52.326356 20.183047) (xy 52.360646 20.122893) (xy 52.399116 20.065319) (xy 52.402144 20.050094) (xy 52.409831 20.03661) + (xy 52.418491 19.967915) (xy 52.432 19.9) (xy 52.428972 19.884776) (xy 52.430913 19.869376) (xy 52.412625 19.802597) + (xy 52.399116 19.734681) (xy 52.390491 19.721773) (xy 52.386392 19.706804) (xy 51.486393 17.906804) (xy 51.443938 17.852101) + (xy 51.40547 17.79453) (xy 51.392564 17.785906) (xy 51.383047 17.773644) (xy 51.322893 17.739354) (xy 51.265319 17.700884) + (xy 51.250094 17.697856) (xy 51.23661 17.690169) (xy 51.167915 17.681509) (xy 51.1 17.668) (xy 23.9 17.668) + (xy 23.832085 17.681509) (xy 23.76339 17.690169) (xy 23.749906 17.697856) (xy 23.734681 17.700884) (xy 23.677107 17.739354) + (xy 23.616953 17.773644) (xy 23.607436 17.785906) (xy 23.59453 17.79453) (xy 23.556062 17.852101) (xy 23.513607 17.906804) + (xy 22.613607 19.706804) (xy 22.609507 19.721776) (xy 22.600884 19.734681) (xy 22.593262 19.773) (xy 20.546491 19.773) + (xy 22.266991 16.332) (xy 52.733009 16.332) + ) + ) + (filled_polygon + (pts + (xy 28.877 48.875) (xy 28.897 48.875) (xy 28.897 49.125) (xy 28.877 49.125) (xy 28.877 49.147) + (xy 28.623 49.147) (xy 28.623 49.125) (xy 28.603 49.125) (xy 28.603 48.875) (xy 28.623 48.875) + (xy 28.623 48.853) (xy 28.877 48.853) + ) + ) + (filled_polygon + (pts + (xy 42.122999 33.879999) (xy 42.157786 34.054886) (xy 42.256851 34.203147) (xy 43.14301 35.089306) (xy 43.142887 35.230112) + (xy 43.242698 35.471674) (xy 43.427354 35.656652) (xy 43.668741 35.756885) (xy 43.810713 35.757009) (xy 43.896853 35.843149) + (xy 44.045114 35.942214) (xy 44.220001 35.977001) (xy 44.421635 35.977001) (xy 43.350515 37.048121) (xy 43.235192 37.220714) + (xy 43.194696 37.424302) (xy 43.194696 40.120006) (xy 42.710696 40.120006) (xy 42.5784 40.144899) (xy 42.456894 40.223086) + (xy 42.37538 40.342386) (xy 42.346702 40.484) (xy 42.346702 42.516) (xy 42.371595 42.648296) (xy 42.449782 42.769802) + (xy 42.569082 42.851316) (xy 42.710696 42.879994) (xy 43.069696 42.879994) (xy 43.069696 43.726696) (xy 43.119707 43.978119) + (xy 43.207428 44.109403) (xy 43.109698 44.011673) (xy 42.876309 43.915) (xy 42.78375 43.915) (xy 42.625 44.07375) + (xy 42.625 44.873) (xy 43.22625 44.873) (xy 43.385 44.71425) (xy 43.385 44.42369) (xy 43.307535 44.236673) + (xy 44.570862 45.5) (xy 43.656648 46.414214) (xy 43.55 46.393) (xy 42.776467 46.393) (xy 42.771614 46.389684) + (xy 42.63 46.361006) (xy 41.57 46.361006) (xy 41.437704 46.385899) (xy 41.316198 46.464086) (xy 41.234684 46.583386) + (xy 41.206006 46.725) (xy 41.206006 47.375) (xy 41.230899 47.507296) (xy 41.309086 47.628802) (xy 41.428386 47.710316) + (xy 41.57 47.738994) (xy 42.63 47.738994) (xy 42.762296 47.714101) (xy 42.773331 47.707) (xy 43.021731 47.707) + (xy 43.035899 47.782296) (xy 43.04649 47.798754) (xy 43.015301 47.811673) (xy 42.836673 47.990302) (xy 42.74 48.223691) + (xy 42.74 48.283282) (xy 42.63 48.261006) (xy 41.57 48.261006) (xy 41.437704 48.285899) (xy 41.316198 48.364086) + (xy 41.286486 48.407571) (xy 41.131259 48.343115) (xy 41.065 48.343057) (xy 41.065 48.28575) (xy 40.90625 48.127) + (xy 40.027 48.127) (xy 40.027 48.147) (xy 39.773 48.147) (xy 39.773 48.127) (xy 39.753 48.127) + (xy 39.753 47.873) (xy 39.773 47.873) (xy 39.773 47.853) (xy 40.027 47.853) (xy 40.027 47.873) + (xy 40.90625 47.873) (xy 41.065 47.71425) (xy 41.065 47.54869) (xy 40.968327 47.315301) (xy 40.793994 47.140969) + (xy 40.793994 46.725) (xy 40.769101 46.592704) (xy 40.690914 46.471198) (xy 40.571614 46.389684) (xy 40.43 46.361006) + (xy 39.37 46.361006) (xy 39.237704 46.385899) (xy 39.226669 46.393) (xy 38.2 46.393) (xy 38.093352 46.414214) + (xy 37.546138 45.867) (xy 37.79 45.867) (xy 38.041423 45.816989) (xy 38.045905 45.813994) (xy 38.25 45.813994) + (xy 38.382296 45.789101) (xy 38.503802 45.710914) (xy 38.585316 45.591614) (xy 38.613994 45.45) (xy 38.613994 45.216206) + (xy 38.657 45) (xy 38.613994 44.783794) (xy 38.613994 44.55) (xy 38.589101 44.417704) (xy 38.510914 44.296198) + (xy 38.391614 44.214684) (xy 38.25 44.186006) (xy 37.75 44.186006) (xy 37.617704 44.210899) (xy 37.496198 44.289086) + (xy 37.414684 44.408386) (xy 37.386006 44.55) (xy 37.386006 44.553) (xy 36.70747 44.553) (xy 36.497757 44.239142) + (xy 36.052323 43.941513) (xy 35.995007 43.930112) (xy 38.842887 43.930112) (xy 38.942698 44.171674) (xy 39.034988 44.264125) + (xy 38.996198 44.289086) (xy 38.914684 44.408386) (xy 38.886006 44.55) (xy 38.886006 45.45) (xy 38.910899 45.582296) + (xy 38.989086 45.703802) (xy 39.108386 45.785316) (xy 39.25 45.813994) (xy 39.75 45.813994) (xy 39.882296 45.789101) + (xy 40.003802 45.710914) (xy 40.085316 45.591614) (xy 40.102451 45.507) (xy 40.396731 45.507) (xy 40.410899 45.582296) + (xy 40.489086 45.703802) (xy 40.608386 45.785316) (xy 40.75 45.813994) (xy 41.25 45.813994) (xy 41.382296 45.789101) + (xy 41.503802 45.710914) (xy 41.585316 45.591614) (xy 41.613994 45.45) (xy 41.613994 45.28575) (xy 41.615 45.28575) + (xy 41.615 45.57631) (xy 41.711673 45.809699) (xy 41.890302 45.988327) (xy 42.123691 46.085) (xy 42.21625 46.085) + (xy 42.375 45.92625) (xy 42.375 45.127) (xy 42.625 45.127) (xy 42.625 45.92625) (xy 42.78375 46.085) + (xy 42.876309 46.085) (xy 43.109698 45.988327) (xy 43.288327 45.809699) (xy 43.385 45.57631) (xy 43.385 45.28575) + (xy 43.22625 45.127) (xy 42.625 45.127) (xy 42.375 45.127) (xy 41.77375 45.127) (xy 41.615 45.28575) + (xy 41.613994 45.28575) (xy 41.613994 44.55) (xy 41.590228 44.42369) (xy 41.615 44.42369) (xy 41.615 44.71425) + (xy 41.77375 44.873) (xy 42.375 44.873) (xy 42.375 44.07375) (xy 42.21625 43.915) (xy 42.123691 43.915) + (xy 41.890302 44.011673) (xy 41.711673 44.190301) (xy 41.615 44.42369) (xy 41.590228 44.42369) (xy 41.589101 44.417704) + (xy 41.510914 44.296198) (xy 41.391614 44.214684) (xy 41.25 44.186006) (xy 40.75 44.186006) (xy 40.617704 44.210899) + (xy 40.496198 44.289086) (xy 40.414684 44.408386) (xy 40.397549 44.493) (xy 40.103269 44.493) (xy 40.089101 44.417704) + (xy 40.010914 44.296198) (xy 39.964591 44.264547) (xy 40.056652 44.172646) (xy 40.156885 43.931259) (xy 40.157113 43.669888) + (xy 40.057302 43.428326) (xy 39.872646 43.243348) (xy 39.631259 43.143115) (xy 39.369888 43.142887) (xy 39.128326 43.242698) + (xy 38.943348 43.427354) (xy 38.843115 43.668741) (xy 38.842887 43.930112) (xy 35.995007 43.930112) (xy 35.526899 43.837) + (xy 35.473101 43.837) (xy 34.947677 43.941513) (xy 34.502243 44.239142) (xy 34.269926 44.58683) (xy 34.188577 44.603011) + (xy 33.975431 44.745431) (xy 32.359856 46.361006) (xy 32.07 46.361006) (xy 31.965657 46.380639) (xy 34.523148 43.823148) + (xy 34.622213 43.674886) (xy 34.657001 43.5) (xy 34.657 43.499995) (xy 34.657 40.772125) (xy 34.756652 40.672646) + (xy 34.856885 40.431259) (xy 34.857113 40.169888) (xy 34.757302 39.928326) (xy 34.60297 39.773724) (xy 36.532087 37.844607) + (xy 36.436109 38.075747) (xy 36.435881 38.337118) (xy 36.535692 38.57868) (xy 36.720348 38.763658) (xy 36.961735 38.863891) + (xy 37.223106 38.864119) (xy 37.464668 38.764308) (xy 37.649646 38.579652) (xy 37.749879 38.338265) (xy 37.750003 38.196293) + (xy 39.196666 36.749629) (xy 39.196669 36.749627) (xy 39.22644 36.705071) (xy 39.245195 36.697322) (xy 39.430173 36.512666) + (xy 39.530406 36.271279) (xy 39.530634 36.009908) (xy 39.430823 35.768346) (xy 39.246167 35.583368) (xy 39.00478 35.483135) + (xy 38.893656 35.483038) (xy 42.122999 32.253695) + ) + ) + (filled_polygon + (pts + (xy 33.022877 40.93923) (xy 33.122688 41.180792) (xy 33.307344 41.36577) (xy 33.548731 41.466003) (xy 33.743 41.466172) + (xy 33.743 43.310704) (xy 31.176852 45.876852) (xy 31.077787 46.025113) (xy 31.077787 46.025114) (xy 31.043 46.2) + (xy 31.043 46.383889) (xy 30.93 46.361006) (xy 30.640144 46.361006) (xy 29.613994 45.334856) (xy 29.613994 44.875) + (xy 29.589101 44.742704) (xy 29.515905 44.628954) (xy 29.734699 44.538327) (xy 29.913327 44.359698) (xy 29.914637 44.356536) + (xy 30.00459 44.33961) (xy 30.125 44.363994) (xy 30.375 44.363994) (xy 30.50459 44.33961) (xy 30.585106 44.355915) + (xy 30.586673 44.359698) (xy 30.765301 44.538327) (xy 30.99869 44.635) (xy 31.02875 44.635) (xy 31.1875 44.47625) + (xy 31.1875 44.175006) (xy 31.210316 44.141614) (xy 31.238994 44) (xy 31.238994 43.777) (xy 31.3125 43.777) + (xy 31.3125 44.47625) (xy 31.47125 44.635) (xy 31.50131 44.635) (xy 31.734699 44.538327) (xy 31.913327 44.359698) + (xy 32.01 44.126309) (xy 32.01 43.93575) (xy 31.85125 43.777) (xy 31.3125 43.777) (xy 31.238994 43.777) + (xy 31.238994 43.61) (xy 31.35131 43.61) (xy 31.561346 43.523) (xy 31.85125 43.523) (xy 31.885256 43.488994) + (xy 32.25 43.488994) (xy 32.382296 43.464101) (xy 32.503802 43.385914) (xy 32.585316 43.266614) (xy 32.605915 43.164894) + (xy 32.609698 43.163327) (xy 32.788327 42.984699) (xy 32.885 42.75131) (xy 32.885 42.72125) (xy 32.72625 42.5625) + (xy 32.425006 42.5625) (xy 32.391614 42.539684) (xy 32.25 42.511006) (xy 31.86 42.511006) (xy 31.86 42.488994) + (xy 32.25 42.488994) (xy 32.382296 42.464101) (xy 32.423635 42.4375) (xy 32.72625 42.4375) (xy 32.885 42.27875) + (xy 32.885 42.24869) (xy 32.788327 42.015301) (xy 32.609698 41.836673) (xy 32.606536 41.835363) (xy 32.58961 41.74541) + (xy 32.613994 41.625) (xy 32.613994 41.375) (xy 32.58961 41.24541) (xy 32.613994 41.125) (xy 32.613994 40.957) + (xy 32.777836 40.957) (xy 32.952723 40.922213) (xy 33.022933 40.8753) + ) + ) + (filled_polygon + (pts + (xy 29.261006 43.797) (xy 29.238994 43.797) (xy 29.238994 43.61) (xy 29.261006 43.61) + ) + ) + (filled_polygon + (pts + (xy 28.7645 40.2605) (xy 30.2355 40.2605) (xy 30.2355 40.2405) (xy 30.4895 40.2405) (xy 30.4895 40.2605) + (xy 30.5095 40.2605) (xy 30.5095 40.5145) (xy 30.4895 40.5145) (xy 30.4895 41.9855) (xy 30.5095 41.9855) + (xy 30.5095 42.2395) (xy 30.4895 42.2395) (xy 30.4895 42.2595) (xy 30.2355 42.2595) (xy 30.2355 42.2395) + (xy 28.7645 42.2395) (xy 28.7645 42.2595) (xy 28.5105 42.2595) (xy 28.5105 42.2395) (xy 28.4905 42.2395) + (xy 28.4905 41.9855) (xy 28.5105 41.9855) (xy 28.5105 40.5145) (xy 28.7645 40.5145) (xy 28.7645 41.9855) + (xy 30.2355 41.9855) (xy 30.2355 40.5145) (xy 28.7645 40.5145) (xy 28.5105 40.5145) (xy 28.4905 40.5145) + (xy 28.4905 40.2605) (xy 28.5105 40.2605) (xy 28.5105 40.2405) (xy 28.7645 40.2405) + ) + ) + (filled_polygon + (pts + (xy 24.043 30.589296) (xy 24.043 35.947298) (xy 24.077787 36.122185) (xy 24.176852 36.270446) (xy 25.209584 37.303178) + (xy 25.357846 37.402243) (xy 25.532732 37.437031) (xy 25.532737 37.43703) (xy 26.216674 37.43703) (xy 24.414333 39.239371) + (xy 24.341614 39.189684) (xy 24.2 39.161006) (xy 23.4 39.161006) (xy 23.267704 39.185899) (xy 23.251246 39.19649) + (xy 23.238327 39.165301) (xy 23.059698 38.986673) (xy 22.867282 38.906972) (xy 23.21825 38.907278) (xy 23.809103 38.663143) + (xy 24.261554 38.211481) (xy 24.50672 37.621054) (xy 24.507278 36.98175) (xy 24.263143 36.390897) (xy 23.811481 35.938446) + (xy 23.221054 35.69328) (xy 22.58175 35.692722) (xy 21.990897 35.936857) (xy 21.538446 36.388519) (xy 21.29328 36.978946) + (xy 21.292722 37.61825) (xy 21.536857 38.209103) (xy 21.988519 38.661554) (xy 22.571939 38.903811) (xy 22.427 39.04875) + (xy 22.427 39.773) (xy 22.447 39.773) (xy 22.447 40.027) (xy 22.427 40.027) (xy 22.427 40.047) + (xy 22.173 40.047) (xy 22.173 40.027) (xy 21.42375 40.027) (xy 21.265 40.18575) (xy 21.265 40.40131) + (xy 21.353886 40.6159) (xy 21.21054 40.6159) (xy 20.785862 40.750898) (xy 20.445172 41.038137) (xy 20.432 41.064963) + (xy 20.432 39.39869) (xy 21.265 39.39869) (xy 21.265 39.61425) (xy 21.42375 39.773) (xy 22.173 39.773) + (xy 22.173 39.04875) (xy 22.01425 38.89) (xy 21.773691 38.89) (xy 21.540302 38.986673) (xy 21.361673 39.165301) + (xy 21.265 39.39869) (xy 20.432 39.39869) (xy 20.432 32.727) (xy 23.9 32.727) (xy 23.94941 32.716994) + (xy 23.991035 32.688553) (xy 24.018315 32.646159) (xy 24.027 32.6) (xy 24.027 30.573296) + ) + ) + (filled_polygon + (pts + (xy 29.761006 38.89) (xy 29.738994 38.89) (xy 29.738994 38.703) (xy 29.761006 38.703) + ) + ) + (filled_polygon + (pts + (xy 30.127 30.873) (xy 30.147 30.873) (xy 30.147 31.127) (xy 30.127 31.127) (xy 30.127 31.85125) + (xy 30.28575 32.01) (xy 30.526309 32.01) (xy 30.759698 31.913327) (xy 30.938327 31.734699) (xy 31.035 31.50131) + (xy 31.035 31.381296) (xy 32.676852 33.023148) (xy 32.825113 33.122213) (xy 32.963242 33.149688) (xy 33.070019 33.256652) + (xy 33.311406 33.356885) (xy 33.543 33.357087) (xy 33.543 34.027875) (xy 33.443348 34.127354) (xy 33.343115 34.368741) + (xy 33.342887 34.630112) (xy 33.442698 34.871674) (xy 33.627354 35.056652) (xy 33.811246 35.133011) (xy 30.556158 35.133011) + (xy 30.556885 35.131259) (xy 30.557113 34.869888) (xy 30.457302 34.628326) (xy 30.272646 34.443348) (xy 30.151425 34.393013) + (xy 30.151423 34.393011) (xy 30.15142 34.39301) (xy 30.031259 34.343115) (xy 29.956962 34.34305) (xy 29.957113 34.169888) + (xy 29.857302 33.928326) (xy 29.707 33.777762) (xy 29.707 32.01) (xy 29.71425 32.01) (xy 29.873 31.85125) + (xy 29.873 31.127) (xy 29.853 31.127) (xy 29.853 30.873) (xy 29.873 30.873) (xy 29.873 30.853) + (xy 30.127 30.853) + ) + ) + (filled_polygon + (pts + (xy 36.559174 32.740825) (xy 36.585621 32.758496) (xy 36.715547 32.84531) (xy 36.9 32.882) (xy 39.583804 32.882) + (xy 39.738445 32.85124) (xy 39.768258 32.84531) (xy 39.822421 32.809119) (xy 38.77015 33.86139) (xy 38.77021 33.792389) + (xy 38.670399 33.550827) (xy 38.485743 33.365849) (xy 38.244356 33.265616) (xy 37.982985 33.265388) (xy 37.741423 33.365199) + (xy 37.556445 33.549855) (xy 37.474156 33.748028) (xy 37.459204 33.73305) (xy 37.217817 33.632817) (xy 36.956446 33.632589) + (xy 36.714884 33.7324) (xy 36.614407 33.832702) (xy 36.443827 33.832702) (xy 34.147966 31.536841) (xy 33.999705 31.437776) + (xy 33.824818 31.402989) (xy 33.301847 31.402989) (xy 32.155819 30.256961) (xy 32.330112 30.257113) (xy 32.571674 30.157302) + (xy 32.59702 30.132) (xy 32.624264 30.132) (xy 32.827852 30.091504) (xy 33.000445 29.976181) (xy 33.276181 29.700445) + (xy 33.373359 29.555009) + ) + ) + (filled_polygon + (pts + (xy 46.063702 21.288661) (xy 46.056708 21.323198) (xy 46.056708 21.62336) (xy 46.020702 21.616198) (xy 45.001802 21.616198) + (xy 44.847951 21.646801) (xy 44.842667 21.647852) (xy 44.831259 21.643115) (xy 44.569888 21.642887) (xy 44.328326 21.742698) + (xy 44.143348 21.927354) (xy 44.043115 22.168741) (xy 44.042887 22.430112) (xy 44.142698 22.671674) (xy 44.168 22.69702) + (xy 44.168 23.777496) (xy 44.208496 23.981084) (xy 44.299981 24.118001) (xy 44.323819 24.153677) (xy 45.116054 24.945912) + (xy 45.116024 24.980745) (xy 45.215835 25.222307) (xy 45.400491 25.407285) (xy 45.641878 25.507518) (xy 45.688316 25.507559) + (xy 45.582375 25.613499) (xy 45.485702 25.846888) (xy 45.485702 26.062448) (xy 45.644452 26.221198) (xy 46.393702 26.221198) + (xy 46.393702 26.201198) (xy 46.647702 26.201198) (xy 46.647702 26.221198) (xy 46.667702 26.221198) (xy 46.667702 26.475198) + (xy 46.647702 26.475198) (xy 46.647702 27.199448) (xy 46.806452 27.358198) (xy 47.047011 27.358198) (xy 47.2804 27.261525) + (xy 47.459029 27.082897) (xy 47.471326 27.05321) (xy 47.479088 27.058514) (xy 47.620702 27.087192) (xy 48.420702 27.087192) + (xy 48.552998 27.062299) (xy 48.674504 26.984112) (xy 48.756018 26.864812) (xy 48.784696 26.723198) (xy 48.784696 25.973198) + (xy 48.770736 25.899008) (xy 48.871674 25.857302) (xy 49.056652 25.672646) (xy 49.156885 25.431259) (xy 49.157113 25.169888) + (xy 49.057302 24.928326) (xy 48.984696 24.855593) (xy 48.984696 24.573036) (xy 49.020702 24.580198) (xy 49.988702 24.580198) + (xy 49.988702 26.708936) (xy 46.529638 30.168) (xy 44.697255 30.168) (xy 44.672646 30.143348) (xy 44.431259 30.043115) + (xy 44.169888 30.042887) (xy 43.928326 30.142698) (xy 43.743348 30.327354) (xy 43.643115 30.568741) (xy 43.642887 30.830112) + (xy 43.742698 31.071674) (xy 43.927354 31.256652) (xy 44.168741 31.356885) (xy 44.430112 31.357113) (xy 44.671674 31.257302) + (xy 44.69702 31.232) (xy 46.529638 31.232) (xy 48.533644 33.236006) (xy 48 33.236006) (xy 47.867704 33.260899) + (xy 47.799916 33.30452) (xy 47.741614 33.264684) (xy 47.6 33.236006) (xy 47 33.236006) (xy 46.867704 33.260899) + (xy 46.799916 33.30452) (xy 46.741614 33.264684) (xy 46.6 33.236006) (xy 46 33.236006) (xy 45.867704 33.260899) + (xy 45.799916 33.30452) (xy 45.741614 33.264684) (xy 45.7296 33.262251) (xy 45.722213 33.225114) (xy 45.623148 33.076852) + (xy 43.557 31.010704) (xy 43.557 26.633948) (xy 45.485702 26.633948) (xy 45.485702 26.849508) (xy 45.582375 27.082897) + (xy 45.761004 27.261525) (xy 45.994393 27.358198) (xy 46.234952 27.358198) (xy 46.393702 27.199448) (xy 46.393702 26.475198) + (xy 45.644452 26.475198) (xy 45.485702 26.633948) (xy 43.557 26.633948) (xy 43.557 21.557009) (xy 44.752554 21.557008) + (xy 44.927441 21.522221) (xy 45.075702 21.423156) (xy 45.221848 21.27701) (xy 46.063702 21.27701) + ) + ) + (filled_polygon + (pts + (xy 39.254576 23.680227) (xy 39.249684 23.687386) (xy 39.221006 23.829) (xy 39.221006 25.129) (xy 39.245899 25.261296) + (xy 39.324086 25.382802) (xy 39.443386 25.464316) (xy 39.585 25.492994) (xy 40.085 25.492994) (xy 40.217296 25.468101) + (xy 40.338802 25.389914) (xy 40.420316 25.270614) (xy 40.448994 25.129) (xy 40.448994 23.829) (xy 40.424101 23.696704) + (xy 40.345914 23.575198) (xy 40.311577 23.551737) (xy 40.303141 23.509327) (xy 40.290593 23.446244) (xy 40.524576 23.680227) + (xy 40.519684 23.687386) (xy 40.491006 23.829) (xy 40.491006 25.129) (xy 40.515899 25.261296) (xy 40.594086 25.382802) + (xy 40.713386 25.464316) (xy 40.855 25.492994) (xy 41.305458 25.492994) (xy 41.305458 29.119292) (xy 41.23 29.19475) + (xy 41.23 30.194) (xy 41.252 30.194) (xy 41.252 30.448) (xy 41.23 30.448) (xy 41.23 30.468) + (xy 40.98 30.468) (xy 40.98 30.448) (xy 40.958 30.448) (xy 40.958 30.194) (xy 40.98 30.194) + (xy 40.98 29.310055) (xy 40.982 29.3) (xy 40.982 27.314) (xy 40.94771 27.141614) (xy 40.94531 27.129546) + (xy 40.840825 26.973174) (xy 39.145424 25.277774) (xy 39.150316 25.270614) (xy 39.178994 25.129) (xy 39.178994 23.829) + (xy 39.154101 23.696704) (xy 39.075914 23.575198) (xy 38.956614 23.493684) (xy 38.815 23.465006) (xy 38.315 23.465006) + (xy 38.182704 23.489899) (xy 38.061198 23.568086) (xy 37.979684 23.687386) (xy 37.951006 23.829) (xy 37.951006 25.129) + (xy 37.975899 25.261296) (xy 38.054086 25.382802) (xy 38.088423 25.406263) (xy 38.109963 25.514551) (xy 38.11969 25.563454) + (xy 38.224175 25.719825) (xy 40.018 27.513651) (xy 40.018 29.3) (xy 40.019394 29.307006) (xy 39.585 29.307006) + (xy 39.452704 29.331899) (xy 39.331198 29.410086) (xy 39.249684 29.529386) (xy 39.221006 29.671) (xy 39.221006 30.971) + (xy 39.22985 31.018) (xy 39.169476 31.018) (xy 39.178994 30.971) (xy 39.178994 29.671) (xy 39.154101 29.538704) + (xy 39.075914 29.417198) (xy 39.041577 29.393737) (xy 39.01031 29.236547) (xy 39.01031 29.236546) (xy 38.905825 29.080174) + (xy 35.584825 25.759175) (xy 35.428454 25.65469) (xy 35.397851 25.648603) (xy 35.244 25.618) (xy 35.000155 25.618) + (xy 35.040825 25.590825) (xy 36.681006 23.950645) (xy 36.681006 25.129) (xy 36.705899 25.261296) (xy 36.784086 25.382802) + (xy 36.903386 25.464316) (xy 37.045 25.492994) (xy 37.545 25.492994) (xy 37.677296 25.468101) (xy 37.798802 25.389914) + (xy 37.880316 25.270614) (xy 37.908994 25.129) (xy 37.908994 23.829) (xy 37.884101 23.696704) (xy 37.827 23.607967) + (xy 37.827 23.602246) (xy 37.856652 23.572646) (xy 37.956885 23.331259) (xy 37.957054 23.136999) (xy 38.711349 23.136999) + ) + ) + (filled_polygon + (pts + (xy 29.761006 29.547) (xy 29.738994 29.547) (xy 29.738994 29.36) (xy 29.761006 29.36) + ) + ) + (filled_polygon + (pts + (xy 28.7645 26.0105) (xy 30.2355 26.0105) (xy 30.2355 25.9905) (xy 30.4895 25.9905) (xy 30.4895 26.0105) + (xy 30.5095 26.0105) (xy 30.5095 26.2645) (xy 30.4895 26.2645) (xy 30.4895 27.7355) (xy 30.5095 27.7355) + (xy 30.5095 27.9895) (xy 30.4895 27.9895) (xy 30.4895 28.0095) (xy 30.2355 28.0095) (xy 30.2355 27.9895) + (xy 28.7645 27.9895) (xy 28.7645 28.0095) (xy 28.5105 28.0095) (xy 28.5105 27.9895) (xy 28.4905 27.9895) + (xy 28.4905 27.7355) (xy 28.5105 27.7355) (xy 28.5105 26.2645) (xy 28.7645 26.2645) (xy 28.7645 27.7355) + (xy 30.2355 27.7355) (xy 30.2355 26.2645) (xy 28.7645 26.2645) (xy 28.5105 26.2645) (xy 28.4905 26.2645) + (xy 28.4905 26.0105) (xy 28.5105 26.0105) (xy 28.5105 25.9905) (xy 28.7645 25.9905) + ) + ) + (filled_polygon + (pts + (xy 42.256851 20.727251) (xy 42.157786 20.875512) (xy 42.12551 21.037777) (xy 42.122999 21.050399) (xy 42.122999 22.524141) + (xy 40.7357 21.136842) (xy 40.587439 21.037777) (xy 40.412552 21.00299) (xy 35.517851 21.00299) (xy 35.517846 21.002989) + (xy 35.34296 21.037777) (xy 35.194698 21.136842) (xy 34.747955 21.583585) (xy 34.649144 21.583585) (xy 34.735 21.37631) + (xy 34.735 21.28375) (xy 34.57625 21.125) (xy 33.927 21.125) (xy 33.927 21.72625) (xy 34.012165 21.811415) + (xy 32.48058 23.343) (xy 32.305025 23.343) (xy 32.438327 23.209699) (xy 32.535 22.97631) (xy 32.535 22.68575) + (xy 32.37625 22.527) (xy 31.477 22.527) (xy 31.477 22.547) (xy 31.223 22.547) (xy 31.223 22.527) + (xy 31.203 22.527) (xy 31.203 22.273) (xy 31.223 22.273) (xy 31.223 22.253) (xy 31.477 22.253) + (xy 31.477 22.273) (xy 32.37625 22.273) (xy 32.535 22.11425) (xy 32.535 21.82369) (xy 32.448141 21.613994) + (xy 32.965968 21.613994) (xy 33.140302 21.788327) (xy 33.373691 21.885) (xy 33.51425 21.885) (xy 33.673 21.72625) + (xy 33.673 21.125) (xy 33.653 21.125) (xy 33.653 20.875) (xy 33.673 20.875) (xy 33.673 20.853) + (xy 33.927 20.853) (xy 33.927 20.875) (xy 34.57625 20.875) (xy 34.735 20.71625) (xy 34.735 20.632) + (xy 42.352102 20.632) + ) + ) + (filled_polygon + (pts + (xy 27.640301 20.361673) (xy 27.545983 20.455992) (xy 27.32631 20.365) (xy 27.03575 20.365) (xy 26.877 20.52375) + (xy 26.877 21.125) (xy 27.67625 21.125) (xy 27.72825 21.073) (xy 28.125 21.073) (xy 28.125 21.053) + (xy 28.375 21.053) (xy 28.375 21.073) (xy 28.97625 21.073) (xy 29.07625 20.973) (xy 29.523 20.973) + (xy 29.523 20.953) (xy 29.777 20.953) (xy 29.777 20.973) (xy 29.797 20.973) (xy 29.797 21.227) + (xy 29.777 21.227) (xy 29.777 21.247) (xy 29.523 21.247) (xy 29.523 21.227) (xy 28.62375 21.227) + (xy 28.52375 21.327) (xy 28.375 21.327) (xy 28.375 21.347) (xy 28.125 21.347) (xy 28.125 21.327) + (xy 27.52375 21.327) (xy 27.47575 21.375) (xy 26.877 21.375) (xy 26.877 21.97625) (xy 27.03575 22.135) + (xy 27.32631 22.135) (xy 27.559699 22.038327) (xy 27.6 21.998026) (xy 27.636006 22.034032) (xy 27.636006 22.6) + (xy 27.660899 22.732296) (xy 27.699961 22.793) (xy 27.563994 22.793) (xy 27.563994 22.5) (xy 27.539101 22.367704) + (xy 27.460914 22.246198) (xy 27.341614 22.164684) (xy 27.2 22.136006) (xy 26.3 22.136006) (xy 26.167704 22.160899) + (xy 26.046198 22.239086) (xy 25.964684 22.358386) (xy 25.936006 22.5) (xy 25.936006 22.835216) (xy 25.924887 22.827787) + (xy 25.863994 22.815675) (xy 25.863994 22.8) (xy 25.839101 22.667704) (xy 25.760914 22.546198) (xy 25.707 22.50936) + (xy 25.707 22.228269) (xy 25.782296 22.214101) (xy 25.903802 22.135914) (xy 25.963823 22.04807) (xy 26.17369 22.135) + (xy 26.46425 22.135) (xy 26.623 21.97625) (xy 26.623 21.375) (xy 26.603 21.375) (xy 26.603 21.125) + (xy 26.623 21.125) (xy 26.623 20.52375) (xy 26.46425 20.365) (xy 26.17369 20.365) (xy 25.940301 20.461673) + (xy 25.761673 20.640302) (xy 25.706903 20.772529) (xy 25.65 20.761006) (xy 24.85 20.761006) (xy 24.717704 20.785899) + (xy 24.596198 20.864086) (xy 24.514684 20.983386) (xy 24.500514 21.053359) (xy 24.489101 20.992704) (xy 24.410914 20.871198) + (xy 24.291614 20.789684) (xy 24.15 20.761006) (xy 24.027 20.761006) (xy 24.027 20.332) (xy 27.711938 20.332) + ) + ) + ) +) diff --git a/board/v1/handgelenk.net b/board/v1/handgelenk.net new file mode 100644 index 0000000..1b074e8 --- /dev/null +++ b/board/v1/handgelenk.net @@ -0,0 +1,1040 @@ +(export (version D) + (design + (source /home/florian/prgm/handgelenk/board/handgelenk.sch) + (date "Sa 19 Sep 2015 11:42:33 CEST") + (tool "Eeschema (2015-08-11 BZR 6084)-product") + (sheet (number 1) (name /) (tstamps /) + (title_block + (title) + (company) + (rev) + (date) + (source handgelenk.sch) + (comment (number 1) (value "")) + (comment (number 2) (value "")) + (comment (number 3) (value "")) + (comment (number 4) (value "")))) + (sheet (number 2) (name "/Power Management/") (tstamps /55CFAED1/) + (title_block + (title) + (company) + (rev) + (date) + (source power.sch) + (comment (number 1) (value "")) + (comment (number 2) (value "")) + (comment (number 3) (value "")) + (comment (number 4) (value "")))) + (sheet (number 3) (name /MPU-9250/) (tstamps /55F844A4/) + (title_block + (title) + (company) + (rev) + (date) + (source mpu9250.sch) + (comment (number 1) (value "")) + (comment (number 2) (value "")) + (comment (number 3) (value "")) + (comment (number 4) (value "")))) + (sheet (number 4) (name /RV-3029-C2/) (tstamps /55F97917/) + (title_block + (title) + (company) + (rev) + (date) + (source rv3029c2.sch) + (comment (number 1) (value "")) + (comment (number 2) (value "")) + (comment (number 3) (value "")) + (comment (number 4) (value ""))))) + (components + (comp (ref R2) + (value 12K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F6E5F4)) + (comp (ref C1) + (value 100n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F6EFF8)) + (comp (ref R1) + (value 1K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F6F69B)) + (comp (ref U1) + (value ESP8266EX) + (footprint Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm) + (libsource (lib esp8266ex) (part ESP8266EX)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F70BBB)) + (comp (ref X1) + (value 26MHz) + (footprint "Project Libraries:crystal_2.5x2") + (libsource (lib device) (part CRYSTAL_SMD)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F71659)) + (comp (ref C9) + (value 10p) + (footprint Capacitors_SMD:C_0402) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F73D4E)) + (comp (ref C10) + (value 10p) + (footprint Capacitors_SMD:C_0402) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F73EE1)) + (comp (ref C8) + (value 5.6p) + (footprint Capacitors_SMD:C_0402) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F80CB5)) + (comp (ref ANT1) + (value AN9520) + (footprint "Project Libraries:an9520") + (libsource (lib pspice) (part INDUCTOR)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F8139E)) + (comp (ref R5) + (value 300) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F9485D)) + (comp (ref C11) + (value 100n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F956F5)) + (comp (ref U5) + (value W25Q32BV) + (footprint "Project Libraries:wson8_5x6") + (libsource (lib w25q32bv) (part W25Q32BV)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F989A1)) + (comp (ref R6) + (value 200) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55F9BA0E)) + (comp (ref R14) + (value 390K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FB6136)) + (comp (ref C21) + (value 2u2) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FB8922)) + (comp (ref C20) + (value 4u7) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FB96CA)) + (comp (ref C24) + (value 100n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FB9F0B)) + (comp (ref C19) + (value 2u2) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FBAEDC)) + (comp (ref C22) + (value 1u) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FBD1F4)) + (comp (ref C23) + (value 1u) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FBD8B2)) + (comp (ref C18) + (value 1u) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FBFB19)) + (comp (ref R13) + (value 10K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC214E)) + (comp (ref D3) + (value 1N4148) + (footprint Diodes_SMD:SOD-323) + (libsource (lib device) (part D)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC41A1)) + (comp (ref R10) + (value 10K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FCA3EE)) + (comp (ref R11) + (value 10K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FCA4BD)) + (comp (ref R3) + (value 1K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FCF00A)) + (comp (ref P3) + (value VIBR_MOTOR) + (footprint Pin_Headers:Pin_Header_Straight_1x02) + (libsource (lib conn) (part CONN_01X02)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FD1063)) + (comp (ref Q1) + (value BC849) + (footprint TO_SOT_Packages_SMD:SOT-23) + (libsource (lib transistors) (part BC849)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC47BF)) + (comp (ref SW1) + (value BUTTON_UP) + (footprint "Project Libraries:ts015a") + (libsource (lib device) (part SW_PUSH)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC62E9)) + (comp (ref SW3) + (value BUTTON_CENTER) + (footprint "Project Libraries:ts015a") + (libsource (lib device) (part SW_PUSH)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC6544)) + (comp (ref SW2) + (value BUTTON_DOWN) + (footprint "Project Libraries:ts015a") + (libsource (lib device) (part SW_PUSH)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC65FF)) + (comp (ref D1) + (value 1N4148) + (footprint Diodes_SMD:SOD-323) + (libsource (lib device) (part D)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC9042)) + (comp (ref D2) + (value 1N4148) + (footprint Diodes_SMD:SOD-323) + (libsource (lib device) (part D)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC91A0)) + (comp (ref R12) + (value 50) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FC9C6F)) + (comp (ref C17) + (value 1u) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FCCBEB)) + (comp (ref C16) + (value 1u) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FCCDBC)) + (comp (ref DS1) + (value ER-OLED-SSD1306) + (footprint "Project Libraries:er-oled-ssd1306") + (libsource (lib er-oled-ssd1306) (part ER-OLED-SSD1306)) + (sheetpath (names /) (tstamps /)) + (tstamp 55FB110E)) + (comp (ref U3) + (value MCP73831) + (footprint TO_SOT_Packages_SMD:SOT-23-5) + (libsource (lib mcp73831) (part MCP73831)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55CFAFFF)) + (comp (ref R4) + (value 3K3) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D05DFE)) + (comp (ref C4) + (value 4u7) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D05F2E)) + (comp (ref P1) + (value USB_OTG) + (footprint Connect:USB_Micro-B) + (libsource (lib conn) (part USB_OTG)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D06165)) + (comp (ref P2) + (value LIPO) + (footprint Pin_Headers:Pin_Header_Straight_1x02) + (libsource (lib conn) (part CONN_01X02)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D0747F)) + (comp (ref C5) + (value 4u7) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D07963)) + (comp (ref C7) + (value 10u) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D084FD)) + (comp (ref C6) + (value 100u) + (footprint Capacitors_SMD:C_1206) + (libsource (lib device) (part C_Small)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D088C0)) + (comp (ref C2) + (value 100n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D08232)) + (comp (ref FB1) + (value "BLM21PG 600") + (footprint Capacitors_SMD:C_0805) + (libsource (lib device) (part FILTER)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D0855B)) + (comp (ref C3) + (value 10n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55D09B38)) + (comp (ref R7) + (value 330K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55F9A99C)) + (comp (ref R8) + (value 100K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55F9A9FE)) + (comp (ref U4) + (value TLV70233-SOT-23) + (footprint TO_SOT_Packages_SMD:SOT-23-5) + (libsource (lib tlv70233) (part TLV70233-SOT-23)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55FAB6D1)) + (comp (ref U2) + (value FT232RQ) + (footprint Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm) + (libsource (lib ft232rq) (part FT232RQ)) + (sheetpath (names "/Power Management/") (tstamps /55CFAED1/)) + (tstamp 55FD3EAE)) + (comp (ref U6) + (value MPU-9250) + (footprint Housings_DFN_QFN:QFN-24-1EP_3x3mm_Pitch0.4mm) + (libsource (lib mpu9250) (part MPU-9250)) + (sheetpath (names /MPU-9250/) (tstamps /55F844A4/)) + (tstamp 55F84634)) + (comp (ref C14) + (value 100n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /MPU-9250/) (tstamps /55F844A4/)) + (tstamp 55F84959)) + (comp (ref C12) + (value 100n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /MPU-9250/) (tstamps /55F844A4/)) + (tstamp 55F83B4A)) + (comp (ref C13) + (value 10n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /MPU-9250/) (tstamps /55F844A4/)) + (tstamp 55F83D26)) + (comp (ref C15) + (value 10n) + (footprint Capacitors_SMD:C_0603) + (libsource (lib device) (part C_Small)) + (sheetpath (names /RV-3029-C2/) (tstamps /55F97917/)) + (tstamp 55F98261)) + (comp (ref R9) + (value 10K) + (footprint Resistors_SMD:R_0603) + (libsource (lib pspice) (part R)) + (sheetpath (names /RV-3029-C2/) (tstamps /55F97917/)) + (tstamp 55F993EB)) + (comp (ref U7) + (value RV-3029-C2) + (footprint "Project Libraries:rv3029") + (libsource (lib rv3029c2) (part RV-3029-C2)) + (sheetpath (names /RV-3029-C2/) (tstamps /55F97917/)) + (tstamp 55F9C7CF))) + (libparts + (libpart (lib transistors) (part BC850) + (aliases + (alias BC849)) + (description "45V Vce, 0.1A Ic, Low noise, NPN, SOT-23") + (docs http://www.fairchildsemi.com/ds/BC/BC850.pdf) + (footprints + (fp SOT-23*)) + (fields + (field (name Reference) Q) + (field (name Value) BC850) + (field (name Footprint) SOT-23)) + (pins + (pin (num 1) (name B) (type input)) + (pin (num 2) (name E) (type passive)) + (pin (num 3) (name C) (type passive)))) + (libpart (lib device) (part FILTER) + (description "Filtre EMI") + (fields + (field (name Reference) FB) + (field (name Value) FILTER)) + (pins + (pin (num 1) (name 1) (type passive)) + (pin (num 2) (name 2) (type passive)))) + (libpart (lib device) (part SW_PUSH) + (description Button) + (fields + (field (name Reference) SW) + (field (name Value) SW_PUSH)) + (pins + (pin (num 1) (name 1) (type passive)) + (pin (num 2) (name 2) (type passive)))) + (libpart (lib conn) (part CONN_01X02) + (footprints + (fp Pin_Header_Straight_1X02) + (fp Pin_Header_Angled_1X02) + (fp Socket_Strip_Straight_1X02) + (fp Socket_Strip_Angled_1X02)) + (fields + (field (name Reference) P) + (field (name Value) CONN_01X02)) + (pins + (pin (num 1) (name P1) (type passive)) + (pin (num 2) (name P2) (type passive)))) + (libpart (lib ft232rq) (part FT232RQ) + (footprints + (fp QFN-32-1EP_5x5mm_Pitch0.5mm)) + (fields + (field (name Reference) U) + (field (name Value) FT232RQ)) + (pins + (pin (num 1) (name VCCIO) (type power_in)) + (pin (num 2) (name RXD) (type input)) + (pin (num 3) (name ~RI) (type input)) + (pin (num 4) (name GND) (type power_in)) + (pin (num 5) (name NC) (type NotConnected)) + (pin (num 6) (name ~DSR) (type input)) + (pin (num 7) (name ~DCD) (type input)) + (pin (num 8) (name ~CTS) (type input)) + (pin (num 9) (name CBUS4) (type BiDi)) + (pin (num 10) (name CBUS2) (type BiDi)) + (pin (num 11) (name CBUS3) (type BiDi)) + (pin (num 12) (name NC) (type NotConnected)) + (pin (num 13) (name NC) (type NotConnected)) + (pin (num 14) (name USBDP) (type BiDi)) + (pin (num 15) (name USBDM) (type BiDi)) + (pin (num 16) (name 3V3OUT) (type power_out)) + (pin (num 17) (name GND) (type power_in)) + (pin (num 18) (name ~RESET) (type input)) + (pin (num 19) (name VCC) (type power_in)) + (pin (num 20) (name GND) (type power_in)) + (pin (num 21) (name CBUS1) (type BiDi)) + (pin (num 22) (name CBUS0) (type BiDi)) + (pin (num 23) (name NC) (type NotConnected)) + (pin (num 24) (name AGND) (type power_in)) + (pin (num 25) (name NC) (type NotConnected)) + (pin (num 26) (name TEST) (type power_in)) + (pin (num 27) (name OSCI) (type input)) + (pin (num 28) (name OSCO) (type output)) + (pin (num 29) (name NC) (type NotConnected)) + (pin (num 30) (name TXD) (type output)) + (pin (num 31) (name ~DTR) (type output)) + (pin (num 32) (name ~RTS) (type output)) + (pin (num 33) (name PAD) (type power_in)))) + (libpart (lib conn) (part USB_OTG) + (description "micro/mini connector") + (footprints + (fp USB*)) + (fields + (field (name Reference) P) + (field (name Value) USB_OTG)) + (pins + (pin (num 1) (name VCC) (type power_out)) + (pin (num 2) (name D-) (type passive)) + (pin (num 3) (name D+) (type passive)) + (pin (num 4) (name ID) (type power_in)) + (pin (num 5) (name GND) (type power_in)) + (pin (num 6) (name shield) (type passive)))) + (libpart (lib device) (part CRYSTAL_SMD) + (fields + (field (name Reference) X) + (field (name Value) CRYSTAL_SMD)) + (pins + (pin (num 1) (name 1) (type passive)) + (pin (num 2) (name 2) (type passive)) + (pin (num 3) (name case) (type passive)))) + (libpart (lib device) (part C_Small) + (description "Unpolarized capacitor") + (footprints + (fp C?) + (fp C_????_*) + (fp C_????) + (fp SMD*_c) + (fp Capacitor*)) + (fields + (field (name Reference) C) + (field (name Value) C_Small)) + (pins + (pin (num 1) (name ~) (type passive)) + (pin (num 2) (name ~) (type passive)))) + (libpart (lib device) (part D) + (description Diode) + (footprints + (fp Diode_*) + (fp D-Pak_TO252AA) + (fp *SingleDiode) + (fp *_Diode_*) + (fp *SingleDiode*)) + (fields + (field (name Reference) D) + (field (name Value) D)) + (pins + (pin (num 1) (name K) (type passive)) + (pin (num 2) (name A) (type passive)))) + (libpart (lib esp8266ex) (part ESP8266EX) + (fields + (field (name Reference) U) + (field (name Value) ESP8266EX)) + (pins + (pin (num 1) (name VDDA) (type power_in)) + (pin (num 2) (name LNA) (type BiDi)) + (pin (num 3) (name VDD3P3) (type power_in)) + (pin (num 4) (name VDD3P3) (type power_in)) + (pin (num 5) (name VDD_RTC) (type power_out)) + (pin (num 6) (name TOUT) (type input)) + (pin (num 7) (name CHIP_EN) (type input)) + (pin (num 8) (name XPD_DCDC) (type BiDi)) + (pin (num 9) (name MTMS/GPIO14) (type BiDi)) + (pin (num 10) (name MTDI/GPIO12) (type BiDi)) + (pin (num 11) (name VDDPST) (type power_in)) + (pin (num 12) (name MTCK/GPIO13) (type BiDi)) + (pin (num 13) (name MTDO/GPIO15) (type BiDi)) + (pin (num 14) (name GPIO2) (type BiDi)) + (pin (num 15) (name GPIO0) (type BiDi)) + (pin (num 16) (name GPIO4/VD) (type BiDi)) + (pin (num 17) (name VDDPST) (type power_in)) + (pin (num 18) (name SD_DATA_2) (type BiDi)) + (pin (num 19) (name SD_DATA_3) (type BiDi)) + (pin (num 20) (name SD_CMD) (type BiDi)) + (pin (num 21) (name SD_CLK) (type BiDi)) + (pin (num 22) (name SD_DATA_0) (type BiDi)) + (pin (num 23) (name SD_DATA_1) (type BiDi)) + (pin (num 24) (name GPIO5) (type input)) + (pin (num 25) (name U0RXD) (type BiDi)) + (pin (num 26) (name U0TXD) (type BiDi)) + (pin (num 27) (name XTAL_OUT) (type BiDi)) + (pin (num 28) (name XTAL_IN) (type BiDi)) + (pin (num 29) (name VDDD) (type power_in)) + (pin (num 30) (name VDDA) (type power_in)) + (pin (num 31) (name RES12K) (type input)) + (pin (num 32) (name EXT_RSTB) (type input)) + (pin (num 33) (name GND) (type power_in)))) + (libpart (lib mcp73831) (part MCP73831) + (footprints + (fp SOT23-5)) + (fields + (field (name Reference) U) + (field (name Value) MCP73831)) + (pins + (pin (num 1) (name STAT) (type 3state)) + (pin (num 2) (name VSS) (type power_in)) + (pin (num 3) (name VBAT) (type power_out)) + (pin (num 4) (name VDD) (type power_in)) + (pin (num 5) (name PROG) (type input)))) + (libpart (lib mpu9250) (part MPU-9250) + (fields + (field (name Reference) U) + (field (name Value) MPU-9250)) + (pins + (pin (num 1) (name RE_VDDIO) (type passive)) + (pin (num 7) (name AUX_CL) (type output)) + (pin (num 8) (name VDDIO) (type power_in)) + (pin (num 9) (name AD0) (type input)) + (pin (num 10) (name REGOUT) (type input)) + (pin (num 11) (name FSYNC) (type input)) + (pin (num 12) (name INT) (type output)) + (pin (num 13) (name VDD) (type power_in)) + (pin (num 18) (name GND) (type power_in)) + (pin (num 19) (name RE_NC) (type passive)) + (pin (num 20) (name RE_GND) (type passive)) + (pin (num 21) (name AUX_DA) (type BiDi)) + (pin (num 22) (name nCS) (type input)) + (pin (num 23) (name SCL) (type input)) + (pin (num 24) (name SDA) (type BiDi)) + (pin (num 25) (name PAD) (type power_in)))) + (libpart (lib tlv70233) (part TLV70233-SOT-23) + (fields + (field (name Reference) U) + (field (name Value) TLV70233-SOT-23)) + (pins + (pin (num 1) (name IN) (type power_in)) + (pin (num 2) (name GND) (type power_in)) + (pin (num 3) (name EN) (type input)) + (pin (num 5) (name OUT) (type power_out)))) + (libpart (lib rv3029c2) (part RV-3029-C2) + (fields + (field (name Reference) U) + (field (name Value) RV-3029-C2)) + (pins + (pin (num 1) (name Vdd) (type power_in)) + (pin (num 2) (name CLKOUT) (type output)) + (pin (num 4) (name SCL) (type input)) + (pin (num 5) (name SDA) (type BiDi)) + (pin (num 6) (name Vss) (type power_in)) + (pin (num 7) (name ~INT) (type output)) + (pin (num 8) (name Vback) (type power_in)) + (pin (num 10) (name CLKOE) (type input)))) + (libpart (lib er-oled-ssd1306) (part ER-OLED-SSD1306) + (fields + (field (name Reference) DS) + (field (name Value) ER-OLED-SSD1306)) + (pins + (pin (num 1) (name GND) (type power_in)) + (pin (num 2) (name C2P) (type passive)) + (pin (num 3) (name C2N) (type passive)) + (pin (num 4) (name C1P) (type passive)) + (pin (num 5) (name C1N) (type passive)) + (pin (num 6) (name VBAT) (type power_in)) + (pin (num 7) (name ~) (type NotConnected)) + (pin (num 8) (name VSS) (type power_in)) + (pin (num 9) (name VDD) (type power_in)) + (pin (num 10) (name BS0) (type input)) + (pin (num 11) (name BS1) (type input)) + (pin (num 12) (name BS2) (type input)) + (pin (num 13) (name ~CS) (type input)) + (pin (num 14) (name ~RES) (type input)) + (pin (num 15) (name D/~C) (type input)) + (pin (num 16) (name R/~W) (type input)) + (pin (num 17) (name E/~RD) (type input)) + (pin (num 18) (name D0) (type BiDi)) + (pin (num 19) (name D1) (type input)) + (pin (num 20) (name D2) (type input)) + (pin (num 21) (name D3) (type input)) + (pin (num 22) (name D4) (type input)) + (pin (num 23) (name D5) (type input)) + (pin (num 24) (name D6) (type input)) + (pin (num 25) (name D7) (type input)) + (pin (num 26) (name IREF) (type input)) + (pin (num 27) (name VCOMH) (type output)) + (pin (num 28) (name VCC) (type power_in)) + (pin (num 29) (name VLSS) (type power_in)) + (pin (num 30) (name GND) (type power_in)))) + (libpart (lib pspice) (part R) + (description Resistance) + (fields + (field (name Reference) R) + (field (name Value) R)) + (pins + (pin (num 1) (name ~) (type passive)) + (pin (num 2) (name ~) (type passive)))) + (libpart (lib w25q32bv) (part W25Q32BV) + (fields + (field (name Reference) U) + (field (name Value) W25Q32BV)) + (pins + (pin (num 1) (name ~CS) (type input)) + (pin (num 2) (name DO) (type BiDi)) + (pin (num 3) (name ~WP) (type BiDi)) + (pin (num 4) (name GND) (type power_in)) + (pin (num 5) (name DI) (type BiDi)) + (pin (num 6) (name CLK) (type input)) + (pin (num 7) (name ~HOLD) (type BiDi)) + (pin (num 8) (name VCC) (type power_in)))) + (libpart (lib pspice) (part INDUCTOR) + (fields + (field (name Reference) L) + (field (name Value) INDUCTOR)) + (pins + (pin (num 1) (name 1) (type input)) + (pin (num 2) (name 2) (type input))))) + (libraries + (library (logical pspice) + (uri /usr/share/kicad/library/pspice.lib)) + (library (logical conn) + (uri /usr/share/kicad/library/conn.lib)) + (library (logical device) + (uri /usr/share/kicad/library/device.lib)) + (library (logical esp8266ex) + (uri /home/florian/prgm/handgelenk/board/lib/esp8266ex.lib)) + (library (logical mcp73831) + (uri /home/florian/prgm/handgelenk/board/lib/mcp73831.lib)) + (library (logical ft232rq) + (uri /home/florian/prgm/handgelenk/board/lib/ft232rq.lib)) + (library (logical mpu9250) + (uri /home/florian/prgm/handgelenk/board/lib/mpu9250.lib)) + (library (logical rv3029c2) + (uri /home/florian/prgm/handgelenk/board/lib/rv3029c2.lib)) + (library (logical w25q32bv) + (uri /home/florian/prgm/handgelenk/board/lib/w25q32bv.lib)) + (library (logical tlv70233) + (uri /home/florian/prgm/handgelenk/board/lib/tlv70233.lib)) + (library (logical er-oled-ssd1306) + (uri /home/florian/prgm/handgelenk/board/lib/er-oled-ssd1306.lib)) + (library (logical transistors) + (uri /usr/share/kicad/library/transistors.lib))) + (nets + (net (code 1) (name "Net-(R2-Pad1)") + (node (ref R2) (pin 1)) + (node (ref U1) (pin 31))) + (net (code 2) (name +3V3) + (node (ref U1) (pin 29)) + (node (ref U1) (pin 17)) + (node (ref C12) (pin 1)) + (node (ref C1) (pin 1)) + (node (ref R1) (pin 1)) + (node (ref U1) (pin 1)) + (node (ref U1) (pin 3)) + (node (ref U4) (pin 5)) + (node (ref U6) (pin 8)) + (node (ref U6) (pin 1)) + (node (ref U6) (pin 13)) + (node (ref R9) (pin 1)) + (node (ref U1) (pin 30)) + (node (ref P3) (pin 1)) + (node (ref U1) (pin 11)) + (node (ref DS1) (pin 6)) + (node (ref DS1) (pin 9)) + (node (ref U7) (pin 1)) + (node (ref DS1) (pin 11)) + (node (ref C13) (pin 1)) + (node (ref R10) (pin 1)) + (node (ref R11) (pin 1)) + (node (ref C6) (pin 1)) + (node (ref U5) (pin 8)) + (node (ref C7) (pin 1)) + (node (ref U1) (pin 4)) + (node (ref C18) (pin 1)) + (node (ref C15) (pin 1))) + (net (code 3) (name /VIBR) + (node (ref R3) (pin 2)) + (node (ref U1) (pin 10))) + (net (code 4) (name /MPU-9250/SCL) + (node (ref U6) (pin 23)) + (node (ref U1) (pin 9)) + (node (ref DS1) (pin 18)) + (node (ref U7) (pin 4)) + (node (ref R11) (pin 2))) + (net (code 5) (name /MPU-9250/SDA) + (node (ref U1) (pin 14)) + (node (ref DS1) (pin 19)) + (node (ref DS1) (pin 20)) + (node (ref U7) (pin 5)) + (node (ref R10) (pin 2)) + (node (ref U6) (pin 24))) + (net (code 6) (name "Net-(C19-Pad1)") + (node (ref R13) (pin 1)) + (node (ref DS1) (pin 14)) + (node (ref D3) (pin 2)) + (node (ref C19) (pin 1))) + (net (code 7) (name /MPU-9250/INT) + (node (ref C11) (pin 1)) + (node (ref R5) (pin 1)) + (node (ref U6) (pin 12)) + (node (ref U1) (pin 32))) + (net (code 8) (name /DS_WAKE) + (node (ref U1) (pin 8)) + (node (ref R5) (pin 2))) + (net (code 9) (name /RV-3029-C2/INT) + (node (ref R9) (pin 2)) + (node (ref U7) (pin 7)) + (node (ref C11) (pin 2))) + (net (code 10) (name "/Power Management/BATT_SENSE") + (node (ref R7) (pin 2)) + (node (ref R8) (pin 1)) + (node (ref U1) (pin 6))) + (net (code 11) (name /SD_CMD) + (node (ref U1) (pin 20)) + (node (ref U5) (pin 1))) + (net (code 12) (name /SD_D0) + (node (ref U5) (pin 2)) + (node (ref U1) (pin 22))) + (net (code 13) (name /SD_D1) + (node (ref U5) (pin 5)) + (node (ref U1) (pin 23))) + (net (code 14) (name /SD_D3) + (node (ref U5) (pin 3)) + (node (ref U1) (pin 19))) + (net (code 15) (name "/Power Management/TXD") + (node (ref U2) (pin 30)) + (node (ref U1) (pin 25))) + (net (code 16) (name "Net-(C9-Pad1)") + (node (ref U1) (pin 28)) + (node (ref X1) (pin 1)) + (node (ref C9) (pin 1))) + (net (code 17) (name "Net-(C10-Pad1)") + (node (ref X1) (pin 2)) + (node (ref C10) (pin 1)) + (node (ref U1) (pin 27))) + (net (code 18) (name "/Power Management/RXD") + (node (ref U1) (pin 26)) + (node (ref U2) (pin 2))) + (net (code 19) (name "/Power Management/DTR") + (node (ref U2) (pin 31)) + (node (ref U1) (pin 15))) + (net (code 20) (name "Net-(C8-Pad1)") + (node (ref U1) (pin 2)) + (node (ref C8) (pin 1))) + (net (code 21) (name "Net-(ANT1-Pad1)") + (node (ref C8) (pin 2)) + (node (ref ANT1) (pin 1))) + (net (code 22) (name "Net-(DS1-Pad7)") + (node (ref DS1) (pin 7))) + (net (code 23) (name "Net-(C23-Pad1)") + (node (ref DS1) (pin 5)) + (node (ref C23) (pin 1))) + (net (code 24) (name "Net-(C23-Pad2)") + (node (ref C23) (pin 2)) + (node (ref DS1) (pin 4))) + (net (code 25) (name "Net-(C22-Pad1)") + (node (ref DS1) (pin 3)) + (node (ref C22) (pin 1))) + (net (code 26) (name "Net-(C22-Pad2)") + (node (ref C22) (pin 2)) + (node (ref DS1) (pin 2))) + (net (code 27) (name "Net-(C20-Pad1)") + (node (ref C20) (pin 1)) + (node (ref DS1) (pin 27))) + (net (code 28) (name /BTN2) + (node (ref U1) (pin 24)) + (node (ref SW1) (pin 1)) + (node (ref C16) (pin 1)) + (node (ref D1) (pin 2))) + (net (code 29) (name "Net-(Q1-Pad1)") + (node (ref R3) (pin 1)) + (node (ref Q1) (pin 1))) + (net (code 30) (name GND) + (node (ref U6) (pin 20)) + (node (ref U2) (pin 33)) + (node (ref U6) (pin 9)) + (node (ref U2) (pin 24)) + (node (ref U2) (pin 26)) + (node (ref U2) (pin 17)) + (node (ref R13) (pin 2)) + (node (ref C15) (pin 2)) + (node (ref U7) (pin 10)) + (node (ref U7) (pin 8)) + (node (ref U7) (pin 6)) + (node (ref R8) (pin 2)) + (node (ref C14) (pin 2)) + (node (ref C2) (pin 2)) + (node (ref C12) (pin 2)) + (node (ref C13) (pin 2)) + (node (ref C7) (pin 2)) + (node (ref C6) (pin 2)) + (node (ref C3) (pin 2)) + (node (ref U6) (pin 25)) + (node (ref U2) (pin 20)) + (node (ref U2) (pin 4)) + (node (ref U6) (pin 11)) + (node (ref U4) (pin 2)) + (node (ref R4) (pin 2)) + (node (ref P1) (pin 6)) + (node (ref P1) (pin 5)) + (node (ref C4) (pin 2)) + (node (ref U6) (pin 18)) + (node (ref U3) (pin 2)) + (node (ref C5) (pin 2)) + (node (ref P2) (pin 1)) + (node (ref C1) (pin 2)) + (node (ref R2) (pin 2)) + (node (ref U5) (pin 4)) + (node (ref X1) (pin 3)) + (node (ref C9) (pin 2)) + (node (ref C10) (pin 2)) + (node (ref R12) (pin 2)) + (node (ref Q1) (pin 2)) + (node (ref DS1) (pin 22)) + (node (ref DS1) (pin 13)) + (node (ref DS1) (pin 23)) + (node (ref DS1) (pin 24)) + (node (ref DS1) (pin 15)) + (node (ref DS1) (pin 25)) + (node (ref U1) (pin 13)) + (node (ref U1) (pin 33)) + (node (ref D3) (pin 1)) + (node (ref DS1) (pin 10)) + (node (ref DS1) (pin 30)) + (node (ref DS1) (pin 21)) + (node (ref DS1) (pin 1)) + (node (ref DS1) (pin 8)) + (node (ref DS1) (pin 16)) + (node (ref DS1) (pin 17)) + (node (ref C17) (pin 2)) + (node (ref DS1) (pin 29)) + (node (ref C19) (pin 2)) + (node (ref C16) (pin 2)) + (node (ref DS1) (pin 12)) + (node (ref C18) (pin 2)) + (node (ref C24) (pin 2)) + (node (ref R14) (pin 2)) + (node (ref C21) (pin 2)) + (node (ref C20) (pin 2))) + (net (code 31) (name /BTN1) + (node (ref D2) (pin 2)) + (node (ref SW2) (pin 1)) + (node (ref C17) (pin 1)) + (node (ref U1) (pin 16))) + (net (code 32) (name "Net-(P3-Pad2)") + (node (ref Q1) (pin 3)) + (node (ref P3) (pin 2))) + (net (code 33) (name "Net-(D1-Pad1)") + (node (ref D1) (pin 1)) + (node (ref D2) (pin 1)) + (node (ref SW3) (pin 1))) + (net (code 34) (name "Net-(R12-Pad1)") + (node (ref R12) (pin 1)) + (node (ref SW2) (pin 2)) + (node (ref SW1) (pin 2)) + (node (ref SW3) (pin 2))) + (net (code 35) (name "Net-(ANT1-Pad2)") + (node (ref ANT1) (pin 2))) + (net (code 36) (name "/Power Management/RTS") + (node (ref U2) (pin 32)) + (node (ref U1) (pin 7)) + (node (ref R1) (pin 2))) + (net (code 37) (name /SD_CLK) + (node (ref U1) (pin 21)) + (node (ref R6) (pin 2))) + (net (code 38) (name "Net-(R6-Pad1)") + (node (ref R6) (pin 1)) + (node (ref U5) (pin 6))) + (net (code 39) (name "Net-(U1-Pad5)") + (node (ref U1) (pin 5))) + (net (code 40) (name "/Power Management/~CHARGE") + (node (ref U3) (pin 1)) + (node (ref U1) (pin 12))) + (net (code 41) (name /SD_D2) + (node (ref U1) (pin 18)) + (node (ref U5) (pin 7))) + (net (code 42) (name "Net-(DS1-Pad26)") + (node (ref DS1) (pin 26)) + (node (ref R14) (pin 1))) + (net (code 43) (name "Net-(C21-Pad1)") + (node (ref C21) (pin 1)) + (node (ref C24) (pin 1)) + (node (ref DS1) (pin 28))) + (net (code 44) (name +BATT) + (node (ref C5) (pin 1)) + (node (ref U4) (pin 3)) + (node (ref P2) (pin 2)) + (node (ref U3) (pin 3)) + (node (ref R7) (pin 1)) + (node (ref U4) (pin 1))) + (net (code 45) (name "Net-(U2-Pad28)") + (node (ref U2) (pin 28))) + (net (code 46) (name "Net-(U2-Pad27)") + (node (ref U2) (pin 27))) + (net (code 47) (name "Net-(U2-Pad22)") + (node (ref U2) (pin 22))) + (net (code 48) (name "/Power Management/USB_DM") + (node (ref P1) (pin 2)) + (node (ref U2) (pin 15))) + (net (code 49) (name "/Power Management/USB_DP") + (node (ref P1) (pin 3)) + (node (ref U2) (pin 14))) + (net (code 50) (name "Net-(U2-Pad21)") + (node (ref U2) (pin 21))) + (net (code 51) (name "Net-(U2-Pad10)") + (node (ref U2) (pin 10))) + (net (code 52) (name "Net-(U2-Pad11)") + (node (ref U2) (pin 11))) + (net (code 53) (name "Net-(U2-Pad9)") + (node (ref U2) (pin 9))) + (net (code 54) (name "Net-(U2-Pad18)") + (node (ref U2) (pin 18))) + (net (code 55) (name "Net-(U2-Pad3)") + (node (ref U2) (pin 3))) + (net (code 56) (name "Net-(U2-Pad7)") + (node (ref U2) (pin 7))) + (net (code 57) (name "Net-(U2-Pad6)") + (node (ref U2) (pin 6))) + (net (code 58) (name "Net-(U2-Pad8)") + (node (ref U2) (pin 8))) + (net (code 59) (name "Net-(C2-Pad1)") + (node (ref C2) (pin 1)) + (node (ref U2) (pin 1)) + (node (ref U2) (pin 16))) + (net (code 60) (name "Net-(U2-Pad12)") + (node (ref U2) (pin 12))) + (net (code 61) (name "Net-(U2-Pad13)") + (node (ref U2) (pin 13))) + (net (code 62) (name "Net-(U2-Pad23)") + (node (ref U2) (pin 23))) + (net (code 63) (name "Net-(U2-Pad25)") + (node (ref U2) (pin 25))) + (net (code 64) (name +5V) + (node (ref U2) (pin 19)) + (node (ref C4) (pin 1)) + (node (ref U3) (pin 4)) + (node (ref FB1) (pin 2))) + (net (code 65) (name "Net-(U2-Pad29)") + (node (ref U2) (pin 29))) + (net (code 66) (name "Net-(U2-Pad5)") + (node (ref U2) (pin 5))) + (net (code 67) (name "Net-(R4-Pad1)") + (node (ref R4) (pin 1)) + (node (ref U3) (pin 5))) + (net (code 68) (name "Net-(P1-Pad4)") + (node (ref P1) (pin 4))) + (net (code 69) (name "Net-(C3-Pad1)") + (node (ref P1) (pin 1)) + (node (ref FB1) (pin 1)) + (node (ref C3) (pin 1))) + (net (code 70) (name "Net-(U6-Pad19)") + (node (ref U6) (pin 19))) + (net (code 71) (name "Net-(U6-Pad21)") + (node (ref U6) (pin 21))) + (net (code 72) (name "Net-(U6-Pad7)") + (node (ref U6) (pin 7))) + (net (code 73) (name "Net-(U6-Pad22)") + (node (ref U6) (pin 22))) + (net (code 74) (name "Net-(C14-Pad1)") + (node (ref U6) (pin 10)) + (node (ref C14) (pin 1))) + (net (code 75) (name "Net-(U7-Pad2)") + (node (ref U7) (pin 2))))) \ No newline at end of file diff --git a/board/v1/handgelenk.pro b/board/v1/handgelenk.pro new file mode 100644 index 0000000..473a3a7 --- /dev/null +++ b/board/v1/handgelenk.pro @@ -0,0 +1,118 @@ +update=Sa 19 Sep 2015 10:45:39 CEST +version=1 +last_client=kicad +[pcbnew] +version=1 +LastNetListRead= +UseCmpFile=1 +PadDrill=0.600000000000 +PadDrillOvalY=0.600000000000 +PadSizeH=1.500000000000 +PadSizeV=1.500000000000 +PcbTextSizeV=1.500000000000 +PcbTextSizeH=1.500000000000 +PcbTextThickness=0.300000000000 +ModuleTextSizeV=1.000000000000 +ModuleTextSizeH=1.000000000000 +ModuleTextSizeThickness=0.150000000000 +SolderMaskClearance=0.000000000000 +SolderMaskMinWidth=0.000000000000 +DrawSegmentWidth=0.200000000000 +BoardOutlineThickness=0.100000000000 +ModuleOutlineThickness=0.150000000000 +[cvpcb] +version=1 +NetIExt=net +[general] +version=1 +[eeschema] +version=1 +LibDir= +[eeschema/libraries] +LibName1=handgelenk-rescue +LibName2=Zilog +LibName3=xilinx +LibName4=Xicor +LibName5=video +LibName6=valves +LibName7=ttl_ieee +LibName8=transistors +LibName9=transf +LibName10=texas +LibName11=switches +LibName12=supertex +LibName13=stm32 +LibName14=stm8 +LibName15=siliconi +LibName16=silabs +LibName17=sensors +LibName18=rfcom +LibName19=relays +LibName20=regul +LibName21=references +LibName22=pspice +LibName23=Power_Management +LibName24=powerint +LibName25=power +LibName26=philips +LibName27=Oscillators +LibName28=opto +LibName29=onsemi +LibName30=nxp_armmcu +LibName31=nordicsemi +LibName32=msp430 +LibName33=motorola +LibName34=motor_drivers +LibName35=microcontrollers +LibName36=microchip_pic32mcu +LibName37=microchip_pic18mcu +LibName38=microchip_pic16mcu +LibName39=microchip_pic12mcu +LibName40=microchip_pic10mcu +LibName41=microchip_dspic33dsc +LibName42=microchip +LibName43=memory +LibName44=maxim +LibName45=logo +LibName46=linear +LibName47=Lattice +LibName48=ir +LibName49=interface +LibName50=intel +LibName51=hc11 +LibName52=graphic +LibName53=gennum +LibName54=ftdi +LibName55=ESD_Protection +LibName56=elec-unifil +LibName57=dsp +LibName58=display +LibName59=diode +LibName60=digital-audio +LibName61=device +LibName62=dc-dc +LibName63=cypress +LibName64=contrib +LibName65=conn +LibName66=cmos_ieee +LibName67=cmos4000 +LibName68=brooktre +LibName69=audio +LibName70=atmel +LibName71=analog_switches +LibName72=analog_devices +LibName73=Altera +LibName74=adc-dac +LibName75=actel +LibName76=ac-dc +LibName77=74xx +LibName78=74xgxx +LibName79=lib/mcp73831 +LibName80=lib/esp8266ex +LibName81=lib/ft232rq +LibName82=lib/mpu9250 +LibName83=lib/w25q32bv +LibName84=lib/lt1129cst +LibName85=lib/rv3029c2 +LibName86=lib/tlv70233 +LibName87=lib/er-oled-ssd1306 diff --git a/board/v1/handgelenk.sch b/board/v1/handgelenk.sch new file mode 100644 index 0000000..d83a51a --- /dev/null +++ b/board/v1/handgelenk.sch @@ -0,0 +1,1221 @@ +EESchema Schematic File Version 2 +LIBS:handgelenk-rescue +LIBS:Zilog +LIBS:xilinx +LIBS:Xicor +LIBS:video +LIBS:valves +LIBS:ttl_ieee +LIBS:transistors +LIBS:transf +LIBS:texas +LIBS:switches +LIBS:supertex +LIBS:stm32 +LIBS:stm8 +LIBS:siliconi +LIBS:silabs +LIBS:sensors +LIBS:rfcom +LIBS:relays +LIBS:regul +LIBS:references +LIBS:pspice +LIBS:Power_Management +LIBS:powerint +LIBS:power +LIBS:philips +LIBS:Oscillators +LIBS:opto +LIBS:onsemi +LIBS:nxp_armmcu +LIBS:nordicsemi +LIBS:msp430 +LIBS:motorola +LIBS:motor_drivers +LIBS:microcontrollers +LIBS:microchip_pic32mcu +LIBS:microchip_pic18mcu +LIBS:microchip_pic16mcu +LIBS:microchip_pic12mcu +LIBS:microchip_pic10mcu +LIBS:microchip_dspic33dsc +LIBS:microchip +LIBS:memory +LIBS:maxim +LIBS:logo +LIBS:linear +LIBS:Lattice +LIBS:ir +LIBS:interface +LIBS:intel +LIBS:hc11 +LIBS:graphic +LIBS:gennum +LIBS:ftdi +LIBS:ESD_Protection +LIBS:elec-unifil +LIBS:dsp +LIBS:display +LIBS:diode +LIBS:digital-audio +LIBS:device +LIBS:dc-dc +LIBS:cypress +LIBS:contrib +LIBS:conn +LIBS:cmos_ieee +LIBS:cmos4000 +LIBS:brooktre +LIBS:audio +LIBS:atmel +LIBS:analog_switches +LIBS:analog_devices +LIBS:Altera +LIBS:adc-dac +LIBS:actel +LIBS:ac-dc +LIBS:74xx +LIBS:74xgxx +LIBS:mcp73831 +LIBS:esp8266ex +LIBS:ft232rq +LIBS:mpu9250 +LIBS:w25q32bv +LIBS:lt1129cst +LIBS:rv3029c2 +LIBS:tlv70233 +LIBS:er-oled-ssd1306 +LIBS:handgelenk-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 1 4 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +$Sheet +S 1050 5600 1250 700 +U 55CFAED1 +F0 "Power Management" 60 +F1 "power.sch" 60 +F2 "~CHARGE" O R 2300 5700 60 +F3 "TXD" O R 2300 5800 60 +F4 "RXD" I L 1050 5700 60 +F5 "RTS" O R 2300 5900 60 +F6 "DTR" O R 2300 6000 60 +F7 "BATT_SENSE" O R 2300 6100 60 +$EndSheet +Text Label 2700 5900 2 60 ~ 0 +ESP_EN +Text Label 2700 6000 2 60 ~ 0 +ESP_PRG +Text Label 650 5700 0 60 ~ 0 +ESP_TXD +Text Label 2700 5800 2 60 ~ 0 +ESP_RXD +$Comp +L GND #PWR01 +U 1 1 55F6E5C0 +P 4650 4550 +F 0 "#PWR01" H 4650 4300 50 0001 C CNN +F 1 "GND" H 4650 4400 50 0000 C CNN +F 2 "" H 4650 4550 60 0000 C CNN +F 3 "" H 4650 4550 60 0000 C CNN + 1 4650 4550 + 1 0 0 -1 +$EndComp +$Comp +L R R2 +U 1 1 55F6E5F4 +P 3700 4200 +F 0 "R2" V 3600 4200 50 0000 C CNN +F 1 "12K" V 3700 4200 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 3700 4200 60 0001 C CNN +F 3 "" H 3700 4200 60 0000 C CNN + 1 3700 4200 + 1 0 0 -1 +$EndComp +$Comp +L +3V3 #PWR02 +U 1 1 55F6ECF1 +P 1700 1100 +F 0 "#PWR02" H 1700 950 50 0001 C CNN +F 1 "+3V3" H 1700 1240 50 0000 C CNN +F 2 "" H 1700 1100 60 0000 C CNN +F 3 "" H 1700 1100 60 0000 C CNN + 1 1700 1100 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C1 +U 1 1 55F6EFF8 +P 1700 1800 +F 0 "C1" H 1710 1870 50 0000 L CNN +F 1 "100n" H 1710 1720 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 1700 1800 60 0001 C CNN +F 3 "" H 1700 1800 60 0000 C CNN + 1 1700 1800 + 1 0 0 -1 +$EndComp +$Comp +L R R1 +U 1 1 55F6F69B +P 2400 1800 +F 0 "R1" V 2480 1800 50 0000 C CNN +F 1 "1K" V 2400 1800 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 2400 1800 60 0001 C CNN +F 3 "" H 2400 1800 60 0000 C CNN + 1 2400 1800 + 1 0 0 -1 +$EndComp +$Comp +L ESP8266EX U1 +U 1 1 55F70BBB +P 3750 2650 +F 0 "U1" H 3250 3600 60 0000 C CNN +F 1 "ESP8266EX" H 4150 1650 60 0000 C CNN +F 2 "Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm" H 2950 2950 60 0001 C CNN +F 3 "" H 2950 2950 60 0000 C CNN + 1 3750 2650 + 1 0 0 -1 +$EndComp +NoConn ~ 2900 2100 +$Comp +L CRYSTAL_SMD X1 +U 1 1 55F71659 +P 2150 3050 +F 0 "X1" H 2150 3140 50 0000 C CNN +F 1 "26MHz" V 2250 2750 50 0000 L CNN +F 2 "Project Libraries:crystal_2.5x2" H 2150 3050 60 0001 C CNN +F 3 "" H 2150 3050 60 0000 C CNN + 1 2150 3050 + 0 1 1 0 +$EndComp +$Comp +L C_Small C9 +U 1 1 55F73D4E +P 1900 2750 +F 0 "C9" H 1910 2820 50 0000 L CNN +F 1 "10p" H 1910 2670 50 0000 L CNN +F 2 "Capacitors_SMD:C_0402" H 1900 2750 60 0001 C CNN +F 3 "" H 1900 2750 60 0000 C CNN + 1 1900 2750 + 0 1 1 0 +$EndComp +$Comp +L C_Small C10 +U 1 1 55F73EE1 +P 1950 3350 +F 0 "C10" H 1960 3420 50 0000 L CNN +F 1 "10p" H 1960 3270 50 0000 L CNN +F 2 "Capacitors_SMD:C_0402" H 1950 3350 60 0001 C CNN +F 3 "" H 1950 3350 60 0000 C CNN + 1 1950 3350 + 0 1 1 0 +$EndComp +Text Label 2450 3250 0 60 ~ 0 +ESP_RXD +Text Label 2450 3350 0 60 ~ 0 +ESP_TXD +Text Label 2450 2450 0 60 ~ 0 +ESP_PRG +Text Label 2450 2250 0 60 ~ 0 +ESP_EN +$Comp +L C_Small C8 +U 1 1 55F80CB5 +P 1250 2600 +F 0 "C8" V 1100 2500 50 0000 L CNN +F 1 "5.6p" V 1400 2550 50 0000 L CNN +F 2 "Capacitors_SMD:C_0402" H 1250 2600 60 0001 C CNN +F 3 "" H 1250 2600 60 0000 C CNN + 1 1250 2600 + 0 1 1 0 +$EndComp +$Comp +L INDUCTOR ANT1 +U 1 1 55F8139E +P 850 2250 +F 0 "ANT1" H 850 2350 50 0000 C CNN +F 1 "AN9520" H 850 2200 50 0000 C CNN +F 2 "Project Libraries:an9520" H 850 2250 60 0001 C CNN +F 3 "" H 850 2250 60 0000 C CNN + 1 850 2250 + 0 -1 -1 0 +$EndComp +NoConn ~ 850 2000 +$Sheet +S 1100 6950 1250 700 +U 55F844A4 +F0 "MPU-9250" 60 +F1 "mpu9250.sch" 60 +F2 "SCL" I L 1100 7050 60 +F3 "SDA" B L 1100 7150 60 +F4 "INT" O R 2350 7050 60 +$EndSheet +Text Label 5000 2250 2 60 ~ 0 +SDA +Text Label 5000 2800 2 60 ~ 0 +SCL +Text Label 700 7050 0 60 ~ 0 +SCL +Text Label 700 7150 0 60 ~ 0 +SDA +Text Label 2450 3000 0 60 ~ 0 +DS_WAKE +Text Label 2450 3100 0 60 ~ 0 +ESP_RST +Text Notes 5600 5150 0 30 ~ 0 +Reset / deep sleep\nwakeup triggers:\nXPD_DCDC (ESP RTC\nTimer), MPU-9250, RTC +Text Label 2750 7050 2 60 ~ 0 +MPU_INT +Text Label 7800 4900 2 60 ~ 0 +ESP_RST +Text Label 6300 4900 0 60 ~ 0 +DS_WAKE +$Comp +L R R5 +U 1 1 55F9485D +P 7050 4900 +F 0 "R5" V 7130 4900 50 0000 C CNN +F 1 "300" V 7050 4900 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 7050 4900 60 0001 C CNN +F 3 "" H 7050 4900 60 0000 C CNN + 1 7050 4900 + 0 1 1 0 +$EndComp +Text Label 6300 5100 0 60 ~ 0 +MPU_INT +Text Label 6300 5300 0 60 ~ 0 +RTC_INT +$Comp +L C_Small C11 +U 1 1 55F956F5 +P 7050 5300 +F 0 "C11" H 7060 5370 50 0000 L CNN +F 1 "100n" H 7060 5220 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 7050 5300 60 0001 C CNN +F 3 "" H 7050 5300 60 0000 C CNN + 1 7050 5300 + 0 1 1 0 +$EndComp +$Sheet +S 3800 6950 1250 700 +U 55F97917 +F0 "RV-3029-C2" 60 +F1 "rv3029c2.sch" 60 +F2 "SCL" I L 3800 7050 60 +F3 "SDA" B L 3800 7150 60 +F4 "INT" O R 5050 7050 60 +$EndSheet +Text Label 3450 7050 0 60 ~ 0 +SCL +Text Label 3450 7150 0 60 ~ 0 +SDA +Text Label 5450 7050 2 60 ~ 0 +RTC_INT +Text Label 2700 6100 2 60 ~ 0 +ESP_ADC +Text Label 5000 2100 2 60 ~ 0 +ESP_ADC +$Comp +L W25Q32BV U5 +U 1 1 55F989A1 +P 10150 5700 +F 0 "U5" H 9900 6050 60 0000 C CNN +F 1 "W25Q32BV" H 10450 5350 60 0000 C CNN +F 2 "Project Libraries:wson8_5x6" H 10150 5500 60 0001 C CNN +F 3 "" H 10150 5500 60 0000 C CNN + 1 10150 5700 + 1 0 0 -1 +$EndComp +Text Notes 7950 6450 0 60 ~ 0 +PCB supports both SOIC8 and WSON\nchips. SOIC-8 chips are well-tested\nand easy to obtain, WSON chips are\nflatter (better suited for a watch), but\nharder to obtain +$Comp +L +3V3 #PWR03 +U 1 1 55F991E3 +P 10150 5100 +F 0 "#PWR03" H 10150 4950 50 0001 C CNN +F 1 "+3V3" H 10150 5240 50 0000 C CNN +F 2 "" H 10150 5100 60 0000 C CNN +F 3 "" H 10150 5100 60 0000 C CNN + 1 10150 5100 + 1 0 0 -1 +$EndComp +$Comp +L GND #PWR04 +U 1 1 55F99421 +P 10150 6300 +F 0 "#PWR04" H 10150 6050 50 0001 C CNN +F 1 "GND" H 10150 6150 50 0000 C CNN +F 2 "" H 10150 6300 60 0000 C CNN +F 3 "" H 10150 6300 60 0000 C CNN + 1 10150 6300 + 1 0 0 -1 +$EndComp +Text Label 8650 5650 0 60 ~ 0 +SD_CMD +Text Label 8650 5750 0 60 ~ 0 +SD_CLK +Text Label 11050 5900 2 60 ~ 0 +SD_D3 +Text Label 11050 5750 2 60 ~ 0 +SD_D0 +Text Label 11050 5650 2 60 ~ 0 +SD_D1 +Text Label 11050 5500 2 60 ~ 0 +SD_D2 +Text Label 5000 2950 2 60 ~ 0 +SD_D1 +Text Label 5000 3050 2 60 ~ 0 +SD_D0 +Text Label 5000 3150 2 60 ~ 0 +SD_CLK +Text Label 5000 3250 2 60 ~ 0 +SD_CMD +Text Label 5000 3350 2 60 ~ 0 +SD_D3 +Text Label 5000 3450 2 60 ~ 0 +SD_D2 +$Comp +L R R6 +U 1 1 55F9BA0E +P 9300 5750 +F 0 "R6" V 9380 5750 50 0000 C CNN +F 1 "200" V 9300 5750 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 9300 5750 60 0001 C CNN +F 3 "" H 9300 5750 60 0000 C CNN + 1 9300 5750 + 0 1 1 0 +$EndComp +Text Label 5000 2700 2 60 ~ 0 +~CHARGE +Text Label 2700 5700 2 60 ~ 0 +~CHARGE +Text Notes 7950 4800 0 120 ~ 0 +SPI Flash Memory +$Comp +L GND #PWR05 +U 1 1 55FB2E97 +P 10200 4250 +F 0 "#PWR05" H 10200 4000 50 0001 C CNN +F 1 "GND" H 10200 4100 50 0000 C CNN +F 2 "" H 10200 4250 60 0000 C CNN +F 3 "" H 10200 4250 60 0000 C CNN + 1 10200 4250 + 1 0 0 -1 +$EndComp +Text Label 9450 2750 0 60 ~ 0 +SDA +Text Label 9450 2650 0 60 ~ 0 +SCL +$Comp +L R R14 +U 1 1 55FB6136 +P 9200 3800 +F 0 "R14" V 9280 3800 50 0000 C CNN +F 1 "390K" V 9200 3800 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 9200 3800 60 0001 C CNN +F 3 "" H 9200 3800 60 0000 C CNN + 1 9200 3800 + 1 0 0 -1 +$EndComp +$Comp +L +3V3 #PWR06 +U 1 1 55FB776A +P 8050 950 +F 0 "#PWR06" H 8050 800 50 0001 C CNN +F 1 "+3V3" H 8050 1090 50 0000 C CNN +F 2 "" H 8050 950 60 0000 C CNN +F 3 "" H 8050 950 60 0000 C CNN + 1 8050 950 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C21 +U 1 1 55FB8922 +P 9700 3850 +F 0 "C21" H 9710 3920 50 0000 L CNN +F 1 "2u2" H 9710 3770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 9700 3850 60 0001 C CNN +F 3 "" H 9700 3850 60 0000 C CNN + 1 9700 3850 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C20 +U 1 1 55FB96CA +P 9450 3850 +F 0 "C20" H 9460 3920 50 0000 L CNN +F 1 "4u7" H 9460 3770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 9450 3850 60 0001 C CNN +F 3 "" H 9450 3850 60 0000 C CNN + 1 9450 3850 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C24 +U 1 1 55FB9F0B +P 9950 3850 +F 0 "C24" H 9960 3920 50 0000 L CNN +F 1 "100n" H 9960 3770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 9950 3850 60 0001 C CNN +F 3 "" H 9950 3850 60 0000 C CNN + 1 9950 3850 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C19 +U 1 1 55FBAEDC +P 8950 3850 +F 0 "C19" H 8960 3920 50 0000 L CNN +F 1 "2u2" H 8960 3770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 8950 3850 60 0001 C CNN +F 3 "" H 8950 3850 60 0000 C CNN + 1 8950 3850 + 1 0 0 -1 +$EndComp +Text Notes 9500 2450 0 39 ~ 0 +Pin 15 D/C is Low:\nI²C Addr. is 0x3c\nread, 0x78 write +$Comp +L C_Small C22 +U 1 1 55FBD1F4 +P 9750 1050 +F 0 "C22" H 9760 1120 50 0000 L CNN +F 1 "1u" H 9760 970 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 9750 1050 60 0001 C CNN +F 3 "" H 9750 1050 60 0000 C CNN + 1 9750 1050 + 0 -1 -1 0 +$EndComp +$Comp +L C_Small C23 +U 1 1 55FBD8B2 +P 9750 1350 +F 0 "C23" H 9760 1420 50 0000 L CNN +F 1 "1u" H 9760 1270 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 9750 1350 60 0001 C CNN +F 3 "" H 9750 1350 60 0000 C CNN + 1 9750 1350 + 0 1 1 0 +$EndComp +$Comp +L C_Small C18 +U 1 1 55FBFB19 +P 8050 3850 +F 0 "C18" H 8060 3920 50 0000 L CNN +F 1 "1u" H 8060 3770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 8050 3850 60 0001 C CNN +F 3 "" H 8050 3850 60 0000 C CNN + 1 8050 3850 + 1 0 0 -1 +$EndComp +Text Notes 8150 3400 0 60 ~ 0 +Bypass cap,\nplace close\nto display +$Comp +L R R13 +U 1 1 55FC214E +P 8700 3800 +F 0 "R13" V 8780 3800 50 0000 C CNN +F 1 "10K" V 8700 3800 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 8700 3800 60 0001 C CNN +F 3 "" H 8700 3800 60 0000 C CNN + 1 8700 3800 + 1 0 0 -1 +$EndComp +Connection ~ 10050 1750 +Wire Wire Line + 10300 1750 10050 1750 +Connection ~ 10050 1450 +Wire Wire Line + 10050 1950 10050 1450 +Wire Wire Line + 10300 1950 10050 1950 +Connection ~ 8950 3500 +Wire Wire Line + 8450 3500 8950 3500 +Wire Wire Line + 8700 3550 8700 3500 +Connection ~ 8700 4200 +Wire Wire Line + 8700 4050 8700 4200 +Connection ~ 8950 4200 +Wire Wire Line + 9850 1350 10300 1350 +Wire Wire Line + 9600 1350 9650 1350 +Wire Wire Line + 9600 1250 9600 1350 +Wire Wire Line + 9600 1250 10300 1250 +Wire Wire Line + 9600 1150 10300 1150 +Wire Wire Line + 9600 1050 9600 1150 +Wire Wire Line + 9650 1050 9600 1050 +Wire Wire Line + 9850 1050 10300 1050 +Connection ~ 10200 2150 +Wire Wire Line + 10300 2150 10200 2150 +Connection ~ 10200 2350 +Wire Wire Line + 10300 2350 10200 2350 +Connection ~ 10200 2550 +Wire Wire Line + 10300 2550 10200 2550 +Connection ~ 10200 2450 +Wire Wire Line + 10300 2450 10200 2450 +Wire Wire Line + 8950 2250 8950 3750 +Wire Wire Line + 8950 2250 10300 2250 +Connection ~ 9200 4200 +Wire Wire Line + 8950 4200 8950 3950 +Connection ~ 9700 4200 +Wire Wire Line + 9700 3950 9700 4200 +Connection ~ 9950 3650 +Wire Wire Line + 9700 3750 9700 3650 +Wire Wire Line + 10300 3450 9200 3450 +Connection ~ 9450 4200 +Wire Wire Line + 9450 3950 9450 4200 +Wire Wire Line + 9450 3550 9450 3750 +Wire Wire Line + 9450 3550 10300 3550 +Wire Wire Line + 9200 4050 9200 4200 +Wire Wire Line + 9200 3450 9200 3550 +Connection ~ 9950 4200 +Wire Wire Line + 9950 4200 9950 3950 +Wire Wire Line + 9950 3350 9950 3750 +Wire Wire Line + 9700 3650 10300 3650 +Wire Wire Line + 8050 1450 10300 1450 +Connection ~ 10200 4200 +Wire Wire Line + 8050 4200 10200 4200 +Wire Wire Line + 9450 2650 10300 2650 +Connection ~ 9700 2750 +Wire Wire Line + 9450 2750 10300 2750 +Wire Wire Line + 9700 2850 9700 2750 +Wire Wire Line + 9700 2850 10300 2850 +Connection ~ 10200 2050 +Wire Wire Line + 10300 2050 10200 2050 +Connection ~ 10200 1850 +Wire Wire Line + 10300 1850 10200 1850 +Connection ~ 10200 3750 +Wire Wire Line + 10300 3750 10200 3750 +Connection ~ 10200 1650 +Wire Wire Line + 10300 1650 10200 1650 +Connection ~ 10200 3850 +Wire Wire Line + 10300 950 10200 950 +Wire Wire Line + 10200 950 10200 4250 +Wire Wire Line + 10300 3850 10200 3850 +Wire Notes Line + 11150 4600 7900 4600 +Wire Notes Line + 11150 6500 11150 4600 +Wire Notes Line + 7900 6500 11150 6500 +Wire Notes Line + 7900 4600 7900 6500 +Wire Wire Line + 2700 5700 2300 5700 +Wire Wire Line + 4600 2700 5000 2700 +Connection ~ 1700 3050 +Wire Wire Line + 2050 3050 1700 3050 +Wire Wire Line + 9050 5750 8650 5750 +Wire Wire Line + 9550 5750 9650 5750 +Wire Wire Line + 4600 3450 5000 3450 +Wire Wire Line + 5000 3350 4600 3350 +Wire Wire Line + 4600 3250 5000 3250 +Wire Wire Line + 4600 3150 5000 3150 +Wire Wire Line + 4600 3050 5000 3050 +Wire Wire Line + 4600 2950 5000 2950 +Wire Wire Line + 11050 5500 10650 5500 +Wire Wire Line + 11050 5650 10650 5650 +Wire Wire Line + 11050 5750 10650 5750 +Wire Wire Line + 11050 5900 10650 5900 +Wire Wire Line + 8650 5650 9650 5650 +Wire Wire Line + 10150 6300 10150 6200 +Wire Wire Line + 10150 5100 10150 5200 +Wire Wire Line + 4600 2100 5000 2100 +Wire Wire Line + 2300 6100 2700 6100 +Wire Wire Line + 5450 7050 5050 7050 +Wire Wire Line + 3450 7150 3800 7150 +Wire Wire Line + 3450 7050 3800 7050 +Connection ~ 7350 5100 +Wire Wire Line + 7350 5300 7150 5300 +Wire Wire Line + 6950 5300 6300 5300 +Connection ~ 7350 4900 +Wire Wire Line + 7350 4900 7350 5300 +Wire Wire Line + 6300 5100 7350 5100 +Wire Wire Line + 7300 4900 7800 4900 +Wire Wire Line + 6300 4900 6800 4900 +Wire Wire Line + 2750 7050 2350 7050 +Wire Wire Line + 2900 3100 2450 3100 +Wire Wire Line + 2450 3000 2900 3000 +Wire Wire Line + 850 2600 850 2500 +Wire Wire Line + 1100 7150 700 7150 +Wire Wire Line + 1100 7050 700 7050 +Wire Wire Line + 4600 2800 5000 2800 +Wire Wire Line + 4600 2250 5000 2250 +Wire Wire Line + 850 2600 1150 2600 +Wire Wire Line + 1350 2600 2900 2600 +Connection ~ 1700 1350 +Wire Wire Line + 1700 1100 1700 1700 +Connection ~ 1700 2350 +Wire Wire Line + 2400 2250 2900 2250 +Wire Wire Line + 2450 2450 2900 2450 +Wire Wire Line + 2450 3250 2900 3250 +Wire Wire Line + 2900 3350 2450 3350 +Connection ~ 1700 2750 +Wire Wire Line + 1800 2750 1700 2750 +Connection ~ 1700 3350 +Wire Wire Line + 1850 3350 1700 3350 +Connection ~ 2150 3350 +Connection ~ 2150 2750 +Wire Wire Line + 2300 3350 2050 3350 +Wire Wire Line + 2150 3250 2150 3350 +Wire Wire Line + 2300 2850 2300 3350 +Wire Wire Line + 2900 2850 2300 2850 +Wire Wire Line + 2150 2750 2150 2850 +Wire Wire Line + 1700 1900 1700 4500 +Wire Wire Line + 2000 2750 2900 2750 +Connection ~ 3700 4500 +Wire Wire Line + 2400 2050 2400 2250 +Wire Wire Line + 1700 2350 2900 2350 +Connection ~ 2400 1350 +Wire Wire Line + 2400 1550 2400 1350 +Wire Wire Line + 1700 1350 4100 1350 +Connection ~ 3350 1350 +Wire Wire Line + 3350 1450 3350 1350 +Connection ~ 3450 1350 +Wire Wire Line + 3450 1450 3450 1350 +Connection ~ 3600 1350 +Wire Wire Line + 3600 1450 3600 1350 +Connection ~ 3700 1350 +Wire Wire Line + 3700 1450 3700 1350 +Connection ~ 3850 1350 +Wire Wire Line + 3850 1450 3850 1350 +Connection ~ 3950 1350 +Wire Wire Line + 3950 1450 3950 1350 +Wire Wire Line + 4100 1350 4100 1450 +Connection ~ 3800 4500 +Wire Wire Line + 3800 3850 3800 4500 +Wire Wire Line + 3700 3950 3700 3850 +Wire Wire Line + 4650 4500 4650 4550 +Wire Wire Line + 1700 4500 4650 4500 +Wire Wire Line + 3700 4450 3700 4500 +Wire Wire Line + 2300 5800 2700 5800 +Wire Wire Line + 650 5700 1050 5700 +Wire Wire Line + 2300 6000 2700 6000 +Wire Wire Line + 2300 5900 2700 5900 +$Comp +L D D3 +U 1 1 55FC41A1 +P 8450 3800 +F 0 "D3" H 8450 3900 50 0000 C CNN +F 1 "1N4148" H 8450 3700 50 0000 C CNN +F 2 "Diodes_SMD:SOD-323" H 8450 3800 60 0001 C CNN +F 3 "" H 8450 3800 60 0000 C CNN + 1 8450 3800 + 0 -1 -1 0 +$EndComp +Wire Wire Line + 8450 3500 8450 3650 +Connection ~ 8700 3500 +Wire Wire Line + 8450 3950 8450 4200 +Connection ~ 8450 4200 +Wire Wire Line + 8050 4200 8050 3950 +Wire Wire Line + 8050 950 8050 3750 +Connection ~ 8050 1450 +Wire Notes Line + 11150 500 11150 4550 +Wire Notes Line + 11150 500 7900 500 +Wire Notes Line + 7900 500 7900 4550 +$Comp +L +3V3 #PWR07 +U 1 1 55FCA236 +P 7600 6050 +F 0 "#PWR07" H 7600 5900 50 0001 C CNN +F 1 "+3V3" H 7600 6190 50 0000 C CNN +F 2 "" H 7600 6050 60 0000 C CNN +F 3 "" H 7600 6050 60 0000 C CNN + 1 7600 6050 + 1 0 0 -1 +$EndComp +$Comp +L R R10 +U 1 1 55FCA3EE +P 7300 6150 +F 0 "R10" V 7380 6150 50 0000 C CNN +F 1 "10K" V 7300 6150 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 7300 6150 60 0001 C CNN +F 3 "" H 7300 6150 60 0000 C CNN + 1 7300 6150 + 0 1 1 0 +$EndComp +$Comp +L R R11 +U 1 1 55FCA4BD +P 7300 6350 +F 0 "R11" V 7380 6350 50 0000 C CNN +F 1 "10K" V 7300 6350 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 7300 6350 60 0001 C CNN +F 3 "" H 7300 6350 60 0000 C CNN + 1 7300 6350 + 0 1 1 0 +$EndComp +Wire Wire Line + 7600 6050 7600 6350 +Connection ~ 7600 6150 +Text Label 6550 6150 0 60 ~ 0 +SDA +Wire Wire Line + 6550 6150 7050 6150 +Text Label 6550 6350 0 60 ~ 0 +SCL +Wire Wire Line + 6550 6350 7050 6350 +Wire Wire Line + 7600 6350 7550 6350 +Wire Wire Line + 7600 6150 7550 6150 +Wire Wire Line + 4600 2600 5000 2600 +Text Label 5000 2600 2 60 ~ 0 +VIBR +$Comp +L +3V3 #PWR08 +U 1 1 55FCD40F +P 7150 3250 +F 0 "#PWR08" H 7150 3100 50 0001 C CNN +F 1 "+3V3" H 7150 3390 50 0000 C CNN +F 2 "" H 7150 3250 60 0000 C CNN +F 3 "" H 7150 3250 60 0000 C CNN + 1 7150 3250 + 1 0 0 -1 +$EndComp +Text Label 6100 4000 0 60 ~ 0 +VIBR +$Comp +L GND #PWR09 +U 1 1 55FCDB21 +P 7150 4300 +F 0 "#PWR09" H 7150 4050 50 0001 C CNN +F 1 "GND" H 7150 4150 50 0000 C CNN +F 2 "" H 7150 4300 60 0000 C CNN +F 3 "" H 7150 4300 60 0000 C CNN + 1 7150 4300 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7150 3250 7150 3450 +Wire Wire Line + 7150 3550 7150 3800 +$Comp +L R R3 +U 1 1 55FCF00A +P 6550 4000 +F 0 "R3" V 6630 4000 50 0000 C CNN +F 1 "1K" V 6550 4000 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 6550 4000 60 0001 C CNN +F 3 "" H 6550 4000 60 0000 C CNN + 1 6550 4000 + 0 1 1 0 +$EndComp +$Comp +L CONN_01X02 P3 +U 1 1 55FD1063 +P 7400 3500 +F 0 "P3" H 7400 3650 50 0000 C CNN +F 1 "VIBR_MOTOR" V 7500 3500 50 0000 C CNN +F 2 "Pin_Headers:Pin_Header_Straight_1x02" H 7400 3500 60 0001 C CNN +F 3 "" H 7400 3500 60 0000 C CNN + 1 7400 3500 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7150 3450 7200 3450 +Wire Wire Line + 7200 3550 7150 3550 +Wire Wire Line + 4600 2350 5000 2350 +Wire Wire Line + 4600 2450 5000 2450 +Text Label 5000 2350 2 60 ~ 0 +BTN1 +Text Label 5000 2450 2 60 ~ 0 +BTN2 +$Comp +L BC849 Q1 +U 1 1 55FC47BF +P 7050 4000 +F 0 "Q1" H 7250 4075 50 0000 L CNN +F 1 "BC849" H 7250 4000 50 0000 L CNN +F 2 "TO_SOT_Packages_SMD:SOT-23" H 7250 3925 50 0001 L CIN +F 3 "" H 7050 4000 50 0000 L CNN + 1 7050 4000 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7150 4300 7150 4200 +Wire Wire Line + 6100 4000 6300 4000 +Wire Wire Line + 6800 4000 6850 4000 +$Comp +L SW_PUSH SW1 +U 1 1 55FC62E9 +P 7300 1200 +F 0 "SW1" H 7450 1310 50 0000 C CNN +F 1 "BUTTON_UP" H 7300 1120 50 0000 C CNN +F 2 "Project Libraries:ts015a" H 7300 1200 60 0001 C CNN +F 3 "" H 7300 1200 60 0000 C CNN + 1 7300 1200 + 1 0 0 -1 +$EndComp +$Comp +L SW_PUSH SW3 +U 1 1 55FC6544 +P 7300 2000 +F 0 "SW3" H 7450 2110 50 0000 C CNN +F 1 "BUTTON_CENTER" H 7300 1920 50 0000 C CNN +F 2 "Project Libraries:ts015a" H 7300 2000 60 0001 C CNN +F 3 "" H 7300 2000 60 0000 C CNN + 1 7300 2000 + 1 0 0 -1 +$EndComp +$Comp +L SW_PUSH SW2 +U 1 1 55FC65FF +P 7300 1500 +F 0 "SW2" H 7450 1610 50 0000 C CNN +F 1 "BUTTON_DOWN" H 7300 1420 50 0000 C CNN +F 2 "Project Libraries:ts015a" H 7300 1500 60 0001 C CNN +F 3 "" H 7300 1500 60 0000 C CNN + 1 7300 1500 + 1 0 0 -1 +$EndComp +Text Label 5650 1200 0 60 ~ 0 +BTN2 +Text Label 5650 1500 0 60 ~ 0 +BTN1 +$Comp +L D D1 +U 1 1 55FC9042 +P 6500 1750 +F 0 "D1" H 6500 1850 50 0000 C CNN +F 1 "1N4148" H 6500 1650 50 0000 C CNN +F 2 "Diodes_SMD:SOD-323" H 6500 1750 60 0001 C CNN +F 3 "" H 6500 1750 60 0000 C CNN + 1 6500 1750 + 0 -1 -1 0 +$EndComp +$Comp +L D D2 +U 1 1 55FC91A0 +P 6850 1750 +F 0 "D2" H 6850 1850 50 0000 C CNN +F 1 "1N4148" H 6850 1650 50 0000 C CNN +F 2 "Diodes_SMD:SOD-323" H 6850 1750 60 0001 C CNN +F 3 "" H 6850 1750 60 0000 C CNN + 1 6850 1750 + 0 -1 -1 0 +$EndComp +Wire Wire Line + 6500 1600 6500 1200 +Connection ~ 6500 1200 +Wire Wire Line + 6500 1900 6500 2000 +Wire Wire Line + 6500 2000 7000 2000 +$Comp +L R R12 +U 1 1 55FC9C6F +P 7750 2350 +F 0 "R12" V 7830 2350 50 0000 C CNN +F 1 "50" V 7750 2350 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 7750 2350 60 0001 C CNN +F 3 "" H 7750 2350 60 0000 C CNN + 1 7750 2350 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7750 1200 7750 2100 +Wire Wire Line + 7750 2000 7600 2000 +Wire Wire Line + 7750 1500 7600 1500 +Connection ~ 7750 2000 +Wire Wire Line + 7750 1200 7600 1200 +Connection ~ 7750 1500 +$Comp +L GND #PWR010 +U 1 1 55FCAB14 +P 7750 2700 +F 0 "#PWR010" H 7750 2450 50 0001 C CNN +F 1 "GND" H 7750 2550 50 0000 C CNN +F 2 "" H 7750 2700 60 0000 C CNN +F 3 "" H 7750 2700 60 0000 C CNN + 1 7750 2700 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7750 2700 7750 2600 +Wire Wire Line + 6850 1500 6850 1600 +Connection ~ 6850 1500 +Wire Wire Line + 6850 1900 6850 2000 +Connection ~ 6850 2000 +Text Notes 5600 900 0 30 ~ 0 +Button center = Button p + Button down\nSaves GPIO pins\nCompatible buttons: WS-TUS 434331045822, TS-015A +$Comp +L C_Small C17 +U 1 1 55FCCBEB +P 6300 2350 +F 0 "C17" H 6310 2420 50 0000 L CNN +F 1 "1u" H 6310 2270 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 6300 2350 60 0001 C CNN +F 3 "" H 6300 2350 60 0000 C CNN + 1 6300 2350 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C16 +U 1 1 55FCCDBC +P 6100 2350 +F 0 "C16" H 6110 2420 50 0000 L CNN +F 1 "1u" H 6110 2270 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 6100 2350 60 0001 C CNN +F 3 "" H 6100 2350 60 0000 C CNN + 1 6100 2350 + 1 0 0 -1 +$EndComp +Wire Wire Line + 6100 2650 7750 2650 +Wire Wire Line + 6300 2650 6300 2450 +Connection ~ 7750 2650 +Wire Wire Line + 6100 2650 6100 2450 +Connection ~ 6300 2650 +Wire Wire Line + 6300 2250 6300 1500 +Connection ~ 6300 1500 +Wire Wire Line + 6100 2250 6100 1200 +Connection ~ 6100 1200 +Wire Notes Line + 7850 2950 7850 500 +Text Notes 5550 700 0 120 ~ 0 +Side Buttons +Text Notes 5550 3200 0 120 ~ 0 +Vibration Motor +Wire Notes Line + 5500 3000 7850 3000 +Wire Notes Line + 500 500 500 4850 +Wire Notes Line + 500 500 5450 500 +Text Notes 600 750 0 120 ~ 0 +ESP8266EX Core System +Wire Notes Line + 6350 6500 7850 6500 +Wire Notes Line + 7850 6500 7850 5600 +Wire Notes Line + 7850 5600 6350 5600 +Wire Notes Line + 6350 5600 6350 6500 +Text Notes 6400 5800 0 120 ~ 0 +I²C Pullups +Wire Notes Line + 7900 4550 11150 4550 +Wire Notes Line + 7850 3000 7850 4550 +Wire Notes Line + 7850 4550 5500 4550 +Wire Notes Line + 5500 4550 5500 3000 +Text Notes 5550 4800 0 120 ~ 0 +Reset Interrupts +Wire Notes Line + 5500 4600 7850 4600 +Wire Notes Line + 7850 4600 7850 5550 +Wire Notes Line + 7850 5550 5500 5550 +Wire Notes Line + 5500 5550 5500 4600 +Wire Wire Line + 5650 1200 7000 1200 +Wire Wire Line + 7000 1500 5650 1500 +Wire Notes Line + 7850 2950 5500 2950 +Wire Notes Line + 5500 2950 5500 500 +Wire Notes Line + 5500 500 7850 500 +Wire Notes Line + 5450 500 5450 4850 +Wire Notes Line + 5450 4850 500 4850 +Text Notes 550 6800 0 120 ~ 0 +Acc., Gyro, Magnet Sensor +Text Notes 3700 6800 0 120 ~ 0 +Real Time Clock +Text Notes 950 5450 0 120 ~ 0 +USB, Power, LiPo +$Comp +L ER-OLED-SSD1306 DS1 +U 1 1 55FB110E +P 10600 2350 +F 0 "DS1" H 10800 700 60 0000 C CNN +F 1 "ER-OLED-SSD1306" H 10450 3950 60 0000 C CNN +F 2 "Project Libraries:er-oled-ssd1306" H 10500 3150 60 0001 C CNN +F 3 "" H 10500 3150 60 0000 C CNN + 1 10600 2350 + 1 0 0 -1 +$EndComp +Wire Wire Line + 10300 3350 10200 3350 +Connection ~ 10200 3350 +Wire Wire Line + 10300 3250 10200 3250 +Connection ~ 10200 3250 +Wire Wire Line + 10300 3150 10200 3150 +Connection ~ 10200 3150 +Wire Wire Line + 10300 3050 10200 3050 +Connection ~ 10200 3050 +Wire Wire Line + 10300 2950 10200 2950 +Connection ~ 10200 2950 +$Comp +L PWR_FLAG #FLG011 +U 1 1 55FD27DA +P 9950 3350 +F 0 "#FLG011" H 9950 3445 50 0001 C CNN +F 1 "PWR_FLAG" H 9950 3530 50 0000 C CNN +F 2 "" H 9950 3350 60 0000 C CNN +F 3 "" H 9950 3350 60 0000 C CNN + 1 9950 3350 + 1 0 0 -1 +$EndComp +Text Notes 8100 4400 0 59 ~ 0 +TODO: Remove D3, R13 to +3V3, not GND +$EndSCHEMATC diff --git a/board/v1/handgelenk.xml b/board/v1/handgelenk.xml new file mode 100644 index 0000000..8a73cb6 --- /dev/null +++ b/board/v1/handgelenk.xml @@ -0,0 +1,1264 @@ + + + + /home/florian/prgm/handgelenk/board/v1/handgelenk.sch + Fr 11 Mär 2016 10:04:17 CET + Eeschema 4.0.2-stable + + + + <company/> + <rev/> + <date/> + <source>handgelenk.sch</source> + <comment number="1" value=""/> + <comment number="2" value=""/> + <comment number="3" value=""/> + <comment number="4" value=""/> + </title_block> + </sheet> + <sheet number="2" name="/Power Management/" tstamps="/55CFAED1/"> + <title_block> + <title/> + <company/> + <rev/> + <date/> + <source>power.sch</source> + <comment number="1" value=""/> + <comment number="2" value=""/> + <comment number="3" value=""/> + <comment number="4" value=""/> + </title_block> + </sheet> + <sheet number="3" name="/MPU-9250/" tstamps="/55F844A4/"> + <title_block> + <title/> + <company/> + <rev/> + <date/> + <source>mpu9250.sch</source> + <comment number="1" value=""/> + <comment number="2" value=""/> + <comment number="3" value=""/> + <comment number="4" value=""/> + </title_block> + </sheet> + <sheet number="4" name="/RV-3029-C2/" tstamps="/55F97917/"> + <title_block> + <title/> + <company/> + <rev/> + <date/> + <source>rv3029c2.sch</source> + <comment number="1" value=""/> + <comment number="2" value=""/> + <comment number="3" value=""/> + <comment number="4" value=""/> + </title_block> + </sheet> + </design> + <components> + <comp ref="R2"> + <value>12K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F6E5F4</tstamp> + </comp> + <comp ref="C1"> + <value>100n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F6EFF8</tstamp> + </comp> + <comp ref="R1"> + <value>1K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F6F69B</tstamp> + </comp> + <comp ref="U1"> + <value>ESP8266EX</value> + <footprint>Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm</footprint> + <libsource lib="esp8266ex" part="ESP8266EX"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F70BBB</tstamp> + </comp> + <comp ref="X1"> + <value>26MHz</value> + <footprint>Project Libraries:crystal_2.5x2</footprint> + <libsource lib="device" part="CRYSTAL_SMD"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F71659</tstamp> + </comp> + <comp ref="C9"> + <value>10p</value> + <footprint>Capacitors_SMD:C_0402</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F73D4E</tstamp> + </comp> + <comp ref="C10"> + <value>10p</value> + <footprint>Capacitors_SMD:C_0402</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F73EE1</tstamp> + </comp> + <comp ref="C8"> + <value>5.6p</value> + <footprint>Capacitors_SMD:C_0402</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F80CB5</tstamp> + </comp> + <comp ref="ANT1"> + <value>AN9520</value> + <footprint>Project Libraries:an9520</footprint> + <libsource lib="pspice" part="INDUCTOR"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F8139E</tstamp> + </comp> + <comp ref="R5"> + <value>300</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F9485D</tstamp> + </comp> + <comp ref="C11"> + <value>100n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F956F5</tstamp> + </comp> + <comp ref="U5"> + <value>W25Q32BV</value> + <footprint>Project Libraries:wson8_5x6</footprint> + <libsource lib="w25q32bv" part="W25Q32BV"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F989A1</tstamp> + </comp> + <comp ref="R6"> + <value>200</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55F9BA0E</tstamp> + </comp> + <comp ref="R14"> + <value>390K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FB6136</tstamp> + </comp> + <comp ref="C21"> + <value>2u2</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FB8922</tstamp> + </comp> + <comp ref="C20"> + <value>4u7</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FB96CA</tstamp> + </comp> + <comp ref="C24"> + <value>100n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FB9F0B</tstamp> + </comp> + <comp ref="C19"> + <value>2u2</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FBAEDC</tstamp> + </comp> + <comp ref="C22"> + <value>1u</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FBD1F4</tstamp> + </comp> + <comp ref="C23"> + <value>1u</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FBD8B2</tstamp> + </comp> + <comp ref="C18"> + <value>1u</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FBFB19</tstamp> + </comp> + <comp ref="R13"> + <value>10K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC214E</tstamp> + </comp> + <comp ref="D3"> + <value>1N4148</value> + <footprint>Diodes_SMD:SOD-323</footprint> + <libsource lib="device" part="D"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC41A1</tstamp> + </comp> + <comp ref="R10"> + <value>10K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FCA3EE</tstamp> + </comp> + <comp ref="R11"> + <value>10K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FCA4BD</tstamp> + </comp> + <comp ref="R3"> + <value>1K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FCF00A</tstamp> + </comp> + <comp ref="P3"> + <value>VIBR_MOTOR</value> + <footprint>Pin_Headers:Pin_Header_Straight_1x02</footprint> + <libsource lib="conn" part="CONN_01X02"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FD1063</tstamp> + </comp> + <comp ref="Q1"> + <value>BC849</value> + <footprint>TO_SOT_Packages_SMD:SOT-23</footprint> + <libsource lib="transistors" part="BC849"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC47BF</tstamp> + </comp> + <comp ref="SW1"> + <value>BUTTON_UP</value> + <footprint>Project Libraries:ts015a</footprint> + <libsource lib="device" part="SW_PUSH"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC62E9</tstamp> + </comp> + <comp ref="SW3"> + <value>BUTTON_CENTER</value> + <footprint>Project Libraries:ts015a</footprint> + <libsource lib="device" part="SW_PUSH"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC6544</tstamp> + </comp> + <comp ref="SW2"> + <value>BUTTON_DOWN</value> + <footprint>Project Libraries:ts015a</footprint> + <libsource lib="device" part="SW_PUSH"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC65FF</tstamp> + </comp> + <comp ref="D1"> + <value>1N4148</value> + <footprint>Diodes_SMD:SOD-323</footprint> + <libsource lib="device" part="D"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC9042</tstamp> + </comp> + <comp ref="D2"> + <value>1N4148</value> + <footprint>Diodes_SMD:SOD-323</footprint> + <libsource lib="device" part="D"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC91A0</tstamp> + </comp> + <comp ref="R12"> + <value>50</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FC9C6F</tstamp> + </comp> + <comp ref="C17"> + <value>1u</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FCCBEB</tstamp> + </comp> + <comp ref="C16"> + <value>1u</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FCCDBC</tstamp> + </comp> + <comp ref="DS1"> + <value>ER-OLED-SSD1306</value> + <footprint>Project Libraries:er-oled-ssd1306</footprint> + <libsource lib="er-oled-ssd1306" part="ER-OLED-SSD1306"/> + <sheetpath names="/" tstamps="/"/> + <tstamp>55FB110E</tstamp> + </comp> + <comp ref="U3"> + <value>MCP73831</value> + <footprint>TO_SOT_Packages_SMD:SOT-23-5</footprint> + <libsource lib="mcp73831" part="MCP73831"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55CFAFFF</tstamp> + </comp> + <comp ref="R4"> + <value>3K3</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D05DFE</tstamp> + </comp> + <comp ref="C4"> + <value>4u7</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D05F2E</tstamp> + </comp> + <comp ref="P1"> + <value>USB_OTG</value> + <footprint>Connect:USB_Micro-B</footprint> + <libsource lib="conn" part="USB_OTG"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D06165</tstamp> + </comp> + <comp ref="P2"> + <value>LIPO</value> + <footprint>Pin_Headers:Pin_Header_Straight_1x02</footprint> + <libsource lib="conn" part="CONN_01X02"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D0747F</tstamp> + </comp> + <comp ref="C5"> + <value>4u7</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D07963</tstamp> + </comp> + <comp ref="C7"> + <value>10u</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D084FD</tstamp> + </comp> + <comp ref="C6"> + <value>100u</value> + <footprint>Capacitors_SMD:C_1206</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D088C0</tstamp> + </comp> + <comp ref="C2"> + <value>100n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D08232</tstamp> + </comp> + <comp ref="FB1"> + <value>BLM21PG 600</value> + <footprint>Capacitors_SMD:C_0805</footprint> + <libsource lib="device" part="FILTER"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D0855B</tstamp> + </comp> + <comp ref="C3"> + <value>10n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55D09B38</tstamp> + </comp> + <comp ref="R7"> + <value>330K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55F9A99C</tstamp> + </comp> + <comp ref="R8"> + <value>100K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55F9A9FE</tstamp> + </comp> + <comp ref="U4"> + <value>TLV70233-SOT-23</value> + <footprint>TO_SOT_Packages_SMD:SOT-23-5</footprint> + <libsource lib="tlv70233" part="TLV70233-SOT-23"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55FAB6D1</tstamp> + </comp> + <comp ref="U2"> + <value>FT232RQ</value> + <footprint>Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm</footprint> + <libsource lib="ft232rq" part="FT232RQ"/> + <sheetpath names="/Power Management/" tstamps="/55CFAED1/"/> + <tstamp>55FD3EAE</tstamp> + </comp> + <comp ref="U6"> + <value>MPU-9250</value> + <footprint>Housings_DFN_QFN:QFN-24-1EP_3x3mm_Pitch0.4mm</footprint> + <libsource lib="mpu9250" part="MPU-9250"/> + <sheetpath names="/MPU-9250/" tstamps="/55F844A4/"/> + <tstamp>55F84634</tstamp> + </comp> + <comp ref="C14"> + <value>100n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/MPU-9250/" tstamps="/55F844A4/"/> + <tstamp>55F84959</tstamp> + </comp> + <comp ref="C12"> + <value>100n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/MPU-9250/" tstamps="/55F844A4/"/> + <tstamp>55F83B4A</tstamp> + </comp> + <comp ref="C13"> + <value>10n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/MPU-9250/" tstamps="/55F844A4/"/> + <tstamp>55F83D26</tstamp> + </comp> + <comp ref="C15"> + <value>10n</value> + <footprint>Capacitors_SMD:C_0603</footprint> + <libsource lib="device" part="C_Small"/> + <sheetpath names="/RV-3029-C2/" tstamps="/55F97917/"/> + <tstamp>55F98261</tstamp> + </comp> + <comp ref="R9"> + <value>10K</value> + <footprint>Resistors_SMD:R_0603</footprint> + <libsource lib="pspice" part="R"/> + <sheetpath names="/RV-3029-C2/" tstamps="/55F97917/"/> + <tstamp>55F993EB</tstamp> + </comp> + <comp ref="U7"> + <value>RV-3029-C2</value> + <footprint>Project Libraries:rv3029</footprint> + <libsource lib="rv3029c2" part="RV-3029-C2"/> + <sheetpath names="/RV-3029-C2/" tstamps="/55F97917/"/> + <tstamp>55F9C7CF</tstamp> + </comp> + </components> + <libparts> + <libpart lib="transistors" part="BC850"> + <aliases> + <alias>BC849</alias> + </aliases> + <description>45V Vce, 0.1A Ic, Low noise, NPN, SOT-23</description> + <docs>http://www.fairchildsemi.com/ds/BC/BC850.pdf</docs> + <footprints> + <fp>SOT-23*</fp> + </footprints> + <fields> + <field name="Reference">Q</field> + <field name="Value">BC850</field> + <field name="Footprint">SOT-23</field> + </fields> + <pins> + <pin num="1" name="B" type="input"/> + <pin num="2" name="E" type="passive"/> + <pin num="3" name="C" type="passive"/> + </pins> + </libpart> + <libpart lib="conn" part="CONN_01X02"> + <description>Connector 01x02</description> + <footprints> + <fp>Pin_Header_Straight_1X02</fp> + <fp>Pin_Header_Angled_1X02</fp> + <fp>Socket_Strip_Straight_1X02</fp> + <fp>Socket_Strip_Angled_1X02</fp> + </footprints> + <fields> + <field name="Reference">P</field> + <field name="Value">CONN_01X02</field> + </fields> + <pins> + <pin num="1" name="P1" type="passive"/> + <pin num="2" name="P2" type="passive"/> + </pins> + </libpart> + <libpart lib="device" part="CRYSTAL_SMD"> + <fields> + <field name="Reference">X</field> + <field name="Value">CRYSTAL_SMD</field> + </fields> + <pins> + <pin num="1" name="1" type="passive"/> + <pin num="2" name="2" type="passive"/> + <pin num="3" name="case" type="passive"/> + </pins> + </libpart> + <libpart lib="device" part="C_Small"> + <description>Unpolarized capacitor</description> + <footprints> + <fp>C?</fp> + <fp>C_????_*</fp> + <fp>C_????</fp> + <fp>SMD*_c</fp> + <fp>Capacitor*</fp> + </footprints> + <fields> + <field name="Reference">C</field> + <field name="Value">C_Small</field> + </fields> + <pins> + <pin num="1" name="~" type="passive"/> + <pin num="2" name="~" type="passive"/> + </pins> + </libpart> + <libpart lib="device" part="D"> + <description>Diode</description> + <footprints> + <fp>Diode_*</fp> + <fp>D-Pak_TO252AA</fp> + <fp>*SingleDiode</fp> + <fp>*_Diode_*</fp> + <fp>*SingleDiode*</fp> + </footprints> + <fields> + <field name="Reference">D</field> + <field name="Value">D</field> + </fields> + <pins> + <pin num="1" name="K" type="passive"/> + <pin num="2" name="A" type="passive"/> + </pins> + </libpart> + <libpart lib="er-oled-ssd1306" part="ER-OLED-SSD1306"> + <fields> + <field name="Reference">DS</field> + <field name="Value">ER-OLED-SSD1306</field> + </fields> + <pins> + <pin num="1" name="GND" type="power_in"/> + <pin num="2" name="C2P" type="passive"/> + <pin num="3" name="C2N" type="passive"/> + <pin num="4" name="C1P" type="passive"/> + <pin num="5" name="C1N" type="passive"/> + <pin num="6" name="VBAT" type="power_in"/> + <pin num="7" name="~" type="NotConnected"/> + <pin num="8" name="VSS" type="power_in"/> + <pin num="9" name="VDD" type="power_in"/> + <pin num="10" name="BS0" type="input"/> + <pin num="11" name="BS1" type="input"/> + <pin num="12" name="BS2" type="input"/> + <pin num="13" name="~CS" type="input"/> + <pin num="14" name="~RES" type="input"/> + <pin num="15" name="D/~C" type="input"/> + <pin num="16" name="R/~W" type="input"/> + <pin num="17" name="E/~RD" type="input"/> + <pin num="18" name="D0" type="BiDi"/> + <pin num="19" name="D1" type="input"/> + <pin num="20" name="D2" type="input"/> + <pin num="21" name="D3" type="input"/> + <pin num="22" name="D4" type="input"/> + <pin num="23" name="D5" type="input"/> + <pin num="24" name="D6" type="input"/> + <pin num="25" name="D7" type="input"/> + <pin num="26" name="IREF" type="input"/> + <pin num="27" name="VCOMH" type="output"/> + <pin num="28" name="VCC" type="power_in"/> + <pin num="29" name="VLSS" type="power_in"/> + <pin num="30" name="GND" type="power_in"/> + </pins> + </libpart> + <libpart lib="esp8266ex" part="ESP8266EX"> + <fields> + <field name="Reference">U</field> + <field name="Value">ESP8266EX</field> + </fields> + <pins> + <pin num="1" name="VDDA" type="power_in"/> + <pin num="2" name="LNA" type="BiDi"/> + <pin num="3" name="VDD3P3" type="power_in"/> + <pin num="4" name="VDD3P3" type="power_in"/> + <pin num="5" name="VDD_RTC" type="power_out"/> + <pin num="6" name="TOUT" type="input"/> + <pin num="7" name="CHIP_EN" type="input"/> + <pin num="8" name="XPD_DCDC" type="BiDi"/> + <pin num="9" name="MTMS/GPIO14" type="BiDi"/> + <pin num="10" name="MTDI/GPIO12" type="BiDi"/> + <pin num="11" name="VDDPST" type="power_in"/> + <pin num="12" name="MTCK/GPIO13" type="BiDi"/> + <pin num="13" name="MTDO/GPIO15" type="BiDi"/> + <pin num="14" name="GPIO2" type="BiDi"/> + <pin num="15" name="GPIO0" type="BiDi"/> + <pin num="16" name="GPIO4/VD" type="BiDi"/> + <pin num="17" name="VDDPST" type="power_in"/> + <pin num="18" name="SD_DATA_2" type="BiDi"/> + <pin num="19" name="SD_DATA_3" type="BiDi"/> + <pin num="20" name="SD_CMD" type="BiDi"/> + <pin num="21" name="SD_CLK" type="BiDi"/> + <pin num="22" name="SD_DATA_0" type="BiDi"/> + <pin num="23" name="SD_DATA_1" type="BiDi"/> + <pin num="24" name="GPIO5" type="input"/> + <pin num="25" name="U0RXD" type="BiDi"/> + <pin num="26" name="U0TXD" type="BiDi"/> + <pin num="27" name="XTAL_OUT" type="BiDi"/> + <pin num="28" name="XTAL_IN" type="BiDi"/> + <pin num="29" name="VDDD" type="power_in"/> + <pin num="30" name="VDDA" type="power_in"/> + <pin num="31" name="RES12K" type="input"/> + <pin num="32" name="EXT_RSTB" type="input"/> + <pin num="33" name="GND" type="power_in"/> + </pins> + </libpart> + <libpart lib="device" part="FILTER"> + <description>Filtre EMI</description> + <fields> + <field name="Reference">FB</field> + <field name="Value">FILTER</field> + </fields> + <pins> + <pin num="1" name="1" type="passive"/> + <pin num="2" name="2" type="passive"/> + </pins> + </libpart> + <libpart lib="ft232rq" part="FT232RQ"> + <footprints> + <fp>QFN-32-1EP_5x5mm_Pitch0.5mm</fp> + </footprints> + <fields> + <field name="Reference">U</field> + <field name="Value">FT232RQ</field> + </fields> + <pins> + <pin num="1" name="VCCIO" type="power_in"/> + <pin num="2" name="RXD" type="input"/> + <pin num="3" name="~RI" type="input"/> + <pin num="4" name="GND" type="power_in"/> + <pin num="5" name="NC" type="NotConnected"/> + <pin num="6" name="~DSR" type="input"/> + <pin num="7" name="~DCD" type="input"/> + <pin num="8" name="~CTS" type="input"/> + <pin num="9" name="CBUS4" type="BiDi"/> + <pin num="10" name="CBUS2" type="BiDi"/> + <pin num="11" name="CBUS3" type="BiDi"/> + <pin num="12" name="NC" type="NotConnected"/> + <pin num="13" name="NC" type="NotConnected"/> + <pin num="14" name="USBDP" type="BiDi"/> + <pin num="15" name="USBDM" type="BiDi"/> + <pin num="16" name="3V3OUT" type="power_out"/> + <pin num="17" name="GND" type="power_in"/> + <pin num="18" name="~RESET" type="input"/> + <pin num="19" name="VCC" type="power_in"/> + <pin num="20" name="GND" type="power_in"/> + <pin num="21" name="CBUS1" type="BiDi"/> + <pin num="22" name="CBUS0" type="BiDi"/> + <pin num="23" name="NC" type="NotConnected"/> + <pin num="24" name="AGND" type="power_in"/> + <pin num="25" name="NC" type="NotConnected"/> + <pin num="26" name="TEST" type="power_in"/> + <pin num="27" name="OSCI" type="input"/> + <pin num="28" name="OSCO" type="output"/> + <pin num="29" name="NC" type="NotConnected"/> + <pin num="30" name="TXD" type="output"/> + <pin num="31" name="~DTR" type="output"/> + <pin num="32" name="~RTS" type="output"/> + <pin num="33" name="PAD" type="power_in"/> + </pins> + </libpart> + <libpart lib="pspice" part="INDUCTOR"> + <fields> + <field name="Reference">L</field> + <field name="Value">INDUCTOR</field> + </fields> + <pins> + <pin num="1" name="1" type="input"/> + <pin num="2" name="2" type="input"/> + </pins> + </libpart> + <libpart lib="mcp73831" part="MCP73831"> + <footprints> + <fp>SOT23-5</fp> + </footprints> + <fields> + <field name="Reference">U</field> + <field name="Value">MCP73831</field> + </fields> + <pins> + <pin num="1" name="STAT" type="3state"/> + <pin num="2" name="VSS" type="power_in"/> + <pin num="3" name="VBAT" type="power_out"/> + <pin num="4" name="VDD" type="power_in"/> + <pin num="5" name="PROG" type="input"/> + </pins> + </libpart> + <libpart lib="mpu9250" part="MPU-9250"> + <fields> + <field name="Reference">U</field> + <field name="Value">MPU-9250</field> + </fields> + <pins> + <pin num="1" name="RE_VDDIO" type="passive"/> + <pin num="7" name="AUX_CL" type="output"/> + <pin num="8" name="VDDIO" type="power_in"/> + <pin num="9" name="AD0" type="input"/> + <pin num="10" name="REGOUT" type="input"/> + <pin num="11" name="FSYNC" type="input"/> + <pin num="12" name="INT" type="output"/> + <pin num="13" name="VDD" type="power_in"/> + <pin num="18" name="GND" type="power_in"/> + <pin num="19" name="RE_NC" type="passive"/> + <pin num="20" name="RE_GND" type="passive"/> + <pin num="21" name="AUX_DA" type="BiDi"/> + <pin num="22" name="nCS" type="input"/> + <pin num="23" name="SCL" type="input"/> + <pin num="24" name="SDA" type="BiDi"/> + <pin num="25" name="PAD" type="power_in"/> + </pins> + </libpart> + <libpart lib="pspice" part="R"> + <description>Resistance</description> + <fields> + <field name="Reference">R</field> + <field name="Value">R</field> + </fields> + <pins> + <pin num="1" name="~" type="passive"/> + <pin num="2" name="~" type="passive"/> + </pins> + </libpart> + <libpart lib="rv3029c2" part="RV-3029-C2"> + <fields> + <field name="Reference">U</field> + <field name="Value">RV-3029-C2</field> + </fields> + <pins> + <pin num="1" name="Vdd" type="power_in"/> + <pin num="2" name="CLKOUT" type="output"/> + <pin num="4" name="SCL" type="input"/> + <pin num="5" name="SDA" type="BiDi"/> + <pin num="6" name="Vss" type="power_in"/> + <pin num="7" name="~INT" type="output"/> + <pin num="8" name="Vback" type="power_in"/> + <pin num="10" name="CLKOE" type="input"/> + </pins> + </libpart> + <libpart lib="device" part="SW_PUSH"> + <description>Button</description> + <fields> + <field name="Reference">SW</field> + <field name="Value">SW_PUSH</field> + </fields> + <pins> + <pin num="1" name="1" type="passive"/> + <pin num="2" name="2" type="passive"/> + </pins> + </libpart> + <libpart lib="tlv70233" part="TLV70233-SOT-23"> + <fields> + <field name="Reference">U</field> + <field name="Value">TLV70233-SOT-23</field> + </fields> + <pins> + <pin num="1" name="IN" type="power_in"/> + <pin num="2" name="GND" type="power_in"/> + <pin num="3" name="EN" type="input"/> + <pin num="5" name="OUT" type="power_out"/> + </pins> + </libpart> + <libpart lib="conn" part="USB_OTG"> + <description>micro/mini connector</description> + <footprints> + <fp>USB*</fp> + </footprints> + <fields> + <field name="Reference">P</field> + <field name="Value">USB_OTG</field> + </fields> + <pins> + <pin num="1" name="VCC" type="power_out"/> + <pin num="2" name="D-" type="passive"/> + <pin num="3" name="D+" type="passive"/> + <pin num="4" name="ID" type="power_in"/> + <pin num="5" name="GND" type="power_in"/> + <pin num="6" name="shield" type="passive"/> + </pins> + </libpart> + <libpart lib="w25q32bv" part="W25Q32BV"> + <fields> + <field name="Reference">U</field> + <field name="Value">W25Q32BV</field> + </fields> + <pins> + <pin num="1" name="~CS" type="input"/> + <pin num="2" name="DO" type="BiDi"/> + <pin num="3" name="~WP" type="BiDi"/> + <pin num="4" name="GND" type="power_in"/> + <pin num="5" name="DI" type="BiDi"/> + <pin num="6" name="CLK" type="input"/> + <pin num="7" name="~HOLD" type="BiDi"/> + <pin num="8" name="VCC" type="power_in"/> + </pins> + </libpart> + </libparts> + <libraries> + <library logical="device"> + <uri>/usr/share/kicad/library/device.lib</uri> + </library> + <library logical="mcp73831"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/mcp73831.lib</uri> + </library> + <library logical="er-oled-ssd1306"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/er-oled-ssd1306.lib</uri> + </library> + <library logical="ft232rq"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/ft232rq.lib</uri> + </library> + <library logical="mpu9250"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/mpu9250.lib</uri> + </library> + <library logical="w25q32bv"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/w25q32bv.lib</uri> + </library> + <library logical="tlv70233"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/tlv70233.lib</uri> + </library> + <library logical="rv3029c2"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/rv3029c2.lib</uri> + </library> + <library logical="esp8266ex"> + <uri>/home/florian/prgm/handgelenk/board/v1/lib/esp8266ex.lib</uri> + </library> + <library logical="pspice"> + <uri>/usr/share/kicad/library/pspice.lib</uri> + </library> + <library logical="conn"> + <uri>/usr/share/kicad/library/conn.lib</uri> + </library> + <library logical="transistors"> + <uri>/usr/share/kicad/library/transistors.lib</uri> + </library> + </libraries> + <nets> + <net code="1" name="Net-(R2-Pad1)"> + <node ref="R2" pin="1"/> + <node ref="U1" pin="31"/> + </net> + <net code="2" name="+3V3"> + <node ref="U1" pin="29"/> + <node ref="U1" pin="17"/> + <node ref="C12" pin="1"/> + <node ref="C1" pin="1"/> + <node ref="R1" pin="1"/> + <node ref="U1" pin="1"/> + <node ref="U1" pin="3"/> + <node ref="U4" pin="5"/> + <node ref="U6" pin="8"/> + <node ref="U6" pin="1"/> + <node ref="U6" pin="13"/> + <node ref="R9" pin="1"/> + <node ref="U1" pin="30"/> + <node ref="P3" pin="1"/> + <node ref="U1" pin="11"/> + <node ref="DS1" pin="6"/> + <node ref="DS1" pin="9"/> + <node ref="U7" pin="1"/> + <node ref="DS1" pin="11"/> + <node ref="C13" pin="1"/> + <node ref="R10" pin="1"/> + <node ref="R11" pin="1"/> + <node ref="C6" pin="1"/> + <node ref="U5" pin="8"/> + <node ref="C7" pin="1"/> + <node ref="U1" pin="4"/> + <node ref="C18" pin="1"/> + <node ref="C15" pin="1"/> + </net> + <net code="3" name="/VIBR"> + <node ref="R3" pin="2"/> + <node ref="U1" pin="10"/> + </net> + <net code="4" name="/MPU-9250/SCL"> + <node ref="U6" pin="23"/> + <node ref="U1" pin="9"/> + <node ref="DS1" pin="18"/> + <node ref="U7" pin="4"/> + <node ref="R11" pin="2"/> + </net> + <net code="5" name="/MPU-9250/SDA"> + <node ref="U1" pin="14"/> + <node ref="DS1" pin="19"/> + <node ref="DS1" pin="20"/> + <node ref="U7" pin="5"/> + <node ref="R10" pin="2"/> + <node ref="U6" pin="24"/> + </net> + <net code="6" name="Net-(C19-Pad1)"> + <node ref="R13" pin="1"/> + <node ref="DS1" pin="14"/> + <node ref="D3" pin="2"/> + <node ref="C19" pin="1"/> + </net> + <net code="7" name="/MPU-9250/INT"> + <node ref="C11" pin="1"/> + <node ref="R5" pin="1"/> + <node ref="U6" pin="12"/> + <node ref="U1" pin="32"/> + </net> + <net code="8" name="/DS_WAKE"> + <node ref="U1" pin="8"/> + <node ref="R5" pin="2"/> + </net> + <net code="9" name="/RV-3029-C2/INT"> + <node ref="R9" pin="2"/> + <node ref="U7" pin="7"/> + <node ref="C11" pin="2"/> + </net> + <net code="10" name="/Power Management/BATT_SENSE"> + <node ref="R7" pin="2"/> + <node ref="R8" pin="1"/> + <node ref="U1" pin="6"/> + </net> + <net code="11" name="/SD_CMD"> + <node ref="U1" pin="20"/> + <node ref="U5" pin="1"/> + </net> + <net code="12" name="/SD_D0"> + <node ref="U5" pin="2"/> + <node ref="U1" pin="22"/> + </net> + <net code="13" name="/SD_D1"> + <node ref="U5" pin="5"/> + <node ref="U1" pin="23"/> + </net> + <net code="14" name="/SD_D3"> + <node ref="U5" pin="3"/> + <node ref="U1" pin="19"/> + </net> + <net code="15" name="/Power Management/TXD"> + <node ref="U2" pin="30"/> + <node ref="U1" pin="25"/> + </net> + <net code="16" name="Net-(C9-Pad1)"> + <node ref="U1" pin="28"/> + <node ref="X1" pin="1"/> + <node ref="C9" pin="1"/> + </net> + <net code="17" name="Net-(C10-Pad1)"> + <node ref="X1" pin="2"/> + <node ref="C10" pin="1"/> + <node ref="U1" pin="27"/> + </net> + <net code="18" name="/Power Management/RXD"> + <node ref="U1" pin="26"/> + <node ref="U2" pin="2"/> + </net> + <net code="19" name="/Power Management/DTR"> + <node ref="U2" pin="31"/> + <node ref="U1" pin="15"/> + </net> + <net code="20" name="Net-(C8-Pad1)"> + <node ref="U1" pin="2"/> + <node ref="C8" pin="1"/> + </net> + <net code="21" name="Net-(ANT1-Pad1)"> + <node ref="C8" pin="2"/> + <node ref="ANT1" pin="1"/> + </net> + <net code="22" name="Net-(DS1-Pad7)"> + <node ref="DS1" pin="7"/> + </net> + <net code="23" name="Net-(C23-Pad1)"> + <node ref="DS1" pin="5"/> + <node ref="C23" pin="1"/> + </net> + <net code="24" name="Net-(C23-Pad2)"> + <node ref="C23" pin="2"/> + <node ref="DS1" pin="4"/> + </net> + <net code="25" name="Net-(C22-Pad1)"> + <node ref="DS1" pin="3"/> + <node ref="C22" pin="1"/> + </net> + <net code="26" name="Net-(C22-Pad2)"> + <node ref="C22" pin="2"/> + <node ref="DS1" pin="2"/> + </net> + <net code="27" name="Net-(C20-Pad1)"> + <node ref="C20" pin="1"/> + <node ref="DS1" pin="27"/> + </net> + <net code="28" name="/BTN2"> + <node ref="U1" pin="24"/> + <node ref="SW1" pin="1"/> + <node ref="C16" pin="1"/> + <node ref="D1" pin="2"/> + </net> + <net code="29" name="Net-(Q1-Pad1)"> + <node ref="R3" pin="1"/> + <node ref="Q1" pin="1"/> + </net> + <net code="30" name="GND"> + <node ref="U6" pin="20"/> + <node ref="U2" pin="33"/> + <node ref="U6" pin="9"/> + <node ref="U2" pin="24"/> + <node ref="U2" pin="26"/> + <node ref="U2" pin="17"/> + <node ref="R13" pin="2"/> + <node ref="C15" pin="2"/> + <node ref="U7" pin="10"/> + <node ref="U7" pin="8"/> + <node ref="U7" pin="6"/> + <node ref="R8" pin="2"/> + <node ref="C14" pin="2"/> + <node ref="C2" pin="2"/> + <node ref="C12" pin="2"/> + <node ref="C13" pin="2"/> + <node ref="C7" pin="2"/> + <node ref="C6" pin="2"/> + <node ref="C3" pin="2"/> + <node ref="U6" pin="25"/> + <node ref="U2" pin="20"/> + <node ref="U2" pin="4"/> + <node ref="U6" pin="11"/> + <node ref="U4" pin="2"/> + <node ref="R4" pin="2"/> + <node ref="P1" pin="6"/> + <node ref="P1" pin="5"/> + <node ref="C4" pin="2"/> + <node ref="U6" pin="18"/> + <node ref="U3" pin="2"/> + <node ref="C5" pin="2"/> + <node ref="P2" pin="1"/> + <node ref="C1" pin="2"/> + <node ref="R2" pin="2"/> + <node ref="U5" pin="4"/> + <node ref="X1" pin="3"/> + <node ref="C9" pin="2"/> + <node ref="C10" pin="2"/> + <node ref="R12" pin="2"/> + <node ref="Q1" pin="2"/> + <node ref="DS1" pin="22"/> + <node ref="DS1" pin="13"/> + <node ref="DS1" pin="23"/> + <node ref="DS1" pin="24"/> + <node ref="DS1" pin="15"/> + <node ref="DS1" pin="25"/> + <node ref="U1" pin="13"/> + <node ref="U1" pin="33"/> + <node ref="D3" pin="1"/> + <node ref="DS1" pin="10"/> + <node ref="DS1" pin="30"/> + <node ref="DS1" pin="21"/> + <node ref="DS1" pin="1"/> + <node ref="DS1" pin="8"/> + <node ref="DS1" pin="16"/> + <node ref="DS1" pin="17"/> + <node ref="C17" pin="2"/> + <node ref="DS1" pin="29"/> + <node ref="C19" pin="2"/> + <node ref="C16" pin="2"/> + <node ref="DS1" pin="12"/> + <node ref="C18" pin="2"/> + <node ref="C24" pin="2"/> + <node ref="R14" pin="2"/> + <node ref="C21" pin="2"/> + <node ref="C20" pin="2"/> + </net> + <net code="31" name="/BTN1"> + <node ref="D2" pin="2"/> + <node ref="SW2" pin="1"/> + <node ref="C17" pin="1"/> + <node ref="U1" pin="16"/> + </net> + <net code="32" name="Net-(P3-Pad2)"> + <node ref="Q1" pin="3"/> + <node ref="P3" pin="2"/> + </net> + <net code="33" name="Net-(D1-Pad1)"> + <node ref="D1" pin="1"/> + <node ref="D2" pin="1"/> + <node ref="SW3" pin="1"/> + </net> + <net code="34" name="Net-(R12-Pad1)"> + <node ref="R12" pin="1"/> + <node ref="SW2" pin="2"/> + <node ref="SW1" pin="2"/> + <node ref="SW3" pin="2"/> + </net> + <net code="35" name="Net-(ANT1-Pad2)"> + <node ref="ANT1" pin="2"/> + </net> + <net code="36" name="/Power Management/RTS"> + <node ref="U2" pin="32"/> + <node ref="U1" pin="7"/> + <node ref="R1" pin="2"/> + </net> + <net code="37" name="/SD_CLK"> + <node ref="U1" pin="21"/> + <node ref="R6" pin="2"/> + </net> + <net code="38" name="Net-(R6-Pad1)"> + <node ref="R6" pin="1"/> + <node ref="U5" pin="6"/> + </net> + <net code="39" name="Net-(U1-Pad5)"> + <node ref="U1" pin="5"/> + </net> + <net code="40" name="/Power Management/~CHARGE"> + <node ref="U3" pin="1"/> + <node ref="U1" pin="12"/> + </net> + <net code="41" name="/SD_D2"> + <node ref="U1" pin="18"/> + <node ref="U5" pin="7"/> + </net> + <net code="42" name="Net-(DS1-Pad26)"> + <node ref="DS1" pin="26"/> + <node ref="R14" pin="1"/> + </net> + <net code="43" name="Net-(C21-Pad1)"> + <node ref="C21" pin="1"/> + <node ref="C24" pin="1"/> + <node ref="DS1" pin="28"/> + </net> + <net code="44" name="+BATT"> + <node ref="C5" pin="1"/> + <node ref="U4" pin="3"/> + <node ref="P2" pin="2"/> + <node ref="U3" pin="3"/> + <node ref="R7" pin="1"/> + <node ref="U4" pin="1"/> + </net> + <net code="45" name="Net-(U2-Pad28)"> + <node ref="U2" pin="28"/> + </net> + <net code="46" name="Net-(U2-Pad27)"> + <node ref="U2" pin="27"/> + </net> + <net code="47" name="Net-(U2-Pad22)"> + <node ref="U2" pin="22"/> + </net> + <net code="48" name="/Power Management/USB_DM"> + <node ref="P1" pin="2"/> + <node ref="U2" pin="15"/> + </net> + <net code="49" name="/Power Management/USB_DP"> + <node ref="P1" pin="3"/> + <node ref="U2" pin="14"/> + </net> + <net code="50" name="Net-(U2-Pad21)"> + <node ref="U2" pin="21"/> + </net> + <net code="51" name="Net-(U2-Pad10)"> + <node ref="U2" pin="10"/> + </net> + <net code="52" name="Net-(U2-Pad11)"> + <node ref="U2" pin="11"/> + </net> + <net code="53" name="Net-(U2-Pad9)"> + <node ref="U2" pin="9"/> + </net> + <net code="54" name="Net-(U2-Pad18)"> + <node ref="U2" pin="18"/> + </net> + <net code="55" name="Net-(U2-Pad3)"> + <node ref="U2" pin="3"/> + </net> + <net code="56" name="Net-(U2-Pad7)"> + <node ref="U2" pin="7"/> + </net> + <net code="57" name="Net-(U2-Pad6)"> + <node ref="U2" pin="6"/> + </net> + <net code="58" name="Net-(U2-Pad8)"> + <node ref="U2" pin="8"/> + </net> + <net code="59" name="Net-(C2-Pad1)"> + <node ref="C2" pin="1"/> + <node ref="U2" pin="1"/> + <node ref="U2" pin="16"/> + </net> + <net code="60" name="Net-(U2-Pad12)"> + <node ref="U2" pin="12"/> + </net> + <net code="61" name="Net-(U2-Pad13)"> + <node ref="U2" pin="13"/> + </net> + <net code="62" name="Net-(U2-Pad23)"> + <node ref="U2" pin="23"/> + </net> + <net code="63" name="Net-(U2-Pad25)"> + <node ref="U2" pin="25"/> + </net> + <net code="64" name="+5V"> + <node ref="U2" pin="19"/> + <node ref="C4" pin="1"/> + <node ref="U3" pin="4"/> + <node ref="FB1" pin="2"/> + </net> + <net code="65" name="Net-(U2-Pad29)"> + <node ref="U2" pin="29"/> + </net> + <net code="66" name="Net-(U2-Pad5)"> + <node ref="U2" pin="5"/> + </net> + <net code="67" name="Net-(R4-Pad1)"> + <node ref="R4" pin="1"/> + <node ref="U3" pin="5"/> + </net> + <net code="68" name="Net-(P1-Pad4)"> + <node ref="P1" pin="4"/> + </net> + <net code="69" name="Net-(C3-Pad1)"> + <node ref="P1" pin="1"/> + <node ref="FB1" pin="1"/> + <node ref="C3" pin="1"/> + </net> + <net code="70" name="Net-(U6-Pad19)"> + <node ref="U6" pin="19"/> + </net> + <net code="71" name="Net-(U6-Pad21)"> + <node ref="U6" pin="21"/> + </net> + <net code="72" name="Net-(U6-Pad7)"> + <node ref="U6" pin="7"/> + </net> + <net code="73" name="Net-(U6-Pad22)"> + <node ref="U6" pin="22"/> + </net> + <net code="74" name="Net-(C14-Pad1)"> + <node ref="U6" pin="10"/> + <node ref="C14" pin="1"/> + </net> + <net code="75" name="Net-(U7-Pad2)"> + <node ref="U7" pin="2"/> + </net> + </nets> +</export> diff --git a/board/v1/lib/er-oled-ssd1306.dcm b/board/v1/lib/er-oled-ssd1306.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/er-oled-ssd1306.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/er-oled-ssd1306.lib b/board/v1/lib/er-oled-ssd1306.lib new file mode 100644 index 0000000..3ed2423 --- /dev/null +++ b/board/v1/lib/er-oled-ssd1306.lib @@ -0,0 +1,46 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# ER-OLED-SSD1306 +# +DEF ER-OLED-SSD1306 DS 0 40 Y Y 1 F N +F0 "DS" 200 -1650 60 H V C CNN +F1 "ER-OLED-SSD1306" 100 1600 60 H V C CNN +F2 "" -100 800 60 H V C CNN +F3 "" -100 800 60 H V C CNN +DRAW +S -100 1500 300 -1600 0 1 0 f +X GND 1 -300 1400 200 R 50 50 1 1 W +X C2P 2 -300 1300 200 R 50 50 1 1 P +X C2N 3 -300 1200 200 R 50 50 1 1 P +X C1P 4 -300 1100 200 R 50 50 1 1 P +X C1N 5 -300 1000 200 R 50 50 1 1 P +X VBAT 6 -300 900 200 R 50 50 1 1 W +X ~ 7 -300 800 200 R 50 50 1 1 N +X VSS 8 -300 700 200 R 50 50 1 1 W +X VDD 9 -300 600 200 R 50 50 1 1 W +X BS0 10 -300 500 200 R 50 50 1 1 I +X D2 20 -300 -500 200 R 50 50 1 1 I +X GND 30 -300 -1500 200 R 50 50 1 1 W +X BS1 11 -300 400 200 R 50 50 1 1 I +X D3 21 -300 -600 200 R 50 50 1 1 I +X BS2 12 -300 300 200 R 50 50 1 1 I +X D4 22 -300 -700 200 R 50 50 1 1 I +X ~CS 13 -300 200 200 R 50 50 1 1 I +X D5 23 -300 -800 200 R 50 50 1 1 I +X ~RES 14 -300 100 200 R 50 50 1 1 I +X D6 24 -300 -900 200 R 50 50 1 1 I +X D/~C 15 -300 0 200 R 50 50 1 1 I +X D7 25 -300 -1000 200 R 50 50 1 1 I +X R/~W 16 -300 -100 200 R 50 50 1 1 I +X IREF 26 -300 -1100 200 R 50 50 1 1 I +X E/~RD 17 -300 -200 200 R 50 50 1 1 I +X VCOMH 27 -300 -1200 200 R 50 50 1 1 O +X D0 18 -300 -300 200 R 50 50 1 1 B +X VCC 28 -300 -1300 200 R 50 50 1 1 W +X D1 19 -300 -400 200 R 50 50 1 1 I +X VLSS 29 -300 -1400 200 R 50 50 1 1 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/esp8266ex.dcm b/board/v1/lib/esp8266ex.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/esp8266ex.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/esp8266ex.lib b/board/v1/lib/esp8266ex.lib new file mode 100644 index 0000000..6cc0546 --- /dev/null +++ b/board/v1/lib/esp8266ex.lib @@ -0,0 +1,49 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# ESP8266EX +# +DEF ESP8266EX U 0 40 Y Y 1 F N +F0 "U" -500 950 60 H V C CNN +F1 "ESP8266EX" 400 -1000 60 H V C CNN +F2 "" -800 300 60 H V C CNN +F3 "" -800 300 60 H V C CNN +DRAW +S -550 900 550 -900 1 1 0 f +X VDDA 1 -400 1200 300 D 50 50 1 1 W +X LNA 2 -850 50 300 R 50 50 1 1 B +X VDD3P3 3 -150 1200 300 D 50 50 1 1 W +X VDD3P3 4 -50 1200 300 D 50 50 1 1 W +X VDD_RTC 5 -850 550 300 R 50 50 1 1 w +X TOUT 6 850 550 300 L 50 50 1 1 I +X CHIP_EN 7 -850 400 300 R 50 50 1 1 I +X XPD_DCDC 8 -850 -350 300 R 50 50 1 1 B +X MTMS/GPIO14 9 850 -150 300 L 50 50 1 1 B +X MTDI/GPIO12 10 850 50 300 L 50 50 1 1 B +X SD_CMD 20 850 -600 300 L 50 50 1 1 B +X VDDA 30 -300 1200 300 D 50 50 1 1 W +X VDDPST 11 100 1200 300 D 50 50 1 1 W +X SD_CLK 21 850 -500 300 L 50 50 1 1 B +X RES12K 31 -50 -1200 300 U 50 50 1 1 I +X MTCK/GPIO13 12 850 -50 300 L 50 50 1 1 B +X SD_DATA_0 22 850 -400 300 L 50 50 1 1 B +X EXT_RSTB 32 -850 -450 300 R 50 50 1 1 I +X MTDO/GPIO15 13 -850 300 300 R 50 50 1 1 B +X SD_DATA_1 23 850 -300 300 L 50 50 1 1 B +X GND 33 50 -1200 300 U 50 50 1 1 W +X GPIO2 14 850 400 300 L 50 50 1 1 B +X GPIO5 24 850 200 300 L 50 50 1 1 I +X GPIO0 15 -850 200 300 R 50 50 1 1 B +X U0RXD 25 -850 -600 300 R 50 50 1 1 B +X GPIO4/VD 16 850 300 300 L 50 50 1 1 B +X U0TXD 26 -850 -700 300 R 50 50 1 1 B +X VDDPST 17 200 1200 300 D 50 50 1 1 W +X XTAL_OUT 27 -850 -200 300 R 50 50 1 1 B +X SD_DATA_2 18 850 -800 300 L 50 50 1 1 B +X XTAL_IN 28 -850 -100 300 R 50 50 1 1 B +X SD_DATA_3 19 850 -700 300 L 50 50 1 1 B +X VDDD 29 350 1200 300 D 50 50 1 1 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/ft232rq.bck b/board/v1/lib/ft232rq.bck new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/ft232rq.bck @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/ft232rq.dcm b/board/v1/lib/ft232rq.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/ft232rq.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/ft232rq.lib b/board/v1/lib/ft232rq.lib new file mode 100644 index 0000000..5459a3a --- /dev/null +++ b/board/v1/lib/ft232rq.lib @@ -0,0 +1,52 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# FT232RQ +# +DEF FT232RQ U 0 40 Y Y 1 F N +F0 "U" -600 900 60 H V C CNN +F1 "FT232RQ" 550 -950 60 H V C CNN +F2 "" 550 -100 120 H V C CNN +F3 "" 550 -100 120 H V C CNN +$FPLIST + QFN-32-1EP_5x5mm_Pitch0.5mm +$ENDFPLIST +DRAW +S -650 -850 650 850 0 1 0 f +X VCCIO 1 -850 750 200 R 50 50 1 1 W +X RXD 2 850 600 200 L 50 50 1 1 I +X ~RI 3 850 -200 200 L 50 50 1 1 I +X GND 4 -50 -1050 200 U 50 50 1 1 W +X NC 5 -850 200 200 R 50 50 1 1 N +X ~DSR 6 850 50 200 L 50 50 1 1 I +X ~DCD 7 850 -100 200 L 50 50 1 1 I +X ~CTS 8 850 300 200 L 50 50 1 1 I +X CBUS4 9 850 -750 200 L 50 50 1 1 B +X CBUS2 10 850 -550 200 L 50 50 1 1 B +X GND 20 150 -1050 200 U 50 50 1 1 W +X TXD 30 850 750 200 L 50 50 1 1 O +X CBUS3 11 850 -650 200 L 50 50 1 1 B +X CBUS1 21 850 -450 200 L 50 50 1 1 B +X ~DTR 31 850 150 200 L 50 50 1 1 O +X NC 12 -850 100 200 R 50 50 1 1 N +X CBUS0 22 850 -350 200 L 50 50 1 1 B +X ~RTS 32 850 400 200 L 50 50 1 1 O +X NC 13 -850 0 200 R 50 50 1 1 N +X NC 23 -850 -450 200 R 50 50 1 1 N +X PAD 33 -250 -1050 200 U 50 50 1 1 W +X USBDP 14 -850 350 200 R 50 50 1 1 B +X AGND 24 -150 -1050 200 U 50 50 1 1 W +X USBDM 15 -850 450 200 R 50 50 1 1 B +X NC 25 -850 -100 200 R 50 50 1 1 N +X 3V3OUT 16 -850 -750 200 R 50 50 1 1 w +X TEST 26 250 -1050 200 U 50 50 1 1 W +X GND 17 50 -1050 200 U 50 50 1 1 W +X OSCI 27 -850 -550 200 R 50 50 1 1 I +X ~RESET 18 -850 -350 200 R 50 50 1 1 I +X OSCO 28 -850 -650 200 R 50 50 1 1 O +X VCC 19 -850 650 200 R 50 50 1 1 W +X NC 29 -850 -200 200 R 50 50 1 1 N +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/lt1129cst.dcm b/board/v1/lib/lt1129cst.dcm new file mode 100644 index 0000000..43b88e9 --- /dev/null +++ b/board/v1/lib/lt1129cst.dcm @@ -0,0 +1,9 @@ +EESchema-DOCLIB Version 2.0 +# +$CMP LT1129CST-3.3-Pad +D 700 mA Low Dropout Voltage Regulator, Fixed 3.3V, SOT-223 +K 700mA LDO Regulator 3.3V Positive +F http://cds.linear.com/docs/en/datasheet/112935ff.pdf +$ENDCMP +# +#End Doc Library diff --git a/board/v1/lib/lt1129cst.lib b/board/v1/lib/lt1129cst.lib new file mode 100644 index 0000000..1254931 --- /dev/null +++ b/board/v1/lib/lt1129cst.lib @@ -0,0 +1,23 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# LT1129CST-3.3-Pad +# +DEF LT1129CST-3.3-Pad U 0 40 Y Y 1 F N +F0 "U" -250 200 40 H V C CNN +F1 "LT1129CST-3.3-Pad" 150 200 40 H V C CNN +F2 "SOT-223" 0 100 35 H V C CIN +F3 "" 0 0 60 H V C CNN +$FPLIST + SOT* +$ENDFPLIST +DRAW +S -300 150 300 -200 0 1 10 f +X VIN 1 -450 50 150 R 40 40 1 1 W +X GND 2 -50 -300 100 U 40 40 1 1 W +X OUT 3 450 50 150 L 40 40 1 1 w +X PAD 4 50 -300 100 U 50 50 1 1 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/mcp73831.dcm b/board/v1/lib/mcp73831.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/mcp73831.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/mcp73831.lib b/board/v1/lib/mcp73831.lib new file mode 100644 index 0000000..a4feb37 --- /dev/null +++ b/board/v1/lib/mcp73831.lib @@ -0,0 +1,24 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# MCP73831 +# +DEF MCP73831 U 0 40 Y Y 1 F N +F0 "U" -250 200 50 H V C CNN +F1 "MCP73831" 100 -200 50 H V C CNN +F2 "" 0 0 60 H V C CNN +F3 "" 0 0 60 H V C CNN +$FPLIST + SOT23-5 +$ENDFPLIST +DRAW +S -300 150 300 -150 0 1 0 f +X STAT 1 -400 -100 100 R 40 40 1 1 T +X VSS 2 400 -100 100 L 40 40 1 1 W +X VBAT 3 400 100 100 L 40 40 1 1 w +X VDD 4 -400 100 100 R 40 40 1 1 W +X PROG 5 400 0 100 L 40 40 1 1 I +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/mpu9250.dcm b/board/v1/lib/mpu9250.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/mpu9250.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/mpu9250.lib b/board/v1/lib/mpu9250.lib new file mode 100644 index 0000000..6f791cb --- /dev/null +++ b/board/v1/lib/mpu9250.lib @@ -0,0 +1,32 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# MPU-9250 +# +DEF MPU-9250 U 0 40 Y Y 1 F N +F0 "U" -400 500 60 H V C CNN +F1 "MPU-9250" 750 -400 60 H V C CNN +F2 "" -300 250 60 H V C CNN +F3 "" -300 250 60 H V C CNN +DRAW +S -450 450 450 -450 0 1 0 f +X RE_VDDIO 1 -150 650 200 D 50 50 1 1 P +X AUX_CL 7 650 250 200 L 50 50 1 1 O +X VDDIO 8 -50 650 200 D 50 50 1 1 W +X AD0 9 -650 -200 200 R 50 50 1 1 I +X REGOUT 10 -200 -650 200 U 50 50 1 1 I +X RE_GND 20 50 -650 200 U 50 50 1 1 P +X FSYNC 11 -50 -650 200 U 50 50 1 1 I +X AUX_DA 21 650 150 200 L 50 50 1 1 B +X INT 12 650 -50 200 L 50 50 1 1 O +X nCS 22 -650 -50 200 R 50 50 1 1 I +X VDD 13 100 650 200 D 50 50 1 1 W +X SCL 23 -650 250 200 R 50 50 1 1 I +X SDA 24 -650 150 200 R 50 50 1 1 B +X PAD 25 250 -650 200 U 50 50 1 1 W +X GND 18 150 -650 200 U 50 50 1 1 W +X RE_NC 19 650 -200 200 L 50 50 1 1 P +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/rv3029c2.dcm b/board/v1/lib/rv3029c2.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/rv3029c2.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/rv3029c2.lib b/board/v1/lib/rv3029c2.lib new file mode 100644 index 0000000..f56f97f --- /dev/null +++ b/board/v1/lib/rv3029c2.lib @@ -0,0 +1,24 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# RV-3029-C2 +# +DEF RV-3029-C2 U 0 40 Y Y 1 F N +F0 "U" -350 350 60 H V C CNN +F1 "RV-3029-C2" 350 -350 60 H V C CNN +F2 "" -100 -50 60 H V C CNN +F3 "" -100 -50 60 H V C CNN +DRAW +S -400 250 400 -250 0 1 0 f +X Vdd 1 100 450 200 D 50 50 1 1 W +X CLKOUT 2 600 -150 200 L 50 50 1 1 O +X SCL 4 -600 150 200 R 50 50 1 1 I +X SDA 5 -600 50 200 R 50 50 1 1 B +X Vss 6 0 -450 200 U 50 50 1 1 W +X ~INT 7 600 150 200 L 50 50 1 1 O +X Vback 8 -100 450 200 D 50 50 1 1 W +X CLKOE 10 -600 -150 200 R 50 50 1 1 I +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/tlv70233.dcm b/board/v1/lib/tlv70233.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/tlv70233.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/tlv70233.lib b/board/v1/lib/tlv70233.lib new file mode 100644 index 0000000..9ab5d6f --- /dev/null +++ b/board/v1/lib/tlv70233.lib @@ -0,0 +1,20 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# TLV70233-SOT-23 +# +DEF TLV70233-SOT-23 U 0 40 Y Y 1 F N +F0 "U" -200 200 60 H V C CNN +F1 "TLV70233-SOT-23" 450 -200 60 H V C CNN +F2 "" 0 -150 60 H V C CNN +F3 "" 0 -150 60 H V C CNN +DRAW +S -250 -150 250 150 0 1 0 f +X IN 1 -450 50 200 R 50 50 1 1 W +X GND 2 0 -350 200 U 50 50 1 1 W +X EN 3 -450 -50 200 R 50 50 1 1 I +X OUT 5 450 50 200 L 50 50 1 1 w +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/lib/w25q32bv.bck b/board/v1/lib/w25q32bv.bck new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/w25q32bv.bck @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/w25q32bv.dcm b/board/v1/lib/w25q32bv.dcm new file mode 100644 index 0000000..5f3ed79 --- /dev/null +++ b/board/v1/lib/w25q32bv.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/board/v1/lib/w25q32bv.lib b/board/v1/lib/w25q32bv.lib new file mode 100644 index 0000000..a9518a0 --- /dev/null +++ b/board/v1/lib/w25q32bv.lib @@ -0,0 +1,24 @@ +EESchema-LIBRARY Version 2.3 +#encoding utf-8 +# +# W25Q32BV +# +DEF W25Q32BV U 0 40 Y Y 1 F N +F0 "U" -250 350 60 H V C CNN +F1 "W25Q32BV" 300 -350 60 H V C CNN +F2 "" 0 -200 60 H V C CNN +F3 "" 0 -200 60 H V C CNN +DRAW +S -300 300 300 -300 0 1 0 f +X ~CS 1 -500 50 200 R 50 50 1 1 I +X DO 2 500 -50 200 L 50 50 1 1 B +X ~WP 3 500 -200 200 L 50 50 1 1 B +X GND 4 0 -500 200 U 50 50 1 1 W +X DI 5 500 50 200 L 50 50 1 1 B +X CLK 6 -500 -50 200 R 50 50 1 1 I +X ~HOLD 7 500 200 200 L 50 50 1 1 B +X VCC 8 0 500 200 D 50 50 1 1 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/board/v1/mod/an9520.kicad_mod b/board/v1/mod/an9520.kicad_mod new file mode 100644 index 0000000..157a8e2 --- /dev/null +++ b/board/v1/mod/an9520.kicad_mod @@ -0,0 +1,12 @@ +(module AN9520 (layer F.Cu) (tedit 55F9B480) + (fp_text reference REF** (at 0 2) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value AN9520 (at 0 0) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 3.5 1) (end -3.5 1) (layer F.SilkS) (width 0.15)) + (fp_line (start -3.5 -1) (end 3.5 -1) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -4.75 0) (size 1.4 2) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at 4.75 0) (size 1.4 2) (layers F.Cu F.Paste F.Mask)) +) diff --git a/board/v1/mod/crystal_2.5x2.kicad_mod b/board/v1/mod/crystal_2.5x2.kicad_mod new file mode 100644 index 0000000..4079226 --- /dev/null +++ b/board/v1/mod/crystal_2.5x2.kicad_mod @@ -0,0 +1,16 @@ +(module crystal_2.5x2 (layer F.Cu) (tedit 55FD1E89) + (fp_text reference REF** (at 1 3.8) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value crystal_2.5x2 (at 0 -2) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 1.25 0.1) (end 1.25 -0.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.2 1) (end 0.2 1) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.25 0.1) (end -1.25 -0.1) (layer F.SilkS) (width 0.15)) + (fp_line (start -0.2 -1) (end 0.2 -1) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -0.85 0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at -0.85 -0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at 0.85 0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at 0.85 -0.65) (size 1.1 0.9) (layers F.Cu F.Paste F.Mask)) +) diff --git a/board/v1/mod/er-oled-ssd1306.kicad_mod b/board/v1/mod/er-oled-ssd1306.kicad_mod new file mode 100644 index 0000000..6af40e1 --- /dev/null +++ b/board/v1/mod/er-oled-ssd1306.kicad_mod @@ -0,0 +1,57 @@ +(module ER-OLED-SSD1306 (layer F.Cu) (tedit 55FC6ADD) + (fp_text reference REF** (at 0 2.4) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value ER-OLED-SSD1306 (at 0 -2.5) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 12.4 -0.7) (end -13.4 -0.7) (layer B.SilkS) (width 0.15)) + (fp_text user "1.1-1.2mm max. PCB thickness" (at 0 -7.9) (layer Dwgs.User) + (effects (font (size 0.45 0.45) (thickness 0.11))) + ) + (fp_line (start -13.4 14.8) (end 12.4 14.8) (layer B.SilkS) (width 0.15)) + (fp_line (start 12.4 -4.5) (end 12.4 14.8) (layer B.SilkS) (width 0.15)) + (fp_line (start -13.4 -4.5) (end -13.4 14.8) (layer B.SilkS) (width 0.15)) + (fp_line (start 6 -4.5) (end 12.4 -4.5) (layer B.SilkS) (width 0.15)) + (fp_line (start -6 -4.5) (end -13.4 -4.5) (layer B.SilkS) (width 0.15)) + (fp_line (start 6 -6.4) (end 6 -7.4) (layer F.SilkS) (width 0.15)) + (fp_line (start -6 -7.4) (end -6 -6.4) (layer F.SilkS) (width 0.15)) + (fp_line (start 6 -4.5) (end 6 -7.4) (layer B.SilkS) (width 0.15)) + (fp_line (start -6 -4.5) (end -6 -7.4) (layer B.SilkS) (width 0.15)) + (fp_line (start -6 -7.4) (end -5.1 -7.4) (layer F.SilkS) (width 0.15)) + (fp_line (start -5.1 -7.4) (end 6 -7.4) (layer F.SilkS) (width 0.15)) + (fp_line (start 11 -3.5) (end 6 -6.4) (layer F.SilkS) (width 0.15)) + (fp_line (start -6 -6.4) (end -11 -3.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 11 0.5) (end 11 -3.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -11 0.5) (end -11 -3.5) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -10.15 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at -9.45 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at -8.75 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 4 smd rect (at -8.05 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 5 smd rect (at -7.35 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 7 smd rect (at -5.95 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 8 smd rect (at -5.25 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 9 smd rect (at -4.55 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 10 smd rect (at -3.85 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 11 smd rect (at -3.15 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 12 smd rect (at -2.45 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 13 smd rect (at -1.75 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 14 smd rect (at -1.05 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 15 smd rect (at -0.35 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 16 smd rect (at 0.35 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 17 smd rect (at 1.05 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 18 smd rect (at 1.75 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 19 smd rect (at 2.45 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 20 smd rect (at 3.15 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 21 smd rect (at 3.85 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 22 smd rect (at 4.55 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 23 smd rect (at 5.25 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 24 smd rect (at 5.95 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 25 smd rect (at 6.65 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 26 smd rect (at 7.35 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 27 smd rect (at 8.05 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 28 smd rect (at 8.75 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 29 smd rect (at 9.45 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 30 smd rect (at 10.15 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) + (pad 6 smd rect (at -6.65 0) (size 0.4 3) (layers F.Cu F.Paste F.Mask)) +) diff --git a/board/v1/mod/rv3029.kicad_mod b/board/v1/mod/rv3029.kicad_mod new file mode 100644 index 0000000..e3a9ca1 --- /dev/null +++ b/board/v1/mod/rv3029.kicad_mod @@ -0,0 +1,24 @@ +(module RV-3029 (layer F.Cu) (tedit 55F9C351) + (fp_text reference REF** (at 4 0 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value RV-3029 (at -4 0 90) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 3 1.5) (end 2.5 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 3 -1.5) (end 3 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.5 -1.5) (end 3 -1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -3 1.5) (end -2.5 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -3 -1.5) (end -3 1.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 -1.5) (end -3 -1.5) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2 1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at -1 1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at 0 1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 4 smd rect (at 1 1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 5 smd rect (at 2 1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 6 smd rect (at 2 -1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 7 smd rect (at 1 -1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 8 smd rect (at 0 -1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 9 smd rect (at -1 -1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) + (pad 10 smd rect (at -2 -1.55) (size 0.6 0.9) (layers F.Cu F.Paste F.Mask)) +) diff --git a/board/v1/mod/ts015a.kicad_mod b/board/v1/mod/ts015a.kicad_mod new file mode 100644 index 0000000..54e20a9 --- /dev/null +++ b/board/v1/mod/ts015a.kicad_mod @@ -0,0 +1,19 @@ +(module ts015a (layer F.Cu) (tedit 55FC44C4) + (fp_text reference REF** (at 0 0) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value ts015a (at 0 -3.8) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start -1.3 -1.8) (end -1.3 -2.9) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.3 -1.8) (end 1.3 -2.9) (layer F.SilkS) (width 0.15)) + (fp_line (start -1.3 -2.9) (end 1.3 -2.9) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.3 -1.8) (end 2.3 -1.8) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.3 1.8) (end 2.3 -1.8) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.3 1.8) (end -2.3 -1.8) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.3 1.8) (end 2.3 1.8) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.8 -0.85) (size 1.2 1) (layers F.Cu F.Paste F.Mask)) + (pad 1 smd rect (at 2.8 -0.85) (size 1.2 1) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at -2.8 0.85) (size 1.2 1) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at 2.8 0.85) (size 1.2 1) (layers F.Cu F.Paste F.Mask)) +) diff --git a/board/v1/mod/wifilogo.kicad_mod b/board/v1/mod/wifilogo.kicad_mod new file mode 100644 index 0000000..1f4220a --- /dev/null +++ b/board/v1/mod/wifilogo.kicad_mod @@ -0,0 +1,109 @@ +(module LOGO (layer F.Cu) + (at 0 0) + (fp_text reference "G***" (at 0 0) (layer F.SilkS) hide + (effects (font (thickness 0.3))) + ) + (fp_text value "LOGO" (at 0.75 0) (layer F.SilkS) hide + (effects (font (thickness 0.3))) + ) + (fp_poly (pts (xy 0.038917 -1.485993) (xy 0.136323 -1.479296) (xy 0.231400 -1.466279) (xy 0.325018 -1.446787) (xy 0.418047 -1.420667) (xy 0.511356 -1.387763) (xy 0.526143 -1.381949) (xy 0.607126 -1.346625) + (xy 0.687969 -1.305470) (xy 0.767683 -1.259173) (xy 0.845284 -1.208422) (xy 0.919785 -1.153906) (xy 0.990200 -1.096313) (xy 1.055543 -1.036333) (xy 1.114827 -0.974654) (xy 1.123600 -0.964769) + (xy 1.155061 -0.928914) (xy 1.337241 -0.928914) (xy 1.382403 -0.928882) (xy 1.421055 -0.928742) (xy 1.453941 -0.928433) (xy 1.481808 -0.927892) (xy 1.505401 -0.927058) (xy 1.525467 -0.925867) + (xy 1.542752 -0.924258) (xy 1.558000 -0.922168) (xy 1.571959 -0.919535) (xy 1.585374 -0.916296) (xy 1.598991 -0.912390) (xy 1.613556 -0.907754) (xy 1.621288 -0.905189) (xy 1.661207 -0.889746) + (xy 1.703678 -0.869560) (xy 1.746898 -0.845692) (xy 1.789065 -0.819205) (xy 1.828375 -0.791161) (xy 1.862402 -0.763179) (xy 1.901130 -0.725171) (xy 1.938576 -0.681854) (xy 1.973974 -0.634477) + (xy 2.006561 -0.584290) (xy 2.035573 -0.532540) (xy 2.060245 -0.480477) (xy 2.079815 -0.429350) (xy 2.091650 -0.388455) (xy 2.094412 -0.376708) (xy 2.096859 -0.365301) (xy 2.099009 -0.353746) + (xy 2.100877 -0.341555) (xy 2.102480 -0.328241) (xy 2.103836 -0.313318) (xy 2.104959 -0.296298) (xy 2.105868 -0.276693) (xy 2.106579 -0.254016) (xy 2.107108 -0.227780) (xy 2.107472 -0.197498) + (xy 2.107688 -0.162683) (xy 2.107771 -0.122847) (xy 2.107740 -0.077502) (xy 2.107610 -0.026162) (xy 2.107398 0.031660) (xy 2.107241 0.068943) (xy 2.106977 0.127210) (xy 2.106714 0.178672) + (xy 2.106443 0.223784) (xy 2.106154 0.262996) (xy 2.105839 0.296764) (xy 2.105488 0.325539) (xy 2.105093 0.349773) (xy 2.104644 0.369922) (xy 2.104133 0.386436) (xy 2.103549 0.399769) + (xy 2.102885 0.410374) (xy 2.102131 0.418703) (xy 2.101277 0.425211) (xy 2.100316 0.430348) (xy 2.099956 0.431890) (xy 2.090511 0.465394) (xy 2.078792 0.497449) (xy 2.064302 0.528853) + (xy 2.046545 0.560404) (xy 2.025023 0.592899) (xy 1.999239 0.627136) (xy 1.968697 0.663912) (xy 1.932899 0.704026) (xy 1.925134 0.712444) (xy 1.875560 0.761739) (xy 1.824350 0.804205) + (xy 1.770893 0.840195) (xy 1.714577 0.870067) (xy 1.654793 0.894173) (xy 1.590931 0.912868) (xy 1.573238 0.916963) (xy 1.563891 0.918994) (xy 1.555394 0.920722) (xy 1.547079 0.922179) + (xy 1.538280 0.923395) (xy 1.528327 0.924400) (xy 1.516553 0.925226) (xy 1.502291 0.925904) (xy 1.484872 0.926465) (xy 1.463629 0.926938) (xy 1.437894 0.927356) (xy 1.407000 0.927749) + (xy 1.370278 0.928148) (xy 1.327061 0.928584) (xy 1.320424 0.928650) (xy 1.111405 0.930728) (xy 1.092924 0.953762) (xy 1.031812 1.024560) (xy 0.964702 1.092371) (xy 0.892488 1.156474) + (xy 0.816064 1.216150) (xy 0.736327 1.270679) (xy 0.654170 1.319340) (xy 0.609295 1.342835) (xy 0.527232 1.381088) (xy 0.446332 1.413087) (xy 0.365051 1.439309) (xy 0.281846 1.460235) + (xy 0.195174 1.476342) (xy 0.165100 1.480744) (xy 0.142605 1.483224) (xy 0.114476 1.485384) (xy 0.082193 1.487188) (xy 0.047234 1.488603) (xy 0.011078 1.489594) (xy -0.024797 1.490127) + (xy -0.058910 1.490169) (xy -0.089784 1.489684) (xy -0.115940 1.488640) (xy -0.130629 1.487560) (xy -0.231476 1.474484) (xy -0.329938 1.454557) (xy -0.425942 1.427809) (xy -0.519413 1.394268) + (xy -0.610277 1.353965) (xy -0.698459 1.306927) (xy -0.783886 1.253185) (xy -0.850504 1.205146) (xy -0.903885 1.162055) (xy -0.956706 1.115009) (xy -1.007315 1.065606) (xy -1.054063 1.015447) + (xy -1.089569 0.973364) (xy -1.122239 0.932543) (xy -1.314955 0.932528) (xy -1.361324 0.932492) (xy -1.401164 0.932357) (xy -1.435202 0.932072) (xy -1.464166 0.931587) (xy -1.488783 0.930851) + (xy -1.509782 0.929813) (xy -1.527890 0.928423) (xy -1.543834 0.926628) (xy -1.558343 0.924380) (xy -1.572143 0.921626) (xy -1.585963 0.918317) (xy -1.600530 0.914401) (xy -1.608999 0.912007) + (xy -1.674042 0.889681) (xy -1.736684 0.860568) (xy -1.796988 0.824632) (xy -1.842553 0.791028) (xy -0.178339 0.791028) (xy 0.568509 0.790960) (xy 0.643160 0.790936) (xy 0.716746 0.790879) + (xy 0.788867 0.790792) (xy 0.859120 0.790675) (xy 0.927103 0.790530) (xy 0.992416 0.790360) (xy 1.054657 0.790165) (xy 1.113423 0.789947) (xy 1.168314 0.789708) (xy 1.218928 0.789450) + (xy 1.264863 0.789174) (xy 1.305717 0.788882) (xy 1.341089 0.788576) (xy 1.370578 0.788257) (xy 1.393781 0.787927) (xy 1.410297 0.787588) (xy 1.415143 0.787443) (xy 1.456004 0.785929) + (xy 1.490579 0.784292) (xy 1.519838 0.782298) (xy 1.544751 0.779711) (xy 1.566289 0.776294) (xy 1.585420 0.771814) (xy 1.603116 0.766033) (xy 1.620346 0.758718) (xy 1.638081 0.749631) + (xy 1.657291 0.738538) (xy 1.678945 0.725203) (xy 1.683639 0.722257) (xy 1.739753 0.683286) (xy 1.790315 0.640558) (xy 1.835069 0.594379) (xy 1.873761 0.545059) (xy 1.906135 0.492905) + (xy 1.931938 0.438226) (xy 1.942719 0.408760) (xy 1.945835 0.398837) (xy 1.948582 0.388741) (xy 1.950982 0.377972) (xy 1.953060 0.366028) (xy 1.954838 0.352407) (xy 1.956338 0.336609) + (xy 1.957584 0.318133) (xy 1.958598 0.296477) (xy 1.959404 0.271140) (xy 1.960024 0.241620) (xy 1.960481 0.207417) (xy 1.960798 0.168028) (xy 1.960998 0.122954) (xy 1.961104 0.071693) + (xy 1.961139 0.013742) (xy 1.961140 0.005443) (xy 1.961092 -0.057144) (xy 1.960946 -0.112704) (xy 1.960698 -0.161468) (xy 1.960346 -0.203666) (xy 1.959887 -0.239529) (xy 1.959317 -0.269286) + (xy 1.958633 -0.293168) (xy 1.957833 -0.311405) (xy 1.956913 -0.324228) (xy 1.956751 -0.325831) (xy 1.948137 -0.374158) (xy 1.932860 -0.423021) (xy 1.911398 -0.471673) (xy 1.884229 -0.519365) + (xy 1.851833 -0.565349) (xy 1.814689 -0.608878) (xy 1.773274 -0.649204) (xy 1.728069 -0.685577) (xy 1.725157 -0.687682) (xy 1.704870 -0.701028) (xy 1.680687 -0.715007) (xy 1.654415 -0.728737) + (xy 1.627860 -0.741337) (xy 1.602828 -0.751926) (xy 1.581125 -0.759623) (xy 1.572986 -0.761894) (xy 1.563956 -0.764062) (xy 1.555064 -0.766021) (xy 1.545908 -0.767782) (xy 1.536085 -0.769357) + (xy 1.525194 -0.770758) (xy 1.512832 -0.771999) (xy 1.498596 -0.773090) (xy 1.482086 -0.774044) (xy 1.462898 -0.774875) (xy 1.440631 -0.775593) (xy 1.414882 -0.776210) (xy 1.385250 -0.776741) + (xy 1.351332 -0.777195) (xy 1.312726 -0.777587) (xy 1.269030 -0.777927) (xy 1.219841 -0.778229) (xy 1.164759 -0.778504) (xy 1.103380 -0.778764) (xy 1.035302 -0.779023) (xy 1.006928 -0.779125) + (xy 0.542471 -0.780791) (xy 0.502061 -0.767718) (xy 0.450904 -0.748419) (xy 0.403064 -0.724469) (xy 0.357384 -0.695161) (xy 0.312708 -0.659784) (xy 0.285623 -0.635084) (xy 0.249078 -0.598047) + (xy 0.215442 -0.559771) (xy 0.185242 -0.521043) (xy 0.159001 -0.482649) (xy 0.137247 -0.445376) (xy 0.120503 -0.410009) (xy 0.109296 -0.377335) (xy 0.106997 -0.367730) (xy 0.104950 -0.356340) + (xy 0.103085 -0.342162) (xy 0.101384 -0.324801) (xy 0.099834 -0.303858) (xy 0.098420 -0.278937) (xy 0.097125 -0.249641) (xy 0.095936 -0.215573) (xy 0.094837 -0.176336) (xy 0.093813 -0.131533) + (xy 0.092849 -0.080768) (xy 0.091930 -0.023642) (xy 0.091040 0.040240) (xy 0.090811 0.058057) (xy 0.090094 0.113362) (xy 0.089403 0.161967) (xy 0.088698 0.204426) (xy 0.087935 0.241296) + (xy 0.087074 0.273132) (xy 0.086074 0.300491) (xy 0.084891 0.323927) (xy 0.083485 0.343997) (xy 0.081814 0.361257) (xy 0.079836 0.376262) (xy 0.077509 0.389568) (xy 0.074792 0.401732) + (xy 0.071644 0.413308) (xy 0.068022 0.424852) (xy 0.063884 0.436921) (xy 0.061998 0.442240) (xy 0.042637 0.491538) (xy 0.020531 0.538052) (xy -0.005017 0.582855) (xy -0.034699 0.627024) + (xy -0.069210 0.671631) (xy -0.109244 0.717753) (xy -0.130996 0.741136) (xy -0.178339 0.791028) (xy -1.842553 0.791028) (xy -1.855018 0.781836) (xy -1.902542 0.740095) (xy -1.954413 0.686415) + (xy -1.999627 0.629855) (xy -2.038192 0.570396) (xy -2.070119 0.508022) (xy -2.095419 0.442714) (xy -2.112806 0.380218) (xy -2.114153 0.374160) (xy -2.115336 0.368158) (xy -2.116368 0.361714) + (xy -2.117262 0.354331) (xy -2.118032 0.345511) (xy -2.118688 0.334758) (xy -2.119245 0.321575) (xy -2.119715 0.305464) (xy -2.120111 0.285927) (xy -2.120446 0.262469) (xy -2.120731 0.234592) + (xy -2.120981 0.201798) (xy -2.121207 0.163590) (xy -2.121422 0.119471) (xy -2.121640 0.068945) (xy -2.121802 0.029028) (xy -2.122025 -0.027630) (xy -2.122197 -0.077554) (xy -2.122298 -0.121266) + (xy -2.122311 -0.159288) (xy -2.122217 -0.192143) (xy -2.121997 -0.220353) (xy -2.121632 -0.244441) (xy -2.121103 -0.264929) (xy -2.120393 -0.282340) (xy -2.119481 -0.297196) (xy -2.118350 -0.310020) + (xy -2.116980 -0.321333) (xy -2.115354 -0.331659) (xy -2.113451 -0.341521) (xy -2.111254 -0.351439) (xy -2.108744 -0.361938) (xy -2.107631 -0.366486) (xy -2.089738 -0.425324) (xy -2.071766 -0.468333) + (xy -1.744449 -0.468333) (xy -1.742278 -0.456050) (xy -1.741964 -0.454600) (xy -1.737998 -0.436656) (xy -1.732665 -0.412829) (xy -1.726100 -0.383706) (xy -1.718437 -0.349873) (xy -1.709812 -0.311918) + (xy -1.700360 -0.270428) (xy -1.690216 -0.225990) (xy -1.679514 -0.179192) (xy -1.668390 -0.130621) (xy -1.656978 -0.080863) (xy -1.645415 -0.030506) (xy -1.633834 0.019863) (xy -1.622371 0.069657) + (xy -1.611161 0.118288) (xy -1.600339 0.165169) (xy -1.590039 0.209714) (xy -1.580397 0.251335) (xy -1.571548 0.289445) (xy -1.563627 0.323457) (xy -1.556768 0.352783) (xy -1.551108 0.376837) + (xy -1.546780 0.395031) (xy -1.543920 0.406778) (xy -1.543776 0.407351) (xy -1.540221 0.420590) (xy -1.536572 0.428515) (xy -1.530936 0.432841) (xy -1.521423 0.435284) (xy -1.511300 0.436814) + (xy -1.504209 0.437256) (xy -1.491511 0.437474) (xy -1.474329 0.437492) (xy -1.453786 0.437336) (xy -1.431006 0.437028) (xy -1.407111 0.436592) (xy -1.383225 0.436053) (xy -1.360470 0.435435) + (xy -1.339970 0.434761) (xy -1.322848 0.434056) (xy -1.310226 0.433344) (xy -1.303228 0.432648) (xy -1.302211 0.432344) (xy -1.301041 0.428367) (xy -1.298681 0.418052) (xy -1.295294 0.402187) + (xy -1.291043 0.381563) (xy -1.286089 0.356972) (xy -1.280596 0.329203) (xy -1.274727 0.299047) (xy -1.273737 0.293914) (xy -1.264092 0.244010) (xy -1.254702 0.195723) (xy -1.245668 0.149570) + (xy -1.237095 0.106064) (xy -1.229086 0.065722) (xy -1.221744 0.029057) (xy -1.215173 -0.003415) (xy -1.209476 -0.031179) (xy -1.204758 -0.053721) (xy -1.201120 -0.070525) (xy -1.198667 -0.081077) + (xy -1.197709 -0.084470) (xy -1.195627 -0.088810) (xy -1.193873 -0.087869) (xy -1.191596 -0.080848) (xy -1.190837 -0.078014) (xy -1.189508 -0.072024) (xy -1.186940 -0.059535) (xy -1.183259 -0.041178) + (xy -1.178586 -0.017583) (xy -1.173046 0.010620) (xy -1.166763 0.042801) (xy -1.159859 0.078330) (xy -1.152459 0.116576) (xy -1.144686 0.156910) (xy -1.141020 0.175986) (xy -1.133131 0.216890) + (xy -1.125546 0.255855) (xy -1.118391 0.292270) (xy -1.111787 0.325523) (xy -1.105858 0.355002) (xy -1.100729 0.380094) (xy -1.096522 0.400188) (xy -1.093361 0.414672) (xy -1.091370 0.422933) + (xy -1.090863 0.424513) (xy -1.083418 0.432753) (xy -1.075837 0.435877) (xy -1.068086 0.436724) (xy -1.054382 0.437404) (xy -1.035975 0.437917) (xy -1.014115 0.438264) (xy -0.990053 0.438447) + (xy -0.965040 0.438467) (xy -0.940324 0.438325) (xy -0.917156 0.438023) (xy -0.896787 0.437561) (xy -0.880467 0.436942) (xy -0.869446 0.436166) (xy -0.866034 0.435659) (xy -0.856768 0.433213) + (xy -0.851053 0.431153) (xy -0.850485 0.430779) (xy -0.849246 0.426883) (xy -0.846521 0.416446) (xy -0.842426 0.399980) (xy -0.837080 0.377995) (xy -0.830602 0.351005) (xy -0.823110 0.319520) + (xy -0.814722 0.284053) (xy -0.805557 0.245114) (xy -0.795732 0.203215) (xy -0.785367 0.158868) (xy -0.774579 0.112585) (xy -0.763487 0.064877) (xy -0.752209 0.016256) (xy -0.740864 -0.032768) + (xy -0.729569 -0.081681) (xy -0.718444 -0.129972) (xy -0.707606 -0.177131) (xy -0.697173 -0.222645) (xy -0.695813 -0.228600) (xy -0.511629 -0.228600) (xy -0.511629 0.439057) (xy -0.286657 0.439057) + (xy -0.286657 -0.228600) (xy -0.511629 -0.228600) (xy -0.695813 -0.228600) (xy -0.687265 -0.266002) (xy -0.677999 -0.306692) (xy -0.669494 -0.344202) (xy -0.661868 -0.378021) (xy -0.655239 -0.407637) + (xy -0.653885 -0.413755) (xy -0.530764 -0.413755) (xy -0.526858 -0.390636) (xy -0.522233 -0.378604) (xy -0.508641 -0.357802) (xy -0.489695 -0.338835) (xy -0.467287 -0.323127) (xy -0.443308 -0.312104) + (xy -0.428894 -0.308320) (xy -0.408350 -0.306476) (xy -0.384207 -0.307183) (xy -0.359559 -0.310187) (xy -0.337499 -0.315232) (xy -0.334988 -0.316023) (xy -0.308874 -0.327606) (xy -0.286826 -0.343528) + (xy -0.269791 -0.362892) (xy -0.258716 -0.384801) (xy -0.257213 -0.389724) (xy -0.254692 -0.407635) (xy -0.255310 -0.428189) (xy -0.258759 -0.448107) (xy -0.264098 -0.462913) (xy -0.274584 -0.478292) + (xy -0.289535 -0.493758) (xy -0.306535 -0.507097) (xy -0.321328 -0.515343) (xy -0.344367 -0.522865) (xy -0.370397 -0.527509) (xy -0.397388 -0.529225) (xy -0.423306 -0.527958) (xy -0.446120 -0.523660) + (xy -0.459099 -0.518845) (xy -0.475559 -0.508835) (xy -0.492455 -0.495163) (xy -0.507734 -0.479773) (xy -0.519344 -0.464607) (xy -0.522704 -0.458624) (xy -0.529385 -0.437314) (xy -0.530764 -0.413755) + (xy -0.653885 -0.413755) (xy -0.649726 -0.432538) (xy -0.645447 -0.452214) (xy -0.642520 -0.466153) (xy -0.641064 -0.473842) (xy -0.640944 -0.475241) (xy -0.644897 -0.475728) (xy -0.655259 -0.476242) + (xy -0.671181 -0.476761) (xy -0.691815 -0.477265) (xy -0.716313 -0.477732) (xy -0.743827 -0.478141) (xy -0.766836 -0.478405) (xy -0.890814 -0.479653) (xy -0.912138 -0.333262) (xy -0.918806 -0.287632) + (xy -0.925360 -0.243056) (xy -0.931707 -0.200151) (xy -0.937755 -0.159533) (xy -0.943409 -0.121818) (xy -0.948577 -0.087623) (xy -0.953166 -0.057564) (xy -0.957083 -0.032256) (xy -0.960235 -0.012316) + (xy -0.962527 0.001641) (xy -0.963821 0.008773) (xy -0.965921 0.015403) (xy -0.968225 0.015235) (xy -0.968865 0.014216) (xy -0.970472 0.009045) (xy -0.973467 -0.003065) (xy -0.977811 -0.021939) + (xy -0.983467 -0.047399) (xy -0.990397 -0.079269) (xy -0.998562 -0.117374) (xy -1.007925 -0.161536) (xy -1.018447 -0.211580) (xy -1.030092 -0.267329) (xy -1.042820 -0.328607) (xy -1.045309 -0.340626) + (xy -1.051701 -0.371406) (xy -1.057653 -0.399889) (xy -1.063004 -0.425309) (xy -1.067590 -0.446899) (xy -1.071247 -0.463894) (xy -1.073814 -0.475527) (xy -1.075127 -0.481032) (xy -1.075248 -0.481371) + (xy -1.078986 -0.481650) (xy -1.089105 -0.481964) (xy -1.104727 -0.482298) (xy -1.124976 -0.482636) (xy -1.148975 -0.482962) (xy -1.175847 -0.483261) (xy -1.190305 -0.483398) (xy -1.304352 -0.484414) + (xy -1.317546 -0.420914) (xy -1.321153 -0.403547) (xy -1.325999 -0.380201) (xy -1.331850 -0.352005) (xy -1.338473 -0.320085) (xy -1.345632 -0.285569) (xy -1.353095 -0.249586) (xy -1.360627 -0.213263) + (xy -1.364218 -0.195943) (xy -1.374079 -0.148460) (xy -1.382591 -0.107669) (xy -1.389845 -0.073150) (xy -1.395933 -0.044481) (xy -1.400949 -0.021244) (xy -1.404983 -0.003017) (xy -1.408130 0.010620) + (xy -1.410481 0.020087) (xy -1.412128 0.025805) (xy -1.413164 0.028194) (xy -1.413477 0.028275) (xy -1.414406 0.024393) (xy -1.416308 0.014014) (xy -1.419075 -0.002183) (xy -1.422603 -0.023518) + (xy -1.426784 -0.049313) (xy -1.431512 -0.078886) (xy -1.436681 -0.111560) (xy -1.442185 -0.146655) (xy -1.447916 -0.183490) (xy -1.453769 -0.221388) (xy -1.459637 -0.259669) (xy -1.465413 -0.297652) + (xy -1.470993 -0.334660) (xy -1.476268 -0.370011) (xy -1.481133 -0.403028) (xy -1.482772 -0.414274) (xy -1.492617 -0.482018) (xy -1.525544 -0.484476) (xy -1.542082 -0.485370) (xy -1.562503 -0.485942) + (xy -1.585719 -0.486215) (xy -1.610644 -0.486212) (xy -1.636189 -0.485955) (xy -1.661267 -0.485466) (xy -1.684791 -0.484768) (xy -1.705674 -0.483883) (xy -1.722826 -0.482834) (xy -1.735162 -0.481644) + (xy -1.741593 -0.480334) (xy -1.742142 -0.480000) (xy -1.744400 -0.475707) (xy -1.744449 -0.468333) (xy -2.071766 -0.468333) (xy -2.065304 -0.483795) (xy -2.034934 -0.541240) (xy -1.999229 -0.597002) + (xy -1.958792 -0.650423) (xy -1.914226 -0.700844) (xy -1.866132 -0.747609) (xy -1.815113 -0.790059) (xy -1.761771 -0.827537) (xy -1.706710 -0.859383) (xy -1.650531 -0.884941) (xy -1.624110 -0.894528) + (xy -1.608390 -0.899740) (xy -1.594542 -0.904163) (xy -1.581821 -0.907867) (xy -1.569477 -0.910921) (xy -1.556764 -0.913395) (xy -1.542933 -0.915357) (xy -1.527238 -0.916878) (xy -1.508930 -0.918026) + (xy -1.487263 -0.918870) (xy -1.461487 -0.919481) (xy -1.430857 -0.919927) (xy -1.394623 -0.920278) (xy -1.352039 -0.920603) (xy -1.342104 -0.920675) (xy -1.151137 -0.922064) (xy -1.123912 -0.957239) + (xy -1.078534 -1.011765) (xy -1.027099 -1.066241) (xy -0.970746 -1.119686) (xy -0.910616 -1.171123) (xy -0.847849 -1.219572) (xy -0.783585 -1.264054) (xy -0.724200 -1.300584) (xy -0.635860 -1.347818) + (xy -0.546693 -1.387942) (xy -0.456262 -1.421079) (xy -0.364133 -1.447352) (xy -0.269868 -1.466882) (xy -0.173032 -1.479791) (xy -0.073189 -1.486204) (xy -0.061686 -1.486525) (xy 0.038917 -1.485993) )(layer F.SilkS) (width 0.010000) + ) + (fp_poly (pts (xy 1.600200 0.442686) (xy 1.367971 0.442686) (xy 1.367971 -0.232229) (xy 1.600200 -0.232229) (xy 1.600200 0.442686) )(layer F.SilkS) (width 0.010000) + ) + (fp_poly (pts (xy 1.226457 -0.268514) (xy 0.671286 -0.268514) (xy 0.671286 -0.054429) (xy 1.161143 -0.054429) (xy 1.161143 0.163286) (xy 0.671286 0.163286) (xy 0.671286 0.435428) (xy 0.414417 0.435428) + (xy 0.412164 0.015421) (xy 0.411850 -0.040119) (xy 0.411513 -0.094249) (xy 0.411159 -0.146453) (xy 0.410790 -0.196217) (xy 0.410414 -0.243026) (xy 0.410033 -0.286365) (xy 0.409654 -0.325720) + (xy 0.409281 -0.360576) (xy 0.408919 -0.390419) (xy 0.408572 -0.414733) (xy 0.408245 -0.433003) (xy 0.407944 -0.444716) (xy 0.407843 -0.447222) (xy 0.405775 -0.489857) (xy 1.226457 -0.489857) + (xy 1.226457 -0.268514) )(layer F.SilkS) (width 0.010000) + ) + (fp_poly (pts (xy 1.509540 -0.535345) (xy 1.516456 -0.534431) (xy 1.545891 -0.527173) (xy 1.573078 -0.515271) (xy 1.596762 -0.499537) (xy 1.615691 -0.480783) (xy 1.627315 -0.462643) (xy 1.631434 -0.450686) + (xy 1.634571 -0.435310) (xy 1.635729 -0.424543) (xy 1.634032 -0.397289) (xy 1.625984 -0.372467) (xy 1.612214 -0.350536) (xy 1.593354 -0.331956) (xy 1.570035 -0.317184) (xy 1.542890 -0.306680) + (xy 1.512548 -0.300902) (xy 1.479641 -0.300309) (xy 1.466509 -0.301550) (xy 1.437799 -0.308323) (xy 1.410606 -0.320726) (xy 1.386409 -0.337781) (xy 1.366689 -0.358507) (xy 1.356536 -0.374305) + (xy 1.349789 -0.393877) (xy 1.347686 -0.416407) (xy 1.350217 -0.439286) (xy 1.356923 -0.459014) (xy 1.372616 -0.483081) (xy 1.393664 -0.503299) (xy 1.418973 -0.519151) (xy 1.447450 -0.530120) + (xy 1.478003 -0.535690) (xy 1.509540 -0.535345) )(layer F.SilkS) (width 0.010000) + ) +) diff --git a/board/v1/mod/wson8_5x6.kicad_mod b/board/v1/mod/wson8_5x6.kicad_mod new file mode 100644 index 0000000..7faa2ff --- /dev/null +++ b/board/v1/mod/wson8_5x6.kicad_mod @@ -0,0 +1,25 @@ +(module "Project Libraries:wson8_5x6" (layer F.Cu) (tedit 55FD25D6) + (fp_text reference U5 (at 0 3.5) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value W25Q32BV (at 0 -3.25) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_circle (center -2 -2.1) (end -2 -2) (layer F.SilkS) (width 0.2)) + (fp_line (start -2.5 -2.25) (end -2.5 -2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 -2.5) (end 1.75 -2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 1.75 -2.5) (end 2.5 -2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.5 -2.5) (end 2.5 -2.25) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 2.25) (end -2.5 2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start -2.5 2.5) (end 1 2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 1 2.5) (end 2.5 2.5) (layer F.SilkS) (width 0.15)) + (fp_line (start 2.5 2.5) (end 2.5 2.25) (layer F.SilkS) (width 0.15)) + (pad 1 smd rect (at -2.921 -1.905) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 2 smd rect (at -2.921 -0.635) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 3 smd rect (at -2.921 0.635) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 4 smd rect (at -2.921 1.905) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 5 smd rect (at 2.921 1.905) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 6 smd rect (at 2.921 0.635) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 7 smd rect (at 2.921 -0.635) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) + (pad 8 smd rect (at 2.921 -1.905) (size 1.3 0.5) (layers F.Cu F.Paste F.Mask)) +) diff --git a/board/v1/mpu9250.sch b/board/v1/mpu9250.sch new file mode 100644 index 0000000..eeac4c7 --- /dev/null +++ b/board/v1/mpu9250.sch @@ -0,0 +1,239 @@ +EESchema Schematic File Version 2 +LIBS:handgelenk-rescue +LIBS:Zilog +LIBS:xilinx +LIBS:Xicor +LIBS:video +LIBS:valves +LIBS:ttl_ieee +LIBS:transistors +LIBS:transf +LIBS:texas +LIBS:switches +LIBS:supertex +LIBS:stm32 +LIBS:stm8 +LIBS:siliconi +LIBS:silabs +LIBS:sensors +LIBS:rfcom +LIBS:relays +LIBS:regul +LIBS:references +LIBS:pspice +LIBS:Power_Management +LIBS:powerint +LIBS:power +LIBS:philips +LIBS:Oscillators +LIBS:opto +LIBS:onsemi +LIBS:nxp_armmcu +LIBS:nordicsemi +LIBS:msp430 +LIBS:motorola +LIBS:motor_drivers +LIBS:microcontrollers +LIBS:microchip_pic32mcu +LIBS:microchip_pic18mcu +LIBS:microchip_pic16mcu +LIBS:microchip_pic12mcu +LIBS:microchip_pic10mcu +LIBS:microchip_dspic33dsc +LIBS:microchip +LIBS:memory +LIBS:maxim +LIBS:logo +LIBS:linear +LIBS:Lattice +LIBS:ir +LIBS:interface +LIBS:intel +LIBS:hc11 +LIBS:graphic +LIBS:gennum +LIBS:ftdi +LIBS:ESD_Protection +LIBS:elec-unifil +LIBS:dsp +LIBS:display +LIBS:diode +LIBS:digital-audio +LIBS:device +LIBS:dc-dc +LIBS:cypress +LIBS:contrib +LIBS:conn +LIBS:cmos_ieee +LIBS:cmos4000 +LIBS:brooktre +LIBS:audio +LIBS:atmel +LIBS:analog_switches +LIBS:analog_devices +LIBS:Altera +LIBS:adc-dac +LIBS:actel +LIBS:ac-dc +LIBS:74xx +LIBS:74xgxx +LIBS:mcp73831 +LIBS:esp8266ex +LIBS:ft232rq +LIBS:mpu9250 +LIBS:w25q32bv +LIBS:lt1129cst +LIBS:rv3029c2 +LIBS:tlv70233 +LIBS:er-oled-ssd1306 +LIBS:handgelenk-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 3 4 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +$Comp +L MPU-9250 U6 +U 1 1 55F84634 +P 3450 2550 +F 0 "U6" H 3050 3050 60 0000 C CNN +F 1 "MPU-9250" H 3950 2050 60 0000 C CNN +F 2 "Housings_DFN_QFN:QFN-24-1EP_3x3mm_Pitch0.4mm" H 3150 2800 60 0001 C CNN +F 3 "" H 3150 2800 60 0000 C CNN + 1 3450 2550 + 1 0 0 -1 +$EndComp +Text HLabel 2700 2300 0 60 Input ~ 0 +SCL +Wire Wire Line + 2700 2300 2800 2300 +Text HLabel 2700 2400 0 60 BiDi ~ 0 +SDA +Wire Wire Line + 2700 2400 2800 2400 +NoConn ~ 2800 2600 +$Comp +L GND #PWR024 +U 1 1 55F847F4 +P 4150 3750 +F 0 "#PWR024" H 4150 3500 50 0001 C CNN +F 1 "GND" H 4150 3600 50 0000 C CNN +F 2 "" H 4150 3750 60 0000 C CNN +F 3 "" H 4150 3750 60 0000 C CNN + 1 4150 3750 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C14 +U 1 1 55F84959 +P 3250 3450 +F 0 "C14" H 3050 3500 50 0000 L CNN +F 1 "100n" H 3050 3350 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 3250 3450 60 0001 C CNN +F 3 "" H 3250 3450 60 0000 C CNN + 1 3250 3450 + 1 0 0 -1 +$EndComp +Wire Wire Line + 3250 3200 3250 3350 +Wire Wire Line + 4150 3700 4150 3750 +Wire Wire Line + 2250 3700 4150 3700 +Wire Wire Line + 3250 3700 3250 3550 +Wire Wire Line + 3400 3200 3400 3700 +Connection ~ 3400 3700 +Wire Wire Line + 3500 3200 3500 3700 +Connection ~ 3500 3700 +Wire Wire Line + 3600 3200 3600 3700 +Connection ~ 3600 3700 +NoConn ~ 4100 2300 +NoConn ~ 4100 2400 +Text HLabel 4200 2600 2 60 Output ~ 0 +INT +Wire Wire Line + 4200 2600 4100 2600 +NoConn ~ 4100 2750 +Wire Wire Line + 2250 2750 2800 2750 +Connection ~ 3250 3700 +$Comp +L +3V3 #PWR025 +U 1 1 55F84D6F +P 1950 1750 +F 0 "#PWR025" H 1950 1600 50 0001 C CNN +F 1 "+3V3" H 1950 1890 50 0000 C CNN +F 2 "" H 1950 1750 60 0000 C CNN +F 3 "" H 1950 1750 60 0000 C CNN + 1 1950 1750 + 1 0 0 -1 +$EndComp +Wire Wire Line + 3700 3200 3700 3700 +Connection ~ 3700 3700 +$Comp +L C_Small C12 +U 1 1 55F83B4A +P 1950 2000 +F 0 "C12" H 1960 2070 50 0000 L CNN +F 1 "100n" H 1960 1920 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 1950 2000 60 0001 C CNN +F 3 "" H 1950 2000 60 0000 C CNN + 1 1950 2000 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C13 +U 1 1 55F83D26 +P 2250 2000 +F 0 "C13" H 2260 2070 50 0000 L CNN +F 1 "10n" H 2260 1920 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 2250 2000 60 0001 C CNN +F 3 "" H 2250 2000 60 0000 C CNN + 1 2250 2000 + 1 0 0 -1 +$EndComp +Wire Wire Line + 1950 1750 1950 1900 +Wire Wire Line + 2250 2100 2250 3700 +Connection ~ 2250 2750 +Wire Wire Line + 1950 2100 1950 2200 +Wire Wire Line + 1950 2200 2250 2200 +Connection ~ 2250 2200 +Wire Wire Line + 2250 1900 2250 1800 +Wire Wire Line + 1950 1800 3550 1800 +Connection ~ 1950 1800 +Wire Wire Line + 3300 1800 3300 1900 +Connection ~ 2250 1800 +Wire Wire Line + 3400 1800 3400 1900 +Connection ~ 3300 1800 +Wire Wire Line + 3550 1800 3550 1900 +Connection ~ 3400 1800 +Text Notes 2150 1700 0 60 ~ 0 +Place 10n cap near VDDIO,\n100n cap near VDD +Text Notes 4650 2750 0 60 ~ 0 +Set interrupt pin active low:\nRegister INT_PIN_CFG:\nACTL 0\nOPEN 0\nLATCH_INT_EN 0 +Text Notes 4650 3050 0 60 ~ 0 +TODO: INT pin doesn't work, connection has to be removed +$EndSCHEMATC diff --git a/board/v1/power.sch b/board/v1/power.sch new file mode 100644 index 0000000..7a9aa87 --- /dev/null +++ b/board/v1/power.sch @@ -0,0 +1,640 @@ +EESchema Schematic File Version 2 +LIBS:handgelenk-rescue +LIBS:Zilog +LIBS:xilinx +LIBS:Xicor +LIBS:video +LIBS:valves +LIBS:ttl_ieee +LIBS:transistors +LIBS:transf +LIBS:texas +LIBS:switches +LIBS:supertex +LIBS:stm32 +LIBS:stm8 +LIBS:siliconi +LIBS:silabs +LIBS:sensors +LIBS:rfcom +LIBS:relays +LIBS:regul +LIBS:references +LIBS:pspice +LIBS:Power_Management +LIBS:powerint +LIBS:power +LIBS:philips +LIBS:Oscillators +LIBS:opto +LIBS:onsemi +LIBS:nxp_armmcu +LIBS:nordicsemi +LIBS:msp430 +LIBS:motorola +LIBS:motor_drivers +LIBS:microcontrollers +LIBS:microchip_pic32mcu +LIBS:microchip_pic18mcu +LIBS:microchip_pic16mcu +LIBS:microchip_pic12mcu +LIBS:microchip_pic10mcu +LIBS:microchip_dspic33dsc +LIBS:microchip +LIBS:memory +LIBS:maxim +LIBS:logo +LIBS:linear +LIBS:Lattice +LIBS:ir +LIBS:interface +LIBS:intel +LIBS:hc11 +LIBS:graphic +LIBS:gennum +LIBS:ftdi +LIBS:ESD_Protection +LIBS:elec-unifil +LIBS:dsp +LIBS:display +LIBS:diode +LIBS:digital-audio +LIBS:device +LIBS:dc-dc +LIBS:cypress +LIBS:contrib +LIBS:conn +LIBS:cmos_ieee +LIBS:cmos4000 +LIBS:brooktre +LIBS:audio +LIBS:atmel +LIBS:analog_switches +LIBS:analog_devices +LIBS:Altera +LIBS:adc-dac +LIBS:actel +LIBS:ac-dc +LIBS:74xx +LIBS:74xgxx +LIBS:mcp73831 +LIBS:esp8266ex +LIBS:ft232rq +LIBS:mpu9250 +LIBS:w25q32bv +LIBS:lt1129cst +LIBS:rv3029c2 +LIBS:tlv70233 +LIBS:er-oled-ssd1306 +LIBS:handgelenk-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 2 4 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +$Comp +L MCP73831 U3 +U 1 1 55CFAFFF +P 4100 1950 +F 0 "U3" H 3850 2150 50 0000 C CNN +F 1 "MCP73831" H 4200 1750 50 0000 C CNN +F 2 "TO_SOT_Packages_SMD:SOT-23-5" H 4100 1950 60 0001 C CNN +F 3 "" H 4100 1950 60 0000 C CNN + 1 4100 1950 + 1 0 0 -1 +$EndComp +Text Notes 6200 1250 0 60 ~ 0 +do NOT use AMS1117 +Text Notes 6200 1150 0 60 ~ 0 +LM 3940 IMP-3,3 should also work +Text Notes 6200 1050 0 60 ~ 0 +MCP 1755S-3302ED should also work +$Comp +L GND #PWR012 +U 1 1 55D05DB2 +P 4750 2750 +F 0 "#PWR012" H 4750 2500 50 0001 C CNN +F 1 "GND" H 4750 2600 50 0000 C CNN +F 2 "" H 4750 2750 60 0000 C CNN +F 3 "" H 4750 2750 60 0000 C CNN + 1 4750 2750 + 1 0 0 -1 +$EndComp +$Comp +L R R4 +U 1 1 55D05DFE +P 4750 2350 +F 0 "R4" V 4830 2350 50 0000 C CNN +F 1 "3K3" V 4750 2350 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 4750 2350 60 0001 C CNN +F 3 "" H 4750 2350 60 0000 C CNN + 1 4750 2350 + 1 0 0 -1 +$EndComp +$Comp +L +BATT #PWR013 +U 1 1 55D05E8A +P 4750 1150 +F 0 "#PWR013" H 4750 1000 50 0001 C CNN +F 1 "+BATT" H 4750 1290 50 0000 C CNN +F 2 "" H 4750 1150 60 0000 C CNN +F 3 "" H 4750 1150 60 0000 C CNN + 1 4750 1150 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C4 +U 1 1 55D05F2E +P 2950 2350 +F 0 "C4" H 2960 2420 50 0000 L CNN +F 1 "4u7" H 2960 2270 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 2950 2350 60 0001 C CNN +F 3 "" H 2950 2350 60 0000 C CNN + 1 2950 2350 + 1 0 0 -1 +$EndComp +$Comp +L USB_OTG P1 +U 1 1 55D06165 +P 1200 2050 +F 0 "P1" H 1525 1925 50 0000 C CNN +F 1 "USB_OTG" H 1200 2250 50 0000 C CNN +F 2 "Connect:USB_Micro-B" V 1150 1950 60 0001 C CNN +F 3 "" V 1150 1950 60 0000 C CNN + 1 1200 2050 + 0 -1 1 0 +$EndComp +NoConn ~ 1500 2150 +$Comp +L +5V #PWR014 +U 1 1 55D07042 +P 2950 1150 +F 0 "#PWR014" H 2950 1000 50 0001 C CNN +F 1 "+5V" H 2950 1290 50 0000 C CNN +F 2 "" H 2950 1150 60 0000 C CNN +F 3 "" H 2950 1150 60 0000 C CNN + 1 2950 1150 + 1 0 0 -1 +$EndComp +Wire Wire Line + 4750 1950 4750 2100 +Wire Wire Line + 4750 1950 4500 1950 +Wire Wire Line + 4500 2050 4600 2050 +Wire Wire Line + 4600 2050 4600 2700 +Connection ~ 4750 2700 +Wire Wire Line + 4750 1850 4500 1850 +Wire Wire Line + 4750 2600 4750 2750 +Wire Wire Line + 2950 1150 2950 2250 +Wire Wire Line + 2950 2700 2950 2450 +Connection ~ 4600 2700 +Connection ~ 2950 2700 +Connection ~ 2950 1850 +Wire Wire Line + 4750 1150 4750 1850 +Wire Wire Line + 3450 2050 3700 2050 +Wire Wire Line + 1100 2450 1100 2700 +Wire Wire Line + 1500 2250 1550 2250 +Wire Wire Line + 1550 2250 1550 2700 +Connection ~ 1550 2700 +Wire Wire Line + 1100 2700 4750 2700 +Text Notes 2350 3100 0 60 ~ 0 +3.3K programming resistor for approx. 300mA charge current +$Comp +L CONN_01X02 P2 +U 1 1 55D0747F +P 5750 1850 +F 0 "P2" H 5750 2000 50 0000 C CNN +F 1 "LIPO" V 5850 1850 50 0000 C CNN +F 2 "Pin_Headers:Pin_Header_Straight_1x02" H 5750 1850 60 0001 C CNN +F 3 "" H 5750 1850 60 0000 C CNN + 1 5750 1850 + -1 0 0 1 +$EndComp +$Comp +L +BATT #PWR015 +U 1 1 55D07672 +P 6000 1200 +F 0 "#PWR015" H 6000 1050 50 0001 C CNN +F 1 "+BATT" H 6000 1340 50 0000 C CNN +F 2 "" H 6000 1200 60 0000 C CNN +F 3 "" H 6000 1200 60 0000 C CNN + 1 6000 1200 + 1 0 0 -1 +$EndComp +Wire Wire Line + 5950 1800 6000 1800 +Wire Wire Line + 6000 1800 6000 1200 +Wire Wire Line + 5950 1900 6000 1900 +Connection ~ 6000 1600 +$Comp +L C_Small C5 +U 1 1 55D07963 +P 6300 1850 +F 0 "C5" H 6310 1920 50 0000 L CNN +F 1 "4u7" H 6310 1770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 6300 1850 60 0001 C CNN +F 3 "" H 6300 1850 60 0000 C CNN + 1 6300 1850 + 1 0 0 -1 +$EndComp +Wire Wire Line + 6300 1750 6300 1600 +Wire Wire Line + 6000 1600 6650 1600 +Wire Wire Line + 6300 1950 6300 2700 +Connection ~ 6300 1600 +Wire Wire Line + 6000 2700 8050 2700 +Wire Notes Line + 600 600 600 3150 +Wire Notes Line + 600 3150 5250 3150 +Wire Notes Line + 5250 3150 5250 600 +Wire Notes Line + 5250 600 600 600 +Connection ~ 6300 2700 +Wire Wire Line + 6000 1900 6000 2700 +Wire Wire Line + 7550 1600 8050 1600 +$Comp +L C_Small C7 +U 1 1 55D084FD +P 8050 1850 +F 0 "C7" H 8060 1920 50 0000 L CNN +F 1 "10u" H 8060 1770 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 8050 1850 60 0001 C CNN +F 3 "" H 8050 1850 60 0000 C CNN + 1 8050 1850 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7750 1600 7750 1750 +Wire Wire Line + 7750 1950 7750 2700 +$Comp +L C_Small C6 +U 1 1 55D088C0 +P 7750 1850 +F 0 "C6" H 7760 1920 50 0000 L CNN +F 1 "100u" H 7760 1770 50 0000 L CNN +F 2 "Capacitors_SMD:C_1206" H 7750 1850 60 0001 C CNN +F 3 "" H 7750 1850 60 0000 C CNN + 1 7750 1850 + 1 0 0 -1 +$EndComp +Wire Wire Line + 8050 1950 8050 2750 +Connection ~ 7750 2700 +Wire Wire Line + 8050 1200 8050 1750 +Connection ~ 7750 1600 +$Comp +L GND #PWR016 +U 1 1 55D0915C +P 8050 2750 +F 0 "#PWR016" H 8050 2500 50 0001 C CNN +F 1 "GND" H 8050 2600 50 0000 C CNN +F 2 "" H 8050 2750 60 0000 C CNN +F 3 "" H 8050 2750 60 0000 C CNN + 1 8050 2750 + 1 0 0 -1 +$EndComp +Connection ~ 8050 2700 +Wire Notes Line + 5300 3150 5300 600 +Wire Notes Line + 5300 600 8600 600 +Wire Notes Line + 8600 600 8600 3150 +Wire Notes Line + 8600 3150 5300 3150 +Text Notes 5350 800 0 120 ~ 0 +LiPo 3.3V LDO +$Comp +L GND #PWR017 +U 1 1 55D07EB2 +P 4050 6050 +F 0 "#PWR017" H 4050 5800 50 0001 C CNN +F 1 "GND" H 4050 5900 50 0000 C CNN +F 2 "" H 4050 6050 60 0000 C CNN +F 3 "" H 4050 6050 60 0000 C CNN + 1 4050 6050 + 1 0 0 -1 +$EndComp +Wire Wire Line + 1900 5900 4050 5900 +Wire Wire Line + 2650 5900 2650 5800 +Wire Wire Line + 2750 5800 2750 5900 +Connection ~ 2750 5900 +Wire Wire Line + 2850 5800 2850 5900 +Connection ~ 2850 5900 +Wire Wire Line + 2950 5800 2950 5900 +Connection ~ 2950 5900 +Wire Wire Line + 3050 5800 3050 5900 +Connection ~ 3050 5900 +$Comp +L C_Small C2 +U 1 1 55D08232 +P 1900 5700 +F 0 "C2" H 1910 5770 50 0000 L CNN +F 1 "100n" H 1910 5620 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 1900 5700 60 0001 C CNN +F 3 "" H 1900 5700 60 0000 C CNN + 1 1900 5700 + 1 0 0 -1 +$EndComp +Wire Wire Line + 2050 5500 1900 5500 +Wire Wire Line + 1900 4000 1900 5600 +Wire Wire Line + 1900 5900 1900 5800 +Connection ~ 2650 5900 +$Comp +L FILTER FB1 +U 1 1 55D0855B +P 2400 1850 +F 0 "FB1" H 2400 2000 50 0000 C CNN +F 1 "BLM21PG 600" H 2400 1750 50 0000 C CNN +F 2 "Capacitors_SMD:C_0805" H 2400 1850 60 0001 C CNN +F 3 "" H 2400 1850 60 0000 C CNN + 1 2400 1850 + 1 0 0 -1 +$EndComp +Text Notes 700 850 0 120 ~ 0 +USB LiPo Charger +Wire Wire Line + 1500 1850 2050 1850 +Wire Wire Line + 1450 4100 2050 4100 +Wire Wire Line + 2050 4000 1900 4000 +Connection ~ 1900 5500 +Wire Wire Line + 2750 1850 3700 1850 +Text HLabel 3450 2050 0 60 Output ~ 0 +~CHARGE +$Comp +L C_Small C3 +U 1 1 55D09B38 +P 1950 2350 +F 0 "C3" H 1960 2420 50 0000 L CNN +F 1 "10n" H 1960 2270 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 1950 2350 60 0001 C CNN +F 3 "" H 1950 2350 60 0000 C CNN + 1 1950 2350 + 1 0 0 -1 +$EndComp +Wire Wire Line + 1950 2250 1950 1850 +Connection ~ 1950 1850 +Wire Wire Line + 1950 2450 1950 2700 +Connection ~ 1950 2700 +Wire Wire Line + 1500 1950 1850 1950 +Text Label 1850 1950 2 60 ~ 0 +USB_DM +Text Label 1850 2050 2 60 ~ 0 +USB_DP +Wire Wire Line + 1500 2050 1850 2050 +Wire Wire Line + 2050 4300 1450 4300 +Wire Wire Line + 2050 4400 1450 4400 +$Comp +L +5V #PWR018 +U 1 1 55D09373 +P 1450 3750 +F 0 "#PWR018" H 1450 3600 50 0001 C CNN +F 1 "+5V" H 1450 3890 50 0000 C CNN +F 2 "" H 1450 3750 60 0000 C CNN +F 3 "" H 1450 3750 60 0000 C CNN + 1 1450 3750 + 1 0 0 -1 +$EndComp +Wire Wire Line + 1450 4100 1450 3750 +Text Label 1450 4300 0 60 ~ 0 +USB_DM +Text Label 1450 4400 0 60 ~ 0 +USB_DP +NoConn ~ 3750 5100 +NoConn ~ 3750 5200 +NoConn ~ 3750 5300 +NoConn ~ 3750 5400 +NoConn ~ 3750 5500 +NoConn ~ 2050 5100 +NoConn ~ 3750 4950 +NoConn ~ 3750 4850 +NoConn ~ 3750 4700 +NoConn ~ 3750 4450 +Text HLabel 3950 4000 2 60 Output ~ 0 +TXD +Wire Wire Line + 3950 4000 3750 4000 +Text HLabel 3950 4150 2 60 Input ~ 0 +RXD +Wire Wire Line + 3950 4150 3750 4150 +Text HLabel 3950 4350 2 60 Output ~ 0 +RTS +Wire Wire Line + 3950 4350 3750 4350 +Text HLabel 3950 4600 2 60 Output ~ 0 +DTR +Wire Wire Line + 3950 4600 3750 4600 +NoConn ~ 2050 5300 +NoConn ~ 2050 5400 +Wire Notes Line + 600 3200 5250 3200 +Wire Notes Line + 5250 3200 5250 6350 +Wire Notes Line + 5250 6350 600 6350 +Wire Notes Line + 600 6350 600 3200 +Text Notes 700 3400 0 120 ~ 0 +FT232RQ USB to UART +Wire Wire Line + 4050 5900 4050 6050 +$Comp +L +BATT #PWR019 +U 1 1 55F9A881 +P 9050 1200 +F 0 "#PWR019" H 9050 1050 50 0001 C CNN +F 1 "+BATT" H 9050 1340 50 0000 C CNN +F 2 "" H 9050 1200 60 0000 C CNN +F 3 "" H 9050 1200 60 0000 C CNN + 1 9050 1200 + 1 0 0 -1 +$EndComp +$Comp +L GND #PWR020 +U 1 1 55F9A973 +P 9050 2750 +F 0 "#PWR020" H 9050 2500 50 0001 C CNN +F 1 "GND" H 9050 2600 50 0000 C CNN +F 2 "" H 9050 2750 60 0000 C CNN +F 3 "" H 9050 2750 60 0000 C CNN + 1 9050 2750 + 1 0 0 -1 +$EndComp +$Comp +L R R7 +U 1 1 55F9A99C +P 9050 1550 +F 0 "R7" V 9130 1550 50 0000 C CNN +F 1 "330K" V 9050 1550 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 9050 1550 60 0001 C CNN +F 3 "" H 9050 1550 60 0000 C CNN + 1 9050 1550 + 1 0 0 -1 +$EndComp +$Comp +L R R8 +U 1 1 55F9A9FE +P 9050 2400 +F 0 "R8" V 9130 2400 50 0000 C CNN +F 1 "100K" V 9050 2400 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 9050 2400 60 0001 C CNN +F 3 "" H 9050 2400 60 0000 C CNN + 1 9050 2400 + 1 0 0 -1 +$EndComp +Wire Wire Line + 9050 1300 9050 1200 +Wire Wire Line + 9050 2650 9050 2750 +Wire Wire Line + 9050 1800 9050 2150 +Connection ~ 9050 2000 +Wire Notes Line + 8700 600 8700 3150 +Wire Notes Line + 8700 3150 10550 3150 +Text Notes 8750 800 0 120 ~ 0 +Batt. volt. sense +Text Notes 8800 900 0 60 ~ 0 +Use low-tolerance resistors +Text HLabel 9150 2000 2 60 Output ~ 0 +BATT_SENSE +Wire Wire Line + 9150 2000 9050 2000 +Text Notes 9250 2650 0 60 ~ 0 +Voltage divider:\n4.3V Batt. --> 1V Sense\nESP8266 ADC 10bit\nup to 1V, so resolution\nis about 4.2mV +Wire Notes Line + 8700 600 10550 600 +Wire Notes Line + 10550 600 10550 3150 +Text Notes 9250 1350 0 60 ~ 0 +Voltage divider leaks\n4µA at 4.3V Battery +Connection ~ 8050 1600 +$Comp +L +3V3 #PWR021 +U 1 1 55FA7E2A +P 8050 1200 +F 0 "#PWR021" H 8050 1050 50 0001 C CNN +F 1 "+3V3" H 8050 1340 50 0000 C CNN +F 2 "" H 8050 1200 60 0000 C CNN +F 3 "" H 8050 1200 60 0000 C CNN + 1 8050 1200 + 1 0 0 -1 +$EndComp +$Comp +L TLV70233-SOT-23 U4 +U 1 1 55FAB6D1 +P 7100 1650 +F 0 "U4" H 6900 1850 60 0000 C CNN +F 1 "TLV70233-SOT-23" H 7100 1950 60 0000 C CNN +F 2 "TO_SOT_Packages_SMD:SOT-23-5" H 7100 1500 60 0001 C CNN +F 3 "" H 7100 1500 60 0000 C CNN + 1 7100 1650 + 1 0 0 -1 +$EndComp +Wire Wire Line + 7100 2000 7100 2700 +Connection ~ 7100 2700 +Wire Wire Line + 6650 1700 6500 1700 +Wire Wire Line + 6500 1700 6500 1600 +Connection ~ 6500 1600 +$Comp +L PWR_FLAG #FLG022 +U 1 1 55FD3AB2 +P 2600 1200 +F 0 "#FLG022" H 2600 1295 50 0001 C CNN +F 1 "PWR_FLAG" H 2600 1380 50 0000 C CNN +F 2 "" H 2600 1200 60 0000 C CNN +F 3 "" H 2600 1200 60 0000 C CNN + 1 2600 1200 + 1 0 0 -1 +$EndComp +Wire Wire Line + 2600 1200 2600 1250 +Wire Wire Line + 2600 1250 2950 1250 +Connection ~ 2950 1250 +$Comp +L FT232RQ U2 +U 1 1 55FD3EAE +P 2900 4750 +F 0 "U2" H 2350 5650 60 0000 C CNN +F 1 "FT232RQ" H 3400 3850 60 0000 C CNN +F 2 "Housings_DFN_QFN:QFN-32-1EP_5x5mm_Pitch0.5mm" H 3500 4650 120 0001 C CNN +F 3 "" H 3500 4650 120 0000 C CNN + 1 2900 4750 + 1 0 0 -1 +$EndComp +$Comp +L PWR_FLAG #FLG023 +U 1 1 55FD49BC +P 5950 2250 +F 0 "#FLG023" H 5950 2345 50 0001 C CNN +F 1 "PWR_FLAG" H 5950 2430 50 0000 C CNN +F 2 "" H 5950 2250 60 0000 C CNN +F 3 "" H 5950 2250 60 0000 C CNN + 1 5950 2250 + 0 -1 -1 0 +$EndComp +Wire Wire Line + 5950 2250 6000 2250 +Connection ~ 6000 2250 +Wire Wire Line + 3150 5800 3150 5900 +Connection ~ 3150 5900 +$EndSCHEMATC diff --git a/board/v1/rv3029c2.sch b/board/v1/rv3029c2.sch new file mode 100644 index 0000000..65f29eb --- /dev/null +++ b/board/v1/rv3029c2.sch @@ -0,0 +1,200 @@ +EESchema Schematic File Version 2 +LIBS:handgelenk-rescue +LIBS:Zilog +LIBS:xilinx +LIBS:Xicor +LIBS:video +LIBS:valves +LIBS:ttl_ieee +LIBS:transistors +LIBS:transf +LIBS:texas +LIBS:switches +LIBS:supertex +LIBS:stm32 +LIBS:stm8 +LIBS:siliconi +LIBS:silabs +LIBS:sensors +LIBS:rfcom +LIBS:relays +LIBS:regul +LIBS:references +LIBS:pspice +LIBS:Power_Management +LIBS:powerint +LIBS:power +LIBS:philips +LIBS:Oscillators +LIBS:opto +LIBS:onsemi +LIBS:nxp_armmcu +LIBS:nordicsemi +LIBS:msp430 +LIBS:motorola +LIBS:motor_drivers +LIBS:microcontrollers +LIBS:microchip_pic32mcu +LIBS:microchip_pic18mcu +LIBS:microchip_pic16mcu +LIBS:microchip_pic12mcu +LIBS:microchip_pic10mcu +LIBS:microchip_dspic33dsc +LIBS:microchip +LIBS:memory +LIBS:maxim +LIBS:logo +LIBS:linear +LIBS:Lattice +LIBS:ir +LIBS:interface +LIBS:intel +LIBS:hc11 +LIBS:graphic +LIBS:gennum +LIBS:ftdi +LIBS:ESD_Protection +LIBS:elec-unifil +LIBS:dsp +LIBS:display +LIBS:diode +LIBS:digital-audio +LIBS:device +LIBS:dc-dc +LIBS:cypress +LIBS:contrib +LIBS:conn +LIBS:cmos_ieee +LIBS:cmos4000 +LIBS:brooktre +LIBS:audio +LIBS:atmel +LIBS:analog_switches +LIBS:analog_devices +LIBS:Altera +LIBS:adc-dac +LIBS:actel +LIBS:ac-dc +LIBS:74xx +LIBS:74xgxx +LIBS:mcp73831 +LIBS:esp8266ex +LIBS:ft232rq +LIBS:mpu9250 +LIBS:w25q32bv +LIBS:lt1129cst +LIBS:rv3029c2 +LIBS:tlv70233 +LIBS:er-oled-ssd1306 +LIBS:handgelenk-cache +EELAYER 25 0 +EELAYER END +$Descr A4 11693 8268 +encoding utf-8 +Sheet 4 4 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +Text HLabel 1600 1700 0 60 Input ~ 0 +SCL +Wire Wire Line + 1600 1700 1700 1700 +Text HLabel 1600 1800 0 60 BiDi ~ 0 +SDA +Wire Wire Line + 1600 1800 1700 1800 +$Comp +L +3V3 #PWR026 +U 1 1 55F98236 +P 1200 850 +F 0 "#PWR026" H 1200 700 50 0001 C CNN +F 1 "+3V3" H 1200 990 50 0000 C CNN +F 2 "" H 1200 850 60 0000 C CNN +F 3 "" H 1200 850 60 0000 C CNN + 1 1200 850 + 1 0 0 -1 +$EndComp +$Comp +L C_Small C15 +U 1 1 55F98261 +P 1200 1100 +F 0 "C15" H 1210 1170 50 0000 L CNN +F 1 "10n" H 1210 1020 50 0000 L CNN +F 2 "Capacitors_SMD:C_0603" H 1200 1100 60 0001 C CNN +F 3 "" H 1200 1100 60 0000 C CNN + 1 1200 1100 + 1 0 0 -1 +$EndComp +Wire Wire Line + 1200 850 1200 1000 +Wire Wire Line + 1200 900 3000 900 +Wire Wire Line + 2400 900 2400 1400 +Connection ~ 1200 900 +Wire Wire Line + 2200 1400 2200 1350 +Wire Wire Line + 2200 1350 1200 1350 +Wire Wire Line + 1200 1200 1200 2550 +$Comp +L GND #PWR027 +U 1 1 55F98317 +P 2300 2650 +F 0 "#PWR027" H 2300 2400 50 0001 C CNN +F 1 "GND" H 2300 2500 50 0000 C CNN +F 2 "" H 2300 2650 60 0000 C CNN +F 3 "" H 2300 2650 60 0000 C CNN + 1 2300 2650 + 1 0 0 -1 +$EndComp +Connection ~ 1200 1350 +Wire Wire Line + 2300 2300 2300 2650 +Connection ~ 2300 2550 +Wire Wire Line + 1700 2000 1200 2000 +Connection ~ 1200 2000 +NoConn ~ 2900 2000 +Text HLabel 3200 1700 2 60 Output ~ 0 +INT +Wire Wire Line + 2900 1700 3200 1700 +$Comp +L R R9 +U 1 1 55F993EB +P 3000 1300 +F 0 "R9" V 3080 1300 50 0000 C CNN +F 1 "10K" V 3000 1300 50 0000 C CNN +F 2 "Resistors_SMD:R_0603" H 3000 1300 60 0001 C CNN +F 3 "" H 3000 1300 60 0000 C CNN + 1 3000 1300 + 1 0 0 -1 +$EndComp +Connection ~ 2400 900 +Wire Wire Line + 3000 1550 3000 1700 +Connection ~ 3000 1700 +Wire Wire Line + 3000 900 3000 1050 +Wire Wire Line + 1200 2550 2300 2550 +$Comp +L RV-3029-C2 U7 +U 1 1 55F9C7CF +P 2300 1850 +F 0 "U7" H 1950 2200 60 0000 C CNN +F 1 "RV-3029-C2" H 2650 1500 60 0000 C CNN +F 2 "Project Libraries:rv3029" H 2200 1800 60 0001 C CNN +F 3 "" H 2200 1800 60 0000 C CNN + 1 2300 1850 + 1 0 0 -1 +$EndComp +$EndSCHEMATC diff --git a/firmwares/README.md b/firmwares/README.md new file mode 100644 index 0000000..f128dc9 --- /dev/null +++ b/firmwares/README.md @@ -0,0 +1,2 @@ +## Notice +While it would certainly be nice to have one firmware that supports all the features of the watch, I haven't had the time yet to write that. Technically it is absolutely possible, since the watch has a 32Mbit flash chip which is certainly more than enough for all of the different firmwares here. Also, I haven't published a firmware yet that uses all of the power-saving features of the ESP8266. `wifitime` uses light sleep mode and wakes up every 1 second to update the screen, which makes the battery last for about 1 day. With deep sleep and less frequent updates, battery life can easily reach 2 days. diff --git a/firmwares/compass/.gitignore b/firmwares/compass/.gitignore new file mode 100644 index 0000000..722a501 --- /dev/null +++ b/firmwares/compass/.gitignore @@ -0,0 +1,2 @@ +build/ +obj/ diff --git a/firmwares/compass/Makefile b/firmwares/compass/Makefile new file mode 100644 index 0000000..60ea550 --- /dev/null +++ b/firmwares/compass/Makefile @@ -0,0 +1,64 @@ +# Esptool firmware download options +PORT := /dev/ttyUSB0 +BAUD := 1000000 + +# Directory structure +BUILDDIR := build +SRCDIR := src +OBJDIR := obj +LDSCRIPT := ldscript.ld + +SRCS := $(wildcard $(SRCDIR)/*.c) +OBJS := $(addprefix $(OBJDIR)/,$(notdir $(SRCS:.c=.o))) +DEPS := $(addprefix $(OBJDIR),$(notdir $(SRCS:.c=.d))) + +# SDK / Compiler settings +SDK_DIR := /opt/esp-open-sdk/esp_iot_sdk_v1.5.0 +CC := xtensa-lx106-elf-gcc +LD := xtensa-lx106-elf-gcc +ESPTOOL := esptool.py +CFLAGS := -Os -fdata-sections -ffunction-sections -Wpointer-arith -Wall -Wno-parentheses -Wno-implicit-function-declaration -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH +LDLIBS := -Wl,--start-group -lc -lgcc -lhal -lphy -lpp -lnet80211 -lwpa -lmain -llwip -lcrypto -lm $(OBJS) -Wl,--end-group +LDFLAGS := -nostdlib -Wl,--gc-sections -Wl,--no-check-sections -u call_user_start -Wl,-static -T $(LDSCRIPT) +INCLUDES := -I $(SDK_DIR)/include -I $(SDK_DIR)/include/json -I $(SRCDIR)/ + +# Project settings +TARGET := handgelenk +FLASH_FREQ := 80m +FLASH_MODE := qio +FLASH_SIZE := 32m +FLASH_OPT := --flash_freq $(FLASH_FREQ) --flash_mode $(FLASH_MODE) --flash_size $(FLASH_SIZE) + +TARGET_ELF := $(BUILDDIR)/$(TARGET).elf +TARGET_FLASH := $(BUILDDIR)/$(TARGET)-0x00000.bin +TARGET_IROM := $(BUILDDIR)/$(TARGET)-0x40000.bin + +all: $(OBJDIR) $(BUILDDIR) $(TARGET_FLASH) $(TARGET_IROM) + @echo Compilation successful + @echo Use \'make flash\' to flash firmware + +$(TARGET_FLASH) $(TARGET_IROM): $(TARGET_ELF) + $(ESPTOOL) elf2image $(FLASH_OPT) $^ --output $(BUILDDIR)/$(TARGET)- + +$(TARGET_ELF): $(OBJS) + $(LD) -L$(SDK_DIR)/lib $(LDFLAGS) $(LDLIBS) -o $@ + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@ + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(BUILDDIR): + mkdir -p $(BUILDDIR) + +flash: all + $(ESPTOOL) --port $(PORT) --baud $(BAUD) write_flash $(FLASH_OPT) 0x00000 $(TARGET_FLASH) 0x40000 $(TARGET_IROM) + +.PHONY: clean + +clean: + $(RM) -r $(OBJDIR) + $(RM) -r $(BUILDDIR) + +-include $(DEPS) diff --git a/firmwares/compass/ldscript.ld b/firmwares/compass/ldscript.ld new file mode 100644 index 0000000..585d0d1 --- /dev/null +++ b/firmwares/compass/ldscript.ld @@ -0,0 +1,214 @@ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40240000, len = 0x3C000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.sdk.version) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + + /** Libraries manually placed into IROM: libm.a, libc.a **/ + *libm.a:(.literal .text .literal.* .text.*) + *libc.a:(.literal .text .literal.* .text.*) + + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/firmwares/compass/src/buttons.c b/firmwares/compass/src/buttons.c new file mode 100644 index 0000000..4705d31 --- /dev/null +++ b/firmwares/compass/src/buttons.c @@ -0,0 +1,27 @@ +// System +#include <ets_sys.h> +#include <gpio.h> + +// Project +#include "buttons.h" + +void ICACHE_FLASH_ATTR buttons_init() { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5); + gpio_output_set(0, 0, 0, BIT4); + gpio_output_set(0, 0, 0, BIT5); + PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO4_U); + PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO5_U); +} + +bool ICACHE_FLASH_ATTR button_get(button_t btn) { + if (btn == BUTTON_UP) { + return !GPIO_INPUT_GET(4); + } else if (btn == BUTTON_DOWN) { + return !GPIO_INPUT_GET(5); + } else if (btn == BUTTON_CENTER) { + return !GPIO_INPUT_GET(4) && !GPIO_INPUT_GET(5); + } + + return false; +} diff --git a/firmwares/compass/src/buttons.h b/firmwares/compass/src/buttons.h new file mode 100644 index 0000000..46ca215 --- /dev/null +++ b/firmwares/compass/src/buttons.h @@ -0,0 +1,14 @@ +#ifndef _BUTTONS_H +#define _BUTTONS_H + +enum ButtonIdentifier { + BUTTON_UP, + BUTTON_DOWN, + BUTTON_CENTER +}; +typedef enum ButtonIdentifier button_t; + +void buttons_init(); +bool buttons_get(button_t btn); + +#endif diff --git a/firmwares/compass/src/font.h b/firmwares/compass/src/font.h new file mode 100644 index 0000000..fe9d9ca --- /dev/null +++ b/firmwares/compass/src/font.h @@ -0,0 +1,199 @@ +#ifndef _FONT_H +#define _FONT_H + +const unsigned char font_small[][6] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space + { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! + { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // " + { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # + { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ + { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // % + { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // & + { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( + { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) + { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * + { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // , + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // - + { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // . + { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // / + { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 + { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 + { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 + { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 + { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 + { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 + { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 + { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 + { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 + { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 + { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; + { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // < + { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // = + { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // > + { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? + { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ + { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C + { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F + { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G + { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H + { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I + { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J + { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K + { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L + { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M + { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P + { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q + { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R + { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S + { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T + { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U + { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V + { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W + { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X + { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y + { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z + { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ + { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // backslash + { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] + { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ + { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ + { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' + { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a + { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c + { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d + { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e + { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f + { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g + { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h + { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i + { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j + { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k + { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l + { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o + { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p + { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r + { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s + { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t + { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u + { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v + { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w + { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x + { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y + { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z + { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }, // horizontal lines +}; + +const unsigned char font_large[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space + { 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00 }, // ! + { 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // " + { 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00 }, // # + { 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00 }, // $ + { 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00 }, // % + { 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10 }, // & + { 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00 }, // ( + { 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00 }, // ) + { 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00 }, // * + { 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00 }, // + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 }, // , + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // - + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 }, // . + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00 }, // / + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // 0 + { 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // 1 + { 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00 }, // 2 + { 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 3 + { 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00 }, // 4 + { 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 5 + { 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 6 + { 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 }, // 7 + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00 }, // 8 + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00 }, // 9 + { 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00 }, // ; + { 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, // < + { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00 }, // = + { 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 }, // > + { 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00 }, // ? + { 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00 }, // @ + { 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20 }, // A + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // B + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00 }, // C + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // D + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00 }, // E + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00 }, // F + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00 }, // G + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20 }, // H + { 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // I + { 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00 }, // J + { 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00 }, // K + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00 }, // L + { 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00 }, // M + { 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00 }, // N + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // O + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00 }, // P + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00 }, // Q + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20 }, // R + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00 }, // S + { 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, // T + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, // U + { 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00 }, // V + { 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00 }, // W + { 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20 }, // X + { 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, // Y + { 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00 }, // Z + { 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00 }, // [ + { 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00 }, // backslash + { 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00 }, // ] + { 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ^ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, // _ + { 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ` + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20 }, // a + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // b + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00 }, // c + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20 }, // d + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00 }, // e + { 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // f + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00 }, // g + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, // h + { 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // i + { 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00 }, // j + { 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00 }, // k + { 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // l + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F }, // m + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, // n + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, // o + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // p + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80 }, // q + { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00 }, // r + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00 }, // s + { 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00 }, // t + { 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20 }, // u + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00 }, // v + { 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00 }, // w + { 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00 }, // x + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00 }, // y + { 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00 }, // z + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40 }, // { + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, // | + { 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00 }, // } + { 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ~ +}; + +#endif diff --git a/firmwares/compass/src/httpclient.c b/firmwares/compass/src/httpclient.c new file mode 100644 index 0000000..96a48c9 --- /dev/null +++ b/firmwares/compass/src/httpclient.c @@ -0,0 +1,483 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +// FIXME: sprintf->snprintf everywhere. +// FIXME: support null characters in responses. + +#include "osapi.h" +#include "user_interface.h" +#include "espconn.h" +#include "mem.h" +#include "limits.h" +#include "httpclient.h" + + +// Debug output. +#if 0 +#define PRINTF(...) os_printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +// Internal state. +typedef struct { + char * path; + int port; + char * post_data; + char * headers; + char * hostname; + char * buffer; + int buffer_size; + http_callback user_callback; +} request_args; + +static char * ICACHE_FLASH_ATTR esp_strdup(const char * str) +{ + if (str == NULL) { + return NULL; + } + char * new_str = (char *)os_malloc(os_strlen(str) + 1); // 1 for null character + if (new_str == NULL) { + os_printf("esp_strdup: malloc error"); + return NULL; + } + os_strcpy(new_str, str); + return new_str; +} + +static int ICACHE_FLASH_ATTR +esp_isupper(char c) +{ + return (c >= 'A' && c <= 'Z'); +} + +static int ICACHE_FLASH_ATTR +esp_isalpha(char c) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +} + + +static int ICACHE_FLASH_ATTR +esp_isspace(char c) +{ + return (c == ' ' || c == '\t' || c == '\n' || c == '\12'); +} + +static int ICACHE_FLASH_ATTR +esp_isdigit(char c) +{ + return (c >= '0' && c <= '9'); +} + +/* + * Convert a string to a long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long ICACHE_FLASH_ATTR +esp_strtol(nptr, endptr, base) + const char *nptr; + char **endptr; + int base; +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (esp_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } else if ((base == 0 || base == 2) && + c == '0' && (*s == 'b' || *s == 'B')) { + c = s[1]; + s += 2; + base = 2; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (esp_isdigit(c)) + c -= '0'; + else if (esp_isalpha(c)) + c -= esp_isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; +// errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + +static int ICACHE_FLASH_ATTR chunked_decode(const char * chunked, char * decode) +{ + int i = 0, j = 0; + int decode_size = 0; + char *str = (char *)chunked; + do + { + char * endstr = NULL; + //[chunk-size] + i = esp_strtol(str + j, endstr, 16); + PRINTF("Chunk Size:%d\r\n", i); + if (i <= 0) + break; + //[chunk-size-end-ptr] + endstr = (char *)os_strstr(str + j, "\r\n"); + //[chunk-ext] + j += endstr - (str + j); + //[CRLF] + j += 2; + //[chunk-data] + decode_size += i; + os_memcpy((char *)&decode[decode_size - i], (char *)str + j, i); + j += i; + //[CRLF] + j += 2; + } while(true); + + // + //footer CRLF + // + + return j; +} + +static void ICACHE_FLASH_ATTR receive_callback(void * arg, char * buf, unsigned short len) +{ + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + if (req->buffer == NULL) { + return; + } + + // Let's do the equivalent of a realloc(). + const int new_size = req->buffer_size + len; + char * new_buffer; + if (new_size > BUFFER_SIZE_MAX || NULL == (new_buffer = (char *)os_malloc(new_size))) { + os_printf("Response too long (%d)\n", new_size); + req->buffer[0] = '\0'; // Discard the buffer to avoid using an incomplete response. + espconn_disconnect(conn); + return; // The disconnect callback will be called. + } + + os_memcpy(new_buffer, req->buffer, req->buffer_size); + os_memcpy(new_buffer + req->buffer_size - 1 /*overwrite the null character*/, buf, len); // Append new data. + new_buffer[new_size - 1] = '\0'; // Make sure there is an end of string. + + os_free(req->buffer); + req->buffer = new_buffer; + req->buffer_size = new_size; +} + +static void ICACHE_FLASH_ATTR sent_callback(void * arg) +{ + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + if (req->post_data == NULL) { + PRINTF("All sent\n"); + } + else { + // The headers were sent, now send the contents. + PRINTF("Sending request body\n"); + espconn_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data)); + os_free(req->post_data); + req->post_data = NULL; + } +} + +static void ICACHE_FLASH_ATTR connect_callback(void * arg) +{ + PRINTF("Connected\n"); + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + espconn_regist_recvcb(conn, receive_callback); + espconn_regist_sentcb(conn, sent_callback); + + const char * method = "GET"; + char post_headers[32] = ""; + + if (req->post_data != NULL) { // If there is data this is a POST request. + method = "POST"; + os_sprintf(post_headers, "Content-Length: %d\r\n", strlen(req->post_data)); + } + + char buf[69 + strlen(method) + strlen(req->path) + strlen(req->hostname) + + strlen(req->headers) + strlen(post_headers)]; + int len = os_sprintf(buf, + "%s %s HTTP/1.1\r\n" + "Host: %s:%d\r\n" + "Connection: close\r\n" + "User-Agent: ESP8266\r\n" + "%s" + "%s" + "\r\n", + method, req->path, req->hostname, req->port, req->headers, post_headers); + + espconn_sent(conn, (uint8_t *)buf, len); + os_free(req->headers); + req->headers = NULL; + PRINTF("Sending request header\n"); +} + +static void ICACHE_FLASH_ATTR disconnect_callback(void * arg) +{ + PRINTF("Disconnected\n"); + struct espconn *conn = (struct espconn *)arg; + + if(conn == NULL) { + return; + } + + if(conn->proto.tcp != NULL) { + os_free(conn->proto.tcp); + } + if(conn->reverse != NULL) { + request_args * req = (request_args *)conn->reverse; + int http_status = -1; + char * body = ""; + if (req->buffer == NULL) { + os_printf("Buffer shouldn't be NULL\n"); + } + else if (req->buffer[0] != '\0') { + // FIXME: make sure this is not a partial response, using the Content-Length header. + + const char * version = "HTTP/1.1 "; + if (os_strncmp(req->buffer, version, strlen(version)) != 0) { + os_printf("Invalid version in %s\n", req->buffer); + } + else { + http_status = atoi(req->buffer + strlen(version)); + body = (char *)os_strstr(req->buffer, "\r\n\r\n") + 4; + if(os_strstr(req->buffer, "Transfer-Encoding: chunked")) + { + int body_size = req->buffer_size - (body - req->buffer); + char chunked_decode_buffer[body_size]; + os_memset(chunked_decode_buffer, 0, body_size); + // Chuncked data + chunked_decode(body, chunked_decode_buffer); + os_memcpy(body, chunked_decode_buffer, body_size); + } + } + } + + if (req->user_callback != NULL) { // Callback is optional. + req->user_callback(body, http_status, req->buffer); + } + + os_free(req->buffer); + os_free(req->hostname); + os_free(req->path); + os_free(req); + } + os_free(conn); +} + +static void ICACHE_FLASH_ATTR error_callback(void *arg, sint8 errType) +{ + PRINTF("Disconnected with error\n"); + disconnect_callback(arg); +} + +static void ICACHE_FLASH_ATTR dns_callback(const char * hostname, ip_addr_t * addr, void * arg) +{ + request_args * req = (request_args *)arg; + + if (addr == NULL) { + os_printf("DNS failed for %s\n", hostname); + if (req->user_callback != NULL) { + req->user_callback("", -1, ""); + } + os_free(req); + } + else { + PRINTF("DNS found %s " IPSTR "\n", hostname, IP2STR(addr)); + + struct espconn * conn = (struct espconn *)os_malloc(sizeof(struct espconn)); + conn->type = ESPCONN_TCP; + conn->state = ESPCONN_NONE; + conn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp)); + conn->proto.tcp->local_port = espconn_port(); + conn->proto.tcp->remote_port = req->port; + conn->reverse = req; + + os_memcpy(conn->proto.tcp->remote_ip, addr, 4); + + espconn_regist_connectcb(conn, connect_callback); + espconn_regist_disconcb(conn, disconnect_callback); + espconn_regist_reconcb(conn, error_callback); + + espconn_connect(conn); + } +} + +void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, const char * headers, http_callback user_callback) +{ + PRINTF("DNS request\n"); + + request_args * req = (request_args *)os_malloc(sizeof(request_args)); + req->hostname = esp_strdup(hostname); + req->path = esp_strdup(path); + req->port = port; + req->headers = esp_strdup(headers); + req->post_data = esp_strdup(post_data); + req->buffer_size = 1; + req->buffer = (char *)os_malloc(1); + req->buffer[0] = '\0'; // Empty string. + req->user_callback = user_callback; + + ip_addr_t addr; + err_t error = espconn_gethostbyname((struct espconn *)req, // It seems we don't need a real espconn pointer here. + hostname, &addr, dns_callback); + + if (error == ESPCONN_INPROGRESS) { + PRINTF("DNS pending\n"); + } + else if (error == ESPCONN_OK) { + // Already in the local names table (or hostname was an IP address), execute the callback ourselves. + dns_callback(hostname, &addr, req); + } + else { + if (error == ESPCONN_ARG) { + os_printf("DNS arg error %s\n", hostname); + } + else { + os_printf("DNS error code %d\n", error); + } + dns_callback(hostname, NULL, req); // Handle all DNS errors the same way. + } +} + +/* + * Parse an URL of the form http://host:port/path + * <host> can be a hostname or an IP address + * <port> is optional + */ +void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback) +{ + // FIXME: handle HTTP auth with http://user:pass@host/ + // FIXME: get rid of the #anchor part if present. + + char hostname[128] = ""; + int port = 80; + + bool is_http = os_strncmp(url, "http://", strlen("http://")) == 0; + + if (is_http) + url += strlen("http://"); // Get rid of the protocol. + else { + os_printf("URL is not HTTP or HTTPS %s\n", url); + return; + } + + char * path = os_strchr(url, '/'); + if (path == NULL) { + path = os_strchr(url, '\0'); // Pointer to end of string. + } + + char * colon = os_strchr(url, ':'); + if (colon > path) { + colon = NULL; // Limit the search to characters before the path. + } + + if (colon == NULL) { // The port is not present. + os_memcpy(hostname, url, path - url); + hostname[path - url] = '\0'; + } + else { + port = atoi(colon + 1); + if (port == 0) { + os_printf("Port error %s\n", url); + return; + } + + os_memcpy(hostname, url, colon - url); + hostname[colon - url] = '\0'; + } + + + if (path[0] == '\0') { // Empty path is not allowed. + path = "/"; + } + + PRINTF("hostname=%s\n", hostname); + PRINTF("port=%d\n", port); + PRINTF("path=%s\n", path); + http_raw_request(hostname, port, path, post_data, headers, user_callback); +} + +void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback user_callback) +{ + http_post(url, NULL, headers, user_callback); +} + +void ICACHE_FLASH_ATTR http_callback_example(char * response, int http_status, char * full_response) +{ + os_printf("http_status=%d\n", http_status); + if (http_status != HTTP_STATUS_GENERIC_ERROR) { + os_printf("strlen(full_response)=%d\n", strlen(full_response)); + os_printf("response=%s<EOF>\n", response); + } +} diff --git a/firmwares/compass/src/httpclient.h b/firmwares/compass/src/httpclient.h new file mode 100644 index 0000000..019f57f --- /dev/null +++ b/firmwares/compass/src/httpclient.h @@ -0,0 +1,50 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +#ifndef HTTPCLIENT_H +#define HTTPCLIENT_H + +#define HTTP_STATUS_GENERIC_ERROR -1 // In case of TCP or DNS error the callback is called with this status. +#define BUFFER_SIZE_MAX 5000 // Size of http responses that will cause an error. + +/* + * "full_response" is a string containing all response headers and the response body. + * "response_body and "http_status" are extracted from "full_response" for convenience. + * + * A successful request corresponds to an HTTP status code of 200 (OK). + * More info at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes + */ +typedef void (* http_callback)(char * response_body, int http_status, char * full_response); + +/* + * Download a web page from its URL. + * Try: + * http_get("http://wtfismyip.com/text", http_callback_example); + */ +void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback user_callback); + +/* + * Post data to a web form. + * The data should be encoded as application/x-www-form-urlencoded. + * Try: + * http_post("http://httpbin.org/post", "first_word=hello&second_word=world", http_callback_example); + */ +void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback); + +/* + * Call this function to skip URL parsing if the arguments are already in separate variables. + */ +void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, const char * headers, http_callback user_callback); + +/* + * Output on the UART. + */ +void http_callback_example(char * response, int http_status, char * full_response); + +#endif diff --git a/firmwares/compass/src/i2c_master.c b/firmwares/compass/src/i2c_master.c new file mode 100644 index 0000000..8da2611 --- /dev/null +++ b/firmwares/compass/src/i2c_master.c @@ -0,0 +1,316 @@ +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: i2c_master.c + * + * Description: i2c master API + * + * Modification history: + * 2014/3/12, v1.0 create this file. +*******************************************************************************/ +#include "ets_sys.h" +#include "osapi.h" +#include "gpio.h" + +#include "i2c_master.h" + +LOCAL uint8 m_nLastSDA; +LOCAL uint8 m_nLastSCL; + +/****************************************************************************** + * FunctionName : i2c_master_setDC + * Description : Internal used function - + * set i2c SDA and SCL bit value for half clk cycle + * Parameters : uint8 SDA + * uint8 SCL + * Returns : NONE +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +i2c_master_setDC(uint8 SDA, uint8 SCL) +{ + SDA &= 0x01; + SCL &= 0x01; + m_nLastSDA = SDA; + m_nLastSCL = SCL; + + if ((0 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_LOW(); + } else if ((0 == SDA) && (1 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_HIGH(); + } else if ((1 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_HIGH_SCL_LOW(); + } else { + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + } +} + +/****************************************************************************** + * FunctionName : i2c_master_getDC + * Description : Internal used function - + * get i2c SDA bit value + * Parameters : NONE + * Returns : uint8 - SDA bit value +*******************************************************************************/ +LOCAL uint8 ICACHE_FLASH_ATTR +i2c_master_getDC(void) +{ + uint8 sda_out; + sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)); + return sda_out; +} + +/****************************************************************************** + * FunctionName : i2c_master_init + * Description : initilize I2C bus to enable i2c operations + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_init(void) +{ + uint8 i; + + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + // when SCL = 0, toggle SDA to clear up + i2c_master_setDC(0, 0) ; + i2c_master_wait(5); + i2c_master_setDC(1, 0) ; + i2c_master_wait(5); + + // set data_cnt to max value + for (i = 0; i < 28; i++) { + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + } + + // reset all + i2c_master_stop(); + return; +} + +/****************************************************************************** + * FunctionName : i2c_master_gpio_init + * Description : config SDA and SCL gpio to open-drain output mode, + * mux and gpio num defined in i2c_master.h + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_gpio_init(void) +{ + ETS_GPIO_INTR_DISABLE() ; +// ETS_INTR_LOCK(); + + PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC); + PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC); + + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain; + GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SDA_GPIO)); + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain; + GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SCL_GPIO)); + + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + + ETS_GPIO_INTR_ENABLE() ; +// ETS_INTR_UNLOCK(); + + i2c_master_init(); +} + +/****************************************************************************** + * FunctionName : i2c_master_start + * Description : set i2c to send state + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_start(void) +{ + i2c_master_setDC(1, m_nLastSCL); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 +} + +/****************************************************************************** + * FunctionName : i2c_master_stop + * Description : set i2c to stop sending state + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_stop(void) +{ + i2c_master_wait(5); + + i2c_master_setDC(0, m_nLastSCL); + i2c_master_wait(5); // sda 0 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 +} + +/****************************************************************************** + * FunctionName : i2c_master_setAck + * Description : set ack to i2c bus as level value + * Parameters : uint8 level - 0 or 1 + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_setAck(uint8 level) +{ + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(level, 1); + i2c_master_wait(8); // sda level, scl 1 + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(1, 0); + i2c_master_wait(5); +} + +/****************************************************************************** + * FunctionName : i2c_master_getAck + * Description : confirm if peer send ack + * Parameters : NONE + * Returns : uint8 - ack value, 0 or 1 +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR +i2c_master_getAck(void) +{ + uint8 retVal; + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); + + retVal = i2c_master_getDC(); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + return retVal; +} + +/****************************************************************************** +* FunctionName : i2c_master_checkAck +* Description : get dev response +* Parameters : NONE +* Returns : true : get ack ; false : get nack +*******************************************************************************/ +bool ICACHE_FLASH_ATTR +i2c_master_checkAck(void) +{ + if(i2c_master_getAck()){ + return FALSE; + }else{ + return TRUE; + } +} + +/****************************************************************************** +* FunctionName : i2c_master_send_ack +* Description : response ack +* Parameters : NONE +* Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_send_ack(void) +{ + i2c_master_setAck(0x0); +} +/****************************************************************************** +* FunctionName : i2c_master_send_nack +* Description : response nack +* Parameters : NONE +* Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_send_nack(void) +{ + i2c_master_setAck(0x1); +} + +/****************************************************************************** + * FunctionName : i2c_master_readByte + * Description : read Byte from i2c bus + * Parameters : NONE + * Returns : uint8 - readed value +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR +i2c_master_readByte(void) +{ + uint8 retVal = 0; + uint8 k, i; + + i2c_master_wait(5); + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); // sda 1, scl 0 + + for (i = 0; i < 8; i++) { + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + + k = i2c_master_getDC(); + i2c_master_wait(5); + + if (i == 7) { + i2c_master_wait(3); //// + } + + k <<= (7 - i); + retVal |= k; + } + + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + + return retVal; +} + +/****************************************************************************** + * FunctionName : i2c_master_writeByte + * Description : write wrdata value(one byte) into i2c + * Parameters : uint8 wrdata - write value + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_writeByte(uint8 wrdata) +{ + uint8 dat; + sint8 i; + + i2c_master_wait(5); + + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + + for (i = 7; i >= 0; i--) { + dat = wrdata >> i; + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + i2c_master_setDC(dat, 1); + i2c_master_wait(5); + + if (i == 0) { + i2c_master_wait(3); //// + } + + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + } +} diff --git a/firmwares/compass/src/i2c_master.h b/firmwares/compass/src/i2c_master.h new file mode 100644 index 0000000..6e0c9f0 --- /dev/null +++ b/firmwares/compass/src/i2c_master.h @@ -0,0 +1,39 @@ +#ifndef __I2C_MASTER_H__ +#define __I2C_MASTER_H__ + +#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO2_U +#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_MTMS_U +#define I2C_MASTER_SDA_GPIO 2 +#define I2C_MASTER_SCL_GPIO 14 +#define I2C_MASTER_SDA_FUNC FUNC_GPIO2 +#define I2C_MASTER_SCL_FUNC FUNC_GPIO14 + +#define I2C_MASTER_SDA_HIGH_SCL_HIGH() \ + gpio_output_set(1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0) + +#define I2C_MASTER_SDA_HIGH_SCL_LOW() \ + gpio_output_set(1<<I2C_MASTER_SDA_GPIO, 1<<I2C_MASTER_SCL_GPIO, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0) + +#define I2C_MASTER_SDA_LOW_SCL_HIGH() \ + gpio_output_set(1<<I2C_MASTER_SCL_GPIO, 1<<I2C_MASTER_SDA_GPIO, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0) + +#define I2C_MASTER_SDA_LOW_SCL_LOW() \ + gpio_output_set(0, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 1<<I2C_MASTER_SDA_GPIO | 1<<I2C_MASTER_SCL_GPIO, 0) + +void i2c_master_gpio_init(void); +void i2c_master_init(void); + +#define i2c_master_wait os_delay_us +//#define i2c_master_wait +void i2c_master_stop(void); +void i2c_master_start(void); +void i2c_master_setAck(uint8 level); +uint8 i2c_master_getAck(void); +uint8 i2c_master_readByte(void); +void i2c_master_writeByte(uint8 wrdata); + +bool i2c_master_checkAck(void); +void i2c_master_send_ack(void); +void i2c_master_send_nack(void); + +#endif diff --git a/firmwares/compass/src/i2cdevice.c b/firmwares/compass/src/i2cdevice.c new file mode 100644 index 0000000..6417bbf --- /dev/null +++ b/firmwares/compass/src/i2cdevice.c @@ -0,0 +1,118 @@ +// System +#include <ets_sys.h> +#include <osapi.h> + +// Project +#include "i2c_master.h" +#include "util.h" + +#define I2C_ADDR_W(addr) ((addr<<1)) +#define I2C_ADDR_R(addr) ((addr<<1) | 0x01) + +bool ICACHE_FLASH_ATTR i2cdevice_read(uint8_t devaddr, uint8_t regaddr, uint8_t len, uint8_t *data) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(I2C_ADDR_W(devaddr)); + if (i2c_master_getAck()) { + os_printf("I²C device %x R: no ACK for write addr\r\n", devaddr); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("I²C device %x R: no ACK for register\r\n", devaddr); + i2c_master_stop(); + return false; + } + + i2c_master_start(); + + // Write I²C Address for reading + i2c_master_writeByte(I2C_ADDR_R(devaddr)); + if (i2c_master_getAck()) { + os_printf("I²C device %x R: no ACK for read addr\r\n", devaddr); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + data[i] = i2c_master_readByte(); + if (i != len - 1) + i2c_master_send_ack(); + else + i2c_master_send_nack(); + } + + i2c_master_stop(); + //os_printf("Just read %x from %x\r\n", *data, regaddr); + + return true; +} + +bool ICACHE_FLASH_ATTR i2cdevice_write(uint8_t devaddr, uint8_t regaddr, uint8_t len, uint8_t *data) { + //os_printf("Writing %x to %x\r\n", *data, regaddr); + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(I2C_ADDR_W(devaddr)); + if (i2c_master_getAck()) { + os_printf("I²C device %x W: no ACK for write addr\r\n", devaddr); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("I²C device %x W: no ACK for register\r\n", devaddr); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + i2c_master_writeByte(data[i]); + if (i2c_master_getAck()) { + os_printf("I²C device %x W: no ACK for datawrite\r\n", devaddr); + i2c_master_stop(); + return false; + } + } + + i2c_master_stop(); + + return true; +} + +// Single-byte operations +inline bool i2cdevice_writebyte(uint8_t devaddr, uint8_t regaddr, uint8_t data) { + return i2cdevice_write(devaddr, regaddr, 1, &data); +} + +inline bool i2cdevice_readbyte(uint8_t devaddr, uint8_t regaddr, uint8_t *data) { + return i2cdevice_read(devaddr, regaddr, 1, data); +} + +// Get bit in any register +bool ICACHE_FLASH_ATTR i2cdevice_readbit(uint8_t devaddr, uint8_t regaddr, uint8_t bit, bool *val) { + uint8_t dat; + if (!i2cdevice_read(devaddr, regaddr, 1, &dat)) return false; + *val = (gbi(dat, bit) != false); + return true; +} + +// Set bit in any register +bool ICACHE_FLASH_ATTR i2cdevice_writebit(uint8_t devaddr, uint8_t regaddr, uint8_t bit, bool val) { + uint8_t dat; + if (!i2cdevice_read(devaddr, regaddr, 1, &dat)) return false; + if (val) + sbi(dat, bit); + else + cbi(dat, bit); + if (!i2cdevice_write(devaddr, regaddr, 1, &dat)) return false; + return true; +} diff --git a/firmwares/compass/src/i2cdevice.h b/firmwares/compass/src/i2cdevice.h new file mode 100644 index 0000000..c49dc74 --- /dev/null +++ b/firmwares/compass/src/i2cdevice.h @@ -0,0 +1,16 @@ +#include <ets_sys.h> + +#ifndef _I2CUTIL_H +#define _I2CUTIL_H + +// Most I²C devices use a commons protocol for reading / writing registers, e.g. MPU-9250 and the integrated AK8963 +bool i2cdevice_read(uint8_t regaddr, uint8_t len, uint8_t *data); +bool i2cdevice_write(uint8_t regaddr, uint8_t len, uint8_t *data); + +inline bool i2cdevice_writebyte(uint8_t devaddr, uint8_t regaddr, uint8_t data); +inline bool i2cdevice_readbyte(uint8_t devaddr, uint8_t regaddr, uint8_t *data); + +bool i2cdevice_readbit(uint8_t regaddr, uint8_t bit, bool *val); +bool i2cdevice_writebit(uint8_t regaddr, uint8_t bit, bool val); + +#endif diff --git a/firmwares/compass/src/main.c b/firmwares/compass/src/main.c new file mode 100644 index 0000000..2773d31 --- /dev/null +++ b/firmwares/compass/src/main.c @@ -0,0 +1,114 @@ +// System +#include <user_interface.h> +#include <math.h> +#include <os_type.h> +#include <ets_sys.h> +#include <osapi.h> +#include <gpio.h> + +// Configuration +#include "user_config.h" + +// Project +#include "httpclient.h" +#include "i2c_master.h" +#include "buttons.h" +#include "mpu9250.h" +#include "ssd1306.h" +#include "rv3029.h" +#include "vector.h" +#include "util.h" + +os_timer_t magnet_timer; +vec3f calib_bias; + +#define COMPASS_CENTER_X 32 +#define COMPASS_CENTER_Y 32 +#define COMPASS_RADIUS 30 +void ICACHE_FLASH_ATTR compass_draw(float angle) { + float a; + ssd1306_setpixel(COMPASS_CENTER_X, COMPASS_CENTER_Y, true); + ssd1306_setpixel(COMPASS_CENTER_X + 1, COMPASS_CENTER_Y, true); + ssd1306_setpixel(COMPASS_CENTER_X, COMPASS_CENTER_Y + 1, true); + ssd1306_setpixel(COMPASS_CENTER_X - 1, COMPASS_CENTER_Y, true); + ssd1306_setpixel(COMPASS_CENTER_X, COMPASS_CENTER_Y - 1, true); + + for (a = angle; a < angle + 2 * PI; a += PI / 8) { + float startx = ((a == angle) ? COMPASS_RADIUS - 15 : COMPASS_RADIUS - 5) * sin(a) + COMPASS_CENTER_X; + float starty = -((a == angle) ? COMPASS_RADIUS - 15 : COMPASS_RADIUS - 5) * cos(a) + COMPASS_CENTER_Y; + float endx = COMPASS_RADIUS * sin(a) + COMPASS_CENTER_X; + float endy = -COMPASS_RADIUS * cos(a) + COMPASS_CENTER_Y; + if (a == angle) + ssd1306_text_small(startx - 3 - (endx - startx) / 2, starty - 4 - (endy - starty) / 2, "N"); + ssd1306_line(startx, starty, endx, endy, true); + } +} + +void ICACHE_FLASH_ATTR magnet_timer_cb() { + vec3s16 field; + ak8963_get_field(&field); + field.x -= calib_bias.x; + field.y -= calib_bias.y; + field.z -= calib_bias.z; + //os_printf("Measurement: { x = %d, y = %d, z = %d }\r\n", (int16_t)(field.x), (int16_t)(field.y), (int16_t)(field.z)); + angles2f north = vec3s16_to_angles2f(field); + //os_printf("North: { yaw = %d, pitch = %d }\r\n", (int16_t)(north.yaw * 180 / PI), (int16_t)(north.pitch * 180 / PI)); + ak8963_set_opmode(AK8963_SINGLE, AK8963_16BIT); + + ssd1306_clear(); + compass_draw(north.yaw); + ssd1306_line(70, 0, 70, 63, true); + ssd1306_text_small(75, 24, "Inclin.:"); + char incdeg[6]; + os_sprintf(incdeg, "%d°", (int16_t)(north.pitch * 180 / PI)); + ssd1306_text_small(75, 32, incdeg); + ssd1306_flip(); +} + +void ICACHE_FLASH_ATTR on_ak8963_calibration(vec3f bias) { + os_printf("Bias: { x = %d, y = %d, z = %d }\r\n", (int16_t)bias.x, (int16_t)bias.y, (int16_t)bias.z); + calib_bias.x = bias.x; + calib_bias.y = bias.y; + calib_bias.z = bias.z; + + /*** WiFi sleep ***/ + wifi_station_disconnect(); + wifi_set_opmode(NULL_MODE); + wifi_fpm_set_sleep_type(MODEM_SLEEP_T); + wifi_fpm_open(); + wifi_fpm_do_sleep(0xfffffff); + + os_timer_setfn(&magnet_timer, (os_timer_func_t *)magnet_timer_cb, NULL); + os_timer_arm(&magnet_timer, 300, true); +} + +void ICACHE_FLASH_ATTR user_init(void) { + uart_div_modify(0, UART_CLK_FREQ / BAUD); + + wifi_set_opmode(STATION_MODE); + wifi_station_connect(); + + /*** I²C init ***/ + i2c_master_gpio_init(); + mpu9250_init(); + ak8963_init(); + + os_delay_us(10000); + i2c_scanbus(); + + /*** LCD Init ***/ + ssd1306_init(0); + ssd1306_text_small(10, 10, "Init..."); + ssd1306_flip(); + + // ~Charge input + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); + gpio_output_set(0, 0, 0, BIT13); + + // Button inputs + buttons_init(); + + ak8963_calibration_start(10000, on_ak8963_calibration); + + os_printf("Startup\r\n"); +} diff --git a/firmwares/compass/src/mpu9250.c b/firmwares/compass/src/mpu9250.c new file mode 100644 index 0000000..d1cff79 --- /dev/null +++ b/firmwares/compass/src/mpu9250.c @@ -0,0 +1,146 @@ +// System +#include <ets_sys.h> +#include <os_type.h> +#include <osapi.h> + +// Project +#include "mpu9250_reg.h" +#include "i2c_master.h" +#include "mpu9250.h" +#include "vector.h" +#include "util.h" + +/*** Internal I²C functions ***/ +#define mpu9250_write(regaddr, len, data) (i2cdevice_write(MPU9250_ADDR, regaddr, len, data)) +#define mpu9250_read(regaddr, len, data) (i2cdevice_read(MPU9250_ADDR, regaddr, len, data)) +#define mpu9250_readbyte(regaddr, data) (i2cdevice_readbyte(MPU9250_ADDR, regaddr, data)) +#define mpu9250_writebyte(regaddr, data) (i2cdevice_writebyte(MPU9250_ADDR, regaddr, data)) +#define mpu9250_readbit(regaddr, bit, val) (i2cdevice_readbit(MPU9250_ADDR, regaddr, bit, val)) +#define mpu9250_writebit(regaddr, bit, val) (i2cdevice_writebit(MPU9250_ADDR, regaddr, bit, val)) + +#define ak8963_write(regaddr, len, data) (i2cdevice_write(AK8963_ADDR, regaddr, len, data)) +#define ak8963_read(regaddr, len, data) (i2cdevice_read(AK8963_ADDR, regaddr, len, data)) +#define ak8963_readbyte(regaddr, data) (i2cdevice_readbyte(AK8963_ADDR, regaddr, data)) +#define ak8963_writebyte(regaddr, data) (i2cdevice_writebyte(AK8963_ADDR, regaddr, data)) +#define ak8963_readbit(regaddr, bit, val) (i2cdevice_readbit(AK8963_ADDR, regaddr, bit, val)) +#define ak8963_writebit(regaddr, bit, val) (i2cdevice_writebit(AK8963_ADDR, regaddr, bit, val)) + +/*** Common ***/ +/* + * Initialize to configuration used in this project: + * - Reset MPU-9250 and restore sane defaults + * - Some dummy reads to ensure communication works + * - Enable I²C Bypass to Compass + */ +void ICACHE_FLASH_ATTR mpu9250_init() { + // Reset MPU-9250 + mpu9250_writebyte(MPU9250_RA_PWR_MGMT_1, 1<<MPU9250_PWR1_DEVICE_RESET_BIT); + os_delay_us(10000); + + // Select clock source, enable accelerometer and gyrometer, + mpu9250_writebyte(MPU9250_RA_PWR_MGMT_1, 0x01); + mpu9250_writebyte(MPU9250_RA_PWR_MGMT_2, 0x00); + + // Dummy read: + uint8_t id; + mpu9250_read(MPU9250_RA_WHO_AM_I, 1, &id); + os_printf("MPU9250 WHOAMI: %x\r\n", id); + + // I²C Bypass: + mpu9250_i2cbypass_set(true); + os_delay_us(1000); +} + +void ICACHE_FLASH_ATTR mpu9250_i2cbypass_set(bool active) { + mpu9250_writebit(MPU9250_RA_INT_PIN_CFG, MPU9250_INTCFG_I2C_BYPASS_EN_BIT, active); +} + +/*** Compass: ***/ +bool ICACHE_FLASH_ATTR ak8963_init() { + // Reset device + if (!ak8963_writebyte(AK8963_RA_CNTL2, 1)) return false; + os_delay_us(1000); + + uint8_t wia; + ak8963_readbyte(AK8963_RA_WIA, &wia); + if (!os_printf("AK8963 WIA: %x\r\n", wia)) return false; + + return true; +} + +bool ICACHE_FLASH_ATTR ak8963_set_opmode(enum ak8963_opmode mode, enum ak8963_bitwidth width) { + return ak8963_writebyte(AK8963_RA_CNTL1, mode | width); +} + +bool ICACHE_FLASH_ATTR ak8963_get_drdy(bool *drdy) { + return ak8963_readbit(AK8963_RA_ST1, 0, drdy); +} + +bool ICACHE_FLASH_ATTR ak8963_get_field(vec3s16 *measurement) { + uint8_t buffer[6]; + if (!ak8963_read(AK8963_RA_HXL, 6, buffer)) return false; + measurement->x = (((int16_t)buffer[1]) << 8) | buffer[0]; + measurement->y = (((int16_t)buffer[3]) << 8) | buffer[2]; + measurement->z = (((int16_t)buffer[5]) << 8) | buffer[4]; + + return true; +} + +/*** Compass Calibration: ***/ +struct ak8963_calib_proc { + os_timer_t datatimer; + os_timer_t completetimer; + vec3s16 maximum; + vec3s16 minimum; + ak8963_calibration_callback complete; +}; + +void ICACHE_FLASH_ATTR ak8963_calibration_datatimer_cb(struct ak8963_calib_proc *proc) { + bool drdy; + ak8963_get_drdy(&drdy); + if (!drdy) return; + + vec3s16 field; + if (!ak8963_get_field(&field)) return; + + // Store maximum and minimum magnetic values + if (field.x > proc->maximum.x) proc->maximum.x = field.x; + if (field.y > proc->maximum.y) proc->maximum.y = field.y; + if (field.z > proc->maximum.z) proc->maximum.z = field.z; + + if (field.x < proc->minimum.x) proc->minimum.x = field.x; + if (field.y < proc->minimum.y) proc->minimum.y = field.y; + if (field.z < proc->minimum.z) proc->minimum.z = field.z; + + ak8963_set_opmode(AK8963_SINGLE, AK8963_16BIT); +} + +void ICACHE_FLASH_ATTR ak8963_calibration_completetimer_cb(struct ak8963_calib_proc *proc) { + os_timer_disarm(proc->datatimer); + + os_printf("Maximum: %d, %d, %d\r\n", proc->maximum.x, proc->maximum.y, proc->maximum.z); + os_printf("Minimum: %d, %d, %d\r\n", proc->minimum.x, proc->minimum.y, proc->minimum.z); + + vec3f bias; + bias.x = (proc->maximum.x + proc->minimum.x) / 2.f; + bias.y = (proc->maximum.y + proc->minimum.y) / 2.f; + bias.z = (proc->maximum.z + proc->minimum.z) / 2.f; + + proc->complete(bias); +} + +void ICACHE_FLASH_ATTR ak8963_calibration_start(uint16_t milliseconds, ak8963_calibration_callback cb) { + static struct ak8963_calib_proc proc; + + proc.complete = cb; + proc.maximum.x = 0x8000; proc.maximum.y = 0x8000; proc.maximum.z = 0x8000; + proc.minimum.x = 0x7fff; proc.minimum.y = 0x7fff; proc.minimum.z = 0x7fff; + + os_timer_setfn(&proc.datatimer, (os_timer_func_t *)ak8963_calibration_datatimer_cb, &proc); + os_timer_arm(&proc.datatimer, AK8963_CALIB_INTERVAL, true); + + os_timer_setfn(&proc.completetimer, (os_timer_func_t *)ak8963_calibration_completetimer_cb, &proc); + os_timer_arm(&proc.completetimer, milliseconds, false); + + ak8963_set_opmode(AK8963_SINGLE, AK8963_16BIT); +} diff --git a/firmwares/compass/src/mpu9250.h b/firmwares/compass/src/mpu9250.h new file mode 100644 index 0000000..231095d --- /dev/null +++ b/firmwares/compass/src/mpu9250.h @@ -0,0 +1,39 @@ +#include <ets_sys.h> + +#include "vector.h" + +#ifndef _MPU9250_H +#define _MPU9250_H + +// Configuration - Addresses include write/read bit +#define MPU9250_ADDR 0x68 +#define AK8963_ADDR 0x0c +#define AK8963_CALIB_INTERVAL 10 + +/*** Common ***/ +void mpu9250_init(); +void mpu9250_i2cbypass_set(bool active); + +/*** Compass: ***/ +enum ak8963_opmode { + AK8963_PWRDOWN = 0, + AK8963_SINGLE = 1, + AK8963_8HZ = 2, + AK8963_100HZ = 6, + AK8963_SELFTEST = 8, + AK8963_FUSEACCESS = 15 +}; + +enum ak8963_bitwidth { + AK8963_14BIT = 0, + AK8963_16BIT = (1<<4) +}; + +typedef void (*ak8963_calibration_callback)(vec3f bias); + +bool ak8963_init(); +bool ak8963_set_opmode(enum ak8963_opmode mode, enum ak8963_bitwidth width); +bool ak8963_get_drdy(bool *drdy); +bool ak8963_get_field(vec3s16 *measurement); + +#endif diff --git a/firmwares/compass/src/mpu9250_reg.h b/firmwares/compass/src/mpu9250_reg.h new file mode 100644 index 0000000..14860b3 --- /dev/null +++ b/firmwares/compass/src/mpu9250_reg.h @@ -0,0 +1,388 @@ +/* + * From https://github.com/Seeed-Studio/IMU_10DOF/blob/master/MPU9250.h, originally from I²Cdevlib (http://i2cdevlib.com) + * Modified, removed everything but the register addresses and added some AK8963 registers. Documented in the MPU-9250 Register Map: + * http://www.invensense.com/products/motion-tracking/9-axis/mpu-9250/ + * + * ============================================ + * I2Cdev device library code is placed under the MIT license + * Copyright (c) 2012 Jeff Rowberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * =============================================== + */ + +//Magnetometer Registers +#define AK8963_RA_WIA 0x00 +#define AK8963_RA_INFO 0x01 +#define AK8963_RA_ST1 0x02 +#define AK8963_RA_HXL 0x03 +#define AK8963_RA_HXH 0x04 +#define AK8963_RA_HYL 0x05 +#define AK8963_RA_HYH 0x06 +#define AK8963_RA_HZL 0x07 +#define AK8963_RA_HZH 0x08 +#define AK8963_RA_CNTL1 0x0a +#define AK8963_RA_CNTL2 0x0b +#define AK8963_RA_ASTC 0x0c +#define AK8963_RA_I2CDIS 0x0f +#define AK8963_RA_ASAX 0x10 +#define AK8963_RA_ASAY 0x11 +#define AK8963_RA_ASAZ 0x12 + +#define MPU9250_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9250_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9250_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9250_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU9250_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU9250_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU9250_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU9250_RA_XA_OFFS_L_TC 0x07 +#define MPU9250_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU9250_RA_YA_OFFS_L_TC 0x09 +#define MPU9250_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU9250_RA_ZA_OFFS_L_TC 0x0B +#define MPU9250_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU9250_RA_XG_OFFS_USRL 0x14 +#define MPU9250_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU9250_RA_YG_OFFS_USRL 0x16 +#define MPU9250_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU9250_RA_ZG_OFFS_USRL 0x18 +#define MPU9250_RA_SMPLRT_DIV 0x19 +#define MPU9250_RA_CONFIG 0x1A +#define MPU9250_RA_GYRO_CONFIG 0x1B +#define MPU9250_RA_ACCEL_CONFIG 0x1C +#define MPU9250_RA_FF_THR 0x1D +#define MPU9250_RA_FF_DUR 0x1E +#define MPU9250_RA_MOT_THR 0x1F +#define MPU9250_RA_MOT_DUR 0x20 +#define MPU9250_RA_ZRMOT_THR 0x21 +#define MPU9250_RA_ZRMOT_DUR 0x22 +#define MPU9250_RA_FIFO_EN 0x23 +#define MPU9250_RA_I2C_MST_CTRL 0x24 +#define MPU9250_RA_I2C_SLV0_ADDR 0x25 +#define MPU9250_RA_I2C_SLV0_REG 0x26 +#define MPU9250_RA_I2C_SLV0_CTRL 0x27 +#define MPU9250_RA_I2C_SLV1_ADDR 0x28 +#define MPU9250_RA_I2C_SLV1_REG 0x29 +#define MPU9250_RA_I2C_SLV1_CTRL 0x2A +#define MPU9250_RA_I2C_SLV2_ADDR 0x2B +#define MPU9250_RA_I2C_SLV2_REG 0x2C +#define MPU9250_RA_I2C_SLV2_CTRL 0x2D +#define MPU9250_RA_I2C_SLV3_ADDR 0x2E +#define MPU9250_RA_I2C_SLV3_REG 0x2F +#define MPU9250_RA_I2C_SLV3_CTRL 0x30 +#define MPU9250_RA_I2C_SLV4_ADDR 0x31 +#define MPU9250_RA_I2C_SLV4_REG 0x32 +#define MPU9250_RA_I2C_SLV4_DO 0x33 +#define MPU9250_RA_I2C_SLV4_CTRL 0x34 +#define MPU9250_RA_I2C_SLV4_DI 0x35 +#define MPU9250_RA_I2C_MST_STATUS 0x36 +#define MPU9250_RA_INT_PIN_CFG 0x37 +#define MPU9250_RA_INT_ENABLE 0x38 +#define MPU9250_RA_DMP_INT_STATUS 0x39 +#define MPU9250_RA_INT_STATUS 0x3A +#define MPU9250_RA_ACCEL_XOUT_H 0x3B +#define MPU9250_RA_ACCEL_XOUT_L 0x3C +#define MPU9250_RA_ACCEL_YOUT_H 0x3D +#define MPU9250_RA_ACCEL_YOUT_L 0x3E +#define MPU9250_RA_ACCEL_ZOUT_H 0x3F +#define MPU9250_RA_ACCEL_ZOUT_L 0x40 +#define MPU9250_RA_TEMP_OUT_H 0x41 +#define MPU9250_RA_TEMP_OUT_L 0x42 +#define MPU9250_RA_GYRO_XOUT_H 0x43 +#define MPU9250_RA_GYRO_XOUT_L 0x44 +#define MPU9250_RA_GYRO_YOUT_H 0x45 +#define MPU9250_RA_GYRO_YOUT_L 0x46 +#define MPU9250_RA_GYRO_ZOUT_H 0x47 +#define MPU9250_RA_GYRO_ZOUT_L 0x48 +#define MPU9250_RA_EXT_SENS_DATA_00 0x49 +#define MPU9250_RA_EXT_SENS_DATA_01 0x4A +#define MPU9250_RA_EXT_SENS_DATA_02 0x4B +#define MPU9250_RA_EXT_SENS_DATA_03 0x4C +#define MPU9250_RA_EXT_SENS_DATA_04 0x4D +#define MPU9250_RA_EXT_SENS_DATA_05 0x4E +#define MPU9250_RA_EXT_SENS_DATA_06 0x4F +#define MPU9250_RA_EXT_SENS_DATA_07 0x50 +#define MPU9250_RA_EXT_SENS_DATA_08 0x51 +#define MPU9250_RA_EXT_SENS_DATA_09 0x52 +#define MPU9250_RA_EXT_SENS_DATA_10 0x53 +#define MPU9250_RA_EXT_SENS_DATA_11 0x54 +#define MPU9250_RA_EXT_SENS_DATA_12 0x55 +#define MPU9250_RA_EXT_SENS_DATA_13 0x56 +#define MPU9250_RA_EXT_SENS_DATA_14 0x57 +#define MPU9250_RA_EXT_SENS_DATA_15 0x58 +#define MPU9250_RA_EXT_SENS_DATA_16 0x59 +#define MPU9250_RA_EXT_SENS_DATA_17 0x5A +#define MPU9250_RA_EXT_SENS_DATA_18 0x5B +#define MPU9250_RA_EXT_SENS_DATA_19 0x5C +#define MPU9250_RA_EXT_SENS_DATA_20 0x5D +#define MPU9250_RA_EXT_SENS_DATA_21 0x5E +#define MPU9250_RA_EXT_SENS_DATA_22 0x5F +#define MPU9250_RA_EXT_SENS_DATA_23 0x60 +#define MPU9250_RA_MOT_DETECT_STATUS 0x61 +#define MPU9250_RA_I2C_SLV0_DO 0x63 +#define MPU9250_RA_I2C_SLV1_DO 0x64 +#define MPU9250_RA_I2C_SLV2_DO 0x65 +#define MPU9250_RA_I2C_SLV3_DO 0x66 +#define MPU9250_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU9250_RA_SIGNAL_PATH_RESET 0x68 +#define MPU9250_RA_MOT_DETECT_CTRL 0x69 +#define MPU9250_RA_USER_CTRL 0x6A +#define MPU9250_RA_PWR_MGMT_1 0x6B +#define MPU9250_RA_PWR_MGMT_2 0x6C +#define MPU9250_RA_BANK_SEL 0x6D +#define MPU9250_RA_MEM_START_ADDR 0x6E +#define MPU9250_RA_MEM_R_W 0x6F +#define MPU9250_RA_DMP_CFG_1 0x70 +#define MPU9250_RA_DMP_CFG_2 0x71 +#define MPU9250_RA_FIFO_COUNTH 0x72 +#define MPU9250_RA_FIFO_COUNTL 0x73 +#define MPU9250_RA_FIFO_R_W 0x74 +#define MPU9250_RA_WHO_AM_I 0x75 + +#define MPU9250_TC_PWR_MODE_BIT 7 +#define MPU9250_TC_OFFSET_BIT 6 +#define MPU9250_TC_OFFSET_LENGTH 6 +#define MPU9250_TC_OTP_BNK_VLD_BIT 0 + +#define MPU9250_VDDIO_LEVEL_VLOGIC 0 +#define MPU9250_VDDIO_LEVEL_VDD 1 + +#define MPU9250_CFG_EXT_SYNC_SET_BIT 5 +#define MPU9250_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU9250_CFG_DLPF_CFG_BIT 2 +#define MPU9250_CFG_DLPF_CFG_LENGTH 3 + +#define MPU9250_EXT_SYNC_DISABLED 0x0 +#define MPU9250_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU9250_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU9250_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU9250_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU9250_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU9250_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU9250_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU9250_DLPF_BW_256 0x00 +#define MPU9250_DLPF_BW_188 0x01 +#define MPU9250_DLPF_BW_98 0x02 +#define MPU9250_DLPF_BW_42 0x03 +#define MPU9250_DLPF_BW_20 0x04 +#define MPU9250_DLPF_BW_10 0x05 +#define MPU9250_DLPF_BW_5 0x06 + +#define MPU9250_GCONFIG_FS_SEL_BIT 4 +#define MPU9250_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU9250_GYRO_FS_250 0x00 +#define MPU9250_GYRO_FS_500 0x01 +#define MPU9250_GYRO_FS_1000 0x02 +#define MPU9250_GYRO_FS_2000 0x03 + +#define MPU9250_ACONFIG_XA_ST_BIT 7 +#define MPU9250_ACONFIG_YA_ST_BIT 6 +#define MPU9250_ACONFIG_ZA_ST_BIT 5 +#define MPU9250_ACONFIG_AFS_SEL_BIT 4 +#define MPU9250_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU9250_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU9250_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU9250_ACCEL_FS_2 0x00 +#define MPU9250_ACCEL_FS_4 0x01 +#define MPU9250_ACCEL_FS_8 0x02 +#define MPU9250_ACCEL_FS_16 0x03 + +#define MPU9250_DHPF_RESET 0x00 +#define MPU9250_DHPF_5 0x01 +#define MPU9250_DHPF_2P5 0x02 +#define MPU9250_DHPF_1P25 0x03 +#define MPU9250_DHPF_0P63 0x04 +#define MPU9250_DHPF_HOLD 0x07 + +#define MPU9250_TEMP_FIFO_EN_BIT 7 +#define MPU9250_XG_FIFO_EN_BIT 6 +#define MPU9250_YG_FIFO_EN_BIT 5 +#define MPU9250_ZG_FIFO_EN_BIT 4 +#define MPU9250_ACCEL_FIFO_EN_BIT 3 +#define MPU9250_SLV2_FIFO_EN_BIT 2 +#define MPU9250_SLV1_FIFO_EN_BIT 1 +#define MPU9250_SLV0_FIFO_EN_BIT 0 + +#define MPU9250_MULT_MST_EN_BIT 7 +#define MPU9250_WAIT_FOR_ES_BIT 6 +#define MPU9250_SLV_3_FIFO_EN_BIT 5 +#define MPU9250_I2C_MST_P_NSR_BIT 4 +#define MPU9250_I2C_MST_CLK_BIT 3 +#define MPU9250_I2C_MST_CLK_LENGTH 4 + +#define MPU9250_CLOCK_DIV_348 0x0 +#define MPU9250_CLOCK_DIV_333 0x1 +#define MPU9250_CLOCK_DIV_320 0x2 +#define MPU9250_CLOCK_DIV_308 0x3 +#define MPU9250_CLOCK_DIV_296 0x4 +#define MPU9250_CLOCK_DIV_286 0x5 +#define MPU9250_CLOCK_DIV_276 0x6 +#define MPU9250_CLOCK_DIV_267 0x7 +#define MPU9250_CLOCK_DIV_258 0x8 +#define MPU9250_CLOCK_DIV_500 0x9 +#define MPU9250_CLOCK_DIV_471 0xA +#define MPU9250_CLOCK_DIV_444 0xB +#define MPU9250_CLOCK_DIV_421 0xC +#define MPU9250_CLOCK_DIV_400 0xD +#define MPU9250_CLOCK_DIV_381 0xE +#define MPU9250_CLOCK_DIV_364 0xF + +#define MPU9250_I2C_SLV_RW_BIT 7 +#define MPU9250_I2C_SLV_ADDR_BIT 6 +#define MPU9250_I2C_SLV_ADDR_LENGTH 7 +#define MPU9250_I2C_SLV_EN_BIT 7 +#define MPU9250_I2C_SLV_BYTE_SW_BIT 6 +#define MPU9250_I2C_SLV_REG_DIS_BIT 5 +#define MPU9250_I2C_SLV_GRP_BIT 4 +#define MPU9250_I2C_SLV_LEN_BIT 3 +#define MPU9250_I2C_SLV_LEN_LENGTH 4 + +#define MPU9250_I2C_SLV4_RW_BIT 7 +#define MPU9250_I2C_SLV4_ADDR_BIT 6 +#define MPU9250_I2C_SLV4_ADDR_LENGTH 7 +#define MPU9250_I2C_SLV4_EN_BIT 7 +#define MPU9250_I2C_SLV4_INT_EN_BIT 6 +#define MPU9250_I2C_SLV4_REG_DIS_BIT 5 +#define MPU9250_I2C_SLV4_MST_DLY_BIT 4 +#define MPU9250_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU9250_MST_PASS_THROUGH_BIT 7 +#define MPU9250_MST_I2C_SLV4_DONE_BIT 6 +#define MPU9250_MST_I2C_LOST_ARB_BIT 5 +#define MPU9250_MST_I2C_SLV4_NACK_BIT 4 +#define MPU9250_MST_I2C_SLV3_NACK_BIT 3 +#define MPU9250_MST_I2C_SLV2_NACK_BIT 2 +#define MPU9250_MST_I2C_SLV1_NACK_BIT 1 +#define MPU9250_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU9250_INTCFG_INT_LEVEL_BIT 7 +#define MPU9250_INTCFG_INT_OPEN_BIT 6 +#define MPU9250_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU9250_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU9250_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU9250_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU9250_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU9250_INTMODE_ACTIVEHIGH 0x00 +#define MPU9250_INTMODE_ACTIVELOW 0x01 + +#define MPU9250_INTDRV_PUSHPULL 0x00 +#define MPU9250_INTDRV_OPENDRAIN 0x01 + +#define MPU9250_INTLATCH_50USPULSE 0x00 +#define MPU9250_INTLATCH_WAITCLEAR 0x01 + +#define MPU9250_INTCLEAR_STATUSREAD 0x00 +#define MPU9250_INTCLEAR_ANYREAD 0x01 + +#define MPU9250_INTERRUPT_FF_BIT 7 +#define MPU9250_INTERRUPT_MOT_BIT 6 +#define MPU9250_INTERRUPT_ZMOT_BIT 5 +#define MPU9250_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU9250_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU9250_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU9250_INTERRUPT_DMP_INT_BIT 1 +#define MPU9250_INTERRUPT_DATA_RDY_BIT 0 + +#define MPU9250_MOTION_MOT_XNEG_BIT 7 +#define MPU9250_MOTION_MOT_XPOS_BIT 6 +#define MPU9250_MOTION_MOT_YNEG_BIT 5 +#define MPU9250_MOTION_MOT_YPOS_BIT 4 +#define MPU9250_MOTION_MOT_ZNEG_BIT 3 +#define MPU9250_MOTION_MOT_ZPOS_BIT 2 +#define MPU9250_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU9250_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU9250_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU9250_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU9250_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU9250_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU9250_PATHRESET_GYRO_RESET_BIT 2 +#define MPU9250_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU9250_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU9250_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU9250_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU9250_DETECT_FF_COUNT_BIT 3 +#define MPU9250_DETECT_FF_COUNT_LENGTH 2 +#define MPU9250_DETECT_MOT_COUNT_BIT 1 +#define MPU9250_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU9250_DETECT_DECREMENT_RESET 0x0 +#define MPU9250_DETECT_DECREMENT_1 0x1 +#define MPU9250_DETECT_DECREMENT_2 0x2 +#define MPU9250_DETECT_DECREMENT_4 0x3 + +#define MPU9250_USERCTRL_DMP_EN_BIT 7 +#define MPU9250_USERCTRL_FIFO_EN_BIT 6 +#define MPU9250_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU9250_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU9250_USERCTRL_DMP_RESET_BIT 3 +#define MPU9250_USERCTRL_FIFO_RESET_BIT 2 +#define MPU9250_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU9250_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU9250_PWR1_DEVICE_RESET_BIT 7 +#define MPU9250_PWR1_SLEEP_BIT 6 +#define MPU9250_PWR1_CYCLE_BIT 5 +#define MPU9250_PWR1_TEMP_DIS_BIT 3 +#define MPU9250_PWR1_CLKSEL_BIT 2 +#define MPU9250_PWR1_CLKSEL_LENGTH 3 + +#define MPU9250_CLOCK_INTERNAL 0x00 +#define MPU9250_CLOCK_PLL_XGYRO 0x01 +#define MPU9250_CLOCK_PLL_YGYRO 0x02 +#define MPU9250_CLOCK_PLL_ZGYRO 0x03 +#define MPU9250_CLOCK_PLL_EXT32K 0x04 +#define MPU9250_CLOCK_PLL_EXT19M 0x05 +#define MPU9250_CLOCK_KEEP_RESET 0x07 + +#define MPU9250_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU9250_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU9250_PWR2_STBY_XA_BIT 5 +#define MPU9250_PWR2_STBY_YA_BIT 4 +#define MPU9250_PWR2_STBY_ZA_BIT 3 +#define MPU9250_PWR2_STBY_XG_BIT 2 +#define MPU9250_PWR2_STBY_YG_BIT 1 +#define MPU9250_PWR2_STBY_ZG_BIT 0 + +#define MPU9250_WAKE_FREQ_1P25 0x0 +#define MPU9250_WAKE_FREQ_2P5 0x1 +#define MPU9250_WAKE_FREQ_5 0x2 +#define MPU9250_WAKE_FREQ_10 0x3 + +#define MPU9250_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU9250_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU9250_BANKSEL_MEM_SEL_BIT 4 +#define MPU9250_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU9250_WHO_AM_I_BIT 6 +#define MPU9250_WHO_AM_I_LENGTH 8 + +#define MPU9250_DMP_MEMORY_BANKS 8 +#define MPU9250_DMP_MEMORY_BANK_SIZE 256 +#define MPU9250_DMP_MEMORY_CHUNK_SIZE 16 + diff --git a/firmwares/compass/src/rv3029.c b/firmwares/compass/src/rv3029.c new file mode 100644 index 0000000..3d72437 --- /dev/null +++ b/firmwares/compass/src/rv3029.c @@ -0,0 +1,117 @@ +#include "ets_sys.h" +#include "osapi.h" + +#include "i2c_master.h" +#include "rv3029.h" + +#define BCD2BIN(val) ((((val) & 0x0f) + ((val) >> 4) * 10)) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +bool rv3029_read(uint8_t regaddr, uint8_t len, uint8_t *data) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(RV3029_ADDR_W); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for write addr\r\n"); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for register\r\n"); + i2c_master_stop(); + return false; + } + + i2c_master_stop(); + i2c_master_start(); + + // Write I²C Address for reading + i2c_master_writeByte(RV3029_ADDR_R); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for read addr\r\n"); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + data[i] = i2c_master_readByte(); + i2c_master_send_ack(); + } + + i2c_master_stop(); + + return true; +} + +bool rv3029_write(uint8_t regaddr, uint8_t len, uint8_t *data) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(RV3029_ADDR_W); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for write addr\r\n"); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for register\r\n"); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + i2c_master_writeByte(data[i]); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for datawrite\r\n"); + i2c_master_stop(); + return false; + } + } + + i2c_master_stop(); + + return true; +} + + +int8_t rv3029_temp() { + uint8_t temp; + if (rv3029_read(0x20, 1, &temp)) return (int8_t)temp - 60; + else return 255; +} + +bool rv3029_gettime(struct TimeSpec *time) { + uint8_t raw[7]; + if (!rv3029_read(0x08, 7, raw)) return false; + + time->seconds = BCD2BIN(raw[0]); + time->minutes = BCD2BIN(raw[1]); + time->hours = BCD2BIN(raw[2]); + time->date = BCD2BIN(raw[3]); + time->dow = raw[4]; + time->months = BCD2BIN(raw[5]); + time->years = BCD2BIN(raw[6]); + + return true; +} + +bool rv3029_settime(struct TimeSpec *time) { + uint8_t raw[7]; + raw[0] = BIN2BCD(time->seconds); + raw[1] = BIN2BCD(time->minutes); + raw[2] = BIN2BCD(time->hours); + raw[3] = BIN2BCD(time->date); + raw[4] = time->dow; + raw[5] = BIN2BCD(time->months); + raw[6] = BIN2BCD(time->years); + return rv3029_write(0x08, 7, raw); +} diff --git a/firmwares/compass/src/rv3029.h b/firmwares/compass/src/rv3029.h new file mode 100644 index 0000000..c65c438 --- /dev/null +++ b/firmwares/compass/src/rv3029.h @@ -0,0 +1,30 @@ +#include <ets_sys.h> + +#ifndef _RV3029_H +#define _RV3029_H + +// Configuration +#define RV3029_ADDR_W 0xAC +#define RV3029_ADDR_R 0xAD + +// 24-hour format only +// Years from 0 - 79, meaning 20xx +// Months from 1 - 12, dow from 1 - 7 +struct TimeSpec { + uint8_t seconds; + uint8_t minutes; + uint8_t hours; + uint8_t date; + uint8_t dow; + uint8_t months; + uint8_t years; +}; + +int8_t rv3029_temp(); +bool rv3029_gettime(struct TimeSpec *time); + +// Internal +bool rv3029_read(uint8_t regaddr, uint8_t len, uint8_t *val); +bool rv3029_write(uint8_t regaddr, uint8_t len, uint8_t *val); + +#endif diff --git a/firmwares/compass/src/ssd1306.c b/firmwares/compass/src/ssd1306.c new file mode 100644 index 0000000..2cf6a68 --- /dev/null +++ b/firmwares/compass/src/ssd1306.c @@ -0,0 +1,310 @@ +#include <ets_sys.h> +#include <os_type.h> +#include <osapi.h> +#include <math.h> + +#include "user_config.h" +#include "i2c_master.h" +#include "ssd1306.h" +#include "util.h" +#include "font.h" + +#define CONTROL_CMD 0b00000000 +#define CONTROL_DATA 0b01000000 +#define SSD1306_PAGES 8 +#define SSD1306_WIDTH 128 + +uint8_t buf[SSD1306_PAGES][SSD1306_WIDTH]; +bool buf_changed[SSD1306_PAGES] = { false }; + +/** Internal commands **/ +void ICACHE_FLASH_ATTR ssd1306_putbyte(uint8_t byte) { + i2c_master_writeByte(byte); + if (i2c_master_getAck()) os_printf("SSD1306: No ACK for 0x%02x\r\n", byte); +} + +void ICACHE_FLASH_ATTR ssd1306_cmd(uint8_t cmd) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_CMD); + ssd1306_putbyte(cmd); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_data(uint8_t dat) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_DATA); + ssd1306_putbyte(dat); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_databurst(uint8_t *dat, uint32_t len) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_DATA); + uint32_t i; + for (i = 0; i < len; ++i) ssd1306_putbyte(dat[i]); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_cmdburst(uint8_t *dat, uint32_t len) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_CMD); + uint16_t i; + for (i = 0; i < len; ++i) ssd1306_putbyte(dat[i]); + i2c_master_stop(); +} + +/** Initialization **/ +void ICACHE_FLASH_ATTR ssd1306_init(uint8_t contrast) { + os_delay_us(10000); + + ssd1306_setaddressing(SSD1306_PAGE_ADDRESSING); + ssd1306_setstartline(0); + ssd1306_setstartpage(0); + ssd1306_setstartaddress(0); + ssd1306_setcontrast(contrast); + ssd1306_setglow(0); + ssd1306_setmirror_h(false); + ssd1306_setinverse(false); + ssd1306_setmultiplex(63); + ssd1306_setmirror_v(false); + ssd1306_setoffset(0); + ssd1306_setosc(0, 8); + ssd1306_setprecharge(2, 2); + ssd1306_setcomconfig(0x12); + ssd1306_setvcomh(0x40); + ssd1306_scroll_disable(); + ssd1306_vscroll_area(0, 64); + ssd1306_setblinkfade(SSD1306_BLINKFADE_OFF, 0); + ssd1306_setchargepump(true); + ssd1306_setonoff(true); +} + +/** Text output **/ +void ssd1306_text_small(uint8_t x, uint8_t y, char *text) { + uint16_t c = 0; + uint8_t page = y / 8; + while (text[c] != 0x00) { + uint8_t i; + for (i = 0; i < 6; ++i) { + uint16_t xpos = x + c * 6 + i; + if (xpos >= SSD1306_WIDTH) return; + uint8_t draw = font_small[text[c] - 0x20][i]; + + // The text may now span between two pages, so the bits have + // to be sperated for first and second page + uint8_t firstpage = (draw << y % 8); + uint8_t secondpage = (draw >> (8 - y % 8)); + + buf[page][xpos] |= firstpage; + buf_changed[page] = true; + if (y % 8) { + buf_changed[page + 1] = true; + buf[page + 1][xpos] |= secondpage; + } + } + c++; + } +} + +void ssd1306_text_large(uint8_t x, uint8_t y, char *text) { + uint16_t c = 0; + uint8_t page = y / 8; + while (text[c] != 0x00) { + uint8_t i; + for (i = 0; i < 8; ++i) { + uint16_t xpos = x + c * 8 + i; + if (xpos >= SSD1306_WIDTH) return; + uint16_t draw_firstpage = font_large[text[c] - 0x20][i]; + uint16_t draw_secondpage = font_large[text[c] - 0x20][i+8]; + + // The text may now span between two pages, so the bits have + // to be sperated for first and second page + uint8_t firstpage = draw_firstpage << (y % 8); + uint8_t secondpage = (draw_firstpage >> (8 - y % 8)) | (draw_secondpage << (y % 8)); + uint8_t thirdpage = draw_secondpage >> (8 - y % 8); + + buf_changed[page] = true; + buf_changed[page + 1] = true; + + buf[page][xpos] |= firstpage; + buf[page + 1][xpos] |= secondpage; + + if (y % 8) { + buf[page + 2][xpos] |= thirdpage; + buf_changed[page + 2] = true; + } + } + c++; + } +} + +/** Graphics **/ +void ICACHE_FLASH_ATTR ssd1306_setpixel(uint8_t x, uint8_t y, bool state) { + if (state) + sbi(buf[y / 8][x], y % 8); + else + cbi(buf[y / 8][x], y % 8); +} + +void ICACHE_FLASH_ATTR ssd1306_line(uint8_t startx, uint8_t starty, uint8_t endx, uint8_t endy, bool state) { + float x = startx; + float y = starty; + float max = abs(endx - startx) > abs(endy - starty) ? abs(endx - startx) : abs(endy - starty); + + while (((endx > startx) ? x < endx : x > endx) || ((endy > starty) ? y < endy : y > endy)) { + x += (endx - startx) / max; + y += (endy - starty) / max; + ssd1306_setpixel((uint8_t)x, (uint8_t)y, state); + } +} + +/** Buffer related **/ +void ICACHE_FLASH_ATTR ssd1306_fill(uint8_t content) { + uint8_t page = 0, col = 0; + for(page = 0; page < 8; page++) { + buf_changed[page] = true; + for(col = 0; col < SSD1306_WIDTH; col++) + buf[page][col] = content; + } +} + +void ICACHE_FLASH_ATTR ssd1306_clear(void) { + ssd1306_fill(0x00); +} + +// Requires page addressing mode +void ICACHE_FLASH_ATTR ssd1306_flip(void) { + // Some dummy commands, to make controller align timing for bursts + ssd1306_setglow(false); + ssd1306_scroll_disable(); + + uint8_t page; + for (page = 0; page < SSD1306_PAGES; page++) { + ssd1306_setstartaddress(0); + ssd1306_setstartpage(page); + ssd1306_databurst(buf[page], 128); + } +} + +/** Misc commands **/ +void ICACHE_FLASH_ATTR ssd1306_setcontrast(uint8_t contrast) { + ssd1306_cmd(0x81); + ssd1306_cmd(contrast); +} + +void ICACHE_FLASH_ATTR ssd1306_setonoff(bool on) { + ssd1306_cmd(0xAE + (on ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setaddressing(enum ssd1306_addr_mode mode) { + ssd1306_cmd(0x20); + ssd1306_cmd(mode); +} + +// startline from 0 - 63 +void ICACHE_FLASH_ATTR ssd1306_setstartline(uint8_t startline) { + ssd1306_cmd(0x40 + startline); +} + +// startpage from 0 - 7 +void ICACHE_FLASH_ATTR ssd1306_setstartpage(uint8_t startpage) { + ssd1306_cmd(0xB0 + startpage); +} + +// start address from 0 - 128 +void ICACHE_FLASH_ATTR ssd1306_setstartaddress(uint8_t address) { + ssd1306_cmd((0x10 | (address & 0xf0) >> 4)); + ssd1306_cmd(0x01 | (address & 0x0f)); +} + +void ICACHE_FLASH_ATTR ssd1306_setmirror_h(bool mirror) { + ssd1306_cmd(0xA0 + (mirror ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setmirror_v(bool mirror) { + ssd1306_cmd(0xC0 + (mirror ? 8 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setinverse(bool inverse) { + ssd1306_cmd(0xA6 + (inverse ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setoffset(uint8_t x) { + ssd1306_cmd(0xD3); + ssd1306_cmd(x); +} + +// division ration from 0 - 15, fosc from 0 - 15, see datasheet section 8.3 +// "Oscillator Circuit and Display Time Generator" +void ICACHE_FLASH_ATTR ssd1306_setosc(uint8_t divratio, uint8_t fosc) { + ssd1306_cmd(0xD5); + ssd1306_cmd(divratio | (fosc << 4)); +} + +void ICACHE_FLASH_ATTR ssd1306_setprecharge(uint8_t period_phase1, uint8_t period_phase2) { + ssd1306_cmd(0xD9); + ssd1306_cmd(period_phase1 | (period_phase2 << 4)); +} + +// Refer to datasheet section 10.1.18 for more information +// configures connection of panel to controller +void ICACHE_FLASH_ATTR ssd1306_setcomconfig(uint8_t comconfig) { + ssd1306_cmd(0xDA); + ssd1306_cmd(comconfig); +} + +// level is either 0x00 (0.65 * Vcc), 0x40 (0.77 * Vcc, default), 0x60 (0.83 * Vcc) +void ICACHE_FLASH_ATTR ssd1306_setvcomh(uint8_t level) { + ssd1306_cmd(0xDB); + ssd1306_cmd(level); +} + +void ICACHE_FLASH_ATTR ssd1306_setchargepump(bool enable) { + ssd1306_cmd(0x8D); + ssd1306_cmd(enable ? 0x14 : 0x10); +} + +// multiplex from 15- 63 +void ICACHE_FLASH_ATTR ssd1306_setmultiplex(uint8_t multiplex) { + ssd1306_cmd(0xA8); + ssd1306_cmd(multiplex); +} + +/** Fading and Blinking **/ +// Turns all pixels on (or disables this feature) +void ICACHE_FLASH_ATTR ssd1306_setglow(bool enable) { + ssd1306_cmd(0xA4 + (enable ? 1 : 0)); +} + +// Speed 0 - 15 +void ICACHE_FLASH_ATTR ssd1306_setblinkfade(enum ssd1306_blinkfade_mode mode, uint8_t time) { + ssd1306_cmd(0x23); + ssd1306_cmd((mode << 4) | time); +} + + +/** Scrolling **/ +void ICACHE_FLASH_ATTR ssd1306_scroll(enum ssd1306_scroll_dir direction, uint8_t startpage, uint8_t endpage, + enum ssd1306_scroll_frequency freq, uint8_t voffset) { + ssd1306_cmd(0x29 + direction); + ssd1306_cmd(0x00); + ssd1306_cmd(startpage); + ssd1306_cmd(freq); + ssd1306_cmd(endpage); + ssd1306_cmd(voffset); + ssd1306_cmd(0x2f); +} + +void ICACHE_FLASH_ATTR ssd1306_vscroll_area(uint8_t fixedrows, uint8_t scrollrows) { + ssd1306_cmd(0xa3); + ssd1306_cmd(fixedrows); + ssd1306_cmd(scrollrows); +} + +void ICACHE_FLASH_ATTR ssd1306_scroll_disable() { + ssd1306_cmd(0x2e); +} diff --git a/firmwares/compass/src/ssd1306.h b/firmwares/compass/src/ssd1306.h new file mode 100644 index 0000000..cab3ef5 --- /dev/null +++ b/firmwares/compass/src/ssd1306.h @@ -0,0 +1,90 @@ +#include <ets_sys.h> + +#ifndef _SSD1306_H +#define _SSD1306_H + +// Configuration +#define SSD1306_ADDR 0x78 + +/** Internal commands **/ +void ssd1306_cmd(uint8_t cmd); +void ssd1306_data(uint8_t dat); +void ssd1306_databurst(uint8_t *dat, uint32_t len); +void ssd1306_cmdburst(uint8_t *dat, uint32_t len); + +/** Initialization **/ +void ssd1306_init(uint8_t contrast); + +/** Text output **/ +void ssd1306_text_small(uint8_t x, uint8_t y, char *text); +void ssd1306_text_large(uint8_t x, uint8_t y, char *text); + +/** Graphics **/ +void ssd1306_setpixel(uint8_t x, uint8_t y, bool state); +void ssd1306_line(uint8_t startx, uint8_t starty, uint8_t endx, uint8_t endy, bool state); + +/** Buffer related **/ +void ssd1306_fill(uint8_t content); +void ssd1306_clear(void); +void ssd1306_flip(void); + +/** Addressing modes **/ +enum ssd1306_addr_mode { + SSD1306_HORIZONTAL_ADDRESSING = 0, + SSD1306_VERTICAL_ADDRESSING = 1, + SSD1306_PAGE_ADDRESSING = 2 +}; + +/** Scroll directions and frequency **/ +enum ssd1306_scroll_dir { + SSD1306_SCROLL_RIGHT = 0, + SSD1306_SCROLL_LEFT = 1 +}; + +enum ssd1306_scroll_frequency { + SSD1306_SCROLLFREQ_5 = 0b000, + SSD1306_SCROLLFREQ_64 = 0b001, + SSD1306_SCROLLFREQ_128 = 0b010, + SSD1306_SCROLLFREQ_256 = 0b011, + SSD1306_SCROLLFREQ_3 = 0b100, + SSD1306_SCROLLFREQ_4 = 0b101, + SSD1306_SCROLLFREQ_25 = 0b110, + SSD1306_SCROLLFREQ_2 = 0b111 +}; + +/** Blinking / fading modes **/ +enum ssd1306_blinkfade_mode { + SSD1306_BLINKFADE_OFF = 0b00, + SSD1306_BLINKFADE_FADE = 0b10, + SSD1306_BLINKFADE_BLINK = 0b11 +}; + +/** Misc commands **/ +void ssd1306_setcontrast(uint8_t contrast); +void ssd1306_setonoff(bool on); +void ssd1306_setaddressing(enum ssd1306_addr_mode mode); +void ssd1306_setstartline(uint8_t startline); +void ssd1306_setstartpage(uint8_t startpage); +void ssd1306_setstartaddress(uint8_t address); +void ssd1306_setmirror_h(bool mirror); +void ssd1306_setmirror_v(bool mirror); +void ssd1306_setinverse(bool inverse); +void ssd1306_setoffset(uint8_t x); +void ssd1306_setosc(uint8_t divratio, uint8_t fosc); +void ssd1306_setprecharge(uint8_t period_phase1, uint8_t period_phase2); +void ssd1306_setcomconfig(uint8_t comconfig); +void ssd1306_setvcomh(uint8_t level); +void ssd1306_setchargepump(bool enable); +void ssd1306_setmultiplex(uint8_t multiplex); + +/** Fading and Blinking **/ +void ssd1306_setglow(bool enable); +void ssd1306_setblinkfade(enum ssd1306_blinkfade_mode mode, uint8_t time); + +/** Scrolling **/ +void ssd1306_scroll(enum ssd1306_scroll_dir direction, uint8_t startpage, uint8_t endpage, + enum ssd1306_scroll_frequency freq, uint8_t voffset); +void ssd1306_vscroll_area(uint8_t fixedrows, uint8_t scrollrows); +void ssd1306_scroll_disable(); + +#endif diff --git a/firmwares/compass/src/user_config.h b/firmwares/compass/src/user_config.h new file mode 100644 index 0000000..1859836 --- /dev/null +++ b/firmwares/compass/src/user_config.h @@ -0,0 +1,5 @@ +#define BAUD 1000000 + +// Battery voltage measurement divisor - pullup & pulldown resistor proportions +#define VOLT_DIV_UP 330 +#define VOLT_DIV_DOWN 100 diff --git a/firmwares/compass/src/util.c b/firmwares/compass/src/util.c new file mode 100644 index 0000000..1fa6201 --- /dev/null +++ b/firmwares/compass/src/util.c @@ -0,0 +1,26 @@ +// System +#include <ets_sys.h> +#include <osapi.h> +#include <gpio.h> +#include <os_type.h> +#include <user_interface.h> + +// Configuration +#include "user_config.h" + +// Project +#include "i2c_master.h" +#include "util.h" + +void i2c_scanbus() { + // Scan I²C Bus + os_printf("\r\n=== Scanning I²C Bus ===\r\n"); + uint8_t i; + for (i = 0; i < 0xff; ++i) { + i2c_master_start(); + i2c_master_writeByte(i); + if (!i2c_master_getAck()) os_printf("ACK for address: 0x%02x\r\n", i); + i2c_master_stop(); + } + os_printf("========================\r\n\r\n"); +} diff --git a/firmwares/compass/src/util.h b/firmwares/compass/src/util.h new file mode 100644 index 0000000..9eba195 --- /dev/null +++ b/firmwares/compass/src/util.h @@ -0,0 +1,16 @@ +#ifndef _UTIL_H +#define _UTIL_H + +// Bit manipulation: Set / clear / get / toggle bit +#define sbi(ADDR, BIT) ((ADDR |= (1<<BIT))) +#define cbi(ADDR, BIT) ((ADDR &= ~(1<<BIT))) +#define gbi(ADDR, BIT) ((ADDR & (1<<BIT))) +#define tbi(ADDR, BIT) ((ADDR ^= (1<<BIT))) + +// For debugging: +void i2c_scanbus(); + +// Constants +#define PI 3.141592f + +#endif diff --git a/firmwares/compass/src/vector.c b/firmwares/compass/src/vector.c new file mode 100644 index 0000000..1028f15 --- /dev/null +++ b/firmwares/compass/src/vector.c @@ -0,0 +1,19 @@ +// System +#include <math.h> + +// Project +#include "vector.h" + +angles2f ICACHE_FLASH_ATTR vec3f_to_angles2f(vec3f v) { + angles2f ret; + ret.yaw = atan2(v.y, v.x); + ret.pitch = atan2(v.z, sqrt((v.x * v.x) + (v.y * v.y))); + return ret; +} + +angles2f ICACHE_FLASH_ATTR vec3s16_to_angles2f(vec3s16 v) { + angles2f ret; + ret.yaw = atan2(v.y, v.x); + ret.pitch = atan2(v.z, sqrt((v.x * v.x) + (v.y * v.y))); + return ret; +} diff --git a/firmwares/compass/src/vector.h b/firmwares/compass/src/vector.h new file mode 100644 index 0000000..b9dab8c --- /dev/null +++ b/firmwares/compass/src/vector.h @@ -0,0 +1,29 @@ +#include <ets_sys.h> + +#ifndef _VECTOR_H +#define _VECTOR_H + +struct _vec3s16_t { + int16_t x; + int16_t y; + int16_t z; +}; +typedef struct _vec3s16_t vec3s16; + +struct _vec3f_t { + float x; + float y; + float z; +}; +typedef struct _vec3f_t vec3f; + +struct _angles2f_t { + float pitch; + float yaw; +}; +typedef struct _angles2f_t angles2f; + +angles2f vec3f_to_angles2f(vec3f v); +angles2f vec3s16_to_angles2f(vec3s16 v); + +#endif diff --git a/firmwares/minetest/.gitignore b/firmwares/minetest/.gitignore new file mode 100644 index 0000000..722a501 --- /dev/null +++ b/firmwares/minetest/.gitignore @@ -0,0 +1,2 @@ +build/ +obj/ diff --git a/firmwares/minetest/Makefile b/firmwares/minetest/Makefile new file mode 100644 index 0000000..618ffee --- /dev/null +++ b/firmwares/minetest/Makefile @@ -0,0 +1,76 @@ +# Esptool firmware download options +PORT ?= /dev/ttyUSB0 +BAUD := 1000000 + +# Directory structure +BUILDDIR := build +SRCDIR := src +OBJDIR := obj +LDSCRIPT := ldscript.ld +LIBESPHTTPD_DIR := libesphttpd + +SRCS := $(wildcard $(SRCDIR)/*.c) +OBJS := $(addprefix $(OBJDIR)/,$(notdir $(SRCS:.c=.o))) +DEPS := $(addprefix $(OBJDIR),$(notdir $(SRCS:.c=.d))) + +# SDK / Compiler settings +SDK_DIR := /opt/esp-open-sdk/esp_iot_sdk_v1.5.0 +CC := xtensa-lx106-elf-gcc +LD := xtensa-lx106-elf-gcc +ESPTOOL := esptool.py +CFLAGS := -Os -fdata-sections -ffunction-sections -Wpointer-arith -Wall -Wno-parentheses -Wno-implicit-function-declaration -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH +LDLIBS := -Wl,--start-group -lc -lgcc -lhal -lphy -lpp -lnet80211 -lwpa -lmain -llwip -lesphttpd -lwebpages-espfs -lcrypto -lm $(OBJS) -Wl,--end-group +LDFLAGS := -nostdlib -Wl,--gc-sections -Wl,--no-check-sections -u call_user_start -Wl,-static -T $(LDSCRIPT) +INCLUDES := -I $(SDK_DIR)/include -I $(SDK_DIR)/include/json -I $(LIBESPHTTPD_DIR)/include -I $(SRCDIR)/ + +# Project settings +TARGET := handgelenk +FLASH_FREQ := 40m +FLASH_MODE := dio +FLASH_SIZE := 512 +FLASH_SIZE_BIT := 4m +FLASH_OPT := --flash_freq $(FLASH_FREQ) --flash_mode $(FLASH_MODE) --flash_size $(FLASH_SIZE_BIT) + +TARGET_ELF := $(BUILDDIR)/$(TARGET).elf +TARGET_FLASH := $(BUILDDIR)/$(TARGET)-0x00000.bin +TARGET_IROM := $(BUILDDIR)/$(TARGET)-0x40000.bin +MEM_LDSCRIPT := $(OBJDIR)/ldscript_memspecific.ld + +LIBESPHTTPD := $(LIBESPHTTPD_DIR)/libesphttpd.a + +all: $(OBJDIR) $(BUILDDIR) $(TARGET_FLASH) $(TARGET_IROM) + @echo Compilation successful + @echo Use \'make flash\' to flash firmware + +$(TARGET_FLASH) $(TARGET_IROM): $(TARGET_ELF) + $(ESPTOOL) elf2image $(FLASH_OPT) $^ --output $(BUILDDIR)/$(TARGET)- + +$(TARGET_ELF): $(OBJS) $(LIBESPHTTPD) $(MEM_LDSCRIPT) + $(LD) -L$(LIBESPHTTPD_DIR) -L$(SDK_DIR)/lib $(LDFLAGS) $(MEM_LDSCRIPT) $(LDLIBS) -o $@ + +$(MEM_LDSCRIPT): + echo "MEMORY { irom0_0_seg : org = 0x40240000, len = "$$(printf "0x%X" $$(($(FLASH_SIZE)-0x4000)))" }"> $(MEM_LDSCRIPT) + +$(LIBESPHTTPD):$(LIBESPHTTPD_DIR) + $(MAKE) -C $(LIBESPHTTPD_DIR) + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@ + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(BUILDDIR): + mkdir -p $(BUILDDIR) + +flash: all + $(ESPTOOL) --port $(PORT) --baud $(BAUD) write_flash $(FLASH_OPT) 0x00000 $(TARGET_FLASH) 0x40000 $(TARGET_IROM) + +.PHONY: clean + +clean: + $(RM) -r $(OBJDIR) + $(RM) -r $(BUILDDIR) + $(MAKE) -C $(LIBESPHTTPD_DIR) clean + +-include $(DEPS) diff --git a/firmwares/minetest/html/index.html b/firmwares/minetest/html/index.html new file mode 100644 index 0000000..3a82f32 --- /dev/null +++ b/firmwares/minetest/html/index.html @@ -0,0 +1,11 @@ +<!DOCYTPE html> + +<html> +<head> + <title>Minetest Controller + + +

Minetest Controller

+ Hello World! + + diff --git a/firmwares/minetest/ldscript.ld b/firmwares/minetest/ldscript.ld new file mode 100644 index 0000000..585d0d1 --- /dev/null +++ b/firmwares/minetest/ldscript.ld @@ -0,0 +1,214 @@ +MEMORY +{ + dport0_0_seg : org = 0x3FF00000, len = 0x10 + dram0_0_seg : org = 0x3FFE8000, len = 0x14000 + iram1_0_seg : org = 0x40100000, len = 0x8000 + irom0_0_seg : org = 0x40240000, len = 0x3C000 +} + +PHDRS +{ + dport0_0_phdr PT_LOAD; + dram0_0_phdr PT_LOAD; + dram0_0_bss_phdr PT_LOAD; + iram1_0_phdr PT_LOAD; + irom0_0_phdr PT_LOAD; +} + + +/* Default entry point: */ +ENTRY(call_user_start) +EXTERN(_DebugExceptionVector) +EXTERN(_DoubleExceptionVector) +EXTERN(_KernelExceptionVector) +EXTERN(_NMIExceptionVector) +EXTERN(_UserExceptionVector) +PROVIDE(_memmap_vecbase_reset = 0x40000000); +/* Various memory-map dependent cache attribute settings: */ +_memmap_cacheattr_wb_base = 0x00000110; +_memmap_cacheattr_wt_base = 0x00000110; +_memmap_cacheattr_bp_base = 0x00000220; +_memmap_cacheattr_unused_mask = 0xFFFFF00F; +_memmap_cacheattr_wb_trapnull = 0x2222211F; +_memmap_cacheattr_wba_trapnull = 0x2222211F; +_memmap_cacheattr_wbna_trapnull = 0x2222211F; +_memmap_cacheattr_wt_trapnull = 0x2222211F; +_memmap_cacheattr_bp_trapnull = 0x2222222F; +_memmap_cacheattr_wb_strict = 0xFFFFF11F; +_memmap_cacheattr_wt_strict = 0xFFFFF11F; +_memmap_cacheattr_bp_strict = 0xFFFFF22F; +_memmap_cacheattr_wb_allvalid = 0x22222112; +_memmap_cacheattr_wt_allvalid = 0x22222112; +_memmap_cacheattr_bp_allvalid = 0x22222222; +PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull); + +SECTIONS +{ + + .dport0.rodata : ALIGN(4) + { + _dport0_rodata_start = ABSOLUTE(.); + *(.dport0.rodata) + *(.dport.rodata) + _dport0_rodata_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.literal : ALIGN(4) + { + _dport0_literal_start = ABSOLUTE(.); + *(.dport0.literal) + *(.dport.literal) + _dport0_literal_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .dport0.data : ALIGN(4) + { + _dport0_data_start = ABSOLUTE(.); + *(.dport0.data) + *(.dport.data) + _dport0_data_end = ABSOLUTE(.); + } >dport0_0_seg :dport0_0_phdr + + .data : ALIGN(4) + { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + _data_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .rodata : ALIGN(4) + { + _rodata_start = ABSOLUTE(.); + *(.sdk.version) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + *(.eh_frame) + /* C++ constructor and destructor tables, properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _bss_table_start = ABSOLUTE(.); + LONG(_bss_start) + LONG(_bss_end) + _bss_table_end = ABSOLUTE(.); + _rodata_end = ABSOLUTE(.); + } >dram0_0_seg :dram0_0_phdr + + .bss ALIGN(8) (NOLOAD) : ALIGN(4) + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); +/* _stack_sentry = ALIGN(0x8); */ + } >dram0_0_seg :dram0_0_bss_phdr +/* __stack = 0x3ffc8000; */ + + .irom0.text : ALIGN(4) + { + _irom0_text_start = ABSOLUTE(.); + *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) + + /** Libraries manually placed into IROM: libm.a, libc.a **/ + *libm.a:(.literal .text .literal.* .text.*) + *libc.a:(.literal .text .literal.* .text.*) + + _irom0_text_end = ABSOLUTE(.); + } >irom0_0_seg :irom0_0_phdr + + .text : ALIGN(4) + { + _stext = .; + _text_start = ABSOLUTE(.); + *(.UserEnter.text) + . = ALIGN(16); + *(.DebugExceptionVector.text) + . = ALIGN(16); + *(.NMIExceptionVector.text) + . = ALIGN(16); + *(.KernelExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.UserExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN(16); + *(.DoubleExceptionVector.text) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + } >iram1_0_seg :iram1_0_phdr + + .lit4 : ALIGN(4) + { + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + } >iram1_0_seg :iram1_0_phdr +} + +/* get ROM code address */ +INCLUDE "../ld/eagle.rom.addr.v6.ld" diff --git a/firmwares/minetest/libesphttpd/.gitignore b/firmwares/minetest/libesphttpd/.gitignore new file mode 100644 index 0000000..33c48ec --- /dev/null +++ b/firmwares/minetest/libesphttpd/.gitignore @@ -0,0 +1,12 @@ +build/ +espfs/mkespfsimage/*.o +espfs/mkespfsimage/mkespfsimage +webpages.espfs +libesphttpd.a +espfs/espfstest/*.o +espfs/espfstest/espfstest +*.DS_Store +html_compressed/ +libwebpages-espfs.a +libesphttpd.a +libwebpages-espfs.a diff --git a/firmwares/minetest/libesphttpd/.gitmodules b/firmwares/minetest/libesphttpd/.gitmodules new file mode 100644 index 0000000..772d424 --- /dev/null +++ b/firmwares/minetest/libesphttpd/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/heatshrink"] + path = lib/heatshrink + url = https://github.com/atomicobject/heatshrink.git diff --git a/firmwares/minetest/libesphttpd/Makefile b/firmwares/minetest/libesphttpd/Makefile new file mode 100644 index 0000000..8815d1e --- /dev/null +++ b/firmwares/minetest/libesphttpd/Makefile @@ -0,0 +1,191 @@ + +# Directory the Makefile is in. Please don't include other Makefiles before this. +THISDIR:=$(dir $(abspath $(lastword $(MAKEFILE_LIST)))) + +#Include httpd config from lower level, if it exists +-include ../esphttpdconfig.mk + + +#Default options. If you want to change them, please create ../esphttpdconfig.mk with the options you want in it. +GZIP_COMPRESSION ?= no +COMPRESS_W_YUI ?= no +YUI-COMPRESSOR ?= /usr/bin/yui-compressor +USE_HEATSHRINK ?= no +HTTPD_WEBSOCKETS ?= no +USE_OPENSDK ?= no +FREERTOS ?= no +HTTPD_MAX_CONNECTIONS ?= 4 +#For FreeRTOS +HTTPD_STACKSIZE ?= 2048 + +# Output directors to store intermediate compiled files +# relative to the project directory +BUILD_BASE = build + +# Base directory for the compiler. Needs a / at the end; if not set it'll use the tools that are in +# the PATH. +XTENSA_TOOLS_ROOT ?= + +# base directory of the ESP8266 SDK package, absolute +# Only used for the non-FreeRTOS build +SDK_BASE ?= /opt/Espressif/ESP8266_SDK + +# Base directory of the ESP8266 FreeRTOS SDK package, absolute +# Only used for the FreeRTOS build +SDK_PATH ?= /opt/Espressif/ESP8266_RTOS_SDK + + +# name for the target project +LIB = libesphttpd.a + +# which modules (subdirectories) of the project to include in compiling +MODULES = espfs core util +EXTRA_INCDIR = ./include \ + . \ + lib/heatshrink/ + + +# compiler flags using during compilation of source files +CFLAGS = -Os -ggdb -std=c99 -Werror -Wpointer-arith -Wundef -Wall -Wl,-EL -fno-inline-functions \ + -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH \ + -Wno-address -DHTTPD_MAX_CONNECTIONS=$(HTTPD_MAX_CONNECTIONS) -DHTTPD_STACKSIZE=$(HTTPD_STACKSIZE) \ + + + + +# various paths from the SDK used in this project +SDK_LIBDIR = lib +SDK_LDDIR = ld + + +ifeq ("$(FREERTOS)","yes") +CFLAGS += -DFREERTOS -DLWIP_OPEN_SRC -ffunction-sections -fdata-sections +SDK_INCDIR = include \ + include/freertos \ + include/espressif/esp8266 \ + include/espressif \ + extra_include \ + include/lwip \ + include/lwip/lwip \ + include/lwip/ipv4 \ + include/lwip/ipv6 +SDK_INCDIR := $(addprefix -I$(SDK_PATH)/,$(SDK_INCDIR)) +else +SDK_INCDIR = include +SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR)) +endif + + +# select which tools to use as compiler, librarian and linker +CC := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-gcc +AR := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-ar +LD := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-gcc +OBJCOPY := $(XTENSA_TOOLS_ROOT)xtensa-lx106-elf-objcopy + +#### +#### no user configurable options below here +#### +SRC_DIR := $(MODULES) +BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES)) + +SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c)) +OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC)) + +INCDIR := $(addprefix -I,$(SRC_DIR)) +EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR)) +MODULE_INCDIR := $(addsuffix /include,$(INCDIR)) + +V ?= $(VERBOSE) +ifeq ("$(V)","1") +Q := +vecho := @true +else +Q := @ +vecho := @echo +endif + + +ifneq ("$(FREERTOS)","yes") +ifeq ("$(USE_OPENSDK)","yes") +CFLAGS += -DUSE_OPENSDK +else +CFLAGS += -D_STDINT_H +endif +endif + +ifeq ("$(GZIP_COMPRESSION)","yes") +CFLAGS += -DGZIP_COMPRESSION +endif + +ifeq ("$(USE_HEATSHRINK)","yes") +CFLAGS += -DESPFS_HEATSHRINK +endif + +ifeq ("$(HTTPD_WEBSOCKETS)","yes") +CFLAGS += -DHTTPD_WEBSOCKETS +endif + +vpath %.c $(SRC_DIR) + +define compile-objects +$1/%.o: %.c + $(vecho) "CC $$<" + $(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@ +endef + +.PHONY: all checkdirs clean webpages.espfs submodules + +all: checkdirs $(LIB) webpages.espfs libwebpages-espfs.a + +submodules: lib/heatshrink/Makefile +lib/heatshrink/Makefile: + $(Q) echo "Heatshrink isn't found. Checking out submodules to fetch it." + $(Q) git submodule init + $(Q) git submodule update + + +$(LIB): $(BUILD_DIR) submodules $(OBJ) + $(vecho) "AR $@" + $(Q) $(AR) cru $@ $(OBJ) + +checkdirs: $(BUILD_DIR) + +$(BUILD_DIR): + $(Q) mkdir -p $@ + + +webpages.espfs: $(HTMLDIR) espfs/mkespfsimage/mkespfsimage +ifeq ("$(COMPRESS_W_YUI)","yes") + $(Q) rm -rf html_compressed; + $(Q) cp -r ../html html_compressed; + $(Q) echo "Compression assets with yui-compressor. This may take a while..." + $(Q) for file in `find html_compressed -type f -name "*.js"`; do $(YUI-COMPRESSOR) --type js $$file -o $$file; done + $(Q) for file in `find html_compressed -type f -name "*.css"`; do $(YUI-COMPRESSOR) --type css $$file -o $$file; done + $(Q) awk "BEGIN {printf \"YUI compression ratio was: %.2f%%\\n\", (`du -b -s html_compressed/ | sed 's/\([0-9]*\).*/\1/'`/`du -b -s ../html/ | sed 's/\([0-9]*\).*/\1/'`)*100}" +# mkespfsimage will compress html, css, svg and js files with gzip by default if enabled +# override with -g cmdline parameter + $(Q) cd html_compressed; find . | $(THISDIR)/espfs/mkespfsimage/mkespfsimage > $(THISDIR)/webpages.espfs; cd ..; +else + $(Q) cd ../html; find . | $(THISDIR)/espfs/mkespfsimage/mkespfsimage > $(THISDIR)/webpages.espfs; cd .. +endif + +libwebpages-espfs.a: webpages.espfs + $(Q) $(OBJCOPY) -I binary -O elf32-xtensa-le -B xtensa --rename-section .data=.irom0.literal \ + webpages.espfs build/webpages.espfs.o.tmp + $(Q) $(LD) -nostdlib -Wl,-r build/webpages.espfs.o.tmp -o build/webpages.espfs.o -Wl,-T webpages.espfs.ld + $(Q) $(AR) cru $@ build/webpages.espfs.o + +espfs/mkespfsimage/mkespfsimage: espfs/mkespfsimage/ + $(Q) $(MAKE) -C espfs/mkespfsimage USE_HEATSHRINK="$(USE_HEATSHRINK)" GZIP_COMPRESSION="$(GZIP_COMPRESSION)" + +clean: + $(Q) rm -f $(LIB) + $(Q) find $(BUILD_BASE) -type f | xargs rm -f + $(Q) make -C espfs/mkespfsimage/ clean + $(Q) rm -rf $(FW_BASE) + $(Q) rm -f webpages.espfs libwebpages-espfs.a +ifeq ("$(COMPRESS_W_YUI)","yes") + $(Q) rm -rf html_compressed +endif + +$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir)))) diff --git a/firmwares/minetest/libesphttpd/README.md b/firmwares/minetest/libesphttpd/README.md new file mode 100644 index 0000000..a3538b8 --- /dev/null +++ b/firmwares/minetest/libesphttpd/README.md @@ -0,0 +1,320 @@ +# Libesphttpd intro + +Libesphttpd is a HTTP server library for the ESP8266. It supports integration in projects +running under the non-os and FreeRTOS-based SDK. Its core is clean and small, but it provides an +extensible architecture with plugins to handle a flash-based compressed read-only filesystem +for static files, a tiny template engine, websockets, a captive portal, and more. + +# Examples + +There are two example projects that integrate this code, both a [non-os](http://git.spritesserver.nl/esphttpd.git/) +as well as a [FreeRTOS-based](http://git.spritesserver.nl/esphttpd-freertos.git/) example. They show +how to use libesphttpd to serve files from an ESP8266 and illustrate a way to make an user associate +the ESP8266 with an access point from a standard webbrowser on a PC or mobile phone. + +# Programming guide + +Programming libesphttpd will require some knowledge of HTTP. Knowledge of the exact RFCs isn't needed, +but it helps if you know the difference between a GET and a POST request, how HTTP headers work, +what an mime-type is and so on. Furthermore, libesphttpd is written in the C language and uses the +libraries available on the ESP8266 SDK. It is assumed the developer knows C and has some experience +with the SDK. + +## Initializing libesphttpd + +Initializing libesphttpd is usually done in the `user_main()` of your project, but it is not mandatory +to place the call here. Initialization is done by the `httpdInit(builtInUrls, port)` call. The port +is the TCP port the webserver will listen on; the builtInUrls is the CGI list. + +(As an aside: CGI actually is an abbreviation for Common Gateway Interface, which is a specification +to allow external processes to interface with a non-embedded webserver. The CGI functions mentioned here +have nothing to do with the CGI protocol specification; the term 'CGI' is just used as a quick +handle for a function interpreting headers and generating data to send to the web client.) + +The CGI list is an array of the HttpdBuiltInUrl type. Here's an example: +```c +HttpdBuiltInUrl builtInUrls[]={ + {"/", cgiRedirect, "/index.cgi"}, + {"/index.cgi", cgiMyFunction, NULL}, + {"*", cgiEspFsHook, NULL}, + {NULL, NULL, NULL} +}; +``` +As you can see, the array consists of a number of entries, with the last entry filled with NULLs. When +the webserver gets a request, it will run down the list and try to match the URL the browser sent to the +pattern specified in the first argument in the list. If a match is detected, the corresponding CGI +function is called. This function gets the opportunity to handle the request, but it also can pass +on handling it; if this happens, the webserver will keep going down the list to look for a CGI +with a matching pattern willing to handle the request; if there is none on the list, it will +generate a 404 page itself. + +The patterns can also have wildcards: a * at the end of the pattern matches any text. For instance, +the pattern `/wifi/*` will match requests for `/wifi/index.cgi` and `/wifi/picture.jpg`, but not +for example `/settings/wifi/`. The cgiEspFsHook is used like that in the example: it will be called +on any request that is not handled by the cgi functions earlier in the list. + +There also is a third entry in the list. This is an optional argument for the CGI function; its +purpose differs per specific function. If this is not needed, it's okay to put NULL there instead. + +### Sidenote: About the cgiEspFsHook call +While `cgiEspFsHook` isn't handled any different than any other cgi function, it may be useful +to shortly elaborate what its function is. `cgiEspFsHook` is responsible, on most implementations, +for serving up the static files that are included in the project: static HTML pages, images, Javascript +code etc. Esphttpd doesn't have a built-in method to serve static files: the code responsible +for doing it is plugged into it the same way as any cgi function is. This allows the developer to +leave away the ability to serve static files if it isn't needed, or use a different implementation +that serves e.g. files off the FAT-partition of a SD-card. + +## Built-in CGI functions +The webserver provides a fair amount of general-use CGI functions. Because of the structure of +libesphttpd works and some linker magic in the Makefiles of the SDKs, the compiler will only +include them in the output binary if they're actually used. + +* __cgiRedirect__ (arg: URL to redirect to) +This is a convenience function to redirect the browser requesting this URL to a different URL. For +example, an entry like {"/google", cgiRedirect, "http://google.com"} would redirect +all browsers requesting /google to the website of the search giant. + +* __cgiRedirectToHostname__ (arg: hostname to redirect to) +If the host as requested by the browser isn't the hostname in the argument, the webserver will do a redirect +to the host instead. If the hostname does match, it will pass on the request. + +* __cgiRedirectApClientToHostname__ (arg: hostname to redirect to) +This does the same as `cgiRedirectToHostname` but only to clients connected to the SoftAP of the +ESP8266. This and the former function are used with the captive portal mode. The captive portal consists +of a DNS-server (started by calling `captdnsInit()`) resolving all hostnames into the IP of the +ESP8266. These redirect functions can then be used to further redirect the client to the hostname of +the ESP8266. + +* __cgiReadFlash__ (arg: none) +Will serve up the SPI flash of the ESP8266 as a binary file. + +* __cgiGetFirmwareNext__ (arg: CgiUploadFlashDef flash description data) +For OTA firmware upgrade: indicates if the user1 or user2 firmware needs to be sent to the ESP to do +an OTA upgrade + +* __cgiUploadFirmware__ (arg: CgiUploadFlashDef flash description data) +Accepts a POST request containing the user1 or user2 firmware binary and flashes it to the SPI flash + +* __cgiRebootFirmware__ (arg: none) +Reboots the ESP8266 to the newly uploaded code after a firmware upload. + +* __cgiWiFi* functions__ (arg: various) +These are used to change WiFi mode, scan for access points, associate to an access point etcetera. See +the example projects for an implementation that uses these function calls. + +* __cgiWebsocket__ (arg: connect function) +This CGI is used to set up a websocket. Websockets are described later in this document. + +* __cgiEspFsHook__ (arg: none) +Serves files from the espfs filesystem. The espFsInit function should be called first, with as argument +a pointer to the start of the espfs binary data in flash. The binary data can be both flashed separately +to a free bit of SPI flash, as well as linked in with the binary. The nonos example project can be +configured to do either. + +* __cgiEspFsTemplate__ (arg: template function) +The espfs code comes with a small but efficient template routine, which can fill a template file stored on +the espfs filesystem with user-defined data. + + +## Writing a CGI function + +A CGI function, in principle, is called when the HTTP headers have come in and the client is waiting for +the response of the webserver. The CGI function is responsible for generating this response, including +the correct headers and an appropriate body. To decide what response to generate and what other actions +to take, the CGI function can inspect various information sources, like data passed as GET- or +POST-arguments. + +A simple CGI function may, for example, greet the user with a name given as a GET argument: + +```c +int ICACHE_FLASH_ATTR cgiGreetUser(HttpdConnData *connData) { + int len; //length of user name + char name[128]; //Temporary buffer for name + char output[256]; //Temporary buffer for HTML output + + //If the browser unexpectedly closes the connection, the CGI will be called + //with connData->conn=NULL. We can use this to clean up any data. It's not really + //used in this simple CGI function. + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + if (connData->requestType!=HTTPD_METHOD_GET) { + //Sorry, we only accept GET requests. + httpdStartResponse(connData, 406); //http error code 'unacceptable' + httpdEndHeaders(connData); + return HTTPD_CGI_DONE; + } + + //Look for the 'name' GET value. If found, urldecode it and return it into the 'name' var. + len=httpdFindArg(connData->getArgs, "name", name, sizeof(name)); + if (len==-1) { + //If the result of httpdFindArg is -1, the variable isn't found in the data. + strcpy(name, "unknown person"); + } else { + //If len isn't -1, the variable is found and is copied to the 'name' variable + } + + //Generate the header + //We want the header to start with HTTP code 200, which means the document is found. + httpdStartResponse(connData, 200); + //We are going to send some HTML. + httpdHeader(connData, "Content-Type", "text/html"); + //No more headers. + httpdEndHeaders(connData); + + //We're going to send the HTML as two pieces: a head and a body. We could've also done + //it in one go, but this demonstrates multiple ways of calling httpdSend. + //Send the HTML head. Using -1 as the length will make httpdSend take the length + //of the zero-terminated string it's passed as the amount of data to send. + httpdSend(connData, "Page", -1) + //Generate the HTML body. + len=sprintf(output, "

Hello, %s!

", name); + //Send HTML body to webbrowser. We use the length as calculated by sprintf here. + //Using -1 again would also have worked, but this is more efficient. + httpdSend(connData, output, len); + + //All done. + return HTTPD_CGI_DONE; +} +``` + +Putting this CGI function into the HttpdBuiltInUrl array, for example with pattern `"/hello.cgi"`, +would allow an user to request the page `"http://192.168.4.1/hello.cgi?name=John+Doe"` and get a document +saying *"Hello, John Doe!"*. + +A word of warning: while it may look like you could forego the entire +httpdStartResponse/httpdHeader/httpdEndHeader structure and send all the HTTP headers using httpdSend, +this will break a few things that need to know when the headers are finished, for example the +HTTP 1.1 chunked transfer mode. + +The approach of parsing the arguments, building up a response and then sending it in one go is pretty +simple and works just fine for small bits of data. The gotcha here is that all http data sent during the +CGI function (headers and data) are temporarily stored in a buffer, which is sent to the client when +the function returns. The size of this buffer is typically about 2K; if the CGI tries to send more than +this, data will be lost. + +The way to get around this is to send part of the data using `httpdSend` and then return with `HTTPD_CGI_MORE` +instead of `HTTPD_CGI_DONE`. The webserver will send the partial data and will call the CGI function +again so it can send another part of the data, until the CGI function finally returns with `HTTPD_CGI_DONE`. +The CGI can store it's state in connData->cgiData, which is a freely usable pointer that will persist across +all calls in the request. It is NULL on the first call, and the standard way of doing things is to allocate +a pointer to a struct that stores state here. Here's an example: + +```c +typedef struct { + char *stringPos; +} LongStringState; + +static char *longString="Please assume this is a very long string, way too long to be sent"\ + "in one time because it won't fit in the send buffer in it's entirety; we have to"\ + "break up sending it in multiple parts." + +int ICACHE_FLASH_ATTR cgiSendLongString(HttpdConnData *connData) { + LongStringState *state=connData->cgiData; + int len; + + //If the browser unexpectedly closes the connection, the CGI will be called + //with connData->conn=NULL. We can use this to clean up any data. It's pretty relevant + //here because otherwise we may leak memory when the browser aborts the connection. + if (connData->conn==NULL) { + //Connection aborted. Clean up. + if (state!=NULL) free(state); + return HTTPD_CGI_DONE; + } + + if (state==NULL) { + //This is the first call to the CGI for this webbrowser request. + //Allocate a state structure. + state=malloc(sizeof(LongStringState); + //Save the ptr in connData so we get it passed the next time as well. + connData->cgiData=state; + //Set initial pointer to start of string + state->stringPos=longString; + //We need to send the headers before sending any data. Do that now. + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/plain"); + httpdEndHeaders(connData); + } + + //Figure out length of string to send. We will never send more than 128 bytes in this example. + len=strlen(state->stringPos); //Get remaining length + if (len>128) len=128; //Never send more than 128 bytes + + //Send that amount of data + httpdSend(connData, state->stringPos, len); + //Adjust stringPos to first byte we haven't sent yet + state->stringPos+=len; + //See if we need to send more + if (strlen(state->stringPos)!=0) { + //we have more to send; let the webserver call this function again. + return HTTPD_CGI_MORE; + } else { + //We're done. Clean up here as well: if the CGI function returns HTTPD_CGI_DONE, it will + //not be called again. + free(state); + return HTTPD_CGI_DONE; + } +} + +``` + +For POST data, a similar technique is used. For small amounts of POST data (smaller than MAX_POST, typically +1024 bytes) the entire thing will be stored in `connData->post->buff` and is accessible in its entirely +on the first call to the CGI function. For example, when using POST to send form data, if the amount of expected +data is low, it is acceptable to do a call like `len=httpdFindArg(connData->post->buff, "varname", buff, sizeof(buff));` +to get the data for the individual form elements. + +In all cases, `connData->post->len` will contain the length of the entirety of the POST data, while +`connData->post->buffLen` contains the length of the data in `connData->post->buff`. In the case where the +total POST data is larger than the POST buffer, the latter will be less than the former. In this case, the +CGI function is expected to not send any headers or data out yet, but to process the incoming bit of POST data and +return with `HTTPD_CGI_MORE`. The next call will contain the next chunk of POST data. `connData->post->received` +will always contain the total amount of POST data received for the request, including the data passed +to the CGI. When that number equals `connData->post->len`, it means no more POST data is expected and +the CGI function is free to send out the reply headers and data for the request. + +## The template engine + +The espfs driver comes with a tiny template engine, which allows for runtime-calculated value changes in a static +html page. It can be included in the builtInUrls variable like this: + +```c + {"/showname.tpl", cgiEspFsTemplate, tplShowName} +``` + +It requires two things. First of all, the template is needed, which specifically is a file on the espfs with the +same name as the first argument of the builtInUrls value, in this case `showname.tpl`. It is a standard HTML file +containing a number of %name% entries. For example: + +```html + +Welcome + +

Welcome, %username%, to the %thing%!

+ + +``` + +When this URL is requested, the words between percent characters will invoke the `tplShowName` function, allowing +it to output specific data. For example: + +```c +int ICACHE_FLASH_ATTR tplShowName(HttpdConnData *connData, char *token, void **arg) { + if (token==NULL) return HTTPD_CGI_DONE; + + if (os_strcmp(token, "username")==0) httpdSend(connData, "John Doe", -1); + if (os_strcmp(token, "thing")==0) httpdSend(connData, "ESP8266 webserver", -1); + + return HTTPD_CGI_DONE; +} +``` + +This will result in a page stating *Welcome, John Doe, to the ESP8266 webserver!*. + + +## Websocket functionality + +ToDo: document this \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/core/auth.c b/firmwares/minetest/libesphttpd/core/auth.c new file mode 100644 index 0000000..e244a44 --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/auth.c @@ -0,0 +1,61 @@ +/* +HTTP auth implementation. Only does basic authentication for now. +*/ + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +#include +#include "auth.h" +#include "base64.h" + +int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData) { + const char *forbidden="401 Forbidden."; + int no=0; + int r; + char hdr[(AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2)*10]; + char userpass[AUTH_MAX_USER_LEN+AUTH_MAX_PASS_LEN+2]; + char user[AUTH_MAX_USER_LEN]; + char pass[AUTH_MAX_PASS_LEN]; + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + r=httpdGetHeader(connData, "Authorization", hdr, sizeof(hdr)); + if (r && strncmp(hdr, "Basic", 5)==0) { + r=base64_decode(strlen(hdr)-6, hdr+6, sizeof(userpass), (unsigned char *)userpass); + if (r<0) r=0; //just clean out string on decode error + userpass[r]=0; //zero-terminate user:pass string +// printf("Auth: %s\n", userpass); + while (((AuthGetUserPw)(connData->cgiArg))(connData, no, + user, AUTH_MAX_USER_LEN, pass, AUTH_MAX_PASS_LEN)) { + //Check user/pass against auth header + if (strlen(userpass)==strlen(user)+strlen(pass)+1 && + strncmp(userpass, user, strlen(user))==0 && + userpass[strlen(user)]==':' && + strcmp(userpass+strlen(user)+1, pass)==0) { + //Authenticated. Yay! + return HTTPD_CGI_AUTHENTICATED; + } + no++; //Not authenticated with this user/pass. Check next user/pass combo. + } + } + + //Not authenticated. Go bug user with login screen. + httpdStartResponse(connData, 401); + httpdHeader(connData, "Content-Type", "text/plain"); + httpdHeader(connData, "WWW-Authenticate", "Basic realm=\""HTTP_AUTH_REALM"\""); + httpdEndHeaders(connData); + httpdSend(connData, forbidden, -1); + //Okay, all done. + return HTTPD_CGI_DONE; +} + diff --git a/firmwares/minetest/libesphttpd/core/base64.c b/firmwares/minetest/libesphttpd/core/base64.c new file mode 100644 index 0000000..3e9dc58 --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/base64.c @@ -0,0 +1,109 @@ +/* base64.c : base-64 / MIME encode/decode */ +/* PUBLIC DOMAIN - Jon Mayo - November 13, 2003 */ +#include +#include "base64.h" + +static const int base64dec_tab[256] ICACHE_RODATA_ATTR={ + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, + 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, + 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +}; + +#if 0 +static int ICACHE_FLASH_ATTR base64decode(const char in[4], char out[3]) { + uint8_t v[4]; + + v[0]=base64dec_tab[(unsigned)in[0]]; + v[1]=base64dec_tab[(unsigned)in[1]]; + v[2]=base64dec_tab[(unsigned)in[2]]; + v[3]=base64dec_tab[(unsigned)in[3]]; + + out[0]=(v[0]<<2)|(v[1]>>4); + out[1]=(v[1]<<4)|(v[2]>>2); + out[2]=(v[2]<<6)|(v[3]); + return (v[0]|v[1]|v[2]|v[3])!=255 ? in[3]=='=' ? in[2]=='=' ? 1 : 2 : 3 : 0; +} +#endif + +/* decode a base64 string in one shot */ +int ICACHE_FLASH_ATTR base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out) { + unsigned int ii, io; + uint32_t v; + unsigned int rem; + + for(io=0,ii=0,v=0,rem=0;ii=8) { + rem-=8; + if(io>=out_len) return -1; /* truncation is failure */ + out[io++]=(v>>rem)&255; + } + } + if(rem>=8) { + rem-=8; + if(io>=out_len) return -1; /* truncation is failure */ + out[io++]=(v>>rem)&255; + } + return io; +} + +static const uint8_t base64enc_tab[64]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +#if 0 +void base64encode(const unsigned char in[3], unsigned char out[4], int count) { + out[0]=base64enc_tab[(in[0]>>2)]; + out[1]=base64enc_tab[((in[0]&3)<<4)|(in[1]>>4)]; + out[2]=count<2 ? '=' : base64enc_tab[((in[1]&15)<<2)|(in[2]>>6)]; + out[3]=count<3 ? '=' : base64enc_tab[(in[2]&63)]; +} +#endif + +int ICACHE_FLASH_ATTR base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out) { + unsigned ii, io; + uint32_t v; + unsigned rem; + + for(io=0,ii=0,v=0,rem=0;ii=6) { + rem-=6; + if(io>=out_len) return -1; /* truncation is failure */ + out[io++]=base64enc_tab[(v>>rem)&63]; + } + } + if(rem) { + v<<=(6-rem); + if(io>=out_len) return -1; /* truncation is failure */ + out[io++]=base64enc_tab[v&63]; + } + while(io&3) { + if(io>=out_len) return -1; /* truncation is failure */ + out[io++]='='; + } + if(io>=out_len) return -1; /* no room for null terminator */ + out[io]=0; + return io; +} + diff --git a/firmwares/minetest/libesphttpd/core/base64.h b/firmwares/minetest/libesphttpd/core/base64.h new file mode 100644 index 0000000..a6a4bae --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/base64.h @@ -0,0 +1,6 @@ +#ifndef BASE64_H +#define BASE64_H + +int base64_decode(size_t in_len, const char *in, size_t out_len, unsigned char *out); +int base64_encode(size_t in_len, const unsigned char *in, size_t out_len, char *out); +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/core/httpd-freertos.c b/firmwares/minetest/libesphttpd/core/httpd-freertos.c new file mode 100644 index 0000000..0398b58 --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/httpd-freertos.c @@ -0,0 +1,243 @@ +/* +ESP8266 web server - platform-dependent routines, FreeRTOS version + + +Thanks to my collague at Espressif for writing the foundations of this code. +*/ +#ifdef FREERTOS + + +#include +#include "httpd.h" +#include "platform.h" +#include "httpd-platform.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" + +#include "lwip/lwip/sockets.h" + + +static int httpPort; +static int httpMaxConnCt; + +struct RtosConnType{ + int fd; + int needWriteDoneNotif; + int needsClose; + int port; + char ip[4]; +}; + +static RtosConnType rconn[HTTPD_MAX_CONNECTIONS]; + +int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) { + conn->needWriteDoneNotif=1; + return (write(conn->fd, buff, len)>=0); +} + +void ICACHE_FLASH_ATTR httpdPlatDisconnect(ConnTypePtr conn) { + conn->needsClose=1; + conn->needWriteDoneNotif=1; //because the real close is done in the writable select code +} + +void httpdPlatDisableTimeout(ConnTypePtr conn) { + //Unimplemented for FreeRTOS +} + + +#define RECV_BUF_SIZE 2048 +static void platHttpServerTask(void *pvParameters) { + int32 listenfd; + int32 remotefd; + int32 len; + int32 ret; + int x; + int maxfdp = 0; + char *precvbuf; + fd_set readset,writeset; + struct sockaddr name; + //struct timeval timeout; + struct sockaddr_in server_addr; + struct sockaddr_in remote_addr; + + for (x=0; xmaxfdp) maxfdp=rconn[x].fd; + } else { + socketsFull=0; + } + } + + if (!socketsFull) { + FD_SET(listenfd, &readset); + if (listenfd>maxfdp) maxfdp=listenfd; + } + + //polling all exist client handle,wait until readable/writable + ret = select(maxfdp+1, &readset, &writeset, NULL, NULL);//&timeout + if(ret > 0){ + //See if we need to accept a new connection + if (FD_ISSET(listenfd, &readset)) { + len=sizeof(struct sockaddr_in); + remotefd = accept(listenfd, (struct sockaddr *)&remote_addr, (socklen_t *)&len); + if (remotefd<0) { + httpd_printf("platHttpServerTask: Huh? Accept failed.\n"); + continue; + } + for(x=0; xsin_port; + memcpy(&rconn[x].ip, &piname->sin_addr.s_addr, sizeof(rconn[x].ip)); + + httpdConnectCb(&rconn[x], rconn[x].ip, rconn[x].port); + //os_timer_disarm(&connData[x].conn->stop_watch); + //os_timer_setfn(&connData[x].conn->stop_watch, (os_timer_func_t *)httpserver_conn_watcher, connData[x].conn); + //os_timer_arm(&connData[x].conn->stop_watch, STOP_TIMER, 0); +// httpd_printf("httpserver acpt index %d sockfd %d!\n", x, remotefd); + } + + //See if anything happened on the existing connections. + for(x=0; x < HTTPD_MAX_CONNECTIONS; x++){ + //Skip empty slots + if (rconn[x].fd==-1) continue; + + //Check for write availability first: the read routines may write needWriteDoneNotif while + //the select didn't check for that. + if (rconn[x].needWriteDoneNotif && FD_ISSET(rconn[x].fd, &writeset)) { + rconn[x].needWriteDoneNotif=0; //Do this first, httpdSentCb may write something making this 1 again. + if (rconn[x].needsClose) { + //Do callback and close fd. + httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); + close(rconn[x].fd); + rconn[x].fd=-1; + } else { + httpdSentCb(&rconn[x], rconn[x].ip, rconn[x].port); + } + } + + if (FD_ISSET(rconn[x].fd, &readset)) { + precvbuf=(char*)malloc(RECV_BUF_SIZE); + if (precvbuf==NULL) httpd_printf("platHttpServerTask: memory exhausted!\n"); + ret=recv(rconn[x].fd, precvbuf, RECV_BUF_SIZE,0); + if (ret > 0) { + //Data received. Pass to httpd. + httpdRecvCb(&rconn[x], rconn[x].ip, rconn[x].port, precvbuf, ret); + } else { + //recv error,connection close + httpdDisconCb(&rconn[x], rconn[x].ip, rconn[x].port); + close(rconn[x].fd); + rconn[x].fd=-1; + } + if (precvbuf) free(precvbuf); + } + } + } + } + +#if 0 +//Deinit code, not used here. + /*release data connection*/ + for(x=0; x < HTTPD_MAX_CONNECTIONS; x++){ + //find all valid handle + if(connData[x].conn == NULL) continue; + if(connData[x].conn->sockfd >= 0){ + os_timer_disarm((os_timer_t *)&connData[x].conn->stop_watch); + close(connData[x].conn->sockfd); + connData[x].conn->sockfd = -1; + connData[x].conn = NULL; + if(connData[x].cgi!=NULL) connData[x].cgi(&connData[x]); //flush cgi data + httpdRetireConn(&connData[x]); + } + } + /*release listen socket*/ + close(listenfd); + + vTaskDelete(NULL); +#endif +} + + + +//Initialize listening socket, do general initialization +void ICACHE_FLASH_ATTR httpdPlatInit(int port, int maxConnCt) { + httpPort=port; + httpMaxConnCt=maxConnCt; + xTaskCreate(platHttpServerTask, (const signed char *)"esphttpd", HTTPD_STACKSIZE, NULL, 4, NULL); +} + + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/core/httpd-nonos.c b/firmwares/minetest/libesphttpd/core/httpd-nonos.c new file mode 100644 index 0000000..2fc7314 --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/httpd-nonos.c @@ -0,0 +1,76 @@ +/* +ESP8266 web server - platform-dependent routines, nonos version +*/ + +#include +#include "httpd.h" +#include "platform.h" +#include "httpd-platform.h" + +#ifndef FREERTOS + +//Listening connection data +static struct espconn httpdConn; +static esp_tcp httpdTcp; + + +static void ICACHE_FLASH_ATTR platReconCb(void *arg, sint8 err) { + //Yeah, this is pretty useless... +} + +static void ICACHE_FLASH_ATTR platDisconCb(void *arg) { + ConnTypePtr conn=arg; + httpdDisconCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port); +} + +static void ICACHE_FLASH_ATTR platRecvCb(void *arg, char *data, unsigned short len) { + ConnTypePtr conn=arg; + httpdRecvCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port, data, len); +} + +static void ICACHE_FLASH_ATTR platSentCb(void *arg) { + ConnTypePtr conn=arg; + httpdSentCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port); +} + +static void ICACHE_FLASH_ATTR platConnCb(void *arg) { + ConnTypePtr conn=arg; + if (httpdConnectCb(conn, (char*)conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port)) { + espconn_regist_recvcb(conn, platRecvCb); + espconn_regist_reconcb(conn, platReconCb); + espconn_regist_disconcb(conn, platDisconCb); + espconn_regist_sentcb(conn, platSentCb); + } else { + espconn_disconnect(conn); + } +} + + +int ICACHE_FLASH_ATTR httpdPlatSendData(ConnTypePtr conn, char *buff, int len) { + int r; + r=espconn_sent(conn, (uint8_t*)buff, len); + return (r>=0); +} + +void ICACHE_FLASH_ATTR httpdPlatDisconnect(ConnTypePtr conn) { + espconn_disconnect(conn); +} + +void ICACHE_FLASH_ATTR httpdPlatDisableTimeout(ConnTypePtr conn) { + //Can't disable timeout; set to 2 hours instead. + espconn_regist_time(conn, 7199, 1); +} + +//Initialize listening socket, do general initialization +void ICACHE_FLASH_ATTR httpdPlatInit(int port, int maxConnCt) { + httpdConn.type=ESPCONN_TCP; + httpdConn.state=ESPCONN_NONE; + httpdTcp.local_port=port; + httpdConn.proto.tcp=&httpdTcp; + espconn_regist_connectcb(&httpdConn, platConnCb); + espconn_accept(&httpdConn); + espconn_tcp_set_max_con_allow(&httpdConn, maxConnCt); +} + + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/core/httpd-platform.h b/firmwares/minetest/libesphttpd/core/httpd-platform.h new file mode 100644 index 0000000..e3e5140 --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/httpd-platform.h @@ -0,0 +1,9 @@ +#ifndef HTTPD_PLATFORM_H +#define HTTPD_PLATFORM_H + +int httpdPlatSendData(ConnTypePtr conn, char *buff, int len); +void httpdPlatDisconnect(ConnTypePtr conn); +void httpdPlatDisableTimeout(ConnTypePtr conn); +void httpdPlatInit(int port, int maxConnCt); + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/core/httpd.c b/firmwares/minetest/libesphttpd/core/httpd.c new file mode 100644 index 0000000..28a1ad0 --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/httpd.c @@ -0,0 +1,775 @@ +/* +Esp8266 http server - core routines +*/ + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +#include +#include "httpd.h" +#include "httpd-platform.h" + + +//Max length of request head. This is statically allocated for each connection. +#define MAX_HEAD_LEN 1024 +//Max post buffer len. This is dynamically malloc'ed if needed. +#define MAX_POST 1024 +//Max send buffer len. This is allocated on the stack. +#define MAX_SENDBUFF_LEN 2048 +//If some data can't be sent because the underlaying socket doesn't accept the data (like the nonos +//layer is prone to do), we put it in a backlog that is dynamically malloc'ed. This defines the max +//size of the backlog. +#define MAX_BACKLOG_SIZE (4*1024) + +//This gets set at init time. +static HttpdBuiltInUrl *builtInUrls; + +typedef struct HttpSendBacklogItem HttpSendBacklogItem; + +struct HttpSendBacklogItem { + int len; + HttpSendBacklogItem *next; + char data[]; +}; + +//Flags +#define HFL_HTTP11 (1<<0) +#define HFL_CHUNKED (1<<1) +#define HFL_SENDINGBODY (1<<2) +#define HFL_DISCONAFTERSENT (1<<3) + +//Private data for http connection +struct HttpdPriv { + char head[MAX_HEAD_LEN]; + int headPos; + char *sendBuff; + int sendBuffLen; + char *chunkHdr; + HttpSendBacklogItem *sendBacklog; + int sendBacklogSize; + int flags; +}; + + +//Connection pool +static HttpdConnData *connData[HTTPD_MAX_CONNECTIONS]; + +//Struct to keep extension->mime data in +typedef struct { + const char *ext; + const char *mimetype; +} MimeMap; + + +//#define RSTR(a) ((const char)(a)) + +//The mappings from file extensions to mime types. If you need an extra mime type, +//add it here. +static const ICACHE_RODATA_ATTR MimeMap mimeTypes[]={ + {"htm", "text/htm"}, + {"html", "text/html"}, + {"css", "text/css"}, + {"js", "text/javascript"}, + {"txt", "text/plain"}, + {"jpg", "image/jpeg"}, + {"jpeg", "image/jpeg"}, + {"png", "image/png"}, + {"svg", "image/svg+xml"}, + {NULL, "text/html"}, //default value +}; + +//Returns a static char* to a mime type for a given url to a file. +const char ICACHE_FLASH_ATTR *httpdGetMimetype(char *url) { + int i=0; + //Go find the extension + char *ext=url+(strlen(url)-1); + while (ext!=url && *ext!='.') ext--; + if (*ext=='.') ext++; + + //ToDo: strcmp is case sensitive; we may want to do case-intensive matching here... + while (mimeTypes[i].ext!=NULL && strcmp(ext, mimeTypes[i].ext)!=0) i++; + return mimeTypes[i].mimetype; +} + +//Looks up the connData info for a specific connection +static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(ConnTypePtr conn, char *remIp, int remPort) { + for (int i=0; iremote_port == remPort && + memcmp(connData[i]->remote_ip, remIp, 4) == 0) { + connData[i]->conn=conn; + return connData[i]; + } + } + //Shouldn't happen. + httpd_printf("*** Unknown connection %d.%d.%d.%d:%d\n", remIp[0]&0xff, remIp[1]&0xff, remIp[2]&0xff, remIp[3]&0xff, remPort); + httpdPlatDisconnect(conn); + return NULL; +} + +//Retires a connection for re-use +static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) { + if (conn->priv->sendBacklog!=NULL) { + HttpSendBacklogItem *i, *j; + i=conn->priv->sendBacklog; + do { + j=i; + i=i->next; + free(j); + } while (i!=NULL); + } + if (conn->post->buff!=NULL) free(conn->post->buff); + if (conn->post!=NULL) free(conn->post); + if (conn->priv!=NULL) free(conn->priv); + if (conn) free(conn); + for (int i=0; i='0' && c<='9') return c-'0'; + if (c>='A' && c<='F') return c-'A'+10; + if (c>='a' && c<='f') return c-'a'+10; + return 0; +} + +//Decode a percent-encoded value. +//Takes the valLen bytes stored in val, and converts it into at most retLen bytes that +//are stored in the ret buffer. Returns the actual amount of bytes used in ret. Also +//zero-terminates the ret buffer. +int ICACHE_FLASH_ATTR httpdUrlDecode(char *val, int valLen, char *ret, int retLen) { + int s=0, d=0; + int esced=0, escVal=0; + while (spriv->head; + p=p+strlen(p)+1; //skip GET/POST part + p=p+strlen(p)+1; //skip HTTP part + while (p<(conn->priv->head+conn->priv->headPos)) { + while(*p<=32 && *p!=0) p++; //skip crap at start + //See if this is the header + if (strncmp(p, header, strlen(header))==0 && p[strlen(header)]==':') { + //Skip 'key:' bit of header line + p=p+strlen(header)+1; + //Skip past spaces after the colon + while(*p==' ') p++; + //Copy from p to end + while (*p!=0 && *p!='\r' && *p!='\n' && retLen>1) { + *ret++=*p++; + retLen--; + } + //Zero-terminate string + *ret=0; + //All done :) + return 1; + } + p+=strlen(p)+1; //Skip past end of string and \0 terminator + } + return 0; +} + +//Call before calling httpdStartResponse to disable automatically-chosen transfer +//encodings (specifically, for now, chunking) and fall back on Connection: Close. +void ICACHE_FLASH_ATTR httpdDisableTransferEncoding(HttpdConnData *conn) { + conn->priv->flags&=~HFL_CHUNKED; +} + +//Start the response headers. +void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) { + char buff[256]; + int l; + l=sprintf(buff, "HTTP/1.%d %d OK\r\nServer: esp8266-httpd/"HTTPDVER"\r\n%s\r\n", + (conn->priv->flags&HFL_HTTP11)?1:0, + code, + (conn->priv->flags&HFL_CHUNKED)?"Transfer-Encoding: chunked":"Connection: close"); + httpdSend(conn, buff, l); +} + +//Send a http header. +void ICACHE_FLASH_ATTR httpdHeader(HttpdConnData *conn, const char *field, const char *val) { + httpdSend(conn, field, -1); + httpdSend(conn, ": ", -1); + httpdSend(conn, val, -1); + httpdSend(conn, "\r\n", -1); +} + +//Finish the headers. +void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn) { + httpdSend(conn, "\r\n", -1); + conn->priv->flags|=HFL_SENDINGBODY; +} + +//Redirect to the given URL. +void ICACHE_FLASH_ATTR httpdRedirect(HttpdConnData *conn, char *newUrl) { + httpdStartResponse(conn, 302); + httpdHeader(conn, "Location", newUrl); + httpdEndHeaders(conn); + httpdSend(conn, "Moved to ", -1); + httpdSend(conn, newUrl, -1); +} + +//Use this as a cgi function to redirect one url to another. +int ICACHE_FLASH_ATTR cgiRedirect(HttpdConnData *connData) { + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + httpdRedirect(connData, (char*)connData->cgiArg); + return HTTPD_CGI_DONE; +} + +//Used to spit out a 404 error +static int ICACHE_FLASH_ATTR cgiNotFound(HttpdConnData *connData) { + if (connData->conn==NULL) return HTTPD_CGI_DONE; + httpdStartResponse(connData, 404); + httpdEndHeaders(connData); + httpdSend(connData, "404 File not found.", -1); + return HTTPD_CGI_DONE; +} + +//This CGI function redirects to a fixed url of http://[hostname]/ if hostname field of request isn't +//already that hostname. Use this in combination with a DNS server that redirects everything to the +//ESP in order to load a HTML page as soon as a phone, tablet etc connects to the ESP. Watch out: +//this will also redirect connections when the ESP is in STA mode, potentially to a hostname that is not +//in the 'official' DNS and so will fail. +int ICACHE_FLASH_ATTR cgiRedirectToHostname(HttpdConnData *connData) { + static const char hostFmt[]="http://%s/"; + char *buff; + int isIP=0; + int x; + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + if (connData->hostName==NULL) { + httpd_printf("Huh? No hostname.\n"); + return HTTPD_CGI_NOTFOUND; + } + + //Quick and dirty code to see if host is an IP + if (strlen(connData->hostName)>8) { + isIP=1; + for (x=0; xhostName); x++) { + if (connData->hostName[x]!='.' && (connData->hostName[x]<'0' || connData->hostName[x]>'9')) isIP=0; + } + } + if (isIP) return HTTPD_CGI_NOTFOUND; + //Check hostname; pass on if the same + if (strcmp(connData->hostName, (char*)connData->cgiArg)==0) return HTTPD_CGI_NOTFOUND; + //Not the same. Redirect to real hostname. + buff=malloc(strlen((char*)connData->cgiArg)+sizeof(hostFmt)); + sprintf(buff, hostFmt, (char*)connData->cgiArg); + httpd_printf("Redirecting to hostname url %s\n", buff); + httpdRedirect(connData, buff); + free(buff); + return HTTPD_CGI_DONE; +} + + +//Same as above, but will only redirect clients with an IP that is in the range of +//the SoftAP interface. This should preclude clients connected to the STA interface +//to be redirected to nowhere. +int ICACHE_FLASH_ATTR cgiRedirectApClientToHostname(HttpdConnData *connData) { +#ifndef FREERTOS + uint32 *remadr; + struct ip_info apip; + int x=wifi_get_opmode(); + //Check if we have an softap interface; bail out if not + if (x!=2 && x!=3) return HTTPD_CGI_NOTFOUND; + remadr=(uint32 *)connData->remote_ip; + wifi_get_ip_info(SOFTAP_IF, &apip); + if ((*remadr & apip.netmask.addr) == (apip.ip.addr & apip.netmask.addr)) { + return cgiRedirectToHostname(connData); + } else { + return HTTPD_CGI_NOTFOUND; + } +#else + return HTTPD_CGI_NOTFOUND; +#endif +} + + +//Add data to the send buffer. len is the length of the data. If len is -1 +//the data is seen as a C-string. +//Returns 1 for success, 0 for out-of-memory. +int ICACHE_FLASH_ATTR httpdSend(HttpdConnData *conn, const char *data, int len) { + if (conn->conn==NULL) return 0; + if (len<0) len=strlen(data); + if (len==0) return 0; + if (conn->priv->flags&HFL_CHUNKED && conn->priv->flags&HFL_SENDINGBODY && conn->priv->chunkHdr==NULL) { + if (conn->priv->sendBuffLen+len+6>MAX_SENDBUFF_LEN) return 0; + //Establish start of chunk + conn->priv->chunkHdr=&conn->priv->sendBuff[conn->priv->sendBuffLen]; + strcpy(conn->priv->chunkHdr, "0000\r\n"); + conn->priv->sendBuffLen+=6; + } + if (conn->priv->sendBuffLen+len>MAX_SENDBUFF_LEN) return 0; + memcpy(conn->priv->sendBuff+conn->priv->sendBuffLen, data, len); + conn->priv->sendBuffLen+=len; + return 1; +} + +static char ICACHE_FLASH_ATTR httpdHexNibble(int val) { + val&=0xf; + if (val<10) return '0'+val; + return 'A'+(val-10); +} + +//Function to send any data in conn->priv->sendBuff. Do not use in CGIs unless you know what you +//are doing! Also, if you do set conn->cgi to NULL to indicate the connection is closed, do it BEFORE +//calling this. +void ICACHE_FLASH_ATTR httpdFlushSendBuffer(HttpdConnData *conn) { + int r, len; + if (conn->conn==NULL) return; + if (conn->priv->chunkHdr!=NULL) { + //We're sending chunked data, and the chunk needs fixing up. + //Finish chunk with cr/lf + httpdSend(conn, "\r\n", 2); + //Calculate length of chunk + len=((&conn->priv->sendBuff[conn->priv->sendBuffLen])-conn->priv->chunkHdr)-8; + //Fix up chunk header to correct value + conn->priv->chunkHdr[0]=httpdHexNibble(len>>12); + conn->priv->chunkHdr[1]=httpdHexNibble(len>>8); + conn->priv->chunkHdr[2]=httpdHexNibble(len>>4); + conn->priv->chunkHdr[3]=httpdHexNibble(len>>0); + //Reset chunk hdr for next call + conn->priv->chunkHdr=NULL; + } + if (conn->priv->flags&HFL_CHUNKED && conn->priv->flags&HFL_SENDINGBODY && conn->cgi==NULL) { + //Connection finished sending whatever needs to be sent. Add NULL chunk to indicate this. + strcpy(&conn->priv->sendBuff[conn->priv->sendBuffLen], "0\r\n\r\n"); + conn->priv->sendBuffLen+=5; + } + if (conn->priv->sendBuffLen!=0) { + r=httpdPlatSendData(conn->conn, conn->priv->sendBuff, conn->priv->sendBuffLen); + if (!r) { + //Can't send this for some reason. Dump packet in backlog, we can send it later. + if (conn->priv->sendBacklogSize+conn->priv->sendBuffLen>MAX_BACKLOG_SIZE) { + httpd_printf("Httpd: Backlog: Exceeded max backlog size, dropped %d bytes instead of sending them.\n", conn->priv->sendBuffLen); + conn->priv->sendBuffLen=0; + return; + } + HttpSendBacklogItem *i=malloc(sizeof(HttpSendBacklogItem)+conn->priv->sendBuffLen); + if (i==NULL) { + httpd_printf("Httpd: Backlog: malloc failed, out of memory!\n"); + return; + } + memcpy(i->data, conn->priv->sendBuff, conn->priv->sendBuffLen); + i->len=conn->priv->sendBuffLen; + i->next=NULL; + if (conn->priv->sendBacklog==NULL) { + conn->priv->sendBacklog=i; + } else { + HttpSendBacklogItem *e=conn->priv->sendBacklog; + while (e->next!=NULL) e=e->next; + e->next=i; + } + conn->priv->sendBacklogSize+=conn->priv->sendBuffLen; + } + conn->priv->sendBuffLen=0; + } +} + +void ICACHE_FLASH_ATTR httpdCgiIsDone(HttpdConnData *conn) { + conn->cgi=NULL; //no need to call this anymore + if (conn->priv->flags&HFL_CHUNKED) { + httpd_printf("Pool slot %d is done. Cleaning up for next req\n", conn->slot); + httpdFlushSendBuffer(conn); + //Note: Do not clean up sendBacklog, it may still contain data at this point. + conn->priv->headPos=0; + conn->post->len=-1; + conn->priv->flags=0; + if (conn->post->buff) free(conn->post->buff); + conn->post->buff=NULL; + conn->post->buffLen=0; + conn->post->received=0; + conn->hostName=NULL; + } else { + //Cannot re-use this connection. Mark to get it killed after all data is sent. + conn->priv->flags|=HFL_DISCONAFTERSENT; + } +} + +//Callback called when the data on a socket has been successfully +//sent. +void ICACHE_FLASH_ATTR httpdSentCb(ConnTypePtr rconn, char *remIp, int remPort) { + int r; + HttpdConnData *conn=httpdFindConnData(rconn, remIp, remPort); + char *sendBuff; + + if (conn==NULL) return; + + if (conn->priv->sendBacklog!=NULL) { + //We have some backlog to send first. + HttpSendBacklogItem *next=conn->priv->sendBacklog->next; + httpdPlatSendData(conn->conn, conn->priv->sendBacklog->data, conn->priv->sendBacklog->len); + conn->priv->sendBacklogSize-=conn->priv->sendBacklog->len; + free(conn->priv->sendBacklog); + conn->priv->sendBacklog=next; + return; + } + + if (conn->priv->flags&HFL_DISCONAFTERSENT) { //Marked for destruction? + httpd_printf("Pool slot %d is done. Closing.\n", conn->slot); + httpdPlatDisconnect(conn->conn); + return; //No need to call httpdFlushSendBuffer. + } + + //If we don't have a CGI function, there's nothing to do but wait for something from the client. + if (conn->cgi==NULL) return; + + sendBuff=malloc(MAX_SENDBUFF_LEN); + conn->priv->sendBuff=sendBuff; + conn->priv->sendBuffLen=0; + r=conn->cgi(conn); //Execute cgi fn. + if (r==HTTPD_CGI_DONE) { + httpdCgiIsDone(conn); + } + if (r==HTTPD_CGI_NOTFOUND || r==HTTPD_CGI_AUTHENTICATED) { + httpd_printf("ERROR! CGI fn returns code %d after sending data! Bad CGI!\n", r); + httpdCgiIsDone(conn); + } + httpdFlushSendBuffer(conn); + free(sendBuff); +} + +//This is called when the headers have been received and the connection is ready to send +//the result headers and data. +//We need to find the CGI function to call, call it, and dependent on what it returns either +//find the next cgi function, wait till the cgi data is sent or close up the connection. +static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) { + int r; + int i=0; + if (conn->url==NULL) { + httpd_printf("WtF? url = NULL\n"); + return; //Shouldn't happen + } + //See if we can find a CGI that's happy to handle the request. + while (1) { + //Look up URL in the built-in URL table. + while (builtInUrls[i].url!=NULL) { + int match=0; + //See if there's a literal match + if (strcmp(builtInUrls[i].url, conn->url)==0) match=1; + //See if there's a wildcard match + if (builtInUrls[i].url[strlen(builtInUrls[i].url)-1]=='*' && + strncmp(builtInUrls[i].url, conn->url, strlen(builtInUrls[i].url)-1)==0) match=1; + if (match) { + httpd_printf("Is url index %d\n", i); + conn->cgiData=NULL; + conn->cgi=builtInUrls[i].cgiCb; + conn->cgiArg=builtInUrls[i].cgiArg; + break; + } + i++; + } + if (builtInUrls[i].url==NULL) { + //Drat, we're at the end of the URL table. This usually shouldn't happen. Well, just + //generate a built-in 404 to handle this. + httpd_printf("%s not found. 404!\n", conn->url); + conn->cgi=cgiNotFound; + } + + //Okay, we have a CGI function that matches the URL. See if it wants to handle the + //particular URL we're supposed to handle. + r=conn->cgi(conn); + if (r==HTTPD_CGI_MORE) { + //Yep, it's happy to do so and has more data to send. + if (conn->recvHdl) { + //Seems the CGI is planning to do some long-term communications with the socket. + //Disable the timeout on it, so we won't run into that. + httpdPlatDisableTimeout(conn->conn); + } + httpdFlushSendBuffer(conn); + return; + } else if (r==HTTPD_CGI_DONE) { + //Yep, it's happy to do so and already is done sending data. + httpdCgiIsDone(conn); + return; + } else if (r==HTTPD_CGI_NOTFOUND || r==HTTPD_CGI_AUTHENTICATED) { + //URL doesn't want to handle the request: either the data isn't found or there's no + //need to generate a login screen. + i++; //look at next url the next iteration of the loop. + } + } +} + +//Parse a line of header data and modify the connection data accordingly. +static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { + int i; + char firstLine=0; + + if (strncmp(h, "GET ", 4)==0) { + conn->requestType = HTTPD_METHOD_GET; + firstLine=1; + } else if (strncmp(h, "Host:", 5)==0) { + i=5; + while (h[i]==' ') i++; + conn->hostName=&h[i]; + } else if (strncmp(h, "POST ", 5)==0) { + conn->requestType = HTTPD_METHOD_POST; + firstLine=1; + } + + if (firstLine) { + char *e; + + //Skip past the space after POST/GET + i=0; + while (h[i]!=' ') i++; + conn->url=h+i+1; + + //Figure out end of url. + e=(char*)strstr(conn->url, " "); + if (e==NULL) return; //wtf? + *e=0; //terminate url part + e++; //Skip to protocol indicator + while (*e==' ') e++; //Skip spaces. + //If HTTP/1.1, note that and set chunked encoding + if (strcasecmp(e, "HTTP/1.1")==0) conn->priv->flags|=HFL_HTTP11|HFL_CHUNKED; + + httpd_printf("URL = %s\n", conn->url); + //Parse out the URL part before the GET parameters. + conn->getArgs=(char*)strstr(conn->url, "?"); + if (conn->getArgs!=0) { + *conn->getArgs=0; + conn->getArgs++; + httpd_printf("GET args = %s\n", conn->getArgs); + } else { + conn->getArgs=NULL; + } + } else if (strncmp(h, "Connection:", 11)==0) { + i=11; + //Skip trailing spaces + while (h[i]==' ') i++; + if (strncmp(&h[i], "close", 5)==0) conn->priv->flags&=~HFL_CHUNKED; //Don't use chunked conn + } else if (strncmp(h, "Content-Length:", 15)==0) { + i=15; + //Skip trailing spaces + while (h[i]==' ') i++; + //Get POST data length + conn->post->len=atoi(h+i); + + // Allocate the buffer + if (conn->post->len > MAX_POST) { + // we'll stream this in in chunks + conn->post->buffSize = MAX_POST; + } else { + conn->post->buffSize = conn->post->len; + } + httpd_printf("Mallocced buffer for %d + 1 bytes of post data.\n", conn->post->buffSize); + conn->post->buff=(char*)malloc(conn->post->buffSize + 1); + conn->post->buffLen=0; + } else if (strncmp(h, "Content-Type: ", 14)==0) { + if (strstr(h, "multipart/form-data")) { + // It's multipart form data so let's pull out the boundary for future use + char *b; + if ((b = strstr(h, "boundary=")) != NULL) { + conn->post->multipartBoundary = b + 7; // move the pointer 2 chars before boundary then fill them with dashes + conn->post->multipartBoundary[0] = '-'; + conn->post->multipartBoundary[1] = '-'; + httpd_printf("boundary = %s\n", conn->post->multipartBoundary); + } + } + } +} + + +//Callback called when there's data available on a socket. +void httpdRecvCb(ConnTypePtr rconn, char *remIp, int remPort, char *data, unsigned short len) { + int x, r; + char *p, *e; + char *sendBuff=malloc(MAX_SENDBUFF_LEN); + HttpdConnData *conn=httpdFindConnData(rconn, remIp, remPort); + if (conn==NULL) return; + conn->priv->sendBuff=sendBuff; + conn->priv->sendBuffLen=0; + + //This is slightly evil/dirty: we abuse conn->post->len as a state variable for where in the http communications we are: + //<0 (-1): Post len unknown because we're still receiving headers + //==0: No post data + //>0: Need to receive post data + //ToDo: See if we can use something more elegant for this. + + for (x=0; xpost->len<0) { + //This byte is a header byte. + if (data[x]=='\n') { + //Compatibility with clients that send \n only: fake a \r in front of this. + if (conn->priv->headPos!=0 && conn->priv->head[conn->priv->headPos-1]!='\r') { + conn->priv->head[conn->priv->headPos++]='\r'; + } + } + //ToDo: return http error code 431 (request header too long) if this happens + if (conn->priv->headPos!=MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++]=data[x]; + conn->priv->head[conn->priv->headPos]=0; + //Scan for /r/n/r/n. Receiving this indicate the headers end. + if (data[x]=='\n' && (char *)strstr(conn->priv->head, "\r\n\r\n")!=NULL) { + //Indicate we're done with the headers. + conn->post->len=0; + //Reset url data + conn->url=NULL; + //Iterate over all received headers and parse them. + p=conn->priv->head; + while(p<(&conn->priv->head[conn->priv->headPos-4])) { + e=(char *)strstr(p, "\r\n"); //Find end of header line + if (e==NULL) break; //Shouldn't happen. + e[0]=0; //Zero-terminate header + httpdParseHeader(p, conn); //and parse it. + p=e+2; //Skip /r/n (now /0/n) + } + //If we don't need to receive post data, we can send the response now. + if (conn->post->len==0) { + httpdProcessRequest(conn); + } + } + } else if (conn->post->len!=0) { + //This byte is a POST byte. + conn->post->buff[conn->post->buffLen++]=data[x]; + conn->post->received++; + conn->hostName=NULL; + if (conn->post->buffLen >= conn->post->buffSize || conn->post->received == conn->post->len) { + //Received a chunk of post data + conn->post->buff[conn->post->buffLen]=0; //zero-terminate, in case the cgi handler knows it can use strings + //Process the data + if (conn->cgi) { + r=conn->cgi(conn); + if (r==HTTPD_CGI_DONE) { + httpdCgiIsDone(conn); + } + } else { + //No CGI fn set yet: probably first call. Allow httpdProcessRequest to choose CGI and + //call it the first time. + httpdProcessRequest(conn); + } + conn->post->buffLen = 0; + } + } else { + //Let cgi handle data if it registered a recvHdl callback. If not, ignore. + if (conn->recvHdl) { + r=conn->recvHdl(conn, data+x, len-x); + if (r==HTTPD_CGI_DONE) { + httpd_printf("Recvhdl returned DONE\n"); + httpdCgiIsDone(conn); + //We assume the recvhdlr has sent something; we'll kill the sock in the sent callback. + } + break; //ignore rest of data, recvhdl has parsed it. + } else { + httpd_printf("Eh? Got unexpected data from client. %s\n", data); + } + } + } + if (conn->conn) httpdFlushSendBuffer(conn); + free(sendBuff); +} + +//The platform layer should ALWAYS call this function, regardless if the connection is closed by the server +//or by the client. +void ICACHE_FLASH_ATTR httpdDisconCb(ConnTypePtr rconn, char *remIp, int remPort) { + HttpdConnData *hconn=httpdFindConnData(rconn, remIp, remPort); + if (hconn==NULL) return; + httpd_printf("Pool slot %d: socket closed.\n", hconn->slot); + hconn->conn=NULL; //indicate cgi the connection is gone + if (hconn->cgi) hconn->cgi(hconn); //Execute cgi fn if needed + httpdRetireConn(hconn); +} + + +int ICACHE_FLASH_ATTR httpdConnectCb(ConnTypePtr conn, char *remIp, int remPort) { + int i; + //Find empty conndata in pool + for (i=0; ipriv=malloc(sizeof(HttpdPriv)); + memset(connData[i]->priv, 0, sizeof(HttpdPriv)); + connData[i]->conn=conn; + connData[i]->slot=i; + connData[i]->priv->headPos=0; + connData[i]->post=malloc(sizeof(HttpdPostData)); + memset(connData[i]->post, 0, sizeof(HttpdPostData)); + connData[i]->post->buff=NULL; + connData[i]->post->buffLen=0; + connData[i]->post->received=0; + connData[i]->post->len=-1; + connData[i]->hostName=NULL; + connData[i]->remote_port=remPort; + connData[i]->priv->sendBacklog=NULL; + connData[i]->priv->sendBacklogSize=0; + memcpy(connData[i]->remote_ip, remIp, 4); + + return 1; +} + +//Httpd initialization routine. Call this to kick off webserver functionality. +void ICACHE_FLASH_ATTR httpdInit(HttpdBuiltInUrl *fixedUrls, int port) { + int i; + + for (i=0; i wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +#include +#include "httpdespfs.h" +#include "espfs.h" +#include "espfsformat.h" + +// The static files marked with FLAG_GZIP are compressed and will be served with GZIP compression. +// If the client does not advertise that he accepts GZIP send following warning message (telnet users for e.g.) +static const char *gzipNonSupportedMessage = "HTTP/1.0 501 Not implemented\r\nServer: esp8266-httpd/"HTTPDVER"\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 52\r\n\r\nYour browser does not accept gzip-compressed data.\r\n"; + + +//This is a catch-all cgi function. It takes the url passed to it, looks up the corresponding +//path in the filesystem and if it exists, passes the file through. This simulates what a normal +//webserver would do with static files. +int ICACHE_FLASH_ATTR cgiEspFsHook(HttpdConnData *connData) { + EspFsFile *file=connData->cgiData; + int len; + char buff[1024]; + char acceptEncodingBuffer[64]; + int isGzip; + + if (connData->conn==NULL) { + //Connection aborted. Clean up. + espFsClose(file); + return HTTPD_CGI_DONE; + } + + if (file==NULL) { + //First call to this cgi. Open the file so we can read it. + file=espFsOpen(connData->url); + if (file==NULL) { + return HTTPD_CGI_NOTFOUND; + } + + // The gzip checking code is intentionally without #ifdefs because checking + // for FLAG_GZIP (which indicates gzip compressed file) is very easy, doesn't + // mean additional overhead and is actually safer to be on at all times. + // If there are no gzipped files in the image, the code bellow will not cause any harm. + + // Check if requested file was GZIP compressed + isGzip = espFsFlags(file) & FLAG_GZIP; + if (isGzip) { + // Check the browser's "Accept-Encoding" header. If the client does not + // advertise that he accepts GZIP send a warning message (telnet users for e.g.) + httpdGetHeader(connData, "Accept-Encoding", acceptEncodingBuffer, 64); + if (strstr(acceptEncodingBuffer, "gzip") == NULL) { + //No Accept-Encoding: gzip header present + httpdSend(connData, gzipNonSupportedMessage, -1); + espFsClose(file); + return HTTPD_CGI_DONE; + } + } + + connData->cgiData=file; + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); + if (isGzip) { + httpdHeader(connData, "Content-Encoding", "gzip"); + } + httpdHeader(connData, "Cache-Control", "max-age=3600, must-revalidate"); + httpdEndHeaders(connData); + return HTTPD_CGI_MORE; + } + + len=espFsRead(file, buff, 1024); + if (len>0) httpdSend(connData, buff, len); + if (len!=1024) { + //We're done. + espFsClose(file); + return HTTPD_CGI_DONE; + } else { + //Ok, till next time. + return HTTPD_CGI_MORE; + } +} + + +//cgiEspFsTemplate can be used as a template. + +typedef struct { + EspFsFile *file; + void *tplArg; + char token[64]; + int tokenPos; +} TplData; + +typedef void (* TplCallback)(HttpdConnData *connData, char *token, void **arg); + +int ICACHE_FLASH_ATTR cgiEspFsTemplate(HttpdConnData *connData) { + TplData *tpd=connData->cgiData; + int len; + int x, sp=0; + char *e=NULL; + char buff[1025]; + + if (connData->conn==NULL) { + //Connection aborted. Clean up. + ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); + espFsClose(tpd->file); + free(tpd); + return HTTPD_CGI_DONE; + } + + if (tpd==NULL) { + //First call to this cgi. Open the file so we can read it. + tpd=(TplData *)malloc(sizeof(TplData)); + tpd->file=espFsOpen(connData->url); + tpd->tplArg=NULL; + tpd->tokenPos=-1; + if (tpd->file==NULL) { + espFsClose(tpd->file); + free(tpd); + return HTTPD_CGI_NOTFOUND; + } + if (espFsFlags(tpd->file) & FLAG_GZIP) { + httpd_printf("cgiEspFsTemplate: Trying to use gzip-compressed file %s as template!\n", connData->url); + espFsClose(tpd->file); + free(tpd); + return HTTPD_CGI_NOTFOUND; + } + connData->cgiData=tpd; + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", httpdGetMimetype(connData->url)); + httpdEndHeaders(connData); + return HTTPD_CGI_MORE; + } + + len=espFsRead(tpd->file, buff, 1024); + if (len>0) { + sp=0; + e=buff; + for (x=0; xtokenPos==-1) { + //Inside ordinary text. + if (buff[x]=='%') { + //Send raw data up to now + if (sp!=0) httpdSend(connData, e, sp); + sp=0; + //Go collect token chars. + tpd->tokenPos=0; + } else { + sp++; + } + } else { + if (buff[x]=='%') { + if (tpd->tokenPos==0) { + //This is the second % of a %% escape string. + //Send a single % and resume with the normal program flow. + httpdSend(connData, "%", 1); + } else { + //This is an actual token. + tpd->token[tpd->tokenPos++]=0; //zero-terminate token + ((TplCallback)(connData->cgiArg))(connData, tpd->token, &tpd->tplArg); + } + //Go collect normal chars again. + e=&buff[x+1]; + tpd->tokenPos=-1; + } else { + if (tpd->tokenPos<(sizeof(tpd->token)-1)) tpd->token[tpd->tokenPos++]=buff[x]; + } + } + } + } + //Send remaining bit. + if (sp!=0) httpdSend(connData, e, sp); + if (len!=1024) { + //We're done. + ((TplCallback)(connData->cgiArg))(connData, NULL, &tpd->tplArg); + espFsClose(tpd->file); + free(tpd); + return HTTPD_CGI_DONE; + } else { + //Ok, till next time. + return HTTPD_CGI_MORE; + } +} + diff --git a/firmwares/minetest/libesphttpd/core/sha1.c b/firmwares/minetest/libesphttpd/core/sha1.c new file mode 100644 index 0000000..062db2c --- /dev/null +++ b/firmwares/minetest/libesphttpd/core/sha1.c @@ -0,0 +1,168 @@ +/* This code is public-domain - it is based on libcrypt + * placed in the public domain by Wei Dai and other contributors. + */ +// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test + +#include +#include +#include + +#include "sha1.h" + +//according to http://ip.cadence.com/uploads/pdf/xtensalx_overview_handbook.pdf +// the cpu is normally defined as little ending, but can be big endian too. +// for the esp this seems to work +//#define SHA_BIG_ENDIAN + + + +/* code */ +#define SHA1_K0 0x5a827999 +#define SHA1_K20 0x6ed9eba1 +#define SHA1_K40 0x8f1bbcdc +#define SHA1_K60 0xca62c1d6 + +void ICACHE_FLASH_ATTR sha1_init(sha1nfo *s) { + s->state[0] = 0x67452301; + s->state[1] = 0xefcdab89; + s->state[2] = 0x98badcfe; + s->state[3] = 0x10325476; + s->state[4] = 0xc3d2e1f0; + s->byteCount = 0; + s->bufferOffset = 0; +} + +uint32_t ICACHE_FLASH_ATTR sha1_rol32(uint32_t number, uint8_t bits) { + return ((number << bits) | (number >> (32-bits))); +} + +void ICACHE_FLASH_ATTR sha1_hashBlock(sha1nfo *s) { + uint8_t i; + uint32_t a,b,c,d,e,t; + + a=s->state[0]; + b=s->state[1]; + c=s->state[2]; + d=s->state[3]; + e=s->state[4]; + for (i=0; i<80; i++) { + if (i>=16) { + t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; + s->buffer[i&15] = sha1_rol32(t,1); + } + if (i<20) { + t = (d ^ (b & (c ^ d))) + SHA1_K0; + } else if (i<40) { + t = (b ^ c ^ d) + SHA1_K20; + } else if (i<60) { + t = ((b & c) | (d & (b | c))) + SHA1_K40; + } else { + t = (b ^ c ^ d) + SHA1_K60; + } + t+=sha1_rol32(a,5) + e + s->buffer[i&15]; + e=d; + d=c; + c=sha1_rol32(b,30); + b=a; + a=t; + } + s->state[0] += a; + s->state[1] += b; + s->state[2] += c; + s->state[3] += d; + s->state[4] += e; +} + +void ICACHE_FLASH_ATTR sha1_addUncounted(sha1nfo *s, uint8_t data) { + uint8_t * const b = (uint8_t*) s->buffer; +#ifdef SHA_BIG_ENDIAN + b[s->bufferOffset] = data; +#else + b[s->bufferOffset ^ 3] = data; +#endif + s->bufferOffset++; + if (s->bufferOffset == BLOCK_LENGTH) { + sha1_hashBlock(s); + s->bufferOffset = 0; + } +} + +void ICACHE_FLASH_ATTR sha1_writebyte(sha1nfo *s, uint8_t data) { + ++s->byteCount; + sha1_addUncounted(s, data); +} + +void ICACHE_FLASH_ATTR sha1_write(sha1nfo *s, const char *data, size_t len) { + for (;len--;) sha1_writebyte(s, (uint8_t) *data++); +} + +void ICACHE_FLASH_ATTR sha1_pad(sha1nfo *s) { + // Implement SHA-1 padding (fips180-2 §5.1.1) + + // Pad with 0x80 followed by 0x00 until the end of the block + sha1_addUncounted(s, 0x80); + while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); + + // Append length in the last 8 bytes + sha1_addUncounted(s, 0); // We're only using 32 bit lengths + sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths + sha1_addUncounted(s, 0); // So zero pad the top bits + sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 + sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as + sha1_addUncounted(s, s->byteCount >> 13); // byte. + sha1_addUncounted(s, s->byteCount >> 5); + sha1_addUncounted(s, s->byteCount << 3); +} + +uint8_t* ICACHE_FLASH_ATTR sha1_result(sha1nfo *s) { + // Pad to complete the last block + sha1_pad(s); + +#ifndef SHA_BIG_ENDIAN + // Swap byte order back + int i; + for (i=0; i<5; i++) { + s->state[i]= + (((s->state[i])<<24)& 0xff000000) + | (((s->state[i])<<8) & 0x00ff0000) + | (((s->state[i])>>8) & 0x0000ff00) + | (((s->state[i])>>24)& 0x000000ff); + } +#endif + + // Return pointer to hash (20 characters) + return (uint8_t*) s->state; +} + +#define HMAC_IPAD 0x36 +#define HMAC_OPAD 0x5c + +void ICACHE_FLASH_ATTR sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) { + uint8_t i; + memset(s->keyBuffer, 0, BLOCK_LENGTH); + if (keyLength > BLOCK_LENGTH) { + // Hash long keys + sha1_init(s); + for (;keyLength--;) sha1_writebyte(s, *key++); + memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); + } else { + // Block length keys are used as is + memcpy(s->keyBuffer, key, keyLength); + } + // Start inner hash + sha1_init(s); + for (i=0; ikeyBuffer[i] ^ HMAC_IPAD); + } +} + +uint8_t* ICACHE_FLASH_ATTR sha1_resultHmac(sha1nfo *s) { + uint8_t i; + // Complete inner hash + memcpy(s->innerHash,sha1_result(s),HASH_LENGTH); + // Calculate outer hash + sha1_init(s); + for (i=0; ikeyBuffer[i] ^ HMAC_OPAD); + for (i=0; iinnerHash[i]); + return sha1_result(s); +} diff --git a/firmwares/minetest/libesphttpd/espfs/espfs.c b/firmwares/minetest/libesphttpd/espfs/espfs.c new file mode 100644 index 0000000..e57a8c4 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/espfs.c @@ -0,0 +1,269 @@ +/* +This is a simple read-only implementation of a file system. It uses a block of data coming from the +mkespfsimg tool, and can use that block to do abstracted operations on the files that are in there. +It's written for use with httpd, but doesn't need to be used as such. +*/ + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +//These routines can also be tested by comping them in with the espfstest tool. This +//simplifies debugging, but needs some slightly different headers. The #ifdef takes +//care of that. + +#ifdef __ets__ +//esp build +#include +#else +//Test build +#include +#include +#include +#include +#define ICACHE_FLASH_ATTR +#endif + +#include "espfsformat.h" +#include "espfs.h" + +#ifdef ESPFS_HEATSHRINK +#include "heatshrink_config_custom.h" +#include "heatshrink_decoder.h" +#endif + +static char* espFsData = NULL; + + +struct EspFsFile { + EspFsHeader *header; + char decompressor; + int32_t posDecomp; + char *posStart; + char *posComp; + void *decompData; +}; + +/* +Available locations, at least in my flash, with boundaries partially guessed. This +is using 0.9.1/0.9.2 SDK on a not-too-new module. +0x00000 (0x10000): Code/data (RAM data?) +0x10000 (0x02000): Gets erased by something? +0x12000 (0x2E000): Free (filled with zeroes) (parts used by ESPCloud and maybe SSL) +0x40000 (0x20000): Code/data (ROM data?) +0x60000 (0x1C000): Free +0x7c000 (0x04000): Param store +0x80000 - end of flash + +Accessing the flash through the mem emulation at 0x40200000 is a bit hairy: All accesses +*must* be aligned 32-bit accesses. Reading a short, byte or unaligned word will result in +a memory exception, crashing the program. +*/ + +EspFsInitResult ICACHE_FLASH_ATTR espFsInit(void *flashAddress) { + if((uint32_t)flashAddress > 0x40200000) { + flashAddress = (void*)((uint32_t)flashAddress-0x40200000); + } + + // base address must be aligned to 4 bytes + if (((int)flashAddress & 3) != 0) { + return ESPFS_INIT_RESULT_BAD_ALIGN; + } + + // check if there is valid header at address + EspFsHeader testHeader; + spi_flash_read((uint32)flashAddress, (uint32*)&testHeader, sizeof(EspFsHeader)); + if (testHeader.magic != ESPFS_MAGIC) { + return ESPFS_INIT_RESULT_NO_IMAGE; + } + + espFsData = (char *)flashAddress; + return ESPFS_INIT_RESULT_OK; +} + +//Copies len bytes over from dst to src, but does it using *only* +//aligned 32-bit reads. Yes, it's no too optimized but it's short and sweet and it works. + +//ToDo: perhaps memcpy also does unaligned accesses? +#ifdef __ets__ +void ICACHE_FLASH_ATTR readFlashUnaligned(char *dst, char *src, int len) { + uint8_t src_offset = ((uint32_t)src) & 3; + uint32_t src_address = ((uint32_t)src) - src_offset; + + uint32_t tmp_buf[len/4 + 2]; + spi_flash_read((uint32)src_address, (uint32*)tmp_buf, len+src_offset); + memcpy(dst, ((uint8_t*)tmp_buf)+src_offset, len); +} +#else +#define readFlashUnaligned memcpy +#endif + +// Returns flags of opened file. +int ICACHE_FLASH_ATTR espFsFlags(EspFsFile *fh) { + if (fh == NULL) { + httpd_printf("File handle not ready\n"); + return -1; + } + + int8_t flags; + readFlashUnaligned((char*)&flags, (char*)&fh->header->flags, 1); + return (int)flags; +} + +//Open a file and return a pointer to the file desc struct. +EspFsFile ICACHE_FLASH_ATTR *espFsOpen(char *fileName) { + if (espFsData == NULL) { + httpd_printf("Call espFsInit first!\n"); + return NULL; + } + char *p=espFsData; + char *hpos; + char namebuf[256]; + EspFsHeader h; + EspFsFile *r; + //Strip initial slashes + while(fileName[0]=='/') fileName++; + //Go find that file! + while(1) { + hpos=p; + //Grab the next file header. + spi_flash_read((uint32)p, (uint32*)&h, sizeof(EspFsHeader)); + + if (h.magic!=ESPFS_MAGIC) { + httpd_printf("Magic mismatch. EspFS image broken.\n"); + return NULL; + } + if (h.flags&FLAG_LASTFILE) { + httpd_printf("End of image.\n"); + return NULL; + } + //Grab the name of the file. + p+=sizeof(EspFsHeader); + spi_flash_read((uint32)p, (uint32*)&namebuf, sizeof(namebuf)); +// httpd_printf("Found file '%s'. Namelen=%x fileLenComp=%x, compr=%d flags=%d\n", +// namebuf, (unsigned int)h.nameLen, (unsigned int)h.fileLenComp, h.compression, h.flags); + if (strcmp(namebuf, fileName)==0) { + //Yay, this is the file we need! + p+=h.nameLen; //Skip to content. + r=(EspFsFile *)malloc(sizeof(EspFsFile)); //Alloc file desc mem +// httpd_printf("Alloc %p\n", r); + if (r==NULL) return NULL; + r->header=(EspFsHeader *)hpos; + r->decompressor=h.compression; + r->posComp=p; + r->posStart=p; + r->posDecomp=0; + if (h.compression==COMPRESS_NONE) { + r->decompData=NULL; +#ifdef ESPFS_HEATSHRINK + } else if (h.compression==COMPRESS_HEATSHRINK) { + //File is compressed with Heatshrink. + char parm; + heatshrink_decoder *dec; + //Decoder params are stored in 1st byte. + readFlashUnaligned(&parm, r->posComp, 1); + r->posComp++; + httpd_printf("Heatshrink compressed file; decode parms = %x\n", parm); + dec=heatshrink_decoder_alloc(16, (parm>>4)&0xf, parm&0xf); + r->decompData=dec; +#endif + } else { + httpd_printf("Invalid compression: %d\n", h.compression); + return NULL; + } + return r; + } + //We don't need this file. Skip name and file + p+=h.nameLen+h.fileLenComp; + if ((int)p&3) p+=4-((int)p&3); //align to next 32bit val + } +} + +//Read len bytes from the given file into buff. Returns the actual amount of bytes read. +int ICACHE_FLASH_ATTR espFsRead(EspFsFile *fh, char *buff, int len) { + int flen; + if (fh==NULL) return 0; + + readFlashUnaligned((char*)&flen, (char*)&fh->header->fileLenComp, 4); + //Cache file length. + //Do stuff depending on the way the file is compressed. + if (fh->decompressor==COMPRESS_NONE) { + int toRead; + toRead=flen-(fh->posComp-fh->posStart); + if (len>toRead) len=toRead; +// httpd_printf("Reading %d bytes from %x\n", len, (unsigned int)fh->posComp); + readFlashUnaligned(buff, fh->posComp, len); + fh->posDecomp+=len; + fh->posComp+=len; +// httpd_printf("Done reading %d bytes, pos=%x\n", len, fh->posComp); + return len; +#ifdef ESPFS_HEATSHRINK + } else if (fh->decompressor==COMPRESS_HEATSHRINK) { + int fdlen; + readFlashUnaligned((char*)&fdlen, (char*)&fh->header->fileLenDecomp, 4); + int decoded=0; + size_t elen, rlen; + char ebuff[16]; + heatshrink_decoder *dec=(heatshrink_decoder *)fh->decompData; +// httpd_printf("Alloc %p\n", dec); + if (fh->posDecomp == fdlen) { + return 0; + } + + // We must ensure that whole file is decompressed and written to output buffer. + // This means even when there is no input data (elen==0) try to poll decoder until + // posDecomp equals decompressed file length + + while(decodedposComp - fh->posStart); + if (elen>0) { + readFlashUnaligned(ebuff, fh->posComp, 16); + heatshrink_decoder_sink(dec, (uint8_t *)ebuff, (elen>16)?16:elen, &rlen); + fh->posComp+=rlen; + } + //Grab decompressed data and put into buff + heatshrink_decoder_poll(dec, (uint8_t *)buff, len-decoded, &rlen); + fh->posDecomp+=rlen; + buff+=rlen; + decoded+=rlen; + +// httpd_printf("Elen %d rlen %d d %d pd %ld fdl %d\n",elen,rlen,decoded, fh->posDecomp, fdlen); + + if (elen == 0) { + if (fh->posDecomp == fdlen) { +// httpd_printf("Decoder finish\n"); + heatshrink_decoder_finish(dec); + } + return decoded; + } + } + return len; +#endif + } + return 0; +} + +//Close the file. +void ICACHE_FLASH_ATTR espFsClose(EspFsFile *fh) { + if (fh==NULL) return; +#ifdef ESPFS_HEATSHRINK + if (fh->decompressor==COMPRESS_HEATSHRINK) { + heatshrink_decoder *dec=(heatshrink_decoder *)fh->decompData; + heatshrink_decoder_free(dec); +// httpd_printf("Freed %p\n", dec); + } +#endif +// httpd_printf("Freed %p\n", fh); + free(fh); +} + + + diff --git a/firmwares/minetest/libesphttpd/espfs/espfsformat.h b/firmwares/minetest/libesphttpd/espfs/espfsformat.h new file mode 100644 index 0000000..8ce5549 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/espfsformat.h @@ -0,0 +1,33 @@ +#ifndef ESPROFSFORMAT_H +#define ESPROFSFORMAT_H + +/* +Stupid cpio-like tool to make read-only 'filesystems' that live on the flash SPI chip of the module. +Can (will) use lzf compression (when I come around to it) to make shit quicker. Aligns names, files, +headers on 4-byte boundaries so the SPI abstraction hardware in the ESP8266 doesn't crap on itself +when trying to do a <4byte or unaligned read. +*/ + +/* +The idea 'borrows' from cpio: it's basically a concatenation of {header, filename, file} data. +Header, filename and file data is 32-bit aligned. The last file is indicated by data-less header +with the FLAG_LASTFILE flag set. +*/ + + +#define FLAG_LASTFILE (1<<0) +#define FLAG_GZIP (1<<1) +#define COMPRESS_NONE 0 +#define COMPRESS_HEATSHRINK 1 +#define ESPFS_MAGIC 0x73665345 + +typedef struct { + int32_t magic; + int8_t flags; + int8_t compression; + int16_t nameLen; + int32_t fileLenComp; + int32_t fileLenDecomp; +} __attribute__((packed)) EspFsHeader; + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/espfs/espfstest/Makefile b/firmwares/minetest/libesphttpd/espfs/espfstest/Makefile new file mode 100644 index 0000000..f8296f4 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/espfstest/Makefile @@ -0,0 +1,13 @@ +CFLAGS=-I../../lib/heatshrink -I.. -std=gnu99 -DESPFS_HEATSHRINK + +espfstest: main.o espfs.o heatshrink_decoder.o + $(CC) -o $@ $^ + +espfs.o: ../espfs.c + $(CC) $(CFLAGS) -c $^ -o $@ + +heatshrink_decoder.o: ../heatshrink_decoder.c + $(CC) $(CFLAGS) -c $^ -o $@ + +clean: + rm -f *.o espfstest diff --git a/firmwares/minetest/libesphttpd/espfs/espfstest/main.c b/firmwares/minetest/libesphttpd/espfs/espfstest/main.c new file mode 100644 index 0000000..16a6287 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/espfstest/main.c @@ -0,0 +1,67 @@ +/* +Simple and stupid file decompressor for an espfs image. Mostly used as a testbed for espfs.c and +the decompressors: code compiled natively is way easier to debug using gdb et all :) +*/ +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "espfs.h" + +char *espFsData; + +int main(int argc, char **argv) { + int f, out; + int len; + char buff[128]; + EspFsFile *ef; + off_t size; + EspFsInitResult ir; + + if (argc!=3) { + printf("Usage: %s espfs-image file\nExpands file from the espfs-image archive.\n", argv[0]); + exit(0); + } + + f=open(argv[1], O_RDONLY); + if (f<=0) { + perror(argv[1]); + exit(1); + } + size=lseek(f, 0, SEEK_END); + espFsData=mmap(NULL, size, PROT_READ, MAP_SHARED, f, 0); + if (espFsData==MAP_FAILED) { + perror("mmap"); + exit(1); + } + + ir=espFsInit(espFsData); + if (ir != ESPFS_INIT_RESULT_OK) { + printf("Couldn't init espfs filesystem (code %d)\n", ir); + exit(1); + } + + ef=espFsOpen(argv[2]); + if (ef==NULL) { + printf("Couldn't find %s in image.\n", argv[2]); + exit(1); + } + + out=open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0644); + if (out<=0) { + perror(argv[2]); + exit(1); + } + + while ((len=espFsRead(ef, buff, 128))!=0) { + write(out, buff, len); + } + espFsClose(ef); + //munmap, close, ... I can't be bothered. +} diff --git a/firmwares/minetest/libesphttpd/espfs/heatshrink_config_custom.h b/firmwares/minetest/libesphttpd/espfs/heatshrink_config_custom.h new file mode 100644 index 0000000..158b5ec --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/heatshrink_config_custom.h @@ -0,0 +1,25 @@ +//Heatshrink config for the decompressor. +#ifndef HEATSHRINK_CONFIG_H +#define HEATSHRINK_CONFIG_H + +/* Should functionality assuming dynamic allocation be used? */ +#define HEATSHRINK_DYNAMIC_ALLOC 1 + +#if HEATSHRINK_DYNAMIC_ALLOC + /* Optional replacement of malloc/free */ + #define HEATSHRINK_MALLOC(SZ) malloc(SZ) + #define HEATSHRINK_FREE(P, SZ) free(P) +#else + /* Required parameters for static configuration */ + #define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 32 + #define HEATSHRINK_STATIC_WINDOW_BITS 8 + #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4 +#endif + +/* Turn on logging for debugging. */ +#define HEATSHRINK_DEBUGGING_LOGS 0 + +/* Use indexing for faster compression. (This requires additional space.) */ +#define HEATSHRINK_USE_INDEX 1 + +#endif diff --git a/firmwares/minetest/libesphttpd/espfs/heatshrink_decoder.c b/firmwares/minetest/libesphttpd/espfs/heatshrink_decoder.c new file mode 100644 index 0000000..bda1f63 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/heatshrink_decoder.c @@ -0,0 +1,17 @@ +#include "espfs.h" +#ifdef ESPFS_HEATSHRINK +//Stupid wrapper so we don't have to move c-files around +//Also loads httpd-specific config. + +#ifdef __ets__ +//esp build + +#include + +#endif + +#include "heatshrink_config_custom.h" +#include "../lib/heatshrink/heatshrink_decoder.c" + + +#endif diff --git a/firmwares/minetest/libesphttpd/espfs/mkespfsimage/Makefile b/firmwares/minetest/libesphttpd/espfs/mkespfsimage/Makefile new file mode 100644 index 0000000..0d862e7 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/mkespfsimage/Makefile @@ -0,0 +1,24 @@ +GZIP_COMPRESSION ?= no +USE_HEATSHRINK ?= yes + +CFLAGS=-I../../lib/heatshrink -I../../include -I.. -std=gnu99 +ifeq ("$(GZIP_COMPRESSION)","yes") +CFLAGS += -DESPFS_GZIP +endif + +ifeq ("$(USE_HEATSHRINK)","yes") +CFLAGS += -DESPFS_HEATSHRINK +endif + +OBJS=main.o heatshrink_encoder.o +TARGET=mkespfsimage + +$(TARGET): $(OBJS) +ifeq ("$(GZIP_COMPRESSION)","yes") + $(CC) -o $@ $^ -lz +else + $(CC) -o $@ $^ +endif + +clean: + rm -f $(TARGET) $(OBJS) \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c b/firmwares/minetest/libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c new file mode 100644 index 0000000..b563970 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/mkespfsimage/heatshrink_encoder.c @@ -0,0 +1,4 @@ +//Stupid wraparound include to make sure object file doesn't end up in heatshrink dir +#ifdef ESPFS_HEATSHRINK +#include "../lib/heatshrink/heatshrink_encoder.c" +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/espfs/mkespfsimage/main.c b/firmwares/minetest/libesphttpd/espfs/mkespfsimage/main.c new file mode 100644 index 0000000..4fe2e21 --- /dev/null +++ b/firmwares/minetest/libesphttpd/espfs/mkespfsimage/main.c @@ -0,0 +1,362 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "espfs.h" +#include "espfsformat.h" + +//Heatshrink +#ifdef ESPFS_HEATSHRINK +#include "heatshrink_common.h" +#include "heatshrink_config.h" +#include "heatshrink_encoder.h" +#endif + +//Gzip +#ifdef ESPFS_GZIP +// If compiler complains about missing header, try running "sudo apt-get install zlib1g-dev" +// to install missing package. +#include +#endif + + +//Routines to convert host format to the endianness used in the xtensa +short htoxs(short in) { + char r[2]; + r[0]=in; + r[1]=in>>8; + return *((short *)r); +} + +int htoxl(int in) { + unsigned char r[4]; + r[0]=in; + r[1]=in>>8; + r[2]=in>>16; + r[3]=in>>24; + return *((int *)r); +} + +#ifdef ESPFS_HEATSHRINK +size_t compressHeatshrink(char *in, int insize, char *out, int outsize, int level) { + char *inp=in; + char *outp=out; + size_t len; + int ws[]={5, 6, 8, 11, 13}; + int ls[]={3, 3, 4, 4, 4}; + HSE_poll_res pres; + HSE_sink_res sres; + size_t r; + if (level==-1) level=8; + level=(level-1)/2; //level is now 0, 1, 2, 3, 4 + heatshrink_encoder *enc=heatshrink_encoder_alloc(ws[level], ls[level]); + if (enc==NULL) { + perror("allocating mem for heatshrink"); + exit(1); + } + //Save encoder parms as first byte + *outp=(ws[level]<<4)|ls[level]; + outp++; outsize--; + + r=1; + do { + if (insize>0) { + sres=heatshrink_encoder_sink(enc, inp, insize, &len); + if (sres!=HSER_SINK_OK) break; + inp+=len; insize-=len; + if (insize==0) heatshrink_encoder_finish(enc); + } + do { + pres=heatshrink_encoder_poll(enc, outp, outsize, &len); + if (pres!=HSER_POLL_MORE && pres!=HSER_POLL_EMPTY) break; + outp+=len; outsize-=len; + r+=len; + } while (pres==HSER_POLL_MORE); + } while (insize!=0); + + if (insize!=0) { + fprintf(stderr, "Heatshrink: Bug? insize is still %d. sres=%d pres=%d\n", insize, sres, pres); + exit(1); + } + + heatshrink_encoder_free(enc); + return r; +} +#endif + +#ifdef ESPFS_GZIP +size_t compressGzip(char *in, int insize, char *out, int outsize, int level) { + z_stream stream; + int zresult; + + stream.zalloc = Z_NULL; + stream.zfree = Z_NULL; + stream.opaque = Z_NULL; + stream.next_in = in; + stream.avail_in = insize; + stream.next_out = out; + stream.avail_out = outsize; + // 31 -> 15 window bits + 16 for gzip + zresult = deflateInit2 (&stream, level, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY); + if (zresult != Z_OK) { + fprintf(stderr, "DeflateInit2 failed with code %d\n", zresult); + exit(1); + } + + zresult = deflate(&stream, Z_FINISH); + if (zresult != Z_STREAM_END) { + fprintf(stderr, "Deflate failed with code %d\n", zresult); + exit(1); + } + + zresult = deflateEnd(&stream); + if (zresult != Z_OK) { + fprintf(stderr, "DeflateEnd failed with code %d\n", zresult); + exit(1); + } + + return stream.total_out; +} + +char **gzipExtensions = NULL; + +int shouldCompressGzip(char *name) { + char *ext = name + strlen(name); + while (*ext != '.') { + ext--; + if (ext < name) { + // no dot in file name -> no extension -> nothing to match against + return 0; + } + } + ext++; + + int i = 0; + while (gzipExtensions[i] != NULL) { + if (strcmp(ext,gzipExtensions[i]) == 0) { + return 1; + } + i++; + } + + return 0; +} + +int parseGzipExtensions(char *input) { + char *token; + char *extList = input; + int count = 2; // one for first element, second for terminator + + // count elements + while (*extList != 0) { + if (*extList == ',') count++; + extList++; + } + + // split string + extList = input; + gzipExtensions = malloc(count * sizeof(char*)); + count = 0; + token = strtok(extList, ","); + while (token) { + gzipExtensions[count++] = token; + token = strtok(NULL, ","); + } + // terminate list + gzipExtensions[count] = NULL; + + return 1; +} +#endif + +int handleFile(int f, char *name, int compression, int level, char **compName) { + char *fdat, *cdat; + off_t size, csize; + EspFsHeader h; + int nameLen; + int8_t flags = 0; + size=lseek(f, 0, SEEK_END); + fdat=malloc(size); + lseek(f, 0, SEEK_SET); + read(f, fdat, size); + + +#ifdef ESPFS_GZIP + if (shouldCompressGzip(name)) { + csize = size*3; + if (csize<100) // gzip has some headers that do not fit when trying to compress small files + csize = 100; // enlarge buffer if this is the case + cdat=malloc(csize); + csize=compressGzip(fdat, size, cdat, csize, level); + compression = COMPRESS_NONE; + flags = FLAG_GZIP; + } else +#endif + if (compression==COMPRESS_NONE) { + csize=size; + cdat=fdat; +#ifdef ESPFS_HEATSHRINK + } else if (compression==COMPRESS_HEATSHRINK) { + cdat=malloc(size*2); + csize=compressHeatshrink(fdat, size, cdat, size*2, level); +#endif + } else { + fprintf(stderr, "Unknown compression - %d\n", compression); + exit(1); + } + + if (csize>size) { + //Compressing enbiggened this file. Revert to uncompressed store. + compression=COMPRESS_NONE; + csize=size; + cdat=fdat; + flags=0; + } + + //Fill header data + h.magic=('E'<<0)+('S'<<8)+('f'<<16)+('s'<<24); + h.flags=flags; + h.compression=compression; + h.nameLen=nameLen=strlen(name)+1; + if (h.nameLen&3) h.nameLen+=4-(h.nameLen&3); //Round to next 32bit boundary + h.nameLen=htoxs(h.nameLen); + h.fileLenComp=htoxl(csize); + h.fileLenDecomp=htoxl(size); + + write(1, &h, sizeof(EspFsHeader)); + write(1, name, nameLen); + while (nameLen&3) { + write(1, "\000", 1); + nameLen++; + } + write(1, cdat, csize); + //Pad out to 32bit boundary + while (csize&3) { + write(1, "\000", 1); + csize++; + } + free(fdat); + + if (compName != NULL) { + if (h.compression==COMPRESS_HEATSHRINK) { + *compName = "heatshrink"; + } else if (h.compression==COMPRESS_NONE) { + if (h.flags & FLAG_GZIP) { + *compName = "gzip"; + } else { + *compName = "none"; + } + } else { + *compName = "unknown"; + } + } + return (csize*100)/size; +} + +//Write final dummy header with FLAG_LASTFILE set. +void finishArchive() { + EspFsHeader h; + h.magic=('E'<<0)+('S'<<8)+('f'<<16)+('s'<<24); + h.flags=FLAG_LASTFILE; + h.compression=COMPRESS_NONE; + h.nameLen=htoxs(0); + h.fileLenComp=htoxl(0); + h.fileLenDecomp=htoxl(0); + write(1, &h, sizeof(EspFsHeader)); +} + +int main(int argc, char **argv) { + int f, x; + char fileName[1024]; + char *realName; + struct stat statBuf; + int serr; + int rate; + int err=0; + int compType; //default compression type - heatshrink + int compLvl=-1; + +#ifdef ESPFS_HEATSHRINK + compType = COMPRESS_HEATSHRINK; +#else + compType = COMPRESS_NONE; +#endif + + for (x=1; x=x-2) { + compType=atoi(argv[x+1]); + x++; + } else if (strcmp(argv[x], "-l")==0 && argc>=x-2) { + compLvl=atoi(argv[x+1]); + if (compLvl<1 || compLvl>9) err=1; + x++; +#ifdef ESPFS_GZIP + } else if (strcmp(argv[x], "-g")==0 && argc>=x-2) { + if (!parseGzipExtensions(argv[x+1])) err=1; + x++; +#endif + } else { + err=1; + } + } + +#ifdef ESPFS_GZIP + if (gzipExtensions == NULL) { + parseGzipExtensions(strdup("html,css,js,svg")); + } +#endif + + if (err) { + fprintf(stderr, "%s - Program to create espfs images\n", argv[0]); + fprintf(stderr, "Usage: \nfind | %s [-c compressor] [-l compression_level] ", argv[0]); +#ifdef ESPFS_GZIP + fprintf(stderr, "[-g gzipped_extensions] "); +#endif + fprintf(stderr, "> out.espfs\n"); + fprintf(stderr, "Compressors:\n"); +#ifdef ESPFS_HEATSHRINK + fprintf(stderr, "0 - None\n1 - Heatshrink(default)\n"); +#else + fprintf(stderr, "0 - None(default)\n"); +#endif + fprintf(stderr, "\nCompression level: 1 is worst but low RAM usage, higher is better compression \nbut uses more ram on decompression. -1 = compressors default.\n"); +#ifdef ESPFS_GZIP + fprintf(stderr, "\nGzipped extensions: list of comma separated, case sensitive file extensions \nthat will be gzipped. Defaults to 'html,css,js'\n"); +#endif + exit(0); + } + + while(fgets(fileName, sizeof(fileName), stdin)) { + //Kill off '\n' at the end + fileName[strlen(fileName)-1]=0; + //Only include files + serr=stat(fileName, &statBuf); + if ((serr==0) && S_ISREG(statBuf.st_mode)) { + //Strip off './' or '/' madness. + realName=fileName; + if (fileName[0]=='.') realName++; + if (realName[0]=='/') realName++; + f=open(fileName, O_RDONLY); + if (f>0) { + char *compName = "unknown"; + rate=handleFile(f, realName, compType, compLvl, &compName); + fprintf(stderr, "%s (%d%%, %s)\n", realName, rate, compName); + close(f); + } else { + perror(fileName); + } + } else { + if (serr!=0) { + perror(fileName); + } + } + } + finishArchive(); + return 0; +} + diff --git a/firmwares/minetest/libesphttpd/include/auth.h b/firmwares/minetest/libesphttpd/include/auth.h new file mode 100644 index 0000000..1ef0f61 --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/auth.h @@ -0,0 +1,22 @@ +#ifndef AUTH_H +#define AUTH_H + +#include "httpd.h" + +#ifndef HTTP_AUTH_REALM +#define HTTP_AUTH_REALM "Protected" +#endif + +#define HTTPD_AUTH_SINGLE 0 +#define HTTPD_AUTH_CALLBACK 1 + +#define AUTH_MAX_USER_LEN 32 +#define AUTH_MAX_PASS_LEN 32 + +//Parameter given to authWhatever functions. This callback returns the usernames/passwords the device +//has. +typedef int (* AuthGetUserPw)(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen); + +int ICACHE_FLASH_ATTR authBasic(HttpdConnData *connData); + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/include/captdns.h b/firmwares/minetest/libesphttpd/include/captdns.h new file mode 100644 index 0000000..ba17ebd --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/captdns.h @@ -0,0 +1,5 @@ +#ifndef CAPTDNS_H +#define CAPTDNS_H +void ICACHE_FLASH_ATTR captdnsInit(void); + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/include/cgiflash.h b/firmwares/minetest/libesphttpd/include/cgiflash.h new file mode 100644 index 0000000..847621d --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/cgiflash.h @@ -0,0 +1,22 @@ +#ifndef CGIFLASH_H +#define CGIFLASH_H + +#include "httpd.h" + +#define CGIFLASH_TYPE_FW 0 +#define CGIFLASH_TYPE_ESPFS 1 + +typedef struct { + int type; + int fw1Pos; + int fw2Pos; + int fwSize; + char *tagName; +} CgiUploadFlashDef; + +int cgiReadFlash(HttpdConnData *connData); +int cgiGetFirmwareNext(HttpdConnData *connData); +int cgiUploadFirmware(HttpdConnData *connData); +int cgiRebootFirmware(HttpdConnData *connData); + +#endif diff --git a/firmwares/minetest/libesphttpd/include/cgiwebsocket.h b/firmwares/minetest/libesphttpd/include/cgiwebsocket.h new file mode 100644 index 0000000..f65253f --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/cgiwebsocket.h @@ -0,0 +1,37 @@ +#ifndef CGIWEBSOCKET_H +#define CGIWEBSOCKET_H + +#include "httpd.h" + +#define WEBSOCK_FLAG_NONE 0 +#define WEBSOCK_FLAG_CONT (1<<0) //Set if the data is not the final data in the message; more follows +#define WEBSOCK_FLAG_BIN (1<<1) //Set if the data is binary instead of text + + + +typedef struct Websock Websock; +typedef struct WebsockPriv WebsockPriv; + +typedef void(*WsConnectedCb)(Websock *ws); +typedef void(*WsRecvCb)(Websock *ws, char *data, int len, int flags); +typedef void(*WsSentCb)(Websock *ws); +typedef void(*WsCloseCb)(Websock *ws); + +struct Websock { + void *userData; + HttpdConnData *conn; + uint8_t status; + WsRecvCb recvCb; + WsSentCb sentCb; + WsCloseCb closeCb; + WebsockPriv *priv; +}; + +int ICACHE_FLASH_ATTR cgiWebsocket(HttpdConnData *connData); +int ICACHE_FLASH_ATTR cgiWebsocketSend(Websock *ws, char *data, int len, int flags); +void ICACHE_FLASH_ATTR cgiWebsocketClose(Websock *ws, int reason); +int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int len); +int ICACHE_FLASH_ATTR cgiWebsockBroadcast(char *resource, char *data, int len, int flags); + + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/include/cgiwifi.h b/firmwares/minetest/libesphttpd/include/cgiwifi.h new file mode 100644 index 0000000..21ef2fc --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/cgiwifi.h @@ -0,0 +1,13 @@ +#ifndef CGIWIFI_H +#define CGIWIFI_H + +#include "httpd.h" + +int cgiWiFiScan(HttpdConnData *connData); +int tplWlan(HttpdConnData *connData, char *token, void **arg); +int cgiWiFi(HttpdConnData *connData); +int cgiWiFiConnect(HttpdConnData *connData); +int cgiWiFiSetMode(HttpdConnData *connData); +int cgiWiFiConnStatus(HttpdConnData *connData); + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/include/esp8266.h b/firmwares/minetest/libesphttpd/include/esp8266.h new file mode 100644 index 0000000..6e4b63f --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/esp8266.h @@ -0,0 +1,27 @@ +// Combined include file for esp8266 + + +#include +#include +#include +#include + +#ifdef FREERTOS +#include +#include + +#else +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "platform.h" +#include "espmissingincludes.h" + diff --git a/firmwares/minetest/libesphttpd/include/espfs.h b/firmwares/minetest/libesphttpd/include/espfs.h new file mode 100644 index 0000000..c41df0a --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/espfs.h @@ -0,0 +1,23 @@ +#ifndef ESPFS_H +#define ESPFS_H + +// This define is done in Makefile. If you do not use default Makefile, uncomment +// to be able to use Heatshrink-compressed espfs images. +//#define ESPFS_HEATSHRINK + +typedef enum { + ESPFS_INIT_RESULT_OK, + ESPFS_INIT_RESULT_NO_IMAGE, + ESPFS_INIT_RESULT_BAD_ALIGN, +} EspFsInitResult; + +typedef struct EspFsFile EspFsFile; + +EspFsInitResult espFsInit(void *flashAddress); +EspFsFile *espFsOpen(char *fileName); +int espFsFlags(EspFsFile *fh); +int espFsRead(EspFsFile *fh, char *buff, int len); +void espFsClose(EspFsFile *fh); + + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/include/espmissingincludes.h b/firmwares/minetest/libesphttpd/include/espmissingincludes.h new file mode 100644 index 0000000..4c313fd --- /dev/null +++ b/firmwares/minetest/libesphttpd/include/espmissingincludes.h @@ -0,0 +1,76 @@ +#ifndef ESPMISSINGINCLUDES_H +#define ESPMISSINGINCLUDES_H + +#include +#include + + +int strcasecmp(const char *a, const char *b); +#ifndef FREERTOS +#include +#include +//Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere. +//MOST OF THESE ARE GUESSED! but they seem to swork and shut up the compiler. +typedef struct espconn espconn; + +int atoi(const char *nptr); +void ets_install_putc1(void *routine); +void ets_isr_attach(int intr, void *handler, void *arg); +void ets_isr_mask(unsigned intr); +void ets_isr_unmask(unsigned intr); +int ets_memcmp(const void *s1, const void *s2, size_t n); +void *ets_memcpy(void *dest, const void *src, size_t n); +void *ets_memset(void *s, int c, size_t n); +int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3))); +int ets_str2macaddr(void *, void *); +int ets_strcmp(const char *s1, const char *s2); +char *ets_strcpy(char *dest, const char *src); +size_t ets_strlen(const char *s); +int ets_strncmp(const char *s1, const char *s2, int len); +char *ets_strncpy(char *dest, const char *src, size_t n); +char *ets_strstr(const char *haystack, const char *needle); +void ets_timer_arm_new(os_timer_t *a, int b, int c, int isMstimer); +void ets_timer_disarm(os_timer_t *a); +void ets_timer_setfn(os_timer_t *t, ETSTimerFunc *fn, void *parg); +void ets_update_cpu_frequency(int freqmhz); +int os_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2))); +int os_snprintf(char *str, size_t size, const char *format, ...) __attribute__ ((format (printf, 3, 4))); +int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2))); +void uart_div_modify(int no, unsigned int freq); +uint8 wifi_get_opmode(void); +uint32 system_get_time(); +int rand(void); +void ets_bzero(void *s, size_t n); +void ets_delay_us(int ms); + +//Hack: this is defined in SDK 1.4.0 and undefined in 1.3.0. It's only used for this, the symbol itself +//has no meaning here. +#ifndef RC_LIMIT_P2P_11N +//Defs for SDK <1.4.0 +void *pvPortMalloc(size_t xWantedSize); +void *pvPortZalloc(size_t); +void vPortFree(void *ptr); +void *vPortMalloc(size_t xWantedSize); +void pvPortFree(void *ptr); +#else +void *pvPortMalloc(size_t xWantedSize, const char *file, int line); +void *pvPortZalloc(size_t, const char *file, int line); +void vPortFree(void *ptr, const char *file, int line); +void *vPortMalloc(size_t xWantedSize, const char *file, int line); +void pvPortFree(void *ptr, const char *file, int line); +#endif + +//Standard PIN_FUNC_SELECT gives a warning. Replace by a non-warning one. +#ifdef PIN_FUNC_SELECT +#undef PIN_FUNC_SELECT +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \ + WRITE_PERI_REG(PIN_NAME, \ + (READ_PERI_REG(PIN_NAME) \ + & (~(PERIPHS_IO_MUX_FUNC< +All rights reserved. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/Makefile b/firmwares/minetest/libesphttpd/lib/heatshrink/Makefile new file mode 100644 index 0000000..d8e6875 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/Makefile @@ -0,0 +1,49 @@ +PROJECT = heatshrink +#OPTIMIZE = -O0 +#OPTIMIZE = -Os +OPTIMIZE = -O3 +WARN = -Wall -Wextra -pedantic #-Werror +CFLAGS += -std=c99 -g ${WARN} ${OPTIMIZE} +CFLAGS += -Wmissing-prototypes +CFLAGS += -Wstrict-prototypes +CFLAGS += -Wmissing-declarations + +# If libtheft is available, build additional property-based tests. +# Uncomment these to use it in test_heatshrink_dynamic. +#CFLAGS += -DHEATSHRINK_HAS_THEFT +#LDFLAGS += -ltheft + +all: + @echo "For tests, make test_heatshrink_dynamic (default) or change the" + @echo "config.h to disable static memory and build test_heatshrink_static." + @echo "For the standalone command-line tool, make heatshrink." + +${PROJECT}: heatshrink.c + +OBJS= heatshrink_encoder.o \ + heatshrink_decoder.o \ + +heatshrink: ${OBJS} +test_heatshrink_dynamic: ${OBJS} test_heatshrink_dynamic_theft.o +test_heatshrink_static: ${OBJS} + +*.o: Makefile heatshrink_config.h + +heatshrink_decoder.o: heatshrink_decoder.h heatshrink_common.h +heatshrink_encoder.o: heatshrink_encoder.h heatshrink_common.h + +tags: TAGS + +TAGS: + etags *.[ch] + +diagrams: dec_sm.png enc_sm.png + +dec_sm.png: dec_sm.dot + dot -o $@ -Tpng $< + +enc_sm.png: enc_sm.dot + dot -o $@ -Tpng $< + +clean: + rm -f ${PROJECT} test_heatshrink_{dynamic,static} *.o *.core {dec,enc}_sm.png TAGS diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/README.md b/firmwares/minetest/libesphttpd/lib/heatshrink/README.md new file mode 100644 index 0000000..ab150ee --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/README.md @@ -0,0 +1,49 @@ +# heatshrink + +A data compression/decompression library for embedded/real-time systems. + +## Key Features: + +- **Low memory usage (as low as 50 bytes)** + It is useful for some cases with less than 50 bytes, and useful + for many general cases with < 300 bytes. +- **Incremental, bounded CPU use** + You can chew on input data in arbitrarily tiny bites. + This is a useful property in hard real-time environments. +- **Can use either static or dynamic memory allocation** + The library doesn't impose any constraints on memory management. +- **ISC license** + You can use it freely, even for commercial purposes. + +## Getting Started: + +There is a standalone command-line program, `heatshrink`, but the +encoder and decoder can also be used as libraries, independent of each +other. To do so, copy `heatshrink_common.h`, `heatshrink_config.h`, and +either `heatshrink_encoder.c` or `heatshrink_decoder.c` (and their +respective header) into your project. + +Dynamic allocation is used by default, but in an embedded context, you +probably want to statically allocate the encoder/decoder. Set +`HEATSHRINK_DYNAMIC_ALLOC` to 0 in `heatshrink_config.h`. + +## More Information and Benchmarks: + +heatshrink is based on [LZSS], since it's particularly suitable for +compression in small amounts of memory. It can use an optional, small +[index] to make compression significantly faster, but otherwise can run +in under 100 bytes of memory. The index currently adds 2^(window size+1) +bytes to memory usage for compression, and temporarily allocates 512 +bytes on the stack during index construction. + +For more information, see the [blog post] for an overview, and the +`heatshrink_encoder.h` / `heatshrink_decoder.h` header files for API +documentation. + +[blog post]: http://spin.atomicobject.com/2013/03/14/heatshrink-embedded-data-compression/ +[index]: http://spin.atomicobject.com/2014/01/13/lightweight-indexing-for-embedded-systems/ +[LZSS]: http://en.wikipedia.org/wiki/Lempel-Ziv-Storer-Szymanski + +## Build Status + + [![Build Status](https://travis-ci.org/atomicobject/heatshrink.png)](http://travis-ci.org/atomicobject/heatshrink) diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/dec_sm.dot b/firmwares/minetest/libesphttpd/lib/heatshrink/dec_sm.dot new file mode 100644 index 0000000..470012f --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/dec_sm.dot @@ -0,0 +1,52 @@ +digraph { + graph [label="Decoder state machine", labelloc="t"] + Start [style="invis", shape="point"] + empty + input_available + yield_literal + backref_index_msb + backref_index_lsb + backref_count_msb + backref_count_lsb + yield_backref + check_for_more_input + done [peripheries=2] + + empty->input_available [label="sink()", color="blue", weight=10] + Start->empty + + input_available->yield_literal [label="pop 1-bit"] + input_available->backref_index_msb [label="pop 0-bit", weight=10] + input_available->backref_index_lsb [label="pop 0-bit, index <8 bits", weight=10] + + yield_literal->yield_literal [label="sink()", color="blue"] + yield_literal->yield_literal [label="poll()", color="red"] + yield_literal->check_for_more_input [label="poll(), done", color="red"] + + backref_index_msb->backref_index_msb [label="sink()", color="blue"] + backref_index_msb->backref_index_lsb [label="pop index, upper bits", weight=10] + backref_index_msb->done [label="finish()", color="blue"] + + backref_index_lsb->backref_index_lsb [label="sink()", color="blue"] + backref_index_lsb->backref_count_msb [label="pop index, lower bits", weight=10] + backref_index_lsb->backref_count_lsb [label="pop index, count <=8 bits", weight=10] + backref_index_lsb->done [label="finish()", color="blue"] + + backref_count_msb->backref_count_msb [label="sink()", color="blue"] + backref_count_msb->backref_count_lsb [label="pop count, upper bits", weight=10] + backref_count_msb->done [label="finish()", color="blue"] + + backref_count_lsb->backref_count_lsb [label="sink()", color="blue"] + backref_count_lsb->yield_backref [label="pop count, lower bits", weight=10] + backref_count_lsb->done [label="finish()", color="blue"] + + yield_backref->yield_backref [label="sink()", color="blue"] + yield_backref->yield_backref [label="poll()", color="red"] + yield_backref->check_for_more_input [label="poll(), done", + color="red", weight=10] + + check_for_more_input->empty [label="no"] + check_for_more_input->input_available [label="yes"] + + empty->done [label="finish()", color="blue"] +} diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/enc_sm.dot b/firmwares/minetest/libesphttpd/lib/heatshrink/enc_sm.dot new file mode 100644 index 0000000..6d3030f --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/enc_sm.dot @@ -0,0 +1,51 @@ +digraph { + graph [label="Encoder state machine", labelloc="t"] + start [style="invis", shape="point"] + not_full + filled + search + yield_tag_bit + yield_literal + yield_br_length + yield_br_index + save_backlog + flush_bits + done [peripheries=2] + + start->not_full [label="start"] + + not_full->not_full [label="sink(), not full", color="blue"] + not_full->filled [label="sink(), buffer is full", color="blue"] + not_full->filled [label="finish(), set is_finished", color="blue"] + + filled->search [label="indexing (if any)"] + + search->search [label="step"] + search->yield_tag_bit [label="literal"] + search->yield_tag_bit [label="match found"] + search->save_backlog [label="input exhausted"] + + yield_tag_bit->yield_tag_bit [label="poll(), full buf", color="red"] + yield_tag_bit->yield_literal [label="poll(), literal", color="red"] + yield_tag_bit->yield_br_index [label="poll(), no literal", color="red"] + yield_tag_bit->flush_bits [label="finishing, no literal"] + + yield_literal->yield_literal [label="poll(), full buf", color="red"] + yield_literal->search [label="poll(), no match", color="red"] + yield_literal->yield_tag_bit [label="poll(), match", color="red"] + yield_literal->flush_bits [label="poll(), final literal", color="red"] + + yield_br_index->yield_br_index [label="poll(), full buf", color="red"] + yield_br_index->yield_br_length [label="poll()", color="red"] + + yield_br_length->yield_br_length [label="poll(), full buf", color="red"] + yield_br_length->search [label="done"] + + save_backlog->flush_bits [label="finishing, no literal"] + save_backlog->yield_tag_bit [label="finishing, literal"] + save_backlog->not_full [label="expect more input"] + + flush_bits->flush_bits [label="poll(), full buf", color="red"] + flush_bits->done [label="poll(), flushed", color="red"] + flush_bits->done [label="no more output"] +} diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/greatest.h b/firmwares/minetest/libesphttpd/lib/heatshrink/greatest.h new file mode 100644 index 0000000..a92c642 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/greatest.h @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2011 Scott Vokes + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef GREATEST_H +#define GREATEST_H + +#define GREATEST_VERSION_MAJOR 0 +#define GREATEST_VERSION_MINOR 9 +#define GREATEST_VERSION_PATCH 3 + +/* A unit testing system for C, contained in 1 file. + * It doesn't use dynamic allocation or depend on anything + * beyond ANSI C89. */ + + +/********************************************************************* + * Minimal test runner template + *********************************************************************/ +#if 0 + +#include "greatest.h" + +TEST foo_should_foo() { + PASS(); +} + +static void setup_cb(void *data) { + printf("setup callback for each test case\n"); +} + +static void teardown_cb(void *data) { + printf("teardown callback for each test case\n"); +} + +SUITE(suite) { + /* Optional setup/teardown callbacks which will be run before/after + * every test case in the suite. + * Cleared when the suite finishes. */ + SET_SETUP(setup_cb, voidp_to_callback_data); + SET_TEARDOWN(teardown_cb, voidp_to_callback_data); + + RUN_TEST(foo_should_foo); +} + +/* Add all the definitions that need to be in the test runner's main file. */ +GREATEST_MAIN_DEFS(); + +int main(int argc, char **argv) { + GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */ + RUN_SUITE(suite); + GREATEST_MAIN_END(); /* display results */ +} + +#endif +/*********************************************************************/ + + +#include +#include +#include +#include + + +/*********** + * Options * + ***********/ + +/* Default column width for non-verbose output. */ +#ifndef GREATEST_DEFAULT_WIDTH +#define GREATEST_DEFAULT_WIDTH 72 +#endif + +/* FILE *, for test logging. */ +#ifndef GREATEST_STDOUT +#define GREATEST_STDOUT stdout +#endif + +/* Remove GREATEST_ prefix from most commonly used symbols? */ +#ifndef GREATEST_USE_ABBREVS +#define GREATEST_USE_ABBREVS 1 +#endif + + +/********* + * Types * + *********/ + +/* Info for the current running suite. */ +typedef struct greatest_suite_info { + unsigned int tests_run; + unsigned int passed; + unsigned int failed; + unsigned int skipped; + + /* timers, pre/post running suite and individual tests */ + clock_t pre_suite; + clock_t post_suite; + clock_t pre_test; + clock_t post_test; +} greatest_suite_info; + +/* Type for a suite function. */ +typedef void (greatest_suite_cb)(void); + +/* Types for setup/teardown callbacks. If non-NULL, these will be run + * and passed the pointer to their additional data. */ +typedef void (greatest_setup_cb)(void *udata); +typedef void (greatest_teardown_cb)(void *udata); + +typedef enum { + GREATEST_FLAG_VERBOSE = 0x01, + GREATEST_FLAG_FIRST_FAIL = 0x02, + GREATEST_FLAG_LIST_ONLY = 0x04 +} GREATEST_FLAG; + +typedef struct greatest_run_info { + unsigned int flags; + unsigned int tests_run; /* total test count */ + + /* Overall pass/fail/skip counts. */ + unsigned int passed; + unsigned int failed; + unsigned int skipped; + + /* currently running test suite */ + greatest_suite_info suite; + + /* info to print about the most recent failure */ + const char *fail_file; + unsigned int fail_line; + const char *msg; + + /* current setup/teardown hooks and userdata */ + greatest_setup_cb *setup; + void *setup_udata; + greatest_teardown_cb *teardown; + void *teardown_udata; + + /* formatting info for ".....s...F"-style output */ + unsigned int col; + unsigned int width; + + /* only run a specific suite or test */ + char *suite_filter; + char *test_filter; + + /* overall timers */ + clock_t begin; + clock_t end; +} greatest_run_info; + +/* Global var for the current testing context. + * Initialized by GREATEST_MAIN_DEFS(). */ +extern greatest_run_info greatest_info; + + +/********************** + * Exported functions * + **********************/ + +void greatest_do_pass(const char *name); +void greatest_do_fail(const char *name); +void greatest_do_skip(const char *name); +int greatest_pre_test(const char *name); +void greatest_post_test(const char *name, int res); +void greatest_usage(const char *name); +void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata); +void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata); + + +/********** + * Macros * + **********/ + +/* Define a suite. */ +#define GREATEST_SUITE(NAME) void NAME(void) + +/* Start defining a test function. + * The arguments are not included, to allow parametric testing. */ +#define GREATEST_TEST static int + +/* Run a suite. */ +#define GREATEST_RUN_SUITE(S_NAME) greatest_run_suite(S_NAME, #S_NAME) + +/* Run a test in the current suite. */ +#define GREATEST_RUN_TEST(TEST) \ + do { \ + if (greatest_pre_test(#TEST) == 1) { \ + int res = TEST(); \ + greatest_post_test(#TEST, res); \ + } else if (GREATEST_LIST_ONLY()) { \ + fprintf(GREATEST_STDOUT, " %s\n", #TEST); \ + } \ + } while (0) + +/* Run a test in the current suite with one void* argument, + * which can be a pointer to a struct with multiple arguments. */ +#define GREATEST_RUN_TEST1(TEST, ENV) \ + do { \ + if (greatest_pre_test(#TEST) == 1) { \ + int res = TEST(ENV); \ + greatest_post_test(#TEST, res); \ + } else if (GREATEST_LIST_ONLY()) { \ + fprintf(GREATEST_STDOUT, " %s\n", #TEST); \ + } \ + } while (0) + +/* If __VA_ARGS__ (C99) is supported, allow parametric testing + * without needing to manually manage the argument struct. */ +#if __STDC_VERSION__ >= 19901L +#define GREATEST_RUN_TESTp(TEST, ...) \ + do { \ + if (greatest_pre_test(#TEST) == 1) { \ + int res = TEST(__VA_ARGS__); \ + greatest_post_test(#TEST, res); \ + } else if (GREATEST_LIST_ONLY()) { \ + fprintf(GREATEST_STDOUT, " %s\n", #TEST); \ + } \ + } while (0) +#endif + + +/* Check if the test runner is in verbose mode. */ +#define GREATEST_IS_VERBOSE() (greatest_info.flags & GREATEST_FLAG_VERBOSE) +#define GREATEST_LIST_ONLY() (greatest_info.flags & GREATEST_FLAG_LIST_ONLY) +#define GREATEST_FIRST_FAIL() (greatest_info.flags & GREATEST_FLAG_FIRST_FAIL) +#define GREATEST_FAILURE_ABORT() (greatest_info.suite.failed > 0 && GREATEST_FIRST_FAIL()) + +/* Message-less forms. */ +#define GREATEST_PASS() GREATEST_PASSm(NULL) +#define GREATEST_FAIL() GREATEST_FAILm(NULL) +#define GREATEST_SKIP() GREATEST_SKIPm(NULL) +#define GREATEST_ASSERT(COND) GREATEST_ASSERTm(#COND, COND) +#define GREATEST_ASSERT_FALSE(COND) GREATEST_ASSERT_FALSEm(#COND, COND) +#define GREATEST_ASSERT_EQ(EXP, GOT) GREATEST_ASSERT_EQm(#EXP " != " #GOT, EXP, GOT) +#define GREATEST_ASSERT_STR_EQ(EXP, GOT) GREATEST_ASSERT_STR_EQm(#EXP " != " #GOT, EXP, GOT) + +/* The following forms take an additional message argument first, + * to be displayed by the test runner. */ + +/* Fail if a condition is not true, with message. */ +#define GREATEST_ASSERTm(MSG, COND) \ + do { \ + greatest_info.msg = MSG; \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + if (!(COND)) return -1; \ + greatest_info.msg = NULL; \ + } while (0) + +#define GREATEST_ASSERT_FALSEm(MSG, COND) \ + do { \ + greatest_info.msg = MSG; \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + if ((COND)) return -1; \ + greatest_info.msg = NULL; \ + } while (0) + +#define GREATEST_ASSERT_EQm(MSG, EXP, GOT) \ + do { \ + greatest_info.msg = MSG; \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + if ((EXP) != (GOT)) return -1; \ + greatest_info.msg = NULL; \ + } while (0) + +#define GREATEST_ASSERT_STR_EQm(MSG, EXP, GOT) \ + do { \ + const char *exp_s = (EXP); \ + const char *got_s = (GOT); \ + greatest_info.msg = MSG; \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + if (0 != strcmp(exp_s, got_s)) { \ + fprintf(GREATEST_STDOUT, \ + "Expected:\n####\n%s\n####\n", exp_s); \ + fprintf(GREATEST_STDOUT, \ + "Got:\n####\n%s\n####\n", got_s); \ + return -1; \ + } \ + greatest_info.msg = NULL; \ + } while (0) + +#define GREATEST_PASSm(MSG) \ + do { \ + greatest_info.msg = MSG; \ + return 0; \ + } while (0) + +#define GREATEST_FAILm(MSG) \ + do { \ + greatest_info.fail_file = __FILE__; \ + greatest_info.fail_line = __LINE__; \ + greatest_info.msg = MSG; \ + return -1; \ + } while (0) + +#define GREATEST_SKIPm(MSG) \ + do { \ + greatest_info.msg = MSG; \ + return 1; \ + } while (0) + +#define GREATEST_SET_TIME(NAME) \ + NAME = clock(); \ + if (NAME == (clock_t) -1) { \ + fprintf(GREATEST_STDOUT, \ + "clock error: %s\n", #NAME); \ + exit(EXIT_FAILURE); \ + } + +#define GREATEST_CLOCK_DIFF(C1, C2) \ + fprintf(GREATEST_STDOUT, " (%lu ticks, %.3f sec)", \ + (long unsigned int) (C2) - (C1), \ + (double)((C2) - (C1)) / (1.0 * (double)CLOCKS_PER_SEC)) \ + +/* Include several function definitions in the main test file. */ +#define GREATEST_MAIN_DEFS() \ + \ +/* Is FILTER a subset of NAME? */ \ +static int greatest_name_match(const char *name, \ + const char *filter) { \ + size_t offset = 0; \ + size_t filter_len = strlen(filter); \ + while (name[offset] != '\0') { \ + if (name[offset] == filter[0]) { \ + if (0 == strncmp(&name[offset], filter, filter_len)) { \ + return 1; \ + } \ + } \ + offset++; \ + } \ + \ + return 0; \ +} \ + \ +int greatest_pre_test(const char *name) { \ + if (!GREATEST_LIST_ONLY() \ + && (!GREATEST_FIRST_FAIL() || greatest_info.suite.failed == 0) \ + && (greatest_info.test_filter == NULL || \ + greatest_name_match(name, greatest_info.test_filter))) { \ + GREATEST_SET_TIME(greatest_info.suite.pre_test); \ + if (greatest_info.setup) { \ + greatest_info.setup(greatest_info.setup_udata); \ + } \ + return 1; /* test should be run */ \ + } else { \ + return 0; /* skipped */ \ + } \ +} \ + \ +void greatest_post_test(const char *name, int res) { \ + GREATEST_SET_TIME(greatest_info.suite.post_test); \ + if (greatest_info.teardown) { \ + void *udata = greatest_info.teardown_udata; \ + greatest_info.teardown(udata); \ + } \ + \ + if (res < 0) { \ + greatest_do_fail(name); \ + } else if (res > 0) { \ + greatest_do_skip(name); \ + } else if (res == 0) { \ + greatest_do_pass(name); \ + } \ + greatest_info.suite.tests_run++; \ + greatest_info.col++; \ + if (GREATEST_IS_VERBOSE()) { \ + GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test, \ + greatest_info.suite.post_test); \ + fprintf(GREATEST_STDOUT, "\n"); \ + } else if (greatest_info.col % greatest_info.width == 0) { \ + fprintf(GREATEST_STDOUT, "\n"); \ + greatest_info.col = 0; \ + } \ + if (GREATEST_STDOUT == stdout) fflush(stdout); \ +} \ + \ +static void greatest_run_suite(greatest_suite_cb *suite_cb, \ + const char *suite_name) { \ + if (greatest_info.suite_filter && \ + !greatest_name_match(suite_name, greatest_info.suite_filter)) \ + return; \ + if (GREATEST_FIRST_FAIL() && greatest_info.failed > 0) return; \ + greatest_info.suite.tests_run = 0; \ + greatest_info.suite.failed = 0; \ + greatest_info.suite.passed = 0; \ + greatest_info.suite.skipped = 0; \ + greatest_info.suite.pre_suite = 0; \ + greatest_info.suite.post_suite = 0; \ + greatest_info.suite.pre_test = 0; \ + greatest_info.suite.post_test = 0; \ + greatest_info.col = 0; \ + fprintf(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name); \ + GREATEST_SET_TIME(greatest_info.suite.pre_suite); \ + suite_cb(); \ + GREATEST_SET_TIME(greatest_info.suite.post_suite); \ + if (greatest_info.suite.tests_run > 0) { \ + fprintf(GREATEST_STDOUT, \ + "\n%u tests - %u pass, %u fail, %u skipped", \ + greatest_info.suite.tests_run, \ + greatest_info.suite.passed, \ + greatest_info.suite.failed, \ + greatest_info.suite.skipped); \ + GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite, \ + greatest_info.suite.post_suite); \ + fprintf(GREATEST_STDOUT, "\n"); \ + } \ + greatest_info.setup = NULL; \ + greatest_info.setup_udata = NULL; \ + greatest_info.teardown = NULL; \ + greatest_info.teardown_udata = NULL; \ + greatest_info.passed += greatest_info.suite.passed; \ + greatest_info.failed += greatest_info.suite.failed; \ + greatest_info.skipped += greatest_info.suite.skipped; \ + greatest_info.tests_run += greatest_info.suite.tests_run; \ +} \ + \ +void greatest_do_pass(const char *name) { \ + if (GREATEST_IS_VERBOSE()) { \ + fprintf(GREATEST_STDOUT, "PASS %s: %s", \ + name, greatest_info.msg ? greatest_info.msg : ""); \ + } else { \ + fprintf(GREATEST_STDOUT, "."); \ + } \ + greatest_info.suite.passed++; \ +} \ + \ +void greatest_do_fail(const char *name) { \ + if (GREATEST_IS_VERBOSE()) { \ + fprintf(GREATEST_STDOUT, \ + "FAIL %s: %s (%s:%u)", \ + name, greatest_info.msg ? greatest_info.msg : "", \ + greatest_info.fail_file, greatest_info.fail_line); \ + } else { \ + fprintf(GREATEST_STDOUT, "F"); \ + /* add linebreak if in line of '.'s */ \ + if (greatest_info.col % greatest_info.width != 0) \ + fprintf(GREATEST_STDOUT, "\n"); \ + greatest_info.col = 0; \ + fprintf(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)\n", \ + name, \ + greatest_info.msg ? greatest_info.msg : "", \ + greatest_info.fail_file, greatest_info.fail_line); \ + } \ + greatest_info.suite.failed++; \ +} \ + \ +void greatest_do_skip(const char *name) { \ + if (GREATEST_IS_VERBOSE()) { \ + fprintf(GREATEST_STDOUT, "SKIP %s: %s", \ + name, \ + greatest_info.msg ? \ + greatest_info.msg : "" ); \ + } else { \ + fprintf(GREATEST_STDOUT, "s"); \ + } \ + greatest_info.suite.skipped++; \ +} \ + \ +void greatest_usage(const char *name) { \ + fprintf(GREATEST_STDOUT, \ + "Usage: %s [-hlfv] [-s SUITE] [-t TEST]\n" \ + " -h print this Help\n" \ + " -l List suites and their tests, then exit\n" \ + " -f Stop runner after first failure\n" \ + " -v Verbose output\n" \ + " -s SUITE only run suite named SUITE\n" \ + " -t TEST only run test named TEST\n", \ + name); \ +} \ + \ +void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata) { \ + greatest_info.setup = cb; \ + greatest_info.setup_udata = udata; \ +} \ + \ +void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, \ + void *udata) { \ + greatest_info.teardown = cb; \ + greatest_info.teardown_udata = udata; \ +} \ + \ +greatest_run_info greatest_info + +/* Handle command-line arguments, etc. */ +#define GREATEST_MAIN_BEGIN() \ + do { \ + int i = 0; \ + memset(&greatest_info, 0, sizeof(greatest_info)); \ + if (greatest_info.width == 0) { \ + greatest_info.width = GREATEST_DEFAULT_WIDTH; \ + } \ + for (i = 1; i < argc; i++) { \ + if (0 == strcmp("-t", argv[i])) { \ + if (argc <= i + 1) { \ + greatest_usage(argv[0]); \ + exit(EXIT_FAILURE); \ + } \ + greatest_info.test_filter = argv[i+1]; \ + i++; \ + } else if (0 == strcmp("-s", argv[i])) { \ + if (argc <= i + 1) { \ + greatest_usage(argv[0]); \ + exit(EXIT_FAILURE); \ + } \ + greatest_info.suite_filter = argv[i+1]; \ + i++; \ + } else if (0 == strcmp("-f", argv[i])) { \ + greatest_info.flags |= GREATEST_FLAG_FIRST_FAIL; \ + } else if (0 == strcmp("-v", argv[i])) { \ + greatest_info.flags |= GREATEST_FLAG_VERBOSE; \ + } else if (0 == strcmp("-l", argv[i])) { \ + greatest_info.flags |= GREATEST_FLAG_LIST_ONLY; \ + } else if (0 == strcmp("-h", argv[i])) { \ + greatest_usage(argv[0]); \ + exit(EXIT_SUCCESS); \ + } else { \ + fprintf(GREATEST_STDOUT, \ + "Unknown argument '%s'\n", argv[i]); \ + greatest_usage(argv[0]); \ + exit(EXIT_FAILURE); \ + } \ + } \ + } while (0); \ + GREATEST_SET_TIME(greatest_info.begin) + +#define GREATEST_MAIN_END() \ + do { \ + if (!GREATEST_LIST_ONLY()) { \ + GREATEST_SET_TIME(greatest_info.end); \ + fprintf(GREATEST_STDOUT, \ + "\nTotal: %u tests", greatest_info.tests_run); \ + GREATEST_CLOCK_DIFF(greatest_info.begin, \ + greatest_info.end); \ + fprintf(GREATEST_STDOUT, "\n"); \ + fprintf(GREATEST_STDOUT, \ + "Pass: %u, fail: %u, skip: %u.\n", \ + greatest_info.passed, \ + greatest_info.failed, greatest_info.skipped); \ + } \ + return (greatest_info.failed > 0 \ + ? EXIT_FAILURE : EXIT_SUCCESS); \ + } while (0) + +/* Make abbreviations without the GREATEST_ prefix for the + * most commonly used symbols. */ +#if GREATEST_USE_ABBREVS +#define TEST GREATEST_TEST +#define SUITE GREATEST_SUITE +#define RUN_TEST GREATEST_RUN_TEST +#define RUN_TEST1 GREATEST_RUN_TEST1 +#define RUN_SUITE GREATEST_RUN_SUITE +#define ASSERT GREATEST_ASSERT +#define ASSERTm GREATEST_ASSERTm +#define ASSERT_FALSE GREATEST_ASSERT_FALSE +#define ASSERT_EQ GREATEST_ASSERT_EQ +#define ASSERT_STR_EQ GREATEST_ASSERT_STR_EQ +#define ASSERT_FALSEm GREATEST_ASSERT_FALSEm +#define ASSERT_EQm GREATEST_ASSERT_EQm +#define ASSERT_STR_EQm GREATEST_ASSERT_STR_EQm +#define PASS GREATEST_PASS +#define FAIL GREATEST_FAIL +#define SKIP GREATEST_SKIP +#define PASSm GREATEST_PASSm +#define FAILm GREATEST_FAILm +#define SKIPm GREATEST_SKIPm +#define SET_SETUP GREATEST_SET_SETUP_CB +#define SET_TEARDOWN GREATEST_SET_TEARDOWN_CB + +#if __STDC_VERSION__ >= 19901L +#endif /* C99 */ +#define RUN_TESTp GREATEST_RUN_TESTp +#endif /* USE_ABBREVS */ + +#endif diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink.c b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink.c new file mode 100755 index 0000000..9de553f --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink.c @@ -0,0 +1,446 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "heatshrink_encoder.h" +#include "heatshrink_decoder.h" + +#define DEF_WINDOW_SZ2 11 +#define DEF_LOOKAHEAD_SZ2 4 +#define DEF_DECODER_INPUT_BUFFER_SIZE 256 +#define DEF_BUFFER_SIZE (64 * 1024) + +#if 0 +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define LOG(...) /* NO-OP */ +#endif + +static const int version_major = HEATSHRINK_VERSION_MAJOR; +static const int version_minor = HEATSHRINK_VERSION_MINOR; +static const int version_patch = HEATSHRINK_VERSION_PATCH; +static const char author[] = HEATSHRINK_AUTHOR; +static const char url[] = HEATSHRINK_URL; + +static void usage(void) { + fprintf(stderr, "heatshrink version %u.%u.%u by %s\n", + version_major, version_minor, version_patch, author); + fprintf(stderr, "Home page: %s\n\n", url); + fprintf(stderr, + "Usage:\n" + " heatshrink [-h] [-e|-d] [-v] [-w SIZE] [-l BITS] [IN_FILE] [OUT_FILE]\n" + "\n" + "heatshrink compresses or uncompresses byte streams using LZSS, and is\n" + "designed especially for embedded, low-memory, and/or hard real-time\n" + "systems.\n" + "\n" + " -h print help\n" + " -e encode (compress, default)\n" + " -d decode (uncompress)\n" + " -v verbose (print input & output sizes, compression ratio, etc.)\n" + "\n" + " -w SIZE Base-2 log of LZSS sliding window size\n" + "\n" + " A larger value allows searches a larger history of the data for repeated\n" + " patterns, potentially compressing more effectively, but will use\n" + " more memory and processing time.\n" + " Recommended default: -w 8 (embedded systems), -w 10 (elsewhere)\n" + " \n" + " -l BITS Number of bits used for back-reference lengths\n" + "\n" + " A larger value allows longer substitutions, but since all\n" + " back-references must use -w + -l bits, larger -w or -l can be\n" + " counterproductive if most patterns are small and/or local.\n" + " Recommended default: -l 4\n" + "\n" + " If IN_FILE or OUT_FILE are unspecified, they will default to\n" + " \"-\" for standard input and standard output, respectively.\n"); + exit(1); +} + +typedef enum { IO_READ, IO_WRITE, } IO_mode; +typedef enum { OP_ENC, OP_DEC, } Operation; + +typedef struct { + int fd; /* file descriptor */ + IO_mode mode; + size_t fill; /* fill index */ + size_t read; /* read index */ + size_t size; + size_t total; + uint8_t buf[]; +} io_handle; + +typedef struct { + uint8_t window_sz2; + uint8_t lookahead_sz2; + size_t decoder_input_buffer_size; + size_t buffer_size; + uint8_t verbose; + Operation cmd; + char *in_fname; + char *out_fname; + io_handle *in; + io_handle *out; +} config; + +static void die(char *msg) { + fprintf(stderr, "%s\n", msg); + exit(EXIT_FAILURE); +} + +static void report(config *cfg); + +/* Open an IO handle. Returns NULL on error. */ +static io_handle *handle_open(char *fname, IO_mode m, size_t buf_sz) { + io_handle *io = NULL; + io = malloc(sizeof(*io) + buf_sz); + if (io == NULL) { return NULL; } + memset(io, 0, sizeof(*io) + buf_sz); + io->fd = -1; + io->size = buf_sz; + io->mode = m; + + if (m == IO_READ) { + if (0 == strcmp("-", fname)) { + io->fd = STDIN_FILENO; + } else { + io->fd = open(fname, O_RDONLY); + } + } else if (m == IO_WRITE) { + if (0 == strcmp("-", fname)) { + io->fd = STDOUT_FILENO; + } else { + io->fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC /*| O_EXCL*/, 0644); + } + } + + if (io->fd == -1) { /* failed to open */ + free(io); + err(1, "open"); + return NULL; + } + + return io; +} + +/* Read SIZE bytes from an IO handle and return a pointer to the content. + * BUF contains at least size_t bytes. Returns 0 on EOF, -1 on error. */ +static ssize_t handle_read(io_handle *io, size_t size, uint8_t **buf) { + LOG("@ read %zd\n", size); + if (buf == NULL) { return -1; } + if (size > io->size) { + printf("size %zd, io->size %zd\n", size, io->size); + return -1; + } + if (io->mode != IO_READ) { return -1; } + + size_t rem = io->fill - io->read; + if (rem >= size) { + *buf = &io->buf[io->read]; + return size; + } else { /* read and replenish */ + if (io->fd == -1) { /* already closed, return what we've got */ + *buf = &io->buf[io->read]; + return rem; + } + + memmove(io->buf, &io->buf[io->read], rem); + io->fill -= io->read; + io->read = 0; + ssize_t read_sz = read(io->fd, &io->buf[io->fill], io->size - io->fill); + if (read_sz < 0) { err(1, "read"); } + io->total += read_sz; + if (read_sz == 0) { /* EOF */ + if (close(io->fd) < 0) { err(1, "close"); } + io->fd = -1; + } + io->fill += read_sz; + *buf = io->buf; + return io->fill > size ? size : io->fill; + } +} + +/* Drop the oldest SIZE bytes from the buffer. Returns <0 on error. */ +static int handle_drop(io_handle *io, size_t size) { + LOG("@ drop %zd\n", size); + if (io->read + size <= io->fill) { + io->read += size; + } else { + return -1; + } + if (io->read == io->fill) { + io->read = 0; + io->fill = 0; + } + return 0; +} + +/* Sink SIZE bytes from INPUT into the io handle. Returns the number of + * bytes written, or -1 on error. */ +static ssize_t handle_sink(io_handle *io, size_t size, uint8_t *input) { + LOG("@ sink %zd\n", size); + if (size > io->size) { return -1; } + if (io->mode != IO_WRITE) { return -1; } + + if (io->fill + size > io->size) { + ssize_t written = write(io->fd, io->buf, io->fill); + LOG("@ flushing %zd, wrote %zd\n", io->fill, written); + io->total += written; + if (written == -1) { err(1, "write"); } + memmove(io->buf, &io->buf[written], io->fill - written); + io->fill -= written; + } + memcpy(&io->buf[io->fill], input, size); + io->fill += size; + return size; +} + +static void handle_close(io_handle *io) { + if (io->fd != -1) { + if (io->mode == IO_WRITE) { + ssize_t written = write(io->fd, io->buf, io->fill); + io->total += written; + LOG("@ close: flushing %zd, wrote %zd\n", io->fill, written); + if (written == -1) { err(1, "write"); } + } + close(io->fd); + io->fd = -1; + } +} + +static void close_and_report(config *cfg) { + handle_close(cfg->in); + handle_close(cfg->out); + if (cfg->verbose) { report(cfg); } + free(cfg->in); + free(cfg->out); +} + +static int encoder_sink_read(config *cfg, heatshrink_encoder *hse, + uint8_t *data, size_t data_sz) { + size_t out_sz = 4096; + uint8_t out_buf[out_sz]; + memset(out_buf, 0, out_sz); + size_t sink_sz = 0; + size_t poll_sz = 0; + HSE_sink_res sres; + HSE_poll_res pres; + HSE_finish_res fres; + io_handle *out = cfg->out; + + size_t sunk = 0; + do { + if (data_sz > 0) { + sres = heatshrink_encoder_sink(hse, &data[sunk], data_sz - sunk, &sink_sz); + if (sres < 0) { die("sink"); } + sunk += sink_sz; + } + + do { + pres = heatshrink_encoder_poll(hse, out_buf, out_sz, &poll_sz); + if (pres < 0) { die("poll"); } + if (handle_sink(out, poll_sz, out_buf) < 0) die("handle_sink"); + } while (pres == HSER_POLL_MORE); + + if (poll_sz == 0 && data_sz == 0) { + fres = heatshrink_encoder_finish(hse); + if (fres < 0) { die("finish"); } + if (fres == HSER_FINISH_DONE) { return 1; } + } + } while (sunk < data_sz); + return 0; +} + +static int encode(config *cfg) { + uint8_t window_sz2 = cfg->window_sz2; + size_t window_sz = 1 << window_sz2; + heatshrink_encoder *hse = heatshrink_encoder_alloc(window_sz2, cfg->lookahead_sz2); + if (hse == NULL) { die("failed to init encoder: bad settings"); } + ssize_t read_sz = 0; + io_handle *in = cfg->in; + + /* Process input until end of stream */ + while (1) { + uint8_t *input = NULL; + read_sz = handle_read(in, window_sz, &input); + if (input == NULL) { + printf("handle read failure\n"); + die("read"); + } + if (read_sz < 0) { die("read"); } + + /* Pass read to encoder and check if input is fully processed. */ + if (encoder_sink_read(cfg, hse, input, read_sz)) break; + + if (handle_drop(in, read_sz) < 0) { die("drop"); } + }; + + if (read_sz == -1) { err(1, "read"); } + + heatshrink_encoder_free(hse); + close_and_report(cfg); + return 0; +} + +static int decoder_sink_read(config *cfg, heatshrink_decoder *hsd, + uint8_t *data, size_t data_sz) { + io_handle *out = cfg->out; + size_t sink_sz = 0; + size_t poll_sz = 0; + size_t out_sz = 4096; + uint8_t out_buf[out_sz]; + memset(out_buf, 0, out_sz); + + HSD_sink_res sres; + HSD_poll_res pres; + HSD_finish_res fres; + + size_t sunk = 0; + do { + if (data_sz > 0) { + sres = heatshrink_decoder_sink(hsd, &data[sunk], data_sz - sunk, &sink_sz); + if (sres < 0) { die("sink"); } + sunk += sink_sz; + } + + do { + pres = heatshrink_decoder_poll(hsd, out_buf, out_sz, &poll_sz); + if (pres < 0) { die("poll"); } + if (handle_sink(out, poll_sz, out_buf) < 0) die("handle_sink"); + } while (pres == HSDR_POLL_MORE); + + if (data_sz == 0 && poll_sz == 0) { + fres = heatshrink_decoder_finish(hsd); + if (fres < 0) { die("finish"); } + if (fres == HSDR_FINISH_DONE) { return 1; } + } + } while (sunk < data_sz); + + return 0; +} + +static int decode(config *cfg) { + uint8_t window_sz2 = cfg->window_sz2; + size_t window_sz = 1 << window_sz2; + size_t ibs = cfg->decoder_input_buffer_size; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(ibs, + window_sz2, cfg->lookahead_sz2); + if (hsd == NULL) { die("failed to init decoder"); } + + ssize_t read_sz = 0; + + io_handle *in = cfg->in; + + HSD_finish_res fres; + + /* Process input until end of stream */ + while (1) { + uint8_t *input = NULL; + read_sz = handle_read(in, window_sz, &input); + if (input == NULL) { + printf("handle read failure\n"); + die("read"); + } + if (read_sz == 0) { + fres = heatshrink_decoder_finish(hsd); + if (fres < 0) { die("finish"); } + if (fres == HSDR_FINISH_DONE) break; + } else if (read_sz < 0) { + die("read"); + } else { + if (decoder_sink_read(cfg, hsd, input, read_sz)) { break; } + if (handle_drop(in, read_sz) < 0) { die("drop"); } + } + } + if (read_sz == -1) { err(1, "read"); } + + heatshrink_decoder_free(hsd); + close_and_report(cfg); + return 0; +} + +static void report(config *cfg) { + size_t inb = cfg->in->total; + size_t outb = cfg->out->total; + fprintf(cfg->out->fd == STDOUT_FILENO ? stderr : stdout, + "%s %0.2f %%\t %zd -> %zd (-w %u -l %u)\n", + cfg->in_fname, 100.0 - (100.0 * outb) / inb, inb, outb, + cfg->window_sz2, cfg->lookahead_sz2); +} + +static void proc_args(config *cfg, int argc, char **argv) { + cfg->window_sz2 = DEF_WINDOW_SZ2; + cfg->lookahead_sz2 = DEF_LOOKAHEAD_SZ2; + cfg->buffer_size = DEF_BUFFER_SIZE; + cfg->decoder_input_buffer_size = DEF_DECODER_INPUT_BUFFER_SIZE; + cfg->cmd = OP_ENC; + cfg->verbose = 0; + cfg->in_fname = "-"; + cfg->out_fname = "-"; + + int a = 0; + while ((a = getopt(argc, argv, "hedi:w:l:v")) != -1) { + switch (a) { + case 'h': /* help */ + usage(); + case 'e': /* encode */ + cfg->cmd = OP_ENC; break; + case 'd': /* decode */ + cfg->cmd = OP_DEC; break; + case 'i': /* input buffer size */ + cfg->decoder_input_buffer_size = atoi(optarg); + break; + case 'w': /* window bits */ + cfg->window_sz2 = atoi(optarg); + break; + case 'l': /* lookahead bits */ + cfg->lookahead_sz2 = atoi(optarg); + break; + case 'v': /* verbosity++ */ + cfg->verbose++; + break; + case '?': /* unknown argument */ + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc > 0) { + cfg->in_fname = argv[0]; + argc--; + argv++; + } + if (argc > 0) { cfg->out_fname = argv[0]; } +} + +int main(int argc, char **argv) { + config cfg; + memset(&cfg, 0, sizeof(cfg)); + proc_args(&cfg, argc, argv); + + if (0 == strcmp(cfg.in_fname, cfg.out_fname) + && (0 != strcmp("-", cfg.in_fname))) { + printf("Refusing to overwrite file '%s' with itself.\n", cfg.in_fname); + exit(1); + } + + cfg.in = handle_open(cfg.in_fname, IO_READ, cfg.buffer_size); + if (cfg.in == NULL) { die("Failed to open input file for read"); } + cfg.out = handle_open(cfg.out_fname, IO_WRITE, cfg.buffer_size); + if (cfg.out == NULL) { die("Failed to open output file for write"); } + + if (cfg.cmd == OP_ENC) { + return encode(&cfg); + } else if (cfg.cmd == OP_DEC) { + return decode(&cfg); + } else { + usage(); + } +} diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_common.h b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_common.h new file mode 100644 index 0000000..0d396b9 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_common.h @@ -0,0 +1,20 @@ +#ifndef HEATSHRINK_H +#define HEATSHRINK_H + +#define HEATSHRINK_AUTHOR "Scott Vokes " +#define HEATSHRINK_URL "https://github.com/atomicobject/heatshrink" + +/* Version 0.3.1 */ +#define HEATSHRINK_VERSION_MAJOR 0 +#define HEATSHRINK_VERSION_MINOR 3 +#define HEATSHRINK_VERSION_PATCH 1 + +#define HEATSHRINK_MIN_WINDOW_BITS 4 +#define HEATSHRINK_MAX_WINDOW_BITS 15 + +#define HEATSHRINK_MIN_LOOKAHEAD_BITS 2 + +#define HEATSHRINK_LITERAL_MARKER 0x01 +#define HEATSHRINK_BACKREF_MARKER 0x00 + +#endif diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_config.h b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_config.h new file mode 100644 index 0000000..51d4772 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_config.h @@ -0,0 +1,24 @@ +#ifndef HEATSHRINK_CONFIG_H +#define HEATSHRINK_CONFIG_H + +/* Should functionality assuming dynamic allocation be used? */ +#define HEATSHRINK_DYNAMIC_ALLOC 1 + +#if HEATSHRINK_DYNAMIC_ALLOC + /* Optional replacement of malloc/free */ + #define HEATSHRINK_MALLOC(SZ) malloc(SZ) + #define HEATSHRINK_FREE(P, SZ) free(P) +#else + /* Required parameters for static configuration */ + #define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 32 + #define HEATSHRINK_STATIC_WINDOW_BITS 8 + #define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4 +#endif + +/* Turn on logging for debugging. */ +#define HEATSHRINK_DEBUGGING_LOGS 0 + +/* Use indexing for faster compression. (This requires additional space.) */ +#define HEATSHRINK_USE_INDEX 1 + +#endif diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.c b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.c new file mode 100644 index 0000000..b92be13 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.c @@ -0,0 +1,382 @@ +#include +#include +#include "heatshrink_decoder.h" + +/* States for the polling state machine. */ +typedef enum { + HSDS_EMPTY, /* no input to process */ + HSDS_INPUT_AVAILABLE, /* new input, completely unprocessed */ + HSDS_YIELD_LITERAL, /* ready to yield literal byte */ + HSDS_BACKREF_INDEX_MSB, /* most significant byte of index */ + HSDS_BACKREF_INDEX_LSB, /* least significant byte of index */ + HSDS_BACKREF_COUNT_MSB, /* most significant byte of count */ + HSDS_BACKREF_COUNT_LSB, /* least significant byte of count */ + HSDS_YIELD_BACKREF, /* ready to yield back-reference */ + HSDS_CHECK_FOR_MORE_INPUT, /* check if input is exhausted */ +} HSD_state; + +#if HEATSHRINK_DEBUGGING_LOGS +#include +#include +#include +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#define ASSERT(X) assert(X) +static const char *state_names[] = { + "empty", + "input_available", + "yield_literal", + "backref_index", + "backref_count", + "yield_backref", + "check_for_more_input", +}; +#else +#define LOG(...) /* no-op */ +#define ASSERT(X) /* no-op */ +#endif + +typedef struct { + uint8_t *buf; /* output buffer */ + size_t buf_size; /* buffer size */ + size_t *output_size; /* bytes pushed to buffer, so far */ +} output_info; + +#define NO_BITS ((uint32_t)-1) + +/* Forward references. */ +static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count); +static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte); + +#if HEATSHRINK_DYNAMIC_ALLOC +heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, + uint8_t window_sz2, + uint8_t lookahead_sz2) { + if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) || + (window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) || + (input_buffer_size == 0) || + (lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) || + (lookahead_sz2 > window_sz2)) { + return NULL; + } + size_t buffers_sz = (1 << window_sz2) + input_buffer_size; + size_t sz = sizeof(heatshrink_decoder) + buffers_sz; + heatshrink_decoder *hsd = HEATSHRINK_MALLOC(sz); + if (hsd == NULL) { return NULL; } + hsd->input_buffer_size = input_buffer_size; + hsd->window_sz2 = window_sz2; + hsd->lookahead_sz2 = lookahead_sz2; + heatshrink_decoder_reset(hsd); + LOG("-- allocated decoder with buffer size of %zu (%zu + %u + %u)\n", + sz, sizeof(heatshrink_decoder), (1 << window_sz2), input_buffer_size); + return hsd; +} + +void heatshrink_decoder_free(heatshrink_decoder *hsd) { + size_t buffers_sz = (1 << hsd->window_sz2) + hsd->input_buffer_size; + size_t sz = sizeof(heatshrink_decoder) + buffers_sz; + HEATSHRINK_FREE(hsd, sz); + (void)sz; /* may not be used by free */ +} +#endif + +void heatshrink_decoder_reset(heatshrink_decoder *hsd) { + size_t buf_sz = 1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd); + size_t input_sz = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd); + memset(hsd->buffers, 0, buf_sz + input_sz); + hsd->state = HSDS_EMPTY; + hsd->input_size = 0; + hsd->input_index = 0; + hsd->bit_index = 0x00; + hsd->current_byte = 0x00; + hsd->output_count = 0; + hsd->output_index = 0; + hsd->head_index = 0; + hsd->bit_accumulator = 0x00000000; +} + +/* Copy SIZE bytes into the decoder's input buffer, if it will fit. */ +HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd, + uint8_t *in_buf, size_t size, size_t *input_size) { + if ((hsd == NULL) || (in_buf == NULL) || (input_size == NULL)) { + return HSDR_SINK_ERROR_NULL; + } + + size_t rem = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd) - hsd->input_size; + if (rem == 0) { + *input_size = 0; + return HSDR_SINK_FULL; + } + + size = rem < size ? rem : size; + LOG("-- sinking %zd bytes\n", size); + /* copy into input buffer (at head of buffers) */ + memcpy(&hsd->buffers[hsd->input_size], in_buf, size); + hsd->input_size += size; + if (hsd->state == HSDS_EMPTY) { + hsd->state = HSDS_INPUT_AVAILABLE; + hsd->input_index = 0; + } + *input_size = size; + return HSDR_SINK_OK; +} + + +/***************** + * Decompression * + *****************/ + +#define BACKREF_COUNT_BITS(HSD) (HEATSHRINK_DECODER_LOOKAHEAD_BITS(HSD)) +#define BACKREF_INDEX_BITS(HSD) (HEATSHRINK_DECODER_WINDOW_BITS(HSD)) + +// States +static HSD_state st_input_available(heatshrink_decoder *hsd); +static HSD_state st_yield_literal(heatshrink_decoder *hsd, + output_info *oi); +static HSD_state st_backref_index_msb(heatshrink_decoder *hsd); +static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd); +static HSD_state st_backref_count_msb(heatshrink_decoder *hsd); +static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd); +static HSD_state st_yield_backref(heatshrink_decoder *hsd, + output_info *oi); +static HSD_state st_check_for_input(heatshrink_decoder *hsd); + +HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd, + uint8_t *out_buf, size_t out_buf_size, size_t *output_size) { + if ((hsd == NULL) || (out_buf == NULL) || (output_size == NULL)) { + return HSDR_POLL_ERROR_NULL; + } + *output_size = 0; + + output_info oi; + oi.buf = out_buf; + oi.buf_size = out_buf_size; + oi.output_size = output_size; + + while (1) { + LOG("-- poll, state is %d (%s), input_size %d\n", + hsd->state, state_names[hsd->state], hsd->input_size); + uint8_t in_state = hsd->state; + switch (in_state) { + case HSDS_EMPTY: + return HSDR_POLL_EMPTY; + case HSDS_INPUT_AVAILABLE: + hsd->state = st_input_available(hsd); + break; + case HSDS_YIELD_LITERAL: + hsd->state = st_yield_literal(hsd, &oi); + break; + case HSDS_BACKREF_INDEX_MSB: + hsd->state = st_backref_index_msb(hsd); + break; + case HSDS_BACKREF_INDEX_LSB: + hsd->state = st_backref_index_lsb(hsd); + break; + case HSDS_BACKREF_COUNT_MSB: + hsd->state = st_backref_count_msb(hsd); + break; + case HSDS_BACKREF_COUNT_LSB: + hsd->state = st_backref_count_lsb(hsd); + break; + case HSDS_YIELD_BACKREF: + hsd->state = st_yield_backref(hsd, &oi); + break; + case HSDS_CHECK_FOR_MORE_INPUT: + hsd->state = st_check_for_input(hsd); + break; + default: + return HSDR_POLL_ERROR_UNKNOWN; + } + + /* If the current state cannot advance, check if input or output + * buffer are exhausted. */ + if (hsd->state == in_state) { + if (*output_size == out_buf_size) { return HSDR_POLL_MORE; } + return HSDR_POLL_EMPTY; + } + } +} + +static HSD_state st_input_available(heatshrink_decoder *hsd) { + uint32_t bits = get_bits(hsd, 1); // get tag bit + if (bits) { + return HSDS_YIELD_LITERAL; + } else if (HEATSHRINK_DECODER_WINDOW_BITS(hsd) > 8) { + return HSDS_BACKREF_INDEX_MSB; + } else { + hsd->output_index = 0; + return HSDS_BACKREF_INDEX_LSB; + } +} + +static HSD_state st_yield_literal(heatshrink_decoder *hsd, + output_info *oi) { + /* Emit a repeated section from the window buffer, and add it (again) + * to the window buffer. (Note that the repetition can include + * itself.)*/ + if (*oi->output_size < oi->buf_size) { + uint32_t byte = get_bits(hsd, 8); + if (byte == NO_BITS) { return HSDS_YIELD_LITERAL; } /* out of input */ + uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)]; + uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1; + uint8_t c = byte & 0xFF; + LOG("-- emitting literal byte 0x%02x ('%c')\n", c, isprint(c) ? c : '.'); + buf[hsd->head_index++ & mask] = c; + push_byte(hsd, oi, c); + return HSDS_CHECK_FOR_MORE_INPUT; + } else { + return HSDS_YIELD_LITERAL; + } +} + +static HSD_state st_backref_index_msb(heatshrink_decoder *hsd) { + uint8_t bit_ct = BACKREF_INDEX_BITS(hsd); + ASSERT(bit_ct > 8); + uint32_t bits = get_bits(hsd, bit_ct - 8); + LOG("-- backref index (msb), got 0x%04x (+1)\n", bits); + if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_MSB; } + hsd->output_index = bits << 8; + return HSDS_BACKREF_INDEX_LSB; +} + +static HSD_state st_backref_index_lsb(heatshrink_decoder *hsd) { + uint8_t bit_ct = BACKREF_INDEX_BITS(hsd); + uint32_t bits = get_bits(hsd, bit_ct < 8 ? bit_ct : 8); + LOG("-- backref index (lsb), got 0x%04x (+1)\n", bits); + if (bits == NO_BITS) { return HSDS_BACKREF_INDEX_LSB; } + hsd->output_index |= bits; + hsd->output_index++; + uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd); + hsd->output_count = 0; + return (br_bit_ct > 8) ? HSDS_BACKREF_COUNT_MSB : HSDS_BACKREF_COUNT_LSB; +} + +static HSD_state st_backref_count_msb(heatshrink_decoder *hsd) { + uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd); + ASSERT(br_bit_ct > 8); + uint32_t bits = get_bits(hsd, br_bit_ct - 8); + LOG("-- backref count (msb), got 0x%04x (+1)\n", bits); + if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_MSB; } + hsd->output_count = bits << 8; + return HSDS_BACKREF_COUNT_LSB; +} + +static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd) { + uint8_t br_bit_ct = BACKREF_COUNT_BITS(hsd); + uint32_t bits = get_bits(hsd, br_bit_ct < 8 ? br_bit_ct : 8); + LOG("-- backref count (lsb), got 0x%04x (+1)\n", bits); + if (bits == NO_BITS) { return HSDS_BACKREF_COUNT_LSB; } + hsd->output_count |= bits; + hsd->output_count++; + return HSDS_YIELD_BACKREF; +} + +static HSD_state st_yield_backref(heatshrink_decoder *hsd, + output_info *oi) { + size_t count = oi->buf_size - *oi->output_size; + if (count > 0) { + if (hsd->output_count < count) count = hsd->output_count; + uint8_t *buf = &hsd->buffers[HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd)]; + uint16_t mask = (1 << HEATSHRINK_DECODER_WINDOW_BITS(hsd)) - 1; + uint16_t neg_offset = hsd->output_index; + LOG("-- emitting %zu bytes from -%u bytes back\n", count, neg_offset); + ASSERT(neg_offset < mask + 1); + ASSERT(count <= 1 << BACKREF_COUNT_BITS(hsd)); + + for (size_t i=0; ihead_index - neg_offset) & mask]; + push_byte(hsd, oi, c); + buf[hsd->head_index & mask] = c; + hsd->head_index++; + LOG(" -- ++ 0x%02x\n", c); + } + hsd->output_count -= count; + if (hsd->output_count == 0) { return HSDS_CHECK_FOR_MORE_INPUT; } + } + return HSDS_YIELD_BACKREF; +} + +static HSD_state st_check_for_input(heatshrink_decoder *hsd) { + return (hsd->input_size == 0) ? HSDS_EMPTY : HSDS_INPUT_AVAILABLE; +} + +/* Get the next COUNT bits from the input buffer, saving incremental progress. + * Returns NO_BITS on end of input, or if more than 31 bits are requested. */ +static uint32_t get_bits(heatshrink_decoder *hsd, uint8_t count) { + if (count > 31) { return NO_BITS; } + LOG("-- popping %u bit(s)\n", count); + + /* If we aren't able to get COUNT bits, suspend immediately, because we + * don't track how many bits of COUNT we've accumulated before suspend. */ + if (hsd->input_size == 0) { + if (hsd->bit_index < (1 << (count - 1))) { return NO_BITS; } + } + + for (int i = 0; i < count; i++) { + if (hsd->bit_index == 0x00) { + if (hsd->input_size == 0) { + LOG(" -- out of bits, suspending w/ accumulator of %u (0x%02x)\n", + hsd->bit_accumulator, hsd->bit_accumulator); + return NO_BITS; + } + hsd->current_byte = hsd->buffers[hsd->input_index++]; + LOG(" -- pulled byte 0x%02x\n", hsd->current_byte); + if (hsd->input_index == hsd->input_size) { + hsd->input_index = 0; /* input is exhausted */ + hsd->input_size = 0; + } + hsd->bit_index = 0x80; + } + hsd->bit_accumulator <<= 1; + if (hsd->current_byte & hsd->bit_index) { + hsd->bit_accumulator |= 0x01; + if (0) { + LOG(" -- got 1, accumulator 0x%04x, bit_index 0x%02x\n", + hsd->bit_accumulator, hsd->bit_index); + } + } else { + if (0) { + LOG(" -- got 0, accumulator 0x%04x, bit_index 0x%02x\n", + hsd->bit_accumulator, hsd->bit_index); + } + } + hsd->bit_index >>= 1; + } + + uint32_t res = 0; + res = hsd->bit_accumulator; + hsd->bit_accumulator = 0x00000000; + if (count > 1) { LOG(" -- accumulated %08x\n", res); } + return res; +} + +HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd) { + if (hsd == NULL) { return HSDR_FINISH_ERROR_NULL; } + switch (hsd->state) { + case HSDS_EMPTY: + return HSDR_FINISH_DONE; + + /* If we want to finish with no input, but are in these states, it's + * because the 0-bit padding to the last byte looks like a backref + * marker bit followed by all 0s for index and count bits. */ + case HSDS_BACKREF_INDEX_LSB: + case HSDS_BACKREF_INDEX_MSB: + case HSDS_BACKREF_COUNT_LSB: + case HSDS_BACKREF_COUNT_MSB: + return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE; + + /* If the output stream is padded with 0xFFs (possibly due to being in + * flash memory), also explicitly check the input size rather than + * uselessly returning MORE but yielding 0 bytes when polling. */ + case HSDS_YIELD_LITERAL: + return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE; + + default: + return HSDR_FINISH_MORE; + } +} + +static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte) { + LOG(" -- pushing byte: 0x%02x ('%c')\n", byte, isprint(byte) ? byte : '.'); + oi->buf[(*oi->output_size)++] = byte; + (void)hsd; +} diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.h b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.h new file mode 100644 index 0000000..c1eb144 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_decoder.h @@ -0,0 +1,101 @@ +#ifndef HEATSHRINK_DECODER_H +#define HEATSHRINK_DECODER_H + +#include +#include +#include "heatshrink_common.h" +#include "heatshrink_config.h" + +typedef enum { + HSDR_SINK_OK, /* data sunk, ready to poll */ + HSDR_SINK_FULL, /* out of space in internal buffer */ + HSDR_SINK_ERROR_NULL=-1, /* NULL argument */ +} HSD_sink_res; + +typedef enum { + HSDR_POLL_EMPTY, /* input exhausted */ + HSDR_POLL_MORE, /* more data remaining, call again w/ fresh output buffer */ + HSDR_POLL_ERROR_NULL=-1, /* NULL arguments */ + HSDR_POLL_ERROR_UNKNOWN=-2, +} HSD_poll_res; + +typedef enum { + HSDR_FINISH_DONE, /* output is done */ + HSDR_FINISH_MORE, /* more output remains */ + HSDR_FINISH_ERROR_NULL=-1, /* NULL arguments */ +} HSD_finish_res; + +#if HEATSHRINK_DYNAMIC_ALLOC +#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(BUF) \ + ((BUF)->input_buffer_size) +#define HEATSHRINK_DECODER_WINDOW_BITS(BUF) \ + ((BUF)->window_sz2) +#define HEATSHRINK_DECODER_LOOKAHEAD_BITS(BUF) \ + ((BUF)->lookahead_sz2) +#else +#define HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_) \ + HEATSHRINK_STATIC_INPUT_BUFFER_SIZE +#define HEATSHRINK_DECODER_WINDOW_BITS(_) \ + (HEATSHRINK_STATIC_WINDOW_BITS) +#define HEATSHRINK_DECODER_LOOKAHEAD_BITS(BUF) \ + (HEATSHRINK_STATIC_LOOKAHEAD_BITS) +#endif + +typedef struct { + uint16_t input_size; /* bytes in input buffer */ + uint16_t input_index; /* offset to next unprocessed input byte */ + uint16_t output_count; /* how many bytes to output */ + uint16_t output_index; /* index for bytes to output */ + uint16_t head_index; /* head of window buffer */ + uint16_t bit_accumulator; + uint8_t state; /* current state machine node */ + uint8_t current_byte; /* current byte of input */ + uint8_t bit_index; /* current bit index */ + +#if HEATSHRINK_DYNAMIC_ALLOC + /* Fields that are only used if dynamically allocated. */ + uint8_t window_sz2; /* window buffer bits */ + uint8_t lookahead_sz2; /* lookahead bits */ + uint16_t input_buffer_size; /* input buffer size */ + + /* Input buffer, then expansion window buffer */ + uint8_t buffers[]; +#else + /* Input buffer, then expansion window buffer */ + uint8_t buffers[(1 << HEATSHRINK_DECODER_WINDOW_BITS(_)) + + HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(_)]; +#endif +} heatshrink_decoder; + +#if HEATSHRINK_DYNAMIC_ALLOC +/* Allocate a decoder with an input buffer of INPUT_BUFFER_SIZE bytes, + * an expansion buffer size of 2^WINDOW_SZ2, and a lookahead + * size of 2^lookahead_sz2. (The window buffer and lookahead sizes + * must match the settings used when the data was compressed.) + * Returns NULL on error. */ +heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, + uint8_t expansion_buffer_sz2, uint8_t lookahead_sz2); + +/* Free a decoder. */ +void heatshrink_decoder_free(heatshrink_decoder *hsd); +#endif + +/* Reset a decoder. */ +void heatshrink_decoder_reset(heatshrink_decoder *hsd); + +/* Sink at most SIZE bytes from IN_BUF into the decoder. *INPUT_SIZE is set to + * indicate how many bytes were actually sunk (in case a buffer was filled). */ +HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd, + uint8_t *in_buf, size_t size, size_t *input_size); + +/* Poll for output from the decoder, copying at most OUT_BUF_SIZE bytes into + * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */ +HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd, + uint8_t *out_buf, size_t out_buf_size, size_t *output_size); + +/* Notify the dencoder that the input stream is finished. + * If the return value is HSDR_FINISH_MORE, there is still more output, so + * call heatshrink_decoder_poll and repeat. */ +HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd); + +#endif diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.c b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.c new file mode 100644 index 0000000..ede5f60 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.c @@ -0,0 +1,650 @@ +#include +#include +#include +#include "heatshrink_encoder.h" + +typedef enum { + HSES_NOT_FULL, /* input buffer not full enough */ + HSES_FILLED, /* buffer is full */ + HSES_SEARCH, /* searching for patterns */ + HSES_YIELD_TAG_BIT, /* yield tag bit */ + HSES_YIELD_LITERAL, /* emit literal byte */ + HSES_YIELD_BR_INDEX, /* yielding backref index */ + HSES_YIELD_BR_LENGTH, /* yielding backref length */ + HSES_SAVE_BACKLOG, /* copying buffer to backlog */ + HSES_FLUSH_BITS, /* flush bit buffer */ + HSES_DONE, /* done */ +} HSE_state; + +#if HEATSHRINK_DEBUGGING_LOGS +#include +#include +#include +#define LOG(...) fprintf(stderr, __VA_ARGS__) +#define ASSERT(X) assert(X) +static const char *state_names[] = { + "not_full", + "filled", + "search", + "yield_tag_bit", + "yield_literal", + "yield_br_index", + "yield_br_length", + "save_backlog", + "flush_bits", + "done", +}; +#else +#define LOG(...) /* no-op */ +#define ASSERT(X) /* no-op */ +#endif + +// Encoder flags +enum { + FLAG_IS_FINISHING = 0x01, + FLAG_HAS_LITERAL = 0x02, + FLAG_ON_FINAL_LITERAL = 0x04, + FLAG_BACKLOG_IS_PARTIAL = 0x08, + FLAG_BACKLOG_IS_FILLED = 0x10, +}; + +typedef struct { + uint8_t *buf; /* output buffer */ + size_t buf_size; /* buffer size */ + size_t *output_size; /* bytes pushed to buffer, so far */ +} output_info; + +#define MATCH_NOT_FOUND ((uint16_t)-1) + +static uint16_t get_input_offset(heatshrink_encoder *hse); +static uint16_t get_input_buffer_size(heatshrink_encoder *hse); +static uint16_t get_lookahead_size(heatshrink_encoder *hse); +static void add_tag_bit(heatshrink_encoder *hse, output_info *oi, uint8_t tag); +static int can_take_byte(output_info *oi); +static int is_finishing(heatshrink_encoder *hse); +static int backlog_is_partial(heatshrink_encoder *hse); +static int backlog_is_filled(heatshrink_encoder *hse); +static int on_final_literal(heatshrink_encoder *hse); +static void save_backlog(heatshrink_encoder *hse); +static int has_literal(heatshrink_encoder *hse); + +/* Push COUNT (max 8) bits to the output buffer, which has room. */ +static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits, + output_info *oi); +static uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi); +static void push_literal_byte(heatshrink_encoder *hse, output_info *oi); + +#if HEATSHRINK_DYNAMIC_ALLOC +heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2, + uint8_t lookahead_sz2) { + if ((window_sz2 < HEATSHRINK_MIN_WINDOW_BITS) || + (window_sz2 > HEATSHRINK_MAX_WINDOW_BITS) || + (lookahead_sz2 < HEATSHRINK_MIN_LOOKAHEAD_BITS) || + (lookahead_sz2 > window_sz2)) { + return NULL; + } + + /* Note: 2 * the window size is used because the buffer needs to fit + * (1 << window_sz2) bytes for the current input, and an additional + * (1 << window_sz2) bytes for the previous buffer of input, which + * will be scanned for useful backreferences. */ + size_t buf_sz = (2 << window_sz2); + + heatshrink_encoder *hse = HEATSHRINK_MALLOC(sizeof(*hse) + buf_sz); + if (hse == NULL) { return NULL; } + hse->window_sz2 = window_sz2; + hse->lookahead_sz2 = lookahead_sz2; + heatshrink_encoder_reset(hse); + +#if HEATSHRINK_USE_INDEX + size_t index_sz = buf_sz*sizeof(uint16_t); + hse->search_index = HEATSHRINK_MALLOC(index_sz + sizeof(struct hs_index)); + if (hse->search_index == NULL) { + HEATSHRINK_FREE(hse, sizeof(*hse) + buf_sz); + return NULL; + } + hse->search_index->size = index_sz; +#endif + + LOG("-- allocated encoder with buffer size of %zu (%u byte input size)\n", + buf_sz, get_input_buffer_size(hse)); + return hse; +} + +void heatshrink_encoder_free(heatshrink_encoder *hse) { + size_t buf_sz = (2 << HEATSHRINK_ENCODER_WINDOW_BITS(hse)); +#if HEATSHRINK_USE_INDEX + size_t index_sz = sizeof(struct hs_index) + hse->search_index->size; + HEATSHRINK_FREE(hse->search_index, index_sz); + (void)index_sz; +#endif + HEATSHRINK_FREE(hse, sizeof(heatshrink_encoder) + buf_sz); + (void)buf_sz; +} +#endif + +void heatshrink_encoder_reset(heatshrink_encoder *hse) { + size_t buf_sz = (2 << HEATSHRINK_ENCODER_WINDOW_BITS(hse)); + memset(hse->buffer, 0, buf_sz); + hse->input_size = 0; + hse->state = HSES_NOT_FULL; + hse->match_scan_index = 0; + hse->flags = 0; + hse->bit_index = 0x80; + hse->current_byte = 0x00; + hse->match_length = 0; + + hse->outgoing_bits = 0x0000; + hse->outgoing_bits_count = 0; + + #ifdef LOOP_DETECT + hse->loop_detect = (uint32_t)-1; + #endif +} + +HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse, + uint8_t *in_buf, size_t size, size_t *input_size) { + if ((hse == NULL) || (in_buf == NULL) || (input_size == NULL)) { + return HSER_SINK_ERROR_NULL; + } + + /* Sinking more content after saying the content is done, tsk tsk */ + if (is_finishing(hse)) { return HSER_SINK_ERROR_MISUSE; } + + /* Sinking more content before processing is done */ + if (hse->state != HSES_NOT_FULL) { return HSER_SINK_ERROR_MISUSE; } + + uint16_t write_offset = get_input_offset(hse) + hse->input_size; + uint16_t ibs = get_input_buffer_size(hse); + uint16_t rem = ibs - hse->input_size; + uint16_t cp_sz = rem < size ? rem : size; + + memcpy(&hse->buffer[write_offset], in_buf, cp_sz); + *input_size = cp_sz; + hse->input_size += cp_sz; + + LOG("-- sunk %u bytes (of %zu) into encoder at %d, input buffer now has %u\n", + cp_sz, size, write_offset, hse->input_size); + if (cp_sz == rem) { + LOG("-- internal buffer is now full\n"); + hse->state = HSES_FILLED; + } + + return HSER_SINK_OK; +} + + +/*************** + * Compression * + ***************/ + +static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start, + uint16_t end, const uint16_t maxlen, uint16_t *match_length); +static void do_indexing(heatshrink_encoder *hse); + +static HSE_state st_step_search(heatshrink_encoder *hse); +static HSE_state st_yield_tag_bit(heatshrink_encoder *hse, + output_info *oi); +static HSE_state st_yield_literal(heatshrink_encoder *hse, + output_info *oi); +static HSE_state st_yield_br_index(heatshrink_encoder *hse, + output_info *oi); +static HSE_state st_yield_br_length(heatshrink_encoder *hse, + output_info *oi); +static HSE_state st_save_backlog(heatshrink_encoder *hse); +static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse, + output_info *oi); + +HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse, + uint8_t *out_buf, size_t out_buf_size, size_t *output_size) { + if ((hse == NULL) || (out_buf == NULL) || (output_size == NULL)) { + return HSER_POLL_ERROR_NULL; + } + if (out_buf_size == 0) { + LOG("-- MISUSE: output buffer size is 0\n"); + return HSER_POLL_ERROR_MISUSE; + } + *output_size = 0; + + output_info oi; + oi.buf = out_buf; + oi.buf_size = out_buf_size; + oi.output_size = output_size; + + while (1) { + LOG("-- polling, state %u (%s), flags 0x%02x\n", + hse->state, state_names[hse->state], hse->flags); + + uint8_t in_state = hse->state; + switch (in_state) { + case HSES_NOT_FULL: + return HSER_POLL_EMPTY; + case HSES_FILLED: + do_indexing(hse); + hse->state = HSES_SEARCH; + break; + case HSES_SEARCH: + hse->state = st_step_search(hse); + break; + case HSES_YIELD_TAG_BIT: + hse->state = st_yield_tag_bit(hse, &oi); + break; + case HSES_YIELD_LITERAL: + hse->state = st_yield_literal(hse, &oi); + break; + case HSES_YIELD_BR_INDEX: + hse->state = st_yield_br_index(hse, &oi); + break; + case HSES_YIELD_BR_LENGTH: + hse->state = st_yield_br_length(hse, &oi); + break; + case HSES_SAVE_BACKLOG: + hse->state = st_save_backlog(hse); + break; + case HSES_FLUSH_BITS: + hse->state = st_flush_bit_buffer(hse, &oi); + case HSES_DONE: + return HSER_POLL_EMPTY; + default: + LOG("-- bad state %s\n", state_names[hse->state]); + return HSER_POLL_ERROR_MISUSE; + } + + if (hse->state == in_state) { + /* Check if output buffer is exhausted. */ + if (*output_size == out_buf_size) return HSER_POLL_MORE; + } + } +} + +HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse) { + if (hse == NULL) { return HSER_FINISH_ERROR_NULL; } + LOG("-- setting is_finishing flag\n"); + hse->flags |= FLAG_IS_FINISHING; + if (hse->state == HSES_NOT_FULL) { hse->state = HSES_FILLED; } + return hse->state == HSES_DONE ? HSER_FINISH_DONE : HSER_FINISH_MORE; +} + +static HSE_state st_step_search(heatshrink_encoder *hse) { + uint16_t window_length = get_input_buffer_size(hse); + uint16_t lookahead_sz = get_lookahead_size(hse); + uint16_t msi = hse->match_scan_index; + LOG("## step_search, scan @ +%d (%d/%d), input size %d\n", + msi, hse->input_size + msi, 2*window_length, hse->input_size); + + bool fin = is_finishing(hse); + if (msi >= hse->input_size - (fin ? 0 : lookahead_sz)) { + /* Current search buffer is exhausted, copy it into the + * backlog and await more input. */ + LOG("-- end of search @ %d, saving backlog\n", msi); + return HSES_SAVE_BACKLOG; + } + + uint16_t input_offset = get_input_offset(hse); + uint16_t end = input_offset + msi; + + uint16_t start = 0; + if (backlog_is_filled(hse)) { /* last WINDOW_LENGTH bytes */ + start = end - window_length + 1; + } else if (backlog_is_partial(hse)) { /* clamp to available data */ + start = end - window_length + 1; + if (start < lookahead_sz) { start = lookahead_sz; } + } else { /* only scan available input */ + start = input_offset; + } + + uint16_t max_possible = lookahead_sz; + if (hse->input_size - msi < lookahead_sz) { + max_possible = hse->input_size - msi; + } + + uint16_t match_length = 0; + uint16_t match_pos = find_longest_match(hse, + start, end, max_possible, &match_length); + + if (match_pos == MATCH_NOT_FOUND) { + LOG("ss Match not found\n"); + hse->match_scan_index++; + hse->flags |= FLAG_HAS_LITERAL; + hse->match_length = 0; + return HSES_YIELD_TAG_BIT; + } else { + LOG("ss Found match of %d bytes at %d\n", match_length, match_pos); + hse->match_pos = match_pos; + hse->match_length = match_length; + ASSERT(match_pos < 1 << hse->window_sz2 /*window_length*/); + + return HSES_YIELD_TAG_BIT; + } +} + +static HSE_state st_yield_tag_bit(heatshrink_encoder *hse, + output_info *oi) { + if (can_take_byte(oi)) { + if (hse->match_length == 0) { + add_tag_bit(hse, oi, HEATSHRINK_LITERAL_MARKER); + return HSES_YIELD_LITERAL; + } else { + add_tag_bit(hse, oi, HEATSHRINK_BACKREF_MARKER); + hse->outgoing_bits = hse->match_pos - 1; + hse->outgoing_bits_count = HEATSHRINK_ENCODER_WINDOW_BITS(hse); + return HSES_YIELD_BR_INDEX; + } + } else { + return HSES_YIELD_TAG_BIT; /* output is full, continue */ + } +} + +static HSE_state st_yield_literal(heatshrink_encoder *hse, + output_info *oi) { + if (can_take_byte(oi)) { + push_literal_byte(hse, oi); + hse->flags &= ~FLAG_HAS_LITERAL; + if (on_final_literal(hse)) { return HSES_FLUSH_BITS; } + return hse->match_length > 0 ? HSES_YIELD_TAG_BIT : HSES_SEARCH; + } else { + return HSES_YIELD_LITERAL; + } +} + +static HSE_state st_yield_br_index(heatshrink_encoder *hse, + output_info *oi) { + if (can_take_byte(oi)) { + LOG("-- yielding backref index %u\n", hse->match_pos); + if (push_outgoing_bits(hse, oi) > 0) { + return HSES_YIELD_BR_INDEX; /* continue */ + } else { + hse->outgoing_bits = hse->match_length - 1; + hse->outgoing_bits_count = HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse); + return HSES_YIELD_BR_LENGTH; /* done */ + } + } else { + return HSES_YIELD_BR_INDEX; /* continue */ + } +} + +static HSE_state st_yield_br_length(heatshrink_encoder *hse, + output_info *oi) { + if (can_take_byte(oi)) { + LOG("-- yielding backref length %u\n", hse->match_length); + if (push_outgoing_bits(hse, oi) > 0) { + return HSES_YIELD_BR_LENGTH; + } else { + hse->match_scan_index += hse->match_length; + hse->match_length = 0; + return HSES_SEARCH; + } + } else { + return HSES_YIELD_BR_LENGTH; + } +} + +static HSE_state st_save_backlog(heatshrink_encoder *hse) { + if (is_finishing(hse)) { + /* copy remaining literal (if necessary) */ + if (has_literal(hse)) { + hse->flags |= FLAG_ON_FINAL_LITERAL; + return HSES_YIELD_TAG_BIT; + } else { + return HSES_FLUSH_BITS; + } + } else { + LOG("-- saving backlog\n"); + save_backlog(hse); + return HSES_NOT_FULL; + } +} + +static HSE_state st_flush_bit_buffer(heatshrink_encoder *hse, + output_info *oi) { + if (hse->bit_index == 0x80) { + LOG("-- done!\n"); + return HSES_DONE; + } else if (can_take_byte(oi)) { + LOG("-- flushing remaining byte (bit_index == 0x%02x)\n", hse->bit_index); + oi->buf[(*oi->output_size)++] = hse->current_byte; + LOG("-- done!\n"); + return HSES_DONE; + } else { + return HSES_FLUSH_BITS; + } +} + +static void add_tag_bit(heatshrink_encoder *hse, output_info *oi, uint8_t tag) { + LOG("-- adding tag bit: %d\n", tag); + push_bits(hse, 1, tag, oi); +} + +static uint16_t get_input_offset(heatshrink_encoder *hse) { + return get_input_buffer_size(hse); +} + +static uint16_t get_input_buffer_size(heatshrink_encoder *hse) { + return (1 << HEATSHRINK_ENCODER_WINDOW_BITS(hse)); + (void)hse; +} + +static uint16_t get_lookahead_size(heatshrink_encoder *hse) { + return (1 << HEATSHRINK_ENCODER_LOOKAHEAD_BITS(hse)); + (void)hse; +} + +static void do_indexing(heatshrink_encoder *hse) { +#if HEATSHRINK_USE_INDEX + /* Build an index array I that contains flattened linked lists + * for the previous instances of every byte in the buffer. + * + * For example, if buf[200] == 'x', then index[200] will either + * be an offset i such that buf[i] == 'x', or a negative offset + * to indicate end-of-list. This significantly speeds up matching, + * while only using sizeof(uint16_t)*sizeof(buffer) bytes of RAM. + * + * Future optimization options: + * 1. Since any negative value represents end-of-list, the other + * 15 bits could be used to improve the index dynamically. + * + * 2. Likewise, the last lookahead_sz bytes of the index will + * not be usable, so temporary data could be stored there to + * dynamically improve the index. + * */ + struct hs_index *hsi = HEATSHRINK_ENCODER_INDEX(hse); + uint16_t last[256]; + memset(last, 0xFF, sizeof(last)); + + uint8_t * const data = hse->buffer; + int16_t * const index = hsi->index; + + const uint16_t input_offset = get_input_offset(hse); + const uint16_t end = input_offset + hse->input_size; + + for (uint16_t i=0; iflags & FLAG_IS_FINISHING; +} + +static int backlog_is_partial(heatshrink_encoder *hse) { + return hse->flags & FLAG_BACKLOG_IS_PARTIAL; +} + +static int backlog_is_filled(heatshrink_encoder *hse) { + return hse->flags & FLAG_BACKLOG_IS_FILLED; +} + +static int on_final_literal(heatshrink_encoder *hse) { + return hse->flags & FLAG_ON_FINAL_LITERAL; +} + +static int has_literal(heatshrink_encoder *hse) { + return (hse->flags & FLAG_HAS_LITERAL); +} + +static int can_take_byte(output_info *oi) { + return *oi->output_size < oi->buf_size; +} + +/* Return the longest match for the bytes at buf[end:end+maxlen] between + * buf[start] and buf[end-1]. If no match is found, return -1. */ +static uint16_t find_longest_match(heatshrink_encoder *hse, uint16_t start, + uint16_t end, const uint16_t maxlen, uint16_t *match_length) { + LOG("-- scanning for match of buf[%u:%u] between buf[%u:%u] (max %u bytes)\n", + end, end + maxlen, start, end + maxlen - 1, maxlen); + uint8_t *buf = hse->buffer; + + uint16_t match_maxlen = 0; + uint16_t match_index = MATCH_NOT_FOUND; + const uint16_t break_even_point = 3; + uint16_t len = 0; + uint8_t * const needlepoint = &buf[end]; +#if HEATSHRINK_USE_INDEX + struct hs_index *hsi = HEATSHRINK_ENCODER_INDEX(hse); + int16_t pos = hsi->index[end]; + + while (pos >= start) { + uint8_t * const pospoint = &buf[pos]; + len = 0; + + /* Only check matches that will potentially beat the current maxlen. + * This is redundant with the index if match_maxlen is 0, but the + * added branch overhead to check if it == 0 seems to be worse. */ + if (pospoint[match_maxlen] != needlepoint[match_maxlen]) { + pos = hsi->index[pos]; + continue; + } + + for (len = 1; len < maxlen; len++) { + if (pospoint[len] != needlepoint[len]) break; + } + + if (len > match_maxlen) { + match_maxlen = len; + match_index = pos; + if (len == maxlen) { break; } /* won't find better */ + } + pos = hsi->index[pos]; + } +#else + for (int16_t pos=end - 1; pos >= start; pos--) { + uint8_t * const pospoint = &buf[pos]; + if ((pospoint[match_maxlen] == needlepoint[match_maxlen]) + && (*pospoint == *needlepoint)) { + for (len=1; len cmp buf[%d] == 0x%02x against %02x (start %u)\n", + pos + len, pospoint[len], needlepoint[len], start); + } + if (pospoint[len] != needlepoint[len]) { break; } + } + if (len > match_maxlen) { + match_maxlen = len; + match_index = pos; + if (len == maxlen) { break; } /* don't keep searching */ + } + } + } +#endif + + if (match_maxlen >= break_even_point) { + LOG("-- best match: %u bytes at -%u\n", + match_maxlen, end - match_index); + *match_length = match_maxlen; + return end - match_index; + } + LOG("-- none found\n"); + return MATCH_NOT_FOUND; +} + +static uint8_t push_outgoing_bits(heatshrink_encoder *hse, output_info *oi) { + uint8_t count = 0; + uint8_t bits = 0; + if (hse->outgoing_bits_count > 8) { + count = 8; + bits = hse->outgoing_bits >> (hse->outgoing_bits_count - 8); + } else { + count = hse->outgoing_bits_count; + bits = hse->outgoing_bits; + } + + if (count > 0) { + LOG("-- pushing %d outgoing bits: 0x%02x\n", count, bits); + push_bits(hse, count, bits, oi); + hse->outgoing_bits_count -= count; + } + return count; +} + +/* Push COUNT (max 8) bits to the output buffer, which has room. + * Bytes are set from the lowest bits, up. */ +static void push_bits(heatshrink_encoder *hse, uint8_t count, uint8_t bits, + output_info *oi) { + ASSERT(count <= 8); + LOG("++ push_bits: %d bits, input of 0x%02x\n", count, bits); + + /* If adding a whole byte and at the start of a new output byte, + * just push it through whole and skip the bit IO loop. */ + if (count == 8 && hse->bit_index == 0x80) { + oi->buf[(*oi->output_size)++] = bits; + } else { + for (int i=count - 1; i>=0; i--) { + bool bit = bits & (1 << i); + if (bit) { hse->current_byte |= hse->bit_index; } + if (0) { + LOG(" -- setting bit %d at bit index 0x%02x, byte => 0x%02x\n", + bit ? 1 : 0, hse->bit_index, hse->current_byte); + } + hse->bit_index >>= 1; + if (hse->bit_index == 0x00) { + hse->bit_index = 0x80; + LOG(" > pushing byte 0x%02x\n", hse->current_byte); + oi->buf[(*oi->output_size)++] = hse->current_byte; + hse->current_byte = 0x00; + } + } + } +} + +static void push_literal_byte(heatshrink_encoder *hse, output_info *oi) { + uint16_t processed_offset = hse->match_scan_index - 1; + uint16_t input_offset = get_input_offset(hse) + processed_offset; + uint8_t c = hse->buffer[input_offset]; + LOG("-- yielded literal byte 0x%02x ('%c') from +%d\n", + c, isprint(c) ? c : '.', input_offset); + push_bits(hse, 8, c, oi); +} + +static void save_backlog(heatshrink_encoder *hse) { + size_t input_buf_sz = get_input_buffer_size(hse); + + uint16_t msi = hse->match_scan_index; + + /* Copy processed data to beginning of buffer, so it can be + * used for future matches. Don't bother checking whether the + * input is less than the maximum size, because if it isn't, + * we're done anyway. */ + uint16_t rem = input_buf_sz - msi; // unprocessed bytes + uint16_t shift_sz = input_buf_sz + rem; + + memmove(&hse->buffer[0], + &hse->buffer[input_buf_sz - rem], + shift_sz); + + if (backlog_is_partial(hse)) { + /* The whole backlog is filled in now, so include it in scans. */ + hse->flags |= FLAG_BACKLOG_IS_FILLED; + } else { + /* Include backlog, except for the first lookahead_sz bytes, which + * are still undefined. */ + hse->flags |= FLAG_BACKLOG_IS_PARTIAL; + } + hse->match_scan_index = 0; + hse->input_size -= input_buf_sz - rem; +} diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.h b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.h new file mode 100644 index 0000000..18c1773 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/heatshrink_encoder.h @@ -0,0 +1,109 @@ +#ifndef HEATSHRINK_ENCODER_H +#define HEATSHRINK_ENCODER_H + +#include +#include +#include "heatshrink_common.h" +#include "heatshrink_config.h" + +typedef enum { + HSER_SINK_OK, /* data sunk into input buffer */ + HSER_SINK_ERROR_NULL=-1, /* NULL argument */ + HSER_SINK_ERROR_MISUSE=-2, /* API misuse */ +} HSE_sink_res; + +typedef enum { + HSER_POLL_EMPTY, /* input exhausted */ + HSER_POLL_MORE, /* poll again for more output */ + HSER_POLL_ERROR_NULL=-1, /* NULL argument */ + HSER_POLL_ERROR_MISUSE=-2, /* API misuse */ +} HSE_poll_res; + +typedef enum { + HSER_FINISH_DONE, /* encoding is complete */ + HSER_FINISH_MORE, /* more output remaining; use poll */ + HSER_FINISH_ERROR_NULL=-1, /* NULL argument */ +} HSE_finish_res; + +#if HEATSHRINK_DYNAMIC_ALLOC +#define HEATSHRINK_ENCODER_WINDOW_BITS(HSE) \ + ((HSE)->window_sz2) +#define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(HSE) \ + ((HSE)->lookahead_sz2) +#define HEATSHRINK_ENCODER_INDEX(HSE) \ + ((HSE)->search_index) +struct hs_index { + uint16_t size; + int16_t index[]; +}; +#else +#define HEATSHRINK_ENCODER_WINDOW_BITS(_) \ + (HEATSHRINK_STATIC_WINDOW_BITS) +#define HEATSHRINK_ENCODER_LOOKAHEAD_BITS(_) \ + (HEATSHRINK_STATIC_LOOKAHEAD_BITS) +#define HEATSHRINK_ENCODER_INDEX(HSE) \ + (&(HSE)->search_index) +struct hs_index { + uint16_t size; + int16_t index[2 << HEATSHRINK_STATIC_WINDOW_BITS]; +}; +#endif + +typedef struct { + uint16_t input_size; /* bytes in input buffer */ + uint16_t match_scan_index; + uint16_t match_length; + uint16_t match_pos; + uint16_t outgoing_bits; /* enqueued outgoing bits */ + uint8_t outgoing_bits_count; + uint8_t flags; + uint8_t state; /* current state machine node */ + uint8_t current_byte; /* current byte of output */ + uint8_t bit_index; /* current bit index */ +#if HEATSHRINK_DYNAMIC_ALLOC + uint8_t window_sz2; /* 2^n size of window */ + uint8_t lookahead_sz2; /* 2^n size of lookahead */ +#if HEATSHRINK_USE_INDEX + struct hs_index *search_index; +#endif + /* input buffer and / sliding window for expansion */ + uint8_t buffer[]; +#else + #if HEATSHRINK_USE_INDEX + struct hs_index search_index; + #endif + /* input buffer and / sliding window for expansion */ + uint8_t buffer[2 << HEATSHRINK_ENCODER_WINDOW_BITS(_)]; +#endif +} heatshrink_encoder; + +#if HEATSHRINK_DYNAMIC_ALLOC +/* Allocate a new encoder struct and its buffers. + * Returns NULL on error. */ +heatshrink_encoder *heatshrink_encoder_alloc(uint8_t window_sz2, + uint8_t lookahead_sz2); + +/* Free an encoder. */ +void heatshrink_encoder_free(heatshrink_encoder *hse); +#endif + +/* Reset an encoder. */ +void heatshrink_encoder_reset(heatshrink_encoder *hse); + +/* Sink up to SIZE bytes from IN_BUF into the encoder. + * INPUT_SIZE is set to the number of bytes actually sunk (in case a + * buffer was filled.). */ +HSE_sink_res heatshrink_encoder_sink(heatshrink_encoder *hse, + uint8_t *in_buf, size_t size, size_t *input_size); + +/* Poll for output from the encoder, copying at most OUT_BUF_SIZE bytes into + * OUT_BUF (setting *OUTPUT_SIZE to the actual amount copied). */ +HSE_poll_res heatshrink_encoder_poll(heatshrink_encoder *hse, + uint8_t *out_buf, size_t out_buf_size, size_t *output_size); + +/* Notify the encoder that the input stream is finished. + * If the return value is HSER_FINISH_MORE, there is still more output, so + * call heatshrink_encoder_poll and repeat. */ +HSE_finish_res heatshrink_encoder_finish(heatshrink_encoder *hse); + +#endif diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic.c b/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic.c new file mode 100644 index 0000000..1e18a69 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic.c @@ -0,0 +1,999 @@ +#include +#include +#include + +#include "heatshrink_encoder.h" +#include "heatshrink_decoder.h" +#include "greatest.h" + +#if !HEATSHRINK_DYNAMIC_ALLOC +#error Must set HEATSHRINK_DYNAMIC_ALLOC to 1 for dynamic allocation test suite. +#endif + +SUITE(encoding); +SUITE(decoding); +SUITE(integration); + +#ifdef HEATSHRINK_HAS_THEFT +SUITE(properties); +#endif + +static void dump_buf(char *name, uint8_t *buf, uint16_t count) { + for (int i=0; iinput_size, 6); + ASSERT_EQ(hsd->input_index, 0); + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST decoder_poll_should_return_empty_if_empty(void) { + uint8_t output[256]; + size_t out_sz = 0; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, + HEATSHRINK_MIN_WINDOW_BITS, 4); + HSD_poll_res res = heatshrink_decoder_poll(hsd, output, 256, &out_sz); + ASSERT_EQ(HSDR_POLL_EMPTY, res); + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST decoder_poll_should_reject_null_hsd(void) { + uint8_t output[256]; + size_t out_sz = 0; + HSD_poll_res res = heatshrink_decoder_poll(NULL, output, 256, &out_sz); + ASSERT_EQ(HSDR_POLL_ERROR_NULL, res); + PASS(); +} + +TEST decoder_poll_should_reject_null_output_buffer(void) { + size_t out_sz = 0; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, + HEATSHRINK_MIN_WINDOW_BITS, 4); + HSD_poll_res res = heatshrink_decoder_poll(hsd, NULL, 256, &out_sz); + ASSERT_EQ(HSDR_POLL_ERROR_NULL, res); + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST decoder_poll_should_reject_null_output_size_pointer(void) { + uint8_t output[256]; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, + HEATSHRINK_MIN_WINDOW_BITS, 4); + HSD_poll_res res = heatshrink_decoder_poll(hsd, output, 256, NULL); + ASSERT_EQ(HSDR_POLL_ERROR_NULL, res); + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST decoder_poll_should_expand_short_literal(void) { + uint8_t input[] = {0xb3, 0x5b, 0xed, 0xe0 }; //"foo" + uint8_t output[4]; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, 7, 3); + size_t count = 0; + + HSD_sink_res sres = heatshrink_decoder_sink(hsd, input, sizeof(input), &count); + ASSERT_EQ(HSDR_SINK_OK, sres); + + size_t out_sz = 0; + HSD_poll_res pres = heatshrink_decoder_poll(hsd, output, 4, &out_sz); + ASSERT_EQ(HSDR_POLL_EMPTY, pres); + ASSERT_EQ(3, out_sz); + ASSERT_EQ('f', output[0]); + ASSERT_EQ('o', output[1]); + ASSERT_EQ('o', output[2]); + + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST decoder_poll_should_expand_short_literal_and_backref(void) { + uint8_t input[] = {0xb3, 0x5b, 0xed, 0xe0, 0x40, 0x80}; //"foofoo" + uint8_t output[6]; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, 7, 7); + memset(output, 0, sizeof(*output)); + size_t count = 0; + + HSD_sink_res sres = heatshrink_decoder_sink(hsd, input, sizeof(input), &count); + ASSERT_EQ(HSDR_SINK_OK, sres); + + size_t out_sz = 0; + (void)heatshrink_decoder_poll(hsd, output, 6, &out_sz); + + if (0) dump_buf("output", output, out_sz); + ASSERT_EQ(6, out_sz); + ASSERT_EQ('f', output[0]); + ASSERT_EQ('o', output[1]); + ASSERT_EQ('o', output[2]); + ASSERT_EQ('f', output[3]); + ASSERT_EQ('o', output[4]); + ASSERT_EQ('o', output[5]); + + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST decoder_poll_should_expand_short_self_overlapping_backref(void) { + /* "aaaaa" == (literal, 1), ('a'), (backref, 1 back, 4 bytes) */ + uint8_t input[] = {0xb0, 0x80, 0x01, 0x80}; + uint8_t output[6]; + uint8_t expected[] = {'a', 'a', 'a', 'a', 'a'}; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, 8, 7); + size_t count = 0; + + HSD_sink_res sres = heatshrink_decoder_sink(hsd, input, sizeof(input), &count); + ASSERT_EQ(HSDR_SINK_OK, sres); + + size_t out_sz = 0; + (void)heatshrink_decoder_poll(hsd, output, sizeof(output), &out_sz); + + if (0) dump_buf("output", output, out_sz); + ASSERT_EQ(sizeof(expected), out_sz); + for (size_t i=0; iwindow_sz2, + cfg->lookahead_sz2); + heatshrink_decoder *hsd = heatshrink_decoder_alloc(cfg->decoder_input_buffer_size, + cfg->window_sz2, cfg->lookahead_sz2); + size_t comp_sz = input_size + (input_size/2) + 4; + size_t decomp_sz = input_size + (input_size/2) + 4; + uint8_t *comp = malloc(comp_sz); + uint8_t *decomp = malloc(decomp_sz); + if (comp == NULL) FAILm("malloc fail"); + if (decomp == NULL) FAILm("malloc fail"); + memset(comp, 0, comp_sz); + memset(decomp, 0, decomp_sz); + + size_t count = 0; + + if (cfg->log_lvl > 1) { + printf("\n^^ COMPRESSING\n"); + dump_buf("input", input, input_size); + } + + size_t sunk = 0; + size_t polled = 0; + while (sunk < input_size) { + ASSERT(heatshrink_encoder_sink(hse, &input[sunk], input_size - sunk, &count) >= 0); + sunk += count; + if (cfg->log_lvl > 1) printf("^^ sunk %zd\n", count); + if (sunk == input_size) { + ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(hse)); + } + + HSE_poll_res pres; + do { /* "turn the crank" */ + pres = heatshrink_encoder_poll(hse, &comp[polled], comp_sz - polled, &count); + ASSERT(pres >= 0); + polled += count; + if (cfg->log_lvl > 1) printf("^^ polled %zd\n", count); + } while (pres == HSER_POLL_MORE); + ASSERT_EQ(HSER_POLL_EMPTY, pres); + if (polled >= comp_sz) FAILm("compression should never expand that much"); + if (sunk == input_size) { + ASSERT_EQ(HSER_FINISH_DONE, heatshrink_encoder_finish(hse)); + } + } + if (cfg->log_lvl > 0) printf("in: %u compressed: %zu ", input_size, polled); + size_t compressed_size = polled; + sunk = 0; + polled = 0; + + if (cfg->log_lvl > 1) { + printf("\n^^ DECOMPRESSING\n"); + dump_buf("comp", comp, compressed_size); + } + while (sunk < compressed_size) { + ASSERT(heatshrink_decoder_sink(hsd, &comp[sunk], compressed_size - sunk, &count) >= 0); + sunk += count; + if (cfg->log_lvl > 1) printf("^^ sunk %zd\n", count); + if (sunk == compressed_size) { + ASSERT_EQ(HSDR_FINISH_MORE, heatshrink_decoder_finish(hsd)); + } + + HSD_poll_res pres; + do { + pres = heatshrink_decoder_poll(hsd, &decomp[polled], + decomp_sz - polled, &count); + ASSERT(pres >= 0); + ASSERT(count > 0); + polled += count; + if (cfg->log_lvl > 1) printf("^^ polled %zd\n", count); + } while (pres == HSDR_POLL_MORE); + ASSERT_EQ(HSDR_POLL_EMPTY, pres); + if (sunk == compressed_size) { + HSD_finish_res fres = heatshrink_decoder_finish(hsd); + ASSERT_EQ(HSDR_FINISH_DONE, fres); + } + + if (polled > input_size) { + printf("\nExpected %zd, got %zu\n", (size_t)input_size, polled); + FAILm("Decompressed data is larger than original input"); + } + } + if (cfg->log_lvl > 0) printf("decompressed: %zu\n", polled); + if (polled != input_size) { + FAILm("Decompressed length does not match original input length"); + } + + if (cfg->log_lvl > 1) dump_buf("decomp", decomp, polled); + for (uint32_t i=0; i out[%d] == 0x%02x ('%c') %c\n", + j, input[j], isprint(input[j]) ? input[j] : '.', + j, decomp[j], isprint(decomp[j]) ? decomp[j] : '.', + input[j] == decomp[j] ? ' ' : 'X'); + } + } + } + ASSERT_EQ(input[i], decomp[i]); + } + free(comp); + free(decomp); + heatshrink_encoder_free(hse); + heatshrink_decoder_free(hsd); + PASS(); +} + +TEST data_without_duplication_should_match(void) { + uint8_t input[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; + cfg_info cfg; + cfg.log_lvl = 0; + cfg.window_sz2 = 8; + cfg.lookahead_sz2 = 3; + cfg.decoder_input_buffer_size = 256; + return compress_and_expand_and_check(input, sizeof(input), &cfg); +} + +TEST data_with_simple_repetition_should_compress_and_decompress_properly(void) { + uint8_t input[] = {'a', 'b', 'c', 'a', 'b', 'c', 'd', 'a', 'b', + 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e', 'f', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h'}; + cfg_info cfg; + cfg.log_lvl = 0; + cfg.window_sz2 = 8; + cfg.lookahead_sz2 = 3; + cfg.decoder_input_buffer_size = 256; + return compress_and_expand_and_check(input, sizeof(input), &cfg); +} + +TEST data_without_duplication_should_match_with_absurdly_tiny_buffers(void) { + heatshrink_encoder *hse = heatshrink_encoder_alloc(8, 3); + heatshrink_decoder *hsd = heatshrink_decoder_alloc(256, 8, 3); + uint8_t input[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', + 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; + uint8_t comp[60]; + uint8_t decomp[60]; + size_t count = 0; + int log = 0; + + if (log) dump_buf("input", input, sizeof(input)); + for (uint32_t i=0; i= 0); + } + ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(hse)); + + size_t packed_count = 0; + do { + ASSERT(heatshrink_encoder_poll(hse, &comp[packed_count], 1, &count) >= 0); + packed_count += count; + } while (heatshrink_encoder_finish(hse) == HSER_FINISH_MORE); + + if (log) dump_buf("comp", comp, packed_count); + for (uint32_t i=0; i= 0); + } + + for (uint32_t i=0; i= 0); + } + + if (log) dump_buf("decomp", decomp, sizeof(input)); + for (uint32_t i=0; i= 0); + } + ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(hse)); + + size_t packed_count = 0; + do { + ASSERT(heatshrink_encoder_poll(hse, &comp[packed_count], 1, &count) >= 0); + packed_count += count; + } while (heatshrink_encoder_finish(hse) == HSER_FINISH_MORE); + + if (log) dump_buf("comp", comp, packed_count); + for (uint32_t i=0; i= 0); + } + + for (uint32_t i=0; i= 0); + } + + if (log) dump_buf("decomp", decomp, sizeof(input)); + for (uint32_t i=0; ilog_lvl > 0) { + printf("\n-- size %u, seed %u, input buf %zu\n", + size, seed, cfg->decoder_input_buffer_size); + } + fill_with_pseudorandom_letters(input, size, seed); + return compress_and_expand_and_check(input, size, cfg); +} + +TEST small_input_buffer_should_not_impact_decoder_correctness(void) { + int size = 5; + uint8_t input[size]; + cfg_info cfg; + cfg.log_lvl = 0; + cfg.window_sz2 = 8; + cfg.lookahead_sz2 = 3; + cfg.decoder_input_buffer_size = 5; + for (uint16_t i=0; i= 19901L + printf("\n\nFuzzing (single-byte sizes):\n"); + for (uint8_t lsize=3; lsize < 8; lsize++) { + for (uint32_t size=1; size < 128*1024L; size <<= 1) { + if (GREATEST_IS_VERBOSE()) printf(" -- size %u\n", size); + for (uint16_t ibs=32; ibs<=8192; ibs <<= 1) { /* input buffer size */ + if (GREATEST_IS_VERBOSE()) printf(" -- input buffer %u\n", ibs); + for (uint32_t seed=1; seed<=10; seed++) { + if (GREATEST_IS_VERBOSE()) printf(" -- seed %u\n", seed); + cfg_info cfg; + cfg.log_lvl = 0; + cfg.window_sz2 = 8; + cfg.lookahead_sz2 = lsize; + cfg.decoder_input_buffer_size = ibs; + RUN_TESTp(pseudorandom_data_should_match, size, seed, &cfg); + } + } + } + } + + printf("\nFuzzing (multi-byte sizes):\n"); + for (uint8_t lsize=6; lsize < 9; lsize++) { + for (uint32_t size=1; size < 128*1024L; size <<= 1) { + if (GREATEST_IS_VERBOSE()) printf(" -- size %u\n", size); + for (uint16_t ibs=32; ibs<=8192; ibs <<= 1) { /* input buffer size */ + if (GREATEST_IS_VERBOSE()) printf(" -- input buffer %u\n", ibs); + for (uint32_t seed=1; seed<=10; seed++) { + if (GREATEST_IS_VERBOSE()) printf(" -- seed %u\n", seed); + cfg_info cfg; + cfg.log_lvl = 0; + cfg.window_sz2 = 11; + cfg.lookahead_sz2 = lsize; + cfg.decoder_input_buffer_size = ibs; + RUN_TESTp(pseudorandom_data_should_match, size, seed, &cfg); + } + } + } + } + +#endif +} + +/* Add all the definitions that need to be in the test runner's main file. */ +GREATEST_MAIN_DEFS(); + +int main(int argc, char **argv) { + GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */ + RUN_SUITE(encoding); + RUN_SUITE(decoding); + RUN_SUITE(integration); + #ifdef HEATSHRINK_HAS_THEFT + RUN_SUITE(properties); + #endif + GREATEST_MAIN_END(); /* display results */ +} diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic_theft.c b/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic_theft.c new file mode 100644 index 0000000..2752886 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_dynamic_theft.c @@ -0,0 +1,521 @@ +#include "heatshrink_config.h" +#ifdef HEATSHRINK_HAS_THEFT + +#include +#include +#include +#include +#include + +#include "heatshrink_encoder.h" +#include "heatshrink_decoder.h" +#include "greatest.h" +#include "theft.h" +#include "greatest_theft.h" + +#if !HEATSHRINK_DYNAMIC_ALLOC +#error Must set HEATSHRINK_DYNAMIC_ALLOC to 1 for this test suite. +#endif + +SUITE(properties); + +typedef struct { + int limit; + int fails; + int dots; +} test_env; + +typedef struct { + size_t size; + uint8_t buf[]; +} rbuf; + +static void *rbuf_alloc_cb(struct theft *t, theft_hash seed, void *env) { + test_env *te = (test_env *)env; + //printf("seed is 0x%016llx\n", seed); + + size_t sz = (size_t)(seed % te->limit) + 1; + rbuf *r = malloc(sizeof(rbuf) + sz); + if (r == NULL) { return THEFT_ERROR; } + r->size = sz; + + for (size_t i = 0; i < sz; i += sizeof(theft_hash)) { + theft_hash s = theft_random(t); + for (uint8_t b = 0; b < sizeof(theft_hash); b++) { + if (i + b >= sz) { break; } + r->buf[i + b] = (uint8_t) (s >> (8*b)) & 0xff; + } + } + + return r; +} + +static void rbuf_free_cb(void *instance, void *env) { + free(instance); + (void)env; +} + +static uint64_t rbuf_hash_cb(void *instance, void *env) { + rbuf *r = (rbuf *)instance; + (void)env; + return theft_hash_onepass(r->buf, r->size); +} + +/* Make a copy of a buffer, keeping NEW_SZ bytes starting at OFFSET. */ +static void *copy_rbuf_subset(rbuf *cur, size_t new_sz, size_t byte_offset) { + if (new_sz == 0) { return THEFT_DEAD_END; } + rbuf *nr = malloc(sizeof(rbuf) + new_sz); + if (nr == NULL) { return THEFT_ERROR; } + nr->size = new_sz; + memcpy(nr->buf, &cur->buf[byte_offset], new_sz); + /* printf("%zu -> %zu\n", cur->size, new_sz); */ + return nr; +} + +/* Make a copy of a buffer, but only PORTION, starting OFFSET in + * (e.g. the third quarter is (0.25 at +0.75). Rounds to ints. */ +static void *copy_rbuf_percent(rbuf *cur, float portion, float offset) { + size_t new_sz = cur->size * portion; + size_t byte_offset = (size_t)(cur->size * offset); + return copy_rbuf_subset(cur, new_sz, byte_offset); +} + +/* How to shrink a random buffer to a simpler one. */ +static void *rbuf_shrink_cb(void *instance, uint32_t tactic, void *env) { + rbuf *cur = (rbuf *)instance; + + if (tactic == 0) { /* first half */ + return copy_rbuf_percent(cur, 0.5, 0); + } else if (tactic == 1) { /* second half */ + return copy_rbuf_percent(cur, 0.5, 0.5); + } else if (tactic <= 18) { /* drop 1-16 bytes at start */ + const int last_tactic = 1; + const size_t drop = tactic - last_tactic; + if (cur->size < drop) { return THEFT_DEAD_END; } + return copy_rbuf_subset(cur, cur->size - drop, drop); + } else if (tactic <= 34) { /* drop 1-16 bytes at end */ + const int last_tactic = 18; + const size_t drop = tactic - last_tactic; + if (cur->size < drop) { return THEFT_DEAD_END; } + return copy_rbuf_subset(cur, cur->size - drop, 0); + } else if (tactic == 35) { + /* Divide every byte by 2, saturating at 0 */ + rbuf *cp = copy_rbuf_percent(cur, 1, 0); + if (cp == NULL) { return THEFT_ERROR; } + for (size_t i = 0; i < cp->size; i++) { cp->buf[i] /= 2; } + return cp; + } else if (tactic == 36) { + /* subtract 1 from every byte, saturating at 0 */ + rbuf *cp = copy_rbuf_percent(cur, 1, 0); + if (cp == NULL) { return THEFT_ERROR; } + for (size_t i = 0; i < cp->size; i++) { + if (cp->buf[i] > 0) { cp->buf[i]--; } + } + return cp; + } else { + (void)env; + return THEFT_NO_MORE_TACTICS; + } + + return THEFT_NO_MORE_TACTICS; +} + +static void rbuf_print_cb(FILE *f, void *instance, void *env) { + rbuf *r = (rbuf *)instance; + (void)env; + fprintf(f, "buf[%zd]:\n ", r->size); + uint8_t bytes = 0; + for (size_t i = 0; i < r->size; i++) { + fprintf(f, "%02x", r->buf[i]); + bytes++; + if (bytes == 16) { + fprintf(f, "\n "); + bytes = 0; + } + } + fprintf(f, "\n"); +} + +static struct theft_type_info rbuf_info = { + .alloc = rbuf_alloc_cb, + .free = rbuf_free_cb, + .hash = rbuf_hash_cb, + .shrink = rbuf_shrink_cb, + .print = rbuf_print_cb, +}; + +static theft_progress_callback_res +progress_cb(struct theft_trial_info *info, void *env) { + test_env *te = (test_env *)env; + if ((info->trial & 0xff) == 0) { + printf("."); + fflush(stdout); + te->dots++; + if (te->dots == 64) { + printf("\n"); + te->dots = 0; + } + } + + if (info->status == THEFT_TRIAL_FAIL) { + te->fails++; + rbuf *cur = info->args[0]; + if (cur->size < 5) { return THEFT_PROGRESS_HALT; } + } + + if (te->fails > 10) { + return THEFT_PROGRESS_HALT; + } + return THEFT_PROGRESS_CONTINUE; +} + +/* For an arbitrary input buffer, it should never get stuck in a + * state where the data has been sunk but no data can be polled. */ +static theft_trial_res prop_should_not_get_stuck(void *input) { + /* Make a buffer large enough for the output: 4 KB of input with + * each 16 bits becoming up to 16 bytes will fit in a 64 KB buffer. + * (4 KB of input comes from `env.limit = 1 << 12;` below.) */ + uint8_t output[64 * 1024]; + heatshrink_decoder *hsd = heatshrink_decoder_alloc((64 * 1024L) - 1, 12, 4); + if (hsd == NULL) { return THEFT_TRIAL_ERROR; } + + rbuf *r = (rbuf *)input; + + size_t count = 0; + HSD_sink_res sres = heatshrink_decoder_sink(hsd, r->buf, r->size, &count); + if (sres != HSDR_SINK_OK) { return THEFT_TRIAL_ERROR; } + + size_t out_sz = 0; + HSD_poll_res pres = heatshrink_decoder_poll(hsd, output, sizeof(output), &out_sz); + if (pres != HSDR_POLL_EMPTY) { return THEFT_TRIAL_FAIL; } + + HSD_finish_res fres = heatshrink_decoder_finish(hsd); + heatshrink_decoder_free(hsd); + if (fres != HSDR_FINISH_DONE) { return THEFT_TRIAL_FAIL; } + + return THEFT_TRIAL_PASS; +} + +static bool get_time_seed(theft_seed *seed) +{ + struct timeval tv; + if (-1 == gettimeofday(&tv, NULL)) { return false; } + *seed = (theft_seed)((tv.tv_sec << 32) | tv.tv_usec); + /* printf("seed is 0x%016llx\n", *seed); */ + return true; +} + +TEST decoder_fuzzing_should_not_detect_stuck_state(void) { + // Get a random number seed based on the time + theft_seed seed; + if (!get_time_seed(&seed)) { FAIL(); } + + /* Pass the max buffer size for this property (4 KB) in a closure */ + test_env env = { .limit = 1 << 12 }; + + theft_seed always_seeds = { 0xe87bb1f61032a061 }; + + struct theft *t = theft_init(0); + struct theft_cfg cfg = { + .name = __func__, + .fun = prop_should_not_get_stuck, + .type_info = { &rbuf_info }, + .seed = seed, + .trials = 100000, + .progress_cb = progress_cb, + .env = &env, + + .always_seeds = &always_seeds, + .always_seed_count = 1, + }; + + theft_run_res res = theft_run(t, &cfg); + theft_free(t); + printf("\n"); + GREATEST_ASSERT_EQm("should_not_get_stuck", THEFT_RUN_PASS, res); + PASS(); +} + +static theft_trial_res prop_encoded_and_decoded_data_should_match(void *input) { + uint8_t e_output[64 * 1024]; + uint8_t d_output[64 * 1024]; + heatshrink_encoder *hse = heatshrink_encoder_alloc(12, 4); + if (hse == NULL) { return THEFT_TRIAL_ERROR; } + heatshrink_decoder *hsd = heatshrink_decoder_alloc(4096, 12, 4); + if (hsd == NULL) { return THEFT_TRIAL_ERROR; } + + rbuf *r = (rbuf *)input; + + size_t e_input_size = 0; + HSE_sink_res esres = heatshrink_encoder_sink(hse, + r->buf, r->size, &e_input_size); + if (esres != HSER_SINK_OK) { return THEFT_TRIAL_ERROR; } + if (e_input_size != r->size) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + HSE_finish_res efres = heatshrink_encoder_finish(hse); + if (efres != HSER_FINISH_MORE) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + size_t e_output_size = 0; + HSE_poll_res epres = heatshrink_encoder_poll(hse, + e_output, sizeof(e_output), &e_output_size); + if (epres != HSER_POLL_EMPTY) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + size_t count = 0; + HSD_sink_res sres = heatshrink_decoder_sink(hsd, e_output, e_output_size, &count); + if (sres != HSDR_SINK_OK) { return THEFT_TRIAL_ERROR; } + + size_t d_output_size = 0; + HSD_poll_res pres = heatshrink_decoder_poll(hsd, d_output, + sizeof(d_output), &d_output_size); + if (pres != HSDR_POLL_EMPTY) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + if (d_output_size != r->size) { + printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; + } + + if (0 != memcmp(d_output, r->buf, d_output_size)) { + return THEFT_TRIAL_FAIL; + } + + HSD_finish_res fres = heatshrink_decoder_finish(hsd); + if (fres != HSDR_FINISH_DONE) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + heatshrink_encoder_free(hse); + heatshrink_decoder_free(hsd); + return THEFT_TRIAL_PASS; +} + + +TEST encoded_and_decoded_data_should_match(void) { + test_env env = { .limit = 1 << 11 }; + + theft_seed seed; + if (!get_time_seed(&seed)) { FAIL(); } + + struct theft *t = theft_init(0); + struct theft_cfg cfg = { + .name = __func__, + .fun = prop_encoded_and_decoded_data_should_match, + .type_info = { &rbuf_info }, + .seed = seed, + .trials = 1000000, + .env = &env, + .progress_cb = progress_cb, + }; + + theft_run_res res = theft_run(t, &cfg); + theft_free(t); + printf("\n"); + ASSERT_EQ(THEFT_RUN_PASS, res); + PASS(); +} + +static size_t ceil_nine_eighths(size_t sz) { + return sz + sz/8 + (sz & 0x07 ? 1 : 0); +} + +static theft_trial_res +prop_encoding_data_should_never_increase_it_by_more_than_an_eighth_at_worst(void *input) { + uint8_t output[32 * 1024]; + heatshrink_encoder *hse = heatshrink_encoder_alloc(12, 4); + if (hse == NULL) { return THEFT_TRIAL_ERROR; } + + rbuf *r = (rbuf *)input; + + size_t input_size = 0; + HSE_sink_res esres = heatshrink_encoder_sink(hse, + r->buf, r->size, &input_size); + if (esres != HSER_SINK_OK) { return THEFT_TRIAL_ERROR; } + /* Assumes data fits in one sink, failure here means buffer must be larger. */ + if (input_size != r->size) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + HSE_finish_res efres = heatshrink_encoder_finish(hse); + if (efres != HSER_FINISH_MORE) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + size_t output_size = 0; + HSE_poll_res epres = heatshrink_encoder_poll(hse, + output, sizeof(output), &output_size); + if (epres != HSER_POLL_EMPTY) { printf("FAIL %d\n", __LINE__); return THEFT_TRIAL_FAIL; } + + size_t ceil_9_8s = ceil_nine_eighths(r->size); + if (output_size > ceil_9_8s) { + return THEFT_TRIAL_FAIL; + } + + heatshrink_encoder_free(hse); + return THEFT_TRIAL_PASS; +} + +TEST encoding_data_should_never_increase_it_by_more_than_an_eighth_at_worst(void) { + test_env env = { .limit = 1 << 11 }; + + theft_seed seed; + if (!get_time_seed(&seed)) { FAIL(); } + + struct theft *t = theft_init(0); + struct theft_cfg cfg = { + .name = __func__, + .fun = prop_encoding_data_should_never_increase_it_by_more_than_an_eighth_at_worst, + .type_info = { &rbuf_info }, + .seed = seed, + .trials = 10000, + .env = &env, + .progress_cb = progress_cb, + }; + + theft_run_res res = theft_run(t, &cfg); + theft_free(t); + printf("\n"); + ASSERT_EQ(THEFT_RUN_PASS, res); + PASS(); +} + +static theft_trial_res +prop_encoder_should_always_make_progress(void *instance) { + uint8_t output[64 * 1024]; + heatshrink_encoder *hse = heatshrink_encoder_alloc(8, 4); + if (hse == NULL) { return THEFT_TRIAL_ERROR; } + + rbuf *r = (rbuf *)instance; + + size_t sunk = 0; + int no_progress = 0; + + while (1) { + if (sunk < r->size) { + size_t input_size = 0; + HSE_sink_res esres = heatshrink_encoder_sink(hse, + &r->buf[sunk], r->size - sunk, &input_size); + if (esres != HSER_SINK_OK) { return THEFT_TRIAL_ERROR; } + sunk += input_size; + } else { + HSE_finish_res efres = heatshrink_encoder_finish(hse); + if (efres == HSER_FINISH_DONE) { + break; + } else if (efres != HSER_FINISH_MORE) { + printf("FAIL %d\n", __LINE__); + return THEFT_TRIAL_FAIL; + } + } + + size_t output_size = 0; + HSE_poll_res epres = heatshrink_encoder_poll(hse, + output, sizeof(output), &output_size); + if (epres < 0) { return THEFT_TRIAL_ERROR; } + if (output_size == 0 && sunk == r->size) { + no_progress++; + if (no_progress > 2) { + return THEFT_TRIAL_FAIL; + } + } else { + no_progress = 0; + } + } + + heatshrink_encoder_free(hse); + return THEFT_TRIAL_PASS; +} + +TEST encoder_should_always_make_progress(void) { + test_env env = { .limit = 1 << 15 }; + + theft_seed seed; + if (!get_time_seed(&seed)) { FAIL(); } + + struct theft *t = theft_init(0); + struct theft_cfg cfg = { + .name = __func__, + .fun = prop_encoder_should_always_make_progress, + .type_info = { &rbuf_info }, + .seed = seed, + .trials = 10000, + .env = &env, + .progress_cb = progress_cb, + }; + + theft_run_res res = theft_run(t, &cfg); + theft_free(t); + printf("\n"); + ASSERT_EQ(THEFT_RUN_PASS, res); + PASS(); +} + +static theft_trial_res +prop_decoder_should_always_make_progress(void *instance) { + uint8_t output[64 * 1024]; + heatshrink_decoder *hsd = heatshrink_decoder_alloc(512, 8, 4); + if (hsd == NULL) { return THEFT_TRIAL_ERROR; } + + rbuf *r = (rbuf *)instance; + + size_t sunk = 0; + int no_progress = 0; + + while (1) { + if (sunk < r->size) { + size_t input_size = 0; + HSD_sink_res sres = heatshrink_decoder_sink(hsd, + &r->buf[sunk], r->size - sunk, &input_size); + if (sres != HSER_SINK_OK) { return THEFT_TRIAL_ERROR; } + sunk += input_size; + } else { + HSD_finish_res fres = heatshrink_decoder_finish(hsd); + if (fres == HSDR_FINISH_DONE) { + break; + } else if (fres != HSDR_FINISH_MORE) { + printf("FAIL %d\n", __LINE__); + return THEFT_TRIAL_FAIL; + } + } + + size_t output_size = 0; + HSD_poll_res pres = heatshrink_decoder_poll(hsd, + output, sizeof(output), &output_size); + if (pres < 0) { return THEFT_TRIAL_ERROR; } + if (output_size == 0 && sunk == r->size) { + no_progress++; + if (no_progress > 2) { + return THEFT_TRIAL_FAIL; + } + } else { + no_progress = 0; + } + } + + heatshrink_decoder_free(hsd); + return THEFT_TRIAL_PASS; +} + +TEST decoder_should_always_make_progress(void) { + test_env env = { .limit = 1 << 15 }; + + theft_seed seed; + if (!get_time_seed(&seed)) { FAIL(); } + + struct theft *t = theft_init(0); + struct theft_cfg cfg = { + .name = __func__, + .fun = prop_decoder_should_always_make_progress, + .type_info = { &rbuf_info }, + .seed = seed, + .trials = 10000, + .env = &env, + .progress_cb = progress_cb, + }; + + theft_run_res res = theft_run(t, &cfg); + theft_free(t); + printf("\n"); + ASSERT_EQ(THEFT_RUN_PASS, res); + PASS(); +} + +SUITE(properties) { + RUN_TEST(decoder_fuzzing_should_not_detect_stuck_state); + RUN_TEST(encoded_and_decoded_data_should_match); + RUN_TEST(encoding_data_should_never_increase_it_by_more_than_an_eighth_at_worst); + RUN_TEST(encoder_should_always_make_progress); + RUN_TEST(decoder_should_always_make_progress); +} +#else +struct because_iso_c_requires_at_least_one_declaration; +#endif diff --git a/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_static.c b/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_static.c new file mode 100644 index 0000000..e9c9754 --- /dev/null +++ b/firmwares/minetest/libesphttpd/lib/heatshrink/test_heatshrink_static.c @@ -0,0 +1,167 @@ +#include +#include + +#include "heatshrink_encoder.h" +#include "heatshrink_decoder.h" +#include "greatest.h" + +#if HEATSHRINK_DYNAMIC_ALLOC +#error HEATSHRINK_DYNAMIC_ALLOC must be false for static allocation test suite. +#endif + +SUITE(integration); + +/* The majority of the tests are in test_heatshrink_dynamic, because that allows + * instantiating encoders/decoders with different settings at run-time. */ + +static heatshrink_encoder hse; +static heatshrink_decoder hsd; + +static void fill_with_pseudorandom_letters(uint8_t *buf, uint16_t size, uint32_t seed) { + uint64_t rn = 9223372036854775783; /* prime under 2^64 */ + for (int i=0; i 1) { + printf("\n^^ COMPRESSING\n"); + dump_buf("input", input, input_size); + } + + uint32_t sunk = 0; + uint32_t polled = 0; + while (sunk < input_size) { + ASSERT(heatshrink_encoder_sink(&hse, &input[sunk], input_size - sunk, &count) >= 0); + sunk += count; + if (log_lvl > 1) printf("^^ sunk %zd\n", count); + if (sunk == input_size) { + ASSERT_EQ(HSER_FINISH_MORE, heatshrink_encoder_finish(&hse)); + } + + HSE_poll_res pres; + do { /* "turn the crank" */ + pres = heatshrink_encoder_poll(&hse, &comp[polled], comp_sz - polled, &count); + ASSERT(pres >= 0); + polled += count; + if (log_lvl > 1) printf("^^ polled %zd\n", count); + } while (pres == HSER_POLL_MORE); + ASSERT_EQ(HSER_POLL_EMPTY, pres); + if (polled >= comp_sz) FAILm("compression should never expand that much"); + if (sunk == input_size) { + ASSERT_EQ(HSER_FINISH_DONE, heatshrink_encoder_finish(&hse)); + } + } + if (log_lvl > 0) printf("in: %u compressed: %u ", input_size, polled); + uint32_t compressed_size = polled; + sunk = 0; + polled = 0; + + if (log_lvl > 1) { + printf("\n^^ DECOMPRESSING\n"); + dump_buf("comp", comp, compressed_size); + } + while (sunk < compressed_size) { + ASSERT(heatshrink_decoder_sink(&hsd, &comp[sunk], compressed_size - sunk, &count) >= 0); + sunk += count; + if (log_lvl > 1) printf("^^ sunk %zd\n", count); + if (sunk == compressed_size) { + ASSERT_EQ(HSDR_FINISH_MORE, heatshrink_decoder_finish(&hsd)); + } + + HSD_poll_res pres; + do { + pres = heatshrink_decoder_poll(&hsd, &decomp[polled], + decomp_sz - polled, &count); + ASSERT(pres >= 0); + polled += count; + if (log_lvl > 1) printf("^^ polled %zd\n", count); + } while (pres == HSDR_POLL_MORE); + ASSERT_EQ(HSDR_POLL_EMPTY, pres); + if (sunk == compressed_size) { + HSD_finish_res fres = heatshrink_decoder_finish(&hsd); + ASSERT_EQ(HSDR_FINISH_DONE, fres); + } + + if (polled > input_size) { + FAILm("Decompressed data is larger than original input"); + } + } + if (log_lvl > 0) printf("decompressed: %u\n", polled); + if (polled != input_size) { + FAILm("Decompressed length does not match original input length"); + } + + if (log_lvl > 1) dump_buf("decomp", decomp, polled); + for (size_t i=0; i out[%zd] == 0x%02x ('%c')\n", + j, input[j], isprint(input[j]) ? input[j] : '.', + j, decomp[j], isprint(decomp[j]) ? decomp[j] : '.'); + } + } + } + ASSERT_EQ(input[i], decomp[i]); + } + free(comp); + free(decomp); + PASS(); +} + +TEST pseudorandom_data_should_match(uint32_t size, uint32_t seed) { + uint8_t input[size]; + fill_with_pseudorandom_letters(input, size, seed); + return compress_and_expand_and_check(input, size, 0); +} + +SUITE(integration) { +#if __STDC_VERSION__ >= 19901L + for (uint32_t size=1; size < 64*1024; size <<= 1) { + if (GREATEST_IS_VERBOSE()) printf(" -- size %u\n", size); + for (uint32_t seed=1; seed<=100; seed++) { + if (GREATEST_IS_VERBOSE()) printf(" -- seed %u\n", seed); + RUN_TESTp(pseudorandom_data_should_match, size, seed); + } + } +#endif +} + +/* Add all the definitions that need to be in the test runner's main file. */ +GREATEST_MAIN_DEFS(); + +int main(int argc, char **argv) { + GREATEST_MAIN_BEGIN(); /* command-line arguments, initialization. */ + printf("INPUT_BUFFER_SIZE: %u\n", HEATSHRINK_STATIC_INPUT_BUFFER_SIZE); + printf("WINDOW_BITS: %u\n", HEATSHRINK_STATIC_WINDOW_BITS); + printf("LOOKAHEAD_BITS: %u\n", HEATSHRINK_STATIC_LOOKAHEAD_BITS); + + printf("sizeof(heatshrink_encoder): %zd\n", sizeof(heatshrink_encoder)); + printf("sizeof(heatshrink_decoder): %zd\n", sizeof(heatshrink_decoder)); + RUN_SUITE(integration); + GREATEST_MAIN_END(); /* display results */ +} diff --git a/firmwares/minetest/libesphttpd/mkupgimg/.gitignore b/firmwares/minetest/libesphttpd/mkupgimg/.gitignore new file mode 100644 index 0000000..bf27dbe --- /dev/null +++ b/firmwares/minetest/libesphttpd/mkupgimg/.gitignore @@ -0,0 +1 @@ +mkupgimg diff --git a/firmwares/minetest/libesphttpd/mkupgimg/Makefile b/firmwares/minetest/libesphttpd/mkupgimg/Makefile new file mode 100644 index 0000000..9df6f6a --- /dev/null +++ b/firmwares/minetest/libesphttpd/mkupgimg/Makefile @@ -0,0 +1,5 @@ +mkupgimg: mkupgimg.c + $(CC) -o $@ $^ + +clean: + rm -f mkupgimg diff --git a/firmwares/minetest/libesphttpd/mkupgimg/mkupgimg.c b/firmwares/minetest/libesphttpd/mkupgimg/mkupgimg.c new file mode 100644 index 0000000..8c32848 --- /dev/null +++ b/firmwares/minetest/libesphttpd/mkupgimg/mkupgimg.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct __attribute__((packed)) { + char magic[4]; + char tag[28]; + int32_t len1; + int32_t len2; +} Header; + + +int openFile(char *file) { + int r=open(file, O_RDONLY); + if (r<=0) { + perror(file); + exit(1); + } + return r; +} + +int32_t intToEsp(int32_t v) { + int32_t ret; + char *p=(char*)&ret; + *p++=(v>>0)&0xff; + *p++=(v>>8)&0xff; + *p++=(v>>16)&0xff; + *p++=(v>>24)&0xff; + return ret; +} + +size_t fileLen(int f) { + size_t r; + r=lseek(f, 0, SEEK_END); + lseek(f, 0, SEEK_SET); + return r; +} + + +int main(int argc, char **argv) { + int u1, u2; + size_t l1, l2; + int of; + char *fc1, *fc2; + Header hdr; + if (argc!=5) { + printf("Usage: %s user1.bin user2.bin tagname outfile.bin\n", argv[0]); + exit(1); + } + if (strlen(argv[3])>27) { + printf("Error: Tag can't be longer than 27 characters.\n"); + exit(1); + } + memset(&hdr, 0, sizeof(hdr)); + memcpy(hdr.magic, "EHUG", 4); + strcpy(hdr.tag, argv[3]); + u1=openFile(argv[1]); + u2=openFile(argv[2]); + l1=fileLen(u1); + l2=fileLen(u2); + hdr.len1=intToEsp(l1); + hdr.len2=intToEsp(l2); + fc1=malloc(l1); + fc2=malloc(l2); + if (read(u1, fc1, l1)!=l1) { + perror(argv[1]); + exit(1); + } + if (read(u2, fc2, l2)!=l2) { + perror(argv[2]); + exit(1); + } + close(u1); + close(u2); + of=open(argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (of<=0) { + perror(argv[4]); + exit(1); + } + write(of, &hdr, sizeof(hdr)); + write(of, fc1, l1); + write(of, fc2, l2); + printf("Header: %d bytes, user1: %d bytes, user2: %d bytes.\n", sizeof(hdr), (int)l1, (int)l2); + close(of); + exit(0); +} + diff --git a/firmwares/minetest/libesphttpd/util/captdns.c b/firmwares/minetest/libesphttpd/util/captdns.c new file mode 100644 index 0000000..729211d --- /dev/null +++ b/firmwares/minetest/libesphttpd/util/captdns.c @@ -0,0 +1,331 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +/* +This is a 'captive portal' DNS server: it basically replies with a fixed IP (in this case: +the one of the SoftAP interface of this ESP module) for any and all DNS queries. This can +be used to send mobile phones, tablets etc which connect to the ESP in AP mode directly to +the internal webserver. +*/ + +#include +#ifdef FREERTOS +#include "espressif/esp_common.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#include "lwip/sockets.h" +#include "lwip/err.h" +static int sockFd; +#endif + + +#define DNS_LEN 512 + +typedef struct __attribute__ ((packed)) { + uint16_t id; + uint8_t flags; + uint8_t rcode; + uint16_t qdcount; + uint16_t ancount; + uint16_t nscount; + uint16_t arcount; +} DnsHeader; + + +typedef struct __attribute__ ((packed)) { + uint8_t len; + uint8_t data; +} DnsLabel; + + +typedef struct __attribute__ ((packed)) { + //before: label + uint16_t type; + uint16_t class; +} DnsQuestionFooter; + + +typedef struct __attribute__ ((packed)) { + //before: label + uint16_t type; + uint16_t class; + uint32_t ttl; + uint16_t rdlength; + //after: rdata +} DnsResourceFooter; + +typedef struct __attribute__ ((packed)) { + uint16_t prio; + uint16_t weight; +} DnsUriHdr; + + +#define FLAG_QR (1<<7) +#define FLAG_AA (1<<2) +#define FLAG_TC (1<<1) +#define FLAG_RD (1<<0) + +#define QTYPE_A 1 +#define QTYPE_NS 2 +#define QTYPE_CNAME 5 +#define QTYPE_SOA 6 +#define QTYPE_WKS 11 +#define QTYPE_PTR 12 +#define QTYPE_HINFO 13 +#define QTYPE_MINFO 14 +#define QTYPE_MX 15 +#define QTYPE_TXT 16 +#define QTYPE_URI 256 + +#define QCLASS_IN 1 +#define QCLASS_ANY 255 +#define QCLASS_URI 256 + + +//Function to put unaligned 16-bit network values +static void ICACHE_FLASH_ATTR setn16(void *pp, int16_t n) { + char *p=pp; + *p++=(n>>8); + *p++=(n&0xff); +} + +//Function to put unaligned 32-bit network values +static void ICACHE_FLASH_ATTR setn32(void *pp, int32_t n) { + char *p=pp; + *p++=(n>>24)&0xff; + *p++=(n>>16)&0xff; + *p++=(n>>8)&0xff; + *p++=(n&0xff); +} + +static uint16_t ICACHE_FLASH_ATTR my_ntohs(uint16_t *in) { + char *p=(char*)in; + return ((p[0]<<8)&0xff00)|(p[1]&0xff); +} + + +//Parses a label into a C-string containing a dotted +//Returns pointer to start of next fields in packet +static char* ICACHE_FLASH_ATTR labelToStr(char *packet, char *labelPtr, int packetSz, char *res, int resMaxLen) { + int i, j, k; + char *endPtr=NULL; + i=0; + do { + if ((*labelPtr&0xC0)==0) { + j=*labelPtr++; //skip past length + //Add separator period if there already is data in res + if (ipacketSz) return NULL; + if (ipacketSz) return NULL; + labelPtr=&packet[offset]; + } + //check for out-of-bound-ness + if ((labelPtr-packet)>packetSz) return NULL; + } while (*labelPtr!=0); + res[i]=0; //zero-terminate + if (endPtr==NULL) endPtr=labelPtr+1; + return endPtr; +} + + +//Converts a dotted hostname to the weird label form dns uses. +static char ICACHE_FLASH_ATTR *strToLabel(char *str, char *label, int maxLen) { + char *len=label; //ptr to len byte + char *p=label+1; //ptr to next label byte to be written + while (1) { + if (*str=='.' || *str==0) { + *len=((p-len)-1); //write len of label bit + len=p; //pos of len for next part + p++; //data ptr is one past len + if (*str==0) break; //done + str++; + } else { + *p++=*str++; //copy byte +// if ((p-label)>maxLen) return NULL; //check out of bounds + } + } + *len=0; + return p; //ptr to first free byte in resp +} + + +//Receive a DNS packet and maybe send a response back +#ifndef FREERTOS +static void ICACHE_FLASH_ATTR captdnsRecv(void* arg, char *pusrdata, unsigned short length) { + struct espconn *conn=(struct espconn *)arg; +#else +static void ICACHE_FLASH_ATTR captdnsRecv(struct sockaddr_in *premote_addr, char *pusrdata, unsigned short length) { +#endif + char buff[DNS_LEN]; + char reply[DNS_LEN]; + int i; + char *rend=&reply[length]; + char *p=pusrdata; + DnsHeader *hdr=(DnsHeader*)p; + DnsHeader *rhdr=(DnsHeader*)&reply[0]; + p+=sizeof(DnsHeader); +// httpd_printf("DNS packet: id 0x%X flags 0x%X rcode 0x%X qcnt %d ancnt %d nscount %d arcount %d len %d\n", +// my_ntohs(&hdr->id), hdr->flags, hdr->rcode, my_ntohs(&hdr->qdcount), my_ntohs(&hdr->ancount), my_ntohs(&hdr->nscount), my_ntohs(&hdr->arcount), length); + //Some sanity checks: + if (length>DNS_LEN) return; //Packet is longer than DNS implementation allows + if (lengthancount || hdr->nscount || hdr->arcount) return; //this is a reply, don't know what to do with it + if (hdr->flags&FLAG_TC) return; //truncated, can't use this + //Reply is basically the request plus the needed data + memcpy(reply, pusrdata, length); + rhdr->flags|=FLAG_QR; + for (i=0; iqdcount); i++) { + //Grab the labels in the q string + p=labelToStr(pusrdata, p, length, buff, sizeof(buff)); + if (p==NULL) return; + DnsQuestionFooter *qf=(DnsQuestionFooter*)p; + p+=sizeof(DnsQuestionFooter); + httpd_printf("DNS: Q (type 0x%X class 0x%X) for %s\n", my_ntohs(&qf->type), my_ntohs(&qf->class), buff); + if (my_ntohs(&qf->type)==QTYPE_A) { + //They want to know the IPv4 address of something. + //Build the response. + rend=strToLabel(buff, rend, sizeof(reply)-(rend-reply)); //Add the label + if (rend==NULL) return; + DnsResourceFooter *rf=(DnsResourceFooter *)rend; + rend+=sizeof(DnsResourceFooter); + setn16(&rf->type, QTYPE_A); + setn16(&rf->class, QCLASS_IN); + setn32(&rf->ttl, 0); + setn16(&rf->rdlength, 4); //IPv4 addr is 4 bytes; + //Grab the current IP of the softap interface + struct ip_info info; + wifi_get_ip_info(SOFTAP_IF, &info); + *rend++=ip4_addr1(&info.ip); + *rend++=ip4_addr2(&info.ip); + *rend++=ip4_addr3(&info.ip); + *rend++=ip4_addr4(&info.ip); + setn16(&rhdr->ancount, my_ntohs(&rhdr->ancount)+1); +// httpd_printf("Added A rec to resp. Resp len is %d\n", (rend-reply)); + } else if (my_ntohs(&qf->type)==QTYPE_NS) { + //Give ns server. Basically can be whatever we want because it'll get resolved to our IP later anyway. + rend=strToLabel(buff, rend, sizeof(reply)-(rend-reply)); //Add the label + DnsResourceFooter *rf=(DnsResourceFooter *)rend; + rend+=sizeof(DnsResourceFooter); + setn16(&rf->type, QTYPE_NS); + setn16(&rf->class, QCLASS_IN); + setn16(&rf->ttl, 0); + setn16(&rf->rdlength, 4); + *rend++=2; + *rend++='n'; + *rend++='s'; + *rend++=0; + setn16(&rhdr->ancount, my_ntohs(&rhdr->ancount)+1); +// httpd_printf("Added NS rec to resp. Resp len is %d\n", (rend-reply)); + } else if (my_ntohs(&qf->type)==QTYPE_URI) { + //Give uri to us + rend=strToLabel(buff, rend, sizeof(reply)-(rend-reply)); //Add the label + DnsResourceFooter *rf=(DnsResourceFooter *)rend; + rend+=sizeof(DnsResourceFooter); + DnsUriHdr *uh=(DnsUriHdr *)rend; + rend+=sizeof(DnsUriHdr); + setn16(&rf->type, QTYPE_URI); + setn16(&rf->class, QCLASS_URI); + setn16(&rf->ttl, 0); + setn16(&rf->rdlength, 4+16); + setn16(&uh->prio, 10); + setn16(&uh->weight, 1); + memcpy(rend, "http://esp.nonet", 16); + rend+=16; + setn16(&rhdr->ancount, my_ntohs(&rhdr->ancount)+1); +// httpd_printf("Added NS rec to resp. Resp len is %d\n", (rend-reply)); + } + } + //Send the response +#ifndef FREERTOS + remot_info *remInfo=NULL; + //Send data to port/ip it came from, not to the ip/port we listen on. + if (espconn_get_connection_info(conn, &remInfo, 0)==ESPCONN_OK) { + conn->proto.udp->remote_port=remInfo->remote_port; + memcpy(conn->proto.udp->remote_ip, remInfo->remote_ip, sizeof(remInfo->remote_ip)); + } + espconn_sendto(conn, (uint8*)reply, rend-reply); +#else + sendto(sockFd,(uint8*)reply, rend-reply, 0, (struct sockaddr *)premote_addr, sizeof(struct sockaddr_in)); +#endif +} + +#ifdef FREERTOS +static void captdnsTask(void *pvParameters) { + struct sockaddr_in server_addr; + int32 ret; + struct sockaddr_in from; + socklen_t fromlen; + struct ip_info ipconfig; + char udp_msg[DNS_LEN]; + + memset(&ipconfig, 0, sizeof(ipconfig)); + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(53); + server_addr.sin_len = sizeof(server_addr); + + do { + sockFd=socket(AF_INET, SOCK_DGRAM, 0); + if (sockFd==-1) { + httpd_printf("captdns_task failed to create sock!\n"); + vTaskDelay(1000/portTICK_RATE_MS); + } + } while (sockFd==-1); + + do { + ret=bind(sockFd, (struct sockaddr *)&server_addr, sizeof(server_addr)); + if (ret!=0) { + httpd_printf("captdns_task failed to bind sock!\n"); + vTaskDelay(1000/portTICK_RATE_MS); + } + } while (ret!=0); + + httpd_printf("CaptDNS inited.\n"); + while(1) { + memset(&from, 0, sizeof(from)); + fromlen=sizeof(struct sockaddr_in); + ret=recvfrom(sockFd, (u8 *)udp_msg, DNS_LEN, 0,(struct sockaddr *)&from,(socklen_t *)&fromlen); + if (ret>0) captdnsRecv(&from,udp_msg,ret); + } + + close(sockFd); + vTaskDelete(NULL); +} + +void captdnsInit(void) { + xTaskCreate(captdnsTask, (const signed char *)"captdns_task", 1200, NULL, 3, NULL); +} + +#else + +void ICACHE_FLASH_ATTR captdnsInit(void) { + static struct espconn conn; + static esp_udp udpconn; + conn.type=ESPCONN_UDP; + conn.proto.udp=&udpconn; + conn.proto.udp->local_port = 53; + espconn_regist_recvcb(&conn, captdnsRecv); + espconn_create(&conn); +} + +#endif \ No newline at end of file diff --git a/firmwares/minetest/libesphttpd/util/cgiflash.c b/firmwares/minetest/libesphttpd/util/cgiflash.c new file mode 100644 index 0000000..4773fd7 --- /dev/null +++ b/firmwares/minetest/libesphttpd/util/cgiflash.c @@ -0,0 +1,323 @@ +/* +Some flash handling cgi routines. Used for reading the existing flash and updating the ESPFS image. +*/ + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +#include +#include "cgiflash.h" +#include "espfs.h" +#include "cgiflash.h" +#include "espfs.h" + +//#include +#include "cgiflash.h" +#include "espfs.h" + +#ifndef UPGRADE_FLAG_FINISH +#define UPGRADE_FLAG_FINISH 0x02 +#endif + +// Check that the header of the firmware blob looks like actual firmware... +static int ICACHE_FLASH_ATTR checkBinHeader(void *buf) { + uint8_t *cd = (uint8_t *)buf; + if (cd[0] != 0xEA) return 0; + if (cd[1] != 4 || cd[2] > 3 || cd[3] > 0x40) return 0; + if (((uint16_t *)buf)[3] != 0x4010) return 0; + if (((uint32_t *)buf)[2] != 0) return 0; + return 1; +} + +static int ICACHE_FLASH_ATTR checkEspfsHeader(void *buf) { + if (memcmp(buf, "ESfs", 4)!=0) return 0; + return 1; +} + + +// Cgi to query which firmware needs to be uploaded next +int ICACHE_FLASH_ATTR cgiGetFirmwareNext(HttpdConnData *connData) { + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + uint8 id = system_upgrade_userbin_check(); + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/plain"); + httpdHeader(connData, "Content-Length", "9"); + httpdEndHeaders(connData); + char *next = id == 1 ? "user1.bin" : "user2.bin"; + httpdSend(connData, next, -1); + httpd_printf("Next firmware: %s (got %d)\n", next, id); + return HTTPD_CGI_DONE; +} + + +//Cgi that reads the SPI flash. Assumes 512KByte flash. +//ToDo: Figure out real flash size somehow? +int ICACHE_FLASH_ATTR cgiReadFlash(HttpdConnData *connData) { + int *pos=(int *)&connData->cgiData; + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + if (*pos==0) { + httpd_printf("Start flash download.\n"); + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "application/bin"); + httpdEndHeaders(connData); + *pos=0x40200000; + return HTTPD_CGI_MORE; + } + //Send 1K of flash per call. We will get called again if we haven't sent 512K yet. + httpdSend(connData, (char*)(*pos), 1024); + *pos+=1024; + if (*pos>=0x40200000+(512*1024)) return HTTPD_CGI_DONE; else return HTTPD_CGI_MORE; +} + + +//Cgi that allows the firmware to be replaced via http POST This takes +//a direct POST from e.g. Curl or a Javascript AJAX call with either the +//firmware given by cgiGetFirmwareNext or an OTA upgrade image. + +//Because we don't have the buffer to allocate an entire sector but will +//have to buffer some data because the post buffer may be misaligned, we +//write SPI data in pages. The page size is a software thing, not +//a hardware one. +#define PAGELEN 64 + +#define FLST_START 0 +#define FLST_WRITE 1 +#define FLST_SKIP 2 +#define FLST_DONE 3 +#define FLST_ERROR 4 + +#define FILETYPE_ESPFS 0 +#define FILETYPE_FLASH 1 +#define FILETYPE_OTA 2 +typedef struct { + int state; + int filetype; + int flashPos; + char pageData[PAGELEN]; + int pagePos; + int address; + int len; + int skip; + char *err; +} UploadState; + +typedef struct __attribute__((packed)) { + char magic[4]; + char tag[28]; + int32_t len1; + int32_t len2; +} OtaHeader; + + +int ICACHE_FLASH_ATTR cgiUploadFirmware(HttpdConnData *connData) { + CgiUploadFlashDef *def=(CgiUploadFlashDef*)connData->cgiArg; + UploadState *state=(UploadState *)connData->cgiData; + int len; + char buff[128]; + + if (connData->conn==NULL) { + //Connection aborted. Clean up. + if (state!=NULL) free(state); + return HTTPD_CGI_DONE; + } + + if (state==NULL) { + //First call. Allocate and initialize state variable. + httpd_printf("Firmware upload cgi start.\n"); + state=malloc(sizeof(UploadState)); + if (state==NULL) { + httpd_printf("Can't allocate firmware upload struct!\n"); + return HTTPD_CGI_DONE; + } + memset(state, 0, sizeof(UploadState)); + state->state=FLST_START; + connData->cgiData=state; + state->err="Premature end"; + } + + char *data=connData->post->buff; + int dataLen=connData->post->buffLen; + + while (dataLen!=0) { + if (state->state==FLST_START) { + //First call. Assume the header of whatever we're uploading already is in the POST buffer. + if (def->type==CGIFLASH_TYPE_FW && memcmp(data, "EHUG", 4)==0) { + //Type is combined flash1/flash2 file + OtaHeader *h=(OtaHeader*)data; + strncpy(buff, h->tag, 27); + buff[27]=0; + if (strcmp(buff, def->tagName)!=0) { + httpd_printf("OTA tag mismatch! Current=`%s` uploaded=`%s`.\n", + def->tagName, buff); + len=httpdFindArg(connData->getArgs, "force", buff, sizeof(buff)); + if (len!=-1 && atoi(buff)) { + httpd_printf("Forcing firmware flash.\n"); + } else { + state->err="Firmware not intended for this device!\n"; + state->state=FLST_ERROR; + } + } + if (state->state!=FLST_ERROR && connData->post->len > def->fwSize*2+sizeof(OtaHeader)) { + state->err="Firmware image too large"; + state->state=FLST_ERROR; + } + if (state->state!=FLST_ERROR) { + //Flash header seems okay. + dataLen-=sizeof(OtaHeader); //skip header when parsing data + data+=sizeof(OtaHeader); + if (system_upgrade_userbin_check()==1) { + httpd_printf("Flashing user1.bin from ota image\n"); + state->len=h->len1; + state->skip=h->len2; + state->state=FLST_WRITE; + state->address=def->fw1Pos; + } else { + httpd_printf("Flashing user2.bin from ota image\n"); + state->len=h->len2; + state->skip=h->len1; + state->state=FLST_SKIP; + state->address=def->fw2Pos; + } + } + } else if (def->type==CGIFLASH_TYPE_FW && checkBinHeader(connData->post->buff)) { + if (connData->post->len > def->fwSize) { + state->err="Firmware image too large"; + state->state=FLST_ERROR; + } else { + state->len=connData->post->len; + state->address=def->fw1Pos; + state->state=FLST_WRITE; + } + } else if (def->type==CGIFLASH_TYPE_ESPFS && checkEspfsHeader(connData->post->buff)) { + if (connData->post->len > def->fwSize) { + state->err="Firmware image too large"; + state->state=FLST_ERROR; + } else { + state->len=connData->post->len; + state->address=def->fw1Pos; + state->state=FLST_WRITE; + } + } else { + state->err="Invalid flash image type!"; + state->state=FLST_ERROR; + httpd_printf("Did not recognize flash image type!\n"); + } + } else if (state->state==FLST_SKIP) { + //Skip bytes without doing anything with them + if (state->skip>dataLen) { + //Skip entire buffer + state->skip-=dataLen; + dataLen=0; + } else { + //Only skip part of buffer + dataLen-=state->skip; + data+=state->skip; + state->skip=0; + if (state->len) state->state=FLST_WRITE; else state->state=FLST_DONE; + } + } else if (state->state==FLST_WRITE) { + //Copy bytes to page buffer, and if page buffer is full, flash the data. + //First, calculate the amount of bytes we need to finish the page buffer. + int lenLeft=PAGELEN-state->pagePos; + if (state->lenlen; //last buffer can be a cut-off one + //See if we need to write the page. + if (dataLenpageData[state->pagePos], data, dataLen); + state->pagePos+=dataLen; + state->len-=dataLen; + dataLen=0; + } else { + //Finish page; take data we need from post buffer + memcpy(&state->pageData[state->pagePos], data, lenLeft); + data+=lenLeft; + dataLen-=lenLeft; + state->pagePos+=lenLeft; + state->len-=lenLeft; + //Erase sector, if needed + if ((state->address&(SPI_FLASH_SEC_SIZE-1))==0) { + spi_flash_erase_sector(state->address/SPI_FLASH_SEC_SIZE); + } + //Write page + //httpd_printf("Writing %d bytes of data to SPI pos 0x%x...\n", state->pagePos, state->address); + spi_flash_write(state->address, (uint32 *)state->pageData, state->pagePos); + state->address+=PAGELEN; + state->pagePos=0; + if (state->len==0) { + //Done. + if (state->skip) state->state=FLST_SKIP; else state->state=FLST_DONE; + } + } + } else if (state->state==FLST_DONE) { + httpd_printf("Huh? %d bogus bytes received after data received.\n", dataLen); + //Ignore those bytes. + dataLen=0; + } else if (state->state==FLST_ERROR) { + //Just eat up any bytes we receive. + dataLen=0; + } + } + + if (connData->post->len==connData->post->received) { + //We're done! Format a response. + httpd_printf("Upload done. Sending response.\n"); + httpdStartResponse(connData, state->state==FLST_ERROR?400:200); + httpdHeader(connData, "Content-Type", "text/plain"); + httpdEndHeaders(connData); + if (state->state!=FLST_DONE) { + httpdSend(connData, "Firmware image error:", -1); + httpdSend(connData, state->err, -1); + httpdSend(connData, "\n", -1); + } + free(state); + return HTTPD_CGI_DONE; + } + + return HTTPD_CGI_MORE; +} + + + +static os_timer_t resetTimer; + +static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { + system_upgrade_flag_set(UPGRADE_FLAG_FINISH); + system_upgrade_reboot(); +} + +// Handle request to reboot into the new firmware +int ICACHE_FLASH_ATTR cgiRebootFirmware(HttpdConnData *connData) { + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + // TODO: sanity-check that the 'next' partition actually contains something that looks like + // valid firmware + + //Do reboot in a timer callback so we still have time to send the response. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 200, 0); + + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/plain"); + httpdEndHeaders(connData); + httpdSend(connData, "Rebooting...", -1); + return HTTPD_CGI_DONE; +} + diff --git a/firmwares/minetest/libesphttpd/util/cgiwebsocket.c b/firmwares/minetest/libesphttpd/util/cgiwebsocket.c new file mode 100644 index 0000000..adf6c18 --- /dev/null +++ b/firmwares/minetest/libesphttpd/util/cgiwebsocket.c @@ -0,0 +1,354 @@ +/* +Websocket support for esphttpd. Inspired by https://github.com/dangrie158/ESP-8266-WebSocket +*/ + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +#include +#include "httpd.h" +#include "sha1.h" +#include "base64.h" +#include "cgiwebsocket.h" + +#define WS_KEY_IDENTIFIER "Sec-WebSocket-Key: " +#define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" + +/* from IEEE RFC6455 sec 5.2 + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-------+-+-------------+-------------------------------+ + |F|R|R|R| opcode|M| Payload len | Extended payload length | + |I|S|S|S| (4) |A| (7) | (16/64) | + |N|V|V|V| |S| | (if payload len==126/127) | + | |1|2|3| |K| | | + +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + | Extended payload length continued, if payload len == 127 | + + - - - - - - - - - - - - - - - +-------------------------------+ + | |Masking-key, if MASK set to 1 | + +-------------------------------+-------------------------------+ + | Masking-key (continued) | Payload Data | + +-------------------------------- - - - - - - - - - - - - - - - + + : Payload Data continued ... : + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + | Payload Data continued ... | + +---------------------------------------------------------------+ +*/ + +#define FLAG_FIN (1 << 7) + +#define OPCODE_CONTINUE 0x0 +#define OPCODE_TEXT 0x1 +#define OPCODE_BINARY 0x2 +#define OPCODE_CLOSE 0x8 +#define OPCODE_PING 0x9 +#define OPCODE_PONG 0xA + +#define FLAGS_MASK ((uint8_t)0xF0) +#define OPCODE_MASK ((uint8_t)0x0F) +#define IS_MASKED ((uint8_t)(1<<7)) +#define PAYLOAD_MASK ((uint8_t)0x7F) + +typedef struct WebsockFrame WebsockFrame; + +#define ST_FLAGS 0 +#define ST_LEN0 1 +#define ST_LEN1 2 +#define ST_LEN2 3 +//... +#define ST_LEN8 9 +#define ST_MASK1 10 +#define ST_MASK4 13 +#define ST_PAYLOAD 14 + +struct WebsockFrame { + uint8_t flags; + uint8_t len8; + uint64_t len; + uint8_t mask[4]; +}; + +struct WebsockPriv { + struct WebsockFrame fr; + uint8_t maskCtr; + uint8 frameCont; + uint8 closedHere; + int wsStatus; + Websock *next; //in linked list +}; + +static Websock *llStart=NULL; + +static int ICACHE_FLASH_ATTR sendFrameHead(Websock *ws, int opcode, int len) { + char buf[14]; + int i=0; + buf[i++]=opcode; + if (len>65535) { + buf[i++]=127; + buf[i++]=0; buf[i++]=0; buf[i++]=0; buf[i++]=0; + buf[i++]=len>>24; + buf[i++]=len>>16; + buf[i++]=len>>8; + buf[i++]=len; + } else if (len>125) { + buf[i++]=126; + buf[i++]=len>>8; + buf[i++]=len; + } else { + buf[i++]=len; + } + httpd_printf("WS: Sent frame head for payload of %d bytes.\n", len); + return httpdSend(ws->conn, buf, i); +} + +int ICACHE_FLASH_ATTR cgiWebsocketSend(Websock *ws, char *data, int len, int flags) { + int r=0; + int fl=0; + if (flags&WEBSOCK_FLAG_BIN) fl=OPCODE_BINARY; else fl=OPCODE_TEXT; + if (!(flags&WEBSOCK_FLAG_CONT)) fl|=FLAG_FIN; + sendFrameHead(ws, fl, len); + if (len!=0) r=httpdSend(ws->conn, data, len); + httpdFlushSendBuffer(ws->conn); + return r; +} + +//Broadcast data to all websockets at a specific url. Returns the amount of connections sent to. +int ICACHE_FLASH_ATTR cgiWebsockBroadcast(char *resource, char *data, int len, int flags) { +//This is majorly broken (and actually, always, it just tended to work because the circumstances +//were juuuust right). Because the socket is used outside of the httpd send/receive context, it +//will not have an associated send buffer. This means httpdSend will write to a dangling pointer! +//Disabled for now. If you really need this, open an issue on github or otherwise poke me and I'll +//see what I can do. +/* + Websock *lw=llStart; + int ret=0; + while (lw!=NULL) { + if (strcmp(lw->conn->url, resource)==0) { + cgiWebsocketSend(lw, data, len, flags); + ret++; + } + lw=lw->priv->next; + } + return ret; +*/ + return 0; +} + + +void ICACHE_FLASH_ATTR cgiWebsocketClose(Websock *ws, int reason) { + char rs[2]={reason>>8, reason&0xff}; + sendFrameHead(ws, FLAG_FIN|OPCODE_CLOSE, 2); + httpdSend(ws->conn, rs, 2); + ws->priv->closedHere=1; + httpdFlushSendBuffer(ws->conn); +} + + +static void ICACHE_FLASH_ATTR websockFree(Websock *ws) { + httpd_printf("Ws: Free\n"); + if (ws->closeCb) ws->closeCb(ws); + //Clean up linked list + if (llStart==ws) { + llStart=ws->priv->next; + } else if (llStart) { + Websock *lws=llStart; + //Find ws that links to this one. + while (lws!=NULL && lws->priv->next!=ws) lws=lws->priv->next; + if (lws!=NULL) lws->priv->next=ws->priv->next; + } + if (ws->priv) free(ws->priv); +} + +int ICACHE_FLASH_ATTR cgiWebSocketRecv(HttpdConnData *connData, char *data, int len) { + int i, j, sl; + int r=HTTPD_CGI_MORE; + int wasHeaderByte; + Websock *ws=(Websock*)connData->cgiData; + for (i=0; ipriv->wsStatus, data[i]); + wasHeaderByte=1; + if (ws->priv->wsStatus==ST_FLAGS) { + ws->priv->maskCtr=0; + ws->priv->frameCont=0; + ws->priv->fr.flags=(uint8_t)data[i]; + ws->priv->wsStatus=ST_LEN0; + } else if (ws->priv->wsStatus==ST_LEN0) { + ws->priv->fr.len8=(uint8_t)data[i]; + if ((ws->priv->fr.len8&127)>=126) { + ws->priv->fr.len=0; + ws->priv->wsStatus=ST_LEN1; + } else { + ws->priv->fr.len=ws->priv->fr.len8&127; + ws->priv->wsStatus=(ws->priv->fr.len8&IS_MASKED)?ST_MASK1:ST_PAYLOAD; + } + } else if (ws->priv->wsStatus<=ST_LEN8) { + ws->priv->fr.len=(ws->priv->fr.len<<8)|data[i]; + if (((ws->priv->fr.len8&127)==126 && ws->priv->wsStatus==ST_LEN2) || ws->priv->wsStatus==ST_LEN8) { + ws->priv->wsStatus=(ws->priv->fr.len8&IS_MASKED)?ST_MASK1:ST_PAYLOAD; + } else { + ws->priv->wsStatus++; + } + } else if (ws->priv->wsStatus<=ST_MASK4) { + ws->priv->fr.mask[ws->priv->wsStatus-ST_MASK1]=data[i]; + ws->priv->wsStatus++; + } else { + //Was a payload byte. + wasHeaderByte=0; + } + + if (ws->priv->wsStatus==ST_PAYLOAD && wasHeaderByte) { + //We finished parsing the header, but i still is on the last header byte. Move one forward so + //the payload code works as usual. + i++; + } + //Also finish parsing frame if we haven't received any payload bytes yet, but the length of the frame + //is zero. + if (ws->priv->wsStatus==ST_PAYLOAD) { + //Okay, header is in; this is a data byte. We're going to process all the data bytes we have + //received here at the same time; no more byte iterations till the end of this frame. + //First, unmask the data + sl=len-i; + httpd_printf("Ws: Frame payload. wasHeaderByte %d fr.len %d sl %d cmd 0x%x\n", wasHeaderByte, (int)ws->priv->fr.len, (int)sl, ws->priv->fr.flags); + if (sl > ws->priv->fr.len) sl=ws->priv->fr.len; + for (j=0; jpriv->fr.mask[(ws->priv->maskCtr++)&3]); + +// httpd_printf("Unmasked: "); +// for (j=0; jpriv->fr.flags&OPCODE_MASK)==OPCODE_PING) { + if (ws->priv->fr.len>125) { + if (!ws->priv->frameCont) cgiWebsocketClose(ws, 1002); + r=HTTPD_CGI_DONE; + break; + } else { + if (!ws->priv->frameCont) sendFrameHead(ws, OPCODE_PONG|FLAG_FIN, ws->priv->fr.len); + if (sl>0) httpdSend(ws->conn, data+i, sl); + } + } else if ((ws->priv->fr.flags&OPCODE_MASK)==OPCODE_TEXT || + (ws->priv->fr.flags&OPCODE_MASK)==OPCODE_BINARY || + (ws->priv->fr.flags&OPCODE_MASK)==OPCODE_CONTINUE) { + if (sl>ws->priv->fr.len) sl=ws->priv->fr.len; + if (!(ws->priv->fr.len8&IS_MASKED)) { + //We're a server; client should send us masked packets. + cgiWebsocketClose(ws, 1002); + r=HTTPD_CGI_DONE; + break; + } else { + int flags=0; + if ((ws->priv->fr.flags&OPCODE_MASK)==OPCODE_BINARY) flags|=WEBSOCK_FLAG_BIN; + if ((ws->priv->fr.flags&FLAG_FIN)==0) flags|=WEBSOCK_FLAG_CONT; + if (ws->recvCb) ws->recvCb(ws, data+i, sl, flags); + } + } else if ((ws->priv->fr.flags&OPCODE_MASK)==OPCODE_CLOSE) { + httpd_printf("WS: Got close frame\n"); + if (!ws->priv->closedHere) { + httpd_printf("WS: Sending response close frame\n"); + cgiWebsocketClose(ws, ((data[i]<<8)&0xff00)+(data[i+1]&0xff)); + } + r=HTTPD_CGI_DONE; + break; + } else { + if (!ws->priv->frameCont) httpd_printf("WS: Unknown opcode 0x%X\n", ws->priv->fr.flags&OPCODE_MASK); + } + i+=sl-1; + ws->priv->fr.len-=sl; + if (ws->priv->fr.len==0) { + ws->priv->wsStatus=ST_FLAGS; //go receive next frame + } else { + ws->priv->frameCont=1; //next payload is continuation of this frame. + } + } + } + if (r==HTTPD_CGI_DONE) { + //We're going to tell the main webserver we're done. The webserver expects us to clean up by ourselves + //we're chosing to be done. Do so. + websockFree(ws); + free(connData->cgiData); + connData->cgiData=NULL; + } + return r; +} + +//Websocket 'cgi' implementation +int ICACHE_FLASH_ATTR cgiWebsocket(HttpdConnData *connData) { + char buff[256]; + int i; + sha1nfo s; + if (connData->conn==NULL) { + //Connection aborted. Clean up. + httpd_printf("WS: Cleanup\n"); + if (connData->cgiData) { + Websock *ws=(Websock*)connData->cgiData; + websockFree(ws); + free(connData->cgiData); + connData->cgiData=NULL; + } + return HTTPD_CGI_DONE; + } + + if (connData->cgiData==NULL) { +// httpd_printf("WS: First call\n"); + //First call here. Check if client headers are OK, send server header. + i=httpdGetHeader(connData, "Upgrade", buff, sizeof(buff)-1); + httpd_printf("WS: Upgrade: %s\n", buff); + if (i && strcasecmp(buff, "websocket")==0) { + i=httpdGetHeader(connData, "Sec-WebSocket-Key", buff, sizeof(buff)-1); + if (i) { +// httpd_printf("WS: Key: %s\n", buff); + //Seems like a WebSocket connection. + // Alloc structs + connData->cgiData=malloc(sizeof(Websock)); + memset(connData->cgiData, 0, sizeof(Websock)); + Websock *ws=(Websock*)connData->cgiData; + ws->priv=malloc(sizeof(WebsockPriv)); + memset(ws->priv, 0, sizeof(WebsockPriv)); + ws->conn=connData; + //Reply with the right headers. + strcat(buff, WS_GUID); + sha1_init(&s); + sha1_write(&s, buff, strlen(buff)); + httpdDisableTransferEncoding(connData); + httpdStartResponse(connData, 101); + httpdHeader(connData, "Upgrade", "websocket"); + httpdHeader(connData, "Connection", "upgrade"); + base64_encode(20, sha1_result(&s), sizeof(buff), buff); + httpdHeader(connData, "Sec-WebSocket-Accept", buff); + httpdEndHeaders(connData); + //Set data receive handler + connData->recvHdl=cgiWebSocketRecv; + //Inform CGI function we have a connection + WsConnectedCb connCb=connData->cgiArg; + connCb(ws); + //Insert ws into linked list + if (llStart==NULL) { + llStart=ws; + } else { + Websock *lw=llStart; + while (lw->priv->next) lw=lw->priv->next; + lw->priv->next=ws; + } + return HTTPD_CGI_MORE; + } + } + //No valid websocket connection + httpdStartResponse(connData, 500); + httpdEndHeaders(connData); + return HTTPD_CGI_DONE; + } + + //Sending is done. Call the sent callback if we have one. + Websock *ws=(Websock*)connData->cgiData; + if (ws && ws->sentCb) ws->sentCb(ws); + + return HTTPD_CGI_MORE; +} + diff --git a/firmwares/minetest/libesphttpd/util/cgiwifi.c b/firmwares/minetest/libesphttpd/util/cgiwifi.c new file mode 100644 index 0000000..4e06432 --- /dev/null +++ b/firmwares/minetest/libesphttpd/util/cgiwifi.c @@ -0,0 +1,314 @@ +/* +Cgi/template routines for the /wifi url. +*/ + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Jeroen Domburg wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + + +#include +#include "cgiwifi.h" + +//Enable this to disallow any changes in AP settings +//#define DEMO_MODE + +//WiFi access point data +typedef struct { + char ssid[32]; + char bssid[8]; + int channel; + char rssi; + char enc; +} ApData; + +//Scan result +typedef struct { + char scanInProgress; //if 1, don't access the underlying stuff from the webpage. + ApData **apData; + int noAps; +} ScanResultData; + +//Static scan status storage. +static ScanResultData cgiWifiAps; + +#define CONNTRY_IDLE 0 +#define CONNTRY_WORKING 1 +#define CONNTRY_SUCCESS 2 +#define CONNTRY_FAIL 3 +//Connection result var +static int connTryStatus=CONNTRY_IDLE; +static os_timer_t resetTimer; + +//Callback the code calls when a wlan ap scan is done. Basically stores the result in +//the cgiWifiAps struct. +void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { + int n; + struct bss_info *bss_link = (struct bss_info *)arg; + httpd_printf("wifiScanDoneCb %d\n", status); + if (status!=OK) { + cgiWifiAps.scanInProgress=0; + return; + } + + //Clear prev ap data if needed. + if (cgiWifiAps.apData!=NULL) { + for (n=0; nnext.stqe_next; + n++; + } + //Allocate memory for access point data + cgiWifiAps.apData=(ApData **)malloc(sizeof(ApData *)*n); + cgiWifiAps.noAps=n; + httpd_printf("Scan done: found %d APs\n", n); + + //Copy access point data to the static struct + n=0; + bss_link = (struct bss_info *)arg; + while (bss_link != NULL) { + if (n>=cgiWifiAps.noAps) { + //This means the bss_link changed under our nose. Shouldn't happen! + //Break because otherwise we will write in unallocated memory. + httpd_printf("Huh? I have more than the allocated %d aps!\n", cgiWifiAps.noAps); + break; + } + //Save the ap data. + cgiWifiAps.apData[n]=(ApData *)malloc(sizeof(ApData)); + cgiWifiAps.apData[n]->rssi=bss_link->rssi; + cgiWifiAps.apData[n]->channel=bss_link->channel; + cgiWifiAps.apData[n]->enc=bss_link->authmode; + strncpy(cgiWifiAps.apData[n]->ssid, (char*)bss_link->ssid, 32); + strncpy(cgiWifiAps.apData[n]->bssid, (char*)bss_link->bssid, 6); + + bss_link = bss_link->next.stqe_next; + n++; + } + //We're done. + cgiWifiAps.scanInProgress=0; +} + + +//Routine to start a WiFi access point scan. +static void ICACHE_FLASH_ATTR wifiStartScan() { +// int x; + if (cgiWifiAps.scanInProgress) return; + cgiWifiAps.scanInProgress=1; + wifi_station_scan(NULL, wifiScanDoneCb); +} + +//This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a +//scan for access points and if available will return the result of an earlier scan. +//The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. +int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { + int pos=(int)connData->cgiData; + int len; + char buff[1024]; + + if (!cgiWifiAps.scanInProgress && pos!=0) { + //Fill in json code for an access point + if (pos-1ssid, MAC2STR(cgiWifiAps.apData[pos-1]->bssid), cgiWifiAps.apData[pos-1]->rssi, + cgiWifiAps.apData[pos-1]->enc, cgiWifiAps.apData[pos-1]->channel, (pos-1==cgiWifiAps.noAps-1)?"":","); + httpdSend(connData, buff, len); + } + pos++; + if ((pos-1)>=cgiWifiAps.noAps) { + len=sprintf(buff, "]\n}\n}\n"); + httpdSend(connData, buff, len); + //Also start a new scan. + wifiStartScan(); + return HTTPD_CGI_DONE; + } else { + connData->cgiData=(void*)pos; + return HTTPD_CGI_MORE; + } + } + + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/json"); + httpdEndHeaders(connData); + + if (cgiWifiAps.scanInProgress==1) { + //We're still scanning. Tell Javascript code that. + len=sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; + } else { + //We have a scan result. Pass it on. + len=sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n"); + httpdSend(connData, buff, len); + if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0; + connData->cgiData=(void *)1; + return HTTPD_CGI_MORE; + } +} + +//Temp store for new ap info. +static struct station_config stconf; + +//This routine is ran some time after a connection attempt to an access point. If +//the connect succeeds, this gets the module in STA-only mode. +static void ICACHE_FLASH_ATTR resetTimerCb(void *arg) { + int x=wifi_station_get_connect_status(); + if (x==STATION_GOT_IP) { + //Go to STA mode. This needs a reset, so do that. + httpd_printf("Got IP. Going into STA mode..\n"); + wifi_set_opmode(1); + system_restart(); + } else { + connTryStatus=CONNTRY_FAIL; + httpd_printf("Connect fail. Not going into STA-only mode.\n"); + //Maybe also pass this through on the webpage? + } +} + + + +//Actually connect to a station. This routine is timed because I had problems +//with immediate connections earlier. It probably was something else that caused it, +//but I can't be arsed to put the code back :P +static void ICACHE_FLASH_ATTR reassTimerCb(void *arg) { + int x; + httpd_printf("Try to connect to AP....\n"); + wifi_station_disconnect(); + wifi_station_set_config(&stconf); + wifi_station_connect(); + x=wifi_get_opmode(); + connTryStatus=CONNTRY_WORKING; + if (x!=1) { + //Schedule disconnect/connect + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 15000, 0); //time out after 15 secs of trying to connect + } +} + + +//This cgi uses the routines above to connect to a specific access point with the +//given ESSID using the given password. +int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { + char essid[128]; + char passwd[128]; + static os_timer_t reassTimer; + + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + httpdFindArg(connData->post->buff, "essid", essid, sizeof(essid)); + httpdFindArg(connData->post->buff, "passwd", passwd, sizeof(passwd)); + + strncpy((char*)stconf.ssid, essid, 32); + strncpy((char*)stconf.password, passwd, 64); + httpd_printf("Try to connect to AP %s pw %s\n", essid, passwd); + + //Schedule disconnect/connect + os_timer_disarm(&reassTimer); + os_timer_setfn(&reassTimer, reassTimerCb, NULL); +//Set to 0 if you want to disable the actual reconnecting bit +#ifdef DEMO_MODE + httpdRedirect(connData, "/wifi"); +#else + os_timer_arm(&reassTimer, 500, 0); + httpdRedirect(connData, "connecting.html"); +#endif + return HTTPD_CGI_DONE; +} + +//This cgi uses the routines above to connect to a specific access point with the +//given ESSID using the given password. +int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { + int len; + char buff[1024]; + + if (connData->conn==NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + + len=httpdFindArg(connData->getArgs, "mode", buff, sizeof(buff)); + if (len!=0) { + httpd_printf("cgiWifiSetMode: %s\n", buff); +#ifndef DEMO_MODE + wifi_set_opmode(atoi(buff)); + system_restart(); +#endif + } + httpdRedirect(connData, "/wifi"); + return HTTPD_CGI_DONE; +} + +int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { + char buff[1024]; + int len; + struct ip_info info; + int st=wifi_station_get_connect_status(); + httpdStartResponse(connData, 200); + httpdHeader(connData, "Content-Type", "text/json"); + httpdEndHeaders(connData); + if (connTryStatus==CONNTRY_IDLE) { + len=sprintf(buff, "{\n \"status\": \"idle\"\n }\n"); + } else if (connTryStatus==CONNTRY_WORKING || connTryStatus==CONNTRY_SUCCESS) { + if (st==STATION_GOT_IP) { + wifi_get_ip_info(0, &info); + len=sprintf(buff, "{\n \"status\": \"success\",\n \"ip\": \"%d.%d.%d.%d\" }\n", + (info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff, + (info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff); + //Reset into AP-only mode sooner. + os_timer_disarm(&resetTimer); + os_timer_setfn(&resetTimer, resetTimerCb, NULL); + os_timer_arm(&resetTimer, 1000, 0); + } else { + len=sprintf(buff, "{\n \"status\": \"working\"\n }\n"); + } + } else { + len=sprintf(buff, "{\n \"status\": \"fail\"\n }\n"); + } + + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; +} + +//Template code for the WLAN page. +int ICACHE_FLASH_ATTR tplWlan(HttpdConnData *connData, char *token, void **arg) { + char buff[1024]; + int x; + static struct station_config stconf; + if (token==NULL) return HTTPD_CGI_DONE; + wifi_station_get_config(&stconf); + + strcpy(buff, "Unknown"); + if (strcmp(token, "WiFiMode")==0) { + x=wifi_get_opmode(); + if (x==1) strcpy(buff, "Client"); + if (x==2) strcpy(buff, "SoftAP"); + if (x==3) strcpy(buff, "STA+AP"); + } else if (strcmp(token, "currSsid")==0) { + strcpy(buff, (char*)stconf.ssid); + } else if (strcmp(token, "WiFiPasswd")==0) { + strcpy(buff, (char*)stconf.password); + } else if (strcmp(token, "WiFiapwarn")==0) { + x=wifi_get_opmode(); + if (x==2) { + strcpy(buff, "Can't scan in this mode. Click here to go to STA+AP mode."); + } else { + strcpy(buff, "Click here to go to standalone AP mode."); + } + } + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; +} + diff --git a/firmwares/minetest/libesphttpd/webpages.espfs.ld b/firmwares/minetest/libesphttpd/webpages.espfs.ld new file mode 100644 index 0000000..0968d4b --- /dev/null +++ b/firmwares/minetest/libesphttpd/webpages.espfs.ld @@ -0,0 +1,12 @@ +OUTPUT_FORMAT("elf32-xtensa-le") + + +SECTIONS +{ + .irom0.literal : ALIGN(4) SUBALIGN(4) { + webpages_espfs_start = .; + *(*) + webpages_espfs_end = .; + webpages_espfs_size = webpages_espfs_end - webpages_espfs_start; + } +} \ No newline at end of file diff --git a/firmwares/minetest/src/buttons.c b/firmwares/minetest/src/buttons.c new file mode 100644 index 0000000..4705d31 --- /dev/null +++ b/firmwares/minetest/src/buttons.c @@ -0,0 +1,27 @@ +// System +#include +#include + +// Project +#include "buttons.h" + +void ICACHE_FLASH_ATTR buttons_init() { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5); + gpio_output_set(0, 0, 0, BIT4); + gpio_output_set(0, 0, 0, BIT5); + PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO4_U); + PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO5_U); +} + +bool ICACHE_FLASH_ATTR button_get(button_t btn) { + if (btn == BUTTON_UP) { + return !GPIO_INPUT_GET(4); + } else if (btn == BUTTON_DOWN) { + return !GPIO_INPUT_GET(5); + } else if (btn == BUTTON_CENTER) { + return !GPIO_INPUT_GET(4) && !GPIO_INPUT_GET(5); + } + + return false; +} diff --git a/firmwares/minetest/src/buttons.h b/firmwares/minetest/src/buttons.h new file mode 100644 index 0000000..46ca215 --- /dev/null +++ b/firmwares/minetest/src/buttons.h @@ -0,0 +1,14 @@ +#ifndef _BUTTONS_H +#define _BUTTONS_H + +enum ButtonIdentifier { + BUTTON_UP, + BUTTON_DOWN, + BUTTON_CENTER +}; +typedef enum ButtonIdentifier button_t; + +void buttons_init(); +bool buttons_get(button_t btn); + +#endif diff --git a/firmwares/minetest/src/font.h b/firmwares/minetest/src/font.h new file mode 100644 index 0000000..fe9d9ca --- /dev/null +++ b/firmwares/minetest/src/font.h @@ -0,0 +1,199 @@ +#ifndef _FONT_H +#define _FONT_H + +const unsigned char font_small[][6] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space + { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! + { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // " + { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # + { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ + { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // % + { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // & + { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( + { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) + { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * + { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // , + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // - + { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // . + { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // / + { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 + { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 + { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 + { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 + { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 + { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 + { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 + { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 + { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 + { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 + { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; + { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // < + { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // = + { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // > + { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? + { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ + { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C + { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F + { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G + { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H + { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I + { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J + { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K + { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L + { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M + { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P + { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q + { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R + { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S + { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T + { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U + { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V + { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W + { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X + { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y + { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z + { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ + { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // backslash + { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] + { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ + { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ + { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' + { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a + { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c + { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d + { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e + { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f + { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g + { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h + { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i + { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j + { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k + { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l + { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o + { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p + { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r + { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s + { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t + { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u + { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v + { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w + { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x + { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y + { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z + { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }, // horizontal lines +}; + +const unsigned char font_large[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space + { 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00 }, // ! + { 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // " + { 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00 }, // # + { 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00 }, // $ + { 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00 }, // % + { 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10 }, // & + { 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00 }, // ( + { 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00 }, // ) + { 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00 }, // * + { 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00 }, // + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 }, // , + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // - + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 }, // . + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00 }, // / + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // 0 + { 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // 1 + { 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00 }, // 2 + { 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 3 + { 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00 }, // 4 + { 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 5 + { 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 6 + { 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 }, // 7 + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00 }, // 8 + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00 }, // 9 + { 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00 }, // ; + { 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, // < + { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00 }, // = + { 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 }, // > + { 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00 }, // ? + { 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00 }, // @ + { 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20 }, // A + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // B + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00 }, // C + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // D + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00 }, // E + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00 }, // F + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00 }, // G + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20 }, // H + { 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // I + { 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00 }, // J + { 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00 }, // K + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00 }, // L + { 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00 }, // M + { 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00 }, // N + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // O + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00 }, // P + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00 }, // Q + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20 }, // R + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00 }, // S + { 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, // T + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, // U + { 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00 }, // V + { 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00 }, // W + { 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20 }, // X + { 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, // Y + { 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00 }, // Z + { 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00 }, // [ + { 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00 }, // backslash + { 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00 }, // ] + { 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ^ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, // _ + { 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ` + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20 }, // a + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // b + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00 }, // c + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20 }, // d + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00 }, // e + { 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // f + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00 }, // g + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, // h + { 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // i + { 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00 }, // j + { 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00 }, // k + { 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // l + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F }, // m + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, // n + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, // o + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // p + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80 }, // q + { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00 }, // r + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00 }, // s + { 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00 }, // t + { 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20 }, // u + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00 }, // v + { 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00 }, // w + { 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00 }, // x + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00 }, // y + { 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00 }, // z + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40 }, // { + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, // | + { 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00 }, // } + { 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ~ +}; + +#endif diff --git a/firmwares/minetest/src/httpclient.c b/firmwares/minetest/src/httpclient.c new file mode 100644 index 0000000..96a48c9 --- /dev/null +++ b/firmwares/minetest/src/httpclient.c @@ -0,0 +1,483 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Martin d'Allens wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +// FIXME: sprintf->snprintf everywhere. +// FIXME: support null characters in responses. + +#include "osapi.h" +#include "user_interface.h" +#include "espconn.h" +#include "mem.h" +#include "limits.h" +#include "httpclient.h" + + +// Debug output. +#if 0 +#define PRINTF(...) os_printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +// Internal state. +typedef struct { + char * path; + int port; + char * post_data; + char * headers; + char * hostname; + char * buffer; + int buffer_size; + http_callback user_callback; +} request_args; + +static char * ICACHE_FLASH_ATTR esp_strdup(const char * str) +{ + if (str == NULL) { + return NULL; + } + char * new_str = (char *)os_malloc(os_strlen(str) + 1); // 1 for null character + if (new_str == NULL) { + os_printf("esp_strdup: malloc error"); + return NULL; + } + os_strcpy(new_str, str); + return new_str; +} + +static int ICACHE_FLASH_ATTR +esp_isupper(char c) +{ + return (c >= 'A' && c <= 'Z'); +} + +static int ICACHE_FLASH_ATTR +esp_isalpha(char c) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +} + + +static int ICACHE_FLASH_ATTR +esp_isspace(char c) +{ + return (c == ' ' || c == '\t' || c == '\n' || c == '\12'); +} + +static int ICACHE_FLASH_ATTR +esp_isdigit(char c) +{ + return (c >= '0' && c <= '9'); +} + +/* + * Convert a string to a long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long ICACHE_FLASH_ATTR +esp_strtol(nptr, endptr, base) + const char *nptr; + char **endptr; + int base; +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (esp_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } else if ((base == 0 || base == 2) && + c == '0' && (*s == 'b' || *s == 'B')) { + c = s[1]; + s += 2; + base = 2; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (esp_isdigit(c)) + c -= '0'; + else if (esp_isalpha(c)) + c -= esp_isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; +// errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + +static int ICACHE_FLASH_ATTR chunked_decode(const char * chunked, char * decode) +{ + int i = 0, j = 0; + int decode_size = 0; + char *str = (char *)chunked; + do + { + char * endstr = NULL; + //[chunk-size] + i = esp_strtol(str + j, endstr, 16); + PRINTF("Chunk Size:%d\r\n", i); + if (i <= 0) + break; + //[chunk-size-end-ptr] + endstr = (char *)os_strstr(str + j, "\r\n"); + //[chunk-ext] + j += endstr - (str + j); + //[CRLF] + j += 2; + //[chunk-data] + decode_size += i; + os_memcpy((char *)&decode[decode_size - i], (char *)str + j, i); + j += i; + //[CRLF] + j += 2; + } while(true); + + // + //footer CRLF + // + + return j; +} + +static void ICACHE_FLASH_ATTR receive_callback(void * arg, char * buf, unsigned short len) +{ + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + if (req->buffer == NULL) { + return; + } + + // Let's do the equivalent of a realloc(). + const int new_size = req->buffer_size + len; + char * new_buffer; + if (new_size > BUFFER_SIZE_MAX || NULL == (new_buffer = (char *)os_malloc(new_size))) { + os_printf("Response too long (%d)\n", new_size); + req->buffer[0] = '\0'; // Discard the buffer to avoid using an incomplete response. + espconn_disconnect(conn); + return; // The disconnect callback will be called. + } + + os_memcpy(new_buffer, req->buffer, req->buffer_size); + os_memcpy(new_buffer + req->buffer_size - 1 /*overwrite the null character*/, buf, len); // Append new data. + new_buffer[new_size - 1] = '\0'; // Make sure there is an end of string. + + os_free(req->buffer); + req->buffer = new_buffer; + req->buffer_size = new_size; +} + +static void ICACHE_FLASH_ATTR sent_callback(void * arg) +{ + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + if (req->post_data == NULL) { + PRINTF("All sent\n"); + } + else { + // The headers were sent, now send the contents. + PRINTF("Sending request body\n"); + espconn_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data)); + os_free(req->post_data); + req->post_data = NULL; + } +} + +static void ICACHE_FLASH_ATTR connect_callback(void * arg) +{ + PRINTF("Connected\n"); + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + espconn_regist_recvcb(conn, receive_callback); + espconn_regist_sentcb(conn, sent_callback); + + const char * method = "GET"; + char post_headers[32] = ""; + + if (req->post_data != NULL) { // If there is data this is a POST request. + method = "POST"; + os_sprintf(post_headers, "Content-Length: %d\r\n", strlen(req->post_data)); + } + + char buf[69 + strlen(method) + strlen(req->path) + strlen(req->hostname) + + strlen(req->headers) + strlen(post_headers)]; + int len = os_sprintf(buf, + "%s %s HTTP/1.1\r\n" + "Host: %s:%d\r\n" + "Connection: close\r\n" + "User-Agent: ESP8266\r\n" + "%s" + "%s" + "\r\n", + method, req->path, req->hostname, req->port, req->headers, post_headers); + + espconn_sent(conn, (uint8_t *)buf, len); + os_free(req->headers); + req->headers = NULL; + PRINTF("Sending request header\n"); +} + +static void ICACHE_FLASH_ATTR disconnect_callback(void * arg) +{ + PRINTF("Disconnected\n"); + struct espconn *conn = (struct espconn *)arg; + + if(conn == NULL) { + return; + } + + if(conn->proto.tcp != NULL) { + os_free(conn->proto.tcp); + } + if(conn->reverse != NULL) { + request_args * req = (request_args *)conn->reverse; + int http_status = -1; + char * body = ""; + if (req->buffer == NULL) { + os_printf("Buffer shouldn't be NULL\n"); + } + else if (req->buffer[0] != '\0') { + // FIXME: make sure this is not a partial response, using the Content-Length header. + + const char * version = "HTTP/1.1 "; + if (os_strncmp(req->buffer, version, strlen(version)) != 0) { + os_printf("Invalid version in %s\n", req->buffer); + } + else { + http_status = atoi(req->buffer + strlen(version)); + body = (char *)os_strstr(req->buffer, "\r\n\r\n") + 4; + if(os_strstr(req->buffer, "Transfer-Encoding: chunked")) + { + int body_size = req->buffer_size - (body - req->buffer); + char chunked_decode_buffer[body_size]; + os_memset(chunked_decode_buffer, 0, body_size); + // Chuncked data + chunked_decode(body, chunked_decode_buffer); + os_memcpy(body, chunked_decode_buffer, body_size); + } + } + } + + if (req->user_callback != NULL) { // Callback is optional. + req->user_callback(body, http_status, req->buffer); + } + + os_free(req->buffer); + os_free(req->hostname); + os_free(req->path); + os_free(req); + } + os_free(conn); +} + +static void ICACHE_FLASH_ATTR error_callback(void *arg, sint8 errType) +{ + PRINTF("Disconnected with error\n"); + disconnect_callback(arg); +} + +static void ICACHE_FLASH_ATTR dns_callback(const char * hostname, ip_addr_t * addr, void * arg) +{ + request_args * req = (request_args *)arg; + + if (addr == NULL) { + os_printf("DNS failed for %s\n", hostname); + if (req->user_callback != NULL) { + req->user_callback("", -1, ""); + } + os_free(req); + } + else { + PRINTF("DNS found %s " IPSTR "\n", hostname, IP2STR(addr)); + + struct espconn * conn = (struct espconn *)os_malloc(sizeof(struct espconn)); + conn->type = ESPCONN_TCP; + conn->state = ESPCONN_NONE; + conn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp)); + conn->proto.tcp->local_port = espconn_port(); + conn->proto.tcp->remote_port = req->port; + conn->reverse = req; + + os_memcpy(conn->proto.tcp->remote_ip, addr, 4); + + espconn_regist_connectcb(conn, connect_callback); + espconn_regist_disconcb(conn, disconnect_callback); + espconn_regist_reconcb(conn, error_callback); + + espconn_connect(conn); + } +} + +void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, const char * headers, http_callback user_callback) +{ + PRINTF("DNS request\n"); + + request_args * req = (request_args *)os_malloc(sizeof(request_args)); + req->hostname = esp_strdup(hostname); + req->path = esp_strdup(path); + req->port = port; + req->headers = esp_strdup(headers); + req->post_data = esp_strdup(post_data); + req->buffer_size = 1; + req->buffer = (char *)os_malloc(1); + req->buffer[0] = '\0'; // Empty string. + req->user_callback = user_callback; + + ip_addr_t addr; + err_t error = espconn_gethostbyname((struct espconn *)req, // It seems we don't need a real espconn pointer here. + hostname, &addr, dns_callback); + + if (error == ESPCONN_INPROGRESS) { + PRINTF("DNS pending\n"); + } + else if (error == ESPCONN_OK) { + // Already in the local names table (or hostname was an IP address), execute the callback ourselves. + dns_callback(hostname, &addr, req); + } + else { + if (error == ESPCONN_ARG) { + os_printf("DNS arg error %s\n", hostname); + } + else { + os_printf("DNS error code %d\n", error); + } + dns_callback(hostname, NULL, req); // Handle all DNS errors the same way. + } +} + +/* + * Parse an URL of the form http://host:port/path + * can be a hostname or an IP address + * is optional + */ +void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback) +{ + // FIXME: handle HTTP auth with http://user:pass@host/ + // FIXME: get rid of the #anchor part if present. + + char hostname[128] = ""; + int port = 80; + + bool is_http = os_strncmp(url, "http://", strlen("http://")) == 0; + + if (is_http) + url += strlen("http://"); // Get rid of the protocol. + else { + os_printf("URL is not HTTP or HTTPS %s\n", url); + return; + } + + char * path = os_strchr(url, '/'); + if (path == NULL) { + path = os_strchr(url, '\0'); // Pointer to end of string. + } + + char * colon = os_strchr(url, ':'); + if (colon > path) { + colon = NULL; // Limit the search to characters before the path. + } + + if (colon == NULL) { // The port is not present. + os_memcpy(hostname, url, path - url); + hostname[path - url] = '\0'; + } + else { + port = atoi(colon + 1); + if (port == 0) { + os_printf("Port error %s\n", url); + return; + } + + os_memcpy(hostname, url, colon - url); + hostname[colon - url] = '\0'; + } + + + if (path[0] == '\0') { // Empty path is not allowed. + path = "/"; + } + + PRINTF("hostname=%s\n", hostname); + PRINTF("port=%d\n", port); + PRINTF("path=%s\n", path); + http_raw_request(hostname, port, path, post_data, headers, user_callback); +} + +void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback user_callback) +{ + http_post(url, NULL, headers, user_callback); +} + +void ICACHE_FLASH_ATTR http_callback_example(char * response, int http_status, char * full_response) +{ + os_printf("http_status=%d\n", http_status); + if (http_status != HTTP_STATUS_GENERIC_ERROR) { + os_printf("strlen(full_response)=%d\n", strlen(full_response)); + os_printf("response=%s\n", response); + } +} diff --git a/firmwares/minetest/src/httpclient.h b/firmwares/minetest/src/httpclient.h new file mode 100644 index 0000000..019f57f --- /dev/null +++ b/firmwares/minetest/src/httpclient.h @@ -0,0 +1,50 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Martin d'Allens wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +#ifndef HTTPCLIENT_H +#define HTTPCLIENT_H + +#define HTTP_STATUS_GENERIC_ERROR -1 // In case of TCP or DNS error the callback is called with this status. +#define BUFFER_SIZE_MAX 5000 // Size of http responses that will cause an error. + +/* + * "full_response" is a string containing all response headers and the response body. + * "response_body and "http_status" are extracted from "full_response" for convenience. + * + * A successful request corresponds to an HTTP status code of 200 (OK). + * More info at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes + */ +typedef void (* http_callback)(char * response_body, int http_status, char * full_response); + +/* + * Download a web page from its URL. + * Try: + * http_get("http://wtfismyip.com/text", http_callback_example); + */ +void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback user_callback); + +/* + * Post data to a web form. + * The data should be encoded as application/x-www-form-urlencoded. + * Try: + * http_post("http://httpbin.org/post", "first_word=hello&second_word=world", http_callback_example); + */ +void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback); + +/* + * Call this function to skip URL parsing if the arguments are already in separate variables. + */ +void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, const char * headers, http_callback user_callback); + +/* + * Output on the UART. + */ +void http_callback_example(char * response, int http_status, char * full_response); + +#endif diff --git a/firmwares/minetest/src/i2c_master.c b/firmwares/minetest/src/i2c_master.c new file mode 100644 index 0000000..8da2611 --- /dev/null +++ b/firmwares/minetest/src/i2c_master.c @@ -0,0 +1,316 @@ +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: i2c_master.c + * + * Description: i2c master API + * + * Modification history: + * 2014/3/12, v1.0 create this file. +*******************************************************************************/ +#include "ets_sys.h" +#include "osapi.h" +#include "gpio.h" + +#include "i2c_master.h" + +LOCAL uint8 m_nLastSDA; +LOCAL uint8 m_nLastSCL; + +/****************************************************************************** + * FunctionName : i2c_master_setDC + * Description : Internal used function - + * set i2c SDA and SCL bit value for half clk cycle + * Parameters : uint8 SDA + * uint8 SCL + * Returns : NONE +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +i2c_master_setDC(uint8 SDA, uint8 SCL) +{ + SDA &= 0x01; + SCL &= 0x01; + m_nLastSDA = SDA; + m_nLastSCL = SCL; + + if ((0 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_LOW(); + } else if ((0 == SDA) && (1 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_HIGH(); + } else if ((1 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_HIGH_SCL_LOW(); + } else { + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + } +} + +/****************************************************************************** + * FunctionName : i2c_master_getDC + * Description : Internal used function - + * get i2c SDA bit value + * Parameters : NONE + * Returns : uint8 - SDA bit value +*******************************************************************************/ +LOCAL uint8 ICACHE_FLASH_ATTR +i2c_master_getDC(void) +{ + uint8 sda_out; + sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)); + return sda_out; +} + +/****************************************************************************** + * FunctionName : i2c_master_init + * Description : initilize I2C bus to enable i2c operations + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_init(void) +{ + uint8 i; + + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + // when SCL = 0, toggle SDA to clear up + i2c_master_setDC(0, 0) ; + i2c_master_wait(5); + i2c_master_setDC(1, 0) ; + i2c_master_wait(5); + + // set data_cnt to max value + for (i = 0; i < 28; i++) { + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + } + + // reset all + i2c_master_stop(); + return; +} + +/****************************************************************************** + * FunctionName : i2c_master_gpio_init + * Description : config SDA and SCL gpio to open-drain output mode, + * mux and gpio num defined in i2c_master.h + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_gpio_init(void) +{ + ETS_GPIO_INTR_DISABLE() ; +// ETS_INTR_LOCK(); + + PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC); + PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC); + + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain; + GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SDA_GPIO)); + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain; + GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SCL_GPIO)); + + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + + ETS_GPIO_INTR_ENABLE() ; +// ETS_INTR_UNLOCK(); + + i2c_master_init(); +} + +/****************************************************************************** + * FunctionName : i2c_master_start + * Description : set i2c to send state + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_start(void) +{ + i2c_master_setDC(1, m_nLastSCL); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 +} + +/****************************************************************************** + * FunctionName : i2c_master_stop + * Description : set i2c to stop sending state + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_stop(void) +{ + i2c_master_wait(5); + + i2c_master_setDC(0, m_nLastSCL); + i2c_master_wait(5); // sda 0 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 +} + +/****************************************************************************** + * FunctionName : i2c_master_setAck + * Description : set ack to i2c bus as level value + * Parameters : uint8 level - 0 or 1 + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_setAck(uint8 level) +{ + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(level, 1); + i2c_master_wait(8); // sda level, scl 1 + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(1, 0); + i2c_master_wait(5); +} + +/****************************************************************************** + * FunctionName : i2c_master_getAck + * Description : confirm if peer send ack + * Parameters : NONE + * Returns : uint8 - ack value, 0 or 1 +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR +i2c_master_getAck(void) +{ + uint8 retVal; + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); + + retVal = i2c_master_getDC(); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + return retVal; +} + +/****************************************************************************** +* FunctionName : i2c_master_checkAck +* Description : get dev response +* Parameters : NONE +* Returns : true : get ack ; false : get nack +*******************************************************************************/ +bool ICACHE_FLASH_ATTR +i2c_master_checkAck(void) +{ + if(i2c_master_getAck()){ + return FALSE; + }else{ + return TRUE; + } +} + +/****************************************************************************** +* FunctionName : i2c_master_send_ack +* Description : response ack +* Parameters : NONE +* Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_send_ack(void) +{ + i2c_master_setAck(0x0); +} +/****************************************************************************** +* FunctionName : i2c_master_send_nack +* Description : response nack +* Parameters : NONE +* Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_send_nack(void) +{ + i2c_master_setAck(0x1); +} + +/****************************************************************************** + * FunctionName : i2c_master_readByte + * Description : read Byte from i2c bus + * Parameters : NONE + * Returns : uint8 - readed value +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR +i2c_master_readByte(void) +{ + uint8 retVal = 0; + uint8 k, i; + + i2c_master_wait(5); + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); // sda 1, scl 0 + + for (i = 0; i < 8; i++) { + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + + k = i2c_master_getDC(); + i2c_master_wait(5); + + if (i == 7) { + i2c_master_wait(3); //// + } + + k <<= (7 - i); + retVal |= k; + } + + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + + return retVal; +} + +/****************************************************************************** + * FunctionName : i2c_master_writeByte + * Description : write wrdata value(one byte) into i2c + * Parameters : uint8 wrdata - write value + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_writeByte(uint8 wrdata) +{ + uint8 dat; + sint8 i; + + i2c_master_wait(5); + + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + + for (i = 7; i >= 0; i--) { + dat = wrdata >> i; + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + i2c_master_setDC(dat, 1); + i2c_master_wait(5); + + if (i == 0) { + i2c_master_wait(3); //// + } + + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + } +} diff --git a/firmwares/minetest/src/i2c_master.h b/firmwares/minetest/src/i2c_master.h new file mode 100644 index 0000000..6e0c9f0 --- /dev/null +++ b/firmwares/minetest/src/i2c_master.h @@ -0,0 +1,39 @@ +#ifndef __I2C_MASTER_H__ +#define __I2C_MASTER_H__ + +#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO2_U +#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_MTMS_U +#define I2C_MASTER_SDA_GPIO 2 +#define I2C_MASTER_SCL_GPIO 14 +#define I2C_MASTER_SDA_FUNC FUNC_GPIO2 +#define I2C_MASTER_SCL_FUNC FUNC_GPIO14 + +#define I2C_MASTER_SDA_HIGH_SCL_HIGH() \ + gpio_output_set(1< +#include + +// Project +#include "i2c_master.h" +#include "util.h" + +#define I2C_ADDR_W(addr) ((addr<<1)) +#define I2C_ADDR_R(addr) ((addr<<1) | 0x01) + +bool ICACHE_FLASH_ATTR i2cdevice_read(uint8_t devaddr, uint8_t regaddr, uint8_t len, uint8_t *data) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(I2C_ADDR_W(devaddr)); + if (i2c_master_getAck()) { + os_printf("I²C device %x R: no ACK for write addr\r\n", devaddr); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("I²C device %x R: no ACK for register\r\n", devaddr); + i2c_master_stop(); + return false; + } + + i2c_master_start(); + + // Write I²C Address for reading + i2c_master_writeByte(I2C_ADDR_R(devaddr)); + if (i2c_master_getAck()) { + os_printf("I²C device %x R: no ACK for read addr\r\n", devaddr); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + data[i] = i2c_master_readByte(); + if (i != len - 1) + i2c_master_send_ack(); + else + i2c_master_send_nack(); + } + + i2c_master_stop(); + //os_printf("Just read %x from %x\r\n", *data, regaddr); + + return true; +} + +bool ICACHE_FLASH_ATTR i2cdevice_write(uint8_t devaddr, uint8_t regaddr, uint8_t len, uint8_t *data) { + //os_printf("Writing %x to %x\r\n", *data, regaddr); + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(I2C_ADDR_W(devaddr)); + if (i2c_master_getAck()) { + os_printf("I²C device %x W: no ACK for write addr\r\n", devaddr); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("I²C device %x W: no ACK for register\r\n", devaddr); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + i2c_master_writeByte(data[i]); + if (i2c_master_getAck()) { + os_printf("I²C device %x W: no ACK for datawrite\r\n", devaddr); + i2c_master_stop(); + return false; + } + } + + i2c_master_stop(); + + return true; +} + +// Single-byte operations +inline bool i2cdevice_writebyte(uint8_t devaddr, uint8_t regaddr, uint8_t data) { + return i2cdevice_write(devaddr, regaddr, 1, &data); +} + +inline bool i2cdevice_readbyte(uint8_t devaddr, uint8_t regaddr, uint8_t *data) { + return i2cdevice_read(devaddr, regaddr, 1, data); +} + +// Get bit in any register +bool ICACHE_FLASH_ATTR i2cdevice_readbit(uint8_t devaddr, uint8_t regaddr, uint8_t bit, bool *val) { + uint8_t dat; + if (!i2cdevice_read(devaddr, regaddr, 1, &dat)) return false; + *val = (gbi(dat, bit) != false); + return true; +} + +// Set bit in any register +bool ICACHE_FLASH_ATTR i2cdevice_writebit(uint8_t devaddr, uint8_t regaddr, uint8_t bit, bool val) { + uint8_t dat; + if (!i2cdevice_read(devaddr, regaddr, 1, &dat)) return false; + if (val) + sbi(dat, bit); + else + cbi(dat, bit); + if (!i2cdevice_write(devaddr, regaddr, 1, &dat)) return false; + return true; +} diff --git a/firmwares/minetest/src/i2cdevice.h b/firmwares/minetest/src/i2cdevice.h new file mode 100644 index 0000000..c49dc74 --- /dev/null +++ b/firmwares/minetest/src/i2cdevice.h @@ -0,0 +1,16 @@ +#include + +#ifndef _I2CUTIL_H +#define _I2CUTIL_H + +// Most I²C devices use a commons protocol for reading / writing registers, e.g. MPU-9250 and the integrated AK8963 +bool i2cdevice_read(uint8_t regaddr, uint8_t len, uint8_t *data); +bool i2cdevice_write(uint8_t regaddr, uint8_t len, uint8_t *data); + +inline bool i2cdevice_writebyte(uint8_t devaddr, uint8_t regaddr, uint8_t data); +inline bool i2cdevice_readbyte(uint8_t devaddr, uint8_t regaddr, uint8_t *data); + +bool i2cdevice_readbit(uint8_t regaddr, uint8_t bit, bool *val); +bool i2cdevice_writebit(uint8_t regaddr, uint8_t bit, bool val); + +#endif diff --git a/firmwares/minetest/src/main.c b/firmwares/minetest/src/main.c new file mode 100644 index 0000000..7f3b383 --- /dev/null +++ b/firmwares/minetest/src/main.c @@ -0,0 +1,158 @@ +// System +#include +#include +#include +#include +#include +#include + +// Configuration +#include "user_config.h" + +// Libesphttpd +#include "webpages-espfs.h" +#include "httpdespfs.h" +#include "httpd.h" +#include "espfs.h" + +// Project +#include "httpclient.h" +#include "i2c_master.h" +#include "buttons.h" +#include "mpu9250.h" +#include "ssd1306.h" +#include "rv3029.h" +#include "vector.h" +#include "util.h" + +// Globals +os_timer_t sensor_timer; +os_timer_t setup_timer; +vec3f calib_bias; + +vec3s16 acc; +vec3s16 gyro; +vec3s16 field; + +void ICACHE_FLASH_ATTR sensor_timer_cb() { + // Compass + ak8963_get_field(&field); + field.x -= calib_bias.x; + field.y -= calib_bias.y; + field.z -= calib_bias.z; + //angles2f north = vec3s16_to_angles2f(field); + ak8963_set_opmode(AK8963_SINGLE, AK8963_16BIT); + + // Acceleration + mpu9250_acc_get_acceleration(&acc); + + // Gyro + mpu9250_gyr_get_angvelocity(&gyro); + + //compass_yaw = north.yaw; + //acc_pitch = atan2(acc.y, acc.z); +} + +void ICACHE_FLASH_ATTR on_ak8963_calibration(vec3f bias) { + calib_bias.x = bias.x; + calib_bias.y = bias.y; + calib_bias.z = bias.z; + + os_timer_setfn(&sensor_timer, (os_timer_func_t *)sensor_timer_cb, NULL); + os_timer_arm(&sensor_timer, 50, true); +} + +void ICACHE_FLASH_ATTR setup_timer_cb() { + ak8963_calibration_start(10000, on_ak8963_calibration); +} + +int cmd_minetest(HttpdConnData *conn) { + char answer[200]; + + int len = os_sprintf(answer, + "{ \"acc\" : { \"x\" : %d, \"y\" : %d, \"z\" : %d }, \ + \"gyro\" : { \"x\" : %d, \"y\" : %d, \"z\" : %d }, \ + \"compass\" : { \"x\" : %d, \"y\" : %d, \"z\" : %d } }", + acc.x, acc.y, acc.z, gyro.x, gyro.y, gyro.z, field.x, field.y, field.z); + + httpdStartResponse(conn, 200); + httpdHeader(conn, "Content-Type", "application/json"); + httpdEndHeaders(conn); + httpdSend(conn, answer, len); + + return HTTPD_CGI_DONE; +} + +HttpdBuiltInUrl builtInUrls[]={ + {"/", cgiRedirect, "/index.html"}, + {"/minetest", cmd_minetest, NULL}, + {"*", cgiEspFsHook, NULL}, + {NULL, NULL, NULL} +}; + +void ICACHE_FLASH_ATTR user_init(void) { + uart_div_modify(0, UART_CLK_FREQ / BAUD); + + wifi_set_opmode(STATION_MODE); + wifi_station_connect(); + + /*** I²C init ***/ + i2c_master_gpio_init(); + mpu9250_init(); + ak8963_init(); + + os_delay_us(10000); + i2c_scanbus(); + + /*** LCD Init ***/ + ssd1306_init(0); + ssd1306_text_small(10, 10, "Minetest Mode!"); + ssd1306_flip(); + + // ~Charge input + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); + gpio_output_set(0, 0, 0, BIT13); + + // Button inputs + buttons_init(); + + /*** WiFi configuration ***/ + wifi_set_opmode(STATION_MODE); + + // This is just some sample WiFi network I created + // for this purpose + char ssid[32] = "minetest"; + char pass[64] = "minetest_handgelenk"; + struct station_config sta_conf; + sta_conf.bssid_set = 0; + os_memcpy(&sta_conf.ssid, ssid, 32); + os_memcpy(&sta_conf.password, pass, 64); + wifi_station_set_config(&sta_conf); + wifi_station_connect(); + + /*** Network configuration ***/ + wifi_station_dhcpc_stop(); + struct ip_info ip_conf; + + IP4_ADDR(&ip_conf.ip, 192, 168, 0, 60); + IP4_ADDR(&ip_conf.gw, 192, 168, 0, 2); + IP4_ADDR(&ip_conf.netmask, 255, 255, 0, 0); + wifi_set_ip_info(STATION_IF, &ip_conf); + + /*** Compass calibration and setup ***/ + // Delay so that WiFi configuration can be applied before + os_timer_setfn(&setup_timer, (os_timer_func_t *)setup_timer_cb, NULL); + os_timer_arm(&setup_timer, 3000, false); + + /*** Accelerometer setup ***/ + mpu9250_acc_config(MPU9250_ACC_SCALE_8G); + + /*** Gyroscope setup ***/ + mpu9250_gyr_config(MPU9250_GYR_SCALE_250DPS); + + /*** Set up HTTP Server ***/ + espFsInit((void*)(webpages_espfs_start)); + httpdInit(builtInUrls, 80); + + os_printf("Startup\r\n"); +} diff --git a/firmwares/minetest/src/mpu9250.c b/firmwares/minetest/src/mpu9250.c new file mode 100644 index 0000000..892f781 --- /dev/null +++ b/firmwares/minetest/src/mpu9250.c @@ -0,0 +1,182 @@ +// System +#include +#include +#include + +// Project +#include "mpu9250_reg.h" +#include "i2c_master.h" +#include "mpu9250.h" +#include "vector.h" +#include "util.h" + +/*** Internal I²C functions ***/ +#define mpu9250_write(regaddr, len, data) (i2cdevice_write(MPU9250_ADDR, regaddr, len, data)) +#define mpu9250_read(regaddr, len, data) (i2cdevice_read(MPU9250_ADDR, regaddr, len, data)) +#define mpu9250_readbyte(regaddr, data) (i2cdevice_readbyte(MPU9250_ADDR, regaddr, data)) +#define mpu9250_writebyte(regaddr, data) (i2cdevice_writebyte(MPU9250_ADDR, regaddr, data)) +#define mpu9250_readbit(regaddr, bit, val) (i2cdevice_readbit(MPU9250_ADDR, regaddr, bit, val)) +#define mpu9250_writebit(regaddr, bit, val) (i2cdevice_writebit(MPU9250_ADDR, regaddr, bit, val)) + +#define ak8963_write(regaddr, len, data) (i2cdevice_write(AK8963_ADDR, regaddr, len, data)) +#define ak8963_read(regaddr, len, data) (i2cdevice_read(AK8963_ADDR, regaddr, len, data)) +#define ak8963_readbyte(regaddr, data) (i2cdevice_readbyte(AK8963_ADDR, regaddr, data)) +#define ak8963_writebyte(regaddr, data) (i2cdevice_writebyte(AK8963_ADDR, regaddr, data)) +#define ak8963_readbit(regaddr, bit, val) (i2cdevice_readbit(AK8963_ADDR, regaddr, bit, val)) +#define ak8963_writebit(regaddr, bit, val) (i2cdevice_writebit(AK8963_ADDR, regaddr, bit, val)) + +/*** Common ***/ +/* + * Initialize to configuration used in this project: + * - Reset MPU-9250 and restore sane defaults + * - Some dummy reads to ensure communication works + * - Enable I²C Bypass to Compass + */ +void ICACHE_FLASH_ATTR mpu9250_init() { + // Reset MPU-9250 + mpu9250_writebyte(MPU9250_RA_PWR_MGMT_1, 1<x = (((int16_t)buffer[0]) << 8) | buffer[1]; + measurement->y = (((int16_t)buffer[2]) << 8) | buffer[3]; + measurement->z = (((int16_t)buffer[4]) << 8) | buffer[5]; + + return true; +} + +/*** Gyroscope ***/ +bool ICACHE_FLASH_ATTR mpu9250_gyr_config(enum mpu9250_gyr_scale scale) { + if (!mpu9250_writebit(MPU9250_RA_GYRO_CONFIG, 3, gbi(scale, 0))) return false; + if (!mpu9250_writebit(MPU9250_RA_GYRO_CONFIG, 4, gbi(scale, 1))) return false; + + return true; +} + +bool ICACHE_FLASH_ATTR mpu9250_gyr_get_angvelocity(vec3s16 *measurement) { + uint8_t buffer[6]; + if (!mpu9250_read(MPU9250_RA_GYRO_XOUT_H, 6, buffer)) return false; + measurement->x = (((int16_t)buffer[0]) << 8) | buffer[1]; + measurement->y = (((int16_t)buffer[2]) << 8) | buffer[3]; + measurement->z = (((int16_t)buffer[4]) << 8) | buffer[5]; + + return true; +} + +/*** Compass: ***/ +bool ICACHE_FLASH_ATTR ak8963_init() { + // Reset device + if (!ak8963_writebyte(AK8963_RA_CNTL2, 1)) return false; + os_delay_us(1000); + + uint8_t wia; + ak8963_readbyte(AK8963_RA_WIA, &wia); + if (!os_printf("AK8963 WIA: %x\r\n", wia)) return false; + + return true; +} + +bool ICACHE_FLASH_ATTR ak8963_set_opmode(enum ak8963_opmode mode, enum ak8963_bitwidth width) { + return ak8963_writebyte(AK8963_RA_CNTL1, mode | width); +} + +bool ICACHE_FLASH_ATTR ak8963_get_drdy(bool *drdy) { + return ak8963_readbit(AK8963_RA_ST1, 0, drdy); +} + +bool ICACHE_FLASH_ATTR ak8963_get_field(vec3s16 *measurement) { + uint8_t buffer[6]; + if (!ak8963_read(AK8963_RA_HXL, 6, buffer)) return false; + measurement->x = (((int16_t)buffer[1]) << 8) | buffer[0]; + measurement->y = (((int16_t)buffer[3]) << 8) | buffer[2]; + measurement->z = (((int16_t)buffer[5]) << 8) | buffer[4]; + + return true; +} + +/*** Compass Calibration: ***/ +struct ak8963_calib_proc { + os_timer_t datatimer; + os_timer_t completetimer; + vec3s16 maximum; + vec3s16 minimum; + ak8963_calibration_callback complete; +}; + +void ICACHE_FLASH_ATTR ak8963_calibration_datatimer_cb(struct ak8963_calib_proc *proc) { + bool drdy; + ak8963_get_drdy(&drdy); + if (!drdy) return; + + vec3s16 field; + if (!ak8963_get_field(&field)) return; + + // Store maximum and minimum magnetic values + if (field.x > proc->maximum.x) proc->maximum.x = field.x; + if (field.y > proc->maximum.y) proc->maximum.y = field.y; + if (field.z > proc->maximum.z) proc->maximum.z = field.z; + + if (field.x < proc->minimum.x) proc->minimum.x = field.x; + if (field.y < proc->minimum.y) proc->minimum.y = field.y; + if (field.z < proc->minimum.z) proc->minimum.z = field.z; + + ak8963_set_opmode(AK8963_SINGLE, AK8963_16BIT); +} + +void ICACHE_FLASH_ATTR ak8963_calibration_completetimer_cb(struct ak8963_calib_proc *proc) { + os_timer_disarm(proc->datatimer); + + os_printf("Maximum: %d, %d, %d\r\n", proc->maximum.x, proc->maximum.y, proc->maximum.z); + os_printf("Minimum: %d, %d, %d\r\n", proc->minimum.x, proc->minimum.y, proc->minimum.z); + + vec3f bias; + bias.x = (proc->maximum.x + proc->minimum.x) / 2.f; + bias.y = (proc->maximum.y + proc->minimum.y) / 2.f; + bias.z = (proc->maximum.z + proc->minimum.z) / 2.f; + + proc->complete(bias); +} + +void ICACHE_FLASH_ATTR ak8963_calibration_start(uint16_t milliseconds, ak8963_calibration_callback cb) { + static struct ak8963_calib_proc proc; + + proc.complete = cb; + proc.maximum.x = 0x8000; proc.maximum.y = 0x8000; proc.maximum.z = 0x8000; + proc.minimum.x = 0x7fff; proc.minimum.y = 0x7fff; proc.minimum.z = 0x7fff; + + os_timer_setfn(&proc.datatimer, (os_timer_func_t *)ak8963_calibration_datatimer_cb, &proc); + os_timer_arm(&proc.datatimer, AK8963_CALIB_INTERVAL, true); + + os_timer_setfn(&proc.completetimer, (os_timer_func_t *)ak8963_calibration_completetimer_cb, &proc); + os_timer_arm(&proc.completetimer, milliseconds, false); + + ak8963_set_opmode(AK8963_SINGLE, AK8963_16BIT); +} diff --git a/firmwares/minetest/src/mpu9250.h b/firmwares/minetest/src/mpu9250.h new file mode 100644 index 0000000..a9f661c --- /dev/null +++ b/firmwares/minetest/src/mpu9250.h @@ -0,0 +1,61 @@ +#include + +#include "vector.h" + +#ifndef _MPU9250_H +#define _MPU9250_H + +// Configuration - Addresses include write/read bit +#define MPU9250_ADDR 0x68 +#define AK8963_ADDR 0x0c +#define AK8963_CALIB_INTERVAL 10 + +/*** Common ***/ +void mpu9250_init(); +void mpu9250_i2cbypass_set(bool active); + +/*** Accelerometer ***/ +enum mpu9250_acc_scale { + MPU9250_ACC_SCALE_2G = 0b00, + MPU9250_ACC_SCALE_4G = 0b01, + MPU9250_ACC_SCALE_8G = 0b10, + MPU9250_ACC_SCALE_16G = 0b11, +}; + +bool mpu9250_acc_config(enum mpu9250_acc_scale scale); +bool mpu9250_acc_get_acceleration(vec3s16 *measurement); + +/*** Gyroscope ***/ +enum mpu9250_gyr_scale { + MPU9250_GYR_SCALE_250DPS = 0b00, + MPU9250_GYR_SCALE_500DPS = 0b01, + MPU9250_GYR_SCALE_1000DPS = 0b10, + MPU9250_GYR_SCALE_2000DPS = 0b11, +}; + +bool mpu9250_gyr_config(enum mpu9250_gyr_scale scale); +bool mpu9250_gyr_get_angvelocity(vec3s16 *measurement); + +/*** Compass ***/ +enum ak8963_opmode { + AK8963_PWRDOWN = 0, + AK8963_SINGLE = 1, + AK8963_8HZ = 2, + AK8963_100HZ = 6, + AK8963_SELFTEST = 8, + AK8963_FUSEACCESS = 15 +}; + +enum ak8963_bitwidth { + AK8963_14BIT = 0, + AK8963_16BIT = (1<<4) +}; + +typedef void (*ak8963_calibration_callback)(vec3f bias); + +bool ak8963_init(); +bool ak8963_set_opmode(enum ak8963_opmode mode, enum ak8963_bitwidth width); +bool ak8963_get_drdy(bool *drdy); +bool ak8963_get_field(vec3s16 *measurement); + +#endif diff --git a/firmwares/minetest/src/mpu9250_reg.h b/firmwares/minetest/src/mpu9250_reg.h new file mode 100644 index 0000000..14860b3 --- /dev/null +++ b/firmwares/minetest/src/mpu9250_reg.h @@ -0,0 +1,388 @@ +/* + * From https://github.com/Seeed-Studio/IMU_10DOF/blob/master/MPU9250.h, originally from I²Cdevlib (http://i2cdevlib.com) + * Modified, removed everything but the register addresses and added some AK8963 registers. Documented in the MPU-9250 Register Map: + * http://www.invensense.com/products/motion-tracking/9-axis/mpu-9250/ + * + * ============================================ + * I2Cdev device library code is placed under the MIT license + * Copyright (c) 2012 Jeff Rowberg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * =============================================== + */ + +//Magnetometer Registers +#define AK8963_RA_WIA 0x00 +#define AK8963_RA_INFO 0x01 +#define AK8963_RA_ST1 0x02 +#define AK8963_RA_HXL 0x03 +#define AK8963_RA_HXH 0x04 +#define AK8963_RA_HYL 0x05 +#define AK8963_RA_HYH 0x06 +#define AK8963_RA_HZL 0x07 +#define AK8963_RA_HZH 0x08 +#define AK8963_RA_CNTL1 0x0a +#define AK8963_RA_CNTL2 0x0b +#define AK8963_RA_ASTC 0x0c +#define AK8963_RA_I2CDIS 0x0f +#define AK8963_RA_ASAX 0x10 +#define AK8963_RA_ASAY 0x11 +#define AK8963_RA_ASAZ 0x12 + +#define MPU9250_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9250_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9250_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD +#define MPU9250_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN +#define MPU9250_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN +#define MPU9250_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN +#define MPU9250_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS +#define MPU9250_RA_XA_OFFS_L_TC 0x07 +#define MPU9250_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS +#define MPU9250_RA_YA_OFFS_L_TC 0x09 +#define MPU9250_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS +#define MPU9250_RA_ZA_OFFS_L_TC 0x0B +#define MPU9250_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR +#define MPU9250_RA_XG_OFFS_USRL 0x14 +#define MPU9250_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR +#define MPU9250_RA_YG_OFFS_USRL 0x16 +#define MPU9250_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR +#define MPU9250_RA_ZG_OFFS_USRL 0x18 +#define MPU9250_RA_SMPLRT_DIV 0x19 +#define MPU9250_RA_CONFIG 0x1A +#define MPU9250_RA_GYRO_CONFIG 0x1B +#define MPU9250_RA_ACCEL_CONFIG 0x1C +#define MPU9250_RA_FF_THR 0x1D +#define MPU9250_RA_FF_DUR 0x1E +#define MPU9250_RA_MOT_THR 0x1F +#define MPU9250_RA_MOT_DUR 0x20 +#define MPU9250_RA_ZRMOT_THR 0x21 +#define MPU9250_RA_ZRMOT_DUR 0x22 +#define MPU9250_RA_FIFO_EN 0x23 +#define MPU9250_RA_I2C_MST_CTRL 0x24 +#define MPU9250_RA_I2C_SLV0_ADDR 0x25 +#define MPU9250_RA_I2C_SLV0_REG 0x26 +#define MPU9250_RA_I2C_SLV0_CTRL 0x27 +#define MPU9250_RA_I2C_SLV1_ADDR 0x28 +#define MPU9250_RA_I2C_SLV1_REG 0x29 +#define MPU9250_RA_I2C_SLV1_CTRL 0x2A +#define MPU9250_RA_I2C_SLV2_ADDR 0x2B +#define MPU9250_RA_I2C_SLV2_REG 0x2C +#define MPU9250_RA_I2C_SLV2_CTRL 0x2D +#define MPU9250_RA_I2C_SLV3_ADDR 0x2E +#define MPU9250_RA_I2C_SLV3_REG 0x2F +#define MPU9250_RA_I2C_SLV3_CTRL 0x30 +#define MPU9250_RA_I2C_SLV4_ADDR 0x31 +#define MPU9250_RA_I2C_SLV4_REG 0x32 +#define MPU9250_RA_I2C_SLV4_DO 0x33 +#define MPU9250_RA_I2C_SLV4_CTRL 0x34 +#define MPU9250_RA_I2C_SLV4_DI 0x35 +#define MPU9250_RA_I2C_MST_STATUS 0x36 +#define MPU9250_RA_INT_PIN_CFG 0x37 +#define MPU9250_RA_INT_ENABLE 0x38 +#define MPU9250_RA_DMP_INT_STATUS 0x39 +#define MPU9250_RA_INT_STATUS 0x3A +#define MPU9250_RA_ACCEL_XOUT_H 0x3B +#define MPU9250_RA_ACCEL_XOUT_L 0x3C +#define MPU9250_RA_ACCEL_YOUT_H 0x3D +#define MPU9250_RA_ACCEL_YOUT_L 0x3E +#define MPU9250_RA_ACCEL_ZOUT_H 0x3F +#define MPU9250_RA_ACCEL_ZOUT_L 0x40 +#define MPU9250_RA_TEMP_OUT_H 0x41 +#define MPU9250_RA_TEMP_OUT_L 0x42 +#define MPU9250_RA_GYRO_XOUT_H 0x43 +#define MPU9250_RA_GYRO_XOUT_L 0x44 +#define MPU9250_RA_GYRO_YOUT_H 0x45 +#define MPU9250_RA_GYRO_YOUT_L 0x46 +#define MPU9250_RA_GYRO_ZOUT_H 0x47 +#define MPU9250_RA_GYRO_ZOUT_L 0x48 +#define MPU9250_RA_EXT_SENS_DATA_00 0x49 +#define MPU9250_RA_EXT_SENS_DATA_01 0x4A +#define MPU9250_RA_EXT_SENS_DATA_02 0x4B +#define MPU9250_RA_EXT_SENS_DATA_03 0x4C +#define MPU9250_RA_EXT_SENS_DATA_04 0x4D +#define MPU9250_RA_EXT_SENS_DATA_05 0x4E +#define MPU9250_RA_EXT_SENS_DATA_06 0x4F +#define MPU9250_RA_EXT_SENS_DATA_07 0x50 +#define MPU9250_RA_EXT_SENS_DATA_08 0x51 +#define MPU9250_RA_EXT_SENS_DATA_09 0x52 +#define MPU9250_RA_EXT_SENS_DATA_10 0x53 +#define MPU9250_RA_EXT_SENS_DATA_11 0x54 +#define MPU9250_RA_EXT_SENS_DATA_12 0x55 +#define MPU9250_RA_EXT_SENS_DATA_13 0x56 +#define MPU9250_RA_EXT_SENS_DATA_14 0x57 +#define MPU9250_RA_EXT_SENS_DATA_15 0x58 +#define MPU9250_RA_EXT_SENS_DATA_16 0x59 +#define MPU9250_RA_EXT_SENS_DATA_17 0x5A +#define MPU9250_RA_EXT_SENS_DATA_18 0x5B +#define MPU9250_RA_EXT_SENS_DATA_19 0x5C +#define MPU9250_RA_EXT_SENS_DATA_20 0x5D +#define MPU9250_RA_EXT_SENS_DATA_21 0x5E +#define MPU9250_RA_EXT_SENS_DATA_22 0x5F +#define MPU9250_RA_EXT_SENS_DATA_23 0x60 +#define MPU9250_RA_MOT_DETECT_STATUS 0x61 +#define MPU9250_RA_I2C_SLV0_DO 0x63 +#define MPU9250_RA_I2C_SLV1_DO 0x64 +#define MPU9250_RA_I2C_SLV2_DO 0x65 +#define MPU9250_RA_I2C_SLV3_DO 0x66 +#define MPU9250_RA_I2C_MST_DELAY_CTRL 0x67 +#define MPU9250_RA_SIGNAL_PATH_RESET 0x68 +#define MPU9250_RA_MOT_DETECT_CTRL 0x69 +#define MPU9250_RA_USER_CTRL 0x6A +#define MPU9250_RA_PWR_MGMT_1 0x6B +#define MPU9250_RA_PWR_MGMT_2 0x6C +#define MPU9250_RA_BANK_SEL 0x6D +#define MPU9250_RA_MEM_START_ADDR 0x6E +#define MPU9250_RA_MEM_R_W 0x6F +#define MPU9250_RA_DMP_CFG_1 0x70 +#define MPU9250_RA_DMP_CFG_2 0x71 +#define MPU9250_RA_FIFO_COUNTH 0x72 +#define MPU9250_RA_FIFO_COUNTL 0x73 +#define MPU9250_RA_FIFO_R_W 0x74 +#define MPU9250_RA_WHO_AM_I 0x75 + +#define MPU9250_TC_PWR_MODE_BIT 7 +#define MPU9250_TC_OFFSET_BIT 6 +#define MPU9250_TC_OFFSET_LENGTH 6 +#define MPU9250_TC_OTP_BNK_VLD_BIT 0 + +#define MPU9250_VDDIO_LEVEL_VLOGIC 0 +#define MPU9250_VDDIO_LEVEL_VDD 1 + +#define MPU9250_CFG_EXT_SYNC_SET_BIT 5 +#define MPU9250_CFG_EXT_SYNC_SET_LENGTH 3 +#define MPU9250_CFG_DLPF_CFG_BIT 2 +#define MPU9250_CFG_DLPF_CFG_LENGTH 3 + +#define MPU9250_EXT_SYNC_DISABLED 0x0 +#define MPU9250_EXT_SYNC_TEMP_OUT_L 0x1 +#define MPU9250_EXT_SYNC_GYRO_XOUT_L 0x2 +#define MPU9250_EXT_SYNC_GYRO_YOUT_L 0x3 +#define MPU9250_EXT_SYNC_GYRO_ZOUT_L 0x4 +#define MPU9250_EXT_SYNC_ACCEL_XOUT_L 0x5 +#define MPU9250_EXT_SYNC_ACCEL_YOUT_L 0x6 +#define MPU9250_EXT_SYNC_ACCEL_ZOUT_L 0x7 + +#define MPU9250_DLPF_BW_256 0x00 +#define MPU9250_DLPF_BW_188 0x01 +#define MPU9250_DLPF_BW_98 0x02 +#define MPU9250_DLPF_BW_42 0x03 +#define MPU9250_DLPF_BW_20 0x04 +#define MPU9250_DLPF_BW_10 0x05 +#define MPU9250_DLPF_BW_5 0x06 + +#define MPU9250_GCONFIG_FS_SEL_BIT 4 +#define MPU9250_GCONFIG_FS_SEL_LENGTH 2 + +#define MPU9250_GYRO_FS_250 0x00 +#define MPU9250_GYRO_FS_500 0x01 +#define MPU9250_GYRO_FS_1000 0x02 +#define MPU9250_GYRO_FS_2000 0x03 + +#define MPU9250_ACONFIG_XA_ST_BIT 7 +#define MPU9250_ACONFIG_YA_ST_BIT 6 +#define MPU9250_ACONFIG_ZA_ST_BIT 5 +#define MPU9250_ACONFIG_AFS_SEL_BIT 4 +#define MPU9250_ACONFIG_AFS_SEL_LENGTH 2 +#define MPU9250_ACONFIG_ACCEL_HPF_BIT 2 +#define MPU9250_ACONFIG_ACCEL_HPF_LENGTH 3 + +#define MPU9250_ACCEL_FS_2 0x00 +#define MPU9250_ACCEL_FS_4 0x01 +#define MPU9250_ACCEL_FS_8 0x02 +#define MPU9250_ACCEL_FS_16 0x03 + +#define MPU9250_DHPF_RESET 0x00 +#define MPU9250_DHPF_5 0x01 +#define MPU9250_DHPF_2P5 0x02 +#define MPU9250_DHPF_1P25 0x03 +#define MPU9250_DHPF_0P63 0x04 +#define MPU9250_DHPF_HOLD 0x07 + +#define MPU9250_TEMP_FIFO_EN_BIT 7 +#define MPU9250_XG_FIFO_EN_BIT 6 +#define MPU9250_YG_FIFO_EN_BIT 5 +#define MPU9250_ZG_FIFO_EN_BIT 4 +#define MPU9250_ACCEL_FIFO_EN_BIT 3 +#define MPU9250_SLV2_FIFO_EN_BIT 2 +#define MPU9250_SLV1_FIFO_EN_BIT 1 +#define MPU9250_SLV0_FIFO_EN_BIT 0 + +#define MPU9250_MULT_MST_EN_BIT 7 +#define MPU9250_WAIT_FOR_ES_BIT 6 +#define MPU9250_SLV_3_FIFO_EN_BIT 5 +#define MPU9250_I2C_MST_P_NSR_BIT 4 +#define MPU9250_I2C_MST_CLK_BIT 3 +#define MPU9250_I2C_MST_CLK_LENGTH 4 + +#define MPU9250_CLOCK_DIV_348 0x0 +#define MPU9250_CLOCK_DIV_333 0x1 +#define MPU9250_CLOCK_DIV_320 0x2 +#define MPU9250_CLOCK_DIV_308 0x3 +#define MPU9250_CLOCK_DIV_296 0x4 +#define MPU9250_CLOCK_DIV_286 0x5 +#define MPU9250_CLOCK_DIV_276 0x6 +#define MPU9250_CLOCK_DIV_267 0x7 +#define MPU9250_CLOCK_DIV_258 0x8 +#define MPU9250_CLOCK_DIV_500 0x9 +#define MPU9250_CLOCK_DIV_471 0xA +#define MPU9250_CLOCK_DIV_444 0xB +#define MPU9250_CLOCK_DIV_421 0xC +#define MPU9250_CLOCK_DIV_400 0xD +#define MPU9250_CLOCK_DIV_381 0xE +#define MPU9250_CLOCK_DIV_364 0xF + +#define MPU9250_I2C_SLV_RW_BIT 7 +#define MPU9250_I2C_SLV_ADDR_BIT 6 +#define MPU9250_I2C_SLV_ADDR_LENGTH 7 +#define MPU9250_I2C_SLV_EN_BIT 7 +#define MPU9250_I2C_SLV_BYTE_SW_BIT 6 +#define MPU9250_I2C_SLV_REG_DIS_BIT 5 +#define MPU9250_I2C_SLV_GRP_BIT 4 +#define MPU9250_I2C_SLV_LEN_BIT 3 +#define MPU9250_I2C_SLV_LEN_LENGTH 4 + +#define MPU9250_I2C_SLV4_RW_BIT 7 +#define MPU9250_I2C_SLV4_ADDR_BIT 6 +#define MPU9250_I2C_SLV4_ADDR_LENGTH 7 +#define MPU9250_I2C_SLV4_EN_BIT 7 +#define MPU9250_I2C_SLV4_INT_EN_BIT 6 +#define MPU9250_I2C_SLV4_REG_DIS_BIT 5 +#define MPU9250_I2C_SLV4_MST_DLY_BIT 4 +#define MPU9250_I2C_SLV4_MST_DLY_LENGTH 5 + +#define MPU9250_MST_PASS_THROUGH_BIT 7 +#define MPU9250_MST_I2C_SLV4_DONE_BIT 6 +#define MPU9250_MST_I2C_LOST_ARB_BIT 5 +#define MPU9250_MST_I2C_SLV4_NACK_BIT 4 +#define MPU9250_MST_I2C_SLV3_NACK_BIT 3 +#define MPU9250_MST_I2C_SLV2_NACK_BIT 2 +#define MPU9250_MST_I2C_SLV1_NACK_BIT 1 +#define MPU9250_MST_I2C_SLV0_NACK_BIT 0 + +#define MPU9250_INTCFG_INT_LEVEL_BIT 7 +#define MPU9250_INTCFG_INT_OPEN_BIT 6 +#define MPU9250_INTCFG_LATCH_INT_EN_BIT 5 +#define MPU9250_INTCFG_INT_RD_CLEAR_BIT 4 +#define MPU9250_INTCFG_FSYNC_INT_LEVEL_BIT 3 +#define MPU9250_INTCFG_FSYNC_INT_EN_BIT 2 +#define MPU9250_INTCFG_I2C_BYPASS_EN_BIT 1 +#define MPU9250_INTCFG_CLKOUT_EN_BIT 0 + +#define MPU9250_INTMODE_ACTIVEHIGH 0x00 +#define MPU9250_INTMODE_ACTIVELOW 0x01 + +#define MPU9250_INTDRV_PUSHPULL 0x00 +#define MPU9250_INTDRV_OPENDRAIN 0x01 + +#define MPU9250_INTLATCH_50USPULSE 0x00 +#define MPU9250_INTLATCH_WAITCLEAR 0x01 + +#define MPU9250_INTCLEAR_STATUSREAD 0x00 +#define MPU9250_INTCLEAR_ANYREAD 0x01 + +#define MPU9250_INTERRUPT_FF_BIT 7 +#define MPU9250_INTERRUPT_MOT_BIT 6 +#define MPU9250_INTERRUPT_ZMOT_BIT 5 +#define MPU9250_INTERRUPT_FIFO_OFLOW_BIT 4 +#define MPU9250_INTERRUPT_I2C_MST_INT_BIT 3 +#define MPU9250_INTERRUPT_PLL_RDY_INT_BIT 2 +#define MPU9250_INTERRUPT_DMP_INT_BIT 1 +#define MPU9250_INTERRUPT_DATA_RDY_BIT 0 + +#define MPU9250_MOTION_MOT_XNEG_BIT 7 +#define MPU9250_MOTION_MOT_XPOS_BIT 6 +#define MPU9250_MOTION_MOT_YNEG_BIT 5 +#define MPU9250_MOTION_MOT_YPOS_BIT 4 +#define MPU9250_MOTION_MOT_ZNEG_BIT 3 +#define MPU9250_MOTION_MOT_ZPOS_BIT 2 +#define MPU9250_MOTION_MOT_ZRMOT_BIT 0 + +#define MPU9250_DELAYCTRL_DELAY_ES_SHADOW_BIT 7 +#define MPU9250_DELAYCTRL_I2C_SLV4_DLY_EN_BIT 4 +#define MPU9250_DELAYCTRL_I2C_SLV3_DLY_EN_BIT 3 +#define MPU9250_DELAYCTRL_I2C_SLV2_DLY_EN_BIT 2 +#define MPU9250_DELAYCTRL_I2C_SLV1_DLY_EN_BIT 1 +#define MPU9250_DELAYCTRL_I2C_SLV0_DLY_EN_BIT 0 + +#define MPU9250_PATHRESET_GYRO_RESET_BIT 2 +#define MPU9250_PATHRESET_ACCEL_RESET_BIT 1 +#define MPU9250_PATHRESET_TEMP_RESET_BIT 0 + +#define MPU9250_DETECT_ACCEL_ON_DELAY_BIT 5 +#define MPU9250_DETECT_ACCEL_ON_DELAY_LENGTH 2 +#define MPU9250_DETECT_FF_COUNT_BIT 3 +#define MPU9250_DETECT_FF_COUNT_LENGTH 2 +#define MPU9250_DETECT_MOT_COUNT_BIT 1 +#define MPU9250_DETECT_MOT_COUNT_LENGTH 2 + +#define MPU9250_DETECT_DECREMENT_RESET 0x0 +#define MPU9250_DETECT_DECREMENT_1 0x1 +#define MPU9250_DETECT_DECREMENT_2 0x2 +#define MPU9250_DETECT_DECREMENT_4 0x3 + +#define MPU9250_USERCTRL_DMP_EN_BIT 7 +#define MPU9250_USERCTRL_FIFO_EN_BIT 6 +#define MPU9250_USERCTRL_I2C_MST_EN_BIT 5 +#define MPU9250_USERCTRL_I2C_IF_DIS_BIT 4 +#define MPU9250_USERCTRL_DMP_RESET_BIT 3 +#define MPU9250_USERCTRL_FIFO_RESET_BIT 2 +#define MPU9250_USERCTRL_I2C_MST_RESET_BIT 1 +#define MPU9250_USERCTRL_SIG_COND_RESET_BIT 0 + +#define MPU9250_PWR1_DEVICE_RESET_BIT 7 +#define MPU9250_PWR1_SLEEP_BIT 6 +#define MPU9250_PWR1_CYCLE_BIT 5 +#define MPU9250_PWR1_TEMP_DIS_BIT 3 +#define MPU9250_PWR1_CLKSEL_BIT 2 +#define MPU9250_PWR1_CLKSEL_LENGTH 3 + +#define MPU9250_CLOCK_INTERNAL 0x00 +#define MPU9250_CLOCK_PLL_XGYRO 0x01 +#define MPU9250_CLOCK_PLL_YGYRO 0x02 +#define MPU9250_CLOCK_PLL_ZGYRO 0x03 +#define MPU9250_CLOCK_PLL_EXT32K 0x04 +#define MPU9250_CLOCK_PLL_EXT19M 0x05 +#define MPU9250_CLOCK_KEEP_RESET 0x07 + +#define MPU9250_PWR2_LP_WAKE_CTRL_BIT 7 +#define MPU9250_PWR2_LP_WAKE_CTRL_LENGTH 2 +#define MPU9250_PWR2_STBY_XA_BIT 5 +#define MPU9250_PWR2_STBY_YA_BIT 4 +#define MPU9250_PWR2_STBY_ZA_BIT 3 +#define MPU9250_PWR2_STBY_XG_BIT 2 +#define MPU9250_PWR2_STBY_YG_BIT 1 +#define MPU9250_PWR2_STBY_ZG_BIT 0 + +#define MPU9250_WAKE_FREQ_1P25 0x0 +#define MPU9250_WAKE_FREQ_2P5 0x1 +#define MPU9250_WAKE_FREQ_5 0x2 +#define MPU9250_WAKE_FREQ_10 0x3 + +#define MPU9250_BANKSEL_PRFTCH_EN_BIT 6 +#define MPU9250_BANKSEL_CFG_USER_BANK_BIT 5 +#define MPU9250_BANKSEL_MEM_SEL_BIT 4 +#define MPU9250_BANKSEL_MEM_SEL_LENGTH 5 + +#define MPU9250_WHO_AM_I_BIT 6 +#define MPU9250_WHO_AM_I_LENGTH 8 + +#define MPU9250_DMP_MEMORY_BANKS 8 +#define MPU9250_DMP_MEMORY_BANK_SIZE 256 +#define MPU9250_DMP_MEMORY_CHUNK_SIZE 16 + diff --git a/firmwares/minetest/src/rv3029.c b/firmwares/minetest/src/rv3029.c new file mode 100644 index 0000000..3d72437 --- /dev/null +++ b/firmwares/minetest/src/rv3029.c @@ -0,0 +1,117 @@ +#include "ets_sys.h" +#include "osapi.h" + +#include "i2c_master.h" +#include "rv3029.h" + +#define BCD2BIN(val) ((((val) & 0x0f) + ((val) >> 4) * 10)) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +bool rv3029_read(uint8_t regaddr, uint8_t len, uint8_t *data) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(RV3029_ADDR_W); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for write addr\r\n"); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for register\r\n"); + i2c_master_stop(); + return false; + } + + i2c_master_stop(); + i2c_master_start(); + + // Write I²C Address for reading + i2c_master_writeByte(RV3029_ADDR_R); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for read addr\r\n"); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + data[i] = i2c_master_readByte(); + i2c_master_send_ack(); + } + + i2c_master_stop(); + + return true; +} + +bool rv3029_write(uint8_t regaddr, uint8_t len, uint8_t *data) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(RV3029_ADDR_W); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for write addr\r\n"); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for register\r\n"); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < len; ++i) { + i2c_master_writeByte(data[i]); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for datawrite\r\n"); + i2c_master_stop(); + return false; + } + } + + i2c_master_stop(); + + return true; +} + + +int8_t rv3029_temp() { + uint8_t temp; + if (rv3029_read(0x20, 1, &temp)) return (int8_t)temp - 60; + else return 255; +} + +bool rv3029_gettime(struct TimeSpec *time) { + uint8_t raw[7]; + if (!rv3029_read(0x08, 7, raw)) return false; + + time->seconds = BCD2BIN(raw[0]); + time->minutes = BCD2BIN(raw[1]); + time->hours = BCD2BIN(raw[2]); + time->date = BCD2BIN(raw[3]); + time->dow = raw[4]; + time->months = BCD2BIN(raw[5]); + time->years = BCD2BIN(raw[6]); + + return true; +} + +bool rv3029_settime(struct TimeSpec *time) { + uint8_t raw[7]; + raw[0] = BIN2BCD(time->seconds); + raw[1] = BIN2BCD(time->minutes); + raw[2] = BIN2BCD(time->hours); + raw[3] = BIN2BCD(time->date); + raw[4] = time->dow; + raw[5] = BIN2BCD(time->months); + raw[6] = BIN2BCD(time->years); + return rv3029_write(0x08, 7, raw); +} diff --git a/firmwares/minetest/src/rv3029.h b/firmwares/minetest/src/rv3029.h new file mode 100644 index 0000000..c65c438 --- /dev/null +++ b/firmwares/minetest/src/rv3029.h @@ -0,0 +1,30 @@ +#include + +#ifndef _RV3029_H +#define _RV3029_H + +// Configuration +#define RV3029_ADDR_W 0xAC +#define RV3029_ADDR_R 0xAD + +// 24-hour format only +// Years from 0 - 79, meaning 20xx +// Months from 1 - 12, dow from 1 - 7 +struct TimeSpec { + uint8_t seconds; + uint8_t minutes; + uint8_t hours; + uint8_t date; + uint8_t dow; + uint8_t months; + uint8_t years; +}; + +int8_t rv3029_temp(); +bool rv3029_gettime(struct TimeSpec *time); + +// Internal +bool rv3029_read(uint8_t regaddr, uint8_t len, uint8_t *val); +bool rv3029_write(uint8_t regaddr, uint8_t len, uint8_t *val); + +#endif diff --git a/firmwares/minetest/src/ssd1306.c b/firmwares/minetest/src/ssd1306.c new file mode 100644 index 0000000..2cf6a68 --- /dev/null +++ b/firmwares/minetest/src/ssd1306.c @@ -0,0 +1,310 @@ +#include +#include +#include +#include + +#include "user_config.h" +#include "i2c_master.h" +#include "ssd1306.h" +#include "util.h" +#include "font.h" + +#define CONTROL_CMD 0b00000000 +#define CONTROL_DATA 0b01000000 +#define SSD1306_PAGES 8 +#define SSD1306_WIDTH 128 + +uint8_t buf[SSD1306_PAGES][SSD1306_WIDTH]; +bool buf_changed[SSD1306_PAGES] = { false }; + +/** Internal commands **/ +void ICACHE_FLASH_ATTR ssd1306_putbyte(uint8_t byte) { + i2c_master_writeByte(byte); + if (i2c_master_getAck()) os_printf("SSD1306: No ACK for 0x%02x\r\n", byte); +} + +void ICACHE_FLASH_ATTR ssd1306_cmd(uint8_t cmd) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_CMD); + ssd1306_putbyte(cmd); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_data(uint8_t dat) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_DATA); + ssd1306_putbyte(dat); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_databurst(uint8_t *dat, uint32_t len) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_DATA); + uint32_t i; + for (i = 0; i < len; ++i) ssd1306_putbyte(dat[i]); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_cmdburst(uint8_t *dat, uint32_t len) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_CMD); + uint16_t i; + for (i = 0; i < len; ++i) ssd1306_putbyte(dat[i]); + i2c_master_stop(); +} + +/** Initialization **/ +void ICACHE_FLASH_ATTR ssd1306_init(uint8_t contrast) { + os_delay_us(10000); + + ssd1306_setaddressing(SSD1306_PAGE_ADDRESSING); + ssd1306_setstartline(0); + ssd1306_setstartpage(0); + ssd1306_setstartaddress(0); + ssd1306_setcontrast(contrast); + ssd1306_setglow(0); + ssd1306_setmirror_h(false); + ssd1306_setinverse(false); + ssd1306_setmultiplex(63); + ssd1306_setmirror_v(false); + ssd1306_setoffset(0); + ssd1306_setosc(0, 8); + ssd1306_setprecharge(2, 2); + ssd1306_setcomconfig(0x12); + ssd1306_setvcomh(0x40); + ssd1306_scroll_disable(); + ssd1306_vscroll_area(0, 64); + ssd1306_setblinkfade(SSD1306_BLINKFADE_OFF, 0); + ssd1306_setchargepump(true); + ssd1306_setonoff(true); +} + +/** Text output **/ +void ssd1306_text_small(uint8_t x, uint8_t y, char *text) { + uint16_t c = 0; + uint8_t page = y / 8; + while (text[c] != 0x00) { + uint8_t i; + for (i = 0; i < 6; ++i) { + uint16_t xpos = x + c * 6 + i; + if (xpos >= SSD1306_WIDTH) return; + uint8_t draw = font_small[text[c] - 0x20][i]; + + // The text may now span between two pages, so the bits have + // to be sperated for first and second page + uint8_t firstpage = (draw << y % 8); + uint8_t secondpage = (draw >> (8 - y % 8)); + + buf[page][xpos] |= firstpage; + buf_changed[page] = true; + if (y % 8) { + buf_changed[page + 1] = true; + buf[page + 1][xpos] |= secondpage; + } + } + c++; + } +} + +void ssd1306_text_large(uint8_t x, uint8_t y, char *text) { + uint16_t c = 0; + uint8_t page = y / 8; + while (text[c] != 0x00) { + uint8_t i; + for (i = 0; i < 8; ++i) { + uint16_t xpos = x + c * 8 + i; + if (xpos >= SSD1306_WIDTH) return; + uint16_t draw_firstpage = font_large[text[c] - 0x20][i]; + uint16_t draw_secondpage = font_large[text[c] - 0x20][i+8]; + + // The text may now span between two pages, so the bits have + // to be sperated for first and second page + uint8_t firstpage = draw_firstpage << (y % 8); + uint8_t secondpage = (draw_firstpage >> (8 - y % 8)) | (draw_secondpage << (y % 8)); + uint8_t thirdpage = draw_secondpage >> (8 - y % 8); + + buf_changed[page] = true; + buf_changed[page + 1] = true; + + buf[page][xpos] |= firstpage; + buf[page + 1][xpos] |= secondpage; + + if (y % 8) { + buf[page + 2][xpos] |= thirdpage; + buf_changed[page + 2] = true; + } + } + c++; + } +} + +/** Graphics **/ +void ICACHE_FLASH_ATTR ssd1306_setpixel(uint8_t x, uint8_t y, bool state) { + if (state) + sbi(buf[y / 8][x], y % 8); + else + cbi(buf[y / 8][x], y % 8); +} + +void ICACHE_FLASH_ATTR ssd1306_line(uint8_t startx, uint8_t starty, uint8_t endx, uint8_t endy, bool state) { + float x = startx; + float y = starty; + float max = abs(endx - startx) > abs(endy - starty) ? abs(endx - startx) : abs(endy - starty); + + while (((endx > startx) ? x < endx : x > endx) || ((endy > starty) ? y < endy : y > endy)) { + x += (endx - startx) / max; + y += (endy - starty) / max; + ssd1306_setpixel((uint8_t)x, (uint8_t)y, state); + } +} + +/** Buffer related **/ +void ICACHE_FLASH_ATTR ssd1306_fill(uint8_t content) { + uint8_t page = 0, col = 0; + for(page = 0; page < 8; page++) { + buf_changed[page] = true; + for(col = 0; col < SSD1306_WIDTH; col++) + buf[page][col] = content; + } +} + +void ICACHE_FLASH_ATTR ssd1306_clear(void) { + ssd1306_fill(0x00); +} + +// Requires page addressing mode +void ICACHE_FLASH_ATTR ssd1306_flip(void) { + // Some dummy commands, to make controller align timing for bursts + ssd1306_setglow(false); + ssd1306_scroll_disable(); + + uint8_t page; + for (page = 0; page < SSD1306_PAGES; page++) { + ssd1306_setstartaddress(0); + ssd1306_setstartpage(page); + ssd1306_databurst(buf[page], 128); + } +} + +/** Misc commands **/ +void ICACHE_FLASH_ATTR ssd1306_setcontrast(uint8_t contrast) { + ssd1306_cmd(0x81); + ssd1306_cmd(contrast); +} + +void ICACHE_FLASH_ATTR ssd1306_setonoff(bool on) { + ssd1306_cmd(0xAE + (on ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setaddressing(enum ssd1306_addr_mode mode) { + ssd1306_cmd(0x20); + ssd1306_cmd(mode); +} + +// startline from 0 - 63 +void ICACHE_FLASH_ATTR ssd1306_setstartline(uint8_t startline) { + ssd1306_cmd(0x40 + startline); +} + +// startpage from 0 - 7 +void ICACHE_FLASH_ATTR ssd1306_setstartpage(uint8_t startpage) { + ssd1306_cmd(0xB0 + startpage); +} + +// start address from 0 - 128 +void ICACHE_FLASH_ATTR ssd1306_setstartaddress(uint8_t address) { + ssd1306_cmd((0x10 | (address & 0xf0) >> 4)); + ssd1306_cmd(0x01 | (address & 0x0f)); +} + +void ICACHE_FLASH_ATTR ssd1306_setmirror_h(bool mirror) { + ssd1306_cmd(0xA0 + (mirror ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setmirror_v(bool mirror) { + ssd1306_cmd(0xC0 + (mirror ? 8 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setinverse(bool inverse) { + ssd1306_cmd(0xA6 + (inverse ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setoffset(uint8_t x) { + ssd1306_cmd(0xD3); + ssd1306_cmd(x); +} + +// division ration from 0 - 15, fosc from 0 - 15, see datasheet section 8.3 +// "Oscillator Circuit and Display Time Generator" +void ICACHE_FLASH_ATTR ssd1306_setosc(uint8_t divratio, uint8_t fosc) { + ssd1306_cmd(0xD5); + ssd1306_cmd(divratio | (fosc << 4)); +} + +void ICACHE_FLASH_ATTR ssd1306_setprecharge(uint8_t period_phase1, uint8_t period_phase2) { + ssd1306_cmd(0xD9); + ssd1306_cmd(period_phase1 | (period_phase2 << 4)); +} + +// Refer to datasheet section 10.1.18 for more information +// configures connection of panel to controller +void ICACHE_FLASH_ATTR ssd1306_setcomconfig(uint8_t comconfig) { + ssd1306_cmd(0xDA); + ssd1306_cmd(comconfig); +} + +// level is either 0x00 (0.65 * Vcc), 0x40 (0.77 * Vcc, default), 0x60 (0.83 * Vcc) +void ICACHE_FLASH_ATTR ssd1306_setvcomh(uint8_t level) { + ssd1306_cmd(0xDB); + ssd1306_cmd(level); +} + +void ICACHE_FLASH_ATTR ssd1306_setchargepump(bool enable) { + ssd1306_cmd(0x8D); + ssd1306_cmd(enable ? 0x14 : 0x10); +} + +// multiplex from 15- 63 +void ICACHE_FLASH_ATTR ssd1306_setmultiplex(uint8_t multiplex) { + ssd1306_cmd(0xA8); + ssd1306_cmd(multiplex); +} + +/** Fading and Blinking **/ +// Turns all pixels on (or disables this feature) +void ICACHE_FLASH_ATTR ssd1306_setglow(bool enable) { + ssd1306_cmd(0xA4 + (enable ? 1 : 0)); +} + +// Speed 0 - 15 +void ICACHE_FLASH_ATTR ssd1306_setblinkfade(enum ssd1306_blinkfade_mode mode, uint8_t time) { + ssd1306_cmd(0x23); + ssd1306_cmd((mode << 4) | time); +} + + +/** Scrolling **/ +void ICACHE_FLASH_ATTR ssd1306_scroll(enum ssd1306_scroll_dir direction, uint8_t startpage, uint8_t endpage, + enum ssd1306_scroll_frequency freq, uint8_t voffset) { + ssd1306_cmd(0x29 + direction); + ssd1306_cmd(0x00); + ssd1306_cmd(startpage); + ssd1306_cmd(freq); + ssd1306_cmd(endpage); + ssd1306_cmd(voffset); + ssd1306_cmd(0x2f); +} + +void ICACHE_FLASH_ATTR ssd1306_vscroll_area(uint8_t fixedrows, uint8_t scrollrows) { + ssd1306_cmd(0xa3); + ssd1306_cmd(fixedrows); + ssd1306_cmd(scrollrows); +} + +void ICACHE_FLASH_ATTR ssd1306_scroll_disable() { + ssd1306_cmd(0x2e); +} diff --git a/firmwares/minetest/src/ssd1306.h b/firmwares/minetest/src/ssd1306.h new file mode 100644 index 0000000..cab3ef5 --- /dev/null +++ b/firmwares/minetest/src/ssd1306.h @@ -0,0 +1,90 @@ +#include + +#ifndef _SSD1306_H +#define _SSD1306_H + +// Configuration +#define SSD1306_ADDR 0x78 + +/** Internal commands **/ +void ssd1306_cmd(uint8_t cmd); +void ssd1306_data(uint8_t dat); +void ssd1306_databurst(uint8_t *dat, uint32_t len); +void ssd1306_cmdburst(uint8_t *dat, uint32_t len); + +/** Initialization **/ +void ssd1306_init(uint8_t contrast); + +/** Text output **/ +void ssd1306_text_small(uint8_t x, uint8_t y, char *text); +void ssd1306_text_large(uint8_t x, uint8_t y, char *text); + +/** Graphics **/ +void ssd1306_setpixel(uint8_t x, uint8_t y, bool state); +void ssd1306_line(uint8_t startx, uint8_t starty, uint8_t endx, uint8_t endy, bool state); + +/** Buffer related **/ +void ssd1306_fill(uint8_t content); +void ssd1306_clear(void); +void ssd1306_flip(void); + +/** Addressing modes **/ +enum ssd1306_addr_mode { + SSD1306_HORIZONTAL_ADDRESSING = 0, + SSD1306_VERTICAL_ADDRESSING = 1, + SSD1306_PAGE_ADDRESSING = 2 +}; + +/** Scroll directions and frequency **/ +enum ssd1306_scroll_dir { + SSD1306_SCROLL_RIGHT = 0, + SSD1306_SCROLL_LEFT = 1 +}; + +enum ssd1306_scroll_frequency { + SSD1306_SCROLLFREQ_5 = 0b000, + SSD1306_SCROLLFREQ_64 = 0b001, + SSD1306_SCROLLFREQ_128 = 0b010, + SSD1306_SCROLLFREQ_256 = 0b011, + SSD1306_SCROLLFREQ_3 = 0b100, + SSD1306_SCROLLFREQ_4 = 0b101, + SSD1306_SCROLLFREQ_25 = 0b110, + SSD1306_SCROLLFREQ_2 = 0b111 +}; + +/** Blinking / fading modes **/ +enum ssd1306_blinkfade_mode { + SSD1306_BLINKFADE_OFF = 0b00, + SSD1306_BLINKFADE_FADE = 0b10, + SSD1306_BLINKFADE_BLINK = 0b11 +}; + +/** Misc commands **/ +void ssd1306_setcontrast(uint8_t contrast); +void ssd1306_setonoff(bool on); +void ssd1306_setaddressing(enum ssd1306_addr_mode mode); +void ssd1306_setstartline(uint8_t startline); +void ssd1306_setstartpage(uint8_t startpage); +void ssd1306_setstartaddress(uint8_t address); +void ssd1306_setmirror_h(bool mirror); +void ssd1306_setmirror_v(bool mirror); +void ssd1306_setinverse(bool inverse); +void ssd1306_setoffset(uint8_t x); +void ssd1306_setosc(uint8_t divratio, uint8_t fosc); +void ssd1306_setprecharge(uint8_t period_phase1, uint8_t period_phase2); +void ssd1306_setcomconfig(uint8_t comconfig); +void ssd1306_setvcomh(uint8_t level); +void ssd1306_setchargepump(bool enable); +void ssd1306_setmultiplex(uint8_t multiplex); + +/** Fading and Blinking **/ +void ssd1306_setglow(bool enable); +void ssd1306_setblinkfade(enum ssd1306_blinkfade_mode mode, uint8_t time); + +/** Scrolling **/ +void ssd1306_scroll(enum ssd1306_scroll_dir direction, uint8_t startpage, uint8_t endpage, + enum ssd1306_scroll_frequency freq, uint8_t voffset); +void ssd1306_vscroll_area(uint8_t fixedrows, uint8_t scrollrows); +void ssd1306_scroll_disable(); + +#endif diff --git a/firmwares/minetest/src/user_config.h b/firmwares/minetest/src/user_config.h new file mode 100644 index 0000000..1859836 --- /dev/null +++ b/firmwares/minetest/src/user_config.h @@ -0,0 +1,5 @@ +#define BAUD 1000000 + +// Battery voltage measurement divisor - pullup & pulldown resistor proportions +#define VOLT_DIV_UP 330 +#define VOLT_DIV_DOWN 100 diff --git a/firmwares/minetest/src/util.c b/firmwares/minetest/src/util.c new file mode 100644 index 0000000..1fa6201 --- /dev/null +++ b/firmwares/minetest/src/util.c @@ -0,0 +1,26 @@ +// System +#include +#include +#include +#include +#include + +// Configuration +#include "user_config.h" + +// Project +#include "i2c_master.h" +#include "util.h" + +void i2c_scanbus() { + // Scan I²C Bus + os_printf("\r\n=== Scanning I²C Bus ===\r\n"); + uint8_t i; + for (i = 0; i < 0xff; ++i) { + i2c_master_start(); + i2c_master_writeByte(i); + if (!i2c_master_getAck()) os_printf("ACK for address: 0x%02x\r\n", i); + i2c_master_stop(); + } + os_printf("========================\r\n\r\n"); +} diff --git a/firmwares/minetest/src/util.h b/firmwares/minetest/src/util.h new file mode 100644 index 0000000..9eba195 --- /dev/null +++ b/firmwares/minetest/src/util.h @@ -0,0 +1,16 @@ +#ifndef _UTIL_H +#define _UTIL_H + +// Bit manipulation: Set / clear / get / toggle bit +#define sbi(ADDR, BIT) ((ADDR |= (1< + +// Project +#include "vector.h" + +angles2f ICACHE_FLASH_ATTR vec3f_to_angles2f(vec3f v) { + angles2f ret; + ret.yaw = atan2(v.y, v.x); + ret.pitch = atan2(v.z, sqrt((v.x * v.x) + (v.y * v.y))); + return ret; +} + +angles2f ICACHE_FLASH_ATTR vec3s16_to_angles2f(vec3s16 v) { + angles2f ret; + ret.yaw = atan2(v.y, v.x); + ret.pitch = atan2(v.z, sqrt((v.x * v.x) + (v.y * v.y))); + return ret; +} diff --git a/firmwares/minetest/src/vector.h b/firmwares/minetest/src/vector.h new file mode 100644 index 0000000..b9dab8c --- /dev/null +++ b/firmwares/minetest/src/vector.h @@ -0,0 +1,29 @@ +#include + +#ifndef _VECTOR_H +#define _VECTOR_H + +struct _vec3s16_t { + int16_t x; + int16_t y; + int16_t z; +}; +typedef struct _vec3s16_t vec3s16; + +struct _vec3f_t { + float x; + float y; + float z; +}; +typedef struct _vec3f_t vec3f; + +struct _angles2f_t { + float pitch; + float yaw; +}; +typedef struct _angles2f_t angles2f; + +angles2f vec3f_to_angles2f(vec3f v); +angles2f vec3s16_to_angles2f(vec3s16 v); + +#endif diff --git a/firmwares/wifitime/.gitignore b/firmwares/wifitime/.gitignore new file mode 100644 index 0000000..722a501 --- /dev/null +++ b/firmwares/wifitime/.gitignore @@ -0,0 +1,2 @@ +build/ +obj/ diff --git a/firmwares/wifitime/Makefile b/firmwares/wifitime/Makefile new file mode 100644 index 0000000..5a30a27 --- /dev/null +++ b/firmwares/wifitime/Makefile @@ -0,0 +1,63 @@ +# Esptool firmware download options +PORT := /dev/ttyUSB0 +BAUD := 1000000 + +# Directory structure +BUILDDIR := build +SRCDIR := src +OBJDIR := obj + +SRCS := $(wildcard $(SRCDIR)/*.c) +OBJS := $(addprefix $(OBJDIR)/,$(notdir $(SRCS:.c=.o))) +DEPS := $(addprefix $(OBJDIR),$(notdir $(SRCS:.c=.d))) + +# SDK / Compiler settings +SDK_DIR := /opt/esp-open-sdk/esp_iot_sdk_v1.5.0 +CC := xtensa-lx106-elf-gcc +LD := xtensa-lx106-elf-gcc +ESPTOOL := esptool.py +CFLAGS := -Os -fdata-sections -ffunction-sections -Wpointer-arith -Wall -Wno-parentheses -Wno-implicit-function-declaration -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -DICACHE_FLASH +LDLIBS := -nostdlib -Wl,--gc-sections -Wl,--no-check-sections -u call_user_start -Wl,-static -Wl,--start-group -lc -lgcc -lhal -lphy -lpp -lnet80211 -lwpa -lcrypto -lmain -llwip $(OBJS) -Wl,--end-group +LDFLAGS := -Os -T$(SDK_DIR)/ld/eagle.app.v6.ld +INCLUDES := -I $(SDK_DIR)/include -I $(SDK_DIR)/include/json -I $(SRCDIR)/ + +# Project settings +TARGET := handgelenk +FLASH_FREQ := 80m +FLASH_MODE := qio +FLASH_SIZE := 32m +FLASH_OPT := --flash_freq $(FLASH_FREQ) --flash_mode $(FLASH_MODE) --flash_size $(FLASH_SIZE) + +TARGET_ELF := $(BUILDDIR)/$(TARGET).elf +TARGET_FLASH := $(BUILDDIR)/$(TARGET)-0x00000.bin +TARGET_IROM := $(BUILDDIR)/$(TARGET)-0x40000.bin + +all: $(OBJDIR) $(BUILDDIR) $(TARGET_FLASH) $(TARGET_IROM) + @echo Compilation successful + @echo Use \'make flash\' to flash firmware + +$(TARGET_FLASH) $(TARGET_IROM): $(TARGET_ELF) + $(ESPTOOL) elf2image $(FLASH_OPT) $^ --output $(BUILDDIR)/$(TARGET)- + +$(TARGET_ELF): $(OBJS) + $(LD) -L$(SDK_DIR)/lib $(LDFLAGS) $(LDLIBS) -o $@ + +$(OBJDIR)/%.o: $(SRCDIR)/%.c + $(CC) $(CFLAGS) $(INCLUDES) -MMD -MP -c $< -o $@ + +$(OBJDIR): + mkdir -p $(OBJDIR) + +$(BUILDDIR): + mkdir -p $(BUILDDIR) + +flash: all + $(ESPTOOL) --port $(PORT) --baud $(BAUD) write_flash $(FLASH_OPT) 0x00000 $(TARGET_FLASH) 0x40000 $(TARGET_IROM) + +.PHONY: clean + +clean: + $(RM) -r $(OBJDIR) + $(RM) -r $(BUILDDIR) + +-include $(DEPS) diff --git a/firmwares/wifitime/src/font.h b/firmwares/wifitime/src/font.h new file mode 100644 index 0000000..fe9d9ca --- /dev/null +++ b/firmwares/wifitime/src/font.h @@ -0,0 +1,199 @@ +#ifndef _FONT_H +#define _FONT_H + +const unsigned char font_small[][6] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space + { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! + { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // " + { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # + { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ + { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // % + { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // & + { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( + { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) + { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * + { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // , + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // - + { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // . + { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // / + { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 + { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 + { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 + { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 + { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 + { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 + { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 + { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 + { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 + { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 + { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; + { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // < + { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // = + { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // > + { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? + { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ + { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C + { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F + { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G + { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H + { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I + { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J + { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K + { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L + { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M + { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P + { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q + { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R + { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S + { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T + { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U + { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V + { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W + { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X + { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y + { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z + { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ + { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // backslash + { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] + { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ + { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ + { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' + { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a + { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c + { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d + { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e + { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f + { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g + { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h + { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i + { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j + { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k + { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l + { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o + { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p + { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r + { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s + { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t + { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u + { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v + { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w + { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x + { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y + { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z + { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }, // horizontal lines +}; + +const unsigned char font_large[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // space + { 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x30, 0x00, 0x00, 0x00 }, // ! + { 0x00, 0x10, 0x0C, 0x06, 0x10, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // " + { 0x40, 0xC0, 0x78, 0x40, 0xC0, 0x78, 0x40, 0x00, 0x04, 0x3F, 0x04, 0x04, 0x3F, 0x04, 0x04, 0x00 }, // # + { 0x00, 0x70, 0x88, 0xFC, 0x08, 0x30, 0x00, 0x00, 0x00, 0x18, 0x20, 0xFF, 0x21, 0x1E, 0x00, 0x00 }, // $ + { 0xF0, 0x08, 0xF0, 0x00, 0xE0, 0x18, 0x00, 0x00, 0x00, 0x21, 0x1C, 0x03, 0x1E, 0x21, 0x1E, 0x00 }, // % + { 0x00, 0xF0, 0x08, 0x88, 0x70, 0x00, 0x00, 0x00, 0x1E, 0x21, 0x23, 0x24, 0x19, 0x27, 0x21, 0x10 }, // & + { 0x10, 0x16, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x00, 0xE0, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, 0x20, 0x40, 0x00 }, // ( + { 0x00, 0x02, 0x04, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x07, 0x00, 0x00, 0x00 }, // ) + { 0x40, 0x40, 0x80, 0xF0, 0x80, 0x40, 0x40, 0x00, 0x02, 0x02, 0x01, 0x0F, 0x01, 0x02, 0x02, 0x00 }, // * + { 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x1F, 0x01, 0x01, 0x01, 0x00 }, // + + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xB0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00 }, // , + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, // - + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00 }, // . + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x18, 0x04, 0x00, 0x60, 0x18, 0x06, 0x01, 0x00, 0x00, 0x00 }, // / + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // 0 + { 0x00, 0x10, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // 1 + { 0x00, 0x70, 0x08, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x30, 0x28, 0x24, 0x22, 0x21, 0x30, 0x00 }, // 2 + { 0x00, 0x30, 0x08, 0x88, 0x88, 0x48, 0x30, 0x00, 0x00, 0x18, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 3 + { 0x00, 0x00, 0xC0, 0x20, 0x10, 0xF8, 0x00, 0x00, 0x00, 0x07, 0x04, 0x24, 0x24, 0x3F, 0x24, 0x00 }, // 4 + { 0x00, 0xF8, 0x08, 0x88, 0x88, 0x08, 0x08, 0x00, 0x00, 0x19, 0x21, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 5 + { 0x00, 0xE0, 0x10, 0x88, 0x88, 0x18, 0x00, 0x00, 0x00, 0x0F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // 6 + { 0x00, 0x38, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00 }, // 7 + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00, 0x1C, 0x22, 0x21, 0x21, 0x22, 0x1C, 0x00 }, // 8 + { 0x00, 0xE0, 0x10, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x00, 0x00, 0x31, 0x22, 0x22, 0x11, 0x0F, 0x00 }, // 9 + { 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x00, 0x00 }, // ; + { 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00 }, // < + { 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00 }, // = + { 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00 }, // > + { 0x00, 0x70, 0x48, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x36, 0x01, 0x00, 0x00 }, // ? + { 0xC0, 0x30, 0xC8, 0x28, 0xE8, 0x10, 0xE0, 0x00, 0x07, 0x18, 0x27, 0x24, 0x23, 0x14, 0x0B, 0x00 }, // @ + { 0x00, 0x00, 0xC0, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x20, 0x3C, 0x23, 0x02, 0x02, 0x27, 0x38, 0x20 }, // A + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // B + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x07, 0x18, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00 }, // C + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // D + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x23, 0x20, 0x18, 0x00 }, // E + { 0x08, 0xF8, 0x88, 0x88, 0xE8, 0x08, 0x10, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x00, 0x00, 0x00 }, // F + { 0xC0, 0x30, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x07, 0x18, 0x20, 0x20, 0x22, 0x1E, 0x02, 0x00 }, // G + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x21, 0x3F, 0x20 }, // H + { 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // I + { 0x00, 0x00, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00, 0x00 }, // J + { 0x08, 0xF8, 0x88, 0xC0, 0x28, 0x18, 0x08, 0x00, 0x20, 0x3F, 0x20, 0x01, 0x26, 0x38, 0x20, 0x00 }, // K + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x20, 0x20, 0x20, 0x30, 0x00 }, // L + { 0x08, 0xF8, 0xF8, 0x00, 0xF8, 0xF8, 0x08, 0x00, 0x20, 0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x20, 0x00 }, // M + { 0x08, 0xF8, 0x30, 0xC0, 0x00, 0x08, 0xF8, 0x08, 0x20, 0x3F, 0x20, 0x00, 0x07, 0x18, 0x3F, 0x00 }, // N + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x10, 0x20, 0x20, 0x20, 0x10, 0x0F, 0x00 }, // O + { 0x08, 0xF8, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x00, 0x20, 0x3F, 0x21, 0x01, 0x01, 0x01, 0x00, 0x00 }, // P + { 0xE0, 0x10, 0x08, 0x08, 0x08, 0x10, 0xE0, 0x00, 0x0F, 0x18, 0x24, 0x24, 0x38, 0x50, 0x4F, 0x00 }, // Q + { 0x08, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x03, 0x0C, 0x30, 0x20 }, // R + { 0x00, 0x70, 0x88, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x38, 0x20, 0x21, 0x21, 0x22, 0x1C, 0x00 }, // S + { 0x18, 0x08, 0x08, 0xF8, 0x08, 0x08, 0x18, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, // T + { 0x08, 0xF8, 0x08, 0x00, 0x00, 0x08, 0xF8, 0x08, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, // U + { 0x08, 0x78, 0x88, 0x00, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x07, 0x38, 0x0E, 0x01, 0x00, 0x00 }, // V + { 0xF8, 0x08, 0x00, 0xF8, 0x00, 0x08, 0xF8, 0x00, 0x03, 0x3C, 0x07, 0x00, 0x07, 0x3C, 0x03, 0x00 }, // W + { 0x08, 0x18, 0x68, 0x80, 0x80, 0x68, 0x18, 0x08, 0x20, 0x30, 0x2C, 0x03, 0x03, 0x2C, 0x30, 0x20 }, // X + { 0x08, 0x38, 0xC8, 0x00, 0xC8, 0x38, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x00, 0x00 }, // Y + { 0x10, 0x08, 0x08, 0x08, 0xC8, 0x38, 0x08, 0x00, 0x20, 0x38, 0x26, 0x21, 0x20, 0x20, 0x18, 0x00 }, // Z + { 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x40, 0x40, 0x40, 0x00 }, // [ + { 0x00, 0x0C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x38, 0xC0, 0x00 }, // backslash + { 0x00, 0x02, 0x02, 0x02, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x7F, 0x00, 0x00, 0x00 }, // ] + { 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ^ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, // _ + { 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ` + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x19, 0x24, 0x22, 0x22, 0x22, 0x3F, 0x20 }, // a + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x11, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // b + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x20, 0x11, 0x00 }, // c + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x88, 0xF8, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0x10, 0x3F, 0x20 }, // d + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x22, 0x22, 0x22, 0x22, 0x13, 0x00 }, // e + { 0x00, 0x80, 0x80, 0xF0, 0x88, 0x88, 0x88, 0x18, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // f + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x6B, 0x94, 0x94, 0x94, 0x93, 0x60, 0x00 }, // g + { 0x08, 0xF8, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, // h + { 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // i + { 0x00, 0x00, 0x00, 0x80, 0x98, 0x98, 0x00, 0x00, 0x00, 0xC0, 0x80, 0x80, 0x80, 0x7F, 0x00, 0x00 }, // j + { 0x08, 0xF8, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x24, 0x02, 0x2D, 0x30, 0x20, 0x00 }, // k + { 0x00, 0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x3F, 0x20, 0x20, 0x00, 0x00 }, // l + { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x20, 0x3F, 0x20, 0x00, 0x3F, 0x20, 0x00, 0x3F }, // m + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x3F, 0x21, 0x00, 0x00, 0x20, 0x3F, 0x20 }, // n + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x20, 0x1F, 0x00 }, // o + { 0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xA1, 0x20, 0x20, 0x11, 0x0E, 0x00 }, // p + { 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x0E, 0x11, 0x20, 0x20, 0xA0, 0xFF, 0x80 }, // q + { 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x20, 0x20, 0x3F, 0x21, 0x20, 0x00, 0x01, 0x00 }, // r + { 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x33, 0x24, 0x24, 0x24, 0x24, 0x19, 0x00 }, // s + { 0x00, 0x80, 0x80, 0xE0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x00, 0x00 }, // t + { 0x80, 0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x1F, 0x20, 0x20, 0x20, 0x10, 0x3F, 0x20 }, // u + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x0E, 0x30, 0x08, 0x06, 0x01, 0x00 }, // v + { 0x80, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, 0x0F, 0x30, 0x0C, 0x03, 0x0C, 0x30, 0x0F, 0x00 }, // w + { 0x00, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x20, 0x31, 0x2E, 0x0E, 0x31, 0x20, 0x00 }, // x + { 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x81, 0x8E, 0x70, 0x18, 0x06, 0x01, 0x00 }, // y + { 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x21, 0x30, 0x2C, 0x22, 0x21, 0x30, 0x00 }, // z + { 0x00, 0x00, 0x00, 0x00, 0x80, 0x7C, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x40, 0x40 }, // { + { 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00 }, // | + { 0x00, 0x02, 0x02, 0x7C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x3F, 0x00, 0x00, 0x00, 0x00 }, // } + { 0x00, 0x06, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // ~ +}; + +#endif diff --git a/firmwares/wifitime/src/httpclient.c b/firmwares/wifitime/src/httpclient.c new file mode 100644 index 0000000..96a48c9 --- /dev/null +++ b/firmwares/wifitime/src/httpclient.c @@ -0,0 +1,483 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Martin d'Allens wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +// FIXME: sprintf->snprintf everywhere. +// FIXME: support null characters in responses. + +#include "osapi.h" +#include "user_interface.h" +#include "espconn.h" +#include "mem.h" +#include "limits.h" +#include "httpclient.h" + + +// Debug output. +#if 0 +#define PRINTF(...) os_printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +// Internal state. +typedef struct { + char * path; + int port; + char * post_data; + char * headers; + char * hostname; + char * buffer; + int buffer_size; + http_callback user_callback; +} request_args; + +static char * ICACHE_FLASH_ATTR esp_strdup(const char * str) +{ + if (str == NULL) { + return NULL; + } + char * new_str = (char *)os_malloc(os_strlen(str) + 1); // 1 for null character + if (new_str == NULL) { + os_printf("esp_strdup: malloc error"); + return NULL; + } + os_strcpy(new_str, str); + return new_str; +} + +static int ICACHE_FLASH_ATTR +esp_isupper(char c) +{ + return (c >= 'A' && c <= 'Z'); +} + +static int ICACHE_FLASH_ATTR +esp_isalpha(char c) +{ + return ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); +} + + +static int ICACHE_FLASH_ATTR +esp_isspace(char c) +{ + return (c == ' ' || c == '\t' || c == '\n' || c == '\12'); +} + +static int ICACHE_FLASH_ATTR +esp_isdigit(char c) +{ + return (c >= '0' && c <= '9'); +} + +/* + * Convert a string to a long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long ICACHE_FLASH_ATTR +esp_strtol(nptr, endptr, base) + const char *nptr; + char **endptr; + int base; +{ + const char *s = nptr; + unsigned long acc; + int c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + do { + c = *s++; + } while (esp_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } else if ((base == 0 || base == 2) && + c == '0' && (*s == 'b' || *s == 'B')) { + c = s[1]; + s += 2; + base = 2; + } + if (base == 0) + base = c == '0' ? 8 : 10; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set any if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; + cutlim = cutoff % (unsigned long)base; + cutoff /= (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (esp_isdigit(c)) + c -= '0'; + else if (esp_isalpha(c)) + c -= esp_isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; +// errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + +static int ICACHE_FLASH_ATTR chunked_decode(const char * chunked, char * decode) +{ + int i = 0, j = 0; + int decode_size = 0; + char *str = (char *)chunked; + do + { + char * endstr = NULL; + //[chunk-size] + i = esp_strtol(str + j, endstr, 16); + PRINTF("Chunk Size:%d\r\n", i); + if (i <= 0) + break; + //[chunk-size-end-ptr] + endstr = (char *)os_strstr(str + j, "\r\n"); + //[chunk-ext] + j += endstr - (str + j); + //[CRLF] + j += 2; + //[chunk-data] + decode_size += i; + os_memcpy((char *)&decode[decode_size - i], (char *)str + j, i); + j += i; + //[CRLF] + j += 2; + } while(true); + + // + //footer CRLF + // + + return j; +} + +static void ICACHE_FLASH_ATTR receive_callback(void * arg, char * buf, unsigned short len) +{ + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + if (req->buffer == NULL) { + return; + } + + // Let's do the equivalent of a realloc(). + const int new_size = req->buffer_size + len; + char * new_buffer; + if (new_size > BUFFER_SIZE_MAX || NULL == (new_buffer = (char *)os_malloc(new_size))) { + os_printf("Response too long (%d)\n", new_size); + req->buffer[0] = '\0'; // Discard the buffer to avoid using an incomplete response. + espconn_disconnect(conn); + return; // The disconnect callback will be called. + } + + os_memcpy(new_buffer, req->buffer, req->buffer_size); + os_memcpy(new_buffer + req->buffer_size - 1 /*overwrite the null character*/, buf, len); // Append new data. + new_buffer[new_size - 1] = '\0'; // Make sure there is an end of string. + + os_free(req->buffer); + req->buffer = new_buffer; + req->buffer_size = new_size; +} + +static void ICACHE_FLASH_ATTR sent_callback(void * arg) +{ + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + if (req->post_data == NULL) { + PRINTF("All sent\n"); + } + else { + // The headers were sent, now send the contents. + PRINTF("Sending request body\n"); + espconn_sent(conn, (uint8_t *)req->post_data, strlen(req->post_data)); + os_free(req->post_data); + req->post_data = NULL; + } +} + +static void ICACHE_FLASH_ATTR connect_callback(void * arg) +{ + PRINTF("Connected\n"); + struct espconn * conn = (struct espconn *)arg; + request_args * req = (request_args *)conn->reverse; + + espconn_regist_recvcb(conn, receive_callback); + espconn_regist_sentcb(conn, sent_callback); + + const char * method = "GET"; + char post_headers[32] = ""; + + if (req->post_data != NULL) { // If there is data this is a POST request. + method = "POST"; + os_sprintf(post_headers, "Content-Length: %d\r\n", strlen(req->post_data)); + } + + char buf[69 + strlen(method) + strlen(req->path) + strlen(req->hostname) + + strlen(req->headers) + strlen(post_headers)]; + int len = os_sprintf(buf, + "%s %s HTTP/1.1\r\n" + "Host: %s:%d\r\n" + "Connection: close\r\n" + "User-Agent: ESP8266\r\n" + "%s" + "%s" + "\r\n", + method, req->path, req->hostname, req->port, req->headers, post_headers); + + espconn_sent(conn, (uint8_t *)buf, len); + os_free(req->headers); + req->headers = NULL; + PRINTF("Sending request header\n"); +} + +static void ICACHE_FLASH_ATTR disconnect_callback(void * arg) +{ + PRINTF("Disconnected\n"); + struct espconn *conn = (struct espconn *)arg; + + if(conn == NULL) { + return; + } + + if(conn->proto.tcp != NULL) { + os_free(conn->proto.tcp); + } + if(conn->reverse != NULL) { + request_args * req = (request_args *)conn->reverse; + int http_status = -1; + char * body = ""; + if (req->buffer == NULL) { + os_printf("Buffer shouldn't be NULL\n"); + } + else if (req->buffer[0] != '\0') { + // FIXME: make sure this is not a partial response, using the Content-Length header. + + const char * version = "HTTP/1.1 "; + if (os_strncmp(req->buffer, version, strlen(version)) != 0) { + os_printf("Invalid version in %s\n", req->buffer); + } + else { + http_status = atoi(req->buffer + strlen(version)); + body = (char *)os_strstr(req->buffer, "\r\n\r\n") + 4; + if(os_strstr(req->buffer, "Transfer-Encoding: chunked")) + { + int body_size = req->buffer_size - (body - req->buffer); + char chunked_decode_buffer[body_size]; + os_memset(chunked_decode_buffer, 0, body_size); + // Chuncked data + chunked_decode(body, chunked_decode_buffer); + os_memcpy(body, chunked_decode_buffer, body_size); + } + } + } + + if (req->user_callback != NULL) { // Callback is optional. + req->user_callback(body, http_status, req->buffer); + } + + os_free(req->buffer); + os_free(req->hostname); + os_free(req->path); + os_free(req); + } + os_free(conn); +} + +static void ICACHE_FLASH_ATTR error_callback(void *arg, sint8 errType) +{ + PRINTF("Disconnected with error\n"); + disconnect_callback(arg); +} + +static void ICACHE_FLASH_ATTR dns_callback(const char * hostname, ip_addr_t * addr, void * arg) +{ + request_args * req = (request_args *)arg; + + if (addr == NULL) { + os_printf("DNS failed for %s\n", hostname); + if (req->user_callback != NULL) { + req->user_callback("", -1, ""); + } + os_free(req); + } + else { + PRINTF("DNS found %s " IPSTR "\n", hostname, IP2STR(addr)); + + struct espconn * conn = (struct espconn *)os_malloc(sizeof(struct espconn)); + conn->type = ESPCONN_TCP; + conn->state = ESPCONN_NONE; + conn->proto.tcp = (esp_tcp *)os_malloc(sizeof(esp_tcp)); + conn->proto.tcp->local_port = espconn_port(); + conn->proto.tcp->remote_port = req->port; + conn->reverse = req; + + os_memcpy(conn->proto.tcp->remote_ip, addr, 4); + + espconn_regist_connectcb(conn, connect_callback); + espconn_regist_disconcb(conn, disconnect_callback); + espconn_regist_reconcb(conn, error_callback); + + espconn_connect(conn); + } +} + +void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, const char * headers, http_callback user_callback) +{ + PRINTF("DNS request\n"); + + request_args * req = (request_args *)os_malloc(sizeof(request_args)); + req->hostname = esp_strdup(hostname); + req->path = esp_strdup(path); + req->port = port; + req->headers = esp_strdup(headers); + req->post_data = esp_strdup(post_data); + req->buffer_size = 1; + req->buffer = (char *)os_malloc(1); + req->buffer[0] = '\0'; // Empty string. + req->user_callback = user_callback; + + ip_addr_t addr; + err_t error = espconn_gethostbyname((struct espconn *)req, // It seems we don't need a real espconn pointer here. + hostname, &addr, dns_callback); + + if (error == ESPCONN_INPROGRESS) { + PRINTF("DNS pending\n"); + } + else if (error == ESPCONN_OK) { + // Already in the local names table (or hostname was an IP address), execute the callback ourselves. + dns_callback(hostname, &addr, req); + } + else { + if (error == ESPCONN_ARG) { + os_printf("DNS arg error %s\n", hostname); + } + else { + os_printf("DNS error code %d\n", error); + } + dns_callback(hostname, NULL, req); // Handle all DNS errors the same way. + } +} + +/* + * Parse an URL of the form http://host:port/path + * can be a hostname or an IP address + * is optional + */ +void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback) +{ + // FIXME: handle HTTP auth with http://user:pass@host/ + // FIXME: get rid of the #anchor part if present. + + char hostname[128] = ""; + int port = 80; + + bool is_http = os_strncmp(url, "http://", strlen("http://")) == 0; + + if (is_http) + url += strlen("http://"); // Get rid of the protocol. + else { + os_printf("URL is not HTTP or HTTPS %s\n", url); + return; + } + + char * path = os_strchr(url, '/'); + if (path == NULL) { + path = os_strchr(url, '\0'); // Pointer to end of string. + } + + char * colon = os_strchr(url, ':'); + if (colon > path) { + colon = NULL; // Limit the search to characters before the path. + } + + if (colon == NULL) { // The port is not present. + os_memcpy(hostname, url, path - url); + hostname[path - url] = '\0'; + } + else { + port = atoi(colon + 1); + if (port == 0) { + os_printf("Port error %s\n", url); + return; + } + + os_memcpy(hostname, url, colon - url); + hostname[colon - url] = '\0'; + } + + + if (path[0] == '\0') { // Empty path is not allowed. + path = "/"; + } + + PRINTF("hostname=%s\n", hostname); + PRINTF("port=%d\n", port); + PRINTF("path=%s\n", path); + http_raw_request(hostname, port, path, post_data, headers, user_callback); +} + +void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback user_callback) +{ + http_post(url, NULL, headers, user_callback); +} + +void ICACHE_FLASH_ATTR http_callback_example(char * response, int http_status, char * full_response) +{ + os_printf("http_status=%d\n", http_status); + if (http_status != HTTP_STATUS_GENERIC_ERROR) { + os_printf("strlen(full_response)=%d\n", strlen(full_response)); + os_printf("response=%s\n", response); + } +} diff --git a/firmwares/wifitime/src/httpclient.h b/firmwares/wifitime/src/httpclient.h new file mode 100644 index 0000000..019f57f --- /dev/null +++ b/firmwares/wifitime/src/httpclient.h @@ -0,0 +1,50 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * Martin d'Allens wrote this file. As long as you retain + * this notice you can do whatever you want with this stuff. If we meet some day, + * and you think this stuff is worth it, you can buy me a beer in return. + * ---------------------------------------------------------------------------- + */ + +#ifndef HTTPCLIENT_H +#define HTTPCLIENT_H + +#define HTTP_STATUS_GENERIC_ERROR -1 // In case of TCP or DNS error the callback is called with this status. +#define BUFFER_SIZE_MAX 5000 // Size of http responses that will cause an error. + +/* + * "full_response" is a string containing all response headers and the response body. + * "response_body and "http_status" are extracted from "full_response" for convenience. + * + * A successful request corresponds to an HTTP status code of 200 (OK). + * More info at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes + */ +typedef void (* http_callback)(char * response_body, int http_status, char * full_response); + +/* + * Download a web page from its URL. + * Try: + * http_get("http://wtfismyip.com/text", http_callback_example); + */ +void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback user_callback); + +/* + * Post data to a web form. + * The data should be encoded as application/x-www-form-urlencoded. + * Try: + * http_post("http://httpbin.org/post", "first_word=hello&second_word=world", http_callback_example); + */ +void ICACHE_FLASH_ATTR http_post(const char * url, const char * post_data, const char * headers, http_callback user_callback); + +/* + * Call this function to skip URL parsing if the arguments are already in separate variables. + */ +void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, const char * path, const char * post_data, const char * headers, http_callback user_callback); + +/* + * Output on the UART. + */ +void http_callback_example(char * response, int http_status, char * full_response); + +#endif diff --git a/firmwares/wifitime/src/i2c_master.c b/firmwares/wifitime/src/i2c_master.c new file mode 100644 index 0000000..8da2611 --- /dev/null +++ b/firmwares/wifitime/src/i2c_master.c @@ -0,0 +1,316 @@ +/****************************************************************************** + * Copyright 2013-2014 Espressif Systems (Wuxi) + * + * FileName: i2c_master.c + * + * Description: i2c master API + * + * Modification history: + * 2014/3/12, v1.0 create this file. +*******************************************************************************/ +#include "ets_sys.h" +#include "osapi.h" +#include "gpio.h" + +#include "i2c_master.h" + +LOCAL uint8 m_nLastSDA; +LOCAL uint8 m_nLastSCL; + +/****************************************************************************** + * FunctionName : i2c_master_setDC + * Description : Internal used function - + * set i2c SDA and SCL bit value for half clk cycle + * Parameters : uint8 SDA + * uint8 SCL + * Returns : NONE +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +i2c_master_setDC(uint8 SDA, uint8 SCL) +{ + SDA &= 0x01; + SCL &= 0x01; + m_nLastSDA = SDA; + m_nLastSCL = SCL; + + if ((0 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_LOW(); + } else if ((0 == SDA) && (1 == SCL)) { + I2C_MASTER_SDA_LOW_SCL_HIGH(); + } else if ((1 == SDA) && (0 == SCL)) { + I2C_MASTER_SDA_HIGH_SCL_LOW(); + } else { + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + } +} + +/****************************************************************************** + * FunctionName : i2c_master_getDC + * Description : Internal used function - + * get i2c SDA bit value + * Parameters : NONE + * Returns : uint8 - SDA bit value +*******************************************************************************/ +LOCAL uint8 ICACHE_FLASH_ATTR +i2c_master_getDC(void) +{ + uint8 sda_out; + sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)); + return sda_out; +} + +/****************************************************************************** + * FunctionName : i2c_master_init + * Description : initilize I2C bus to enable i2c operations + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_init(void) +{ + uint8 i; + + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + // when SCL = 0, toggle SDA to clear up + i2c_master_setDC(0, 0) ; + i2c_master_wait(5); + i2c_master_setDC(1, 0) ; + i2c_master_wait(5); + + // set data_cnt to max value + for (i = 0; i < 28; i++) { + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + } + + // reset all + i2c_master_stop(); + return; +} + +/****************************************************************************** + * FunctionName : i2c_master_gpio_init + * Description : config SDA and SCL gpio to open-drain output mode, + * mux and gpio num defined in i2c_master.h + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_gpio_init(void) +{ + ETS_GPIO_INTR_DISABLE() ; +// ETS_INTR_LOCK(); + + PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC); + PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC); + + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain; + GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SDA_GPIO)); + GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain; + GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SCL_GPIO)); + + I2C_MASTER_SDA_HIGH_SCL_HIGH(); + + ETS_GPIO_INTR_ENABLE() ; +// ETS_INTR_UNLOCK(); + + i2c_master_init(); +} + +/****************************************************************************** + * FunctionName : i2c_master_start + * Description : set i2c to send state + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_start(void) +{ + i2c_master_setDC(1, m_nLastSCL); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 +} + +/****************************************************************************** + * FunctionName : i2c_master_stop + * Description : set i2c to stop sending state + * Parameters : NONE + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_stop(void) +{ + i2c_master_wait(5); + + i2c_master_setDC(0, m_nLastSCL); + i2c_master_wait(5); // sda 0 + i2c_master_setDC(0, 1); + i2c_master_wait(5); // sda 0, scl 1 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 +} + +/****************************************************************************** + * FunctionName : i2c_master_setAck + * Description : set ack to i2c bus as level value + * Parameters : uint8 level - 0 or 1 + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_setAck(uint8 level) +{ + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(level, 1); + i2c_master_wait(8); // sda level, scl 1 + i2c_master_setDC(level, 0); + i2c_master_wait(5); // sda level, scl 0 + i2c_master_setDC(1, 0); + i2c_master_wait(5); +} + +/****************************************************************************** + * FunctionName : i2c_master_getAck + * Description : confirm if peer send ack + * Parameters : NONE + * Returns : uint8 - ack value, 0 or 1 +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR +i2c_master_getAck(void) +{ + uint8 retVal; + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + i2c_master_setDC(1, 1); + i2c_master_wait(5); + + retVal = i2c_master_getDC(); + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); + + return retVal; +} + +/****************************************************************************** +* FunctionName : i2c_master_checkAck +* Description : get dev response +* Parameters : NONE +* Returns : true : get ack ; false : get nack +*******************************************************************************/ +bool ICACHE_FLASH_ATTR +i2c_master_checkAck(void) +{ + if(i2c_master_getAck()){ + return FALSE; + }else{ + return TRUE; + } +} + +/****************************************************************************** +* FunctionName : i2c_master_send_ack +* Description : response ack +* Parameters : NONE +* Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_send_ack(void) +{ + i2c_master_setAck(0x0); +} +/****************************************************************************** +* FunctionName : i2c_master_send_nack +* Description : response nack +* Parameters : NONE +* Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_send_nack(void) +{ + i2c_master_setAck(0x1); +} + +/****************************************************************************** + * FunctionName : i2c_master_readByte + * Description : read Byte from i2c bus + * Parameters : NONE + * Returns : uint8 - readed value +*******************************************************************************/ +uint8 ICACHE_FLASH_ATTR +i2c_master_readByte(void) +{ + uint8 retVal = 0; + uint8 k, i; + + i2c_master_wait(5); + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); // sda 1, scl 0 + + for (i = 0; i < 8; i++) { + i2c_master_wait(5); + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + i2c_master_setDC(1, 1); + i2c_master_wait(5); // sda 1, scl 1 + + k = i2c_master_getDC(); + i2c_master_wait(5); + + if (i == 7) { + i2c_master_wait(3); //// + } + + k <<= (7 - i); + retVal |= k; + } + + i2c_master_setDC(1, 0); + i2c_master_wait(5); // sda 1, scl 0 + + return retVal; +} + +/****************************************************************************** + * FunctionName : i2c_master_writeByte + * Description : write wrdata value(one byte) into i2c + * Parameters : uint8 wrdata - write value + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +i2c_master_writeByte(uint8 wrdata) +{ + uint8 dat; + sint8 i; + + i2c_master_wait(5); + + i2c_master_setDC(m_nLastSDA, 0); + i2c_master_wait(5); + + for (i = 7; i >= 0; i--) { + dat = wrdata >> i; + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + i2c_master_setDC(dat, 1); + i2c_master_wait(5); + + if (i == 0) { + i2c_master_wait(3); //// + } + + i2c_master_setDC(dat, 0); + i2c_master_wait(5); + } +} diff --git a/firmwares/wifitime/src/i2c_master.h b/firmwares/wifitime/src/i2c_master.h new file mode 100644 index 0000000..6e0c9f0 --- /dev/null +++ b/firmwares/wifitime/src/i2c_master.h @@ -0,0 +1,39 @@ +#ifndef __I2C_MASTER_H__ +#define __I2C_MASTER_H__ + +#define I2C_MASTER_SDA_MUX PERIPHS_IO_MUX_GPIO2_U +#define I2C_MASTER_SCL_MUX PERIPHS_IO_MUX_MTMS_U +#define I2C_MASTER_SDA_GPIO 2 +#define I2C_MASTER_SCL_GPIO 14 +#define I2C_MASTER_SDA_FUNC FUNC_GPIO2 +#define I2C_MASTER_SCL_FUNC FUNC_GPIO14 + +#define I2C_MASTER_SDA_HIGH_SCL_HIGH() \ + gpio_output_set(1< +#include +#include +#include +#include + +// Configuration +#include "user_config.h" + +// Project +#include "i2c_master.h" +#include "ssd1306.h" +#include "rv3029.h" +#include "httpclient.h" + +os_timer_t oled_refresh; +os_timer_t time_refresh; + +bool scanning = false; + +os_timer_t resume_timer; +void ICACHE_FLASH_ATTR resume_cb() { + scanning = false; +} + +void ICACHE_FLASH_ATTR scan_done(void *arg, STATUS status) { + char ssid[33]; + ssd1306_fill(0x00); + if (status == OK) { + struct bss_info *bss_link = (struct bss_info *)arg; + + uint8_t i = 0; + while (bss_link != NULL && i < 8) { + os_memcpy(ssid, bss_link->ssid, os_strlen(bss_link->ssid)); + ssid[os_strlen(bss_link->ssid)] = 0x00; + + os_printf("> %s\r\n", ssid); + ssd1306_text_small(0, i * 8, ssid); + + bss_link = bss_link->next.stqe_next; + i++; + } + } + + os_timer_setfn(&resume_timer, (os_timer_func_t *)resume_cb, NULL); + os_timer_arm(&resume_timer, 4000, 0); + ssd1306_flip(); +} + +void ICACHE_FLASH_ATTR wifi_scan(void) { + scanning = true; + ssd1306_fill(0x00); + ssd1306_text_large(20, 10, "Scanning..."); + ssd1306_flip(); + wifi_station_scan(NULL, scan_done); +} + +void ICACHE_FLASH_ATTR oled_refresh_cb(void) { + // Button status + // if (!GPIO_INPUT_GET(4) && !GPIO_INPUT_GET(5)) wifi_scan(); + + if (scanning) return; + ssd1306_fill(0x00); + + struct TimeSpec time; + rv3029_gettime(&time); + char timestring[20]; + os_sprintf(timestring, "%2d:%02d:%02d", time.hours, time.minutes, time.seconds); + ssd1306_text_large(32, 15, timestring); + + char datestring[20]; + os_sprintf(datestring, "%d-%02d-%02d", 2000 + time.years, time.months, time.date); + ssd1306_text_small(34, 31, datestring); + + if (!GPIO_INPUT_GET(4)) { + char voltline[10]; + float batt_volt = ((float)system_adc_read()) * (VOLT_DIV_DOWN + VOLT_DIV_UP) / VOLT_DIV_DOWN / 1024; + os_sprintf(voltline, "%d.%02d V", (uint16_t)batt_volt, ((uint16_t)(batt_volt * 100)) % 100); + ssd1306_text_small(46, 50, voltline); + } + + ssd1306_flip(); +} + +void ICACHE_FLASH_ATTR http_callback_time(char *res, int status, char *res_full) +{ + if (status == HTTP_STATUS_GENERIC_ERROR) return; + + // Send "ESP" string in request to make sure the API actually answered the request + if (res[0] == 'E' && res[1] == 'S' && res[2] == 'P') { + // Split res by inserting NUL-termination characters between numbers + uint8_t i = 0; + while (res[i] != 0x00) { + if (res[i] == ' ') res[i] = 0x00; + i++; + } + + struct TimeSpec settime; + settime.years = atoi(res + 4); + settime.months = atoi(res + 7); + settime.date = atoi(res + 10); + settime.dow = atoi(res + 13); + settime.hours = atoi(res + 15); + settime.minutes = atoi(res + 18); + settime.seconds = atoi(res + 21); + + rv3029_settime(&settime); + + /*** WiFi sleep ***/ + wifi_station_disconnect(); + wifi_set_opmode(NULL_MODE); + wifi_fpm_set_sleep_type(MODEM_SLEEP_T); + wifi_fpm_open(); + wifi_fpm_do_sleep(0xfffffff); + } +} + +void ICACHE_FLASH_ATTR time_refresh_cb(void) { + // year month date dow hours minutes seconds + http_get("http://www.timeapi.org/cet?ESP%20\\y%20\\m%20\\d%20\\u%20\\H%20\\M%20\\S", "", http_callback_time); +} + +void ICACHE_FLASH_ATTR user_init(void) { + uart_div_modify(0, UART_CLK_FREQ / BAUD); + + // LCD Init + i2c_master_gpio_init(); + i2c_scanbus(); + ssd1306_init(0); + + // ~Charge input + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13); + gpio_output_set(0, 0, 0, BIT13); + + // Button inputs + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5); + gpio_output_set(0, 0, 0, BIT4); + gpio_output_set(0, 0, 0, BIT5); + PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO4_U); + PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO5_U); + + // Setup Wifi + wifi_set_opmode(STATION_MODE); + + // No need for a Password in the German "Freifunk" Network ;) + char ssid[32] = "Freifunk"; + char pass[64] = ""; + struct station_config sta_conf; + sta_conf.bssid_set = 0; + os_memcpy(&sta_conf.ssid, ssid, 32); + os_memcpy(&sta_conf.password, pass, 64); + + wifi_station_set_config(&sta_conf); + wifi_station_connect(); + + //struct TimeSpec time; + //rv3029_gettime(&time); + //os_printf("Time: %d-%d-%d %d:%d:%d\r\n", 2000 + time.years, time.months, time.date, time.hours, time.minutes, time.seconds); + + os_printf("Startup\r\n"); + + // Timers + os_timer_setfn(&oled_refresh, (os_timer_func_t *)oled_refresh_cb, NULL); + os_timer_arm(&oled_refresh, 1000, 1); + + os_timer_setfn(&time_refresh, (os_timer_func_t *)time_refresh_cb, NULL); + os_timer_arm(&time_refresh, 120000, 1); +} diff --git a/firmwares/wifitime/src/rv3029.c b/firmwares/wifitime/src/rv3029.c new file mode 100644 index 0000000..8a6e50f --- /dev/null +++ b/firmwares/wifitime/src/rv3029.c @@ -0,0 +1,120 @@ +#include "ets_sys.h" +#include "osapi.h" + +#include "i2c_master.h" +#include "rv3029.h" + +#define RV3029_ADDR_W 0xAC +#define RV3029_ADDR_R 0xAD + +#define BCD2BIN(val) ((((val) & 0x0f) + ((val) >> 4) * 10)) +#define BIN2BCD(val) ((((val)/10)<<4) + (val)%10) + +bool rv3029_read(uint8_t regaddr, uint8_t bytes, uint8_t *val) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(RV3029_ADDR_W); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for write addr\r\n"); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if(i2c_master_getAck()) { + os_printf("RV3029: no ACK for register\r\n"); + i2c_master_stop(); + return false; + } + + i2c_master_stop(); + i2c_master_start(); + + // Write I²C Address for reading + i2c_master_writeByte(RV3029_ADDR_R); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for read addr\r\n"); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < bytes; ++i) { + val[i] = i2c_master_readByte(); + i2c_master_send_ack(); + } + + i2c_master_stop(); + + return true; +} + +bool rv3029_write(uint8_t regaddr, uint8_t bytes, uint8_t *val) { + i2c_master_start(); + + // Write I²C Address for writing register + i2c_master_writeByte(RV3029_ADDR_W); + if (i2c_master_getAck()) { + os_printf("RV3029: no ACK for write addr\r\n"); + i2c_master_stop(); + return false; + } + + // Write register address + i2c_master_writeByte(regaddr); + if(i2c_master_getAck()) { + os_printf("RV3029: no ACK for register\r\n"); + i2c_master_stop(); + return false; + } + + uint8_t i; + for (i = 0; i < bytes; ++i) { + i2c_master_writeByte(val[i]); + if(i2c_master_getAck()) { + os_printf("RV3029: no ACK for datawrite\r\n"); + i2c_master_stop(); + return false; + } + } + + i2c_master_stop(); + + return true; +} + + +int8_t rv3029_temp() { + uint8_t temp; + if (rv3029_read(0x20, 1, &temp)) return (int8_t)temp - 60; + else return 255; +} + +bool rv3029_gettime(struct TimeSpec *time) { + uint8_t raw[7]; + if (!rv3029_read(0x08, 7, raw)) return false; + + time->seconds = BCD2BIN(raw[0]); + time->minutes = BCD2BIN(raw[1]); + time->hours = BCD2BIN(raw[2]); + time->date = BCD2BIN(raw[3]); + time->dow = raw[4]; + time->months = BCD2BIN(raw[5]); + time->years = BCD2BIN(raw[6]); + + return true; +} + +bool rv3029_settime(struct TimeSpec *time) { + uint8_t raw[7]; + raw[0] = BIN2BCD(time->seconds); + raw[1] = BIN2BCD(time->minutes); + raw[2] = BIN2BCD(time->hours); + raw[3] = BIN2BCD(time->date); + raw[4] = time->dow; + raw[5] = BIN2BCD(time->months); + raw[6] = BIN2BCD(time->years); + return rv3029_write(0x08, 7, raw); +} diff --git a/firmwares/wifitime/src/rv3029.h b/firmwares/wifitime/src/rv3029.h new file mode 100644 index 0000000..cb46f05 --- /dev/null +++ b/firmwares/wifitime/src/rv3029.h @@ -0,0 +1,22 @@ +#include "ets_sys.h" + +#ifndef _RV3029_H +#define _RV3029_H + +// 24-hour format only +// Years from 0 - 79, meaning 20xx +// Months from 1 - 12, dow from 1 - 7 +struct TimeSpec { + uint8_t seconds; + uint8_t minutes; + uint8_t hours; + uint8_t date; + uint8_t dow; + uint8_t months; + uint8_t years; +}; + +int8_t rv3029_temp(); +bool rv3029_gettime(struct TimeSpec *time); + +#endif diff --git a/firmwares/wifitime/src/ssd1306.c b/firmwares/wifitime/src/ssd1306.c new file mode 100644 index 0000000..b5ae0e8 --- /dev/null +++ b/firmwares/wifitime/src/ssd1306.c @@ -0,0 +1,285 @@ +#include +#include +#include + +#include "user_config.h" +#include "ssd1306.h" +#include "i2c_master.h" +#include "font.h" + +#define CONTROL_CMD 0b00000000 +#define CONTROL_DATA 0b01000000 +#define SSD1306_PAGES 8 +#define SSD1306_WIDTH 128 +#define SSD1306_ADDR 0x78 + +uint8_t buf[SSD1306_PAGES][SSD1306_WIDTH]; +bool buf_changed[SSD1306_PAGES] = { false }; + +/** Internal commands **/ +void ssd1306_putbyte(uint8_t byte) { + i2c_master_writeByte(byte); + if (i2c_master_getAck()) os_printf("SSD1306: No ACK for 0x%02x\r\n", byte); +} + +void ICACHE_FLASH_ATTR ssd1306_cmd(uint8_t cmd) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_CMD); + ssd1306_putbyte(cmd); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_data(uint8_t dat) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_DATA); + ssd1306_putbyte(dat); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_databurst(uint8_t *dat, uint32_t len) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_DATA); + uint32_t i; + for (i = 0; i < len; ++i) ssd1306_putbyte(dat[i]); + i2c_master_stop(); +} + +void ICACHE_FLASH_ATTR ssd1306_cmdburst(uint8_t *dat, uint32_t len) { + i2c_master_start(); + ssd1306_putbyte(SSD1306_ADDR); + ssd1306_putbyte(CONTROL_CMD); + uint16_t i; + for (i = 0; i < len; ++i) ssd1306_putbyte(dat[i]); + i2c_master_stop(); +} + +/** Initialization **/ +void ICACHE_FLASH_ATTR ssd1306_init(uint8_t contrast) { + os_delay_us(10000); + + ssd1306_setaddressing(SSD1306_PAGE_ADDRESSING); + ssd1306_setstartline(0); + ssd1306_setstartpage(0); + ssd1306_setstartaddress(0); + ssd1306_setcontrast(contrast); + ssd1306_setglow(0); + ssd1306_setmirror_h(false); + ssd1306_setinverse(false); + ssd1306_setmultiplex(63); + ssd1306_setmirror_v(false); + ssd1306_setoffset(0); + ssd1306_setosc(0, 8); + ssd1306_setprecharge(2, 2); + ssd1306_setcomconfig(0x12); + ssd1306_setvcomh(0x40); + ssd1306_scroll_disable(); + ssd1306_vscroll_area(0, 64); + ssd1306_setblinkfade(SSD1306_BLINKFADE_OFF, 0); + ssd1306_setchargepump(true); + ssd1306_setonoff(true); +} + +/** Text ouput **/ +void ssd1306_text_small(uint8_t x, uint8_t y, char *text) { + uint16_t c = 0; + uint8_t page = y / 8; + while (text[c] != 0x00) { + uint8_t i; + for (i = 0; i < 6; ++i) { + uint16_t xpos = x + c * 6 + i; + if (xpos >= SSD1306_WIDTH) return; + uint8_t draw = font_small[text[c] - 0x20][i]; + + // The text may now span between two pages, so the bits have + // to be sperated for first and second page + uint8_t firstpage = (draw << y % 8); + uint8_t secondpage = (draw >> (8 - y % 8)); + + buf[page][xpos] |= firstpage; + buf_changed[page] = true; + if (y % 8) { + buf_changed[page + 1] = true; + buf[page + 1][xpos] |= secondpage; + } + } + c++; + } +} + +void ssd1306_text_large(uint8_t x, uint8_t y, char *text) { + uint16_t c = 0; + uint8_t page = y / 8; + while (text[c] != 0x00) { + uint8_t i; + for (i = 0; i < 8; ++i) { + uint16_t xpos = x + c * 8 + i; + if (xpos >= SSD1306_WIDTH) return; + uint16_t draw_firstpage = font_large[text[c] - 0x20][i]; + uint16_t draw_secondpage = font_large[text[c] - 0x20][i+8]; + + // The text may now span between two pages, so the bits have + // to be sperated for first and second page + uint8_t firstpage = draw_firstpage << (y % 8); + uint8_t secondpage = (draw_firstpage >> (8 - y % 8)) | (draw_secondpage << (y % 8)); + uint8_t thirdpage = draw_secondpage >> (8 - y % 8); + + buf_changed[page] = true; + buf_changed[page + 1] = true; + + buf[page][xpos] |= firstpage; + buf[page + 1][xpos] |= secondpage; + + if (y % 8) { + buf[page + 2][xpos] |= thirdpage; + buf_changed[page + 2] = true; + } + } + c++; + } +} + +/** Buffer related **/ +void ICACHE_FLASH_ATTR ssd1306_fill(uint8_t content) { + uint8_t page = 0, col = 0; + for(page = 0; page < 8; page++) { + buf_changed[page] = true; + for(col = 0; col < SSD1306_WIDTH; col++) + buf[page][col] = content; + } +} + +// Requires page addressing mode +void ICACHE_FLASH_ATTR ssd1306_flip(void) { + // Some dummy commands, to make controller align timing for bursts + ssd1306_setglow(false); + ssd1306_scroll_disable(); + + uint8_t page; + for (page = 0; page < SSD1306_PAGES; page++) { + ssd1306_setstartaddress(0); + ssd1306_setstartpage(page); + ssd1306_databurst(buf[page], 128); + } +} + +/** Misc commands **/ +void ICACHE_FLASH_ATTR ssd1306_setcontrast(uint8_t contrast) { + ssd1306_cmd(0x81); + ssd1306_cmd(contrast); +} + +void ICACHE_FLASH_ATTR ssd1306_setonoff(bool on) { + ssd1306_cmd(0xAE + (on ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setaddressing(enum ssd1306_addr_mode mode) { + ssd1306_cmd(0x20); + ssd1306_cmd(mode); +} + +// startline from 0 - 63 +void ICACHE_FLASH_ATTR ssd1306_setstartline(uint8_t startline) { + ssd1306_cmd(0x40 + startline); +} + +// startpage from 0 - 7 +void ICACHE_FLASH_ATTR ssd1306_setstartpage(uint8_t startpage) { + ssd1306_cmd(0xB0 + startpage); +} + +// start address from 0 - 128 +void ICACHE_FLASH_ATTR ssd1306_setstartaddress(uint8_t address) { + ssd1306_cmd((0x10 | (address & 0xf0) >> 4)); + ssd1306_cmd(0x01 | (address & 0x0f)); +} + +void ICACHE_FLASH_ATTR ssd1306_setmirror_h(bool mirror) { + ssd1306_cmd(0xA0 + (mirror ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setmirror_v(bool mirror) { + ssd1306_cmd(0xC0 + (mirror ? 8 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setinverse(bool inverse) { + ssd1306_cmd(0xA6 + (inverse ? 1 : 0)); +} + +void ICACHE_FLASH_ATTR ssd1306_setoffset(uint8_t x) { + ssd1306_cmd(0xD3); + ssd1306_cmd(x); +} + +// division ration from 0 - 15, fosc from 0 - 15, see datasheet section 8.3 +// "Oscillator Circuit and Display Time Generator" +void ICACHE_FLASH_ATTR ssd1306_setosc(uint8_t divratio, uint8_t fosc) { + ssd1306_cmd(0xD5); + ssd1306_cmd(divratio | (fosc << 4)); +} + +void ICACHE_FLASH_ATTR ssd1306_setprecharge(uint8_t period_phase1, uint8_t period_phase2) { + ssd1306_cmd(0xD9); + ssd1306_cmd(period_phase1 | (period_phase2 << 4)); +} + +// Refer to datasheet section 10.1.18 for more information +// configures connection of panel to controller +void ICACHE_FLASH_ATTR ssd1306_setcomconfig(uint8_t comconfig) { + ssd1306_cmd(0xDA); + ssd1306_cmd(comconfig); +} + +// level is either 0x00 (0.65 * Vcc), 0x40 (0.77 * Vcc, default), 0x60 (0.83 * Vcc) +void ICACHE_FLASH_ATTR ssd1306_setvcomh(uint8_t level) { + ssd1306_cmd(0xDB); + ssd1306_cmd(level); +} + +void ICACHE_FLASH_ATTR ssd1306_setchargepump(bool enable) { + ssd1306_cmd(0x8D); + ssd1306_cmd(enable ? 0x14 : 0x10); +} + +// multiplex from 15- 63 +void ICACHE_FLASH_ATTR ssd1306_setmultiplex(uint8_t multiplex) { + ssd1306_cmd(0xA8); + ssd1306_cmd(multiplex); +} + +/** Fading and Blinking **/ +// Turns all pixels on (or disables this feature) +void ICACHE_FLASH_ATTR ssd1306_setglow(bool enable) { + ssd1306_cmd(0xA4 + (enable ? 1 : 0)); +} + +// Speed 0 - 15 +void ICACHE_FLASH_ATTR ssd1306_setblinkfade(enum ssd1306_blinkfade_mode mode, uint8_t time) { + ssd1306_cmd(0x23); + ssd1306_cmd((mode << 4) | time); +} + + +/** Scrolling **/ +void ICACHE_FLASH_ATTR ssd1306_scroll(enum ssd1306_scroll_dir direction, uint8_t startpage, uint8_t endpage, + enum ssd1306_scroll_frequency freq, uint8_t voffset) { + ssd1306_cmd(0x29 + direction); + ssd1306_cmd(0x00); + ssd1306_cmd(startpage); + ssd1306_cmd(freq); + ssd1306_cmd(endpage); + ssd1306_cmd(voffset); + ssd1306_cmd(0x2f); +} + +void ICACHE_FLASH_ATTR ssd1306_vscroll_area(uint8_t fixedrows, uint8_t scrollrows) { + ssd1306_cmd(0xa3); + ssd1306_cmd(fixedrows); + ssd1306_cmd(scrollrows); +} + +void ICACHE_FLASH_ATTR ssd1306_scroll_disable() { + ssd1306_cmd(0x2e); +} diff --git a/firmwares/wifitime/src/ssd1306.h b/firmwares/wifitime/src/ssd1306.h new file mode 100644 index 0000000..e621dde --- /dev/null +++ b/firmwares/wifitime/src/ssd1306.h @@ -0,0 +1,80 @@ +#ifndef _SSD1306_H +#define _SSD1306_H + +/** Internal commands **/ +void ssd1306_cmd(uint8_t cmd); +void ssd1306_data(uint8_t dat); +void ssd1306_databurst(uint8_t *dat, uint32_t len); +void ssd1306_cmdburst(uint8_t *dat, uint32_t len); + +/** Initialization **/ +void ssd1306_init(uint8_t contrast); + +/** Text ouput **/ +void ssd1306_text_small(uint8_t x, uint8_t y, char *text); +void ssd1306_text_large(uint8_t x, uint8_t y, char *text); + +/** Buffer related **/ +void ssd1306_fill(uint8_t content); +void ssd1306_flip(void); + +/** Addressing modes **/ +enum ssd1306_addr_mode { + SSD1306_HORIZONTAL_ADDRESSING = 0, + SSD1306_VERTICAL_ADDRESSING = 1, + SSD1306_PAGE_ADDRESSING = 2 +}; + +/** Scroll directions and frequency **/ +enum ssd1306_scroll_dir { + SSD1306_SCROLL_RIGHT = 0, + SSD1306_SCROLL_LEFT = 1 +}; + +enum ssd1306_scroll_frequency { + SSD1306_SCROLLFREQ_5 = 0b000, + SSD1306_SCROLLFREQ_64 = 0b001, + SSD1306_SCROLLFREQ_128 = 0b010, + SSD1306_SCROLLFREQ_256 = 0b011, + SSD1306_SCROLLFREQ_3 = 0b100, + SSD1306_SCROLLFREQ_4 = 0b101, + SSD1306_SCROLLFREQ_25 = 0b110, + SSD1306_SCROLLFREQ_2 = 0b111 +}; + +/** Blinking / fading modes **/ +enum ssd1306_blinkfade_mode { + SSD1306_BLINKFADE_OFF = 0b00, + SSD1306_BLINKFADE_FADE = 0b10, + SSD1306_BLINKFADE_BLINK = 0b11 +}; + +/** Misc commands **/ +void ssd1306_setcontrast(uint8_t contrast); +void ssd1306_setonoff(bool on); +void ssd1306_setaddressing(enum ssd1306_addr_mode mode); +void ssd1306_setstartline(uint8_t startline); +void ssd1306_setstartpage(uint8_t startpage); +void ssd1306_setstartaddress(uint8_t address); +void ssd1306_setmirror_h(bool mirror); +void ssd1306_setmirror_v(bool mirror); +void ssd1306_setinverse(bool inverse); +void ssd1306_setoffset(uint8_t x); +void ssd1306_setosc(uint8_t divratio, uint8_t fosc); +void ssd1306_setprecharge(uint8_t period_phase1, uint8_t period_phase2); +void ssd1306_setcomconfig(uint8_t comconfig); +void ssd1306_setvcomh(uint8_t level); +void ssd1306_setchargepump(bool enable); +void ssd1306_setmultiplex(uint8_t multiplex); + +/** Fading and Blinking **/ +void ssd1306_setglow(bool enable); +void ssd1306_setblinkfade(enum ssd1306_blinkfade_mode mode, uint8_t time); + +/** Scrolling **/ +void ssd1306_scroll(enum ssd1306_scroll_dir direction, uint8_t startpage, uint8_t endpage, + enum ssd1306_scroll_frequency freq, uint8_t voffset); +void ssd1306_vscroll_area(uint8_t fixedrows, uint8_t scrollrows); +void ssd1306_scroll_disable(); + +#endif diff --git a/firmwares/wifitime/src/user_config.h b/firmwares/wifitime/src/user_config.h new file mode 100644 index 0000000..1859836 --- /dev/null +++ b/firmwares/wifitime/src/user_config.h @@ -0,0 +1,5 @@ +#define BAUD 1000000 + +// Battery voltage measurement divisor - pullup & pulldown resistor proportions +#define VOLT_DIV_UP 330 +#define VOLT_DIV_DOWN 100 diff --git a/firmwares/wifitime/src/util.c b/firmwares/wifitime/src/util.c new file mode 100644 index 0000000..a75f411 --- /dev/null +++ b/firmwares/wifitime/src/util.c @@ -0,0 +1,25 @@ +// System +#include +#include +#include +#include +#include + +// Configuration +#include "user_config.h" + +// Project +#include "i2c_master.h" +#include "util.h" + +void i2c_scanbus() { + // Scan I²C Bus + os_printf("=== Scanning I²C Bus ===\r\n"); + uint8_t i; + for (i = 0; i < 0xff; ++i) { + i2c_master_start(); + i2c_master_writeByte(i); + if (!i2c_master_getAck()) os_printf("ACK for address: 0x%02x\r\n", i); + i2c_master_stop(); + } +} diff --git a/firmwares/wifitime/src/util.h b/firmwares/wifitime/src/util.h new file mode 100644 index 0000000..2df0997 --- /dev/null +++ b/firmwares/wifitime/src/util.h @@ -0,0 +1,7 @@ +#ifndef _UTIL_H +#define _UTIL_H + +// For debugging: +void i2c_scanbus(); + +#endif diff --git a/model/model.scad b/model/model.scad new file mode 100644 index 0000000..8399475 --- /dev/null +++ b/model/model.scad @@ -0,0 +1,162 @@ +// All units in millimeters +handle_height = 2; +handle_outer_width = 31; +handle_inner_width = 27; +handle_distance = 2; +handle_conn_width = 3; + +pcb_width = 35; +pcb_height = 30; +pcb_thickness = 1; + +oled_offset_top = 3; +oled_nodisp_height = 4; +oled_disp_height = 15; +oled_width = 26.5; +oled_thickness = 2; + +battery_width = 31.5; +battery_height = 20; +battery_thickness = 6; +battery_offset_left = 0; +battery_offset_bottom = 8; + +button_height = 5; +button_width = 3.5; +button_thickness = 2; + +button_knob_thickness = 1.4; +button_knob_height = 2.6; +button_knob_width = 1; + +button1_offset_top = 2.5; +button2_offset_top = 12.5; +button3_offset_top = 22.5; + +usbconn_width = 6.5; +usbconn_height = 8; +usbconn_thickness = 2.5; +usbconn_width_pcb = 4.5; +usbconn_offset_bottom = 1; + +pcb_drillhole_offset_bottom = 3.5; +pcb_drillhole_offset_right = 14; +pcb_drillhole_diameter = 2; + +module pcb_handle() { + linear_extrude(height = pcb_thickness) polygon(points=[ + [-handle_inner_width / 2, pcb_height / 2 + handle_distance], + [handle_inner_width / 2, pcb_height / 2 + handle_distance], + [handle_outer_width / 2, pcb_height / 2 + handle_distance + handle_height], + [-handle_outer_width / 2, pcb_height / 2 + handle_distance + handle_height] + ]); + + linear_extrude(height = pcb_thickness) polygon(points=[ + [-pcb_width / 2, pcb_height / 2], + [-pcb_width / 2 + handle_conn_width, pcb_height / 2], + [-handle_inner_width / 2, pcb_height / 2 + handle_distance], + [-handle_outer_width / 2, pcb_height / 2 + handle_distance + handle_height] + ]); + + linear_extrude(height = pcb_thickness) polygon(points=[ + [pcb_width / 2, pcb_height / 2], + [pcb_width / 2 - handle_conn_width, pcb_height / 2], + [handle_inner_width / 2, pcb_height / 2 + handle_distance], + [handle_outer_width / 2, pcb_height / 2 + handle_distance + handle_height] + ]); +} + +module pcb_drillhole() { + translate([pcb_width / 2 - pcb_drillhole_offset_right, + -pcb_height / 2 + pcb_drillhole_offset_bottom, 0]) { + cylinder(h = pcb_thickness * 2, d1 = pcb_drillhole_diameter, $fn = 90, center = true); + } +} + +module pcb() { + color([0, 0.6, 0, 1]) { + difference() { + translate([-pcb_width / 2, -pcb_height / 2, -pcb_thickness / 2]) { + cube(size = [pcb_width, pcb_height, pcb_thickness]); + } + pcb_drillhole(); + } + + translate([0, 0, -pcb_thickness / 2]) { + // Upper handle + pcb_handle(); + + // Lower handle + mirror([0, 1, 0]) pcb_handle(); + } + } +} + +module oled() { + translate([-oled_width / 2, pcb_height / 2 - oled_offset_top, pcb_thickness / 2]) { + // Controller area + color([0.5, 0.5, 0.5, 0.5]) { + translate([0, -oled_nodisp_height, 0]) + cube(size = [oled_width, oled_nodisp_height, oled_thickness]); + } + + // Display area + color([0, 0, 0, 0.8]) { + translate([0, -oled_nodisp_height - oled_disp_height, 0]) + cube(size = [oled_width, oled_disp_height, oled_thickness]); + } + } +} + +module battery() { + translate([-pcb_width / 2, -pcb_height / 2, -pcb_thickness / 2]) { + translate([battery_offset_left, battery_offset_bottom, -battery_thickness]) { + color([0.5, 0.5, 0.5, 1.0]) + cube(size = [battery_width, battery_height, battery_thickness]); + } + } +} + +module button(offsetx, offsety) { + translate([offsetx, offsety, -button_thickness - pcb_thickness / 2]) { + color([0.7, 0.7, 0.7, 1.0]) { + cube(size = [button_width, button_height, button_thickness]); + } + + translate([button_width, button_height / 2 - button_knob_height / 2, 0]) { + color([0.2, 0.2, 0.2, 1.0]) { + cube(size = [button_knob_width, button_knob_height, button_knob_thickness]); + } + } + } +} + +module buttons() { + button(pcb_width / 2 - button_width, pcb_height / 2 - button_height - button1_offset_top); + button(pcb_width / 2 - button_width, pcb_height / 2 - button_height - button2_offset_top); + button(pcb_width / 2 - button_width, pcb_height / 2 - button_height - button3_offset_top); +} + +module usbconn(offsetx, offsety) { + translate([offsetx, offsety, -pcb_thickness / 2 - usbconn_thickness]) { + color([0.3, 0.3, 0.3, 1.0]) { + cube([usbconn_width, usbconn_height, usbconn_thickness]); + } + } +} + +module connectors() { + usbconn(-pcb_width / 2 - usbconn_width + usbconn_width_pcb, -pcb_height / 2 + usbconn_offset_bottom); +} + +module watch(centerx, centery) { + translate([centerx, centery]) { + pcb(); + oled(); + battery(); + buttons(); + connectors(); + } +} + +watch(0, 0); \ No newline at end of file