itty-bitty-vtty/vt100.modem.S

293 lines
3.6 KiB
ArmAsm

lst off
rel
xc
xc
mx %11
cas se
* use vt.equ
SCCBREG equ $c038
SCCAREG equ $c039
SCCBDATA equ $c03a
SCCADATA equ $c03b
SerFlag equ $e10104 ;
*
* scc speed:
*
* time constant = ( clock / (2 * clock mode * baud rate)) - 2
* baud rate = clock / ( 2 * clock mode * (time constant + 2))
*
* clock mode = 1x, 16x, 32x, or 64x (selected via write register 4 bits 6/7)
* clock = 3.6864 MHz crystal (scc runs at 14.31818 / 4 = ~ 3.58 Mhz)
* time constant = write register 12 (low) + 13 (high)
*
*
* see IIgs TN #18 - Do-It-Yourself SCC Access
init_modem ent
* sep #$30
stz q_head
stz q_tail
* reset channel B (modem port)
ldx #9
lda #%01_0_1_0_0_0_1
stx SCCBREG
sta SCCBREG
nop
nop
* x16 clock mode, 1 stop bit, no parity
ldx #4
lda #%01_00_01_0_0
stx SCCBREG
sta SCCBREG
* 8 bits/char, rx disabled.
ldx #3
lda #%11_0_0_0_0_0_0
stx SCCBREG
sta SCCBREG
* 8 data bits, RTS
ldx #5
lda #%0_11_0_0_0_1_0
stx SCCBREG
sta SCCBREG
* bit 7 = 1 for printer port, 0 for modem port.
* 5/6 = (%10) rcv clock = br output
* 4/3 = (%10) tx clock = br output
ldx #11
lda #%0_10_10_0_00
stx SCCBREG
sta SCCBREG
* 9600 baud
ldx #12
lda #10
stx SCCBREG
sta SCCBREG
* 9600 baud
ldx #13
lda #0
stx SCCBREG
sta SCCBREG
* disable baud rate generator
ldx #14
lda #0
stx SCCBREG
sta SCCBREG
* enable baud rate generator
ldx #14
lda #%000_0_0_0_0_1
stx SCCBREG
sta SCCBREG
* 8 bits/char, rx enabled.
ldx #3
lda #%11_0_0_0_0_0_1
stx SCCBREG
sta SCCBREG
* 8 data bits, tx enabled, RTS
ldx #5
lda #%0_11_0_1_0_1_0
stx SCCBREG
sta SCCBREG
* disable interrupts
ldx #15
lda #0
stx SCCBREG
sta SCCBREG
* reset ext/status interrupts
ldx #0
lda #%00_010_0_00
stx SCCBREG
sta SCCBREG
* enable interrupts
ldx #1
* lda #0
lda #%0_0_0_10_0_0_0 ; inr on rx or special condition.
stx SCCBREG
sta SCCBREG
* reset ch b ptr to 0?
lda SCCBREG
* no vector, master interrupts enabled
ldx #9
lda #%00_0_0_1_0_1_0
stx SCCBREG
sta SCCBREG
nop
nop
* adjust SerFlag so serial IRQs will be handled.
lda >SerFlag
ora #%00_000_111 ; channel B interrupts.
sta >SerFlag
rts
write_modem ent
mx %11
* a: byte to send
tay ; save
* ldx #0
:mask = %0010_0100 ; tx buffer empty, clear to send
:wait stz SCCBREG
lda SCCBREG
and #:mask
cmp #:mask
bne :wait
sty SCCBDATA
rts
read_modem_sync ent
* c set if data read
* v set if overrun
mx %11
* ldx #0
rep #$41 ; clear C + V
stz SCCBREG
lda SCCBREG
and #%0001
beq :rts
* read reg 1 for overrun
lda #1
sta SCCBREG
lda SCCBREG
and #%0010_0000
beq :ok
* indicate overrun...
lda #"x"
sta |$07d0+20
* clear the overrun
lda #$30 ; reg0, error reset.
sta SCCBREG
stz SCCBREG
sep #$40 ; V
:ok
* lda #8
* sta SCCBREG
* lda SCCBREG
lda SCCBDATA
* debugging...
ldx :debug
sta $1e00,x
inc :debug
sec
:rts rts
:debug ds 2
buffer equ $1d00
modem_vector ent
jml modem_int
modem_int
*
* called in 8-bit native mode, interrupts disabled.
* d = unknown
* a/x/y don't need to be preserved.
* return carry clear if handled, carry set if not.
* check/clear overrun?
mx %11
phb
phk
plb
stz SCCBREG
lda SCCBREG
and #%0000_0001 ; rx ready.
beq :nope
:read
lda SCCBDATA
ldx q_tail
sta buffer,x
inc q_tail
* more?
stz SCCBREG
lda SCCBREG
and #%0000_0001 ; rx ready.
bne :read
clc
bra :finish
:nope
sec
:finish
* reset errors.
lda #%00_110_000
stz SCCBREG
sta SCCBREG
* reset highest ius
lda #%00_111_000
stz SCCBREG
sta SCCBREG
plb
rtl
read_modem ent
read_modem_async ent
mx %11
php
sei
ldx q_head
cpx q_tail
beq :nope
lda buffer,x
inc q_head
plp
sec
rts
:nope
plp
clc
rts
q_head ds 2
q_tail ds 2
*buffer ds 256
sav vt100.modem.L