Skip to content

Commit

Permalink
Merge pull request #296 from ZuluSCSI/pico
Browse files Browse the repository at this point in the history
Firmware for the ZuluSCSI Pico
  • Loading branch information
aperezbios authored Sep 12, 2023
2 parents c108dae + 354456b commit caa34d9
Show file tree
Hide file tree
Showing 16 changed files with 961 additions and 20 deletions.
6 changes: 1 addition & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode/extensions.json
.vscode
19 changes: 16 additions & 3 deletions lib/ZuluSCSI_platform_RP2040/ZuluSCSI_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,27 +121,38 @@ void platform_init()
/* Check dip switch settings */
#ifdef HAS_DIP_SWITCHES
gpio_conf(DIP_INITIATOR, GPIO_FUNC_SIO, false, false, false, false, false);
# ifndef ZULUSCSI_PICO
gpio_conf(DIP_DBGLOG, GPIO_FUNC_SIO, false, false, false, false, false);
gpio_conf(DIP_TERM, GPIO_FUNC_SIO, false, false, false, false, false);

# endif
delay(10); // 10 ms delay to let pull-ups do their work

# ifndef ZULUSCSI_PICO
bool dbglog = !gpio_get(DIP_DBGLOG);
bool termination = !gpio_get(DIP_TERM);
# endif
#else
delay(10);
#endif

#ifndef DISABLE_SWO
/* Initialize logging to SWO pin (UART0) */
gpio_conf(SWO_PIN, GPIO_FUNC_UART,false,false, true, false, true);
uart_init(uart0, 1000000);
g_uart_initialized = true;
#endif

mbed_set_error_hook(mbed_error_hook);

logmsg("Platform: ", g_platform_name);
logmsg("FW Version: ", g_log_firmwareversion);

#ifdef HAS_DIP_SWITCHES
#ifdef ZULUSCSI_PICO
logmsg("SCSI termination is determined by the DIP switch labeled \"TERM\"");
logmsg("Debug logging can only be enabled via INI file \"DEBUG=1\" under [SCSI] in zuluscsi.ini");
logmsg("-- DEBUG DIP switch setting is ignored on ZuluSCSI Pico FS Rev. 2023b boards");
g_log_debug = false;

#elif defined(HAS_DIP_SWITCHES)
logmsg("DIP switch settings: debug log ", (int)dbglog, ", termination ", (int)termination);
g_log_debug = dbglog;

Expand Down Expand Up @@ -326,6 +337,8 @@ void platform_late_init()
gpio_conf(SCSI_IN_REQ, GPIO_FUNC_SIO, true ,false, false, true, false);
gpio_conf(SCSI_IN_BSY, GPIO_FUNC_SIO, true, false, false, true, false);
gpio_conf(SCSI_IN_RST, GPIO_FUNC_SIO, true, false, false, true, false);
// Reinitialize OUT_RST to output mode. On RP Pico variant the pin is shared with IN_RST.
gpio_conf(SCSI_OUT_RST, GPIO_FUNC_SIO, false, false, true, true, true);
gpio_conf(SCSI_OUT_SEL, GPIO_FUNC_SIO, false,false, true, true, true);
gpio_conf(SCSI_OUT_ACK, GPIO_FUNC_SIO, false,false, true, true, true);
gpio_conf(SCSI_OUT_ATN, GPIO_FUNC_SIO, false,false, true, true, true);
Expand Down
11 changes: 9 additions & 2 deletions lib/ZuluSCSI_platform_RP2040/ZuluSCSI_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@
#include <stdint.h>
#include <Arduino.h>

