Browse Source

ArdSCSino V1 & V2

ztto 6 years ago
parent
commit
84282b08c6
8 changed files with 797 additions and 67 deletions
  1. 63 67
      ArdSCSino.ino
  2. BIN
      ArdSCSino.png
  3. 734 0
      ArdSCSinoV2.ino
  4. 0 0
      ArdSCSinoV2.png
  5. BIN
      gerber/ArdSCSino.jpg
  6. BIN
      gerber/ArdSCSino.zip
  7. BIN
      gerber/ArdSCSinoV2.zip
  8. BIN
      gerber/size.png

+ 63 - 67
ArdSCSino.ino

@@ -6,9 +6,11 @@
 
 //ENABLE_EXTENDED_TRANSFER_CLASSを1に設定する
 //libraries/SdFat/SdFatConfig.h
-SPIClass SPI_1(1);
-SdFatEX  SD(&SPI_1);
+SPIClass SPI_2(2);
+SdFatEX  SD(&SPI_2);
 
+//#define SPI_SPEED SD_SCK_MHZ(18)
+     
 #define LOG(XX)     //Serial.print(XX)
 #define LOGHEX(XX)  //Serial.print(XX, HEX)
 #define LOGN(XX)    //Serial.println(XX)
@@ -24,27 +26,27 @@ SdFatEX  SD(&SPI_1);
 #define gpio_write(pin,val) gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val)
 #define gpio_read(pin) gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit)
 
-//#define DB0       PB8     // SCSI:DB0
-//#define DB1       PB9     // SCSI:DB1
-//#define DB2       PB10    // SCSI:DB2
-//#define DB3       PB11    // SCSI:DB3
-//#define DB4       PB12    // SCSI:DB4
-//#define DB5       PB13    // SCSI:DB5
-//#define DB6       PB14    // SCSI:DB6
-//#define DB7       PB15    // SCSI:DB7
-//#define DBP       PB0     // SCSI:DBP
-
-#define ATN       PA8      // SCSI:ATN
-#define BSY       PA9      // SCSI:BSY
-#define ACK       PA10     // SCSI:ACK
-#define RST       PA15     // SCSI:RST
-#define MSG       PB3      // SCSI:MSG
-#define SEL       PB4      // SCSI:SEL
-#define CD        PB5      // SCSI:C/D
-#define REQ       PB6      // SCSI:REQ
-#define IO        PB7      // SCSI:I/O
-
-#define SD_CS     PA4      // SDCARD:CS
+//#define DB0       PA0     // SCSI:DB0
+//#define DB1       PA1     // SCSI:DB1
+//#define DB2       PA2     // SCSI:DB2
+//#define DB3       PA3     // SCSI:DB3
+//#define DB4       PA4     // SCSI:DB4
+//#define DB5       PA5     // SCSI:DB5
+//#define DB6       PA6     // SCSI:DB6
+//#define DB7       PA7     // SCSI:DB7
+//#define DBP       PA8     // SCSI:DBP
+
+#define ATN       PB0     // SCSI:ATN
+#define BSY       PB1     // SCSI:BSY
+#define ACK       PB10    // SCSI:ACK
+#define RST       PB11    // SCSI:RST
+#define MSG       PB5     // SCSI:MSG
+#define SEL       PB6     // SCSI:SEL
+#define CD        PB7     // SCSI:C/D
+#define REQ       PB8     // SCSI:REQ
+#define IO        PB9     // SCSI:I/O
+
+#define SD_CS     PB12     // SDCARD:CS
 #define LED       PC13     // LED
 
 #define SCSIID    0                 // SCSI-ID 
