![]() |
Forum Index : Microcontroller and PC projects : uMITE 5.2 Postfix FORTH like INKEY$ SFLCP
Author | Message | ||||
redrok![]() Senior Member ![]() Joined: 15/09/2014 Location: United StatesPosts: 209 |
Hi All; I was working on a driver for a Servo Motor with Quadrature Encoder. However, I ran into a problem. The encoder routines used interrupts to watch changes on the encoder. This motor has a bit of inertia. When the goal count was reached I immediately jumped to an INPUT command to tell the motor where to go next. But I would find that the motor had coasted past the goal. How can this be? I find out the interrupts are disabled during the INPUT command. I guess I could wait for the motor to settle down and then do the INPUT. But during this time the motor may have slipped a bit as there is no active interrupt control of the motor. Anyway, I find out that the INKEY$ function doesn't disable the interrupts so active control of the motor is still running in the background. I decided to make a reasonably simple input command processor. Mine is based on a FORTH like Postfix notation style which has push down stack. I find it very useful to have math functions when entering numbers. OK, I probably when overboard in this example but anything you don't need is easily removed or added functions easily added. The inner interpreter is about 8 lines long. It takes single keystrokes from INKEY$ and builds up characters in CMD$. CMD$ is tested for known character sequences and processes the commands or numbers on the stack. There is also a memory where intermediate values or constants can be stored. Try it and see what you think. It will take a bit of getting uses to to get the hang of the postfix notation like HP calculators. You may find you like it. This code was specifically designed to use the TERA TERM terminal in my PC. It makes extensive use of VT-100 color and cursor movement commands. I will keep updates of this code here: SFLCP.bas 'SFLCP.bas
'Simple FORTH Like Command Processor DT$="16/09/20" '28 pin uMITE Ver 5.2 (5.02) 'Written by Duane C. Johnson AD0TJ 'Red Rock Energy 'redrok@redrok.com 'http://www.redrok.com BK1$=CHR$(27)+"[1;30m" ' Bold Black RD1$=CHR$(27)+"[1;31m" ' Bold Red GR1$=CHR$(27)+"[1;32m" ' Bold Green YE1$=CHR$(27)+"[1;33m" ' Bold Yellow BU1$=CHR$(27)+"[1;34m" ' Bold Blue MG1$=CHR$(27)+"[1;35m" ' Bold Magenta CY1$=CHR$(27)+"[1;36m" ' Bold Cyan ED2$=CHR$(27)+"[2J" ' Erase Display After the Curser, Pause 500mS EL0$=CHR$(27)+"[0K" ' ERACE TO EOL HM1$=CHR$(27)+"[f" ' Curser to Upper Left Corner UP1$=CHR$(27)+"[1A" ' Up 1 Line PRINT ED2$; StkLen = 3 ' Visable Stack Elements, 0 TO StkLen MemLen = 3 ' IF -1 No Memerys will be visable MemExtra=10 IF StkLen < 1THEN StkLen = 1 ' Minimum of 2, 2Over Still Works IF MemLen <-1THEN MemLen =-1 IF MemExtra< 2THEN MemExtra= 2 DIM FLOAT Stk(StkLen+2) DIM STRING StkLbl(StkLen+2) FOR T=StkLen+2 TO 4 STEP -1:StkLbl(T)=STR$(T,LEN(STR$(StkLen)),0):NEXT T StkLbl(3)=SPACE$(LEN(STR$(StkLen))-1)+"T" StkLbl(2)=SPACE$(LEN(STR$(StkLen))-1)+"Z" StkLbl(1)=SPACE$(LEN(STR$(StkLen))-1)+"Y" StkLbl(0)=SPACE$(LEN(STR$(StkLen))-1)+"X" DIM Mem(MemLen+MemExtra):FOR T=0 TO MemLen+MemExtra:Mem(T)=0:NEXT T ' Mem(1)=3.40282e+38 ' NumMax=3.40282e+38 3.40282347e+38 ' Mem(0)=1.17549e-38 ' NumMin=1.17549e-38 1.17549435e-38 GOSUB DispStk AGAIN: GOSUB DispStk:CMD$="":PRINT BU1$; INP: IN$=INKEY$:IF IN$=""THEN GOTO INP CMD$=CMD$+UCASE$(IN$) IF LEN(CMD$)=1 THEN PRINT EL0$; GOSUB DispStk:PRINT BU1$;CMD$:PRINT UP1$; ' Special Characters IF ASC(IN$)= 8 THEN PRINT EL0$;:GOTO AGAIN 'Backspace Key Delete Entry IF ASC(IN$)=13 OR ASC(IN$)=32 THEN GOSUB DupStk:Stk(0)=VAL(CMD$):GOSUB DispStk:GOTO AGAIN IF ASC(IN$)=61 THEN GOSUB DoSomeThing:GOTO AGAIN ' "=" ' The Commands IF CMD$="+" THEN GOSUB plus :PRINT"+ ";CY1$;"FLOAT Y+X"; :GOTO AGAIN IF CMD$="P" THEN GOSUB plus :PRINT"+ ";CY1$;"FLOAT Y+X"; :GOTO AGAIN IF CMD$="-" THEN GOSUB minus :PRINT"- ";CY1$;"FLOAT Y-X"; :GOTO AGAIN IF CMD$="*" THEN GOSUB times :PRINT"* ";CY1$;"FLOAT Y*X"; :GOTO AGAIN IF CMD$="T" THEN GOSUB times :PRINT"* ";CY1$;"FLOAT Y*X"; :GOTO AGAIN IF CMD$="/" THEN GOSUB divide :PRINT"/ ";CY1$;"FLOAT Y/X"; :GOTO AGAIN IF CMD$="\" THEN GOSUB idivide:PRINT"\ ";CY1$;"CINT(Y)\CINT(X)"; :GOTO AGAIN ' USES CINT() IF CMD$="^" THEN GOSUB YtoX :PRINT"^ ";CY1$;"FLOAT Y^X"; :GOTO AGAIN IF CMD$="?" THEN GOSUB Help :PRINT"? ";CY1$;"HELP"; :GOTO AGAIN IF CMD$="H" THEN GOSUB Help :PRINT"H ";CY1$;"HELP"; :GOTO AGAIN IF CMD$="C" THEN GOSUB ClStk :PRINT"C ";CY1$;"CLEAR STACK"; :GOTO AGAIN IF CMD$="D" THEN PRINT"D ";CY1$;"d";BU1$;"R";CY1$;"op,d";BU1$;"U";CY1$;"p";:GOTO INP IF CMD$="DR"THEN GOSUB DRopStk:PRINT"DR";CY1$;" DROP STACK"; :GOTO AGAIN IF CMD$="DU"THEN GOSUB DUpStk :PRINT"DU";CY1$;" DUP STACK"; :GOTO AGAIN IF CMD$="I" THEN GOSUB Integr :PRINT"I ";CY1$;"INTEGER INT(x)"; :GOTO AGAIN ' INT() IF CMD$="L" THEN GOSUB LstX :PRINT"L ";CY1$;"LAST X"; :GOTO AGAIN IF CMD$="M" THEN PRINT"M ";CY1$;"m";BU1$;"O";CY1$;"d,";BU1$;"R";CY1$;"ecall,";BU1$;"S";CY1$;"tore";:GOTO INP IF CMD$="MO"THEN GOSUB MOdulus:PRINT"MO";CY1$;" INTEGER Y MOD X";:GOTO AGAIN IF CMD$="MR"THEN GOSUB MRecall:PRINT"MR";CY1$;" MEM RECALL ";:GOTO AGAIN IF CMD$="MS"THEN GOSUB MStore :PRINT"MS";CY1$;" MEM STORE ";:GOTO AGAIN IF CMD$="N" THEN GOSUB Negate :PRINT"N ";CY1$;"NEGATE -(X)"; :GOTO AGAIN IF CMD$="O" THEN GOSUB OverStk:PRINT"O ";CY1$;"OVER"; :GOTO AGAIN IF CMD$="2O"THEN GOSUB Ovr2Stk:PRINT"2O";CY1$;" 2OVER"; :GOTO AGAIN IF CMD$="R" THEN PRINT"R D";CY1$;"own, r";BU1$;"O";CY1$;"und, ";BU1$;"U";CY1$;"p";:GOTO INP IF CMD$="RD"THEN GOSUB RollDn :PRINT"RD";CY1$;" ROLL DOWN "; :GOTO AGAIN IF CMD$="RO"THEN GOSUB ROund :PRINT"RO";CY1$;" ROUND CINT(X) "; :GOTO AGAIN ' CINT() IF CMD$="RU"THEN GOSUB RollUp :PRINT"RU";CY1$;" ROLL UP "; :GOTO AGAIN IF CMD$="S" THEN GOSUB SwapStk:PRINT"S ";CY1$;"SWAP X&Y"; :GOTO AGAIN IF CMD$="V" THEN GOSUB inVrt :PRINT"V ";CY1$;"FLOAT 1/X"; :GOTO AGAIN IF CMD$="X" THEN GOSUB fiXx :PRINT"X ";CY1$;"FIX(X)"; :GOTO AGAIN ' Truncate X GOTO INP DoSomeThing: ' Jump to where the value in Stk(n) or Mem(m) will be used. PRINT CHR$(7); END SUB DispStk: PRINT HM1$;ED2$; ' Curser To Home FOR T=MemLen TO 0 STEP-1 PRINT EL0$; ' Erace To EOL 'PRINT BK1$;"M";STR$(T,2);STR$(Mem(T),7) ' Print Memory PRINT BK1$;"M";STR$(T,2);" ";Mem(T) ' Print Memory NEXT T FOR T=StkLen TO 0 STEP-1 PRINT EL0$; ' Erace To EOL 'PRINT BU1$;"S ";StkLbl(T);STR$(Stk(T),7) ' Print Stack PRINT BU1$;"S ";StkLbl(T);" ";Stk(T) ' Print Stack NEXT T 'PRINT EL0$;RD1$;"LX=";STR$(LASTX,7) ' Last X PRINT EL0$;RD1$;"LX=";" ";LASTX ' Last X PRINT:PRINT UP1$;BU1$; END SUB Help: 'H or ? PRINT HM1$;ED2$;STRING$(40,45) PRINT"DU DUp|DR|DRop|S Swap |O Over |2O 2Over" PRINT"MO MOd| ^ Y^X | | | C ClrStk" PRINT" + Add| - Sub |* Times|/ FlDiv| \ IntDiv" PRINT" I Int| X fiX |RO ROnd|V inVrt| N Negate" PRINT"MS Sto|MR Rcl |L LastX|RU RolUp|RD RolDn" PRINT STRING$(40,45) PRINT"This FORTH like input command processor" PRINT" uses INKEY$, unlike INPUT, that doesn't" PRINT" disable interupts." PRINT"It processes INKEY$ one character at a" PRINT" time terminated by SPACE or ENTER keys." PRINT"A special key ";CHR$(61);" jumps to a subroutine" PRINT" where the results of calculations can" PRINT" control a running program." PRINT"I have included many commands I find" PRINT" useful. More can be added as needed or" PRINT" a bare minimum to concerve space." PRINT"Stack & Memory are easy to configure." PRINT" I hope I have made it fairly easy to" PRINT" do this." PRINT STRING$(40,45) MEMORY PRINT STRING$(40,45); Hlp:Q$=INKEY$:IF Q$=""THEN GOTO Hlp ELSE PRINT HM1$;ED2$;:GOSUB DispStk END SUB LX: LASTX=Stk(0) END SUB SUB MM.PROMPT PRINT RD1$;"SFLCP";BU1$;">"; END SUB ' Do The Commands plus: GOSUB LX:TM0=Stk(1)+Stk(0):GOSUB DropStk:Stk(0)=TM0 :END SUB '+ minus: GOSUB LX:TM1=Stk(1)-Stk(0):GOSUB DropStk:Stk(0)=TM1 :END SUB '- times: GOSUB LX:TM2=Stk(1)*Stk(0):GOSUB DropStk:Stk(0)=TM2 :END SUB '* divide: GOSUB LX:TM3=Stk(1)/Stk(0):GOSUB DropStk:Stk(0)=TM3 :END SUB '/ ' GOSUB LX:ON ERROR SKIP:TM3=Stk(1)/Stk(0):GOSUB DropStk:Stk(0)=TM3: ' IF MM.ERRNO=16 THEN Stk(0)=3.40282e+38 :END SUB '/ idivide: GOSUB LX:TM4=Stk(1)\Stk(0):GOSUB DropStk:Stk(0)=TM4 :END SUB '\ Integer Divide 'GOSUB LX:ON ERROR SKIP:TM4=Stk(1)\Stk(0):GOSUB DropStk:Stk(0)=TM4 'IF MM.ERRNO=16 THEN Stk(0)=3.40282e+38 :END SUB '\ Integer Divide YtoX: GOSUB LX:TM5=Stk(1)^Stk(0):GOSUB DropStk:Stk(0)=TM5 :END SUB '^ Exponentiation ClStk: FOR T=0 TO StkLen+2 STEP 1:Stk(T)=0:NEXT T:LASTX=0 :END SUB 'C DRopStk: FOR T= 1 TO StkLen+2 STEP 1:Stk(T-1)=Stk(T):NEXT T :END SUB 'DR DUpStk: FOR T=StkLen+2 TO 1 STEP -1:Stk(T)=Stk(T-1):NEXT T:STK(0)=Stk(1):END SUB 'DU Integr: GOSUB LX:Stk(0)=INT(Stk(0)) :END SUB 'I Integer LstX: FOR T= StkLen+2 TO 1 STEP -1:Stk(T)=Stk(T-1):NEXT T:Stk(0)=LASTX:END SUB 'L Last X MOdulus: GOSUB LX:TM6=Stk(1)MOD Stk(0):GOSUB DropStk:Stk(0)=TM6 :END SUB 'MO MOdulus ' GOSUB LX:ON ERROR SKIP:TM6=Stk(1)MOD Stk(0):GOSUB DropStk:Stk(0)=TM6: ' IF MM.ERRNO=16 THEN Stk(0)=3.40282e+38 :END SUB 'MO MOdulus MRecall: Stk(0)=Mem(Stk(0)) :END SUB 'MR MStore: Mem(Stk(0))=Stk(1):GOSUB DropStk :END SUB 'MS Negate: GOSUB LX:Stk(0)=-Stk(0) :END SUB 'N Negate OverStk: FOR T=StkLen+2 TO 2 STEP -1:Stk(T)=Stk(T-1):NEXT T:Stk(2)=Stk(0):END SUB 'O Ovr2Stk: FOR T=StkLen+2 TO 2 STEP -1:Stk(T)=Stk(T-2):NEXT T:Stk(2)=Stk(0):Stk(3)=Stk(1):END SUB '2O RollDn: TM7=Stk(0):GOSUB DRopStk:Stk(StkLen)=TM7 :END SUB 'RD ROund: GOSUB LX:Stk(0)=CINT(Stk(0)) :END SUB 'RO ROund OR CINT FUNCTION RollUp: TM8=Stk(StkLen):GOSUB DUpStk:Stk(0)=TM8 :END SUB 'RU SwapStk: TM9=Stk(0):Stk(0)=Stk(1):Stk(1)=TM9 :END SUB 'S inVrt: GOSUB LX:Stk(0)=1/Stk(0) :END SUB 'V inVert fiXx: GOSUB LX:Stk(0)=FIX(Stk(0)) :END SUB 'X fiXx END redrok |
||||
bigmik![]() Guru ![]() Joined: 20/06/2011 Location: AustraliaPosts: 2949 |
Hi Redrok, I have NO IDEA what you are doing but you gladden my heart with all those GOSUBS and GOTOS.. (They are not dead ... YET!!) ![]() ![]() ![]() ![]() ![]() ![]() Mick Mick's uMite Stuff can be found >>> HERE (Kindly hosted by Dontronics) <<< |
||||
redrok![]() Senior Member ![]() Joined: 15/09/2014 Location: United StatesPosts: 209 |
Hi bigmik; OK, technically, this example doesn't actually do anything except generate a beep when the "=" key is pressed. The program is essentially a Polish Calculator built using the INKEY$. A kind of smart input device that is programmable and can do math on the fly. I find this type of input method very convenient. Such as: 1. Not needing to remember what what 65536 is Just do this. 2 space 16 space ^ = now 65536 is entered. Nice and easy. 2. Remember a number of values in a memory. 3. Do things like add a constant value: Start with 100 and keep adding 2 100 space = 2 space + = L + = L + = L + = (L for last x) This entered 100, 102, 104, 106, 108 4. Entering a number and its negative value repeatedly. 12345 space = N = N = N = (N for NEGATE) This entered 12345, -12345, 12345, -12345 Have fun with it. Just press H or ? for a small help message. redrok |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |