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.

Some questions on TI example code of TRF7960A .

Other Parts Discussed in Thread: TRF7960A, TRF7970A, TRF7963A, TRF7960

Hi Ti employee,

 I'm working on a project demands TRF7960A to read and write a ISO15693 tag(Tag-it). I have experenced on

using TRF7970A , so I migrated my TRF7970A code to TRF7960A. However, it works not quite well.  I downloaded

the example code of TRF796x(sloc251.zip) and find some issues need  your  help.

1st) SpiReadSingle  must  send 0x00 when read data from TRF7960A.

void SpiReadSingle(u08_t *pbuf, u08_t number)

{                          

    SLAVE_SELECT_LOW;                                                    // Start SPI Mode

    while(number > 0)

    {       

        // Address/Command Word Bit Distribution

        *pbuf = (0x40 | *pbuf);                     // address, read, single

        *pbuf = (0x5f & *pbuf);                                // register address

        while (!(IFG2 & UCB0TXIFG))                     // USCI_B0 TX buffer ready?

        {

        }

        UCB0TXBUF = *pbuf;                                             // Previous data to TX, RX

        while(UCB0STAT & UCBUSY)

        {

        }

        temp=UCB0RXBUF;

        UCB0CTL0 &= ~UCCKPH;

        while (!(IFG2 & UCB0TXIFG))  // USCI_B0 TX buffer ready?

        {

        }

        UCB0TXBUF = 0x00;        // Receive initiated by a dummy TX write???

// UCB0TXBUF must be assigned with 0x00, if u give 0xAA or any other value to  UCB0TXBUF. This fuction will

//failed.   how to explain ?

       while (!(IFG2 & UCB0RXIFG))  // USCI_B0 RX buffer ready?

        {

        }

        *pbuf = UCB0RXBUF;

        pbuf++;

        number--;

        UCB0CTL0 |= UCCKPH;

    }

    while(UCB0STAT & UCBUSY)

    {

    }

    SLAVE_SELECT_HIGH;                                                   // Stop SPI Mode

}

2nd)

void

SpiReadCont(u08_t *pbuf, u08_t length)

