module Uart
 
    assert $ > #8000 ;; Important keep it in FAST memory
 
init:
 
    di
 
    ld a, #07
 
    ld bc, #fffd
 
    out (c), a
 
    ld a, #fc
 
    ld b, #bf
 
    out (c), a ; Enable read mode
 
    
 
    ld a, #0e
 
    ld bc, #fffd
 
    out (c), a
 
 
 
    ld b, #bf
 
    in a, (c)
 
    and #fb
 
    out (c), a ; Make CTS low
 
 
 
    ei
 
    ld b, #ff
 
.flush
 
    halt
 
    djnz .flush
 
    ret
 
 
 
 
 
write:
 
    push hl, de, bc
 
    push af
 
    ld c, #fd ; prepare port addresses
 
    ld d, #ff
 
    ld e, #bf
 
    ld b, d
 
    
 
    ld a, #0e
 
    out (c), a ; Select AY's PORT A
 
 
 
    ld hl, (_baud)
 
    ld de, #0002
 
    or a
 
    sbc hl, de
 
    ex hl, de
 
 
 
    pop af
 
    cpl
 
    scf
 
    ld b, #0b ; Numbers of bits - 1 start, 8 data, 2 stop
 
 
 
    di ; Hard timing starts
 
transmitBit:
 
    push bc
 
    push af
 
 
 
    ld a, #fe
 
    ld h, d
 
    ld l, e
 
    ld bc, #bffd
 
    jp nc, transmitOne
 
; Transmit Zero:
 
    and #f7
 
    out (c), a
 
    jr transmitNext
 
transmitOne:
 
    or 8
 
    out (c), a
 
    jr transmitNext
 
 
 
transmitNext:
 
    dec hl
 
    ld a, h 
 
    or l
 
    jr nz, transmitNext
 
    
 
    nop
 
    nop
 
    nop
 
 
 
    pop af
 
    pop bc
 
    or a
 
    rra 
 
    djnz transmitBit
 
    exx
 
    ei
 
    pop bc, de, hl
 
    ret
 
 
 
read:
 
    push bc, de, hl
 
    call uartRead
 
    pop hl, de, bc
 
    ret c
 
    jr read
 
 
 
uartRead:
 
    ld hl, _isSecondByteAvail
 
    ld a, (hl)
 
    and a 
 
    jr z, startReadByte
 
    ld (hl), 0
 
    inc hl
 
    ld a, (hl)
 
    scf
 
    ret
 
startReadByte:
 
    di
 
    xor a
 
    exx
 
    ld de, (_baud) 
 
    ld hl, (_baud)
 
    srl h 
 
    rr l  ; HL=_baud/2
 
    or a 
 
    ld b, #FA ; Wait look length
 
    exx
 
    ld c, #fd
 
    ld d, #ff
 
    ld e, #bf
 
    ld b, d 
 
    ld a, #0e
 
    out (c), a
 
    in a, (c)
 
    or #f0      ; Input lines is 1
 
    and #fb     ; CTS force to 0
 
    ld b, e     ; B = #BF
 
    out (c), a  ; Make CTS high
 
    ld h, a
 
 
 
waitStartBit:
 
    ld b, d
 
    in a, (c)
 
    and #80
 
    jr z, startBitFound
 
readTimeOut:
 
    exx
 
    dec b 
 
    exx
 
    jr nz, waitStartBit
 
    xor a
 
    push af
 
    jr readFinish
 
startBitFound:
 
    in a, (c)
 
    and #80
 
    jr nz, readTimeOut
 
 
 
    in a, (c)
 
    and #80
 
    jr nz, readTimeOut
 
    ;; Start bit found!
 
    
 
    exx
 
    ld bc, #fffd
 
    ld a, #80
 
    ex af, af
 
readTune:
 
    add hl, de ; HL = 1.5 * _baud
 
    nop
 
    nop
 
    nop
 
    nop ; Fine tuning delay
 
 
 
bdDelay:
 
    dec hl
 
    ld a, h
 
    or l 
 
    jr nz, bdDelay
 
 
 
    in a, (c)
 
    and #80
 
    jp z, zeroReceived
 
; One received:       
 
    ex af, af
 
    scf
 
    rra 
 
    jr c, receivedByte
 
    ex af, af
 
    jp readTune
 
zeroReceived:
 
    ex af, af
 
    or a 
 
    RRA 
 
    jr c, receivedByte
 
    ex af, af
 
    jp readTune
 
receivedByte:
 
    scf
 
    push af
 
    exx
 
readFinish: 
 
    ld a, h
 
    or #04 
 
    ld b, e
 
    out (c), a
 
    
 
    exx 
 
    ld h, d
 
    ld l, e 
 
 
 
    ld bc, #0007
 
    or a 
 
    sbc hl, bc
 
 
 
delayForStopBit:
 
    dec hl
 
    ld a, h
 
    or l
 
    jr nz, delayForStopBit
 
 
 
    ld bc, #fffd
 
    add hl, de
 
    add hl, de
 
    add hl, de
 
 
 
waitStartBitSecondByte:
 
    in a, (c)
 
    and #80
 
    jr z, secondStartBitFound
 
    dec hl
 
    ld a, h
 
    or l
 
    jr nz, waitStartBitSecondByte
 
    ; No second byte
 
    pop af
 
    ei
 
    ret
 
 
 
secondStartBitFound:
 
    in a, (c)
 
    and #80
 
    jr nz, waitStartBitSecondByte
 
    ld h, d
 
    ld l, e 
 
    ld bc, #0002
 
    srl h
 
    rr l
 
    or a 
 
    sbc hl, bc
 
    ld bc, #fffd
 
    ld a, #80
 
    ex af, af
 
secondByteTune:
 
    nop
 
    nop
 
    nop
 
    nop
 
    add hl, de
 
 
 
secondDelay:
 
    dec hl
 
    ld a, h
 
    or l
 
    jr nz, secondDelay
 
 
 
    in a, (c)
 
    and #80
 
    jr z, secondZeroReceived
 
; Second 1 received    
 
    ex af, af
 
    scf 
 
    rra 
 
    jr c, secondByteFinished
 
    ex af, af
 
    jp secondByteTune
 
 
 
secondZeroReceived:
 
    ex af, af
 
    or a 
 
    rra 
 
    jr c, secondByteFinished
 
    ex af, af
 
    jp secondByteTune
 
secondByteFinished:
 
    ld hl, _isSecondByteAvail
 
    ld (hl), 1
 
    inc hl 
 
    ld (hl), a
 
    pop af 
 
    ei 
 
    ret
 
 
 
 
 
_baud dw 11 ; 54 - 2400 --- 25 - 4800 --- 11 - 9600
 
_isSecondByteAvail dw #0
 
_testByte dw #0
 
 
 
    endmodule