Convert articles to skribe format.
authorrekado <>
Sun, 16 Aug 2015 03:15:04 +0000 (05:15 +0200)
committerrekado <>
Mon, 17 Aug 2015 20:56:02 +0000 (22:56 +0200)
68 files changed:
non-posts/index.skr [new file with mode: 0644]
non-posts/lv2/mdaepiano/index.skr [new file with mode: 0644]
non-posts/lv2/mdapiano/index.skr [new file with mode: 0644]
non-posts/projects.skr [new file with mode: 0644]
non-posts/wavedrum/index.skr [new file with mode: 0644]
posts/2009-07-01-chapman_stick.markdown [deleted file]
posts/2009-07-01-chapman_stick.skr [new file with mode: 0644]
posts/2010-03-23-fur-man.markdown [deleted file]
posts/2010-03-23-fur-man.skr [new file with mode: 0644]
posts/2010-03-26-billie-jean.markdown [deleted file]
posts/2010-03-26-billie-jean.skr [new file with mode: 0644]
posts/2010-03-26-rehearsals.markdown [deleted file]
posts/2010-03-26-rehearsals.skr [new file with mode: 0644]
posts/2010-03-26-youku-niuren.markdown [deleted file]
posts/2010-03-26-youku-niuren.skr [new file with mode: 0644]
posts/2010-03-26-youku-vs-tudou-final.markdown [deleted file]
posts/2010-03-26-youku-vs-tudou-final.skr [new file with mode: 0644]
posts/2010-03-28-elephly.markdown [deleted file]
posts/2010-03-28-elephly.skr [new file with mode: 0644]
posts/2010-04-05-deng-hou.markdown [deleted file]
posts/2010-04-05-deng-hou.skr [new file with mode: 0644]
posts/2010-04-12-jiatingyanboshi.markdown [deleted file]
posts/2010-04-12-jiatingyanboshi.skr [new file with mode: 0644]
posts/2010-06-01-chapman-stick-on-national-tv.markdown [deleted file]
posts/2010-06-01-chapman-stick-on-national-tv.skr [new file with mode: 0644]
posts/2010-06-24-2010-niuren.markdown [deleted file]
posts/2010-06-24-2010-niuren.skr [new file with mode: 0644]
posts/2010-07-02-newspaper.markdown [deleted file]
posts/2010-07-02-newspaper.skr [new file with mode: 0644]
posts/2010-07-08-wishful-thinking.markdown [deleted file]
posts/2010-07-08-wishful-thinking.skr [new file with mode: 0644]
posts/2010-07-14-one-night-in-beijing.markdown [deleted file]
posts/2010-07-14-one-night-in-beijing.skr [new file with mode: 0644]
posts/2010-08-04-alto-stick.markdown [deleted file]
posts/2010-08-04-alto-stick.skr [new file with mode: 0644]
posts/2010-08-15-yueyintang.markdown [deleted file]
posts/2010-08-15-yueyintang.skr [new file with mode: 0644]
posts/2010-08-17-tianshi.markdown [deleted file]
posts/2010-08-17-tianshi.skr [new file with mode: 0644]
posts/2010-10-14-chinese-tune-mda-epiano.markdown [deleted file]
posts/2010-10-14-chinese-tune-mda-epiano.skr [new file with mode: 0644]
posts/2012-01-25-new-blog.markdown [deleted file]
posts/2012-01-25-new-blog.skr [new file with mode: 0644]
posts/2013-01-27-preamp-board-arrived.markdown [deleted file]
posts/2013-01-27-preamp-board-arrived.skr [new file with mode: 0644]
posts/2013-05-24-improvisation.markdown [deleted file]
posts/2013-05-24-improvisation.skr [new file with mode: 0644]
posts/2013-08-11-hacking-the-wavedrum.markdown [deleted file]
posts/2013-08-11-hacking-the-wavedrum.skr [new file with mode: 0644]
posts/2013-10-01-dm-crypt.markdown [deleted file]
posts/2013-10-01-dm-crypt.skr [new file with mode: 0644]
posts/2013-10-31-wavedrum-data-comparison.markdown [deleted file]
posts/2013-10-31-wavedrum-data-comparison.skr [new file with mode: 0644]
posts/2013-12-09-wavedrum-connectors.markdown [deleted file]
posts/2013-12-09-wavedrum-connectors.skr [new file with mode: 0644]
posts/2014-09-18-wavedrum-firmware-disassembler.markdown [deleted file]
posts/2014-09-18-wavedrum-firmware-disassembler.skr [new file with mode: 0644]
posts/2014-11-23-upgrading-trulyergonomic-firmware.markdown [deleted file]
posts/2014-11-23-upgrading-trulyergonomic-firmware.skr [new file with mode: 0644]
posts/2015-04-17-gnu-guix.markdown [deleted file]
posts/2015-04-17-gnu-guix.skr [new file with mode: 0644]
posts/2015-06-21-getting-started-with-guix.markdown [deleted file]
posts/2015-06-21-getting-started-with-guix.skr [new file with mode: 0644]
static/index.markdown [deleted file]
static/lv2/mdaepiano.markdown [deleted file]
static/lv2/mdapiano.markdown [deleted file]
static/projects.markdown [deleted file]
static/wavedrum/index.markdown [deleted file]

