Added a serial driver for the builtin 6551 of the Plus/4 (untested, but taken
mostly from the C64 version which is tested and works). Improved interrupt handling (was needed for the driver). git-svn-id: svn://svn.cc65.org/cc65/trunk@2754 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
ba079ae6a1
commit
ad6a85b255
5 changed files with 509 additions and 86 deletions
|
@ -1 +1,4 @@
|
|||
*.emd
|
||||
*.joy
|
||||
*.ser
|
||||
*.tgi
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
%.joy: %.o ../runtime/zeropage.o
|
||||
@$(LD) -t module -o $@ $^
|
||||
|
||||
%.ser: %.o ../runtime/zeropage.o
|
||||
@$(LD) -t module -o $@ $^
|
||||
|
||||
%.tgi: %.o ../runtime/zeropage.o
|
||||
@$(LD) -t module -o $@ $^
|
||||
|
||||
|
@ -73,6 +76,8 @@ EMDS =
|
|||
|
||||
JOYS = plus4-stdjoy.joy
|
||||
|
||||
SERS = plus4-stdser.ser
|
||||
|
||||
TGIS =
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
|
@ -80,14 +85,14 @@ TGIS =
|
|||
|
||||
.PHONY: all clean zap
|
||||
|
||||
all: $(OBJS) $(EMDS) $(JOYS) $(TGIS)
|
||||
all: $(OBJS) $(EMDS) $(JOYS) $(SERS) $(TGIS)
|
||||
|
||||
../runtime/zeropage.o:
|
||||
$(MAKE) -C $(dir $@) $(notdir $@)
|
||||
|
||||
clean:
|
||||
@$(RM) $(OBJS) $(EMDS:.emd=.o) $(JOYS:.joy=.o) $(TGIS:.tgi=.o)
|
||||
@$(RM) $(OBJS) $(EMDS:.emd=.o) $(JOYS:.joy=.o) $(SERS:.ser=.o) $(TGIS:.tgi=.o)
|
||||
|
||||
zap: clean
|
||||
@$(RM) $(EMDS) $(JOYS) $(TGIS)
|
||||
@$(RM) $(EMDS) $(JOYS) $(SERS) $(TGIS)
|
||||
|
||||
|
|
|
@ -55,11 +55,12 @@ uservec: jmp $FFFF ; Patched at runtime
|
|||
|
||||
|
||||
|
||||
; Break handler, called if a break occurs. Note: Y is not on the stack!
|
||||
; Break handler, called if a break occurs.
|
||||
|
||||
.proc brk_handler
|
||||
|
||||
sty _brk_y
|
||||
pla
|
||||
sta _brk_y
|
||||
pla
|
||||
sta _brk_x
|
||||
pla
|
||||
|
|
|
@ -55,20 +55,6 @@ L1: lda sp,x
|
|||
lda #14
|
||||
jsr $FFD2 ; BSOUT
|
||||
|
||||
; Setup the IRQ vector in the banked RAM and switch off the ROM
|
||||
|
||||
sei ; No ints, handler not yet in place
|
||||
sta ENABLE_RAM
|
||||
lda #<IRQ
|
||||
sta $FFFE ; Install interrupt handler
|
||||
lda #>IRQ
|
||||
sta $FFFF
|
||||
cli ; Allow interrupts
|
||||
|
||||
; Clear the BSS data
|
||||
|
||||
jsr zerobss
|
||||
|
||||
; Save system stuff and setup the stack. The stack starts at the top of the
|
||||
; usable RAM.
|
||||
|
||||
|
@ -80,44 +66,39 @@ L1: lda sp,x
|
|||
lda #>$FD00
|
||||
sta sp+1
|
||||
|
||||
; Setup the IRQ vector in the banked RAM and switch off the ROM
|
||||
|
||||
ldx #<IRQ
|
||||
ldy #>IRQ
|
||||
sei ; No ints, handler not yet in place
|
||||
sta ENABLE_RAM
|
||||
stx $FFFE ; Install interrupt handler
|
||||
sty $FFFF
|
||||
cli ; Allow interrupts
|
||||
|
||||
; Clear the BSS data
|
||||
|
||||
jsr zerobss
|
||||
|
||||
; Call module constructors
|
||||
|
||||
jsr initlib
|
||||
|
||||
; If we have IRQ functions, chain our stub into the IRQ vector
|
||||
; Initialize irqcount, which means that from now own custom linked in IRQ
|
||||
; handlers (via condes) will be called.
|
||||
|
||||
lda #<__IRQFUNC_COUNT__
|
||||
beq NoIRQ1
|
||||
lda IRQVec
|
||||
ldx IRQVec+1
|
||||
sta IRQInd+1
|
||||
stx IRQInd+2
|
||||
lda #<IRQStub
|
||||
ldx #>IRQStub
|
||||
sei
|
||||
sta IRQVec
|
||||
stx IRQVec+1
|
||||
cli
|
||||
lda #.lobyte(__IRQFUNC_COUNT__*2)
|
||||
sta irqcount
|
||||
|
||||
; Push arguments and call main()
|
||||
|
||||
NoIRQ1: jsr callmain
|
||||
jsr callmain
|
||||
|
||||
; Back from main (this is also the _exit entry). Reset the IRQ vector if
|
||||
; we chained it.
|
||||
; Back from main (this is also the _exit entry). Run module destructors.
|
||||
|
||||
_exit: lda #<__IRQFUNC_COUNT__
|
||||
beq NoIRQ2
|
||||
lda IRQInd+1
|
||||
ldx IRQInd+2
|
||||
sei
|
||||
sta IRQVec
|
||||
stx IRQVec+1
|
||||
cli
|
||||
|
||||
; Run module destructors.
|
||||
|
||||
NoIRQ2: jsr donelib ; Run module destructors
|
||||
_exit: lda #0
|
||||
sta irqcount ; Disable custom IRQ handlers
|
||||
jsr donelib ; Run module destructors
|
||||
|
||||
; Restore system stuff
|
||||
|
||||
|
@ -139,30 +120,57 @@ L2: lda zpsave,x
|
|||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; IRQ handler
|
||||
; IRQ handler. The handler in the ROM enables the kernal and jumps to
|
||||
; $CE00, where the ROM code checks for a BRK or IRQ and branches via the
|
||||
; indirect vectors at $314/$316.
|
||||
; To make our stub as fast as possible, we skip the whole part of the ROM
|
||||
; handler and jump to the indirect vectors directly. We do also call our
|
||||
; own interrupt handlers if we have any, so they need not use $314.
|
||||
|
||||
.segment "LOWCODE"
|
||||
|
||||
IRQ: pha
|
||||
IRQ: cld ; Just to be sure
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
tsx ; Get the stack pointer
|
||||
lda $0103,x ; Get the saved status register
|
||||
tax ; Save for later
|
||||
lda $0104,x ; Get the saved status register
|
||||
and #$10 ; Test for BRK bit
|
||||
bne dobreak
|
||||
lda #>irq_ret ; Push new return address
|
||||
|
||||
; It's an IRQ and RAM is enabled. If we have handlers, call them. We will use
|
||||
; a flag here instead of loading __IRQFUNC_COUNT__ directly, since the condes
|
||||
; function is not reentrant. The irqcount flag will be set/reset from the main
|
||||
; code, to avoid races.
|
||||
|
||||
ldy irqcount
|
||||
beq @L1
|
||||
lda #<__IRQFUNC_TABLE__
|
||||
ldx #>__IRQFUNC_TABLE__
|
||||
jsr condes ; Call the IRQ functions
|
||||
|
||||
; Since the ROM handler will end with an RTI, we have to fake an IRQ return
|
||||
; on stack, so we get control of the CPU after the ROM handler and can switch
|
||||
; back to RAM.
|
||||
|
||||
@L1: lda #>irq_ret ; Push new return address
|
||||
pha
|
||||
lda #<irq_ret
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
php ; Push faked IRQ frame on stack
|
||||
pha ; Push faked A register
|
||||
pha ; Push faked X register
|
||||
pha ; Push faked Y register
|
||||
sta ENABLE_ROM ; Switch to ROM
|
||||
jmp ($FFFE) ; Jump to kernal irq handler
|
||||
jmp (IRQVec) ; Jump indirect to kernal irq handler
|
||||
|
||||
irq_ret:
|
||||
sta ENABLE_RAM ; Switch back to RAM
|
||||
pla
|
||||
tay
|
||||
pla
|
||||
tax
|
||||
pla
|
||||
rti
|
||||
|
@ -175,27 +183,9 @@ dobreak:
|
|||
; No break handler installed, jump to ROM
|
||||
|
||||
nohandler:
|
||||
tya
|
||||
pha ; ROM handler expects Y on stack
|
||||
sta ENABLE_ROM
|
||||
jmp (BRKVec) ; Jump indirect to the break vector
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Stub for the IRQ chain. Is used only if there are IRQs defined. Needed in
|
||||
; low memory because of the banking.
|
||||
|
||||
.segment "LOWCODE"
|
||||
|
||||
IRQStub:
|
||||
cld ; Just to be sure
|
||||
sta ENABLE_RAM ; Switch to RAM
|
||||
ldy #<(__IRQFUNC_COUNT__*2)
|
||||
lda #<__IRQFUNC_TABLE__
|
||||
ldx #>__IRQFUNC_TABLE__
|
||||
jsr condes ; Call the IRQ functions
|
||||
sta ENABLE_ROM
|
||||
jmp IRQInd ; Jump to the saved IRQ vector
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Data
|
||||
|
||||
|
@ -205,8 +195,8 @@ zpsave: .res zpspace
|
|||
; BRK handling
|
||||
brk_jmp: jmp $0000
|
||||
|
||||
.bss
|
||||
spsave: .res 1
|
||||
|
||||
|
||||
.bss
|
||||
irqcount: .byte 0
|
||||
|
||||
|
|
424
libsrc/plus4/plus4-stdser.s
Normal file
424
libsrc/plus4/plus4-stdser.s
Normal file
|
@ -0,0 +1,424 @@
|
|||
;
|
||||
; Serial driver for the builtin 6551 ACIA of the Plus/4.
|
||||
;
|
||||
; Ullrich von Bassewitz, 2003-12-13
|
||||
;
|
||||
; The driver is based on the cc65 rs232 module, which in turn is based on
|
||||
; Craig Bruce device driver for the Switftlink/Turbo-232.
|
||||
;
|
||||
; SwiftLink/Turbo-232 v0.90 device driver, by Craig Bruce, 14-Apr-1998.
|
||||
;
|
||||
; This software is Public Domain. It is in Buddy assembler format.
|
||||
;
|
||||
; This device driver uses the SwiftLink RS-232 Serial Cartridge, available from
|
||||
; Creative Micro Designs, Inc, and also supports the extensions of the Turbo232
|
||||
; Serial Cartridge. Both devices are based on the 6551 ACIA chip. It also
|
||||
; supports the "hacked" SwiftLink with a 1.8432 MHz crystal.
|
||||
;
|
||||
; The code assumes that the kernal + I/O are in context. On the C128, call
|
||||
; it from Bank 15. On the C64, don't flip out the Kernal unless a suitable
|
||||
; NMI catcher is put into the RAM under then Kernal. For the SuperCPU, the
|
||||
; interrupt handling assumes that the 65816 is in 6502-emulation mode.
|
||||
;
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "ser-kernel.inc"
|
||||
.include "ser-error.inc"
|
||||
.include "plus4.inc"
|
||||
|
||||
|
||||
; ------------------------------------------------------------------------
|
||||
; Header. Includes jump table
|
||||
|
||||
.segment "JUMPTABLE"
|
||||
|
||||
; Driver signature
|
||||
|
||||
.byte $73, $65, $72 ; "ser"
|
||||
.byte SER_API_VERSION ; Serial API version number
|
||||
|
||||
; Jump table.
|
||||
|
||||
.word INSTALL
|
||||
.word UNINSTALL
|
||||
.word OPEN
|
||||
.word CLOSE
|
||||
.word GET
|
||||
.word PUT
|
||||
.word STATUS
|
||||
.word IOCTL
|
||||
.word IRQ
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; I/O definitions
|
||||
|
||||
ACIA = $DE00
|
||||
ACIA_DATA = ACIA+0 ; Data register
|
||||
ACIA_STATUS = ACIA+1 ; Status register
|
||||
ACIA_CMD = ACIA+2 ; Command register
|
||||
ACIA_CTRL = ACIA+3 ; Control register
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
;
|
||||
; Global variables
|
||||
;
|
||||
|
||||
.bss
|
||||
RecvHead: .res 1 ; Head of receive buffer
|
||||
RecvTail: .res 1 ; Tail of receive buffer
|
||||
RecvFreeCnt: .res 1 ; Number of bytes in receive buffer
|
||||
SendHead: .res 1 ; Head of send buffer
|
||||
SendTail: .res 1 ; Tail of send buffer
|
||||
SendFreeCnt: .res 1 ; Number of bytes in send buffer
|
||||
|
||||
Stopped: .res 1 ; Flow-stopped flag
|
||||
RtsOff: .res 1 ;
|
||||
|
||||
; Send and receive buffers: 256 bytes each
|
||||
RecvBuf: .res 256
|
||||
SendBuf: .res 256
|
||||
|
||||
.rodata
|
||||
|
||||
; Tables used to translate RS232 params into register values
|
||||
|
||||
BaudTable: ; bit7 = 1 means setting is invalid
|
||||
.byte $FF ; SER_BAUD_45_5
|
||||
.byte $01 ; SER_BAUD_50
|
||||
.byte $02 ; SER_BAUD_75
|
||||
.byte $03 ; SER_BAUD_110
|
||||
.byte $04 ; SER_BAUD_134_5
|
||||
.byte $05 ; SER_BAUD_150
|
||||
.byte $06 ; SER_BAUD_300
|
||||
.byte $07 ; SER_BAUD_600
|
||||
.byte $08 ; SER_BAUD_1200
|
||||
.byte $09 ; SER_BAUD_1800
|
||||
.byte $0A ; SER_BAUD_2400
|
||||
.byte $0B ; SER_BAUD_3600
|
||||
.byte $0C ; SER_BAUD_4800
|
||||
.byte $0D ; SER_BAUD_7200
|
||||
.byte $0E ; SER_BAUD_9600
|
||||
.byte $0F ; SER_BAUD_19200
|
||||
.byte $FF ; SER_BAUD_38400
|
||||
.byte $FF ; SER_BAUD_57600
|
||||
.byte $FF ; SER_BAUD_115200
|
||||
.byte $FF ; SER_BAUD_230400
|
||||
|
||||
BitTable:
|
||||
.byte $60 ; SER_BITS_5
|
||||
.byte $40 ; SER_BITS_6
|
||||
.byte $20 ; SER_BITS_7
|
||||
.byte $00 ; SER_BITS_8
|
||||
|
||||
StopTable:
|
||||
.byte $00 ; SER_STOP_1
|
||||
.byte $80 ; SER_STOP_2
|
||||
|
||||
ParityTable:
|
||||
.byte $00 ; SER_PAR_NONE
|
||||
.byte $20 ; SER_PAR_ODD
|
||||
.byte $60 ; SER_PAR_EVEN
|
||||
.byte $A0 ; SER_PAR_MARK
|
||||
.byte $E0 ; SER_PAR_SPACE
|
||||
|
||||
.code
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; INSTALL routine. Is called after the driver is loaded into memory. If
|
||||
; possible, check if the hardware is present.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
;
|
||||
; Since we don't have to manage the IRQ vector on the Plus/4, this is actually
|
||||
; the same as:
|
||||
;
|
||||
; UNINSTALL routine. Is called before the driver is removed from memory.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
|
||||
|
||||
INSTALL:
|
||||
UNINSTALL:
|
||||
|
||||
; Deactivate DTR and disable 6551 interrupts
|
||||
|
||||
lda #%00001010
|
||||
sta ACIA_CMD
|
||||
|
||||
; Done, return an error code
|
||||
|
||||
lda #<SER_ERR_OK
|
||||
tax ; A is zero
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; PARAMS routine. A pointer to a ser_params structure is passed in ptr1.
|
||||
; Must return an SER_ERR_xx code in a/x.
|
||||
|
||||
OPEN:
|
||||
|
||||
; Check if the handshake setting is valid
|
||||
|
||||
ldy #SER_PARAMS::HANDSHAKE ; Handshake
|
||||
lda (ptr1),y
|
||||
cmp #SER_HS_HW ; This is all we support
|
||||
bne InvParam
|
||||
|
||||
; Initialize buffers
|
||||
|
||||
jsr InitBuffers
|
||||
|
||||
; Set the value for the control register, which contains stop bits, word
|
||||
; length and the baud rate.
|
||||
|
||||
ldy #SER_PARAMS::BAUDRATE
|
||||
lda (ptr1),y ; Baudrate index
|
||||
tay
|
||||
lda BaudTable,y ; Get 6551 value
|
||||
bmi InvBaud ; Branch if rate not supported
|
||||
sta tmp1
|
||||
|
||||
ldy #SER_PARAMS::DATABITS ; Databits
|
||||
lda (ptr1),y
|
||||
tay
|
||||
lda BitTable,y
|
||||
ora tmp1
|
||||
sta tmp1
|
||||
|
||||
ldy #SER_PARAMS::STOPBITS ; Stopbits
|
||||
lda (ptr1),y
|
||||
tay
|
||||
lda StopTable,y
|
||||
ora tmp1
|
||||
ora #%00010000 ; Receiver clock source = baudrate
|
||||
sta ACIA_CTRL
|
||||
|
||||
; Set the value for the command register. We remember the base value in
|
||||
; RtsOff, since we will have to manipulate ACIA_CMD often.
|
||||
|
||||
ldy #SER_PARAMS::PARITY ; Parity
|
||||
lda (ptr1),y
|
||||
tay
|
||||
lda ParityTable,y
|
||||
ora #%00000001 ; DTR active
|
||||
sta RtsOff
|
||||
ora #%00001000 ; Enable receive interrupts
|
||||
sta ACIA_CMD
|
||||
|
||||
; Done
|
||||
|
||||
lda #<SER_ERR_OK
|
||||
tax ; A is zero
|
||||
rts
|
||||
|
||||
; Invalid parameter
|
||||
|
||||
InvParam:
|
||||
lda #<SER_ERR_INIT_FAILED
|
||||
ldx #>SER_ERR_INIT_FAILED
|
||||
rts
|
||||
|
||||
; Baud rate not available
|
||||
|
||||
InvBaud:
|
||||
lda #<SER_ERR_BAUD_UNAVAIL
|
||||
ldx #>SER_ERR_BAUD_UNAVAIL
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; CLOSE: Close the port, disable interrupts and flush the buffer. Called
|
||||
; without parameters. Must return an error code in a/x.
|
||||
;
|
||||
|
||||
CLOSE:
|
||||
|
||||
; Stop interrupts, drop DTR
|
||||
|
||||
lda #%00001010
|
||||
sta ACIA_CMD
|
||||
|
||||
; Initalize buffers.
|
||||
|
||||
jsr InitBuffers
|
||||
|
||||
; Return OK
|
||||
|
||||
lda #<SER_ERR_OK
|
||||
tax ; A is zero
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; GET: Will fetch a character from the receive buffer and store it into the
|
||||
; variable pointer to by ptr1. If no data is available, SER_ERR_NO_DATA is
|
||||
; return.
|
||||
;
|
||||
|
||||
GET: ldx SendFreeCnt ; Send data if necessary
|
||||
inx ; X == $FF?
|
||||
beq @L1
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
|
||||
; Check for buffer empty
|
||||
|
||||
@L1: lda RecvFreeCnt ; (25)
|
||||
cmp #$ff
|
||||
bne @L2
|
||||
lda #<SER_ERR_NO_DATA
|
||||
ldx #>SER_ERR_NO_DATA
|
||||
rts
|
||||
|
||||
; Check for flow stopped & enough free: release flow control
|
||||
|
||||
@L2: ldx Stopped ; (34)
|
||||
beq @L3
|
||||
cmp #63
|
||||
bcc @L3
|
||||
lda #$00
|
||||
sta Stopped
|
||||
lda RtsOff
|
||||
ora #%00001000
|
||||
sta ACIA_CMD
|
||||
|
||||
; Get byte from buffer
|
||||
|
||||
@L3: ldx RecvHead ; (41)
|
||||
lda RecvBuf,x
|
||||
inc RecvHead
|
||||
inc RecvFreeCnt
|
||||
ldx #$00 ; (59)
|
||||
sta (ptr1,x)
|
||||
txa ; Return code = 0
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; PUT: Output character in A.
|
||||
; Must return an error code in a/x.
|
||||
;
|
||||
|
||||
PUT:
|
||||
|
||||
; Try to send
|
||||
|
||||
ldx SendFreeCnt
|
||||
inx ; X = $ff?
|
||||
beq @L2
|
||||
pha
|
||||
lda #$00
|
||||
jsr TryToSend
|
||||
pla
|
||||
|
||||
; Put byte into send buffer & send
|
||||
|
||||
@L2: ldx SendFreeCnt
|
||||
bne @L3
|
||||
lda #<SER_ERR_OVERFLOW ; X is already zero
|
||||
rts
|
||||
|
||||
@L3: ldx SendTail
|
||||
sta SendBuf,x
|
||||
inc SendTail
|
||||
dec SendFreeCnt
|
||||
lda #$ff
|
||||
jsr TryToSend
|
||||
lda #<SER_ERR_OK
|
||||
tax
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; STATUS: Return the status in the variable pointed to by ptr1.
|
||||
; Must return an error code in a/x.
|
||||
;
|
||||
|
||||
STATUS: lda ACIA_STATUS
|
||||
ldx #0
|
||||
sta (ptr1,x)
|
||||
txa ; SER_ERR_OK
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl
|
||||
; specific data in ptr1, and the ioctl code in A.
|
||||
; Must return an error code in a/x.
|
||||
;
|
||||
|
||||
IOCTL: lda #<SER_ERR_INV_IOCTL ; We don't support ioclts for now
|
||||
ldx #>SER_ERR_INV_IOCTL
|
||||
; rts ; Run into IRQ instead
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; IRQ: Called from the builtin runtime IRQ handler as a subroutine. All
|
||||
; registers are already save, no parameters are passed and no return code
|
||||
; is expected.
|
||||
;
|
||||
|
||||
IRQ: lda ACIA_STATUS ; Check ACIA status for receive interrupt
|
||||
and #$08
|
||||
beq @L9 ; Jump if no ACIA interrupt
|
||||
lda ACIA_DATA ; Get byte from ACIA
|
||||
ldx RecvFreeCnt ; Check if we have free space left
|
||||
beq @L1 ; Jump if no space in receive buffer
|
||||
ldy RecvTail ; Load buffer pointer
|
||||
sta RecvBuf,y ; Store received byte in buffer
|
||||
inc RecvTail ; Increment buffer pointer
|
||||
dec RecvFreeCnt ; Decrement free space counter
|
||||
cpx #33 ; Check for buffer space low
|
||||
bcc @L1 ; Assert flow control if buffer space low
|
||||
@L9: rts
|
||||
|
||||
; Assert flow control if buffer space too low
|
||||
|
||||
@L1: lda RtsOff
|
||||
sta ACIA_CMD
|
||||
sta Stopped
|
||||
rts
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Try to send a byte. Internal routine. A = TryHard
|
||||
|
||||
.proc TryToSend
|
||||
|
||||
sta tmp1 ; Remember tryHard flag
|
||||
@L0: lda SendFreeCnt
|
||||
cmp #$ff
|
||||
beq @L3 ; Bail out
|
||||
|
||||
; Check for flow stopped
|
||||
|
||||
@L1: lda Stopped
|
||||
bne @L3 ; Bail out
|
||||
|
||||
; Check that swiftlink is ready to send
|
||||
|
||||
@L2: lda ACIA_STATUS
|
||||
and #$10
|
||||
bne @L4
|
||||
bit tmp1 ;keep trying if must try hard
|
||||
bmi @L0
|
||||
@L3: rts
|
||||
|
||||
; Send byte and try again
|
||||
|
||||
@L4: ldx SendHead
|
||||
lda SendBuf,x
|
||||
sta ACIA_DATA
|
||||
inc SendHead
|
||||
inc SendFreeCnt
|
||||
jmp @L0
|
||||
|
||||
.endproc
|
||||
|
||||
|
||||
;----------------------------------------------------------------------------
|
||||
; Initialize buffers
|
||||
|
||||
InitBuffers:
|
||||
ldx #0
|
||||
stx Stopped
|
||||
stx RecvHead
|
||||
stx RecvTail
|
||||
stx SendHead
|
||||
stx SendTail
|
||||
dex ; X = 255
|
||||
stx RecvFreeCnt
|
||||
stx SendFreeCnt
|
||||
rts
|
||||
|
Loading…
Add table
Reference in a new issue