Procházet zdrojové kódy

Setup reclockable SDIO

Setup up SDIO delays in a struct that is rewritable and used that
struct to initialize the SDIO interface. This should allow reclocking
of the SDIO interface PIO statemachine.
Morio před 1 rokem
rodič
revize
0c420c01fd

+ 1 - 1
lib/SCSI2SD/include/scsi2sd.h

@@ -102,7 +102,7 @@ typedef enum
 	S2S_CFG_SPEED_ASYNC_50,
 	S2S_CFG_SPEED_SYNC_5,
 	S2S_CFG_SPEED_SYNC_10,
-	S2S_CFG_SPEED_TURBO
+	S2S_CFG_SPEED_SYNC_20
 } S2S_CFG_SPEED;
 
 typedef struct __attribute__((packed))

+ 16 - 20
lib/SCSI2SD/src/firmware/scsi.c

@@ -28,6 +28,7 @@
 #include "led.h"
 #include "mode.h"
 #include "scsi2sd_time.h"
+#include "scsi2sd_timings.h"
 #include "bsp.h"
 #include "cdrom.h"
 #include "network.h"
@@ -1105,31 +1106,26 @@ static void process_MessageOut()
 				//The speeds above correspond to syncPeriod values of 25, 18, 15 and 12 (maybe, the last 3 are truncated)
 				//We will set the syncPeriod and syncOffset to the fastest we 
 				//can support if the initiator requests a faster speed
-				if ((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO) &&
-					(transferPeriod <= 18))
+				if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_SYNC_20 || S2S_CFG_SPEED_NoLimit)
 				{
-					scsiDev.target->syncPeriod = 18; // 20 corresponds to 12.5 MB/s
+					if (transferPeriod <= g_max_sync_20_period)
+						scsiDev.target->syncPeriod = g_max_sync_20_period;
+					else 
+						scsiDev.target->syncPeriod = transferPeriod;	
 				}
-				else if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_TURBO)
+				else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)
 				{
-					scsiDev.target->syncPeriod = transferPeriod;
+					if (transferPeriod <= g_max_sync_10_period)
+						scsiDev.target->syncPeriod = g_max_sync_10_period;
+					else
+						scsiDev.target->syncPeriod = transferPeriod;
 				}
-				else if (transferPeriod <= 25 &&
-					((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit) ||
-						(scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)))
-				{
-					scsiDev.target->syncPeriod = 25; // 100ns, 10MB/s
-
-				} else if (transferPeriod < 50 &&
-					((scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit) ||
-						(scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_SYNC_10)))
+				else if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_SYNC_5)
 				{
-					scsiDev.target->syncPeriod = transferPeriod;
-				} else if (transferPeriod >= 50)
-				{
-					scsiDev.target->syncPeriod = transferPeriod;
-				} else {
-					scsiDev.target->syncPeriod = 50;
+					if (transferPeriod <= g_max_sync_5_period)
+						scsiDev.target->syncPeriod = g_max_sync_5_period;
+					else
+						scsiDev.target->syncPeriod = transferPeriod;
 				}
 			}
 

+ 24 - 0
lib/ZuluSCSI_platform_GD32F205/scsi2sd_timings.c

@@ -0,0 +1,24 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#include "scsi2sd_timings.h"
+uint8_t g_max_sync_20_period = 25;
+uint8_t g_max_sync_10_period = 25;
+uint8_t g_max_sync_5_period  = 50; 

+ 27 - 0
lib/ZuluSCSI_platform_GD32F205/scsi2sd_timings.h

@@ -0,0 +1,27 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#ifndef ZULUSCSI_PLATFORM_TIMINGS_H
+#define ZULUSCSI_PLATFORM_TIMINGS_H
+#include <stdint.h>
+extern uint8_t g_max_sync_20_period;
+extern uint8_t g_max_sync_10_period;
+extern uint8_t g_max_sync_5_period;
+#endif // ZULUSCSI_RP2MCU_TIMINGS_H

+ 24 - 0
lib/ZuluSCSI_platform_GD32F450/scsi2sd_timings.c

@@ -0,0 +1,24 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#include "scsi2sd_timings.h"
+uint8_t g_max_sync_20_period = 25;
+uint8_t g_max_sync_10_period = 25;
+uint8_t g_max_sync_5_period  = 50; 

+ 27 - 0
lib/ZuluSCSI_platform_GD32F450/scsi2sd_timings.h

@@ -0,0 +1,27 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#ifndef ZULUSCSI_PLATFORM_TIMINGS_H
+#define ZULUSCSI_PLATFORM_TIMINGS_H
+#include <stdint.h>
+extern uint8_t g_max_sync_20_period;
+extern uint8_t g_max_sync_10_period;
+extern uint8_t g_max_sync_5_period;
+#endif // ZULUSCSI_RP2MCU_TIMINGS_H

+ 1 - 0
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform.cpp

@@ -389,6 +389,7 @@ void platform_late_init()
         gpio_conf(SCSI_OUT_ATN,   GPIO_FUNC_SIO, false,false, true,  true, true);
 #endif  // PLATFORM_HAS_INITIATOR_MODE
     }
+    scsi_accel_rp2040_init();
 }
 
 void platform_post_sd_card_init() {}

+ 3 - 3
lib/ZuluSCSI_platform_RP2MCU/ZuluSCSI_platform.h

@@ -71,13 +71,13 @@ extern const char *g_platform_name;
 # define PLATFORM_REVISION "2.0"
 # define PLATFORM_HAS_INITIATOR_MODE 1
 # define DISABLE_SWO
-#define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_TURBO
+#define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 #elif defined(ZULUSCSI_RP2350A)
 # define PLATFORM_NAME "ZuluSCSI RP2350A"
 # define PLATFORM_PID "RP2350A"
 # define PLATFORM_REVISION "2.0"
 # define PLATFORM_HAS_INITIATOR_MODE 1
-#define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_TURBO
+#define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 #elif defined(ZULUSCSI_BS2)
 # define PLATFORM_NAME "ZuluSCSI BS2"
 # define PLATFORM_PID "BS2"
@@ -103,7 +103,7 @@ extern const char *g_platform_name;
 
 // NOTE: The driver supports synchronous speeds higher than 10MB/s, but this
 // has not been tested due to lack of fast enough SCSI adapter.
-// #define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_TURBO
+// #define PLATFORM_MAX_SCSI_SPEED S2S_CFG_SPEED_SYNC_20
 
 // Debug logging function, can be used to print to e.g. serial port.
 // May get called from interrupt handlers.

+ 31 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi2sd_timings.c

@@ -0,0 +1,31 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#include "scsi2sd_timings.h"
+#include "ZuluSCSI_platform.h"
+#if defined(ZULUSCSI_MCU_RP23XX)
+uint8_t g_max_sync_20_period = 18;
+uint8_t g_max_sync_10_period = 25;
+uint8_t g_max_sync_5_period  = 50; 
+#elif defined(ZULUSCSI_MCU_RP20XX)
+uint8_t g_max_sync_20_period = 25;
+uint8_t g_max_sync_10_period = 25;
+uint8_t g_max_sync_5_period  = 50; 
+#endif

+ 27 - 0
lib/ZuluSCSI_platform_RP2MCU/scsi2sd_timings.h

@@ -0,0 +1,27 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#ifndef ZULUSCSI_PLATFORM_TIMINGS_H
+#define ZULUSCSI_PLATFORM_TIMINGS_H
+#include <stdint.h>
+extern uint8_t g_max_sync_20_period;
+extern uint8_t g_max_sync_10_period;
+extern uint8_t g_max_sync_5_period;
+#endif // ZULUSCSI_RP2MCU_TIMINGS_H

+ 2 - 1
lib/ZuluSCSI_platform_RP2MCU/sd_card_sdio.cpp

@@ -28,6 +28,7 @@
 
 #include "ZuluSCSI_log.h"
 #include "sdio.h"
+#include "timings.h"
 #include <hardware/gpio.h>
 #include <SdFat.h>
 #include <SdCard/SdCardInfo.h>
@@ -92,7 +93,7 @@ bool SdioCard::begin(SdioConfig sdioConfig)
     sdio_status_t status;
     
     // Initialize at 1 MHz clock speed
-    rp2040_sdio_init(25);
+    rp2040_sdio_init(g_zuluscsi_timings.sdio.clk_div_1mhz);
 
     // Establish initial connection with the card
     for (int retries = 0; retries < 5; retries++)

