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 / MBUG / MBUG167.ARC / ZMP-BEE.LBR / RSXMAIN.IZC / RSXMAIN.INC
Text File  |  1979-12-31  |  14KB  |  520 lines

  1. ; Microbee Serial I/O RSX -- Ron Murray, 12/11/88
  2. ;
  3. ; Part of the RSX system.  C.B. Falconer, 85/11/18
  4. ;
  5. ; This file should be named "RSXMAIN.INC".  It is the actual
  6. ; RSX code to be installed.  It has available to it the routines
  7. ; TSTR     (like DOS string call, but registers preserved)
  8. ; DOS    (like BDOS call, but register A specified the function,
  9. ;      and the bc and de registers are preserved)
  10. ; GOBDOS (Just like the original BDOS call).
  11. ;  note that DOS and GOBDOS do not use the RSX code.
  12. ; DO NOT MAKE A SEPARATE dseg.
  13. ;
  14. ; Equates used only by Microbee routines grouped together here.
  15. ;
  16. ; Z80 PIO equates:
  17. DATAB    equ    2        ;PIO port B data
  18. CTLB    equ    3        ; "   "   " control
  19. DTR    equ    4        ;DTR  output on bit 2
  20. RSOUT    equ    20h        ;RS-232  "   "   "  5
  21. CTS    equ    8        ;CTS   input "   "  3
  22. RSIN    equ    10h        ;RS-232  "   "   "  4
  23.  
  24. XOFF    equ    'S'-40h
  25. XON    equ    'Q'-40h
  26.  
  27. ; End of Microbee equates
  28.  
  29. stksz    equ    48        ;     REQUIRED equate.  Customize to system.
  30. ;
  31. ; Message for example only, not required
  32. exumsg:    db    'RSX executed',cr,lf,'$'
  33. ;
  34. ; This routine MUST be supplied.  It may be only a "ret".
  35. ; This is executed on each warmboot (or DOS call #0)
  36. ; a,f,b,c,d,e,h,l (allowed)
  37. boothk:    ret
  38. ;
  39. ; This routine MUST be supplied.  It may be only a "ret".
  40. ; This is executed each time CPM is rebooted or the disk
  41. ; system is reset by BDOS function 13.
  42. ; a,f,b,c,d,e,h,l (allowed)
  43. bthook:
  44.     ret
  45. ;    ld    de,btmsg
  46. ;    jp    tstr        ;         and exit
  47. ;
  48. ; message for example only.  Not required
  49. ;btmsg:    db    cr,lf,'Disks reset$'
  50. ;
  51. ; This message must be supplied.  It can be empty (consisting of
  52. ; only the terminal $).  End it with a "$" character.  This message
  53. ; is displayed whenever the CPM system reboots, provided that this
  54. ; is the last RSX installed.
  55. actmsg:    db    cr,lf,'Modem RSX active$'
  56. ;
  57. ; This message must also be supplied.  It is output following the
  58. ; actmsg above.  This combination allows one portion to be
  59. ; dynamically modified.
  60. altid:    db    '$'
  61. ;
  62. ; This message must also be supplied.  It is output when the RSX
  63. ; is actually removed, either by running the program again, or
  64. ; by some other program signalling removal.  Terminate with '$'.
  65. ; NOTE that the actual removal is performed on the reboot following
  66. ; the termination, and only if this is the last RSX in the chain.
  67. donemsg:
  68.     db    cr,lf,'Modem RSX removed$'
  69. ;
  70. ; This routine MUST be supplied
  71. ; The actual code for the application goes here.  The stack has
  72. ; been switched, and a return value (if any) should be in (hl).
  73. ; Note that the (de) parameter can never be 0 or 0ffffh on entry.
  74. ; If this system is really an i/o driver (such as a foreign disk
  75. ; reader/writer) then the RSX itself never need do anything, and
  76. ; this code can be left alone (except that a DOS call is available
  77. ; to trigger the message below).  Otherwise the registers are set
  78. ; as if receiving a BDOS call, and appropriate action can be taken.
  79. ; If this application need only modify, and/or conditionally
  80. ; intercept a normal BDOS call, it can exit to the real BDOS by
  81. ; a "jmp gobdos".  In this case ensure the bc and de values are
  82. ; suitable.  We never get here for de = 0 or 0ffffh.
  83. ; Return address of rec_interrupt if de=0001.
  84. rsx:    ld    a,e
  85.     dec    a        ;      whenever de=0001
  86.     or    d        ;      then
  87.     ld    hl,addtab    ;    return table of addresses
  88.     ret    z        ;     (de) was 1, data pointer enquiry
  89.  
  90.     ld    a,c        ; get function
  91.     cp    @rsx        ; get status?
  92.     jp    z,get_stat    ; yes
  93.     cp    @rsxx        ; Data out?
  94.     jr    z,put_data    ; yes
  95.     cp    @rsxy        ; data in?
  96.     jr    z,get_data    ; yes
  97.     ret            ; should never get here
  98.  
  99. ;Get data from modem port
  100. get_data:
  101.     call    iDATA        ; get into A
  102.     ld    l,a        ; get into hl
  103.     ld    h,0
  104.     ret
  105.  
  106. ;Send data to modem port
  107. put_data:
  108.     ld    a,e        ; get it into A
  109.     call    oDATA        ; send it
  110.     ret
  111.  
  112. ;Get simulated status reg. Return with bit 3 = Receive Data Register Full
  113. ;(1 == full), bit 4 = Transmit Data Register Empty (1 == empty).
  114. ; Similar to a 6551 (Revenge!)
  115. get_stat:
  116.     call    send_stat    ; get send status
  117.     ld    e,0        ; clear result
  118.     cp    CTS        ; ready?
  119.     jr    nz,getst1
  120.     set    4,e        ; yes, set the bit
  121.  
  122. getst1:
  123.     push    de
  124.     call    rec_stat    ; get receive status
  125.     pop    de        ; restore send stat
  126.     cp    1        ; rx ready?
  127.     jr    nz,getst2
  128.     set    3,e        ; yes, set the bit
  129.  
  130. getst2:
  131.     ld    a,e        ; status to A
  132.     ld    l,a        ; and hl
  133.     ld    h,0
  134.     ret
  135.  
  136. ;Simulated status ports:
  137. send_stat:
  138.     in    a,(DATAB)
  139.     and    CTS
  140.     ret
  141.  
  142. rec_stat:            ; Check if data in buffer:
  143.     ld    a,(statbyte)    ; 1=char-ready, 0=not-ready
  144.     or    a
  145.     jr    nz,rstat1
  146.     push    bc
  147.     push    hl
  148.     ld    hl,(rs_wptr)
  149.     ld    bc,(rs_rptr)
  150.     sbc    hl,bc
  151.     jr    z,iDATAE    ; Buffer empty
  152.     pop    hl
  153.     pop    bc
  154.     ld    a,2        ; return ready-state
  155.     ld    (statbyte),a
  156.     dec    a
  157.     ret
  158.  
  159. rstat1:    dec    a
  160.     ld    (statbyte),a    ; return not-ready
  161.     xor    a
  162.     ret
  163.     
  164. ;  iDATA also handles the internal automatic XOFF/XON on impending
  165. ;  buffer overflow
  166. iDATA:                ;in modem data port
  167.     push    bc        ;Reads input buffer 
  168.     push    hl
  169.     ld    bc,(rs_rptr)
  170.     ld    hl,(rs_wptr)
  171.     xor    a
  172.     sbc    hl,bc
  173.     jr    z,iDATAE    ; 0=empty, 1=one byte ... -1=full
  174.     inc    h
  175.     jr    nz,iDATA1
  176.     ld    a,l
  177.     add    a,20h
  178.     call    c,iDATAF    ; Buffer nearly full - PANIC!!
  179. iDATA1:    inc    bc
  180.     res    1,b        ; Determines buffer size (200H)
  181.     ld    hl,rs_buff
  182.     add    hl,bc
  183.     ld    a,(hl)        ; first read buffer
  184.     ld    (rs_rptr),bc    ; THEN update rptr
  185.     dec    h        ; Set NZ flag
  186.     pop    hl
  187.     pop    bc
  188.     ret
  189.  
  190. iDATAE:    pop    hl        ; Buffer empty
  191.     pop    bc
  192.     call    rec_reti    ; ei, in case disabled by buffer overflow
  193.     ld    a,(xflag)
  194.     or    a
  195.     ret    z
  196.     ld    a,XON
  197.     call    oDATA        ; send XON if remote was XOFFed
  198.     xor    a        ; Set Z flag
  199.     ld    (xflag),a
  200.     ret
  201.  
  202. iDATAF:    ld    a,(xflag)    ; Buffer (nearly) full
  203.     or    a
  204.     ret    nz        ; XOFF already sent
  205.     dec    a
  206.     ld    (xflag),a
  207.     ld    a,XOFF
  208. ;    jp    oDATA        ; Send XOFF character
  209.  
  210. ; Serial I/O routine
  211. ;    register assignments: A=G.P.
  212. ;    Normal register set:
  213. ;        B = send delay count    C = receive data count
  214. ;            never 1 for rec-only    1..n if receiving, 0 if rec idle
  215. ;                        -1 if waiting for stop-bit
  216. ;        D = send delay        E = data count, send
  217. ;        H = send data        L = send data
  218. ;            DE,HL not used on receive only
  219. ;
  220. ;    Alternate register set:
  221. ;            not used on send only
  222. ;        B'= rec delay count    C'= rec delay
  223. ;        D'= rec data        E'= RSIN
  224. ;                    L'= (ndatap) for adjustment at write
  225.  
  226. oDATA:                ;out modem data port
  227.     out    (9),a        ;turn off wait cycling (not needed on all bees)
  228.     push    af        ;  & let CPU run at full speed 
  229.     push    bc        ;  wait-ing initiated by writing to screen RAM
  230.     exx
  231.     push    bc
  232.     push    de
  233.     push    hl
  234.     exx
  235.     push    de
  236.     push    hl
  237.     ld    c,a
  238.     ld    a,(ndata)
  239.     ld    b,a
  240.     ld    e,a        ; no of data bits (send)
  241.     ld    a,1
  242. send_1:    rrc    c
  243.     rl    l        ; reverse order of bits
  244.     add    a,a        ; generate mask
  245.     djnz    send_1
  246.     dec    a        ; a = mask
  247.     and    l        ; mask send data
  248.     jp    pe,send_2
  249.     ccf            ; carry = parity bit
  250. send_2: ld    a,(bparity)
  251.     dec    a
  252.     jr    z,send_nopar
  253.     dec    a
  254.     jr    nz,send_pe
  255.     ccf
  256. send_pe:
  257.     adc    hl,hl        ; add parity bit to send data
  258.     inc    e        ; +1 to data count for parity
  259. send_nopar:
  260.     ld    a,13
  261.     sub    e        ; no of data bits + parity (if req)
  262.     ld    b,a
  263. send_3:    add    hl,hl
  264.     inc    hl
  265.     djnz    send_3
  266.     ld    a,(stopbits)
  267.     add    a,e        ; +stopbits
  268.     inc    a        ; +1 since d=1 -> finished sending
  269.     ld    e,a        ; send data counter
  270.     ld    c,b        ; rec data count = 0
  271.     ld    a,(baud+1)    ; send delay
  272.     ld    d,a        ; send delay (for resetting)
  273.     ld    b,a        ; send delay counter
  274. send_cts: in    a,(DATAB)
  275.     and    CTS
  276.     jr    z,send_cts
  277.     ld    a,DTR
  278.     ld    (sendflag),a    ; NZ = sending
  279.     out    (DATAB),a    ; output start bit (high)
  280.     jp    receive
  281.  
  282. ; Timing loop
  283. ; Ideally, 176 clock cycles long
  284. ; Instructions used purely for timing labled '+'
  285.  
  286. rec_write:            ; receive + 21 cycles
  287.     exx            ;  4\
  288.     ld    a,9        ;  7 \
  289.     djnz    rec_weq        ;  8  |    13
  290.     sub    l        ;  4  |    = 37
  291.     ld    b,a        ;  4 /
  292.     in    a,(DATAB)    ; 10/
  293.     jr    z,rec_noadj    ;  7\    12
  294.     and    e        ;  4 \
  295.     sub    e        ;  4  |
  296.     ld    a,d        ;  4  |    =12(9b) =35(8b) =52(7b)
  297. rec_adj: rr    a        ;  4  |
  298.     djnz    rec_adj        ;  8 /    13
  299.     ld    d,a        ;  4/
  300. rec_noadj: ld    hl,(rs_rptr)    ; 16\
  301.     ld    bc,(rs_wptr)    ; 20 \
  302.     inc    bc        ;  6  |
  303.     res    1,b        ;  8  |    dictates buffer size (200H)
  304.     xor    a        ;  4  |
  305.     sbc    hl,bc        ; 15  |
  306.     jr    z,rec_full    ;  7  |
  307.     ld    (rs_wptr),bc    ; 20  |    = 196(ei) =167(no ei)
  308.     dec    a        ;  4  |        total = 289 (8b, ei)
  309. rec_full: ld    hl,rs_buff    ; 10  |    hl = buffer
  310.     add    hl,bc        ; 11  |
  311.     ld    (hl),d        ;  7  |        d' = data for receive
  312.     exx            ;  4  |
  313.     ld    c,a        ;  4  |    -1=ei, 0=don't ei
  314.     in    a,(DATAB)    ; 10  |
  315.     and    RSIN        ;  7  |
  316.     add    a,c        ;  4 /
  317.     call    m,rec_ei    ; 10/    17+22
  318. send:
  319.     djnz    send_eq        ;  8\    13    b = delay counter
  320.     dec    e        ;  4 \        e = data counter
  321.     jr    z,send_finish    ;  7  |    12    e=1, finished send, pop HL,DE
  322.     add    hl,hl        ; 11  |
  323.     ld    a,h        ;  4  | total = 63
  324.     and    RSOUT        ;  7  |
  325.     or    DTR        ;  7  |
  326.     out    (DATAB),a    ; 11 /
  327.     ld    b,d        ;  4/    reset delay count
  328. receive:
  329. ;    push    hl        ;+11\  2MHz only
  330. ;    add    hl,hl        ;+11 |    "    "
  331. ;    pop    hl        ;+10/    "    "     (total = 32)
  332.  
  333.     ld    a,-1        ;  7\
  334.     add    a,c        ;  4 |        c = data counter for receive
  335.     jp    z,rec_write    ; 10 |        c=1, last bit
  336.     jr    nc,rec_idle    ;  7 |    12    c=0, idle
  337.     jp    m,rec_test    ; 10 |        c=-1, wait for RSIN to go low
  338.     exx            ;  4 |
  339.     djnz    rec_eq        ;  8 |    13    b'= delay counter (rec)
  340.     in    a,(DATAB)    ; 10 |        receive and record data
  341.     and    RSIN        ;  7 |
  342.     sub    RSIN        ;  7 |    total = 113
  343.     rr    d        ;  8 |
  344.     ld    b,c        ;  4 |        reset delay counter
  345.     exx            ;  4 |
  346.     dec    c        ;  4 |        dec data counter
  347.     ld    a,(hl)        ;+ 7 |
  348.     jr    send        ; 12/
  349.  
  350. rec_idle:            ; receive + 33 cycles
  351.     ld    a,(hl)        ;+ 7\    rec is only waiting for send to finish
  352.     ld    a,(hl)        ;+ 7 |
  353.     jr    rec_59        ; 12/    receive + 59
  354.  
  355. rec_weq:            ; receive + 45 cycles
  356.     jp    rec_eq        ;+10 >
  357. rec_eq:                ; receive + 55 cycles
  358.     exx            ;  4\
  359. rec_59:                ; receive + 59
  360.     nop            ;+ 4 |
  361.     ex    (sp),hl        ;+19 |
  362.     ex    (sp),hl        ;+19 |
  363.     jr    send        ; 12/    total = 55 + 58 = 113
  364.  
  365. rec_test:            ; receive + 38 cycles
  366.     in    a,(DATAB)    ; 10 \
  367.     and    RSIN        ;  7  |        rec is testing RSIN
  368.     jr    nz,rec_wait    ;  7  |    12
  369.     call    rec_ei        ;17+22|
  370.     jr    send        ; 12 /    total = 75 + 38 = 113
  371.  
  372. rec_wait:            ; receive + 67 cycles
  373.     ld    a,(sendflag)    ; 13\    rec is waiting for input to go low (to
  374.     or    a        ;  4 |     prevent unwanted interrupt)
  375.     jp    z,rec_test    ; 10 |        short waiting loop
  376.     ld    a,(hl)        ;+ 7 |
  377.     jr    send        ; 12/    total = 67 + 46 = 113
  378.  
  379. rec_ei:    inc    c        ;  4\
  380. rec_reti:            ;    |        rec_reti called by rec_stat
  381.     ei            ;  4 |
  382.     reti            ; 14/
  383.  
  384.  
  385. send_finish:            ; send + 24  (execute once only per send)
  386.     xor    a        ;  4\
  387.     ld    (sendflag),a    ; 13 |
  388.     pop    hl        ; 10 |
  389.     pop    de        ; 10 |
  390.     jp    receive        ; 10/    total = 47 + 24 = 63 + 8
  391.  
  392. send_eq:            ; send + 13
  393.     ld    a,(sendflag)    ; 13\
  394.     or    a        ;  4 |
  395.     jp    z,send_idle    ; 10 |
  396.     ld    a,(hl)        ;+ 7 |
  397.     nop            ;+ 4 |
  398.     jr    receive        ; 12/        total = 13 + 50 = 63
  399.  
  400. send_idle:            ; send + 40
  401.     ld    b,0FFh        ;  7\    stay on send_eq path
  402.     or    c        ;  4 |
  403.     jr    nz,receive    ;  7/    12    total = 40 + 23 = 63
  404. exit:                ; send + 58
  405.     exx            ;  4\
  406.     pop    hl        ; 10 |
  407.     pop    de        ; 10 |
  408.     pop    bc        ; 10 | = 68
  409.     exx            ;  4 |
  410.     pop    bc        ; 10 |
  411.     pop    af        ; 10 |
  412.     ret            ; 10/
  413.                 ; send + 126 = receive + 415 (min) via write
  414.  
  415. rec_interrupt:             ; 19\ cycles to respond to interrupt
  416.     out    (9),a        ; 11 |
  417.     push    af        ; 11 |
  418.     ld    a,(sendflag)    ; 13 | = 68
  419.     or    a        ;  4 |
  420.     jp    nz,rec_wsend    ; 10/
  421.     push    bc        ; 11\
  422.     ld    b,a        ;  4 |    b = send delay count = 0 (disable send)
  423.     ld    a,(npdata)    ; 13 |
  424.     ld    c,a        ;  4 |    c = rec data count
  425.     exx            ;  4 |
  426.     push    bc        ; 11 |
  427.     push    de        ; 11 |
  428.     push    hl        ; 11 | = 126
  429.     ld    l,a        ;  4 |    l' = (npdata) used in adjusting
  430.     ld    de,RSIN        ; 10 |    d' = data for rec
  431.     ld    a,(baud)    ; 13 | 
  432.     ld    c,a        ;  4 |    c' = rec delay (for resetting counter)
  433.     rra            ;  4 |    a' = c'/2  (carry = 0 from "or a")
  434.     add    a,c        ;  4 |       = delay x 1.5 for 1st bit
  435.     ld    b,a        ;  4 |    b' = rec delay counter
  436.     exx            ;  4 |
  437.     jp    nz,receive    ; 10/    rec_interrupt + 194
  438. ; Special handlng of delay=0 (75 baud)
  439.     exx
  440.     ld    b,128
  441.     exx
  442.     inc    c        ;    read extra data bit at start
  443.     jp    receive
  444.  
  445. rec_wsend:            ; rec_interrupt + 68 cycles
  446.     ld    a,(npdata)    ; 13\
  447.     ld    c,a        ;  4 |    c = rec data counter
  448.     exx            ;  4 |
  449.     ld    l,a        ;  4 |    l' = (npdata) for adjusting
  450.     ld    de,RSIN        ; 10 |    d' = data for rec
  451.     ld    a,(baud)    ; 13 | = 95 
  452.     ld    c,a        ;  4 |    c' = rec delay (for resetting counter)
  453.     rra            ;  4 |    a' = c'/2  (carry = 0 from "or a")
  454.     add    a,c        ;  4 |       = delay x 1.5 for 1st bit
  455.     ld    b,a        ;  4 |    b' = rec delay counter
  456.     jr    z,rec_75    ;  7 |    12
  457.     exx            ;  4 |
  458.     pop    af        ; 10 |
  459.     ret            ; 10/    rec_interrupt + 163
  460.  
  461. rec_75:    ld    b,128        ; Special handling for delay=0 (75b)
  462.     exx
  463.     inc    c        ;    read extra data bit at start
  464.     pop    af
  465.     ret
  466.  
  467.  
  468. ;
  469. ; ------------------- Initialized storage --------------------------
  470. ;
  471. ; This initialized byte is required
  472. active:    db    true        ;     Non zero if active. allows 1..255
  473. ;
  474. ; ==================================================================
  475. ; ****    Put initialized application storage past this point    ****    
  476. ; ==================================================================
  477. ;
  478. ;
  479.  
  480. ;Table of addresses: address of this returned by hl when de=1
  481. addtab:
  482.     dw    rec_interrupt
  483.     dw    bparity
  484.     dw    stopbits
  485.     dw    ndata
  486.     dw    npdata
  487.     dw    baud
  488.  
  489. ; Microbee serial I/O routines - Data area
  490. sendflag:    db    0    ; NZ while sending data
  491. xflag:        db    0    ; indicates if automatic XOFF sent
  492. baud:        dw    4040h    ; 300 baud
  493. ndata:        db    8    ; 8 data bits
  494. npdata:        db    8    ; (ndata) + parity bit (if req)
  495. stopbits:    db    1    ; 1 stop bit
  496. bparity:    db    1    ; 1=none, 2=odd, else even 
  497. rs_rptr:    dw    0    ; read pointer into buffer
  498. rs_wptr:    dw    0    ; write   "     "     "
  499. oldvcb:        dw    0    ; Storage for old interrupt vector
  500. statbyte:    db    0    ; counter for 0's returned by rec_stat after 1
  501.  
  502. ; ------------------ End initialized storage -----------------------
  503. ;
  504. ; ------------------- Uninitialized storage ------------------------
  505. ;
  506. ; Required equate.  Nothing from here on but "DS" statements.
  507. segsiz    equ    $-@base        ;     Relocation bit table starts here
  508. ;
  509. ; ==================================================================
  510. ; ****    Put uninitialized application storage past this point    ****
  511. ; ==================================================================
  512. ;
  513. ; NOTE - If more that 32 bytes of stack are required see RSXMAST.Z80
  514.  
  515. ; Buffer for incoming data
  516. rs_buff:    ds    200h
  517.  
  518. ;
  519. ; -------------- End application uninitialized storage -------------
  520.