The TI E2E™ design support forums will undergo maintenance from July 11 to July 13. If you need design support during this time, open a new support request with our customer support center.

LAUNCHXL-CC1312R1: CC1312R's sub-1ghz communication and I2S inquiries

Part Number: LAUNCHXL-CC1312R1

Tool/software:

Hi friends I have a question about a project using sub-1ghz and I2S in CC1312R1.

SDK is using simplelink_cc13x_cc26x_sdk_7_41_00_17, and I constructed the project based on rfEchoRx and rfEchoTx among samples.

The symptom is that Tx only sends Send 1 time with RF_cmdRun when sending data read from I2S to Rx and then the receive to Rx is normal but not echoing. By the way,

Tx, Rx echo works when I2S_startClocks(i2sHandle) of I2S; is removed and performed. Please let me know the cause of this symptom and how to resolve it.

CMD_PROP_RX, CMD_PROP_TX settings are as follows.

------. Tx

/* Modify CMD_PROP_TX and CMD_PROP_RX commands for application needs */
RF_cmdPropTx_2gfsk1mbps868_0.pktLen = PAYLOAD_LENGTH;
RF_cmdPropTx_2gfsk1mbps868_0.pPkt = txPacket;
RF_cmdPropTx_2gfsk1mbps868_0.startTrigger.triggerType = TRIG_NOW; //TRIG_NOW; //TRIG_ABSTIME;
RF_cmdPropTx_2gfsk1mbps868_0.startTrigger.pastTrig = 1;
RF_cmdPropTx_2gfsk1mbps868_0.startTime = 0;
RF_cmdPropTx_2gfsk1mbps868_0.pNextOp = (rfc_radioOp_t *)&RF_cmdPropRx_2gfsk1mbps868_0;
/* Only run the RX command if TX is successful */
RF_cmdPropTx_2gfsk1mbps868_0.condition.rule = COND_ALWAYS; //COND_ALWAYS; //COND_STOP_ON_FALSE;

/* Set the Data Entity queue for received data */
RF_cmdPropRx_2gfsk1mbps868_0.pQueue = &dataQueue;
/* Discard ignored packets from Rx queue */
RF_cmdPropRx_2gfsk1mbps868_0.rxConf.bAutoFlushIgnored = 1;
/* Discard packets with CRC error from Rx queue */
RF_cmdPropRx_2gfsk1mbps868_0.rxConf.bAutoFlushCrcErr = 1;
/* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
RF_cmdPropRx_2gfsk1mbps868_0.maxPktLen = PAYLOAD_LENGTH;
RF_cmdPropRx_2gfsk1mbps868_0.pktConf.bRepeatOk = 0;
RF_cmdPropRx_2gfsk1mbps868_0.pktConf.bRepeatNok = 1;
RF_cmdPropRx_2gfsk1mbps868_0.pOutput = (uint8_t *)&rxStatistics;
/* Receive operation will end RX_TIMEOUT ms after command starts */
RF_cmdPropRx_2gfsk1mbps868_0.endTrigger.triggerType = TRIG_NOW; //TRIG_NOW; //TRIG_REL_PREVEND;
RF_cmdPropRx_2gfsk1mbps868_0.condition.rule = COND_ALWAYS;
RF_cmdPropRx_2gfsk1mbps868_0.endTime = RX_TIMEOUT;

------. Rx

