SHARE
TWEET

Untitled

a guest Oct 13th, 2017 58 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * Q3.asm
  3.  *
  4.  *  Created: 12/10/2017 4:34:06 PM
  5.  *   Author: Michael
  6.  */
  7.  
  8.  
  9. .include "m2560def.inc"
  10.  
  11. ; Delay Constants
  12. .equ F_CPU = 16000000
  13. .equ DELAY_1MS = F_CPU / 4 / 1000 - 4       ; 4 cycles per iteration - setup/call-return overhead
  14.  
  15. ; LCD Instructions
  16. .equ LCD_RS = 7
  17. .equ LCD_E = 6
  18. .equ LCD_RW = 5
  19. .equ LCD_BE = 4
  20.  
  21. .macro do_lcd_command
  22.     ldi r16, @0
  23.     rcall lcd_command
  24.     rcall lcd_wait
  25. .endmacro
  26.  
  27. .macro do_lcd_data
  28.     ldi r16, @0
  29.     rcall lcd_data
  30.     rcall lcd_wait
  31. .endmacro
  32.  
  33. .macro do_lcd_data_register
  34.     mov r16, @0
  35.     rcall lcd_data
  36.     rcall lcd_wait
  37. .endmacro
  38.  
  39. .macro lcd_set
  40.     sbi PORTA, @0
  41. .endmacro
  42.  
  43. .macro lcd_clr
  44.     cbi PORTA, @0
  45. .endmacro
  46.  
  47. .def row = r17                      ; current row number
  48. .def col = r18                      ; current column number
  49. .def rmask = r19                    ; mask for current row during scan
  50. .def cmask = r20                    ; mask for current column during scan
  51. .def temp1 = r21                    ; general use temp register
  52. .def temp2 = r22                    ; general use temp register
  53. .def temp3 = r23
  54.  
  55. .equ PORTLDIR = 0xF0                ; PL7-4: output, PL3-0, input
  56. .equ INITCOLMASK = 0xEF             ; scan from the rightmost column,
  57. .equ INITROWMASK = 0x01             ; scan from the top row
  58. .equ ROWMASK  = 0x0F                ; for obtaining input from Port L
  59.  
  60. ; Calculator
  61. .def current = r0
  62. .def sum = r2
  63.  
  64.  
  65. .cseg
  66. .org 0x0000
  67.     jmp RESET
  68.     jmp DEFAULT         ; No handling for IRQ0
  69.     jmp DEFAULT         ; No handling for IRQ1
  70.  
  71. DEFAULT:
  72.     reti
  73.  
  74. RESET:
  75.     ldi r16, low(RAMEND)
  76.     out SPL, r16
  77.     ldi r16, high(RAMEND)
  78.     out SPH, r16
  79.  
  80.     ser r16                         ; set PORTF and PORTA to output
  81.     out DDRF, r16
  82.     out DDRA, r16
  83.     clr r16                    
  84.     out PORTF, r16
  85.     out PORTA, r16
  86.  
  87.     ldi temp1, PORTLDIR             ; columns are outputs, rows are inputs
  88.     sts DDRL, temp1                 ; cannot use out
  89.  
  90.     do_lcd_command 0b00111000       ; 2 lines of 5x7
  91.     rcall sleep_5ms
  92.     do_lcd_command 0b00111000       ; 2 lines of 5x7
  93.     rcall sleep_1ms
  94.     do_lcd_command 0b00111000       ; 2 lines of 5x7
  95.     do_lcd_command 0b00111000       ; 2 lines of 5x7
  96.     do_lcd_command 0b00001000       ; display off?
  97.     do_lcd_command 0b00000001       ; clear display
  98.     do_lcd_command 0b00000110       ; increment, no display shift
  99.     do_lcd_command 0b00001110       ; Cursor on, bar, no blink
  100.  
  101.     clr sum
  102.     clr current
  103.  
  104.     rjmp main
  105.  
  106. main:
  107.     ldi cmask, INITCOLMASK          ; initial column mask
  108.     clr col                         ; initial column
  109.     rjmp colloop
  110.  
  111. colloop:
  112.     cpi col, 4                                      ; compare current column # to total # columns
  113.     breq main                                       ; if all keys are scanned, repeat
  114.     sts PORTL, cmask                                ; otherwise, scan a column
  115.  
  116.     ldi temp1, 0xFF                                 ; slow down the scan operation to debounce button press
  117.     delay:
  118.     rcall sleep_1ms
  119.     dec temp1
  120.     brne delay
  121.  
  122.     lds temp1, PINL                                 ; read PORTL
  123.     andi temp1, ROWMASK                             ; get the keypad output value
  124.     cpi temp1, 0xF0                                 ; check if any row is low (0)
  125.     breq colloop                                    ; if yes, find which row is low
  126.     ldi rmask, INITROWMASK                          ; initialize rmask with 0000 0001 for row check
  127.     clr row
  128.  
  129. rowloop:
  130.     cpi row, 4                                      ; compare current value of row with total number of rows (4)
  131.     breq nextcol                                    ; if theyre equal, the row scan is over.
  132.     mov temp2, temp1                                ; temp1 is 0xF
  133.     and temp2, rmask                                ; check un-masked bit
  134.     breq convert                                    ; if bit is clear, the key is pressed
  135.     inc row                                         ; else move to the next row
  136.     lsl rmask                                       ; shift row mask left by one
  137.     jmp rowloop
  138.  
  139. nextcol:                                            ; if row scan is over
  140.     lsl cmask                                       ; shift column mask left by one
  141.     inc col                                         ; increase column value
  142.     jmp colloop                                     ; go to the next column
  143.  
  144. convert:
  145.     cpi col, 3                                      ; if the pressed key is in col.3
  146.     breq letters                                    ; we have a letter
  147.     cpi row, 3                                      ; if the key is not in col 3 and is in row3,
  148.     breq symbols                                    ; we have a symbol or 0
  149.     mov temp1, row                                  ; otherwise we have a number in 1-9
  150.     lsl temp1                                       ; multiply temp1 by 2
  151.     add temp1, row                                  ; add row again to temp1 -> temp1 = row * 3
  152.     add temp1, col                                  ; temp1 = col*3 + row
  153.     inc temp1
  154.  
  155. number:
  156.     ldi temp2, 10
  157.     mul current, temp2
  158.     add current, temp1
  159.     subi temp1, -'0'
  160.     do_lcd_data_register temp1
  161.     jmp main
  162.  
  163. letters:
  164.     cpi row, 2
  165.     breq equals
  166.     cpi row, 1
  167.     breq subtraction
  168.     cpi row, 0
  169.     breq addition
  170.     jmp main
  171.  
  172. symbols:
  173.     cpi col, 1                     
  174.     breq zero
  175.     jmp main
  176.  
  177. equals:
  178.     do_lcd_data '='
  179.     jmp printResult
  180.     jmp stop
  181.  
  182. stop:
  183.     rjmp stop
  184.  
  185. addition:
  186.     add sum, current       
  187.     clr current
  188.     mov temp1, sum
  189.     do_lcd_data '+'
  190.     jmp main
  191.  
  192. subtraction:
  193.     sub sum, current
  194.     clr current
  195.     mov temp1, sum
  196.     do_lcd_data '-'
  197.     jmp main
  198.  
  199. zero:
  200.     ldi temp1, 0
  201.     jmp number
  202.  
  203. lcd_command:
  204.     out PORTF, r16
  205.     rcall sleep_1ms
  206.     lcd_set LCD_E
  207.     rcall sleep_1ms
  208.     lcd_clr LCD_E
  209.     rcall sleep_1ms
  210.     ret
  211.  
  212. lcd_data:
  213.     out PORTF, r16
  214.     lcd_set LCD_RS
  215.     rcall sleep_1ms
  216.     lcd_set LCD_E
  217.     rcall sleep_1ms
  218.     lcd_clr LCD_E
  219.     rcall sleep_1ms
  220.     lcd_clr LCD_RS
  221.     ret
  222.  
  223. lcd_wait:
  224.     push r16
  225.     clr r16
  226.     out DDRF, r16
  227.     out PORTF, r16
  228.     lcd_set LCD_RW
  229. lcd_wait_loop:
  230.     rcall sleep_1ms
  231.     lcd_set LCD_E
  232.     rcall sleep_1ms
  233.     in r16, PINF
  234.     lcd_clr LCD_E
  235.     sbrc r16, 7
  236.     rjmp lcd_wait_loop
  237.     lcd_clr LCD_RW
  238.     ser r16
  239.     out DDRF, r16
  240.     pop r16
  241.     ret
  242.  
  243. sleep_1ms:
  244.     push r24
  245.     push r25
  246.     ldi r25, high(DELAY_1MS)
  247.     ldi r24, low(DELAY_1MS)
  248. delayloop_1ms:
  249.     sbiw r25:r24, 1
  250.     brne delayloop_1ms
  251.     pop r25
  252.     pop r24
  253.     ret
  254.  
  255. sleep_5ms:
  256.     rcall sleep_1ms
  257.     rcall sleep_1ms
  258.     rcall sleep_1ms
  259.     rcall sleep_1ms
  260.     rcall sleep_1ms
  261.     ret
  262.  
  263. sleep_25ms:
  264.     rcall sleep_5ms
  265.     rcall sleep_5ms
  266.     rcall sleep_5ms
  267.     rcall sleep_5ms
  268.     rcall sleep_5ms
  269.     ret
  270.  
  271.  
  272. printResult:
  273.     push temp2
  274.        
  275.     hundreds:
  276.         clr temp2                          
  277.         clr temp3
  278.  
  279.         hundredsCount:
  280.             ldi temp1, 100
  281.             cp sum, temp1      
  282.             brlo printHundreds
  283.            
  284.             ldi temp2, 100  
  285.             sub sum, temp2
  286.             inc temp3
  287.             jmp hundredsCount
  288.        
  289.         printHundreds:
  290.             cpi temp3, 0
  291.             breq tens
  292.  
  293.             subi temp3, -'0'
  294.             do_lcd_data_register temp3
  295.        
  296.     tens:
  297.         clr temp2  
  298.         clr temp3
  299.        
  300.         tensCount:
  301.             ldi temp1, 10
  302.             cp sum, temp1      
  303.             brlo printTens
  304.            
  305.             ldi temp2, 10              
  306.             sub sum, temp2
  307.             inc temp3
  308.             jmp tensCount
  309.            
  310.         printTens:
  311.             subi temp3, -'0'
  312.             do_lcd_data_register temp3
  313.    
  314.     ones:              
  315.         mov temp1, sum                     
  316.         subi temp1, -'0'                           
  317.         do_lcd_data_register temp1
  318.  
  319.     epilogue:
  320.     pop temp2
  321.     rcall sleep_25ms
  322.     ret
RAW Paste Data
Top