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.

CC2541 unexpected error by setting of the send-frequency

Other Parts Discussed in Thread: CC2541

Hi!
I am using CC2541 for my own application. Senging of the paket should work using "CMD_TX_FIFO_TEST" command, Receiver using "CMD_RX" command.

For data transmission im using the folowing functions:

uint8 freq = 33;

RFSetDirectFrequency(&freq );

SEND_LLE_CMD(CMD_TX_FIFO_TEST);

(Functiondefinitions:)
#define SEND_LLE_CMD(cmd)      st(while(RFST != 0); RFST = (cmd); while(RFST != 0);)

void RFSetDirectFrequency(uint8* frequency) { // frequency in range 1..83
    RFDisableRadio(FORCE);     // Stop the radio
    FREQCTRL = (*frequency) + 21;
    RF_RadioChannel = (*frequency);
    RFEnableRadio();                  // Activate Radio
    return;
}//RFSetDirectFrequency

For receiving of the data im using folowing instructions:

uint8 freq = 13;

RFSetFrequency(&freq );
RF_ReceiveStartedHandler (void)

void RFSetFrequency(uint8* frequency) {
    RFDisableRadio(FORCE);
    PRF_CHAN = (*frequency) + 21;
    RF_RadioChannel = (*frequency);
    RFEnableRadio();           // Activate Radio
    return;
}//RFSetFrequency

void RF_ReceiveStartedHandler (void)
{  
    RFIRQM1 |= RFIRQF1_RXOK; // Activate "Packet Received Correctly" Interrupt
    S1CON    = 0;                            // Clear RF CPU Finterrupt flags
    RFIRQF1  = 0x00;                     // Clear all RF core interrupts Flags
    RFIRQF0  = 0x00;                     // Clear all RF core interrupts Flags
    IEN2    |= IEN2_RFIE;               // activate Radio Interrupts
    SEND_LLE_CMD(CMD_RX);   // Start Receive Operation
    while (!(LLESTAT& 0x03));
    MCUTimer2CompareCC0(RF_ReceiveTimeoutHandler, GetGlobalTimeLow()+RF_MaxReceiveDuration+200);  
    return;
} // RF_ReceiveStartedHandle

My problem is following:

After the initialisation i can send data without any problems - the frequency passt.
But if Receiver was activated at least once, the next transmission will not met the frequency!
(It will be one or two MHz smaller or greater as it was set).
I can not find what I am doing wrong! It would be great if someone mentions where
can an error be.
Thanks in advance!

In Following I give an essential part of my code for Timer and RF :
Timer:

r


#Finclude "MCUTimer2.h"


__monitor uint8 GetLock(void);
__monitor void ReleaseLock(void);
MCUTimer2_Com_CBF MCUTimer2_Com0_CBF;
MCUTimer2_Com_CBF MCUTimer2_Com1_CBF;

uint8 Lock;
uint16 currenteventmoment = 0;
uint16 SettetTime = 0;

void MCUTimer2_Init(void)
{
//********************************************************************//   
  EA = 0;
  T2CTRL = STOP;      //Stop Timer2
  T2EVTCFG = 0xFF;// no event
  T2MSEL = T2OVF;
  T2MOVF0 = 0x00;     //Reset OverflowCount 0
  T2MOVF1 = 0x00;     //Reset OverflowCount 1
  T2MOVF2 = 0x00;     //Reset OverflowCount 2
//********************************************************************//
  T2MSEL = T2_PER;      //Set MUX to Overflov Count and Timer Period (timer period)
  T2M0 = 0x20;     //Set Timer Period to 32 => Overflow after 1us
  T2M1 = 0x00;     //Set Timer Period to 32 => Overflow after 1us
//********************************************************************//  
  T2MSEL = T2TIM;   //Set MUX to Overflov Count and Timer Value (timer count value)
  T2M0   = 0x00;   //Reset Timer Value
  T2M1   = 0x00;   //Reset Timer Value
//********************************************************************//
  T2MSEL = T2OVF_PER;      //Set MUX to Overflov Count and Timer Period (timer period)
  T2MOVF0 = 0xFF;     //Reset OverflowCount 0
  T2MOVF1 = 0xFF;     //Reset OverflowCount 1
  T2MOVF2 = 0x00;     //Reset OverflowCount 2
  T2IRQM = 0x00;
  T2IRQM = 0x00;   //Disable all Timer2 Interrupt Sources
  T2IE = 1;
  T2IF = 0;
  T2EVTCFG =  NO_TIMER_EVENT;        // No timer 2 events sent to LLE  
  EA = 1;           //Enable Global Interrupts  
  return;
}//MCUTimer2_Init