+ 37 - 3
lib/ZuluSCSI_platform_RP2MCU/sdio.cpp

@@ -37,6 +37,7 @@
 #include <hardware/structs/scb.h>
 #include <ZuluSCSI_platform.h>
 #include <ZuluSCSI_log.h>
+#include "timings.h"
 
 #if defined(ZULUSCSI_PICO) || defined(ZULUSCSI_BS2)
 # include "sdio_Pico.pio.h"
@@ -814,7 +815,17 @@ void rp2040_sdio_init(int clock_divider)
     pio_clear_instruction_memory(SDIO_PIO);
 
     // Command & clock state machine
-    g_sdio.pio_cmd_clk_offset = pio_add_program(SDIO_PIO, &sdio_cmd_clk_program);
+    uint16_t temp_program_instr[32];
+    pio_program rewrite_sdio_cmd_clk_program = { temp_program_instr, sdio_cmd_clk_program.length,  sdio_cmd_clk_program.origin, sdio_cmd_clk_program.pio_version };
+    memcpy(temp_program_instr, sdio_cmd_clk_program_instructions, sizeof(sdio_cmd_clk_program_instructions));
+    // Set the delays for the sdio_cmd_clk SDIO state machine
+    for (uint8_t i = 0; i < sizeof(sdio_cmd_clk_program_instructions) / sizeof(sdio_cmd_clk_program_instructions[0]); i++)
+    {
+        uint16_t instr = sdio_cmd_clk_program_instructions[i]
+            | ((i & 1) ? pio_encode_delay(g_zuluscsi_timings.sdio.delay0) : pio_encode_delay(g_zuluscsi_timings.sdio.delay1));
+        temp_program_instr[i] = instr;
+    }
+    g_sdio.pio_cmd_clk_offset = pio_add_program(SDIO_PIO, &rewrite_sdio_cmd_clk_program);
     pio_sm_config cfg = sdio_cmd_clk_program_get_default_config(g_sdio.pio_cmd_clk_offset);
     sm_config_set_out_pins(&cfg, SDIO_CMD, 1);
     sm_config_set_in_pins(&cfg, SDIO_CMD);
@@ -831,7 +842,16 @@ void rp2040_sdio_init(int clock_divider)
     pio_sm_set_enabled(SDIO_PIO, SDIO_CMD_SM, true);
 
     // Data reception program
-    g_sdio.pio_data_rx_offset = pio_add_program(SDIO_PIO, &sdio_data_rx_program);
+
+    // Set delays for sdio_data_rx PIO state machine
+    pio_program rewrite_sdio_data_rx_program = { temp_program_instr, sdio_data_rx_program.length,  sdio_data_rx_program.origin, sdio_data_rx_program.pio_version };
+    memcpy(temp_program_instr, sdio_data_rx_program_instructions, sizeof(sdio_data_rx_program_instructions));
+    uint16_t instr = sdio_data_rx_program_instructions[2] | pio_encode_delay(g_zuluscsi_timings.sdio.clk_div_pio - 1);
+    temp_program_instr[2] = instr;
+    instr = sdio_data_rx_program_instructions[3] | pio_encode_delay(g_zuluscsi_timings.sdio.clk_div_pio - 2);
+    temp_program_instr[3] = instr;
+
+    g_sdio.pio_data_rx_offset = pio_add_program(SDIO_PIO, &rewrite_sdio_data_rx_program);
     g_sdio.pio_cfg_data_rx = sdio_data_rx_program_get_default_config(g_sdio.pio_data_rx_offset);
     sm_config_set_in_pins(&g_sdio.pio_cfg_data_rx, SDIO_D0);
     sm_config_set_in_shift(&g_sdio.pio_cfg_data_rx, false, true, 32);
@@ -839,7 +859,21 @@ void rp2040_sdio_init(int clock_divider)
     sm_config_set_clkdiv_int_frac(&g_sdio.pio_cfg_data_rx, clock_divider, 0);
 
     // Data transmission program
