/*
*使用说明：
*1.创建CAN设备对象  CANHw = usb2canfd.USB2CANHW(); 
*2.加载DLL          CANHw.LoadDll();
*3.扫描设备         hwnum = CANHw.FlashHw();
*4.获取可用设备     allhw = CANHw.GetAvailableHW();
*5.打开设备(初始化) CANHw.OpenDevice(设备序号,通道)
*6.通过SendMsg和GetMsg发送和获取报文
*/
namespace usb2canfd{
	//参考 http://www.toomoss.com/help/index.htm
	
	
	//初始化CAN的数据类型定义  
	class CANFD_INIT_CONFIG{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		BYTE Mode; //0-正常模式，1-自发自收模式  
    	BYTE ISOCRCEnable;//0-禁止ISO CRC,1-使能ISO CRC  
    	BYTE RetrySend;//0-禁止重发，1-无限制重发  
    	BYTE ResEnable;//0-不接入内部120欧终端电阻，1-接入内部120欧终端电阻  
    	//波特率参数可以用TCANLINPro软件里面的波特率计算工具计算  
    	//仲裁段波特率参数,波特率=40M/NBT_BRP*(1+NBT_SEG1+NBT_SEG2)  
    	BYTE NBT_BRP;  
    	BYTE NBT_SEG1;  
    	BYTE NBT_SEG2;  
    	BYTE NBT_SJW;  
    	//数据段波特率参数,波特率=40M/DBT_BRP*(1+DBT_SEG1+DBT_SEG2)  
    	BYTE DBT_BRP;  
    	BYTE DBT_SEG1;  
    	BYTE DBT_SEG2;  
    	BYTE DBT_SJW;  
    	BYTE __Res0[8];  
	}
	
	//初始化CAN的数据类型定义  
	class CAN_INIT_CONFIG{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		//CAN波特率 = 100MHz/(CAN_BRP)/(CAN_SJW+CAN_BS1+CAN_BS2)  
    	INT    CAN_BRP;         //取值范围1~1024  
    	BYTE   CAN_SJW;      //取值范围1~4  
    	BYTE   CAN_BS1;       //取值范围1~16  
    	BYTE   CAN_BS2;       //取值范围1~8  
    	BYTE   CAN_Mode;    //CAN工作模式，0-正常模式，1-环回模式，2-静默模式，3-静默环回模式，bit7为1则接入适配器内部终端电阻，否则不接入  
    	BYTE   CAN_ABOM;    //自动离线管理，0-禁止，1-使能  
    	BYTE   CAN_NART;     //报文重发管理，0-使能报文重传，1-禁止报文重传  
    	BYTE   CAN_RFLM;     //FIFO锁定管理，0-新报文覆盖旧报文，1-丢弃新报文  
    	BYTE   CAN_TXFP;     //发送优先级管理，0-标识符决定，1-发送请求顺序决定  
	}
	
	class CAN_FILTER_CONFIG{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		BYTE   Enable;              //使能该过滤器，1-使能，0-禁止  
    	BYTE   FilterIndex;         //过滤器索引号，取值范围为0到13  
    	BYTE   FilterMode;          //过滤器模式，0-屏蔽位模式，1-标识符列表模式  
    	BYTE   ExtFrame;           	//过滤的帧类型标志，为1 代表要过滤的为扩展帧，为0 代表要过滤的为标准帧。  
    	INT    ID_Std_Ext;          //验收码ID  
    	INT    ID_IDE;              //验收码IDE  
    	INT    ID_RTR;              //验收码RTR  
    	INT    MASK_Std_Ext;        //屏蔽码ID，该项只有在过滤器模式为屏蔽位模式时有用  
    	INT    MASK_IDE;            //屏蔽码IDE，该项只有在过滤器模式为屏蔽位模式时有用  
    	INT    MASK_RTR;            //屏蔽码RTR，该项只有在过滤器模式为屏蔽位模式时有用  
	}
	
	
	//CANfd信息帧的数据类型定义  
	class CANFD_MSG{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		INT    ID;                       //报文ID。 //| (1<<31);//扩展帧
		BYTE   DLC;          //数据字节长度，可设置为-0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64  
		BYTE   Flags;        //bit[0]-BRS,bit[1]-ESI,bit[2]-FDF,bit[6..5]-Channel,bit[7]-RXD
		BYTE   __Res0;       //保留  
    	BYTE   __Res1;       //保留  
    	INT    TimeStamp;    //帧接收或者发送时的时间戳，单位为10us  
    	BYTE   Data[64];     //报文的数据。   
	}
	
