| 
					
				 | 
			
			
				@@ -0,0 +1,724 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * SCSI-HDデバイスエミュレータ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <SPI.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <SdFat.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//ENABLE_EXTENDED_TRANSFER_CLASSを1に設定する 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//libraries/SdFat/SdFatConfig.h 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+SPIClass SPI_2(2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//SdFat  SD(2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+SdFatEX  SD(&SPI_2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//#define SPI_SPEED SD_SCK_MHZ(18) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define LOG(XX)    //Serial.println(XX) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define LOGHEX(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       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  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  byte bret =  0x00; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPIOA->regs->CRL = 0x88888888; // Configure GPIOA[7:0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uint32 ret = GPIOA->regs->IDR; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/*  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * IO書き込み. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+inline void writeIO(byte v) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  GPIOA->regs->CRL = 0x11111111; // Configure GPIOA PP[7:0]10MHz 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPIOA->regs->CRL = 0x33333333;  // Configure GPIOA PP[7:0]50MHz 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPIOA->regs->CRH = 0x00000003;  // Configure GPIOA PP[16:8]50MHz 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uint32 retL =  0x00; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uint32 retH =  0x00; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(!parity(v)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 8, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 8, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 7 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 7, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 7, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 6 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 6, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 6, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 5 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 5, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 5, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 4 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 4, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 4, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 3 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 3, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 3, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 2 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 2, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 2, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 1 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 1, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 1, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(v & ( 1 << 0 )) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retL, 0, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bitWrite(retH, 0, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //ビットがLOWに設定される 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPIOA->regs->BRR = retL ; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // ビットがHIGHに設定される 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPIOA->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(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+//  afio_cfg_debug_ports(AFIO_DEBUG_NONE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //シリアル初期化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  Serial.begin(9600); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  while (!Serial); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //PINの初期化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_mode(LED, GPIO_OUTPUT_OD); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(LED, low); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  //GPIO(SCSI BUS)初期化 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  GPIOA->regs->CRL = 0x888888888; // Configure GPIOA[8:0] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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_READ | O_WRITE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  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))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      LOG("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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("-R"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOGHEX(adds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOGHEX(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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("-W"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOGHEX(adds); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOGHEX(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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("MsgIn2"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(MSG, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(CD, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(IO, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  writeHandshake(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * MsgOut2. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void MsgOut2() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  switch(cmd[0]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x00: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[Test Unit]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x01: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[Rezero Unit]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x03: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[RequestSense]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onRequestSenseCommand(cmd[4]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x04: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[FormatUnit]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x06: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[FormatUnit]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x07: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[ReassignBlocks]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x08: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[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: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[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: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[Seek6]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x12: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[Inquiry]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onInquiryCommand(cmd[4]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x1A: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[ModeSense6]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onModeSenseCommand(cmd[1]&0x80, cmd[2] & 0x3F, cmd[4]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x1B: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[StartStopUnit]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x1E: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[PreAllowMed.Removal]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x25: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[ReadCapacity]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onReadCapacityCommand(cmd[8]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x28: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[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: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[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: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[Seek10]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  case 0x5A: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[ModeSense10]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    onModeSenseCommand(cmd[1] & 0x80, cmd[2] & 0x3F, ((uint32_t)cmd[7] << 8) | cmd[8]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  default: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    LOG("[*Unknown]"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sts = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    m_senseKey = 5; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(m_isBusReset) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     goto BusFree; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("Sts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(MSG, low); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(CD, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(IO, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  writeHandshake(sts); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if(m_isBusReset) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     goto BusFree; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("MsgIn"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(MSG, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(CD, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpio_write(IO, high); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  writeHandshake(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+BusFree: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  LOG("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); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |