TriOS-alt/zubehör/sphinx/spinx100225-ori/sphinx2/sphinx.spn

367 lines
11 KiB
Plaintext

{
_clkfreq = 96_000_000 ' Hybrid
_clkmode = xtal1 + pll16x
tvPins = 24
kbPins = 12
sdPins = 8
}
_clkfreq = 80_000_000 ' Hydra
_clkmode = xtal1 + pll8x
tvPins = 24
kbPins = 13
sdPins = 16
{
Simple command line
2009
April
15 Adding file transfer to/from PC via serial
16 0.02
SendFile bugfix (while blksize == 1024)
Tries to run .bin before .eep now.
June
4 Changing name from cl to sphinx. Converting to use sxfs, sxtv.
15 sxkb; adding c and cl commands
23 Corrected clock mode calculation.
}
obj
kb: "sxkb"
term: "sxtv"
sxfs: "sxfs"
f: "sxfile"
ser: "fdserial"
con
SXTVRENDEZVOUS = $8000 - 4
SXKBRENDEZVOUS = SXTVRENDEZVOUS - 4
SDSPIRENDEZVOUS = SXKBRENDEZVOUS - 3 * 4
SXFS2RENDEZVOUS = SDSPIRENDEZVOUS - 4 * 4 ' four rendezvous variables
SXFSRENDEZVOUS = SXFS2RENDEZVOUS - 4 * 4 ' four rendezvous variables
METADATABUFFER = SXFSRENDEZVOUS - 512
_free = ($8000 - METADATABUFFER) / 4
pub Main | err, p
if term.start( tvPins, SXTVRENDEZVOUS )
term.str( string("============= Sphinx 090627 ============", 13) )
term.str( string("video @ pin ") )
term.dec( tvPins )
term.str( string(13, "keyboard @ pin ") )
term.dec( kbPins )
term.str( string(13, "SD @ pin ") )
term.dec( sdPins )
term.out( 13 )
sxfs.start( sdPins )
kb.start( kbPins )
repeat
if ina[31] ' USB cable connected?
ser.start( 31, 30, %0000, 19200 )
f.Close
err := \DoIt
if err
if err > 0
term.str( err )
else
term.str( string("Error ") )
term.dec( err )
term.out( 13 )
else
term.str( string("Normal exit") ) ' This never happens
pri DoIt | ch
term.out( ">" )
term.out( "_" )
term.out( 8 )
repeat
if kb.peekkey
EditCmdLine
Execute
term.out( ">" )
term.out( "_" )
term.out( 8 )
if (ch := ser.rxcheck) <> -1
term.out( 8 )
FileTransfer( ch )
term.out( ">" )
term.out( "_" )
term.out( 8 )
con
MAXCMDLINELENGTH = 78 ' some arbitray limit.
CR = $0d
BKSP = $c8
var
byte cmdLine[MAXCMDLINELENGTH+1] ' +1 for null terminator
long cmdLineLength
pri EditCmdLine | key
cmdLineLength~ ' cursor is always at end of command line
repeat
case key := kb.key
$20..$7f:
if cmdLineLength < MAXCMDLINELENGTH
cmdLine[ cmdLineLength++ ] := key
term.out( key )
term.out( "_" )
term.out( 8 )
CR:
term.out( " " )
term.out( 13 )
cmdLine[ cmdLineLength ]~
return true
BKSP:
if cmdLineLength
--cmdLineLength
term.out( " " )
term.out( 8 )
term.out( 8 )
term.out( "_" )
term.out( 8 )
pri FileTransfer( cmd ) | ch, i
if cmd <> "G" and cmd <> "P"
term.out( cmd )
abort string(" -- unrecognized command from PC")
i~
repeat
ch := RxSerByte
if i => FILENAMEBUFFERSIZE
abort string("Filename too long")
filename[i++] := ch
while ch
if cmd == "G"
term.str( string("sending ") )
term.str( @filename )
term.out( 13 )
SendFileToPC
else
term.str( string("receiving ") )
term.str( @filename )
term.out( 13 )
ReceiveFileFromPC
pri SendFileToPC | blksize, i, chksum, b, n
if f.Open( @filename, "R" ) <> 0
term.str( @filename )
abort string(" -- can't open file for reading")
TxSerByte( "A" ) ' ack
n~
repeat
blksize := f.Read( @buffer, 1024 )
if blksize == -1
blksize~
TxSerByte( blksize.byte[0] )
TxSerByte( blksize.byte[1] )
i~
chksum~
repeat blksize
b := buffer[i++]
chksum += b
TxSerByte( b )
n += blksize
if chksum & $ff <> RxSerByte
abort string("Checksum error")
while blksize == 1024
f.Close
term.dec( n )
term.str( string(" bytes sent", 13) )
pri ReceiveFileFromPC | blksize, i, chksum, b, n
if f.Open( @filename, "W" ) <> 0
term.str( @filename )
abort string(" -- can't open file for writing")
TxSerByte( "A" ) ' ack
n~
repeat
blksize~
blksize.byte[0] := RxSerByte
blksize.byte[1] := RxSerByte
if blksize > 1024
abort string("Block size > 1024")
i~
chksum~
repeat blksize
b := RxSerByte
buffer[i++] := b
chksum += b
n += blksize
f.Write( @buffer, blksize )
TxSerByte( chksum )
while blksize == 1024
f.Close
term.dec( n )
term.str( string(" bytes received", 13) )
pri RxSerByte : b
' ser.rx with timeout
b := ser.rxtime( TIMEOUT )
if b == -1
abort string("RxSerByte timed out")
pri TxSerByte( b )
' just for symmetry with RxSerByte
ser.tx( b )
con
TIMEOUT = 500
var
byte buffer[1024]
pri Execute | n, p, q, run, c
c~
ifnot n := ParseCmdLine
return
p := @cmdLine
ToUpper(p)
if run := strcomp( @cmdLine, string("RUN") )
--n
p += strsize(p) + 1
elseif strcomp( @cmdLine, string("C") )
c := 1
--n
p += strsize(p) + 1 ' command arg1 arg2...
elseif strcomp( @cmdLine, string("CL") ) ' run command arg1 arg2...
c := 2 ' c arg1 arg2...
--n ' cl arg1 arg2...
p += strsize(p) + 1
ifnot n
abort string("No file specified")
f.Open( string("args.d8a"), "W" ) ' write args
if c == 0
q := p + strsize(p) + 1 ' for run and plain command, skip first arg (command name)
--n
f.Write( @n, 1 )
repeat n
f.Write( q, strsize(q) + 1 )
q += strsize(q) + 1
else ' for c and cl,
++n ' add extra arg (/c or /l)
f.Write( @n, 1 )
repeat n-1
f.Write( p, strsize(p) + 1 )
p += strsize(p) + 1
if c == 1
f.Write( string("/c"), 3 )
else
f.Write( string("/l"), 3 )
n~
f.Write( @n, 1 ) ' final terminating null
f.Close
if c
if f.Open( string("lex.bin"), "R" ) <> 0
abort string("lex.bin not found")
ser.stop
f.Execute( 0 )
if EndsWith( p, string(".BIN") ) or EndsWith( p, string(".EEP") )
if f.Open( p, "R" ) <> 0
term.str( p )
abort string(" -- not found")
else
if strsize(p) > MAXFILENAMELENGTH - 4
term.str( p )
abort string(" -- filename too long")
bytemove( @filename, p, strsize(p) + 1 )
bytemove( @filename + strsize(p), string(".BIN"), 5 )
if f.Open( @filename, "R" ) <> 0
bytemove( @filename + strsize(p), string(".EEP"), 5 )
if f.Open( @filename, "R" ) <> 0
term.str( p )
abort string(" -- no .bin or .eep found")
ser.stop
f.Execute( run )
pri ToUpper( p )
repeat while byte[p]
if "a" =< byte[p] and byte[p] =< "z"
byte[p] += "A" - "a"
++p
pri EndsWith( p, s )
if strsize(p) < strsize(s)
return false
p += strsize(p) - strsize(s)
repeat while byte[p]
if byte[p++] <> byte[s++]
return false
return true
con
MAXFILENAMELENGTH = 12 ' 8 + . + 3
FILENAMEBUFFERSIZE = MAXFILENAMELENGTH + 1 ' 8 + . + 3 + null
CMDNAMEBUFFERSIZE = 9 ' 8 + null
var
byte filename[MAXFILENAMELENGTH+1] ' 8 + . + 3 + null
pri ParseCmdLine : n | pSrc, pDst, state
{{
Converts cmdLine from " ab de fg \" to "ab\de\fg\" ('\' = null).
Returns # of "words".
}}
{
state whitespace null other char
0 ++pSrc; append \0; quit append char; => 1
1 append \0; ++n; => 0 append \0; ++n; quit append char;
}
pSrc := @cmdLine
pDst := @cmdLine
state~
repeat
if state == 0
if byte[pSrc] == " "
++pSrc
elseif byte[pSrc] == 0
byte[pDst++]~
quit
else
byte[pDst++] := byte[pSrc++]
state := 1
elseif state == 1
if byte[pSrc] == " "
++pSrc
byte[pDst++]~
++n
state~
elseif byte[pSrc] == 0
byte[pDst++]~
++n
quit
else
byte[pDst++] := byte[pSrc++]
{{
Copyright (c) 2009 Michael Park
+------------------------------------------------------------------------------------------------------------------------------+
| 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. |
+------------------------------------------------------------------------------------------------------------------------------+
}}