home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / cpm / mex / mxm-cq12.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  14.6 KB  |  483 lines

  1.     TITLE    'MEX CONCORD DATA SYSTEMS 224 ARQ/AD OVERLAY V1.2'
  2. ;
  3. ; (DELETE ABOVE TITLE LINE IF ASSEMBLING WITH ASM)
  4. ;
  5. ; MXM-CQ12.ASM  Current version 3 Sep 85
  6. ;
  7. ; Concord Data Systems 224 ARQ/AD modem overlay for MEX v1.1x
  8. ;  Written 7 Feb 85 by Dave Mabry
  9. ;  Adapted using information and excerps from Ron Fowler's
  10. ;   overlay for the PMMI modem.
  11. ;
  12. ; Please leave any bug reports or requests on TCBBS in Dearborn,
  13. ;  Michigan (313-846-6127) or Royal Oak RCPM (313-759-6569)
  14. ;  or call me at 313-956-5703 (voice).        mabry
  15. ;
  16. ; Updates:
  17. ;  MXM-CQ10.ASM
  18. ;   2/7/85...Original release.
  19. ;  MXM-CQ11.ASM
  20. ;   6/29/85...Modified for MEX V1.3x
  21. ;  MXM-CQ12.ASM
  22. ;   9/3/85...Made generic for MEX and MEX Plus.  Use MXPLUS equate for
  23. ;         different versions.
  24. ;
  25. ; Note that unlike the Hayes modem, the Concord does not
  26. ;  have an ascii command that will cause a disconnect.  Therefore
  27. ;  for that feature of MEX to work properly, your normal overlay
  28. ;  for your machine must be able to toggle DTR in the DISCV routine.
  29. ; Note also that the modem must be set for 2400 bps to the eia (rs232)
  30. ;  interface back to your computer.  It will adjust automatically for
  31. ;  dial-up systems that do not support 2400 bps by communicating to
  32. ;  the remote system as 1200 bps, but still communicate to your computer
  33. ;  at 2400 bps.
  34. ;
  35. ; This overlay will work with any other overlays that terminate
  36. ; prior to 0B00H.
  37. ;
  38. VERS    EQU    12        ; Version number
  39. FALSE    EQU    0
  40. TRUE    EQU    0FFH
  41. MXPLUS    EQU    TRUE        ; True for MEX Plus, False for MEX
  42. ;
  43. ;
  44. ; SYSTEM CONSTANTS
  45. ;
  46. NDISCV    EQU    015FH        ; Modem disc routine
  47. DIALV    EQU    0162H        ;LOCATION OF DIAL VECTOR IN OVERLAY
  48. DISCV    EQU    0165H        ;LOCATION OF DISCONNECT VECTOR IN OVERLAY
  49. DIALOC    EQU    0B00H        ;DIALING CODE GOES HERE
  50. SMTABL    EQU    0D55H        ; Smart modem INIT, DE-INIT, SSET ovlys
  51. ;
  52. ;
  53. ; MEX service processor stuff ... MEX supports an overlay service
  54. ; processor, located at 0D00H (and maintained at this address from
  55. ; version to version).  If your overlay needs to call BDOS for any
  56. ; reason, it should call MEX instead; function calls below about
  57. ; 240 are simply passed on to the BDOS (console and list I/O calls
  58. ; are specially handled to allow modem port queueing, which is why
  59. ; you should call MEX instead of BDOS).  MEX uses function calls
  60. ; above about 244 for special overlay services (described below).
  61. ;
  62. ; Some sophisticated overlays may need to do file I/O; if so, use
  63. ; the PARSFN MEX call with a pointer to the FCB in DE to parse out
  64. ; the name.  This FCB should support a spare byte immediately pre-
  65. ; ceeding the actual FCB (to contain user # information).  If you've
  66. ; used MEX-10 for input instead of BDOS-10 (or you're parsing part
  67. ; of a SET command line that's already been input), then MEX will
  68. ; take care of DU specs, and set up the FCB accordingly.  There-
  69. ; after all file I/O calls done through the MEX service processor
  70. ; will handle drive and user with no further effort necessary on
  71. ; the part of the programmer.
  72. ;
  73. MEX    EQU    0D00H        ;address of the service processor
  74. INMDM    EQU    255        ;get char from port to A, CY=no more in 100 ms
  75. TIMER    EQU    254        ;delay 100ms * reg B
  76. TMDINP    EQU    253        ;B=# secs to wait for char, cy=no char
  77. CHEKCC    EQU    252        ;check for ^C from KBD, Z=present
  78. SNDRDY    EQU    251        ;test for modem-send ready
  79. RCVRDY    EQU    250        ;test for modem-receive ready
  80. SNDCHR    EQU    249        ;send a character to the modem (after sndrdy)
  81. RCVCHR    EQU    248        ;recv a char from modem (after rcvrdy)
  82. LOOKUP    EQU    247        ;table search: see CMDTBL comments for info
  83. PARSFN    EQU    246        ;parse filename from input stream
  84. BDPARS    EQU    245        ;parse baud-rate from input stream
  85. SBLANK    EQU    244        ;scan input stream to next non-blank
  86. EVALA    EQU    243        ;evaluate numeric from input stream
  87. LKAHED    EQU    242        ;get nxt char w/o removing from input
  88. GNC    EQU    241        ;get char from input, cy=1 if none
  89. ILP    EQU    240        ;inline print
  90. DECOUT    EQU    239        ;decimal output
  91. PRBAUD    EQU    238        ;print baud rate
  92. PRNTBL    EQU    237        ;print MEX format table (HL)
  93. PRID    EQU    236        ;print MEX ID string on console
  94. ONOFF    EQU    235        ;parse on/off from input stream (a=0 or 1,
  95.                 ; cy=error)
  96. ;
  97. ;
  98. CONOUT    EQU    2        ;simulated BDOS function 2: console char out
  99. PRINT    EQU    9        ;simulated BDOS function 9: print string
  100. INBUF    EQU    10        ;input buffer, same structure as BDOS 10
  101. ;
  102. ;
  103. CR    EQU    0DH
  104. LF    EQU    0AH
  105. ESC    EQU    1BH
  106. ;
  107. ;
  108. MSPEED    EQU    107H        ; Modem speed byte
  109. B1200    EQU    5        ; Byte for 1200 baud
  110. B2400    EQU    6        ; Byte for 2400 baud
  111. NEWBDV    EQU    16EH        ; Entry point for new baud routine
  112. ;
  113. ;
  114.     IF    MXPLUS
  115.  
  116.     ORG    100H        ; TPA
  117.     DB    0C3H        ; Flag overlay
  118.  
  119.     ORG    NDISCV
  120.     RET
  121.  
  122.     ENDIF
  123.  
  124.     ORG    DIALV        ;OVERLAY THE DIALING VECTOR
  125.     JMP    DIAL
  126. ;    
  127. ;
  128. ; This is the DIAL routine called by MEX to dial a digit. The digit
  129. ; to be dialed is passed in the A register.  Note that two special
  130. ; codes must be intercepted as non-digits: 254 (start dial sequence)
  131. ; and 255 (end-dial sequence).  Mex will always call DIAL with 254
  132. ; in the accumulator prior to dialing a number.  Mex will also call
  133. ; dial with 255 in A as an indication that dialing is complete. Thus,
  134. ; the overlay may use these values to "block" the number, holding it
  135. ; in a buffer until it is completely assembled (in fact, that's the
  136. ; scheme employed here).
  137. ;
  138. ; After the 254-start-dial sequence, MEX will call the overlay with
  139. ; digits, one-at-a-time.  MEX will make no assumptions about the dig-
  140. ; its, and will send each to the DIAL routine un-inspected (some modems,
  141. ; like the Smartmodem, allow special non-numeric characters in the
  142. ; phone number, and MEX may make no assumptions about these).
  143. ;
  144. ; After receiving the end-dial sequence (255) the overlay must take
  145. ; whatever end-of-dial actions are necessary *including* waiting for
  146. ; carrier at the distant end.  The overlay should monitor the keyboard
  147. ; during this wait (using the MEX keystat service call), and return
  148. ; an exit code to MEX in the A register, as follows:
  149. ;
  150. ;    0 - Carrier detected, connection established
  151. ;    1 - Far end busy (only for modems that can detect this condition)
  152. ;    2 - No answer (or timed out waiting for modem response)
  153. ;    3 - Keyboard abort (^C only: all others should be ignored)
  154. ;    4 - Error reported by modem
  155. ;    5 - No ring reported by modem
  156. ;    6 - No dial tone reported by modem
  157. ;
  158. ; <No other codes should be returned after an end-dial sequence>
  159. ;
  160. ; The overlay should not loop forever in the carrier-wait routine, but
  161. ; instead use either the overlay timer vector, or the INMDMV (timed 100
  162. ; ms character wait) service call routine.
  163. ;
  164. ; The DIAL routine is free to use any of the registers, but must return
  165. ; the above code after an end-dial sequence
  166. ;
  167.     ORG    DIALOC
  168. ;
  169. DIAL:    LHLD    DIALPT        ;FETCH POINTER
  170.     CPI    254        ;START DIAL?
  171.     JZ    STDIAL        ;JUMP IF SO
  172.     CPI    255        ;END DIAL?
  173.     JZ    ENDIAL        ;JUMP IF SO
  174. ;
  175. ; Not start or end sequence, must be a digit to be sent to the modem
  176. ;
  177.     MOV    M,A        ;PUT CHAR IN BUFFER
  178.     INX    H        ;ADVANCE POINTER
  179.     SHLD    DIALPT        ;STUFF PNTR
  180.     RET            ;ALL DONE
  181. ;
  182. ; Here on a start-dial sequence
  183. ;
  184. STDIAL:    LXI    H,DIALBF    ;SET UP BUFFER POINTER
  185.     SHLD    DIALPT
  186.     RET
  187. ;
  188. ; Here on an end-dial sequence
  189. ;
  190. ENDIAL:
  191.     MVI    M,0        ; Terminate phone number string
  192. ;
  193. CLEAR:
  194.     MVI    C,INMDM        ; Clear out the data buffer in USART
  195.     CALL    MEX
  196.     JNC    CLEAR        ; Get them all
  197.     MVI    A,B2400        ; Assume modem is at 2400 bps
  198.     CALL    NEWBDV        ;  so set computer
  199.     LXI    H,WAKEUP    ; Get modem's attention
  200.     CALL    CDSEND
  201.     MVI    C,5        ; ~.5 second wait
  202.     CALL    CATCHR        ; Catch response from modem
  203.     ORA    A        ; Check response
  204.     JZ    AROUND        ; If there was a response, then modem
  205.                 ;  and system were at same baud rate
  206.     CPI    3        ; User typed ^C ?
  207.     JNZ    ERRET        ; If no, then modem error
  208.     RET            ; Otherwise, return with user abort code
  209. AROUND:
  210.     LXI    H,DCMD        ; Send "dial" command and # to modem
  211.     CALL    CDSEND
  212.     CALL    SENDCR        ; Send <cr> to terminate phone number
  213. ;
  214. ; Here starts the main loop waiting for messages from the modem
  215. ;  and interpreting them.  Some are just passed to the console
  216. ;  and others trigger a specific action.
  217. ;
  218. DLOOP:
  219.     MVI    C,255        ; Long wait here
  220.     CALL    CATCHR        ; Catch response from modem
  221.     ORA    A        ; Zero return code ?
  222.     JNZ    IDLE        ; No, disconnect and return error code
  223.     MOV    A,B        ; Get character count from CATCHR
  224.     ORA    A        ; Hope it isn't zero
  225.     JZ    DLOOP        ; If it is, then ignore this response
  226.     LXI    H,RESPBF    ; Point to string from modem
  227.     LXI    D,RSPTBL    ; Point to valid response table
  228.     CALL    COMPR        ; Find out which response we got
  229.     MOV    A,B        ; Get return value
  230.     CPI    255        ; No response match
  231.     JNZ    DIAL05
  232. ERRET:
  233.     MVI    A,4        ; Error return to MEX
  234.     JMP    IDLE        ; Disconnect and return error code
  235. DIAL05:
  236.     CPI    3        ; OK ?
  237.     JZ    DLOOP        ; Ignore this one
  238.     ORA    A        ; Need to know if 0 ==> connected
  239.     RZ            ; Only this code can return w/o disconnecting
  240.     CPI    7        ; If <= 6 then let it return to MEX
  241.     JC    IDLE
  242.     JNZ    DIAL10        ; If not 7 (7 = voice)
  243.     MVI    A,1
  244.     JMP    IDLE        ; Return BUSY code to MEX
  245. DIAL10:
  246.     CPI    8        ; Call fail ?
  247.     JZ    ERRET        ; Return modem error code
  248.     CPI    13        ; Between 9 and 12 (inclusive) ?
  249.     JNC    DLOOP        ; Ignore 13 and above (13 = dial tone)
  250. ; At this point the match code from COMPR is between 9 and 12 inclusive.
  251. ;  Use this number as an offset into a table of messages, print the
  252. ;  appropriate message and continue to loop.
  253.     SUI    9        ; Now between 0 and 3
  254.     RLC            ; *2
  255.     RLC            ; *4
  256.     RLC            ; *8
  257.     MVI    B,0
  258.     MOV    C,A        ; BC contain offset
  259.     LXI    H,MSGS        ; Point to messages table
  260.     DAD    B        ; Index into it
  261.     XCHG            ; Pointer to message into DE
  262.     MVI    C,9        ; Let mex to string print
  263.     CALL    MEX
  264.     LXI    D,COMSP        ; Print ", "
  265.     MVI    C,9
  266.     CALL    MEX
  267.     JMP    DLOOP        ; And continue to loop
  268.  
  269.  
  270. ;
  271. IDLE:
  272. ;
  273. ; Forces modem into idle state by sending "idle" command and
  274. ;  then toggling DTR using the user's DISCV entry.
  275. ; Preserves any return code that may be in register A.
  276. ;
  277.     PUSH    PSW        ; Preserve any return code
  278.     LXI    H,IDLCMD    ; Send abort character to modem
  279.     CALL    CDSEND
  280.     CALL    DISCV        ; Make sure modem disconnects
  281.     POP    PSW        ; Retrieve return code
  282.     RET
  283.  
  284. SENDCR:
  285. ;
  286. ; Sends a carriage return character to the modem.
  287. ;
  288.     LXI    H,CRMSG        ; Send <cr> to modem
  289.     JMP    CDSEND
  290.  
  291.  
  292. ; Table of valid responses from modem
  293. RSPTBL:
  294.     DB    'IN',0        ; Initiating
  295.     DB    'BSY',0        ; Busy
  296.     DB    'NOA',0        ; No answer
  297.     DB    'OK',0        ; Signon
  298.     DB    'NOT',0        ; No answer tone
  299.     DB    'NOR',0        ; No ring
  300.     DB    'NDT',0        ; No dial tone
  301.     DB    'VDT',0        ; Voice detected
  302.     DB    'CFL',0        ; Call failed
  303.     DB    'DG',0        ; Dialing
  304.     DB    'RG',0        ; Ringing
  305.     DB    'AT',0        ; Answer tone
  306.     DB    'AR',0        ; Answer
  307.     DB    'DT',0        ; Dial tone
  308.     DB    0        ; Table terminator
  309.  
  310. ; Table of messages for some of the entries in the above table.
  311. ;  Each entry must be exactly eight characters including the "$".
  312. MSGS:
  313.     DB    'dialing$'
  314.     DB    'ringing$'
  315.     DB    'anstone$'
  316.     DB    'answer$ '
  317.  
  318. COMSP:
  319.     DB    ', $'        ; To delimit messages
  320.  
  321. COMPR:
  322. ; Compares a string of characters in memory to a table of
  323. ;  strings.  Each entry of the table must be terminated by
  324. ;  a zero byte, and the table must be terminated by another
  325. ;  zero byte.
  326. ; Inputs:  HL points to the string to look for
  327. ;       DE points to the table
  328. ; Output:  B contains the number of the table entry that
  329. ;         matches the string, and a 255 if no entry matched.
  330. ;
  331.     MVI    B,0        ; Init index
  332. CMPR02:
  333.     PUSH    H        ; Save pointer to string in question
  334. CMPR05:
  335.     LDAX    D        ; Fetch char from table
  336.     ORA    A        ; Is it end of table entry ?
  337.     JNZ    CMPR10        ; Not end of entry
  338.     POP    H
  339.     RET            ; Return with match code in B
  340. CMPR10:
  341.     CMP    M        ; Same as char in string ?
  342.     JNZ    CMPR15        ; Jump if not this entry in table
  343.     INX    H        ; Else, point to next char in string
  344.     INX    D        ;  and next char in table entry
  345.     JMP    CMPR05        ; Check next char
  346. CMPR15:
  347.     INR    B        ; Increment index
  348. CMPR20:
  349.     INX    D        ; Next char in table
  350.     LDAX    D        ; Get next char from table
  351.     ORA    A        ; Is it last char in that entry ?
  352.     JNZ    CMPR20        ; No, keep looking
  353.     INX    D        ; Yes, then point to first char of next one
  354.     LDAX    D        ; Now check for end of table
  355.     ORA    A        ; Zero delimits table
  356.     POP    H        ; Point to original string again
  357.     JNZ    CMPR02        ; Go check next table entry
  358.     MVI    B,255        ; No match return code
  359.     RET
  360.  
  361.  
  362. CATCHR:
  363. ;
  364. ; Catch response from modem.
  365. ; Input:  C  delay allowed before timeout (multiples of 100ms)
  366. ; Output: Buffer (RESPBF) contains the string received from modem with
  367. ;       any control characters filtered out.
  368. ;      C  count of characters received before <cr>
  369. ;      A  error code:  0 ==> normal return
  370. ;              2 ==> time out occurred
  371. ;              3 ==> user typed ^C
  372. ;
  373.     LXI    H,RESPBF
  374.     PUSH    H
  375.     MVI    B,BUFLEN    ; Length of character buffer
  376. CRL10:
  377.     MVI    M,0        ; Fill buffer with zeros
  378.     INX    H
  379.     DCR    B
  380.     JNZ    CRL10
  381.     POP    H        ; Get original pointer
  382.     MVI    B,0        ; Character counter
  383. CRLOOP:
  384.     MOV    D,C        ; Initialize count down timer
  385. CRL05:
  386.     PUSH    B        ; Save character counter
  387.     PUSH    D        ; Save time out count down
  388.     PUSH    H        ; Save buffer pointer
  389.     MVI    C,CHEKCC    ; See if user typed ^C
  390.     CALL    MEX
  391.     JZ    UABORT        ; If yes, jump to user abort code
  392.     MVI    C,INMDM        ; Else, continue
  393.     CALL    MEX        ; Get char in 1ms if available
  394.     POP    H        ; Restore working registers
  395.     POP    D
  396.     POP    B
  397.     JC    NOCHAR        ; If no char in 1ms, handle it
  398.     ANI    7FH        ; Mask any parity bit
  399.     CPI    CR        ; End of line from modem ?
  400.     JZ    EOL        ; If <cr> then end of line
  401.     MOV    M,A        ; Here we have a valid character
  402.     INX    H        ;  so save it and bump pointer
  403.     INR    B        ; Increment character counter also
  404.     JMP    CRLOOP        ; Go get the next one
  405.  
  406. ;
  407. ; Handle no character from modem in 1ms
  408. ;
  409. NOCHAR:
  410.     DCR    D        ; Decrement time out counter
  411.     JNZ    CRL05        ; If not to zero, wait some more
  412.     MOV    C,B        ; Else, return with what we have now
  413.     MVI    A,2        ; Time-out error code
  414.     RET
  415. ;
  416. ; End of line from modem
  417. ;
  418. EOL:
  419.     MOV    C,B        ; Character count
  420.     XRA    A        ; Return zero
  421.     RET
  422. ;
  423. ; User abort from ^C
  424. ;
  425. UABORT:
  426.     CALL    IDLE        ; Force disconnect
  427.     POP    H        ; Since these are still on the stack
  428.     POP    D
  429.     POP    B
  430.     MOV    C,B        ; Count of characters up to now
  431.     MVI    A,3        ; User abort code
  432.     RET
  433.  
  434. ;
  435. ; Sends a string of characters pointed to by HL terminated by zero
  436. ;
  437. CDSEND:
  438.     MVI    C,SNDRDY    ; Get modem send status
  439.     CALL    MEX
  440.     JNZ    CDSEND        ; Wait for modem ready
  441.     MOV    A,M        ; Get character
  442.     INX    H        ; Point to next character
  443.     ORA    A        ; Is this the terminator ?
  444.     RZ            ; If yes, done
  445.     MOV    B,A        ; Pass character in B
  446.     MVI    C,SNDCHR    ; Let MEX send to modem
  447.     CALL    MEX
  448.     JMP    CDSEND
  449.  
  450. ;
  451. NOTIMP:
  452.     MVI    C,ILP
  453.     CALL    MEX
  454.     DB    'Not implemented'
  455.     DB    ' (CDS ARQ v'
  456.     DB    (VERS / 10) + '0', '.', (VERS MOD 10) + '0'
  457.     DB    ')',CR,LF,0
  458. JUSTRT:
  459.     RET
  460.  
  461. ;
  462. ; DATA AREA
  463. ;
  464. ; Wakeup string to put modem into "interactive DTE" mode
  465. WAKEUP:    DB    CR,CR,'B',CR,0 ; String to wake up modem
  466. IDLCMD:    DB    ESC,0        ; Idle command
  467. CRMSG:    DB    CR,0
  468.  
  469. DCMD:    DB    'DM'        ; Dial command to modem
  470. DIALBF:    DS    30        ; Phone number buffer
  471.  
  472. BUFLEN    EQU    8        ; Length of response buffer
  473. RESPBF:    DS    BUFLEN        ; Response from modem
  474. DIALPT:    DS    2        ;DIAL POSITION POINTER
  475. ;
  476.     ORG    SMTABL
  477.  
  478.     DW    JUSTRT        ; Initialization
  479.     DW    NOTIMP        ; SSET
  480.     DW    JUSTRT        ; De-initialization
  481.  
  482.     END
  483.