Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Q3.asm
- *
- * Created: 12/10/2017 4:34:06 PM
- * Author: Michael
- */
- .include "m2560def.inc"
- ; Delay Constants
- .equ F_CPU = 16000000
- .equ DELAY_1MS = F_CPU / 4 / 1000 - 4 ; 4 cycles per iteration - setup/call-return overhead
- ; LCD Instructions
- .equ LCD_RS = 7
- .equ LCD_E = 6
- .equ LCD_RW = 5
- .equ LCD_BE = 4
- .macro do_lcd_command
- ldi r16, @0
- rcall lcd_command
- rcall lcd_wait
- .endmacro
- .macro do_lcd_data
- ldi r16, @0
- rcall lcd_data
- rcall lcd_wait
- .endmacro
- .macro do_lcd_data_register
- mov r16, @0
- rcall lcd_data
- rcall lcd_wait
- .endmacro
- .macro lcd_set
- sbi PORTA, @0
- .endmacro
- .macro lcd_clr
- cbi PORTA, @0
- .endmacro
- .def row = r17 ; current row number
- .def col = r18 ; current column number
- .def rmask = r19 ; mask for current row during scan
- .def cmask = r20 ; mask for current column during scan
- .def temp1 = r21 ; general use temp register
- .def temp2 = r22 ; general use temp register
- .def temp3 = r23
- .equ PORTLDIR = 0xF0 ; PL7-4: output, PL3-0, input
- .equ INITCOLMASK = 0xEF ; scan from the rightmost column,
- .equ INITROWMASK = 0x01 ; scan from the top row
- .equ ROWMASK = 0x0F ; for obtaining input from Port L
- ; Calculator
- .def current = r0
- .def sum = r2
- .cseg
- .org 0x0000
- jmp RESET
- jmp DEFAULT ; No handling for IRQ0
- jmp DEFAULT ; No handling for IRQ1
- DEFAULT:
- reti
- RESET:
- ldi r16, low(RAMEND)
- out SPL, r16
- ldi r16, high(RAMEND)
- out SPH, r16
- ser r16 ; set PORTF and PORTA to output
- out DDRF, r16
- out DDRA, r16
- clr r16
- out PORTF, r16
- out PORTA, r16
- ldi temp1, PORTLDIR ; columns are outputs, rows are inputs
- sts DDRL, temp1 ; cannot use out
- do_lcd_command 0b00111000 ; 2 lines of 5x7
- rcall sleep_5ms
- do_lcd_command 0b00111000 ; 2 lines of 5x7
- rcall sleep_1ms
- do_lcd_command 0b00111000 ; 2 lines of 5x7
- do_lcd_command 0b00111000 ; 2 lines of 5x7
- do_lcd_command 0b00001000 ; display off?
- do_lcd_command 0b00000001 ; clear display
- do_lcd_command 0b00000110 ; increment, no display shift
- do_lcd_command 0b00001110 ; Cursor on, bar, no blink
- clr sum
- clr current
- rjmp main
- main:
- ldi cmask, INITCOLMASK ; initial column mask
- clr col ; initial column
- rjmp colloop
- colloop:
- cpi col, 4 ; compare current column # to total # columns
- breq main ; if all keys are scanned, repeat
- sts PORTL, cmask ; otherwise, scan a column
- ldi temp1, 0xFF ; slow down the scan operation to debounce button press
- delay:
- rcall sleep_1ms
- dec temp1
- brne delay
- lds temp1, PINL ; read PORTL
- andi temp1, ROWMASK ; get the keypad output value
- cpi temp1, 0xF0 ; check if any row is low (0)
- breq colloop ; if yes, find which row is low
- ldi rmask, INITROWMASK ; initialize rmask with 0000 0001 for row check
- clr row
- rowloop:
- cpi row, 4 ; compare current value of row with total number of rows (4)
- breq nextcol ; if theyre equal, the row scan is over.
- mov temp2, temp1 ; temp1 is 0xF
- and temp2, rmask ; check un-masked bit
- breq convert ; if bit is clear, the key is pressed
- inc row ; else move to the next row
- lsl rmask ; shift row mask left by one
- jmp rowloop
- nextcol: ; if row scan is over
- lsl cmask ; shift column mask left by one
- inc col ; increase column value
- jmp colloop ; go to the next column
- convert:
- cpi col, 3 ; if the pressed key is in col.3
- breq letters ; we have a letter
- cpi row, 3 ; if the key is not in col 3 and is in row3,
- breq symbols ; we have a symbol or 0
- mov temp1, row ; otherwise we have a number in 1-9
- lsl temp1 ; multiply temp1 by 2
- add temp1, row ; add row again to temp1 -> temp1 = row * 3
- add temp1, col ; temp1 = col*3 + row
- inc temp1
- number:
- ldi temp2, 10
- mul current, temp2
- add current, temp1
- subi temp1, -'0'
- do_lcd_data_register temp1
- jmp main
- letters:
- cpi row, 2
- breq equals
- cpi row, 1
- breq subtraction
- cpi row, 0
- breq addition
- jmp main
- symbols:
- cpi col, 1
- breq zero
- jmp main
- equals:
- do_lcd_data '='
- jmp printResult
- jmp stop
- stop:
- rjmp stop
- addition:
- add sum, current
- clr current
- mov temp1, sum
- do_lcd_data '+'
- jmp main
- subtraction:
- sub sum, current
- clr current
- mov temp1, sum
- do_lcd_data '-'
- jmp main
- zero:
- ldi temp1, 0
- jmp number
- lcd_command:
- out PORTF, r16
- rcall sleep_1ms
- lcd_set LCD_E
- rcall sleep_1ms
- lcd_clr LCD_E
- rcall sleep_1ms
- ret
- lcd_data:
- out PORTF, r16
- lcd_set LCD_RS
- rcall sleep_1ms
- lcd_set LCD_E
- rcall sleep_1ms
- lcd_clr LCD_E
- rcall sleep_1ms
- lcd_clr LCD_RS
- ret
- lcd_wait:
- push r16
- clr r16
- out DDRF, r16
- out PORTF, r16
- lcd_set LCD_RW
- lcd_wait_loop:
- rcall sleep_1ms
- lcd_set LCD_E
- rcall sleep_1ms
- in r16, PINF
- lcd_clr LCD_E
- sbrc r16, 7
- rjmp lcd_wait_loop
- lcd_clr LCD_RW
- ser r16
- out DDRF, r16
- pop r16
- ret
- sleep_1ms:
- push r24
- push r25
- ldi r25, high(DELAY_1MS)
- ldi r24, low(DELAY_1MS)
- delayloop_1ms:
- sbiw r25:r24, 1
- brne delayloop_1ms
- pop r25
- pop r24
- ret
- sleep_5ms:
- rcall sleep_1ms
- rcall sleep_1ms
- rcall sleep_1ms
- rcall sleep_1ms
- rcall sleep_1ms
- ret
- sleep_25ms:
- rcall sleep_5ms
- rcall sleep_5ms
- rcall sleep_5ms
- rcall sleep_5ms
- rcall sleep_5ms
- ret
- printResult:
- push temp2
- hundreds:
- clr temp2
- clr temp3
- hundredsCount:
- ldi temp1, 100
- cp sum, temp1
- brlo printHundreds
- ldi temp2, 100
- sub sum, temp2
- inc temp3
- jmp hundredsCount
- printHundreds:
- cpi temp3, 0
- breq tens
- subi temp3, -'0'
- do_lcd_data_register temp3
- tens:
- clr temp2
- clr temp3
- tensCount:
- ldi temp1, 10
- cp sum, temp1
- brlo printTens
- ldi temp2, 10
- sub sum, temp2
- inc temp3
- jmp tensCount
- printTens:
- subi temp3, -'0'
- do_lcd_data_register temp3
- ones:
- mov temp1, sum
- subi temp1, -'0'
- do_lcd_data_register temp1
- epilogue:
- pop temp2
- rcall sleep_25ms
- ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement