Ejemplo n.º 1
0
        // Function to output an entire frame to the USB3 Chip
        public bool Send_test_sequence(bool altOn)
        {
            FTDI.FT_STATUS ftStatus       = FTDI.FT_STATUS.FT_OK;
            FTDI           d3xxDevice     = new FTDI();
            bool           bLoopbackFails = false;
            UInt32         words_per_line = 40;

            byte[] line_one     = new byte[words_per_line];
            byte[] line_two     = new byte[words_per_line];
            UInt32 bytesWritten = 0;
            bool   TestResult   = false;

            //var pOverlapped = new System.Threading.NativeOverlapped();



            //if (!TestLoopbackPrepare.bBasicLoopbackWorking)
            //{
            //    Debug.WriteLine("ERROR: Basic Loopback failed, test will be skipped!");
            //    return TestResult;
            //}

            // Open our FTDI601 USB3 Chip
            ftStatus = d3xxDevice.OpenBySerialNumber(FTDI.FT_60XCONFIGURATION_DEFAULT_SERIALNUMBER);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Debug.WriteLine("OpenByIndex failed! ftStatus={0}", ftStatus);
                return(TestResult);
            }



            ///////////////////////////////////////////////
            ////////////// Chip Configuration /////////////
            ///////////////////////////////////////////////

            //// Set our config Values
            //var conf = new FTDI.FT_60XCONFIGURATION
            //{
            //    // Set default values
            //    VendorID = FTDI.FT_60XCONFIGURATION_DEFAULT_VENDORID,
            //    ProductID = FTDI.FT_60XCONFIGURATION_DEFAULT_PRODUCTID_601,
            //    PowerAttributes = FTDI.FT_60XCONFIGURATION_DEFAULT_POWERATTRIBUTES,
            //    PowerConsumption = FTDI.FT_60XCONFIGURATION_DEFAULT_POWERCONSUMPTION,
            //    BatteryChargingGPIOConfig = FTDI.FT_60XCONFIGURATION_DEFAULT_BATTERYCHARGING,
            //    OptionalFeatureSupport = FTDI.FT_60XCONFIGURATION_DEFAULT_OPTIONALFEATURE,
            //    MSIO_Control = FTDI.FT_60XCONFIGURATION_DEFAULT_MSIOCONTROL,
            //    GPIO_Control = FTDI.FT_60XCONFIGURATION_DEFAULT_GPIOCONTROL,
            //    FlashEEPROMDetection = 0,
            //    SerialNumber = FTDI.FT_60XCONFIGURATION_DEFAULT_SERIALNUMBER,
            //    // Set custom values
            //    FIFOMode = (byte)FTDI.FT_60XCONFIGURATION_FIFO_MODE.MODE_245,
            //    //FIFOClock = (byte)FTDI.FT_60XCONFIGURATION_FIFO_CLK.CLK_100_MHZ:
            //    FIFOClock = (byte)FTDI.FT_60XCONFIGURATION_FIFO_CLK.CLK_66_MHZ,
            //    ChannelConfig = (byte)FTDI.FT_60XCONFIGURATION_CHANNEL_CONFIG.ONE_OUTPIPE,
            //    Manufacturer = "Awesome Inc",
            //    Description = "Being Awesome"
            //};
            ////conf.SerialNumber = "123456789012345";
            //ftStatus = d3xxDevice.SetChipConfiguration(conf);
            //if (ftStatus != FTDI.FT_STATUS.FT_OK) { Console.WriteLine("Fatal Error"); };
            //// Need to close afterwards and wait at least 2s before re-opening (from datasheet)
            //ftStatus = d3xxDevice.Close();
            //if (ftStatus != FTDI.FT_STATUS.FT_OK) { Console.WriteLine("Fatal Error"); };
            //Thread.Sleep(2000);
            //ftStatus = d3xxDevice.OpenByIndex(0);
            //if (ftStatus != FTDI.FT_STATUS.FT_OK) { Console.WriteLine("OpenByIndex failed! ftStatus={0}", ftStatus); return TestResult; }

            //// Read what is set
            //ftStatus = d3xxDevice.GetChipConfiguration(conf);
            //if (ftStatus != FTDI.FT_STATUS.FT_OK) { Console.WriteLine("Fatal Error"); };
            //// Print results
            //Console.WriteLine("\tChip Configuration");
            //Console.WriteLine("\tVendorID : 0x{0:X4}", conf.VendorID);
            //Console.WriteLine("\tProductID : 0x{0:X4}", conf.ProductID);
            //Console.WriteLine("\tManufacturer : " + conf.Manufacturer);
            //Console.WriteLine("\tDescription : " + conf.Description);
            //Console.WriteLine("\tSerialNumber : " + conf.SerialNumber);
            //Console.WriteLine("\tPowerAttributes : 0x{0:X2}", conf.PowerAttributes);
            //Console.WriteLine("\tPowerConsumption : 0x{0:X4}", conf.PowerConsumption);
            //Console.WriteLine("\tFIFOClock : 0x{0:X4}", conf.FIFOClock);
            //Console.WriteLine("\tFIFOMode : 0x{0:X2}", conf.FIFOMode);
            //Console.WriteLine("\tChannelConfig : 0x{0:X2}", conf.ChannelConfig);
            //Console.WriteLine("\tOptionalFeatureSupport : 0x{0:X4}", conf.OptionalFeatureSupport);
            //Console.WriteLine("\tBatteryChargingGPIOConfig: 0x{0:X2}", conf.BatteryChargingGPIOConfig);
            //Console.WriteLine("\tMSIO_Control : 0x{0:X8}", conf.MSIO_Control);
            //Console.WriteLine("\tGPIO_Control : 0x{0:X8}", conf.GPIO_Control);
            //Console.WriteLine("\tFlashEEPROMDetection : 0x{0:X2}", conf.FlashEEPROMDetection);
            //if (conf.FlashEEPROMDetection > 0)
            //{
            //    bool bROM = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.ROM)) > 0;
            //    Debug.WriteLine("\t\tMEMORY : {0}", bROM ? "Rom" : "Flash");
            //    if (bROM)
            //    {
            //        bool bMemoryExist = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.MEMORY_NOTEXIST)) > 0;
            //        Debug.WriteLine("\t\tMEMORY_NOTEXIST : {0}", bMemoryExist ? "Invalid" : "Valid");
            //    }
            //    bool bCustom = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.CUSTOM)) > 0;
            //    Debug.WriteLine("\t\tVALUES : {0}", bCustom ? "Custom" : "Default");
            //    if (!bCustom)
            //    { // Default configuration
            //        bool bGPIO0 = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.GPIO_0)) > 0;
            //        bool bGPIO1 = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.GPIO_1)) > 0;
            //        Debug.WriteLine("\t\tGPIO_0 : {0}", bGPIO0 ? "High" : "Low"); Debug.WriteLine("\t\tGPIO_1 : {0}", bGPIO1 ? "High" : "Low");
            //        if (bGPIO0 && bGPIO1)
            //        {
            //            Debug.WriteLine("\t\tChannel : 4 channels, 600 mode");
            //        }
            //        else if (!bGPIO0 && bGPIO1)
            //        {
            //            Debug.WriteLine("\t\tChannel : 2 channels, 600 mode");
            //        }
            //        else if (bGPIO0 && !bGPIO1)
            //        {
            //            Debug.WriteLine("\t\tChannel : 1 channel, 600 mode");
            //        }
            //        else if (!bGPIO0 && !bGPIO1)
            //        {
            //            Debug.WriteLine("\t\tChannel : 1 channel, 245 mode");
            //        }
            //    }
            //    else
            //    { // Custom configuration
            //        bool bInvalidData = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.CUSTOMDATA_INVALID)) > 0;
            //        bool bInvalidDataChecksum = (conf.FlashEEPROMDetection & (1 << (byte)FTDI.FT_60XCONFIGURATION_FLASH_ROM_BIT.CUSTOMDATACHKSUM_INVALID)) > 0;
            //        Debug.WriteLine("\t\tCUSTOMDATA : {0}", bInvalidData ? "Invalid" : "Valid"); Debug.WriteLine("\t\tCUSTOMDATACHKSUM: {0}", bInvalidDataChecksum ? "Invalid" : "Valid");
            //    }
            //}
            ////ftStatus = d3xxDevice.Close();
            ////if (ftStatus != FTDI.FT_STATUS.FT_OK) { Console.WriteLine("Fatal Error"); };



            // Disable Input Timeouts
            //d3xxDevice.SetPipeTimeout(0x82, 0);
            //PipeTimeout.Disable(d3xxDevice, 0x82);

            // Disable tiomeouts on our output pipe
            d3xxDevice.SetPipeTimeout(0x02, 0);
            //d3xxDevice.SetPipeTimeout(0x02, 500);

            // We drive the entire FPGA design off of the FIFO's 100MHz vlock, therefore we want clock to run all the time
            // Set a timeout of 0 to achieve this, without this, clock will only be on for 10 seconds
            d3xxDevice.SetSuspendTimeout(0);


            // Diagnostics Code
            System.Collections.Generic.List <FT_PIPE_INFORMATION> info = d3xxDevice.DataPipeInformation;
            //d3xxDevice.ResetChipConfiguration();
            //var conf = new FTDI.FT_60XCONFIGURATION();
            //FT_STATUS status = d3xxDevice.GetChipConfiguration(conf);



            // Setup GPIO
            UInt32 ulDirection = ((byte)FTDI.FT_GPIO_DIRECTION.OUT << (byte)FTDI.FT_GPIO.GPIO_0) |
                                 ((byte)FTDI.FT_GPIO_DIRECTION.OUT << (byte)FTDI.FT_GPIO.GPIO_1);
            //UInt32 ulMask = (UInt32)FTDI.FT_GPIO_MASK.GPIO_ALL;
            //ftStatus = d3xxDevice.EnableGPIO(ulMask, ulDirection);
            //if (ftStatus != FTDI.FT_STATUS.FT_OK)
            //{
            //    Debug.WriteLine("EnableGPIO failed! ftStatus={0}", ftStatus);
            //    return TestResult;
            //}

            // Write next_frame_rdy signal
            //ftStatus = d3xxDevice.EnableGPIO((UInt32)FTDI.FT_GPIO_MASK.GPIO_ALL, ulDirection);
            //ftStatus = d3xxDevice.WriteGPIO((UInt32)FTDI.FT_GPIO_MASK.GPIO_1, 3);
            //ftStatus = d3xxDevice.WriteGPIO((UInt32)FTDI.FT_GPIO_MASK.GPIO_1, 0);
            //ftStatus = d3xxDevice.EnableGPIO((UInt32)0, ulDirection);

            //for (UInt32 i = 0; i < 100; i++)
            //{


            /////////////////////////////////////////////
            ///////////// Single Lines Test /////////////
            /////////////////////////////////////////////
            //// Line 1
            //for (UInt32 j = 0; j < line_one.Length; j++)
            //{
            //    //line_one[j] = (byte)(0xAA);
            //    line_one[j] = (byte)(j << 4);
            //}
            //// Line 2
            //for (UInt32 j = 0; j < line_two.Length; j++)
            //{
            //    //line_two[j] = (byte)(0x55);
            //    line_two[j] = (byte)(j << 4);
            //}
            //// Write Line1
            //ftStatus = d3xxDevice.WritePipe(0x02, line_one, (UInt32)line_one.Length, ref bytesWritten);
            //// Write Line2
            //ftStatus = d3xxDevice.WritePipe(0x02, line_two, (UInt32)line_two.Length, ref bytesWritten);



            ///////////////////////////////////////////
            /////////// Entire Image Test /////////////
            ///////////////////////////////////////////

            //bool altOn = true;
            //altOn = false;

            //uint lines_per_frame = 1280;
            // Just use 50 lines for now (less than 8kb, 1 buffer, until get to the bottom of the USB FIFO issue)
            //uint lines_per_frame = 256+2+3;// 1280;// 1304;// 66;// 1304;// 1280;
            //uint lines_per_frame = 256+2+3;
            //uint lines_per_frame = 512 - 4; // This can varyu, no idea why or how
            uint lines_per_frame       = 1280;// 32;// 512;// 1280;//512;// 256;// 64;//32;// 64;// 2;// 16;// 6;// 64; // This can varyu, no idea why or how
            uint bytes_per_line        = words_per_line * 4;
            uint total_bytes_per_frame = lines_per_frame * bytes_per_line;

            byte[] Frame1 = new byte[total_bytes_per_frame];
            // Load up all of our 32-bit words with alternating data
            // Iterate through 8 bytes at a time
            for (int curr_byte = 0; curr_byte < (total_bytes_per_frame - 7); curr_byte += 8)
            {
                if (altOn)
                {
                    //// Pattern on even 32-bit words
                    //Frame1[curr_byte + 0] = 0xAA;
                    //Frame1[curr_byte + 1] = 0xAA;
                    //Frame1[curr_byte + 2] = 0xAA;
                    //Frame1[curr_byte + 3] = 0xAA;
                    //// Pattern on odd 32-bit words
                    //Frame1[curr_byte + 4] = 0x55;
                    //Frame1[curr_byte + 5] = 0x55;
                    //Frame1[curr_byte + 6] = 0x55;
                    //Frame1[curr_byte + 7] = 0x55;

                    //// Pattern on even 32-bit words
                    //Frame1[curr_byte + 0] = 0xFF;
                    //Frame1[curr_byte + 1] = 0xFF;
                    //Frame1[curr_byte + 2] = 0xFF;
                    //Frame1[curr_byte + 3] = 0xFF;
                    //// Pattern on odd 32-bit words
                    //Frame1[curr_byte + 4] = 0x00;
                    //Frame1[curr_byte + 5] = 0x00;
                    //Frame1[curr_byte + 6] = 0x00;
                    //Frame1[curr_byte + 7] = 0x00;

                    //// Counting
                    //Frame1[curr_byte + 0] = 0x01;
                    //Frame1[curr_byte + 1] = 0x02;
                    //Frame1[curr_byte + 2] = 0x03;
                    //Frame1[curr_byte + 3] = 0x04;
                    //Frame1[curr_byte + 4] = 0x05;
                    //Frame1[curr_byte + 5] = 0x06;
                    //Frame1[curr_byte + 6] = 0x07;
                    //Frame1[curr_byte + 7] = 0x08;

                    // Counting remembering we only get to write to half of pixels....
                    Frame1[curr_byte + 0] = 0x01;
                    Frame1[curr_byte + 1] = 0x02;
                    Frame1[curr_byte + 2] = 0xFF;
                    Frame1[curr_byte + 3] = 0xFF;
                    Frame1[curr_byte + 4] = 0x03;
                    Frame1[curr_byte + 5] = 0x04;
                    Frame1[curr_byte + 6] = 0xFF;
                    Frame1[curr_byte + 7] = 0xFF;

                    //// All Off
                    //Frame1[curr_byte + 0] = 0x00;
                    //Frame1[curr_byte + 1] = 0x00;
                    //Frame1[curr_byte + 2] = 0x00;
                    //Frame1[curr_byte + 3] = 0x00;
                    //Frame1[curr_byte + 4] = 0x00;
                    //Frame1[curr_byte + 5] = 0x00;
                    //Frame1[curr_byte + 6] = 0x00;
                    //Frame1[curr_byte + 7] = 0x00;
                }
                else
                {
                    //// Pattern on even 32-bit words
                    //Frame1[curr_byte + 0] = 0x55;
                    //Frame1[curr_byte + 1] = 0x55;
                    //Frame1[curr_byte + 2] = 0x55;
                    //Frame1[curr_byte + 3] = 0x55;
                    //// Pattern on odd 32-bit words
                    //Frame1[curr_byte + 4] = 0xAA;
                    //Frame1[curr_byte + 5] = 0xAA;
                    //Frame1[curr_byte + 6] = 0xAA;
                    //Frame1[curr_byte + 7] = 0xAA;

                    //// Global Counting
                    //Frame1[curr_byte + 0] = (byte)(curr_byte+0);
                    //Frame1[curr_byte + 1] = (byte)(curr_byte+1);
                    //Frame1[curr_byte + 2] = (byte)(curr_byte+2);
                    //Frame1[curr_byte + 3] = (byte)(curr_byte+3);
                    //Frame1[curr_byte + 4] = (byte)(curr_byte+4);
                    //Frame1[curr_byte + 5] = (byte)(curr_byte+5);
                    //Frame1[curr_byte + 6] = (byte)(curr_byte+6);
                    //Frame1[curr_byte + 7] = (byte)(curr_byte+7);

                    //// Corners Test Image
                    //Frame1[curr_byte + 0] = TestImages.corners[curr_byte + 0];
                    //Frame1[curr_byte + 1] = TestImages.corners[curr_byte + 1];
                    //Frame1[curr_byte + 2] = TestImages.corners[curr_byte + 2];
                    //Frame1[curr_byte + 3] = TestImages.corners[curr_byte + 3];
                    //Frame1[curr_byte + 4] = TestImages.corners[curr_byte + 4];
                    //Frame1[curr_byte + 5] = TestImages.corners[curr_byte + 5];
                    //Frame1[curr_byte + 6] = TestImages.corners[curr_byte + 6];
                    //Frame1[curr_byte + 7] = TestImages.corners[curr_byte + 7];

                    //// All-on Test Image
                    //Frame1[curr_byte + 0] = TestImages.all_on[curr_byte + 0];
                    //Frame1[curr_byte + 1] = TestImages.all_on[curr_byte + 1];
                    //Frame1[curr_byte + 2] = TestImages.all_on[curr_byte + 2];
                    //Frame1[curr_byte + 3] = TestImages.all_on[curr_byte + 3];
                    //Frame1[curr_byte + 4] = TestImages.all_on[curr_byte + 4];
                    //Frame1[curr_byte + 5] = TestImages.all_on[curr_byte + 5];
                    //Frame1[curr_byte + 6] = TestImages.all_on[curr_byte + 6];
                    //Frame1[curr_byte + 7] = TestImages.all_on[curr_byte + 7];

                    //// Incrementing Words
                    //Frame1[curr_byte + 0] = TestImages.incr_words[curr_byte + 0];
                    //Frame1[curr_byte + 1] = TestImages.incr_words[curr_byte + 1];
                    //Frame1[curr_byte + 2] = TestImages.incr_words[curr_byte + 2];
                    //Frame1[curr_byte + 3] = TestImages.incr_words[curr_byte + 3];
                    //Frame1[curr_byte + 4] = TestImages.incr_words[curr_byte + 4];
                    //Frame1[curr_byte + 5] = TestImages.incr_words[curr_byte + 5];
                    //Frame1[curr_byte + 6] = TestImages.incr_words[curr_byte + 6];
                    //Frame1[curr_byte + 7] = TestImages.incr_words[curr_byte + 7];

                    //// Smiley Face
                    //Frame1[curr_byte + 0] = TestImages.smiley_face[curr_byte + 0];
                    //Frame1[curr_byte + 1] = TestImages.smiley_face[curr_byte + 1];
                    //Frame1[curr_byte + 2] = TestImages.smiley_face[curr_byte + 2];
                    //Frame1[curr_byte + 3] = TestImages.smiley_face[curr_byte + 3];
                    //Frame1[curr_byte + 4] = TestImages.smiley_face[curr_byte + 4];
                    //Frame1[curr_byte + 5] = TestImages.smiley_face[curr_byte + 5];
                    //Frame1[curr_byte + 6] = TestImages.smiley_face[curr_byte + 6];
                    //Frame1[curr_byte + 7] = TestImages.smiley_face[curr_byte + 7];

                    // Data from Python Scripts
                    Frame1[curr_byte + 0] = PythonImages.generated_frame_buffer[curr_byte + 0];
                    Frame1[curr_byte + 1] = PythonImages.generated_frame_buffer[curr_byte + 1];
                    Frame1[curr_byte + 2] = PythonImages.generated_frame_buffer[curr_byte + 2];
                    Frame1[curr_byte + 3] = PythonImages.generated_frame_buffer[curr_byte + 3];
                    Frame1[curr_byte + 4] = PythonImages.generated_frame_buffer[curr_byte + 4];
                    Frame1[curr_byte + 5] = PythonImages.generated_frame_buffer[curr_byte + 5];
                    Frame1[curr_byte + 6] = PythonImages.generated_frame_buffer[curr_byte + 6];
                    Frame1[curr_byte + 7] = PythonImages.generated_frame_buffer[curr_byte + 7];
                }
            }


            // Run in streaming mode for max performance with fixed block sizes
            ftStatus = d3xxDevice.SetStreamPipe(0x02, total_bytes_per_frame);
            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Debug.WriteLine("Couldnt set to streaming mode! ftStatus={0}", ftStatus);
                d3xxDevice.AbortPipe(0x02);
                bLoopbackFails = true;
            }


            // Output Frame
            //ftStatus = d3xxDevice.WritePipe(0x02, Frame1, (UInt32)total_bytes_per_frame, ref bytesWritten);
            NativeOverlapped pOverlapped = new NativeOverlapped();

            //for (int i = 0; i < 1280; i++)
            //{

            //ftStatus = d3xxDevice.WritePipe(0x02, Frame1, (UInt32)total_bytes_per_frame, ref bytesWritten);
            Thread.Sleep(10);

            // Write
            ftStatus = d3xxDevice.WritePipeAsync(0x02, Frame1, (UInt32)total_bytes_per_frame, ref bytesWritten, ref pOverlapped);
            // Async wait
            ftStatus = d3xxDevice.WaitAsync(ref pOverlapped, ref bytesWritten, true);
            Thread.Sleep(10);
            if ((ftStatus != FTDI.FT_STATUS.FT_OK) || (bytesWritten != total_bytes_per_frame))
            {
                Console.WriteLine("Error with async transfer");
            }
            ;
            // Print Transfer Details
            Console.WriteLine("Bytes: " + bytesWritten.ToString() + " Status: " + ftStatus.ToString());



            //// Just send 32 lines at a time, 40 times
            //for(int i=0; i<40; i++)
            //{
            //    ftStatus = d3xxDevice.WritePipe(0x02, Frame1, (UInt32)total_bytes_per_frame, ref bytesWritten);
            //    Thread.Sleep(10);
            //    if ((ftStatus != FTDI.FT_STATUS.FT_OK) || (bytesWritten != total_bytes_per_frame))
            //    {
            //        Console.WriteLine("Error with async transfer");
            //    };
            //    // Print Transfer Details
            //    Console.WriteLine("Bytes: " + bytesWritten.ToString() + " Status: " + ftStatus.ToString());
            //}



            //ftStatus = d3xxDevice.WritePipe(0x02, Frame1, (UInt32)total_bytes_per_frame, ref bytesWritten);
            ////Thread.Sleep(10);

            //// Write
            ////ftStatus = d3xxDevice.WritePipeAsync(0x02, Frame1, (UInt32)total_bytes_per_frame, ref bytesWritten, ref pOverlapped);
            //// Async wait
            ////ftStatus = d3xxDevice.WaitAsync(ref pOverlapped, ref bytesWritten, true);
            ////Thread.Sleep(1);
            //if ((ftStatus != FTDI.FT_STATUS.FT_OK) || (bytesWritten != total_bytes_per_frame))
            //{
            //    Console.WriteLine("Error with async transfer");
            //};
            //// Print Transfer Details
            //Console.WriteLine("Bytes: " + bytesWritten.ToString() + " Status: " + ftStatus.ToString());



            // Print Pipe State
            //foreach (var desc in d3xxDevice.DataPipeInformation)
            //{
            //    Console.WriteLine("\tPIPE INFORMATION");
            //    Console.WriteLine("\tPipeType : {0:d} ({1})", desc.PipeType, desc.PipeType.ToString());
            //    Console.WriteLine("\tPipeId : 0x{0:X2}", desc.PipeId);
            //    Console.WriteLine("\tMaximumPacketSize : 0x{0:X4}", desc.MaximumPacketSize);
            //    Console.WriteLine("\tInterval : 0x{0:X2}", desc.Interval);
            //}
            //Frame1[row].ToList().ForEach(i => Console.WriteLine(i.ToString()));
            //Thread.Sleep(1);

            //}

            //// Pump all our lines, lots of data!!
            //for (int row = 0; row < lines_per_frame; row++)
            //{
            //    //ftStatus = d3xxDevice.WritePipe(0x02, Frame1[row], (UInt32)bytes_per_line, ref bytesWritten);
            //    // Write
            //    ftStatus = d3xxDevice.WritePipeAsync(0x02, Frame1[row], (UInt32)bytes_per_line, ref bytesWritten, ref pOverlapped);
            //    // Async wait
            //    ftStatus = d3xxDevice.WaitAsync(ref pOverlapped, ref bytesWritten, true);
            //    if (ftStatus != FTDI.FT_STATUS.FT_OK || bytesWritten != bytes_per_line){ Console.WriteLine("Error with async transfer"); };
            //    // Print Transfer Details
            //    Console.WriteLine("Bytes: " + bytesWritten.ToString() + " Status: " + ftStatus.ToString() );
            //    // Print Pipe State
            //    foreach (var desc in d3xxDevice.DataPipeInformation)
            //    {
            //        Console.WriteLine("\tPIPE INFORMATION");
            //        Console.WriteLine("\tPipeType : {0:d} ({1})", desc.PipeType, desc.PipeType.ToString());
            //        Console.WriteLine("\tPipeId : 0x{0:X2}", desc.PipeId);
            //        Console.WriteLine("\tMaximumPacketSize : 0x{0:X4}", desc.MaximumPacketSize);
            //        Console.WriteLine("\tInterval : 0x{0:X2}", desc.Interval);
            //    }
            //    //Frame1[row].ToList().ForEach(i => Console.WriteLine(i.ToString()));
            //    //Thread.Sleep(100);
            //}



            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Debug.WriteLine("WritePipe failed! ftStatus={0}", ftStatus);
                d3xxDevice.AbortPipe(0x02);
                bLoopbackFails = true;
                //break;
            }
            //if (bytesWritten != writeBytes.Length)
            //{
            //    Debug.WriteLine("WritePipe failed! bytesWritten={0} != writeBytes.Length={1}", bytesWritten, writeBytes.Length);
            //    bLoopbackFails = true;
            //    break;
            //}

            //Debug.WriteLine("\t[{0:d}] WritePipe {1:d}", i, bytesWritten);



            // Write next_line_rdy signal
            //ftStatus = d3xxDevice.EnableGPIO((UInt32)FTDI.FT_GPIO_MASK.GPIO_ALL, ulDirection);
            //ftStatus = d3xxDevice.WriteGPIO((UInt32)FTDI.FT_GPIO_MASK.GPIO_0, 3);
            //ftStatus = d3xxDevice.WriteGPIO((UInt32)FTDI.FT_GPIO_MASK.GPIO_0, 0);
            //ftStatus = d3xxDevice.EnableGPIO((UInt32)0, ulDirection);



            //    UInt32 bytesRead = 0;
            //    while (true)
            //    {
            //        ftStatus = d3xxDevice.ReadPipe(0x82, readBytes, (UInt32)readBytes.Length, ref bytesRead);
            //        if (ftStatus != FTDI.FT_STATUS.FT_OK)
            //        {
            //            Debug.WriteLine("ReadPipe failed! ftStatus={0}", ftStatus);
            //            d3xxDevice.AbortPipe(0x82);
            //            bLoopbackFails = true;
            //            break;
            //        }
            //        if (bytesRead == 0)
            //        {
            //            Debug.WriteLine("ReadPipe bytesRead == 0, retry");
            //            continue;
            //        }
            //        else if (bytesRead != readBytes.Length)
            //        {
            //            Debug.WriteLine("ReadPipe failed! bytesRead={0} != readBytes.Length={1}", bytesRead, readBytes.Length);
            //            bLoopbackFails = true;
            //            break;
            //        }

            //        break;
            //    }

            //    Debug.WriteLine("\t[{0:d}] ReadPipe  {1:d}", i, bytesRead);

            //    bool same = writeBytes.SequenceEqual(readBytes);
            //    if (same == false)
            //    {
            //        Debug.WriteLine("Loopback fails! SequenceEqual fails!");
            //        bLoopbackFails = true;
            //        break;
            //    }
            //}

            Thread.Sleep(200);
            d3xxDevice.AbortPipe(0x02);
            Thread.Sleep(200);

            Thread.Sleep(200);
            d3xxDevice.FlushPipe(0x02);
            Thread.Sleep(200);

            ftStatus = d3xxDevice.Close();

            //d3xxDevice.ResetDevicePort();

            if (ftStatus != FTDI.FT_STATUS.FT_OK)
            {
                Debug.WriteLine("Close failed! ftStatus={0}", ftStatus);
                return(TestResult);
            }

            if (!bLoopbackFails)
            {
                TestResult = true;
            }

            return(TestResult);
        }