uint16 GetGlobalTimeLow(void)
{

  T2MSEL = T2OVF;       //Setze Multiplexer für T2MOVF0...T2MOVF2 auf OverflowCounter;
  return (T2MOVF0 + (((uint16)T2MOVF1)<<8));
}//GetGlobalTimeLow

void ResetTimer(void) {
  if (GetLock()) {
     //********************************************************************//   
      T2CTRL = STOP;      //Stop Timer2
      T2MSEL = T2OVF;
      T2MOVF0 = 0x00;     //Reset OverflowCount 0
      T2MOVF1 = 0x00;     //Reset OverflowCount 1
      T2MOVF2 = 0x00;     //Reset OverflowCount 2
    //********************************************************************//  
      T2MSEL = T2TIM;   //Set MUX to Overflov Count and Timer Value
      T2M0   = 0x00;   //Reset Timer Value
      T2M1   = 0x00;   //Reset Timer Value
    //********************************************************************//  
      T2IRQM = 0x00;   //Disable all Timer2 Interrupt Sources   
      T2IRQF = 0; // Clear All Timer2 Interrupt flags.
      T2IF   = 0;
      ReleaseLock();
    }
}//ResetTimer


void StartTimer(void) {
  if (GetLock()) {
    T2IRQM = 0x00;  //Disable all Timer2 Interrupt Sources
    IRCON &= ~0x04;   //Clear Timer2 Interrupt Flag
    T2CTRL = RUN;   //Start Timer2
    ReleaseLock();
  }
}//StartTimer

void MCUTimer2CompareCC0(MCUTimer2_Com_CBF com0_cbf, uint16 latch_time)
{
  //EA = 0;
  if (GetLock()) {
    //TimerReceiveTime     = latch_time;
    T2IF    = 0;                                    //Clear Timer2 Interrupt Flag
    T2IRQF &= TIMER2_OVF_COMPARE1F;                 //Clear Timer2 OverflowCompare1 IRQ Flag
    T2MSEL  = T2OVF_CMP1;                           //Set MUX to Overflov Compare Value1 and Timer Value
    T2MOVF0 = (uint8)(latch_time& 0xFF);            //Set OverflowCount 0
    T2MOVF1 = (uint8)((latch_time >> 8)& 0xFF);     //Set OverflowCount 1
    T2MOVF2 = 0x00;            
    T2IRQM |= TIMER2_OVF_COMPARE1M;         //Enable Timer2 OverflowCompare Interrupt 1
    T2IE    = 1;
    MCUTimer2_Com0_CBF = com0_cbf;
    ReleaseLock();
  }
}//MCUTimer2CompareCC0

void MCUTimer2CompareCC1(MCUTimer2_Com_CBF com1_cbf, uint16 latch_time)
{
  if (GetLock()) {
    T2IF    = 0;                             //Clear Timer2 Interrupt Flag
    T2IRQF  &= TIMER2_OVF_COMPARE2F;         //Clear Timer2 OverflowCompare1 IRQ Flag
    T2MSEL  = T2OVF_CMP2;                   //Set MUX to Overflov Compare Value2 and Timer Value
    T2MOVF0 = (uint8)(latch_time & 0xFF);            //Set OverflowCount 0
    T2MOVF1 = (uint8)((latch_time >> 8) & 0xFF);     //Set OverflowCount 1
    T2MOVF2 = 0x00;
    T2IRQM  |= TIMER2_OVF_COMPARE2M;         //Enable Timer2 OverflowCompare Interrupt 1
    T2IE    = 1;
    MCUTimer2_Com1_CBF = com1_cbf;
     
    ReleaseLock();
  }
}//MCUTimer2CompareCC1

//********************************************************************//  
void TimerClearCallBack(void) {
   MCUTimer2_Com1_CBF = NULL;
   MCUTimer2_Com0_CBF = NULL;
   T2IE   = 0;
   T2IRQM = 0x00;  //Disable all Timer2 Interrupt Sources
   IRCON &= ~0x04;   //Clear Timer2 Interrupt Flag
}//TimerClearCallBack


