Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Bitwise GCR decoding
2021-01-05 10:34
Krill

Registered: Apr 2002
Posts: 3098
Bitwise GCR decoding

This is some kind of ongoing basic research pet project of mine, possibly re-inventing the wheel, and so far with fewer opportunities for practical application than i've hoped.
Posting this here because it might be of interest to some and may lead to more insights than i've had so far. =)

Consider the traditional Commodore GCR to raw nibble mapping:
$09 %01001 -> %1000 $08
$0a %01010 -> %0000 $00
$0b %01011 -> %0001 $01
$0d %01101 -> %1100 $0c
$0e %01110 -> %0100 $04
$0f %01111 -> %0101 $05
$12 %10010 -> %0010 $02
$13 %10011 -> %0011 $03
$15 %10101 -> %1111 $0f
$16 %10110 -> %0110 $06
$17 %10111 -> %0111 $07
$19 %11001 -> %1001 $09
$1a %11010 -> %1010 $0a
$1b %11011 -> %1011 $0b
$1d %11101 -> %1101 $0d
$1e %11110 -> %1110 $0e
A decoder must know all 5 GCR bits in order to decode a raw nibble.

Consider an alternative GCR to raw nibble mapping:
$09 %01001 -> %1111 $0f
$0a %01010 -> %1110 $0e
$0b %01011 -> %1101 $0d
$0d %01101 -> %1100 $0c
$0e %01110 -> %1011 $0b
$0f %01111 -> %1010 $0a
$12 %10010 -> %0100 $04
$13 %10011 -> %0011 $03
$15 %10101 -> %0010 $02
$16 %10110 -> %0001 $01
$17 %10111 -> %0000 $00
$19 %11001 -> %1001 $09
$1a %11010 -> %1000 $08
$1b %11011 -> %0111 $07
$1d %11101 -> %0110 $06
$1e %11110 -> %0101 $05
This mapping has some interesting properties, which become apparent with different representations:
                   [0] 6
                   / \
                  /   \                  [0] f
                 /     \                 / \ +0
                /       \               /  [1] f 1111
               /         \             / +2
              /           \ +4       [0] d
             /             \         / \ +0
            /               \       /   \  [0] e 1110
           /                 \     /     \ / +1
          /                   \   / +3   [1] d
         /                     \ /        \ +0
        / +6                   [1] a       [1] d 1101
       /                         \
      /                           \ +0   [0] c
     /                             \     / \ +0
    /                               \   /  [1] c 1100
   /                                 \ / +2
  /                                  [1] a
 /                                     \ +0
/                                       \  [0] b 1011
GCR|+16 +8 +4 +2 +1                      \ / +1
  0| +6 +0 +3 +2 +1 decode               [1] a
  1| +0 +4 +0 +0 +0 to raw                 \ +0
\                                          [1] a 1010
 \
  \                                  [0] 3
   \                                 / \ +0
    \                               /   \  [0] 4 0100
     \                             /     \ / +1
      \                           / +3   [1] 3
       \                         /         \ +0
        \ +0                   [0] 0       [1] 3 0011
         \                     / \
          \                   /   \ +0   [0] 2
           \                 /     \     / \ +0
            \               /       \   /  [1] 2 0010
             \             /         \ / +2
              \           / +0       [1] 0
               \         /             \ +0
                \       /               \  [0] 1 0001
                 \     /                 \ / +1
                  \   /                  [1] 0
                   \ /                     \ +0
                   [1] 0                   [1] 0 0000
                     \
                      \                  [0] 9
                       \                 / \ +0
                        \               /  [1] 9 1001
                         \             / +2
                          \ +4       [0] 7
                           \         / \ +0
                            \       /   \  [0] 8 1000
                             \     /     \ / +1
                              \   / +3   [1] 7
                               \ /         \ +0
                               [1] 4       [1] 7 0111
                                 \
                                  \ +0   [0] 6
                                   \     / \ +0
                                    \   /  [1] 6 0110
                                     \ / +2
                                     [1] 4
                                       \ +0
                                        \  [0] 5 0101
                                         \ / +1
                                         [1] 4
The GCR values form some kind of positional number system.

Each GCR bit position/value pair maps to a decoded value.
The individual decoded values of all 5 GCR nibble bits can be added to decode a raw nibble.
As the add operation is commutative and associative, a decoder can consume GCR nibbles piece-wise in any order of the input bits.

This can be used to decode a GCR stream like so:
ldx $1c01     ; 00000111
lda decode01,x; 00001... - nibble 0 complete, nibble 1 partial
[...]
ldx $1c01     ; 11222223
adc decode1,x ; 00001111 - byte 0 complete
[...]
lda decode23,x; 22223... - nibble 2 complete, nibble 3 partial
ldx $1c01     ; 33334444
adc decode3,x ; 22223333 - byte 1 complete
[...]
This concept can also be used to decode a GCR stream on-the-fly while it is sent over the serial bus in bitpairs.

Note that an additional look-up would be required to map the custom-GCR decoded bytes to original standard Commodore GCR decoded bytes.

