Interrupt-Serviced 256-Byte Data Buffer from 6502 Applications
[Up to Source Code Repository]
Interrupt-Serviced 256-Byte Data Buffer
An Interrupt-Serviced 256-Byte Data Buffer in 6502 assembly lanauge.
By Lee Davison (leeedavison@googlemail.com), 19 October 2000.
; code for an interrupt serviced data buffer. similar code is used to drive the XY
; stepper motors on a plotter with new position information every 5mS and also to
; allow pen up/down movement time of 70mS
*= $B000 ; set origin (buffer and variables must be in RAM)
Buffer ; 256 byte buffer (must start at page edge)
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
.word $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
BRindx ; buffer read index
.byte $00
BWindx ; buffer write index
.byte $00
Sendf ; am sending flag
.byte $00
WByte ; temp store for the byte to be sent
.byte $00
; write the data to the buffer a byte at a time and increment the pointer.
; the routine is called with the byte to write in A. If the interrupt device
; is idle when this routine is called it will wake it up by doing a BRK
; before it exits
;
; destroys the Y register
*= $C000 ; set origin (can be ROM or RAM)
Incwritb
STA WByte ; save byte to write
LDA BRindx ; get read index
SEC ; set carry for subtract
SBC BWindx ; subtract write index
BEQ Dowrite ; if equal then buffer empty so do write
CMP #$02 ; need at least n+1 bytes to avoid rollover
BCC Incwritb ; loop if no space
; construct and write data to buffer
Dowrite
LDY BWindx ; get write index
LDA WByte ; get byte to write
STA Buffer,Y ; save it
INY ; increment index to next byte
STY BWindx ; save new write index byte
; now see if the interrupt service routine is already running or if it's idle
LDA Sendf ; get the sending flag
BNE Doingit ; skip call if running
BRK ; software call to interrupt routine
NOP ; need this as return from BRK is +1 byte!
CLI ; enable the interrupts
Doingit
RTS
; this is the interrupt service routine. takes a byte a time from the buffer
; and does some thing with it. also sets up the device(s) for the next interrupt
; no registers altered
BuffIRQ
PHA ; save A
TXA ; copy X
PHA ; save X
TYA ; copy Y
PHA ; save Y
; insert code here to ensure this is the interrupt you want. if it isn't then just exit
; quietly via ResExit the end of the routine
Getnext
JSR Increadb ; increment pointer and read byte from buffer
BCS ExitIRQ ; branch if no byte to do
; here would be the guts of the routine such as sending the byte to the ACIA or a
; printer port or some other byte device. it will also ensure the device is set to
; generate an interrupt when it's completed it's task
LDA #$FF ; set byte
STA Sendf ; set sending flag
JMP ResExit ; restore the registers & exit
; all done so clear the flag restore the regs & exit
ExitIRQ
LDA #$00 ; clear byte
STA Sendf ; clear sending flag
ResExit
PLA ; pull Y
TAY ; restore it
PLA ; pull X
TAX ; restore it
PLA ; restore A
RTI ; this was an interrupt service so exit properly
; get byte from the buffer and increment the pointer. If the buffer is empty then
; exit with the carry flag set else exit with carry clear and the byte in A
Increadb
LDY BRindx ; get buffer read index
CPY BWindx ; compare write index
BEQ NOktoread ; branch if empty (= sets carry)
LDA Buffer,Y ; get byte from buffer
INY ; increment pointer
STY BRindx ; save buffer read index
CLC ; clear not ok flag
NOktoread
RTS
Last page update: October 27, 2000.