====== 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