-    g_sdio.pio_data_tx_offset = pio_add_program(SDIO_PIO, &sdio_data_tx_program);
+
+    // Set delays for sdio_data_tx PIO state machine
+    pio_program rewrite_sdio_data_tx_program = { temp_program_instr, sdio_data_tx_program.length,  sdio_data_tx_program.origin, sdio_data_tx_program.pio_version };
+    memcpy(temp_program_instr, sdio_data_tx_program_instructions, sizeof(sdio_data_tx_program_instructions));
+
+    instr = sdio_data_tx_program_instructions[1] | pio_encode_delay(g_zuluscsi_timings.sdio.clk_div_pio + g_zuluscsi_timings.sdio.delay1 - 1);
+    temp_program_instr[1] = instr;
+    
+    for (uint8_t i = 2; i < sizeof(sdio_data_tx_program_instructions) / sizeof(sdio_data_tx_program_instructions[0]); i++)
+    {    
+        uint16_t instr = sdio_data_tx_program_instructions[i]
+            | ((i & 1) ? pio_encode_delay(g_zuluscsi_timings.sdio.delay1) : pio_encode_delay(g_zuluscsi_timings.sdio.delay0));
+        temp_program_instr[i] = instr;
+    }
+    g_sdio.pio_data_tx_offset = pio_add_program(SDIO_PIO, &rewrite_sdio_data_tx_program);
     g_sdio.pio_cfg_data_tx = sdio_data_tx_program_get_default_config(g_sdio.pio_data_tx_offset);
     sm_config_set_in_pins(&g_sdio.pio_cfg_data_tx, SDIO_D0);
     sm_config_set_set_pins(&g_sdio.pio_cfg_data_tx, SDIO_D0, 4);

+ 29 - 29
lib/ZuluSCSI_platform_RP2MCU/sdio_RP2040.pio

@@ -70,42 +70,42 @@
 .program sdio_cmd_clk
     .side_set 1
 
-    mov OSR, NULL       side 1 [D1]    ; Make sure OSR is full of zeros to prevent autopull
+    mov OSR, NULL       side 1 [0] ;[D1]    ; Make sure OSR is full of zeros to prevent autopull
 
 wait_cmd:
-    mov Y, !STATUS      side 0 [D0]    ; Check if TX FIFO has data
-    jmp !Y wait_cmd     side 1 [D1]
+    mov Y, !STATUS      side 0 [0]; [D0]    ; Check if TX FIFO has data
+    jmp !Y wait_cmd     side 1 [0]; [D1]
 
 load_cmd:
-    out NULL, 32        side 0 [D0]    ; Load first word (trigger autopull)
-    out X, 8            side 1 [D1]    ; Number of bits to send
-    set pins, 1         side 0 [D0]    ; Initial state of CMD is high
-    set pindirs, 1      side 1 [D1]    ; Set SDIO_CMD as output
+    out NULL, 32        side 0 [0]; [D0]    ; Load first word (trigger autopull)
+    out X, 8            side 1 [0]; [D1]    ; Number of bits to send
+    set pins, 1         side 0 [0]; [D0]    ; Initial state of CMD is high
+    set pindirs, 1      side 1 [0]; [D1]    ; Set SDIO_CMD as output
 
 send_cmd:
-    out pins, 1         side 0 [D0]    ; Write output on falling edge of CLK
-    jmp X-- send_cmd    side 1 [D1]
+    out pins, 1         side 0 [0]; [D0]    ; Write output on falling edge of CLK
+    jmp X-- send_cmd    side 1 [0]; [D1]
 
 prep_resp:
-    set pindirs, 0      side 0 [D0]    ; Set SDIO_CMD as input
-    out X, 8            side 1 [D1]    ; Get number of bits in response
-    nop                 side 0 [D0]    ; For clock alignment
-    jmp !X resp_done    side 1 [D1]    ; Check if we expect a response
+    set pindirs, 0      side 0 [0]; [D0]    ; Set SDIO_CMD as input
+    out X, 8            side 1 [0]; [D1]    ; Get number of bits in response
+    nop                 side 0 [0]; [D0]    ; For clock alignment
+    jmp !X resp_done    side 1 [0]; [D1]    ; Check if we expect a response
 
 wait_resp:
