From 5473fe9cd01a61e9441f5b2063ca234b15c250fb Mon Sep 17 00:00:00 2001 From: Gadget Hackwrench Date: Mon, 31 Mar 2025 17:12:43 -0700 Subject: [PATCH 1/7] Double the delay (now ~/0.6 seconds) before PS2 ident... --- bin/3b.bin | Bin 8192 -> 8192 bytes bin/3c.bin | Bin 8192 -> 8192 bytes bin/3f.bin | Bin 8192 -> 8192 bytes hardware/ps2_auto.asm | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/3b.bin b/bin/3b.bin index 9675f37a35366b4c4cdedc20c91a976a17104099..b90e747633281ee42ac07f0be1ccd4462cf5bb1c 100644 GIT binary patch delta 13 UcmZp0XmD7-#JF)YBh!Cb03i+prvLx| delta 13 UcmZp0XmD7-#JFlRBh!Cb03hT9pa1{> diff --git a/bin/3c.bin b/bin/3c.bin index 6168dd6a72ab953934dbe4f88505d65806b4bbe0..2d438653bd3573501f44c4e271d02add04c2116b 100644 GIT binary patch delta 14 VcmZp0XmHrzCC;d^*;{-o2LL3Q1dRXy delta 14 VcmZp0XmHrzCC(_a*;{-o2LL1?1bF}e diff --git a/bin/3f.bin b/bin/3f.bin index 19459c45ff1c39bedae7db79322b2bc8d63c0ba2..877f4acf0ceed80903f0e4331fdeab06ab471db5 100644 GIT binary patch delta 45 rcmZp0XmAkrb`A1#^ Date: Wed, 20 Aug 2025 00:07:15 +0200 Subject: [PATCH 2/7] JiffyDOS protocol implementation for X2 systems --- f256/iec.asm | 315 ++++++++++++++++++++++++++++++++----------------- f256/jiffy.asm | 249 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 458 insertions(+), 106 deletions(-) create mode 100755 f256/jiffy.asm diff --git a/f256/iec.asm b/f256/iec.asm index 440a174..29f3f61 100755 --- a/f256/iec.asm +++ b/f256/iec.asm @@ -15,7 +15,7 @@ iec .namespace port .namespace .section kernel2 ; TODO: iec_code or somesuch - + IEC_INPUT_PORT = $D680 ; Read Only, this is the Value on the BUS ; IEC Input PORT ; Bit[0] IEC_DATA_i @@ -56,7 +56,7 @@ assert_bit .macro BIT pla rts .endm - + release_bit .macro BIT pha lda IEC_OUTPUT_PORT @@ -66,6 +66,28 @@ release_bit .macro BIT rts .endm +assert .macro BITS + pha + lda #platform.iec.port.\BITS + trb platform.iec.port.IEC_OUTPUT_PORT + pla + .endm + +release .macro BITS + pha + lda #platform.iec.port.\BITS + tsb platform.iec.port.IEC_OUTPUT_PORT + pla + .endm + +toggle .macro BITS + pha + lda #platform.iec.port.\BITS + trb platform.iec.port.IEC_OUTPUT_PORT + tsb platform.iec.port.IEC_OUTPUT_PORT + pla + .endm + read_bit .macro BIT pha _loop lda IEC_INPUT_PORT @@ -76,7 +98,7 @@ _loop lda IEC_INPUT_PORT pla rts .endm - + bit_funcs .segment NAME,IN,OUT read_\NAME .read_bit \IN @@ -85,7 +107,7 @@ assert_\NAME release_\NAME .release_bit \OUT .endm - + .bit_funcs SREQ, IEC_SREQ_i, IEC_SREQ_o .bit_funcs ATN, IEC_ATN_i, IEC_ATN_o .bit_funcs CLOCK, IEC_CLK_i, IEC_CLK_o @@ -103,29 +125,29 @@ test_DATA .proc ; Grab the current output state. ldx IEC_OUTPUT_PORT - + ; Prepare to release DATA txa ora #IEC_DATA_o tay - + ; Prepare to test DATA lda #IEC_DATA_i ; Release DATA sty IEC_OUTPUT_PORT - + ; Test DATA and IEC_INPUT_PORT bne _out - + ; Re-assert DATA if it's still low. stx IEC_OUTPUT_PORT - + _out ; Place the DATA state in the carry cmp #1 - + ply plx pla @@ -133,13 +155,14 @@ _out .pend init .proc + jsr sleep_1ms stz io_ctrl jsr release_ATN jsr release_DATA jsr release_SREQ ;jsr release_CLOCK ; IDLE state - jsr assert_CLOCK ; IDLE state + jsr assert_CLOCK ; IDLE state jsr sleep_1ms jsr sleep_1ms jsr sleep_1ms @@ -159,21 +182,38 @@ self .namespace eoi_pending .byte ? rx_eoi .fill 0 ; shared with mark mark .byte ? +jiffy .byte ? ; jiffy support (0: no/not tested, <0: jiffy detected) +temp .byte ? ; bit assembly +status .byte ? ; last drive status .endn .send .section kernel2 +IEC_DEBUG = true +DBG_CALL .macro routine + .if IEC_DEBUG + jsr \routine + .endif + .endm + init ; Initialize the port and make sure ATN and SREQ aren't stuck. ; Carry set on error. + pha + lda $d6a7 ; MID + bpl _iec_init + lda #40 + ;sta self.sleep20 +_iec_init + pla jsr platform.iec.port.init - jsr debug_init + DBG_CALL debug_init ; Bail if ATN and SRQ fail to float back up. ; We'll have a more thorough test when we send - ; our first command. + ; our first command. nop nop nop @@ -189,8 +229,8 @@ init _err ;jsr wtf sec - rts - + rts + wtf php phy @@ -203,18 +243,19 @@ _loop lda _wtf,y _done ply php rts -_wtf .text "ATN line stuck low.", $0a, 0 +_wtf .text "ATN line stuck low.", $0a, 0 TALK ora #$40 jsr flush + stz self.jiffy ; re-check for jiffy jmp atn_release_data ; NOTE: does NOT drop ATN! TALK_SA jsr atn_common - sei + sei jsr platform.iec.port.assert_DATA jsr platform.iec.port.release_ATN jsr platform.iec.port.release_CLOCK @@ -223,18 +264,19 @@ TALK_SA cli rts - + LISTEN ora #$20 jsr flush + stz self.jiffy ; re-check for jiffy jmp atn_release_data ; NOTE: does NOT drop ATN! - + LISTEN_SA jsr atn_common jsr platform.iec.port.release_ATN cli - ; TODO: WARNING! No delay here! + ; TODO: WARNING! No delay here! ; TODO: IMHO, should wait at least 100us to avoid accidental turn-around! ; TODO: tho we do protect against this in the send code. rts @@ -246,9 +288,9 @@ UNTALK ; Detangled from C64 sources; TODO: compare with Stef's ; There should never be a need to flush here, and if you ; do manage to call IECOUT between a TALK/TALKSA and an - ; UNTALK, the C64 will flush it while ATN is asserted and + ; UNTALK, the C64 will flush it while ATN is asserted and ; the drive will be mighty confused. - ; + ; ; TODO: track the state and cause calls to IECOUT to fail. ; pre-sets CLOCK IMMEDIATELY before the ATN ... again, TODO: makes no sense @@ -264,7 +306,7 @@ UNLISTEN ; Detangled from C64 sources; TODO: compare with Stef's lda #$3f jsr flush jmp atn_release - + atn_release_data sei @@ -274,9 +316,9 @@ atn_release_data jsr atn_common ; NOTE: does NOT release ATN! Does NOT release IRQs! cli rts - + atn_release - jsr atn_common + jsr atn_common sei jsr platform.iec.port.release_ATN @@ -291,7 +333,7 @@ atn_release atn_common ; NOTE: at present, leaves IRQs disabled on success! - ; Assert ATN; if we aren't already in sending mode, + ; Assert ATN; if we aren't already in sending mode, ; get there: sei jsr platform.iec.port.assert_ATN @@ -301,7 +343,7 @@ atn_common ; Now give the devices ~1ms to start listening. jsr sleep_1ms - + ; If no one is listening, there's nothing on ; the bus, so signal an error. jsr platform.iec.port.read_DATA @@ -309,8 +351,8 @@ atn_common ; ATN bytes are technically never EOI bytes stz self.eoi_pending - - jmp send_common + + jmp send_common _err ; Always release the ATN line on error; TODO: add post delay @@ -320,7 +362,8 @@ _err send_eoi send_data_eoi - jsr debug_last + DBG_CALL debug_last + jsr waste_time jsr set_eoi jmp send @@ -333,18 +376,24 @@ send jsr send_common cli rts - + send_common ; A = byte ; Assumes we are in the sending state: ; the host is asserting CLOCK and the devices are asserting DATA. ; This part of the code should be moved to the kernel thread. - jsr debug_write ; There must be at least 100us between bytes. - jsr sleep_300us + jsr sleep_100us + DBG_CALL debug_write + jsr platform.iec.port.read_ATN + bcc _not_jiffy + bit self.jiffy + bpl _not_jiffy + jmp jiffy.send +_not_jiffy ; Clever cheating @@ -357,7 +406,7 @@ send_common ; We can do this without disabling interrupts because ; we are also asserting DATA. jsr platform.iec.port.release_CLOCK - + ; Now we wait for all of the listeners to acknowledge. _wait ; We're still asserting DATA. @@ -374,25 +423,25 @@ _wait sei jsr platform.iec.port.test_DATA bcs _ready - + ; Other listeners are still busy; go back to sleep. bra _wait _ready - jsr debug_tick + DBG_CALL debug_tick bit self.eoi_pending bpl _send bmi _eoi _eoi ; Alas, we can't get too clever here, or the 1541 hates us. - + ; Hard-wait the 200us for the drive to acknowledge the EOI. ; This duration is technically unbounded, but the ersatz ; listener trick during the EOI signal, and the drive ; already had the opportunity to delay before starting the ; ack, so hopefully it will stay in nominal 250us range. - + _Tye jsr platform.iec.port.read_DATA bcs _Tye @@ -417,16 +466,22 @@ _send ; least 20us (with 70us more typical for clock low). phx - ldx #8 + phy + ldx #7 _loop - ; Don't let an interrupt put space between the clock - ; and the data. - sei ; Already true for the first bit. - ; TODO: opt test for a frame error + bne _send_bit + jsr platform.iec.port.read_ATN + bcs _send_bit + bit self.jiffy + bmi _send_bit + jsr jiffy.detect + +_send_bit ; Clock out the next bit jsr platform.iec.port.assert_CLOCK + jsr sleep_20us lsr a bcs _one @@ -442,16 +497,16 @@ _clock jsr sleep_20us ; 1541 needs this. jsr platform.iec.port.release_CLOCK - jsr sleep_20us + jsr platform.iec.port.release_DATA dex - bne _loop + bpl _loop + ply plx - + ; Finish the last bit and wait for the listeners to ack. ; Again do this synchronously. sei - jsr platform.iec.port.release_DATA jsr platform.iec.port.assert_CLOCK ; Now wait for listener ack. Of course, if there are @@ -463,15 +518,15 @@ _clock ; to completely change the code below. .if true - jsr debug_test ; T + ;DBG_CALL debug_test ; T _ack jsr platform.iec.port.read_DATA bcs _ack - jsr debug_ACK ; A + ;DBG_CALL debug_ACK ; ' clc rts -.else +.else ; Timing here isn't critical - cli + cli ; Test the port every 20us for up to 1ms. lda #50 @@ -488,11 +543,12 @@ _done sleep_20us phx ldx #20 + ;ldx self.sleep20 _loop dex bne _loop plx rts - + sleep_100us phx ldx #5 @@ -500,24 +556,24 @@ _loop jsr sleep_20us dex bne _loop plx - rts + rts sleep_300us jsr sleep_100us jsr sleep_100us jsr sleep_100us rts - + sleep_1ms jsr sleep_300us jsr sleep_300us jsr sleep_300us jmp sleep_100us - + recv_data - - ;jsr debug_read + + DBG_CALL debug_read ; Assume not EOI until proved otherwise stz self.rx_eoi @@ -527,7 +583,7 @@ recv_data _wait1 jsr platform.iec.port.read_CLOCK bcc _wait1 - ;jsr debug_tick + ;DBG_CALL debug_tick _ready ; Sadly, we must do the rests with interrupts disabled. @@ -540,8 +596,8 @@ _ready ; Wait for all other listeners to signal _wait2 jsr platform.iec.port.read_DATA bcc _wait2 - ;jsr debug_tick - + ;DBG_CALL debug_tick + ; Wait for the first bit or an EOI condition ; Each iteration takes 6-7us lda #0 ; counter @@ -555,7 +611,7 @@ _eoi lda self.rx_eoi bmi _error - jsr debug_last + DBG_CALL debug_last ; Ack the EOI; we can enable IRQs for this. jsr platform.iec.port.assert_DATA cli @@ -563,11 +619,11 @@ _eoi jsr sleep_20us jsr sleep_20us - ; Set the EOI flag. + ; Set the EOI flag. dec self.rx_eoi ; TODO: error on second round - + ; Go back to the ready state - bra _ready + bra _ready _error cli @@ -584,7 +640,7 @@ _wait_fall jsr platform.iec.port.read_CLOCK _wait_rise jsr platform.iec.port.read_CLOCK bcc _wait_rise - + jsr platform.iec.port.read_DATA ror a dex @@ -603,9 +659,9 @@ _wait_rise jsr platform.iec.port.read_CLOCK jsr sleep_20us ; Seems to be missing the ack. jsr sleep_20us ; Seems to be missing the ack. jsr sleep_20us ; Seems to be missing the ack. - - ;jsr debug_ACK - jsr debug_write + + ;DBG_CALL debug_ACK + DBG_CALL debug_write ; Return EOI in NV clc @@ -635,8 +691,12 @@ IOINIT IECIN ; Receives a byte into A; ; NV set on EOI + bit self.jiffy + bpl _not_jiffy + jmp jiffy.receive +_not_jiffy jmp recv_data - + IECOUT ; Sends the byte in A. @@ -656,7 +716,7 @@ IECOUT stz delayed ; Queue the new byte -_queue +_queue sta queue dec delayed rts @@ -694,15 +754,15 @@ probe_device ; Soft reset phy tay - + jsr LISTEN bcs _out lda #$0f jsr DEV_RECV bcs _out - - lda #'U' + + lda #'U' jsr IECOUT lda #'I' ; TODO: test 'J' (hard) instead. jsr IECOUT @@ -711,7 +771,7 @@ probe_device ; Soft reset tya jsr UNLISTEN plp - + _out ply rts @@ -723,7 +783,7 @@ clear_status phy tay - + jsr TALK bcs _out @@ -731,30 +791,61 @@ clear_status lda #$0f jsr DEV_SEND bcs _close - + + stz self.status + jsr IECIN + bcs _error + + sec + sbc #$30 + asl a + asl a + asl a + asl a + sta self.status + + jsr IECIN + bcs _error + + sec + sbc #$30 + tsb self.status + _loop jsr IECIN - bcs _close + bcs _error bvc _loop - + bra _close + +_error + sec + lda #$ff + sta self.status + _close php + DBG_CALL debug_test tya jsr UNTALK plp - + _out ply + lda self.status + cmp #0 rts +waste_time rts + .send +.if IEC_DEBUG .section dp screen .word ? read .byte ? .send - .section kernel2 + .section kernel2 debug_init pha @@ -766,19 +857,23 @@ debug_init rts debug_write - stz read - jsr port.read_ATN ; cs->high->not asserted - ror read ; underline->not asserted - jmp print_hex + pha + lda #$00 + jsr platform.iec.port.read_ATN ; cs->high->not asserted + ror a ; inverted->asserted + eor #$80 + sta read + pla + ;jmp print_hex print_hex php pha - stz io_ctrl - jsr port.read_ATN - bcc _x - jsr debug_print - bra _done + ;stz io_ctrl + ;jsr platform.iec.port.read_ATN + ;bcc _x + ;jsr debug_print + ;bra _done _x phy jsr _hex @@ -786,13 +881,14 @@ _x _done pla plp + stz read rts _hex pha - lsr a - lsr a - lsr a - lsr a + lsr a + lsr a + lsr a + lsr a jsr _digit pla and #$0f @@ -806,7 +902,7 @@ _digit jmp debug_print _digits .text "0123456789abcdef" -debug_tick rts +debug_tick php pha lda #'.' @@ -822,7 +918,7 @@ debug_ACK pla plp rts -debug_EOI rts +debug_error php pha lda #'E' @@ -830,7 +926,7 @@ debug_EOI rts pla plp rts - + debug_last php pha @@ -840,7 +936,7 @@ debug_last plp rts -debug_test rts +debug_test php pha lda #'T' @@ -848,8 +944,8 @@ debug_test rts pla plp rts - -debug_read rts + +debug_read rts php pha lda #'R' @@ -857,24 +953,31 @@ debug_read rts pla plp rts - -debug_print rts + +debug_print phy ldy #2 sty io_ctrl - ora read - eor #$80 + sta (screen) + ldy #3 + sty io_ctrl + lda #$f1 + bit read + bpl _setcol + lda #$1f +_setcol sta (screen) stz io_ctrl inc screen bne _out inc screen+1 -_out +_out ply rts - + .send - +.endif + .endn .endn diff --git a/f256/jiffy.asm b/f256/jiffy.asm new file mode 100755 index 0000000..adcadf0 --- /dev/null +++ b/f256/jiffy.asm @@ -0,0 +1,249 @@ +; Jiffy implementation Copyright 2025 Matthias Brukner +; SPDX-License-Identifier: GPL-3.0-only + + .cpu "w65c02" + + + .namespace platform +jiffy .namespace + .section kernel2 + + .with platform.iec +JIFFY_DEBUG = IEC_DEBUG +DBG_CALL .macro routine + .if JIFFY_DEBUG + jsr \routine + .endif + .endm + +init .proc + rts + .endproc + + ; ------------------------------------------- Jiffy transfers---- + ; Translation tables for sending out data, going from 4 bits to + ; two bit pairs, aligned with IEC output register so it is easy + ; and cheap to send out. + + ; Bit[0] IEC_DATA_o + ; Bit[1] IEC_CLK_o + + ; HIGH nibble (7..4) +tx_high + .byte $0f, $0d, $0e, $0c, $07, $05, $06, $04 + .byte $0b, $09, $0a, $08, $03, $01, $02, $00 + + ; LOW nibble (3..0) +tx_low + .byte $f0, $b0, $e0, $a0, $70, $30, $60, $20 + .byte $d0, $90, $c0, $80, $50, $10, $40, $00 + +send .proc + ; A = byte + ; Assumes we are in the sending state: + ; the host is asserting CLOCK and the device is asserting DATA. + + ; prepare the bits to be sent so we can push them to IEC output + ; efficiently during the transfer--which is timing critical + phx + pha + lsr a + lsr a + lsr a + lsr a + tax + lda tx_high,x + sta self.temp + pla + and #$0f + tax + lda tx_low,x + ora self.temp + + ; Jiffy: wait for device to release DATA, allow interrupts while waiting + cli +_wait + jsr platform.iec.port.test_DATA + bcs _ready + + jsr sleep_20us + bra _wait + +_ready + sei + ldx #4 + ; Release CLOCK for 11-13 usecs to indicate start of transfer. + jsr platform.iec.port.release_CLOCK + + ; Timing now is critical, bit timings in usec after CLOCK release: + ; (10, 20, 31, 41) send + jsr sleep_5us +_loop + pha + and #$03 + ora #(port.IEC_SREQ_o | port.IEC_ATN_o) + sta port.IEC_OUTPUT_PORT + jsr sleep_10us + + pla + lsr a + lsr a + dex + bne _loop + + bit platform.iec.self.eoi_pending + bpl _no_eoi +_eoi + jsr platform.iec.port.release_CLOCK ; signal EOI +_no_eoi + jsr platform.iec.port.release_DATA + ; TODO: verify timing + jsr sleep_10us + + jsr platform.iec.port.read_DATA + bcc _ack + DBG_CALL debug_error + bra _end +_ack + DBG_CALL debug_ACK +_end + jsr platform.iec.port.assert_CLOCK ; back to idle state asserting CLOCK + jsr sleep_20us + plx + rts + .endproc + +receive .proc + ; (17, 30, 41, 54) receive + + ; Assume not EOI until proved otherwise + stz self.rx_eoi + + ; Wait for the sender to have a byte + stz self.temp + phx + ldx #4 + + ;cli + sei +_wait1 jsr platform.iec.port.read_CLOCK + bcc _wait1 + + jsr sleep_20us ; give the drive some time to catch up + jsr sleep_20us ; give the drive some time to catch up + ;sei + + ; Signal we are ready to receive + jsr platform.iec.port.release_DATA + + jsr sleep_4us + ; Clock in the bits, 2 at a time, keep the result in temp +_jiffy_read + jsr sleep_4us + lda port.IEC_INPUT_PORT + and #$03 + asl self.temp + asl self.temp + ora self.temp + sta self.temp + dex + bne _jiffy_read + + ; All bits transferred, now check data signal (EOI indication) + jsr sleep_10us + + jsr platform.iec.port.assert_DATA + jsr platform.iec.port.read_CLOCK + bcc _no_eoi + ; Set the EOI flag. + dec self.rx_eoi + DBG_CALL debug_last +_no_eoi + cli + + ; reshuffle bits to in the correct order + lda self.temp + ldx #8 + stz self.temp +_rev_loop + lsr a + rol self.temp + dex + bne _rev_loop + lda self.temp + + plx + + ;DBG_CALL debug_ACK + DBG_CALL debug_write + + ; Return EOI in NV + clc + bit self.rx_eoi + ora #0 + rts + .endproc + +detect .proc + ; just return if not running on an X2 core as the timings will be off + bit $d6a7 + bmi _detect + rts + +_detect + jsr platform.iec.port.assert_CLOCK + ; TODO: measure with non jiffy drive to see if this matches 400us at 12MHz + ldy #61 +_loop + jsr platform.iec.port.read_DATA + bcc _detected + dey + bne _loop + rts +_detected + ldy #20 +_wait_loop + jsr platform.iec.port.read_DATA + bcs _out + dey + bne _wait_loop +_out + dec self.jiffy ; 0 -> ff + rts + .endproc + + + ; NB: the timing values need not to be taken literally; + ; they have been manually adjusted to match Jiffy timings +sleep_4us .proc + phx + ldx #4 +_loop dex + bne _loop + plx + rts + .endproc + +sleep_5us .proc + phx + ldx #6 +_loop dex + bne _loop + plx + rts + .endproc + +sleep_10us .proc + phx + ldx #7 +_loop dex + bne _loop + plx + rts + .endproc + + + .endwith ; platform.iec + .send ; kernel2 + .endn ; jiffy + .endn ; platform From afd8589df8e7c2d432eb6f734cab243b3d138451 Mon Sep 17 00:00:00 2001 From: Matthias Brukner Date: Wed, 20 Aug 2025 00:14:08 +0200 Subject: [PATCH 3/7] disable debug output --- f256/iec.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/f256/iec.asm b/f256/iec.asm index 29f3f61..f5a2e96 100755 --- a/f256/iec.asm +++ b/f256/iec.asm @@ -190,7 +190,7 @@ status .byte ? ; last drive status .section kernel2 -IEC_DEBUG = true +IEC_DEBUG = false DBG_CALL .macro routine .if IEC_DEBUG jsr \routine From e187c613cee0db047a88ed5a23e3c3afb20c0210 Mon Sep 17 00:00:00 2001 From: Matthias Brukner Date: Wed, 20 Aug 2025 11:54:59 +0200 Subject: [PATCH 4/7] Jiffy currently runs on X1 cores only --- f256/jiffy.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/f256/jiffy.asm b/f256/jiffy.asm index adcadf0..1de42ac 100755 --- a/f256/jiffy.asm +++ b/f256/jiffy.asm @@ -185,14 +185,14 @@ _rev_loop .endproc detect .proc - ; just return if not running on an X2 core as the timings will be off + ; just return if not running on an X1 core as the timings will be off bit $d6a7 - bmi _detect + bpl _detect rts _detect jsr platform.iec.port.assert_CLOCK - ; TODO: measure with non jiffy drive to see if this matches 400us at 12MHz + ; TODO: measure with non jiffy drive to see if this matches 400us at 6MHz ldy #61 _loop jsr platform.iec.port.read_DATA From a6d122c0057d19ac38a05875922219a7714328d5 Mon Sep 17 00:00:00 2001 From: Matthias Brukner Date: Sun, 24 Aug 2025 23:58:22 +0200 Subject: [PATCH 5/7] Use delay macro for both core1x and core2x, fixed timings (fingers crossed) JiffyDOS fixed timings for X1 and X2 --- Makefile | 1 + f256/iec.asm | 55 ++++++++--- f256/jiffy.asm | 236 ++++++++++++++++++++++++++++++++++------------- hardware/iec.asm | 2 +- 4 files changed, 215 insertions(+), 79 deletions(-) diff --git a/Makefile b/Makefile index af7b69c..ada14df 100755 --- a/Makefile +++ b/Makefile @@ -49,6 +49,7 @@ Jr = \ f256/iec.asm \ f256/interrupt_def.asm \ f256/irq.asm \ + f256/jiffy.asm \ f256/jr.asm \ f256/k2_lcd.asm \ f256/kbd_cbm.asm \ diff --git a/f256/iec.asm b/f256/iec.asm index f5a2e96..9a22379 100755 --- a/f256/iec.asm +++ b/f256/iec.asm @@ -176,21 +176,26 @@ init .proc ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Transaction routines +IEC_DEBUG = false .section dp ; For rx_eoi, could be ,x self .namespace eoi_pending .byte ? rx_eoi .fill 0 ; shared with mark mark .byte ? +sleep20 .byte ? jiffy .byte ? ; jiffy support (0: no/not tested, <0: jiffy detected) temp .byte ? ; bit assembly status .byte ? ; last drive status + .if IEC_DEBUG +col1 .byte ? +col2 .byte ? + .endif .endn .send .section kernel2 -IEC_DEBUG = false DBG_CALL .macro routine .if IEC_DEBUG jsr \routine @@ -202,14 +207,16 @@ init ; Carry set on error. pha - lda $d6a7 ; MID + lda #20 + bit $d6a7 ; MID bpl _iec_init - lda #40 - ;sta self.sleep20 + lda #50 _iec_init + sta self.sleep20 pla jsr platform.iec.port.init DBG_CALL debug_init + jsr platform.jiffy.init ; Bail if ATN and SRQ fail to float back up. ; We'll have a more thorough test when we send @@ -387,7 +394,6 @@ send_common ; There must be at least 100us between bytes. jsr sleep_100us - DBG_CALL debug_write jsr platform.iec.port.read_ATN bcc _not_jiffy bit self.jiffy @@ -395,6 +401,7 @@ send_common jmp jiffy.send _not_jiffy + DBG_CALL debug_write ; Clever cheating ; Act as an ersatz listener to keep the other listeners busy @@ -542,8 +549,7 @@ _done sleep_20us phx - ldx #20 - ;ldx self.sleep20 + ldx self.sleep20 _loop dex bne _loop plx @@ -853,6 +859,10 @@ debug_init stz screen+0 inc screen+0 sta screen+1 + lda #$f1 + sta self.col1 + lda #$1f + sta self.col2 pla rts @@ -869,11 +879,11 @@ debug_write print_hex php pha - ;stz io_ctrl - ;jsr platform.iec.port.read_ATN - ;bcc _x - ;jsr debug_print - ;bra _done + stz io_ctrl + jsr platform.iec.port.read_ATN + bcc _x + jsr debug_print + bra _done _x phy jsr _hex @@ -954,6 +964,23 @@ debug_read rts plp rts +debug_set_color + pha + sta self.col1 + asl a + asl a + asl a + asl a + sta self.col2 + pla + lsr a + lsr a + lsr a + lsr a + ora self.col2 + sta self.col2 + rts + debug_print phy ldy #2 @@ -961,10 +988,10 @@ debug_print sta (screen) ldy #3 sty io_ctrl - lda #$f1 + lda self.col1 bit read bpl _setcol - lda #$1f + lda self.col2 _setcol sta (screen) stz io_ctrl diff --git a/f256/jiffy.asm b/f256/jiffy.asm index 1de42ac..a65a22a 100755 --- a/f256/jiffy.asm +++ b/f256/jiffy.asm @@ -9,13 +9,36 @@ jiffy .namespace .section kernel2 .with platform.iec + + ; Screen buffer output debugging JIFFY_DEBUG = IEC_DEBUG + + ; To debug RX/TX timings you can enable SREQ toggling + ; on bit timings +TX_DEBUG = false +RX_DEBUG = false + +MACHINE_ID = $d6a7 +TIMEOUT = 255 + DBG_CALL .macro routine .if JIFFY_DEBUG jsr \routine .endif .endm +delay_y .macro x1_delay, x2_delay + ldy #\x1_delay + bit MACHINE_ID + bpl _delay_sel + ldy #\x2_delay +_delay_sel + nop + nop +_delay dey + bne _delay + .endm + init .proc rts .endproc @@ -38,6 +61,7 @@ tx_low .byte $f0, $b0, $e0, $a0, $70, $30, $60, $20 .byte $d0, $90, $c0, $80, $50, $10, $40, $00 + ; ------------------------------------------- Jiffy send -------- send .proc ; A = byte ; Assumes we are in the sending state: @@ -46,6 +70,16 @@ send .proc ; prepare the bits to be sent so we can push them to IEC output ; efficiently during the transfer--which is timing critical phx + phy + + .if JIFFY_DEBUG + pha + lda #$0e ; blue + jsr debug_set_color + pla + jsr debug_write + .endif + pha lsr a lsr a @@ -60,68 +94,139 @@ send .proc lda tx_low,x ora self.temp - ; Jiffy: wait for device to release DATA, allow interrupts while waiting + ; Wait for device to release DATA, allow interrupts while waiting cli + ldx #TIMEOUT _wait - jsr platform.iec.port.test_DATA + ; Is this enough waiting, are there slower drives? This may be a + ; situation where having this interrupt driven might be good to + ; guarantee correct timings, aligned to the drives internal clock + jsr platform.iec.port.read_DATA bcs _ready + dex + bne _wait - jsr sleep_20us - bra _wait + ; error -- data not being asserted by device + ; TODO: follow up on error handling + ; Clock still being asserted + ply + plx + sec + rts _ready sei - ldx #4 ; Release CLOCK for 11-13 usecs to indicate start of transfer. - jsr platform.iec.port.release_CLOCK + + ;delay_y 1,6 + ;jsr platform.iec.port.release_CLOCK + .port.release IEC_CLK_o ; Timing now is critical, bit timings in usec after CLOCK release: ; (10, 20, 31, 41) send - jsr sleep_5us + delay_y 9,23 _loop pha and #$03 + .if TX_DEBUG + ora #(port.IEC_ATN_o) + .else ora #(port.IEC_SREQ_o | port.IEC_ATN_o) + .endif sta port.IEC_OUTPUT_PORT - jsr sleep_10us + delay_y 10,26 + pla + lsr a + lsr a + pha + and #$03 + ora #(port.IEC_SREQ_o | port.IEC_ATN_o) + sta port.IEC_OUTPUT_PORT + delay_y 8,23 + pla + lsr a + lsr a + + pha + and #$03 + .if TX_DEBUG + ora #(port.IEC_ATN_o) + .else + ora #(port.IEC_SREQ_o | port.IEC_ATN_o) + .endif + sta port.IEC_OUTPUT_PORT + delay_y 8,23 + pla + lsr a + lsr a + + pha + and #$03 + ora #(port.IEC_SREQ_o | port.IEC_ATN_o) + sta port.IEC_OUTPUT_PORT + delay_y 10,26 pla lsr a lsr a - dex - bne _loop bit platform.iec.self.eoi_pending bpl _no_eoi _eoi - jsr platform.iec.port.release_CLOCK ; signal EOI + ; staus: EOI + .if TX_DEBUG + lda #(port.IEC_ATN_o | port.IEC_DATA_o | port.IEC_CLK_o) + .else + lda #(port.IEC_ATN_o | port.IEC_SREQ_o | port.IEC_DATA_o | port.IEC_CLK_o) + .endif + bra _send_status _no_eoi - jsr platform.iec.port.release_DATA - ; TODO: verify timing - jsr sleep_10us + ; status: OK + .if TX_DEBUG + lda #(port.IEC_ATN_o | port.IEC_DATA_o) + .else + lda #(port.IEC_ATN_o | port.IEC_SREQ_o | port.IEC_DATA_o) + .endif +_send_status + sta port.IEC_OUTPUT_PORT + delay_y 11,28 + + ; assert clock (in case it wasn't already), also release debug signal + ;lda #(port.IEC_ATN_o | port.IEC_SREQ_o | port.IEC_DATA_o | port.IEC_CLK_o) + lda #(port.IEC_ATN_o | port.IEC_SREQ_o | port.IEC_DATA_o) + sta port.IEC_OUTPUT_PORT + delay_y 5,14 jsr platform.iec.port.read_DATA bcc _ack - DBG_CALL debug_error + ;DBG_CALL debug_error bra _end _ack - DBG_CALL debug_ACK + ;DBG_CALL debug_ACK _end jsr platform.iec.port.assert_CLOCK ; back to idle state asserting CLOCK jsr sleep_20us + + ply plx + ;lda #$f1 + ;DBG_CALL debug_set_color rts .endproc + ; ------------------------------------------- Jiffy receive ----- receive .proc ; (17, 30, 41, 54) receive ; Assume not EOI until proved otherwise stz self.rx_eoi + lda #$0d ; green + DBG_CALL debug_set_color ; Wait for the sender to have a byte stz self.temp phx + phy ldx #4 ;cli @@ -129,17 +234,28 @@ receive .proc _wait1 jsr platform.iec.port.read_CLOCK bcc _wait1 - jsr sleep_20us ; give the drive some time to catch up - jsr sleep_20us ; give the drive some time to catch up + delay_y 37,80 + ;sei ; Signal we are ready to receive jsr platform.iec.port.release_DATA - jsr sleep_4us + delay_y 4,16 + nop + nop + ;nop + nop ; Clock in the bits, 2 at a time, keep the result in temp _jiffy_read - jsr sleep_4us + delay_y 4,14 + nop + nop + nop + nop + .if RX_DEBUG + .port.toggle IEC_SREQ_o + .endif lda port.IEC_INPUT_PORT and #$03 asl self.temp @@ -150,17 +266,29 @@ _jiffy_read bne _jiffy_read ; All bits transferred, now check data signal (EOI indication) - jsr sleep_10us + delay_y 9,23 jsr platform.iec.port.assert_DATA jsr platform.iec.port.read_CLOCK + .if RX_DEBUG + .port.toggle IEC_SREQ_o + .endif + cli bcc _no_eoi ; Set the EOI flag. dec self.rx_eoi DBG_CALL debug_last + ldy #67 + sty $D6A8 + stz $D6A9 + bra _shuffle_bits _no_eoi - cli + sta $D6A9 + lsr a + lsr a + sta $D6A8 +_shuffle_bits ; reshuffle bits to in the correct order lda self.temp ldx #8 @@ -172,8 +300,6 @@ _rev_loop bne _rev_loop lda self.temp - plx - ;DBG_CALL debug_ACK DBG_CALL debug_write @@ -181,68 +307,50 @@ _rev_loop clc bit self.rx_eoi ora #0 + + ply + plx + + pha + lda #$f1 + ;DBG_CALL debug_set_color + pla rts .endproc + ; ------------------------------------------- Jiffy detection --- detect .proc - ; just return if not running on an X1 core as the timings will be off - bit $d6a7 - bpl _detect - rts - -_detect + phy jsr platform.iec.port.assert_CLOCK - ; TODO: measure with non jiffy drive to see if this matches 400us at 6MHz - ldy #61 + ldy #50 + bit MACHINE_ID + bpl _loop + ldy #120 _loop jsr platform.iec.port.read_DATA bcc _detected dey bne _loop + ply rts _detected ldy #20 + bit MACHINE_ID + bpl _wait_loop + ldy #44 _wait_loop jsr platform.iec.port.read_DATA bcs _out dey bne _wait_loop _out - dec self.jiffy ; 0 -> ff - rts - .endproc - - - ; NB: the timing values need not to be taken literally; - ; they have been manually adjusted to match Jiffy timings -sleep_4us .proc - phx - ldx #4 -_loop dex - bne _loop - plx - rts - .endproc - -sleep_5us .proc - phx - ldx #6 -_loop dex - bne _loop - plx + sec + ror self.jiffy ; 0 -> 80 + ;dec self.jiffy + ply rts .endproc -sleep_10us .proc - phx - ldx #7 -_loop dex - bne _loop - plx - rts - .endproc - - .endwith ; platform.iec .send ; kernel2 .endn ; jiffy diff --git a/hardware/iec.asm b/hardware/iec.asm index 08b97e1..14fd480 100755 --- a/hardware/iec.asm +++ b/hardware/iec.asm @@ -89,7 +89,7 @@ _loop sta channels,x ; Wait before enabling IEC operations. stz awake - lda #5 + lda #1 jsr kernel.clock.insert phy From dc92e5caa1e1fe80a5cb9e0e3afeabd47bb5848c Mon Sep 17 00:00:00 2001 From: Matthias Brukner Date: Fri, 16 Jan 2026 16:57:32 +0100 Subject: [PATCH 6/7] tune jiffy timings --- f256/jiffy.asm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/f256/jiffy.asm b/f256/jiffy.asm index a65a22a..70455ad 100755 --- a/f256/jiffy.asm +++ b/f256/jiffy.asm @@ -220,8 +220,10 @@ receive .proc ; Assume not EOI until proved otherwise stz self.rx_eoi + .if JIFFY_DEBUG lda #$0d ; green - DBG_CALL debug_set_color + jsr debug_set_color + .endif ; Wait for the sender to have a byte stz self.temp @@ -234,7 +236,7 @@ receive .proc _wait1 jsr platform.iec.port.read_CLOCK bcc _wait1 - delay_y 37,80 + delay_y 37,84 ;sei From 4ce2273983d0fbc10381aad61e297243042ff019 Mon Sep 17 00:00:00 2001 From: Matthias Brukner Date: Sun, 18 Jan 2026 09:00:21 +0100 Subject: [PATCH 7/7] Tweak LED signalling --- f256/jiffy.asm | 1 + 1 file changed, 1 insertion(+) diff --git a/f256/jiffy.asm b/f256/jiffy.asm index 70455ad..ed3e3c1 100755 --- a/f256/jiffy.asm +++ b/f256/jiffy.asm @@ -285,6 +285,7 @@ _jiffy_read stz $D6A9 bra _shuffle_bits _no_eoi + adc #$80 sta $D6A9 lsr a lsr a