summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@ka-ata-killa.panaceas.james.local>2021-11-21 17:27:02 +0000
committerroot <root@ka-ata-killa.panaceas.james.local>2021-11-21 17:27:02 +0000
commit64f632692fe2a164830a363f8db158a8a2ae33de (patch)
treec2106d606b7e355ede93ff2a04848224a480dbc7
downloadmetric_clock-64f632692fe2a164830a363f8db158a8a2ae33de.tar.gz
metric_clock-64f632692fe2a164830a363f8db158a8a2ae33de.tar.bz2
metric_clock-64f632692fe2a164830a363f8db158a8a2ae33de.zip
first workingish cut
-rw-r--r--.gitmodules3
-rw-r--r--dial/base.jpgbin0 -> 32541 bytes
-rw-r--r--dial/base.svg851
-rw-r--r--dial/try1.svg860
-rw-r--r--dial/try2.svg299
-rw-r--r--dial/try3.svg328
-rw-r--r--stm32/.gitignore10
-rw-r--r--stm32/Makefile.include45
-rw-r--r--stm32/Makefile.rules251
-rw-r--r--stm32/app/Makefile80
-rw-r--r--stm32/app/asm_fns.h4
-rw-r--r--stm32/app/board.h15
-rw-r--r--stm32/app/cdcacm.c221
-rw-r--r--stm32/app/clock.ld43
-rw-r--r--stm32/app/dfu.c86
-rw-r--r--stm32/app/dummy_kb.c26
-rw-r--r--stm32/app/events.c101
-rw-r--r--stm32/app/gdb.script2
-rw-r--r--stm32/app/hands.c90
-rw-r--r--stm32/app/main.c50
-rw-r--r--stm32/app/motor.c75
-rw-r--r--stm32/app/pins.h54
-rw-r--r--stm32/app/project.h50
-rw-r--r--stm32/app/prototypes.h81
-rw-r--r--stm32/app/ring.c64
-rw-r--r--stm32/app/ring.h7
-rw-r--r--stm32/app/rtc.c170
-rw-r--r--stm32/app/ticker.c74
-rw-r--r--stm32/app/time_fn.c650
-rw-r--r--stm32/app/time_fn.h47
-rw-r--r--stm32/app/usart.c88
-rw-r--r--stm32/app/usb.c148
-rw-r--r--stm32/boot/Makefile48
-rw-r--r--stm32/boot/gdb.script2
-rw-r--r--stm32/boot/project.h23
-rw-r--r--stm32/boot/prototypes.h18
-rw-r--r--stm32/boot/usbdfu.c334
-rw-r--r--stm32/boot/usbdfu.ld40
-rw-r--r--stm32/docs/Astronomical Algorithms.pdfbin0 -> 17207937 bytes
-rw-r--r--stm32/docs/rm0008.pdfbin0 -> 13016697 bytes
-rw-r--r--stm32/id.h4
m---------stm32/libopencm30
-rw-r--r--stm32/oocd/board/STM32F103R_BOARD.cfg6
-rw-r--r--stm32/oocd/interface/j-link.cfg5
-rw-r--r--stm32/oocd/interface/stlink-v2.cfg11
-rw-r--r--stm32/oocd/stm32-f103.cfg6
-rwxr-xr-xstm32/tools/dfuse-pack.py256
47 files changed, 5626 insertions, 0 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..981d79a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "stm32/libopencm3"]
+ path = stm32/libopencm3
+ url = git://git.panaceas.org/stm32/libopencm3
diff --git a/dial/base.jpg b/dial/base.jpg
new file mode 100644
index 0000000..adaa1ef
--- /dev/null
+++ b/dial/base.jpg
Binary files differ
diff --git a/dial/base.svg b/dial/base.svg
new file mode 100644
index 0000000..3866756
--- /dev/null
+++ b/dial/base.svg
@@ -0,0 +1,851 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ viewBox="0 0 210 297"
+ version="1.1"
+ id="svg8"
+ inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
+ sodipodi:docname="base.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.1123202"
+ inkscape:cx="478.78127"
+ inkscape:cy="590.94566"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ inkscape:window-width="3044"
+ inkscape:window-height="1702"
+ inkscape:window-x="653"
+ inkscape:window-y="223"
+ inkscape:window-maximized="1"
+ showguides="false" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="image"
+ style="display:none">
+ <image
+ sodipodi:absref="/root/projects/metric_clock/base.jpg"
+ xlink:href="base.jpg"
+ style="fill:#ff0000;stroke:#000000"
+ y="37.229919"
+ x="8.6489792"
+ id="image929"
+ preserveAspectRatio="none"
+ height="194.02777"
+ width="194.02777" />
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1378"
+ cx="105.49754"
+ cy="134.01634"
+ r="71.176346" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="old pips"
+ style="display:none">
+ <g
+ id="g1842">
+ <g
+ id="g1141">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1135"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1137"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1147"
+ transform="rotate(7.2,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1143"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1145"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1153"
+ transform="rotate(14.4,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1149"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1151"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1159"
+ transform="rotate(21.6,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1155"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1157"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1165"
+ transform="rotate(28.8,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1161"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1163"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1171"
+ transform="rotate(36,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1167"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1169"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1177"
+ transform="rotate(43.2,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1173"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1175"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1183"
+ transform="rotate(50.4,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1179"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1181"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1189"
+ transform="rotate(57.6,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1185"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1187"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1195"
+ transform="rotate(64.8,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1191"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1193"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1201"
+ transform="rotate(72,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1197"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1199"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1207"
+ transform="rotate(79.2,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1203"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1205"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1213"
+ transform="rotate(86.4,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1209"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1211"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1237"
+ transform="matrix(-0.06302185,1.0017036,-1.0017036,-0.06302185,246.6788,36.874562)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1233"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1235"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1243"
+ transform="matrix(-0.18807164,0.98590605,-0.98590605,-0.18807164,257.76399,55.32396)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1239"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1241"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1249"
+ transform="matrix(-0.31015544,0.95456027,-0.95456027,-0.31015544,266.44943,75.017219)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1245"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1247"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1255"
+ transform="matrix(-0.42734789,0.90816049,-0.90816049,-0.42734789,272.59816,95.643766)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1251"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1253"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1261"
+ transform="matrix(-0.53780081,0.84743848,-0.84743848,-0.53780081,276.11322,116.87831)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1257"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1259"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1267"
+ transform="matrix(-0.6397723,0.77335186,-0.77335186,-0.6397723,276.93917,138.38596)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1263"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1265"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1273"
+ transform="matrix(-0.73165419,0.68706902,-0.68706902,-0.73165419,275.06298,159.82754)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1269"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1271"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1279"
+ transform="matrix(-0.81199746,0.58995069,-0.58995069,-0.81199746,270.51424,180.8649)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1275"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1277"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1285"
+ transform="matrix(-0.87953505,0.48352848,-0.48352848,-0.87953505,263.36469,201.16626)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1281"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1283"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1291"
+ transform="matrix(-0.93320184,0.36948075,-0.36948075,-0.93320184,253.72709,220.41147)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1287"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1289"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1297"
+ transform="matrix(-0.97215148,0.24960607,-0.24960607,-0.97215148,241.7534,238.297)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1293"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1295"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1303"
+ transform="matrix(-0.99576972,0.12579497,-0.12579497,-0.99576972,227.63249,254.5408)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1299"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1301"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ </g>
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1845"
+ cx="105.49754"
+ cy="134.01634"
+ r="71.176346" />
+ <g
+ id="g1939"
+ style="display:inline">
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1933"
+ cx="105.33971"
+ cy="134.17418"
+ r="71.176346" />
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1935"
+ cx="105.33971"
+ cy="134.17418"
+ r="68.756615" />
+ </g>
+ </g>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <g
+ id="g995"
+ transform="translate(0.00821436,0.04586345)"
+ style="stroke:#000000">
+ <path
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 142.62011,171.00294 c -0.77532,0.8116 -1.74601,1.45294 -1.69031,2.60136 l -0.0451,12.04127 -1.00434,1.41555 1.36953,1.46493 c 0.73978,-0.78263 1.87134,-1.76247 1.86355,-2.60431 l -0.0436,-12.18219 0.82224,-1.20249 z"
+ id="path951"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path960"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 138.45302,178.09954 8.05529,0.0319 0.002,0.12594 c 0,1.11333 -0.76094,2.01586 -1.69962,2.01586 v 0 l -7.44358,-0.0173 -0.59615,-0.002 c 0,-1.11332 0.74339,-2.15445 1.68206,-2.15445 z"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <path
+ id="path1018"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 165.42907,147.14224 c 1.48292,1.79487 1.95406,4.21946 1.25123,6.43907 -0.70283,2.21961 -2.48366,3.93112 -4.72941,4.54532 l -0.41085,-1.88943 c 1.88114,-0.6989 3.18124,-2.4315 3.32643,-4.43302 0.14519,-2.00152 -0.89125,-3.90361 -2.65184,-4.86668 l -0.004,-0.0635 c 1.06407,-0.16125 1.95224,-0.89667 2.30911,-1.912 0.35687,-1.01533 0.12416,-2.14472 -0.60501,-2.93627 l 1.42625,-1.34002 c 1.01902,0.76829 1.62025,1.96881 1.62512,3.245 0.005,1.27619 -0.58718,2.48126 -1.6003,3.25731"
+ sodipodi:nodetypes="csccsccsccsc" />
+ <path
+ id="path1054"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.189676px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 160.27638,119.48712 h 3.39357 l -0.7927,2.0749 h -5.70621 l 4.71175,-11.02413 c 0.46026,-1.02664 0.47591,-1.96296 -0.0376,-2.83449 -0.5135,-0.87153 -1.44963,-1.4065 -2.46119,-1.4065 v -1.96032 c 1.72867,0 3.32844,0.91422 4.20597,2.4036 0.87753,1.48938 0.79014,3.18621 0.0642,4.84389 z"
+ sodipodi:nodetypes="cccccsccscc" />
+ <path
+ id="path1063"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 139.20258,92.443022 c 0.0227,1.492933 -0.71046,2.184358 -1.71218,3.088513 l -1.36412,-1.379764 0.91515,-1.290498 c 0.0752,-4.613157 0.0727,-7.122012 0.0727,-11.735567 -0.0227,-1.492933 0.71046,-2.184358 1.71218,-3.088513 l 1.36412,1.379764 -0.91515,1.290498 c -0.0752,4.613157 -0.0727,7.122012 -0.0727,11.735567 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <g
+ id="g1110"
+ transform="translate(0.08439634,0.03638421)">
+ <path
+ id="path1066"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 99.335085,82.703014 c 0.0227,1.49293 -0.71046,2.18436 -1.71218,3.08851 l -1.36412,-1.37976 0.91515,-1.2905 c 0.0752,-4.613159 0.0727,-7.122014 0.0727,-11.735569 -0.0227,-1.492933 0.71046,-2.184358 1.71218,-3.088513 l 1.364125,1.379764 -0.915155,1.290498 c -0.0752,4.613157 -0.0727,7.122012 -0.0727,11.73557 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1104"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.34794,77.22145 c -0.009,-4.008906 -1.45649,-5.885766 -2.94934,-7.436765 -1.49285,1.551 -2.94034,3.427859 -2.94934,7.436765 0.009,4.008906 1.45649,5.885765 2.94934,7.436764 1.49285,-1.551 2.94072,-3.427858 2.94934,-7.436764 z m -7.75346,-10e-7 c 0,-3.970502 1.39203,-7.485929 3.44361,-8.696446 h 2.72102 c 2.05158,1.210517 3.44361,4.725944 3.44361,8.696446 m 0,0 c 0,3.970503 -1.39203,7.48593 -3.44361,8.696447 h -2.72102 c -2.05158,-1.210517 -3.44361,-4.725944 -3.44361,-8.696447" />
+ </g>
+ <path
+ id="circle1126"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 69.659555,85.08518 -1.894017,-0.0277 c 0.222034,-2.890953 1.399433,-5.625912 3.346761,-7.774126 2.178503,2.403238 3.385124,5.53093 3.385124,8.774604 0,3.243674 -1.061988,6.152795 -3.24049,8.556033 l -1.497126,-1.379597 c 1.712443,-1.977148 2.655035,-4.505188 2.655035,-7.065439 0,-1.819926 -0.484876,-3.663385 -1.407554,-5.296014 -0.732977,1.296964 -1.191703,2.730677 -1.347733,4.212239 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1133"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 72.650668,180.22034 1.894017,0.0277 c -0.222034,2.89095 -1.399433,5.62591 -3.346761,7.77413 -2.178503,-2.40324 -3.385124,-5.53093 -3.385124,-8.77461 0,-3.24367 1.061988,-6.15279 3.24049,-8.55603 l 1.497126,1.3796 c -1.712443,1.97715 -2.655035,4.50519 -2.655035,7.06544 0,1.81992 0.484876,3.66338 1.407554,5.29601 0.732977,-1.29696 1.191703,-2.73068 1.347733,-4.21224 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1322"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 50.287154,117.66409 c 0,2.16984 -1.759002,3.92884 -3.92884,3.92884 v -2.1373 c 0.98944,0 1.791539,-0.8021 1.791539,-1.79154 v -9.54908 c 0,-2.16984 1.759002,-3.92884 3.92884,-3.92884 v 2.1373 c -0.98944,0 -1.791539,0.8021 -1.791539,1.79154 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1349"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 51.538753,140.65131 h -6.110409 l -0.778053,2.10287 h 3.465667 l -1.624213,3.02055 c -2.095652,3.62916 -1.593366,8.50944 1.333431,12.13361 l 1.546982,-1.28068 c -2.503817,-2.94881 -2.765529,-7.3652 -0.973802,-9.89319 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1367"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.6004,185.91358 c 1.97118,-0.2694 3.9338,0.54911 5.12947,2.13924 1.19567,1.59013 1.43712,3.70284 0.63105,5.52174 -0.80607,1.8189 -2.53341,3.05912 -4.51455,3.24141 l 0.18078,1.96467 c 3.59307,-0.33061 6.43467,-3.18511 6.749,-6.77964 0.31433,-3.59454 -1.9887,-6.89892 -5.46986,-7.84814 l 0.23909,-0.51828 h 3.32706 l 0.77138,-2.12989 h -5.54686 z"
+ sodipodi:nodetypes="cssccscccccc" />
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1907"
+ cx="105.33971"
+ cy="134.17418"
+ r="71.176346" />
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1912"
+ cx="105.33971"
+ cy="134.17418"
+ r="68.756615" />
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1916"
+ cx="105.33971"
+ cy="134.17418"
+ r="68.756615" />
+ <path
+ id="path1950"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 36.583092,134.17418 c 0,-1.44015 0.04525,-2.87995 0.135675,-4.31726 l -2.414956,-0.15194 c -0.09361,1.48789 -0.14045,2.97836 -0.14045,4.4692 z m 137.377558,4.31726 c 0.0904,-1.43731 0.13567,-2.87711 0.13567,-4.31726 h 2.41973 c 0,1.49084 -0.0468,2.98131 -0.14045,4.4692 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1957"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 37.125258,125.55669 c 0.180499,-1.42879 0.405847,-2.85157 0.675702,-4.26621 l -2.37687,-0.45342 c -0.279354,1.46443 -0.51263,2.93727 -0.699482,4.41636 z m 135.753202,21.50119 c 0.26983,-1.41464 0.49519,-2.83742 0.67569,-4.26621 l 2.40065,0.30327 c -0.18685,1.47909 -0.42008,2.95194 -0.69948,4.41636 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1959"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 38.743207,117.07511 c 0.358151,-1.39491 0.760043,-2.77822 1.205072,-4.14789 l -2.3013,-0.74774 c -0.460692,1.41786 -0.876725,2.84986 -1.247482,4.29386 z m 131.987933,38.34603 c 0.445,-1.36967 0.84691,-2.75298 1.20506,-4.14789 l 2.34371,0.60177 c -0.37075,1.444 -0.78675,2.87601 -1.24748,4.29386 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1961"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 41.411423,108.86318 c 0.530154,-1.33901 1.102253,-2.66105 1.715437,-3.96414 l -2.189436,-1.03028 c -0.634766,1.34895 -1.226994,2.71751 -1.77581,4.10366 z m 126.141137,54.58614 c 0.61316,-1.30309 1.18527,-2.62513 1.71543,-3.96414 l 2.2498,0.89076 c -0.54881,1.38615 -1.141,2.75473 -1.7758,4.10366 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1963"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 45.087826,101.05043 c 0.693797,-1.262014 1.427079,-2.501921 2.198749,-3.717883 l -2.043045,-1.29656 c -0.798827,1.258751 -1.557913,2.542294 -2.276131,3.848728 z m 118.305014,69.96539 c 0.77165,-1.21598 1.50495,-2.45588 2.19875,-3.71789 l 2.12042,1.16572 c -0.71822,1.30643 -1.47727,2.58999 -2.27613,3.84872 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1965"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 49.714437,93.760055 c 0.846497,-1.165102 1.729401,-2.303331 2.647384,-3.412986 l -1.86443,-1.542401 c -0.950294,1.14871 -1.864262,2.326988 -2.740558,3.533108 z M 158.3176,178.0013 c 0.91796,-1.10967 1.80087,-2.24789 2.64737,-3.413 l 1.95761,1.42228 c -0.8763,1.20612 -1.79023,2.38443 -2.74056,3.53311 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1967"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 55.218289,87.107043 c 0.985853,-1.049828 2.004448,-2.068419 3.054274,-3.054276 l -1.656418,-1.763909 c -1.086767,1.02054 -2.141211,2.074986 -3.16176,3.161759 z M 152.40686,184.2956 c 1.0498,-0.98587 2.06841,-2.00446 3.05426,-3.05428 l 1.7639,1.65642 c -1.02054,1.08678 -2.07496,2.14125 -3.16176,3.16176 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1969"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 61.512592,81.196297 c 1.10965,-0.91798 2.247882,-1.800882 3.412988,-2.647385 l -1.422277,-1.95761 c -1.206111,0.876293 -2.384393,1.790264 -3.533107,2.740562 z M 145.75384,189.79945 c 1.16508,-0.84651 2.30333,-1.72941 3.41298,-2.64739 l 1.54239,1.86443 c -1.14871,0.9503 -2.32697,1.86431 -3.5331,2.74057 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1971"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 45.087826,101.05043 c 0.693798,-1.262014 1.42708,-2.501921 2.198749,-3.717883 l -2.043044,-1.29656 c -0.798828,1.258751 -1.557914,2.542295 -2.276131,3.848728 z m 118.305014,69.96539 c 0.77165,-1.21598 1.50495,-2.45588 2.19875,-3.71789 l 2.12042,1.16572 c -0.71822,1.30643 -1.47727,2.58999 -2.27613,3.84872 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1973"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 49.714437,93.760055 c 0.846498,-1.165102 1.729401,-2.303331 2.647385,-3.412986 l -1.86443,-1.542401 c -0.950295,1.14871 -1.864262,2.326988 -2.740559,3.533108 z M 158.3176,178.0013 c 0.91796,-1.10967 1.80087,-2.24789 2.64737,-3.413 l 1.95761,1.42228 c -0.8763,1.20612 -1.79023,2.38443 -2.74056,3.53311 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1975"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 55.218289,87.107043 c 0.985853,-1.049828 2.004449,-2.068419 3.054274,-3.054276 l -1.656418,-1.763909 c -1.086767,1.02054 -2.14121,2.074986 -3.16176,3.161759 z M 152.40686,184.2956 c 1.0498,-0.98587 2.06841,-2.00446 3.05426,-3.05428 l 1.7639,1.65642 c -1.02054,1.08678 -2.07496,2.14125 -3.16175,3.16176 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1977"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 61.512592,81.196297 c 1.109651,-0.91798 2.247883,-1.800882 3.412988,-2.647385 l -1.422276,-1.95761 c -1.206111,0.876293 -2.384394,1.790264 -3.533108,2.740562 z M 145.75384,189.79945 c 1.16508,-0.84651 2.30333,-1.72941 3.41298,-2.64739 l 1.54239,1.86443 c -1.14871,0.9503 -2.32697,1.86431 -3.5331,2.74057 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1979"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 68.49807,76.121052 c 1.215959,-0.771672 2.455868,-1.504949 3.717882,-2.19875 l -1.165711,-2.120429 c -1.306426,0.718215 -2.589969,1.477299 -3.848728,2.276132 z m 69.96539,118.305018 c 1.262,-0.69383 2.50193,-1.42709 3.71789,-2.19876 l 1.29654,2.04305 c -1.25875,0.79883 -2.54227,1.55794 -3.84872,2.27612 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1981"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 76.064565,71.961335 c 1.303083,-0.613184 2.625124,-1.185279 3.964139,-1.715436 l -0.890755,-2.249812 c -1.386145,0.548815 -2.754701,1.14104 -4.103658,1.775812 z M 130.65071,198.10247 c 1.339,-0.53018 2.66105,-1.10226 3.96414,-1.71545 l 1.03027,2.18944 c -1.34896,0.63477 -2.71749,1.22704 -4.10366,1.77581 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1983"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 84.09274,68.782757 c 1.369668,-0.445033 2.75298,-0.846919 4.147889,-1.205075 l -0.60176,-2.34371 c -1.44399,0.370752 -2.87599,0.786787 -4.29386,1.247481 z m 38.34605,131.987933 c 1.39489,-0.35818 2.77822,-0.76006 4.14788,-1.20509 l 0.74773,2.3013 c -1.41787,0.46071 -2.84986,0.87677 -4.29386,1.24748 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1985"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 92.456003,66.635434 c 1.414634,-0.269854 2.837416,-0.495199 4.266212,-0.675701 L 96.41895,63.559079 c -1.47908,0.186853 -2.951926,0.42013 -4.416361,0.699485 z M 113.9572,202.38863 c 1.42878,-0.18052 2.85158,-0.40585 4.26621,-0.67571 l 0.45341,2.37687 c -1.46443,0.27936 -2.93728,0.51268 -4.41636,0.69949 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1987"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 68.498069,76.121052 c 1.21596,-0.771671 2.455869,-1.504949 3.717882,-2.19875 l -1.16571,-2.120428 c -1.306427,0.718214 -2.589971,1.477299 -3.848728,2.276132 z M 138.46346,194.42607 c 1.262,-0.69383 2.50193,-1.42709 3.71789,-2.19876 l 1.29654,2.04305 c -1.25875,0.79883 -2.54227,1.55794 -3.84872,2.27612 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1989"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 76.064564,71.961335 c 1.303084,-0.613183 2.625124,-1.185279 3.96414,-1.715435 l -0.890755,-2.249812 c -1.386145,0.548814 -2.754701,1.14104 -4.103658,1.775811 z M 130.65071,198.10247 c 1.339,-0.53018 2.66105,-1.10226 3.96414,-1.71545 l 1.03027,2.18944 c -1.34896,0.63477 -2.7175,1.22704 -4.10366,1.77581 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1991"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 84.092739,68.782757 c 1.369668,-0.445033 2.752981,-0.846919 4.14789,-1.205075 l -0.601761,-2.34371 c -1.44399,0.370752 -2.875989,0.786788 -4.29386,1.247481 z M 122.43879,200.77069 c 1.39489,-0.35818 2.77822,-0.76006 4.14788,-1.20509 l 0.74773,2.3013 c -1.41787,0.46071 -2.84986,0.87677 -4.29385,1.24749 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1993"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 92.456003,66.635434 c 1.414634,-0.269853 2.837416,-0.495199 4.266211,-0.675701 L 96.41895,63.559079 c -1.47908,0.186853 -2.951927,0.42013 -4.416362,0.699485 z M 113.9572,202.38863 c 1.42878,-0.18052 2.85158,-0.40585 4.26621,-0.67571 l 0.45341,2.37687 c -1.46443,0.27936 -2.93728,0.51268 -4.41636,0.69949 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1995"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.02244,65.553243 c 1.43731,-0.09043 2.87711,-0.135673 4.31726,-0.135676 l 1e-5,-2.419732 c -1.49084,10e-7 -2.9813,0.04684 -4.4692,0.140451 z M 105.3397,202.9308 c 1.44016,-3e-5 2.87997,-0.0453 4.31728,-0.13568 l 0.15192,2.41495 c -1.48789,0.0936 -2.97836,0.14049 -4.46919,0.14045 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1997"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 109.65697,65.553242 c 1.4373,0.09043 2.87143,0.225995 4.30022,0.406491 l 0.30328,-2.40065 c -1.47908,-0.18685 -2.96366,-0.327187 -4.45157,-0.420797 z M 96.722219,202.38864 c 1.428791,0.18047 2.862914,0.31605 4.300231,0.40648 l -0.15194,2.41495 c -1.487908,-0.0936 -2.972488,-0.23389 -4.45157,-0.4208 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1999"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 118.22341,66.635436 c 1.41464,0.269857 2.82046,0.584097 4.21537,0.942245 l 0.60176,-2.343709 c -1.44399,-0.370755 -2.89928,-0.696052 -4.36371,-0.975407 z M 88.240634,200.77069 c 1.394906,0.35812 2.800734,0.67238 4.215371,0.94223 l -0.453419,2.37687 c -1.464437,-0.27934 -2.919738,-0.60461 -4.363716,-0.97541 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2001"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 126.58667,68.782755 c 1.36966,0.44503 2.72501,0.932989 4.06403,1.463142 l 0.89077,-2.249808 c -1.38614,-0.548812 -2.78919,-1.053939 -4.20706,-1.514635 z M 80.028711,198.10247 c 1.339016,0.53013 2.694379,1.01811 4.064034,1.46313 l -0.747739,2.3013 c -1.417873,-0.46069 -2.820944,-0.96578 -4.207068,-1.51463 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2003"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.02244,65.553244 c 1.43731,-0.09043 2.87711,-0.135673 4.31726,-0.135676 l 0,-2.41973 c -1.49083,-1e-6 -2.9813,0.04684 -4.4692,0.140451 z m 4.31726,137.377566 c 1.44016,-4e-5 2.87997,-0.0453 4.31727,-0.13569 l 0.15192,2.41496 c -1.48789,0.0936 -2.97835,0.14048 -4.46918,0.14044 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2005"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 109.65697,65.553243 c 1.4373,0.09043 2.87142,0.225995 4.30022,0.406492 l 0.30328,-2.40065 c -1.47908,-0.186851 -2.96366,-0.327186 -4.45157,-0.420797 z M 96.722218,202.38864 c 1.42879,0.18047 2.862913,0.31605 4.300222,0.40648 l -0.15193,2.41495 c -1.487909,-0.0936 -2.972498,-0.2339 -4.451572,-0.42079 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2007"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 118.2234,66.635437 c 1.41465,0.269857 2.82047,0.584098 4.21538,0.942246 l 0.60176,-2.34371 c -1.44399,-0.370755 -2.89929,-0.69605 -4.36372,-0.975407 z M 88.240632,200.77069 c 1.394906,0.35812 2.800735,0.67238 4.215372,0.94223 l -0.453419,2.37687 c -1.464438,-0.27934 -2.919739,-0.60461 -4.363712,-0.97539 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2009"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 126.58667,68.782756 c 1.36965,0.445031 2.72501,0.93299 4.06403,1.463142 l 0.89077,-2.249808 c -1.38614,-0.548812 -2.78919,-1.053939 -4.20707,-1.514635 z M 80.02871,198.10247 c 1.339016,0.53013 2.694378,1.01811 4.064034,1.46313 l -0.74774,2.3013 c -1.417872,-0.46069 -2.820943,-0.96578 -4.207067,-1.51463 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2011"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 134.61484,71.961338 c 1.30309,0.613185 2.5866,1.267167 3.84861,1.960962 l 1.16572,-2.120423 c -1.30643,-0.718217 -2.63509,-1.395206 -3.98405,-2.029975 z M 72.215945,194.42606 c 1.262036,0.69378 2.54556,1.34774 3.848625,1.96097 l -1.030282,2.18943 c -1.34894,-0.63478 -2.677639,-1.31173 -3.984044,-2.02997 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2013"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 142.18134,76.121053 c 1.21595,0.771669 2.40738,1.581363 3.57248,2.427858 l 1.42229,-1.9576 c -1.20611,-0.87629 -2.43945,-1.71447 -3.69822,-2.513307 z M 64.925576,189.79946 c 1.165117,0.84648 2.356533,1.65618 3.572498,2.42786 l -1.296557,2.04304 c -1.258772,-0.79883 -2.492134,-1.63697 -3.698219,-2.51331 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2015"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 149.16682,81.196301 c 1.10965,0.917986 2.1902,1.870615 3.24003,2.856466 l 1.65641,-1.763908 c -1.08676,-1.020543 -2.20533,-2.006694 -3.35404,-2.956989 z M 58.27256,184.29561 c 1.04984,0.98582 2.13038,1.93847 3.240035,2.85645 l -1.5424,1.86443 c -1.148723,-0.95028 -2.267313,-1.93642 -3.354046,-2.95699 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2017"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 155.46112,87.107042 c 0.98585,1.049822 1.93847,2.130368 2.85646,3.240023 l 1.86444,-1.54239 c -0.95029,-1.148706 -1.93644,-2.267277 -2.95699,-3.354052 z M 52.361822,178.0013 c 0.917996,1.10964 1.870624,2.19021 2.856472,3.24002 l -1.763909,1.65642 c -1.020552,-1.08677 -2.006744,-2.20532 -2.957003,-3.35405 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2019"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 134.61484,71.961339 c 1.30309,0.613185 2.5866,1.267167 3.84861,1.960962 l 1.16571,-2.120426 c -1.30642,-0.718213 -2.63509,-1.395206 -3.98405,-2.029975 z M 72.215941,194.42607 c 1.262041,0.69377 2.54556,1.34774 3.848621,1.96096 l -1.030287,2.18943 c -1.34894,-0.63477 -2.677625,-1.31173 -3.98403,-2.02997 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2021"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 142.18134,76.121055 c 1.21595,0.771669 2.40737,1.581358 3.57248,2.427858 l 1.42229,-1.957599 c -1.20611,-0.876291 -2.43945,-1.71447 -3.69822,-2.513308 z M 64.925576,189.79946 c 1.165116,0.84647 2.356531,1.65618 3.57249,2.42785 l -1.296548,2.04305 c -1.258773,-0.79883 -2.492138,-1.63698 -3.698226,-2.51331 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2023"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 149.16681,81.196298 c 1.10966,0.91799 2.1902,1.87062 3.24003,2.856471 l 1.65642,-1.763909 c -1.08676,-1.020542 -2.20534,-2.006697 -3.35405,-2.956994 z M 58.272559,184.29561 c 1.04984,0.98582 2.130381,1.93847 3.240036,2.85645 l -1.5424,1.86443 c -1.148724,-0.95028 -2.267314,-1.93642 -3.354053,-2.95697 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2025"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 155.46112,87.107044 c 0.98584,1.049817 1.93847,2.130369 2.85646,3.240022 l 1.86444,-1.54239 c -0.95029,-1.148706 -1.93644,-2.267276 -2.957,-3.354056 z M 52.361821,178.0013 c 0.917997,1.10964 1.870624,2.19021 2.856472,3.24002 l -1.763909,1.65642 c -1.020552,-1.08677 -2.006743,-2.20532 -2.957002,-3.35405 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2027"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 160.96497,93.760057 c 0.8465,1.165106 1.65619,2.356531 2.42786,3.572486 l 2.04305,-1.296551 c -0.79883,-1.258756 -1.637,-2.492093 -2.5133,-3.698212 z M 47.286567,171.01581 c 0.7717,1.21596 1.581413,2.40737 2.427872,3.5725 l -1.957609,1.42227 c -0.876278,-1.20611 -1.714503,-2.43944 -2.513299,-3.6982 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2029"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 165.59158,101.05043 c 0.69379,1.26201 1.34778,2.54552 1.96096,3.84861 l 2.18944,-1.03027 c -0.63476,-1.34895 -1.31175,-2.67761 -2.02998,-3.984058 z m -122.46473,62.3989 c 0.613205,1.30308 1.267175,2.58659 1.960973,3.84862 l -2.120423,1.1657 c -0.718231,-1.30643 -1.395258,-2.63508 -2.029978,-3.98406 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2031"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 169.26799,108.86319 c 0.53015,1.33901 1.01811,2.69437 1.46314,4.06403 l 2.30129,-0.74774 c -0.46068,-1.41786 -0.96581,-2.82091 -1.51462,-4.20705 z M 39.948267,155.42116 c 0.44506,1.36964 0.933002,2.72501 1.463159,4.06402 l -2.249811,0.89076 c -0.548833,-1.38614 -1.053984,-2.78919 -1.514632,-4.20706 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2033"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 171.9362,117.07511 c 0.35815,1.3949 0.67238,2.80072 0.94224,4.21536 l 2.37688,-0.4534 c -0.27936,-1.46443 -0.60465,-2.91972 -0.97541,-4.36372 z M 37.800955,147.05789 c 0.269873,1.41463 0.584099,2.82048 0.942254,4.21537 l -2.343712,0.60176 c -0.370761,-1.444 -0.696102,-2.89929 -0.975415,-4.36372 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2035"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 173.55415,125.5567 c 0.1805,1.42878 0.31605,2.8629 0.40648,4.30021 l 2.41497,-0.15192 c -0.0936,-1.4879 -0.23395,-2.97248 -0.4208,-4.45156 z M 36.718762,138.49145 c 0.09045,1.4373 0.225993,2.87145 0.406498,4.30022 l -2.400652,0.30327 c -0.186856,-1.47908 -0.327235,-2.96367 -0.420804,-4.45156 z"
+ sodipodi:nodetypes="cccccccccc" />
+ </g>
+</svg>
diff --git a/dial/try1.svg b/dial/try1.svg
new file mode 100644
index 0000000..9cfb1a7
--- /dev/null
+++ b/dial/try1.svg
@@ -0,0 +1,860 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ viewBox="0 0 210 297"
+ version="1.1"
+ id="svg8"
+ inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
+ sodipodi:docname="try1.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.74681796"
+ inkscape:cx="416.08367"
+ inkscape:cy="907.46405"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ inkscape:window-width="3044"
+ inkscape:window-height="1702"
+ inkscape:window-x="651"
+ inkscape:window-y="199"
+ inkscape:window-maximized="1"
+ showguides="false" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="image"
+ style="display:none">
+ <image
+ sodipodi:absref="/root/projects/metric_clock/base.jpg"
+ xlink:href="base.jpg"
+ style="fill:#ff0000;stroke:#000000"
+ y="37.229919"
+ x="8.6489792"
+ id="image929"
+ preserveAspectRatio="none"
+ height="194.02777"
+ width="194.02777" />
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1378"
+ cx="105.49754"
+ cy="134.01634"
+ r="71.176346" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="old pips"
+ style="display:none">
+ <g
+ id="g1842">
+ <g
+ id="g1141">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1135"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1137"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1147"
+ transform="rotate(7.2,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1143"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1145"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1153"
+ transform="rotate(14.4,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1149"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1151"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1159"
+ transform="rotate(21.6,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1155"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1157"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1165"
+ transform="rotate(28.8,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1161"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1163"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1171"
+ transform="rotate(36,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1167"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1169"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1177"
+ transform="rotate(43.2,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1173"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1175"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1183"
+ transform="rotate(50.4,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1179"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1181"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1189"
+ transform="rotate(57.6,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1185"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1187"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1195"
+ transform="rotate(64.8,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1191"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1193"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1201"
+ transform="rotate(72,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1197"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1199"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1207"
+ transform="rotate(79.2,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1203"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1205"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1213"
+ transform="rotate(86.4,105.599,134.19615)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1209"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1211"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1237"
+ transform="matrix(-0.06302185,1.0017036,-1.0017036,-0.06302185,246.6788,36.874562)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1233"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1235"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1243"
+ transform="matrix(-0.18807164,0.98590605,-0.98590605,-0.18807164,257.76399,55.32396)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1239"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1241"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1249"
+ transform="matrix(-0.31015544,0.95456027,-0.95456027,-0.31015544,266.44943,75.017219)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1245"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1247"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1255"
+ transform="matrix(-0.42734789,0.90816049,-0.90816049,-0.42734789,272.59816,95.643766)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1251"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1253"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1261"
+ transform="matrix(-0.53780081,0.84743848,-0.84743848,-0.53780081,276.11322,116.87831)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1257"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1259"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1267"
+ transform="matrix(-0.6397723,0.77335186,-0.77335186,-0.6397723,276.93917,138.38596)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1263"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1265"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1273"
+ transform="matrix(-0.73165419,0.68706902,-0.68706902,-0.73165419,275.06298,159.82754)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1269"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1271"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1279"
+ transform="matrix(-0.81199746,0.58995069,-0.58995069,-0.81199746,270.51424,180.8649)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1275"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1277"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1285"
+ transform="matrix(-0.87953505,0.48352848,-0.48352848,-0.87953505,263.36469,201.16626)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1281"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1283"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1291"
+ transform="matrix(-0.93320184,0.36948075,-0.36948075,-0.93320184,253.72709,220.41147)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1287"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1289"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1297"
+ transform="matrix(-0.97215148,0.24960607,-0.24960607,-0.97215148,241.7534,238.297)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1293"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1295"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ <g
+ id="g1303"
+ transform="matrix(-0.99576972,0.12579497,-0.12579497,-0.99576972,227.63249,254.5408)">
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1299"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.73463"
+ y="62.477757" />
+ <rect
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="rect1301"
+ width="3.9854157"
+ height="2.1983638"
+ x="103.47796"
+ y="203.71619" />
+ </g>
+ </g>
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1845"
+ cx="105.49754"
+ cy="134.01634"
+ r="71.176346" />
+ <g
+ id="g1939"
+ style="display:inline">
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.197022;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1933"
+ cx="105.33971"
+ cy="134.17418"
+ r="71.176346" />
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.190324;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1935"
+ cx="105.33971"
+ cy="134.17418"
+ r="68.756615" />
+ </g>
+ </g>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <g
+ id="g2214"
+ style="fill:#000000">
+ <g
+ id="g995"
+ transform="matrix(1.3967804,0,0,1.3967804,-39.841068,-37.660351)"
+ style="stroke:#000000;fill:#000000">
+ <path
+ style="fill:#000000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 142.62011,171.00294 c -0.77532,0.8116 -1.74601,1.45294 -1.69031,2.60136 l -0.0451,12.04127 -1.00434,1.41555 1.36953,1.46493 c 0.73978,-0.78263 1.87134,-1.76247 1.86355,-2.60431 l -0.0436,-12.18219 0.82224,-1.20249 z"
+ id="path951"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path960"
+ style="fill:#000000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 138.45302,178.09954 8.05529,0.0319 0.002,0.12594 c 0,1.11333 -0.76094,2.01586 -1.69962,2.01586 v 0 l -7.44358,-0.0173 -0.59615,-0.002 c 0,-1.11332 0.74339,-2.15445 1.68206,-2.15445 z"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <path
+ id="path1018"
+ style="fill:#000000;stroke:#000000;stroke-width:0.279356;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 191.21554,167.80098 c 2.07131,2.50704 2.72939,5.89366 1.74769,8.99397 -0.9817,3.10031 -3.46912,5.49091 -6.60594,6.34882 l -0.57387,-2.63912 c 2.62754,-0.97621 4.44349,-3.39627 4.64629,-6.19196 0.2028,-2.79568 -1.24488,-5.45248 -3.70404,-6.79768 l -0.006,-0.0887 c 1.48627,-0.22523 2.72685,-1.25245 3.22532,-2.67064 0.49847,-1.41819 0.17342,-2.9957 -0.84507,-4.10133 l 1.99216,-1.87171 c 1.42335,1.07313 2.26313,2.75 2.26993,4.53255 0.007,1.78256 -0.82016,3.46578 -2.23526,4.54975"
+ sodipodi:nodetypes="csccsccsccsc" />
+ <path
+ id="path1054"
+ style="fill:#000000;stroke:#000000;stroke-width:0.264936px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 184.01836,129.17286 h 4.74008 l -1.10723,2.89817 h -7.97032 l 6.58128,-15.39828 c 0.64288,-1.43399 0.66474,-2.74183 -0.0525,-3.95916 -0.71725,-1.21734 -2.02482,-1.96458 -3.43774,-1.96458 v -2.73813 c 2.41457,0 4.6491,1.27696 5.87481,3.3573 1.22572,2.08034 1.10365,4.45043 0.0897,6.76585 z"
+ sodipodi:nodetypes="cccccsccscc" />
+ <path
+ id="path1063"
+ style="fill:#000000;stroke:#000000;stroke-width:0.369564px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 154.58289,91.398189 c 0.0317,2.0853 -0.99235,3.051069 -2.39154,4.313975 l -1.90537,-1.927228 1.27826,-1.802542 c 0.10504,-6.443567 0.10155,-9.947887 0.10155,-16.39201 -0.0317,-2.085299 0.99235,-3.051068 2.39154,-4.313974 l 1.90537,1.927227 -1.27826,1.802542 c -0.10504,6.443568 -0.10155,9.947887 -0.10155,16.39201 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <g
+ id="g1110"
+ transform="matrix(1.3967804,0,0,1.3967804,-39.734659,-37.673591)"
+ style="fill:#000000">
+ <path
+ id="path1066"
+ style="fill:#000000;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 99.335085,82.703014 c 0.0227,1.49293 -0.71046,2.18436 -1.71218,3.08851 l -1.36412,-1.37976 0.91515,-1.2905 c 0.0752,-4.613159 0.0727,-7.122014 0.0727,-11.735569 -0.0227,-1.492933 0.71046,-2.184358 1.71218,-3.088513 l 1.364125,1.379764 -0.915155,1.290498 c -0.0752,4.613157 -0.0727,7.122012 -0.0727,11.73557 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1104"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.34794,77.22145 c -0.009,-4.008906 -1.45649,-5.885766 -2.94934,-7.436765 -1.49285,1.551 -2.94034,3.427859 -2.94934,7.436765 0.009,4.008906 1.45649,5.885765 2.94934,7.436764 1.49285,-1.551 2.94072,-3.427858 2.94934,-7.436764 z m -7.75346,-10e-7 c 0,-3.970502 1.39203,-7.485929 3.44361,-8.696446 h 2.72102 c 2.05158,1.210517 3.44361,4.725944 3.44361,8.696446 m 0,0 c 0,3.970503 -1.39203,7.48593 -3.44361,8.696447 h -2.72102 c -2.05158,-1.210517 -3.44361,-4.725944 -3.44361,-8.696447" />
+ </g>
+ <path
+ id="circle1126"
+ style="fill:#000000;stroke:#000000;stroke-width:0.279356;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 57.446559,81.1209 -2.645526,-0.03869 c 0.310133,-4.038027 1.954701,-7.858164 4.67469,-10.858747 3.042891,3.356796 4.728275,7.725495 4.728275,12.256195 0,4.5307 -1.483364,8.594103 -4.526253,11.950899 l -2.091156,-1.926994 c 2.391907,-2.761641 3.708501,-6.292758 3.708501,-9.868867 0,-2.542037 -0.677265,-5.116944 -1.966044,-7.397368 -1.023808,1.811574 -1.664547,3.814156 -1.882487,5.883573 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1133"
+ style="fill:#000000;stroke:#000000;stroke-width:0.279356;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 61.624487,214.00383 2.645526,0.0387 c -0.310133,4.03802 -1.954701,7.85816 -4.67469,10.85875 -3.042891,-3.3568 -4.728275,-7.72549 -4.728275,-12.2562 0,-4.5307 1.483364,-8.5941 4.526253,-11.9509 l 2.091156,1.927 c -2.391907,2.76164 -3.708501,6.29276 -3.708501,9.86887 0,2.54203 0.677266,5.11694 1.966044,7.39736 1.023808,-1.81157 1.664547,-3.81416 1.882487,-5.88357 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1322"
+ style="fill:#000000;stroke:#000000;stroke-width:0.279356;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 30.387569,126.62648 c 0,3.03079 -2.456939,5.48773 -5.487727,5.48773 v -2.98534 c 1.382031,0 2.502387,-1.12036 2.502387,-2.50239 v -13.33797 c 0,-3.03079 2.456939,-5.48772 5.487727,-5.48772 v 2.98534 c -1.382031,0 -2.502387,1.12035 -2.502387,2.50238 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1349"
+ style="fill:#000000;stroke:#000000;stroke-width:0.369564px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 32.135778,158.73458 h -8.534899 l -1.08677,2.93725 h 4.840776 l -2.268669,4.21904 c -2.927165,5.06914 -2.225582,11.88582 1.86251,16.94799 l 2.160795,-1.78883 c -3.497283,-4.11884 -3.862837,-10.28756 -1.360188,-13.81861 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1367"
+ style="fill:#000000;stroke:#000000;stroke-width:0.279356;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 102.06091,221.95603 c 2.7533,-0.37629 5.49465,0.76699 7.16474,2.98805 1.67009,2.22106 2.00734,5.17206 0.88144,7.71266 -1.12591,2.5406 -3.53862,4.27292 -6.30584,4.52754 l 0.25251,2.74421 c 5.01873,-0.46179 8.98782,-4.4489 9.42687,-9.46967 0.43905,-5.02078 -2.77777,-9.63627 -7.64019,-10.96213 l 0.33396,-0.72392 h 4.64717 l 1.07745,-2.97499 h -7.74775 z"
+ sodipodi:nodetypes="cssccscccccc" />
+ </g>
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.275196;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1907"
+ cx="107.2839"
+ cy="149.68745"
+ r="99.417725" />
+ <circle
+ style="display:inline;fill:none;stroke:#ff0000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1912"
+ cx="107.2839"
+ cy="149.68745"
+ r="96.037895" />
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1916"
+ cx="107.2839"
+ cy="149.68745"
+ r="96.037895" />
+ <path
+ id="path1963"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 23.12525,103.42085 c 0.969082,-1.76276 1.993316,-3.494636 3.071169,-5.193068 l -2.853685,-1.81101 c -1.115786,1.758199 -2.176062,3.551027 -3.179255,5.375828 z m 165.24612,97.72628 c 1.07783,-1.69845 2.10209,-3.43032 3.07118,-5.19307 l 2.96176,1.62825 c -1.0032,1.8248 -2.06343,3.61765 -3.17926,5.37582 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1965"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 29.587609,93.237795 c 1.182371,-1.627392 2.415594,-3.217247 3.697814,-4.767192 l -2.604199,-2.154395 c -1.327352,1.604495 -2.603965,3.250291 -3.827958,4.934976 z M 181.28238,210.90432 c 1.28219,-1.54997 2.51542,-3.13981 3.69779,-4.76722 l 2.73435,1.98662 c -1.22399,1.68468 -2.50055,3.33052 -3.82796,4.93498 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1967"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 37.275282,83.944998 c 1.37702,-1.466379 2.799773,-2.889127 4.26615,-4.266152 L 39.22778,77.215052 c -1.517975,1.42547 -2.990802,2.8983 -4.416285,4.416283 z M 173.02637,219.69607 c 1.46634,-1.37704 2.88912,-2.79979 4.26613,-4.26616 l 2.46378,2.31366 c -1.42547,1.51799 -2.89826,2.99085 -4.41628,4.41628 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1969"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 46.067041,75.688984 c 1.549937,-1.282216 3.139797,-2.515436 4.767195,-3.697815 l -1.986609,-2.734352 c -1.684672,1.223989 -3.330473,2.500606 -4.934975,3.827964 z M 163.73356,227.38374 c 1.62737,-1.18239 3.21725,-2.41561 4.76719,-3.69782 l 2.15438,2.6042 c -1.6045,1.32736 -3.25027,2.60403 -4.93497,3.82797 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1979"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 55.82422,68.599981 c 1.698427,-1.077856 3.430308,-2.102083 5.193064,-3.07117 l -1.628242,-2.961774 c -1.82479,1.003189 -3.617618,2.063462 -5.375828,3.179256 z m 97.72629,165.246129 c 1.76273,-0.96913 3.49464,-1.99333 5.19307,-3.07118 l 1.81098,2.85369 c -1.75819,1.11579 -3.55099,2.1761 -5.37581,3.17924 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1981"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 66.392952,62.78977 c 1.82012,-0.856483 3.666721,-1.655574 5.537031,-2.396087 L 70.685794,57.25119 c -1.93614,0.766574 -3.847712,1.593782 -5.731909,2.480419 z m 76.244858,176.19147 c 1.87029,-0.74055 3.7169,-1.53962 5.53703,-2.39611 l 1.43906,3.05817 c -1.8842,0.88663 -3.79573,1.7139 -5.73191,2.48041 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1983"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 77.606549,58.349995 c 1.913125,-0.621614 3.845309,-1.18296 5.79369,-1.683225 l -0.840527,-3.273648 c -2.016936,0.517859 -4.017126,1.098968 -5.997579,1.742457 z M 131.16756,242.70815 c 1.94836,-0.5003 3.88056,-1.06163 5.79368,-1.68324 l 1.04441,3.21441 c -1.98045,0.64351 -3.98063,1.22465 -5.99758,1.74245 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1985"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 89.288191,55.350656 c 1.975933,-0.376927 3.963247,-0.691684 5.958961,-0.943806 l -0.423594,-3.353186 c -2.06595,0.260992 -4.123193,0.586829 -6.168687,0.977027 z M 119.32064,244.96806 c 1.99569,-0.25215 3.98303,-0.56688 5.95896,-0.94382 l 0.63331,3.31997 c -2.04548,0.3902 -4.10273,0.7161 -6.16868,0.97703 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1995"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.25362,53.839073 c 2.00761,-0.126311 4.01869,-0.189505 6.03027,-0.18951 l 1e-5,-3.379834 c -2.08238,2e-6 -4.16422,0.06543 -6.24249,0.196179 z m 6.03027,191.886277 c 2.01158,-4e-5 4.02268,-0.0633 6.03029,-0.18951 l 0.2122,3.37315 c -2.07826,0.13074 -4.16012,0.19624 -6.24248,0.19618 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1997"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.31416,53.839072 c 2.0076,0.12631 4.01076,0.315665 6.00647,0.567778 l 0.42361,-3.353181 c -2.06595,-0.260988 -4.13958,-0.457008 -6.21786,-0.587761 z M 95.247158,244.96807 c 1.995707,0.25208 3.998862,0.44146 6.006482,0.56777 l -0.21223,3.37315 c -2.078281,-0.13074 -4.151914,-0.32669 -6.217866,-0.58776 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1999"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 125.2796,55.350659 c 1.97594,0.376931 3.93956,0.815855 5.88795,1.316109 l 0.84052,-3.273646 c -2.01693,-0.517864 -4.04965,-0.972232 -6.09514,-1.36243 z M 83.400246,242.70815 c 1.948377,0.50022 3.91201,0.93917 5.887948,1.31609 l -0.633327,3.31997 c -2.045497,-0.39018 -4.078233,-0.84451 -6.095153,-1.36244 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2001"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 136.96124,58.349992 c 1.91311,0.621609 3.80624,1.303181 5.67656,2.043688 l 1.24421,-3.142488 c -1.93614,-0.766569 -3.89589,-1.472121 -5.87634,-2.115612 z M 71.929993,238.98124 c 1.870311,0.74047 3.763456,1.42207 5.676563,2.04367 l -1.044427,3.21441 c -1.980457,-0.64349 -3.940239,-1.34899 -5.87635,-2.11561 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2011"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 148.17483,62.789774 c 1.82013,0.856485 3.61291,1.769955 5.37566,2.739034 l 1.62826,-2.961766 c -1.8248,-1.003191 -3.68065,-1.948796 -5.56485,-2.835429 z M 61.017275,233.8461 c 1.762787,0.96906 3.555588,1.88249 5.375684,2.73904 l -1.439078,3.05816 c -1.884173,-0.88665 -3.740074,-1.8322 -5.564835,-2.83543 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2013"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 158.74357,68.599983 c 1.69841,1.077852 3.36258,2.208817 4.98997,3.391184 l 1.98662,-2.734337 c -1.68467,-1.223985 -3.40737,-2.394738 -5.1656,-3.510538 z M 50.83423,227.38375 c 1.627413,1.18235 3.291559,2.31332 4.989995,3.39119 l -1.811005,2.85368 c -1.758228,-1.11579 -3.480964,-2.28649 -5.1656,-3.51054 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2015"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 168.50075,75.68899 c 1.54994,1.282225 3.05923,2.612838 4.52561,3.989856 L 175.34,77.215053 c -1.51797,-1.425474 -3.08036,-2.80291 -4.68486,-4.130264 z M 41.541428,219.69608 c 1.466396,1.37698 2.975673,2.70762 4.525617,3.98984 l -2.154394,2.6042 c -1.604514,-1.32734 -3.166938,-2.70476 -4.684866,-4.13027 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2017"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 177.2925,83.944997 c 1.37702,1.466371 2.70762,2.975656 3.98985,4.525601 l 2.60421,-2.154381 c -1.32734,-1.60449 -2.70478,-3.166888 -4.13026,-4.684874 z M 33.285425,210.90432 c 1.282238,1.54992 2.612851,3.05924 3.989864,4.52559 l -2.463794,2.31366 c -1.425487,-1.51798 -2.80298,-3.08035 -4.130284,-4.68487 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <g
+ id="g2198"
+ style="fill:#000000">
+ <path
+ id="path1950"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 11.246004,149.68745 c 0,-2.01157 0.0632,-4.02265 0.189508,-6.03026 l -3.3731631,-0.21223 c -0.1307527,2.07826 -0.1961779,4.16012 -0.1961779,6.24249 z m 191.886276,6.03027 c 0.12627,-2.00761 0.18951,-4.01869 0.18951,-6.03027 h 3.37983 c 0,2.08238 -0.0654,4.16424 -0.19618,6.24249 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1957"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 12.003291,137.65071 c 0.252117,-1.9957 0.566879,-3.98302 0.943807,-5.95896 l -3.3199654,-0.63332 c -0.3901962,2.04548 -0.7160315,4.10272 -0.9770227,6.16868 z M 201.6207,167.68315 c 0.3769,-1.97594 0.69167,-3.96325 0.94379,-5.95896 l 3.35318,0.42361 c -0.26098,2.06596 -0.58676,4.12321 -0.97702,6.16868 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1959"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 14.26321,125.80381 c 0.500258,-1.94839 1.061613,-3.88057 1.683221,-5.79369 l -3.214411,-1.04443 c -0.643485,1.98044 -1.224592,3.98063 -1.742458,5.99758 z m 184.35816,53.56098 c 0.62157,-1.91313 1.18295,-3.84531 1.6832,-5.79369 l 3.27365,0.84054 c -0.51786,2.01695 -1.09892,4.01715 -1.74246,5.99758 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1961"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 17.990122,114.33354 c 0.740509,-1.8703 1.539605,-3.7169 2.396089,-5.53703 l -3.058162,-1.43907 c -0.886628,1.88418 -1.713841,3.79576 -2.480416,5.73191 z m 176.191468,76.24485 c 0.85645,-1.82013 1.65556,-3.66673 2.39608,-5.53703 l 3.14248,1.2442 c -0.76657,1.93614 -1.59373,3.84775 -2.48041,5.73191 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1971"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 23.12525,103.42085 c 0.969083,-1.76276 1.993317,-3.494636 3.071169,-5.193068 l -2.853684,-1.81101 C 22.226948,98.174971 21.166672,99.9678 20.16348,101.7926 Z m 165.24612,97.72628 c 1.07783,-1.69845 2.10209,-3.43032 3.07118,-5.19307 l 2.96176,1.62825 c -1.0032,1.8248 -2.06343,3.61765 -3.17926,5.37582 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1973"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 29.587609,93.237795 c 1.182372,-1.627392 2.415594,-3.217247 3.697816,-4.767192 l -2.6042,-2.154395 c -1.327353,1.604495 -2.603964,3.250291 -3.827959,4.934976 z M 181.28238,210.90432 c 1.28219,-1.54997 2.51542,-3.13981 3.69779,-4.76722 l 2.73435,1.98662 c -1.22399,1.68468 -2.50055,3.33052 -3.82796,4.93498 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1975"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 37.275282,83.944998 c 1.37702,-1.466379 2.799775,-2.889127 4.26615,-4.266152 L 39.22778,77.215052 c -1.517975,1.42547 -2.990801,2.8983 -4.416285,4.416283 z M 173.02637,219.69607 c 1.46634,-1.37704 2.88912,-2.79979 4.26613,-4.26616 l 2.46378,2.31366 c -1.42547,1.51799 -2.89826,2.99085 -4.41627,4.41628 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1977"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 46.067041,75.688984 c 1.549939,-1.282216 3.139799,-2.515436 4.767195,-3.697815 l -1.986608,-2.734352 c -1.684672,1.223989 -3.330474,2.500606 -4.934976,3.827964 z M 163.73356,227.38374 c 1.62737,-1.18239 3.21725,-2.41561 4.76719,-3.69782 l 2.15438,2.6042 c -1.6045,1.32736 -3.25027,2.60403 -4.93497,3.82797 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1987"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 55.824218,68.599981 c 1.698429,-1.077854 3.43031,-2.102083 5.193065,-3.07117 l -1.628241,-2.961773 c -1.824792,1.003188 -3.617621,2.063463 -5.375828,3.179257 z M 153.55051,233.84611 c 1.76273,-0.96913 3.49464,-1.99333 5.19307,-3.07118 l 1.81098,2.85369 c -1.75819,1.11579 -3.55099,2.1761 -5.37581,3.17924 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1989"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 66.39295,62.78977 c 1.820122,-0.856482 3.666722,-1.655574 5.537033,-2.396086 l -1.244189,-3.142493 c -1.93614,0.766573 -3.847712,1.593782 -5.731909,2.480418 z m 76.24486,176.19147 c 1.87029,-0.74055 3.7169,-1.53962 5.53703,-2.39611 l 1.43906,3.05817 c -1.8842,0.88663 -3.79575,1.7139 -5.73191,2.48041 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1991"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 77.606548,58.349995 c 1.913125,-0.621614 3.84531,-1.18296 5.793691,-1.683225 l -0.840528,-3.273648 c -2.016937,0.517859 -4.017125,1.09897 -5.997579,1.742457 z M 131.16756,242.70815 c 1.94836,-0.5003 3.88056,-1.06163 5.79368,-1.68324 l 1.04441,3.21441 c -1.98045,0.64351 -3.98063,1.22465 -5.99756,1.74247 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1993"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 89.288191,55.350656 c 1.975933,-0.376925 3.963247,-0.691684 5.95896,-0.943806 l -0.423593,-3.353186 c -2.06595,0.260992 -4.123194,0.586829 -6.168688,0.977027 z M 119.32064,244.96806 c 1.99569,-0.25215 3.98303,-0.56688 5.95896,-0.94382 l 0.63331,3.31997 c -2.04548,0.3902 -4.10273,0.7161 -6.16868,0.97703 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2003"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.25362,53.839074 c 2.00761,-0.12631 4.01869,-0.189505 6.03027,-0.189509 v -3.379832 c -2.08237,-1e-6 -4.16423,0.06543 -6.24249,0.19618 z m 6.03027,191.886296 c 2.01158,-6e-5 4.02268,-0.0633 6.03027,-0.18953 l 0.2122,3.37317 c -2.07825,0.13073 -4.1601,0.19622 -6.24246,0.19616 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2005"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.31416,53.839073 c 2.0076,0.126311 4.01075,0.315665 6.00647,0.56778 l 0.42361,-3.353181 c -2.06595,-0.26099 -4.13958,-0.457007 -6.21786,-0.587761 z M 95.247156,244.96807 c 1.995706,0.25208 3.998861,0.44146 6.006464,0.56777 l -0.21221,3.37315 c -2.078283,-0.13074 -4.151928,-0.32671 -6.217869,-0.58775 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2007"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 125.27959,55.35066 c 1.97595,0.376931 3.93957,0.815857 5.88796,1.316111 l 0.84052,-3.273648 c -2.01693,-0.517863 -4.04967,-0.972229 -6.09516,-1.362429 z M 83.400243,242.70815 c 1.948378,0.50022 3.912012,0.93917 5.887949,1.31609 l -0.633327,3.31997 c -2.045498,-0.39018 -4.078234,-0.84451 -6.095147,-1.36241 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2009"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 136.96124,58.349993 c 1.9131,0.621611 3.80624,1.303183 5.67656,2.043689 l 1.24421,-3.142488 c -1.93614,-0.76657 -3.89589,-1.472122 -5.87636,-2.115613 z M 71.929992,238.98124 c 1.870311,0.74047 3.763454,1.42207 5.676563,2.04367 l -1.044429,3.21441 c -1.980456,-0.64349 -3.940238,-1.34899 -5.876349,-2.11561 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2019"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 148.17483,62.789776 c 1.82013,0.856485 3.61291,1.769954 5.37566,2.739033 l 1.62824,-2.961769 c -1.82478,-1.003186 -3.68064,-1.948797 -5.56484,-2.83543 z M 61.017269,233.84611 c 1.762794,0.96905 3.555588,1.8825 5.375678,2.73903 l -1.439084,3.05816 c -1.884173,-0.88664 -3.740054,-1.8322 -5.564815,-2.83543 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2021"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 158.74357,68.599986 c 1.69841,1.077852 3.36256,2.20881 4.98997,3.391184 l 1.98662,-2.734336 c -1.68467,-1.223986 -3.40737,-2.394738 -5.1656,-3.510539 z M 50.83423,227.38375 c 1.627411,1.18234 3.291556,2.31332 4.989984,3.39118 l -1.810993,2.85369 c -1.758229,-1.11579 -3.480969,-2.2865 -5.165609,-3.51054 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2023"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 168.50073,75.688986 c 1.54996,1.28223 3.05923,2.612845 4.52561,3.989862 L 175.34,77.215055 c -1.51797,-1.425473 -3.08038,-2.802915 -4.68487,-4.130271 z M 41.541426,219.69608 c 1.466396,1.37698 2.975675,2.70762 4.525619,3.98984 l -2.154394,2.6042 c -1.604515,-1.32734 -3.16694,-2.70476 -4.684876,-4.13024 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2025"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 177.2925,83.945 c 1.37701,1.466364 2.70762,2.975657 3.98985,4.525599 l 2.60421,-2.15438 c -1.32734,-1.60449 -2.70478,-3.166887 -4.13028,-4.68488 z M 33.285423,210.90432 c 1.28224,1.54992 2.612851,3.05924 3.989864,4.52559 l -2.463793,2.31366 c -1.425487,-1.51798 -2.802979,-3.08035 -4.130283,-4.68487 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2027"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 184.98017,93.237798 c 1.18238,1.627397 2.31334,3.291556 3.39119,4.989978 l 2.85369,-1.810997 c -1.11579,-1.758205 -2.28653,-3.480906 -3.51053,-5.16559 z M 26.196408,201.14712 c 1.077895,1.69843 2.208887,3.36257 3.391204,4.99 l -2.73435,1.9866 c -1.223968,-1.68467 -2.394784,-3.40737 -3.510527,-5.16558 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2029"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 191.44253,103.42085 c 0.96907,1.76275 1.88255,3.55553 2.73903,5.37566 l 3.05817,-1.43906 c -0.88662,-1.88419 -1.83223,-3.74003 -2.83544,-5.56485 z M 20.386197,190.57841 c 0.856513,1.82012 1.769965,3.6129 2.739048,5.37568 l -2.961765,1.62822 c -1.003211,-1.82479 -1.948869,-3.68063 -2.835433,-5.56485 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2031"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 196.57767,114.33356 c 0.7405,1.8703 1.42207,3.76344 2.04368,5.67656 l 3.2144,-1.04443 c -0.64347,-1.98044 -1.34902,-3.94019 -2.11559,-5.87633 z M 15.946414,179.36482 c 0.621651,1.91308 1.303199,3.80624 2.043712,5.67654 l -3.142492,1.2442 c -0.766599,-1.93614 -1.472184,-3.89589 -2.115608,-5.87634 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2033"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 200.30457,125.80381 c 0.50026,1.94837 0.93917,3.91199 1.3161,5.88793 l 3.31998,-0.6333 c -0.3902,-2.04549 -0.84456,-4.07821 -1.36243,-6.09516 z M 12.947091,167.68317 c 0.376953,1.97592 0.815858,3.93959 1.316122,5.88794 l -3.273651,0.84053 c -0.517872,-2.01695 -0.972302,-4.04967 -1.3624406,-6.09516 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2035"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.265841;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 202.56449,137.65073 c 0.25212,1.99569 0.44146,3.99884 0.56777,6.00644 l 3.37318,-0.21219 c -0.13074,-2.07827 -0.32678,-4.15191 -0.58777,-6.21786 z m -191.128985,18.067 c 0.126339,2.00759 0.315663,4.01079 0.567789,6.00646 l -3.3531841,0.42361 c -0.2609968,-2.06595 -0.4570755,-4.1396 -0.5877708,-6.21786 z"
+ sodipodi:nodetypes="cccccccccc" />
+ </g>
+ </g>
+</svg>
diff --git a/dial/try2.svg b/dial/try2.svg
new file mode 100644
index 0000000..fd61d07
--- /dev/null
+++ b/dial/try2.svg
@@ -0,0 +1,299 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ viewBox="0 0 210 297"
+ version="1.1"
+ id="svg8"
+ inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
+ sodipodi:docname="try2.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.9872718"
+ inkscape:cx="445.90903"
+ inkscape:cy="522.79404"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ inkscape:window-width="3926"
+ inkscape:window-height="2029"
+ inkscape:window-x="-94"
+ inkscape:window-y="194"
+ inkscape:window-maximized="1"
+ showguides="false" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="image"
+ style="display:none">
+ <image
+ sodipodi:absref="/root/projects/metric_clock/base.jpg"
+ xlink:href="base.jpg"
+ style="fill:#ff0000;stroke:#000000"
+ y="37.184856"
+ x="3.8290849"
+ id="image929"
+ preserveAspectRatio="none"
+ height="194.02777"
+ width="194.02777" />
+ </g>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1916"
+ cx="100.63864"
+ cy="134.26129"
+ r="68.959427" />
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1907"
+ cx="100.63864"
+ cy="134.26129"
+ r="71.386292" />
+ <g
+ id="g2198"
+ style="fill:#ff0000;stroke-width:0.2785345;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.71804391,0,0,0.71804391,23.604096,26.779127)">
+ <path
+ id="path1950"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 11.246004,149.68745 c 0,-2.01157 0.0632,-4.02265 0.189508,-6.03026 l -3.3731631,-0.21223 c -0.1307527,2.07826 -0.1961779,4.16012 -0.1961779,6.24249 z m 191.886276,6.03027 c 0.12627,-2.00761 0.18951,-4.01869 0.18951,-6.03027 h 3.37983 c 0,2.08238 -0.0654,4.16424 -0.19618,6.24249 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1957"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 12.003291,137.65071 c 0.252117,-1.9957 0.566879,-3.98302 0.943807,-5.95896 l -3.3199654,-0.63332 c -0.3901962,2.04548 -0.7160315,4.10272 -0.9770227,6.16868 z M 201.6207,167.68315 c 0.3769,-1.97594 0.69167,-3.96325 0.94379,-5.95896 l 3.35318,0.42361 c -0.26098,2.06596 -0.58676,4.12321 -0.97702,6.16868 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1959"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 14.26321,125.80381 c 0.500258,-1.94839 1.061613,-3.88057 1.683221,-5.79369 l -3.214411,-1.04443 c -0.643485,1.98044 -1.224592,3.98063 -1.742458,5.99758 z m 184.35816,53.56098 c 0.62157,-1.91313 1.18295,-3.84531 1.6832,-5.79369 l 3.27365,0.84054 c -0.51786,2.01695 -1.09892,4.01715 -1.74246,5.99758 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1961"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 17.990122,114.33354 c 0.740509,-1.8703 1.539605,-3.7169 2.396089,-5.53703 l -3.058162,-1.43907 c -0.886628,1.88418 -1.713841,3.79576 -2.480416,5.73191 z m 176.191468,76.24485 c 0.85645,-1.82013 1.65556,-3.66673 2.39608,-5.53703 l 3.14248,1.2442 c -0.76657,1.93614 -1.59373,3.84775 -2.48041,5.73191 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1971"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 23.12525,103.42085 c 0.969083,-1.76276 1.993317,-3.494636 3.071169,-5.193068 l -2.853684,-1.81101 C 22.226948,98.174971 21.166672,99.9678 20.16348,101.7926 Z m 165.24612,97.72628 c 1.07783,-1.69845 2.10209,-3.43032 3.07118,-5.19307 l 2.96176,1.62825 c -1.0032,1.8248 -2.06343,3.61765 -3.17926,5.37582 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1973"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 29.587609,93.237795 c 1.182372,-1.627392 2.415594,-3.217247 3.697816,-4.767192 l -2.6042,-2.154395 c -1.327353,1.604495 -2.603964,3.250291 -3.827959,4.934976 z M 181.28238,210.90432 c 1.28219,-1.54997 2.51542,-3.13981 3.69779,-4.76722 l 2.73435,1.98662 c -1.22399,1.68468 -2.50055,3.33052 -3.82796,4.93498 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1975"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 37.275282,83.944998 c 1.37702,-1.466379 2.799775,-2.889127 4.26615,-4.266152 L 39.22778,77.215052 c -1.517975,1.42547 -2.990801,2.8983 -4.416285,4.416283 z M 173.02637,219.69607 c 1.46634,-1.37704 2.88912,-2.79979 4.26613,-4.26616 l 2.46378,2.31366 c -1.42547,1.51799 -2.89826,2.99085 -4.41627,4.41628 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1977"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 46.067041,75.688984 c 1.549939,-1.282216 3.139799,-2.515436 4.767195,-3.697815 l -1.986608,-2.734352 c -1.684672,1.223989 -3.330474,2.500606 -4.934976,3.827964 z M 163.73356,227.38374 c 1.62737,-1.18239 3.21725,-2.41561 4.76719,-3.69782 l 2.15438,2.6042 c -1.6045,1.32736 -3.25027,2.60403 -4.93497,3.82797 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1987"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 55.824218,68.599981 c 1.698429,-1.077854 3.43031,-2.102083 5.193065,-3.07117 l -1.628241,-2.961773 c -1.824792,1.003188 -3.617621,2.063463 -5.375828,3.179257 z M 153.55051,233.84611 c 1.76273,-0.96913 3.49464,-1.99333 5.19307,-3.07118 l 1.81098,2.85369 c -1.75819,1.11579 -3.55099,2.1761 -5.37581,3.17924 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1989"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 66.39295,62.78977 c 1.820122,-0.856482 3.666722,-1.655574 5.537033,-2.396086 l -1.244189,-3.142493 c -1.93614,0.766573 -3.847712,1.593782 -5.731909,2.480418 z m 76.24486,176.19147 c 1.87029,-0.74055 3.7169,-1.53962 5.53703,-2.39611 l 1.43906,3.05817 c -1.8842,0.88663 -3.79575,1.7139 -5.73191,2.48041 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1991"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 77.606548,58.349995 c 1.913125,-0.621614 3.84531,-1.18296 5.793691,-1.683225 l -0.840528,-3.273648 c -2.016937,0.517859 -4.017125,1.09897 -5.997579,1.742457 z M 131.16756,242.70815 c 1.94836,-0.5003 3.88056,-1.06163 5.79368,-1.68324 l 1.04441,3.21441 c -1.98045,0.64351 -3.98063,1.22465 -5.99756,1.74247 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1993"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 89.288191,55.350656 c 1.975933,-0.376925 3.963247,-0.691684 5.95896,-0.943806 l -0.423593,-3.353186 c -2.06595,0.260992 -4.123194,0.586829 -6.168688,0.977027 z M 119.32064,244.96806 c 1.99569,-0.25215 3.98303,-0.56688 5.95896,-0.94382 l 0.63331,3.31997 c -2.04548,0.3902 -4.10273,0.7161 -6.16868,0.97703 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2003"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.25362,53.839074 c 2.00761,-0.12631 4.01869,-0.189505 6.03027,-0.189509 v -3.379832 c -2.08237,-1e-6 -4.16423,0.06543 -6.24249,0.19618 z m 6.03027,191.886296 c 2.01158,-6e-5 4.02268,-0.0633 6.03027,-0.18953 l 0.2122,3.37317 c -2.07825,0.13073 -4.1601,0.19622 -6.24246,0.19616 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2005"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.31416,53.839073 c 2.0076,0.126311 4.01075,0.315665 6.00647,0.56778 l 0.42361,-3.353181 c -2.06595,-0.26099 -4.13958,-0.457007 -6.21786,-0.587761 z M 95.247156,244.96807 c 1.995706,0.25208 3.998861,0.44146 6.006464,0.56777 l -0.21221,3.37315 c -2.078283,-0.13074 -4.151928,-0.32671 -6.217869,-0.58775 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2007"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 125.27959,55.35066 c 1.97595,0.376931 3.93957,0.815857 5.88796,1.316111 l 0.84052,-3.273648 c -2.01693,-0.517863 -4.04967,-0.972229 -6.09516,-1.362429 z M 83.400243,242.70815 c 1.948378,0.50022 3.912012,0.93917 5.887949,1.31609 l -0.633327,3.31997 c -2.045498,-0.39018 -4.078234,-0.84451 -6.095147,-1.36241 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2009"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 136.96124,58.349993 c 1.9131,0.621611 3.80624,1.303183 5.67656,2.043689 l 1.24421,-3.142488 c -1.93614,-0.76657 -3.89589,-1.472122 -5.87636,-2.115613 z M 71.929992,238.98124 c 1.870311,0.74047 3.763454,1.42207 5.676563,2.04367 l -1.044429,3.21441 c -1.980456,-0.64349 -3.940238,-1.34899 -5.876349,-2.11561 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2019"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 148.17483,62.789776 c 1.82013,0.856485 3.61291,1.769954 5.37566,2.739033 l 1.62824,-2.961769 c -1.82478,-1.003186 -3.68064,-1.948797 -5.56484,-2.83543 z M 61.017269,233.84611 c 1.762794,0.96905 3.555588,1.8825 5.375678,2.73903 l -1.439084,3.05816 c -1.884173,-0.88664 -3.740054,-1.8322 -5.564815,-2.83543 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2021"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 158.74357,68.599986 c 1.69841,1.077852 3.36256,2.20881 4.98997,3.391184 l 1.98662,-2.734336 c -1.68467,-1.223986 -3.40737,-2.394738 -5.1656,-3.510539 z M 50.83423,227.38375 c 1.627411,1.18234 3.291556,2.31332 4.989984,3.39118 l -1.810993,2.85369 c -1.758229,-1.11579 -3.480969,-2.2865 -5.165609,-3.51054 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2023"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 168.50073,75.688986 c 1.54996,1.28223 3.05923,2.612845 4.52561,3.989862 L 175.34,77.215055 c -1.51797,-1.425473 -3.08038,-2.802915 -4.68487,-4.130271 z M 41.541426,219.69608 c 1.466396,1.37698 2.975675,2.70762 4.525619,3.98984 l -2.154394,2.6042 c -1.604515,-1.32734 -3.16694,-2.70476 -4.684876,-4.13024 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2025"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 177.2925,83.945 c 1.37701,1.466364 2.70762,2.975657 3.98985,4.525599 l 2.60421,-2.15438 c -1.32734,-1.60449 -2.70478,-3.166887 -4.13028,-4.68488 z M 33.285423,210.90432 c 1.28224,1.54992 2.612851,3.05924 3.989864,4.52559 l -2.463793,2.31366 c -1.425487,-1.51798 -2.802979,-3.08035 -4.130283,-4.68487 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2027"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 184.98017,93.237798 c 1.18238,1.627397 2.31334,3.291556 3.39119,4.989978 l 2.85369,-1.810997 c -1.11579,-1.758205 -2.28653,-3.480906 -3.51053,-5.16559 z M 26.196408,201.14712 c 1.077895,1.69843 2.208887,3.36257 3.391204,4.99 l -2.73435,1.9866 c -1.223968,-1.68467 -2.394784,-3.40737 -3.510527,-5.16558 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2029"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 191.44253,103.42085 c 0.96907,1.76275 1.88255,3.55553 2.73903,5.37566 l 3.05817,-1.43906 c -0.88662,-1.88419 -1.83223,-3.74003 -2.83544,-5.56485 z M 20.386197,190.57841 c 0.856513,1.82012 1.769965,3.6129 2.739048,5.37568 l -2.961765,1.62822 c -1.003211,-1.82479 -1.948869,-3.68063 -2.835433,-5.56485 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2031"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 196.57767,114.33356 c 0.7405,1.8703 1.42207,3.76344 2.04368,5.67656 l 3.2144,-1.04443 c -0.64347,-1.98044 -1.34902,-3.94019 -2.11559,-5.87633 z M 15.946414,179.36482 c 0.621651,1.91308 1.303199,3.80624 2.043712,5.67654 l -3.142492,1.2442 c -0.766599,-1.93614 -1.472184,-3.89589 -2.115608,-5.87634 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2033"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 200.30457,125.80381 c 0.50026,1.94837 0.93917,3.91199 1.3161,5.88793 l 3.31998,-0.6333 c -0.3902,-2.04549 -0.84456,-4.07821 -1.36243,-6.09516 z M 12.947091,167.68317 c 0.376953,1.97592 0.815858,3.93959 1.316122,5.88794 l -3.273651,0.84053 c -0.517872,-2.01695 -0.972302,-4.04967 -1.3624406,-6.09516 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2035"
+ style="display:inline;fill:#ff0000;stroke:#000000;stroke-width:0.2785345;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 202.56449,137.65073 c 0.25212,1.99569 0.44146,3.99884 0.56777,6.00644 l 3.37318,-0.21219 c -0.13074,-2.07827 -0.32678,-4.15191 -0.58777,-6.21786 z m -191.128985,18.067 c 0.126339,2.00759 0.315663,4.01079 0.567789,6.00646 l -3.3531841,0.42361 c -0.2609968,-2.06595 -0.4570755,-4.1396 -0.5877708,-6.21786 z"
+ sodipodi:nodetypes="cccccccccc" />
+ </g>
+ <path
+ id="path1322"
+ style="fill:#ff0000;stroke:#800080;stroke-width:0.20059;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -9.1630385,117.43187 c 0.915852,1.97414 0.05794,4.31695 -1.9162025,5.2328 l -0.902116,-1.94454 c 0.900203,-0.41762 1.291407,-1.48594 0.873781,-2.38614 l -4.030503,-8.68785 c -0.915851,-1.97414 -0.05793,-4.31694 1.916207,-5.23279 l 0.902116,1.94454 c -0.900203,0.41762 -1.291411,1.48593 -0.873785,2.38613 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path2891"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.20059;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -21.026462,118.153 c 0,2.17624 -1.76419,3.94043 -3.940429,3.94043 v -2.1436 c 0.992359,0 1.796824,-0.80447 1.796824,-1.79683 v -9.57725 c 0,-2.17624 1.76419,-3.94042 3.940429,-3.94042 v 2.1436 c -0.992359,0 -1.796824,0.80446 -1.796824,1.79682 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <g
+ id="g3120"
+ style="fill:#ff0000;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 138.03726,171.24469 c -0.77761,0.81399 -1.75116,1.45722 -1.6953,2.60903 l -0.0452,12.07679 -1.00731,1.41973 1.37357,1.46925 c 0.74197,-0.78494 1.87686,-1.76767 1.86905,-2.612 l -0.0437,-12.21812 0.82467,-1.20604 z"
+ id="path951"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path960"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 133.85787,178.36222 8.07906,0.032 0.002,0.12631 c 0,1.11661 -0.76318,2.0218 -1.70463,2.0218 v 0 l -7.46554,-0.0173 -0.59791,-0.002 c 0,-1.11661 0.74559,-2.16081 1.68702,-2.16081 z"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <path
+ id="path1018"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 160.90525,147.2676 c 1.48729,1.80016 1.95982,4.23191 1.25492,6.45806 -0.70491,2.22616 -2.49098,3.94272 -4.74336,4.55874 l -0.41206,-1.89501 c 1.88669,-0.70096 3.19062,-2.43867 3.33624,-4.4461 0.14562,-2.00742 -0.89388,-3.91512 -2.65966,-4.88103 l -0.004,-0.0637 c 1.06721,-0.16173 1.958,-0.89931 2.31592,-1.91764 0.35792,-1.01832 0.12452,-2.15104 -0.6068,-2.94493 l 1.43046,-1.34397 c 1.02203,0.77055 1.62503,1.97462 1.62991,3.25457 0.005,1.27995 -0.58891,2.48858 -1.60502,3.26692"
+ sodipodi:nodetypes="csccsccsccsc" />
+ <path
+ id="path1054"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 155.73736,119.53091 h 3.40358 l -0.79504,2.08102 h -5.72304 l 4.72565,-11.05665 c 0.46162,-1.02966 0.47732,-1.96875 -0.0377,-2.84285 -0.51502,-0.8741 -1.45391,-1.41065 -2.46845,-1.41065 v -1.9661 c 1.73376,0 3.33826,0.91691 4.21837,2.41069 0.88012,1.49378 0.79247,3.1956 0.0644,4.85818 z"
+ sodipodi:nodetypes="cccccsccscc" />
+ <path
+ id="path1063"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 134.6014,92.40704 c 0.0228,1.497337 -0.71255,2.190802 -1.71723,3.097623 l -1.36814,-1.383834 0.91785,-1.294304 c 0.0754,-4.626764 0.0729,-7.14302 0.0729,-11.770183 -0.0228,-1.497336 0.71255,-2.190801 1.71723,-3.097623 l 1.36814,1.383834 -0.91784,1.294304 c -0.0754,4.626765 -0.0729,7.14302 -0.0729,11.770183 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <g
+ id="g1110"
+ transform="matrix(1.0029497,0,0,1.0029497,-4.9271339,-0.27216559)"
+ style="fill:#ff0000;stroke-width:0.199412;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ id="path1066"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.199412;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 99.335085,82.703014 c 0.0227,1.49293 -0.71046,2.18436 -1.71218,3.08851 l -1.36412,-1.37976 0.91515,-1.2905 c 0.0752,-4.613159 0.0727,-7.122014 0.0727,-11.735569 -0.0227,-1.492933 0.71046,-2.184358 1.71218,-3.088513 l 1.364125,1.379764 -0.915155,1.290498 c -0.0752,4.613157 -0.0727,7.122012 -0.0727,11.73557 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1104"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.199412;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.34794,77.22145 c -0.009,-4.008906 -1.45649,-5.885766 -2.94934,-7.436765 -1.49285,1.551 -2.94034,3.427859 -2.94934,7.436765 0.009,4.008906 1.45649,5.885765 2.94934,7.436764 1.49285,-1.551 2.94072,-3.427858 2.94934,-7.436764 z m -7.75346,-10e-7 c 0,-3.970502 1.39203,-7.485929 3.44361,-8.696446 h 2.72102 c 2.05158,1.210517 3.44361,4.725944 3.44361,8.696446 m 0,0 c 0,3.970503 -1.39203,7.48593 -3.44361,8.696447 h -2.72102 c -2.05158,-1.210517 -3.44361,-4.725944 -3.44361,-8.696447" />
+ </g>
+ <path
+ id="circle1126"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 64.853248,85.027495 -1.899604,-0.02778 c 0.222689,-2.899481 1.403561,-5.642507 3.356633,-7.797057 2.184929,2.410327 3.395109,5.547245 3.395109,8.800486 0,3.253242 -1.065121,6.170943 -3.250049,8.58127 l -1.501541,-1.383666 c 1.717494,-1.982979 2.662866,-4.518476 2.662866,-7.08628 0,-1.825294 -0.486306,-3.67419 -1.411706,-5.311635 -0.735139,1.30079 -1.195218,2.738732 -1.351708,4.224664 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1133"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 67.853184,180.44327 1.899603,0.0278 c -0.222689,2.89948 -1.403561,5.64251 -3.356632,7.79706 -2.18493,-2.41033 -3.395109,-5.54724 -3.395109,-8.80049 0,-3.25324 1.06512,-6.17094 3.250048,-8.58127 l 1.501542,1.38367 c -1.717494,1.98298 -2.662867,4.51848 -2.662867,7.08628 0,1.82529 0.486307,3.67419 1.411706,5.31163 0.735139,-1.30078 1.195218,-2.73873 1.351709,-4.22466 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1349"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 46.678996,140.75753 h -6.128433 l -0.780348,2.10907 h 3.47589 l -1.629004,3.02946 c -2.101833,3.63986 -1.598066,8.53454 1.337364,12.1694 L 44.50601,156.781 c -2.511202,-2.95751 -2.773686,-7.38692 -0.976674,-9.92237 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1367"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 96.888311,186.1533 c 1.97699,-0.27019 3.945399,0.55074 5.144599,2.14555 1.1992,1.59482 1.44136,3.71377 0.63291,5.53803 -0.80845,1.82426 -2.54088,3.06815 -4.527869,3.25097 l 0.181314,1.97047 c 3.603665,-0.33159 6.453645,-3.19451 6.768905,-6.79964 0.31526,-3.60514 -1.99456,-6.91927 -5.485991,-7.87129 l 0.239798,-0.51981 h 3.336873 l 0.77366,-2.13617 h -5.563229 z"
+ sodipodi:nodetypes="cssccscccccc" />
+ <path
+ id="path2903"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 46.878234,104.783 c -1.346097,-0.23347 -2.717168,0.2461 -3.624294,1.26767 -0.907126,1.02155 -1.221185,2.43972 -0.830183,3.74876 l 1.852962,6.81017 c 0.181143,0.60644 0.03565,1.26345 -0.384603,1.73671 -0.420249,0.47327 -1.05543,0.69543 -1.679042,0.58728 l -0.371582,2.14248 c 1.346097,0.23347 2.717168,-0.2461 3.624295,-1.26767 0.907126,-1.02155 1.221185,-2.43972 0.830183,-3.74876 l -1.852962,-6.81017 c -0.181143,-0.60644 -0.03565,-1.26345 0.384603,-1.73671 0.420249,-0.47327 1.05543,-0.69543 1.679042,-0.58728 z"
+ sodipodi:nodetypes="csccsccsccscc" />
+ <path
+ id="path3188"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -3.6524867,104.83764 c -1.366193,0 -2.635148,0.7068 -3.354361,1.86836 -0.719214,1.16155 -0.786313,2.61252 -0.177369,3.83549 l 2.989454,6.39336 c 0.28211,0.56657 0.251026,1.23877 -0.08217,1.77689 -0.333194,0.53812 -0.921068,0.86556 -1.553989,0.86556 l -1e-6,2.17447 c 1.366193,0 2.635148,-0.7068 3.354362,-1.86836 0.719214,-1.16155 0.786313,-2.61252 0.177369,-3.83549 l -2.989454,-6.39336 c -0.28211,-0.56657 -0.251026,-1.23877 0.08217,-1.77689 0.333194,-0.53812 0.921068,-0.86556 1.553989,-0.86556 z"
+ sodipodi:nodetypes="csccsccsccscc" />
+ </g>
+</svg>
diff --git a/dial/try3.svg b/dial/try3.svg
new file mode 100644
index 0000000..fe0f89c
--- /dev/null
+++ b/dial/try3.svg
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="210mm"
+ height="297mm"
+ viewBox="0 0 210 297"
+ version="1.1"
+ id="svg8"
+ inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
+ sodipodi:docname="try3.svg">
+ <defs
+ id="defs2" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.1123202"
+ inkscape:cx="498.87637"
+ inkscape:cy="545.626"
+ inkscape:document-units="mm"
+ inkscape:current-layer="layer1"
+ inkscape:document-rotation="0"
+ showgrid="false"
+ inkscape:window-width="3801"
+ inkscape:window-height="2031"
+ inkscape:window-x="15"
+ inkscape:window-y="68"
+ inkscape:window-maximized="1"
+ showguides="false" />
+ <metadata
+ id="metadata5">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="image"
+ style="display:none">
+ <image
+ sodipodi:absref="/root/projects/metric_clock/base.jpg"
+ xlink:href="base.jpg"
+ style="fill:#ff0000;stroke:#000000"
+ y="37.184856"
+ x="3.8290849"
+ id="image929"
+ preserveAspectRatio="none"
+ height="194.02777"
+ width="194.02777" />
+ </g>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ style="display:inline">
+ <path
+ id="path1322"
+ style="fill:#ff0000;stroke:#800080;stroke-width:0.20059;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -42.569444,101.38292 c 0.915852,1.97414 0.05794,4.31695 -1.916203,5.2328 l -0.902116,-1.94454 c 0.900203,-0.41762 1.291407,-1.48594 0.873781,-2.38614 l -4.030503,-8.687855 c -0.915851,-1.97414 -0.05793,-4.31694 1.916207,-5.23279 l 0.902116,1.94454 c -0.900203,0.41762 -1.291411,1.48593 -0.873785,2.38613 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path2891"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.20059;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -54.432868,102.10405 c 0,2.17624 -1.76419,3.94043 -3.940429,3.94043 v -2.1436 c 0.992359,0 1.796824,-0.80447 1.796824,-1.79683 v -9.577255 c 0,-2.17624 1.76419,-3.94042 3.940429,-3.94042 v 2.1436 c -0.992359,0 -1.796824,0.80446 -1.796824,1.79682 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path3188"
+ style="fill:#ff0000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m -37.058892,88.788685 c -1.366193,0 -2.635148,0.7068 -3.354361,1.86836 -0.719214,1.16155 -0.786313,2.61252 -0.177369,3.83549 l 2.989454,6.393365 c 0.28211,0.56657 0.251026,1.23877 -0.08217,1.77689 -0.333194,0.53812 -0.921068,0.86556 -1.553989,0.86556 l -10e-7,2.17447 c 1.366193,0 2.635148,-0.7068 3.354362,-1.86836 0.719214,-1.16155 0.786313,-2.61252 0.177369,-3.835495 l -2.989454,-6.39336 c -0.28211,-0.56657 -0.251026,-1.23877 0.08217,-1.77689 0.333194,-0.53812 0.921068,-0.86556 1.553989,-0.86556 z"
+ sodipodi:nodetypes="csccsccsccscc" />
+ <g
+ id="g3554"
+ transform="matrix(0.98923371,0,0,0.98923371,1.501849,0.57564236)">
+ <g
+ id="g3212"
+ transform="matrix(1.3758923,0,0,1.3758923,-34.238319,-40.900596)">
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1916"
+ cx="100.63864"
+ cy="134.26129"
+ r="68.959427" />
+ <circle
+ style="display:inline;fill:none;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="circle1907"
+ cx="100.63864"
+ cy="134.26129"
+ r="71.386292" />
+ </g>
+ <g
+ id="g3505"
+ style="fill:#000000">
+ <g
+ id="g2198"
+ style="fill:#000000;stroke-width:0.278535;stroke-miterlimit:4;stroke-dasharray:none"
+ transform="matrix(0.98795109,0,0,0.98795109,-1.7616251,-4.0554014)">
+ <path
+ id="path1950"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 11.246004,149.68745 c 0,-2.01157 0.0632,-4.02265 0.189508,-6.03026 l -3.3731631,-0.21223 c -0.1307527,2.07826 -0.1961779,4.16012 -0.1961779,6.24249 z m 191.886276,6.03027 c 0.12627,-2.00761 0.18951,-4.01869 0.18951,-6.03027 h 3.37983 c 0,2.08238 -0.0654,4.16424 -0.19618,6.24249 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1957"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 12.003291,137.65071 c 0.252117,-1.9957 0.566879,-3.98302 0.943807,-5.95896 l -3.3199654,-0.63332 c -0.3901962,2.04548 -0.7160315,4.10272 -0.9770227,6.16868 z M 201.6207,167.68315 c 0.3769,-1.97594 0.69167,-3.96325 0.94379,-5.95896 l 3.35318,0.42361 c -0.26098,2.06596 -0.58676,4.12321 -0.97702,6.16868 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1959"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 14.26321,125.80381 c 0.500258,-1.94839 1.061613,-3.88057 1.683221,-5.79369 l -3.214411,-1.04443 c -0.643485,1.98044 -1.224592,3.98063 -1.742458,5.99758 z m 184.35816,53.56098 c 0.62157,-1.91313 1.18295,-3.84531 1.6832,-5.79369 l 3.27365,0.84054 c -0.51786,2.01695 -1.09892,4.01715 -1.74246,5.99758 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1961"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 17.990122,114.33354 c 0.740509,-1.8703 1.539605,-3.7169 2.396089,-5.53703 l -3.058162,-1.43907 c -0.886628,1.88418 -1.713841,3.79576 -2.480416,5.73191 z m 176.191468,76.24485 c 0.85645,-1.82013 1.65556,-3.66673 2.39608,-5.53703 l 3.14248,1.2442 c -0.76657,1.93614 -1.59373,3.84775 -2.48041,5.73191 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1971"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 23.12525,103.42085 c 0.969083,-1.76276 1.993317,-3.494636 3.071169,-5.193068 l -2.853684,-1.81101 C 22.226948,98.174971 21.166672,99.9678 20.16348,101.7926 Z m 165.24612,97.72628 c 1.07783,-1.69845 2.10209,-3.43032 3.07118,-5.19307 l 2.96176,1.62825 c -1.0032,1.8248 -2.06343,3.61765 -3.17926,5.37582 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1973"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 29.587609,93.237795 c 1.182372,-1.627392 2.415594,-3.217247 3.697816,-4.767192 l -2.6042,-2.154395 c -1.327353,1.604495 -2.603964,3.250291 -3.827959,4.934976 z M 181.28238,210.90432 c 1.28219,-1.54997 2.51542,-3.13981 3.69779,-4.76722 l 2.73435,1.98662 c -1.22399,1.68468 -2.50055,3.33052 -3.82796,4.93498 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1975"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 37.275282,83.944998 c 1.37702,-1.466379 2.799775,-2.889127 4.26615,-4.266152 L 39.22778,77.215052 c -1.517975,1.42547 -2.990801,2.8983 -4.416285,4.416283 z M 173.02637,219.69607 c 1.46634,-1.37704 2.88912,-2.79979 4.26613,-4.26616 l 2.46378,2.31366 c -1.42547,1.51799 -2.89826,2.99085 -4.41627,4.41628 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1977"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 46.067041,75.688984 c 1.549939,-1.282216 3.139799,-2.515436 4.767195,-3.697815 l -1.986608,-2.734352 c -1.684672,1.223989 -3.330474,2.500606 -4.934976,3.827964 z M 163.73356,227.38374 c 1.62737,-1.18239 3.21725,-2.41561 4.76719,-3.69782 l 2.15438,2.6042 c -1.6045,1.32736 -3.25027,2.60403 -4.93497,3.82797 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1987"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 55.824218,68.599981 c 1.698429,-1.077854 3.43031,-2.102083 5.193065,-3.07117 l -1.628241,-2.961773 c -1.824792,1.003188 -3.617621,2.063463 -5.375828,3.179257 z M 153.55051,233.84611 c 1.76273,-0.96913 3.49464,-1.99333 5.19307,-3.07118 l 1.81098,2.85369 c -1.75819,1.11579 -3.55099,2.1761 -5.37581,3.17924 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1989"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 66.39295,62.78977 c 1.820122,-0.856482 3.666722,-1.655574 5.537033,-2.396086 l -1.244189,-3.142493 c -1.93614,0.766573 -3.847712,1.593782 -5.731909,2.480418 z m 76.24486,176.19147 c 1.87029,-0.74055 3.7169,-1.53962 5.53703,-2.39611 l 1.43906,3.05817 c -1.8842,0.88663 -3.79575,1.7139 -5.73191,2.48041 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1991"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 77.606548,58.349995 c 1.913125,-0.621614 3.84531,-1.18296 5.793691,-1.683225 l -0.840528,-3.273648 c -2.016937,0.517859 -4.017125,1.09897 -5.997579,1.742457 z M 131.16756,242.70815 c 1.94836,-0.5003 3.88056,-1.06163 5.79368,-1.68324 l 1.04441,3.21441 c -1.98045,0.64351 -3.98063,1.22465 -5.99756,1.74247 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path1993"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 89.288191,55.350656 c 1.975933,-0.376925 3.963247,-0.691684 5.95896,-0.943806 l -0.423593,-3.353186 c -2.06595,0.260992 -4.123194,0.586829 -6.168688,0.977027 z M 119.32064,244.96806 c 1.99569,-0.25215 3.98303,-0.56688 5.95896,-0.94382 l 0.63331,3.31997 c -2.04548,0.3902 -4.10273,0.7161 -6.16868,0.97703 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2003"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 101.25362,53.839074 c 2.00761,-0.12631 4.01869,-0.189505 6.03027,-0.189509 v -3.379832 c -2.08237,-1e-6 -4.16423,0.06543 -6.24249,0.19618 z m 6.03027,191.886296 c 2.01158,-6e-5 4.02268,-0.0633 6.03027,-0.18953 l 0.2122,3.37317 c -2.07825,0.13073 -4.1601,0.19622 -6.24246,0.19616 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2005"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.31416,53.839073 c 2.0076,0.126311 4.01075,0.315665 6.00647,0.56778 l 0.42361,-3.353181 c -2.06595,-0.26099 -4.13958,-0.457007 -6.21786,-0.587761 z M 95.247156,244.96807 c 1.995706,0.25208 3.998861,0.44146 6.006464,0.56777 l -0.21221,3.37315 c -2.078283,-0.13074 -4.151928,-0.32671 -6.217869,-0.58775 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2007"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 125.27959,55.35066 c 1.97595,0.376931 3.93957,0.815857 5.88796,1.316111 l 0.84052,-3.273648 c -2.01693,-0.517863 -4.04967,-0.972229 -6.09516,-1.362429 z M 83.400243,242.70815 c 1.948378,0.50022 3.912012,0.93917 5.887949,1.31609 l -0.633327,3.31997 c -2.045498,-0.39018 -4.078234,-0.84451 -6.095147,-1.36241 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2009"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 136.96124,58.349993 c 1.9131,0.621611 3.80624,1.303183 5.67656,2.043689 l 1.24421,-3.142488 c -1.93614,-0.76657 -3.89589,-1.472122 -5.87636,-2.115613 z M 71.929992,238.98124 c 1.870311,0.74047 3.763454,1.42207 5.676563,2.04367 l -1.044429,3.21441 c -1.980456,-0.64349 -3.940238,-1.34899 -5.876349,-2.11561 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2019"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 148.17483,62.789776 c 1.82013,0.856485 3.61291,1.769954 5.37566,2.739033 l 1.62824,-2.961769 c -1.82478,-1.003186 -3.68064,-1.948797 -5.56484,-2.83543 z M 61.017269,233.84611 c 1.762794,0.96905 3.555588,1.8825 5.375678,2.73903 l -1.439084,3.05816 c -1.884173,-0.88664 -3.740054,-1.8322 -5.564815,-2.83543 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2021"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 158.74357,68.599986 c 1.69841,1.077852 3.36256,2.20881 4.98997,3.391184 l 1.98662,-2.734336 c -1.68467,-1.223986 -3.40737,-2.394738 -5.1656,-3.510539 z M 50.83423,227.38375 c 1.627411,1.18234 3.291556,2.31332 4.989984,3.39118 l -1.810993,2.85369 c -1.758229,-1.11579 -3.480969,-2.2865 -5.165609,-3.51054 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2023"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 168.50073,75.688986 c 1.54996,1.28223 3.05923,2.612845 4.52561,3.989862 L 175.34,77.215055 c -1.51797,-1.425473 -3.08038,-2.802915 -4.68487,-4.130271 z M 41.541426,219.69608 c 1.466396,1.37698 2.975675,2.70762 4.525619,3.98984 l -2.154394,2.6042 c -1.604515,-1.32734 -3.16694,-2.70476 -4.684876,-4.13024 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2025"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 177.2925,83.945 c 1.37701,1.466364 2.70762,2.975657 3.98985,4.525599 l 2.60421,-2.15438 c -1.32734,-1.60449 -2.70478,-3.166887 -4.13028,-4.68488 z M 33.285423,210.90432 c 1.28224,1.54992 2.612851,3.05924 3.989864,4.52559 l -2.463793,2.31366 c -1.425487,-1.51798 -2.802979,-3.08035 -4.130283,-4.68487 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2027"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 184.98017,93.237798 c 1.18238,1.627397 2.31334,3.291556 3.39119,4.989978 l 2.85369,-1.810997 c -1.11579,-1.758205 -2.28653,-3.480906 -3.51053,-5.16559 z M 26.196408,201.14712 c 1.077895,1.69843 2.208887,3.36257 3.391204,4.99 l -2.73435,1.9866 c -1.223968,-1.68467 -2.394784,-3.40737 -3.510527,-5.16558 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2029"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 191.44253,103.42085 c 0.96907,1.76275 1.88255,3.55553 2.73903,5.37566 l 3.05817,-1.43906 c -0.88662,-1.88419 -1.83223,-3.74003 -2.83544,-5.56485 z M 20.386197,190.57841 c 0.856513,1.82012 1.769965,3.6129 2.739048,5.37568 l -2.961765,1.62822 c -1.003211,-1.82479 -1.948869,-3.68063 -2.835433,-5.56485 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2031"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 196.57767,114.33356 c 0.7405,1.8703 1.42207,3.76344 2.04368,5.67656 l 3.2144,-1.04443 c -0.64347,-1.98044 -1.34902,-3.94019 -2.11559,-5.87633 z M 15.946414,179.36482 c 0.621651,1.91308 1.303199,3.80624 2.043712,5.67654 l -3.142492,1.2442 c -0.766599,-1.93614 -1.472184,-3.89589 -2.115608,-5.87634 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2033"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 200.30457,125.80381 c 0.50026,1.94837 0.93917,3.91199 1.3161,5.88793 l 3.31998,-0.6333 c -0.3902,-2.04549 -0.84456,-4.07821 -1.36243,-6.09516 z M 12.947091,167.68317 c 0.376953,1.97592 0.815858,3.93959 1.316122,5.88794 l -3.273651,0.84053 c -0.517872,-2.01695 -0.972302,-4.04967 -1.3624406,-6.09516 z"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ id="path2035"
+ style="display:inline;fill:#000000;stroke:#000000;stroke-width:0.278535;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 202.56449,137.65073 c 0.25212,1.99569 0.44146,3.99884 0.56777,6.00644 l 3.37318,-0.21219 c -0.13074,-2.07827 -0.32678,-4.15191 -0.58777,-6.21786 z m -191.128985,18.067 c 0.126339,2.00759 0.315663,4.01079 0.567789,6.00646 l -3.3531841,0.42361 c -0.2609968,-2.06595 -0.4570755,-4.1396 -0.5877708,-6.21786 z"
+ sodipodi:nodetypes="cccccccccc" />
+ </g>
+ <g
+ id="g3208"
+ transform="matrix(1.3758923,0,0,1.3758923,-34.238319,-40.900596)"
+ style="fill:#000000">
+ <g
+ id="g3120"
+ style="fill:#000000;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 138.03726,171.24469 c -0.77761,0.81399 -1.75116,1.45722 -1.6953,2.60903 l -0.0452,12.07679 -1.00731,1.41973 1.37357,1.46925 c 0.74197,-0.78494 1.87686,-1.76767 1.86905,-2.612 l -0.0437,-12.21812 0.82467,-1.20604 z"
+ id="path951"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path960"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 133.85787,178.36222 8.07906,0.032 0.002,0.12631 c 0,1.11661 -0.76318,2.0218 -1.70463,2.0218 v 0 l -7.46554,-0.0173 -0.59791,-0.002 c 0,-1.11661 0.74559,-2.16081 1.68702,-2.16081 z"
+ sodipodi:nodetypes="ccccccccc" />
+ </g>
+ <path
+ id="path1018"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 160.90525,147.2676 c 1.48729,1.80016 1.95982,4.23191 1.25492,6.45806 -0.70491,2.22616 -2.49098,3.94272 -4.74336,4.55874 l -0.41206,-1.89501 c 1.88669,-0.70096 3.19062,-2.43867 3.33624,-4.4461 0.14562,-2.00742 -0.89388,-3.91512 -2.65966,-4.88103 l -0.004,-0.0637 c 1.06721,-0.16173 1.958,-0.89931 2.31592,-1.91764 0.35792,-1.01832 0.12452,-2.15104 -0.6068,-2.94493 l 1.43046,-1.34397 c 1.02203,0.77055 1.62503,1.97462 1.62991,3.25457 0.005,1.27995 -0.58891,2.48858 -1.60502,3.26692"
+ sodipodi:nodetypes="csccsccsccsc" />
+ <path
+ id="path1054"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 155.73736,119.53091 h 3.40358 l -0.79504,2.08102 h -5.72304 l 4.72565,-11.05665 c 0.46162,-1.02966 0.47732,-1.96875 -0.0377,-2.84285 -0.51502,-0.8741 -1.45391,-1.41065 -2.46845,-1.41065 v -1.9661 c 1.73376,0 3.33826,0.91691 4.21837,2.41069 0.88012,1.49378 0.79247,3.1956 0.0644,4.85818 z"
+ sodipodi:nodetypes="cccccsccscc" />
+ <path
+ id="path1063"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 134.6014,92.40704 c 0.0228,1.497337 -0.71255,2.190802 -1.71723,3.097623 l -1.36814,-1.383834 0.91785,-1.294304 c 0.0754,-4.626764 0.0729,-7.14302 0.0729,-11.770183 -0.0228,-1.497336 0.71255,-2.190801 1.71723,-3.097623 l 1.36814,1.383834 -0.91784,1.294304 c -0.0754,4.626765 -0.0729,7.14302 -0.0729,11.770183 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <g
+ id="g1110"
+ transform="matrix(1.0029497,0,0,1.0029497,-4.9271339,-0.27216559)"
+ style="fill:#000000;stroke-width:0.199412;stroke-miterlimit:4;stroke-dasharray:none">
+ <path
+ id="path1066"
+ style="fill:#000000;stroke:#000000;stroke-width:0.199412;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 99.335085,82.703014 c 0.0227,1.49293 -0.71046,2.18436 -1.71218,3.08851 l -1.36412,-1.37976 0.91515,-1.2905 c 0.0752,-4.613159 0.0727,-7.122014 0.0727,-11.735569 -0.0227,-1.492933 0.71046,-2.184358 1.71218,-3.088513 l 1.364125,1.379764 -0.915155,1.290498 c -0.0752,4.613157 -0.0727,7.122012 -0.0727,11.73557 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1104"
+ style="fill:#000000;stroke:#000000;stroke-width:0.199412;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 113.34794,77.22145 c -0.009,-4.008906 -1.45649,-5.885766 -2.94934,-7.436765 -1.49285,1.551 -2.94034,3.427859 -2.94934,7.436765 0.009,4.008906 1.45649,5.885765 2.94934,7.436764 1.49285,-1.551 2.94072,-3.427858 2.94934,-7.436764 z m -7.75346,-10e-7 c 0,-3.970502 1.39203,-7.485929 3.44361,-8.696446 h 2.72102 c 2.05158,1.210517 3.44361,4.725944 3.44361,8.696446 m 0,0 c 0,3.970503 -1.39203,7.48593 -3.44361,8.696447 h -2.72102 c -2.05158,-1.210517 -3.44361,-4.725944 -3.44361,-8.696447" />
+ </g>
+ <path
+ id="circle1126"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 64.853248,85.027495 -1.899604,-0.02778 c 0.222689,-2.899481 1.403561,-5.642507 3.356633,-7.797057 2.184929,2.410327 3.395109,5.547245 3.395109,8.800486 0,3.253242 -1.065121,6.170943 -3.250049,8.58127 l -1.501541,-1.383666 c 1.717494,-1.982979 2.662866,-4.518476 2.662866,-7.08628 0,-1.825294 -0.486306,-3.67419 -1.411706,-5.311635 -0.735139,1.30079 -1.195218,2.738732 -1.351708,4.224664 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1133"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 67.853184,180.44327 1.899603,0.0278 c -0.222689,2.89948 -1.403561,5.64251 -3.356632,7.79706 -2.18493,-2.41033 -3.395109,-5.54724 -3.395109,-8.80049 0,-3.25324 1.06512,-6.17094 3.250048,-8.58127 l 1.501542,1.38367 c -1.717494,1.98298 -2.662867,4.51848 -2.662867,7.08628 0,1.82529 0.486307,3.67419 1.411706,5.31163 0.735139,-1.30078 1.195218,-2.73873 1.351709,-4.22466 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1349"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 46.678996,140.75753 h -6.128433 l -0.780348,2.10907 h 3.47589 l -1.629004,3.02946 c -2.101833,3.63986 -1.598066,8.53454 1.337364,12.1694 L 44.50601,156.781 c -2.511202,-2.95751 -2.773686,-7.38692 -0.976674,-9.92237 z"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ id="path1367"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 96.888311,186.1533 c 1.97699,-0.27019 3.945399,0.55074 5.144599,2.14555 1.1992,1.59482 1.44136,3.71377 0.63291,5.53803 -0.80845,1.82426 -2.54088,3.06815 -4.527869,3.25097 l 0.181314,1.97047 c 3.603665,-0.33159 6.453645,-3.19451 6.768905,-6.79964 0.31526,-3.60514 -1.99456,-6.91927 -5.485991,-7.87129 l 0.239798,-0.51981 h 3.336873 l 0.77366,-2.13617 h -5.563229 z"
+ sodipodi:nodetypes="cssccscccccc" />
+ <path
+ id="path2903"
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ d="m 46.878234,104.783 c -1.346097,-0.23347 -2.717168,0.2461 -3.624294,1.26767 -0.907126,1.02155 -1.221185,2.43972 -0.830183,3.74876 l 1.852962,6.81017 c 0.181143,0.60644 0.03565,1.26345 -0.384603,1.73671 -0.420249,0.47327 -1.05543,0.69543 -1.679042,0.58728 l -0.371582,2.14248 c 1.346097,0.23347 2.717168,-0.2461 3.624295,-1.26767 0.907126,-1.02155 1.221185,-2.43972 0.830183,-3.74876 l -1.852962,-6.81017 c -0.181143,-0.60644 -0.03565,-1.26345 0.384603,-1.73671 0.420249,-0.47327 1.05543,-0.69543 1.679042,-0.58728 z"
+ sodipodi:nodetypes="csccsccsccscc" />
+ </g>
+ </g>
+ <circle
+ style="fill:none;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path3190"
+ cx="104.22961"
+ cy="143.82848"
+ r="101.99923" />
+ <circle
+ style="fill:#000000;stroke:#000000;stroke-width:0.2;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path3192"
+ cx="104.22961"
+ cy="143.82848"
+ r="1.0175619" />
+ </g>
+ </g>
+</svg>
diff --git a/stm32/.gitignore b/stm32/.gitignore
new file mode 100644
index 0000000..ac9bbcd
--- /dev/null
+++ b/stm32/.gitignore
@@ -0,0 +1,10 @@
+*.o
+*.a
+*.d
+*.elf
+*.map
+*.hex
+*~
+*.dfu
+*.bin
+*.orig
diff --git a/stm32/Makefile.include b/stm32/Makefile.include
new file mode 100644
index 0000000..389aa68
--- /dev/null
+++ b/stm32/Makefile.include
@@ -0,0 +1,45 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = opencm3_stm32f1
+DEFS = -DSTM32F1
+
+FP_FLAGS ?= -msoft-float
+ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd
+
+################################################################################
+# OpenOCD specific variables
+
+OOCD ?= openocd
+OOCD_INTERFACE ?= ../oocd/interface/stlink-v2.cfg
+#OOCD_INTERFACE ?= ../oocd/interface/j-link.cfg
+OOCD_BOARD ?= ../oocd/board/STM32F103R_BOARD.cfg
+
+################################################################################
+# Black Magic Probe specific variables
+# Set the BMP_PORT to a serial port and then BMP is used for flashing
+BMP_PORT ?=
+
+################################################################################
+# texane/stlink specific variables
+#STLINK_PORT ?= :4242
+
+
+include ../Makefile.rules
diff --git a/stm32/Makefile.rules b/stm32/Makefile.rules
new file mode 100644
index 0000000..6e9fe6c
--- /dev/null
+++ b/stm32/Makefile.rules
@@ -0,0 +1,251 @@
+#
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+# Be silent per default, but 'make V=1' will show all compiler calls.
+ifneq ($(V),1)
+Q := @
+NULL := 2>/dev/null
+endif
+
+###############################################################################
+# Executables
+
+PREFIX ?= arm-none-eabi
+
+CC := $(PREFIX)-gcc
+CXX := $(PREFIX)-g++
+LD := $(PREFIX)-gcc
+AR := $(PREFIX)-ar
+AS := $(PREFIX)-as
+OBJCOPY := $(PREFIX)-objcopy
+OBJDUMP := $(PREFIX)-objdump
+GDB := $(PREFIX)-gdb
+STFLASH = $(shell which st-flash)
+STYLECHECK := /checkpatch.pl
+STYLECHECKFLAGS := --no-tree -f --terse --mailback
+STYLECHECKFILES := $(shell find . -name '*.[ch]')
+
+
+###############################################################################
+# Source files
+
+LDSCRIPT ?= $(BINARY).ld
+
+#OBJS += $(BINARY).o
+
+
+ifeq ($(strip $(OPENCM3_DIR)),)
+# user has not specified the library path, so we try to detect it
+
+# where we search for the library
+LIBPATHS := ./libopencm3 ../libopencm3
+
+OPENCM3_DIR := $(wildcard $(LIBPATHS:=/locm3.sublime-project))
+OPENCM3_DIR := $(firstword $(dir $(OPENCM3_DIR)))
+
+ifeq ($(strip $(OPENCM3_DIR)),)
+$(warning Cannot find libopencm3 library in the standard search paths.)
+$(error Please specify it through OPENCM3_DIR variable!)
+endif
+endif
+
+ifeq ($(V),1)
+$(info Using $(OPENCM3_DIR) path to library)
+endif
+
+INCLUDE_DIR = $(OPENCM3_DIR)/include
+LIB_DIR = $(OPENCM3_DIR)/lib
+SCRIPT_DIR = $(OPENCM3_DIR)/scripts
+
+###############################################################################
+# C flags
+
+CFLAGS += -Os -g
+CFLAGS += -Wextra -Wimplicit-function-declaration
+CFLAGS += -Wmissing-prototypes -Wstrict-prototypes
+CFLAGS += -fno-common -ffunction-sections -fdata-sections
+
+###############################################################################
+# C++ flags
+
+CXXFLAGS += -Os -g
+CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++
+CXXFLAGS += -fno-common -ffunction-sections -fdata-sections
+
+###############################################################################
+# C & C++ preprocessor common flags
+
+CPPFLAGS += -MD
+CPPFLAGS += -Wall -Wundef
+
+INCLUDES = -I$(INCLUDE_DIR)
+DEFINES = $(DEFS)
+
+CPPFLAGS += $(INCLUDES) $(DEFINES)
+
+###############################################################################
+# Linker flags
+
+LDFLAGS += --static -nostartfiles
+LDFLAGS += -L$(LIB_DIR)
+LDFLAGS += -T$(LDSCRIPT)
+LDFLAGS += -Wl,-Map=$(*).map
+LDFLAGS += -Wl,--gc-sections
+ifeq ($(V),99)
+LDFLAGS += -Wl,--print-gc-sections
+endif
+
+###############################################################################
+# Used libraries
+
+LDLIBS += -l$(LIBNAME)
+LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
+
+###############################################################################
+###############################################################################
+###############################################################################
+
+.SUFFIXES: .elf .bin .hex .srec .list .map .images .dfu
+.SECONDEXPANSION:
+.SECONDARY:
+
+all: elf
+
+elf: $(BINARY).elf
+bin: $(BINARY).bin
+hex: $(BINARY).hex
+srec: $(BINARY).srec
+list: $(BINARY).list
+
+images: $(BINARY).images
+flash: $(BINARY).flash
+
+%.images: %.bin %.hex %.srec %.list %.map %.dfu
+ @#printf "*** $* images generated ***\n"
+
+%.bin: %.elf
+ @#printf " OBJCOPY $(*).bin\n"
+ $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
+
+%.hex: %.elf
+ @#printf " OBJCOPY $(*).hex\n"
+ $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
+
+#%.dfu: %.elf
+# @#printf " OBJCOPY $(*).dfu\n"
+# $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).dfu
+
+%.srec: %.elf
+ @#printf " OBJCOPY $(*).srec\n"
+ $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
+
+%.list: %.elf
+ @#printf " OBJDUMP $(*).list\n"
+ $(Q)$(OBJDUMP) -S $(*).elf > $(*).list
+
+fish:
+ echo %.elf %.map: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
+ echo $(BINARY).elf
+
+%.elf %.map: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
+ @#printf " LD $(*).elf\n"
+ $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(*).elf
+
+%.o: %.c
+ @#printf " CC $(*).c\n"
+ $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).c
+
+%.o: %.cxx
+ @#printf " CXX $(*).cxx\n"
+ $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx
+
+%.o: %.cpp
+ @#printf " CXX $(*).cpp\n"
+ $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp
+
+clean:
+ @#printf " CLEAN\n"
+ $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map *~ *.dfu *.orig
+
+stylecheck: $(STYLECHECKFILES:=.stylecheck)
+styleclean: $(STYLECHECKFILES:=.styleclean)
+
+# the cat is due to multithreaded nature - we like to have consistent chunks of text on the output
+%.stylecheck: %
+ $(Q)$(SCRIPT_DIR)$(STYLECHECK) $(STYLECHECKFLAGS) $* > $*.stylecheck; \
+ if [ -s $*.stylecheck ]; then \
+ cat $*.stylecheck; \
+ else \
+ rm -f $*.stylecheck; \
+ fi;
+
+%.styleclean:
+ $(Q)rm -f $*.stylecheck;
+
+
+%.stlink-flash: %.bin
+ @printf " FLASH $<\n"
+ $(Q)$(STFLASH) write $(*).bin 0x8000000
+
+ifeq ($(STLINK_PORT),)
+ifeq ($(BMP_PORT),)
+ifeq ($(OOCD_SERIAL),)
+%.flash: %.hex
+ @printf " FLASH $<\n"
+ @# IMPORTANT: Don't use "resume", only "reset" will work correctly!
+ $(Q)$(OOCD) -f $(OOCD_INTERFACE) \
+ -f $(OOCD_BOARD) \
+ -c "init" -c "reset init" \
+ -c "flash write_image erase $(*).hex" \
+ -c "reset" \
+ -c "shutdown" $(NULL)
+else
+%.flash: %.hex
+ @printf " FLASH $<\n"
+ @# IMPORTANT: Don't use "resume", only "reset" will work correctly!
+ $(Q)$(OOCD) -f $(OOCD_INTERFACE) \
+ -f $(OOCD_BOARD) \
+ -c "ft2232_serial $(OOCD_SERIAL)" \
+ -c "init" -c "reset init" \
+ -c "flash write_image erase $(*).hex" \
+ -c "reset" \
+ -c "shutdown" $(NULL)
+endif
+else
+%.flash: %.elf
+ @printf " GDB $(*).elf (flash)\n"
+ $(Q)$(GDB) --batch \
+ -ex 'target extended-remote $(BMP_PORT)' \
+ -x $(SCRIPT_DIR)/black_magic_probe_flash.scr \
+ $(*).elf
+endif
+else
+%.flash: %.elf
+ @printf " GDB $(*).elf (flash)\n"
+ $(Q)$(GDB) --batch \
+ -ex 'target extended-remote $(STLINK_PORT)' \
+ -x $(SCRIPT_DIR)/stlink_flash.scr \
+ $(*).elf
+endif
+
+.PHONY: images clean stylecheck styleclean elf bin hex srec list
+
+-include $(OBJS:.o=.d)
diff --git a/stm32/app/Makefile b/stm32/app/Makefile
new file mode 100644
index 0000000..997011f
--- /dev/null
+++ b/stm32/app/Makefile
@@ -0,0 +1,80 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+CPROTO=cproto
+PROG=clock
+
+LDLIBS+=-lm
+
+V=1
+default: ${PROG}.elf
+
+CSRCS= main.c cdcacm.c dfu.c ring.c usart.c ticker.c dummy_kb.c usb.c rtc.c time_fn.c events.c hands.c motor.c
+HSRCS = project.h
+
+
+BINARY = ${PROG}
+OBJS = ${CSRCS:%.c=%.o}
+
+include ../Makefile.include
+
+DID=$(shell printf '\#include "id.h"\nID_PRODUCT' | ${CC} -I.. -E - | grep -v ^\# )
+VID=$(shell printf '\#include "id.h"\nID_VENDOR' | ${CC} -I.. -E - | grep -v ^\# )
+
+INCLUDES += -I..
+
+
+%.bin: %.elf
+ $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
+
+%.dfu:%.bin
+ ../tools/dfuse-pack.py -D 0x483:0xff03 -b 0x08002000:$< $@
+
+dfu:${PROG}.bin
+ dfu-util -R -a 0 -d 0483:ff03,0483:df11 -s 0x08002000:leave -D $<
+
+program: ${PROG}.elf
+ echo halt | nc -t localhost 4444
+ echo flash write_image erase ${PWD}/$< 0x2000 | nc -t localhost 4444
+ echo reset run | nc -t localhost 4444
+
+ds:
+ $(Q)$(OOCD) -f $(OOCD_INTERFACE) \
+ -f $(OOCD_BOARD) \
+
+debug: ${PROG}.elf
+ ${PREFIX}-gdb -x gdb.script ${PROG}.elf
+
+reset:
+ $(Q)$(OOCD) -f $(OOCD_INTERFACE) \
+ -f $(OOCD_BOARD) \
+ -c "init" -c "reset run" \
+ -c shutdown
+
+
+
+
+protos:
+ echo -n > prototypes.h
+ ${CPROTO} $(INCLUDES) $(DEFINES) -e -v ${CSRCS} > prototypes.h.tmp
+ mv -f prototypes.h.tmp prototypes.h
+
+
+tidy:
+ astyle -A3 -s2 --attach-extern-c -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS} || astyle -A3 -s2 -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS}
diff --git a/stm32/app/asm_fns.h b/stm32/app/asm_fns.h
new file mode 100644
index 0000000..b0d10d9
--- /dev/null
+++ b/stm32/app/asm_fns.h
@@ -0,0 +1,4 @@
+static inline void compiler_mb(void) {
+asm volatile ("");
+}
+
diff --git a/stm32/app/board.h b/stm32/app/board.h
new file mode 100644
index 0000000..41eeafc
--- /dev/null
+++ b/stm32/app/board.h
@@ -0,0 +1,15 @@
+
+#define LED1 GPIO8
+#define LED1_PORT GPIOB
+
+#define LED2 GPIO9
+#define LED2_PORT GPIOB
+
+
+#define USART1_TX GPIO_USART1_TX
+#define USART1_TX_PORT GPIOA
+
+#define USART1_RX GPIO_USART1_RX
+#define USART1_RX_PORT GPIOA
+
+
diff --git a/stm32/app/cdcacm.c b/stm32/app/cdcacm.c
new file mode 100644
index 0000000..0b4a4e3
--- /dev/null
+++ b/stm32/app/cdcacm.c
@@ -0,0 +1,221 @@
+#include "project.h"
+
+
+#define BUFFER_SIZE 512
+
+ring_t cdcacm_rx_ring;
+static uint8_t cdcacm_rx_ring_buf[BUFFER_SIZE];
+
+ring_t cdcacm_tx_ring;
+static uint8_t cdcacm_tx_ring_buf[BUFFER_SIZE];
+
+static int cdcacm_ready = 0;
+
+#define COMM_EP 0x83
+#define DATA_IN 0x01
+#define DATA_OUT 0x82
+
+static const struct usb_endpoint_descriptor comm_endp[] = {
+ {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = COMM_EP,
+ .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
+ .wMaxPacketSize = 16,
+ .bInterval = 255,
+ }
+};
+
+static const struct usb_endpoint_descriptor data_endp[] = {
+ {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = DATA_IN,
+ .bmAttributes = USB_ENDPOINT_ATTR_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 1,
+ },
+ {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = DATA_OUT,
+ .bmAttributes = USB_ENDPOINT_ATTR_BULK,
+ .wMaxPacketSize = 64,
+ .bInterval = 1,
+ }
+};
+
+static const struct {
+ struct usb_cdc_header_descriptor header;
+ struct usb_cdc_call_management_descriptor call_mgmt;
+ struct usb_cdc_acm_descriptor acm;
+ struct usb_cdc_union_descriptor cdc_union;
+} __attribute__ ((packed)) cdcacm_functional_descriptors = {
+ .header = {
+ .bFunctionLength = sizeof (struct usb_cdc_header_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_HEADER,
+ .bcdCDC = 0x0110,
+ },
+ .call_mgmt = {
+ .bFunctionLength =
+ sizeof (struct usb_cdc_call_management_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT,
+ .bmCapabilities = 0,
+ .bDataInterface = 3,
+ },
+ .acm = {
+ .bFunctionLength = sizeof (struct usb_cdc_acm_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_ACM,
+ .bmCapabilities = 0,
+ },
+ .cdc_union = {
+ .bFunctionLength = sizeof (struct usb_cdc_union_descriptor),
+ .bDescriptorType = CS_INTERFACE,
+ .bDescriptorSubtype = USB_CDC_TYPE_UNION,
+ .bControlInterface = 2,
+ .bSubordinateInterface0 = 3,
+ }
+};
+
+const struct usb_interface_descriptor comm_iface = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 2,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_CDC,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_PROTOCOL_AT,
+ .iInterface = 0,
+ .endpoint = comm_endp,
+ .extra = &cdcacm_functional_descriptors,
+ .extralen = sizeof (cdcacm_functional_descriptors)
+};
+
+const struct usb_interface_descriptor data_iface = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 3,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0,
+ .endpoint = data_endp,
+};
+
+
+const struct usb_iface_assoc_descriptor cdc_iface_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 2,
+ .bInterfaceCount = 2,
+ .bFunctionClass = USB_CLASS_CDC,
+ .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
+ .bFunctionProtocol = USB_CDC_PROTOCOL_AT,
+ .iFunction = 6,
+};
+
+
+
+enum usbd_request_return_codes
+cdcacm_control_request (usbd_device *usbd_dev,
+ struct usb_setup_data *req,
+ uint8_t **buf,
+ uint16_t *len,
+ usbd_control_complete_callback *complete) {
+ (void) complete;
+ (void) buf;
+ (void) usbd_dev;
+
+
+ switch (req->bRequest)
+ {
+ case USB_CDC_REQ_SET_CONTROL_LINE_STATE: {
+ /*
+ * This Linux cdc_acm driver requires this to be implemented
+ * even though it's optional in the CDC spec, and we don't
+ * advertise it in the ACM functional descriptor.
+ */
+ return USBD_REQ_HANDLED;
+ }
+
+ case USB_CDC_REQ_SET_LINE_CODING:
+ if (*len < sizeof (struct usb_cdc_line_coding))
+ return USBD_REQ_NOTSUPP;
+
+ return USBD_REQ_HANDLED;
+ }
+
+ return USBD_REQ_NEXT_CALLBACK;
+}
+
+
+
+void cdcacm_tick (void)
+{
+ unsigned ep = DATA_OUT;
+ uint8_t buf[16];
+ uint8_t *ptr = buf;
+ size_t n = 0;
+
+ if (!cdcacm_ready)
+ return;
+
+ if (ring_empty (&cdcacm_tx_ring))
+ return;
+
+ /* Return if endpoint is already enabled. */
+ if ((*USB_EP_REG (ep & 0x7f) & USB_EP_TX_STAT) == USB_EP_TX_STAT_VALID)
+ return;
+
+ while (!ring_read_byte (&cdcacm_tx_ring, ptr++)) {
+ n++;
+
+ if (n == sizeof (buf)) break;
+ }
+
+ usbd_ep_write_packet (usb_device, ep, buf, n);
+}
+
+int cdcacm_write (char *ptr, int len)
+{
+ int ret;
+
+ ret = ring_write (&cdcacm_tx_ring, (uint8_t *) ptr, len);
+ return ret;
+}
+
+
+
+static void cdcacm_data_rx_cb (usbd_device *usbd_dev, uint8_t ep)
+{
+ (void) ep;
+ uint8_t buf[64];
+ int len = usbd_ep_read_packet (usbd_dev, DATA_IN, buf, 64);
+
+ if (len)
+ ring_write (&cdcacm_rx_ring, buf, len);
+}
+
+void cdcacm_set_config (usbd_device *usbd_dev, uint16_t wValue)
+{
+ (void) wValue;
+
+ usbd_ep_setup (usbd_dev, DATA_IN, USB_ENDPOINT_ATTR_BULK, 64, cdcacm_data_rx_cb);
+ usbd_ep_setup (usbd_dev, DATA_OUT, USB_ENDPOINT_ATTR_BULK, 64, NULL);
+ usbd_ep_setup (usbd_dev, COMM_EP, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL);
+ cdcacm_ready = 1;
+}
+
+void cdcacm_rings_init (void)
+{
+ ring_init (&cdcacm_rx_ring, cdcacm_rx_ring_buf, sizeof (cdcacm_rx_ring_buf));
+ ring_init (&cdcacm_tx_ring, cdcacm_tx_ring_buf, sizeof (cdcacm_tx_ring_buf));
+}
+
+
diff --git a/stm32/app/clock.ld b/stm32/app/clock.ld
new file mode 100644
index 0000000..20cbff9
--- /dev/null
+++ b/stm32/app/clock.ld
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */
+
+/* Define memory regions. */
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08002000, LENGTH = 120K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
+}
+
+/* Include the common ld script. */
+INCLUDE cortex-m-generic.ld
+
+dfu_shared_location = ORIGIN(ram) + LENGTH(ram) - 1024;
+
+/* PROVIDE(_stack = dfu_shared_location ); */
+
+SECTIONS
+{
+ .dfu_shared dfu_shared_location :{
+ dfu_flag = .;
+ }
+}
+
+
diff --git a/stm32/app/dfu.c b/stm32/app/dfu.c
new file mode 100644
index 0000000..29a2428
--- /dev/null
+++ b/stm32/app/dfu.c
@@ -0,0 +1,86 @@
+#include "project.h"
+
+const struct usb_dfu_descriptor dfu_function = {
+ .bLength = sizeof (struct usb_dfu_descriptor),
+ .bDescriptorType = DFU_FUNCTIONAL,
+ .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
+ .wDetachTimeout = 255,
+ .wTransferSize = 1024,
+ .bcdDFUVersion = 0x011A,
+};
+
+const struct usb_interface_descriptor dfu_iface = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = 0xFE,
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 1,
+ .iInterface = 4,
+ .extra = &dfu_function,
+ .extralen = sizeof (dfu_function),
+};
+
+
+const struct usb_iface_assoc_descriptor dfu_iface_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 1,
+ .bInterfaceCount = 1,
+ .bFunctionClass = 0xfe,
+ .bFunctionSubClass = 1,
+ .bFunctionProtocol = 1,
+ .iFunction = 5,
+};
+
+
+static void
+dfu_detach_complete (usbd_device *usbd_dev, struct usb_setup_data *req)
+{
+ (void) req;
+ (void) usbd_dev;
+ dfu_flag = 0xfee1dead;
+
+ scb_reset_core();
+}
+
+enum usbd_request_return_codes
+dfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req,
+ uint8_t **buf, uint16_t *len,
+ usbd_control_complete_callback *complete) {
+ (void) buf;
+ (void) len;
+ (void) usbd_dev;
+
+ if ((req->bmRequestType & 0x7F) != 0x21)
+ return USBD_REQ_NEXT_CALLBACK;
+
+ switch (req->bRequest)
+ {
+ case DFU_GETSTATUS: {
+ (*buf) [0] = DFU_STATUS_OK;
+ (*buf) [1] = 0;
+ (*buf) [2] = 0;
+ (*buf) [3] = 0;
+ (*buf) [4] = STATE_APP_IDLE;
+ (*buf) [5] = 0; /* iString not used here */
+ *len = 6;
+ return USBD_REQ_HANDLED;
+ }
+
+ case DFU_GETSTATE:
+ /* Return state with no state transision. */
+ *buf[0] = STATE_APP_IDLE;
+ *len = 1;
+ return USBD_REQ_HANDLED;
+
+ case DFU_DETACH:
+ *complete = dfu_detach_complete;
+ return USBD_REQ_HANDLED;
+ }
+
+ return USBD_REQ_NEXT_CALLBACK;
+}
+
diff --git a/stm32/app/dummy_kb.c b/stm32/app/dummy_kb.c
new file mode 100644
index 0000000..a1d61c7
--- /dev/null
+++ b/stm32/app/dummy_kb.c
@@ -0,0 +1,26 @@
+#include "project.h"
+
+const struct usb_interface_descriptor dummy_kb_iface = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ .iInterface = 0,
+};
+
+
+const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc = {
+ .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 0,
+ .bInterfaceCount = 1,
+ .bFunctionClass = 0xff,
+ .bFunctionSubClass = 0,
+ .bFunctionProtocol = 0,
+ .iFunction = 4,
+};
+
diff --git a/stm32/app/events.c b/stm32/app/events.c
new file mode 100644
index 0000000..2ad9b47
--- /dev/null
+++ b/stm32/app/events.c
@@ -0,0 +1,101 @@
+#include "project.h"
+
+#define D2R(a) ((a)*(M_PI/180.))
+
+
+
+
+// shamelessly stolen from Meeus Astronmical Algorithms Chapter 27 table 27.B
+// chapter 25 is probably more tractable, but this is easier to code up
+
+static double mean_vernal_equinox (unsigned year)
+{
+ double y = year;
+ y -= 2000;
+ y *= 0.001;
+ return 2451623.80984 + 365242.37404 * y + 0.05169 * (y * y) - 0.00411 * (y * y * y) - 0.00057 * (y * y * y * y);
+}
+
+static double mean_summer_solstice (unsigned year)
+{
+ double y = year;
+ y -= 2000;
+ y *= 0.001;
+ return 2451716.56767 + 365241.62603 * y + 0.00325 * (y * y) + 0.00888 * (y * y * y) - 0.00030 * (y * y * y * y);
+}
+
+static double mean_autumnal_equinox (unsigned year)
+{
+ double y = year;
+ y -= 2000;
+ y *= 0.001;
+ return 2451810.21715 + 365242.01767 * y - 0.11575 * (y * y) + 0.00337 * (y * y * y) + 0.00078 * (y * y * y * y);
+}
+
+static double mean_winter_solstice (unsigned year)
+{
+ double y = year;
+ y -= 2000;
+ y *= 0.001;
+ return 2451900.05952 + 365242.74049 * y - 0.06223 * (y * y) - 0.00823 * (y * y * y) + 0.00032 * (y * y * y * y);
+}
+
+
+static double orbital_periodic_terms (double t)
+{
+#define N 24
+ const double A[N] = {485, 203, 199, 182, 156, 136, 77, 74, 70, 58, 52, 50, 45,
+ 44, 29, 18, 17, 16, 14, 12, 12, 12, 9, 8
+ };
+ const double B[N] = {D2R (324.96), D2R (337.23), D2R (342.08), D2R (27.85),
+ D2R (73.14), D2R (171.52), D2R (222.54), D2R (296.72),
+ D2R (243.58), D2R (119.81), D2R (297.17), D2R (21.02),
+ D2R (247.54), D2R (325.15), D2R (60.93), D2R (155.12),
+ D2R (288.79), D2R (198.04), D2R (199.76), D2R (95.39),
+ D2R (287.11), D2R (320.81), D2R (227.73), D2R (15.45)
+ };
+ const double C[N] = {D2R (1934.136), D2R (32964.467), D2R (20.186),
+ D2R (445267.112), D2R (45036.886), D2R (22518.443),
+ D2R (65928.934), D2R (3034.906), D2R (9037.513),
+ D2R (33718.147), D2R (150.678), D2R (2281.226),
+ D2R (29929.562), D2R (31555.956), D2R (4443.417),
+ D2R (67555.328), D2R (4562.452), D2R (62894.029),
+ D2R (31436.921), D2R (14577.848), D2R (31931.756),
+ D2R (34777.259), D2R (1222.114), D2R (16859.074)
+ };
+ double s = 0;
+ unsigned i;
+
+ for (i = 0; i < N; ++i)
+ s += A[i] * cos (B[i] + (C[i] * t));
+
+ return s;
+}
+
+
+static double mean_to_real (double j0)
+{
+
+ double t = (j0 - 2451545.) / 36525.;
+ double w = D2R ((35999.373 * t) - 2.47);
+ double dl = 1 + 0.0334 * cos (w) + 0.0007 * cos (2. * w);
+ double s = orbital_periodic_terms (t);
+
+#if 0
+ printf ("j0=%.6f\r\n", j0);
+ printf ("t=%.6f\r\n", t);
+ printf ("w=%.6f\r\n", w);
+ printf ("dl=%.6f\r\n", dl);
+ printf ("s=%.6f\r\n", s);
+#endif
+
+ return j0 + ((0.00001 * s) / dl);
+}
+
+
+
+double autumnal_equinox (unsigned y)
+{
+ return mean_to_real (mean_autumnal_equinox (y));
+ // return mean_to_real (mean_summer_solstice (y));
+}
diff --git a/stm32/app/gdb.script b/stm32/app/gdb.script
new file mode 100644
index 0000000..7cf9d09
--- /dev/null
+++ b/stm32/app/gdb.script
@@ -0,0 +1,2 @@
+target remote localhost:3333
+cont
diff --git a/stm32/app/hands.c b/stm32/app/hands.c
new file mode 100644
index 0000000..5414d9e
--- /dev/null
+++ b/stm32/app/hands.c
@@ -0,0 +1,90 @@
+#include "project.h"
+
+
+unsigned hands_pos[HANDS];
+unsigned hands_ready;
+
+
+static unsigned calc_minute_pos (MTIME *m)
+{
+ uint64_t p;
+
+ p = m->minute;
+ p *= 100;
+ p += m->second;
+ p *= 1000;
+ p += m->nanosecond / 1000000;
+
+ p *= MOTOR_STEPS;
+ p /= 10000000;
+
+
+
+ return (unsigned) p;
+
+}
+
+static unsigned calc_hour_pos (MTIME *m)
+{
+ uint64_t p;
+
+ p = m->hour;
+ p *= 100;
+ p += m->minute;
+ p *= 100;
+ p += m->second;
+ p *= 1000;
+ p += m->nanosecond / 1000000;
+
+ p *= MOTOR_STEPS;
+ p /= 100000000;
+
+
+
+ return (unsigned) p;
+}
+
+
+
+
+void hands_tick (void)
+{
+ EPOCH e;
+ UTC u;
+ MTIME m;
+ static unsigned old_pos[HANDS];
+ unsigned i, p;
+
+
+ static uint32_t last;
+
+ if ((ticks - last) < 100) return;
+
+ last = ticks;
+
+ if (!rtc_ready) return;
+
+
+ e = rtc_get();
+ u = time_epoch_to_utc (e);
+ m = time_to_metric (e, u);
+
+
+ hands_pos[0] = calc_hour_pos (&m);
+ hands_pos[1] = calc_minute_pos (&m);
+ hands_ready = 1;
+
+ for (i = 0, p = 0; i < HANDS; ++i) {
+ if (hands_pos[i] != old_pos[i]) p++;
+
+ old_pos[i] = hands_pos[i];
+
+ }
+
+ if (p) {
+ time_print_utc ("UTC: ", &u, NULL);
+ time_print_metric ("Metric: ", &m, NULL);
+ printf ("Hands: hour %4d/%4d min %4d/%4d\r\n", hands_pos[0], MOTOR_STEPS, hands_pos[1], MOTOR_STEPS);
+ }
+
+}
diff --git a/stm32/app/main.c b/stm32/app/main.c
new file mode 100644
index 0000000..4722479
--- /dev/null
+++ b/stm32/app/main.c
@@ -0,0 +1,50 @@
+#include "project.h"
+
+
+
+
+
+int main (void)
+{
+ /*set up pll */
+ rcc_clock_setup_pll (&rcc_hse_configs[RCC_HSE_CONFIG]);
+
+ /*turn on clocks to periferals */
+ rcc_periph_clock_enable (RCC_GPIOA);
+ rcc_periph_clock_enable (RCC_GPIOB);
+ rcc_periph_clock_enable (RCC_GPIOC);
+ rcc_periph_clock_enable (RCC_USART1);
+ rcc_periph_clock_enable (RCC_AFIO);
+ rcc_periph_clock_enable (RCC_PWR);
+ rcc_periph_clock_enable (RCC_BKP);
+ pwr_disable_backup_domain_write_protect();
+ DWT_CTRL |= DWT_CTRL_CYCCNTENA;
+
+
+ nvic_set_priority (NVIC_SYSTICK_IRQ, 0x80);
+ nvic_set_priority (NVIC_USART1_IRQ, 0x40);
+ nvic_set_priority (NVIC_USB_HP_CAN_TX_IRQ, 0x40);
+ nvic_set_priority (NVIC_USB_LP_CAN_RX0_IRQ, 0x40);
+ nvic_set_priority (NVIC_RTC_IRQ, 0x10);
+
+ MAP_OUTPUT_OD (LED1);
+ MAP_OUTPUT_OD (LED2);
+
+
+ usart_init();
+ cdcacm_rings_init();
+ rtc_init();
+
+ printf ("Startup:\r\n");
+
+ motor_init();
+ ticker_init();
+ usb_init();
+
+
+ for (;;);
+
+
+ return 0;
+}
+
diff --git a/stm32/app/motor.c b/stm32/app/motor.c
new file mode 100644
index 0000000..392089b
--- /dev/null
+++ b/stm32/app/motor.c
@@ -0,0 +1,75 @@
+#include "project.h"
+
+
+static unsigned motor_pos[HANDS];
+
+
+static void coils (unsigned m, int a, int b, int c, int d)
+{
+ printf ("Motor %d: %+d %+d\r\n", m, a - b, c - d);
+}
+
+static void step (unsigned m, int d)
+{
+ unsigned s = motor_pos[m];
+
+ if (d < 0) d += MOTOR_STEPS;
+
+ s += d;
+ s %= MOTOR_STEPS;
+
+ coils (m, !! ((s + 6) & 4), !! ((s + 1) & 4), !! ((s + 4) & 4), !! ((s + 7) & 4));
+
+ if (!m)
+ BKP_DR8 = motor_pos[0] = s;
+ else
+ BKP_DR9 = motor_pos[1] = s;
+
+
+}
+
+
+
+
+
+void motor_tick (void)
+{
+ static uint32_t last;
+ unsigned i, d;
+
+ if ((ticks - last) < 10) return;
+
+ last = ticks;
+
+ if (!hands_ready) return;
+
+ //printf("HANDS: %d -> %d %d -> %d\r\n",hands_pos[0],motor_pos[0],hands_pos[1],motor_pos[1]);
+
+
+ for (i = 0; i < HANDS; ++i) {
+ d = MOTOR_STEPS + hands_pos[i];
+ d -= motor_pos[i];
+ d %= MOTOR_STEPS;
+
+ if (d) {
+ if (d < (MOTOR_STEPS / 2))
+ step (i, 1);
+ else
+ step (i, -1);
+ }
+ }
+}
+
+
+
+
+void motor_init (void)
+{
+
+ motor_pos[0] = BKP_DR8;
+ motor_pos[1] = BKP_DR9;
+
+ step (0, 0);
+ step (1, 0);
+
+}
diff --git a/stm32/app/pins.h b/stm32/app/pins.h
new file mode 100644
index 0000000..954396f
--- /dev/null
+++ b/stm32/app/pins.h
@@ -0,0 +1,54 @@
+#ifndef _PINS_H_
+#define _PINS_H_
+
+/* st seem to change these with every chip revision */
+
+#define MAP_ANA(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, a ); \
+ } while (0)
+
+#define MAP_AF(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, a ); \
+ } while (0)
+
+/* STM32F1 doesn't have AF pull up, but also doesn't disconnect af inputs so just use regular pull up */
+#define MAP_AF_PU(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, a); \
+ gpio_set( a ## _PORT, a); \
+ } while (0)
+
+#define MAP_AF_OD(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN, a ); \
+ } while (0)
+
+
+#define MAP_OUTPUT_PP(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, a ); \
+ } while (0)
+
+
+#define MAP_OUTPUT_OD(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, a ); \
+ } while (0)
+
+
+/* STM32F1 madly uses the output register to drive the other end of the resistor, so pull up */
+/* requires us to write a 1 there */
+
+#define MAP_INPUT_PU(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, a); \
+ gpio_set( a ## _PORT, a); \
+ } while (0)
+
+
+#define MAP_INPUT(a) do { \
+ gpio_set_mode( a ## _PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, a); \
+ } while (0)
+
+
+#define CLEAR(a) gpio_clear( a ## _PORT, a)
+#define SET(a) gpio_set( a ## _PORT, a)
+#define GET(a) gpio_get( a ## _PORT, a)
+#define TOGGLE(a) gpio_toggle( a ## _PORT, a)
+
+#endif
diff --git a/stm32/app/project.h b/stm32/app/project.h
new file mode 100644
index 0000000..fd71876
--- /dev/null
+++ b/stm32/app/project.h
@@ -0,0 +1,50 @@
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/st_usbfs.h>
+#include <libopencm3/stm32/rtc.h>
+#include <libopencm3/stm32/pwr.h>
+#include <libopencm3/stm32/f1/bkp.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/cortex.h>
+#include <libopencm3/cm3/scb.h>
+#include <libopencm3/cm3/dwt.h>
+#include <libopencm3/usb/usbd.h>
+#include <libopencm3/usb/hid.h>
+#include <libopencm3/usb/dfu.h>
+#include <libopencm3/usb/cdc.h>
+#include <id.h>
+
+
+
+#define RCC_HSE_CONFIG RCC_CLOCK_HSE8_72MHZ
+#define US (72)
+#define MS (US * 1000)
+#define HZ (MS * 1000)
+#define MS_TO_TICKS(a) ((a) *2)
+
+#define TRACE do { printf("%s:%d\r\n",__FILE__,__LINE__); } while (0)
+
+#define DWT_FREQ 48000000
+
+#define HANDS 2
+#define MOTOR_STEPS (1080 * 2)
+
+#include "board.h"
+#include "ring.h"
+#include "pins.h"
+#include "time_fn.h"
+#include "asm_fns.h"
+
+#include "prototypes.h"
+
+
+
+extern uint32_t dfu_flag;
diff --git a/stm32/app/prototypes.h b/stm32/app/prototypes.h
new file mode 100644
index 0000000..751ba25
--- /dev/null
+++ b/stm32/app/prototypes.h
@@ -0,0 +1,81 @@
+/* main.c */
+extern int main(void);
+/* cdcacm.c */
+extern ring_t cdcacm_rx_ring;
+extern ring_t cdcacm_tx_ring;
+extern const struct usb_interface_descriptor comm_iface;
+extern const struct usb_interface_descriptor data_iface;
+extern const struct usb_iface_assoc_descriptor cdc_iface_assoc;
+extern enum usbd_request_return_codes cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete);
+extern void cdcacm_tick(void);
+extern int cdcacm_write(char *ptr, int len);
+extern void cdcacm_set_config(usbd_device *usbd_dev, uint16_t wValue);
+extern void cdcacm_rings_init(void);
+/* dfu.c */
+extern const struct usb_dfu_descriptor dfu_function;
+extern const struct usb_interface_descriptor dfu_iface;
+extern const struct usb_iface_assoc_descriptor dfu_iface_assoc;
+extern enum usbd_request_return_codes dfu_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete);
+/* ring.c */
+extern void ring_init(ring_t *r, uint8_t *buf, size_t len);
+extern int ring_write_byte(ring_t *r, uint8_t c);
+extern int ring_empty(ring_t *r);
+extern int ring_read_byte(ring_t *r, uint8_t *c);
+extern int ring_write(ring_t *r, uint8_t *buf, size_t len);
+/* usart.c */
+extern ring_t usart_rx_ring;
+extern ring_t usart_tx_ring;
+extern void usart1_isr(void);
+extern void usart_kick(void);
+extern int _write(int file, char *ptr, int len);
+extern void usart_init(void);
+/* ticker.c */
+extern volatile uint32_t ticks;
+extern unsigned led2;
+extern void delay_us(uint32_t d);
+extern void sys_tick_handler(void);
+extern void ticker_init(void);
+extern void delay_ms(uint32_t d);
+/* dummy_kb.c */
+extern const struct usb_interface_descriptor dummy_kb_iface;
+extern const struct usb_iface_assoc_descriptor dummy_kb_iface_assoc;
+/* usb.c */
+extern uint8_t usbd_control_buffer[128];
+extern usbd_device *usb_device;
+extern void usb_hp_can_tx_isr(void);
+extern void usb_lp_can_rx0_isr(void);
+extern void usb_init(void);
+/* rtc.c */
+extern volatile unsigned rtc_ready;
+extern void rtc_isr(void);
+extern EPOCH rtc_get(void);
+extern void rtc_init(void);
+/* time_fn.c */
+extern EPOCH time_epoch_sub(EPOCH a, EPOCH b);
+extern EPOCH time_epoch_add(EPOCH a, EPOCH b);
+extern UTC time_epoch_to_utc(EPOCH epoch);
+extern EPOCH time_utc_to_epoch(UTC u);
+extern void utc_to_str(char *dst, UTC *u);
+extern void time_print_utc(const char *p, UTC *u, const char *t);
+extern void time_print_epoch(const char *p, EPOCH e, const char *t);
+extern double time_utc_to_tjd(UTC u);
+extern EPOCH time_tjd_to_epoch(double tjd);
+extern UTC time_tjd_to_utc(double tjd);
+extern RA ra_normalize(RA r);
+extern RA time_utc_to_ra(UTC u);
+extern RA time_st_to_ra(ST st);
+extern ST time_ra_to_st(RA r);
+extern ST time_utc_to_lst(UTC u, double lon);
+extern MTIME time_to_metric(EPOCH e, UTC u);
+extern MTIME time_utc_to_metric(UTC u);
+extern MTIME time_epoch_to_metric(EPOCH e);
+extern void time_print_metric(const char *p, MTIME *m, const char *t);
+/* events.c */
+extern double autumnal_equinox(unsigned y);
+/* hands.c */
+extern unsigned hands_pos[2];
+extern unsigned hands_ready;
+extern void hands_tick(void);
+/* motor.c */
+extern void motor_tick(void);
+extern void motor_init(void);
diff --git a/stm32/app/ring.c b/stm32/app/ring.c
new file mode 100644
index 0000000..26bba3a
--- /dev/null
+++ b/stm32/app/ring.c
@@ -0,0 +1,64 @@
+#include "project.h"
+
+
+static inline size_t
+ring_next (ring_t *r, size_t p)
+{
+ p++;
+
+ if (p >= r->size)
+ p -= r->size;
+
+ return p;
+}
+
+void
+ring_init (ring_t *r, uint8_t *buf, size_t len)
+{
+ r->data = buf;
+ r->size = len;
+ r->write = 0;
+ r->read = 0;
+}
+
+int
+ring_write_byte (ring_t *r, uint8_t c)
+{
+ size_t n = ring_next (r, r->write);
+
+ if (n == r->read)
+ return -1;
+
+ r->data[r->write] = c;
+ r->write = n;
+ return 0;
+}
+
+int ring_empty (ring_t *r)
+{
+ return (r->read == r->write);
+}
+
+int
+ring_read_byte (ring_t *r, uint8_t *c)
+{
+ size_t n = ring_next (r, r->read);
+
+ if (r->read == r->write)
+ return -1;
+
+ *c = r->data[r->read];
+ r->read = n;
+ return 0;
+}
+
+int
+ring_write (ring_t *r, uint8_t *buf, size_t len)
+{
+ while (len--) {
+ if (ring_write_byte (r, * (buf++)))
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/stm32/app/ring.h b/stm32/app/ring.h
new file mode 100644
index 0000000..ba8887b
--- /dev/null
+++ b/stm32/app/ring.h
@@ -0,0 +1,7 @@
+typedef struct ring
+{
+ uint8_t *data;
+ size_t size;
+ size_t write;
+ size_t read;
+} ring_t;
diff --git a/stm32/app/rtc.c b/stm32/app/rtc.c
new file mode 100644
index 0000000..0030cfd
--- /dev/null
+++ b/stm32/app/rtc.c
@@ -0,0 +1,170 @@
+#include "project.h"
+
+static volatile uint32_t hz = HZ;
+static volatile uint32_t cycle_ref;
+static volatile uint32_t rtc_ref;
+
+#define RTC_IN_LH 0x21f7
+#define RTC_IN_UH 0x6a6d
+
+static EPOCH rtc_offset;
+static uint16_t rtc_half;
+
+volatile unsigned rtc_ready;
+
+
+
+
+static EPOCH bkp_read_off (void)
+{
+ EPOCH e;
+ uint64_t v;
+
+ v = BKP_DR1 & 0xffff;
+ v <<= 16;
+ v |= (BKP_DR2 & 0xffff);
+ v <<= 16;
+ v |= (BKP_DR3 & 0xffff);
+ v <<= 16;
+ v |= (BKP_DR4 & 0xffff);
+
+ e.s = (int64_t) v;
+
+ v = BKP_DR5 & 0xffff;
+ v <<= 16;
+ v |= (BKP_DR6 & 0xffff);
+
+ e.ns = (int64_t) v;
+
+ return e;
+}
+
+static void bkp_write_off (EPOCH e)
+{
+ uint64_t v;
+
+ v = (uint64_t) e.s;
+
+ BKP_DR4 = (uint16_t) (v & 0xffff);
+ v >>= 16;
+ BKP_DR3 = (uint16_t) (v & 0xffff);
+ v >>= 16;
+ BKP_DR2 = (uint16_t) (v & 0xffff);
+ v >>= 16;
+ BKP_DR1 = (uint16_t) (v & 0xffff);
+
+ v = (uint64_t) e.ns;
+
+ BKP_DR6 = (uint16_t) (v & 0xffff);
+ v >>= 16;
+ BKP_DR5 = (uint16_t) (v & 0xffff);
+
+}
+
+
+
+void rtc_isr (void)
+{
+ uint32_t now;
+ static uint32_t then;
+ uint32_t v;
+ static int warm_up = 3;
+
+
+ now = DWT_CYCCNT;
+ compiler_mb();
+ rtc_clear_flag (RTC_SEC);
+
+ v = rtc_get_counter_val();
+
+ TOGGLE (LED1);
+
+ cycle_ref = now;
+
+ if (warm_up) warm_up--;
+ else hz = now - then;
+
+
+ switch (rtc_half) {
+ case RTC_IN_LH:
+ if (! (v & 0x8000000)) break;
+
+ BKP_DR7 = rtc_half = RTC_IN_UH;
+ break;
+
+ case RTC_IN_UH:
+ if (v & 0x8000000) break;
+
+ BKP_DR7 = rtc_half = RTC_IN_LH;
+ rtc_offset.s += 0x100000000ULL;
+ bkp_write_off (rtc_offset);
+ break;
+
+ default:
+ if (v & 0x8000000)
+ BKP_DR7 = rtc_half = RTC_IN_UH;
+ else
+ BKP_DR7 = rtc_half = RTC_IN_LH;
+ }
+
+
+ compiler_mb();
+ rtc_ref = v;
+ rtc_ready = 1;
+
+
+ // printf ("Ctr %d %u %u\r\n", (int) v, (int) (now - then),(unsigned) rtc_offset.s);
+
+ then = now;
+}
+
+
+EPOCH rtc_get (void)
+{
+ EPOCH e, o;
+ uint32_t h, c, r1, r2;
+ uint32_t now = DWT_CYCCNT;
+
+ do {
+ r1 = rtc_ref;
+ compiler_mb();
+ c = cycle_ref;
+ h = hz;
+ o = rtc_offset;
+ compiler_mb();
+ r2 = rtc_ref;
+ } while (r1 != r2);
+
+ now -= c;
+
+ e.ns = now;
+ e.ns *= 1000000000ULL;
+
+ if (h) e.ns /= h;
+ else e.ns /= HZ;
+
+ e.s = r1;
+
+ return time_epoch_add (e, o);
+}
+
+
+void rtc_init (void)
+{
+ rtc_offset = bkp_read_off();
+ rtc_half = BKP_DR7;
+
+#if 1
+ rtc_offset.s = 1637490753;
+ rtc_offset.ns = 498866999;
+ bkp_write_off (rtc_offset);
+#endif
+
+
+ rtc_auto_awake (RCC_LSE, 0x7fff); //32768Hz
+ rtc_interrupt_enable (RTC_SEC);
+ nvic_enable_irq (NVIC_RTC_IRQ);
+
+}
+
+
diff --git a/stm32/app/ticker.c b/stm32/app/ticker.c
new file mode 100644
index 0000000..f124307
--- /dev/null
+++ b/stm32/app/ticker.c
@@ -0,0 +1,74 @@
+#include "project.h"
+
+
+volatile uint32_t ticks;
+static uint32_t scale = 7;
+
+unsigned led2 = 1000;
+
+
+
+void
+delay_us (uint32_t d)
+{
+ d *= scale;
+
+ while (d--)
+ __asm__ ("nop");
+}
+
+void
+sys_tick_handler (void)
+{
+ ticks++;
+ cdcacm_tick();
+ hands_tick();
+ motor_tick();
+
+ if (led2)
+ led2--;
+
+ if (led2)
+ CLEAR (LED2);
+
+ else
+ SET (LED2);
+}
+
+void
+ticker_init (void)
+{
+ uint32_t v, w;
+ /*Start periodic timer */
+ systick_set_clocksource (STK_CSR_CLKSOURCE_AHB_DIV8);
+ /* 72MHz / 8 = > 9Mhz */
+ systick_set_reload (9000);
+ /* 9MHz / 9000 => 1kHz */
+ systick_interrupt_enable();
+ systick_counter_enable();
+
+ /*Calibrate the delay loop */
+ do {
+ scale--;
+ v = ticks;
+
+ while (v == ticks)
+ ;
+
+ delay_us (1000);
+ w = ticks;
+ v++;
+ w -= v;
+ } while (w);
+
+}
+
+
+void delay_ms (uint32_t d)
+{
+ uint32_t v = ticks;
+
+ while ((ticks - v) < d);
+}
+
+
diff --git a/stm32/app/time_fn.c b/stm32/app/time_fn.c
new file mode 100644
index 0000000..825d90f
--- /dev/null
+++ b/stm32/app/time_fn.c
@@ -0,0 +1,650 @@
+#include <math.h>
+#include "project.h"
+
+static int is_leap (unsigned year)
+{
+ if (year % 4)
+ return 0;
+
+ if (year % 100)
+ return 1;
+
+ if (year % 400)
+ return 0;
+
+ return 1;
+}
+
+EPOCH time_epoch_sub (EPOCH a, EPOCH b)
+{
+ EPOCH ret;
+
+ ret.ns = a.ns - b.ns;
+ ret.s = a.s - b.s;
+
+ if (!ret.s) return ret;
+
+ if (ret.ns < 0) {
+ ret.s--;
+ ret.ns += 1000000000;
+ }
+
+ return ret;
+}
+
+
+EPOCH time_epoch_add (EPOCH a, EPOCH b)
+{
+ EPOCH ret;
+
+ ret.ns = a.ns + b.ns;
+ ret.s = a.s + b.s;
+
+ while (ret.ns > 1000000000) {
+ ret.s++;
+ ret.ns -= 1000000000;
+ }
+
+ return ret;
+}
+
+
+UTC time_epoch_to_utc (EPOCH epoch)
+{
+ UTC u = {0};
+ uint64_t day;
+ unsigned y400, y100, y4;
+
+ day = epoch.s / 86400;
+ epoch.s -= day * 86400;
+
+ day += 134774;
+
+ u.wday = day % 7;
+ u.wday++;
+
+
+ y400 = day / 146097; /*146097 days in 400 years */
+ day -= (y400 * 146097);
+
+ y100 = day / 36524; /*36524 days in 100 years */
+ day -= (y100 * 36524);
+
+ y4 = day / 1461; /*1461 days in 4 years */
+ day -= (y4 * 1461);
+
+ /* This may look redundant but 31 Dec in year 4 is special case */
+ if (day < 1095) { /*1095 days in 3 years */
+ u.year = day / 365; /*365 days in a year */
+ day -= (365 * u.year);
+ } else {
+ u.year = 3;
+ day -= 1095;
+ }
+
+
+ /* Now put it all back together */
+ u.year += 1601;
+ u.year += 4 * y4;
+ u.year += 100 * y100;
+ u.year += 400 * y400;
+
+
+ u.jday = day + 1;
+
+ u.is_leap = is_leap (u.year);
+
+
+ if (!u.is_leap) {
+ /*Days and months for ordinary years */
+ if (u.jday < 32) {
+ u.month = 1;
+ u.mday = u.jday;
+ } else if (u.jday < 60) {
+ u.month = 2;
+ u.mday = u.jday - 31;
+ } else if (u.jday < 91) {
+ u.month = 3;
+ u.mday = u.jday - 59;
+ } else if (u.jday < 121) {
+ u.month = 4;
+ u.mday = u.jday - 90;
+ } else if (u.jday < 152) {
+ u.month = 5;
+ u.mday = u.jday - 120;
+ } else if (u.jday < 182) {
+ u.month = 6;
+ u.mday = u.jday - 151;
+ } else if (u.jday < 213) {
+ u.month = 7;
+ u.mday = u.jday - 181;
+ } else if (u.jday < 244) {
+ u.month = 8;
+ u.mday = u.jday - 212;
+ } else if (u.jday < 274) {
+ u.month = 9;
+ u.mday = u.jday - 243;
+ } else if (u.jday < 305) {
+ u.month = 10;
+ u.mday = u.jday - 273;
+ } else if (u.jday < 335) {
+ u.month = 11;
+ u.mday = u.jday - 304;
+ } else {
+ u.month = 12;
+ u.mday = u.jday - 334;
+ }
+ } else {
+ /*And leap years */
+ if (u.jday < 32) {
+ u.month = 1;
+ u.mday = u.jday;
+ } else if (u.jday < 61) {
+ u.month = 2;
+ u.mday = u.jday - 31;
+ } else if (u.jday < 92) {
+ u.month = 3;
+ u.mday = u.jday - 60;
+ } else if (u.jday < 122) {
+ u.month = 4;
+ u.mday = u.jday - 91;
+ } else if (u.jday < 153) {
+ u.month = 5;
+ u.mday = u.jday - 121;
+ } else if (u.jday < 183) {
+ u.month = 6;
+ u.mday = u.jday - 152;
+ } else if (u.jday < 214) {
+ u.month = 7;
+ u.mday = u.jday - 182;
+ } else if (u.jday < 245) {
+ u.month = 8;
+ u.mday = u.jday - 213;
+ } else if (u.jday < 275) {
+ u.month = 9;
+ u.mday = u.jday - 244;
+ } else if (u.jday < 306) {
+ u.month = 10;
+ u.mday = u.jday - 274;
+ } else if (u.jday < 336) {
+ u.month = 11;
+ u.mday = u.jday - 305;
+ } else {
+ u.month = 12;
+ u.mday = u.jday - 335;
+ }
+ }
+
+ u.hour = epoch.s / 3600;
+ epoch.s -= u.hour * 3600;
+ u.minute = epoch.s / 60;
+ epoch.s -= u.minute * 60;
+ u.second = epoch.s;
+
+ u.nanosecond = epoch.ns;
+
+ return u;
+}
+
+EPOCH time_utc_to_epoch (UTC u)
+{
+ unsigned y400;
+ unsigned y100;
+ unsigned y4;
+
+ EPOCH ret;
+
+ static int const mdays[] =
+ { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ static int const lmdays[] =
+ { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
+
+ u.is_leap = is_leap (u.year);
+
+ if (u.year < 100) u.year += 2000;
+
+
+ if (!u.jday) {
+ if (u.is_leap)
+ u.jday = u.mday + lmdays[u.month];
+ else
+ u.jday = u.mday + mdays[u.month];
+ }
+
+ u.year -= 1601;
+ y400 = u.year / 400;
+ u.year -= y400 * 400;
+ y100 = u.year / 100;
+ u.year -= y100 * 100;
+ y4 = u.year / 4;
+ u.year -= y4 * 4;
+
+
+
+ ret.s = u.jday - 1;
+ ret.s += u.year * 365;
+ ret.s += y4 * 1461;
+ ret.s += y100 * 36524;
+ ret.s += y400 * 146097;
+
+ ret.s -= 134774;
+
+ ret.s *= 86400;
+
+ ret.s += u.second;
+ ret.s += u.minute * 60;
+ ret.s += u.hour * 3600;
+
+ ret.ns = u.nanosecond;
+
+ return ret;
+}
+
+void utc_to_str (char *dst, UTC *u)
+{
+ const char *dname[] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", "Sun"};
+ const char *mname[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ sprintf (dst, "%s %04d-%s-%02d %02d:%02d:%02d.%09d", dname[u->wday], u->year, mname[u->month], u->mday, u->hour, u->minute, u->second, u->nanosecond);
+}
+
+
+void time_print_utc (const char *p, UTC *u, const char *t)
+{
+ const char *dname[] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", "Sun"};
+ const char *mname[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ printf ("%s%s %04d-%s-%02d %02d:%02d:%02d.%09d %s\r\n", p ? p : "", dname[u->wday], u->year, mname[u->month], u->mday, u->hour, u->minute, u->second, u->nanosecond, t ? t : "");
+}
+
+void time_print_epoch (const char *p, EPOCH e, const char *t)
+{
+ UTC u = time_epoch_to_utc (e);
+ time_print_utc (p, &u, t);
+}
+
+
+double
+time_utc_to_tjd (UTC u)
+{
+ unsigned y400;
+ unsigned y100;
+ unsigned y4;
+
+ double ret;
+ unsigned jd;
+
+ static int const mdays[] =
+ { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ static int const lmdays[] =
+ { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
+
+ u.is_leap = is_leap (u.year);
+
+ if (u.year < 100)
+ u.year += 2000;
+
+
+ if (!u.jday) {
+ if (u.is_leap)
+ u.jday = u.mday + lmdays[u.month];
+ else
+ u.jday = u.mday + mdays[u.month];
+ }
+
+ u.year -= 1601;
+ y400 = u.year / 400;
+ u.year -= y400 * 400;
+ y100 = u.year / 100;
+ u.year -= y100 * 100;
+ y4 = u.year / 4;
+ u.year -= y4 * 4;
+
+ jd = u.jday - 1;
+ jd += u.year * 365;
+ jd += y4 * 1461;
+ jd += y100 * 36524;
+ jd += y400 * 146097;
+
+
+ jd += 2305813;
+ jd -= 2451545;
+
+
+
+ ret = (double) u.nanosecond;
+ ret /= 1000000000.;
+ ret += (double) u.second;
+ ret /= 60.;
+ ret += (double) u.minute;
+ ret /= 60.;
+ ret += (double) u.hour;
+ ret /= 24.;
+
+ ret += .5;
+
+ ret += (double) jd;
+
+ return ret;
+}
+
+
+EPOCH time_tjd_to_epoch (double tjd)
+{
+ EPOCH e;
+
+
+ tjd -= 2440587.5;
+
+ tjd *= 86400.;
+ e.s = (uint64_t) floor (tjd);
+
+ tjd -= (double) e.s;
+
+ tjd *= 1000000000.;
+ e.ns = (unsigned) floor (tjd);
+
+ return e;
+}
+
+UTC time_tjd_to_utc (double tjd)
+{
+ return time_epoch_to_utc (time_tjd_to_epoch (tjd));
+}
+
+
+
+RA ra_normalize (RA r)
+{
+
+ while (r.ra < 0.) {
+ r.ra += 360.;
+ r.days--;
+ }
+
+ if (r.ra >= 3600.0) {
+ r.days = (unsigned) (floor (r.ra / 360.) + .5);
+ r.ra = remainder (r.ra, 360.);
+ } else while (r.ra >= 360.0) {
+ r.ra -= 360.;
+ r.days++;
+ }
+
+ return r;
+}
+
+
+RA time_utc_to_ra (UTC u)
+{
+ RA r;
+ double tjd = time_utc_to_tjd (u);
+ double T = tjd / 36525.;
+
+ r.ra =
+ 280.46061837 + (360.98564736629 * tjd) + (0.000387933 * T * T) -
+ (T * T * T / 38710000.0);
+
+ r.days = 0;
+
+ return ra_normalize (r);
+}
+
+
+
+RA time_st_to_ra (ST st)
+{
+ RA r;
+ unsigned i;
+
+ r.days = st.days;
+
+ i = st.hour;
+ i *= 60;
+ i += st.minute;
+ i *= 60;
+ i += st.second;
+
+ r.ra = (double) st.nanosecond;
+ r.ra /= 1000000000.;
+ r.ra += (double) i;
+
+ r.ra /= 240.;
+
+ return r;
+}
+
+
+
+ST
+time_ra_to_st (RA r)
+{
+ ST ret;
+ unsigned i;
+
+ r = ra_normalize (r);
+
+ ret.days = r.days;
+
+ r.ra *= 240.0;
+
+ i = (int) (floor (r.ra) + .5);
+ r.ra -= (double) i;
+ r.ra *= 1000000000.;
+
+ ret.nanosecond = (unsigned) (r.ra + .5);
+ ret.second = i % 60;
+ i /= 60;
+ ret.minute = i % 60;
+ i /= 60;
+ ret.hour = i;
+
+
+ return ret;
+}
+
+
+
+ST time_utc_to_lst (UTC u, double lon)
+{
+ RA r;
+
+ r = time_utc_to_ra (u);
+
+ r.ra += lon;
+
+ return time_ra_to_st (r);
+}
+
+
+
+#if 0
+int time_ra_cmp (double a, double b)
+{
+ return (ra_normalize (a - b) < 180.) ? -1 : 1;;
+}
+
+
+/*Find the next occuring time for RA tra */
+
+static int test_side (EPOCH m, double tra)
+{
+
+ double ra;
+ UTC u;
+
+ u = time_epoch_to_utc (m);
+ ra = time_utc_to_ra (u);
+
+ return time_ra_cmp (ra, tra);
+}
+
+
+EPOCH time_ra_to_next_epoch (EPOCH l, double tra)
+{
+ EPOCH r, m;
+ unsigned n;
+
+ int dog = 48;
+
+ printf ("time_ra_to_next_epoch %.9f\n", tra);
+
+ /* XXX: we should use newton raphson, but */
+ /* 1) we're on team hooke */
+ /* 2) we want to limit the domain of solutions */
+ /* So IB works better */
+
+
+ while ((test_side (l, tra) != 1) && dog--)
+ l.s += 3600;
+
+ r = l;
+
+ while ((test_side (r, tra) != -1) && dog--)
+ r.s += 3600;
+
+ for (n = 0; n < 64; ++n) {
+
+ m = time_epoch_sub (r, l);
+
+ if (m.s < 0) {
+ m.s = 0;
+ m.ns = 0;
+ break;
+ }
+
+ if (m.s & 1)
+ m.ns += 1000000000;
+
+ m.s /= 2;
+ m.ns /= 2;
+
+ m = time_epoch_add (l, m);
+
+ if (test_side (m, tra) < 0)
+ r = m;
+ else
+ l = m;
+ }
+
+ return m;
+}
+
+#endif
+
+
+
+
+
+/*
+ * Returns the EPOCH for the start of the metric year which
+ * starts in the custumary year y
+ *
+ * the metric year begins on the autumnal equinox (at the paris observatory natch.)
+ */
+static EPOCH start_of_year (unsigned y)
+{
+ double tjd = autumnal_equinox (y);
+ UTC u;
+
+ tjd += (2.3372305555 / 360); /* Offset of paris meridian from greenwich */
+
+ u = time_tjd_to_utc (tjd);
+
+ u.hour =
+ u.minute =
+ u.second =
+ u.nanosecond = 0;
+
+ return time_utc_to_epoch (u);
+}
+
+MTIME time_to_metric (EPOCH e, UTC u)
+{
+ MTIME ret;
+
+ static EPOCH year_start, year_end;
+ static unsigned year;
+
+ unsigned s;
+ unsigned d;
+
+ double fd;
+
+ EPOCH equinox;
+
+ if ((e.s > year_end.s) || (e.s < year_start.s)) {
+ /*calculate the equinox in this customary year */
+
+ equinox = start_of_year (u.year);
+
+ if (e.s < equinox.s) {
+ year_start = start_of_year (u.year - 1);
+ year_end = equinox;
+ year = u.year - 1792;
+ } else {
+ year_start = equinox;
+ year_end = start_of_year (u.year + 1);
+ year = u.year - 1791;
+ }
+ }
+
+ ret.year = year;
+
+ e = time_epoch_sub (e, year_start);
+ s = e.s;
+ d = s / 86400;
+ s -= d * 86400;
+
+ ret.jday = d;
+
+ ret.month = (d / 30) + 1;
+ ret.mday = (d % 30) + 1;
+ ret.wday = d % 10;
+
+ /* Now for the horror of time of day */
+
+ fd = (double) e.ns;
+ fd /= 1000000000.;
+ fd += (double) s;
+ fd /= 86400.;
+ fd *= 100000;
+
+ s = (int) fd;
+ fd -= (double) s;
+ fd *= 1000000000.;
+
+ ret.nanosecond = (int) fd;
+
+ ret.second = s % 100;
+ s -= ret.second;
+ s /= 100;
+
+ ret.minute = s % 100;
+ s -= ret.minute;
+ s /= 100;
+
+ ret.hour = s;
+
+ return ret;
+}
+
+
+MTIME time_utc_to_metric (UTC u)
+{
+ return time_to_metric (time_utc_to_epoch (u), u);
+}
+
+
+MTIME time_epoch_to_metric (EPOCH e)
+{
+ return time_to_metric (e, time_epoch_to_utc (e));
+}
+
+
+
+void time_print_metric (const char *p, MTIME *m, const char *t)
+{
+ const char *dname[] = {"Pri", "Duo", "Tri", "Qua", "Qui", "Sex", "Sep", "Oct", "Non", "Dec" };
+ const char *mname[] = {"", "Ven", "Bru", "Fri", "Niv", "Plu", "Ven", "Ger", "Flo", "Pra", "Mes", "The", "Fru", "San"};
+ printf ("%s%s %03d-%s-%02d %01d:%02d:%02d.%09d %s\r\n", p ? p : "", dname[m->wday], m->year, mname[m->month], m->mday, m->hour, m->minute, m->second, m->nanosecond, t ? t : "");
+}
+
+
diff --git a/stm32/app/time_fn.h b/stm32/app/time_fn.h
new file mode 100644
index 0000000..0775a0f
--- /dev/null
+++ b/stm32/app/time_fn.h
@@ -0,0 +1,47 @@
+typedef struct {
+ unsigned year;
+ unsigned is_leap;
+ unsigned jday;
+ unsigned month;
+ unsigned mday;
+ unsigned wday;
+ unsigned hour;
+ unsigned minute;
+ unsigned second;
+ unsigned nanosecond;
+} UTC;
+
+typedef struct {
+ int64_t s;
+ int64_t ns;
+} EPOCH;
+
+
+typedef struct {
+ unsigned days;
+ double ra;
+} RA;
+
+typedef struct {
+ unsigned days;
+ unsigned hour;
+ unsigned minute;
+ unsigned second;
+ unsigned nanosecond;
+} ST;
+
+
+typedef struct {
+ unsigned year;
+ unsigned is_leap;
+ unsigned jday;
+ unsigned month;
+ unsigned mday;
+ unsigned wday;
+ unsigned hour;
+ unsigned minute;
+ unsigned second;
+ unsigned nanosecond;
+} MTIME;
+
+
diff --git a/stm32/app/usart.c b/stm32/app/usart.c
new file mode 100644
index 0000000..6b44656
--- /dev/null
+++ b/stm32/app/usart.c
@@ -0,0 +1,88 @@
+#include "project.h"
+
+#define BUFFER_SIZE 512
+
+ring_t usart_rx_ring;
+static uint8_t usart_rx_ring_buf[BUFFER_SIZE];
+
+ring_t usart_tx_ring;
+static uint8_t usart_tx_ring_buf[BUFFER_SIZE];
+
+void
+usart1_isr (void)
+{
+ uint8_t data;
+
+ /* Check if we were called because of RXNE. */
+ if (((USART_CR1 (USART1) & USART_CR1_RXNEIE) != 0) &&
+ ((USART_SR (USART1) & USART_SR_RXNE) != 0)) {
+ /* Retrieve the data from the peripheral. */
+ data = usart_recv (USART1);
+ ring_write_byte (&usart_rx_ring, data);
+ }
+
+ /* Check if we were called because of TXE. */
+ if (((USART_CR1 (USART1) & USART_CR1_TXEIE) != 0) &&
+ ((USART_SR (USART1) & USART_SR_TXE) != 0)) {
+ if (ring_read_byte (&usart_tx_ring, &data)) {
+ /*No more data, Disable the TXE interrupt, it's no longer needed. */
+ USART_CR1 (USART1) &= ~USART_CR1_TXEIE;
+ } else
+ usart_send (USART1, data);
+ }
+}
+
+void usart_kick (void)
+{
+ if (!ring_empty (&usart_tx_ring))
+ USART_CR1 (USART1) |= USART_CR1_TXEIE;
+}
+
+
+int
+_write (int file, char *ptr, int len)
+{
+ int ret;
+
+ if (file == 1) {
+ ret = ring_write (&usart_tx_ring, (uint8_t *) ptr, len);
+ usart_kick();
+ ring_write (&cdcacm_tx_ring, (uint8_t *) ptr, len);
+
+ if (ret < 0)
+ ret = -ret;
+
+ return ret;
+ }
+
+ errno = EIO;
+ return -1;
+}
+
+
+
+
+void
+usart_init (void)
+{
+ ring_init (&usart_rx_ring, usart_rx_ring_buf, sizeof (usart_rx_ring_buf));
+ ring_init (&usart_tx_ring, usart_tx_ring_buf, sizeof (usart_tx_ring_buf));
+ /* Enable the USART1 interrupt. */
+ nvic_enable_irq (NVIC_USART1_IRQ);
+
+ MAP_AF (USART1_TX);
+ MAP_AF_PU (USART1_RX);
+
+ /* Setup UART1 parameters. */
+ usart_set_baudrate (USART1, 115200);
+ usart_set_databits (USART1, 8);
+ usart_set_stopbits (USART1, USART_STOPBITS_1);
+ usart_set_parity (USART1, USART_PARITY_NONE);
+ usart_set_flow_control (USART1, USART_FLOWCONTROL_NONE);
+ usart_set_mode (USART1, USART_MODE_TX_RX);
+
+ /* Enable USART1 Receive interrupt. */
+ USART_CR1 (USART1) |= USART_CR1_RXNEIE;
+ /* Finally enable USART1. */
+ usart_enable (USART1);
+}
diff --git a/stm32/app/usb.c b/stm32/app/usb.c
new file mode 100644
index 0000000..e644270
--- /dev/null
+++ b/stm32/app/usb.c
@@ -0,0 +1,148 @@
+#include "project.h"
+
+#define USB_DM GPIO11
+#define USB_DM_PORT GPIOA
+#define USB_DP GPIO12
+#define USB_DP_PORT GPIOA
+
+/* Buffer to be used for control requests. */
+uint8_t usbd_control_buffer[128];
+usbd_device *usb_device;
+
+static const struct usb_device_descriptor dev = {
+ .bLength = USB_DT_DEVICE_SIZE,
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = 0xef,
+ .bDeviceSubClass = 0x02,
+ .bDeviceProtocol = 0x01,
+ .bMaxPacketSize0 = 64,
+ .idVendor = 0x0483,
+ .idProduct = 0xff03,
+ .bcdDevice = 0x0200,
+ .iManufacturer = 1,
+ .iProduct = 2,
+ .iSerialNumber = 3,
+ .bNumConfigurations = 1,
+};
+
+
+static const struct usb_interface ifaces[] = {
+ {
+ .num_altsetting = 1,
+ .altsetting = &dummy_kb_iface,
+ .iface_assoc = &dummy_kb_iface_assoc,
+ },
+ {
+ .num_altsetting = 1,
+ .altsetting = &dfu_iface,
+ .iface_assoc = &dfu_iface_assoc,
+ },
+ {
+ .num_altsetting = 1,
+ .altsetting = &comm_iface,
+ .iface_assoc = &cdc_iface_assoc,
+ },
+ {
+ .num_altsetting = 1,
+ .altsetting = &data_iface,
+ },
+};
+
+static const struct usb_config_descriptor config = {
+ .bLength = USB_DT_CONFIGURATION_SIZE,
+ .bDescriptorType = USB_DT_CONFIGURATION,
+ .wTotalLength = 0,
+ .bNumInterfaces = 4,
+ .bConfigurationValue = 1,
+ .iConfiguration = 0,
+ .bmAttributes = 0x80,
+ .bMaxPower = 0x32,
+ .interface = ifaces,
+};
+#define N_USB_STRINGS (sizeof(usb_strings)/sizeof(usb_strings[0]))
+
+static const char *usb_strings[] = {
+ VENDOR_NAME, /*1*/
+ PRODUCT_NAME, /*2*/
+ SERIAL_NUMBER, /*3*/
+ "dummy device", /*4*/
+ "DFU interface", /*5*/
+ "Debug interface", /*6*/
+};
+
+void usb_hp_can_tx_isr (void)
+{
+ usbd_poll (usb_device);
+}
+
+void usb_lp_can_rx0_isr (void)
+{
+ usbd_poll (usb_device);
+}
+
+static enum usbd_request_return_codes control_request (usbd_device *usbd_dev,
+ struct usb_setup_data *req,
+ uint8_t **buf,
+ uint16_t *len,
+ usbd_control_complete_callback *complete)
+{
+ enum usbd_request_return_codes ret;
+
+ ret = dfu_control_request (usbd_dev, req, buf, len, complete);
+
+ if (ret != USBD_REQ_NEXT_CALLBACK)
+ return ret;
+
+ ret = cdcacm_control_request (usbd_dev, req, buf, len, complete);
+
+ if (ret != USBD_REQ_NEXT_CALLBACK)
+ return ret;
+
+ return USBD_REQ_NOTSUPP;
+}
+
+static void set_config (usbd_device *usbd_dev, uint16_t wValue)
+{
+
+ cdcacm_set_config (usbd_dev, wValue);
+
+ usbd_register_control_callback (usbd_dev,
+ USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
+ USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
+ control_request);
+
+}
+
+
+
+void usb_init (void)
+{
+ /*Force USB reset */
+ gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
+ gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
+ gpio_clear (GPIOA, GPIO12);
+ gpio_clear (GPIOA, GPIO13);
+ delay_us (50000);
+ gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO11);
+ gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO12);
+
+
+ usb_device = usbd_init (&st_usbfs_v1_usb_driver,
+ &dev,
+ &config,
+ usb_strings,
+ N_USB_STRINGS,
+ usbd_control_buffer,
+ sizeof (usbd_control_buffer));
+
+ usbd_register_set_config_callback (usb_device, set_config);
+
+ nvic_enable_irq (NVIC_USB_HP_CAN_TX_IRQ);
+ nvic_enable_irq (NVIC_USB_LP_CAN_RX0_IRQ);
+
+
+
+}
+
+
diff --git a/stm32/boot/Makefile b/stm32/boot/Makefile
new file mode 100644
index 0000000..4891184
--- /dev/null
+++ b/stm32/boot/Makefile
@@ -0,0 +1,48 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+
+CSRCS=usbdfu.c
+PROG = usbdfu
+
+CPROTO=cproto
+V=1
+BINARY = ${PROG}
+OBJS = ${CSRCS:%.c=%.o}
+
+include ../Makefile.include
+
+CFLAGS += -I..
+
+ds:
+ $(Q)$(OOCD) -f $(OOCD_INTERFACE) \
+ -f $(OOCD_BOARD) \
+
+debug: ${PROG}.elf
+ ${PREFIX}-gdb -x gdb.script ${PROG}.elf
+
+reset:
+ $(Q)$(OOCD) -f $(OOCD_INTERFACE) \
+ -f $(OOCD_BOARD) \
+ -c "init" -c "reset run" \
+ -c shutdown
+
+tidy:
+ astyle -A3 -s2 --attach-extern-c -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS} || astyle -A3 -s2 -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS}
+
diff --git a/stm32/boot/gdb.script b/stm32/boot/gdb.script
new file mode 100644
index 0000000..7cf9d09
--- /dev/null
+++ b/stm32/boot/gdb.script
@@ -0,0 +1,2 @@
+target remote localhost:3333
+cont
diff --git a/stm32/boot/project.h b/stm32/boot/project.h
new file mode 100644
index 0000000..0323569
--- /dev/null
+++ b/stm32/boot/project.h
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/usb/usbd.h>
+#include <libopencm3/usb/hid.h>
+
+#define INCLUDE_DFU_INTERFACE
+
+
+#ifdef INCLUDE_DFU_INTERFACE
+#include <libopencm3/cm3/scb.h>
+#include <libopencm3/usb/dfu.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "ring.h"
+
+#include "prototypes.h"
diff --git a/stm32/boot/prototypes.h b/stm32/boot/prototypes.h
new file mode 100644
index 0000000..45d399c
--- /dev/null
+++ b/stm32/boot/prototypes.h
@@ -0,0 +1,18 @@
+/* usbdfu.c */
+extern uint8_t usbd_control_buffer[1024];
+extern const struct usb_device_descriptor dev;
+extern const struct usb_dfu_descriptor dfu_function;
+extern const struct usb_interface_descriptor iface;
+extern const struct usb_interface ifaces[];
+extern const struct usb_config_descriptor config;
+extern int main(void);
+/* ring.c */
+extern void ring_init(ring_t *r, uint8_t *buf, size_t len);
+extern int ring_write_byte(ring_t *r, uint8_t c);
+extern int ring_read_byte(ring_t *r, uint8_t *c);
+extern int ring_write(ring_t *r, uint8_t *buf, size_t len);
+/* usart.c */
+extern void usart1_isr(void);
+extern int _write(int file, char *ptr, int len);
+extern void usart_queue(uint8_t d);
+extern void usart_init(void);
diff --git a/stm32/boot/usbdfu.c b/stm32/boot/usbdfu.c
new file mode 100644
index 0000000..7cba7f9
--- /dev/null
+++ b/stm32/boot/usbdfu.c
@@ -0,0 +1,334 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/flash.h>
+#include <libopencm3/cm3/scb.h>
+#include <libopencm3/usb/usbd.h>
+#include <libopencm3/usb/dfu.h>
+
+#include <id.h>
+
+#define APP_ADDRESS 0x08002000
+
+/* Commands sent with wBlockNum == 0 as per ST implementation. */
+#define CMD_SETADDR 0x21
+#define CMD_ERASE 0x41
+
+void usb_set_config (usbd_device *usbd_dev, uint16_t wValue);
+
+/* We need a special large control buffer for this device: */
+uint8_t usbd_control_buffer[1024];
+
+static enum dfu_state usbdfu_state = STATE_DFU_IDLE;
+
+extern uint32_t dfu_flag;
+
+static struct {
+ uint8_t buf[sizeof (usbd_control_buffer)];
+ uint16_t len;
+ uint32_t addr;
+ uint16_t blocknum;
+} prog;
+
+const struct usb_device_descriptor dev = {
+ .bLength = USB_DT_DEVICE_SIZE,
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = 0x0200,
+ .bDeviceClass = 0,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
+ .bMaxPacketSize0 = 64,
+ .idVendor = 0x0483,
+ .idProduct = 0xdf11,
+ .bcdDevice = 0x0200,
+ .iManufacturer = 1,
+ .iProduct = 2,
+ .iSerialNumber = 3,
+ .bNumConfigurations = 1,
+};
+
+const struct usb_dfu_descriptor dfu_function = {
+ .bLength = sizeof (struct usb_dfu_descriptor),
+ .bDescriptorType = DFU_FUNCTIONAL,
+ .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH,
+ .wDetachTimeout = 255,
+ .wTransferSize = 1024,
+ .bcdDFUVersion = 0x011A,
+};
+
+const struct usb_interface_descriptor iface = {
+ .bLength = USB_DT_INTERFACE_SIZE,
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = 0xFE, /* Device Firmware Upgrade */
+ .bInterfaceSubClass = 1,
+ .bInterfaceProtocol = 2,
+
+ /* The ST Microelectronics DfuSe application needs this string.
+ * The format isn't documented... */
+ .iInterface = 4,
+
+ .extra = &dfu_function,
+ .extralen = sizeof (dfu_function),
+};
+
+const struct usb_interface ifaces[] = {{
+ .num_altsetting = 1,
+ .altsetting = &iface,
+ }
+};
+
+const struct usb_config_descriptor config = {
+ .bLength = USB_DT_CONFIGURATION_SIZE,
+ .bDescriptorType = USB_DT_CONFIGURATION,
+ .wTotalLength = 0,
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = 0,
+ .bmAttributes = 0xC0,
+ .bMaxPower = 0x32,
+
+ .interface = ifaces,
+};
+
+static const char *usb_strings[] = {
+ VENDOR_NAME,
+ PRODUCT_NAME " (dfu mode)",
+ SERIAL_NUMBER,
+ /* This string is used by ST Microelectronics' DfuSe utility. */
+ "@Internal Flash /0x08000000/8*001Ka,56*001Kg",
+};
+#define N_USB_STRINGS (sizeof(usb_strings)/sizeof(usb_strings[0]))
+
+static void
+delay_us (uint32_t d)
+{
+ d *= 7;
+
+ while (d--)
+ __asm__ ("nop");
+}
+
+
+static uint8_t usbdfu_getstatus (usbd_device *usbd_dev, uint32_t *bwPollTimeout)
+{
+ (void)usbd_dev;
+
+ switch (usbdfu_state) {
+ case STATE_DFU_DNLOAD_SYNC:
+ usbdfu_state = STATE_DFU_DNBUSY;
+ *bwPollTimeout = 100;
+ return DFU_STATUS_OK;
+
+ case STATE_DFU_MANIFEST_SYNC:
+ /* Device will reset when read is complete. */
+ usbdfu_state = STATE_DFU_MANIFEST;
+ return DFU_STATUS_OK;
+
+ default:
+ return DFU_STATUS_OK;
+ }
+}
+
+static void usbdfu_getstatus_complete (usbd_device *usbd_dev, struct usb_setup_data *req)
+{
+ int i;
+ (void)req;
+ (void)usbd_dev;
+
+ switch (usbdfu_state) {
+ case STATE_DFU_DNBUSY:
+ flash_unlock();
+
+ if (prog.blocknum == 0) {
+ switch (prog.buf[0]) {
+ case CMD_ERASE: {
+ uint32_t *dat = (uint32_t *) (prog.buf + 1);
+ flash_erase_page (*dat);
+ }
+ break;
+
+ case CMD_SETADDR: {
+ uint32_t *dat = (uint32_t *) (prog.buf + 1);
+ prog.addr = *dat;
+ }
+ }
+ } else {
+ uint32_t baseaddr = prog.addr + ((prog.blocknum - 2) *
+ dfu_function.wTransferSize);
+
+ for (i = 0; i < prog.len; i += 2) {
+ uint16_t *dat = (uint16_t *) (prog.buf + i);
+ flash_program_half_word (baseaddr + i,
+ *dat);
+ }
+ }
+
+ flash_lock();
+
+ /* Jump straight to dfuDNLOAD-IDLE, skipping dfuDNLOAD-SYNC. */
+ usbdfu_state = STATE_DFU_DNLOAD_IDLE;
+ return;
+
+ case STATE_DFU_MANIFEST:
+ /* USB device must detach, we just reset... */
+ scb_reset_system();
+ return; /* Will never return. */
+
+ default:
+ ;
+ }
+
+}
+
+static enum usbd_request_return_codes usbdfu_control_request (usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf,
+ uint16_t *len, usbd_control_complete_callback *complete)
+{
+
+ if ((req->bmRequestType & 0x7F) != 0x21)
+ return USBD_REQ_NEXT_CALLBACK;
+
+ switch (req->bRequest) {
+ case DFU_DNLOAD:
+ if ((len == NULL) || (*len == 0)) {
+ usbdfu_state = STATE_DFU_MANIFEST_SYNC;
+ } else {
+ /* Copy download data for use on GET_STATUS. */
+ prog.blocknum = req->wValue;
+ prog.len = *len;
+ memcpy (prog.buf, *buf, *len);
+ usbdfu_state = STATE_DFU_DNLOAD_SYNC;
+ }
+ return USBD_REQ_HANDLED;
+
+ case DFU_CLRSTATUS:
+
+ /* Clear error and return to dfuIDLE. */
+ if (usbdfu_state == STATE_DFU_ERROR)
+ usbdfu_state = STATE_DFU_IDLE;
+
+ return USBD_REQ_HANDLED;
+
+ case DFU_ABORT:
+ /* Abort returns to dfuIDLE state. */
+ usbdfu_state = STATE_DFU_IDLE;
+ return USBD_REQ_HANDLED;
+
+ case DFU_UPLOAD:
+ /* Upload not supported for now. */
+ return USBD_REQ_NOTSUPP;
+
+ case DFU_GETSTATUS: {
+ uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */
+ (*buf)[0] = usbdfu_getstatus (usbd_dev, &bwPollTimeout);
+ (*buf)[1] = bwPollTimeout & 0xFF;
+ (*buf)[2] = (bwPollTimeout >> 8) & 0xFF;
+ (*buf)[3] = (bwPollTimeout >> 16) & 0xFF;
+ (*buf)[4] = usbdfu_state;
+ (*buf)[5] = 0; /* iString not used here */
+ *len = 6;
+ *complete = usbdfu_getstatus_complete;
+ return USBD_REQ_HANDLED;
+ }
+
+ case DFU_GETSTATE:
+ /* Return state with no state transision. */
+ *buf[0] = usbdfu_state;
+ *len = 1;
+ return USBD_REQ_HANDLED;
+ }
+
+ return USBD_REQ_NEXT_CALLBACK;
+}
+
+static void usb_reset (void)
+{
+ /*Force USB reset */
+ gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
+ gpio_set_mode (GPIOA, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
+ gpio_clear (GPIOA, GPIO11);
+ gpio_clear (GPIOA, GPIO12);
+
+ delay_us (5000);
+ gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO11);
+ gpio_set_mode (GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO12);
+}
+
+
+void
+usb_set_config (usbd_device *usbd_dev, uint16_t wValue)
+{
+ (void) wValue;
+ (void) usbd_dev;
+
+ usbd_register_control_callback (
+ usbd_dev,
+ USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE,
+ USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
+ usbdfu_control_request);
+
+}
+
+int main (void)
+{
+ usbd_device *usbd_dev;
+
+ rcc_periph_clock_enable (RCC_GPIOA);
+ rcc_periph_reset_pulse (RST_USB);
+
+ if (dfu_flag != 0xfee1dead) {
+ /* Boot the application if it's valid. */
+ if ((* (volatile uint32_t *)APP_ADDRESS & 0x2FFE0000) == 0x20000000) {
+ /* Set vector table base address. */
+ SCB_VTOR = APP_ADDRESS & 0xFFFF;
+ /* Initialise master stack pointer. */
+ asm volatile ("msr msp, %0"::"g"
+ (* (volatile uint32_t *)APP_ADDRESS));
+ /* Jump to application. */
+ (* (void (* *)()) (APP_ADDRESS + 4))();
+ }
+ }
+
+ usb_reset();
+
+ dfu_flag = 0;
+
+ rcc_clock_setup_pll(&rcc_hsi_configs[RCC_CLOCK_HSI_48MHZ]);
+
+ rcc_periph_clock_enable (RCC_GPIOC);
+
+ gpio_set_mode (GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
+ GPIO_CNF_OUTPUT_PUSHPULL, GPIO11);
+ gpio_set (GPIOC, GPIO11);
+
+
+ usbd_dev = usbd_init (&st_usbfs_v1_usb_driver, &dev, &config, usb_strings, N_USB_STRINGS, usbd_control_buffer, sizeof (usbd_control_buffer));
+
+ usbd_register_set_config_callback (usbd_dev, usb_set_config);
+
+ gpio_clear (GPIOC, GPIO11);
+
+ while (1)
+ usbd_poll (usbd_dev);
+}
diff --git a/stm32/boot/usbdfu.ld b/stm32/boot/usbdfu.ld
new file mode 100644
index 0000000..498bcea
--- /dev/null
+++ b/stm32/boot/usbdfu.ld
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the libopencm3 project.
+ *
+ * Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+ *
+ * This library is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Linker script for Olimex STM32-H103 (STM32F103RBT6, 128K flash, 20K RAM). */
+
+/* Define memory regions. */
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K
+ ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K
+}
+
+/* Include the common ld script. */
+INCLUDE cortex-m-generic.ld
+
+dfu_shared_location = ORIGIN(ram) + LENGTH(ram) - 1024;
+
+SECTIONS
+{
+ .dfu_shared dfu_shared_location :{
+ dfu_flag = .;
+ }
+}
+
diff --git a/stm32/docs/Astronomical Algorithms.pdf b/stm32/docs/Astronomical Algorithms.pdf
new file mode 100644
index 0000000..52cc63a
--- /dev/null
+++ b/stm32/docs/Astronomical Algorithms.pdf
Binary files differ
diff --git a/stm32/docs/rm0008.pdf b/stm32/docs/rm0008.pdf
new file mode 100644
index 0000000..8f3d0e1
--- /dev/null
+++ b/stm32/docs/rm0008.pdf
Binary files differ
diff --git a/stm32/id.h b/stm32/id.h
new file mode 100644
index 0000000..d27ecf7
--- /dev/null
+++ b/stm32/id.h
@@ -0,0 +1,4 @@
+#define VENDOR_NAME "HP"
+#define PRODUCT_NAME "DDC Debug Dongle"
+#define SERIAL_NUMBER "Serialy McSerialFace"
+
diff --git a/stm32/libopencm3 b/stm32/libopencm3
new file mode 160000
+Subproject a9cc6953817e0de1cad06662ce58a81607cd796
diff --git a/stm32/oocd/board/STM32F103R_BOARD.cfg b/stm32/oocd/board/STM32F103R_BOARD.cfg
new file mode 100644
index 0000000..11217d2
--- /dev/null
+++ b/stm32/oocd/board/STM32F103R_BOARD.cfg
@@ -0,0 +1,6 @@
+#
+
+source [find target/stm32f1x.cfg]
+
+adapter_khz 500
+
diff --git a/stm32/oocd/interface/j-link.cfg b/stm32/oocd/interface/j-link.cfg
new file mode 100644
index 0000000..3e95768
--- /dev/null
+++ b/stm32/oocd/interface/j-link.cfg
@@ -0,0 +1,5 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+source [find interface/jlink.cfg]
diff --git a/stm32/oocd/interface/stlink-v2.cfg b/stm32/oocd/interface/stlink-v2.cfg
new file mode 100644
index 0000000..0985230
--- /dev/null
+++ b/stm32/oocd/interface/stlink-v2.cfg
@@ -0,0 +1,11 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+#interface hla
+#hla_layout stlink
+#hla_device_desc "ST-LINK/V2"
+#hla_vid_pid 0x0483 0x3748
+
+source [find interface/stlink-v2.cfg]
+
diff --git a/stm32/oocd/stm32-f103.cfg b/stm32/oocd/stm32-f103.cfg
new file mode 100644
index 0000000..0809223
--- /dev/null
+++ b/stm32/oocd/stm32-f103.cfg
@@ -0,0 +1,6 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+source [find interface/jlink.cfg]
+source [find target/stm32f1x.cfg]
diff --git a/stm32/tools/dfuse-pack.py b/stm32/tools/dfuse-pack.py
new file mode 100755
index 0000000..c0a5f0a
--- /dev/null
+++ b/stm32/tools/dfuse-pack.py
@@ -0,0 +1,256 @@
+#!/usr/bin/python
+
+# Written by Antonio Galea - 2010/11/18
+# Distributed under Gnu LGPL 3.0
+# see http://www.gnu.org/licenses/lgpl-3.0.txt
+
+import sys,struct,zlib,os
+import binascii
+from optparse import OptionParser
+
+try:
+ from intelhex import IntelHex
+except ImportError:
+ IntelHex = None
+
+DEFAULT_DEVICE="0x0483:0xdf11"
+DEFAULT_NAME=b'ST...'
+
+# Prefix and Suffix sizes are derived from ST's DfuSe File Format Specification (UM0391), DFU revision 1.1a
+PREFIX_SIZE=11
+SUFFIX_SIZE=16
+
+def named(tuple,names):
+ return dict(list(zip(names.split(),tuple)))
+def consume(fmt,data,names):
+ n = struct.calcsize(fmt)
+ return named(struct.unpack(fmt,data[:n]),names),data[n:]
+def cstring(bytestring):
+ return bytestring.partition(b'\0')[0]
+def compute_crc(data):
+ return 0xFFFFFFFF & -zlib.crc32(data) -1
+
+def parse(file,dump_images=False):
+ print('File: "%s"' % file)
+ data = open(file,'rb').read()
+ crc = compute_crc(data[:-4])
+ prefix, data = consume('<5sBIB',data,'signature version size targets')
+ print('%(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d' % prefix)
+ for t in range(prefix['targets']):
+ tprefix, data = consume('<6sBI255s2I',data,'signature altsetting named name size elements')
+ tprefix['num'] = t
+ if tprefix['named']:
+ tprefix['name'] = cstring(tprefix['name'])
+ else:
+ tprefix['name'] = ''
+ print('%(signature)s %(num)d, alt setting: %(altsetting)s, name: "%(name)s", size: %(size)d, elements: %(elements)d' % tprefix)
+ tsize = tprefix['size']
+ target, data = data[:tsize], data[tsize:]
+ for e in range(tprefix['elements']):
+ eprefix, target = consume('<2I',target,'address size')
+ eprefix['num'] = e
+ print(' %(num)d, address: 0x%(address)08x, size: %(size)d' % eprefix)
+ esize = eprefix['size']
+ image, target = target[:esize], target[esize:]
+ if dump_images:
+ out = '%s.target%d.image%d.bin' % (file,t,e)
+ open(out,'wb').write(image)
+ print(' DUMPED IMAGE TO "%s"' % out)
+ if len(target):
+ print("target %d: PARSE ERROR" % t)
+ suffix = named(struct.unpack('<4H3sBI',data[:SUFFIX_SIZE]),'device product vendor dfu ufd len crc')
+ print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix)
+ if crc != suffix['crc']:
+ print("CRC ERROR: computed crc32 is 0x%08x" % crc)
+ data = data[SUFFIX_SIZE:]
+ if data:
+ print("PARSE ERROR")
+
+def checkbin(binfile):
+ data = open(binfile,'rb').read()
+ if (len(data) < SUFFIX_SIZE):
+ return
+ crc = compute_crc(data[:-4])
+ suffix = named(struct.unpack('<4H3sBI',data[-SUFFIX_SIZE:]),'device product vendor dfu ufd len crc')
+ if crc == suffix['crc'] and suffix['ufd'] == b'UFD':
+ print('usb: %(vendor)04x:%(product)04x, device: 0x%(device)04x, dfu: 0x%(dfu)04x, %(ufd)s, %(len)d, 0x%(crc)08x' % suffix)
+ print("It looks like the file %s has a DFU suffix!" % binfile)
+ print("Please remove any DFU suffix and retry.")
+ sys.exit(1)
+
+def build(file,targets,name=DEFAULT_NAME,device=DEFAULT_DEVICE):
+ data = b''
+ for t,target in enumerate(targets):
+ tdata = b''
+ for image in target:
+ tdata += struct.pack('<2I',image['address'],len(image['data']))+image['data']
+ ealt = image['alt']
+ tdata = struct.pack('<6sBI255s2I',b'Target',ealt,1,name,len(tdata),len(target)) + tdata
+ data += tdata
+ data = struct.pack('<5sBIB',b'DfuSe',1,PREFIX_SIZE + len(data) + SUFFIX_SIZE,len(targets)) + data
+ v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)]
+ data += struct.pack('<4H3sB',0,d,v,0x011a,b'UFD',SUFFIX_SIZE)
+ crc = compute_crc(data)
+ data += struct.pack('<I',crc)
+ open(file,'wb').write(data)
+
+if __name__=="__main__":
+ usage = """
+%prog [-d|--dump] infile.dfu
+%prog {-b|--build} address:file.bin [-b address:file.bin ...] [{-D|--device}=vendor:device] outfile.dfu
+%prog {-s|--build-s19} file.s19 [{-D|--device}=vendor:device] outfile.dfu
+%prog {-i|--build-ihex} file.hex [-i file.hex ...] [{-D|--device}=vendor:device] outfile.dfu"""
+ parser = OptionParser(usage=usage)
+ parser.add_option("-b", "--build", action="append", dest="binfiles",
+ help="Include a raw binary file, to be loaded at the specified address. The BINFILES argument is of the form address:path-to-file. The address can have @X appended where X is the alternate interface number for this binary file. Note that the binary files must not have any DFU suffix!", metavar="BINFILES")
+ parser.add_option("-i", "--build-ihex", action="append", dest="hexfiles",
+ help="build a DFU file from given Intel HEX HEXFILES", metavar="HEXFILES")
+ parser.add_option("-s", "--build-s19", type="string", dest="s19files",
+ help="build a DFU file from given S19 S-record S19FILE", metavar="S19FILE")
+ parser.add_option("-D", "--device", action="store", dest="device",
+ help="build for DEVICE, defaults to %s" % DEFAULT_DEVICE, metavar="DEVICE")
+ parser.add_option("-a", "--alt-intf", action="store", dest="alt",
+ help="build for alternate interface number ALTINTF, defaults to 0", metavar="ALTINTF")
+ parser.add_option("-d", "--dump", action="store_true", dest="dump_images",
+ default=False, help="dump contained images to current directory")
+ (options, args) = parser.parse_args()
+
+ targets = []
+
+ if options.alt:
+ try:
+ default_alt = int(options.alt)
+ except ValueError:
+ print("Alternate interface option argument %s invalid." % options.alt)
+ sys.exit(1)
+ else:
+ default_alt = 0
+
+ if (options.binfiles or options.hexfiles) and len(args)==1:
+ target = []
+ old_ealt = None
+
+ if options.binfiles:
+ for arg in options.binfiles:
+ try:
+ address,binfile = arg.split(':',1)
+ except ValueError:
+ print("Address:file couple '%s' invalid." % arg)
+ sys.exit(1)
+ try:
+ address,alts = address.split('@',1)
+ if alts:
+ try:
+ ealt = int(alts)
+ except ValueError:
+ print("Alternate interface number %s invalid." % alts)
+ sys.exit(1)
+ else:
+ ealt = default_alt
+ except ValueError:
+ ealt = default_alt
+ try:
+ address = int(address,0) & 0xFFFFFFFF
+ except ValueError:
+ print("Address %s invalid." % address)
+ sys.exit(1)
+ if not os.path.isfile(binfile):
+ print("Unreadable file '%s'." % binfile)
+ sys.exit(1)
+ checkbin(binfile)
+ if old_ealt is not None and ealt != old_ealt:
+ targets.append(target)
+ target = []
+ target.append({ 'address': address, 'alt': ealt, 'data': open(binfile,'rb').read() })
+ old_ealt = ealt
+ targets.append(target)
+
+ if options.hexfiles:
+ if not IntelHex:
+ print("Error: IntelHex python module could not be found")
+ sys.exit(1)
+ for hexf in options.hexfiles:
+ ih = IntelHex(hexf)
+ for (address,end) in ih.segments():
+ try:
+ address = address & 0xFFFFFFFF
+ except ValueError:
+ print("Address %s invalid." % address)
+ sys.exit(1)
+ target.append({ 'address': address, 'alt': default_alt, 'data': ih.tobinstr(start=address, end=end-1)})
+ targets.append(target)
+
+ outfile = args[0]
+ device = DEFAULT_DEVICE
+ if options.device:
+ device=options.device
+ try:
+ v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)]
+ except:
+ print("Invalid device '%s'." % device)
+ sys.exit(1)
+ build(outfile,targets,DEFAULT_NAME,device)
+ elif options.s19files and len(args)==1:
+ address = 0
+ data = ""
+ target = []
+ name = DEFAULT_NAME
+ with open(options.s19files) as f:
+ lines = f.readlines()
+ for line in lines:
+ curaddress = 0
+ curdata = ""
+ line = line.rstrip()
+ if line.startswith ( "S0" ):
+ name = binascii.a2b_hex(line[8:len(line) - 2])
+ elif line.startswith ( "S3" ):
+ try:
+ curaddress = int(line[4:12], 16) & 0xFFFFFFFF
+ except ValueError:
+ print("Address %s invalid." % address)
+ sys.exit(1)
+ curdata = binascii.unhexlify(line[12:-2])
+ elif line.startswith ( "S2" ):
+ try:
+ curaddress = int(line[4:10], 16) & 0xFFFFFFFF
+ except ValueError:
+ print("Address %s invalid." % address)
+ sys.exit(1)
+ curdata = binascii.unhexlify(line[10:-2])
+ elif line.startswith ( "S1" ):
+ try:
+ curaddress = int(line[4:8], 16) & 0xFFFFFFFF
+ except ValueError:
+ print("Address %s invalid." % address)
+ sys.exit(1)
+ curdata = binascii.unhexlify(line[8:-2])
+ if address == 0:
+ address = curaddress
+ data = curdata
+ elif address + len(data) != curaddress:
+ target.append({ 'address': address, 'alt': default_alt, 'data': data })
+ address = curaddress
+ data = curdata
+ else:
+ data += curdata
+ outfile = args[0]
+ device = DEFAULT_DEVICE
+ if options.device:
+ device=options.device
+ try:
+ v,d=[int(x,0) & 0xFFFF for x in device.split(':',1)]
+ except:
+ print("Invalid device '%s'." % device)
+ sys.exit(1)
+ build(outfile,[target],name,device)
+ elif len(args)==1:
+ infile = args[0]
+ if not os.path.isfile(infile):
+ print("Unreadable file '%s'." % infile)
+ sys.exit(1)
+ parse(infile, dump_images=options.dump_images)
+ else:
+ parser.print_help()
+ if not IntelHex:
+ print("Note: Intel hex files support requires the IntelHex python module")
+ sys.exit(1)