#ifdef ZULUSCSI_BS2
#ifdef ZULUSCSI_PICO
// ZuluSCSI Pico carrier board variant
#include "ZuluSCSI_platform_gpio_Pico.h"
#elif defined(ZULUSCSI_BS2)
// BS2 hardware variant, using Raspberry Pico board on a carrier PCB
#include "ZuluSCSI_platform_gpio_BS2.h"
#else
Expand All @@ -44,7 +47,11 @@ extern "C" {
/* These are used in debug output and default SCSI strings */
extern const char *g_platform_name;

#ifdef ZULUSCSI_BS2
#ifdef ZULUSCSI_PICO
# define PLATFORM_NAME "ZuluSCSI Pico"
# define PLATFORM_REVISION "2.0"
# define PLATFORM_HAS_INITIATOR_MODE 1
#elif defined(ZULUSCSI_BS2)
# define PLATFORM_NAME "ZuluSCSI BS2"
# define PLATFORM_REVISION "1.0"
#else
Expand Down
171 changes: 171 additions & 0 deletions lib/ZuluSCSI_platform_RP2040/ZuluSCSI_platform_gpio_Pico.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/**
* ZuluSCSI™ - Copyright (c) 2022 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/>.
**/

// GPIO definitions for ZuluSCSI RP2040-based hardware

#pragma once

#include <hardware/gpio.h>

// SCSI data input/output port.
// The data bus uses external bidirectional buffer, with
// direction controlled by DATA_DIR pin.
#define SCSI_IO_DB0 0
#define SCSI_IO_DB1 1
#define SCSI_IO_DB2 2
#define SCSI_IO_DB3 3
#define SCSI_IO_DB4 4
#define SCSI_IO_DB5 5
#define SCSI_IO_DB6 6
#define SCSI_IO_DB7 7
#define SCSI_IO_DBP 8
#define SCSI_IO_DATA_MASK 0x1FF
#define SCSI_IO_SHIFT 0

// Data direction control
#define SCSI_DATA_DIR 9

// SCSI output status lines
#define SCSI_OUT_IO 22
#define SCSI_OUT_CD 18
#define SCSI_OUT_MSG 20
#define SCSI_OUT_RST 21
#define SCSI_OUT_BSY 27
#define SCSI_OUT_REQ 17
#define SCSI_OUT_SEL 19

// SCSI input status signals
#define SCSI_IN_SEL 18
#define SCSI_IN_ACK 26
#define SCSI_IN_ATN 28
#define SCSI_IN_BSY 20
#define SCSI_IN_RST 21

// Status line outputs for initiator mode
#define SCSI_OUT_ACK 26
#define SCSI_OUT_ATN 28

// Status line inputs for initiator mode
#define SCSI_IN_IO 22
#define SCSI_IN_CD 18
#define SCSI_IN_MSG 20
#define SCSI_IN_REQ 17

// Status LED pins
#define LED_PIN 16
#define LED_ON() sio_hw->gpio_set = 1 << LED_PIN
#define LED_OFF() sio_hw->gpio_clr = 1 << LED_PIN

// SD card pins in SDIO mode
#define SDIO_CLK 10
#define SDIO_CMD 11
#define SDIO_D0 12
#define SDIO_D1 13
#define SDIO_D2 14
#define SDIO_D3 15

// SD card pins in SPI mode
#define SD_SPI spi0
#define SD_SPI_SCK 10
#define SD_SPI_MOSI 11
#define SD_SPI_MISO 12
#define SD_SPI_CS 15

#ifndef ENABLE_AUDIO_OUTPUT
// No spare pins for I2C
// IO expander I2C
// #define GPIO_I2C_SDA 14
// #define GPIO_I2C_SCL 15
#else
// IO expander I2C pins being used as SPI for audio
#define AUDIO_SPI spi1
#define GPIO_EXP_SPARE 14
#define GPIO_EXP_AUDIO 15
#endif

// DIP switch pins
#define HAS_DIP_SWITCHES
#define DIP_INITIATOR 28
#define DIP_DBGLOG 17
#define DIP_TERM 22

// Other pins
#define SWO_PIN 16

// Below are GPIO access definitions that are used from scsiPhy.cpp.

// Write a single SCSI pin.
// Example use: SCSI_OUT(ATN, 1) sets SCSI_ATN to low (active) state.
#define SCSI_OUT(pin, state) \
*(state ? &sio_hw->gpio_clr : &sio_hw->gpio_set) = 1 << (SCSI_OUT_ ## pin)

// Read a single SCSI pin.
// Example use: SCSI_IN(ATN), returns 1 for active low state.
#define SCSI_IN(pin) \
((sio_hw->gpio_in & (1 << (SCSI_IN_ ## pin))) ? 0 : 1)

// Set pin directions for initiator vs. target mode
#define SCSI_ENABLE_INITIATOR() \
(sio_hw->gpio_oe_set = (1 << SCSI_OUT_ACK) | \
(1 << SCSI_OUT_ATN)), \
(sio_hw->gpio_oe_clr = (1 << SCSI_IN_IO) | \
(1 << SCSI_IN_CD) | \
(1 << SCSI_IN_MSG) | \
(1 << SCSI_IN_REQ))

// Enable driving of shared control pins
#define SCSI_ENABLE_CONTROL_OUT() \
(sio_hw->gpio_oe_set = (1 << SCSI_OUT_CD) | \
(1 << SCSI_OUT_MSG))

// Set SCSI data bus to output
#define SCSI_ENABLE_DATA_OUT() \
(sio_hw->gpio_clr = (1 << SCSI_DATA_DIR), \
sio_hw->gpio_oe_set = SCSI_IO_DATA_MASK)

// Write SCSI data bus, also sets REQ to inactive.
#define SCSI_OUT_DATA(data) \
gpio_put_masked(SCSI_IO_DATA_MASK | (1 << SCSI_OUT_REQ), \
g_scsi_parity_lookup[(uint8_t)(data)] | (1 << SCSI_OUT_REQ)), \
SCSI_ENABLE_DATA_OUT()

// Release SCSI data bus and REQ signal
#define SCSI_RELEASE_DATA_REQ() \
(sio_hw->gpio_oe_clr = SCSI_IO_DATA_MASK, \
sio_hw->gpio_set = (1 << SCSI_DATA_DIR) | (1 << SCSI_OUT_REQ))

// Release all SCSI outputs
#define SCSI_RELEASE_OUTPUTS() \
SCSI_RELEASE_DATA_REQ(), \
sio_hw->gpio_oe_clr = (1 << SCSI_OUT_CD) | \
(1 << SCSI_OUT_MSG), \
sio_hw->gpio_set = (1 << SCSI_OUT_IO) | \
(1 << SCSI_OUT_CD) | \
(1 << SCSI_OUT_MSG) | \
(1 << SCSI_OUT_RST) | \
(1 << SCSI_OUT_BSY) | \
(1 << SCSI_OUT_REQ) | \
(1 << SCSI_OUT_SEL)

// Read SCSI data bus
#define SCSI_IN_DATA() \
(~sio_hw->gpio_in & SCSI_IO_DATA_MASK) >> SCSI_IO_SHIFT

7 changes: 5 additions & 2 deletions lib/ZuluSCSI_platform_RP2040/run_pioasm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
# This script regenerates the .pio.h files from .pio

pioasm sdio_RP2040.pio sdio_RP2040.pio.h
pioasm sdio_Pico.pio sdio_Pico.pio.h
pioasm sdio_BS2.pio sdio_BS2.pio.h

pioasm scsi_accel_target_RP2040.pio scsi_accel_target_RP2040.pio.h
pioasm scsi_accel_target_RP2040.pio scsi_accel_target_RPP2040.pio.h
pioasm scsi_accel_target_Pico.pio scsi_accel_target_Pico.pio.h
pioasm scsi_accel_target_BS2.pio scsi_accel_target_BS2.pio.h

pioasm scsi_accel_host_RP2040.pio scsi_accel_host_RP2040.pio.h
pioasm scsi_accel_host_RP2040.pio scsi_accel_host_RP2040.pio.h
pioasm scsi_accel_host_Pico.pio scsi_accel_host_Pico.pio.h
16 changes: 12 additions & 4 deletions lib/ZuluSCSI_platform_RP2040/scsi_accel_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@
#include "scsi_accel_host.h"
#include "ZuluSCSI_platform.h"
#include "ZuluSCSI_log.h"
#include "scsi_accel_host_RP2040.pio.h"
#include <hardware/pio.h>
#include <hardware/dma.h>
#include <hardware/irq.h>
#include <hardware/structs/iobank0.h>
#include <hardware/sync.h>

#ifdef PLATFORM_HAS_INITIATOR_MODE
#ifdef ZULUSCSI_PICO
#include "scsi_accel_host_Pico.pio.h"
#else
#include "scsi_accel_host_RP2040.pio.h"
#endif


#define SCSI_PIO pio0
#define SCSI_SM 0
Expand Down Expand Up @@ -59,14 +64,16 @@ static void scsi_accel_host_config_gpio()
iobank0_hw->io[SCSI_IO_DB6].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IO_DB7].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IO_DBP].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IN_REQ].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_OUT_ACK].ctrl = GPIO_FUNC_SIO;
}
else if (g_scsi_host_state == SCSIHOST_READ)
{
// Data bus and REQ as input, ACK pin as output
pio_sm_set_pins(SCSI_PIO, SCSI_SM, 0x7FF);
pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, 0, 10, false);
pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, 10, 1, true);
pio_sm_set_pins(SCSI_PIO, SCSI_SM, SCSI_IO_DATA_MASK | 1 << SCSI_IN_REQ | 1 << SCSI_OUT_ACK);
pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_IO_DB0, 9, false);
pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_IN_REQ, 1, false);
pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_OUT_ACK, 1, true);

iobank0_hw->io[SCSI_IO_DB0].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IO_DB1].ctrl = GPIO_FUNC_SIO;
Expand All @@ -77,6 +84,7 @@ static void scsi_accel_host_config_gpio()
iobank0_hw->io[SCSI_IO_DB6].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IO_DB7].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IO_DBP].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_IN_REQ].ctrl = GPIO_FUNC_SIO;
iobank0_hw->io[SCSI_OUT_ACK].ctrl = GPIO_FUNC_PIO0;
}
}
Expand Down
46 changes: 46 additions & 0 deletions lib/ZuluSCSI_platform_RP2040/scsi_accel_host_Pico.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
; ZuluSCSI™ - Copyright (c) 2022 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/>.


; RP2040 PIO program for accelerating SCSI initiator / host function
; Run "pioasm scsi_accel_host.pio scsi_accel_host.pio.h" to regenerate the C header from this.
; GPIO mapping:
; - 0-7: DB0-DB7
; - 8: DBP
; Side set is ACK pin

.define REQ 17
.define ACK 26

; Read from SCSI bus using asynchronous handshake.
; Data is returned as 16-bit words that contain the 8 data bits + 1 parity bit.
; Number of bytes to receive minus 1 should be written to TX fifo.
; Number of bytes to receive must be divisible by 2.
.program scsi_host_async_read
.side_set 1

pull block side 1 ; Get number of bytes to receive
mov x, osr side 1 ; Store to counter X

start:
wait 0 gpio REQ side 1 ; Wait for REQ low
in pins, 9 side 0 ; Assert ACK, read GPIO
in null, 7 side 0 ; Padding bits
wait 1 gpio REQ side 0 ; Wait for REQ high
jmp x-- start side 1 ; Deassert ACK, decrement byte count and jump to start
Loading

0 comments on commit caa34d9

Please sign in to comment.