-    nop                  side 0 [D0]
-    jmp PIN wait_resp    side 1 [D1]    ; Loop until SDIO_CMD = 0
+    nop                  side 0 [0]; [D0]
+    jmp PIN wait_resp    side 1 [0]; [D1]    ; Loop until SDIO_CMD = 0
 
     ; Note: input bits are read at the same time as we write CLK=0.
     ; Because the host controls the clock, the read happens before
     ; the card sees the falling clock edge. This gives maximum time
     ; for the data bit to settle.
 read_resp:
-    in PINS, 1          side 0 [D0]    ; Read input data bit
-    jmp X-- read_resp   side 1 [D1]    ; Loop to receive all data bits
+    in PINS, 1          side 0 [0]; [D0]    ; Read input data bit
+    jmp X-- read_resp   side 1 [0]; [D1]    ; Loop to receive all data bits
 
 resp_done:
-    push                side 0 [D0]    ; Push the remaining part of response
+    push                side 0 [0]; [D0]    ; Push the remaining part of response
 
 ; State machine 1 is used to send and receive data blocks.
 ; Pin mapping for this state machine:
@@ -121,10 +121,10 @@ resp_done:
 wait_start:
     mov X, Y                               ; Reinitialize number of nibbles to receive
     wait 0 pin 0                           ; Wait for zero state on D0
-    wait 1 gpio SDIO_CLK_GPIO  [CLKDIV-1]  ; Wait for rising edge and then whole clock cycle
+    wait 1 gpio SDIO_CLK_GPIO  [0]; [CLKDIV-1]  ; Wait for rising edge and then whole clock cycle
 
 rx_data:
-    in PINS, 4                 [CLKDIV-2]  ; Read nibble
+    in PINS, 4                 [0]; [CLKDIV-2]  ; Read nibble
     jmp X--, rx_data
 
 ; Data transmission program
@@ -145,20 +145,20 @@ rx_data:
 
 .program sdio_data_tx
     wait 0 gpio SDIO_CLK_GPIO  
-    wait 1 gpio SDIO_CLK_GPIO  [CLKDIV + D1 - 1]; Synchronize so that write occurs on falling edge
+    wait 1 gpio SDIO_CLK_GPIO  [0]; [CLKDIV + D1 - 1]; Synchronize so that write occurs on falling edge
 
 tx_loop:
-    out PINS, 4                [D0]    ; Write nibble and wait for whole clock cycle
-    jmp X-- tx_loop            [D1]
+    out PINS, 4                [0]; [D0]    ; Write nibble and wait for whole clock cycle
+    jmp X-- tx_loop            [0]; [D1]
 
-    set pindirs, 0x00          [D0]    ; Set data bus as input
+    set pindirs, 0x00          [0]; [D0]    ; Set data bus as input
 
 .wrap_target
 response_loop:
-    in PINS, 1                 [D1]    ; Read D0 on rising edge
-    jmp Y--, response_loop     [D0]
-
+    in PINS, 1                 [0]; [D1]    ; Read D0 on rising edge
+    jmp Y--, response_loop     [0]; [D0]
+    
 wait_idle:
-    wait 1 pin 0               [D1]    ; Wait for card to indicate idle condition
-    push                       [D0]    ; Push the response token
+    wait 1 pin 0               [0]; [D1]    ; Wait for card to indicate idle condition
+    push                       [0]; [D0]    ; Push the response token
 .wrap

+ 28 - 29
lib/ZuluSCSI_platform_RP2MCU/sdio_RP2040.pio.h

