Advertisement
Guest User

Untitled

a guest
Oct 13th, 2017
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.44 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement