Often you need to read in some keys. There is a simple example to scan 12
keys. They keys are placed on every cross point of 4 rows and 3 columns.
Row0 is connected to ground, the other and the columns to the pins defined
in the example.
The rows are outputs. If they activated they are driven low.
The columns are inputs. They are pulled high by its internal pull ups.
If a key was pressed and its row is activated (=low) then its column is on
low level too.
In general all keys give many pulses during pressing or releasing. So you
need a debouncing. This can be done by scanning 2 or more times with a delay
between every scanning.
And only if these scans equal this key can be accept.
Look at the list file:
The columns are all pulled high by the internal pull ups. The rows are put
to low, row0 first (permanent) and row3 last (by the "jbc" instructions line
29 .. 31).
If no key was pressed all columns still high and no jump (line 23, 25, 27)
was done. So acc was 12 times incremented and be 1.
If a key was pressed the column was put low by the key which connect it with
the low driven row. So the jump to ks2 was executed and the decrementing
of acc was interrupted.
The key between row0 and col0 was checked at first and give 13 as result
in the acc. The key between row3 and col2 was checked last and remain the
acc = 2.
If 1 pressed key was found no other was checked.
The new value was stored and the previous was placed in acc by the "xch"
instruction (line 33).
Then both compared and only if equal accepted (debouncing).
In most cases only the key pressing or releasing was needed.
So the value was compared with the older accepted. And only if the new different
from the older the value was returned. Otherwise acc = 0 mark no change in
key state.
E.g. if 1 key used to increment the hour of a timer you get only 1 increment
of it by every pressing of this key.
In some cases an action want to be repeat if the key was pressed longer.
To do this, you can start a timer which gives out the last stored key number
(=oldkey). And if the key release value (acc=1) was read, this timer can
be stopped.
If you want detect 2 simultaneously pressed keys you must drive all 4 rows
and only 1 row can be driven low at the time (use not the "jbc" instructions,
shift simple the low level trough all rows, e.g.
mov a,p1
rl a
mov p1,a ), store the number of the 1.key and continue searching to get the
2.key.
It's also easy to expand the count of rows and columns to scan more
keys.