tape training

This commit is contained in:
Joppe Blondel
2026-10-03 17:30:43 +02:00
parent 5897e55094
commit 9823a05ffe
8 changed files with 1085 additions and 43 deletions
+15 -10
View File
@@ -41,6 +41,9 @@ mode, or UART/CTC setup must restore it before returning.
prints the low 16 bits of the sum as four hexadecimal digits. The end address prints the low 16 bits of the sum as four hexadecimal digits. The end address
must be greater than or equal to the start address. must be greater than or equal to the start address.
`D` prints 16 bytes per row followed by an ASCII column. Bytes outside the
printable ASCII range are shown as `.`.
Build the ROM and programmer-format images with: Build the ROM and programmer-format images with:
```sh ```sh
@@ -84,15 +87,15 @@ The outputs are:
- `build/tinybasic/tinybasic.bin`: standalone relocated Tiny BASIC payload - `build/tinybasic/tinybasic.bin`: standalone relocated Tiny BASIC payload
- `build/casette/tape_loader.bin`: standalone relocated tape-loader payload - `build/casette/tape_loader.bin`: standalone relocated tape-loader payload
The current compact image is 12,318 bytes. Its ROM layout is: The current compact image is 12,967 bytes. Its ROM layout is:
- `0000-007F`: reset/copy bootstrap - `0000-007F`: reset/copy bootstrap
- `0080-1201`: packed BIOS+monitor image copied to RAM at `C000-D181` - `0080-12DD`: packed BIOS+monitor image copied to RAM at `C000-D25D`
- `1202-13FF`: unused space reserved for the resident image to grow - `12DE-13FF`: unused space reserved for the resident image to grow
- `1400-1C0C`: Tiny BASIC, executed directly from ROM - `1400-1C0C`: Tiny BASIC, executed directly from ROM
- `1C0D-2FFF`: unused ROM - `1C0D-2FFF`: unused ROM
- `3000-301D`: tape loader, executed directly from ROM - `3000-32A6`: tape loader, executed directly from ROM
- `301E-7FFF`: unused space available for additional ROM content - `32A7-7FFF`: unused space available for additional ROM content
The resident image starts at `C000`, its IM 2 vector table is at `C040`, and The resident image starts at `C000`, its IM 2 vector table is at `C040`, and
linked code starts at `C080`. The bootstrap obtains the resident copy length linked code starts at `C080`. The bootstrap obtains the resident copy length
@@ -103,8 +106,8 @@ The resulting RAM layout is:
- `8000-AFFF`: Tiny BASIC workspace and BASIC program text - `8000-AFFF`: Tiny BASIC workspace and BASIC program text
- `B000-B077`: Tiny BASIC variables and input buffer - `B000-B077`: Tiny BASIC variables and input buffer
- `B078-BFFF`: Tiny BASIC stack space - `B078-BFFF`: Tiny BASIC stack space
- `C000-D181`: resident BIOS, vectors, services, and monitor - `C000-D25D`: resident BIOS, vectors, services, and monitor
- `D182-EFFF`: free space for resident-image growth - `D25E-EFFF`: free space for resident-image growth
- `F000-FFFF`: BIOS globals, UART buffers, and monitor stack - `F000-FFFF`: BIOS globals, UART buffers, and monitor stack
The BIOS and monitor continue to work if low ROM is disabled. ROM-resident The BIOS and monitor continue to work if low ROM is disabled. ROM-resident
@@ -197,12 +200,14 @@ returns to the Tiny BASIC prompt.
Tiny BASIC resets the stack pointer when it starts, so it does not currently Tiny BASIC resets the stack pointer when it starts, so it does not currently
return through the monitor's `G` call. Reset the machine to return to the return through the monitor's `G` call. Reset the machine to return to the
monitor. The tape loader occupies the later ROM slot at `3000-301D`; the first monitor. The tape loader occupies the later ROM slot at `3000-32A6`; the first
unused byte after it is `301E`. unused byte after it is `32A7`.
## Tape loader ## Tape loader
The tape-loader image is built from `apps/casette/tape_loader.asm`, linked at The tape-loader image is built from `apps/casette/tape_loader.asm`, linked at
`3000`, and included in both ROM images. Start it with `T`, `TAPE`, or `G 3000`. `3000`, and included in both ROM images. Start it with `T`, `TAPE`, or `G 3000`.
The current image polls the comparator input and prints its state through the The current image polls the comparator input and prints its state through the
resident BIOS console service. resident BIOS console service. Signal acquisition is bounded; a missing,
unstable, or permanently high signal reports `TAPE SIGNAL TIMEOUT` and returns
to the monitor instead of waiting forever with interrupts disabled.
+2 -2
View File
@@ -9,8 +9,8 @@ The current allocation is:
- `1400-1C0C`: Tiny BASIC - `1400-1C0C`: Tiny BASIC
- `1C0D-2FFF`: available - `1C0D-2FFF`: available
- `3000-301D`: tape loader - `3000-32A6`: tape loader
- `301E-7FFF`: available for more applications (`3100` is the next convenient - `32A7-7FFF`: available for more applications (`3300` is the next convenient
aligned origin) aligned origin)
The resident BIOS and monitor own high RAM at `C000-FFFF`. Tiny BASIC owns The resident BIOS and monitor own high RAM at `C000-FFFF`. Tiny BASIC owns
+1 -1
View File
@@ -163,7 +163,7 @@ def main() -> None:
parser.add_argument("--low", type=float, default=2000.0, help="low tone in Hz") parser.add_argument("--low", type=float, default=2000.0, help="low tone in Hz")
parser.add_argument("--high", type=float, default=4000.0, help="high tone in Hz") parser.add_argument("--high", type=float, default=4000.0, help="high tone in Hz")
parser.add_argument("--sample-rate", type=int, default=48000) parser.add_argument("--sample-rate", type=int, default=48000)
parser.add_argument("--leader", type=float, default=1.0, help="leader seconds") parser.add_argument("--leader", type=float, default=4.0, help="leader seconds")
parser.add_argument("--preamble", type=int, default=64, help="number of 0x55 preamble bytes") parser.add_argument("--preamble", type=int, default=64, help="number of 0x55 preamble bytes")
parser.add_argument("--block-size", type=int, default=64) parser.add_argument("--block-size", type=int, default=64)
parser.add_argument("--amplitude", type=float, default=0.75) parser.add_argument("--amplitude", type=float, default=0.75)
File diff suppressed because it is too large Load Diff
+12 -1
View File
@@ -5,6 +5,8 @@
#define UART_CTC_CARD_BASE 0x20 #define UART_CTC_CARD_BASE 0x20
#define CTC_BASE (UART_CTC_CARD_BASE + 0x00) #define CTC_BASE (UART_CTC_CARD_BASE + 0x00)
#define CTC_CHANNEL_0 (CTC_BASE + 0) #define CTC_CHANNEL_0 (CTC_BASE + 0)
#define CTC_CHANNEL_1 (CTC_BASE + 1)
#define CTC_CHANNEL_2 (CTC_BASE + 2)
#define CTC_CHANNEL_3 (CTC_BASE + 3) #define CTC_CHANNEL_3 (CTC_BASE + 3)
#define UART_BASE (UART_CTC_CARD_BASE + 0x04) #define UART_BASE (UART_CTC_CARD_BASE + 0x04)
#define UART_CONTROL (UART_BASE + 0) #define UART_CONTROL (UART_BASE + 0)
@@ -76,6 +78,16 @@ void bios_init(void)
buffer_init(&rx_buf); buffer_init(&rx_buf);
buffer_init(&tx_buf); buffer_init(&tx_buf);
/* A CPU-only reset does not necessarily reset the external CTC. Stop and
disable every channel before rebuilding the UART clock/IRQ path. */
io_out(CTC_CHANNEL_0, 0x03);
io_out(CTC_CHANNEL_1, 0x03);
io_out(CTC_CHANNEL_2, 0x03);
io_out(CTC_CHANNEL_3, 0x03);
/* The 6850 has no reset input; CR1:CR0 = 11 is its master reset. */
io_out(UART_CONTROL, 0b00000011);
io_out(CTC_CHANNEL_0, 0x57); io_out(CTC_CHANNEL_0, 0x57);
io_out(CTC_CHANNEL_0, 13); io_out(CTC_CHANNEL_0, 13);
io_out(CTC_CHANNEL_3, 0b11001111); io_out(CTC_CHANNEL_3, 0b11001111);
@@ -84,7 +96,6 @@ void bios_init(void)
io_out(CTC_CHANNEL_0, 0x40); io_out(CTC_CHANNEL_0, 0x40);
uart_tx_busy = 0; uart_tx_busy = 0;
io_out(UART_CONTROL, 0b00000011);
io_out(UART_CONTROL, 0b10010101); io_out(UART_CONTROL, 0b10010101);
enable_interrupts(); enable_interrupts();
} }
+12
View File
@@ -113,6 +113,15 @@ init:
di di
ld sp, #STACK_TOP ld sp, #STACK_TOP
; A reset may have interrupted a CTC service routine without executing
; RETI. Release any stale daisy-chain in-service latches before the
; channels are reinitialized. RETI acts as RET for each CALL while
; also signalling end-of-interrupt to daisy-chained peripherals.
call release_daisy_chain
call release_daisy_chain
call release_daisy_chain
call release_daisy_chain
call gsinit call gsinit
; Setup interrupt mode 2 ; Setup interrupt mode 2
@@ -125,6 +134,9 @@ init:
hang: hang:
jr hang jr hang
release_daisy_chain:
reti
.area _GSINIT .area _GSINIT
gsinit: gsinit:
ld bc, #l__INITIALIZER ld bc, #l__INITIALIZER
+9
View File
@@ -131,6 +131,15 @@ static void command_dump(uint8_t argc, char **argv)
print_hex8(*(volatile uint8_t *)(address + offset + column)); print_hex8(*(volatile uint8_t *)(address + offset + column));
bios_putc(' '); bios_putc(' ');
} }
for (; column < 16; ++column) {
bios_puts(" ");
}
bios_putc('|');
for (column = 0; column < row_length; ++column) {
uint8_t value = *(volatile uint8_t *)(address + offset + column);
bios_putc(value >= ' ' && value <= '~' ? (char)value : '.');
}
bios_putc('|');
bios_puts("\r\n"); bios_puts("\r\n");
offset += row_length; offset += row_length;
} }
BIN
View File
Binary file not shown.