prjbrook

forth85_12C

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