Back to the begin
This commit is contained in:
@@ -4,22 +4,13 @@
|
||||
.org TAPE_LOADER_ROM_ADDRESS
|
||||
|
||||
TAPE_PORT = 0x18
|
||||
MAX_CYCLE_COUNT = 20
|
||||
MAX_BLOCK_SIZE = 0x200
|
||||
MAX_BLOCK_SIZE = 0x100
|
||||
|
||||
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
|
||||
BLOCK_LENGTH = WORK_BASE + 0x08 ; word
|
||||
BLOCK_NUMBER = WORK_BASE + 0x0a ; byte
|
||||
NR_OF_BLOCKS = WORK_BASE + 0x0b ; word
|
||||
|
||||
BLOCK_BUFFER = WORK_BASE + 0x100 ; MAX_BLOCK_SIZE
|
||||
|
||||
@@ -40,87 +31,17 @@ save_iff:
|
||||
di
|
||||
ld sp,#STACK_TOP
|
||||
|
||||
|
||||
main:
|
||||
; Initial message.
|
||||
ld hl,#msg_start
|
||||
call print_with_irqs
|
||||
|
||||
; Read the first block
|
||||
call read_block
|
||||
jr z,1$
|
||||
ld hl,#msg_error_checksum
|
||||
ei
|
||||
call print_string
|
||||
call print_crlf
|
||||
di
|
||||
jp exit
|
||||
1$:
|
||||
; nr of blocks and filename stored in buffer
|
||||
ld hl,(BLOCK_BUFFER)
|
||||
ld (NR_OF_BLOCKS),hl
|
||||
|
||||
; Print info of blocks
|
||||
ei
|
||||
ld hl,#msg_filename
|
||||
call print_string
|
||||
ld hl,#BLOCK_BUFFER
|
||||
inc hl
|
||||
inc hl
|
||||
call print_string
|
||||
call print_crlf
|
||||
ld hl,#msg_nr_of_blocks
|
||||
call print_string
|
||||
ld hl,(NR_OF_BLOCKS)
|
||||
call print_hex16
|
||||
call print_crlf
|
||||
|
||||
call BIOS_FLUSH
|
||||
di
|
||||
|
||||
; #################################################3
|
||||
; Read a consecutive list of blocks
|
||||
; #################################################3
|
||||
read_consecutive_blocks:
|
||||
ld bc,(NR_OF_BLOCKS)
|
||||
push bc
|
||||
1$:
|
||||
call read_block
|
||||
jr z,2$
|
||||
ei
|
||||
ld a,#'x'
|
||||
call BIOS_PUTC
|
||||
call BIOS_FLUSH
|
||||
di
|
||||
jr 3$
|
||||
2$:
|
||||
ei
|
||||
ld a,#'*'
|
||||
call BIOS_PUTC
|
||||
call BIOS_FLUSH
|
||||
di
|
||||
|
||||
3$:
|
||||
pop bc
|
||||
dec bc
|
||||
push bc
|
||||
; Check for zero
|
||||
ld a,b
|
||||
or a,c
|
||||
jr nz,1$
|
||||
pop bc
|
||||
|
||||
; All blocks are read
|
||||
ei
|
||||
ld a,#'V'
|
||||
call BIOS_PUTC
|
||||
call print_crlf
|
||||
call BIOS_FLUSH
|
||||
di
|
||||
call print_string_ei
|
||||
|
||||
; #################################################3
|
||||
; Exit
|
||||
; #################################################3
|
||||
exit:
|
||||
ei
|
||||
call BIOS_FLUSH
|
||||
di
|
||||
ld sp,(OLD_SP)
|
||||
; Return code 0
|
||||
@@ -136,350 +57,10 @@ exit:
|
||||
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
|
||||
; Eat A cycles
|
||||
; #################################################3
|
||||
eat_cycles:
|
||||
or a,a
|
||||
ret z
|
||||
ld c,a
|
||||
1$:
|
||||
call wait_cycle
|
||||
dec c
|
||||
jr nz,1$
|
||||
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
|
||||
; Calibrate
|
||||
; Gets short and long pulse lenghts and bit pulse counts
|
||||
; from training sequence
|
||||
; carry = succeeded
|
||||
; #################################################3
|
||||
calibrate:
|
||||
; establish comparator state
|
||||
in a,(TAPE_PORT)
|
||||
ld d,a
|
||||
; Wait for the first edge
|
||||
call wait_edge
|
||||
; Wait for the next edge to be back in phase with the
|
||||
; audio stream
|
||||
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
|
||||
ld a,#MAX_CYCLE_COUNT
|
||||
cp a,e
|
||||
jp c,error_cycle_count
|
||||
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
|
||||
ld a,#MAX_CYCLE_COUNT
|
||||
cp a,e
|
||||
jp c,error_cycle_count
|
||||
jr 6$
|
||||
7$:
|
||||
ld a,e
|
||||
ld (LONG_COUNT),a
|
||||
|
||||
; First cycle of short was already consymed
|
||||
ld a,(SHORT_COUNT)
|
||||
dec a
|
||||
call eat_cycles
|
||||
|
||||
; Consume rest of training bits
|
||||
; 6 L/S pairs then last L
|
||||
ld h,#6
|
||||
8$:
|
||||
ld a,(LONG_COUNT)
|
||||
call eat_cycles
|
||||
ld a,(SHORT_COUNT)
|
||||
call eat_cycles
|
||||
dec h
|
||||
jr nz,8$
|
||||
ld a,(LONG_COUNT)
|
||||
call eat_cycles
|
||||
|
||||
; Test calibration with sync byte
|
||||
call check_sync_byte
|
||||
ret
|
||||
|
||||
error_cycle_count:
|
||||
ei
|
||||
ld hl,#msg_error_cycle_count
|
||||
call print_string
|
||||
call print_crlf
|
||||
di
|
||||
jp exit
|
||||
|
||||
|
||||
; #################################################3
|
||||
; Read one bit
|
||||
; carry = value
|
||||
; #################################################3
|
||||
read_bit:
|
||||
call wait_cycle
|
||||
ld a,(TRESHOLD)
|
||||
ld c,a
|
||||
ld a,b
|
||||
cp a,c
|
||||
jr c,2$
|
||||
|
||||
; zero bit
|
||||
1$:
|
||||
ld a,(LONG_COUNT)
|
||||
dec a
|
||||
call eat_cycles
|
||||
or a,a ; clear carry
|
||||
ret
|
||||
; one bit
|
||||
2$:
|
||||
ld a,(SHORT_COUNT)
|
||||
dec a
|
||||
call eat_cycles
|
||||
scf ; set carry
|
||||
ret
|
||||
|
||||
; #################################################3
|
||||
; Read byte
|
||||
; A = byte
|
||||
; #################################################3
|
||||
read_byte:
|
||||
ld e,#0
|
||||
ld h,#8
|
||||
1$:
|
||||
call read_bit
|
||||
rl e
|
||||
dec h
|
||||
jr nz,1$
|
||||
ld a,e
|
||||
ret
|
||||
|
||||
; #################################################3
|
||||
; Check sync byte
|
||||
; carry = succeeded
|
||||
; #################################################3
|
||||
check_sync_byte:
|
||||
call read_byte
|
||||
ld e,a
|
||||
ld a,#0xf0
|
||||
cp a,e
|
||||
jr z,1$
|
||||
or a,a
|
||||
ret
|
||||
1$:
|
||||
scf
|
||||
ret
|
||||
|
||||
error_wrong_sync_byte:
|
||||
ei
|
||||
ld hl,#msg_error_sync_not_found
|
||||
call print_string
|
||||
call print_crlf
|
||||
di
|
||||
jp exit
|
||||
|
||||
; #################################################3
|
||||
; Read a block
|
||||
; checksum in a
|
||||
; #################################################3
|
||||
read_block:
|
||||
call calibrate
|
||||
jp nc,error_wrong_sync_byte
|
||||
|
||||
; Get block number
|
||||
call read_byte
|
||||
ld (BLOCK_NUMBER),a
|
||||
|
||||
; Get block length
|
||||
call read_byte
|
||||
ld b,a
|
||||
push bc
|
||||
call read_byte
|
||||
pop bc
|
||||
ld c,a
|
||||
ld (BLOCK_LENGTH),bc
|
||||
|
||||
; Check block length against max length
|
||||
;ld hl,#MAX_BLOCK_SIZE
|
||||
;and a,a
|
||||
;sbc hl, bc
|
||||
;jp c,error_block_too_big
|
||||
|
||||
exx
|
||||
|
||||
ld bc,(BLOCK_LENGTH)
|
||||
ld hl,#BLOCK_BUFFER
|
||||
|
||||
1$:
|
||||
exx
|
||||
call read_byte
|
||||
exx
|
||||
|
||||
ld (hl),a
|
||||
inc hl
|
||||
|
||||
dec bc
|
||||
; Check for zero
|
||||
ld a,b
|
||||
or a,c
|
||||
jr nz,1$
|
||||
|
||||
; Read checksum
|
||||
exx
|
||||
call read_byte
|
||||
|
||||
; Calculate checksum of block
|
||||
ld hl,#BLOCK_BUFFER
|
||||
ld bc,(BLOCK_LENGTH)
|
||||
push af
|
||||
xor a,a
|
||||
ld e,a
|
||||
2$:
|
||||
ld a,e
|
||||
add a,(hl)
|
||||
ld e,a
|
||||
inc hl
|
||||
dec bc
|
||||
; Check for zero
|
||||
ld a,b
|
||||
or a,c
|
||||
jr nz,2$
|
||||
|
||||
pop af
|
||||
; e is calculated checksum
|
||||
; a is received checksum
|
||||
ld h,a
|
||||
ld l,e
|
||||
cp a,e
|
||||
ret
|
||||
|
||||
error_block_too_big:
|
||||
ei
|
||||
ld hl,#msg_error_block_too_big
|
||||
call print_string
|
||||
call print_crlf
|
||||
di
|
||||
jp exit
|
||||
|
||||
|
||||
; #################################################3
|
||||
; IO Helper functions
|
||||
; #################################################3
|
||||
print_with_irqs:
|
||||
print_string_ei:
|
||||
ei
|
||||
call print_string
|
||||
call BIOS_FLUSH
|
||||
@@ -537,48 +118,3 @@ print_hex_digit:
|
||||
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
|
||||
|
||||
msg_error_cycle_count:
|
||||
.ascii "Cycle count out of bounds"
|
||||
.db 0
|
||||
|
||||
msg_error_sync_not_found:
|
||||
.ascii "Sync not found"
|
||||
.db 0
|
||||
|
||||
msg_error_checksum:
|
||||
.ascii "Checksum error"
|
||||
.db 0
|
||||
|
||||
msg_filename:
|
||||
.ascii "Filename: "
|
||||
.db 0
|
||||
|
||||
msg_nr_of_blocks:
|
||||
.ascii "Blocks: "
|
||||
.db 0
|
||||
|
||||
msg_error_block_too_big:
|
||||
.ascii "Block too big"
|
||||
.db 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user