home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / 22RSX / RXMD.ARK / RXMD09.MAC < prev    next >
Text File  |  1985-12-07  |  14KB  |  539 lines

  1. ;
  2. ; Receive a record - returns with carry bit set if EOT received
  3. ;
  4. rcvrecd:
  5.     xra    a;        Clear error count
  6.     sta    errct
  7. rcvrpt:    call    funchk;        Check function keys
  8.     mvi    b,10;        10-seconds to get 1st byte
  9.     lda    frstim
  10.     ora    a
  11.     jnz    rcvr1;        If started, skip next line
  12.     mvi    b,3+1;        Check every 4 seconds until started
  13. rcvr1:    call    recv;        Get any char received
  14.     jc    rcvstot;    Timeout error if no char received
  15.     cpi    soh;        See if it is SOH
  16.     jz    rcvsoh;        Got SOH, get record
  17.     cpi    stx;        See if it is STX for 1k blocks
  18.     jz    rcvstx;        Got STR, get record
  19.     cpi    cancel;        Was it a CTL-X to abort?
  20.     jz    ckcan;        If yes, check for aborting
  21.     ora    a;        Get another char, if a null
  22.     jz    rcvrpt
  23.     cpi    '{';        V.22 synch char, ignore
  24.     jz    rcvrpt
  25.     cpi    '{' + 80h;    V.22 synch char with high bit set
  26.     jz    rcvrpt
  27.     cpi    eot
  28.     stc
  29.     rz;            with carry on end of transmission
  30.     cpi    crc;        Ignore our own char coming back
  31.     jz    rcvrpt
  32.     cpi    ksnd;        Ignore our own char coming back
  33.     jz    rcvrpt
  34.     cpi    nak;        Ignore our own char coming back
  35.     jz    rcvrpt
  36.     mvi    a,1;        Prevents going to modem
  37.     sta    remoff
  38.     call    crlf
  39.     mov    a,b
  40.     call    hexo
  41.     call    ilprt
  42.  db    'H received not SOH ',0
  43. ;    "    "
  44. ; Didn't get SOH or EOT or did not get valid header so purge the line,
  45. ; then send NAK.
  46. ;
  47. rcvsr:    call    wait1;        Flush incoming
  48.     call    ckabort;    Want to quit now?
  49.     lda    frstim;        Get first time switch
  50.     ora    a;        Has first 'SOH' been received?
  51.     mvi    a,nak
  52.     jnz    rcvsr1;        Yes, then send 'NAK'
  53.     lda    crcflg
  54.     ora    a
  55.     mvi    a,nak
  56.     jz    rcvsr1;        Not CRC, signal checksum with NAK
  57.     mvi    a,crc;        Else tell sender we have 'CRC'
  58.     call    send
  59.     lda    kflg
  60.     ora    a
  61.     jz    rcvsr1;        not requesting 1k transmissions
  62.     mvi    a,ksnd;        Signal we also have 1k capability
  63. rcvsr1:    call    send
  64.     lda    errct
  65.     inr    a;        Increment error count
  66.     sta    errct
  67.     mov    b,a;        Keep error count for now
  68.     lda    frstim;        Have we gotten under way yet?
  69.     ora    a
  70.     mov    a,b;        get error count back
  71.     jz    rcvsr2;        Not started yet, exit
  72.     cpi    10;        10 errors the limit, once under way
  73.     jnc    rcvsabt;    Abort if over the limit
  74.     call    rdcount;    Display record count before repeating
  75.     jmp    rcvrpt;        Less than 10, keep going
  76. ;
  77. rcvsr2:    cpi    10;        10 times for 1k/CRC yet? (40 seconds)
  78.     jc    rcvrpt;        Keep trying if less
  79.     xra    a;        Else flip to checksum mode
  80.     sta    crcflg
  81.     mov    a,b;        Get the count back
  82.     cpi    15;        Another 5 times for checksum?
  83.     jc    rcvrpt;        If less, try again, quit at 60 seconds
  84. ;    "    "
  85. ; Error limit exceeded, so abort
  86. rcvsabt:
  87.     xra    a
  88.     sta    remoff;        Allow console output to remote
  89.     lxi    sp,stack;    Clear the stack just in case
  90.     call    closfil;    Keep whatever we got
  91.     call    ilprt
  92.  db    cr,lf,cr,lf,'++ RECEIVED FILE CANCELLED ++',0
  93.     call    delfile;    Delete received file
  94.     call    erxit;        Print 2nd half of message
  95.  db    '++ UNFINISHED FILE DELETED ++','$'
  96. ;
  97. ; Deletes the received file (used if receive aborts)
  98. ;
  99. delfile:
  100.     mvi    a,delet
  101.     call    fileop;        Delete it
  102.     inr    a
  103.     rnz;            Success, return
  104.     call    erxit
  105.  db    cr,lf,'++ Can''t delete received file ++','$'
  106. ;
  107. ; Aborts with 1 CTL-X if first time flag is not set, two otherwise
  108. ;
  109. ckcan:    lda    frstim;        1st time flag set yet?
  110.     ora    a
  111.     jz    rcvsabt;    If not, Abort and close file
  112.     mvi    b,2;        Max 2 seconds for extra CTL-X
  113.     call    recv
  114.     jc    rcvrpt;        No additional char, ignore CTL-X
  115.     cpi    cancel;        If a 2nd CTL-X, abort and close file
  116.     jz    rcvsabt
  117.     jmp    rcvrpt;        Else wait for a STX, SOH or timeout
  118. ;
  119. ; Timed out on receive
  120. ;
  121. rcvstot:
  122.     lda    frstim;        1st time flag set yet?
  123.     ora    a
  124.     jz    rcvsr;        If not, don't show an error
  125.     sta    remoff
  126.     call    ilprt
  127.  db    '++ Timeout waiting for character ++',cr,lf,0
  128.     jmp    rcvsr;        Bump error count, etc.
  129. ;
  130. ; Got a STX - set KFLG for 1k
  131. ;
  132. rcvstx:    sta    kflg;        Set 1k flag
  133.     sta    crcflg;        Ensure in CRC mode for 1k blocks
  134.     jmp    rcvs1
  135. ;
  136. ; Got SOH - get block number, block number complemented
  137. ;
  138. rcvsoh:    xra    a
  139.     sta    kflg;        If SOH, clear the 1k flag
  140. rcvs1:    mvi    b,5;        Timeout = 5 seconds
  141.     mov    a,b;        Get something to store
  142.     sta    remoff;        Error messages only shown locally
  143.     sta    frstim;        Indicate first 'SOH' or 'STX' recvd.
  144.     call    recv;        Get block number
  145.     jc    rcvstot;    timeout
  146.     mov    d,a;        Save block number
  147.     mvi    b,5;        Timeout = 5 seconds
  148.     call    recv;        Get complement of rcd no.
  149.     jc    rcvstot;    Timeout
  150.     cma
  151.     cmp    d;        Same as original block number?
  152.     jz    rcvdata;    Yes, get data
  153. ;    "    "
  154. ; Got bad record number in header
  155.     call    ilprt
  156.  db    '++ Error in header ++',cr,lf,0
  157.     jmp    rcvsr;        Go check error limit and send NAK
  158. ;
  159. rcvdata:
  160.     mov    a,d
  161.     sta    rcvcnt;        get and save record num.
  162.     mvi    c,0;        Init checksum
  163.     lxi    h,0;        Init CRC
  164.     shld    crcval;        Clear CRC counter
  165.     call    grcdsz;        128/1024 on kflg
  166.     lhld    recptr;        Get buffer address
  167. ;    "    "
  168. rcvchr:    mvi    b,5;        5 sec timeout
  169.     call    recv;        Get the character
  170.     jc    rcvstot;    Timeout
  171.     mov    m,a;        Store char
  172.     inx    h;        Point to next char
  173.     dcx    d;        One less to go
  174.     mov    a,d
  175.     ora    e
  176.     jnz    rcvchr;        Not done, get next char
  177.     lda    crcflg;        Using 'CRC'?
  178.     ora    a
  179.     jnz    rcvcrc;        If yes go get 'CRC'
  180. ;    "    "
  181. ; Verify checksum
  182.     mov    d,c;        Save checksum
  183.     mvi    b,5;        Timeout length
  184.     call    recv;        Get checksum
  185.     jc    rcvstot;    Timeout
  186.     cmp    d;        Checksum ok?
  187.     jz    chksnum;    Yes, exit
  188.     call    ilprt
  189.  db    '++ Checksum error ++',cr,lf,0
  190.     jmp    rcvsr;        Go check the error limit and send NAK
  191. ;
  192. ; Got a record, it's a duplicate if equal to the previous number,
  193. ; it's OK if previous + 1 record
  194. chksnum:
  195.     lda    rcvcnt;        Get received record number
  196.     mov    b,a
  197.     lda    rcdcnt;        previous record number
  198.     cmp    b;        Previous record repeated?
  199.     jz    rcvack;        If yes 'ACK' to catch up
  200.     inr    a;        Increment by 1 for 128 char block
  201.     cmp    b;        Match this one we just got?
  202.     jnz    abort;        No match, stop the sender, exit
  203.     ret;            Else return with carry not set, was ok
  204. ;
  205. ; Receive the Cyclic Redundancy Check characters (2 bytes) and see if
  206. ; the CRC received matches the one calculated.    If they match, get next
  207. ; record, else send a NAK requesting the record be sent again.
  208. ;
  209. rcvcrc:    mvi    e,2;        Number of bytes to receive
  210. rcvcrc2:
  211.     mvi    b,5;        5 second timeout
  212.     call    recv;        Get CRC byte
  213.     jc    rcvstot;    Timeout
  214.     dcr    e;        Decrement the number of bytes
  215.     jnz    rcvcrc2;    Get both bytes
  216.     call    crcchk;        Check received CRC against calc'd CRC
  217.     ora    a
  218.     jz    chksnum;    CRC ok, go check record numbers
  219.     call    ilprt
  220.  db    '++ CRC error ++',cr,lf,0
  221.     jmp    rcvsr;        Go check error limit and send NAK
  222. ;
  223. ; Previous record repeated, due to the last ACK being garbaged.
  224. ; ACK it so sender will catch up
  225. rcvack:    call    sndack
  226.     jmp    rcvrecd
  227. ;
  228. ; Send an ACK for the record
  229. ;
  230. sndack:    mvi    a,ack
  231.     jmp    send
  232. ;
  233. ; ---------------------------------
  234. ;
  235. ; Send the record header
  236. ; Send SOH, block number and complemented block number (3 bytes total)
  237. ;
  238. sndhdr:    lda    kflg;        Sending 1k blocks?
  239.     ora    a
  240.     mvi    a,stx;        If yes, send a STX rather than SOH
  241.     jnz    sndhd1
  242.     mvi    a,soh;        Send start of header
  243. sndhd1:    call    send
  244. sndhnm:    lda    rcdcnt;        Send the current record number
  245.     call    send
  246.     lda    rcdcnt;        Get the record number again
  247.     cma;            Complemented
  248.     jmp    send
  249. ;
  250. ; Send the data record
  251. ;
  252. sndrec:    mvi    c,0;        Init checksum
  253.     lxi    h,0;        Init CRC
  254.     shld    crcval
  255.     call    grcdsz;        128/1024 on kflg
  256.     lhld    recptr;        Get buffer address
  257. sendc:    mov    a,m;        Get a char
  258.     call    send;        Send it
  259.     inx    h;        next char
  260.     dcx    d
  261.     mov    a,e
  262.     ora    d
  263.     jnz    sendc;        More
  264.     ret
  265. ;
  266. ; Send the CRC or checksum value, whichever appropriate
  267. ;
  268. sndchk:    lda    crcflg;        See if sending 'CRC' or 'checksum'
  269.     ora    a
  270.     mov    a,c;        checksum value
  271.     jz    send;        If chksum send it
  272. ;    "    "
  273. ; Send the two Cyclic Redundancy Check characters.  Call FINCRC to
  274. ; calculate the CRC which will be in 'DE' upon return.
  275. ;
  276. sndcrc:    call    fincrc;        Calculate the 'CRC' for this record
  277.     mov    a,d;        Put first 'CRC' byte in accumulator
  278.     call    send;        Send it
  279.     mov    a,e;        Put second 'CRC' byte in accumulator
  280.     call    send;        Send it
  281.     xra    a;        Set zero return code
  282.     ret
  283. ;
  284. ; After a record has been sent, and accepted, move the pointers
  285. ; forward 128 or 1024 characters for the next record.
  286. ;
  287. setptr:    call    grcdsz;        128/1024 on kflg
  288.     lhld    recptr;        Get the buffer pointer
  289.     dad    d;        Increment for the record just sent
  290.     shld    recptr;        New buffer address for next block
  291.     ret
  292. ;
  293. ; Get current protocol record size (128 or 1024, on KFLG)
  294. ; a,f,d,e
  295. grcdsz:    lxi    d,128
  296.     lda    kflg
  297.     ora    a
  298.     rz
  299.     lxi    d,1024
  300.     ret
  301. ;
  302. ; After a library transmission has been made, decrement the remaining
  303. ; records in that library file, then reset the 1k flag if less than 8
  304. ; remaining.
  305. ;
  306. setlbr:    lda    kflg
  307.     lxi    d,-1
  308.     ora    a
  309.     jz    setl1
  310.     lxi    d,-8
  311. setl1:    lhld    rcnt;        Alter the records-sent count
  312.     dad    d
  313.     shld    rcnt;        One less transmission to go
  314.     ora    a;        'K' flag already zero?
  315.     rz;            If yes, skip the rest
  316. ;    "    "
  317. ; See if enough records left to use 1k protocol if requested
  318. ;
  319. setflg:    lhld    rcnt
  320.     mov    a,h
  321.     ora    a
  322.     rnz;            256 or more left
  323.     mov    a,l;        Get number of records in 'L' register
  324.     cpi    8
  325.     rnc;            If 8 or more, keep going
  326.     xra    a;        Reset the 'K' flag
  327.     sta    kflg
  328.     ret
  329. ;
  330. ; After a record is sent, a character is returned telling if it was
  331. ; received properly or not.  An ACK allows the next record to be sent.
  332. ; A NAK causes the current record to be resent.  If no character (or
  333. ; any character other than ACK or NAK) is received after a short wait
  334. ; (10 to 12 seconds), a timeout error message is shown and the record
  335. ; will be resent.
  336. ;
  337. gtack:    call    mdinst
  338.     jz    gtack1;        No char ready now
  339.     call    mdinp;        Get the char
  340.     cpi    ack
  341.     rz;            ACK, return
  342.     cpi    nak
  343.     jz    gtack2;        NAK, print error, then resend
  344.     cpi    cancel;        CTL-X to cancel attempt?
  345.     jz    gtcan
  346. gtack1:    mvi    b,1;        1 second for an ACK or NAK
  347.     call    recv;        Go wait for a char
  348.     jc    gtack2;        timed out
  349.     cpi    ack
  350.     rz;            ACK, return
  351.     cpi    nak
  352.     jz    gtack3;        NAK, error
  353.     cpi    cancel;        CTL-X to cancel attempt?
  354.     jz    gtcan
  355. gtack2:    mvi    b,12;        12-seconds more for an ACK or NAK
  356.     call    recv;        Go wait for a char
  357.     jc    gtatot;        timeout
  358.     cpi    ack
  359.     rz;            ACK, return
  360.     cpi    '{'
  361.     jz    gtack2;        ignore V.22 sync char
  362.     cpi    '{' + 080h
  363.     jz    gtack2;        ignore V.22 sync char w/hi bit
  364.     cpi    cancel;        CTL-X to cancel attempt?
  365.     jnz    gtack3
  366. ;    "    "
  367. ; Two or more CTL-X will cancel the file transfer
  368. gtcan:    mvi    b,2;        Up to 2 secs. for another CTL-X
  369.     call    recv
  370.     mvi    a,cancel;    Get original char back
  371.     jc    gtack3;        If no more CTL-X, display the first
  372.     cpi    cancel;        Was it a second one?
  373.     jz    ackmsg;        If yes, abort the file transfer
  374. gtack3:    mov    b,a;        Save the char
  375.     sta    remoff;        Send to console only
  376.     lda    chkeot;        Sending EOT?
  377.     ora    a
  378.     jnz    ackerr;        If yes, don't show error (for KMD)
  379.     call    ilprt
  380.  db    '++ ',0
  381.     mov    a,b
  382.     cpi    nak
  383.     jz    gtack4
  384.     call    hexo
  385.     call    ilprt
  386.  db    'H',0
  387.     jmp    gtack5
  388. ;
  389. gtack4:    call    ilprt
  390.  db    'NAK',0
  391. ;    "    "
  392. gtack5:    call    ilprt
  393.  db    ' received not ACK ++',cr,lf,0
  394. ;    "    "
  395. ; Timeout or error on ACK - bump error count then resend the record
  396. ; if error limit is not exceeded
  397. ;
  398. ackerr:    lda    accerr;        Count accumulated errors on ACK
  399.     inr    a
  400.     sta    accerr
  401.     lda    errct
  402.     inr    a;        Bump error count
  403.     sta    errct
  404.     cpi    10
  405.     jnc    ackmsg;        At limit, send error msg and abort
  406.     call    rdcount;    Else show the record count for repeat
  407.     stc;            Make sure carry is set for repeat
  408.     ret;            And go back
  409. ;
  410. ;
  411. ; Reached error limit
  412. ;
  413. ackmsg:    call    wait1;        Flush input
  414.     call    send3can;    Tell remote we are quitting
  415.     mvi    b,1;        Wait for remote to perhaps quit too
  416.     call    recv
  417.     mvi    a,bs
  418.     call    send3x;        Clear any CTL-X from buffer
  419.     xra    a
  420.     sta    remoff;        Show message on remote and local
  421.     call    erxit
  422.  db    cr,lf,'++ FILE TRANSFER ABORTED ++','$'
  423. ;
  424. ;
  425. ; Timed out, with no character - set the carry bit and return
  426. ;
  427. gtatot:    call    ilprt
  428.  db    '++ Timeout - no character received ++',cr,lf,0
  429.     jmp    ackerr
  430. ;
  431. ; Check the total error count vs. records sent, switch from 1k to 128
  432. ; character transmissions if higher than operator selected value.
  433. ;
  434. gtratio:
  435.     lda    kflg
  436.     ora    a
  437.     rz;            Not 1k blocks, skip this
  438.     lda    errct;        See if we got any errors last record
  439.     cpi    4
  440.     jnc    gtratio1;    If 4 or more, switch to 128 size
  441.     lda    accerr;        See if up to minimum errors yet
  442.     cpi    3;        Had as many as three errors yet?
  443.     rc;            If not, don't get excited too quickly
  444.     lhld    recdno;        Get current record number increment
  445.     lxi    d,-8;        Have not successfully sent this 1k yet
  446.     dad    d;        Subtract the current increment
  447.     xchg
  448.     lhld    accerr;        Number of non-'ACK' errors in HL
  449.     xchg
  450.     call    dvhlde;        Get ratio in BC of records/hit
  451.     call    mspeed;        get current speed
  452.     cpi    5;        1200 baud?
  453.     mvi    a,71-1;        for 1200 bps
  454.     jz    gtr1;        If 1200, skip next line
  455.     mvi    a,43-1;        for 2400 bps
  456. gtr1:    cmp    c;        Compare with actual ratio
  457.     rc;            return if less hits than allowed
  458. ;    "    "
  459. gtratio1:
  460.     xra    a;        Else reset the system to 128
  461.     sta    kflg
  462.     call    ilprt
  463.  db    cr,lf,'Aborting 1k blocks, too many hits',cr,lf,0
  464.     ret
  465. ;
  466. ckabort:
  467.     call    constat
  468.     ora    a
  469.     rz
  470.     call    conin
  471.     cpi    cancel
  472.     rnz
  473. ;    "    "
  474. ; Aborts send or receive routines and returns to command line
  475. ;
  476. abort:    lxi    sp,stack
  477.     call    wait1;        1- sec delay to clear input
  478.     call    send3can;    Show cancelling, remote may quit also
  479.     call    wait1;        1-second delay to clear input
  480.     mvi    a,bs
  481.     call    send3x
  482. abortx:    xra    a;        Reset the batch flag
  483.     sta    bchflg
  484.     call    catch
  485.     call    erxit;        Exit with abort message
  486.  db    cr,lf,'++ RXMD ABORTED ++','$'
  487. ;
  488. ; Send 3 cancels
  489. send3can:
  490.     mvi    a,cancel
  491. ;    "    "
  492. ; Send 3 copies of (a)
  493. send3x:    call    send
  494.     call    send
  495.     jmp    send
  496. ;
  497. ; Increment record number
  498. ; a,f
  499. incrno:    push    h
  500.     push    d
  501.     lhld    rcdcnt;        Incr transmission count
  502.     inx    h
  503.     shld    rcdcnt
  504.     lxi    d,1
  505.     lda    kflg
  506.     ora    a
  507.     jz    incrn1;        not 1k blocks, incr by 1
  508.     mvi    e,8;        If 1k blocks incr. by 8
  509. incrn1:    lhld    recdno;        Get current record count
  510.     dad    d;        Increment that count properly
  511.     shld    recdno
  512.     call    rdcount
  513.     pop    d
  514.     pop    h
  515.     ret
  516. ;
  517. ; Display the record count on the local CRT
  518. ; a,f,h,l
  519. rdcount:
  520.     lhld    recdno;        Get the record number for display
  521.     mvi    a,1
  522.     sta    remoff;        Set local only
  523.     lda    optsav;        See if receive or send mode
  524.     cpi    'R'
  525.     jz    rmsg
  526.     call    ilprt
  527.  db    cr,'Sending # ',0
  528.     jmp    rest
  529. rmsg:    call    ilprt
  530.  db    cr,'Received # ',0
  531. rest:    lhld    recdno
  532.     call    decout
  533.     call    ilprt
  534.  db    ' (',0
  535.     call    t4hex
  536.     call    ilprt
  537.  db    'h) ',0
  538.     jmp    funchk;        Check for function keys
  539. %