/* Modify CMD_PROP_TX and CMD_PROP_RX commands for application needs */
/* Set the Data Entity queue for received data */
RF_cmdPropRx_2gfsk1mbps868_0.pQueue = &dataQueue;
/* Discard ignored packets from Rx queue */
RF_cmdPropRx_2gfsk1mbps868_0.rxConf.bAutoFlushIgnored = 1;
/* Discard packets with CRC error from Rx queue */
RF_cmdPropRx_2gfsk1mbps868_0.rxConf.bAutoFlushCrcErr = 1;
/* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
RF_cmdPropRx_2gfsk1mbps868_0.maxPktLen = PAYLOAD_LENGTH; //PAYLOAD_LENGTH+NUM_APPENDED_BYTES+1;
/* End RX operation when a packet is received correctly and move on to the
* next command in the chain */
RF_cmdPropRx_2gfsk1mbps868_0.pktConf.bRepeatOk = 0;
RF_cmdPropRx_2gfsk1mbps868_0.pktConf.bRepeatNok = 0;
RF_cmdPropRx_2gfsk1mbps868_0.startTrigger.triggerType = TRIG_NOW;
RF_cmdPropRx_2gfsk1mbps868_0.pNextOp = (rfc_radioOp_t *)&RF_cmdPropTx_2gfsk1mbps868_0;
/* Only run the TX command if RX is successful */
RF_cmdPropRx_2gfsk1mbps868_0.condition.rule = COND_STOP_ON_FALSE; //COND_ALWAYS; //COND_STOP_ON_FALSE;
RF_cmdPropRx_2gfsk1mbps868_0.pOutput = (uint8_t *)&rxStatistics;

