You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1572 lines
47 KiB
C#

using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Net.NetworkInformation;
namespace MFSerial_Lib
{
public class MFCan_DevInfo
{
public int Send_Count;
public int Recv_Count;
public string InterfaceName;
public string ProtocolVersion;
public string Name;
public string SN;
public MFCan_DevInfo()
{
Send_Count = Recv_Count = 0;
InterfaceName = "";
ProtocolVersion = "";
Name = "";
SN = "";
}
}
public class MFCan_MSG
{
public const int CAN_MSG_TYPE_SD = 0;
public const int CAN_MSG_TYPE_SR = 1;
public const int CAN_MSG_TYPE_ED = 2;
public const int CAN_MSG_TYPE_ER = 3;
public byte Ch;
public UInt32 TimeStamp_100us;
public UInt32 TimeStamp;
public Byte Type;
public UInt32 Id;
public Byte Dlc;
public Byte[] Dat;
public MFCan_MSG()
{
Dat = new byte[64];
}
public override String ToString()
{
String str;
str = string.Format("Ch={0:D2},T={1:X8},", Ch, TimeStamp);
switch(Type)
{
case CAN_MSG_TYPE_SD:
str += string.Format("SD,ID={0:X3},L={1:D2},Dat=", Id, Dlc);
break;
case CAN_MSG_TYPE_SR:
str += string.Format("SR,ID={0:X3},L={1:D2},Dat=", Id, Dlc);
break;
case CAN_MSG_TYPE_ED:
str += string.Format("ED,ID={0:X8},L={1:D2},Dat=", Id, Dlc);
break;
case CAN_MSG_TYPE_ER:
str += string.Format("ER,ID={0:X8},L={1:D2},Dat=", Id, Dlc);
break;
}
for (int i = 0; i < Dlc; i++)
str += string.Format(" {0:X2}", Dat[i]);
return str;
}
}
public class MFCan_CFG
{
//old define
public const int CHECK_MODE_NORMAL = 0;
public const int CHECK_MODE_SILENT = 1;
public const int CHECK_MODE_LOOPBACK_OUT = 2;
public const int CHECK_MODE_LOOPBACK_IN = 3;
public const int CHECK_TYPE_NOMAL = 0;
public const int CHECK_TYPE_FD_BRS = 1;
public const int CHECK_TYPE_FD_NOBRS = 2;
public const int CHECK_TYPE_FD_BRS_NONISO = 3;
public const int CHECK_TYPE_FD_NOBRS_NONISO = 4;
//redefine
public const int MODE_NORMAL = 0;
public const int MODE_SILENT = 1;
public const int MODE_LOOPBACK_EXT = 2;
public const int MODE_LOOPBACK_IN = 3;
public const int FORMAT_TYPE_CLASSIC = 0;
public const int FORMAT_TYPE_FD_BRS = 1;
public const int FORMAT_TYPE_FD_NOBRS = 2;
public const int FORMAT_TYPE_FD_BRS_NONISO = 3;
public const int FORMAT_TYPE_FD_NOBRS_NONISO = 4;
public byte Ch;
public byte Mode;
public byte Type;
public bool Ack;
public bool single;
public int NormalBps;
public int DataBps;
public MFCan_CFG(Byte ch, int bps)
{
Ch = ch;
NormalBps = bps;
DataBps = bps;
Mode = MODE_NORMAL;
Type = FORMAT_TYPE_CLASSIC;
Ack = false;
single = false;
}
public MFCan_CFG(Byte ch, int nbps, int dbps)
{
Ch = ch;
NormalBps = nbps;
DataBps = dbps;
Mode = MODE_NORMAL;
Type = FORMAT_TYPE_FD_BRS;
Ack = false;
single = false;
}
public MFCan_CFG()
{
Ch = 0;
NormalBps = 500000;
DataBps = 500000;
Mode = MODE_NORMAL;
Type = FORMAT_TYPE_CLASSIC;
Ack = false;
single = false;
}
}
public class MFLin_DevInfo
{
public int Lin_Count;
public string InterfaceName;
public string ProtocolVersion;
public string Name;
public string SN;
public MFLin_DevInfo()
{
Lin_Count = 0;
InterfaceName = "";
ProtocolVersion = "";
Name = "";
SN = "";
}
}
public class MFLin_MSG
{
public UInt32 TimeStamp;
public Byte Ch;
public Byte Err;
public Byte Id;
public Byte Dlc;
public Byte[] Dat;
public MFLin_MSG()
{
Dat = new byte[64];
}
public override String ToString()
{
String str;
str = string.Format("Ch={0:D2},T={1:X8},ID={2:X2},Len={3:D2},ERR={4:D},Data=", Ch, TimeStamp, Id, Dlc, Err);
for (int i = 0; i < Dlc; i++)
str += string.Format(" {0:X2}", Dat[i]);
return str;
}
}
public class MFLin_CFG
{
public const int CHECK_MODE_CLASSIC = 0;
public const int CHECK_MODE_ENHANCE = 1;
public Byte Ch;
public bool Master;
public Byte Check;
public int Bps;
public MFLin_CFG(Byte ch,bool ms, Byte chk,int bps)
{
Ch = ch;
Master = ms;
Check = chk;
Bps = bps;
}
public MFLin_CFG()
{
Ch = 0;
Master = true;
Check = CHECK_MODE_ENHANCE;
Bps = 19200;
}
}
public class MFLin_IDLength
{
public Byte Id;
public Byte Len;
public MFLin_IDLength(byte id,byte len)
{
Id = id;
Len = len;
}
public MFLin_IDLength()
{
Id = 0;
Len = 0;
}
}
class MFSerial
{
public int VERSION = 0x0003;
public SerialPort Serial;
public NetworkStream DataStream;
public Byte LinkChar;
private Byte[] send_buff;
private Byte[] recv_buff;
private Byte[] msg_buff;
private const int MSG_HEAD = 0x68;
private const int MSG_TAIL = 0x16;
private const int MSG_STA_HEAD = 0;
private const int MSG_STA_LENGTH = 1;
private const int MSG_STA_DAT = 2;
private const int MSG_STA_CS = 3;
private const int MSG_STA_TAIL = 4;
//command code for can
private const int U2CAN_COM_ENTER = 0;
private const int U2CAN_COM_LINK = 1;
private const int U2CAN_COM_SYNC = 9;
private const int U2CAN_COM_SEND = 2;
private const int U2CAN_COM_RECV = 3;
private const int U2CAN_COM_SETCFG = 4;
private const int U2CAN_COM_SETMODE = 5;
private const int U2CAN_COM_READCFG = 6;
private const int U2CAN_COM_FILTER_ID = 7;
private const int U2CAN_COM_ADVSET = 10;
private const int U2CAN_COM_ADVMSG = 11;
private const int U2LIN_COM_ENTER = 0;
private const int U2LIN_COM_LINK = 1;
private const int U2LIN_COM_SYNC = 9;
//command code for lin
private const int U2LIN_COM_RECV = 0x10;
private const int U2LIN_COM_SEND = 0X11;
private const int U2LIN_COM_SETRES = 0x12;
private const int U2LIN_COM_SETMODE = 0x13;
private const int U2LIN_COM_EVENT = 0x14;
private const int U2LIN_COM_SETLEN = 0x15;
private const int U2LIN_COM_SETBPS = 0x16;
private const int U2LIN_COM_SERLEN = 0x17;
private const int U2LIN_CH_MAX = 4;
private const int U2CAN_CH_MAX = 4;
private Queue<Byte[]> Q_can_ack; //can
private Queue<Byte[]> Q_lin_ack;
private Queue<Byte[]> Q_uni_ack; //common ack
private Queue<Byte[]> Q_can_dat;
private Queue<Byte[]> Q_lin_dat;
public event EventHandler<EventArgs> MsgPushEvent;
//for recv msg state
private int MsgState;
private int MsgRp;
private int MsgLen;
private Byte MsgCs;
private Thread read_thread;
private Mutex Queuemutex;
private Mutex Writemutex;
//device infomation
public string Device_CanVersion;
public string Device_LinVersion;
public string Device_Name;
public string Device_SN;
//lin
public MFLin_CFG Lin_Cfg;
public bool Lin_Is_Opened;
public int Lin_Count;
public int Lin_Count_Max = 0;
public int UL_RES_DAT_MAX = 64;
private byte[] IdLengthBuff;
//can
public bool Can_Is_Opened;
public int Can_Send_Count;
public int Can_Recv_Count;
public int Can_Recv_Count_Max = 999999999;
public MFSerial()
{
send_buff = new Byte[1024];
recv_buff = new Byte[1024];
msg_buff = new Byte[1024];
IdLengthBuff = new Byte[64* U2LIN_CH_MAX];
for (int i = 0; i < IdLengthBuff.Length; i++)
IdLengthBuff[i] = 0;
Q_uni_ack = new Queue<Byte[]>();
Q_can_ack = new Queue<Byte[]>();
Q_lin_ack = new Queue<Byte[]>();
Q_can_dat = new Queue<Byte[]>();
Q_lin_dat = new Queue<Byte[]>();
Queuemutex = new Mutex();
Writemutex = new Mutex();
MsgState = MSG_STA_HEAD;
read_thread = null;
Lin_Cfg = new MFLin_CFG(0, true, MFLin_CFG.CHECK_MODE_CLASSIC, 19200);
Serial = null;
DataStream = null;
Can_Is_Opened = false;
Lin_Is_Opened = false;
LinkChar = (Byte)'L';
}
public bool SyncTimeStamp(UInt32 ts)
{
Byte[] msg = new Byte[1024];
msg[0] = 0x09;
msg[1] = (Byte)(ts >> 0) ;
msg[2] = (Byte)(ts >> 8);
msg[3] = (Byte)(ts >> 16);
msg[4] = (Byte)(ts >> 24);
write_msg(msg, 5);
return true;
}
public bool Can_Open(string portname, int bps)
{
if (DataStream != null) return false;
if (Can_Is_Opened) return true;
if(Serial == null)
{
Serial = new SerialPort();
Serial.Parity = System.IO.Ports.Parity.None;
Serial.DataBits = 8;
Serial.StopBits = System.IO.Ports.StopBits.One;
Serial.Handshake = System.IO.Ports.Handshake.None;
Serial.WriteBufferSize = 4096;
Serial.ReadBufferSize = 4096;
// Set the read/write timeouts
Serial.ReadTimeout = 1;
Serial.WriteTimeout = 50;
Serial.DtrEnable = true;
}
if (!Serial.IsOpen)
{
try
{
Serial.PortName = portname;
Serial.BaudRate = bps;
Serial.Open();
}
catch
{
return false;
}
}
if (read_thread == null)
{
read_thread = new Thread(new ThreadStart(read_task));
read_thread.Start();
}
Queuemutex.WaitOne();
Q_can_ack.Clear();
Queuemutex.ReleaseMutex();
Byte[] msg = new Byte[1024];
msg[0] = 0x41;
msg[1] = LinkChar;
write_msg(msg, 2);
Thread.Sleep(100);
while (Q_can_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] buff = Q_can_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (buff[1] == 'U' && buff[2] == '2' && buff[3] == 'C')
{
Can_Is_Opened = true;
Can_Recv_Count = Q_lin_dat.Count;
Can_Send_Count = 0;
Device_CanVersion = System.Text.Encoding.Default.GetString(buff, 1, 8);
if (buff.Length > 9)
{
int i, pos;
for (i = 0; i < 32; i++)
{
byte c = buff[10 + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_Name = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
pos = i + 10 + 1;
for (i = 0; i < 32; i++)
{
if (pos + i >= buff.Length) break;
byte c = buff[pos + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_SN = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
}
return true;
}
}
try
{
if(Lin_Is_Opened == false) Serial.Close();
}
catch { };
return false;
}
public bool Can_Open(NetworkStream stream)
{
if (Serial != null) return false;
if (DataStream != null)
{
if (DataStream != stream) return false;
}
else
{
DataStream = stream;
}
if (Can_Is_Opened) return true;
if (read_thread == null)
{
read_thread = new Thread(new ThreadStart(read_task));
read_thread.Start();
}
Queuemutex.WaitOne();
Q_can_ack.Clear();
Queuemutex.ReleaseMutex();
Byte[] msg = new Byte[1024];
msg[0] = 0x41;
msg[1] = LinkChar;
write_msg(msg, 2);
Thread.Sleep(100);
while (Q_can_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] buff = Q_can_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (buff[1] == 'U' && buff[2] == '2' && buff[3] == 'C')
{
Can_Is_Opened = true;
Can_Recv_Count = Q_lin_dat.Count;
Can_Send_Count = 0;
Device_CanVersion = System.Text.Encoding.Default.GetString(buff, 1, 8);
if (buff.Length > 9)
{
int i, pos;
for (i = 0; i < 32; i++)
{
byte c = buff[10 + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_Name = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
pos = i + 10 + 1;
for (i = 0; i < 32; i++)
{
if (pos + i >= buff.Length) break;
byte c = buff[pos + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_SN = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
}
return true;
}
}
return false;
}
public MFCan_DevInfo MFCanGetInfo()
{
MFCan_DevInfo dev;
dev = new MFCan_DevInfo();
dev.Send_Count = Can_Send_Count;
dev.Recv_Count = Can_Recv_Count;
dev.ProtocolVersion = Device_CanVersion;
dev.Name = Device_Name;
dev.SN = Device_SN;
if (DataStream != null) dev.InterfaceName = "TCP";
else if (Serial != null) dev.InterfaceName = Serial.PortName;
return dev;
}
public bool CanClose()
{
Can_Is_Opened = false;
Device_CanVersion = "";
if (Lin_Is_Opened == false)
{
Device_Name = "";
Device_SN = "";
if (Serial != null)
{
try { Serial.Close(); } catch { }
Serial = null;
}
if (DataStream != null) DataStream = null;
if (read_thread != null) read_thread.Abort();
read_thread = null;
}
return true;
}
public bool CanSet(MFCan_CFG cfg)
{
Byte[] buff = new Byte[1024];
if (Can_Is_Opened == false) return false;
Queuemutex.WaitOne();
Q_can_ack.Clear();
Queuemutex.ReleaseMutex();
buff[0] = 0x40+ U2CAN_COM_SETCFG;
buff[1] = cfg.Ch;
buff[2] = (Byte)(cfg.NormalBps >> 0);
buff[3] = (Byte)(cfg.NormalBps >> 8);
buff[4] = (Byte)(cfg.NormalBps >> 16);
buff[5] = (Byte)(cfg.NormalBps >> 24);
buff[6] = 0;
write_msg(buff, 7);
for (int i = 0; i < 200; i++)
{
if (Q_can_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] rmsg = Q_can_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (rmsg[1] == U2CAN_COM_SETCFG) return true;
}
Thread.Sleep(1);
}
return false;
}
public bool CanAdvSet(MFCan_CFG cfg)
{
Byte[] buff = new Byte[1024];
if (Can_Is_Opened == false) return false;
Queuemutex.WaitOne();
Q_can_ack.Clear();
Queuemutex.ReleaseMutex();
buff[0] = 0x40 + U2CAN_COM_ADVSET;
buff[1] = cfg.Ch;
buff[2] = cfg.Mode;
buff[3] = cfg.Type;
buff[4] = (Byte)(cfg.NormalBps >> 0);
buff[5] = (Byte)(cfg.NormalBps >> 8);
buff[6] = (Byte)(cfg.NormalBps >> 16);
buff[7] = (Byte)(cfg.NormalBps >> 24);
buff[8] = (Byte)(cfg.DataBps >> 0);
buff[9] = (Byte)(cfg.DataBps >> 8);
buff[10] = (Byte)(cfg.DataBps >> 16);
buff[11] = (Byte)(cfg.DataBps >> 24);
write_msg(buff, 12);
for (int i = 0; i < 200; i++)
{
if (Q_can_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] rmsg = Q_can_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (rmsg[1] == U2CAN_COM_ADVSET) return true;
}
Thread.Sleep(1);
}
return false;
}
public bool CanSendOne(MFCan_MSG msg)
{
if (Can_Is_Opened == false) return false;
Byte[] buff = new Byte[256];
for (int i = 0; i < buff.Length; i++)
buff[i] = 0;
buff[0] = U2CAN_COM_SEND;
buff[1] = (byte)msg.Ch;
buff[2] = 1;
//3 4 5 6
byte n = msg.Dlc;
if (n > 8) n = 8;
buff[5] = n;
switch (msg.Type)
{
case MFCan_MSG.CAN_MSG_TYPE_SR:
buff[6] = 0x40;
break;
case MFCan_MSG.CAN_MSG_TYPE_ED:
buff[6] = 0x80;
break;
case MFCan_MSG.CAN_MSG_TYPE_ER:
buff[6] = 0xC0;
break;
default:break;
}
//id 7 8 9 10
buff[7] = (Byte)(msg.Id >> 0);
buff[8] = (Byte)(msg.Id >> 8);
buff[9] = (Byte)(msg.Id >> 16);
buff[10] = (Byte)(msg.Id >> 24);
//DAT
for (int i = 0; i < n; i++)
buff[11 + i] = msg.Dat[i];
write_msg(buff, 19);
return false;
}
public bool CanSendAdvOne(MFCan_MSG msg)
{
if (Can_Is_Opened == false) return false;
Byte[] buff = new Byte[256];
buff[0] = U2CAN_COM_ADVMSG;
buff[1] = (byte)msg.Ch;
buff[2] = 1;
//id
buff[3] = (Byte)(msg.Id >> 0);
buff[4] = (Byte)(msg.Id >> 8);
buff[5] = (Byte)(msg.Id >> 16);
buff[6] = (Byte)(msg.Id >> 24);
buff[7] = msg.Type;
byte n = msg.Dlc;
if (n > 64) n = msg.Dlc;
buff[8] = n;
//DAT
for (int i = 0; i < n; i++)
buff[9 + i] = msg.Dat[i];
write_msg(buff, n+9);
return false;
}
public int MFCanGetMsg(MFCan_MSG[] msg,int num)
{
int cnt = 0;
while (Q_can_dat.Count > 0)
{
Queuemutex.WaitOne();
Byte[] buff = Q_can_dat.Dequeue();
Queuemutex.ReleaseMutex();
if (buff[0] == U2CAN_COM_RECV)
{
msg[cnt].Ch = buff[1];
msg[cnt].TimeStamp = (uint)(buff[3 ]) + (uint)(buff[4] << 8) + (uint)(buff[5] << 16) + (uint)(buff[6] << 24);
msg[cnt].Dlc = buff[9];
if ((buff[10] & 0x80) > 0) //ext
{
if ((buff[10 ] & 0x40) > 0) //remote
{
msg[cnt].Type = MFCan_MSG.CAN_MSG_TYPE_ER;
}
else //data
{
msg[cnt].Type = MFCan_MSG.CAN_MSG_TYPE_ED;
}
}
else //std
{
if ((buff[10] & 0x40) > 0) //remote
{
msg[cnt].Type = MFCan_MSG.CAN_MSG_TYPE_SR;
}
else //data
{
msg[cnt].Type = MFCan_MSG.CAN_MSG_TYPE_SD;
}
}
msg[cnt].Id = (uint)(buff[11 ]) + (uint)(buff[12] << 8) + (uint)(buff[13] << 16) + (uint)(buff[14] << 24);
for (int i = 0; i < 8; i++)
{
msg[cnt].Dat[i] = buff[15 + i];
}
if(Can_Recv_Count > 0) Can_Recv_Count--;
cnt++;
}
else if (buff[0] == U2CAN_COM_ADVMSG)
{
msg[cnt].Ch = buff[1];
msg[cnt].TimeStamp_100us = (uint)(buff[3]) + (uint)(buff[4] << 8) + (uint)(buff[5] << 16) + (uint)(buff[6] << 24);
msg[cnt].TimeStamp = msg[cnt].TimeStamp_100us/10;
msg[cnt].Id = (uint)(buff[7]) + (uint)(buff[8] << 8) + (uint)(buff[9] << 16) + (uint)(buff[10] << 24);
msg[cnt].Type = buff[11];
msg[cnt].Dlc = buff[12];
for (int i = 0; i < msg[cnt].Dlc; i++)
{
msg[cnt].Dat[i] = buff[13 + i];
}
if (Can_Recv_Count > 0) Can_Recv_Count--;
cnt++;
}
if (cnt >= num) break;
}
return cnt;
}
public bool Lin_Open(string portname,int bps)
{
if (DataStream != null) return false;
if (Lin_Is_Opened == true) return true;
if (Serial == null)
{
Serial = new SerialPort();
Serial.Parity = System.IO.Ports.Parity.None;
Serial.DataBits = 8;
Serial.StopBits = System.IO.Ports.StopBits.One;
Serial.Handshake = System.IO.Ports.Handshake.None;
Serial.WriteBufferSize = 4096;
Serial.ReadBufferSize = 4096;
// Set the read/write timeouts
Serial.ReadTimeout = 1;
Serial.WriteTimeout = 50;
Serial.DtrEnable = true;
}
if (!Serial.IsOpen)
{
try
{
Serial.PortName = portname;
Serial.BaudRate = bps;
Serial.Open();
}
catch
{
return false;
}
}
if (read_thread == null)
{
read_thread = new Thread(new ThreadStart(read_task));
read_thread.Start();
}
Queuemutex.WaitOne();
Q_lin_ack.Clear();
Queuemutex.ReleaseMutex();
Byte[] msg = new Byte[1024];
msg[0] = 0x41;
msg[1] = LinkChar;
write_msg(msg, 2);
Thread.Sleep(100);
while (Q_lin_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] buff = Q_lin_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (buff[1] == 'U' && buff[2] == '2' && buff[3] == 'L')
{
Lin_Is_Opened = true;
Lin_Count = Q_lin_dat.Count;
Device_LinVersion = System.Text.Encoding.Default.GetString(buff, 1,8);
if (buff.Length > 9)
{
int i,pos;
for (i = 0; i < 32; i++)
{
byte c = buff[10 + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_Name = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
pos = i + 10 + 1;
for (i = 0; i < 32; i++)
{
if(pos + i >= buff.Length) break;
byte c = buff[pos + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_SN = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
}
return true;
}
}
try
{
if (Can_Is_Opened == false) Serial.Close();
} catch { };
return false;
}
public bool Lin_Open(NetworkStream stream)
{
if (Serial != null) return false;
if (DataStream != null)
{
if (DataStream != stream) return false;
}
else
{
DataStream = stream;
}
if (Lin_Is_Opened) return true;
if (read_thread == null)
{
read_thread = new Thread(new ThreadStart(read_task));
read_thread.Start();
}
Queuemutex.WaitOne();
Q_lin_ack.Clear();
Queuemutex.ReleaseMutex();
Byte[] msg = new Byte[1024];
msg[0] = 0x41;
msg[1] = LinkChar;
write_msg(msg, 2);
Thread.Sleep(100);
while (Q_lin_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] buff = Q_lin_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (buff[1] == 'U' && buff[2] == '2' && buff[3] == 'L')
{
Lin_Is_Opened = true;
Lin_Count = Q_lin_dat.Count;
Device_LinVersion = System.Text.Encoding.Default.GetString(buff, 1, 8);
if (buff.Length > 9)
{
int i, pos;
for (i = 0; i < 32; i++)
{
byte c = buff[10 + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_Name = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
pos = i + 10 + 1;
for (i = 0; i < 32; i++)
{
if (pos + i >= buff.Length) break;
byte c = buff[pos + i];
if (c == 0) break;
msg_buff[i] = c;
}
msg_buff[i] = 0;
Device_SN = System.Text.Encoding.Default.GetString(msg_buff, 0, i);
}
return true;
}
}
return false;
}
public MFLin_DevInfo MFLinGetInfo()
{
MFLin_DevInfo dev;
dev = new MFLin_DevInfo();
dev.Lin_Count = Lin_Count;
dev.ProtocolVersion = Device_LinVersion;
dev.Name = Device_Name;
dev.SN = Device_SN;
if (DataStream != null) dev.InterfaceName = "TCP";
else if (Serial != null) dev.InterfaceName = Serial.PortName;
return dev;
}
public bool MFLinIsOpen()
{
return Lin_Is_Opened;
}
public bool LinClose()
{
Lin_Is_Opened = false;
Device_LinVersion = "";
if (Can_Is_Opened == false)
{
Device_Name = "";
Device_SN = "";
if (Serial != null)
{
try { Serial.Close(); } catch { }
Serial = null;
}
if (DataStream != null) DataStream = null;
if (read_thread != null) read_thread.Abort();
read_thread = null;
}
return true;
}
public bool LinSet(MFLin_CFG cfg)
{
Byte[] buff = new Byte[1024];
if (Lin_Is_Opened == false) return false;
Queuemutex.WaitOne();
Q_lin_ack.Clear();
Queuemutex.ReleaseMutex();
buff[0] = 0x53;
buff[1] = cfg.Ch;
if (cfg.Master) buff[2] = 0x01;
else buff[2] = 0x00;
if (cfg.Check == MFLin_CFG.CHECK_MODE_ENHANCE) buff[2] |= 1 << 2;
write_msg(buff, 3);
for(int i = 0; i< 200; i++)
{
if(Q_lin_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] rmsg = Q_lin_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (rmsg[0] == U2LIN_COM_SETMODE) goto setbps;
}
Thread.Sleep(1);
}
return false;
setbps:
buff[0] = 0xd6;
buff[1] = cfg.Ch;
buff[2] = (Byte)(cfg.Bps >> 0);
buff[3] = (Byte)(cfg.Bps >> 8);
buff[4] = (Byte)(cfg.Bps >> 16);
buff[5] = (Byte)(cfg.Bps >> 24);
write_msg(buff, 6);
for (int i = 0; i < 200; i++)
{
if (Q_lin_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] rmsg = Q_lin_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (rmsg[0] == U2LIN_COM_SETMODE)
{
Lin_Cfg.Ch = rmsg[1];
if ((rmsg[2] & 0x01) != 0) Lin_Cfg.Master = true;
else Lin_Cfg.Master = false;
if (((rmsg[2]>>2)& 0x03) == 0x01) Lin_Cfg.Check = MFLin_CFG.CHECK_MODE_ENHANCE;
else Lin_Cfg.Check = MFLin_CFG.CHECK_MODE_CLASSIC;
Lin_Cfg.Bps = rmsg[5] << 0 | rmsg[6] << 8 | rmsg[7] << 16 | rmsg[8] << 24;
return true;
}
}
Thread.Sleep(1);
}
return false;
}
public bool LinSetIdLength(byte ch,MFLin_IDLength[] set)
{
Byte[] buff = new Byte[1024];
if(ch >= U2LIN_CH_MAX) return false;
if (Lin_Is_Opened == false) return false;
Queuemutex.WaitOne();
Q_lin_ack.Clear();
Queuemutex.ReleaseMutex();
for (int i = 0; i < set.Length; i++)
{
byte id, len;
id = set[i].Id;
len = set[i].Len;
if (id < 0x40 && len < UL_RES_DAT_MAX)
{
IdLengthBuff[ch*64+id] = len;
}
}
buff[0] = U2LIN_COM_SETLEN | 0x40;
buff[1] = ch;
Array.Copy(IdLengthBuff, ch * 64, buff, 2, 64);
write_msg(buff, 66);
for (int i = 0; i < 200; i++)
{
if (Q_lin_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] rmsg = Q_lin_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (rmsg[0] == U2LIN_COM_ENTER && rmsg[1] == U2LIN_COM_SETLEN) return true;
}
Thread.Sleep(1);
}
return false;
}
public bool LinUpLoad(MFLin_MSG Msg,bool ack)
{
Byte[] buff = new Byte[1024];
if (Lin_Is_Opened == false) return false;
Queuemutex.WaitOne();
Q_lin_ack.Clear();
Queuemutex.ReleaseMutex();
buff[0] = U2LIN_COM_SETRES ;
if (ack) buff[0] |= 0x40;
buff[1] = Msg.Ch;
buff[2] = 1;
buff[3] = Msg.Id;
if (Msg.Dlc > UL_RES_DAT_MAX) Msg.Dlc = (byte)UL_RES_DAT_MAX;
buff[4] = Msg.Dlc;
Array.Copy(Msg.Dat, 0, buff, 5, Msg.Dlc);
write_msg(buff, Msg.Dlc + 5);
if (ack == false) return true;
for (int i = 0; i < 200; i++)
{
if (Q_lin_ack.Count > 0)
{
Queuemutex.WaitOne();
Byte[] rmsg = Q_lin_ack.Dequeue();
Queuemutex.ReleaseMutex();
if (rmsg[0] == U2LIN_COM_ENTER && rmsg[1] == U2LIN_COM_SETRES) return true;
}
Thread.Sleep(1);
}
return false;
}
public bool LinSlaveDisable( byte ch, byte id)
{
MFLin_MSG res_msg = new MFLin_MSG();
res_msg.Ch = ch;
res_msg.Id = id;
res_msg.Dlc = 0;
return LinUpLoad(res_msg,true);
}
public bool LinMasterSend( byte ch, byte id)
{
Byte[] buff = new Byte[64];
buff[0] = U2LIN_COM_SEND;
buff[1] = ch;
buff[2] = 13;
buff[3] = id;
write_msg(buff, 4);
return true;
}
public bool LinMasterSendOne(MFLin_MSG Msg)
{
LinUpLoad(Msg,true);
LinMasterSend( Msg.Ch, Msg.Id);
return true;
}
public int MFLinGetMsg(MFLin_MSG[] msg, int num)
{
int cnt = 0;
while (Q_lin_dat.Count > 0)
{
Queuemutex.WaitOne();
Byte[] buff = Q_lin_dat.Dequeue();
Queuemutex.ReleaseMutex();
if (buff[0] == U2LIN_COM_RECV)
{
msg[cnt].Ch = buff[1];
msg[cnt].TimeStamp = (uint)(buff[2]) + (uint)(buff[3] << 8) + (uint)(buff[4] << 16) + (uint)(buff[5] << 24);
msg[cnt].Err = buff[6];
msg[cnt].Id = buff[7];
msg[cnt].Dlc = (byte)buff[8];
for (int i = 0; i < buff[8]; i++)
{
msg[cnt].Dat[i] = buff[9 + i];
}
}
else if (buff[0] == U2LIN_COM_EVENT)
{
msg[cnt].Ch = buff[1];
msg[cnt].TimeStamp = (uint)(buff[2]) + (uint)(buff[3] << 8) + (uint)(buff[4] << 16) + (uint)(buff[5] << 24);
msg[cnt].Err = (byte)(buff[6] + 6);
msg[cnt].Id = 0;
msg[cnt].Dlc = 0;
}
if (Lin_Count > 0) Lin_Count--;
if (++cnt >= num) break;
}
return cnt;
}
// for class self
public bool write_msg(Byte[] msg, int num)
{
int i;
int csum;
Writemutex.WaitOne();
send_buff[0] = MSG_HEAD;
send_buff[1] = (Byte)(num & 0xff);
send_buff[2] = (Byte)((num >> 8) & 0xff);
csum = send_buff[0] + send_buff[1] + send_buff[2];
for (i = 0; i < num; i++)
{
send_buff[3 + i] = msg[i];
csum += msg[i];
}
send_buff[3 + i] = (Byte)(csum & 0xff);
send_buff[3 + i + 1] = MSG_TAIL;
num += 5;
try
{
if (DataStream != null) DataStream.Write(send_buff, 0, num);
else if(Serial != null) Serial.Write(send_buff, 0, num);
}
catch { };
Writemutex.ReleaseMutex();
return true;
}
private void read_task()
{
int ret;
while (true)
{
ret = read_dat_proc();
if(ret < 0) Thread.Sleep(2);
else Thread.Sleep(20);
}
}
private int read_dat_proc()
{
int i;
int num;
try
{
if (DataStream != null) num = DataStream.Read(recv_buff, 0, 1024);
else if (Serial != null) num = Serial.Read(recv_buff, 0, 1024);
else return -1;
}
catch
{
return -1;
}
for (i = 0; i < num; i++)
{
switch (MsgState)
{
case MSG_STA_HEAD:
if (recv_buff[i] == MSG_HEAD)
{
MsgState = MSG_STA_LENGTH;
MsgRp = 0;
MsgLen = 2;
}
break;
case MSG_STA_LENGTH:
msg_buff[MsgRp] = recv_buff[i];
MsgRp++;
MsgLen -= 1;
if (MsgLen == 0)
{
MsgLen = msg_buff[0] + msg_buff[1] * 256;
if (MsgLen > 1023)
{
MsgState = MSG_STA_HEAD;
}
else
{
MsgCs = (Byte)(MSG_HEAD + msg_buff[0] + msg_buff[1]); //
MsgState = MSG_STA_DAT;
MsgRp = 0;
}
}
break;
case MSG_STA_DAT:
msg_buff[MsgRp] = recv_buff[i];
MsgRp += 1;
MsgCs += recv_buff[i];
if (MsgRp == MsgLen)
{
MsgState = MSG_STA_CS;
}
break;
case MSG_STA_CS:
if ((MsgCs & 0xff) == recv_buff[i]) MsgState = MSG_STA_TAIL;
else MsgState = MSG_STA_HEAD;
break;
case MSG_STA_TAIL:
if (recv_buff[i] == MSG_TAIL)
{
msg_push(msg_buff, MsgLen);
}
MsgState = MSG_STA_HEAD;
break;
default:
MsgState = MSG_STA_HEAD;
break;
}
}
return num;
}
private void msg_push(Byte[] msg, int len)
{
if ((msg[0] & 0x80) == 0) return;//no dir flag
msg[0] = (Byte)(msg[0] & 0x3f);
Byte[] pbuff = new Byte[len];
Array.Copy(msg, pbuff, len);
Queuemutex.WaitOne();
if (MsgPushEvent != null) MsgPushEvent(pbuff, null);
switch (msg[0])
{
case 0x00:
if (msg[1] >= 0x02 && msg[1] <= 0x0f)
{ //can ack
Q_can_ack.Enqueue(pbuff);
}
else if (msg[1] >= 0x10 && msg[1] <= 0x1e)
{ //lin ack
Q_lin_ack.Enqueue(pbuff);
}
else
{
//uni_ack
Q_uni_ack.Enqueue(pbuff);
}
break;
case 0x01: //link
if (msg[3] == 'C')
{
//can ack
Q_can_ack.Enqueue(pbuff);
}
if (msg[3] == 'L')
{
//lin ack
Q_lin_ack.Enqueue(pbuff);
}
break;
case 0x03: //can data
{
int n = pbuff[2];
int pos = 3;
for(int i = 0; i< n; i++)
{
if (Can_Recv_Count > Can_Recv_Count_Max) break;
byte[] mbuff = new Byte[23];
mbuff[0] = pbuff[0];
mbuff[1] = pbuff[1];
mbuff[2] = 1;
if (pos+20 > pbuff.Length) break;
Array.Copy(pbuff, pos, mbuff ,3, 20);
Q_can_dat.Enqueue(mbuff);
pos += 20;
Can_Recv_Count++;
}
}
break;
case 0x0b: //adv can data
{
int n = pbuff[2];
int pos = 3;
for (int i = 0; i < n; i++)
{
if (Can_Recv_Count > Can_Recv_Count_Max) break;
if (pos + 5 > pbuff.Length) break;
int datlen = pbuff[pos + 9];
if (datlen > 64) break;
byte[] mbuff = new Byte[3 + 10 + datlen];
mbuff[0] = pbuff[0];
mbuff[1] = pbuff[1];
mbuff[2] = 1;
if (pos + 10 + datlen > pbuff.Length) break;
Array.Copy(pbuff, pos, mbuff, 3, 10 + datlen);
Q_can_dat.Enqueue(mbuff);
pos += 10 + datlen;
Can_Recv_Count++;
}
}
break;
case 0x10:
case 0x14:
//lin dat
Q_lin_dat.Enqueue(pbuff);
break;
default:
if (msg[0] >= 0x02 && msg[0] <= 0x0f)
{ //can ack
Q_can_ack.Enqueue(pbuff);
}
else if (msg[0] >= 0x10 && msg[0] <= 0x1e)
{ //link ack
Q_lin_ack.Enqueue(pbuff);
}
else
{// other
Q_uni_ack.Enqueue(pbuff);
}
break;
}
Queuemutex.ReleaseMutex();
}
}
class MFNetDevice
{
public string Name;
public string ServerPort;
public string Ip;
}
struct UdpState
{
public UdpClient u;
public IPEndPoint e;
}
class MFNetDeviceScanner
{
public bool Scanning;
private UdpState sta;
List <MFNetDevice> DevList;
public delegate void ScanDevResult(MFNetDevice dev);
public event ScanDevResult FoundADevice;
public MFNetDeviceScanner()
{
Scanning = false;
DevList = new List<MFNetDevice>();
}
public void ReceiveCallback(IAsyncResult ar)
{
UdpClient u = ((UdpState)(ar.AsyncState)).u;
IPEndPoint e = ((UdpState)(ar.AsyncState)).e;
byte[] receiveBytes;
try
{
receiveBytes = u.EndReceive(ar, ref e);
}
catch {
Scanning = false;
return;
}
string receiveString = System.Text.Encoding.ASCII.GetString(receiveBytes);
string[] strs = receiveString.Split(' ');
if(strs.Length == 2)
{
MFNetDevice dev = new MFNetDevice();
dev.Ip = e.Address.ToString();
dev.Name = strs[0];
dev.ServerPort = strs[1];
MFNetDevice result = DevList.Find(
delegate (MFNetDevice d)
{
return d.Name == dev.Name;
}
);
if (result == null)
{
DevList.Add(dev);
if (FoundADevice != null) FoundADevice(dev);
}
}
try
{
u.BeginReceive(new AsyncCallback(ReceiveCallback), sta);
}
catch
{
Scanning = false;
}
}
public bool Start(int port)
{
if (Scanning) return true;
DevList.Clear();
IPEndPoint e = new IPEndPoint(IPAddress.Any, port);
UdpClient u = new UdpClient(e);
sta = new UdpState();
sta.e = e;
sta.u = u;
try
{
u.BeginReceive(new AsyncCallback(ReceiveCallback), sta);
}
catch { return false; }
Scanning = true;
return true;
}
public bool Stop()
{
try
{
if(Scanning) sta.u.Close();
}
catch { };
Scanning = false;
return true;
}
}
}