/* AIOAIO.cs — accesio.com */

using System;
using System.Runtime.InteropServices; // For the DllImport of AIOAIO Driver API

namespace AIOAIONet
{
    //These 3 should be copied into source files that reference them.
    using TWinErrCode     = UInt32;
    using TBoardIndex     = UInt64;
    using TChannelIndex   = UInt32;

    public class AIOAIO
    {
        #region Consts / Sentinel Values, Enums
        public const TWinErrCode ERROR_SUCCESS = 0;
        public const TBoardIndex biAuto = 0;
        public const TBoardIndex biNone = 0xFFFFFFFFFFFFFFFF;
        public const TChannelIndex ciAll = 0xFFFFFFFF;

        public const UInt32 DIOControlRegisterOffset = 0x48;
        public const UInt32 DIODataRegisterOffset = 0x44;

        public enum Range : UInt32
        {
            NoChange   = 0xFFFFFFFF,
            Unipolar10 = 0x30313055, // FourCC("U010");
            Unipolar5  = 0x35303055, // FourCC("U005");
            Bipolar24  = 0x3432E142, // FourCC("B±24");
            Bipolar20  = 0x3032E142, // FourCC("B±20");
            Bipolar12  = 0x3231E142, // FourCC("B±12");
            Bipolar10  = 0x3031E142, // FourCC("B±10");
            Bipolar5   = 0x3530E142, // FourCC("B±05");
            Bipolar2_5 = 0xBD32E142, // FourCC("B±2½");
            Bipolar1_25 = 0xBC31E142, // FourCC("B±1¼");
            Bipolar_625 = 0x3835E142, // FourCC("B±58");
            Bipolar_3125 = 0x3331E142, // FourCC("B±13");
            Current420 = 0x30323449, // FourCC("I420"); // 4-20mA
            Current020 = 0x30323049, // FourCC("I020"); // 0-20mA
            Current024 = 0x34323049, // FourCC("I024"); // 0-24mA
            Code0 = 0,
            Code1 = 1,
            Code2 = 2,
            Code3 = 3,
            Code4 = 4,
            Code5 = 5,
            Code6 = 6,
            Code7 = 7,
            Code8 = 8,
            Code9 = 9,
            Code10 = 10
        }

        public enum Sequencer : UInt32 { First = 0, Second = 1 }
        public enum IRQIndex : UInt32 { Only = 0 }
        public enum ChunkingType : UInt32 { Auto = 0, Size = 1, Rate = 1}
        public enum CallbackType : UInt32 { Raw = 0, Volts = 1, Current = 2}
        #endregion

        #region Board-level functions
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TBoardIndex BRD_GetHighestBoardIndex();
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_GetNameW(TBoardIndex iBoard, UInt32 bufLen, IntPtr pNameBuf, ref UInt32 pNameLen);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_GetNameA(TBoardIndex iBoard, UInt32 bufLen, IntPtr pNameBuf, ref UInt32 pNameLen);

        internal static TWinErrCode BRD_GetName(TBoardIndex iBoard, out string Name)
        {
            UInt32 Status;
            UInt32 NameLen = 256;
            IntPtr pNameStr = Marshal.AllocHGlobal((Int32)(NameLen * 2));

            Status = BRD_GetNameW(iBoard, NameLen, pNameStr, ref NameLen);
            if (Status == 0)
            {
                Name = Marshal.PtrToStringUni(pNameStr);
            }
            else
            {
                Name = "error during BRD_GetName";
            }
            Marshal.FreeHGlobal(pNameStr);
            return Status;
        }

        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_GetSerialNumber(TBoardIndex iBoard, out UInt64 serialNumber);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_Reset(TBoardIndex iBoard);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_SleepDevice(TBoardIndex iBoard);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_GetID(TBoardIndex iBoard, out UInt64 pID);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode BRD_GetRev(TBoardIndex iBoard, out UInt32 pRev);

        #endregion