uint8 status = 0;
#pragma vector=T2_VECTOR
__interrupt void Timer2_isr(void) {
  if (GetLock()) {
    status = T2IRQF;
    T2IRQM  = 0x00;    // mask interrupts        
    T2IRQF  = 0x00;    // clear flags
    T2IF    = 0;
    if(status & TIMER2_OVF_COMPARE1F) {      // independent from counter overflow react ob the Overflow counter compare to start the first CALLBACK function
      ReleaseLock();
      if(MCUTimer2_Com0_CBF != NULL)MCUTimer2_Com0_CBF();                         /* NUR Wenn der Funktionzeiger kein leerer Zeiger ist*/
    }
    if(status & TIMER2_OVF_COMPARE2F)   { // If we have received second overflow start the second CALLBACK function
      ReleaseLock();
      if(MCUTimer2_Com1_CBF != NULL)MCUTimer2_Com1_CBF();                         /* NUR Wenn der Funktionzeiger kein leerer Zeiger ist*/
    }    
  }
  T2IRQF  = 0x00;    // clear IRQ CPU flags
  T2IF    = 0;      // clear CPU flags
}

 __monitor uint8 GetLock (void)
 {
     if (Lock == 0)                                                     /* ? Ist Lock Semaphore besetzt ?*/
     {
         Lock = 1;                                                      /* Semaphore ist frei -> Semaphore besetzen */
         return TRUE;
     }
     else                                                                        /* Semaphore ist besetzt  */
     {
         return FALSE;
     }
 } // RF_GetLock

 __monitor void ReleaseLock (void)
 {
     Lock = 0;              /* Semaphore freigeben */
 } // RF_ReleaseLock

RF:

#pragma vector=RFERR_VECTOR
__interrupt void RF_ErrorInterrupt(void)
{
    RFForceShutdown();
   if (RFERRF & TXUNDERF) {              
      SEND_LLE_CMD(CMD_TXFIFO_RESET);  // Reset TX FiFo
   }
   if (RFERRF & RXTXABO) {
      SEND_LLE_CMD(CMD_TXFIFO_RESET);  // Reset TX FiFo
      SEND_LLE_CMD(CMD_RXFIFO_RESET);  // Reset RX FiFo
   }
   if (RFERRF & RXOVERF) {
      SEND_LLE_CMD(CMD_RXFIFO_RESET);  // Reset RX FiFo
   }  
                          // Deactive Transmitter Imidiately
   RFERRF = 0x00;
}

#pragma vector=RF_VECTOR          // Transmission complete event do not implemented jet
__interrupt void RF_Interrupt(void) {
 
   if (RFIRQF1 & RFIRQF1_RXOK) {
      RF_ReceiveStructPtr->ReceiveTime = GetGlobalTimeLow();
      TimerClearCallBack();
      RFForceShutdown();
      RF_ReceivedPPDUHandler();
   }
}

void RFInit(){
   /* Clear radio memory.
   *  The RAM registers don't have a default value set after power on */
  

    memset((void*)RFCORE_RAM_PAGE, 0, RFCORE_RAM_PAGE_SZ);
   // Reset RXFIFO and TXFIFO.
   SEND_LLE_CMD(CMD_RXFIFO_RESET);
   SEND_LLE_CMD(CMD_TXFIFO_RESET);
   RFFCFG    = 0x33;               // Auto Commit TX FIFO and RX FIFO

   RFTXFTHRS = 0x10;               //TX FIFO Threshold at 16 Bytes
   RFRXFTHRS = 0x10;               //TX FIFO Threshold at 16 Bytes

   RFERRM   |= TXUNDERF;     // Underflow interrupt for transmitter
   //RFIRQM0   = 0x00;               // Do not react on transmisson errors; TRANSMITTER ONLY  
   // Set default output power: 0dBm.
   TXPOWER   = TXPOWER_0_DBM;
   //T2EVTCFG =  NO_TIMER_EVENT;        // No timer 2 events sent to LLE  
   return;
   }//RFInit

