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

Calculating ppm offset between the 32khz and the 16mhz clocks

I am trying to build a run time test routine that will return the ppm offset between the 32khz and the 16mhz clocks.

Can i use PPI to hook 10 clocks 32khz ticks to capture the value of a 16mhz time?

Can you instrurct me how to do that?

I need to get 20ppm resolution, so i need to count 16mhz ticks in between 10 32khz ticks.

Parents Reply Children
  • Thanks a lot.

    I have written a quick code without testing it yet.

    Is it in line with your suggestion?

    void ppm_test(void)
    {
      // user RTC2 to count 32khz tick via its compare registers 
      NRF_RTC2->PRESCALER = 0;
      NRF_RTC2->EVTENSET = RTC_EVTENCLR_COMPARE0_Enabled | RTC_EVTENCLR_COMPARE1_Enabled;
      NRF_RTC2->CC[0] = 1;  // get 1st tick 
      NRF_RTC2->CC[1] = 21; // get 21th tick 
      
      // get interrupt on RTC2 CC[1] 
      NRF_RTC2->INTENSET = RTC_INTENSET_COMPARE1_Enabled; 
      NVIC_ClearPendingIRQ(RTC2_IRQn);
      NVIC_EnableIRQ(RTC2_IRQn);
      
      // use TIMER2 capture counting 16mhz ticks  
      NRF_TIMER2->MODE = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos); 
      NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
      NRF_TIMER2->PRESCALER = 0; // 16mhz 
      NRF_TIMER2->TASKS_CLEAR = 1;
    
      // use ppi to hook RTC compare and to timer capture 
      NRF_PPI->CH[0].EEP = (uint32_t) &NRF_RTC2->EVENTS_COMPARE[0]; 
      NRF_PPI->CH[0].TEP = (uint32_t) &NRF_TIMER2->TASKS_CAPTURE[0]; 
      NRF_PPI->CH[1].EEP = (uint32_t) &NRF_RTC2->EVENTS_COMPARE[1]; 
      NRF_PPI->CH[1].TEP = (uint32_t) &NRF_TIMER2->TASKS_CAPTURE[1]; 
      NRF_PPI->CHENSET = (PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos) | 
                         (PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos); 
    
      // enable it all 
      NRF_TIMER2->TASKS_START = 1; 
      NRF_RTC2->TASKS_START = 1; 
    }
    
    // interrupt on compare 1 
    void TIMER2_IRQHandler(void)
    {
      NVIC_ClearPendingIRQ(TIMER2_IRQn);
      NVIC_DisableIRQ(TIMER2_IRQn);
    
      int delta = NRF_TIMER2->CC[1] - NRF_TIMER2->CC[0];
      
      // in there are 100000 16mhz ticks in 20 32khz tick (as if it is a 1.6khz)
      ppm = (delta - 100000) * ( 1000000 / 100000 );
    
      // disable it all 
      NRF_TIMER2->TASKS_STOPT = 1; 
      NRF_RTC2->TASKS_STOP = 1; 
      NRF_PPI->CHENCLR = (PPI_CHENCLR_CH0_Clear << PPI_CHENCLR_CH0_Pos) | 
                          PPI_CHENCLR_CH1_Clear << PPI_CHENCLR_CH1_Pos);
    }

Related