summaryrefslogtreecommitdiff
path: root/posts
diff options
context:
space:
mode:
authorrekado <rekado@elephly.net>2015-08-16 05:15:04 +0200
committerrekado <rekado@elephly.net>2015-08-17 22:56:02 +0200
commit0d58b658a63f4ec3e938deffee22763131a816b8 (patch)
tree95f5475f5bb021209f9d239af29d6c58d11c72a0 /posts
parent69b4e3db8cac30029fb94640f30354ac7c338b5b (diff)
Convert articles to skribe format.
Diffstat (limited to 'posts')
-rw-r--r--posts/2009-07-01-chapman_stick.markdown29
-rw-r--r--posts/2009-07-01-chapman_stick.skr36
-rw-r--r--posts/2010-03-23-fur-man.markdown22
-rw-r--r--posts/2010-03-23-fur-man.skr27
-rw-r--r--posts/2010-03-26-billie-jean.markdown24
-rw-r--r--posts/2010-03-26-billie-jean.skr30
-rw-r--r--posts/2010-03-26-rehearsals.markdown13
-rw-r--r--posts/2010-03-26-rehearsals.skr13
-rw-r--r--posts/2010-03-26-youku-niuren.markdown12
-rw-r--r--posts/2010-03-26-youku-niuren.skr13
-rw-r--r--posts/2010-03-26-youku-vs-tudou-final.markdown11
-rw-r--r--posts/2010-03-26-youku-vs-tudou-final.skr12
-rw-r--r--posts/2010-03-28-elephly.markdown21
-rw-r--r--posts/2010-03-28-elephly.skr26
-rw-r--r--posts/2010-04-05-deng-hou.markdown92
-rw-r--r--posts/2010-04-05-deng-hou.skr108
-rw-r--r--posts/2010-04-12-jiatingyanboshi.markdown21
-rw-r--r--posts/2010-04-12-jiatingyanboshi.skr24
-rw-r--r--posts/2010-06-01-chapman-stick-on-national-tv.markdown39
-rw-r--r--posts/2010-06-01-chapman-stick-on-national-tv.skr44
-rw-r--r--posts/2010-06-24-2010-niuren.markdown28
-rw-r--r--posts/2010-06-24-2010-niuren.skr33
-rw-r--r--posts/2010-07-02-newspaper.markdown25
-rw-r--r--posts/2010-07-02-newspaper.skr31
-rw-r--r--posts/2010-07-08-wishful-thinking.markdown88
-rw-r--r--posts/2010-07-08-wishful-thinking.skr92
-rw-r--r--posts/2010-07-14-one-night-in-beijing.markdown62
-rw-r--r--posts/2010-07-14-one-night-in-beijing.skr73
-rw-r--r--posts/2010-08-04-alto-stick.markdown18
-rw-r--r--posts/2010-08-04-alto-stick.skr36
-rw-r--r--posts/2010-08-15-yueyintang.markdown39
-rw-r--r--posts/2010-08-15-yueyintang.skr40
-rw-r--r--posts/2010-08-17-tianshi.markdown92
-rw-r--r--posts/2010-08-17-tianshi.skr88
-rw-r--r--posts/2010-10-14-chinese-tune-mda-epiano.markdown24
-rw-r--r--posts/2010-10-14-chinese-tune-mda-epiano.skr35
-rw-r--r--posts/2012-01-25-new-blog.markdown10
-rw-r--r--posts/2012-01-25-new-blog.skr11
-rw-r--r--posts/2013-01-27-preamp-board-arrived.markdown42
-rw-r--r--posts/2013-01-27-preamp-board-arrived.skr50
-rw-r--r--posts/2013-05-24-improvisation.markdown22
-rw-r--r--posts/2013-05-24-improvisation.skr28
-rw-r--r--posts/2013-08-11-hacking-the-wavedrum.markdown420
-rw-r--r--posts/2013-08-11-hacking-the-wavedrum.skr454
-rw-r--r--posts/2013-10-01-dm-crypt.markdown71
-rw-r--r--posts/2013-10-01-dm-crypt.skr87
-rw-r--r--posts/2013-10-31-wavedrum-data-comparison.markdown72
-rw-r--r--posts/2013-10-31-wavedrum-data-comparison.skr82
-rw-r--r--posts/2013-12-09-wavedrum-connectors.markdown135
-rw-r--r--posts/2013-12-09-wavedrum-connectors.skr149
-rw-r--r--posts/2014-09-18-wavedrum-firmware-disassembler.markdown120
-rw-r--r--posts/2014-09-18-wavedrum-firmware-disassembler.skr136
-rw-r--r--posts/2014-11-23-upgrading-trulyergonomic-firmware.markdown88
-rw-r--r--posts/2014-11-23-upgrading-trulyergonomic-firmware.skr99
-rw-r--r--posts/2015-04-17-gnu-guix.markdown292
-rw-r--r--posts/2015-04-17-gnu-guix.skr315
-rw-r--r--posts/2015-06-21-getting-started-with-guix.markdown105
-rw-r--r--posts/2015-06-21-getting-started-with-guix.skr113
58 files changed, 2285 insertions, 2037 deletions
diff --git a/posts/2009-07-01-chapman_stick.markdown b/posts/2009-07-01-chapman_stick.markdown
deleted file mode 100644
index d576b92..0000000
--- a/posts/2009-07-01-chapman_stick.markdown
+++ /dev/null
@@ -1,29 +0,0 @@
----
-title: The Chapman Stick®
-date: 2009/07/01
-tags: music, chapman stick
----
-
-The [Chapman Stick](http://stick.com) is a stringed instrument invented quite
-some time ago by [Emmett Chapman](http://www.emmettchapman.net). 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.
-
-![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](http://stick.com/instruments/tunings/12/classic_66).
-
-Check out the [official website](http://stick.com) 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](http://www.chapdoc.com/trailer.html).
-
-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
index 0000000..119b941
--- /dev/null
+++ b/posts/2009-07-01-chapman_stick.skr
@@ -0,0 +1,36 @@
+(define meta
+ `((title . "The Chapman Stick®")
+ (date . ,(string->date* "2009-07-01 00:00"))
+ (tags "music" "chapman stick")))
+
+(list
+ (p [The ,(ref "http://stick.com" [Chapman Stick]) is a stringed
+ instrument invented quite some time ago by ,(ref
+ "http://www.emmettchapman.net" [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 "http://stick.com/instruments/tunings/12/classic_66"
+ [improvements and innovations]).])
+
+ (p [Check out the ,(ref "http://stick.com" [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 "http://www.chapdoc.com/trailer.html" [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
index cf245ed..0000000
--- a/posts/2010-03-23-fur-man.markdown
+++ /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'/>
-</a>
-
-**Update:**
-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
index 0000000..15273f4
--- /dev/null
+++ b/posts/2010-03-23-fur-man.skr
@@ -0,0 +1,27 @@
+(define meta
+ `((title . "Fur Man")
+ (date . ,(string->date* "2010-03-23 00:00"))
+ (license . "by-sa")
+ (tags "drawing" "weird")))
+
+(list
+ (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
index 9d3901f..0000000
--- a/posts/2010-03-26-billie-jean.markdown
+++ /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](http://v.youku.com/v_show/id_XMTMyOTc3Nzcy.html) 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 [Youku.com](http://youku.com). 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](http://v.youku.com/v_show/id_XMTMzMDA1MDU2.html).
-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
-here](http://v.youku.com/v_show/id_XMTMyOTc3Nzcy.html).
diff --git a/posts/2010-03-26-billie-jean.skr b/posts/2010-03-26-billie-jean.skr
new file mode 100644
index 0000000..3c20155
--- /dev/null
+++ b/posts/2010-03-26-billie-jean.skr
@@ -0,0 +1,30 @@
+(define meta
+ `((title . "Billie Jean")
+ (date . ,(string->date* "2010-03-26 00:00"))
+ (tags "video" "music")))
+
+(list
+ (figure "billiejean.png" "Playing Billie Jean on the Stick")
+
+ (p [,(ref "http://v.youku.com/v_show/id_XMTMyOTc3Nzcy.html" "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
+ "http://youku.com" "Youku.com"). 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
+ "http://v.youku.com/v_show/id_XMTMzMDA1MDU2.html" "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 "http://v.youku.com/v_show/id_XMTMyOTc3Nzcy.html" "can be
+ seen here").]))
+
diff --git a/posts/2010-03-26-rehearsals.markdown b/posts/2010-03-26-rehearsals.markdown
deleted file mode 100644
index d6b3c51..0000000
--- a/posts/2010-03-26-rehearsals.markdown
+++ /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](http://v.youku.com/v_show/id_XMTUxMDczMDE2.html) 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
index 0000000..82e55c4
--- /dev/null
+++ b/posts/2010-03-26-rehearsals.skr
@@ -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")))
+
+(list
+ (p [,(ref "http://v.youku.com/v_show/id_XMTUxMDczMDE2.html" "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
index 18887e5..0000000
--- a/posts/2010-03-26-youku-niuren.markdown
+++ /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
-ceremony](http://v.youku.com/v_show/id_XMTQ3NjI2MzYw.html).
diff --git a/posts/2010-03-26-youku-niuren.skr b/posts/2010-03-26-youku-niuren.skr
new file mode 100644
index 0000000..b64dc63
--- /dev/null
+++ b/posts/2010-03-26-youku-niuren.skr
@@ -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")))
+
+(list
+ (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 "http://v.youku.com/v_show/id_XMTQ3NjI2MzYw.html" "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
index 6798698..0000000
--- a/posts/2010-03-26-youku-vs-tudou-final.markdown
+++ /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](http://v.youku.com/v_show/id_XMTUxNTM5NjUy.html) 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
index 0000000..4b70029
--- /dev/null
+++ b/posts/2010-03-26-youku-vs-tudou-final.skr
@@ -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")))
+
+(list
+ (p [Here is a ,(ref "http://v.youku.com/v_show/id_XMTUxNTM5NjUy.html"
+ "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
index 99b45a0..0000000
--- a/posts/2010-03-28-elephly.markdown
+++ /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
index 0000000..9696367
--- /dev/null
+++ b/posts/2010-03-28-elephly.skr
@@ -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")))
+
+(list
+
+ (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
index 982da7b..0000000
--- a/posts/2010-04-05-deng-hou.markdown
+++ /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="https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6334329"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src="https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6334329" type="application/x-shockwave-flash" width="100%"></embed> </object> <span><a href="http://soundcloud.com/rekado/deng-hou">等候</a> by <a href="http://soundcloud.com/rekado">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
-微笑 的感觉那么简单的回来
-</pre>
-
-### 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
-黎明的方向
-</pre>
-
-### 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
-的生活呈现在我的脑海
-</pre>
-
-
-### 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
-黎明的曙光
-</pre>
diff --git a/posts/2010-04-05-deng-hou.skr b/posts/2010-04-05-deng-hou.skr
new file mode 100644
index 0000000..7f8c7c4
--- /dev/null
+++ b/posts/2010-04-05-deng-hou.skr
@@ -0,0 +1,108 @@
+(define meta
+ `((title . "Deng Hou")
+ (date . ,(string->date* "2010-04-05 00:00"))
+ (flattr . "325437")
+ (tags "music" "chinese")))
+
+(list
+
+ (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 "https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6334329")))
+ (param (@ (name "allowscriptaccess")
+ (value "always")))
+ (embed (@ (allowscriptaccess "always")
+ (height "81")
+ (src "https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6334329")
+ (type "application/x-shockwave-flash")
+ (width "100%"))))
+
+ '(span (a (@ (href "http://soundcloud.com/rekado/deng-hou")) "等候")
+ " by "
+ (a (@ (href "http://soundcloud.com/rekado")) "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
index edb0242..0000000
--- a/posts/2010-04-12-jiatingyanboshi.markdown
+++ /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
-program.
-
-**Update (April 18, 2010):** A 20 minute section of [the show is already
-online](http://www.letv.com/ptv/vplay/660375.html).
-
-**Update (April 21, 2010):** [Part B](http://ent.joy.cn/video/1168864.htm) and
-[part C](http://ent.joy.cn/video/1168865.htm) 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
index 0000000..f31c3bc
--- /dev/null
+++ b/posts/2010-04-12-jiatingyanboshi.skr
@@ -0,0 +1,24 @@
+(define meta
+ `((title . "Jia Ting Yan Bo Shi")
+ (date . ,(string->date* "2010-04-12 00:00"))
+ (tags "tv" "chinese")))
+
+(list
+ (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
+ "http://www.letv.com/ptv/vplay/660375.html" "the show is already
+ online").])
+
+ (p [,(strong [Update (April 21, 2010):]) ,(ref
+ "http://ent.joy.cn/video/1168864.htm" "Part B") and ,(ref
+ "http://ent.joy.cn/video/1168865.htm" "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
index a39d0d7..0000000
--- a/posts/2010-06-01-chapman-stick-on-national-tv.markdown
+++ /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](http://v.youku.com/v_show/id_XMTc3OTAyMTY0.html) 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
-here](/downies/videos/qjdls_chapman_stick_1.mp4).
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
index 0000000..7f5f878
--- /dev/null
+++ b/posts/2010-06-01-chapman-stick-on-national-tv.skr
@@ -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")))
+
+(list
+ (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
+ "http://v.youku.com/v_show/id_XMTc3OTAyMTY0.html" "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
index a58b1dd..0000000
--- a/posts/2010-06-24-2010-niuren.markdown
+++ /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](http://v.youku.com/v_show/id_XMTgzNDE0OTU2.html)! If you prefer to watch
-a version that I'm okay with, then [check out the older
-video](/posts/2009-11-02-qtbhl.html).
-
-**Update (June 29, 2010)**: There is a [short clip on
-youku](http://v.youku.com/v_show/id_XMTg1MjkyODAw.html) 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
index 0000000..1e2dff6
--- /dev/null
+++ b/posts/2010-06-24-2010-niuren.skr
@@ -0,0 +1,33 @@
+(define meta
+ `((title . "2010 Youku Niuren Competition")
+ (date . ,(string->date* "2010-06-24 00:00"))
+ (tags "music" "show" "youku")))
+
+(list
+ (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
+ "http://v.youku.com/v_show/id_XMTgzNDE0OTU2.html" "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
+ "http://v.youku.com/v_show/id_XMTg1MjkyODAw.html" "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
index 0dc3b0d..0000000
--- a/posts/2010-07-02-newspaper.markdown
+++ /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"](http://www.yesqiaobao.com). Later the journalist asked me to send her
-some photos of myself playing an instrument to illustrate an article they were
-preparing.
-
-The article is now available online, both as a [newspaper-styled
-image](http://www.yesqiaobao.com/qilinzhoukan/epaper/linfen/html/2010/06/30/C1/images/back.jpg)
-and a [text
-version](http://www.yesqiaobao.com/qilinzhoukan/epaper/linfen/html/2010/06/30/C1/C1_40.htm).
-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
index 0000000..0c07319
--- /dev/null
+++ b/posts/2010-07-02-newspaper.skr
@@ -0,0 +1,31 @@
+(define meta
+ `((title . "Newspaper Report")
+ (date . ,(string->date* "2010-07-02 00:00"))
+ (tags "niuren" "youku" "chapman stick" "media")))
+
+(list
+
+ (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 "http://www.yesqiaobao.com" "“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
+ "http://www.yesqiaobao.com/qilinzhoukan/epaper/linfen/html/2010/06/30/C1/images/back.jpg"
+ "newspaper-styled image") and a ,(ref
+ "http://www.yesqiaobao.com/qilinzhoukan/epaper/linfen/html/2010/06/30/C1/C1_40.htm"
+ "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
index e5a7339..0000000
--- a/posts/2010-07-08-wishful-thinking.markdown
+++ /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
-dream.
-
-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.)
-
-<blockquote>
-
- <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>
-
-</blockquote>
-
-
-&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
index 0000000..7abf251
--- /dev/null
+++ b/posts/2010-07-08-wishful-thinking.skr
@@ -0,0 +1,92 @@
+(define meta
+ `((title . "Wishful Thinking")
+ (date . ,(string->date* "2010-07-08 00:00"))
+ (tags "musings" "ecology" "energy")))
+
+(list
+
+ (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
index 64535c5..0000000
--- a/posts/2010-07-14-one-night-in-beijing.markdown
+++ /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
-hotel.
-
-![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
-confirmed.
-
-**Update (July 29):*** The short video clip has been uploaded. You can [watch
-it on youku](http://v.youku.com/v_show/id_XMTkzMzc1NDI4.html).
-
-**Update:*** Gao Ming interviewed the participants during the preparations of
-the show. There is a 25+ minutes [video clip on
-youku](http://v.youku.com/v_show/id_XMTg5NzMwNDI4.html). 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
index 0000000..9027747
--- /dev/null
+++ b/posts/2010-07-14-one-night-in-beijing.skr
@@ -0,0 +1,73 @@
+(define meta
+ `((title . "One Night In Beijing")
+ (date . ,(string->date* "2010-07-14 00:00"))
+ (tags "music" "youku" "video" "show")))
+
+(list
+ (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
+ "http://v.youku.com/v_show/id_XMTkzMzc1NDI4.html" "watch it on
+ youku").])
+
+ (p [,(strong [Update:]) Gao Ming interviewed the participants during
+ the preparations of the show. There is a 25+ minutes ,(ref
+ "http://v.youku.com/v_show/id_XMTg5NzMwNDI4.html" "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
index d5687ba..0000000
--- a/posts/2010-08-04-alto-stick.markdown
+++ /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
-morning.
-
-There are many bumps in this recording, still I like it. Maybe you do, too.
-
-<object height="81" width="100%"> <param name="movie" value="https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F34493000&amp;show_comments=true&amp;auto_play=false&amp;color=ff7700"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src="https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F34493000&amp;show_comments=true&amp;auto_play=false&amp;color=ff7700" type="application/x-shockwave-flash" width="100%"></embed> </object> <span><a href="http://soundcloud.com/rekado/flow">Flow</a> by <a href="http://soundcloud.com/rekado">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
index 0000000..0c90d06
--- /dev/null
+++ b/posts/2010-08-04-alto-stick.skr
@@ -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")))
+
+(list
+ (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 "https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F34493000&amp;show_comments=true&amp;auto_play=false&amp;color=ff7700")))
+ (param (@ (name "allowscriptaccess")
+ (value "always")))
+ (embed (@ (allowscriptaccess "always")
+ (height "81")
+ (src "https://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F34493000&amp;show_comments=true&amp;auto_play=false&amp;color=ff7700")
+ (type "application/x-shockwave-flash")
+ (width "100%"))))
+
+ `(span
+ ,(ref "http://soundcloud.com/rekado/flow" "Flow")
+ " by "
+ ,(ref "http://soundcloud.com/rekado" "rekado")))
diff --git a/posts/2010-08-15-yueyintang.markdown b/posts/2010-08-15-yueyintang.markdown
deleted file mode 100644
index d070c68..0000000
--- a/posts/2010-08-15-yueyintang.markdown
+++ /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
-little.
-
-"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
-tonight.
diff --git a/posts/2010-08-15-yueyintang.skr b/posts/2010-08-15-yueyintang.skr
new file mode 100644
index 0000000..bd350ee
--- /dev/null
+++ b/posts/2010-08-15-yueyintang.skr
@@ -0,0 +1,40 @@
+(define meta
+ `((title . "Yueyin Tang")
+ (date . ,(string->date* "2010-08-15 00:00"))
+ (tags "music")))
+
+(list
+ (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
index 4da1752..0000000
--- a/posts/2010-08-17-tianshi.markdown
+++ /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
-earlier](/posts/2010-08-05-flow-on-the-alto-stick-video.html).
-
-(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 youku.com 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'/>
-</video>
-
-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](http://videolan.org). If you are on Linux `mplayer` will work fine,
-too.
-
-
-## 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>
-
-<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>
-</div>
-
-
-## 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>
-
-<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>
-</div>
-
-## Streaming
-
-The video is available on both
-[Youku](http://v.youku.com/v_show/id_XMTk5MDQ4MDE2.html) and
-[YouTube](http://www.youtube.com/watch?v=rSclwOFYIYc).
diff --git a/posts/2010-08-17-tianshi.skr b/posts/2010-08-17-tianshi.skr
new file mode 100644
index 0000000..69dc223
--- /dev/null
+++ b/posts/2010-08-17-tianshi.skr
@@ -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")))
+
+(list
+ (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 youku.com 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 "http://videolan.org" "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
+ "http://v.youku.com/v_show/id_XMTk5MDQ4MDE2.html" "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
index 9b8b984..0000000
--- a/posts/2010-10-14-chinese-tune-mda-epiano.markdown
+++ /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](http://mda-vst.com) 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="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6120886&amp;show_comments=true&amp;auto_play=false&amp;color=ffaa00"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6120886&amp;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](http://soundcloud.com/rekado/chinese-tune).
-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
-here](/downies/music/chinese-tune.mid).
-
-The LV2 port can be
-[downloaded from my git repository](http://git.elephly.net/software/lv2-mdametapiano.git).
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
index 0000000..b009a89
--- /dev/null
+++ b/posts/2010-10-14-chinese-tune-mda-epiano.skr
@@ -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")))
+
+(list
+ (p [In the past two days (actually, mornings and evenings) I have
+ been working on porting the famous ,(ref "http://mda-vst.com"
+ "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 "http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6120886&amp;show_comments=true&amp;auto_play=false&amp;color=ffaa00")))
+ (param (@ (name "allowscriptaccess") (value "always")))
+ (embed (@ (allowscriptaccess "always")
+ (height "81")
+ (src "http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F6120886&amp;show_comments=true&amp;auto_play=false&amp;color=ffaa00")
+ (type "application/x-shockwave-flash")
+ (width "100%"))))
+
+ (p [You can ,(ref "http://soundcloud.com/rekado/chinese-tune"
+ "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
+ "http://git.elephly.net/software/lv2-mdametapiano.git"
+ "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
index e661ee3..0000000
--- a/posts/2012-01-25-new-blog.markdown
+++ /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
index 0000000..4d2e0f8
--- /dev/null
+++ b/posts/2012-01-25-new-blog.skr
@@ -0,0 +1,11 @@
+(define meta
+ `((title . "New Blog")
+ (date . ,(string->date* "2012-01-25 00:00"))
+ (tags "meta")))
+
+(list
+ (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
index aee96d9..0000000
--- a/posts/2013-01-27-preamp-board-arrived.markdown
+++ /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](http://taobao.com) 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](http://www.fsf.org/about/what-is-free-software) programs
-`gschem` and `pcb` of the excellent
-[gEDA suite](http://www.geda-project.org). (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](http://git.elephly.net/hardware/stick-preamp.git) I
-set up for this project.
-
-![Oops.](/images/posts/pcb-2.jpg)
-
-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
index 0000000..5888ef8
--- /dev/null
+++ b/posts/2013-01-27-preamp-board-arrived.skr
@@ -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")))
+
+(list
+ (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
+ "http://taobao.com" "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
+ "http://www.fsf.org/about/what-is-free-software" "free") programs
+ ,(code [gschem]) and ,(code [pcb]) of the excellent ,(ref
+ "http://www.geda-project.org" "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
+ "http://git.elephly.net/hardware/stick-preamp.git" "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
index 05846f1..0000000
--- a/posts/2013-05-24-improvisation.markdown
+++ /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](http://coursera.org) MOOC
-[Introduction to
-Improvisation](https://class.coursera.org/improvisation-001/).
-
-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
-SoundCloud](https://soundcloud.com/rekado/sets/gary-burtons-improvisation),
-embedded below:
-
-<iframe width="100%" height="450" scrolling="no" frameborder="no"
-src="http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F5556211&show_artwork=true"></iframe> \ 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
index 0000000..051708b
--- /dev/null
+++ b/posts/2013-05-24-improvisation.skr
@@ -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")))
+
+(list
+ (p [Since a few weeks I’m learning how to play more interesting jazz
+ solos from Gary Burton through his ,(ref "http://coursera.org"
+ "Coursera") MOOC ,(ref
+ "https://class.coursera.org/improvisation-001/" "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
+ "https://soundcloud.com/rekado/sets/gary-burtons-improvisation"
+ "on SoundCloud"), embedded below:])
+
+ '(iframe (@ (width "100%")
+ (height "450")
+ (scrolling "no")
+ (frameborder "no")
+ (src "http://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Fplaylists%2F5556211&show_artwork=true"))))
diff --git a/posts/2013-08-11-hacking-the-wavedrum.markdown b/posts/2013-08-11-hacking-the-wavedrum.markdown
deleted file mode 100644
index 0046386..0000000
--- a/posts/2013-08-11-hacking-the-wavedrum.markdown
+++ /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
-head.
-
-<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>
-**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.
-</warning>
-
-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
-lifted.
-
-![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>&#x22ee;</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>
-</ul>
-
-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](http://sox.sourceforge.net) 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,
-SYSTEM/WDX_M100.BIN, SYSTEM/WDX_S100.BIN, and SUBXXXXX.BIN (a
-pattern?).
-
-
-# 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](https://en.wikipedia.org/wiki/Two%27s_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
-[free](https://www.fsf.org/about/what-is-free-software)
-[here](http://git.elephly.net/wavedrum/wavedrum-lib.git) under the
-[GNU GPLv3](https://gnu.org/licenses/gpl.html).
-
-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`](http://www.isthe.com/chongo/tech/comp/calc/), a calculator
- for the command line supporting hexadecimal representations of
- numbers (both input and output using the `base` and `base2`
- functions)
-
-- [`vbindiff`](http://www.cjmweb.net/vbindiff/), a tool to visualise
- differences between two binary files with a split-screen hexadecimal
- display
-
-- [`ghex`](https://wiki.gnome.org/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
-size).
-
-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](http://elephly.net/tags/wavedrum.html).
diff --git a/posts/2013-08-11-hacking-the-wavedrum.skr b/posts/2013-08-11-hacking-the-wavedrum.skr
new file mode 100644
index 0000000..39115a3
--- /dev/null
+++ b/posts/2013-08-11-hacking-the-wavedrum.skr
@@ -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)))
+
+(list
+
+ (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 "http://sox.sourceforge.net" "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,
+ SYSTEM/WDORS100.BIN, SYSTEM/WDX_M100.BIN, SYSTEM/WDX_S100.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
+ "https://en.wikipedia.org/wiki/Two%27s_complement" "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
+ "https://www.fsf.org/about/what-is-free-software" "free") ,(ref
+ "http://git.elephly.net/wavedrum/wavedrum-lib.git" "here") under
+ the ,(ref "https://gnu.org/licenses/gpl.html" "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 "http://www.isthe.com/chongo/tech/comp/calc/" "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 "http://www.cjmweb.net/vbindiff/" "vbindiff"), a tool to
+ visualise differences between two binary files with a
+ split-screen hexadecimal display])
+
+ (li [,(ref "https://wiki.gnome.org/Ghex" "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
+ "rekado@elephly.net").])
+
+ (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
index 401de87..0000000
--- a/posts/2013-10-01-dm-crypt.markdown
+++ /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
-passphrase.
-
- 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
index 0000000..cae43e6
--- /dev/null
+++ b/posts/2013-10-01-dm-crypt.skr
@@ -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")))
+
+(list
+
+ (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
index 6c6320c..0000000
--- a/posts/2013-10-31-wavedrum-data-comparison.markdown
+++ /dev/null
@@ -1,72 +0,0 @@
----
-title: Firmware comparison between Wavedrums Original, Black and Oriental
-tags: DIY,electronics,music,hacking,wavedrum
----
-
-Since
-[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
-differ: `USER.BIN`, `CALIB.BIN`, `WD2_PROG.BIN`, `SYSTEM/VERSION.INF`,
-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
-Oriental:
-
- 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](http://elephly.net/tags/wavedrum.html).
diff --git a/posts/2013-10-31-wavedrum-data-comparison.skr b/posts/2013-10-31-wavedrum-data-comparison.skr
new file mode 100644
index 0000000..911777b
--- /dev/null
+++ b/posts/2013-10-31-wavedrum-data-comparison.skr
@@ -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)))
+
+(list
+
+ (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
index ab03368..0000000
--- a/posts/2013-12-09-wavedrum-connectors.markdown
+++ /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
-destination.
-
-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](http://www.analog.com/static/imported-files/data_sheets/ADSP-21371_21375.pdf)
-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](http://openocd.sourceforge.net) 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
-firmware.
-
-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](http://www.analog.com/static/imported-files/data_sheets/ADSP-21371_21375.pdf)
-- [ADSP hardware reference](http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf)
diff --git a/posts/2013-12-09-wavedrum-connectors.skr b/posts/2013-12-09-wavedrum-connectors.skr
new file mode 100644
index 0000000..a6382ed
--- /dev/null
+++ b/posts/2013-12-09-wavedrum-connectors.skr
@@ -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")))
+
+(list
+
+ (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
+ "http://www.analog.com/static/imported-files/data_sheets/ADSP-21371_21375.pdf"
+ "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 "http://openocd.sourceforge.net" "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 "http://www.analog.com/static/imported-files/data_sheets/ADSP-21371_21375.pdf"
+ "ADSP-21371/ADSP-21375 datasheet")])
+ (li [,(ref "http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf"
+ "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
index af8d043..0000000
--- a/posts/2014-09-18-wavedrum-firmware-disassembler.markdown
+++ /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](http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf)
-(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
-17-27:
-
-> 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](http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf)
-(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
-challenging.
-
-
-# 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](http://www.gnu.org/licenses/#GPL) and can be
-[downloaded here](http://git.elephly.net/wavedrum/sharc-disassembler.git).
-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](http://elephly.net/posts/2013-08-11-hacking-the-wavedrum.html)
-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](http://elephly.net/tags/wavedrum.html).
diff --git a/posts/2014-09-18-wavedrum-firmware-disassembler.skr b/posts/2014-09-18-wavedrum-firmware-disassembler.skr
new file mode 100644
index 0000000..244aecd
--- /dev/null
+++ b/posts/2014-09-18-wavedrum-firmware-disassembler.skr
@@ -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")))
+
+(list
+
+ (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
+ "http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf"
+ "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
+ "http://www.analog.com/static/imported-files/processor_manuals/ADSP-21367_hwr_rev2-1.pdf"
+ "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
+ "http://www.gnu.org/licenses/#GPL" "GPL") and can be ,(ref
+ "http://git.elephly.net/wavedrum/sharc-disassembler.git"
+ "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
index 25f470c..0000000
--- a/posts/2014-11-23-upgrading-trulyergonomic-firmware.markdown
+++ /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](http://modern.ie) 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](https://www.trulyergonomic.com/store/troubleshooting--truly-ergonomic-mechanical-keyboard#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
-*vboxusers*.
-
-
-## 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
-settings.
-
-
-## 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
index 0000000..b0b8ce3
--- /dev/null
+++ b/posts/2014-11-23-upgrading-trulyergonomic-firmware.skr
@@ -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")))
+
+(list
+
+ (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
+ "http://modern.ie" "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
+ "https://www.trulyergonomic.com/store/troubleshooting--truly-ergonomic-mechanical-keyboard#Reset"
+ "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
index d17d514..0000000
--- a/posts/2015-04-17-gnu-guix.markdown
+++ /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
-platforms.
-
-## 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
-problem.
-
-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](https://www.gnu.org/software/guix/), a functional package
-manager written in
-[Guile Scheme](https://www.gnu.org/software/guile/), the designated
-extension language for the [GNU system](https://www.gnu.org/).
-
-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](https://www.gnu.org/software/guix/guix-fosdem-20150131.pdf))
-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
-`/gnu/store`.
-
-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
-manually.
-
-
-## 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](http://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/bioinformatics.scm).
-A list of software (updated daily) available through Guix is
-[available here](https://www.gnu.org/software/guix/package-list.html).
-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](https://gnu.org/distros/free-system-distribution-guidelines.html),
-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
-`GUIX_PACKAGE_PATH`.
-
-If you want to learn more about GNU Guix I recommend taking a look at
-the excellent
-[GNU Guix project page](https://www.gnu.org/software/guix/). 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.
-
-The Guix community is very friendly, supportive, responsive and
-welcoming. I encourage you to visit the project's
-[IRC channel #guix on Freenode](https://webchat.freenode.net?channels=#guix),
-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
index 0000000..f7e2400
--- /dev/null
+++ b/posts/2015-04-17-gnu-guix.skr
@@ -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")))
+
+(list
+ (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
+ "https://www.gnu.org/software/guix/" "GNU Guix"), a functional
+ package manager written in ,(ref
+ "https://www.gnu.org/software/guile/" "Guile Scheme"), the
+ designated extension language for the ,(ref
+ "https://www.gnu.org/" "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
+ "https://www.gnu.org/software/guix/guix-fosdem-20150131.pdf"
+ "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
+ "http://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/bioinformatics.scm"
+ "bioinformatics tools and libraries"). A list of software
+ (updated daily) available through Guix is ,(ref
+ "https://www.gnu.org/software/guix/package-list.html" "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
+ "https://gnu.org/distros/free-system-distribution-guidelines.html"
+ "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 "https://www.gnu.org/software/guix/"
+ "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
+ "https://webchat.freenode.net?channels=#guix" "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
index 25dfb00..0000000
--- a/posts/2015-06-21-getting-started-with-guix.markdown
+++ /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](https://www.gnu.org/software/guix/manual/guix.html),
-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](ftp://alpha.gnu.org/gnu/guix/guix-binary-0.8.2.x86_64-linux.tar.xz).
-There also is a
-[tarball for 32 bit machines](ftp://alpha.gnu.org/gnu/guix/guix-binary-0.8.2.i686-linux.tar.xz)
-and
-[one for the less common MIPS](ftp://alpha.gnu.org/gnu/guix/guix-binary-0.8.2.mips64el-linux.tar.xz).
-
-*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 hydra.gnu.org, authorise it as a source for so-called binary
- substitutes using the included public key:
-
- # guix archive --authorize < /root/.guix-profile/share/guix/hydra.gnu.org.pub
-
-Note that hydra.gnu.org 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](https://www.gnu.org/software/guix/manual/guix.html)
-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](https://webchat.freenode.net/?channels=#guix).
-For matters relating to using Guix in a bioinformatics environment you
-are welcome to subscribe and write to the
-[mailing list bio-packaging@mailman.open-bio.org](http://lists.open-bio.org/mailman/listinfo/bio-packaging).
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
index 0000000..503978f
--- /dev/null
+++ b/posts/2015-06-21-getting-started-with-guix.skr
@@ -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")))
+
+(list
+ (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
+ "https://www.gnu.org/software/guix/manual/guix.html" "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
+ "ftp://alpha.gnu.org/gnu/guix/guix-binary-0.8.2.x86_64-linux.tar.xz"
+ "x86_64 archive from the FTP server"). There also is a ,(ref
+ "ftp://alpha.gnu.org/gnu/guix/guix-binary-0.8.2.i686-linux.tar.xz"
+ "tarball for 32 bit machines") and ,(ref
+ "ftp://alpha.gnu.org/gnu/guix/guix-binary-0.8.2.mips64el-linux.tar.xz"
+ "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 hydra.gnu.org, 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/hydra.gnu.org.pub]))
+
+ (p [Note that hydra.gnu.org 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 "https://www.gnu.org/software/guix/manual/guix.html"
+ "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
+ "https://webchat.freenode.net/?channels=#guix" "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
+ "http://lists.open-bio.org/mailman/listinfo/bio-packaging"
+ "mailing list bio-packaging@mailman.open-bio.org").]))