@@ -67,22 +69,18 @@ bool          m_msb[256];
 inline byte readIO(void)
 {
   //GPIO(SCSI BUS)初期化
-  //ポート設定レジスタ(下位)
-//  GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
-  //ポート設定レジスタ(上位)
-  GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
-//  GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
-  //ポート入力データレジスタ
-  uint32 ret = GPIOB->regs->IDR;
+  //ポート設定レジスタ(下位  
+  GPIOA->regs->CRL = 0x88888888; // Configure GPIOA[7:0]
+  uint32 ret = GPIOA->regs->IDR;
   byte bret =  0x00;
-  bret |= (!(ret & (1<<15))) << 7;
-  bret |= (!(ret & (1<<14))) << 6;
-  bret |= (!(ret & (1<<13))) << 5;
-  bret |= (!(ret & (1<<12))) << 4;
-  bret |= (!(ret & (1<<11))) << 3;
-  bret |= (!(ret & (1<<10))) << 2;
-  bret |= (!(ret & (1<<9)))  << 1;
-  bret |= (!(ret & (1<<8)))  << 0;
+  bret |= ((!bitRead(ret,7)) << 7);
+  bret |= ((!bitRead(ret,6)) << 6);
+  bret |= ((!bitRead(ret,5)) << 5);
+  bret |= ((!bitRead(ret,4)) << 4);
+  bret |= ((!bitRead(ret,3)) << 3);
+  bret |= ((!bitRead(ret,2)) << 2);
+  bret |= ((!bitRead(ret,1)) << 1);
+  bret |= ((!bitRead(ret,0)) << 0);
   return bret;
 }
 
@@ -93,61 +91,62 @@ inline void writeIO(byte v)
 {
   //GPIO(SCSI BUS)初期化
   //ポート設定レジスタ(下位)
-  GPIOB->regs->CRL |= 0x00000003; // SET OUTPUT W/ PUPD on PA7-PB0 50MHz
+//  GPIOA->regs->CRL = 0x11111111; // Configure GPIOA PP[7:0]10MHz
+  GPIOA->regs->CRL = 0x33333333;  // Configure GPIOA PP[7:0]50MHz
   //ポート設定レジスタ(上位)
-  GPIOB->regs->CRH = 0x33333333; // SET OUTPUT W/ PUPD on PB15-PB8 50MHz
-//  GPIOB->regs->ODR != 0x0000FF00; // SET PULL-UPs on PB15-PB8
+  GPIOA->regs->CRH = 0x00000003;  // Configure GPIOA PP[16:8]50MHz
   uint32 retL =  0x00;
   uint32 retH =  0x00;
+
   if(!parity(v)) {
-    retL |= (1<<0);
+    bitWrite(retL, 8, 1);
   } else {
-    retH |= (1<<0);
+    bitWrite(retH, 8, 1);
   }
   if(v & ( 1 << 7 )) {
-    retL |= (1<<15);
+    bitWrite(retL, 7, 1);
   } else {
-    retH |= (1<<15);
-  }  
+    bitWrite(retH, 7, 1);
+  }
   if(v & ( 1 << 6 )) {
-    retL |= (1<<14);
+    bitWrite(retL, 6, 1);
   } else {
-    retH |= (1<<14);
+    bitWrite(retH, 6, 1);
   }
   if(v & ( 1 << 5 )) {
-    retL |= (1<<13);
+    bitWrite(retL, 5, 1);
   } else {
-    retH |= (1<<13);
+    bitWrite(retH, 5, 1);
   }
   if(v & ( 1 << 4 )) {
-    retL |= (1<<12);
+    bitWrite(retL, 4, 1);
   } else {
-    retH |= (1<<12);
+    bitWrite(retH, 4, 1);
   }
   if(v & ( 1 << 3 )) {
-    retL |= (1<<11);
+    bitWrite(retL, 3, 1);
   } else {
-    retH |= (1<<11);
+    bitWrite(retH, 3, 1);
   }
   if(v & ( 1 << 2 )) {
-    retL |= (1<<10);
+    bitWrite(retL, 2, 1);
   } else {
-    retH |= (1<<10);
+    bitWrite(retH, 2, 1);
   }
   if(v & ( 1 << 1 )) {
-    retL |= (1<<9);
+    bitWrite(retL, 1, 1);
   } else {
-    retH |= (1<<9);
+    bitWrite(retH, 1, 1);
   }
   if(v & ( 1 << 0 )) {
-    retL |= (1<<8);
+    bitWrite(retL, 0, 1);
   } else {
-    retH |= (1<<8);
+    bitWrite(retH, 0, 1);
   }
   //ビットがLOWに設定される
-  GPIOB->regs->BRR = retL ;
+  GPIOA->regs->BRR = retL ;
   // ビットがHIGHに設定される
