I’ve been considering this for a while, since I’m not fond of plugging in the USB-C cable constantly, and the charge lasts so long with two batteries that I hardly need to plug it in at all. But I also grew tired of having to remove the SD card to copy programs and data back and forth.
WebMite doesn’t provide very much functionality in terms of WiFi, so while it might be theoretically possible to create a simple FTP server in MMBasic, that seemed like a nightmare. It does support TFTP (automatically enabled when running WebMite), which is incredibly simple, only allows sending or receiving one file at a time, has slow transfer speeds, and seems to fail during transfers regularly. The few TFTP clients out there seem barely usable. But I discovered curl can be used to fake a TFTP client. Since I’m using Windows (and command line curl under Windows), I wrote some MMBasic code to work with that. It’s very much a hack, but it does work.
When you run the program, you can either hit enter to prepare your entire SD for backup, or you could enter the full path to a directory and everything in that directory and below it will be backed up. So, for example, entering B:/test
will back up everything under that directory recursively.
It unfortunately takes a few steps. Once you run backup.bas
, it will create backup.bat
in your current directory and show a command on the screen that you need to run on your Windows machine. It will be something like:
curl --tftp-blksize 8192 -O tftp://192.168.12.242/b:/backup.bat
with the IP address of your device.
Run that command under windows, and you’ll download the backup.bat
file that was just created on your PicoCalc. Feel free to examine it before running it, but once you do, it will create directories and issue the curl commands to download each file and eventually you’ll have a backup of the contents of your PicoCalc.
There’s no compression and no encryption, sadly, so it works best with small source files. File type is irrelevant, as it works with text as well as binary. I was able to transfer several large .uf2 files I had foolishly left on my SD card, and they eventually made it over but it took a while. I’ve got error checking in the batch file, since the TFTP server on WebMite seems to freak out and issue “Access Violation” errors sometimes. So it will get in a retry loop until curl reports a success. So far I’ve never seen it only download a partial file, and it always finished.
This batch file could probably be adapted pretty easily to a shell script for Linux/Mac but I’ll leave that as an exercise to the reader.
This is only one direction – it downloads files from the PicoCalc to your Windows machine. A similar curl command can be used to push files, one at a time, like so:
curl --tftp-blksize 8192 -T test.bas tftp://192.168.12.242/b:/test.bas
But if you’re copying large numbers of files to the device, it’s probably easiest to just take the SD card out and do it that way. I wanted this backup solution as a way to keep backup copies of things I edited on the PicoCalc.
The blksize
can be adjusted, but I found 8192 worked better than the default of 512. I’m not sure if it depends on file size, network configuration, or what, so you may want to play with that.
' Create backup script
DIM f$, fullpth$, fixpth$
DIM queue$(500) ' queue of paths
DIM head=0, tail=0
DIM ipaddress$=MM.INFO(IP address)
DIM s$=CHR$(34)
DIM counter=0
FUNCTION Swap$(in$,find$,replace$)
LOCAL i, output$
output$ = ""
FOR i = 1 TO LEN(in$)
IF MID$(in$,i,1)=find$ THEN
output$=output$+replace$
ELSE
output$=output$+MID$(in$,i,1)
END IF
NEXT i
Swap$ = output$
END FUNCTION
SUB ListFiles(pth$)
LOCAL cmd$
CHDIR pth$
f$ = DIR$(pth$ + "*", FILE)
IF f$ <> "" THEN
DO WHILE f$ <> ""
INC counter
fullpth$=pth$+f$
fullpth$=Swap$(fullpth$," ","%20")
cmd$="curl --tftp-blksize"
CAT cmd$," 8192 -O tftp://"
CAT cmd$,ipaddress$+"/"
CAT cmd$,fullpth$
PRINT #1,"ECHO "+fullpth$
PRINT #1,":LBL"+HEX$(counter)
PRINT #1,cmd$
PRINT #1,"IF %ERRORLEVEL% NEQ 0 GOTO :LBL"+HEX$(counter)
f$ = DIR$()
LOOP
ENDIF
END SUB
INPUT "Starting directory: ",startDir$
IF startDir$="" THEN startDir$="B:/"
IF RIGHT$(startDir$,1)<>"/" THEN
CAT startDir$,"/"
ENDIF
CHDIR startDir$
' Enqueue the starting directory
queue$(tail)=startDir$
INC tail
OPEN "B:/backup.bat" FOR OUTPUT AS #1
PRINT #1,"@ECHO OFF"
PRINT #1,"SET cdir="+s$+"%CD%"+s$
DO WHILE head < tail
current$=queue$(head)
INC head
fixpth$=Swap$(current$,":","_")
fixpth$=Swap$(fixpth$,"/","\")
PRINT #1,"mkdir "+s$+"%cdir%\"+fixpth$+s$
PRINT #1,"chdir "+s$+"%cdir%\"+fixpth$+s$
ListFiles current$
' List subdirectories of current$
entry$=DIR$(current$+"*", DIR)
DO WHILE entry$ <> ""
IF entry$<>"." AND entry$<>".." THEN
fullpth$=current$+entry$+"/"
' Enqueue subdirectory
queue$(tail) = fullpth$
INC tail
ENDIF
entry$ = DIR$()
LOOP
LOOP
PRINT #1,"chdir "+s$+"%cdir%\"+s$
FLUSH #1
CLOSE #1
CHDIR "/"
cmd$="curl --tftp-blksize 8192 "
CAT cmd$,"-O tftp://"+ipaddress$
CAT cmd$,"/B:/backup.bat"
PRINT "Windows:"
PRINT cmd$