using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

// @Name: ai_continuous.cs
// @Author: Smacq
// @Copyright: Smacq
// @Date: 2024/12/25
// @Brief:
// This code focuses on the Ai functions of the USB - 3000 device, performing continuous acquisition.
// It acquires 100 data points from the Ai0 channel 10 times.
// You can refer to the user manual for more information about functions or device details.
//
// Execution result when only connecting USB for USB - 3000:
// Device_number: 1
// 0
// Device_Index: 0 Device_SN: 66666666 Device_Model: 3323
// 0
//...
// 0
//remain_buffer: 2
//Ai0 100 data points
//0.04219265
///...
//0.04188011
//Press Enter to continue...
// 0
// 0
// 0

class Program
{
    static void Main(string[] args)
    {
        // Initialize Ai_data_array
        // Usually the array size need >= acquisition data points size.
        // Data type is float32, it is not modifiable.
        // The data points saved to Ai_data_array arrange from opened Ai channel
        float[] Ai_data_array = new float[2400];

        // Device index starts from zero
        int DevIndex = 0;

        // Ai voltage range:
        // 10.24 = -10.24 to +10.24V and so on
        // Voltage range param support 10.24/5.12/2.56/1.28/0.64
        float Range = 10.24f;

        // Ai channel sample mode:
        // 0 = Continuous acquisition or 1 = Oneshot, param support 0/1
        byte AiSampleMode = 0;

        // Ai channel connect type:
        // 0 = Diff or 1 = NRSE, param support 0/1
        byte AiConnectType = 1;

        // Acquisition amount of data:
        // Each opened Ai channel will get this amount of data.
        // Suggest value within sampling rate 10%~20%.
        uint Num = 100;

        // Configuration values for Ai channels:
        // Device model channel number start from 0
        byte Channel = 0;

        // Set channel ON/OFF
        byte Channel_ON = 1;
        byte Channel_OFF = 0;

        // Ai Sampling period, unit ns, steps 10ns:
        // USB - 3000 is asynchronous DAQ, single channel max rate is 1M = 1000.
        // Multichannel each channel share out samplerate, 1M/channel.
        // sample rate and period:
        // 100k = 10000
        // 10k = 100000
        // 1k = 1000000
        // 100 = 10000000
        // 10 = 100000000
        // 1 = 1000000000
        uint AiSamplePeriod = 1000000;

        // Ai acquisition trig source:
        // 0 = SetUSB3AiSoftTrig(), 1 = Ext_Trig_In, 2~5 = Din_0~3,
        // 7 = with DI, 8 = with DO, 9~12 = with AO~3, 255 = GlobalSoftTrig
        // Supported parameters: 0/1/2/3/4/5/7/8/9/10/11/12/255
        byte AiTrigSource = 0;

        // Ai acquisition clock source:
        // 0 = SetUSB3AiSampleRate(), 1 = Conv_In, 3 = Di, 4 = DO, 5~8 = AO~3
        // Supported parameters: 0/1/3/4/5/6/7/8
        byte AiConvSource = 0;

        // Timeout unit ms:
        // Suggest Timeout > (Num*Channel_count/Samplerate)*1000
        // Avoid USB3GetAi() func timeout, if timeout return -7.
        int Timeout = 200;

        int error_code;
        // Find connected DAQ number
        int Device_number = USB3000DLL.FindUSB3DAQ();
        Console.WriteLine("Device_number: " + Device_number);

        // Open specific device and print return value.
        error_code = USB3000DLL.USB3OpenDevice(DevIndex);
        Console.WriteLine(error_code);

        // Get and print Device_SN
        int Device_SN = USB3000DLL.USB3ReadDevcieSN(DevIndex);
        int Device_Model = USB3000DLL.USB3ReadDevcieModel(DevIndex);
        Console.WriteLine("Device_Index: " + DevIndex + " Device_SN: " + Device_SN + " Device_Model: " + Device_Model);

        // Turn OFF Ai channel 0 - 8 (default Ai channel 0 - 8 is ON)
        for (int i = 0; i < 8; i++)
        {
            error_code = USB3000DLL.SetUSB3AiChanSel(DevIndex, (byte)i, Channel_OFF);
            if (error_code != 0)
            {
                Console.WriteLine(error_code);
            }
        }

        // Turn ON and set input voltage Range for Ai channel 0
        for (int i = 0; i < 1; i++)
        {
            error_code = USB3000DLL.SetUSB3AiChanSel(DevIndex, (byte)i, Channel_ON);
            Console.WriteLine(error_code);
            error_code = USB3000DLL.SetUSB3AiRange(DevIndex, (byte)i, Range);
            Console.WriteLine(error_code);
        }

        // Set Device Ai sample mode
        error_code = USB3000DLL.SetUSB3AiSampleMode(DevIndex, AiSampleMode);
        Console.WriteLine(error_code);

        // Set Device Ai connect type
        error_code = USB3000DLL.SetUSB3AiConnectType(DevIndex, AiConnectType);
        Console.WriteLine(error_code);

        // Set Device sample rate
        error_code = USB3000DLL.SetUSB3AiSampleRate(DevIndex, AiSamplePeriod);
        Console.WriteLine(error_code);

        // Set Device clock source
        error_code = USB3000DLL.SetUSB3AiConvSource(DevIndex, AiConvSource);
        Console.WriteLine(error_code);

        // Clear AI FIFO
        error_code = USB3000DLL.SetUSB3ClrAiFifo(DevIndex);
        Console.WriteLine(error_code);

        // Set Device trig source
        error_code = USB3000DLL.SetUSB3AiTrigSource(DevIndex, AiTrigSource);
        Console.WriteLine(error_code);

        // Enable Ai software trig acquisition
        error_code = USB3000DLL.SetUSB3AiSoftTrig(DevIndex);
        Console.WriteLine(error_code);

        // Continuous acquisition execution 10 times GetAiChans()
        for (int i = 0; i < 10; i++)
        {
            int remain_buffer = USB3000DLL.USB3GetAi(DevIndex, Num, Ai_data_array, Timeout);
            /*
            remain_buffer range 0~2000000
            USB3GetAi() return the remaining Device FIFO buffer value.
            FIFO buffer 100 data points save to Ai_data_array.
            Channel_0 100 data points is Ai_data_array[0:100]
            If open channel 0~1, Channel_1 100 data points is Ai_data_array[100:200] and so on.
            If remain_buffer increase you should run USB3GetAi() more quick, let remain_buffer steady.
            */
            Console.WriteLine("remain_buffer: " + remain_buffer);
            Console.WriteLine("Ai0 100 data points");
            for (int j = 0; j < 100; j++)
            {
                Console.WriteLine(Ai_data_array[j] + " ");
            }
            Console.WriteLine();
            // Add your code here can handle data
        }

        Console.WriteLine("Press Enter to continue...");
        Console.ReadLine();

        // Disable Ai software trig acquisition, clear flag
        error_code = USB3000DLL.SetUSB3ClrAiTrigger(DevIndex);
        Console.WriteLine(error_code);

        // Clear AI FIFO
        error_code = USB3000DLL.SetUSB3ClrAiFifo(DevIndex);
        Console.WriteLine(error_code);

        // Close Device
        error_code = USB3000DLL.USB3CloseDevice(DevIndex);
        Console.WriteLine(error_code);
    }
    class USB3000DLL
    {
        [DllImport("USB3000.dll")]
        public static extern int FindUSB3DAQ();
        [DllImport("USB3000.dll")]
        public static extern int USB3OpenDevice(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int USB3CloseDevice(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int USB3ReadDevcieSN(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int USB3ReadDevcieModel(int DevIndex);

        //--------------------------------------------------------------------------
        // Ananlog Input Configuration

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiSampleRate(int DevIndex, uint SamplePeriod);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiSampleMode(int DevIndex, byte AiSampleMode);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiConnectType(int DevIndex, byte AiConnectType);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiRange(int DevIndex, byte Chan, float AiRange);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiChanSel(int DevIndex, byte Chan, byte Sel);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiTrigSource(int DevIndex, byte AiTrigSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiConvSource(int DevIndex, byte AiConvSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiPreTrigPoints(int DevIndex, uint AiPreTrigPoints);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiOneShotPoints(int DevIndex, uint AiOneShotPoints);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrAiFifo(int DevIndex);

        //--------------------------------------------------------------------------
        // Digital I/O Configuration

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiSampleRate(int DevIndex, uint SamplePeriod);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiSampleMode(int DevIndex, byte DiSampleMode);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiTrigSource(int DevIndex, byte DiTrigSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiConvSource(int DevIndex, byte DiConvSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiPreTrigPoints(int DevIndex, uint DiPreTrigPoints);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiOneShotPoints(int DevIndex, uint DiOneShotPoints);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrDiFifo(int DevIndex);

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoSampleRate(int DevIndex, uint SamplePeriod);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoSampleMode(int DevIndex, byte DoSampleMode);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoTrigSource(int DevIndex, byte DoTrigSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoConvSource(int DevIndex, byte DoConvSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoCycle(int DevIndex, uint DoCycle);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoDataFifo(int DevIndex, uint[] Value, uint Len);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrDoFifo(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoWaveCtrl(int DevIndex, uint Chan);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoImmediately(int DevIndex, uint Chan, uint Value);

        //--------------------------------------------------------------------------
        // Ananlog Output Configuration

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoSampleRate(int DevIndex, byte Chan, uint SamplePeriod);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoSampleMode(int DevIndex, byte Chan, byte AoSampleMode);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoTrigSource(int DevIndex, byte Chan, byte AoTrigSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoConvSource(int DevIndex, byte Chan, byte AoConvSource);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoCycle(int DevIndex, byte Chan, byte AoCycle);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoDataFifo(int DevIndex, byte Chan, float[] Voltage, uint Len);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrAoFifo(int DevIndex, byte Chan);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoSync(int DevIndex, byte Chans);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoImmediately(int DevIndex, byte Chan, float Voltage);

        //--------------------------------------------------------------------------
        // Trig Control

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AiSoftTrig(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DiSoftTrig(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3DoSoftTrig(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3AoSoftTrig(int DevIndex, byte Chan);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3GlobalSoftTrig(int DevIndex);

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrTrigger(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrAiTrigger(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrDiTrigger(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrDoTrigger(int DevIndex);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrAoTrigger(int DevIndex, byte Chan);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ClrGlobalSoftTrig(int DevIndex);

        //--------------------------------------------------------------------------
        // Sync Configuration

        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ExtTrigOutSource(int DevIndex, byte Source);
        [DllImport("USB3000.dll")]
        public static extern int SetUSB3ExtConvOutSource(int DevIndex, byte Source);

        //--------------------------------------------------------------------------
        // Get Data Acquired

        [DllImport("USB3000.dll")]
        public static extern int USB3GetAi(int DevIndex, uint Points, float[] Ai, int TimeOut);
        [DllImport("USB3000.dll")]
        public static extern int USB3GetDi(int DevIndex, uint Points, byte[] Di, int TimeOut);
    }
}