This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Modifying wireless timer sync using RTC

Hello,

I'm modifying the code of Wireless timer synchronization among nRF5 devices blog to use RTC instead of two TIMERs. I started with the code on Git for SDK 16. Writing for nRF52832.

Timers on multiple nRF5 devices are synced by one device (master) sending sync packets containing captured timer values to other devices (nodes). (TIMER3 is free running, TIMER2 counts TIMER3 overflows.) A receiving node calculates an appropriate offset between the master timers and its own and compensates accordingly when its timer value is requested.

With the current code, PPI is used to capture the TIMER3 and TIMER2 values just before the master sends a sync packet to other nodes, and (for a node) upon receipt of a sync packet from the master. (See ppi_radio_rx_configure() and ppi_radio_tx_configure().) The event NRF_RADIO->EVENTS_READY is used for when the master sends a sync packet. For receiving sync packets, the event NRF_RADIO->EVENTS_ADDRESS is used.

Since PPI cannot be used to capture the COUNTER value of an RTC, for when the master sends a sync packet, I see that the timeslot_begin_handler() routine directly sets the rtc_val of the packet to be sent (p_pkt) to the current rtc value (m_params.rtc->COUNTER) as soon as NRF_RADIO->EVENTS_READY becomes 1. That makes sense.

What about when a node receives a sync packet? Would that best be done in RADIO_IRQHandler()? Something like:

if (NRF_RADIO->EVENTS_ADDRESS != 0)
{
    NRF_RADIO->EVENTS_ADDRESS = 0;
    (void)NRF_RADIO->EVENTS_ADDRESS;
    
    if (m_radio_state == RADIO_STATE_RX)
    {
        // Save current RTC value into global.
        m_local_rtc_at_time_of_sync_packet_arrival = m_params.rtc->COUNTER;
    }
}

And then in sync_timer_offset_compensate():

master_rtc_timer  = p_pkt->rtc_val;
master_rtc_timer += TX_CHAIN_DELAY;
local_rtc_timer = m_local_rtc_at_time_of_sync_packet_arrival;

m_rtc_counter_offset = master_rtc_timer - local_rtc_timer;

if (m_rtc_counter_offset == 0)
{
    // Already in sync
    return false;
}

return true;

Unrelated to the above, another question: in sync_timer_button_init() of main.c we see:

ts_params.high_freq_timer[0] = NRF_TIMER3;
ts_params.high_freq_timer[1] = NRF_TIMER2;
ts_params.rtc             = NRF_RTC1;
ts_params.egu             = NRF_EGU3;
ts_params.egu_irq_type    = SWI3_EGU3_IRQn;
ts_params.ppi_chg         = 0;
ts_params.ppi_chns[0]     = 1;
ts_params.ppi_chns[1]     = 2;
ts_params.ppi_chns[2]     = 3;
ts_params.ppi_chns[3]     = 4;
ts_params.rf_chn          = 125; /* For testing purposes */
memcpy(ts_params.rf_addr, rf_address, sizeof(rf_address));

And then in update_radio_parameters() of time_sync.c:

NRF_RADIO->FREQUENCY = m_params.rf_chn;

In preparing this code for production, any considerations relating to this?

Many thanks,

Tim

Parents Reply Children
No Data
Related