using System;
using System.Runtime.InteropServices;
using System.Text;

namespace ltrModulesNet
{
    public class ltr216api 
    {
        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_Init(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_Open(ref TLTR216 hnd, uint net_addr, ushort net_port,
                                                     string crate_sn, int slot_num);
        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_Close(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_IsOpened(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_SetADC(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillSyncFreqDiv(ref TLTR216 hnd, double adcFreq, out double resultAdcFreq);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillSyncFreqDiv(ref TLTR216 hnd, double adcFreq, IntPtr resultAdcFreq);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindSyncFreqDiv(double adcFreq, out uint div, out double resultAdcFreq);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindSyncFreqDiv(double adcFreq, out uint div, IntPtr resultAdcFreq);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillFilterParams(ref TLTR216 hnd, double adcFreq, out FILTER_OUT_PARAMS filterParams, out double swTimeRes);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillFilterParams(ref TLTR216 hnd, double adcFreq, out FILTER_OUT_PARAMS filterParams, IntPtr swTimeRes);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillFilterParams(ref TLTR216 hnd, double adcFreq, IntPtr filterParams, IntPtr swTimeRes);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindFilterParams(uint adcSwMode, double adcFreq, double swTimeUs, out FILTER_OUT_PARAMS filterParams, out double swTimeRes);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindFilterParams(uint adcSwMode, double adcFreq, double swTimeUs, out FILTER_OUT_PARAMS filterParams, IntPtr swTimeRes);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindFilterParams(uint adcSwMode, double adcFreq, double swTimeUs, IntPtr filterParams, IntPtr swTimeRes);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_GetFilterOutParams(uint adcSwMode, FilterTypes filterType, uint adcOdrCode, out FILTER_OUT_PARAMS filterParams);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillISrcCode(ref TLTR216 hnd, double isrc, out double resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillISrcCode(ref TLTR216 hnd, double isrc, IntPtr resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindISrcCode(ref ISRC_CBR cbr, double isrc, out uint code, out double resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindISrcCode(ref ISRC_CBR cbr, double isrc, out uint code, IntPtr resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindISrcCode(IntPtr cbr, double isrc, out uint code, out double resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FindISrcCode(IntPtr cbr, double isrc, out uint code, IntPtr resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_CalcISrcValue(ref ISRC_CBR cbr, uint code, out double resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_CalcISrcValue(IntPtr cbr, uint code, out double resultValue);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FillRawTables(ref INFO minfo, ref CONFIG cfg, out RAWCONFIG rawCfg);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_InitMeasParams(ref TLTR216 hnd, InitMeasTypes meas, BgMeasTypes bgMeas, ref DATA_STATUS status);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_InitMeasParams(ref TLTR216 hnd, InitMeasTypes meas, BgMeasTypes bgMeas, IntPtr status);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_Start(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_Stop(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_DataStatusInit(out DATA_STATUS status);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_DataChannelsStatusInit(IntPtr chStatusList, uint chCnt);

          [DllImport("ltr216api.dll")]
        static extern int LTR216_Recv(ref TLTR216 hnd, uint[] buf, uint[] tmark, uint size, uint timeout);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_ProcessData(ref TLTR216 hnd, uint[] src,
                                                             double[] dest, ref int size, ProcFlags flags,
                                                             out DATA_STATUS status, IntPtr chStatusList);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_ProcessData(ref TLTR216 hnd, uint[] src,
                                                             double[] dest, ref int size, ProcFlags flags,
                                                             IntPtr status, IntPtr chStatusList);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_CheckMeasStatus(ref TLTR216 hnd, BgMeasTypes measList,
                                                             out DATA_STATUS status,
                                                             IntPtr chStatusList);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_TareOffset(ref TLTR216 hnd, uint chsMask, out uint chsOk);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_TareScale(ref TLTR216 hnd, uint chsMask, out uint chsOk);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_WriteTareInfo(ref TLTR216 hnd, uint chsMask);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_ReadTareInfo(ref TLTR216 hnd, uint chsMask);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FlashRead(ref TLTR216 hnd, uint addr, byte[] data, uint size);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FlashWrite(ref TLTR216 hnd, uint addr, byte[] data, uint size);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FlashErase(ref TLTR216 hnd, uint addr, uint size);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FlashWriteEnable(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_FlashWriteDisable(ref TLTR216 hnd);

        [DllImport("ltr216api.dll")]
        static extern _LTRNative.LTRERROR LTR216_SetISrcEnabled(ref TLTR216 hnd, bool enabled);

        [DllImport("ltr216api.dll")]
        public static extern IntPtr LTR216_GetErrorString(int err);



        public const int LTR216_CHANNELS_CNT = 16;
        public const int LTR216_RANGES_CNT = 2;
        public const int LTR216_CBR_RANGES_CNT = 3;
        public const uint LTR216_CHANNEL_MASK_ALL = 0xFFFF;
        public const int LTR216_ADC_SCALE_CODE_MAX = 8000000;
        public const double LTR216_ADC_CLOCK = 32000000;
        public const uint LTR216_SYNC_FDIV_MAX = 0xFFFFFF;
        public const uint LTR216_ISRC_CODE_MAX = 4095;
        public const int LTR216_MAX_LCHANNEL = 1024;
        public const int LTR216_NAME_SIZE = 8;
        public const int LTR216_SERIAL_SIZE = 16;
        public const uint LTR216_FLASH_USERDATA_ADDR = 0;
        public const uint LTR216_FLASH_USERDATA_SIZE = 0x100000;
        public const double LTR216_VADJ_THRESHOLD = 7;
        public const uint LTR216_SINC3_ODR_MAX_DIV = 32767;
        public const double LTR216_DEFAULT_SHORT_THRESH_R = 10;
        public const double LTR216_CH_INTERNAL_CAPACITY = 1450;
        public const double LTR216_DEFAULT_CABLE_CAPACITY_PER_UNIT = 150;
        public const double LTR216_DEFAULT_CABLE_LENGTH = 100;
        public const double LTR216_I_BURNOUT = 5e-6;

        public enum AdcRanges : byte
        {
            Range_35 = 0,
            Range_70 = 1,
        }

        public enum FilterTypes : uint
        {
            SINC5_1 = 0,
            SINC3 = 1,
            ENH_50HZ = 2
        }

        public enum AdcSwModes : byte
        {
            MULTICH_SYNC = 0,
            SIGNLECH_CONT = 1
        }

        [Flags]
        public enum ConfigFlags : uint
        {
            RAWTABLE = 0x00000001
        }

        [Flags]
        public enum BgMeasTypes : uint
        {
            OFFS = 1 << 0,
            UREF = 1 << 1,
            UREF_OFFS = 1 << 2,
            VADJ = 1 << 3,
            UNEG = 1 << 4,
            UREF_SHORT = 1 << 5,
            UREF_OPEN = 1 << 6,
            UNEG_OPEN = 1 << 7,
            CH_SHORT = 1 << 8,
            CH_OPEN = 1 << 9,
            CH_UX = 1 << 10,
            CH_CM = 1 << 11,

            MEASGROUP_OPEN = CH_OPEN | UNEG_OPEN | UREF_OPEN,
            MEASGROUP_SHORT = CH_SHORT | UREF_SHORT,
            MEASGROUP_SECTBL = UREF | UREF_OFFS | VADJ | UNEG | CH_UX | CH_CM | MEASGROUP_OPEN | MEASGROUP_SHORT,
            MEASGROUP_UREF_CHECK = UREF_SHORT | UREF_OPEN | UNEG_OPEN,
            MEASGROUP_CH_CHECK = CH_SHORT | CH_OPEN | CH_UX | CH_CM,
            MEASGROUP_ALL = OFFS | MEASGROUP_SECTBL
        }

        [Flags]
        public enum InitMeasTypes : uint
        {
            OFFS = 1 << 0,
            UREF = 1 << 1,
            ALL = OFFS | UREF
        }

        public enum MeasStatus : byte
        {
            NOT_USED = 0,
            OK = 1,
            NOT_INIT = 2, 
            ADC_OVERRANGE = 3,
            SHORT = 4,
            OPEN = 5,
            BAD_VALUE_RANGE = 6,
            CANT_CALC = 7
        }

        [Flags]
        public enum ProcFlags : uint
        {
            MEAS_UNBALANCE = 0 << 16,
            MEAS_UDIFF = 1 << 16,
            MEAS_UDIFF_CODE = 2 << 16,
            NO_FABRIC_CBR = 1 << 0,
            NONCONT_DATA = 0x0100
        }

        [Flags]
        public enum ChStatusFlags : uint
        {
            OVERRANGE = 1 << 0
        }

        [Flags]
        public enum ChDetectErrs : uint
        {
            OVERRANGE = 1 << 0,
            UCM_OUT_OF_RANGE = 1 << 1,
            UX_OPEN = 1 << 2,
            UX_SHORT = 1 << 3
        }

        [Flags]
        public enum StatusFlags : uint
        {
            LOAD_POW_EXCEEDED = 1 << 0
        }

        [Flags]
        public enum DetectErrs : uint
        {
            LOAD_POW_EXCEEDED = 1 << 0,
            UREF_OVERRANGE = 1 << 1,
            UREF_OPEN = 1 << 2,
            UREF_SHORT = 1 << 3,
            VADJ_ERROR = 1 << 4,
            UNEG_OPEN = 1 << 5
        }

        [Flags]
        public enum FlashInfoFlags : uint
        {
            SERIAL_VALID = 1 << 0,
            ISRC_CBR_VALID = 1 << 1,
            DAC_CBR_VALID = 0x7 << 8,
            ADC_CBR_VALID = 0x7 << 12,
        }


        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct CBR_VALUE
        {
            double _offset;
            double _scale;

            public double Offset { get { return _offset; } }
            public double Scale { get { return _scale; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct ISRC_CBR
        {
            CBR_VALUE _ref;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_CHANNELS_CNT)]
            CBR_VALUE[] _ch;


            public CBR_VALUE Ref { get { return _ref; } set { _ref = value; } }

            public CBR_VALUE ChCbr(int ch)
            {
                return _ch[ch];
            }

            public void SetChCbr(int ch, CBR_VALUE coef)
            {
                _ch[ch] = coef;
            }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct FABRIC_CBR
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_CBR_RANGES_CNT)]
            CBR_VALUE[] _adc;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_CBR_RANGES_CNT)]
            CBR_VALUE[] _dac;
            ISRC_CBR _isrc;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 48)]
            double[] _reserved;

            public ISRC_CBR ISrc { get { return _isrc; } set { _isrc = value; } }
            public CBR_VALUE AdcChCbr(int ch)
            {
                return _adc[ch];
            }

            public void SetAdcChCbr(int ch, CBR_VALUE coef)
            {
                _adc[ch] = coef;
            }

            public CBR_VALUE DacChCbr(int ch)
            {
                return _dac[ch];
            }

            public void SetDacChCbr(int ch, CBR_VALUE coef)
            {
                _dac[ch] = coef;
            }

        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct TARE_CH_CFG
        {
            uint _isrccode;
            AdcRanges _range;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            uint[] _reserved;


            public uint ISrcCode { get { return _isrccode; } set { _isrccode = value; } }
            public AdcRanges Range { get { return _range; } set { _range = value; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct TARE_CH_COEFS
        {
            [MarshalAs(UnmanagedType.U1)]
            bool _dac_valid;
            [MarshalAs(UnmanagedType.U1)]
            bool _offs_valid;
            [MarshalAs(UnmanagedType.U1)]
            bool _scale_valid;
            uint _reserved1;
            double _dac_value;
            double _offset;
            double _scale;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            uint[] _reserved2;
            
            uint _isrccode;
            AdcRanges _range;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            uint[] _reserved;

            public bool DacValid { get { return _dac_valid; } set { _dac_valid = value; } }
            public bool OffsetValid { get { return _offs_valid; } set { _offs_valid = value; } }
            public bool ScaleValid { get { return _scale_valid; } set { _scale_valid = value; } }

            public double DacValue { get { return _dac_value; } set { _dac_value = value; } }
            public double Offset { get { return _offset; } set { _offset = value; } }
            public double Scale { get { return _scale; } set { _scale = value; } }

            public uint ISrcCode { get { return _isrccode; } set { _isrccode = value; } }
            public AdcRanges Range { get { return _range; } set { _range = value; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct INFO
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_NAME_SIZE)]
            char[] _name;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_SERIAL_SIZE)]
            char[] _serial;
            ushort _ver_fpga;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            uint[] _reserved;
            
            FlashInfoFlags _flash_info_flags;
            FABRIC_CBR _fabric_cbr;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_CHANNELS_CNT)]
            TARE_CH_COEFS[] _tare;
            
            public string Name { get { return new string(_name).Split('\0')[0]; } }
            public string Serial { get { return new string(_serial).Split('\0')[0]; } }
            public ushort VerFPGA { get { return _ver_fpga; } }
            public FlashInfoFlags FlashInfoFlags { get { return _flash_info_flags; } }
            public FABRIC_CBR FabricCbr { get { return _fabric_cbr; } }

            public TARE_CH_COEFS ChTare(int ch)
            {
                return _tare[ch];
            }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct STATE
        {
            [MarshalAs(UnmanagedType.U1)]
            bool _configured;
            [MarshalAs(UnmanagedType.U1)]
            bool _run;
            uint _frame_words_cnt;
            double _adc_freq;
            double _frame_freq;
            double _i_src_value;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            uint[] _reserved;

            public bool Configured { get { return _configured; } }
            public bool Run { get { return _run; } }
            public uint FrameWordsCount { get { return _frame_words_cnt; } }
            public double AdcFreq { get { return _adc_freq; } }
            public double FrameFreq { get { return _frame_freq; } }
            public double ISrcValue { get { return _i_src_value; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct LCHANNEL
        {
            byte _phy_ch;
            AdcRanges _range;
            ushort _reserved;

            public LCHANNEL(byte phy_ch, AdcRanges range)
            {
                _phy_ch = phy_ch;
                _range = range;
                _reserved = 0;
            }

            public byte PhyChannel { get { return _phy_ch; } set { _phy_ch = value; } }
            public AdcRanges Range { get { return _range; } set { _range = value; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct CONFIG
        {
            AdcSwModes _adc_sw_mode;
            uint _sync_freq_div;
            FilterTypes _filter_type;
            uint _adc_odr_code;
            double _adc_min_sw_time_us;
            double _adc_req_frame_freq;
            uint _isrc_code;
            BgMeasTypes _bg_meas;
            [MarshalAs(UnmanagedType.U1)]
            bool _ch16_for_uref;
            [MarshalAs(UnmanagedType.U1)]
            bool _tare_en;
            ConfigFlags _flags;
            uint _lch_cnt;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_MAX_LCHANNEL)]
            LCHANNEL[] _lch_tbl;
            double _rref_wire_r;
            double _short_thresh_r;
            double _cable_len;
            double _cable_cap_per_unit;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
            double[] _reserved;

            public AdcSwModes AdcSwMode { get { return _adc_sw_mode; } set { _adc_sw_mode = value; } }
            public uint SyncFreqDiv { get { return _sync_freq_div; } set { _sync_freq_div = value; } }
            public FilterTypes FilterType { get { return _filter_type; } set { _filter_type = value; } }
            public uint AdcOdrCode { get { return _adc_odr_code; } set { _adc_odr_code = value; } }
            public double AdcMinSwTimeUs { get { return _adc_min_sw_time_us; } set { _adc_min_sw_time_us = value; } }
            public double AdcReqFrameFreq { get { return _adc_req_frame_freq; } set { _adc_req_frame_freq = value; } }
            public uint ISrcCode { get { return _isrc_code; } set { _isrc_code = value; } }
            public BgMeasTypes BgMeas { get { return _bg_meas; } set { _bg_meas = value; } }
            public bool Ch16ForUref { get { return _ch16_for_uref; } set { _ch16_for_uref = value; } }
            public bool TareEnabled { get { return _tare_en; } set { _tare_en = value; } }
            public ConfigFlags Flags { get { return _flags; } set { _flags = value; } }
            public uint LChCnt { get { return _lch_cnt; } set { _lch_cnt = value; } }
            public LCHANNEL[] LChTbl { get { return _lch_tbl; } set { _lch_tbl = value; } }
            public void SetLChannel(int lchNum, byte phyChNum, AdcRanges range)
            {
                _lch_tbl[lchNum] = new LCHANNEL(phyChNum, range);
            }
            public double RrefWireResistance { get { return _rref_wire_r; } set { _rref_wire_r = value; } }
            public double ShortThresholdR { get { return _short_thresh_r; } set { _short_thresh_r = value; } }
            public double CableLength { get { return _cable_len; } set { _cable_len = value; } }
            public double CableCapacityPerUnit { get { return _cable_cap_per_unit; } set { _cable_cap_per_unit = value; } }


            public _LTRNative.LTRERROR FillSyncFreqDiv(double adcFreq, out double resultAdcFreq)
            {
                return LTR216_FindSyncFreqDiv(adcFreq, out _sync_freq_div, out resultAdcFreq);
            }

            public _LTRNative.LTRERROR FillSyncFreqDiv(double adcFreq)
            {
                return LTR216_FindSyncFreqDiv(adcFreq, out _sync_freq_div, IntPtr.Zero);
            }

            public _LTRNative.LTRERROR FillFilterParams(double adcFreq, out FILTER_OUT_PARAMS filterParams, out double swTimeRes)
            {
                _LTRNative.LTRERROR err;
                if (_adc_sw_mode == AdcSwModes.MULTICH_SYNC)
                {
                    adcFreq = LTR216_ADC_CLOCK / (_sync_freq_div + 1);
                }

                err = LTR216_FindFilterParams((uint)_adc_sw_mode, adcFreq, _adc_min_sw_time_us,  out filterParams, out swTimeRes);
                if (err == _LTRNative.LTRERROR.OK)
                {
                    _filter_type = filterParams.FilterType;
                    _adc_odr_code = filterParams.AdcOdrCode;
                }
                return err;
            }

            public _LTRNative.LTRERROR FillFilterParams(double adcFreq, out FILTER_OUT_PARAMS filterParams)
            {
                _LTRNative.LTRERROR err;
                if (_adc_sw_mode == AdcSwModes.MULTICH_SYNC)
                {
                    adcFreq = LTR216_ADC_CLOCK / (_sync_freq_div + 1);
                }
                err = LTR216_FindFilterParams((uint)_adc_sw_mode, adcFreq, _adc_min_sw_time_us, out filterParams, IntPtr.Zero);
                if (err == _LTRNative.LTRERROR.OK)
                {
                    _filter_type = filterParams.FilterType;
                    _adc_odr_code = filterParams.AdcOdrCode;
                }
                return err;
            }

            public _LTRNative.LTRERROR FillFilterParams(double adcFreq)
            {
                _LTRNative.LTRERROR err;
                FILTER_OUT_PARAMS filterParams;
                if (_adc_sw_mode == AdcSwModes.MULTICH_SYNC)
                {
                    adcFreq = LTR216_ADC_CLOCK / (_sync_freq_div + 1);
                }
                err = LTR216_FindFilterParams((uint)_adc_sw_mode, adcFreq, _adc_min_sw_time_us, out filterParams, IntPtr.Zero);
                if (err == _LTRNative.LTRERROR.OK)
                {
                    _filter_type = filterParams.FilterType;
                    _adc_odr_code = filterParams.AdcOdrCode;
                }
                return err;
            }

            FILTER_OUT_PARAMS FilterOutParams
            {
                get
                {
                    FILTER_OUT_PARAMS filterParams;
                    LTR216_GetFilterOutParams((uint)_adc_sw_mode, _filter_type, _adc_odr_code, out filterParams);
                    return filterParams;
                }
            }

            public _LTRNative.LTRERROR FillISrcCode(ISRC_CBR cbr, double isrc, out double resultValue)
            {
                return LTR216_FindISrcCode(ref cbr, isrc, out _isrc_code, out resultValue);
            }

            public _LTRNative.LTRERROR FillISrcCode(ISRC_CBR cbr, double isrc)
            {
                return LTR216_FindISrcCode(ref cbr, isrc, out _isrc_code, IntPtr.Zero);
            }

            public _LTRNative.LTRERROR FillISrcCode(double isrc, out double resultValue)
            {
                return LTR216_FindISrcCode(IntPtr.Zero, isrc, out _isrc_code, out resultValue);
            }

            public _LTRNative.LTRERROR FillISrcCode(double isrc)
            {
                return LTR216_FindISrcCode(IntPtr.Zero, isrc, out _isrc_code, IntPtr.Zero);
            }

            public double GetSrcValue(ref ISRC_CBR cbr)
            {
                _LTRNative.LTRERROR err;
                double resultValue;
                err = LTR216_CalcISrcValue(ref cbr, _isrc_code, out resultValue);
                return resultValue;
            }

            public double GetSrcValue()
            {
                _LTRNative.LTRERROR err;
                double resultValue;
                err = LTR216_CalcISrcValue(IntPtr.Zero, _isrc_code, out resultValue);
                return resultValue;
            }

            

            
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct RAWCONFIG
        {
            uint _user_ch_cnt;
            uint _proc_ch_cnt;
            uint _main_lch_chn;
            uint _bg_step_size;
            uint _bg_steps_cnt;
            uint _bg_frame_step_cnt;
            uint _bg_lch_cnt;
            uint _bg_bout_lch_cnt;
            uint _frame_size;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
            uint[] _reserved;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_MAX_LCHANNEL)]
            uint[] _main_lch_tbl;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = LTR216_MAX_LCHANNEL)]
            uint[] _bg_lch_tbl;

            public uint UserChCnt { get { return _user_ch_cnt; } set { _user_ch_cnt = value; } }
            public uint ProcChCnt { get { return _proc_ch_cnt; } set { _proc_ch_cnt = value; } }
            public uint MainLChCnt { get { return _main_lch_chn; } set { _main_lch_chn = value; } }
            public uint BgStepSize { get { return _bg_step_size; } set { _bg_step_size = value; } }
            public uint BgStepsCnt { get { return _bg_steps_cnt; } set { _bg_steps_cnt = value; } }
            public uint BgFrameStepCnt { get { return _bg_frame_step_cnt; } set { _bg_frame_step_cnt = value; } }
            public uint BgLChCnt { get { return _bg_lch_cnt; } set { _bg_lch_cnt = value; } }
            public uint BgBoutLChCnt { get { return _bg_bout_lch_cnt; } set { _bg_bout_lch_cnt = value; } }
            public uint FrameSize { get { return _frame_size; } set { _frame_size = value; } }

        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        struct TLTR216
        {
            int _size;
            public _LTRNative.TLTR Channel;
            IntPtr _internal; 
            CONFIG _cfg;
            RAWCONFIG _raw_cfg;
            STATE _stat;
            INFO _info;


            public CONFIG Cfg { get { return _cfg; } set { _cfg = value; } }
            public RAWCONFIG RawCfg { get { return _raw_cfg; } set { _raw_cfg = value; } }
            public STATE State { get { return _stat; } }
            public INFO ModuleInfo { get { return _info; } }
        };


        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct FILTER_OUT_PARAMS
        {
            FilterTypes _filter_type;
            uint _adc_odr_code;
            double _odr;
            double _notch_freq;
            double _notch_db;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            double[] _reserved;

            public FilterTypes FilterType { get { return _filter_type; } }
            public uint AdcOdrCode { get { return _adc_odr_code; } }
            public double Odr { get { return _odr; } }
            public double NotchFreq { get { return _notch_freq; } }
            public double NotchDB { get { return _notch_db; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct MEASSTATE
        {
            MeasStatus _status;
            [MarshalAs(UnmanagedType.U1)]
            bool _value_valid;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            byte[] _reserved;
            double _value;

            public MeasStatus Status { get { return _status; } }
            public bool ValueValid { get { return _value_valid; } }
            public double Value { get { return _value; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct DATA_STATUS
        {
            DetectErrs _detected_errs;
            StatusFlags _status_flags;
            MEASSTATE _uref;
            MEASSTATE _urefr;
            MEASSTATE _vadj;
            MEASSTATE _uneg;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            uint[] _reserved;

            public DetectErrs DetectedErrors { get { return _detected_errs; } }
            public StatusFlags StatusFlags { get { return _status_flags; } }
            public MEASSTATE Uref { get { return _uref; } }
            public MEASSTATE UrefR { get { return _urefr; } }
            public MEASSTATE Vadj { get { return _vadj; } }
            public MEASSTATE Uneg { get { return _uneg; } }
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct DATA_CH_STATUS
        {
            ChDetectErrs _detected_errs;
            ChStatusFlags _status_flags;
            MEASSTATE _ures;
            MEASSTATE _ux;
            MEASSTATE _ucm;
            double _ucm_min;
            double _ucm_max;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
            uint[] _reserved;

            public ChDetectErrs DetectedErrors { get { return _detected_errs; } }
            public ChStatusFlags StatusFlags { get { return _status_flags; } }
            public MEASSTATE Ures { get { return _ures; } }
            public MEASSTATE Ux { get { return _ux; } }
            public MEASSTATE Ucm { get { return _ucm; } }
            public double UcmMin { get { return _ucm_min; } }
            public double UcmMax { get { return _ucm_max; } }
        }


        TLTR216 module;

        public CONFIG Cfg { get { return module.Cfg; } set { module.Cfg = value; } }
        public STATE State { get { return module.State; } }
        public INFO ModuleInfo { get { return module.ModuleInfo; } }
        public RAWCONFIG RawCfg { get { return module.RawCfg; } set { module.RawCfg = value; } }

       

        

        public void SetLChannel(byte lchNum, byte phyChNum, AdcRanges range)
        {
            Cfg.SetLChannel(lchNum, phyChNum, range);
        }

        public _LTRNative.LTRERROR FillSyncFreqDiv(double adcFreq, out double resultAdcFreq)
        {
            return LTR216_FillSyncFreqDiv(ref module, adcFreq, out resultAdcFreq);
        }

        public _LTRNative.LTRERROR FillSyncFreqDiv(double adcFreq)
        {
            return LTR216_FillSyncFreqDiv(ref module, adcFreq, IntPtr.Zero);
        }

        public _LTRNative.LTRERROR FillFilterParams(double adcFreq, out FILTER_OUT_PARAMS filterParams, out double swTimeRes)
        {
            return LTR216_FillFilterParams(ref module, adcFreq, out filterParams, out swTimeRes);
        }

        public _LTRNative.LTRERROR FillFilterParams(double adcFreq, out FILTER_OUT_PARAMS filterParams)
        {
            return LTR216_FillFilterParams(ref module, adcFreq, out filterParams, IntPtr.Zero);
        }

        public _LTRNative.LTRERROR FillFilterParams(double adcFreq)
        {
            return LTR216_FillFilterParams(ref module, adcFreq, IntPtr.Zero, IntPtr.Zero);
        }

        public _LTRNative.LTRERROR FillISrcCode(double isrc, out double resultValue)
        {
            return LTR216_FillISrcCode(ref module, isrc, out resultValue);
        }

        public _LTRNative.LTRERROR FillISrcCode(double isrc)
        {
            return LTR216_FillISrcCode(ref module, isrc, IntPtr.Zero);
        }

        public static _LTRNative.LTRERROR FindSyncFreqDiv(double adcFreq, out uint div, out double resultAdcFreq)
        {
            return LTR216_FindSyncFreqDiv(adcFreq, out div, out resultAdcFreq);
        }

        public static _LTRNative.LTRERROR FindSyncFreqDiv(double adcFreq, out uint div)
        {
            return LTR216_FindSyncFreqDiv(adcFreq, out div, IntPtr.Zero);
        }

        public static _LTRNative.LTRERROR FindFilterParams(AdcSwModes adcSwMode, double adcFreq, double swTimeUs, out FILTER_OUT_PARAMS filterParams, out double swTimeRes)
        {
            return LTR216_FindFilterParams((uint)adcSwMode, adcFreq, swTimeUs, out filterParams, out swTimeRes);
        }

        public static _LTRNative.LTRERROR FindFilterParams(AdcSwModes adcSwMode, double adcFreq, double swTimeUs, out FILTER_OUT_PARAMS filterParams)
        {
            return LTR216_FindFilterParams((uint)adcSwMode, adcFreq, swTimeUs, out filterParams, IntPtr.Zero);
        }

        public static _LTRNative.LTRERROR GetFilterOutParams(uint adcSwMode, FilterTypes filterType, uint adcOdrCode, out FILTER_OUT_PARAMS filterParams)
        {
            return LTR216_GetFilterOutParams((uint)adcSwMode, filterType, adcOdrCode, out filterParams);
        }

        public static _LTRNative.LTRERROR FindISrcCode(ref ISRC_CBR cbr, double isrc, out uint code, out double resultValue)
        {
            return LTR216_FindISrcCode(ref cbr, isrc, out code, out resultValue);
        }
        public static _LTRNative.LTRERROR FindISrcCode(double isrc, out uint code, out double resultValue)
        {
            return LTR216_FindISrcCode(IntPtr.Zero, isrc, out code, out resultValue);
        }
        public static _LTRNative.LTRERROR CalcISrcValue(ref ISRC_CBR cbr, uint code, out double resultValue)
        {
            return LTR216_CalcISrcValue(ref cbr, code, out resultValue);
        }
        public static _LTRNative.LTRERROR CalcISrcValue(uint code, out double resultValue)
        {
            return LTR216_CalcISrcValue(IntPtr.Zero, code, out resultValue);
        }
        public static _LTRNative.LTRERROR FillRawTables(ref INFO minfo, ref CONFIG cfg, out RAWCONFIG rawCfg)
        {
            return LTR216_FillRawTables(ref minfo, ref cfg, out rawCfg);
        }

        public ltr216api()
        {
            LTR216_Init(ref module);
        }

        ~ltr216api()
        {
            LTR216_Close(ref module);
        }



        public virtual _LTRNative.LTRERROR Open(uint saddr, ushort sport, string csn, ushort cc)
        {
            return LTR216_Open(ref module, saddr, sport, csn, cc);
        }

        public virtual _LTRNative.LTRERROR Open(string csn, ushort cc)
        {
            return Open(_LTRNative.SADDR_DEFAULT, _LTRNative.SPORT_DEFAULT, csn, cc);
        }

        public virtual _LTRNative.LTRERROR Open(ushort cc)
        {
            return Open("", cc);
        }

        public virtual _LTRNative.LTRERROR Close()
        {
            return LTR216_Close(ref module);
        }

        public virtual _LTRNative.LTRERROR IsOpened()
        {
            return LTR216_IsOpened(ref module);
        }

        public virtual _LTRNative.LTRERROR SetADC()
        {
            return LTR216_SetADC(ref module);
        }

        public virtual _LTRNative.LTRERROR InitMeasParams(InitMeasTypes meas, BgMeasTypes bgMeas, out DATA_STATUS status)
        {
            LTR216_DataStatusInit(out status);
            return LTR216_InitMeasParams(ref module, meas, bgMeas, ref status);
        }

        public virtual _LTRNative.LTRERROR InitMeasParams(InitMeasTypes meas, BgMeasTypes bgMeas)
        {
            return LTR216_InitMeasParams(ref module, meas, bgMeas, IntPtr.Zero);
        }

        public virtual _LTRNative.LTRERROR Start()
        {
            return LTR216_Start(ref module);
        }

        public virtual _LTRNative.LTRERROR Stop()
        {
            return LTR216_Stop(ref module);
        }


        public virtual int Recv(uint[] Data, uint[] tstamp, uint size, uint timeout)
        {
            return LTR216_Recv(ref module, Data, tstamp, size, timeout);
        }

        /* такой вариант оставлен только для совместимости .... */
        public virtual int Recv(uint[] Data, uint size, uint[] tstamp, uint timeout)
        {
            return LTR216_Recv(ref module, Data, tstamp, size, timeout);
        }

        public virtual int Recv(uint[] Data, uint size, uint timeout)
        {
            return LTR216_Recv(ref module, Data, null, size, timeout);
        }

        public virtual _LTRNative.LTRERROR ProcessData(uint[] src, double[] dest,
            ref int size, ProcFlags flags, out DATA_STATUS status, out DATA_CH_STATUS[] chStatusList)
        {
            int ch_status_size = Marshal.SizeOf(typeof(DATA_CH_STATUS));
            int ch_status_cnt = (int)Cfg.LChCnt;

            IntPtr ch_status_arr_ptr = Marshal.AllocHGlobal(ch_status_size * ch_status_cnt);
            LTR216_DataChannelsStatusInit(ch_status_arr_ptr, (uint)ch_status_cnt);
            _LTRNative.LTRERROR res = LTR216_ProcessData(ref module, src, dest, ref size, flags, out status, ch_status_arr_ptr);
            if (res == _LTRNative.LTRERROR.OK) {
                chStatusList = new DATA_CH_STATUS[ch_status_cnt];

                for (int i = 0; i < ch_status_cnt; i++)
                {
                    IntPtr ch_status_ptr = new IntPtr(ch_status_arr_ptr.ToInt64() + ch_status_size * i);
                    chStatusList[i] = new DATA_CH_STATUS();
                    chStatusList[i] = (DATA_CH_STATUS)Marshal.PtrToStructure(ch_status_ptr, typeof(DATA_CH_STATUS));
                }
            }
            else
            {
                chStatusList = new DATA_CH_STATUS[0];
            }
            Marshal.FreeHGlobal(ch_status_arr_ptr);
            return res;
        }

        public virtual _LTRNative.LTRERROR ProcessData(uint[] src, double[] dest,
           ref int size, ProcFlags flags, out DATA_STATUS status)
        {
            return LTR216_ProcessData(ref module, src, dest, ref size, flags, out status, IntPtr.Zero);
        }

        public virtual _LTRNative.LTRERROR ProcessData(uint[] src, double[] dest, ref int size, ProcFlags flags)
        {
            return LTR216_ProcessData(ref module, src, dest, ref size, flags, IntPtr.Zero, IntPtr.Zero);
        }

        public virtual _LTRNative.LTRERROR CheckMeasStatus(BgMeasTypes measList, out DATA_STATUS status, out DATA_CH_STATUS[] chStatusList) {
            int ch_status_size = Marshal.SizeOf(typeof(DATA_CH_STATUS));
            int ch_status_cnt = (int)Cfg.LChCnt;

            IntPtr ch_status_arr_ptr = Marshal.AllocHGlobal(ch_status_size * ch_status_cnt);
            LTR216_DataChannelsStatusInit(ch_status_arr_ptr, (uint)ch_status_cnt);
            _LTRNative.LTRERROR res = LTR216_CheckMeasStatus(ref module, measList, out status, ch_status_arr_ptr);
            if (res == _LTRNative.LTRERROR.OK)
            {
                chStatusList = new DATA_CH_STATUS[ch_status_cnt];

                for (int i = 0; i < ch_status_cnt; i++)
                {
                    IntPtr ch_status_ptr = new IntPtr(ch_status_arr_ptr.ToInt64() + ch_status_size * i);
                    chStatusList[i] = new DATA_CH_STATUS();
                    chStatusList[i] = (DATA_CH_STATUS)Marshal.PtrToStructure(ch_status_ptr, typeof(DATA_CH_STATUS));
                }
            }
            else
            {
                chStatusList = new DATA_CH_STATUS[0];
            }
            Marshal.FreeHGlobal(ch_status_arr_ptr);
            return res;
        }

        public virtual _LTRNative.LTRERROR CheckMeasStatus(BgMeasTypes measList, out DATA_STATUS status)
        {
            return LTR216_CheckMeasStatus(ref module, measList, out status, IntPtr.Zero);
        }

        public virtual _LTRNative.LTRERROR TareOffset(uint chsMask, out uint chsOk)
        {
            return LTR216_TareOffset(ref module, chsMask, out chsOk);
        }

        public virtual _LTRNative.LTRERROR TareScale(uint chsMask, out uint chsOk)
        {
            return LTR216_TareScale(ref module, chsMask, out chsOk);
        }

        public virtual _LTRNative.LTRERROR WriteTareInfo(uint chsMask)
        {
            return LTR216_WriteTareInfo(ref module, chsMask);
        }

        public virtual _LTRNative.LTRERROR ReadTareInfo(uint chsMask)
        {
            return LTR216_ReadTareInfo(ref module, chsMask);
        }

        public _LTRNative.LTRERROR FlashRead(uint addr, byte[] data, uint size)
        {
            return LTR216_FlashRead(ref module, addr, data, size);
        }

        public _LTRNative.LTRERROR FlashWrite(uint addr, byte[] data, uint size)
        {
            return LTR216_FlashWrite(ref module, addr, data, size);
        }

        public _LTRNative.LTRERROR FlashErase(uint addr, uint size)
        {
            return LTR216_FlashErase(ref module, addr, size);
        }

        public _LTRNative.LTRERROR FlashWriteEnable()
        {
            return LTR216_FlashWriteEnable(ref module);
        }

        public _LTRNative.LTRERROR FlashWriteDisable()
        {
            return LTR216_FlashWriteDisable(ref module);
        }

        public _LTRNative.LTRERROR SetISrcEnabled(bool enabled) 
        {
            return LTR216_SetISrcEnabled(ref module, enabled);
        }  

        public static string GetErrorString(_LTRNative.LTRERROR err)
        {
            IntPtr ptr = LTR216_GetErrorString((int)err);
            string str = Marshal.PtrToStringAnsi(ptr);
            Encoding srcEncodingFormat = Encoding.GetEncoding("windows-1251");
            Encoding dstEncodingFormat = Encoding.UTF8;
            return dstEncodingFormat.GetString(Encoding.Convert(srcEncodingFormat, dstEncodingFormat, srcEncodingFormat.GetBytes(str)));
        }
    }
}