void RFConfig(uint8 modulationSheme, uint8 SyncLength, uint8 usedConfiguration){//, uint8 tx) {
   //Eigene Konfiguration
  // Change this parameters if needed!

   EA = 0;
   RFDisableInterrupt(0xFF);
   PRF.PKT_CONF.ADDR_LEN         = 0x00;//!!(usedConfiguration & PKT_CONF_ADDR);
   PRF.PKT_CONF.AGC_EN              = 0;
   PRF.PKT_CONF.START_TONE     = 0;
   // Task Config

   PRF.TASK_CONF.MODE                = 0x00;
   PRF.TASK_CONF.REPEAT             = 0;        // Repeat. // was 1
   PRF.TASK_CONF.START_CONF    = 0;        // Start immediately after command.
   PRF.TASK_CONF.STOP_CONF     = 0;        // Don't stop on timer 2 event 2.
   PRF.TASK_CONF.TX_ON_CC_CONF     = 1;
   PRF.TASK_CONF.REPEAT_CONF          = 0;
   PRF.FIFO_CONF.AUTOFLUSH_IGN       = 0;        // No Flush duplicate packets.
   PRF.FIFO_CONF.AUTOFLUSH_CRC      = 0;        // do not Flush packets with CRC error.
   PRF.FIFO_CONF.AUTOFLUSH_EMPTY = 0;        // do not Flush empty packets.
   PRF.FIFO_CONF.RX_STATUS_CONF     = 0;        // append status information in FIFO.
   PRF.FIFO_CONF.RX_ADDR_CONF        = 0;        // address byte in Rx FIFO.
   PRF.FIFO_CONF.TX_ADDR_CONF         = 0;        // Read address from PRF.ADDR_ENTRY[0].ADDRESS.
   PRF.CRC_LEN                     = 0;        // Number of CRC bytes, permitted values are 0..4
   PRF.CRC_INIT[0]                 = 0xFF;     // CRC init Byte 0
   PRF.CRC_INIT[1]                 = 0xFF;     // CRC init Byte 1
   PRF.CRC_INIT[2]                 = 0xFF;     // CRC init Byte 2
   PRF.CRC_INIT[3]                 = 0xFF;     // CRC init Byte 3

   PRF_CHAN                        = 0;     // Channel 21 = 2400 MHz
   PRF_RSSI_LIMIT               = 0x7F;     //0x00;
   PRF_RSSI_COUNT           = 0x0000;   // 2 bytes

   PRF_W_INIT                      = 0xFF;
   PRF_RETRANS_CNT        = 0x00;
   PRF_TX_DELAY                = 0x0000; // 2 bytes
   PRF_RETRANS_DELAY   = 0x0000; // 2 bytes
   PRF_SEARCH_TIME        = 0x0000; // 2 bytes
   PRF_RX_TX_TIME           = 0x0000; // 2 bytes
   PRF_TX_RX_TIME            = 0x0000; // 2 bytes
   PRF.ADDR_ENTRY[0].CONF.ENA0     = 1;
   PRF_N_TX                        = 0x00;
   PRF_LAST_RSSI              = 0x00;
   PRF_RADIO_CONF          = 0x00;
   PRF_ENDCAUSE              = 0x00;   

   TXCTRL                             = 0x19;     // TX Settings.
   TXFILTCFG                        = 0x03;     // Set Tx Filter bandwidth.
   IVCTRL                              = 0x1B;     // Analog Control.
   FRMCTRL0                        = 0x41| (!!(usedConfiguration & PKT_CONF_ADDR)); // Amplitude weight in frequency offset compensation (assuming MSB first).
   //MDMCTRL0                     = (modulationSheme) | (!!(usedConfiguration & PKT_CONF_PHASE_INV));   // Set Modulation and data rate.
   MDMCTRL0                       = modulationSheme;// | PKT_CONF_PHASE_INV;
   MDMCTRL1                       = 0x08;      // Correlation threshold.
   MDMCTRL2                       = 0xA3;      //Synch: MSB first, Preamble for Freq.-Offset estimation, Preamble is set to 0101 0101  4 Byte Preamble // Pre inv.to first SyncBit,

   // Set RSSI mode to peak detect after sync.
   MDMCTRL3                        = 0x63;      //no ErrorBits in Sync, Ramping of DAC, no Sniff, peak detect after sync.
   ADCTEST0                        = 0x10;      // was 0x66
   
   MDMTEST0                        = 0xAC;      //RSSI: two 21us Windows Mean, DC-Block 128 Samples, DC-Cancellation enabled
   MDMTEST1                        = 0x0A;      //DC-Delay = 5, IF = 1MHz, Baseband Freq = 0MHz
   // Set gain  (will set correct gain even for 2 MBPS).
   RFSetGain(HAL_RF_GAIN_HIGH);

   // Program sync word length and configure single sync word.    
   // Set Default Sync Word lengths and the sync word itself
   RFSetSyncWord(SyncLength, 0x00, 0x3E, 0x94, 0x59, 0x00, 0x3E, 0x94, 0x59);
   LLECTRL = 0x00;
   RFSetWhitening(0x00);
   RFSetWhiteningRegister (0x65);
   //Quadrature Skew Setting (see User Guide Table 23-24)
   setQuadratureSkew(0x16);
   FREQTUNE   = 0x0F;                     //no Freq. Tune   
   RFERRIE    = 1;
   EA = 1;
   return;
}//RFConfig

