000
09.02.2019, 13:46 Uhr
mwd
|
Hallo, habe mal wieder etwas für FORTH-Freunde. So viele scheinen das zwar nicht zu sein, aber vielleicht interessiert es ja einige. Ich habe ein paar FORTH Worte zur Ansteuerung von Bauteilen wie Sensoren oder LCD/OLED mit SPI- (4 Drähte) und I2C- (2 Drähte) Schnittstelle geschrieben. Warum mit dem Arduino, wenn es auch mit dem KC geht? Also habe ich den Druck- und Temperatursensor BMP280 und so ein kleines 0.96" OLED mit 128x64 Pixeln am M001 in Betrieb genommen. Funktioniert wunderbar! Für die beiden Beispiele habe ich den Quellcode angehangen. Bei Bedarf kann ich auch die *.(F) Files schicken (die ja kein Zeilenende haben). Im Forum kann ich keine Files anhängen.
Auf dem OLED kann Text mit dem CAOS Zeichensatz dargestellt werden, und zwar sowohl im Hoch- als auch im Querformat. Für das Querformat mußte ich die Zeichen um 90° drehen. Ist etwas umständlich, geht aber. SCR 6 beinhaltet die eigentliche Ausgabe eines Bytes an das OLED mittels SPI-Protokoll. Benutzt habe ich Port A am M001. Pin 2 ist das Clock-Signal, Pin 7 ist SDI, Pin 0 ist DC, Pin 3 ist CS und Pin 1 ist Reset. Mittels OPRINT (SCR 12) kann direkt auf das OLED geschrieben werden.
SCR # 1 0 ( 2/ 2* ) 1 2 CREATE 2/ 3 HEX E1 C, ( POP HL ) 4 2CCB , ( SRA H ) 5 1DCB , ( RR L ) 6 E5 C, ( PUSH HL ) 7 C3 C, NEXT , ( JP NEXT ) 8 DECIMAL SMUDGE 9 10 CREATE 2* 11 HEX E1 C, ( POP HL ) 12 29 C, ( ADD HL,HL) 13 E5 C, ( PUSH HL ) 14 C3 C, NEXT , ( JP NEXT ) 15 DECIMAL SMUDGE -->
SCR # 2 0 ( U.BIN ) 1 2 : U.BIN ( N -> ) 3 BASE @ SWAP 2 BASE ! S->D 4 <# 2 0 DO 5 2 0 DO 6 4 0 DO # LOOP 7 32 HOLD 8 LOOP 9 32 HOLD 10 LOOP #> 11 TYPE SPACE BASE ! 12 ; 13 14 HEX 15 -->
SCR # 3 0 ( M001 BMP280 KONSTANTEN ) 1 2 04 CONSTANT DWA 3 05 CONSTANT DWB 4 06 CONSTANT SWA 5 07 CONSTANT SWB 6 7 CF CONSTANT BITMODE 8 70 CONSTANT BITMASKE 9 10 F4 CONSTANT 'CTRL 11 F5 CONSTANT 'CONF 12 F7 CONSTANT 'PTDAT 13 14 15 -->
SCR # 4 0 ( INITPIO GET SET STOP ) 1 2 : INITPIO ( - ) 3 BITMODE SWA BUSOUT 4 BITMASKE SWA BUSOUT 5 ; 6 7 : GET ( -> B ) DWA BUSIN ; 8 : SET ( B -> ) DWA BUSOUT ; 9 10 : STOP ( - ) A SET ; 11 12 0 VARIABLE DC# 13 : CMD 0 DC# ! ; 14 : DATA 1 DC# ! ; 15 -->
SCR # 5 0 ( WAIT 50MS RESET ) 1 2 CREATE WAIT ( b -> ) 3 E1 C, 7D C, C5 C, 141E , 4 CD C, F00C , C1 C, 5 C3 C, NEXT , 6 SMUDGE 7 8 : 50MS ( N -> ) 9 0 DO 8 WAIT LOOP 10 ; 11 12 : RESET 13 1 10 SWITCH INITPIO 14 0 SET STOP 15 ; -->
SCR # 6 0 ( BIT> BYTE> DWRITE ) 1 2 : BIT> ( N1 -> N2 ) 3 DUP F0 AND DC# @ OR 2 OR DUP 4 SET 4 OR SET 2* 5 ; 6 7 : BYTE> ( N -> ) 8 8 0 DO BIT> LOOP DROP 9 ; 10 11 : DWRITE ( B -> ) 12 BYTE> STOP 13 ; 14 15 -->
SCR # 7 0 ( COL PAGE DISP ) 1 2 : COL ( 0-127 -> ) 3 10 /MOD 10 OR CMD BYTE> 4 DWRITE 5 ; 6 7 : PAGE ( 0-7 -> ) 8 B0 OR CMD DWRITE 9 ; 10 11 : DISP ( 0/1 -> ) 12 AE OR CMD DWRITE 13 ; 14 15 -->
SCR # 8 0 ( INIT FULLINIT ) 1 2 : INIT ( N -> ) 3 RESET CMD 81 BYTE> BYTE> 4 8D BYTE> 14 BYTE> 1 DISP 5 ; 6 : FULLINIT ( N -> ) 7 RESET CMD 8 A8 BYTE> 63 BYTE> D3 BYTE> 9 00 BYTE> 40 BYTE> A0 BYTE> 10 C0 BYTE> DA BYTE> 12 BYTE> 11 81 BYTE> BYTE> A4 BYTE> 12 A6 BYTE> D5 BYTE> 80 BYTE> 13 8D BYTE> 14 BYTE> AF DWRITE 14 ; 15 -->
SCR # 9 0 ( CCTL0 CCTL1 'ZB ) 1 2 B7A6 CONSTANT CCTL0 3 B7A8 CONSTANT CCTL1 4 5 : 'ZB ( ASCII -> ADR ) 6 DUP 1F > IF 7 20 - DUP 3F > IF 8 20 - 8 * CCTL1 I@ + 9 ELSE 8 * CCTL0 I@ + 10 ENDIF 11 ELSE 8 * CCTL1 I@ + 12 ENDIF 13 ; 14 15 -->
SCR # 10 0 ( PEMIT OCLS ) 1 2 : PEMIT ( ASCII -> ) 3 DATA 'ZB DUP 8 + SWAP DO 4 I C@ BYTE> 5 LOOP STOP 6 ; 7 8 : OCLS ( - ) 9 0 COL 8 0 DO 10 I PAGE DATA 11 80 0 DO 0 BYTE> LOOP 12 LOOP STOP 13 ; 14 15 -->
SCR # 11 0 ( LEMIT ) 1 2 1 VARIABLE X 3 4 : LEMIT ( ASCII -> ) 5 DATA 1 X ! 'ZB 8 0 DO 6 0 OVER 7 1 - DUP 8 + DO 8 I C@ X @ * FF AND OR 2* 9 FF00 AND 10 -1 +LOOP 0 100 U/ BYTE> DROP 11 X @ 2* X ! 12 LOOP DROP STOP 13 ; 14 15 -->
SCR # 12 0 ( OTYPE ) 1 2 : OTYPE ( ADR U -> ) 3 OVER + SWAP DO 4 I C@ LEMIT 5 LOOP 6 ; 7 8 : OPRINT ( - ) 9 D WORD HERE COUNT OTYPE 10 ; 11 12 13 DECIMAL 14 15 ----------------------------------------------------------------------------------
Hier noch die Ansteuerung des Druck- und Temperatursensors BMP280 mittels I2C Schnittstelle. Bit 2 des PORT A am M001 ist wieder Clock und Bit 7 ist SDA. Mehr ist hier hardwareseitig nicht nötig.
SCR # 1 0 ( 100H/ 2* ) 1 2 CREATE 100H/ ( N -> N ) 3 HEX E1 C, ( POP HL ) 4 6C C, ( LD L,H ) 5 0026 , ( LD H,0 ) 6 E5 C, ( PUSH HL ) 7 C3 C, NEXT , ( JP NEXT ) 8 DECIMAL SMUDGE 9 10 CREATE 2* ( N -> N ) 11 HEX E1 C, ( POP HL ) 12 29 C, ( ADD HL,HL) 13 E5 C, ( PUSH HL ) 14 C3 C, NEXT , ( JP NEXT ) 15 DECIMAL SMUDGE -->
SCR # 2 0 ( U.BIN ) 1 2 : U.BIN ( N -> ) 3 BASE @ SWAP 2 BASE ! S->D 4 <# 2 0 DO 5 2 0 DO 6 4 0 DO # LOOP 7 32 HOLD 8 LOOP 9 32 HOLD 10 LOOP #> 11 TYPE SPACE BASE ! 12 ; 13 14 HEX 15 -->
SCR # 3 0 ( M001 BMP280 KONSTANTEN ) 1 2 04 CONSTANT DWA 3 05 CONSTANT DWB 4 06 CONSTANT SWA 5 07 CONSTANT SWB 6 10 CONSTANT MODSCH 7 CF CONSTANT BITMODE 8 7B CONSTANT BIT_OUT 9 FB CONSTANT BIT_IN 10 11 76 2* CONSTANT DEVADR 12 F4 CONSTANT 'CTRL 13 F5 CONSTANT 'CONF 14 F7 CONSTANT 'PTDAT 15 -->
SCR # 4 0 ( PORTA INITPIO GET SET ) 1 2 : PORTA ( I/O -> ) 3 BITMODE SWA BUSOUT 4 SWA BUSOUT 5 ; 6 : INITPIO ( - ) 7 BIT_OUT PORTA 8 ; 9 10 : GET ( -> B ) DWA BUSIN ; 11 : SET ( B -> ) DWA BUSOUT ; 12 13 : START ( - ) 84 SET 04 SET ; 14 : STOP ( - ) 04 SET 84 SET ; 15 -->
SCR # 5 0 ( SCL0 SCL1 BIT> >BIT >BYTE ) 1 2 : SCL0 ( - ) GET FB AND SET ; 3 : SCL1 ( - ) GET 4 OR SET ; 4 5 : BIT> ( N1 -> N2 ) 6 SCL0 DUP FB AND SET SCL1 2* 7 ; 8 : >BIT ( N1 -> N2 ) 9 SCL1 FF00 AND GET OR SCL0 2* 10 ; 11 : >BYTE ( -> N ) 12 SCL0 BIT_IN PORTA 13 0 8 0 DO >BIT LOOP 100H/ 14 BIT_OUT PORTA 15 ; -->
SCR # 6 0 ( BYTE> DWRITE ) 1 2 : BYTE> ( N -> ) 3 8 0 DO BIT> LOOP DROP 4 SCL0 BIT_IN PORTA 0 >BIT 5 100H/ . BIT_OUT PORTA 6 ; 7 8 9 10 : DWRITE ( B ADR -> ) 11 START DEVADR 12 3 0 DO BYTE> LOOP STOP 13 ; 14 15 -->
SCR # 7 0 ( DREAD ) 1 2 : DREAD ( DEST N ADR -> ) 3 START DEVADR BYTE> BYTE> 4 START DEVADR 1 OR BYTE> 5 1 - DUP IF 6 0 DO 7 >BYTE 0 SET SCL1 8 OVER C! 1+ 9 LOOP 10 ELSE DROP 11 ENDIF 12 >BYTE 80 SET SCL1 SWAP C! 13 STOP 14 ; 15 -->
SCR # 8 0 ( COMPDATA !COMPDATA ?COMPDATA ) 1 2 0 VARIABLE COMPDATA 18 ALLOT 3 4 : !COMPDATA ( - ) 5 COMPDATA 18 88 DREAD 6 ; 7 8 : ?COMPDATA ( - ) 9 CR 18 0 DO 10 COMPDATA I + ? CR 11 2 +LOOP 12 ; 13 14 15 -->
SCR # 9 0 : c0 COMPDATA @ ; 1 : c1 COMPDATA 2 + @ ; 2 : c2 COMPDATA 4 + @ ; 3 : c3 COMPDATA 6 + @ ; 4 : c4 COMPDATA 8 + @ ; 5 : c5 COMPDATA A + @ ; 6 : c6 COMPDATA C + @ ; 7 : c7 COMPDATA E + @ ; 8 : c8 COMPDATA 10 + @ ; 9 : c9 COMPDATA 12 + @ ; 10 : c10 COMPDATA 14 + @ ; 11 : c11 COMPDATA 16 + @ ; 12 0 VARIABLE v1 2 ALLOT 13 0 VARIABLE v1s 2 ALLOT 14 15 -->
SCR # 10 0 ( WAIT 50MS INIT ) 1 2 CREATE WAIT ( b -> ) 3 E1 C, 7D C, C5 C, 141E , 4 CD C, F00C , C1 C, 5 C3 C, NEXT , 6 DECIMAL SMUDGE 7 8 : 50MS ( N -> ) 9 0 DO 8 WAIT LOOP 10 ; 11 12 : INIT 13 1 MODSCH SWITCH INITPIO 14 !COMPDATA 15 ; -->
SCR # 11 0 ( UD* UD/ D/ D* ) 1 2 : UD* ( ud u -> ud ) 3 ROT OVER U* >R >R U* DROP 0 4 SWAP R> R> D+ ; 5 : UD/ ( ud u -> ud ) 6 M/MOD ROT DROP 7 ; 8 : D/ ( d n -> d ) 9 2DUP XOR >R 10 >R DABS R> ABS UD/ R> D+- 11 ; 12 : D* ( d n -> d ) 13 2DUP XOR >R 14 >R DABS R> ABS UD* R> D+- 15 ; -->
SCR # 12 0 ( X VT1 VT2 TF ) 1 2 : X ( d -> d ) 3 8 UD/ c0 2 U* DMINUS D+ 4 ; 5 : VT1 ( d -> d ) 6 c1 D* 2048 D/ 7 ; 8 : VT2 ( d -> d ) 9 2 D/ DROP ABS DUP U* 4096 10 D/ c2 D* 16384 D/ 11 ; 12 : TF ( d -> d ) 13 X 2DUP VT1 >R >R VT2 R> R> D+ 14 ; 15 -->
SCR # 13 0 : PINIT ( d -> ) 1 2 D/ -64000. D+ 2DUP v1 2! 4 2 D/ DROP ABS DUP U* 2048 D/ 3 v1s 2! ; 4 : T ( d -> n ) 5 TF 2DUP PINIT 6 5 D* 256 M/ SWAP 128 / + 7 ; 8 : V2 ( -> d ) 9 v1s 2@ c8 D* v1 2@ c7 D* 2 D* 10 D+ 4 D/ 0 c6 D+ 11 ; 12 : V3 ( -> d ) 13 v1s 2@ 4 D/ c5 D* 8 D/ v1 2@ 14 c4 D* 2 D/ D+ 512 D/ 512 D/ 15 ; -->
SCR # 14 0 : V4 ( -> d ) 1 V3 32768. D+ c3 UD* 8192 D/ 4 2 D/ 3 ; 4 : P0 ( d -> d ) 5 >R >R 1048576. R> R> DMINUS 6 D+ V2 4096 D/ DMINUS D+ 3125 7 D* V4 DROP UD/ 2 D* 8 ; 9 : W1 ( d -> d ) 10 8 D/ DROP ABS DUP U* 8192 11 D/ c11 D* 4096 D/ 12 ; 13 : W2 ( d -> d ) 14 4 D/ c10 D* 8192 D/ 15 ; -->
SCR # 15 0 ( P CTRL CONF RAW OS_T ) 1 2 : P ( d -> d ) 3 P0 2DUP W1 >R >R 2DUP 4 W2 R> R> D+ c9 0 D+ 16 D/ D+ 5 ; 6 7 0 VARIABLE CTRL 8 0 VARIABLE CONF 9 0 VARIABLE RAW 4 ALLOT 10 11 : OS_T ( N -> ) 12 32 * CTRL C@ 31 AND OR 13 CTRL C! 14 ; 15 -->
SCR # 16 0 ( OS_P MODE UPDATE ) 1 2 : OS_P ( N -> ) 3 4 * CTRL C@ 227 AND OR 4 CTRL C! 5 ; 6 : MODE ( N -> ) 7 CTRL C@ 252 AND OR CTRL C! 8 ; 9 : UPDATE ( - ) 10 CONF C@ 'CONF DWRITE 11 CTRL C@ 'CTRL DWRITE 12 1 50MS RAW 6 'PTDAT DREAD 13 ; 14 15 -->
SCR # 17 0 ( UT UP FORCED SLEEP ) 1 2 : UT ( -> d ) 3 RAW 4 + C@ 256 * RAW 5 + C@ + 4 RAW 3 + C@ 16 D/ 5 ; 6 : UP ( -> d ) 7 RAW 1+ C@ 256 * RAW 2 + C@ + 8 RAW C@ 16 D/ 9 ; 10 11 : FORCED 2 OS_T 4 OS_P 1 MODE ; 12 : SLEEP 0 MODE ; 13 14 15 -->
SCR # 18 0 ( .X MESS ) 1 2 : .X ( N -> ) 3 <# SWAP OVER DABS # # 46 HOLD 4 #S SIGN #> TYPE SPACE 5 ; 6 7 : MESS ( - ) 8 UPDATE CR 9 UT ." T = " T 0 .X ." C" CR 10 UP ." P = " P .X ." hPa" CR 11 ; 12 13 14 15
Hier noch ein Bild vom OLED. Unten ist auch der Drucksensor zu sehen.
Viele Grüße, Matthias. Dieser Beitrag wurde am 09.02.2019 um 14:31 Uhr von mwd editiert. |