:CueCat Decoder

The XPL0 program shown below decodes and displays the output from a :CueCat.

A :CueCat is a barcode scanner that plugs into a PC's keyboard port. One of the best things about a :CueCat is that you can get one absolutely free from your friendly neighborhood Radio Shack.

After you've plugged it in and done a few practice swipes, you should see something like this:

Looks like a lot of useless gibberish, but notice that there are four fields separated by periods. The first field "q" is a header that always contains Alt+F10. The second field contains the serial number of your particular scanner. The next field identifies the type of barcode detected, and the last field is the numeric value of the barcode.

Here's how to unscramble the characters:

        1. Get a 4-character sequence.
        2. Look up each character's position in this table:

                 0: abcdefghijklmnop
                16: qrstuvwxyzABCDEF
                32: GHIJKLMNOPQRSTUV
                48: WXYZ0123456789+-

        3. Convert the position number to binary.
        4. Regroup the binary digits to form three 8-bit values.
        5. Exclusive-or 01000011 with each of the three values.
        6. Convert the binary to ASCII.
For example, the last field above begins with "C3DW":
        1. C      3      D      W
        2. 28     55     29     48
        3. 011100 110111 011101 110000
        4. 01110011 01110111 01110000
        5. 01000011 01000011 01000011
           00110000 00110100 00110011
        6. 0        4        3
The complete decoding reveals the Universal Product Code of my favorite cereal:

\CUECAT.XPL     19-MAY-2001
\:CueCat Decoder
\32-bit XPL (XPLP) must be used because of the 24-bit value in the Decode proc.

include \cxpl\codesi;

char    LineBuf,        \line of text read in by :CueCat
        CodeTbl;        \decoder table
int     Ch, J, Field;
def     CR=$0D, Esc=$1B;\ASCII control characters

func    GetIndex(Ch);   \Return index to Ch in CodeTbl, 0 if none
int     Ch;
int     I;
for I:= 0, 63 do        \for all the characters in CodeTbl...
        if Ch = CodeTbl(I) then return I;
return 0;               \illegal character
end;    \GetIndex

proc    Decode(S4);
\Convert a 4-character string S4 into 3 ASCII characters and display them
char    S4;     \address of 4-character string
int     S3, I;
char    AS3;    \address of S3 (to access the bytes)
S3:= 0;
for I:= 0, 3 do
        S3:= S3<<6 + GetIndex(S4(I));
AS3:= addr S3;
for I:= 0, 2 do Chout(0, AS3(2-I) | $43);
end;    \Decode

begin   \Main
LineBuf:= Reserve(100);
Text(0, ":CueCat Decoder

Esc = exit
CodeTbl:= "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+- ";

loop    begin
        for J:= 0, 99 do LineBuf(J):= ^.;       \(required for UPE barcodes)
        J:= 0;
        repeat  Ch:= Chin(1);           \read character from :CueCat
                if Ch = Esc then quit;  \Esc aborts program (manual keystroke)
                Chout(0, Ch);           \echo character to display
                LineBuf(J):= Ch;        \store character into line buffer
                J:= J + 1;
        until Ch = CR;                  \:CueCat line terminator

        J:= 3;                          \skip Alt+F10's scan code and skip "."

        for Field:= 0, 2 do
                repeat  Decode(addr LineBuf(J));
                        J:= J + 4;      \next 4-char string
                until LineBuf(J) = ^.;  \field separator
                J:= J + 1;              \skip "."
end;    \Main


There's a great deal of information about the :CueCat. Here are some links to get you started:

:CueCat is a trademark of Digital:Convergence Corporation

Back to the XPL0 home page

Last updated: 13-Mar-2004