====== 4d2008-01 Listings ======
===== 1-wire.fs =====
\ 1-wire interface
[IFUNDEF] set-baud include serial.fs [THEN]
0 Value 1-wire-fd
also dos
: set-tty ( fd -- ) filehandle @ >r
t_old r@ tcgetattr drop
t_old t_buf sizeof termios move
$805 t_buf termios c_iflag !
$000 t_buf termios c_oflag !
$8BD t_buf termios c_cflag !
0 t_buf termios c_lflag !
0 t_buf termios c_cc VMIN + c!
3 t_buf termios c_cc VTIME + c!
$D dup t_buf termios c_ispeed ! t_buf termios c_ospeed !
t_buf 1 r> tcsetattr drop ;
previous
: open-1-wire ( addr u -- ) r/w open-file throw to 1-wire-fd
1-wire-fd set-tty ;
s" /dev/ttyUSB0" open-1-wire
: 1w-write ( addr u -- )
1-wire-fd write-file throw ;
: 1w-read ( addr u -- n )
1-wire-fd read-file throw ;
: 1w? ( -- n ) 1-wire-fd check-read ;
$E3 Constant :cmd
$E1 Constant :data
$C1 Constant :reset
$C5 Constant :reset2
$BE Constant :read
$B1 Constant :accel
$A1 Constant :accel-off
Create cmdbuf 0 c,
Create 'cmd :cmd c, 0 c, :data c,
Create 'address 8 0 [DO] 0 c, [LOOP]
Create 'dummies 16 0 [DO] $FF c, [LOOP]
Create 'search 16 0 [DO] 0 c, [LOOP]
Create 'stuff $17 c, $45 c, $5b c, $0f c, $91 c,
Variable results $100 allot
Variable timeout
: waitx &10 wait timeout @ 0 after - 0< ;
: >results ( n -- ) &100 after timeout !
BEGIN dup 1-wire-fd check-read > WHILE waitx UNTIL
results off true abort" Timeout" ELSE
results cell+ swap 1w-read results ! THEN ;
: .results ( -- ) base push hex
results @+ swap bounds ?DO
I c@ 3 .r LOOP ;
: >address ( -- )
'address 8 erase
$40 0 DO results cell+ I 2* 1+ bit@ IF
'address I +bit
THEN LOOP ;
Code bswap AX bswap Next end-code macro
: "address ( -- addr u ) base push hex
>address 'address 2@ bswap swap bswap swap
<# # # '# hold 12 0 DO # LOOP '. hold # # #> ;
: .address "address type ;
: maxdisc ( -- n ) 0
$40 0 DO results cell+ I 2* bit@ IF drop I THEN LOOP ;
: cmd ( n -- ) cmdbuf c! cmdbuf 1 1w-write ;
: cmdr ( n -- ) cmd 1 >results ;
: addr ( -- ) 'address 8 1w-write 8 >results ;
: dummies8 ( -- ) 'dummies 8 1w-write 8 >results ;
: dummies9 ( -- ) 'dummies 9 1w-write 9 >results ;
: search16 ( -- ) 'search 16 1w-write 16 >results ;
: >temp ( -- ) base push decimal results cell+ w@ 2/
&100 * results cell+ 6 + c@ &100 results cell+ 7 + c@ */ - &75 +
extend under dabs <# 'C hold '° xhold # # '. hold #S rot sign #> ;
: .temp ( -- ) >temp type ;
: >cmd ( n -- ) 'cmd 1+ c! 'cmd 3 1w-write ;
: >cmdr ( n -- ) >cmd 1 >results ;
: reset2 ( -- ) :reset2 >cmdr ;
: init ( -- ) :reset >cmdr 'stuff 5 1w-write 5 >results reset2 ;
: accel ( -- ) :accel >cmd ;
: accel-off ( -- ) :accel-off >cmd ;
\ "skip ROM": no address
: noaddress reset2 $CC cmdr ;
\ "search ROM": apply an address
: address
reset2 $55 cmdr addr ;
: search-first ( -- ) 'search 16 erase
init $F0 cmdr accel search16 accel-off ;
: search-next ( -- ) results cell+ 'search 16 move
'search maxdisc 2* 1+ +bit
$40 maxdisc 1+ DO 'search I 2* 1+ -bit LOOP
init $F0 cmdr accel search16 accel-off ;
: search-all ( -- ) search-first .address cr maxdisc
BEGIN search-next .address cr maxdisc tuck = UNTIL drop ;
: readout
noaddress
$44 cmdr &750 ms \ convert temperature
noaddress
$BE cmdr \ read scratchpad
dummies9 ;
: readrom \ would work if host didn't reply as well
reset2 $33 cmdr
dummies8 ;
init search-first >address
===== 1wire implementation =====
#! xbigforth
\ automatic generated code
\ do not edit
also editor also minos also forth
component class ds1920-f5
public:
early widget
early open
early dialog
early open-app
infotextfield ptr temp
varbox ptr devices
text-label ptr dev-first
( [varstart] ) ( [varend] )
how:
: open new DF[ 0 ]DF s" DS 1920-F5 sensor" open-component ;
: dialog new DF[ 0 ]DF s" DS 1920-F5 sensor" open-dialog ;
: open-app new DF[ 0 ]DF s" DS 1920-F5 sensor" open-application ;
class;
include 1wire.fs
ds1920-f5 implements
( [methodstart] ) : show super show
search-first ^^ 0 T[ ][ ]T "address rbutton new
dev-first widgets self devices add maxdisc
BEGIN search-next ^^ 0 T[ ][ ]T "address rbutton new
dev-first widgets self devices add maxdisc tuck = UNTIL
drop
^ 1 $1000 dup NewTask pass >o
BEGIN readout >temp temp assign AGAIN ; ( [methodend] )
: widget ( [dumpstart] )
^^ ST[ ]ST ( MINOS ) T" " X" Temperature:" infotextfield new ^^bind temp
X" Devices:" text-label new ^^bind dev-first
&1 varbox new ^^bind devices
&2 vabox new panel
( [dumpend] ) ;
: init ^>^^ assign widget 1 :: init ;
class;
: main
ds1920-f5 open-app
$1 0 ?DO stop LOOP bye ;
script? [IF] main [THEN]
previous previous previous
===== Projekt Euler - p146 =====
#! /usr/bin/gforth
\ ---- logic and shift words for double cell operands -------------------------
: dand ( d d -- d ) rot and >r and r> ;
: dinvert ( d -- d ) swap invert swap invert ;
: dlshift ( d u -- d ) 0 ?do d2* loop ;
: dor ( d d -- d ) rot or >r or r> ;
: dnot ( d -- 0.|1. ) d0= abs s>d ;
: drshift ( d u -- d ) 0 ?do d2/ loop dabs ;
: dxor ( d d -- d ) rot xor >r xor r> ;
\ ---- ran4 : a random number generator ---------------------------------------
: (FuncG) ( d dc1 dc2 -- d )
2>r dxor 2dup um* 2swap dup um* dinvert rot dup um* d+ swap 2r> dxor d+
;
: (PseudoDes) ( d d -- d d )
2swap 2over $BAA96887E34C383B. $4B0F3B583D02B5F8. (FuncG) dxor
2swap 2over $1E17D32C39F74033. $E874F0C39226BF1A. (FuncG) dxor
2swap 2over $03BCDC3C60B43DA7. $6955C5A61D38CD47. (FuncG) dxor
2swap 2over $0F33D1B265E9215B. $55A7CA46F358B432. (FuncG) dxor
;
2variable Counter
2variable Sequence#
: start-sequence ( dcounter dseq# -- ) Sequence# 2! Counter 2! ;
: ran4 ( -- d )
Sequence# 2@ Counter 2@ (PseudoDes)
2swap 2drop
Counter 2@ 1. d+ Counter 2!
;
\ ---- arithmetic words for unsigned double cell operands ---------------------
: d* ( d d -- d ) 3 pick * >r tuck * >r um* r> + r> + ;
: t* ( ud un -- ut ) dup rot um* 2>r um* 0 2r> d+ ;
: t/ ( ut un -- ud )
>r r@ um/mod swap
rot 0 r@ um/mod swap
rot r> um/mod swap drop
0 2swap swap d+
;
: u*/ ( ud un un -- ud ) >r t* r> t/ ;
\ initialize SUPERBASE (normally $100000000. on 32 bits machine, with fallback value of $10000.)
s" max-u" environment? 0= [if] $10000. [then] 0 1. d+ 2constant SUPERBASE
: d/ { D: u D: v -- ud_quot }
v 0. d= if -10 throw then \ throw for division by zero
v u du> if 0. exit then \ if v is bigger then 0.
v u d= if 1. exit then \ if v is equal then 1.
v 0= if >r u 1 r> u*/ exit then \ use mixed precision word
drop
v { v1 v0 } \ v = v0 * b + v1
v0 -1 = if 1 else SUPERBASE 1 v0 1+ u*/ drop then { d } \ d = b/(v0+1)
v d 1 u*/ { w1 w0 } \ w = d * v = w0 * b + w1
u over 0 w1 w0 u*/ d- d w0 u*/ nip 0
;
: dmod { D: d1 D: d2 -- d } d1 2dup d2 d/ d2 d* d- ;
: dumin ( d1 d2 -- d ) 2over 2over du> if 2swap then 2drop ; \ d is min(d1,d2)
\ initialize UMAX (normally $ffffffffffffffff. on 32 bits machine, with fallback value of $ffffffff.)
s" max-ud" environment? 0= [if] $ffffffff. [then] 2constant UMAX
: d+mod { D: a D: b D: m -- d } \ addition modulo m
a m dmod to a \ normalize a
b m dmod to b \ normalize b
a UMAX b d- d<= if \ no overflow..
a b d+ m dmod exit \ ..built-in computation
then
\ ---- go with the algorithm ;-)
a m a d- dumin { D: aA }
b m b d- dumin { D: bB }
b bB d= ( -- f ) \ leave a flag on stack
a aA d= if
bB aA du> if
if aA bB d+ m dmod else m bB aA d- d- then exit ( f -- ) \ ..consume the flag
else
>r aA bB r> if d+ else d- then m dmod exit ( f -- ) \ ..consume the flag
then
else
if aA bB du> if m aA bB else m m bB aA d- then d- d- exit then ( f -- ) \ ..consume the flag
then
m aA bB d+ m dmod d-
;
: d*mod { D: a D: b D: m -- d } \ multiplication modulo m
a m dmod to a \ normalize a
b m dmod to b \ normalize b
a 1. d= if b exit then
b 1. d= if a exit then
a m a d- dumin { D: aA }
b m b d- dumin { D: bB }
aA d0= bB d0= or if 0. exit then
aA 1. d= if m b d- exit then
bB 1. d= if m a d- exit then
aA a d= bB b d= and aA a d<> bB b d<> and or { pos } \ pos is True if positive, False otherwise
aA UMAX bB d/ du<= if
aA bB d* m dmod pos 0= if m 2swap d- m dmod then exit
then
aA d2/ { D: a0 }
aA a0 d- { D: a1 }
bB d2/ { D: b0 }
bB b0 d- { D: b1 }
a1 b1 m recurse { D: p4 }
0. 0. 0. { D: p1 D: p2 D: p3 }
a0 a1 d= b0 b1 d= and if
p4 to p1
p4 to p2
p4 to p3
else
a0 a1 d= if
p4 m a1 d- m dmod m d+mod 2dup to p3
to p1
p4 to p2
else
p4 m b1 d- m dmod m d+mod to p2
b0 b1 d= if
p2 to p1
p4 to p3
else
p4 m a1 d- m dmod m b1 d- m dmod 1. m d+mod m d+mod m d+mod to p1
p4 m a1 d- m dmod m d+mod to p3
then
then
then
p1 p2 p3 p4 m d+mod m d+mod m d+mod pos 0= if m 2swap d- m dmod then
;
: d**mod { D: base D: power D: m -- d } \ exponentiation modulo m
1. { D: res }
begin power 0. du> while
1. power dand drop if \ if power is odd
res base m d*mod to res
then
base base m d*mod to base
power 1 drshift to power
repeat
res
;
: miller_rabin { D: n W: rounds -- f }
n 1. du<= if false exit then
n 19. du<= if
n drop \ to use single cell in the following tests
dup 2 = if drop true exit then
dup 3 = if drop true exit then
dup 5 = if drop true exit then
dup 7 = if drop true exit then
dup 11 = if drop true exit then
dup 13 = if drop true exit then
dup 17 = if drop true exit then
19 = if true exit then \ do not dup in the last test
false exit
else
n 2. dmod 0. d= if false exit then
n 3. dmod 0. d= if false exit then
n 5. dmod 0. d= if false exit then
n 7. dmod 0. d= if false exit then
n 11. dmod 0. d= if false exit then
n 13. dmod 0. d= if false exit then
n 17. dmod 0. d= if false exit then
n 19. dmod 0. d= if false exit then
then
n 1. d- { D: d }
0 { W: s }
begin d 1. dand 0. d= while
d 1 drshift to d
s 1+ to s
repeat
0. 0. 0. 0 { D: a D: tst D: Rbig W: Rsmall }
begin rounds 1- dup to rounds 0> while
ran4 n 1. d- dmod 1. d+ to a
a d n d**mod 1. du<> if
1. to Rbig
0 to Rsmall
begin Rsmall s u< while
a Rbig d d* n d**mod to tst \ tst = powmod( a, R * d, n )
n 1. d- tst du= if
s to Rsmall \ cause a break from the loop
else
Rbig Rbig d+ to Rbig \ double Rbig
Rsmall 1+ to Rsmall
then
repeat
n 1. d- tst du<> if
false exit \ return false (composite number)
then
then
repeat
true \ return true (maybe prime)
;
\ ---- main and its internal words --------------------------------------------
: (main-inc-p) ( u -- u ) dup 2 + 3 mod 0= if 4 else 2 then + ;
: (main-ba) { W: n -- n' }
11 { W: p }
0 { W: nd }
n s>d 2dup d* { D: n2 }
begin
n2 p s>d dmod d>s to nd
nd 1+ p mod 0= if 0 exit then
nd 3 + p mod 0= if 0 exit then
nd 7 + p mod 0= if 0 exit then
nd 9 + p mod 0= if 0 exit then
nd 13 + p mod 0= if 0 exit then
nd 27 + p mod 0= if 0 exit then
p (main-inc-p) to p \ inc. p by 2 or by 4
p n 1+ > if
n2 15. d+ 10 miller_rabin if 0 exit then
n2 19. d+ 10 miller_rabin if 0 exit then
n2 21. d+ 10 miller_rabin if 0 exit then
n2 25. d+ 10 miller_rabin if 0 exit then
." Found n=" n . cr
n exit
then
again
;
: main { W: limit -- d }
0. { D: sum }
limit 1+ 10 do \ i must be divisible by 10, loop only through multiples of 10
i 3 mod 0<> if \ i can't be divisible by 3
i 4 + 7 mod 1 <= if \ i % 7 must be either 3 or 4
i (main-ba) s>d sum d+ to sum
then
then
10 +loop
." sum=" sum ud. cr
;
150000000 main
bye
===== Cursor Togglen =====
\ CursorTogglen.fs
hex
code curs-on ( -- ) \ Cursor einschalten
ds di mov \ Datensegment aufbewahren,
bx bx xor bx ds mov \ dann auf 0 setzen.
460 [bx] cx mov \ Rasterzeilen: ch oben, cl unten
di ds mov \ Datensegment wiederherstellen
1f # ch and \ Bits 5-7 der obersten Rasterzeile auf 0
1 # ah mov \ Interrupt-Funktion nach ah
10 int \ Bildschirm-Interrupt aufrufen
next end-code
code curs-off ( -- ) \ Cursor ausschalten
ds di mov \ mov-Operationen beziehen sich
bx bx xor bx ds mov \ auf das Datensegment ds
460 [bx] cx mov
di ds mov
e0 # ch or \ Bits 5-7 der obersten Rasterzeile auf 1
1 # ah mov 10 int
next end-code
code curs-togg ( -- ) \ Cursor umschalten
ds di mov
bx bx xor bx ds mov
460 [bx] cx mov
di ds mov
e0 # ch xor \ Bits 5-7 der obers. Rasterz. 0/1 -> 1/0
1 # ah mov 10 int
next end-code
code curs-shape ( anf end -- ) \ Cursor-Formgebung
ds di mov
bx bx xor bx ds mov
460 [bx] cx mov
di ds mov
ax pop \ Unterste Cursor-Rasterzeile auf
1f # al and al cl mov \ (0..1f) beschränken und nach cl legen.
ax pop \ Oberste Cursor-Rasterzeile auf
1f # al and \ (0..1f) beschränken, dann bisherigen
e0 # ch and \ Einschaltzustand (Bits 5-7) retten
al ch or \ und beides nach ch zusammenführen.
1 # ah mov 10 int
next end-code
\ Der so implementierte Cursor kann auch im ausgeschalteten
\ Zustand (im Verborgenen) neu geformt werden, ohne dass er
\ sich dadurch schon einschaltet. Beim anschließenden
\ Einschalten zeigt er dann seine neueingestellte Form.
===== word scrambler =====
\ word scrambler based on random shuffle
vocabulary scrambler
scrambler definitions
variable seed
base @ hex 10450405 constant generator
base !
: rnd ( -- n ) seed @ generator UM* DROP 1+ DUP seed ! ;
: random ( n -- 0..n-1 ) rnd UM* NIP ;
: init ( -- )
TIME&DATE 12 * + 31 * + 24 * + 60 * + 60 * + seed ! ; init
: c>< ( c-addr1 c-addr2 -- ) \ character exchange
2dup c@ ( c-addr1 c-addr2 c-addr-1 c2 )
swap c@ ( c-addr1 c-addr2 c2 c1 )
rot c! ( c-addr1 c2 )
swap c! ;
: cshuffle ( c-addr n -- ) \ shuffle Durstenfeld/Knuth
BEGIN ?dup WHILE ( c-addr i )
2dup 1- chars + >r
2dup random chars + r> c><
1-
REPEAT drop ;
: scramble-word2 ( c-addr len -- ) \ some case handling included.
dup 4 < IF 2drop exit THEN
dup 4 = IF over char+ dup char+ c>< 2drop exit THEN
2 - swap char+ swap cshuffle ;
: scramble ( -- )
cr
BEGIN
bl word count
dup
WHILE ( c-addr len )
2dup scramble-word2 type space
REPEAT
2drop ;
words
scramble sah ein knab ein röslein stehen
cr cr
\ study random behavior, execute serveral times.
\ : xxx ( -- ) 0 10 do cr i . i random . -1 +loop ;
\ scramble (.) (.O) (.:O) (.:=O) (.:=#O) (.:=#*O)
\ finis