A "card" is a sheet of paper with a 5mm square grid (like you can find in any office supplies shop). You can create your own cards by hand with a black marker. You can also print the "cards" with a toner printer or inkjet printer.

There are (so far) 10 tracks :

  • 1 "clock"
  • 8 data
  • 1 parity

Each track is 5mm wide and the center is considered (a few mm²) to reduce manual alignment problems.

The "clock" is "shifted" so its edges correspond to the middle of the data and parity squares.

Each data and parity track starts with a little preamble (4 or 5 bits), then 32 data bits, then 7 bits of Hamming code (more reliable and useful than plain CRC) and a repeat of preamble (to ensure data are inserted in the right direction).

The preamble is also used to calibrate the black and white levels, which are necessary to discriminate the bits. Some analog circuitry generates the mean value that is fed to the analog comparators.Since there are a total of 5+32+7+5=49 bits, a "card" is about 25cm long by 5cm wide. There can be 4 "cards" in a A4 paper sheet, on both long edges and both sides.

The following image is a not faithful illustration of the idea:

Parity is easy to compute by hand : if the number of black bits is odd, mark the parity bit black. The total number of black bits of a line/row is even.

Hamming coding is less easy but not too hard to code in assembly language.

Each "card" is 32*8=256 bits (only). Multiple cards can be chained, the encoded data must take care of the serial numbers etc.

Optoelectronics :

A red LED focuses its light to the center of the square. The reflected light is picked up by a BPW34 photodiode (which is less than 5mm wide). A trimmer finely adjusts sensitivity between all the 10 channels. The output of each track goes to a comparator (LMC7221) then to logic processing (the parity detection is just a couple of 74HC84).

The other input of the analog comparator comes from the filtered mean value of all the channels.

The "card" should be readable with varying sliding speeds... the average would then be updated at each "clock edge".