time synchronization across different nodes in a mesh network, single hop as well as multi hop.

I am working on time synchronizations between different nodes in a mesh network. I have earlier worked on the radio and the ppi examples given. I wish to generate time stamps at each send and receive events between two different nodes for which i am using the nRF radio along with two crystal oscillators, 16 M XOSC as well as 32.768 KHz XOSC with quartz crystal. Could you let me know that if i am using the ppi with the radio functionality, how do i define the two nodes in my code between which i want to send packets. then can i extend this case for n nodes too.

  • Hi Khosla,

    How do you plan to connect your mesh network ? How would the re-transmission between nodes in the network work ?

    It you only plan to synchronize between 2 device (or multiple devices but not mesh) you can have a look here.

  • Thanks for this. Seems good enough as a guide!!!

    I am using the ppi code with radio in segger as seen below. Considering both the the transmit as well as receive cases in the same code. I have to collect the timestamps for each of the send as well as receive events for each of the two crystal oscillators, 16 MHz as well as 32.768 KHz XOSC as i mentioned earlier. Just let me know ur comments on how appropriate the code is. Basically, my task is to synchronize between two neighboring nodes (single hop) as well as then extend this to synchronize between 7-8 nodes.

    Lemme know if something can be added in the code. One more thing is that i would be using only hardware clocks as you defined too, the timer and RTC.

    Here is the code:

    /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved. *

    • The information contained herein is property of Nordic Semiconductor ASA.
    • Terms and conditions of usage are described in detail in NORDIC
    • SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
    • Licensees are granted free, non-transferable use of the information. NO
    • WARRANTY of ANY KIND is provided. This heading must NOT be removed from
    • the file.

    */

    /** @file *

    • @defgroup ppi_example_main main.c
    • @{
    • @ingroup ppi_example
    • @brief PPI Example Application main file.
    • This file contains the source code for a sample application using PPI to communicate between timers.

    */ #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include "nrf_delay.h" #include "app_error.h" #include "boards.h" #include "nrf_drv_ppi.h" #include "nrf_drv_timer.h" #include "nordic_common.h" #include "nrf_drv_gpiote.h" #include "SEGGER_RTT.h"

    #define NRF_LOG_MODULE_NAME "APP" #include "nrf_log.h" #include "nrf_log_ctrl.h"

    #include "bsp.h" #include "app_button.h"

    #ifdef BSP_LED_0 #define GPIO_OUTPUT_PIN_NUMBER BSP_LED_0 /**< Pin number for output. */ #endif #ifndef GPIO_OUTPUT_PIN_NUMBER #error "Please indicate output pin" #endif

    uint32_t counter = 0;

    const nrf_drv_timer_t timer0 = NRF_DRV_TIMER_INSTANCE(0); const nrf_drv_timer_t timer1 = NRF_DRV_TIMER_INSTANCE(1); const nrf_drv_timer_t timer2 = NRF_DRV_TIMER_INSTANCE(2);

    static uint32_t *radio_register = (uint32_t *) 0x40001000; nrf_ppi_channel_t ppi_channel1, ppi_channel2, ppi_channel3, ppi_channel4, ppi_channel5, ppi_channel6, ppi_channel7, ppi_channel8, ppi_channel9, ppi_channel10, ppi_channel11, ppi_channel11, ppi_channel12, ppi_channel13;

    // Timer even handler. Not used since timer is used only for PPI. void timer_event_handler(nrf_timer_event_t event_type, void * p_context){}

    /** @brief Function for initializing the PPI peripheral. */ static void ppi_init(void) { uint32_t err_code = NRF_SUCCESS;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
    // Configure 1st available PPI channel to stop TIMER0 counter on TIMER1 COMPARE[0] match, which is every even number of seconds.
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
                                          nrf_drv_timer_event_address_get(&timer1, NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_timer_task_address_get(&timer0, NRF_TIMER_TASK_STOP));
    APP_ERROR_CHECK(err_code);
    
    // Configure 2nd available PPI channel to start timer0 counter at TIMER2 COMPARE[0] match, which is every odd number of seconds.
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
                                          nrf_drv_timer_event_address_get(&timer2, NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_timer_task_address_get(&timer0, NRF_TIMER_TASK_START));
    APP_ERROR_CHECK(err_code);
    // Enable both configured PPI channels
    err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
    APP_ERROR_CHECK(err_code);
    

    }

    /** @brief Function for Timer 0 initialization, which will be started and stopped by timer1 and timer2 using PPI. */ static void timer0_init(void) { nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.mode = NRF_TIMER_MODE_COUNTER; ret_code_t err_code = nrf_drv_timer_init(&timer0, &timer_cfg, timer_event_handler); APP_ERROR_CHECK(err_code); }

    /** @brief Function for Timer 1 initialization.

    • @details Initializes Timer 1 peripheral, creates event and interrupt every 2 seconds,
    •       by configuring CC[0] to timer overflow value, we create events at even number of seconds
      
    •       for example, events are created at 2,4,6 ... seconds. This event can be used to stop Timer 0
      
    •       with Timer1->Event_Compare[0] triggering Timer 0 TASK_STOP through PPI.
      

    */ static void timer1_init(void) { // Configure Timer 1 to overflow every 2 seconds. Check TIMER1 configuration for details // The overflow occurs every 0xFFFF/(SysClk/2^PRESCALER). // = 65535/31250 = 2.097 sec nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = NRF_TIMER_FREQ_31250Hz; ret_code_t err_code = nrf_drv_timer_init(&timer1, &timer_cfg, timer_event_handler); APP_ERROR_CHECK(err_code);

    nrf_drv_timer_extended_compare(&timer1, NRF_TIMER_CC_CHANNEL0, 0xFFFFUL, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
    

    }

    /** @brief Function for Timer 2 initialization.

    • @details Initializes Timer 2 peripheral, creates event and interrupt every 2 seconds
    •       by configuring CC[0] to half of timer overflow value. Events are created at odd number of seconds.
      
    •       For example, events are created at 1,3,5,... seconds. This event can be used to start Timer 0
      
    •       with Timer2->Event_Compare[0] triggering Timer 0 TASK_START through PPI.
      

    */ static void timer2_init(void) { // Generate interrupt/event when half of time before the timer overflows has past, that is at 1,3,5,7... seconds from start. // Check TIMER1 configuration for details // now the overflow occurs every 0xFFFF/(SysClk/2^PRESCALER) // = 65535/31250 = 2.097 sec */ nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.frequency = NRF_TIMER_FREQ_31250Hz; ret_code_t err_code = nrf_drv_timer_init(&timer2, &timer_cfg, timer_event_handler); APP_ERROR_CHECK(err_code);

    nrf_drv_timer_extended_compare(&timer2, NRF_TIMER_CC_CHANNEL0, 0x7FFFUL, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
    

    }

    /**

    • @brief Function for application main entry. */

    uint32_t low_mask(char n) { return (1<<(n+1)) - 1; }

    void set_address0(uint32_t address) { uint32_t base = address << 8; NRF_RADIO->BASE0 = base; uint32_t prefix = (address >> 24) & low_mask(8); NRF_RADIO->PREFIX0 = prefix;
    }

    void radio_init(){ uint32_t err_code = NRF_SUCCESS;

    //Set frequency, advertising channel 37. 
    NRF_RADIO->FREQUENCY = 2UL;  // Frequency bin 2, 2402MHz
    
    //Set whitening to same as channel
    NRF_RADIO->DATAWHITEIV = 37;
    NRF_RADIO->TXADDRESS = 0; //Base0 + prefix0
    NRF_RADIO->RXADDRESSES = 1;
    
    //Set TXPOWER
    NRF_RADIO->TXPOWER = RADIO_TXPOWER_TXPOWER_0dBm;
    
     uint32_t override_val = NRF_FICR->OVERRIDEEN & FICR_OVERRIDEEN_BLE_1MBIT_Msk;
    

    if (override_val == FICR_OVERRIDEEN_BLE_1MBIT_Override) { NRF_RADIO->OVERRIDE0 = NRF_FICR->BLE_1MBIT[0]; NRF_RADIO->OVERRIDE1 = NRF_FICR->BLE_1MBIT[1]; NRF_RADIO->OVERRIDE2 = NRF_FICR->BLE_1MBIT[2]; NRF_RADIO->OVERRIDE3 = NRF_FICR->BLE_1MBIT[3]; NRF_RADIO->OVERRIDE4 = NRF_FICR->BLE_1MBIT[4]; }

    NRF_RADIO->MODE = RADIO_MODE_MODE_Nrf_1Mbit;
    
    //Set CRC initial value
    NRF_RADIO->CRCINIT = 0x555555;
    //Set CRC size and address include
    NRF_RADIO->CRCCNF = 
            (3 << RADIO_CRCCNF_LEN_Pos)  |
            (true << RADIO_CRCCNF_SKIPADDR_Pos);
    
    NRF_RADIO->CRCPOLY = (1<<24) | (1<<10) | (1<<9) | (1<<6) | (1<<4) | (1<<3) | (1<<1) | 1;
    
    //Set size of length, s0 and s1
    NRF_RADIO->PCNF0 =
            (1 << RADIO_PCNF0_S0LEN_Pos) |
            (6 << RADIO_PCNF0_LFLEN_Pos) |
            (2 << RADIO_PCNF0_S1LEN_Pos);
    
    NRF_RADIO->PCNF1 = 
            (100 << RADIO_PCNF1_MAXLEN_Pos) |
            (0 << RADIO_PCNF1_STATLEN_Pos)  |
            (3 << RADIO_PCNF1_BALEN_Pos)    |
            (RADIO_PCNF1_ENDIAN_Little << RADIO_PCNF1_ENDIAN_Pos)   |
            (true << RADIO_PCNF1_WHITEEN_Pos);
    
    //Set Radio address
    set_address0(0x8E89BED6);
    
    
    NRF_RADIO->SHORTS = 
            (1 << RADIO_SHORTS_END_DISABLE_Pos);
    

    }

    void timer_init(){ uint32_t err_code; //Configure timer and compare for timer0 nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_24; timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;

    err_code = nrf_drv_timer_init(&timer0, &timer_cfg, timer_event_handler);
    APP_ERROR_CHECK(err_code);
    nrf_drv_timer_extended_compare(&timer0, NRF_TIMER_CC_CHANNEL0, 5, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);
    
    
    //Configure Timer SHORTS
    NRF_TIMER0->SHORTS = (TIMER_SHORTS_COMPARE0_STOP_Enabled << TIMER_SHORTS_COMPARE0_STOP_Pos);
    
    nrf_drv_timer_enable(&timer0);
    nrf_drv_timer_enable(&timer1);
    

    }

    void ppi_init_new(){

    ret_code_t err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
    
    
    
    
    //Config event task
    nrf_drv_gpiote_out_config_t task_config4 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    ret_code_t err_code2 = nrf_drv_gpiote_out_init(24, &task_config4);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_gpiote_out_config_t task_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    err_code2 = nrf_drv_gpiote_out_init(23, &task_config);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_gpiote_out_config_t task_config2 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    err_code2 = nrf_drv_gpiote_out_init(22, &task_config2);
    APP_ERROR_CHECK(err_code);
    
    nrf_drv_gpiote_out_config_t task_config3 = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    err_code2 = nrf_drv_gpiote_out_init(21, &task_config3);
    APP_ERROR_CHECK(err_code);
    
    
    uint32_t gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(23);
    // Configure 1st available PPI channel to stop TIMER0 counter on TIMER1 COMPARE[0] match, which is every even number of seconds.
    
    
    
    
    
    //Usefull PPI Channels that trigger important things
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel13);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel13,
                                          nrf_drv_timer_event_address_get(&timer0, NRF_TIMER_EVENT_COMPARE0),
                                          nrf_drv_gpiote_out_task_addr_get(22));
    APP_ERROR_CHECK(err_code);
    

    /* err_code = nrf_drv_ppi_channel_alloc(&ppi_channel5); APP_ERROR_CHECK(err_code); err_code = nrf_drv_ppi_channel_assign(ppi_channel5, NRF_RADIO->EVENTS_READY, NRF_TIMER0->TASKS_START); APP_ERROR_CHECK(err_code);

    /* err_code = nrf_drv_ppi_channel_alloc(&ppi_channel11); APP_ERROR_CHECK(err_code); err_code = nrf_drv_ppi_channel_assign(ppi_channel11, nrf_drv_timer_event_address_get(&timer1, NRF_TIMER_EVENT_COMPARE0), NRF_RADIO->TASKS_STOP); APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel12);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel12,
                                          NRF_RADIO->EVENTS_ADDRESS,
                                          NRF_TIMER1->TASKS_STOP);
    APP_ERROR_CHECK(err_code);
    

    */

    //PPI Channels Used for debugging
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
                                          (uint32_t) (&NRF_RADIO->EVENTS_READY), //(uint32_t) (0x40001000+0x104), //(&NRF_RADIO->EVENTS_READY),
                                          gpiote_task_addr);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel6);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel6,
                                          (uint32_t) (&NRF_RADIO->EVENTS_ADDRESS), //(uint32_t) (0x40001000+0x104), //(&NRF_RADIO->EVENTS_READY),
                                          gpiote_task_addr);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
                                          (uint32_t) (&NRF_RADIO->EVENTS_PAYLOAD), //(uint32_t) (0x40001000+0x108), //(&NRF_RADIO->EVENTS_END),
                                          gpiote_task_addr);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel3);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel3,
                                          (uint32_t) (&NRF_RADIO->EVENTS_END),
                                          gpiote_task_addr);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel4);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel4,
                                          (uint32_t) (&NRF_RADIO->EVENTS_DISABLED),
                                          gpiote_task_addr);
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel7);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel7,
                                          (uint32_t) (&NRF_RADIO->EVENTS_READY), //(uint32_t) (0x40001000+0x104), //(&NRF_RADIO->EVENTS_READY),
                                          nrf_drv_gpiote_out_task_addr_get(21));
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel8);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel8,
                                          (uint32_t) (&NRF_RADIO->EVENTS_ADDRESS), //(uint32_t) (0x40001000+0x104), //(&NRF_RADIO->EVENTS_READY),
                                          nrf_drv_gpiote_out_task_addr_get(21));
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel9);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel9,
                                          (uint32_t) (&NRF_RADIO->EVENTS_PAYLOAD), //(uint32_t) (0x40001000+0x108), //(&NRF_RADIO->EVENTS_END),
                                          nrf_drv_gpiote_out_task_addr_get(21));
    APP_ERROR_CHECK(err_code);
    
    err_code = nrf_drv_ppi_channel_alloc(&ppi_channel10);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_assign(ppi_channel10,
                                          (uint32_t) (&NRF_RADIO->EVENTS_END),
                                          nrf_drv_gpiote_out_task_addr_get(21));
    
    
    
    
    //Enable ppi
    err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel3);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel4);
    APP_ERROR_CHECK(err_code);   
    err_code = nrf_drv_ppi_channel_enable(ppi_channel5);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel6);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel7);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel8);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel9);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_enable(ppi_channel10);
    APP_ERROR_CHECK(err_code);
    
    
    err_code = nrf_drv_ppi_channel_enable(ppi_channel13);
    APP_ERROR_CHECK(err_code);
    
    
    
    //nrf_drv_gpiote_out_task_enable(23);
    nrf_drv_gpiote_out_task_enable(21);
    nrf_drv_gpiote_out_task_enable(22);
    nrf_drv_gpiote_out_task_enable(23);
    nrf_drv_gpiote_out_task_enable(24);
    
    //Start clock 0
    
    //nrf_gpio_cfg_output(23);
    

    }

    void start_crystal_clock(){ // Start 16 MHz crystal oscillator NRF_CLOCK->EVENTS_HFCLKSTARTED = 0; * (int *) 0x40000000 = 1;

    // Wait for the external oscillator to start up 
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
    {
        // Do nothing.
    }
     /* Start low frequency crystal oscillator for app_timer(used by bsp)*/
    NRF_CLOCK->LFCLKSRC            = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
    NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_LFCLKSTART    = 1;
    
    while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0)
    {
        // Do nothing.
    }
    

    }

    void send_adv_ind(char* adv_packet){ //NRF_RADIO->PACKETPTR = (uint32_t) adv_packet;

    //Set packet pointer
    NRF_RADIO->PACKETPTR = (uint32_t) adv_packet;
    
    NRF_RADIO->EVENTS_DISABLED = 0U;
    NRF_RADIO->EVENTS_READY = 0U;
    NRF_RADIO->TASKS_TXEN   = 1U;
    while (NRF_RADIO->EVENTS_READY == 0U)
    {
        // wait
    }
    
    NRF_RADIO->TASKS_START = 1U;
    
    while (NRF_RADIO->EVENTS_DISABLED == 0U)
    {
        // wait
    }
    

    }

    void send_packet(char* send_packet){ //NRF_RADIO->PACKETPTR = (uint32_t) adv_packet;

    //Set packet pointer
    NRF_RADIO->PACKETPTR = (uint32_t) send_packet;
    
    NRF_RADIO->EVENTS_DISABLED = 0U;
    NRF_RADIO->EVENTS_READY = 0U;
    NRF_RADIO->TASKS_TXEN   = 1U;
    while (NRF_RADIO->EVENTS_READY == 0U)
    {
        // wait
    }
    
    
    while (NRF_RADIO->EVENTS_DISABLED == 0U)
    {
        // wait
    }
    

    }

    void start_reciever(char* recieve_packet){ //Set packet pointer NRF_RADIO->PACKETPTR = (uint32_t) recieve_packet;

    NRF_RADIO->EVENTS_READY = 0U;
    // Enable radio and wait for ready
    NRF_RADIO->TASKS_RXEN = 1U;
    while (NRF_RADIO->EVENTS_READY == 0U)
    {
        // wait
    }
    
    NRF_RADIO->EVENTS_END = 0U;
    // Start listening and wait for address received event
    NRF_RADIO->TASKS_START = 1U;
    
    // Wait for end of packet or buttons state changed
    while (NRF_RADIO->EVENTS_END == 0U)
    {
        // wait
    }
    

    }

    void send_scan_res(char* scan_res_packet){

    NRF_RADIO->EVENTS_DISABLED = 0U;
    NRF_RADIO->EVENTS_READY = 0U;
    NRF_RADIO->TASKS_TXEN   = 1U;
    while (NRF_RADIO->EVENTS_READY == 0U)
    {
        // wait
    }
    
    //NRF_RADIO->TASKS_START = 1U;
    
    while (NRF_RADIO->EVENTS_DISABLED == 0U)
    {
        // wait
    }
    

    }

    #define BUTTON_DETECTION_DELAY 10

    static volatile uint16_t button_tick = 0; static volatile uint16_t button_min_hand = 0; static volatile bool button_pressed = false;

    static void button_handler(uint8_t button, uint8_t action) {

    switch(action) {
    case APP_BUTTON_PUSH:
        button_pressed = true;
        break;
    case APP_BUTTON_RELEASE:
        button_pressed = false;
        //SEGGER_RTT_printf(0, "button_ticks are: %d, button_min_hand is %d\n", button_tick, button_min_hand);
        button_tick = 0;
        button_min_hand = 0;
        break;
    }
    

    }

    void buttons_init(void) { uint32_t err_code = 0; static app_button_cfg_t buttons[] = { {1, APP_BUTTON_ACTIVE_LOW, NRF_GPIO_PIN_PULLUP, button_handler} }; err_code = app_button_init((app_button_cfg_t *)buttons, sizeof(buttons) / sizeof(buttons[0]), BUTTON_DETECTION_DELAY); APP_ERROR_CHECK(err_code); err_code = app_button_enable(); APP_ERROR_CHECK(err_code);

    }

    void button_tick_increment(void) { if (button_pressed == true) { if (button_tick >= 65534) { button_min_hand++; button_tick = 0; } button_tick++; } }

    int main(void) {/* //0b00000010 //Device address: 0xee, 0x1c, 0x35, 0x21, 0x03, 0xf1, sent LSByte first uint8_t adv_packet[100] = {0b01000000, 15, 0, 0xee, 0x03, 0x21, 0x35, 0x1c, 0xee, 8, 0x09, 'N','i','c','o','l','a','i'}; uint8_t recieve_packet[100] = {0}; uint8_t scan_res_packet[100] = {0b01000100, 16, 0, 0xf1, 0x03, 0x21, 0x35, 0x1c, 0xee, 9, 0x09, 'R','e','s','p','o','n','s', 'e'}; */

    //power_manage();
    

    } int button_tick = 0; uint32_t err_code; //ppi_init_new(); radio_init(); start_crystal_clock(); timer_init();

     NRF_GPIO->DIRSET = (1 << 21) | (1 << 22) | (1 << 23) | (1 << 24);
    NRF_GPIO->OUTCLR = (1 << 21) | (1 << 22) | (1 << 23) | (1 << 24);
    int tick = 0;
    int b = 2;
    
    uint8_t v_nr_1 = 0;
    uint8_t v_nr_2 = 0;
    uint8_t mesh_demo_packet[] = {0b01000000, 15, 0, 0xee, 0x03, 0x21, 0x35, 0x1c, 0xee, 0x07, 0x09, 'R','a','g','h','a','v'};
    while(b == 2){
      
        send_adv_ind(mesh_demo_packet);
        if(v_nr_1 >= 255){
            v_nr_1 = 0;
            v_nr_2++;
        }else{
            v_nr_1++;
        }
        
        nrf_delay_ms(100);
    } 
    

    }

    /** @} */

  • Please attach your code as a text file. Please have look again at your comment above, how would you expect me to read what you pasted ?

    You still haven't described clearly enough what you are planing to do and what the difficulties you have. Please try to follow the tutorial and get back if you have issues.

  • main.c

    This is the code i would be using for my work. I looked at the link you gave me. But it would be good if u could see mine and lemme know whether its appropriate enough. As far as the main problem is concerned, my task is synchronizing all events in a mesh network. I need to timestamp the events using hardware timers. Then once i have the time values, i can verify them by sniffing packets on air and seeing results on the Logic Analyzer. Then getting the data out from the board to the pc. Using certain algorithms to estimate the drift and the offset variations with regard to the time events recorded. Hope this will clarify your queries.