From f2ac7b405786f6bc047dfda7b45c139d194ba032 Mon Sep 17 00:00:00 2001 From: Maxwell Beck Date: Sun, 20 Jul 2025 20:23:03 -0500 Subject: feat: Disk swapping --- CMakeLists.txt | 2 +- src/6502.c | 4 +- src/6522.c | 10 +-- src/drive.c | 17 +++-- src/drive.h | 2 +- src/ff/ffconf.h | 4 +- src/pico1541.c | 195 +++++++++++++++++++++++++++++++++++--------------------- 7 files changed, 147 insertions(+), 87 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4963841..195534f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ add_executable(pico1541 src/pico1541.c src/6502.c src/6522.c src/drive.c src/usb_descriptors.c src/ff/ff.c ) -pico_set_binary_type(pico1541 copy_to_ram) +# pico_set_binary_type(pico1541 copy_to_ram) target_include_directories(pico1541 PRIVATE src) target_link_libraries(pico1541 pico_runtime pico_multicore hardware_timer hardware_flash hardware_irq tinyusb_device tinyusb_board pico_stdlib) pico_add_extra_outputs(pico1541) diff --git a/src/6502.c b/src/6502.c index 09f0a04..0ed0773 100644 --- a/src/6502.c +++ b/src/6502.c @@ -1,3 +1,5 @@ +#include + #include "6502.h" #define STACK_PUSH(v) \ @@ -529,7 +531,7 @@ void cpu_reset(cpu_t *cpu) { FETCH_PC(0xfffc); } -uint8_t cpu_step(cpu_t *cpu) { +uint8_t __not_in_flash_func(cpu_step)(cpu_t *cpu) { uint8_t cycles = 0; if (cpu->jammed) { return cycles; diff --git a/src/6522.c b/src/6522.c index 89bc102..76c8872 100644 --- a/src/6522.c +++ b/src/6522.c @@ -1,3 +1,5 @@ +#include + #include "6522.h" void via_init(via_t *via) { @@ -20,7 +22,7 @@ void via_init(via_t *via) { via->tbv = true; } -void via_read(via_t *via, uint8_t addr, uint8_t *v, uint8_t cycle) { +void __not_in_flash_func(via_read)(via_t *via, uint8_t addr, uint8_t *v, uint8_t cycle) { uint16_t tca = via->tca - cycle; uint16_t tcb = via->tcb - cycle; @@ -81,7 +83,7 @@ void via_read(via_t *via, uint8_t addr, uint8_t *v, uint8_t cycle) { } } -void via_write(via_t *via, uint8_t addr, uint8_t v, uint8_t cycle) { +void __not_in_flash_func(via_write)(via_t *via, uint8_t addr, uint8_t v, uint8_t cycle) { switch (addr) { case 0: via->orb = v; @@ -153,7 +155,7 @@ void via_write(via_t *via, uint8_t addr, uint8_t v, uint8_t cycle) { } } -void via_cycle(via_t *via, uint8_t cycles) { +void __not_in_flash_func(via_cycle)(via_t *via, uint8_t cycles) { if (!via->tav) { uint16_t tca = via->tca - cycles; @@ -182,6 +184,6 @@ void via_cycle(via_t *via, uint8_t cycles) { via->tcb = tcb; } -bool via_irq(via_t *via) { +bool __not_in_flash_func(via_irq)(via_t *via) { return (via->ifr & via->ier) > 0; } diff --git a/src/drive.c b/src/drive.c index 9193608..8c06e69 100644 --- a/src/drive.c +++ b/src/drive.c @@ -1,7 +1,8 @@ -#include "drive.h" - +#include #include +#include "drive.h" + const uint8_t SECTORS_PER_TRACK[35] = { 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 19, 19, 19, 19, 19, 19, 19, @@ -46,7 +47,7 @@ void drive_init(drive_t *drive) { drive_cycle(drive); } -void drive_step_up(drive_t *drive) { +void __not_in_flash_func(drive_step_up)(drive_t *drive) { drive->halftrack = (drive->halftrack + 1) & 1; if (drive->track < 34 && drive->halftrack == 0) { drive->image_ptr += SECTORS_PER_TRACK[drive->track] << 8; @@ -55,7 +56,7 @@ void drive_step_up(drive_t *drive) { } } -void drive_step_down(drive_t *drive) { +void __not_in_flash_func(drive_step_down)(drive_t *drive) { drive->halftrack = (drive->halftrack + 1) & 1; if (drive->track > 0 && drive->halftrack == 0) { drive->image_ptr -= SECTORS_PER_TRACK[drive->track - 1] << 8; @@ -64,7 +65,7 @@ void drive_step_down(drive_t *drive) { } } -bool drive_advance(drive_t *drive, uint8_t cycles) { +bool __not_in_flash_func(drive_advance)(drive_t *drive, uint8_t cycles) { bool byte_ready = false; for (uint8_t i = 0; i < cycles; i++) { @@ -76,7 +77,7 @@ bool drive_advance(drive_t *drive, uint8_t cycles) { return byte_ready; } -void drive_cycle(drive_t *drive) { +void __not_in_flash_func(drive_cycle)(drive_t *drive) { while (drive->lookahead_idx != ((drive->current_idx - 1) & (DRIVE_LOOKAHEAD - 1))) { uint8_t j = (drive->lookahead_idx + 1) & (DRIVE_LOOKAHEAD - 1); uint16_t timer_next = drive->timer + BITRATES[drive->bitrate]; @@ -170,7 +171,9 @@ void drive_cycle(drive_t *drive) { drive->unlatched[j] = ((prev << 1) | ((drive->gcr_word & 0x200) >> 9)) & 0x3ff; drive->gcr_word <<= 1; - drive->gcr_bits--; + if (drive->gcr_bits > 0) { + drive->gcr_bits--; + } drive->bit_counter += 1; } else { drive->unlatched[j] = prev; diff --git a/src/drive.h b/src/drive.h index a555f15..7d1daae 100644 --- a/src/drive.h +++ b/src/drive.h @@ -13,7 +13,7 @@ extern const uint8_t GCR_CONV[16]; typedef struct drive_s { volatile bool spinning; uint16_t timer; - uint8_t *image; + volatile uint8_t *volatile image; volatile uint8_t track; volatile uint8_t halftrack; diff --git a/src/ff/ffconf.h b/src/ff/ffconf.h index c8370e6..c9c96e1 100644 --- a/src/ff/ffconf.h +++ b/src/ff/ffconf.h @@ -15,7 +15,7 @@ / and optional writing functions as well. */ -#define FF_FS_MINIMIZE 3 +#define FF_FS_MINIMIZE 1 /* This option defines minimization level to remove some basic API functions. / / 0: Basic functions are fully enabled. @@ -25,7 +25,7 @@ / 3: f_lseek() function is removed in addition to 2. */ -#define FF_USE_FIND 0 +#define FF_USE_FIND 1 /* This option switches filtered directory read functions, f_findfirst() and / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ diff --git a/src/pico1541.c b/src/pico1541.c index 3bf52a8..cb0473b 100644 --- a/src/pico1541.c +++ b/src/pico1541.c @@ -1,4 +1,3 @@ -#include #include #include @@ -9,6 +8,7 @@ #include #include +#include #include #include "ff/ff.h" @@ -22,28 +22,32 @@ const uint32_t GPIO_CLK = 2; const uint32_t GPIO_DATA = 3; const uint32_t GPIO_DATA2 = 5; const uint32_t GPIO_ATN = 4; +const uint32_t GPIO_SWAP = 6; const uint32_t GPIO_LED = 25; const uint8_t DEVICE = 8; #define FS_BYTES 1572864 +#define MAX_DISKS 16 static uint8_t __in_flash("fs") __attribute__((aligned(4096))) FS[FS_BYTES]; static FATFS FAT_FS; +static uint8_t n_disks; +static FILINFO disks[MAX_DISKS]; static uint8_t ram[2048]; -static uint8_t dos1541[16384]; -static uint8_t disk[174848]; +static volatile uint8_t dos1541[16384]; +static volatile uint8_t disk[174848]; -uint32_t ts; -cpu_t cpu; +static uint32_t ts; +static cpu_t cpu; static via_t via1; static via_t via2; -drive_t drive; +static drive_t drive; -int8_t track_step; +static int8_t track_step; -void via_pa_read(via_t *via, uint8_t cycle) { +void __not_in_flash_func(via_pa_read)(via_t *via, uint8_t cycle) { if (via == &via2) { via->ira = drive.latched[(drive.current_idx + cycle) & (DRIVE_LOOKAHEAD - 1)]; } else { @@ -51,7 +55,7 @@ void via_pa_read(via_t *via, uint8_t cycle) { } } -void via_pb_read(via_t *via, uint8_t cycle) { +void __not_in_flash_func(via_pb_read)(via_t *via, uint8_t cycle) { if (via == &via1) { while (ts + cycle > time_us_32()) {} uint8_t clk = gpio_get(GPIO_CLK) ? 0 : 0b00000100; @@ -69,10 +73,10 @@ void via_pb_read(via_t *via, uint8_t cycle) { } } -void via_pa_write(via_t *via, uint8_t cycle) { +void __not_in_flash_func(via_pa_write)(via_t *via, uint8_t cycle) { } -void via_pb_write(via_t *via, uint8_t cycle) { +void __not_in_flash_func(via_pb_write)(via_t *via, uint8_t cycle) { if (via == &via1) { while (ts + cycle > time_us_32()) {} gpio_set_dir(GPIO_CLK, (via->orb & 0b00001000) > 0 && (via->ddrb & 0b00001000) > 0); @@ -102,7 +106,7 @@ void via_pb_write(via_t *via, uint8_t cycle) { } } -uint8_t bus_read(uint16_t addr, uint8_t cycle) { +uint8_t __not_in_flash_func(bus_read)(uint16_t addr, uint8_t cycle) { if (addr < 2048) { return ram[addr]; } else if (addr >= 0xc000) { @@ -120,7 +124,7 @@ uint8_t bus_read(uint16_t addr, uint8_t cycle) { } } -void bus_write(uint16_t addr, uint8_t v, uint8_t cycle) { +void __not_in_flash_func(bus_write)(uint16_t addr, uint8_t v, uint8_t cycle) { if (addr < 2048) { ram[addr] = v; } else if (addr >= 0x1800 && addr < 0x1810) { @@ -130,7 +134,7 @@ void bus_write(uint16_t addr, uint8_t v, uint8_t cycle) { } } -void atn_irq_callback(uint pin, uint32_t flags) { +void __not_in_flash_func(atn_irq_callback)(uint pin, uint32_t flags) { if (flags & GPIO_IRQ_EDGE_RISE) { if (!(via1.pcr & 1)) { via1.ifr |= 0b10000010; @@ -274,79 +278,125 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) { return RES_PARERR; } -void drive_irq() { - multicore_fifo_pop_blocking(); - drive_cycle(&drive); +int file_cmp(const void *lhs, const void *rhs) { + return strcmp(((FILINFO *)lhs)->fname, ((FILINFO *)rhs)->fname); +} + +void __not_in_flash_func(drive_irq)() { + while (multicore_fifo_rvalid()) { + multicore_fifo_pop_blocking(); + drive_cycle(&drive); + } + multicore_fifo_clear_irq(); } void drive_thread() { drive_init(&drive); - drive.image = disk; - irq_set_exclusive_handler(SIO_IRQ_PROC1, drive_irq); - irq_set_priority(SIO_IRQ_PROC1, 0); - irq_set_enabled(SIO_IRQ_PROC1, true); + multicore_fifo_clear_irq(); + irq_set_exclusive_handler(SIO_FIFO_IRQ_NUM(1), drive_irq); + irq_set_priority(SIO_FIFO_IRQ_NUM(1), 0); + irq_set_enabled(SIO_FIFO_IRQ_NUM(1), true); - multicore_fifo_push_blocking(1); -} - -int main() { - board_init(); - tud_init(BOARD_TUD_RHPORT); - if (board_init_after_tusb) { - board_init_after_tusb(); - } - - while (!ejected) { - tud_task(); - } - tud_disconnect(); - f_mount(&FAT_FS, "0:", 0); FIL file; FRESULT res; uint32_t btr; uint32_t br; + uint8_t fread_buf[4096]; res = f_open(&file, "0:dos1541.bin", FA_READ); - if (res) { - return 0; - } - btr = 16384; - br = 0; - while (btr > 0) { - UINT brr; - if (btr < 4096) { - f_read(&file, dos1541 + br, btr, &brr); - } else { - f_read(&file, dos1541 + br, 4096, &brr); + if (!res) { + btr = 16384; + br = 0; + while (btr > 0) { + UINT brr; + if (btr < 4096) { + f_read(&file, fread_buf, btr, &brr); + } else { + f_read(&file, fread_buf, 4096, &brr); + } + for (uint32_t i = 0; i < brr; i++) { + dos1541[br + i] = fread_buf[i]; + } + br += brr; + btr -= brr; } - br += brr; - btr -= brr; + f_close(&file); } - f_close(&file); - res = f_open(&file, "0:image.d64", FA_READ); - if (res) { - return 0; + n_disks = 0; + DIR d; + res = f_findfirst(&d, &disks[0], "0:", "*.d64"); + while ( + !res + && disks[n_disks].fname[0] + && n_disks < MAX_DISKS - 1 + ) { + if (disks[n_disks].fsize == 174848) { + n_disks++; + } + res = f_findnext(&d, &disks[n_disks]); } - btr = 174848; - br = 0; - while (btr > 0) { - UINT brr; - if (btr < 4096) { - f_read(&file, disk + br, btr, &brr); - } else { - f_read(&file, disk + br, 4096, &brr); + f_closedir(&d); + + qsort(disks, n_disks, sizeof(FILINFO), file_cmp); + + multicore_fifo_push_blocking(1); + + uint8_t cur_disk = 0; + while (true) { + drive.image = NULL; + + if (n_disks > 0) { + char im_path[16]; + sprintf(im_path, "0:%s", disks[cur_disk].fname); + + res = f_open(&file, im_path, FA_READ); + if (!res) { + btr = 174848; + br = 0; + while (btr > 0) { + UINT brr; + if (btr < 4096) { + f_read(&file, fread_buf, btr, &brr); + } else { + f_read(&file, fread_buf, 4096, &brr); + } + for (uint32_t i = 0; i < brr; i++) { + disk[br + i] = fread_buf[i]; + } + br += brr; + btr -= brr; + } + f_close(&file); + } + + drive.image = disk; + } + + while (gpio_get(GPIO_SWAP)) {} + + cur_disk++; + if (cur_disk >= MAX_DISKS) { + cur_disk = 0; } - br += brr; - btr -= brr; } - f_close(&file); +} + +int __not_in_flash_func(main)() { + board_init(); + tud_init(BOARD_TUD_RHPORT); + if (board_init_after_tusb) { + board_init_after_tusb(); + } - f_unmount("0:"); + while (!ejected) { + tud_task(); + } + tud_disconnect(); set_sys_clock_khz(250000, true); multicore_launch_core1(drive_thread); @@ -355,7 +405,8 @@ int main() { gpio_init(GPIO_DATA); gpio_init(GPIO_ATN); gpio_init(GPIO_DATA2); - gpio_init(25); + gpio_init(GPIO_SWAP); + gpio_init(GPIO_LED); gpio_put(GPIO_CLK, 0); gpio_put(GPIO_DATA, 0); @@ -366,12 +417,14 @@ int main() { gpio_set_dir(GPIO_DATA, GPIO_IN); gpio_set_dir(GPIO_ATN, GPIO_IN); gpio_set_dir(GPIO_LED, GPIO_OUT); + gpio_set_dir(GPIO_SWAP, GPIO_IN); gpio_set_dir(GPIO_DATA2, GPIO_IN); gpio_set_pulls(GPIO_CLK, true, false); gpio_set_pulls(GPIO_DATA, true, false); gpio_set_pulls(GPIO_DATA2, true, false); gpio_set_pulls(GPIO_ATN, true, false); + gpio_set_pulls(GPIO_SWAP, true, false); gpio_set_irq_enabled_with_callback(GPIO_ATN, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &atn_irq_callback); @@ -383,25 +436,25 @@ int main() { via_init(&via2); ts = time_us_32(); - uint16_t osc2 = 0xffff; while (!cpu.jammed) { if (ts + 100 < time_us_32()) { break; } uint8_t cycles = cpu_step(&cpu); + via_cycle(&via1, cycles); + via_cycle(&via2, cycles); + cpu.irq = via_irq(&via1) | via_irq(&via2); + if (drive_advance(&drive, cycles) && (via2.pcr & 0b1110) == 0b1110) { cpu.flags |= 1 << FLAG_V_BIT; } multicore_fifo_push_blocking_inline(1); - via_cycle(&via1, cycles); - via_cycle(&via2, cycles); - cpu.irq = via_irq(&via1) | via_irq(&via2); - ts += cycles; while (ts > time_us_32()) {} } + return 0; } -- cgit 1.4.1