-  GPIOB->regs->BSRR = retH ;
+  GPIOA->regs->BSRR = retH ;
 }
 
 /*
@@ -182,12 +181,9 @@ void setup()
   gpio_mode(LED, GPIO_OUTPUT_OD);
   gpio_write(LED, low);
 
- //GPIO(SCSI BUS)初期化
+  //GPIO(SCSI BUS)初期化
   //ポート設定レジスタ(下位)
-//  GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
-  //ポート設定レジスタ(上位)
-  GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
-//  GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
+  GPIOA->regs->CRL = 0x888888888; // Configure GPIOA[8:0]
 
   gpio_mode(ATN, GPIO_INPUT_PU);
   gpio_mode(BSY, GPIO_INPUT_PU);

BIN
ArdSCSino.png


+ 734 - 0
ArdSCSinoV2.ino

@@ -0,0 +1,734 @@
+/*
+ * SCSI-HDデバイスエミュレータ
+ */
+#include <SPI.h>
+#include "SdFat.h"
+
+//ENABLE_EXTENDED_TRANSFER_CLASSを1に設定する
+//libraries/SdFat/SdFatConfig.h
+SPIClass SPI_1(1);
+SdFatEX  SD(&SPI_1);
+
+#define LOG(XX)     //Serial.print(XX)
+#define LOGHEX(XX)  //Serial.print(XX, HEX)
+#define LOGN(XX)    //Serial.println(XX)
+#define LOGHEXN(XX) //Serial.println(XX, HEX)
+
+#define high 0
+#define low 1
+
+#define isHigh(XX) ((XX) == high)
+#define isLow(XX) ((XX) != high)
+
+#define gpio_mode(pin,val) gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);
+#define gpio_write(pin,val) gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val)
+#define gpio_read(pin) gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit)
+
+//#define DB0       PB8     // SCSI:DB0
+//#define DB1       PB9     // SCSI:DB1
+//#define DB2       PB10    // SCSI:DB2
+//#define DB3       PB11    // SCSI:DB3
+//#define DB4       PB12    // SCSI:DB4
+//#define DB5       PB13    // SCSI:DB5
+//#define DB6       PB14    // SCSI:DB6
+//#define DB7       PB15    // SCSI:DB7
+//#define DBP       PB0     // SCSI:DBP
+
+#define ATN       PA8      // SCSI:ATN
+#define BSY       PA9      // SCSI:BSY
+#define ACK       PA10     // SCSI:ACK
+#define RST       PA15     // SCSI:RST
+#define MSG       PB3      // SCSI:MSG
+#define SEL       PB4      // SCSI:SEL
+#define CD        PB5      // SCSI:C/D
+#define REQ       PB6      // SCSI:REQ
+#define IO        PB7      // SCSI:I/O
+
+#define SD_CS     PA4      // SDCARD:CS
+#define LED       PC13     // LED
+
+#define SCSIID    0                 // SCSI-ID 
+
+#define BLOCKSIZE 512               // 1BLOCKサイズ
+uint8_t       m_senseKey = 0;       //センスキー
+volatile bool m_isBusReset = false; //バスリセット
+
+#define HDIMG_FILE "HD.HDS"         // HDイメージファイル名
+File          m_file;               // ファイルオブジェクト
+uint32_t      m_fileSize;           // ファイルサイズ
+byte          m_buf[BLOCKSIZE];     // 汎用バッファ
+
+int           m_msc;
+bool          m_msb[256];
+
+/*
+ * IO読み込み.
+ */
+inline byte readIO(void)
+{
+  //GPIO(SCSI BUS)初期化
+  //ポート設定レジスタ(下位)
+//  GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
+  //ポート設定レジスタ(上位)
+  GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
+//  GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
+  //ポート入力データレジスタ
+  uint32 ret = GPIOB->regs->IDR;
+  byte bret =  0x00;
+  bret |= (!(ret & (1<<15))) << 7;
+  bret |= (!(ret & (1<<14))) << 6;
+  bret |= (!(ret & (1<<13))) << 5;
+  bret |= (!(ret & (1<<12))) << 4;
+  bret |= (!(ret & (1<<11))) << 3;
+  bret |= (!(ret & (1<<10))) << 2;
+  bret |= (!(ret & (1<<9)))  << 1;
+  bret |= (!(ret & (1<<8)))  << 0;
+  return bret;
+}
+
+/* 
+ * IO書き込み.
+ */
+inline void writeIO(byte v)
+{
+  //GPIO(SCSI BUS)初期化
+  //ポート設定レジスタ(下位)
+  GPIOB->regs->CRL |= 0x00000003; // SET OUTPUT W/ PUPD on PA7-PB0 50MHz
+  //ポート設定レジスタ(上位)
+  GPIOB->regs->CRH = 0x33333333; // SET OUTPUT W/ PUPD on PB15-PB8 50MHz
+//  GPIOB->regs->ODR != 0x0000FF00; // SET PULL-UPs on PB15-PB8
+  uint32 retL =  0x00;
+  uint32 retH =  0x00;
+  if(!parity(v)) {
+    retL |= (1<<0);
+  } else {
+    retH |= (1<<0);
+  }
+  if(v & ( 1 << 7 )) {
+    retL |= (1<<15);
+  } else {
+    retH |= (1<<15);
+  }  
+  if(v & ( 1 << 6 )) {
+    retL |= (1<<14);
+  } else {
+    retH |= (1<<14);
+  }
+  if(v & ( 1 << 5 )) {
+    retL |= (1<<13);
+  } else {
+    retH |= (1<<13);
+  }
+  if(v & ( 1 << 4 )) {
+    retL |= (1<<12);
+  } else {
+    retH |= (1<<12);
+  }
+  if(v & ( 1 << 3 )) {
+    retL |= (1<<11);
+  } else {
+    retH |= (1<<11);
+  }
+  if(v & ( 1 << 2 )) {
+    retL |= (1<<10);
+  } else {
+    retH |= (1<<10);
+  }
+  if(v & ( 1 << 1 )) {
+    retL |= (1<<9);
+  } else {
+    retH |= (1<<9);
+  }
+  if(v & ( 1 << 0 )) {
+    retL |= (1<<8);
+  } else {
+    retH |= (1<<8);
+  }
+  //ビットがLOWに設定される
+  GPIOB->regs->BRR = retL ;
+  // ビットがHIGHに設定される
+  GPIOB->regs->BSRR = retH ;
+}
+
+/*
+ * 初期化.
+ *  パリティチェック
+ */
+inline int parity(byte val) {
+  val ^= val >> 16;
+  val ^= val >> 8;
+  val ^= val >> 4;
+  val ^= val >> 2;
+  val ^= val >> 1;
+
+  return val & 0x00000001;
+}
+
+/*
+ * 初期化.
+ *  バスの初期化、PINの向きの設定を行う
+ */
+void setup()
+{
+  // PA15 / PB3 / PB4 が使えない
+  // JTAG デバッグ用に使われているからです。
+  disableDebugPorts();
+
+  //シリアル初期化
+  //Serial.begin(9600);
+  //while (!Serial);
+
+  //PINの初期化
+  gpio_mode(LED, GPIO_OUTPUT_OD);
+  gpio_write(LED, low);
+
+ //GPIO(SCSI BUS)初期化
+  //ポート設定レジスタ(下位)
+//  GPIOB->regs->CRL |= 0x000000008; // SET INPUT W/ PUPD on PAB-PB0
+  //ポート設定レジスタ(上位)
+  GPIOB->regs->CRH = 0x88888888; // SET INPUT W/ PUPD on PB15-PB8
+//  GPIOB->regs->ODR = 0x0000FF00; // SET PULL-UPs on PB15-PB8
+
+  gpio_mode(ATN, GPIO_INPUT_PU);
+  gpio_mode(BSY, GPIO_INPUT_PU);
+  gpio_mode(ACK, GPIO_INPUT_PU);
+  gpio_mode(RST, GPIO_INPUT_PU);
+  gpio_mode(SEL, GPIO_INPUT_PU);
+  
+  gpio_mode(MSG, GPIO_OUTPUT_PP);
+  gpio_mode(CD, GPIO_OUTPUT_PP);
+  gpio_mode(REQ, GPIO_OUTPUT_PP);
+  gpio_mode(IO, GPIO_OUTPUT_PP);
+
+  gpio_write(MSG, low);
+  gpio_write(CD, low);
+  gpio_write(REQ, low);
+  gpio_write(IO, low);
+
+  //RSTピンの状態がHIGHからLOWに変わったときに発生
+  attachInterrupt(PIN_MAP[RST].gpio_bit, onBusReset, FALLING);
+  
+  if(!SD.begin(SD_CS,SPI_FULL_SPEED)) {
+    Serial.println("SD initialization failed!");
+    onFalseInit();
+  }
+  //HDイメージファイル
+  m_file = SD.open(HDIMG_FILE, O_RDWR);
+  if(!m_file) {
+    Serial.println("Error: open hdimg");
+    onFalseInit();
+  }
+  m_fileSize = m_file.size();
+  Serial.println("Found Valid HD Image File.");
+  Serial.print(m_fileSize);
+  Serial.println("byte");
+  Serial.print(m_fileSize / 1024);
+  Serial.println("KB");
+  Serial.print(m_fileSize / 1024 / 1024);
+  Serial.println("MB");
+}
+
+/*
+ * 初期化失敗.
+ */
+void onFalseInit(void)
+{
+  while(true) {
+    gpio_write(LED, high);
+    delay(500); 
+    gpio_write(LED, low);
+    delay(500);
+  }
+}
+
+/*
+ * バスリセット割り込み.
+ */
+void onBusReset(void)
+{
+  if(isHigh(gpio_read(RST))) {
+    delayMicroseconds(20);
+    if(isHigh(gpio_read(RST))) {
+      LOGN("BusReset!");
+      m_isBusReset = true;
+    }
+  }
+}
+
+/*
+ * ハンドシェイクで読み込む.
+ */
+byte readHandshake(void)
+{
+  gpio_write(REQ, high);
+  while(isLow(gpio_read(ACK))) {
+    if(m_isBusReset) {
+      return 0;
+    }
+  }
+  byte r = readIO();
+  gpio_write(REQ, low);
+  while(isHigh(gpio_read(ACK))) {
+    if(m_isBusReset) {
+      return 0;
+    }
+  }
+  return r;  
+}
+
+/*
+ * ハンドシェイクで書込み.
+ */
+void writeHandshake(byte d)
+{
+  writeIO(d);
+  gpio_write(REQ, high);
+  while(isLow(gpio_read(ACK))) {
+    if(m_isBusReset) {
+      return;
+    }
+  }
+  gpio_write(REQ, low);
+  while(isHigh(gpio_read(ACK))) {
+    if(m_isBusReset) {
+      return;
+    }
+  }
+}
+
+/*
+ * データインフェーズ.
+ *  データ配列 p を len バイト送信する。
+ */
+void writeDataPhase(int len, byte* p)
+{
+  LOGN("DATAIN PHASE");
+  gpio_write(MSG, low);
+  gpio_write(CD, low);
+  gpio_write(IO, high);
+  for (int i = 0; i < len; i++) {
+    if(m_isBusReset) {
+      return;
+    }
+    writeHandshake(p[i]);
+  }
+}
+
+/* 
+ * データインフェーズ.
+ *  SDカードからの読み込みながら len ブロック送信する。
+ */
+void writeDataPhaseSD(uint32_t adds, uint32_t len)
+{
+  LOGN("DATAIN PHASE(SD)");
+  uint32_t pos = adds * BLOCKSIZE;
+  m_file.seek(pos);
+  gpio_write(MSG, low);
+  gpio_write(CD, low);
+  gpio_write(IO, high);
+  for(uint32_t i = 0; i < len; i++) {
+    m_file.read(m_buf, BLOCKSIZE);
+    for(int j = 0; j < BLOCKSIZE; j++) {
+      if(m_isBusReset) {
+        return;
+      }
+      writeHandshake(m_buf[j]);
+    }
+  }
+}
+
+/*
+ * データアウトフェーズ.
+ *  len ブロック読み込みながら SDカードへ書き込む。
+ */
+void readDataPhaseSD(uint32_t adds, uint32_t len)
+{
+  LOGN("DATAOUT PHASE(SD)");
+  uint32_t pos = adds * BLOCKSIZE;
+  m_file.seek(pos);
+  gpio_write(MSG, low);
+  gpio_write(CD, low);
+  gpio_write(IO, low);
+  for(uint32_t i = 0; i < len; i++) {
+    for(int j = 0; j < BLOCKSIZE; j++) {
+      if(m_isBusReset) {
+        return;
+      }
+      m_buf[j] = readHandshake();
+    }
+    m_file.write(m_buf, BLOCKSIZE);
+  }
+  m_file.flush();
+}
+
+/*
+ * INQUIRY コマンド処理.
+ */
+void onInquiryCommand(byte len)
+{
+  byte buf[36] = {
+    0x00, //デバイスタイプ
+    0x00, //RMB = 0
+    0x01, //ISO,ECMA,ANSIバージョン
+    0x01, //レスポンスデータ形式
+    35 - 4, //追加データ長
+    0, 0, //Reserve
+    0x00, //サポート機能
+    'T', 'N', 'B', ' ', ' ', ' ', ' ', ' ',
+    'A', 'r', 'd', 'S', 'C', 'S', 'i', 'n', 'o', ' ', ' ',' ', ' ', ' ', ' ', ' ',
+    '0', '0', '1', '0',
+  };
+  writeDataPhase(len < 36 ? len : 36, buf);
+}
+
+/*
+ * REQUEST SENSE コマンド処理.
+ */
+void onRequestSenseCommand(byte len)
+{
+  byte buf[18] = {
+    0x70,   //CheckCondition
+    0,      //セグメント番号
+    0x00,   //センスキー
+    0, 0, 0, 0,  //インフォメーション
+    17 - 7 ,   //追加データ長
+    0,
+  };
+  buf[2] = m_senseKey;
+  m_senseKey = 0;
+  writeDataPhase(len < 18 ? len : 18, buf);  
+}
+
+/*
+ * READ CAPACITY コマンド処理.
+ */
+void onReadCapacityCommand(byte pmi)
+{
+  uint32_t bc = m_fileSize / BLOCKSIZE;
+  uint32_t bl = BLOCKSIZE;
+  uint8_t buf[8] = {
+    bc >> 24, bc >> 16, bc >> 8, bc,
+    bl >> 24, bl >> 16, bl >> 8, bl    
+  };
+  writeDataPhase(8, buf);
+}
+
+/*
+ * READ6/10 コマンド処理.
+ */
+byte onReadCommand(uint32_t adds, uint32_t len)
+{
+  LOGN("-R");
+  LOGHEXN(adds);
+  LOGHEXN(len);
+  gpio_write(LED, high);
+  writeDataPhaseSD(adds, len);
+  gpio_write(LED, low);
+  return 0; //sts
+}
+
+/*
+ * WRITE6/10 コマンド処理.
+ */
+byte onWriteCommand(uint32_t adds, uint32_t len)
+{
+  LOGN("-W");
+  LOGHEXN(adds);
+  LOGHEXN(len);
+  gpio_write(LED, high);
+  readDataPhaseSD(adds, len);
+  gpio_write(LED, low);
+  return 0; //sts
+}
+
+/*
+ * MODE SENSE コマンド処理.
+ */
+void onModeSenseCommand(byte dbd, int pageCode, uint32_t len)
+{
+  memset(m_buf, 0, sizeof(m_buf)); 
+  int a = 4;
+  if(dbd == 0) {
+    uint32_t bc = m_fileSize / BLOCKSIZE;
+    uint32_t bl = BLOCKSIZE;
+    byte c[8] = {
+      0,//デンシティコード
+      bc >> 16, bc >> 8, bc,
+      0, //Reserve
+      bl >> 16, bl >> 8, bl    
+    };
+    memcpy(&m_buf[4], c, 8);
+    a += 8;
+    m_buf[3] = 0x08;
+  }
+  switch(pageCode) {
+  case 0x3F:
+  case 0x03:  //ドライブパラメータ
+    m_buf[a + 0] = 0x03; //ページコード
+    m_buf[a + 1] = 0x16; // ページ長
+    m_buf[a + 11] = 0x3F;//セクタ数/トラック
+    a += 24;
+    if(pageCode != 0x3F) {
+      break;
+    }
+  case 0x04:  //ドライブパラメータ
+    {
+      uint32_t bc = m_fileSize / BLOCKSIZE;
+      m_buf[a + 0] = 0x04; //ページコード
+      m_buf[a + 1] = 0x16; // ページ長
+      m_buf[a + 2] = bc >> 16;// シリンダ長
+      m_buf[a + 3] = bc >> 8;
+      m_buf[a + 4] = bc;
+      m_buf[a + 5] = 1;   //ヘッド数
+      a += 24;
+    }
+    if(pageCode != 0x3F) {
+      break;
+    }
+  default:
+    break;
+  }
+  m_buf[0] = a - 1;
+  writeDataPhase(len < a ? len : a, m_buf);
+}
+
+/*
+ * MsgIn2.
+ */
+void MsgIn2(int msg)
+{
+  LOGN("MsgIn2");
+  gpio_write(MSG, high);
+  gpio_write(CD, high);
+  gpio_write(IO, high);
+  writeHandshake(msg);
+}
+
+/*
+ * MsgOut2.
+ */
+void MsgOut2()
+{
+  LOGN("MsgOut2");
+  gpio_write(MSG, high);
+  gpio_write(CD, high);
+  gpio_write(IO, low);
+  m_msb[m_msc] = readHandshake();
+  m_msc++;
+  m_msc %= 256;
+}
+
+/*
+ * メインループ.
+ */
+void loop() 
+{
+  int sts = 0;
+  int msg = 0;
+
+  //BSY,SELが+はバスフリー
+  // セレクションチェック
+  // BSYが-の間ループ
+  if(isHigh(gpio_read(BSY))) {
+    return;
+  }
+  // SELが+の間ループ
+  if(isLow(gpio_read(SEL))) {
+    return;
+  }
+  // BSY+ SEL-
+  byte db = readIO();  
+  if((db & (1 << SCSIID)) == 0) {
+    return;
+  }
+
+  LOGN("Selection");
+  m_isBusReset = false;
+  // セレクトされたらBSYを-にする
+  gpio_mode(BSY, GPIO_OUTPUT_PP);
+  gpio_write(BSY, high);
+  while(isHigh(gpio_read(SEL))) {
+    if(m_isBusReset) {
+      goto BusFree;
+    }
+  }
+  if(isHigh(gpio_read(ATN))) {
+    bool syncenable = false;
+    int syncperiod = 50;
+    int syncoffset = 0;
+    m_msc = 0;
+    memset(m_msb, 0x00, sizeof(m_msb));
+    while(isHigh(gpio_read(ATN))) {
+      MsgOut2();
+    }
+    for(int i = 0; i < m_msc; i++) {
+      // ABORT
+      if (m_msb[i] == 0x06) {
+        goto BusFree;
+      }
+      // BUS DEVICE RESET
+      if (m_msb[i] == 0x0C) {
+        syncoffset = 0;
+        goto BusFree;
+      }
+      // IDENTIFY
+      if (m_msb[i] >= 0x80) {
+      }
+      // 拡張メッセージ
+      if (m_msb[i] == 0x01) {
+        // 同期転送が可能な時だけチェック
+        if (!syncenable || m_msb[i + 2] != 0x01) {
+          MsgIn2(0x07);
+          break;
+        }
+        // Transfer period factor(50 x 4 = 200nsに制限)
+        syncperiod = m_msb[i + 3];
+        if (syncperiod > 50) {
+          syncoffset = 50;
+        }
+        // REQ/ACK offset(16に制限)
+        syncoffset = m_msb[i + 4];
+        if (syncoffset > 16) {
+          syncoffset = 16;
+        }
+        // STDR応答メッセージ生成
+        MsgIn2(0x01);
+        MsgIn2(0x03);
+        MsgIn2(0x01);
+        MsgIn2(syncperiod);
+        MsgIn2(syncoffset);
+        break;
+      }
+    }
+  }
+
+  LOGN("Command");
+  gpio_write(MSG, low);
+  gpio_write(CD, high);
+  gpio_write(IO, low);
+  int len;
+  byte cmd[12];
+  cmd[0] = readHandshake();
+  LOGHEX(cmd[0]);
+  len = 1;
+  switch(cmd[0] >> 5) {
+  case 0b000:
+    len = 6;
+    break;
+  case 0b001:
+    len = 10;
+    break;
+  case 0b010:
+    len = 10;
+    break;
+  case 0b101:
+    len = 12;
+    break;
+  default:
+    break;
+  }
+  for(int i = 1; i < len; i++ ) {
+    cmd[i] = readHandshake();
+    LOGHEX(cmd[i]);
+  }
+  LOGN("");
+
+  switch(cmd[0]) {
+  case 0x00:
+    LOGN("[Test Unit]");
+    break;
+  case 0x01:
+    LOGN("[Rezero Unit]");
+    break;
+  case 0x03:
+    LOGN("[RequestSense]");
+    onRequestSenseCommand(cmd[4]);
+    break;
+  case 0x04:
+    LOGN("[FormatUnit]");
+    break;
+  case 0x06:
+    LOGN("[FormatUnit]");
+    break;
+  case 0x07:
+    LOGN("[ReassignBlocks]");
+    break;
+  case 0x08:
+    LOGN("[Read6]");
+    sts = onReadCommand((((uint32_t)cmd[1] & 0x1F) << 16) | ((uint32_t)cmd[2] << 8) | cmd[3], (cmd[4] == 0) ? 0x100 : cmd[4]);
+    break;
+  case 0x0A:
+    LOGN("[Write6]");
+    sts = onWriteCommand((((uint32_t)cmd[1] & 0x1F) << 16) | ((uint32_t)cmd[2] << 8) | cmd[3], (cmd[4] == 0) ? 0x100 : cmd[4]);
+    break;
+  case 0x0B:
+    LOGN("[Seek6]");
+    break;
+  case 0x12:
+    LOGN("[Inquiry]");
+    onInquiryCommand(cmd[4]);
+    break;
+  case 0x1A:
+    LOGN("[ModeSense6]");
+    onModeSenseCommand(cmd[1]&0x80, cmd[2] & 0x3F, cmd[4]);
+    break;
+  case 0x1B:
+    LOGN("[StartStopUnit]");
+    break;
+  case 0x1E:
+    LOGN("[PreAllowMed.Removal]");
+    break;
+  case 0x25:
+    LOGN("[ReadCapacity]");
+    onReadCapacityCommand(cmd[8]);
+    break;
+  case 0x28:
+    LOGN("[Read10]");
+    sts = onReadCommand(((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
+    break;
+  case 0x2A:
+    LOGN("[Write10]");
+    sts = onWriteCommand(((uint32_t)cmd[2] << 24) | ((uint32_t)cmd[3] << 16) | ((uint32_t)cmd[4] << 8) | cmd[5], ((uint32_t)cmd[7] << 8) | cmd[8]);
+    break;
+  case 0x2B:
+    LOGN("[Seek10]");
+    break;
+  case 0x5A:
+    LOGN("[ModeSense10]");
+    onModeSenseCommand(cmd[1] & 0x80, cmd[2] & 0x3F, ((uint32_t)cmd[7] << 8) | cmd[8]);
+    break;
+  default:
+    LOGN("[*Unknown]");
+    sts = 2;
+    m_senseKey = 5;
+    break;
+  }
+  if(m_isBusReset) {
+     goto BusFree;
+  }
+
+  LOGN("Sts");
+  gpio_write(MSG, low);
+  gpio_write(CD, high);
+  gpio_write(IO, high);
+  writeHandshake(sts);
+  if(m_isBusReset) {
+     goto BusFree;
+  }
+
+  LOGN("MsgIn");
+  gpio_write(MSG, high);
+  gpio_write(CD, high);
+  gpio_write(IO, high);
+  writeHandshake(msg);
+
+BusFree:
+  LOGN("BusFree");
+  m_isBusReset = false;
+  gpio_write(REQ, low);
+  gpio_write(MSG, low);
+  gpio_write(CD, low);
+  gpio_write(IO, low);
+//  gpio_write(BSY, low);
+  gpio_mode(BSY, GPIO_INPUT_PU);
+}

+ 0 - 0
pin.png → ArdSCSinoV2.png


BIN
gerber/ArdSCSino.jpg


BIN
gerber/ArdSCSino.zip


BIN
gerber/ArdSCSinoV2.zip


BIN
gerber/size.png