work towards tape speed calibration in normal system load

This commit is contained in:
FeralChild64 committed 2020-01-19 20:59:59 +01:00
1 parent 585d37c899
commit 37c86a33d1
17 files changed
+325 -187

No files matched your search

+24 -6
View File
@@ -1,6 +1,6 @@
//
// Names of ZP and low memory locations:
// - Compute's Mapping the Commodore 64
// - Computes Mapping the Commodore 64
// - https://www.c64-wiki.com/wiki/Zeropage
// - http://unusedino.de/ec64/technical/project64/memory_maps.html
//
@@ -83,8 +83,8 @@
//
.label IOSTATUS = $90
.label STKEY = $91 // Keys down clears bits. STOP - bit 7, C= - bit 6, SPACE - bit 4, CTRL - bit 2
.label SVXT = $92 // -- NOT IMPLEMENTED --
.label STKEY = $91 // keys down clears bits. STOP - bit 7, C= - bit 6, SPACE - bit 4, CTRL - bit 2
.label SVXT = $92 // tape reading constant [!] our tape routines use it differently
.label VERCKK = $93 // 0 = LOAD, 1 = VERIFY
.label C3PO = $94 // flag - is BSOUR content valid
.label BSOUR = $95 // serial bus buffered output byte
@@ -118,8 +118,8 @@
.label RIDDATA = $AA // -- NOT IMPLEMENTED --
.label RIPRTY = $AB // -- WIP -- checksum while reading tape
#endif
.label SAL = $AC // $AC-$AD -- NOT IMPLEMENTED -- (implemented screen part)
.label EAL = $AE // $AE-$AF -- NOT IMPLEMENTED -- [!] used also by screen editor, for temporary color storage when scrolling
.label SAL = $AC // $AC-$AD -- XXX: describe -- (implemented screen part)
.label EAL = $AE // $AE-$AF -- XXX: describe -- [!] used also by screen editor, for temporary color storage when scrolling
.label CMP0 = $B0 // $B0-$B1 temporary tape storage, [!] here used for BRK instruction address
.label TAPE1 = $B2 // $B2-$B3 tape buffer pointer
#if !CONFIG_LEGACY_SCNKEY
@@ -227,7 +227,7 @@
#if CONFIG_MEMORY_MODEL_60K
// IRQs are disabled when doing such accesses, and a default NMI handler only increments
// a counter, so that if an NMI occurs, it doesn't crash the machine, but can be captured.
// a counter, so that if an NMI occurs, it does not crash the machine, but can be captured.
.label missed_nmi_flag = $2A7
.label tiny_nmi_handler = $2A8
@@ -288,3 +288,21 @@
#endif
// $3FC $3FC-$3FF -- UNUSED -- free for user software
//
// Definitions foor tape functionality
//
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
.label __normal_time_S = IRQTMP+0 // duration of the short pulse
.label __normal_time_M = IRQTMP+1 // duration of the medium pulse
.label __turbo_half_S = IRQTMP+0 // half-duration of the short pulse
.label __turbo_half_L = IRQTMP+1 // half-duration of the long pulse
.label __pulse_threshold = SVXT // pulse classification threshold
.label __pulse_threshold_ML = SYNO // M/L pulse classification threshold, for normal only
#endif
+14 -1
View File
@@ -43,19 +43,32 @@ LOAD:
// Check whether we support the requested device
lda FA
#if !CONFIG_TAPE_AUTODETECT
#if CONFIG_TAPE_NORMAL
cmp #$01
beq_16 load_tape_normal
#endif
#if CONFIG_TAPE_TURBO
cmp #$07
beq_16 load_tape_turbo
#endif
#else // CONFIG_TAPE_AUTODETECT
cmp #$01
beq_16 load_tape_auto
cmp #$07
beq_16 load_tape_auto
#endif
#if CONFIG_IEC
jsr iec_check_devnum_lvs
bcc_16 load_iec
#endif
jmp lvs_illegal_device_number
+7 -17
View File
@@ -33,37 +33,27 @@
// (L,S) = end-of-data marker
// XXX use pilot to calibrate reading speed
// XXX add error correction
// XXX implement proper takeover to turbo during sync/pilot
#if CONFIG_TAPE_NORMAL
#if !CONFIG_TAPE_AUTODETECT
load_tape_normal:
jsr tape_ditch_verify // only LOAD is supported, no VERIFY
#if CONFIG_TAPE_AUTODETECT
// Prepare for sound effects in case of turbo takeover
jsr tape_clean_sid
#endif
// Start playing
jsr tape_common_prepare_cia
jsr tape_ask_play
#if CONFIG_TAPE_AUTODETECT
// FALLTROUGH
#else
load_tape_normal_takeover: // entry point for turbo->normal takeover
jsr tape_common_autodetect
bcs_16 load_tape_turbo_takeover
#endif
// Temporarily store MEMUSS in EAL
@@ -86,10 +76,10 @@ load_tape_normal_header:
// Retrieve the header
jsr tape_normal_pilot_header
jsr tape_normal_get_pilot_header
ldy #$C1 // size limit (including checksum)
jsr tape_normal_get_data
bcs load_tape_normal_header // unable to read block, try again
bcs load_tape_normal_header // unable to read block, try again XXX restore MEMUSS and jump to turbo detection
// Check header type
@@ -127,7 +117,7 @@ load_tape_normal_payload:
// Retrieve data
jsr tape_normal_pilot_data
jsr tape_normal_get_pilot_data
ldy #$00 // no data size limit
jsr tape_normal_get_data
bcs_16 tape_load_error
+8
View File
@@ -14,8 +14,16 @@
#if CONFIG_TAPE_TURBO
#if !CONFIG_TAPE_AUTODETECT
load_tape_turbo:
#else
load_tape_auto:
#endif
jsr tape_ditch_verify // only LOAD is supported, no VERIFY
// Prepare for sound effects
+2 -2
View File
@@ -38,13 +38,13 @@ tape_common_autodetect_retry:
sta XSAV
ldy #$60 // $60 pulses cover 12 bytes of turbo recording
jsr tape_normal_get_pulse // first pulse might be a garbage, ignore it
jsr tape_common_get_pulse // first pulse might be a garbage, ignore it
// FALLTROUGH
tape_common_autodetect_loop:
jsr tape_normal_get_pulse // read pulse for detection attempt
jsr tape_common_get_pulse // read pulse for detection attempt
// If garbage found, retry detection
cmp #$28
+33
View File
@@ -0,0 +1,33 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tape helper routine - pulse reading
//
// Returns pulse length (with a bias, see comments) in .A
//
#if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO
tape_common_get_pulse:
// Contrary to original ROM implementation we do not use interrupts
// (see http://unusedino.de/ec64/technical/formats/tap.html) - busy wait
// implementation is probably just shorter
lda #$10
!:
bit CIA1_ICR // $DC0D
beq !- // busy loop to detect signal, restart timer afterwards
lda CIA2_TIMBLO // $DD06
ldx #%01010001 // start timer, force latch reload, count timer A underflows
stx CIA2_CRB // $DD0F
cmp __pulse_threshold // sdefault pulse check
rts
#endif
+1 -1
View File
@@ -7,7 +7,7 @@
//
//
// Checked under VICE, PAL, average of 256 pulses: XXX retry measurements for NORMAL, something is probably wrong
// Checked under VICE, PAL, average of 256 pulses:
//
// normal - short - timer goes down to $A5
// normal - medium - timer goes down to $7D
+86
View File
@@ -0,0 +1,86 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tape (normal) helper routine - reading speed calibration
//
// Needs pulse length in .A
//
#if CONFIG_TAPE_NORMAL
tape_normal_calibrate_during_pilot: // reecalibration during the pilot
sta __normal_time_S
// We do not have any recent medium pulse measurement,
// probably the only solution is to estimate it
lda $FF
sec
sbc __normal_time_S
// We now have a difference from the starting point ($FF)
clc
rol
sta __normal_time_M // this is temporary only!
// We now have half the difference, substract it from
// short pulse measurement result
lda __normal_time_S
clc
sbc __normal_time_M
// XXX add some constant to get a proper __normal_time_M ($7D if starting from $A5), afterwards remove __normal_time_M initialization from tape_normal_get_pilot_header
sta __normal_time_M
jmp tape_normal_calibrate_common
tape_normal_calibrate_after_S: // recalibration after short pulse
sta __normal_time_S
rts
skip_2_bytes_trash_nvz
// FALLTROUGH
tape_normal_calibrate_after_M: // recalibration after medium pulse
sta __normal_time_M
// FALLTROUGH
tape_normal_calibrate_common:
// Now compare results with current threshold
lda __normal_time_S
sec
sbc __pulse_threshold
clc
adc __normal_time_M
cmp __pulse_threshold
beq tape_normal_calibrate_done // branch if no recalibration needed
// XXX implement recalibration
tape_normal_calibrate_done:
rts
#endif
+12 -4
View File
@@ -16,17 +16,20 @@ tape_normal_get_bit:
// Fetch the first pulse
jsr tape_normal_get_pulse
jsr tape_common_get_pulse
bcc tape_normal_get_bit_1
// First impulse was short, second should be medium
jsr tape_normal_get_pulse
jsr tape_normal_calibrate_after_S
jsr tape_common_get_pulse
bcs tape_normal_get_bit_error
jsr tape_normal_calibrate_after_M
// We have a bit '0'
// Carry flag already clear
lda #$00
// FALLTROUGH
@@ -34,6 +37,7 @@ tape_normal_get_bit:
tape_normal_get_bit_done:
sta VIC_EXTCOL
clc
rts
@@ -41,9 +45,13 @@ tape_normal_get_bit_1:
// First impulse was medium, second should be short
jsr tape_normal_get_pulse
jsr tape_normal_calibrate_after_M
jsr tape_common_get_pulse
bcc tape_normal_get_bit_error
jsr tape_normal_calibrate_after_S
// We have a bit '1'
clc
+33 -6
View File
@@ -5,22 +5,49 @@
//
// Tape (normal) helper routine - marker reading
//
// Reeturns marker type in Carry flag, set = end of data
// Reeturns marker type in Carry flag, set = end of data (normal marker) or failure (marker while sync)
//
#if CONFIG_TAPE_NORMAL
// (L,M) - end of byte, (L,S) - end of data
tape_normal_get_marker:
tape_normal_get_marker:
jsr tape_common_get_pulse
cmp __pulse_threshold_ML
bcs tape_normal_get_marker // too short for a long pulse
// FALLTROUGH
tape_normal_get_marker_type:
jmp tape_common_get_pulse
!: // Not an entry point!!!
// XXX check for short pulses of turbo here
jsr tape_normal_calibrate_during_pilot // while sync use short pulses for calibration
// FALLTROUGH
tape_normal_get_marker_while_sync:
// (L,M) - end of byte, (L,S) - end of data
jsr tape_normal_get_pulse
cmp #($FF - $98 - $04)
bcs tape_normal_get_marker // too short for a long pulse
jsr tape_common_get_pulse
bcs !- // branch if short pulse
jmp tape_normal_get_pulse
cmp __pulse_threshold_ML
bcs tape_normal_get_marker_while_sync // too short for a long pulse
bcc tape_normal_get_marker_type // branch always
#endif
+93
View File
@@ -0,0 +1,93 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tape (turbo) helper routine - handling the pilot
//
// Injest the pilot - series of short pulses. According to http://sidpreservation.6581.org/tape-format/
// it consist of the following number of pulses:
// - $6A00 for header
// - $1A00 for data and seq block header
// - $4F for repeated header/data
#if CONFIG_TAPE_NORMAL
// XXX in tape_normal_get_pilot_header also try to detect turbo
tape_normal_get_pilot_header: // entry point, reset calibration, require 128x $40 pulses
// Reading the pilot header is the first action performed,
// thus start by setting default timings, as measured during
// VICE test
lda #$7D
sta __normal_time_M // __normal_time_S will be set within the pilot
lda #$91
sta __pulse_threshold
lda #$67
sta __pulse_threshold_ML
lda #$80
skip_2_bytes_trash_nvz
// FALLTROUGH
tape_normal_get_pilot_data: // entry point, require 4x $40 pulses
lda #$04
skip_2_bytes_trash_nvz
// FALLTROUGH
tape_normal_get_pilot_short: // entry point, require 1x $40 pulses
lda #$01
// FALLTROUGH
tape_normal_get_pilot_common:
sta FSBLK
lda #$0B
sta VIC_EXTCOL
// FALLTROUGH
tape_normal_get_pilot_common_restart:
lda FSBLK
sta ROPRTY
// FALLTROUGH
tape_normal_get_pilot_common_loop_outer:
ldy #$40
// FALLTROUGH
tape_normal_get_pilot_common_loop_inner:
jsr tape_common_get_pulse
// XXX check for short pulses of turbo here
bcc tape_normal_get_pilot_common_restart // not a pilot - try again
jsr tape_normal_calibrate_during_pilot
dey
bne tape_normal_get_pilot_common_loop_inner
dec ROPRTY
bne tape_normal_get_pilot_common_loop_outer
rts
#endif
-44
View File
@@ -1,44 +0,0 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tape (normal) helper routine - pulse reading
//
// Returns pulse length (with a bias, see comments) in .A
//
#if CONFIG_TAPE_NORMAL
tape_normal_get_pulse:
// Contrary to original ROM implementation we do not use interrupts
// (see http://unusedino.de/ec64/technical/formats/tap.html) - busy wait
// implementation is probably just shorter
lda #$10
!:
bit CIA1_ICR // $DC0D
beq !- // busy loop to detect signal, restart timer afterwards
lda CIA2_TIMBLO // $DD06
ldx #%01010001 // start timer, force latch reload, count timer A underflows
stx CIA2_CRB // $DD0F
// Since the signal appeared to the point of timer restart we used:
// bit - 4 cycles
// beq - 2 cycles
// lda - 4 cycles
// ldx - 2 cycles
// stx - 4 cycles
// plus average 3 cycles (bit + beq time divided by 2) from value change to 'bit' instruction
// minus average 2 cycles due to timer A running continouslyy (might start before the pulse)
// this is total 17 cycles, or $4 periods of 4 ticks (timer A) each - we need to take it into account
// every time we check the pulse length
cmp #($FF - $72 - $04) // short vs medium is the default check
rts
#endif
-78
View File
@@ -1,78 +0,0 @@
// #LAYOUT# STD * #TAKE
// #LAYOUT# * KERNAL_0 #TAKE
// #LAYOUT# * * #IGNORE
//
// Tape (turbo) helper routine - handling the pilot
//
// Injest the pilot - series of short pulses. According to http://sidpreservation.6581.org/tape-format/
// it consist of the following number of pulses:
// - $6A00 for header
// - $1A00 for data and seq block header
// - $4F for repeated header/data
#if CONFIG_TAPE_NORMAL
tape_normal_pilot_short: // require 1x $40 pulses
lda #$01
// FALLTROUGH
tape_normal_pilot_common:
sta FSBLK
// FALLTROUGH
tape_normal_pilot_common_restart:
lda #$0B
sta VIC_EXTCOL
lda FSBLK
sta ROPRTY
// FALLTROUGH
tape_normal_pilot_common_loop_outer:
ldy #$40
// FALLTROUGH
tape_normal_pilot_common_loop_inner:
jsr tape_normal_get_pulse
bcc tape_normal_pilot_common_restart // not a pilot - try again
dey
bne tape_normal_pilot_common_loop_inner
dec ROPRTY
bne tape_normal_pilot_common_loop_outer
rts
tape_normal_pilot_data: // require 4x $40 pulses
lda #$04
skip_2_bytes_trash_nvz
// FALLTROUGH
tape_normal_pilot_header: // require 128x $40 pulses
lda #$80
jmp tape_normal_pilot_common // XXX calibrate tape speed afterwards
#endif
+1 -1
View File
@@ -19,7 +19,7 @@ tape_normal_sync:
// Injest bytes of decreasing values
jsr tape_normal_get_marker
jsr tape_normal_get_marker_while_sync
bcs tape_normal_sync_fail // branch if end of data marker
jsr tape_normal_get_byte
+3 -19
View File
@@ -14,29 +14,13 @@
tape_turbo_get_bit:
#if CONFIG_TAPE_NORMAL
jsr tape_normal_get_pulse // reuse routine from NORMAL system
#else
lda #$10
!:
bit CIA1_ICR // $DC0D
beq !- // busy loop to detect signal, restart timer afterwards
lda CIA2_TIMBLO // $DD06
ldx #%01010001 // start timer, force latch reload, count timer A underflows
stx CIA2_CRB // $DD0F
#endif
cmp SYNO // threshold
jsr tape_common_get_pulse
bcs !+
clc
ror
sta IRQTMP+0 // store half of the last measurement result for short pulse
sta __turbo_half_S // store half of the last measurement result for short pulse
lda #$01
sta SID_SIGVOL
@@ -47,7 +31,7 @@ tape_turbo_get_bit:
!:
clc
ror
sta IRQTMP+1 // store half of the last measurement result for long pulse
sta __turbo_half_L // store half of the last measurement result for long pulse
lda #$00
sta SID_SIGVOL
+7 -7
View File
@@ -28,28 +28,28 @@ tape_turbo_get_byte:
// Compensate for tape speed variations
lda IRQTMP+0 // half of the last value for bit '0'
lda __turbo_half_S // half of the last value for bit '0'
clc
adc IRQTMP+1 // half of the last value for bit '1'
adc __turbo_half_L // half of the last value for bit '1'
sec
sbc SYNO // now we have a diff between current threshold and calculated one
sbc __pulse_threshold // now we have a diff between current threshold and calculated one
beq tape_turbo_get_byte_done // branch if threshold correction not needed
bpl !+
lda SYNO
lda __pulse_threshold
cmp #($BF - 10)
beq tape_turbo_get_byte_done // do not decrease threshold too far no matter what
dec SYNO
dec __pulse_threshold
bne tape_turbo_get_byte_done // branch always
!:
lda SYNO
lda __pulse_threshold
cmp #($BF + 10)
beq tape_turbo_get_byte_done // do not increase threshold too far no matter what
inc SYNO
inc __pulse_threshold
tape_turbo_get_byte_done:
+1 -1
View File
@@ -17,7 +17,7 @@ tape_turbo_sync_header:
// Initial pulse threshold
lda #$BF // measured 128 bits '0' and 128 bits '1' under VICE, calculated average
sta SYNO
sta __pulse_threshold
// Synchronize with start of sync sequence
jsr tape_turbo_sync_first