I have noticed the transceiver takes over 50ms to initialize, and with our startup requirements, I really need to be able to go to sleep after 10ms. I have narrowed the vast majority of the time to the following function:
rx_bba_dcoc_dac_trim_shortIQ() which is the last call in XCVR_Configure()
I am using the MKW41Z_ConnSw_1.0.2 package, and creating a project with genfsk.
1. What are the implications of just skipping the rx_bba_dcoc_dac_trim_shortIQ function?
2. if the function is needed, is it really necessary to be using floating point math on a cortex M0? That is incredibly inefficient and time consuming. I have narrowed most of the time from rx_bba_dcoc_dac_trim_shortIQ be due to several calls to DC_Measure_short, which call rx_dc_sample_average, which does a large loop operation with floating point divide (each of which consumes approximately 30us for each divide), called 256 times in this function, and this function is called 6 times during the radio initialization.
num_iq_samples = 128 for (i = 0; i < num_iq_samples*2; i+=2) { static int16_t i_value; static int16_t q_value; /* Average I & Q channels separately. */ i_value = *(sample_ptr+i); /* Sign extend from 12 to 16 bits. */ q_value = *(sample_ptr+i+1); /* Sign extend from 12 to 16 bits. */ avg_i += ((float)i_value - avg_i) / (float)(i+1); /* Rolling average I */ avg_q += ((float)q_value - avg_q) / (float)(i+1); /* Rolling average Q */ }
Also, In the process of trying to identify where the time was being spent, I've also noticed a bug in fsl_xcvr_trim.c in XcvrCalDelay(). This busy wait loop appears to be only half written. In using timestamps, I measured this function to be off by an order of magnitude. I fixed it by doing the following.
void XcvrCalDelay(uint32_t time) { int32_t delay = time*32; while(delay > 0) /* Time delay is roughly in uSec. */ { delay-=10; } }
But with this fix, that begs the question, are the places this function and the parameter passed in for wait duration just empirically found? In which case all delay parameters would need to be corrected now that I have fixed the delay function to be more accurate.
In case anyone finds this thread when investigating why there is floating point code in the radio driver:
I wrote an integer only version of the trimming procedure for use in the RIOT driver for the KW41Z radio.
The code from the pull request is available here: RIOT/kw41zrf_xcvr.c at pr/kw41zrf · gebart/RIOT · GitHub
The pull request thread can be found here: drivers: Add support for KW41Z builtin transceiver by gebart · Pull Request #7107 · RIOT-OS/RIOT · G...
Some minor code typos were corrected in the rewrite as well.
Hi Justin,
You CAN NOT skip the rx_bba_dcoc_dac_trim_shortIQ().
This procedure was optimized in the newer release. Instead of running the rx_bba_dcoc_dac_trim_shortIQ(), the newer release calls the rx_bba_dcoc_dac_trim_DCest().
I checked the "rx_bba_dcoc_dac_trim_DCest()" function, and it takes to run 409.9us
Regarding to the XcvrCalDelay(). The incorrect implementation was already identified. However, this does not impact the trimming procedure.
Best Regards,
Mario