RF_cmdPropTx_2gfsk1mbps868_0.pktLen = PAYLOAD_LENGTH; //PAYLOAD_LENGTH+NUM_APPENDED_BYTES+1;
RF_cmdPropTx_2gfsk1mbps868_0.pPkt = txPacket;
RF_cmdPropTx_2gfsk1mbps868_0.startTrigger.triggerType = TRIG_NOW;//TRIG_REL_PREVEND;
RF_cmdPropTx_2gfsk1mbps868_0.startTime = 0;

  • Hi Peter,

    How do you fill the txPacket variable? Is it being filled directly by the I2S driver? Where do you copy the I2S data prior to sending?

    Regards,

    Arthur

  • I2S data is being copied to the queue, and before sending, we get the data from the queue, put it in the txPacket variable, and send it.

    The code to import and transfer data from the queue is as follows:

    if (!Queue_empty(queueHandle)) {
    int16_t pcm_buffer[64] = {0};
    AUDIOBUFFER *audioBuffe = (AUDIOBUFFER *)Queue_dequeue(queueHandle);
    uint32_t sendSize = 0;
    int32_t pcmLData = 0x00000000;

    sendAudioDataField.rfAddress = 0xABCD;
    sendAudioDataField.command = commandStatus;
    sendAudioDataField.deviceId = device_id;
    sendAudioDataField.curtime = RF_getCurrentTime();
    for(int i = 0, m = 0; i<PCMSIZE; i++){
    int16_t pcmLData = 0x0000;
    pcmLData = (audioBuffe->i2sAudioData.data[m+1]);
    pcmLData |= (audioBuffe->i2sAudioData.data[m+2])<<8;
    pcm_buffer[i] = pcmLData;
    m = m+6;
    }

    ima_adpcm_encode_block(pcm_buffer, sendAudioDataField.encoded, &imaAdpcmState);

    memcpy(txPacket, &sendAudioDataField, sendAudioDataSize);
    currentCRC = CRC16_CCITT(txPacket, sendAudioDataSize);
    txPacket[44] = (currentCRC >>8 ) & 0xFF;
    txPacket[45] = (currentCRC ) & 0xFF;
    txPacket[46] = '\0';

    //printf("currentCRC: 0x%x\n", currentCRC);
    }

    RF_EventMask terminationReason = RF_EventCmdAborted | RF_EventCmdPreempted;
    while(( terminationReason & RF_EventCmdAborted ) && ( terminationReason & RF_EventCmdPreempted ))
    {
    // Re-run if command was aborted due to SW TCXO compensation
    //terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx_2gfsk1mbps868_0, RF_PriorityNormal, NULL, 0);
    terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx_2gfsk1mbps868_0, RF_PriorityNormal, echoCallback, (RF_EventCmdDone | RF_EventRxEntryDone | RF_EventLastCmdDone));
    }

  • Hi Peter, 

    I have several comments:

    • The TI-RTOS queue is not marked as thread safe by default. You have to follow the following code snippet to render it safe: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_8_30_01_01/docs/tirtos7/doxygen/m4/html/Queue_8h.html#a96a54f733f0e473ad937fa458b362277
    • I would recommend using the MessageQueue.h API instead: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_8_30_01_01/docs/drivers/doxygen/html/_message_queue_p_8h.html#a7158ccab7f730769818300c5653790a9
      H
      ere is an example where send I2S transaction buffers to a MessageQueue:

          /* Treatment */
          while (1)
          {
              GPIO_write(CONFIG_GPIO_DBG_1, 1);
      
              /* Wait for transaction ready for treatment */
              retc = sem_wait(&semDataReady);
              if (retc == -1)
              {
                  while (1) {}
              }
      
              I2S_Transaction *transactionToSend = (I2S_Transaction *)List_head(&data2transfer);
      
              if (transactionToSend != NULL)
              {
                  started = 1;
      
                  if (MessageQueueP_getFreeCount(SendMsgQueueHandle) > 0)
                  {
                      /* We can wait until we get the next sample */
                      mq_status = MessageQueueP_post(SendMsgQueueHandle, (void *)transactionToSend->bufPtr, ClockP_getSystemTickPeriod() * 2);
      
                  }
      
                  List_remove(&data2transfer, (List_Elem *)transactionToSend);
                  List_put(&i2sReadList, (List_Elem *)transactionToSend);
              }
              GPIO_write(CONFIG_GPIO_DBG_1, 0);
          }


      semDataReady is posted in the I2S readCallbackFxn:


      static void readCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr)
      {
          /*
           * The content of this callback is executed every time a read-transaction
           * is started
           */
          GPIO_write(CONFIG_GPIO_DBG_0, 1);
          /* We must consider the previous transaction (the current one is not over) */
          I2S_Transaction *transactionFinished = (I2S_Transaction *)List_prev(&transactionPtr->queueElement);
      
          if (transactionFinished != NULL)
          {
              /* The finished transaction contains data that must be treated */
              List_remove(&i2sReadList, (List_Elem *)transactionFinished);
              List_put(&data2transfer, (List_Elem *)transactionFinished);
      
              /* Start the treatment of the data */
              sem_post(&semDataReady);
      
          }
      
          GPIO_write(CONFIG_GPIO_DBG_0, 0);
      }
    • Lastly, do you see an exception when running I2S_startClocks?

    Regards,

    Arthur

  • I reviewed the contents you sent me.

    MessageQueueP-related codes cannot be used in the project. API for MessageQueue cannot be used for the project. file ti/osal/messagequeue.h was not found.

    And even if this content is applied, data cannot be written/read through Sub-1GHz even when queues are not used.

    Once again, please let me know how I can find out what caused this.

  • Lastly, do you see an exception when running I2S_startClocks?

    Hi Peter,

    Did you observe any exception when turning on I2SStartClocks? If you pause the device after I2SStartClocks, where is the program counter?

    You can do so using our ROV2 tool.

    Regards,

    Arthur

  • I couldn't confirm it by what you sent me.

    However, I have checked a few things, but now the RF_EventLastCmdDone event occurs in the echoCallBack function of rfEchoTx and is confirmed as RxtimedOut.
    Should I adjust the RF parameter for this symptom? If so, please let me know which parameter should be adjusted.

  • Hi Peter,

    That is a good clue. How do you calculate RX_TIMEOUT? Please be mindful that the timeout is expressed in Radio timer ticks, and not milliseconds.

    Here is an helper function to the the conversion: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_8_30_01_01/docs/rflib/html/group__rf__driver__cc13x2__cc26x2.html#gaabead042beafa5e5347f1e7b003202f2

    Regards,

    Arthur