This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TRF7960EVM: Anticollision failure

Part Number: TRF7960EVM

I am using the EVM7960A. When trying to read two IEC15693 tags with three identical least significant nibbles

the anticollision fails that the tags are not read. For example UIDs:

E00401504C3948F0

E00401504A2608F0

This event is unusual but it does occur. Any help would be appreciated.

Will

  • Hello Will,

    I believe this is related to a bug in the firmware anticollision process, please try see this post which has an updated iso15693.c file: https://e2e.ti.com/support/wireless_connectivity/nfc_rfid/f/667/p/557855/2040789#2040789

    If you use that along with the firmware provided on the TRF7960AEVM page and re-flash the TRF7960AEVM, you should be able to read the tags.

  • Hi Ralph,

    Thanks for your answer. I had to get an MSP-FET430UIF to try the new iso15693.c file but it did not make a difference.
    Still fails to read tags with the same final three nibbles.

    Regards,

    Will
  • Hello Will,

    Sorry for the delay in getting back to you on this - I tested the code further was able to recreate the failures. They didn't happen always for me, just sporadically, but I uncovered the root source and made one more key change (a delay is needed when getting a collision error).

    Please try this updated iso15693.c file: 

    4478.iso15693.c
    /****************************************************************
    * FILENAME: iso15693.c
    *
    * BRIEF: Contain functions to search ISO15693 standardized tags
    * in stand alone mode and execute ISO15693 Anticollision in
    * remote mode.
    *
    * Copyright (C) 2010 Texas Instruments, Inc.
    *
    * AUTHOR(S): Reiser Peter		DATE: 02 DEC 2010
    *
    * EDITED BY:
    * *
    *
    ****************************************************************/
    
    #include "iso15693.h"
    
    //===============================================================
    
    u08_t afi = 0;
    u08_t flags = 0;							// stores the mask value (used in anticollision)
    extern u08_t buf[300];
    extern u08_t i_reg;
    extern u08_t irq_flag;
    extern s08_t rxtx_state;
    extern u08_t rx_error_flag;
    extern u08_t stand_alone_flag;
    extern u08_t host_control_flag;
    
    //===============================================================
    // NAME: void Iso15693FindTag(void)
    //
    // BRIEF: Is used to detect ISO15693 conform tags in stand alone 
    // mode.
    //
    // INPUTS:
    //	
    // OUTPUTS:
    //
    // PROCESS:	[1] turn on RF driver
    //			[2] do a complete anticollision sequence
    //			[3] turn off RF driver
    //
    // NOTE: If ISO15693 conform Tag is detected, ISO15693 LED will
    //       be turned on.
    //
    // CHANGE:
    // DATE  		WHO	DETAIL
    // 23Nov2010	RP	Original Code
    //===============================================================
    
    void
    Iso15693FindTag(void)
    {
    	Trf796xTurnRfOn();
    	
    	Trf796xWriteIsoControl(0x02);
    
    	// The VCD should wait at least 1 ms after it activated the
    	// powering field before sending the first request, to
    	// ensure that the VICCs are ready to receive it. (ISO15693-3)
    	McuDelayMillisecond(1);
    
    	flags = SIXTEEN_SLOTS;
    	
    	buf[20] = 0x00;
    	Iso15693Anticollision(&buf[20], 0);					// send Inventory request
    
    	Trf796xTurnRfOff();
    
    	Trf796xResetIrqStatus();                         
    	// clear any IRQs
    }
    
    //===============================================================
    // NAME: void Iso15693Anticollision(u08_t *mask, u08_t length)
    //
    // BRIEF: Is used to perform a inventory cycle of 1 or 16
    // timeslots.
    //
    // INPUTS:
    //	Parameters:
    //		u08_t		*mask		mask value
    //		u08_t		length		number of significant bits of
    //								mask value
    //	
    // OUTPUTS:
    //
    // PROCESS:	[1] send command
    //			[2] receive respond
    //			[3] send respond to host
    //
    // CHANGE:
    // DATE  		WHO	DETAIL
    // 23Nov2010	RP	Original Code
    //  3May2011    AF  Bugfix
    //===============================================================
    
    void
    Iso15693Anticollision(u08_t *mask, u08_t length)		// host command 0x14
    {
    	
    
    	
    	
    	u08_t	i = 1, j = 1, command[2], no_slots, found = 0;
    	
    	u08_t	*p_slot_no, slot_no[17];
    	u08_t	new_mask[8], new_length, mask_size;
    	u32_t	size;
            
    	u08_t	fifo_length = 0;
    	
    	u16_t	k;
    
    	slot_no[0] = 0x00;
    	
    	// BUGFIX
    	TRF796xCheckRXWaitTime();		
    	
    	if((flags & BIT5) == 0x00)							// flag bit5 is the number of slots indicator	
    	{	
    		no_slots = 16;									// 16 slots if bit is cleared
    		Trf796xEnableSlotCounter();
    	}
    	else
    	{	
    		no_slots = 1;									// 1 slot if bit is set
    	}
    
    	p_slot_no = &slot_no[0];							// slot number pointer
    
    	mask_size = (((length >> 2) + 1) >> 1);				// mask_size is 1 for length = 4 or 8
    
    	buf[0] = 0x8F;
    	buf[1] = 0x91;										// send with CRC
    	buf[2] = 0x3D;										// write continuous from 1D
    	buf[5] = flags;										// ISO15693 flags
    	buf[6] = 0x01;										// anticollision command code
    
    	//optional afi should be here
    	if(flags & 0x10)
    	{
    		// mask_size is 2 for length = 12 or 16 ;
    		// and so on
    
    		size = mask_size + 4;							// mask value + mask length + afi + command code + flags
              
    		buf[7] = afi;
    		buf[8] = length;								// masklength
    		if(length > 0)
    		{	
    			for(i = 0; i < mask_size; i++) 
                {	
                	buf[9 + i] = *(mask + ((mask_size-1)-i));
                }
    		}									
    		fifo_length = 9;
    	}
    	else
    	{ 
    		// mask_size is 2 for length = 12 or 16
    		// and so on
    
    		size = mask_size + 3;							// mask value + mask length + command code + flags
              
    		buf[7] = length;								// masklength
    		if(length > 0)
    		{	
    			for(i = 0; i < mask_size; i++)
    			{	
    				buf[8 + i] = *(mask + ((mask_size-1)-i));
    			}
    		}									
    		fifo_length = 8;
    	}
    
    	buf[3] = (char) (size >> 8);
    	buf[4] = (char) (size << 4);
              
    	Trf796xResetIrqStatus();
    
    
    	McuCounterSet();									// TimerA set
    	COUNT_VALUE = COUNT_1ms * 30;						// 20ms
    	IRQ_CLR;											// PORT2 interrupt flag clear
    	IRQ_ON;
    
    	Trf796xRawWrite(&buf[0], mask_size + fifo_length);	// writing to FIFO
    	
    	
    	
    	i_reg = 0x01;
    	irq_flag = 0x00;
    	START_COUNTER;										//	start timer up mode
    	
    	while(irq_flag == 0x00)
    	{
    	}													// wait for end of TX interrupt
    
    	for(j = 1; j <= no_slots; j++)						// 1 or 16 available timeslots
    	{	rxtx_state = 1;									// prepare the extern counter
    
    		// the first UID will be stored from buf[1] upwards
    		McuCounterSet();								// TimerA set
    		COUNT_VALUE = COUNT_1ms * 20;	
    		START_COUNTER;									// start timer up mode 
    		
    		irq_flag = 0x00;
    
    		while(irq_flag == 0x00)
    		{
    		}												// wait for interrupt
    	
    		while(i_reg == 0x01)							// wait for RX complete
    		{
    			k++;
    
    			if(k == 0xFFF0)
    			{
    				i_reg = 0x00;
    				rx_error_flag = 0x00;
    			}
    		}
    
    		command[0] = RSSI_LEVELS;						// read RSSI levels
    		Trf796xReadSingle(command, 1);
    		switch(i_reg)
    		{
    			case 0xFF:									// if recieved UID in buffer
    				if(stand_alone_flag == 1)
    				{	
    					found = 1;
    				}
    				else
    				{	
    					#ifdef ENABLE_HOST
    						UartPutCrlf();
    						UartPutChar('[');
    						for(i = 3; i < 11; i++)
    						{	
    							UartPutByte(buf[i]);		// send UID to host
    						}
    						UartPutChar(',');
    						UartPutByte(command[0]);		// RSSI levels
    						UartPutChar(']');
    						UartPutCrlf();
    					#endif
    				}
    				break;
    				
    			case 0x02:									// collision occured	
    				if(stand_alone_flag == 0)
    				{	
    					#ifdef ENABLE_HOST
    						UartPutChar('[');
    						UartPutChar('z');
    						UartPutChar(',');
    						UartPutByte(command[0]);		// RSSI levels
    						UartPutChar(']');
    					#endif
    				}
    	
    				p_slot_no++;							// remember a collision was detected
    				*p_slot_no = j;
    				McuDelayMillisecond(5);
    				break;
    				
    			case 0x00:									// timer interrupt
    				if(stand_alone_flag == 0)
    				{	
    					#ifdef ENABLE_HOST
    						UartPutChar('[');				// send no-response massage to host
    						UartPutChar(',');
    						UartPutByte(command[0]);		// RSSI levels
    						UartPutChar(']');
    					#endif
    				}
    				break;
    			
    			default:
    				break;
    		}
    		
    		Trf796xReset();									// FIFO has to be reset before recieving the next response
    		if((no_slots == 16) && (j < 16))				// if 16 slots used send EOF(next slot)
    		{	
    			Trf796xStopDecoders();
    			Trf796xRunDecoders();
    			Trf796xTransmitNextSlot();
    		}
    		else if((no_slots == 16) && (j == 16))			// at the end of slot 16 stop the slot counter
    		{	Trf796xStopDecoders();
    			Trf796xDisableSlotCounter();
    		}
    		else if(no_slots == 1)							// 1 slot is used
    		{	
    			break;
    		}
    
    		if(stand_alone_flag == 0)
    		{	
    			#ifdef ENABLE_HOST
    				//UartPutCrlf();
    			#endif
    		}
    	}													// for
    
    	if(host_control_flag == 0)
    	{
    		if(found == 1)									// LED on?
    		{	
    			LED_15693_ON;								// LEDs indicate detected ISO15693 tag		
    		}
    		else
    		{	
    			LED_15693_OFF;
    			LED_POWER_ON;		
    		}
    	}
    
    	new_length = length + 4; 							// the mask length is a multiple of 4 bits
    
    	mask_size = (((new_length >> 2) + 1) >> 1);
    	
    	while((*p_slot_no != 0x00) && (no_slots == 16) && (new_length < 61) && (slot_no[16] != 16))
    	{	
    		*p_slot_no = *p_slot_no - 1;
    
    		for(i = 0; i < 8; i++)
    		{	
    			new_mask[i] = *(mask + i);				//first the whole mask is copied
    		}
    		
    		if((new_length & BIT2) == 0x00)
    		{	
    			*p_slot_no = *p_slot_no << 4;
    		}
    		else
    		{
    			for(i = 7; i > 0; i--)
    			{
    				new_mask[i] = new_mask[i - 1];
    			}
    			new_mask[0] &= 0x00;
    		}
    		new_mask[0] |= *p_slot_no;				// the mask is changed
    		McuDelayMillisecond(2);
    
    		Iso15693Anticollision(&new_mask[0], new_length);	// recursive call with new Mask
    
    		p_slot_no--;
    	}
    	
    	IRQ_OFF;
    
    }														// Iso15693Anticollision
    
    //===============================================================
    // NAME: void TRF796xCheckRXWaitTime()
    //
    // BRIEF: a bug writes wrong value in register 0x07 "RX no response wait"
    //        this causes ISO15693 Anticollision to fail
    //
    // INPUTS:
    //	
    // OUTPUTS:
    //
    // PROCESS:	[1] read ISO register to check if low or high data rate
    //			[2] set correct value in register 0x07 "RX no response wait"
    //			
    //
    // CHANGE:
    // DATE  		WHO	DETAIL
    // 3May2011	Andre Frantzke	Bugfix
    //===============================================================
    
    void TRF796xCheckRXWaitTime(void)
    {
    	u08_t MyRegister[2],write[2];
    	
    	// [1] read ISO register to check if low or high data rate
    	MyRegister[0] = ISO_CONTROL;
    	MyRegister[1] = ISO_CONTROL;				
    	Trf796xReadSingle (&MyRegister[1], 1);
    	
    	//[2] set correct value in register 0x07 "RX no response wait"
    	if((MyRegister[1] < 0x02) || (MyRegister[1] == 0x04) || (MyRegister[1] == 0x05)) // low data rate
    	{
    		write[0] = RX_NO_RESPONSE_WAIT_TIME;
    		write[1] = 0x30;				// 1812 us
    		Trf796xWriteSingle(write, 2);
    	}
    	else
    	{
    		write[0] = RX_NO_RESPONSE_WAIT_TIME;
    		write[1] = 0x14;				// 755 us
    		Trf796xWriteSingle(write, 2);
    	}
    
    
    }
    
    
    /*
    	u08_t MyRegisters[30], MyTemp[2];
    	MyRegisters[0] = CHIP_STATE_CONTROL;
    	MyRegisters[1] = CHIP_STATE_CONTROL;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[1], 1);
    	
    	MyRegisters[2] = ISO_CONTROL;
    	MyRegisters[3] = ISO_CONTROL;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[3], 1);
    	
    	MyRegisters[4] = ISO_14443B_OPTIONS;
    	MyRegisters[5] = ISO_14443B_OPTIONS;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[5], 1);
    	
    	MyRegisters[6] = ISO_14443A_OPTIONS;
    	MyRegisters[7] = ISO_14443A_OPTIONS;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[7], 1);
    	
    	MyRegisters[8] = TX_TIMER_EPC_HIGH;
    	MyRegisters[9] = TX_TIMER_EPC_HIGH;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[6], 1);
    	
    	MyRegisters[10] = TX_TIMER_EPC_LOW;
    	MyRegisters[11] = TX_TIMER_EPC_LOW;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[11], 1);
    	
    	MyRegisters[12] = TX_PULSE_LENGTH_CONTROL;
    	MyRegisters[13] = TX_PULSE_LENGTH_CONTROL;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[13], 1);
    	
    	MyRegisters[14] = RX_NO_RESPONSE_WAIT_TIME;
    	MyRegisters[15] = RX_NO_RESPONSE_WAIT_TIME;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[15], 1);
    	
    	MyRegisters[16] = RX_WAIT_TIME;
    	MyRegisters[17] = RX_WAIT_TIME;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[17], 1);
    	
    	MyRegisters[18] = MODULATOR_CONTROL;
    	MyRegisters[19] = MODULATOR_CONTROL;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[19], 1);
    	
    	MyRegisters[20] = RX_SPECIAL_SETTINGS;
    	MyRegisters[21] = RX_SPECIAL_SETTINGS;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[21], 1);
    	
    	MyRegisters[22] = REGULATOR_CONTROL;
    	MyRegisters[23] = REGULATOR_CONTROL;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[23], 1);
    			
    	MyRegisters[24] = IRQ_STATUS;
    	MyRegisters[25] = IRQ_STATUS;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[25], 1);
    	
    	MyRegisters[26] = IRQ_MASK;
    	MyRegisters[27] = IRQ_MASK;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[27], 1);
    	
    	MyRegisters[28] = COLLISION_POSITION;
    	MyRegisters[29] = COLLISION_POSITION;				// next slot counter
    	Trf796xReadSingle (&MyRegisters[29], 1);
    	*/
    

  • Hi Ralph,

    Thanks again for your answer. I compiled the iso15693.c file you linked and reprogrammed the
    the TRF7960A EVM but had the same result. I am using the ICODE SLIX2 tags. Not sure why that
    might make a difference. Tried reading the tags on the TRF7970A BoosterPack and LaunchPad
    combination and had no problem.

    Regards,

    Will
  • Hello Will,

    There are timing differences between NXP SLI tags and TI Tag-It Transponders, typically concerning the amount of time until a tag replies to a command.

    In the trf796x.c file, there is a function to set the registers, Trf796xWriteIsoControl

    Find these lines in it (look around line 717): 

    if((iso_control < 0x02) || (iso_control == 0x04) || (iso_control == 0x05)) // low data rate
    {
    	write[0] = RX_NO_RESPONSE_WAIT_TIME;
    	write[1] = 0x30;				// 1812 us
    	Trf796xWriteSingle(write, 2);
    }
    else
    {
    	write[0] = RX_NO_RESPONSE_WAIT_TIME;
    	write[1] = 0x14;				// 755 us
    	Trf796xWriteSingle(write, 2);
    }
    		

    The setting in the ELSE statement is what you want to change, the 0x14. In the TRF7970A BoosterPack code, it is set to 0x15 if I remember right, so try increasing that. I'd try 0x20 and see if that works just to give the tags more time.

    I would usually try and track down the setting myself but I don't have NXP tags that collide that far in...

    In the past, that setting was been the culprit, so tinker with it a bit and see if you get better results.

  • Hi Ralph,

    I made modifications to the 'while block' which runs the recursive anti-collision call

    along the lines of the TRF7970A BoosterPack and LaunchPack code. The GUI for

    the TRF7960A EVM still does not report tags with collisions in the first 3 nibbles but

    when I connect the firmware directly to a terminal and step through code I can see

    the collisions are correctly resolved and then each of the tags are reported. This

    along with adjusting the wait times solves the problem for me.

    Many thanks,

    Will