Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 02:25 07 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

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 States
Posts: 209
Posted: 06:25pm 20 Sep 2016
Copy link to clipboard 
Print this post

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
Edited by redrok 2016-09-22
 
bigmik

Guru

Joined: 20/06/2011
Location: Australia
Posts: 2949
Posted: 07:38pm 21 Sep 2016
Copy link to clipboard 
Print this post

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 States
Posts: 209
Posted: 07:15pm 22 Sep 2016
Copy link to clipboard 
Print this post

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.

redrokEdited by redrok 2016-09-24
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025