#define uds_c
//===============================

#include "uds_defines.h"
#include "..\main.h"
#include "watchdog_hal.h"
#include "..\board.h"


extern const uint8_t AppVersion[];
extern uint32_t appsign[2];

T_UDS_ uds;

/** =================================
 
 =================================	*/
void avoid_empty_block(void)
{
	uds.avoid_empty++;
}
/** =================================

=================================  */
void uds_10ms(void)
{
	if(uds.c_1000ms++ > 100) {
		uds.c_1000ms=0;
	}
	if(uds.c_wait_flowcontrol_10ms) {  
		uds.c_wait_flowcontrol_10ms--;
		if(uds.c_wait_flowcontrol_10ms==0u){
			uds.wait_flowcontrol=0u;
			uds.table_seq=0u;
		}	
	}
	if(uds.c_wait_cf_10ms) {  
		uds.c_wait_cf_10ms--;
		if(uds.c_wait_cf_10ms==0u){
			if(uds.table_seq==3u) uds.table_seq=0u;
		}	
	}

	if(uds.c_timeout_session_10ms) {  
		uds.c_timeout_session_10ms--;
		if(uds.c_timeout_session_10ms==0u){
			uds.session=NSESSION_DEFAULT;
			uds.rom_access_level=0;
			uds.wait_key=0;
		}	
	}
	uds.r_seed++;
	dtc_control();
	if(uds.xreq_eep_write_did) {
		uds.xreq_eep_write_did=0;
		table_write(0);
	}
	if(uds.timeout) {
		uds.timeout--;

		if(!uds.timeout) 	{
			uds.table_seq=0;
			uds.wait_flowcontrol=0;
			uds.bootloader_update=0;
			uds.wait_key=0;
			uds.disable_rx_tx=0;
		}	
	}

}

/** =================================

=================================  */
void uds_2ms(void)
{
	uds_logic_event();
}

/** =================================

=================================  */
void uds_timer_interrupt(void)
{
	uds.x2ms++;
}
/** ======================================================================

=====================================================================  */
uint32_t uds_can_TxData(uint32_t index, uint32_t id, uint8_t ide, uint8_t dlc, uint8_t data[])
{

}
/** =================================

=================================  */
void send_uds_tx(void)
{
	uds.c_monitor_inhibit_10ms=3;
	//monprintf("cantx\n\r");
	can_send_txring(0,uds.tx.id,uds.tx.buf,8);
	//uds_can_TxData(MB_UDS_TX, uds.tx.id, 1, 8u, uds.tx.buf);
	uds.tx.xreq_send=0;
}

/** =================================

=================================  */
void clear_uds_tx_buf(void)
{
	uint8_t i;
	for(i=0; i<8; i++) uds.tx.buf[i]=0;
}


/** =================================

=================================  */
void uds_wait(void)
{
	static uint8_t c_1ms=0;
	if(uds.init==0) 	{
		uds_init();
		OutStr("uds_init\n\r");	
		return;
	}	

	// =============================
	if(uds.x2ms>=1u) {
		uds.x2ms=0u;
		if(uds.req_dtc_1st_frame) {
			uds.req_dtc_1st_frame=0;
			set_dtc_1st_frame(uds.dtc_type);						
			uds.tx.xreq_send=1;
		}

		if(uds.tx.xreq_send) {
			uds.timeout=UDS_TIME_OUT;			
			send_uds_tx();
			return;
		}
		if(++c_1ms > 2) {
			c_1ms=0;		
		} else {
			return;
		}
		uds_2ms();	
		uds.c_10ms++;
		uds.r_seed++;
		if(uds.c_10ms >= 5u) {
			uds.c_10ms=0u;
			uds_10ms();	
			if(uds.c_test++ >= 200u) {
				uds.c_test=0;
				//goto_reset();
				//OutDev0('A'+uds.rom_access_level);
			}
		}
	}

	if(uds.XREQ_UDS_RESET) {
		goto_reset();
	}
	if(uds.XREQ_RESET) {
		goto_reset();
	}
}



/** =================================

=================================  */
void uds_init(void)
{
	uds.x2ms                                   =0;
	uds.c_10ms                                 =0;
	uds.ndata			                             =0;
	uds.address                                =0;
	uds.start_address                          =0;
	uds.ndata_pre_packet                       =0;
	uds.timeout				                         =0;
	uds.flow_control_ms                        =0;
	uds.c_flow_control_ms		                   =0;
	uds.wait_flowcontrol                       =0;
	uds.c_wait_flowcontrol_10ms                =0;
	uds.c_wait_cf_10ms                         =0;
	uds.seq                                    =0;
	uds.frame_len                              =0;
	uds.ntable                                 =0;
	uds.ntable_did                             =0;
	uds.p_data                                 =0;
	uds.tx_len			                           =0;
	uds.table_control				                   =0;
	uds.table_write_to			                   =0;
	uds.table_seq		                           =0;
	uds.consecutive_rx_num                     =0;
	uds.data_send_seq				                   =0;
	uds.response_to_negetive                   =0;
	uds.xreq_dtc_clear                         =0;
	uds.xreq_eep_write_did                     =0;
	uds.xreq_table_snap_short_write            =0;
	uds.bootloader_update                      =0;
	uds.wait_key                               =0;
	uds.ReadDataByPeriodicIdentifier_10ms      =0;
	uds.c_ReadDataByPeriodicIdentifier_10ms    =0;
	uds.c_inhibut_10ms                         =0;
	uds.XUPDTE_FLASH                           =0;
	uds.XREQ_UDS_RESET                         =0;
	uds.XREQ_RESET                             =0;
	uds.XINIT_TABLE                            =0;

	uds.c_log_send                             =0;
	uds.eep_status                             =0;
	uds.rom_access_level                       =0;
  uds.group_of_dtc                          =0;
  uds.dtc_check_inhibit                      =0;
	uds.nrc                                    =0;
	uds.consecutive_length_fail                =0;
	uds.disable_rx_tx                          =0;
	uds.c_timeout_session_10ms                 =0;
  uds.c_dtc_event	                           =0;
  uds.monitor_mode                           =0;
	uds.session=NSESSION_DEFAULT;
	uds.program_type=0;

	uds.tx.id=ID_UDS_TX;
	uds.rx.id=ID_UDS_RX;
	uds.tx.length=8;
	uds.init=1;
	uds.r_seed=35;
	uds.session=NSESSION_DEFAULT;

	uds.c_inhibut_10ms=0;
	uds.timeout=0;
	UpLoadID=ID_UDS_TX;
	DownLoadID=ID_UDS_RX;

	uds.init=1;
}


/** =================================

=================================  */
void uds_table_receve_finish(uint8_t print)
{
//	uint8_t	b;
	uds.table_seq=0;

	//monprintf("tend\n\r");
	if(uds.write_data_type==0) { //null
		uds.tx.buf[0]=0x03;uds.tx.buf[1]=uds.table_control|0x40;
		uds.ntable_did=0;
	}	else {
		uds.tx.buf[0]=0x03;uds.tx.buf[1]=SID_WriteDataByIdentifier|0x40;
	}	
	if(	uds.response_to_negetive==1) {
		uds.tx.buf[1]=0x7f;
		uds.response_to_negetive=0;
	}	
	uds.tx.buf[2]=uds.ntable_did>>8;uds.tx.buf[3]=uds.ntable_did;
	uds.tx.buf[4]=0;uds.tx.buf[5]=0;uds.tx.buf[6]=0;uds.tx.buf[7]=0;
	//setup_out();
}
/** =================================

=================================  */
void set_flow_control(void)
{
	uds.tx.buf[0]=0x30;uds.tx.buf[1]=0x00;uds.tx.buf[2]=0x0a;	
	uds.c_wait_cf_10ms=13;			
}
/** =================================

=================================  */
void set_wait_flow_control(void)
{
	uds.wait_flowcontrol=1;
	uds.c_wait_flowcontrol_10ms=V_c_wait_flowcontrol_10ms;			
}
/** =================================

=================================  */

void set_dtc_1st_frame(uint8_t type)
{
	uint16_t len;
	len=dtc_send_table_set(type);	
	len+=3;
	if(len <= 7) {
		uds.tx.buf[0]=(uint8_t)len;
		uds.tx.buf[1]=(uint8_t)(SID_ReadDTCInformation|0x40U);
		uds.tx.buf[2]=uds.dtc_type;
		uds.tx.buf[3]=0xFF;
		uds.p_data=0;
		uds.pdata_rd=(void *)TABLE_DTC_SEND;
		uds.tx.buf[4]=uds.pdata_rd[uds.p_data];
		uds.p_data++;
		uds.tx.buf[5]=uds.pdata_rd[uds.p_data];
		uds.p_data++;
		uds.tx.buf[6]=uds.pdata_rd[uds.p_data];
		uds.p_data++;
		uds.tx.buf[7]=uds.pdata_rd[uds.p_data];
		uds.p_data++;
	} else {
		uds.tx_len=len;
		uds.tx.buf[0]=(uint8_t)(len>>8u);
		uds.tx.buf[0]|=0x10U;
		uds.tx.buf[1]=(uint8_t)len;
		uds.tx.buf[2]=(uint8_t)(SID_ReadDTCInformation|0x40U);
		uds.tx.buf[3]=uds.dtc_type;
		uds.tx.buf[4]=0xFF;
		uds.p_data=0;
		uds.pdata_rd=(void *)TABLE_DTC_SEND;
		uds.tx.buf[5]=uds.pdata_rd[uds.p_data];
		uds.p_data++;
		uds.tx.buf[6]=uds.pdata_rd[uds.p_data];
		uds.p_data++;
		uds.tx.buf[7]=uds.pdata_rd[uds.p_data];
		uds.p_data++;

		uds.wait_flowcontrol=1;
		uds.table_seq=2;	
		uds.data_send_seq=0x21;	
		uds.table_control=SID_ReadDataByIdentifier;
	}
}

void uds_tx_buf_clear(void)
{
	uint8_t	i;
	for(i=0;i<8;i++) uds.tx.buf[0]=0;
}
void uds_send_data_set(uint16_t did,uint16_t size,uint32_t address)
{
	uint16_t n;
	n=size;
	n+=3;		// 0xfff 이상은 ?보냄.
	if(n>0xfff) n=0xfff;
	uds.tx.buf[0]=n>>8;uds.tx.buf[0]|=0x10;
	uds.tx.buf[1]=n;
	uds.tx.buf[2]=SID_ReadDataByIdentifier+0x40;
	uds.tx.buf[3]=(did>>8)|0xf0;uds.tx.buf[4]=did;
	uds.pdata_rd=(void *)address;
	uds.tx_len=size;
	uds.p_data=0;
	uds.tx.buf[5]=uds.pdata_rd[uds.p_data++];
	uds.tx.buf[6]=uds.pdata_rd[uds.p_data++];
	uds.tx.buf[7]=uds.pdata_rd[uds.p_data++];
	set_wait_flow_control();
	uds.table_seq=2;			// wait flow control
	uds.data_send_seq=0x21;			
}
/** =====================================================================

======================================================================  */
void uds_logic_event(void)
{
	uint16_t n;
	uint8_t	i;
	uint8_t rp=1u;
	uint32_t add;
	uint8_t * p;

	uds.r_seed++;
	if(uds.r_seed >= 0x80) uds.r_seed=0;
	if(uds.c_inhibut_10ms!=0) {uds.c_inhibut_10ms--;	}	

	if(uds.xreq_dtc_clear) {
		uds.xreq_dtc_clear=0u;
		dtc_clear();
	}
	
	if(uds.table_seq==1u) {
		if(uds.table_control==SID_WriteDataByIdentifier) {
			uds.tx.buf[0]=0x03u;
			uds.tx.buf[1]=SID_WriteDataByIdentifier+0x40u;
			uds.tx.buf[2]=uds.rx.buf[2];
			uds.tx.buf[3]=uds.rx.buf[3];
			if(uds.write_data_type==UDS_WTYPE_1_DATA) { //========================
				// address = 	uds.ntable   나중에 사용.
				// data = uds.write_data[0..3]
				uds.table_seq=0;
			} else if(uds.write_data_type==UDS_WTYPE_TABLE_CONTROL) { //=========
				monprintf("useq=%d,tbl=%d,tcon=%02x,fc=%d,wrtype=%d,pdata=%d,uds.pdata_rd=%08x,writeto=%d\n\r",uds.table_seq,uds.ntable,uds.table_control,uds.wait_flowcontrol,uds.write_data_type,uds.p_data,&uds.pdata_rd,uds.table_write_to);
				if(uds.table_write_to== UDS_TABLE_CONTROL_RAM_TO_FLASH) {
					//uds_tx_can(uds.tx.id,8u,uds.tx.buf,NID_UDS_TX);  // 너무오래걸림,.
					//rp=0;
					table_write(0);
				}	else if(uds.table_write_to== UDS_TABLE_CONTROL_FLASH_TO_RAM) {
					table_read(0);
				}	else if(uds.table_write_to== UDS_TABLE_CONTROL_DEFULT) { 
					//flashErase(DFLSH, DFLASH_DATA_BLOCK);
					uds.XREQ_RESET=1; 
				}
				uds.table_seq=0;
			}
		} else if(uds.table_control==SID_ReadDataByIdentifier) {
			if(uds.ntable == NTABLE_VERSION) { 
				//p=APPVERSION;
				//monprintf("rdbi:\n\r");
				p=AppVersion;
				n=0;
				for(i=0;i<50;i++) {
					if(p[i] < ' ') break;
					uds.data[n++]=p[i];
				}
				uds.data[n++]=',';
				uds.data[n++]='B';
				uds.data[n++]='O';
				uds.data[n++]='O';
				uds.data[n++]='T';
				uds.data[n++]='V';
				uds.data[n++]=':';

				p=(void *)BOOTVERSION_ADDRESS;
				i=0;
				if(p[0]!='B') {
					uds.data[n++]='N';
					uds.data[n++]='0';
					uds.data[n++]=' ';
				} else {
					for(i=0;i<25;i++) {
						if(p[i] < ' ') break;
						uds.data[n++]=p[i];
					}
				}
				uds.data[n++]=0;
				add=(uint32_t)&uds.data[0];
				uds_send_data_set(uds.ntable,n,add);
			}			else {				
				n=(uint16_t)EEP_ADDR_TABLE[uds.ntable][2];
				n+=3u;
				if(n>7) {
					uds.tx.buf[0]=((n>>8u)&0x000f);uds.tx.buf[0]|=0x10u;
					uds.tx.buf[1]=n;
					uds.tx.buf[2]=SID_ReadDataByIdentifier|0x40u;
					uds.tx.buf[3]=(uds.ntable_did>>8);uds.tx.buf[4]=uds.ntable_did;
					uds.pdata_rd=(void *)EEP_ADDR_TABLE[uds.ntable][3];
					uds.tx_len=EEP_ADDR_TABLE[uds.ntable][2];

					uds.p_data=0u;
					uds.tx.buf[5]=uds.pdata_rd[uds.p_data];uds.p_data++;
					uds.tx.buf[6]=uds.pdata_rd[uds.p_data];uds.p_data++;
					uds.tx.buf[7]=uds.pdata_rd[uds.p_data];uds.p_data++;
					set_wait_flow_control();
					uds.c_wait_flowcontrol_10ms=50U;			
					uds.table_seq=2u;			
					uds.data_send_seq=0x21u;			
				} else {
					uds.tx.buf[0]=n;
					uds.tx.buf[1]=SID_ReadDataByIdentifier|0x40u;
					uds.tx.buf[2]=(uds.ntable_did>>8);uds.tx.buf[3]=uds.ntable_did;
					uds.pdata_rd=(void *)EEP_ADDR_TABLE[uds.ntable][3];
					uds.tx_len=EEP_ADDR_TABLE[uds.ntable][2];
					uds.p_data=0u;
					uds.tx.buf[4]=uds.pdata_rd[uds.p_data];uds.p_data++;
					uds.tx.buf[5]=uds.pdata_rd[uds.p_data];uds.p_data++;
					uds.tx.buf[6]=uds.pdata_rd[uds.p_data];uds.p_data++;
					uds.tx.buf[7]=uds.pdata_rd[uds.p_data];uds.p_data++;
					for(i=(n+1);i<8;i++) {					
						uds.tx.buf[i]=0;
					}	
					uds.table_seq=0;
				}
			}
		}		
		else {
			uds.table_seq=0;
		}
	}		
	else if(uds.table_seq==2u) {
		if(uds.wait_flowcontrol != 0) return;
		if(uds.table_control==SID_ReadDataByIdentifier) {
			if(uds.c_flow_control_ms < 2) uds.c_flow_control_ms=0;		
			else { uds.c_flow_control_ms -= 2; }

			if(uds.c_flow_control_ms != 0) return;
			uds.c_flow_control_ms=uds.flow_control_ms;
			uds.tx.buf[0]=uds.data_send_seq;
			for(i=1;i<8;i++) {
				if(uds.p_data >= uds.tx_len) {
					uds.tx.buf[i]='.';
				} else {
					uds.tx.buf[i]=uds.pdata_rd[uds.p_data];
				}	
				uds.p_data++;
			}	
			if(uds.p_data >= uds.tx_len) {
				uds.table_seq=0u;
			}
			uds.data_send_seq++;
			if(uds.data_send_seq >= 0x30u) uds.data_send_seq=0x21u;
		}
	}
	else if(uds.table_seq==3u) {
		rp=0;
	} else {
		rp=0;
	}
	if(rp!=0) {
		uds.tx.xreq_send=1;	
		uds.timeout=UDS_TIME_OUT;
	}	


}

#define is_sel_all_clear (uds.rx.buf[7]==1)
#define is_sel_set (uds.rx.buf[7]==0)
#define is_sel_clear (uds.rx.buf[7]==2)
uint8_t uds_interrupt_sid_dtc(void)
{
	uint8_t rp=1u;
//	uint8_t i;
	uint16_t k;
	uds.dtc_type=uds.rx.buf[2];uds.dtc_mask=uds.rx.buf[3];
	uds_tx_buf_clear();
	if(uds.dtc_type==0x02u) {
		uds.req_dtc_1st_frame=1;
		//set_dtc_1st_frame(uds.dtc_type);						
		rp=0;
	} else if(uds.dtc_type==0x0Au) { 
		uds.req_dtc_1st_frame=1;
		//set_dtc_1st_frame(uds.dtc_type);						
		rp=0;
	} else if(uds.dtc_type==0x01u)	{
		uds.tx.buf[0]=0x06u;uds.tx.buf[1]=(uint8_t)(SID_ReadDTCInformation|0x40U);
		uds.tx.buf[2]=uds.dtc_type;	
		uds.tx.buf[3]=uds.dtc_mask;	//
		k=dtc_count_set();
		uds.tx.buf[4]=k>>8;
		uds.tx.buf[5]=k;	
	} else if(uds.dtc_type==0x03u) 	{		
		uds.tx.buf[0]=0x02u;uds.tx.buf[1]=(uint8_t)(SID_ReadDTCInformation|0x40U);
		uds.tx.buf[2]=uds.dtc_type;	
	} else {
		uds.tx.buf[0]=0x02u;uds.tx.buf[1]=0x7fu;uds.tx.buf[2]=UDS_NRC_subFunctionNotSupported;	
	}
	return rp;
}
uint8_t uds_SID_ControlDTCSetting(uint8_t k)
{
	uint8_t rp=1u;
//	uint8_t i;

	uds_tx_buf_clear();
	uds.tx.buf[0]=0x02u;
	uds.tx.buf[1]=(uint8_t)(SID_ControlDTCSetting|0x40U);
	uds.tx.buf[2]=uds.rx.buf[2]; 		

	if(uds.rx.buf[2]==0x01u) { 			
		uds.dtc_check_inhibit=0;
	} else if(uds.rx.buf[2]==0x02u) { 	// 0ff
		uds.dtc_check_inhibit=1;
	} else {
		uds.tx.buf[0]=0x02u;uds.tx.buf[1]=0x7fu;
	}
	return rp;
}
void uds_fail_massage(uint8_t sid,uint8_t fail_code)
{
	uds.tx.buf[0]=0x03u;
	uds.tx.buf[1]=UDS_NAK; // NAK
	uds.tx.buf[2]=sid;		// SUB FUCTION
	uds.tx.buf[3]=fail_code;		// NRC
	uds.response_to_negetive=1;
}

void uds_fail_check_no_extended(uint8_t error_code)
{
	if(uds.nrc!=UDS_NRC_LEN) {
		if(uds.session != NSESSION_EXTENDED_DIAGNOSTIC) {
			uds.nrc=UDS_NRC_serviceNotSupportedInActiveSession;
			uds.response_to_negetive=1;
		}
	}
}

