nrossi@jarthur.Claremont.EDU (Nick Rossi) (03/12/91)
These routines were written by George Hug and appeared in the February 1989
issue of Transactor magazine. The routines modify (indeed, somewhat replace)
the RS232 routines in the kernal ROM in order to achieve perfect transmission
at 300, 1200, and 2400 baud. The routines may be modified for use on the
C-128 by changing a few lines where indicated.
These routines can easily be modified for your own needs. You may want to
make some improvements, such as a check to prevent the receive buffer from
overflowing (as there is none currently).
This source code is distributed under the premise that material published in
Transactor magazine is public domain.
------------- cut here! ---------------
;--------------------------------------
; "newmodem.src" - 64 mode
; @128 = changes for 128 mode.
;--------------------------------------
ribuf = $f7
robuf = $f9
baudof = $0299
ridbe = $029b
ridbs = $029c
rodbs = $029d
rodbe = $029e
enabl = $02a1
rstkey = $fe56
norest = $fe72
return = $febc
oldout = $f1ca
oldchk = $f21b
findfn = $f30f
devnum = $f31f
nofile = $f701
;--------------------------------------
*= $ce00 ; @128 $1a00
;--------------------------------------
xx00 jmp setup
xx03 jmp inable
xx06 jmp disabl
xx09 jmp rsget
xx0c jmp rsout
nop
strt24 .word $01cb ; 459 start bit times
strt12 .word $0442 ; 1090
strt03 .word $1333 ; 4915
full24 .word $01a5 ; 421 full bit times
full12 .word $034d ; 845
full03 .word $0d52 ; 3410
;--------------------------------------
setup lda #<nmi64 ; @128 #<nmi128
ldy #>nmi64 ; @128 #>nmi128
sta $0318
sty $0319
lda #<nchkin
ldy #>nchkin
sta $031e
sty $031f
lda #<nbsout
ldy #>nbsout
sta $0326
sty $0327
rts
;--------------------------------------
nmi64 pha ; new nmi handler
txa
pha
tya
pha
nmi128 cld
ldx $dd07 ; sample timer b hi byte
lda #$7f ; disable cia nmi's
sta $dd0d
lda $dd0d ; read/clear flags
bpl notcia ; (restore key)
cpx $dd07 ; tb timeout since timer b sampled?
ldy $dd01 ; (sample pin c)
bcs mask ; no
ora #$02 ; yes, set flag in acc.
ora $dd0d ; read/clear flags again
mask and enabl ; mask out non-enabled
tax ; these must be serviced
lsr ; timer a? (bit 0)
bcc ckflag ; no
lda $dd00 ; yes, put but on pin m
and #$fb
ora $b5
sta $dd00
ckflag txa
and #$10 ; *flag nmi (bit 4)
beq nmion ; no
strtlo lda #$42 ; yes, start-bit to tb
sta $dd06
strthi lda #$04
sta $dd07
lda #$11 ; start tb counting
sta $dd0f
lda #$12 ; *flag nmi off, tb on
eor enabl ; update mask
sta enabl
sta $dd0d ; enable new config
fulllo lda #$4d ; change reload latch
sta $dd06 ; to full-bit time
fullhi lda #$03
sta $dd07
lda #$08 ; # of bits to receive
sta $a8
bne chktxd ; branch always
notcia ldy #$00
jmp rstkey ; or jmp norest
nmion lda enabl ; re-enable nmi's
sta $dd0d
txa
and #$02 ; timer b? (bit 1)
beq chktxd ; no
tya ; yes, get sample of pin c
lsr
ror $aa ; rs232 is lsb first
dec $a8 ; byte finished?
bne txd ; no
ldy ridbe ; yes, byte to buffer
lda $aa
sta (ribuf),y ; (no overrun test)
inc ridbe
lda #$00 ; stop timer b
sta $dd0f
lda #$12 ; tb nmi off, *flag on
switch ldy #$7f ; disable nmi's
sty $dd0d ; twice
sty $dd0d
eor enabl ; update mask
sta enabl
sta $dd0d ; enable new config
txd txa
lsr ; timer a?
chktxd bcc exit ; no
dec $b4 ; yes, byte finished?
bmi char ; yes
lda #$04 ; no, prep next bit
ror $b6 ; (fill with stop bits)
bcs store
low lda #$00
store sta $b5
exit jmp return ; restore regs, rti
char ldy rodbs
cpy rodbe ; buffer empty?
beq txoff ; yes
getbuf lda (robuf),y ; no, prep next byte
inc rodbs
sta $b6
lda #$09 ; # bits to send
sta $b4
bne low ; always - do start bit
txoff ldx #$00 ; stop timer a
stx $dd0e
lda #$01 ; disable ta nmi
bne switch ; always
;--------------------------------------
disabl pha ; turns off modem port
test lda enabl
and #$03 ; any current activity?
bne test ; yes, test again
lda #$10 ; no, disable *flag nmi
sta $dd0d
lda #$02
and enabl ; currently receiving?
bne test ; yes, start over
sta enabl ; all off, update mask
pla
rts
;--------------------------------------
nbsout pha ; new bsout
lda $9a
cmp #02
bne notmod
pla
rsout sta $9e ; output to modem
sty $97
point ldy rodbe
sta (robuf),y ; not official till pointer bumped
iny
cpy rodbs ; buffer full?
beq fulbuf ; yes
sty rodbe ; no, bump pointer
strtup lda enabl
and #$01 ; transmitting now?
bne ret3 ; yes
sta $b5 ; no, prep start bit,
lda #$09
sta $b4 ; # bits to send,
ldy rodbs
lda (robuf),y
sta $b6 ; and next byte
inc rodbs
lda baudof ; full tx bit time to ta
sta $dd04
lda baudof+1
sta $dd05
lda #$11 ; start timer a
sta $dd0e
lda #$81 ; enable ta nmi
change sta $dd0d ; nmi clears flag if set
php ; save irq status
sei ; disable irq's
ldy #$7f ; disable nmi's
sty $dd0d ; twice
sty $dd0d
ora enabl ; update mask
sta enabl
sta $dd0d ; enable new config
plp ; restore irq status
ret3 clc
ldy $97
lda $9e
rts
fulbuf jsr strtup
jmp point
notmod pla ; back to old bsout
jmp oldout
;--------------------------------------
nchkin jsr findfn ; new chkin
bne nosuch
jsr devnum
lda $ba
cmp #$02
bne back
sta $99
inable sta $9e ; enable rs232 input
sty $97
baud lda baudof+1 ; set receive to same
and #$06 ; baud rate as xmit
tay
lda strt24,y
sta strtlo+1 ; overwrite values in nmi handler
lda strt24+1,y
sta strthi+1
lda full24,y
sta fulllo+1
lda full24+1,y
sta fullhi+1
lda enabl
and #$12 ; *flag or tb on?
bne ret1 ; yes
sta $dd0f ; no, stop tb
lda #$90 ; turn on flag nmi
jmp change
nosuch jmp nofile
back lda $ba
jmp oldchk
;--------------------------------------
rsget sta $9e ; input from modem
sty $9f
ldy ridbs
cpy ridbe ; buffer empty?
beq ret2 ; yes
lda (ribuf),y ; no, fetch character
sta $9e
inc ridbs
ret1 clc ; cc = char in acc.
ret2 ldy $9f
lda $9e
last rts ; cs = buffer was empty