uint8 RFReceiveMsg (RFReceiveStructPtr rsp)
{
    //uint32 tmp1;
        if(RF_State == RF_IDLE_STATE)                               /* ? Idle ?*/
        {
            //tmp1 = rsp->ReceiveStartTime - GetGlobalTimeLow();
            //if((tmp1 > RECEIVER_STARTUP_TIME) && (tmp1 < 0xF000))               /* ? Reicht die Zeit zum Anschalten des Empfängers ?*/
            //{
               RF_PSDUPtr    = rsp->PSDU;                                /* Parameterübernahme in die lokalen Variablen */
               if((RF_RadioChannel == CONFIG_CHANNEL_1) || (RF_RadioChannel == CONFIG_CHANNEL_2))
               {
                  RXPacketLength = 11;    // 88 BITS  Config Telegram DSLOT (normal)
               }
               else
               {
                  RXPacketLength = 15;    // 120 Bits, 80 BitPayload + 24 Bits SyncWord + 2Bit UL group + 6 Bit Cell ID (Downlink Telegramm DSLOT Extended)
               }   
               RF_ExecTime             = rsp->ReceiveStartTime;

               RF_MaxReceiveDuration   = rsp->MaxReceiveDuration;
               RF_ReceiveStructPtr     = rsp;
              /* if (OK) {
                 asm("NOP");
               }*/
               PRF.ADDR_ENTRY[0].RXLENGTH = RXPacketLength;   
               RF_ReturnPtr->RF_ErrorType = RF_NO_ERROR;
               RF_State = RF_RX_PACKET_STATE;
               RF_ReturnPtr->RF_State = RF_RX_PACKET_STATE;
               MCUTimer2CompareCC1(RF_ReceiveStartedHandler, (RF_ExecTime - (uint16)RXPREPARETIME));
               return TRUE;
        }
        else                                                                    /* Radio ist nicht Idle -> Cmd nicht annehmen und State zurückgeben */
        {
            RF_ReturnPtr->RF_ErrorType = RF_FALSE_STATE;
            return FALSE;
        }
} // RFReceiveMsg

void RF_ReceiveStartedHandler (void)
{   
 
    RFIRQM1 |= RFIRQF1_RXOK; // Activate "Packet Received Correctly" Interrupt
    S1CON    = 0;
    RFIRQF1  = 0x00;         // Clear all RF core interrupts Flags
    RFIRQF0  = 0x00;         // Clear all RF core interrupts Flags
    IEN2    |= IEN2_RFIE;    // activate Radio Interrupts
    SEND_LLE_CMD(CMD_RX);             // Start Receive Operation
    while (!(LLESTAT& 0x03));

  MCUTimer2CompareCC0(RF_ReceiveTimeoutHandler, GetGlobalTimeLow()+RF_MaxReceiveDuration+200);  
  return;

} // RF_ReceiveStartedHandler

