Here is your code with the comments that it should have had all along added in, plus tables showing exactly what the shift operations are doing (the latter shouldn't be necessary for any experienced C programmer):
#define KEYPAD A
#define KEYPAD_PORT PORT(KEYPAD)
#define KEYPAD_DDR DDR(KEYPAD)
#define KEYPAD_PIN PIN(KEYPAD)
uint8_t GetKeyPressed()
{
uint8_t r, c;
/* Preset the data for the row inputs to 1.
*/
KEYPAD_PORT |= 0X0F;
/* Scan through the three columns - 0, 1, 2
*/
for (c=0; c<3; c++) {
/* Enable the output for the column we want to drive, but also be sure
* not to modify the existing DDR value for bit 7. This sets DDR to
* c == 0: ?1000000
* c == 1: ?0100000
* c == 2: ?0010000
*/
KEYPAD_DDR &= ~(0X7F);
KEYPAD_DDR |= (0X40>>c);
/* Scan through the four rows - 0, 1, 2, 3
*/
for (r=0; r<4; r++) {
/* If the corresponding input pin is low, return the key location,
* a number in the range 0-11. The mask (0x08 >> r) becomes
* r == 0: 00001000
* r == 1: 00000100
* r == 2: 00000010
* r == 3: 00000001
*/
if (!(KEYPAD_PIN & (0X08>>r))) {
return (r*3+c);
}
}
}
/* No keys pressed, return special code.
*/
return 0XFF;
}
Note that there's a subtle bug. The intent is to drive the column lines low one at a time, but we don't actually know what the port data is for those lines. The line
KEYPAD_PORT |= 0X0F;
Only sets bits 0-3, but doesn't affect bits 4-7. This is a useless operation, since we never enable those pins as outputs anyway. This line needs to be replaced by
KEYPAD_PORT &= 0X8F;
in order to force bits 4-6 low so that we can use the data to drive the columns one at a time. This leaves bit 7 alone, since we don't want to affect it, and we don't care about the data for bits 0-3.