	//CAN信息帧的数据类型定义  
	class CAN_MSG{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		INT    ID;                       //报文ID。  
    	INT    TimeStamp;         //接收到信息帧时的时间标识，从CAN 控制器初始化开始计时。  
    	BYTE   RemoteFlag;      //是否是远程帧  
    	BYTE   ExternFlag;        //是否是扩展帧  
    	BYTE   DataLen;           //数据长度(<=8)，即Data 的长度。  
    	BYTE   Data[8];            //报文的数据。  
    	BYTE   __Res;     
	}
	
	class CAN_UDS_ADDR{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		INT 	ReqID;        //请求报文ID。  
    	INT 	ResID;        //应答报文ID。  
    	BYTE   	Flag;   //bit[0]-帧类型(0-标准帧，1-扩展帧),
    					//bit[1]-FDF(0-普通CAN帧，1-CANFD帧),
    					//bit[2]-BRS(0-CANFD帧不加速，1-CANFD帧加速)
    	BYTE   	AddrFormats;  //0-normal, 1-extended ,2-mixed
    	BYTE   	AddrExt;      //当AddrFormats不为normal时，该数据放到CAN数据域第1字节  
    	BYTE   	MaxDLC;       //每帧最大数据字节数，一般设置为8
		
	}
	
	
	class DEVICE_INFO{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		BYTE    FirmwareName[32];   //固件名称字符串  
    	BYTE    BuildDate[32];           //固件编译时间字符串  
    	INT     HardwareVersion;       //硬件版本号  
    	INT     FirmwareVersion;        //固件版本号  
    	INT     SerialNumber[3];        //适配器序列号  
    	INT     Functions;                   //适配器当前具备的功能  
	}
	
	
	
	//调用函数
	class USB2CANHW{
		ctor( /*输入构造函数所需要的参数*/ ){
		
		};
		type=me;
		/*对象的所有成员必须用分号分隔*/
		
		//初始化全局变量
		DllHandle = null;
		
		
		
		//加载DLL
		LoadDll = function(){
			try{
				DllHandle = ..raw.loadDll("\USB2XXX.dll")
			}
			catch(err)
			{
				import win;
				DllHandle = null;
				win.msgboxTimeout("加载USB2LIN的DLL失败，请检查USB2XXX.dll和libusb-1.0.dll文件","错误",3000,);
			}
			if(DllHandle == null)return 1;
			return 0;
		}
		
		//刷新硬件
		FlashHw = function(){

			if(DllHandle = null){
            	//DLL为空，返回
            	AvailableHW = {}
        		return 0; 
        	}
        	var arr_temp = {int value[] = { length = 10/*可以使用变量*/ } }//类似动态数组
        	HwNum = DllHandle.USB_ScanDevice(arr_temp)
        	AvailableHW = {}
        	for(i=1;HwNum;1){
        		var devtemp = {};
        		devtemp.devnum = i;
        		devtemp.channel = 1;
        		devtemp.hLINHW = arr_temp.value[i];
        		devtemp.name = "dev-" + i + ":" + tostring(arr_temp.value[i],16);
        		..table.push(AvailableHW,devtemp);
        		}
        	return HwNum; //返回有效硬件数
		}
		
		//获取设备信息
		GetDevInfo = function(index){
			if(index > HwNum)
			{	//如果序号大于最大硬件数
				return 0; 
			}
			DllHandle.USB_OpenDevice(AvailableHW[index].hLINHW);
			var DeviceInfo = ..usb2canfd.DEVICE_INFO();
			var funcstr = ..raw.buffer(100);
			
			var ret = DllHandle.DEV_GetDeviceInfo(AvailableHW[index].hLINHW,DeviceInfo,funcstr);
			
			return ret,DeviceInfo,funcstr; 
		}
		
		//获取设备信息
		GetNowInfo = function(){
			if(Hwconnected == null){
				return 0; 
			}
			//DllHandle.USB_OpenDevice(Hwconnected);
			var DeviceInfo = ..usb2canfd.DEVICE_INFO();
			var funcstr = ..raw.buffer(100);
			
			var ret = DllHandle.DEV_GetDeviceInfo(Hwconnected,DeviceInfo,funcstr);
			
			return ret,DeviceInfo,funcstr; 
		}
		
		//获取有效硬件
		GetAvailableHW = function(){
			return AvailableHW;
		}
		