As the individual decoding tables take the better part of 256 indices each, memory required for them quickly becomes quite big.
This is problematic with the 2 KB of RAM of a 1541.

There may be opportunities to squeeze the tables together or apply other optimisations, considering these 16 mappings which satisfy the bitwise GCR decoding constraints.
GCR:   4  3  2  1  0

 1. 0: 2, 4, 1, 6, 0
    1: 0, 0, 0, 0, 5

 2. 0: 1, 2, 3, 6, 0
    1: 0, 0, 0, 0, 5

 3. 0: 3, 0, 0, 2, 1
    1: 0, 2, 8, 0, 0

 4. 0: 3, 6, 0, 2, 1
    1: 0, 0, 7, 0, 0

 5. 0: 6, 0, 3, 2, 1
    1: 0, 4, 0, 0, 0

 6. 0: 0, 6, 3, 2, 1
    1: 5, 0, 0, 0, 0

 7. 0: 3, 0, 8, 2, 1
    1: 0, 2, 0, 0, 0

 8. 0: 6, 0, 0, 4, 2
    1: 0, 4, 1, 0, 0

 9. 0: 6, 0, 1, 4, 2
    1: 0, 4, 0, 0, 0

10. 0: 0, 6, 1, 4, 2
    1: 5, 0, 0, 0, 0

11. 0: 1, 2, 0, 0, 3
    1: 0, 0, 8, 2, 0

12. 0: 1, 2, 8, 0, 3
    1: 0, 0, 0, 2, 0

13. 0: 1, 2, 0, 6, 3
    1: 0, 0, 7, 0, 0

14. 0: 2, 4, 0, 0, 6
    1: 0, 0, 1, 4, 0

15. 0: 2, 4, 1, 0, 6
    1: 0, 0, 0, 4, 0

16. 0: 1, 2, 3, 0, 6
    1: 0, 0, 0, 4, 0
 
... 20 posts hidden. Click here to view all posts....
 
2025-04-25 17:23
Quiss

Registered: Nov 2016
Posts: 52
Quote:

I think I found working ones, though. Will double-check and then post here.


The second set was wrong as well. Which is sad.

But at least the universe makes sense again now. There are 20922789888000 ways to order the GCR values. Only 16 of which can be decoded bit-by-bit, see OP.
It would have very improbable that the (more or less) random choice of the default GCR order and its 5160960 checksum-compatible reshufflings would have happened to contain one of those 16.

Quote:

Would this be a less strong restriction than allowing for bitwise decoding in any order of input bits?


It's the same restriction, actually!

Quote:

More mappings to choose from would be quite something in (my, at least) quest for the somewhat holy grail of requiring only those two lookups plus add with no more than say 2 pages worth of tables. =)


You can give each partition (i.e., each nibble) its own mapping?

Only the 4:1 partition can be made "checksum-compatible", though.
2025-04-25 17:54
Krill

Registered: Apr 2002
Posts: 3098
Quoting Quiss
It's the same restriction, actually!
That's what i thought, but then your post made me question that assumption. =)

Quoting Quiss
You can give each partition (i.e., each nibble) its own mapping?
Of course, but then more mappings would still come in handy! And yeah, all by-partition mappings are a few more than just the 16. But how to cleverly combine them to squeeze the lookup tables while still avoiding shifts and masking... =)

Quoting Quiss
Only the 4:1 partition can be made "checksum-compatible", though.
Oh well, the original checksum is really weak anyways. Wouldn't have any problems to sacrifice a payload byte for a stronger checksum, like i did with Transwarp.
But it would be cool still to be able to transform the original checksum.
Previous - 1 | 2 | 3 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Tommy/Noice^DCS
csabanw
DnP
MWR/Visdom
crl
dstar
Guests online: 314
Top Demos
1 Next Level  (9.7)
2 13:37  (9.7)
3 Codeboys & Endians  (9.7)
4 Mojo  (9.6)
5 Coma Light 13  (9.6)
6 Edge of Disgrace  (9.6)
7 Signal Carnival  (9.6)
8 Wonderland XIV  (9.5)
9 Uncensored  (9.5)
10 Comaland 100%  (9.5)
Top onefile Demos
1 Nine  (9.7)
2 Layers  (9.6)
3 Cubic Dream  (9.6)
4 Party Elk 2  (9.6)
5 Copper Booze  (9.5)
6 Scan and Spin  (9.5)
7 Onscreen 5k  (9.5)
8 Grey  (9.5)
9 Dawnfall V1.1  (9.5)
10 Rainbow Connection  (9.5)
Top Groups
1 Artline Designs  (9.3)
2 Booze Design  (9.3)
3 Oxyron  (9.3)
4 Performers  (9.3)
5 Censor Design  (9.3)
Top Organizers
1 Burglar  (9.9)
2 Sixx  (9.8)
3 Tim  (9.7)
4 Irata  (9.7)
5 hedning  (9.7)

Home - Disclaimer
Copyright © No Name 2001-2025
Page generated in: 0.053 sec.