A Gray code is a way of encoding binary numbers so that only digit changes from one number to the next. That means that a single 0 can change to a 1, or a single 1 can change to a zero:
Decimal Gray code 0 00001 00012 00113 00104 01105 01116 01017 01008 11009 110110 111111 111012 101013 101114 100115 1000
The highlighted digits are the ones that changed (counting up). The Gray code "wraps around:" When rolling over from 15 to 0, only one digit changes.
Mechanical position sensors use Gray code to convert the angular position of a shaft to digital form. The shaft has a disk attached to it; the disk has tracks like a computer storage device. Some parts of a track have metal, corresponding to a "1", and other parts have insulator, corresponding to a "0". The sensor has a row of metal fingers, radiating out from the center of the disk, with one finger riding on each track. As the shaft rotates, the disk carries metal or insulator under each finger. The combination of 1's and 0's read by the fingers indicate the angular position of the disk. Gray code is used instead of binary numbers because the fingers can't be lined up exactly. If two bits were to change at the same time (as in going from binary "01" to binary "10", one finger would invariably notice its bit change before the other finger did. That would be a very glitchy position sensor.
Here is a recursive algorithm for generating Gray codes:
It's actually much simpler to look at when it's in code. So here is a Ruby example.
#!/usr/bin/env ruby def prepend(prefix, array) array.collect { |item| prefix + item} end def grayCodes(bits) if bits == 1 ["0", "1"] else prepend("0", grayCodes(bits - 1)) + prepend("1", grayCodes(bits - 1).reverse) end end puts grayCodes(4)
And here's the output:
0000 0001 0011 0010 0110 0111 0101 0100 1100 1101 1111 1110 1010 1011 1001 1000
Let's compare an ordinary binary sequence with Gray code. The left-most binary digit that changed is highlighted. As before, the gray code bit that changed is highlighted.
Decimal Gray code Binary 0 00000000 1 00010001 2 00110010 3 00100011 4 01100100 5 01110101 6 01010110 7 01000111 8 11001000 9 11011001 10 11111010 11 11101011 12 10101100 13 10111101 14 10011110 15 10001111
Fascinating, isn't it? The digit to toggle when counting in Gray code happens to be the most significant digit that changed when counting in binary. Let's see if we can turn that into code.
#!/usr/bin/env ruby bits = 4 grayCode = 0 (1 << bits).times do |i| printf "%0#{bits}b\n", grayCode binaryBitsThatChanged = i ^ (i + 1) grayCodeBitToChange = binaryBitsThatChanged ^ (binaryBitsThatChanged >> 1) grayCode = grayCode ^ grayCodeBitToChange end
Here's the simplest algorithm for translating binary to Gray code. This algorithm can convert an arbitrary binary number to Gray code in finite time. Wonderful! Here it is in Ruby:
grayCode = binary ^ (binary >> 1)
How does it work? Beats me. It's a code version of this logic circuit using XOR gates (shown here for converting 4-bit numbers, but easily modified for any bit width):
It takes a little more to convert Gray code to binary. Here's the Ruby code:
# Convert binary to gray code. bits is the number of bits to convert # (could be calculated by looking at the size of the binary input). binary # is the number to convert. def gray_code(bits, binary) gray_code = 0 bit_number = bits - 1 bit = 0 while bit_number >= 0 bit ^= binary >> bit_number & 1 gray_code |= (1 << bit_number) * bit bit_number -= 1 end gray_code end
This code is easier to understand if you see the digital logic that it came from. It's just a cascade of XOR gates:
Every binary digit is the XOR of all gray code digits with equal or greater significance.