/** ===========================================================

===========================================================  */
void uds_single_frame_error_check(void)
{
	uint8_t c;

	uds.nrc=0;
	
	if(uds.sid==SID_ReadDataByIdentifier) {
		if(uds.length != 3) uds.nrc=UDS_NRC_LEN;
		if(uds.nrc!=UDS_NRC_LEN) {	/*if(uds.rom_access_level) uds.nrc=UDS_NRC_securityAccessDenied;*/ }
	} else if(uds.sid==SID_StopDiagnosticSession) {
		if(uds.length > 2) uds.nrc=UDS_NRC_LEN;
	} else if(uds.sid==SID_DiagnosticSessionControl) {
		c=uds.rx.buf[2];c&=0x7f;
		if(uds.length != 2) uds.nrc=UDS_NRC_LEN;
		else {
			if(((c == 1) ||(c == 2) ||(c == 3))==0) uds.nrc=UDS_NRC_subFunctionNotSupported; 
		}	
	} else if(uds.sid==SID_ControlDTCSetting) {
		c=uds.rx.buf[2];
		if(((c == 1) ||(c == 2))==0) uds.nrc=UDS_NRC_subFunctionNotSupported; 
		if(uds.length != 2) uds.nrc=UDS_NRC_LEN;
		uds_fail_check_no_extended(uds.nrc);
	} else if(uds.sid==SID_SecurityAccess) {
		if(((uds.length == 2) ||(uds.length == 6))==0) uds.nrc=UDS_NRC_LEN;

		//else if(((uds.rx.buf[2]==0x01) || (uds.rx.buf[2]==0x02) || (uds.rx.buf[2]==0x05) || (uds.rx.buf[2]==0x06))==0) uds.nrc=UDS_NRC_subFunctionNotSupported;
		//else {
			//if((uds.session!=NSESSION_PROGRAMMING) && (uds.rx.buf[2]==0x05)) {
		//	if(0) {
		//		uds.nrc=UDS_NRC_subFunctionNotSupportedInActiveSession;
		//	}	
		//}
	} else if(uds.sid==SID_ReadDTCInformation) {
		if(uds.length == 1) {
			uds.nrc=UDS_NRC_LEN;
		} else if((uds.rx.buf[2]==0x0a) || (uds.rx.buf[2]==0x03)) {
			if(uds.length != 2) uds.nrc=UDS_NRC_LEN;
		} else if(uds.rx.buf[2]==0x02) {
			if(uds.length != 3) uds.nrc=UDS_NRC_LEN;
		} else if(uds.rx.buf[2]==0x04) {		// SNAPSHORT
			if(uds.length != 6) {
				uds.nrc=UDS_NRC_LEN;
			} else {
				if(((uds.rx.buf[6]==1) ||(uds.rx.buf[6]==0xff))==0) {
					 uds.nrc=UDS_NRC_OUTOFRANGE;
				}
			}
		} else if(uds.rx.buf[2]==0x01) {
			if(uds.length != 3) uds.nrc=UDS_NRC_LEN;
		} else {
			uds.nrc=UDS_NRC_subFunctionNotSupported;
		}	
	} else if(uds.sid==SID_CommunicationControl) {
		c=uds.rx.buf[2]&0x7f;
		if((uds.length != 3u) && ((c == 0)||(c == 3)))  {
			uds.nrc=UDS_NRC_LEN;
		}else if((uds.length != 2u) && ((c == 1)||(c == 2)))  {
			uds.nrc=UDS_NRC_LEN;
		} else {
			if(c>0x03) {
				uds.nrc=UDS_NRC_subFunctionNotSupported;
			} else {
				if((((uds.rx.buf[3]==1) ||(uds.rx.buf[3]==2) ||(uds.rx.buf[3]==3))==0) && ((c == 0)||(c == 3))) {
					uds.nrc=UDS_NRC_OUTOFRANGE;
				}	else if((c==0x03)&&(uds.rx.buf[3]==1)) {
					//uds.nrc=UDS_NRC_subFunctionNotSupported;
				}
			}	
			//if(uds.rx.buf[2]&0x80) uds.nrc=0; 
		}	
		uds_fail_check_no_extended(uds.nrc);
	} else if(uds.sid==SID_ClearDiagnosticInformation) {
		if(uds.length != 4) uds.nrc=UDS_NRC_LEN;
		else {
			uds.group_of_dtc=uds.rx.buf[2];uds.group_of_dtc<<=8;
			uds.group_of_dtc+=uds.rx.buf[3];uds.group_of_dtc<<=8;
			uds.group_of_dtc+=uds.rx.buf[4];
			if((uds.group_of_dtc!=UDS_GroupOfDTC_ALL) && (uds.group_of_dtc!=UDS_GroupOfDTC_CHASSIS)) {
				if(is_dtc_exist(uds.group_of_dtc) == 255) 	uds.nrc=UDS_NRC_OUTOFRANGE;
			}
		}
	} else if(uds.sid==SID_TesterPresent) {
		c=uds.rx.buf[2]&0x7f;
		if(uds.length != 2) uds.nrc=UDS_NRC_LEN;
		else if(c != 0) {
			uds.nrc=UDS_NRC_subFunctionNotSupported; 
			uds.c_timeout_session_10ms=V_TIMEOUT_SESSION_10MS;
		}	else 	{
			uds.c_timeout_session_10ms=V_TIMEOUT_SESSION_10MS;
		}	
		//if(is_noresponse(uds.rx.buf[2]) && (uds.nrc!=UDS_NRC_LEN)) uds.nrc=0;
	} else if(uds.sid==SID_RoutineControl) {
		if(uds.length > 6) {
			uds.nrc=UDS_NRC_LEN;
		} else {
			if(!((uds.rx.buf[2]==1) ||(uds.rx.buf[2]==2) ||(uds.rx.buf[2]==3))) {
				uds.nrc=UDS_NRC_OUTOFRANGE;
			}	
		}
	} else if(uds.sid==SID_WriteDataByIdentifier) {
		if(uds.length < 3) uds.nrc=UDS_NRC_LEN;
	} else if(uds.sid<0x10) {
		uds.nrc=UDS_NRC_serviceNotSupport;
	}

	// =======================
	if(uds.nrc !=0) {
		uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=uds.nrc;
		uds.response_to_negetive=1;
	}
}

