628 lines
13 KiB
C#
628 lines
13 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
using LFP_Manager.DataStructure;
|
|
|
|
namespace LFP_Manager.Function
|
|
{
|
|
public static class csSbCanAPI
|
|
{
|
|
#region CONST DATA
|
|
|
|
/*************************************
|
|
define
|
|
**************************************/
|
|
public static bool ISDAR(byte x)
|
|
{
|
|
return (x & 0x01) != 0x00;
|
|
}
|
|
|
|
public static bool ISABOR(byte x)
|
|
{
|
|
return (x & 0x02) != 0x00;
|
|
}
|
|
|
|
public static void SETDAR(ref byte x)
|
|
{
|
|
x |= 0x01;
|
|
}
|
|
public static void SETABOR(ref byte x)
|
|
{
|
|
x |= 0x02;
|
|
}
|
|
|
|
// VCP Status Const data
|
|
public const byte CS_CANv2_ActiveMode = 0x11;
|
|
public const byte CS_CANv2_SetupMode = 0x10;
|
|
public const byte uCAN_VCOM = 0x21;
|
|
public const byte eCAN_VCOM = 0x31;
|
|
public const byte NotConnect = 0x00;
|
|
public const byte NotFind = 0xFF;
|
|
|
|
// CAN
|
|
public const byte CR = 0x0D;
|
|
|
|
// Error Code
|
|
public const byte Invalid_Arg = 0x01;
|
|
public const byte No_Error = 0x00;
|
|
|
|
#endregion
|
|
|
|
public static bool IsSTD(byte format)
|
|
{
|
|
if ((format & 0x06) == 0x04)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
public static bool IsEXT(byte format)
|
|
{
|
|
if ((format & 0x06) == 0x06)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
public static bool IsDATA(byte format)
|
|
{
|
|
if ((format & 0x05) == 0x04)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
public static bool IsREMOTE(byte format)
|
|
{
|
|
if ((format & 0x05) == 0x05)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
public static byte SendCANTxFrame(CAN_Struct Tx, ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
byte ind = 0;
|
|
byte tmp_index = 0;
|
|
byte[] buf = new byte[40];
|
|
|
|
switch (Tx.Format)
|
|
{
|
|
case (byte)CAN_StructFormat.TX_STD_DATA: buf[ind++] = (byte)CAN_SerialCommandHeader.STD_DATA; break;
|
|
case (byte)CAN_StructFormat.TX_STD_REMOTE: buf[ind++] = (byte)CAN_SerialCommandHeader.STD_REMOTE; break;
|
|
case (byte)CAN_StructFormat.TX_EXT_DATA: buf[ind++] = (byte)CAN_SerialCommandHeader.EXT_DATA; break;
|
|
case (byte)CAN_StructFormat.TX_EXT_REMOTE: buf[ind++] = (byte)CAN_SerialCommandHeader.EXT_REMOTE; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
if (IsSTD(Tx.Format))
|
|
tmp_index = 3;
|
|
else if (IsEXT(Tx.Format))
|
|
tmp_index = 8;
|
|
|
|
for (int i = 1; i <= tmp_index; i++)
|
|
{
|
|
buf[ind++] = toASCII_HEX(Div_4(Tx.ID, (byte)(tmp_index - i)));
|
|
}
|
|
|
|
buf[ind++] = toASCII_HEX(Tx.DLC);
|
|
|
|
if (IsDATA(Tx.Format))
|
|
{
|
|
|
|
for (int i = 0; i < Tx.DLC; i++)
|
|
{
|
|
buf[ind++] = toASCII_HEX(Div_4(Tx.DATA[i], 1));
|
|
buf[ind++] = toASCII_HEX(Div_4(Tx.DATA[i], 0));
|
|
}
|
|
}
|
|
|
|
buf[ind++] = CR;
|
|
|
|
if (ind > BufferSize)
|
|
return Invalid_Arg;
|
|
|
|
ConvertSize = ind;
|
|
|
|
for (int i = 0; i < ind; i++)
|
|
{
|
|
SerialBuffer[i] = buf[i];
|
|
}
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
public static byte SetSerialConfig(SerialConfigInfo info, ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
|
|
byte len;
|
|
byte[] buf = new byte[21];
|
|
|
|
buf[0] = (byte)'W';
|
|
buf[1] = (byte)'S';
|
|
switch (info.flow)
|
|
{
|
|
case (byte)FlowControl.NoFlowControl: buf[2] = (byte)'N'; break;
|
|
case (byte)FlowControl.HardwareControl: buf[2] = (byte)'H'; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
switch (info.data)
|
|
{
|
|
case (byte)DataBits.Data8: buf[3] = (byte)'8'; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
switch (info.parity)
|
|
{
|
|
case (byte)Parity.NoParity: buf[4] = (byte)'N'; break;
|
|
case (byte)Parity.EvenParity: buf[4] = (byte)'E'; break;
|
|
case (byte)Parity.OddParity: buf[4] = (byte)'O'; break;
|
|
case (byte)Parity.SpaceParity: buf[4] = (byte)'S'; break;
|
|
case (byte)Parity.MarkParity: buf[4] = (byte)'M'; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
switch (info.stop)
|
|
{
|
|
case (byte)StopBits.OneStop: buf[5] = (byte)'1'; break;
|
|
case (byte)StopBits.TwoStop: buf[5] = (byte)'2'; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
byte[] value = new byte[20 - 6];
|
|
len = int2ascii(info.Baudrate, ref value, 20 - 6);
|
|
if (len == 0)
|
|
{
|
|
return Invalid_Arg;
|
|
}
|
|
for (int i = 0; i < len; i++)
|
|
buf[6 + i] = value[i];
|
|
|
|
buf[6 + len] = CR;
|
|
|
|
if ((len + 7) > BufferSize)
|
|
return Invalid_Arg;
|
|
|
|
ConvertSize = (byte)(len + 7);
|
|
|
|
for (int i = 0; i < (len + 7); i++)
|
|
{
|
|
SerialBuffer[i] = buf[i];
|
|
}
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte SetCANConfig(CANConfigInfo info, ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
byte len;
|
|
byte ind;
|
|
byte[] buf = new byte[31];
|
|
byte[] value = new byte[30];
|
|
byte function;
|
|
function = 0;
|
|
|
|
buf[0] = (byte)'W';
|
|
buf[1] = (byte)'C';
|
|
switch (info.Spec)
|
|
{
|
|
case (byte)CANSpec.CAN_A: buf[2] = (byte)'A'; break;
|
|
case (byte)CANSpec.CAN_B: buf[2] = (byte)'B'; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
buf[3] = (byte)',';
|
|
|
|
len = int2ascii(info.Baudrate, ref value, 4);
|
|
if (len == 0)
|
|
{
|
|
return Invalid_Arg;
|
|
}
|
|
for (int i = 0; i < len; i++)
|
|
buf[4 + i] = value[i];
|
|
|
|
buf[len + 4] = (byte)',';
|
|
ind = (byte)(len + 5);
|
|
|
|
len = hex2ID(info.ID, info.Spec, ref value, 8);
|
|
if (len == 0)
|
|
{
|
|
return Invalid_Arg;
|
|
}
|
|
for (int i = 0; i < len; i++)
|
|
buf[ind + i] = value[i];
|
|
|
|
buf[len + ind] = (byte)',';
|
|
ind = (byte)(len + ind + 1);
|
|
|
|
len = hex2ID(info.Mask, info.Spec, ref value, 8);
|
|
if (len == 0)
|
|
{
|
|
return Invalid_Arg;
|
|
}
|
|
for (int i = 0; i < len; i++)
|
|
buf[ind + i] = value[i];
|
|
|
|
buf[len + ind] = (byte)',';
|
|
ind = (byte)(len + ind + 1);
|
|
|
|
if (info.DAR)
|
|
SETDAR(ref function);
|
|
if (info.ABOR)
|
|
SETABOR(ref function);
|
|
|
|
buf[ind++] = toASCII_HEX(function);
|
|
buf[ind++] = CR;
|
|
|
|
|
|
if (ind > BufferSize)
|
|
return Invalid_Arg;
|
|
|
|
ConvertSize = ind;
|
|
|
|
for (int i = 0; i < ind; i++)
|
|
SerialBuffer[i] = buf[i];
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte GetSerialConfig(ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
if (3 > BufferSize)
|
|
return Invalid_Arg;
|
|
ConvertSize = 3;
|
|
|
|
SerialBuffer[0] = (byte)'R';
|
|
SerialBuffer[1] = (byte)'S';
|
|
SerialBuffer[2] = CR;
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte GetCANConfig(ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
if (3 > BufferSize)
|
|
return Invalid_Arg;
|
|
ConvertSize = 3;
|
|
|
|
SerialBuffer[0] = (byte)'R';
|
|
SerialBuffer[1] = (byte)'C';
|
|
SerialBuffer[2] = CR;
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte SaveConfig(ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
if (3 > BufferSize)
|
|
return Invalid_Arg;
|
|
ConvertSize = 3;
|
|
|
|
SerialBuffer[0] = (byte)'S';
|
|
SerialBuffer[1] = (byte)'V';
|
|
SerialBuffer[2] = CR;
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte FirmwareUpgrade(ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
if (3 > BufferSize)
|
|
return Invalid_Arg;
|
|
ConvertSize = 3;
|
|
|
|
SerialBuffer[0] = (byte)'F';
|
|
SerialBuffer[1] = (byte)'U';
|
|
SerialBuffer[2] = CR;
|
|
|
|
return No_Error;
|
|
}
|
|
static byte FirmwareVersion(ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
if (3 > BufferSize)
|
|
return Invalid_Arg;
|
|
ConvertSize = 3;
|
|
|
|
SerialBuffer[0] = (byte)'F';
|
|
SerialBuffer[1] = (byte)'V';
|
|
SerialBuffer[2] = CR;
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte GetErrorInfo(ref byte[] SerialBuffer, byte BufferSize, ref byte ConvertSize)
|
|
{
|
|
if (1 > BufferSize)
|
|
return Invalid_Arg;
|
|
ConvertSize = 1;
|
|
|
|
SerialBuffer[0] = (byte)'!';
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
|
|
|
|
static byte ParsingSerialInfo(ref SerialConfigInfo info, ref byte[] SerialBuffer, byte BufferSize)
|
|
{
|
|
SerialConfigInfo tmp;
|
|
UInt32 baudrate;
|
|
byte flow, stop, data, parity;
|
|
|
|
flow = SerialBuffer[0];
|
|
data = SerialBuffer[1];
|
|
parity = SerialBuffer[2];
|
|
stop = SerialBuffer[3];
|
|
|
|
byte[] bBuf = new byte[BufferSize - 5];
|
|
for (int i = 0; i < BufferSize - 5; i++)
|
|
bBuf[i] = SerialBuffer[4 + i];
|
|
|
|
baudrate = ascii2int(ref bBuf, (byte)(BufferSize - 5));
|
|
|
|
switch (flow)
|
|
{
|
|
case (byte)'N': tmp.flow = (byte)FlowControl.NoFlowControl; break;
|
|
case (byte)'H': tmp.flow = (byte)FlowControl.HardwareControl; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
switch (data)
|
|
{
|
|
case (byte)'8': tmp.data = (byte)DataBits.Data8; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
switch (parity)
|
|
{
|
|
case (byte)'N': tmp.parity = (byte)Parity.NoParity; break;
|
|
case (byte)'E': tmp.parity = (byte)Parity.EvenParity; break;
|
|
case (byte)'O': tmp.parity = (byte)Parity.OddParity; break;
|
|
case (byte)'S': tmp.parity = (byte)Parity.SpaceParity; break;
|
|
case (byte)'M': tmp.parity = (byte)Parity.MarkParity; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
switch (stop)
|
|
{
|
|
case (byte)'1': tmp.stop = (byte)StopBits.OneStop; break;
|
|
case (byte)'2': tmp.stop = (byte)StopBits.TwoStop; break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
if ((baudrate % 100) > 0)
|
|
return Invalid_Arg;
|
|
else
|
|
{
|
|
tmp.Baudrate = baudrate;
|
|
}
|
|
|
|
//*info = tmp;
|
|
info = tmp;
|
|
|
|
return No_Error;
|
|
}
|
|
static byte ParsingCANInfo(ref CANConfigInfo info, ref byte[] SerialBuffer, byte BufferSize)
|
|
{
|
|
CANConfigInfo tmp;
|
|
byte[] org = new byte[50];
|
|
byte[][] tt = new byte[5][];
|
|
byte function;
|
|
|
|
switch (SerialBuffer[0])
|
|
{
|
|
case (byte)'A':
|
|
tmp.Spec = (byte)CANSpec.CAN_A;
|
|
if (14 >= BufferSize || BufferSize >= 18)
|
|
return Invalid_Arg;
|
|
break;
|
|
case (byte)'B':
|
|
if (24 >= BufferSize || BufferSize >= 28)
|
|
return Invalid_Arg;
|
|
tmp.Spec = (byte)CANSpec.CAN_B;
|
|
break;
|
|
default: return Invalid_Arg;
|
|
}
|
|
|
|
org = SerialBuffer;
|
|
|
|
//for (int i = 0; i < tt.GetLength(0); i++)
|
|
// for (int j = 0; j < tt.GetLength(1); j++)
|
|
// tt[i, j] = 0x00;
|
|
|
|
string equation = Encoding.Default.GetString(org);
|
|
string[] equationTokens = equation.Split(new char[1] { ',' });
|
|
|
|
for (int i = 0; i < equationTokens.Length; i++)
|
|
{
|
|
tt[i] = Encoding.UTF8.GetBytes(equationTokens[i]);
|
|
}
|
|
|
|
tmp.Baudrate = ascii2int(ref tt[0], (byte)tt[0].Length);
|
|
tmp.ID = (uint)ascii2ID_Rev(ref tt[1], tmp.Spec);
|
|
tmp.Mask = (uint)ascii2ID_Rev(ref tt[2], tmp.Spec);
|
|
function = (byte)ascii2int(ref tt[3], 1);
|
|
|
|
if (function > 255)
|
|
return No_Error;
|
|
|
|
if (ISDAR(function))
|
|
tmp.DAR = true;
|
|
else
|
|
tmp.DAR = false;
|
|
|
|
if (ISABOR(function))
|
|
tmp.ABOR = true;
|
|
else
|
|
tmp.ABOR = false;
|
|
|
|
//*info = tmp;
|
|
info = tmp;
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
static byte ParsingErrorInfo(ref CANErorrInfo info, ref byte[] SerialBuffer, byte BufferSize)
|
|
{
|
|
CANErorrInfo tmp = new CANErorrInfo();
|
|
|
|
info = tmp;
|
|
|
|
return No_Error;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
private functions
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
static byte Div_8(UInt32 data, byte index)
|
|
{
|
|
byte ret;
|
|
data = data >> (index * 8);
|
|
ret = (byte)(data & 0xFF);
|
|
return ret;
|
|
}
|
|
|
|
public static int ascii2hex(byte ch)
|
|
{
|
|
if (0x30 <= ch && ch <= 0x39)
|
|
{//0~9
|
|
ch &= 0x0f;
|
|
return ch;
|
|
}
|
|
else if (0x61 <= ch && ch <= 0x66)
|
|
{ //a~f
|
|
ch &= 0x0f;
|
|
ch += 9;
|
|
return ch;
|
|
}
|
|
else if (0x41 <= ch && ch <= 0x46)
|
|
{ //A~F
|
|
ch &= 0x0f;
|
|
ch += 9;
|
|
return ch;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
static int ascii2ID_Rev(ref byte[] SourceBuffer, byte idCount)
|
|
{
|
|
int idTmp = 0;
|
|
int tmp = 0, i = 0;
|
|
for (i = 0; i < idCount; i++)
|
|
{
|
|
tmp = ascii2hex(SourceBuffer[i]);
|
|
if (tmp != -1)
|
|
{
|
|
idTmp = idTmp << 4;
|
|
idTmp |= tmp;
|
|
}
|
|
}
|
|
return idTmp;
|
|
}
|
|
|
|
|
|
|
|
static byte Div_4(UInt32 data, byte index)
|
|
{
|
|
byte ret;
|
|
data = data >> (index * 4);
|
|
ret = (byte)(data & 0x0F);
|
|
return ret;
|
|
}
|
|
static byte int2ascii(UInt32 val, ref byte[] SourceBuffer, byte size)
|
|
{
|
|
UInt32 check = 10;
|
|
byte su = 1;
|
|
|
|
if (val < 10)
|
|
return 0;
|
|
|
|
while ((val / check) > 0)
|
|
{
|
|
su++;
|
|
check *= 10;
|
|
}
|
|
|
|
if (su > size)
|
|
return 0;
|
|
|
|
string tmpStr = String.Format("{0}", val);
|
|
|
|
SourceBuffer = Encoding.UTF8.GetBytes(tmpStr);
|
|
|
|
return su;
|
|
}
|
|
static UInt32 ascii2int(ref byte[] SourceBuffer, byte size)
|
|
{
|
|
UInt32 val = 0;
|
|
byte ind = 0;
|
|
int ret = 0;
|
|
UInt32 mul = 1;
|
|
|
|
while (ret != -1)
|
|
{
|
|
ret = ascii2hex(SourceBuffer[ind++]);
|
|
}
|
|
ind--;
|
|
|
|
while (ind > 0)
|
|
{
|
|
ind--;
|
|
ret = ascii2hex(SourceBuffer[ind]);
|
|
val = (UInt32)(val + (ret * mul));
|
|
mul *= 10;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
|
|
|
|
static byte hex2ID(UInt32 val, byte idCount, ref byte[] SourceBuffer, byte size)
|
|
{
|
|
|
|
UInt32 comp;
|
|
|
|
switch (idCount)
|
|
{
|
|
case (byte)CANSpec.CAN_A: comp = 0x07ff; break;
|
|
case (byte)CANSpec.CAN_B: comp = 0x1fffffff; break;
|
|
default: return 0;
|
|
}
|
|
|
|
if (val > comp)
|
|
return 0;
|
|
|
|
if (idCount > size)
|
|
return 0;
|
|
|
|
switch (idCount)
|
|
{
|
|
case (byte)CANSpec.CAN_A: SourceBuffer = Encoding.UTF8.GetBytes(String.Format("{0:X3}", val)); break;
|
|
case (byte)CANSpec.CAN_B: SourceBuffer = Encoding.UTF8.GetBytes(String.Format("{0:X8}", val)); break;
|
|
default: return 0;
|
|
}
|
|
|
|
return idCount;
|
|
}
|
|
|
|
static byte toASCII_HEX(byte int_hex)
|
|
{
|
|
byte ret = 0;
|
|
if (0 <= int_hex && int_hex <= 9)
|
|
{
|
|
ret = (byte)('0' + int_hex);
|
|
}
|
|
else if (0x0A <= int_hex && int_hex <= 0x0F)
|
|
{
|
|
ret = (byte)('A' + (int_hex % 10));
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
}
|