Browse Source

Added project files

asdrea 7 years ago
parent
commit
a4b9a8350c
8 changed files with 1025 additions and 1 deletions
  1. 2 1
      LICENSE
  2. 21 0
      Makefile
  3. 392 0
      box-cover.svg
  4. 63 0
      genwts.py
  5. 196 0
      main.c
  6. 200 0
      main.hex
  7. 140 0
      wavetables.c
  8. 11 0
      wavetables.h

+ 2 - 1
LICENSE

@@ -1,4 +1,5 @@
-Copyright (c) <year> <owner> . All rights reserved.
+Copyright (c) 2017, Ridiculous Glitch <goat@ridiculousglitch.com>
+
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 
 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

+ 21 - 0
Makefile

@@ -0,0 +1,21 @@
+CROSS_COMPILE=/opt/avr8-gnu-toolchain-linux_x86_64/bin/avr-
+OBJCOPY=$(CROSS_COMPILE)objcopy
+CC=$(CROSS_COMPILE)gcc
+CFLAGS=-O3 -Wall -mmcu=attiny85
+
+main.hex: main
+	$(OBJCOPY) -j .data -j .text -O ihex main main.hex
+
+main: main.c wavetables.c
+
+# hfuse DISABLE RESET, then *high-voltage serial ONLY*
+# avrdude -c usbasp -p t85 -U lfuse:w:0xf1:m -U hfuse:w:0x5f:m # efuse
+
+flash: main.hex
+#	avrdude -c usbasp -p t85 -U lfuse:w:0xf1:m # hfuse,efuse
+	avrdude -c usbasp -p t85 -U flash:w:main.hex
+
+clean:
+	rm -f main main.hex
+
+.PHONY: clean flash

+ 392 - 0
box-cover.svg

