diff --git a/apps/casette/tape_loader.asm b/apps/casette/tape_loader.asm index a25dacc..975b26c 100644 --- a/apps/casette/tape_loader.asm +++ b/apps/casette/tape_loader.asm @@ -4,581 +4,117 @@ .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 +OLD_SP = WORK_BASE + 0x00 ; word +OLD_IFF = WORK_BASE + 0x02 ; byte -BLOCK_BUFFER = WORK_BASE + 0x100 ; MAX_BLOCK_SIZE +BLOCK_BUFFER = WORK_BASE + 0x100 ; MAX_BLOCK_SIZE ; #################################################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 + 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 + xor a save_iff: - ld (OLD_IFF),a - di - ld sp,#STACK_TOP + ld (OLD_IFF),a + di + ld sp,#STACK_TOP - - ; 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 +main: + ; Initial message. + ld hl,#msg_start + call print_string_ei ; #################################################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 + ei + call BIOS_FLUSH + 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 -; 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 - + ret ; #################################################3 ; IO Helper functions ; #################################################3 -print_with_irqs: - ei - call print_string - call BIOS_FLUSH - di - ret +print_string_ei: + 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 + 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 + ld a,#13 + call BIOS_PUTC + ld a,#10 + jp BIOS_PUTC print_hex16: - push hl - ld a,h - call print_hex8 - pop hl - ld a,l - call print_hex8 - ret + push hl + ld a,h + call print_hex8 + pop hl + ld a,l + call print_hex8 + ret print_hex8: - push af - rrca - rrca - rrca - rrca - and #0x0F - call print_hex_nibble - pop af - and #0x0F + push af + rrca + rrca + rrca + rrca + and #0x0F + call print_hex_nibble + pop af + and #0x0F - ; fall through + ; fall through print_hex_nibble: - cp #10 - jr c,print_hex_digit - add a,#('A' - 10) - jp BIOS_PUTC + cp #10 + jr c,print_hex_digit + add a,#('A' - 10) + jp BIOS_PUTC print_hex_digit: - add a,#'0' - jp BIOS_PUTC + 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 - -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 - + .ascii "TAPE DECODE TEST - PLAY TAPE" + .db 13,10,0