/** ===========================================================

===========================================================  */
void uds_fail_check_did_length(uint16_t did,uint8_t len)
{
	uds.nrc=0;
	if((did >= 0xF000) && (did < (0xffff+NTABLE_MAX))){
		
	}
	if((did == 0xF187)) {
		if(len != 10) uds.nrc=UDS_NRC_LEN;
	} else if(did==0xF18B) {
		if(len != 4) uds.nrc=UDS_NRC_LEN;
	} else if(did==0xF195) {
		if(len != 3) uds.nrc=UDS_NRC_LEN;
	} else if(did==0xF193) {
		if(len != 3) uds.nrc=UDS_NRC_LEN;
	} else if(did==0xF18C) {
		if(len != 7) uds.nrc=UDS_NRC_LEN;
	} 
	// =======================
	if(uds.nrc !=0) {
		uds.consecutive_length_fail=1;
	} else {
		uds.consecutive_length_fail=0;
	}
}
uint8_t uds_SID_StopDiagnosticSession(uint8_t k)
{
	uint8_t rp=1u;

	if(is_response_supressed) { rp=0; uds.rx.buf[2]&=0x7f;} 
	else {
		uds.tx.buf[0]=0x01u;uds.tx.buf[1]=k;
	}
	uds.session=NSESSION_DEFAULT;
	return rp;
}
/** ===========================================================

===========================================================  */
uint8_t uds_SID_DiagnosticSessionControl(uint8_t k)
{
	uint8_t * p;
	uint8_t rp=1u;
//	uint8_t print=0u;

	if(is_response_supressed) { rp=0; uds.rx.buf[2]&=0x7f;} 
  if((uds.rx.buf[2]==NSESSION_PROGRAMMING) || (uds.rx.buf[2]==NSESSION_DEFAULT) || (uds.rx.buf[2]==NSESSION_EXTENDED_DIAGNOSTIC)) {
		uds.tx.buf[0]=0x06u;uds.tx.buf[1]=k;uds.tx.buf[2]=uds.rx.buf[2];
		uds.tx.buf[3]=00; uds.tx.buf[4]=0x32;uds.tx.buf[5]=0x01;uds.tx.buf[6]=0xf4; // P2 50MS,P2*= 500
		uds.c_timeout_session_10ms=V_TIMEOUT_SESSION_10MS;
		uds.session=uds.rx.buf[2];
		if(uds.session==NSESSION_PROGRAMMING) {
			p=(void *)(BOOTVERSION_ADDRESS);
			if((p[0]!='B') || (p[1]!='O')) {
				uds.response_to_negetive=1; 		// no bootloader
			} else {
				//uds.XUPDTE_FLASH=1u;
				uds.XREQ_UDS_RESET=1u;
				rp=0;
			}	
		} else if(uds.session==NSESSION_EXTENDED_DIAGNOSTIC) {

		}
	} else {	// NRC
		uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=UDS_NRC_subFunctionNotSupported;
		uds.response_to_negetive=1;
		//uds.tx.buf[3]=00; uds.tx.buf[4]=0x32;uds.tx.buf[5]=0x01;uds.tx.buf[6]=0xf4; // P2 50MS,P2*= 500
	}
	uds.rom_access_level=0;
	return rp;
}

/** =================================

=================================  */
uint8_t uds_SID_ReadDataByIdentifier(uint8_t k)
{
	uint16_t n,nt;
	uint8_t rp=1u;

	n=uds.rx.buf[2];n<<=8u;n+=uds.rx.buf[3];	// FXXXX
	uds.ntable_did=n;
	if(n==UDS_SID_VERSION) { // VERSION READ
		n&=0x0FFF;
		uds.ntable=n;
		uds.table_seq=1;
		uds.table_control=SID_ReadDataByIdentifier;
		rp=0;
	} else if(n>=UDS_DID_F000)	{ // =
		nt=table_did_maping(n);
		if(nt==0xFFFF) {
			uds.tx.buf[0]=0x02u;uds.tx.buf[1]=uds.rx.buf[1]|0x40u;		
		} else {
			uds.ntable=nt;
			uds.table_seq=1;
			uds.table_control=SID_ReadDataByIdentifier;
			rp=0;
		}
	} else {
		if(uds.can_id == ID_UDS_TP) rp=0;
		uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=UDS_NRC_OUTOFRANGE;
		uds.response_to_negetive=1;
	} 
	return rp;
}
/** ========================================================
single frame
========================================================  */
uint8_t uds_SID_WriteDataByIdentifier(uint8_t k)
{
	uint16_t n,nt;
	uint8_t	i,len;
	uint8_t rp=1u;
	uds.table_control=SID_WriteDataByIdentifier;
	n=uds.rx.buf[2];n>>=4; 
	uds.write_data_type=n;
	uds.table_write_to=uds.rx.buf[4];
	
	n=uds.rx.buf[2];n<<=8;n+=uds.rx.buf[3];
	uds.ntable_did=n;

	if(uds.write_data_type==UDS_WTYPE_TABLE_CONTROL) {  // 'EXXX'
		rp=0;
		uds.table_seq=1;
	} else if(n>=UDS_DID_F000)	{ // 
		nt=table_did_maping_write(uds.ntable_did);
		uds.ntable=nt;
		//monprintf("nt=%d,did=%04x\n\r",nt,uds.ntable_did);
		uds.write_data_type=15;
		if((nt==0xffff) ||(EEP_ADDR_TABLE[nt][7]==0)) {
			uds.consecutive_length_fail=3;
		} else {
			if(uds.rom_access_level != 1) {
				//monprintf("Acess Level FAIL %d\n\r",uds.rom_access_level);
				uds.consecutive_length_fail=2;			// 
			} else {
				// =============================================== legth fail check
				uds.response_to_negetive=0;
				if(uds.consecutive_length_fail==0) {
					len=EEP_ADDR_TABLE[uds.ntable][2]+3;
					if(uds.length != len) {
						uds.nrc=UDS_NRC_LEN;
						uds.consecutive_length_fail=1;
						monprintf("length FAIL=%d,%d\n\r",uds.consecutive_length_fail,uds.ntable);
					}		
					uds.pdata_wr=(void *)EEP_ADDR_TABLE[uds.ntable][3];
					uds.tx_len=EEP_ADDR_TABLE[uds.ntable][2];
					uds.p_data=0;
					for(i=4;i<8;i++) {
						uds.pdata_wr[uds.p_data]=uds.rx.buf[i];
						//put_charp(uds.rx.buf[i]);put_charp(uds.rx.buf[i]);
						uds.p_data++;
						if(uds.p_data >= uds.tx_len) {
							break;
						}	
						uds_table_receve_finish(0);
						uds.consecutive_length_fail=0;
						if(uds.response_to_negetive==0) {
							if(EEP_ADDR_TABLE[uds.ntable][7]==1) uds.xreq_eep_write_did=1;
						}	
					}
				} 
				// ===============================================
			}
		}
	} 
FINISH:

	if(uds.consecutive_length_fail==1) {
		//monprintf("CF FAIL 1\n\r");
		uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=SID_WriteDataByIdentifier;uds.tx.buf[3]=UDS_NRC_LEN;
		uds.response_to_negetive=1;
	} else	if(uds.consecutive_length_fail==2) {
		//monprintf("CF FAIL 2\n\r");
		uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=SID_WriteDataByIdentifier;uds.tx.buf[3]=UDS_NRC_securityAccessDenied;
		uds.response_to_negetive=1;
	} else	if(uds.consecutive_length_fail==3) {
		uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=SID_WriteDataByIdentifier;uds.tx.buf[3]=UDS_NRC_OUTOFRANGE;
		//monprintf("lf\n\r");
	} 
	return rp;
}


/** =================================

=================================  */
uint8_t uds_SID_CommunicationControl(uint8_t k)
{
	uint8_t rp=1u;
//	uint8_t print=0u;

	if(is_response_supressed) {rp=0; uds.rx.buf[2]&=0x7f;} 
	if((uds.rx.buf[3]==NCOM_TYPE_NORMAL) || (uds.rx.buf[3]==NCOM_TYPE_ALL)) {
		if((uds.rx.buf[2]==3u) || (uds.rx.buf[2]==1u)) {
			uds.disable_rx_tx=1u;
		} else if(uds.rx.buf[2]==0u) {
			uds.disable_rx_tx=0u;
		} else if(uds.rx.buf[2]==2u) {
			uds.disable_rx_tx=1u;
			rp=0u;
		} else {
			uds.response_to_negetive=1u;
			uds.tx.buf[0]=0x02u;
		}
	}	else if(uds.rx.buf[3]==NCOM_TYPE_NM) {
		; // do not thing
	}	else  {
		uds.tx.buf[0]=0x02u;uds.rx.buf[1]=0x7F;uds.rx.buf[2]=UDS_NRC_subFunctionNotSupported;
	}

	if(is_session_default) {
		uds.tx.buf[0]=0x02u;uds.rx.buf[1]=0x7F;uds.rx.buf[2]=UDS_NRC_conditionsNotCorrect;
		uds.disable_rx_tx=0u;
	} else {
		uds.tx.buf[0]=0x02u;uds.tx.buf[1]=k;uds.tx.buf[2]=uds.rx.buf[2];
	} 
	return rp;
}


