; For I/O registers located in extended I/O map, "IN", "OUT", "SBIS", "SBIC", ; "CBI", and "SBI" instructions must be replaced with instructions that allow access to ; extended I/O. Typically "LDS" and "STS" combined with "SBRS", "SBRC", "SBR", and "CBR". .include "m2560def.inc" .def temp =r16 .def row =r17 .def col =r18 .def mask =r19 .def temp2 =r20 .equ PORTLDIR = 0xF0 .equ INITCOLMASK = 0xEF .equ INITROWMASK = 0x01 .equ ROWMASK = 0x0F .cseg jmp RESET .org 0x72 RESET: ldi temp, low(RAMEND) out SPL, temp ldi temp, high(RAMEND) out SPH, temp ldi temp, PORTLDIR ; columns are outputs, rows are inputs STS DDRL, temp ; cannot use out ser temp out DDRC, temp ; Make PORTC all outputs out PORTC, temp ; Turn on all the LEDs ; main keeps scanning the keypad to find which key is pressed. main: ldi mask, INITCOLMASK ; initial column mask clr col ; initial column colloop: STS PORTL, mask ; set column to mask value ; (sets column 0 off) ldi temp, 0xFF ; implement a delay so the ; hardware can stabilize delay: dec temp brne delay LDS temp, PINL ; read PORTL. Cannot use in andi temp, ROWMASK ; read only the row bits cpi temp, 0xF ; check if any rows are grounded breq nextcol ; if not go to the next column ldi mask, INITROWMASK ; initialise row check clr row ; initial row rowloop: mov temp2, temp and temp2, mask ; check masked bit brne skipconv ; if the result is non-zero, ; we need to look again rcall convert ; if bit is clear, convert the bitcode jmp main ; and start again skipconv: inc row ; else move to the next row lsl mask ; shift the mask to the next bit jmp rowloop nextcol: cpi col, 3 ; check if we are on the last column breq main ; if so, no buttons were pushed, ; so start again. ; else shift the column mask: sec ; We must set the carry bit rol mask ; and then rotate left by a bit, ; shifting the carry into ; bit zero. We need this to make ; sure all the rows have ; pull-up resistors inc col ; increment column value jmp colloop ; and check the next column ; convert function converts the row and column given to a ; binary number and also outputs the value to PORTC. ; Inputs come from registers row and col and output is in ; temp. convert: cpi col, 3 ; if column is 3 we have a letter breq letters cpi row, 3 ; if row is 3 we have a symbol or 0 breq symbols mov temp, row ; otherwise we have a number (1-9) lsl temp ; temp = row * 2 add temp, row ; temp = row * 3 add temp, col ; add the column address ; to get the offset from 1 inc temp ; add 1. Value of switch is ; row*3 + col + 1. jmp convert_end letters: ldi temp, 0xA add temp, row ; increment from 0xA by the row value jmp convert_end symbols: cpi col, 0 ; check if we have a star breq star cpi col, 1 ; or if we have zero breq zero ldi temp, 0xF ; we'll output 0xF for hash jmp convert_end star: ldi temp, 0xE ; we'll output 0xE for star jmp convert_end zero: clr temp ; set to zero convert_end: out PORTC, temp ; write value to PORTC ret ; return to caller