@@ -17,24 +17,24 @@
 
 static const uint16_t sdio_cmd_clk_program_instructions[] = {
             //     .wrap_target
-    0xb1e3, //  0: mov    osr, null       side 1 [1] 
-    0xa24d, //  1: mov    y, !status      side 0 [2] 
-    0x1161, //  2: jmp    !y, 1           side 1 [1] 
-    0x6260, //  3: out    null, 32        side 0 [2] 
-    0x7128, //  4: out    x, 8            side 1 [1] 
-    0xe201, //  5: set    pins, 1         side 0 [2] 
-    0xf181, //  6: set    pindirs, 1      side 1 [1] 
-    0x6201, //  7: out    pins, 1         side 0 [2] 
-    0x1147, //  8: jmp    x--, 7          side 1 [1] 
-    0xe280, //  9: set    pindirs, 0      side 0 [2] 
-    0x7128, // 10: out    x, 8            side 1 [1] 
-    0xa242, // 11: nop                    side 0 [2] 
-    0x1131, // 12: jmp    !x, 17          side 1 [1] 
-    0xa242, // 13: nop                    side 0 [2] 
-    0x11cd, // 14: jmp    pin, 13         side 1 [1] 
-    0x4201, // 15: in     pins, 1         side 0 [2] 
-    0x114f, // 16: jmp    x--, 15         side 1 [1] 
-    0x8220, // 17: push   block           side 0 [2] 
+    0xb0e3, //  0: mov    osr, null       side 1     
+    0xa04d, //  1: mov    y, !status      side 0     
+    0x1061, //  2: jmp    !y, 1           side 1     
+    0x6060, //  3: out    null, 32        side 0     
+    0x7028, //  4: out    x, 8            side 1     
+    0xe001, //  5: set    pins, 1         side 0     
+    0xf081, //  6: set    pindirs, 1      side 1     
+    0x6001, //  7: out    pins, 1         side 0     
+    0x1047, //  8: jmp    x--, 7          side 1     
+    0xe080, //  9: set    pindirs, 0      side 0     
+    0x7028, // 10: out    x, 8            side 1     
+    0xa042, // 11: nop                    side 0     
+    0x1031, // 12: jmp    !x, 17          side 1     
+    0xa042, // 13: nop                    side 0     
+    0x10cd, // 14: jmp    pin, 13         side 1     
+    0x4001, // 15: in     pins, 1         side 0     
+    0x104f, // 16: jmp    x--, 15         side 1     
+    0x8020, // 17: push   block           side 0     
             //     .wrap
 };
 
@@ -64,8 +64,8 @@ static const uint16_t sdio_data_rx_program_instructions[] = {
             //     .wrap_target
     0xa022, //  0: mov    x, y                       
     0x2020, //  1: wait   0 pin, 0                   
-    0x2492, //  2: wait   1 gpio, 18             [4] 
-    0x4304, //  3: in     pins, 4                [3] 
+    0x2092, //  2: wait   1 gpio, 18                 
+    0x4004, //  3: in     pins, 4                    
     0x0043, //  4: jmp    x--, 3                     
             //     .wrap
 };
@@ -93,15 +93,15 @@ static inline pio_sm_config sdio_data_rx_program_get_default_config(uint offset)
 
 static const uint16_t sdio_data_tx_program_instructions[] = {
     0x2012, //  0: wait   0 gpio, 18                 
-    0x2592, //  1: wait   1 gpio, 18             [5] 
-    0x6204, //  2: out    pins, 4                [2] 
-    0x0142, //  3: jmp    x--, 2                 [1] 
-    0xe280, //  4: set    pindirs, 0             [2] 
+    0x2092, //  1: wait   1 gpio, 18                 
+    0x6004, //  2: out    pins, 4                    
+    0x0042, //  3: jmp    x--, 2                     
+    0xe080, //  4: set    pindirs, 0                 
             //     .wrap_target
-    0x4101, //  5: in     pins, 1                [1] 
-    0x0285, //  6: jmp    y--, 5                 [2] 
-    0x21a0, //  7: wait   1 pin, 0               [1] 
-    0x8220, //  8: push   block                  [2] 
+    0x4001, //  5: in     pins, 1                    
+    0x0085, //  6: jmp    y--, 5                     
+    0x20a0, //  7: wait   1 pin, 0                   
+    0x8020, //  8: push   block                      
             //     .wrap
 };
 
@@ -118,4 +118,3 @@ static inline pio_sm_config sdio_data_tx_program_get_default_config(uint offset)
     return c;
 }
 #endif
-

+ 128 - 0
lib/ZuluSCSI_platform_RP2MCU/timings.c

