tlc-apple2/src/bitbangr.asm

109 lines
3.6 KiB
NASM

;
; Bitbang RS-232 (using a pushbutton input in our case)
;
;
; CPU cycle counting must be done to meet bit-time requirements on the wire.
; Bit time is defined as (1 / baud) seconds, or (1000000 / baud) microseconds.
; So at 9600 baud, we get a bit time 0.000104166 seconds, or 104.166 microseconds.
; With a 6502 CPU running at about 1MHz, each CPU clock cycle is about 1.023
; microseconds long.
;
.org $300 ; For now
; Some system constants
WAIT = $FCA8
CROUT = $FD8E
PRBYTE = $FDDA
PRHEX = $FDE3
COUT = $FDED
PRERR = $FF2D
PB0 = $C061 ; Paddle 0 PushButton: HIGH/ON if > 127, LOW/OFF if < 128.
start:
lda #$09 ; We'll be watching for 8 bits plus one stop bit
sta bits
clc
jsr pb0_recv ; Pull a byte from PB0
bcs printit ; Carry set means we got a '1' stop bit, so we're good
jsr CROUT
jsr PRERR ; Else we got a framing error
printit:
ora #$80
jsr COUT ; PRBYTE
lda $25
cmp #$17
bne start
lda #$00
sta $25
beq start
done: rts
pb0_recv:
; State is unknown
poll_for_1:
; sample state
lda PB0
bpl poll_for_1 ; if not negative, branch to wait_for_1
; State is now 1
poll_for_0:
; sample state
lda PB0
bmi poll_for_0 ; if negative, branch to wait_for_0
; State just became 0 (start bit)
; Wait 1.5 bit times (104.2 + 52.1 = 156.3us at 9600 baud) to get into the middle of the first bit
; Approximately 152.8 ($99) CPU cycles
; When falling through to here, the above branch was not taken - consuming 2 cycles to get here
ldx #$14 ; 2 loop count
: nop ; 2 \
dex ; 2 |-- 7 * loop count
bne :- ; 3 / final exit of the loop adds 2, branch not taken
; $90 cycles to get here; need to burn 7 more
beq :+ ; 3
: nop ; 2
nop ; 2
; $97 cycles to get here; save 2 for upcoming clc
pull_byte:
; We now have one bit time (104.2us at 9600 baud) to process this bit
; Approximately 106.6 ($6B) CPU cycles
clc ; 2
lda PB0 ; 4
bmi :+ ; 2 if positive, 3 if negative
jmp push_bit ; 3
: sec ; 2 bit was low/negative
push_bit: ; We now have a bit in the carry
dec bits ; 6
beq byte_complete ; Have we read all 8 bits? Then this bit is the stop bit; leave with carry set
; 2 (in the case we care about, i.e. more bits to read)
lda ring ; 4
ror ; 2
sta ring ; 4
; $1C/$1D cycles to get here (since center of bit time)
; We are now done with processing that bit; we need to cool our heels for the rest ($6B - $1C = $4F) of the
; bit time in order to get into the middle of the next bit
ldx #$0A ; 2 loop count
: nop ; 2 \
dex ; 2 |-- 7 * loop count
bne :- ; 3 / final exit of the loop adds 2, branch not taken
; $48 cycles to get here
nop ; 2
nop ; 2
jmp pull_byte ; 3 Loop around for another bit - we burned $4F cycles
; $6B
byte_complete:
; Carry now holds stop bit (clear/0 indicates framing error, because we end with set/1)
lda ring ; Exit with the assembled byte in A
rts
pb_state: .byte $00
ring: .byte $55
bits: .byte $00