TWR CIR and Distance problem

Hi to everyone who will help me solve my questions:
Please excuse me if I’m not clear enough.
I’m doing TWR with two DWM3001CDK boards, one side initiator and the other one will be set as responder.
The problem that i’m facing with is that i modified the code provided by default by adding some option to display the CIR in the log of the terminal, since i need the CIR analysis for my studies.
What i want to have is the display of the distance measureamnts and the CIR at the same time. The problem is that when i’m enabling my function for the CIR printing it will occour some error and i will not be able to show the dIstance measureaments as well, while if i comment the print CIR (meaning disabling it) then i will have my Distance measurement back. My purpose is to have both the measurements.
This is the code modified:
In dw3000_mcps_mcu.c:

bool readDW3000CIRData(int32_t *realvalues, int32_t *imgvalues ,int len, int offset) {

 

    if ((len + offset)>1016)
        len = 1016-offset;
    if (len <1) 
        return false;

    const int bytesPerValue = 6; // dw3000


    uint8_t cir_buffer[1016*bytesPerValue+1]; // worst case

    dwt_readaccdata(cir_buffer, len*bytesPerValue+1, offset);
    int byteAddress = 1;
    for (int i=0;i<len;i++) {
        int32_t iValue = cir_buffer[byteAddress++];
        iValue |= ((int32_t)cir_buffer[byteAddress++]<<8);
        iValue |= ((int32_t)(cir_buffer[byteAddress++] & 0x03)<<16);

        int32_t qValue = cir_buffer[byteAddress++];
        qValue |= ((int32_t)cir_buffer[byteAddress++]<<8);         
        qValue |= ((int32_t)(cir_buffer[byteAddress++] & 0x03)<<16);
	
        if (iValue & 0x020000)  // MSB of 18 bit value is 1
            iValue |= 0xfffc0000;
        if (qValue & 0x020000)  // MSB of 18 bit value is 1
            qValue |= 0xfffc0000;

        realvalues[i]=iValue;
        imgvalues[i]=qValue;
       // *(CIRValues+i) = sqrt((float)(iValue*iValue+qValue*qValue));
    }
    return true;	
}


void printCIR() {
    int CIR_length = 900; // Number of complex CIR samples we want to read
   
    int32_t realSample[CIR_length];
    int32_t imagSample[CIR_length];
 
    

    char* CIR_string_real;
    char* CIR_string_real_sv;
    char* CIR_string_imag_sv;
    char* CIR_string_imag;
    //char* teststring;
    CIR_string_real = (char*)malloc(5000);
    CIR_string_imag = (char*)malloc(5000); // Allocate memory for the string buffer
    CIR_string_real_sv = (char*)malloc(10);
    CIR_string_imag_sv = (char*)malloc(10); // Allocate memory for the string buffer

 
    readDW3000CIRData(realSample,imagSample,CIR_length,0);
  /*  dwt_readaccdata(CIR, 6 * CIR_length + 1, 0);
    for (int i = 0; i < CIR_length; i++) {
        CIRsample[0] = CIR[i * 6 + 1]; // Assign each element individually
        CIRsample[1] = CIR[i * 6 + 2];
        CIRsample[2] = CIR[i * 6 + 3];
        realSample[i] = readDW3000CIRData(CIRsample,CIR_length,0);
        CIRsample[0] = CIR[i * 6 + 4];
        CIRsample[1] = CIR[i * 6 + 5];
        CIRsample[2] = CIR[i * 6 + 6];
        imagSample[i] = readDW3000CIRData(CIRsample,CIR_length,0);
    }
*/
  
reporter_instance.print("\nCIR_real_values\n", 17);
   int len = 0;
    for (int i = 0; i < CIR_length; i++) {
         int len = snprintf(CIR_string_real,10, "%ld ", (realSample[i]));
      
        reporter_instance.print(CIR_string_real, len); 
    }
 reporter_instance.print("\nCIR_imag_values\n", 17);
   len = 0;
    for (int i = 0; i < CIR_length; i++) {
          int len = snprintf(CIR_string_imag,10, "%ld ", (imagSample[i])); 
  
       
        reporter_instance.print(CIR_string_imag, len); 
    }
 reporter_instance.print("\n", 1);
 

   
    reporter_instance.print("\nCIR_real_values\n", 17);
   

    reporter_instance.print(strcat(CIR_string_real, "\n"), 50);

    reporter_instance.print("\nCIR_imag_values\n", 17);
    reporter_instance.print(strcat(CIR_string_imag, "\n"), 50);


    free(CIR_string_real);
    free(CIR_string_imag); // Deallocate the memory for the string buffer
}











/* @brief     ISR layer
 *             TWR application Rx callback
 *             to be called from dwt_isr() as an Rx call-back
 */