@@ -0,0 +1,128 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#include "timings.h"
+#ifdef ZULUSCSI_MCU_RP23XX
+    zuluscsi_timings_t g_zuluscsi_timings = 
+    {
+        .clk_hz = 150000000,
+        .scsi = 
+        {
+            .delay0 = 0,
+            .delay1 = 0,
+            .req_delay = 0,
+            .gpio_ack = 0,
+            .gpio_req = 0,
+            .mode = ZULUSCSI_PIO_TARGET_MODE_SIMPLE
+        
+        },
+        .sdio =
+        {
+            .clk_div_1mhz = 0,
+            .clk_div_pio = 0,
+            .delay0 = 0,
+            .delay1 = 0
+        }
+    };
+#else
+    zuluscsi_timings_t g_zuluscsi_timings = 
+    {
+        .clk_hz = 125000000,
+        .scsi = 
+        {
+            .delay0 = 0,
+            .delay1 = 0,
+            .req_delay = 0,
+
+            .mode = ZULUSCSI_PIO_TARGET_MODE_SIMPLE
+        
+        },
+        .sdio =
+        {
+            .clk_div_1mhz = 25, // = 125MHz clk / clk_div_pio  
+            .clk_div_pio = 5,
+            .delay0 = 3 - 1, // subtract one for the instruction delay 
+            .delay1 = 2 - 1  // clk_div_pio - delay0 and subtract one for the instruction delay
+        }
+    };
+#endif
+
+zuluscsi_timings_t predefined_timings[] =
+    {
+        {
+            .clk_hz = 125000000,
+            .scsi = 
+            {
+                .delay0 = 0,
+                .delay1 = 0,
+                .req_delay = 0,
+                .mode = ZULUSCSI_PIO_TARGET_MODE_SIMPLE
+            
+            },
+            .sdio =
+            {
+                .clk_div_1mhz = 25, // = 125MHz clk / clk_div_pio  
+                .clk_div_pio = 5,
+                .delay0 = 3 - 1, // subtract one for the instruction delay 
+                .delay1 = 2 - 1  // clk_div_pio - delay0 and subtract one for the instruction delay
+            }
+        },
+        {
+            .clk_hz = 150000000,
+            .scsi = 
+            {
+                .delay0 = 0,
+                .delay1 = 0,
+                .req_delay = 0,
+                .mode = ZULUSCSI_PIO_TARGET_MODE_SIMPLE
+            
+            },
+            .sdio =
+            {
+                .clk_div_1mhz = 0,
+                .clk_div_pio = 0,
+                .delay0 = 0,
+                .delay1 = 0
+            }
+        },
+        {
+            .clk_hz = 250000000,
+            .scsi = 
+            {
+                .delay0 = 0,
+                .delay1 = 0,
+                .req_delay = 0,
+                .mode = ZULUSCSI_PIO_TARGET_MODE_SIMPLE
+            
+            },
+            .sdio =
+            {
+                .clk_div_1mhz = 0,
+                .clk_div_pio = 0,
+                .delay0 = 0,
+                .delay1 = 0
+            }
+        }
+    };
+
+void set_timings(uint32_t system_clk)
+{
+;
+}

+ 56 - 0
lib/ZuluSCSI_platform_RP2MCU/timings.h

@@ -0,0 +1,56 @@
+/** 
+ * ZuluSCSI™ - Copyright (c) 2024 Rabbit Hole Computing™
+ * 
+ * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version. 
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+#ifndef ZULUSCSI_RP2MCU_TIMINGS_H
+#define ZULUSCSI_RP2MCU_TIMINGS_H
+#include <stdint.h>
+
+typedef enum
+{
+    ZULUSCSI_PIO_TARGET_MODE_SIMPLE,
+    ZULUSCSI_PIO_TARGET_MODE_EXTRA_DELAY1,
+    ZULUSCSI_PIO_TARGET_MODE_EXTRA_DELAY2,
+    ZULUSCSI_PIO_TARGET_MODE_EXTRA_DELAY_1AND2
+} zuluscsi_pio_target_mode_t;
+
+typedef struct
+{
+    uint32_t clk_hz;
+    struct
+    {
+        uint8_t req_delay;
+        zuluscsi_pio_target_mode_t mode;
+        uint8_t delay0;
+        uint8_t delay1;
+    } scsi;
+
+    struct 
+    {
+        uint8_t clk_div_1mhz;
+        uint8_t clk_div_pio;
+        uint8_t delay0;
+        uint8_t delay1;
+    } sdio;
+
+} zuluscsi_timings_t;
+
+extern  zuluscsi_timings_t g_zuluscsi_timings;
+void set_timings(uint32_t system_clk);
+#endif // ZULUSCSI_RP2MCU_TIMINGS_H