{       

    u08_t        j = 0;

   

    SLAVE_SELECT_LOW;                                                              //Start SPI Mode

    // Address/Command Word Bit Distribution

    *pbuf = (0x60 | *pbuf);                                        // address, read, continuous

    *pbuf = (0x7f &*pbuf);                                                   // register address

    while (!(IFG2 & UCB0TXIFG))                                        // USCI_B0 TX buffer ready?

    {

    }

    UCB0TXBUF = *pbuf;                                                   // Previous data to TX, RX

    while(UCB0STAT & UCBUSY)

    {

    }

    temp = UCB0RXBUF;

    UCB0CTL0 &= ~UCCKPH;

   

    if(*pbuf != 0x6C)      // execute only when IRQRead is not called

    {       

        if (length != 0x1F)

        {       

            for (j=0;j<2;j++)

            {       

                while (!(IFG2 & UCB0TXIFG))// USCI_B0 TX buffer ready?

                {

                }

                UCB0TXBUF = 0x00; // Receive initiated by a dummy TX write

                while(UCB0STAT & UCBUSY)

                {

                }

                temp = UCB0RXBUF;

            }

        }

    }

   // what's the purpose of this red code ?  It's not needed in TRF7970A . It looks like when we cont read a

register except (0x0C) , we need tx extra 16 CLKs ? why ?

   

    while(length > 0)

    {       

        while (!(IFG2 & UCB0TXIFG))

        {

        }

        UCB0TXBUF = 0x00;                                             // Receive initiated by a dummy TX write

        while(UCB0STAT & UCBUSY)

        {

        }

        _NOP();

        _NOP();

        *pbuf = UCB0RXBUF;

        pbuf++;

        length--;

    }

    UCB0CTL0 |= UCCKPH;

    while(UCB0STAT & UCBUSY)

    {

    }

    SLAVE_SELECT_HIGH;                                                   // Stop SPI Mode

}

 3rd)  In P2.1 interrput service routine

         else if(*irq_status == BIT6)

         {        // RX flag means that EOF has been recieved

                   // and the number of unread bytes is in FIFOstatus regiter   

                   if(rx_error_flag == 0x02)

                   {

                            i_reg = 0x02;

                            return;

                   }

 

                   *irq_status = FIFO_STATUS;

                   Trf796xReadSingle(irq_status, 1);                     // determine the number of bytes left in FIFO

                   *irq_status = (0x0F &*irq_status) + 0x01;

                   buf[rxtx_state] = FIFO;                                // write the recieved bytes to the correct place of the buffer

                                                                                                                        

                                                                                                               

                   Trf796xReadCont(&buf[rxtx_state], *irq_status);

                   rxtx_state = rxtx_state +*irq_status;

                   *irq_status = TX_LENGTH_BYTE_2;                           // determine if there are broken bytes

                   Trf796xReadCont(irq_status, 1);

                   if((*irq_status & BIT0) == BIT0)

                   {

                            *irq_status = (*irq_status >> 1) & 0x07;         // mask the first 5 bits-------I know

                            *irq_status = 8 -*irq_status;  // what's the meaning? 

                            buf[rxtx_state - 1] &= 0xFF << *irq_status;  // what's the meaning? 

                   }  

  // I   can't understang why we need to check  value in  register  TX_LENGTH_BYTE_2  ,espasially in this RX service  branch.  

//In my brain, this register works only in TX process , for example when send REQA  ,because this cmd is

a  short frame.                                           

 

#if DBG

                   UartPutChar('E');

#endif

                   Trf796xReset();                                              // reset the FIFO after last byte has been read out

 

                   i_reg = 0xFF;                                          // signal to the recieve funnction that this are the last bytes

         }       

         else if(*irq_status == 0x60)

         {                                                                                   // RX active and 9 bytes allready in FIFO

                   i_reg = 0x01;

                   buf[rxtx_state] = FIFO;

                   Trf796xReadCont(&buf[rxtx_state], 9);  // read 9 bytes from FIFO

                   rxtx_state = rxtx_state + 9;

#if DBG

                   UartPutChar('F');

#endif

                   if(IRQ_PORT & IRQ_PIN)                   // if IRQ pin high

                   {

                            Trf796xReadIrqStatus(irq_status);

                            IRQ_CLR;

                            if(*irq_status == 0x40)                                                            // end of recieve

                            {       

                                     *irq_status = FIFO_STATUS;

                                     Trf796xReadSingle(irq_status, 1);                       // determine the number of bytes left in FIFO

                                     *irq_status = 0x0F & (*irq_status + 0x01);

                                     buf[rxtx_state] = FIFO;                         // write the recieved bytes to the correct place of the buffer

                                     Trf796xReadCont(&buf[rxtx_state], *irq_status);

                                     rxtx_state = rxtx_state +*irq_status;

                                     *irq_status = TX_LENGTH_BYTE_2;                              // determine if there are broken bytes

                                     Trf796xReadSingle(irq_status, 1);                                        // determine the number of bits

                                     if((*irq_status & BIT0) == BIT0)

                                     {

                                               *irq_status = (*irq_status >> 1) & 0x07;         // mask the first 5 bits

                                               *irq_status = 8 -*irq_status;

                                               buf[rxtx_state - 1] &= 0xFF << *irq_status;

                                     }            

                                           // the same doubt....

 

#if DBG

                                     UartPutChar('E');

#endif

                                     i_reg = 0xFF;                       // signal to the recieve funnction that this are the last bytes

                                     Trf796xReset();                  // reset the FIFO after last byte has been read out

                            }

                            else if(*irq_status == 0x50)     // end of recieve and error

                            {

                                     i_reg = 0x02;

#if DBG

                                     UartPutChar('x');

#endif

                            }

                   }

                   else

                   {

                            Trf796xReadIrqStatus(irq_status);

                            if(irq_status[0] == 0x00)

                            {       

                                     i_reg = 0xFF;

                            }

                   }

         }

Thanks .

B&R

SeaFesse.