		SetFilter = function(index){
			CANFilter = ..usb2canfd.CAN_FILTER_CONFIG();
			CANFilter.FilterIndex = 0;  
			CANFilter.Enable = 1;  
			CANFilter.ExtFrame = 0;  //需要过滤接收的帧为标准帧  
			CANFilter.FilterMode = 1;//标识符列表模式  
			CANFilter.ID_IDE = 0;      //接收到的数据帧IDE必须为1，也就是必须为扩展帧数据  
			CANFilter.ID_RTR = 0;      //接收到的帧类型必须为数据帧  
			CANFilter.ID_Std_Ext = 0x620;//接收到的帧ID必须等于CANFilter.ID_Std_Ext设置的值  
			var ret = DllHandle.CAN_Filter_Init(AvailableHW[index].hLINHW,0,CANFilter);  
			
			CANFilter.FilterIndex = 1; 
			CANFilter.ID_Std_Ext = 0x610;
			var ret = DllHandle.CAN_Filter_Init(AvailableHW[index].hLINHW,0,CANFilter);
			
			
			for(i=2;13;1){
				CANFilter.FilterIndex = i;
				CANFilter.Enable = 0;
				DllHandle.CAN_Filter_Init(AvailableHW[index].hLINHW,0,CANFilter);
			}
			
		}
		
		//打开设备，包括初始化通道
		OpenDevice = function(index,channel,canfd){
			if(index > HwNum)
			{	//如果序号大于最大硬件数
				return 0; 
			}
			import console;
			var ret = DllHandle.USB_OpenDevice(AvailableHW[index].hLINHW)
			//canfd = true;
			if(canfd == true){
				var canconfig = ..usb2canfd.CANFD_INIT_CONFIG();
			
				canconfig.Mode = 0; //0-正常模式，1-自发自收模式  
				canconfig.ISOCRCEnable = 0;//0-禁止ISO CRC,1-使能ISO CRC  
				canconfig.RetrySend = 0;//0-禁止重发，1-无限制重发  
				canconfig.ResEnable = 1;//0-不接入内部120欧终端电阻，1-接入内部120欧终端电阻  
				//波特率参数可以用TCANLINPro软件里面的波特率计算工具计算  
				//仲裁段波特率参数,波特率=40M/NBT_BRP*(1+NBT_SEG1+NBT_SEG2)  
				canconfig.NBT_BRP = 1;  //参数来自官方上位机，默认500K
				canconfig.NBT_SEG1 = 59;  
				canconfig.NBT_SEG2 = 20;  
				canconfig.NBT_SJW = 2;  
				//数据段波特率参数,波特率=40M/DBT_BRP*(1+DBT_SEG1+DBT_SEG2)  
				canconfig.DBT_BRP = 2;  //参数来自官方上位机，默认500K
				canconfig.DBT_SEG1 = 29;  
				canconfig.DBT_SEG2 = 10;  
				canconfig.DBT_SJW = 2;   
			 	
				ret = DllHandle.CANFD_Init(AvailableHW[index].hLINHW,channel,canconfig);
			}
			else {
				var canconfig = ..usb2canfd.CAN_INIT_CONFIG();

				canconfig.CAN_Mode = 0x80;//0-正常模式  1-环回模式  0x80终端电阻

				canconfig.CAN_ABOM = 0;//禁止自动离线  
				canconfig.CAN_NART = 0;//禁止报文重传  
				canconfig.CAN_RFLM = 0;//FIFO满之后覆盖旧报文  
				canconfig.CAN_TXFP = 1;//发送请求决定发送顺序  
				//配置波特率,波特率 = 42M/(BRP*(SJW+BS1+BS2))  
				canconfig.CAN_BRP = 4;  
				canconfig.CAN_BS1 = 15;  
				canconfig.CAN_BS2 = 5;  
				canconfig.CAN_SJW = 2;  
				ret = DllHandle.CAN_Init(AvailableHW[index].hLINHW,channel,canconfig);
				//console.log("init ret = " + ret); 
				this.SetFilter(index);
			}
			
			canfd_connected = canfd;
			if(ret == 0){//调用成功
				Hwconnected = AvailableHW[index].hLINHW;
				Chconntected = channel;
				
			}
			else {
				//Hwconnected = null
				Chconntected = null;
			}
			
			return ret;
		}
		
		//关闭设备
		CloseDevice = function(){
			if(Hwconnected == null){
				return; 
			}
			try{
				DllHandle.USB_CloseDevice(Hwconnected);
				Hwconnected = null;
			}			
		}
		
