calc.4th 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. \ simple calculator
  2. base @ decimal
  3. 30 constant box-width
  4. 30 constant box-height
  5. : draw-box ( x y -- )
  6. lcd-move-to lcd-black
  7. box-width box-height lcd-box
  8. ;
  9. : (highlight-box) ( x y -- )
  10. lcd-move-to
  11. 1 1 lcd-move-rel
  12. box-width 2 - box-height 2 - lcd-box
  13. 1 1 lcd-move-rel
  14. box-width 4 - box-height 4 - lcd-box
  15. ;
  16. : highlight-box ( x y -- )
  17. lcd-black (highlight-box)
  18. ;
  19. : unhighlight-box ( x y -- )
  20. lcd-white (highlight-box)
  21. lcd-black
  22. ;
  23. : within-box ( x y x0 y0 x1 y1 -- flag )
  24. swap >r rot >r \ x y y0 y1
  25. within \ x flag
  26. swap r> r> \ flag x x0 x1
  27. within and
  28. ;
  29. 48 constant y-offset
  30. 4 font-width * constant x-offset
  31. create positions
  32. \ x is multiple of font-width
  33. 0 font-width * x-offset + c, 0 y-offset + c, char 1 c, bl c,
  34. 4 font-width * x-offset + c, 0 y-offset + c, char 2 c, bl c,
  35. 8 font-width * x-offset + c, 0 y-offset + c, char 3 c, bl c,
  36. 12 font-width * x-offset + c, 0 y-offset + c, char + c, bl c,
  37. 16 font-width * x-offset + c, 0 y-offset + c, char C c, bl c,
  38. 0 font-width * x-offset + c, 32 y-offset + c, char 4 c, bl c,
  39. 4 font-width * x-offset + c, 32 y-offset + c, char 5 c, bl c,
  40. 8 font-width * x-offset + c, 32 y-offset + c, char 6 c, bl c,
  41. 12 font-width * x-offset + c, 32 y-offset + c, char - c, bl c,
  42. 16 font-width * x-offset + c, 32 y-offset + c, char M c, char C c,
  43. 0 font-width * x-offset + c, 64 y-offset + c, char 7 c, bl c,
  44. 4 font-width * x-offset + c, 64 y-offset + c, char 8 c, bl c,
  45. 8 font-width * x-offset + c, 64 y-offset + c, char 9 c, bl c,
  46. 12 font-width * x-offset + c, 64 y-offset + c, char * c, bl c,
  47. 16 font-width * x-offset + c, 64 y-offset + c, char M c, char + c,
  48. 0 font-width * x-offset + c, 96 y-offset + c, char . c, bl c,
  49. 4 font-width * x-offset + c, 96 y-offset + c, char 0 c, bl c,
  50. 8 font-width * x-offset + c, 96 y-offset + c, char = c, bl c,
  51. 12 font-width * x-offset + c, 96 y-offset + c, char / c, bl c,
  52. 16 font-width * x-offset + c, 96 y-offset + c, char M c, char R c,
  53. 20 constant position-count
  54. : box-data ( u -- x y c1 c2 )
  55. dup 0< if drop 0 then
  56. dup position-count < 0= if
  57. drop 0
  58. then
  59. 2* 2* positions + dup c@
  60. swap char+ dup c@
  61. swap char+ dup c@
  62. swap char+ c@
  63. ;
  64. : inside-box ( x y u -- flag )
  65. box-data 2drop \ x y x0 y0
  66. over box-width + \ x y x0 y0 x1
  67. over box-height + \ x y x0 y0 x1 yi
  68. within-box
  69. ;
  70. variable v-sign
  71. variable v-int
  72. variable v-frac
  73. variable v-point
  74. variable v-op
  75. variable total-sign
  76. variable total-int
  77. variable total-frac
  78. variable mem-sign
  79. variable mem-int
  80. variable mem-frac
  81. variable auto-clear
  82. \ define 8.8 number
  83. 99999999 constant v-max
  84. v-max 1+ constant v-overflow
  85. 8 constant int-digits
  86. 8 constant frac-digits
  87. : half-add ( carry u1 u2 -- u carry )
  88. + + dup v-max > if
  89. v-max - 1- 1
  90. else
  91. 0
  92. then
  93. ;
  94. : half-sub ( borrow u1 u2 -- u borrow )
  95. - swap - dup 0< if
  96. v-max + 1+ 1
  97. else
  98. 0
  99. then
  100. ;
  101. : add ( -- )
  102. v-sign @ total-sign @ =
  103. if
  104. 0 total-frac @ v-frac @ half-add \ frac carry
  105. total-int @ v-int @ half-add \ overflow
  106. if
  107. 2drop v-max v-max
  108. then
  109. else
  110. total-int @ v-int @ 2dup < if
  111. 2drop true
  112. else
  113. = if
  114. total-frac @ v-frac @ <
  115. then
  116. then
  117. if
  118. 0 v-frac @ total-frac @ half-sub \ frac borrow
  119. v-int @ total-int @ half-sub
  120. v-sign @ total-sign !
  121. else
  122. 0 total-frac @ v-frac @ half-sub \ frac borrow
  123. total-int @ v-int @ half-sub
  124. then
  125. drop
  126. then
  127. 2dup or 0= if
  128. false total-sign !
  129. then
  130. total-int !
  131. total-frac !
  132. ;
  133. : mem-add ( -- )
  134. total-sign @ mem-sign @ =
  135. if
  136. 0 mem-frac @ total-frac @ half-add \ frac carry
  137. mem-int @ total-int @ half-add \ overflow
  138. if
  139. 2drop v-max v-max
  140. then
  141. else
  142. mem-int @ total-int @ 2dup < if
  143. 2drop true
  144. else
  145. = if
  146. mem-frac @ total-frac @ <
  147. then
  148. then
  149. if
  150. 0 total-frac @ mem-frac @ half-sub \ frac borrow
  151. total-int @ mem-int @ half-sub
  152. total-sign @ mem-sign !
  153. else
  154. 0 mem-frac @ total-frac @ half-sub \ frac borrow
  155. mem-int @ total-int @ half-sub
  156. then
  157. drop
  158. then
  159. 2dup or 0= if
  160. false mem-sign !
  161. then
  162. mem-int !
  163. mem-frac !
  164. ;
  165. : sub ( -- )
  166. v-sign @ dup invert v-sign !
  167. add
  168. v-sign !
  169. ;
  170. : mul ( -- )
  171. total-sign @ v-sign @ <> total-sign !
  172. total-frac @ v-frac @ um*
  173. v-overflow fm/mod
  174. total-int @ v-frac @ um*
  175. v-overflow fm/mod
  176. >r +
  177. total-frac @ v-int @ um*
  178. v-overflow fm/mod
  179. >r +
  180. s>d v-overflow fm/mod
  181. total-int @ v-int @ um*
  182. v-overflow fm/mod
  183. >r + r> swap
  184. r> + r> +
  185. s>d v-overflow fm/mod
  186. rot +
  187. if
  188. 2drop
  189. v-max v-max
  190. then
  191. total-int !
  192. total-frac !
  193. v-overflow 2/ > if
  194. total-frac @ 1+ v-max > if
  195. total-int @ 1+ v-max > if
  196. v-max v-max
  197. total-int !
  198. total-frac !
  199. else
  200. 0 total-frac !
  201. 1 total-int +!
  202. then
  203. else
  204. 1 total-frac +!
  205. then
  206. then
  207. ;
  208. variable r-int
  209. variable r-frac
  210. variable rs-int
  211. variable rs-frac
  212. variable q-int
  213. variable q-frac
  214. : div-gr ( -- flag )
  215. r-int @ total-int @ >
  216. if
  217. true exit
  218. then
  219. r-int @ total-int @ =
  220. r-frac @ total-frac @ > and
  221. ;
  222. : div-q*10 ( -- )
  223. q-frac @ 10 *
  224. s>d v-overflow fm/mod
  225. q-int @ 10 * +
  226. q-int ! q-frac !
  227. ;
  228. : div-r*10 ( -- )
  229. r-frac @ 10 *
  230. s>d v-overflow fm/mod
  231. r-int @ 10 * +
  232. r-int ! r-frac !
  233. ;
  234. : div-t*10 ( -- )
  235. total-frac @ 10 *
  236. s>d v-overflow fm/mod
  237. total-int @ 10 * +
  238. total-int ! total-frac !
  239. ;
  240. : div ( -- )
  241. v-int @ v-frac @ or 0=
  242. if
  243. v-max v-max
  244. total-int !
  245. total-frac !
  246. exit
  247. then
  248. total-int @ total-frac @ or 0=
  249. if
  250. exit
  251. then
  252. v-sign @ total-sign @ xor total-sign !
  253. v-int @ dup r-int ! rs-int !
  254. v-frac @ dup r-frac ! rs-frac !
  255. 0 q-int ! 0 q-frac !
  256. \ shift count
  257. div-gr if
  258. 1
  259. else
  260. 0
  261. then
  262. begin
  263. div-gr 0=
  264. while
  265. r-frac @ rs-frac !
  266. r-int @ rs-int !
  267. div-r*10
  268. 1+
  269. repeat
  270. rs-frac @ r-frac !
  271. rs-int @ r-int !
  272. \ loop count on stack
  273. frac-digits +
  274. 0 ?do
  275. div-q*10
  276. begin
  277. 0 total-frac @ r-frac @ half-sub
  278. total-int @ r-int @ half-sub 0=
  279. while
  280. total-int !
  281. total-frac !
  282. 1 q-frac +! \ never gets bigger than 9 so no need for carry
  283. repeat
  284. 2drop
  285. div-t*10
  286. loop
  287. q-frac @ total-frac !
  288. q-int @ total-int !
  289. ;
  290. : output-number ( frac int sign x y -- )
  291. lcd-at-xy
  292. if
  293. [char] -
  294. else
  295. bl
  296. then
  297. lcd-emit
  298. 8 lcd-u.r
  299. [char] . lcd-emit
  300. s>d <# # # # # # # # # #> lcd-type
  301. ;
  302. : refresh-display ( -- )
  303. total-frac @
  304. total-int @
  305. total-sign @
  306. 5 1 output-number
  307. lcd-space [char] T lcd-emit
  308. v-frac @
  309. v-int @
  310. v-sign @
  311. 5 2 output-number
  312. 26 1 lcd-at-xy
  313. v-op @
  314. case
  315. -1 of bl endof
  316. 0 of bl endof
  317. 1 of [char] + endof
  318. 2 of [char] - endof
  319. 3 of [char] * endof
  320. 4 of [char] / endof
  321. endcase
  322. lcd-emit
  323. mem-frac @
  324. mem-int @
  325. mem-sign @
  326. 5 lcd-text-rows 2 - output-number
  327. lcd-space [char] M lcd-emit
  328. ;
  329. : clear-mem ( -- )
  330. false mem-sign !
  331. 0 mem-int !
  332. 0 mem-frac !
  333. ;
  334. : clear-entry ( -- )
  335. false v-sign !
  336. 0 v-int !
  337. 0 v-frac !
  338. 0 v-point !
  339. false auto-clear !
  340. v-op @ -1 = if
  341. 0 v-op !
  342. then
  343. ;
  344. : clear-all ( -- )
  345. clear-entry
  346. 0 v-op !
  347. false total-sign !
  348. 0 total-int !
  349. 0 total-frac !
  350. ;
  351. : recall-mem ( -- )
  352. clear-entry
  353. mem-sign @ v-sign !
  354. mem-int @ v-int !
  355. mem-frac @ v-frac !
  356. ;
  357. : copy-to-total ( -- )
  358. v-sign @ total-sign !
  359. v-int @ total-int !
  360. v-frac @ total-frac !
  361. ;
  362. : new-digit ( u -- )
  363. auto-clear @ if
  364. clear-entry
  365. then
  366. v-point @ if
  367. v-point @ 0> if
  368. v-point @ 10 / dup
  369. 0= if
  370. drop -1 v-point !
  371. else
  372. dup v-point !
  373. * v-frac +!
  374. then
  375. then
  376. else
  377. v-int @ 10 * + dup v-max > if
  378. drop v-max
  379. then
  380. v-int !
  381. then
  382. ;
  383. : operator-set ( u -- )
  384. v-op @
  385. case
  386. 0 of copy-to-total endof
  387. 1 of add endof
  388. 2 of sub endof
  389. 3 of mul endof
  390. 4 of div endof
  391. endcase
  392. v-op !
  393. true auto-clear !
  394. ;
  395. : process ( u -- )
  396. case
  397. 0 of \ 1
  398. 1 new-digit
  399. endof
  400. 1 of \ 2
  401. 2 new-digit
  402. endof
  403. 2 of \ 3
  404. 3 new-digit
  405. endof
  406. 3 of \ +
  407. 1 operator-set
  408. endof
  409. 4 of \ C
  410. clear-all
  411. endof
  412. 5 of \ 4
  413. 4 new-digit
  414. endof
  415. 6 of \ 5
  416. 5 new-digit
  417. endof
  418. 7 of \ 6
  419. 6 new-digit
  420. endof
  421. 8 of \ -
  422. 2 operator-set
  423. endof
  424. 9 of \ MC
  425. clear-mem
  426. endof
  427. 10 of \ 7
  428. 7 new-digit
  429. endof
  430. 11 of \ 8
  431. 8 new-digit
  432. endof
  433. 12 of \ 9
  434. 9 new-digit
  435. endof
  436. 13 of \ *
  437. 3 operator-set
  438. endof
  439. 14 of \ M+
  440. mem-add
  441. endof
  442. 15 of \ .
  443. auto-clear @ if
  444. clear-entry
  445. then
  446. v-overflow v-point !
  447. endof
  448. 16 of \ 0
  449. 0 new-digit
  450. endof
  451. 17 of \ =
  452. -1 operator-set
  453. endof
  454. 18 of \ /
  455. 4 operator-set
  456. endof
  457. 19 of \ MR
  458. recall-mem
  459. endof
  460. endcase
  461. refresh-display
  462. ;
  463. variable down
  464. variable box-number
  465. variable can-exit
  466. : calculator ( -- )
  467. lcd-cls
  468. button-flush
  469. key-flush
  470. ctp-flush
  471. can-exit @ if
  472. 24 lcd-text-rows 1- lcd-at-xy s" Exit" lcd-type
  473. then
  474. position-count 0 ?do
  475. i box-data >r >r 2dup draw-box
  476. 8 + >r font-width + r> lcd-move-to
  477. r> lcd-emit r> lcd-emit
  478. loop
  479. false down !
  480. refresh-display
  481. -1 box-number !
  482. begin
  483. ctp-pos? if
  484. ctp-pos dup 0<
  485. if
  486. 2drop
  487. down @ if
  488. box-number @ dup
  489. box-data 2drop
  490. unhighlight-box
  491. 1 1 lcd-at-xy 2 lcd-spaces
  492. 0 0 unhighlight-box
  493. process
  494. -1 box-number !
  495. then
  496. false down !
  497. else
  498. position-count 0 ?do
  499. 2dup i inside-box if
  500. true down !
  501. box-number @ 0< 0=
  502. box-number @ i <> and
  503. if
  504. box-number @
  505. box-data 2drop
  506. 1 1 lcd-at-xy 2 lcd-spaces
  507. unhighlight-box
  508. 0 0 unhighlight-box
  509. then
  510. i dup box-number !
  511. box-data
  512. swap 1 1 lcd-at-xy lcd-emit lcd-emit
  513. highlight-box
  514. 0 0 highlight-box
  515. then
  516. loop
  517. 2drop
  518. then
  519. then
  520. key? if
  521. key-flush
  522. then
  523. button? if
  524. button
  525. case
  526. button-left of
  527. endof
  528. button-centre of
  529. endof
  530. button-right of
  531. can-exit @ if
  532. exit
  533. then
  534. endof
  535. button-power of
  536. power-off
  537. endof
  538. endcase
  539. then
  540. wait-for-event
  541. again
  542. ;
  543. base !