There’s a series of interesting observations that come handy when attempting to transfer the GCR representation of a track value in a Commodore 1541 disk using fewer than 10 bits.
First of all, Commodore’s own GCR encoding is covered here.
Because track count can only go up to 42 for a 5’1/2” disk, the highest track value in hex is $2A. This means that the first five bits of a track’s GCR representation can only be one of:
01010, for tracks $01-$0F
01011, for tracks $10-$1F
10010, for tracks $20-$2A
It only takes two bits to index any one of four objects, right? So two bits are certainly enough for our circumstances. How to choose the arrangement of these two bits to represent one of the above values?
Here’s one opinionated way to do so, which actually focuses on bit values that are occurring at certain positions within the GCR representation.
Starting from the left side: the group of first two bits can be represented with just one bit: 1 for the couple 01 and 0 for the couple 10, i.e. we just note down the second bit. The subsequent couple of bits is the same for all values, so we don’t need to note these down. The last bit on the right we have to note down then.
So, our mapping looks like below:
10 -> 01010
11 -> 01011
00 -> 10010
Again, although the above is an arbitrarily chosen mapping, it has the advantage that it actually is tracking the values of two bits as they occur in the GCR value itself, which means we don’t need a lookup table and we can just use ASL/ROL instructions to pack them into a single byte, together with the subsequent 5 bits of the GCR representation of the track value, for transmission purposes.
How is this any useful? Well, it provides a strategy for capturing the track value in a sector header and transferring it efficiently to IECHost, which is not currently happening. There are pro and cons to that, but that’s the topic for another post!