		//是否连接
		isConnected = function(){
			if(Hwconnected == null){
				return false; 
			}
			else {
				return true; 
			}
				
		}
		
		
		//发送报文
		SendMsg = function(id,data){
			if(Hwconnected == null){//未连接
				return 0;
			}
			if(#data == 0 || #data>8){//长度不对
				return 0;
			}
			//console.log("发送报文")
			var ret = 0;
			if(canfd_connected == true){
				var msg = ..usb2canfd.CANFD_MSG();
				msg.Flags = 0;
				if(id <= 0x7ff){
					msg.ID = id; 	//| (1<<31);//扩展帧
				}
				else {
					msg.ID = id | (1<<31);//扩展帧
				}
				
				
				msg.DLC = #data;
				msg.Data = data;
				
				//console.dumpJson(msg);
				//console.log("Hwconnected = " + Hwconnected);
				//console.log("Chconntected = " + Chconntected);
				ret = DllHandle.CANFD_SendMsg(Hwconnected,Chconntected,msg,1);
			}
			else {
				var msg = ..usb2canfd.CAN_MSG();
				//msg.Flags = 0;
				if(id <= 0x7ff){
					msg.ID = id; 	//| (1<<31);//扩展帧
				}
				else {
					msg.ID = id | (1<<31);//扩展帧
				}
				msg.ExternFlag = 0;  
    			msg.RemoteFlag = 0;  
    			msg.DataLen = #data;
				msg.Data = data;
				//console.log("发送报文")
				ret = DllHandle.CAN_SendMsg(Hwconnected,Chconntected,msg,1);
				//console.log("ret = " + ret);
			}
			
			
			return ret; 
		}
		
		//从设备缓冲区获取报文
		GetMsg = function(){
			var ret = 0;
			var retdata = {};
			if(canfd_connected == true){
				//CANFD
				do{
					var msgbuf = ..usb2canfd.CANFD_MSG();
					ret = DllHandle.CANFD_GetMsg(Hwconnected,CANIndex,msgbuf,1);
					if(ret == 1){
						var data = {};
						for(i=1;msgbuf.DLC;1){
							data[i] = msgbuf.Data[i];
						}
						var msg = {"id"=msgbuf.ID;"data"=data;};//
						..table.push(retdata,msg);
					}
				}while(ret > 0)
			}
			else {
				//CAN
				do{
					//raw.convertArray(raw.sizeof(..usb2canfd.CAN_MSG())
					var msgbuf = {};
					for(i=1;10;1){
						//msgbuf.push(new ..usb2canfd.CAN_MS())
						var temp = ..usb2canfd.CAN_MSG()
						..table.push(msgbuf,temp);
					}
					
					//var msgbuf = ..raw.toarray(10,"struct",..usb2canfd.CAN_MS);
					ret = DllHandle.CAN_GetMsgWithSize(Hwconnected,CANIndex,msgbuf[1],1);
					if(ret == 1){
						var data = {};
						for(i=1;msgbuf[1].DataLen;1){
							data[i] = msgbuf[1].Data[i];
						}
						var msg = {"id"=msgbuf[1].ID;"data"=data;};//
						..table.push(retdata,msg);
					}
				}while(ret > 0)
			}
			
			
			return retdata;
		}
		
		GetDiag = function(data){
			if(#data<2){
				return 0,1; 
			}
			var UDSAddr = ..usb2canfd.CAN_UDS_ADDR()
			UDSAddr.Flag = 1;//使用扩展帧  
			UDSAddr.AddrFormats = 0;  
			UDSAddr.ReqID = 0x18dadff1;  
			UDSAddr.ResID = 0x18daf1df;  
			UDSAddr.MaxDLC = 8;  
			var req_data = ..raw.buffer(#data);
			for(i=1;#data;1){
				req_data[i] = data[i];
			}
			ret = DllHandle.CAN_UDS_Request(Hwconnected,CANIndex,UDSAddr,req_data,#data);
			var res_data = ..raw.buffer(4096);
			//sleep(10);
			var ret = DllHandle.CAN_UDS_Response(Hwconnected,CANIndex,UDSAddr,res_data,1000);  
			
			return ret,2,res_data; 
		}
		
		SetPower = function(state){
			var ret = DllHandle.LIN_EX_CtrlPowerOut(Hwconnected,state);
			return ret; 
		}
		
		GetPower = function(){
			var buf = ..raw.buffer(10);
			var ret = DllHandle.LIN_EX_GetVbatValue(Hwconnected,buf);
			
			return ret,buf;
		}
		
		
		
		
	}
}


/**intellisense()
usb2canfd = 图莫斯CANFD驱动
usb2canfd.USB2CANHW = USB2CAN库
usb2canfd.USB2CANHW() = 创建设备对象\n!usb2canfdUSB2CANHW.
!usb2canfdUSB2CANHW.LoadDll() = 加载DLL
!usb2canfdUSB2CANHW.FlashHw() = 刷新硬件
!usb2canfdUSB2CANHW.GetDevInfo() = 获取设备信息
!usb2canfdUSB2CANHW.GetAvailableHW() = 获取有效设备，需要先FlashHw()刷新
!usb2canfdUSB2CANHW.OpenDevice() = 打开设备
!usb2canfdUSB2CANHW.CloseDevice() = 关闭设备
!usb2canfdUSB2CANHW.isConnected() = 是否已连接
!usb2canfdUSB2CANHW.SendMsg() = 发送报文
!usb2canfdUSB2CANHW.GetMsg() = 接收报文
end intellisense**/

