====== 4d2006-03 Listings ======
===== SMBus Basiscode =====
\ 2006-07-31 SMBus.fs --- SMBus Basiscode
\ i2c Bus am R8C
\ P1.0 -- SCL
\ P1.1 -- SDA
\ Konstanten
0 Constant PinSCL
1 Constant PinSDA
port1 Constant PortI2C
$E3 Constant PddrI2C
\ SDA,SCL Pins auf 0 oder 1 setzen
: sda0 PinSDA PortI2C bclr ;
: sda1 PinSDA PortI2C bset ;
: scl0 PinSCL PortI2C bclr ;
: scl1 PinSCL PortI2C bset ;
\ 1 SCL Zyklus sind im Programm 4 ticks
: tick 1 us ;
: 2tick tick tick ;
\ sende 1 Bit
: bit>i2c ( bit -- )
IF sda1 ELSE sda0 ENDIF
tick scl1 2tick scl0 tick ;
\ erzeuge Bit Nr. i aus Byte x als 0 oder 1
: getBit ( x i -- b ) rshift $01 and ;
\ sende 1 Byte, (8 Bit) "most significant bit" zuerst
: >i2c ( x -- )
8 0 DO
dup 8 I 1+ - getBit
bit>i2c
LOOP
drop ;
\ sende START, STOP, REPEATED_START
: i2c_start ( -- ) tick sda0 2tick scl0 tick ;
: i2c_stop ( -- ) tick scl1 2tick sda1 tick ;
: i2c_rstart sda1 tick scl1 tick sda0 tick scl0 tick ;
\ setze SDA zum Lesen / Senden
: sdaInput ( -- ) PinSDA PddrI2C bclr ;
: sdaOutput ( -- ) PinSDA PddrI2C bset ;
\ lies SDA
: readSDA ( -- f )
PinSDA PortI2C btst IF 1 ELSE 0 ENDIF ;
\ lies 1 Byte (8 Bit), "most significant bit" zuerst
: i2c ( x1 .. xN.msB N addr -- )
i2c_start \ START
>i2c acki2c acki2c ack IF \ Schleife ueber N-1 Byte
0 DO \ Datenbyte = 0 (initialisieren)
i2c \ DATA_BYTE lesen, ACK schicken
LOOP \ Ende Schleife
ENDIF \
i2c \ letzes Byte lesen, NACK schicken
i2c_stop \ STOP
;
\ finis
===== adv_01 =====
\ 2006-06-28 EW adv_01.fs
\
\ i2c_bus connected to r8c
\ P1.0 -- SCL
\ P1.1 -- SDA
\ device PCF8574 (8bit IO) at address $20
rom
include SMBus.fs
$40 Constant i2c_addr_portexpander
\ send Byte x to portexpander
: >portexpander ( x -- )
i2c_start \ START
i2c_addr_portexpander >i2c \ Adresse schreiben
acki2c \ Datenbyte schreiben
ackportexpander
1000 ms
BEGIN
N @
dup invert >portexpander
1+ N !
1000 ms
key? UNTIL
;
ram
\ finis
===== adv_02 =====
\ 2006-06-28 EW adv_02.fs
\
\ i2c Bus am R8C
\ P1.0 -- SCL
\ P1.1 -- SDA
\ am Bus:
\ PCF8574 (8bit IO), 7-bit Adresse: $20
rom
include SMBus.fs
$40 Constant i2c_addr_portexpander
\ vom portexpander lesen
: i2c
1 i2c_addr_portexpander NB
===== adv_03 =====
\ 2006-06-28 EW adv_03.fs --- Thermometer
\
\ i2c Bus am R8C
\ P1.0 -- SCL
\ P1.1 -- SDA
\ am Bus:
\ PCF8574 (8bit IO), 7-bit Adresse: $20
\ LM75 (Thermometer, 9-bit signed, 7-bit Adresse: $4f
rom
include SMBus.fs
$9e Constant i2c_addr_lm75
: get.T ( -- xh xl )
$00 \ ControlByte
1 i2c_addr_lm75 NB>i2c \ verschicken
2 i2c_addr_lm75 NBR \ store copy for sign
abs s>d \ remove sign, make double
\ 1 digit, "." 2digits sign_always
\ Numbers >= 1000 are truncated in the high digits!!!
<# # 46 hold # # R> sign! #> \ == "%+5.1f"
;
\ write string to lcd position col (0..15) row (0..1)
\ with next lcdtype
: lcdpos ( row col -- )
swap $40 * + $80 + lcdctrl! &1 ms ;
: thermometer
lcdpage
BEGIN
0 5 lcdpos
get.T decode.T format.T lcdtype
250 ms
key? UNTIL
;
ram
\ finis
===== Sudoku =====
\ Nach geladenem Gforth-R8C ueber die Tastatur in das
\ RAM des R8Cs eingeben. Danach per SAVESYSTEM
\ "festfrieren". Kann per EMPTY bis auf das eigentliche
\ Forth-System geloescht werden.
\ Ich verwende im gesamten Programm Grossschreibung.
\ Kleinschreibung reicht aber. Das System ist auf
\ egal voreingestellt.
HEX
\ Sudoku-Matrix, zeilenweise, pro Element ein Byte
CREATE M
0 C, 1 C, 2 C, 3 C, 4 C, 5 C, 6 C, 7 C, 8 C,
3 C, 4 C, 5 C, 6 C, 7 C, 8 C, 0 C, 1 C, 2 C,
6 C, 7 C, 8 C, 0 C, 1 C, 2 C, 3 C, 4 C, 5 C,
1 C, 2 C, 3 C, 4 C, 5 C, 6 C, 7 C, 8 C, 0 C,
4 C, 5 C, 6 C, 7 C, 8 C, 0 C, 1 C, 2 C, 3 C,
7 C, 8 C, 0 C, 1 C, 2 C, 3 C, 4 C, 5 C, 6 C,
2 C, 3 C, 4 C, 5 C, 6 C, 7 C, 8 C, 0 C, 1 C,
5 C, 6 C, 7 C, 8 C, 0 C, 1 C, 2 C, 3 C, 4 C,
8 C, 0 C, 1 C, 2 C, 3 C, 4 C, 5 C, 6 C, 7 C,
\ Hole Element in Zeile i und Spalte j von Matrix M
: IJ@ ( i j -- a[ij] ) SWAP 9 * + M + C@ ;
\ Speichere Element in Zeile i und Spalte j nach Matrix M
: IJ! ( a[ij] i j -- ) SWAP 9 * + M + C! ;
\ Addiere n modulo 9 zu saemtlichen Elementen von Matrix M
: ADDn ( n -- )
51 0 DO DUP M I + C@ + 9 MOD M I + C! LOOP DROP ;
\ INDEX
VARIABLE IX
\ Vertausche willkuerlich 2 Spalten einer Laengsdreierreihe in Matrix M
: XCHJ ( -- ) IX @ C@ 9 0
DO DUP 9 MOD DUP DUP 3 MOD 0> IF 1 - ELSE 1+ THEN
2DUP I SWAP IJ@ I ROT IJ@ ROT I SWAP IJ! I ROT IJ!
LOOP DROP ;
\ Vertausche Zeile 3 und 5 und Zeile 7 und 8 in Matrix M
: XCHI ( -- ) 9 0
DO 3 I IJ@ 5 I IJ@ 3 I IJ! 5 I IJ! 7 I IJ@ 8 I IJ@ 7 I IJ! 8 I IJ!
LOOP ;
\ ASCII --> Ziffernausgabe
: ZIFF ( n -- ) DUP 8 U> IF DROP SPACE SPACE ELSE 1+ . THEN ;
\ IX um 5 weitersetzen
: I5+! ( -- ) IX @ DUP 600 > IF 300 - THEN 5 + IX ! ;
\ Zufaellige Auslassungen
\ Etwa 27d Elemente bleiben als Vorgabe stehen. Breite Streuung!
: RAND ( n -- m ) IX @ C@ 3 MOD IF DROP 20 THEN I5+! ;
\ Bildschirmdarstellung von geaenderter Vorgabematrix
: V ( -- ) CR 9 0
DO 9 0 DO J I IJ@ ZIFF LOOP 5 SPACES
9 0 DO J I IJ@ RAND ZIFF LOOP CR
LOOP ;
\ Neue Sudoku-Matrix mit passender Vorgabematrix
: S ( -- ) IX @ C@ ADDN XCHI XCHJ I5+! V ;
\ Will man zu ein und derselben (Loesungs-)Matrix M verschiedene
\ Vorgabematrizen erzeugen, dann rufe man (beliebig oft) V auf.
\ Bei jedem erneuten Aufruf von V wird die bis dato erreichte
\ Sudoku-Matrix M beibehalten, waehrend die Vorgabematrix neu er-
\ zeugt wird.
\ Selbstverstaendlich kann man eine erreichte Vorgabematrix
\ auch per Hand ausbessern: Man uebernehme (und notiere auf
\ Papier) nur, sagen wir, 27d Elemente oder ergaenze (bei zu
\ wenigen Vorgabeelementen) Elemente durch Einfuegen von der
\ Sudoku-Matrix M her.
\ Man kann eine erreichte Sudoku-Matrix M auch per Hand aendern:
\ Dazu stehen die drei Forth-Worte x ADDN XCHI XCHJ (in
\ beliebiger Anwendungsreihenfolge) zur Verfuegung. x kann
\ eine beliebige Zahl sein.
\ Geaenderte Vorgabe-Matrizen bei gleichbleibender Sudoku-
\ Matrix werden durch V angezeigt. Geaenderte Sudoku-Matrizen
\ mit passender Vorgabe-Matrix werden durch S angezeigt.
\ Solche Tastatureingaben muessen natuerlich immer durch
\ [return] abgeschlossen werden, um Wirksamkeit zu erlangen.
===== Arithmetik in Galois Feldern, Grundkoerper F_p =====
( Arithmetik in Galois Feldern, Grundkoerper F_p )
: Restklassen ;
variable F_pp
2 F_pp ! \ Vorbesetzung mit 2
: F_p+ ( a b -- a+b ) + F_pp @ mod ;
: F_p- ( a b -- a-b ) - F_pp @ mod ;
: F_p* ( a b -- a*b ) * F_pp @ mod ;
: F_p/ ( a b -- a/b )
swap 0 swap ( b 0 a) ( oder b q r )
begin
rot dup >r \ q r b
/mod \ q r delta-q
rot + \ r q
r> swap rot dup \ b q r r
F_pp @ + swap \ b q r' r
0=
until
drop swap drop ;
\ Einrichtung des gesonderten F_p^n Stapels entfaellt hier
\ ************ weil nur fuer F_p^2 *******************
2 constant F_p^nn
F_p^nn cell * constant F_p^2#bytes \ Speicherplatz fuer eine Zahl aus F_p^2
\ --------------------------------------------------------------
\ Arithmetik fuer Galois-Felder F_p^n auf dem Parameterstapel
\ nur Spezialfall n=2 und Polynom a^2+a+1=0
\ dieses Polynom ist irreduzibel fuer z. B. p= 2, 5
: F_p^2+ ( a0 a1 b0 b1 -- a0+b0 a1+b1 )
swap >r f_p+ swap r> f_p+ swap ;
: F_p^2- ( a0 a1 b0 b1 -- a0-bo a1-b1 )
swap >r f_p- swap r> f_p- swap ;
: F_p^2* ( a0 a1 b0 b1 -- c0 c1 )
\ c0 = a0*b0 - a1*b1
\ c1 = a1*b0 + a0*b1 - a1*b1
dup >r swap dup >r \ a0 a1 b1 b0 |R b0 b1
rot dup >r f_p* \ a0 b1 a1*b0 |R a1 b0 b1
rot dup >r \ b1 a1*b0 a0 |R a0 a1 b0 b1
rot f_p* f_p+ \ a1*b0+a0*b1 |R a0 a1 b0 b1
r> r> r> rot \ a1*b0+a0*b1 a1 b0 a0 |R b1
f_p* swap r> f_p* \ a1*b0+a0*b1 a0*b0 a1*b1 |R
dup >r f_p- \ a1*b0+a0*b1 a0*b0-a1*b1 |R a1 b1
swap r> f_p- ; \ a0*b0-a1*b1 a1*b0+a0*b1-a1*b1 |R
: konj ( a0 a1 -- a0+a1 a1 )
dup rot f_p+ swap ; \ nur falls Polynom a^2+a+1=0 korrekt
: F_p^2/ ( a0 a1 b0 b1 - c0 c1 )
\ aehnlich wie durch Erweiterung mit dem konjugiert komplexen Nenner
\ machbar, Als Uebungsaufgabe empfohlen.
;
\ -----------------------------------------------------------------
\ Variablen und Konstanten
: F_p^2variable
create [ F_p^2#bytes ] literal allot ;
: F_p^2!
dup [ F_p^2#bytes 1- ] literal + swap
do
i ! 4
+loop ;
: F_p^2@ dup 1- swap [ F_p^2#bytes 2 / ] literal +
do
i @ -4
+loop ;
f_p^2variable test
\ finis