Thursday, July 9, 2009

Interface with keypad in C, help needed!?

1 2 3 F (j)


4 5 6 E (k)


7 8 9 D (l)


A 0 B C (m)


(e) (f) (g) (h)





I have the above keypad, which I need to read inputs from.


To read from it, i have two 8 bit latches, called COLUMN and ROW.





Signals from J,K,L and M are mapped to bits 0-3 of ROW,


and E,F,G and H are mapped to bits 4-7 of COLUMN.





0x40 = 0 1 0 0 0 0 0 0


bit number = 7 6 5 4 3 2 1 0


row/column = H G F E M L K J








To check it, I'm masking it like this:


x = COLUMN;


x %26amp;= 0x40;


// so if (x!=0), then g is high





So I can identify what row and column are active, so for example, pressing '5' makes K and F high.








Is there a more elegant way to do this, than creating 8 integers for EFGHJKLM and typing out all 16 permutations like this?








if (k==1)%26amp;%26amp;(f==1) output = '5';


else if (k==1)%26amp;%26amp;(g==1) output = '6';


else if (k==1)%26amp;%26amp;(h==1) output = 'E'; and so on...








Any help, even if you're unsure, would be greatly appreciated.

Interface with keypad in C, help needed!?
0x40 = 0 1 0 0 0 0 0 0


bit number = 7 6 5 4 3 2 1 0


row/column = H G F E M L K J





The above seems to me to col/row not row/col so I switched them around since row/col is more natural in C arrays.





(1) Any input byte is going to have one bit on in the high nibble (row) and one on in the low nibble (col).





(2) Separate the nibbles.





(3) Count the shifts until each nibble is zero. Note that each nibble by definition has to have 1 bit on so it will never be 0.





(4) Map row/col results to your output display.





(5) This may be basically what Mark G was getting at but I am not sure.





#include%26lt;stdio.h%26gt;





int main ()


{


#define MAX_VALUES 16





//valid input bytes with 2 lines active


unsigned char rowcol[MAX_VALUES] = {0x11, 0x12, 0x14, 0x18,


0x21, 0x22, 0x24, 0x28,


0x41, 0x42, 0x44, 0x48,


0x81, 0x82, 0x84, 0x88};





char table[4][4] = {'1', '2', '3', 'F', '4', '5', '6', 'E',


'7', '8', '9', 'D', 'A', '0', 'B', 'C'};





int z = 0;


for (; z %26lt; MAX_VALUES; ++z)


{


unsigned char row = rowcol[z] %26gt;%26gt; 4;


unsigned char col = rowcol[z] %26amp; 0x0F;





int m = -1;


while (row %26gt; 0)


{


m++;


row = row %26gt;%26gt; 1;


}





int n = -1;


while (col %26gt; 0)


{


n++;


col = col %26gt;%26gt; 1;


}





printf("%c\n", table[m][n]);


}


}
Reply:You can try using a look up table, place the value of each key in an array or map in memory in numerical order starting at row 0 column 0. You have four rows by four columns. For any key press two bits on the 8-bit latch will go high (row %26amp; col).





Split the 8-bit latch into two nibbles representing the row and column values. (I Assume the row is in the high nibble) The column is the value of the low nibble which will also have a single bit set and can only be one of the following values


1000 = 8


0100 = 4


0010 = 2


0001 = 1


(The row and col nibbles can only be these 4 values for a proper key press)





You want to convert these nibble values in to a sequental value of 3,2,1,0 to indicate which col or row has been pressed.





Using a counter and the ZERO flag in the status register perform a series of right shifts incrementing a count for each shift. When the zero flag gets set stop shifting/counting as you will have just removed the only set bit in the col nibble.


Place the increment after the zero test to give you a zero based count (3 to 0) (If you code so you get 4 to1 just subtract 1)





Do the same thing for the ROW (High nibble)





This will give you row and col values of following in two seperate bytes





00000011 = 3


00000010 = 2


00000001 = 1


00000000 = 0





Depending on you array layout left shift ROW by two and AND with COL





00000011 = 3 %26lt;%26lt; 2 = 00001100 = 12


00000010 = 2 %26lt;%26lt; 2 = 00001000 = 8


00000001 = 1 %26lt;%26lt; 2 = 00000100 = 4


00000000 = 0 %26lt;%26lt; 2 = 00000000 = 0





Let assume that a third row button was pressed this results in the value of 8 which will be AND'ed (ADD) with the COL value (0 to 3) Lets assume COL 2





_00001000(8)


%26amp;00000010(2)


=00001010(10 or 0xA)





If you map out a truth table for this method for each key you will find that you will get a sequential binary count from 0000 to 1111.





The above example value of 10 is then used in a look up table or Array to return the mapped value of the key pad.





You can use this sequential value as a pointer to read a value from memory off set from a base address where key press value bytes are stored (mapped)
Reply:Could you arrange a short table in memory such that the offset to the proper value is ROW%26amp;COLUMN?





(the vast majority are of course unreachable/invalid values)


No comments:

Post a Comment