Use VIA T2, implment output

This commit is contained in:
Gregor Riepl 2022-08-19 15:03:38 +02:00
parent 4a6e099f5f
commit 83cfce2960

View file

@ -24,6 +24,7 @@ BAUD_RATE = 300
; we expect to be loaded somewhere in the middle of user ram
; TODO verify if this is safe with the Editor/Basic 2.0 ROM
; or if there is a way to limit memory usage by the ROM
.org $7000
; entry points
@ -67,7 +68,7 @@ BAUD_RATE = 300
initialized: .byte 0
; saved IRQ vector
oldvector: .word 0
; current CRA value on CA1 change (bit contains the state of CA1)
; state of the CA1 input: bit2=0 low level, bit2=1 high level
ca1state: .byte 0
; output buffer
; this is 16bit, because we need to process start and stop bits as well
@ -116,13 +117,18 @@ BAUD_RATE = 300
lda #<irqhandler
sta IRQVec+1
; the timer is only started when a transmission is actually initiated
; but we'll enable VIA timer 1 interrupt
lda VIA_IER
ora #%01000000
; VIA timer 2 cannot be enabled and disabled on the fly, so we'll
; configure it here and arm it later
; one-shot mode
lda VIA_CR
and #%11011111
sta VIA_CR
; enable interrupt
; interrupt enable is done by setting bit7 and the desired interrupt
; bit in IER to 1 (no need to read-modify-write)
lda #%10100000
sta VIA_IER
; set up the PIA1 and VIA to process I/O
; TXD: VIA PB3, output
lda VIA_DDRB
@ -186,9 +192,9 @@ BAUD_RATE = 300
; IRQ disable
and #%11111110
sta PIA1_CRA
; and the VIA timer 1
lda VIA_IER
and #%10111111
; and the VIA timer 2
; clearing is done by setting bit 7 to 0 and the desired interrupt to 1
lda #%00100000
sta VIA_IER
; we leave the I/O pins and the state alone
@ -336,17 +342,13 @@ BAUD_RATE = 300
rts
; start the timer
@starttimer:
; set up the VIA timer 1 to fire periodically
starttimer:
; arm VIA timer 2 by latching the counter
period = PHI2_CLOCK/BAUD_RATE
lda #>period
sta VIA_T1CL
lda #<period
sta VIA_T1CH
; VIA timer 1 free-run mode
lda VIA_CR
ora #%01000000
sta VIA_CR
; return
rts
@ -398,20 +400,86 @@ BAUD_RATE = 300
sta PIA1_CRA
@handletimer:
; VIA timer 1 fired?
; VIA timer 2 fired?
lda VIA_IFR
and #%01000000
and #%00100000
; zero, no interrupt
beq @irqreturn
; handle timer interrupt
; reset timer 1 interrupt
; FIXME should we do this? perhaps someone else is also expecting a VIA interrupt
; if not, we *must* reset it
lda VIA_T1CL
; timer 2 fired: rearm (we're in one-shot mode!), and clear the interrupt flag
; FIXME this should be done earlier, for more accurate timing
; FIXME we could skip writing the low byte here, writing the high byte is enough
jsr starttimer
@processfifo:
; TODO process input and output
@loadout:
; do we have more bits to send?
lda outshift
; yes, skip loading next byte
bne @shiftout
; load next byte from FIFO
; do we have more bytes?
lda outqlen
; nope, skip ahead to input processing
beq @shiftin
; load length
ldx outqlen
; decrement, also gives the index
dex
; load next byte from fifo
lda outq,x
; store new queue length
stx outqlen
; prepare shift register
; bit0 = start bit = 0
; bit1..7 = data0..6
clc
rol
sta outbuf
; bit8 = data7
; bit9 = stop bit = 1
lda #%00000001
rol
sta outbuf+1
; set shift length
lda #10
sta outshift
@shiftout:
; make sure overflow flag is clear, so we can do unconditional branches
clv
; load shift register bit 0
lda outbuf
and #%00000001
; set or clear?
beq @shiftoutclear
; set output
lda #%00001000
ora VIA_PB
bvc @shiftoutstore
@shiftoutclear:
; clear output
lda #%11110111
and VIA_PB
@shiftoutstore:
sta VIA_PB
; shift the next bit in
; 0 -> high byte -> carry
lsr outbuf+1
; carry -> low byte
ror outbuf
; decrement counter
dec outshift
@shiftin:
; TODO process input bit-bang
@storein:
; TODO process input fifo
@irqreturn:
; restore registers