public int ReadWrite(byte[] dSend, ref byte[] dRecv, int length) { if (length > dSend.Length || length > dRecv.Length) { throw new ArgumentOutOfRangeException("length", "The length is over data length"); } if (ftHandle == IntPtr.Zero) { throw new InvalidOperationException("SPI device not initialized"); } byte OpCode = 0x00; switch (mode) { case SPIMode.MODE0: OpCode = 0x31; //Out Falling Edge break; case SPIMode.MODE1: OpCode = 0x34; //Out Rising Edge break; } int lenremain = length, i = 0, szTransfered = 0; uint szToTransfer = 0, szSent = 0, szRead = 0; IntPtr ptrIn, ptrOut; byte[] dIn, dOut; _CS_enable(true); while (lenremain > 0) { szToTransfer = (lenremain > 65536) ? 65536 : (uint)lenremain; lenremain -= (int)szToTransfer; dIn = new byte[szToTransfer]; dOut = new byte[szToTransfer + 3]; dOut[0] = OpCode; dOut[1] = (byte)((szToTransfer - 1) & 0xff); dOut[2] = (byte)(((szToTransfer - 1) >> 8) & 0xff); Array.Copy(dSend, i * 65536, dOut, 3, szToTransfer); ptrOut = Marshal.AllocHGlobal((int)szToTransfer + 3); Marshal.Copy(dOut, 0, ptrOut, dOut.Length); status = DllWraper.FT_Write(ftHandle, ptrOut, szToTransfer + 3, ref szSent); System.Threading.Thread.Sleep(20); do { status = DllWraper.FT_GetQueueStatus(ftHandle, ref szRead); System.Threading.Thread.Sleep(20); } while (szRead != szToTransfer && status == FTStatus.OK); ptrIn = Marshal.AllocHGlobal((int)szToTransfer); status = DllWraper.FT_Read(ftHandle, ptrIn, szToTransfer, ref szRead); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Read data"); } Marshal.Copy(ptrIn, dIn, 0, (int)szToTransfer); Array.Copy(dIn, 0, dRecv, i * 65536, szToTransfer); szTransfered += (int)szRead; Marshal.FreeHGlobal(ptrIn); Marshal.FreeHGlobal(ptrOut); i++; } _CS_enable(false); return(szTransfered); }
/// <summary> /// Initialize the MPSSE /// </summary> /// <param name="index">the device index</param> /// <exception cref="FTDIException"></exception> public void FT_MPSSE_Init(int index = 0) { status = DllWraper.FT_Open(index, ref ftHandle); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Open FTDI device"); } status = DllWraper.FT_ResetDevice(ftHandle); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Reset FTDI device"); } status = DllWraper.FT_SetUSBParameters(ftHandle, 10000, 10000); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Set USB on FTDI"); } status = DllWraper.FT_SetLatencyTimer(ftHandle, 2); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Set Latency in FTDI"); } status = DllWraper.FT_SetFlowControl(ftHandle, 0x0100, 0x00, 0x00); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Set Flow Control in FTDI"); } status = DllWraper.FT_SetBitMode(ftHandle, 0, 0); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Reset FTDI Chip"); } status = DllWraper.FT_SetBitMode(ftHandle, 0, 2); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Initialize MPSSE on FTDI"); } status = DllWraper.FT_Purge(ftHandle, 3); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Initialize MPSSE on FTDI"); } // Config MPSSE byte[] outBuf = new byte[8]; byte[] inBuf = new byte[8]; uint szSent = 0, szRead = 0; IntPtr inptr = Marshal.AllocHGlobal(inBuf.Length); IntPtr outptr = Marshal.AllocHGlobal(outBuf.Length); outBuf[0] = 0x84; //Loopback Marshal.Copy(outBuf, 0, outptr, 8); status = DllWraper.FT_Write(ftHandle, outptr, 1, ref szSent); //Check Receive Data status = DllWraper.FT_GetQueueStatus(ftHandle, ref szRead); if (szRead != 0) { DllWraper.FT_SetBitMode(ftHandle, 0, 0); DllWraper.FT_Close(ftHandle); ftHandle = IntPtr.Zero; throw new FTDIException("MPSSE Initialization Error, MPSSE receive buffer not zero"); } //Bad Command outBuf[0] = 0xAB; Marshal.Copy(outBuf, 0, outptr, 8); status = DllWraper.FT_Write(ftHandle, outptr, 1, ref szSent); do { status = DllWraper.FT_GetQueueStatus(ftHandle, ref szRead); } while (szRead == 0 && status == FTStatus.OK); status = DllWraper.FT_Read(ftHandle, inptr, szRead, ref szRead); Marshal.Copy(inptr, inBuf, 0, (int)szRead); bool echod = false; for (int i = 0; i < szRead - 1; i++) { if (inBuf[i] == 0xFA && (inBuf[i + 1] == 0xAB)) { echod = true; break; } } if (!echod) { DllWraper.FT_Close(ftHandle); throw new FTDIException("Error in Sync the MPSSE"); } outBuf[0] = 0x85; Marshal.Copy(outBuf, 0, outptr, 1); status = DllWraper.FT_Write(ftHandle, outptr, 1, ref szSent); status = DllWraper.FT_GetQueueStatus(ftHandle, ref szRead); if (szRead != 0) { DllWraper.FT_SetBitMode(ftHandle, 0, 0); DllWraper.FT_Close(ftHandle); throw new FTDIException("MPSSE Receive Buffer not Empty"); } outBuf[0] = 0x8A; //Disable Clock Divide outBuf[1] = 0x8D; //Disable 3 phase data clocking outBuf[2] = 0x97; //Disable adaptive clocking Marshal.Copy(outBuf, 0, outptr, 3); status = DllWraper.FT_Write(ftHandle, outptr, 3, ref szSent); // Clean the unmanaged memory Marshal.FreeHGlobal(outptr); Marshal.FreeHGlobal(inptr); }
/// <summary> /// Read Data from SPI /// </summary> /// <param name="data">the read data</param> /// <param name="length">The length of data to read</param> /// <returns>The real read bytes</returns> public int Read(ref byte[] data, int length) { if (data.Length < length) { throw new IndexOutOfRangeException("The data doesn't have enough memory"); } if (ftHandle == IntPtr.Zero) { throw new InvalidOperationException("SPI Driver not initialized"); } byte[] ftcmd = new byte[3]; IntPtr ptrCmd = Marshal.AllocHGlobal(3); IntPtr ptrRead; switch (mode) { case SPIMode.MODE0: ftcmd[0] = 0x20; //In in rising edge break; case SPIMode.MODE1: ftcmd[0] = 0x24; // In in falling edge break; } int lenreamin = length, i = 0, szReceiveAll = 0; uint szSent = 0, szToRead = 0, szRead = 0; _CS_enable(true); while (lenreamin > 0) { szToRead = (lenreamin > 65536) ? 65536 : (uint)lenreamin; lenreamin -= (int)szToRead; ptrRead = Marshal.AllocHGlobal((int)szToRead); ftcmd[1] = (byte)((szToRead - 1) & 0x00ff); ftcmd[2] = (byte)(((szToRead - 1) >> 8) & 0x00ff); Marshal.Copy(ftcmd, 0, ptrCmd, 3); status = DllWraper.FT_Write(ftHandle, ptrCmd, 3, ref szSent); if (status != FTStatus.OK) { throw new FTDIException(status, "Error in sending reading command"); } do { status = DllWraper.FT_GetQueueStatus(ftHandle, ref szRead); System.Threading.Thread.Sleep(20); } while (szRead != szToRead && status == FTStatus.OK); status = DllWraper.FT_Read(ftHandle, ptrRead, szToRead, ref szRead); if (status != FTStatus.OK) { throw new FTDIException(status, "Cannot Read data"); } Marshal.Copy(ptrRead, data, i * 65536, (int)szRead); szReceiveAll += (int)szRead; Marshal.FreeHGlobal(ptrRead); } _CS_enable(false); return(szReceiveAll); }