/** =================================

=================================  */
uint8_t uds_SID_RoutineControl(uint8_t k)
{
	return k;

}
/** =================================

=================================  */
uint8_t uds_SID_RequestDownload(uint8_t k)
{
	return k;

}


/** =================================

=================================  */
uint8_t uds_SID_RequestTransferExit(uint8_t k)
{
	return k;
}
/** =================================
single frame transfer
=================================  */
uint8_t uds_SID_TransferData(uint8_t k)
{
	return k;
}

/** =================================

=================================  */
uint32_t seedToKey (uint32_t seed, uint8_t level) 
{ 
	uint32_t key = 0; 		
	uint16_t i; 		
	uint32_t MASK; 	

	MASK=SECURITY_MASK_L1;

	if (seed !=0 ) {
		for ( i=0; i<35; i++ ) {
			if (seed & 0x80000000) { 
				seed = seed <<1; seed = seed^MASK; 
			} else { 
				seed = seed << 1;
			} 
		} 
		key = seed; 
	} 
	return key; 
}

/** =================================

=================================  */
uint8_t uds_SID_SecurityAccess(uint8_t k)
{
	uint32_t add;
	uint8_t rp=1u;
	uint8_t * p;

	if(is_session_default) {
		uds.tx.buf[0]=0x3u;uds.tx.buf[1]=0x7F;uds.tx.buf[2]=uds.rx.buf[1];uds.tx.buf[3]=UDS_NRC_serviceNotSupportedInActiveSession;
	} else {
		if((uds.rx.buf[2]==0x01u) || (uds.rx.buf[2]==0x05u)) { 
			uds.tx.buf[0]=0x06u;uds.tx.buf[1]=k;uds.tx.buf[2]=uds.rx.buf[2];
			if((uds.rom_access_level==1) && (uds.rx.buf[2]==0x01u)) { // alreay unloak then 0
				uds.seed[0]=0;uds.seed[1]=0;uds.seed[2]=0;uds.seed[3]=0;
				//monprintf("seed 0\n\r");
			} else {
				uds.seed[0]=uds.r_seed;uds.seed[1]=uds.r_seed+0x11;uds.seed[2]=uds.r_seed+0x22;uds.seed[3]=uds.r_seed+0x34;
			}
			uds.tx.buf[3]=uds.seed[0];uds.tx.buf[4]=uds.seed[1];uds.tx.buf[5]=uds.seed[2];uds.tx.buf[6]=uds.seed[3];
			add=uds.seed[0];add<<=8;add+=uds.seed[1];add<<=8;add+=uds.seed[2];add<<=8;add+=uds.seed[3];
			if(uds.rx.buf[2]==0x01u) {		// level 1
				add=seedToKey(add,1); 
				//uds.seed[0]=0x81;uds.seed[1]=0xBA;uds.seed[2]=0xC9;uds.seed[3]=0x29;
			} else {  // level 2
				//monprintf("seed=%08x->",add);
				add=seedToKey(add,2); 
				//monprintf("%08x\n\r",add);
				//uds.seed[0]=0x76;uds.seed[1]=0xe4;uds.seed[2]=0x98;uds.seed[3]=0x35;
			}
			uds.seed[0]=(add>>24)&0x00ff ;uds.seed[1]=(add>>16)&0x00ff;uds.seed[2]=(add>>8)&0x00ff;uds.seed[3]=(add)&0x00ff;
			uds.wait_key=1;
		}
		else if((uds.rx.buf[2]==0x02u) || (uds.rx.buf[2]==0x06u))  { 
			if(uds.wait_key!=1) {
				uds.wait_key=0;
				uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=UDS_NRC_requestSequenceError;
				uds.response_to_negetive=1;
				return rp;
			}
			uds.wait_key=0;
			
			if((uds.rx.buf[3]==uds.seed[0])&&(uds.rx.buf[4]==uds.seed[1])&&(uds.rx.buf[5]==uds.seed[2])&&(uds.rx.buf[6]==uds.seed[3])) {
				// pass
				//monprintf("seq pass\n\r");
			} else {
				uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=UDS_NRC_invalidKey;
				uds.response_to_negetive=1;
				//monprintf("key error\n\r");
			} 	

			if(uds.rx.buf[2]==0x06u) {
				p=(void *)(BOOTVERSION_ADDRESS);
				if(p[0]!='B') {
					uds.response_to_negetive=1; 		// no bootloader
					monprintf("No boot\n\r");
				}
			} 
			if(uds.response_to_negetive==0) {
				uds.tx.buf[0]=0x02u;uds.tx.buf[1]=k;uds.tx.buf[2]=uds.rx.buf[2];
				rp=0;
				send_uds_tx();
				if(uds.rx.buf[2]==0x06u) {
					uds.rom_access_level=2;
					//uds.XUPDTE_FLASH=1u;
					uds.XREQ_UDS_RESET=1u;
					OutStr("reset\n\r");
					OutStr("reset\n\r");
					OutStr("reset\n\r");
				} else {
					if((uds.session==NSESSION_PROGRAMMING) || (uds.session==NSESSION_EXTENDED_DIAGNOSTIC)) {
						uds.rom_access_level=1;
						//monprintf("AL 1,%d\n\r",uds.session);
					}	
				}
			} 	
		}
	}

	return rp;
}


/** =================================

=================================  */
uint8_t uds_data_receve_finish(uint8_t print)
{

	uint8_t	rp=1;
	uds.nrc=0;

	if(	uds.response_to_negetive==1) {
		uds.tx.buf[1]=0x7f;
		uds.response_to_negetive=0;
	}	

	if(uds.sid==SID_RoutineControl) {
		if(uds.length > 6) {
			uds.nrc=UDS_NRC_LEN;
		} else {
			if(!((uds.rx.buf[2]==1) ||(uds.rx.buf[2]==2) ||(uds.rx.buf[2]==3))) {
				uds.nrc=UDS_NRC_OUTOFRANGE;
			}	
		}
	} else if(uds.sid==SID_RequestDownload) {
		uds.nrc=UDS_NRC_subFunctionNotSupported;
	}
	//put_int_dec(uds.p_data);put_int_dec(uds.tx_len);	OutStr("data_receve finish\n\r");

	return rp;



}

