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 / BEEHIVE / COMMS / MEX4BEE.ARC / MXOBEE15.ASM < prev    next >
Assembly Source File  |  1990-09-20  |  40KB  |  1,441 lines

  1. ;    Title    'MEX114 overlay for the Microbee version 1.51'
  2.     maclib    z80
  3.  
  4. REV    equ    15        ; overlay revision number
  5.  
  6. ;MEX114 Microbee Overlay
  7. ;  Version 1.0: May 31, 1986 adapted from PMMI overlay v2.2 by George Hansper
  8. ;     "    1.1: June 21, 1986 revised by G.H. & Julian Loke
  9. ;     "    1.2: 86.08.23 auto-dial added, rewrote I/O - G.H.
  10. ;     "    1.3: 86.08.25 fixed small bug - G.H.
  11. ;     "    1.4: 87.03.24 Made dialling TELCOM compatible, modified I/O - G.H.
  12. ;     "    1.5: 87.07.11 Auto-setting of port-B interrupt vect, - G.H.
  13. ;     "       1.51:87.08.20 Auto clearing of buffer during disconnect - S.C.
  14. ;             Modified to assemble with DRI MAC.COM
  15. ;             Added ESC-@ send break
  16. ;             Made interrupt setting work on cassete out bit
  17. ;             instead of speaker bit to stop the thing clicking
  18. ;             Increased maximum wait allowed for carrier
  19. ;             Made modem go OFFLINE if dialling aborted
  20. ;             Added optional fast dialling
  21. ;
  22. ;------------------------ C O P Y R I G H T ---------------------------
  23. ; This overlay is hereby placed in the public domain.
  24. ; Any persons wishing to use the serial I/O routines contained herein
  25. ; for any purposes (commercial or otherwise), feel free to do so.
  26. ; This does not extend to the MEX set of programs, which have their
  27. ; own copyright
  28. ;----------------------------------------------------------------------
  29.  
  30. ;---------------- Suggested Installation Procedure: -------------------
  31. ;   You will need:
  32. ;    (this overlay)
  33. ;    the MEX set of programs (Sigm 218, MEX114 is in Sigm 214)
  34. ;    Z80.LIB
  35. ;    MAC.COM (dri)
  36. ;    MLOAD.COM
  37. ;
  38. ;   First, edit this overlay to suit your system:
  39. ;    if you have a 2MHz bee:
  40. ;      include the instuctions noted after the "receive:" label
  41. ;      modify each entry to the "setbds:"/"setbdt:" table
  42. ;      as per this example -
  43. ;        db    '30',0b0h,64,1
  44. ;        db    '45',0b0h,43,2
  45. ;      becomes:
  46. ;        db    '30',0b0h,32,1
  47. ;        db    '45',0b0h,21,2
  48. ;      (all delay constants are halved)
  49. ;      except the delay for 75b, 0 becomes 128
  50. ;      (do not change the special handler at the end of rec$interrupt)
  51. ;      NOTE: the maximum baud rate attainable is now 9600 (not 19200)
  52. ;    endif
  53. ;    if your modem supports TELCOM-type dialling:
  54. ;      set DIALON to DTR
  55. ;    else
  56. ;      set DIALON to 0  (as supplied)
  57. ;    endif
  58. ;    you may wish to edit the CLREOS routine    if your console does not
  59. ;      use ^W for clear to end-of-screen
  60. ;
  61. ;   To construct a working copy of MEX, I used the following sequence:
  62. ;
  63. ;    MAC MXOBEE15 $PZ -S
  64. ;    MLOAD MEX=MEX,MXOBEE15
  65. ;----------------------------------------------------------------------
  66.  
  67. ;------------------------  User Notes  --------------------------------
  68. ;   This overlay implements a full-featured MEX.  Please refer to
  69. ;    the MEX commands 'HELP','?' and 'SET ?' for user instructions.
  70. ;   It is intended for use on non-smart modems, so the auto-baud rate
  71. ;    selection only affects MEX, and not your modem (ie change your
  72. ;    modem mode manually). The same goes for the 'SET FLIP' command.
  73. ;    Some extra signals are required when dialling, (see below) but
  74. ;    these are available on most non-smart modems.
  75. ;   One non-standard variation has been included: specifying a baud-rate
  76. ;    of 110 in the PHONE library will actually set send=75, receive=1200
  77. ;    when the DIAL or CALL commands are used.
  78. ;   Overlay version 1.5 does NOT need to be 'customized' to suit your
  79. ;    operating system. (This was done by setting INTVCB in version 1.4
  80. ;    and earlier.)
  81. ;----------------------------------------------------------------------
  82.  
  83. ;------------------------ Notes on Auto-Dialling ----------------------
  84. ; The mode of dialling is configured by the label DIALON. In overlay version
  85. ; 1.5 this is stored at memory location 1B4h, (so you can easily change it)
  86. ; DIALON may be set to DTR or 0.
  87. ;
  88. ; In addition, the following two signals are essential:
  89. ;    1. the CTS input (RS232 pin 5) on the 'Bee is used to indicate the
  90. ;    presence of carrier (HIGH=carrier present)
  91. ;    2. the CLK output (RS232 pin 24) on the 'Bee is used to place the
  92. ;    the modem ONLINE ('off-hook') and OFFLINE ('on-hook')
  93. ;    (HIGH=ONLINE)
  94. ;
  95. ; Method 1:
  96. ;        DIALON    =    0        ; (1B4h)=0
  97. ;    The dialling pulses are simulated by switching the modem ONLINE
  98. ;    and OFFLINE in the appropriate sequence.
  99. ;    The dialling pulses will appear on pin 24 as follows:
  100. ;        DTR    pin 24 CLK        PHONE LINE    equivalent to
  101. ;         0        low              on-hook        'break'
  102. ;         1        high             off-hook       'make'
  103. ;    Dialling in this manner does NOT meet the Telecom specification
  104. ;    on dialling, but it works.
  105. ;    The RS232 connector should be wired (more-or-less):
  106. ;           BEE                          MODEM
  107. ;    I/O       Signal       Pin    Pin       Signal        I/O
  108. ;    Out        TDX          2 ---- 2         TDX          In
  109. ;    In         RDX          3 ---- 3         RDX          Out
  110. ;    +5V        RTS          4 ---- 4         RTS          In
  111. ;    In  CTS (Used for DCD)  5 ---- 8 DCD (carrier detect) Out
  112. ;     -         GND          7 ---- 7         GND           -
  113. ;    Out CLK (Used for DTR) 24 ---- 20  DTR (on/off hook)  In
  114. ;
  115. ;    Make sure your modem does use the DCD and DTR pins as above.
  116. ;    If not, use whatever pins perform these functions.
  117. ;
  118. ;Method 2:
  119. ;        DIALON    =    DTR        ; (1B4h)=4
  120. ;    This method of dialling is equivalent to that used by TELCOM.
  121. ;    The DTR output (pin 24 CLK) will be placed in a high
  122. ;    resistance (Hi-Z) state for the duration of dialling.
  123. ;    The hardware should detect this condition and place the modem
  124. ;    in an 'off normal' state.
  125. ;    The pulses will appear on the RSOUT output (pin 2 TDX):
  126. ;        pin 24 CLK     RSOUT  pin 2 TDX      PHONE LINE
  127. ;           Hi-Z          1       low           'make'
  128. ;           Hi-Z          0       high          'break'
  129. ;    Except while dialling, CLK and CTS are used as described above.
  130. ;----------------------------------------------------------------------
  131.  
  132.  
  133.  
  134. ; Equates used only by Microbee routines grouped together here.
  135. ;
  136. ; Z80 PIO equates:
  137. CTLA    equ    1        ;PIO port A control
  138. DATAB    equ    2        ; "   "   B data
  139. CTLB    equ    3        ; "   "   " control
  140. DTR    equ    4        ;DTR  output on bit 2  (PIO port B)
  141. RSOUT    equ    20h        ;RS-232  "   "   "  5
  142. CTS    equ    8        ;CTS   input "   "  3
  143. RSIN    equ    10h        ;RS-232  "   "   "  4
  144. CASOUT    equ    02h        ;Cassette output on bit 1 (only used for
  145.                 ;setting up the interrupts
  146.  
  147. XOFF    equ    'S'-40h
  148. XON    equ    'Q'-40h
  149.  
  150. ; Misc equates
  151. NO    equ    0
  152. YES    equ    0FFh
  153. TPA    equ    100h
  154. CR    equ    13
  155. LF    equ    10
  156. BS    equ    8
  157. TAB    equ    9
  158. ESC    equ    27
  159.  
  160.  
  161.  
  162.     ;User options... the following equates will change the character
  163.     ;of your overlay.
  164.  
  165.  
  166. DIALON    equ    0    ;DTR    ;bit used for 'off-normal' (dialling) state
  167. FAST$DIAL equ    YES    ;YES = dial at twice normal rate
  168. ; MEX function codes:
  169. ;
  170. MEX    equ    0D00h        ;address of the service processor
  171. INMDM    equ    255        ;get char from port to A, CY=no more in 100 ms
  172. TIMER    equ    254        ;delay 100ms * reg B
  173. TMDINP    equ    253        ;B=# secs to wait for char, cy=no char
  174. CHEKCC    equ    252        ;check for ^C from KBD, Z=present
  175. SNDRDY    equ    251        ;test for modem-send ready
  176. RCVRDY    equ    250        ;test for modem-receive ready
  177. SNDCHR    equ    249        ;send a character to the modem (after sndrdy)
  178. RCVCHR    equ    248        ;recv a char from modem (after rcvrdy)
  179. LOOKUP    equ    247        ;table search: see CMDTBL comments for info
  180. PARSFN    equ    246        ;parse filename from input stream
  181. BDPARS    equ    245        ;parse baud-rate from input stream
  182. SBLANK    equ    244        ;scan input stream to next non-blank
  183. EVALA    equ    243        ;evaluate numeric from input stream => hl
  184. LKAHED    equ    242        ;get nxt char w/o removing from input
  185. GNC    equ    241        ;get char from input, cy=1 if none
  186. ILP    equ    240        ;inline print
  187. DECOUT    equ    239        ;decimal output
  188. PRBAUD    equ    238        ;print baud rate
  189. ;
  190. CONOUT    equ    2        ;simulated BDOS function 2: console char out
  191. PRINT    equ    9        ;simulated BDOS function 9: print string
  192. INBUF    equ    10        ;input buffer, same structure as BDOS 10
  193.  
  194.  
  195.     org    TPA        ;we begin
  196.     ds    3        ;MEX has a JMP START here
  197.  
  198. ; The following variables are located at the beginning of the program
  199. ; to facilitate modification without the need of re-assembly. They will
  200. ; be moved in MEX 2.0.
  201. ;
  202. PMODEM:    db    NO        ;yes=PMMI modem \ / These 2 locations are not
  203. SMODEM:    db    NO        ;yes=Smartmodem / \ referenced by MEX
  204. TPULSE:    db    'P'        ;T=touch, P=pulse (not referenced by MEX)
  205. CLOCK:    db    34        ;clock speed x .1, up to 25.5 mhz.
  206. MSPEED:    db    5        ;sets display time for sending a file
  207.                 ;0=110    1=300  2=450  3=600  4=710
  208.                 ;5=1200 6=2400 7=4800 8=9600 9=19200
  209. BYTDLY:    db    0        ;default time to send character in
  210.                 ;terminal mode file transfer (0-9)
  211.                 ;0=0 delay, 1=10 ms, 5=50 ms, 9=90 ms
  212. CRDLY:    db    5        ;end-of-line delay after CRLF in terminal
  213.                 ;mode file transfer for slow BBS systems
  214.                 ;0=0 delay, 1=100 ms, 5=500 ms, 9=900 ms
  215. COLUMS:    db    5        ;number of directory columns
  216. SETFL:    db    YES        ;yes=user-defined SET command
  217. SCRTST:    db    YES        ;yes=if home cursor and clear screen
  218.                 ;routine at CLRSCRN
  219.     db    0        ;was once ACKNAK, now spare
  220. BAKFLG:    db    NO        ;yes=make .BAK file
  221. CRCDFL:    db    YES        ;yes=default to CRC checking
  222.                 ;no=default to Checksum checking
  223. TOGCRC:    db    YES        ;yes=allow toggling of Checksum to CRC
  224. CVTBS:    db    NO        ;yes=convert backspace to rub
  225. TOGLBK:    db    YES        ;yes=allow toggling of bksp to rub
  226. ADDLF:    db    NO        ;no=no LF after CR to send file in
  227.                 ;terminal mode (added by remote echo)
  228. TOGLF:    db    YES        ;yes=allow toggling of LF after CR
  229. TRNLOG:    db    NO        ;yes=allow transmission of logon
  230.                 ;write logon sequence at location LOGON
  231. SAVCCP:    db    NO        ;yes=do not overwrite CCP
  232. LOCNXT:    db    NO        ;yes=local cmd if EXTCHR precedes
  233.                 ;no=not local cmd if EXTCHR precedes
  234. TOGLOC:    db    YES        ;yes=allow toggling of LOCNXTCHR
  235. LSTTST:    db    YES        ;yes=allow toggling of printer on/off
  236.                 ;in terminal mode. Set to no if using
  237.                 ;the printer port for the modem
  238. XOFTST:    db    YES        ;yes=allow testing of XOFF from remote
  239.                 ;while sending a file in terminal mode
  240. XONWT:    db    NO        ;yes=wait for XON after sending CR while
  241.                 ;transmitting a file in terminal mode    
  242. TOGXOF:    db    YES        ;yes=allow toggling of XOFF testing
  243. IGNCTL:    db    YES        ;yes=do not send control characters
  244.                 ;above CTL-M to CRT in terminal mode
  245.                 ;no=send any incoming CTL-char to CRT
  246. EXTRA1:    db    0        ;for future expansion
  247. EXTRA2:    db    0        ;for future expansion
  248. BRKCHR:    db    '@'-40h        ;^@ = Send a 300 ms. break tone
  249. NOCONN:    db    'N'-40h        ;^N = Disconnect from phone line
  250. LOGCHR:    db    'L'-40h        ;^L = Send logon
  251. LSTCHR:    db    'P'-40h        ;^P = Toggle printer
  252. UNSVCH:    db    'R'-40h        ;^R = Close input text buffer
  253. TRNCHR:    db    'T'-40h        ;^T = Transmit file to remote
  254. SAVCHR:    db    'Y'-40h        ;^Y = Open input text buffer
  255. EXTCHR:    db    '^'-40h        ;^^ = Send next character
  256.     db    0        ;not used
  257.     db    0        ; "   "
  258. ;
  259. ; Low-level modem I/O routines: this will be replaced with
  260. ; a jump table in MEX 2.0 (you can insert jumps here to longer
  261. ; routines if you'd like ... I'd recommend NOT putting part of
  262. ; a routine in this area, then jumping to the rest of the routine
  263. ; in the non-fixed area; that will complicate the 2.0 conversion)
  264. ;
  265. INCTL1:    ret            ;in modem control port, 10 bytes
  266.     db    0,0,0,0,0,0,0,0,0
  267.  
  268. OTDATA:    jmp    oDATA
  269.     db    0,0,0,0,0,0,0
  270.  
  271. INPORT:    jmp    iDATA
  272.     db    0,0,0,0,0,0,0
  273.  
  274. ; Bit-test routines. These routines were used to mask & test the status of
  275. ; the byte returned by INTCTL1. The MASKx routines now also get the required
  276. ; status, as well as masking it - G.H.
  277. ;
  278. MASKR:    jmp    rec$stat    ;bit to test for receive ready
  279. TESTR:    cpi    1        ;value of receive bit when ready
  280.     ret
  281. MASKS:    jmp    send$stat    ;bit to test for send ready
  282. TESTS:    cpi    CTS        ;value of send bit when ready
  283.     ret
  284.  
  285. ; Save space by using these 12 spare bytes for send$stat
  286. ; send$stat is not called until there is data to output (eg key pressed)
  287. send$stat:
  288.     call    ONLINE        ; Set DTR before sending data
  289.     mvi    a,CTS
  290. ;    in    DATAB        ; modified so that terminal doesn't
  291.                 ; hang if there is no carrier (this
  292.                 ; condition could prevent disconnect)
  293.     ani    CTS
  294.     ret
  295.  
  296.     ds    12-($-send$stat) ; unused but necessary (MDM compat)
  297.  
  298.  
  299. ; Special modem function jump vectors
  300.  
  301. LOGON:    ds    2        ;needed for MDM compat, not ref'd by MEX
  302. DIALV:    jmp    PDIAL        ;dial digit in A
  303. DISCV:    jmp    OFFLINE        ;disconnect the modem
  304. GOODBV:    jmp    RESTORE        ;called before exit to CP/M
  305. INMODV:    jmp    INITMOD        ;initialization. Called at cold-start
  306. NEWBDV:    jmp    PBAUD        ;set baud rate
  307. NOPARV:    jmp    NOPAR        ;set modem for no-parity
  308. PARITV:    jmp    PARITY        ;set modem parity
  309. SETUPV:    jmp    SETCMD        ;SET cmd: jump to a RET if you don't write SET
  310. SPMENV:    ds    3        ;not used with MEX
  311. VERSNV:    jmp    SYSVER        ;Overlay's voice in the sign-on message
  312. BREAKV:    jmp    PBREAK        ;send a break
  313.  
  314. ; MDM compatible routines:
  315.  
  316. ILPRTV:    ds    3        ;replace with MEX function 9
  317. INBUFV:    ds    3        ;replace with MEX function 10
  318. ILCMPV:    ds    3        ;replace with table lookup funct. 247
  319. INMDMV:    ds    3        ;replace with MEX function 255
  320. NXSCRV:    ds    3        ;not supported by MEX (returns w/no action)
  321. TIMERV:    ds    3        ;replace with MEX function 254
  322. ;
  323. ;
  324. ; Clear/screen and clear/end-of-screen. Each routine must use the
  325. ; full 9 bytes alloted (may be padded with nulls).
  326. ;
  327. CLREOS:
  328.     call    ILPRT        ;Clear to end of screen code
  329.     db    01bh,'Y',0
  330.     ret
  331.     ds    2
  332.  
  333. CLS:    mvi    a,'Z'-40h    ;CLS code
  334.     jmp    TYPE
  335. ;    ds    4
  336.  
  337. ;------------------------------------------------------------
  338. ;
  339. ;    *** END OF FIXED FORMAT AREA ***
  340. ;
  341. ;------------------------------------------------------------
  342.  
  343. ; Microbee serial I/O routines - Data area
  344. sendflag:    db    0    ; NZ while sending data
  345. xflag:        db    1    ; indicates if automatic XOFF sent. Initialised
  346.                 ; to NZ so that X-ON sent on first logon
  347. baud:        db    10h    ; Receive baud rate (1200 baud)
  348.         db    10h    ; Send baud rate (1200 baud)
  349. ndata:        db    8    ; 8 data bits
  350. npdata:        db    8    ; (ndata) + parity bit (if req)
  351. stopbits:    db    1    ; 1 stop bits
  352. bparity:    db    1    ; 1=none, 2=odd, else even 
  353. rs$rptr:    dw    0    ; read pointer into buffer
  354. rs$wptr:    dw    0    ; write   "     "     "
  355. oldvcb:        dw    0    ; Storage for old interrupt vector
  356. statbyte:    db    0    ; counter for 0's returned by rec$stat after 1
  357. ans$time:    db    30    ; timeout for answer in seconds (max. 50 secs)
  358. dial$abort:    db    0    ; flag for ^C during dial
  359. dialtype:    db    DIALON    ; Dialling is hook-toggle if 0, TELCOM if DTR
  360.  
  361. ;Simulated status ports:
  362.  
  363. ; Before MEX will start any (terminal) send/rec, it must first read at least
  364. ;    3 rec-not-ready states.
  365. ; Furthermore, if more than ~280h (D4h chars) consecutive rec-ready states
  366. ;    are read, MEX will only display every 3rd byte read from the buffer
  367. ;    unless two not-ready states are given for every ready state!!!
  368. ; I have noted that once a char-ready state is sent, iDATA is called, but
  369. ;    MASKr (ie rec$stat) is called twice before the character is actually
  370. ;    displayed. The buffer is not read again (even if rec$stat returns
  371. ;    ready states) until the third time rec$stat is called.
  372. ; In summary, for efficient, reliable operation  rec$stat must return two
  373. ;    not-ready states straight after returning a ready-state
  374. ; MDM730 does not suffer from this peculiarity
  375. ;
  376. rec$stat:            ; Check if data in buffer
  377.     lda    statbyte    ; 1=char-ready, 0=not-ready
  378.     ora    a
  379.     jrnz    rstat1
  380.     push    b
  381.     push    h
  382.     call    bufftest    ; Test for data in buffer, NZ=yes
  383.     pop    h
  384.     pop    b
  385.     rz            ; Z = buffer empty, return A=0
  386.     mvi    a,2        ; return ready-state
  387.     sta    statbyte
  388.     dcr    a        ; data in buffer, return A=1
  389.     ret
  390.  
  391. rstat1:    dcr    a
  392.     sta    statbyte    ; return not-ready
  393.     xra    a
  394.     ret
  395.     
  396. ;  iDATA also handles the internal automatic XOFF/XON on impending
  397. ;  buffer overflow
  398. iDATA:                ;in modem data port
  399.     push    b        ;Reads input buffer 
  400.     push    h
  401.     call    bufftest    ; data in buffer? returns BC=(rs$rptr),HL=diff
  402.     jrz    iDATA2        ; 0=empty, 1=one byte ... -1=full
  403.     mvi    a,0FEh        ; Unused bits of rs$rptr, rs$wptr
  404.     ora    h
  405.     inr    a
  406.     jrnz    iDATA1
  407.     mov    a,l
  408.     adi    20h
  409.     cc    iDATAF        ; Buffer nearly full - PANIC!!
  410. iDATA1:    inx    b
  411.     res    1,b        ; Determines buffer size (200H)
  412.     lxi    h,rs$buff
  413.     dad    b
  414.     mov    a,m        ; first read buffer
  415.     sbcd    rs$rptr        ; THEN update rptr
  416.     dcr    h        ; Set NZ flag
  417. iDATA2:    pop    h
  418.     pop    b
  419.     ret
  420.  
  421. bufftest:            ; Test for data in buffer, NZ=yes
  422.     lhld    rs$wptr
  423.     lbcd    rs$rptr
  424.     xra    a
  425.     dsbc    bc
  426.     rnz            ; Yes, data in buffer, return NZ
  427.     ; Buffer empty
  428.     call    rec$reti    ; ei, in case disabled by buffer overflow
  429.     lda    xflag
  430.     ora    a
  431.     rz
  432.     mvi    a,XON
  433.     call    oDATA        ; send XON if remote was XOFFed
  434.     xra    a        ; Set Z flag
  435.     sta    xflag
  436.     ret
  437.  
  438. iDATAF:    lda    xflag        ; Buffer (nearly) full
  439.     ora    a
  440.     rnz            ; XOFF already sent
  441.     dcr    a
  442.     sta    xflag
  443.     mvi    a,XOFF
  444. ;    jmp    oDATA        ; Send XOFF character
  445.  
  446. ; Serial I/O routine
  447. ;    register assignments: A=G.P.
  448. ;    Normal register set:
  449. ;        B = send delay count    C = receive data count
  450. ;            never 1 for rec-only    1..n if receiving, 0 if rec idle
  451. ;                        -1 if waiting for stop-bit
  452. ;        D = send delay        E = data count, send
  453. ;        H = send data        L = send data
  454. ;            DE,HL not used on receive-only
  455. ;
  456. ;    Alternate register set:
  457. ;            not used on send-only
  458. ;        B'= rec delay count    C'= rec delay
  459. ;        D'= rec data        E'= RSIN
  460. ;                    L'= (npdata) for adjustment at write
  461.  
  462. oDATA:                ;out modem data port
  463. ;    out    9        ;turn off wait cycling (not needed on all bees)
  464.     push    psw        ;  & let CPU run at full speed 
  465.     push    b        ;  wait-ing initiated by writing to screen RAM
  466.     exx
  467.     push    b
  468.     push    d
  469.     push    h
  470.     exx
  471.     push    d
  472.     push    h
  473.     mov    c,a        ;store character in C
  474.     lda    ndata        ;number of data bits (send)
  475.     mov    b,a        ;store it in b
  476.     mov    e,a        ;and e
  477.     mvi    a,1
  478. send$1:    rrcr    c        ;shift data into carry in one direction and
  479.     ralr    l        ;out the other (reverse the order of bits)
  480.     add    a        ; generate mask
  481.     djnz    send$1
  482.     dcr    a        ; a = mask
  483.     ana    l        ; mask send data
  484.     jpe    send$2
  485.     cmc            ; carry = parity bit
  486. send$2: lda    bparity
  487.     dcr    a
  488.     jrz    send$nopar
  489.     dcr    a
  490.     jrnz    send$pe
  491.     cmc
  492. send$pe:
  493.     dadc    hl        ; add parity bit to send data
  494.     inr    e        ; +1 to data count for parity
  495. send$nopar:
  496.     mvi    a,13
  497.     sub    e        ; no of data bits + parity (if req)
  498.     mov    b,a
  499. send$3:    dad    h
  500.     inx    h
  501.     djnz    send$3
  502.     lda    stopbits
  503.     add    e        ; +stopbits
  504.     inr    a        ; +1 since e=1 -> finished sending
  505.     mov    e,a        ; send data counter
  506.     mov    c,b        ; rec data count = 0 ie rec is idle
  507.     lda    baud+1        ; send delay
  508.     mov    d,a        ; send delay (for resetting)
  509.     adi    20        ; this will have more effect on the higher
  510.                 ; baud rates
  511.     mov    b,a        
  512.     djnz    $-1        ; - these three instructions were added to give
  513.     mov    b,d        ; - an effectively longer stop pulse (gave
  514.                 ; problems with only one stop bit at 1200
  515.                 ; baud on file transfers)
  516.     mov    b,d        ; send delay counter
  517.     mvi    a,DTR
  518.     sta    sendflag    ; NZ = sending
  519.     out    DATAB        ; output start bit (high)
  520.     jmp    receive
  521.  
  522. ; Timing loop
  523. ; Ideally, 176 clock cycles long
  524. ; Instructions used purely for timing labled '+'
  525.  
  526. rec$write:            ; receive + 18 cycles
  527.     exx            ;  4\
  528.     mvi    a,9        ;  7 \
  529.     djnz    rec$weq        ;  8  |    13
  530.     sub    l        ;  4  |    = 37
  531.     mov    b,a        ;  4 /
  532.     in    DATAB        ; 10/
  533.     jrz    rec$noadj    ;  7\    12
  534.     ana    e        ;  4 \
  535.     sub    e        ;  4  |
  536.     mov    a,d        ;  4  |    =12(9b) =35(8b) =52(7b)
  537. rec$adj: rarr    a        ;  4  |
  538.     djnz    rec$adj        ;  8 /    13
  539.     mov    d,a        ;  4/
  540. rec$noadj: lhld    rs$rptr        ; 16\
  541.     lbcd    rs$wptr        ; 20 \
  542.     inx    b        ;  6  |
  543.     res    1,b        ;  8  |    dictates buffer size (200H)
  544.     xra    a        ;  4  |
  545.     dsbc    bc        ; 15  |
  546.     jrz    rec$full    ;  7  |
  547.     sbcd    rs$wptr        ; 20  |    = 196(ei) =177(no ei)
  548.     dcr    a        ;  4  |        total = 286 (8b, ei)
  549. rec$full: lxi    h,rs$buff    ; 10  |    hl = buffer
  550.     dad    b        ; 11  |
  551.     mov    m,d        ;  7  |        d' = data for receive
  552.     exx            ;  4  |
  553.     mov    c,a        ;  4  |    -1=ei, 0=don't ei
  554.     in    DATAB        ; 10  |
  555.     ani    RSIN        ;  7  |
  556.     add    c        ;  4 /
  557.     cm    rec$ei        ; 10/    17+22
  558. send:
  559.     djnz    send$eq        ;  8\    13    b = delay counter
  560.     dcr    e        ;  4 \        e = data counter
  561.     jrz    send$finish    ;  7  |    12    e=1, finished send, pop HL,DE
  562.     dad    h        ; 11  |
  563.     mov    a,h        ;  4  | total = 63
  564.     ani    RSOUT        ;  7  |
  565.     ori    DTR        ;  7  |
  566.     out    DATAB        ; 11 /
  567.     mov    b,d        ;  4/    reset delay count
  568. receive:
  569. ;    push    h        ;+11\  2MHz only
  570. ;    dad    h        ;+11 |    "    "
  571. ;    pop    h        ;+10/    "    "     (total = 32)
  572.  
  573.     mov    a,c        ;  4\
  574.     dcr    a        ;  4 |        c = data counter for receive
  575.     jz    rec$write    ; 10 |        c=1, last bit
  576.     inr    a        ;  4 |
  577.     jm    rec$test    ; 10 |        c=-1, wait for RSIN to go low
  578.     jrz    rec$idle    ;  7 |    12    c=0, idle
  579.     exx            ;  4 |
  580.     djnz    rec$eq        ;  8 |    13    b'= delay counter (rec)
  581.     in    DATAB        ; 10 |        receive and record data
  582.     ana    e        ;  4 |
  583.     sub    e        ;  4 |    total = 113
  584.     rarr    d        ;  8 |
  585.     mov    b,c        ;  4 |        reset delay counter
  586.     exx            ;  4 |
  587.     dcr    c        ;  4 |        dec data counter
  588.     jr    rec$101        ; 12/    receive + 101
  589.  
  590. rec$idle:            ; receive + 44 cycles
  591.     lda    sendflag    ; 13\    rec is only waiting for send to finish
  592.     ora    a        ;  4 |
  593.     jrz    exit        ;  7 |    12
  594.     nop            ;+ 4 |
  595.  
  596. rec$72:                ; receive + 72
  597.     push    h        ;+11 |
  598.     pop    h        ;+10 |
  599.     nop            ;+ 4 |
  600. rec$97:                ; receive + 97
  601.     nop            ;+ 4 |
  602. rec$101:            ; receive + 101
  603.     jr    send        ; 12/    total = 44 + 69 = 113
  604.  
  605. rec$weq:            ; receive + 42 cycles
  606.     mov    a,m        ;+ 7 \
  607.     mov    a,m        ;+ 7 /
  608. rec$eq:                ; receive + 56 cycles
  609.     exx            ;  4\
  610.     jr    rec$72        ; 12/    receive + 72
  611.  
  612. ; waiting forms a second closed loop, which is run when both sending and
  613. ; receiving have finished, but RSIN is still high. If RSIN remains high for
  614. ; more than 24ms (~2 bits @ 75 baud), an exit without ei will occur
  615. waiting:            ; waiting loop = 79 clk cycles
  616.     dcx    b        ;  6\
  617.     bit    2,b        ;  8 |        bc counts FFFF down to FBFF
  618.     jrz    exit        ;  7/    12    timeout... exit without ei
  619.  
  620. rec$test:            ; receive + 32 cycles
  621.     in    DATAB        ; 10 \
  622.     ani    RSIN        ;  7  |        rec is testing RSIN
  623.     jrnz    rec$high    ;  7  |    12
  624.     mov    c,a        ;  4  |        =0  receive = idle
  625.     call    rec$reti    ;17+18|
  626.     jr    send        ; 12 /    total = 75 + 39 = 113 - 6
  627.     ; Must have c=0 and b<>1 upon return to main loop
  628.  
  629. rec$high:            ; receive + 61 cycles
  630.     lda    sendflag    ; 13\    rec is waiting for input to go low (to
  631.     ora    a        ;  4 |        prevent unwanted interrupt)
  632.     jrz    waiting        ;  7 |    12    execute waiting loop
  633.     jr    rec$97        ; 12/    total = 61 + 36 = receive + 97
  634.  
  635. rec$ei:    inr    c        ;  4\
  636. rec$reti:            ;    |        rec$reti called by rec$stat
  637.     ei            ;  4\|
  638.     reti            ; 14/    'interrupt serviced' signal for PIO
  639.                 ;    (PIO won't re-interrupt till serviced)
  640.  
  641. send$finish:            ; send + 24  (execute once only per send)
  642.     xra    a        ;  4\
  643.     sta    sendflag    ; 13 |
  644.     pop    h        ; 10 |
  645.     pop    d        ; 10 |
  646.     djnz    receive        ; 13/        sets b=FF, always jumps
  647.                 ;    total = 50 + 24 = 63 + 11
  648.  
  649. send$eq:            ; send + 13
  650.     lda    sendflag    ; 13\
  651.     ora    a        ;  4 |
  652.     jz    send$idle    ; 10 |
  653.     mov    a,m        ;+ 7 |
  654.     nop            ;+ 4 |
  655.     jr    receive        ; 12/        total = 13 + 50 = 63
  656.  
  657. send$idle:            ; send + 40
  658.     mvi    b,0FFh        ;  7\    stay on send$eq path
  659.     ora    c        ;  4 |
  660.     jrnz    receive        ;  7/    12    total = 40 + 23 = 63
  661. exit:                ; send + 58
  662.     exx            ;  4\
  663.     pop    h        ; 10 |
  664.     pop    d        ; 10 |
  665.     pop    b        ; 10 | = 68
  666.     exx            ;  4 |
  667.     pop    b        ; 10 |
  668.     pop    psw        ; 10 |
  669.     ret            ; 10/
  670.                 ; send + 126 = receive + 412 (no waiting)
  671.  
  672. rec$interrupt:             ; 19\ cycles to respond to interrupt
  673.     out    9        ; 11 |
  674.     push    psw        ; 11 |
  675.     lda    sendflag    ; 13 | = 68
  676.     ora    a        ;  4 |
  677.     jnz    rec$wsend    ; 10/
  678.     push    b        ; 11\
  679.     mov    b,a        ;  4 |    b = send delay count = 0 (disable send)
  680.     lda    npdata        ; 13 |
  681.     mov    c,a        ;  4 |    c = rec data count
  682.     exx            ;  4 |
  683.     push    b        ; 11 |
  684.     push    d        ; 11 |
  685.     push    h        ; 11 | = 126
  686.     mov    l,a        ;  4 |    l' = (npdata) used in adjusting
  687.     lxi    d,RSIN        ; 10 |    d' = data for rec
  688.     lda    baud        ; 13 | 
  689.     mov    c,a        ;  4 |    c' = rec delay (for resetting counter)
  690.     rar            ;  4 |    a' = c'/2  (carry = 0 from "or a")
  691.     add    c        ;  4 |       = delay x 1.5 for 1st bit
  692.     mov    b,a        ;  4 |    b' = rec delay counter
  693.     exx            ;  4 |
  694.     jnz    receive        ; 10/    rec$interrupt + 194
  695. ; Special handlng of delay=0 (75 baud)
  696.     exx
  697.     mvi    b,128
  698.     exx
  699.     inr    c        ;    read extra data bit at start
  700.     jmp    receive
  701.  
  702. rec$wsend:            ; rec$interrupt + 68 cycles
  703.     lda    npdata        ; 13\
  704.     mov    c,a        ;  4 |    c = rec data counter
  705.     exx            ;  4 |
  706.     mov    l,a        ;  4 |    l' = (npdata) for adjusting
  707.     lxi    d,RSIN        ; 10 |    d' = data for rec
  708.     lda    baud        ; 13 | = 95 
  709.     mov    c,a        ;  4 |    c' = rec delay (for resetting counter)
  710.     rar            ;  4 |    a' = c'/2  (carry = 0 from "or a")
  711.     add    c        ;  4 |       = delay x 1.5 for 1st bit
  712.     mov    b,a        ;  4 |    b' = rec delay counter
  713.     jrz    rec$75        ;  7 |    12
  714.     exx            ;  4 |
  715.     pop    psw        ; 10 |
  716.     ret            ; 10/    rec$interrupt + 163
  717.  
  718. rec$75:    mvi    b,128        ; Special handling for delay=0 (75b)
  719.     exx
  720.     inr    c        ;    read extra data bit at start
  721.     pop    psw
  722.     ret
  723.  
  724. ; Modem initialization.
  725. INITMOD:
  726.     lxi    b,rec$interrupt
  727.     jr    NEWVCB        ; Set (interrupt vector) to bc, save old
  728.  
  729. ; exit routine
  730. RESTORE:
  731.     lbcd    oldvcb
  732. NEWVCB:
  733.     ; saves current (interrupt vector) in (oldvcb),
  734.     ;   loads (interrupt vector) with BC.
  735.     ; Upper half of address in 'I' reg, lower half determined as follows:
  736.     ;   Method: fill a whole memory page with interrupt vectors, so that
  737.     ;    each will execute a different number of 'inc a' instructions.
  738.     ;    The number of 'inc a' instructions executed will reflect the
  739.     ;    setting of the PIO interrupt vector.
  740.  
  741.     push    b
  742.     lxi    d,0BFFh        ; end of 'inc a' series
  743.     lxi    h,0C00h        ; start of table of interrupt vectors
  744.     mvi    b,80h        ; counter
  745.     mvi    a,0C9h        ; 'ret' instruction
  746. VCBFILL:
  747.     stax    d        ; store interrupt routine instruction
  748.     mov    m,e        ; store (vector) lsb
  749.     inx    h
  750.     mov    m,d        ; store (vector) msb
  751.     inx    h
  752.     dcx    d
  753.     mvi    a,3Ch        ; 'inc a' instruction
  754.     djnz    VCBFILL
  755.  
  756.     ; Force an interrupt from port-B, MUST be from port-B, NOT port-A
  757.     mvi    a,03h
  758.     out    CTLA        ; Disable port-A interrupts
  759.  
  760.     in    DATAB
  761.     ani    0FFh-CASOUT    ; Cassette output-bit=0, used to force interrupt
  762.     out    DATAB
  763.     lxi    h,INITTABLE
  764.     lxi    b,CTLB+256* 4
  765.     di            ; wait until we're ready
  766.     outir            ; initialize port-B for interrupt
  767.     im2    
  768.     ori    CASOUT        ; Cassette output-bit=1
  769.     out    DATAB        ;    (generates the interrupt)
  770.     ldai
  771.     mov    d,a        ; save interrupt page
  772.     mvi    a,0Ch        ; set new interrupt page
  773.     stai
  774.     xra    a
  775.     call    init$reti    ; in case of 'unserviced' interrupt (else PIO
  776.                 ;   won't interrupt)
  777.                 ; eg if buffer full, NO 'reti' is executed
  778.     ei            ; let interrupt happen
  779.     hlt            ; wait for interrupt
  780.     di            ; (Note: ei performed by rec$stat->bufftest)
  781.     add    a        ; A reg contains value number of 'inc a'
  782.                 ;  instructions executed
  783.     mov    e,a
  784.     mov    a,d
  785.     stai            ; Restore interrupt page
  786.     outi
  787.     outi            ; Initialize PIO for normal operation
  788.     mvi    a,83h
  789.     out    CTLA        ; Re-enable port-A interrupts
  790.     pop    b
  791.     xchg
  792.     mov    e,m        ; save old (vector) lsb
  793.     mov    m,c        ; store new (vector) lsb
  794.     inx    h
  795.     mov    d,m        ; save old (vector) msb
  796.     mov    m,b        ; store new (vector) msb
  797.     sded    oldvcb        ; store old (vector)
  798. init$reti:
  799.     reti            ; 'interrupt serviced' signal for PIO
  800.  
  801. INITTABLE:            ; Table used to initialize PIO (port B)
  802.         db    0ffh    ; = mmxx1111 set port B mode (control: mm=11)
  803.         db    99h    ; I/O mask: 1=in, 0=out
  804.  
  805.         db    0B7h    ; = eahm0111:   e=1 enable interrupt,
  806.                 ; a=0 OR bits, h=1 bits high, m=1  mask follows
  807.         db    0FFh-CASOUT    ; interrupt mask: 1=ignore, 0=monitor
  808.                 ;^ this was modified by Simeon from being the
  809.                 ;speaker bit.  It is used to set up the ints.
  810.                 ;however it clicked the speaker every time
  811.                 ;the program was initialised
  812.         db    0f7h    ; = eahm0111:   e=1 enable interrupt,
  813.                 ; a=1 AND bits, h=1 bits high, m=1 mask follows
  814.         db    0ffh-RSIN-CTS ; interrupt mask: 1=ignore, 0=monitor
  815.  
  816.  
  817. ; Setup for odd/even parity (called before file-transfer)
  818. PARITY:
  819. ; set no-parity (called after file-transfer)
  820. NOPAR:    ret
  821. ; send-break routine
  822. PBREAK: ;Added by Simeon
  823.     ;Break sends a signal that will cause a framing error at the remote
  824.     ;end (on purpose).  This is used to reset some computers.  This
  825.     ;routine will continue to receive while sending the break.
  826.  
  827.     push    psw
  828.     push    b
  829.     exx
  830.     push    b
  831.     push    d
  832.     push    h
  833.     exx
  834.     push    d
  835.     push    h
  836.     lxi    h,00ffh        ;HL holds the data and stop bits
  837.     mvi    c,0
  838.     mvi    d,00h        ;this controls the length of time for the
  839.                 ;break tone condition (080h= approx 50ms)
  840.     mov    b,d
  841.     mvi    e,8
  842.     mvi    a,DTR
  843.     sta    sendflag
  844.     out    DATAB
  845.     jmp    receive
  846.  
  847. ; Dialing routine
  848. ;
  849. ; A  =  ASCII digit to dial | 254 start dial | 255 end dial
  850. ; At end of dialing (A=255), return (in A)
  851. ;    0 carrier present
  852. ;    1 busy
  853. ;    2 timeout (no answer)
  854. ;    3 keyboard abort
  855. ;    4 error reported
  856. ;
  857. PDIAL:    di            ; Stop noise, etc from interfering (ei done by
  858.     lxi    h,dial$abort    ;    rec$stat->bufftest)
  859.     inr    a
  860.     jrz    DIALEND
  861.  
  862.     inr    a
  863.     jrz    DIALSTART
  864.     bit    0,m        ; (hl)=0 ok,3 abort
  865.     rnz
  866.     sui    '9'+3        ; '9'-> -1, '0'-> -10
  867.     adi    10
  868.     jrnc    DIALNIX
  869.     jrnz    DIAL1
  870.     mvi    a,10        ; convert 0 to 10
  871. DIAL1:    mov    b,a
  872. DIAL2:    if    dialon
  873.     xra    a        ; Dial 10 pps, make:break = 1:2
  874.     else
  875.     mvi    a,RSOUT
  876.     endif
  877.     if    fast$dial    ; note the new option to allow you to dial
  878.                 ; faster if the exchange will take it - SC
  879.     mvi    c,33
  880.     else
  881.     mvi    c,66
  882.     endif    ;fast$dial
  883.     call    PULSE        ; 'break' pulse (> 0.5 megaohm)
  884.     mvi    a,DTR+RSOUT
  885.     if    fast$dial
  886.     mvi    c,16
  887.     else
  888.     mvi    c,33
  889.     endif    ;fast$dial
  890.     call    PULSE        ; 'make' pulse (< 0.5 ohm)
  891.     djnz    DIAL2
  892. DIALNIX:
  893.     if    fast$dial
  894.     mvi    b,8
  895.     else
  896.     mvi    b,16        ; Delay between digits 800ms
  897.     endif    ;fast$dial
  898.     ;jmp    DIALCK        ; fall into DIALCK
  899.  
  900. ; Check for abort, over period = b*50ms
  901. ;    requires: hl=dial$abort, b=delay
  902. ;    returns: a=(hl)
  903. DIALCK:    mvi    c,CHEKCC
  904.     call    MEX
  905.     jrnz    DIALC1
  906.     mvi    m,3
  907. DIALC1:    mov    a,m
  908.     ora    a
  909.     rnz
  910.     mvi    c,50
  911.     call    MSECS        ; No regs affected
  912.     djnz    DIALCK
  913.     ret
  914.  
  915. DIALSTART:
  916.     mov    m,a        ; (a=0)
  917.     call    ONLINE
  918.     mvi    b,60
  919.     call    DIALCK        ; wait 3 secs for dial tone
  920.     mvi    a,0FFH        ; Set port B to control mode - I/O mask follows
  921.     out    CTLB
  922.     lda    dialtype    ; Activate off-normal contacts on modem by
  923.     xri    99H        ;  making DIALON an input = hi-impedance
  924.     out    CTLB
  925.     ret
  926.  
  927. ; RSOUT is kept high as I found this necessary for carrier detection
  928. ; Changed to become a DIALON option by Simeon
  929. DIALEND:
  930.     mvi    a,0FFH        ; Set port B to control mode - I/O mask follows
  931.     out    CTLB
  932.     mvi    a,99H        ; Make DIALON output again (return to normal)
  933.     out    CTLB
  934.     if    dialon
  935.     mvi    a,DTR        ; Modem online, RSOUT high (for carrier detect)
  936.     else
  937.     mvi    a,DTR+RSOUT
  938.     endif
  939.     out    DATAB
  940.     lda    ans$time
  941.     mov    e,a        ; Multiply A by 5 (8 bit)
  942.     add    a        ; x 2
  943.     add    a        ; x 4
  944.     add    e        ; + 1
  945.     mov    e,a        ; e = (ans$time) x 5
  946.     mvi    d,0
  947. DIALE1:
  948.     mvi    b,4
  949.     call    DIALCK        ; Delay 200ms, NZ = abort (ctrl-C)
  950.     jrnz    OFFLINE        ; Keyboard abort: connect modem, return 3
  951.     in    DATAB        ; Test carrier
  952.     ani    CTS
  953.     jrnz    DIALE2
  954.     mov    d,a        ; Carrier interrupted, reset count (a=0)
  955. DIALE2:    mvi    a,5        ; require 1 second uninterrupted carrier
  956.     sub    d
  957.     jrz    ONLINE    ; Carrier detect confirmed: connect, return 0
  958.     inr    d
  959.     dcr    e
  960.     jrnz    DIALE1
  961.  
  962.     call    OFFLINE        ; No answer: hangup phone, return 2
  963.     mvi    b,40
  964.     call    DIALCK        ; do 2s delay
  965.     ori    2        ; no answer: return 2 (or 3 if aborted)
  966.     ret
  967.  
  968. ; Put pulse on phone line (DTR in A, C ms long)
  969. PULSE:    out    DATAB
  970.  
  971. ; Delay C milliseconds
  972. MSECS:    push    psw
  973.     push    b
  974.     mov    b,c
  975. MSECS1:    lda    CLOCK
  976. MSECS2:    mvi    c,5        ; 7
  977. MSECS3:    dcr    c         ; 4*5
  978.     jrnz    MSECS3        ;12*4+7
  979.     dcr    a        ; 4
  980.     jrnz    MSECS2        ; 12
  981.     djnz    MSECS1    
  982.     pop    b
  983.     pop    psw
  984.     ret
  985.  
  986. ; connect modem to phone line
  987. ONLINE:
  988.     mvi    a,DTR+RSOUT    ; DTR high, RSOUT low
  989.     out    DATAB
  990.     mov    a,m        ; A=return code (0 or 3) if hl=dial$abort
  991.     ret
  992.  
  993. ; disconnect the modem
  994. OFFLINE:
  995.     mvi    a,RSOUT        ; DTR low, RSOUT low
  996.     out    DATAB
  997.     di
  998.     push    h
  999.     lhld    rs$rptr
  1000.     shld    rs$wptr        ;make the read and write pointers the same
  1001.     pop    h        ;(necessary if disconnecting while still
  1002.                 ; receiving so that the buffer is empty
  1003.                 ; when started up next time)
  1004.     ret
  1005.  
  1006. ; Sign-on message
  1007. SYSVER:    call    ILPRT
  1008. SOMESG: db    'Microbee version',cr,lf,'Software port',0
  1009.  
  1010. ; Newline on console
  1011. CRLF:    call    ILPRT
  1012.     db    CR,LF,0
  1013.     ret
  1014.  
  1015. ; type char in A on console
  1016. TYPE:    push    h        ;save 'em
  1017.     push    d
  1018.     push    b
  1019.     mov    e,a        ;align output character
  1020.     mvi    c,CONOUT    ;print via MEX
  1021.     call    MEX
  1022.     pop    b
  1023.     pop    d
  1024.     pop    h
  1025.     ret
  1026.  
  1027. ;------------------------------------------------------------
  1028. ;
  1029. ; The remainder of this overlay implements a very versatile
  1030. ; SET command
  1031. ; Control is passed here after MEX parses a SET command.
  1032. ;
  1033. SETCMD:    
  1034.     mvi    c,SBLANK
  1035.     call    MEX
  1036.     jc    SETSHO        ;jump if no arguments with SET
  1037.     lxi    d,CMDTBL
  1038.     mvi    c,LOOKUP
  1039.     call    MEX
  1040.     push    h
  1041.     rnc            ;execute set command
  1042.     pop    h
  1043.     call    ILPRT
  1044.     db    TAB,'SET command error - type "SET ?" for help',CR,LF,0
  1045.     ret
  1046.  
  1047. ; SET command table ... note that tables are constructed of command-
  1048. ; name (terminated by high bit=1) followed by word-data-value returned
  1049. ; in HL by MEX service processor LOOKUP.  Table must be terminated by
  1050. ; a binary zero.
  1051. ;
  1052. ; Note that LOOKUP attempts to find the next item in the input stream
  1053. ; in the table passed to it in HL ... if found, the table data item is
  1054. ; returned in HL; if not found, LOOKUP returns carry set.
  1055.  
  1056. CMDTBL:    db    '?'+80h            ; set ?
  1057.     dw    STHELP            ;
  1058.     db    'HEL','P'+80h        ; set help
  1059.     dw    STHELP
  1060.     db    'BAU','D'+80h        ; set baud
  1061.     dw    STBAUD            ;
  1062.     db    'B'+80h            ; set baud
  1063.     dw    STBAUD            ;
  1064.     db    'SEN','D'+80h        ; set send baud rate
  1065.     dw    SETSND
  1066.     db    'S'+80h
  1067.     dw    SETSND
  1068.     db    'RECEIV','E'+80h    ; set receive baud rate
  1069.     dw    SETREC
  1070.     db    'R'+80h
  1071.     dw    SETREC
  1072.     db    'DAT','A'+80h        ; set no of data bits
  1073.     dw    SETDATA
  1074.     db    'D'+80h
  1075.     dw    SETDATA
  1076.     db    'STO','P'+80h        ; set stop bits
  1077.     dw    SETSTOP
  1078.     db    'PARIT','Y'+80h        ; set parity
  1079.     dw    SETPAR
  1080.     db    'P'+80h
  1081.     dw    SETPAR
  1082.     db    'FLI','P'+80H        ; swap send/receive
  1083.     dw    SETFLIP
  1084.     db    'F'+80h
  1085.     dw    SETFLIP
  1086.     db    'WAI','T'+80H
  1087.     dw    SETWAIT            ; set wait time for answer
  1088.     db    'W'+80H
  1089.     dw    SETWAIT
  1090.  
  1091.     db    0            ; <<=== table terminator
  1092.  
  1093. ; SET <no-args>: print current statistics
  1094. ;
  1095. SETSHO:    lxi    h,SHOTBL    ;get table of SHOW subroutines
  1096. SETSLP:    mov    e,m        ;get table address
  1097.     inx    h
  1098.     mov    d,m
  1099.     inx    h
  1100.     mov    a,d        ;end of table?
  1101.     ora    e
  1102.     rz            ;exit if so
  1103.     push    h        ;save table pointer
  1104.     xchg            ;adrs to HL
  1105.     call    GOHL        ;do it
  1106.     call    CRLF
  1107.     pop    h        ;it's done
  1108.     jr    SETSLP
  1109.  
  1110. GOHL:    pchl
  1111.  
  1112. ; table of SHOW subroutines, last address executed first
  1113. SHOTBL:    dw    BDSHOW
  1114.     dw    SHODATA
  1115.     dw    SHOSTOP
  1116.     dw    SHOPAR
  1117.     dw    SHODCD
  1118.     dw    0        ;<<== table terminator
  1119.  
  1120. ; SET ?  processor
  1121. ;
  1122. STHELP:
  1123.     mvi    a,25
  1124.     call    EQUALA
  1125.     call    ILPRT
  1126.     db    '  Microbee SET command  ',0
  1127.     mvi    a,25
  1128.     call    EQUALA
  1129.     call    ILPRT
  1130.     db    LF
  1131.     db    CR,LF, 'SET BAUD <value>  or  SET B <value>'
  1132.     db    CR,LF, 'SET SEND <value>  or  SET S <value>'
  1133.     db    CR,LF, 'SET RECEIVE <value>  or  '
  1134.     db    'SET R <value>'
  1135.     db    CR,LF, 'SET FLIP  or  SET F            ... swaps baud rates: send <=> receive'
  1136.     db    CR,LF,LF,'    baud rates allowed are:'
  1137.     db    CR,LF, '        75,  110,  134,  150,  300,  450,  600'
  1138.     db    CR,LF, '        710, 1200, 1800, 2400, 4800, 9600, 19200'
  1139.     db    CR,LF,LF,'SET DATA <value>  or  SET D <value>'
  1140.     db    CR,LF, '                  ... DATA bits sent/received: 1 <= value <= 8'
  1141.     db    CR,LF,LF,'SET PARITY <c>  or  SET P <c>'
  1142.     db    CR,LF, '          ... <c>:  N = no parity, E = even parity, O = odd parity'
  1143.     db    CR,LF,LF,'SET STOP              ... toggles number of stop bits: 1 <=> 2'
  1144.     db    CR,LF,LF,'SET WAIT <value>          ... set timeout for answer: 1 to 25 secs'
  1145.     db    CR,LF,0
  1146.     mvi    a,74
  1147.     ;jmp    EQUALA        ;fall into EQUALA
  1148.  
  1149. ;Type '=' x A reg  (scrounging bytes)
  1150. EQUALA:    push    b
  1151.     mov    b,a        ;store value in b
  1152.     mvi    a,'='
  1153. EQUAL1: call    TYPE
  1154.     djnz    EQUAL1
  1155.     pop    b
  1156.     ret
  1157.  
  1158. ; Show carrier detect status
  1159. SHODCD:    in    DATAB
  1160.     ani    CTS        ; (actually DCD)
  1161.     jrnz    SHODC1
  1162.     call    ILPRT
  1163.     db    'NO ',0
  1164. SHODC1:    call    ILPRT
  1165.     db    'Carrier is present',0
  1166.     ret
  1167.  
  1168.  
  1169. ; Automatic SET BAUD through phone library
  1170. ; Note: specifying 110 in phone library sets 1200/75
  1171. PBAUD:    
  1172.     call    MTOBAUD        ; get baud rate corresponding to mspeed
  1173.     push    h
  1174.     ora    a        ; mspeed=0 <=> 110 baud
  1175.     mvi    a,5        ; mspeed=5 <=> 1200 baud
  1176.     cz    MTOBAUD    ; get 1200 baud in L, if mspeed is 110
  1177.     mov    a,l
  1178.     sta    baud        ; set receive baud rate
  1179.     pop    h
  1180.     jr    PBAUDSET
  1181.  
  1182. ; SET BAUD processor
  1183. STBAUD:    lxi    d,setbdt
  1184.     call    setbd1
  1185.     mov    a,h
  1186.     sta    MSPEED
  1187.     mov    h,l
  1188.     shld    baud
  1189.     jr    BDSHOW
  1190.  
  1191. SETSND:    lxi    d,setbds    ; set sending baud rate
  1192.     call    setbd1
  1193. PBAUDSET:
  1194.     mov    a,h
  1195.     sta    MSPEED
  1196.     mov    a,l
  1197.     sta    baud+1
  1198.     jr    BDSHOW
  1199.  
  1200. SETREC:    lxi    d,setbdt    ; set receiving baud rate
  1201.     call    setbd1
  1202.     mov    a,l
  1203.     sta    baud
  1204.     jr    BDSHOW
  1205.  
  1206. SETFLIP:            ; Swap send<=>receive baud rates
  1207.     lhld    baud
  1208.     mov    a,h
  1209.     mov    h,l
  1210.     mov    l,a
  1211.     shld    baud
  1212.     lxi    d,setbdt-1    ; make MSPEED correspond to send baud rate
  1213. setfl1:    inx    d
  1214.     call    NEXTBD
  1215.     jrc    BDSHOW
  1216.     ldax    d
  1217.     inx    d
  1218.     cmp    h
  1219.     jrnz    setfl1
  1220.     ldax    d
  1221.     sta    MSPEED
  1222.  
  1223. BDSHOW:    call    ILPRT        ;display baud
  1224.     db    'Baud rate, send = ',0
  1225.     lda    baud+1
  1226.     call    bdsho1        ;display baud rate + '  '
  1227.     call    ILPRT
  1228.     db    'receive = ',0
  1229.     lda    baud
  1230. bdsho1:
  1231.     mov    c,a
  1232.     lxi    d,setbds
  1233. bdsho2:    mov    h,d
  1234.     mov    l,e
  1235.     call    NEXTBD
  1236.     jrc    bdsho5
  1237.     ldax    d
  1238.     inx    d
  1239.     inx    d
  1240.     cmp    c
  1241.     jrnz    bdsho2
  1242. bdsho4:    mov    a,m
  1243.     ani    7fh
  1244.     call    TYPE
  1245.     bit    7,m
  1246.     inx    h
  1247.     jrz    bdsho4
  1248. bdsho5:    call    ILPRT
  1249.     db    '  ',0
  1250.     ret
  1251.  
  1252. setbd1:    mvi    c,SBLANK
  1253.     call    MEX
  1254.     jrc    setbd2
  1255.     mvi    c,LOOKUP
  1256.     call    MEX
  1257.     rnc
  1258.     call    ILPRT
  1259.     db    TAB,'Invalid baud rate',CR,LF,0
  1260. setbd2:    pop    psw
  1261.     jr    BDSHOW
  1262.  
  1263. NEXTBD:    ldax    d
  1264.     inx    d
  1265.     ora    a
  1266.     rm
  1267.     jrnz    NEXTBD    ; Z = End of table (should not occur)
  1268.     stc
  1269.     ret            ; error, return carry set
  1270.  
  1271. MTOBAUD:            ; convert mspeed in A to baud
  1272.     mov    h,a        ; A = MSPEED
  1273.     lxi    d,setbdt-1
  1274. MTOB1:    inx    d
  1275.     call    NEXTBD
  1276.     rc            ; Error, mspeed not in table
  1277.     ldax    d
  1278.     mov    l,a        ; store baud in l
  1279.     inx    d
  1280.     ldax    d
  1281.     cmp    h
  1282.     jrnz    MTOB1
  1283.     ret            ; Exit with A=H=mspeed, L=baud
  1284.  
  1285. ; Look-up table for SET BAUD format: 'nnn',baudrate,MSPEED
  1286. setbds:                    ; could use any delay for sending,
  1287.                     ; but 170 is maximum for receiving
  1288.                     ; ie do not use: 170 < delay <=255
  1289. setbdt:
  1290.     db    '7','5'+80h,0,0        ; Special case, see rec$interrupt
  1291.     db    '11',0b0h,170,0
  1292.     db    '13','4'+80h,143,0
  1293.     db    '15',0b0h,128,0
  1294.     db    '30',0b0h,64,1
  1295.     db    '45',0b0h,43,2
  1296.     db    '60',0b0h,32,3
  1297.     db    '71',0b0h,27,4
  1298.     db    '120',0b0h,16,5
  1299.     db    '180',0b0h,11,5
  1300.     db    '240',0b0h,8,6
  1301.     db    '480',0b0h,4,7
  1302.     db    '960',0b0h,2,8
  1303.     db    '1920',0b0h,1,9
  1304.     db    0
  1305.  
  1306. ; Set no. of stop bits, toggles 1<=>2
  1307. SETSTOP: lda    stopbits
  1308.     dcr    a
  1309.     jrnz    ststp1
  1310.     mvi    a,2
  1311. ststp1:    sta    stopbits
  1312. SHOSTOP: lda    stopbits
  1313.     call    DECA            ; Display A, ILPRT
  1314.     db    ' stop bits',0
  1315.     ret
  1316.  
  1317. SETDATA: mvi    c,SBLANK
  1318.     call    MEX
  1319.     mvi    c,GNC
  1320.     call    MEX
  1321.     jrc    SHODATA
  1322.     sui    '0'
  1323.     jrz    setdte
  1324.     cpi    9
  1325.     jrnc    setdte
  1326.     sta    ndata
  1327. SHODATA: lda    ndata
  1328.     call    DECA            ; Display A, ILPRT
  1329.     db    ' data bits',0
  1330.  
  1331. GET$NPDATA:                ; sets (npdata)
  1332.     lda    bparity
  1333.     mov    b,a
  1334.     lda    ndata
  1335.     dcr    b
  1336.     jrz    setdt1        ; parity = none
  1337.     inr    a            ; parity = odd,even
  1338. setdt1:    sta    npdata            ; = no of data bits + parity bit
  1339.     ret
  1340.  
  1341. setdte: call    ERROR
  1342.     db    '1 <= n <= 8',CR,LF,0
  1343.     jr    SHODATA
  1344.  
  1345. ;Set parity 1=none, 2=odd else even:
  1346. SETPAR:    mvi    c,SBLANK
  1347.     call    MEX
  1348.     mvi    c,GNC
  1349.     call    MEX
  1350.     jrc    SHOPAR
  1351.     mvi    c,1
  1352.     ani    5fh
  1353.     cpi    'N'
  1354.     jrz    setpr1    ; none = 1
  1355.     inr    c
  1356.     cpi    'O'
  1357.     jrz    setpr1    ; odd  = 2
  1358.     inr    c        ; even = 3
  1359.     cpi    'E'
  1360.     jrnz    SETPER
  1361. setpr1:    mov    a,c
  1362.     sta    bparity
  1363.     call    GET$NPDATA    ; (npdata) = (ndata) + parity bit (if present)
  1364. SHOPAR:    call    ILPRT        ; Show parity status:
  1365.     db    'parity: ',0
  1366.     lda    bparity
  1367.     mov    b,a
  1368.     djnz    SHOPR1        ; b = 1?
  1369.     call    ILPRT        ; yes
  1370.     db    'none',0
  1371.     ret
  1372. SHOPR1:    djnz    SHOPR2        ; no, b = 2?
  1373.     call    ILPRT        ; yes
  1374.     db    'odd',0
  1375.     ret
  1376. SHOPR2:    call    ILPRT        ; no
  1377.     db    'even',0
  1378.     ret
  1379.  
  1380. SETPER:    call    ERROR
  1381.     db    'N, O, or E',CR,LF,0
  1382.     jr    SHOPAR
  1383.  
  1384.  
  1385. SETWAIT:
  1386.     mvi    c,SBLANK
  1387.     call    MEX
  1388.     jrc    SHOWAIT        ; No <value> to parse
  1389.     mvi    c,EVALA
  1390.     call    MEX
  1391.     mov    a,l
  1392.     cpi    26
  1393.     jrnc    SETWERR
  1394.     ora    a
  1395.     jrz    SETWERR
  1396.     sta    ans$time
  1397. SHOWAIT:
  1398.     lda    ans$time
  1399.     call    DECA        ; Display A in decimal, then ILPRT
  1400.     db    ' s wait',0
  1401.     ret
  1402.  
  1403. SETWERR: call    ERROR
  1404.     db    '1-25 secs',CR,LF,0
  1405.     jr    SHOWAIT
  1406.  
  1407.  
  1408. ; Display A reg in decimal, then print in-line text
  1409. DECA:    mov    l,a
  1410.     mvi    h,0
  1411.     mvi    c,DECOUT
  1412.     call    MEX
  1413.     jr    ILPRT
  1414.  
  1415. ; Print Error Message (ILPRT fashion)
  1416. ERROR:    call    ILPRT
  1417.     db    TAB,'Invalid - must be ',0
  1418.  
  1419. ; Print in-line message
  1420. ILPRT:    mvi    c,ILP        ;get function code
  1421.     jmp    MEX        ;go do it
  1422.  
  1423.  
  1424. ; Buffer for incoming data
  1425. rs$buff    equ    0B00h        ;Code must end before 0B00h
  1426.  
  1427. ;------------------------------------------------------------
  1428. ;
  1429. ; End of Microbee MEX modem overlay
  1430. ;
  1431. ;------------------------------------------------------------
  1432.     end            ; Overlay must end before 0D00h
  1433. all    MEX
  1434.     mvi    c,GNC
  1435.     call    MEX
  1436.     jrc    SHOPAR
  1437.     mvi    c,1
  1438.     ani    5fh
  1439.     cpi    'N'
  1440.     jrz    setpr1    ; none = 1
  1441.     inr