123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 |
- \ simple calculator
- base @ decimal
- 30 constant box-width
- 30 constant box-height
- : draw-box ( x y -- )
- lcd-move-to lcd-black
- box-width box-height lcd-box
- ;
- : (highlight-box) ( x y -- )
- lcd-move-to
- 1 1 lcd-move-rel
- box-width 2 - box-height 2 - lcd-box
- 1 1 lcd-move-rel
- box-width 4 - box-height 4 - lcd-box
- ;
- : highlight-box ( x y -- )
- lcd-black (highlight-box)
- ;
- : unhighlight-box ( x y -- )
- lcd-white (highlight-box)
- lcd-black
- ;
- : within-box ( x y x0 y0 x1 y1 -- flag )
- swap >r rot >r \ x y y0 y1
- within \ x flag
- swap r> r> \ flag x x0 x1
- within and
- ;
- 48 constant y-offset
- 4 font-width * constant x-offset
- create positions
- \ x is multiple of font-width
- 0 font-width * x-offset + c, 0 y-offset + c, char 1 c, bl c,
- 4 font-width * x-offset + c, 0 y-offset + c, char 2 c, bl c,
- 8 font-width * x-offset + c, 0 y-offset + c, char 3 c, bl c,
- 12 font-width * x-offset + c, 0 y-offset + c, char + c, bl c,
- 16 font-width * x-offset + c, 0 y-offset + c, char C c, bl c,
- 0 font-width * x-offset + c, 32 y-offset + c, char 4 c, bl c,
- 4 font-width * x-offset + c, 32 y-offset + c, char 5 c, bl c,
- 8 font-width * x-offset + c, 32 y-offset + c, char 6 c, bl c,
- 12 font-width * x-offset + c, 32 y-offset + c, char - c, bl c,
- 16 font-width * x-offset + c, 32 y-offset + c, char M c, char C c,
- 0 font-width * x-offset + c, 64 y-offset + c, char 7 c, bl c,
- 4 font-width * x-offset + c, 64 y-offset + c, char 8 c, bl c,
- 8 font-width * x-offset + c, 64 y-offset + c, char 9 c, bl c,
- 12 font-width * x-offset + c, 64 y-offset + c, char * c, bl c,
- 16 font-width * x-offset + c, 64 y-offset + c, char M c, char + c,
- 0 font-width * x-offset + c, 96 y-offset + c, char . c, bl c,
- 4 font-width * x-offset + c, 96 y-offset + c, char 0 c, bl c,
- 8 font-width * x-offset + c, 96 y-offset + c, char = c, bl c,
- 12 font-width * x-offset + c, 96 y-offset + c, char / c, bl c,
- 16 font-width * x-offset + c, 96 y-offset + c, char M c, char R c,
- 20 constant position-count
- : box-data ( u -- x y c1 c2 )
- dup 0< if drop 0 then
- dup position-count < 0= if
- drop 0
- then
- 2* 2* positions + dup c@
- swap char+ dup c@
- swap char+ dup c@
- swap char+ c@
- ;
- : inside-box ( x y u -- flag )
- box-data 2drop \ x y x0 y0
- over box-width + \ x y x0 y0 x1
- over box-height + \ x y x0 y0 x1 yi
- within-box
- ;
- variable v-sign
- variable v-int
- variable v-frac
- variable v-point
- variable v-op
- variable total-sign
- variable total-int
- variable total-frac
- variable mem-sign
- variable mem-int
- variable mem-frac
- variable auto-clear
- \ define 8.8 number
- 99999999 constant v-max
- v-max 1+ constant v-overflow
- 8 constant int-digits
- 8 constant frac-digits
- : half-add ( carry u1 u2 -- u carry )
- + + dup v-max > if
- v-max - 1- 1
- else
- 0
- then
- ;
- : half-sub ( borrow u1 u2 -- u borrow )
- - swap - dup 0< if
- v-max + 1+ 1
- else
- 0
- then
- ;
- : add ( -- )
- v-sign @ total-sign @ =
- if
- 0 total-frac @ v-frac @ half-add \ frac carry
- total-int @ v-int @ half-add \ overflow
- if
- 2drop v-max v-max
- then
- else
- total-int @ v-int @ 2dup < if
- 2drop true
- else
- = if
- total-frac @ v-frac @ <
- then
- then
- if
- 0 v-frac @ total-frac @ half-sub \ frac borrow
- v-int @ total-int @ half-sub
- v-sign @ total-sign !
- else
- 0 total-frac @ v-frac @ half-sub \ frac borrow
- total-int @ v-int @ half-sub
- then
- drop
- then
- 2dup or 0= if
- false total-sign !
- then
- total-int !
- total-frac !
- ;
- : mem-add ( -- )
- total-sign @ mem-sign @ =
- if
- 0 mem-frac @ total-frac @ half-add \ frac carry
- mem-int @ total-int @ half-add \ overflow
- if
- 2drop v-max v-max
- then
- else
- mem-int @ total-int @ 2dup < if
- 2drop true
- else
- = if
- mem-frac @ total-frac @ <
- then
- then
- if
- 0 total-frac @ mem-frac @ half-sub \ frac borrow
- total-int @ mem-int @ half-sub
- total-sign @ mem-sign !
- else
- 0 mem-frac @ total-frac @ half-sub \ frac borrow
- mem-int @ total-int @ half-sub
- then
- drop
- then
- 2dup or 0= if
- false mem-sign !
- then
- mem-int !
- mem-frac !
- ;
- : sub ( -- )
- v-sign @ dup invert v-sign !
- add
- v-sign !
- ;
- : mul ( -- )
- total-sign @ v-sign @ <> total-sign !
- total-frac @ v-frac @ um*
- v-overflow fm/mod
- total-int @ v-frac @ um*
- v-overflow fm/mod
- >r +
- total-frac @ v-int @ um*
- v-overflow fm/mod
- >r +
- s>d v-overflow fm/mod
- total-int @ v-int @ um*
- v-overflow fm/mod
- >r + r> swap
- r> + r> +
- s>d v-overflow fm/mod
- rot +
- if
- 2drop
- v-max v-max
- then
- total-int !
- total-frac !
- v-overflow 2/ > if
- total-frac @ 1+ v-max > if
- total-int @ 1+ v-max > if
- v-max v-max
- total-int !
- total-frac !
- else
- 0 total-frac !
- 1 total-int +!
- then
- else
- 1 total-frac +!
- then
- then
- ;
- variable r-int
- variable r-frac
- variable rs-int
- variable rs-frac
- variable q-int
- variable q-frac
- : div-gr ( -- flag )
- r-int @ total-int @ >
- if
- true exit
- then
- r-int @ total-int @ =
- r-frac @ total-frac @ > and
- ;
- : div-q*10 ( -- )
- q-frac @ 10 *
- s>d v-overflow fm/mod
- q-int @ 10 * +
- q-int ! q-frac !
- ;
- : div-r*10 ( -- )
- r-frac @ 10 *
- s>d v-overflow fm/mod
- r-int @ 10 * +
- r-int ! r-frac !
- ;
- : div-t*10 ( -- )
- total-frac @ 10 *
- s>d v-overflow fm/mod
- total-int @ 10 * +
- total-int ! total-frac !
- ;
- : div ( -- )
- v-int @ v-frac @ or 0=
- if
- v-max v-max
- total-int !
- total-frac !
- exit
- then
- total-int @ total-frac @ or 0=
- if
- exit
- then
- v-sign @ total-sign @ xor total-sign !
- v-int @ dup r-int ! rs-int !
- v-frac @ dup r-frac ! rs-frac !
- 0 q-int ! 0 q-frac !
- \ shift count
- div-gr if
- 1
- else
- 0
- then
- begin
- div-gr 0=
- while
- r-frac @ rs-frac !
- r-int @ rs-int !
- div-r*10
- 1+
- repeat
- rs-frac @ r-frac !
- rs-int @ r-int !
- \ loop count on stack
- frac-digits +
- 0 ?do
- div-q*10
- begin
- 0 total-frac @ r-frac @ half-sub
- total-int @ r-int @ half-sub 0=
- while
- total-int !
- total-frac !
- 1 q-frac +! \ never gets bigger than 9 so no need for carry
- repeat
- 2drop
- div-t*10
- loop
- q-frac @ total-frac !
- q-int @ total-int !
- ;
- : output-number ( frac int sign x y -- )
- lcd-at-xy
- if
- [char] -
- else
- bl
- then
- lcd-emit
- 8 lcd-u.r
- [char] . lcd-emit
- s>d <# # # # # # # # # #> lcd-type
- ;
- : refresh-display ( -- )
- total-frac @
- total-int @
- total-sign @
- 5 1 output-number
- lcd-space [char] T lcd-emit
- v-frac @
- v-int @
- v-sign @
- 5 2 output-number
- 26 1 lcd-at-xy
- v-op @
- case
- -1 of bl endof
- 0 of bl endof
- 1 of [char] + endof
- 2 of [char] - endof
- 3 of [char] * endof
- 4 of [char] / endof
- endcase
- lcd-emit
- mem-frac @
- mem-int @
- mem-sign @
- 5 lcd-text-rows 2 - output-number
- lcd-space [char] M lcd-emit
- ;
- : clear-mem ( -- )
- false mem-sign !
- 0 mem-int !
- 0 mem-frac !
- ;
- : clear-entry ( -- )
- false v-sign !
- 0 v-int !
- 0 v-frac !
- 0 v-point !
- false auto-clear !
- v-op @ -1 = if
- 0 v-op !
- then
- ;
- : clear-all ( -- )
- clear-entry
- 0 v-op !
- false total-sign !
- 0 total-int !
- 0 total-frac !
- ;
- : recall-mem ( -- )
- clear-entry
- mem-sign @ v-sign !
- mem-int @ v-int !
- mem-frac @ v-frac !
- ;
- : copy-to-total ( -- )
- v-sign @ total-sign !
- v-int @ total-int !
- v-frac @ total-frac !
- ;
- : new-digit ( u -- )
- auto-clear @ if
- clear-entry
- then
- v-point @ if
- v-point @ 0> if
- v-point @ 10 / dup
- 0= if
- drop -1 v-point !
- else
- dup v-point !
- * v-frac +!
- then
- then
- else
- v-int @ 10 * + dup v-max > if
- drop v-max
- then
- v-int !
- then
- ;
- : operator-set ( u -- )
- v-op @
- case
- 0 of copy-to-total endof
- 1 of add endof
- 2 of sub endof
- 3 of mul endof
- 4 of div endof
- endcase
- v-op !
- true auto-clear !
- ;
- : process ( u -- )
- case
- 0 of \ 1
- 1 new-digit
- endof
- 1 of \ 2
- 2 new-digit
- endof
- 2 of \ 3
- 3 new-digit
- endof
- 3 of \ +
- 1 operator-set
- endof
- 4 of \ C
- clear-all
- endof
- 5 of \ 4
- 4 new-digit
- endof
- 6 of \ 5
- 5 new-digit
- endof
- 7 of \ 6
- 6 new-digit
- endof
- 8 of \ -
- 2 operator-set
- endof
- 9 of \ MC
- clear-mem
- endof
- 10 of \ 7
- 7 new-digit
- endof
- 11 of \ 8
- 8 new-digit
- endof
- 12 of \ 9
- 9 new-digit
- endof
- 13 of \ *
- 3 operator-set
- endof
- 14 of \ M+
- mem-add
- endof
- 15 of \ .
- auto-clear @ if
- clear-entry
- then
- v-overflow v-point !
- endof
- 16 of \ 0
- 0 new-digit
- endof
- 17 of \ =
- -1 operator-set
- endof
- 18 of \ /
- 4 operator-set
- endof
- 19 of \ MR
- recall-mem
- endof
- endcase
- refresh-display
- ;
- variable down
- variable box-number
- variable can-exit
- : calculator ( -- )
- lcd-cls
- button-flush
- key-flush
- ctp-flush
- can-exit @ if
- 24 lcd-text-rows 1- lcd-at-xy s" Exit" lcd-type
- then
- position-count 0 ?do
- i box-data >r >r 2dup draw-box
- 8 + >r font-width + r> lcd-move-to
- r> lcd-emit r> lcd-emit
- loop
- false down !
- refresh-display
- -1 box-number !
- begin
- ctp-pos? if
- ctp-pos dup 0<
- if
- 2drop
- down @ if
- box-number @ dup
- box-data 2drop
- unhighlight-box
- 1 1 lcd-at-xy 2 lcd-spaces
- 0 0 unhighlight-box
- process
- -1 box-number !
- then
- false down !
- else
- position-count 0 ?do
- 2dup i inside-box if
- true down !
- box-number @ 0< 0=
- box-number @ i <> and
- if
- box-number @
- box-data 2drop
- 1 1 lcd-at-xy 2 lcd-spaces
- unhighlight-box
- 0 0 unhighlight-box
- then
- i dup box-number !
- box-data
- swap 1 1 lcd-at-xy lcd-emit lcd-emit
- highlight-box
- 0 0 highlight-box
- then
- loop
- 2drop
- then
- then
- key? if
- key-flush
- then
- button? if
- button
- case
- button-left of
- endof
- button-centre of
- endof
- button-right of
- can-exit @ if
- exit
- then
- endof
- button-power of
- power-off
- endof
- endcase
- then
- wait-for-event
- again
- ;
- base !
|