/** ==================================================================

==================================================================  */
uint8_t uds_single_frame(void)
{
	uint8_t i,k,rp=1u;
	//uint8_t seq=0;
	
	uds.sid =uds.rx.buf[1];
	uds.length=uds.rx.buf[0];
	uds.response_to_negetive=0;
	if((uds.can_length-1) <  uds.length) {	rp=0;	return rp;	}
	if((uds.length==0) || (uds.length>7)) {rp=0;	return rp; }
	// ======================================
	uds_single_frame_error_check();
	if(uds.response_to_negetive==1) {
		if((uds.can_id==ID_UDS_TP) && ((uds.nrc==UDS_NRC_subFunctionNotSupported)||(uds.nrc==UDS_NRC_serviceNotSupport)))	{
			uds.response_to_negetive=0;		// FUCTIONAL DPSMS NO RES
			rp=0;
		}	
		return rp;
	}
	// ======================================
	k=uds.sid|0x40u;	// ack
	if(uds.rx.buf[1]==SID_DiagnosticSessionControl)  { 
		rp=uds_SID_DiagnosticSessionControl(k);
	} else if(uds.rx.buf[1]==SID_StopDiagnosticSession) {
		rp=uds_SID_StopDiagnosticSession(k);
	} else if(uds.rx.buf[1]==SID_ControlDTCSetting) {
		rp=uds_SID_ControlDTCSetting(k);
	} else if(uds.sid==SID_ReadDataByPeriodicIdentifier) {
		uds.ReadDataByPeriodicIdentifier_10ms=uds.rx.buf[3];
		uds.tx.buf[0]=0x02u;uds.tx.buf[1]=0x6a;uds.tx.buf[2]=uds.rx.buf[2];
	} else if(uds.sid==SID_ReadDataByIdentifier) {
		rp=uds_SID_ReadDataByIdentifier(k);
	} else if(uds.sid==SID_WriteDataByIdentifier) {
		rp=uds_SID_WriteDataByIdentifier(k);
	} else if(uds.sid==SID_CommunicationControl) {
		rp=uds_SID_CommunicationControl(k);
	} else if(uds.sid==SID_InputOutputControlByIdentifier) {
		uds.tx.buf[0]=0x06u;uds.tx.buf[1]=0x6fu;
		for(i=0;i<6;i++)	{
			/*TABLE_IO_CONTROL[i]=uds.rx.buf[i+2u];  IO CONTROL */
			uds.tx.buf[i+2u]=uds.rx.buf[i+2u];
		} 
	} else if(uds.sid==SID_ClearDiagnosticInformation) {
		uds_tx_buf_clear();
		if((uds.group_of_dtc==UDS_GroupOfDTC_ALL) || (uds.group_of_dtc==UDS_GroupOfDTC_CHASSIS)) {
			uds.xreq_dtc_clear=1u;
		} else {
			dtc_found_and_clear(uds.group_of_dtc);
		}
		uds.tx.buf[0]=0x01u;uds.tx.buf[1]=SID_ClearDiagnosticInformation|0x40u;
	} else if(uds.sid==SID_SecurityAccess) {
		rp=uds_SID_SecurityAccess(k);
	} else if(uds.sid==SID_ReadDTCInformation) {
		rp=uds_interrupt_sid_dtc();
	} else if(uds.sid==SID_RoutineControl) {
		for(i=0;i<7;i++) uds.data[i]=uds.rx.buf[i+1];
		rp=uds_SID_RoutineControl(k);
	} else if(uds.sid==SID_ECUReset) { 
		uds.tx.buf[0]=0x02u;uds.tx.buf[1]=k;uds.tx.buf[2]=uds.rx.buf[2];
		send_uds_tx();
		//delayN(20000);
			OutStr("SID_ECUReset:reset\n\r");
			//goto_application();
			// MAP REFLASH		
			OutStr("APP JUMP FAIL\n\r");
			//uds.tx.buf[1]=0x7E;		// NEGATIVE
	} else if(uds.sid==SID_TesterPresent) {
		if(is_response_supressed) { 	
			rp=0;
		} else { 
			uds.tx.buf[0]=0x02u;uds.tx.buf[1]=uds.rx.buf[1]|0x40;uds.tx.buf[2]=uds.rx.buf[2];
			rp=1;
		}
	}else{
		rp=0;
		avoid_empty_block();	
	} 
	return rp;
}
/** =================================

=================================  */
uint8_t uds_SID_FF_dataread(uint8_t k)
{
	uint16_t n,nt;
	uint8_t rp=1u;

	uds.write_data_type=UDS_WTYPE_TABLE_WRITE;
	uds.tx_len=uds.rx.buf[0]&0xf;uds.tx_len<<=8;
	uds.tx_len+=uds.rx.buf[1];
	uds.pdata_wr=uds.data;
	uds.table_seq=3u;
	uds.consecutive_rx_num=0x20;
	if(uds.sid==SID_InputOutputControlByIdentifier) {
		uds.table_control=SID_WriteDataByIdentifier;
		uds.table_seq=3;
		uds.pdata_wr=(void *)&uds.io_control_parameter[0];
		n=uds.rx.buf[3];n<<=8;n+=uds.rx.buf[4];
		uds.io_control_did=n;
		uds.io_control_parm=uds.rx.buf[5];
		uds.ntable_did=n;		// response .
		uds.tx_len-=3;		// SID , DID 3 BYTE 
		uds.io_control_parameter_len=uds.tx_len;		// SID , DID 3 BYTE 
		uds.p_data=0;
		uds.pdata_wr[uds.p_data++]=uds.rx.buf[4];
		uds.pdata_wr[uds.p_data++]=uds.rx.buf[5];
		uds.pdata_wr[uds.p_data++]=uds.rx.buf[6];
		uds.pdata_wr[uds.p_data++]=uds.rx.buf[7];
		//monprintf("FF io cont did=%x,[%d]len=%d\n\r",uds.io_control_did,uds.io_control_parm,uds.io_control_parameter_len);
		set_flow_control();
	} else {
		n=uds.rx.buf[3];n<<=8;n+=uds.rx.buf[4];
		uds.ntable_did=n;
		nt=table_did_maping(uds.ntable_did);
		//monprintf("wr %x,[%d]%d\n\r",uds.ntable_did,nt,rp);
		if(nt==0xFFFF) {
			uds.nrc=UDS_NRC_OUTOFRANGE;
			uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=uds.nrc;
		} else if(EEP_ADDR_TABLE[nt][7]==0) {
			uds.nrc=UDS_NRC_OUTOFRANGE;
			uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=uds.nrc;
		} else {
			uds.ntable=nt;
			uds.table_control=SID_WriteDataByIdentifier;
			uds.table_seq=3;
			uds.pdata_wr=(void *)EEP_ADDR_TABLE[uds.ntable][3];
			uds.tx_len=EEP_ADDR_TABLE[uds.ntable][2];
			uds.p_data=0;
			uds.pdata_wr[uds.p_data++]=uds.rx.buf[5];
			uds.pdata_wr[uds.p_data++]=uds.rx.buf[6];
			uds.pdata_wr[uds.p_data++]=uds.rx.buf[7];
			set_flow_control();
		}
	}	
	return rp;
}

