I had a few minutes of uninterrupted time to begin to scrutinize the DW code.   The code base is pretty big.  The actual demo “application” code, (not even the libraries) are extensive.  See ->

I printed out just the demo part of the code so that I could start to understand how they set up the radios for TOF calculations.  Now it got depressing.

The following code translates TOF to a distance.  It appears that the hardware can produce TOF results that are negative!  OK, I can see how that can happen, but simply turning it into a positive number seems like a odd solution.  I wonder why that is the right thing to do?

Then I notice that the code assumes two complete round trips, i.e. 4 transmissions, and averages them.
Then if the result is less than -50cms discard it – which is odd because the previous line of code should have guaranteed that the TOF is positive.
And then if the distance is still negative then the sign is inverted –  after all the previous work, how can it be negative anyway?
Finally, just to be sure, they generate a moving average of the last 8 estimates.

So each report is actually the average of 32 TOF estimates.   That can’t be good for our power budget!

void reportTOF_f(instance_data_t *inst)
{
        double distance ;
        double tof ;
        int32 tofi ;

        // check for negative results and accept them making them proper negative integers
        tofi = (int32) inst->tof32 ;                          // make it signed
        if (tofi < 0)                          // close up TOF may be negative
        {
            tofi *= -1 ;                       // make it positive
        }

        // convert to seconds (as floating point)
        tof = convertdevicetimetosec(tofi) * 0.25;          //this is divided by 4 to get single time of flight
        distance = tof * SPEED_OF_LIGHT;

        if ((distance < -0.5) || (distance > 20000.000))    // discard any results less than <50 cm or >20km
            return;

#if (CORRECT_RANGE_BIAS == 1)
        distance = distance – dwt_getrangebias(inst->configData.chan, (float) distance, inst->configData.prf);
#endif

        distance = fabs(distance) ;                         // make any (small) negatives positive.

        inst_idist = distance;

        inst->longTermRangeCount++ ;

        inst->adist[inst->tofindex++] = distance;

        if(inst->tofindex == RTD_MED_SZ) inst->tofindex = 0;

        if(inst->tofcount == RTD_MED_SZ)
        {
            int i;
            double sumdiff, avg;

            avg = 0;
            sumdiff = 0;
            for(i = 0; i < inst->tofcount; i++)
            {
                avg += inst->adist[i];
            }
            avg /= inst->tofcount;

            inst_adist = avg ;

        }
        else
            inst->tofcount++;
    return ;
}// end of reportTOF_f

This is my first program that actually needed to know the speed of light.

Glorious fudge factors (pulled out of rectal orifice) require floating point.  N.B. No FP hardware on the Nordic.


//assume PHR length is 172308us for 110k and 21539us for 850k/6.81M
if(instance_data[instance].configData.dataRate == DWT_BR_110K)
{
msgdatalen *= 8205.13f;
msgdatalen += 172308;

}
else if(instance_data[instance].configData.dataRate == DWT_BR_850K)
{
msgdatalen *= 1025.64f;
msgdatalen += 21539;
}
else
{
msgdatalen *= 128.21f;
msgdatalen += 21539;

}

Antenna delay

               //MP bug – TX antenna delay needs reprogramming as it is not preserved
                dwt_settxantennadelay(inst->txantennaDelay) ;

So we have to figure out the antenna delay.

Here’s a useful bit of code for later

int instance_starttxtest(int framePeriod)
{
//define some test data for the tx buffer
uint8 msg[127] = “The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the l”; 
//NOTE: SPI frequency must be < 3MHz

// the value here 0x1000 gives a period of 32.82 µs
//this is setting 0x1000 as frame period (125MHz clock cycles) (time from Tx en – to next – Tx en)
dwt_configcontinuousframemode(framePeriod);

dwt_writetxdata(127, (uint8 *)  msg, 0) ;
dwt_writetxfctrl(127, 0);

    //to start the first frame – set TXSTRT
dwt_starttx(DWT_START_TX_IMMEDIATE); 

//measure the power 
//Spectrum Analyser set:
//FREQ to be channel default e.g. 3.9936 GHz for channel 2
//SPAN to 1GHz
//SWEEP TIME 1s
//RBW and VBW 1MHz
//measure channel power

return DWT_SUCCESS ;
}


This looks like code for using a spectrum analyzer to trim the crystal.


//NOTE: SPI frequency must be < 3MHz
//reduce the SPI speed before switching to XTAL
//
// reset device 
//
dwt_softreset();
//
// configure TX channel parameters
//
configTx.PGdly = txSpectrumConfig[chan].PGdelay ;
//Assume smart power is disabled – not relevant for XTAL trimming as CW mode
    pow = txSpectrumConfig[chan].txPwr[prf – DWT_PRF_16M] & 0xFF ;
configTx.power = (pow | (pow << 8) | (pow << 16) | (pow << 24));
dwt_configuretxrf(&configTx);
dwt_configcwmode(chan);
for(i=0; i<=0x1F; i++)
{
dwt_xtaltrim(i);
//measure the frequency
//Spectrum Analyser set:
//FREQ to be channel default e.g. 3.9936 GHz for channel 2
//SPAN to 10MHz
//PEAK SEARCH
}

Leave a Reply