<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>codeblog</title>
	<atom:link href="http://tpreclik.dyndns.org/codeblog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://tpreclik.dyndns.org/codeblog</link>
	<description></description>
	<lastBuildDate>Sat, 08 Jan 2011 15:40:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Ranking and Unranking of Rubik&#8217;s cubes</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=66</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=66#comments</comments>
		<pubDate>Tue, 26 Feb 2008 21:06:50 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[computer-science]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/codeblog/?p=66</guid>
		<description><![CDATA[Have you ever seen someone solving the Rubik&#8217;s cube within a minute? I did and I was amazed! Afterwards I walked through Lissabon staring at the cube and desperately trying to figure out how to solve it. By now I finally learned how to proceed. You can find an intuitive approach on Lars Petrus&#8217; website. [...]]]></description>
			<content:encoded><![CDATA[<div style="float:left; margin-right:1em;">
		<script type="text/javascript">
			function startGallery_gallery_cfa06f_img() {
				$('gallery_cfa06f_img').style.height='120px';
				$('gallery_cfa06f_img').style.width='160px';
			}
			window.addEvent('domready', startGallery_gallery_cfa06f_img);
		</script><div id="gallery_cfa06f"><a href="#" title="dscn3897" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/rubikscube/dscn3897.jpg?m=1279480550" id="gallery_cfa06f_img"/></a></div></div>
<p>Have you ever seen someone solving the Rubik&#8217;s cube within a minute? I did and I was amazed! Afterwards I walked through Lissabon staring at the cube and desperately trying to figure out how to solve it. By now I finally learned how to proceed. You can find an intuitive approach on <a href="http://www.lar5.com/cube/index.html">Lars Petrus&#8217;</a> website. As with many complicated toys a lot of math is involved. In this case a lot of group theory and combinatorics. But actually I am no big fan of sober complicated math. Nevertheless I was eager to tinker with the cube and began by writing a program which had an explicit representation of the cubes&#8217; face colors and operations to arbitrarily rotate the sides. The explicit representation is good if you want to <em>modify</em> the cube. However often it is just necessary to <em>identify</em> a particular cube state. Imagine you want to enumerate all cube states starting from the solution then you can use for example a breadth-first search. As with general graphs you need to remember states which you already encountered. For that purpose you should use a more compact representation of the cube. Suppose there are <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> Rubik&#8217;s cube states in total, then the minimum number of bits to represent a state is clearly <img src='/codeblog/latexrender/pictures/4769e850c841965e74d78f0bde0d576f.png' title='$\lceil \log_2 n \rceil$' alt='$\lceil \log_2 n \rceil$' align=absmiddle>. You achieve that goal if you are able to assign a unique number <img src='/codeblog/latexrender/pictures/2fd2b35bd48763e34216c191853dd413.png' title='$x \in \{0, \dots, n - 1\}$' alt='$x \in \{0, \dots, n - 1\}$' align=absmiddle> to each different possible cube state. This number is also called rank and the conversion from the explicit representation to the rank is referred to as <em>ranking</em>. The reverse is of course <em>unranking</em>.</p>
<p><span id="more-66"></span></p>

		<script type="text/javascript">
			function startGallery_gallery_e5f5ad_img() {
				$('gallery_e5f5ad_img').style.height='337px';
				$('gallery_e5f5ad_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_e5f5ad_img);
		</script><div id="gallery_e5f5ad"><a href="#" title="dscn3892" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/rubikscube/dscn3892.jpg?m=1279480547" id="gallery_e5f5ad_img"/></a></div>
<p>The Rubik&#8217;s cube consists of 12 edge pieces, 8 corner pieces and a fixed cross with the center pieces at the end of the axes. Suppose you disassemble the cube and reassemble it, then you can choose an arbitrary permutation of the edges as well as the corners resulting in <img src='/codeblog/latexrender/pictures/bc7d81c9049d0cf1696979d62f52be05.png' title='$12! \cdot 8!$' alt='$12! \cdot 8!$' align=absmiddle> different relative positions of the pieces (which are often also called cubies). Additionally you can choose the orientation of the pieces. The edge pieces have two possible orientations each and the corner pieces three. Thus the total number of Rubik&#8217;s cube states is <img src='/codeblog/latexrender/pictures/1465c24d78ab73d49d7f8aeeb3a609a6.png' title='$12! \cdot 8! \cdot 3^8 \cdot 2^{12}$' alt='$12! \cdot 8! \cdot 3^8 \cdot 2^{12}$' align=absmiddle>. However only 1/12 of those states can be solved &#8211; we will get to that later. Assuming we can determine the orientations of the edges <img src='/codeblog/latexrender/pictures/38582a8b87725d050b60f039b6ce25cd.png' title='$\bar{o}_i \in \{0, 1\}$' alt='$\bar{o}_i \in \{0, 1\}$' align=absmiddle> (flipped or not), then encoding them in a single number is fairly easy. Each edge position <img src='/codeblog/latexrender/pictures/77a3b857d53fb44e33b53e4c8b68351a.png' title='$i$' alt='$i$' align=absmiddle> corresponds to a single bit. If the edge is flipped then we set the corresponding bit. For corner orientations <img src='/codeblog/latexrender/pictures/10a5a9afccb59c0228f5aa822b738acf.png' title='$\hat{o}_i \in \{0, 1, 2\}$' alt='$\hat{o}_i \in \{0, 1, 2\}$' align=absmiddle> we proceed actually the same way but this time we use a number representation with basis three: <img src='/codeblog/latexrender/pictures/a7c5226d9ea98573835ce1753e933be3.png' title='$\hat{o}_{7} \cdot 3^{7} + \dots + \hat{o}_1 \cdot 3 + \hat{o}_0$' alt='$\hat{o}_{7} \cdot 3^{7} + \dots + \hat{o}_1 \cdot 3 + \hat{o}_0$' align=absmiddle></p>
<p>We have encoded the edge and corner orientations but still need to encode their permutations. To do that each piece gets a unique id so edge ids range from 0 to 11 and corner ids from 0 to 7. To facilitate explanation we also introduce positions which have ids just like the pieces. The position with id <img src='/codeblog/latexrender/pictures/332cc365a4987aacce0ead01b8bdcc0b.png' title='$x$' alt='$x$' align=absmiddle> equals the position where the piece with id <img src='/codeblog/latexrender/pictures/332cc365a4987aacce0ead01b8bdcc0b.png' title='$x$' alt='$x$' align=absmiddle> is located when the cube is in the solved state. Now it is easy to determine the permutations of the edges and corners respectively. Just iterate over all positions and check the ids of the pieces there. The result will be a permutation for the edges (e.g. (0, 6, 4, 7, 1, 3, 2, 5)) as well as for the corners. Now we need to rank both permutations. If we can enumerate all possible permutations systematically then we can assign ranks by numbering the permutations serially. Often the permutations are enumerated lexicographically which leads to the following for size 3:</p>
<table cellspacing="10">
<tbody>
<tr>
<th align="left">Rank</th>
<th align="left">Permutations</th>
</tr>
<tr>
<td>0</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</td>
<td>(0, 1, 2)</p>
<p>(0, 2, 1)</p>
<p>(1, 0, 2)</p>
<p>(1, 2, 0)</p>
<p>(2, 0, 1)</p>
<p>(2, 1, 0)</td>
</tr>
</tbody>
</table>
<p>The lexiographic ranking could be described by the following recursion:</p>
<p><img src='/codeblog/latexrender/pictures/cfda2a4af3827affbc72630520e0649c.png' title='$rank\left( (p_0), 1 \right) = 0$' alt='$rank\left( (p_0), 1 \right) = 0$' align=absmiddle><br />
<img src='/codeblog/latexrender/pictures/b8a5de8a286c0de8ba62f4a8e32e5023.png' title='$rank((p_0, \dots, p_{n-1}), n) = p_0 \cdot (n-1)! + rank( (q_1, \dots, q_{n-1}), n - 1)$' alt='$rank((p_0, \dots, p_{n-1}), n) = p_0 \cdot (n-1)! + rank( (q_1, \dots, q_{n-1}), n - 1)$' align=absmiddle><br />
<img src='/codeblog/latexrender/pictures/e247cca1c9e3a6bafdb86ed86539ee92.png' title='\textnormal{where}\quad$q_i = \begin{cases}p_i - 1 &amp; \textnormal{if}~p_i &amp;gt; p_0\\ p_i &amp; \textnormal{else}\end{cases}$' alt='\textnormal{where}\quad$q_i = \begin{cases}p_i - 1 &amp; \textnormal{if}~p_i &amp;gt; p_0\\ p_i &amp; \textnormal{else}\end{cases}$' align=absmiddle></p>
<p>However a different ordering will come in handy later &#8211; we will need an ordering where every second permutation is even and every other odd. Even permutations can always be generated by an even number of transpositions. It can be proved that it is not possible to generate an even permutation with an odd number of transpositions and the other way round. The sign or signature of a permutation <img src='/codeblog/latexrender/pictures/2ec6e630f199f589a2402fdf3e0289d5.png' title='$p$' alt='$p$' align=absmiddle> is defined as:</p>
<p><img src='/codeblog/latexrender/pictures/b5920ee25ab82fe501c179f7fb850123.png' title='$sgn(p) = \begin{cases}+1 &amp; \textnormal{if}~p~\textnormal{even}\\-1 &amp; \textnormal{else}\end{cases}$' alt='$sgn(p) = \begin{cases}+1 &amp; \textnormal{if}~p~\textnormal{even}\\-1 &amp; \textnormal{else}\end{cases}$' align=absmiddle></p>
<p>Thus we need a ranking with an alternating sign. Let us try an induction approach. Assume we have such a ranking for permutations of size <img src='/codeblog/latexrender/pictures/efcf8d472ecdd2ea56d727b5746100e3.png' title='$n-1$' alt='$n-1$' align=absmiddle>, how can we extend it without losing the property of the alternating sign? In principle we need to take each of the permutations and insert the number <img src='/codeblog/latexrender/pictures/efcf8d472ecdd2ea56d727b5746100e3.png' title='$n-1$' alt='$n-1$' align=absmiddle> at every possible place of the permutation which equals to <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> possibilities. If we insert it last, the new permutation will have the same number of transpositions as the previous permutation because the number <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> is at it&#8217;s correct place. If we insert it one place to the left, then we need an additional transposition. For each place further left we need another transposition. For example if we start with the even permutation (2, 0, 1) and append 3 to extend it to size 4, (2, 0, 1, 3) is again even. However as we shift the 3 to the left, the sign of the permutation will alternate. So in summary we can extend each permutation of size <img src='/codeblog/latexrender/pictures/efcf8d472ecdd2ea56d727b5746100e3.png' title='$n-1$' alt='$n-1$' align=absmiddle> to <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> permutations of size <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> with alternating sign. If <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> is odd we have a proper ranking at hand. However if it is even, then every n-th sign will repeat once. To remedy this deficiency we need to reverse the <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> extended permutations of every second permutation we extend if <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> is even. Have a look at the following table which demonstrates the ranking with alternating sign:</p>
<table cellspacing="10">
<tbody>
<tr>
<th>Rank</th>
<th>Permutations</th>
<th>Rank</th>
<th>Permutations</th>
<th>Rank</th>
<th>Permutations</th>
</tr>
<tr>
<td valign="top">0</td>
<td valign="top">(0)</td>
<td valign="top">0</p>
<hr />
1</td>
<td valign="top">(0, 1)</p>
<hr />
(1, 0)</td>
<td valign="top">0</p>
<p>1</p>
<p>2</p>
<hr />
3</p>
<p>4</p>
<p>5</td>
<td valign="top">(0, 1, 2)</p>
<p>(0, 2, 1)</p>
<p>(2, 0, 1)</p>
<hr />
(1, 0, 2)</p>
<p>(1, 2, 0)</p>
<p>(2, 1, 0)</td>
</tr>
</tbody>
</table>
<table cellspacing="10">
<tbody>
<tr>
<th>Rank</th>
<th>Permutations</th>
<th>Rank</th>
<th>Permutations</th>
<th>Rank</th>
<th>Permutations</th>
</tr>
<tr>
<td valign="top">0</p>
<p>1</p>
<p>2</p>
<p>3</p>
<hr />
4</p>
<p>5</p>
<p>6</p>
<p>7</td>
<td valign="top">(0, 1, 2, 3)</p>
<p>(0, 1, 3, 2)</p>
<p>(0, 3, 1, 2)</p>
<p>(3, 0, 1, 2)</p>
<hr />
(3, 0, 2, 1)</p>
<p>(0, 3, 2, 1)</p>
<p>(0, 2, 3, 1)</p>
<p>(0, 2, 1, 3)</td>
<td valign="top">8</p>
<p>9</p>
<p>10</p>
<p>11</p>
<hr />
12</p>
<p>13</p>
<p>14</p>
<p>15</td>
<td valign="top">(2, 0, 1, 3)</p>
<p>(2, 0, 3, 1)</p>
<p>(2, 3, 0, 1)</p>
<p>(3, 2, 0, 1)</p>
<hr />
(3, 1, 0, 2)</p>
<p>(1, 3, 0, 2)</p>
<p>(1, 0, 3, 2)</p>
<p>(1, 0, 2, 3)</td>
<td valign="top">16</p>
<p>17</p>
<p>18</p>
<p>19</p>
<hr />
20</p>
<p>21</p>
<p>22</p>
<p>23</td>
<td valign="top">(1, 2, 0, 3)</p>
<p>(1, 2, 3, 0)</p>
<p>(1, 3, 2, 0)</p>
<p>(3, 1, 2, 0)</p>
<hr />
(3, 2, 1, 0)</p>
<p>(2, 3, 1, 0)</p>
<p>(2, 1, 3, 0)</p>
<p>(2, 1, 0, 3)</td>
</tr>
</tbody>
</table>
<p>This scheme results in the following recursion:</p>
<p><img src='/codeblog/latexrender/pictures/44c58aa00e05a5f58c07dda6d46f6272.png' title='\footnotesize rank\left( (p_0), 1 \right) = 0\\ rank\left( (p_0, \dots, p_{n-1}), n \right) =\\n \cdot rank\left( (p_0, \dots, p_{i-1}, p_{i+1}, \dots, p_{n-1}), n-1 \right) +\\ \begin{cases}i &amp; \textnormal{if}~rank\left( (p_0, \dots, p_{i-1}, p_{i+1}, \dots, p_{n-1}), n-1 \right)~\textnormal{odd}~\land~n~\textnormal{even}\\ n-1-i &amp; \textnormal{else}\end{cases}\\ \textnormal{where}~p_i = n-1' alt='\footnotesize rank\left( (p_0), 1 \right) = 0\\ rank\left( (p_0, \dots, p_{n-1}), n \right) =\\n \cdot rank\left( (p_0, \dots, p_{i-1}, p_{i+1}, \dots, p_{n-1}), n-1 \right) +\\ \begin{cases}i &amp; \textnormal{if}~rank\left( (p_0, \dots, p_{i-1}, p_{i+1}, \dots, p_{n-1}), n-1 \right)~\textnormal{odd}~\land~n~\textnormal{even}\\ n-1-i &amp; \textnormal{else}\end{cases}\\ \textnormal{where}~p_i = n-1' align=absmiddle></p>
<p>So what did we achieve already? We have an encoding of the edge orientations <img src='/codeblog/latexrender/pictures/32e374e9cce7c4f74df6c9b007ca8a0b.png' title='(\bar{o} \in \{0, \dots, 2^{12}-1\})' alt='(\bar{o} \in \{0, \dots, 2^{12}-1\})' align=absmiddle>, the corner orientations <img src='/codeblog/latexrender/pictures/f24fb78775ca439db48bab421f69d00e.png' title='(\hat{o} \in \{0, \dots, 3^{8}-1\})' alt='(\hat{o} \in \{0, \dots, 3^{8}-1\})' align=absmiddle>, the edge permutation <img src='/codeblog/latexrender/pictures/73a335ccaa4a3b7e86abc583391e582f.png' title='(\bar{p} \in \{0, \dots, 12!-1\})' alt='(\bar{p} \in \{0, \dots, 12!-1\})' align=absmiddle> and the corner permutation <img src='/codeblog/latexrender/pictures/ae3448f7d9681b18d31e4ac69ddf4186.png' title='(\hat{p} \in \{0, \dots, 8!-1\})' alt='(\hat{p} \in \{0, \dots, 8!-1\})' align=absmiddle>. If we just take the binary representations and concatenate them we reach an encoding length of <img src='/codeblog/latexrender/pictures/204110e551a20ac245c72ec75e99cdfa.png' title='$\lceil \log_2 2^{12} \rceil + \lceil \log_2 3^{8} \rceil + \lceil \log_2 12! \rceil + \lceil \log_2 8! \rceil$' alt='$\lceil \log_2 2^{12} \rceil + \lceil \log_2 3^{8} \rceil + \lceil \log_2 12! \rceil + \lceil \log_2 8! \rceil$' align=absmiddle> = 12 + 13 + 29 + 16 = 70bits which already fits in 9 bytes. However we can easily improve upon that by using a mixed base encoding: The tupel <img src='/codeblog/latexrender/pictures/a5eb8cacd1c88c4b26c1b991bcd6278e.png' title='$(\bar{o}, \hat{o}, \bar{p}, \hat{p})$' alt='$(\bar{o}, \hat{o}, \bar{p}, \hat{p})$' align=absmiddle> can be encoded as <img src='/codeblog/latexrender/pictures/885204b77e6f3e76391884fb9f35797a.png' title='$\bar{o} \cdot (3^8 \cdot 12! \cdot 8!) + \hat{o} \cdot (12! \cdot 8!) + \bar{p} \cdot 8! + \hat{p}$' alt='$\bar{o} \cdot (3^8 \cdot 12! \cdot 8!) + \hat{o} \cdot (12! \cdot 8!) + \bar{p} \cdot 8! + \hat{p}$' align=absmiddle> which results in a number ranging from 0 to <img src='/codeblog/latexrender/pictures/a4b9b8c7e2c69e51f04d40e2b77e7773.png' title='$2^{12} \cdot 3^8 \cdot 12! \cdot 8! - 1$' alt='$2^{12} \cdot 3^8 \cdot 12! \cdot 8! - 1$' align=absmiddle>.</p>
<p>If we want to be able to encode all possible Rubik&#8217;s cube states we are done. However if we only want to identify solvable states we can save some more bits. As already mentioned before only 1 in 12 states can be solved. This fact is well known and the following explanations thereof are merely the rephrased laws as they are presented on <a href="http://www.ryanheise.com/cube/cube_laws.html">Ryan Heise&#8217;s</a> website. The first restriction is due to the number of flipped edges. When starting from the solved stated no matter what you do there will always be an even number of flipped edges. For this to be true we have to chose a frame of reference which suits our needs. Let us define an edge to be not flipped if we can position it correctly by only rotating the front (F), left (L), back (B) and right (R) sides. Therefore all rotations of the F, L, B or R sides will never flip any edges. However when rotating the top (T) or down (D) side of the cube, four edges are flipped at once. Consequently we can safely omit a bit of the encoded edge orientations because we can always reconstruct it by counting the number of bits set. If the number of flipped edges is odd we know that the omitted edge was also flipped.</p>
<p>The corner orientations are also restricted. Each of the corner pieces can have three orientations. To be able to identify the orientation state let&#8217;s use the sticker colors: A corner has always either a red (x)or an orange sticker. If that sticker either points upwards or downwards the corner is defined to be correctly oriented and we assign the orientation 0. If we need to twist the corner once counterclockwise to be correctly oriented we assign orientation 1 and otherwise 2. With this frame of reference it is easy to see that the sum over the corner orientations remains equal if we only rotate the top and down side of the cube. If we rotate any other side, the orientations of all four affected corners change. Two corner orientations increase by two and the others by one (modulo 3). So the total sum of corner orientations stays always <img src='/codeblog/latexrender/pictures/bf3b854ce6420bce3a3da45a9b45e36c.png' title='0 \equiv 1+1+2+2 \mod 3' alt='0 \equiv 1+1+2+2 \mod 3' align=absmiddle>. Again we can omit information &#8211; this time we just divide the encoding of the corner orientation by 3 and round off. We can reconstruct it any time by multiplying by 3 and adding 0, 1 or 2 to make it divisible by 3.</p>
<p>The last and trickiest part is the restriction of the edge and corner permutations. As mentioned earlier you can decompose every permutation into a sequence of transpositions. The number of edge transpositions <em>plus</em> the number of corner transpositions is preserved by any move to be even. Thus if the edge permutation is even, the corner permutation is even and likewise if the edge permutation is odd, the corner permutation is also odd. Since the encoding of the edge and corner permutations were constructed to have an alternating sign (see above) the rank is even if and only if the permutation is even. That&#8217;s why we can skip the least significant bit of either of the permutations ranks. It can be reconstructed by copying the least significant bit of the other permutation rank.</p>
<p>So the overall number of bits required is <img src='/codeblog/latexrender/pictures/0b18bfd823743900492a1aeec55b299e.png' title='$\lceil \log_2 \frac{2^{12} \cdot 3^8 \cdot 12! \cdot 8!}{2 \cdot 3 \cdot 3}\rceil = 66$' alt='$\lceil \log_2 \frac{2^{12} \cdot 3^8 \cdot 12! \cdot 8!}{2 \cdot 3 \cdot 3}\rceil = 66$' align=absmiddle>. Unfortunately this still requires 9 bytes. However we still might be able to improve upon that by only ranking <em>asymmetric</em>, solvable Rubik&#8217;s cube states. For instance if you intend to compute the number of states reachable from the solved state which can be optimally solved in <img src='/codeblog/latexrender/pictures/77a3b857d53fb44e33b53e4c8b68351a.png' title='$i$' alt='$i$' align=absmiddle> moves, you can count instead only the asymmetric states because all symmetric ones can be solved with exactly the same number of moves. Since the numbers in this sequences get quickly very big you better safe every possible byte/bit you need to remember. Later you can reconstruct the true number of reachable states. The sequence I talk about can be also found in the <a href="http://www.research.att.com/~njas/sequences/">The On-Line Encyclopedia of Integer Sequences</a>: <a href="http://www.research.att.com/~njas/sequences/A080601">Number of positions that the 3 X 3 X 3 Rubik cube puzzle can be in after exactly n moves.</a> But that&#8217;s a whole different story. Have fun!</p>

		<script type="text/javascript">
			function startGallery_gallery_74b6b1() {
				var myGallery = new gallery($('gallery_74b6b1'), {
					timed: true,
					delay: 10000,
					showCarousel: true,
					textShowCarousel: 'Select',
					showInfopane: true
				});
				$('gallery_74b6b1').style.height='337px';
				$('gallery_74b6b1').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_74b6b1);
		</script><div id="gallery_74b6b1">
			<div class="imageElement">
				<h3>dscn3892</h3>
				<p>&nbsp;Disassembled Cube</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/rubikscube/dscn3892" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/rubikscube/dscn3892.jpg?m=1279480547" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/rubikscube/dscn3892.jpg?m=1279480547" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>dscn3894</h3>
				<p>&nbsp;Cube frame</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/rubikscube/dscn3894" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/rubikscube/dscn3894.jpg?m=1279480549" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/rubikscube/dscn3894.jpg?m=1279480549" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>dscn3897</h3>
				<p>&nbsp;Rubik's Cube</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/rubikscube/dscn3897" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/rubikscube/dscn3897.jpg?m=1279480550" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/rubikscube/dscn3897.jpg?m=1279480550" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>dscn3898</h3>
				<p>&nbsp;Rubik's Cube</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/rubikscube/dscn3898" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/rubikscube/dscn3898.jpg?m=1279480552" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/rubikscube/dscn3898.jpg?m=1279480551" class="thumbnail"/>
			</div>
			</div>
<ul class="papercite_bibliography">
<li>                   S. Skiena, <span style="font-style: italic">The algorithm design manual</span>, New York, NY, USA: Springer-Verlag New York, Inc., 1998. <br/>    <a href="javascript:void(0)" id="papercite_2" class="papercite_toggle">[Bibtex]</a>
<pre class="papercite_bibtex" id="papercite_2_block"><code>@book{skiena98,
  author = {Steven S. Skiena},
  title = {The algorithm design manual},
  year = {1998},
  isbn = {0-387-94860-0},
  publisher = {Springer-Verlag New York, Inc.},
  address = {New York, NY, USA},
  URL = {http://www2.toki.or.id/book/AlgDesignManual/}
}</code></pre>
</li>
</ul>
<ul class="papercite_bibliography">
<li>                   R. Heise, <span style="font-style: italic">Laws of the cube</span>. <br/>    <a href="javascript:void(0)" id="papercite_3" class="papercite_toggle">[Bibtex]</a>
<pre class="papercite_bibtex" id="papercite_3_block"><code>@misc{heise,
  author = {Ryan Heise},
  title = {Laws of the cube},
  URL = {http://www.ryanheise.com/cube/cube_laws.html}
}</code></pre>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=66</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Digital Television with Linux</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=28</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=28#comments</comments>
		<pubDate>Tue, 10 Apr 2007 14:15:07 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[information-technology]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=28</guid>
		<description><![CDATA[Analog TV is dead. Well almost. Digital television is state of the art. In 2005 the terrestrial digital video broadcasting (DVB-T) in the region Nuremberg in Germany started. Therefore I decided to buy a digital receiver some time ago. I chose an external receiver connected via USB 2.0 manufactured by AVerMedia which was branded as: [...]]]></description>
			<content:encoded><![CDATA[<p>
Analog TV is dead. Well almost. Digital television is state of the art. In 2005 the terrestrial digital video broadcasting (DVB-T) in the region Nuremberg in Germany started. Therefore I decided to buy a digital receiver some time ago. I chose an external receiver connected via USB 2.0 manufactured by AVerMedia which was branded as: &#8220;AVerTV DVB-T USB2.0&#8243;
</p>
<p>
To get some more information let us use the usbutils.
</p>
<p><code><br />
# lsusb -v<br />
...<br />
Bus 001 Device 003: ID 07ca:a801 AVerMedia Technologies, Inc.<br />
Device Descriptor:<br />
  bLength                18<br />
  bDescriptorType         1<br />
  bcdUSB               2.00<br />
  bDeviceClass            0 (Defined at Interface level)<br />
  bDeviceSubClass         0<br />
  bDeviceProtocol         0<br />
  bMaxPacketSize0        64<br />
  idVendor           0x07ca AVerMedia Technologies, Inc.<br />
  idProduct          0xa801<br />
  bcdDevice            0.00<br />
  iManufacturer           1 AVerTV<br />
  iProduct                2 A801<br />
  iSerial                 0<br />
  bNumConfigurations      1<br />
...<br />
</code></p>
<p>
Every digital as well as analog television receiver has a tuner module integerated. A little research revealed that the &#8220;AVerTV DVB-T USB2.0 (A801)&#8221; has a DiB3000M-C/P tuner (also called frontend). Since the device is a so called budget &#8211; in contrast to a full featured &#8211; dvb-t receiver, it has no MPEG decoder chip to decode the compressed video signal in hardware. Thus the receiver is cheaper but the decoding has to be done by the host cpu itself which is quite computationally expensive.
</p>
<p><span id="more-28"></span></p>
<h3>System Configuration</h3>
<p>
The AVerTV DVB-T receiver needs to load a firmware when it is plugged into the usb port. You need to download this firmware and place it into the appropriate directory. Download it from <a href="http://www.linuxtv.org/downloads/firmware/">linuxtv.org</a>. Grab the latest dvb-usb-avertv-a800-*.fw file and move it into your distributions firmware directory (in Gentoo for example <code>/lib/firmware</code>).
</p>
<p>
As usual you need the appropriate device drivers for the receiver. You will also want USB 2.0 support (EHCI HCD) and firmware loading. If you compiled a customized kernel you need to check the following options in your kernel configuration:
</p>
<pre>
→ Device Drivers
  → Multimedia devices
    → Digital Video Broadcasting Devices
      → DVB For Linux (CONFIG_DVB=y)
      → DVB Core Support (CONFIG_DVB_CORE=y/m)
      → Support for various USB DVB devices (CONFIG_DVB_USB=y/m)
      → AVerMedia AverTV DVB-T USB 2.0 (A800) (CONFIG_DVB_USB_A800=y/m)
      → DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (CONFIG_DVB_USB_DIBUSB_MC=y/m)
      → Customise DVB Frontends
        → DiBcom 3000 M-C (CONFIG_DVB_DIB3000MC=y/m)
</pre>
<p>
For further instructions refer to your distributions manuals for compiling your own kernel. Most distributions probably ship with kernels which have those kernel modules <em>readily compiled anyway</em>. Just try modprobing them:
</p>
<p><code># modprobe dvb-usb-a800</code></p>
<p>
All other necessary kernel modules will be loaded automatically. The kernel log should now report something like:
</p>
<p><code><br />
# dmesg | tail<br />
usb 1-3: new high speed USB device using ehci_hcd and address 6<br />
usb 1-3: configuration #1 chosen from 1 choice<br />
dvb-usb: found a 'AVerMedia AverTV DVB-T USB 2.0 (A800)' in warm state.<br />
dvb-usb: will pass the complete MPEG2 transport stream to the software demuxer.<br />
DVB: registering new adapter (AVerMedia AverTV DVB-T USB 2.0 (A800)).<br />
DVB: registering frontend 0 (DiBcom 3000MC/P)...<br />
input: IR-receiver inside an USB DVB receiver as /class/input/input5<br />
dvb-usb: schedule remote query interval to 150 msecs.<br />
dvb-usb: AVerMedia AverTV DVB-T USB 2.0 (A800) successfully initialized and connected.<br />
</code></p>
<h3>DVB Television Software</h3>
<p>
To watch television you now need the appropriate software. The DVB-T support in TV applications under Linux is spare. Mainly there is the giant beast <a href="http://www.mythtv.org/">MythTV</a> and the little beasts <a href="http://www.mplayerhq.hu/">MPlayer</a> and <a href="http://www.linuxtv.org/vdrwiki/">VDR</a>. For installing these either use the package system of your distribution or compile them by hand. In either case make sure the DVB-T support is activated. If you intend to use MythTV be sure you read the <a href="http://www.mythtv.org/docs/mythtv-HOWTO-3.html#ss3.2">requirements</a> first.
</p>
<h4>MythTV</h4>
<p>I had little success with setting up MythTV. This with partially due to some broken QT library dependencies. The most scary requirement is the MySQL database though which is certainly not what I expected for a TV application.</p>
<h4>MPlayer</h4>
<p>
I will describe MPlayer here since it is way easier to configure than MythTV for example and is one of the most powerful media players out there. Unfortunately DVB-T tuning is fairly slow and channel switching not very convenient since a new window is opened each time when switching channels. Furthermore audio and video tend to get out of sync. Nevertheless it is probably the easiest to setup.
</p>
<p>
After you have installed MPlayer you need to scan for TV channels. Therefore you can use the <a href="http://www.linuxtv.org/wiki/index.php/LinuxTV_dvb-apps">linuxtv-dvb-apps</a>. Install them and run <code>dvbscan</code> once without parameters. It will list many files, which contain information about the frequencies used in many DVB-T areas. Select the filename appropriate for you and run <code>dvbscan</code> with the file as a parameter. Redirect the standard output to a file. If <code>dvbscan</code> ran successfully you can move the output file to the MPlayer&#8217;s configuration directory. For example:
</p>
<p><code><br />
# dvbscan /usr/share/dvb/dvb-t/de-Nuernberg > new-channels.conf<br />
# mv new-channels.conf ~/.mplayer/channels.conf<br />
</code></p>
<p>
To get a list of available channel names try this:
</p>
<p><code><br />
# awk -F: '{ print $1 }' ~/.mplayer/channels.conf<br />
</code></p>
<p>
To watch a channel start MPlayer with <code>"dvb://channel name"</code> as a parameter. To switch channels you can use the keys <code>h</code> and <code>k</code>. If you have some more cpu time to spare you can add a deinterlace filter with <code>-vf pp=fd</code> to the command line:
</p>
<p><code><br />
# mplayer "dvb://channel name" -vf pp=fd<br />
</code></p>
<h4>VDR</h4>
<p>
The aim of the <a href="http://www.cadsoft.de/vdr/">VDR project</a> was originally to build your own digital satellite receiver and video disk recorder &#8211; hence the name. But the software is flexible enough to be used as a simple TV application on your desktop. In the background a daemon runs which operates the DVB device and can supply the video stream.
</p>
<p>
Since I bought a budget receiver the daemon must decode the MPEG2 stream from the device. Therefore the separate plugin <a href="http://www.vdr-wiki.de/wiki/index.php/Softdevice-plugin">Softdevice</a> exists. The Softdevice plugin takes the stream decodes it and usually directly passes the images to the <a href="http://en.wikipedia.org/wiki/Linux_framebuffer">framebuffer</a>. For our purpose &#8211; watching TV on our day-to-day desktop environment &#8211; the video image will be written to shared memory instead. A frontend application will get the images from the shared memory and display them inside a window. The Softdevice plugin provides exactly such a frontend which is called <code>ShmClient</code>. The configuration in Gentoo can be done in few steps:
</p>
<p><code><br />
$ # Install the backend<br />
$ emerge vdr<br />
...<br />
$ # Install the Softdevice plugin<br />
$ emerge vdr-softdevice<br />
...<br />
$ # Activate the Softdevice plugin<br />
$ emerge --config vdr-softdevice<br />
...<br />
$ # Configure the plugin to decode into shared memory<br />
$ echo SOFTDEVICE_VIDEO_OUT="shm" >> /etc/conf.d/vdr.softdevice<br />
</code></p>
<p class="notice">
<img src='http://tobias.preclik.de/blog/wp-content/uploads/2007/04/warning-32x32.png' alt='Warning Sign' class='notice' /> <strong>Note:</strong> The Softdevice plugin version 0.3.1 contains a bug which prevents users with 64-bit operating systems from using the keyboard. The bug is fixed in newer versions (currently only CVS).
</p>
<p>
As with MPlayer we must scan for channels now. Again we will use the <code>dvbscan</code> application but the output format is different now. For further instructions refer to the above section.
</p>
<p><code><br />
$ dvbscan -o vdr /usr/share/dvb/dvb-t/de-Nuernberg > new-channels.conf<br />
$ mv new-channels.conf /etc/vdr/channels.conf<br />
</code></p>
<p>
Now we are ready to test our setup:
</p>
<p><code><br />
$ # Start the background daemon<br />
$ /etc/init.d/vdr start<br />
$ # Start the TV client application<br />
$ ShmClient<br />
</code></p>
<p>
When starting for the first time you will be prompted to configure your key bindings. The results will be stored into <code>/etc/vdr/remote.conf</code>. In case something went wrong delete it and restart the daemon &#8211; you will be prompted for the key bindings again. If everything worked out you can add the daemon to the default runlevel in order that it will be started each time the computer boots. Furthermore the kernel module should be loaded automatically in the future. In Gentoo these steps require:
</p>
<p><code><br />
$ # Add VDR to the default runlevel<br />
$ rc-update add vdr default<br />
$ # Automatically load the device driver<br />
$ echo dvb-usb-a800 >> /etc/modules.autoload.d/kernel-2.6<br />
</code></p>
<p>
VDR has many more nifty plugins. Especially the <a href="http://www.vdr-wiki.de/wiki/index.php/Remote-plugin">remote plugin</a> comes in handy if you intend to control the TV application by an infrared remote-control. Look at the <code>dmesg</code> output above. It tells us that a new input device (&#8220;IR-receiver inside an USB DVB receiver&#8221; in this case) has been registered as /class/input/input5. All input devices (mice, keyboards, infrared receivers) get a device node usually called <code>/dev/input/eventX</code> (with an appended number X) and all those input devices can be used by the remote plugin. Unfortunately it is not always clear which name is assigned to the device thus a custom <a href="http://en.wikipedia.org/wiki/Udev">udev</a> rule is needed which assigns a static name like <code>/dev/input/dvb-ir</code>. Refer to the <a href="http://www.vdr-wiki.de/wiki/index.php/Remote-plugin">VDR Wiki</a> for further instructions. For me the following did the trick:
</p>
<p><code><br />
$ # Add custom udev rule which basically says: Add a symbolic link called "/dev/input/dvb-ir" as soon as you encounter a device<br />
which is normally called input with something appended and whose device name is "IR-receiver ..."<br />
$ echo 'KERNELS=="input*", ATTRS{name}=="IR-receiver inside an USB DVB receiver", SYMLINK+="input/dvb-ir"' >> /etc/udev/rules.d/10-local.rules<br />
</code></p>
<p>
To install and configure the remote plugin in Gentoo:
</p>
<p><code><br />
$ # Install the remote plugin<br />
$ emerge vdr-remote<br />
...<br />
$ # Activate the remote plugin<br />
$ emerge --config vdr-remote<br />
...<br />
$ # Instruct the plugin to use the infrared device (you can also leave this alone then the device will be hopefully autodetected and it takes some more time for the VDR daemon to start up)<br />
$ echo 'REMOTE_PLUGIN_INPUT_DEVICE="/dev/input/dvb-ir"' >> /etc/conf.d/vdr.remote<br />
$ # Restart the VDR daemon<br />
$ /etc/init.d/vdr restart<br />
</code></p>
<p>
As with the keyboard you will be prompted for the remote-controller key bindings when the daemon restarts. Again those will be appended to <code>/etc/vdr/remote.conf</code>. The entries will look like:
</p>
<p><code>remote-dvb-ir.Mute       0000000100010071</code></p>
<p>
The first part (<code>remote-</code>) refers to the VDR plugin, the second part (<code>dvb-ir.</code>) specifies the input device, the third part (<code>Mute</code>) the action name and the last part is the key code which is assigned to the action. If you want to repeat the setup of the remote control bindings, remove all entries which start with <code>remote-dvb-ir.</code>.
</p>
<p>
The VDR application is my TV application of choice. It is stable, feature-rich and good to handle. If I missed some steps above or you think something should be added please drop me a note.</p>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=28</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Programming the Game Boy</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=16</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=16#comments</comments>
		<pubDate>Tue, 06 Mar 2007 21:42:57 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[electronics]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=16</guid>
		<description><![CDATA[The original Game Boy has a modified 8-bit Z80 micro processing unit which is running at about 4.2 MHz. It features a serial port (link cable) for multiplayer games, a sound unit and a screen with an resolution of 160×144px. In 2001 a major successor was released: The Game Boy Advance. It relys upon an [...]]]></description>
			<content:encoded><![CDATA[<p>The original Game Boy has a modified 8-bit Z80 micro processing unit which is running at about 4.2 MHz. It features a serial port (link cable) for multiplayer games, a sound unit and a screen with an resolution of 160×144px. In 2001 a major successor was released: The Game Boy Advance. It relys upon an 32-bit ARM processor running at 16.8MHz. For backwards compatibility a Z80 is integrated clocked at 8.4MHz.</p>
<p>A long time ago (back in school) I read about a Game Boy programming device. I was quite amazed and immediately knew &#8220;I want such a device!&#8221;. Later on in the first term of my computer-science studies I met <a href="http://www.johannes-bauer.com/">Johannes Bauer</a> who has very good electronics knowledge. I told him about that device and the project was born. We ordered the parts immediately. Though the assembling of the programmer began two years later&#8230; Well now we finished it and the Game Boy is quite out of date &#8211; but who cares? At least they are cheaper now&#8230;</p>
<p><span id="more-16"></span>The page where I read about the programmer is still available. It is Lukas Zimmermann&#8217;s <a href="http://azug.minpet.unibas.ch/~lukas/GBprojects/CartIO.html">homepage</a>. There you can find the circuit diagram, the pcb layout and a complete list of necessary parts. There is only one uncommon part which is hard to find: The Game Boy cartridge connector. Therefore we bought a more or less working Game Boy at a junk market for about 2€.</p>

		<script type="text/javascript">
			function startGallery_gallery_a7135e_img() {
				$('gallery_a7135e_img').style.height='337px';
				$('gallery_a7135e_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_a7135e_img);
		</script><div id="gallery_a7135e"><a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/gb-circuit-board" title="gb-circuit-board" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/gb-circuit-board.jpg?m=1279480537" id="gallery_a7135e_img"/></a></div>
<p>We disassembled it and heated the  circuit board on which the connector was attached using a heat gun. The board was trash afterwards but the connector was quite safe.</p>

		<script type="text/javascript">
			function startGallery_gallery_b40da5_img() {
				$('gallery_b40da5_img').style.height='337px';
				$('gallery_b40da5_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_b40da5_img);
		</script><div id="gallery_b40da5"><a href="#" title="gb-circuit-board-later" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/gb-circuit-board-later.jpg?m=1279480538" id="gallery_b40da5_img"/></a></div>
<p>Next we had to etch the circuit board. We printed the pcb layout using a laser printer onto a sheet of magazine paper. Afterwards we taped the paper to a copper laminated board. Now the laser printer toner must be transfered from the sheet of paper to the board. Therefore we used a custom pouch laminator which Johannes modified himself earlier &#8211; hail to the king, baby! If you do not have such a device ready at hand <img src='http://tpreclik.dyndns.org/codeblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  just search for &#8220;homemade pcbs&#8221; to find some introducing informations. Anyway, the circuit paths should now be protected by the laser printed toner and the board is ready to be etched. Besides we also tried to use exposure and photoresist boards but we had no luck with that. The toner transfer method turned out to be way more accurate.</p>

		<script type="text/javascript">
			function startGallery_gallery_195668_img() {
				$('gallery_195668_img').style.height='337px';
				$('gallery_195668_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_195668_img);
		</script><div id="gallery_195668"><a href="#" title="etching" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/etching.jpg?m=1279480535" id="gallery_195668_img"/></a></div>
<p>When the board is ready you may want to have a close look at the circuit paths again. Check each and every pair of circuit path endpoints for connectivity. To do that a continuity tester with an integrated beeper comes in <em>very</em> handy. If you double-checked the paths you can start to populate the board. <em>First</em> solder the bridges and afterwards the parts since some of the bridges are situated below the ICs. Besides &#8211; before you make the same mistake as we did &#8211; Lukas provides a layout including the connector and one excluding the connector, so be aware of that. Instead of etching another board we chose to solder a ribbon cable directly to the connector.</p>

		<script type="text/javascript">
			function startGallery_gallery_3199b1_img() {
				$('gallery_3199b1_img').style.height='337px';
				$('gallery_3199b1_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_3199b1_img);
		</script><div id="gallery_3199b1"><a href="#" title="circuit-board-ready" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/circuit-board-ready.jpg?m=1279480535" id="gallery_3199b1_img"/></a></div>
<p>I concealed one nasty detail so far. To program the Game Boy it is not sufficient to own a game. The game volumes (so called cartridges) have a ROM soldered which means if you want to replace the software you have to replace the read-only memory by a flash memory. Reiner Ziegler describes on his <a href="http://www.reinerziegler.de/readplus.htm">homepage</a> which game catridges can be modified and by which flash memories the ROM must be replaced. If you need a list of which game has which hardware features look <a href="http://www.devrs.com/gb/files/gbmbcsiz.txt">here</a>. We first tried to replace the ROM of an MBC1 cartridge by an AT29C040A flash which turned out to be a complete flop since it had a different sector size as the one Reiner Ziegler suggested. But the second attempt with an AM29F040B-90 flash in a PLCC package was a success.</p>

		<script type="text/javascript">
			function startGallery_gallery_2e2fc8_img() {
				$('gallery_2e2fc8_img').style.height='337px';
				$('gallery_2e2fc8_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_2e2fc8_img);
		</script><div id="gallery_2e2fc8"><a href="#" title="cartridge-rom-removed" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/cartridge-rom-removed.jpg?m=1279480534" id="gallery_2e2fc8_img"/></a></div>
<p>However the first hurdle is to open the cartridge case &#8211; it has an uncommon screw. I cannot remember what we used for this purpose. Then the ROM chip needs to be removed carefully. Therefore we distributed some solder across the pins and heated it until one side of the ROM could be lifted. After this has been repeated for the second side the remaining solder can be removed using for example a desoldering wick. After that bend the pins of the flash chip to the outside and solder it slightly rotated, as Reiner Ziegler describes it. The rest is a sisyphean challenge.</p>
<p>If you come that far it is time to download the software <a href="http://www.reinerziegler.de/readplus.htm">readplus</a> which communicates with the programming device. It is available for Windows and for Linux. Please be aware that it does not check the command line arguments thoroughly &#8211; it took me hours to figure out that it expects &#8220;1&#8243; instead of &#8220;/dev/parport0&#8243; as the parallel port interface option. Never mind. Readplus must be run with administrator privileges/as root since it needs direct access to the parallel port. That&#8217;s why you also need the ppdev kernel module loaded on linux. For the first attempt you will want to run the &#8220;cartridge reader test&#8221;:</p>
<p><code><br />
# ./readplus -t<br />
</code></p>
<p>Like that you can check each of the connector pins of your programming device if the correct levels are applied. Be aware that if you measure at the back of the connector the pins at the front can still have no contact &#8211; which happened in our case&#8230;  If all goes well you can try to program the cartridge or alternatively if you have not yet modified a cartridge read one of your Game Boy games.  The readplus software has a bug in the checksum calculation so don&#8217;t get worried. Instead you can double-check the md5sum with a ROM image which you downloaded (or fix the checksum calculation <img src='http://tpreclik.dyndns.org/codeblog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</p>

		<script type="text/javascript">
			function startGallery_gallery_0ed7b9_img() {
				$('gallery_0ed7b9_img').style.height='337px';
				$('gallery_0ed7b9_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_0ed7b9_img);
		</script><div id="gallery_0ed7b9"><a href="#" title="gbprog1" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/gbprog1.jpg?m=1279480538" id="gallery_0ed7b9_img"/></a></div> 
		<script type="text/javascript">
			function startGallery_gallery_d516d6_img() {
				$('gallery_d516d6_img').style.height='337px';
				$('gallery_d516d6_img').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_d516d6_img);
		</script><div id="gallery_d516d6"><a href="#" title="cartridge-mod2" target="_blank"><img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/cartridge-mod2.jpg?m=1279480545" id="gallery_d516d6_img"/></a></div>
<p>The Game Boy can be programmed either in Assembler or in C. If you want to code in C you can use the <a href="http://gbdk.sourceforge.net/">Game Boy Development Kit</a> (GBDK). It comes with a libc and other helpful library functions. A simple hello world sample code can be done in few lines. For example:</p>
<p><code><br />
#include &lt;gb/gb.h&gt;<br />
#include &lt;stdio.h&gt;</code></p>
<p>int main() {<br />
puts(&#8220;Hello world&#8230;&#8221;);<br />
puts(&#8220;Press any key to continue&#8230;&#8221;);<br />
waitpad(0xFF);<br />
waitpadup();</p>
<p>puts(&#8220;See you later!&#8221;);</p>
<p>return 0;<br />
}</p>
<p>The code can be compiled and programmed to the cartridge for example using&#8230;</p>
<p><code><br />
# lcc -o helloworld.gb helloworld.c<br />
# readplus -p helloworld.gb<br />
</code></p>
<p>Good luck!</p>

		<script type="text/javascript">
			function startGallery_gallery_f1cd24() {
				var myGallery = new gallery($('gallery_f1cd24'), {
					timed: true,
					delay: 10000,
					showCarousel: true,
					textShowCarousel: 'Select',
					showInfopane: true
				});
				$('gallery_f1cd24').style.height='337px';
				$('gallery_f1cd24').style.width='450px';
			}
			window.addEvent('domready', startGallery_gallery_f1cd24);
		</script><div id="gallery_f1cd24">
			<div class="imageElement">
				<h3>cartridge-rom-removed</h3>
				<p>&nbsp;Cartridge with ROM removed</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/cartridge-rom-removed" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/cartridge-rom-removed.jpg?m=1279480534" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/cartridge-rom-removed.jpg?m=1279480534" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>circuit-board-ready</h3>
				<p>&nbsp;Connector is soldered to cable</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/circuit-board-ready" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/circuit-board-ready.jpg?m=1279480535" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/circuit-board-ready.jpg?m=1279480535" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>etching</h3>
				<p>&nbsp;Circuit board etching</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/etching" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/etching.jpg?m=1279480535" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/etching.jpg?m=1279480535" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>gb-circuit-board</h3>
				<p>&nbsp;Gameboy circuit board after removal of connector</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/gb-circuit-board" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/gb-circuit-board.jpg?m=1279480537" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/gb-circuit-board.jpg?m=1279480536" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>gb-circuit-board-later</h3>
				<p>&nbsp;Gameboy circuit board before removal of connector</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/gb-circuit-board-later" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/gb-circuit-board-later.jpg?m=1279480538" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/gb-circuit-board-later.jpg?m=1279480538" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>gbprog1</h3>
				<p>&nbsp;The final programmer and the Gameboy running a selfwritten demo.</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/gbprog1" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/gbprog1.jpg?m=1279480538" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/gbprog1.jpg?m=1279480538" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040729</h3>
				<p>&nbsp;Gameboy circuit board from the back</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040729" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040729.jpg?m=1279480539" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040729.jpg?m=1279480538" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040732</h3>
				<p>&nbsp;The unmounted connector</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040732" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040732.jpg?m=1279480539" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040732.jpg?m=1279480539" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040739</h3>
				<p>&nbsp;Mounting the flash (first attempt)</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040739" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040739.jpg?m=1279480540" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040739.jpg?m=1279480540" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040740</h3>
				<p>&nbsp;Mounting the flash (first attempt)</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040740" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040740.jpg?m=1279480541" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040740.jpg?m=1279480541" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040743</h3>
				<p>&nbsp;Mounting the flash (first attempt)</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040743" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040743.jpg?m=1279480542" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040743.jpg?m=1279480541" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040744</h3>
				<p>&nbsp;Mounting the flash (first attempt)</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040744" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040744.jpg?m=1279480543" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040744.jpg?m=1279480542" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040746</h3>
				<p>&nbsp;Preparing for etching</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040746" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040746.jpg?m=1279480543" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040746.jpg?m=1279480543" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb040748</h3>
				<p>&nbsp;First cartridge attempt</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb040748" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb040748.jpg?m=1279480544" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb040748.jpg?m=1279480543" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>pb050755</h3>
				<p>&nbsp;Assembled programmer circuit board</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/pb050755" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/pb050755.jpg?m=1279480545" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/pb050755.jpg?m=1279480544" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>cartridge-mod2</h3>
				<p>&nbsp;Second cartridge attempt</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/cartridge-mod2" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/cartridge-mod2.jpg?m=1279480545" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/cartridge-mod2.jpg?m=1279480545" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>IMG_6831</h3>
				<p>&nbsp;Programmer case open</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/IMG_6831" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/IMG_6831.JPG?m=1279480545" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/IMG_6831.JPG?m=1279480545" class="thumbnail"/>
			</div>
			
			<div class="imageElement">
				<h3>IMG_6837</h3>
				<p>&nbsp;Programmer case closed</p>
				<a href="http://tpreclik.dyndns.org/gallery3/index.php/gbprog/IMG_6837" title="open image" class="open">&nbsp;</a>
				<img src="http://tpreclik.dyndns.org/gallery3/var/resizes/gbprog/IMG_6837.JPG?m=1279480546" class="full" />
				<img src="http://tpreclik.dyndns.org/gallery3/var/thumbs/gbprog/IMG_6837.JPG?m=1279480546" class="thumbnail"/>
			</div>
			</div>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=16</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Unwrap sphere textures</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=9</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=9#comments</comments>
		<pubDate>Sun, 11 Feb 2007 15:49:38 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[computer-science]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=9</guid>
		<description><![CDATA[When rendering 3d graphics today there exists an underlying geometric model which is visually spiced up by wrapping texture bitmaps round the basic surface. So each time a pixel of the object is drawn on the screen the geometric three dimensional coordinates are known. To derive the pixel&#8217;s color the coordinates must be mapped to [...]]]></description>
			<content:encoded><![CDATA[<p>When rendering 3d graphics today there exists an underlying geometric model which is visually spiced up by wrapping texture bitmaps round the basic surface. So each time a pixel of the object is drawn on the screen the geometric three dimensional coordinates are known. To derive the pixel&#8217;s color the coordinates must be mapped to a point in the texture image. Therefore texture coordinates are stored at each vertex of the geometric model. When drawing pixels which are not vertices the texture coordinates are interpolated using the neighbouring vertices. But where do those texture coordinates come from? There are basically two possibilities. Either the coordinates are specified manually (for example with the help of the modelling software) or the coordinates are generated automagically.</p>
<p><span id="more-9"></span></p>
<p><a class="imagelink" href="/codeblog/wp-content/uploads/2007/02/texture-on-sphere.png" title="texture-on-sphere.png"><img id="image10" align="left" src="/codeblog/wp-content/uploads/2007/02/texture-on-sphere.thumbnail.png" alt="texture-on-sphere.png" /></a>Let&#8217;s have a deeper look at how an automatic mapping might work with a sphere. To specify the coordinates in the texture image, <img src='/codeblog/latexrender/pictures/3ed758a824c63bee2a6299d2f0291a34.png' title='$u \in [0; 1]$' alt='$u \in [0; 1]$' align=absmiddle> is used for the horizontal direction and <img src='/codeblog/latexrender/pictures/b9357107db8e4557674e32992c340f1b.png' title='$v \in [0; 1]$' alt='$v \in [0; 1]$' align=absmiddle> for the vertical direction. For the sphere two coordinates <img src='/codeblog/latexrender/pictures/27e556cf3caa0673ac49a8f0de3c73ca.png' title='$\theta$' alt='$\theta$' align=absmiddle> and <img src='/codeblog/latexrender/pictures/f50853d41be7d55874e952eb0d80c53e.png' title='$\phi$' alt='$\phi$' align=absmiddle> are also enough to mark a point on the surface (remember geographical latitude and longitude). The following equations relate spherical coordinates and cartesian coordinates:</p>
<p><img src='/codeblog/latexrender/pictures/74e60d82c04fc35706cf753fcc58bef6.png' title='$\left( \begin{array}{c} x \\ y \\ z \end{array} \right) = r \left( \begin{array}{c} \sin \theta \cos \phi \\ \sin \theta \sin \phi \\ \cos \theta \end{array} \right) \qquad \theta \in [0; \pi], \phi \in [0; 2 \pi] $' alt='$\left( \begin{array}{c} x \\ y \\ z \end{array} \right) = r \left( \begin{array}{c} \sin \theta \cos \phi \\ \sin \theta \sin \phi \\ \cos \theta \end{array} \right) \qquad \theta \in [0; \pi], \phi \in [0; 2 \pi] $' align=absmiddle></p>
<p>So a possible mapping for the <img src='/codeblog/latexrender/pictures/1d0b93e02eb15eddd39b4687112dc1c1.png' title='$(\theta, \phi)$' alt='$(\theta, \phi)$' align=absmiddle> to the <img src='/codeblog/latexrender/pictures/85dc9e5e6e7c8dd93f9d61b0acafd876.png' title='$(u, v)$' alt='$(u, v)$' align=absmiddle> coordinates is easy to define &#8211; just normalize the range:</p>
<p><img src='/codeblog/latexrender/pictures/75787d29cfc2e479fe454f83981ff9bc.png' title='$u = \frac{\phi}{2 \pi} \qquad v = \frac{\theta}{\pi}$' alt='$u = \frac{\phi}{2 \pi} \qquad v = \frac{\theta}{\pi}$' align=absmiddle></p>
<p>Back to our above scenario. To draw a pixel of the sphere object the color needs to be determined. So the cartesian coordinates <img src='/codeblog/latexrender/pictures/4fae0f09ce5106b5af1515d439e30216.png' title='$(x, y, z)$' alt='$(x, y, z)$' align=absmiddle> are converted to sphere coordinates <img src='/codeblog/latexrender/pictures/1d0b93e02eb15eddd39b4687112dc1c1.png' title='$(\theta, \phi)$' alt='$(\theta, \phi)$' align=absmiddle>. Those can be used to convert to the texture coordinates <img src='/codeblog/latexrender/pictures/85dc9e5e6e7c8dd93f9d61b0acafd876.png' title='$(u, v)$' alt='$(u, v)$' align=absmiddle>. By looking up the color in the texture image at position <img src='/codeblog/latexrender/pictures/85dc9e5e6e7c8dd93f9d61b0acafd876.png' title='$(u, v)$' alt='$(u, v)$' align=absmiddle> we know the pixel&#8217;s color and draw it to the screen buffer.</p>
<p>Now let&#8217;s reverse this process. We start with a readily rendered scene or an ordinary photo. For example some ball or orange is depicted. How can we generate the texture image? For each pixel in the texture we start with the <img src='/codeblog/latexrender/pictures/85dc9e5e6e7c8dd93f9d61b0acafd876.png' title='$(u, v)$' alt='$(u, v)$' align=absmiddle> coordinates, convert them to sphere coordinates and finally calculate the cartesian coordinates.</p>
<p><img src='/codeblog/latexrender/pictures/71e232a6c870579351446fcc1b7c8808.png' title='$\left( \begin{array}{c} x \\ y \\ z \end{array} \right) = \left( \begin{array}{c} c_x \\ c_y \\ c_z \end{array} \right) + r \left( \begin{array}{c} \sin \left( v \pi \right) \cos \left( u \pi \right) \\ \sin \left( v \pi \right) \sin \left( u \pi \right) \\ \cos \left( v \pi \right) \end{array} \right)$' alt='$\left( \begin{array}{c} x \\ y \\ z \end{array} \right) = \left( \begin{array}{c} c_x \\ c_y \\ c_z \end{array} \right) + r \left( \begin{array}{c} \sin \left( v \pi \right) \cos \left( u \pi \right) \\ \sin \left( v \pi \right) \sin \left( u \pi \right) \\ \cos \left( v \pi \right) \end{array} \right)$' align=absmiddle></p>
<p>Since the back of the sphere is missing the above equations use <img src='/codeblog/latexrender/pictures/35e360ed390791b1d7d60df6764cd09a.png' title='$\theta = u \pi$' alt='$\theta = u \pi$' align=absmiddle> instead of <img src='/codeblog/latexrender/pictures/002aa122f96dac5bccd4e84654d8999d.png' title='$\theta = u 2 \pi $' alt='$\theta = u 2 \pi $' align=absmiddle>.<br />
Up until now we skipped an important step. The three dimensional coordinates have to be somehow mapped to the screen which requires a projection from three dimensions to two. There exist different types of projections. For simplicity let&#8217;s stick with the easiest one: Orthographic projection. To project the sphere to the screen the depth coordinate is thrown away. In our case the second component. Otherwise not all pixels of the projected image are used to generate the texture.</p>
<p>In my subversion repository you can find an implementation which is capable of reading several image formats and writing a png file (<a href="https://www.faui2k3.org/svn/tobias/untexture/">link</a>). The command line application requires the SDL, SDL_image and libpng libraries (the latter two dependencies can be removed quite easily). A possible execution might look like:</p>
<pre># make
...
# ./untexture
usage: untexture &lt;bitmap&gt; &lt;centerx&gt; &lt;centery&gt; &lt;radius&gt;
# ./untexture res/orange.jpg 1234 1337 311
</pre>
<p>Some appetizers:</p>
<table>
<tr>
<td><a class="imagelink" title="An orange" href="/codeblog/wp-content/uploads/2007/02/orange.jpg"><img id="image14" alt="An orange" src="/codeblog/wp-content/uploads/2007/02/orange.thumbnail.jpg" /></a></td>
<td><a class="imagelink" title="A generated orange texture" href="/codeblog/wp-content/uploads/2007/02/orange-texture.jpg"><img id="image15" alt="A generated orange texture" src="/codeblog/wp-content/uploads/2007/02/orange-texture.thumbnail.jpg" /></a></td>
</tr>
<tr>
<td><a class="imagelink" title="tennisball.jpg" href="/codeblog/wp-content/uploads/2007/02/tennisball.jpg"><img id="image11" alt="tennisball.jpg" src="/codeblog/wp-content/uploads/2007/02/tennisball.thumbnail.jpg" /></a></td>
<td><a class="imagelink" title="tennisball-texture.jpg" href="/codeblog/wp-content/uploads/2007/02/tennisball-texture.jpg"><img id="image12" alt="tennisball-texture.jpg" src="/codeblog/wp-content/uploads/2007/02/tennisball-texture.thumbnail.jpg" /></a></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=9</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Wake-on-Lan</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=7</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=7#comments</comments>
		<pubDate>Fri, 09 Feb 2007 15:32:50 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[information-technology]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=7</guid>
		<description><![CDATA[I like accessing my machine at home from university. I tend to forget to commit my source code changes or upload other import files. Thus it comes in handy if I have secure shell access. But what if I forgot to switch on the computer? Cycling home 30 minutes, press the power button, cycling to [...]]]></description>
			<content:encoded><![CDATA[<p>I like accessing my machine at home from university. I tend to forget to commit my source code changes or upload other import files. Thus it comes in handy if I have secure shell access. But what if I forgot to switch on the computer? Cycling home 30 minutes, press the power button, cycling to university again. Since I am usually late every morning I forget to press the power button quite often. Since 1h is just too much time wasted there must be a better solution.</p>
<p><span id="more-7"></span></p>
<p>There exist several ways to remotely switch on your computer: Wake-on-Ring/Modem, Wake-on-Lan, Wake-on-Pci, &#8230;</p>
<p>Since I can reach my home network from university Wake-on-Lan fits my needs. I have a Asus A8N-E mainboard which supports as most modern mainboards do WOL. Be sure to activate it in the BIOS settings. For my mainboard I had to activate Wake-on-Pci (there exists no seperate WOL option though it has an onboard ethernet controller).</p>
<p>Different network controllers support different wake-up modes. To find out the supported modes of your network controller and to activate WOL you may want to install <a href="http://sourceforge.net/projects/gkernel/">ethtool</a>.</p>
<pre># ethtool eth0
Settings for eth0:
Supported ports: [ MII ]
Supported link modes:   10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supports auto-negotiation: Yes
Advertised link modes:  10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised auto-negotiation: Yes
Speed: 100Mb/s
Duplex: Full
Port: MII
PHYAD: 1
Transceiver: external
Auto-negotiation: on
Supports Wake-on: g
Wake-on: d
Link detected: yes</pre>
<p>Have a look at the line &#8220;Supports Wake-on:&#8221; line. It contains all supported modes abbreviated by a letter. Have a look at the ethtool manpage for further explanations. In principal the network card can trigger wake-signals on different events: Physical activity (p), broadcast messages (b), arp packets (a), &#8230; or so called MagicPackets (g). Which modes are supported depends on the hardware and the driver. For example the 3Com Vortex device driver requires that you explicitly activate Wake-on-Lan support when loading the kernel module.<br />
MagicPackets are network packets which use most often UDP as a transport protocol and contain as a payload <tt>FF FF FF FF FF FF</tt> followed by 16 times the MAC address of the network controller to wakeup. Of course everybody (in the local area network) can craft such a special packet and send it to your computer. That&#8217;s why there exist MagicPackets which have a password appended which is checked by your network controller. Forget about it &#8211; anyone who is able to send those packets to you is able to eavesdrop the MagicPacket&#8217;s password!</p>
<p>To activate Wake-on-Lan you must configure your network controller each time before you shutdown your computer. To do that by hand you can use ethtool:</p>
<pre># ethtool -s eth0 wol g</pre>
<p>Before you shutdown your computer write down your network controllers MAC address:</p>
<pre># ifconfig eth0 | grep HWaddr
eth0      Link encap:Ethernet  HWaddr 00:C0:1D:C0:FF:EE</pre>
<p>Now you can shut it down. To wakeup the computer you need to send the MagicPacket. Therefore several different utilities exist. I am using etherwake.</p>
<pre># ether-wake 00:C0:1D:C0:FF:EE</pre>
<p>If that does not wake the machine, maybe the network interfaces were shut down while powering off your computer. To prevent this, have a look at your distributions documentation or search the internet. For <a href="http://www.gentoo.org/">Gentoo</a> I had to set the option <tt>RC_DOWN_INTERFACE</tt> to <tt>no</tt> in <tt>/etc/conf.d/rc</tt>. It controls if the parameter <tt>i</tt> will be passed to the <tt>/sbin/halt</tt> command.<br />
If it worked you will probably want to activate WOL on every shutdown process. For Gentoo this can be achieved by adding the above ethtool command to <tt>/etc/conf.d/local.stop</tt>. Each time the computer starts the wake mode of the network controller will be reset to disabled. If you are dualbooting with Windows you will also have to activate the WOL features in Windows. Open the device manager and go to the preferences of your network controller where you can activate WOL. The checkbox with the cryptical description is what you want to check if you want to use MagicPackets.<br />
So what can we do now? If your router allows secure shell access, login there from remote and send a MagicPacket to your computer. Alternatively you can use WOL for example if you have a server in your LAN and want to shut it down or put it into standby when it is idle. Then everytime someone tries to access the machine it will automatically wakeup. In this case you will probably not use MagicPackets but wake on ARP packets.</p>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=7</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Heaps of size n</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=4</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=4#comments</comments>
		<pubDate>Fri, 09 Feb 2007 13:53:49 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[computer-science]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=4</guid>
		<description><![CDATA[The ordering of the elements in a heap of size is not unique. That is no magic observation. Have a look at the heap images. Both contain the same elements, both fulfill the heap property and are different. So how many different orderings are there? To answer this question we need some observations. The easiest [...]]]></description>
			<content:encoded><![CDATA[<p><a class="imagelink" href="/codeblog/wp-content/uploads/2007/01/heap_a.png" title="heap_a.png"><img id="image5" align="left" src="/codeblog/wp-content/uploads/2007/01/heap_a.thumbnail.png" alt="heap_a.png" /></a><a class="imagelink" href="/codeblog/wp-content/uploads/2007/01/heap_b.png" title="heap_b.png"><img id="image6" align="right" src="/codeblog/wp-content/uploads/2007/01/heap_b.thumbnail.png" alt="heap_b.png" /></a>The ordering of the elements in a heap of size <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> is not unique. That is no magic observation. Have a look at the heap images. Both contain the same elements, both fulfill the heap property and are different. So how many different orderings are there? To answer this question we need some observations. The easiest one: The root at the very top of the heap contains the biggest element. Both children in the binary tree are again heaps &#8211; but with how many elements?
</p>
<p><span id="more-4"></span></p>
<p>
Let&#8217;s have a deeper look at a typical binary tree (in context of a heap): Heaps usually require that the binary tree is balanced and nearly complete. Which means that on level <img src='/codeblog/latexrender/pictures/77a3b857d53fb44e33b53e4c8b68351a.png' title='$i$' alt='$i$' align=absmiddle> (all nodes that are i edges away from root) there exist <img src='/codeblog/latexrender/pictures/3a4a83447347e8eae50b856ef8a03468.png' title='$2^i$' alt='$2^i$' align=absmiddle> nodes. There is one exception. The last level may contain less or equal than <img src='/codeblog/latexrender/pictures/3a4a83447347e8eae50b856ef8a03468.png' title='$2^i$' alt='$2^i$' align=absmiddle> elements but those must be filled from the left to the right. So how many elements has a complete binary heap where the last level has also <img src='/codeblog/latexrender/pictures/3a4a83447347e8eae50b856ef8a03468.png' title='$2^i$' alt='$2^i$' align=absmiddle> elements? Assuming that the tree is of height h we can sum up the number of nodes per level: <img src='/codeblog/latexrender/pictures/68fb35976709485759ff2834e10c9699.png' title='$\sum_{i=0}^{h}2^i = 2^{h+1}-1$' alt='$\sum_{i=0}^{h}2^i = 2^{h+1}-1$' align=absmiddle>.
</p>
<p>
Let us name the left child of the root node <img src='/codeblog/latexrender/pictures/2e8775a7254de3c01cc341a8232f42cf.png' title='$c_{left}$' alt='$c_{left}$' align=absmiddle> and the right one <img src='/codeblog/latexrender/pictures/8b3cc4484a0c758334914ce9e28cd6a7.png' title='$c_{right}$' alt='$c_{right}$' align=absmiddle>. Both nodes are again  roots of smaller heaps. Both are again nearly complete heaps but with height <img src='/codeblog/latexrender/pictures/c84cc62ecb00e0df700742b534ade734.png' title='$h - 1$' alt='$h - 1$' align=absmiddle>. If they are complete we can easily calculate the number of elements they contain: <img src='/codeblog/latexrender/pictures/2b4f0f9976884a71ae6ae2cee94c4ec5.png' title='$\sum_{i=0}^{h-1}2^i = 2^h-1$' alt='$\sum_{i=0}^{h-1}2^i = 2^h-1$' align=absmiddle>. Unfortunately they are not complete since the last level is usually not completely filled. So let&#8217;s ignore the last level <img src='/codeblog/latexrender/pictures/ac93a104c81d2fb68196052c96b4f753.png' title='$h-1$' alt='$h-1$' align=absmiddle> and calculate the number of elements each of the heaps must <em>at least</em> have: <img src='/codeblog/latexrender/pictures/9a70097a66984b6391c12ca9aa24d07f.png' title='$\sum_{i=0}^{h-2}2^i = 2^{h-1}-1$' alt='$\sum_{i=0}^{h-2}2^i = 2^{h-1}-1$' align=absmiddle>
</p>
<p>
Now we must find out how the elements of the last level are distributed to the heap with root <img src='/codeblog/latexrender/pictures/2e8775a7254de3c01cc341a8232f42cf.png' title='$c_{left}$' alt='$c_{left}$' align=absmiddle> and the heap with root <img src='/codeblog/latexrender/pictures/8b3cc4484a0c758334914ce9e28cd6a7.png' title='$c_{right}$' alt='$c_{right}$' align=absmiddle>. There are <img src='/codeblog/latexrender/pictures/c62dcf57a8ea189b61d9d3e4e5f55ed3.png' title='$m = n - \sum_{i=0}^{h-1}2^i = n - (2^h - 1)$' alt='$m = n - \sum_{i=0}^{h-1}2^i = n - (2^h - 1)$' align=absmiddle> elements in the last level (where <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> is the size of the heap). If the last level is not filled up to the half then all nodes belong to the heap with root <img src='/codeblog/latexrender/pictures/2e8775a7254de3c01cc341a8232f42cf.png' title='$c_{left}$' alt='$c_{left}$' align=absmiddle>. Otherwise <img src='/codeblog/latexrender/pictures/2e8775a7254de3c01cc341a8232f42cf.png' title='$c_{left}$' alt='$c_{left}$' align=absmiddle> gets <img src='/codeblog/latexrender/pictures/171b623b2dac58ea33d168417b42147e.png' title='$\frac{1}{2}2^h$' alt='$\frac{1}{2}2^h$' align=absmiddle> additional nodes and <img src='/codeblog/latexrender/pictures/8b3cc4484a0c758334914ce9e28cd6a7.png' title='$c_{right}$' alt='$c_{right}$' align=absmiddle> gets <img src='/codeblog/latexrender/pictures/98a3da9b066dfd9849be065ffc2f12df.png' title='$m - \frac{1}{2}2^h$' alt='$m - \frac{1}{2}2^h$' align=absmiddle> nodes. In summary this yields:
</p>
<p>
<img src='/codeblog/latexrender/pictures/dfa5da1255957c3a74dfadf569b71091.png' title='$n_{left} = \begin{cases}2^{h-1} - 1 + m &amp; \text{if $m \leq \frac{1}{2}2^h$} \\ 2^{h-1} - 1 + \frac{1}{2}2^h &amp; \text{else} \end{cases}$' alt='$n_{left} = \begin{cases}2^{h-1} - 1 + m &amp; \text{if $m \leq \frac{1}{2}2^h$} \\ 2^{h-1} - 1 + \frac{1}{2}2^h &amp; \text{else} \end{cases}$' align=absmiddle>
</p>
<p>
<img src='/codeblog/latexrender/pictures/8e52f543734e56d02db07ac6f3f6416d.png' title='$n_{right} = \begin{cases}2^{h-1} - 1 &amp; \text{if $m \leq \frac{1}{2}2^h$} \\ 2^{h-1} - 1 + (m - \frac{1}{2}2^h) &amp; \text{else}\end{cases}$' alt='$n_{right} = \begin{cases}2^{h-1} - 1 &amp; \text{if $m \leq \frac{1}{2}2^h$} \\ 2^{h-1} - 1 + (m - \frac{1}{2}2^h) &amp; \text{else}\end{cases}$' align=absmiddle>
</p>
<p>
Now we can phrase a preliminary recursion formular. In principal the number of different heaps of size <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle> can be calculated by multiplying the number of different child-heaps. But this still ignores the fact that we can distribute the heap values differently to the left and right heap. In the following formula those permutations are hidden in the factor <img src='/codeblog/latexrender/pictures/190083ef7a1625fbc75f243cffb9c96d.png' title='$f$' alt='$f$' align=absmiddle>:
</p>
<p>
<img src='/codeblog/latexrender/pictures/31d1411b3e42a0aab1bb70da27fbee52.png' title='$heapnum(n) = f \cdot heapnum(n_{left}) \cdot heapnum(n_{right})$' alt='$heapnum(n) = f \cdot heapnum(n_{left}) \cdot heapnum(n_{right})$' align=absmiddle>
</p>
<p>
To calculate the value <img src='/codeblog/latexrender/pictures/190083ef7a1625fbc75f243cffb9c96d.png' title='$f$' alt='$f$' align=absmiddle> we need to find out, how we can distribute the values of the original heap to the children. We already observed that the largest value is at the top of the heap and thus will never be distributed.  So what about the children roots? One of the children heaps must contain the second largest value, otherwise the heap property cannot be fulfilled. This fact leads to two cases: Either the second largest value belongs to the left child-heap or the right child-heap.
</p>
<p>
Let&#8217;s observe the case where the second largest element belongs to the right child-heap. We still have to choose the value for the root of the left child-heap. Since we need at least <img src='/codeblog/latexrender/pictures/05fc8871ec838a4eaeba4c19da8272f3.png' title='$n_{left}-1$' alt='$n_{left}-1$' align=absmiddle> smaller values for the rest of the left heap, the <img src='/codeblog/latexrender/pictures/97fd6eb2599598e78741aea2e905b77e.png' title='$n_{left}$' alt='$n_{left}$' align=absmiddle>-smallest element is the first one we may choose. The last possible value is the third largest in the heap (where the largest is at the parent root and the second largest at the right child-heap&#8217;s root). For each of these roots we may choose the remaining heap values among the values smaller than the chosen root:
</p>
<p>
<img src='/codeblog/latexrender/pictures/c5ca469dd6e9c3d2383ba97579c0dcb0.png' title='$\sum_{i=n_{left}}^{n-2} \binom{i - 1}{n_{left}-1}$' alt='$\sum_{i=n_{left}}^{n-2} \binom{i - 1}{n_{left}-1}$' align=absmiddle>
</p>
<p>
The number of permutations of the right child-heap is fixed independent of the values we chose for the left child-heap. We must always choose <img src='/codeblog/latexrender/pictures/b415fa480eef66ecc6e8cf22a1d2443b.png' title='$n_{right} -1$' alt='$n_{right} -1$' align=absmiddle> elements among the remaining values, which results in <img src='/codeblog/latexrender/pictures/9c4cd913eb33cfc3872f016aceb9885b.png' title='$\binom{n-2-n_{left}}{n_{right}-1}$' alt='$\binom{n-2-n_{left}}{n_{right}-1}$' align=absmiddle>.
</p>
<p>
Now let&#8217;s have a look at the second case where the second largest element moves into the left child-heap. Here the number of permutations of the left child-heap is fixed no matter which values we will choose for the other heap:
</p>
<p>
<img src='/codeblog/latexrender/pictures/00f8ecbce74be6071ae80bbaf5c77fc2.png' title='$\binom{n-2-n_{right}}{n_{left}-1}$' alt='$\binom{n-2-n_{right}}{n_{left}-1}$' align=absmiddle>
</p>
<p>
Analog to the previous case we can derive the formula for the permutations of the right child-heap:
</p>
<p>
<img src='/codeblog/latexrender/pictures/ca0616cbe11184613617b7f29233ef32.png' title='$\sum_{i=n_{right}}^{n-2} \binom{i - 1}{n_{right}-1}$' alt='$\sum_{i=n_{right}}^{n-2} \binom{i - 1}{n_{right}-1}$' align=absmiddle>
</p>
<p>
Unfortunately we still miss a special case: If the right heap is empty, one of the above binomial coefficients will always become zero, which is obviously not what we expect.  Thus for this case we must only choose the values for the left child-heap:
</p>
<p>
<img src='/codeblog/latexrender/pictures/5a021ae7ad257ce510a3bd9b8b6c0281.png' title='$\binom{n-2}{n_{left}-1}$' alt='$\binom{n-2}{n_{left}-1}$' align=absmiddle>
</p>
<p>
Sticking all parts together we can compute the factor <img src='/codeblog/latexrender/pictures/190083ef7a1625fbc75f243cffb9c96d.png' title='$f$' alt='$f$' align=absmiddle>:
</p>
<p>
<img src='/codeblog/latexrender/pictures/1e9e9694a4b25f076958301f6764f1dc.png' title='$f = \binom{n-2-n_{left}}{n_{right}-1} \cdot \left( \sum_{i=n_{left}}^{n-2} \binom{i - 1}{n_{left}-1} \right) $' alt='$f = \binom{n-2-n_{left}}{n_{right}-1} \cdot \left( \sum_{i=n_{left}}^{n-2} \binom{i - 1}{n_{left}-1} \right) $' align=absmiddle>
</p>
<p>
<img src='/codeblog/latexrender/pictures/decea059b969a82f8db4167f2d015e46.png' title='$+ \binom{n-2-n_{right}}{n_{left}-1} \cdot \left( \sum_{i=n_{right}}^{n-2} \binom{i - 1}{n_{right}-1} \right)$' alt='$+ \binom{n-2-n_{right}}{n_{left}-1} \cdot \left( \sum_{i=n_{right}}^{n-2} \binom{i - 1}{n_{right}-1} \right)$' align=absmiddle>
</p>
<p>
<img src='/codeblog/latexrender/pictures/d28f2d58eb92ca009af10afe6ee66a09.png' title='$+ \begin{cases}\binom{n-2}{n_{left}-1} &amp; \text{if $n_{right} = 0$} \\ 0 &amp; \text{else}\end{cases}$' alt='$+ \begin{cases}\binom{n-2}{n_{left}-1} &amp; \text{if $n_{right} = 0$} \\ 0 &amp; \text{else}\end{cases}$' align=absmiddle>
</p>
<p>
Example:
</p>
<p>
Have a look at the heap image at the top. The heap contains five nodes thus <img src='/codeblog/latexrender/pictures/c2ec17c139a8e866e7df7274cd3fd9e8.png' title='$n = 5$' alt='$n = 5$' align=absmiddle>. The left child-heap contains three nodes thus <img src='/codeblog/latexrender/pictures/dc5727f4354755c1e42597c72d237360.png' title='$n_{left} = 3$' alt='$n_{left} = 3$' align=absmiddle> and the right one only a single node (<img src='/codeblog/latexrender/pictures/a79166a942969dc38a1162b70aa832b3.png' title='$n_{right} = 1$' alt='$n_{right} = 1$' align=absmiddle>). By using the above formula we calculate <img src='/codeblog/latexrender/pictures/190083ef7a1625fbc75f243cffb9c96d.png' title='$f$' alt='$f$' align=absmiddle>:
</p>
<p>
<img src='/codeblog/latexrender/pictures/adbf49146d9c42f27f930dfaf92c913a.png' title='$f = \binom{0}{0} \cdot \left( \sum_{i=3}^3 \binom {i-1}{2} \right) + \binom{2}{2} \cdot \left( \sum_{i=1}^3 \binom{i-1}{0} \right) + 0 = 1 + 3 = 4$' alt='$f = \binom{0}{0} \cdot \left( \sum_{i=3}^3 \binom {i-1}{2} \right) + \binom{2}{2} \cdot \left( \sum_{i=1}^3 \binom{i-1}{0} \right) + 0 = 1 + 3 = 4$' align=absmiddle>
</p>
<p>
So there is one possibility if the second largest value is in the right child-heap &#8211; this is one of the images. And if the second largest value is in the left child-heap there are three different configurations: The values 3, 2 and 0 can be at the root of the right child-heap. The number of different orderings is calculated by the <img src='/codeblog/latexrender/pictures/2fcc63a9bde491bb8dee2ca72a3dc241.png' title='$heapnum$' alt='$heapnum$' align=absmiddle> recursion.
</p>
<p>
I have written a small C++ code which uses (more or less) the above forumals to calculate the number of different heaps of size <img src='/codeblog/latexrender/pictures/55a049b8f161ae7cfeb0197d75aff967.png' title='$n$' alt='$n$' align=absmiddle>. The source code can be found <a href="https://www.faui2k3.org/svn/tobias/heapnum/heapnum.cpp">here</a>. The results for <img src='/codeblog/latexrender/pictures/9fe2d710dbae23a19fa401e926a2056c.png' title='$n \in \left\{ 1, \dots, 27 \right\}$' alt='$n \in \left\{ 1, \dots, 27 \right\}$' align=absmiddle> are:
</p>
<p><code><br />
$ seq 1 27 | ./heapnum<br />
1<br />
1<br />
2<br />
3<br />
8<br />
20<br />
80<br />
210<br />
896<br />
3360<br />
19200<br />
79200<br />
506880<br />
2745600<br />
21964800<br />
108108000<br />
820019200<br />
5227622400<br />
48881664000<br />
319258368000<br />
3143467008000<br />
25540669440000<br />
299677188096000<br />
2261626278912000<br />
25732281217843200<br />
241240136417280000<br />
3258308336025600000<br />
</code></p>
<p>
If you do not trust my results &#8211; that&#8217;s good since I tend to make mistakes <img src='http://tpreclik.dyndns.org/codeblog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  &#8211; you may want to have a look at the <a href="http://www.research.att.com/~njas/sequences/">On-Line Encyclopedia of Integer Sequences</a>. Search for example for &#8220;1,1,2,3,8,20,80,210&#8243;. If you take a careful look at the sequence you will notice that it is different (for example for <img src='/codeblog/latexrender/pictures/a8b640bea3181e4983e7d0f7dd48caf5.png' title='$n = 15$' alt='$n = 15$' align=absmiddle>) from mine. Wait! They also provide a maple script. If you execute the maple script it will output exactly the same sequence as mine (except for overflows for large n).
</p>
<p>
Maybe one last question which should be clarified: Does that hold for arbitrary values in the heap? To answer the question imagine a heap of size n which contains only nodes with value x. Then there exists of course only a single heap ordering. So the equations only hold for heaps with pairwise different values.
</p>
<p>
Update:
</p>
<p>
I updated the program code to support arbitrary precision integers using the <a href="http://www.swox.com/gmp/">gmp</a> library. To compile with gmp support:
</p>
<p><code><br />
$ g++ -O3 -DHAVE_GMP -DMAX_K=1024 -o heapnum heapnum.cpp -lgmpxx -lgmp<br />
$ seq 1 1024 | ./heapnum > heapnum.out<br />
</code</p>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=4</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My very own blog&#8230;</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=3</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=3#comments</comments>
		<pubDate>Fri, 12 Jan 2007 17:24:03 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[news]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=3</guid>
		<description><![CDATA[Well, now I got a shiny new blog. cute isn&#8217;t it? Stay tuned&#8230;]]></description>
			<content:encoded><![CDATA[<p>Well, now I got a shiny new blog. cute isn&#8217;t it? Stay tuned&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=3</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Defrosting revealed</title>
		<link>http://tpreclik.dyndns.org/codeblog/?p=44</link>
		<comments>http://tpreclik.dyndns.org/codeblog/?p=44#comments</comments>
		<pubDate>Thu, 08 Jul 2004 21:08:05 +0000</pubDate>
		<dc:creator>Tobias Preclik</dc:creator>
				<category><![CDATA[misc]]></category>

		<guid isPermaLink="false">http://tobias.preclik.de/blog/?p=44</guid>
		<description><![CDATA[This quick article is meant to reveal the &#8220;tricks&#8221; behind defrosting your refrigerator in a quick and efficient manner. There&#8217;s no need to occupy your neighbors fridge. Just get your hair-dryer or ask your neighboring bonny if you haven&#8217;t got one at hand. Now let&#8217;s get our hands on. Dump the content of your fridge [...]]]></description>
			<content:encoded><![CDATA[<p>
 This quick article is meant to reveal the &#8220;tricks&#8221; behind defrosting your refrigerator in a quick and efficient manner. There&#8217;s no need to occupy your neighbors fridge. Just get your hair-dryer or ask your neighboring bonny if you haven&#8217;t got one at hand. Now let&#8217;s get our hands on.
</p>
<p><span id="more-44"></span></p>
<p>
Dump the content of your fridge somewhere (assumed that your fridge isn&#8217;t as empty as mine) and attach the hair-dryer next to the ice box. In order that you can figure it out properly study the instruction photos.
</p>
<p>
Now plug in the dryer and take a nap until the ice box is completely defrosted.
</p>
<p>
Until the fridge&#8217;s cold again cool your beer in the bucket with the icy water. That&#8217;s all to it&#8230;
</p>
<p>
Cheers!
</p>
<table align="center">
<tr>
<td>
<a href='/codeblog/wp-content/uploads/2007/04/beer.jpg' title='Icy Beer'><img src='/codeblog/wp-content/uploads/2007/04/beer.thumbnail.jpg' alt='Icy Beer' /></a>
</td>
<td>
<a href='/codeblog/wp-content/uploads/2007/04/detail1.jpg' title='Hair Dryer Attached'><img src='/codeblog/wp-content/uploads/2007/04/detail1.thumbnail.jpg' alt='Hair Dryer Attached' /></a>
</td>
</tr>
<tr>
<td>
<a href='/codeblog/wp-content/uploads/2007/04/overview2.jpg' title='Defrosting Overview'><img src='/codeblog/wp-content/uploads/2007/04/overview2.thumbnail.jpg' alt='Defrosting Overview' /></a>
</td>
<td>
<a href='/codeblog/wp-content/uploads/2007/04/overview3.jpg' title='Defrosting Overview'><img src='/codeblog/wp-content/uploads/2007/04/overview3.thumbnail.jpg' alt='Defrosting Overview' /></a>
</td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://tpreclik.dyndns.org/codeblog/?feed=rss2&#038;p=44</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