diff --git a/non-posts/index.skr b/non-posts/index.skr
new file mode 100644 (file)
index 0000000..718bf46
--- /dev/null
@@ -0,0 +1,65 @@
+(define meta
+  `((title . "Free software and music")))
+ (h1 [Free software and music])
+ (p [My name is rekado and I’m currently working as a programmer and
+     ,(ref "" "GNU/Linux") server administrator.  I
+     enjoy writing ,(ref
+     "" "Free
+     Software").  You can find some of ,(ref ""
+     "my code here") or on ,(ref "" "Github").
+     At night I’m a musician.  I play the ,(ref ""
+     "Chapman Stick").  Some of my recordings and performances can be
+     found on ,(ref "" "SoundCloud") or on
+     ,(ref ""
+     "Youku").])
+ (p [You can contact me via email at ,(email "").
+     Please use ,(ref "/rekado.pubkey" "my public key") when writing
+     me email.  If you don’t know much about encrypting email, please
+     take a look at the ,(ref ""
+     "email self-defense website") by the ,(ref "" "Free
+     Software Foundation").])
+ `(h2 ,(ref "/posts" "Blog")
+      (a (@ (href "feed.xml"))
+         (img (@ (class "feed-icon")
+                 (src "/images/feed.png")
+                 (alt "subscribe to atom feed")))))
+ (p [On occasion I write articles.  Here’s the ,(ref
+     "/posts/latest.html" "latest article").  I recommend the series
+     of posts on ,(ref "/tags/wavedrum.html" "hacking the
+     Wavedrum").])
+ (h2 [,(ref "/projects.html" "Projects")])
+ (ul
+  (li [,(ref "/wavedrum/index.html" "Wavedrum stuff")])
+  (li [I was one of the founding members of
+       ,(ref "" "Libertree") and wrote lots of
+       code for it.  I have since stopped contributing, but Pistos
+       continues to work on Libertree.])
+  (li [,(ref "/soundcli.html" "SoundCLI"), a command line interface
+       for streaming music from SoundCloud.])
+  (li [I ported some VST instruments (,(ref "/lv2/mdapiano/index.html"
+       "mda Piano") and ,(ref "/lv2/mdaepiano/index.html" "mda
+       EPiano")) to the LV2 plugin framework.]))
+ (h2 [Ecology])
+ (p [Currently (with some interruptions), I’m studying toward a
+     Bachelor of Applied Science via distance learning at the ,(ref
+     "" "Open Polytechnic").  Some of
+     my ,(ref "/ecology.html" "writings on ecology can be found in
+     this section").])
+ (h2 [Weird stuff])
+ (ul
+  (li [,(ref "/elephly.html" "The Elephly")])
+  (li [,(ref "/fur-man.html" "Fur man")])))
diff --git a/non-posts/lv2/mdaepiano/index.skr b/non-posts/lv2/mdaepiano/index.skr
new file mode 100644 (file)
index 0000000..78bcaf4
--- /dev/null
@@ -0,0 +1,73 @@
+(define meta
+  `((title . "LV2 plugin: mda EPiano")))
+ (h1 [mda EPiano])
+ (p [This is an LV2 port of the mda EPiano VSTi (not to be confused
+     with the ,(ref "/lv2/mdapiano/" "mda Piano")).  The original
+     VST that this port is based on was written by Paul Kellett.])
+ (p [The original ,(ref "/posts/2010-10-14-chinese-tune-mda-epiano.html"
+     "announcement post can be found here").])
+ (h2 [Compiling])
+ (p [To compile the mda EPiano plugin, just execute the following
+     statement:])
+ (p (pre (code
+          [make TYPE=mdaEPiano
+sudo make install TYPE=mdaEPiano])))
+ (p [This will copy the compiled plugin to ,(code
+     [/usr/local/lib/lv2]).  To change the target prefix, pass the
+     ,(code [PREFIX]) variable to ,(code [make]).])
+ (p [To build the ,(ref "/lv2/mdapiano/" "mda Piano plugin")
+     instead, pass ,(code [TYPE=mdaPiano]) to ,(code [make]):])
+ (p (pre (code
+          [make TYPE=mdaPiano
+sudo make install TYPE=mdaPiano])))
+ (p [,(strong [NOTE]): you will need the ,(ref ""
+     "lvtoolkit libraries") to compile this plugin.])
+ (h2 [Connecting])
+ (p [You will need an LV2 host to use the plugin.  I’m using ,(code
+     [jalv.gtk]):])
+ (p (pre (code [jalv.gtk])))
+ (p [You should now be able to connect your MIDI device to the plugin
+     via JACK.  Also don’t forget to connect the plugin’s stereo output
+     to your system’s outputs:])
+ (p (pre (code
+          [jack_connect system:playback_1 mdaEPiano:left
+jack_connect system:playback_2 mdaEPiano:right])))
+ (p [I provide a simple connect script with the code which does these
+     things automatically.])
+ (h2 [License])
+ (p [The original mda VST plug-ins by Paul Kellett are released under
+     the MIT license or under the GPL ,(em [“either version 2 of the
+     License, or (at your option) any later version”]).  The LV2 ports
+     of the mdaPiano and mdaEPiano plugins by rekado are released
+     under GPLv3, or (at your option) any later version.])
+ (h2 [Download])
+ (p [,(ref ""
+           "Fetch the source here").
+     The latest
+     ,(ref ""
+           "release tarball can be downloaded here").]))
diff --git a/non-posts/lv2/mdapiano/index.skr b/non-posts/lv2/mdapiano/index.skr
new file mode 100644 (file)
index 0000000..4509701
--- /dev/null
@@ -0,0 +1,70 @@
+(define meta
+  `((title . "LV2 plugin: mda Piano")))
+ (h1 [mda Piano])
+ (p [This is an LV2 port of the mda Piano VSTi (not to be confused
+     with the ,(ref "/lv2/mdaepiano/" "mda EPiano")).  The original
+     VST that this port is based on was written by Paul Kellett.])
+ (h2 [Compiling])
+ (p [To compile the mda Piano plugin, just execute the following
+     statement:])
+ (p (pre (code
+          [make TYPE=mdaPiano
+sudo make install TYPE=mdaPiano])))
+ (p [This will copy the compiled plugin to ,(code
+     [/usr/local/lib/lv2]).  To change the target prefix, pass the
+     ,(code [PREFIX]) variable to ,(code [make]).])
+ (p [To build the ,(ref "/lv2/mdaepiano/" "mda EPiano plugin")
+     instead, pass ,(code [TYPE=mdaEPiano]) to ,(code [make]):])
+ (p (pre (code
+          [make TYPE=mdaEPiano
+sudo make install TYPE=mdaEPiano])))
+ (p [,(strong [NOTE]): you will need the ,(ref ""
+     "lvtoolkit libraries") to compile this plugin.])
+ (h2 [Connecting])
+ (p [You will need an LV2 host to use the plugin.  I’m using ,(code
+     [jalv.gtk]):])
+ (p (pre (code [jalv.gtk])))
+ (p [You should now be able to connect your MIDI device to the plugin
+     via JACK.  Also don’t forget to connect the plugin’s stereo output
+     to your system’s outputs:])
+ (p (pre (code
+          [jack_connect system:playback_1 mdaPiano:left
+jack_connect system:playback_2 mdaPiano:right])))
+ (p [I provide a simple connect script with the code which does these
+     things automatically.])
+ (h2 [License])
+ (p [The original mda VST plug-ins by Paul Kellett are released under
+     the MIT license or under the GPL ,(em [“either version 2 of the
+     License, or (at your option) any later version”]).  The LV2 ports
+     of the mdaPiano and mdaEPiano plugins by rekado are released
+     under GPLv3, or (at your option) any later version.])
+ (h2 [Download])
+ (p [,(ref ""
+           "Fetch the source here").
+     The latest
+     ,(ref ""
+           "release tarball can be downloaded here").]))
diff --git a/non-posts/projects.skr b/non-posts/projects.skr
new file mode 100644 (file)
index 0000000..5468f8e
--- /dev/null
@@ -0,0 +1,70 @@
+(define meta
+  `((title . "Projects")))
+ (h1 [Projects])
+ (p [Here is a list of some of the projects that I’m involved with that
+     actually might be useful to others.])
+ (h2 [Hacking the Wavedrum])
+ (p [I wrote a ,(ref "/tags/wavedrum.html" "series of blog posts") in
+     which I document my efforts to understand and possibly manipulate
+     the firmware of Korg’s Wavedrum.  The PCB is easily accessible
+     and exposes big connector pads as well as a microSD card—an
+     invitation to play with the hardware.])
+ (p [The ,(ref "/wavedrum/index.html" "project page") is the best
+     place to get an overview and to see the current status.  It
+     contains links to the sources of any software artifacts I create
+     in the process.])
+ (h2 [GNU Guix])
+ (p [,(ref "" "GNU Guix") is a novel package
+     manager for ,(ref "" "GNU systems").  In Guix a
+     package is treated as a pure function whose output is fully
+     described by its inputs (its dependencies).  I’m packaging lots
+     of bioinformatics software when I’m in the office and audio tools
+     when I’m off work.])
+ (p [The Guix package manager forms the foundation of the Guix System
+     Distribution (short: GuixSD), which is the GNU system I use on my
+     laptop.])
+ (h2 [Libertree])
+ (p [,(ref "" "Libertree") is a collection of
+     software to build social networks.  The core components include a
+     web frontend application and an XMPP backend component that will
+     work with any regular XMPP server.])
+ (figure "/images/libertree-logo.png" "The Libertree logo")
+ (p [I was one of two core developers for about three years and hosted
+     the second public node.  The network isn’t very active and
+     development has slowed considerably.  I’m no longer interested in
+     traditional www-based social networking applications and am
+     thinking about using ,(ref "" "Gnunet") for
+     pseudonymous social networking purposes.])
+ (h2 [SoundCLI])
+ (p [,(ref "/soundcli.html" "SoundCLI") is a SoundCloud client for the
+     console.  Check out the ,(ref "/soundcli.html" "project page")
+     for more information.])
+ (h2 [LV2 plugins])
+ (p [I have ported two VST instruments to the LV2 plugin framework,
+     because I missed them after my move to GNU/Linux.])
+ (ul
+  (li (ref "/lv2/mdaepiano/index.html" "mda EPiano"))
+  (li (ref "/lv2/mdapiano/index.html" "mda Piano"))))
diff --git a/non-posts/wavedrum/index.skr b/non-posts/wavedrum/index.skr
new file mode 100644 (file)
index 0000000..91ccdc1
--- /dev/null
@@ -0,0 +1,59 @@
+(define meta
+  `((title . "Wavedrum")))
+ (h1 [Wavedrum])
+ (p [I wrote a ,(ref "/tags/wavedrum.html" "series of blog posts") in
+     which I document my efforts to understand and possibly manipulate
+     the firmware of Korg’s Wavedrum.  The PCB is easily accessible
+     and exposes big connector pads as well as a microSD card—an
+     invitation to play with the hardware.])
+ (p [Although I’m perfectly content just playing with the hardware, I
+     do hope that my work will eventually allow me and others to
+     modify the data on the Wavedrum such that custom sounds and loops
+     (and possibly algorithms) can be used.])
+ (h2 [Current status])
+ (p [It is possible to load firmware from the microSD card by pressing
+     ,(em [Write]) and ,(em [1]) while powering on the Wavedrum,
+     followed by pressing ,(em [Write]) again (another undocumented
+     mode can be entered by pressing ,(em [Write]) and ,(em [Mode])
+     while powering on).])
+ (p [The Wavedrum unfortunately rejects any modified firmware.  The
+     Oriental edition will not load the firmware of the Original/Black
+     edition, nor will it load the firmware of the Global edition.  It
+     also won’t load any modified firmware (e.g. where the only
+     difference is that two bytes are swapped).  I intend to figure
+     out how the Wavedrum validates the data on the SD card before
+     deciding to reject them.])
+ (h2 [Blog posts])
+ (ul
+   (li (ref "/posts/2013-08-11-hacking-the-wavedrum.html"
+            "Hacking the Wavedrum"))
+   (li (ref "/posts/2013-10-31-wavedrum-data-comparison.html"
+            "Firmware comparison between Wavedrums Original, Black and Oriental"))
+   (li (ref "/posts/2013-12-09-wavedrum-connectors.html"
+            "Connectors on the Wavedrum’s circuit board"))
+   (li (ref "/posts/2014-09-18-wavedrum-firmware-disassembler.html"
+            "Disassembling the Wavedrum firmware")))
+ (h2 [Software])
+ (dl
+   (dt (ref ""
+            "wavedrum-lib"))
+   (dd [Haskell library for parsing, editing, and writing Wavedrum programmes (presets).])
+   (dt (ref ""
+            "sharc-disassembler"))
+   (dd [Very rudimentary, partial disassembler for SHARC ADSP binaries
+        helping me to understand the Wavedrum’s bootloader.])))
diff --git a/posts/2009-07-01-chapman_stick.markdown b/posts/2009-07-01-chapman_stick.markdown
deleted file mode 100644 (file)
index d576b92..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-title: The Chapman Stick®
-date: 2009/07/01
-tags: music, chapman stick
-The [Chapman Stick]( is a stringed instrument invented quite
-some time ago by [Emmett Chapman]( It is a blank
-slate equipped with a grid-like touchboard, two groups of stings and a powerful
-pickup allowing the player to tap notes rather than requiring fretting and
-![Grand Stick after arrival in Shanghai](/images/posts/stick.jpg)
-I usually describe the Stick as being a guitar and a bass unified on one
-fretboard, though I think that it is much more than that. It rather combines
-the advantages of a piano over a traditionally stringed instument---such as
-tonal range---with the advantages of the fretted instruments, i.e. direct fine
-control over the sound through plain fingers on strings. More than that, it
-even expands on these concepts and brings a number of [improvements and innovations](
-Check out the [official website]( to read more about what sets
-apart the Stick from other tapping instruments.
-There's a documentary about Emmett and the Stick story in the make. You can
-[see the trailer here](
-I've received my first Stick---a 12-stringed Grand---in July 2009 and have just
-placed my order for an Alto Stick made from Indonesian Rosewood.
diff --git a/posts/2009-07-01-chapman_stick.skr b/posts/2009-07-01-chapman_stick.skr
new file mode 100644 (file)
index 0000000..119b941
--- /dev/null
@@ -0,0 +1,36 @@
+(define meta
+  `((title . "The Chapman Stick®")
+    (date  . ,(string->date* "2009-07-01 00:00"))
+    (tags "music" "chapman stick")))
+ (p [The ,(ref "" [Chapman Stick]) is a stringed
+     instrument invented quite some time ago by ,(ref
+     "" [Emmett Chapman]).  It is a
+     blank slate equipped with a grid-like touchboard, two groups of
+     stings and a powerful pickup allowing the player to tap notes
+     rather than requiring fretting and strumming.])
+ (figure "stick.jpg" "Grand Stick after arrival in Shanghai")
+ (p [I usually describe the Stick as being a guitar and a bass
+     unified on one fretboard, though I think that it is much more
+     than that.  It rather combines the advantages of a piano over a
+     traditionally stringed instument—such as tonal range—with the
+     advantages of the fretted instruments, i.e. direct fine control
+     over the sound through plain fingers on strings.  More than
+     that, it even expands on these concepts and brings a number of
+     ,(ref ""
+     [improvements and innovations]).])
+ (p [Check out the ,(ref "" [official website]) to
+     read more about what sets apart the Stick from other tapping
+     instruments.])
+ (p [There’s a documentary about Emmett and the Stick story in the
+     make.  You can ,(ref "" [see
+     the trailer here]).])
+ (p [I’ve received my first Stick—a 12-stringed Grand—in July 2009
+     and have just placed my order for an Alto Stick made from
+     Indonesian Rosewood.]))
diff --git a/posts/2010-03-23-fur-man.markdown b/posts/2010-03-23-fur-man.markdown
deleted file mode 100644 (file)
index cf245ed..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-title: Fur Man
-date: 2010/03/23
-tags: drawing, weird
-license: by-sa
-The Fur Man is an obese mammal, who lives most of his miserable lifetime in
-utter solitude. The reasons for that are rather obvious.
-So far there has only been one sighting of the sickening Fur Man (on March 23,
-2010). Some have suggested there might be only a single specimen existing on
-earth, though this claim is disputed.
-<a href='/downies/fur-man.png' title='click to see super-large version'>
-  <img class='full' src='/images/posts/fur-man.png' alt='artist rendering of the sickening Fur Man'/>
-The Fur Man was sighted hiding behind a plant in an office building in Shanghai.
-<img class='full' src='/images/posts/fur-man-white-board.jpg' alt='Fur Man sighting'/>
diff --git a/posts/2010-03-23-fur-man.skr b/posts/2010-03-23-fur-man.skr
new file mode 100644 (file)
index 0000000..15273f4
--- /dev/null
@@ -0,0 +1,27 @@
+(define meta
+  `((title   . "Fur Man")
+    (date    . ,(string->date* "2010-03-23 00:00"))
+    (license . "by-sa")
+    (tags "drawing" "weird")))
+ (p [The Fur Man is an obese mammal, who lives most of his miserable
+     lifetime in utter solitude.  The reasons for that are rather
+     obvious.])
+ (p [So far there has only been one sighting of the sickening Fur Man
+     (on March 23, 2010).  Some have suggested there might be only a
+     single specimen existing on earth, though this claim is
+     disputed.])
+ '(a (@ (href "/downies/fur-man.png")
+        (title "click to see super-large version"))
+     (img (@ (class "full")
+             (src "/images/posts/fur-man.png")
+             (alt "artist rendering of the sickening Fur Man"))))
+ (p [,(strong [Update:]) The Fur Man was sighted hiding behind a plant
+     in an office building in Shanghai.])
+ (wide-img "fur-man-white-board.jpg"
+           "Fur Man sighting"))
diff --git a/posts/2010-03-26-billie-jean.markdown b/posts/2010-03-26-billie-jean.markdown
deleted file mode 100644 (file)
index 9d3901f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-title: Billie Jean
-date: 2010/03/26
-tags: video, music
-![Playing Billie Jean on the Stick](/images/posts/billiejean.png)
-[This video]( was recorded some
-time in December 2009. I had just learned how to [tap with both hands on the
-Chapman Stick](/posts/2009-07-01-chapman_stick.html) when I was contacted by
-representatives of the Chinese video portal []( They
-asked me to provide them with a quick video of myself showing off the peculiar
-instrument I told them I had just learned to play.
-Later the video was to be tacked on to [footage that was recorded some days
-earlier with the Youku team](
-All together this was supposed to be my entry for the voting to join the show
-全家都来赛 (the official English name is the silly *"Super Family"*).
-As the show's purpose is to present talented families, I asked Jackie to play
-the drums while I would cover bass, chords and vocals of Michael Jackson's
-*Billie Jean*. The result [can be seen
diff --git a/posts/2010-03-26-billie-jean.skr b/posts/2010-03-26-billie-jean.skr
new file mode 100644 (file)
index 0000000..3c20155
--- /dev/null
@@ -0,0 +1,30 @@
+(define meta
+  `((title . "Billie Jean")
+    (date . ,(string->date* "2010-03-26 00:00"))
+    (tags "video" "music")))
+ (figure "billiejean.png" "Playing Billie Jean on the Stick")
+ (p [,(ref "" "This
+     video") was recorded some time in December 2009. I had just
+     learned how to ,(ref "/posts/2009-07-01-chapman_stick.html" "tap
+     with both hands on the Chapman Stick") when I was contacted by
+     representatives of the Chinese video portal ,(ref
+     "" ""). They asked me to provide them
+     with a quick video of myself showing off the peculiar instrument I
+     told them I had just learned to play.])
+ (p [Later the video was to be tacked on to ,(ref
+     "" "footage that
+     was recorded some days earlier with the Youku team").  All
+     together this was supposed to be my entry for the voting to join
+     the show 全家都来赛 (the official English name is the silly ,(em
+     [“Super Family”])).])
+ (p [As the show’s purpose is to present ‘talented families’, I asked
+     Jackie to play the drums while I would cover bass, chords and
+     vocals of Michael Jackson’s ,(em [Billie Jean]).  The result
+     ,(ref "" "can be
+     seen here").]))
diff --git a/posts/2010-03-26-rehearsals.markdown b/posts/2010-03-26-rehearsals.markdown
deleted file mode 100644 (file)
index d6b3c51..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-title: Rehearsals
-date: 2010/03/26
-tags: music, chapman stick, video, tv, quan jia dou lai sai
-type: short
-photo: rehearsals.jpg
-[This video]( was shot by the
-friendly youku team during the rehearsals for the live broadcast of Quan Jia
-Dou Lai Sai.
-Thanks to youku for their support!
diff --git a/posts/2010-03-26-rehearsals.skr b/posts/2010-03-26-rehearsals.skr
new file mode 100644 (file)
index 0000000..82e55c4
--- /dev/null
@@ -0,0 +1,13 @@
+(define meta
+  `((title . "Rehearsals")
+    (date  . ,(string->date* "2010-03-26 00:00"))
+    (tags "music" "chapman stick" "video" "tv" "quan jia dou lai sai")
+    (type  . "short")
+    (photo . "rehearsals.jpg")))
+ (p [,(ref "" "This
+    video") was shot by the friendly youku team during the rehearsals
+    for the live broadcast of Quan Jia Dou Lai Sai.])
+ (p [Thanks to Youku for their support!]))
diff --git a/posts/2010-03-26-youku-niuren.markdown b/posts/2010-03-26-youku-niuren.markdown
deleted file mode 100644 (file)
index 18887e5..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-title: 2009 Youku Niuren
-date: 2010/03/26
-tags: tv, youku, video, quan jia dou lai sai
-photo: niuren.jpg
-type: short
-On January 23, 2010 Jackie and I attended the annual Niuren show hosted by
-youku. We were handed a cheap plastic board, symbolizing entry into Quan Jia
-Dou Lai Sai. Here's a [video of the
diff --git a/posts/2010-03-26-youku-niuren.skr b/posts/2010-03-26-youku-niuren.skr
new file mode 100644 (file)
index 0000000..b64dc63
--- /dev/null
@@ -0,0 +1,13 @@
+(define meta
+  `((title . "2009 Youku Niuren")
+    (date  . ,(string->date* "2010-03-26 00:00"))
+    (photo . "niuren.jpg")
+    (type  . "short")
+    (tags "tv" "youku" "video" "quan jia dou lai sai")))
+ (p [On January 23, 2010 Jackie and I attended the annual Niuren show
+     hosted by Youku.  We were handed a cheap plastic board,
+     symbolizing entry into ,(em [Quan Jia Dou Lai Sai]).  Here’s a
+     ,(ref "" "video of
+     the ceremony").]))
diff --git a/posts/2010-03-26-youku-vs-tudou-final.markdown b/posts/2010-03-26-youku-vs-tudou-final.markdown
deleted file mode 100644 (file)
index 6798698..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-title: Youku vs. Tudou&mdash;Final
-date: 2010/03/26
-tags: tv, youku, quan jia dou lai sai
-type: short
-photo: 2010-02-10-qiutianbuhuilai.jpg
-Here is a [full recording of the live
-broadcast]( on Wednesday,
-thanks to Youku! Some timestamps for all the impatient: 24:24, 53:50, 111:00.
diff --git a/posts/2010-03-26-youku-vs-tudou-final.skr b/posts/2010-03-26-youku-vs-tudou-final.skr
new file mode 100644 (file)
index 0000000..4b70029
--- /dev/null
@@ -0,0 +1,12 @@
+(define meta
+  `((title . "Youku vs. Tudou—Final")
+    (date  . ,(string->date* "2010-03-26 00:00"))
+    (type  . "short")
+    (photo . "2010-02-10-qiutianbuhuilai.jpg")
+    (tags "tv" "youku" "quan jia dou lai sai")))
+ (p [Here is a ,(ref ""
+     "full recording of the live broadcast") on Wednesday, thanks to
+     Youku!  Some timestamps for all the impatient: 24:24, 53:50,
+     111:00.]))
diff --git a/posts/2010-03-28-elephly.markdown b/posts/2010-03-28-elephly.markdown
deleted file mode 100644 (file)
index 99b45a0..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-title: The Elephly
-date: 2010/03/28
-flattr: 390348/The-Elephly
-license: by-sa
-This is Chlodwig, the marvelous elephly. The Elephly is a creature half
-elephant, half fly, a quarter duck and three quarters weirdness---amounting to
-200% of pure awesomeness!
-[![The elephly](/images/posts/elephly.png)](/downies/elephly.svg)
-Chlodwig came into existence when Rekado felt bored during a class of
-Electrical Engineering. When Rekado realized the wonder that his creation was,
-he decided to manually trace the outline of the faint sketch in Inkscape and
-colorize it. This process took quite some time, because it often required
-Rekado to remove strokes and blur out details in order to reduce the drawing to
-the most essential.
-Get your very own scalable drawing of the elephly by touching the elephly's belly!
diff --git a/posts/2010-03-28-elephly.skr b/posts/2010-03-28-elephly.skr
new file mode 100644 (file)
index 0000000..9696367
--- /dev/null
@@ -0,0 +1,26 @@
+(define meta
+  `((title   . "The Elephly")
+    (date    . ,(string->date* "2010-03-28 00:00"))
+    (flattr  . "390348/The-Elephly")
+    (license . "by-sa")
+    (tags "weird")))
+ (p [This is Chlodwig, the marvelous elephly.  The elephly is a
+     creature half elephant, half fly, a quarter duck and three
+     quarters weirdness—amounting to 200% of pure awesomeness!])
+ (p (ref "/downies/elephly.svg" '(img (@ (src "/images/posts/elephly.png")
+                                         (alt "The elephly")))))
+ (p [Chlodwig came into existence when Rekado felt bored during a
+     class of Electrical Engineering.  When Rekado realised the wonder
+     that his creation was, he decided to manually trace the outline
+     of the faint sketch in Inkscape and colorise it.  This process
+     took quite some time, because it often required Rekado to remove
+     strokes and blur out details in order to reduce the drawing to
+     the most essential.])
+ (p [Get your very own scalable drawing of the elephly by touching the
+     elephly’s belly!]))
diff --git a/posts/2010-04-05-deng-hou.markdown b/posts/2010-04-05-deng-hou.markdown
deleted file mode 100644 (file)
index 982da7b..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-title: Deng Hou
-date: 2010/04/05
-tags: music, chinese
-flattr: "325437"
-When we were told that during our appearance on &ldquo;Jia Ting Yan Bo
-Shi&rdquo; we were to peform a song, Jackie and I thought it would be a good
-idea to write our own song. I still had a chunk of nice simple music without
-lyrics. After Jackie had spent a day to think about the first verse, we would
-both sit down to discuss, reject and rewrite both words and music.
-The unnamed song was first performed on the set of &ldquo;Jia Ting Yan Bo
-Shi&rdquo;. I hope we can get our greedy hands on a recording if the program
-directors decide to remove it from the final cut.
-You can [download a demo recording here](/downies/music/deng_hou.ogg) or listen
-to it right here. 
-<object height="81" width="100%"> <param name="movie" value=""></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src="" type="application/x-shockwave-flash" width="100%"></embed> </object>  <span><a href="">等候</a> by <a href="">rekado</a></span> 
-## Lyrics
-### Verse 1
-<pre class="lyrics">
-da da da da  
-ping dan de ri zi you ni cai hui jing cai
-da da da da
-wei feng ta chui guo ni liu xia de hua
-gu du de xin
-xiang yao fei dao you ni de tian kong xia
-wei xiao
-de gan jue na me jian dan de hui lai
-微笑 的感觉那么简单的回来
-### Part B
-<pre class="lyrics">
-cen jing de tian mi hui yi wang bu liao
-shi luo de xin kan bu dao
-yang guang de fang xiang
-### Verse 2
-<pre class="lyrics">
-da da da da
-ping dan de ri zi you ni cai hui jing cai
-da da da da
-xue hua ta piao guo ni wo zou de lu
-jian ding de xin
-kan jian bu yuan chu lv se de chun tian
-wei lai
-de sheng huo cheng xian zai wo de nao hai
-### Part B'
-<pre class="lyrics">
-ming tian de xiang yi xiang wei meng jian liao
-yong gan de xin zai hu huan
-li ming de shu guang
diff --git a/posts/2010-04-05-deng-hou.skr b/posts/2010-04-05-deng-hou.skr
new file mode 100644 (file)
index 0000000..7f8c7c4
--- /dev/null
@@ -0,0 +1,108 @@
+(define meta
+  `((title . "Deng Hou")
+    (date  . ,(string->date* "2010-04-05 00:00"))
+    (flattr . "325437")
+    (tags "music" "chinese")))
+ (p [When we were told that during our appearance on “Jia Ting Yan Bo
+     Shi” we were to peform a song, Jackie and I thought it would be a
+     good idea to write our own song.  I still had a chunk of nice
+     simple music without lyrics.  After Jackie had spent a day to
+     think about the first verse, we would both sit down to discuss,
+     reject and rewrite both words and music.])
+ (p [The unnamed song was first performed on the set of “Jia Ting Yan
+     Bo Shi”.  I hope we can get our greedy hands on a recording if
+     the program directors decide to remove it from the final cut.])
+ (p [You can ,(ref "/downies/music/deng_hou.ogg" "download a demo
+     recording here") or listen to it right here.])
+ '(object (@ (height "81")
+             (width "100%"))
+          (param (@ (name "movie")
+                    (value "")))
+          (param (@ (name "allowscriptaccess")
+                    (value "always")))
+          (embed (@ (allowscriptaccess "always")
+                    (height "81")
+                    (src "")
+                    (type "application/x-shockwave-flash")
+                    (width "100%"))))
+ '(span (a (@ (href "")) "等候")
+        " by "
+        (a (@ (href "")) "rekado"))
+ (h2 [Lyrics])
+ (h3 [Verse 1])
+ (lyrics [
+da da da da
+ping dan de ri zi you ni cai hui jing cai
+da da da da
+wei feng ta chui guo ni liu xia de hua
+gu du de xin
+xiang yao fei dao you ni de tian kong xia
+wei xiao
+de gan jue na me jian dan de hui lai
+微笑 的感觉那么简单的回来
+ (h3 [Part B])
+ (lyrics [
+cen jing de tian mi hui yi wang bu liao
+shi luo de xin kan bu dao
+yang guang de fang xiang
+ (h3 [Verse 2])
+ (lyrics [
+da da da da
+ping dan de ri zi you ni cai hui jing cai
+da da da da
+xue hua ta piao guo ni wo zou de lu
+jian ding de xin
+kan jian bu yuan chu lv se de chun tian
+wei lai
+de sheng huo cheng xian zai wo de nao hai
+ (h3 [Part B'])
+ (lyrics [
+ming tian de xiang yi xiang wei meng jian liao
+yong gan de xin zai hu huan
+li ming de shu guang
diff --git a/posts/2010-04-12-jiatingyanboshi.markdown b/posts/2010-04-12-jiatingyanboshi.markdown
deleted file mode 100644 (file)
index edb0242..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-title: Jia Ting Yan Bo Shi
-date: 2010/04/12
-tags: tv, chinese
-The final cut of what has been recorded for the interview show *Jia Ting Yan Bo
-Shi* is going to be aired on Friday, April 16 on *Shanghai Dianshi Tai*.
-You will hear Jackie and myself talk about many private issues and our opinions
-on living in Shanghai. Our first live performance of [&ldquo;Deng
-Hou&rdquo;](/posts/2010-04-05-deng-hou.html) is also going to be aired during the
-**Update (April 18, 2010):** A 20 minute section of [the show is already
-**Update (April 21, 2010):** [Part B]( and
-[part C]( are also up now. At the end of
-part C you can hear our terrible rendition of Deng Hou. The vocal harmony is
-pretty off there.
diff --git a/posts/2010-04-12-jiatingyanboshi.skr b/posts/2010-04-12-jiatingyanboshi.skr
new file mode 100644 (file)
index 0000000..f31c3bc
--- /dev/null
@@ -0,0 +1,24 @@
+(define meta
+  `((title . "Jia Ting Yan Bo Shi")
+    (date  . ,(string->date* "2010-04-12 00:00"))
+    (tags "tv" "chinese")))
+ (p [The final cut of what has been recorded for the interview show
+     ,(em [Jia Ting Yan Bo Shi]) is going to be aired on Friday,
+     April 16 on ,(em [Shanghai Dianshi Tai]).])
+ (p [You will hear Jackie and myself talk about many private issues
+     and our opinions on living in Shanghai.  Our first live
+     performance of ,(ref "/posts/2010-04-05-deng-hou.html" "“Deng
+     Hou”") is also going to be aired during the program.])
+ (p [,(strong [Update (April 18, 2010):]) A 20 minute section of ,(ref
+     "" "the show is already
+     online").])
+ (p [,(strong [Update (April 21, 2010):]) ,(ref
+     "" "Part B") and ,(ref
+     "" "part C") are also up
+     now.  At the end of part C you can hear our terrible rendition of
+     Deng Hou.  The vocal harmony is pretty off there.]))
diff --git a/posts/2010-06-01-chapman-stick-on-national-tv.markdown b/posts/2010-06-01-chapman-stick-on-national-tv.markdown
deleted file mode 100644 (file)
index a39d0d7..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-title: The Stick&mdash;Live on Chinese TV
-date: 2010/06/01
-tags: show, tv, chapman stick, video, music
-Once upon a time, there was a mediocre musician with a dream. The story has not
-yet ended, so I cannot say much more than that. If this story would, however,
-be written down by my sentimental alter ego one day (long after the last polar
-bear will have surrendered before the army of blind manatees, oh, the huge
-manatee!), it would probably make mention of the following event.
-![The Chapman Stick on Chinese national TV](/images/posts/stick-on-tv.jpg)
-Tossed around on the waves of his whimsical nature, the mediocre musican fell
-into the path of an opportunity. In a way as to apologize for the accidental
-collision, the clumsy musician offered to make up for the damage by playing
-tunes and singing songs for pure entertainment. Not without a hidden agenda was
-it that on that day the musician decided to bring an instrument, playing which
-he was not even capable of.
-Lo and behold: &#8217;twas the Chapman Stick the musician had strapped on,
-knowing well that the juxtaposition of the minimalistic yet noble instrument
-with the silly cowboy dress... What can I say? There is no way I could justify
-that preposterous appearance.
-Anyway, I participated in a popular Shanghainese show and played the Stick. The
-show was broadcast live on February 8, 2010 and despite the promise to be given
-a reel of the performance, it took four months and lots of effort on my part to
-find [this low-fi snippet]( of
-the very first appearance of the Stick on Chinese TV.
-What you can see here is part of my introduction, a teaser of sorts, to keep
-the audience hooked till the actual performance later in the show.  The song I
-was playing is a somewhat funkier adaption of Wang Li Hong's
-You can [download this historical video clip
diff --git a/posts/2010-06-01-chapman-stick-on-national-tv.skr b/posts/2010-06-01-chapman-stick-on-national-tv.skr
new file mode 100644 (file)
index 0000000..7f5f878
--- /dev/null
@@ -0,0 +1,44 @@
+(define meta
+  `((title . "The Stick—Live on Chinese TV")
+    (date  . ,(string->date* "2010-06-01 00:00"))
+    (tags "show" "tv" "chapman stick" "video" "music")))
+ (p [Once upon a time, there was a mediocre musician with a dream.  The
+     story has not yet ended, so I cannot say much more than that.  If
+     this story would, however, be written down by my sentimental alter
+     ego one day (long after the last polar bear will have surrendered
+     before the army of blind manatees, oh, the huge manatee!), it
+     would probably make mention of the following event.])
+ (figure "stick-on-tv.jpg"
+         "The Chapman Stick on Chinese national TV")
+ (p [Tossed around on the waves of his whimsical nature, the mediocre
+     musican fell into the path of an opportunity.  In a way as to
+     apologize for the accidental collision, the clumsy musician
+     offered to make up for the damage by playing tunes and singing
+     songs for pure entertainment.  Not without a hidden agenda was it
+     that on that day the musician decided to bring an instrument,
+     playing which he was not even capable of.])
+ (p [Lo and behold: ’twas the Chapman Stick the musician had strapped
+     on, knowing well that the juxtaposition of the minimalistic yet
+     noble instrument with the silly cowboy dress... What can I say?
+     There is no way I could justify that preposterous appearance.])
+ (p [Anyway, I participated in a popular Shanghainese show and played
+     the Stick.  The show was broadcast live on February 8, 2010 and
+     despite the promise to be given a reel of the performance, it took
+     four months and lots of effort on my part to find ,(ref
+     "" "this low-fi
+     snippet") of the very first appearance of the Stick on Chinese
+     TV.])
+ (p [What you can see here is part of my introduction, a teaser of
+     sorts, to keep the audience hooked till the actual performance
+     later in the show.  The song I was playing is a somewhat funkier
+     adaption of Wang Li Hong’s “龙的传人”.])
+ (p [You can ,(ref "/downies/videos/qjdls_chapman_stick_1.mp4"
+     "download this historical video clip here").]))
diff --git a/posts/2010-06-24-2010-niuren.markdown b/posts/2010-06-24-2010-niuren.markdown
deleted file mode 100644 (file)
index a58b1dd..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-title: 2010 Youku Niuren Competition
-date: 2010/06/24
-tags: music, show, youku
-<img class="full stretch" src="/images/posts/niuren2010.jpg" alt="At the Shanghai venue of Niuren 2010"/>
-In an SMS two days before the Shanghai event of this year's Niuren competition,
-my friend at Youku asked me if I would want to perform a song on the stage.
-After some initial hesitation I eventually agreed to playing the guitar while
-singing. Originally, I wanted to perform 坏人 but at the venue I realized that
-this particular song is not quite as popular as 秋天不回来.
-Not very well prepared I got on the stage as the third performer that
-afternoon. I unexplicably managed to spoil the guitar intro, but still nobody
-seemed to really mind. It felt good not to feel the pressuring perfectionism
-flaring up inside of me again.
-With this precautionary tale in mind, go ahead and [watch the clip on
-youku](! If you prefer to watch
-a version that I'm okay with, then [check out the older
-**Update (June 29, 2010)**: There is a [short clip on
-youku]( that aired on TV to
-advertise the competition. The clip was featured on the start page of youku and
-thus reached quite a large number of people.
diff --git a/posts/2010-06-24-2010-niuren.skr b/posts/2010-06-24-2010-niuren.skr
new file mode 100644 (file)
index 0000000..1e2dff6
--- /dev/null
@@ -0,0 +1,33 @@
+(define meta
+  `((title . "2010 Youku Niuren Competition")
+    (date  . ,(string->date* "2010-06-24 00:00"))
+    (tags "music" "show" "youku")))
+ (wide-img "niuren2010.jpg"
+           "At the Shanghai venue of Niuren 2010")
+ (p [In an SMS two days before the Shanghai event of this year’s
+     Niuren competition, my friend at Youku asked me if I would want
+     to perform a song on the stage.  After some initial hesitation I
+     eventually agreed to playing the guitar while singing.
+     Originally, I wanted to perform 坏人 but at the venue I realized
+     that this particular song is not quite as popular as 秋天不回来.])
+ (p [Not very well prepared I got on the stage as the third performer
+     that afternoon.  I unexplicably managed to spoil the guitar
+     intro, but still nobody seemed to really mind.  It felt good not
+     to feel the pressuring perfectionism flaring up inside of me
+     again.])
+ (p [With this precautionary tale in mind, go ahead and ,(ref
+     "" "watch the clip
+     on youku")!  If you prefer to watch a version that I’m okay with,
+     then ,(ref "/posts/2009-11-02-qtbhl.html" "check out the older
+     video").])
+ (p [,(strong [Update (June 29, 2010)]): There is a ,(ref
+     "" "short clip on
+     youku") that aired on TV to advertise the competition.  The clip
+     was featured on the start page of youku and thus reached quite a
+     large number of people.]))
diff --git a/posts/2010-07-02-newspaper.markdown b/posts/2010-07-02-newspaper.markdown
deleted file mode 100644 (file)
index 0dc3b0d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-title: Newspaper Report
-date: 2010/07/02
-tags: niuren, youku, chapman stick, media
-[![small view of the article](/images/posts/newspaper.jpg)](/images/posts/newspaper-large.jpg)
-A few weeks ago I accepted the offer to perform a song at this year's Niuren
-Competition. As I was notified just two days before the event, I couldn't make
-arrangements for taking the Stick, so [I just played a well-known song on the
-guitar](/posts/2010-06-24-2010-niuren.html). After the performance, I chatted with
-a woman on site who had an awful lot of questions for me. Turns out she is a
-reporter for the local newspaper ["Overseas Chinese
-News"]( Later the journalist asked me to send her
-some photos of myself playing an instrument to illustrate an article they were
-The article is now available online, both as a [newspaper-styled
-and a [text
-I am very happy that they chose the photo of me playing the Chapman Stick at
-home. Thanks to Sandra Yan for the article! (Careful: the newspaper's website
-seems to be optimized for the Internet Explorer.)
diff --git a/posts/2010-07-02-newspaper.skr b/posts/2010-07-02-newspaper.skr
new file mode 100644 (file)
index 0000000..0c07319
--- /dev/null
@@ -0,0 +1,31 @@
+(define meta
+  `((title . "Newspaper Report")
+    (date  . ,(string->date* "2010-07-02 00:00"))
+    (tags "niuren" "youku" "chapman stick" "media")))
+ (ref "/images/posts/newspaper-large.jpg"
+      (figure "newspaper.jpg"
+              "small view of the article"))
+ (p [A few weeks ago I accepted the offer to perform a song at this
+     year’s Niuren Competition.  As I was notified just two days
+     before the event, I couldn’t make arrangements for taking the
+     Stick, so ,(ref "/posts/2010-06-24-2010-niuren.html" "I just
+     played a well-known song on the guitar").  After the performance,
+     I chatted with a woman on site who had an awful lot of questions
+     for me.  Turns out she is a reporter for the local newspaper
+     ,(ref "" "“Overseas Chinese News”").
+     Later the journalist asked me to send her some photos of myself
+     playing an instrument to illustrate an article they were
+     preparing.])
+ (p [The article is now available online, both as a ,(ref
+     ""
+     "newspaper-styled image") and a ,(ref
+     ""
+     "text version").  I am very happy that they chose the photo of me
+     playing the Chapman Stick at home.  Thanks to Sandra Yan for the
+     article!  (Careful: the newspaper’s website seems to be optimized
+     for the Internet Explorer.)]))
diff --git a/posts/2010-07-08-wishful-thinking.markdown b/posts/2010-07-08-wishful-thinking.markdown
deleted file mode 100644 (file)
index e5a7339..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-title: Wishful Thinking
-date: 2010/07/08
-tags: musings, ecology, energy
-I used to be a magical thinker many years ago. Whenever I wished for something
-I would keep looking at the road side while sitting on the backseat of my
-parents&#8217; car or when I was walking home from school, hoping to spot the
-object of my dreams.
-For many years I badly wished for a tortoise or a turtle to come into my life,
-just waiting for me at the side of the road. As I used to find coins just about
-twice a month, I reckoned I could stumble upon animals just as easily. Animals
-longing to let go of their wild nature, willing to become my companion and just
-waiting for me to come by.
-It never happened. (It should also be noted that my dream to stumble upon a
-tame specimen of Gallimimus at the side of the road never came true.) I never
-found a turtle at the side of the road.
-Until today. A dream came true, but it had unnoticedly turned into a nightmare.
-When I walked out the door this morning I caught sight of about four
-centimeters of what seemed to resemble a six-legged crab. As I got closer I
-could make out that one of the legs was actually a tail and another was a head
-on a long neck. Closer yet I recognized it as a tiny turtle standing squarely
-on the right side of my path.
-![dead turtle](/images/posts/turtle.jpg)
-Noticing an ant crawling on its eye I realized that it was dead. Its limbs had
-not completely stiffened yet when I picked it up to move its body off the
-street and onto the sidewalk where I went on to take a picture of a shattered
-In an attempt to stretch this story into a metaphor for something more dramatic
-than the mere death of critter&mdash;albeit a cute one&mdash;I chose
-&ldquo;Wishful Thinking&rdquo; as the title for this entry. Although this story
-is not representative of anything in particular, it did remind me of what I
-recently read on Magical Thinking in Derrick Jensen&#8127;s &ldquo;What We
-Leave Behind&rdquo;.
-(There's much I disagree with when it comes to Jensen's worldview, but this
-section is quite powerful.)
-  <p>Are you a magical thinker? I know that too often I am. With apologies to Jeff
-  Foxworthy, let&#8127;s play a little game.</p>
-  <p>If you put a bumper sticker on you hybrid Prius that reads <em>Visualize World
-  Peace</em> in the hope this will bring about world peace, you might just be a
-  magical thinker.</p>
-  <p>If you buy a hybrid Prius in the hope this will slow global warming, you
-  might just be a magical thinker.</p>
-  <p>[...]</p>
-  <p>If you think buying compact fluorescent light bulbs will slow global warming,
-  you might just be a magical thinker.</p>
-  <p>[...]</p>
-  <p>If you think this culture will stop killing the planet without being
-  force-fully stopped, you might just be delusional, and if you don&#8127;t act
-  to stop this culture, then you will be failing in your responsibility as a
-  living being (p.224/5).</p>
-&ldquo;Ugh, did he just really turn a story about a rotting turtle into an
-environmental protection guilt-fest?&rdquo;---so it seems. What I was aiming
-for was that: remembering my innocent dreaming and my firm believe that
-watching just closely enough will make the unlikely more likely, in the face of
-the distasteful partial manifestation of that dream demonstrated just how
-unsatisfying Wishful Thinking can be. Observing the road side would have only
-increased my chance of discovering unpleasant road-kills. My convenient idea of
-looking out for what is easiest to spot just addressed the wrong problem
-(turtles aren't the type to lurk at the side of roads) and at the same time
-left me unsatisfied. I think I'm eventually driving the point home: attempting
-to solve the wrong problem is unrewarding in every way.
-If you think our culture will survive if only we could manage to find an
-alternative to cheap oil, you might just be a magical thinker---or you might be
-part of the actual problem.
diff --git a/posts/2010-07-08-wishful-thinking.skr b/posts/2010-07-08-wishful-thinking.skr
new file mode 100644 (file)
index 0000000..7abf251
--- /dev/null
@@ -0,0 +1,92 @@
+(define meta
+  `((title . "Wishful Thinking")
+    (date  . ,(string->date* "2010-07-08 00:00"))
+    (tags "musings" "ecology" "energy")))
+ (p [I used to be a magical thinker many years ago.  Whenever I wished
+     for something I would keep looking at the road side while sitting
+     on the backseat of my parents’ car or when I was walking home
+     from school, hoping to spot the object of my dreams.])
+ (p [For many years I badly wished for a tortoise or a turtle to come
+     into my life, just waiting for me at the side of the road.  As I
+     used to find coins just about twice a month, I reckoned I could
+     stumble upon animals just as easily.  Animals longing to let go
+     of their wild nature, willing to become my companion and just
+     waiting for me to come by.])
+ (p [It never happened. (It should also be noted that my dream to
+     stumble upon a tame specimen of Gallimimus at the side of the
+     road never came true.) I never found a turtle at the side of the
+     road.])
+ (p [Until today.  A dream came true, but it had unnoticedly turned
+     into a nightmare.  When I walked out the door this morning I
+     caught sight of about four centimeters of what seemed to resemble
+     a six-legged crab.  As I got closer I could make out that one of
+     the legs was actually a tail and another was a head on a long
+     neck.  Closer yet I recognized it as a tiny turtle standing
+     squarely on the right side of my path.])
+ (wide-img "turtle.jpg"
+           "dead turtle")
+ (p [Noticing an ant crawling on its eye I realized that it was dead.
+     Its limbs had not completely stiffened yet when I picked it up to
+     move its body off the street and onto the sidewalk where I went
+     on to take a picture of a shattered dream.])
+ (p [In an attempt to stretch this story into a metaphor for something
+     more dramatic than the mere death of critter—albeit a cute one—I
+     chose “Wishful Thinking” as the title for this entry.  Although
+     this story is not representative of anything in particular, it
+     did remind me of what I recently read on Magical Thinking in
+     Derrick Jensen’s “What We Leave Behind”.])
+ (p [(There’s much I disagree with when it comes to Jensen’s
+     worldview, but this section is quite powerful.)])
+ (blockquote
+  (p [Are you a magical thinker?  I know that too often I am.  With
+      apologies to Jeff Foxworthy, let’s play a little game.])
+  (p [If you put a bumper sticker on you hybrid Prius that reads
+      ,(em [Visualize World Peace]) in the hope this will bring
+      about world peace, you might just be a magical thinker.])
+  (p [If you buy a hybrid Prius in the hope this will slow global
+      warming, you might just be a magical thinker.])
+  '(p "[...]")
+  (p [If you think buying compact fluorescent light bulbs will slow
+      global warming, you might just be a magical thinker.])
+  '(p "[...]")
+  (p [If you think this culture will stop killing the planet without
+      being force-fully stopped, you might just be delusional, and if
+      you don’t act to stop this culture, then you will be failing in
+      your responsibility as a living being (p.224/5).]))
+ (p [“Ugh, did he just really turn a story about a rotting turtle into
+     an environmental protection guilt-fest?”—so it seems.  What I was
+     aiming for was that: remembering my innocent dreaming and my firm
+     believe that watching just closely enough will make the unlikely
+     more likely, in the face of the distasteful partial manifestation
+     of that dream demonstrated just how unsatisfying Wishful Thinking
+     can be.  Observing the road side would have only increased my
+     chance of discovering unpleasant road-kills.  My convenient idea
+     of looking out for what is easiest to spot just addressed the
+     wrong problem (turtles aren’t the type to lurk at the side of
+     roads) and at the same time left me unsatisfied.  I think I’m
+     eventually driving the point home: attempting to solve the wrong
+     problem is unrewarding in every way.])
+ (p [If you think our culture will survive if only we could manage to
+     find an alternative to cheap oil, you might just be a magical
+     thinker—or you might be part of the actual problem.]))
diff --git a/posts/2010-07-14-one-night-in-beijing.markdown b/posts/2010-07-14-one-night-in-beijing.markdown
deleted file mode 100644 (file)
index 64535c5..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-title: One Night In Beijing
-date: 2010/07/14
-tags: music, youku, video, show
-When I noticed that the online voting system for the big Niuren 2010 event was
-not to be trusted, I was pretty convinced not be one of those chosen to perform
-on stage in Bejing. In order to be sure, I wrote a message to my friend at
-Youku. Some hours later I was informed that disregarding the number of the
-votes (which did turn out to be comparatively high in the end) I was supposed
-to be invited to give a performance on the Stick. After all formal issues were
-agreed upon, I prepared to leave for Beijing on Sunday morning with the Chapman
-Stick in tow.
-When I arrived at the venue I was surprised to find the stage to be a lot
-larger than I anticipated.
-<img class="full" src="/images/posts/niuren2010_beijing_stage.jpg" alt="The stage in Beijing"/>
-When it was time for my soundcheck the clouds had formed a dark opaque blanket
-across the unattractive skies of Beijing and at times rain drops mixed with the
-soil on the vast meadow to form squishy mud. The crew seemed to marvel at the
-impression of hearing two instruments' sounds, each articulated by one
-individual hand on its own set of strings but on one instrument.
-At about ten o&#8127;clock in the evening, the show began. It only lasted for
-about 15 minutes as the occasional rain proceeded to grow into drowning
-vertical streams of water. The stage was lacking any sort of rain protection
-and it didn&#8127;t take long until the stage lights went off as the cables
-were drenched.
-The show was eventually cancelled which only made sense considering that most
-of the mud-dwellers in front of the stage had given up their hopes for better
-weather and had left the premises in shoals.
-Disappointed we returned to the hotel. When finally everybody had returned we
-discussed with the organizers how to proceed, how to salvage the investment. At
-first the idea was going around to stage the event on Monday evening, without
-an audience, just recording and pretending it all happened the day before. This
-idea was soon discarded, though, when the organizers learned that most of had
-would be flying back home on Monday morning. A compromises was found when the
-decision was made to record individual performances&mdash;or rather very pale
-and primitive versions of what was originally planned&mdash;in the lobby of the
-![Recording video clips in the hotel lobby at 2am](/images/posts/niuren2010_beijing_lobby.jpg)
-These clips&mdash;all of which were recorded between two and three
-a.m.&mdash;are supposed to serve as teasers for the actual show which has now
-been postponed to some time in August or September. I will add the links to
-those video clips in the next few days, provided I can find them. A new entry
-will be posted once the date for the postponed show in Beijing has been
-**Update (July 29):*** The short video clip has been uploaded. You can [watch
-it on youku](
-**Update:*** Gao Ming interviewed the participants during the preparations of
-the show. There is a 25+ minutes [video clip on
-youku]( At about 2:40 he comes
-across the table where I am relaxing with other participants.
diff --git a/posts/2010-07-14-one-night-in-beijing.skr b/posts/2010-07-14-one-night-in-beijing.skr
new file mode 100644 (file)
index 0000000..9027747
--- /dev/null
@@ -0,0 +1,73 @@
+(define meta
+  `((title . "One Night In Beijing")
+    (date  . ,(string->date* "2010-07-14 00:00"))
+    (tags "music" "youku" "video" "show")))
+ (p [When I noticed that the online voting system for the big Niuren
+     2010 event was not to be trusted, I was pretty convinced not be
+     one of those chosen to perform on stage in Bejing.  In order to
+     be sure, I wrote a message to my friend at Youku.  Some hours
+     later I was informed that disregarding the number of the votes
+     (which did turn out to be comparatively high in the end) I was
+     supposed to be invited to give a performance on the Stick.  After
+     all formal issues were agreed upon, I prepared to leave for
+     Beijing on Sunday morning with the Chapman Stick in tow.])
+ (p [When I arrived at the venue I was surprised to find the stage to
+     be a lot larger than I anticipated.])
+ (wide-img "niuren2010_beijing_stage.jpg"
+           "The stage in Beijing")
+ (p [When it was time for my soundcheck the clouds had formed a dark
+     opaque blanket across the unattractive skies of Beijing and at
+     times rain drops mixed with the soil on the vast meadow to form
+     squishy mud.  The crew seemed to marvel at the impression of
+     hearing two instruments’ sounds, each articulated by one
+     individual hand on its own set of strings but on one
+     instrument.])
+ (p [At about ten o’clock in the evening, the show began. It only
+     lasted for about 15 minutes as the occasional rain proceeded to
+     grow into drowning vertical streams of water.  The stage was
+     lacking any sort of rain protection and it didn’t take long until
+     the stage lights went off as the cables were drenched.])
+ (p [The show was eventually cancelled which only made sense
+     considering that most of the mud-dwellers in front of the stage
+     had given up their hopes for better weather and had left the
+     premises in shoals.])
+ (p [Disappointed we returned to the hotel.  When finally everybody
+     had returned we discussed with the organizers how to proceed, how
+     to salvage the investment.  At first the idea was going around to
+     stage the event on Monday evening, without an audience, just
+     recording and pretending it all happened the day before.  This
+     idea was soon discarded, though, when the organizers learned that
+     most of had would be flying back home on Monday morning.  A
+     compromise was found when the decision was made to record
+     individual performances—or rather very pale and primitive
+     versions of what was originally planned—in the lobby of the
+     hotel.])
+ (figure "niuren2010_beijing_lobby.jpg"
+         "Recording video clips in the hotel lobby at 2am")
+ (p [These clips—all of which were recorded between two and three
+     a.m.—are supposed to serve as teasers for the actual show which
+     has now been postponed to some time in August or September.  I
+     will add the links to those video clips in the next few days,
+     provided I can find them.  A new entry will be posted once the
+     date for the postponed show in Beijing has been confirmed.])
+ (p [,(strong [Update (July 29):]) The short video clip has been
+     uploaded.  You can ,(ref
+     "" "watch it on
+     youku").])
+ (p [,(strong [Update:]) Gao Ming interviewed the participants during
+     the preparations of the show.  There is a 25+ minutes ,(ref
+     "" "video clip on
+     youku").  At about 2:40 he comes across the table where I am
+     relaxing with other participants.]))
diff --git a/posts/2010-08-04-alto-stick.markdown b/posts/2010-08-04-alto-stick.markdown
deleted file mode 100644 (file)
index d5687ba..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-title: &ldquo;Flow&rdquo; on Alto Stick
-date: 2010/08/04
-tags: music, alto stick, chapman stick
-<img src='/images/posts/alto-stick.jpg' alt="Alto Stick 6061" class="full stretch"/>
-Just yesterday I received my new Alto Stick (#6061). It is a Chapman Stick with
-ten strings and a shorter scale, very similar to a guitar, really. Yesterday
-night I just could not put it down, so I experimented with layered chords and
-arpeggios. The video I recorded that night just would not sync to the audio
-track, so I recorded the idea once again just some minutes ago in the early
-There are many bumps in this recording, still I like it. Maybe you do, too.
-<object height="81" width="100%"> <param name="movie" value=";show_comments=true&amp;auto_play=false&amp;color=ff7700"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src=";show_comments=true&amp;auto_play=false&amp;color=ff7700" type="application/x-shockwave-flash" width="100%"></embed> </object>   <span><a href="">Flow</a> by <a href="">rekado</a></span>
diff --git a/posts/2010-08-04-alto-stick.skr b/posts/2010-08-04-alto-stick.skr
new file mode 100644 (file)
index 0000000..0c90d06
--- /dev/null
@@ -0,0 +1,36 @@
+(define meta
+  `((title . "“Flow” on Alto Stick")
+    (date  . ,(string->date* "2010-08-04 00:00"))
+    (tags "music" "alto stick" "chapman stick")))
+ (wide-img "alto-stick.jpg"
+           "Alto Stick 6061")
+ (p [Just yesterday I received my new Alto Stick (#6061).  It is a
+     Chapman Stick with ten strings and a shorter scale, very similar
+     to a guitar, really.  Yesterday night I just could not put it
+     down, so I experimented with layered chords and arpeggios.  The
+     video I recorded that night just would not sync to the audio
+     track, so I recorded the idea once again just some minutes ago in
+     the early morning.])
+ (p [There are many bumps in this recording, still I like it.  Maybe
+     you do, too.])
+ '(object (@ (height "81")
+             (width "100%"))
+          (param (@ (name "movie")
+                    (value ";show_comments=true&amp;auto_play=false&amp;color=ff7700")))
+          (param (@ (name "allowscriptaccess")
+                    (value "always")))
+          (embed (@ (allowscriptaccess "always")
+                    (height "81")
+                    (src ";show_comments=true&amp;auto_play=false&amp;color=ff7700")
+                    (type "application/x-shockwave-flash")
+                    (width "100%"))))
+ `(span
+   ,(ref "" "Flow")
+   " by "
+   ,(ref "" "rekado")))
diff --git a/posts/2010-08-15-yueyintang.markdown b/posts/2010-08-15-yueyintang.markdown
deleted file mode 100644 (file)
index d070c68..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-title: Yueyin Tang
-date: 2010/08/15
-tags: music
-Just so you know why there has not been any update for a while: Jackie and I
-were asked to play a 20 to 40 minutes set on a Wednesday night in September
-with some friends in a bar. We think we could be playing these songs without
-too much hassle:
-  - 神话
-  - Eye of the Tiger
-  - 天使
-  - Kayleigh
-  - 秋天不回来
-  - Caveman (original song)
-I was told that there would be a full drum set and amplifiers for bass and
-guitar. As we are but two people, I will play the Grand Stick to fill the spots
-of both guitarist and bass player while singing. Jackie has to get back into
-drumming within in the next few days, so I will be busy with tutoring her a
-"Caveman" is not a full song yet. Once intended to be the second part of my
-*opus magnum*, writing stalled when I stopped actively working on the whole
-thing. About three years ago I made a short [demo
-recording](/downies/music/caveman_demo.ogg) of it in Berlin. The lyrics have
-changed since, but are still incomplete. I will have to take some time to flesh
-it out and turn it into a real song.
-Last Wednesday I failed at recording 天使 for various reasons. For one the fear
-to disturb the sleeping neighbours---they go to bed at eight in the
-evening---was very inhibiting to my singing; on top of that sleep deprivation
-attributed to rather sloppy playing. I also stared into the camera to often,
-which made for disturbing footage. I am going to venture another attempt
diff --git a/posts/2010-08-15-yueyintang.skr b/posts/2010-08-15-yueyintang.skr
new file mode 100644 (file)
index 0000000..bd350ee
--- /dev/null
@@ -0,0 +1,40 @@
+(define meta
+  `((title . "Yueyin Tang")
+    (date  . ,(string->date* "2010-08-15 00:00"))
+    (tags "music")))
+ (p [Just so you know why there has not been any update for a while:
+     Jackie and I were asked to play a 20 to 40 minutes set on a
+     Wednesday night in September with some friends in a bar.  We
+     think we could be playing these songs without too much hassle:])
+ (ul
+  (li [神话])
+  (li [Eye of the Tiger])
+  (li [天使])
+  (li [Kayleigh])
+  (li [秋天不回来])
+  (li [Caveman (original song)]))
+ (p [I was told that there would be a full drum set and amplifiers for
+     bass and guitar.  As we are but two people, I will play the Grand
+     Stick to fill the spots of both guitarist and bass player while
+     singing.  Jackie has to get back into drumming within in the next
+     few days, so I will be busy with tutoring her a little.])
+ (p [“Caveman” is not a full song yet.  Once intended to be the second
+     part of my ,(em [opus magnum]), writing stalled when I stopped
+     actively working on the whole thing.  About three years ago I
+     made a short ,(ref "/downies/music/caveman_demo.ogg" "demo
+     recording") of it in Berlin.  The lyrics have changed since, but
+     are still incomplete.  I will have to take some time to flesh it
+     out and turn it into a real song.])
+ (p [Last Wednesday I failed at recording 天使 for various reasons.
+     For one the fear to disturb the sleeping neighbours—they go to
+     bed at eight in the evening—was very inhibiting to my singing; on
+     top of that sleep deprivation attributed to rather sloppy
+     playing.  I also stared into the camera to often, which made for
+     disturbing footage.  I am going to venture another attempt
+     tonight.]))
diff --git a/posts/2010-08-17-tianshi.markdown b/posts/2010-08-17-tianshi.markdown
deleted file mode 100644 (file)
index 4da1752..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-title: &ldquo;Tianshi&rdquo; on Alto Stick
-date: 2010/08/17
-tags: music, video, chinese, alto stick, chapman stick
-flattr: 472329/Tianshi-on-Alto-Stick
-When my colleague was in the middle of preparations for getting married, he
-asked me to play a nice song at his wedding. &ldquo;Nice&rdquo; songs are a
-neglected minority in Chinese pop music; most of the popular songs deal with
-love affairs gone wrong, broken hearts, the loss of the original feeling, or
-they describe the emptiness after the loved one has passed away. Nothing that
-would really fit to the (admittedly cheesy) celebration of Eternal Love™.
-Hence, my vast catalogue of popular songs was all but useless. I had to learn
-how to play a new song: Mayday&#8127;s &ldquo;Angel&rdquo;.
-This is my practise session in its blunt ugliness. I spliced in a solo section
-recorded at a different angle to divert you from the boredom. As you will
-probably notice, the introduction was lifted from my improvisation
-[&ldquo;Flow&rdquo; which I recorded
-(Yes, this is the same shirt as in my last video...)
-My next recording will likely be an original song, unless I will be asked by my
-friends at for more sino pop before it is ready.
-<video width="100%" autobuffer controls poster="tianshi.jpg">
-  <source src='/downies/videos/tianshi_low.mp4'/>
-  <source src='/downies/videos/tianshi_low.ogv'/>
-I offer this video for download in several formats. Choose one from the list
-below. When you do not want to care about codecs, [download the free VLC
-player]( If you are on Linux `mplayer` will work fine,
-## Medium Quality (HD 720)
-<div class="download">
-  <table>
-    <tr><th>codecs</th><td>h.264 + mp3</td></tr>
-    <tr><th>bitrate A</th><td>192&thinsp;kbps</td></tr>
-    <tr><th>bitrate V</th><td>3&thinsp;Mbps</td></tr>
-    <tr><th>container</th><td>mp4</td></tr>
-    <tr><th>size</th><td>109&thinsp;MB<td></tr>
-  </table>
-  <a href='/downies/videos/tianshi_medium.mp4'>download</a>
-<div class="download">
-  <table>
-    <tr><th>codecs</th><td>ogg theora</td></tr>
-    <tr><th>bitrate A</th><td>192&thinsp;kbps</td></tr>
-    <tr><th>bitrate V</th><td>3&thinsp;Mbps</td></tr>
-    <tr><th>container</th><td>ogv</td></tr>
-    <tr><th>size</th><td>135&thinsp;MB</td></tr>
-  </table>
-  <a href='/downies/videos/tianshi_medium.ogv'>download</a>
-## Low Quality (HD 480)
-<div class="download">
-  <table>
-    <tr><th>codecs</th><td>h.264 + mp3</td></tr>
-    <tr><th>bitrate A</th><td>128&thinsp;kbps</td></tr>
-    <tr><th>bitrate V</th><td>1.5&thinsp;Mbps</td></tr>
-    <tr><th>container</th><td>mp4</td></tr>
-    <tr><th>size</th><td>56&thinsp;MB<td></tr>
-  </table>
-  <a href='/downies/videos/tianshi_low.mp4'>download</a>
-<div class="download">
-  <table>
-    <tr><th>codecs</th><td>ogg theora</td></tr>
-    <tr><th>bitrate A</th><td>128&thinsp;kbps</td></tr>
-    <tr><th>bitrate V</th><td>1.5&thinsp;Mbps</td></tr>
-    <tr><th>container</th><td>ogv</td></tr>
-    <tr><th>size</th><td>55&thinsp;MB</td></tr>
-  </table>
-  <a href='/downies/videos/tianshi_low.ogv'>download</a>
-## Streaming
-The video is available on both
-[Youku]( and
diff --git a/posts/2010-08-17-tianshi.skr b/posts/2010-08-17-tianshi.skr
new file mode 100644 (file)
index 0000000..69dc223
--- /dev/null
@@ -0,0 +1,88 @@
+(define meta
+  `((title  . "“Tianshi” on Alto Stick")
+    (date   . ,(string->date* "2010-08-17 00:00"))
+    (flattr . "472329/Tianshi-on-Alto-Stick")
+    (tags "music" "video" "chinese" "alto stick" "chapman stick")))
+ (p [When my colleague was in the middle of preparations for getting
+     married, he asked me to play a nice song at his wedding.  “Nice”
+     songs are a neglected minority in Chinese pop music; most of the
+     popular songs deal with love affairs gone wrong, broken hearts,
+     the loss of the original feeling, or they describe the emptiness
+     after the loved one has passed away.  Nothing that would really
+     fit to the (admittedly cheesy) celebration of Eternal Love™.
+     Hence, my vast catalogue of popular songs was all but useless. I
+     had to learn how to play a new song: Mayday’s “Angel”.])
+ (p [This is my practise session in its blunt ugliness.  I spliced in a
+     solo section recorded at a different angle to divert you from the
+     boredom.  As you will probably notice, the introduction was lifted
+     from my improvisation ,(ref
+     "/posts/2010-08-05-flow-on-the-alto-stick-video.html" "“Flow”
+     which I recorded earlier").])
+ (p [(Yes, this is the same shirt as in my last video...)])
+ (p [My next recording will likely be an original song, unless I will
+     be asked by my friends at for more sino pop before it is
+     ready.])
+ '(video (@ (width "100%")
+            (autobuffer "true")
+            (controls "true")
+            (poster "tianshi.jpg"))
+   (source (@ (src "/downies/videos/tianshi_low.mp4")))
+   (source (@ (src "/downies/videos/tianshi_low.ogv"))))
+ (p [I offer this video for download in several formats.  Choose one
+     from the list below.  When you do not want to care about codecs,
+     ,(ref "" "download the free VLC player").  If
+     you are on GNU/Linux ,(code [mplayer]) will work fine, too.])
+ (h2 [Medium Quality (HD 720)])
+ `(div (@ (class "download"))
+   (table
+     (tr (th "codecs")    (td "h.264 + mp3"))
+     (tr (th "bitrate A") (td "192 kbps"))
+     (tr (th "bitrate V") (td "3 Mbps"))
+     (tr (th "container") (td "mp4"))
+     (tr (th "size")      (td "109 MB")))
+   ,(ref "/downies/videos/tianshi_medium.mp4" "download"))
+ `(div (@ (class "download"))
+   (table
+     (tr (th "codecs")    (td "ogg theora"))
+     (tr (th "bitrate A") (td "192 kbps"))
+     (tr (th "bitrate V") (td "3 Mbps"))
+     (tr (th "container") (td "ogv"))
+     (tr (th "size")      (td "135 MB")))
+   ,(ref "/downies/videos/tianshi_medium.ogv" "download")) 
+ (h2 [Low Quality (HD 480)])
+ `(div (@ (class "download"))
+   (table
+     (tr (th "codecs")    (td "h.264 + mp3"))
+     (tr (th "bitrate A") (td "128 kbps"))
+     (tr (th "bitrate V") (td "1.5 Mbps"))
+     (tr (th "container") (td "mp4"))
+     (tr (th "size")      (td "56 MB")))
+   ,(ref "/downies/videos/tianshi_low.mp4" "download"))
+ `(div (@ (class "download"))
+   (table
+     (tr (th "codecs")    (td "ogg theora"))
+     (tr (th "bitrate A") (td "128 kbps"))
+     (tr (th "bitrate V") (td "1.5 Mbps"))
+     (tr (th "container") (td "ogv"))
+     (tr (th "size")      (td "55 MB")))
+   ,(ref "/downies/videos/tianshi_low.ogv" "download")) 
+ (h2 [Streaming])
+ (p [The video is available on ,(ref
+     "" "Youku").]))
diff --git a/posts/2010-10-14-chinese-tune-mda-epiano.markdown b/posts/2010-10-14-chinese-tune-mda-epiano.markdown
deleted file mode 100644 (file)
index 9b8b984..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-title: Chinese Tune / The mdaEPiano
-date: 2010/10/14
-tags: code, music
-photo: mda-epiano-coding.jpg
-flattr: 72898/LV2-port-of-the-mda-E-Piano-VSTi
-In the past two days (actually, mornings and evenings) I have been working on
-porting the famous [mda EPiano VSTi plugin]( to the LV2
-plugin framework. The sound of the electric piano is very inspiring.  Hear for
-<object height="81" width="100%"> <param name="movie" value=";show_comments=true&amp;auto_play=false&amp;color=ffaa00"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src=";show_comments=true&amp;auto_play=false&amp;color=ffaa00" type="application/x-shockwave-flash" width="100%"></embed> </object>
-You can [download the recording from soundcloud](
-The recording was done with `arecordmidi` while routing all incoming midi
-events through the LV2 plugin.  An instance of `jack_capture` was used to
-record the generated sound simultaneously. If you want to compare my port of
-the plugin to your favorite synthesizer, you can [download the midi file
-The LV2 port can be
-[downloaded from my git repository](
diff --git a/posts/2010-10-14-chinese-tune-mda-epiano.skr b/posts/2010-10-14-chinese-tune-mda-epiano.skr
new file mode 100644 (file)
index 0000000..b009a89
--- /dev/null
@@ -0,0 +1,35 @@
+(define meta
+  `((title  . "Chinese Tune / The mdaEPiano")
+    (date   . ,(string->date* "2010-10-14 00:00"))
+    (photo  . "mda-epiano-coding.jpg")
+    (flattr . "72898/LV2-port-of-the-mda-E-Piano-VSTi")
+    (tags "code" "music")))
+ (p [In the past two days (actually, mornings and evenings) I have
+     been working on porting the famous ,(ref ""
+     "mda EPiano VSTi plugin") to the LV2 plugin framework.  The sound
+     of the electric piano is very inspiring.  Hear for yourself:])
+ '(object (@ (height "81") (width "100%"))
+          (param (@ (name "movie") (value ";show_comments=true&amp;auto_play=false&amp;color=ffaa00")))
+          (param (@ (name "allowscriptaccess") (value "always")))
+          (embed (@ (allowscriptaccess "always")
+                    (height "81")
+                    (src ";show_comments=true&amp;auto_play=false&amp;color=ffaa00")
+                    (type "application/x-shockwave-flash")
+                    (width "100%"))))
+ (p [You can ,(ref ""
+     "download the recording from soundcloud").  The recording was
+     done with ,(code [arecordmidi]) while routing all incoming midi
+     events through the LV2 plugin.  An instance of ,(code
+     [jack_capture]) was used to record the generated sound
+     simultaneously.  If you want to compare my port of the plugin to
+     your favorite synthesizer, you can ,(ref
+     "/downies/music/chinese-tune.mid" "download the midi file
+     here").])
+ (p [The LV2 port can be ,(ref
+     ""
+     "downloaded from my git repository").]))
diff --git a/posts/2012-01-25-new-blog.markdown b/posts/2012-01-25-new-blog.markdown
deleted file mode 100644 (file)
index e661ee3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-title: New Blog
-date: 2012/01/25
-tags: meta
-Hey there, I'm back!
-I'm currently migrating the old blog posts to my new site. Once this is done
-you can expect me to use this blog thingie a little more often.
diff --git a/posts/2012-01-25-new-blog.skr b/posts/2012-01-25-new-blog.skr
new file mode 100644 (file)
index 0000000..4d2e0f8
--- /dev/null
@@ -0,0 +1,11 @@
+(define meta
+  `((title . "New Blog")
+    (date  . ,(string->date* "2012-01-25 00:00"))
+    (tags "meta")))
+ (p [Hey there, I’m back!])
+ (p [I’m currently migrating the old blog posts to my new site. Once
+     this is done you can expect me to use this blog thingie a little
+     more often.]))
diff --git a/posts/2013-01-27-preamp-board-arrived.markdown b/posts/2013-01-27-preamp-board-arrived.markdown
deleted file mode 100644 (file)
index aee96d9..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-title: Stick preamp PCB arrived
-tags: audio,pcb,DIY,preamp,chapman stick,free software
-![One of the boards](/images/posts/pcb-1.jpg)
-Today I received a package from Shenzhen containing ten printed circuit boards.
-I ordered a single board through [a taobao store]( for only
-100&nbsp;RMB (about USD&nbsp;16), but I suppose there is not much of a
-difference between the production costs of ten boards and that of one.
-The board is the heart of my two-channel Chapman Stick preamp / signal router.
-It includes a cross-over circuit for the bass side, so that I can partition the
-bass signal into two frequency ranges that can be routed and processed
-independently. It has three very simple effect inserts (high bass, low bass,
-and melody), two buffered outputs (both signals mixed down to mono or dual
-mono), and a tuner output (which could be used for an on-stage monitor).
-The circuit and the board were designed using the
-[free]( programs
-`gschem` and `pcb` of the excellent
-[gEDA suite]( (For some odd reason `pcb`
-is not available through the official Archlinux repositories; I
-installed it through the Arch User Repository.) You can get my circuit
-diagrams, the PCB layout, and custom footprints through the
-[git repository]( I
-set up for this project.
-The manufacturer only received the exported Gerber files that I checked with
-`gerbv`. Sadly, I didn't realise that the silk screen layer would be printed on
-the bottom side of the single-layer board, so the text on all ten boards is
-mirrored. (I suppose I could get used to saying "TЯƎƧИI", but "YᗡO⅃ƎM" just
-sounds weird.) Now I will have to carefully check the orientation of the
-transistors before soldering them onto the board because I'm not sure whether
-they have been mirrored when I designed the board.
-I'm still missing two or three parts (different component packages and power
-line filtering), but I'll start soldering the first components to one of the
-boards tonight.
diff --git a/posts/2013-01-27-preamp-board-arrived.skr b/posts/2013-01-27-preamp-board-arrived.skr
new file mode 100644 (file)
index 0000000..5888ef8
--- /dev/null
@@ -0,0 +1,50 @@
+(define meta
+  `((title . "Stick preamp PCB arrived")
+    (date  . ,(string->date* "2013-01-27 00:00"))
+    (tags "audio" "pcb" "DIY" "preamp" "chapman stick" "free software")))
+ (figure "pcb-1.jpg" "One of the boards")
+ (p [Today I received a package from Shenzhen containing ten printed
+     circuit boards.  I ordered a single board through ,(ref
+     "" "a taobao store") for only 100,(~)RMB (about
+     USD,(~)16), but I suppose there is not much of a difference
+     between the production costs of ten boards and that of one.])
+ (p [The board is the heart of my two-channel Chapman Stick preamp /
+     signal router.  It includes a cross-over circuit for the bass
+     side, so that I can partition the bass signal into two frequency
+     ranges that can be routed and processed independently.  It has
+     three very simple effect inserts (high bass, low bass, and
+     melody), two buffered outputs (both signals mixed down to mono or
+     dual mono), and a tuner output (which could be used for an
+     on-stage monitor).])
+ (p [The circuit and the board were designed using the ,(ref
+     "" "free") programs
+     ,(code [gschem]) and ,(code [pcb]) of the excellent ,(ref
+     "" "gEDA suite"). (For some odd reason
+     ,(code [pcb]) is not available through the official Archlinux
+     repositories; I installed it through the Arch User Repository.)
+     You can get my circuit diagrams, the PCB layout, and custom
+     footprints through the ,(ref
+     "" "git
+     repository") I set up for this project.])
+ (figure "pcb-2.jpg" "Oops.")
+ (p [The manufacturer only received the exported Gerber files that I
+     checked with ,(code [gerbv]).  Sadly, I didn’t realise that the
+     silk screen layer would be printed on the bottom side of the
+     single-layer board, so the text on all ten boards is mirrored. (I
+     suppose I could get used to saying “TЯƎƧИI”, but “YᗡO⅃ƎM” just
+     sounds weird.)  Now I will have to carefully check the orientation
+     of the transistors before soldering them onto the board because
+     I’m not sure whether they have been mirrored when I designed the
+     board.])
+ (p [I’m still missing two or three parts (different component packages
+     and power line filtering), but I’ll start soldering the first
+     components to one of the boards tonight.]))
diff --git a/posts/2013-05-24-improvisation.markdown b/posts/2013-05-24-improvisation.markdown
deleted file mode 100644 (file)
index 05846f1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-title: Introduction to jazz improvisation
-tags: audio,music,guitar,coursera,learning,jazz
-Since a few weeks I'm learning how to play more interesting jazz solos
-from Gary Burton through his [Coursera]( MOOC
-[Introduction to
-What's great about the course is that it forces me to record solos and
-upload them for peer review.  I don't normally publish practice
-recordings as I'm never quite satisfied with them, but this also means
-that many half-decent ideas are never published at all.
-You can find my growing collection of improvisation recordings in
-fulfilment of the assignments [on
-embedded below:
-<iframe width="100%" height="450" scrolling="no" frameborder="no"
\ No newline at end of file
diff --git a/posts/2013-05-24-improvisation.skr b/posts/2013-05-24-improvisation.skr
new file mode 100644 (file)
index 0000000..051708b
--- /dev/null
@@ -0,0 +1,28 @@
+(define meta
+  `((title . "Introduction to jazz improvisation")
+    (date  . ,(string->date* "2013-05-24 00:00"))
+    (tags "audio" "music" "guitar" "coursera" "learning" "jazz")))
+ (p [Since a few weeks I’m learning how to play more interesting jazz
+     solos from Gary Burton through his ,(ref ""
+     "Coursera") MOOC ,(ref
+     "" "Introduction to
+     Improvisation").])
+ (p [What’s great about the course is that it forces me to record solos
+     and upload them for peer review.  I don’t normally publish
+     practice recordings as I’m never quite satisfied with them, but
+     this also means that many half-decent ideas are never published at
+     all.])
+ (p [You can find my growing collection of improvisation recordings in
+     fulfilment of the assignments ,(ref
+     ""
+     "on SoundCloud"), embedded below:])
+ '(iframe (@ (width "100%")
+             (height "450")
+             (scrolling "no")
+             (frameborder "no")
+             (src ""))))
diff --git a/posts/2013-08-11-hacking-the-wavedrum.markdown b/posts/2013-08-11-hacking-the-wavedrum.markdown
deleted file mode 100644 (file)
index 0046386..0000000
+++ /dev/null
@@ -1,420 +0,0 @@
-title: Hacking the Wavedrum
-tags: DIY,electronics,music,hacking,wavedrum
-The Wavedrum Oriental is a wonderful electronic instrument.  Unlike an
-electronic drum set or drum machines with touch sensitive pads, this
-drum synthesizer's sensors don't merely trigger samples.  The sensors
-rather behave like microphones or the pickup in an electric guitar;
-the signals of the four sensors---one sensor for the drum head, one
-sensor on the left and another on the right of the metal rim, and a
-pressure sensor in the centre of the drum---are used to control drum
-synthesizer algorithms whose output can be mixed with PCM samples.  As
-a result, the instrument feels a lot like a real drum, a feat that
-cannot easily be achieved with devices that use simple
-velocity-sensitive sample triggers.
-For all its magic, the Wavedrum also has a number of flaws.  Most
-prominently, all editing is done through five buttons and an endless
-rotary encoder.  What parameters can be selected by the buttons and
-thus manipulated by the encoder depends entirely on context; one
-button is used to jump to the next parameter page; simultaneously
-pressing a pair of buttons switches between the two edit modes (why
-two?), "global" mode and "live" mode; as one navigates through this
-confusing environment, a three-character seven-segment display
-conjures up magic strings that occasionally resemble abbreviations of
-what appear to be parameter names.  Without a copy of the manual lying
-next to the device, any attempt at deciphering the cryptic
-three-character hints is doomed to fail.
-Another painful flaw is the lack of connectivity.  There is no way to
-export these precious custom programmes that were edited with so much
-difficulty.  There is no way to back up the programmes, nor can one
-share programmes with another Wavedrum.  When the device dies, all
-custom patches go down with it.  Or so it seemed.
-# A look inside the Wavedrum
-Not really knowing what to look for I opened up the Wavedrum in the
-hopes of finding *something* that would allow me to extend the feature
-set of the instrument.  I first took off the control panel.  Only
-three screws have to be loosened to lift the front panel and look
-underneath.  The PCB, however, does not offer much of interest.
-Much more interesting is the main board which is located right
-underneath the drum head.  Removing the rim and the drum head
-apparently is a permitted activity which does not void the
-warranty---the manual includes instructions on how to change the drum
-<img class="full stretch" src="/images/posts/2013/wavedrum-opened.jpg" alt="After removing the rim and the drum head" />
-Once the rim and drum head are out of the way, one can already
-see much of the main board, but access is denied by a transparent
-plastic disk.  In my instrument the plastic disk was only screwed to
-two posts although there are holes for seven screws.  The heads of the
-two screws are covered with adhesive pads that can easily be removed
-to undo the screws.  (Don't worry, the glue on the pads is strong
-enough to put them back on when you're done.)
-**Warning:** if you are following these instructions, at this point, I
-  believe, you might be voiding your warranty.  If you're careful and
-  you don't tell anyone, nobody should ever notice.  Note that I
-  cannot be made responsible for any damage to your device that may
-  result from following these instructions.
-With this warning out of the way, let's move on.
-The main board is very tidy making it easy to understand what's going
-on.  The densely packed section on the right appears to be power
-supply and rim sensor amplification logic.  On the left you can see
-two medium-sized chips, a bulky capacitor and something covered with a
-black, textured tape.  The two chips are RAM (ESMT) and flash memory
-(cFeon), respectively.  The big capacitor buffers the power for the
-two memory chips and the massive DSP on the back of the board.  The
-back side of the board is rather boring as it really only holds the
-DSP chip (ADSP-21375 by Analog Devices).  The board has a somewhat
-unusually great number of test pads (most of which are connected to
-ground, used for automated testing) and quite a few connector pads,
-possibly allowing a hardware debugger to be connected to debug the
-DSP's firmware *in situ*.
-<img class="full stretch" src="/images/posts/2013/wavedrum-mainboard.jpg" alt="The mainboard of the Wavedrum Oriental" />
-# The treasure trove
-What is underneath that black tape on the front, though?  This is
-where things get really interesting (well, to people like me, at
-least).  As I carefully removed the tape I was pleasently surprised to
-see a micro SD card reader underneath.  The card is locked to the
-reading interface to make sure it stays in place during operation.
-Unlock it by shifting the metal brace to the right whereupon it can be
-![The taped-over SD card](/images/posts/2013/wavedrum-card-tape.jpg)
-The 2GB micro SD card is a standard card formatted with a FAT32
-filesystem, making it possible to read it out with a standard card
-reader.  My netbook has a built-in SD card reader only, so I first
-needed to buy an adapter to connect the micro SD card.  This reader is
-a little weird.  It seems that the adapter must be in the reader slot
-on boot or the micro SD card won't be recognised.  (If you're unsure
-whether the card is recognised by your system check the output of
-`dmesg`.)  Eventually, the card was recognised as `/dev/sdb1`.
-(`/dev/sdb` is the SD card reader device itself.)  As this is my only
-Wavedrum and I intend to use it for years to come I decided to be
-especially careful this time and only operate on a *copy* of the card.
-The Wavedrum's card reader is perfectly capable of reading 8GB micro
-SD HC cards, so if you want to play with the data on the card I
-recommend mirroring the original card image onto whatever micro SD
-card you have at your disposal and play with that instead of the
-original card.  To create a block level copy of the card I *did not*
-mount the filesystem and simply executed the following command:
-    dd if=/dev/sdb1 of=wavedrum.img
-This instructs `dd` to copy all blocks from the input device file
-(`if`, i.e. `/dev/sdb1`) to the output file (`of`) of the name
-`wavedrum.img`.  Dependent on the number of disks on your system, the
-input device file may have a different name.  Check the output of
-`dmesg | tail` as you connect the card reader to see which device node
-is created for the micro SD card. Note that this blindly copies
-*everything* on the micro SD card, not just files that are available
-through the FAT32 filesystem.  Hence, the size of the image is quite a
-bit larger than the sum of all files on the mounted image (502,145,536
-bytes vs 234,479,878 bytes).
-Before continuing, please put the micro SD card back into the
-Wavedrum's card reader and lock it to prevent it from being damaged
-(things can get messy, you know).  Going forward, we only need to
-mount the image to access the data stored on the card.  Run the following as
-root to mount the card image as a read-only filesystem:
-    mkdir wavedrum
-    mount -o loop,ro wavedrum.img wavedrum/
-Let's take a look at the files on the card:
-<ul class="tree">
-<li><b class="NORM">/</b></li>
-<li>├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">CALIB.BOR</b></li>
-<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">Factory</b></li>
-<li>│   ├── [192K]&nbsp;&nbsp;<b class="EXEC">F_INFO.BOR</b></li>
-<li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_H.BOR</b></li>
-<li>│   ├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">F_INST_R.BOR</b></li>
-<li>│   ├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">F_PROG.BOR</b></li>
-<li>│   └── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">F_USER.BOR</b></li>
-<li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_H.BOR</b></li>
-<li>├── [&nbsp;57K]&nbsp;&nbsp;<b class="EXEC">INST_R.BOR</b></li>
-<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">LOOP</b></li>
-<li>│   ├── [744K]&nbsp;&nbsp;<b class="EXEC">LOOP0001.BIN</b></li>
-<li>│   ├── [402K]&nbsp;&nbsp;<b class="EXEC">LOOP0002.BIN</b></li>
-<li>│   ├── [750K]&nbsp;&nbsp;<b class="EXEC">LOOP0003.BIN</b></li>
-<li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0138.BIN</b></li>
-<li>│   ├── [173K]&nbsp;&nbsp;<b class="EXEC">LOOP0139.BIN</b></li>
-<li>│   └── [234K]&nbsp;&nbsp;<b class="EXEC">LOOP0140.BIN</b></li>
-<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">PRE_PROG.BOR</b></li>
-<li>├── [&nbsp;16K]&nbsp;&nbsp;<b class="DIR">SYSTEM</b></li>
-<li>│   ├── [&nbsp;&nbsp;16]&nbsp;&nbsp;<b class="EXEC">VERSION.INF</b></li>
-<li>│   ├── [1.0M]&nbsp;&nbsp;<b class="EXEC">WDORM202.BIN</b></li>
-<li>│   └── [8.0K]&nbsp;&nbsp;<b class="EXEC">WDORS110.BIN</b></li>
-<li>├── [&nbsp;&nbsp;88]&nbsp;&nbsp;<b class="EXEC">USER.BOR</b></li>
-<li>├── [157M]&nbsp;&nbsp;<b class="EXEC">WD2_DATA.BOR</b></li>
-<li>├── [192K]&nbsp;&nbsp;<b class="EXEC">WD2_INFO.BOR</b></li>
-<li>└── [&nbsp;16K]&nbsp;&nbsp;<b class="EXEC">WD2_PROG.BOR</b></li>
-The files in the `Factory` directory contain initialisation data.
-When a factory reset is performed, the customised versions of these
-files in the root directory are overwritten with the versions
-contained in the `Factory` directory.  All initial programmes that
-come with the Wavedrum are stored in `Factory/F_PROG.BOR`; once
-programmes have been edited `WD2_PROG.BOR` in the root directory will
-differ from `Factory/F_PROG.BOR`.  (More about the nature of these
-differences later.)  `PRE_PROG.BOR` is the same as
-`Factory/F_PROG.BOR` and is probably used to make the original factory
-presets available in addition to custom programmes, starting at
-position `P.00`, the programme slot after `149`.
-The initial mapping of presets to any of the 12 slots (3 banks with 4
-slots each) is stored in `Factory/F_USER.BOR`.  Initially, `USER.BOR`
-in the root directory will be identical to this file.  The format of
-this file is rather simple:
-    00000000 |  00 00 00 64 00 00 00 67  00 00 00 7b 00 00 00 6c
-    00000010 |  00 00 00 65 00 00 00 68  00 00 00 71 00 00 00 7a
-    00000020 |  00 00 00 84 00 00 00 8c  00 00 00 8b 00 00 00 95
-    00000030 |  00 00 00 00 00 00 00 00  00 00 00 75 00 00 00 26
-    00000040 |  00 00 00 07 00 00 00 14  00 00 00 07 00 00 00 14
-    00000050 |  00 00 00 05 00 00 00 64
-Every 8 digit block (4 byte) is used for one slot.  We can see that
-the first slot in bank A is set to programme 100 (0x64 hex), the
-second to programme 103 (0x67 hex) and so on.  As the Wavedrum only
-allows for 12 slots to store programme identifiers, only the first 48
-bytes are used for programmes.  The remaining 40 bytes (starting at
-0x30) are used for global parameters that can be adjusted in "global"
-editing mode.  The global parameters are stored in this order:
-  - delay pan
-  - aux input level
-  - loop phrase select
-  - loop play mode (off=38)
-  - head sensor threshold
-  - head sensor sensitivity
-  - rim sensor threshold
-  - rim sensor sensitivity
-  - pressure sensor threshold
-  - pressure maximum
-I don't know yet what purpose `F_INST_H.BOR` and `F_INST_R.BOR`
-fulfil, but it is clear that the former relates to settings for the
-drum head while the latter contains similar settings for the rim.
-Even after editing a few programmes, `INST_H.BOR` and `INST_R.BOR` in
-the root directory were still identical to their counterparts in the
-`Factory` directory.
-The `CALIB.BOR` appears to contain calibration information for the
-head and rim sensors.  This is different from the calibration
-performed by adjusting the four global paramaters for sensor threshold
-and sensitivity.  I have not been able to edit these settings through
-the Wavedrum so far, so these probably are factory settings.
-## Audio data
-All files in the `LOOP` directory as well as `WD2_DATA.BOR` contain
-raw audio data.  Unfortunately, I haven't quite figured out the format
-yet, but you can listen to the clearly recognisable loop patterns with
-`play` (part of the [SoX]( applications):
-    find LOOP -name "*.BIN" -print |\
-      xargs -I XXX \
-      play -t raw -r 48k -b 16 -e signed-integer -c 1 XXX
-Obviously, this isn't quite correct.  I'm interpreting every 16 bits
-as a sample in signed integer format, but the sound is distorted and
-far from the realistic instrument sound when playing back the loops
-through the Wavedrum.
-All loops start with this 44 byte long header:
-    04 dc 10 d3 uU vV 5W 95  01 d4 00 d0 30 f8 22 b5
-    46 95 56 95 57 95 57 95  d6 2e 56 95 56 e2 57 95
-    54 95 46 95 32 f4 22 f4  xX yY 5W 95
-With a few exceptions (namely 0009, 0025, 0027, 0030, 0033, 0036,
-0049, 0054, 0064, 0082, 0091, 0103, 0104, 0107, 0108, 0127, 0128,
-0129, 0130, 0131, 0132, 0135), vV equals yY in most loops. It seems
-that loops with the same number of bytes have the exact same numbers
-for uU, vV, W, xX, and yY.  This is especially apparent in the
-loops 0127 to 0132 (inclusive), which are all 192,010 bytes long and
-all have the values 54:7b:54 for uU:vV:5W and 88:78:54 for xX:yY:5W.
-Clearly, more work is required to figure out the complete format of
-these loop files.  Once this is understood we could use custom loops
-with the Wavedrum.
-The raw audio data in `WD2_DATA.BOR` suffers from the same problems.
-Although the data can be interpreted as raw audio, the sound is
-distorted and playback is unnaturally fast.
-## System files
-I don't know what `SYSTEM/WDORS110.BIN` is used for.  The only useful
-string contained in the file is "BOOTABLE".  Your guess is as good as
-mine as to what it does.
-`SYSTEM/VERSION.INF` is only 16 bytes short and pretty boring as it
-contains just what the name implies: version numbers.
-    02 02 01 10 02 02 00 00  57 44 4f 52 00 00 00 00
-This string of numbers is interpreted as follows: firmware version
-2.02, sub-version 1.10, data version 2.02 (followed by two empty
-bytes); 57 44 4f 52 (hex for "WDOR") stands for "Wavedrum Oriental"
-(followed by four empty bytes).  You can have the Wavedrum display all
-its version numbers by pressing the button labelled "Global" when
-powering on the device. Note that the file name `WDORS110.BIN`
-references the version number 1.10, while `WDORM202.BIN` references
-the firmware version number 2.02.
-`SYSTEM/WDORM202.BIN` contains the firmware of the Wavedrum Oriental.
-There are many interesting strings and binary patterns in the file,
-but I'm still a long way from *understanding* how it works.  To view
-the strings with the `strings` command, you have to specify the
-encoding as 32-bit little endian:
-    strings --encoding L SYSTEM/WDORM202.BIN
-Some of the strings embedded in the firmware are file names, some of
-which are not available on the micro SD card.  This includes the
-following files: SYS00000.BIN, SYS00100.BIN, SYSTEM/WDORS100.BIN,
-# The programme format
-Looking at the hexdump of the file `WD2_PROG.BOR` which holds all custom
-presets, I couldn't find any obvious patterns in the file, so I
-resorted to editing a single programme, setting particular consecutive
-parameters to easily recognisable sequences of values (such as 100,
-99, 98, and 97 for hd1, hd2, hd3, and hd4) and locating the changes in
-the hexdump.
-<img class="full stretch" src="/images/posts/2013/wavedrum-diff.png" alt="Analysing the programme format by changing values and looking at the differences" />
-This procedure has allowed me to figure out in what order the
-parameters are stored in the file.  Each programme is exactly 54
-16-bit words long; each parameter takes up exactly 16 bits.  Negative
-values are stored in [two's
-complement]( format
-(e.g. negative six is stored as 0xFFFA).  The file is exactly 16200
-bytes long which is just enough to hold 150 custom programmes, each
-taking up 108 bytes.
-I'm currently writing a Haskell library to parse / build progammes and
-parameters.  The code is available for
-[here]( under the
-[GNU GPLv3](
-The parameters are stored in this order:
-|identifier |  mode  | target              | name                         |
-|07.1       | Edit 1 | head algorithm      | Pressure curve               |
-|type       | Edit 2 | --                  | Pre EQ                       |
-|01.1       | Edit 1 | head algorithm      | Tune                         |
-|02.1       | Edit 1 | head algorithm      | Decay                        |
-|03.1       | Edit 1 | head algorithm      | Level                        |
-|04.1       | Edit 1 | head algorithm      | Pan                          |
-|05.1       | Edit 1 | head algorithm      | Algorithm select             |
-|hd.1       | Edit 2 | head algorithm      | Algorithm parameter 1        |
-|hd.2       | Edit 2 | head algorithm      | Algorithm parameter 2        |
-|hd.3       | Edit 2 | head algorithm      | Algorithm parameter 3        |
-|hd.4       | Edit 2 | head algorithm      | Algorithm parameter 4        |
-|hd.5       | Edit 2 | head algorithm      | Algorithm parameter 5        |
-|hd.6       | Edit 2 | head algorithm      | Algorithm parameter 6        |
-|hd.7       | Edit 2 | head algorithm      | Algorithm parameter 7        |
-|hd.8       | Edit 2 | head algorithm      | Algorithm parameter 8        |
-|01.3       | Edit 1 | rim algorithm       | Tune                         |
-|02.3       | Edit 1 | rim algorithm       | Decay                        |
-|03.3       | Edit 1 | rim algorithm       | Level                        |
-|04.3       | Edit 1 | rim algorithm       | Pan                          |
-|05.3       | Edit 1 | rim algorithm       | Algorithm select             |
-|rm.1       | Edit 2 | rim algorithm       | Algorithm parameter 1        |
-|rm.2       | Edit 2 | rim algorithm       | Algorithm parameter 2        |
-|rm.3       | Edit 2 | rim algorithm       | Algorithm parameter 3        |
-|rm.4       | Edit 2 | rim algorithm       | Algorithm parameter 4        |
-|rm.5       | Edit 2 | rim algorithm       | Algorithm parameter 5        |
-|rm.6       | Edit 2 | rim algorithm       | Algorithm parameter 6        |
-|rm.7       | Edit 2 | rim algorithm       | Algorithm parameter 7        |
-|rm.8       | Edit 2 | rim algorithm       | Algorithm parameter 8        |
-|01.2       | Edit 1 | head PCM instrument | Tune                         |
-|02.2       | Edit 1 | head PCM instrument | Decay                        |
-|03.2       | Edit 1 | head PCM instrument | Level                        |
-|04.2       | Edit 1 | head PCM instrument | Pan                          |
-|05.2       | Edit 1 | head PCM instrument | PCM instrument select        |
-|06.2       | Edit 1 | head PCM instrument | Velocity curve               |
-|07.2       | Edit 1 | head PCM instrument | Pressure curve               |
-|08.2       | Edit 1 | head PCM instrument | Pressure tune                |
-|09.2       | Edit 1 | head PCM instrument | Pressure decay               |
-|01.4       | Edit 1 | rim PCM instrument  | Tune                         |
-|02.4       | Edit 1 | rim PCM instrument  | Decay                        |
-|03.4       | Edit 1 | rim PCM instrument  | Level                        |
-|04.4       | Edit 1 | rim PCM instrument  | Pan                          |
-|05.4       | Edit 1 | rim PCM instrument  | PCM instrument select        |
-|06.4       | Edit 1 | rim PCM instrument  | Velocity curve               |
-|07.4       | Edit 1 | rim PCM instrument  | Pressure curve               |
-|08.4       | Edit 1 | rim PCM instrument  | Pressure tune                |
-|09.4       | Edit 1 | rim PCM instrument  | Pressure decay               |
-|10.1       | Edit 1 | --                  | Reverb type                  |
-|10.2       | Edit 1 | --                  | Reverb effect level          |
-|10.3       | Edit 1 | --                  | Reverb decay time            |
-|10.4       | Edit 1 | --                  | Reverb frequency damping     |
-|11.3       | Edit 1 | --                  | Delay feedback               |
-|11.2       | Edit 1 | --                  | Delay effect level           |
-|11.1       | Edit 1 | --                  | Delay time                   |
-|11.4       | Edit 1 | --                  | Delay frequency damping      |
-# Thanks
-The following tools have proven indispensable in the analysis:
-- [`calc`](, a calculator
-  for the command line supporting hexadecimal representations of
-  numbers (both input and output using the `base` and `base2`
-  functions)
-- [`vbindiff`](, a tool to visualise
-  differences between two binary files with a split-screen hexadecimal
-  display
-- [`ghex`](, a simple hexadecimal editor
-  supporting pattern search and highlighting
-# Call for help
-If you own an earlier model of the Wavedrum or the latest Wavedrum
-Global Edition, I would be *very* happy if you could send me a
-block-level copy of the SD card (see above for instructions).  This
-would allow me to understand the firmware better and maybe even make
-it possible to upgrade an older Wavedrum to the latest version (taking
-into account possible hardware differences, such as differing memory
-Please send a link to the micro SD card image to
-<span class="obfuscated">sflbep,xbwfesvnAfmfqimz/ofu</span>.
-Read [more posts about the Wavedrum here](
diff --git a/posts/2013-08-11-hacking-the-wavedrum.skr b/posts/2013-08-11-hacking-the-wavedrum.skr
new file mode 100644 (file)
index 0000000..39115a3
--- /dev/null
@@ -0,0 +1,454 @@
+(define meta
+  `((title . "Hacking the Wavedrum")
+    (date  . ,(string->date* "2013-08-11 00:00"))
+    (tags "DIY" "electronics" "music" "hacking" "wavedrum")))
+(define (row id mode target name)
+  `(tr (td (@ (align "right")) ,id)
+       (td (@ (align "left")) ,mode)
+       (td (@ (align "left")) ,target)
+       (td (@ (align "left")) ,name)))
+ (p [The Wavedrum Oriental is a wonderful electronic instrument.
+     Unlike an electronic drum set or drum machines with touch
+     sensitive pads, this drum synthesizer’s sensors don’t merely
+     trigger samples.  The sensors rather behave like microphones or
+     the pickup in an electric guitar; the signals of the four
+     sensors—one sensor for the drum head, one sensor on the left and
+     another on the right of the metal rim, and a pressure sensor in
+     the centre of the drum—are used to control drum synthesizer
+     algorithms whose output can be mixed with PCM samples.  As a
+     result, the instrument feels a lot like a real drum, a feat that
+     cannot easily be achieved with devices that use simple
+     velocity-sensitive sample triggers.])
+ (p [For all its magic, the Wavedrum also has a number of flaws.  Most
+     prominently, all editing is done through five buttons and an
+     endless rotary encoder.  What parameters can be selected by the
+     buttons and thus manipulated by the encoder depends entirely on
+     context; one button is used to jump to the next parameter page;
+     simultaneously pressing a pair of buttons switches between the
+     two edit modes (why two?), “global” mode and “live” mode; as one
+     navigates through this confusing environment, a three-character
+     seven-segment display conjures up magic strings that occasionally
+     resemble abbreviations of what appear to be parameter names.
+     Without a copy of the manual lying next to the device, any
+     attempt at deciphering the cryptic three-character hints is
+     doomed to fail.])
+ (p [Another painful flaw is the lack of connectivity.  There is no
+     way to export these precious custom programmes that were edited
+     with so much difficulty.  There is no way to back up the
+     programmes, nor can one share programmes with another Wavedrum.
+     When the device dies, all custom patches go down with it.  Or so
+     it seemed.])
+ (h2 [A look inside the Wavedrum])
+ (p [Not really knowing what to look for I opened up the Wavedrum in
+     the hopes of finding ,(em [something]) that would allow me to
+     extend the feature set of the instrument.  I first took off the
+     control panel.  Only three screws have to be loosened to lift the
+     front panel and look underneath.  The PCB, however, does not
+     offer much of interest.])
+ (p [Much more interesting is the main board which is located right
+     underneath the drum head.  Removing the rim and the drum head
+     apparently is a permitted activity which does not void the
+     warranty—the manual includes instructions on how to change the
+     drum head.])
+ (wide-img "2013/wavedrum-opened.jpg"
+           "After removing the rim and the drum head")
+ (p [Once the rim and drum head are out of the way, one can already
+     see much of the main board, but access is denied by a transparent
+     plastic disk.  In my instrument the plastic disk was only screwed
+     to two posts although there are holes for seven screws.  The
+     heads of the two screws are covered with adhesive pads that can
+     easily be removed to undo the screws.  (Don’t worry, the glue on
+     the pads is strong enough to put them back on when you’re done.)])
+ (list 'warning [,(strong [Warning:]) if you are following these
+  instructions, at this point, I believe, you might be voiding your
+  warranty.  If you’re careful and you don’t tell anyone, nobody
+  should ever notice.  Note that I cannot be made responsible for any
+  damage to your device that may result from following these
+  instructions.])
+ (p [With this warning out of the way, let’s move on.])
+ (p [The main board is very tidy making it easy to understand what’s
+     going on.  The densely packed section on the right appears to be
+     power supply and rim sensor amplification logic.  On the left you
+     can see two medium-sized chips, a bulky capacitor and something
+     covered with a black, textured tape.  The two chips are RAM
+     (ESMT) and flash memory (cFeon), respectively.  The big capacitor
+     buffers the power for the two memory chips and the massive DSP on
+     the back of the board.  The back side of the board is rather
+     boring as it really only holds the DSP chip (ADSP-21375 by Analog
+     Devices).  The board has a somewhat unusually great number of
+     test pads (most of which are connected to ground, used for
+     automated testing) and quite a few connector pads, possibly
+     allowing a hardware debugger to be connected to debug the DSP’s
+     firmware ,(em [in situ]).])
+ (wide-img "2013/wavedrum-mainboard.jpg"
+           "The mainboard of the Wavedrum Oriental")
+ (h2 [The treasure trove])
+ (p [What is underneath that black tape on the front, though?  This is
+     where things get really interesting (well, to people like me, at
+     least).  As I carefully removed the tape I was pleasently
+     surprised to see a micro SD card reader underneath.  The card is
+     locked to the reading interface to make sure it stays in place
+     during operation.  Unlock it by shifting the metal brace to the
+     right whereupon it can be lifted.])
+ (figure "2013/wavedrum-card-tape.jpg" "The taped-over SD card")
+ (p [The 2GB micro SD card is a standard card formatted with a FAT32
+     filesystem, making it possible to read it out with a standard
+     card reader.  My netbook has a built-in SD card reader only, so I
+     first needed to buy an adapter to connect the micro SD card.
+     This reader is a little weird.  It seems that the adapter must be
+     in the reader slot on boot or the micro SD card won’t be
+     recognised.  (If you’re unsure whether the card is recognised by
+     your system check the output of ,(code [dmesg]).)  Eventually,
+     the card was recognised as ,(code [/dev/sdb1]).  (,(code
+     [/dev/sdb]) is the SD card reader device itself.)  As this is my
+     only Wavedrum and I intend to use it for years to come I decided
+     to be especially careful this time and only operate on a ,(em
+     [copy]) of the card.  The Wavedrum’s card reader is perfectly
+     capable of reading 8GB micro SD HC cards, so if you want to play
+     with the data on the card I recommend mirroring the original card
+     image onto whatever micro SD card you have at your disposal and
+     play with that instead of the original card.  To create a block
+     level copy of the card I ,(em [did not]) mount the filesystem and
+     simply executed the following command:])
+ (pre (code [dd if=/dev/sdb1 of=wavedrum.img]))
+ (p [This instructs ,(code [dd]) to copy all blocks from the input
+     device file (,(code [if]), i.e. ,(code [/dev/sdb1])) to the
+     output file (,(code [of])) of the name ,(code [wavedrum.img]).
+     Dependent on the number of disks on your system, the input device
+     file may have a different name.  Check the output of ,(code
+     [dmesg | tail]) as you connect the card reader to see which
+     device node is created for the micro SD card. Note that this
+     blindly copies ,(em [everything]) on the micro SD card, not just
+     files that are available through the FAT32 filesystem.  Hence,
+     the size of the image is quite a bit larger than the sum of all
+     files on the mounted image (502,145,536 bytes vs 234,479,878
+     bytes).])
+ (p [Before continuing, please put the micro SD card back into the
+     Wavedrum’s card reader and lock it to prevent it from being
+     damaged (things can get messy, you know).  Going forward, we only
+     need to mount the image to access the data stored on the card.
+     Run the following as root to mount the card image as a read-only
+     filesystem:])
+ (pre (code [mkdir wavedrum
+mount -o loop,ro wavedrum.img wavedrum/]))
+ (p [Let’s take a look at the files on the card:])
+ '(ul (@ (class "tree"))
+      (li (span (@ (class "NORM")) "/" ))
+      (li "├── (  16)  "     (span (@ (class "EXEC")) "CALIB.BOR"))
+      (li "├── ( 16K)  "     (span (@ (class "DIR"))  "Factory"))
+      (li "│   ├── (192K)  " (span (@ (class "EXEC")) "F_INFO.BOR"))
+      (li "│   ├── ( 57K)  " (span (@ (class "EXEC")) "F_INST_H.BOR"))
+      (li "│   ├── ( 57K)  " (span (@ (class "EXEC")) "F_INST_R.BOR"))
+      (li "│   ├── ( 16K)  " (span (@ (class "EXEC")) "F_PROG.BOR"))
+      (li "│   └── (  88)  " (span (@ (class "EXEC")) "F_USER.BOR"))
+      (li "├── ( 57K)  "     (span (@ (class "EXEC")) "INST_H.BOR"))
+      (li "├── ( 57K)  "     (span (@ (class "EXEC")) "INST_R.BOR"))
+      (li "├── ( 16K)  "     (span (@ (class "DIR"))  "LOOP"))
+      (li "│   ├── (744K)  " (span (@ (class "EXEC")) "LOOP0001.BIN"))
+      (li "│   ├── (402K)  " (span (@ (class "EXEC")) "LOOP0002.BIN"))
+      (li "│   ├── (750K)  " (span (@ (class "EXEC")) "LOOP0003.BIN"))
+      (li "...")
+      (li "│   ├── (173K)  " (span (@ (class "EXEC")) "LOOP0138.BIN"))
+      (li "│   ├── (173K)  " (span (@ (class "EXEC")) "LOOP0139.BIN"))
+      (li "│   └── (234K)  " (span (@ (class "EXEC")) "LOOP0140.BIN"))
+      (li "├── ( 16K)  "     (span (@ (class "EXEC")) "PRE_PROG.BOR"))
+      (li "├── ( 16K)  "     (span (@ (class "DIR"))  "SYSTEM"))
+      (li "│   ├── (  16)  " (span (@ (class "EXEC")) "VERSION.INF"))
+      (li "│   ├── (1.0M)  " (span (@ (class "EXEC")) "WDORM202.BIN"))
+      (li "│   └── (8.0K)  " (span (@ (class "EXEC")) "WDORS110.BIN"))
+      (li "├── (  88)  "     (span (@ (class "EXEC")) "USER.BOR"))
+      (li "├── (157M)  "     (span (@ (class "EXEC")) "WD2_DATA.BOR"))
+      (li "├── (192K)  "     (span (@ (class "EXEC")) "WD2_INFO.BOR"))
+      (li "└── ( 16K)  "     (span (@ (class "EXEC")) "WD2_PROG.BOR")))
+ (p [The files in the ,(code [Factory]) directory contain
+     initialisation data.  When a factory reset is performed, the
+     customised versions of these files in the root directory are
+     overwritten with the versions contained in the ,(code [Factory])
+     directory.  All initial programmes that come with the Wavedrum
+     are stored in ,(code [Factory/F_PROG.BOR]); once programmes have
+     been edited ,(code [WD2_PROG.BOR]) in the root directory will
+     differ from ,(code [Factory/F_PROG.BOR]).  (More about the nature
+     of these differences later.)  ,(code [PRE_PROG.BOR]) is the same
+     as ,(code [Factory/F_PROG.BOR]) and is probably used to make the
+     original factory presets available in addition to custom
+     programmes, starting at position ,(code [P.00]), the programme
+     slot after ,(code [149]).])
+ (p [The initial mapping of presets to any of the 12 slots (3 banks
+     with 4 slots each) is stored in ,(code [Factory/F_USER.BOR]).
+     Initially, ,(code [USER.BOR]) in the root directory will be
+     identical to this file.  The format of this file is rather
+     simple:])
+ (pre (code [00000000 |  00 00 00 64 00 00 00 67  00 00 00 7b 00 00 00 6c
+00000010 |  00 00 00 65 00 00 00 68  00 00 00 71 00 00 00 7a
+00000020 |  00 00 00 84 00 00 00 8c  00 00 00 8b 00 00 00 95
+00000030 |  00 00 00 00 00 00 00 00  00 00 00 75 00 00 00 26
+00000040 |  00 00 00 07 00 00 00 14  00 00 00 07 00 00 00 14
+00000050 |  00 00 00 05 00 00 00 64]))
+ (p [Every 8 digit block (4 byte) is used for one slot.  We can see
+     that the first slot in bank A is set to programme 100 (0x64 hex),
+     the second to programme 103 (0x67 hex) and so on.  As the
+     Wavedrum only allows for 12 slots to store programme identifiers,
+     only the first 48 bytes are used for programmes.  The remaining
+     40 bytes (starting at 0x30) are used for global parameters that
+     can be adjusted in “global” editing mode.  The global parameters
+     are stored in this order:])
+ (ul
+  (li [delay pan])
+  (li [aux input level])
+  (li [loop phrase select])
+  (li [loop play mode (off=38)])
+  (li [head sensor threshold])
+  (li [head sensor sensitivity])
+  (li [rim sensor threshold])
+  (li [rim sensor sensitivity])
+  (li [pressure sensor threshold])
+  (li [pressure maximum]))
+ (p [I don’t know yet what purpose ,(code [F_INST_H.BOR]) and ,(code
+     [F_INST_R.BOR]) serve, but it is clear that the former relates to
+     settings for the drum head while the latter contains similar
+     settings for the rim.  Even after editing a few programmes,
+     ,(code [INST_H.BOR]) and ,(code [INST_R.BOR]) in the root
+     directory were still identical to their counterparts in the
+     ,(code [Factory]) directory.])
+ (p [The ,(code [CALIB.BOR]) appears to contain calibration
+     information for the head and rim sensors.  This is different from
+     the calibration performed by adjusting the four global paramaters
+     for sensor threshold and sensitivity.  I have not been able to
+     edit these settings through the Wavedrum so far, so these
+     probably are factory settings.])
+ (h2 [Audio data])
+ (p [All files in the ,(code [LOOP]) directory as well as ,(code
+     [WD2_DATA.BOR]) contain raw audio data.  Unfortunately, I haven’t
+     quite figured out the format yet, but you can listen to the
+     clearly recognisable loop patterns with ,(code [play]) (part of
+     the ,(ref "" "SoX") applications):])
+ (pre (code [find LOOP -name "*.BIN" -print |\\
+  xargs -I XXX \\
+  play -t raw -r 48k -b 16 -e signed-integer -c 1 XXX]))
+ (p [Obviously, this isn’t quite correct.  I’m interpreting every 16
+     bits as a sample in signed integer format, but the sound is
+     distorted and far from the realistic instrument sound when
+     playing back the loops through the Wavedrum.])
+ (p [All loops start with this 44 byte long header:])
+ (pre (code [04 dc 10 d3 uU vV 5W 95  01 d4 00 d0 30 f8 22 b5
+46 95 56 95 57 95 57 95  d6 2e 56 95 56 e2 57 95
+54 95 46 95 32 f4 22 f4  xX yY 5W 95]))
+ (p [With a few exceptions (namely 0009, 0025, 0027, 0030, 0033, 0036,
+     0049, 0054, 0064, 0082, 0091, 0103, 0104, 0107, 0108, 0127, 0128,
+     0129, 0130, 0131, 0132, 0135), vV equals yY in most loops. It
+     seems that loops with the same number of bytes have the exact
+     same numbers for uU, vV, W, xX, and yY.  This is especially
+     apparent in the loops 0127 to 0132 (inclusive), which are all
+     192,010 bytes long and all have the values 54:7b:54 for uU:vV:5W
+     and 88:78:54 for xX:yY:5W.])
+ (p [Clearly, more work is required to figure out the complete format
+     of these loop files.  Once this is understood we could use custom
+     loops with the Wavedrum.])
+ (p [The raw audio data in ,(code [WD2_DATA.BOR]) suffers from the
+     same problems.  Although the data can be interpreted as raw
+     audio, the sound is distorted and playback is unnaturally fast.])
+ (h2 [System files])
+ (p [I don’t know what ,(code [SYSTEM/WDORS110.BIN]) is used for.  The
+     only useful string contained in the file is “BOOTABLE”.  Your
+     guess is as good as mine as to what it does.])
+ (p [,(code [SYSTEM/VERSION.INF]) is only 16 bytes short and pretty
+     boring as it contains just what the name implies: version
+     numbers.])
+ (pre (code [02 02 01 10 02 02 00 00  57 44 4f 52 00 00 00 00]))
+ (p [This string of numbers is interpreted as follows: firmware
+     version 2.02, sub-version 1.10, data version 2.02 (followed by
+     two empty bytes); 57 44 4f 52 (hex for “WDOR”) stands for
+     “Wavedrum Oriental” (followed by four empty bytes).  You can have
+     the Wavedrum display all its version numbers by pressing the
+     button labelled “Global” when powering on the device. Note that
+     the file name ,(code [WDORS110.BIN]) references the version
+     number 1.10, while ,(code [WDORM202.BIN]) references the firmware
+     version number 2.02.])
+ (p [,(code [SYSTEM/WDORM202.BIN]) contains the firmware of the
+     Wavedrum Oriental.  There are many interesting strings and binary
+     patterns in the file, but I’m still a long way from ,(em
+     [understanding]) how it works.  To view the strings with the
+     ,(code [strings]) command, you have to specify the encoding as
+     32-bit little endian:])
+ (pre (code [strings --encoding L SYSTEM/WDORM202.BIN]))
+ (p [Some of the strings embedded in the firmware are file names, some
+     of which are not available on the micro SD card.  This includes
+     the following files: SYS00000.BIN, SYS00100.BIN,
+     and SUBXXXXX.BIN (a pattern?).])
+ (h2 [The programme format])
+ (p [Looking at the hexdump of the file ,(code [WD2_PROG.BOR]) which
+     holds all custom presets, I couldn’t find any obvious patterns in
+     the file, so I resorted to editing a single programme, setting
+     particular consecutive parameters to easily recognisable
+     sequences of values (such as 100, 99, 98, and 97 for hd1, hd2,
+     hd3, and hd4) and locating the changes in the hexdump.])
+ (wide-img "2013/wavedrum-diff.png"
+           "Analysing the programme format by changing values and looking at the differences")
+ (p [This procedure has allowed me to figure out in what order the
+     parameters are stored in the file.  Each programme is exactly 54
+     16-bit words long; each parameter takes up exactly 16 bits.
+     Negative values are stored in ,(ref
+     "" "two’s
+     complement") format (e.g. negative six is stored as 0xFFFA).  The
+     file is exactly 16200 bytes long which is just enough to hold 150
+     custom programmes, each taking up 108 bytes.])
+ (p [I’m currently writing a Haskell library to parse / build
+     progammes and parameters.  The code is available for ,(ref
+     "" "free") ,(ref
+     "" "here") under
+     the ,(ref "" "GNU GPLv3").])
+ (p [The parameters are stored in this order:])
+ (table :align '("right")
+        :headers '("identifier" "mode" "target" "name")
+        :rows
+        '(("07.1" "Edit 1" "head algorithm"      "Pressure curve")
+          ("type" "Edit 2" "–"                   "Pre EQ")
+          ("01.1" "Edit 1" "head algorithm"      "Tune")
+          ("02.1" "Edit 1" "head algorithm"      "Decay")
+          ("03.1" "Edit 1" "head algorithm"      "Level")
+          ("04.1" "Edit 1" "head algorithm"      "Pan")
+          ("05.1" "Edit 1" "head algorithm"      "Algorithm select")
+          ("hd.1" "Edit 2" "head algorithm"      "Algorithm parameter 1")
+          ("hd.2" "Edit 2" "head algorithm"      "Algorithm parameter 2")
+          ("hd.3" "Edit 2" "head algorithm"      "Algorithm parameter 3")
+          ("hd.4" "Edit 2" "head algorithm"      "Algorithm parameter 4")
+          ("hd.5" "Edit 2" "head algorithm"      "Algorithm parameter 5")
+          ("hd.6" "Edit 2" "head algorithm"      "Algorithm parameter 6")
+          ("hd.7" "Edit 2" "head algorithm"      "Algorithm parameter 7")
+          ("hd.8" "Edit 2" "head algorithm"      "Algorithm parameter 8")
+          ("01.3" "Edit 1" "rim algorithm"       "Tune")
+          ("02.3" "Edit 1" "rim algorithm"       "Decay")
+          ("03.3" "Edit 1" "rim algorithm"       "Level")
+          ("04.3" "Edit 1" "rim algorithm"       "Pan")
+          ("05.3" "Edit 1" "rim algorithm"       "Algorithm select")
+          ("rm.1" "Edit 2" "rim algorithm"       "Algorithm parameter 1")
+          ("rm.2" "Edit 2" "rim algorithm"       "Algorithm parameter 2")
+          ("rm.3" "Edit 2" "rim algorithm"       "Algorithm parameter 3")
+          ("rm.4" "Edit 2" "rim algorithm"       "Algorithm parameter 4")
+          ("rm.5" "Edit 2" "rim algorithm"       "Algorithm parameter 5")
+          ("rm.6" "Edit 2" "rim algorithm"       "Algorithm parameter 6")
+          ("rm.7" "Edit 2" "rim algorithm"       "Algorithm parameter 7")
+          ("rm.8" "Edit 2" "rim algorithm"       "Algorithm parameter 8")
+          ("01.2" "Edit 1" "head PCM instrument" "Tune")
+          ("02.2" "Edit 1" "head PCM instrument" "Decay")
+          ("03.2" "Edit 1" "head PCM instrument" "Level")
+          ("04.2" "Edit 1" "head PCM instrument" "Pan")
+          ("05.2" "Edit 1" "head PCM instrument" "PCM instrument select")
+          ("06.2" "Edit 1" "head PCM instrument" "Velocity curve")
+          ("07.2" "Edit 1" "head PCM instrument" "Pressure curve")
+          ("08.2" "Edit 1" "head PCM instrument" "Pressure tune")
+          ("09.2" "Edit 1" "head PCM instrument" "Pressure decay")
+          ("01.4" "Edit 1" "rim PCM instrument"  "Tune")
+          ("02.4" "Edit 1" "rim PCM instrument"  "Decay")
+          ("03.4" "Edit 1" "rim PCM instrument"  "Level")
+          ("04.4" "Edit 1" "rim PCM instrument"  "Pan")
+          ("05.4" "Edit 1" "rim PCM instrument"  "PCM instrument select")
+          ("06.4" "Edit 1" "rim PCM instrument"  "Velocity curve")
+          ("07.4" "Edit 1" "rim PCM instrument"  "Pressure curve")
+          ("08.4" "Edit 1" "rim PCM instrument"  "Pressure tune")
+          ("09.4" "Edit 1" "rim PCM instrument"  "Pressure decay")
+          ("10.1" "Edit 1" "–"                   "Reverb type")
+          ("10.2" "Edit 1" "–"                   "Reverb effect level")
+          ("10.3" "Edit 1" "–"                   "Reverb decay time")
+          ("10.4" "Edit 1" "–"                   "Reverb frequency damping")
+          ("11.3" "Edit 1" "–"                   "Delay feedback")
+          ("11.2" "Edit 1" "–"                   "Delay effect level")
+          ("11.1" "Edit 1" "–"                   "Delay time")
+          ("11.4" "Edit 1" "–"                   "Delay frequency damping")))
+ (h2 [Thanks])
+ (p [The following tools have proven indispensable in the analysis:])
+ (ul
+  (li [,(ref "" "calc"), a
+       calculator for the command line supporting hexadecimal
+       representations of numbers (both input and output using the
+       ,(code [base]) and ,(code [base2]) functions)])
+  (li [,(ref "" "vbindiff"), a tool to
+       visualise differences between two binary files with a
+       split-screen hexadecimal display])
+  (li [,(ref "" "ghex"), a simple
+       hexadecimal editor supporting pattern search and highlighting]))
+ (h2 [Call for help])
+ (p [If you own an earlier model of the Wavedrum or the latest
+     Wavedrum Global Edition, I would be ,(em [very]) happy if you
+     could send me a block-level copy of the SD card (see above for
+     instructions).  This would allow me to understand the firmware
+     better and maybe even make it possible to upgrade an older
+     Wavedrum to the latest version (taking into account possible
+     hardware differences, such as differing memory size).])
+ (p [Please send a link to the micro SD card image to ,(email
+     "").])
+ (p [Read ,(ref "/tags/wavedrum.html" "more posts about the Wavedrum
+     here").]))
diff --git a/posts/2013-10-01-dm-crypt.markdown b/posts/2013-10-01-dm-crypt.markdown
deleted file mode 100644 (file)
index 401de87..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-title: How to create an encrypted file container with dm-crypt
-tags: gnu, linux, crypto, tutorial
-Here are some instructions on how to create an encrypted filesystem on a file.
-Create an empty file with the size of your container.  Here I'll use a 100MB
-container.  The file is created with `dd` which reads chunks from an input
-device and writes the contents to a file or another device.
-    dd if=/dev/zero bs=1M count=100 of=~/my-container.img
-This command means the following: read 100 chunks of one megabyte from the zero
-device `/dev/zero` and write them to the file `~/my-container.img`.  This will
-create a file named `my-container.img` in your home directory that will be
-about 100MB of zeros[^1].
-[^1]: You could use `/dev/random` as the input device if you wanted to, but
-that would be considerably slower and wouldn't help you much.  Later commands
-will initialise the file/partition, so you don't need to initialise it manually
-with random numbers.)
-Next, we'll initialise the LUKS partition on the file and set the initial
-    sudo cryptsetup luksFormat ~/mycontainer
-Note that you need to type "YES" (i.e. "yes" in *uppercase*) to confirm the
-operation; there is no error message when you fail this step which may be
-confusing.  Make sure that the file you want to format is your container file
-or an empty partition's device file.  Input your passphrase when prompted.  You
-will have to input this passphrase whenever you mount the container unless you
-decide to store the passphrase with the container (which obviously is not very
-safe).  Note that you have to run this as root, because cryptsetup must access
-the loopback device.  (On the Hurd this would not be necessary, I think.)
-Now, we'll open the container.  Opening the container creates a kernel device
-file which can then be mounted.
-    sudo cryptsetup luksOpen ~/mycontainer secret-device
-This command will prompt for the container's passphrase and then create a
-device file with the name `/dev/mapper/secret-device`.  You may choose another
-name than "secret-device".
-The container is now decrypted.  Since the device has no filesystem yet we
-still cannot put any data on it.  Use `mkfs.ext4` to create an ext4 filesystem
-on the decrypted container:
-    sudo mkfs.ext4 /dev/mapper/secret-device
-Now the filesystem can be mounted like a filesystem on a regular block device.
-    mkdir ~/my-mount-point
-    sudo mount /dev/mapper/secret-device ~/my-mount-point
-The first command creates a new mount point (an empty directory) named
-"my-mount-point" in your home directory.  The second command mounts the
-decrypted device at this location.
-You can now write to the directory as usual.  Once you are done follow these
-steps to unmount the device and close (= re-encrypt) the container:
-    sudo umount ~/my-mount-point
-    sudo cryptsetup luksClose secret-device
-To access the container again only these two commands are required:
-    sudo cryptsetup luksOpen ~/mycontainer secret-device
-    sudo mount /dev/mapper/secret-device ~/my-mount-point
diff --git a/posts/2013-10-01-dm-crypt.skr b/posts/2013-10-01-dm-crypt.skr
new file mode 100644 (file)
index 0000000..cae43e6
--- /dev/null
@@ -0,0 +1,87 @@
+(define meta
+  `((title . "How to create an encrypted file container with dm-crypt")
+    (date  . ,(string->date* "2013-10-01 00:00"))
+    (tags "gnu" "linux" "crypto" "tutorial")))
+ (p [Here are some instructions on how to create an encrypted
+     filesystem on a file.])
+ (p [Create an empty file with the size of your container.  Here I’ll
+     use a 100MB container.  The file is created with ,(code [dd])
+     which reads chunks from an input device and writes the contents
+     to a file or another device.])
+ (pre (code [dd if=/dev/zero bs=1M count=100 of=~/my-container.img]))
+ (p [This command means the following: read 100 chunks of one megabyte
+     from the ,(ref "#fn1" "zero device") ,(code [/dev/zero]) and
+     write them to the file ,(code [~/my-container.img]).  This will
+     create a file named ,(code [my-container.img]) in your home
+     directory that will be about 100MB of zeros.])
+ (p [Next, we’ll initialise the LUKS partition on the file and set the
+     initial passphrase.])
+ (pre (code [sudo cryptsetup luksFormat ~/mycontainer]))
+ (p [Note that you need to type “YES” (i.e. ‘yes’ in ,(em [uppercase])
+     to confirm the operation; there is no error message when you fail
+     this step which may be confusing.  Make sure that the file you
+     want to format is your container file or an empty partition’s
+     device file.  Input your passphrase when prompted.  You will have
+     to input this passphrase whenever you mount the container unless
+     you decide to store the passphrase with the container (which
+     obviously is not very safe).  Note that you have to run this as
+     root, because cryptsetup must access the loopback device.  (On
+     the Hurd this would not be necessary, I think.)])
+ (p [Now, we’ll open the container.  Opening the container creates a
+     kernel device file which can then be mounted.])
+ (pre (code [sudo cryptsetup luksOpen ~/mycontainer secret-device]))
+ (p [This command will prompt for the container’s passphrase and then
+     create a device file with the name ,(code
+     [/dev/mapper/secret-device]).  You may choose another name than
+     “secret-device”.])
+ (p [The container is now decrypted.  Since the device has no
+     filesystem yet we still cannot put any data on it.  Use ,(code
+     [mkfs.ext4]) to create an ext4 filesystem on the decrypted
+     container:])
+ (pre (code [sudo mkfs.ext4 /dev/mapper/secret-device]))
+ (p [Now the filesystem can be mounted like a filesystem on a regular
+     block device.])
+ (pre (code [mkdir ~/my-mount-point
+sudo mount /dev/mapper/secret-device ~/my-mount-point]))
+ (p [The first command creates a new mount point (an empty directory)
+     named “my-mount-point” in your home directory.  The second
+     command mounts the decrypted device at this location.])
+ (p [You can now write to the directory as usual.  Once you are done
+     follow these steps to unmount the device and close (= re-encrypt)
+     the container:])
+ (pre (code [sudo umount ~/my-mount-point
+sudo cryptsetup luksClose secret-device]))
+ (p [To access the container again only these two commands are
+     required:])
+ (pre (code [sudo cryptsetup luksOpen ~/mycontainer secret-device
+sudo mount /dev/mapper/secret-device ~/my-mount-point]))
+ `(div (@ (class "footnotes"))
+       (ol
+        (li (@ (id "fn1"))
+         ,(p [You could use ,(code [/dev/random]) as the input device if
+              you wanted to, but that would be considerably slower and
+              wouldn’t help you much.  Later commands will initialise
+              the file/partition, so you don’t need to initialise it
+              manually with random numbers.])))))
diff --git a/posts/2013-10-31-wavedrum-data-comparison.markdown b/posts/2013-10-31-wavedrum-data-comparison.markdown
deleted file mode 100644 (file)
index 6c6320c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-title: Firmware comparison between Wavedrums Original, Black and Oriental
-tags: DIY,electronics,music,hacking,wavedrum
-[my first post on hacking the Wavedrum](/posts/2013-08-11-hacking-the-wavedrum.html)
-two fellow musicians have sent me copies of the contents of their
-Wavedrum instruments, so I now have the data for the original silver
-issue, the black re-issue and the Oriental.
-The differences between the data from the silver and the data from the
-black Wavedrum are very few.  Of the files sent to me only five
-and `SYSTEM/WDX_M100.BIN`.  `USER.BIN` contains only the mapping of
-programmes to slots and banks, which have been altered by the
-respective owners of the two instruments, so it can safely be ignored.
-Likewise, `WD2_PROG.BIN` contains custom user programmes and hence is
-of no interest.
-`CALIB.BIN` contains as of yet unknown calibration information, just
-like the similarly named `CALIB.BOR` on my Wavedrum Oriental.  The
-contents of `CALIB.BIN` from the original Wavedrum are identical to
-those of the matching file on the Oriental.  The only difference
-that the Black has over the other two is a single digit.  This is from
-the Oriental:
-    01 00 00 75 00 00 00 00  02 00 00 00 00 00 00 00
-And this is from the Black:
-    01 00 00 75 00 00 00 00  01 00 00 00 00 00 00 00
-Not very exciting.
-`SYSTEM/VERSION.INF` contains the hardware/software versions.  Here
-are the contents of the Original, followed by the Black and the
-    01 20 01 10 01 20 00 00  00 00 00 00 00 00 00 00
-    01 32 01 10 01 32 00 00  57 44 58 5F 00 00 00 00
-    02 02 01 10 02 02 00 00  57 44 4f 52 00 00 00 00
-Again, these are in decimal notation and are in this format: firmware
-version (two bytes), sub-version (two bytes), data version
-(two-bytes), two empty bytes, four bytes for an optional identifier
-followed by four empty bytes.
-|Type     | Firmware version | Sub-version  |  Data version  | Identifier   |
-|Original | 1.20             | 1.10         | 1.20           | none         |
-|Black    | 1.32             | 1.10         | 1.32           | WDX_         |
-|Oriental | 2.02             | 1.10         | 2.02           | WDOR         |
-Looking at the version numbers above it becomes apparent that the
-sounds themselves are not covered by these numbers as the sounds on
-the Black are no different from those on the Original, yet the data
-version differs.
-The file `SYSTEM/WDX_M100.BIN` must be the firmware on both the
-Original and the Black Wavedrum, serving the same purpose as
-`SYSTEM/WDORM202.BIN` on the Oriental.  There are quite a few changes
-even between version 1.20 and 1.32, but I haven't yet taken the time
-to analyse them.  It is interesting to note, though, that every
-firmware file is /exactly/ one megabyte long, independent of the
-Wavedrum type.  This is due to padding which in the Original firmware
-begins at offset 0xC967C, in the Black firmware at offset 0xC9C68, and
-in the Oriental firmware at offset 0xDCB64
-More to follow.
-Read [more posts about the Wavedrum here](
diff --git a/posts/2013-10-31-wavedrum-data-comparison.skr b/posts/2013-10-31-wavedrum-data-comparison.skr
new file mode 100644 (file)
index 0000000..911777b
--- /dev/null
@@ -0,0 +1,82 @@
+(define meta
+  `((title . "Firmware comparison between Wavedrums Original, Black and Oriental")
+    (date  . ,(string->date* "2013-10-31 00:00"))
+    (tags "DIY" "electronics" "music" "hacking" "wavedrum")))
+(define (row first . rest)
+ `(tr (td (@ (align "right")) ,first)
+      ,@(map (lambda (field) `(td (@ (align "left")) ,field)) rest)))
+ (p [Since ,(ref "/posts/2013-08-11-hacking-the-wavedrum.html" "my
+     first post on hacking the Wavedrum") two fellow musicians have
+     sent me copies of the contents of their Wavedrum instruments, so
+     I now have the data for the original silver issue, the black
+     re-issue and the Oriental.])
+ (p [The differences between the data from the silver and the data
+     from the black Wavedrum are very few.  Of the files sent to me
+     only five differ: ,(code [USER.BIN]), ,(code [CALIB.BIN]), ,(code
+     [WD2_PROG.BIN]), ,(code [SYSTEM/VERSION.INF]), and ,(code
+     [SYSTEM/WDX_M100.BIN]).  ,(code [USER.BIN]) contains only the
+     mapping of programmes to slots and banks, which have been altered
+     by the respective owners of the two instruments, so it can safely
+     be ignored.  Likewise, ,(code [WD2_PROG.BIN]) contains custom
+     user programmes and hence is of no interest.])
+ (p [,(code [CALIB.BIN]) contains as of yet unknown calibration
+     information, just like the similarly named ,(code [CALIB.BOR]) on
+     my Wavedrum Oriental.  The contents of ,(code [CALIB.BIN]) from
+     the original Wavedrum are identical to those of the matching file
+     on the Oriental.  The only difference that the Black has over the
+     other two is a single digit.  This is from the Oriental:])
+ (pre (code [01 00 00 75 00 00 00 00  02 00 00 00 00 00 00 00]))
+ (p [And this is from the Black:])
+ (pre (code [01 00 00 75 00 00 00 00  01 00 00 00 00 00 00 00]))
+ (p [Not very exciting.])
+ (p [,(code [SYSTEM/VERSION.INF]) contains the hardware/software
+     versions.  Here are the contents of the Original, followed by the
+     Black and the Oriental:])
+ (pre (code [01 20 01 10 01 20 00 00  00 00 00 00 00 00 00 00
+01 32 01 10 01 32 00 00  57 44 58 5F 00 00 00 00
+02 02 01 10 02 02 00 00  57 44 4f 52 00 00 00 00]))
+ (p [Again, these are in decimal notation and are in this format:
+     firmware version (two bytes), sub-version (two bytes), data
+     version (two-bytes), two empty bytes, four bytes for an optional
+     identifier followed by four empty bytes.])
+ (table :align '("right")
+        :headers '("Type" "Firmware" "Sub-version" "Data version" "Identifier")
+        :rows
+        '(("Original" "1.20" "1.10" "1.20" "none")
+          ("Black"    "1.32" "1.10" "1.32" "WDX_")
+          ("Oriental" "2.02" "1.10" "2.02" "WDOR")))
+ (p [Looking at the version numbers above it becomes apparent that the
+     sounds themselves are not covered by these numbers as the sounds
+     on the Black are no different from those on the Original, yet the
+     data version differs.])
+ (p [The file ,(code [SYSTEM/WDX_M100.BIN]) must be the firmware on
+     both the Original and the Black Wavedrum, serving the same
+     purpose as ,(code [SYSTEM/WDORM202.BIN]) on the Oriental.  There
+     are quite a few changes even between version 1.20 and 1.32, but I
+     haven’t yet taken the time to analyse them.  It is interesting to
+     note, though, that every firmware file is ,(em [exactly]) one
+     megabyte long, independent of the Wavedrum type.  This is due to
+     padding which in the Original firmware begins at offset 0xC967C,
+     in the Black firmware at offset 0xC9C68, and in the Oriental
+     firmware at offset 0xDCB64.])
+ (p [More to follow.])
+ (p [Read ,(ref "/tags/wavedrum.html" "more posts about the Wavedrum
+     here").]))
diff --git a/posts/2013-12-09-wavedrum-connectors.markdown b/posts/2013-12-09-wavedrum-connectors.markdown
deleted file mode 100644 (file)
index ab03368..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-title: Connectors on the Wavedrum's circuit board
-tags: DIY,electronics,music,hacking,wavedrum
-On the circuit board of the Wavedrum there are solder holes to
-accomodate three large connectors.  Since they are so easily
-accessible and thus very inviting to anyone interested in modifying
-the instrument, I decided to trace each of the pins to its
-The three connectors are named CN10, CN11, and CN12, respectively.
-CN10 is found on the bottom right, CN11 on the bottom left, and CN12
-close to the left edge below the micro SD card reader.
-<img class="full stretch" src="/images/posts/2013/wavedrum-connectors.jpg" alt="connectors on the mainboard" />
-# CN10: digital audio interface
-Most of the ten pins of CN10 are outputs.  The first three pins carry
-clock signals used by the analogue to digital and digital to analogue
-converters on the top-side of the board.  Pin four gives access to the
-PDN (power down) signal which is used to disable the converters.  The
-next three pins are connected over the resistors R85, R84, and R83 to
-the DSP's pins 145, 144, and 143 (respectively); according to the
-[DSP's datasheet](
-these pins are `DAI_P8` (`SFSI`), `DAI_P10` (`SD2B`), and `DAI_P11`
-(`SD3A`), and are thus part of the Digital Audio Interface (DAI).  The
-remaining three pins on CN10 expose the supply voltage, ground, and an
-alternative positive voltage (the same as on the plus pole of the
-silver capacitors near the right edge of the board).  These are the
-signals left to right:
- . | direction | description
- 1 | output    | Master clock
- 2 | output    | Audio serial clock
- 3 | output    | Left/right clock
- 4 | output    | `PDN` (power down)
- 5 | input?    | `DAI_P8` / `SFSI`
- 6 | input?    | `DAI_P10` / `SD2B`
- 7 | input?    | `DAI_P11` / `SD3A`
- 8 | output    | V_A, or V_DD
- 9 | output    | GND
-10 | output    | alternative positive voltage
-What is this all good for?  Well, since all these clocks and voltages
-are exported it becomes relatively easy to connect an external digital
-to analogue converter (when `DAI_P8`, `DAI_P10`, and `DAI_P11` are
-used as outputs), or an external analogue to digital converter (if the
-DSP pins are used as inputs instead).  As there are protective
-resistors between the DSP pins and the connector pins 5--7 I assume
-that they are supposed to be used as inputs.
-# CN11: JTAG interface
-Moving on to the left bottom edge of the board we see a 14-pin
-connector with the name CN11.  This connector gives access to the JTAG
-interface on the DSP, which allows system debugging.  Unfortunately, I
-don't own a JTAG dongle and the free JTAG debugger
-[OpenOCD]( does not support the SHARC
-core, so I haven't been able to experiment with the debugging
-interface.  I'm not sure whether it is possible to use debugging
-feature without hardware/software provided by Analog Devices.  Using
-JTAG it should be possible to overwrite the flash memory and replace
-the firmware.  This is the most promising method to upgrade (or
-downgrade) a Wavedrum.
-The pins on the bottom row are all connected to ground, so the
-following table only lists the signal names of the upper row of the
-connector in order from left to right:
-. | Signal  | Full name
-1 | `~EMU`  | Emulation status
-2 | `GND`   | Ground
-3 | `TMS`   | Test mode select
-4 | `TCK`   | Test clock
-5 | `~TRST` | Test reset
-6 | `TDI`   | Test data input
-7 | `TDO`   | Test data output
-# CN12: two-wire serial interface
-CN12 exposes the DSP's two-wire interface, a serial interface
-compatible with the proprietary I^2C interface.  This allows us to
-connect a number of external serial devices to the serial bus.  As
-firmware support is required to communicate with the devices on the
-serial bus I don't see how this could be used without a custom
-The following table lists the signals from top to bottom:
-. | Signal     | Full name
-1 | `V_D`      | Positive voltage
-2 | `TWI_DATA` | Two-wire interface data
-3 | `TWI_CLK`  | Two-wire interface clock
-4 | `GND`      | Ground
-# Bonus: boot mode
-What led me to tracing the routes of the connectors was my curiosity
-about the boot mode.  According to the DSP's datasheet, there are four
-possible boot modes to select from by playing with the states of the
-pins `BOOT_CFG1-0` (one of these boot modes is "no boot").  Tracing
-these two pins from the DSP it becomes clear that the third boot mode
-"EPROM/FLASH boot" is hardwired (`BOOT_CFG1-0 = 10`).  The other two
-usable boot modes are SPI master and slave boots.
-BOOT_CFG1-0  | Booting Mode
-00           | SPI Slave Boot
-01           | SPI Master Boot
-10           | EPROM/Flash Boot
-11           | No boot
-<img class="full stretch" src="/images/posts/2013/wavedrum-bootcfg.jpg" alt="boot configuration traces" />
-As can be seen on the photo, the Wavedrum engineers were kind enough
-to leave solder pads connected to boot configuration pins on the
-board, allowing us to rewire them as we see fit.  To set `BOOT_CFG0`
-the pads for `R72` have to be bridged; likewise, to clear `BOOT_CFG1`
-only the two pads of `R59` have to be bridged.
-# References
-- [ADSP-21371/ADSP-21375 datasheet](
-- [ADSP hardware reference](
diff --git a/posts/2013-12-09-wavedrum-connectors.skr b/posts/2013-12-09-wavedrum-connectors.skr
new file mode 100644 (file)
index 0000000..a6382ed
--- /dev/null
@@ -0,0 +1,149 @@
+(define meta
+  `((title . "Connectors on the Wavedrum’s circuit board")
+    (date  . ,(string->date* "2013-12-09 00:00"))
+    (tags "DIY" "electronics" "music" "hacking" "wavedrum")))
+ (p [On the circuit board of the Wavedrum there are solder holes to
+     accomodate three large connectors.  Since they are so easily
+     accessible and thus very inviting to anyone interested in
+     modifying the instrument, I decided to trace each of the pins to
+     its destination.])
+ (p [The three connectors are named CN10, CN11, and CN12,
+     respectively.  CN10 is found on the bottom right, CN11 on the
+     bottom left, and CN12 close to the left edge below the micro SD
+     card reader.])
+ (wide-img "2013/wavedrum-connectors.jpg"
+           "connectors on the mainboard")
+ (h2 [CN10: digital audio interface])
+ (p [Most of the ten pins of CN10 are outputs.  The first three pins
+     carry clock signals used by the analogue to digital and digital
+     to analogue converters on the top-side of the board.  Pin four
+     gives access to the PDN (power down) signal which is used to
+     disable the converters.  The next three pins are connected over
+     the resistors R85, R84, and R83 to the DSP's pins 145, 144, and
+     143 (respectively); according to the ,(ref
+     ""
+     "DSP's datasheet") these pins are ,(code [DAI_P8]) (,(code [SFSI])), ,(code [DAI_P10])
+     (,(code [SD2B])), and ,(code [DAI_P11]) (,(code [SD3A])), and are thus part of the
+     Digital Audio Interface (DAI).  The remaining three pins on CN10
+     expose the supply voltage, ground, and an alternative positive
+     voltage (the same as on the plus pole of the silver capacitors
+     near the right edge of the board).  These are the signals left to
+     right:])
+ (table :align '("right")
+        :headers '("" "direction" "description")
+        :rows
+        '(("1"  "output" "Master clock")
+          ("2"  "output" "Audio serial clock")
+          ("3"  "output" "Left/right clock")
+          ("4"  "output" ((code "PDN") " (power down)"))
+          ("5"  "input?" ((code "DAI_P8") " / " (code "SFSI")))
+          ("6"  "input?" ((code "DAI_P10") " / " (code "SD2B")))
+          ("7"  "input?" ((code "DAI_P11") " / " (code "SD3A")))
+          ("8"  "output" ((code "V_A") ", or " (code "V_DD")))
+          ("9"  "output" "GND")
+          ("10" "output" "alternative positive voltage")))
+ (p [What is this all good for?  Well, since all these clocks and
+     voltages are exported it becomes relatively easy to connect an
+     external digital to analogue converter (when ,(code [DAI_P8]),
+     ,(code [DAI_P10]), and ,(code [DAI_P11]) are used as outputs), or
+     an external analogue to digital converter (if the DSP pins are
+     used as inputs instead).  nAs there are protective resistors
+     between the DSP pins and the connector pins 5–7 I assume that
+     they are supposed to be used as inputs.])
+ (h2 [CN11: JTAG interface])
+ (p [Moving on to the left bottom edge of the board we see a 14-pin
+     connector with the name CN11.  This connector gives access to the
+     JTAG interface on the DSP, which allows system debugging.
+     Unfortunately, I don't own a JTAG dongle and the free JTAG
+     debugger ,(ref "" "OpenOCD") does
+     not support the SHARC core, so I haven't been able to experiment
+     with the debugging interface.  I'm not sure whether it is
+     possible to use debugging feature without hardware/software
+     provided by Analog Devices.  Using JTAG it should be possible to
+     overwrite the flash memory and replace the firmware.  This is the
+     most promising method to upgrade (or downgrade) a Wavedrum.])
+ (p [The pins on the bottom row are all connected to ground, so the
+     following table only lists the signal names of the upper row of
+     the connector in order from left to right:])
+ (table :align '("right")
+        :headers '("" "Signal" "Full name")
+        :rows
+        '(("1" (code [~EMU])  "Emulation status")
+          ("2" (code [GND])   "Ground")
+          ("3" (code [TMS])   "Test mode select")
+          ("4" (code [TCK])   "Test clock")
+          ("5" (code [~TRST]) "Test reset")
+          ("6" (code [TDI])   "Test data input")
+          ("7" (code [TDO])   "Test data output")))
+ (h2 [CN12: two-wire serial interface])
+ (p [CN12 exposes the DSP's two-wire interface, a serial interface
+     compatible with the proprietary I^2C interface.  This allows us
+     to connect a number of external serial devices to the serial bus.
+     As firmware support is required to communicate with the devices
+     on the serial bus I don't see how this could be used without a
+     custom firmware.])
+ (p [The following table lists the signals from top to bottom:])
+ (table :align '("right")
+        :headers '("" "Signal" "Full name")
+        :rows
+        '(("1" (code [V_D])      "Positive voltage")
+          ("2" (code [TWI_DATA]) "Two-wire interface data")
+          ("3" (code [TWI_CLK])  "Two-wire interface clock")
+          ("4" (code [GND])      "Ground")))
+ (h2 [Bonus: boot mode])
+ (p [What led me to tracing the routes of the connectors was my
+     curiosity about the boot mode.  According to the DSP's datasheet,
+     there are four possible boot modes to select from by playing with
+     the states of the pins ,(code [BOOT_CFG1-0]) (one of these boot
+     modes is “no boot”).  Tracing these two pins from the DSP it
+     becomes clear that the third boot mode “EPROM/FLASH boot” is
+     hardwired (,(code [BOOT_CFG1-0 = 10])).  The other two usable
+     boot modes are SPI master and slave boots.])
+ (table :align '("right")
+        :headers '("BOOT_CFG1-0" "Booting mode")
+        :rows
+        '(("00" "SPI Slave Boot")
+          ("01" "SPI Master Boot")
+          ("10" "EPROM/Flash Boot")
+          ("11" "No boot")))
+ (wide-img "2013/wavedrum-bootcfg.jpg"
+           "boot configuration traces")
+ (p [As can be seen on the photo, the Wavedrum engineers were kind
+     enough to leave solder pads connected to boot configuration pins
+     on the board, allowing us to rewire them as we see fit.  To set
+     ,(code [BOOT_CFG0]) the pads for ,(code [R72]) have to be
+     bridged; likewise, to clear ,(code [BOOT_CFG1]) only the two pads
+     of ,(code [R59]) have to be bridged.])
+ (h2 [References])
+ (ul
+  (li [,(ref ""
+             "ADSP-21371/ADSP-21375 datasheet")])
+  (li [,(ref ""
+             "ADSP hardware reference")])))
diff --git a/posts/2014-09-18-wavedrum-firmware-disassembler.markdown b/posts/2014-09-18-wavedrum-firmware-disassembler.markdown
deleted file mode 100644 (file)
index af8d043..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-title: Disassembling the Wavedrum firmware
-tags: DIY,electronics,music,hacking,wavedrum,SHARC
-The Wavedrum's processing unit is an ADSP-21375 by Analog Devices, a
-member of the SHARC processor family.  The firmware of the Wavedrum,
-which is stored on a micro SD-card and, more importantly, on the flash
-memory chip is loaded into the processor during the boot process.
-[Last time](2013-12-09-wavedrum-connectors.html) I confirmed by tracing the
-connections of the two boot pins that the processor is wired to boot
-from EPROM/Flash (`BOOT_CFG1-0 = 10`).  I'm too lazy to try to verify
-that the firmware on the micro SD-card is identical to the contents of
-the flash memory, so I'll just assume that this is the case.
-When the processor is initially powered on, the internal memory is in
-an undefined state.  According to the
-[ADSP hardware reference](
-(section 17-7 *Processor Booting*), the processor core is put into
-`IDLE` mode while loading the boot kernel from an external source (in
-our case this is the flash memory) into the internal memory at address
-0x90000 (`IVT_START_ADDR`), and finally executes the boot kernel code
-when a peripheral interrupt signals that the kernel has been loaded.
-Then the application code is loaded from the memory and finally the
-application's Interrupt Vector Table (IVT) is loaded.  The boot kernel
-is 256 48-bit words long, as is the IVT.  The application code is of
-arbitrary length.
-# Word packing
-The boot kernel is exactly 256 48-bit words long (shorter kernels are
-padded with NOPs), but the words are not transferred as 48-bit words.
-The boot kernel is transferred from the external memory as a stream of
-384 "packed" 32-bit words (see table 17-6 in the hardware reference).
-To understand packing we have to know that conceptionally the internal
-memory consists of many rows of four columns, each of which is 16 bit
-wide.  Accessing 48-bit words is often referred to as 3-column access
-in the reference, whereas accessing 32-bit words is called 2-column
-access.  All of the SHARC instructions are 48 bit wide.  This means
-that any 32-bit wide package never contains the full instruction.
-Dependent on the order of the packages, the 48-bit words can be
-reconstructed from a stream of 32-bit words.
-Here's the original explanation in the hardware reference on page
-> During the boot process, word packing (for example 8 to 32-bit) is
-> performed over the SPI. In other words, the kernel is not loaded
-> directly with 256 x 48-bit words, instead it is loaded with 384 x
-> 32-bit ‘packed words’ (2-column access). The same physical memory
-> for instruction boot is loaded via DMA in normal word (NW) 2
-> column. However, after booting the same physical memory region is
-> fetched by the sequencer in NW 3-column. For example the loader
-> kernel itself has a NW 2 columns count of 256 x 3/2 = 384 words but
-> the kernel is executed with 256 instruction fetches.
-When booting from external memory the bus width is set to 8 bits.
-According to the
-[ADSP hardware reference](
-(section "External Port Booting"), the processor reads a stream of
-8-bit words from the data port and packs four of them into 32-bit
-words (LSB first) before storing them into the internal memory.
-Figure 17-5 in the hardware reference visualises this process rather
-nicely.  It shows how streams of different word sizes end up being
-stored in the internal memory.
-<img class="full stretch" src="/images/posts/2014/wavedrum-word-packing.png" alt="word packing" />
-Once I understood that words are transferred from the memory in 8-bit
-chuncks with the LSB first, writing a disassembler that would
-translate the binary boot kernel into assembly code was no longer very
-# A free disassembler for ADSP-213xx
-I implemented a simple tool in Haskell that takes a binary firmware
-and spits out assembly code for the ADSP.  At the moment it only
-supports a limited set of instructions, just enough so that I could
-translate the boot kernel.  The remainder of the instructions
-will be implemented later as I happen to encounter them in the
-application code.
-It currently only parses the first 256 words of the firmware,
-i.e. only the boot kernel.  Before I can parse the remainder I need to
-figure out the memory layout.
-The code is freely available under the
-[GPL]( and can be
-[downloaded here](
-See the included instructions for assistance in compiling and using
-the disassembler.
-# Next steps
-My work isn't over yet.  Next I'll focus on the following tasks:
-- figure out how the boot kernel loads the application code into the
-  processor
-- disassemble (parts of) the application code
-- look out for snippets that involve loading code from the micro-SD
-  card to the flash memory, because that's our ticket to upgrade the
-  firmware easily
-If you want to help me, I'd be happy if you could send me a copy of
-the Global Edition's firmware.  To do this you only need to take out
-the micro SD-card and create a disk image of it.  (On GNU/Linux this
-can easily be done with `dd` on the command line; see
-[my first post on hacking the Wavedrum](
-for more detailed instructions.)
-I would also be very grateful for code reviews and patches.
-Translating the various specifications into executable code wasn't
-always easy and I'm sure there are bugs in the code here and there.
-Read [more posts about the Wavedrum here](
diff --git a/posts/2014-09-18-wavedrum-firmware-disassembler.skr b/posts/2014-09-18-wavedrum-firmware-disassembler.skr
new file mode 100644 (file)
index 0000000..244aecd
--- /dev/null
@@ -0,0 +1,136 @@
+(define meta
+`((title . "Disassembling the Wavedrum firmware")
+  (date  . ,(string->date* "2014-09-18 00:00"))
+  (tags "DIY" "electronics" "music" "hacking" "wavedrum" "SHARC")))
+ (p [The Wavedrum’s processing unit is an ADSP-21375 by Analog Devices,
+     a member of the SHARC processor family.  The firmware of the
+     Wavedrum, which is stored on a micro SD-card and, more
+     importantly, on the flash memory chip is loaded into the processor
+     during the boot process.])
+ (p [,(ref "2013-12-09-wavedrum-connectors.html" "Last time") I
+     confirmed by tracing the connections of the two boot pins that the
+     processor is wired to boot from EPROM/Flash (,(code [BOOT_CFG1-0 =
+     10])).  I’m too lazy to try to verify that the firmware on the
+     micro SD-card is identical to the contents of the flash memory, so
+     I’ll just assume that this is the case.])
+ ;; TODO: link to hardware reference is dead
+ (p [When the processor is initially powered on, the internal memory is
+     in an undefined state.  According to the ,(ref
+     ""
+     "ADSP hardware reference") (section 17-7 ,(em [Processor
+     Booting])), the processor core is put into ,(code [IDLE]) mode
+     while loading the boot kernel from an external source (in our case
+     this is the flash memory) into the internal memory at address
+     0x90000 (,(code [IVT_START_ADDR])), and finally executes the boot
+     kernel code when a peripheral interrupt signals that the kernel
+     has been loaded.  Then the application code is loaded from the
+     memory and finally the application’s Interrupt Vector Table (IVT)
+     is loaded.  The boot kernel is 256 48-bit words long, as is the
+     IVT.  The application code is of arbitrary length.])
+ (h2 [Word packing])
+ (p [The boot kernel is exactly 256 48-bit words long (shorter kernels
+     are padded with NOPs), but the words are not transferred as 48-bit
+     words.  The boot kernel is transferred from the external memory as
+     a stream of 384 “packed” 32-bit words (see table 17-6 in the
+     hardware reference).  To understand packing we have to know that
+     conceptionally the internal memory consists of many rows of four
+     columns, each of which is 16 bit wide.  Accessing 48-bit words is
+     often referred to as 3-column access in the reference, whereas
+     accessing 32-bit words is called 2-column access.  All of the
+     SHARC instructions are 48 bit wide.  This means that any 32-bit
+     wide package never contains the full instruction.  Dependent on
+     the order of the packages, the 48-bit words can be reconstructed
+     from a stream of 32-bit words.])
+ (p [Here’s the original explanation in the hardware reference on page
+     17-27:])
+ (blockquote (p [During the boot process, word packing (for example 8
+                 to 32-bit) is performed over the SPI. In other words,
+                 the kernel is not loaded directly with 256 x 48-bit
+                 words, instead it is loaded with 384 x 32-bit ‘packed
+                 words’ (2-column access). The same physical memory for
+                 instruction boot is loaded via DMA in normal word (NW)
+                 2 column. However, after booting the same physical
+                 memory region is fetched by the sequencer in NW
+                 3-column. For example the loader kernel itself has a
+                 NW 2 columns count of 256 x 3/2 = 384 words but the
+                 kernel is executed with 256 instruction fetches.]))
+ (p [When booting from external memory the bus width is set to 8 bits.
+     According to the ,(ref
+     ""
+     "ADSP hardware reference") (section “External Port Booting”), the
+     processor reads a stream of 8-bit words from the data port and
+     packs four of them into 32-bit words (LSB first) before storing
+     them into the internal memory.])
+ (p [Figure 17-5 in the hardware reference visualises this process
+     rather nicely.  It shows how streams of different word sizes end
+     up being stored in the internal memory.])
+ (wide-img "2014/wavedrum-word-packing.png" "word packing")
+ (p [Once I understood that words are transferred from the memory in
+     8-bit chuncks with the LSB first, writing a disassembler that
+     would translate the binary boot kernel into assembly code was no
+     longer very challenging.])
+ (h2 [A free disassembler for ADSP-213xx])
+ (p [I implemented a simple tool in Haskell that takes a binary
+     firmware and spits out assembly code for the ADSP.  At the moment
+     it only supports a limited set of instructions, just enough so
+     that I could translate the boot kernel.  The remainder of the
+     instructions will be implemented later as I happen to encounter
+     them in the application code.])
+ (p [It currently only parses the first 256 words of the firmware,
+     i.e. only the boot kernel.  Before I can parse the remainder I
+     need to figure out the memory layout.])
+ (p [The code is freely available under the ,(ref
+     "" "GPL") and can be ,(ref
+     ""
+     "downloaded here").  See the included instructions for assistance
+     in compiling and using the disassembler.])
+ (h2 [Next steps])
+ (p [My work isn’t over yet.  Next I’ll focus on the following tasks:])
+ (ul
+  (li [figure out how the boot kernel loads the application code into
+       the processor])
+  (li [disassemble (parts of) the application code])
+  (li [look out for snippets that involve loading code from the
+       micro-SD card to the flash memory, because that’s our ticket to
+       upgrade the firmware easily]))
+ (p [If you want to help me, I’d be happy if you could send me a copy
+     of the Global Edition’s firmware.  To do this you only need to
+     take out the micro SD-card and create a disk image of it.  (On
+     GNU/Linux this can easily be done with ,(code [dd]) on the command
+     line; see ,(ref
+     "/posts/2013-08-11-hacking-the-wavedrum.html"
+     "my first post on hacking the Wavedrum") for more detailed
+     instructions.)])
+ (p [I would also be very grateful for code reviews and patches.
+     Translating the various specifications into executable code wasn’t
+     always easy and I’m sure there are bugs in the code here and
+     there.])
+ (p [Read ,(ref "/tags/wavedrum.html" "more posts
+     about the Wavedrum here").]))
diff --git a/posts/2014-11-23-upgrading-trulyergonomic-firmware.markdown b/posts/2014-11-23-upgrading-trulyergonomic-firmware.markdown
deleted file mode 100644 (file)
index 25f470c..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-title: Upgrading the TEK's firmware on GNU/Linux
-date: 2014/11/23
-tags: keyboard, virtualbox
-I'm using the Truly Ergonomic Keyboard (model 209) for most of my
-typing, because it's a pretty comfortable keyboard (when it works).
-One of the greatest features of this keyboard is that the layout can
-be customised and flashed to the hardware with a firmware upgrade.
-Unfortunately, the application used to flash the firmware is only
-available for Microsoft Windows.
-As a GNU/Linux user I find this to be very inconvenient.  I simply
-don't have access to a machine running Microsoft Windows (not even at
-the office).  Luckily, Microsoft provides
-[free virtual machine images]( of various versions of
-their operating system for browser evaluation purposes.  I
-occasionally use them to verify that a web page works all right in the
-proprietary and often quirky Microsoft browsers.  Although these
-images could be used in KVM, converting and tweaking them takes a
-little too long and is a bit annoying.  For the quickest results these
-images should be imported with Virtual Box instead.
-Truly Ergonomic recommends not to use virtualisation software to
-update the firmware of the keyboard, but as I was out of other options
-I decided to give it a try anyway.  You probably should not be doing
-this if you don't feel you would be able to perform a
-[manual reset](
-of the controller in case something goes wrong.
-## Preparation
-- a recent version of Virtual Box
-- a virtual machine image of Microsoft Windows
-- a user account that is a member of the group *vboxusers*; required
-  to access any host USB devices from within a Virtual Box machine.
-  If you have just added your account to this group, remember that you
-  need to log off and on again before the changes come into effect.
-- enable USB 2.0 support, provided by the *Oracle VM VirtualBox
-  Extension Pack*.  The extension pack has to be installed through the
-  preferences menu in the VirtualBox client.  Note that you may have
-  to run the client as root to have sufficient permissions to install
-  the extension pack.
-- a USB device filter configured to pass host USB devices through to
-  the virtual machine
-If everything is set up properly you should be able to forward USB
-devices from the host system to the virtual machine.  Try setting up a
-USB device filter in the USB settings menu of the virtual machine.
-You should be able to create a filter for the Truly Ergonomic Keyboard
-right there.  If you cannot see a list of USB devices at all at this
-point check that your user account is a member of the group
-## Performing the upgrade
-Inside the Windows machine start the official firmware upgrade tool,
-load the firmware you want to flash to the keyboard, and click on
-*Upgrade*.  This will result in an error message, but that's okay:
-don't panic!  The reason why this error occurs is that the USB
-identifier of the keyboard will have changed from something like this:
-    ID 0e6a:030c Megawin Technology Co., Ltd Truly Ergonomic Computer Keyboard
-to something like this:
-    ID 0e6a:030b Megawin Technology Co., Ltd Truly Ergonomic Computer Keyboard (Device Firmware Update mode)
-Since the USB identifier has changed, VirtualBox may no longer forward
-this device from the host to the virtual machine guest system.  All
-you have to do is add a filter for this new USB device in the guest
-settings and resume the upgrade by clicking on *Upgrade* again.  This
-will again lead to another error, but I found that by that time the
-upgrade has already been performed successfully.
-Note that while the USB device is being forwarded to the guest system
-you cannot use it in the host.  To test if the new firmware works as
-expected in your system, disable the USB filters in the guest
-## Next steps
-It should also be possible to flash the firmware directly from a
-GNU/Linux system.  I suppose one could sniff the USB communication and
-build a little tool that performs the upgrade natively on GNU/Linux.
diff --git a/posts/2014-11-23-upgrading-trulyergonomic-firmware.skr b/posts/2014-11-23-upgrading-trulyergonomic-firmware.skr
new file mode 100644 (file)
index 0000000..b0b8ce3
--- /dev/null
@@ -0,0 +1,99 @@
+(define meta
+`((title . "Upgrading the TEK’s firmware on GNU/Linux")
+  (date  . ,(string->date* "2014-11-23 00:00"))
+  (tags "keyboard" "virtualbox")))
+ (p [I’m using the Truly Ergonomic Keyboard (model 209) for most of my
+     typing, because it’s a pretty comfortable keyboard (when it
+     works).  One of the greatest features of this keyboard is that the
+     layout can be customised and flashed to the hardware with a
+     firmware upgrade.  Unfortunately, the application used to flash
+     the firmware is only available for Microsoft Windows.])
+ (p [As a GNU/Linux user I find this to be very inconvenient.  I
+     simply don’t have access to a machine running Microsoft Windows
+     (not even at the office).  Luckily, Microsoft provides ,(ref
+     "" "free virtual machine images") of various
+     versions of their operating system for browser evaluation
+     purposes.  I occasionally use them to verify that a web page
+     works all right in the proprietary and often quirky Microsoft
+     browsers.  Although these images could be used in KVM, converting
+     and tweaking them takes a little too long and is a bit annoying.
+     For the quickest results these images should be imported with
+     Virtual Box instead.])
+ (p [Truly Ergonomic recommends not to use virtualisation software to
+     update the firmware of the keyboard, but as I was out of other
+     options I decided to give it a try anyway.  You probably should
+     not be doing this if you don’t feel you would be able to perform a
+     ,(ref
+     ""
+     "manual reset") of the controller in case something goes wrong.])
+ (h2 [Preparation])
+ (ul
+  (li [a recent version of Virtual Box])
+  (li [a virtual machine image of Microsoft Windows])
+  (li [a user account that is a member of the group ,(code
+       [vboxusers]); required to access any host USB devices from
+       within a Virtual Box machine.  If you have just added your
+       account to this group, remember that you need to log off and on
+       again before the changes come into effect.])
+  (li [enable USB 2.0 support, provided by the ,(em [Oracle VM
+       VirtualBox Extension Pack]).  The extension pack has to be
+       installed through the preferences menu in the VirtualBox client.
+       Note that you may have to run the client as root to have
+       sufficient permissions to install the extension pack.])
+  (li [a USB device filter configured to pass host USB devices through
+       to the virtual machine]))
+ (p [If everything is set up properly you should be able to forward USB
+     devices from the host system to the virtual machine.  Try setting
+     up a USB device filter in the USB settings menu of the virtual
+     machine.  You should be able to create a filter for the Truly
+     Ergonomic Keyboard right there.  If you cannot see a list of USB
+     devices at all at this point check that your user account is a
+     member of the group ,(code [vboxusers]).])
+ (h2 [Performing the upgrade])
+ (p [Inside the Windows machine start the official firmware upgrade
+     tool, load the firmware you want to flash to the keyboard, and
+     click on ,(em [Upgrade]).  This will result in an error message,
+     but that’s okay: don’t panic!  The reason why this error occurs is
+     that the USB identifier of the keyboard will have changed from
+     something like this:])
+ (pre (code [ID 0e6a:030c Megawin Technology Co., Ltd Truly Ergonomic Computer Keyboard]))
+ (p [to something like this:])
+ (pre (code [ID 0e6a:030b Megawin Technology Co., Ltd Truly Ergonomic Computer Keyboard (Device Firmware Update mode)]))
+ (p [Since the USB identifier has changed, VirtualBox may no longer
+     forward this device from the host to the virtual machine guest
+     system.  All you have to do is add a filter for this new USB
+     device in the guest settings and resume the upgrade by clicking on
+     ,(em [Upgrade]) again.  This will again lead to another error, but
+     I found that by that time the upgrade has already been performed
+     successfully.])
+ (p [Note that while the USB device is being forwarded to the guest
+     system you cannot use it in the host.  To test if the new firmware
+     works as expected in your system, disable the USB filters in the
+     guest settings.])
+ (h2 [Next steps])
+ (p [It should also be possible to flash the firmware directly from a
+     GNU/Linux system.  I suppose one could sniff the USB communication
+     and build a little tool that performs the upgrade natively on
+     GNU/Linux.]))
diff --git a/posts/2015-04-17-gnu-guix.markdown b/posts/2015-04-17-gnu-guix.markdown
deleted file mode 100644 (file)
index d17d514..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-title: GNU Guix in an HPC environment
-date: 2015/04/17
-tags: free software, bioinformatics, system administration, packaging, cluster
-I spend my daytime hours as a system administrator at a research
-institute in a heterogeneous computing environment.  We have two big
-compute clusters (one on CentOS the other on Ubuntu) with about 100
-nodes each and dozens of custom GNU/Linux workstations.  A common task
-for me is to ensure the users can run their bioinformatics software,
-both on their workstation and on the clusters.  Only few
-bioinformatics tools and libraries are popular enough to have been
-packaged for CentOS or Ubuntu, so usually some work has to be done to
-build the applications and all of their dependencies for the target
-## How to waste time building and deploying software
-In theory compiling software is not a very difficult thing to do.
-Once all development headers have been installed on the build host,
-compilation is usually a matter of configuring the build with a
-configure script and running GNU make with various flags (this is an
-assumption which is violated by bioinformatics software on a regular
-basis, but let's not get into this now).  However, there are practical
-problems that become painfully obvious in a shared environment with a
-large number of users.
-### Naive compilation
-Compiling software directly on the target machine is an option only in
-the most trivial cases.  With more complicated build systems or
-complicated build-time dependencies there is a strong incentive for
-system administrators to do the hard work of setting up a suitable
-build environment for a particular piece of software only once.  Most
-people would agree that package management is a great step up from
-naive compilation, as the build steps are formalised in some sort of
-recipe that can be executed by build tools in a reproducible manner.
-Updates to software only require tweaks to these recipes.  Package
-management is a good thing.
-### System-dependence
-Non-trivial software that was built and dynamically linked on one
-machine with a particular set of libraries and header files at
-particular versions can only really work on a system with the very
-same libraries at compatible versions in place.  Established package
-managers allow packagers to specify hard dependencies and version
-ranges, but the binaries that are produced on the build host will only
-work under the constraints imposed on them at build time.  To support
-an environment in which software must run on, say, both CentOS 6.5 and
-CentOS 7.1, the packages must be built in both environments and
-binaries for both targets have to be provided.
-There are ways to emulate a different build environment (e.g. Fedora's
-`mockbuild`), but we cannot get around the fact that dynamically
-linked software built for one kind of system will only ever work on
-that very kind of system.  At runtime we can change what libraries
-will be dynamically loaded, but this is a hack that pushes the problem
-from package maintainers to users.  Running software with
-`LD_LIBRARY_PATH` set is not a solution, nor is static linking, the
-equivalent to copying chunks of libraries at build time.
-### Version conflicts
-Libraries and applications that come pre-installed or pre-packaged
-with the system may not be the versions a user claims to need.  Say, a
-user wants the latest version of GCC to compile code using new
-language features specified in C++11 (e.g. anonymous functions).  Full
-support for C++11 arrived in GCC 4.8.1, yet on CentOS 6.5 only version
-4.4.7 is available through the repositories.  The system administrator
-may not necessarily be able to upgrade GCC system-wide.  Or maybe
-other users on a shared system do need version 4.4.7 to be available
-(e.g. for bug-compatibility).  There is no easy way to satisfy all
-users, so a system administrator might give up and let users build
-their own software in their home directories instead of solving the
-However, compiling GCC is a daunting task for a user and they really
-shouldn't have to do this at all.  We already established that package
-management is a good thing; why should we deny users the benefits of
-package management?  Traditional package management techniques are
-ill-suited to the task of installing multiple versions of applications
-or libraries into independent prefixes.  RPM, for example, allows
-users to maintain a local, independent package database, but `yum`
-won't work with multiple package databases.  Additionally, only *one*
-package database can be used at once, so a user would have to
-re-install system libraries into the local package database to satisfy
-dependencies.  As a result, users lose the important feature of
-automatic dependency resolution.
-### Interoperability
-A system administrator who decides to package software as relocatable
-RPMs, to install the applications to custom prefixes and to maintain a
-separate repository has nothing to show for when a user asks to have
-the packaged software installed on an Ubuntu workstation.  There are
-ways to convert RPMs to DEB packages (with varying degrees of
-success), but it seems silly to have to convert or rebuild stuff
-repeatedly when the software, its dependencies and its mode of
-deployment really didn't change at all.
-What happens when a Slackware user comes along next?  Or someone using
-Arch Linux?  Sure, as a system administrator you could refuse to
-support any system other than CentOS 7.1, users be damned.
-Traditionally, it seems that system administrators default to this
-style for convenience and/or practical reasons, but I consider this
-unhelpful and even somewhat oppressive.
-## Functional package management with GNU Guix
-Luckily I'm not the only person to consider traditional packaging
-methods inadequate for a number of valid purposes.  There are
-different projects aiming to improve and simplify software deployment
-and management, one of which I will focus on in this article.  As a
-functional programmer, Scheme aficionado and free software enthusiast
-I was intrigued to learn about
-[GNU Guix](, a functional package
-manager written in
-[Guile Scheme](, the designated
-extension language for the [GNU system](
-In purely functional programming languages a function will produce the
-very same output when called repeatedly with the same input values.
-This allows for interesting optimisation, but most importantly it
-makes it *possible* and in some cases even *easy* to reason about the
-behaviour of a function.  It is independent from global state, has no
-side effects, and its outputs can be cached as they are certain not to
-change as long as the inputs stay the same.
-Functional package management lifts this concept to the realm of
-software building and deployment.  Global state in a system equates to
-system-wide installations of software, libraries and development
-headers.  Side effects are changes to the global environment or global
-system paths such as `/usr/bin/`.  To reject global state means to
-reject the common file system hierarchy for software deployment and to
-use a minimal `chroot` for building software.  The introduction of the
-Guix manual describes the approach as follows:
-> The term "functional" refers to a specific package management
-> discipline.  In Guix, the package build and installation process is
-> seen as a function, in the mathematical sense.  That function takes
-> inputs, such as build scripts, a compiler, and libraries, and
-> returns an installed package.  As a pure function, its result
-> depends solely on its inputs—for instance, it cannot refer to
-> software or scripts that were not explicitly passed as inputs.  A
-> build function always produces the same result when passed a given
-> set of inputs.  It cannot alter the system’s environment in any way;
-> for instance, it cannot create, modify, or delete files outside of
-> its build and installation directories.  This is achieved by running
-> build processes in isolated environments (or "containers"), where
-> only their explicit inputs are visible.
-> The result of package build functions is "cached" in the file
-> system, in a special directory called "the store".  Each package is
-> installed in a directory of its own, in the store—by default under
-> ‘/gnu/store’.  The directory name contains a hash of all the inputs
-> used to build that package; thus, changing an input yields a
-> different directory name.
-The following diagram (taken from the
-[slides for a talk by Ludovic Courtès](
-illustrates how the build daemon handles the package build processes
-requested by a client via remote procedure calls:
-<img class="full stretch" src="/images/posts/2015/guix-build.png" alt="Software is built by the Guix daemon in isolttion" />
-### Isolated, yet shared
-Note that the package outputs are still dynamically linked.  Libraries
-are referenced in the binaries with their full store paths using the
-runpath feature.  These package outputs are no self-contained,
-monolithic application directories as you might know them from MacOS.
-Any built software is cached in the store which is shared by all users
-system-wide.  However, by default the software in the store has no
-effect whatsoever on the users' environments.  Building software and
-have the results stored in `/gnu/store` does not alter any global
-state; no files pollute `/usr/bin/` or `/usr/lib/`.  Any effects are
-restricted to the package's single output directory inside the
-Guix provides per-user profiles to map software from the store into a
-user environment.  The store provides deduplication as it serves as a
-cache for packages that have already been built.  A profile is little
-more than a "forest" of symbolic links to items in the store.  The
-union of links to the outputs of all software packages the user
-requested makes up the user's profile.  By adding another layer of
-symbolic link indirection, Guix allows users to seamlessly switch
-among different generations of the same profile, going back in time.
-Each user profile is completely isolated from one another, making it
-possible for different users to have different versions of GCC
-installed.  Even one and the same user could have multiple profiles
-with different versions of GCC and switch between them as needed.
-Guix takes the functional packaging method seriously, so except for
-the running kernel and the exposed machine hardware there are
-virtually no dependencies on global state (i.e. system libraries or
-headers).  This also means that the Guix store is populated with the
-complete dependency tree, down to the kernel headers and the C
-library.  As a result, software in the Guix store can run on very
-different GNU/Linux distributions; a shared Guix store allows me to
-use the very same software on my Fedora workstation, as well as on the
-Ubuntu cluster, and on the CentOS 6.5 cluster.
-This means that software only has to be packaged up once.  Since
-package recipes are written in a very declarative domain-specific
-language on top of Scheme, packaging is surprisingly simple (and to
-this Schemer is rather enjoyable).
-### User freedom
-Guix liberates users from the software deployment decisions of their
-system administrators by giving them the power to build software into
-an isolated directory in the store using simple package recipes.
-Administrators only need to configure and run the Guix daemon, the
-core piece running as root.  The daemon listens to requests issued by
-the Guix command line tool, which can be run by users without root
-permissions.  The command line tool allows users to manage their
-profiles, switch generations, build and install software through the
-Guix daemon.  The daemon takes care of the store, of evaluating the
-build expressions and "caching" build results, and it updates the
-forest of symbolic links to update profile state.
-Users are finally free to conveniently manage their own software,
-something they could previously only do in a crude manner by compiling
-## Using a shared Guix store
-Guix is not designed to be run in a centralised manner.  A Guix daemon
-is supposed to run on each system as root and it listens to RPCs from
-local users only.  In an environment with multiple clusters and
-multiple workstations this approach requires considerable effort to
-make it work correctly and securely.
-<img class="full stretch" src="/images/posts/2015/guix-shared.svg" alt="Sharing Guix store and profiles" />
-Instead we opted to run the Guix daemon on a single dedicated server,
-writing profile data and store items onto an NFS share.  The cluster
-nodes and workstations mount this share read-only.  Although this
-means that users lose the ability to manage their profiles directly on
-their workstations and on the cluster nodes (because they have no
-local installation of the Guix client or the Guix daemon, and because
-they lack write access to the shared store), their software profiles
-are now available wherever they are.  To manage their profiles, users
-would log on to the Guix server where they can install software into
-their profiles, roll back to previous versions or send other queries
-to the Guix daemon.  (At some point I think it would make sense to
-enhance Guix such that RPCs can be made over SSH, so that explicit
-logging on to a management machine is no longer necessary.)
-## Guix as a platform for scientific software
-Since winter 2014 I have been packaging software for GNU Guix, which
-meanwhile has accumulated quite a few common and obscure
-[bioinformatics tools and libraries](
-A list of software (updated daily) available through Guix is
-[available here](
-We also have common Python modules for scientific computing, as well
-as programming languages such as R and Julia.
-I think GNU Guix is a great platform for scientific software in
-heterogeneous computing environments.  The Guix project follows the
-[Free System Distribution Guidelines](,
-which mean that free software is welcome upstream.  For software that
-imposes additional usage or distribution restrictions (such as when
-the original Artistic license is used instead of the Clarified
-Artistic license, or when commercial use is prohibited by the license)
-Guix allows the use of out-of-tree package modules through the
-`GUIX_PACKAGE_PATH` variable.  As Guix packages are just Scheme
-variables in Scheme modules, it is trivial to extend the official GNU
-Guix distribution with package modules by simply setting the
-If you want to learn more about GNU Guix I recommend taking a look at
-the excellent
-[GNU Guix project page](  Feel
-free to contact me if you want to learn more about packaging
-scientific software for Guix.  It is not difficult and we all can
-benefit from joining efforts in adopting this usable, dependable,
-hackable, and liberating platform for scientific computing with free
-The Guix community is very friendly, supportive, responsive and
-welcoming.  I encourage you to visit the project's
-[IRC channel #guix on Freenode](,
-where I go by the handle "rekado".
diff --git a/posts/2015-04-17-gnu-guix.skr b/posts/2015-04-17-gnu-guix.skr
new file mode 100644 (file)
index 0000000..f7e2400
--- /dev/null
@@ -0,0 +1,315 @@
+(define meta
+  `((title . "GNU Guix in an HPC environment")
+    (date  . ,(string->date* "2015-04-17 00:00"))
+    (tags "gnu" "free software" "guix" "bioinformatics" "system administration" "packaging" "cluster")))
+ (p [I spend my daytime hours as a system administrator at a research
+     institute in a heterogeneous computing environment.  We have two
+     big compute clusters (one on CentOS the other on Ubuntu) with
+     about 100 nodes each and dozens of custom GNU/Linux workstations.
+     A common task for me is to ensure the users can run their
+     bioinformatics software, both on their workstation and on the
+     clusters.  Only few bioinformatics tools and libraries are
+     popular enough to have been packaged for CentOS or Ubuntu, so
+     usually some work has to be done to build the applications and
+     all of their dependencies for the target platforms.])
+ (h2 [How to waste time building and deploying software])
+ (p [In theory, compiling software is not a very difficult thing to
+     do.  Once all development headers have been installed on the
+     build host, compilation is usually a matter of configuring the
+     build with a configure script and running GNU make with various
+     flags (this is an assumption which is violated by bioinformatics
+     software on a regular basis, but let’s not get into this now).
+     However, there are practical problems that become painfully
+     obvious in a shared environment with a large number of users.])
+ (h3 [Naive compilation])
+ (p [Compiling software directly on the target machine is an option
+     only in the most trivial cases.  With more complicated build
+     systems or complicated build-time dependencies there is a strong
+     incentive for system administrators to do the hard work of
+     setting up a suitable build environment for a particular piece of
+     software only once.  Most people would agree that package
+     management is a great step up from naive compilation, as the
+     build steps are formalised in some sort of recipe that can be
+     executed by build tools in a reproducible manner.  Updates to
+     software only require tweaks to these recipes.  Package
+     management is a good thing.])
+ (h3 [System-dependence])
+ (p [Non-trivial software that was built and dynamically linked on one
+     machine with a particular set of libraries and header files at
+     particular versions can only really work on a system with the
+     very same libraries at compatible versions in place.  Established
+     package managers allow packagers to specify hard dependencies and
+     version ranges, but the binaries that are produced on the build
+     host will only work under the constraints imposed on them at
+     build time.  To support an environment in which software must run
+     on, say, both CentOS 6.5 and CentOS 7.1, the packages must be
+     built in both environments and binaries for both targets have to
+     be provided.])
+ (p [There are ways to emulate a different build environment
+     (e.g. Fedora’s ,(code [mockbuild])), but we cannot get around the
+     fact that dynamically linked software built for one kind of
+     system will only ever work on that very kind of system.  At
+     runtime we can change what libraries will be dynamically loaded,
+     but this is a hack that pushes the problem from package
+     maintainers to users.  Running software with ,(code
+     [LD_LIBRARY_PATH]) set is not a solution, nor is static linking,
+     the equivalent to copying chunks of libraries at build time.])
+ (h3 [Version conflicts])
+ (p [Libraries and applications that come pre-installed or
+     pre-packaged with the system may not be the versions a user
+     claims to need.  Say, a user wants the latest version of GCC to
+     compile code using new language features specified in C++11
+     (e.g. anonymous functions).  Full support for C++11 arrived in
+     GCC 4.8.1, yet on CentOS 6.5 only version 4.4.7 is available
+     through the repositories.  The system administrator may not
+     necessarily be able to upgrade GCC system-wide.  Or maybe other
+     users on a shared system do need version 4.4.7 to be available
+     (e.g. for bug-compatibility).  There is no easy way to satisfy
+     all users, so a system administrator might give up and let users
+     build their own software in their home directories instead of
+     solving the problem.])
+ (p [However, compiling GCC is a daunting task for a user and they
+     really shouldn’t have to do this at all.  We already established
+     that package management is a good thing; why should we deny users
+     the benefits of package management?  Traditional package
+     management techniques are ill-suited to the task of installing
+     multiple versions of applications or libraries into independent
+     prefixes.  RPM, for example, allows users to maintain a local,
+     independent package database, but ,(code [yum]) won’t work with
+     multiple package databases.  Additionally, only ,(em [one])
+     package database can be used at once, so a user would have to
+     re-install system libraries into the local package database to
+     satisfy dependencies.  As a result, users lose the important
+     feature of automatic dependency resolution.])
+ (h3 [Interoperability])
+ (p [A system administrator who decides to package software as
+     relocatable RPMs, to install the applications to custom prefixes
+     and to maintain a separate repository has nothing to show for
+     when a user asks to have the packaged software installed on an
+     Ubuntu workstation.  There are ways to convert RPMs to DEB
+     packages (with varying degrees of success), but it seems silly to
+     have to convert or rebuild stuff repeatedly when the software,
+     its dependencies and its mode of deployment really didn’t change
+     at all.])
+ (p [What happens when a Slackware user comes along next?  Or someone
+     using Arch Linux?  Sure, as a system administrator you could
+     refuse to support any system other than CentOS 7.1, users be
+     damned.  Traditionally, it seems that system administrators
+     default to this style for convenience and/or practical reasons,
+     but I consider this unhelpful and even somewhat oppressive.])
+ (h2 [Functional package management with GNU Guix])
+ (p [Luckily, I’m not the only person to consider traditional
+     packaging methods inadequate for a number of valid purposes.
+     There are different projects aiming to improve and simplify
+     software deployment and management, one of which I will focus on
+     in this article.  As a functional programmer, Scheme aficionado
+     and free software enthusiast I was intrigued to learn about ,(ref
+     "" "GNU Guix"), a functional
+     package manager written in ,(ref
+     "" "Guile Scheme"), the
+     designated extension language for the ,(ref
+     "" "GNU system").])
+ (p [In purely functional programming languages a function will
+     produce the very same output when called repeatedly with the same
+     input values.  This allows for interesting optimisation, but most
+     importantly it makes it ,(em [possible]) and in some cases even
+     ,(em [easy]) to reason about the behaviour of a function.  It is
+     independent from global state, has no side effects, and its
+     outputs can be cached as they are certain not to change as long
+     as the inputs stay the same.])
+ (p [Functional package management lifts this concept to the realm of
+     software building and deployment.  Global state in a system
+     equates to system-wide installations of software, libraries and
+     development headers.  Side effects are changes to the global
+     environment or global system paths such as ,(code [/usr/bin/]).
+     To reject global state means to reject the common file system
+     hierarchy for software deployment and to use a minimal ,(code
+     [chroot]) for building software.  The introduction of the Guix
+     manual describes the approach as follows:])
+ (blockquote
+  (p [The term “functional” refers to a specific package management
+      discipline.  In Guix, the package build and installation process
+      is seen as a function, in the mathematical sense.  That function
+      takes inputs, such as build scripts, a compiler, and libraries,
+      and returns an installed package.  As a pure function, its
+      result depends solely on its inputs—for instance, it cannot
+      refer to software or scripts that were not explicitly passed as
+      inputs.  A build function always produces the same result when
+      passed a given set of inputs.  It cannot alter the system’s
+      environment in any way; for instance, it cannot create, modify,
+      or delete files outside of its build and installation
+      directories.  This is achieved by running build processes in
+      isolated environments (or “containers”), where only their
+      explicit inputs are visible.])
+  (p [The result of package build functions is “cached” in the file
+      system, in a special directory called “the store”.  Each package
+      is installed in a directory of its own, in the store—by default
+      under ‘/gnu/store’.  The directory name contains a hash of all
+      the inputs used to build that package; thus, changing an input
+      yields a different directory name.]))
+ (p [The following diagram (taken from the ,(ref
+     ""
+     "slides for a talk by Ludovic Courtès")) illustrates how the
+     build daemon handles the package build processes requested by a
+     client via remote procedure calls:])
+ (wide-img "2015/guix-build.png"
+           "Software is built by the Guix daemon in isolation")
+ (h3 [Isolated, yet shared])
+ (p [Note that the package outputs are still dynamically linked.
+     Libraries are referenced in the binaries with their full store
+     paths using the runpath feature.  These package outputs are no
+     self-contained, monolithic application directories as you might
+     know them from MacOS.])
+ (p [Any built software is cached in the store which is shared by all
+     users system-wide.  However, by default the software in the store
+     has no effect whatsoever on the users’ environments.  Building
+     software and have the results stored in ,(code [/gnu/store]) does
+     not alter any global state; no files pollute ,(code [/usr/bin/])
+     or ,(code [/usr/lib/]).  Any effects are restricted to the
+     package’s single output directory inside the ,(code
+     [/gnu/store]).])
+ (p [Guix provides per-user profiles to map software from the store
+     into a user environment.  The store provides deduplication as it
+     serves as a cache for packages that have already been built.  A
+     profile is little more than a “forest” of symbolic links to items
+     in the store.  The union of links to the outputs of all software
+     packages the user requested makes up the user’s profile.  By
+     adding another layer of symbolic link indirection, Guix allows
+     users to seamlessly switch among different generations of the
+     same profile, going back in time.])
+ (p [Each user profile is completely isolated from one another, making
+     it possible for different users to have different versions of GCC
+     installed.  Even one and the same user could have multiple
+     profiles with different versions of GCC and switch between them
+     as needed.])
+ (p [Guix takes the functional packaging method seriously, so except
+     for the running kernel and the exposed machine hardware there are
+     virtually no dependencies on global state (i.e. system libraries
+     or headers).  This also means that the Guix store is populated
+     with the complete dependency tree, down to the kernel headers and
+     the C library.  As a result, software in the Guix store can run
+     on very different GNU/Linux distributions; a shared Guix store
+     allows me to use the very same software on my Fedora workstation,
+     as well as on the Ubuntu cluster, and on the CentOS 6.5 cluster.])
+ (p [This means that software only has to be packaged up once.  Since
+     package recipes are written in a very declarative domain-specific
+     language on top of Scheme, packaging is surprisingly simple (and
+     to this Schemer is rather enjoyable).])
+ (h3 [User freedom])
+ (p [Guix liberates users from the software deployment decisions of
+     their system administrators by giving them the power to build
+     software into an isolated directory in the store using simple
+     package recipes.  Administrators only need to configure and run
+     the Guix daemon, the core piece running as root.  The daemon
+     listens to requests issued by the Guix command line tool, which
+     can be run by users without root permissions.  The command line
+     tool allows users to manage their profiles, switch generations,
+     build and install software through the Guix daemon.  The daemon
+     takes care of the store, of evaluating the build expressions and
+     “caching” build results, and it updates the forest of symbolic
+     links to update profile state.])
+ (p [Users are finally free to conveniently manage their own software,
+     something they could previously only do in a crude manner by
+     compiling manually.])
+ (h2 [Using a shared Guix store])
+ (p [Guix is not designed to be run in a centralised manner.  A Guix
+     daemon is supposed to run on each system as root and it listens
+     to RPCs from local users only.  In an environment with multiple
+     clusters and multiple workstations this approach requires
+     considerable effort to make it work correctly and securely.])
+ (wide-img "2015/guix-shared.svg"
+           "Sharing Guix store and profiles")
+ (p [Instead we opted to run the Guix daemon on a single dedicated
+     server, writing profile data and store items onto an NFS share.
+     The cluster nodes and workstations mount this share read-only.
+     Although this means that users lose the ability to manage their
+     profiles directly on their workstations and on the cluster nodes
+     (because they have no local installation of the Guix client or
+     the Guix daemon, and because they lack write access to the shared
+     store), their software profiles are now available wherever they
+     are.  To manage their profiles, users would log on to the Guix
+     server where they can install software into their profiles, roll
+     back to previous versions or send other queries to the Guix
+     daemon.  (At some point I think it would make sense to enhance
+     Guix such that RPCs can be made over SSH, so that explicit
+     logging on to a management machine is no longer necessary.)])
+ (h2 [Guix as a platform for scientific software])
+ (p [Since winter 2014 I have been packaging software for GNU Guix,
+     which meanwhile has accumulated quite a few common and obscure
+     ,(ref
+     ""
+     "bioinformatics tools and libraries").  A list of software
+     (updated daily) available through Guix is ,(ref
+     "" "available
+     here").  We also have common Python modules for scientific
+     computing, as well as programming languages such as R and Julia.])
+ (p [I think GNU Guix is a great platform for scientific software in
+     heterogeneous computing environments.  The Guix project follows
+     the ,(ref
+     ""
+     "Free System Distribution Guidelines"), which mean that free
+     software is welcome upstream.  For software that imposes
+     additional usage or distribution restrictions (such as when the
+     original Artistic license is used instead of the Clarified
+     Artistic license, or when commercial use is prohibited by the
+     license) Guix allows the use of out-of-tree package modules
+     through the ,(code [GUIX_PACKAGE_PATH]) variable.  As Guix
+     packages are just Scheme variables in Scheme modules, it is
+     trivial to extend the official GNU Guix distribution with package
+     modules by simply setting the ,(code [GUIX_PACKAGE_PATH]).])
+ (p [If you want to learn more about GNU Guix I recommend taking a
+     look at the excellent ,(ref ""
+     "GNU Guix project page").  Feel free to contact me if you want to
+     learn more about packaging scientific software for Guix.  It is
+     not difficult and we all can benefit from joining efforts in
+     adopting this usable, dependable, hackable, and liberating
+     platform for scientific computing with free software.])
+ (p [The Guix community is very friendly, supportive, responsive and
+     welcoming.  I encourage you to visit the project’s ,(ref
+     "" "IRC channel #guix
+     on Freenode"), where I go by the handle “rekado”.]))
diff --git a/posts/2015-06-21-getting-started-with-guix.markdown b/posts/2015-06-21-getting-started-with-guix.markdown
deleted file mode 100644 (file)
index 25dfb00..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-title: Getting started with GNU Guix
-date: 2015/06/21
-tags: free software, system administration, packaging, guix
-[Previously I wrote](/posts/2015-04-17-gnu-guix.html) about how using
-GNU Guix in an HPC environment enables easy software deployment for
-multiple users with different needs when it comes to application and
-library versions.  Although Guix comes with an excellent manual which
-is also
-[available online](,
-some people may want to have just some simple installation
-instructions in one place and some pointers to get started.  I'm
-attempting to provide just that with this article.
-While Guix can be built from source it is much more convenient to use
-the self-contained tarball which provides pre-built binaries for Guix
-and all its dependencies.  You need to have GNU tar and xz installed
-to unpack the tarball.  Note that the tarball will only work on
-GNU/Linux systems; it will not work on MacOS.
-## Six simple steps
-*First*, if you are using a 64 bit machine, download the compressed
-[x86_64 archive from the FTP server](
-There also is a
-[tarball for 32 bit machines](
-[one for the less common MIPS](
-*Second*, unpack the archive as root in the root directory:
-    # cd /
-    # tar xf guix-binary-0.8.2.SYSTEM.tar.xz
-This creates a pre-populated store at `/gnu/store` (containing the
-"guix" package and the complete dependency graph), the *local state
-directory* `/var/guix`, and a Guix profile for the root user at
-`/root/.guix-profile`, which contains the guix command line tools and
-the daemon.
-*Third*, create a build user pool, as root:
-     # groupadd --system guix-builder
-     # for i in `seq 1 10`;
-       do
-         useradd -g guix-builder -G guix-builder           \
-                 -d /var/empty -s `which nologin`          \
-                 -c "Guix build user $i" --system          \
-                 guix-builder$i;
-       done
-These are the restricted user accounts which are used by the daemon to
-build software in a controlled environment.  You may not need ten, but
-it's a good default.
-*Fourth*, run the daemon and tell it about the `guix-builder` group:
-    # /root/.guix-profile/bin/guix-daemon --build-users-group=guix-builder
-*Fifth*, make the `guix` command available to other users on the
- machine by linking it to a location everyone can access, such as
- `/usr/local/bin`.
-    # mkdir -p /usr/local/bin
-    # cd /usr/local/bin
-    # ln -s /root/.guix-profile/bin/guix
-Now any user---not just the almighty root---can install software by
-invoking `guix package -i whatever`.  Yay!
-*Finally*, if you do not want to build all software locally (which can
- take a very long time) and you think you can trust the GNU Guix build
- farm, authorise it as a source for so-called binary
- substitutes using the included public key:
-    # guix archive --authorize < /root/.guix-profile/share/guix/
-Note that isn't at all special.  Packages are built
-there continuously from source.  Guix is flexible and can pull binary
-substitutes from other locations as long as you authorise them.
-# Where to go from here
-Congratulations!  You now have a fully functional installation of the
-Guix package manager.
-To get the latest package recipes for Guix just run `guix pull`, which
-will download and compile the most recent development version.
-I recommend reading the excellent Guix reference manual, which is
-[available on the web](
-and, of course, included as an Info document in your Guix
-installation.  If you don't have Emacs---the best Info reader, which
-also happens to be an excellent text editor---I encourage you to
-install it from Guix; it is just a `guix package -i emacs` away!
-If you have questions that are not covered by the manual feel free to
-chat with members of the Guix community
-[on IRC in the #guix channel on Freenode](
-For matters relating to using Guix in a bioinformatics environment you
-are welcome to subscribe and write to the
-[mailing list](
diff --git a/posts/2015-06-21-getting-started-with-guix.skr b/posts/2015-06-21-getting-started-with-guix.skr
new file mode 100644 (file)
index 0000000..503978f
--- /dev/null
@@ -0,0 +1,113 @@
+(define meta
+  `((title . "Getting started with GNU Guix")
+    (date  . ,(string->date* "2015-06-21 00:00"))
+    (tags "gnu" "free software" "system administration" "packaging" "guix")))
+ (p [,(ref "/posts/2015-04-17-gnu-guix.html" "Previously I wrote")
+     about how using GNU Guix in an HPC environment enables easy
+     software deployment for multiple users with different needs when
+     it comes to application and library versions.  Although Guix comes
+     with an excellent manual which is also ,(ref
+     "" "available
+     online"), some people may want to have just some simple
+     installation instructions in one place and some pointers to get
+     started.  I’m attempting to provide just that with this article.])
+ (p [While Guix can be built from source it is much more convenient to
+     use the self-contained tarball which provides pre-built binaries
+     for Guix and all its dependencies.  You need to have GNU tar and
+     xz installed to unpack the tarball.  Note that the tarball will
+     only work on GNU/Linux systems; it will not work on MacOS.])
+ (h2 [Six simple steps])
+ (p [,(em [First]), if you are using a 64 bit machine, download the
+     compressed ,(ref
+     ""
+     "x86_64 archive from the FTP server").  There also is a ,(ref
+     ""
+     "tarball for 32 bit machines") and ,(ref
+     ""
+     "one for the less common MIPS").])
+ (p [,(em [Second]), unpack the archive as root in the root directory:])
+ (pre (code [# cd /
+# tar xf guix-binary-0.8.2.SYSTEM.tar.xz]))
+ (p [This creates a pre-populated store at ,(code [/gnu/store])
+     (containing the “guix” package and the complete dependency graph),
+     the ,(em [local state directory]) ,(code [/var/guix]), and a Guix
+     profile for the root user at ,(code [/root/.guix-profile]), which
+     contains the guix command line tools and the daemon.])
+ (p [,(em [Third]), create a build user pool, as root:])
+ (pre (code [# groupadd --system guix-builder
+# for i in `seq 1 10`;
+  do
+    useradd -g guix-builder -G guix-builder           \
+            -d /var/empty -s `which nologin`          \
+            -c "Guix build user $i" --system          \
+            guix-builder$i;
+  done]))
+ (p [These are the restricted user accounts which are used by the
+     daemon to build software in a controlled environment.  You may not
+     need ten, but it’s a good default.])
+ (p [,(em [Fourth]), run the daemon and tell it about the ,(code
+     [guix-builder]) group:])
+ (pre (code [# /root/.guix-profile/bin/guix-daemon --build-users-group=guix-builder]))
+ (p [,(em [Fifth]), make the ,(code [guix]) command available to other users
+     on the machine by linking it to a location everyone can access,
+     such as ,(code [/usr/local/bin]).])
+ (pre (code [# mkdir -p /usr/local/bin
+# cd /usr/local/bin
+# ln -s /root/.guix-profile/bin/guix]))
+ (p [Now any user—not just the almighty root—can install software by
+     invoking ,(code [guix package -i whatever]).  Yay!])
+ (p [,(em [Finally]), if you do not want to build all software locally
+     (which can take a very long time) and you think you can trust the
+     GNU Guix build farm, authorise it as a source for
+     so-called binary substitutes using the included public key:])
+ (pre (code [# guix archive --authorize < /root/.guix-profile/share/guix/]))
+ (p [Note that isn’t at all special.  Packages are built
+     there continuously from source.  Guix is flexible and can pull
+     binary substitutes from other locations as long as you authorise
+     them.])
+ (h2 [Where to go from here])
+ (p [Congratulations!  You now have a fully functional installation of
+     the Guix package manager.])
+ (p [To get the latest package recipes for Guix just run ,(code [guix
+     pull]), which will download and compile the most recent
+     development version.])
+ (p [I recommend reading the excellent Guix reference manual, which is
+     ,(ref ""
+     "available on the web") and, of course, included as an Info
+     document in your Guix installation.  If you don’t have Emacs—the
+     best Info reader, which also happens to be an excellent text
+     editor—I encourage you to install it from Guix; it is just a
+     ,(code [guix package -i emacs]) away!])
+ (p [If you have questions that are not covered by the manual feel free
+     to chat with members of the Guix community ,(ref
+     "" "on IRC in the
+     #guix channel on Freenode").  For matters relating to using Guix
+     in a bioinformatics environment you are welcome to subscribe and
+     write to the ,(ref
+     ""
+     "mailing list").]))
diff --git a/static/index.markdown b/static/index.markdown
deleted file mode 100644 (file)
index 6fb8424..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# Free software and music
-My name is rekado and I'm currently working as a programmer and
-[GNU/Linux]( server administrator.  I enjoy writing
-Free Software.  You can find some of
-[my code here]( or on
-[Github](  At night I'm a musician. I play
-the [Chapman Stick](  Some of my recordings and
-performances can be found on
-[SoundCloud]( or on
-You can contact me via email at <span
-class="obfuscated">sflbep,xfcAfmfqimz/ofu</span>.  Please use
-[my public key](/rekado.pubkey) when writing me email.  If you don't
-know much about encrypting email please take a look at the
-[email self-defense website]( by the
-[Free Software Foundation](
-## [Blog](/posts)
-On occasion I write articles.  Here's the
-[latest article](/posts/latest.html).  I recommend the series of posts
-on [hacking the Wavedrum](/tags/wavedrum.html).
-## [Projects](/projects.html)
-- [Wavedrum stuff](/wavedrum/index.html)
-- Libertree
-- [SoundCLI](/soundcli.html)
-- [LV2 Plugins](/lv2/mdapiano.html)
-## Ecology
-Currently I'm studying toward a Bachelor of Applied Science via
-distance learning at the
-[Open Polytechnic](  Some of my
-[writings on ecology can be found in this section](ecology.html).
-## Weird stuff
-- [The Elephly](/elephly.html)
-- [Fur man](/fur-man.html)
diff --git a/static/lv2/mdaepiano.markdown b/static/lv2/mdaepiano.markdown
deleted file mode 100644 (file)
index 5865adf..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-# mda EPiano
-This is an LV2 port of the mda EPiano VSTi (not to be confused with the
-[mda Piano](/lv2/mdapiano.html)). The original VST that this port is
-based on was written by Paul Kellett.
-The original [announcement post can be found here](/posts/2010-10-14-chinese-tune-mda-epiano.html).
-## Compiling
-To compile the mda Piano plugin, just execute the following statement:
-    make && sudo make install
-This will copy the compiled plugin to `/usr/local/lib/lv2`.  To change
-the target prefix, pass the `PREFIX` variable to `make`.
-To build the mda EPiano plugin, pass `TYPE=mdaEPiano` to `make`:
-    make TYPE=mdaEPiano
-    sudo make install TYPE=mdaEPiano
-**NOTE**: you will need the [lvtoolkit libraries]( to
-compile this plugin.
-## Connecting
-You will need an LV2 host to use the plugin. I'm using `jalv.gtk`:
-    jalv.gtk
-You should now be able to connect your MIDI device to the plugin via JACK. Also
-don't forget to connect the plugin's stereo output to your system's outputs:
-    jack_connect system:playback_1 mdaPiano:left
-    jack_connect system:playback_2 mdaPiano:right
-I provide a simple connect script with the code which does these things
-## License
-The original mda VST plug-ins by Paul Kellett are released under the
-MIT license or under the GPL "either version 2 of the License, or (at
-your option) any later version". The LV2 ports of the mdaPiano and
-mdaEPiano plugins by rekado are released under GPLv3, or (at your
-option) any later version.
-## Download
-[Fetch the source here](
-The latest
-[release tarball can be downloaded here](
diff --git a/static/lv2/mdapiano.markdown b/static/lv2/mdapiano.markdown
deleted file mode 100644 (file)
index ccb1142..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-# mdaPiano
-This is an LV2 port of the mdaPiano VSTi (not to be confused with the
-[mdaEPiano](/lv2/mdaepiano.html)). The original VST that this port is based on
-was written by Paul Kellett.
-## Compiling
-To compile the mda Piano plugin, just execute the following statement:
-    make && sudo make install
-This will copy the compiled plugin to `/usr/local/lib/lv2`.  To change
-the target prefix, pass the `PREFIX` variable to `make`.
-To build the mda EPiano plugin, pass `TYPE=mdaEPiano` to `make`:
-    make TYPE=mdaEPiano
-    sudo make install TYPE=mdaEPiano
-**NOTE**: you will need the [lvtoolkit libraries]( to
-compile this plugin.
-## Connecting
-You will need an LV2 host to use the plugin. I'm using `jalv.gtk`:
-    jalv.gtk
-You should now be able to connect your MIDI device to the plugin via JACK. Also
-don't forget to connect the plugin's stereo output to your system's outputs:
-    jack_connect system:playback_1 mdaPiano:left
-    jack_connect system:playback_2 mdaPiano:right
-I provide a simple connect script with the code which does these things
-## License
-The original mda VST plug-ins by Paul Kellett are released under the
-MIT license or under the GPL "either version 2 of the License, or (at
-your option) any later version". The LV2 ports of the mdaPiano and
-mdaEPiano plugins by rekado are released under GPLv3, or (at your
-option) any later version.
-## Download
-[Fetch the source here](
-The latest
-[release tarball can be downloaded here](
diff --git a/static/projects.markdown b/static/projects.markdown
deleted file mode 100644 (file)
index f64a252..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-# Projects
-Here is a list of some of the projects that I'm involved with that
-actually might be useful to others.
-## Hacking the Wavedrum
-I wrote a [series of blog posts](/tags/wavedrum.html) in which I
-document my efforts to understand and possibly manipulate the firmware
-of Korg's Wavedrum.  The PCB is easily accessible and exposes big
-connector pads as well as a microSD card---an invitation to play with
-the hardware.
-The [project page](/wavedrum/index.html) is the best place to get an
-overview and to see the current status.  It contains links to the
-sources of any software artifacts I create in the process.
-## GNU Guix
-[GNU Guix]( is a novel package manager for
-[GNU systems](  In Guix a package is treated as a pure
-function whose output is fully described by its inputs (its
-dependencies).  I'm packaging lots of bioinformatics software when I'm
-in the office and audio tools when I'm off work.
-## Libertree
-[Libertree]( is a collection of software
-to build social networks.  The core components include a web frontend
-application and an XMPP backend component that will work with any
-regular XMPP server.
-![The Libertree logo](/images/libertree-logo.png)
-If you want to test Libertree, request an invitation to [my server]( by sending an email to <span class="obfuscated">mjcfsusffAfmfqimz/ofu</span>.
-You can also run Libertree on your own server if you wish. The code for all components is hosted on [github]( Refer to the [installation
-or use the [installer]( If you need help, just ask in our chat channel ([#libertree]( on Freenode).  
-I'm currently working on turning Libertree into a [pubsub service](
-Here is [a collection of public announcements]( I made on Libertree.
-## SoundCLI
-[SoundCLI](/soundcli.html) is a SoundCloud client for the console. Check out
-the [project page](/soundcli.html) for more information.
-## LV2 plugins
-I have ported two VST instruments to the LV2 plugin framework, because I missed
-them after my move to GNU/Linux.
-- [mda EPiano](/lv2/mdaepiano.html)
-- [mda Piano](/lv2/mdapiano.html)
diff --git a/static/wavedrum/index.markdown b/static/wavedrum/index.markdown
deleted file mode 100644 (file)
index 4b48e62..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-# Wavedrum
-I wrote a [series of blog posts](/tags/wavedrum.html) in which I
-document my efforts to understand and possibly manipulate the firmware
-of Korg's Wavedrum.  The PCB is easily accessible and exposes big
-connector pads as well as a microSD card---an invitation to play with
-the hardware.
-Although I'm perfectly content just playing with the hardware, I do
-hope that my work will eventually allow me and others to modify the
-data on the Wavedrum such that custom sounds and loops (and possibly
-algorithms) can be used.
-## Current status
-It is possible to load firmware from the microSD card by pressing
-*Write* and *1* while powering on the Wavedrum, followed by pressing
-*Write* again (another undocumented mode can be entered by pressing
-*Write* and *Mode* while powering on).
-The Wavedrum unfortunately rejects any modified firmware.  The
-Oriental edition will not load the firmware of the Original/Black
-edition, nor will it load the firmware of the Global edition.  It also
-won't load any modified firmware (e.g. where the only difference is
-that two bytes are swapped).  I intend to figure out how the Wavedrum
-validates the data on the SD card before deciding to reject them.
-## Blog posts
-- [Hacking the Wavedrum](/posts/2013-08-11-hacking-the-wavedrum.html)
-- [Firmware comparison between Wavedrums Original, Black and Oriental](/posts/2013-10-31-wavedrum-data-comparison.html)
-- [Connectors on the Wavedrum's circuit board](/posts/2013-12-09-wavedrum-connectors.html)
-- [Disassembling the Wavedrum firmware](/posts/2014-09-18-wavedrum-firmware-disassembler.html)
-## Software
-:   Haskell library for parsing, editing, and writing Wavedrum
-    programmes (presets).
-:   Very rudimentary, partial disassembler for SHARC ADSP binaries
-    helping me to understand the Wavedrum's bootloader.