From 98cab31fc3659e33aef260efca55bf9f1753164c Mon Sep 17 00:00:00 2001 From: Lars-Dominik Braun Date: Mon, 11 Feb 2019 11:49:19 +0100 Subject: Add source files from Michael --- system/shard-z80-ruc-64180/1.5/src/DISK.MAC | 1658 +++++++++++++++++++++++++++ 1 file changed, 1658 insertions(+) create mode 100644 system/shard-z80-ruc-64180/1.5/src/DISK.MAC (limited to 'system/shard-z80-ruc-64180/1.5/src/DISK.MAC') diff --git a/system/shard-z80-ruc-64180/1.5/src/DISK.MAC b/system/shard-z80-ruc-64180/1.5/src/DISK.MAC new file mode 100644 index 0000000..56bf2f3 --- /dev/null +++ b/system/shard-z80-ruc-64180/1.5/src/DISK.MAC @@ -0,0 +1,1658 @@ +; + 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 + \ No newline at end of file -- cgit v1.2.3