/** -------------------------------------------
TABLE_DTC_SEND 로 받아둔다.
---------------------------------------------- */
uint8_t uds_SID_FF_NULL(uint8_t k)
{
	uint8_t	i;
	uint8_t rp=1u;

	uds.write_data_type=0;							// null
	uds.tx_len=uds.rx.buf[0] & 0x0fu;
	uds.tx_len<<=8u;
	uds.tx_len+=uds.rx.buf[1];
	if(uds.tx_len > MAX_DTC_SEND) uds.tx_len=MAX_DTC_SEND;
	uds.ntable=0;	
	uds.table_control=uds.rx.buf[2];
	uds.ntable_did=uds.rx.buf[3];uds.ntable_did	<<=8;uds.ntable_did	+=uds.rx.buf[4];
	uds.table_seq=3u;
	uds.consecutive_rx_num=0x20;
	uds.pdata_wr=(void *)TABLE_DTC_SEND;
	uds.p_data=0;
	for(i=3;i<8;i++)	uds.data[uds.p_data++]=uds.rx.buf[i];
	set_flow_control();

	return rp;
}

uint8_t uds_first_frame(void)
{
	uint16_t k=0;
	uint8_t rp=1u;
	uds.nrc=0;uds.response_to_negetive=0;
	uds.sid=uds.rx.buf[2];
	uds.response_to_negetive=0;
	uds.nrc=0;

	if((uds.sid==SID_RoutineControl)||(uds.sid==SID_RequestDownload)||(uds.sid==SID_WriteDataByIdentifier)||(uds.sid==SID_TransferData)) {
		uds.consecutive_length_fail=0;
		if((uds.sid==SID_WriteDataByIdentifier) && (is_session_default || uds.rom_access_level==0)) {
			uds.nrc=UDS_NRC_subFunctionNotSupportedInActiveSession;
			uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=uds.nrc;
			uds.response_to_negetive=1;
		} else {
			rp=uds_SID_FF_dataread(k);
		}	
	}
	return rp;
}

/** =================================================

=================================================== */
#define is_7DF_to_PHY(n) ((n==SID_CommunicationControl) ||(n==SID_DiagnosticSessionControl) ||(n==SID_ClearDiagnosticInformation) ||(n==SID_ControlDTCSetting) || (n==SID_TesterPresent)|| (n==SID_ReadDataByIdentifier) || (n==SID_ECUReset) || (n==SID_ReadDTCInformation)) 
void uds_logic_interrupt(uint8_t *buf)
{
	uint8_t	i,k;
	uint8_t rp=1u;	
	uint32_t n;

	uds.x2ms=0;
	uds.timeout=UDS_TIME_OUT;
	uds.c_timeout_session_10ms=V_TIMEOUT_SESSION_10MS;
	

	//monprintf("UDS\n\r");
	for(k=0;k<8;k++) uds.tx.buf[k]=0x00u;
	uds.response_to_negetive=0u;
	if(uds.rx.id==ID_UDS_RX) {
		for(i=0;i<8;i++) uds.rx.buf[i]=buf[i];
		uds.can_id=ID_UDS_RX;	
	}	else if (uds.rx.id==ID_UDS_TP) {
		if(buf[0] & 0xF0) return;				 
		if(is_7DF_to_PHY(buf[1])) {
			uds.can_id=ID_UDS_TP;	
			for(i=0;i<8;i++) uds.rx.buf[i]=buf[i];
		}	else {
			return;
		}
	} else {
		return;
	}
	

	if(is_single_frame) {
		rp=uds_single_frame();
	}	else if(is_first_frame) {
		rp= uds_first_frame();
	} else if(is_consecutive_frame) {
		if((uds.sid==SID_WriteDataByIdentifier)||(uds.sid==SID_RoutineControl)||(uds.sid==SID_RequestDownload)) {
			rp=0;
			if((uds.table_seq==3u) /*&& ((uds.table_control==SID_WriteDataByIdentifier)||(uds.table_control==0))*/) {
				k=1u;
				if(uds.can_length < 8) {
					n=uds.can_length-1;
					if((uds.p_data+n) < uds.tx_len) {
						rp=0u;
						uds.table_seq=0;
					}
				} else {
					if(uds.consecutive_rx_num==uds.rx.buf[0]) { // 21,22....2f
						rp=0;
						uds.table_seq=0;
						OutStr("#consecutive_num FAIL\n\r");
					}	else {
						uds.consecutive_rx_num=uds.rx.buf[0];
						uds.c_wait_cf_10ms=13;			// 100 + bs
						for(i=k;i<8;i++)	{
							if(uds.consecutive_length_fail==0) uds.pdata_wr[uds.p_data]=uds.rx.buf[i]; // set data
							uds.p_data++;
							if(uds.p_data >= uds.tx_len) {
								if(uds.consecutive_length_fail==1) {
									uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=UDS_NRC_LEN;
									uds.response_to_negetive=1;
								} else	if(uds.consecutive_length_fail==2) {
									uds.tx.buf[0]=0x03u;uds.tx.buf[1]=UDS_NAK;uds.tx.buf[2]=uds.sid;uds.tx.buf[3]=UDS_NRC_securityAccessDenied;
									uds.response_to_negetive=1;
								} else {
									uds_table_receve_finish(0);
									if(EEP_ADDR_TABLE[uds.ntable][7]==1) uds.xreq_eep_write_did=1;
									monprintf("CS end %d,%d,%d\n\r",uds.response_to_negetive,EEP_ADDR_TABLE[uds.ntable][7],uds.xreq_eep_write_did);
									rp=1;
								}	
								uds.consecutive_length_fail=0;
								rp=1u;
								break;
							}
						}	
					}
				}
			}	
		}
	} else if(is_flow_control) {
		if(uds.can_length < 3) {
				uds.table_seq=0;
		} else {
			if(is_flow_control_wait==1)  {
				uds.c_wait_flowcontrol_10ms=V_c_wait_flowcontrol_10ms;		
			} else {
				if((uds.wait_flowcontrol==0u) && (uds.rx.buf[0]==0x32)) {
					uds.tx.buf[0]=0x3u;uds.tx.buf[1]=0x62;
					uds.tx.buf[2]=uds.ntable_did>>8;uds.tx.buf[3]=uds.ntable_did;
					return;
				}
				uds.wait_flowcontrol=0u;
				uds.flow_control_ms=uds.rx.buf[2];
				uds.flow_control_ms+=3;
				uds.c_flow_control_ms=uds.flow_control_ms;
				uds.c_wait_flowcontrol_10ms=0;		
				if(is_flow_control_abort_cons)  {
					uds.table_seq=0;
				}
			}
		}
		rp=0u;
	} else  {
		rp=0u;
	}
	if(rp!=0) {
		if( uds.response_to_negetive==1) {
			uds.tx.buf[1]=0x7f;
		} 
		uds.tx.xreq_send=1u;	
	}
	uds.response_to_negetive=0;
	uds.x2ms=0;
}
/** ==================================================================

==================================================================  */
void goto_reset(void) 
{ 			 
	uint8_t *p;
	uint32_t *add;
	uint32_t i;

	monprintf("goto reset\n\r");
	__asm(" cpsid i");	//  OsIf_SuspendAllInterrupts();
	i=1000; 
	while(i) i--;
	add=(void *)(SHADOWRAM);			
	add[0]=SHADOW_BOOT;
	add[1]=0x10;			// REQ REPLAY POISITIVE
	monprintf("WATCHDOG_HAL_SystemRest\n\r");
  WATCHDOG_HAL_SystemRest();
  while(1)
  {
		monprintf("wait Rest...\n\r");
    /*wait watch dog reset mcu*/
  }
	while(1) {
		monprintf("wait until watchdog\r");
	}	
}

