3D1-Microprocessor Systems 1

Lecture 20: Example of Polled Input: 16-key keypad

Imagine you have a 16-key keypad, interfaced to your computer at location $F05204, providing a 2-of-8 code for each key. You have to write an initial subroutine to read a character from it into D0.

The problem is that the switches suffer from "bounce" -- when they change state (from open to closed or from closed to open), the springiness and inertia of the moving parts combine to make the contacts open and close rapidly and irregularly for a short period, usually less than 5 milliseconds before finally settling into their new state.

You will the write a second subroutine that reliably and consistently returns the ASCII code of a key when it is pressed.

Learning Outcomes:

On completion of this lecture, you will be able to

·  Write a program that communicates with an Input interface;

·  Implement a programmed polling loop;

·  Discuss the advantages and drawbacks of memory-mapped I/O interface.

20.1 Write a subroutine to read a character from a keypad:

*All outputs are logic 1 normally, but when a button is pressed its *corresponding row and column number go to logic 0. We can create a look-up *table of ascii code equivalent for each key pressed. For example, the key *representing character '1' is at column 1 and row 1, hence its code return *by the keypad if '1' is pressed will be: 01110111 in binary.

KEYPAD EQU $F05204 memory location of keypad interface

ORG $1FFE

RSLT DS.B 1 allocate 1 byte space for result

ORG $2000

KPDLUT DC.B %01110111,'1' *

DC.B %10110111,'2' *

DC.B %11010111,'3' *

DC.B %11100111,'A' *

DC.B %01111011,'4' *

DC.B %10111011,'5' *

DC.B %11011011,'6' *

DC.B %11101011,'B' *

DC.B %01111101,'7' * look-up table

DC.B %10111101,'8' *

DC.B %11011101,'9' *

DC.B %11101101,'C' *

DC.B %11101110,'*' *

DC.B %11101110,'0' *

DC.B %11101110,'#' *

DC.B %11101110,'D' *

ORG $3000 returns ASCII code of a key pressed

GETKEY MOVEM.L D0/D1/A0,-(A7) save working registers on the stack

READ MOVE.B KEYPAD,D0 load keypad code in D0 [.5μs]

MOVEQ #15,D1 initialise counter D1 to 16-1: 16 keys [.5μs]

LEA KPDLUT,A0 A0 points at address of look-up table [.5μs]

FINDKEY CMP.B (A0),D0 search keypad code in look-up table [.5μs]

ADDA.L #2,A0 2 bytes stored in KPLUT -> incr of 2 [.5μs]

DBEQ D1,FINDKEY if not found decr D1 keep searching [.5μs]

BNE READ if no match found, re-load key [.5μs]

MOVE.B -(A0),D0 else save ascii code for matched key [.5μs]

return MOVE.B D0,RSLT save ascii code in memory [.5μs]

MOVEM.L (A7)+,D0/D1/A0 restore working registers

RTS

20.2 Write a subroutine that reliably and consistently returns the ASCII code of a key when it is pressed:

*We assume that each instruction of the polling loop takes .5μs. Thus we can work out how *long we want a key to be pressed before we accept it as valid. Then we will check it over *5ms and ensure it stays constant.

ORG $5000 solves switch bounce problems

BOUNCE MOVEM.L D0-D2/A0,-(A7)

DELCOUNT EQU 2500 polling loop takes 4*0.5μs=2μs must be run

over 5ms -> 2500 times

CLR D0

GETKEY00 MOVE.L #DELCOUNT-1,D1 initialise D1 as counter [.5μs]

MOVE.B KEYPAD,D0 load keypad code in D0 [.5μs]

TST.B D0 has key been pressed? [.5μs]

BEQ GETKEY00 if not read again [.5μs]

MOVE.B D0,D2 else copy keypad code in D2 [.5μs]

*bounce test polling loop:

GETKEY01 MOVE.B KEYPAD,D0 read keypad one more time [.5μs]

CMP.B D0,D2 compare with previous reading [.5μs]

BNE GETKEY00 if different then restart all [.5μs]

DBRA D1,GETKEY01 else decr D1 goto GETKEY01 if [D1]=>0 [.5μs]

GETKEY02 MOVEQ #15,D1 initialise counter D1 to 16-1: 16 keys [.5μs]

LEA KPDLUT,A0 A0 points at address of look-up table [.5μs]

FINDKEY02 CMP.B (A0),D0 search keypad code in look-up table [.5μs]

ADDA.L #2,A0 2 bytes stored in LUT -> incr of 2 [.5μs]

DBEQ D1,FINDKEY02 if not found decr D1 keep searching [.5μs]

BNE GETKEY02 if no match found, re-load key [.5μs]

MOVE.B -(A0),D0 else save ascii code for matched key [.5μs]

return2 MOVE.B D0,RSLT save ascii code in memory [.5μs]

MOVEM.L (A7)+,D0/D1/A0 restore working registers

RTS

ORG $4000

MOVE.B #%01111101,KEYPAD

BSR GETKEY

BSR BOUNCE

END $4000

20.3 Conclusion

Operating a compute in a polled I/O mode is grossly inefficient because so much of the computer’s time is wasted for the port to become available. If a microcomputer has nothing better to do while it is waiting for a peripheral to become free, polled I/O is perfectly acceptable. Many of the first generation of computers were operated this way. However, a more powerful computer working in a multiprogramming environment can attend to another task or program during the time the I/O port is busy. In this case a better I/O strategy is to ignore the peripheral until it is ready for a data transfer and then let the peripheral ask the CPU for attention. Such strategy is called interrupt-driven I/O.

REFERENCES

·  A. Clements; Peripheral Programming, In: 68000 Family Assembly Language; pp.368-435; PWS Publishing Company; 1994.

·  Dr. Mike Brady, Microprocessor Systems 1, dept of Computer Science, Trinity College Dublin: http://www.tcd.ie/Engineering/Courses/BAI/JS_Subjects/3D1/

·  Look on the Web at http://www.mee.tcd.ie/~assambc/3D1

20-4