prjbrook

forth85_12 eeprom, eHERE etc

Jul 20th, 2014
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 26.70 KB | None | 0 0
  1. ;this is forth85_12
  2. ;Task. Start compiler. First to eeprom system variables like HERE.
  3. ;Did a lot of work relating to eeprom variables, eHERE and eLATEST
  4. .NOLIST
  5. .include "tn85def.inc"
  6. .LIST
  7. .LISTMAC ;sometimes macro code gets in way of clarity in listing
  8. .MACRO header
  9. .db high(@0), low(@0), @1, @2
  10. .ENDMACRO
  11. .MACRO mypop
  12. ld @0,-y
  13. .ENDMACRO
  14. .MACRO mypush
  15. st y+, @0
  16. .ENDMACRO
  17. .MACRO mypop2
  18. mypop @0
  19. mypop @1
  20. .ENDMACRO
  21. .MACRO mypush2
  22. mypush @0
  23. mypush @1
  24. .ENDMACRO
  25. .MACRO pushx
  26. push xl
  27. push xh
  28. .ENDMACRO
  29. .MACRO popx
  30. pop xh
  31. pop xl
  32. .ENDMACRO
  33. .MACRO pushz
  34. push zl
  35. push zh
  36. .ENDMACRO
  37. .MACRO popz
  38. pop zh
  39. pop zl
  40. .ENDMACRO
  41. .MACRO mypopa ;call r16,17 the accumulator a, ditto for r18,r19 for b
  42. mypop r17
  43. mypop r16
  44. .ENDMACRO
  45. .MACRO mypopb
  46. mypop2 r19,r18
  47. .ENDMACRO
  48.  
  49.  
  50.  
  51. .def FOUND = r15 ;if found=1 we have a match of Ram word on dictionary
  52. .def BOTTOM = r14 ;have hit the bottom of the dict and not found a match
  53. .def STOP = r13 ;stop interpreting line of words
  54. .def STATE = r12
  55. .def FOUNDCOUNTER = r11 ;dealWithWord clicks this if found =1. Counts successful finds in dictionary.
  56. .def SECONDLETTER =r10 ;helpful for debugging
  57. .def vl = r22
  58. .def vh = r23 ; u,v,w,x,y,z are all pointers
  59. .DSEG
  60. .ORG 0x60
  61.  
  62. ;consts: .DB "jksdafhsdf",8, 255, 0b01010101, -128, 0xaa
  63. .equ BUF1LENGTH = 64
  64. .equ eHERE = $0010 ;eeprom adr of system varial eHere
  65. .equ eLATEST = $0012
  66.  
  67. buf1: .byte BUF1LENGTH
  68. buf2: .byte 64 ;could have third buffer?
  69. varSpace: .byte 64 ;might need more than 32 variables
  70. ;.org 0x1E0
  71. myStackStart: .byte 64
  72.  
  73. .cseg
  74. .ORG 0x800 ;dictionary starts at 4K (2K words) mark
  75. ;----------------------------------------------------
  76. one_1:
  77. .db 0,0,3, "one" ;code for one
  78. one:
  79. ; rcall stackme
  80. rcall stackme_2
  81. .db 01, 00
  82. ret
  83. ;----------------------------------------------
  84. two_1:
  85. header one_1, 3, "two"
  86. two:
  87. rcall stackme_2
  88. .db 02,00
  89. ret
  90. ;------------------------------------------
  91. dup_1:
  92. header two_1,3,"dup"
  93. dup:
  94. mypop r17
  95. mypop r16
  96. mypush r16
  97. mypush r17
  98. mypush r16
  99. mypush r17
  100.  
  101. ret
  102. ;-------------------------------------------
  103. drop_1:
  104. header dup_1,4,"drop"
  105. drop:
  106. mypop r17
  107. mypop r16 ;TODO what if stack pointer goes thru floor?
  108. ret
  109. ;----------------------------------
  110. swapp_1: ;twp p's becasue assembler recognizes avr opcode swap
  111. header drop_1,5, "swapp"
  112. swapp:
  113. mypop2 r17,r16
  114. mypop2 r19,r18
  115. mypush2 r16,r17
  116. mypush2 r18,r19
  117. ret
  118.  
  119.  
  120. ;-------------------------------------------------
  121. ;shift this later
  122.  
  123. S_1:
  124. ;the EOL token that gets put into end of buf1 to stop parsing
  125. header swapp_1,1,"S"
  126. S: ldi r16,02
  127. mov BOTTOM,r16 ;r14 =2 means a nice stop. EOL without errors
  128. clr STOP
  129. inc STOP ;set time-to-quit flag
  130. ret
  131. ;------------------------------------------
  132.  
  133. fetch_1: ;doesn't like label = @-1
  134. ;classic fetch. (adr -- num). Only in RAM
  135. header S_1,1,"@"
  136. fetch:
  137. pushx ;going to use x to point so better save
  138. mypop xh
  139. mypop xl
  140. ld r16,x+
  141. ld r17,x
  142. mypush r16
  143. mypush r17 ; and put them on my stack
  144. popx ;return with x intact and RAM val on my stack
  145. ret
  146. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  147.  
  148. cfetch_1: ;doesn't like label = c@-1
  149. ;classic fetch. (adr -- num). Only in RAM. Do I want y to advance just one byte on mystack
  150. header fetch_1,2,"c@"
  151. cfetch:
  152. pushx ;going to use x to point so better save
  153. mypop xh
  154. mypop xl
  155. ld r16,x+
  156. mypush r16
  157. popx ;return with x intact and RAM val on my stack
  158. ret
  159. ;dddddddddddddddddddddddddddddddddddddddddddddddd
  160.  
  161. store_1: ;classic != "store"(adr num --) . Num is now at cell adr.
  162. header cfetch_1,1,"!"
  163. store:
  164. mypop2 r17,r16 ;there goes the num
  165. pushx
  166. mypop2 xh,xl ;there goes the address
  167. st x+,r16
  168. st x,r17 ;num goes to cell with location=adr
  169. popx
  170. ret
  171. ;ddddddddddddddddddddddddddddddddddddddddddddddddddd
  172.  
  173. cstore_1: ;classic c!= "store"(adr 8-bitnum --) . 8 bit Num is now at cell adr.
  174. header store_1,2,"c!"
  175. cstore:
  176. mypop r16 ;there goes the num. Just 8 bits at this stage.
  177. pushx
  178. mypop2 xh,xl ;there goes the address
  179. st x+,r16
  180. ; st x,r17 ;num goes to cell with location=adr
  181. popx
  182. ret
  183. ;------------------------------------
  184.  
  185. star_1: ;classic 16*16 mulitply (n n -- n*n)
  186. header cstore_1,1,"*"
  187. star:
  188. mypop2 r17,r16
  189. mypop2 r19,r18 ;now have both numbers in r16..r19
  190. rcall mpy16s ; multiply them. Result in r18..r21. Overflow in r20,21
  191. mypush2 r18,r19
  192. ret
  193. ;-----------------------------------------
  194.  
  195. slashMod_1: ;classic /MOD (n m -- n/m rem)
  196. header star_1,4,"/mod"
  197. slashMod:
  198. mypop2 r19,r18 ; that's m
  199. mypop2 r17,r16 ;that's n
  200. rcall div16s ;the the 16 by 16 bit divsion
  201. mypush2 r16,r17 ;answer ie n/m
  202. mypush2 r14,r15 ;remainder
  203. ret
  204. ;dddddddddddddddddddddddddddddddddddddddddddd
  205.  
  206. plus_1: ;classic + ( n n -- n+n)
  207. header slashMod_1,1,"+"
  208. plus:
  209. mypop2 r17,r16
  210. mypop2 r19,r18
  211. clc
  212. add r16,r18
  213. adc r17,r19
  214. mypush2 r16,r17
  215. ret
  216. ;--
  217.  
  218. minus_1: ;classic - ( n m -- n-m)
  219. header plus_1,1,"-"
  220. minus:
  221. mypop2 r19,r18
  222. mypop2 r17,r16
  223. clc
  224. sub r16,r18
  225. sbc r17,r19
  226. mypush2 r16,r17
  227. ret
  228. ;dddddddddddddddddddddddddddddddddddddddddd
  229.  
  230. pstore_1: ;expects eg. 0003 PORTB P! etc, "output 3 via PORTB"
  231. header minus_1,2, "p!"
  232. pstore:
  233. mypopb ;get rid of PORTB number, not used for tiny85, just one port
  234. mypopa ; this is used. it's eg the 003 = R16 above
  235. out PORTB,r16
  236. ret
  237. ;ddddddddddddddddddddddddd
  238.  
  239. portblabel_1:
  240. header pstore_1,5,"PORTB" ; note caps just a filler that point 0b in stack for dropping
  241. portblabel:
  242. ; Extend later on to include perhaps other ports
  243. ; one:
  244. ; rcall stackme
  245.  
  246. rcall stackme_2
  247. .db $0b, 00
  248. ret
  249. ;---------------------
  250.  
  251. datadirstore_1: ;set ddrb. invioked like this 000f PORTB dd! to make pb0..pb3 all outputs
  252. header portblabel_1, 3, "dd!"
  253. datadirstore:
  254. mypopb ; there goes useless 0b = PORTB
  255. mypopa ; 000f now in r17:16
  256. out DDRB,r16
  257. ret
  258. ;dddddddddddddddddddddddddddddddddddd
  259. ;sbilabel_1 ;set bit in PORTB. Just a kludge at this stage
  260. ;header datadirstore_1,3,"sbi" TODO sort out sbi and delay later. Now get on with compiler.
  261. ;first need store system vars in the eeprom. Arbitrarily 0010 is HERE and 0012 (in eeprom) is LATEST
  262. ;----------------------------------------
  263.  
  264. percentcstore_1: ;(adr16 n16 --) %c! stores stack val LSbyte to eeprom adr
  265. ; eg 10 00 1234 stores 34 to 0010 <--eeprom adr
  266. header datadirstore_1,3,"%c!"
  267. percentcstore:
  268. mypopa ;data. Lower byte into r16
  269. mypopb ;adr in r18,19
  270. rcall eewritebyte ;burn it into eeprom
  271. ret
  272. ;----------------------------------
  273.  
  274. percentstore_1: ; (adr16 n16 --) b16 stored at eeprom adr adr16 and adr16+1
  275. header percentcstore_1,2, "%!"
  276. percentstore:
  277. mypopa ;n16 into r16,17 as data
  278. mypopb ;adr in b=r18,19
  279. rcall eewritebyte ;burn low data byte
  280. clc
  281. inc r18
  282. brne outpcs
  283. inc r17 ;sets up adr+1 for next byte
  284. outpcs:
  285. mov r16,r17 ;r16 now conatins hi byte
  286. rcall eewritebyte
  287. ret
  288. ;-------------------------------
  289.  
  290. percentcfetch_1: ;(eepromadr16--char). Fetch eeprom byte at adr on stack
  291. header percentstore_1,3,"%c@"
  292. percentcfetch:
  293. mypopb ;adr now in r18,19
  294. rcall eereadbyte
  295. mypush r16 ; there's the char going on stack. Should be n16? Not n8?
  296. ret
  297. ;-------------------
  298.  
  299. percentfetch_1: ;(adr16--n16) get 16bits at adr and adr+1
  300. header percentcfetch_1,2,"%@"
  301. percentfetch:
  302. rcall percentcfetch ;low byte now on stack
  303. inc r18
  304. brcc downpf
  305. inc r19
  306. downpf:
  307. rcall eereadbyte ;there's the high byte hitting the mystack
  308. mypush r16
  309. ret
  310. ;-------------------------------
  311. gethere_1: ; leaves current value of eHERE on stack
  312. header percentfetch_1,7,"gethere"
  313. gethere:
  314. rcall stackme_2
  315. .dw eHere
  316. rcall percentfetch
  317. ret
  318. ;--------------------
  319. LATEST:
  320. getlatest_1: ;leaves current value of latest on stack
  321. header gethere_1,9, "getlatest"
  322. getlatest:
  323. rcall stackme_2
  324. .dw eLATEST ;the address of the latest link lives in eeprom at address 0012
  325. rcall percentfetch ;get the val out of eeprom
  326. ret
  327. ;------------------
  328. HERE:
  329. nop
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.  
  340.  
  341.  
  342.  
  343.  
  344. ;-------------------------------------------------
  345. stackme_2: ;stacks on my stack next 16bit num. Address of 16bit number is on SP-stack
  346. ; Used like this stackme_2 0034. Puts 0034 on myStack and increments past number on return stack.
  347. pop r17
  348. pop r16 ; they now contain eg 0x0804 which contain the 16bit num
  349. movw zl,r16 ;z now points to cell that cobtains the number
  350. clc
  351. rol zl
  352. rol zh ;double word address for z. lpm coming up
  353.  
  354.  
  355.  
  356. lpm r16,z+
  357. lpm r17,z+ ;now have 16bit number in r16,17
  358.  
  359. st y+,r16
  360. st y+, r17 ;mystack now contains the number
  361.  
  362. clc
  363. ror zh
  364. ror zl ;halve the z pointer to step past the number to return at the right place
  365.  
  366. push zl
  367. push zh
  368.  
  369. ret
  370.  
  371.  
  372.  
  373. ;====================================================================================================
  374.  
  375. .ORG 0
  376. rjmp start
  377. typein: .db "0012 abcd %! getlatest",$0d, "0013 %@",0x0d
  378. ;" one 0010 00ab %c! 0012 cdef %! 0013 %c@ 0013 %@ 0987 drop ", 0x0d
  379.  
  380. ;stackme dropx onex stackme swap drop",0x0d
  381. start:
  382. ldi r16, low(RAMEND)
  383. out SPL, r16
  384. ldi r16,high(RAMEND)
  385. out SPH, r16
  386.  
  387. ldi YL,low(myStackStart)
  388. ldi YH,high(myStackStart)
  389.  
  390. ;rjmp test_interpretLine
  391. ;rjmp test_cfetch
  392. ;rjmp test_store
  393. ;rjmp test_cstore
  394. ;rjmp test_mpy16s
  395. ;rjmp test_mpy16s0
  396. ;rjmp test_star
  397. ;rjmp test_div16s
  398. ;rjmp test_slashMod
  399. ;rjmp test_Hex4ToBin2
  400. rjmp test_interpretLine
  401.  
  402. rjmp start
  403.  
  404. getline0: ;force a line into buf1 via flash string. Simulates GETLINE
  405. ldi zl, low(typein<<1)
  406. ldi zh, high(typein<<1)
  407. ldi xl, low(buf1)
  408. ldi xh, high(buf1)
  409. type0:
  410. lpm r16,Z+
  411. st x+,r16
  412. cpi r16,0x0d ;have we got to the end of the line?
  413. brne type0
  414. ret
  415. ;--------------------------------------------
  416. ;WORD gets x to point to start of word (copy in w=r24,25) with the length in len = r20
  417. ;assume word points to somewhere in buf1. Should advance thru spaces=0x20 to first real char
  418. word: ;maybe give it a header later
  419. ld r16,x+ ;get char
  420. ld SECONDLETTER, x ;for debugging
  421.  
  422. cpi r16,0x20 ;is it a space?
  423. breq word ;if so get next char
  424. ;if here we're point to word start. so save this adr in w
  425. mov r24,xl
  426. mov r25,xh ;wordstart now saved in w
  427.  
  428.  
  429. clr r20 ;length initially 0
  430. nextchar:
  431. inc r20 ;r20 = word length
  432. ld r16,x+ ;get next char
  433. cpi r16,0x20
  434. brne nextchar
  435. dec r24 ;adjust start of word
  436. ;if here we've found a word.Starting at w length in r20.x points to space just past word
  437. ret
  438. ;----------------------------------------
  439.  
  440. compare: ;given a word in buf1 and a word in the dic are they the same? The word in the dic is pointed to by Z.
  441. ; and the word in buf1 is pointed to by w=r24,25. len = r20. Z on entry points to the link. Needs +2 to
  442. lpm r23,z+
  443. lpm r22,z+ ;store next link in v=r22,23. z now points to len byte
  444.  
  445. startc:
  446. push r20 ;save length
  447. lpm r16,Z+ ;length of dictionary word, first entry now in r16
  448. cp r16,r20 ;same lengths?
  449. brne outcom ;not = so bail out
  450. ;if here the words are the same length, what about the rest of the chars.First get x to point to word.
  451. mov xl,r24
  452. mov xh,r25 ;x now point to start of buf1 word
  453. upcom:
  454. lpm r16,z+
  455. ld r17,x+ ;get one corresponding char from each word
  456. cp r16,r17 ;same word?
  457. brne outcom ;bail out if chars are different
  458. dec r20 ;count chars
  459. brne upcom ;still matching and not finished so keep going
  460. ;if here r20 is 0 so match must have been perfect so FOUND = 1
  461. clr FOUND
  462. inc FOUND
  463. outcom:
  464. pop r20 ;get old lngth of buf1 word back
  465. ret
  466. ;-------------------------------------------
  467. jmpNextWord: ;go to next word in the dictionary. Assume v=r22,23 contains next link word(not byte)
  468. ; and w = r24,25 contains RAM word start with len in r20
  469. ;exit with z pointing to next word ready for next COMPARE.
  470. clc
  471. rol r22
  472. rol r23 ;above 3 instructions change word address into byte address by doubling
  473. movw r30,r22 ;z now points to next word
  474. ret
  475. ;-----------------------------------------
  476.  
  477. doLatest: ;set up so first jump in dictionary is to top=LATEST and other flags set up.
  478. ldi vl, low(LATEST)
  479. ldi vh, high(LATEST)
  480. clr FOUND
  481. clr BOTTOM ;not yet found the match, not yet at the bottom. Either will stop search.
  482. clr STOP ;keep parsing words til this goes to a 1
  483. ret
  484. ;---------------------------------------------
  485. interpretLine: ;given line of words in buf one, search for words one by one. Don't do code
  486. ; or compile at this stage, just find and report that and go into next one.
  487. rcall getline0 ;change later to real getline via terminal
  488. rcall pasteEOL
  489. ldi xl, low(buf1)
  490. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  491. clr FOUNDCOUNTER ;counts finds in line parsing.
  492.  
  493. nextWord:
  494. tst STOP
  495. brne stopLine
  496. rcall word
  497. rcall findWord ;not done yet
  498. rcall dealWithWord ;go and run code STATE=0, or compile (STATE =1).{ c0de, comp1le}
  499. rjmp nextWord
  500. stopLine:
  501. ret
  502. ;-----------------------------------------------------------------
  503. findWord:
  504. rcall doLatest
  505. upjmpf:
  506. rcall jmpNextWord
  507. rcall compare
  508. tst FOUND
  509. brne stopsearchf ;if last compare got a match (FOUND=1) then stop searching
  510. tst vl
  511. brne upjmpf ;if v=0000 then we've hit the bottom of the dictionary
  512. tst vh
  513. brne upjmpf ;not found and not at bottom so keep going
  514. ;if here FOUND =0, ie no match yet and we've hit the bottom of the dictionary
  515. clr BOTTOM
  516. inc BOTTOM ;exit with FOUND=0 and BOTTOM =1
  517. stopsearchf: nop
  518. ret
  519. ;----------------------------
  520. test_interpretLine:
  521. rcall interpretLine
  522. til: rjmp til ;** with r24 pointing to 'S' and FOUND = r15 =1
  523. ;------------------------------
  524. dealWithWord: ;come here when it's time to compile or run code
  525. ;Good debugging spot. Enter here with Z pointing to CFA of word found. Y points to myStack. X points to just
  526. ; past the word we are seeking (w-s). r10 is 2nd letter of w-s. w = start adr of w-s. v is a link
  527. ; to the next word in dic. Either just below the found word or 0000 if we get to the bottome with no match
  528. ;
  529. nop
  530. tst FOUND
  531. breq notfound
  532. inc FOUNDCOUNTER
  533.  
  534. ;want to hop over filler bytes,0's added to keep codes on even byte boundaries
  535. ; so if r30 is odd at this stage inc it. odd is lsbit = 1.
  536. sbrs r30,0 ;skip next instruction if final bit lsb = 1
  537. rjmp downdw
  538. ;if here lsb = 1 so we're on a padding byte and have to add 1 to get to a 2 byte boundary
  539. inc r30
  540. brcc downdw
  541. inc r31 ;add one to z before converting to bytes
  542.  
  543. downdw:
  544. clc
  545. ror zh
  546. ror zl ;put z back into word values
  547.  
  548.  
  549. rcall executeCode
  550.  
  551.  
  552.  
  553. .MESSAGE "Word found"
  554. rjmp outdww
  555. notfound:
  556. nop
  557. ; .MESSAGE "Word not found"
  558. ; clr STOP
  559. ; inc STOP ;stop parsing line
  560. rcall numberh ; word not in dict so must be a number? Form = HHHH
  561. ;now have to add 3 to x so it points past this word ready not next one
  562. clc
  563. inc r26
  564. inc r26
  565. inc r26
  566. brcc outdww
  567. inc r27 ;but only if overflow
  568. nop
  569. outdww:
  570. ret ;with STOP =1 in not a number
  571. ;------------------------------------------------------------------------
  572. pasteEOL: ;when a line of text is TYPEd into buf1 it should end with CR=$0d. This gets replaced with ]}, a
  573. ; special end of line word. When the word is invoked it casues a QUIT back to the waiting for input stage.
  574. ; Start at buf1 start and inspect each char for a $0D. When found replace with a "$20 S $20 "
  575. ldi xl, low(buf1)
  576. ldi xh, high(buf1) ;pnt to start of buffer
  577. clr r17
  578. nxtChar:
  579. inc r17 ;r17 is counter. Bail out when r17 > BUF1LENGTH
  580. cpi r17, BUF1LENGTH -3
  581. breq outProb
  582. ld r16, x+
  583. cpi r16, $0d
  584. brne nxtChar
  585. ;if here we've found a $0d in buf1 before the end, so replace with an EOL token. x points to just after it.
  586. ldi r16,$20
  587. st -x, r16 ;back up. Then go forward.
  588. ; ldi r16, ']'
  589. st x+, r16
  590. ldi r16,'S'
  591. st x+, r16
  592. ; ldi r16, '}'
  593. ; st x+, r16
  594. ldi r16, $20
  595. st x, r16
  596. rjmp outpel
  597.  
  598.  
  599. outProb:
  600. nop
  601. .MESSAGE "Couldn't find $0d"
  602. outpel:
  603. ret
  604.  
  605. ;-------------------------------------
  606. executeCode: ;with Z pointing to cfa. Not sure whether to jmp or call
  607.  
  608. ijmp
  609. ret
  610. ;---------------------------------------
  611. test_fetch: ;do run thru of @
  612. rcall getline0 ;change later to real getline via terminal
  613. rcall pasteEOL
  614. ldi xl, low(buf1)
  615. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  616.  
  617. ldi r16,$62
  618. mypush r16
  619. ldi r16,$0
  620. mypush r16 ;should now have adr $0062 on mystack
  621. rcall fetch
  622. tf1:
  623. rjmp tf1
  624. ;---------------------------------
  625. test_cfetch: ;do run thru of @
  626. rcall getline0 ;change later to real getline via terminal
  627. rcall pasteEOL
  628. ldi xl, low(buf1)
  629. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  630.  
  631. ldi r16,$62
  632. mypush r16
  633. ldi r16,$0
  634. mypush r16 ;should now have adr $62 on mystack
  635. rcall cfetch
  636. tcf1:
  637. rjmp tcf1
  638. ;----------------------------
  639. test_store:
  640. rcall getline0 ;change later to real getline via terminal
  641. rcall pasteEOL
  642. ldi xl, low(buf1)
  643. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  644. ldi r16,$62
  645. ldi r17,$0
  646. mypush2 r16,r17 ;should now have adr $62 on mystack
  647. ldi r16, $AB
  648. ldi r17, $CD
  649. mypush2 r16,r17 ;now have $ABCD on mystack
  650. rcall store
  651. ts1:
  652. rjmp ts1
  653. ;------------------------
  654. test_cstore:
  655. rcall getline0 ;change later to real getline via terminal
  656. rcall pasteEOL
  657. ldi xl, low(buf1)
  658. ldi xh,high(buf1) ;last 3 statemnts are done onece. Now the main loop.
  659. ldi r16,$62
  660. ldi r17,$0
  661. mypush2 r16,r17 ;should now have adr $62 on mystack
  662. ldi r16, $AB
  663. ; ldi r17, $CD
  664. mypush r16 ;now have $ABCD on mystack
  665. rcall cstore
  666.  
  667. ts11:
  668. rjmp ts11
  669. ;Now put arith routines here. Are from AVR200. Just using 16*16 for * but get 32bit result.
  670.  
  671.  
  672. ;***************************************************************************
  673. ;*
  674. ;* "mpy16s" - 16x16 Bit Signed Multiplication
  675. ;*
  676. ;* This subroutine multiplies signed the two 16-bit register variables
  677. ;* mp16sH:mp16sL and mc16sH:mc16sL.
  678. ;* The result is placed in m16s3:m16s2:m16s1:m16s0.
  679. ;* The routine is an implementation of Booth's algorithm. If all 32 bits
  680. ;* in the result are needed, avoid calling the routine with
  681. ;* -32768 ($8000) as multiplicand
  682. ;*
  683. ;* Number of words :16 + return
  684. ;* Number of cycles :210/226 (Min/Max) + return
  685. ;* Low registers used :None
  686. ;* High registers used :7 (mp16sL,mp16sH,mc16sL/m16s0,mc16sH/m16s1,
  687. ;* m16s2,m16s3,mcnt16s)
  688. ;*
  689. ;***************************************************************************
  690.  
  691. ;***** Subroutine Register Variables
  692.  
  693. .def mc16sL =r16 ;multiplicand low byte
  694. .def mc16sH =r17 ;multiplicand high byte
  695. .def mp16sL =r18 ;multiplier low byte
  696. .def mp16sH =r19 ;multiplier high byte
  697. .def m16s0 =r18 ;result byte 0 (LSB)
  698. .def m16s1 =r19 ;result byte 1
  699. .def m16s2 =r20 ;result byte 2
  700. .def m16s3 =r21 ;result byte 3 (MSB)
  701. .def mcnt16s =r22 ;loop counter
  702.  
  703. ;***** Code
  704. mpy16s: clr m16s3 ;clear result byte 3
  705. sub m16s2,m16s2 ;clear result byte 2 and carry
  706. ldi mcnt16s,16 ;init loop counter
  707. m16s_1: brcc m16s_2 ;if carry (previous bit) set
  708. add m16s2,mc16sL ; add multiplicand Low to result byte 2
  709. adc m16s3,mc16sH ; add multiplicand High to result byte 3
  710. m16s_2: sbrc mp16sL,0 ;if current bit set
  711. sub m16s2,mc16sL ; sub multiplicand Low from result byte 2
  712. sbrc mp16sL,0 ;if current bit set
  713. sbc m16s3,mc16sH ; sub multiplicand High from result byte 3
  714. asr m16s3 ;shift right result and multiplier
  715. ror m16s2
  716. ror m16s1
  717. ror m16s0
  718. dec mcnt16s ;decrement counter
  719. brne m16s_1 ;if not done, loop more
  720. ret
  721. ;----------------------------------------------------------
  722. ;***** Multiply Two Signed 16-Bit Numbers (-12345*(-4321))
  723. test_mpy16s:
  724. ldi mc16sL,low(-12345)
  725. ldi mc16sH,high(-12345)
  726. ldi mp16sL,low(-4321)
  727. ldi mp16sH,high(-4321)
  728. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  729. ;=$032df219 (53,342,745)
  730. tmpy: rjmp tmpy
  731.  
  732. test_mpy16s0:
  733. ldi mc16sL,low(123)
  734. ldi mc16sH,high(123)
  735. ldi mp16sL,low(147)
  736. ldi mp16sH,high(147)
  737. rcall mpy16s ;result: m16s3:m16s2:m16s1:m16s0
  738. tmpy0: rjmp tmpy0
  739. ;-----------------------
  740. test_star:
  741. ldi r16,-$7b
  742. mypush r16
  743. ldi r16,$00
  744. mypush r16 ;that's decimal 123 on stack
  745. ldi r16,$93
  746. mypush r16
  747. ldi r16,$00
  748. mypush r16 ; and thats dec'147
  749. rcall star
  750. tsr: rjmp tsr
  751.  
  752. ;--------------------------
  753. ;***************************************************************************
  754. ;*
  755. ;* "div16s" - 16/16 Bit Signed Division
  756. ;*
  757. ;* This subroutine divides signed the two 16 bit numbers
  758. ;* "dd16sH:dd16sL" (dividend) and "dv16sH:dv16sL" (divisor).
  759. ;* The result is placed in "dres16sH:dres16sL" and the remainder in
  760. ;* "drem16sH:drem16sL".
  761. ;*
  762. ;* Number of words :39
  763. ;* Number of cycles :247/263 (Min/Max)
  764. ;* Low registers used :3 (d16s,drem16sL,drem16sH)
  765. ;* High registers used :7 (dres16sL/dd16sL,dres16sH/dd16sH,dv16sL,dv16sH,
  766. ;* dcnt16sH)
  767. ;*
  768. ;***************************************************************************
  769.  
  770. ;***** Subroutine Register Variables
  771.  
  772. .def d16s =r13 ;sign register
  773. .def drem16sL=r14 ;remainder low byte
  774. .def drem16sH=r15 ;remainder high byte
  775. .def dres16sL=r16 ;result low byte
  776. .def dres16sH=r17 ;result high byte
  777. .def dd16sL =r16 ;dividend low byte
  778. .def dd16sH =r17 ;dividend high byte
  779. .def dv16sL =r18 ;divisor low byte
  780. .def dv16sH =r19 ;divisor high byte
  781. .def dcnt16s =r20 ;loop counter
  782.  
  783. ;***** Code
  784.  
  785. div16s: mov d16s,dd16sH ;move dividend High to sign register
  786. eor d16s,dv16sH ;xor divisor High with sign register
  787. sbrs dd16sH,7 ;if MSB in dividend set
  788. rjmp d16s_1
  789. com dd16sH ; change sign of dividend
  790. com dd16sL
  791. subi dd16sL,low(-1)
  792. sbci dd16sL,high(-1)
  793. d16s_1: sbrs dv16sH,7 ;if MSB in divisor set
  794. rjmp d16s_2
  795. com dv16sH ; change sign of divisor
  796. com dv16sL
  797. subi dv16sL,low(-1)
  798. sbci dv16sL,high(-1)
  799. d16s_2: clr drem16sL ;clear remainder Low byte
  800. sub drem16sH,drem16sH;clear remainder High byte and carry
  801. ldi dcnt16s,17 ;init loop counter
  802.  
  803. d16s_3: rol dd16sL ;shift left dividend
  804. rol dd16sH
  805. dec dcnt16s ;decrement counter
  806. brne d16s_5 ;if done
  807. sbrs d16s,7 ; if MSB in sign register set
  808. rjmp d16s_4
  809. com dres16sH ; change sign of result
  810. com dres16sL
  811. subi dres16sL,low(-1)
  812. sbci dres16sH,high(-1)
  813. d16s_4: ret ; return
  814. d16s_5: rol drem16sL ;shift dividend into remainder
  815. rol drem16sH
  816. sub drem16sL,dv16sL ;remainder = remainder - divisor
  817. sbc drem16sH,dv16sH ;
  818. brcc d16s_6 ;if result negative
  819. add drem16sL,dv16sL ; restore remainder
  820. adc drem16sH,dv16sH
  821. clc ; clear carry to be shifted into result
  822. rjmp d16s_3 ;else
  823. d16s_6: sec ; set carry to be shifted into result
  824. rjmp d16s_3
  825.  
  826. ;-----------------------------------------------
  827.  
  828. test_div16s:
  829. ;***** Divide Two Signed 16-Bit Numbers (-22,222/10)
  830. ldi dd16sL,low(-22222)
  831. ldi dd16sH,high(-22222)
  832. ldi dv16sL,low(10)
  833. ldi dv16sH,high(10)
  834. rcall div16s ;result: $f752 (-2222)
  835. ;remainder: $0002 (2)
  836.  
  837. forever:rjmp forever
  838. ;----------------------------------
  839. test_slashMod:
  840. ldi r16,$12
  841. mypush r16
  842. ldi r16,$34
  843. mypush r16
  844. ldi r16,$56 ;NB this is $3412 not $1234
  845. mypush r16
  846. ldi r16,$00
  847. mypush r16
  848. rcall slashMod ;$3412 / $56 = $9b rem 0 works
  849. tslm: rjmp tslm
  850.  
  851. ;---------------------------------------
  852. ;From http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#hex2bin
  853. ; Hex4ToBin2
  854. ; converts a 4-digit-hex-ascii to a 16-bit-binary
  855. ; In: Z points to first digit of a Hex-ASCII-coded number
  856. ; Out: T-flag has general result:
  857. ; T=0: rBin1H:L has the 16-bit-binary result, Z points
  858. ; to the first digit of the Hex-ASCII number
  859. ; T=1: illegal character encountered, Z points to the
  860. ; first non-hex-ASCII character
  861. ; Used registers: rBin1H:L (result), R0 (restored after
  862. ; use), rmp
  863. ; Called subroutines: Hex2ToBin1, Hex1ToBin1
  864.  
  865. .def rBin1H =r17
  866. .def rBin1L = r16
  867. .def rmp = r18
  868. ;
  869. Hex4ToBin2:
  870. clt ; Clear error flag
  871. rcall Hex2ToBin1 ; convert two digits hex to Byte
  872. brts Hex4ToBin2a ; Error, go back
  873. mov rBin1H,rmp ; Byte to result MSB
  874. rcall Hex2ToBin1 ; next two chars
  875. brts Hex4ToBin2a ; Error, go back
  876. mov rBin1L,rmp ; Byte to result LSB
  877. sbiw ZL,4 ; result ok, go back to start
  878. Hex4ToBin2a:
  879. ret
  880. ;
  881. ; Hex2ToBin1 converts 2-digit-hex-ASCII to 8-bit-binary
  882. ; Called By: Hex4ToBin2
  883. ;
  884. Hex2ToBin1:
  885. push R0 ; Save register
  886. rcall Hex1ToBin1 ; Read next char
  887. brts Hex2ToBin1a ; Error
  888. swap rmp; To upper nibble
  889. mov R0,rmp ; interim storage
  890. rcall Hex1ToBin1 ; Read another char
  891. brts Hex2ToBin1a ; Error
  892. or rmp,R0 ; pack the two nibbles together
  893. Hex2ToBin1a:
  894. pop R0 ; Restore R0
  895. ret ; and return
  896. ;
  897. ; Hex1ToBin1 reads one char and converts to binary
  898. ;
  899. Hex1ToBin1:
  900. ld rmp,z+ ; read the char
  901. subi rmp,'0' ; ASCII to binary
  902. brcs Hex1ToBin1b ; Error in char
  903. cpi rmp,10 ; A..F
  904. brcs Hex1ToBin1c ; not A..F
  905. cpi rmp,$30 ; small letters?
  906. brcs Hex1ToBin1a ; No
  907. subi rmp,$20 ; small to capital letters
  908. Hex1ToBin1a:
  909. subi rmp,7 ; A..F
  910. cpi rmp,10 ; A..F?
  911. brcs Hex1ToBin1b ; Error, is smaller than A
  912. cpi rmp,16 ; bigger than F?
  913. brcs Hex1ToBin1c ; No, digit ok
  914. Hex1ToBin1b: ; Error
  915. sbiw ZL,1 ; one back
  916. set ; Set flag
  917. Hex1ToBin1c:
  918. ret ; Return
  919. ;--------------------------------------
  920. test_Hex4ToBin2:
  921. pushz
  922. ldi zl,$60
  923. clr zh ;z now points to start of buf1
  924. ldi r16,'0'
  925. st z+,r16
  926. ldi r16,'f'
  927. st z+,r16
  928. ldi r16,'2'
  929. st z+,r16
  930. ldi r16,'3'
  931. st z+,r16
  932. ldi zl,$60
  933. clr zh ;z now points back to start of buf1
  934. rcall Hex4ToBin2
  935. popz
  936. th4: rjmp th4
  937. ;-------------------------------------
  938. numberh: ;word not in dictionary. Try to convert it to hex.
  939. pushz ;algorithm uses z, pity
  940. movw zl,r24 ;r4,25 = w holds start of current word
  941. ;z now points eg to '12ab'start. If t=0 then it coverts to real hex
  942. rcall hex4ToBin2 ;try to convert
  943. ;above call needs 4 hex digits to emerge with t=0 and binary in r16,17
  944. ;want this. If t=0 stack r16,17 and carry on interpreting, else emerge with
  945. ; t=1 and zpointing to first problem char
  946. brtc gotHex
  947. ; if here there's a problem that z is pointing to. Bail out of interpret line
  948. clr STOP
  949. inc STOP
  950. rjmp outnh
  951.  
  952. gotHex: ;sucess.Real hex in r16,17
  953. mypush2 r16,r17 ; so push num onto mystack
  954. outnh:
  955. popz ; but will it be pointing to "right"place in buf1? Yes now OK
  956.  
  957. ret
  958. ; numberh not working fully, ie doesn't point to right place after action.
  959. ; also no action if not a number? DONE better save this first.
  960. ;---------------------------------
  961. ;eeroutines
  962. eewritebyte: ;write what's in r16 to eeprom adr in r18,19
  963. sbic EECR,EEPE
  964. rjmp eewritebyte ;keep looping til ready to write
  965. ;if here the previous write is all done and we can write the next byte to eeprom
  966. out EEARH,r19
  967. out EEARL,r18 ;adr done
  968. out EEDR,r16 ;byte in right place now
  969. sbi EECR,EEMPE
  970. sbi EECR,EEPE ;last 2 instruc write eprom. Takes 3.4 ms
  971. ret
  972. ;test with %!
  973. ;---------------------------------
  974. eereadbyte: ; read eeprom byte at adr in r18,19 into r16
  975. ; Wait for completion of previous write
  976. sbic EECR,EEPE
  977. rjmp eereadbyte
  978. ; Set up address (r18:r17) in address register
  979. out EEARH, r19
  980. out EEARL, r18
  981. ; Start eeprom read by writing EERE
  982. sbi EECR,EERE
  983. ; Read data from data register
  984. in r16,EEDR
  985. ret
  986. ;------------------------------
Advertisement
Add Comment
Please, Sign In to add comment