<?xml version="1.0" encoding="utf-8"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
<link rel="alternate" type="text/html" href="https://gamma.unpythonic.net/"/>

<title>Jeff Epler's blog</title>
<modified>2026-03-09T20:55:10Z</modified>
<tagline>Photos, electronics, cnc, and more</tagline>
<author><name>Jeff Epler</name><email>jepler@unpythonic.net</email></author>
<entry>
<title>radix40 encoding</title>
<issued>2026-03-09T20:55:10Z</issued>
<modified>2026-03-09T20:55:10Z</modified>
<id>https://gamma.unpythonic.net/01773089710</id>
<link rel="alternate" type="text/html" href="https://gamma.unpythonic.net/01773089710"/>
<content type="text/html" mode="escaped">



&lt;link rel=&quot;stylesheet&quot; href=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/styles/default.min.css&quot;&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.11.1/languages/python.min.js&quot;&gt;&lt;/script&gt;
&lt;style&gt;
.junkpre { border: 1px solid black; max-width: 132ex; max-height: 45lh; overflow: auto; }
&lt;/style&gt;
&lt;script&gt;
const do_embed = function(container, url) {
    const request = new Request(url);
    fetch(request)
      .then((response) =&gt; response.json())
      .then((data) =&gt; {
        container.textContent = atob(data['content']);
        hljs.highlightElement(container)    
    })
    .catch((error) =&gt; {
       console.error(error);
    });
}
const do_embed_here = function(url, classes) {
    const id = &quot;embed&quot; + (((1 + Math.random()) * 0x1000000) | 0).toString(16).substring(1);
    document.write(&quot;&lt;pre class=junkpre&gt;&lt;code id=&quot; + id + &quot; class=junkembed&gt;&lt;/code&gt;&lt;/pre&gt;&quot;)
    const el = document.getElementById(id)
    if (classes) {
        el.className = el.className + &quot; &quot; + classes
    }
    do_embed(el, url)
}
&lt;/script&gt;



&lt;p&gt;&lt;br&gt;I was inspired to design an original(?) text encoding for tiny embedded
computers. It is, however, similar to &lt;a href=&quot;https://en.wikipedia.org/wiki/DEC_RADIX_50&quot;&gt;DEC RADIX 50&lt;/a&gt; from 1965. (That's 50₈=40₁₀).
Since 40³&amp;lt;65536, it is possible to store 3 symbols in each 16 bit word.

&lt;p&gt;In radix 40 you get the 26 basic alphabetic characters, 10 digits, and 4
additional symbols. I chose:
&lt;ul&gt;
&lt;li&gt;End of string
&lt;li&gt;Space (ASCII 32)
&lt;li&gt;Exclamation point (ASCII 33)
&lt;li&gt;Double quote (ASCII 34)
&lt;/ul&gt;

&lt;p&gt;The choice of 3 characters that are adjacent in ASCII saved code size on the
decoder; initially I thought maybe &amp;quot;-&amp;quot; and &amp;quot;.&amp;quot; would be useful choices.

&lt;p&gt;Unlike RADIX 50, the encoding is arranged so that no division or
remainder operation is needed. Instead, at each step of decoding, a
24 bit temporary value is multiplied by 40 and the top byte gives the
output code. In the assembler vesion, the multiplication is coded as 
&lt;tt&gt;x&lt;-x*8; tmp&lt;-x; x&lt;-x*4; x&lt;=x+tmp&lt;/tt&gt;) since the MC6800 has no multiply
instruction.

&lt;p&gt;Here are the not quite matching Python encoder

&lt;script&gt;
do_embed_here(&quot;https://codeberg.org/api/v1/repos/jepler/junkdrawer/contents/epvenhla/b40.py?ref=main&quot;, &quot;language-python&quot;);
&lt;/script&gt;


&lt;p&gt;And decoder/test program in m6800 assembly:

&lt;script&gt;
do_embed_here(&quot;https://codeberg.org/api/v1/repos/jepler/junkdrawer/contents/epvenhla/b40.asm?ref=main&quot;);
&lt;/script&gt;


&lt;p&gt;The implementation costs 90 bytes of code and 6 bytes of zero-page (which can
be used for other purposes when the routine is not running). I estimate you'd
need somewhat above 320 characters of text in your program for it to be a benefit.

&lt;p&gt;The m6800 decoder can over-read the data by 1 byte, which seldom poses a problem in such environments.
</content>
</entry>
</feed>
