Files
z80_monitor/apps/casette/tape_loader.asm
T
2026-10-04 13:53:22 +02:00

305 lines
5.0 KiB
NASM

.include "bios.inc"
.area TAPELOAD (ABS)
.org TAPE_LOADER_ROM_ADDRESS
TAPE_PORT = 0x18
STACK_TOP = 0xBFFF
WORK_BASE = 0xB000
OLD_SP = WORK_BASE + 0x00 ; word
OLD_IFF = WORK_BASE + 0x02 ; byte
SHORT_LEN = WORK_BASE + 0x03 ; byte
LONG_LEN = WORK_BASE + 0x04 ; byte
TRESHOLD = WORK_BASE + 0x05 ; byte
SHORT_COUNT = WORK_BASE + 0x06 ; byte
LONG_COUNT = WORK_BASE + 0x07 ; byte
; #################################################3
; Entry
; #################################################3
tape_loader:
ld (OLD_SP),sp
; Save interrupt state.
ld a,i
jp po,iff_was_off
ld a,#1
jr save_iff
iff_was_off:
xor a
save_iff:
ld (OLD_IFF),a
di
ld sp,#STACK_TOP
; Initial message.
ld hl,#msg_start
call print_with_irqs
; Calibrate receiver
call calibrate
; Print parameters
ei
ld hl,#msg_short_len
call print_string
ld a,(SHORT_LEN)
call print_hex8
call print_crlf
ld hl,#msg_long_len
call print_string
ld a,(LONG_LEN)
call print_hex8
call print_crlf
ld hl,#msg_treshold
call print_string
ld a,(TRESHOLD)
call print_hex8
call print_crlf
ld hl,#msg_short_count
call print_string
ld a,(SHORT_COUNT)
call print_hex8
call print_crlf
ld hl,#msg_long_count
call print_string
ld a,(LONG_COUNT)
call print_hex8
call print_crlf
call BIOS_FLUSH
di
; #################################################3
; Exit
; #################################################3
exit:
di
ld sp,(OLD_SP)
; Return code 0
ld a,#0
ld c,a
; Restore caller's interrupt state.
ld a,(OLD_IFF)
or a
ld a,c
jr z,return_di
ei
ret
return_di:
ret
; #################################################3
; Wait for next edge
; D holds current comparator state
; Returns B = loop count
; #################################################3
wait_edge:
ld b,#0
1$:
inc b
in a,(TAPE_PORT)
cp a,d
jr z,1$
ld d,a
ret
; #################################################3
; Wait for a full cycle
; D holds the current comparator state
; Returns B = loop count
; #################################################3
wait_cycle:
ld b,#0
1$:
inc b
in a,(TAPE_PORT)
cp a,d
jp z,1$
ld d,a
2$:
inc b
in a,(TAPE_PORT)
cp a,d
jp z,2$
ld d,a
ret
; #################################################3
; Average 16 cycle intervals
; Returns A = average loop count
; preserves bc
; #################################################3
average16:
push bc
ld c,#16
ld e,#0
1$:
call wait_cycle
; Add loop count to e and take moving average
ld a,e
add a,b
srl a
ld e,a
dec c
jr nz,1$
ld a,e
pop bc
ret
; #################################################3
; #################################################3
calibrate:
; establish comparator state
in a,(TAPE_PORT)
ld d,a
; Wait for the first edge
call wait_edge
; Measure shoft pulses
call average16
ld (SHORT_LEN), a
; Threshold for finding long pulse -> short*1.5
; stored in c
ld c,a
srl a
add a,c
ld c,a
; Wait for the first long pulse
1$:
call average16
cp a,c
jr c,1$
; Measure long pulses
call average16
ld (LONG_LEN), a
; Calculate period treshold
ld b,a
ld a,(SHORT_LEN)
; Average between the two lengths
add a,b
srl a
ld (TRESHOLD),a
; Wait for first short for training
ld c,a
3$:
call wait_cycle
ld a,b
cp a,c
jr nc,3$
; Count short cycles
ld e,#1
4$:
call wait_cycle
ld a,b
cp a,c
jr nc,5$
inc e
jr 4$
5$:
ld a,e
ld (SHORT_COUNT),a
; Count long cycles
ld e,#1
6$:
call wait_cycle
ld a,b
cp a,c
jr c,7$
inc e
jr 6$
7$:
ld a,e
ld (LONG_COUNT),a
ret
; #################################################3
; IO Helper functions
; #################################################3
print_with_irqs:
ei
call print_string
call BIOS_FLUSH
di
ret
print_string:
ld a,(hl)
or a
ret z
call BIOS_PUTC
inc hl
jr print_string
print_crlf:
ld a,#13
call BIOS_PUTC
ld a,#10
jp BIOS_PUTC
print_hex8:
push af
rrca
rrca
rrca
rrca
and #0x0F
call print_hex_nibble
pop af
and #0x0F
; fall through
print_hex_nibble:
cp #10
jr c,print_hex_digit
add a,#('A' - 10)
jp BIOS_PUTC
print_hex_digit:
add a,#'0'
jp BIOS_PUTC
; #################################################3
; Strings
; #################################################3
msg_start:
.ascii "TAPE DECODE TEST - PLAY TAPE"
.db 13,10,0
msg_short_len:
.ascii "Short len: "
.db 0
msg_long_len:
.ascii "Long len: "
.db 0
msg_treshold:
.ascii "Treshold: "
.db 0
msg_short_count:
.ascii "Short count: "
.db 0
msg_long_count:
.ascii "Long count: "
.db 0