1248 lines
77 KiB
Plaintext
1248 lines
77 KiB
Plaintext
{{
|
|
Modified Tiny Basic for use with Propeller Demo Board and Hydra.
|
|
Original Tiny Basic written by Tomas Rokicki & Radical Eye Software.
|
|
|
|
Copyright (c) 2008 Michael Green. See end of file for terms of use.
|
|
}}
|
|
|
|
'' Note: There are three places in the next 50 lines where there are
|
|
'' pairs of lines with one commented out. One is marked TV
|
|
'' and the other is marked VGA. All three places should have
|
|
'' the appropriate line commented out for the display being used.
|
|
'' The combination of Hydra and VGA is not supported because the
|
|
'' I/O pins used for the SD card and the VGA display conflict.
|
|
|
|
|
|
{{ ---------------------------------------------------------------------------------------------------------
|
|
|
|
Hive-Computer-Projekt
|
|
|
|
Name : FemtoBasic
|
|
Chip : Regnatix-Code
|
|
Version : 0.1
|
|
Dateien :
|
|
|
|
Beschreibung : Modifiziertes FemtoBasic für den Hive.
|
|
|
|
Eigenschaften :
|
|
|
|
Logbuch :
|
|
|
|
29.04.2009 - erste an ios angepasste version
|
|
- eeprom-zugriff deaktiviert
|
|
|
|
|
|
|
|
Notizen:
|
|
|
|
|
|
--------------------------------------------------------------------------------------------------------- }}
|
|
|
|
obj
|
|
ios : "ios.spin"
|
|
|
|
con
|
|
|
|
_CLKMODE = XTAL1 + PLL16X
|
|
_XINFREQ = 5_000_000
|
|
|
|
version = 3 ' Major version
|
|
release = 006 ' Minor release
|
|
testLevel = 0 ' Test change level
|
|
|
|
' progsize = 8192 ' Space reserved for program
|
|
progsize = $3FFF
|
|
_stack = 100 ' Roughly 4 nested expressions
|
|
_free = (progsize + 12) / 4
|
|
|
|
bspKey = $C8 ' PS/2 keyboard backspace key
|
|
breakKey = $CB ' PS/2 keyboard escape key
|
|
backspace = 8
|
|
fReturn = 13
|
|
fLinefeed = 10
|
|
fEof = $FF
|
|
|
|
maxstack = 20 ' Maximum stack depth
|
|
linelen = 256 ' Maximum input line length
|
|
quote = 34 ' Double quote
|
|
caseBit = !32 ' Uppercase/Lowercase bit
|
|
' userPtr = $7FEC ' Pointer to program memory
|
|
userPtr = $4000
|
|
|
|
var
|
|
long sp, tp, eop, nextlineloc, rv, curlineno, pauseTime
|
|
long vars[26], stack[maxstack], control[2]
|
|
long forStep[26], forLimit[26], forLoop[26]
|
|
long ioControl[2]
|
|
word outputs
|
|
byte tline[linelen], tailLine[linelen], inVars[26], fileOpened
|
|
|
|
dat
|
|
tok0 byte "IF", 0
|
|
tok1 byte "THEN", 0
|
|
tok2 byte "INPUT", 0 ' INPUT {"<prompt>";} <var> {,<var>}
|
|
tok3 byte "PRINT", 0 ' PRINT {USING "<format>";} ...
|
|
tok4 byte "GOTO", 0
|
|
tok5 byte "GOSUB", 0
|
|
tok6 byte "RETURN", 0
|
|
tok7 byte "REM", 0
|
|
tok8 byte "NEW", 0
|
|
tok9 byte "LIST", 0
|
|
tok10 byte "RUN", 0
|
|
tok11 byte "RND", 0
|
|
tok12 byte "OPEN", 0 ' OPEN " <file> ",<mode>
|
|
tok13 byte "READ", 0 ' READ <var> {,<var>}
|
|
tok14 byte "WRITE", 0 ' WRITE {USING "<format>";} ...
|
|
tok15 byte "CLOSE", 0 ' CLOSE
|
|
tok16 byte "DELETE", 0 ' DELETE " <file> "
|
|
tok17 byte "RENAME", 0 ' RENAME " <file> "," <file> "
|
|
tok18 byte "FILES", 0 ' FILES
|
|
tok19 byte "SAVE", 0 ' SAVE or SAVE [<expr>] or SAVE "<file>"
|
|
tok20 byte "LOAD", 0 ' LOAD or LOAD [<expr>] or LOAD "<file>"
|
|
tok21 byte "NOT" ,0 ' NOT <logical>
|
|
tok22 byte "AND" ,0 ' <logical> AND <logical>
|
|
tok23 byte "OR", 0 ' <logical> OR <logical>
|
|
tok24 byte "SHL", 0 ' <expr> SHL <expr>
|
|
tok25 byte "SHR", 0 ' <expr> SHR <expr>
|
|
tok26 byte "FOR", 0 ' FOR <var> = <expr> TO <expr>
|
|
tok27 byte "TO", 0
|
|
tok28 byte "STEP", 0 ' optional STEP <expr>
|
|
tok29 byte "NEXT", 0 ' NEXT <var>
|
|
tok30 byte "INA", 0 ' INA [ <expr> ]
|
|
tok31 byte "OUTA", 0 ' OUTA [ <expr> ] = <expr>
|
|
tok32 byte "PAUSE", 0 ' PAUSE <time ms> {,<time us>}
|
|
tok33 byte "USING", 0 ' PRINT USING "<format>"; ...
|
|
tok34 byte "ROL", 0 ' <expr> ROL <expr>
|
|
tok35 byte "ROR", 0 ' <expr> ROR <expr>
|
|
tok36 byte "SAR", 0 ' <expr> SAR <expr>
|
|
tok37 byte "REV", 0 ' <expr> REV <expr>
|
|
tok38 byte "BYTE", 0 ' BYTE [ <expr> ]
|
|
tok39 byte "WORD", 0 ' WORD [ <expr> ]
|
|
tok40 byte "LONG", 0 ' LONG [ <expr> ]
|
|
tok41 byte "CNT", 0
|
|
tok42 byte "PHSA", 0
|
|
tok43 byte "PHSB", 0
|
|
tok44 byte "FRQA", 0
|
|
tok45 byte "FRQB", 0
|
|
tok46 byte "CTRA", 0
|
|
tok47 byte "CTRB", 0
|
|
tok48 byte "DISPLAY", 0 ' DISPLAY <expr> {,<expr>}
|
|
tok49 byte "KEYCODE", 0 ' KEYCODE
|
|
tok50 byte "LET", 0
|
|
tok51 byte "STOP", 0
|
|
tok52 byte "END", 0
|
|
tok53 byte "EEPROM", 0 ' EEPROM[ <expr> ]
|
|
tok54 byte "FILE", 0 ' FILE
|
|
tok55 byte "MEM", 0 ' MEM
|
|
tok56 byte "SPIN", 0 ' SPIN [<expr>] or SPIN "<file>"
|
|
tok57 byte "COPY", 0 ' COPY [<expr>],"<file>" or COPY "<file>",[<expr>] or
|
|
' COPY [<expr>],<expr> where <expr> are different
|
|
tok58 byte "DUMP", 0 ' DUMP <expr>,<expr> or DUMP [<expr>],<expr>
|
|
|
|
toks word @tok0, @tok1, @tok2, @tok3, @tok4, @tok5, @tok6, @tok7
|
|
word @tok8, @tok9, @tok10, @tok11, @tok12, @tok13, @tok14, @tok15
|
|
word @tok16, @tok17, @tok18, @tok19, @tok20, @tok21, @tok22, @tok23
|
|
word @tok24, @tok25, @tok26, @tok27, @tok28, @tok29, @tok30, @tok31
|
|
word @tok32, @tok33, @tok34, @tok35, @tok36, @tok37, @tok38, @tok39
|
|
word @tok40, @tok41, @tok42, @tok43, @tok44, @tok45, @tok46, @tok47
|
|
word @tok48, @tok49, @tok50, @tok51, @tok52, @tok53, @tok54, @tok55
|
|
word @tok56, @tok57, @tok58
|
|
tokx word
|
|
|
|
syn byte "Syntax Error", 0
|
|
ln byte "Invalid Line Number", 0
|
|
|
|
ver byte "▶Hive: FemtoBasic • 18-09-2010-dr235",13,0
|
|
|
|
PUB main | err, s
|
|
|
|
ios.start
|
|
|
|
' code für test im ram, sollte bei bin-datei auskommentiert werden
|
|
' ios.startram
|
|
|
|
' clear the program space and variables, then read a line and interpret it.
|
|
pauseTime := 0
|
|
outputs := 0
|
|
fileOpened := 0
|
|
long[userPtr] := userPtr - progsize ' Allocate memory
|
|
waitcnt(clkfreq + cnt) ' wozu das?
|
|
ios.screeninit(@ver,1)
|
|
clearall
|
|
s := 0
|
|
curlineno := -1
|
|
|
|
repeat
|
|
err := \doline(s) ' eine kommandozeile verarbeiten
|
|
s := 0
|
|
if err ' fehler?
|
|
showError(err)
|
|
|
|
pri doline(s) | c ' Execute the string in s or wait for input
|
|
curlineno := -1
|
|
|
|
if ios.keystat > 0 ' Was the "break key" pressed?
|
|
if ios.key == ios#CHAR_ESC ' escape?
|
|
nextlineloc := eop-2 ' Stop the program
|
|
|
|
if nextlineloc < eop-2
|
|
curlineno := wordat(nextlineloc)
|
|
tp := nextlineloc + 2
|
|
nextlineloc := tp + strsize(tp) + 1
|
|
texec
|
|
else
|
|
pauseTime := 0
|
|
outputs := 0
|
|
if s
|
|
bytemove(tp:=@tline,s,strsize(s)+1)
|
|
else
|
|
putlinet(string("OK"))
|
|
getline
|
|
c := spaces
|
|
if "0" =< c and c =< "9"
|
|
insertline
|
|
nextlineloc := eop - 2
|
|
else
|
|
tokenize
|
|
if spaces
|
|
texec
|
|
|
|
PRI showError(err)
|
|
if curlineno => 0
|
|
ios.print(string("IN LINE "))
|
|
ios.printdec(curlineno)
|
|
ios.printchar(" ")
|
|
if err < 0
|
|
ios.print(string("SD card "))
|
|
ios.printdec(err)
|
|
ios.printnl
|
|
else
|
|
putlinet(err)
|
|
nextlineloc := eop - 2
|
|
|
|
PRI getline | i, c
|
|
|
|
i := 0
|
|
repeat
|
|
c := ios.keywait
|
|
if c == ios#CHAR_BS
|
|
if i > 0
|
|
ios.printctrl(ios#CHAR_TER_BS)
|
|
i--
|
|
elseif c == fReturn
|
|
ios.printchar(c)
|
|
tline[i] := 0
|
|
tp := @tline
|
|
return
|
|
elseif i < linelen-1
|
|
ios.printchar(c)
|
|
tline[i++] := c
|
|
|
|
pri putlinet(s) | c, ntoks
|
|
ntoks := (@tokx - @toks) / 2
|
|
repeat while c := byte[s++]
|
|
if c => 128
|
|
if (c -= 128) < ntoks
|
|
ios.print(@@toks[c])
|
|
if c <> 7 ' REM
|
|
ios.printchar(" ")
|
|
else
|
|
ios.printchar("{")
|
|
ios.printdec(c)
|
|
ios.printchar("}")
|
|
else
|
|
ios.printchar(c)
|
|
ios.printchar(fReturn)
|
|
|
|
pri spaces | c
|
|
repeat
|
|
c := byte[tp]
|
|
if c == 0 or c > " "
|
|
return c
|
|
tp++
|
|
|
|
pri skipspaces
|
|
if byte[tp]
|
|
tp++
|
|
return spaces
|
|
|
|
pri parseliteral | r, c
|
|
r := 0
|
|
repeat
|
|
c := byte[tp]
|
|
if c < "0" or c > "9"
|
|
return r
|
|
r := r * 10 + c - "0"
|
|
tp++
|
|
|
|
pri movprog(at, delta)
|
|
if eop + delta + 2 - long[userPtr] > progsize
|
|
abort string("NO MEMORY")
|
|
bytemove(at+delta, at, eop-at)
|
|
eop += delta
|
|
|
|
pri fixvar(c)
|
|
if c => "a"
|
|
c -= 32
|
|
return c - "A"
|
|
|
|
pri isvar(c)
|
|
c := fixvar(c)
|
|
return c => 0 and c < 26
|
|
|
|
pri tokenize | tok, c, at, put, state, i, j, ntoks
|
|
ntoks := (@tokx - @toks) / 2
|
|
at := tp
|
|
put := tp
|
|
state := 0
|
|
repeat while c := byte[at]
|
|
if c == quote
|
|
if state == "Q"
|
|
state := 0
|
|
elseif state == 0
|
|
state := "Q"
|
|
if state == 0
|
|
repeat i from 0 to ntoks-1
|
|
tok := @@toks[i]
|
|
j := 0
|
|
repeat while byte[tok] and ((byte[tok] ^ byte[j+at]) & caseBit) == 0
|
|
j++
|
|
tok++
|
|
if byte[tok] == 0 and not isvar(byte[j+at])
|
|
byte[put++] := 128 + i
|
|
at += j
|
|
if i == 7
|
|
state := "R"
|
|
else
|
|
repeat while byte[at] == " "
|
|
at++
|
|
state := "F"
|
|
quit
|
|
if state == "F"
|
|
state := 0
|
|
else
|
|
byte[put++] := byte[at++]
|
|
else
|
|
byte[put++] := byte[at++]
|
|
byte[put] := 0
|
|
|
|
pri wordat(loc)
|
|
return (byte[loc]<<8)+byte[loc+1]
|
|
|
|
pri findline(lineno) | at
|
|
at := long[userPtr]
|
|
repeat while wordat(at) < lineno
|
|
at += 3 + strsize(at+2)
|
|
return at
|
|
|
|
pri insertline | lineno, fc, loc, locat, newlen, oldlen
|
|
lineno := parseliteral
|
|
if lineno < 0 or lineno => 65535
|
|
abort @ln
|
|
tokenize
|
|
fc := spaces
|
|
loc := findline(lineno)
|
|
locat := wordat(loc)
|
|
newlen := 3 + strsize(tp)
|
|
if locat == lineno
|
|
oldlen := 3 + strsize(loc+2)
|
|
if fc == 0
|
|
movprog(loc+oldlen, -oldlen)
|
|
else
|
|
movprog(loc+oldlen, newlen-oldlen)
|
|
elseif fc
|
|
movprog(loc, newlen)
|
|
if fc
|
|
byte[loc] := lineno >> 8
|
|
byte[loc+1] := lineno
|
|
bytemove(loc+2, tp, newlen-2)
|
|
|
|
pri clearvars
|
|
bytefill(@vars, 0, 26)
|
|
pauseTime := 0
|
|
nextlineloc := long[userPtr]
|
|
sp := 0
|
|
|
|
pri newprog
|
|
byte[long[userPtr]][0] := 255
|
|
byte[long[userPtr]][1] := 255
|
|
byte[long[userPtr]][2] := 0
|
|
eop := long[userPtr] + 2
|
|
nextlineloc := eop - 2
|
|
sp := 0
|
|
|
|
pri clearall
|
|
newprog
|
|
clearvars
|
|
|
|
pri pushstack
|
|
if sp => constant(maxstack-1)
|
|
abort string("RECURSION ERROR")
|
|
stack[sp++] := nextlineloc
|
|
|
|
pri getAddress(delim) | t
|
|
if spaces <> "["
|
|
abort @syn
|
|
skipspaces
|
|
result := expr
|
|
if delim == "." and (result < 0 or result > 31)
|
|
abort string("Invalid pin number")
|
|
if delim == "." or delim == ","
|
|
if spaces == delim
|
|
if delim == "." ' Handle the form <expr>..<expr>
|
|
if byte[++tp] <> "."
|
|
abort @syn
|
|
result <<= 8
|
|
skipspaces
|
|
t := expr
|
|
if t < 0 or t > 31
|
|
abort string("Invalid pin number")
|
|
result |= t | $10000
|
|
else ' Handle the form <expr>,<expr>
|
|
if result & 1 or result < 0 or result > 31
|
|
abort string("Invalid pin number")
|
|
skipspaces
|
|
result := (result << 18) | (expr & $7FFFF)
|
|
elseif delim == ","
|
|
result := (result & $7FFFF)
|
|
if spaces <> "]"
|
|
abort @syn
|
|
tp++
|
|
|
|
pri factor | tok, t, i
|
|
tok := spaces
|
|
tp++
|
|
case tok
|
|
"(":
|
|
t := expr
|
|
if spaces <> ")"
|
|
abort @syn
|
|
tp++
|
|
return t
|
|
"a".."z","A".."Z":
|
|
return vars[fixvar(tok)]
|
|
158: ' INA [ <expr>{..<expr>} ]
|
|
t := getAddress(".")
|
|
if t > $FFFF
|
|
tok := t & $FF
|
|
t := (t >> 8) & $FF
|
|
repeat i from t to tok
|
|
outputs &= ! |< i
|
|
dira[t..tok]~
|
|
return ina[t..tok]
|
|
else
|
|
outputs &= ! |< t
|
|
dira[t]~
|
|
return ina[t]
|
|
166: ' BYTE [ <expr> ]
|
|
return byte[getAddress(" ")]
|
|
167: ' WORD [ <expr> ]
|
|
return word[getAddress(" ")]
|
|
168: ' LONG [ <expr> ]
|
|
return long[getAddress(" ")]
|
|
181: ' EEPROM [ <expr> ]
|
|
' code ausgefügt
|
|
return
|
|
182: ' FILE
|
|
return ios.sdgetc
|
|
183: ' MEM
|
|
return progsize - (eop - long[userPtr] )
|
|
169: ' CNT
|
|
return CNT
|
|
170: ' PHSA
|
|
return PHSA
|
|
171: ' PHSB
|
|
return PHSB
|
|
172: ' FRQA
|
|
return FRQA
|
|
173: ' FRQB
|
|
return FRQB
|
|
174: ' CTRA
|
|
return CTRA
|
|
175: ' CTRB
|
|
return CTRB
|
|
177: ' KEYCODE
|
|
return ios.keywait
|
|
139: ' RND <factor>
|
|
return (rv? >> 1) ** (factor << 1)
|
|
"-":
|
|
return - factor
|
|
"!":
|
|
return ! factor
|
|
"$", "%", quote, "0".."9":
|
|
--tp
|
|
return getAnyNumber
|
|
other:
|
|
abort(@syn)
|
|
|
|
pri shifts | tok, t
|
|
t := factor
|
|
tok := spaces
|
|
if tok == 152 ' SHL
|
|
tp++
|
|
return t << factor
|
|
elseif tok == 153 ' SHR
|
|
tp++
|
|
return t >> factor
|
|
elseif tok == 162 ' ROL
|
|
tp++
|
|
return t <- factor
|
|
elseif tok == 163 ' ROR
|
|
tp++
|
|
return t -> factor
|
|
elseif tok == 164 ' SAR
|
|
tp++
|
|
return t ~> factor
|
|
elseif tok == 165 ' REV
|
|
tp++
|
|
return t >< factor
|
|
else
|
|
return t
|
|
|
|
pri bitFactor | tok, t
|
|
t := shifts
|
|
repeat
|
|
tok := spaces
|
|
if tok == "&"
|
|
tp++
|
|
t &= shifts
|
|
else
|
|
return t
|
|
|
|
pri bitTerm | tok, t
|
|
t := bitFactor
|
|
repeat
|
|
tok := spaces
|
|
if tok == "|"
|
|
tp++
|
|
t |= bitFactor
|
|
elseif tok == "^"
|
|
tp++
|
|
t ^= bitFactor
|
|
else
|
|
return t
|
|
|
|
pri term | tok, t
|
|
t := bitTerm
|
|
repeat
|
|
tok := spaces
|
|
if tok == "*"
|
|
tp++
|
|
t *= bitTerm
|
|
elseif tok == "/"
|
|
if byte[++tp] == "/"
|
|
tp++
|
|
t //= bitTerm
|
|
else
|
|
t / =bitTerm
|
|
else
|
|
return t
|
|
|
|
pri arithExpr | tok, t
|
|
t := term
|
|
repeat
|
|
tok := spaces
|
|
if tok == "+"
|
|
tp++
|
|
t += term
|
|
elseif tok == "-"
|
|
tp++
|
|
t -= term
|
|
else
|
|
return t
|
|
|
|
pri compare | op, a, b, c
|
|
a := arithExpr
|
|
op := 0
|
|
spaces
|
|
repeat
|
|
c := byte[tp]
|
|
case c
|
|
"<": op |= 1
|
|
tp++
|
|
">": op |= 2
|
|
tp++
|
|
"=": op |= 4
|
|
tp++
|
|
other: quit
|
|
case op
|
|
0: return a
|
|
1: return a < arithExpr
|
|
2: return a > arithExpr
|
|
3: return a <> arithExpr
|
|
4: return a == arithExpr
|
|
5: return a =< arithExpr
|
|
6: return a => arithExpr
|
|
7: abort string("Invalid comparison")
|
|
|
|
pri logicNot | tok
|
|
tok := spaces
|
|
if tok == 149 ' NOT
|
|
tp++
|
|
return not compare
|
|
return compare
|
|
|
|
pri logicAnd | t, tok
|
|
t := logicNot
|
|
repeat
|
|
tok := spaces
|
|
if tok == 150 ' AND
|
|
tp++
|
|
t := t and logicNot
|
|
else
|
|
return t
|
|
|
|
pri expr | tok, t
|
|
t := logicAnd
|
|
repeat
|
|
tok := spaces
|
|
if tok == 151 ' OR
|
|
tp++
|
|
t := t or logicAnd
|
|
else
|
|
return t
|
|
|
|
pri specialExpr
|
|
if spaces <> "="
|
|
abort @syn
|
|
skipspaces
|
|
return expr
|
|
|
|
pri scanFilename(f) | c, chars
|
|
chars := 0
|
|
tp++ ' skip past initial quote
|
|
repeat while (c := byte[tp++]) <> quote
|
|
if chars++ < 31
|
|
byte[f++] := c
|
|
byte[f] := 0
|
|
|
|
pri texec | ht, nt, restart, thisLine, uS, a,b,c,d, f0,f1,f2,f3,f4,f5,f6,f7
|
|
uS := clkfreq / 1_000_000
|
|
thisLine := tp - 2
|
|
restart := 1
|
|
repeat while restart
|
|
restart := 0
|
|
ht := spaces
|
|
if ht == 0
|
|
return
|
|
nt := skipspaces
|
|
if isvar(ht) and nt == "="
|
|
tp++
|
|
vars[fixvar(ht)] := expr
|
|
elseif ht => 128
|
|
case ht
|
|
128: ' THEN
|
|
a := expr
|
|
if spaces <> 129
|
|
abort string("MISSING THEN")
|
|
skipspaces
|
|
if not a
|
|
return
|
|
restart := 1
|
|
130: ' INPUT {"<prompt>";} <var> {, <var>}
|
|
if nt == quote
|
|
c := byte[++tp]
|
|
repeat while c <> quote and c
|
|
ios.printchar(c)
|
|
c := byte[++tp]
|
|
if c <> quote
|
|
abort @syn
|
|
if skipspaces <> ";"
|
|
abort @syn
|
|
nt := skipspaces
|
|
if not isvar(nt)
|
|
abort @syn
|
|
b := 0
|
|
inVars[b++] := fixvar(nt)
|
|
repeat while skipspaces == ","
|
|
nt := skipspaces
|
|
if not isvar(nt) or b == 26
|
|
abort @syn
|
|
inVars[b++] := fixvar(nt)
|
|
getline
|
|
tokenize
|
|
repeat a from 1 to b
|
|
vars[inVars[a-1]] := expr
|
|
if a < b
|
|
if spaces == ","
|
|
skipspaces
|
|
131: ' PRINT
|
|
a := 0
|
|
repeat
|
|
nt := spaces
|
|
if nt == 0 or nt == ":"
|
|
quit
|
|
if nt == quote
|
|
tp++
|
|
repeat
|
|
c := byte[tp++]
|
|
if c == 0 or c == quote
|
|
quit
|
|
ios.printchar(c)
|
|
a++
|
|
else
|
|
d~
|
|
if (b := expr) < 0
|
|
-b
|
|
ios.printchar("-")
|
|
a++
|
|
c := 1_000_000_000
|
|
repeat 10
|
|
if b => c
|
|
ios.printchar(b / c + "0")
|
|
a++
|
|
b //= c
|
|
d~~
|
|
elseif d or c == 1
|
|
ios.printchar("0")
|
|
a++
|
|
c /= 10
|
|
nt := spaces
|
|
if nt == ";"
|
|
tp++
|
|
elseif nt == ","
|
|
ios.printchar(" ")
|
|
a++
|
|
repeat while a & 7
|
|
ios.printchar(" ")
|
|
a++
|
|
tp++
|
|
elseif nt == 0 or nt == ":"
|
|
ios.printchar(fReturn)
|
|
quit
|
|
else
|
|
abort @syn
|
|
132, 133: ' GOTO, GOSUB
|
|
a := expr
|
|
if a < 0 or a => 65535
|
|
abort @ln
|
|
b := findline(a)
|
|
if wordat(b) <> a
|
|
abort @ln
|
|
if ht == 133
|
|
pushstack
|
|
nextlineloc := b
|
|
134: ' RETURN
|
|
if sp == 0
|
|
abort string("INVALID RETURN")
|
|
nextlineloc := stack[--sp]
|
|
135: ' REM
|
|
repeat while skipspaces
|
|
136: ' NEW
|
|
clearall
|
|
137: ' LIST {<expr> {,<expr>}}
|
|
b := 0 ' Default line range
|
|
c := 65535
|
|
if spaces <> 0 ' At least one parameter
|
|
b := c := expr
|
|
if spaces == ","
|
|
skipspaces
|
|
c := expr
|
|
a := long[userPtr]
|
|
repeat while a+2 < eop
|
|
d := wordat(a)
|
|
if d => b and d =< c
|
|
ios.printdec(d)
|
|
ios.printchar(" ")
|
|
putlinet(a+2)
|
|
a += 3 + strsize(a+2)
|
|
138: ' RUN
|
|
clearvars
|
|
140: ' OPEN " <file> ", R/W/A
|
|
if spaces <> quote
|
|
abort @syn
|
|
scanFilename(@f0)
|
|
if spaces <> ","
|
|
abort @syn
|
|
case skipspaces
|
|
"A", "a": d := "a"
|
|
"W", "w": d := "w"
|
|
"R", "r": d := "r"
|
|
other: abort string("Invalid open file mode")
|
|
tp++
|
|
if ios.sdmount < 0
|
|
abort string("Can't mount SD card")
|
|
if ios.sdopen(d,@f0)
|
|
abort string("Can't open file")
|
|
fileOpened := true
|
|
141: ' READ <var> {, <var> }
|
|
if not isvar(nt)
|
|
abort @syn
|
|
d := 0
|
|
inVars[d++] := fixvar(nt)
|
|
repeat while skipspaces == ","
|
|
nt := skipspaces
|
|
if not isvar(nt) or d == 26
|
|
abort @syn
|
|
inVars[d++] := fixvar(nt)
|
|
a := 0
|
|
repeat
|
|
c := ios.sdgetc
|
|
if c < 0
|
|
abort string("Can't read file")
|
|
elseif c == fReturn or c == fEof
|
|
tline[a] := 0
|
|
tp := @tline
|
|
quit
|
|
elseif c == fLinefeed
|
|
next
|
|
elseif a < linelen-1
|
|
tline[a++] := c
|
|
tokenize
|
|
repeat a from 1 to d
|
|
vars[inVars[a-1]] := expr
|
|
if a < d
|
|
if spaces == ","
|
|
skipspaces
|
|
142: ' WRITE ...
|
|
d := 0 ' record column
|
|
repeat
|
|
nt := spaces
|
|
if nt == 0 or nt == ":"
|
|
quit
|
|
if nt == quote
|
|
tp++
|
|
repeat
|
|
c := byte[tp++]
|
|
if c == 0 or c == quote
|
|
quit
|
|
ios.sdputc(c)
|
|
d++
|
|
else
|
|
a := expr
|
|
if a < 0
|
|
-a
|
|
ios.sdputc("-")
|
|
b := 1_000_000_000
|
|
c := false
|
|
repeat 10
|
|
if a => b
|
|
ios.sdputc(a / b + "0")
|
|
a //= b
|
|
c := true
|
|
elseif c or b == 1
|
|
ios.sdputc("0")
|
|
b /= 10
|
|
nt := spaces
|
|
if nt == ";"
|
|
tp++
|
|
elseif nt == ","
|
|
ios.sdputc(" ")
|
|
d++
|
|
repeat while d & 7
|
|
ios.sdputc(" ")
|
|
d++
|
|
tp++
|
|
elseif nt == 0 or nt == ":"
|
|
ios.sdputc(fReturn)
|
|
ios.sdputc(fLinefeed)
|
|
quit
|
|
else
|
|
abort @syn
|
|
143: ' CLOSE
|
|
fileOpened := false
|
|
if ios.sdclose < 0
|
|
abort string("Error closing file")
|
|
ios.sdunmount
|
|
144: ' DELETE " <file> "
|
|
if spaces <> quote
|
|
abort @syn
|
|
scanFilename(@f0)
|
|
if ios.sdmount < 0
|
|
abort string("Can't mount SD card")
|
|
if ios.sdopen("d",@f0)
|
|
abort string("Can't delete file")
|
|
if ios.sdclose < 0
|
|
abort string("Error deleting file")
|
|
ios.sdunmount
|
|
145: ' RENAME " <file> "," <file> "
|
|
if spaces <> quote
|
|
abort @syn
|
|
scanFilename(@f0)
|
|
if spaces <> ","
|
|
abort @syn
|
|
if skipspaces <> quote
|
|
abort @syn
|
|
scanFilename(@f0)
|
|
abort string("Rename not implemented")
|
|
|
|
146: ' FILES
|
|
h_dir
|
|
|
|
147: ' SAVE or SAVE "<filename>"
|
|
if (nt := spaces) == quote
|
|
scanFilename(@f0)
|
|
if ios.sdmount < 0
|
|
abort string("Can't mount SD card")
|
|
if ios.sdopen("w",@f0)
|
|
abort string("Can't create file")
|
|
processSave
|
|
if ios.sdclose < 0
|
|
abort string("Error closing file")
|
|
ios.sdunmount
|
|
|
|
148: ' LOAD or LOAD "<filename>"
|
|
if (nt := spaces) == quote
|
|
scanFilename(@f0)
|
|
if ios.sdmount < 0
|
|
abort string("Can't mount SD card")
|
|
if ios.sdopen("r",@f0) ' Open requested file
|
|
abort string("Can't open file")
|
|
bytemove(@tailLine,tp,strsize(tp)+1)
|
|
newprog
|
|
processLoad
|
|
tp := @tailLine ' Scan command tail after load
|
|
if ios.sdclose < 0
|
|
abort string("Error closing file")
|
|
ios.sdunmount
|
|
|
|
154: ' FOR <var> = <expr> TO <expr> {STEP <expr>}
|
|
ht := spaces
|
|
if ht == 0
|
|
abort @syn
|
|
nt := skipspaces
|
|
if not isvar(ht) or nt <> "="
|
|
abort @syn
|
|
a := fixvar(ht)
|
|
skipspaces
|
|
vars[a] := expr
|
|
if spaces <> 155 ' TO ' Save FOR limit
|
|
abort @syn
|
|
skipspaces
|
|
forLimit[a] := expr
|
|
if spaces == 156 ' STEP ' Save step size
|
|
skipspaces
|
|
forStep[a] := expr
|
|
else
|
|
forStep[a] := 1 ' Default step is 1
|
|
if spaces
|
|
abort @syn
|
|
forLoop[a] := nextlineloc ' Save address of line
|
|
if forStep[a] < 0 ' following the FOR
|
|
b := vars[a] => forLimit[a]
|
|
else ' Initially past the limit?
|
|
b := vars[a] =< forLimit[a]
|
|
if not b ' Search for matching NEXT
|
|
repeat while nextlineloc < eop-2
|
|
curlineno := wordat(nextlineloc)
|
|
tp := nextlineloc + 2
|
|
nextlineloc := tp + strsize(tp) + 1
|
|
if spaces == 157 ' NEXT <var>
|
|
nt := skipspaces ' Variable has to agree
|
|
if not isvar(nt)
|
|
abort @syn
|
|
if fixvar(nt) == a ' If match, continue after
|
|
quit ' the matching NEXT
|
|
157: ' NEXT <var>
|
|
nt := spaces
|
|
if not isvar(nt)
|
|
abort @syn
|
|
a := fixvar(nt)
|
|
vars[a] += forStep[a] ' Increment or decrement the
|
|
if forStep[a] < 0 ' FOR variable and check for
|
|
b := vars[a] => forLimit[a]
|
|
else ' the limit value
|
|
b := vars[a] =< forLimit[a]
|
|
if b ' If continuing loop, go to
|
|
nextlineloc := forLoop[a] ' statement after FOR
|
|
tp++
|
|
159: ' OUTA [ <expr>{..<expr>} ] = <expr>
|
|
a := getAddress(".")
|
|
if a > $FFFF
|
|
b := a & $FF
|
|
a := (a >> 8) & $FF
|
|
outa[a..b] := specialExpr
|
|
dira[a..b]~~
|
|
repeat c from a to b
|
|
outputs |= |< c
|
|
else
|
|
outa[a] := specialExpr
|
|
dira[a]~~
|
|
outputs |= |< a
|
|
160: ' PAUSE <expr> {,<expr>}
|
|
if pauseTime == 0 ' If no active pause time, set it
|
|
spaces ' with a minimum time of 50us
|
|
pauseTime := expr * 1000
|
|
if spaces == "," ' First (or only) value is in ms
|
|
skipspaces
|
|
pauseTime += expr ' Second value is in us
|
|
pauseTime #>= 50
|
|
if pauseTime < 10_050 ' Normally pause at most 10ms at a time,
|
|
waitcnt(pauseTime * uS + cnt) ' but, if that would leave < 50us,
|
|
pauseTime := 0 ' pause the whole amount now
|
|
else
|
|
a := pauseTime <# 10_000
|
|
waitcnt(a * uS + cnt) ' Otherwise, pause at most 10ms and
|
|
nextlineloc := thisLine ' re-execute the PAUSE for the rest
|
|
pauseTime -= 10_000
|
|
166: ' BYTE [ <expr> ] = <expr>
|
|
a := getAddress(" ")
|
|
byte[a] := specialExpr
|
|
167: ' WORD [ <expr> ] = <expr>
|
|
a := getAddress(" ")
|
|
word[a] := specialExpr
|
|
168: ' LONG [ <expr> ] = <expr>
|
|
a := getAddress(" ")
|
|
long[a] := specialExpr
|
|
170: ' PHSA =
|
|
PHSA := specialExpr
|
|
171: ' PHSB =
|
|
PHSB := specialExpr
|
|
172: ' FRQA =
|
|
FRQA := specialExpr
|
|
173: ' FRQB =
|
|
FRQB := specialExpr
|
|
174: ' CTRA =
|
|
CTRA := specialExpr
|
|
175: ' CTRB =
|
|
CTRB := specialExpr
|
|
176: ' DISPLAY <expr> {,<expr>}
|
|
spaces
|
|
ios.printchar(expr)
|
|
repeat while spaces == ","
|
|
skipspaces
|
|
ios.printchar(expr)
|
|
178: ' LET <var> = <expr>
|
|
nt := spaces
|
|
if not isvar(nt)
|
|
abort @syn
|
|
tp++
|
|
vars[fixvar(nt)] := specialExpr
|
|
179: ' STOP
|
|
nextlineloc := eop-2
|
|
return
|
|
180: ' END
|
|
nextlineloc := eop-2
|
|
return
|
|
181: ' EEPROM [ <expr> ] = <expr>
|
|
' code ausgefügt
|
|
ios.print(@msg0)
|
|
|
|
182: ' FILE = <expr>
|
|
if ios.sdputc(specialExpr) < 0
|
|
abort string("SDCARD write error")
|
|
184: ' SPIN [{<expr>,}<expr>] or "<file>"
|
|
if spaces == quote
|
|
scanFilename(@f0)
|
|
ios.ldbin(@f0)
|
|
|
|
185: ' COPY [<expr>],"<file>" or COPY "<file>",[<expr>] or
|
|
' COPY [<expr>],[<expr>] where <expr> are different
|
|
' code ausgefügt
|
|
ios.print(@msg0)
|
|
|
|
186: ' DUMP <expr>,<expr> or DUMP [<expr>],<expr>
|
|
if spaces == "["
|
|
c := getAddress(",")
|
|
a := c & $F80000
|
|
b := c & $07FFFF
|
|
else
|
|
a := -1
|
|
b := expr
|
|
if spaces <> ","
|
|
abort @syn
|
|
skipspaces
|
|
dumpMemory(a,b,expr)
|
|
else
|
|
abort(@syn)
|
|
if spaces == ":"
|
|
restart := 1
|
|
tp++
|
|
|
|
|
|
PRI processLoad : c | a
|
|
repeat
|
|
a := 0
|
|
repeat
|
|
c := ios.sdgetc
|
|
if c == fReturn or c == fEof
|
|
tline[a] := 0
|
|
tp := @tline
|
|
quit
|
|
elseif c == fLinefeed
|
|
next
|
|
elseif c < 0
|
|
quit
|
|
elseif a < linelen-1
|
|
tline[a++] := c
|
|
if ios.sdeof and tline[0] == 0
|
|
quit
|
|
if c < 0
|
|
abort string("Error while loading file")
|
|
tp := @tline
|
|
a := spaces
|
|
if "0" =< a and a =< "9"
|
|
insertline
|
|
nextlineloc := eop - 2
|
|
else
|
|
if a <> 0
|
|
abort string("Missing line number in file")
|
|
|
|
PRI processSave | a, c, d, ntoks
|
|
ntoks := (@tokx - @toks) / 2
|
|
a := long[userPtr]
|
|
repeat while a+2 < eop
|
|
d := wordat(a)
|
|
ios.sddec(d)
|
|
ios.sdputc(" ")
|
|
d := a + 2
|
|
repeat while c := byte[d++]
|
|
if c => 128
|
|
if (c -= 128) < ntoks
|
|
ios.sdputstr(@@toks[c])
|
|
if c <> 7 ' REM
|
|
ios.sdputc(" ")
|
|
else
|
|
ios.sdputc("{")
|
|
ios.sddec(c)
|
|
ios.sdputc("}")
|
|
else
|
|
ios.sdputc(c)
|
|
ios.sdputc(fReturn)
|
|
ios.sdputc(fLinefeed)
|
|
a += 3 + strsize(a+2)
|
|
|
|
PRI getAnyNumber | c, t
|
|
case c := byte[tp]
|
|
quote:
|
|
if result := byte[++tp]
|
|
if byte[++tp] == quote
|
|
tp++
|
|
else
|
|
abort string("missing closing quote")
|
|
else
|
|
abort string("end of line in string")
|
|
"$":
|
|
c := byte[++tp]
|
|
if (t := hexDigit(c)) < 0
|
|
abort string("invalid hex character")
|
|
result := t
|
|
c := byte[++tp]
|
|
repeat until (t := hexDigit(c)) < 0
|
|
result := result << 4 | t
|
|
c := byte[++tp]
|
|
"%":
|
|
c := byte[++tp]
|
|
if not (c == "0" or c == "1")
|
|
abort string("invalid binary character")
|
|
result := c - "0"
|
|
c := byte[++tp]
|
|
repeat while c == "0" or c == "1"
|
|
result := result << 1 | (c - "0")
|
|
c := byte[++tp]
|
|
"0".."9":
|
|
result := c - "0"
|
|
c := byte[++tp]
|
|
repeat while c => "0" and c =< "9"
|
|
result := result * 10 + c - "0"
|
|
c := byte[++tp]
|
|
other:
|
|
abort string("invalid literal value")
|
|
|
|
PRI hexDigit(c)
|
|
'' Convert hexadecimal character to the corresponding value or -1 if invalid.
|
|
if c => "0" and c =< "9"
|
|
return c - "0"
|
|
if c => "A" and c =< "F"
|
|
return c - "A" + 10
|
|
if c => "a" and c =< "f"
|
|
return c - "a" + 10
|
|
return -1
|
|
|
|
PUB dumpMemory(pin,addr,size) | i, c, p, first, buf0, buf1, buf2
|
|
'' This routine dumps a portion of the RAM/ROM to the display (pin == -1).
|
|
'' If pin is not -1, it is an EEPROM address in the form required by the
|
|
'' I2C routines in i2cSpiInit. The specified address is or'd with this.
|
|
'' The format is 8 bytes wide with hexadecimal and ASCII.
|
|
addr &= $7FFFF
|
|
first := true
|
|
p := addr & $7FFF8
|
|
repeat while p < (addr + size)
|
|
if first
|
|
ios.printhex(addr,5)
|
|
first := false
|
|
else
|
|
ios.printhex(p,5)
|
|
ios.printchar(":")
|
|
repeat i from 0 to 7
|
|
byte[@buf0][i] := " "
|
|
if p => addr and p < (addr + size)
|
|
c := byte[p]
|
|
ios.printhex(c,2)
|
|
if c => " " and c =< "~"
|
|
byte[@buf0][i] := c
|
|
else
|
|
ios.printchar(" ")
|
|
ios.printchar(" ")
|
|
ios.printchar(" ")
|
|
p++
|
|
buf2 := 0
|
|
ios.printchar("|")
|
|
ios.print(@buf0)
|
|
ios.printchar("|")
|
|
ios.printchar(fReturn)
|
|
|
|
PUB h_dir | stradr,n,wflag,c,i,len,mflag 'hive: verzeichnis anzeigen
|
|
{{h_dir - anzeige verzeichnis}}
|
|
wflag := 1
|
|
mflag := 1
|
|
ios.sdmount 'medium mounten
|
|
ios.sddir 'kommando: verzeichnis öffnen
|
|
n := 1
|
|
c := 0 'spalten
|
|
i := 0 'dateizähler
|
|
repeat 'wiederhole bis verzeichnisende
|
|
stradr := ios.sdnext 'einen eintrag holen
|
|
if stradr <> 0 'ist eintrag gültig?
|
|
i++
|
|
len := strsize(stradr)
|
|
n++
|
|
ios.print(stradr)
|
|
if wflag == 1
|
|
c++
|
|
ios.printtab
|
|
if (wflag == 0 OR c == 3)
|
|
ios.printnl
|
|
c := 0
|
|
if mflag == 1 AND i == 20
|
|
ios.printnl
|
|
ios.print(@wait1)
|
|
if ios.keywait == "q"
|
|
return
|
|
ios.printnl
|
|
i := 0
|
|
while stradr <> 0 'wiederholen solange stradr <> 0
|
|
if wflag == 1
|
|
ios.printnl
|
|
ios.printdec(--n)
|
|
ios.print(string(" Datei(en)"))
|
|
ios.printnl
|
|
ios.sdunmount 'medium unmounten
|
|
|
|
DAT
|
|
wait1 byte "<WEITER? */q:>",0
|
|
msg0 byte "Funktion nicht implementiert!",0
|
|
|
|
|
|
{{
|
|
TERMS OF USE: MIT License
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
}}
|