;***** 16 key keybd test ******** ; Scans a 4x4 keyboard and lights LEDS corresponding ; to keys 1 to 16 ;See lab 5 writeup for keyboard connection details, ;Upper nibble of port is columns; lower is rows, ;A button press shorts a column to a row. ;Normally this demo would be coded as a subroutine and called ;from a debounce state machine once every 30 milliseconds or so. ,nolist .include "d:\bruce\atmel\asm src\4414def.inc" .list .def Temp =r16 ;temporary register .def key =r17 ;holds raw press value .def butnum =r18 ;final press value . ;***** Initialization .cseg .org $0000 rjmp RESET ;reset entry vector reti reti reti reti reti reti reti reti reti reti reti reti ;The following table is used to convert raw button-press high/low ;values to a sequence number. Invalid codes caused by multiple ;button presses are ignored. keytbl: .db 0b11101110, 0b11101101, 0b11101011, 0b11100111 .db 0b11011110, 0b11011101, 0b11011011, 0b11010111 .db 0b10111110, 0b10111101, 0b10111011, 0b10110111 .db 0b01111110, 0b01111101, 0b01111011, 0b01110111 RESET: ldi Temp, LOW(RAMEND) ;setup stack pointer out SPL, Temp ldi Temp, HIGH(RAMEND) out SPH, Temp ;set up LEDs for output ser temp out DDRB, temp out PORTB, temp loop: ldi temp, 0x0f ;set lower four lines to output out DDRC, temp ldi temp, 0xf0 ;and turn on the pullups on the inputs out PORTC, temp nop ;Need some time for the pullups to nop ;charge the port pins nop nop in temp, PINC ;read the high nibble mov key, temp ;and store it (with zeros in the low nibble) ldi temp, 0xf0 ;set upper four lines to outputs out DDRC, temp ldi temp, 0x0f ;and turn on pullups on the inputs out PORTC, temp nop ;As before wait for the pin to charge nop nop nop in temp, PINC ;read the low nibble or key, temp ;combine to make key code ;At the point the raw key code should have exactly one zero each in ;the lower and upper nibbles. Any other number of zeros indicates ;either no-button pressed or multiple-button pressed. ;Now search the table for a match to the raw key code ;and exit with a button number ldi ZL, low(keytbl*2) ;table pointer in FLASH ldi ZH, high(keytbl*2) ;so convert from word to byte addr ldi butnum, 0 tbllp: lpm ;get the table entry cp key, r0 ;match? breq foundit inc butnum ;if not, have we exhaused the cpi butnum, 0x10 ;table breq illegal adiw ZL, 1 ;if not, get the next table entry rjmp tbllp foundit:subi butnum, -1 ;add one for display com butnum ;invert to drive LEDs out PORTB, butnum ;display button number rjmp loop illegal:ser temp ;no table match means show out PORTB, temp ;a zero clr butnum rjmp loop