void RF_ReceiveTimeoutHandler(void)
{
    if(RF_State == RF_RX_PACKET_STATE)
    {
      RFForceShutdown();
      TimerClearCallBack();
      RF_ReceiveStructPtr->ReceivedPacketStatus = RF_RECEIVE_TIMEOUT;
      RF_State = RF_IDLE_STATE;
      RF_ReturnPtr->RF_State = RF_IDLE_STATE;
      RF_ReceiveStructPtr->ReceiveCBF();
    }                                                                           //Ein Packet wurde empfangen befor die Timeout erreicht wurde
}
void RFForceShutdown(void) {
    // Send Rx command
      // Disable RX interrupts
    RFIRQM1 &= ~RFIRQF1_RXOK;
    IEN2 &= ~IEN2_RFIE; // RFIE = 0
    S1CON    = 0;
    RFIRQF1  = 0x00; // Clear all RF core interrupts Flags
    RFIRQF0  = 0x00; // Clear all RF core interrupts Flags
    SEND_LLE_CMD(CMD_SHUTDOWN);
    return;
}//RFStartRx

  • Hello Dmytro,

    The CMD_TX_FIFO_TEST is originally meant for use in the lab for transmitting a specific bit pattern. You cannot end the transmission gracefully. Enter a payload in the TXFIFO and use TX_CMD instead.

    What do you mean by: "But if Receiver was activated at least once, the next transmission will not met the frequency!" ?

    Could you instead upload an IAR project with the code so that i can look at it. It is much easier that way. And also try to explain what you want the code to do in more detail.

  • Hello Dmytro,

    Just wanted to give an update with regards to the frequency programming. Read more details in the CC2541 Users Guide in chapter 25.5 (Frequency and Channel Programming). 

    For normal transmit and receive tasks, the carrier frequency is set by using the PRF_CHAN.FREQ register. But you used a TEST command for TX. Then the frequency must be programmed directly in hardware registers. In this case, the synthesizer frequency is set by programming the 7-bit frequency word located in FREQCTRL.FREQ[6:0] and the IF is set in the register MDMTEST1.TX_TONE. In Rx, the system may operate on a positive or negative IF when the data rate is 1 Mbps and lower; this is controlled with MDMTEST1.RX_IF. Because you used the CMD_RX standard command the IF will be set automatically for RX, but not for TX because you used a TX TEST command.

    When the symbol rate is 1 Mbps or lower and the LLE programs the frequency, it uses a ±1 MHz IF on Tx. For both Rx and Tx, a negative IF is used when PRF_CHAN.FREQ < 62, and a positive IF is used when PRF_CHAN.FREQ ≥ 62. 

  • Hello Eirik,

     in case of receive-operations I am using PRF_CHAN.FREQ for frequency setup. For transmisson I use FREQCTRL register. The MDMTEST1.TX_TONE is set to "A = 10 = 0MHz". Observed frequency error is always +/- 1 or 2 MHz (Real Spektum Analyser used as observer) but only after one succesful RX command.


    I cannot use standart Transmit command because it sends the length of the paket. Used protokoll (WSAN) will fail in this case.

    I will create a smal project with the same Behavioral and post it tomorrow. (The project I working with, is a sensor. It is too large and the does not work without WSAN base station)

    I hope you can help me with this problem.
    Thanks in advance
    D.Krush

  • Hello Eric,

    As You asked I'm sending a small example project. It has the same behavioral as the big one. I have not changed anything only the pereferrie interface and MAC Layer has been deleted.


    To see an unexpected behavioral, You have to send a packet with 11 byte payload on the frequency 2401 or 2483 using an another transmitter.
    Modulation should be set to 1 Mbit, 160 KHz
    Syncword is 3 bytes long:
    SW0 = 0x00;
    SW1 = 0x3E;
    SW2 = 0x94;
    SW3 = 0x59;


    Preabmle is 4 bytes long. Each preamble byte is 0101 0101

    Payload is irrelevant, CRC error will not be observed.

    Pin P2_0 -> GPIO6 is used as trigger for Real Time Spectrum Analyser.

    The first sendng operation works correctly, after the receiver have received something, a frequency offset can be observed.

    8400.CC2541_EXEMPLE_CODE_FOR_TI.zip

    P.S. My IAR version is  8.10.3 (8.10.3.40338)
    Thanks in advance
    D.Krush

  • Hello Dmytro, 

    I will have a look at it next week.

  • Hello Dmytro,

    I see in the code that the RX operation will automatically change the MDMTEST1.TX_TONE to either 0x05 or 0x0F to set a IF of -1MHz or +1MHz. This is as expected, but to make sure to transmit with 0MHz IF you will have to set the MDMTEST1.TX_TONE back to 0x0A manually after each RX operation.


    Read more about the details in "23.5   Frequency and Channel Programming" of the user guide:

    When the symbol rate is 1 Mbps or lower and the LLE programs the frequency, it uses a ±1 MHz IF on Tx. For both Rx and Tx, a negative IF is used when PRF_CHAN.FREQ < 62 and a positive IF is used when PRF_CHAN.FREQ ≥ 62


  • Thanks, it works!

     if it is possible I wont to ask some another quastion. I have changed code as You purposed. Now TX_FIFO_TEST command do not needed any more.
    And I had a wish to use timer2 events for send and receive operations.

    Receive Operation works propertly.

    Send Operation do not work propertly and I cannot find what im doing wrong:

    If I start a send operation it does not end with TASKDONE and PRF_ENDCAUSE == 0. It ends with TXDONE and PRF_ENDCAUSE == 15.(I can see the Packet on RSA, but cannot say anything about right timing)

    Hope You can help me...

    Relevant INIT Setting

    RFIRQM1    = (RFIRQF1_TXDONE | RFIRQF1_TASKDONE | RFIRQF1_RXOK); // Activate Interrupts
    PRF.PKT_CONF.ADDR_LEN           = 0x00;
    PRF.PKT_CONF.AGC_EN               = 0;
    PRF.PKT_CONF.START_TONE      = 0;
       // Task Config
    PRF.TASK_CONF.MODE                 = 0x00;
    PRF.TASK_CONF.REPEAT              = 0;        // Repeat.
    PRF.TASK_CONF.START_CONF     = 1;        // Start on timer 2 event 1.
    PRF.TASK_CONF.STOP_CONF      = 1;        //  stop on timer 2 event 2.
    PRF.TASK_CONF.TX_ON_CC_CONF     = 1;
    PRF.TASK_CONF.REPEAT_CONF  = 0;
    PRF.FIFO_CONF.AUTOFLUSH_IGN = 0;        // No Flush duplicate packets.
    PRF.FIFO_CONF.AUTOFLUSH_CRC= 0;        // do not Flush packets with CRC error.
    PRF.FIFO_CONF.AUTOFLUSH_EMPTY= 0;        // do not Flush empty packets.
    PRF.FIFO_CONF.RX_STATUS_CONF   = 0;        // do not append status information in FIFO.
    PRF.FIFO_CONF.RX_ADDR_CONF       = 0;        // do not address byte in Rx FIFO.
    PRF.FIFO_CONF.TX_ADDR_CONF       = 0;        // Read address from PRF.ADDR_ENTRY[0].ADDRESS.
    PRF.CRC_LEN                     = 0;        // Number of CRC bytes, permitted values are 0..4
    PRF.CRC_INIT[0]                 = 0xFF;     // CRC init Byte 0
    PRF.CRC_INIT[1]                 = 0xFF;     // CRC init Byte 1
    PRF.CRC_INIT[2]                 = 0xFF;     // CRC init Byte 2
    PRF.CRC_INIT[3]                 = 0xFF;     // CRC init Byte 3

    RFFCFG    = 0x33;               // Auto Commit + auto dealocate TX FIFO and RX FIFO
    RFTXFTHRS = 0x7F;           //TX FIFO Threshold set to max
    RFRXFTHRS = 0x7F;           //RX FIFO Threshold set to max

    Timer setting

    T2EVTCFG =  0x54;     // Timer2 Stop Event overflow compare 2; Timer2 Start Event overflow compare 1 (PAGE 207 User Guide)

    Receive Function

    uint8 RFReceiveMsg (uint8 RXPacketLength, uint16 ExecTime)
    {
                   PRF.ADDR_ENTRY[0].RXLENGTH = RXPacketLength;  
                   PRF.TASK_CONF.STOP_CONF    = 1;              // If packet was not present on a channel in a given time >> call CMD_STOP
                   SEND_LLE_CMD(CMD_RX);
                   MCUTimer2CompareCC1( (uint16)(ExecTime - RXPREPARETIME));   // Set timer compare event 1 (START EVENT)
                   MCUTimer2CompareCC2( ExecTime + SLOT_DURATION);// Set timer compare event 2 (STOP EVENT -- Timeout)
                   return TRUE;

    } // RFReceiveMsg

    Send Funktion


    uint8 RFSendMsg (uint8 *PSDUPtr, uint8 PSDULength, uint16 ExecTime) {
        if((PSDULength > PHYLAYER_TX_PSDU_MIN_LENGTH)
                    && (PSDULength < PHYLAYER_TX_PSDU_MAX_LENGTH))  {       
                    RF_CalcSendCRC = crc32_1byte(PSDUPtr, RF_PSDULength);       // Compute Software CRC
                   

                    RFD = PHYLAYER_TX_PSDU_MAX_LENGTH;                                // write the length of the packet to be send, PSDULength=11 + 4(CRC Length) = 15
                    
                    if(LONG_UPLINK_SYNC)                                                                   // Load CRC values
                    {
                       RFD = (((uint8*)(&RF_CalcSendCRC))[3]);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[2]);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[1]);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[0]);

                      while(PSDULength--) // Optimisation
                      {
                         RFD = (*(PSDUPtr++));                          // Load payload to be send
                      }                                                                 // Guard Byte needed, transmitter generate an Underflow interrupt 8 mu earlier as all data were send. (1 Byte == 8 mu)
                    }
                      else
                      {
                       RFD = 0xB0 + (((uint8*)(&RF_CalcSendCRC))[3]>>4);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[3]<<4) + (((uint8*)(&RF_CalcSendCRC))[2]>>4);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[2]<<4) + (((uint8*)(&RF_CalcSendCRC))[1]>>4);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[1]<<4) + (((uint8*)(&RF_CalcSendCRC))[0]>>4);
                       RFD = (((uint8*)(&RF_CalcSendCRC))[0]<<4) + (*PSDUPtr >> 4);

                       while(--PSDULength) // Optimisation
                       {
                         RFD = ((*(PSDUPtr)) << 4) + ((*(PSDUPtr + 1)) >> 4);
                         PSDUPtr++;
                       }   
                      }
                                  /* Variant 1 : use timer 2 event for dummy stop*/
                     // PRF.TASK_CONF.STOP_CONF = 1;        // Stop on timer 2 event 2
                     // MCUTimer2CompareCC2(NULL, (uint16)(ExecTime + DSLOT_EXT_DURATION));  // Set transmiter stop on Transmitter Event
                                 /* Variant 2 : do not use timer 2 stop event*/
                      PRF.TASK_CONF.STOP_CONF = 0;        // Don't stop on timer 2 event 2
                      MCUTimer2CompareCC1(NULL, (uint16)(ExecTime - TXPREPARETIME));  // Set Timer-Interrupt on Transmitter Event           
                      SEND_LLE_CMD(CMD_TX);
                }
              
    } // RFSendMsg

    // Interrupt Handler

    #pragma vector=RF_VECTOR
    __interrupt void RF_Interrupt(void) {
      ENDCAUSE      = PRF_ENDCAUSE;
      INT_FLAGS     = RFIRQF1;
      RFMaskFlags();                                                                                // Clears RF flags (RFIRQF1, RFIRQF0)
      if (INT_FLAGS & RFIRQF1_TASKDONE) {                                     // Task ends successfully
        if (INT_FLAGS & RFIRQF1_RXOK) {                                            // Receiver task completed successfully
            ReceiveTime = (GetGlobalTimeLow()-184);                              // By receiving of the data we obtain the end of the packet only, but not the start we need.    
            RF_ReceivedPPDUHandler();                                                   // Evaluate packet
            return;                                                                                        // break execution
        }
      }


      if (INT_FLAGS & RFIRQF1_TXDONE) {                                         // Transmitter task completed. successfully? Do not know!
          RF_SendStructPtr->SendCBF();                                                 // Call Received Handler
          return;                                                                                          // break execution
     }   


     if ((ENDCAUSE & TASK_RXTIMEOUT) || (ENDCAUSE & TASK_ABORT) || (ENDCAUSE & TASK_STOP)) {    // timeout observed
        RF_ReceiveStructPtr->ReceivedPacketStatus = RF_RECEIVE_TIMEOUT;     // Set the software flag
        RF_ReceiveStructPtr->ReceiveCBF();                                                               // CallBack with time out flag active
      }
     }
      

  • Hello Dmytro, 

    Glad it worked :). Try to set the following to 0 instead of 1 for the transmitter part:

    PRF.TASK_CONF.STOP_CONF      = 0;        //  No stop based on timer 2