using CommonLib.LOG;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace CommonLib.DAQ
{
public class CardADLINK :INotifyPropertyChanged
{
public double[][] Threashold = null;
protected static int AllCardCount;
protected int CardNO;
///
/// 板卡在系统中的编号
///
private int CardNumberInSystem = -1;
///
/// 缓存大小
///
protected const int DATA_COUNT = CardADLINK_Wrapper.MAX_CH_NUM * CardADLINK_Wrapper.DATA_COUNT_PERCH ;
///
/// 缓存
///
protected double[] Voltage = new Double[DATA_COUNT];
private Int32[] DataBuffer = new Int32[DATA_COUNT];
private int bufLen = (DATA_COUNT * sizeof(UInt32));
private IntPtr IntPBuffer = IntPtr.Zero;
///
/// 单块卡的设置
///
public MCMDAQ_DEVICE mCMDAQ_DEVICE { get; protected set; } = new MCMDAQ_DEVICE();
#region .ctor
public CardADLINK()
{
CardNO = AllCardCount;
AllCardCount++;
}
#endregion
#region attrib
protected bool m_Enable = false;
protected ManualResetEvent EventKill = new ManualResetEvent(false);
protected Thread ThreadRead = null;
public bool Enable
{
get
{
return m_Enable;
}
set
{
Boolean bPreEn = m_Enable;
if (bPreEn != value)
{
if (value)
{
m_Enable = InitDevice();
}
else
{
CloseDevice();
m_Enable = value;
}
if (bPreEn != m_Enable)
OnPropertyChanged();
}
}
}
EventHandler EventError = null;
public int m_chlCnt = 0;
public int chlCnt
{
get
{
return m_chlCnt;
}
set
{
if (value != m_chlCnt)
{
OnPropertyChanged();
}
}
}
private void DoEventError(int errCode,string ErrorInfo)
{
ErrInfo info = new ErrInfo(errCode, ErrorInfo);
EventError?.Invoke(this,info);
}
///
/// 断开连接
///
private void CloseDevice()
{
int err = -1;
//杀死线程
try
{
if (ThreadRead != null)
{
while (ThreadRead.IsAlive)
{
EventKill.Set();
Thread.Sleep(10);
}
}
}
catch (Exception ex)
{
string Info = $"{ex.Message} \n{ex.StackTrace}";
LogStorage.Logs.Add(LogLevel.Error, Info);
DoEventError(err, Info);
}
finally
{
Marshal.FreeHGlobal(IntPBuffer);
//关闭端口
}
}
///
/// 连接设备
///
///
private bool InitDevice()
{
string Info = string.Empty;
Boolean bResult = false;
int err = -1;
ushort CardNumber = 0;
IntPBuffer = Marshal.AllocHGlobal(bufLen);
try
{
// 分配内存
// err = CardADLINK_Wrapper.MCM_Release_Card(CardNumber);
// 注册板卡,获取板卡ID
CardNumberInSystem = CardADLINK_Wrapper.MCM_Register_Card(mCMDAQ_DEVICE.HostName); // 配置板卡通道
if (CardNumberInSystem < 0)
{
throw (new Exception($"MCM_Register_Card Fail CardNumberInSystem= {CardNumberInSystem}"));
}
CardNumber = (ushort)CardNumberInSystem;
err = CardADLINK_Wrapper.MCM_AI_AsyncDblBufferMode(CardNumber, false);
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncDblBufferMode] err = {0} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
ushort wChanCfg1 = CardADLINK_Wrapper.MCM_AI_DisableIEPE | CardADLINK_Wrapper.MCM_AI_Coupling_DC | CardADLINK_Wrapper.MCM_AI_PseudoDifferential;
ushort wChanCfg2 = CardADLINK_Wrapper.MCM_AI_DisableIEPE | CardADLINK_Wrapper.MCM_AI_Coupling_DC | CardADLINK_Wrapper.MCM_AI_PseudoDifferential;
ushort wChanCfg3 = CardADLINK_Wrapper.MCM_AI_DisableIEPE | CardADLINK_Wrapper.MCM_AI_Coupling_DC | CardADLINK_Wrapper.MCM_AI_PseudoDifferential;
ushort wChanCfg4 = CardADLINK_Wrapper.MCM_AI_DisableIEPE | CardADLINK_Wrapper.MCM_AI_Coupling_DC | CardADLINK_Wrapper.MCM_AI_PseudoDifferential;
// 配置板卡通道
// 不使能IEPE,DC耦合方式,伪差分连接
err = CardADLINK_Wrapper.MCM_AI_204_Chan_Config(
CardNumber,
wChanCfg1,
wChanCfg2,
wChanCfg3,
wChanCfg4
);
if (err != 0)
{
throw new Exception($"[MCM_AI_204_Chan_Config] err ={err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
// 设置触发参数
// 使用板载时钟,立即触发
ushort wConvSrc = CardADLINK_Wrapper.MCM_AI_CONVSRC_INT;
ushort wTrigMode = CardADLINK_Wrapper.MCM_AI_TRGMOD_POST;
ushort wTrigCtrl = (ushort)CardADLINK_Wrapper.MCM_Trig_Type.MCM_AI_TRGSRC_SOFT;
uint wReTrigCnt = 0;
uint dwDLY1Cnt = 0;
uint dwDLY2Cnt = 0;
double dwTrgLevel = 0;
err = CardADLINK_Wrapper.MCM_AI_Trig_Config(
CardNumber,
wConvSrc,
wTrigMode,
wTrigCtrl,
wReTrigCnt,
dwDLY1Cnt,
dwDLY2Cnt,
dwTrgLevel
); // 使用板载时钟,立即触发
if (err != 0)
{
throw new Exception($"[MCM_AI_204_Trig_Config] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
// 使能双buffer模式
err = CardADLINK_Wrapper.MCM_AI_AsyncDblBufferMode(CardNumber, true);
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncDblBufferMode] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
// 配置通道数组,选择所有通道
UInt16[] chs = {
(UInt16) CardADLINK_Wrapper.AI_CHANNEL.AI_CH_0,
(UInt16) CardADLINK_Wrapper.AI_CHANNEL.AI_CH_1,
(UInt16) CardADLINK_Wrapper.AI_CHANNEL.AI_CH_2,
(UInt16) CardADLINK_Wrapper.AI_CHANNEL.AI_CH_3
};
// 设置每通道输入范围,±10V输入
UInt16[] adranges = {
(UInt16) CardADLINK_Wrapper.VRange.AD_B_10_V,
(UInt16) CardADLINK_Wrapper.VRange.AD_B_10_V,
(UInt16) CardADLINK_Wrapper.VRange. AD_B_10_V,
(UInt16) CardADLINK_Wrapper.VRange. AD_B_10_V
};
UInt16 asyncMode = (UInt16) CardADLINK_Wrapper.SyncMode.ASYNCH_OP;
err = CardADLINK_Wrapper.MCM_AI_ContReadMultiChannels(
CardNumber,
4,//CardADLINK_Wrapper.CH_NUM,
chs,
adranges,
IntPBuffer,
CardADLINK_Wrapper.DATA_COUNT_PERCH,
CardADLINK_Wrapper.SAMPLING_RATE,
asyncMode
);
if (err != 0)
{
throw new Exception($"[MCM_AI_ContReadMultiChannels] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
ThreadRead = new Thread(TaskRead);
ThreadRead.IsBackground = true;
ThreadRead.Start();
bResult = err == 0;
}
catch (Exception ex)
{
int err2 = CardADLINK_Wrapper.MCM_Release_Card(CardNumber); // 释放板卡资源
Info = $"{mCMDAQ_DEVICE.HostName} {ex.Message} \n{ex.StackTrace}";
LogStorage.Logs.Add(LogLevel.Error, Info);
}
finally
{
if(bResult==false)
{
CloseDeviceBySelf(CardNumber);
}
}
return bResult;
}
public EventHandler EventVoltage;
public void DoEventVoltage()
{
EventVoltage?.Invoke(this, new EventArgs());
}
private void TaskRead()
{
ushort CardNumber = (ushort)CardNumberInSystem;
int err = -1;
byte halfReady = 0;
byte stopFlag = 0;
UInt16 overrunFlag = 0;
EventKill.Reset();
try
{
while (EventKill.WaitOne(10) == false)
{
err = CardADLINK_Wrapper.MCM_AI_AsyncDblBufferHalfReady(CardNumber, out halfReady, out stopFlag);
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncDblBufferHalfReady] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
if (halfReady == 1)
{
err = CardADLINK_Wrapper.MCM_AI_AsyncDblBufferTransfer(CardNumber, IntPBuffer);
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncDblBufferTransfer] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
err = CardADLINK_Wrapper.MCM_AI_AsyncDblBufferOverrun(CardNumber, 0, out overrunFlag);
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncDblBufferOverrun] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
Marshal.Copy(IntPBuffer, DataBuffer, 0, DATA_COUNT);
err = CardADLINK_Wrapper.MCM_AI_ContVScale(CardNumber, CardADLINK_Wrapper.VRange.AD_B_10_V,
IntPBuffer, Voltage, DATA_COUNT);
if (err != 0)
{
throw new Exception($"[MCM_AI_ContVScale] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
DoEventVoltage();
}
}
}
catch (Exception ex)
{
int err2 = CardADLINK_Wrapper.MCM_Release_Card(CardNumber); // 释放板卡资源
string Info = $"{mCMDAQ_DEVICE.HostName} {ex.Message} \n{ex.StackTrace}";
LogStorage.Logs.Add(LogLevel.Error, Info);
}
finally
{
try
{
CloseDeviceBySelf(CardNumber);
}
catch(Exception ex)
{
string Info = $"{mCMDAQ_DEVICE.HostName} {ex.Message} \n{ex.StackTrace}";
LogStorage.Logs.Add(LogLevel.Error, Info);
}
}
}
#endregion
void CloseDeviceBySelf(ushort CardNumber)
{
string Info = string.Empty;
UInt32 accessCnt = 0; // 可访问数
int err = 0;
try
{
err = CardADLINK_Wrapper.MCM_AI_AsyncClear(CardNumber, ref accessCnt); // 清除缓存
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncClear] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
err = CardADLINK_Wrapper.MCM_AI_AsyncDblBufferMode(CardNumber, false); // 清除双buffer模式
if (err != 0)
{
throw new Exception($"[MCM_AI_AsyncDblBufferMode] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
err = CardADLINK_Wrapper.MCM_Release_Card(CardNumber); // 释放板卡资源
if (err != 0)
{
throw new Exception($"[MCM_Release_Card] err = {err} {((CardADLINK_Wrapper.CARDADLINK_ERROR)err).ToString()}");
}
}
catch (Exception ex)
{
Info = $"{mCMDAQ_DEVICE.HostName} {ex.Message} \n{ex.StackTrace}";
LogStorage.Logs.Add(LogLevel.Error, Info);
}
}
#region staticMethod
/*
public static int ScanDevice(Type type)
{
ushort wModuleNum = 0;
MCMDAQ_DEVICE[] _AvailModules = new MCMDAQ_DEVICE[250];
var card = Activator.CreateInstance(type);
// DAQCard card = new DAQCard();
//启动DDS模式 ,网页连上 板卡,启用
//网卡配置文件ospl.xml
// AUTO 修改为
// MCM204
//然后将网卡名字修改为 MCM204
int err = CardADLINK_Wrapper.MCM_Device_Scan(out wModuleNum, _AvailModules); // 扫描设备
if (err == 0)
{
dictCard.Clear();
CardADLINK.AllCardCount = 0;
for (int i = 0; i < wModuleNum; i++)
{
card = Activator.CreateInstance(type);
//card.mCMDAQ_DEVICE = _AvailModules[i];
//dictCard.Add(card.CardNO, card); ;
}
}
else
{
if (Debugger.isInDebug())
{
MCMDAQ_DEVICE module = new MCMDAQ_DEVICE();
module.IP = "169.254.1.11";
module.cardID = 0;
module.HostName ="MCM204-11";
module.MAC = "00:30:64:32:62:b0";
module.deviceID = 204;
module.moduleType = 5;
//card.mCMDAQ_DEVICE = module;
//dictCard.Add(card.CardNO, card);
err = 0;
}
}
return err;
}
*/
#endregion
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
///
/// //属性更新事件 CallerMemberName 自动填写属性的名字
///
/// //[CallerMemberName] 需要 4.0以上才有
///
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName=null)
{
//通过反射读取变量名,将值加入log
if (PropertyChanged != null)
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}