diff --git a/src/inc/cmdsys.plh b/src/inc/cmdsys.plh index 4928ded..bf0eb2b 100644 --- a/src/inc/cmdsys.plh +++ b/src/inc/cmdsys.plh @@ -1,7 +1,7 @@ import cmdsys predef putc, putln, puts, getc, gets predef call, syscall - predef heapmark, heapallocallign, heapalloc, heaprelease, heapavail + predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail predef memset, memcpy predef isugt, isuge, isult, isule predef modload, modexec, modaddr diff --git a/src/inc/prodos.plh b/src/inc/prodos.plh new file mode 100644 index 0000000..c632c8a --- /dev/null +++ b/src/inc/prodos.plh @@ -0,0 +1,5 @@ +import prodos + const sysbuf = $0800 + predef getpfx, setpfx, open, close, read, write, create, destroy, newline + byte perr +end \ No newline at end of file diff --git a/src/inc/sdfat.plh b/src/inc/sdfat.plh index 29361eb..244edd3 100644 --- a/src/inc/sdfat.plh +++ b/src/inc/sdfat.plh @@ -2,6 +2,21 @@ // FAT I/O object // import sdFAT + // + // Open flags + // + const O_READ = $01 + const O_WRITE = $02 + const O_APPEND = $04 + const O_SYNC = $08 + const O_TRUNC = $10 + const O_AT_END = $20 + const O_CREAT = $40 + const O_EXCL = $80 + const MAX_FAT_BUF_SIZE = 512 + // + // Interface + // struc t_fatio word dirGet word dirSet diff --git a/src/inc/spiport.plh b/src/inc/spiport.plh index dd71089..6469034 100644 --- a/src/inc/spiport.plh +++ b/src/inc/spiport.plh @@ -1,3 +1,6 @@ import spiport - predef spiXferByte, spiSend, spiRecv, spiWriteBuf, spiReadBuf, spiDelay + const SPI_SLAVE_READY = '@' + const SPI_SLAVE_ERROR = '!' + const SPI_SLAVE_BUSY = $FF + predef spiXferByte, spiSend, spiRecv, spiWriteBuf, spiReadBuf, spiDelay, spiReady end diff --git a/src/libsrc/prodos.pla b/src/libsrc/prodos.pla new file mode 100644 index 0000000..67097dc --- /dev/null +++ b/src/libsrc/prodos.pla @@ -0,0 +1,97 @@ +include "inc/cmdsys.plh" +// +// ProDOS error code +// +export byte perr +// +// ProDOS routines +// +export def getpfx(path) + byte params[3] + + ^path = 0 + params.0 = 1 + params:1 = path + perr = syscall($C7, @params) + return path +end +export def setpfx(path) + byte params[3] + + params.0 = 1 + params:1 = path + perr = syscall($C6, @params) + return path +end +export def open(path, buff) + byte params[6] + + params.0 = 3 + params:1 = path + params:3 = buff + params.5 = 0 + perr = syscall($C8, @params) + return params.5 +end +export def close(refnum) + byte params[2] + + params.0 = 1 + params.1 = refnum + perr = syscall($CC, @params) + return perr +end +export def read(refnum, buff, len) + byte params[8] + + params.0 = 4 + params.1 = refnum + params:2 = buff + params:4 = len + params:6 = 0 + perr = syscall($CA, @params) + return params:6 +end +export def write(refnum, buff, len) + byte params[8] + + params.0 = 4 + params.1 = refnum + params:2 = buff + params:4 = len + params:6 = 0 + perr = syscall($CB, @params) + return params:6 +end +export def create(path, access, type, aux) + byte params[12] + + params.0 = 7 + params:1 = path + params.3 = access + params.4 = type + params:5 = aux + params.7 = $1 + params:8 = 0 + params:10 = 0 + perr = syscall($C0, @params) + return perr +end +export def destroy(path) + byte params[3] + + params.0 = 1 + params:1 = path + perr = syscall($C1, @params) + return perr +end +export def newline(refnum, emask, nlchar) + byte params[4] + + params.0 = 3 + params.1 = refnum + params.2 = emask + params.3 = nlchar + perr = syscall($C9, @params) + return perr +end diff --git a/src/libsrc/sdfat.pla b/src/libsrc/sdfat.pla index 2f6809d..a882589 100644 --- a/src/libsrc/sdfat.pla +++ b/src/libsrc/sdfat.pla @@ -19,8 +19,8 @@ def cwd(pathname) byte namelen namelen = 0 - spiSend(15) - namelen = spiSend(15)//spiRecv + spiSend(15) // CWD + namelen = spiRecv if namelen spiReadBuf(pathname+1, namelen) fin @@ -31,7 +31,7 @@ end def chdir(path) spiWriteBuf(path + 1, ^path) spiSend(16) // CHGDIR - return spiSend(16)//spiRecv + return spiRecv end def mkdir(path) @@ -54,7 +54,7 @@ def openDir(cmd, filename) namelen = 0 spiSend(cmd) - namelen = spiSend(cmd)//spiRecv + namelen = spiRecv if namelen == 0xFF namelen = 0 fin @@ -75,17 +75,39 @@ end // // File related functions // -def open(path) +def open(path, mode) + spiWriteBuf(path + 1, ^path) // send filename + spiSend(21) // OPEN + spiSend(mode) + return spiRecv // status end def close - spiSend(24) // CLOSE + return spiSend(24) // CLOSE end def read(buf, len) + if len > 512 + len = 512 + fin + spiSend(25) // READ + spiSend(len >> 8); spiSend(len) + len = (spiRecv << 8) | spiRecv + if len > 0 and len <= 512 + spiReadBuf(buf, len) + fin + return len end def write(buf, len) + if len > 512 + len = 512 + fin + spiWriteBuf(buf, len) + spiSend(26) // WRITE + spiSend(len >> 8); spiSend(len) + len = (spiRecv << 8) | spiRecv + return len end def sync @@ -111,7 +133,7 @@ end def isDir spiSend(35) // ISDIR - return spiSend(35)//spiRecv + return spiRecv end def isFile @@ -122,5 +144,5 @@ end // spiSend(14) // SDINIT spiDelay(100) -return spiRecv <> '@' // Is Arduino READY? +return spiRecv <> SPI_SLAVE_READY // Is Arduino READY? done \ No newline at end of file diff --git a/src/libsrc/spiport.pla b/src/libsrc/spiport.pla index e9bbf86..2ac3f00 100644 --- a/src/libsrc/spiport.pla +++ b/src/libsrc/spiport.pla @@ -4,6 +4,10 @@ end // // Bit banged spi over gameport // +const SPI_SLAVE_READY = '@' +const SPI_SLAVE_ERROR = '!' +const SPI_SLAVE_BUSY = $FF + asm spiInc !SOURCE "vmsrc/plvmzp.inc" end @@ -65,6 +69,7 @@ export asm spiXferByte(outbyte) INY + STA $C058,Y STA $C040 + NOP ASL $C061 STA $C05B ; DISABLE SLAVE ROL @@ -83,6 +88,7 @@ asm spiReadBytes(buf, len) + LDY #$00 - STA $C05A ; ENABLE SLAVE STA $C040 ; CLOCK + NOP ASL $C061 ; SHIFT IN ALL BITS STARTING WITH MSB STA $C040 ROL @@ -190,15 +196,15 @@ asm spiWriteBytes(buf, len) end export def spiDelay(time) - return call($fca8, time, 0, 0, 0) // DELAY + return call($FCA8, time, 0, 0, 0) // DELAY end export def spiSend(data) byte timeout, status - for timeout = 0 to 50 step 10 + for timeout = 1 to 5 status = spiXferByte(data) - if status <> $ff + if status <> SPI_SLAVE_BUSY return status fin spiDelay(timeout) @@ -213,28 +219,31 @@ end export def spiWriteBuf(buf, len) spiSend(13) // CMD_BUF_WRITE - spiSend(len>>8) // LEN_HI - spiSend(len) // LEN_LO - return spiWriteBytes(buf, len) + spiSend(len >> 8); spiSend(len) + return spiWriteBytes(buf, len) end export def spiReadBuf(buf, len) spiSend(12) // CMD_BUF_READ - spiSend(len>>8) // LEN_HI - spiSend(len) // LEN_LO + spiSend(len >> 8); spiSend(len) return spiReadBytes(buf, len) end -export def spiReset - byte timeout, status - ^$C05B - timeout = $FF - repeat - status = spiSend(0) +export def spiReady + byte timeout + + timeout = 0xFF + while spiXferByte(0) <> SPI_SLAVE_READY and timeout // WAIT FOR READY timeout-- - until status == '@' or !timeout // WAIT FOR READY - return status <> '@' + spiDelay(10) + loop + return timeout end -return spiReset +export def spiReset + ^$C05B + return spiReady +end + +return spiReset <> 0 done diff --git a/src/makefile b/src/makefile index 09acdad..7c1e36a 100644 --- a/src/makefile +++ b/src/makefile @@ -13,6 +13,8 @@ ARGS = ARGS\#FE1000 SPIPORT = SPIPORT\#FE1000 SDFAT = SDFAT\#FE1000 FATCAT = FATCAT\#FE1000 +FATGET = FATGET\#FE1000 +PRODOS = PRODOS\#FE1000 WIZNET = WIZNET\#FE1000 UTHERNET2= UTHERNET2\#FE1000 UTHERNET= UTHERNET\#FE1000 @@ -57,7 +59,7 @@ TXTTYPE = .TXT #SYSTYPE = \#FF2000 #TXTTYPE = \#040000 -all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1) $(TONE) $(DGR) $(DGRTEST) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) +all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(ARGS) $(MEMMGR) $(MEMTEST) $(FIBER) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET2) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(HTTPD) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1) $(TONE) $(DGR) $(DGRTEST) $(PRODOS) $(PORTIO) $(SPIPORT) $(SDFAT) $(FATCAT) $(FATGET) clean: -rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) @@ -166,6 +168,10 @@ $(HTTPD): samplesrc/httpd.pla $(PLVM02) $(PLASM) ./$(PLASM) -AM < samplesrc/httpd.pla > samplesrc/httpd.a acme --setpc 4094 -o $(HTTPD) samplesrc/httpd.a +$(PRODOS): libsrc/prodos.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AM < libsrc/prodos.pla > libsrc/prodos.a + acme --setpc 4094 -o $(PRODOS) libsrc/prodos.a + $(TONE): libsrc/tone.pla $(PLVM02) $(PLASM) ./$(PLASM) -AM < libsrc/tone.pla > libsrc/tone.a acme --setpc 4094 -o $(TONE) libsrc/tone.a @@ -174,6 +180,10 @@ $(FATCAT): samplesrc/fatcat.pla $(PLVM02) $(PLASM) ./$(PLASM) -AM < samplesrc/fatcat.pla > samplesrc/fatcat.a acme --setpc 4094 -o $(FATCAT) samplesrc/fatcat.a +$(FATGET): samplesrc/fatget.pla $(PLVM02) $(PLASM) + ./$(PLASM) -AM < samplesrc/fatget.pla > samplesrc/fatget.a + acme --setpc 4094 -o $(FATGET) samplesrc/fatget.a + $(SDFAT): libsrc/sdfat.pla $(PLVM02) $(PLASM) ./$(PLASM) -AM < libsrc/sdfat.pla > libsrc/sdfat.a acme --setpc 4094 -o $(SDFAT) libsrc/sdfat.a diff --git a/src/samplesrc/fatget.pla b/src/samplesrc/fatget.pla new file mode 100644 index 0000000..0c5c84c --- /dev/null +++ b/src/samplesrc/fatget.pla @@ -0,0 +1,175 @@ +include "inc/cmdsys.plh" +include "inc/prodos.plh" +include "inc/args.plh" +include "inc/sdfat.plh" + +const COPY_BUF_SIZE = 8912 // 8K + +byte[17] proname +byte protype +word proaux +word arg + +def putByte(val) + byte c + c = ((val >> 4) & $0F) + '0' + if c > '9' + c = c + 7 + fin + putc(c) + c = (val & $0F) + '0' + if c > '9' + c = c + 7 + fin + return putc(c) +end + +def putWord(val) + putByte(val.1) + return putByte(val.0) +end + +def hexByte(hexChars) + byte lo, hi + + lo = ^(hexChars + 1) - '0' + if lo > 9 + lo = lo - 7 + fin + hi = ^hexChars - '0' + if hi > 9 + hi = hi - 7 + fin + return (hi << 4) | lo +end + +def hexWord(hexChars) + return (hexByte(hexChars + 2) << 8) | hexByte(hexChars) +end + +def mkProName(fatName, proName, proType, proAux) + byte n, l + + ^proType = $02 // default to BIN + *proAux = $0000 // default to 0 + // + // Check for CiderPress style extension + // + l = ^fatName + if l > 7 and ^(fatName + l - 6) == '#' + ^proType = hexByte(fatName + l - 5) + *proAux = hexWord(fatName + l - 3) + l = l - 7 + fin + // + // Scan backward looking for dir seperator + // + for n = l downto 1 + if ^(fatName + n) == '/' + break + fin + next + if l - n > 15 + l = n + 15 + fin + memcpy(proName + 1, fatName + 1 + n, l - n) + ^proName = l - n +end + +def getYN(prompt) + byte yn + + puts(prompt) + yn = getc + return yn == 'Y' or yn == 'y' +end + +def bigFatRead(buf, len) + word xferLen, fatLen + + xferLen = 0 + repeat + if len > MAX_FAT_BUF_SIZE + fatLen = MAX_FAT_BUF_SIZE + else + fatLen = len + fin + fatLen = sdFAT:fileRead(buf, fatLen) + if fatLen > 0 and fatLen <= 512 + xferLen = xferLen + fatLen + len = len - fatLen + buf = buf + fatLen + else + len = 0 + fin + until len == 0 + return xferLen +end + +def fatCopyFrom(src, dst, type, aux) + word copyBuf, copyLen, freeAddr + byte ref + + copyBuf = heapallocalign(COPY_BUF_SIZE, 8, @freeAddr) + if not copyBuf + puts("Not enough free memory!\n"); putln + return -1 + fin + // + // Check if dst already exists + // + ref = open(dst, sysbuf) + if ref + close(ref) + puts("Overwrite "); puts(dst) + if not getYN("(Y/N)?") + heaprelease(freeAddr) + return -1 + fin + putln + destroy(dst) + fin + // + // Create dst file + // + if create(dst, $C3, type, aux) + puts("Create file error: "); putByte(perr); putln + fin + ref = open(dst, sysbuf) + if not ref + puts("Error opening file: "); puts(dst); putln + puts("Open file error: "); putByte(perr); putln + return -1 + fin + // + // Copy FAT file over in big chunks + // + if sdFAT:fileOpen(src, O_READ) + repeat + copyLen = bigFatRead(copyBuf, COPY_BUF_SIZE) + if copyLen + if write(ref, copyBuf, copyLen) <> copyLen + puts("Error writing file:"); puts(dst); putln + puts("Write file error: "); putByte(perr); putln + copyLen = 0 // Force end of copy + fin + fin + until copyLen == 0 + sdFAT:fileClose() + else + puts("Error opening FAT file:"); puts(src); putln + fin + close(ref) + heaprelease(freeAddr) +end + +arg = argNext(argFirst) +if ^arg + mkProName(arg, @proname, @protype, @proaux) + puts(arg);puts("==>");puts(@proname) + putc(' ');putByte(protype);putc(',');putWord(proaux);putln + fatCopyFrom(arg, @proname, protype, proaux) +else + puts("Usage: +FATGET "); putln +fin +done \ No newline at end of file