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 : XModem file transfers.
Author | Message | ||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
|
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
Just found this 30 year old code example for QBasic. Seems it supports:- Both Send and Receive functions. Supports AT Command set controls for RS-232/PTSN Modems. 3 Modes, Checksum, CRC & XModem 1k. BPS Transfer Rate Calculation. 300 code lines with comments stripped. Don't need most of it's functions:- Receive Mode - Not really. Modem Support - Not at all. 3 different modes (but advice on which is most appropriate). Transfer rate calculations - Not needed. Does this look like the appropriate starting point for something to simply retrieve files from the SD card via an XModem transfer in Teraterm? Feedback & advice appreciated before I make an attempt. Thanks Phil. [Code] 'call xmodem:end 'test mode sub XMODEM static '************************************************************************** '* EBBS-PC xmodem module copyright 1987 by Ed Parry - started 871107 * '************************************************************************** ' ' Handles xmodem checksum & xmodem/crc-ccitt ' ' Read "XMODEM.DAT" file for passed/shared variables ' Read : port, baud$, name$, start.time!, filename$, mode$, xm, local.mode ' Defs : ' port = active rs232 port ' baud$ = baud rate IE:0300, 1200, 2400, etc. ' name$ = User's name (Currently not in use) ' start.time! = Value of TIMER when user 1st logged on ' filename$ = Name of file to transfer ' mode$ = send or receive mode ' xm = xmodem protocol indicator (1 - 3) - Checksum, CRC, 1k ' local.mode = local or remote - if remote then dropped carrier aborts ' ' Send "XMODEM.DAT" file for passed/shared vars ' Send : abort, time.on, xfer.time ' Defs: ' abort = abort status - either true (-1) or false (0) ' time.on = time.of actual transfer ' xfer.time = Actual effective xfer time (So EBBS can calc BPS Rate) ' ' Pass abort status (true/false), time.on, effective xfer rate (BPS & %) ' '************************************************************************* '* INITIALIZE ALL SYSTEM VARIABLES - MISC EBBS SETUP * '************************************************************************* 'INIT.VARS:' Set-up and init defint a-z up$="871126":au$="Ed Parry":ve$="v1.0" locate 15,1 dim xm$(2),crctb(256):r$=chr$(13):rl$=r$+chr$(10) s$=space$(1):q$=chr$(34):true=-1:false=0 offset=0:start.time!=timer:cdm=128:abort=false null$=chr$(0):soh$=chr$(1):eot$=chr$(4) ack$=chr$(6):nak$=chr$(21):can$=chr$(24):pad$=chr$(26) xm$(1)="Xmodem":xm$(2)="Xmodem/CRC":bs=128:crc$=null$+null$ test.mode=false 'set to true for local testing and mods 'LOAD.CONFIG.VARIABLES: ' Load variables here! if test.mode then ' Define for desired settings port=2:baud$="1200":name$="System Operater" filename$="c:\ebbs\NEWUSERS.MSG" mode$="send":xm=2 local.mode=true goto SETUP.CFG.VARS end if open "XMODEM.INP" for input as # 2 if oops=53 then close #2:print"XMODEM.DAT file not found":_ abort=true:goto EXIT.MODULE input#2,port,baud$,name$,start.time!,filename$,mode$,xm,local.mode close # 2 SETUP.CFG.VARS: if port=1 then msr=&h3fe:mcr=&h3fc:lsr=&h3fd if port=2 then msr=&h2fe:mcr=&h2fc:lsr=&h2fd if xm=1 then chking$="CHECKSUM ":xoffset=4:_ else chking$="CRC/CCITT":xoffset=5 if mode$="send" then send=true:recv=false:else recv=true:send=false 'READ.CRC.TABLE: for i=0 to 255:read crctb(i):next:restore data 0,4129,8258,12387,16516,20645,24774,28903 data -32504,-28375,-24246,-20117,-15988,-11859,-7730,-3601 data 4657,528,12915,8786,21173,17044,29431,25302 data -27847,-31976,-19589,-23718,-11331,-15460,-3073,-7202 data 9314,13379,1056,5121,25830,29895,17572,21637 data -23190,-19125,-31448,-27383,-6674,-2609,-14932,-10867 data 13907,9842,5649,1584,30423,26358,22165,18100 data -18597,-22662,-26855,-30920,-2081,-6146,-10339,-14404 data 18628,22757,26758,30887,2112,6241,10242,14371 data -13876,-9747,-5746,-1617,-30392,-26263,-22262,-18133 data 23285,19156,31415,27286,6769,2640,14899,10770 data -9219,-13348,-1089,-5218,-25735,-29864,-17605,-21734 data 27814,31879,19684,23749,11298,15363,3168,7233 data -4690,-625,-12820,-8755,-21206,-17141,-29336,-25271 data 32407,28342,24277,20212,15891,11826,7761,3696 data -97,-4162,-8227,-12292,-16613,-20678,-24743,-28808 data -28280,-32343,-20022,-24085,-12020,-16083,-3762,-7825 data 4224,161,12482,8419,20484,16421,28742,24679 data -31815,-27752,-23557,-19494,-15555,-11492,-7297,-3234 data 689,4752,8947,13010,16949,21012,25207,29270 data -18966,-23093,-27224,-31351,-2706,-6833,-10964,-15091 data 13538,9411,5280,1153,29798,25671,21540,17413 data -22565,-18438,-30823,-26696,-6305,-2178,-14563,-10436 data 9939,14066,1681,5808,26199,30326,17941,22068 data -9908,-13971,-1778,-5841,-26168,-30231,-18038,-22101 data 22596,18533,30726,26663,6336,2273,14466,10403 data -13443,-9380,-5313,-1250,-29703,-25640,-21573,-17510 data 19061,23124,27191,31254,2801,6864,10931,14994 data -722,-4849,-8852,-12979,-16982,-21109,-25112,-29239 data 31782,27655,23652,19525,15522,11395,7392,3265 data -4321,-194,-12451,-8324,-20581,-16454,-28711,-24584 data 28183,32310,20053,24180,11923,16050,3793,7920 '************************************************************************* '* Reset modem and goto xfer file * '************************************************************************* 'INIT.MODEM: close:out mcr,inp(mcr) or 1 'force modem to keep DTR high open "com"+mid$(str$(port),2)+":"+baud$+",n,8,1,DS0,CS0" as # 1 if not test.mode or (inp(msr) and cdm) then goto IM1 print "Press ENTER":while inkey$ <> r$:wend print#1,"AT E0 Q1 M0 A":call SLEEP(7.0) IM1: gosub CLEAR.BUFS if send then goto SEND.FILE if recv then goto RECV.FILE abort=true:goto EXIT.MODULE '************************************************************************* '* Xmodem Module Sub-Routines (Alphabetized) * '************************************************************************* CHECK.ABORT:' Check for a CAN$ (aborted xfer) if a$=can$ then status$="Remote abort" if b$=can$ then status$="Local abort" if a$ = can$ or b$ = can$ then abort=true return CHECK.CARRIER:' Keep an eye on the carrier carrier = true if local.mode or (inp(msr) and cdm) then return if (inp(msr) and cdm) <> cdm then call SLEEP(.5) if (inp(msr) and cdm) <> cdm then carrier=false return CLEAR.BUFS:' Clear keyboard and RS232 input buffers call SLEEP(.1):while not eof(1):a$=input$(loc(1),1):wend while inkey$ > "":a$=inkey$:wend return CONVERT.TIMER:' Use timer to maintain and calc online time if start.time! > timer then offset! = 86400 - start.time!:_ start.time! = 0 time.on = (timer - start.time!) + offset! return CALC.CRC:' Calculates CRC for xfer recv block crc$=null$+null$:for p=1 to bs crc$=mki$(crctb(asc(left$(crc$,1)) xor_ asc(mid$(dat$,p,1))) xor cvi(null$+right$(crc$,1))) crc$=right$(crc$,1)+left$(crc$,1):next return CALC.RECV.CRC:' Calculates CRC for xfer send block if len(block$) < 4 or len(block$) > bs+3 then return crc$=mki$(crctb(asc(left$(crc$,1)) xor_ asc(right$(block$,1))) xor cvi(null$+right$(crc$,1))) crc$=right$(crc$,1)+left$(crc$,1) return GET.BYTE:' Checks keyboard AND modem for a byte a$="":if not eof(1) then a$=input$(1,1) b$=inkey$:return READ.BLOCK:' Read in a block from disk - send file get#2:if loc(2) < filesize! then return block$=left$(bloc$,lof(2) mod bs) bloc$=block$+string$(bs - len(block$),pad$) done=true return RECV.BLOCK:' Reads in a modem block - recv file while not eof(1) and loc(1) > 0 block$=block$+input$(1,1):gosub CALC.RECV.CRC:wend if len(block$) >= bs+xoffset then return gosub CHECK.CARRIER:if not carrier then_ status$="Lost Carrier":goto ABORTED.XFER call SLEEP(.1):if not eof(1) then goto RECV.BLOCK return SEND.NAK:' Sends init nak if nak = 6 then xm=1 ' drop to checksum if xm = 1 then print#1,nak$; ' init checksum if xm = 2 then print#1,"C";:nak=nak+1 ' init CRC return TIMEOUT:' Check carrier & timeouts during xfer gosub CONVERT.TIMER:tim.out=false:er=false if val(sec$) <> time.on mod 60 then gosub UPDATE.TIME.ON:gosub CHECK.CARRIER:gosub XMIT.DATA if not carrier then status$="Lost carrier":abort=true end if if time.on > it+9 then er$="Timeout":er=true:bad.blocks=bad.blocks+1:timeout=timeout+1 gosub XMIT.DATA:tim.out=true if timeout = 10 then status$="Timeout abort":abort=true gosub CONVERT.TIMER:it=time.on end if return UPDATE.TIME.ON:' Prints elapsed time row=csrlin:col=pos(0):view print 1 to 2 gosub CONVERT.TIMER:locate 1,72:min$=mid$(str$(int(time.on/60)),2) sec$=mid$(str$(time.on mod 60),2):if len(sec$) = 1 then sec$="0"+sec$ print min$":"sec$:view print 3 to 24 locate row,col return XMIT.DATA:' Update xfer info print "Error Checking : "chking$ if len(crc$)=1 then crc$=null$+crc$ print "CRC/Checksum : "hex$(cvi(right$(crc$,1)+left$(crc$,1)))s$s$s$ if send then sr$="Sent :":else sr$="Received :" print "Bytes "sr$;bytes! print "Good Blocks :"block-1 print "Errors :"bad.blocks if er then er$=er$+" in block"+str$(block) print "Last Error : "er$;;space$(78-pos(0)):er=false print "Status : "status$;space$(78-pos(0)) gosub CONVERT.TIMER:et=time.on-start.xfer min=int(et/60):sec=et mod 60 if min <> 1 then m$="mins":else m$="min" if sec <> 1 then se$="secs":else se$="sec" print "Elapsed Time :"min;m$;sec;se$;space$(5) locate 16,1 return XMIT.WAIT:' Waits til xmit buffer is clear while inp(lsr)=0:wend return '************************************************************************* '* Xmodem Send Routine * '************************************************************************* SEND.FILE:' 1st set-up oops=0:open filename$ for random access read as # 2 len=bs if oops=53 then goto ABORTED.XFER field #2,bs as bloc$:last.block=false total.blocks=int(lof(2)/bs)+1 filesize!=(lof(2)/bs):counter!=1 print:block=1:bytes!=0:bad.blocks=0 er$="None":done=false:status$="Waiting for initial handshake" gosub XMIT.DATA:b$="":gosub CONVERT.TIMER timeout=0:it=time.on:start.xfer=time.on SEND1: gosub GET.BYTE ' check for init nak or "C" if a$=nak$ then chking$="CHECKSUM ":_ xm=1:goto SEND5 ' CHKSUM init if a$="C" then chking$="CRC/CCITT":_ xm=2:goto SEND5 ' CRC init gosub CHECK.ABORT:if abort then goto ABORTED.XFER gosub TIMEOUT:if abort then goto ABORTED.XFER goto SEND1 SEND5: gosub XMIT.DATA:gosub CONVERT.TIMER start.xfer=time.on:er=false:gosub READ.BLOCK:dat$=bloc$ gosub CALC.CRC SEND2: gosub CLEAR.BUFS:status$="Sending block" x2$=chr$(block and 255):x3$=chr$(255 - (255 and block)) if xm=1 then 'checksum chksum=0:for i=1 to bs:chksum=chksum+asc(mid$(block$,i,1)) next:chksum=chksum and 255:block1$=soh$+x2$+x3$+bloc$+chr$(chksum) crc$=chr$(chksum) goto SEND3 end if ' CRC block1$=soh$+x2$+x3$+bloc$+crc$ SEND3: gosub XMIT.DATA:print#1,block1$; if done then last.block=true:goto SEND4 if a$ <> nak$ then gosub READ.BLOCK:dat$=bloc$:gosub CALC.CRC gosub CONVERT.TIMER:it=time.on:timeout=0 SEND4: gosub GET.BYTE if a$=nak$ then status$="Resending block":_ bad.blocks=bad.blocks+1:er=true:er$="NAK":goto SEND3 if a$=ack$ then block=block+1:bytes!=bytes!+bs:er=false:status$="Received ACK" gosub XMIT.DATA:if last.block then goto SENEX goto SEND2 end if gosub CHECK.ABORT:if abort then goto ABORTED.XFER gosub TIMEOUT:if abort then goto ABORTED.XFER goto SEND4 SENEX: print#1,eot$;:gosub CONVERT.TIMER:it=time.on:timeout=0 SENX1: status$="Sending EOT":gosub XMIT.DATA gosub GET.BYTE gosub CHECK.ABORT:if abort then goto ABORTED.XFER if a$=ack$ then abort=false:status$="Transfer Complete":_ goto EXIT.MODULE if a$=nak$ then print#1,eot$;:goto SENX1 gosub TIMEOUT:if abort then goto ABORTED.XFER goto SENX1 '************************************************************************* '* Xmodem Receive Routine * '************************************************************************* RECV.FILE:' Set-up and init vars oops=0:open filename$ for output as # 2 if oops=53 then goto ABORTED.XFER print:block=1:bytes!=0:bad.blocks=0 er$="none":done=false:status$="Sending initial handshake" gosub XMIT.DATA:b$="":gosub CONVERT.TIMER timeout=0:it=time.on:start.xfer=time.on:seq.err=0:nak=0 gosub CLEAR.BUFS:gosub SEND.NAK:in.row=0 RECV1: gosub GET.BYTE:if a$=soh$ then_ block$=a$:start.xfer=time.on:goto RECV5 gosub CHECK.ABORT:if abort then goto ABORTED.XFER gosub TIMEOUT:if abort then goto ABORTED.XFER if tim.out then gosub SEND.NAK goto RECV1 RECV5: gosub CONVERT.TIMER:it=time.on:timeout=0 RECTO: gosub XMIT.DATA if not eof(1) and b$="" then status$="Receiving block":_ gosub XMIT.DATA:crc$=null$+null$:gosub RECV.BLOCK:er=false gosub TIMEOUT:if abort then goto ABORTED.XFER b$=inkey$:if b$ = can$ then status$="Local abort":goto ABORTED.XFER x1$=left$(block$,1):x2$=mid$(block$,2,1):x3$=mid$(block$,3,1) if x1$ = can$ then status$="Remote abort":goto ABORTED.XFER if x1$ = eot$ then status$="Received EOT":goto RECV3 if (x1$ <> soh$) then er=true:er$="Incorrect SOH":goto RCER if x2$=null$ and x3$=chr$(255) then if block=1 then_ status$="Sending 0 block ACK":print#1,ack$;:block$="":goto RECV5 if x2$ <> chr$(block and 255) then er=true:_ er$="Block out of sequence":goto RCER if x3$ <> chr$(255 - (255 and block)) then_ er=true:er$="Compliment out of sequence":goto RCER if x2$ = chr$((block-1) and 255) then_ er=true:er$="Duplicate block":goto RCER dat$=mid$(block$,4,bs) rcrc$=mid$(block$,132,2):if xm=1 then chk$=right$(block$,1) if len(block$) < bs+xoffset then er=true:er$="Short Block" if len(block$) > bs+xoffset then er=true:er$="Long Block" RCER: if not er and xm=1 then chksum=0:for i=1 to bs:chksum=chksum+asc(mid$(dat$,i,1)) next:chksum=chksum and 255:crc$=chr$(chksum) if chk$ <> chr$(chksum) then er=true:er$="Bad checksum" end if if not er and xm=2 then_ if rcrc$ <> crc$ then er=true:er$="Bad CRC checksum" if er then bad.blocks=bad.blocks+1:in.row=in.row+1 if in.row = 10 then er$="10 consecutive errors":_ status$="Aborting transfer":goto ABORTED.XFER status$="Sending NAK for block"+str$(block) gosub XMIT.DATA:gosub CLEAR.BUFS:print#1,nak$; block$="":goto RECV5 end if block=block+1:print#2,dat$;:bytes!=bytes!+bs:in.row=0:block$="" status$="Sending ACK":gosub CLEAR.BUFS:print#1,ack$; goto RECV5 RECV3: print#1,ack$;:gosub XMIT.DATA:status$="Transfer complete" abort=false:goto EXIT.MODULE '************************************************************************* '* Wrap it up and exit! * '************************************************************************* ABORTED.XFER: close #2:gosub CLEAR.BUFS:abort=true print#1,string$(2,can$); ' send 2 CAN$(celled) EXIT.MODULE:' Clean up and return to EBBS gosub CONVERT.TIMER:xfer.time=time.on-start.xfer gosub CLEAR.BUFS:gosub XMIT.DATA:close #2 open "XMODEM.OUT" for output as #2 print#2,abort;rl$;xfer.time:locate 23,1:close #2 close #1:out mcr,inp(mcr) or 1 'force modem to keep DTR high end sub [/code] |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5923 |
If you do a Google search for "XMODEM Protocol Overview" you will get a description from the person who wrote the protocol back in 1982 If you forget the CRC mode and the 1k mode things get easier to do. Jim VK7JH MMedit MMBasic Help |
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
If you forget the CRC mode and the 1k mode things get easier to do. Thanks Jim, I'm treading water that's on my depth limit, but searching a lot. So MMedit? You are using the Checksum method? Definitely don't need the others. One will do. Another alternative would be if some of the C Guru's on here could look into the possibility of compiling a Custom C-Function to address the task. Can @matherp or any of the others talented in the C programming comment on the feasibility of using something like this C source example to provide MM Plus users with a basic ability to download files from their SD cards. Phil. Edit, I don't really understand that code, but presume there's more to it, Ie this stuff... [Code]+#include <stdio.h> +#include <stdlib.h> .. .. Etc.[/code] |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5923 |
Phil, I have made a start for you but my hot water cistern just filled the house with smoke so it might take me a while to get the smoke back in. This bit of code extracts the file 128 bytes at a time and adds the headers and checksum ready to send It still needs code to wait for the start request and handle NAC and ACK etc. For now, it prints everything without waiting. DIM myfile$="fm2.bas" DIM soh$ = CHR$(1) DIM er er = sendXM(myfile$) IF er = 0 THEN PRINT "sent OK" ELSE PRINT "ERROR!!!" ENDIF END FUNCTION sendXM(filename$) LOCAL n, r, lineofdata$ IF areweready() = 1 THEN OPEN filename$ FOR INPUT AS #2 DO WHILE EOF(#2) = 0 n = (n + 1) AND &hFF lineofdata$= INPUT$(128,#2) IF LEN(lineofdata$)<128 THEN lineofdata$ = lineofdata$ +STRING$(128-LEN(lineofdata$),CHR$(0)) ENDIF ' soh$+" "+STR$(n,3)+" "+STR$(n XOR &hFF,3)+ " "+STR$(chksum(lineofdata$),3)+" "+lineofdata$ r = sendXMline(soh$+CHR$(n)+CHR$(n XOR &hFF)+lineofdata$+CHR$(chksum(lineofdata$))) IF r <> 0 THEN EXIT DO LOOP CLOSE #2 sendXM = r ELSE sendXM = -1 ' failed to start ENDIF END FUNCTION FUNCTION chksum(txt$) LOCAL n, ch$ chksum = 0 FOR n = 1 TO LEN(txt$) ch$=MID$(txt$,n,1) chksum=chksum XOR ASC(ch$) NEXT n END FUNCTION FUNCTION sendXMline(txt$) ' we need to communicate with the receiving end and respond to ACK/NAK etc PRINT txt$ sendXMline = 0 ' return error code for this line END FUNCTION FUNCTION areweready() ' wait for the start request - timeout needed areweready = 1 END FUNCTION That's as far as I will get for now. Jim VK7JH MMedit MMBasic Help |
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
Thanks Jim, Trying to understand it. Have it on an E64 with a 200 line log file saved on the SD card. When I run it, the data is written to the console, (as expected). At this point in time, before anything is sent, I presume the Micromite code should be waiting for a command/string from Tera Term to say "Send me something", as indicated by the areweready function? Thanks Phil. |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5923 |
-------- 5. DATA FLOW EXAMPLE INCLUDING ERROR RECOVERY Here is a sample of the data flow, sending a 3-block message. It includes the two most common line hits - a garbaged block, and an <ack> reply getting garbaged. <xx> represents the checksum byte. SENDER RECIEVER Times out after 10 seconds, <--- <nak> <soh> 01 FE -data- <xx> ---> <--- <ack> <soh> 02 FD -data- <xx> ---> (data gets line hit) <--- <nak> <soh> 02 FD -data- <xx> ---> <--- <ack> <soh> 03 FC -data- <xx> ---> (ack gets garbaged) <--- <ack> <soh> 03 FC -data- <xx> ---> <--- <ack> <eot> ---> <--- <ack> The areweready() function waits for a <NAK> then it sends the first 128 bytes. If the receiver sends an <ACK>, the next packet is sent. If the receiver sends a <NAK>, the same packet is sent again. After the last packet <EOT> is sent. To abort either end can send three or more <CAN>s I'm in holiday mode now (going to see what rotten herring tastes like) so I won't have anything to play with for a month or so. Rather than full XMODEM, you could send your data a line at a time with the checksum added. chksum() works for any length data. The receiving end does a chksum() to each line and compares. Jim VK7JH MMedit MMBasic Help |
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
Thanks Jim, I might give the line at a time idea a go; bit out of my depth with the XMODEM, but can probably do a line by line for the moment & just capture the text. Spent the last 1/2 hour trying to setup a timeout & receive the NAK (Chr$(21), correct), but not getting it right. Dunno about the Herring???, but I've got some great New Zealand Oysters here. Enjoy your time away. Cheers Phil. |
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
Just wrote this, which should be workable with the code Jim wrote. It's only reading lines for testing purposes, but still... Wait's indefinitely for a NAK at this stage... When it sets Resp$ to an ACK to get the first block sent. Then waits for an ACK or NAK, then either sends the next block, or resends the current one. It will need to handle other things like Cancel, to many retries, timeout etc. Any additional help would be appreciated, & I think a few others might fine it useful for retrieving files from SD cards via Tera Term. Print "Waiting for a NAK to Start (n)" do Resp$=Inkey$ if Resp$=NAK$ Then Exit do Loop Print "Starting" OPEN "templog.txt" FOR Input AS #1 Resp$=ACK$ 'Waits for eithe an "a" or "n" to simulate ACK of NAK do if Resp$=ACK$ Then Blk%=Blk%+1 Line Input #1,LineRead$ if LineRead$="" Then Exit do LineSend$="Block_" + Str$(Blk%,3,0,"0") + " " + LineRead$ Print LineSend$ Else if Resp$=NAK$ Then Print LineSend$ End if Resp$=Inkey$ Loop Close #1 Print "Finished" On a tangent, a colleague has pointed me towards some of Someone else's Micromite xModem C Code source. Can this be easily implemented into a custom cFunction which would provide an xmodem send capability for the MM+. I'd presume the main thing you would need to pass to it would be the file name to be sent & the function would handle the rest & wait for the receiver to interact. Can anyone with C talents comment on the feasibility? Thanks Phil. |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3167 |
I am currently working on V5.4 which has the ability to save a file to the SD card within a program. I don't have a finish date yet but it will not be long (weeks rather than months). Geoff Geoff Graham - http://geoffg.net |
||||
TassyJim Guru Joined: 07/08/2011 Location: AustraliaPosts: 5923 |
Phil, while you wait for V5.4, you might like to try this dim myfile$="fm2.bas" dim soh$=CHR$(1),stx$=CHR$(2),eot$=CHR$(4),ack$=CHR$(18),nak$=CHR$(21),can$=CHR$(24) dim er, g$ dim log$ input g$ g$ = ucase$(g$) if g$ = "XM" then er = sendXM(myfile$) if er = 0 then print "sent OK" else print "ERROR!!! "+str$(er) endif endif END FUNCTION sendXM(filename$) LOCAL n, r, lineofdata$ r = areweready() sendXM = r if r = 0 then OPEN filename$ FOR input AS #2 DO WHILE EOF(#2) = 0 n = (n + 1) AND &hFF lineofdata$= INPUT$(128,#2) if LEN(lineofdata$)<128 then lineofdata$ = lineofdata$ +STRING$(128-LEN(lineofdata$),CHR$(0)) endif ' soh$+" "+STR$(n,3)+" "+STR$(n XOR &hFF,3)+ " "+STR$(chksum(lineofdata$),3)+" "+lineofdata$ r = sendXMline(soh$+CHR$(n)+CHR$(n XOR &hFF)+lineofdata$+CHR$(chksum(lineofdata$))) log$= log$+str$(r) if r <> 0 then exit DO LOOP CLOSE #2 if r = 8 then sendXM = r else sendXM = r ' 1 = failed to start endif endif END FUNCTION FUNCTION chksum(txt$) LOCAL n, ch$ chksum = 0 FOR n = 1 TO LEN(txt$) ch$=MID$(txt$,n,1) chksum=chksum XOR ASC(ch$) NEXT n END FUNCTION FUNCTION sendXMline(txt$) LOCAL k$, n, starttime ' we need to communicate with the receiving end and respond to ACK/NAK etc sendXMline = 9 starttime = timer k$ = INPUT$(255,#0) ' flush input buffer print txt$ ' k$ = input$(255,#0) pause 100 DO k$ = INPUT$(1,#0) if k$ = ack$ then sendXMline = 0 ' received the ack exit DO endif if k$ = nak$ then k$ = INPUT$(255,#0)' flush input buffer print txt$ pause 100 endif if k$ = can$ then pause 100 k$ = INPUT$(2,#0) if k$ = can$+can$ then sendXMline = 8 ' received 3 cancels exit DO endif endif if timer - starttime > 10000 then ' timeout waiting for ack sendXMline = crashout() endif LOOP END FUNCTION FUNCTION areweready() LOCAL k$, starttime areweready = 9 ' wait for the start request - timeout needed starttime = timer DO k$ = INPUT$(1,#0) if k$<>"" then print ASC(k$) if k$ = nak$ then print "NAK" areweready = 0 ' received the start request exit DO endif if timer - starttime > 20000 then ' timeout waiting for start areweready = crashout() print "timeout" exit DO endif LOOP END FUNCTION FUNCTION alldone() LOCAL k$, starttime 'terminate the transfer alldone = 9 starttime = timer DO k$ = INPUT$(255,#0) ' flush input buffer print eot$ pause 100 k$ = INPUT$(1,#0) if k$ = ack$ then alldone = 0 exit DO endif if timer - starttime > 10000 then ' timeout alldone = 7 exit DO endif LOOP END FUNCTION FUNCTION crashout() ' terminate due to error print can$+can$+can$ crashout = 6 END FUNCTION I have added the flow control bits to the first code I presented. I can't test it with teraterm for now but it seemed to work OK with some simulating I did. There is a lot of timing to get right for smooth flow and testing over a local network is different to the real world. Jim VK7JH MMedit MMBasic Help |
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
I can't test it with teraterm for now but it seemed to work OK with some simulating I did. Thanks Jim, It's not initially working in Tera Term, Exiting with error 8. It's a little hard to debug when you can't add debug lines to output to console. All I tested with was a bare E64 hanging off the USB port, but will add HC-12 on Com1 a bit later so I can spit some debug print lines out to a separate instance of Teraterm. Have a USB HC-12 that useful for monitoring what's flying about amongst the little collection of other HC-12's Or 2nd though, might grab an E100 & add a few lines to put the debug output on the LCD. Phil. |
||||
Phil23 Guru Joined: 27/03/2016 Location: AustraliaPosts: 1664 |
Teraterm Debug mode ? Has anyone used it? Doesn't seem to work for me despite this in my ini file.... [code]; Display all characters (debug mode) Debug=on ; Debug mode type which can be selected by user. ; on|all = All types ; off|none = Disabled debug mode ; normal = usual teraterm debug mode ; hex = hex output ; noout = disable output completely DebugModes=all[/code] Just seems to ignore "Shift+Esc". |
||||
Print this page |