

// An example of IO communication with GTR-01 device. Version 2.1, 02-March-2022.
// Copyright (C) 2022 by Benev Science & Technology Ltd. All rights reserved.



using System;


namespace GTR
{
    // GTR_IO class.
    public class GTR_IO
    {
        // Constants.
        private const ushort VID = 0x0403;
        private const ushort PID = 0x6015;      // These are FTDI's original pid and vid.

        private const uint BYTES_TO_WRITE = 64u;
        private const uint BYTES_TO_READ = 4096u;

        private const byte EEPROM_WRITE_CONST = (byte)0x55;

        public const byte GET_RND_CHANNEL_A_REQUEST = (byte)0x01;
        public const byte GET_RND_CHANNEL_A_CALIBRATION_REQUEST = (byte)0x02;
        public const byte GET_RND_CHANNEL_B_REQUEST = (byte)0x11;
        public const byte GET_RND_CHANNEL_B_CALIBRATION_REQUEST = (byte)0x12;
        public const byte GET_RND_NORMAL_REQUEST = (byte)0x21;
        public const byte GET_RND_NORMAL_PLUS_REQUEST = (byte)0x22;
        public const byte GET_RND_NORMAL_DEBIAS_REQUEST = (byte)0x23;
        public const byte GET_RND_CHANNEL_A_ASYNC_REQUEST = (byte)0x31;
        public const byte GET_RND_CHANNEL_A_CALIBRATION_ASYNC_REQUEST = (byte)0x32;
        public const byte GET_RND_CHANNEL_B_ASYNC_REQUEST = (byte)0x41;
        public const byte GET_RND_CHANNEL_B_CALIBRATION_ASYNC_REQUEST = (byte)0x42;
        public const byte GET_RND_NORMAL_ASYNC_REQUEST = (byte)0x51;
        public const byte GET_RND_NORMAL_PLUS_ASYNC_REQUEST = (byte)0x52;
        public const byte GET_RND_NORMAL_DEBIAS_ASYNC_REQUEST = (byte)0x53;

        private const byte SET_CALIBRATION_REQUEST = (byte)0x80;
        private const byte GET_CALIBRATION_REQUEST = (byte)0x81;
        private const byte GET_DEVICE_ID_REQUEST = (byte)0x82;


        // Constructor.
        public GTR_IO()
        {
        }


        // Public methods.
        public void GTR_Basic_IO()
        {
            IntPtr handle = IntPtr.Zero;

            try
            {
                FT_STATUS status = FT_STATUS.FT_OK;
                uint numDevs = 0u;

                // Check for GTR device.
                status = FTDI.FT_CreateDeviceInfoList(ref numDevs);

                FT_DEVICE_LIST_INFO_NODE[] vDevInfo = new FT_DEVICE_LIST_INFO_NODE[numDevs];
                status = FTDI.FT_GetDeviceInfoList(vDevInfo, ref numDevs);

                string vidpid = String.Format("{0:X4}{1:X4}", GTR_IO.VID, GTR_IO.PID);

                if (status == FT_STATUS.FT_OK && String.Format("{0:X8}", vDevInfo[0].ID) == vidpid)
                {
                    // GTR is connected.
                }
                else
                {
                    // There is something wrong or device is not connected.
                }


                // Open GTR device.
                if (FTDI.FT_Open(0, ref handle) != FT_STATUS.FT_OK)
                {
                    throw new Exception("Device not found!");
                }


                // Initialize GTR device.
                FTDI.FT_SetBaudRate(handle, 3000000u);
                FTDI.FT_SetDataCharacteristics(handle,
                                                FTDI.FT_BITS_8,
                                                FTDI.FT_STOP_BITS_1,
                                                FTDI.FT_PARITY_NONE);
                FTDI.FT_SetFlowControl(handle, FTDI.FT_FLOW_RTS_CTS, 0, 0);
                FTDI.FT_SetTimeouts(handle, 3000u, 1000u);
                FTDI.FT_Purge(handle, FTDI.FT_PURGE_RX | FTDI.FT_PURGE_TX);


                // IO communication.
                uint bytesToWrite = GTR_IO.BYTES_TO_WRITE;
                uint bytesToRead = GTR_IO.BYTES_TO_READ;
                uint bytesWritten = 0u;
                uint bytesReturned = 0u;
                byte[] bufferWrite = new byte[bytesToWrite];
                byte[] bufferRead = new byte[bytesToRead];


                bufferWrite[0] = GTR_IO.GET_RND_NORMAL_REQUEST;

                status = FTDI.FT_Write(handle,
                                       bufferWrite,
                                       bytesToWrite,
                                       ref bytesWritten);
                status = FTDI.FT_Read(handle,
                                      bufferRead,
                                      bytesToRead,
                                      ref bytesReturned);
                if (status != FT_STATUS.FT_OK)
                {
                    throw new Exception("USB communication problem!");
                }


                // Displaying the result.
                for (int i = 0; i < bufferRead.Length; i++)
                {
                    Console.Write("{0:x2}", bufferRead[i]);
                }
                Console.WriteLine();
            }
            catch (Exception exc)
            {
                // If something goes wrong, show the explanation here.
                Console.WriteLine(exc.Message);
            }
            finally
            {
                // When the IO is completed, close GTR device.
                FTDI.FT_Close(handle);
            }
        }
    }
}