<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel>
        <title>ackstorm.de</title>
        <link>http://ackstorm.de</link>
        <description><![CDATA[ackstorm.de]]></description>
        <atom:link href="http://ackstorm.de/rss.xml" rel="self"
                   type="application/rss+xml" />
        <lastBuildDate>Mon, 10 May 2021 00:00:00 UT</lastBuildDate>
        <item>
    <title>Cross-Development for the Profi-5E Mikrocomputer</title>
    <link>http://ackstorm.de/posts/profi-5e-cross-development.html</link>
    <description><![CDATA[<div class="info">
  Posted on May 10, 2021. Tagged as: <a title="All pages tagged '8085'." href="http://ackstorm.de/tags/8085.html" rel="tag">8085</a>
</div>


<h2 id="introduction">Introduction</h2>
<p>Winter time is retro computing time. This year I got myself an
<a href="https://web.archive.org/web/20160304185822/http://www.kammerer.net/hw/profi.html">Profi-5E Mikrocomputer</a>. It’s
an 8085 based computer used for educational purposes. About 30 years
ago I did learn machine code programing on a similar 8085 based
<a href="https://de.wikipedia.org/wiki/Mikrocomputer_f%C3%BCr_Ausbildung">Mikrocomputer für Ausbildung (MFA computer)</a>. Therefore
the Profi-5E looked like an interesting system to play with. Especially
since it can be found on ebay for a few Euro.</p>
<p>Typing in programs on the hex keypad got old pretty quickly. So a way
to upload binary code to the system was desired to be able to do
cross-development with a <a href="https://github.com/glitchwrks/a85/">cross-assembler like
a85</a>. The documentation does not
have any information how that could be done with the default monitor
ROM. So some reverse engineering was needed.</p>
<h2 id="profi-5e-overview">Profi-5E Overview</h2>
<p>There is a
<a href="https://de.wikipedia.org/wiki/PROFI-5-Mikrocomputerfamilie">Wikipedia page about the Profi-5E</a>
with some basic information. Also, there is still
<a href="https://www.epv-verlag.de/content/fachbuecher/mikrocomputer/">printed documentation available from EPV Verlag</a>.
That includes schematics and programming instructions.</p>
<p>A few technical details:</p>
<ul>
<li>CPU: 8085A</li>
<li>RAM: up to 6 kB</li>
<li>ROM: 8 KB monitor EPROM + additional socket</li>
<li>I/O: 8255 (two of three free for user)</li>
</ul>
<p><img src="http://ackstorm.de/images/profi-5e.png" /></p>
<h2 id="available-inputoutput-options">Available Input/Output Options</h2>
<p>The Profi-5E has a small <strong>keypad</strong> for machine code entry and
control. For output there is an 8 digit LED display. Solder bridges
allow to configure memory size and type. Other settings like serial
speed are done with DIP-Switches. An EEPROM contains a monitor program
to interact with the system. The monitor program allows reading and
writing of memory as well as starting programs.</p>
<p>There is an <strong>audio interface</strong> for storing and loading programs to/from a
cassete deck. The signal level is a little low for -10 dbV equipment,
but storing and loading works fine with an old cassette deck using a
RCA connector cable and an adapter for the DIN connector.</p>
<p>There is also a <strong>V.24 serial port</strong> using a 25 pin D-SUB connector. The
serial port can be operated at the amazing speed of 300 Baud up to
2400 Baud. The interface uses -4V and +4V levels. It can be connected
to a standard FTDI-USB-serial converter (please note: that excludes
the 5V or 3.2V TTL-level USB-serial converters). The cabling has to
ensure that receive readiness is signaled on pin 5, or DIP-Switch 5
has to be switched to OFF. Fortunately I found a chain of adapters
that converts from 25 pin to 9 pin D-SUB and connects pin 5 of the
Profi-5E output to pin 1 on the USB-serial device.</p>
<p>There is a documented <strong>“F-8”-function</strong> (started by pressing F-8-G)
that allows reading ASCII text into memory from the serial port. This
looks promising for the desired goal of cross-development. But to find
out whether it can be misused for binary, the monitor ROM has to be
further analyzed.</p>
<h2 id="monitor-rom-analysis-with-ghidra">Monitor ROM Analysis with Ghidra</h2>
<p>To get the monitor ROM in binary form, one can always use an EPROM
reader. That was unavailable, but there is another way. The “F-6”
function allows to dump memory to the serial port. With some scripting
this can be converted back into binary and loaded into
<a href="https://ghidra-sre.org/">Ghidra</a> without problems. Ghidra does
support 8085 code out of the box.</p>
<p>The Profi-5E documentation contains several useful functions with
entry points. It helps to locate these functions and give them proper
names in Ghidra. Following the cross-references of the serial port
functions, you will find the “F-8” implementation at 0x04B6.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode gnuassembler"><code class="sourceCode gnuassembler"><span id="cb1-1"><a href="http://ackstorm.de#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">**************************************************************</span></span>
<span id="cb1-2"><a href="http://ackstorm.de#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">*</span>                          FUNCTION                          <span class="op">*</span></span>
<span id="cb1-3"><a href="http://ackstorm.de#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">**************************************************************</span></span>
<span id="cb1-4"><a href="http://ackstorm.de#cb1-4" aria-hidden="true" tabindex="-1"></a>                     undefined SYS_F8_ASCII_IN<span class="op">(</span>void<span class="op">)</span></span>
<span id="cb1-5"><a href="http://ackstorm.de#cb1-5" aria-hidden="true" tabindex="-1"></a>     undefined         <span class="fu">A:</span><span class="dv">1</span>            <span class="op">&lt;</span>RETURN<span class="op">&gt;</span></span>
<span id="cb1-6"><a href="http://ackstorm.de#cb1-6" aria-hidden="true" tabindex="-1"></a>                     SYS_F8_ASCII_IN</span>
<span id="cb1-7"><a href="http://ackstorm.de#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>b6 <span class="dv">21</span> <span class="dv">77</span> <span class="dv">77</span>        LXI        HL<span class="op">,</span><span class="bn">0x7777</span></span>
<span id="cb1-8"><a href="http://ackstorm.de#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>b9 cd <span class="dv">07</span> <span class="dv">07</span>        CALL       HEXIN</span>
<span id="cb1-9"><a href="http://ackstorm.de#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>bc <span class="dv">22</span> ac <span class="dv">87</span>        SHLD       <span class="op">(</span>DAT_ram_87ac<span class="op">)</span></span>
<span id="cb1-10"><a href="http://ackstorm.de#cb1-10" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>bf <span class="dv">21</span> <span class="dv">00</span> <span class="dv">87</span>        LXI        HL<span class="op">,</span><span class="bn">0x8700</span></span>
<span id="cb1-11"><a href="http://ackstorm.de#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>c2 <span class="dv">22</span> ae <span class="dv">87</span>        SHLD       <span class="op">(</span>DAT_ram_87ae<span class="op">)</span></span>
<span id="cb1-12"><a href="http://ackstorm.de#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>c5 cd <span class="dv">6</span>b <span class="dv">05</span>        CALL       BAUD</span>
<span id="cb1-13"><a href="http://ackstorm.de#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>c8 cd <span class="dv">80</span> <span class="dv">03</span>        CALL       DUNKL</span>
<span id="cb1-14"><a href="http://ackstorm.de#cb1-14" aria-hidden="true" tabindex="-1"></a>                     sys_f8_loop_next_character</span>
<span id="cb1-15"><a href="http://ackstorm.de#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>cb cd f1 <span class="dv">04</span>        CALL       ASCII</span>
<span id="cb1-16"><a href="http://ackstorm.de#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>ce <span class="dv">2</span>a ac <span class="dv">87</span>        LHLD       <span class="op">(</span>DAT_ram_87ac<span class="op">)</span></span>
<span id="cb1-17"><a href="http://ackstorm.de#cb1-17" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>d1 <span class="dv">77</span>              MOV        <span class="op">(</span>HL<span class="op">=&gt;</span>DAT_ram_7777<span class="op">),</span>A</span>
<span id="cb1-18"><a href="http://ackstorm.de#cb1-18" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>d2 fe <span class="dv">03</span>           CPI        <span class="bn">0x3</span></span>
<span id="cb1-19"><a href="http://ackstorm.de#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>d4 ca b2 <span class="dv">0</span>e        JZ         TEXT8_ENDE</span>
<span id="cb1-20"><a href="http://ackstorm.de#cb1-20" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>d7 cd <span class="dv">1</span>f <span class="dv">05</span>        CALL       SYS_F8_ASCII_IN_BACKSPACE</span>
<span id="cb1-21"><a href="http://ackstorm.de#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>da cd <span class="dv">15</span> <span class="dv">05</span>        CALL       SYS_F8_ASCII_IN_CR_ADD_LF</span>
<span id="cb1-22"><a href="http://ackstorm.de#cb1-22" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>dd <span class="dv">23</span>              INX        HL</span>
<span id="cb1-23"><a href="http://ackstorm.de#cb1-23" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>de <span class="dv">22</span> ac <span class="dv">87</span>        SHLD       <span class="op">(</span>DAT_ram_87ac<span class="op">)</span></span>
<span id="cb1-24"><a href="http://ackstorm.de#cb1-24" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>e1 e5              PUSH       HL<span class="op">=&gt;</span>DAT_ram_7778</span>
<span id="cb1-25"><a href="http://ackstorm.de#cb1-25" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>e2 <span class="dv">2</span>a ae <span class="dv">87</span>        LHLD       <span class="op">(</span>DAT_ram_87ae<span class="op">)</span></span>
<span id="cb1-26"><a href="http://ackstorm.de#cb1-26" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>e5 eb              XCHG</span>
<span id="cb1-27"><a href="http://ackstorm.de#cb1-27" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>e6 e1              POP        HL</span>
<span id="cb1-28"><a href="http://ackstorm.de#cb1-28" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>e7 cd bf <span class="dv">06</span>        CALL       HLDE</span>
<span id="cb1-29"><a href="http://ackstorm.de#cb1-29" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>ea da cb <span class="dv">04</span>        JC         sys_f8_loop_next_character</span>
<span id="cb1-30"><a href="http://ackstorm.de#cb1-30" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>ed cd <span class="dv">25</span> <span class="dv">05</span>        CALL       SYS_F8_ASCII_IN_SFENDB</span>
<span id="cb1-31"><a href="http://ackstorm.de#cb1-31" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">04</span>f0 <span class="dv">76</span>              HALT</span></code></pre></div>
<p>This shows that 0x03 (CTRL-C) is interpreted as end-of-transfer. Also
backspace has special handling and CR is expanded to CR-LF. That
doesn’t look like it works for binary transfer, although the input
function does support 8 bit data.</p>
<p>Looking for a place that calls this function reveals a function
pointer table around 0x028C with 16 function pointers. F-0, F-E and
F-F are not used as they contain 0xFFFF. Interestingly F-D is used but
not documented. It points to 0x0F70:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode gnuassembler"><code class="sourceCode gnuassembler"><span id="cb2-1"><a href="http://ackstorm.de#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="op">**************************************************************</span></span>
<span id="cb2-2"><a href="http://ackstorm.de#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">*</span>                          FUNCTION                          <span class="op">*</span></span>
<span id="cb2-3"><a href="http://ackstorm.de#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">**************************************************************</span></span>
<span id="cb2-4"><a href="http://ackstorm.de#cb2-4" aria-hidden="true" tabindex="-1"></a>                     undefined SYS_FD_BINARY_IN<span class="op">(</span>void<span class="op">)</span></span>
<span id="cb2-5"><a href="http://ackstorm.de#cb2-5" aria-hidden="true" tabindex="-1"></a>     undefined         <span class="fu">A:</span><span class="dv">1</span>            <span class="op">&lt;</span>RETURN<span class="op">&gt;</span></span>
<span id="cb2-6"><a href="http://ackstorm.de#cb2-6" aria-hidden="true" tabindex="-1"></a>                     SYS_FD_BINARY_IN</span>
<span id="cb2-7"><a href="http://ackstorm.de#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f70 <span class="dv">21</span> <span class="dv">77</span> <span class="dv">77</span>        LXI        HL<span class="op">,</span><span class="bn">0x7777</span></span>
<span id="cb2-8"><a href="http://ackstorm.de#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f73 cd <span class="dv">07</span> <span class="dv">07</span>        CALL       HEXIN</span>
<span id="cb2-9"><a href="http://ackstorm.de#cb2-9" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f76 <span class="dv">22</span> ac <span class="dv">87</span>        SHLD       <span class="op">(</span>DAT_ram_87ac<span class="op">)</span></span>
<span id="cb2-10"><a href="http://ackstorm.de#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f79 <span class="dv">21</span> <span class="dv">00</span> <span class="dv">87</span>        LXI        HL<span class="op">,</span><span class="bn">0x8700</span></span>
<span id="cb2-11"><a href="http://ackstorm.de#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f7c <span class="dv">22</span> ae <span class="dv">87</span>        SHLD       <span class="op">(</span>DAT_ram_87ae<span class="op">)</span></span>
<span id="cb2-12"><a href="http://ackstorm.de#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f7f cd <span class="dv">6</span>b <span class="dv">05</span>        CALL       BAUD</span>
<span id="cb2-13"><a href="http://ackstorm.de#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f82 cd <span class="dv">80</span> <span class="dv">03</span>        CALL       DUNKL</span>
<span id="cb2-14"><a href="http://ackstorm.de#cb2-14" aria-hidden="true" tabindex="-1"></a>                     sys_fd_loop_next_character</span>
<span id="cb2-15"><a href="http://ackstorm.de#cb2-15" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f85 cd f1 <span class="dv">04</span>        CALL       ASCII</span>
<span id="cb2-16"><a href="http://ackstorm.de#cb2-16" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f88 <span class="dv">2</span>a ac <span class="dv">87</span>        LHLD       <span class="op">(</span>DAT_ram_87ac<span class="op">)</span></span>
<span id="cb2-17"><a href="http://ackstorm.de#cb2-17" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f8b <span class="dv">77</span>              MOV        <span class="op">(</span>HL<span class="op">=&gt;</span>DAT_ram_7777<span class="op">),</span>A</span>
<span id="cb2-18"><a href="http://ackstorm.de#cb2-18" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f8c <span class="dv">23</span>              INX        HL</span>
<span id="cb2-19"><a href="http://ackstorm.de#cb2-19" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f8d <span class="dv">22</span> ac <span class="dv">87</span>        SHLD       <span class="op">(</span>DAT_ram_87ac<span class="op">)</span></span>
<span id="cb2-20"><a href="http://ackstorm.de#cb2-20" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f90 e5              PUSH       HL<span class="op">=&gt;</span>DAT_ram_7778</span>
<span id="cb2-21"><a href="http://ackstorm.de#cb2-21" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f91 <span class="dv">2</span>a ae <span class="dv">87</span>        LHLD       <span class="op">(</span>DAT_ram_87ae<span class="op">)</span></span>
<span id="cb2-22"><a href="http://ackstorm.de#cb2-22" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f94 eb              XCHG</span>
<span id="cb2-23"><a href="http://ackstorm.de#cb2-23" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f95 e1              POP        HL</span>
<span id="cb2-24"><a href="http://ackstorm.de#cb2-24" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f96 cd bf <span class="dv">06</span>        CALL       HLDE</span>
<span id="cb2-25"><a href="http://ackstorm.de#cb2-25" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f99 da <span class="dv">85</span> <span class="dv">0</span>f        JC         sys_fd_loop_next_character</span>
<span id="cb2-26"><a href="http://ackstorm.de#cb2-26" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f9c cd <span class="dv">25</span> <span class="dv">05</span>        CALL       SYS_F8_ASCII_IN_SFENDB</span>
<span id="cb2-27"><a href="http://ackstorm.de#cb2-27" aria-hidden="true" tabindex="-1"></a><span class="fu">ram:</span><span class="dv">0</span>f9f <span class="dv">76</span>              HALT</span></code></pre></div>
<p>This “F-D” function looks very much like “F-8”, except it doe not
interpret any special characters. There is no stop condition except
the memory limit at 0x8700 (which should protect monitor program
variables space). The missing stop condition is no problem as the
interrupt key can be used instead.</p>
<h2 id="uploading-code-to-the-profi-5e-using-f-d">Uploading Code to the Profi-5E using F-D</h2>
<p>To upload code to the Profi-5E follow these steps:</p>
<ul>
<li><p>Press the red F key and then the black D key</p></li>
<li><p>Press the G key to start the function</p></li>
<li><p>Enter start address and confirm with red S key.</p></li>
<li><p>The display will be turned off (“DUNKL”)</p></li>
<li><p>Transmit a binary from a connected computer:</p>
<pre><code>cat out.bin | cu -s 300 -l /dev/cuaU0</code></pre></li>
</ul>
<p>The transmission is most reliable at lower speeds. With 2400 Baud I
found that bits get lost intermittently.</p>
<h2 id="extending-the-monitor-rom-to-allow-loading-ihex-format">Extending the monitor ROM to allow loading IHEX format</h2>
<p>Uploading programs using F-D requires entering the start address every
time. It would be much nicer if the monitor ROM could accept IHEX
formatted data, which contains the address to load to in every input
line:</p>
<div class="sourceCode">
<pre class="sourceCode">
:10<span style="color: red;">8100</span>00C3148100000000000000004900000000CE
:10<span style="color: red;">8110</span>0000000000160801038179824FCD60033E04
</pre>
</div>
<p>While reading the monitor ROM I noticed that some of the F-functions
were unused, in particular F-0, F-E, F-F. Also there is some unused
space between 0x0fa0 and 0x1c00, which would allow to add
functionality.</p>
<p>So I wrote a little IHEX parser and embedded it into
the monitor monitor ROM. The result <a href="https://github.com/ra1fh/profi-5e-ihex">can found in my Github
repository</a>.
To use this, you have to read the original EPROM content and write a
patched EPROM. Patching the EPROM data is part of the build process.</p>
<p>Afterwards the Profi-5E computer will be able to read IHEX data from
the serial port using the F-E function keys</p>
<h2 id="summary">Summary</h2>
<p>The undocumented F-D function allows to transmit programs to the
Profi-5E using the standard monitor ROM. This allows to develop with a
<a href="https://github.com/glitchwrks/a85/">8085 cross-assembler</a> and
transmit the results via serial line to the target system.</p>
<p>With a <a href="https://github.com/ra1fh/profi-5e-ihex">modified monitor ROM</a>,
the Profi-5E can read IHEX data from the serial port, making
cross-development even easier.</p>
]]></description>
    <pubDate>Mon, 10 May 2021 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/profi-5e-cross-development.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Daum Ergo Bike Reverse Engineering Part 3</title>
    <link>http://ackstorm.de/posts/daum-reverse-part-3.html</link>
    <description><![CDATA[<div class="info">
  Posted on May 10, 2020. Tagged as: <a title="All pages tagged 'daum'." href="http://ackstorm.de/tags/daum.html" rel="tag">daum</a>
</div>


<p>The Daum Ergo Bike writes result records for each training to SD-Card
directory <code>data/result/ergo_bike</code>. The data can be extracted with
<code>emc2edit.exe</code>
<a href="http://www.daum-electronic.de/de/support/pre-bk8i.html">provided by Daum</a>
and converted to CSV.</p>
<p>The result file format was undocumented so far. After procmon revealed
that the records are 44 Bytes long it’s not too hard to figure out the
details by comparing the binary content with the CSV data:</p>
<pre><code>result_file = GreedyRange(
    &quot;result_record&quot; / Struct(
        &quot;elapsed_time&quot;  / Int32ul,   # s
        &quot;distance&quot;      / Float32l,  # m
        &quot;energy&quot;        / Float32l,  # kJ
        &quot;slope&quot;         / Int16sl,   # 1/10 %
        &quot;torque&quot;        / Int16ul,   # 1/10 NM
        &quot;rpm&quot;           / Int16ul,   # 1/10 RPM
        &quot;speed&quot;         / Int16ul,   # 1/10 km/h
        &quot;power&quot;         / Int16ul,   # Watt
        &quot;gear&quot;          / Int8ul,
        &quot;device_active&quot; / Int8ul,    # 1
        &quot;pulse&quot;         / Int8ul,    # bpm
        &quot;pulse_type&quot;    / Int8ul,    # 7=invalid pulse, 0/4=valid pulse?
        &quot;pulse_time_1&quot;  / Int16ul,
        &quot;pulse_time_2&quot;  / Int16ul,
        &quot;pulse_time_3&quot;  / Int16ul,
        &quot;pulse_time_4&quot;  / Int16ul,
        &quot;pulse_time_5&quot;  / Int16ul,
        &quot;pulse_time_6&quot;  / Int16ul,
        &quot;training_type&quot; / Int16ul,
        &quot;training_value&quot;/ Float32l
))</code></pre>
<p>I’ve written a simple python script that decodes the result records to
CSV similar to the emc2edit
output. <a href="https://github.com/ra1fh/daum-ergo/tree/master/result">It’s Available on Github</a>.</p>
]]></description>
    <pubDate>Sun, 10 May 2020 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/daum-reverse-part-3.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Daum Ergo Bike Reverse Engineering Part 2</title>
    <link>http://ackstorm.de/posts/daum-reverse-part-2.html</link>
    <description><![CDATA[<div class="info">
  Posted on April 25, 2020. Tagged as: <a title="All pages tagged 'daum'." href="http://ackstorm.de/tags/daum.html" rel="tag">daum</a>
</div>


<p>I’ve added pictures of the PCB, including serial port location, and a
serial console boot log to the <a href="http://ackstorm.de/projects/daum/daum.html">daum project page</a>.</p>
<p><img src="http://ackstorm.de/projects/daum/board-serial.jpg" /></p>
]]></description>
    <pubDate>Sat, 25 Apr 2020 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/daum-reverse-part-2.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Density Altitude on HP48</title>
    <link>http://ackstorm.de/posts/hp48-density-altitude.html</link>
    <description><![CDATA[<div class="info">
  Posted on October 15, 2019. Tagged as: <a title="All pages tagged 'hp48'." href="http://ackstorm.de/tags/hp48.html" rel="tag">hp48</a>
</div>


<p>For checking the performance calculation of my electronic flight book
application of choice, I have implemented a little program for
calculating the density altitude on an HP48 calculator. Here are the
steps to derive the formula. This is posted an example only without
any guarantees of correctness, so don’t rely on this. Especially these
equations and programs don’t consider humidity.</p>
<h2 id="equations">Equations</h2>
<p>First step is to calculate the density at the given altitude, using
pressure reduced to sea level (QNH or <span class="math inline"><em>p</em><sub>0</sub></span>), and altitude <span class="math inline"><em>h</em></span> as
inputs:</p>
<p><img src="http://ackstorm.de/images/da-eq1.png" class="equation" /></p>
<p>The equations use the following constants:</p>
<p><img src="http://ackstorm.de/images/da-eq2.png" class="equation" /></p>
<p>Next step is to apply temperature correction to the density with
<span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span> as input to get the temperature corrected density <span class="math inline"><em>ρ</em><sub>2</sub></span>:</p>
<p><img src="http://ackstorm.de/images/da-eq3.png" class="equation" /></p>
<p>The calculated density can then be converted back to a virtual
altitude at international standard athmosphere (ISA) conditions, aka
density altitude:</p>
<p><img src="http://ackstorm.de/images/da-eq4.png" class="equation" /></p>
<p>If you fill in the some example numbers (e.g. 0 ft, QNH 1013.25 hPA,
<span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span> 1 K), you will get an increase in density altitude per
<span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span> of about 118 ft per <span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span> for small positive
<span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span>. This closely matches the rule of thumb of 120 ft per
<span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span>.</p>
<h2 id="rpl-program-for-hp48-using-delta-isa">RPL Program for HP48 using <span class="math inline"><em>Δ</em><em>I</em><em>S</em><em>A</em></span></h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="http://ackstorm.de#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">%%</span>HP: T(<span class="dv">3</span>)A(R)F(.)<span class="op">;</span></span>
<span id="cb1-2"><a href="http://ackstorm.de#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="op">@</span> calculate density altitude <span class="cf">with</span> delta ISA:</span>
<span id="cb1-3"><a href="http://ackstorm.de#cb1-3" aria-hidden="true" tabindex="-1"></a>\<span class="op">&lt;&lt;</span></span>
<span id="cb1-4"><a href="http://ackstorm.de#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">&quot;DENSITY ALTITUDE&quot;</span></span>
<span id="cb1-5"><a href="http://ackstorm.de#cb1-5" aria-hidden="true" tabindex="-1"></a>  {</span>
<span id="cb1-6"><a href="http://ackstorm.de#cb1-6" aria-hidden="true" tabindex="-1"></a>    { <span class="st">&quot;ALTITUDE   &quot;</span> <span class="st">&quot;ALTITUDE IN FT             &quot;</span> <span class="dv">0</span>  }</span>
<span id="cb1-7"><a href="http://ackstorm.de#cb1-7" aria-hidden="true" tabindex="-1"></a>    { <span class="st">&quot;QNH        &quot;</span> <span class="st">&quot;QNH IN HPA                 &quot;</span> <span class="dv">0</span>  }</span>
<span id="cb1-8"><a href="http://ackstorm.de#cb1-8" aria-hidden="true" tabindex="-1"></a>    { <span class="st">&quot;DELTA ISA  &quot;</span> <span class="st">&quot;TEMPERATURE DIFFERENCE IN K&quot;</span> <span class="dv">0</span>  }</span>
<span id="cb1-9"><a href="http://ackstorm.de#cb1-9" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb1-10"><a href="http://ackstorm.de#cb1-10" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span></span>
<span id="cb1-11"><a href="http://ackstorm.de#cb1-11" aria-hidden="true" tabindex="-1"></a>  { <span class="dv">0</span> <span class="fl">1013.25</span> <span class="dv">0</span> }</span>
<span id="cb1-12"><a href="http://ackstorm.de#cb1-12" aria-hidden="true" tabindex="-1"></a>  { <span class="dv">0</span> <span class="fl">1013.25</span> <span class="dv">0</span> }</span>
<span id="cb1-13"><a href="http://ackstorm.de#cb1-13" aria-hidden="true" tabindex="-1"></a>  IF INFORM THEN</span>
<span id="cb1-14"><a href="http://ackstorm.de#cb1-14" aria-hidden="true" tabindex="-1"></a>    OBJ\<span class="op">-&gt;</span> DROP</span>
<span id="cb1-15"><a href="http://ackstorm.de#cb1-15" aria-hidden="true" tabindex="-1"></a>	<span class="dv">3</span> PICK</span>
<span id="cb1-16"><a href="http://ackstorm.de#cb1-16" aria-hidden="true" tabindex="-1"></a>	<span class="dv">3</span> PICK</span>
<span id="cb1-17"><a href="http://ackstorm.de#cb1-17" aria-hidden="true" tabindex="-1"></a>	<span class="dv">3</span> PICK</span>
<span id="cb1-18"><a href="http://ackstorm.de#cb1-18" aria-hidden="true" tabindex="-1"></a>    \<span class="op">-&gt;</span> alt qnh isa</span>
<span id="cb1-19"><a href="http://ackstorm.de#cb1-19" aria-hidden="true" tabindex="-1"></a>    \<span class="op">&lt;&lt;</span></span>
<span id="cb1-20"><a href="http://ackstorm.de#cb1-20" aria-hidden="true" tabindex="-1"></a>      alt <span class="fl">0.3048</span> <span class="op">*</span></span>
<span id="cb1-21"><a href="http://ackstorm.de#cb1-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">-</span><span class="fl">9.80665</span> <span class="fl">287.05</span> <span class="op">-</span><span class="fl">0.0065</span> <span class="op">*</span> <span class="op">/</span></span>
<span id="cb1-22"><a href="http://ackstorm.de#cb1-22" aria-hidden="true" tabindex="-1"></a>      <span class="dv">1</span> <span class="op">-</span></span>
<span id="cb1-23"><a href="http://ackstorm.de#cb1-23" aria-hidden="true" tabindex="-1"></a>      qnh <span class="dv">100</span> <span class="op">*</span> <span class="fl">287.05</span> <span class="fl">288.15</span> <span class="op">*</span> <span class="op">/</span></span>
<span id="cb1-24"><a href="http://ackstorm.de#cb1-24" aria-hidden="true" tabindex="-1"></a>      \<span class="op">-&gt;</span> h k1 rho0</span>
<span id="cb1-25"><a href="http://ackstorm.de#cb1-25" aria-hidden="true" tabindex="-1"></a>      \<span class="op">&lt;&lt;</span></span>
<span id="cb1-26"><a href="http://ackstorm.de#cb1-26" aria-hidden="true" tabindex="-1"></a>        rho0</span>
<span id="cb1-27"><a href="http://ackstorm.de#cb1-27" aria-hidden="true" tabindex="-1"></a>        <span class="dv">1</span> <span class="op">-</span><span class="fl">0.0065</span> h <span class="op">*</span> <span class="fl">288.15</span> <span class="op">/</span> <span class="op">+</span></span>
<span id="cb1-28"><a href="http://ackstorm.de#cb1-28" aria-hidden="true" tabindex="-1"></a>        k1 <span class="op">^</span></span>
<span id="cb1-29"><a href="http://ackstorm.de#cb1-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">*</span></span>
<span id="cb1-30"><a href="http://ackstorm.de#cb1-30" aria-hidden="true" tabindex="-1"></a>        \<span class="op">-&gt;</span> rho1</span>
<span id="cb1-31"><a href="http://ackstorm.de#cb1-31" aria-hidden="true" tabindex="-1"></a>        \<span class="op">&lt;&lt;</span></span>
<span id="cb1-32"><a href="http://ackstorm.de#cb1-32" aria-hidden="true" tabindex="-1"></a>          <span class="fl">288.15</span> <span class="op">-</span><span class="fl">0.0065</span> h <span class="op">*</span> <span class="op">+</span></span>
<span id="cb1-33"><a href="http://ackstorm.de#cb1-33" aria-hidden="true" tabindex="-1"></a>          <span class="fl">288.15</span> <span class="op">-</span><span class="fl">0.0065</span> h <span class="op">*</span> <span class="op">+</span> isa <span class="op">+</span> <span class="op">/</span></span>
<span id="cb1-34"><a href="http://ackstorm.de#cb1-34" aria-hidden="true" tabindex="-1"></a>          rho1 <span class="op">*</span></span>
<span id="cb1-35"><a href="http://ackstorm.de#cb1-35" aria-hidden="true" tabindex="-1"></a>          </span>
<span id="cb1-36"><a href="http://ackstorm.de#cb1-36" aria-hidden="true" tabindex="-1"></a>          <span class="dv">1</span></span>
<span id="cb1-37"><a href="http://ackstorm.de#cb1-37" aria-hidden="true" tabindex="-1"></a>          <span class="fl">9.80665</span> <span class="fl">287.05</span> <span class="op">-</span><span class="fl">0.0065</span> <span class="op">*</span> <span class="op">/</span></span>
<span id="cb1-38"><a href="http://ackstorm.de#cb1-38" aria-hidden="true" tabindex="-1"></a>          <span class="dv">1</span> <span class="op">+</span></span>
<span id="cb1-39"><a href="http://ackstorm.de#cb1-39" aria-hidden="true" tabindex="-1"></a>          <span class="op">/</span></span>
<span id="cb1-40"><a href="http://ackstorm.de#cb1-40" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb1-41"><a href="http://ackstorm.de#cb1-41" aria-hidden="true" tabindex="-1"></a>          \<span class="op">-&gt;</span> rho2 k2</span>
<span id="cb1-42"><a href="http://ackstorm.de#cb1-42" aria-hidden="true" tabindex="-1"></a>          \<span class="op">&lt;&lt;</span></span>
<span id="cb1-43"><a href="http://ackstorm.de#cb1-43" aria-hidden="true" tabindex="-1"></a>            <span class="fl">288.15</span></span>
<span id="cb1-44"><a href="http://ackstorm.de#cb1-44" aria-hidden="true" tabindex="-1"></a>            <span class="fl">288.15</span></span>
<span id="cb1-45"><a href="http://ackstorm.de#cb1-45" aria-hidden="true" tabindex="-1"></a>            rho2 <span class="fl">1.225</span> <span class="op">/</span></span>
<span id="cb1-46"><a href="http://ackstorm.de#cb1-46" aria-hidden="true" tabindex="-1"></a>            k2 <span class="op">^</span></span>
<span id="cb1-47"><a href="http://ackstorm.de#cb1-47" aria-hidden="true" tabindex="-1"></a>            <span class="op">*</span></span>
<span id="cb1-48"><a href="http://ackstorm.de#cb1-48" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb1-49"><a href="http://ackstorm.de#cb1-49" aria-hidden="true" tabindex="-1"></a>            <span class="op">-</span></span>
<span id="cb1-50"><a href="http://ackstorm.de#cb1-50" aria-hidden="true" tabindex="-1"></a>            <span class="op">-</span><span class="fl">0.0065</span></span>
<span id="cb1-51"><a href="http://ackstorm.de#cb1-51" aria-hidden="true" tabindex="-1"></a>            rho2 <span class="fl">1.225</span> <span class="op">/</span></span>
<span id="cb1-52"><a href="http://ackstorm.de#cb1-52" aria-hidden="true" tabindex="-1"></a>            k2 <span class="op">^</span></span>
<span id="cb1-53"><a href="http://ackstorm.de#cb1-53" aria-hidden="true" tabindex="-1"></a>            <span class="op">*</span></span>
<span id="cb1-54"><a href="http://ackstorm.de#cb1-54" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb1-55"><a href="http://ackstorm.de#cb1-55" aria-hidden="true" tabindex="-1"></a>            <span class="op">/</span></span>
<span id="cb1-56"><a href="http://ackstorm.de#cb1-56" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb1-57"><a href="http://ackstorm.de#cb1-57" aria-hidden="true" tabindex="-1"></a>            <span class="fl">0.3048</span></span>
<span id="cb1-58"><a href="http://ackstorm.de#cb1-58" aria-hidden="true" tabindex="-1"></a>            <span class="op">/</span></span>
<span id="cb1-59"><a href="http://ackstorm.de#cb1-59" aria-hidden="true" tabindex="-1"></a>          \<span class="op">&gt;&gt;</span></span>
<span id="cb1-60"><a href="http://ackstorm.de#cb1-60" aria-hidden="true" tabindex="-1"></a>        \<span class="op">&gt;&gt;</span></span>
<span id="cb1-61"><a href="http://ackstorm.de#cb1-61" aria-hidden="true" tabindex="-1"></a>      \<span class="op">&gt;&gt;</span></span>
<span id="cb1-62"><a href="http://ackstorm.de#cb1-62" aria-hidden="true" tabindex="-1"></a>    \<span class="op">&gt;&gt;</span></span>
<span id="cb1-63"><a href="http://ackstorm.de#cb1-63" aria-hidden="true" tabindex="-1"></a>  END</span>
<span id="cb1-64"><a href="http://ackstorm.de#cb1-64" aria-hidden="true" tabindex="-1"></a>\<span class="op">&gt;&gt;</span></span></code></pre></div>
<h2 id="rpl-program-for-hp48-using-tempature-in-c">RPL Program for HP48 using tempature in °C</h2>
<div class="sourceCode" id="cb2"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="http://ackstorm.de#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="op">%%</span>HP: T(<span class="dv">3</span>)A(R)F(.)<span class="op">;</span></span>
<span id="cb2-2"><a href="http://ackstorm.de#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">@</span> calculate density altitude <span class="cf">with</span> absolute temperature</span>
<span id="cb2-3"><a href="http://ackstorm.de#cb2-3" aria-hidden="true" tabindex="-1"></a>\<span class="op">&lt;&lt;</span></span>
<span id="cb2-4"><a href="http://ackstorm.de#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">&quot;DENSITY ALTITUDE&quot;</span></span>
<span id="cb2-5"><a href="http://ackstorm.de#cb2-5" aria-hidden="true" tabindex="-1"></a>  {</span>
<span id="cb2-6"><a href="http://ackstorm.de#cb2-6" aria-hidden="true" tabindex="-1"></a>    { <span class="st">&quot;ALTITUDE   &quot;</span> <span class="st">&quot;ALTITUDE IN FT  &quot;</span> <span class="dv">0</span>  }</span>
<span id="cb2-7"><a href="http://ackstorm.de#cb2-7" aria-hidden="true" tabindex="-1"></a>    { <span class="st">&quot;QNH        &quot;</span> <span class="st">&quot;QNH IN HPA      &quot;</span> <span class="dv">0</span>  }</span>
<span id="cb2-8"><a href="http://ackstorm.de#cb2-8" aria-hidden="true" tabindex="-1"></a>    { <span class="st">&quot;TEMPERATURE&quot;</span> <span class="st">&quot;TEMPERATURE IN C&quot;</span> <span class="dv">0</span>  }</span>
<span id="cb2-9"><a href="http://ackstorm.de#cb2-9" aria-hidden="true" tabindex="-1"></a>  }</span>
<span id="cb2-10"><a href="http://ackstorm.de#cb2-10" aria-hidden="true" tabindex="-1"></a>  <span class="dv">1</span></span>
<span id="cb2-11"><a href="http://ackstorm.de#cb2-11" aria-hidden="true" tabindex="-1"></a>  { <span class="dv">0</span> <span class="fl">1013.25</span> <span class="dv">15</span> }</span>
<span id="cb2-12"><a href="http://ackstorm.de#cb2-12" aria-hidden="true" tabindex="-1"></a>  { <span class="dv">0</span> <span class="fl">1013.25</span> <span class="dv">15</span> }</span>
<span id="cb2-13"><a href="http://ackstorm.de#cb2-13" aria-hidden="true" tabindex="-1"></a>  IF INFORM THEN</span>
<span id="cb2-14"><a href="http://ackstorm.de#cb2-14" aria-hidden="true" tabindex="-1"></a>    OBJ\<span class="op">-&gt;</span> DROP</span>
<span id="cb2-15"><a href="http://ackstorm.de#cb2-15" aria-hidden="true" tabindex="-1"></a>	<span class="dv">3</span> PICK</span>
<span id="cb2-16"><a href="http://ackstorm.de#cb2-16" aria-hidden="true" tabindex="-1"></a>	<span class="dv">3</span> PICK</span>
<span id="cb2-17"><a href="http://ackstorm.de#cb2-17" aria-hidden="true" tabindex="-1"></a>	<span class="dv">3</span> PICK</span>
<span id="cb2-18"><a href="http://ackstorm.de#cb2-18" aria-hidden="true" tabindex="-1"></a>    \<span class="op">-&gt;</span> alt qnh tmp</span>
<span id="cb2-19"><a href="http://ackstorm.de#cb2-19" aria-hidden="true" tabindex="-1"></a>    \<span class="op">&lt;&lt;</span></span>
<span id="cb2-20"><a href="http://ackstorm.de#cb2-20" aria-hidden="true" tabindex="-1"></a>      alt <span class="fl">0.3048</span> <span class="op">*</span></span>
<span id="cb2-21"><a href="http://ackstorm.de#cb2-21" aria-hidden="true" tabindex="-1"></a>      <span class="op">-</span><span class="fl">9.80665</span> <span class="fl">287.05</span> <span class="op">-</span><span class="fl">0.0065</span> <span class="op">*</span> <span class="op">/</span></span>
<span id="cb2-22"><a href="http://ackstorm.de#cb2-22" aria-hidden="true" tabindex="-1"></a>      <span class="dv">1</span> <span class="op">-</span></span>
<span id="cb2-23"><a href="http://ackstorm.de#cb2-23" aria-hidden="true" tabindex="-1"></a>      qnh <span class="dv">100</span> <span class="op">*</span> <span class="fl">287.05</span> <span class="fl">288.15</span> <span class="op">*</span> <span class="op">/</span></span>
<span id="cb2-24"><a href="http://ackstorm.de#cb2-24" aria-hidden="true" tabindex="-1"></a>      \<span class="op">-&gt;</span> h k1 rho0</span>
<span id="cb2-25"><a href="http://ackstorm.de#cb2-25" aria-hidden="true" tabindex="-1"></a>      \<span class="op">&lt;&lt;</span></span>
<span id="cb2-26"><a href="http://ackstorm.de#cb2-26" aria-hidden="true" tabindex="-1"></a>        rho0</span>
<span id="cb2-27"><a href="http://ackstorm.de#cb2-27" aria-hidden="true" tabindex="-1"></a>        <span class="dv">1</span> <span class="op">-</span><span class="fl">0.0065</span> h <span class="op">*</span> <span class="fl">288.15</span> <span class="op">/</span> <span class="op">+</span></span>
<span id="cb2-28"><a href="http://ackstorm.de#cb2-28" aria-hidden="true" tabindex="-1"></a>        k1 <span class="op">^</span></span>
<span id="cb2-29"><a href="http://ackstorm.de#cb2-29" aria-hidden="true" tabindex="-1"></a>        <span class="op">*</span></span>
<span id="cb2-30"><a href="http://ackstorm.de#cb2-30" aria-hidden="true" tabindex="-1"></a>        \<span class="op">-&gt;</span> rho1</span>
<span id="cb2-31"><a href="http://ackstorm.de#cb2-31" aria-hidden="true" tabindex="-1"></a>        \<span class="op">&lt;&lt;</span></span>
<span id="cb2-32"><a href="http://ackstorm.de#cb2-32" aria-hidden="true" tabindex="-1"></a>          <span class="fl">288.15</span> <span class="op">-</span><span class="fl">0.0065</span> h <span class="op">*</span> <span class="op">+</span></span>
<span id="cb2-33"><a href="http://ackstorm.de#cb2-33" aria-hidden="true" tabindex="-1"></a>          <span class="fl">273.15</span> tmp <span class="op">+</span> <span class="op">/</span></span>
<span id="cb2-34"><a href="http://ackstorm.de#cb2-34" aria-hidden="true" tabindex="-1"></a>          rho1 <span class="op">*</span></span>
<span id="cb2-35"><a href="http://ackstorm.de#cb2-35" aria-hidden="true" tabindex="-1"></a>          </span>
<span id="cb2-36"><a href="http://ackstorm.de#cb2-36" aria-hidden="true" tabindex="-1"></a>          <span class="dv">1</span></span>
<span id="cb2-37"><a href="http://ackstorm.de#cb2-37" aria-hidden="true" tabindex="-1"></a>          <span class="fl">9.80665</span> <span class="fl">287.05</span> <span class="op">-</span><span class="fl">0.0065</span> <span class="op">*</span> <span class="op">/</span></span>
<span id="cb2-38"><a href="http://ackstorm.de#cb2-38" aria-hidden="true" tabindex="-1"></a>          <span class="dv">1</span> <span class="op">+</span></span>
<span id="cb2-39"><a href="http://ackstorm.de#cb2-39" aria-hidden="true" tabindex="-1"></a>          <span class="op">/</span></span>
<span id="cb2-40"><a href="http://ackstorm.de#cb2-40" aria-hidden="true" tabindex="-1"></a>    </span>
<span id="cb2-41"><a href="http://ackstorm.de#cb2-41" aria-hidden="true" tabindex="-1"></a>          \<span class="op">-&gt;</span> rho2 k2</span>
<span id="cb2-42"><a href="http://ackstorm.de#cb2-42" aria-hidden="true" tabindex="-1"></a>          \<span class="op">&lt;&lt;</span></span>
<span id="cb2-43"><a href="http://ackstorm.de#cb2-43" aria-hidden="true" tabindex="-1"></a>            <span class="fl">288.15</span></span>
<span id="cb2-44"><a href="http://ackstorm.de#cb2-44" aria-hidden="true" tabindex="-1"></a>            <span class="fl">288.15</span></span>
<span id="cb2-45"><a href="http://ackstorm.de#cb2-45" aria-hidden="true" tabindex="-1"></a>            rho2 <span class="fl">1.225</span> <span class="op">/</span></span>
<span id="cb2-46"><a href="http://ackstorm.de#cb2-46" aria-hidden="true" tabindex="-1"></a>            k2 <span class="op">^</span></span>
<span id="cb2-47"><a href="http://ackstorm.de#cb2-47" aria-hidden="true" tabindex="-1"></a>            <span class="op">*</span></span>
<span id="cb2-48"><a href="http://ackstorm.de#cb2-48" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb2-49"><a href="http://ackstorm.de#cb2-49" aria-hidden="true" tabindex="-1"></a>            <span class="op">-</span></span>
<span id="cb2-50"><a href="http://ackstorm.de#cb2-50" aria-hidden="true" tabindex="-1"></a>            <span class="op">-</span><span class="fl">0.0065</span></span>
<span id="cb2-51"><a href="http://ackstorm.de#cb2-51" aria-hidden="true" tabindex="-1"></a>            rho2 <span class="fl">1.225</span> <span class="op">/</span></span>
<span id="cb2-52"><a href="http://ackstorm.de#cb2-52" aria-hidden="true" tabindex="-1"></a>            k2 <span class="op">^</span></span>
<span id="cb2-53"><a href="http://ackstorm.de#cb2-53" aria-hidden="true" tabindex="-1"></a>            <span class="op">*</span></span>
<span id="cb2-54"><a href="http://ackstorm.de#cb2-54" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb2-55"><a href="http://ackstorm.de#cb2-55" aria-hidden="true" tabindex="-1"></a>            <span class="op">/</span></span>
<span id="cb2-56"><a href="http://ackstorm.de#cb2-56" aria-hidden="true" tabindex="-1"></a>            </span>
<span id="cb2-57"><a href="http://ackstorm.de#cb2-57" aria-hidden="true" tabindex="-1"></a>            <span class="fl">0.3048</span></span>
<span id="cb2-58"><a href="http://ackstorm.de#cb2-58" aria-hidden="true" tabindex="-1"></a>            <span class="op">/</span></span>
<span id="cb2-59"><a href="http://ackstorm.de#cb2-59" aria-hidden="true" tabindex="-1"></a>          \<span class="op">&gt;&gt;</span></span>
<span id="cb2-60"><a href="http://ackstorm.de#cb2-60" aria-hidden="true" tabindex="-1"></a>        \<span class="op">&gt;&gt;</span></span>
<span id="cb2-61"><a href="http://ackstorm.de#cb2-61" aria-hidden="true" tabindex="-1"></a>      \<span class="op">&gt;&gt;</span></span>
<span id="cb2-62"><a href="http://ackstorm.de#cb2-62" aria-hidden="true" tabindex="-1"></a>    \<span class="op">&gt;&gt;</span></span>
<span id="cb2-63"><a href="http://ackstorm.de#cb2-63" aria-hidden="true" tabindex="-1"></a>  END</span>
<span id="cb2-64"><a href="http://ackstorm.de#cb2-64" aria-hidden="true" tabindex="-1"></a>\<span class="op">&gt;&gt;</span></span></code></pre></div>
]]></description>
    <pubDate>Tue, 15 Oct 2019 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/hp48-density-altitude.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Daum Ergo Bike Reverse Engineering Part 1</title>
    <link>http://ackstorm.de/posts/daum-reverse-part-1.html</link>
    <description><![CDATA[<div class="info">
  Posted on October  5, 2018. Tagged as: <a title="All pages tagged 'daum'." href="http://ackstorm.de/tags/daum.html" rel="tag">daum</a>
</div>


<p>I've published initial results from some Daum ergo bike reverse
engineering that I did beginning of 2017. It’s available on my
<a href="http://ackstorm.de/projects/daum/daum.html">daum project page</a>. The page will be
updated whenever I find out more. Current status:</p>
<ul>
<li>Documented EPP training file format and implemented converter from
GPX</li>
<li>PINs for protected menus</li>
<li>Root access via telnet</li>
<li>Cross toolchain for Fedora 28, strace and OpenSSH cross-compiled,
running on the control panel</li>
<li>Cross-compiled kernel module as a preparation for additional device
drivers</li>
</ul>
<p><img src="http://ackstorm.de/projects/daum/daum-boot-screen.png" /></p>
]]></description>
    <pubDate>Fri, 05 Oct 2018 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/daum-reverse-part-1.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Automating Unitymedia Speedtest with Selenium</title>
    <link>http://ackstorm.de/posts/automating-unitymedia-speedtest.html</link>
    <description><![CDATA[<div class="info">
  Posted on February  5, 2018. Tagged as: <a title="All pages tagged 'python'." href="http://ackstorm.de/tags/python.html" rel="tag">python</a>, <a title="All pages tagged 'selenium'." href="http://ackstorm.de/tags/selenium.html" rel="tag">selenium</a>
</div>


<p>My internet connection was slow intermittently, so I needed a way to
automatically collect throughput information several times a day. The
internet service provider (Unitymedia in this case) has a speedtest
page that's pretty useful for that, but it requires manual clicking a
button every time. Not very practical for automated collection.</p>
<p>Turns out with <a href="http://www.seleniumhq.org">Selenium</a> this is pretty
easy to automate. I did use the python API with chrome on Ubuntu
17.10, with following packages:</p>
<ul>
<li>python3-selenium</li>
<li>chromedriver</li>
</ul>
<p>The example code below runs the speedtest, collects the results and
prints them to stdout in a somewhat structured way after the test run.</p>
<p><strong>Update</strong> (2018-02-05): The script collects ping time as well now.</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode python"><code class="sourceCode python"><span id="cb1-1"><a href="http://ackstorm.de#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">#!/usr/bin/env python3</span></span>
<span id="cb1-2"><a href="http://ackstorm.de#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="http://ackstorm.de#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> time</span>
<span id="cb1-4"><a href="http://ackstorm.de#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="im">import</span> sys</span>
<span id="cb1-5"><a href="http://ackstorm.de#cb1-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-6"><a href="http://ackstorm.de#cb1-6" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> selenium <span class="im">import</span> webdriver</span>
<span id="cb1-7"><a href="http://ackstorm.de#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> selenium.webdriver.common.keys <span class="im">import</span> Keys</span>
<span id="cb1-8"><a href="http://ackstorm.de#cb1-8" aria-hidden="true" tabindex="-1"></a><span class="im">from</span> selenium.webdriver.support.ui <span class="im">import</span> WebDriverWait</span>
<span id="cb1-9"><a href="http://ackstorm.de#cb1-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-10"><a href="http://ackstorm.de#cb1-10" aria-hidden="true" tabindex="-1"></a>browser <span class="op">=</span> webdriver.Chrome(executable_path<span class="op">=</span><span class="st">&quot;/usr/lib/chromium-browser/chromedriver&quot;</span>)</span>
<span id="cb1-11"><a href="http://ackstorm.de#cb1-11" aria-hidden="true" tabindex="-1"></a>browser.get(<span class="st">'https://speedtest.unitymedia.de/'</span>)</span>
<span id="cb1-12"><a href="http://ackstorm.de#cb1-12" aria-hidden="true" tabindex="-1"></a>browser.implicitly_wait(<span class="dv">2</span>)</span>
<span id="cb1-13"><a href="http://ackstorm.de#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="http://ackstorm.de#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="cf">assert</span> <span class="st">'Unitymedia'</span> <span class="kw">in</span> browser.title</span>
<span id="cb1-15"><a href="http://ackstorm.de#cb1-15" aria-hidden="true" tabindex="-1"></a>browser.find_element_by_link_text(<span class="st">&quot;Weiter zum Internet Speedtest&quot;</span>).click()</span>
<span id="cb1-16"><a href="http://ackstorm.de#cb1-16" aria-hidden="true" tabindex="-1"></a>browser.find_element_by_id(<span class="st">&quot;icon-unitymedia-cable&quot;</span>).click()</span>
<span id="cb1-17"><a href="http://ackstorm.de#cb1-17" aria-hidden="true" tabindex="-1"></a>browser.find_element_by_class_name(<span class="st">&quot;speedtest-btn--primary&quot;</span>).click()</span>
<span id="cb1-18"><a href="http://ackstorm.de#cb1-18" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-19"><a href="http://ackstorm.de#cb1-19" aria-hidden="true" tabindex="-1"></a>result_link <span class="op">=</span> (WebDriverWait(browser, <span class="dv">60</span>)</span>
<span id="cb1-20"><a href="http://ackstorm.de#cb1-20" aria-hidden="true" tabindex="-1"></a>               .until(<span class="kw">lambda</span> x: x.find_element_by_link_text(<span class="st">&quot;Details &amp; alte Ergebnisse ansehen&quot;</span>)))</span>
<span id="cb1-21"><a href="http://ackstorm.de#cb1-21" aria-hidden="true" tabindex="-1"></a>result_link.click()</span>
<span id="cb1-22"><a href="http://ackstorm.de#cb1-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-23"><a href="http://ackstorm.de#cb1-23" aria-hidden="true" tabindex="-1"></a>browser.find_element_by_class_name(<span class="st">&quot;speedtest-toggle-header&quot;</span>).click()</span>
<span id="cb1-24"><a href="http://ackstorm.de#cb1-24" aria-hidden="true" tabindex="-1"></a>results <span class="op">=</span> browser.find_element_by_class_name(<span class="st">&quot;speedtest-toggle-header&quot;</span>)</span>
<span id="cb1-25"><a href="http://ackstorm.de#cb1-25" aria-hidden="true" tabindex="-1"></a>results_id <span class="op">=</span> results.get_attribute(<span class="st">&quot;data-test-id&quot;</span>)</span>
<span id="cb1-26"><a href="http://ackstorm.de#cb1-26" aria-hidden="true" tabindex="-1"></a>results_day <span class="op">=</span> results.find_element_by_class_name(<span class="st">&quot;day&quot;</span>).text</span>
<span id="cb1-27"><a href="http://ackstorm.de#cb1-27" aria-hidden="true" tabindex="-1"></a>results_time <span class="op">=</span> results.find_element_by_class_name(<span class="st">&quot;time&quot;</span>).text</span>
<span id="cb1-28"><a href="http://ackstorm.de#cb1-28" aria-hidden="true" tabindex="-1"></a>results_download <span class="op">=</span> (results</span>
<span id="cb1-29"><a href="http://ackstorm.de#cb1-29" aria-hidden="true" tabindex="-1"></a>                    .find_element_by_class_name(<span class="st">&quot;download&quot;</span>)</span>
<span id="cb1-30"><a href="http://ackstorm.de#cb1-30" aria-hidden="true" tabindex="-1"></a>                    .find_element_by_class_name(<span class="st">&quot;number&quot;</span>)</span>
<span id="cb1-31"><a href="http://ackstorm.de#cb1-31" aria-hidden="true" tabindex="-1"></a>                    .text)</span>
<span id="cb1-32"><a href="http://ackstorm.de#cb1-32" aria-hidden="true" tabindex="-1"></a>results_upload <span class="op">=</span> (results</span>
<span id="cb1-33"><a href="http://ackstorm.de#cb1-33" aria-hidden="true" tabindex="-1"></a>                  .find_element_by_class_name(<span class="st">&quot;upload&quot;</span>)</span>
<span id="cb1-34"><a href="http://ackstorm.de#cb1-34" aria-hidden="true" tabindex="-1"></a>                  .find_element_by_class_name(<span class="st">&quot;number&quot;</span>)</span>
<span id="cb1-35"><a href="http://ackstorm.de#cb1-35" aria-hidden="true" tabindex="-1"></a>                  .text)</span>
<span id="cb1-36"><a href="http://ackstorm.de#cb1-36" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-37"><a href="http://ackstorm.de#cb1-37" aria-hidden="true" tabindex="-1"></a>result_details <span class="op">=</span> browser.find_element_by_class_name(<span class="st">&quot;speedtest-toggle-wrapper&quot;</span>)</span>
<span id="cb1-38"><a href="http://ackstorm.de#cb1-38" aria-hidden="true" tabindex="-1"></a>result_ping <span class="op">=</span> (result_details</span>
<span id="cb1-39"><a href="http://ackstorm.de#cb1-39" aria-hidden="true" tabindex="-1"></a>               .find_element_by_class_name(<span class="st">&quot;ping-result&quot;</span>)</span>
<span id="cb1-40"><a href="http://ackstorm.de#cb1-40" aria-hidden="true" tabindex="-1"></a>               .find_element_by_class_name(<span class="st">&quot;speed&quot;</span>)</span>
<span id="cb1-41"><a href="http://ackstorm.de#cb1-41" aria-hidden="true" tabindex="-1"></a>               .find_element_by_class_name(<span class="st">&quot;number0&quot;</span>)</span>
<span id="cb1-42"><a href="http://ackstorm.de#cb1-42" aria-hidden="true" tabindex="-1"></a>               .text)</span>
<span id="cb1-43"><a href="http://ackstorm.de#cb1-43" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-44"><a href="http://ackstorm.de#cb1-44" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">&quot;</span><span class="sc">{}</span><span class="st">;</span><span class="ch">\t</span><span class="sc">{}</span><span class="st">;</span><span class="ch">\t</span><span class="sc">{}</span><span class="st">;</span><span class="ch">\t</span><span class="sc">{}</span><span class="st">;</span><span class="ch">\t</span><span class="sc">{}</span><span class="st">;</span><span class="ch">\t</span><span class="sc">{}</span><span class="st">;&quot;</span></span>
<span id="cb1-45"><a href="http://ackstorm.de#cb1-45" aria-hidden="true" tabindex="-1"></a>      .<span class="bu">format</span>(results_day, results_time, results_download,</span>
<span id="cb1-46"><a href="http://ackstorm.de#cb1-46" aria-hidden="true" tabindex="-1"></a>              results_upload, result_ping, results_id))</span>
<span id="cb1-47"><a href="http://ackstorm.de#cb1-47" aria-hidden="true" tabindex="-1"></a>browser.quit()</span></code></pre></div>
]]></description>
    <pubDate>Mon, 05 Feb 2018 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/automating-unitymedia-speedtest.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Altitude Module for eZ430-Chronos</title>
    <link>http://ackstorm.de/posts/ez430-chronos-altitude-altitude.html</link>
    <description><![CDATA[<div class="info">
  Posted on December  7, 2017. Tagged as: <a title="All pages tagged 'eZ430-Chronos'." href="http://ackstorm.de/tags/eZ430-Chronos.html" rel="tag">eZ430-Chronos</a>
</div>


<p>Here is a little writeup of the steps taken to implement an altitude
module
<a href="http://processors.wiki.ti.com/index.php/EZ430-Chronos">eZ430-Chronos</a>
within
<a href="https://github.com/BenjaminSoelberg/openchronos-ng-elf">openchronos-ng-elf</a>. The
challenge is that the MSP430 controller is a 16bit RISC controller,
which has no floating point and no builtin multiply/divide
instructions. In addition, the code size is limited to 32K</p>
<p>The TI eZ430-Chronos contains a pressure sensor. To calculate the
altitude from current pressure according to International Standard
Atmosphere (ISA) we can derive the following equations:</p>
<p><img src="http://ackstorm.de/images/alt-eq1.png" class="equation" /></p>
<p>A number of input values are constant:</p>
<p><img src="http://ackstorm.de/images/alt-eq2.png" class="equation" /></p>
<p>Putting the constants into the ISA formula, we get:</p>
<p><img src="http://ackstorm.de/images/alt-eq3.png" class="equation" /></p>
<p>As reference this uses <span class="math inline"><em>p</em><sub>0</sub></span>, the current pressure reduced to mean sea
level using the International Standard Atmosphere. In aviation that’s
called QNH and can be
<a href="https://aviationweather.gov/metar/">looked up online for the closest airport</a>.</p>
<h2 id="straigt-forward-implementation-using-libm">Straigt-forward Implementation Using libm</h2>
<p>Implementing the altitude function using pow() from libm, large chunks
of libm get linked, resulting in a code size of about 16.8K. That is a
lot, considering the controller in the eZ430-Chronos has only 32K of
flash memory. So a better implementation is needed.</p>
<h2 id="implementing-xy-with-binomial-series">Implementing <span class="math inline"><em>x</em><sup><em>y</em></sup></span> with Binomial Series</h2>
<p>Next idea was to replace the exponentiation part of the formula with a
binomial series, which doesn’t require to link libm anymore. That
leaves only multiplications and additions after pre-computing the
constants:</p>
<p><img src="http://ackstorm.de/images/alt-eq4.png" class="equation" /></p>
<p>For low altitudes (p ~ QNH, x ~ 1) the series converges pretty
quickly. As termination criterium for the series the step size seems
to work ok. The resulting altitude module code size is reduced to
about 8K.</p>
<h2 id="lookup-table-with-interpolation">Lookup Table with Interpolation</h2>
<p>The next optimization step was to use a lookup table with
interpolation. This allows to avoid floating point math entirely. The
function to replace with a lookup table looks like this:</p>
<figure>
<img src="http://ackstorm.de/images/alt-plot.png" alt="Altitude Plot, p0 = QNH, p1 = current pressure, z = altitude" />
<figcaption aria-hidden="true">Altitude Plot, p0 = QNH, p1 = current pressure, z = altitude</figcaption>
</figure>
<p>The lookup table has been generated with a ruby script, that also
determines the maximum error in a brute force way by feeding all
possible input values into the lookup table and comparing with the
exact altitude.</p>
<p>To get an error of max 5 ft with a QNH between 900 and 1100 and a
pressure between 500 hPa and 1100 hPA a table size of 1342 bytes is
sufficient. Since the lookup table generator places nodes directly
onto the exact function values, we could optimize a bit by moving the
points slightly off the exact value to minimize the error squares.</p>
<p>The resulting code including lookup table is reduced to about 3.6K.
The code can be found on <a href="https://github.com/ra1fh/openchronos-ng-elf">GitHub</a>.</p>
<h2 id="results">Results</h2>
<p>The following table compares code size of various alternatives with
the firmware without altitude module compiled in (baseline).</p>
<pre><code>---------------------------------------------------
Module            rodata    text     sum   relative
---------------  -------  ------  ------  ---------
baseline             356   13056   13412          0
lookup table        1738   15399   17137       3725
binomial series      716   20918   21634       8222
libm                 722   29894   30616      17204
---------------  -------  ------  ------  ---------</code></pre>
]]></description>
    <pubDate>Thu, 07 Dec 2017 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/ez430-chronos-altitude-altitude.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>UEFI Dual Boot with Fedora and OpenBSD on ThinkPad X230</title>
    <link>http://ackstorm.de/posts/uefi-openbsd-fedora-dual-boot.html</link>
    <description><![CDATA[<div class="info">
  Posted on October 19, 2016. Tagged as: <a title="All pages tagged 'openbsd'." href="http://ackstorm.de/tags/openbsd.html" rel="tag">openbsd</a>, <a title="All pages tagged 'fedora'." href="http://ackstorm.de/tags/fedora.html" rel="tag">fedora</a>, <a title="All pages tagged 'uefi'." href="http://ackstorm.de/tags/uefi.html" rel="tag">uefi</a>, <a title="All pages tagged 'thinkpad'." href="http://ackstorm.de/tags/thinkpad.html" rel="tag">thinkpad</a>
</div>


<p>After getting a new hard disk for my Lenovo X230 a fresh installation
was required, so I decided to try
<a href="https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface">UEFI</a>
dual boot installation of <a href="https://getfedora.org/">Fedora</a> and
<a href="https://www.openbsd.org/">OpenBSD</a> on a single disk. This guide uses
the builtin BIOS boot manager to not depend on chainloading OpenBSD
via GRUB or an external EFI boot manager like
<a href="http://www.rodsbooks.com/refind/">rEFind</a>.</p>
<h2 id="bios-setup">BIOS Setup</h2>
<p>First of all, enable UEFI Boot in BIOS Setup. Navigate to the the
"Startup" tab and select 'UEFI Only'. CSM Support, which enables
legacy support on top of UEFI is automatically disabled:</p>
<figure>
<img src="http://ackstorm.de/images/bios-uefi-options.png" alt="BIOS UEFI Configuration" />
<figcaption aria-hidden="true">BIOS UEFI Configuration</figcaption>
</figure>
<h2 id="fedora-installation">Fedora Installation</h2>
<p>We start with installing Fedora 24. The installer supports UEFI and
Fedora will even be bootable with UEFI Secure Boot, as it is using
a signed shim loader.</p>
<p>Make sure to select "I will configure partitioning" and do not
assign all of the disk to Fedora. There should be space left at the
end. Fedora will automatically create a FAT formatted EFI system
partition that is required for UEFI boot.</p>
<p>Fedora creates a traditional <a href="https://en.wikipedia.org/wiki/Master_boot_record">Master Boot Record
(MBR)</a> with a single
partition that covers the whole disk to protect from legacy system
seeing the disk as empty. In addition it creates a <a href="https://en.wikipedia.org/wiki/GUID_Partition_Table">GPT partition
table</a> that
contains the actual partitions. After Fedora is installed, the disk
partitions should look like this:</p>
<figure>
<img src="http://ackstorm.de/images/partition-1.png" alt="Partition After Fedora Installation" />
<figcaption aria-hidden="true">Partition After Fedora Installation</figcaption>
</figure>
<p>Fedora uses <a href="https://github.com/rhinstaller/efibootmgr">efibootmgr</a> to
add a new boot option to the BIOS boot manager. That means there will
be an entry "Fedora" in the boot device list in BIOS setup and in
the boot menu that is reachable with F12 during boot. We will use
efibootmgr later on to create a similar entry for OpenBSD.</p>
<h2 id="openbsd-installation">OpenBSD Installation</h2>
<p>I have used the latest released OpenBSD version 6.0 for this guide,
UEFI is supported since <a href="https://www.openbsd.org/59.html">version 5.9</a>
there is support for UEFI boot. Depending on the installation medium
you might need to temporarily enable legacy boot in BIOS setup for the
installation process (for example for booting from CD-ROM or PXE).</p>
<p>Having successfully booted the installer and after selecting the
installation disk, you will be presented with the following options:</p>
<pre class="sourceCode"><code>Use (W)hole disk MBR, whole disk (G)PT or (E)dit? [whole] e</code></pre>
<p>Make sure to select (E)dit. Otherwise the installer will directly wipe
your GPT partition table and you have to start over. After selecting
(E) you get a little text what the installer expects from you:</p>
<pre class="sourceCode"><code>You will now create two GPT partitions. The first must have an id
of 'EF' and be large enough to contain the OpenBSD boot programs,
at least 960 blocks. The second must have an id of 'A6' and will
contain your OpenBSD data. Neither may overlap other partitions.
Inside the fdisk command, the 'manual' command describes the fdisk
commands in detail.</code></pre>
<p>Fedora created the EFI system partition with id 'EF' already, so the
only thing left is to create the OpenBSD partition with id 'A6'. At
the fdisk prompt, first print the partition partition table that was created by Fedora:</p>
<pre class="sourceCode"><code>Disk: sd0       Usable LBA: 34 to 937703054 [937703088 Sectors]
GUID: 1876166f-3413-44c9-8b7e-9e559bccb79f
   #: type                                 [       start:         size ]
      guid                                 name
------------------------------------------------------------------------
   0: EFI Sys                              [        2048:      1024000 ]
      c1a42d93-a363-4104-ab7e-050d48291df7 EFI System Partition
   1: Linux files*                         [     1026048:      1024000 ]
      d42b1596-d3cd-403f-8f6a-a191fa70f815
   2: Linux files*                         [     2050048:    325083136 ]
      82e12efd-b0eb-4962-9e55-7a18c759611e</code></pre>
<p>The next free partition would be 3, so type type 'e 3' and enter the
parameters for the new GPT partition. The tricky part is to calculate
the start offset of the new partition and type it correctly, as the
default was 34 in my case (if I remember correctly). The start offset
of partition 3 should be start + size of the previous partition 2,
2050048 + 325083136 = 327133184 in my case. The default for the size
is good again, as we want to use all the remaining space for
OpenBSD. The finished GPT partition table looks like this:</p>
<pre class="sourceCode"><code>Disk: sd0       Usable LBA: 34 to 937703054 [937703088 Sectors]
GUID: 1876166f-3413-44c9-8b7e-9e559bccb79f
   #: type                                 [       start:         size ]
      guid                                 name
------------------------------------------------------------------------
   0: EFI Sys                              [        2048:      1024000 ]
      c1a42d93-a363-4104-ab7e-050d48291df7 EFI System Partition
   1: Linux files*                         [     1026048:      1024000 ]
      d42b1596-d3cd-403f-8f6a-a191fa70f815
   2: Linux files*                         [     2050048:    325083136 ]
      82e12efd-b0eb-4962-9e55-7a18c759611e
   3: OpenBSD                              [   327133184:    610569871 ]
      c9377bdd-3b14-4002-8a22-c1dcd9595d2f</code></pre>
<p>After writing the partition table ('write') and exiting fdisk
('quit'), follow the standard OpenBSD installation process. In my
case I enabled full disk encryption for the OpenBSD part, so I had to
follow <a href="https://www.openbsd.org/faq/faq14.html#softraidFDE">some extra
steps</a>.</p>
<p>After finishing the installation remember to enable UEFI boot again in
case you needed to disable for booting the installer. When booting,
select the disk device as boot device. The UEFI BIOS will try to boot
from the default path within the EFI system partition, which is
'EFI\BOOT\BOOTX64.EFI'. OpenBSD did place its UEFI bootloader
there during installation:</p>
<pre class="sourceCode"><code>[EFI System Partition]
`-- EFI
    `-- BOOT
        |-- BOOTX64.EFI
        `-- BOOTIA32.EFI</code></pre>
<p>There will be no dedicated boot entry created in the UEFI BIOS boot
device list. See the next section on how to use efibootmgr on Fedora
to create a Boot menu entry for OpenBSD.</p>
<h2 id="create-a-bios-boot-manager-entry-for-openbsd">Create a BIOS Boot Manager Entry for OpenBSD</h2>
<p>First of all, mount the EFI partition in either OpenBSD or Fedora and
create a subdirectory for OpenBSD and copy 'EFI\BOOT\BOOTX64.EFI'
into that directory:</p>
<pre class="sourceCode"><code>[EFI System Partition]
`-- EFI
    |-- BOOT
    |   |-- BOOTX64.EFI
    |   `-- BOOTIA32.EFI
    |-- FEDORA
    |   |-- BOOT.CSV
    |   :
    |   
    `-- OPENBSD
        `-- BOOTX64.EFI</code></pre>
<p>Boot into Fedora and run the following command:</p>
<pre class="sourceCode"><code>sudo efibootmgr --create \
	--disk /dev/sda \
	--part 1 \
	--label 'OpenBSD' \
	--loader '\EFI\OPENBSD\BOOTX64.EFI'</code></pre>
<p>On next boot, the UEFI BIOS boot manager should show a new boot
option:</p>
<figure>
<img src="http://ackstorm.de/images/bios-boot-manager.png" alt="UEFI BIOS Boot Manager" />
<figcaption aria-hidden="true">UEFI BIOS Boot Manager</figcaption>
</figure>
<p>Be aware that OpenBSD will install new versions of BOOTX64.EFI into
the default path 'EFI\BOOT\BOOTX64.EFI' on upgrade. So you have to
remember to update the copy that is referenced in the boot
menu. Fedora created 'EFI\BOOT\BOOTX64.EFI' as well and might
overwrite on update, therefore I believe creating a copy in
subdirectory for OpenBSD is best to prevent it from becoming
non-bootable.</p>
]]></description>
    <pubDate>Wed, 19 Oct 2016 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/uefi-openbsd-fedora-dual-boot.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Geogrid-Viewer Version 2, 3 and 4 binary overlay file format</title>
    <link>http://ackstorm.de/posts/geogrid-viewer-file-format.html</link>
    <description><![CDATA[<div class="info">
  Posted on January 12, 2016. Tagged as: <a title="All pages tagged 'gps'." href="http://ackstorm.de/tags/gps.html" rel="tag">gps</a>
</div>


<p>Within the last couple of days I made some progress with decoding the
Geogrid-Viewer OVL binary file format. Geogrid-Viewer is part of
various <a href="https://de.wikipedia.org/wiki/Top50">Top50</a> map products
available in Germany and Austria. The most recent Top50 versions use
file format version 5.0, which consists of ZIP compressed XML files
and likely very easy to convert. But there are still a lot of older
OVL files up to version 4.0 available on the internet. My main
motivation were
<a href="http://web.archive.org/web/20161022075023/http://39x26.de/touren/index.html">these version 2.0 files</a>,
that I wanted to convert into GPX.</p>
<p>To get more information about the OVL file format, it helped to
observe Geogrid-Viewer with
<a href="https://technet.microsoft.com/de-de/sysinternals/bb896645.aspx">Procmon</a>
while reading OVL files. Fortunately the OVL files are read in pieces,
which provides valuable information about the file structure. For
tricky bits <a href="http://www.ollydbg.de/">OllyDbg</a> was helpful as well.</p>
<p>With the following file format "specifications" (there are still a
lot of unknowns in there) I've improved the
<a href="http://ackstorm.de/posts/gpsbabel-ovl.html">gpsbabel importer I wrote a year ago</a>. I
can now successfully parse all of the 153 random binary OVL samples I
found on the internet. The patch will be provided to gpsbabel soon.</p>
<p><strong>Update</strong> (2016-01-13): Corrected type1/type2 decoding in V3.0/V4.0</p>
<p><strong>Update</strong> (2016-01-16): Patch has been merged into <a href="https://github.com/gpsbabel/gpsbabel">gpsbabel git</a></p>
<p><strong>Update</strong> (2019-07-12): “Radtouren rund um Paderborn” has disappeared, link to <a href="http://web.archive.org/web/20161022075023/http://39x26.de/touren/index.html">web.archive.org</a> instead.</p>
<p><strong>Update</strong> (2020-01-08): Corrected subtype decoding in V2.0, add missing padding after magic bytes in V3.0 and V4.0</p>
<h2 id="version-2.0">Version 2.0</h2>
<p>Here is a pseudo C code like structure definition of version 2.0 OVL
files. Those files can be identified by looking at the first 23 bytes
of the file, which contain the string "DOMGVCRD Ovlfile V2.0".</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb1-1"><a href="http://ackstorm.de#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// Geogrid-Viewer OVL binary file format version 2.0</span></span>
<span id="cb1-2"><a href="http://ackstorm.de#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-3"><a href="http://ackstorm.de#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="dt">FILE</span> <span class="op">{</span></span>
<span id="cb1-4"><a href="http://ackstorm.de#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> HEADER <span class="op">{</span></span>
<span id="cb1-5"><a href="http://ackstorm.de#cb1-5" aria-hidden="true" tabindex="-1"></a>    <span class="dt">char</span> magic<span class="op">[</span><span class="dv">23</span><span class="op">];</span>    <span class="co">// &quot;DOMGVCRD Ovlfile V2.0:\0&quot;</span></span>
<span id="cb1-6"><a href="http://ackstorm.de#cb1-6" aria-hidden="true" tabindex="-1"></a>    uint16 header_len<span class="op">;</span> <span class="co">// usually 0x90 or 0x00</span></span>
<span id="cb1-7"><a href="http://ackstorm.de#cb1-7" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>header_len <span class="op">&gt;</span> <span class="dv">4</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-8"><a href="http://ackstorm.de#cb1-8" aria-hidden="true" tabindex="-1"></a>      uint16 i1<span class="op">;</span></span>
<span id="cb1-9"><a href="http://ackstorm.de#cb1-9" aria-hidden="true" tabindex="-1"></a>      uint16 i2<span class="op">;</span></span>
<span id="cb1-10"><a href="http://ackstorm.de#cb1-10" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> map_name<span class="op">[</span>header_len <span class="op">-</span> <span class="dv">4</span><span class="op">];</span></span>
<span id="cb1-11"><a href="http://ackstorm.de#cb1-11" aria-hidden="true" tabindex="-1"></a>      <span class="co">// the map_name field contains more information</span></span>
<span id="cb1-12"><a href="http://ackstorm.de#cb1-12" aria-hidden="true" tabindex="-1"></a>      <span class="co">// then just the null-terminated name, but details</span></span>
<span id="cb1-13"><a href="http://ackstorm.de#cb1-13" aria-hidden="true" tabindex="-1"></a>      <span class="co">// are unknown</span></span>
<span id="cb1-14"><a href="http://ackstorm.de#cb1-14" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-15"><a href="http://ackstorm.de#cb1-15" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-16"><a href="http://ackstorm.de#cb1-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> RECORD<span class="op">[]</span> <span class="op">{</span></span>
<span id="cb1-17"><a href="http://ackstorm.de#cb1-17" aria-hidden="true" tabindex="-1"></a>    uint16 entry_type<span class="op">;</span></span>
<span id="cb1-18"><a href="http://ackstorm.de#cb1-18" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x02: text</span></span>
<span id="cb1-19"><a href="http://ackstorm.de#cb1-19" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x03: line</span></span>
<span id="cb1-20"><a href="http://ackstorm.de#cb1-20" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x04: area</span></span>
<span id="cb1-21"><a href="http://ackstorm.de#cb1-21" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x05: rectangle</span></span>
<span id="cb1-22"><a href="http://ackstorm.de#cb1-22" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x06: circle</span></span>
<span id="cb1-23"><a href="http://ackstorm.de#cb1-23" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x07: triangle</span></span>
<span id="cb1-24"><a href="http://ackstorm.de#cb1-24" aria-hidden="true" tabindex="-1"></a>    <span class="co">// 0x09: bitmap</span></span>
<span id="cb1-25"><a href="http://ackstorm.de#cb1-25" aria-hidden="true" tabindex="-1"></a>    uint16 entry_group<span class="op">;</span></span>
<span id="cb1-26"><a href="http://ackstorm.de#cb1-26" aria-hidden="true" tabindex="-1"></a>    uint16 entry_zoom<span class="op">;</span></span>
<span id="cb1-27"><a href="http://ackstorm.de#cb1-27" aria-hidden="true" tabindex="-1"></a>    uint16 entry_subtype<span class="op">;</span></span>
<span id="cb1-28"><a href="http://ackstorm.de#cb1-28" aria-hidden="true" tabindex="-1"></a>    <span class="cf">if</span> <span class="op">(</span>subtype <span class="op">!=</span> <span class="bn">0x01</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-29"><a href="http://ackstorm.de#cb1-29" aria-hidden="true" tabindex="-1"></a>      uint32 text_len<span class="op">;</span></span>
<span id="cb1-30"><a href="http://ackstorm.de#cb1-30" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> text<span class="op">[</span>text_len<span class="op">];</span></span>
<span id="cb1-31"><a href="http://ackstorm.de#cb1-31" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-32"><a href="http://ackstorm.de#cb1-32" aria-hidden="true" tabindex="-1"></a>    <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb1-33"><a href="http://ackstorm.de#cb1-33" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> TEXT <span class="op">{</span></span>
<span id="cb1-34"><a href="http://ackstorm.de#cb1-34" aria-hidden="true" tabindex="-1"></a>        uint16 color<span class="op">;</span></span>
<span id="cb1-35"><a href="http://ackstorm.de#cb1-35" aria-hidden="true" tabindex="-1"></a>        uint16 size<span class="op">;</span></span>
<span id="cb1-36"><a href="http://ackstorm.de#cb1-36" aria-hidden="true" tabindex="-1"></a>        uint16 trans<span class="op">;</span></span>
<span id="cb1-37"><a href="http://ackstorm.de#cb1-37" aria-hidden="true" tabindex="-1"></a>        uint16 font<span class="op">;</span></span>
<span id="cb1-38"><a href="http://ackstorm.de#cb1-38" aria-hidden="true" tabindex="-1"></a>        uint16 angle<span class="op">;</span></span>
<span id="cb1-39"><a href="http://ackstorm.de#cb1-39" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb1-40"><a href="http://ackstorm.de#cb1-40" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> last<span class="op">;</span></span>
<span id="cb1-41"><a href="http://ackstorm.de#cb1-41" aria-hidden="true" tabindex="-1"></a>        uint16 text_len<span class="op">;</span></span>
<span id="cb1-42"><a href="http://ackstorm.de#cb1-42" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> text<span class="op">[</span>text_len<span class="op">];</span></span>
<span id="cb1-43"><a href="http://ackstorm.de#cb1-43" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb1-44"><a href="http://ackstorm.de#cb1-44" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> LINE_AREA <span class="op">{</span></span>
<span id="cb1-45"><a href="http://ackstorm.de#cb1-45" aria-hidden="true" tabindex="-1"></a>        uint16 color<span class="op">;</span></span>
<span id="cb1-46"><a href="http://ackstorm.de#cb1-46" aria-hidden="true" tabindex="-1"></a>        uint16 width<span class="op">;</span></span>
<span id="cb1-47"><a href="http://ackstorm.de#cb1-47" aria-hidden="true" tabindex="-1"></a>        uint16 type<span class="op">;</span></span>
<span id="cb1-48"><a href="http://ackstorm.de#cb1-48" aria-hidden="true" tabindex="-1"></a>        uint16 point_count<span class="op">;</span></span>
<span id="cb1-49"><a href="http://ackstorm.de#cb1-49" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> POINT <span class="op">{</span></span>
<span id="cb1-50"><a href="http://ackstorm.de#cb1-50" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lon<span class="op">;</span> </span>
<span id="cb1-51"><a href="http://ackstorm.de#cb1-51" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb1-52"><a href="http://ackstorm.de#cb1-52" aria-hidden="true" tabindex="-1"></a>        <span class="op">}[</span>point_count<span class="op">];</span></span>
<span id="cb1-53"><a href="http://ackstorm.de#cb1-53" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb1-54"><a href="http://ackstorm.de#cb1-54" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> RECT_CIRC_TRI <span class="op">{</span></span>
<span id="cb1-55"><a href="http://ackstorm.de#cb1-55" aria-hidden="true" tabindex="-1"></a>        uint16 color<span class="op">;</span></span>
<span id="cb1-56"><a href="http://ackstorm.de#cb1-56" aria-hidden="true" tabindex="-1"></a>        uint16 prop1<span class="op">;</span></span>
<span id="cb1-57"><a href="http://ackstorm.de#cb1-57" aria-hidden="true" tabindex="-1"></a>        uint16 prop2<span class="op">;</span></span>
<span id="cb1-58"><a href="http://ackstorm.de#cb1-58" aria-hidden="true" tabindex="-1"></a>        uint16 angle<span class="op">;</span></span>
<span id="cb1-59"><a href="http://ackstorm.de#cb1-59" aria-hidden="true" tabindex="-1"></a>        uint16 stroke<span class="op">;</span></span>
<span id="cb1-60"><a href="http://ackstorm.de#cb1-60" aria-hidden="true" tabindex="-1"></a>        uint16 area<span class="op">;</span></span>
<span id="cb1-61"><a href="http://ackstorm.de#cb1-61" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb1-62"><a href="http://ackstorm.de#cb1-62" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb1-63"><a href="http://ackstorm.de#cb1-63" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb1-64"><a href="http://ackstorm.de#cb1-64" aria-hidden="true" tabindex="-1"></a>      <span class="kw">struct</span> BITMAP <span class="op">{</span></span>
<span id="cb1-65"><a href="http://ackstorm.de#cb1-65" aria-hidden="true" tabindex="-1"></a>        uint16 color<span class="op">;</span></span>
<span id="cb1-66"><a href="http://ackstorm.de#cb1-66" aria-hidden="true" tabindex="-1"></a>        uint16 prop1<span class="op">;</span></span>
<span id="cb1-67"><a href="http://ackstorm.de#cb1-67" aria-hidden="true" tabindex="-1"></a>        uint16 prop2<span class="op">;</span></span>
<span id="cb1-68"><a href="http://ackstorm.de#cb1-68" aria-hidden="true" tabindex="-1"></a>        uint16 prop3<span class="op">;</span></span>
<span id="cb1-69"><a href="http://ackstorm.de#cb1-69" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb1-70"><a href="http://ackstorm.de#cb1-70" aria-hidden="true" tabindex="-1"></a>        <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb1-71"><a href="http://ackstorm.de#cb1-71" aria-hidden="true" tabindex="-1"></a>        uint32 data_len<span class="op">;</span></span>
<span id="cb1-72"><a href="http://ackstorm.de#cb1-72" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> data<span class="op">[</span>data_len<span class="op">];</span></span>
<span id="cb1-73"><a href="http://ackstorm.de#cb1-73" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb1-74"><a href="http://ackstorm.de#cb1-74" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb1-75"><a href="http://ackstorm.de#cb1-75" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb1-76"><a href="http://ackstorm.de#cb1-76" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<h2 id="version-3.0-and-4.0">Version 3.0 and 4.0</h2>
<p>Version 3.0 and 4.0 are a bit different as they allow multiple parts
in one file that all start with the magic bytes "DOMGVCRD Ovlfile
V3.0" or "DOMGVCRD Ovlfile V4.0". In addition there are two types
of data sections. A "label" section that might contain group
definitions or similar. And a "record" section that contain the
real data, like tracks or other kind of geometric objects.</p>
<p>The header contains the number of "label" and "record" sections
following the header (see label_count and record_count). These might
be zero, which means the part does not contain any label or record
sections. OVL files containing parts without label or record section
or without both do actually exist.</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode c"><code class="sourceCode c"><span id="cb2-1"><a href="http://ackstorm.de#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">struct</span> <span class="dt">FILE</span> <span class="op">{</span></span>
<span id="cb2-2"><a href="http://ackstorm.de#cb2-2" aria-hidden="true" tabindex="-1"></a>  <span class="co">// A version 3.0/4.0 file might contain multiple parts all</span></span>
<span id="cb2-3"><a href="http://ackstorm.de#cb2-3" aria-hidden="true" tabindex="-1"></a>  <span class="co">// starting with DOMGCRD magic bytes and header</span></span>
<span id="cb2-4"><a href="http://ackstorm.de#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="kw">struct</span> PART<span class="op">[]</span> <span class="op">{</span> </span>
<span id="cb2-5"><a href="http://ackstorm.de#cb2-5" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> HEADER <span class="op">{</span></span>
<span id="cb2-6"><a href="http://ackstorm.de#cb2-6" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> magic<span class="op">[</span><span class="dv">23</span><span class="op">];</span> </span>
<span id="cb2-7"><a href="http://ackstorm.de#cb2-7" aria-hidden="true" tabindex="-1"></a>      <span class="co">// either &quot;DOMGVCRD Ovlfile V3.0:\0&quot;</span></span>
<span id="cb2-8"><a href="http://ackstorm.de#cb2-8" aria-hidden="true" tabindex="-1"></a>      <span class="co">//     or &quot;DOMGVCRD Ovlfile V4.0:\0&quot;</span></span>
<span id="cb2-9"><a href="http://ackstorm.de#cb2-9" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> padding<span class="op">[</span><span class="dv">8</span><span class="op">];</span></span>
<span id="cb2-10"><a href="http://ackstorm.de#cb2-10" aria-hidden="true" tabindex="-1"></a>      uint32 label_count<span class="op">;</span></span>
<span id="cb2-11"><a href="http://ackstorm.de#cb2-11" aria-hidden="true" tabindex="-1"></a>      uint32 record_count<span class="op">;</span></span>
<span id="cb2-12"><a href="http://ackstorm.de#cb2-12" aria-hidden="true" tabindex="-1"></a>      uint16 text_len<span class="op">;</span></span>
<span id="cb2-13"><a href="http://ackstorm.de#cb2-13" aria-hidden="true" tabindex="-1"></a>      uint16 text<span class="op">[</span>text_len<span class="op">];</span></span>
<span id="cb2-14"><a href="http://ackstorm.de#cb2-14" aria-hidden="true" tabindex="-1"></a>      uint16 i1<span class="op">;</span></span>
<span id="cb2-15"><a href="http://ackstorm.de#cb2-15" aria-hidden="true" tabindex="-1"></a>      uint16 i2<span class="op">;</span></span>
<span id="cb2-16"><a href="http://ackstorm.de#cb2-16" aria-hidden="true" tabindex="-1"></a>      uint16 i3<span class="op">;</span></span>
<span id="cb2-17"><a href="http://ackstorm.de#cb2-17" aria-hidden="true" tabindex="-1"></a>      uint16 header_len<span class="op">;</span> <span class="co">// usually 0x90 or 0x00</span></span>
<span id="cb2-18"><a href="http://ackstorm.de#cb2-18" aria-hidden="true" tabindex="-1"></a>      uint16 i4<span class="op">;</span></span>
<span id="cb2-19"><a href="http://ackstorm.de#cb2-19" aria-hidden="true" tabindex="-1"></a>      uint16 i5<span class="op">;</span></span>
<span id="cb2-20"><a href="http://ackstorm.de#cb2-20" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>header_len <span class="op">&gt;</span> <span class="dv">4</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-21"><a href="http://ackstorm.de#cb2-21" aria-hidden="true" tabindex="-1"></a>        uint16 i1<span class="op">;</span></span>
<span id="cb2-22"><a href="http://ackstorm.de#cb2-22" aria-hidden="true" tabindex="-1"></a>        uint16 i2<span class="op">;</span></span>
<span id="cb2-23"><a href="http://ackstorm.de#cb2-23" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span>   map_name<span class="op">[</span>header_len <span class="op">-</span> <span class="dv">4</span><span class="op">];</span></span>
<span id="cb2-24"><a href="http://ackstorm.de#cb2-24" aria-hidden="true" tabindex="-1"></a>        <span class="co">// the map_name field contains more information</span></span>
<span id="cb2-25"><a href="http://ackstorm.de#cb2-25" aria-hidden="true" tabindex="-1"></a>        <span class="co">// then just the null-terminated name, but details</span></span>
<span id="cb2-26"><a href="http://ackstorm.de#cb2-26" aria-hidden="true" tabindex="-1"></a>        <span class="co">// are unknown</span></span>
<span id="cb2-27"><a href="http://ackstorm.de#cb2-27" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb2-28"><a href="http://ackstorm.de#cb2-28" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-29"><a href="http://ackstorm.de#cb2-29" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> LABEL<span class="op">[</span>label_count<span class="op">]</span> <span class="op">{</span></span>
<span id="cb2-30"><a href="http://ackstorm.de#cb2-30" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> label_header<span class="op">[</span><span class="dv">8</span><span class="op">];</span></span>
<span id="cb2-31"><a href="http://ackstorm.de#cb2-31" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> label_number<span class="op">[</span><span class="dv">14</span><span class="op">];</span></span>
<span id="cb2-32"><a href="http://ackstorm.de#cb2-32" aria-hidden="true" tabindex="-1"></a>      uint16 label_text_len<span class="op">;</span></span>
<span id="cb2-33"><a href="http://ackstorm.de#cb2-33" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> label_text<span class="op">[</span>label_text_len<span class="op">];</span></span>
<span id="cb2-34"><a href="http://ackstorm.de#cb2-34" aria-hidden="true" tabindex="-1"></a>      uint16 label_flags1<span class="op">;</span></span>
<span id="cb2-35"><a href="http://ackstorm.de#cb2-35" aria-hidden="true" tabindex="-1"></a>      uint16 label_flags2<span class="op">;</span></span>
<span id="cb2-36"><a href="http://ackstorm.de#cb2-36" aria-hidden="true" tabindex="-1"></a>    <span class="op">};</span></span>
<span id="cb2-37"><a href="http://ackstorm.de#cb2-37" aria-hidden="true" tabindex="-1"></a>    <span class="kw">struct</span> RECORD<span class="op">[</span>record_count<span class="op">]</span> <span class="op">{</span></span>
<span id="cb2-38"><a href="http://ackstorm.de#cb2-38" aria-hidden="true" tabindex="-1"></a>      uint16 record_type<span class="op">;</span></span>
<span id="cb2-39"><a href="http://ackstorm.de#cb2-39" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x02: text</span></span>
<span id="cb2-40"><a href="http://ackstorm.de#cb2-40" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x03: line</span></span>
<span id="cb2-41"><a href="http://ackstorm.de#cb2-41" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x04: area</span></span>
<span id="cb2-42"><a href="http://ackstorm.de#cb2-42" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x05: rectangle</span></span>
<span id="cb2-43"><a href="http://ackstorm.de#cb2-43" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x06: circle</span></span>
<span id="cb2-44"><a href="http://ackstorm.de#cb2-44" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x07: triangle</span></span>
<span id="cb2-45"><a href="http://ackstorm.de#cb2-45" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x09: bitmap</span></span>
<span id="cb2-46"><a href="http://ackstorm.de#cb2-46" aria-hidden="true" tabindex="-1"></a>      <span class="co">// 0x17: line</span></span>
<span id="cb2-47"><a href="http://ackstorm.de#cb2-47" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop1<span class="op">;</span></span>
<span id="cb2-48"><a href="http://ackstorm.de#cb2-48" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop2<span class="op">;</span></span>
<span id="cb2-49"><a href="http://ackstorm.de#cb2-49" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop3<span class="op">;</span></span>
<span id="cb2-50"><a href="http://ackstorm.de#cb2-50" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop4<span class="op">;</span></span>
<span id="cb2-51"><a href="http://ackstorm.de#cb2-51" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop5<span class="op">;</span></span>
<span id="cb2-52"><a href="http://ackstorm.de#cb2-52" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop6<span class="op">;</span></span>
<span id="cb2-53"><a href="http://ackstorm.de#cb2-53" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop7<span class="op">;</span></span>
<span id="cb2-54"><a href="http://ackstorm.de#cb2-54" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop8<span class="op">;</span></span>
<span id="cb2-55"><a href="http://ackstorm.de#cb2-55" aria-hidden="true" tabindex="-1"></a>      uint16 record_flags<span class="op">;</span>      <span class="co">// 0x0001=ZOOM, 0x0002=NOZOOM, 0x0800=ROUNDED, 0x10000=CLOSED</span></span>
<span id="cb2-56"><a href="http://ackstorm.de#cb2-56" aria-hidden="true" tabindex="-1"></a>      uint16 record_prop10<span class="op">;</span></span>
<span id="cb2-57"><a href="http://ackstorm.de#cb2-57" aria-hidden="true" tabindex="-1"></a>      uint16 record_text_len<span class="op">;</span></span>
<span id="cb2-58"><a href="http://ackstorm.de#cb2-58" aria-hidden="true" tabindex="-1"></a>      <span class="dt">char</span> record_text<span class="op">[</span>record_text_len<span class="op">];</span></span>
<span id="cb2-59"><a href="http://ackstorm.de#cb2-59" aria-hidden="true" tabindex="-1"></a>      uint16 record_type1<span class="op">;</span></span>
<span id="cb2-60"><a href="http://ackstorm.de#cb2-60" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>record_type1 <span class="op">!=</span> <span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-61"><a href="http://ackstorm.de#cb2-61" aria-hidden="true" tabindex="-1"></a>        uint32 record_object1_len<span class="op">;</span></span>
<span id="cb2-62"><a href="http://ackstorm.de#cb2-62" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> record_object1<span class="op">[</span>record_object1_len<span class="op">];</span></span>
<span id="cb2-63"><a href="http://ackstorm.de#cb2-63" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb2-64"><a href="http://ackstorm.de#cb2-64" aria-hidden="true" tabindex="-1"></a>      uint16 record_type2<span class="op">;</span></span>
<span id="cb2-65"><a href="http://ackstorm.de#cb2-65" aria-hidden="true" tabindex="-1"></a>      <span class="cf">if</span> <span class="op">(</span>record_type2 <span class="op">!=</span> <span class="dv">1</span><span class="op">)</span> <span class="op">{</span></span>
<span id="cb2-66"><a href="http://ackstorm.de#cb2-66" aria-hidden="true" tabindex="-1"></a>        uint32 record_object2_len<span class="op">;</span></span>
<span id="cb2-67"><a href="http://ackstorm.de#cb2-67" aria-hidden="true" tabindex="-1"></a>        <span class="dt">char</span> record_object2<span class="op">[</span>record_object2_len<span class="op">];</span></span>
<span id="cb2-68"><a href="http://ackstorm.de#cb2-68" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb2-69"><a href="http://ackstorm.de#cb2-69" aria-hidden="true" tabindex="-1"></a>      <span class="kw">union</span> <span class="op">{</span></span>
<span id="cb2-70"><a href="http://ackstorm.de#cb2-70" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> TEXT <span class="op">{</span></span>
<span id="cb2-71"><a href="http://ackstorm.de#cb2-71" aria-hidden="true" tabindex="-1"></a>          uint16 text_prop1<span class="op">;</span></span>
<span id="cb2-72"><a href="http://ackstorm.de#cb2-72" aria-hidden="true" tabindex="-1"></a>          uint32 text_prop2<span class="op">;</span></span>
<span id="cb2-73"><a href="http://ackstorm.de#cb2-73" aria-hidden="true" tabindex="-1"></a>          uint16 text_prop3<span class="op">;</span></span>
<span id="cb2-74"><a href="http://ackstorm.de#cb2-74" aria-hidden="true" tabindex="-1"></a>          uint32 text_color<span class="op">;</span>    <span class="co">// 0x80bbggrr</span></span>
<span id="cb2-75"><a href="http://ackstorm.de#cb2-75" aria-hidden="true" tabindex="-1"></a>          uint16 text_size<span class="op">;</span>     <span class="co">// 100-1100</span></span>
<span id="cb2-76"><a href="http://ackstorm.de#cb2-76" aria-hidden="true" tabindex="-1"></a>          uint16 text_back<span class="op">;</span>     <span class="co">// 1=transparent, 2=solid, 3-8=various patterns</span></span>
<span id="cb2-77"><a href="http://ackstorm.de#cb2-77" aria-hidden="true" tabindex="-1"></a>          uint16 text_font<span class="op">;</span>     <span class="co">// 1=Arial, 3=Courier, 4=Times, 10=Comic</span></span>
<span id="cb2-78"><a href="http://ackstorm.de#cb2-78" aria-hidden="true" tabindex="-1"></a>          uint16 text_angle<span class="op">;</span>    <span class="co">// 100-460</span></span>
<span id="cb2-79"><a href="http://ackstorm.de#cb2-79" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb2-80"><a href="http://ackstorm.de#cb2-80" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb2-81"><a href="http://ackstorm.de#cb2-81" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> unkown<span class="op">;</span></span>
<span id="cb2-82"><a href="http://ackstorm.de#cb2-82" aria-hidden="true" tabindex="-1"></a>          uint16 text_label_len<span class="op">;</span></span>
<span id="cb2-83"><a href="http://ackstorm.de#cb2-83" aria-hidden="true" tabindex="-1"></a>          <span class="dt">char</span> <span class="op">[</span>text_label_len<span class="op">];</span></span>
<span id="cb2-84"><a href="http://ackstorm.de#cb2-84" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-85"><a href="http://ackstorm.de#cb2-85" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> AREA_LINE <span class="op">{</span></span>
<span id="cb2-86"><a href="http://ackstorm.de#cb2-86" aria-hidden="true" tabindex="-1"></a>          uint16 line_prop1<span class="op">;</span></span>
<span id="cb2-87"><a href="http://ackstorm.de#cb2-87" aria-hidden="true" tabindex="-1"></a>          uint32 line_prop2<span class="op">;</span></span>
<span id="cb2-88"><a href="http://ackstorm.de#cb2-88" aria-hidden="true" tabindex="-1"></a>          uint16 line_prop3<span class="op">;</span>    <span class="co">// 0x1e</span></span>
<span id="cb2-89"><a href="http://ackstorm.de#cb2-89" aria-hidden="true" tabindex="-1"></a>          uint32 line_color<span class="op">;</span>    <span class="co">// 0x80bbggrr</span></span>
<span id="cb2-90"><a href="http://ackstorm.de#cb2-90" aria-hidden="true" tabindex="-1"></a>          uint16 line_width<span class="op">;</span>    <span class="co">// 101-115</span></span>
<span id="cb2-91"><a href="http://ackstorm.de#cb2-91" aria-hidden="true" tabindex="-1"></a>          uint16 line_back<span class="op">;</span>     <span class="co">// 1=transparent, 2=solid, 3-8=various patterns</span></span>
<span id="cb2-92"><a href="http://ackstorm.de#cb2-92" aria-hidden="true" tabindex="-1"></a>          uint16 line_count<span class="op">;</span></span>
<span id="cb2-93"><a href="http://ackstorm.de#cb2-93" aria-hidden="true" tabindex="-1"></a>          <span class="cf">if</span> <span class="op">(</span>record_type <span class="op">==</span> <span class="bn">0x04</span><span class="op">)</span></span>
<span id="cb2-94"><a href="http://ackstorm.de#cb2-94" aria-hidden="true" tabindex="-1"></a>            uint16 line_stroke<span class="op">;</span> <span class="co">// 1=solid, 2=dashed, 3=dotted, 4=dot-dash</span></span>
<span id="cb2-95"><a href="http://ackstorm.de#cb2-95" aria-hidden="true" tabindex="-1"></a>          <span class="op">}</span></span>
<span id="cb2-96"><a href="http://ackstorm.de#cb2-96" aria-hidden="true" tabindex="-1"></a>          <span class="kw">struct</span> COORD<span class="op">[</span>line_count<span class="op">]</span> <span class="op">{</span></span>
<span id="cb2-97"><a href="http://ackstorm.de#cb2-97" aria-hidden="true" tabindex="-1"></a>            <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb2-98"><a href="http://ackstorm.de#cb2-98" aria-hidden="true" tabindex="-1"></a>            <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb2-99"><a href="http://ackstorm.de#cb2-99" aria-hidden="true" tabindex="-1"></a>            <span class="dt">double</span> unkown<span class="op">;</span></span>
<span id="cb2-100"><a href="http://ackstorm.de#cb2-100" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-101"><a href="http://ackstorm.de#cb2-101" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> RECT_CIRC_TRI <span class="op">{</span></span>
<span id="cb2-102"><a href="http://ackstorm.de#cb2-102" aria-hidden="true" tabindex="-1"></a>          uint16 rct_prop1<span class="op">;</span></span>
<span id="cb2-103"><a href="http://ackstorm.de#cb2-103" aria-hidden="true" tabindex="-1"></a>          uint32 rct_prop2<span class="op">;</span></span>
<span id="cb2-104"><a href="http://ackstorm.de#cb2-104" aria-hidden="true" tabindex="-1"></a>          uint16 rct_prop3<span class="op">;</span>     <span class="co">// 0x1e</span></span>
<span id="cb2-105"><a href="http://ackstorm.de#cb2-105" aria-hidden="true" tabindex="-1"></a>          uint32 rct_color<span class="op">;</span>     <span class="co">// 0x80bbggrr</span></span>
<span id="cb2-106"><a href="http://ackstorm.de#cb2-106" aria-hidden="true" tabindex="-1"></a>          uint32 rct_width<span class="op">;</span></span>
<span id="cb2-107"><a href="http://ackstorm.de#cb2-107" aria-hidden="true" tabindex="-1"></a>          uint32 rct_height<span class="op">;</span></span>
<span id="cb2-108"><a href="http://ackstorm.de#cb2-108" aria-hidden="true" tabindex="-1"></a>          uint16 rct_stroke<span class="op">;</span>    <span class="co">// 1=solid, 2=dashed, 3=dotted, 4=dot-dash</span></span>
<span id="cb2-109"><a href="http://ackstorm.de#cb2-109" aria-hidden="true" tabindex="-1"></a>          uint16 rct_angle<span class="op">;</span>     <span class="co">// 0-360</span></span>
<span id="cb2-110"><a href="http://ackstorm.de#cb2-110" aria-hidden="true" tabindex="-1"></a>          uint16 rct_lwidth<span class="op">;</span>    <span class="co">// 101-115</span></span>
<span id="cb2-111"><a href="http://ackstorm.de#cb2-111" aria-hidden="true" tabindex="-1"></a>          uint16 rct_back<span class="op">;</span>      <span class="co">// 1=transparent, 2=solid, 3-8=various patterns</span></span>
<span id="cb2-112"><a href="http://ackstorm.de#cb2-112" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb2-113"><a href="http://ackstorm.de#cb2-113" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb2-114"><a href="http://ackstorm.de#cb2-114" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> unkown<span class="op">;</span></span>
<span id="cb2-115"><a href="http://ackstorm.de#cb2-115" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-116"><a href="http://ackstorm.de#cb2-116" aria-hidden="true" tabindex="-1"></a>        <span class="kw">struct</span> BITMAP <span class="op">{</span></span>
<span id="cb2-117"><a href="http://ackstorm.de#cb2-117" aria-hidden="true" tabindex="-1"></a>          uint16 bmp_prop1<span class="op">;</span></span>
<span id="cb2-118"><a href="http://ackstorm.de#cb2-118" aria-hidden="true" tabindex="-1"></a>          uint32 bmp_prop2<span class="op">;</span></span>
<span id="cb2-119"><a href="http://ackstorm.de#cb2-119" aria-hidden="true" tabindex="-1"></a>          uint16 bmp_prop3<span class="op">;</span>     <span class="co">// 0x1e</span></span>
<span id="cb2-120"><a href="http://ackstorm.de#cb2-120" aria-hidden="true" tabindex="-1"></a>          uint32 bmp_prop4<span class="op">;</span></span>
<span id="cb2-121"><a href="http://ackstorm.de#cb2-121" aria-hidden="true" tabindex="-1"></a>          uint32 bmp_width<span class="op">;</span></span>
<span id="cb2-122"><a href="http://ackstorm.de#cb2-122" aria-hidden="true" tabindex="-1"></a>          uint32 bmp_height<span class="op">;</span></span>
<span id="cb2-123"><a href="http://ackstorm.de#cb2-123" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lon<span class="op">;</span></span>
<span id="cb2-124"><a href="http://ackstorm.de#cb2-124" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> lat<span class="op">;</span></span>
<span id="cb2-125"><a href="http://ackstorm.de#cb2-125" aria-hidden="true" tabindex="-1"></a>          <span class="dt">double</span> unkown<span class="op">;</span></span>
<span id="cb2-126"><a href="http://ackstorm.de#cb2-126" aria-hidden="true" tabindex="-1"></a>          uint32 bmp_len<span class="op">;</span></span>
<span id="cb2-127"><a href="http://ackstorm.de#cb2-127" aria-hidden="true" tabindex="-1"></a>          uint16 bmp_angle<span class="op">;</span>     <span class="co">// 100-460</span></span>
<span id="cb2-128"><a href="http://ackstorm.de#cb2-128" aria-hidden="true" tabindex="-1"></a>          <span class="dt">char</span> bmp_data<span class="op">[</span>bmp_len<span class="op">];</span></span>
<span id="cb2-129"><a href="http://ackstorm.de#cb2-129" aria-hidden="true" tabindex="-1"></a>        <span class="op">}</span></span>
<span id="cb2-130"><a href="http://ackstorm.de#cb2-130" aria-hidden="true" tabindex="-1"></a>      <span class="op">}</span></span>
<span id="cb2-131"><a href="http://ackstorm.de#cb2-131" aria-hidden="true" tabindex="-1"></a>    <span class="op">}</span></span>
<span id="cb2-132"><a href="http://ackstorm.de#cb2-132" aria-hidden="true" tabindex="-1"></a>  <span class="op">}</span></span>
<span id="cb2-133"><a href="http://ackstorm.de#cb2-133" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
]]></description>
    <pubDate>Tue, 12 Jan 2016 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/geogrid-viewer-file-format.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>
<item>
    <title>Fujitsu Lifebook Keypad Driver Update for OpenBSD 5.7</title>
    <link>http://ackstorm.de/posts/openbsd-fjkey-iic-driver-update-5.7.html</link>
    <description><![CDATA[<div class="info">
  Posted on January 27, 2015. Tagged as: <a title="All pages tagged 'openbsd'." href="http://ackstorm.de/tags/openbsd.html" rel="tag">openbsd</a>, <a title="All pages tagged 'lifebook'." href="http://ackstorm.de/tags/lifebook.html" rel="tag">lifebook</a>, <a title="All pages tagged 'fujitsu'." href="http://ackstorm.de/tags/fujitsu.html" rel="tag">fujitsu</a>
</div>


<p>Recently the workq API was replaced by taskq. This requires a minor
update to the fjkey driver. A new
<a href="http://ackstorm.de/files/fjkey-2015-01-04.patch">patch is available for download</a>. For
more information see the
<a href="http://ackstorm.deopenbsd-fjkey-iic-driver.html">older post</a></p>
<p><strong>Update</strong> (2015-01-27): There was another change affecting fjkey. The latest <a href="http://ackstorm.de/files/fjkey-2015-01-27.patch">patch
is available for download</a>.</p>
]]></description>
    <pubDate>Tue, 27 Jan 2015 00:00:00 UT</pubDate>
    <guid>http://ackstorm.de/posts/openbsd-fjkey-iic-driver-update-5.7.html</guid>
    <dc:creator>Ralf Horstmann</dc:creator>
</item>

    </channel>
</rss>
