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; } } }