home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / simtel / sigm / vols200 / vol220 / mxo-rv13.asm < prev    next >
Encoding:
Assembly Source File  |  1994-07-13  |  14.3 KB  |  478 lines

  1.     TITLE    'MEX RACAL-VADIC VA212 OVERLAY V1.0'
  2. ;
  3. ; (DELETE ABOVE TITLE LINE IF ASSEMBLING WITH ASM)
  4. ;
  5. ; MXO-RV10.ASM  Original release 5/20/84
  6. ;
  7. ; Racal Vadic VA212 overlay for MEX: revision 1.0
  8. ;  Written 20 May 1984 by Dave Mabry
  9. ;  Adapted using information and excerpts 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. ;  MXO-RV11.ASM:
  18. ;   5/21/84...Fixed bug in Busy handler that left modem in
  19. ;    "terminal" mode.  This caused no problems but it
  20. ;    wasn't "clean".
  21. ;  MXO-RV12.ASM
  22. ;   5/22/84...Added code to ensure the modem is left in
  23. ;    "idle" state after busy signal returned.
  24. ;    Major rewrite with debugging done using a data line
  25. ;    monitor.  This version should work without problems
  26. ;    on all systems.
  27. ;  MXO-RV13.ASM
  28. ;   8/25/84...Major change.  This overlay now supports both
  29. ;    the VA3451 (w auto-dial ROM) and the VA212.  Set OLDVA
  30. ;    to true to include VA3451 code.  (Look for "IF OLDVA" to
  31. ;    find additions.)
  32. ;                        Bob Horn
  33. ;
  34. ; Note that unlike the Hayes modem, the Racal Vadic does not
  35. ;  have an ascii command that will cause a disconnect.  Therefore
  36. ;  for that feature of MEX to work properly, your normal overlay
  37. ;  for your machine must be able to toggle DTR in the DISCV routine.
  38. ;
  39. ; This overlay will work with any modem overlay that terminates
  40. ; prior to 0B00H
  41. ;
  42. FALSE    EQU    0
  43. TRUE    EQU    NOT FALSE
  44. OLDVA    EQU    TRUE        ;TRUE if VA3451 instead of VA212
  45. ;
  46. ;
  47. ; SYSTEM CONSTANTS
  48. ;
  49. DIALV    EQU    0162H        ;LOCATION OF DIAL VECTOR IN OVERLAY
  50. DISCV    EQU    0165H        ;LOCATION OF DISCONNECT VECTOR IN OVERLAY
  51. DIALOC    EQU    0B00H        ;DIALING CODE GOES HERE
  52. ;
  53. ;
  54. ; MEX service processor stuff ... MEX supports an overlay service
  55. ; processor, located at 0D00H (and maintained at this address from
  56. ; version to version).  If your overlay needs to call BDOS for any
  57. ; reason, it should call MEX instead; function calls below about
  58. ; 240 are simply passed on to the BDOS (console and list I/O calls
  59. ; are specially handled to allow modem port queueing, which is why
  60. ; you should call MEX instead of BDOS).  MEX uses function calls
  61. ; above about 244 for special overlay services (described below).
  62. ;
  63. ; Some sophisticated overlays may need to do file I/O; if so, use
  64. ; the PARSFN MEX call with a pointer to the FCB in DE to parse out
  65. ; the name.  This FCB should support a spare byte immediately pre-
  66. ; ceeding the actual FCB (to contain user # information).  If you've
  67. ; used MEX-10 for input instead of BDOS-10 (or you're parsing part
  68. ; of a SET command line that's already been input), then MEX will
  69. ; take care of DU specs, and set up the FCB accordingly.  There-
  70. ; after all file I/O calls done through the MEX service processor
  71. ; will handle drive and user with no further effort necessary on
  72. ; the part of the programmer.
  73. ;
  74. MEX    EQU    0D00H        ;address of the service processor
  75. INMDM    EQU    255        ;get char from port to A, CY=no more in 100 ms
  76. TIMER    EQU    254        ;delay 100ms * reg B
  77. TMDINP    EQU    253        ;B=# secs to wait for char, cy=no char
  78. CHEKCC    EQU    252        ;check for ^C from KBD, Z=present
  79. SNDRDY    EQU    251        ;test for modem-send ready
  80. RCVRDY    EQU    250        ;test for modem-receive ready
  81. SNDCHR    EQU    249        ;send a character to the modem (after sndrdy)
  82. RCVCHR    EQU    248        ;recv a char from modem (after rcvrdy)
  83. LOOKUP    EQU    247        ;table search: see CMDTBL comments for info
  84. PARSFN    EQU    246        ;parse filename from input stream
  85. BDPARS    EQU    245        ;parse baud-rate from input stream
  86. SBLANK    EQU    244        ;scan input stream to next non-blank
  87. EVALA    EQU    243        ;evaluate numeric from input stream
  88. LKAHED    EQU    242        ;get nxt char w/o removing from input
  89. GNC    EQU    241        ;get char from input, cy=1 if none
  90. ILP    EQU    240        ;inline print
  91. DECOUT    EQU    239        ;decimal output
  92. PRBAUD    EQU    238        ;print baud rate
  93. ;
  94. ;
  95. CONOUT    EQU    2        ;simulated BDOS function 2: console char out
  96. PRINT    EQU    9        ;simulated BDOS function 9: print string
  97. INBUF    EQU    10        ;input buffer, same structure as BDOS 10
  98. ;
  99. ;
  100. CR    EQU    13
  101. LF    EQU    10
  102. ;
  103. ;
  104.     ORG    DIALV        ;OVERLAY THE DIALING VECTOR
  105.     JMP    DIAL
  106. ;    
  107. ;
  108. ; This is the DIAL routine called by MEX to dial a digit. The digit
  109. ; to be dialed is passed in the A register.  Note that two special
  110. ; codes must be intercepted as non-digits: 254 (start dial sequence)
  111. ; and 255 (end-dial sequence).  Mex will always call DIAL with 254
  112. ; in the accumulator prior to dialing a number.  Mex will also call
  113. ; dial with 255 in A as an indication that dialing is complete. Thus,
  114. ; the overlay may use these values to "block" the number, holding it
  115. ; in a buffer until it is completely assembled (in fact, that's the
  116. ; scheme employed here for the Racal Vadic).
  117. ;
  118. ; After the 254-start-dial sequence, MEX will call the overlay with
  119. ; digits, one-at-a-time.  MEX will make no assumptions about the dig-
  120. ; its, and will send each to the DIAL routine un-inspected (some modems,
  121. ; like the Smartmodem, allow special non-numeric characters in the
  122. ; phone number, and MEX may make no assumptions about these).
  123. ;
  124. ; After receiving the end-dial sequence (255) the overlay must take
  125. ; whatever end-of-dial actions are necessary *including* waiting for
  126. ; carrier at the distant end.  The overlay should monitor the keyboard
  127. ; during this wait (using the MEX keystat service call), and return
  128. ; an exit code to MEX in the A register, as follows:
  129. ;
  130. ;    0 - Carrier detected, connection established
  131. ;    1 - Far end busy (only for modems that can detect this condition)
  132. ;    2 - No answer (or timed out waiting for modem response)
  133. ;    3 - Keyboard abort (^C only: all others should be ignored)
  134. ;    4 - Error reported by modem
  135. ;
  136. ; <No other codes should be returned after an end-dial sequence>
  137. ;
  138. ; The overlay should not loop forever in the carrier-wait routine, but
  139. ; instead use either the overlay timer vector, or the INMDMV (timed 100
  140. ; ms character wait) service call routine.
  141. ;
  142. ; The DIAL routine is free to use any of the registers, but must return
  143. ; the above code after an end-dial sequence
  144. ;
  145.     ORG    DIALOC
  146. ;
  147. DIAL:    LHLD    DIALPT        ;FETCH POINTER
  148.     CPI    254        ;START DIAL?
  149.     JZ    STDIAL        ;JUMP IF SO
  150.     CPI    255        ;END DIAL?
  151.     JZ    ENDIAL        ;JUMP IF SO
  152. ;
  153. ; Not start or end sequence, must be a digit to be sent to the modem
  154. ;
  155.     MOV    M,A        ;PUT CHAR IN BUFFER
  156.     INX    H        ;ADVANCE POINTER
  157.     SHLD    DIALPT        ;STUFF PNTR
  158.     RET            ;ALL DONE
  159. ;
  160. ; Here on a start-dial sequence
  161. ;
  162. STDIAL:    LXI    H,DIALBF    ;SET UP BUFFER POINTER
  163.     SHLD    DIALPT
  164.     RET
  165. ;
  166. ; Here on an end-dial sequence
  167. ;
  168. ENDIAL:
  169.     MVI    M,0        ; Terminate phone number string
  170. CLEAR:
  171.     MVI    C,INMDM        ; Clean out the data buffer in usart
  172.     CALL    MEX
  173.     JNC    CLEAR        ; Get all available
  174.     LXI    H,WAKEUP    ; Get modem's attention
  175.     CALL    RVSEND
  176.     CALL    LFWAIT        ; First thing after ^E,<cr>
  177.     RNZ            ; Return if time out
  178.     CALL    LFWAIT        ; After "HELLO..."
  179.     RNZ            ; Return if time out
  180.     LXI    H,DCMD        ; Send "dial" command to modem
  181.     CALL    RVSEND
  182.     CALL    SENDCR        ; Terminate dial command
  183.     CALL    LFWAIT        ; Wait for "NUMBER?" prompt
  184.     RNZ            ; Return if not normal return from LFWAIT
  185.     LXI    H,DIALBF    ; Point to number
  186.     CALL    RVSEND        ; Send it to modem
  187.     CALL    SENDCR        ; Send <cr> to terminate phone number
  188.      IF    OLDVA
  189.     CALL    DELAY        ; .5 second wait if VA3400
  190.      ENDIF
  191.     CALL    SENDCR        ; Send second <cr> to initiate dialing
  192.     RNZ
  193. ;
  194. ; Here starts the main loop waiting for messages from the modem
  195. ;  and interpreting them.  Some are just passed to the console
  196. ;  and others trigger a specific action.
  197. ;
  198. DLOOP:
  199.     LXI    H,RESPBF    ; Point to response buffer
  200.     MVI    C,255        ; Long wait here
  201.     CALL    CATCHR        ; Catch response from modem
  202.     ORA    A        ; Zero return code ?
  203.     JNZ    IDLE        ; No, disconnect and return error code
  204.     MOV    A,B        ; Get character count from CATCHR
  205.     ORA    A        ; Hope it isn't zero
  206.     JZ    DLOOP        ; If it is, then ignore this response
  207.     LXI    H,RESPBF    ; Point to string from modem
  208.     LXI    D,RSPTBL    ; Point to valid response table
  209.     CALL    COMPR        ; Find out which response we got
  210.     MOV    A,B        ; Get return value
  211.     CPI    255        ; No response match
  212.     JNZ    DIAL05
  213. ERRET:
  214.     MVI    A,4        ; Error return to MEX
  215.     JMP    IDLE        ; Disconnect and return error code
  216. DIAL05:
  217.     CPI    3        ; Failed call ?
  218.     JNZ    DIAL06        ; Say so and error return
  219.      IF    OLDVA
  220.     MVI    A,2
  221.     JMP    IDLE
  222.      ENDIF
  223.      IF    NOT OLDVA
  224.     JMP    ERRET
  225.      ENDIF
  226. DIAL06:
  227.     CPI    1        ; Dialing message ?
  228.     JNZ    DIAL10
  229.     MVI    C,ILP
  230.     CALL    MEX
  231.     DB    'Dial, ',0
  232.     JMP    DLOOP
  233. DIAL10:
  234.     CPI    2        ; Ringing ?
  235.     JNZ    DIAL15
  236.     MVI    C,ILP
  237.     CALL    MEX
  238.     DB    'ring, ',0
  239.     JMP    DLOOP
  240. DIAL15:
  241.     CPI    4        ; Answer tone ?
  242.     JNZ    DIAL20
  243.     MVI    C,ILP
  244.     CALL    MEX
  245.     DB    'answer, ',0
  246.     JMP    DLOOP
  247. DIAL20:
  248.     CPI    5        ; On line ?
  249.     JNZ    DIAL25
  250.     XRA    A        ; Return on line code to MEX
  251.     RET
  252. DIAL25:
  253.     CPI    7        ; Busy ?
  254.     JNZ    DIAL35
  255.     CALL    LFWAIT        ; Busy message has 2 <lf>'s
  256.     RNZ            ; If timeout or user abort
  257. DIAL30:
  258.     MVI    A,1        ; Return busy code to MEX
  259.     JMP    IDLE        ; Disconnect and return error code
  260. DIAL35:
  261.     CPI    8        ; Voice ?
  262.     JNZ    ERRET        ; If there was a match not handled above
  263. ;
  264. ; Handle "VOICE" here
  265. ;
  266.     CALL    SENDCR        ; <cr> ends the "voice" mode
  267.     JMP    DIAL30        ; Abort and return busy code to MEX
  268.  
  269.  
  270. IDLE:
  271. ;
  272. ; Forces modem into idle state by sending "idle" command and
  273. ;  then toggling DTR using the user's DISCV entry.
  274. ; Preserves any return code that may be in register A.
  275. ;
  276.     PUSH    PSW        ; Preserve any return code
  277.      IF    OLDVA
  278.     CALL    LFWAIT
  279.      ENDIF
  280.      IF    NOT OLDVA
  281.     CALL    SENDCR        ; Abort any dialing taking place
  282.      ENDIF
  283.     LXI    H,IDLCMD    ; Send idle message to modem
  284.     CALL    RVSEND
  285.     CALL    DISCV        ; Make sure modem disconnects
  286.     POP    PSW        ; Retrieve return code
  287.     RET
  288.  
  289. SENDCR:
  290. ;
  291. ; Sends a carriage return character to the modem and waits for a
  292. ;  line feed character to be returned.
  293. ;
  294.     LXI    H,CRMSG        ; Send <cr> to modem
  295.     CALL    RVSEND
  296.  
  297. ; Note: execution falls through to LFWAIT
  298. ;
  299. ; Waits til the character from the modem is a line feed
  300. ; Returns the same codes as CATCHR.
  301. ;
  302. LFWAIT:
  303.     MVI    C,10        ; Up to one second for <lf>
  304.     LXI    H,RESPBF
  305.     JMP    CATCHR        ; Use CATCHR to wait for <lf>
  306.  
  307.  
  308.  
  309. ; Table of valid responses from modem
  310. RSPTBL:
  311.     DB    'HE',0        ; "hello..."
  312.     DB    'DI',0        ; "dialing..."
  313.     DB    'RI',0        ; "ringing..."
  314.     DB    'FA',0        ; "failed call"
  315.     DB    'AN',0        ; "answer tone"
  316.     DB    'ON',0        ; "on line"
  317.     DB    'NO',0        ; "no dial tone"
  318.     DB    'BU',0        ; "busy"
  319.     DB    'VO',0        ; "voice"
  320.     DB    0        ; Table terminator
  321.  
  322.  
  323. COMPR:
  324. ; Compares a string of characters in memory to a table of
  325. ;  strings.  Each entry of the table must be terminated by
  326. ;  a zero byte, and the table must be terminated by another
  327. ;  zero byte.
  328. ; Inputs:  HL points to the string to look for
  329. ;       DE points to the table
  330. ; Output:  B contains the number of the table entry that
  331. ;         matches the string, and a 255 if no entry matched.
  332. ;
  333.     MVI    B,0        ; Init index
  334. CMPR05:
  335.     MVI    C,2        ; Number of characters to try to match
  336. CMPR10:
  337.     LDAX    D        ; Fetch char from table
  338.     CMP    M        ; Same as char in string ?
  339.     JNZ    CMPR15        ; Jump if not this entry in table
  340.     INX    H        ; Else, point to next char in string
  341.     INX    D        ;  and next char in table entry
  342.     DCR    C        ; Decrement counter of characters
  343.     JNZ    CMPR10        ; Go check next char
  344.     RET            ; B contains the index of match
  345. CMPR15:
  346.     INR    B        ; Increment index
  347. CMPR20:
  348.     INX    D        ; Next char in table
  349.     LDAX    D        ; Get next char from table
  350.     ORA    A        ; Is it last char in that entry ?
  351.     JNZ    CMPR20        ; No, keep looking
  352.     INX    D        ; Yes, then point to first char of next one
  353.     LDAX    D        ; Now check for end of table
  354.     ORA    A        ; Zero delimits table
  355.     JNZ    CMPR05        ; Go check this table entry
  356.     MVI    B,255        ; No match return code
  357.     RET
  358.  
  359.  
  360. CATCHR:
  361. ;
  362. ; Catch response from modem.
  363. ; Input:  HL pointing to buffer for characters from modem
  364. ;      C  delay allowed before timeout (multiples of 100ms)
  365. ; Output: Buffer contains the string received from modem with
  366. ;       any control characters filtered out.
  367. ;      C  count of characters received before <cr>
  368. ;      A  error code:  0 ==> normal return
  369. ;              2 ==> time out occurred
  370. ;              3 ==> user typed ^C
  371. ;
  372.     MVI    B,0        ; Character counter
  373. CRLOOP:
  374.     MOV    D,C        ; Initialize count down timer
  375. CRL05:
  376.     PUSH    B        ; Save character counter
  377.     PUSH    D        ; Save time out count down
  378.     PUSH    H        ; Save buffer pointer
  379.     MVI    C,CHEKCC    ; See if user typed ^C
  380.     CALL    MEX
  381.     JZ    UABORT        ; If yes, jump to user abort code
  382.     MVI    C,INMDM        ; Else, continue
  383.     CALL    MEX        ; Get char in 1ms if available
  384.     POP    H        ; Restore working registers
  385.     POP    D
  386.     POP    B
  387.     JC    NOCHAR        ; If no char in 1ms, handle it
  388.     ANI    7FH        ; Mask any parity bit
  389.     CPI    LF        ; End of line from modem ?
  390.     JZ    EOL        ; If <lf> then end of line
  391.     CPI    ' '        ; Filter unwanted characters
  392.     JC    CRLOOP        ; Ignore control characters
  393.     CPI    'z'+1        ; Nothing above lower case alpha's
  394.     JNC    CRLOOP
  395.     MOV    M,A        ; Here we have a valid character
  396.     INX    H        ;  so save it and bump pointer
  397.     INR    B        ; Increment character counter also
  398.     JMP    CRLOOP        ; Go get the next one
  399.  
  400. ;
  401. ; Handle no character from modem in 1ms
  402. ;
  403. NOCHAR:
  404.     DCR    D        ; Decrement time out counter
  405.     JNZ    CRL05        ; If not to zero, wait some more
  406.     MOV    C,B        ; Else, return with what we have now
  407.     MVI    A,2        ; Time-out error code
  408.     RET
  409. ;
  410. ; End of line from modem
  411. ;
  412. EOL:
  413.     MOV    C,B        ; Character count
  414.     XRA    A        ; Return zero
  415.     RET
  416. ;
  417. ; User abort from ^C
  418. ;
  419. UABORT:
  420.     CALL    IDLE        ; Force disconnect
  421.     POP    H        ; Since these are still on the stack
  422.     POP    D
  423.     POP    B
  424.     MOV    C,B        ; Count of characters up to now
  425.     MVI    A,3        ; User abort code
  426.     RET
  427.  
  428. ;
  429. ; Sends a string of characters pointed to by HL terminated by zero
  430. ;
  431. RVSEND:
  432.     MVI    C,SNDRDY    ; Get modem send status
  433.     CALL    MEX
  434.     JNZ    RVSEND        ; Wait for modem ready
  435.     MOV    A,M        ; Get character
  436.     INX    H        ; Point to next character
  437.     ORA    A        ; Is this the terminator ?
  438.     RZ            ; If yes, done
  439.     MOV    B,A        ; Pass character in B
  440.     MVI    C,SNDCHR    ; Let MEX send to modem
  441.     CALL    MEX
  442.      IF    OLDVA
  443.     CALL    DELAY        ; .5 second delay here
  444.      ENDIF
  445.     JMP    RVSEND
  446. ;
  447.      IF    OLDVA
  448. ;
  449. ; Provide a 0.5 second delay between command characters to the modem
  450. ;
  451. DELAY:
  452.       PUSH    H    ;Save all registers
  453.       PUSH    D
  454.       PUSH    B
  455.       PUSH    PSW
  456.       MVI    B,5    ;Number of 100 mS intervals
  457.       MVI    C,TIMER
  458.       CALL    MEX
  459.       POP    PSW    ;Restore registers
  460.       POP    B
  461.       POP    D
  462.       POP    H
  463.       RET
  464. ;
  465.      ENDIF
  466. ;
  467. ; DATA AREA
  468. ;
  469. WAKEUP:    DB    'E'-40H,CR,0    ; String to wake up modem
  470. IDLCMD:    DB    'I',CR,0    ; Idle command
  471. DCMD:    DB    'D',0        ; Dial command to modem
  472. CRMSG:    DB    CR,0        ; Note, this is end of DCMD
  473. RESPBF:    DS    20        ; Response from modem
  474. DIALBF:    DS    30        ; Phone number buffer
  475. DIALPT:    DS    2        ;DIAL POSITION POINTER
  476. ;
  477.     END
  478.