home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ABBUC Magazin 60B
/
ABBUC_Magazin_60_2000_ABBUC_Side_B.atr
/
irg.m65
< prev
next >
Wrap
Text File
|
2023-02-26
|
8KB
|
387 lines
; irg.m65: CC65 functions for the infrared gateway (IRG) Version 0.1
; ------------------------------------------------------------------
; Copyright 1994 David Deaven version 0.1
; Permission to use, copy, and distribute this code is granted
; provided that it is not used for commercial applications.
; David Deaven -- deaven@iastate.edu
;
; This ra65 library package provides access to an infrared gateway,
; or IRG, connected to an Atari 400/800/XL/XE 8-bit computer. A
; description of how to build the IRG circuit, which simply plugs into
; a joystick port, can be found in the file README.HARDWARE included
; with this distribution. The functions defined here are:
;
; void IRGinit(int sample, int ton, int toff, int repeat,
; int tonmin, int toffmax, int qtime, int totime)
; int IRGread(char *buffer, int size) = # bytes returned
; int IRGwrite(char *buffer) = 0, or 1 if IRG is active
;
; See the file README for more information, and the C program
; irgdemo.c which demonstrates the use of these functions.
; ------------------------------------------------------------------
rdblen = 128 ; internal read buffer length (<256)
; Some device things that the standard CC65 headers don't have
PACTL = $D302
PORTA = $D300
TRIG0 = $D010
GRACTL = $D01D
; ------------------------------------------------------------------
; Start the vertical blank service routine and set parameters.
;
; void IRGinit(int sample, int ton, int toff, int repeat,
; int tonmin, int toffmax, int qtime, int totime)
;
_irginit:
jsr enterfun ; get all arguments
ldy #16
jsr ldaxysp
sta sample
ldy #14
jsr ldaxysp
sta ton
ldy #12
jsr ldaxysp
sta toff
ldy #10
jsr ldaxysp
sta repeat
ldy #8
jsr ldaxysp
sta tonmin
ldy #6
jsr ldaxysp
sta toffmax
ldy #4
jsr ldaxysp
sta qtime
ldy #2
jsr ldaxysp
sta totime
LDA #%00111001 ; set up PIA
STA PACTL ; output bit A0
LDA #%00000001
STA PORTA
LDA #%00111101
STA PACTL
LDA #0 ; turn IRG output off
STA PORTA
LDA #0
STA nread ; clear read buffer
sta nwrite
sta rdbuf
sta irgstat ; no invalid events
LDA #6 ; new immediate VBLANK
LDX #VImm^
LDY #VImm\
JSR SETVBV
LDA #7 ; new deferred VBLANK
LDX #VBlank^
LDY #VBlank\
JSR SETVBV
jmp exitfun
; ------------------------------------------------------------------
; Read the IRG buffer safely into a user buffer.
;
; int IRGread(char *buffer, int size) = # bytes returned
;
_irgread:
jsr enterfun
ldy #2 ; get arguments
jsr ldaxysp
sta blen
ldy #4
jsr ldaxysp
jsr psave
sta ptr1 ; set to point at buffer
stx ptr1+1
LDX nread
ldy #0 ; # bytes transferred
fine: cpx nwrite ; end of buffer?
beq rddone
LDA rdbuf,x ; transfer one byte
STA (ptr1),Y
iny
INX
CPX #rdblen
BNE skip1
ldx #0
skip1: cmp #0 ; end of buffer?
bne skip2
dey ; zero byte is meaningless, remove
jmp rddone
skip2: cpy blen ; buffer overflow?
bmi fine
rddone: stx nread ; update next read position
tya ; return # bytes
ldy irgstat ; bad buffer?
beq rddo2
lda #0
rddo2: ldx #0
jsr prest
jmp exitfun
; ------------------------------------------------------------------
; Send a buffer out (null-terminated string).
;
; int IRGwrite(char *buffer) = 0, or 1 if IRG is active
;
_irgwrite:
jsr enterfun
ldy #2
jsr ldaxysp
jsr psave
sta ptr1
stx ptr1+1
LDA CRITIC ; is anything else
BEQ ok2 ; going on?
ldax #1 ; if so, don't send
jsr prest
jmp exitfun
ok2: JSR IStop ; stop DMA etc.
lda repeat
sta nwr
wr0: LDY #$FF
LDX #8
loop: INY
LDA (ptr1),Y
BEQ eot
STA bytbuf
sloop: LDA #0
ROL bytbuf
ROL A
STA PORTA
TXA
LDX ton
loop1: JSR DELAY
DEX
BNE loop1
STX PORTA
LDX toff
loop0: JSR DELAY
DEX
BNE loop0
TAX
DEX
BNE sloop
LDX #8
BNE loop
eot: ldx qtime
eot8: jsr delay
dex
bne eot8
dec nwr
bne wr0
JSR IStart ; restart DMA etc
ldax #0
jsr prest
jmp exitfun
nwr: .byte 0
; ------------------------------------------------------------------
; Immediate vertical blank code. Unlike the Atari OS code, if CRITIC is
; set, _nothing_ gets done. This state should not be maintained too
; long, but for the length of an IR packet it's OK.
;
VImm: LDA CRITIC
BEQ cont
JMP XITVBV ; outta here
cont: JMP $E45F ; OS Stage 1
; ------------------------------------------------------------------
; Deferred vertical blank code. Examine TRIG0 for new IR input,
; catch all input by keeping TRIG0 in hardware latch mode. When TRIG0 has
; been low, display DMA is turned off, CRITIC is enabled, and this routine
; becomes the "mainline" code with the interrupt return info still on the
; stack. An attempt is made to read a valid code into the buffer, then
; control is returned to the interrupted code.
;
VBlank: LDA CRITIC
BNE leave ; never happens?
LDA TRIG0
BEQ rec ; IRG has been active
LDA #%100
STA GRACTL ; set TRIG0 latch
leave: JMP XITVBV ; outta here
rec: JSR IStop
LDA #0
STA GRACTL ; clear TRIG0 latch
still: LDX qtime ; detect record gap
LDA #1 ; IR input bit is LSB
wait: JSR Delay
BIT TRIG0
BEQ still ; (input not quiet)
DEX
BNE wait ; we'll wait as long as it takes!
LDY totime ; looking for a "1" bit to start
retry: LDX qtime
mark: BIT TRIG0
BEQ st0 ; got "1", go for it
JSR Delay
DEX
BNE mark
DEY
BNE retry
JMP exit ; time-out, no harm done
st0: LDY #8 ; bit counter
start: LDX #0
wton: JSR Delay
INX
BIT TRIG0
BEQ wton
CPX tonmin ; bit long enough?
BPL okbit
LDA #1 ; bad "1" bit
STA irgstat
JMP exit
okbit: SEC ; store a "1" bit
JSR store
LDX #0 ; wait for "0" to end
wtoff: JSR Delay
INX
BEQ eott ; never? forced EOT (very long "0")
BIT TRIG0
BNE wtoff
CPX qtime ; the space is EOT?
BPL eott
CPX toffmax ; a "0" bit?
BMI start ; normal space
CLC ; store a "0" bit
JSR store
JMP start
eott: CPY #8 ; normal EOT
BEQ done ; last data byte has been written
CLC
JSR store ; pad buffer w/zeroes
JMP eott
done: ldy #8 ; terminate buffer with zero
pad: clc
jsr store
cpy #8
bne pad
LDA #0
STA irgstat ; normal operation
JMP exit
; ------------------------------------------------------------------
; Store bits MSB to LSB in memory at rdbuf
;
; C = bit (0/1)
; X = not saved
; Y = #bits in bytbuf (0-7), 8==0
; A = saved
;
store: ROL bytbuf ; store byte pre-buffer
DEY
BEQ byte
RTS
byte: TAX ; save A
LDA bytbuf
LDY nwrite
STA rdbuf,Y
INY
cpy #rdblen
bne byte1
ldy #0
byte1: cpy nread ; buffer full?
beq over
sty nwrite
LDY #8 ; new byte
TXA
RTS
over: dey ; back off one
cpy #$ff
bne over1
ldy #rdblen
dey
over1: lda #0
sta rdbuf,y ; insert artificial terminator
sty nwrite
PLA ; pop "jsr store" return address
PLA
LDA #2 ; buffer overrun...
STA irgstat ; ...fall through to exit
exit: JSR IStart ; restart DMA etc.
JMP XITVBV ; outta here
; ------------------------------------------------------------------
; Wait one delay time, saving A, X, Y
; time = (20+5*sample) clock pds
;
Delay: PHA ; 3 cycles
TXA ; 2
LDX sample ; 3
dloop: DEX ; 2
BNE dloop ; 3
TAX ; 2
PLA ; 4
RTS ; 6
; ------------------------------------------------------------------
IStop: LDA #0
STA DMACTL ; prevent DMA
LDA #1
STA CRITIC
RTS
IStart: LDA SDMCTL
STA DMACTL ; enable DMA
LDA #0
STA CRITIC
RTS
; ------------------------------------------------------------------
psave: ldy ptr1 ; save system pointer
sty svp1
ldy ptr1+1
sty svp1+1
rts
prest: ldy svp1 ; restore system pointer
sty ptr1
ldy svp1+1
sty ptr1+1
rts
svp1: .word 0
; ------------------------------------------------------------------
nread: .byte 0
nwrite: .byte 0
sample: .byte 2
ton: .byte 20
toff: .byte 20
tonmin: .byte 10
toffmax: .byte 30
qtime: .byte 100
totime: .byte 25
repeat: .byte 3
bytbuf: .byte 0
blen: .byte 0
rdbuf: .blkb rdblen
irgstat: .word 0
.globl _irginit
.globl _irgread
.globl _irgwrite