        #region DAC functions
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode DAC_SetRange1(TBoardIndex iBoard, TChannelIndex ch = ciAll, Range range = Range.NoChange);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode DAC_SetRangeAll(TBoardIndex iBoard, Int32 rangeCt, IntPtr pRangeCodes);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode DAC_OutputCounts(TBoardIndex iBoard, TChannelIndex ch = ciAll, UInt64 raw = 0xFFFFFFFFFFFFFFFF);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode DAC_OutputV(TBoardIndex iBoard, TChannelIndex ch = ciAll, Double V = 0.0);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode DAC_OutputVAll(TBoardIndex iBoard, UInt32 Ct, IntPtr V);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode DAC_OutputAll(TBoardIndex iBoard, UInt32 Ct, UInt64 raw);

        #endregion

        #region ADC functions
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_SetRange1(TBoardIndex iBoard, Sequencer ADC, TChannelIndex channel = ciAll, Range range = Range.Bipolar10);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_SetRangeAll(TBoardIndex iBoard, Sequencer ADC, UInt32 rangeCt, IntPtr ranges);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_SetDifferential(TBoardIndex iBoard, bool bDifferential);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_SetRate(TBoardIndex iBoard, Sequencer ADC, double Hz);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_GetRate(TBoardIndex iBoard, Sequencer ADC, ref double Hz);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_SetChannelCount(TBoardIndex iBoard, Sequencer ADC, uint numChannels);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_GetImmediateV(TBoardIndex iBoard, Sequencer ADC, out double V, TChannelIndex ch, Range range = Range.NoChange);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_GetImmediateScanV(TBoardIndex iBoard, IntPtr V, Range range = Range.NoChange);

        internal static TWinErrCode ADC_GetImmediateScanV(TBoardIndex iBoard, double[] V, Range range = Range.NoChange)
        {
            IntPtr outPtr = Marshal.AllocHGlobal(V.Length * sizeof(double));
            UInt32 Status = ADC_GetImmediateScanV(iBoard, outPtr, range);
            Marshal.Copy(outPtr, V, 0, V.Length);
            Marshal.FreeHGlobal(outPtr);
            return Status;
        }

        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_ConfigureAcquire(TBoardIndex iBoard, Sequencer ADC, ChunkingType chunkingType, UInt32 chunk);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_AcquireBlock(TBoardIndex iBoard, Sequencer ADC, int sampleCt);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_AcquireStream(TBoardIndex iBoard, Sequencer ADC);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_AcquireEnd(TBoardIndex iBoard, Sequencer ADC);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_SetCallback(TBoardIndex iBoard, Sequencer ADC, CallbackType callbackType, IntPtr callback);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_GetDataV(TBoardIndex iBoard, Sequencer ADC, UInt32 DataCt, out UInt32 pGotDataCt, out double[] Data, out UInt16[] Status, out UInt16[] Timestamps);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_GetDataRaw(TBoardIndex iBoard, Sequencer ADC, UInt32 DataCt, out UInt32 pGotDataCt, out UInt16[] Data, out UInt16[] Status, out UInt16[] Timestamps);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_PollData(TBoardIndex iBoard, Sequencer ADC);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode ADC_ClearData(TBoardIndex iBoard, Sequencer ADC);
        #endregion

        #region Low Level register read/write functions
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern byte PIO_In8(TBoardIndex iBoard, UInt32 offset);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern UInt16 PIO_In16(TBoardIndex iBoard, UInt32 offset);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern UInt32 PIO_In32(TBoardIndex iBoard, UInt32 offset);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_Out8(TBoardIndex iBoard, UInt32 offset, byte data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_Out16(TBoardIndex iBoard, UInt32 offset, UInt16 data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_Out32(TBoardIndex iBoard, UInt32 offset, UInt32 data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_INS8(TBoardIndex iBoard, UInt32 offset, UInt32 dataCt, byte[] data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_INS16(TBoardIndex iBoard, UInt32 offset, UInt32 dataCt, UInt16[] data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_INS32(TBoardIndex iBoard, UInt32 offset, UInt32 dataCt, UInt32[] data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_OUTS8(TBoardIndex iBoard, UInt32 Offset, UInt32 DataCt, byte[] Data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_OUTS16(TBoardIndex iBoard, UInt32 Offset, UInt32 DataCt, UInt16[] Data);
        [DllImport("AIOAIO.DLL", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        internal static extern TWinErrCode PIO_OUTS32(TBoardIndex iBoard, UInt32 Offset, UInt32 DataCt, UInt32[] Data);
        #endregion
    }
}
