?login_element?

Subversion Repositories NedoOS

Rev

Blame | Last modification | View Log | Download

  1. ;
  2.  
  3.     MODULE UART5
  4.  
  5. ; https://cygnus.speccy.cz/download/zx128k_rs232/rs232_paul_farrow_57600_data_sequence_with_cts_flow_control.html
  6. ;   via https://cygnus.speccy.cz/popis_zx-spectrum_dg192k_rs232.php
  7.  
  8. ;==============================================================================
  9. ; RS232 - transmitting through AY-3-8912 without data flow control
  10. ;
  11. ; 57600bps (17.3611μs) 61.57813T on ZX128k, 61T will take 17.19811μs, error -0.9% (58146bps)
  12. ;                      60.76389T on ZX48k,  61T will take 17.42857μs, error +0.4% (57377bps)
  13. ;==============================================================================
  14. ; original author Paul Farrow - this is code disassembled from his RS232 ROM,
  15. ; but only RS232 part
  16.  
  17. RS232_CFGDTR:    ; enable/disable DTR check when sending
  18. ; NOTE: this is actually RTS line, IIRC it was a mistake carried on
  19. ; from the original Interface 1 docs
  20. ; A - flag, A=0 -- DTR disabled, A=0xff -- DTR enabled
  21.     and %01000000   ; Bit 6: RS232  DTR (in)  - 0=Device ready for data,     1=Busy
  22.     ld (DTRFL), a   ; patch the code
  23.     ret
  24.  
  25. RS232_INIT:
  26.         di
  27.         call SET_AY_PORTS
  28.         ei
  29.         ret
  30.  
  31. SET_AY_PORTS:
  32.         ld  bc,$fffd        ; 10T   BC = FFFD, register port
  33.         ld  a,7             ; 7T    select AY register 7
  34.         out (c),a           ; 12T
  35.         ld  a,b             ; 4T    A = 255 / set IO port as output (1 on bit 6) and disable all sound channels
  36.         ld  b,$BF           ; 7T    BC = BFFD, data port
  37.         out (c),a           ; 12T
  38.         ld  b,a             ; 4T    BC = FFFD / AY register port
  39.         ld  a,14            ; 7T    select AY register 14 (I/O port)
  40.         out (c),a           ; 12T
  41.         ld  a,b             ; 4T    A = FF
  42.         ld  b,$BF           ; 7T    BC = BFFD / data port
  43.         out (c),a           ; 12T   write data byte 255, all bits high (like pullups?)
  44.         ret                 ; 10T
  45.  
  46. ; total 10+7+12+4+7+12+4+7+12+7+4+12+10 = 108T
  47.  
  48. RS232_RD_BT:
  49.         di
  50.         call SLOAD_AY_R
  51.         ei
  52.         ret
  53.  
  54. SLOAD_AY_R:
  55.         ld  de,$80FB        ; 10T   D = 1000 0000, E = 1111 1011    (ZX 128k RS232 - *A2, A3, A6, *A7)
  56.         jr  SLOAD_AY        ; 12T   jump to common part
  57.        
  58. SLOAD_AY_K:
  59.         ld  de,$20FE        ; 10T   D = 0010 0000, E = 1111 1110    (ZX 128k Keypad - *A0, A1, A4, *A5)
  60. SLOAD_AY:
  61.         ld  a,e             ; 4T
  62.         ld  e,0             ; 7T
  63.         ld  hl,$BFFF        ; 10T   H = 1011 1111 (191 * 256 + 253 = 49149), L = 1111 1111 (255 * 256 + 253 = 65535)
  64.         ld  bc,$BFFD        ; 10T   AY data port
  65.         out (c),a           ; 12T   set CTS (ZX Spectrum is ready recieve data)
  66.         ld  b,l             ; 4T    B = FF -> BC = FFFD
  67. SLOAD_AY_WAIT:
  68.         in  a,(c)           ; 12T   read control port = IO port - repeat 3 times
  69.         and d               ; 4T    check TxD (data from PC)
  70.         jr  z,SLOAD_AY_RD_1 ; 7/12T Z = start bit
  71.         in  a,(c)           ; 12T
  72.         and d               ; 4T
  73.         jr  z,SLOAD_AY_RD_1 ; 7/12T
  74.         in  a,(c)           ; 12T
  75.         and d               ; 4T
  76.         jr  z,SLOAD_AY_RD_1 ; 7/12T
  77.         dec e               ; 4T    decrement counter
  78.         jr  nz,SLOAD_AY_WAIT; 7/12T wait for start bit again if NZ
  79.         in  a,(c)           ; 12T
  80.         and d               ; 4T
  81.         jr  z,SLOAD_AY_RD_1 ; 7/12T
  82.         ld  a,l             ; 4T    A = FF
  83.         ld  b,h             ; 4T    B = BF -> BC = BFFD (what port is it selecting now?)
  84.         out (c),a           ; 12T
  85.         ld  b,l             ; 4T    B = FF -> BC = FFFD
  86. SLOAD_AY_WAI2:
  87.         in  a,(c)           ; 12T   what port was read here?
  88.         and d               ; 4T
  89.         jr  z,SLOAD_AY_RD_2 ; 7/12T
  90.         in  a,(c)           ; 12T
  91.         and d               ; 4T
  92.         jr  z,SLOAD_AY_RD_2 ; 7/12T
  93.         in  a,(c)           ; 12T
  94.         and d               ; 4T
  95.         jr  z,SLOAD_AY_RD_2 ; 7/12T
  96.         dec e               ; 4T
  97.         jp  nz,SLOAD_AY_WAI2; 10T
  98.         xor a               ; 4T    CF=0
  99.         ret                 ; 10T
  100.  
  101. ; start bit detected, read other bits (this is critical for precize timing)
  102.  
  103. SLOAD_AY_RD_1:  nop         ; 4T    only delay?
  104. SLOAD_AY_RD_2:
  105.         ld  a,l             ; 4T    A = FF
  106.         ld  b,h             ; 4T    B = BF -> BC = BFFD
  107.         out (c),a           ; 12T   write FF to what register? 14?
  108.         ld  e,10000000b     ; 7T    this will be counter to 8
  109.         ld  b,l             ; 4T    B = FF -> BC = FFFD
  110. SLOAD_AY_BITL:
  111.         in  a,(c)           ; 12T   read AY I/O port
  112.         cp  (ix+0)          ; 19T   delay?
  113.         and d               ; 4T    zero irrelevant bits, leave only one (bit 7 for RS232/MIDI connector)
  114.         add a,255           ; 7T    activate carry flag if bit from serial port was H
  115.         rr  e               ; 8T    8x rotate E to right and carry flag copy in bit 7
  116.         jr  nc,SLOAD_AY_BITL; 12/7T carry = last bit was read
  117.         xor a               ; 4T    set Z flag, A = 0, only delay?
  118.         ld  a,e             ; 4T    A = E
  119.         scf                 ; 4T    set carry flag
  120.         ret                 ; 10T
  121.  
  122. ; ZX Spectrum 128k Keypad is using bits
  123. ;   A0  ?   output
  124. ;   A1  ?   output
  125. ;   A4  ?   input
  126. ;   A5  ?   input
  127. ;
  128. ; ZX Spectrum 128k RS232 is using bits
  129. ;   A2  CTS output      RTS
  130. ;   A3  RxD output      TxD
  131. ;   A6  DTR input       CTS
  132. ;   A7  TxD input       RxD
  133.  
  134. RS232_WR_BT:
  135.         di
  136.         push hl, de, bc
  137.         call SSAVE_AY_R
  138.         pop bc, de, hl
  139.         ei
  140.         ret
  141.  
  142. SSAVE_AY_R:
  143. DTRFL    equ $ + 2
  144.         ld  hl,$40F6        ; 10T       H = 0100 0000, L = 1111 0110    mask/bits for RS232/MIDI
  145.         jr  SSAVE_AY        ; 12T
  146.  
  147. SSAVE_AY_K:
  148.         ld  hl,$10FC        ; 10T       H = 0001 0000, L = 1111 1100    mask/bits for KEYPAD
  149. SSAVE_AY:
  150.         ld  d,10            ; 7T        bit counter (start bit + 8 bits + stop bit)
  151.         ld  bc,$FFFD        ; 10T       BC = FFFD / register port AY-3-8912
  152.         cpl                 ; 4T        invert A
  153.         ld  e,a             ; 4T        copy inverted data into E
  154. ; wait for CTS or BREAK
  155. SSAVE_AY_WFSB:  ; THE 'BREAK-KEY' SUBROUTINE https://skoolkid.github.io/rom/asm/1F54.html
  156.         call 0x1F54      ; 17T+(33|53T)  test BREAK / nc = BREAK was pressed
  157.         ret nc              ; 11/5T
  158.         in  a,(c)           ; 12T       read AY I/O port
  159.         and h               ; 4T
  160.         jr   nz,SSAVE_AY_WFSB    ; 12/7T     Z = CTS in low detected
  161.         ld  b,$BF           ; 7T        BC = BFFD / data port AY-3-8912
  162.         scf                 ; 4T        set carry
  163. SSAVE_AY_LOOP:
  164.         jr  c,SSAVE_AY_OVER ; 12/7T
  165.         ld  a,$FE           ; 7T        TxD = 1 (A3/A1)
  166.         jr  SSAVE_AY_OUT    ; 12T
  167.        
  168. SSAVE_AY_OVER:
  169.         ld  a,l             ; 4T        TxD = 0 (A3/A1)
  170.         jp  SSAVE_AY_OUT    ; 10T
  171.  
  172. ; CTS detected from in  12+4+7+7+4+12+4+10 = 60T (still not transmitting anything)
  173. ; start bit from out    12+8+4+12+12+4+10 = 62T
  174. ; bit 1         12+8+4+12+7+7+12 = 62T
  175. ; stop bit (nc)     12+8+4+12+7+7+12 = 62T
  176.  
  177. SSAVE_AY_OUT:
  178.         out (c),a       ; 12T       write to AY I/O port
  179.         srl e           ; 8T        shift right logical - shift data byte, 0 to bit 7, bit 0 to carry
  180.         dec d           ; 4T        decrement bit counter
  181.         jr  nz,SSAVE_AY_LOOP    ; 12/7T     jump if any bit left
  182.         scf             ; 4T
  183.         ret             ; 10T
  184.  
  185. ; after stop bit 12+8+4+7+4+10 = 45T (and more)
  186.  
  187.     ENDMODULE; UART5
  188.  
  189. ; EOF vim: et:ai:ts=4:sw=4:
  190.