by using the upper four bits as outputs and the lower four bits as inputs, a simple 4×4, 16 button keypad can be connected to a microcontroller.
the first picture shows the state after the “0″ key has been pressed.
the 0×24 corresponds to the “scancode”, the first digit being the column and the second being the row.
to be exact, in binary 0×24 equals 0b00101000, this shows that during the scan, the key in the second column and the fourth row was pressed.
the bracketed values under that are the contents of the key buffer.
a simple code example for this:
//high bits are columns, low bits are rows
volatile uint8_t scancode = 0x00;
uint8_t i, j;
// set data direction on PORTD
// pins 8,7,6,5 as output, pins 4,3,2,1 as input
outb(DDRD, 0b11110000);
//loop over pins
for( i=4; i<8; i++ ) {
// sets outputs low one pin at a time
// also enables internal pull-ups on inputs
outb( PORTD, ~(1<<i) );
//debounce delay and settling time
timerPause(5);
//loop over port positions
for( j=0; j<4; j++ ) {
if( bit_is_clear(PIND,j) ) {
//set scancode
scancode = (1<<i)|(1<<j);
}
}
}
the “~(1<<n)” is an example of bitshifting, in this case it means “bitshift 1 left “n” times, then invert the result” or if we take n as 3, it would be:
~(1<<3)
after 0 shifts:
~(0b00000001)
after 1 shift:
~(0b00000010)
after 2 shifts:
~(0b00000100)
after 3 shifts:
~(0b00001000)
then inverted:
0b11110111
a slightly more complicated looking example of this is used in the inner loop:
(1<<n)|(1<<m)
or if we take n as 6 and m as 2 it would be:
(0b01000000)|(0b00000100)
and that would resolve to:
0b01000100