@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<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="549.21259"
+   height="318.89764"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="cover.svg"
+   inkscape:export-filename="/home/simonetto/hello-attiny85/cover.png"
+   inkscape:export-xdpi="300.04776"
+   inkscape:export-ydpi="300.04776">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#000000"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.979899"
+     inkscape:cx="357.52634"
+     inkscape:cy="123.79383"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     units="mm"
+     inkscape:showpageshadow="false"
+     borderlayer="false"
+     inkscape:snap-page="false"
+     inkscape:window-width="2560"
+     inkscape:window-height="1018"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:snap-center="true"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-grids="false"
+     inkscape:snap-to-guides="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2987"
+       empspacing="10"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       units="mm"
+       spacingx="1mm"
+       spacingy="1mm"
+       dotted="true" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="274.6063,159.44882"
+       id="guide3048" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="70.866142,318.89764"
+       id="guide3161" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="0,265.74803"
+       id="guide3163" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="0,166.53543"
+       id="guide3165" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="478.34646,318.89764"
+       id="guide3167" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="0,216.14173"
+       id="guide3169" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="201.9685,318.89764"
+       id="guide3171" />
+    <sodipodi:guide
+       orientation="1,0"
+       position="343.70079,318.89764"
+       id="guide3173" />
+    <sodipodi:guide
+       orientation="0,1"
+       position="0,53.149606"
+       id="guide3371" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <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:label="Livello 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-733.46456)">
+    <rect
+       style="color:#000000;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="rect2985"
+       width="549.21259"
+       height="318.89764"
+       x="0"
+       y="0"
+       transform="translate(0,733.46456)"
+       rx="0"
+       ry="0" />
+    <g
+       id="g3132"
+       transform="translate(-17.716536,-35.433067)">
+      <path
+         transform="translate(47.834646,781.2992)"
+         d="m 81.496063,40.748039 c 0,22.504517 -18.243515,40.748032 -40.748031,40.748032 C 18.243515,81.496071 0,63.252556 0,40.748039 0,18.243523 18.243515,7.6293945e-6 40.748032,7.6293945e-6 63.252548,7.6293945e-6 81.496063,18.243523 81.496063,40.748039 z"
+         sodipodi:ry="40.748032"
+         sodipodi:rx="40.748032"
+         sodipodi:cy="40.748039"
+         sodipodi:cx="40.748032"
+         id="path3130"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(72.637796,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3140"
+       transform="translate(-116.92914,14.173228)">
+      <path
+         transform="translate(396.8504,758.26771)"
+         d="m 127.55905,63.779533 c 0,35.22446 -28.555065,63.779527 -63.779524,63.779527 C 28.555066,127.55906 0,99.003993 0,63.779533 0,28.555074 28.555066,7.6293945e-6 63.779526,7.6293945e-6 99.003985,7.6293945e-6 127.55905,28.555074 127.55905,63.779533 z"
+         sodipodi:ry="63.779526"
+         sodipodi:rx="63.779526"
+         sodipodi:cy="63.779533"
+         sodipodi:cx="63.779526"
+         id="path3138"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(444.68504,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7-5"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3132-3"
+       transform="translate(-17.716536,63.779535)">
+      <path
+         transform="translate(47.834646,781.2992)"
+         d="m 81.496063,40.748039 c 0,22.504517 -18.243515,40.748032 -40.748031,40.748032 C 18.243515,81.496071 0,63.252556 0,40.748039 0,18.243523 18.243515,7.6293945e-6 40.748032,7.6293945e-6 63.252548,7.6293945e-6 81.496063,18.243523 81.496063,40.748039 z"
+         sodipodi:ry="40.748032"
+         sodipodi:rx="40.748032"
+         sodipodi:cy="40.748039"
+         sodipodi:cx="40.748032"
+         id="path3130-6"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(72.637796,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7-7"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3132-5"
+       transform="translate(113.38582,-35.433067)">
+      <path
+         transform="translate(47.834646,781.2992)"
+         d="m 81.496063,40.748039 c 0,22.504517 -18.243515,40.748032 -40.748031,40.748032 C 18.243515,81.496071 0,63.252556 0,40.748039 0,18.243523 18.243515,7.6293945e-6 40.748032,7.6293945e-6 63.252548,7.6293945e-6 81.496063,18.243523 81.496063,40.748039 z"
+         sodipodi:ry="40.748032"
+         sodipodi:rx="40.748032"
+         sodipodi:cy="40.748039"
+         sodipodi:cx="40.748032"
+         id="path3130-3"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(72.637796,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7-56"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3132-3-2"
+       transform="translate(113.38583,63.779535)">
+      <path
+         transform="translate(47.834646,781.2992)"
+         d="m 81.496063,40.748039 c 0,22.504517 -18.243515,40.748032 -40.748031,40.748032 C 18.243515,81.496071 0,63.252556 0,40.748039 0,18.243523 18.243515,7.6293945e-6 40.748032,7.6293945e-6 63.252548,7.6293945e-6 81.496063,18.243523 81.496063,40.748039 z"
+         sodipodi:ry="40.748032"
+         sodipodi:rx="40.748032"
+         sodipodi:cy="40.748039"
+         sodipodi:cx="40.748032"
+         id="path3130-6-9"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(72.637796,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7-7-1"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3132-5-2"
+       transform="translate(389.76378,-35.433067)">
+      <path
+         transform="translate(47.834646,781.2992)"
+         d="m 81.496063,40.748039 c 0,22.504517 -18.243515,40.748032 -40.748031,40.748032 C 18.243515,81.496071 0,63.252556 0,40.748039 0,18.243523 18.243515,7.6293945e-6 40.748032,7.6293945e-6 63.252548,7.6293945e-6 81.496063,18.243523 81.496063,40.748039 z"
+         sodipodi:ry="40.748032"
+         sodipodi:rx="40.748032"
+         sodipodi:cy="40.748039"
+         sodipodi:cx="40.748032"
+         id="path3130-3-7"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(72.637796,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7-56-0"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3132-3-2-9"
+       transform="translate(389.76378,63.779535)">
+      <path
+         transform="translate(47.834646,781.2992)"
+         d="m 81.496063,40.748039 c 0,22.504517 -18.243515,40.748032 -40.748031,40.748032 C 18.243515,81.496071 0,63.252556 0,40.748039 0,18.243523 18.243515,7.6293945e-6 40.748032,7.6293945e-6 63.252548,7.6293945e-6 81.496063,18.243523 81.496063,40.748039 z"
+         sodipodi:ry="40.748032"
+         sodipodi:rx="40.748032"
+         sodipodi:cy="40.748039"
+         sodipodi:cx="40.748032"
+         id="path3130-6-9-3"
+         style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+      <path
+         transform="translate(72.637796,806.10236)"
+         d="m 31.889763,15.944888 c 0,8.806115 -7.138767,15.944882 -15.944882,15.944882 C 7.1387666,31.88977 0,24.751003 0,15.944888 0,7.1387733 7.1387666,6.6757202e-6 15.944881,6.6757202e-6 24.750996,6.6757202e-6 31.889763,7.1387733 31.889763,15.944888 z"
+         sodipodi:ry="15.944881"
+         sodipodi:rx="15.944881"
+         sodipodi:cy="15.944888"
+         sodipodi:cx="15.944881"
+         id="path3010-3-6-7-7-1-6"
+         style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g3359"
+       transform="translate(115.15748,-53.149607)">
+      <g
+         inkscape:tile-y0="242.43662"
+         inkscape:tile-x0="118.18785"
+         inkscape:tile-h="38.976379"
+         inkscape:tile-w="38.976379"
+         inkscape:tile-cy="261.92481"
+         inkscape:tile-cx="137.67604"
+         transform="translate(-19.488194,299.40945)"
+         id="g3179">
+        <path
+           sodipodi:type="arc"
+           style="color:#000000;fill:#b3b3b3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="path3177"
+           sodipodi:cx="19.48819"
+           sodipodi:cy="19.488195"
+           sodipodi:rx="19.48819"
+           sodipodi:ry="19.48819"
+           d="m 38.976379,19.488195 c 0,10.76303 -8.725159,19.48819 -19.488189,19.48819 C 8.7251597,38.976385 0,30.251225 0,19.488195 0,8.7251654 8.7251597,5.7220459e-6 19.48819,5.7220459e-6 30.25122,5.7220459e-6 38.976379,8.7251654 38.976379,19.488195 z"
+           transform="translate(0,733.46456)" />
+        <path
+           sodipodi:type="arc"
+           style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+           id="path3175"
+           sodipodi:cx="10.629921"
+           sodipodi:cy="10.629928"
+           sodipodi:rx="10.629921"
+           sodipodi:ry="10.629921"
+           d="m 21.259842,10.629928 c 0,5.870743 -4.759178,10.629921 -10.629921,10.629921 C 4.7591777,21.259849 0,16.500671 0,10.629928 0,4.7591844 4.7591777,6.6757202e-6 10.629921,6.6757202e-6 16.500664,6.6757202e-6 21.259842,4.7591844 21.259842,10.629928 z"
+           transform="translate(8.8582687,742.32283)" />
+      </g>
+      <use
+         height="318.89764"
+         width="549.21259"
+         transform="translate(4.0188832e-6,-3.4087327e-7)"
+         id="use3345"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+      <use
+         height="318.89764"
+         width="549.21259"
+         id="use3347"
+         transform="translate(53.149611,-1.3763429e-6)"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+      <use
+         height="318.89764"
+         width="549.21259"
+         id="use3349"
+         transform="translate(106.29922,-1.3763429e-6)"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+      <use
+         height="318.89764"
+         width="549.21259"
+         id="use3351"
+         transform="translate(159.44882,-1.3763429e-6)"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+      <use
+         height="318.89764"
+         width="549.21259"
+         id="use3353"
+         transform="translate(212.59843,-1.3763429e-6)"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+      <use
+         height="318.89764"
+         width="549.21259"
+         id="use3355"
+         transform="translate(265.74804,-1.3763429e-6)"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+      <use
+         height="318.89764"
+         width="549.21259"
+         id="use3357"
+         transform="translate(318.89764,-1.3763429e-6)"
+         xlink:href="#g3179"
+         inkscape:tiled-clone-of="#g3179"
+         y="0"
+         x="0" />
+    </g>
+  </g>
+</svg>

+ 63 - 0
genwts.py

@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+
+import numpy as np
+import pandas as pd
+
+def voss(nrows, ncols=16):
+    """Generates pink noise using the Voss-McCartney algorithm.
+
+    nrows: number of values to generate
+    rcols: number of random sources to add
+
+    returns: NumPy array
+    """
+    array = np.empty((nrows, ncols))
+    array.fill(np.nan)
+    array[0, :] = np.random.random(ncols)
+    array[:, 0] = np.random.random(nrows)
+
+    # the total number of changes is nrows
+    n = nrows
+    cols = np.random.geometric(0.5, n)
+    cols[cols >= ncols] = 0
+    rows = np.random.randint(nrows, size=n)
+    array[rows, cols] = np.random.random(n)
+
+    df = pd.DataFrame(array)
+    df.fillna(method='ffill', axis=0, inplace=True)
+    total = df.sum(axis=1)
+
+    return total.values
+
+def print_array(ys):
+    print '{\n%s\n}' % (',\n'.join([ ', '.join([ '0x%02x' % (y,) for y in ys[i:(i+16)] ]) for i in range(0, N, 16) ]),)
+
+N = 512
+# Sine
+xs = np.linspace(0, 2 * np.pi, N)
+ys = np.uint8(np.clip((np.sin(xs) + 1) * 255. / 2, 0, 255))
+print_array(ys)
+
+# Square
+xs = np.linspace(0, 1, N)
+ys = np.uint8([ 0 if x <= 0.5 else 255 for x in xs ])
+print_array(ys)
+
+# Triangle
+xs = np.linspace(0, 1, N)
+ys = (np.array([ 2 * x if x <= 0.5 else 2 - 2 * x for x in xs ]) * 255).astype(np.uint8)
+print_array(ys)
+
+# Pink Noise
+#fn = 64
+#xs = np.linspace(0, 1, N)
+#ys = (np.repeat(voss(fn) * 255, len(xs) / fn)).astype(np.uint8)
+
+# White Noise
+xs = np.linspace(0, 1, N)
+ys = np.random.randint(0, N, len(xs)).astype(np.uint8)
+print_array(ys)
+
+import matplotlib.pyplot as plt
+plt.plot(xs, ys)
+plt.show()

+ 196 - 0
main.c

@@ -0,0 +1,196 @@
+#define F_CPU 20000000UL
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include <avr/pgmspace.h>
+#include "wavetables.h"
+
+const uint16_t NOTE_CYCLES[108] PROGMEM = {
+	15420, 14534, 13742, 12950, 12244, 11544, 10920, 10308,  9712,
+	        9182,  8670,  8180,  7710,  7294,  6872,  6496,  6122,  5788,
+	        5460,  5154,  4868,  4592,  4336,  4090,  3864,  3648,  3442,
+	        3248,  3066,  2894,  2730,  2578,  2432,  2296,  2168,  2046,
+	        1930,  1822,  1720,  1624,  1532,  1446,  1366,  1290,  1218,
+	        1148,  1084,  1024,   966,   912,   860,   812,   768,   724,
+	         684,   646,   610,   574,   542,   512,   484,   456,   430,
+	         406,   384,   362,   342,   324,   304,   288,   272,   256,
+	         242,   228,   216,   204,   192,   182,   172,   162,   152,
+	         144,   136,   128,   122,   114,   108,   102,    96,    92,
+	          86,    82,    76,    72,    68,    64,    62,    58,    54,
+	          52,    48,    46,    44,    42,    38,    36,    34,    32
+};
+
+volatile uint8_t pwm_cycle = 0;
+
+// ISR(TIMER1_COMPB_vect)
+// {
+// }
+
+ISR(TIMER1_OVF_vect)
+{
+	++pwm_cycle;
+}
+
+typedef struct {
+	uint16_t pwm_cycle, pwm_num_cycles;
+	uint8_t wt;
+} oscillator_t;
+
+//the PCINT0_vect vector is used to identify the pin change interrupt.
+// ISR(PCINT0_vect)
+// {
+//     mute = !((PINB & (1 << PB1)));
+// }
+
+int main()
+{
+uint16_t n;
+uint8_t d, button_id = 1, line = 0, adc_timer = 0, lfo_volume = 0;
+oscillator_t vco = { 0, 0, 0 }, lfo = { 0, 0, 0 };
+
+  //OSCCAL = 83;
+
+	PLLCSR |= 0x6;
+
+	// setup output pins
+	DDRB = (1 << DDB4) | (1 << DDB2) | (1 << DDB1) | (1 << DDB0);
+
+	// set line mux pins low and turn op ADC pull-up resistor
+	PORTB = ~((1 << PB0) | (1 << PB1) | (1 << PB2)) | (1 << PB3);
+
+	// Set the ADC input to PB2/ADC1, left adjust result
+	ADMUX = (3 << MUX0) | (1 << ADLAR);
+
+	// Set the prescaler to clock/8 & enable ADC
+	ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADEN);
+
+	// Configure counter/timer1 for fast PWM on PB4
+  GTCCR = (1 << PWM1B) | (1 << COM1B1);
+
+	// Set Timer 1 prescaler to clock/1 = 64.0MHz.
+	TCCR1 = (1 << CS10);
+
+	// Interrupts on OC1A match + overflow
+  //TIMSK |= (1 << OCIE1B) | (1 << TOIE1);
+
+	// Interrupts on OC1A overflow
+	TIMSK |= (1 << TOIE1);
+	OCR1B = 0;
+	OCR1C = 255;
+
+	// GIMSK = (1 << PCIE); //Enable Pin Change Interrupts
+	// PCMSK = (1 << PCINT1); //Set Pin 2 to cause an interrupt. You can also enable it on multiple pins
+
+	ADCSRA |= (1 << ADSC);  // Start A2D Conversions
+	while (1) {
+		if(((ADCSRA >> ADSC) & 0x1) == 0) {
+			if(adc_timer == 0) {
+				d = ADCH;
+				switch(line) {
+					case 0:
+						if(button_id > 0) {
+							d /= 5;
+							switch(button_id) {
+								case 7:
+									d += 10;
+									break;
+								case 6:
+									d += 9;
+									break;
+								case 5:
+									d += 7;
+									break;
+								case 4:
+									d += 5;
+									break;
+								case 3:
+									d += 4;
+									break;
+								case 2:
+									d += 2;
+									break;
+								default:
+									break;
+							}
+							vco.pwm_num_cycles = pgm_read_word_near(NOTE_CYCLES + 21 + d);
+						}
+						//vco.pwm_num_cycles = 7812;
+						break;
+					case 1:
+						if(button_id > 0) {
+							lfo.pwm_num_cycles = 0xffff - (d << 8);
+						}
+						break;
+					case 2:
+						lfo_volume = d;
+						//lfo_volume = 127;
+						break;
+					case 3:
+						//button_id = (d < 77 ? 7 : (d > 250 ? 0 : (279 - d) / 29));
+						if(d >= 241)
+							button_id = 0;
+						else if(d >= 216)
+							button_id = 1;
+						else if(d >= 195)
+							button_id = 2;
+						else if(d >= 173)
+							button_id = 3;
+						else if(d >= 144)
+							button_id = 4;
+						else if(d >= 106)
+							button_id = 5;
+						else if(d >= 42)
+							button_id = 6;
+						else
+							button_id = 7;
+						break;
+					case 4:
+						vco.wt = d / (256 / WAVETABLES_NUM);
+						break;
+					case 6:
+						lfo.wt = d / (256 / WAVETABLES_NUM);
+						break;
+					default:
+						// nop;
+						break;
+				}
+
+				line = (line + 1) % 8;
+				PORTB = (PORTB & ~0x7) | line;
+				adc_timer = 1;
+			}
+			else if(adc_timer == 1) {
+				ADCSRA |= (1 << ADSC);  // Start A2D Conversions
+				adc_timer = 0;
+			}
+			else
+				++adc_timer;
+		}
+
+		cli();
+		n = pwm_cycle;
+		sei();
+
+		d = 0;
+
+		if(lfo_volume <= 252) {
+			vco.pwm_cycle = (vco.pwm_cycle + n) % vco.pwm_num_cycles;
+			d += (uint16_t)pgm_read_byte_near(WAVETABLES[vco.wt] + (uint16_t)(((uint32_t)(vco.pwm_cycle)) * WAVETABLES_SIZE / vco.pwm_num_cycles)) * (255 - lfo_volume) >> 8;
+		}
+
+		if(lfo_volume > 8) {
+			//n += 2;
+			lfo.pwm_cycle = (lfo.pwm_cycle + n) % lfo.pwm_num_cycles;
+			d += (uint16_t)pgm_read_byte_near(WAVETABLES[lfo.wt] + (uint16_t)(((uint32_t)(lfo.pwm_cycle)) * WAVETABLES_SIZE / lfo.pwm_num_cycles)) * lfo_volume >> 8;
+		}
+
+		cli();
+		if(button_id > 0)
+			OCR1B = d;
+		pwm_cycle -= n;
+		sei();
+	}
+
+	return 0;
+}

+ 200 - 0
main.hex

@@ -0,0 +1,200 @@
+:100000007AC489C488C487C487C485C484C483C4AB
+:1000100082C481C480C47FC47EC47DC47CC43C3C93
+:10002000C638AE359632D42F182DA82A4428F0258C
+:10003000DE23DE21F41F1E1E7E1CD81A6019EA176B
+:100040009C16541522140413F011F010FA0F180F17
+:10005000400E720DB00CFA0B4E0BAA0A120A800960
+:10006000F8087808FE078A071E07B8065806FC0538
+:10007000A60556050A05C2047C043C040004C60318
+:1000800090035C032C030003D402AC0286026202DC
+:100090003E021E020002E401C801AE019601800189
+:1000A0006A01560144013001200110010001F200F3
+:1000B000E400D800CC00C000B600AC00A20098005C
+:1000C0009000880080007A0072006C00660060007A
+:1000D0005C00560052004C004800440040003E00C6
+:1000E0003A003600340030002E002C002A00260092
+:1000F0002400220020007F8182848587888A8C8D5D
+:100100008F909293959698999B9D9EA0A1A3A4A64B
+:10011000A7A9AAACADAEB0B1B3B4B6B7B8BABBBDBF
+:10012000BEBFC1C2C3C5C6C7C9CACBCCCECFD0D152
+:10013000D2D4D5D6D7D8D9DADBDDDEDFE0E1E2E311
+:10014000E4E5E6E6E7E8E9EAEBECECEDEEEFF0F00B
+:10015000F1F2F2F3F4F4F5F5F6F7F7F8F8F9F9FA45
+:10016000FAFAFBFBFBFCFCFCFDFDFDFDFEFEFEFECA
+:10017000FEFEFEFEFEFEFEFEFEFEFEFEFEFEFEFE9F
+:10018000FDFDFDFDFDFCFCFCFBFBFBFAFAF9F9F8BB
+:10019000F8F7F7F6F6F5F5F4F3F3F2F1F1F0EFEE28
+:1001A000EEEDECEBEAEAE9E8E7E6E5E4E3E2E1E0DC
+:1001B000DFDEDDDCDBDAD9D8D6D5D4D3D2D1CFCED1
+:1001C000CDCCCAC9C8C7C5C4C3C1C0BFBDBCBBB9FB
+:1001D000B8B6B5B3B2B1AFAEACABA9A8A6A5A3A251
+:1001E000A09F9D9C9A9997969493918F8E8C8B89C2
+:1001F0008886848381807E7D7B7A78767573727041
+:100200006F6D6B6A6867656462615F5E5C5B5958BD
+:1002100056555352504F4D4C4B4948464543424129
+:100220003F3E3D3B3A39373635343231302F2D2C75
+:100230002B2A2928262524232221201F1E1D1C1B92
+:100240001A1918171615141413121110100F0E0D79
+:100250000D0C0B0B0A09090808070706060505041B
+:100260000403030302020201010101010000000076
+:10027000000000000000000000000000000000007E
+:10028000010101010202020303030404040505063F
+:100290000607070809090A0A0B0C0C0D0E0E0F10B1
+:1002A00011121213141516171818191A1B1C1D1EDB
+:1002B0001F2021232425262728292A2C2D2E2F30C4
+:1002C000323334353738393B3C3D3F404143444677
+:1002D00047484A4B4D4E505152545557585A5B5D02
+:1002E0005E606163656668696B6C6E6F717274766F
+:1002F00077797A7C7D7F000000000000000000001C
+:1003000000000000000000000000000000000000ED
+:1003100000000000000000000000000000000000DD
+:1003200000000000000000000000000000000000CD
+:1003300000000000000000000000000000000000BD
+:1003400000000000000000000000000000000000AD
+:10035000000000000000000000000000000000009D
+:10036000000000000000000000000000000000008D
+:10037000000000000000000000000000000000007D
+:10038000000000000000000000000000000000006D
+:10039000000000000000000000000000000000005D
+:1003A000000000000000000000000000000000004D
+:1003B000000000000000000000000000000000003D
+:1003C000000000000000000000000000000000002D
+:1003D000000000000000000000000000000000001D
+:1003E000000000000000000000000000000000000D
+:1003F000000000000000FFFFFFFFFFFFFFFFFFFF07
+:10040000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC
+:10041000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC
+:10042000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC
+:10043000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC
+:10044000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC
+:10045000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC
+:10046000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C
+:10047000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C
+:10048000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C
+:10049000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C
+:1004A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C
+:1004B000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C
+:1004C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C
+:1004D000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C
+:1004E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C
+:1004F000FFFFFFFFFFFF00000102030405060708DE
+:10050000090A0B0C0D0E0F101112131415161718E3
+:10051000191A1B1C1D1E1F202122232425262728D3
+:10052000292A2B2C2D2E2F303132333435363738C3
+:10053000393A3B3C3D3E3F404142434445464748B3
+:10054000494A4B4C4D4E4F505152535455565758A3
+:10055000595A5B5C5D5E5F60616263646566676893
+:10056000696A6B6C6D6E6F70717273747576777883
+:10057000797A7B7C7D7E7F80818283848586878873
+:10058000898A8B8C8D8E8F90919293949596979863
+:10059000999A9B9C9D9E9FA0A1A2A3A4A5A6A7A853
+:1005A000A9AAABACADAEAFB0B1B2B3B4B5B6B7B843
+:1005B000B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C833
+:1005C000C9CACBCCCDCECFD0D1D2D3D4D5D6D7D823
+:1005D000D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E813
+:1005E000E9EAEBECEDEEEFF0F1F2F3F4F5F6F7F803
+:1005F000F9FAFBFCFDFEFEFDFCFBFAF9F8F7F6F557
+:10060000F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E522
+:10061000E4E3E2E1E0DFDEDDDCDBDAD9D8D7D6D512
+:10062000D4D3D2D1D0CFCECDCCCBCAC9C8C7C6C502
+:10063000C4C3C2C1C0BFBEBDBCBBBAB9B8B7B6B5F2
+:10064000B4B3B2B1B0AFAEADACABAAA9A8A7A6A5E2
+:10065000A4A3A2A1A09F9E9D9C9B9A9998979695D2
+:1006600094939291908F8E8D8C8B8A8988878685C2
+:1006700084838281807F7E7D7C7B7A7978777675B2
+:1006800074737271706F6E6D6C6B6A6968676665A2
+:1006900064636261605F5E5D5C5B5A595857565592
+:1006A00054535251504F4E4D4C4B4A494847464582
+:1006B00044434241403F3E3D3C3B3A393837363572
+:1006C00034333231302F2E2D2C2B2A292827262562
+:1006D00024232221201F1E1D1C1B1A191817161552
+:1006E00014131211100F0E0D0C0B0A090807060542
+:1006F0000403020100001FC9488DCC3C2128696D0C
+:1007000073B6DD50046D5DFC383E7D44822C2A9525
+:10071000EFFD1428A635E8E679A65F36D53F39E720
+:10072000BE2F67E8987B2793A089B66DAF8D0BEF3E
+:10073000E131914752D5D859A4D81E8035FA0374B7
+:10074000E16310BF0DAAAD133AC2077041C888EC2F
+:100750006FD24ED14B319819BD0F7D533206A9BDD2
+:1007600050890974AEC2A7C0E63B9117FA248946A6
+:10077000DB7FB317FC3DE9673A3F24B6244B1EA745
+:10078000F56DCA3F356F8DE3E54ED56EF0B4E932B5
+:10079000BA54FBC514544F8D431B6656FA0D077DA2
+:1007A000821BFADE1717CCD004C9E74B8CAF44513B
+:1007B00071112FBD7C50212F389522C89696145464
+:1007C000EEB36FBB80F9AEB3A6799DA24CC61B7F7A
+:1007D00028C8479BF46CFE7C3923241F92EA19A396
+:1007E000350B41A68B5A7BEFC2C03414F654BE8938
+:1007F00094CA53B6C2B637E98F2F2276806FD14A9A
+:100800001CC8A16F4894E164DA3129652F85FE1C6C
+:10081000E264A03F90DA2C70A1D4508592E5DC0010
+:1008200068B68B9BBB41F1417AC170D1ACAC31C38E
+:100830009E7C85D5F3FA0F537A515645D6F9A160BF
+:100840001006455944D7F5EA9FFBC6FD6FC0926874
+:10085000FDB9DD6B09EEEC796224D9D934DD10E7FE
+:1008600009C660CEFBB6374C39B575C318C0FD4418
+:100870004BC5757CE43DA5C5E60762C8582719122B
+:10088000FE4971F97AE9ED8F6A8C1A4125B513E0BA
+:10089000BF0F7B626C22572C172B5F5B8AD8E0005E
+:1008A000A8D86E4B8529F0E207D1ED990FF8316B8E
+:1008B000028F9E16D6EDAF57D5358334001CBF741A
+:1008C000FA9C38417CA22C9576F02708C4EB66256B
+:1008D0008413E876A1240B920647227E4CAF276D45
+:1008E00007191A7DC61928877027978F5B36F3F48E
+:1008F00084B2035EFF6311241FBECFE5D2E0DEBFEA
+:10090000CDBF20E0A0E6B0E001C01D92A136B20745
+:10091000E1F713D0A9C174CB1F920F920FB60F92BB
+:1009200011248F93809160008F5F809360008F917E
+:100930000F900FBE0F901F901895CF93DF93CDB7F8
+:10094000DEB727970FB6F894DEBF0FBECDBF87B5D1
+:10095000866087BD87E187BB88EF88BB83E287B964
+:1009600086B1876886B980E68CBD81E080BF89B793
+:10097000846089BF1BBC8FEF8DBD369A1D82212CF0
+:10098000312CC12CD12C1C8280E090E0A12CB12C08
+:1009900010E019821A825524539466246A94712CAB
+:1009A0005B821F832C013CC0C501800F911FB201E7
+:1009B00025D15C019C81E92EF12CF701FE2FEE2759
+:1009C000FF0FDF01AA50BF4F7D01C501A0E0B0E0DD
+:1009D000BC01CD0149E0660F771F881F991F4A951A
+:1009E000D1F7920140E050E01DD1F701E20FF31F73
+:1009F0008491BF818B2E912CB3016819790990E005
+:100A0000E0D0F92EB93008F03FC0F8942B812111C5
+:100A1000FBBC809160009E81891B8093600078946C
+:100A2000369924C02981211157C085B19A8192300D
+:100A300009F487C008F456C0AA81A43009F47BC029
+:100A400008F463C0A63029F4829586958695837054
+:100A50008D83AA818A2F90E00196877099278A83D7
+:100A600098B3987F892B88BBB1E0B983F894209123
+:100A700060002E83022F10E078948F818D3F08F460
+:100A800093CFF12C882E912CC601800F911FB101BC
+:100A9000B5D06C01FD812F2F30E0322F2227330F8C
+:100AA00089010A501F4FC601A0E0B0E0BC01CD0192
+:100AB00029E0660F771F881F991F2A95D1F79101AA
+:100AC00040E050E0AFD0F801E20FF31F849190E0D6
+:100AD000B40177D0F90E99CF2130A1F0F22FFF5F4A
+:100AE000F983C4CF992379F1913009F0B2CF2B81EA
+:100AF000222309F4AECF90E0982F88271C01209480
+:100B00003094A7CF369A1982B1CF813FB0F5883D96
+:100B1000B0F5833C08F03DC08D3A08F046C08039FE
+:100B200008F046C08A3608F046C08A3208F046C04F
+:100B300087E08B838ECF82958695869583708C8394
+:100B400088CF8F8386CFBB81BB2309F482CF65E03A
+:100B500049D0E82FB43029F1A8F0FB81F630F9F044
+:100B6000D8F0F73011F4EAE0E80FF0E0EE0FFF1FE5
+:100B7000E85BFF4F459054906CCF1B826ACF91E0A9
+:100B80009B8367CFB23079F0B33079F7E4E0E80FB8
+:100B9000ECCFA2E0AB835DCFE7E0E80FE6CFE75F05
+:100BA000E4CFEB5FE2CFEE5FE0CFB3E0BB8351CFAA
+:100BB000E4E0EB834ECFF5E0FB834BCF26E02B83C5
+:100BC00048CF0024552704C0080E591F880F991FCD
+:100BD000009729F076956795B8F37105B9F7802DE0
+:100BE000952F0895991B79E004C0991F961708F076
+:100BF000961B881F7A95C9F780950895AA1BBB1B81
+:100C000051E107C0AA1FBB1FA617B70710F0A61B0C
+:100C1000B70B881F991F5A95A9F780959095BC012D
+:100C2000CD010895A1E21A2EAA1BBB1BFD010DC028
+:100C3000AA1FBB1FEE1FFF1FA217B307E407F5078C
+:100C400020F0A21BB30BE40BF50B661F771F881F68
+:100C5000991F1A9469F760957095809590959B01FE
+:0C0C6000AC01BD01CF010895F894FFCF56
+:00000001FF

+ 140 - 0
wavetables.c

@@ -0,0 +1,140 @@
+#include <avr/pgmspace.h>
+#include "wavetables.h"
+
+const uint8_t WAVETABLES[WAVETABLES_NUM][WAVETABLES_SIZE] PROGMEM = {{
+    // Sine
+    0x7f, 0x81, 0x82, 0x84, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x95, 0x96,
+    0x98, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1, 0xa3, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae,
+    0xb0, 0xb1, 0xb3, 0xb4, 0xb6, 0xb7, 0xb8, 0xba, 0xbb, 0xbd, 0xbe, 0xbf, 0xc1, 0xc2, 0xc3, 0xc5,
+    0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcc, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
+    0xd9, 0xda, 0xdb, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe6, 0xe7, 0xe8,
+    0xe9, 0xea, 0xeb, 0xec, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf0, 0xf1, 0xf2, 0xf2, 0xf3, 0xf4, 0xf4,
+    0xf5, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfc,
+    0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
+    0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfc,
+    0xfc, 0xfc, 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5,
+    0xf5, 0xf4, 0xf3, 0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xef, 0xee, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xea,
+    0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda,
+    0xd9, 0xd8, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xcf, 0xce, 0xcd, 0xcc, 0xca, 0xc9, 0xc8, 0xc7,
+    0xc5, 0xc4, 0xc3, 0xc1, 0xc0, 0xbf, 0xbd, 0xbc, 0xbb, 0xb9, 0xb8, 0xb6, 0xb5, 0xb3, 0xb2, 0xb1,
+    0xaf, 0xae, 0xac, 0xab, 0xa9, 0xa8, 0xa6, 0xa5, 0xa3, 0xa2, 0xa0, 0x9f, 0x9d, 0x9c, 0x9a, 0x99,
+    0x97, 0x96, 0x94, 0x93, 0x91, 0x8f, 0x8e, 0x8c, 0x8b, 0x89, 0x88, 0x86, 0x84, 0x83, 0x81, 0x80,
+    0x7e, 0x7d, 0x7b, 0x7a, 0x78, 0x76, 0x75, 0x73, 0x72, 0x70, 0x6f, 0x6d, 0x6b, 0x6a, 0x68, 0x67,
+    0x65, 0x64, 0x62, 0x61, 0x5f, 0x5e, 0x5c, 0x5b, 0x59, 0x58, 0x56, 0x55, 0x53, 0x52, 0x50, 0x4f,
+    0x4d, 0x4c, 0x4b, 0x49, 0x48, 0x46, 0x45, 0x43, 0x42, 0x41, 0x3f, 0x3e, 0x3d, 0x3b, 0x3a, 0x39,
+    0x37, 0x36, 0x35, 0x34, 0x32, 0x31, 0x30, 0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x26, 0x25,
+    0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15,
+    0x14, 0x14, 0x13, 0x12, 0x11, 0x10, 0x10, 0x0f, 0x0e, 0x0d, 0x0d, 0x0c, 0x0b, 0x0b, 0x0a, 0x09,
+    0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02, 0x02,
+    0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+    0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09,
+    0x0a, 0x0a, 0x0b, 0x0c, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15,
+    0x16, 0x17, 0x18, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x23, 0x24, 0x25,
+    0x26, 0x27, 0x28, 0x29, 0x2a, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x32, 0x33, 0x34, 0x35, 0x37, 0x38,
+    0x39, 0x3b, 0x3c, 0x3d, 0x3f, 0x40, 0x41, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4a, 0x4b, 0x4d, 0x4e,
+    0x50, 0x51, 0x52, 0x54, 0x55, 0x57, 0x58, 0x5a, 0x5b, 0x5d, 0x5e, 0x60, 0x61, 0x63, 0x65, 0x66,
+    0x68, 0x69, 0x6b, 0x6c, 0x6e, 0x6f, 0x71, 0x72, 0x74, 0x76, 0x77, 0x79, 0x7a, 0x7c, 0x7d, 0x7f
+  }, {
+    // Square
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+  }, {
+    // Triangle
+    0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+    0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
+    0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
+    0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e,
+    0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+    0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
+    0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
+    0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e,
+    0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
+    0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e,
+    0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae,
+    0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe,
+    0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
+    0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde,
+    0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee,
+    0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe,
+    0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef,
+    0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf,
+    0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, 0xcf,
+    0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, 0xbf,
+    0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, 0xaf,
+    0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, 0x9f,
+    0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f,
+    0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x7f,
+    0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6f,
+    0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5f,
+    0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4f,
+    0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3f,
+    0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f,
+    0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f,
+    0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f,
+    0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00
+  }, {
+    // Noise
+    0x1f, 0xc9, 0x48, 0x8d, 0xcc, 0x3c, 0x21, 0x28, 0x69, 0x6d, 0x73, 0xb6, 0xdd, 0x50, 0x04, 0x6d,
+    0x5d, 0xfc, 0x38, 0x3e, 0x7d, 0x44, 0x82, 0x2c, 0x2a, 0x95, 0xef, 0xfd, 0x14, 0x28, 0xa6, 0x35,
+    0xe8, 0xe6, 0x79, 0xa6, 0x5f, 0x36, 0xd5, 0x3f, 0x39, 0xe7, 0xbe, 0x2f, 0x67, 0xe8, 0x98, 0x7b,
+    0x27, 0x93, 0xa0, 0x89, 0xb6, 0x6d, 0xaf, 0x8d, 0x0b, 0xef, 0xe1, 0x31, 0x91, 0x47, 0x52, 0xd5,
+    0xd8, 0x59, 0xa4, 0xd8, 0x1e, 0x80, 0x35, 0xfa, 0x03, 0x74, 0xe1, 0x63, 0x10, 0xbf, 0x0d, 0xaa,
+    0xad, 0x13, 0x3a, 0xc2, 0x07, 0x70, 0x41, 0xc8, 0x88, 0xec, 0x6f, 0xd2, 0x4e, 0xd1, 0x4b, 0x31,
+    0x98, 0x19, 0xbd, 0x0f, 0x7d, 0x53, 0x32, 0x06, 0xa9, 0xbd, 0x50, 0x89, 0x09, 0x74, 0xae, 0xc2,
+    0xa7, 0xc0, 0xe6, 0x3b, 0x91, 0x17, 0xfa, 0x24, 0x89, 0x46, 0xdb, 0x7f, 0xb3, 0x17, 0xfc, 0x3d,
+    0xe9, 0x67, 0x3a, 0x3f, 0x24, 0xb6, 0x24, 0x4b, 0x1e, 0xa7, 0xf5, 0x6d, 0xca, 0x3f, 0x35, 0x6f,
+    0x8d, 0xe3, 0xe5, 0x4e, 0xd5, 0x6e, 0xf0, 0xb4, 0xe9, 0x32, 0xba, 0x54, 0xfb, 0xc5, 0x14, 0x54,
+    0x4f, 0x8d, 0x43, 0x1b, 0x66, 0x56, 0xfa, 0x0d, 0x07, 0x7d, 0x82, 0x1b, 0xfa, 0xde, 0x17, 0x17,
+    0xcc, 0xd0, 0x04, 0xc9, 0xe7, 0x4b, 0x8c, 0xaf, 0x44, 0x51, 0x71, 0x11, 0x2f, 0xbd, 0x7c, 0x50,
+    0x21, 0x2f, 0x38, 0x95, 0x22, 0xc8, 0x96, 0x96, 0x14, 0x54, 0xee, 0xb3, 0x6f, 0xbb, 0x80, 0xf9,
+    0xae, 0xb3, 0xa6, 0x79, 0x9d, 0xa2, 0x4c, 0xc6, 0x1b, 0x7f, 0x28, 0xc8, 0x47, 0x9b, 0xf4, 0x6c,
+    0xfe, 0x7c, 0x39, 0x23, 0x24, 0x1f, 0x92, 0xea, 0x19, 0xa3, 0x35, 0x0b, 0x41, 0xa6, 0x8b, 0x5a,
+    0x7b, 0xef, 0xc2, 0xc0, 0x34, 0x14, 0xf6, 0x54, 0xbe, 0x89, 0x94, 0xca, 0x53, 0xb6, 0xc2, 0xb6,
+    0x37, 0xe9, 0x8f, 0x2f, 0x22, 0x76, 0x80, 0x6f, 0xd1, 0x4a, 0x1c, 0xc8, 0xa1, 0x6f, 0x48, 0x94,
+    0xe1, 0x64, 0xda, 0x31, 0x29, 0x65, 0x2f, 0x85, 0xfe, 0x1c, 0xe2, 0x64, 0xa0, 0x3f, 0x90, 0xda,
+    0x2c, 0x70, 0xa1, 0xd4, 0x50, 0x85, 0x92, 0xe5, 0xdc, 0x00, 0x68, 0xb6, 0x8b, 0x9b, 0xbb, 0x41,
+    0xf1, 0x41, 0x7a, 0xc1, 0x70, 0xd1, 0xac, 0xac, 0x31, 0xc3, 0x9e, 0x7c, 0x85, 0xd5, 0xf3, 0xfa,
+    0x0f, 0x53, 0x7a, 0x51, 0x56, 0x45, 0xd6, 0xf9, 0xa1, 0x60, 0x10, 0x06, 0x45, 0x59, 0x44, 0xd7,
+    0xf5, 0xea, 0x9f, 0xfb, 0xc6, 0xfd, 0x6f, 0xc0, 0x92, 0x68, 0xfd, 0xb9, 0xdd, 0x6b, 0x09, 0xee,
+    0xec, 0x79, 0x62, 0x24, 0xd9, 0xd9, 0x34, 0xdd, 0x10, 0xe7, 0x09, 0xc6, 0x60, 0xce, 0xfb, 0xb6,
+    0x37, 0x4c, 0x39, 0xb5, 0x75, 0xc3, 0x18, 0xc0, 0xfd, 0x44, 0x4b, 0xc5, 0x75, 0x7c, 0xe4, 0x3d,
+    0xa5, 0xc5, 0xe6, 0x07, 0x62, 0xc8, 0x58, 0x27, 0x19, 0x12, 0xfe, 0x49, 0x71, 0xf9, 0x7a, 0xe9,
+    0xed, 0x8f, 0x6a, 0x8c, 0x1a, 0x41, 0x25, 0xb5, 0x13, 0xe0, 0xbf, 0x0f, 0x7b, 0x62, 0x6c, 0x22,
+    0x57, 0x2c, 0x17, 0x2b, 0x5f, 0x5b, 0x8a, 0xd8, 0xe0, 0x00, 0xa8, 0xd8, 0x6e, 0x4b, 0x85, 0x29,
+    0xf0, 0xe2, 0x07, 0xd1, 0xed, 0x99, 0x0f, 0xf8, 0x31, 0x6b, 0x02, 0x8f, 0x9e, 0x16, 0xd6, 0xed,
+    0xaf, 0x57, 0xd5, 0x35, 0x83, 0x34, 0x00, 0x1c, 0xbf, 0x74, 0xfa, 0x9c, 0x38, 0x41, 0x7c, 0xa2,
+    0x2c, 0x95, 0x76, 0xf0, 0x27, 0x08, 0xc4, 0xeb, 0x66, 0x25, 0x84, 0x13, 0xe8, 0x76, 0xa1, 0x24,
+    0x0b, 0x92, 0x06, 0x47, 0x22, 0x7e, 0x4c, 0xaf, 0x27, 0x6d, 0x07, 0x19, 0x1a, 0x7d, 0xc6, 0x19,
+    0x28, 0x87, 0x70, 0x27, 0x97, 0x8f, 0x5b, 0x36, 0xf3, 0xf4, 0x84, 0xb2, 0x03, 0x5e, 0xff, 0x63
+}};

+ 11 - 0
wavetables.h

@@ -0,0 +1,11 @@
+#ifndef WAVETABLES_H
+#define WAVETABLES_H
+
+#include <stdint.h>
+
+#define WAVETABLES_NUM 4
+#define WAVETABLES_SIZE 512
+
+extern const uint8_t WAVETABLES[WAVETABLES_NUM][WAVETABLES_SIZE];
+
+#endif // WAVETABLES_H