;Tabulatoren mit quickbasic programm entfernen ;Text in AVR studio markieren (alles) ;kopieren ;in MS word einfügen ;seitenlayout auf 2cm linke und rechter rand (nicht mehr) ;alles markieren ;courier new +8 cpi einstellen ;drucken ;------------------------------------------------------------------------------------------------ ; ; ; ; IEC2IEEE ; ; without any warranty ; 2 C ; 5 n ; s t ; u r ; b n ; IEC-BUS IEEE-BUS CENTRONICS D c ;at / \ - s ;flashing normal IIIIII IIIIIIII p - ;IIIIIIII IIIIII VVVVVV VVVVVVVV l p ;VVVVVVVV VVVVVV u l ; g u ; g ; (reset) ; ------------------------- IFC 9 (--I<--) Prime 16 31 ; I ; I ---- ---- ; -----Ipb1 pa0I- Dt1 1 ---I<--- Data1 2 2 I ; I I I I ; I I3 38I I ; I 4 CLKout --------Ipb3 E pa2I- Dt3 3 ---I<--- Data3 4 4 I ; I ------------------' I L I I ; I I I5 36I I ; I I 5 DTAout --------Ipb5 pa4I- Dt5 13 ---I<--- Data5 6 6 I ; I I I A I I ; I I I7 T 34I I ; I I 1 SRQout ---------o I9 5 32I I ;GND ---------------' o---Irst 1 pa7I- Dt8 16 ---I<--- Data8 9 9 I ; ,-o I I 5 I I ; --------------' #2I I10 31I I ; I (JR)I Ipd0 icpI I ; I I I I I ; I +5V-[r=1kOhm]-- I11 30I I ; I Ipd1 aleI I ; I I I ^^ I ; I I12 29I II (+5V) I ; I 3 ATNin -----I>----Ipd2 oc1bI----- 74LS244 ( I-I>-O) ; ; ; - user must set bit1 of r06 to high ; JD closed: print debug-buffer to printer at reset ; JD open: no printing (and printer-line isn't locked) ; ; if user doesn't want to print the analysebuffer to a printer ; => user must set bit1 of r06 to low ; JD closed: AVR doesn't write new values into analysebuffer ; => C64 can read analysebuffer with M-R-command ; JD open: AVR writes new debug values into analysebuffer ; (analysebuffer and debugbuffer is the same) ;0 = analysebuffer starts at $0200 (0) / $0180 (1) (-025f) ; => JiffyDos-load buffer 0100-01ff / 0100-017f ;00=no ;80=IeeePorts ;40=IecPort ;20=analyse byte ;60=AnalyseByte & IecPort ;01/03 = special for save analysebytes of JD-LOAD only .def r07=r7 ;temporary memory for bus declicking (counter, flag for AtnMode, at printing) .def r08=r8 ;temporary memory for bus declicking (port) .def r09=r9 ; r10 unimportant temporary counter ; r16 Accu of 1541 ; r17 Xreg of 1541 ; r18 Yreg of 1541 ; r24 counter delay *10µs ; r25 don't use; for debug printing and debug-LED------- ; r26 Xreglow #$00 (different values only at debug-printing) ; r27 Xreghigh #$ff (different values only at debug-printing) ; r28 Yreglow for writing into debug buffer ; r29 Yreghigh for reading ; r30 Z-register low (only register for lpm icall ijmp) ; r31 Z-register high (for writing...) ;------------------------------------------------------------------------------------------------ ; ;0020-005f I/O ;------------------------------------------------------------------------------------------------ ;0060-025f RAM ;0060-007f Stack .equ emumod = $80 ;emulation-mode see tadeem ;Bit 7-5 ;%000 $00 = IEEE ;%001 $20 = Centronic ;%010 $40 = RTC & memory read&write ;%011 $60 = RS232 ;%100 $80 = IEC additional device-number-translation ;%101 $a0 = 64HDD at additional IEC ((fast) serial) ;%110 $e0 = 64HDD at additional IEC (parallel) ;%111 $f0 = cleared ;bit 4-0 unused .equ devpos = $81 ;device posibilities see tadepo ; at Ieee:7 = 0=no floppy 1=floppy ; 6 ; 5 ; 4-0 = devicenumber to translate to ;at Centronics:7 = 0=no change 1=CBM-ascii->IBM-ascii at ; secundary address 7 ; 6-0 unused .equ flicbb = $82 ;flag iecbus bits ;7 = IecAtnMode($7d) 0=DataMode 1=CommandMode ;6 = IecTalk ($7a) ;5 = IecListen ($79) ;4 = IecEoi ($f8) 0=noEoi 1=Eoi (at 1541 inverted!!!) received ;3 = ;0 = IecEoi at IecOut 0=noEoi 1=Eoi (ldx$82 lda$f2,x and#$08 e92f) .equ icsaco = $83 ;IecSecundaryaddressComplete (all 7 bits) ($84) .equ icsawo = $84 ;IecSecundaryAddress without bits whether open,close,SA ($83) .equ iccode = $85 ;IecCommand&Devicenumber .equ iccbjd = $86 ;IeC-routines ;$00= CBM ;$01= JiffyDOS-IECIN IECOUT ;$60= JiffyDOS-LOAD .equ fljdal = $8f ;flag JiffyDOS allowed ;bit7 0=only CBM allowed 1=JiffyDOS alowed ;bit0 at JD-LOAD: way to see that C64 is ready to receive next block ; 0=waiting-loops (like 1541) 1=analyse C64-DataOut at fb06 .equ tadenu = $90 ;- 9f table device numbers ;16 possible 5 Ieee 1 Centronic 1 RTC 1 Rs232 5 Iec-Switch ;7 = 0=present 1=not present (this memory) ;6 = 0=no Talker (f.e.printer) 1=Talker ;5 = 0=no Listener 1=Listener ;4-0 =devicenumber .equ tadeem = $a0 ;-af table device emulation ; in what to emulate (see emumod) .equ tadepo = $b0 ;-bf table device possibilities see devpos ; at Ieee:7 = 0=no floppy 1=floppy ; 6 ; 5 ; 4-0 = devicenumber to translate to .equ tacode = $c0 ;-cf table IEC command & devicenumber ;%010ddddd ;bit 7-5 =talk important that one bit is set because #$00 is empty ; and bit 4-0=#$00 could be talk to seriel device 0 ;bit 4-0 =device-number ;=> #$00=empty #$40=talk to device 0 .equ tatasa = $d0 ;-df table talk-secundary-address ;bit 7 ;bit 6 ;bit 5 0=no byte in buffer 1=byte in buffer ;bit 4 0=no EOI 1=EOI ;bit3-0 =secundary address .equ tataby = $e0 ;-ef table talk-byte .equ avinco = $00f0 ;AVR-internal command .equ eninbu = $00f1 ;end input buffer (+1) .equ erbuve = $00f2 ;error buffer vector .equ erbuen = $00f3 ;error buffer end ;0100-0129 ;input buffer for AVR-internal ;012a-014c ;error-buffer for AVR-internal ;0100-017f/01ff ;load-buffer at JiffyDos ;0180/0200-025f ;analyse-bytes-buffer ;------------------------------------------------------------------------------------------------ ;EEPROM ;0000-003f ;empty ($ff) ;0040-00bf ;table 0 ;00c0-013f ;table 1 ;0140-01bf ;table 2 ;01c0-01ff ;empty ($ff) ;there are three identical tables. So the AVR can compare them ;and find and repair an EEPROM-corruption ;tables ;tbl0 tbl1 tbl2 ;0040 00c0 0140 0000;flag for autorepair EEPROM-corruption ($55=no $aa=yes) ;0041 00c1 0141 0001;calibrationbyte for internal oscylator for 7.3728MHz ;0042 00c2 0142 0002;analyse buffer mode -> r06 ;004f 00cf 014f 000f;flag JiffyDOS allowed -> $008f-RAM ;0050 00d0 0150 0010;\ ; - - - - ; tadenu = table device numbers ->0090-009f-RAM ;005f 00df 015f 001f;/ ;0060 00e0 0160 0020;\ ; - - - - ; tadeem = table device emulation ->00a0-00af-RAM ;006f 00ef 016f 002f;/ ;0070 00f0 0170 0030;\ ; - - - - ; tadepo = table device possibilities ->00b0-00bf-RAM ;007f 00ff 017f 003f;/ ;0080 0100 0180 0040;\ ; - - - - ; empty ($ff) ;00bf 013f 01bf 007f;/ ;------------------------------------------------------------------------------------------------ ; timer0 = for timing ; timer1 = for error-LED cannot be used for timing ;------------------------------------------------------------------------------------------------ .org $0000 ;------------------------------------------------------------------------------------------------ rjmp l12710 ;external reset rjmp l10000 ;external irq 0 rjmp l10030 ;external irq 1 rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; rjmp l10030 ; ;------------------------------------------------------------------------------------------------ l10000: ; external IRQ 0 ;Global Interrupt Enable Bit is cleared ;=>impossible that second IRQ is executed while first one is executed ;=>r26 r27 can have different values than #$00/#$ff ;=C64 makes ATN = active ;=Atn-line edge from inactive to active in r27,$3f ;reads status register ldi r26,$06 ;$07 at 8MHz l10010: sbic $10,2 ;2 skips if IecAtn=active rjmp l10020 ; =IecAtn=inactive (too short IecAtn-peek => no reaction) dec r26 ;1 brne l10010 ;2 5*6=30 = 4µs at 7.3728MHz cbi $18,4 ;PortB = pulluprestor-off/push to 0V sbi $17,4 ;sets data to active as answer to C64-ATN=active by making DDRB to output out $3b,r26 ;#$00 makes no more IRQ = also flag for ATN-IRQ l10020: out $3f,r27 ;restores status register ldi r26,$00 ldi r27,$ff l10030: reti ;================================================================================================ l10040: ldi r16,$20 ;LED on LED on rjmp l10070 ;--------------- l10050: ldi r16,$10 ;LED blink rjmp l10070 ;--------------- l10060: ldi r16,$30 ;LED off l10070: out $2f,r16 ;Timer/Counter1ControlRegisterA ldi r16,$0c ;%00001100 Clear Timer1 on Compare match CK/256 7.3728MHz/256= out $2e,r16 ;Timer/Counter1ControlRegisterB ldi r16,$00 out $2d,r16 ;Timer/Counter1 high out $2c,r16 ;Timer/Counter1 low make Timer1 = $0000 ldi r16,$30 ;about 80 flashes per minute out $2b,r16 ;T/C1 Output Compare Register A high ldi r16,$00 out $2a,r16 ;T/C1 Output Compare Register A low value resets timer to 0000 ldi r16,$01 out $29,r16 ;T/C1 Output Compare Register B high ldi r16,$00 out $28,r16 ;T/C1 Output Compare Register B low changes LED-pin OC1B ret ;================================================================================================ l10080: ldi r25,$b0 ;b0-- rcall l12490 rcall l10120 ;searches wanted buffer talk-buffer-open if necessary brcs l10110 ;b.i.buffer to this DN & SA already exists ldi r25,$b1 ;b1-- rcall l12490 ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - l10090: ldi r25,$b3 ;b3-- rcall l12490 ldi r30,$f0 ; talk-buffer-open ldi r31,$00 ; z = writevector = $00f0 ldi r28,$ef ldi r29,$00 ; y = readvector =$00ef l10100: ld r16,-y ;copies c0-c1 ce->cf d0->d1 de->df e0->e1 ee->ef st -z,r16 ;(writes wrong values to d0 e0 cpi r28,$c0 brne l10100 lds r16,iccode ;Iec Command & devicenumber 7-5=%010=Talk 4-0=devicenumber sts $c0,r16 ;stores as actual value of table command & devicenumber lds r16,icsawo ;Iec secundaryeaddress without bits for open,close,after listen/talk ;Bit 7=0 ? ;bit 6 ;bit 5=0 =no byte in talk-buffer ;bit 4=0 =no EOI ;bit 3-0 =secundary address sts $d0,r16 ;stores as actual value of table secundary-address at talk ;in e0 stays wrong value ldi r25,$b4 ;b4-- rcall l12490 l10110: ldi r25,$b5 ;b5-- rcall l12490 lds r16,$d0 ;actual talk-bits & secundary address andi r16,$20 ;masks bit for byte in talk-buffer ret ;equal=no byte in talk-buffer not-equal=byte in talk-buffer ;------------------------------------------------------------------------------------------------ l10120: ldi r25,$b6 ;b6-- rcall l12490 andi r16,$1f ;masks devicenumber bits talk-buffer search© to actual position ori r16,$40 ;makes bits for talk (important when close talk-error-buffer at listen) ldi r28,$e0 ldi r29,$00 ; y =read-vector = $00e0 r16=devicenumber r17=secundayr address l10130: ld r18,-y ;reads table secundary-address at talk (predecremented) andi r18,$0f ;masks scundary-address cp r17,r18 ;compares table-value with searched value breq l10150 ;b.i. searched value is this table value l10140: cpi r28,$d0 ;read from 00df to end 00d0? brne l10130 ;b.i.not end ldi r25,$b7 ;b7-- rcall l12490 clc ;flag f.no entry for this devicenumber and this secundary-address ret ;------ l10150: ldi r25,$b8 ;b8-- rcall l12490 clc sbci r28,$10 ;d0->c0 ... df->cf ld r18,y ;table command&devicenumber cp r18,r16 ;searched devicenumber breq l10160 ;b.i.wanted clc sbci r28,$f0 ;c0->d0 rjmp l10140 ;b.i.not wanted ;--------- ; y = readvector showes to wanted entry l10160: ldi r25,$b9 ;b9-- =correct devicenumber and correct secundary address rcall l12490 cpi r28,$c0 breq l10200 ;b.i.searched entry is already at actual position ldi r25,$ba ;ba-- rcall l12490 mov r18,r28 ;backup vector-low where wanted entry is rcall l10180 ;copies c0-c(x) -> c1-c(x+1) rcall l10170 ;copies d0-d(x) -> d1-d(x+1) ;copies e0-e(x) -> e1-e(x+1) l10170: ldi r25,$bb ;bb-- rcall l12490 clc sbci r18,$f0 ;c1->d1 cf->df d1->e1 df->ef mov r28,r18 ;increments vector +$10 l10180: ld r16,y ;backup wanted (->actual) value mov r30,r28 ; z = writevector low ldi r31,$00 ; z high inc r30 ;increments write vector l10190: ld r17,-y ;copies c0->c1 st -z,r17 mov r17,r28 ;lowbyte read-vector andi r17,$0f ;masks bit 3-0 brne l10190 ;b.i.not 00c0 00d0 00e0 st y,r16 ;writes actual value to 00c0 00d0 00e0 l10200: ldi r25,$bc ;bc-- rcall l12490 sec ;flag for entry present (and at actual position) ret ;------------------------------------------------------------------------------------------------ l10210: ldi r25,$bd ;bd-- rcall l12490 rcall l10120 ;searches wanted buffer talk-buffer-close if necessary brcc l10240 ;b.i.wanted buffer doesn't exist ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - l10220: ldi r25,$be ;be-- rcall l12490 ldi r30,$c0 ; talk-buffer-close actual entry ldi r31,$00 ; z = writevector =$00c0 ldi r28,$c1 ; changes: Y-vector ldi r29,$00 ; y = readvector =$00c1 Z-vector l10230: ld r16,y+ ;reads from c1 cf d1 df e1 ef r16 st z+,r16 ;write to c0 ce d0 de e0 ee cpi r28,$f0 brne l10230 ;b.i.not at end ldi r25,$bf ;bf-- rcall l12490 sts $cf,r26 ;#$00 sts $df,r26 sts $ef,r26 l10240: ret ;================================================================================================ l10250: push r16 ;2 (+3 for rcall) 10µs waiting loop ldi r16,$15 ;1 ($17at8MHz) l10260: dec r16 ;1 brne l10260 ;2/1 pop r16 ;2 ret ;4 3+2+1+21*(1+2)-1+2+4=74cycles=10µs at 7.37MHz ;------------------------------------------------------------------------------------------------ l10270: push r16 ;2 (+3 for rcall) r24*10µs waiting loop ldi r16,$16 ;1 ($18at8MHz) l10280: dec r16 ;1 3*22-1=65 brne l10280 ;2 in loop 1 not in loop nop ;1 pop r16 ;2 dec r24 ;1 2+1+65+1+2+1+2=74 brne l10270 ;2 in loop 1 not in loop ret ;4 ;================================================================================================ l10290: ldi r25,$10 ;$10-- e902 wait until IecAtn=inactive rcall l12490 l10300: ldi r18,$07 ;e902 l10310: sbis $10,2 ;2 skips if AtnIn=inactive e8d2 rjmp l10300 ; =Atn=active dec r18 ;1 brne l10310 ;2 7*5=35 = 4µs at 7.3728MHz lds r18,flicbb ;=IecAtn=inactive andi r18,$7f sts flicbb,r18 ;clears flag f.Atn-mode ;is also made here, because it could be that there is an error at ;sending a byte f.e.to Ieee => could be that then flag would never be ;cleared??? ldi r25,$11 ;$11-- rcall l12490 ret ;------------------------------------------------------------------------------------------------ l10320: cli ;disbale IRQs read byte after ATN-edge e85b cbi $18,4 sbi $17,4 ;sets bit4 of DDRB = DataOut=active ; (should be so from IRQ-routine) ; (important when IecAtnIn changes from inactive to active while ; IecOut or IecIn (when IRQs inhibited)) ;AtnAck-hardware isn't present ;Pullup-resistors aren't necessary because ;-there are resistors at the inputs-pins of the AVR (if no driver chips) ;-the 7407-inputs pullup strongly enough (if driver chips) ldi r25,$02 ;02-- rcall l12490 ldi r16,$80 sts flicbb,r16 ;sets flag for Iec-Atn clears flag for Iec-Listen,-Talk,-Eoi ldi r16,$7f out $3d,r16 ;stackpointerlow = 7f out $3e,r26 ;stackpointer high to 0 => stackpointer to 007f cbi $18,6 ;clears bit6 of PortB cbi $17,6 ;clears bit6 of DDRB = SrqOut=inactive (because input) cbi $18,2 cbi $17,2 ;clears bit2 of DDRB = ClockOut=inactive (because input) ldi r25,$03 ;03-- rcall l12490 sts icsaco,r26 ;clears if case that there is no secundary address sts icsawo,r26 ;open10,10 instead of open10,10,0 sts iccode,r26 ;emumod & devpos mustn't be cleared because at unlisten/untalk it is ;important to which emulated device the command goes sts iccbjd,r26 ;#$00 clears flag f. JiffyDos Iec routines l10330: rcall l10690 ;reads IEC-bus (Atn & Clock&Data&Srq) (If IecAtn=inactive -> l10640) brpl l10330 ;b.i.IecClock=active waits until C64 makes Clock=inactive (c41:e87b) ; ldi r25,$04 ;04-- rcall l12490 ;JiffyDOS waits here 350µs (but JD doesn't wait (j41:e879) ;until C64 makes Clock=active (l10330) l10340: rcall l10770 ;reads one byte from C64 (r16) DataOut=active ClockOut=inactive e884 ; (allways CBM-routines) ldi r25,$05 ;05-- rcall l12490 mov r25,r16 ;xx-- displays received IEC-byte to the 8 LEDs rcall l12490 cpi r16,$3f brne l10380 ;b.i.not unlisten ;=UNLISTEN---------- rcall l10290 ;waits until IecAtn=inactive ;at Unlisten, Untalk, SecundaryAddress after Listen/Talk: ; (not at Listen, Talk) ;wait at once after having received the final command-byte for ;Iec-Atn=inactive because: ;example: 28 Listen to 8 (1541) ; 6f SA to command/error-channel of 1541 ; ... ; 3f Unlisten ; 48 Talk to 8 ;C64 sends Untalk => C64 makes IecAtn=inactive ;C64 sends at once Talk => C64 makes IecAtn=active again ;Time-period where IecAtn=inactive is very short ;If AVR wouldn't wait for IecAtn=inactive here but would send the Unlisten ;to an IEEE device, it wouldn't see that IecAtn was inactive (while it ;had sent to IEEE) and would wait at the end (at 1541 e902) in an endless- ;loop that C64 makes IecAtn=inactive after Unlisten while C64 made ;IecAtn=active at Talk =>AVR would be in endless loop ;AVR-DataOut is active => C64 waits when Talk until AVR is ready ldi r25,$3f ;3f-- rcall l12490 sts iccode,r16 ;stores read IEC-command byte to IecCommand&Devicenumber lds r17,emumod ;emulation mode cpi r17,$00 brne l10350 ;b.i.not IEEE rcall l11880 ;IEEEATNOUT (r16=#$3f=unlisten) cbi $14,3 ;DdrC3=input sbi $15,3 ;PortC3 =PullUpOn = IeeeAtn=inactive rjmp l10370 l10350: cpi r17,$20 brne l10360 ;b.i.not Centronic rjmp l10370 ;=Centronic do nothing at unlisten? l10360: nop ;do nothing at AVR-internal? l10370: lds r16,flicbb ;flag IecBusBits andi r16,$df ;clears bit 5 sts flicbb,r16 ;clears flag f.listen rjmp l10640 ;not l10680 as in 1541 because waiting for IecAtn=inactive was before ;------------------------------------------------------------------------- l10380: cpi r16,$5f brne l10410 ;b.i.not untalk rcall l10290 ;waits until C64 makes IecAtn=inactive (see Unlisten) ldi r25,$5f ;5f-- rcall l12490 sts iccode,r16 ;stores read IEC-command byte to IecCommand&Devicenumber lds r17,emumod ;emulation mode cpi r17,$00 brne l10390 ;b.i.not IEEE rcall l11880 ;IEEEATNOUT (r16=#$3f=unlisten) cbi $14,3 ;DdrC3=input sbi $15,3 ;PortC3 =PullUpOn = IeeeAtn=inactive rjmp l10400 l10390: ;nop ;do nothing at Centronics / AVR internal l10400: lds r16,flicbb ;flag IecBusBits andi r16,$bf ;clears bit6 sts flicbb,r16 ;clears flag f. talk rjmp l10640 ;not l10680 (see Unlisten) ;------------------------------------------------------------------------- l10410: ; Listen Talk SecAd Open Close mov r17,r16 ;received Iec-command-byte 20 2f 30 3e 40 4f 50 5e 60 6f e0 ef f0 ff andi r17,$60 ;01100000 20 20 20 20 40 40 40 40 60 60 60 60 60 60 mov r25,r17 ;displays Listen-/Talk-/SA-bits rcall l12490 ;xx-- ldi r28,$a0 ;ylow y=00a0 Vector to 00a0 (90-9f = table) ldi r29,$00 ;yhigh cpi r17,$40 brne l10480 ;b.i.not Talk l10420: ld r17,-y ;009f-0090 predecremented andi r17,$df ;%11011111 masks Listen-bit off cp r16,r17 breq l10440 ;b.i.Talk to this device in table device numbers cpi r28,$90 brne l10420 cpi r16,$40 ;compares with devicenumber #$00 = avr-internal breq l10430 ;b.i.avr-internal rjmp l10670 ;Talk but not to AVR = all inactive&wait until C64 makes Atn=inactive l10430: ldi r17,$40 ;#$40->emumod = AVR-internal ldi r18,$00 ;#$00->devicepossibilities rjmp l10450 ; l10440: clc ;Talk to AVR r29=pointer in tadenu sbci r28,$f0 ;adds #$10 90->a0 91->a1 9f->af ld r17,y ;loads emulationmode clc sbci r28,$f0 ;adds #$10 a0->b0 a1->b1 ... af->bf ld r18,y ;device-posibilities l10450: sts iccode,r16 ;stores read IEC-command byte to IecCommand&Devicenumber sts emumod,r17 sts devpos,r18 cpi r17,$00 brne l10460 ;b.i.not Talk to Ieee ldi r25,$a0 ;a0-- rcall l12490 ld r16,y ;loads b0-bf device possibilities andi r16,$1f ;masks device-number-bits ori r16,$40 ;set Talk-bit = device-number-translation rcall l11880 ;sends byte to Ieee with AtnHigh ATNOUT brcc l10470 ;b.i.ok rjmp l10670 ;error (device not present time out) l10460: ;Talk to Centronic-printer (not possible) cpi r17,$40 ;AVR-internal (do what?) l10470: ldi r16,$c0 ;11000000 sts flicbb,r16 ;sets flag f.Talk clears flag f.Listen (Atn-flag stays active) ldi r25,$a1 ;a1-- rcall l12490 rjmp l10620 l10480: cpi r17,$20 breq l10490 ;b.i.Listen 20-3e %001..... rjmp l10570 ;not Listen 20-3e %001..... l10490: ld r17,-y ;009f-0090 predecremented andi r17,$bf ;masks Talk-bit off cp r16,r17 breq l10510 ;b.i.Listen to this device in table device numbers cpi r28,$90 brne l10490 cpi r16,$20 ;compares with devicenumber #$00 = avr-internal breq l10500 ;b.i.avr-internal rjmp l10670 ;Listen but not to AVR = all inactive&wait until C64 makes Atn=inactive l10500: ldi r17,$40 ;#$40->emumod = AVR-internal ldi r18,$00 ;#$00->devicepossibilities rjmp l10520 ; l10510: ldi r25,$a0 ;a0-- rcall l12490 clc ;Listen to AVR r29=pointer in tadenu sbci r28,$f0 ;adds #$10 90->a0 91->a1 9f->af ld r17,y ;loads emulationmode clc sbci r28,$f0 ;adds #$10 a0->b0 mov r25,r17 rcall l12490 ld r18,y ;device-posibilities l10520: sts iccode,r16 ;stores read IEC-command byte to IecCommand&Devicenumber sts emumod,r17 sts devpos,r18 andi r18,$80 ;masks bit whether floppy breq l10530 ;b.i.no floppy (=chanel 15 = normal channel = no errorchannel) ldi r17,$0f ;=SA for command/errorchannel (r16=devicenumber-bits but listen not talk) rcall l10210 ;close errorchannel to listened device if entry exists lds r16,iccode ;restores IEC command & devicenumber lds r17,emumod ;restores emulation-mode l10530: cpi r17,$00 brne l10540 ;b.i.not Ieee ldi r25,$80 rcall l12490 lds r16,devpos ;loads b0-bf device possibilities andi r16,$1f ;masks device-number-bits ori r16,$20 ;set Listen-bit = device-number-translation rcall l11880 ;sends byte to Ieee with AtnHigh ATNOUT brcc l10560 ;b.i.ok rjmp l10670 ;error (device not present time out) l10540: cpi r17,$20 brne l10550 ;b.i.not listen to centronics-printer ldi r25,$25 ;25-- rcall l12490 rcall l12050 ;tests if centronic-printer is present brcc l10560 ;b.i.printer is present rjmp l10670 ;=printer not connected or off = data=inactive wait until Atn=inactiv l10550: cpi r17,$40 ;AVR-internal (do what) l10560: ldi r16,$a0 ;10100000 sts flicbb,r16 ;sets flag f.listen clears flag f.talk (Atn-flag stays active) rjmp l10620 l10570: cpi r16,$61 ;compares received commandbyte with SA=$61 = SA for SAVE (Je89f) brne l10580 lds r18,flicbb ;flag Iec Bus B cpi r18,$c0 ;compares with flag f.Talk flag f.not-Listen brne l10580 ;b.i.not TALK ldi r16,$60 ;loads SA for LOAD =TALK+SAforSAVE=illegal=flag for JiffyDOS-LOAD sts iccbjd,r16 ;IeC CBM/JD = JD-LOAD ;AVR received TALK + SAforSAVE from C64 ;AVR sends TALK + SAforLOAD to IEEE-floppy => IEEE-floppy sends bytes l10580: cpi r17,$60 ;e8b7 breq l10590 ;b.i.open,close,secundary-address rjmp l10670 ;not open,close,secundary-address (= command isn't to AVR) ; = open,close,secundary-address ;listen+open: talk-error-buffer is already closed when listen received ; at l10520-l10530 ; unknown whether the here-opened-file is later for writing ; into file (listen) or for reading from file (talk) ; => don't open a new talk buffer after liste+open ; open a new talk-buffer when ; (after listen+open+filename+unlisten) talk+SA is ; received (then you know that it's talk) ; (if it would be listen then it would be: ; listen+open+filename+unlisten+listen+SA) ;listen+close: talk-error-buffer is already closed when listen received ; at l10520-l10530 ;listen+SA: talk-error-buffer is already closed when listen received ; at l10520-l10530 ;talk+SA: ; -if no floppy => nothing (look if talk-buffer already exists ; else open it) ; -if floppy => (look if talk-buffer already exists, else open it) ; -if data-channel (0-14) => close error-talk-buffer ; -if error-chanel (15) => nothing additional ;there are two kinds of talk-buffers: - a talk-data-buffer (=talk-buffer) ; - a talk-error-buffer l10590: rcall l10290 ;waits until C64 makes IecAtn=inactive (see Unlisten) ldi r25,$06 ;06-- rcall l12490 lds r17,emumod ;emulation mode cpi r17,$00 brne l10610 ;b.i.not Ieee ldi r25,$07 ;07-- rcall l12490 mov r18,r16 ;=read IEC-command-byte rcall l11900 ;IEEEOUT r16=read Iec command byte -----r18 mustn't change---- ;brcc l10600 ;b.i.ok do what if error????????????????? ;IEEE-lines aren't set for Talk here, because it's possible that there ; is no SA address (f.e. open2,8,"xyz) l10600: mov r16,r18 ;restores IEC-command byte l10610: sts icsaco,r16 ;Iec-secundary-address-complete mov r17,r16 andi r16,$0f sts icsawo,r16 ;SA-only without bits whether open/close/SA mov r16,r17 ;SA (complete) andi r16,$f0 cpi r16,$e0 brne l10640 ;b.i.not close not brne l10680 as at 1541 because waiting for ; C64-Atn=inactive was made before (see Unlisten) ldi r25,$08 ;08-- rcall l12490 ;nop ;close ;at close in 1541 continues here ;after close there should be sent an Unlisten (Listen, Close, Unlisten) ;(after Open and SecAddr a.ListenTalk there are databytes sent) ;between close and unlisten C64 makes Atn=inactive for short period of ; time ;=>when 1541/AVR has closed then it's perhaps faster to receive the ;Unlisten here at once without waiting for C64 makes IecAtn=inactive ;At 1541: There should be a hardwareIRQ and the flag for a ; Atn-active-change should be set ;At AVR: AVR forgets to see that C64 had made IecAtn=inactive for a ; short time-period ;If there should be a problem here perhaps a rjmp l10640 could help??? l10620: ldi r16,$0f ;e8d2 l10630: sbis $10,2 ;skips if AtnIn=inactive e8d2 rjmp l10340 ;=Atn=active -> read next command byte dec r16 brne l10630 l10640: lds r16,flicbb ;=Atn-mode is finished AtnIn=inactive ----------------------------- e8d7 andi r16,$7f sts flicbb,r16 ;clears flag f.Atn-mode ;there is no AtnAck-Hardware ; AVR-DataOut is active ldi r25,$09 ;09-- rcall l12490 ldi r16,$40 ;%01000000 out $3b,r16 ;General IRQ mask register allows int0 irq sei ;enable IRQs ;=> AVR-AtnAck-emulation on ;if C64 makes C64-Atn=active then the AVR makes an IRQ and sets ;AVR-DataOut=active (but AVR-DataOut is already active) ;=> C64 waits lds r16,flicbb ;flag f.listen e8e3 andi r16,$20 breq l10650 ;b.i.no listen ldi r25,$0a ;0a-- rcall l12490 lds r16,iccode ;IEC command&devicenumber =listen lds r17,icsawo ;IEC secundary address without bits for open/close/SA rcall l10210 ;close this (listened to) talk-buffer (data-channel (0-14) ; or error-channel (15)) rcall l11580 ;jsr $ea2e reads bytes from C64 and sends to Ieee/printer/AVRinternal ;IecIn disables IRQ= switches AtnAck-emulation off rjmp l13220 l10650: lds r16,flicbb andi r16,$40 breq l10660 ;b.i.not talk ldi r25,$a8 ;a8-- rcall l12490 cbi $17,4 ;DataOut=inactive perhaps waitingloop here??? =talk sbi $17,2 ;ClockOut=active ;AVR-DataOut is now inactive!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ;=>if C64 makes now ATN=active then the AVR-IRQ-routine (l10000) must ;make AVR-DataOut fast enough to active to show to the C64 that the AVR ;isn't ready ;if there will be a routine where the IRQ cannot be disabled ;(f.e. later secundary IEC-bus-routines with any fastloader) ;then the AVR must perhaps make AVR-DataOut to active while the IRQ is ;disabled and make it to inactive when the IRQ can be enabled ?? ;perhaps waiting here at least 40µs because 1541 is so slow ; (only if 360µs JD loop would be deleted) ldi r24,$28 ;=40 rcall l10270 ;400µs waiting loop ;perhaps 360µs delay at first byte? (fb0f) ;JiffyDos makes 360µs delay-loop at fb0f if JD-DataOut or JD-Load ; (not at CBM-DataOut) (don't know why) ;AVR makes 400µs delay loop allways (at JD-DataOut, JD-Load, CBM-DataOut) ;if the delaylopp would be deleted at CBM-DataOut then there should be ; at least a 50µs delayloop that allows the C64 to read the lines even if ; there should be a C64-badline) rcall l11690 ;e8f7 job when Talk received jsr e909 IRQ is enabled l10660: ;cbi $17,2 ;e8fa ea4e ;cbi $17,4 ;C64 can send f.e. a new Talk-command while AVR has send old Untalk to ;Ieee. AVR must let IecDataOut to active to prevent that C64 thinks that ;AVR would be in receive-routine and C64 would begin to send the Talk ; while AVR isn't yet in receive-routine but in main-waiting-loop rjmp l13220 ;to main-waiting-loop l10670: cbi $17,2 ;ClockOut=inactive drive isn't listened/talked to e8fd cbi $17,4 ;DataOut=inactive l10680: ;e902 rcall l10290 ;waits until Atn=inactive rjmp l10640 ;=Atn is inactive ;------------------------------------------------------------------------------------------------ ;l-99011: mov r08,r16 ;copies actual value -> old value test of Atn-mode-change ea59 ; (error at first time) ; ldi r16,$05 ; mov r07,r16 ; counter register ; ;l-99021: in r16,$10 ;1 PortD = IecAtnIn ; andi r16,$04 ;1 masks Bit2 = IecAtnIn ; cpse r08,r16 ;2 compares old and actual value of IecAtnIn ; rjmp l-99011 ; b.i.IecAtnIn is not constant ; ;---------- ; dec r07 ;1 7*5=35 = 4µs at 8Mhz ; brne l-99021 ;2 (1541 makes 1541:lda$1800 cmp$1800 = 4µs bus constant) ;=IecAtn-line is constant for 4µs <-------mode1------------------------ l10690: clr r08 ;clears r08 test of Atn-mode-change ea59 ldi r16,$03 ; routine changed => perhaps check timing???????????????? mov r07,r16 ;counter for 3 times l10700: in r16,$10 ;1 PortD = IecAtnIn andi r16,$04 ;1 masks Bit2 = IecAtnIn add r08,r16 ;1 ldi r16,$03 ;1 l10710: dec r16 ;1 3*3-1 +1 = 9 +1+1+1 + 1 + 1+2 = 16 = 2µs brne l10710 ;2/1 mov r16,r08 ;1 dec r07 ;1 reads IecBus 3 times 4µs and takes average <----mode2----------- brne l10700 ;2 3210=bits of PortD ; 0000 0000 0000 0100 ; 0000 0000 0100 0100 ; 0000 0100 0100 0100 ; ---- ---- ---- ---- ; 0000 0100 1000 1100 lds r07,flicbb ;flag f. Atn-mode rol r07 ; AtnMode bit -> carry andi r16,$08 ;masks IecAtnIn brcc l10720 ;b.i.not in Atn-mode ; =Atn-mode breq l10730 ;b.i.in Atn-mode and AtnIn=active = mode stays Atn-mode push r25 ldi r25,$40 ;40-- rcall l12490 pop r25 rcall l12490 ;xx-- (analysebyte from routine above to debugbuffer) mov r25,r20 ;conter for IecIn bits perbyte rcall l12490 mov r25,r17 ;so far read IecIn byte rcall l12490 ldi r16,$7f ;mode changes from Atn- to data-mode out $3d,r16 ;stackpointerlow = 7f rjmp l10640 ;to routine at end of Atn !!stack is at C64 wrong!! ;--- l10720: ; =not in Atn-mode=in Data-mode brne l10730 ;b.i.in Data-mode and AtnIn=inactive = mode stays in data-mode ; (DataOut=active is important but made at follow routine) ;ldi r25,$20 ;20-- ;rcall l12490 ;temporary !!!must be fast enough to make data fast enough to active rjmp l10320 ;reads byte after Atn-edge = change from data- to Atn-mode ;------------------------------------------------------------------------------------------------ ;l-99031: mov r08,r16 ;copies actual value -> old value reads IEC-bus-port e9c0 ; ; (error at first time) ; ldi r16,$05 ; ; mov r07,r16 ;counter ; ;l-99041: in r16,$16 ;1 PortB = IecPort ; andi r16,$2a ;1 %00101010 masks Bit 5,3,1 = DataIn ClockIn SrqIn ; cpse r08,r16 ;2 compares old and actual value ; rjmp l-99031 ; b.i.value is not constant ; ;---------- ; dec r07 ;1 7*5=35 = 4µs at 8Mhz ; brne l-99041 ;2 (1541 makes 1541:lda$1800 cmp$1800 = 4µs bus constant) l10730: clr r08 ;clears r08 ldi r16,$03 ; routine changed => perhaps check timing???????????????? mov r07,r16 ;counter for 3 times l10740: in r16,$16 ;1 PortB = IecPort andi r16,$2a ;1 %00101010 masks Bit 5,3,1 = DataIn ClockIn SrqIn add r08,r16 ;1 ldi r16,$03 ;1 l10750: dec r16 ;1 3*3-1 +1 = 9 +1+1+1 + 1 + 1+2 = 16 = 2µs brne l10750 ;2/1 mov r16,r08 ;1 dec r07 ;1 reads IecBus 3 times 4µs and takes average brne l10740 ;2 210=bits of PortB ; 000 000 000 010 ; 000 000 010 010 ; 000 010 010 010 ; --- --- --- --- ; 000 010 100 110 ;=IecPortIn read 3 times in 4µs ;DataIn ClockIn SrqIn ; 6 4 2 rol r16 ; 7 5 3 rol r16 ; c 6 4 rol r07 rol r16 ; 7 5 ror r07 ; c 7 5 andi r16,$a0 ;%10100000 masks bit 7 and 5 (carry stays) ;CarryLow = DataInActive CarryHigh = DataInInactive ;Plus = ClockInActive Minus =ClockInInactive ; (SrqIn=bit 5 of r16) ret ;------------------------------------------------------------------------------------------------ l10760: cli ;disable IRQs reads one byte from C64 IecIn e9c9 ;disadvantage: AVR-AtnAck-emulation is switched off ; ( !!!changes Z-vector!!! if differnt timing for uni NTSC PAL) ; (so far different timing isn't implemented) ; (JD-1541 also hasn't differnt timing) lds r16,iccbjd ;Iec CBM / JiffyDos DataOut=active ClockOut=inactive cpi r16,$00 breq l10770 ;=CBM-serial bus routines (00) rjmp l10920 ;b.i.JD-serial bus routines (01-ff 1-255) l10770: cli ;disables IRQs from l10340 => CLI=important CBM-IECIN ldi r20,$08 ;counter f. 8 bits per byte ldi r25,$25 ;25--- rcall l12500 l10780: rcall l10690 ;tests for AtnMode change & reads bus brpl l10780 ;b.i.C64 makes Clock=active / waits until C64 makes Clock=inactive ldi r25,$26 ;26--- rcall l12500 cbi $17,4 ;DataOut=inactive l10790: rcall l10730 ;reads bus brcc l10790 ;b.i.C64 makes DataIn=active / waits until C64 makes DataIn=inactive ;IRQ is disabled (CLI) ;=> AtnAck-emulation is switched off ;=> even if C64 makes Atn=active then the AVR shouldn't make ; AVR-DataOut=active ;=>the Data-line couldn't be made to active by the AVR ;=> the AVR cannot lock itself => not dangerous? ldi r25,$27 ;27--- rcall l12500 ldi r19,$03 ;%.....011 out $33,r19 ;starts timer0 (8bit) with 8MHz/64 = 1count per 8µs for EOI-recognition out $32,r26 ;#$00 to timer0 counts up 32*8µs=256µs l10800: rcall l10690 brpl l10840 ;b.i.C64 makes Clock=active within 256µs in r19,$32 ;reads timer cpi r19,$20 brcs l10800 ;b.i.counter<$20 = if not yet 256µs without C64 makes Clock=active ;= 256µs without C64 makes Clock=active l10810: sbi $17,4 ;DataOut=active =EOI received EOI-begin ldi r25,$28 ;28--- rcall l12500 l10820: in r19,$32 cpi r19,$30 brcs l10820 ;waits 128µs (1541 waits 50µs) ldi r25,$29 ;29--- rcall l12500 cbi $17,4 ;DataOut=inactive l10830: rcall l10690 ;tests for Atn-mode-change & reads IEC-port brmi l10830 ;b.i.C64 makes Clock=inactive / waits until C64 makes Clock=active lds r19,flicbb ori r19,$10 sts flicbb,r19 ;sets flag for EOI EOI-end l10840: ldi r19,$a0 ;160 =for CBM/JD-recognition out $32,r19 ;from $a0 to $bb timer0 counts up $1b=27*8µs=216µs l10850: rcall l10730 ;reads bus (carry=DataIn) ldi r25,$2a ;2a--- mov r01,r25 ; (jd:e9f5) brmi l10900 ;b.i.C64 makes Clock=inactive / waits until C64 makes Clock=inactive lds r19,fljdal ;flag JiffyDos allowed CBM- (00) / JiffyDos- (80) IecBusRoutines andi r19,$80 breq l10850 ;b.i.only CBM allowed / JD-serial routines not alowed in r19,$32 ;=JD-IecBusRoutines allowed cpi r19,$bb brcs l10850 ;b.i.timer0 not counted 216µs (later 1500µs) ;r17=so far read IecInByte =C64 doesn't make Clock=inactive ; (f674) within 216µs = JiffyDos-C64 ; after transmission of bit 6 ; before transmission of bit 7 lsr r17 ;shifts so far read IecInByte into correct possition (bit7=low) ldi r28,$a0 ;ylow y=00a0 Vector to 00a0 (90-9f = table) ldi r29,$00 ;yhigh l10860: ld r19,-y ;009f-0090 predecremented cpi r28,$8f ;Ylow breq l10890 ;b.i.end of table reached =not Listen or Talk to this AVR andi r19,$df ;%11011111 masks Listen-bit off cp r17,r19 breq l10870 ;b.i.Talk to this device in table device numbers ld r19,y ;009f-0090 (y stays unchanged) andi r19,$bf ;%10111111 masks Talk-bit off cp r17,r19 brne l10860 ;b.i.not Listen to this device ;devicenumber #$00 (=AVR itself) isn't checked => speed from C64 to ;AVR-itself is allways CBM, never JD. Important for calibration byte ;when AVR isn't exactly running with 7.3728MHz l10870: ldi r19,$01 ;=Listen or Talk to AVR sts iccbjd,r19 ;sets flag f.JiffyDos sbi $17,4 ;DataOut=active l10880: ldi r24,$29 ;41 rcall l10270 ;waits 410µs cbi $17,4 ;DataOut=inactive l10890: lsl r17 ;shifts so far read IecInByte into old correct value out $32,r26 ;#$00 starts timer0 so that it counts 160*8=1400µs rjmp l10850 ;----------- l10900: ldi r25,$2b ;2b--- mov r01,r25 ;carry mustn't change from l10850 to here ror r17 ;shifts data-bit into r17 (not inverted at AVR) l10910: rcall l10690 ;tests for Atn-mode-change & reads IEC-bus brmi l10910 ;b.i.C64 makes Clock=inactive / waits until C64 makes Clock=active ldi r25,$2c ;2c--- mov r01,r25 dec r20 ;decrement counter for 8 bits per byte brne l10840 sbi $17,4 ;DataOut=active mov r16,r17 ldi r25,$2d ;2d--- rcall l12500 ret ;r16=r17=read byte dataOut=active ClockOut=inactive ; =>flag for C64 to wait ; => unimportant that AtnAck-emulation ; is switched off end CBM-IecIn ;. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l10920: ;andi r30,$18 ;masks bits for table for timing values JD-IecIn ;ldi r31,$ff ;sets Z-vector (iccbjd would contain vector to ; correct timing-table in flashRom => read it with LPM-command ; (so far not implemented) ;input lines aren't declicked ;JD-1541 aren't declicked, too ;if there should be errors then perhaps declick like at CBM-IecIn sbis $10,2 ;s.i.IecAtn=inactive l10930: rjmp l10320 ;reads byte after Atn-edge = change from data- to Atn-mode in r16,$16 ;reads IEC-bus (fbd3) cbi $17,4 ;DataOut=inactive (fbd8) ldi r17,$02 ;%.....010 ldi r19,$10 andi r16,$08 ;masks IecClockIn before) brne l10950 ;b.i.C64 makes Clock=inactive (=C64error) (!AVR made AVR-DataOut=inactive ; => if C64 wants to send the next command-byte then C64 could think ; that AVR-DataOut=inactive is flag that AVR is ready ; => C64 could begin to send next byte = bad l10940: sbis $10,2 ;s.i.C64-Atn=inactive rjmp l10320 ;reads byte after Atn-edge ;= change from data- to Atn-mode uni- sbis $16,3 ;s.i.C64 makes Clock=inactive 1541 versal NTSC PAL rjmp l10940 ;waits until C64 makes Clock=inactive (fdbe) ;when EOI: C64 sends last byte with EOI (ed19) 0µs 0µs ;C64-ClockOut stays active ;=>1541 even after having read last EOI-byte, ;it reads the next one ;=>it waits at l10940 ;C64 makes Atn=active (when sending unlisten (after EOI)) ;but at 1541 the AtnAck-hardware makes ;41-DataOut=active ;so 41-DataOut=active even if the direct ;DataOut-register is made ; inactive (fbd8) => 41-DataOut=active = falg for C64 to wait ;the AVR hasn't got an AtnAck-hardware = problem ;JD-C64 makes 64Clock=inactive (ed49) ;=>JD-1541 ends waiting-loop at l10940, but doesn't make ; AVR-DataOut=active, because there is no AtnAck-hardware and because ; AtnAck-emulation is switched off and ; if there would be no Atn-test four times while receiving one byte: ; AVRreads one not-existing byte from C64 ; and sees at the end of this that ; C64 makes Atn=active ; and jump to the CBM routine ; (where routine after ATN-edge is made) ; Here AvrDataOut is made active (very late) ; could be perhaps too late to show C64 that AVR isn't ready ; (and C64 could perhaps begin to send command byte) ;=> make test for C64-Atn=active four times l10950: out $33,r17 ;starts timer0 (8bit) with 8MHz/8 = 1count per 1µs ; 7.3728MHz/8 = 1count per 1.08507µs out $32,r19 ;$10 to timer0 counts up from $10 (0.41-1.1µs) ldi r16,$00 l10960: in r17,$32 ;reads timer0 cpi r17,$1f ;$20 at 8MHz brne l10960 ;waits $10=16µs from C64 makes Clock=inactive ; until reading first bits in r17,$16 ;reads IecPort Bit5=data=bit5 of port 0d-14 $10µs ; bit4=clock=bit3 of port lsl r17 ;bit5=data=bit6 bit4=clock=bit4 lsl r17 ;bit5=data=bit7 bit4=clock=bit5 brmi l10970 ;b.i.DataIn=inactive ori r16,$20 l10970: andi r17,$20 brne l10980 ;b.i.ClockIn=inactive ori r16,$10 l10980: sbis $10,2 ;s.i.C64-AtnIn=inactive rjmp l10320 l10990: in r17,$32 ;reads timer0 cpi r17,$2b ;$2d at 8MHz brne l10990 ;waits $0d=13µs from reading first bits ; until reading second bits in r17,$16 ;reads IecPort Bit7=data=bit5 of port 1a-21 $1dµs ; bit6=clock=bit3 of port lsl r17 ;bit5=data=bit6 bit4=clock=bit4 lsl r17 ;bit5=data=bit7 bit4=clock=bit5 brmi l11000 ;b.i.DataIn=inactive ori r16,$80 l11000: andi r17,$20 brne l11010 ;b.i.ClockIn=inactive ori r16,$40 l11010: sbis $10,2 ;s.i.C64-AtnIn=inactive rjmp l10320 l11020: in r17,$32 ;reads timer0 cpi r17,$35 ;$38 at 8MHz brne l11020 ;waits $0b=11µs from reading second bits ; until reading third bits in r17,$16 ;reads IecPort Bit1=data=bit5 of port 25-2c $28µs ; bit3=clock=bit3 of port lsl r17 ;bit1=data=bit6 bit3=clock=bit4 lsl r17 ;bit1=data=bit7 bit3=clock=bit5 brmi l11030 ;b.i.DataIn=inacive ori r16,$02 ;sets bit1 of to received byte l11030: andi r17,$20 ;masks bit5 = clock bit = bit 3 of to receive byte brne l11040 ;b.i.0-bit ori r16,$08 ;sets bit3 of to receive byte l11040: sbis $10,2 ;s.i.C64-AtnIn=inactive rjmp l10320 l11050: in r17,$32 ;reads timer0 cpi r17,$41 ;$45 at 8MHz brne l11050 ;waits $0d=13µs from reading third bits ; until reading fourth bits in r17,$16 ;reads IecPort Bit0=data=bit5 of port 32-39 $35µs ; bit2=clock=bit3 of port lsl r17 ;bit0=data=bit6 bit2=clock=bit4 lsl r17 ;bit0=data=bit7 bit2=clock=bit5 brmi l11060 ;b.i.DataIn=inactive ori r16,$01 ;sets bit0 of to received byte l11060: andi r17,$20 ;masks bit5 = clock bit = bit2 of to receive byte brne l11070 ;b.i.0-bit ori r16,$04 ;sets bit2 of to receive byte l11070: sbis $10,2 ;s.i.C64-AtnIn=inactive rjmp l10320 l11080: in r17,$32 ;reads timer0 cpi r17,$4d ;$52 at 8MHz brne l11080 ;waits $0d=13µs from reading fourth bits ; until reading EOI-bit in r17,$16 ;reads IecPort c64-EOI=clock=bit3 of port 3f-46 $42µs sbi $17,4 ;DataOut=active (fc05) sbis $10,2 ;s.i.C64-Atn=inactive (fc08) rjmp l10320 ;reads byte after Atn-edge = change from data- to Atn-mode andi r17,$08 ;masks bit3 =clock = EOI-bit breq l11090 ;b.i.noEOI lds r19,flicbb ori r19,$10 sts flicbb,r19 ;sets flag for EOI l11090: mov r17,r16 ;=received data-byte (never command-byte) ldi r25,$2f ;2f--- rcall l12500 mov r25,r16 ;----- rcall l12500 ret ;AVR-DataOut=active (AVR-ClockOut=inactive) ;=> =flag for C64 to wait end JD-IecIn ;=>unimportant that AVR-AtnAck-emulation is switched off (cli) ;================================================================================================ l11100: cli ;IecOut IEC from AVR to C64 DataOut=inactive ClockOut=active IecOut e916 ;disable IRQs r16 from l11830 ; => AtnAck-emulation is switched off (and AVR-DataOut=inactive) ; => dangerous if C64 makes C64-Atn=active sbis $10,2 ;s.i.C64-Atn=inactive rjmp l10320 ;read byte after Atn=active-edge !doesn't close Talk-buffer! ;never sends command-bytes => Atn is allways inactive cbi $17,4 ;DataOut=inactive (should be so even before) lds r17,iccbjd ;Iec CBM JiffyDos cpi r17,$00 brne l11220 ;b.i.JD ;------------ l11110: ;ClockOut=active DataOut=inactive CBM-IecOut ldi r25,$50 ;50-- rcall l12490 mov r25,r16 ;--to-send-byte-- rcall l12490 mov r18,r16 ;r18=r16=to sent IecOutByte rcall l10690 ;test for AtnMode Change & reads IecBus cbi $17,2 ;DdrB2 ClockOut=input =inactive (C64:ee1e) brcs l11130 ;b.i.C64 makes Data=inactive (=C64 not present?) ldi r25,$51 ;51-- mov r01,r25 ;faster than rcall l12490 l11120: rcall l10690 brcc l11120 ;waits until C64 makes Data=inactive (C64:ee2a) lds r16,flicbb ;IecBusBits andi r16,$01 ;masks bit 0 breq l11170 ;b.i.noEoi ; --------------begin of EOI ;rjmp l11150 ;1541 doesn't make this / 1541 waits second time for c64 makes data=inact ; this is faster (l11140)??? (C64:ee2a)?? l11130: ldi r25,$52 ;52-- rcall l12490 l11140: ;rcall l10690 ;=Eoi e937 ;brcc l11140 ;waits until C64 makes Data=inactive (C64:ee2a) l11150: ldi r25,$53 ;53-- C64 makes from ee47 to ee2a C64-DataOut to active for 84 cycles ;rcall l12490 would be too long mov r01,r25 ;if it hangs here then you can analyse it by r01=#$25 ;before line: handshake; no waiting-loop necessary ;------------------------------------------------------------------------ ;after line: timing important => waiting-loops l11160: rcall l10690 brcs l11160 ;waits until C64 makes Data=active (C64:ee47) ldi r25,$54 ;54-- rcall l12490 ; ----------------end of EOI l11170: sbi $17,2 ;e94b DdrB2 ClockOut=active sign to C64 that transmission starts (ee37) rcall l10690 brcc l11170 ;waits until C64 makes Data=inactive (C64:ee2a -first time if noEOI ; -second time if EOI) ldi r25,$55 ;55-- rcall l12490 ldi r24,$0a rcall l10270 ;100µs waiting loop ldi r17,$08 ;counter f.8 bits per byte ldi r24,$0e ;=14 = 140µs waiting-loop l11180: rcall l10270 ;140/100µs waiting-loop rcall l10730 ;reads IEC-port brcc l11210 ;b.i.C64 makes Data=active (=error) lsr r18 ;to sent IecOutByte DataOut = allways inactive here brcs l11190 ;b.i.1-bit (DataOut stays inactive) sbi $17,4 ;DdrB4 DataOut=active =0-bit l11190: rcall l10250 ;wait 10µs cbi $17,2 ;DdrB2 ClockOut=inactive ldi r24,$07 rcall l10270 ;wait 10µs*7 70µs sbi $17,2 ;DdrB2 ClockOut=active rcall l10250 ;wait 10µs cbi $17,4 ;DdrB4 DataOut=inactive rcall l10250 ;waits 10µs ldi r24,$0a ;value for 100µs waiting-loop dec r17 ;counter bits per byte brne l11180 ldi r25,$56 ;56-- rcall l12490 l11200: rcall l10690 ;test if AtnModeChange & reads bus brcs l11200 ;b.i.DataIn=inactive waits until C64 makes Data=active ldi r25,$57 ;57-- rcall l12490 clc ;flag f.ok sei ;allow IRQs important because DataOut=inactive ;if C64 sends command-byte then the serial drive must make DataOut=active ;=> AtnAck-substitute-IRQ must be allowed ; AtnAck-emulation is switched on ret ;ClockOut=active DataOut=inactive ;----------------- l11210: ldi r25,$5e ;5e-- rcall l12490 rjmp l13220 ;(C64 makes Data=active) to main waiting loop end CBM-IecOut ;. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l11220: ;400µs delay loop is made at L10670 =JD-IECOUT ;input-lines aren't declicked ;JD-1541 input-lines aren't declicked, too ;perhaps declick as at CBM-IecOut if there should be errors cbi $17,2 ;ClockOut=inactive (ff88) ldi r17,$02 ;%.....010 ldi r19,$10 ;startvalue counter l11230: sbis $10,2 ;2 s.i.C64-Atn=inactive rjmp l10320 ; reads byte after Atn-edge uni- ; = change from data- to Atn-mode 1541 versal NTSC PAL l11240: sbis $16,5 ;1/2 s.i.C64 makes Data=inactive rjmp l11230 ;2 waits until C64 makes Data=inactive (ffbb) 0µs 0µs ; 1 loop = 5cycles =0.68µs at 7.37MHz out $33,r17 ;1 starts timer0 (8bit) with 8MHz/8 = 1count per 1µs l11250: out $32,r19 ;1 $10 to timer0 counts up from $10 (0µs) 0.41-1.1µs ;when C64 makes Data=inactive then the AVR needs ;from l11240 to l11250 3cycles =0.41µs ;when the C64 makes Data=inactive 0.001µs after ;the AVR has read the line at l11240 then the AVR ;must wait one complete loop l11230 - l11240 ;=>delay is 0.41+0.68µs=1.1µs ;1541 sends inverted to sent byte ldi r19,$18 ;$19 at 8MHz rcall l11290 ;sends bit 0&1 06-0d $09µs ldi r19,$22 ;$23 at 8MHz rcall l11290 ;sends bit 2&3 10-17 $13µs ldi r19,$2c ;$2e at 8MHz rcall l11290 ;sends bit 4&5 1b-22 $1eµs ldi r19,$35 ;$38 at 8MHz rcall l11290 ;sends bit 6&7 25-2c $28µs ldi r19,$3f ;$43 at8MHz lds r16,flicbb ;IecBusBits andi r16,$01 ;masks bit 0 breq l11260 ;b.i.noEoi DataOut=inactive ClockOut=active ldi r16,$01 ;$01=Eoi DataOut=active ClockOut=inactive ; EOI rcall l11290 ;sends EOI: 30-37 $33µs ldi r19,$5d ;$64 at 8MHz ;hold this for about 21=33µs ;jd41 at EOI: sets data=active Clock=inactive ;doesn't wait at ffde-ffe3 ;rts to fb70 ;doesn't branch at fb72 ;makes data=inactive clock=active at fb74-fb78 ;=>holds EOI-flag for 33µs to bus ;if bus isn't constant within 4µs then the ;cmp-loop is perhaps made and it's ;42µs instaed of 33µs ;waits at ffde-ffe3 until C64 makes data=active ;(C64 at receiving IECIN-byte with EOI and Untalk: ; makes data=active for 109µs ; => enough time for 41 to read it) l11260: ldi r16,$02 ;$02=noEoi (EOI: 51-58 $54µs) ; noEOI: 30-37 $33µs ; noEOI: DataOut=inactive ClockOut=active rcall l11290 ;sends noEOI (or end after EOI): rcall l10250 ;waits 10µs (jd41 reads bus 4µs after having made dataOut=inactive) l11270: sbis $10,2 ;s.i.C64-Atn=inactive rjmp l10320 ;reads byte after Atn-edge = change from data- to Atn-mode sbic $16,5 ;s.i.C64 makes Data=active rjmp l11270 ;waits until C64 makes Data=inactive (ffbb) l11280: ret ;DataOut=inactive ClockOut=active end JD-IecOut ;------------------------------------------------------------------------------------------------ l11290: in r17,$17 ;reads ddrB andi r17,$eb ;%11101011 masks off bit4&2 DataOut&ClockOut lsr r16 ;to send IecOut-byte bit0,2,4,6->carry brcs l11300 ;b.i.1-bit to send = inverted 0-bit ori r17,$04 ;sets clockOut bit of port l11300: sbis $10,2 ;s.i.C64-Atn=inactive rjmp l10320 ;read byte after Atn=active-edge !doesn't close Talk-buffer! ;never sends command-bytes => Atn is allways inactive lsr r16 ;bit1,3,5,7->carry brcs l11310 ori r17,$10 ;sets DataOut bit of port l11310: in r18,$32 ;reads timer0 cp r18,r19 brcs l11310 ;waits out $17,r17 ;makes bit0,2,4,6->ClockOut bit1,3,5,7->DataOut ret ;------------------------------------------------------------------------------------------------ l11320: ;r16 = actual byte =JiffyDOS-LOAD ;r17 = ddrB ;r18 = timer0 AVR-DataOut=Inactive ;r19 = timevalues AVR-ClockOut=Active DI CA ;r20 = end of load buffer IRQ is enabled ; AtnAck-emulation is switched on ;r28 = Y-vector low =good ;r29 = Y-vector high ;400µs delay-loop is made at l10650 lds r16,fljdal ;flag JiffyDOS allowed andi r16,$01 ;masks bit for way to see when C64 is ready for next block brne l11340 ;b.i.C64-DataOut=inactive at fb06-way l11330: sbis $10,2 ;s.i.C64-Atn=inactive = waiting-loop-way rjmp l13220 ; main waiting looop (!talk buffer isn't closed) sbis $16,5 ;s.i.C64 makes Data=Inactive (ff30) rjmp l11330 ;waits until C64 makes Data=Inactive (fb06) l11340: sts erbuen,r26 ;#00 clears error buffer end because it is overwritten with LOADbuffer ldi r25,$c0 ;c0-- rcall l12490 lds r16,iccode ;IEC command&devicenumber (don't close error channel) lds r17,icsawo ;IEC secundary address without bits for open/close/SA rcall l10080 ;open talk-buffer if necessary and test if talk-byte is in buffer ;equal=no byte in buffer notequal=byte in buffer (!changes Y-vector!) breq l11400 ;b.i.byte isn't in talk-buffer (= error) ldi r25,$c1 ;c1-- rcall l12490 lds r16,$e0 ;byte of talk-buffer sts $0100,r16 ;stores to $0100 lds r17,$d0 ;talk-SA&bits-buffer rcall l10220 ;close actual buffer (changes Y, Z, r16 !mustn't change r17) ldi r29,$01 ;Y-vector high ldi r28,$01 ;Y-vector low =$0101 = LOAD-buffer ldi r30,$80 ldi r31,$02 ;Z-vector =$0280 (=write load-analyse-bytes into not-existing RAM) mov r16,r06 ;analyse buffer mode cpi r16,$01 ;=no analyse-write into buffer but big errorbuffer = unlogical = illegal ; =flag for save load analyse bytes brne l11350 ;b.i.normal analyse-bytes ldi r31,$01 ;Z-vector = $0180 =vector for load-analyse-bytes (not for load-databytes) in r16,$16 ;IEC-bus st z+,r16 l11350: andi r17,$10 ;masks EOI-bit breq l11370 ;b.i.noEOI ldi r25,$c2 ;c2-- rcall l12490 st z+,r25 lds r16,flicbb ;flags IeCBusBits ori r16,$01 ;sets flag f.EOI sts flicbb,r16 ldi r20,$00 ;set buffer end = $0100 rjmp l11440 ;send buffer------------ l11360: ldi r28,$00 ;load write buffer = $0100 l11370: ldi r25,$c3 ;c3-- rcall l12490 st z+,r25 l11380: lds r16,emumod cpi r16,$00 brne l11400 ;b.i.not IEEE ;if only 1 byte is loaded from IEEE-floppy then AVR must wait ;until C64 made STOP-key-routine... (use AVR-timer?) l11390: rcall l11980 ;IeeeIn brcc l11410 ;b.i.ok l11400: rjmp l13220 ;error -> close talkbuffer -> to main-waiting-loop l11410: st y,r16 ;don't use st y+,r16 because highbyte Y-vector would be $0200 st z+,r16 lds r16,flicbb ;flags IeCBusBits andi r16,$01 ;masks bit for EOI brne l11430 ;b.i.EOI inc r28 ;lowbyte Y-vector mov r16,r06 ;analyse buffer mode andi r16,$01 breq l11420 ;b.i.bit0=0 = small error buffer = big load buffer 0100-01ff r16=#$00 ldi r16,$80 ;= big error buffer =small load buffer 0100-017f l11420: cp r28,r16 brne l11380 ldi r25,$c4 ;c4-- rcall l12490 st z+,r25 ;=buffer ($0100-$017f/$01ff) is full => send it to C64 dec r28 ;00->ff 80->7f =position of last byte in buffer l11430: mov r20,r28 ;r20 = end of buffer ldi r25,$c5 ;c5-- rcall l12490 st z+,r25 st z+,r20 l11440: ldi r28,$ff ;read vector = $01ff DI CA in r16,$16 st z+,r16 l11450: ldi r24,$14 ;=20 =200µs lds r16,fljdal ;flag JiffyDOS allowed andi r16,$01 breq l11470 ;b.i.waiting-loop-way l11460: sbis $10,2 ;s.i.C64-Atn=inactive = waiting-loop-way rjmp l13220 ; main waiting looop sbis $16,5 ;s.i.C64 makes Data=Inactive rjmp l11460 ;waits until C64 makes Data=Inactive (fb06) ldi r24,$06 ;60µs waitingloop because C64 needs ;from making C64-DataOut=inactive (fb06) ;to reading bus (fb0c) ;8 + 43 (badline) = 51µs ;waits until C64 has finished stop-key-routine ;and C64 is ready to receive next block ; 60µs l11470: rcall l10270 ;200µs waiting loop because C64 must have enought time for STOP-key ;routine (important if AVR receives only one byte from IEEE-floppy ;and this would be shorter than 200µs) ;D=I C=A => C64 is in loop at fb0c? in r16,$16 st z+,r16 sbi $17,4 ;DataOut=Active (ff98) DA CA rcall l10250 ;waits 10µs cbi $17,2 ;ClockOut=inactive (ff9d) DA CI ;=> C64 leaves loop at fb0e and ;branches to fb3e ldi r24,$08 rcall l10270 ;80µs waiting loop (ffa0-ffb5) in r16,$16 st z+,r16 l11480: inc r28 ;(at beginning: $01ff->$0100) ld r16,y ;= to sent byte from load-buffer $0100-$017f/$01ff st z+,r28 st z+,r16 l11490: cbi $17,4 ; DataOut=inactive cbi $17,2 ;1 ClockOut=inactive (important at first byte in loop) (ffb5) DI CI ldi r17,$08 ;1 l11500: dec r17 ;1 brne l11500 ;3/2 ;30cycles=4µs at 7.37MHz = enought time that data-line goes inactive ldi r17,$02 ;1 %.....010 ldi r19,$10 ;1 startvalue counter in r24,$16 st z+,r24 l11510: sbis $10,2 ;2 s.i.C64-Atn=inactive rjmp l13220 ; main waiting loop uni- ; 1541 versal NTSC PAL l11520: sbic $16,5 ;1/2 s.i.C64 makes Data=active rjmp l11510 ;2 waits until C64 makes Data=active (ffbb) 0µs 0µs ; 1 loop = 5cycles =0.68µs at 7.37MHz out $33,r17 ;1 starts timer0 (8bit) with 8MHz/8 = 1count per 1µs l11530: out $32,r19 ;1 $10 to timer0 counts up from $10 (0µs) 0.41-1.1µs ;when C64 makes Data=inactive then the AVR needs ;from l11520 to l11530 3cycles =0.41µs ;when the C64 makes Data=inactive 0.001µs after ;the AVR has read the line at l11520 then the AVR ;must wait one complete loop l11510 - l11520 ;=>delay is 0.41+0.68µs=1.1µs ldi r25,$c6 st z+,r25 in r25,$16 st z+,r25 ;1541 sends inverted to sent byte ldi r19,$18 ;$19 at 8MHz rcall l11290 ;sends bit 0&1 (ffbd) 06-0d $09µs D1 C0 ldi r19,$22 ;$23 at 8MHz rcall l11290 ;sends bit 2&3 (ffc4) 10-17 $13µs D3 C2 ldi r19,$2c ;$2e at 8MHz rcall l11290 ;sends bit 4&5 (ffcc) 1b-22 $1eµs D5 C4 ldi r19,$35 ;$38 at 8MHz rcall l11290 ;sends bit 6&7 (ffd3) 25-2c $28µs D7 C6 rcall l10250 ;waits 10µs (1541 holds bit 7&6 at IECOUT 10µs long ;=> this must be enough also at JD-LOAD) cp r20,r28 ;compares end of buffer with actual value brne l11480 ;b.i.not at end of buffer ldi r25,$c8 ;(c8--) mov r01,r25 st z+,r25 sbi $17,2 ;ClockOut=Active (about 11µs later than bit 30-37 $33µs cbi $17,4 ;DataOut=Inactive (ffdb) 7&6 set to bus) rcall l10250 ;waits 10µs DI CA ldi r25,$c9 ;(c9--) mov r01,r25 st z+,r25 in r25,$16 st z+,r25 l11540: sbis $10,2 ;s.i.C64-Atn=inactive rjmp l13220 ; main waiting looop sbic $16,5 ;s.i.C64 makes Data=active rjmp l11540 ;waits until C64 makes Data=active (fb51) ldi r25,$ca ;(ca--) mov r01,r25 st z+,r25 in r25,$16 st z+,r25 lds r16,flicbb ;flags IecBusBits andi r16,$01 brne l11560 ;b.i.EOI ldi r25,$cb ;cb-- DI CA rcall l12490 st z+,r25 in r25,$16 st z+,r25 cpi r31,$04 ;highbyte Z-vector brcs l11550 ldi r31,$04 l11550: rjmp l11360 ;noEOI = receive next block from IEEE-floppy l11560: ldi r25,$cc ;cc-- rcall l12490 st z+,r25 in r16,$16 st z+,r16 ldi r24,$0a ;=10 AVR-DataOut=Inactive AVR-ClockOut=Active rcall l10270 ;100µs waiting loop (ff65) cbi $17,2 ;ClockOut=inactive (ff65) DI CI ldi r24,$0a ;=10 rcall l10270 ;100µs waiting loop (ff68) sbi $17,2 ;ClockOut=Active (ff6b) DI CA ldi r24,$0a ;=10 rcall l10270 ;100µs waiting loop (ff6e-ff71) cbi $17,2 ;ClockOut=inactive (ff73) DI CI in r16,$16 st z+,r16 ldi r25,$cd st z+,r25 l11570: rjmp l13220 ;to main-waiting-loop end JD-LOAD ;================================================================================================ l11580: ;from l10640 - l10650 ;action after Listen read byte from C64 ea2e ; C64 made IecAtn=inactive ; DataOut=active ClockOut=inactive ;IRQ is enabled ;IRQs must be enabled because software AtnAck ldi r25,$a8 ;a8-- rcall l12490 cbi $14,3 ;DdrC3=input sbi $15,3 ;PortC3=PullUpOn = IeeeAtn=inactive ;make IeeeAtn=inactive here (not after receiving Secaddr/Open/Close) ;because it could be that there is no SecAddr (f.e. open10,10) ldi r28,$00 ldi r29,$01 ;Y-vector to 0100 = input buffer (important for AVRinternal) l11590: rcall l10760 ;read 1 byte from C64 DataOut=active ClockOut=inactive ea44 ;no return if C64 makes IecAtn=active sei ;enable IRQs => AtnAck-emulation is switched on ; (but AVR-DataOut is active anyway) lds r17,emumod ;emulation mode mov r25,r16 ;---- rcall l12490 cpi r17,$00 brne l11600 ;b.i.not IEEE ldi r25,$1f ;1f-- rcall l12490 rcall l11900 ;IEEEOUT (at once not bufferd because C64 buffers) ;uses same EOI from C64 brcc l11590 ;b.i.ok rjmp l13220 ;main waiting loop (make IEEE inactive???) l11600: cpi r17,$20 brne l11660 ;b.i.not Centronics lds r17,devpos ;device possibilities andi r17,$80 breq l11650 ;b.i.CBM->IBM-codechange off lds r17,icsawo ;Iec secundary address withot bit for open/close/SA cpi r17,$07 brne l11650 ;b.i.not secundary address 7 cpi r16,$41 brcs l11650 ;b.i.$00-$40 cpi r16,$5b brcc l11610 ori r16,$20 ;41-5a -> 61-7a rjmp l11650 l11610: cpi r16,$61 brcs l11650 ;b.i.5b-60 cpi r16,$7b brcs l11630 ;b.i.61-7a cpi r16,80 brcs l11650 ;b.i.7b-7f cpi r16,$c0 brcs l11640 ;b.i.80-bf brne l11620 ldi r16,$60 ;c0 -> 60 rjmp l11650 l11620: cpi r16,$db brcc l11640 ;b.i.db-ff l11630: andi r16,$5f ;c1-da -> 41-5a %110xxxxx -> %010xxxxx rjmp l11650 ;(61-7a-> 41-5a %011xxxxx -> %010xxxxx) l11640: ldi r16,$20 ;space l11650: rcall l12100 ;sends byte (r16) to printer brcc l11590 ;b.i.carry=close = printer=present ;at end: AVR wants to read byte from C64. C64 makes Atn=active ;=>AVR sees in read-byte routine that Atn changes ;goes to begin of read byte after Atn-edge rjmp l13220 ;=printer not present -> mainwaitingloop = AllOut=inactive l11660: cpi r17,$40 brne l11680 ;b.i.not AVR-internal cpi r28,$2a ; cfdf breq l11670 sts eninbu,r28 ;stores lowbyte end input buffer st y+,r16 ;stores read byte to input buffer l11670: lds r16,flicbb andi r16,$10 ;masks IecEoiReceived bit breq l11590 ;b.i.no EOI sts avinco,r16 ;#$10 set flag f. AVR internal command present cfed rjmp l11590 l11680: rjmp l13220 ;temporary ;------------------------------------------------------------------------------------------------ l11690: ;action after Talk from C64 e909 ;IRQ=enebaled => AtnAck-emulation is switched on ;DataOut=inactive ClockOut=active ; C64 made IecAtn=inactive lds r16,emumod cpi r16,$00 brne l11700 ;b.i.not IEEE ldi r25,$1f ;1f-- rcall l12490 cbi $15,5 ;PortC5=PullUpOff sbi $14,5 ;DdrC5=Output = NRFD=active cbi $15,4 ;PortC4=PullUpOff sbi $14,4 ;DdrC4=Output = NDAC=active rcall l10250 ;10µs waitingloop (necessary?) l11700: cbi $14,3 ;DdrC3=input sbi $15,3 ;PortC3=PullUpOn = IeeeAtn=inactive ;make IeeeAtn=inactive here (not after receiving Secaddr/Open/Close) ;because it could be that there is no SecAddr (f.e. open10,10) l11710: lds r16,devpos ;device posibilities andi r16,$80 ;masks bit whether floppy breq l11720 ;b.i.no floppy (= channel 15 is normal data-channel) lds r17,icsawo ;IEC secundary address without bits for open/close/SA cpi r17,$0f ;compares with command/errorchannel breq l11720 ;b.i.errorchannel lds r16,iccode ;IEC command&devicenumber =talk to data-channel=>close talk-error-buffer ldi r17,$0f ;error-channel rcall l10210 ;close talk-(error-)buffer if necessary l11720: lds r16,iccbjd ;iccbjd Iec CBM/JD cpi r16,$60 brne l11730 ;b.i.not JiffyDOS-LOAD rjmp l11320 ;=JiffyDOS-LOAD l11730: lds r16,iccode ;IEC command&devicenumber (don't close error channel) lds r17,icsawo ;IEC secundary address without bits for open/close/SA rcall l10080 ;open talk-buffer if necessary and test if talk-byte is in buffer ;equal=no byte in buffer notequal=byte in buffer breq l11750 ;b.i.byte isn't in talk-buffer (=> read new one from device) lds r16,$d0 ;talk-SA&bits-buffer andi r16,$10 ;masks EOI-bit breq l11740 ;b.i.noEOI lds r16,flicbb ;flags IeCBusBits ori r16,$01 ;sets flag f.EOI sts flicbb,r16 l11740: lds r16,$e0 ;byte of talk-buffer rjmp l11830 ;byte is in talk-buffer (=> send it don't read new one from device) ;---------- l11750: lds r16,emumod cpi r16,$00 brne l11770 ;b.i.not IEEE ldi r25,$a9 ;a9-- rcall l12490 l11760: rcall l11980 ;IeeeIn brcc l11800 ;b.i.ok rjmp l13220 ;error -> to main-waiting-loop l11770: cpi r16,$40 brne l11790 ;b.i.not AVR-internal lds r17,erbuen ;error buffer end 00 00 02 02 02 02 (#$00 if empty or overwritten) lds r16,erbuve ;errorbuffer vector 00 02 00 01 02 03 cp r16,r17 ; c c s s c c brcc l11780 ;b.i.all errorbytes sent = error-buffer empty ldi r17,$2a ;isn't longer than clc sbci mov r30,r16 add r30,r17 ;Z-vector = 012a- =errorbuffer ldi r31,$01 inc r16 sts erbuve,r16 ld r16,z ;reads byte from errorbuffer rjmp l11800 ;------ l11780: ldi r16,$0d ;end-carriage return lds r17,flicbb ;flag iecbus bits ori r17,$01 ;(sets bit f. IecEoi) sts flicbb,r17 ;sets bit f.IecEoi rjmp l11800 ;------------------------- l11790: ;next device rjmp l13220 ;temporary l11800: sts $e0,r16 ;stores read-byte=to-sent-IEC-OUT-byte in talk-buffer lds r17,$d0 ;talk-secundary-address-buffer l11810: lds r18,flicbb ;flags IeCBusBits andi r18,$01 ;masks EOI-bit at IEC-send (from AVR to C64) (not bit4) breq l11820 ;b.i.noEOI ori r17,$10 ;sets EOI-bit in r17 l11820: ori r17,$20 ;sets bit for byte-in-talk-buffer in r17 sts $d0,r17 l11830: rcall l11100 ;IecOut (from AVR to C64) ; IRQ is enabled => AtnAck-emulation is switched on ; = important because AVR-DataOut=inactive ;if in future there should be a device where the IRQ must be disabled ;because of timing, then it's perhaps necessary that AVR makes ; AVR-DataOut= active while IRQ is disabled (and AtnAck-emulation ; is switched off) lds r16,$d0 ;talk-secundary-address-buffer andi r16,$df ;masks byte-in-buffer-bit off (bit5) sts $d0,r16 brcs l11850 ;b.i.error l11840: lds r16,$d0 ;talk-secundary address-buffer andi r16,$10 ;masks EOI-flag brne l11850 ;b.i.EOI rjmp l11750 ;no EOI l11850: rcall l10220 ;close actual talk-buffer ;================================================================================================ l11860: mov r08,r17 ;1 copies actual value -> old value reads IEEEbus-port ; (error at first time) (about 5µs) ldi r17,$05 ;1 mov r07,r17 ;1 counter l11870: in r17,$13 ;1 PortC = IeeeControlPort andi r17,$f0 ;1 %11110000 masks Bit 7,6,5,4 = IeeeEoi Dav Nrfd Ndac cpse r08,r17 ;2 compares old and actual value =35cycles rjmp l11860 ; b.i.value is not constant ;---------- dec r07 ;1 7*5=35 = 4µs at 8Mhz brne l11870 ;2 (1541 makes 1541:lda$1800 cmp$1800 = 4µs bus constant) ret ;4 ;================================================================================================ l11880: ; IeeeAtnOut rcall l12590 ;===== (=write IeeePorts to analyse-bufer) cbi $14,5 ;DdrC5 Nrfd=input IeeeAtnOut sbi $15,5 ;PortC5 Nrfd=PullupOn =Nrfd=inactive cbi $14,4 ;DdrC4 Ndac=input sbi $15,4 ;PortC4 Ndac=PullupOn =Ndac=inactive rcall l12590 ;===== ldi r25,$83 ;83-- rcall l12490 rcall l12590 ;===== l11890: rcall l11860 ;reads IeeeControlPort andi r17,$40 ;masks Dav bit breq l11890 ;b.i.Dav=active waits until Floppy makes Dav=inactive rcall l12590 ;===== ldi r25,$84 ;84-- rcall l12490 cbi $15,3 ;PortC3 IeeeAtn=PullUpOff (->0V) sbi $14,3 ;DdrC3 IeeeAtn=output=0V IeeeAtn=active rcall l12590 ;===== ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - l11900: cbi $14,6 ;DdrC6 = input r16= send Ieee-byte IEEEOUT sbi $15,6 ;PortC6 =pullUpOn =IeeeDav=inactiv rcall l12590 ;===== cbi $14,7 ;DdrC7=input IeeeEoi=input sbi $15,7 ;PortC7=PullupOn IeeeEoi=inactive rcall l12590 ;===== ldi r25,$90 ;90-- rcall l12490 rcall l11860 ;reads IeeeControlPort andi r17,$30 ;00110000 masks Bit5&4 =Ndac Nrfd cpi r17,$30 sec ;flag f. error breq l11950 ;b.i.Ndac and Nrfd = inactive = device not present rcall l12590 ;===== mov r25,r16 rcall l12530 ;xx-- sent-byte to analysebuffer out $1b,r26 ;#$00 (PullupOff) out $1a,r16 ;DdrA 0-bit=Input 1-bit=output com r16 out $1b,r16 ;PortA makes byte inverted to parallelport ; 0-bit=PullUpOn 1-bit=stays 0V ; 0-bit=inactive (->5V) 1-bit=active (=0V) =inverted rcall l12590 ;===== lds r16,flicbb ;flag f. EOI (0=no 1=yes (inverted at 1541)) andi r16,$10 breq l11910 ;b.i.no EOI cbi $15,7 ;PortC7=PullUpOff (->0V) sbi $14,7 ;DdrC7=output IeeeEoi=active rcall l12590 ;===== ldi r25,$96 ;96-- (EOI) rcall l12530 l11910: rcall l10250 ;waits 10µs rcall l12590 ;===== l11920: rcall l11860 ;reads IeeeControlPort andi r17,$20 ;masks Nrfd bit breq l11920 ;b.i=Nrfd=activ waits until Ieee-floppy makes Nrfd=inactiv rcall l12590 ;===== cbi $15,6 ;PortC6 Dav=PullUpOff(->0V) sbi $14,6 ;DdrC6 Dav=output=0V=active rcall l12590 ;===== l11930: ldi r16,$07 l11940: rcall l11860 ;40 reads IeeeControlPort clc ; 1 flag f. ok andi r17,$10 ; 1 masks Ndac bit brne l11960 ; 1 b.i.Ndac=inactiv waits until floppy makes Ndac = inactive dec r10 ; 1 wait 65120µs (64erSH10 waits 8000µs CBM-Ieee 65000µs) brne l11940 ; 2 40+1+1+1+1+2=46 46*256=10000 dec r16 ; 10000*7==70000cycles=70000µs brne l11940 l11950: ;= Ieee-Floppy doesn't make NDAC fast enough to inactive rcall l12590 ;===== cbi $14,3 ;DdrC3 IeeeAtn=input =error sbi $15,3 ;PortC3 IeeeAtn=PullupOn = IeeeAtn=inactive rcall l12590 ;===== ldi r25,$91 ;91-- rcall l12490 sec ;error flag = time out error make all controll-lines=inactiev??? l11960: rcall l12590 ;===== cbi $14,6 ;DdrC6 sbi $15,6 ;PortC6 Dav=inactive (=output&PullUpOn) rcall l12590 ;===== cbi $14,7 ;DdrC7 sbi $15,7 ;PortC7 IeeeEoi=inactive rcall l12590 ;===== out $1a,r26 ;#$00 DDrA = input out $1b,r27 ;#$ff PortA = PullUpOn rcall l12590 ;===== ldi r25,$94 ;94-- (=ok) brcc l11970 ldi r25,$95 ;95-- (=error) l11970: rcall l12490 rcall l12590 ;===== ret ;clc=ok sec=error ;================================================================================================ ;IEEE-routines are made similar to ;www.funet.fi\cbm\firmware\computer\pet\d\mon1.htm f0b6-f1cb ;================================================================================================ ;from l11760 l11980: cbi $15,4 ;PortC4=PullUpOff IeeeIn sbi $14,4 ;DdrC4=Output = NDAC=active at beginning: NRFD=active cbi $14,5 ;DdrC5=Input NDAC=active sbi $15,5 ;PortC5=PullUpOn = NRFD=inactive DAV=inactive out $1a,r26 ;DdrA=#$00=input IeeeAtn=inactive out $1b,r27 ;PortA=#$ff PullUpOn ldi r25,$60 ;60-- rcall l12530 ldi r16,$07 l11990: rcall l11860 ;40 reads IeeeControlPort andi r17,$40 ;1 masks Dav bit breq l12010 ;1 b.i.one floppy makes DAV=active l12000: ; =all floppies make Dav=inactive = AVR must wait dec r10 ;1 65000µs = 500000cycles at 8MHz brne l11990 ;2 45*256=10000 dec r16 ; 7*10000=70000 = 70ms brne l11990 ldi r25,$61 ;61-- rcall l12530 cbi $15,5 ;PortC5=PullupOff =time-out-error sbi $14,5 ;DdrC5=Output = NRFD=active (NDAC=active already) ldi r16,$0d ;carriage return (don't know why Nrfd & Ndac are active if error) sec ;Flag f. error ret l12010: cbi $15,5 ;PortC5=PullupOff sbi $14,5 ;DdrC5=Output = NRFD=active ldi r25,$62 ;62-- rcall l12530 rcall l11860 ;reads IeeeControlPort andi r17,$80 ;masks IeeeEoi bit brne l12020 ;b.i. IeeeEoi=inactive lds r16,flicbb ;flag iecbus bits ori r16,$01 ;(sets bit f. IecEoi) sts flicbb,r16 ;sets bit f.IecEoi =IeeeEoi ldi r25,$63 ;63-- rcall l12530 l12020: mov r08,r16 ;1 copies actual value -> old value reads IEEEbus-port ; (error at first time) ldi r16,$06 ;1 mov r07,r16 ;1 counter l12030: in r16,$19 ;1 PortA = IeeeParallelPort cpse r08,r16 ;2 compares old and actual value rjmp l12020 ; b.i.value is not constant ;---------- dec r07 ;1 6*6=36 = 4µs at 8Mhz brne l12030 ;2 (1541 makes 1541:lda$1800 cmp$1800 = 4µs bus constant) com r16 ;inverts cbi $14,4 ;DdrC4=input sbi $15,4 ;PortC4=PullUpOn = NDAC=inactive mov r25,r16 ;--read-byte-- rcall l12490 ldi r25,$64 ;64-- rcall l12530 l12040: rcall l11860 ;reads IeeeControlPort andi r17,$40 ;masks Dav bit breq l12040 ;b.i.one floppy makes DAV=active ;waits until all floppies make DAV=inactive ;=all floppies make DAV=inactive ldi r25,$65 ;65-- rcall l12530 cbi $15,4 ;PortC4=PullUpOff sbi $14,4 ;DdrC4=Output = NDAC=active clc ;flag f.ok ret ;================================================================================================ l12050: push r16 ;tests if centronic-printer is present l12060: ldi r16,$10 ; (!also at debug printing => r26/r27 not #$00/#$ff) sbic $13,1 ;skips if centronic-printer not connected or off rjmp l12080 ;=printer is connected and on l12070: sbic $13,1 ;s.i.centronic-printer is not connected or off rjmp l12060 dec r16 brne l12070 sec ;=printer not connected or off rjmp l12090 l12080: sbis $13,1 ;s.i.centronic-printer is connected and on rjmp l12060 dec r16 brne l12080 clc ;=printer is connected and present l12090: pop r16 ret ;clc=ok sec=error ;------------------------------------------------------------------------------------------------ l12100: rcall l12050 ;tests if printer is present send 1byte to centronic printer brcs l12160 ;printer not present (!also at debug printing => r26/r27 not #$00/#$ff) l12110: sbic $13,0 ;skips if Busy is 0V = ready for data rjmp l12100 ;jumps if Busy=5V = busy = not ready for data sbic $13,0 rjmp l12100 sbic $13,0 rjmp l12100 push r16 ldi r16,$00 out $1a,r16 ;DDRA all=input to prevent that port pulls with 20mA to +5V pop r16 out $1b,r16 ;PortA 0-Bits=no-pullup 1-bits=pullup com r16 out $1a,r16 ;DDRA 0-bits=output 1-bits=input (pullup) ldi r16,$1a ;26 l12120: dec r16 ;1 brne l12120 ;2 wait 10µs =8*10cycles at 8MHz cbi $15,2 ;PortC Bit5 of PortC=pullup-off (->0V when output) sbi $14,2 ;DdrC Bit5 of PortC=output = Strobe=0V=active ldi r16,$1a ;26 l12130: dec r16 ;1 brne l12130 ;2 wait 10µs =8*10cycles at 8MHz cbi $14,2 ;DdrC Bit5 of PortC=input sbi $15,2 ;PortC Bit5=pullup-on = strobe=inactive ldi r16,$1a ;26 l12140: dec r16 ;1 brne l12140 ;2 wait 10µs =8*10cycles at 8MHz l12150: clc ;flag f. ok sbis $13,0 ;skips if Busy is 5V = busy = not ready for data rjmp l12170 ;jumps if Busy=0V = ready for data rcall l12050 ;tests if printer is present brcc l12150 ;b.i.printer is present l12160: sec ;flag f. error l12170: ldi r16,$00 ;clc/sec out $1a,r16 ;DDRA=paralleport=input ldi r16,$ff out $1b,r16 ;PortA=parallelport=pullup-resistors-on ret ;clc=ok sec=error ;------------------------------------------------------------------------------------------------ l12180: mov r07,r16 ;print space + ascii (!also at debug printing => r26/r27 not #$00/#$ff) ldi r16,$20 rcall l12100 mov r16,r07 ; ---------------- l12190: mov r07,r16 ;change hexdec->ascii (!also at debug printing => r26/r27 not #$00/#$ff) lsr r16 lsr r16 lsr r16 lsr r16 ;00-09 0a-0f rcall l12200 rcall l12100 ;print highnibble in ascii mov r16,r07 andi r16,$0f ;00-09 0a-0f l12200: ori r16,$30 ;30-39 3a-3f cpi r16,$3a brcs l12210 ;b.i.0-9 sbci r16,$f9 ; 41-46 l12210: rjmp l12100 ;print lownibble ;================================================================================================ l12220: andi r19,$01 ;clears bit 7-1 (4000-41ff(7fff)->0000-01ff(01ff)) EEPROM-write out $1e,r18 ;lowbyte address to eeprom address register low r16=to write byte out $1f,r19 ;highbyte address r18,r19=address ; changes r17 out $1d,r16 ;eedr write data (r16) to data register sbi $1c,2 ;eemwe of eecr Write logical one to EEMWE sbi $1c,1 ;start eeprom write by setting EEWE of eecr ;if internal oscylator runs with too fast speed it must be set to ;correct speed before and to fast speed after ????? l12230: sbic $1c,1 ;eecr eeprom control register rjmp l12230 ;wait for completion of write mov r17,r16 ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - l12240: andi r19,$01 ;clears bit 7-1 (4000-41ff(7fff)->0000-01ff(01ff)) EEPROM-read out $1e,r18 ;lowbyte address to eeprom address register low r18,r19=address out $1f,r19 ;highbyte address sbi $1c,0 ;start eeprom read by writing EERE in r16,$1d ;eedr = eeprom data register read data from data register l12250: out $1e,r26 ;clears eepromaddress out $1f,r26 out $1c,r26 ;clears eecr??? cp r16,r17 ;only at write: compares written and read value ret ;================================================================================================ l12260: ;analyse & execute new AVR-internal command c146 ;print OK message to errorbuffer c150 lds r16,$0100 ;c m m ee u u first byte of inputbuffer ;a - - ii i j lds r17,$0102 ;l r w +- lds r18,$0103 ; lds r19,$0104 ; cpi r16,$43 ;'c' brne l12350 l12270: cpi r17,$4c ;'l' =cal calibrate breq l12280 rjmp l12470 ;syntax error l12280: cpi r18,$00 ;00 and ff isn't possible (00=use old value ff=empty or corrupted EEPROM) breq l12290 ;b.i. 'cal chr$(0)' = don't change value out $04,r18 ;calibrationbyte for internal 8MHz-oscilator r18=hexdec l12290: ldi r25,$f0 ;f0-- rcall l12490 ldi r19,$05 ;%.....101 out $33,r19 ;starts timer0 (8bit) with 8MHz/1024 = 1count per 128µs (if wouldbe 8MHz) ldi r19,$ff ; = 1count per 138.888µs at 7.3728MHz out $32,r19 ;$ff to timer0 l12300: in r19,$32 ;reads timer cpi r19,$01 brne l12300 ;b.i.counter<>$01 = waits until counter=01 waits 35555.55µs=35.555ms ; for 1 halfcycle l12310: in r19,$32 ;reads timer cpi r19,$00 brne l12310 ;b.i.counter<>$00 = waits until counter0000 ;DataOut should be active? ;program should be in Data- not in Command-mode l12320: inc r18 andi r18,$01 breq l12330 ; = 71.111ms for 1 (complete) cycle of AVR-ClockOut-period sbi $17,2 ;ClockOut=active (=7.711s for 100cycles at7.3728MHz) rjmp l12340 l12330: cbi $17,2 ;ClockOut=inactive l12340: rcall l10690 ;waits until C64 makes Atn=active rjmp l12300 ;------------------------------------------------------------------------ l12350: cpi r16,$4d ;'m' brne l12440 mov r30,r18 ;lowbyte memory to read/write =m-w m-r mov r31,r19 ;highbyte 0000-3fff RAM lds r16,$0106 ;value to write 4000-7fff EEPROM ; 8000-ffff flashROM andi r31,$7f ;8000-ffff -> 0000-7fff (0000-3fff stays) cpi r19,$40 brcc l12390 ;b.i.4000-ffff cpi r17,$57 ;'w' m-r m-w RAM breq l12360 ld r16,z ;m-r RAM rjmp l12430 ;------ l12360: cpi r19,$00 ;m-w RAM doesn't write to registers and i/o (too dangerous) brne l12370 ;b.i.0100-03ff cpi r18,$61 ;=0000-0100 brcs l12380 ;b.i.0000-0060 l12370: st z,r16 ;=0060-3fff l12380: rjmp l13220 l12390: cpi r19,$80 brcc l12420 ;b.i.8000-ffff l12400: cpi r17,$57 ;'w' =m-r m-w EEPROM breq l12410 ;=m-r (reads allways one byte only) rcall l12240 ;EEPROM-read rjmp l12430 ;------ l12410: ;=m-w (writes allways one byte only) rcall l12220 ;EEPROM-write rjmp l13220 ;--------------- l12420: lpm r16,z ;m-r flashROM (never write) l12430: sts $012a,r16 ;writes to error-buffer ldi r16,$01 sts erbuen,r16 ;sets error buffer end = 1 sts erbuve,r26 ;error buffer vector to first byte of errorbuffer rjmp l13220 ;------------------------------------------------------------------------ l12440: cpi r16,$45 ;'e' Extra Iec (same as S-JiffyDOS) brne l12460 lds r16,fljdal ;flag JiffyDOS allowed ori r16,$80 ;sets bit7 cpi r17,$2b ;'+' breq l12450 ;b.i.ie+ cpi r17,$2d ;'-' brne l12470 ;b.i.not ie- =syntax error andi r16,$7f ;clears bit7 l12450: sts fljdal,r16 rjmp l12480 ;------------------- l12460: cpi r16,$55 ;'u' brne l12470 rjmp l12710 ;=ui uj = reset l12470: ;nop ;syntax error l12480: rjmp l13220 ;temporary to main waiting loop ;================================================================================================ l12490: push r22 ; =analysebyte & IEC-ports in r22,$3f ;status register to printer + LED + buffer push r22 mov r22,r06 andi r22,$08 breq l12510 ;b.i.no print analyse byte to centronics printer push r16 ;save to stack r25=print debugvalue as hexdec mov r16,r25 rcall l12180 ;print as hexdec on printer pop r16 rjmp l12510 ;---------- l12500: push r22 ; =analysebyte & IEC-ports in r22,$3f ;status register to LED + buffer push r22 l12510: mov r22,r06 andi r22,$10 breq l12540 ;b.i.no display analyse byte to (LEDs of) parallelport l12520: push r25 ldi r25,$00 out $1b,r25 ;PortA pop r25 out $1a,r25 ;DdrA com r25 ;SEC !!! changes carry-flag out $1b,r25 ;PortA gives value inverted to port as LED display com r25 rjmp l12540 ;---------- l12530: push r22 ; =analysebyte & IEC-ports in r22,$3f ;status register to buffer push r22 l12540: mov r22,r06 andi r22,$60 l12550: breq l12580 ;b.i.no save of analyse byte or of IecPort to buffer sbis $13,2 ;s.i.debug-jumper is open rjmp l12700 ;debug-jumper is close => don't change r04 r05 (and analyse-buffer) l12560: push r23 in r22,$17 ;IecDdr (0=input=inactiv 1=output=activ) com r22 ; (0=activ 1=inactiv) andi r22,$54 ;%01010100 masks output-bits in r23,$16 ;iecPort andi r23,$2a ;%00101010 masks input-bits or r23,r22 ;(bit 7 allways low) ori r23,$01 ;flag f.analyse- & Iec-byte => bit0=high ;=>at IEC-port bit0 (of second byte) is allways high $x1,$x3...$xf ; (at IEEE-port bit 0 of second byte is allways low ($x8 or $x0)) in r22,$10 ;PortD (IecAtn) rol r22 rol r22 rol r22 rol r22 rol r22 andi r22,$80 or r23,r22 ;r23 Bit7=IecAtn Bit6-1=IecPort Bit0=high cp r00,r23 ;compares actual and old IecBus value brne l12570 ;b.i.change cp r25,r01 ;compare actual and old debug-value brne l12570 ;b.i.new value rjmp l12690 ;=no new value l12570: mov r01,r25 ;actual analyse value -> old value mov r22,r25 ;analyse byte mov r00,r23 ;actual IEC-bus value -> old value rjmp l12620 ;=write analyse- / IECbus-byte into analysebuffer l12580: rjmp l12700 ;no analyse byte wanted ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - l12590: push r22 ; ieee-ports-analyse bytes buffering in r22,$3f ;status register push r22 sbis $13,2 ;s.i.debug-jumper is open rjmp l12700 ;debug-jumper is close => don't change r06 r07 (and analyse-buffer) tst r06 brpl l12700 ;b.i.no IeeePortsAnalyse push r23 push r24 l12600: in r22,$19 ;Parallelport in r23,$13 ;IEEE (&printer) control-port andi r23,$f8 ;masks printer-bits off => bit2-0=low => $x0 or $x8 in r24,$19 ;Parallelport (second time) cp r22,r24 brne l12600 pop r24 com r22 ;inverts parallelport cp r22,r02 ;compares parallelport actual and old value brne l12610 ;b.i.change at parallelport cp r23,r03 ;compares control-port actual and old value breq l12690 ;b.i. no change at Ieee-controlport l12610: mov r02,r22 ;actual value -> old value mov r03,r23 l12620: push r28 ;backup Ylow push r29 ;backup Yhigh mov r28,r06 rol r28 ;save-IeeePort-bit -> carry andi r28,$40 ;masks save-analyse-byte-bit (shifted 1 bit left) mov r28,r04 ;set Y-register to analysebufferposition mov r29,r05 brcs l12630 ;b.i.IeeePorts (allways print two bytes) breq l12640 ;b.i.no save of AnalyseByte (=save one byte only) l12630: st y+,r22 ;stores AnlyseByte / IeeeParallelPort to buffer 00,02,04... l12640: mov r22,r06 rol r22 brcs l12650 ;b.i.IeeePorts (allways print two bytes) brpl l12660 ;b.i.save analys byte only (Not IecPortByte) (=save one byte only) l12650: st y+,r23 ;stores IecPort / IeeeControllPort to buffer 01,03,05... l12660: cpi r28,$60 breq l12670 ;b.i.0260 cpi r28,$61 brne l12680 ;b.i.not 0261 l12670: ldi r28,$00 ;=analysebuffervector is at end ldi r29,$02 ;=$0200 = begin small analysebuffer (big loadbuffer) mov r22,r06 andi r22,$01 breq l12680 ;b.i.analyse buffer 0200-025f ldi r28,$80 ;=analyse buffer begin 0180-025f (big analyse buffer (small loadbuffer)) ldi r29,$01 l12680: mov r04,r28 mov r05,r29 pop r29 ;restore Y-register pop r28 l12690: pop r23 l12700: pop r22 out $3f,r22 ;restores status register pop r22 ret ;if IEEE and analyse+IEC is enabled then difficult to see what is what: ;there are allways written two bytes into the buffer: ; analyse+IEC IEEE ;first byte analysebyte parallelport ;second byte IEC-port controlport ;at bit0 of second byte you can see: ;if it is a odd byte (x1, x3, ... xf) then it's analyse&IEC-port ;if it is even (x0 or x8) then it's IEEE-port ;================================================================================================ l12710: cli ;disables IRQs (= SEI at C64) Reset ;serial IEC-port-----------------------------------PortB------------------ ; DDR Port ;input: 0 1 = Input + 40kOhm-Pullup (0.12mA) ;output-activ (0V): 1 0 = Output + push 0V ;output-inactiv 0 0 = Input (=inactiv output) ;IEC-pins are In- or Output (but an Input is allways an Input ; an Output is allways an Output) ;using two pins for one line is made to allow additional input- and/or ;output-driver-chips (what wouldn't be possible if one line would be ;one pin) ;I2C-pins (at least data) is In- and Output ldi r16,$10 ;%00010000 = DataDirection ;7 0 I2E-Clock SCK (Clock In at flashing) ;6 0 IEC-SRQ Out MISO (same at flashing) ;5 0 IEC-Data In MOSI (same at flashing) ;4 1 IEC-Data Out ;3 0 IEC-Clock In ;2 0 IEC-Clock Out ;1 0 IEC-SRQ In ;0 0 I2E-Data ;7 isn't allways Clock In because danger of accidental flashing if C64 ; would make Clock=active=0V while AVR reset ldi r17,$ab ;%10101011 = Port ;7 1 I2E-Clock SCK (Clock In at flashing) ;6 0 IEC-SRQ Out MISO (same at flashing) ;5 1 IEC-Data In MOSI (same at flashing) ;4 0 IEC-Data Out ;3 1 IEC-Clock In ;2 0 IEC-Clock Out ;1 1 IEC-SRQ In ;0 1 I2E-Data ldi r26,$00 out $18,r26 ;PortB = all 0 to prevent that AVR pulls 20mA to 5V out $17,r16 ;DDRB = serial IEC-port settings out $18,r17 ;PortB ;sets Data=active ; as flag that device isn't ready ldi r27,$ff ;Parallelport--------------------------------------PortA------------------ ; DDR Port ;input: 0 1 = Input + 40kOhm-Pullup (0.12mA) ;output-activ (0V): 1 0 = Output + push 0V ;output-inactiv 0 1 = Input (=inactiv output) ; ;each pin is In- and Output ;AVR must never pull active (with 20mA) to 5V = Bit-combination %11 ;(= DDRA=1 PortA=1) is never allowed ;To write a new value to the port you must change DDRA and PortA in two ;steps. To prevent that accidentially a %11 is written first PortA must be ;cleared ;it's allways important to first clear first DdrX (or PortX) and then set ;bits in PortX (or DdrX). Best is to first write #$00 (r26 later) into ;DdrX or PortX and then set the bits out $1a,r26 ;ddra to input (#00) out $1b,r27 ;PortA = PullUpOn ParallelPort=inactiv out $14,r26 ;DdrC----------------------------------------------PortC------------------ ldi r16,$fd ;%11111101 out $15,r16 ;PortC ;Bit DDR Port ;7 IEEE-EOI 0 1 end or identify ;6 IEEE-DAV 0 1 data valid ;5 IEEE-NRFD 0 1 not ready for data ;4 IEEE-NDAC 0 1 not data acepted ;3 IEEE-ATN 0 1 attention ;2 Strobe Out inactive 0 1 (Out active 1 0) ;1 Present In (only) 0 0 no pullup because 10kOhm external ;0 Busy In & pullup 0 1 pulldown ;bit 7-4 are in- and output ;bit 3 is output only ;bit 2 is usually output (only input when debug-jumper is read) ;bit 1&0 are inputs out $11,r26 ;DdrD = input--------------------------------------PortD------------------ out $12,r27 ;PortD $ff (unused pins PullUpOn to prevent swinging) ; DDR Port ;7 (Data2?) 0 1 ;6 (Clock2?) 0 1 ;5 (SRQ2?) 0 1 ;4 (RTS) - 0 1 ;3 (CTS) - 0 1 ;2 AtnIn In+Pullup 0 1 ;1 (TXD) - 0 1 ;0 (RXD) - 0 1---------------------PortD------------------ out $06,r26 ;DdrE (#$00) ------------------------------------PortE------------------ ldi r16,$03 ;%00000011 ldi r17,$04 ;%00000100 out $07,r16 ;PortE out $06,r17 ;DdrE PinE2=output = OC1B (LED on) atmega-only ; DDR Port (would be necessary at ;2 Error-LED 1 0 AT90S8515) ;1 (ResetOut or 0 1 ; datadirection of ; parallelportdriver?) ;0 (ATN2?) 0 1---------------------PortE------------------ ldi r16,$7f out $3d,r16 ;stackpointerlow = 7f out $3e,r26 ;stackpointer high to 0 => stackpointer to 007f stack=007f-0060 =32bytes mov r16,r06 ;analyse buffer mode andi r16,$02 ;masks bit1 for debug-jumper-function breq l12730 ;b.i.debug-printing isn't allowed ;at first reset r06 contains nonsens => debug-jumper must be open. ;at further resets r06 contains correct value from Eeprom ldi r19,$05 ;%.....101 out $33,r19 ;starts timer0 (8bit) with 8MHz/1024 = 1count per 128µs out $32,r26 ;$00 to timer0 counts up 1*128µs l12720: in r19,$32 ;reads timer cpi r19,$01 brcs l12720 ;b.i.counter<$01 = waits 128µs sbic $13,2 ;b.i.centronic-Strobe-debug-jumper is on l12730: rjmp l12850 ;=Centronics-Strobe-debug-jumper=off = no debug-buffer-printing rcall l10050 ;LED blink =debug printing l12740: ldi r17,$00 l12750: in r16,$19 ;parallelport cpi r16,$ff brne l12740 ;b.i.IeeeFloppy makes any line of IeeePort=active dec r17 brne l12750 ;waits until parallelport is free=unused from Ieee-device rcall l10040 ;LED on ;if AVR-LED blinks while debug-printin, then user must reset IeeeFloppy ;because IeeeFloppy pulls lines of parallelport to active=0V l12760: ldi r16,$00 l12770: sbis $13,2 ;b.i.strobe-debug-jumper gets off-switched rjmp l12760 dec r16 brne l12770 ldi r17,$00 l12780: ldi r16,$7f ;del rcall l12100 ;sends 256 times 'del' to printer to delete earlier received wrong bytes dec r17 ;when debug-jumper caused wrong strobes to printer brne l12780 ldi r16,$0d rcall l12100 ;ldi r16,$0a ;rcall l12100 ;the printer must make an automatic linefeed when it receives a ;carriage-return. ;the AVR cannot send an additional linefeed to the printer when the AVR ;receives a CR $0d from the C64 because a $0d can also be a normal ;data-character byte at printing of a bitmap ldi r17,$05 l12790: ldi r16,$20 rcall l12100 ;print 5 spaces dec r17 brne l12790 ldi r17,$00 l12800: mov r16,r17 rcall l12180 ;print header '$00' - '$0f' inc r17 cpi r17,$10 brne l12800 ldi r27,$00 ;Xhigh=0 (r26=#$00) l12810: ldi r16,$0d rcall l12100 ;ldi r16,$0a ;rcall l12100 l12820: ldi r16,$0d rcall l12100 ;ldi r16,$0a ;rcall l12100 mov r16,r27 ;highbyte address rcall l12190 ;print as asci mov r16,r26 ;lowbyte address rcall l12190 ;print as acsii ldi r16,$3a ; ':' rcall l12100 l12830: ld r16,x+ rcall l12180 ;print as hexdec mov r25,r26 ;r25=Xlow andi r25,$0f brne l12830 cpi r26,$20 brne l12840 ;b.i. cpi r27,$00 breq l12810 ;b.i. $0020=additional break = end of registers r00-r31 l12840: cpi r26,$60 brne l12820 cpi r27,$00 ;=0060,0160,0260 breq l12810 ;b.i.0060=additional break = end of I/O-area cpi r27,$02 brne l12820 ;b.i.0160 ldi r16,$0c ;formfeed =$0260=end rcall l12100 ;-------------------------------------------------------end debug printing l12850: ldi r26,$00 ;x low (important after debug printing) sbis $13,2 ;s.i.debug-jumper is open ldi r26,$07 ;=debug-jumper is closed => don't change r00-r06 ldi r27,$00 ;x high (r26=x low =#$00/#$07) ldi r25,$00 l12860: st x+,r25 ;clears $00/07-$18 $1c-$23 $28-$2f $3c-$47 $50-$5c cpi r26,$19 ; 00/07-24 28-35 40-47 60-71 80-92 brne l12870 ldi r26,$1c ;(not $00-$06 = r00-r06) l12870: cpi r26,$24 ; not $19-$1b = r25-r27 brne l12880 ; not $24-$27 = I/O-$04-$07 = calibration-byte & PortE ldi r26,$28 ; not $30-$3b = I/O-$10-$1b = PortD - PortA l12880: cpi r26,$30 ; not $48-$4f = I/O-$28-$2f = Timer1 (why) brne l12890 ; not $5d-$5f = I/O-$3d-$3f = stack & statusregister ldi r26,$3c l12890: cpi r26,$48 brne l12900 ldi r26,$50 l12900: cpi r26,$5d brne l12860 ldi r26,$60 l12910: st x+,r25 ;clears 0060-015f/025f cpi r26,$60 brne l12910 ldi r24,$01 sbic $13,02 ;s.i.debug-jumper is closed ldi r24,$02 ;debug-jumper is open cp r27,r24 brne l12910 ;-------------------end initialice memory--------------------------------- ldi r26,$00 ;must be #$00 allways because there can allways be an IRQ ldi r27,$ff ;must be #$ff allways because there can allways be an IRQ ldi r20,$00 ;=counter for EEPROM errors l12920: ldi r18,$40 ldi r19,$00 ;EEPROM-address = $0040 = entry-table0 ldi r30,$80 ldi r31,$00 ; z RAM-vector =$0080 l12930: rcall l12240 ;EEPROM read 0040-007f st z+,r16 ;RAM 0080-00bf inc r18 brpl l12930 ldi r18,$c0 ldi r19,$00 ;EEPROM-address = $00c0 = entry-table1 ldi r30,$80 ldi r31,$00 ; z RAM-vector =$0080 l12940: rcall l12240 ;EEPROM read 00c0-00ff ld r17,z+ ;RAM 0080-00bf cp r16,r17 brne l12960 ;b.i.difference of EEPROM-table0 to table1 inc r18 ;=cp r18,$00 brne l12940 ldi r18,$40 ldi r19,$01 ;EEPROM-address = $0140 = entry-table2 ldi r30,$80 ldi r31,$00 ; z RAM-vector =$0080 l12950: rcall l12240 ;EEPROM read 00c0-00ff ld r17,z+ ;RAM 0140-017f cp r16,r17 brne l12960 ;b.i.difference of EEPROM-table0 to table2 inc r18 ;perhaps brpl l12950 would be shorter? brpl l12950 rjmp l13140 ;=no EEPROM-corruption -------------------------------------------------- l12960: dec r20 ;counter for EEPROM errors brne l12970 ;b.i.1-255 rjmp l13120 ;=256 errors (important that no hanging-loop when defectiv EEPROM) l12970: dec r30 ;=EEPROM-corruption mov r18,r30 ; RAM-vector low 80-bf clc sbci r18,$c0 ; c0-ff ldi r19,$00 rcall l12240 ;EEPROM read 00c0-00ff mov r17,r16 clc sbci r18,$80 ; 40-bf ldi r19,$01 rcall l12240 ;EEPROM read 0140-01bf ld r18,z ;RAM =EEPROM-0040-00bf cpi r30,$80 breq l12980 ;b.i.entry-possition00 b.i.auto-repair EEPROM-corruption rjmp l13090 ;=not autorepair-byte l12980: ;flag f.autorepair is $aa or $55, nothing else possible ;r16=$0140 r17=$00c0 r18=$0040 of EEPROM ldi r19,$00 ;=amount of allowed values (55 or aa) cpi r16,$aa breq l12990 cpi r16,$55 brne l13000 l12990: inc r19 l13000: cpi r17,$aa breq l13010 cpi r17,$55 brne l13020 l13010: inc r19 l13020: cpi r18,$aa breq l13030 cpi r18,$55 brne l13040 l13030: inc r19 l13040: ;sts $0110,r16 ;sts $0111,r17 ;sts $0112,r18 ;sts $0113,r19 ;sts $0114,r20 cpi r19,$00 breq l13120 ;b.i.no tableposition00 entry is allowed cpi r19,$01 brne l13050 ;b.i.not only 1 entry is correct (2 or 3 correct entries) cpi r16,$aa ;=1 correct entry breq l13070 ;b.i.r16 is allowed cpi r16,$55 breq l13070 ;b.i.r16 is allowed cpi r17,$aa breq l13060 ;b.i.r17 is allowed cpi r17,$55 breq l13060 ;b.i.r17 is allowed mov r16,r18 ;r16 and r17 are not allowed => r18 must be allowed rjmp l13070 ;repair EEPROM-corruption r16=correct autorepair-value l13050: cp r16,r17 ;=2 or 3 allowed entries (but 2 or 3 allowed entries can be different breq l13080 ;b.i.r16 = r17 55 aa ff 55 55 aa) cp r16,r18 breq l13070 cp r17,r18 brne l13120 ;=2 allowed, but different entries l13060: mov r16,r17 l13070: mov r17,r16 l13080: rjmp l13110 ;repair EEPROM-corruption r16=r17=correct autorepair-value l13090: ; RAM-vector low 81-bf =repair not-'auto-repair-EEPROM'-bytes ; r16=$0140 r17=$00c0 r18=$0040 of Eeprom cp r16,r17 breq l13100 ;b.i.table2-value=table1-value cp r16,r18 breq l13100 ;b.i.table2-value=table0-value mov r16,r17 cp r17,r18 brne l13120 ;b.i.table1-value=table0-value l13100: lds r17,$0080 ; = repair EEPROM corruption r16=correct value l13110: cpi r17,$aa brne l13120 ;b.i.autorepair EEPROM is disabled mov r18,r30 ;lowbyte RAM vector (80-bf) r16=correct to-write value clc sbci r18,$40 ;->40-7f ldi r19,$00 rcall l12220 ;EEPROM-write 0040-007f table0 mov r16,r17 clc sbci r18,$80 ;->00c0-00ff rcall l12220 ;EEPROM-write 00c0-00ff table1 mov r16,r17 clc sbci r18,$80 ;->0140-017f ldi r19,$01 rcall l12220 rjmp l12920 ;again from beginning (easier)------------- l13120: ldi r30,$90 ;=unrepairable EEPROM-corruption or auto-repair disabled ldi r31,$00 l13130: st z+,r27 ;#$ff clears $0090-$00bf=emulation-tables cpi r30,$c0 brne l13130 ldi r20,$ff ;sets flag for EEPROM-error ldi r30,$90 ;clears 008f-0080 ldi r16,$ff ;sets calibrationbyte to illegal rjmp l13150 l13140: ldi r30,$8f ;=no EEPROM-corruption or repairable EEPROM-corruption lds r16,$0081 ;calibrationbyte from EEPROM lds r06,$0082 ;analyse buffer mode inc r06 breq l13150 ;b.i.had been #$ff = empty EEPRPM dec r06 l13150: ldi r31,$00 ;z RAM vector = $008f l13160: st -z,r26 ;'$00 clears 008e-0080 !!change if 8e, 8d ... should be important here!! cpi r30,$80 ;brmi l13160 doesn't work because statusreister isn't changed brne l13160 cpi r16,$ff ;(ff=empty EEPROM or corruted EEPROM) brne l13170 ;b.i.EEPROM-calibratinbyte is allowed ldi r16,$80 ;default for average calibrationbyte !!! wrong timing at JiffyDOS l13170: out 04,r16 ;calibrationbyte for internat 8MHz-oscilator rcall l10060 ;LED off mustn't change r20!!!!!!!!!!! cpi r20,$00 breq l13180 rcall l10050 ;LED blink ;................................................................................................ l13180: ldi r16,$40 ;%01000000 out $3b,r16 ;General IRQ mask register allows int0 irq out $35,r26 ;MCU control register int0-IRQs at low level ;%00000000 low level = IRQ-trigger ; good: triggers allways an IRQ ;%00000010 falling edge = IRQ-trigger doesn't work because: ; IEC-ATN falls so slow that it doesn't trigger reliably an IRQ sbis $13,2 ;s.i.debug-jumper is open rjmp l13200 ;debug-jumper is closed ldi r16,$00 ldi r17,$02 mov r18,r06 ;analyse buffer mode andi r18,$01 breq l13190 ;b.i.0200-025f ldi r16,$80 ; initialize analyse-buffer-vector ldi r17,$01 ;=0180-025f l13190: mov r04,r16 ;X low ieee-analyse buffer mov r05,r17 ;X high rcall l12590 ;===== l13200: ldi r28,$2a ;y=012a ldi r29,$01 ldi r30,low(l13270<<1) ldi r31,high(l13270<<1) ; Initialize Z pointer l13210: lpm r16,z+ ;copies 73... message to errorbuffer st y+,r16 cpi r28,$44 brne l13210 ldi r16,$1a sts erbuen,r16 ;sets error buffer end sts erbuve,r26 ;sets error buffer vector to first byte ;------------------------------------------------------------------------------------------------ l13220: ldi r16,$7f out $3d,r16 ;stackpointerlow = 7f out $3e,r26 ;stackpointer high to 0 => stackpointer to 007f ldi r25,$01 ;01-- rcall l12500 mov r25,r26 ;---- rcall l12500 mov r25,r27 ;---- rcall l12500 ; sts flicbb,r26 ;#$00 clears flag f. IecAtnMode = in DataMode (important f.rcall l10690) ;1541 makes all IecLines = inactive ;AVR shouldn't make DataOut=active because there is no AtnAck-hardware lds r16,avinco ;AVR-internal command ebf0 cpi r16,$00 breq l13230 ;b.i.no avr-internal command sts avinco,r26 ;#$00 rcall l12260 ;analyse & execute new AVR-internal command l13230: rcall l10690 ;test if IecAtn change (if IecAtn=active -> ; l10320 serves bus after Atn-active-edge) ;. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l13240: ldi r16,$40 out $3b,r16 ;enable IRQ at low-level of PinD2=Int0=if AtnIn=active=0V (not inverted) sei ;enable IRQs ldi r25,$01 ;01-- rcall l12500 l13250: cli ;disables IRQs in r16,$3b ;reads General IRQ Mask Register ec00 andi r16,$40 brne l13260 ;b.i.IecAtnPin IRQs still allowed ;=IRQ-routine disabled Atn-line-IRQ (=Atn-active-edge received) rjmp l10320 ;serves bus after Atn-active-edge l13260: out $17,r26 ;DDRB ClockOut=inactive DataOut=inactive SrqOut=inactive ldi r16,$ab ;%10101011 out $18,r16 ;PortB rjmp l13240 ;================================================================================================ l13270: .db "73,IEC2IEEE NLQ@GMX.DE,0,0 ;================================================================================================ ; SUBROUTINES-table ; l10040 LED on ; l10050 LED blink ; l10060 LED off ; l10320 read byte after ATN-edge ; l10760 IECIN read one byte from C64 to AVR ; l11100 IECOUT send one byte from AVR to C64 ; l11690 Job when Talk received ; l11320 JiffyDOS-LOAD ; l12260 analyse & execute new AVR-internal command