diff --git a/pico/mac/CMakeLists.txt b/pico/mac/CMakeLists.txt index e82d8a2f3..3ec818bd2 100644 --- a/pico/mac/CMakeLists.txt +++ b/pico/mac/CMakeLists.txt @@ -31,9 +31,7 @@ pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/commands.pio) pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/echo.pio) pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/latch.pio) pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/mux.pio) -pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/dcd_latch.pio) pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/dcd_commands.pio) -pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/dcd_mux.pio) pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/dcd_read.pio) pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/dcd_write.pio) # however, alternatively you can choose to generate it somewhere else (in this case in the source tree for check in) @@ -41,7 +39,7 @@ pico_generate_pio_header(commands ${CMAKE_CURRENT_LIST_DIR}/dcd_write.pio) # target_sources(pio_and PRIVATE pio_and.c) -target_link_libraries(commands pico_stdlib hardware_pio) +target_link_libraries(commands pico_stdlib hardware_pio hardware_dma) # Add the standard include files to the build target_include_directories(commands PRIVATE diff --git a/pico/mac/commands.c b/pico/mac/commands.c index 1ead5fa02..c226c68c9 100644 --- a/pico/mac/commands.c +++ b/pico/mac/commands.c @@ -15,6 +15,7 @@ #include "hardware/uart.h" #include "hardware/clocks.h" #include "hardware/claim.h" +#include "hardware/dma.h" #include "hardware/pio.h" #include "hardware/pio_instructions.h" @@ -26,22 +27,21 @@ #include "latch.pio.h" #include "mux.pio.h" -// #include "dcd_latch.pio.h" #include "dcd_commands.pio.h" -#include "dcd_mux.pio.h" #include "dcd_read.pio.h" #include "dcd_write.pio.h" // define GPIO pins #define UART_TX_PIN 4 #define UART_RX_PIN 5 -#define ENABLE 7 -#define MCI_CA0 8 -#define MCI_WR 14 -#define ECHO_IN 21 -#define TACH_OUT 21 -#define ECHO_OUT 18 -#define LATCH_OUT 20 +#define ENABLE 7 +#define MCI_CA0 8 +#define MCI_WR 15 +#define ECHO_IN 21 +#define TACH_OUT 21 +#define ECHO_OUT 18 +#define MUX_OUT 18 +#define LATCH_OUT 20 /** * HERE STARTS PIO DEFINITIONS AND HEADERS @@ -66,12 +66,10 @@ uint pio_dcd_cmd_offset; void pio_commands(PIO pio, uint sm, uint offset, uint pin); void pio_echo(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin, uint num_pins); -void pio_latch(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin); +// void pio_latch(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin); void pio_mux(PIO pio, uint sm, uint offset, uint in_pin, uint mux_pin); -// void pio_dcd_latch(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin); void pio_dcd_commands(PIO pio, uint sm, uint offset, uint pin); -void pio_dcd_mux(PIO pio, uint sm, uint offset, uint pin); void pio_dcd_read(PIO pio, uint sm, uint offset, uint pin); void pio_dcd_write(PIO pio, uint sm, uint offset, uint pin); void set_num_dcd(); @@ -178,40 +176,55 @@ enum latch_bits { REVISED // f REVISED This status line is used to indicate that the interface definition of the connected external drive. When REVISED is a one, the drive Part No. will be 699-0326 or when REVISED is a zero, the drive Part No. will be 699-0285. }; -uint16_t latch; -uint8_t dcd_latch; +__aligned(32) bool latch_lut[24]; -inline uint16_t get_latch() { return latch; } -inline uint16_t dcd_get_latch() { return ((dcd_latch << 8) + dcd_latch); } - -void set_latch(enum latch_bits s) { latch |= (1u << s); } +uint16_t get_latch() +{ + int latch = 0; + for (int i=0; i<16; i++) + latch |= ((int)latch_lut[i] << i); + return (uint16_t)(latch & 0xffff); +} -void dcd_set_latch(uint8_t s) { dcd_latch |= (1u << s); } +uint8_t dcd_get_latch() +{ + int latch = 0; + for (int i=0; i<8; i++) + latch |= ((int)latch_lut[16 + i] << i); + return (uint8_t)(latch & 0xff); +} -void clr_latch(enum latch_bits c) { latch &= ~(1u << c); } +void set_latch(enum latch_bits s) { latch_lut[s] = true; } +void clr_latch(enum latch_bits c) { latch_lut[c] = false; } +bool latch_val(enum latch_bits s) { return latch_lut[s]; } -void dcd_clr_latch(uint8_t c) { dcd_latch &= ~(1u << c); } +void dcd_set_latch(uint8_t s) { latch_lut[16 + s] = true; } +void dcd_clr_latch(uint8_t c) { latch_lut[16 + c] = false; } -bool latch_val(enum latch_bits s) { return latch & (1u << s); } void dcd_assert_hshk() { // State CA2 CA1 CA0 HOST HOFF RESET RD Function dcd_clr_latch(2); // 2 Low High Low Low Low Low !HSHK dcd_clr_latch(3); // 3 Low High High High Low Low !HSHK - pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO + // pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO } void dcd_deassert_hshk() { // State CA2 CA1 CA0 HOST HOFF RESET RD Function dcd_set_latch(2); // 2 Low High Low Low Low Low !HSHK dcd_set_latch(3); // 3 Low High High High Low Low !HSHK - pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO + // pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO } void preset_latch() { + for (int i = 0; i < 16; i++) + { + // latch_lut[i] = true; + set_latch(i); + } // set up like an empty floppy - latch =-1; + // latch =-1; // clr_latch(DIRTN); // set_latch(STEP); // set_latch(MOTORON); @@ -226,11 +239,12 @@ void preset_latch() // set_latch(REVISED); // my mac plus revised looks set // for (int i=0; i<16; i++) // printf("\nlatch bit %02d = %d",i, latch_val(i)); + printf("\nFloppy Latch: %04x", get_latch()); } void dcd_preset_latch() { - dcd_latch = 0; + // dcd_latch = 0; // State CA2 CA1 CA0 HOST HOFF RESET RD Function dcd_clr_latch(0); // 0 Low Low Low High High Low Data dcd_clr_latch(1); // 1 Low Low High High Low Low Data @@ -240,6 +254,7 @@ void dcd_preset_latch() dcd_clr_latch(5); // 5 High Low High Low Low Low Drive Low dcd_set_latch(6); // 6 High High Low Low Low Low Drive High dcd_set_latch(7); // 7 High High High Low Low Low Drive High + printf("\nDCD Latch: %02x", dcd_get_latch()); } void set_tach_freq(char c) @@ -265,42 +280,17 @@ void set_tach_freq(char c) void switch_to_floppy() { - // latch - pio_sm_put_blocking(pioblk_rw, SM_LATCH, get_latch()); // send the register word to the PIO - - // mux - pio_remove_program(pioblk_rw, &dcd_mux_program, pio_mux_offset); - pio_add_program_at_offset(pioblk_rw, &mux_program, pio_mux_offset); - pio_mux(pioblk_rw, SM_MUX, pio_mux_offset, MCI_CA0, ECHO_OUT); - // commands while (gpio_get(LSTRB)); pio_sm_set_enabled(pioblk_read_only, SM_DCD_CMD, false); // stop the DCD command interpreter pio_commands(pioblk_read_only, SM_FPY_CMD, pio_floppy_cmd_offset, MCI_CA0); // read phases starting on pin 8 - - // echo - // pio_sm_set_enabled(pioblk_rw, SM_FPY_ECHO, true); - } void switch_to_dcd() { - // latch - pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO - // commands pio_sm_set_enabled(pioblk_read_only, SM_FPY_CMD, false); // stop the floppy command interpreter pio_dcd_commands(pioblk_read_only, SM_DCD_CMD, pio_dcd_cmd_offset, MCI_CA0); // read phases starting on pin 8 - - // mux - pio_remove_program(pioblk_rw, &mux_program, pio_mux_offset); - pio_add_program_at_offset(pioblk_rw, &dcd_mux_program, pio_mux_offset); - pio_dcd_mux(pioblk_rw, SM_MUX, pio_mux_offset, LATCH_OUT); - set_num_dcd(); - - // echo - // pio_sm_set_enabled(pioblk_rw, SM_FPY_ECHO, false); - } void set_num_dcd() @@ -309,11 +299,14 @@ void set_num_dcd() // pause the machine, change the instruction, move the PC, resume pio_sm_set_enabled(pioblk_rw, SM_MUX, false); uint32_t save = hw_claim_lock(); - pioblk_rw->instr_mem[pio_mux_offset] = pio_encode_set(pio_x, num_dcd_drives) | pio_encode_sideset_opt(1, 0); + pioblk_rw->instr_mem[pio_mux_offset] = pio_encode_set(pio_x, num_dcd_drives) | pio_encode_sideset_opt(3, 0); hw_claim_unlock(save); - pio_dcd_mux(pioblk_rw, SM_MUX, pio_mux_offset, LATCH_OUT); + pio_mux(pioblk_rw, SM_MUX, pio_mux_offset, MCI_CA0, MUX_OUT); } +int chan_latch_addr, chan_latch_data; +dma_channel_config cfg_latch_addr, cfg_latch_data; + void setup() { uint offset; @@ -357,8 +350,50 @@ void setup() */ offset = pio_add_program(pioblk_rw, &latch_program); printf("\nLoaded latch program at %d\n", offset); - pio_latch(pioblk_rw, SM_LATCH, offset, MCI_CA0, LATCH_OUT); - pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO + latch_program_init(pioblk_rw, SM_LATCH, offset, MCI_CA0, LATCH_OUT); + pio_sm_put(pioblk_rw, SM_LATCH, (uintptr_t)latch_lut >> 5); + pio_sm_exec_wait_blocking(pioblk_rw, SM_LATCH, pio_encode_pull(false, true)); + pio_sm_exec_wait_blocking(pioblk_rw, SM_LATCH, pio_encode_mov(pio_y, pio_osr)); + pio_sm_exec_wait_blocking(pioblk_rw, SM_LATCH, pio_encode_out(pio_null, 1)); + pio_sm_set_enabled(pioblk_rw, SM_LATCH, true); + + chan_latch_addr = dma_claim_unused_channel(true); + cfg_latch_addr = dma_channel_get_default_config(chan_latch_addr); + + chan_latch_data = dma_claim_unused_channel(true); + cfg_latch_data = dma_channel_get_default_config(chan_latch_data); + + channel_config_set_read_increment(&cfg_latch_data,false); + channel_config_set_write_increment(&cfg_latch_data,false); + channel_config_set_dreq(&cfg_latch_data, pio_get_dreq(pioblk_rw, SM_LATCH, true)); // mux PIO + channel_config_set_chain_to(&cfg_latch_data, chan_latch_addr); + channel_config_set_transfer_data_size(&cfg_latch_data, DMA_SIZE_8); + channel_config_set_irq_quiet(&cfg_latch_data, true); + channel_config_set_enable(&cfg_latch_data, true); + dma_channel_configure( + chan_latch_data, // Channel to be configured + &cfg_latch_data, // The configuration we just created + &pioblk_rw->txf[SM_LATCH], // The initial write address + latch_lut, // The initial read address + 1, // Number of transfers; in this case each is 1 byte. + false // do not Start immediately. + ); + + channel_config_set_read_increment(&cfg_latch_addr,false); + channel_config_set_write_increment(&cfg_latch_addr,false); + channel_config_set_dreq(&cfg_latch_addr, pio_get_dreq(pioblk_rw, SM_LATCH, false)); // mux PIO + channel_config_set_chain_to(&cfg_latch_addr, chan_latch_data); + channel_config_set_transfer_data_size(&cfg_latch_addr, DMA_SIZE_32); + channel_config_set_irq_quiet(&cfg_latch_addr, true); + channel_config_set_enable(&cfg_latch_addr, true); + dma_channel_configure( + chan_latch_addr, // Channel to be configured + &cfg_latch_addr, // The configuration we just created + &dma_channel_hw_addr(chan_latch_data)->read_addr, // The initial write address + &pioblk_rw->rxf[SM_LATCH], // The initial read address + 1, // Number of transfers; in this case each is 1 byte. + true // do not Start immediately. + ); offset = pio_add_program(pioblk_rw, &echo_program); printf("Loaded floppy echo program at %d\n", offset); @@ -368,36 +403,9 @@ void setup() printf("Loaded DCD write program at %d\n", pio_write_offset); pio_dcd_write(pioblk_rw, SM_DCD_WRITE, pio_write_offset, LATCH_OUT); - pio_mux_offset = pio_add_program(pioblk_rw, &dcd_mux_program); - printf("Loaded DCD mux program at %d\n", pio_mux_offset); - pio_dcd_mux(pioblk_rw, SM_MUX, pio_mux_offset, LATCH_OUT); - - // pio_mux_offset = pio_add_program(pioblk_rw, &mux_program); - // printf("Loaded Floppy mux program at %d\n", pio_mux_offset); - // pio_mux(pioblk_rw, SM_MUX, pio_mux_offset, MCI_CA0, ECHO_OUT); - -#ifdef FLOPPY - set_tach_freq(0); // start TACH clock - preset_latch(); - - offset = pio_add_program(pio_floppy, &commands_program); - printf("\nLoaded cmd program at %d\n", offset); - pio_commands(pio_floppy, SM_FPY_CMD, offset, MCI_CA0); // read phases starting on pin 8 - - offset = pio_add_program(pio_floppy, &echo_program); - printf("Loaded echo program at %d\n", offset); - pio_echo(pio_floppy, SM_FPY_ECHO, offset, ECHO_IN, ECHO_OUT, 2); - - offset = pio_add_program(pio_floppy, &latch_program); - printf("Loaded latch program at %d\n", offset); - pio_latch(pio_floppy, SM_LATCH, offset, MCI_CA0, LATCH_OUT); - pio_sm_put_blocking(pio_floppy, SM_LATCH, get_latch()); // send the register word to the PIO - - offset = pio_add_program(pio_floppy, &mux_program); - printf("Loaded mux program at %d\n", offset); - pio_mux(pio_floppy, SM_MUX, offset, MCI_CA0, ECHO_OUT); - -#endif // FLOPPY + pio_mux_offset = pio_add_program(pioblk_rw, &mux_program); + printf("Loaded mux program at %d\n", pio_mux_offset); + pio_mux(pioblk_rw, SM_MUX, pio_mux_offset, MCI_CA0, MUX_OUT); } void dcd_loop(); @@ -450,8 +458,7 @@ void esp_loop() case 'h': // harddisk is mounted/unmounted num_dcd_drives = uart_getc(UART_ID); printf("\nNumber of DCD's mounted: %d", num_dcd_drives); - if (disk_mode == DCD) - set_num_dcd(); + set_num_dcd(); // tell SM_MUX how many DCD's and restart it c = 0; // need to clear c so not picked up by floppy loop although it would never respond to 'h' break; case 's': @@ -480,7 +487,6 @@ void floppy_loop() if (gpio_get(ENABLE) && (num_dcd_drives > 0)) { - pio_sm_put_blocking(pioblk_rw, SM_LATCH, dcd_get_latch()); // send the register word to the PIO disk_mode = TO_DCD; return; } @@ -546,7 +552,6 @@ void floppy_loop() printf("\nUNKNOWN PHASE COMMAND"); break; } - pio_sm_put_blocking(pioblk_rw, SM_LATCH, get_latch()); // send the register word to the PIO uart_putc_raw(UART_ID, (char)(a + '0')); } @@ -600,7 +605,6 @@ void floppy_loop() break; } // printf("latch %04x", get_latch()); - pio_sm_put_blocking(pioblk_rw, SM_LATCH, get_latch()); // send the register word to the PIO c = 0; // clear c because processed it and don't want infinite loop } // to do: read both enable lines and indicate which drive is active when sending single char to esp32 @@ -638,7 +642,7 @@ void dcd_loop() else { // if (!latch_val(CSTIN)) - pio_sm_put_blocking(pioblk_rw, SM_LATCH, latch); // send the register word to the PIO + // pio_sm_put_blocking(pioblk_rw, SM_LATCH, get_latch()); // send the register word to the PIO disk_mode = TO_FPY; return; } @@ -689,7 +693,7 @@ void dcd_loop() dcd_deassert_hshk(); pio_sm_set_enabled(pioblk_rw, SM_DCD_WRITE, false); pio_sm_set_enabled(pioblk_rw, SM_LATCH, true); - pio_sm_exec(pioblk_rw, SM_MUX, pio_encode_set(pio_pindirs, 0)); + pio_sm_exec(pioblk_rw, SM_MUX, pio_encode_set(pio_pindirs, 0)); // to do - does this do anything because out pins not set? break; default: host = false; @@ -1238,11 +1242,6 @@ void pio_echo(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin, uint num pio_sm_set_enabled(pio, sm, true); } -void pio_latch(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin) -{ - latch_program_init(pio, sm, offset, in_pin, out_pin); - pio_sm_set_enabled(pio, sm, true); -} void pio_mux(PIO pio, uint sm, uint offset, uint in_pin, uint mux_pin) { @@ -1250,24 +1249,12 @@ void pio_mux(PIO pio, uint sm, uint offset, uint in_pin, uint mux_pin) pio_sm_set_enabled(pio, sm, true); } -// void pio_dcd_latch(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin) -// { -// latch_program_init(pio, sm, offset, in_pin, out_pin); -// pio_sm_set_enabled(pio, sm, true); -// } - void pio_dcd_commands(PIO pio, uint sm, uint offset, uint pin) { dcd_commands_program_init(pio, sm, offset, pin); pio_sm_set_enabled(pio, sm, true); } -void pio_dcd_mux(PIO pio, uint sm, uint offset, uint pin) -{ - dcd_mux_program_init(pio, sm, offset, pin); - pio_sm_set_enabled(pio, sm, true); -} - void pio_dcd_read(PIO pio, uint sm, uint offset, uint pin) { dcd_read_program_init(pio, sm, offset, pin); diff --git a/pico/mac/commands.pio b/pico/mac/commands.pio index 49eea5bda..caeb0bbee 100644 --- a/pico/mac/commands.pio +++ b/pico/mac/commands.pio @@ -5,7 +5,7 @@ ; sends the phases to the PICO when the strobe sets ; -.define public LSTRB 12 +.define public LSTRB 13 .define ENABLE 7 .program commands diff --git a/pico/mac/dcd_latch.pio b/pico/mac/dcd_latch.pio deleted file mode 100644 index 28e16e54b..000000000 --- a/pico/mac/dcd_latch.pio +++ /dev/null @@ -1,46 +0,0 @@ -; -; FujiNet Project -; -; Vintage Macintosh Microfloppy Controller Interface -; Reads the drive phases and output a dcd_latch bit -; - -.define ENABLE 7 -.define LSTRB 12 - -.program dcd_latch -start: - wait 0 gpio ENABLE - mov osr, pins ; read the GPIO's into the output shift register - out y, 3 ; shift the 3 LSBs into Y - pull noblock ; get the dcd_latch word into OSR, if no new word in FIFO, get it from X - mov x, osr ; put the osr back into X in case it's new -.wrap_target - jmp y-- loop ; if y>0 goto to loop and decrement y - out pins, 1 ; output the desired bit - jmp start ; do it again -loop: - out null, 1 ; get rid of a bit -.wrap - - -% c-sdk { -// this is a raw helper function for use by the user which sets up the GPIO input and output, and configures the SM to output on a particular pin - -void dcd_latch_program_init(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin) { - // configure a SM - pio_sm_config c = dcd_latch_program_get_default_config(offset); - // set the out pin to out_pin - sm_config_set_out_pins(&c, out_pin, 1); - // start at in_pin to read in the phases - sm_config_set_in_pins(&c, in_pin); - // get 8 bit dcd_latch values through the OSR from the main program - sm_config_set_out_shift(&c, true, false, 8); - // set out_pin as a GPIO output connected to this SM - pio_gpio_init(pio, out_pin); - pio_sm_set_consecutive_pindirs(pio, sm, out_pin, 1, true); // TODO change back - manually set output for now - // sm_config_set_set_pins(&c, pin, 1); - // initialize - pio_sm_init(pio, sm, offset, &c); -} -%} \ No newline at end of file diff --git a/pico/mac/dcd_mux.pio b/pico/mac/dcd_mux.pio.old similarity index 69% rename from pico/mac/dcd_mux.pio rename to pico/mac/dcd_mux.pio.old index e359d7e3e..370bdf0a9 100644 --- a/pico/mac/dcd_mux.pio +++ b/pico/mac/dcd_mux.pio.old @@ -6,7 +6,7 @@ ; ; -.define public LSTRB 12 +.define public LSTRB 13 .define public ENABLE 7 ; The DCD mux will really control the RD line direction. @@ -16,46 +16,50 @@ ; probably at some point should push the strobe counter so the FN can decide which disk image to use .program dcd_mux -.side_set 1 opt pindirs +.side_set 3 opt pindirs ; initial state is RD is hi-z and we have 2 DCDs ; we wait to be enabled then RD goes to output .wrap_target start: - set x, 0 side 0 ; put the number of DCD devices in X (0xf020 - last digit is number of DCDs) + set x, 0 side 0b000 ; put the number of DCD devices in X (0xf020 - last digit is number of DCDs) wait 0 gpio ENABLE ; don't do anything until we're enabled - in x, 32 ; say we are at the first DCD - jmp x-- cont ; decrement X to wait for the next strobe + set pins, 1 + jmp entry cont: ; now we need to wait to be strobed or to be disabled - jmp pin start side 1 ; disabled so go back to the beginning! + jmp pin start side 0b100 ; disabled so go back to the beginning! mov osr, pins ; get LSTRB value into osr out y, 1 ; stick it in Y jmp !Y cont ; not strobing loop +entry: in x, 32 ; push X to the FIFO to tell the program a certain drive is selected wait 0 gpio LSTRB jmp x-- cont + set pins, 0 wait 1 gpio ENABLE ; side 0 .wrap - nop ; need to pad a couple instructions to make it same length as floppy mux nop - + % c-sdk { // this is a raw helper function for use by the user which sets up the GPIO input and output, and configures the SM to output on a particular pin // #define LSTRB 12 // #define ENABLE 7 -void dcd_mux_program_init(PIO pio, uint sm, uint offset, uint set_pin) { +void dcd_mux_program_init(PIO pio, uint sm, uint offset, uint mux_pin) { // configure a SM pio_sm_config c = dcd_mux_program_get_default_config(offset); // config side set - sm_config_set_sideset_pins(&c, set_pin); + sm_config_set_sideset_pins(&c, mux_pin); sm_config_set_in_pins(&c, LSTRB); sm_config_set_jmp_pin(&c, ENABLE); // there are 4 wires to read for latch mux, shift to the right, no autopull - sm_config_set_set_pins(&c, set_pin, 1); + sm_config_set_set_pins(&c, 12, 1); // todo: update with a parameter sm_config_set_out_shift(&c, true, false, 1); sm_config_set_in_shift(&c, true, true, 32); - pio_gpio_init(pio, set_pin); - pio_sm_set_consecutive_pindirs(pio, sm, set_pin, 1, false); + for (int i=0; i<3; i++) + pio_gpio_init(pio, mux_pin + i); + pio_sm_set_consecutive_pindirs(pio, sm, mux_pin, 3, false); + pio_gpio_init(pio, 12); + pio_sm_set_consecutive_pindirs(pio, sm, 12, 1, true); // initialize pio_sm_init(pio, sm, offset, &c); } diff --git a/pico/mac/dcd_read.pio b/pico/mac/dcd_read.pio index 0cfff4fbf..b15deb1dc 100644 --- a/pico/mac/dcd_read.pio +++ b/pico/mac/dcd_read.pio @@ -2,16 +2,14 @@ ; FujiNet Project ; ; Vintage Macintosh Microfloppy Controller Interface -; sRead NRZI stream +; Read NRZI stream ; ; -.define ENABLE 7 .define public T0 10 .program dcd_read .side_set 1 - ; wait 0 gpio ENABLE side 1 ; removed if SM was triggered by main program set y, 0 side 0 ; initial state is always 0 set x, 7 side 0 ; bit counter reset: @@ -25,7 +23,7 @@ loop1: low: in y, 1 side 0 [1] ; shift in the decoded value, which is equal to the previous state y set y, 0 side 0 ; previous state is now low (zero) - jmp x-- loop side 1 ; check to see if we're at the last bit? + jmp x-- loop side 1 ; check to see if we are at the last bit? jmp sync side 1 ; if so, then wait for the next byte to start high: mov y, ~y side 0 @@ -47,22 +45,15 @@ void dcd_read_program_init(PIO pio, uint sm, uint offset, uint in_pin) { // configure a SM pio_sm_config c = dcd_read_program_get_default_config(offset); - // config side set - // sm_config_set_sideset_pins(&c, mux_pin); sm_config_set_in_pins(&c, in_pin); sm_config_set_jmp_pin(&c, in_pin); - // sm_config_set_sideset_pins(&c, 15); // TEMPORARY FOR DEBUGGING - // sm_config_set_out_shift(&c, true, false, 1); sm_config_set_in_shift(&c, false, true, 8); sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); - - pio_gpio_init(pio, in_pin); - pio_sm_set_consecutive_pindirs(pio, sm, in_pin, 1, false); -// pio_gpio_init(pio, 15); -// pio_sm_set_consecutive_pindirs(pio, sm, 15, 1, true); // TEMPORARY FOR DEBUG OUTPUT (EXTRA) - pio_gpio_init(pio, 9); - pio_sm_set_consecutive_pindirs(pio, sm, 9, 1, false); // for blocking on CA1 - + + // sm_config_set_sideset_pins(&c, 16); // TEMPORARY FOR DEBUGGING + // pio_gpio_init(pio, 16); + // pio_sm_set_consecutive_pindirs(pio, sm, 16, 1, true); // TEMPORARY FOR DEBUG OUTPUT (EXTRA) + // initialize float cycles_per_bit = T0; float div = clock_get_hz(clk_sys) / (500.0e3 * cycles_per_bit); // 125MHz/500kHz = 250 diff --git a/pico/mac/latch.pio b/pico/mac/latch.pio index 5a6228da8..a1dc358d4 100644 --- a/pico/mac/latch.pio +++ b/pico/mac/latch.pio @@ -2,27 +2,25 @@ ; FujiNet Project ; ; Vintage Macintosh Microfloppy Controller Interface -; Reads the drive phases and output a latch bit -; for DCD, the 8-bit latch register should be copied into upper and lower bytes of the value pulled by the SM +; Reads the drive phases (pushed to RX FIFO) and output a latch bit (pulled to TX_FIFO) +; Uses 2 DMA channels to read the desired latch bit ; - -.define ENABLE 7 +; the Y register is set prior to enabling the SM using + ; put LUT address into the FIFO + ; pull + ; mov y, osr + ; out null, 1 + ; + ; or using c code: + ; pio_sm_put(pioblk_rw, SM_LATCH, (uintptr_t)latch_lut >> 5); + ; pio_sm_exec_wait_blocking(pioblk_rw, SM_LATCH, pio_encode_pull(false, true)); + ; pio_sm_exec_wait_blocking(pioblk_rw, SM_LATCH, pio_encode_mov(pio_y, pio_osr)); + ; pio_sm_exec_wait_blocking(pioblk_rw, SM_LATCH, pio_encode_out(pio_null, 1)); .program latch -start: - wait 0 gpio ENABLE - mov osr, pins ; read the GPIO's into the output shift register - out y, 4 ; shift the 4 LSBs into Y - pull noblock ; get the latch word into OSR, if no new word in FIFO, get it from X - mov x, osr ; put the osr back into X in case it's new -.wrap_target - jmp y-- loop ; if y>0 goto to loop and decrement y - out pins, 1 ; output the desired bit - jmp start ; do it again -loop: - out null, 1 ; get rid of a bit -.wrap - + mov isr, y ; put the base address in ISR + in pins, 5 ; copy the pin combination into the ISR (auto push) + out pins, 1 ; output the latch bit value % c-sdk { // this is a raw helper function for use by the user which sets up the GPIO input and output, and configures the SM to output on a particular pin @@ -30,15 +28,18 @@ loop: void latch_program_init(PIO pio, uint sm, uint offset, uint in_pin, uint out_pin) { // configure a SM pio_sm_config c = latch_program_get_default_config(offset); - // set the out pin to out_pin + + // get 1 bit latch values through the OSR and output on out_pin sm_config_set_out_pins(&c, out_pin, 1); - // start at in_pin to read in the phases + sm_config_set_out_shift(&c, true, true, 1); + + // start at in_pin to read in the phases and push to the FIFO sm_config_set_in_pins(&c, in_pin); - // get 16 bit latch values through the OSR from the main program - sm_config_set_out_shift(&c, true, false, 16); + sm_config_set_in_shift(&c, false, true, 5); + // set out_pin as a GPIO output connected to this SM pio_gpio_init(pio, out_pin); -// pio_sm_set_consecutive_pindirs(pio, sm, out_pin, 1, true); + pio_sm_set_consecutive_pindirs(pio, sm, out_pin, 1, true); // sm_config_set_set_pins(&c, pin, 1); // initialize pio_sm_init(pio, sm, offset, &c); diff --git a/pico/mac/mux.pio b/pico/mac/mux.pio index ada87928f..b6d2caa80 100644 --- a/pico/mac/mux.pio +++ b/pico/mac/mux.pio @@ -6,44 +6,84 @@ ; ; +.define public LSTRB 13 +.define public ENABLE 7 +.define public DISKFLAG 12 + +; The DCD mux will really control the RD line direction. +; It will ... +; count the number of strobes and disable RD after 1, 2, or 3 of them +; it will reset the counter when disable goes high +; probably at some point should push the strobe counter so the FN can decide which disk image to use +; +; combining with Floppy MUX: +; when disabled, should be in hi-z and waiting for enable +; when disabled should go back to DCD mode +; when drive counter == 0 should go to floppy mode + .program mux -.side_set 3 opt pindirs -start: - jmp pin next4 - mov osr, pins ; get the input phases +.side_set 3 opt pindirs + ; initial state is RD is hi-z and we have 2 DCDs + ; we wait to be enabled then RD goes to output + +start: + set x, 0 side 0b000 ; put the number of DCD devices in X (0xf020 - last digit is number of DCDs) + wait 0 gpio ENABLE ; don't do anything until we're enabled +.wrap_target +entry: + in x, 32 ; push X to the FIFO to tell the program a certain drive is selected + wait 0 gpio LSTRB ; wait for strobe to deassert + jmp x-- dcd ; if X>0, then count down to next drive +floppy: + set pins, 0 ; otherwise we're in floppy mode! + jmp pin start ; if not ENABLED then go back to the beginning + mov osr, pins ; otherwise get the input phases out x, 4 ; copy to X set y, 0b0100 ; RDDATA (head 0) jmp x!=y next1 - jmp start side 0b010 + jmp floppy side 0b010 next1: set y, 0b1100 ; RDDATA (head 1) jmp x!=y next2 - jmp start side 0b010 + jmp floppy side 0b010 next2: set y, 0b1011 ; TACH jmp x!=y next3 - jmp start side 0b001 + jmp floppy side 0b001 next3: ; LATCH - jmp start side 0b100 -next4: - jmp start side 0b000 ; enable high (not enabled) + jmp floppy side 0b100 +dcd: + ; now we need to wait to be strobed or to be disabled + set pins, 1 ; say to latch we're in DCD mode + jmp pin start ; disabled so go back to the beginning! + mov osr, pins side 0b100 ; get LSTRB value into osr + out null, 5 ; have to blow some into null first + out y, 1 ; stick it in Y + jmp !Y dcd ; not strobing loop +.wrap + % c-sdk { // this is a raw helper function for use by the user which sets up the GPIO input and output, and configures the SM to output on a particular pin - -void mux_program_init(PIO pio, uint sm, uint offset, uint in_pin, uint mux_pin) { +void mux_program_init(PIO pio, uint sm, uint offset, uint in_pin, uint mux_pin) +{ // configure a SM pio_sm_config c = mux_program_get_default_config(offset); // config side set - sm_config_set_sideset_pins(&c, mux_pin); - sm_config_set_in_pins(&c, in_pin); - sm_config_set_jmp_pin(&c, in_pin-1); + sm_config_set_sideset_pins(&c, mux_pin); + sm_config_set_in_pins(&c, in_pin); + sm_config_set_jmp_pin(&c, ENABLE); // there are 4 wires to read for latch mux, shift to the right, no autopull - sm_config_set_out_shift(&c, true, false, 4); + sm_config_set_set_pins(&c, DISKFLAG, 1); // todo: update with a parameter + sm_config_set_out_shift(&c, true, false, 0); + sm_config_set_in_shift(&c, true, true, 32); for (int i=0; i<3; i++) pio_gpio_init(pio, mux_pin + i); pio_sm_set_consecutive_pindirs(pio, sm, mux_pin, 3, false); + pio_gpio_init(pio, DISKFLAG); + pio_sm_set_consecutive_pindirs(pio, sm, DISKFLAG, 1, true); // initialize pio_sm_init(pio, sm, offset, &c); } -%} \ No newline at end of file +%} + diff --git a/pico/mac/mux.pio.old b/pico/mac/mux.pio.old new file mode 100644 index 000000000..ada87928f --- /dev/null +++ b/pico/mac/mux.pio.old @@ -0,0 +1,49 @@ +; +; FujiNet Project +; +; Vintage Macintosh Microfloppy Controller Interface +; selects output pins between RMT, TACH and LATCH +; +; + +.program mux +.side_set 3 opt pindirs +start: + jmp pin next4 + mov osr, pins ; get the input phases + out x, 4 ; copy to X + set y, 0b0100 ; RDDATA (head 0) + jmp x!=y next1 + jmp start side 0b010 +next1: + set y, 0b1100 ; RDDATA (head 1) + jmp x!=y next2 + jmp start side 0b010 +next2: + set y, 0b1011 ; TACH + jmp x!=y next3 + jmp start side 0b001 +next3: ; LATCH + jmp start side 0b100 +next4: + jmp start side 0b000 ; enable high (not enabled) + +% c-sdk { +// this is a raw helper function for use by the user which sets up the GPIO input and output, and configures the SM to output on a particular pin + +void mux_program_init(PIO pio, uint sm, uint offset, uint in_pin, uint mux_pin) { + // configure a SM + pio_sm_config c = mux_program_get_default_config(offset); + // config side set + sm_config_set_sideset_pins(&c, mux_pin); + sm_config_set_in_pins(&c, in_pin); + sm_config_set_jmp_pin(&c, in_pin-1); + // there are 4 wires to read for latch mux, shift to the right, no autopull + sm_config_set_out_shift(&c, true, false, 4); + for (int i=0; i<3; i++) + pio_gpio_init(pio, mux_pin + i); + pio_sm_set_consecutive_pindirs(pio, sm, mux_pin, 3, false); + // initialize + pio_sm_init(pio, sm, offset, &c); +} +%} \ No newline at end of file