static void mcps_rx_cb(const dwt_cb_data_t *rxd)
{
#define MAX_MSG     2
#define MAX_MSG_LEN 128
    static uint8_t message[MAX_MSG][MAX_MSG_LEN];
    static dwt_mcps_rx_t rx[MAX_MSG];
    static int idx = 0;

    struct dwchip_s *dw = rxd->dw;
    const struct dwt_mcps_ops_s *mcps_ops = dw->dwt_driver->dwt_mcps_ops;
    struct dwt_mcps_runtime_s *rt = dw->mcps_runtime;

    struct dwt_mcps_rx_s *pRx = &rx[idx];
    uint64_t ts, timebase64;
   
    pRx->rtcTimeStamp = Rtc.getTimestamp();

    /* RX TS in RCTU of local timebase */
    ts = mcps_ops->get_timestamp(dw);

    /* convert local timebase in RCTU */
    timebase64 = timestamp_dtu_to_rctu(dw->llhw, get_timebase_dtu(dw));

    pRx->timeStamp = (ts + timebase64 + rt->corr_4ns) & 0xFFFFFFFFFFULL;

    pRx->flags = 0;

    if (rxd->datalength)
    {
        pRx->len = MIN(rxd->datalength, MAX_MSG_LEN);
        pRx->data = (uint8_t *)&message[idx];
        struct dwt_rw_data_s rd = {(uint8_t *)pRx->data, pRx->len, 0};
        mcps_ops->ioctl(dw, DWT_READRXDATA, 0, (void *)&rd);

        int16_t cfo;
        mcps_ops->ioctl(dw, DWT_READCLOCKOFFSET, 0, (void *)&cfo);

        pRx->cfo = cfo;
        /*Below Xtal trimming can be executed in the upper layer: rx[idx].cfo*/
        int cfo_ppm = (int)((float)cfo * (CLOCK_OFFSET_PPM_TO_RATIO * 1e6 * 100));
        dw->mcps_runtime->diag.cfo_ppm = cfo_ppm;


        printCIR();

This is the code in fira_app.c for the distance:

static void report_cb(const struct ranging_results *results, void *user_data) { //anthony 2

   // int32_t binaryValue = 111111111111111111111111;  // Example 24-bit binary value

    //int32_t decimalValue = convertBinaryToDecimal(binaryValue);

    int len = 0;
    struct ranging_measurements *rm;

    struct string_measurement *str_result = (struct string_measurement *)user_data;

    if (results->stopped_reason != 0xFF) {
        len = snprintf(str_result->str, str_result->len, "{\"Session Stopped\":\"%s\"}\r\n",
                      (results->stopped_reason == 0x0) ? "Stop request" :
                      (results->stopped_reason == 0x1) ? "Inband Stop" :
                      (results->stopped_reason == 0x2) ? "Max attempts" : "Unknown");

        reporter_instance.print(str_result->str, len);
        return;
    }

   // len = snprintf(str_result->str, str_result->len, "{\r\n\"Block\": %" PRIu32 ",", results->block_index);

    for (int i = 0; i < results->n_measurements; i++) {
        if (i > 0) {
            len += snprintf(&str_result->str[len], str_result->len - len, ",");
        }

        rm = (struct ranging_measurements *)(&results->measurements[i]);
     // ANTONELLO: Se la misurazione ha uno stato valido vengono mostrati oltre alla distanza anche l'id dei nodi nonostante la misura viene fatta per una coppia di nodi, 
    //lasciare gli ID dei nodi potrebbe risolvere probabili inconvenienti legati al mescolamento dei file, dal guardare i  file sapremo quali nodi sono coinvolti nell'errore. in fase di setup dell'ambiente di misurazione 
    //bisogna assicurarsi di usare sempre lo stesso nodo nella stessa posizione in modo tale che non ci possa essere confusione.
    
        len += snprintf(&str_result->str[len], str_result->len - len,
                        "{\"Addr\":\"0x%04x\",\"Status\":\"%s\"",
                        rm->short_addr, (rm->status) ? ("Err") : ("Ok")); 
                      //MODIFICA PER PROVA CIR  reporter_instance.print("\nprova2\n",8);


        if (rm->status == 0) {
            len += snprintf(&str_result->str[len], str_result->len - len,"\"D_cm\":%d \r\n",
                            (int)(rm->distance_mm / 10));
                            //decimalValue);
        }
    }
   
    /*

    for (int i = 0; i < results->n_measurements; i++) {
        if (i > 0) {
           len += snprintf(&str_result->str[len], str_result->len - len, ",");
        }

        struct ranging_measurements *rm = (struct ranging_measurements *)&results->measurements[i];

        if (rm->status == 0) {
            int distance_mm = rm->distance_mm;
            int D_cm_new = (int)((distance_mm / 10) - 20); // Subtracting 20 as a bias

            len += snprintf(&str_result->str[len], str_result->len - len, "\"D_cm_new\":%d \r\n", D_cm_new);
       }
    }
*/


    len += snprintf(&str_result->str[len], str_result->len - len, "}\r\n");
    reporter_instance.print((char *)str_result->str, len);
}

Thank you to everyone reading and helping me with this.
Kind Regards.

Hi Antonello,

It will be difficult to understand what is happening without the full code ; it is absolutely possible to extract the CIR as well as calculating a distance.

Few points to consider:

  1. Reading CIR can be long, so you need to ensure it will not delay any future ranging you need to schedule to perform the TWR. Maybe reduce the frequency of ranging.
  2. You may want to restrict the size of accumulator you are reading so limit the impact on the TWR.

The best would be to use some logic analyser and capture Tx/Rx signal as well as the CIR reading to ensure they don’t collide. It is likely to be the source of the issue.

Let us know how you experiments are going ?

Hi, do you know how to reduce the ranging frequency?