;
TITLE EUMEL fuer RUC 64180, 6502 Teil & Diskroutinen
;
;****************************************************************
;
; EUMEL 1.8.0 with RUC180-Card on BASIS 108
;
; 6502 DISK-Driver und Motherboard I/O
;
; Stand (1.8) : 14.01.87, mit neuem Puffer-Handling
; : 27.05.87, mit Hardcopy auf SHIFT CTRL F12
; : 26.06.87, Druckerspooler loeschen mit Task 8
; Version 23.09.85 ./. 22.11.85
;
;****************************************************************
;
.6502
.radix 16
;
;----------------------------------------------------------------
;
; Globale Variable
;
GLOBAL DES6502, PRG6502, LEN65, ST6502
;
;----------------------------------------------------------------
;
; Konstanten
;
XOFF EQU 13 ; CTRL-S
XON EQU 11 ; CTRL-Q
;
; Adressen
;
KeyBoard equ 0C000
Keyext equ 0C008
KeyStr equ 0C010
VIDBNK equ 0C00C
prackn equ 0C1C1
prport equ 0C090
speaker equ 0C030
serial_stat equ 0C099
SER_DAT EQU 0C098H ;Serial Interface Data
SER_COM EQU 0C09AH ;Serial Command Register
SER_CTR EQU 0C09BH ;Serial Control Register
analog_1 EQU $C063
analogreset EQU $C070
; Floppy Hardware
phase0 equ 0C080
phase1 equ 0C082
phase2 equ 0C084
phase3 equ 0C086
mtroff equ 0C088
mtron equ 0C089
drive0 equ 0C08A
Q6off equ 0C08C
Q6on equ 0C08D
Rstate equ 0C08E
Wstate equ 0C08F
;
INCLUDE ZPAGE.INC ;Zero Page Adressen
;
; sonstiges
;
bit_z equ 24
fast_step equ $0E ; etwas weniger als 3 ms Track-Wechselzeit
pagerr macro adr
if high(*-start) ne high(adr-start)
.printx 'Page-Error'
endif
endm
cseg
PRG6502:
.phase 0C00
DES6502: ; 6502-Startadresse zum kopieren
start: ; Label fuer Pageboundcheck
nible1: ; Anfang des Nibble-Buffers
defm '6502-Teil'
ST6502: ; Startadresse 6502-Teil Initialisierung
include BOOT.INC
include NIBLE.INC
write_data
SEC
LDA Q6on,X
LDA Rstate,X
BMI wrdat99
LDA nible2
STA temp2
LDA #0FF
STA Wstate,X ; 5
ORA Q6off,X ; 4
PHA ; 3
PLA ; 4 [sta..sta[
NOP ; 2
LDY #04 ; 2
wrdat1 PHA ; 3 3
PLA ; 4 4
JSR wrt_nibl1 ;+13 15 13
DEY ;--- 2
BNE wrdat1 ; 40 + 3
; --- ---
; 20+ 20 = 40
pagerr wrdat1
; -1
LDA #0D5 ; 2
JSR wrt_nibl ; 15 +15
LDA #0AA ; 2 ---
JSR wrt_nibl ;+15 36
LDA #0AD ;---
JSR wrt_nibl ; 32 15
TYA ; 2
LDY #56 ; 2
wrdat11 BNE wrdat3 ; 3
wrdat2 LDA nible2,Y ; 0 4
wrdat3 EOR nible2-1,Y ; 5 5
TAX ; 2 2
LDA to_nibble,X ; 4 4
LDX slot10z ; 3 3
; --- ---
; 36 18
STA Q6on,X ; 5
LDA Q6off,X ; 4
DEY ; 2
BNE wrdat2 ; 3
; ---
; 14 + 18 = 32
; -1
LDA temp2 ; 3
NOP ; 2
wrdat4 EOR nible1,Y ; 4 4
TAX ; 2 2
LDA to_nibble,X ; 4 4
LDX slot10 ; 4 4
; --- ---
; 32 14
STA Q6on,X ; 5
LDA Q6off,X ; 4
LDA nible1,Y ; 4
INY ; 2
BNE wrdat4 ; 3
; ---
; 18+ 14 = 32
pagerr wrdat11
TAX ; 2
LDA to_nibble,X ; 4
LDX slot10z ; 3
JSR wrt_nibl2 ; 6 15
LDA #0DE ; --- 2
JSR wrt_nibl ; 32 15
LDA #0AA ; ---
JSR wrt_nibl ; 32
LDA #0EB
JSR wrt_nibl
LDA #0FF
JSR wrt_nibl
LDA Rstate,X
wrdat99
LDA Q6off,X
wrdat999
dey
bne wrdat999 ; PostErase-Delay 1 ms
RTS
read_hdr
sei
LDY #0FC
STY temp2
rdhdr0
INY
BNE rdhdr1
INC temp2
BEQ fail
rdhdr1
LDA Q6off,X
BPL rdhdr1
rdhdr11 CMP #0D5
BNE rdhdr0
NOP
rdhdr2 LDA Q6off,X
BPL rdhdr2
CMP #0AA
BNE rdhdr11
LDY #03
rdhdr3 LDA Q6off,X
BPL rdhdr3
CMP #96
BNE rdhdr11
pagerr rdhdr1
LDA #00
nxthByte STA chk_sum
rdhdr4 LDA Q6off,X
BPL rdhdr4
ROL A
STA temp2
rdhdr5 LDA Q6off,X
BPL rdhdr5
AND temp2
STA chk_in_hdr,Y
EOR chk_sum
DEY
BPL nxthbyte
TAY
BNE fail
rdhdr6 LDA Q6off,X
bpl rdhdr6
cmp #0DE
BNE fail
NOP
rdhdr7 LDA Q6off,X
BPL rdhdr7
CMP #0AA
BNE fail
CLC
RTS
fail
SEC
RTS
moving
LDY #0
mov0 LDA Q6off,X
JSR mov1
PHA ; 3
PLA ; 4
CMP Q6off,X ; 4
BNE mov1 ;----
DEY ; 21 uS
BNE mov0
mov1 RTS
read_data
TXA
ORA #8C
STA ld1+1
STA ld2+1
STA ld3+1
STA ld4+1
STA ld5+1
LDA user_data
LDY user_data+1
STA st5+1
STY st5+2
SEC
SBC #54
BCS rddat1
DEY
SEC
rddat1
STA st3+1
STY st3+2
SBC #57
BCS rddat2
DEY
rddat2
STA st2+1
STY st2+2
LDY #20
nxt_begin
DEY
BEQ fail
wait_begin
waitb0 LDA Q6off,X
BPL waitb0
waitb00 EOR #0D5
BNE nxt_begin
NOP
waitb1 LDA Q6off,X
BPL waitb1
CMP #0AA
BNE waitb00
NOP
waitb2 LDA Q6off,X
BPL waitb2
CMP #0AD
BNE waitb00
LDY #0AA
LDA #0
rloop1 STA temp2
ld1 LDX Q6off+60 ; addr modified by read init !
BPL ld1
LDA to_bits-96,X
STA nible2-0AA,Y
EOR temp2
INY
BNE rloop1
;
; read nible from disk and convert to user data
;
LDY #0AA
BNE ld2
rloop2
st2 STA 1000,Y
ld2 LDX Q6off+60 ; modified by read init
BPL ld2
EOR to_bits-96,X
LDX nible2-0AA,Y
EOR to_bytes+0,X
INY
BNE rloop2
PHA
AND #0FC
LDY #0AA
ld3 LDX Q6off+60 ; modified by read init
BPL ld3
EOR to_bits-96,X
LDX nible2-0AA,Y
EOR to_bytes+1,X
st3 STA 1000,Y
INY
BNE ld3
ld4 LDX Q6off+60 ; modified by read init
BPL ld4
AND #0FC
LDY #0AC
rloop5 EOR to_bits-96,X
LDX nible2-0AC,Y
EOR to_bytes+2,X
st5 STA 1000,Y
ld5 LDX Q6off+60 ; modified by read init
BPL ld5
INY
BNE rloop5
AND #0FC
EOR to_bits-96,X
LDX slot10z
TAY
BNE chk_fail
rloop6 LDA Q6off,X
BPL rloop6
CMP #0DE
BEQ read_ok
pagerr wait_begin
chk_fail
SEC
db bit_z
read_ok
clc
PLA
LDY #55
STA (user_data),Y
RTS
seekT lda iob_trk
seekL
jsr trk_to_ph
cmp phase0,X
cmp phase1,X
cmp phase2,X
cmp phase3,X
LDY disk_no
LDA head_table,y ; da steht der Kopf jetzt
STA head_pos
lda dest_phase
sta head_table,y ; da soll er nachher stehen
seekH
cmp head_pos
BEQ seek_rts
LDA #0
STA temp2
seekh0 LDA head_pos
STA phase
SEC
SBC dest_phase
BEQ seekh5
BCS seekh1
EOR #0FF
INC head_pos
BCC seekh2
seekh1 ADC #0FE
DEC head_pos
seekh2 CMP temp2
BCC seekh3
LDA temp2
seekh3 CMP #8
BCS seekh4
TAY
seekh4 SEC
JSR step
LDA time0,Y
JSR step_wait
LDA phase
CLC
JSR step1
LDA time1,Y
JSR step_wait
INC temp2
BNE seekh0
seekh5 JSR step_wait
CLC
step LDA head_pos
step1 AND #3
ROL A
ORA slot10z
TAX
LDA phase0,X
LDX slot10z
seek_rts RTS
;-------------------------------;
make_nibl
LDY #56
LDA #0
maken0 STA nible2-1,Y
DEY
BNE maken0
maken1 LDX #55
maken2 LDA (user_data),Y
AND #0FC
STA nible1,Y
EOR (user_data),Y
INY
CMP #02
ORA nible2,X
ROR A
ROR A
STA nible2,X
DEX
BPL maken2
CPY #02
BNE maken1
RTS
; ds 10
Dsk_RW
ldx #0A9 ; LDA #xx
lda def_byte
and #$20 ; Bit 5 ?
bne rw_0 ; Fast Step - use abs. value
; Slow Step - use MotorOn/Off-Tables
ldx #0C9 ; CMP #xx
rw_0: stx step_wait
lda #fast_step ; Set Step Rate
bit def_byte
bmi rw_1 ; Bit7: Controller-Typ
; Bit7=0 => Ehring
lsr a ; bei Ehring 2-fache Phases => halbe Steprate
rw_1: sta step_wait+1 ; Steprate
lda disk_no
LSR A
TAY
LDA slotn,Y
STA slot10
sta slot10z
adc #0
STA iob_drv
include TRACK.INC
trk_to_ph: ; IN: A = track / OUT: A,dest_phase = phase
sta dest_phase
; Select Side 0
bit def_byte ; Bit7: 1=Erphi-Controller
; Bit6: 1=Erphi-Format
bvc ehring_format ; Bit6 = 0 => Ehring-Format
lsr dest_phase ; Erphi-Format
bcc side0
; Select Side 1
; Erphi: mtroff, Q6on, mtron
; Ehring: mtroff,mtron
side1: lda mtroff,x
bit def_byte
bpl side1_2
; Erphi-Side-1-Select
lda Q6on,x
side1_2:
lda mtron,x
jmp ph_mult
ehring_format:
cmp #$50 ; Track >= 80 ?
bcc side0 ; nein: Select Side 0
sbc #$50
sta dest_phase
jmp side1
; Select Side 0
; Ehring: lda cn00,x
; Erphi : mtroff, Q6off, mtron
side0: bit def_byte
bmi erphi_s0 ; Bit7 = 1 => Erphi-Controller
txa ; Ehring-Side-0-Select
lsr a
lsr a
lsr a
lsr a
ora #$C0
sta ehr_sel+2
ehr_sel:lda $C600
jmp ph_mult
erphi_s0: ; Erphi-Side-0-Select
cmp mtroff,x
cmp Q6off,x
cmp mtron,x
ph_mult:
lda def_byte ; Bit 0..1: 0 = 1 Step/Track
and #03 ; 1 = 2 Steps/Track
tay ; 2 = 4 Steps/Track
beq ph_mult2
ph_mult1:
asl dest_phase
dey
bne ph_mult1
ph_mult2:
lda dest_phase
rts
;---------------------------------------------------------------------------
;
; D I S K R W
; Eingang: iob_trk, sektor, def_byte, disk_no, param, last_track
; dma, ilv_tbl,
; Ausgang: iob_err
; Daten: x000..xFFF (Ein Track, Sektoren in log. Reihenfolge)
; 64180 darf nicht auf den Applebus, Aufruf mit JSR
;
;---------------------------------------------------------------------------
DISKRW:
jsr lock_bus
lda iob_trk ; Track fuer Read/Write
bit param ; 0 = Write, FF = Read
bpl writecmd
cmp last_track ; Muss auf neuen Track positioniert
bne readtrack ; werden ?
ldy sektor
ldx ilv_tble,y
lda sec_tble,x
beq readtrack ; Sektor nicht ok
ldx ilv_tble+1,y
lda sec_tble,x
beq readtrack
lda #00 ; Nein, somit auch kein Lesefehler
sta iob_err
jmp unlock_bus
readtrack:
sei
lda #10 ; Track muss ganz neu gelesen werden
sta sec_cnt ; das sind 16 Sektoren a 256 Byte
lda #00 ; Kennzeichen fuer Einlesen
ldx #0F
sec_1_loop: sta sec_tble,x ; Sektortabelle = Kennzeichen setzen
dex
bpl sec_1_loop
bmi readwrite
writecmd:
sei
ldx #02 ; Bei Write nur 512 Byte schreiben
stx sec_cnt
ldx #0F
lda #$FF ; Kennzeichen fuer 'nicht Einlesen'
sec_2_loop: sta sec_tble,x
dex
bpl sec_2_loop
ldy sektor ; gewuenschter 1. Sektor
ldx ilv_tble,y ; logisch --> physisch umrechnen
lda #00 ; Kennzeichen 'Sektor schreiben'
sta sec_tble,x
ldx ilv_tble+1,y ; 2. Sektor logisch --> physisch
sta sec_tble,x ; Auch schreiben
lda last_track
cmp iob_trk ; Anderer Track als der letzte ?
beq readwrite
jsr readwrite ; Ja
lda #$FF ; Muss bei Read neu eingelesen werden,
; da die anderen 14 Sektoren zum
; letzen Track gehoeren
sta last_track
rts
readwrite:
lda #00
tay
tax
interlv_2:
ora #dma_4k ; Cachebereich (4k) fuer Track
sty dma,x
inx
sta dma,x
inx
clc
adc #0B ; Interleave 3
and #0F ; MOD 16
cpx #20 ; 16 Sektoren
bne interlv_2
lda #0F ; Step Rate
sta iob_err
jsr dsk_rw ; Disk Operation
lda iob_err ; Fehlerkennzeichen
beq no_err
ldy sektor
ldx ilv_tble,y
lda sec_tble,x
beq is_err ; Fehler im 1. Teil des Blocks ?
ldx ilv_tble+1,y
lda sec_tble,x
beq is_err ; Fehler im 2. Teil des Blocks ?
; nein,
lda #0
sta iob_err ; Zumindest dieser Block ok
beq no_err ; Always
is_err:
lda #$FF ; Track muss neu gelesen werden
db bit_a ; Skip 2 Bytes
no_err: lda iob_trk ; last_track := track
sta last_track
jmp unlock_bus
;----------------------------------------------------------------------------
;
; A N A L 6 5
; Eingang: param = 1..4 (Analogschalternummer)
; Ausgang: analogwert = 0..255
;
;---------------------------------------------------------------------------
ANAL65:
sei
jsr lock_bus
ldx param ; Nummer des Analogports
lda analogreset ; Timer starten
ldy #00
nop
nop
readanalog:
lda analog_1,x ; Analogwert lesen
bpl anaready
iny
bne readanalog ; Bis Bit 7 auf 0
pagerr readanalog
dey ; Maximum 255
anaready: sty analogwert
cli
jmp unlock_bus
;
INCLUDE GRAFIK65.MAC
;
irqvec:
sta Asave ; Akku retten
pla
pha
and #10 ; BRK -Bit ?
bne brkirq
lda Asave
jmp irq ; Interrupt ausfuehren
brkirq:
lda main_ROM
lda Asave
jmp BREAK ; Alte BREAK-Routine
resvec:
lda main_ROM ; ROM einschalten
jmp RESET ; Alte RESET-Routine
;****************************************************************
;
; B E L L
;
; => Akustisches Signal
beep sei
jsr lock_bus
lda #$32 ; Laenge
; Frequenz = 5000/X Hz
beep1 ldx param ; 3
beep2 ldy #$12 ; 2
beep3 dey ; 2
bne beep3 ; + 3
; ----
; 89 = 5 * 18 - 1
nop ; 2
nop ; 2
nop ; 2
dex ; 2
bne beep2 ; 3
; ----
; 102 * X * 0.9775 us
; = 99.7ms (f ~ 10kHz/X)
; -1 (Branch)
bit speaker ; 4
sec ; 2
sbc #1 ; 2
bne beep1 ; 3
; -----
; (14 + 102 * X) * A States Dauer
; 0.9775 * (14 + 102 * X) * A us
cli
jmp unlock_bus
;*******************************************************************
;
; Zugriffskontrolle fuer 64180 auf 6502-Bus
;
lock_bus:
lda #$FF
sta bus_locked
ldx SLOT180
lda wait180,x
rts
unlock_bus:
lda #$00
sta bus_locked
ldx SLOT180
lda start180,x
rts
;*******************************************************************
;
; Input-Buffer Handler
;
; Der Buffer darf nicht voll sein!
; Interrupts bei Receive-Buffer disabled
; Eingang: A = Zeichen
; X = Bufferdescriptor Offset
; Ausgang: X intakt
; A veraendert
; SEC, wenn Puffer voll war
putbuf:
sei
putbuf0:
pha
lda free,x ; Test, ob Puffer voll
ora free+1,x
beq putbuf4
pla
sta (in,x) ; Zeichen in Puffer schreiben
inc in,x ; Schreibzeiger erhoehen
bne putbuf1
inc in+1,x
lda in+1,x ; Puffer-Ende ?
cmp end,x
bcc putbuf1
lda beg,x ; Ringpuffer, wieder auf Pufferanfang setzen
sta in+1,x
putbuf1:
dec wait_flg ; Warten, bis update vorbei
inc full,x ; Belegten Platz vergroessern
bne putbuf2
inc full+1,x
putbuf2: ; Dieser Wert wird auch von FROUT benutzt!
lda free,x ; Freiplatz verringern
bne putbuf3
dec free+1,x
putbuf3:
dec free,x
inc wait_flg ; Update gelaufen
clc ; Zeichen uebernommen
rts
putbuf4:
pla
sec
rts ; Puffer war voll
;*******************************************************************
;
; Output-Buffer Handler
;
; Interrupts bei Transmit-Buffer disabled
; Der Buffer darf nicht leer sein!
; Eingang: X = Bufferdescriptor Offset
; Ausgang: X intakt
; A = Zeichen
; SEC, wenn Puffer leer war
getbuf:
sei
getbuf0:
sec
lda full,x
ora full+1,x
beq getbuf4 ; Test, ob Puffer leer ist
lda (out,x) ; Zeichen aus Puffer lesen
pha
inc out,x
bne getbuf1
inc out+1,x ; Lesezeiger erhoehen
lda out+1,x
cmp end,x
bne getbuf1
lda beg,x
sta out+1,x ; Ringpuffer, Zeiger wieder auf Pufferanfang
getbuf1:
dec wait_flg ; Warten, bis Update vorbei
inc free,x
bne getbuf2
inc free+1,x ; Freien Platz vergroessern
getbuf2:
lda full,x
bne getbuf3
dec full+1,x
getbuf3:
dec full,x ; Belegten Platz verringern
inc wait_flg ; Update vorbei
pla
clc
getbuf4: ; A enthaelt 00, wenn Puffer leer war
rts
;****************************************************************
;
; => Drucker-Spooler
;
;------------------------------------------------------------------
;
; Zeichen aus Druckerspooler an Drucker senden
;
spochc:
lda prackn
bmi chcend ; Printer ready ?
ldx #pbuf ; Printer Buffer
jsr getbuf0 ; Ohne SEI
bcs chcend ; Nichts auszugeben, fertig
sta prport ; Zeichen ausgeben
jmp spochc ; Bis nichts mehr moeglich ist
chcend:
rts
;--------------------------------------------------------------------
;
; Zeichen in Druckerpuffer schreiben
bufin:
ldx #pbuf ; Zeichen geht verloren, wenn Puffer voll
jmp putbuf0 ; Zeichen in Puffer schreiben
;****************************************************************
;
; => Ausgabe Spooler fuer serielle Schnittstelle
;
;-----------------------------------------------------------------
;
; Zeichen aus dem Transmitbuffer senden
;
;spsero:
; LDA serial_stat
; AND #10 ; Transmit Data Register empty ?
; BEQ schend ; serielles Interface nicht bereit
spserok: ; Einsprung fuer Transmitinterrupt
LDA SerFlg ; Ausgabe Stop ?
BMI dis_tx ; Ja -> nichts ausgeben
ldx #tbuf ; Transmitbuffer
jsr getbuf ; Zeichen aus Puffer lesen
bcs dis_tx ; Transmitter disabled, wenn Puffer leer
sta SER_DAT ; Zeichen ausgeben
schend:
rts
dis_tx:
lda ser_com
and #$F3
ora #$08 ; Transmit Interrupt aus
sta ser_com
rts
;---------------------------------------------------------------------
;
; Zeichen in den Transmitbuffer schreiben
sbufin:
ldx #tbuf ; Zeichen in Transmitbuffer schreiben
jsr putbuf ; Zeichen geht verloren, wenn Puffer voll
cli ; Wird nicht in Interruptrotinen aufgerufen
lda ser_com
and #$F3
cmp #$04 ; War Transmitinterrupt enabled ?
beq sbufin1
ora #$04 ; Enable Transmit Interrupt
sta ser_com
sbufin1:
rts
;****************************************************************
;
; Eingabe Spooler fuer serielle Schnittstelle
;
;-----------------------------------------------------------------
;
; Zeichen in A in den Receivebuffer schreiben
rxser:
bit A_FLG ; Ausgabeflusskontrolle
bpl rxser3 ; XON/XOFF interpretieren ?
cmp #XON
bne rxser4
lda #$7F
and SerFlg ; Transmitter starten
sta SerFlg ; Bit 7 := 0
lda ser_com
and #$F3
ora #$04
sta ser_com
rts
rxser4:
cmp #XOFF
bne rxser3 ; war weder XON noch XOFF
lda #80
ora SerFlg ; Transmit-IRQ schaltet sich selbst aus
sta SerFlg ; Bit 7 := 1
rts
rxser3:
ldx #rbuf
jsr putbuf ; Zeichen geht verloren, wenn Puffer voll
bcs rx_rts
lda free+1+rbuf
bne rx_rts ; Noch genug Platz
lda free+rbuf
cmp #10
bne rx_rts ; Mehr als 16 Zeichen frei
; Flusskontrolle durchfuehren
bit E_FLG ; Eingabeflusskontrolle
bpl rxser1
; XOFF senden
lda #XOFF
jsr DSerOut
rxser1:
bit E_FLG
bvc rx_rts
; DTR low legen
lda ser_com
and #$FE
sta ser_com
rx_rts: rts
;--------------------------------------------------------------------
;
; Zeichen aus Receivepuffer lesen an 64180 senden
;
rxout:
lda INTPAR1
bne rxout_rts ; Letzer Interrupt noch nicht quittiert
bit bus_locked
bmi rxout_rts ; 64180 darf nicht auf den Bus
bit IFLG ; "stop" - Zustand
bmi rxout_rts ; Kein Inputinterrupt
ldx #rbuf
jsr getbuf ; Zeichen lesen
bcs rxout_rts ; Puffer ist leer
ldx #5 ; Kanal 5: serielle Schnittstelle
ldy err5_bits ; Fehlerbits (passen nicht zum Zeichen)
jsr TO180 ; Zeichen im Akku
ldy #0
sty err5_bits ; loeschen
lda full+1+rbuf
bne rxout_rts ; Noch zuviel im Puffer
lda full+rbuf
cmp #10
bne rxout_rts ; Noch mehr als 16 Zeichen im Puffer
bit E_FLG
bpl rxout2
lda #XON ; XON senden
jsr DSerOut
rxout2:
bit E_FLG
bvc rxout_rts
; DTR high legen
lda ser_com
ora #01
sta ser_com
rxout_rts:
rts
;-------------------------------------------------------------------
;
; Direkte Ausgabe auf der seriellen Schnittstelle
;
DSerOut:
pha
lda ser_com
and #$F3
ora #08 ; Transmitter on, Tx_IRQ off
sta ser_com
Wai_empty:
LDA serial_stat
AND #10 ; Transmit Data Register empty ?
BEQ Wai_empty ; warten bis Transmitter empty ->
pla
STA SER_DAT
lda ser_com
and #$F3
ora #$04
sta ser_com ; Transmitter on, TX_IRQ on
RTS
;************************************************************************
;
; => Interrupt: Tastatur/V24
;
;-------------------------------------------------------------------------
;
; Interrupt-Handler
;
IRQ:
sta ASave
stx XSave
sty YSave
bit keyboard ; Taste gedrueckt ?
bpl irq_1
jsr keyIRQ
irq_1:
lda serial_stat
bpl irqret
pha
and #08 ; Receive Data Register full ?
beq irq_2
pla
pha
jsr receive_irq
irq_2:
pla
pha
and #10 ; Transmit Data Register empty ?
beq irq_3
jsr spserok ; Zeichen aus Transmitbuffer senden
irq_3:
pla
pha
and #18
bne irq_4
; External Status Change IRQ
pla
pha
jsr status_irq
irq_4:
pla
IRQret:
ldy YSave
ldx XSave
lda ASave
rti ; Pull Old Status and Return
;-------------------------------------------------------------------
;
; Status Change - Interrupt
;
; Eingang: A = serial_stat
;
status_irq:
bit A_FLG ; Ausgabe Flusskontrolle (DSR beachten)
bvc status1
and #40 ; DSR beobachten
beq status2 ; -DSR low, Transmitter starten
lda #$7F ; Bit 7 := 0
and SerFlg
sta SerFlg
lda ser_com
and #$F3
ora #$04 ; Transmitter on, Tx_IRQ on
sta ser_com
status1:
rts
status2: ; -DSR high, Transmitter stoppen
lda #80
ora SerFlg ; Transmitter stoppt sich selbst
sta SerFlg
rts
;-------------------------------------------------------------------
;
; Receiver - Interrupt
; Eingang: Y = ser_dat
; A = serial_stat
;
receive_irq:
and #7 ; Fehlerbits ausmaskieren
ldy ser_dat ; Zeichen einlesen
bit SerFlg ; Letztes Zeichen war Break
bvc receive1
pha
lda #2 ; Break
ora err5_bits
sta err5_bits ; Break empfangen
lda #$BF
and SerFlg ; Break Bit 6 := 0
sta SerFlg
pla
cpy #2 ; SV-Call
beq sv_call
cpy #'W' ; BREAK - W = control ('weiter') simulieren
beq weiter ; WEITER
cpy #'R' ; BREAK - R = RESET
beq reset_sys ; RESET
cpy #'S' ; BREAK - S = Shutup
bne receive1 ; SHUTUP
pha
ldx #'S' ; Shutup-Kennzeichen
tay
jsr TO180 ; Shutup - Interrupt
pla
receive1:
cmp #2 ; Framing Error ?
bne receive2
cpy #0 ; und Zeichen 00 = Break
bne receive2
lda #$40
ora SerFlg ; Break vermerken
sta SerFlg
rts
sv_call:
jsr weiter
ldy #0
ldx #5
lda #2 ; CTRL-B
jmp TO180
weiter:
lda #0
sta INTPAR1 ; Interrupt als quittiert ansehen
lda #7F
and IFLG
sta IFLG
rts
receive2:
tax
lda errbit_tab,x ; ACIA-Fehlerbits --> EUMEL Fehlerbits
ora err5_bits
sta err5_bits ; Fehler vermerken
tya ; Zeichen war in Y
jsr rxser ; Zeichen in Receivepuffer schreiben
jmp rxout ; Versuchen an 64180 zu senden
;-------------------------------------------------------------------------
;
; Fehlerbits
;
errbit_tab:
db 0, 4, 4, 4, 1, 5, 5, 5
; EUMEL: Bit 0= Overrun, Bit 1= Break, Bit 2= Parity/Framing
;*******************************************************************
;
; Remote - Reset
;
reset_sys:
sei
ldx #rescodelen-1
resetsysa:
lda rescode,x
sta 0,x
dex
bpl resetsysa
ldx SLOT180
lda stop180,x
nop
lda start180,x
nop
lda stop180,x
jmp resvec
rescode:
db $AF, $F3, $ED, $39, $00, $ED, $39, $00, $ED, $76
rescodelen equ $-rescode
; SYSEND:
; XOR A
; DI
; OUT0 (CNTLA0),A
; OUT0 (CNTLA0),A
; SLP
;------------------------------------------------------------------
;
; Keyboard - Interrupt
;
keyIRQ:
lda KeyBoard
asl a
tax ; X = 6543 210O
lda KeyExt
asl a ; Carry = Bit 7
txa
ror a
sta KeyStr ; Strobe loeschen
bit bus_locked
bmi readkey0 ; Nur SHUTUP/RESET erlaubt
cmp #$C2 ; F2 = SV-CALL
bne readkey0a
jsr readkey0b
lda #$C2
ldx #1
jmp TO180
readkey0a:
cmp #$BC ; SHIFT CTRL F12 = HCOPY-KEY
bne readkey0c
jmp HCOPY
readkey0c:
cmp #$BD ; SHIFT CTRL F13 = WEITER-KEY
bne readkey0
readkey0b:
lda #0
sta INTPAR1 ; Interrupt als quittiert ansehen
lda #$BF ; Bit 6 loeschen
and IFLG
sta IFLG
rts
readkey0:
cmp #$BE ; SHIFT CTRL F14 = SHUTUP-KEY
bne readkey1
ldx #'S' ; Kennzeichen fuer Shutup
jmp TO180 ; Shutup-Interrupt
readkey1:
cmp #$BF ; SHIFT CTRL F15 = RESET-KEY
bne readkey2
jmp reset_sys ; Keine Rueckkehr
readkey2:
ldx KeyIn
inx
cpx KeyOut
bne readkey3
; Tastaturpuffer Overflow
lda err1_bits ; Kanal 1 Fehlerbits
ora #1
sta err1_bits ; Overrun-Error
ldx #$0A ; Kurzer Beep: Buffer full
ldy #$10
jmp beep1
readkey3:
dex
sta KeyBuf,x
inc KeyIn
; Versuchen an 64180 zu senden
;----------------------------------------------------------------
;
; Zeichen aus Keyboard-Buffer holen
;
getkey:
ldx INTPAR1 ; letzter Interrupt quittiert ?
bne Getret
bit bus_locked
bmi Getret
bit IFLG ; "stop" - Zustand ?
bvs Getret ; Kein Inputinterrupt
sei
ldx KeyOut
cpx KeyIn
beq GetRet ; Puffer leer
lda KeyBuf,x
inc KeyOut
ldx #1 ; Kanal 1, Zeichen muss da sein
ldy err1_bits ; Overrun Bit
jsr TO180 ; 64180 Interrupt
ldy #0
sty err1_bits
GetRet:
rts
;****************************************************************
;
; Texthardcopy auf Basis-Parallel
; (Interrupt muessen disabled sein)
; (Nur moeglich, wenn Druckerspooler leer, 64180 wird gestoppt)
;
HCOPY:
lda pbuf+full
ora pbuf+full+1
bne getret ; Kein Hardcopy, da Spooler nicht leer ist.
jsr lock_bus ; 64180 vom Dienst suspendieren
lda #$0D
jsr bufin ; CR an Drucker
ldx #0
hcopy2:
ldy #0 ; 1. Spalte
hcopy1:
txa
pha
tya
pha
jsr bascalc ; Zeichen an der Position lesen
and #$7F ; Inversbit ausblenden
jsr bufin ; Zeichen an Drucker
pla
tay
pla
tax
iny
cpy #$50 ; 80. Spalte ?
bne hcopy1
txa
pha
lda #$0D ; CRLF an Drucker
jsr bufin
lda #$0A
jsr bufin
jsr spochc ; Spooler erstmal leeren
pla
tax
inx
cpx #$18 ; 24. Zeile ?
bne hcopy2
jmp unlock_bus ; 64180 darf wieder arbeiten
;------------------------------------------------------------------------
;
; Berechnet Adresse der Bildschirmposition (A,X) nach basl/bash
; Holt Zeichen --> A
; Static/Dynamic - Switch ggf. veraendert
;
bascalc:
lsr a
tay ; Y DIV 2
sta VIDBNK ; default even Y
bcc bascalc1
sta VIDBNK+1 ; odd Y
bascalc1:
txa
lsr a
and #3
ora #4 ; Page 0400..0BFF
sta bash ; High
txa
and #$18
bcc bascalc2
ora #$80
bascalc2:
sta basl ; Low
asl a
asl a
ora basl
sta basl
lda (basl),y
rts
;****************************************************************
;
; Interrupts zum 64180 (Inputinterrupts)
; moeglich von Tastatur (Kanal 1) und seriellem Interface (Kanal 5)
; Shutup-Interrupt mit X = 'S'
; Ausgang: X veraendert
;
TO180:
php
sei
STA intpar2 ; Zeichen
STY intpar3 ; Fehlerbits
STX intpar1 ; Kanalnr.
LDX SLOT180
LDA INT180,X ; 64180 Interrupt erzeugen
LDA intpar2
plp ; Interrupt Flag
RTS
;****************************************************************
;
; Drucker Spooler loeschen
;
init_pbuf:
ldx #initab_len
ploop: lda pbuf_ini,x
sta pbuf,x
dex
bpl ploop
rts
pbuf_ini:
DW (DBUFEND - DBUFBEG) * 100H, 0
DW DBUFBEG * 100H, DBUFBEG * 100H
DB DBUFBEG, DBUFEND
initab_len EQU *-pbuf_ini-1 ; Alle gleich Lang
;****************************************************************
;
; Puffer pollen
;
polling:
jsr spochc ; Zeichen aus Printer Spooler ?
; lda full+tbuf
; ora full+tbuf+1
; beq polling2
; jsr spsero ; Zeichen aus Transmitbuffer senden
; cli
;polling2:
lda INTPAR1 ; letzter Interrupt quittiert ?
bne polling1 ; Puffer garnicht erst testen
; Polling: Interrupts an 64180
jsr getkey ; Zeichen aus Tastatur-Buffer
cli
lda full+rbuf
ora full+rbuf+1
beq polling1
jsr rxout ; Zeichen aus Receive-Buffer
cli
polling1:
rts
;****************************************************************
;
; Hauptschleife des 6502: wartet auf Tasks
;
; Task 1 : Disk R/W
; 2 : Bell
; 3 : Char zum Drucker(spooler)
; 4 : Char zum seriell Spooler
; 5 : Direktausgabe auf serieller Schnittstelle
; 6 : Analog I/O
; 7 : Grafik
;
task_end:
; 8 : Druckerspooler loeschen
lda #0
sta task
sta bus_locked ; Nicht mehr gesperrt
task_loop:
cli
jsr polling ; Puffer pollen
lda task
beq task_loop
cmp #1
bne task_lp1
jsr DISKRW ; Disk I/O
jmp task_end
task_lp1:
cmp #2
bne task_lp2
jsr Beep
jmp task_end
task_lp2:
cmp #3
bne task_lp3
lda param
jsr bufin ; in Spooler-Buffer
jmp task_end
task_lp3:
cmp #4
bne task_lp4
lda param
jsr sbufin ; Output to serial Interface
jmp task_end
task_lp4:
cmp #5
bne task_lp5
lda param
jsr DSerOut ; direkte Ausgabe auf ser. Schnittstelle
jmp task_end
task_lp5:
cmp #6
bne task_lp6
jsr ANAL65 ; Analog I/O
jmp task_end
task_lp6:
cmp #7
bne task_lp7
JSR GRAFIK ; Grafik I/O
jmp task_end
task_lp7:
cmp #8
bne task_end
jsr init_pbuf ; Drucker Spooler loeschen
jmp task_end
defm 'Ende vom SHard'
LEN65 EQU $-start
IF $ GE 2000
.printx '6502-Modul in Grafikseite 1!'
ENDIF
end