PS: How to edit  code in the  post . I find it's not a easy work to alignment.  ^_^

 

  • I use  ReadMultiplteBlock cmd to read 8 bytes from 2 blocks (Ti Tag-it), it always failed. However , if  I  read 3 or 4 or 5 blocks, It's OK . 

    Looked through some screenshots of the logic analyzer, I found  IRQ signal is lost when all data returned.( 1byte flag + 8 bytes data----exactly equal to low FIFO warning threshold). so...Mcu can't get the interrupt signal and stucked in waitting state.

    I looked up on SLOA155. It looks like I meet the same problem with list 3. So, in my code I start a timer to check  register 0x0C.  The value of this register is always 0x00, not 0x40 which value I want to get . Did I miss sth ?

    Besides, I strongly want to know why another 16 CLKs is needed in fuction SpiReadCont. It makes no sense!

    It's normal to have a bug in IC ,however, I want to know  how to fix or avoid it. It also benifit for all potential users.

  • Here I paste the screenshots.

  • Hey SeaFesse,

    I've attached a powerpoint explaining where the extra 16 clocks were coming from, and how to fix this.  

    Please let me know (or start a new thread) if you have any other questions.

    Thanks,

    JD

    TRF7960 Extra Clocks on RX.pptx
  • Hi John ,

      Thanks a lots for your PPT.  It fixed my second issue.

    The first question I have find the instrcution in the lastest version datasheet of TRF7963A.

     Besides,  I want to know  how to explain the 3rd quesiton.

    Thanks in advance.

  • Hi John,

    I looked into the PPT carefully. Some doubt still puzzled me. 

    The following code is copy from TRF7960 example code. 

    It seems like if u want cont read a register except 0x0C , U need extra 16 Clks.

    Besides,The approach providered in the PPT is just give an alternative way to replace the “patch” code, but it does not explain why we need the patch ?

     

    //Note: When the MCU was not resetting the SPI module it was causing the MOSI line to stay high till the next clock cycle.------Copy from the PPT.

    -------If this is the reason that a High MOSI line will lead a misread register , I can’t get how does the patch code works.

    //===============================================================
    // NAME: void SpiReadCont (u08_t *pbuf, u08_t length)
    //
    // BRIEF: Is used in SPI mode to read a specified number of
    // reader chip registers from a specified address upwards.
    //
    // INPUTS:
    //	Parameters:
    //		u08_t		*pbuf		address of first register
    //		u08_t		length		number of registers
    //
    // OUTPUTS:
    //
    // PROCESS:	[1] read registers
    //			[2] write contents to *pbuf
    //
    // CHANGE:
    // DATE  		WHO	DETAIL
    // 24Nov2010	RP	Original Code
    // 07Dec2010	RP	integrated wait while busy loops
    //===============================================================
    
    void
    SpiReadCont(u08_t *pbuf, u08_t length)
    {	
    	u08_t	j = 0;
    	
    	SLAVE_SELECT_LOW; 							//Start SPI Mode
    	// Address/Command Word Bit Distribution
    	*pbuf = (0x60 | *pbuf); 					// address, read, continuous
    	*pbuf = (0x7f &*pbuf);						// register address
    	while (!(IFG2 & UCB0TXIFG))					// USCI_B0 TX buffer ready?
    	{
    	}
    	UCB0TXBUF = *pbuf;  						// Previous data to TX, RX
    	
    	while(UCB0STAT & UCBUSY)
    	{
    	}
    	
    	temp = UCB0RXBUF;
    	UCB0CTL0 &= ~UCCKPH;
    	
    	if(*pbuf != 0x6C)						
    	{	
    		if (length != 0x1F)
    		{	
    			for (j=0;j<2;j++)
    			{	
    				while (!(IFG2 & UCB0TXIFG))		// USCI_B0 TX buffer ready?
    				{
    				}
    				UCB0TXBUF = 0x00; 				// Receive initiated by a dummy TX write
    						
    				while(UCB0STAT & UCBUSY)
    				{
    				}
    				_NOP();
    				_NOP();
    				temp = UCB0RXBUF;
    			}
    		}
    	}
    	while(length > 0)
    	{	
    		while (!(IFG2 & UCB0TXIFG))
    		{
    		}
    		UCB0TXBUF = 0x00; 					// Receive initiated by a dummy TX write
    					
    		while(UCB0STAT & UCBUSY)
    		{
    		}
    		_NOP();
    		_NOP();
    		*pbuf = UCB0RXBUF;
    		pbuf++;
    		length--;
    	}
    	UCB0CTL0 |= UCCKPH;
    	while(UCB0STAT & UCBUSY)
    	{
    	}
    	SLAVE_SELECT_HIGH; 						// Stop SPI Mode
    
    }







    2) I wrote a software spi code , do i need to add the patch  in SpiReadCont() ?
    u08_t  SpiTransceiveByte_MODE_2(u08_t Data)
    {
        u08_t i;
        volatile u08_t MISO_buf=0;
        
        for(i=0;i<8;i++)
        {
            SPI_SCK_L();
            if( Data & 0x80) 
                SPI_MOSI_H();
            else
                SPI_MOSI_L();
            
            Data = Data<<1;
            SPI_DELAY_HALF_BIT();
            SPI_SCK_H();
            SPI_DELAY_HALF_BIT();
            SPI_SCK_L(); 
            MISO_buf = MISO_buf<<1;
            if( GET_MISO() )
                MISO_buf |= 0x01 ; 
            
        } 
        
        SPI_DELAY_HALF_BIT();
        SPI_DELAY_HALF_BIT();
        SPI_DELAY_HALF_BIT();
        SPI_DELAY_HALF_BIT();
        SPI_DELAY_HALF_BIT();
        SPI_DELAY_HALF_BIT();
        return MISO_buf;
    }
    
    
    
    void SpiReadCont(u08_t* pbuf, u08_t length)
    {	
     
        CSN_L; 							
        *pbuf |= 0x60; 	// address, read, continuous
        *pbuf &= 0x7f;	// register address
        
        SpiTransceiveByte_MODE_2(*pbuf);
        
    #ifdef  PATCH_FOR_TRF796X_12FIFO
        if(*pbuf != 0x6C)		
        {	
            if (length != 0x1F)
            {	
                TEMP_Buffer = SpiTransceiveByte_MODE_2(0x00);
                TEMP_Buffer = SpiTransceiveByte_MODE_2(0x00);
            }
        }
    #endif
        
        while(length > 0)
        {	
            *pbuf++ = SpiTransceiveByte_MODE_2(0x00);
            length--;
        }
        
        
        CSN_H; 
        
    }