diff --git a/CONFIG.md b/CONFIG.md index 800e646d..f5aa8e83 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -155,12 +155,6 @@ Adds a minimal turbo tape support - just LOAD command (device 7, like on _Action Needs about 650 bytes in KERNAL segment (if both normal and turbo are enabled, about 950 bytes are needed, as they share some code). If unsure - enable. -### `CONFIG_TAPE_TURBO_AUTOCALIBRATE` - -Extends the tape turbo load functionality by ability to adjust to tape speed differences. - -Needs about 100 bytes in KERNAL segment. If unsure - enable for Datasette or other tape recorder, disable for digital solutions like Tapuino. - ### `CONFIG_TAPE_NO_KEY_SENSE` Enable this option if you are using a tape interface adapter with some audio signal source connected. These adapters lack key sense functionality, so the computer is unable to tell whether Play got pressed or not - with this option ROM will assume Play got pressed after imppulses start arriving from the tape. diff --git a/STATUS.md b/STATUS.md index acbe51e6..80eed824 100644 --- a/STATUS.md +++ b/STATUS.md @@ -11,7 +11,7 @@ Here are the features of the Open ROMs not found in the original ROMs from the 8 * JiffyDOS and DolphinDOS protocols support * DOS wedge (direct mode only) - `@`, `@`, `@$`, `@$`, `@` -* turbo tape load support (as device 7, or using `←L`), quite sophisticated: up to 250 blocks (can store bytes under I/O), can use sync signal for autocalibration (less load errors than simple turbos) +* turbo tape load support (as device 7, or using `←L`), quite sophisticated: up to 250 blocks (can store bytes under I/O), automatically adjusts for tape speed differences * improved support for tape adapters (for using regular casette players and other audio devices instead of Datasette) * extended `LOAD` command diff --git a/c64/,,config_custom.s b/c64/,,config_custom.s index 40fa8d18..95bfda75 100644 --- a/c64/,,config_custom.s +++ b/c64/,,config_custom.s @@ -56,7 +56,6 @@ #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -#define CONFIG_TAPE_TURBO_AUTOCALIBRATE // #define CONFIG_TAPE_NO_KEY_SENSE // #define CONFIG_TAPE_NO_MOTOR_CONTROL diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s index e091a2af..4195ef46 100644 --- a/c64/,,config_generic.s +++ b/c64/,,config_generic.s @@ -50,7 +50,6 @@ #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -#define CONFIG_TAPE_TURBO_AUTOCALIBRATE // #define CONFIG_TAPE_NO_KEY_SENSE // #define CONFIG_TAPE_NO_MOTOR_CONTROL diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s index ea322e26..add9c08e 100644 --- a/c64/,,config_mega65.s +++ b/c64/,,config_mega65.s @@ -50,7 +50,6 @@ // #define CONFIG_TAPE_NORMAL // #define CONFIG_TAPE_TURBO -// #define CONFIG_TAPE_TURBO_AUTOCALIBRATE // #define CONFIG_TAPE_NO_KEY_SENSE // #define CONFIG_TAPE_NO_MOTOR_CONTROL diff --git a/c64/,,config_testing.s b/c64/,,config_testing.s index 59e2dbaa..0f7a164f 100644 --- a/c64/,,config_testing.s +++ b/c64/,,config_testing.s @@ -50,7 +50,6 @@ // #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -// #define CONFIG_TAPE_TURBO_AUTOCALIBRATE // #define CONFIG_TAPE_NO_KEY_SENSE // #define CONFIG_TAPE_NO_MOTOR_CONTROL diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s index 24045b8a..f2927c60 100644 --- a/c64/,,config_ultimate64.s +++ b/c64/,,config_ultimate64.s @@ -50,7 +50,6 @@ #define CONFIG_TAPE_NORMAL #define CONFIG_TAPE_TURBO -#define CONFIG_TAPE_TURBO_AUTOCALIBRATE // #define CONFIG_TAPE_NO_KEY_SENSE // #define CONFIG_TAPE_NO_MOTOR_CONTROL diff --git a/c64/aliases/,aliases_ram_lowmem.s b/c64/aliases/,aliases_ram_lowmem.s index 50f63017..4e6d2593 100644 --- a/c64/aliases/,aliases_ram_lowmem.s +++ b/c64/aliases/,aliases_ram_lowmem.s @@ -88,7 +88,7 @@ .label VERCKK = $93 // 0 = LOAD, 1 = VERIFY .label C3PO = $94 // flag - is BSOUR content valid .label BSOUR = $95 // serial bus buffered output byte - .label SYNO = $96 // -- NOT IMPLEMENTED -- + .label SYNO = $96 // temporary tape routines storage, [!] our usage differs .label XSAV = $97 // temporary register storage for ASCII/tape related routines [!] usage details might differ .label LDTND = $98 // number of entries in LAT / FAT / SAT tables .label DFLTN = $99 // default input device diff --git a/c64/kernal/tape/tape_common_prepare_cia.s b/c64/kernal/tape/tape_common_prepare_cia.s index 113dc339..8650e3e1 100644 --- a/c64/kernal/tape/tape_common_prepare_cia.s +++ b/c64/kernal/tape/tape_common_prepare_cia.s @@ -2,6 +2,37 @@ // #LAYOUT# * KERNAL_0 #TAKE // #LAYOUT# * * #IGNORE +// +// Prepare CIA timers for tape reading +// + +// +// Checked under VICE, PAL, average of 256 pulses: +// +// normal - short - timer goes down to $C9 +// normal - medium - timer goes down to $79 +// normal - long - timer goes down to $52 +// +// turbo - short - timer goes down to $B1 +// turbo - long - timer goes down to $CD +// +// +// Measurement subroutine: .A should contain timer value, $C000-$C002 zeroed +// +// clc +// adc $C001 +// sta $C001 +// bcc !+ +// inc $C000 +// !: +// inc $C002 +// beq !+ +// rts +// !: +// lda $C000 +// .break // .A contains our average +// rts +// #if CONFIG_TAPE_NORMAL || CONFIG_TAPE_TURBO diff --git a/c64/kernal/tape/tape_turbo_get_bit.s b/c64/kernal/tape/tape_turbo_get_bit.s index baba4ffb..e636772a 100644 --- a/c64/kernal/tape/tape_turbo_get_bit.s +++ b/c64/kernal/tape/tape_turbo_get_bit.s @@ -31,16 +31,13 @@ tape_turbo_get_bit: #endif - -#if CONFIG_TAPE_TURBO_AUTOCALIBRATE - tax - cmp IRQTMP+0 -#else - cmp #$BF // threshold calculated by autocalibration routines under VICE -#endif - + cmp SYNO // threshold bcs !+ + clc + ror + sta IRQTMP+0 // store half of the last measurement result for short pulse + lda #$01 sta SID_SIGVOL lda #$06 @@ -48,6 +45,10 @@ tape_turbo_get_bit: sec rts !: + clc + ror + sta IRQTMP+1 // store half of the last measurement result for long pulse + lda #$00 sta SID_SIGVOL sta VIC_EXTCOL diff --git a/c64/kernal/tape/tape_turbo_get_byte.s b/c64/kernal/tape/tape_turbo_get_byte.s index 055bbf0e..7dfe6d66 100644 --- a/c64/kernal/tape/tape_turbo_get_byte.s +++ b/c64/kernal/tape/tape_turbo_get_byte.s @@ -25,8 +25,35 @@ tape_turbo_get_byte: rol INBIT bcc !- // is the initial 1 shifted into carry already? plx_trash_a - lda INBIT + // Compensate for tape speed variations + + lda IRQTMP+0 // half of the last value for bit '0' + clc + adc IRQTMP+1 // half of the last value for bit '1' + + sec + sbc SYNO // 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 + cmp #($BF - 10) + beq tape_turbo_get_byte_done // do not decrease threshold too far no matter what + + dec SYNO + bne tape_turbo_get_byte_done // branch always +!: + lda SYNO + cmp #($BF + 10) + beq tape_turbo_get_byte_done // do not increase threshold too far no matter what + + inc SYNO + +tape_turbo_get_byte_done: + + lda INBIT rts diff --git a/c64/kernal/tape/tape_turbo_sync.s b/c64/kernal/tape/tape_turbo_sync.s index 132f2e07..69367308 100644 --- a/c64/kernal/tape/tape_turbo_sync.s +++ b/c64/kernal/tape/tape_turbo_sync.s @@ -15,8 +15,9 @@ tape_turbo_sync_header: - -#if !CONFIG_TAPE_TURBO_AUTOCALIBRATE + // Initial pulse threshold + lda #$BF // measured 128 bits '0' and 128 bits '1' under VICE, calculated average + sta SYNO // Synchronize with start of sync sequence jsr tape_turbo_sync_first @@ -24,106 +25,19 @@ tape_turbo_sync_header: // Perform synchronization, double loop, total $C0 * $04 iterations ldx #$C0 !: - phx_trash_a ldy #$04 !: + stx XSAV jsr tape_turbo_get_byte cmp #$02 bne tape_turbo_sync_header // branch if failure dey bne !- - plx_trash_a + ldx XSAV dex bne !-- -#else // CONFIG_TAPE_TURBO_AUTOCALIBRATE - - // Initial pulse threshold - lda #$BF // auto-calibration under VICE often returns this value - sta IRQTMP+0 - - // Zero temporary stack area - lda #$00 - ldy #$03 -!: - sta STACK, y - dey - bpl !- - - // Synchronize with start of sync sequence - jsr tape_turbo_sync_first - - // Perform synchronization, get measurements from 128 bytes - ldx #$10 - - // FALLTROUGH - -tape_turbo_sync_outer_loop: - - // Set .Y (inner loop counter) to $28-$38, average $30; $10 * $30 equals $C0 * $04 - // We want a bit of irregularity with byte selection for calibration - txa - pha // store .X - clc - adc #$27 - tay - - // FALLTROUGH - -tape_turbo_sync_inner_loop: - - cpy #$09 - bcc !+ // if inner couter is 8 or lower, get this byte for measurement - - // Get byte without measurements - jsr tape_turbo_get_byte - cmp #$02 - bne tape_turbo_sync_header // branch if failure - beq tape_turbo_sync_header_next_iter // branch always - -!: - // Get byte and take measurements - - phy_trash_a - - // Skip 5 bits, they should be all 0 - ldy #$04 -!: - jsr tape_turbo_get_bit - bcs tape_turbo_sync_header - dey - bpl !- - - // Get measurements from 3 bits - jsr tape_turbo_sync_measure_0 - jsr tape_turbo_sync_measure_1 - jsr tape_turbo_sync_measure_0 - - ply_trash_a - - // FALLTROUGH - -tape_turbo_sync_header_next_iter: - - dey - bne tape_turbo_sync_inner_loop - plx_trash_a - dex - bne tape_turbo_sync_outer_loop - - // Calculate new pulse threshold as arithmetic mean - // We accumulated 256 zeros and 128 ones, so calculating average value is easy - - lda STACK+0 - clc - ror - clc - adc STACK+1 - sta IRQTMP+0 - -#endif // CONFIG_TAPE_TURBO_AUTOCALIBRATE - // FALLTROUGH tape_turbo_sync_payload: